pi-oracle 0.6.16 → 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.
@@ -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: [],
@@ -429,6 +429,15 @@ async function spawnCp(args: string[], options?: { timeoutMs?: number }): Promis
429
429
  });
430
430
  }
431
431
 
432
+ async function removeChromiumProcessSingletonArtifacts(profileDir: string): Promise<void> {
433
+ await Promise.all([
434
+ rm(join(profileDir, "SingletonLock"), { force: true }),
435
+ rm(join(profileDir, "SingletonSocket"), { force: true }),
436
+ rm(join(profileDir, "SingletonCookie"), { force: true }),
437
+ rm(join(profileDir, "DevToolsActivePort"), { force: true }),
438
+ ]);
439
+ }
440
+
432
441
  export async function cloneSeedProfileToRuntime(
433
442
  config: OracleConfig,
434
443
  runtimeProfileDir: string,
@@ -441,6 +450,7 @@ export async function cloneSeedProfileToRuntime(
441
450
  await rm(runtimeProfileDir, { recursive: true, force: true }).catch(() => undefined);
442
451
  await mkdir(dirname(runtimeProfileDir), { recursive: true, mode: 0o700 }).catch(() => undefined);
443
452
  await spawnCp(profileCloneArgs(config, seedDir, runtimeProfileDir), { timeoutMs: options?.cpTimeoutMs ?? PROFILE_CLONE_TIMEOUT_MS });
453
+ await removeChromiumProcessSingletonArtifacts(runtimeProfileDir);
444
454
  });
445
455
 
446
456
  return getSeedGeneration(config);