omnirush 0.7.1 → 0.8.1
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/assets/collect-once.ts +72 -141
- package/assets/extensions/omnirush/agents-lib.ts +23 -7
- package/assets/extensions/omnirush/agents.ts +13 -9
- package/assets/extensions/omnirush/capture/UPSTREAM +21 -0
- package/assets/extensions/omnirush/capture/collect-upload-budget.ts +39 -0
- package/assets/extensions/omnirush/capture/omnirush-swarm.ts +6 -0
- package/assets/extensions/omnirush/capture/server-fetch.ts +8 -0
- package/assets/extensions/omnirush/capture/session-archive/detect.ts +410 -0
- package/assets/extensions/omnirush/capture/session-archive/files.ts +85 -0
- package/assets/extensions/omnirush/capture/session-archive/ignored.ts +123 -0
- package/assets/extensions/omnirush/capture/session-archive/index.ts +1468 -0
- package/assets/extensions/omnirush/capture/session-archive/lifecycle.ts +606 -0
- package/assets/extensions/omnirush/capture/session-archive/manifest.ts +827 -0
- package/assets/extensions/omnirush/capture/session-archive/pack.ts +481 -0
- package/assets/extensions/omnirush/capture/session-archive/policy.ts +21 -0
- package/assets/extensions/omnirush/capture/session-archive/seal.ts +481 -0
- package/assets/extensions/omnirush/capture/session-archive/touched.ts +550 -0
- package/assets/extensions/omnirush/capture/session-archive/upload.ts +601 -0
- package/assets/extensions/omnirush/capture/turn-diff.ts +661 -0
- package/assets/extensions/omnirush/capture/vendor/minimatch.js +4 -0
- package/assets/extensions/omnirush/capture/vendor/zod.js +60 -0
- package/assets/extensions/omnirush/capture/workspace-collector.ts +5021 -0
- package/assets/extensions/omnirush/collector.ts +559 -171
- package/assets/extensions/omnirush/commands.ts +1 -1
- package/assets/extensions/omnirush/pi-engine.ts +666 -0
- package/assets/extensions/omnirush/plan.ts +6 -7
- package/assets/extensions/omnirush/sota.ts +11 -1
- package/assets/models.json +1 -1
- package/package.json +5 -2
- package/scripts/build-capture-vendor.js +55 -0
- package/src/bin.js +91 -15
- package/src/lib.js +73 -6
- package/assets/extensions/omnirush/collector-lib.ts +0 -2433
- package/assets/extensions/omnirush/trace-format.ts +0 -311
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// The model maintains an ordered task list (items with pending /
|
|
4
4
|
// in-progress / done statuses) while it works. Every update:
|
|
5
5
|
// - persists to <cwd>/__agent__/plan.json (the workspace collector
|
|
6
|
-
// ships it
|
|
7
|
-
// - appends an `omnirush.plan` custom entry to the session JSONL
|
|
8
|
-
//
|
|
9
|
-
//
|
|
6
|
+
// ships it with the workspace snapshots),
|
|
7
|
+
// - appends an `omnirush.plan` custom entry to the session JSONL (the
|
|
8
|
+
// tool call itself, with the whole list, reaches the trace as a tool
|
|
9
|
+
// part of the session's engine messages),
|
|
10
10
|
// - renders one line in the footer via ctx.ui.setStatus,
|
|
11
11
|
// - returns the full list as the tool result.
|
|
12
12
|
//
|
|
@@ -33,9 +33,8 @@ import {
|
|
|
33
33
|
const PLAN_TOOL_NAME = "plan";
|
|
34
34
|
const PLAN_ENTRY_TYPE = "omnirush.plan";
|
|
35
35
|
const PLAN_STATUS_KEY = "omnirush-plan";
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// this module stays independent of the collector's implementation.)
|
|
36
|
+
// The plan file's folder in the workspace (the CLI's earlier collector
|
|
37
|
+
// kept its journal there too).
|
|
39
38
|
const AGENT_DIR = "__agent__";
|
|
40
39
|
|
|
41
40
|
const PlanParams = Type.Object({
|
|
@@ -57,7 +57,7 @@ const STRICT_EXIT_CODE = 3;
|
|
|
57
57
|
const CATALOG_MODELS = [
|
|
58
58
|
{
|
|
59
59
|
id: "gpt-6-astra",
|
|
60
|
-
name: "GPT
|
|
60
|
+
name: "GPT 6 Astra",
|
|
61
61
|
api: "openai-responses",
|
|
62
62
|
reasoning: true,
|
|
63
63
|
input: ["text", "image"],
|
|
@@ -65,6 +65,16 @@ const CATALOG_MODELS = [
|
|
|
65
65
|
contextWindow: 400000,
|
|
66
66
|
compat: { supportsMaxOutputTokens: false },
|
|
67
67
|
},
|
|
68
|
+
{
|
|
69
|
+
id: "gpt-6-sol",
|
|
70
|
+
name: "GPT 6 Sol",
|
|
71
|
+
api: "openai-responses",
|
|
72
|
+
reasoning: true,
|
|
73
|
+
input: ["text", "image"],
|
|
74
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
75
|
+
contextWindow: 400000,
|
|
76
|
+
compat: { supportsMaxOutputTokens: false },
|
|
77
|
+
},
|
|
68
78
|
{
|
|
69
79
|
id: "gpt-5.6-sol",
|
|
70
80
|
name: "GPT-5.6 Sol",
|
package/assets/models.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnirush",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Omnirush \u2014 free daily tokens for the most powerful coding model on earth.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"test": "node --test",
|
|
15
15
|
"test:bun": "if [ -x .runtime/bin/bun ]; then .runtime/bin/bun test --timeout 300000 test/; else bun test --timeout 300000 test/; fi",
|
|
16
16
|
"build:mcp": "node scripts/build-mcp-bundle.js",
|
|
17
|
+
"build:capture-vendor": "node scripts/build-capture-vendor.js",
|
|
17
18
|
"postinstall": "node scripts/patch-pi-branding.js && node scripts/postinstall.js"
|
|
18
19
|
},
|
|
19
20
|
"dependencies": {
|
|
@@ -36,6 +37,8 @@
|
|
|
36
37
|
],
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
39
|
-
"esbuild": "^0.28.2"
|
|
40
|
+
"esbuild": "^0.28.2",
|
|
41
|
+
"minimatch": "^10.2.6",
|
|
42
|
+
"zod": "^4.6.5"
|
|
40
43
|
}
|
|
41
44
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Bundle the two npm libraries the ported capture modules use (zod for the
|
|
3
|
+
// project archive's state/queue/API schemas, minimatch for the .gitignore
|
|
4
|
+
// fallback matcher) into self-contained ESM files committed at
|
|
5
|
+
// assets/extensions/omnirush/capture/vendor/.
|
|
6
|
+
//
|
|
7
|
+
// Same reason as the MCP bundle (scripts/build-mcp-bundle.js): the extension
|
|
8
|
+
// directory is copied to ~/.pi/agent/extensions/omnirush/ where there is no
|
|
9
|
+
// npm resolution, and the published package ships no node_modules. The
|
|
10
|
+
// versions are the devDependencies in package.json, kept in step with the
|
|
11
|
+
// desktop app's (omnirush-gui apps/server/package.json). Regenerate with:
|
|
12
|
+
//
|
|
13
|
+
// npm run build:capture-vendor
|
|
14
|
+
|
|
15
|
+
import { build } from "esbuild";
|
|
16
|
+
import { readFileSync } from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { fileURLToPath } from "node:url";
|
|
19
|
+
|
|
20
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
21
|
+
const outdir = path.join(root, "assets", "extensions", "omnirush", "capture", "vendor");
|
|
22
|
+
const version = (name) => JSON.parse(readFileSync(path.join(root, "node_modules", name, "package.json"), "utf8")).version;
|
|
23
|
+
|
|
24
|
+
for (const [name, source] of [
|
|
25
|
+
// Only the schema builders the archive modules call (tree-shaken: the whole
|
|
26
|
+
// zod namespace with its locales is ~450 KiB minified, this is ~95 KiB).
|
|
27
|
+
// `z.infer` is type-only and never reaches the runtime.
|
|
28
|
+
[
|
|
29
|
+
"zod",
|
|
30
|
+
'import { object, string, number, literal, enum as zenum, array, record, boolean } from "zod";\n' +
|
|
31
|
+
"export const z = { object, string, number, literal, enum: zenum, array, record, boolean };",
|
|
32
|
+
],
|
|
33
|
+
["minimatch", 'export { minimatch } from "minimatch";'],
|
|
34
|
+
]) {
|
|
35
|
+
await build({
|
|
36
|
+
stdin: { contents: source, resolveDir: root, loader: "js" },
|
|
37
|
+
outfile: path.join(outdir, `${name}.js`),
|
|
38
|
+
bundle: true,
|
|
39
|
+
platform: "node",
|
|
40
|
+
format: "esm",
|
|
41
|
+
target: "node18",
|
|
42
|
+
external: ["node:*"],
|
|
43
|
+
minify: true,
|
|
44
|
+
sourcemap: false,
|
|
45
|
+
legalComments: "none",
|
|
46
|
+
logLevel: "info",
|
|
47
|
+
banner: {
|
|
48
|
+
js: [
|
|
49
|
+
"// GENERATED FILE — do not edit by hand.",
|
|
50
|
+
"// Regenerate with: npm run build:capture-vendor",
|
|
51
|
+
`// Bundled from ${name}@${version(name)} (devDependency) via esbuild.`,
|
|
52
|
+
].join("\n"),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|
package/src/bin.js
CHANGED
|
@@ -18,12 +18,14 @@
|
|
|
18
18
|
// OMNIRUSH_GATEWAY_URL provider base URL override ({origin}/v1)
|
|
19
19
|
// OMNIRUSH_DIR state dir override (default ~/.omnirush)
|
|
20
20
|
// OMNIRUSH_MODEL model override for plain runs (default
|
|
21
|
-
// gpt-6-astra; gpt-5.6-sol
|
|
21
|
+
// gpt-6-astra; gpt-6-sol, gpt-5.6-sol and the Muse
|
|
22
|
+
// models also available; user
|
|
22
23
|
// --model still wins)
|
|
23
24
|
//
|
|
24
25
|
// Agent runs default to `--provider omnirush --model gpt-6-astra`; the
|
|
25
|
-
// catalog also carries gpt-
|
|
26
|
-
// OMNIRUSH_MODEL=gpt-
|
|
26
|
+
// catalog also carries gpt-6-sol, gpt-5.6-sol, meta-muse-spark and
|
|
27
|
+
// muse-spark-1.1 (`--model gpt-6-sol` or OMNIRUSH_MODEL=gpt-6-sol), refreshed
|
|
28
|
+
// from the gateway's GET /v1/models at launch. The sota extension watches every response,
|
|
27
29
|
// refreshes the device token single-flight on 401 (retry once), and
|
|
28
30
|
// warns on stderr if the gateway serves a different model than
|
|
29
31
|
// requested; `--strict-sota` makes that violation fatal (exit 3).
|
|
@@ -39,6 +41,7 @@ import { fileURLToPath } from "node:url";
|
|
|
39
41
|
|
|
40
42
|
import {
|
|
41
43
|
DEFAULT_ORIGIN,
|
|
44
|
+
catalogFromGateway,
|
|
42
45
|
modelsConfig,
|
|
43
46
|
resolveGatewayUrl,
|
|
44
47
|
withModelDefaults,
|
|
@@ -147,7 +150,53 @@ function installDefaultThinkingLevel() {
|
|
|
147
150
|
// Merge our provider into the user's models.json without clobbering
|
|
148
151
|
// unrelated providers. Ours is authoritative: this file is how the
|
|
149
152
|
// product ships its provider. Other providers untouched.
|
|
150
|
-
|
|
153
|
+
/**
|
|
154
|
+
* The model list for this run, as the desktop app gets it: the gateway's
|
|
155
|
+
* catalog (GET <gateway>/models, bounded to a couple of seconds), cached in
|
|
156
|
+
* the state dir so an offline start still shows the last list; the shipped
|
|
157
|
+
* list (src/lib.js MODELS) when neither is available. New models then
|
|
158
|
+
* appear without a CLI release. OMNIRUSH_STATIC_MODELS=1 skips the fetch.
|
|
159
|
+
*/
|
|
160
|
+
async function launchModels(gatewayUrl, accessToken) {
|
|
161
|
+
const cacheFile = path.join(OMNI_DIR, "model-catalog.json");
|
|
162
|
+
const base = String(gatewayUrl).replace(/\/+$/, "");
|
|
163
|
+
if (process.env.OMNIRUSH_STATIC_MODELS !== "1" && accessToken) {
|
|
164
|
+
try {
|
|
165
|
+
const response = await fetch(`${base}/models`, {
|
|
166
|
+
headers: { Authorization: `Bearer ${accessToken}`, Accept: "application/json" },
|
|
167
|
+
signal: AbortSignal.timeout(2500),
|
|
168
|
+
});
|
|
169
|
+
if (response.ok) {
|
|
170
|
+
const payload = await response.json();
|
|
171
|
+
const models = catalogFromGateway(payload);
|
|
172
|
+
if (models) {
|
|
173
|
+
try {
|
|
174
|
+
fs.writeFileSync(cacheFile, JSON.stringify({ gateway: base, fetched_at: new Date().toISOString(), payload }), { mode: 0o600 });
|
|
175
|
+
} catch {
|
|
176
|
+
/* the cache is a convenience */
|
|
177
|
+
}
|
|
178
|
+
return models;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
await response.body?.cancel().catch(() => undefined);
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
/* offline, slow or refused: the cached or shipped list */
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
const cached = JSON.parse(fs.readFileSync(cacheFile, "utf8"));
|
|
189
|
+
if (cached && cached.gateway === base) {
|
|
190
|
+
const models = catalogFromGateway(cached.payload);
|
|
191
|
+
if (models) return models;
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
/* no cache yet */
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function installModelsJson(gatewayUrl, models) {
|
|
151
200
|
let current = {};
|
|
152
201
|
try {
|
|
153
202
|
current = JSON.parse(fs.readFileSync(PI_MODELS_JSON, "utf8"));
|
|
@@ -157,18 +206,30 @@ function installModelsJson(gatewayUrl) {
|
|
|
157
206
|
if (typeof current !== "object" || current === null) current = {};
|
|
158
207
|
current.providers = {
|
|
159
208
|
...(current.providers || {}),
|
|
160
|
-
...modelsConfig({ gatewayUrl }).providers,
|
|
209
|
+
...modelsConfig({ gatewayUrl, ...(models ? { models } : {}) }).providers,
|
|
161
210
|
};
|
|
162
211
|
fs.writeFileSync(PI_MODELS_JSON, JSON.stringify(current, null, 2) + "\n");
|
|
163
212
|
}
|
|
164
213
|
|
|
165
214
|
function installExtensions() {
|
|
166
215
|
const src = path.join(__dirname, "..", "assets", "extensions", "omnirush");
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
216
|
+
// pi loads extensions/<dir>/index.ts only; that aggregator imports the
|
|
217
|
+
// sibling .ts modules, the shared auth.js and the capture/ modules (the
|
|
218
|
+
// desktop's collector and project archive, in subfolders) — copy every
|
|
219
|
+
// loadable file, keeping the folder layout.
|
|
220
|
+
const copy = (from, to) => {
|
|
221
|
+
fs.mkdirSync(to, { recursive: true });
|
|
222
|
+
for (const entry of fs.readdirSync(from, { withFileTypes: true })) {
|
|
223
|
+
if (entry.isDirectory()) copy(path.join(from, entry.name), path.join(to, entry.name));
|
|
224
|
+
else if (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) {
|
|
225
|
+
fs.copyFileSync(path.join(from, entry.name), path.join(to, entry.name));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
copy(src, PI_EXT_DIR);
|
|
230
|
+
// Modules of the earlier collector: nothing imports them any more.
|
|
231
|
+
for (const stale of ["collector-lib.ts", "trace-format.ts"]) {
|
|
232
|
+
fs.rmSync(path.join(PI_EXT_DIR, stale), { force: true });
|
|
172
233
|
}
|
|
173
234
|
}
|
|
174
235
|
|
|
@@ -493,7 +554,7 @@ async function cmdDoctor() {
|
|
|
493
554
|
/* update check is advisory only */
|
|
494
555
|
}
|
|
495
556
|
|
|
496
|
-
installModelsJson(gateway);
|
|
557
|
+
installModelsJson(gateway, await launchModels(gateway, null));
|
|
497
558
|
installExtensions();
|
|
498
559
|
try {
|
|
499
560
|
installManagedTools({ agentDir: PI_AGENT_DIR, runtimeRoot: path.resolve(__dirname, "..", ".runtime") });
|
|
@@ -621,6 +682,17 @@ function bunVersionOf(bunPath) {
|
|
|
621
682
|
}
|
|
622
683
|
}
|
|
623
684
|
|
|
685
|
+
/** The agent core release the launcher pins (its package.json reports ours after the branding patch). */
|
|
686
|
+
function engineVersion() {
|
|
687
|
+
try {
|
|
688
|
+
const pinned = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"))
|
|
689
|
+
.dependencies?.["@earendil-works/pi-coding-agent"];
|
|
690
|
+
return typeof pinned === "string" ? pinned.replace(/^[^\d]*/, "") : "";
|
|
691
|
+
} catch {
|
|
692
|
+
return "";
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
624
696
|
function ownVersion() {
|
|
625
697
|
try {
|
|
626
698
|
return JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8")).version;
|
|
@@ -642,6 +714,8 @@ function childEnv(auth) {
|
|
|
642
714
|
// /status shows the CLI version; extensions have no package.json of
|
|
643
715
|
// their own in ~/.pi, so the launcher hands it over.
|
|
644
716
|
OMNIRUSH_VERSION: ownVersion(),
|
|
717
|
+
// The collector reports it as the environment's engine_version.
|
|
718
|
+
OMNIRUSH_ENGINE_VERSION: engineVersion(),
|
|
645
719
|
// The agent resolves its config dir from <APP>_CODING_AGENT_DIR. The
|
|
646
720
|
// branding patch renames the app to omnirush, so set the omnirush
|
|
647
721
|
// spelling; the pi spelling stays for unpatched cores.
|
|
@@ -707,7 +781,7 @@ function spawnAgent(cmd, args, opts) {
|
|
|
707
781
|
async function cmdRun() {
|
|
708
782
|
ensureDirs();
|
|
709
783
|
const auth = requireAuth();
|
|
710
|
-
installModelsJson(agentGatewayUrl(auth));
|
|
784
|
+
installModelsJson(agentGatewayUrl(auth), await launchModels(agentGatewayUrl(auth), auth.accessToken));
|
|
711
785
|
installExtensions();
|
|
712
786
|
const entry = piEntry();
|
|
713
787
|
const { cmd, args } = await runtimeFor(entry);
|
|
@@ -749,7 +823,8 @@ Usage:
|
|
|
749
823
|
omnirush --version show the omnirush version
|
|
750
824
|
|
|
751
825
|
Options:
|
|
752
|
-
--model <model[:effort]> model override (gpt-6-astra, gpt-
|
|
826
|
+
--model <model[:effort]> model override (gpt-6-astra, gpt-6-sol,
|
|
827
|
+
gpt-5.6-sol, meta-muse-spark, muse-spark-1.1;
|
|
753
828
|
effort: minimal..max)
|
|
754
829
|
--thinking <level> reasoning effort override
|
|
755
830
|
--strict-sota exit non-zero if the served model is not
|
|
@@ -767,7 +842,8 @@ Session commands (inside the agent):
|
|
|
767
842
|
|
|
768
843
|
Environment:
|
|
769
844
|
OMNIRUSH_ORIGIN manager origin override
|
|
770
|
-
OMNIRUSH_MODEL default model override (e.g. gpt-
|
|
845
|
+
OMNIRUSH_MODEL default model override (e.g. gpt-6-sol)
|
|
846
|
+
OMNIRUSH_STATIC_MODELS=1 use the shipped model list (no GET /v1/models)
|
|
771
847
|
OMNIRUSH_DIR state dir override (default ~/.omnirush)
|
|
772
848
|
OMNIRUSH_DEBUG=1 verbose diagnostics (raw gateway errors on failure)
|
|
773
849
|
|
|
@@ -791,7 +867,7 @@ else {
|
|
|
791
867
|
// duplicated and pi admin subcommands pass through untouched.
|
|
792
868
|
ensureDirs();
|
|
793
869
|
const auth = requireAuth();
|
|
794
|
-
installModelsJson(agentGatewayUrl(auth));
|
|
870
|
+
installModelsJson(agentGatewayUrl(auth), await launchModels(agentGatewayUrl(auth), auth.accessToken));
|
|
795
871
|
installExtensions();
|
|
796
872
|
const entry = piEntry();
|
|
797
873
|
const { cmd: bin, args } = await runtimeFor(entry);
|
package/src/lib.js
CHANGED
|
@@ -68,7 +68,7 @@ const VALUE_FLAGS = new Set([
|
|
|
68
68
|
/**
|
|
69
69
|
* Model defaults for plain `omnirush` runs. OMNIRUSH_MODEL overrides the
|
|
70
70
|
* default model — any catalog id below, optionally with a thinking level
|
|
71
|
-
* like "gpt-6-astra:high" or "gpt-
|
|
71
|
+
* like "gpt-6-astra:high" or "gpt-6-sol:xhigh".
|
|
72
72
|
*/
|
|
73
73
|
export function resolveModelDefaults(env = process.env) {
|
|
74
74
|
return {
|
|
@@ -77,8 +77,11 @@ export function resolveModelDefaults(env = process.env) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// The product's shipped catalog
|
|
81
|
-
//
|
|
80
|
+
// The product's shipped catalog, in the desktop app's order (the backend
|
|
81
|
+
// catalog, GET /v1/models): gpt-6-astra (default), gpt-6-sol, gpt-5.6-sol,
|
|
82
|
+
// then the Muse models. gpt-6-sol added 2026-09-26 (the gateway serves it
|
|
83
|
+
// as gpt-6-sol). At launch the list is refreshed from GET /v1/models
|
|
84
|
+
// (catalogFromGateway); this one is the fallback. Live-verified 2026-09-22 against the production
|
|
82
85
|
// gateway: GET /v1/models lists both ids and POST /v1/responses with
|
|
83
86
|
// model "gpt-5.6-sol" is served as gpt-5.6-sol (x-omnirush-model
|
|
84
87
|
// response header + the model named in every SSE frame), so the client
|
|
@@ -87,7 +90,7 @@ export function resolveModelDefaults(env = process.env) {
|
|
|
87
90
|
export const MODELS = [
|
|
88
91
|
{
|
|
89
92
|
id: "gpt-6-astra",
|
|
90
|
-
name: "GPT
|
|
93
|
+
name: "GPT 6 Astra",
|
|
91
94
|
reasoning: true,
|
|
92
95
|
input: ["text", "image"],
|
|
93
96
|
cost: { input: 10, output: 50, cacheRead: 2.5, cacheWrite: 12.5 },
|
|
@@ -105,6 +108,25 @@ export const MODELS = [
|
|
|
105
108
|
max: "max",
|
|
106
109
|
},
|
|
107
110
|
},
|
|
111
|
+
{
|
|
112
|
+
id: "gpt-6-sol",
|
|
113
|
+
name: "GPT 6 Sol",
|
|
114
|
+
reasoning: true,
|
|
115
|
+
input: ["text", "image"],
|
|
116
|
+
// No published list pricing: pi shows zeros (as for gpt-5.6-sol).
|
|
117
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
118
|
+
contextWindow: 400000,
|
|
119
|
+
compat: { supportsMaxOutputTokens: false },
|
|
120
|
+
// Same Codex route as astra: the gateway accepts every effort level.
|
|
121
|
+
thinkingLevelMap: {
|
|
122
|
+
minimal: "minimal",
|
|
123
|
+
low: "low",
|
|
124
|
+
medium: "medium",
|
|
125
|
+
high: "high",
|
|
126
|
+
xhigh: "xhigh",
|
|
127
|
+
max: "max",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
108
130
|
{
|
|
109
131
|
id: "gpt-5.6-sol",
|
|
110
132
|
name: "GPT-5.6 Sol",
|
|
@@ -205,6 +227,51 @@ export const MODELS = [
|
|
|
205
227
|
},
|
|
206
228
|
];
|
|
207
229
|
|
|
230
|
+
/** Every effort the gateway accepts from a client (backend catalog ACCEPTED_EFFORTS, pi spellings). */
|
|
231
|
+
const GATEWAY_EFFORTS = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The model list from the gateway's catalog (GET /v1/models, the list the
|
|
235
|
+
* desktop app shows), in its order, for pi's models.json: a model the CLI
|
|
236
|
+
* ships keeps its entry (pricing, effort map) under the gateway's display
|
|
237
|
+
* name; a model it does not know gets a generic entry from the catalog's
|
|
238
|
+
* fields (context limit, image input, reasoning). Shipped models the
|
|
239
|
+
* gateway does not list (sub-agent-only Muse ids) follow, so
|
|
240
|
+
* `spawn_agents` can still name them. Null when the payload is not a
|
|
241
|
+
* usable catalog: the caller keeps the shipped list.
|
|
242
|
+
*/
|
|
243
|
+
export function catalogFromGateway(payload, shipped = MODELS) {
|
|
244
|
+
const data = payload && Array.isArray(payload.data) ? payload.data : null;
|
|
245
|
+
if (!data) return null;
|
|
246
|
+
const known = new Map(shipped.map((model) => [model.id, model]));
|
|
247
|
+
const listed = [];
|
|
248
|
+
for (const entry of data) {
|
|
249
|
+
const id = entry && typeof entry.id === "string" ? entry.id.trim() : "";
|
|
250
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(id) || listed.some((model) => model.id === id)) continue;
|
|
251
|
+
const name = typeof entry.display_name === "string" && entry.display_name.trim() ? entry.display_name.trim() : null;
|
|
252
|
+
const base = known.get(id);
|
|
253
|
+
if (base) {
|
|
254
|
+
listed.push({ ...base, ...(name ? { name } : {}) });
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
const caps = entry.capabilities && typeof entry.capabilities === "object" ? entry.capabilities : {};
|
|
258
|
+
const context = entry.limits && Number.isSafeInteger(entry.limits.context) && entry.limits.context > 0 ? entry.limits.context : 400000;
|
|
259
|
+
const reasoning = caps.reasoning !== false;
|
|
260
|
+
listed.push({
|
|
261
|
+
id,
|
|
262
|
+
name: name ?? id,
|
|
263
|
+
reasoning,
|
|
264
|
+
input: caps.image_input === false ? ["text"] : ["text", "image"],
|
|
265
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
266
|
+
contextWindow: context,
|
|
267
|
+
compat: { supportsMaxOutputTokens: false },
|
|
268
|
+
...(reasoning ? { thinkingLevelMap: Object.fromEntries(GATEWAY_EFFORTS.map((level) => [level, level])) } : {}),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (listed.length === 0) return null;
|
|
272
|
+
return [...listed, ...shipped.filter((model) => !listed.some((entry) => entry.id === model.id)).map((model) => ({ ...model }))];
|
|
273
|
+
}
|
|
274
|
+
|
|
208
275
|
/**
|
|
209
276
|
* Prepend `--provider`/`--model` defaults for agent runs, without
|
|
210
277
|
* duplicating flags the user already specified. Consumption rules mirror
|
|
@@ -284,7 +351,7 @@ export function withModelDefaults(args, defaults) {
|
|
|
284
351
|
* `compat.supportsMaxOutputTokens: false` and ships no maxTokens — pi would
|
|
285
352
|
* otherwise clamp a default and break every request.
|
|
286
353
|
*/
|
|
287
|
-
export function modelsConfig({ gatewayUrl } = {}) {
|
|
354
|
+
export function modelsConfig({ gatewayUrl, models = MODELS } = {}) {
|
|
288
355
|
return {
|
|
289
356
|
providers: {
|
|
290
357
|
[DEFAULT_PROVIDER]: {
|
|
@@ -292,7 +359,7 @@ export function modelsConfig({ gatewayUrl } = {}) {
|
|
|
292
359
|
baseUrl: gatewayUrl ?? DEFAULT_GATEWAY_URL,
|
|
293
360
|
api: "openai-responses",
|
|
294
361
|
apiKey: "$OMNIRUSH_TOKEN",
|
|
295
|
-
models:
|
|
362
|
+
models: models.map((model) => ({ ...model })),
|
|
296
363
|
},
|
|
297
364
|
},
|
|
298
365
|
};
|