pi-oracle 0.7.6 → 0.7.7

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 CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.7.7 - 2026-06-08
6
+
7
+ ### Changed
8
+ - updated the local pi development baseline to `@earendil-works/pi-coding-agent` / `@earendil-works/pi-ai` `0.79.0` and regenerated the npm lockfile
9
+ - documented `pi` `0.79.0+` as the suggested tested floor while keeping pi runtime packages as optional wildcard peers so npm peer ranges do not block users from trying newer pi releases
10
+ - updated isolated local-extension and packed package validation workflows to pass explicit `--approve` when they intentionally trust their temporary project fixtures under Pi 0.79.0 project-trust rules
11
+
12
+ ### Fixed
13
+ - made project-local `.pi/extensions/oracle.json` overrides honor explicit Pi project-trust opt-outs (`--no-approve` or a saved “do not trust” decision) while preserving the historical default of loading safe project overrides for existing oracle users
14
+
15
+ ### Compatibility
16
+ - reviewed the pi `0.79.0` changelog, project-trust docs, extension docs, package docs, prompt-template docs, SDK/RPC exports, and matching examples; the oracle extension remains compatible with current extension lifecycle and package install/update behavior
17
+
5
18
  ## 0.7.6 - 2026-06-04
6
19
 
7
20
  ### Changed
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. Validated on macOS, Linux, and Windows native with Chromium-family browsers and pi `0.78.1`. Pi `0.78.1+` is the suggested tested floor for mode-aware background polling, 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.
5
+ > Status: experimental public beta. Validated on macOS, Linux, and Windows native with Chromium-family browsers and pi `0.79.0`. Pi `0.79.0+` 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
 
@@ -77,7 +77,7 @@ You need:
77
77
 
78
78
  - macOS, Linux, or Windows native
79
79
  - Node.js 22 or newer
80
- - Suggested tested floor: `pi` 0.78.1 or newer; older pi versions are not blocked by package metadata but are outside the current validation baseline
80
+ - Suggested tested floor: `pi` 0.79.0 or newer; older pi versions are not blocked by package metadata but are outside the current validation baseline
81
81
  - Google Chrome/Chromium or another Chromium-family browser
82
82
  - ChatGPT or Grok already signed in to the configured local browser profile for the provider you plan to use
83
83
  - `agent-browser`, `tar`, and `zstd` available on the machine
@@ -179,6 +179,8 @@ Agent-facing tools:
179
179
 
180
180
  Most users can start with defaults. Set an agent-level config only when you need a non-default provider, mode, preset, or browser profile.
181
181
 
182
+ Pi 0.79.0 gates project-local inputs behind project trust. `pi-oracle` preserves its historical risk-on extension behavior for existing users: project-local `.pi/extensions/oracle.json` safe overrides still load by default for compatibility. They are ignored when you explicitly opt out of project-local inputs with `--no-approve` or save a “do not trust” decision for the project. Privileged browser/auth settings still come only from the agent-level config.
183
+
182
184
  `~/.pi/agent/extensions/oracle.json`
183
185
 
