pi-oracle 0.7.4 → 0.7.5
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 +18 -0
- package/README.md +51 -17
- package/docs/ORACLE_DESIGN.md +12 -5
- package/docs/platform-smoke.md +153 -0
- package/extensions/oracle/lib/config.ts +53 -27
- package/extensions/oracle/lib/jobs.ts +9 -5
- package/extensions/oracle/lib/runtime.ts +107 -32
- package/extensions/oracle/lib/tools.ts +138 -12
- package/extensions/oracle/shared/browser-profile-helpers.d.mts +59 -0
- package/extensions/oracle/shared/browser-profile-helpers.mjs +395 -0
- package/extensions/oracle/shared/process-helpers.mjs +12 -1
- package/extensions/oracle/shared/state-coordination-helpers.mjs +8 -2
- package/extensions/oracle/worker/auth-bootstrap.mjs +39 -10
- package/extensions/oracle/worker/chatgpt-ui-helpers.d.mts +2 -0
- package/extensions/oracle/worker/chatgpt-ui-helpers.mjs +157 -1
- package/extensions/oracle/worker/chromium-cookie-source.mjs +2 -1
- package/extensions/oracle/worker/run-job.mjs +107 -25
- package/package.json +27 -6
- package/platform-smoke.config.mjs +59 -0
- package/scripts/oracle-real-smoke.mjs +497 -0
- package/scripts/platform-smoke/Dockerfile.ubuntu +8 -0
- package/scripts/platform-smoke/artifacts.mjs +87 -0
- package/scripts/platform-smoke/assertions.mjs +34 -0
- package/scripts/platform-smoke/crabbox-runner.mjs +135 -0
- package/scripts/platform-smoke/doctor.mjs +239 -0
- package/scripts/platform-smoke/invariants.mjs +108 -0
- package/scripts/platform-smoke/platform-build-windows.ps1 +168 -0
- package/scripts/platform-smoke/targets.mjs +434 -0
- package/scripts/platform-smoke.mjs +149 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.7.5 - 2026-06-02
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- added a Crabbox platform release smoke gate for macOS, Ubuntu, and Windows native with doctor-first validation, packed-install real-extension proof, stop evidence, and platform artifacts
|
|
9
|
+
- added canonical workflow docs and scripts for everyday local validation, focused platform-sensitive runs, and full release/publish smoke coverage
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- made the default packed real smoke deterministic by installing the packed package into a clean pi project and invoking the installed `oracle_submit` tool path without waiting on a model-agent turn
|
|
13
|
+
- made Windows native a supported package OS and moved reusable Windows smoke dependencies into the Parallels template/snapshot workflow
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- hardened Windows archive/process/profile handling, including taskkill cleanup, executable resolution, tar/zstd archive behavior, path safety, and auth-bootstrap absolute-path checks
|
|
17
|
+
- removed production `as unknown as` casts and switched Linux/Windows runtime profile copies to Node recursive copy instead of relying on POSIX `cp`
|
|
18
|
+
|
|
19
|
+
### Validation
|
|
20
|
+
- verified `npm run verify:oracle`, `git diff --check`, and `npm run smoke:platform:all` across macOS, Ubuntu, and Windows native before release
|
|
21
|
+
|
|
5
22
|
## 0.7.4 - 2026-05-28
|
|
6
23
|
|
|
7
24
|
### Changed
|
|
@@ -66,6 +83,7 @@
|
|
|
66
83
|
|
|
67
84
|
### Changed
|
|
68
85
|
- made `/oracle-auth` success and failure output easier to scan, with compact source summaries and source-specific troubleshooting for configured Chromium cookie sources
|
|
86
|
+
- expanded package support to Linux, using ordinary profile copies off macOS and documenting `@steipete/sweet-cookie`'s Linux keyring/password options for Chromium cookie import
|
|
69
87
|
- tightened README quickstart/command wording around preflight-first `/oracle` behavior, context-rich archive selection, cleanup retention, and preset defaults
|
|
70
88
|
- added the resolved oracle model preset snapshot to `oracle_submit` queued/dispatched output so agents can see what preset will run
|
|
71
89
|
- clarified `oracle_preflight` output so users can see that it validates the persisted pi session, local config, and ChatGPT auth seed created by `oracle_auth`
|
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
|
|
5
|
+
> Status: experimental public beta. Validated on macOS, Linux, and Windows native with Chromium-family browsers and the current pi package baseline. Pi-bundled runtime packages are optional wildcard peers so npm peer ranges do not block users from trying newer pi releases, though runtime behavior is only verified against the tested baseline until a follow-up package release confirms it. 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
|
|
|
@@ -37,7 +37,7 @@ Do not use it for:
|
|
|
37
37
|
|
|
38
38
|
- short local coding tasks that `pi` can handle directly
|
|
39
39
|
- projects that must never be uploaded to ChatGPT.com, Grok, or another configured web provider
|
|
40
|
-
-
|
|
40
|
+
- machines outside the currently supported local browser/tooling setup
|
|
41
41
|
|
|
42
42
|
## Problem it solves
|
|
43
43
|
|
|
@@ -75,13 +75,15 @@ pi install https://github.com/fitchmultz/pi-oracle
|
|
|
75
75
|
|
|
76
76
|
You need:
|
|
77
77
|
|
|
78
|
-
- macOS
|
|
78
|
+
- macOS, Linux, or Windows native
|
|
79
79
|
- Node.js 22 or newer
|
|
80
80
|
- `pi` 0.65.0 or newer
|
|
81
|
-
- Google Chrome or another Chromium-family browser
|
|
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
|
|
84
|
+
- on macOS APFS clone mode, `cp` available on PATH or via `PI_ORACLE_CP_PATH`; Linux/Windows runtime profile copies use Node's recursive copy
|
|
84
85
|
- a normal persisted `pi` session, not `pi --no-session`
|
|
86
|
+
- on Linux, encrypted Chromium cookies may also require `secret-tool` (GNOME/libsecret) or `kwallet-query` + `dbus-send` (KDE), unless a Chrome/Brave safe-storage password override is set for the auth run
|
|
85
87
|
|
|
86
88
|
### 3. Sync provider auth once
|
|
87
89
|
|
|
@@ -202,11 +204,23 @@ Notes:
|
|
|
202
204
|
- 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`.
|
|
203
205
|
- You usually do not need browser paths unless auto-detection fails.
|
|
204
206
|
|
|
207
|
+
### Linux cookie import notes
|
|
208
|
+
|
|
209
|
+
`/oracle-auth` delegates the default cookie read to `@steipete/sweet-cookie`'s Linux Chrome/Chromium backend. The packaged default auto-detects existing Google Chrome, Chromium, Chromium Browser, or Brave profile roots under `${XDG_CONFIG_HOME:-~/.config}` and passes non-Google roots as absolute profile paths so the correct cookie DB is read. Set `auth.chromeProfile` to another profile name, a profile directory, or a `Cookies` DB path when needed, and leave `auth.chromiumKeychain` unset on Linux.
|
|
210
|
+
|
|
211
|
+
Sweet Cookie's Linux encrypted-cookie handling is controlled outside pi-oracle:
|
|
212
|
+
|
|
213
|
+
- `SWEET_COOKIE_LINUX_KEYRING=gnome|kwallet|basic` selects GNOME/libsecret, KDE KWallet, or no keyring probing.
|
|
214
|
+
- GNOME probing shells out to `secret-tool`; KDE probing shells out to `kwallet-query` and `dbus-send`.
|
|
215
|
+
- `SWEET_COOKIE_CHROME_SAFE_STORAGE_PASSWORD` and `SWEET_COOKIE_BRAVE_SAFE_STORAGE_PASSWORD` bypass keyring probing when you already know the browser safe-storage password.
|
|
216
|
+
|
|
217
|
+
Do not put safe-storage passwords in project config or persistent shell startup files. Prefer keyring helpers when possible; if you use an environment override for one `/oracle-auth` run, pi-oracle scrubs it before launching browser/helper subprocesses after cookie import.
|
|
218
|
+
|
|
205
219
|
### Custom Chromium cookie sources
|
|
206
220
|
|
|
207
|
-
|
|
221
|
+
Most Chrome/Chromium-compatible browsers should work through Sweet Cookie's default Chrome backend when `auth.chromeProfile` points at the right profile or cookie DB. pi-oracle does not currently select Sweet Cookie's Edge or Firefox backends. The `auth.chromiumKeychain` alternate path is macOS-only and is intended for a Chromium-family browser that is not one of Sweet Cookie's built-in Chrome/Brave/Arc/Chromium targets or otherwise cannot import cookies without dependency patching.
|
|
208
222
|
|
|
209
|
-
Before running `/oracle-auth` with this path:
|
|
223
|
+
Before running `/oracle-auth` with this macOS path:
|
|
210
224
|
|
|
211
225
|
1. Log into ChatGPT or Grok in the target browser profile, depending on `defaults.provider`.
|
|
212
226
|
2. Fully quit the browser so its `Cookies` database is stable.
|
|
@@ -214,7 +228,7 @@ Before running `/oracle-auth` with this path:
|
|
|
214
228
|
4. Find the browser's macOS Keychain safe-storage item account and service name.
|
|
215
229
|
5. Configure all of `browser.executablePath`, `auth.chromeCookiePath`, and `auth.chromiumKeychain` in `~/.pi/agent/extensions/oracle.json`.
|
|
216
230
|
|
|
217
|
-
Example Helium config:
|
|
231
|
+
Example macOS Helium config:
|
|
218
232
|
|
|
219
233
|
```json
|
|
220
234
|
{
|
|
@@ -233,7 +247,9 @@ Example Helium config:
|
|
|
233
247
|
}
|
|
234
248
|
```
|
|
235
249
|
|
|
236
|
-
`auth.chromeCookiePath` must be paired with `auth.
|
|
250
|
+
`auth.chromeCookiePath` remains the cookie database path for backward compatibility. On macOS, `auth.chromiumKeychain` must be paired with `auth.chromeCookiePath`; partial config is rejected so oracle does not silently fall back to a different browser source. When both are present on macOS, `/oracle-auth` uses pi-oracle's repo-owned generic Chromium cookie reader instead of patching `@steipete/sweet-cookie` internals. On Linux, `auth.chromiumKeychain` is rejected; use Sweet Cookie's Linux keyring/password environment options instead.
|
|
251
|
+
|
|
252
|
+
If macOS prompts for Keychain access during `/oracle-auth`, allow access for the configured browser safe-storage item. If auth still fails after cookies are synced, the cookie DB may be stale, from the wrong profile, or for an account that is logged out; reopen the configured browser profile, confirm ChatGPT works there, quit the browser, and rerun `/oracle-auth`. On Linux, inspect `/oracle-auth` diagnostics for Sweet Cookie warnings about `secret-tool`, `kwallet-query`, or safe-storage password overrides.
|
|
237
253
|
|
|
238
254
|
## Available providers and presets
|
|
239
255
|
|
|
@@ -279,19 +295,19 @@ Review the code and design docs before using it with private or regulated materi
|
|
|
279
295
|
|
|
280
296
|
## Current limits
|
|
281
297
|
|
|
282
|
-
- Experimental public beta, validated
|
|
298
|
+
- Experimental public beta, validated on macOS, Linux, and Windows native with Chromium-family browsers.
|
|
283
299
|
- Provider UI, auth, model controls, and artifact download behavior can drift.
|
|
284
300
|
- Archive uploads are capped at 250 MiB for ChatGPT and 200 MiB for Grok after default exclusions and automatic whole-repo pruning.
|
|
285
301
|
- A real ChatGPT or Grok web session is required for the provider you use.
|
|
286
302
|
- The README currently uses command-level proof and design docs; no public screenshot or demo GIF is checked into the repo.
|
|
287
|
-
- Production hardening should keep focusing on UI drift detection, auth recovery, artifact capture, and environment diagnostics.
|
|
303
|
+
- Production hardening should keep focusing on UI drift detection, auth recovery, artifact capture, platform compatibility, and environment diagnostics.
|
|
288
304
|
|
|
289
305
|
## Troubleshooting
|
|
290
306
|
|
|
291
307
|
### `/oracle-auth` fails or says login is required
|
|
292
308
|
|
|
293
309
|
- Make sure the selected provider works in the same local browser profile you configured.
|
|
294
|
-
- For custom Chromium cookie sources, confirm `auth.chromeCookiePath` points at that profile's `Cookies` DB
|
|
310
|
+
- For custom Chromium cookie sources, confirm `auth.chromeCookiePath` points at that profile's `Cookies` DB. On macOS, also confirm `auth.chromiumKeychain.services` names the browser's safe-storage Keychain service. On Linux, leave `auth.chromiumKeychain` unset and use Sweet Cookie's `SWEET_COOKIE_LINUX_KEYRING`, `SWEET_COOKIE_CHROME_SAFE_STORAGE_PASSWORD`, or `SWEET_COOKIE_BRAVE_SAFE_STORAGE_PASSWORD` options for encrypted Chrome/Chromium/Brave cookies.
|
|
295
311
|
- Re-run `/oracle-auth`.
|
|
296
312
|
- Agent callers can use `oracle_auth({})` once before retrying a stale-auth oracle submission.
|
|
297
313
|
- If the provider is half-logged-in or challenge flow state looks weird, finish the login/challenge in the headed auth browser and retry.
|
|
@@ -304,7 +320,7 @@ This usually means the cookie import worked but the source cookies are not the a
|
|
|
304
320
|
2. Confirm the selected provider works there without logging in again.
|
|
305
321
|
3. Quit the browser fully so its `Cookies` DB is stable.
|
|
306
322
|
4. Confirm `auth.chromeCookiePath` points at that exact profile's `Cookies` DB.
|
|
307
|
-
5.
|
|
323
|
+
5. On macOS, confirm `auth.chromiumKeychain.services` names the browser's safe-storage Keychain service for that DB. On Linux, confirm the relevant Sweet Cookie keyring helper or Chrome/Brave safe-storage password override is available.
|
|
308
324
|
6. Re-run `/oracle-auth`.
|
|
309
325
|
|
|
310
326
|
### You hit a challenge or verification page
|
|
@@ -330,14 +346,14 @@ This usually means the cookie import worked but the source cookies are not the a
|
|
|
330
346
|
- The command returns a `Retry after ...` timestamp when that guard is active.
|
|
331
347
|
- Wait until that time, then rerun `/oracle-clean <job-id|all>`.
|
|
332
348
|
|
|
333
|
-
### `agent-browser`, `tar`, or `zstd` is missing
|
|
349
|
+
### A local dependency like `agent-browser`, `tar`, or `zstd` is missing
|
|
334
350
|
|
|
335
|
-
Install the missing local dependency and rerun the command.
|
|
351
|
+
Install the missing local dependency and rerun the command. On macOS APFS clone mode, `cp` must also be available on PATH or configured with `PI_ORACLE_CP_PATH`; Linux and Windows profile copies use Node's recursive copy.
|
|
336
352
|
|
|
337
353
|
### Auto-detection picked the wrong browser profile
|
|
338
354
|
|
|
339
355
|
- Set `auth.chromeProfile` in `~/.pi/agent/extensions/oracle.json`.
|
|
340
|
-
- For custom Chromium cookie sources, set `auth.chromeCookiePath` to the exact profile `Cookies` DB
|
|
356
|
+
- For custom Chromium cookie sources, set `auth.chromeCookiePath` to the exact profile `Cookies` DB. Pair it with `auth.chromiumKeychain` only on macOS; on Linux, rely on Sweet Cookie's keyring/password environment options.
|
|
341
357
|
- Re-run `/oracle-auth`.
|
|
342
358
|
|
|
343
359
|
### You want more details about a failed run
|
|
@@ -350,6 +366,7 @@ Useful local checks:
|
|
|
350
366
|
|
|
351
367
|
```bash
|
|
352
368
|
npm run check:oracle-extension
|
|
369
|
+
npm run check:platform-smoke
|
|
353
370
|
npm run typecheck
|
|
354
371
|
npm run typecheck:worker-helpers
|
|
355
372
|
npm run sanity:oracle
|
|
@@ -358,9 +375,25 @@ npm test
|
|
|
358
375
|
npm run verify:oracle
|
|
359
376
|
```
|
|
360
377
|
|
|
361
|
-
`npm publish` is guarded by `prepublishOnly`, which runs `npm run
|
|
378
|
+
`npm publish` is guarded by `prepublishOnly`, which runs `npm run release:check`. That release gate requires doctor-first macOS, Ubuntu, and Windows native Crabbox evidence. The required Crabbox runtime suite uses packed-install proof, not source-tree `pi -e` loading.
|
|
379
|
+
|
|
380
|
+
Use the narrowest validation workflow that proves the change:
|
|
381
|
+
|
|
382
|
+
| Situation | Command(s) |
|
|
383
|
+
| --- | --- |
|
|
384
|
+
| Everyday local iteration | `npm run verify:oracle` |
|
|
385
|
+
| Platform-sensitive changes | `npm run smoke:platform:doctor`, then a focused `node scripts/platform-smoke.mjs run --target <target> --suite <suite>` |
|
|
386
|
+
| Publish/release proof | `npm run smoke:platform:all` |
|
|
387
|
+
|
|
388
|
+
For macOS, Ubuntu, and Windows native package/build plus packed runtime validation, use [`docs/platform-smoke.md`](docs/platform-smoke.md). The full release proof is:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
npm run smoke:platform:all
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
The real runtime suite defaults to deterministic installed-tool execution so platform proof stays bounded. Provider/model defaults remain `zai/glm-5.1` for doctor/config and for optional model-agent debugging; override with `PI_ORACLE_REAL_TEST_PROVIDER` and `PI_ORACLE_REAL_TEST_MODEL` when needed. For inner-loop source loading only, use `npm run smoke:real:source`; it is not release proof. Set `PI_ORACLE_REAL_TEST_MODEL_AGENT=1` only when debugging the slower model-agent path. The optional second real-agent negative symlink check is opt-in via `PI_ORACLE_REAL_TEST_NEGATIVE_SYMLINK=1`; `npm run sanity:oracle` covers archive/symlink rejection by default without adding another model-agent turn to the platform release gate.
|
|
362
395
|
|
|
363
|
-
For end-to-end local-extension smoke testing, use [`docs/ORACLE_ISOLATED_PI_VALIDATION.md`](docs/ORACLE_ISOLATED_PI_VALIDATION.md). That workflow launches isolated `pi` sessions against this checkout and uses `instant` or `thinking_light`, as required by the project validation policy.
|
|
396
|
+
For manual end-to-end local-extension smoke testing, use [`docs/ORACLE_ISOLATED_PI_VALIDATION.md`](docs/ORACLE_ISOLATED_PI_VALIDATION.md). That workflow launches isolated `pi` coding-agent sessions against this checkout and uses `instant` or `thinking_light`, as required by the project validation policy.
|
|
364
397
|
|
|
365
398
|
## Project map
|
|
366
399
|
|
|
@@ -373,6 +406,7 @@ For end-to-end local-extension smoke testing, use [`docs/ORACLE_ISOLATED_PI_VALI
|
|
|
373
406
|
| [`prompts/oracle.md`](prompts/oracle.md) | `/oracle` prompt-template workflow |
|
|
374
407
|
| [`prompts/oracle-followup.md`](prompts/oracle-followup.md) | `/oracle-followup` prompt-template workflow |
|
|
375
408
|
| `scripts/oracle-sanity-*` | Local sanity and archive-safety checks |
|
|
409
|
+
| `scripts/platform-smoke*` | Crabbox macOS, Ubuntu, and Windows release smoke gate |
|
|
376
410
|
| [`docs/ORACLE_DESIGN.md`](docs/ORACLE_DESIGN.md) | Architecture, lifecycle, queueing, persistence, recovery behavior |
|
|
377
411
|
| [`docs/ORACLE_ISOLATED_PI_VALIDATION.md`](docs/ORACLE_ISOLATED_PI_VALIDATION.md) | Repeatable isolated `pi` validation workflow |
|
|
378
412
|
| [`docs/ORACLE_RECOVERY_DRILL.md`](docs/ORACLE_RECOVERY_DRILL.md) | Safe expired-auth recovery drill |
|
package/docs/ORACLE_DESIGN.md
CHANGED
|
@@ -246,7 +246,7 @@ Browser/auth settings are global-only because they control local privileged brow
|
|
|
246
246
|
"authSeedProfileDir": "<absolute path to oracle auth seed profile>",
|
|
247
247
|
"runtimeProfilesDir": "<absolute path to oracle runtime profiles dir>",
|
|
248
248
|
"maxConcurrentJobs": 2,
|
|
249
|
-
"cloneStrategy": "
|
|
249
|
+
"cloneStrategy": "copy",
|
|
250
250
|
"chatUrl": "https://chatgpt.com/",
|
|
251
251
|
"authUrl": "https://chatgpt.com/auth/login",
|
|
252
252
|
"runMode": "headless",
|
|
@@ -260,7 +260,7 @@ Browser/auth settings are global-only because they control local privileged brow
|
|
|
260
260
|
"chromeProfile": "<optional Chrome/Chromium profile name>",
|
|
261
261
|
"chromeCookiePath": "<optional absolute path to Chromium Cookies DB>",
|
|
262
262
|
"chromiumKeychain": {
|
|
263
|
-
"account": "<macOS Keychain account for non-built-in Chromium browsers>",
|
|
263
|
+
"account": "<macOS-only Keychain account for non-built-in Chromium browsers>",
|
|
264
264
|
"services": ["<safe-storage service name>"],
|
|
265
265
|
"label": "<optional human-readable label>"
|
|
266
266
|
}
|
|
@@ -282,9 +282,13 @@ Browser/auth settings are global-only because they control local privileged brow
|
|
|
282
282
|
}
|
|
283
283
|
```
|
|
284
284
|
|
|
285
|
-
`
|
|
285
|
+
`browser.cloneStrategy` defaults to `apfs-clone` on macOS and `copy` on Linux/Windows. macOS APFS clone mode uses `cp -cR` and preflights `cp`; set `PI_ORACLE_CP_PATH` only when the default PATH lookup cannot find the intended copy executable. Linux and Windows runtime profile copies use Node's recursive copy instead of depending on POSIX `cp`.
|
|
286
286
|
|
|
287
|
-
|
|
287
|
+
The default `/oracle-auth` cookie importer delegates to `@steipete/sweet-cookie`'s Chrome/Chromium backend. On Linux, pi-oracle auto-detects existing Google Chrome, Chromium, Chromium Browser, or Brave profile roots under `${XDG_CONFIG_HOME:-~/.config}` and passes non-Google roots as absolute profile paths so Sweet Cookie reads the intended cookie DB. pi-oracle does not currently select Sweet Cookie's Edge or Firefox backends. Encrypted Linux Chromium cookies are handled by Sweet Cookie via `secret-tool`, `kwallet-query`/`dbus-send`, `SWEET_COOKIE_LINUX_KEYRING=gnome|kwallet|basic`, or the `SWEET_COOKIE_CHROME_SAFE_STORAGE_PASSWORD` / `SWEET_COOKIE_BRAVE_SAFE_STORAGE_PASSWORD` overrides. Prefer keyring helpers over password environment variables; if a password override is used for `/oracle-auth`, pi-oracle scrubs it before launching browser/helper subprocesses after cookie import.
|
|
288
|
+
|
|
289
|
+
`auth.chromiumKeychain` is a macOS-only opt-in alternate cookie source for Chromium-family browsers that are not handled by the default `@steipete/sweet-cookie` Chrome-compatible importer. It must be configured with `auth.chromeCookiePath`; partial config is rejected so `/oracle-auth` cannot silently fall back to a different browser profile. On Linux, valid config should leave `auth.chromiumKeychain` unset and use Sweet Cookie's Linux keyring/password options instead.
|
|
290
|
+
|
|
291
|
+
When both `auth.chromeCookiePath` and `auth.chromiumKeychain` are present on macOS, auth bootstrap:
|
|
288
292
|
|
|
289
293
|
1. reads the configured macOS Keychain safe-storage password using `account` and the ordered `services` list
|
|
290
294
|
2. snapshots the Chromium `Cookies` DB plus `Cookies-wal` / `Cookies-shm` sidecars, tolerating sidecars that disappear while the browser is closing
|
|
@@ -292,7 +296,7 @@ When both `auth.chromeCookiePath` and `auth.chromiumKeychain` are present, auth
|
|
|
292
296
|
4. dedupes duplicate cookie rows by keeping the first row after newest-expiry ordering
|
|
293
297
|
5. filters importable provider auth cookies and seeds the isolated oracle auth profile
|
|
294
298
|
|
|
295
|
-
Operational requirements for this path:
|
|
299
|
+
Operational requirements for this macOS-only path:
|
|
296
300
|
|
|
297
301
|
- ChatGPT or Grok must already be logged in in the configured browser profile, depending on the provider being synced.
|
|
298
302
|
- The target browser should be fully quit before `/oracle-auth` so the cookie DB snapshot is stable.
|
|
@@ -633,3 +637,6 @@ Recent proof points:
|
|
|
633
637
|
- expired-auth drill post-repair success: `fa26a2a7-0057-4a21-b3e0-71c1d020facf`
|
|
634
638
|
- successful multi-artifact completion: `b6b3599c-6b91-4315-adfa-8a83aa5eda9b`
|
|
635
639
|
- repo-owned sanity harness: `npm run sanity:oracle`
|
|
640
|
+
- real installed-extension smoke source of truth: `scripts/oracle-real-smoke.mjs`; required release proof runs packed-install mode (`npm run smoke:real:packed`) and executes installed-package `oracle_submit` deterministically, with optional slower model-agent debugging via `PI_ORACLE_REAL_TEST_MODEL_AGENT=1`; source mode (`npm run smoke:real:source`) is inner-loop/debug only
|
|
641
|
+
- macOS, Ubuntu, and Windows native package/build/runtime smoke source of truth: `docs/platform-smoke.md`; use `npm run verify:oracle` for everyday local iteration, `npm run smoke:platform:doctor` plus a focused target/suite run for platform-sensitive changes, and `npm run smoke:platform:all` for doctor-first packed-install Crabbox release evidence
|
|
642
|
+
- release gate: `npm run release:check`, also used by `prepublishOnly`, combines static verification and all required Crabbox platform smokes
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# pi-oracle Crabbox platform smoke
|
|
2
|
+
|
|
3
|
+
`pi-oracle` uses Crabbox for the local release-blocking platform gate. The gate runs on macOS, Ubuntu Linux, and native Windows and is meant to catch broken package installs, platform assumptions, and real `pi` tool-call failures before push or publish.
|
|
4
|
+
|
|
5
|
+
## Source of truth
|
|
6
|
+
|
|
7
|
+
- Config: [`../platform-smoke.config.mjs`](../platform-smoke.config.mjs)
|
|
8
|
+
- CLI: [`../scripts/platform-smoke.mjs`](../scripts/platform-smoke.mjs)
|
|
9
|
+
- Target runner: [`../scripts/platform-smoke/targets.mjs`](../scripts/platform-smoke/targets.mjs)
|
|
10
|
+
- Windows build script: [`../scripts/platform-smoke/platform-build-windows.ps1`](../scripts/platform-smoke/platform-build-windows.ps1)
|
|
11
|
+
- Real runtime smoke: [`../scripts/oracle-real-smoke.mjs`](../scripts/oracle-real-smoke.mjs)
|
|
12
|
+
- Artifact root: `.artifacts/platform-smoke/` (gitignored)
|
|
13
|
+
|
|
14
|
+
Required targets: `macos`, `ubuntu`, `windows-native`.
|
|
15
|
+
Required suites: `platform-build`, `real-extension`.
|
|
16
|
+
Crabbox baseline: `0.24.0` or newer.
|
|
17
|
+
|
|
18
|
+
## Required local setup
|
|
19
|
+
|
|
20
|
+
Install Crabbox with Homebrew and keep it on `PATH`:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
brew install openclaw/tap/crabbox
|
|
24
|
+
crabbox --version
|
|
25
|
+
crabbox providers
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`PI_ORACLE_SMOKE_CRABBOX` is optional and only needed to override the binary path.
|
|
29
|
+
|
|
30
|
+
Target setup:
|
|
31
|
+
|
|
32
|
+
- macOS: Remote Login enabled; noninteractive `ssh $USER@localhost` works; `node`, `npm`, `git`, `tar`, `rsync`, `zstd`, and `agent-browser` are on the SSH PATH.
|
|
33
|
+
- Ubuntu: Docker is running and the configured image (`PI_ORACLE_SMOKE_UBUNTU_IMAGE`, default `pi-oracle-platform-smoke:node24`) has `node`, `npm`, `git`, `tar`, `rsync`, `zstd`, and `agent-browser` on PATH. Build the local image when needed with `docker build -t pi-oracle-platform-smoke:node24 -f scripts/platform-smoke/Dockerfile.ubuntu .`.
|
|
34
|
+
- Windows native: Parallels has stopped source VM `pi-extension-windows-template` and the configured power-off snapshot (`crabbox-ready` by default for this repo). The template must have OpenSSH, PowerShell, Git, Node/npm, `tar`, `zstd`, and `agent-browser` on PATH. Do not bake API keys, browser sessions, project checkouts, `.pi` state, artifacts, or secrets into the template.
|
|
35
|
+
|
|
36
|
+
Real runtime suite auth:
|
|
37
|
+
|
|
38
|
+
- Default deterministic installed-tool smoke does not require provider API keys.
|
|
39
|
+
- Provider/model defaults remain `zai/glm-5.1` for optional model-agent debugging.
|
|
40
|
+
- Set `PI_ORACLE_REAL_TEST_MODEL_AGENT=1` to run the slower model-agent path; then the provider auth env is required (`ZAI_API_KEY` by default, reported only as present/redacted).
|
|
41
|
+
- Override with `PI_ORACLE_REAL_TEST_PROVIDER` and `PI_ORACLE_REAL_TEST_MODEL`; auth variable names live in `platform-smoke.config.mjs`.
|
|
42
|
+
|
|
43
|
+
## Canonical validation workflows
|
|
44
|
+
|
|
45
|
+
Use the narrowest workflow that proves the change. Do not run the full platform matrix for ordinary edits when the local gate and cheap invariants prove the change.
|
|
46
|
+
|
|
47
|
+
| Situation | Canonical command(s) | What it proves |
|
|
48
|
+
| --- | --- | --- |
|
|
49
|
+
| Everyday local iteration | `npm run verify:oracle` | Syntax, bundle, platform-smoke invariants, type checks, oracle sanity, and package dry-run pass locally. |
|
|
50
|
+
| Platform-sensitive change | `npm run smoke:platform:doctor`, then `node scripts/platform-smoke.mjs run --target <target> --suite <suite>` | Target setup is ready and the affected platform/suite works without paying for unrelated targets. |
|
|
51
|
+
| Publish/release proof | `npm run smoke:platform:all` | Doctor-first packed-install proof passes on every required target and suite. |
|
|
52
|
+
|
|
53
|
+
Platform-sensitive changes include archive behavior, process cleanup, runtime/browser profile handling, package metadata, Crabbox harness code, or anything that may differ across macOS/Linux/Windows.
|
|
54
|
+
|
|
55
|
+
## Commands
|
|
56
|
+
|
|
57
|
+
Doctor is mandatory before the full release matrix. The canonical all-target release command enforces that:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npm run smoke:platform:all
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Focused commands:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run smoke:platform:doctor
|
|
67
|
+
npm run smoke:platform:macos
|
|
68
|
+
npm run smoke:platform:ubuntu
|
|
69
|
+
npm run smoke:platform:windows-native
|
|
70
|
+
node scripts/platform-smoke.mjs run --target windows-native --suite real-extension
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Release check:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm run release:check
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`prepublishOnly` runs `npm run release:check`.
|
|
80
|
+
|
|
81
|
+
## What `platform-build` proves
|
|
82
|
+
|
|
83
|
+
On each required target, `platform-build`:
|
|
84
|
+
|
|
85
|
+
1. checks Node major version against `nodeValidationMajor`;
|
|
86
|
+
2. runs `npm ci`;
|
|
87
|
+
3. requires target tools (`zstd`, `agent-browser`) to already be available from target setup;
|
|
88
|
+
4. runs `npm run verify:oracle:platform`, the platform-focused gate for syntax, platform-smoke invariants, real-smoke script syntax, platform-sensitive oracle sanity coverage, and package dry-run;
|
|
89
|
+
5. runs `npm pack`;
|
|
90
|
+
6. creates a fresh target-local pi project;
|
|
91
|
+
7. runs `npm install --no-save <packed tarball>`;
|
|
92
|
+
8. runs `pi install -l ./node_modules/pi-oracle`;
|
|
93
|
+
9. runs `pi list`;
|
|
94
|
+
10. asserts the installed package came from `node_modules/pi-oracle` and did not use `pi -e` / source-extension shortcuts.
|
|
95
|
+
|
|
96
|
+
## What `real-extension` proves
|
|
97
|
+
|
|
98
|
+
`real-extension` is required release proof. It runs `npm run smoke:real:packed` on each target, which:
|
|
99
|
+
|
|
100
|
+
1. packs this checkout with `npm pack`;
|
|
101
|
+
2. installs the tarball into a clean pi project;
|
|
102
|
+
3. runs `pi install -l ./node_modules/pi-oracle`;
|
|
103
|
+
4. asserts `pi list` shows the packed install path;
|
|
104
|
+
5. executes `oracle_submit` from the installed package path, not source `pi -e`;
|
|
105
|
+
6. asserts whole-project archive creation and default exclusions.
|
|
106
|
+
|
|
107
|
+
The default runtime suite executes the installed tool directly so platform proof is deterministic and bounded instead of waiting on a model turn. Set `PI_ORACLE_REAL_TEST_MODEL_AGENT=1` only when you specifically need to debug the slower model-agent path. Symlink escape rejection and other negative archive cases are covered by `npm run sanity:oracle`; the optional second-agent negative check is available with `PI_ORACLE_REAL_TEST_NEGATIVE_SYMLINK=1` when debugging that path.
|
|
108
|
+
|
|
109
|
+
For inner-loop/debug only, use:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npm run smoke:real:source
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
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
|
+
|
|
117
|
+
## Artifacts
|
|
118
|
+
|
|
119
|
+
Each suite writes reviewable evidence under:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
.artifacts/platform-smoke/<run-id>/<target>/<suite>/
|
|
123
|
+
summary.json
|
|
124
|
+
target.json
|
|
125
|
+
suite.json
|
|
126
|
+
command.txt
|
|
127
|
+
exit-code.txt
|
|
128
|
+
crabbox.stdout.txt
|
|
129
|
+
crabbox.stderr.txt
|
|
130
|
+
crabbox.timing.json
|
|
131
|
+
crabbox.stop.stdout.txt
|
|
132
|
+
crabbox.stop.stderr.txt
|
|
133
|
+
crabbox.stop.exit-code.txt
|
|
134
|
+
assertions.json
|
|
135
|
+
artifact-manifest.json
|
|
136
|
+
failures.md # only on failure
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`platform-build` also writes packed install extracts (`packed-tarball.txt`, `packed-node-install.*`, `pi-install.*`, `pi-list.*`). Passing suites require `summary.ok === true`, `assertions.ok === true`, and `artifact-manifest.missing.length === 0`.
|
|
140
|
+
|
|
141
|
+
Artifacts are local evidence only. Do not commit or share them without redaction. Secret scans fail on bearer/API-key/cookie-like values.
|
|
142
|
+
|
|
143
|
+
## Windows template maintenance
|
|
144
|
+
|
|
145
|
+
When Windows lacks a reusable tool such as `zstd` or `agent-browser`, update `pi-extension-windows-template` rather than adding a per-run installer:
|
|
146
|
+
|
|
147
|
+
1. boot `pi-extension-windows-template`;
|
|
148
|
+
2. install/update the tool globally without secrets;
|
|
149
|
+
3. verify from a fresh SSH session: `node --version`, `npm --version`, `git --version`, `tar --version`, `zstd --version`, `agent-browser --version`;
|
|
150
|
+
4. remove downloads, caches, checkouts, `.pi`, `.artifacts`, `.debug`, and secrets;
|
|
151
|
+
5. shut down cleanly;
|
|
152
|
+
6. create/promote the configured power-off snapshot;
|
|
153
|
+
7. clean stale clones/leases.
|
|
@@ -8,6 +8,15 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { isAbsolute, join, normalize } from "node:path";
|
|
11
|
+
import {
|
|
12
|
+
assertNotKnownBrowserUserDataPath,
|
|
13
|
+
chromeUserAgentPlatformToken,
|
|
14
|
+
chromiumKeychainSupportedOnPlatform,
|
|
15
|
+
defaultCloneStrategyForPlatform,
|
|
16
|
+
detectDefaultBrowserProfileSource,
|
|
17
|
+
detectDefaultLinuxChromeExecutablePath,
|
|
18
|
+
sweetCookieSafeStoragePasswordScrubbedEnv,
|
|
19
|
+
} from "../shared/browser-profile-helpers.mjs";
|
|
11
20
|
import { getProjectId } from "./runtime.js";
|
|
12
21
|
|
|
13
22
|
export const ORACLE_PROVIDERS = ["chatgpt", "grok"] as const;
|
|
@@ -225,7 +234,6 @@ export type OracleCloneStrategy = (typeof CLONE_STRATEGIES)[number];
|
|
|
225
234
|
const ALLOWED_CHATGPT_ORIGINS = new Set(["https://chatgpt.com", "https://chat.openai.com"]);
|
|
226
235
|
const PROJECT_OVERRIDE_KEYS = new Set(["defaults", "worker", "poller", "artifacts", "cleanup"]);
|
|
227
236
|
const DEFAULT_MAC_CHROME_EXECUTABLE = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
|
|
228
|
-
const DEFAULT_MAC_CHROME_USER_DATA_DIR = join(homedir(), "Library", "Application Support", "Google", "Chrome");
|
|
229
237
|
|
|
230
238
|
export interface OracleConfig {
|
|
231
239
|
defaults: {
|
|
@@ -274,37 +282,36 @@ export interface OracleConfig {
|
|
|
274
282
|
}
|
|
275
283
|
|
|
276
284
|
function detectDefaultChromeExecutablePath(): string | undefined {
|
|
277
|
-
|
|
285
|
+
if (process.platform === "darwin") {
|
|
286
|
+
return existsSync(DEFAULT_MAC_CHROME_EXECUTABLE) ? DEFAULT_MAC_CHROME_EXECUTABLE : undefined;
|
|
287
|
+
}
|
|
288
|
+
if (process.platform === "linux") {
|
|
289
|
+
return detectDefaultLinuxChromeExecutablePath();
|
|
290
|
+
}
|
|
291
|
+
return undefined;
|
|
278
292
|
}
|
|
279
293
|
|
|
280
294
|
function detectDefaultChromeUserAgent(executablePath: string | undefined): string | undefined {
|
|
281
295
|
if (!executablePath) return undefined;
|
|
296
|
+
// Linux executable discovery is PATH-based, so avoid executing that discovered
|
|
297
|
+
// binary during config module initialization just to derive a user agent.
|
|
298
|
+
if (process.platform === "linux") return undefined;
|
|
299
|
+
const platformToken = chromeUserAgentPlatformToken(process.platform);
|
|
300
|
+
if (!platformToken) return undefined;
|
|
282
301
|
try {
|
|
283
|
-
const versionOutput = execFileSync(executablePath, ["--version"], { encoding: "utf8" }).trim();
|
|
302
|
+
const versionOutput = execFileSync(executablePath, ["--version"], { encoding: "utf8", env: sweetCookieSafeStoragePasswordScrubbedEnv() }).trim();
|
|
284
303
|
const versionMatch = versionOutput.match(/(\d+\.\d+\.\d+\.\d+)/);
|
|
285
304
|
if (!versionMatch) return undefined;
|
|
286
|
-
return `Mozilla/5.0 (
|
|
305
|
+
return `Mozilla/5.0 (${platformToken}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${versionMatch[1]} Safari/537.36`;
|
|
287
306
|
} catch {
|
|
288
307
|
return undefined;
|
|
289
308
|
}
|
|
290
309
|
}
|
|
291
310
|
|
|
292
|
-
function detectDefaultChromeProfileName(): string {
|
|
293
|
-
const localStatePath = join(DEFAULT_MAC_CHROME_USER_DATA_DIR, "Local State");
|
|
294
|
-
if (!existsSync(localStatePath)) return "Default";
|
|
295
|
-
try {
|
|
296
|
-
const localState = JSON.parse(readFileSync(localStatePath, "utf8")) as { profile?: { last_used?: string } };
|
|
297
|
-
const lastUsed = localState?.profile?.last_used;
|
|
298
|
-
return typeof lastUsed === "string" && lastUsed.trim() ? lastUsed.trim() : "Default";
|
|
299
|
-
} catch {
|
|
300
|
-
return "Default";
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
311
|
const detectedChromeExecutablePath = detectDefaultChromeExecutablePath();
|
|
305
312
|
const detectedChromeUserAgent = detectDefaultChromeUserAgent(detectedChromeExecutablePath);
|
|
306
313
|
const agentExtensionsDir = join(getAgentDir(), "extensions");
|
|
307
|
-
const detectedChromeProfileName =
|
|
314
|
+
const detectedChromeProfileName = detectDefaultBrowserProfileSource(process.platform);
|
|
308
315
|
|
|
309
316
|
export interface OracleConfigLoadDetails {
|
|
310
317
|
agentDir: string;
|
|
@@ -367,7 +374,7 @@ export const DEFAULT_CONFIG: OracleConfig = {
|
|
|
367
374
|
authSeedProfileDir: join(agentExtensionsDir, "oracle-auth-seed-profile"),
|
|
368
375
|
runtimeProfilesDir: join(agentExtensionsDir, "oracle-runtime-profiles"),
|
|
369
376
|
maxConcurrentJobs: 2,
|
|
370
|
-
cloneStrategy:
|
|
377
|
+
cloneStrategy: defaultCloneStrategyForPlatform(process.platform),
|
|
371
378
|
chatUrl: "https://chatgpt.com/",
|
|
372
379
|
authUrl: "https://chatgpt.com/auth/login",
|
|
373
380
|
runMode: "headless",
|
|
@@ -452,18 +459,28 @@ function expectAbsoluteNormalizedPath(value: unknown, path: string): string {
|
|
|
452
459
|
return normalize(expanded);
|
|
453
460
|
}
|
|
454
461
|
|
|
455
|
-
function expectSafeProfilePath(
|
|
462
|
+
function expectSafeProfilePath(
|
|
463
|
+
pathValue: string,
|
|
464
|
+
path: string,
|
|
465
|
+
cookieSources?: { chromeProfile?: string; chromeCookiePath?: string },
|
|
466
|
+
): string {
|
|
456
467
|
if (pathValue === "/" || pathValue === homedir()) {
|
|
457
468
|
throw new Error(`Invalid oracle config: ${path} points to an unsafe directory`);
|
|
458
469
|
}
|
|
459
|
-
|
|
460
|
-
|
|
470
|
+
try {
|
|
471
|
+
assertNotKnownBrowserUserDataPath(pathValue, `Invalid oracle config: ${path}`, { cookieSources });
|
|
472
|
+
} catch (error) {
|
|
473
|
+
throw new Error(error instanceof Error ? error.message : String(error));
|
|
461
474
|
}
|
|
462
475
|
return pathValue;
|
|
463
476
|
}
|
|
464
477
|
|
|
465
|
-
function expectSafeProfileDir(
|
|
466
|
-
|
|
478
|
+
function expectSafeProfileDir(
|
|
479
|
+
value: unknown,
|
|
480
|
+
path: string,
|
|
481
|
+
cookieSources?: { chromeProfile?: string; chromeCookiePath?: string },
|
|
482
|
+
): string {
|
|
483
|
+
return expectSafeProfilePath(expectAbsoluteNormalizedPath(value, path), path, cookieSources);
|
|
467
484
|
}
|
|
468
485
|
|
|
469
486
|
function expectBoolean(value: unknown, path: string): boolean {
|
|
@@ -584,17 +601,26 @@ function validateOracleConfig(value: unknown): OracleConfig {
|
|
|
584
601
|
const artifacts = expectObject(root.artifacts, "artifacts");
|
|
585
602
|
const cleanup = expectObject(root.cleanup, "cleanup");
|
|
586
603
|
|
|
587
|
-
const
|
|
588
|
-
const
|
|
604
|
+
const chromeProfile = expectString(auth.chromeProfile, "auth.chromeProfile");
|
|
605
|
+
const chromeCookiePath = expectOptionalAbsoluteNormalizedPath(auth.chromeCookiePath, "auth.chromeCookiePath");
|
|
606
|
+
const cookieSources = { chromeProfile, chromeCookiePath };
|
|
607
|
+
const authSeedProfileDir = expectSafeProfileDir(browser.authSeedProfileDir, "browser.authSeedProfileDir", cookieSources);
|
|
608
|
+
const runtimeProfilesDir = expectSafeProfileDir(browser.runtimeProfilesDir, "browser.runtimeProfilesDir", cookieSources);
|
|
589
609
|
if (runtimeProfilesDir === authSeedProfileDir || runtimeProfilesDir.startsWith(`${authSeedProfileDir}/`)) {
|
|
590
610
|
throw new Error("Invalid oracle config: browser.runtimeProfilesDir must be separate from browser.authSeedProfileDir");
|
|
591
611
|
}
|
|
592
612
|
|
|
593
|
-
const chromeCookiePath = expectOptionalAbsoluteNormalizedPath(auth.chromeCookiePath, "auth.chromeCookiePath");
|
|
594
613
|
const chromiumKeychain = expectOptionalChromiumKeychain(auth.chromiumKeychain, "auth.chromiumKeychain");
|
|
595
614
|
if (chromiumKeychain !== undefined && chromeCookiePath === undefined) {
|
|
596
615
|
throw new Error("Invalid oracle config: auth.chromiumKeychain requires auth.chromeCookiePath");
|
|
597
616
|
}
|
|
617
|
+
if (chromiumKeychain !== undefined && !chromiumKeychainSupportedOnPlatform(process.platform)) {
|
|
618
|
+
throw new Error(
|
|
619
|
+
"Invalid oracle config: auth.chromiumKeychain is macOS-only. " +
|
|
620
|
+
"On Linux, set auth.chromeCookiePath/auth.chromeProfile without auth.chromiumKeychain and use @steipete/sweet-cookie's " +
|
|
621
|
+
"SWEET_COOKIE_LINUX_KEYRING, SWEET_COOKIE_CHROME_SAFE_STORAGE_PASSWORD, or SWEET_COOKIE_BRAVE_SAFE_STORAGE_PASSWORD options for encrypted Chromium cookies.",
|
|
622
|
+
);
|
|
623
|
+
}
|
|
598
624
|
|
|
599
625
|
return {
|
|
600
626
|
defaults: {
|
|
@@ -618,7 +644,7 @@ function validateOracleConfig(value: unknown): OracleConfig {
|
|
|
618
644
|
auth: {
|
|
619
645
|
pollMs: expectInteger(auth.pollMs, "auth.pollMs", 100),
|
|
620
646
|
bootstrapTimeoutMs: expectInteger(auth.bootstrapTimeoutMs, "auth.bootstrapTimeoutMs", 1000),
|
|
621
|
-
chromeProfile
|
|
647
|
+
chromeProfile,
|
|
622
648
|
chromeCookiePath,
|
|
623
649
|
chromiumKeychain,
|
|
624
650
|
},
|
|
@@ -197,9 +197,12 @@ export interface OracleRuntimeAllocation {
|
|
|
197
197
|
seedGeneration?: string;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
function hasSessionFileAccessor(value: unknown): value is { getSessionFile: () => string | undefined } {
|
|
201
|
+
return typeof value === "object" && value !== null && "getSessionFile" in value && typeof value.getSessionFile === "function";
|
|
202
|
+
}
|
|
203
|
+
|
|
200
204
|
export function getSessionFile(ctx: ExtensionContext): string | undefined {
|
|
201
|
-
|
|
202
|
-
return manager.getSessionFile?.();
|
|
205
|
+
return hasSessionFileAccessor(ctx.sessionManager) ? ctx.sessionManager.getSessionFile() : undefined;
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
export function getOracleJobsDir(): string {
|
|
@@ -989,13 +992,14 @@ export function resolveArchiveInputs(cwd: string, files: string[]): { absolute:
|
|
|
989
992
|
throw new Error("Archive input must use '.' exactly for a whole-repo archive");
|
|
990
993
|
}
|
|
991
994
|
const absolute = resolve(cwd, file);
|
|
992
|
-
|
|
995
|
+
const relativeFromCwd = relativePath(cwd, absolute);
|
|
996
|
+
if (relativeFromCwd === "" && file !== ".") {
|
|
993
997
|
throw new Error("Archive input must use '.' exactly for a whole-repo archive");
|
|
994
998
|
}
|
|
995
|
-
|
|
996
|
-
if (!relative) {
|
|
999
|
+
if (relativeFromCwd && (relativeFromCwd === ".." || relativeFromCwd.startsWith(`..${sep}`) || isAbsolute(relativeFromCwd))) {
|
|
997
1000
|
throw new Error(`Archive input must be inside the project cwd: ${file}`);
|
|
998
1001
|
}
|
|
1002
|
+
const relative = relativeFromCwd === "" ? "." : relativeFromCwd.split(sep).join("/");
|
|
999
1003
|
if (!existsSync(absolute)) {
|
|
1000
1004
|
throw new Error(`Archive input does not exist: ${file}`);
|
|
1001
1005
|
}
|