pi-oracle 0.6.1 → 0.6.3

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,21 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.6.3 - 2026-04-13
6
+
7
+ ### Fixed
8
+ - workspace-root detection now prefers nearest project markers like `.pi/` and `AGENTS.md` over unrelated ancestor git roots, so oracle submissions from nested projects no longer widen to a home-directory repo and reject valid project-relative archive inputs like `AGENTS.md`
9
+ - sanity coverage now guards the nested-project-under-ancestor-git case so archive resolution stays anchored to the intended project root
10
+
11
+ ## 0.6.2 - 2026-04-13
12
+
13
+ ### Changed
14
+ - `/oracle` and `/oracle-followup` now treat pre-dispatch `archive_too_large` submit failures as retryable archive-selection misses instead of immediate dead ends, so agents can automatically narrow the archive and retry before surfacing the problem to the user
15
+
16
+ ### Fixed
17
+ - archive-too-large submit errors now explain the 250 MB limit in human-readable terms, state that dispatch stopped before launch, and describe an ordered retry plan for shrinking the archive
18
+ - oracle tool guidance, docs, and sanity coverage now align on only ending the turn after successful/queued `oracle_submit` results instead of accidentally stopping on a retryable oversize failure
19
+
5
20
  ## 0.6.1 - 2026-04-13
6
21
 
7
22
  ### Fixed
package/README.md CHANGED
@@ -54,6 +54,8 @@ The `/oracle` prompt now runs an early oracle preflight before it gathers repo c
54
54
 
55
55
  For explicitly narrow requests, `/oracle` should still prefer a context-rich relevant archive up to the 250 MB ceiling, including nearby tests, docs, config, and adjacent modules when that can improve answer quality. Reserve tightly minimal archives for an explicit user request for a tight archive, privacy-sensitive material, or size-constrained cases. It should also omit `preset` and use the configured default model unless the task clearly needs a different one.
56
56
 
57
+ If a local archive still exceeds the 250 MB limit after default exclusions and automatic whole-repo pruning, the agent should treat that as a retryable archive-selection failure: shrink the archive automatically, retry with a smaller relevant slice, and explain what it cut only if it still cannot fit after the allowed retry budget.
58
+
57
59
  If you miss the wake-up, the result is still saved durably in the oracle job directory and can be read later.
58
60
 
59
61
  ## Example requests
@@ -115,9 +115,11 @@ Instead it instructs the agent to:
115
115
  5. gather enough repo context to submit well and bias toward context-rich archives when they fit within the 250 MB ceiling
116
116
  6. if the request is narrow, start from the directly relevant area but still include nearby tests, docs, config, and adjacent modules when they may improve answer quality
117
117
  7. if the request is broad/repo-wide, gather broader context and usually archive `.`
118
- 8. craft the oracle prompt
119
- 9. call `oracle_submit`
120
- 10. stop and wait for the completion wake-up (best-effort; durable oracle response/artifact state is already persisted outside session history)
118
+ 8. if `oracle_submit` fails before dispatch with an `archive_too_large` / upload-limit error, treat that as retryable: use the reported size summary plus any auto-pruned paths to cut scope and retry automatically with a smaller archive
119
+ 9. stop retrying after at most two total submit attempts for the same request; if it still does not fit, report what was cut and why
120
+ 10. craft the oracle prompt
121
+ 11. call `oracle_submit`
122
+ 12. stop and wait for the completion wake-up (best-effort; durable oracle response/artifact state is already persisted outside session history)
121
123
 
122
124
  ### `/oracle-auth`
123
125
 
@@ -148,7 +150,7 @@ The authenticated seed profile remains the source of truth for future oracle run
148
150
 
149
151
  ### `oracle_submit`
150
152
 
151
- Agent-facing submissions use **`preset`**; the canonical registry is `ORACLE_SUBMIT_PRESETS` in `extensions/oracle/lib/config.ts`. **`preset` is the only model-selection parameter** on `oracle_submit`. There are no `modelFamily`, `effort`, or `autoSwitchToThinking` fields. Submit-time inputs accept canonical preset ids plus matching human-readable labels/common hyphen-space variants, and the tool normalizes them back to the canonical id before persisting job state. Prompt-template guidance biases toward omitting `preset` and using the configured default unless the task clearly needs a different model or the user explicitly asked for one. It also biases toward context-rich archives up to the 250 MB ceiling, narrowing only when the user explicitly asks for a tight archive, privacy/sensitivity requires it, or size pressure forces it.
153
+ Agent-facing submissions use **`preset`**; the canonical registry is `ORACLE_SUBMIT_PRESETS` in `extensions/oracle/lib/config.ts`. **`preset` is the only model-selection parameter** on `oracle_submit`. There are no `modelFamily`, `effort`, or `autoSwitchToThinking` fields. Submit-time inputs accept canonical preset ids plus matching human-readable labels/common hyphen-space variants, and the tool normalizes them back to the canonical id before persisting job state. Prompt-template guidance biases toward omitting `preset` and using the configured default unless the task clearly needs a different model or the user explicitly asked for one. It also biases toward context-rich archives up to the 250 MB ceiling, narrowing only when the user explicitly asks for a tight archive, privacy/sensitivity requires it, or size pressure forces it. When local archive creation still exceeds that ceiling after default exclusions and whole-repo auto-pruning, prompt guidance now treats the failure as a retryable archive-selection miss rather than a terminal dead end: agents should cut scope automatically, retry once or twice, and only surface the cut decisions if the archive still cannot fit.
152
154
 