184
186
  ```json
@@ -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.78.1+ is the suggested tested floor for current mode-aware poller behavior
10
+ - `pi` 0.79.0+ 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
 
@@ -229,9 +229,7 @@ Merged config locations:
229
229
  - global: `~/.pi/agent/extensions/oracle.json`
230
230
  - project: `.pi/extensions/oracle.json`
231
231
 
232
- Project config remains restricted to safe overrides only.
233
-
234
- Browser/auth settings are global-only because they control local privileged browser state.
232
+ Project config remains restricted to safe overrides only. On Pi 0.79.0+, pi itself gates project-local inputs behind project trust, but `pi-oracle` keeps its historical risk-on extension behavior for this package-specific safe override file: `.pi/extensions/oracle.json` loads by default for compatibility, and is ignored only when the run passes `--no-approve` or the project has a saved “do not trust” decision. This preserves the existing extension experience while still honoring explicit opt-out/distrust decisions. Browser/auth settings remain global-only because they control local privileged browser state.
235
233
 
236
234
  ### Current config shape
237
235
 
@@ -633,6 +631,10 @@ Remaining non-blocking hardening work:
633
631
  - keep hardening model-selection verification against future ChatGPT UI variation
634
632
 
635
633
  Recent proof points:
634
+ - Pi 0.79.0 release gate: `npm run release:check` passed on 2026-06-08, including `verify:oracle` plus Crabbox macOS, Ubuntu, and Windows native `platform-build` and `real-extension` suites
635
+ - Pi 0.79.0 platform artifacts: `.artifacts/platform-smoke/run-1780938522145-50q2f2` (macOS platform-build), `.artifacts/platform-smoke/run-1780938572090-bi87g5` (macOS real-extension), `.artifacts/platform-smoke/run-1780938542847-quridb` (Ubuntu platform-build), `.artifacts/platform-smoke/run-1780938587248-c8uo4c` (Ubuntu real-extension), `.artifacts/platform-smoke/run-1780938585007-l0xapp` (Windows native platform-build), `.artifacts/platform-smoke/run-1780938820527-c1j8tt` (Windows native real-extension)
636
+ - Pi 0.79.0 isolated local-extension model-agent smoke: `.artifacts/real-smoke/run-1780935835596-pfbn5o` passed with `PI_ORACLE_REAL_TEST_MODEL_AGENT=1 npm run smoke:real:source`
637
+ - Pi 0.79.0 packed-install smoke: `.artifacts/real-smoke/run-1780935825537-pmna07` passed with `npm run smoke:real:packed`
636
638
  - expired-auth drill fail path: `a2460bc1-7d89-4041-b67d-39680d310325`
637
639
  - `/oracle-auth` repair evidence: the per-run `/tmp/pi-oracle-auth-*/oracle-auth.log` bundle path printed by `/oracle-auth`
638
640
  - expired-auth drill post-repair success: `fa26a2a7-0057-4a21-b3e0-71c1d020facf`
@@ -24,15 +24,15 @@ That keeps the validation run from reusing your normal `pi` agent state.
24
24
  The extension is loaded from the local checkout with:
25
25
 
26
26
  ```bash
27
- pi --no-extensions -e "$REPO/extensions/oracle/index.ts"
27
+ pi --approve --no-extensions -e "$REPO/extensions/oracle/index.ts"
28
28
  ```
29
29
 
30
- That ensures the session is exercising the in-repo code, not a globally installed package.
30
+ That ensures the session is exercising the in-repo code, not a globally installed package. `--approve` is intentional for this isolated workflow on Pi 0.79.0+: the test fixture is this trusted checkout, and non-interactive/scripted validation must not block on the project-trust prompt.
31
31
 
32
32
  If you also need the in-repo `/oracle` prompt template, load it explicitly instead of installing this repository as a project-local package:
33
33
 
34
34
  ```bash
35
- pi --no-extensions -e "$REPO/extensions/oracle/index.ts" \
35
+ pi --approve --no-extensions -e "$REPO/extensions/oracle/index.ts" \
36
36
  --no-prompt-templates --prompt-template "$REPO/prompts/oracle.md"
37
37
  ```
38
38
 
@@ -96,7 +96,7 @@ cleanup() {
96
96
  trap cleanup EXIT
97
97
  cleanup
98
98
 
99
- TMUX_CMD1="cd '$REPO' && env PI_CODING_AGENT_DIR='$TEST1_AGENT' PI_ORACLE_JOBS_DIR='$TEST1_JOBS' PATH='$PATH' pi --session-dir '$TEST1_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
99
+ TMUX_CMD1="cd '$REPO' && env PI_CODING_AGENT_DIR='$TEST1_AGENT' PI_ORACLE_JOBS_DIR='$TEST1_JOBS' PATH='$PATH' pi --approve --session-dir '$TEST1_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
100
100
  tmux new-session -d -s "$SESSION1" "$TMUX_CMD1"
101
101
  sleep 8
102
102
  tmux send-keys -t "$SESSION1":0.0 "$PROMPT1" Enter
@@ -129,7 +129,7 @@ PY
129
129
  rm -f "$LIST"
130
130
  fi
131
131
 
132
- TMUX_CMD2="cd '$FIXTURE' && env PI_CODING_AGENT_DIR='$TEST2_AGENT' PI_ORACLE_JOBS_DIR='$TEST2_JOBS' PATH='$PATH' pi --session-dir '$TEST2_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
132
+ TMUX_CMD2="cd '$FIXTURE' && env PI_CODING_AGENT_DIR='$TEST2_AGENT' PI_ORACLE_JOBS_DIR='$TEST2_JOBS' PATH='$PATH' pi --approve --session-dir '$TEST2_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
133
133
  tmux new-session -d -s "$SESSION2" "$TMUX_CMD2"
134
134
  sleep 8
135
135
  tmux send-keys -t "$SESSION2":0.0 "$PROMPT2" Enter
@@ -178,7 +178,7 @@ Expected behavior:
178
178
  The main smoke test above calls `oracle_submit` directly, so it only needs the local extension entrypoint. If you also changed `prompts/oracle.md`, start the isolated session with the local prompt template explicitly loaded:
179
179
 
180
180
  ```bash
