pi-oracle 0.6.17 → 0.7.0

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,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.7.0 - 2026-05-17
6
+
7
+ ### Added
8
+ - added Grok Heavy as a second oracle provider, with `provider: "grok"`, Grok-only `mode: "heavy"`, `/oracle-auth grok`, separate Grok auth seed profiles, and provider defaults in oracle config
9
+ - added provider-aware `oracle_preflight` support, including explicit Grok checks and follow-up readiness checks that use the prior job's provider
10
+ - added Grok web worker support for auth readiness, Heavy selection, archive upload, prompt submission, response extraction, and same-thread follow-ups
11
+
12
+ ### Changed
13
+ - documented provider selection, Grok's 200 MiB upload ceiling, ChatGPT's 250 MiB ceiling, and same-provider-only follow-up behavior in README, design docs, and prompt templates
14
+ - updated oracle job summaries to report Grok provider/mode selections, not only ChatGPT presets
15
+
16
+ ### Fixed
17
+ - preserved Cloudflare continuity cookies for current ChatGPT verification flows and removed Chromium singleton artifacts when cloning runtime profiles
18
+ - tightened Grok/X cookie import to an explicit auth-cookie allowlist and made Grok jobs fail clearly if a completed response never produces a stable conversation URL
19
+ - improved ChatGPT response extraction fallback behavior when the UI no longer exposes the old `ChatGPT said:` heading structure
20
+
21
+ ### Validation
22
+ - verified Grok Heavy live submission and same-thread Grok follow-up using isolated local-extension `pi` sessions
23
+ - verified a final ChatGPT `instant` live smoke using an isolated local-extension `pi` session before release
24
+
5
25
  ## 0.6.17 - 2026-05-10
6
26
 
7
27
  ### Changed
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pi-oracle
2
2
 
3
- `pi-oracle` lets a `pi` agent send hard, long-running work to ChatGPT.com 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.
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
5
  > Status: experimental public beta. Validated primarily on macOS with Google Chrome/Chromium and `pi` 0.65.0+. Normal oracle jobs run in an isolated browser profile, not your active browser window.
6
6
 
@@ -12,47 +12,47 @@ You: /oracle Review the pending changes. Include the whole repo unless a narrowe
12
12
  pi-oracle:
13
13
  1. preflights local session/auth readiness
14
14
  2. builds a context-rich `.tar.zst` repo archive
15
- 3. starts an isolated ChatGPT web runtime in the background
16
- 4. uploads the archive and prompt to ChatGPT.com
15
+ 3. starts an isolated provider web runtime in the background
16
+ 4. uploads the archive and prompt to the selected provider
17
17
  5. saves the response/artifacts under /tmp/oracle-<job-id>/
18
18
  6. sends a best-effort wake-up back to the matching pi session
19
19
 
20
20
  Later: /oracle-read <job-id>