153
155
  1. resolve the preset (submit-time or config default) into an execution snapshot
154
156
  2. resolve optional `followUpJobId` into a prior `chatUrl` and `conversationId`
@@ -43,6 +43,8 @@ export const ORACLE_NOTIFICATION_CLAIM_TTL_MS = 60_000;
43
43
  export const ORACLE_WAKEUP_MAX_ATTEMPTS = 3;
44
44
  export const ORACLE_WAKEUP_RETRY_DELAYS_MS = [0, 15_000, 60_000] as const;
45
45
  export const ORACLE_WAKEUP_POST_SEND_RETENTION_MS = 2 * 60 * 1000;
46
+ const ORACLE_JOB_DIR_RM_MAX_RETRIES = 5;
47
+ const ORACLE_JOB_DIR_RM_RETRY_DELAY_MS = 50;
46
48
  const ORACLE_COMPLETE_JOB_RETENTION_MS = 14 * 24 * 60 * 60 * 1000;
47
49
  const ORACLE_FAILED_JOB_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
48
50
  export const DEFAULT_ORACLE_JOBS_DIR = "/tmp";
@@ -507,7 +509,12 @@ export async function removeTerminalOracleJob(job: OracleJob): Promise<{ removed
507
509
  }));
508
510
  return { removed: false, cleanupReport };
509
511
  }
510
- await rm(getJobDir(current.id), { recursive: true, force: true });
512
+ await rm(getJobDir(current.id), {
513
+ recursive: true,
514
+ force: true,
515
+ maxRetries: ORACLE_JOB_DIR_RM_MAX_RETRIES,
516
+ retryDelay: ORACLE_JOB_DIR_RM_RETRY_DELAY_MS,
517
+ });
511
518
  return { removed: true, cleanupReport };
512
519
  });
513
520
  }
@@ -23,6 +23,8 @@ const PROFILE_CLONE_TIMEOUT_MS = 120_000;
23
23
  const ORACLE_SUBPROCESS_KILL_GRACE_MS = 2_000;
24
24
  const WORKSPACE_ROOT_MARKERS = [
25
25
  ".pi/extensions/oracle.json",
26
+ ".pi",
27
+ "AGENTS.md",
26
28
  ] as const;