181
- LOCAL_ORACLE_PI_CMD="pi --session-dir '$TEST1_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts' --no-prompt-templates --prompt-template '$REPO/prompts/oracle.md'"
181
+ LOCAL_ORACLE_PI_CMD="pi --approve --session-dir '$TEST1_SESSIONS' --no-extensions -e '$REPO/extensions/oracle/index.ts' --no-prompt-templates --prompt-template '$REPO/prompts/oracle.md'"
182
182
  TMUX_CMD1="cd '$REPO' && env PI_CODING_AGENT_DIR='$TEST1_AGENT' PI_ORACLE_JOBS_DIR='$TEST1_JOBS' PATH='$PATH' $LOCAL_ORACLE_PI_CMD"
183
183
  ```
184
184
 
@@ -226,7 +226,7 @@ cleanup() {
226
226
  trap 'cleanup; rm -rf "$TEST_ROOT"' EXIT
227
227
  cleanup
228
228
 
229
- TMUX_CMD="cd '$REPO' && env PI_CODING_AGENT_DIR='$AGENT_DIR' PI_ORACLE_JOBS_DIR='$JOBS_DIR' AGENT_BROWSER_PATH='$FAKE_BROWSER' PI_ORACLE_AUTH_AGENT_BROWSER_TIMEOUT_MS='250' PI_ORACLE_AUTH_CLOSE_TIMEOUT_MS='250' PI_ORACLE_AUTH_KILL_GRACE_MS='100' PATH='$PATH' pi --session-dir '$SESSION_DIR' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
229
+ TMUX_CMD="cd '$REPO' && env PI_CODING_AGENT_DIR='$AGENT_DIR' PI_ORACLE_JOBS_DIR='$JOBS_DIR' AGENT_BROWSER_PATH='$FAKE_BROWSER' PI_ORACLE_AUTH_AGENT_BROWSER_TIMEOUT_MS='250' PI_ORACLE_AUTH_CLOSE_TIMEOUT_MS='250' PI_ORACLE_AUTH_KILL_GRACE_MS='100' PATH='$PATH' pi --approve --session-dir '$SESSION_DIR' --no-extensions -e '$REPO/extensions/oracle/index.ts'"
230
230
 
231
231
  tmux new-session -d -s "$SESSION_NAME" "$TMUX_CMD"
232
232
  sleep 8
@@ -90,8 +90,8 @@ On each required target, `platform-build`:
90
90
  5. runs `npm pack`;
91
91
  6. creates a fresh target-local pi project;
92
92
  7. runs `npm install --no-save <packed tarball>`;
93
- 8. runs `pi install -l ./node_modules/pi-oracle`;
94
- 9. runs `pi list`;
93
+ 8. runs `pi install -l ./node_modules/pi-oracle --approve` so Pi 0.79.0 project-trust gating intentionally trusts the temporary fixture;
94
+ 9. runs `pi list --approve`;
95
95
  10. asserts the installed package came from `node_modules/pi-oracle` and did not use `pi -e` / source-extension shortcuts.
96
96
 
97
97
  ## What `real-extension` proves
@@ -100,8 +100,8 @@ On each required target, `platform-build`:
100
100
 
101
101
  1. packs this checkout with `npm pack`;
102
102
  2. installs the tarball into a clean pi project;
103
- 3. runs `pi install -l ./node_modules/pi-oracle`;
104
- 4. asserts `pi list` shows the packed install path;
103
+ 3. runs `pi install -l ./node_modules/pi-oracle --approve`;
104
+ 4. asserts `pi list --approve` shows the packed install path;
105
105
  5. executes `oracle_submit` from the installed package path, not source `pi -e`;
106
106
  6. asserts whole-project archive creation and default exclusions.
107
107
 
@@ -113,7 +113,7 @@ For inner-loop/debug only, use:
113
113
  npm run smoke:real:source
114
114
  ```
115
115
 