21
21
  ```
22
22
 
23
- What you are seeing: the local `pi` agent keeps control of context selection and safety checks, while ChatGPT web handles the expensive second-opinion work asynchronously. If the wake-up is missed, the result still lives on disk and can be read by job id.
23
+ What you are seeing: the local `pi` agent keeps control of context selection and safety checks, while the selected web provider handles the expensive second-opinion work asynchronously. If the wake-up is missed, the result still lives on disk and can be read by job id.
24
24
 
25
25
  ## Who this is for
26
26
 
27
- Use `pi-oracle` if you use `pi` and want a larger asynchronous reviewer, planner, or analyst that can use your real ChatGPT web account instead of an API model.
27
+ Use `pi-oracle` if you use `pi` and want a larger asynchronous reviewer, planner, or analyst that can use your real ChatGPT or Grok web account instead of an API model.
28
28
 
29
29
  It is most useful for:
30
30
 
31
31
  - maintainers reviewing broad repo changes before shipping
32
32
  - agents that need a slower second opinion without blocking the main `pi` turn
33
33
  - migration, architecture, or failure-mode analysis that benefits from a large archive
34
- - follow-up questions that should continue the same ChatGPT thread later
34
+ - follow-up questions that should continue the same provider thread later
35
35
 
36
36
  Do not use it for:
37
37
 
38
38
  - short local coding tasks that `pi` can handle directly
39
- - projects that must never be uploaded to ChatGPT.com
39
+ - projects that must never be uploaded to ChatGPT.com, Grok, or another configured web provider
40
40
  - non-macOS environments or machines without the required local browser/tooling
41
41
 
42
42
  ## Problem it solves
43
43
 
44
- A normal coding-agent turn is the wrong shape for some work: the task may need a large repo snapshot, a slower web model, a real ChatGPT subscription, artifact downloads, or a durable result that arrives after the active turn ends.
44
+ A normal coding-agent turn is the wrong shape for some work: the task may need a large repo snapshot, a slower web model, a real ChatGPT/Grok subscription, artifact downloads, or a durable result that arrives after the active turn ends.
45
45
 
46
- `pi-oracle` makes that workflow explicit and recoverable instead of asking the main agent to manually drive ChatGPT in your real browser window.
46
+ `pi-oracle` makes that workflow explicit and recoverable instead of asking the main agent to manually drive provider chat UIs in your real browser window.
47
47
 
48
48
  ## What it does
49
49
 
50
50
  | Problem | Capability | Proof in this repo |
51
51
  | --- | --- | --- |
52
- | Hard tasks need more context than a quick turn should gather. | `/oracle` prompts the agent to preflight, choose a context-rich archive, and submit it to ChatGPT web. | [`prompts/oracle.md`](prompts/oracle.md), `oracle_submit`, archive tests in `scripts/oracle-sanity-*` |
52
+ | Hard tasks need more context than a quick turn should gather. | `/oracle` prompts the agent to preflight, choose a context-rich archive, and submit it to the selected provider web app. | [`prompts/oracle.md`](prompts/oracle.md), `oracle_submit`, archive tests in `scripts/oracle-sanity-*` |
53
53
  | Browser automation should not steal focus or mutate your active profile. | Jobs clone an authenticated seed profile into per-job isolated runtime profiles. | [`docs/ORACLE_DESIGN.md`](docs/ORACLE_DESIGN.md), [`extensions/oracle/lib/runtime.ts`](extensions/oracle/lib/runtime.ts) |
54
54
  | Long jobs need durability. | Job state, responses, logs, and artifacts persist under `${PI_ORACLE_JOBS_DIR:-/tmp}/oracle-<job-id>/`. | [`extensions/oracle/lib/jobs.ts`](extensions/oracle/lib/jobs.ts), `/oracle-read`, `/oracle-status` |
55
- | ChatGPT auth can expire or drift. | `/oracle-auth` refreshes the isolated auth seed from a configured local Chromium profile, with recovery guidance. | [`extensions/oracle/lib/auth.ts`](extensions/oracle/lib/auth.ts), [`docs/ORACLE_RECOVERY_DRILL.md`](docs/ORACLE_RECOVERY_DRILL.md) |
55
+ | Provider auth can expire or drift. | `/oracle-auth [chatgpt|grok]` refreshes the isolated auth seed from a configured local Chromium profile, with recovery guidance. | [`extensions/oracle/lib/auth.ts`](extensions/oracle/lib/auth.ts), [`docs/ORACLE_RECOVERY_DRILL.md`](docs/ORACLE_RECOVERY_DRILL.md) |
56
56
  | Agents need a simple API, not UI-driving instructions. | The package exposes agent-facing tools: `oracle_preflight`, `oracle_submit`, `oracle_read`, `oracle_auth`, and `oracle_cancel`. | [`extensions/oracle/lib/tools.ts`](extensions/oracle/lib/tools.ts) |
57
57
 
58
58
  ## Fastest way to see it work
@@ -79,17 +79,17 @@ You need:
79
79
  - Node.js 22 or newer
80
80
  - `pi` 0.65.0 or newer
81
81
  - Google Chrome or another Chromium-family browser
82
- - ChatGPT already signed in to the configured local browser profile
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
84
84
  - a normal persisted `pi` session, not `pi --no-session`
85
85
 
86
- ### 3. Sync ChatGPT auth once
86
+ ### 3. Sync provider auth once
87
87
 
88
88
  ```text
89
89
  /oracle-auth
90
90
  ```
91
91
 
92
- This reads ChatGPT cookies from your configured local browser profile and writes an isolated oracle seed profile. It should not automate your active browser window for normal jobs.
92
+ This reads cookies for the configured default provider from your local browser profile and writes an isolated oracle seed profile. Use `/oracle-auth grok` to force-refresh the Grok seed when your default provider is still ChatGPT. It should not automate your active browser window for normal jobs.
93
93
 
94
94
  ### 4. Submit a tiny job
95
95
 
@@ -100,10 +100,10 @@ This reads ChatGPT cookies from your configured local browser profile and writes
100
100
  Expected result:
101
101
 
102
102
  - The `/oracle` prompt now runs an early oracle preflight before expensive repo reading or archive creation.
103
- - The agent chooses a context-rich relevant archive up to the 250 MB ceiling, not the smallest possible one-file slice when nearby context helps.
103
+ - The agent chooses a context-rich relevant archive up to the selected provider's upload ceiling, not the smallest possible one-file slice when nearby context helps.
104
104
  - `oracle_submit` creates or queues a job.
105
105
  - If local packing is too large, the prompt treats that as a retryable archive-selection failure and narrows automatically before surfacing the problem.
106
- - The job uploads a repo archive to ChatGPT.com, capped at 250 MiB after default exclusions/pruning.
106
+ - The job uploads a repo archive to the selected provider, capped at 250 MiB for ChatGPT or 200 MiB for Grok after default exclusions/pruning.
107
107
  - The response is saved under `/tmp/oracle-<job-id>/response.md` by default.
108
108
  - The matching `pi` session gets one best-effort wake-up when the job finishes.
109
109
 
@@ -140,7 +140,7 @@ flowchart LR
140
140
  B --> C["Agent chooses context-rich archive inputs"]
141
141
  C --> D["oracle_submit builds .tar.zst archive"]
142
142
  D --> E["Detached worker clones isolated auth seed profile"]
143
- E --> F["ChatGPT web receives archive + prompt"]
143
+ E --> F["Selected provider receives archive + prompt"]
144
144
  F --> G["Response/artifacts saved under oracle job dir"]
145
145
  G --> H["Best-effort wake-up to matching pi session"]
146
146
  ```
@@ -150,16 +150,16 @@ Key design choices:
150
150
  - **Prompt templates own context gathering.** `/oracle` and `/oracle-followup` tell the agent how to preflight, gather context, choose archive inputs, and then stop after dispatch.
