@velum-labs/routekit-tool-codex 0.17.2 → 0.17.4
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/launch.d.ts +1 -1
- package/dist/launch.js +35 -4
- package/dist/test/launch.test.js +67 -1
- package/package.json +6 -6
package/dist/launch.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare function hasCodexLogin(home?: string): boolean;
|
|
|
24
24
|
*/
|
|
25
25
|
export declare function createIsolatedCodexHome(prefix: string, env?: Record<string, string | undefined>): string;
|
|
26
26
|
export declare function codexListedStockSlugs(home?: string): string[];
|
|
27
|
-
export declare function codexCatalogEntries(spec: Pick<ToolLaunchSpec, "defaultModel" | "models">, template: CodexModelPreset, stockModels?: readonly CodexModelPreset[], options?: {
|
|
27
|
+
export declare function codexCatalogEntries(spec: Pick<ToolLaunchSpec, "defaultModel" | "modelSelection" | "models">, template: CodexModelPreset, stockModels?: readonly CodexModelPreset[], options?: {
|
|
28
28
|
appendUnlistedStock?: boolean;
|
|
29
29
|
}): Record<string, unknown>[];
|
|
30
30
|
export declare function codexModelCatalogJson(spec: Pick<ToolLaunchSpec, "defaultModel" | "models">, template: CodexModelPreset, stockModels?: readonly CodexModelPreset[], options?: {
|
package/dist/launch.js
CHANGED
|
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { isAbsolute, join } from "node:path";
|
|
5
|
-
import { isCodexPickerEligibleModel, reasoningEffortDescriptors } from "@velum-labs/routekit-contracts";
|
|
5
|
+
import { codexCompatibility, isCodexPickerEligibleModel, reasoningEffortDescriptors } from "@velum-labs/routekit-contracts";
|
|
6
6
|
import { trimTrailingSlashes } from "@velum-labs/routekit-runtime";
|
|
7
7
|
import { stringify as tomlStringify } from "smol-toml";
|
|
8
8
|
const PROVIDER_ID = "routekit";
|
|
@@ -88,9 +88,33 @@ function codexModelId(modelId) {
|
|
|
88
88
|
return modelId.startsWith("codex/") ? modelId.slice("codex/".length) : modelId;
|
|
89
89
|
}
|
|
90
90
|
function catalogModels(spec) {
|
|
91
|
-
return spec.models.filter((model) =>
|
|
92
|
-
model.
|
|
93
|
-
|
|
91
|
+
return spec.models.filter((model) => {
|
|
92
|
+
const isDefault = model.id === spec.defaultModel ||
|
|
93
|
+
model.aliases?.includes(spec.defaultModel) === true;
|
|
94
|
+
if (spec.modelSelection === undefined) {
|
|
95
|
+
return isDefault || isCodexPickerEligibleModel(model);
|
|
96
|
+
}
|
|
97
|
+
if (isDefault && spec.modelSelection !== "implicit")
|
|
98
|
+
return true;
|
|
99
|
+
return codexCompatibility({
|
|
100
|
+
id: model.id,
|
|
101
|
+
...(model.provider !== undefined ? { provider: model.provider } : {}),
|
|
102
|
+
...(model.architecture !== undefined ? { architecture: model.architecture } : {}),
|
|
103
|
+
...(model.supportedParameters !== undefined
|
|
104
|
+
? { supportedParameters: model.supportedParameters }
|
|
105
|
+
: {}),
|
|
106
|
+
...(model.features?.tools !== undefined
|
|
107
|
+
? {
|
|
108
|
+
capabilities: {
|
|
109
|
+
tools: model.features.tools === "full"
|
|
110
|
+
? "supported"
|
|
111
|
+
: model.features.tools
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
: {}),
|
|
115
|
+
...(model.reasoning !== undefined ? { reasoning: model.reasoning } : {})
|
|
116
|
+
}).status === "compatible";
|
|
117
|
+
});
|
|
94
118
|
}
|
|
95
119
|
function catalogIds(spec) {
|
|
96
120
|
return [
|
|
@@ -387,6 +411,13 @@ function spawnCodex(args, home, cwd, token, dependencies) {
|
|
|
387
411
|
}
|
|
388
412
|
/** Launch against the user's real Codex home; only generated catalog data is temporary. */
|
|
389
413
|
export async function launchCodex(ctx, deps = {}) {
|
|
414
|
+
if (!ctx.spec.models.some((model) => model.id === ctx.spec.defaultModel)) {
|
|
415
|
+
throw new Error(`Codex startup model "${ctx.spec.defaultModel}" is absent from the advertised catalog`);
|
|
416
|
+
}
|
|
417
|
+
if (!catalogModels(ctx.spec).some((model) => model.id === ctx.spec.defaultModel ||
|
|
418
|
+
model.aliases?.includes(ctx.spec.defaultModel) === true)) {
|
|
419
|
+
throw new Error(`Codex startup model "${ctx.spec.defaultModel}" is not in the compatible model picker`);
|
|
420
|
+
}
|
|
390
421
|
const home = resolveCodexHome(deps.env ?? process.env);
|
|
391
422
|
const temp = mkdtempSync(join(tmpdir(), "rk-codex-"));
|
|
392
423
|
ctx.registerDisposer(() => rmSync(temp, { recursive: true, force: true }));
|
package/dist/test/launch.test.js
CHANGED
|
@@ -3,7 +3,7 @@ import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { test } from "node:test";
|
|
6
|
-
import { codexAgentRoleToml, codexCatalogEntries, codexLaunchConfigToml, codexModelCatalogJson, codexPersistentModelCatalogJson, createIsolatedCodexHome, resolveCodexHome } from "../launch.js";
|
|
6
|
+
import { codexAgentRoleToml, codexCatalogEntries, codexLaunchConfigToml, codexModelCatalogJson, codexPersistentModelCatalogJson, createIsolatedCodexHome, launchCodex, resolveCodexHome } from "../launch.js";
|
|
7
7
|
const SPEC = {
|
|
8
8
|
gatewayUrl: "http://127.0.0.1:9999",
|
|
9
9
|
defaultModel: "opaque-primary",
|
|
@@ -71,6 +71,72 @@ test("Codex launcher filters incompatible OpenRouter models and aliases", () =>
|
|
|
71
71
|
};
|
|
72
72
|
assert.deepEqual(codexCatalogEntries(spec, { slug: "stock" }, [], { appendUnlistedStock: false }).map((entry) => entry.slug), ["openai/unknown", "openrouter/reasoning", "reasoning-alias", "openai-alias"]);
|
|
73
73
|
});
|
|
74
|
+
test("implicit Codex picker excludes embedding models and keeps the selected generation model", () => {
|
|
75
|
+
const spec = {
|
|
76
|
+
gatewayUrl: "http://127.0.0.1:9999",
|
|
77
|
+
defaultModel: "openai/a-generation",
|
|
78
|
+
modelSelection: "implicit",
|
|
79
|
+
models: [
|
|
80
|
+
{
|
|
81
|
+
id: "openai/text-embedding-ada-002",
|
|
82
|
+
provider: "openai",
|
|
83
|
+
architecture: {
|
|
84
|
+
inputModalities: ["text"],
|
|
85
|
+
outputModalities: ["embeddings"]
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: "openai/a-generation",
|
|
90
|
+
provider: "openai",
|
|
91
|
+
architecture: {
|
|
92
|
+
inputModalities: ["text"],
|
|
93
|
+
outputModalities: ["text"]
|
|
94
|
+
},
|
|
95
|
+
supportedParameters: ["tools"]
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
args: []
|
|
99
|
+
};
|
|
100
|
+
assert.deepEqual(codexCatalogEntries(spec, { slug: "stock" }, [], {
|
|
101
|
+
appendUnlistedStock: false
|
|
102
|
+
}).map((entry) => entry.slug), ["openai/a-generation"]);
|
|
103
|
+
});
|
|
104
|
+
test("Codex fails before passthrough or child spawn when an implicit default is incompatible", async () => {
|
|
105
|
+
let prepared = false;
|
|
106
|
+
let spawned = false;
|
|
107
|
+
await assert.rejects(launchCodex({
|
|
108
|
+
spec: {
|
|
109
|
+
gatewayUrl: "http://127.0.0.1:9999",
|
|
110
|
+
defaultModel: "openai/text-embedding-ada-002",
|
|
111
|
+
modelSelection: "implicit",
|
|
112
|
+
models: [
|
|
113
|
+
{
|
|
114
|
+
id: "openai/text-embedding-ada-002",
|
|
115
|
+
provider: "openai",
|
|
116
|
+
architecture: {
|
|
117
|
+
inputModalities: ["text"],
|
|
118
|
+
outputModalities: ["embeddings"]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
args: []
|
|
123
|
+
},
|
|
124
|
+
log: () => { },
|
|
125
|
+
prepareForPassthrough: () => {
|
|
126
|
+
prepared = true;
|
|
127
|
+
},
|
|
128
|
+
registerPort: () => "",
|
|
129
|
+
unregisterPort: () => { },
|
|
130
|
+
registerDisposer: () => { }
|
|
131
|
+
}, {
|
|
132
|
+
spawnProcess: (() => {
|
|
133
|
+
spawned = true;
|
|
134
|
+
throw new Error("must not spawn");
|
|
135
|
+
})
|
|
136
|
+
}), /not in the compatible model picker/);
|
|
137
|
+
assert.equal(prepared, false);
|
|
138
|
+
assert.equal(spawned, false);
|
|
139
|
+
});
|
|
74
140
|
test("Codex launcher neutralizes stock-model behavior for gateway-routed models", () => {
|
|
75
141
|
const template = {
|
|
76
142
|
slug: "gpt-stock",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velum-labs/routekit-tool-codex",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.17.
|
|
4
|
+
"version": "0.17.4",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/velum-labs/routekit.git",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"@openai/codex-sdk": "0.145.0",
|
|
30
30
|
"smol-toml": "1.7.0",
|
|
31
31
|
"zod": "4.4.3",
|
|
32
|
-
"@velum-labs/routekit-contracts": "0.17.
|
|
33
|
-
"@velum-labs/routekit-harness-core": "0.17.
|
|
34
|
-
"@velum-labs/routekit-
|
|
35
|
-
"@velum-labs/routekit-tools": "0.17.
|
|
36
|
-
"@velum-labs/routekit-
|
|
32
|
+
"@velum-labs/routekit-contracts": "0.17.4",
|
|
33
|
+
"@velum-labs/routekit-harness-core": "0.17.4",
|
|
34
|
+
"@velum-labs/routekit-registry": "0.17.4",
|
|
35
|
+
"@velum-labs/routekit-tools": "0.17.4",
|
|
36
|
+
"@velum-labs/routekit-runtime": "0.17.4"
|
|
37
37
|
},
|
|
38
38
|
"keywords": [
|
|
39
39
|
"llm",
|