116
- That source-mode smoke loads `extensions/oracle/index.ts` with `pi --no-extensions -e`; it is useful while developing but is not release proof.
116
+ That source-mode smoke loads `extensions/oracle/index.ts` with `pi --approve --no-extensions -e`; it is useful while developing but is not release proof.
117
117
 
118
118
  ## Artifacts
119
119
 
@@ -6,7 +6,7 @@
6
6
  import { execFileSync } from "node:child_process";
7
7
  import { existsSync, readFileSync } from "node:fs";
8
8
  import { homedir } from "node:os";
9
- import { getAgentDir } from "@earendil-works/pi-coding-agent";
9
+ import { getAgentDir, hasProjectTrustInputs, ProjectTrustStore } from "@earendil-works/pi-coding-agent";
10
10
  import { isAbsolute, join, normalize } from "node:path";
11
11
  import {
12
12
  assertNotKnownBrowserUserDataPath,
@@ -313,27 +313,76 @@ const detectedChromeUserAgent = detectDefaultChromeUserAgent(detectedChromeExecu
313
313
  const agentExtensionsDir = join(getAgentDir(), "extensions");
314
314
  const detectedChromeProfileName = detectDefaultBrowserProfileSource(process.platform);
315
315
 
316
+ export interface OracleConfigLoadOptions {
317
+ /**
318
+ * Whether project-local oracle config may be loaded. Omit for the runtime
319
+ * policy that preserves oracle's historical project-config behavior while
320
+ * respecting explicit --no-approve and saved distrust decisions.
321
+ */
322
+ projectConfigTrusted?: boolean;
323
+ /** Session cwd used for Pi's saved project-trust decision when config lookup is anchored to a derived project root. */
324
+ projectConfigTrustCwd?: string;
325
+ }
326
+
316
327
  export interface OracleConfigLoadDetails {
317
328
  agentDir: string;
318
329
  agentConfigPath: string;
319
330
  agentConfigExists: boolean;
320
331
  projectConfigPath: string;
321
332
  projectConfigExists: boolean;
333
+ projectConfigTrusted: boolean;
334
+ projectConfigLoaded: boolean;
335
+ projectConfigSkippedReason?: string;
322
336
  effectiveAuthConfigPath: string;
323
337
  effectiveAuthScope: "agent";
324
338
  }
325
339
 
326
- export function getOracleConfigLoadDetails(cwd: string): OracleConfigLoadDetails {
340
+ function getProjectTrustCliOverride(argv = process.argv): boolean | undefined {
341
+ let trusted: boolean | undefined;
342
+ for (const arg of argv.slice(2)) {
343
+ if (arg === "--approve" || arg === "-a") trusted = true;
344
+ if (arg === "--no-approve" || arg === "-na") trusted = false;
345
+ }
346
+ return trusted;
347
+ }
348
+
349
+ function isProjectConfigTrusted(cwd: string, agentDir: string, projectConfigExists: boolean, options?: OracleConfigLoadOptions): boolean {
350
+ if (options?.projectConfigTrusted !== undefined) return options.projectConfigTrusted;
351
+ const trustCwd = options?.projectConfigTrustCwd ?? cwd;
352
+ const cliOverride = getProjectTrustCliOverride();
353
+ if (cliOverride !== undefined) return cliOverride;
354
+ if (!projectConfigExists && !hasProjectTrustInputs(trustCwd)) return true;
355
+ try {
356
+ const trustStore = new ProjectTrustStore(agentDir);
357
+ const trustDecision = trustStore.get(trustCwd);
358
+ const rootDecision = trustCwd !== cwd ? trustStore.get(cwd) : null;
359
+ if (trustDecision !== null) return trustDecision;
360
+ if (rootDecision !== null) return rootDecision;
361
+ } catch {
362
+ return false;
363
+ }
364
+ return true;
365
+ }
366
+
367
+ export function getOracleConfigLoadDetails(cwd: string, options?: OracleConfigLoadOptions): OracleConfigLoadDetails {
327
368
  const agentDir = getAgentDir();
328
369
  const projectRoot = getProjectId(cwd);
329
370
  const agentConfigPath = join(agentDir, "extensions", "oracle.json");
330
371
  const projectConfigPath = join(projectRoot, ".pi", "extensions", "oracle.json");
372
+ const projectConfigExists = existsSync(projectConfigPath);
373
+ const projectConfigTrusted = isProjectConfigTrusted(projectRoot, agentDir, projectConfigExists, options);
374
+ const projectConfigLoaded = projectConfigExists && projectConfigTrusted;
331
375
  return {
332
376
  agentDir,
333
377
  agentConfigPath,
334
378
  agentConfigExists: existsSync(agentConfigPath),
335
379
  projectConfigPath,
336
- projectConfigExists: existsSync(projectConfigPath),
380
+ projectConfigExists,
381
+ projectConfigTrusted,
382
+ projectConfigLoaded,
383
+ projectConfigSkippedReason: projectConfigExists && !projectConfigTrusted
384
+ ? "Project oracle config is ignored because this run used --no-approve or the project has a saved untrusted decision."
385
+ : undefined,
337
386
  effectiveAuthConfigPath: agentConfigPath,
338
387
  effectiveAuthScope: "agent",
339
388
  };
@@ -341,8 +390,11 @@ export function getOracleConfigLoadDetails(cwd: string): OracleConfigLoadDetails
341
390
 
342
391
  export function formatOracleAuthConfigRemediation(details: OracleConfigLoadDetails): string {
343
392
  const authFields = "auth.chromeProfile / auth.chromeCookiePath / auth.chromiumKeychain";
344
- if (!details.projectConfigExists) {
345
- return `Set ${authFields} in ${details.effectiveAuthConfigPath}.`;
393
+ if (!details.projectConfigLoaded) {
394
+ const projectNote = details.projectConfigSkippedReason
395
+ ? ` Project config at ${details.projectConfigPath} is present but not loaded because this run explicitly does not trust project-local inputs.`
396
+ : "";
397
+ return `Set ${authFields} in ${details.effectiveAuthConfigPath}.${projectNote}`;
346
398
  }
347
399
  return (
348
400
  `Set ${authFields} in ${details.effectiveAuthConfigPath}. ` +
@@ -354,11 +406,13 @@ export function formatOracleAuthConfigSummary(details: OracleConfigLoadDetails):
354
406
  const lines = [
355
407
  `Effective oracle auth config: ${details.effectiveAuthConfigPath} (agent dir: ${details.agentDir}${details.agentConfigExists ? "" : "; create this file to override auth.*"})`,
356
408
  ];
357
- if (details.projectConfigExists) {
409
+ if (details.projectConfigLoaded) {
358
410
  lines.push(
359
411
  `Project oracle config also loaded: ${details.projectConfigPath} ` +
360
412
  `(project scope can override ${[...PROJECT_OVERRIDE_KEYS].join("/")} only; auth.* still comes from ${details.effectiveAuthConfigPath}).`,
361
413
  );
414
+ } else if (details.projectConfigSkippedReason) {
415
+ lines.push(`Project oracle config present but not loaded: ${details.projectConfigPath}. ${details.projectConfigSkippedReason}`);
362
416
  }
363
417
  return lines.join("\n");
364
418
  }
@@ -665,9 +719,9 @@ function validateOracleConfig(value: unknown): OracleConfig {
665
719
  };
666
720
  }
667
721
 
668
- export function loadOracleConfig(cwd: string): OracleConfig {
669
- const details = getOracleConfigLoadDetails(cwd);
722
+ export function loadOracleConfig(cwd: string, options?: OracleConfigLoadOptions): OracleConfig {
723
+ const details = getOracleConfigLoadDetails(cwd, options);
670
724
  const globalConfig = readJson(details.agentConfigPath);
671
- const projectConfig = filterProjectConfig(readJson(details.projectConfigPath));
725
+ const projectConfig = details.projectConfigLoaded ? filterProjectConfig(readJson(details.projectConfigPath)) : undefined;
672
726
  return validateOracleConfig(deepMerge(deepMerge(DEFAULT_CONFIG, globalConfig), projectConfig));
673
727
  }
@@ -1264,7 +1264,7 @@ export function registerOracleTools(pi: ExtensionAPI, workerPath: string, authWo
1264
1264
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
1265
1265
  try {
1266
1266
  const projectCwd = getProjectId(ctx.cwd);
1267
- const baseConfig = loadOracleConfig(projectCwd);
1267
+ const baseConfig = loadOracleConfig(projectCwd, { projectConfigTrustCwd: ctx.cwd });
1268
1268
  const provider = normalizeOracleProvider(params.provider, baseConfig.defaults.provider, "oracle_auth");
1269
1269
  const message = await runOracleAuthBootstrap(authWorkerPath, projectCwd, provider);
1270
1270
  return {
@@ -1311,7 +1311,7 @@ export function registerOracleTools(pi: ExtensionAPI, workerPath: string, authWo
1311
1311
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
1312
1312
  try {
1313
1313
  const projectCwd = getProjectId(ctx.cwd);
1314
- const baseConfig = loadOracleConfig(projectCwd);
1314
+ const baseConfig = loadOracleConfig(projectCwd, { projectConfigTrustCwd: ctx.cwd });
1315
1315
  const originSessionFile = requirePersistedSessionFile(getSessionFile(ctx), "submit oracle jobs");
1316
1316
  const projectId = getProjectId(projectCwd);
1317
1317
  const sessionId = getSessionId(originSessionFile, projectId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-oracle",
3
- "version": "0.7.6",
3
+ "version": "0.7.7",
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",
@@ -83,8 +83,8 @@
83
83
  "protobufjs": "7.6.1"
84
84
  },
85
85
  "devDependencies": {
86
- "@earendil-works/pi-ai": "^0.78.1",
87
- "@earendil-works/pi-coding-agent": "^0.78.1",
86
+ "@earendil-works/pi-ai": "^0.79.0",
87
+ "@earendil-works/pi-coding-agent": "^0.79.0",
88
88
  "@types/node": "^22.19.19",
89
89
  "esbuild": "^0.28.0",
90
90
  "tsx": "^4.22.3",
@@ -22,7 +22,7 @@ function usage() {
22
22
  console.log(`Usage: node scripts/oracle-real-smoke.mjs <doctor|run> [--mode packed|source]
23
23
 
24
24
  Modes:
25
- packed Release proof. npm pack -> clean pi project -> npm install tarball -> pi install -l -> run through installed package. Default.
25
+ packed Release proof. npm pack -> clean pi project -> npm install tarball -> pi install -l --approve -> run through installed package. Default.
26
26
  source Inner-loop/debug only. Loads this checkout with pi --no-extensions -e extensions/oracle/index.ts.
27
27
 
28
28
  Environment:
@@ -257,12 +257,12 @@ async function preparePackedProject({ runDir, provider, model, timeoutMs }) {
257
257
 
258
258
  await mustRun(installDir, "npm-init", npm, ["init", "-y"], { cwd: piProject, env: process.env, timeoutMs: 60_000 });
259
259
  await mustRun(installDir, "packed-node-install", npm, ["install", "--no-save", tarballPath], { cwd: piProject, env: process.env, timeoutMs: 120_000 });
260
- await mustRun(installDir, "pi-install", piCommand(), ["install", "-l", `./node_modules/${PACKAGE_NAME}`], {
260
+ await mustRun(installDir, "pi-install", piCommand(), ["install", "-l", `./node_modules/${PACKAGE_NAME}`, "--approve"], {
261
261
  cwd: piProject,
262
262
  env: { ...process.env, PI_OFFLINE: "1" },
263
263
  timeoutMs: 120_000,
264
264
  });
265
- const piList = await mustRun(installDir, "pi-list", piCommand(), ["list"], {
265
+ const piList = await mustRun(installDir, "pi-list", piCommand(), ["list", "--approve"], {
266
266
  cwd: piProject,
267
267
  env: { ...process.env, PI_OFFLINE: "1" },
268
268
  timeoutMs: 60_000,
@@ -342,6 +342,7 @@ console.log(JSON.stringify(result, null, 2));
342
342
  async function runPiAgent({ prepared, agentDir, sessionDir, jobsDir, prompt, outDir, label, timeoutMs, stopAfterJobArchive = false }) {
343
343
  mkdirSync(outDir, { recursive: true });
344
344
  const args = [
345
+ "--approve",
345
346
  "--print",
346
347
  "--provider", prepared.provider,
347
348
  "--model", prepared.model,
@@ -122,7 +122,7 @@ if ($PackTarball -and $PiCli -and (Test-Path -LiteralPath $TarballPath)) {
122
122
  if ($PACKED_NODE_INSTALL_EXIT -eq 0) {
123
123
  $PreviousPiOffline = $env:PI_OFFLINE
124
124
  $env:PI_OFFLINE = "1"
125
- & $PiCli install -l (Join-Path ".\node_modules" $PackageName) 1> $PiInstallOut 2> $PiInstallErr
125
+ & $PiCli install -l (Join-Path ".\node_modules" $PackageName) --approve 1> $PiInstallOut 2> $PiInstallErr
126
126
  $PI_INSTALL_EXIT = Exit-CodeFromLastCommand
127
127
  if ($null -eq $PreviousPiOffline) { Remove-Item Env:\PI_OFFLINE -ErrorAction SilentlyContinue } else { $env:PI_OFFLINE = $PreviousPiOffline }
128
128
  } else {
@@ -148,7 +148,7 @@ if ($PiCli) {
148
148
  Push-Location $PiProject
149
149
  $PreviousPiOffline = $env:PI_OFFLINE
150
150
  $env:PI_OFFLINE = "1"
151
- & $PiCli list 1> $PiListOut 2> $PiListErr
151
+ & $PiCli list --approve 1> $PiListOut 2> $PiListErr
152
152
  $PI_LIST_EXIT = Exit-CodeFromLastCommand
153
153
  if ($null -eq $PreviousPiOffline) { Remove-Item Env:\PI_OFFLINE -ErrorAction SilentlyContinue } else { $env:PI_OFFLINE = $PreviousPiOffline }
154
154
  Pop-Location
@@ -194,13 +194,13 @@ export function buildPlatformBuildCommand(targetName = "ubuntu", packageName = "
194
194
  lines.push('echo "PLATFORM_PACKED_NODE_INSTALL_EXIT=$PACKED_NODE_INSTALL_EXIT"');
195
195
  lines.push(...posixSection("PACKED_NODE_INSTALL_STDOUT", 'cat "$PACK_DIR/packed-node-install.stdout.txt" 2>/dev/null || true'));
196
196
  lines.push(...posixSection("PACKED_NODE_INSTALL_STDERR", 'cat "$PACK_DIR/packed-node-install.stderr.txt" 2>/dev/null || true'));
197
- lines.push(`if [ "$PACKED_NODE_INSTALL_EXIT" -eq 0 ] && [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" install -l ./node_modules/${packageName} >"$PACK_DIR/pi-install.stdout.txt" 2>"$PACK_DIR/pi-install.stderr.txt"); PI_INSTALL_EXIT=$?; else echo "packed npm install failed or missing pi cli" >"$PACK_DIR/pi-install.stderr.txt"; PI_INSTALL_EXIT=1; fi`);
197
+ lines.push(`if [ "$PACKED_NODE_INSTALL_EXIT" -eq 0 ] && [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" install -l ./node_modules/${packageName} --approve >"$PACK_DIR/pi-install.stdout.txt" 2>"$PACK_DIR/pi-install.stderr.txt"); PI_INSTALL_EXIT=$?; else echo "packed npm install failed or missing pi cli" >"$PACK_DIR/pi-install.stderr.txt"; PI_INSTALL_EXIT=1; fi`);
198
198
  lines.push('echo "PLATFORM_PI_INSTALL_EXIT=$PI_INSTALL_EXIT"');
199
199
  lines.push(...posixSection("PI_INSTALL_STDOUT", 'cat "$PACK_DIR/pi-install.stdout.txt" 2>/dev/null || true'));
200
200
  lines.push(...posixSection("PI_INSTALL_STDERR", 'cat "$PACK_DIR/pi-install.stderr.txt" 2>/dev/null || true'));
201
201
  lines.push("");
202
202
  lines.push('echo "=== pi list ==="');
203
- lines.push('if [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" list >"$PACK_DIR/pi-list.stdout.txt" 2>"$PACK_DIR/pi-list.stderr.txt"); PI_LIST_EXIT=$?; else echo "missing pi cli" >"$PACK_DIR/pi-list.stderr.txt"; PI_LIST_EXIT=1; fi');
203
+ lines.push('if [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" list --approve >"$PACK_DIR/pi-list.stdout.txt" 2>"$PACK_DIR/pi-list.stderr.txt"); PI_LIST_EXIT=$?; else echo "missing pi cli" >"$PACK_DIR/pi-list.stderr.txt"; PI_LIST_EXIT=1; fi');
204
204
  lines.push('echo "PLATFORM_PI_LIST_EXIT=$PI_LIST_EXIT"');
205
205
  lines.push(...posixSection("PI_LIST_STDOUT", 'cat "$PACK_DIR/pi-list.stdout.txt" 2>/dev/null || true'));
206
206
  lines.push(...posixSection("PI_LIST_STDERR", 'cat "$PACK_DIR/pi-list.stderr.txt" 2>/dev/null || true'));