151
151
  - **Tools own execution.** `oracle_submit` builds the archive, admits or queues the job, starts the worker, and returns immediately.
152
152
  - **Auth uses a seed profile.** `/oracle-auth` imports cookies into an isolated seed profile; each job clones that seed into its own temporary runtime profile.
153
- - **Follow-ups preserve ChatGPT thread state.** `/oracle-followup <job-id> ...` resolves the prior job's saved ChatGPT URL and submits the next prompt with `followUpJobId`.
153
+ - **Follow-ups preserve provider thread state.** `/oracle-followup <job-id> ...` resolves the prior job's saved provider URL and submits the next prompt with `followUpJobId`.
154
154
  - **Wake-up is best effort, storage is durable.** A missed wake-up does not lose the result.
155
155
 
156
156
  ## Commands and tools
157
157
 
158
158
  User-facing commands:
159
159
 
160
- - `/oracle <request>` — prepare context and dispatch a ChatGPT web oracle job
161
- - `/oracle-followup <job-id> <request>` — continue an earlier oracle job in the same ChatGPT thread
162
- - `/oracle-auth` — sync ChatGPT cookies into the isolated oracle auth seed profile
160
+ - `/oracle <request>` — prepare context and dispatch a ChatGPT or Grok web oracle job
161
+ - `/oracle-followup <job-id> <request>` — continue an earlier oracle job in the same provider thread
162
+ - `/oracle-auth [chatgpt|grok]` — sync provider cookies into the isolated oracle auth seed profile
163
163
  - `/oracle-read [job-id]` — inspect job status and saved response preview
164
164
  - `/oracle-status [job-id]` — inspect a job or list recent job ids when no explicit id is given
165
165
  - `/oracle-cancel <job-id>` — cancel a queued or active job
@@ -175,14 +175,16 @@ Agent-facing tools:
175
175
 
176
176
  ## Configuration
177
177
 
178
- Most users can start with defaults. Set an agent-level config only when you need a non-default preset or browser profile.
178
+ Most users can start with defaults. Set an agent-level config only when you need a non-default provider, mode, preset, or browser profile.
179
179
 
180
180
  `~/.pi/agent/extensions/oracle.json`
181
181
 
182
182
  ```json
183
183
  {
184
184
  "defaults": {
185
- "preset": "<preset id from ORACLE_SUBMIT_PRESETS>"
185
+ "provider": "chatgpt",
186
+ "preset": "<preset id from ORACLE_SUBMIT_PRESETS>",
187
+ "grokMode": "heavy"
186
188
  },
187
189
  "auth": {
188
190
  "chromeProfile": "Default"
@@ -192,10 +194,12 @@ Most users can start with defaults. Set an agent-level config only when you need
192
194
 
193
195
  Notes:
194
196
 
197
+ - `defaults.provider` is the default web provider: `chatgpt` or `grok`.
195
198
  - `defaults.preset` is the default ChatGPT model preset for oracle jobs.
196
- - The canonical preset ids live in [`extensions/oracle/lib/config.ts`](extensions/oracle/lib/config.ts).
197
- - If the packaged default is fine, omit `defaults.preset`.
198
- - When an agent is unsure which oracle preset fits, it should omit `preset` and use the configured default model instead of asking by default.
199
+ - `defaults.grokMode` is the default Grok mode. Only `heavy` is supported today.
200
+ - The canonical preset ids and provider modes live in [`extensions/oracle/lib/config.ts`](extensions/oracle/lib/config.ts).
201
+ - If the packaged default is fine, omit `defaults`.
202
+ - When an agent is unsure which oracle preset fits, it should omit `preset` and use the configured default model instead of asking by default. If the prompt says to use Grok, it should pass `provider: "grok"` to `oracle_submit`.
199
203
  - You usually do not need browser paths unless auto-detection fails.
200
204
 
201
205
  ### Custom Chromium cookie sources
@@ -204,7 +208,7 @@ Use this only for a Chromium-family browser that the default cookie importer can
204
208
 
205
209
  Before running `/oracle-auth` with this path:
206
210
 
207
- 1. Log into ChatGPT in the target browser profile.
211
+ 1. Log into ChatGPT or Grok in the target browser profile, depending on `defaults.provider`.
208
212
  2. Fully quit the browser so its `Cookies` database is stable.
209
213
  3. Find the profile `Cookies` SQLite DB path.
210
214
  4. Find the browser's macOS Keychain safe-storage item account and service name.
@@ -231,7 +235,16 @@ Example Helium config:
231
235
 
232
236
  `auth.chromeCookiePath` must be paired with `auth.chromiumKeychain`; partial config is rejected so oracle does not silently fall back to another browser source.
233
237
 
234
- ## Available presets
238
+ ## Available providers and presets
239
+
240
+ | Provider | Mode / preset | Upload ceiling |
241
+ | --- | --- | --- |
242
+ | ChatGPT | Presets below | 250 MiB |
243
+ | Grok | `heavy` only | 200 MiB |
244
+
245
+ Grok accepts the same `.tar.zst` archives that pi-oracle builds. Manual testing against `https://grok.com` found a 200 MiB file is accepted and a 200 MiB + 1 byte file is rejected, so pi-oracle caps Grok archives at 200 MiB.
246
+
247
+ ## Available ChatGPT presets
235
248
 
236
249
  | Preset id | Description |
237
250
  | --- | --- |
@@ -244,7 +257,7 @@ Example Helium config:
244
257
  | `instant` | Instant |