27
29
  const REQUIRED_ORACLE_DEPENDENCIES = [
28
30
  { name: "agent-browser", command: AGENT_BROWSER_BIN },
@@ -75,8 +77,8 @@ function resolveWorkspaceRoot(realCwd: string): string {
75
77
  let current = realCwd;
76
78
  let nearestMarkerRoot: string | undefined;
77
79
  while (true) {
78
- if (existsSync(join(current, ".git"))) return current;
79
80
  if (!nearestMarkerRoot && hasWorkspaceRootMarker(current)) nearestMarkerRoot = current;
81
+ if (existsSync(join(current, ".git"))) return nearestMarkerRoot ?? current;
80
82
  const parent = dirname(current);
81
83
  if (parent === current) return nearestMarkerRoot ?? realCwd;
82
84
  current = parent;
@@ -338,14 +338,15 @@ function formatArchiveOversizeError(args: {
338
338
  const topLevel = summarizeTopLevelIncludedPaths(args.entrySizes);
339
339
  const adaptiveCandidates = summarizeAdaptivePruneCandidates(args.entrySizes, args.adaptivePruneMinBytes).slice(0, 7);
340
340
  return [
341
- `Oracle archive exceeds ChatGPT upload limit after default exclusions${args.autoPrunedPrefixes.length > 0 ? " and automatic generic generated-output-dir pruning" : ""}: ${args.archiveBytes} bytes >= ${args.maxBytes} bytes`,
341
+ `Oracle archive exceeds ChatGPT upload limit (${formatBytes(args.maxBytes)}) after default exclusions${args.autoPrunedPrefixes.length > 0 ? " and automatic generic generated-output-dir pruning" : ""}.`,
342
+ `The local archive measured ${formatBytes(args.archiveBytes)} (${args.archiveBytes} bytes), so submission stopped before dispatch.`,
342
343
  args.autoPrunedPrefixes.length > 0 ? "Automatically pruned generic generated-output paths before failing:" : undefined,
343
344
  ...args.autoPrunedPrefixes.map((entry) => `- ${formatDirectoryLabel(entry.relativePath)} — ${formatBytes(entry.bytes)}`),
344
345
  topLevel.length > 0 ? "Approx top-level included sizes:" : undefined,
345
346
  ...topLevel.map((entry) => `- ${entry.relativePath} — ${formatBytes(entry.bytes)}`),
346
347
  adaptiveCandidates.length > 0 ? "Largest remaining generic generated-output-dir candidates:" : undefined,
347
348
  ...adaptiveCandidates.map((entry) => `- ${formatDirectoryLabel(entry.relativePath)} — ${formatBytes(entry.bytes)}`),
348
- "Retry with narrower archive inputs, starting with modified files plus adjacent files plus directly relevant subtrees.",
349
+ "Recommended retry order: (1) remove the largest obviously irrelevant/generated/history/export content, (2) if it still does not fit, keep only the directly relevant subtrees plus adjacent docs/tests/config, (3) if it still does not fit, explain what was cut before asking the user.",
349
350
  ]
350
351
  .filter(Boolean)
351
352
  .join("\n");
@@ -878,7 +879,7 @@ function buildOracleToolErrorDetails(toolName: OracleToolErrorSource, error: unk
878
879
  return {
879
880
  code: "archive_too_large",
880
881
  message,
881
- suggestedNextStep: "Retry with a narrower archive, starting with modified files plus adjacent files plus directly relevant subtrees.",
882
+ suggestedNextStep: "This failure is retryable. Retry automatically with fewer selected files: first remove the largest obviously irrelevant/generated/history/export content, then if needed narrow to the directly relevant subtrees plus adjacent docs/tests/config, and if it still does not fit explain what was cut before asking the user.",
882
883
  };
883
884
  }
884
885
 
@@ -1072,9 +1073,12 @@ export function registerOracleTools(pi: ExtensionAPI, workerPath: string, authWo
1072
1073
  "Do not default to a one-file archive for a single function, file, or stack trace if the relevant surrounding context still fits comfortably within the limit.",
1073
1074
  "When files='.' and the post-exclusion archive is still too large, submit automatically prunes the largest nested directories matching generic generated-output names like build/, dist/, out/, coverage/, and tmp/ outside obvious source roots like src/ and lib/ until the archive fits or no candidate remains; successful submissions report what was pruned.",
1074
1075
  "If a submitted oracle job later fails because upload is rejected, retry smaller: remove the largest obviously irrelevant/generated content first, then narrow to modified files plus adjacent files plus directly relevant subtrees, then explain the cut or ask the user if still needed.",
1075
- "If oracle_submit itself fails because the local archive still exceeds the upload limit after default exclusions and automatic generic generated-output-dir pruning, or for any other submit-time error, stop and report the error instead of retrying automatically.",
1076
+ "If oracle_submit fails before dispatch with details.error.code === 'archive_too_large' or an upload-limit message, treat that as retryable and retry automatically with a smaller archive.",
1077
+ "For archive_too_large retries, use the reported top-level size summary and any auto-pruned paths to decide what to cut: first remove the largest obviously irrelevant/generated/history/export content, then if needed narrow to the directly relevant subtrees plus adjacent docs/tests/config.",
1078
+ "Do not loop forever: stop after at most two total oracle_submit attempts for the same request, and if it still does not fit explain what was cut and why.",
1079
+ "For any other submit-time error, stop and report the error instead of retrying automatically.",
1076
1080
  "If oracle_submit returns a queued job instead of an immediately dispatched one, treat that as success and stop exactly the same way.",
1077
- "Stop after dispatching oracle_submit; do not continue the task while the oracle job is running.",
1081
+ "After a successful or queued oracle_submit, stop; do not continue the task while the oracle job is running. If oracle_submit failed with retryable archive_too_large, narrow the archive and retry first.",
1078
1082
  "Use `preset` as the only model-selection parameter on oracle_submit. Canonical ids are preferred, and matching human-readable preset labels are normalized automatically. Omit preset to use the configured default.",
1079
1083
  ],
1080
1084
  parameters: ORACLE_SUBMIT_PARAMS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-oracle",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "description": "ChatGPT web-oracle extension for pi with isolated browser auth, async jobs, and project-context archives.",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -39,10 +39,12 @@ Rules:
39
39
  - If the request depends on git state or pending changes (for example code review, ship readiness, or release approval), create a tracked diff bundle file inside the repo (for example under `.pi/`) containing `git status` plus `git diff` output, include that file in the archive, and tell the oracle to use it because the `.git` directory is not included in oracle exports.
40
40
  - When `files=["."]` and the post-exclusion archive is still too large, submit automatically prunes the largest nested directories matching generic generated-output names like `build/`, `dist/`, `out/`, `coverage/`, and `tmp/` outside obvious source roots like `src/` and `lib/` until the archive fits or no candidate remains. Successful submissions report what was pruned.
41
41
  - If a submitted oracle job later fails because upload is rejected, retry with a smaller archive in this order: (1) remove the largest obviously irrelevant/generated content, (2) if still too large, include modified files plus adjacent files plus directly relevant subtrees, (3) if still too large, explain the cut or ask the user.
42
+ - If `oracle_submit` fails before dispatch with `details.error.code === "archive_too_large"` or an upload-limit message, that failure is retryable. Use the reported top-level size summary and any auto-pruned paths to choose a smaller archive and retry automatically.
43
+ - For archive-too-large retries, cut scope in this order: (1) if you used `.`, remove the largest obviously irrelevant/generated/history/export/report content while preserving relevant source/docs/config/tests, (2) if it still does not fit, archive only the directly relevant subtrees plus adjacent docs/tests/config, (3) if it still does not fit after at most two total `oracle_submit` attempts, report what you cut and why.
42
44
  - Prefer the configured default (omit **`preset`**) unless the task clearly needs a different model or the user explicitly asked for one; then choose a canonical **`preset`** id.
43
- - If `oracle_submit` itself fails because the local archive still exceeds the upload limit after default exclusions and automatic generic generated-output-dir pruning, or for any other submit-time error, stop and report the error. Do not retry automatically.
45
+ - For any other `oracle_submit` submit-time error, stop and report the error. Do not retry automatically.
44
46
  - If `oracle_submit` returns a queued job instead of an immediately dispatched one, treat that as success and end your turn exactly the same way.
45
- - After `oracle_submit` returns, end your turn. Do not keep working while the oracle runs.
47
+ - After a successful or queued `oracle_submit`, end your turn. Do not keep working while the oracle runs. If `oracle_submit` failed with a retryable archive-too-large error, shrink the archive and retry first.
46
48
 
47
49
  User request:
48
50
  $@
package/prompts/oracle.md CHANGED
@@ -35,10 +35,12 @@ Rules:
35
35
  - If the request depends on git state or pending changes (for example code review, ship readiness, or release approval), create a tracked diff bundle file inside the repo (for example under `.pi/`) containing `git status` plus `git diff` output, include that file in the archive, and tell the oracle to use it because the `.git` directory is not included in oracle exports.
36
36
  - When `files=["."]` and the post-exclusion archive is still too large, submit automatically prunes the largest nested directories matching generic generated-output names like `build/`, `dist/`, `out/`, `coverage/`, and `tmp/` outside obvious source roots like `src/` and `lib/` until the archive fits or no candidate remains. Successful submissions report what was pruned.
37
37
  - If a submitted oracle job later fails because upload is rejected, retry with a smaller archive in this order: (1) remove the largest obviously irrelevant/generated content, (2) if still too large, include modified files plus adjacent files plus directly relevant subtrees, (3) if still too large, explain the cut or ask the user.
38
+ - If `oracle_submit` fails before dispatch with `details.error.code === "archive_too_large"` or an upload-limit message, that failure is retryable. Use the reported top-level size summary and any auto-pruned paths to choose a smaller archive and retry automatically.
39
+ - For archive-too-large retries, cut scope in this order: (1) if you used `.`, remove the largest obviously irrelevant/generated/history/export/report content while preserving relevant source/docs/config/tests, (2) if it still does not fit, archive only the directly relevant subtrees plus adjacent docs/tests/config, (3) if it still does not fit after at most two total `oracle_submit` attempts, report what you cut and why.
38
40
  - Prefer the configured default (omit **`preset`**) unless the task clearly needs a different model or the user explicitly asked for one; then choose a canonical **`preset`** id.
39
- - If `oracle_submit` itself fails because the local archive still exceeds the upload limit after default exclusions and automatic generic generated-output-dir pruning, or for any other submit-time error, stop and report the error. Do not retry automatically.
41
+ - For any other `oracle_submit` submit-time error, stop and report the error. Do not retry automatically.
40
42
  - If `oracle_submit` returns a queued job instead of an immediately dispatched one, treat that as success and end your turn exactly the same way.
41
- - After oracle_submit returns, end your turn. Do not keep working while the oracle runs.
43
+ - After a successful or queued `oracle_submit`, end your turn. Do not keep working while the oracle runs. If `oracle_submit` failed with a retryable archive-too-large error, shrink the archive and retry first.
42
44
 
43
45
  User request:
44
46
  $@