@parall/codex-agent 1.42.0 → 1.43.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/dist/dispatch.d.ts +18 -0
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +42 -0
- package/dist/index.js +41 -4
- package/dist/workspace.d.ts +87 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +445 -9
- package/package.json +4 -4
- package/src/dispatch.ts +54 -0
- package/src/index.ts +41 -2
- package/src/workspace.ts +457 -12
package/dist/dispatch.d.ts
CHANGED
|
@@ -7,6 +7,14 @@ type CodexAppServerAdapterOptions = Pick<CodexAgentConfig, 'approvalPolicy' | 'c
|
|
|
7
7
|
contextFilePath?: string;
|
|
8
8
|
contextDirPath?: string;
|
|
9
9
|
useParallProvider?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Channel-capability shim directory (agent-core's capabilityBinDir),
|
|
12
|
+
* prepended to the subprocess PATH unconditionally. The DIRECTORY is
|
|
13
|
+
* constant for the bridge's lifetime; its CONTENT tracks capability
|
|
14
|
+
* grants, so a grant or revocation reaches even a long-lived app-server
|
|
15
|
+
* on its next shell command — no respawn needed.
|
|
16
|
+
*/
|
|
17
|
+
capabilityBinDir?: string;
|
|
10
18
|
};
|
|
11
19
|
export declare class CodexAppServerAdapter implements DispatchAdapter {
|
|
12
20
|
private readonly opts;
|
|
@@ -41,6 +49,16 @@ export declare class CodexAppServerAdapter implements DispatchAdapter {
|
|
|
41
49
|
forkSession({ sessionKey: parentSessionKey }: ForkOpts): Promise<ForkSessionHandle | null>;
|
|
42
50
|
cleanupFork({ fork }: CleanupForkOpts): void;
|
|
43
51
|
private logForkFailure;
|
|
52
|
+
/**
|
|
53
|
+
* Lazily restart the app-server before the NEXT turn: the workspace
|
|
54
|
+
* config.toml (developer_instructions, carrying capability fragments) is
|
|
55
|
+
* loaded at process start, so a changed fragment set needs a respawn to
|
|
56
|
+
* reach the prompt. Deferred to the next dispatch with no active turns —
|
|
57
|
+
* never kills an in-flight turn; thread state survives via thread/resume.
|
|
58
|
+
*/
|
|
59
|
+
requestProcessRestart(): void;
|
|
60
|
+
private restartRequested;
|
|
61
|
+
private applyPendingRestart;
|
|
44
62
|
stop(): Promise<void>;
|
|
45
63
|
private ensureStarted;
|
|
46
64
|
private doStart;
|
package/dist/dispatch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,YAAY,EACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,KAAK,4BAA4B,GAAG,IAAI,CACtC,gBAAgB,EACd,gBAAgB,GAChB,UAAU,GACV,WAAW,GACX,OAAO,GACP,iBAAiB,GACjB,SAAS,GACT,cAAc,CACjB,GAAG;IACF,cAAc,EAAE,mBAAmB,CAAC;IACpC,GAAG,CAAC,EAAE,aAAa,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAqCF,qBAAa,qBAAsB,YAAW,eAAe;IA+B/C,OAAO,CAAC,QAAQ,CAAC,IAAI;IA9BjC,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,IAAI,CAA+C;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA6B;IAC/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;gBAYQ,IAAI,EAAE,4BAA4B;IAE/D,YAAY,CAAC,MAAM,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAMhF,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqB/E,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAUvC,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAI1C,QAAQ,CAAC,EACd,KAAK,EACL,YAAY,EACZ,UAAU,EACV,OAAO,GACR,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC;IA8P7C,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMjD,WAAW,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAgChG,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe;IAIrC,OAAO,CAAC,cAAc;IAKtB;;;;;;OAMG;IACH,qBAAqB,IAAI,IAAI;IAI7B,OAAO,CAAC,gBAAgB,CAAS;YAEnB,mBAAmB;IAS3B,IAAI;YAuBI,aAAa;YA2Bb,OAAO;IAuGrB,OAAO,CAAC,qBAAqB;YAmCf,UAAU;IA6CxB,OAAO,CAAC,iBAAiB;CA2B1B"}
|
package/dist/dispatch.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execSync, spawn } from 'node:child_process';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
|
+
import * as path from 'node:path';
|
|
4
5
|
import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from '@parall/agent-core/internal/attachment-input';
|
|
5
6
|
import { normalizeApprovalPolicy, normalizeSandbox } from './config.js';
|
|
6
7
|
import { EventMapper } from './event-mapping.js';
|
|
@@ -125,6 +126,7 @@ export class CodexAppServerAdapter {
|
|
|
125
126
|
}
|
|
126
127
|
(this.opts.log ?? context.log)?.warn?.(`pending steer invalidated (subprocess died); falling through to normal dispatch`);
|
|
127
128
|
}
|
|
129
|
+
await this.applyPendingRestart(context.log);
|
|
128
130
|
await this.ensureStarted(context.log);
|
|
129
131
|
// After ensureStarted resolves the subprocess could still die before we
|
|
130
132
|
// capture the client (handleSubprocessClose nulls this.client). Yield a
|
|
@@ -405,6 +407,24 @@ export class CodexAppServerAdapter {
|
|
|
405
407
|
this.opts.log?.warn?.(`thread/fork failed: ${errToString(err)}`);
|
|
406
408
|
return null;
|
|
407
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* Lazily restart the app-server before the NEXT turn: the workspace
|
|
412
|
+
* config.toml (developer_instructions, carrying capability fragments) is
|
|
413
|
+
* loaded at process start, so a changed fragment set needs a respawn to
|
|
414
|
+
* reach the prompt. Deferred to the next dispatch with no active turns —
|
|
415
|
+
* never kills an in-flight turn; thread state survives via thread/resume.
|
|
416
|
+
*/
|
|
417
|
+
requestProcessRestart() {
|
|
418
|
+
this.restartRequested = true;
|
|
419
|
+
}
|
|
420
|
+
restartRequested = false;
|
|
421
|
+
async applyPendingRestart(log) {
|
|
422
|
+
if (!this.restartRequested || this.activeTurns.size > 0)
|
|
423
|
+
return;
|
|
424
|
+
this.restartRequested = false;
|
|
425
|
+
(log ?? this.opts.log)?.info?.('restarting codex app-server to pick up updated developer_instructions');
|
|
426
|
+
await this.stop();
|
|
427
|
+
}
|
|
408
428
|
async stop() {
|
|
409
429
|
this.stopping = true;
|
|
410
430
|
const proc = this.proc;
|
|
@@ -414,6 +434,12 @@ export class CodexAppServerAdapter {
|
|
|
414
434
|
this.initialized = false;
|
|
415
435
|
this.activeTurnIds.clear();
|
|
416
436
|
this.pendingInjections.clear();
|
|
437
|
+
// Resume markers are process-local facts. Clear them HERE, synchronously:
|
|
438
|
+
// the old child's close callback sees the replaced refs and skips its
|
|
439
|
+
// cleanup as stale, so a marker surviving stop() would make the next
|
|
440
|
+
// dispatch treat the persisted thread as already resumed in the NEW
|
|
441
|
+
// process and lose conversation continuity when turn/start rejects.
|
|
442
|
+
this.resumedThreadIds.clear();
|
|
417
443
|
if (client)
|
|
418
444
|
client.dispose(new Error('adapter stopped'));
|
|
419
445
|
if (proc && proc.exitCode === null && proc.signalCode === null) {
|
|
@@ -468,6 +494,22 @@ export class CodexAppServerAdapter {
|
|
|
468
494
|
FORCE_COLOR: '0',
|
|
469
495
|
NO_COLOR: '1',
|
|
470
496
|
};
|
|
497
|
+
// Channel-capability shims resolve ahead of any globally-installed CLI of
|
|
498
|
+
// the same name (the shim owns auth; the real binary is found further
|
|
499
|
+
// down the PATH by the shim itself). On Windows env keys are
|
|
500
|
+
// case-insensitive and the host key is usually `Path`; after the
|
|
501
|
+
// plain-object spread a literal `PATH` write would SPLIT the key
|
|
502
|
+
// (undefined which wins in the child), so reuse the parent's casing. On
|
|
503
|
+
// POSIX keys are case-SENSITIVE — match `PATH` exactly.
|
|
504
|
+
if (this.opts.capabilityBinDir) {
|
|
505
|
+
const pathKey = IS_WIN32
|
|
506
|
+
? (Object.keys(env).find((k) => k.toUpperCase() === 'PATH') ?? 'PATH')
|
|
507
|
+
: 'PATH';
|
|
508
|
+
const existing = env[pathKey];
|
|
509
|
+
env[pathKey] = existing
|
|
510
|
+
? `${this.opts.capabilityBinDir}${path.delimiter}${existing}`
|
|
511
|
+
: this.opts.capabilityBinDir;
|
|
512
|
+
}
|
|
471
513
|
if (this.opts.contextFilePath) {
|
|
472
514
|
env.PRLL_CONTEXT_FILE = this.opts.contextFilePath;
|
|
473
515
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as os from 'node:os';
|
|
3
|
-
import { ParallAgentGateway, createPlatformConfigManager, createLogger, createOtelLogger, childLogger, deriveModelIsPin, resolveRuntimeModel, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, parseProviderConfig, clearAllProviderCreds, llmSource, initAgentTelemetry, } from '@parall/agent-core';
|
|
3
|
+
import { ParallAgentGateway, capabilityBinDir, createPlatformConfigManager, createLogger, createOtelLogger, childLogger, deriveModelIsPin, materializeChannelCapabilities, resolveRuntimeModel, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, parseProviderConfig, clearAllProviderCreds, llmSource, initAgentTelemetry, } from '@parall/agent-core';
|
|
4
4
|
import { ApiError, ParallClient, ParallWs } from '@parall/sdk';
|
|
5
5
|
import { buildCodexRuntimeKey, contextFilePathForSession, dispatchContextDirPath, resolveCodexAgentConfig, resolveWsUrl, sessionStateFilePathForRuntime, stepIdFilePathForSession, } from './config.js';
|
|
6
6
|
import { CodexAppServerAdapter } from './dispatch.js';
|
|
7
7
|
import { CodexSessionManager } from './session-manager.js';
|
|
8
|
-
import { ensureCodexWorkspace, ensureParallProvider, ensureWorkspaceTrusted, isParallProxyMode, } from './workspace.js';
|
|
8
|
+
import { ensureCodexWorkspace, ensureParallProvider, ensureWorkspaceTrusted, isParallProxyMode, writeCodexSystemPrompt, } from './workspace.js';
|
|
9
9
|
const log = createLogger('codex-agent');
|
|
10
10
|
let activeLog = log;
|
|
11
11
|
async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
@@ -58,11 +58,11 @@ async function main() {
|
|
|
58
58
|
ensureParallProvider(config.codexHome, config.apiUrl, agentLog);
|
|
59
59
|
agentLog.info('parall custom provider configured (Responses API HTTP/SSE mode)');
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
const agentIdentity = {
|
|
62
62
|
userId: agentUserId,
|
|
63
63
|
displayName: me.display_name,
|
|
64
64
|
description: me.agent_profile?.description ?? undefined,
|
|
65
|
-
}
|
|
65
|
+
};
|
|
66
66
|
const runtimeKey = config.runtimeKey || buildCodexRuntimeKey(agentUserId);
|
|
67
67
|
const mainContextFilePath = contextFilePathForSession(config.stateDir, runtimeKey);
|
|
68
68
|
const sessionStateFilePath = sessionStateFilePathForRuntime(config.stateDir, runtimeKey);
|
|
@@ -79,6 +79,21 @@ async function main() {
|
|
|
79
79
|
log: agentLog,
|
|
80
80
|
});
|
|
81
81
|
const platformDefaults = await configMgr.fetch();
|
|
82
|
+
// Channel capabilities: ONE call materializes the local artifacts (the
|
|
83
|
+
// lark-cli auth shim under capabilityBinDir) and yields the system-prompt
|
|
84
|
+
// fragments, so declaration and shim can never diverge within a refresh.
|
|
85
|
+
// No freshness gate — a stale (LKG-cached) declaration fail-closes at the
|
|
86
|
+
// mint endpoint, which re-evaluates the grant on every token request.
|
|
87
|
+
const applyChannelCapabilities = () => {
|
|
88
|
+
const caps = configMgr.capabilities();
|
|
89
|
+
materializeChannelCapabilities(config.stateDir, caps, agentLog);
|
|
90
|
+
return caps.map((c) => c.fragment);
|
|
91
|
+
};
|
|
92
|
+
// Assemble the workspace AFTER the first config fetch so
|
|
93
|
+
// developer_instructions carries the capability declarations from boot.
|
|
94
|
+
const bootCapabilityFragments = applyChannelCapabilities();
|
|
95
|
+
let lastCapabilityFragments = bootCapabilityFragments.join('\n\n');
|
|
96
|
+
ensureCodexWorkspace(config.workspaceDir, agentLog, agentIdentity, bootCapabilityFragments);
|
|
82
97
|
// Model precedence: operator PIN (override) > env > server FLOOR. The server
|
|
83
98
|
// now says which it is via model_is_pin (deriveModelIsPin presence-gates the
|
|
84
99
|
// dual-read: old servers omit it → fall back to model_management). A PIN beats
|
|
@@ -104,6 +119,7 @@ async function main() {
|
|
|
104
119
|
contextFilePath: mainContextFilePath,
|
|
105
120
|
contextDirPath: dispatchContextDirPath(config.stateDir),
|
|
106
121
|
useParallProvider,
|
|
122
|
+
capabilityBinDir: capabilityBinDir(config.stateDir),
|
|
107
123
|
});
|
|
108
124
|
// Shared by onConfigUpdate + onSessionReady. /agents/me is only consumed as
|
|
109
125
|
// deriveModelIsPin's legacy fallback when the server omits model_is_pin
|
|
@@ -129,6 +145,24 @@ async function main() {
|
|
|
129
145
|
model: resolveRuntimeModel(isPin, updated.model, config.model) ?? null,
|
|
130
146
|
reasoningEffort: updated.thinkingEffort ?? config.reasoningEffort ?? null,
|
|
131
147
|
});
|
|
148
|
+
// Capability heat-update: re-materialize shims + rewrite the prompt
|
|
149
|
+
// surfaces. The write is refresh-tolerant (warn + retry next refresh);
|
|
150
|
+
// only a SUCCESSFUL write with a changed fragment set schedules the
|
|
151
|
+
// lazy app-server restart (developer_instructions loads at spawn).
|
|
152
|
+
const fragments = applyChannelCapabilities();
|
|
153
|
+
const joinedFragments = fragments.join('\n\n');
|
|
154
|
+
let promptWritten = true;
|
|
155
|
+
try {
|
|
156
|
+
writeCodexSystemPrompt(config.workspaceDir, agentIdentity, fragments);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
promptWritten = false;
|
|
160
|
+
agentLog.warn(`system prompt refresh write failed (retrying next refresh): ${String(err)}`);
|
|
161
|
+
}
|
|
162
|
+
if (promptWritten && joinedFragments !== lastCapabilityFragments) {
|
|
163
|
+
lastCapabilityFragments = joinedFragments;
|
|
164
|
+
adapter.requestProcessRestart();
|
|
165
|
+
}
|
|
132
166
|
};
|
|
133
167
|
const gateway = new ParallAgentGateway({
|
|
134
168
|
accountId: agentUserId,
|
|
@@ -152,6 +186,9 @@ async function main() {
|
|
|
152
186
|
},
|
|
153
187
|
dispatchAdapter: adapter,
|
|
154
188
|
log: agentLog,
|
|
189
|
+
// Live capability view for hint routing: the channel reply hint points
|
|
190
|
+
// at the vendor CLI only while the grant is active.
|
|
191
|
+
getCapabilityKeys: () => configMgr.capabilities().map((c) => c.key),
|
|
155
192
|
shutdownDeadlineMs: parseShutdownDeadlineMs(process.env.PRLL_SHUTDOWN_DEADLINE_MS),
|
|
156
193
|
forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
|
|
157
194
|
dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
|
package/dist/workspace.d.ts
CHANGED
|
@@ -1,4 +1,89 @@
|
|
|
1
1
|
import type { AgentIdentity } from '@parall/agent-core';
|
|
2
|
+
/**
|
|
3
|
+
* Config-lock timings, exported for tests.
|
|
4
|
+
*
|
|
5
|
+
* `staleMs` — a queue ticket untouched this long is treated as a crashed
|
|
6
|
+
* owner (live contenders refresh their ticket's mtime every `retryMs`, so
|
|
7
|
+
* the margin is ~400×). `waitMs` deliberately exceeds `staleMs`: a waiter
|
|
8
|
+
* facing a crashed head-of-queue outlasts the staleness threshold and skips
|
|
9
|
+
* it instead of falling through to a lockless write — the lockless fallback
|
|
10
|
+
* is a last resort, not a normal path.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CONFIG_LOCK_TIMINGS: {
|
|
13
|
+
staleMs: number;
|
|
14
|
+
waitMs: number;
|
|
15
|
+
retryMs: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Advisory cross-process lock serializing `<codexHome>/config.toml`
|
|
19
|
+
* read-modify-write. On a local daemon machine every runtime_auth codex
|
|
20
|
+
* bridge child shares the operator's CODEX_HOME, and the daemon starts them
|
|
21
|
+
* together — without a lock, a whole-file rewrite working from a stale read
|
|
22
|
+
* can erase a trust entry another agent appended in between.
|
|
23
|
+
*
|
|
24
|
+
* Queue design (why not wx-create + steal): any scheme that renames or
|
|
25
|
+
* unlinks the SHARED lock path can, between its staleness check and the
|
|
26
|
+
* destructive op, hit a fresh lock that replaced the stale one — deleting a
|
|
27
|
+
* live holder's lock and overlapping critical sections (reproduced under
|
|
28
|
+
* 12-process contention). Here contenders queue in `config.toml.lock.d/`
|
|
29
|
+
* using Lamport's bakery protocol, and the smallest live ticket holds the
|
|
30
|
+
* lock. Two phases per enqueue: (1) create a `choosing-<token>` marker,
|
|
31
|
+
* (2) take seq = max(existing ticket seqs) + 1 and publish by atomically
|
|
32
|
+
* RENAMING the marker into `t-<seq>-<token>`. Evaluators wait while any
|
|
33
|
+
* live choosing marker exists, so a contender that read the queue but
|
|
34
|
+
* hasn't published yet can never be missed — the classic bakery guarantee.
|
|
35
|
+
* (A naive self-chosen timestamp order would race: a process descheduled
|
|
36
|
+
* between choosing its stamp and writing its ticket could insert itself
|
|
37
|
+
* before an already-running holder.) The rename-publish closes the
|
|
38
|
+
* stale-mid-choosing hole: once a frozen chooser's marker has been GC'd,
|
|
39
|
+
* its publish fails and it must re-enqueue fresh — it can never surface an
|
|
40
|
+
* old low seq under a holder elected in its absence. ENTRY is the same
|
|
41
|
+
* pattern: the elected head atomically renames its ticket into a
|
|
42
|
+
* `held-<entry-ts>-…` entry, racing any staleness eviction of that ticket
|
|
43
|
+
* on the same path — a contender revived at the staleness boundary loses
|
|
44
|
+
* the rename and re-enqueues rather than entering behind an eviction. The
|
|
45
|
+
* holder's freshness is embedded in the held name (atomic with entry), so
|
|
46
|
+
* evicting a holder needs no stat. Evaluators mirror the atomicity: after
|
|
47
|
+
* any GC attempt, or on a marker that vanished mid-scan, they take a fresh
|
|
48
|
+
* snapshot instead of electing from the old one. Ticket order is
|
|
49
|
+
* (seq, token), identical for every observer.
|
|
50
|
+
*
|
|
51
|
+
* No process ever mutates a shared path: release unlinks only the caller's
|
|
52
|
+
* own ticket, and the only cross-process destructive op is GC of entries
|
|
53
|
+
* untouched for `staleMs` — safe because live contenders refresh their
|
|
54
|
+
* ticket's mtime every `retryMs`, and names embed a per-acquisition random
|
|
55
|
+
* token so they are never reused (no identity switch on unlink).
|
|
56
|
+
*
|
|
57
|
+
* Residual (documented, not fixable without OS-level flock, which Node core
|
|
58
|
+
* does not expose): a HOLDER frozen inside `fn` for longer than `staleMs`
|
|
59
|
+
* looks crashed, gets evicted, and the next head may overlap it — `fn` is a
|
|
60
|
+
* millisecond-scale sync config write, 400× within margin. Freezes anywhere
|
|
61
|
+
* else (mid-choosing, at entry) are safe: the atomic renames fail after an
|
|
62
|
+
* eviction and the process re-enqueues. On `waitMs` timeout
|
|
63
|
+
* the mutation proceeds without the lock (warn) — blocking would wedge
|
|
64
|
+
* bridge startup. The lock coordinates bridge processes only; codex itself
|
|
65
|
+
* does not observe it, which is why bridge writes to a shared config are
|
|
66
|
+
* additionally kept rare (the trust write is a no-op after the first boot
|
|
67
|
+
* per workspace, and runtime_auth agents never write the provider block)
|
|
68
|
+
* and whole-file writes are atomic (temp + rename) so codex never reads a
|
|
69
|
+
* truncated file.
|
|
70
|
+
*
|
|
71
|
+
* Exported for tests.
|
|
72
|
+
*/
|
|
73
|
+
export declare function withConfigLock(codexHome: string, log: {
|
|
74
|
+
warn: (msg: string) => void;
|
|
75
|
+
} | undefined, fn: () => void): void;
|
|
76
|
+
/**
|
|
77
|
+
* Test-only scheduling hooks for deterministic race tests. Production code
|
|
78
|
+
* never sets these; tests use them to pause a contender at the two points
|
|
79
|
+
* where another process can act in between (barrier files stand in for the
|
|
80
|
+
* OS scheduler).
|
|
81
|
+
*/
|
|
82
|
+
export declare const CONFIG_LOCK_TEST_HOOKS: {
|
|
83
|
+
beforeChoosingMarker?: () => void;
|
|
84
|
+
beforeTicketPublish?: () => void;
|
|
85
|
+
beforeTicketEntry?: () => void;
|
|
86
|
+
};
|
|
2
87
|
/**
|
|
3
88
|
* Ensure the workspace directory is marked as trusted in the global Codex
|
|
4
89
|
* config so that project-level `developer_instructions` are loaded at
|
|
@@ -35,7 +120,8 @@ export declare function isParallProxyMode(env?: NodeJS.ProcessEnv): boolean;
|
|
|
35
120
|
export declare function ensureParallProvider(codexHome: string, apiUrl: string, log?: {
|
|
36
121
|
warn: (msg: string) => void;
|
|
37
122
|
}): void;
|
|
123
|
+
export declare function writeCodexSystemPrompt(workspaceDir: string, agentIdentity?: AgentIdentity, capabilityFragments?: string[]): void;
|
|
38
124
|
export declare function ensureCodexWorkspace(workspaceDir: string, log?: {
|
|
39
125
|
warn: (msg: string) => void;
|
|
40
|
-
}, agentIdentity?: AgentIdentity): void;
|
|
126
|
+
}, agentIdentity?: AgentIdentity, capabilityFragments?: string[]): void;
|
|
41
127
|
//# sourceMappingURL=workspace.d.ts.map
|
package/dist/workspace.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,GAAG,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GACpC,IAAI,
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB;;;;CAI/B,CAAC;AAUF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,SAAS,EAChD,EAAE,EAAE,MAAM,IAAI,GACb,IAAI,CAkJN;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE;IACnC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAuJP;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,GAAG,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GACpC,IAAI,CAEN;AAqGD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAK/E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,GAAG,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GACpC,IAAI,CAEN;AAoED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EACpB,aAAa,CAAC,EAAE,aAAa,EAC7B,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAC7B,IAAI,CAqBN;AAED,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,GAAG,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,EACrC,aAAa,CAAC,EAAE,aAAa,EAC7B,mBAAmB,CAAC,EAAE,MAAM,EAAE,GAC7B,IAAI,CAQN"}
|