245
258
  | `instant_auto_switch` | Instant - Auto-switch to Thinking Enabled |
246
259
 
247
- `oracle_submit` accepts canonical preset ids or a matching human-readable preset label. Keep config values on canonical ids.
260
+ For ChatGPT, `oracle_submit` accepts canonical preset ids or a matching human-readable preset label. Keep config values on canonical ids. For Grok, use `provider: "grok"`; only Heavy is supported today.
248
261
 
249
262
  ## Outputs and cleanup
250
263
 
@@ -258,8 +271,8 @@ Example Helium config:
258
271
 
259
272
  This extension is local-first, but it handles sensitive local and project data:
260
273
 
261
- - `/oracle-auth` reads ChatGPT cookies from the configured local browser profile.
262
- - `oracle_submit` uploads selected project archives to ChatGPT.com.
274
+ - `/oracle-auth` reads provider cookies from the configured local browser profile. Use `/oracle-auth grok` for Grok when ChatGPT remains the default provider.
275
+ - `oracle_submit` uploads selected project archives to the selected provider web app.
263
276
  - Responses, logs, and artifacts are written to the configured oracle jobs directory.
264
277
 
265
278
  Review the code and design docs before using it with private or regulated material.
@@ -267,9 +280,9 @@ Review the code and design docs before using it with private or regulated materi
267
280
  ## Current limits
268
281
 
269
282
  - Experimental public beta, validated primarily on macOS.
270
- - ChatGPT UI, auth, model controls, and artifact download behavior can drift.
271
- - Archive uploads are capped at 250 MiB after default exclusions and automatic whole-repo pruning.
272
- - A real ChatGPT web session is required.
283
+ - Provider UI, auth, model controls, and artifact download behavior can drift.
284
+ - Archive uploads are capped at 250 MiB for ChatGPT and 200 MiB for Grok after default exclusions and automatic whole-repo pruning.
285
+ - A real ChatGPT or Grok web session is required for the provider you use.
273
286
  - The README currently uses command-level proof and design docs; no public screenshot or demo GIF is checked into the repo.
274
287
  - Production hardening should keep focusing on UI drift detection, auth recovery, artifact capture, and environment diagnostics.
275
288
 
@@ -277,18 +290,18 @@ Review the code and design docs before using it with private or regulated materi
277
290
 
278
291
  ### `/oracle-auth` fails or says login is required
279
292
 
280
- - Make sure ChatGPT works in the same local browser profile you configured.
293
+ - Make sure the selected provider works in the same local browser profile you configured.
281
294
  - For custom Chromium cookie sources, confirm `auth.chromeCookiePath` points at that profile's `Cookies` DB and `auth.chromiumKeychain.services` names the browser's safe-storage Keychain service.
282
295
  - Re-run `/oracle-auth`.
283
296
  - Agent callers can use `oracle_auth({})` once before retrying a stale-auth oracle submission.
284
- - If ChatGPT is half-logged-in or challenge flow state looks weird, finish the login/challenge in the headed auth browser and retry.
297
+ - If the provider is half-logged-in or challenge flow state looks weird, finish the login/challenge in the headed auth browser and retry.
285
298
 
286
299
  ### Custom Chromium auth says cookies synced but the session is rejected
287
300
 
288
- This usually means the cookie import worked but the source cookies are not the active ChatGPT session you expected.
301
+ This usually means the cookie import worked but the source cookies are not the active provider session you expected.
289
302
 
290
303
  1. Open the configured browser profile.
291
- 2. Confirm ChatGPT works there without logging in again.
304
+ 2. Confirm the selected provider works there without logging in again.
292
305
  3. Quit the browser fully so its `Cookies` DB is stable.
293
306
  4. Confirm `auth.chromeCookiePath` points at that exact profile's `Cookies` DB.
294
307
  5. Confirm `auth.chromiumKeychain.services` names the browser's safe-storage Keychain service for that DB.
