pi-oracle 0.7.18 → 0.7.20
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/CHANGELOG.md +13 -1
- package/README.md +2 -2
- package/docs/ORACLE_DESIGN.md +2 -2
- package/extensions/oracle/lib/tools.ts +3 -3
- package/extensions/oracle/worker/chatgpt-ui-helpers.mjs +50 -11
- package/extensions/oracle/worker/run-job.mjs +29 -20
- package/package.json +3 -3
- package/scripts/oracle-real-smoke.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.7.20 - 2026-07-28
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- accepted undifferentiated ChatGPT Pro compact menus (bare Pro / Instant 5.5) so pro presets can configure without Standard/Extended rows
|
|
7
|
+
- replaced `\S` tool-schema non-blank patterns with a GBNF-safe character class so llama.cpp-backed OpenAI-compatible servers can compile oracle tool schemas
|
|
8
|
+
|
|
9
|
+
### Validation
|
|
10
|
+
- ran the full `npm run release:check` local gate before release
|
|
11
|
+
|
|
12
|
+
## 0.7.19 - 2026-07-16
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- refreshed the local Pi/pi-ai development lock, sanity contracts, safe-loader version check, and compatibility guidance for Pi 0.80.9; Oracle does not use the removed SDK auth/session options
|
|
4
16
|
|
|
5
17
|
## 0.7.18 - 2026-07-14
|
|
6
18
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`pi-oracle` lets a `pi` agent send hard, long-running work to ChatGPT.com or Grok through the web app, with repo archives, background execution, saved results, and a best-effort wake-up back into `pi` when the answer is ready.
|
|
4
4
|
|
|
5
|
-
> Status: experimental public beta. Current local validation baseline is pi `0.80.
|
|
5
|
+
> Status: experimental public beta. Current local validation baseline is pi `0.80.9`; the platform-smoke harness covers macOS, Linux, and Windows native with Chromium-family browsers. Pi `0.80.9+` is the suggested tested floor for project-trust-aware package/runtime validation, but pi-bundled runtime packages remain optional wildcard peers so npm peer ranges do not block users from trying newer pi releases. Normal oracle jobs run in an isolated browser profile, not your active browser window.
|
|
6
6
|
|
|
7
7
|
## What a successful run looks like
|
|
8
8
|
|
|
@@ -79,7 +79,7 @@ You need:
|
|
|
79
79
|
|
|
80
80
|
- macOS, Linux, or Windows native
|
|
81
81
|
- Node.js 22.19.0 or newer for package install/use; platform smoke/release validation currently expects Node 24+ per `platform-smoke.config.mjs`
|
|
82
|
-
- Suggested tested floor: `pi` 0.80.
|
|
82
|
+
- Suggested tested floor: `pi` 0.80.9 or newer; older pi versions are not blocked by package metadata but are outside the current validation baseline
|
|
83
83
|
- Google Chrome/Chromium or another Chromium-family browser
|
|
84
84
|
- ChatGPT or Grok already signed in to the configured local browser profile for the provider you plan to use
|
|
85
85
|
- `agent-browser` and `tar` available on the machine; `zstd` is also required when submitting ChatGPT `.tar.zst` archives
|
package/docs/ORACLE_DESIGN.md
CHANGED
|
@@ -7,7 +7,7 @@ Companion doc:
|
|
|
7
7
|
- `docs/ORACLE_RECOVERY_DRILL.md` — safe expired-auth recovery validation drill
|
|
8
8
|
|
|
9
9
|
Compatibility target:
|
|
10
|
-
- `pi` 0.80.
|
|
10
|
+
- `pi` 0.80.9+ is the suggested tested floor for current project-trust-aware package/runtime validation
|
|
11
11
|
- package metadata keeps pi runtime packages as optional wildcard peers, so this suggested floor is not enforced as a hard npm install requirement
|
|
12
12
|
- current extension lifecycle only; no backward-compatibility shims for removed `session_switch` / `session_fork` events
|
|
13
13
|
|
|
@@ -662,6 +662,6 @@ Recent proof points:
|
|
|
662
662
|
- expired-auth drill post-repair success: `fa26a2a7-0057-4a21-b3e0-71c1d020facf`
|
|
663
663
|
- successful multi-artifact completion: `b6b3599c-6b91-4315-adfa-8a83aa5eda9b`
|
|
664
664
|
- repo-owned sanity harness: `npm run sanity:oracle`
|
|
665
|
-
- real installed-extension smoke source of truth: `scripts/oracle-real-smoke.mjs`; required release proof runs packed-install mode (`npm run smoke:real:packed`), asserts Pi 0.80.
|
|
665
|
+
- real installed-extension smoke source of truth: `scripts/oracle-real-smoke.mjs`; required release proof runs packed-install mode (`npm run smoke:real:packed`), asserts Pi 0.80.9, and executes `/oracle-status` through Pi's installed-package loader without provider credentials or an external oracle job; optional slower model-agent submission debugging remains behind `PI_ORACLE_REAL_TEST_MODEL_AGENT=1`; source mode (`npm run smoke:real:source`) is inner-loop/debug only
|
|
666
666
|
- macOS, Ubuntu, and Windows native package/build/runtime smoke source of truth: `docs/platform-smoke.md`; use `npm run verify:oracle` for everyday local iteration, `npm run smoke:platform:doctor` plus a focused target/suite run for platform-sensitive changes, `npm run smoke:platform:all` for doctor-first platform matrix evidence, and `npm run release:check` for the full local-plus-platform release gate
|
|
667
667
|
- release gate: `npm run release:check`, also used by `prepublishOnly`, combines static verification, fresh loaded-extension ChatGPT preset proof via `npm run release:proof:chatgpt-presets`, and all required Crabbox platform smokes
|
|
@@ -81,7 +81,7 @@ const ORACLE_SUBMIT_PARAMS = Type.Object({
|
|
|
81
81
|
files: Type.Array(Type.String({
|
|
82
82
|
description: "Project-relative file or directory path to include in the archive.",
|
|
83
83
|
minLength: 1,
|
|
84
|
-
pattern: "
|
|
84
|
+
pattern: "^.*[^ \\t\\r\\n].*$",
|
|
85
85
|
}), {
|
|
86
86
|
description: "Exact project-relative files/directories to include in the oracle archive.",
|
|
87
87
|
minItems: 1,
|
|
@@ -99,7 +99,7 @@ const ORACLE_SUBMIT_PARAMS = Type.Object({
|
|
|
99
99
|
chatGptConversationId: Type.Optional(Type.String({
|
|
100
100
|
description: "Existing ChatGPT conversation id, or full https://chatgpt.com/c/... URL, to continue. Omit for default behavior: starting a fresh oracle thread. Do not combine with followUpJobId.",
|
|
101
101
|
minLength: 1,
|
|
102
|
-
pattern: "
|
|
102
|
+
pattern: "^.*[^ \\t\\r\\n].*$",
|
|
103
103
|
})),
|
|
104
104
|
}, { additionalProperties: false });
|
|
105
105
|
|
|
@@ -109,7 +109,7 @@ const ORACLE_PREFLIGHT_PARAMS = Type.Object({
|
|
|
109
109
|
chatGptConversationId: Type.Optional(Type.String({
|
|
110
110
|
description: "Existing ChatGPT conversation id, or full https://chatgpt.com/c/... URL, whose provider/thread readiness should be checked. Do not combine with followUpJobId.",
|
|
111
111
|
minLength: 1,
|
|
112
|
-
pattern: "
|
|
112
|
+
pattern: "^.*[^ \\t\\r\\n].*$",
|
|
113
113
|
})),
|
|
114
114
|
}, { additionalProperties: false });
|
|
115
115
|
|
|
@@ -29,9 +29,10 @@ const AUTO_SWITCH_LABEL = "Auto-switch to Thinking";
|
|
|
29
29
|
const THINKING_EFFORT_COMBOBOX_LABEL = "Thinking effort";
|
|
30
30
|
const PRO_THINKING_EFFORT_COMBOBOX_LABEL = "Pro thinking effort";
|
|
31
31
|
const EFFORT_LABELS = new Set(["Light", "Standard", "Extended", "Heavy"]);
|
|
32
|
-
const COMPACT_INTELLIGENCE_MENU_PATTERN = /(?:Intelligence.*Instant.*Medium.*High.*Pro|^(?:Instant|Medium|High|Extra High|Pro Standard|
|
|
33
|
-
|
|
34
|
-
const
|
|
32
|
+
const COMPACT_INTELLIGENCE_MENU_PATTERN = /(?:Intelligence.*Instant.*Medium.*High.*Pro|^(?:Instant|Medium|High|Extra High|Pro(?: Standard| Extended)?)$)/i;
|
|
33
|
+
// Bare Instant is the legacy top-level family radio; compact Instant rows are versioned (Instant 5s / Instant 5.5).
|
|
34
|
+
const COMPACT_INTELLIGENCE_CONTROL_PATTERN = /^(?:Instant\s+[\d.]+s?|Medium(?:\s+5\s*[–-]\s*30s)?|High(?:\s+15\s*[–-]\s*60s)?|Extra High|Pro(?:\s+5\+\s*min|\s+Standard|\s+Extended)?)$/i;
|
|
35
|
+
const COMPACT_INTELLIGENCE_OPENER_PATTERN = /^(?:Instant(?:\s+[\d.]+s?)?|Medium|High|Extra High|Pro(?: Standard| Extended)?)$/i;
|
|
35
36
|
const BARE_EFFORT_PATTERN = /^(light|standard|extended|heavy)(?:, click to remove)?$/i;
|
|
36
37
|
const INSTANT_CHIP_PATTERN = /^instant(?:, click to remove)?$/i;
|
|
37
38
|
const THINKING_CHIP_PATTERN = /^(?:(light|standard|extended|heavy)\s+)?thinking(?:, click to remove)?$/i;
|
|
@@ -184,7 +185,7 @@ function parseCompactIntelligenceSelection(label) {
|
|
|
184
185
|
const normalized = normalizeChipLabel(label);
|
|
185
186
|
if (!COMPACT_INTELLIGENCE_CONTROL_PATTERN.test(normalized)) return undefined;
|
|
186
187
|
|
|
187
|
-
if (/^Instant
|
|
188
|
+
if (/^Instant\s+[\d.]+s?$/i.test(normalized)) {
|
|
188
189
|
return {
|
|
189
190
|
modelFamily: /** @type {OracleUiModelFamily} */ ("instant"),
|
|
190
191
|
compactTier: "instant",
|
|
@@ -219,6 +220,8 @@ function parseCompactIntelligenceSelection(label) {
|
|
|
219
220
|
compactTier: "pro",
|
|
220
221
|
};
|
|
221
222
|
}
|
|
223
|
+
// "Pro 5+ min" is always the compact Pro tier. Bare "Pro" is ambiguous with the
|
|
224
|
+
// legacy top-level family radio and is handled with sibling context below.
|
|
222
225
|
if (/^Pro\s+5\+\s*min$/i.test(normalized)) {
|
|
223
226
|
return {
|
|
224
227
|
modelFamily: /** @type {OracleUiModelFamily} */ ("pro"),
|
|
@@ -229,6 +232,24 @@ function parseCompactIntelligenceSelection(label) {
|
|
|
229
232
|
return undefined;
|
|
230
233
|
}
|
|
231
234
|
|
|
235
|
+
function parseBareProCompactSelection(label) {
|
|
236
|
+
if (/click to remove/i.test(String(label || ""))) return undefined;
|
|
237
|
+
if (!/^Pro$/i.test(normalizeChipLabel(label))) return undefined;
|
|
238
|
+
return {
|
|
239
|
+
modelFamily: /** @type {OracleUiModelFamily} */ ("pro"),
|
|
240
|
+
compactTier: "pro",
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function snapshotHasCompactTierSiblings(entries, exceptLabel) {
|
|
245
|
+
const except = normalizeChipLabel(exceptLabel).toLowerCase();
|
|
246
|
+
return entries.some((entry) => {
|
|
247
|
+
if (entry.disabled || entry.kind !== "menuitemradio") return false;
|
|
248
|
+
if (normalizeChipLabel(entry.label).toLowerCase() === except) return false;
|
|
249
|
+
return Boolean(parseCompactIntelligenceSelection(entry.label));
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
232
253
|
function hasRemovableComposerModelChip(entries) {
|
|
233
254
|
return entries.some(
|
|
234
255
|
(entry) => entry.kind === "button" && /click to remove/i.test(String(entry.label || "")) && parseComposerChipSelection(entry.label),
|
|
@@ -237,7 +258,7 @@ function hasRemovableComposerModelChip(entries) {
|
|
|
237
258
|
|
|
238
259
|
function hasCompactIntelligenceMenuContext(entries) {
|
|
239
260
|
return entries.some((entry) => !entry.disabled && entry.kind === "menu" && COMPACT_INTELLIGENCE_MENU_PATTERN.test(normalizeText(entry.label)))
|
|
240
|
-
|| entries.some((entry) => !entry.disabled && entry.kind === "menuitemradio" && checkedState(entry) === true &&
|
|
261
|
+
|| entries.some((entry) => !entry.disabled && entry.kind === "menuitemradio" && checkedState(entry) === true && compactSelectionFromEntry(entry, entries));
|
|
241
262
|
}
|
|
242
263
|
|
|
243
264
|
function hasLegacyEffortCombobox(entries) {
|
|
@@ -248,18 +269,36 @@ function hasLegacyEffortCombobox(entries) {
|
|
|
248
269
|
});
|
|
249
270
|
}
|
|
250
271
|
|
|
251
|
-
function compactSelectionFromEntry(entry,
|
|
272
|
+
function compactSelectionFromEntry(entry, entries = [], options = {}) {
|
|
252
273
|
if (entry.disabled) return undefined;
|
|
253
274
|
const kind = entry.kind || "";
|
|
254
|
-
if (COMPACT_INTELLIGENCE_CONTROL_KINDS.has(kind))
|
|
275
|
+
if (COMPACT_INTELLIGENCE_CONTROL_KINDS.has(kind)) {
|
|
276
|
+
const parsed = parseCompactIntelligenceSelection(entry.label);
|
|
277
|
+
if (parsed) return parsed;
|
|
278
|
+
// Bare "Pro" is compact only when versioned Instant / Medium / High / Extra High siblings exist.
|
|
279
|
+
if (snapshotHasCompactTierSiblings(entries, entry.label)) {
|
|
280
|
+
return parseBareProCompactSelection(entry.label);
|
|
281
|
+
}
|
|
282
|
+
return undefined;
|
|
283
|
+
}
|
|
255
284
|
if (options.allowClosedButtons && kind === "button" && !/\bexpanded=true\b/.test(String(entry.line || ""))) {
|
|
256
|
-
|
|
285
|
+
const parsed = parseCompactIntelligenceSelection(entry.label);
|
|
286
|
+
if (parsed) return parsed;
|
|
287
|
+
const barePro = parseBareProCompactSelection(entry.label);
|
|
288
|
+
if (barePro) return barePro;
|
|
289
|
+
// Closed composer pills keep bare Instant after the compact menu closes.
|
|
290
|
+
if (/^Instant$/i.test(normalizeChipLabel(entry.label))) {
|
|
291
|
+
return {
|
|
292
|
+
modelFamily: /** @type {OracleUiModelFamily} */ ("instant"),
|
|
293
|
+
compactTier: "instant",
|
|
294
|
+
};
|
|
295
|
+
}
|
|
257
296
|
}
|
|
258
297
|
return undefined;
|
|
259
298
|
}
|
|
260
299
|
|
|
261
300
|
export function matchesCompactIntelligenceControlLabel(label) {
|
|
262
|
-
return Boolean(parseCompactIntelligenceSelection(label));
|
|
301
|
+
return Boolean(parseCompactIntelligenceSelection(label) || parseBareProCompactSelection(label));
|
|
263
302
|
}
|
|
264
303
|
|
|
265
304
|
export function snapshotHasClosedCompactSelection(snapshot, selection) {
|
|
@@ -330,7 +369,7 @@ function detectCompactIntelligenceSelection(entries) {
|
|
|
330
369
|
}
|
|
331
370
|
|
|
332
371
|
export function matchesRequestedModelControlLabel(label, selection) {
|
|
333
|
-
const compactSelection = parseCompactIntelligenceSelection(label);
|
|
372
|
+
const compactSelection = parseCompactIntelligenceSelection(label) || parseBareProCompactSelection(label);
|
|
334
373
|
if (compactSelection) return compactSelectionMatchesRequested(selection, compactSelection);
|
|
335
374
|
return matchesModelFamilyLabel(label, selection.modelFamily);
|
|
336
375
|
}
|
|
@@ -455,7 +494,7 @@ export function snapshotHasModelConfigurationUi(snapshot) {
|
|
|
455
494
|
),
|
|
456
495
|
);
|
|
457
496
|
const visibleCompactControls = entries.filter(
|
|
458
|
-
(entry) => !entry.disabled && entry.kind === "menuitemradio" &&
|
|
497
|
+
(entry) => !entry.disabled && entry.kind === "menuitemradio" && compactSelectionFromEntry(entry, entries),
|
|
459
498
|
);
|
|
460
499
|
const hasCompactIntelligenceMenu = entries.some(
|
|
461
500
|
(entry) => !entry.disabled && entry.kind === "menu" && COMPACT_INTELLIGENCE_MENU_PATTERN.test(normalizeText(entry.label)),
|
|
@@ -895,8 +895,8 @@ function snapshotHasCompactIntelligenceMenuControls(snapshot) {
|
|
|
895
895
|
return Boolean(findEntry(snapshot, (candidate) => {
|
|
896
896
|
if (candidate.disabled) return false;
|
|
897
897
|
const label = normalizeSnapshotLabel(candidate.label);
|
|
898
|
-
return (candidate.kind === "menu" && /(?:Intelligence.*Instant.*Medium.*High.*Pro|^(?:Instant|Medium|High|Extra High|Pro Extended)$)/i.test(label))
|
|
899
|
-
|| (candidate.kind === "menuitemradio" && /^(?:Instant
|
|
898
|
+
return (candidate.kind === "menu" && /(?:Intelligence.*Instant.*Medium.*High.*Pro|^(?:Instant|Medium|High|Extra High|Pro(?: Standard| Extended)?)$)/i.test(label))
|
|
899
|
+
|| (candidate.kind === "menuitemradio" && /^(?:Instant\s+[\d.]+s?|Medium(?:\s+5\s*[–-]\s*30s)?|High(?:\s+15\s*[–-]\s*60s)?|Extra High|Pro(?:\s+5\+\s*min|\s+Standard|\s+Extended)?)$/i.test(label));
|
|
900
900
|
}));
|
|
901
901
|
}
|
|
902
902
|
|
|
@@ -904,7 +904,7 @@ function matchesRequestedModelControl(candidate, selection, options = {}) {
|
|
|
904
904
|
if (!["button", "radio", "menuitemradio"].includes(candidate.kind || "") || typeof candidate.label !== "string" || candidate.disabled) return false;
|
|
905
905
|
if (candidate.kind === "button") {
|
|
906
906
|
if (/\bexpanded=true\b/.test(String(candidate.line || ""))) return false;
|
|
907
|
-
if (options.ignoreCompactTierButtons && /^(?:Instant
|
|
907
|
+
if (options.ignoreCompactTierButtons && /^(?:Instant(?:\s+[\d.]+s?)?|Medium|High|Extra High|Pro(?: Standard| Extended)?)$/i.test(candidate.label)) return false;
|
|
908
908
|
if (options.ignoreCompactOnlyButtons && /^(?:Medium|High|Extra High)$/i.test(candidate.label)) return false;
|
|
909
909
|
}
|
|
910
910
|
if (selection.modelFamily === "pro" && /^Pro(?:\s+Extended)?$/i.test(candidate.label)) return true;
|
|
@@ -1582,25 +1582,34 @@ async function configureModel(job) {
|
|
|
1582
1582
|
if (effortLabel && !effortSelectionVisible(familySnapshot, effortLabel)) {
|
|
1583
1583
|
const opened = await openEffortDropdown(job);
|
|
1584
1584
|
if (!opened) {
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1585
|
+
// Current ChatGPT Pro menus sometimes expose only undifferentiated "Pro" with no Standard/Extended rows.
|
|
1586
|
+
const afterOpenAttempt = await snapshotText(job);
|
|
1587
|
+
if (job.selection.modelFamily === "pro" && snapshotStronglyMatchesRequestedModel(afterOpenAttempt, job.selection)) {
|
|
1588
|
+
await log(`Pro effort dropdown unavailable for ${effortLabel}; accepting undifferentiated Pro selection`);
|
|
1589
|
+
verificationSnapshot = afterOpenAttempt;
|
|
1590
|
+
familySnapshot = afterOpenAttempt;
|
|
1591
|
+
} else {
|
|
1592
|
+
throw new Error(`Could not open effort dropdown for requested effort: ${effortLabel}`);
|
|
1593
|
+
}
|
|
1590
1594
|
} else {
|
|
1591
|
-
await
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1595
|
+
await agentBrowser(job, "wait", "300");
|
|
1596
|
+
if (job.selection.modelFamily === "pro" && await maybeClickLabeledEntry(job, `Pro ${effortLabel}`, { kind: "menuitemradio" })) {
|
|
1597
|
+
// Current ChatGPT exposes Pro effort choices as nested menu radio items.
|
|
1598
|
+
} else {
|
|
1599
|
+
await clickLabeledEntry(job, effortLabel, { kind: "option" });
|
|
1600
|
+
}
|
|
1601
|
+
await agentBrowser(job, "wait", "400");
|
|
1602
|
+
const effortSnapshot = await snapshotText(job);
|
|
1603
|
+
verificationSnapshot = effortSnapshot;
|
|
1604
|
+
const selectedEffort = findEntry(
|
|
1605
|
+
effortSnapshot,
|
|
1606
|
+
(candidate) => candidate.kind === "combobox" && candidate.value === effortLabel && !candidate.disabled,
|
|
1607
|
+
);
|
|
1608
|
+
if (!selectedEffort && !effortSelectionVisible(effortSnapshot, effortLabel)) {
|
|
1609
|
+
throw new Error(`Requested effort did not remain selected: ${effortLabel}`);
|
|
1610
|
+
}
|
|
1611
|
+
familySnapshot = effortSnapshot;
|
|
1602
1612
|
}
|
|
1603
|
-
familySnapshot = effortSnapshot;
|
|
1604
1613
|
}
|
|
1605
1614
|
}
|
|
1606
1615
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-oracle",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.20",
|
|
4
4
|
"description": "ChatGPT and Grok web-oracle extension for pi with isolated browser auth, async jobs, and project-context archives.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
"protobufjs": "7.6.1"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
|
-
"@earendil-works/pi-ai": "^0.80.
|
|
91
|
-
"@earendil-works/pi-coding-agent": "^0.80.
|
|
90
|
+
"@earendil-works/pi-ai": "^0.80.9",
|
|
91
|
+
"@earendil-works/pi-coding-agent": "^0.80.9",
|
|
92
92
|
"@types/node": "^22.19.19",
|
|
93
93
|
"esbuild": "^0.28.0",
|
|
94
94
|
"tsx": "^4.22.3",
|
|
@@ -11,7 +11,7 @@ import { basename, dirname, join, resolve } from "node:path";
|
|
|
11
11
|
const DEFAULT_PROVIDER = "zai";
|
|
12
12
|
const DEFAULT_MODEL = "glm-5.2";
|
|
13
13
|
const DEFAULT_TIMEOUT_MS = 180_000;
|
|
14
|
-
const EXPECTED_PI_VERSION = "0.80.
|
|
14
|
+
const EXPECTED_PI_VERSION = "0.80.9";
|
|
15
15
|
const PACKAGE_NAME = "pi-oracle";
|
|
16
16
|
|
|
17
17
|
function usage() {
|