@velum-labs/routekit-tool-claude 0.17.0 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/install.d.ts +2 -0
- package/dist/install.js +99 -6
- package/dist/launch.js +9 -9
- package/dist/test/install.test.js +54 -1
- package/dist/test/launch.test.js +29 -11
- package/package.json +6 -6
package/dist/install.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export type ClaudeInstallOwner = {
|
|
|
7
7
|
};
|
|
8
8
|
export type ClaudeInstallInput = {
|
|
9
9
|
gatewayUrl: string;
|
|
10
|
+
/** Canonical RouteKit catalog ids permitted by the current model policy. */
|
|
11
|
+
models: readonly string[];
|
|
10
12
|
owner: ClaudeInstallOwner;
|
|
11
13
|
claudeConfigDir?: string;
|
|
12
14
|
};
|
package/dist/install.js
CHANGED
|
@@ -6,9 +6,12 @@ import { SUBSCRIPTIONS } from "@velum-labs/routekit-registry";
|
|
|
6
6
|
import { acquireLifecycleLock, trimTrailingSlashes, writeFileAtomic } from "@velum-labs/routekit-runtime";
|
|
7
7
|
const MANAGED_ENV_KEYS = [
|
|
8
8
|
"ANTHROPIC_BASE_URL",
|
|
9
|
+
"CLAUDE_CODE_ALWAYS_ENABLE_EFFORT"
|
|
10
|
+
];
|
|
11
|
+
const RETIRED_MANAGED_ENV_KEYS = [
|
|
12
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
9
13
|
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"
|
|
10
14
|
];
|
|
11
|
-
const RETIRED_MANAGED_ENV_KEYS = ["ANTHROPIC_AUTH_TOKEN"];
|
|
12
15
|
function reached(boundary) {
|
|
13
16
|
// Deliberately not part of the package API: tests install a same-process
|
|
14
17
|
// throw hook to model termination immediately after an atomic boundary.
|
|
@@ -91,6 +94,9 @@ function isStringRecord(value) {
|
|
|
91
94
|
return (isRecord(value) &&
|
|
92
95
|
Object.values(value).every((entry) => typeof entry === "string"));
|
|
93
96
|
}
|
|
97
|
+
function isStringArray(value) {
|
|
98
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
99
|
+
}
|
|
94
100
|
function isInstalledManifest(value) {
|
|
95
101
|
return (isRecord(value) &&
|
|
96
102
|
value.version === 2 &&
|
|
@@ -99,7 +105,11 @@ function isInstalledManifest(value) {
|
|
|
99
105
|
isSnapshot(value.original) &&
|
|
100
106
|
typeof value.exactRestoreEligible === "boolean" &&
|
|
101
107
|
typeof value.installedContentHash === "string" &&
|
|
102
|
-
isStringRecord(value.managedEnvValues)
|
|
108
|
+
isStringRecord(value.managedEnvValues) &&
|
|
109
|
+
(value.managedPickerModels === undefined || isStringArray(value.managedPickerModels)) &&
|
|
110
|
+
(value.managedAvailableModels === undefined || value.managedAvailableModels === true) &&
|
|
111
|
+
(value.managedEnforceAvailableModels === undefined ||
|
|
112
|
+
value.managedEnforceAvailableModels === true));
|
|
103
113
|
}
|
|
104
114
|
function parseManifest(content, manifestPath) {
|
|
105
115
|
let parsed;
|
|
@@ -159,9 +169,36 @@ function serialize(value) {
|
|
|
159
169
|
function managedEnv(input) {
|
|
160
170
|
return {
|
|
161
171
|
ANTHROPIC_BASE_URL: trimTrailingSlashes(input.gatewayUrl),
|
|
162
|
-
|
|
172
|
+
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT: "1"
|
|
163
173
|
};
|
|
164
174
|
}
|
|
175
|
+
const CLAUDE_PICKER_PREFIX = "anthropic.routekit.";
|
|
176
|
+
function pickerModels(input) {
|
|
177
|
+
const models = new Set();
|
|
178
|
+
for (const model of input.models) {
|
|
179
|
+
if (typeof model !== "string" || model.length === 0) {
|
|
180
|
+
throw new Error("RouteKit's Claude picker catalog contains an invalid model id");
|
|
181
|
+
}
|
|
182
|
+
models.add(`${CLAUDE_PICKER_PREFIX}${model}`);
|
|
183
|
+
}
|
|
184
|
+
return [...models];
|
|
185
|
+
}
|
|
186
|
+
function availableModels(settings, configPath) {
|
|
187
|
+
if (settings.availableModels === undefined)
|
|
188
|
+
return undefined;
|
|
189
|
+
if (!isStringArray(settings.availableModels)) {
|
|
190
|
+
throw new Error(`the "availableModels" field in your Claude settings (${configPath}) must be an array of strings`);
|
|
191
|
+
}
|
|
192
|
+
return [...settings.availableModels];
|
|
193
|
+
}
|
|
194
|
+
function enforceAvailableModels(settings, configPath) {
|
|
195
|
+
if (settings.enforceAvailableModels === undefined)
|
|
196
|
+
return undefined;
|
|
197
|
+
if (typeof settings.enforceAvailableModels !== "boolean") {
|
|
198
|
+
throw new Error(`the "enforceAvailableModels" field in your Claude settings (${configPath}) must be a boolean`);
|
|
199
|
+
}
|
|
200
|
+
return settings.enforceAvailableModels;
|
|
201
|
+
}
|
|
165
202
|
function entryIfExists(path) {
|
|
166
203
|
try {
|
|
167
204
|
return lstatSync(path);
|
|
@@ -412,6 +449,10 @@ export async function installClaudeIntegration(input) {
|
|
|
412
449
|
const settings = parseSettings(beforeSettings.content ?? "{}\n", configPath);
|
|
413
450
|
const env = { ...(settings.env ?? {}) };
|
|
414
451
|
const nextManaged = managedEnv(input);
|
|
452
|
+
const desiredPickerModels = pickerModels(input);
|
|
453
|
+
if (desiredPickerModels.length === 0) {
|
|
454
|
+
throw new Error("RouteKit's Claude picker catalog cannot be empty");
|
|
455
|
+
}
|
|
415
456
|
if (previousManifest === undefined) {
|
|
416
457
|
for (const key of MANAGED_ENV_KEYS) {
|
|
417
458
|
if (env[key] !== undefined) {
|
|
@@ -426,7 +467,33 @@ export async function installClaudeIntegration(input) {
|
|
|
426
467
|
for (const key of removableKeys)
|
|
427
468
|
delete env[key];
|
|
428
469
|
Object.assign(env, nextManaged);
|
|
429
|
-
const
|
|
470
|
+
const currentPickerModels = availableModels(settings, configPath);
|
|
471
|
+
const priorManagedPickerModels = previousManifest?.managedPickerModels ?? [];
|
|
472
|
+
if (priorManagedPickerModels.some((model) => currentPickerModels === undefined || !currentPickerModels.includes(model))) {
|
|
473
|
+
throw new Error(`your Claude settings changed RouteKit-managed availableModels in ${configPath}; ` +
|
|
474
|
+
`restore those entries before rerunning the install command`);
|
|
475
|
+
}
|
|
476
|
+
const userPickerModels = (currentPickerModels ?? []).filter((model) => !priorManagedPickerModels.includes(model));
|
|
477
|
+
const nextManagedPickerModels = desiredPickerModels.filter((model) => !userPickerModels.includes(model));
|
|
478
|
+
const nextPickerModels = [...userPickerModels, ...nextManagedPickerModels];
|
|
479
|
+
const currentEnforceAvailableModels = enforceAvailableModels(settings, configPath);
|
|
480
|
+
if (previousManifest?.managedEnforceAvailableModels === true &&
|
|
481
|
+
currentEnforceAvailableModels !== true) {
|
|
482
|
+
throw new Error(`your Claude settings changed RouteKit-managed enforceAvailableModels in ${configPath}; ` +
|
|
483
|
+
"restore that value before rerunning the install command");
|
|
484
|
+
}
|
|
485
|
+
const nextManagedEnforceAvailableModels = previousManifest?.managedEnforceAvailableModels === true ||
|
|
486
|
+
currentEnforceAvailableModels === undefined
|
|
487
|
+
? true
|
|
488
|
+
: undefined;
|
|
489
|
+
const nextSettings = {
|
|
490
|
+
...settings,
|
|
491
|
+
env,
|
|
492
|
+
availableModels: nextPickerModels,
|
|
493
|
+
...(nextManagedEnforceAvailableModels === true
|
|
494
|
+
? { enforceAvailableModels: true }
|
|
495
|
+
: {})
|
|
496
|
+
};
|
|
430
497
|
const nextContent = serialize(nextSettings);
|
|
431
498
|
const targetSettings = snapshot(nextContent, 0o600);
|
|
432
499
|
const exactRestoreEligible = previousManifest === undefined
|
|
@@ -440,7 +507,14 @@ export async function installClaudeIntegration(input) {
|
|
|
440
507
|
original: previousManifest?.original ?? beforeSettings,
|
|
441
508
|
exactRestoreEligible,
|
|
442
509
|
installedContentHash: targetSettings.hash,
|
|
443
|
-
managedEnvValues: nextManaged
|
|
510
|
+
managedEnvValues: nextManaged,
|
|
511
|
+
managedPickerModels: nextManagedPickerModels,
|
|
512
|
+
...(previousManifest?.managedAvailableModels === true || currentPickerModels === undefined
|
|
513
|
+
? { managedAvailableModels: true }
|
|
514
|
+
: {}),
|
|
515
|
+
...(nextManagedEnforceAvailableModels === true
|
|
516
|
+
? { managedEnforceAvailableModels: true }
|
|
517
|
+
: {})
|
|
444
518
|
};
|
|
445
519
|
const pendingManifest = {
|
|
446
520
|
version: 2,
|
|
@@ -467,7 +541,11 @@ export async function installClaudeIntegration(input) {
|
|
|
467
541
|
return {
|
|
468
542
|
configPath,
|
|
469
543
|
action: previousManifest === undefined ? "installed" : "updated",
|
|
470
|
-
managedKeys:
|
|
544
|
+
managedKeys: [
|
|
545
|
+
...Object.keys(nextManaged),
|
|
546
|
+
"availableModels",
|
|
547
|
+
...(nextManagedEnforceAvailableModels === true ? ["enforceAvailableModels"] : [])
|
|
548
|
+
]
|
|
471
549
|
};
|
|
472
550
|
});
|
|
473
551
|
}
|
|
@@ -521,6 +599,21 @@ export async function uninstallClaudeIntegration(input) {
|
|
|
521
599
|
delete next.env;
|
|
522
600
|
else
|
|
523
601
|
next.env = env;
|
|
602
|
+
const currentPickerModels = availableModels(settings, configPath);
|
|
603
|
+
if (currentPickerModels !== undefined) {
|
|
604
|
+
const remainingPickerModels = currentPickerModels.filter((model) => !(installed.managedPickerModels ?? []).includes(model));
|
|
605
|
+
if (installed.managedAvailableModels === true && remainingPickerModels.length === 0) {
|
|
606
|
+
delete next.availableModels;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
next.availableModels = remainingPickerModels;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
const currentEnforceAvailableModels = enforceAvailableModels(settings, configPath);
|
|
613
|
+
if (installed.managedEnforceAvailableModels === true &&
|
|
614
|
+
currentEnforceAvailableModels === true) {
|
|
615
|
+
delete next.enforceAvailableModels;
|
|
616
|
+
}
|
|
524
617
|
targetSettings = snapshot(serialize(next), beforeSettings.mode);
|
|
525
618
|
}
|
|
526
619
|
else {
|
package/dist/launch.js
CHANGED
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
import { EFFORT_QUALIFIED_MODEL_CODEC, effortQualifiedClientModel } from "@velum-labs/routekit-contracts";
|
|
2
1
|
import { spawnTool } from "@velum-labs/routekit-runtime";
|
|
3
2
|
export function claudeEnv(gatewayUrl, authToken) {
|
|
4
3
|
return {
|
|
5
4
|
ANTHROPIC_BASE_URL: gatewayUrl,
|
|
6
5
|
ANTHROPIC_AUTH_TOKEN: authToken ?? "routekit",
|
|
7
|
-
|
|
6
|
+
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT: "1",
|
|
8
7
|
...(process.env.CLAUDE_CONFIG_DIR !== undefined
|
|
9
8
|
? { CLAUDE_CONFIG_DIR: process.env.CLAUDE_CONFIG_DIR }
|
|
10
9
|
: {})
|
|
11
10
|
};
|
|
12
11
|
}
|
|
13
12
|
export function claudeModelId(modelId) {
|
|
14
|
-
|
|
15
|
-
? modelId.slice("claude-code/".length)
|
|
16
|
-
: modelId;
|
|
17
|
-
return pickerId.startsWith("claude") || pickerId.startsWith("anthropic")
|
|
18
|
-
? pickerId
|
|
19
|
-
: `claude-${pickerId}`;
|
|
13
|
+
return `anthropic.routekit.${modelId}`;
|
|
20
14
|
}
|
|
21
15
|
/** Serialize host-authored profiles once into Claude's session agent format. */
|
|
22
16
|
export function claudeAgentsJson(profiles) {
|
|
@@ -35,10 +29,16 @@ function hasAgentsArg(args) {
|
|
|
35
29
|
function hasModelArg(args) {
|
|
36
30
|
return args.some((arg) => arg === "--model" || arg.startsWith("--model="));
|
|
37
31
|
}
|
|
32
|
+
function hasEffortArg(args) {
|
|
33
|
+
return args.some((arg) => arg === "--effort" || arg.startsWith("--effort="));
|
|
34
|
+
}
|
|
38
35
|
export function claudeLaunchArgs(ctx) {
|
|
39
36
|
const args = [...ctx.spec.args];
|
|
40
37
|
if (!hasModelArg(args)) {
|
|
41
|
-
args.unshift("--model",
|
|
38
|
+
args.unshift("--model", claudeModelId(ctx.spec.defaultModel));
|
|
39
|
+
if (ctx.spec.reasoning?.mode === "effort" && !hasEffortArg(args)) {
|
|
40
|
+
args.unshift("--effort", ctx.spec.reasoning.effort);
|
|
41
|
+
}
|
|
42
42
|
}
|
|
43
43
|
const profiles = ctx.spec.agentProfiles ?? [];
|
|
44
44
|
if (profiles.length > 0 && !hasAgentsArg(args)) {
|
|
@@ -18,6 +18,7 @@ const OWNER = {
|
|
|
18
18
|
function install(configDirectory, gatewayUrl = "http://127.0.0.1:9999/", _authToken) {
|
|
19
19
|
return installClaudeIntegration({
|
|
20
20
|
gatewayUrl,
|
|
21
|
+
models: ["openai/mock-model"],
|
|
21
22
|
owner: OWNER,
|
|
22
23
|
claudeConfigDir: configDirectory
|
|
23
24
|
});
|
|
@@ -32,11 +33,16 @@ test("Claude managed install updates and restores the exact original settings",
|
|
|
32
33
|
assert.equal(installed.action, "installed");
|
|
33
34
|
assert.deepEqual(installed.managedKeys.sort(), [
|
|
34
35
|
"ANTHROPIC_BASE_URL",
|
|
35
|
-
"
|
|
36
|
+
"CLAUDE_CODE_ALWAYS_ENABLE_EFFORT",
|
|
37
|
+
"availableModels",
|
|
38
|
+
"enforceAvailableModels"
|
|
36
39
|
]);
|
|
37
40
|
const settings = JSON.parse(readFileSync(configPath, "utf8"));
|
|
38
41
|
assert.deepEqual(settings.permissions, { allow: ["Bash(git status)"] });
|
|
39
42
|
assert.equal(settings.env.ANTHROPIC_BASE_URL, "http://127.0.0.1:9999");
|
|
43
|
+
assert.equal(settings.env.CLAUDE_CODE_ALWAYS_ENABLE_EFFORT, "1");
|
|
44
|
+
assert.deepEqual(settings.availableModels, ["anthropic.routekit.openai/mock-model"]);
|
|
45
|
+
assert.equal(settings.enforceAvailableModels, true);
|
|
40
46
|
assert.equal("ANTHROPIC_AUTH_TOKEN" in settings.env, false);
|
|
41
47
|
assert.equal(statSync(configPath).mode & 0o777, 0o600);
|
|
42
48
|
const manifestPath = join(configDirectory, `.${OWNER.id}-integration.json`);
|
|
@@ -83,6 +89,48 @@ test("Claude uninstall preserves user edits made after install", async () => {
|
|
|
83
89
|
rmSync(configDirectory, { recursive: true, force: true });
|
|
84
90
|
}
|
|
85
91
|
});
|
|
92
|
+
test("Claude install merges and refreshes only RouteKit-owned picker entries", async () => {
|
|
93
|
+
const configDirectory = mkdtempSync(join(tmpdir(), "routekit-claude-picker-merge-"));
|
|
94
|
+
const configPath = join(configDirectory, "settings.json");
|
|
95
|
+
writeFileSync(configPath, `${JSON.stringify({
|
|
96
|
+
availableModels: ["claude-opus-4-6"],
|
|
97
|
+
enforceAvailableModels: false
|
|
98
|
+
})}\n`);
|
|
99
|
+
try {
|
|
100
|
+
await installClaudeIntegration({
|
|
101
|
+
gatewayUrl: "http://127.0.0.1:9999",
|
|
102
|
+
models: ["openai/gpt-5.6", "codex/gpt-5.6"],
|
|
103
|
+
owner: OWNER,
|
|
104
|
+
claudeConfigDir: configDirectory
|
|
105
|
+
});
|
|
106
|
+
let settings = JSON.parse(readFileSync(configPath, "utf8"));
|
|
107
|
+
assert.deepEqual(settings.availableModels, [
|
|
108
|
+
"claude-opus-4-6",
|
|
109
|
+
"anthropic.routekit.openai/gpt-5.6",
|
|
110
|
+
"anthropic.routekit.codex/gpt-5.6"
|
|
111
|
+
]);
|
|
112
|
+
assert.equal(settings.enforceAvailableModels, false);
|
|
113
|
+
await installClaudeIntegration({
|
|
114
|
+
gatewayUrl: "http://127.0.0.1:9999",
|
|
115
|
+
models: ["openai/gpt-5.7"],
|
|
116
|
+
owner: OWNER,
|
|
117
|
+
claudeConfigDir: configDirectory
|
|
118
|
+
});
|
|
119
|
+
settings = JSON.parse(readFileSync(configPath, "utf8"));
|
|
120
|
+
assert.deepEqual(settings.availableModels, [
|
|
121
|
+
"claude-opus-4-6",
|
|
122
|
+
"anthropic.routekit.openai/gpt-5.7"
|
|
123
|
+
]);
|
|
124
|
+
await uninstallClaudeIntegration({ ownerId: OWNER.id, claudeConfigDir: configDirectory });
|
|
125
|
+
assert.deepEqual(JSON.parse(readFileSync(configPath, "utf8")), {
|
|
126
|
+
availableModels: ["claude-opus-4-6"],
|
|
127
|
+
enforceAvailableModels: false
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
rmSync(configDirectory, { recursive: true, force: true });
|
|
132
|
+
}
|
|
133
|
+
});
|
|
86
134
|
test("Claude install refuses malformed settings and user-owned env conflicts", async () => {
|
|
87
135
|
const configDirectory = mkdtempSync(join(tmpdir(), "routekit-claude-conflict-"));
|
|
88
136
|
const configPath = join(configDirectory, "settings.json");
|
|
@@ -121,6 +169,7 @@ function spawnBlockedInstall(configDirectory, boundary) {
|
|
|
121
169
|
};
|
|
122
170
|
await installClaudeIntegration({
|
|
123
171
|
gatewayUrl: "http://127.0.0.1:9999",
|
|
172
|
+
models: ["openai/mock-model"],
|
|
124
173
|
owner: ${JSON.stringify(OWNER)},
|
|
125
174
|
claudeConfigDir: configDirectory
|
|
126
175
|
});
|
|
@@ -287,11 +336,13 @@ test("explicit config directory wins over CLAUDE_CONFIG_DIR, which wins over the
|
|
|
287
336
|
process.env.CLAUDE_CONFIG_DIR = environmentDirectory;
|
|
288
337
|
const fromEnvironment = await installClaudeIntegration({
|
|
289
338
|
gatewayUrl: "http://127.0.0.1:9999",
|
|
339
|
+
models: ["openai/mock-model"],
|
|
290
340
|
owner: OWNER
|
|
291
341
|
});
|
|
292
342
|
assert.equal(fromEnvironment.configPath, join(environmentDirectory, "settings.json"));
|
|
293
343
|
const explicit = await installClaudeIntegration({
|
|
294
344
|
gatewayUrl: "http://127.0.0.1:9999",
|
|
345
|
+
models: ["openai/mock-model"],
|
|
295
346
|
owner: OWNER,
|
|
296
347
|
claudeConfigDir: explicitDirectory
|
|
297
348
|
});
|
|
@@ -361,6 +412,8 @@ test("updating a v2 install removes an owned token without persisting its replac
|
|
|
361
412
|
const settings = JSON.parse(readFileSync(configPath, "utf8"));
|
|
362
413
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
363
414
|
assert.equal("ANTHROPIC_AUTH_TOKEN" in settings.env, false);
|
|
415
|
+
assert.equal("CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY" in settings.env, false);
|
|
416
|
+
assert.equal(settings.env.CLAUDE_CODE_ALWAYS_ENABLE_EFFORT, "1");
|
|
364
417
|
assert.equal("ANTHROPIC_AUTH_TOKEN" in manifest.managedEnvValues, false);
|
|
365
418
|
assert.equal(readFileSync(manifestPath, "utf8").includes("old-secret"), false);
|
|
366
419
|
assert.equal(readFileSync(manifestPath, "utf8").includes("new-secret"), false);
|
package/dist/test/launch.test.js
CHANGED
|
@@ -30,14 +30,14 @@ test("claudeAgentsJson serializes generic profiles", () => {
|
|
|
30
30
|
reviewer: {
|
|
31
31
|
description: "Review changes.",
|
|
32
32
|
prompt: "Return findings.",
|
|
33
|
-
model: "
|
|
33
|
+
model: "anthropic.routekit.opaque-model"
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
|
-
test("Claude launcher projects
|
|
37
|
+
test("Claude launcher projects RouteKit models to native picker ids", () => {
|
|
38
38
|
assert.deepEqual(claudeLaunchArgs(context([], [], "claude-code/claude-sonnet-4-6")), [
|
|
39
39
|
"--model",
|
|
40
|
-
"claude-sonnet-4-6"
|
|
40
|
+
"anthropic.routekit.claude-code/claude-sonnet-4-6"
|
|
41
41
|
]);
|
|
42
42
|
assert.deepEqual(JSON.parse(claudeAgentsJson([
|
|
43
43
|
{
|
|
@@ -56,12 +56,12 @@ test("Claude launcher projects claude-code models to native picker ids", () => {
|
|
|
56
56
|
native: {
|
|
57
57
|
description: "Use the subscription pool.",
|
|
58
58
|
prompt: "Review.",
|
|
59
|
-
model: "claude-opus-4-8"
|
|
59
|
+
model: "anthropic.routekit.claude-code/claude-opus-4-8"
|
|
60
60
|
},
|
|
61
61
|
cross: {
|
|
62
62
|
description: "Use Codex.",
|
|
63
63
|
prompt: "Review.",
|
|
64
|
-
model: "
|
|
64
|
+
model: "anthropic.routekit.codex/gpt-5.5"
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
});
|
|
@@ -80,13 +80,21 @@ test("Claude launcher forwards an explicit isolated config directory", () => {
|
|
|
80
80
|
});
|
|
81
81
|
test("claudeLaunchArgs adds profiles unless the user supplied agents", () => {
|
|
82
82
|
const args = claudeLaunchArgs(context(["--verbose"]));
|
|
83
|
-
assert.deepEqual(args.slice(0, 4), [
|
|
83
|
+
assert.deepEqual(args.slice(0, 4), [
|
|
84
|
+
"--model",
|
|
85
|
+
"anthropic.routekit.opaque-model",
|
|
86
|
+
"--verbose",
|
|
87
|
+
"--agents"
|
|
88
|
+
]);
|
|
84
89
|
assert.deepEqual(claudeLaunchArgs(context(["--agents={}"])), [
|
|
85
90
|
"--model",
|
|
86
|
-
"
|
|
91
|
+
"anthropic.routekit.opaque-model",
|
|
87
92
|
"--agents={}"
|
|
88
93
|
]);
|
|
89
|
-
assert.deepEqual(claudeLaunchArgs(context([], [])), [
|
|
94
|
+
assert.deepEqual(claudeLaunchArgs(context([], [])), [
|
|
95
|
+
"--model",
|
|
96
|
+
"anthropic.routekit.opaque-model"
|
|
97
|
+
]);
|
|
90
98
|
assert.deepEqual(claudeLaunchArgs(context(["--model", "claude-user-selected"], [])), [
|
|
91
99
|
"--model",
|
|
92
100
|
"claude-user-selected"
|
|
@@ -100,7 +108,12 @@ test("Claude launcher projects validated effort onto the picker model id", () =>
|
|
|
100
108
|
reasoning: { mode: "effort", effort: "high" }
|
|
101
109
|
}
|
|
102
110
|
};
|
|
103
|
-
assert.deepEqual(claudeLaunchArgs(withEffort), [
|
|
111
|
+
assert.deepEqual(claudeLaunchArgs(withEffort), [
|
|
112
|
+
"--effort",
|
|
113
|
+
"high",
|
|
114
|
+
"--model",
|
|
115
|
+
"anthropic.routekit.claude-code/claude-sonnet-4-6"
|
|
116
|
+
]);
|
|
104
117
|
const crossProvider = {
|
|
105
118
|
...context([], [], "codex/gpt-5.5"),
|
|
106
119
|
spec: {
|
|
@@ -108,7 +121,12 @@ test("Claude launcher projects validated effort onto the picker model id", () =>
|
|
|
108
121
|
reasoning: { mode: "effort", effort: "deep" }
|
|
109
122
|
}
|
|
110
123
|
};
|
|
111
|
-
assert.deepEqual(claudeLaunchArgs(crossProvider), [
|
|
124
|
+
assert.deepEqual(claudeLaunchArgs(crossProvider), [
|
|
125
|
+
"--effort",
|
|
126
|
+
"deep",
|
|
127
|
+
"--model",
|
|
128
|
+
"anthropic.routekit.codex/gpt-5.5"
|
|
129
|
+
]);
|
|
112
130
|
assert.deepEqual(claudeLaunchArgs({
|
|
113
131
|
...withEffort,
|
|
114
132
|
spec: {
|
|
@@ -120,7 +138,7 @@ test("Claude launcher projects validated effort onto the picker model id", () =>
|
|
|
120
138
|
test("Claude launches keep native session flags under native-client control", () => {
|
|
121
139
|
assert.deepEqual(claudeLaunchArgs(context(["--continue", "--resume", "native-id"], [])), [
|
|
122
140
|
"--model",
|
|
123
|
-
"
|
|
141
|
+
"anthropic.routekit.opaque-model",
|
|
124
142
|
"--continue",
|
|
125
143
|
"--resume",
|
|
126
144
|
"native-id"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velum-labs/routekit-tool-claude",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.17.
|
|
4
|
+
"version": "0.17.2",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/velum-labs/routekit.git",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@anthropic-ai/claude-agent-sdk": "0.3.198",
|
|
30
30
|
"zod": "4.4.3",
|
|
31
|
-
"@velum-labs/routekit-contracts": "0.17.
|
|
32
|
-
"@velum-labs/routekit-harness-core": "0.17.
|
|
33
|
-
"@velum-labs/routekit-registry": "0.17.
|
|
34
|
-
"@velum-labs/routekit-runtime": "0.17.
|
|
35
|
-
"@velum-labs/routekit-tools": "0.17.
|
|
31
|
+
"@velum-labs/routekit-contracts": "0.17.2",
|
|
32
|
+
"@velum-labs/routekit-harness-core": "0.17.2",
|
|
33
|
+
"@velum-labs/routekit-registry": "0.17.2",
|
|
34
|
+
"@velum-labs/routekit-runtime": "0.17.2",
|
|
35
|
+
"@velum-labs/routekit-tools": "0.17.2"
|
|
36
36
|
},
|
|
37
37
|
"keywords": [
|
|
38
38
|
"llm",
|