@@ -355,7 +368,7 @@ For end-to-end local-extension smoke testing, use [`docs/ORACLE_ISOLATED_PI_VALI
355
368
  | --- | --- |
356
369
  | [`extensions/oracle/index.ts`](extensions/oracle/index.ts) | Extension entrypoint |
357
370
  | `extensions/oracle/lib/` | Commands, tools, config, jobs, queueing, runtime, poller |
358
- | `extensions/oracle/worker/` | Detached ChatGPT web worker and UI/auth helpers |
371
+ | `extensions/oracle/worker/` | Detached provider web worker and UI/auth helpers |
359
372
  | `extensions/oracle/shared/` | Shared process, state, job, and observability helpers |
360
373
  | [`prompts/oracle.md`](prompts/oracle.md) | `/oracle` prompt-template workflow |
361
374
  | [`prompts/oracle-followup.md`](prompts/oracle-followup.md) | `/oracle-followup` prompt-template workflow |
@@ -12,7 +12,7 @@ Compatibility target:
12
12
 
13
13
  ## Goal
14
14
 
15
- Create a `pi` extension that lets the user or agent consult ChatGPT.com through the web product instead of the API, with:
15
+ Create a `pi` extension that lets the user or agent consult ChatGPT.com or Grok through the web product instead of the API, with:
16
16
 
17
17
  - manual invocation via `/oracle ...`
18
18
  - automatic invocation by the agent in rare high-difficulty cases
@@ -34,7 +34,7 @@ The production architecture is now:
34
34
  - clone that seed into a **per-job runtime profile** for each oracle run
35
35
  - launch each job in its own **runtime browser session**
36
36
  - persist same-thread continuity by saved `chatUrl`, not by keeping tabs or browsers alive
37
- - allow parallel jobs only when they do not target the same ChatGPT conversation
37
+ - allow parallel jobs only when they do not target the same provider conversation
38
38
 
39
39
  ## Rejected production path
40
40
 
@@ -67,13 +67,13 @@ The extension now follows the current `pi` session lifecycle model:
67
67
  - intentionally uses native pi prompt/template queueing so submissions survive streaming and compaction
68
68
  - `/oracle-followup <job-id> <request>`
69
69
  - implemented as a prompt template, not an extension command
70
- - asks the agent to continue an earlier oracle job in the same ChatGPT thread via `followUpJobId`
70
+ - asks the agent to continue an earlier oracle job in the same provider thread via `followUpJobId`
71
71
  - keeps same-thread continuation available to normal users without requiring raw tool-call syntax
72
72
 
73
73
  ### Commands
74
74
 
75
- - `/oracle-auth`
76
- - syncs ChatGPT cookies from the configured local browser profile into the isolated oracle profile and verifies them there
75
+ - `/oracle-auth [chatgpt|grok]`
76
+ - syncs ChatGPT or Grok cookies from the configured local browser profile into the isolated oracle profile and verifies them there, based on the configured default provider or explicit command argument
77
77
  - `/oracle-read [job-id]`
78
78
  - shows job status plus the saved response preview
79
79
  - `/oracle-status [job-id]`
@@ -87,13 +87,14 @@ The extension now follows the current `pi` session lifecycle model:
87
87
 
88
88
  - `oracle_preflight`
89
89
  - lightweight agent-facing readiness check for persisted-session and local oracle prerequisites
90
+ - accepts optional `provider` and `followUpJobId` so readiness checks use the same auth seed/provider that submission will use
90
91
  - intended to run before expensive `/oracle` context gathering
91
92
  - `oracle_auth`
92
93
  - agent-facing auth refresh tool that mirrors `/oracle-auth` for stale-auth recovery before a retry
93
94
  - `oracle_submit`
94
95
  - low-level agent-facing dispatch tool
95
96
  - creates archive and launches a detached worker
96
- - supports optional `followUpJobId` to continue the same ChatGPT thread by persisted URL
97
+ - supports optional `followUpJobId` to continue the same provider thread by persisted URL
97
98
  - `oracle_read`
98
99
  - reads job status and outputs
99
100
  - `oracle_cancel`
@@ -103,16 +104,16 @@ The extension now follows the current `pi` session lifecycle model:
103
104
 
104
105
  ### `/oracle ...`
105
106
 
106
- `/oracle <request>` should not directly drive ChatGPT.
107
+ `/oracle <request>` should not directly drive ChatGPT or Grok.
107
108
  It expands through the prompt-template path so pi can apply its native queueing semantics before the agent starts work.
108
109
 
109
110
  Instead it instructs the agent to:
110
111
 
111
- 1. call `oracle_preflight` immediately
112
+ 1. call `oracle_preflight` immediately, passing `provider: "grok"` when the user explicitly asks for Grok
112
113
  2. stop right away if preflight reports the session or local oracle setup is not ready
113
114
  3. understand whether the request is explicitly narrow or genuinely broad
114
- 4. if the immediately preceding oracle run failed because ChatGPT login is required or the worker explicitly said to rerun `/oracle-auth`, call `oracle_auth` once before retrying
115
- 5. gather enough repo context to submit well and bias toward context-rich archives when they fit within the 250 MB ceiling
115
+ 4. if the immediately preceding oracle run failed because ChatGPT or Grok login is required or the worker explicitly said to rerun `/oracle-auth`, call `oracle_auth` once before retrying
116
+ 5. gather enough repo context to submit well and bias toward context-rich archives when they fit within the provider ceiling: 250 MB for ChatGPT and 200 MiB for Grok
116
117
  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
118
  7. if the request is broad/repo-wide, gather broader context and usually archive `.`
118
119
  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
@@ -127,7 +128,7 @@ Auth bootstrap flow:
127
128
 
128
129
  1. load oracle config
129
130
  2. acquire the global auth-maintenance lock
130
- 3. read ChatGPT cookies directly from the configured local browser cookie store in read-only mode
131
+ 3. read ChatGPT or Grok cookies directly from the configured local browser cookie store in read-only mode, depending on `defaults.provider`
131
132
  - configurable source profile / cookie DB path
132
133
  - optional configured Chromium Keychain source for browsers outside the default importer
133
134
  - no launch or mutation of the real browser profile
@@ -137,23 +138,23 @@ Auth bootstrap flow:
137
138
  - dedicated auth `--session`
138
139
  - dedicated staged seed `--profile`
139
140
  - configured executable path / user agent / launch args if set
140
- 7. clear isolated browser cookies and seed the staged profile with imported ChatGPT cookies
141
- 8. open ChatGPT in the isolated browser
142
- 9. verify auth with `/backend-api/me` plus ChatGPT UI readiness checks
141
+ 7. clear isolated browser cookies and seed the staged profile with imported provider cookies
142
+ 8. open the configured provider in the isolated browser
143
+ 9. verify auth with provider-specific readiness checks
143
144
  10. on success, close the isolated browser so Chrome flushes profile state cleanly
144
145
  11. atomically swap the staged profile into `browser.authSeedProfileDir`, keeping `*.prev` as rollback
145
146
  12. write a seed-generation marker used by future runtime clones
146
- 13. if ChatGPT presents a challenge page, leave the staged auth browser/profile open for the user to solve and reuse
147
+ 13. if the provider presents a challenge page, leave the staged auth browser/profile open for the user to solve and reuse
147
148
 
148
- This keeps production oracle jobs off the user’s real Chrome while using the user’s existing authenticated ChatGPT cookies as the bootstrap source.
149
+ This keeps production oracle jobs off the user’s real Chrome while using the user’s existing authenticated provider cookies as the bootstrap source.
149
150
 
150
151
  The authenticated seed profile remains the source of truth for future oracle runtimes.
151
152
 
152
153
  ### `oracle_submit`
153
154
 
154
- 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.
155
+ Agent-facing submissions resolve a provider first. ChatGPT submissions use **`preset`**; the canonical registry is `ORACLE_SUBMIT_PRESETS` in `extensions/oracle/lib/config.ts`. Grok submissions use **`mode: "heavy"`** today and reject ChatGPT-only presets. For ChatGPT, **`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 provider/model fields and using configured defaults unless the task or user explicitly asks for one. It also biases toward context-rich archives up to the provider 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.
155
156
 
156
- 1. resolve the preset (submit-time or config default) into an execution snapshot
157
+ 1. resolve the provider and preset/mode (submit-time or config default) into an execution snapshot
157
158
  2. resolve optional `followUpJobId` into a prior `chatUrl` and `conversationId`
158
159
  3. build the archive first into a temporary path
159
160
  4. allocate a unique runtime:
@@ -182,13 +183,13 @@ Per job:
182
183
  - headless by default
183
184
  3. open either:
184
185
  - the saved `chatUrl` for follow-up jobs, or
185
- - the configured default ChatGPT URL
186
+ - the configured provider URL
186
187
  4. classify page state before touching the UI
187
188
  5. fail fast on:
188
189
  - login required
189
190
  - challenge/verification page
190
191
  - transient outage after one retry
191
- 6. configure model family / effort
192
+ 6. configure ChatGPT model family/effort or Grok Heavy
192
193
  7. upload archive
193
194
  8. wait for upload confirmation scoped to the active composer
194
195
  9. fill prompt
@@ -205,7 +206,7 @@ Per job:
205
206
 
206
207
  Default and recommended:
207
208
 
208
- - auth seed via `--profile <authSeedProfileDir>` for durable ChatGPT authentication state
209
+ - auth seed via `--profile <authSeedProfileDir>` for durable provider authentication state
209
210
  - per-job runtime via unique `--session <runtimeSessionName>` + unique `--profile <runtimeProfileDir>`
210
211
 
211
212
  Not the default:
@@ -236,7 +237,9 @@ Browser/auth settings are global-only because they control local privileged brow
236
237
  ```json
237
238
  {
238
239
  "defaults": {
239
- "preset": "<preset id from ORACLE_SUBMIT_PRESETS>"
240
+ "provider": "chatgpt",
241
+ "preset": "<preset id from ORACLE_SUBMIT_PRESETS>",
242
+ "grokMode": "heavy"
240
243
  },
241
244
  "browser": {
242
245
  "sessionPrefix": "oracle",
@@ -287,11 +290,11 @@ When both `auth.chromeCookiePath` and `auth.chromiumKeychain` are present, auth
287
290
  2. snapshots the Chromium `Cookies` DB plus `Cookies-wal` / `Cookies-shm` sidecars, tolerating sidecars that disappear while the browser is closing
288
291
  3. decrypts Chromium AES-CBC cookie values, including Chromium v24+ host-hash-prefixed values
289
292
  4. dedupes duplicate cookie rows by keeping the first row after newest-expiry ordering
290
- 5. filters importable ChatGPT auth cookies and seeds the isolated oracle auth profile
293
+ 5. filters importable provider auth cookies and seeds the isolated oracle auth profile
291
294
 
292
295
  Operational requirements for this path:
293
296
 
294
- - ChatGPT must already be logged in in the configured browser profile.
297
+ - ChatGPT or Grok must already be logged in in the configured browser profile, depending on the provider being synced.
295
298
  - The target browser should be fully quit before `/oracle-auth` so the cookie DB snapshot is stable.
296
299
  - The configured Keychain item must be accessible to the current macOS user; allow Keychain access if prompted.
297
300
  - `browser.executablePath` should point at the same Chromium-family browser so the headed auth/bootstrap browser uses the intended app.
@@ -357,7 +360,7 @@ Important fields include:
357
360
  - `sessionId`
358
361
  - `originSessionFile`
359
362
  - `requestSource`
360
- - `selection`: resolved execution snapshot with `{ preset, modelFamily, effort?, autoSwitchToThinking }`
363
+ - `selection`: resolved execution snapshot with `{ provider, preset?, mode?, modelFamily, effort?, autoSwitchToThinking }`
361
364
  - `followUpToJobId`
362
365
  - `chatUrl`
363
366
  - `conversationId`
@@ -488,7 +491,7 @@ Same-thread continuity is persisted as data, not runtime browser state.
488
491
 
489
492
  Approach:
490
493
 
491
- - expose `/oracle-followup <job-id> <request>` as the user-facing way to continue the same ChatGPT thread later
494
+ - expose `/oracle-followup <job-id> <request>` as the user-facing way to continue the same provider thread later
492
495
  - store `chatUrl` only after the conversation URL stabilizes
493
496
  - derive and persist `conversationId` from that URL when possible
494
497
  - for a follow-up job, resolve `followUpJobId` to the prior `chatUrl`
@@ -4,12 +4,13 @@
4
4
  // Usage: Imported by oracle commands and tools whenever the shared oracle auth seed profile must be refreshed.
5
5
  // Invariants/Assumptions: Auth bootstrap runs under the global reconcile lock when available, uses the effective oracle config for the current workspace root, and returns the worker's stdout/stderr message verbatim on success or failure.
6
6
  import { spawn } from "node:child_process";
7
- import { formatOracleAuthConfigRemediation, formatOracleAuthConfigSummary, getOracleConfigLoadDetails, loadOracleConfig } from "./config.js";
7
+ import { formatOracleAuthConfigRemediation, formatOracleAuthConfigSummary, getOracleConfigLoadDetails, loadOracleConfig, resolveOracleConfigForProvider, type OracleProvider } from "./config.js";
8
8
  import { pruneTerminalOracleJobs, reconcileStaleOracleJobs } from "./jobs.js";
9
9
  import { isLockTimeoutError, withGlobalReconcileLock } from "./locks.js";
10
10
 
11
- export async function runOracleAuthBootstrap(authWorkerPath: string, cwd: string): Promise<string> {
12
- const config = loadOracleConfig(cwd);
11
+ export async function runOracleAuthBootstrap(authWorkerPath: string, cwd: string, provider?: OracleProvider): Promise<string> {
12
+ const baseConfig = loadOracleConfig(cwd);
13
+ const config = resolveOracleConfigForProvider(baseConfig, provider ?? baseConfig.defaults.provider);
13
14
  const configLoad = getOracleConfigLoadDetails(cwd);
14
15
  const authConfigGuidance = {
15
16
  ...configLoad,
@@ -8,6 +8,7 @@ import { readFile } from "node:fs/promises";
8
8
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
9
9
  import { formatOracleCancelOutcome, formatOracleJobSummary } from "../shared/job-observability-helpers.mjs";
10
10
  import { runOracleAuthBootstrap } from "./auth.js";
11
+ import type { OracleProvider } from "./config.js";
11
12
  import {
12
13
  cancelOracleJob,
13
14
  getJobDir,
@@ -65,13 +66,23 @@ function readScopedJob(jobId: string, cwd: string) {
65
66
  return job;
66
67
  }
67
68
 
69
+ function parseOracleAuthProvider(args: string): OracleProvider | undefined {
70
+ const value = args.trim().toLowerCase();
71
+ if (!value) return undefined;
72
+ if (value === "chatgpt" || value === "chat-gpt" || value === "openai") return "chatgpt";
73
+ if (value === "grok" || value === "xai" || value === "x.ai") return "grok";
74
+ throw new Error("Usage: /oracle-auth [chatgpt|grok]");
75
+ }
76
+
68
77
  export function registerOracleCommands(pi: ExtensionAPI, authWorkerPath: string, workerPath: string): void {
69
78
  pi.registerCommand("oracle-auth", {
70
- description: "Sync ChatGPT cookies from the configured local browser profile into the oracle auth seed profile",
71
- handler: async (_args, ctx) => {
72
- ctx.ui.notify("Syncing ChatGPT cookies from the configured local browser profile into the oracle auth seed profile…", "info");
79
+ description: "Sync ChatGPT or Grok cookies from the configured local browser profile into the provider auth seed profile",
80
+ handler: async (args, ctx) => {
73
81
  try {
74
- const result = await runOracleAuthBootstrap(authWorkerPath, ctx.cwd);
82
+ const provider = parseOracleAuthProvider(args);
83
+ const providerLabel = provider === "grok" ? "Grok" : provider === "chatgpt" ? "ChatGPT" : "configured provider";
84
+ ctx.ui.notify(`Syncing ${providerLabel} cookies from the configured local browser profile into the oracle auth seed profile…`, "info");
85
+ const result = await runOracleAuthBootstrap(authWorkerPath, ctx.cwd, provider);
75
86
  ctx.ui.notify(result, "info");
76
87
  } catch (error) {
77
88
  ctx.ui.notify(error instanceof Error ? error.message : String(error), "warning");
@@ -10,12 +10,18 @@ import { getAgentDir } from "@earendil-works/pi-coding-agent";
10
10
  import { isAbsolute, join, normalize } from "node:path";
11
11
  import { getProjectId } from "./runtime.js";
12
12
 
13
- export const MODEL_FAMILIES = ["instant", "thinking", "pro"] as const;
13
+ export const ORACLE_PROVIDERS = ["chatgpt", "grok"] as const;
14
+ export type OracleProvider = (typeof ORACLE_PROVIDERS)[number];
15
+
16
+ export const MODEL_FAMILIES = ["instant", "thinking", "pro", "grok"] as const;
14
17
  export type OracleModelFamily = (typeof MODEL_FAMILIES)[number];
15
18
 
16
19
  export const EFFORTS = ["light", "standard", "extended", "heavy"] as const;
17
20
  export type OracleEffort = (typeof EFFORTS)[number];
18
21
 
22
+ export const GROK_MODES = ["heavy"] as const;
23
+ export type OracleGrokMode = (typeof GROK_MODES)[number];
24
+
19
25
  /**
20
26
  * Canonical preset registry for `oracle_submit` preset selection.
21
27
  * This is the single authored source of truth — all derived lists come from `Object.keys(...)`.
@@ -156,7 +162,9 @@ export function getOracleSubmitPresetById(id: OracleSubmitPresetId): OracleSubmi
156
162
 
157
163
  /** Resolved execution snapshot generated from a preset at submit time. */
158
164
  export type OracleResolvedSelection = {
159
- preset: OracleSubmitPresetId;
165
+ provider: OracleProvider;
166
+ preset?: OracleSubmitPresetId;
167
+ mode?: OracleGrokMode;
160
168
  modelFamily: OracleModelFamily;
161
169
  effort?: OracleEffort;
162
170
  autoSwitchToThinking: boolean;
@@ -169,6 +177,7 @@ export type OracleResolvedSelection = {
169
177
  export function resolveOracleSubmitPreset(presetId: OracleSubmitPresetId): OracleResolvedSelection {
170
178
  const def = getOracleSubmitPresetById(presetId);
171
179
  return {
180
+ provider: "chatgpt",
172
181
  preset: presetId,
173
182
  modelFamily: def.modelFamily,
174
183
  effort: def.modelFamily === "instant" ? undefined : def.effort,
@@ -176,6 +185,37 @@ export function resolveOracleSubmitPreset(presetId: OracleSubmitPresetId): Oracl
176
185
  };
177
186
  }
178
187
 
188
+ export function resolveOracleGrokMode(mode: OracleGrokMode): OracleResolvedSelection {
189
+ return {
190
+ provider: "grok",
191
+ mode,
192
+ modelFamily: "grok",
193
+ effort: "heavy",
194
+ autoSwitchToThinking: false,
195
+ };
196
+ }
197
+
198
+ export function getProviderAuthSeedProfileDir(config: OracleConfig, provider: OracleProvider): string {
199
+ return provider === "grok" ? `${config.browser.authSeedProfileDir}-grok` : config.browser.authSeedProfileDir;
200
+ }
201
+
202
+ export function resolveOracleConfigForProvider(config: OracleConfig, provider: OracleProvider): OracleConfig {
203
+ if (provider === "chatgpt") return config;
204
+ return {
205
+ ...config,
206
+ defaults: {
207
+ ...config.defaults,
208
+ provider,
209
+ },
210
+ browser: {
211
+ ...config.browser,
212
+ authSeedProfileDir: getProviderAuthSeedProfileDir(config, provider),
213
+ chatUrl: "https://grok.com/",
214
+ authUrl: "https://grok.com/",
215
+ },
216
+ };
217
+ }
218
+
179
219
  export const BROWSER_RUN_MODES = ["headless", "headed"] as const;
180
220
  export type OracleBrowserRunMode = (typeof BROWSER_RUN_MODES)[number];
181
221
 
@@ -189,7 +229,9 @@ const DEFAULT_MAC_CHROME_USER_DATA_DIR = join(homedir(), "Library", "Application
189
229
 
190
230
  export interface OracleConfig {
191
231
  defaults: {
232
+ provider: OracleProvider;
192
233
  preset: OracleSubmitPresetId;
234
+ grokMode: OracleGrokMode;
193
235
  };
194
236
  browser: {
195
237
  sessionPrefix: string;
@@ -316,7 +358,9 @@ export function formatOracleAuthConfigSummary(details: OracleConfigLoadDetails):
316
358
 
317
359
  export const DEFAULT_CONFIG: OracleConfig = {
318
360
  defaults: {
361
+ provider: "chatgpt",
319
362
  preset: "pro_extended",
363
+ grokMode: "heavy",
320
364
  },
321
365
  browser: {
322
366
  sessionPrefix: "oracle",
@@ -529,7 +573,9 @@ function validateOracleConfig(value: unknown): OracleConfig {
529
573
  const root = normalizeLegacyBrowserConfig(expectObject(value, "root"));
530
574
 
531
575
  const defaults = expectObject(root.defaults, "defaults");
576
+ const provider = expectEnum(defaults.provider, "defaults.provider", ORACLE_PROVIDERS);
532
577
  const preset = expectEnum(defaults.preset, "defaults.preset", PRESET_IDS);
578
+ const grokMode = expectEnum(defaults.grokMode, "defaults.grokMode", GROK_MODES);
533
579
 
534
580
  const browser = expectObject(root.browser, "browser");
535
581
  const auth = expectObject(root.auth, "auth");
@@ -552,7 +598,9 @@ function validateOracleConfig(value: unknown): OracleConfig {
552
598
 
553
599
  return {
554
600
  defaults: {
601
+ provider,
555
602
  preset,
603
+ grokMode,
556
604
  },
557
605
  browser: {
558
606
  sessionPrefix: expectString(browser.sessionPrefix, "browser.sessionPrefix"),
@@ -943,7 +943,7 @@ export async function createJob(
943
943
  requestSource: input.requestSource,
944
944
  selection: input.selection,
945
945
  followUpToJobId: input.followUpToJobId,
946
- chatUrl: input.followUpToJobId ? input.chatUrl : undefined,
946
+ chatUrl: input.chatUrl,
947
947
  conversationId,
948
948
  responseFormat: "text/plain",
949
949
  artifactPaths: [],