@excitedjs/agent-runtime-codex 0.5.0-beta.179 → 0.5.0-beta.183
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/activity/budget.d.ts +8 -0
- package/dist/activity/budget.d.ts.map +1 -0
- package/dist/activity/budget.js +9 -0
- package/dist/activity/budget.js.map +1 -0
- package/dist/{transcript → activity}/cursor.d.ts +2 -2
- package/dist/activity/cursor.d.ts.map +1 -0
- package/dist/{transcript → activity}/cursor.js +10 -10
- package/dist/activity/cursor.js.map +1 -0
- package/dist/activity/error.d.ts +16 -0
- package/dist/activity/error.d.ts.map +1 -0
- package/dist/activity/error.js +22 -0
- package/dist/activity/error.js.map +1 -0
- package/dist/activity/opened-file.d.ts +10 -0
- package/dist/activity/opened-file.d.ts.map +1 -0
- package/dist/{transcript → activity}/opened-file.js +10 -10
- package/dist/activity/opened-file.js.map +1 -0
- package/dist/activity/path.d.ts +27 -0
- package/dist/activity/path.d.ts.map +1 -0
- package/dist/{transcript → activity}/path.js +49 -119
- package/dist/activity/path.js.map +1 -0
- package/dist/activity/projection.d.ts +34 -0
- package/dist/activity/projection.d.ts.map +1 -0
- package/dist/activity/projection.js +191 -0
- package/dist/activity/projection.js.map +1 -0
- package/dist/activity/reader.d.ts +14 -0
- package/dist/activity/reader.d.ts.map +1 -0
- package/dist/activity/reader.js +314 -0
- package/dist/activity/reader.js.map +1 -0
- package/dist/approval.d.ts +4 -3
- package/dist/approval.d.ts.map +1 -1
- package/dist/approval.js +6 -5
- package/dist/approval.js.map +1 -1
- package/dist/args.d.ts +3 -3
- package/dist/args.js +4 -4
- package/dist/args.js.map +1 -1
- package/dist/diagnostic.d.ts +2 -2
- package/dist/diagnostic.d.ts.map +1 -1
- package/dist/events.d.ts +1 -1
- package/dist/events.js +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-config.d.ts +27 -3
- package/dist/mcp-config.d.ts.map +1 -1
- package/dist/mcp-config.js +55 -9
- package/dist/mcp-config.js.map +1 -1
- package/dist/provider.d.ts +28 -42
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +37 -56
- package/dist/provider.js.map +1 -1
- package/dist/rpc.d.ts +2 -2
- package/dist/rpc.js +3 -3
- package/dist/rpc.js.map +1 -1
- package/dist/runtime-deps.d.ts +43 -0
- package/dist/runtime-deps.d.ts.map +1 -0
- package/dist/runtime-deps.js +2 -0
- package/dist/runtime-deps.js.map +1 -0
- package/dist/runtime.d.ts +69 -47
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +189 -132
- package/dist/runtime.js.map +1 -1
- package/dist/supervisor.d.ts +2 -2
- package/dist/supervisor.js +2 -2
- package/dist/turn-manager.d.ts +14 -19
- package/dist/turn-manager.d.ts.map +1 -1
- package/dist/turn-manager.js +16 -104
- package/dist/turn-manager.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +3 -3
- package/dist/transcript/budget.d.ts +0 -8
- package/dist/transcript/budget.d.ts.map +0 -1
- package/dist/transcript/budget.js +0 -9
- package/dist/transcript/budget.js.map +0 -1
- package/dist/transcript/cursor.d.ts.map +0 -1
- package/dist/transcript/cursor.js.map +0 -1
- package/dist/transcript/error.d.ts +0 -9
- package/dist/transcript/error.d.ts.map +0 -1
- package/dist/transcript/error.js +0 -9
- package/dist/transcript/error.js.map +0 -1
- package/dist/transcript/opened-file.d.ts +0 -10
- package/dist/transcript/opened-file.d.ts.map +0 -1
- package/dist/transcript/opened-file.js.map +0 -1
- package/dist/transcript/path.d.ts +0 -28
- package/dist/transcript/path.d.ts.map +0 -1
- package/dist/transcript/path.js.map +0 -1
- package/dist/transcript/projection.d.ts +0 -6
- package/dist/transcript/projection.d.ts.map +0 -1
- package/dist/transcript/projection.js +0 -170
- package/dist/transcript/projection.js.map +0 -1
- package/dist/transcript/reader.d.ts +0 -7
- package/dist/transcript/reader.d.ts.map +0 -1
- package/dist/transcript/reader.js +0 -421
- package/dist/transcript/reader.js.map +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ScanBudget } from '@excitedjs/dreamux-utils';
|
|
2
|
+
export type CodexScanBudget = ScanBudget;
|
|
3
|
+
export declare function createCodexScanBudget(input?: {
|
|
4
|
+
maxEntries?: number;
|
|
5
|
+
maxElapsedMs?: number;
|
|
6
|
+
now?: () => number;
|
|
7
|
+
}): CodexScanBudget;
|
|
8
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/activity/budget.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EAChB,MAAM,0BAA0B,CAAC;AAIlC,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC;AAEzC,wBAAgB,qBAAqB,CAAC,KAAK,GAAE;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACf,GAAG,eAAe,CASvB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createScanBudget, } from '@excitedjs/dreamux-utils';
|
|
2
|
+
import { CodexActivityError } from './error.js';
|
|
3
|
+
export function createCodexScanBudget(input = {}) {
|
|
4
|
+
return createScanBudget({
|
|
5
|
+
...input,
|
|
6
|
+
limitError: () => new CodexActivityError('scan_unsupported', 'Codex activity read exceeded its bounded limit'),
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/activity/budget.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,GAEjB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIhD,MAAM,UAAU,qBAAqB,CAAC,QAIlC,EAAE;IACJ,OAAO,gBAAgB,CAAC;QACtB,GAAG,KAAK;QACR,UAAU,EAAE,GAAG,EAAE,CACf,IAAI,kBAAkB,CACpB,kBAAkB,EAClB,gDAAgD,CACjD;KACJ,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { scanDigest } from '@excitedjs/dreamux-utils';
|
|
2
2
|
export interface CodexCursorPosition {
|
|
3
3
|
segment: number;
|
|
4
4
|
offset: number;
|
|
@@ -19,5 +19,5 @@ export declare function encodeCodexCursor(input: {
|
|
|
19
19
|
boundaryDigest: string;
|
|
20
20
|
}): string;
|
|
21
21
|
export declare function decodeCodexCursor(cursor: string, expectedFingerprint: string): CodexCursorEnvelope;
|
|
22
|
-
export {
|
|
22
|
+
export { scanDigest as digest };
|
|
23
23
|
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/activity/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,UAAU,EACX,MAAM,0BAA0B,CAAC;AAIlC,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,mBAAmB;IAC3B,CAAC,EAAE,CAAC,CAAC;IACL,CAAC,EAAE,OAAO,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,mBAAmB,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,OAAO,GAAG,MAAM,CAEnE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAUT;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,MAAM,GAC1B,mBAAmB,CA0BrB;AAyBD,OAAO,EAAE,UAAU,IAAI,MAAM,EAAE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { isScanDigest, scanDigest, } from '@excitedjs/dreamux-utils';
|
|
2
|
+
import { CodexActivityError } from './error.js';
|
|
3
3
|
export function codexQueryFingerprint(includeTools) {
|
|
4
|
-
return
|
|
4
|
+
return scanDigest(JSON.stringify({ include_tools: includeTools }));
|
|
5
5
|
}
|
|
6
6
|
export function encodeCodexCursor(input) {
|
|
7
7
|
const envelope = {
|
|
@@ -23,13 +23,13 @@ export function decodeCodexCursor(cursor, expectedFingerprint) {
|
|
|
23
23
|
value = JSON.parse(decoded.toString('utf8'));
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
|
-
throw new
|
|
26
|
+
throw new CodexActivityError('cursor_invalid', 'Codex activity cursor is invalid', { cause: error });
|
|
27
27
|
}
|
|
28
28
|
if (!isCursorEnvelope(value)) {
|
|
29
|
-
throw new
|
|
29
|
+
throw new CodexActivityError('cursor_invalid', 'Codex activity cursor is invalid');
|
|
30
30
|
}
|
|
31
31
|
if (value.fp !== expectedFingerprint) {
|
|
32
|
-
throw new
|
|
32
|
+
throw new CodexActivityError('cursor_query_mismatch', 'Codex activity cursor belongs to a different query');
|
|
33
33
|
}
|
|
34
34
|
return value;
|
|
35
35
|
}
|
|
@@ -42,9 +42,9 @@ function isCursorEnvelope(value) {
|
|
|
42
42
|
return (Object.keys(record).length === 6 &&
|
|
43
43
|
record['v'] === 1 &&
|
|
44
44
|
record['p'] === 'codex' &&
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
isScanDigest(record['fp']) &&
|
|
46
|
+
isScanDigest(record['gen']) &&
|
|
47
|
+
isScanDigest(record['bd']) &&
|
|
48
48
|
position !== null &&
|
|
49
49
|
typeof position === 'object' &&
|
|
50
50
|
!Array.isArray(position) &&
|
|
@@ -53,5 +53,5 @@ function isCursorEnvelope(value) {
|
|
|
53
53
|
Number.isSafeInteger(position['offset']) &&
|
|
54
54
|
position['offset'] >= 0);
|
|
55
55
|
}
|
|
56
|
-
export {
|
|
56
|
+
export { scanDigest as digest };
|
|
57
57
|
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/activity/cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentActivityError } from '@excitedjs/dreamux-types';
|
|
2
|
+
/**
|
|
3
|
+
* Why a Codex activity read failed, at native granularity. This is internal
|
|
4
|
+
* control-flow vocabulary: only the public {@link AgentActivityError.reason} it
|
|
5
|
+
* projects crosses the provider seam.
|
|
6
|
+
*/
|
|
7
|
+
export type CodexActivityDetail = 'not_found' | 'session_mismatch' | 'locator_outside_root' | 'unreadable' | 'invalid' | 'scan_unsupported' | 'cursor_invalid' | 'cursor_query_mismatch' | 'cursor_stale';
|
|
8
|
+
export declare class CodexActivityError extends Error implements AgentActivityError {
|
|
9
|
+
readonly detail: CodexActivityDetail;
|
|
10
|
+
readonly name = "AgentActivityError";
|
|
11
|
+
readonly reason: AgentActivityError['reason'];
|
|
12
|
+
constructor(detail: CodexActivityDetail, message: string, options?: {
|
|
13
|
+
cause?: unknown;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/activity/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,kBAAkB,GAClB,sBAAsB,GACtB,YAAY,GACZ,SAAS,GACT,kBAAkB,GAClB,gBAAgB,GAChB,uBAAuB,GACvB,cAAc,CAAC;AAiBnB,qBAAa,kBAAmB,SAAQ,KAAM,YAAW,kBAAkB;IAMvE,QAAQ,CAAC,MAAM,EAAE,mBAAmB;IALtC,QAAQ,CAAC,IAAI,wBAAwB;IAErC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBAGnC,MAAM,EAAE,mBAAmB,EACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAKpC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const PUBLIC_REASON = {
|
|
2
|
+
not_found: 'session_unavailable',
|
|
3
|
+
session_mismatch: 'session_unavailable',
|
|
4
|
+
locator_outside_root: 'session_unavailable',
|
|
5
|
+
unreadable: 'session_unavailable',
|
|
6
|
+
invalid: 'activity_corrupt',
|
|
7
|
+
scan_unsupported: 'provider_failure',
|
|
8
|
+
cursor_invalid: 'cursor_invalid',
|
|
9
|
+
cursor_query_mismatch: 'cursor_invalid',
|
|
10
|
+
cursor_stale: 'cursor_invalid',
|
|
11
|
+
};
|
|
12
|
+
export class CodexActivityError extends Error {
|
|
13
|
+
detail;
|
|
14
|
+
name = 'AgentActivityError';
|
|
15
|
+
reason;
|
|
16
|
+
constructor(detail, message, options = {}) {
|
|
17
|
+
super(message, options);
|
|
18
|
+
this.detail = detail;
|
|
19
|
+
this.reason = PUBLIC_REASON[detail];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/activity/error.ts"],"names":[],"mappings":"AAkBA,MAAM,aAAa,GAGf;IACF,SAAS,EAAE,qBAAqB;IAChC,gBAAgB,EAAE,qBAAqB;IACvC,oBAAoB,EAAE,qBAAqB;IAC3C,UAAU,EAAE,qBAAqB;IACjC,OAAO,EAAE,kBAAkB;IAC3B,gBAAgB,EAAE,kBAAkB;IACpC,cAAc,EAAE,gBAAgB;IAChC,qBAAqB,EAAE,gBAAgB;IACvC,YAAY,EAAE,gBAAgB;CAC/B,CAAC;AAEF,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAMhC;IALF,IAAI,GAAG,oBAAoB,CAAC;IAE5B,MAAM,CAA+B;IAE9C,YACW,MAA2B,EACpC,OAAe,EACf,UAA+B,EAAE;QAEjC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAJf,WAAM,GAAN,MAAM,CAAqB;QAKpC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type FileHandle } from 'node:fs/promises';
|
|
2
|
+
export interface CodexOpenedRollout {
|
|
3
|
+
handle: FileHandle;
|
|
4
|
+
path: string;
|
|
5
|
+
size: number;
|
|
6
|
+
dev: number | bigint;
|
|
7
|
+
ino: number | bigint;
|
|
8
|
+
}
|
|
9
|
+
export declare function openCodexRollout(candidate: string, canonicalRoots: readonly string[]): Promise<CodexOpenedRollout>;
|
|
10
|
+
//# sourceMappingURL=opened-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opened-file.d.ts","sourceRoot":"","sources":["../../src/activity/opened-file.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,SAAS,MAAM,EAAE,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA4D7B"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { constants } from 'node:fs';
|
|
2
2
|
import { open, realpath } from 'node:fs/promises';
|
|
3
3
|
import { isPathWithin } from '@excitedjs/dreamux-utils';
|
|
4
|
-
import {
|
|
5
|
-
export async function
|
|
4
|
+
import { CodexActivityError } from './error.js';
|
|
5
|
+
export async function openCodexRollout(candidate, canonicalRoots) {
|
|
6
6
|
let handle;
|
|
7
7
|
try {
|
|
8
8
|
handle = await open(candidate, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
@@ -16,10 +16,10 @@ export async function openCodexTranscript(candidate, canonicalRoots) {
|
|
|
16
16
|
realpath(candidate),
|
|
17
17
|
]);
|
|
18
18
|
if (!opened.isFile()) {
|
|
19
|
-
throw new
|
|
19
|
+
throw new CodexActivityError('invalid', 'Codex activity source is not a regular file');
|
|
20
20
|
}
|
|
21
21
|
if (!canonicalRoots.some((root) => isPathWithin(root, canonicalPath))) {
|
|
22
|
-
throw new
|
|
22
|
+
throw new CodexActivityError('locator_outside_root', 'Codex activity is unavailable for this session');
|
|
23
23
|
}
|
|
24
24
|
const current = await open(canonicalPath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0)).catch((error) => {
|
|
25
25
|
throw classifyOpenError(error);
|
|
@@ -27,7 +27,7 @@ export async function openCodexTranscript(candidate, canonicalRoots) {
|
|
|
27
27
|
try {
|
|
28
28
|
const currentStat = await current.stat();
|
|
29
29
|
if (opened.dev !== currentStat.dev || opened.ino !== currentStat.ino) {
|
|
30
|
-
throw new
|
|
30
|
+
throw new CodexActivityError('unreadable', 'Codex activity source changed while opening');
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
finally {
|
|
@@ -43,19 +43,19 @@ export async function openCodexTranscript(candidate, canonicalRoots) {
|
|
|
43
43
|
}
|
|
44
44
|
catch (error) {
|
|
45
45
|
await handle.close().catch(() => undefined);
|
|
46
|
-
if (error instanceof
|
|
46
|
+
if (error instanceof CodexActivityError)
|
|
47
47
|
throw error;
|
|
48
|
-
throw new
|
|
48
|
+
throw new CodexActivityError('unreadable', 'Codex activity is unreadable', { cause: error });
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
function classifyOpenError(error) {
|
|
52
52
|
const code = error.code;
|
|
53
53
|
if (code === 'ENOENT') {
|
|
54
|
-
return new
|
|
54
|
+
return new CodexActivityError('not_found', 'Codex activity is unavailable for this session', { cause: error });
|
|
55
55
|
}
|
|
56
56
|
if (code === 'ELOOP') {
|
|
57
|
-
return new
|
|
57
|
+
return new CodexActivityError('locator_outside_root', 'Codex activity is unavailable for this session', { cause: error });
|
|
58
58
|
}
|
|
59
|
-
return new
|
|
59
|
+
return new CodexActivityError('unreadable', 'Codex activity is unreadable', { cause: error });
|
|
60
60
|
}
|
|
61
61
|
//# sourceMappingURL=opened-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opened-file.js","sourceRoot":"","sources":["../../src/activity/opened-file.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DreamuxEnvironment } from '@excitedjs/dreamux-types';
|
|
2
|
+
import { type CodexScanBudget } from './budget.js';
|
|
3
|
+
import { type CodexOpenedRollout } from './opened-file.js';
|
|
4
|
+
export interface CodexRolloutRoots {
|
|
5
|
+
home: string;
|
|
6
|
+
sessions: string;
|
|
7
|
+
archived: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CodexValidatedRollout {
|
|
10
|
+
path: string;
|
|
11
|
+
root: string;
|
|
12
|
+
sessionId: string;
|
|
13
|
+
rolloutId: string;
|
|
14
|
+
historyBase: CodexHistoryBase | null;
|
|
15
|
+
dev: number | bigint;
|
|
16
|
+
ino: number | bigint;
|
|
17
|
+
}
|
|
18
|
+
export interface CodexHistoryBase {
|
|
19
|
+
rolloutId: string;
|
|
20
|
+
endByteOffset: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function resolveCodexRolloutRoots(env?: DreamuxEnvironment): Promise<CodexRolloutRoots>;
|
|
23
|
+
export declare function validateCodexRolloutPath(candidate: string, expectedSessionId: string, roots: CodexRolloutRoots): Promise<CodexValidatedRollout>;
|
|
24
|
+
export declare function locateCodexRollout(locator: string | null | undefined, expectedSessionId: string, roots: CodexRolloutRoots, budget?: CodexScanBudget): Promise<CodexValidatedRollout>;
|
|
25
|
+
export declare function findCodexRolloutById(roots: CodexRolloutRoots, rolloutId: string, budget?: CodexScanBudget): Promise<CodexValidatedRollout>;
|
|
26
|
+
export declare function readCodexRolloutText(opened: CodexOpenedRollout, maxDecodedBytes: number): Promise<string>;
|
|
27
|
+
//# sourceMappingURL=path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/activity/path.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACrC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,wBAAwB,CAC5C,GAAG,GAAE,kBAAgC,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAuC5B;AAED,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,qBAAqB,CAAC,CAMhC;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAClC,iBAAiB,EAAE,MAAM,EACzB,KAAK,EAAE,iBAAiB,EACxB,MAAM,GAAE,eAAyC,GAChD,OAAO,CAAC,qBAAqB,CAAC,CA4ChC;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,iBAAiB,EACxB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,eAAyC,GAChD,OAAO,CAAC,qBAAqB,CAAC,CA2BhC;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,kBAAkB,EAC1B,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAwCjB"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { isAbsolute as isAbsolutePath } from 'node:path';
|
|
2
1
|
import { opendir, realpath, stat } from 'node:fs/promises';
|
|
3
|
-
import { basename,
|
|
2
|
+
import { basename, isAbsolute, join, resolve } from 'node:path';
|
|
4
3
|
import { createZstdDecompress } from 'node:zlib';
|
|
5
4
|
import { isPathWithin } from '@excitedjs/dreamux-utils';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { createCodexScanBudget, } from './budget.js';
|
|
6
|
+
import { CodexActivityError } from './error.js';
|
|
7
|
+
import { openCodexRollout, } from './opened-file.js';
|
|
9
8
|
const ROLLOUT_FILENAME = /^rollout-[^/]+-[0-9a-f-]{36}(?:_[0-9a-f-]{36})?\.jsonl(?:\.zst)?$/i;
|
|
10
9
|
const MAX_METADATA_BYTES = 1_048_576;
|
|
11
|
-
export async function
|
|
10
|
+
export async function resolveCodexRolloutRoots(env = process.env) {
|
|
12
11
|
const configured = env['CODEX_HOME'];
|
|
13
12
|
let home;
|
|
14
13
|
if (configured !== undefined) {
|
|
15
|
-
if (!
|
|
16
|
-
throw new
|
|
14
|
+
if (!isAbsolute(configured)) {
|
|
15
|
+
throw new CodexActivityError('invalid', 'Explicit Codex home must be an absolute directory');
|
|
17
16
|
}
|
|
18
17
|
let info;
|
|
19
18
|
try {
|
|
@@ -23,7 +22,7 @@ export async function resolveCodexTranscriptRoots(env = process.env) {
|
|
|
23
22
|
throw classifyRootError(error);
|
|
24
23
|
}
|
|
25
24
|
if (!info.isDirectory()) {
|
|
26
|
-
throw new
|
|
25
|
+
throw new CodexActivityError('invalid', 'Explicit Codex home must be a directory');
|
|
27
26
|
}
|
|
28
27
|
home = await realpath(configured).catch((error) => {
|
|
29
28
|
throw classifyRootError(error);
|
|
@@ -44,48 +43,21 @@ export async function resolveCodexTranscriptRoots(env = process.env) {
|
|
|
44
43
|
archived: join(home, 'archived_sessions'),
|
|
45
44
|
};
|
|
46
45
|
}
|
|
47
|
-
export async function
|
|
48
|
-
|
|
49
|
-
return await validateCodexTranscriptLocator(candidate, expectedSessionId, roots);
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
if (!(error instanceof CodexTranscriptError) ||
|
|
53
|
-
error.reason !== 'not_found') {
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
assertNativeRolloutPath(candidate);
|
|
58
|
-
const rolloutId = rolloutIdFromPath(candidate);
|
|
59
|
-
if (threadIdFromPath(candidate).toLowerCase() !==
|
|
60
|
-
expectedSessionId.toLowerCase()) {
|
|
61
|
-
throw new CodexTranscriptError('session_mismatch', 'Codex transcript does not belong to the selected session');
|
|
62
|
-
}
|
|
63
|
-
const canonicalPath = await canonicalProspectivePath(candidate, roots);
|
|
64
|
-
return {
|
|
65
|
-
path: canonicalPath,
|
|
66
|
-
root: canonicalRootsForProspectivePath(canonicalPath, roots),
|
|
67
|
-
sessionId: expectedSessionId,
|
|
68
|
-
rolloutId,
|
|
69
|
-
historyBase: null,
|
|
70
|
-
dev: -1,
|
|
71
|
-
ino: -1,
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
export async function validateCodexTranscriptLocator(candidate, expectedSessionId, roots) {
|
|
75
|
-
return validateCodexTranscript({
|
|
46
|
+
export async function validateCodexRolloutPath(candidate, expectedSessionId, roots) {
|
|
47
|
+
return validateCodexRollout({
|
|
76
48
|
candidate,
|
|
77
49
|
roots,
|
|
78
50
|
expectedSessionId,
|
|
79
51
|
});
|
|
80
52
|
}
|
|
81
|
-
export async function
|
|
53
|
+
export async function locateCodexRollout(locator, expectedSessionId, roots, budget = createCodexScanBudget()) {
|
|
82
54
|
if (locator !== null && locator !== undefined) {
|
|
83
55
|
try {
|
|
84
|
-
return await
|
|
56
|
+
return await validateCodexRolloutPath(locator, expectedSessionId, roots);
|
|
85
57
|
}
|
|
86
58
|
catch (error) {
|
|
87
|
-
if (!(error instanceof
|
|
88
|
-
error.
|
|
59
|
+
if (!(error instanceof CodexActivityError) ||
|
|
60
|
+
error.detail !== 'not_found') {
|
|
89
61
|
throw error;
|
|
90
62
|
}
|
|
91
63
|
}
|
|
@@ -93,46 +65,46 @@ export async function locateCodexTranscript(locator, expectedSessionId, roots, b
|
|
|
93
65
|
const candidates = await discoverRollouts(roots, expectedSessionId, budget);
|
|
94
66
|
for (const candidate of candidates) {
|
|
95
67
|
try {
|
|
96
|
-
return await
|
|
68
|
+
return await validateCodexRolloutPath(candidate, expectedSessionId, roots);
|
|
97
69
|
}
|
|
98
70
|
catch (error) {
|
|
99
|
-
if (error instanceof
|
|
100
|
-
(error.
|
|
101
|
-
error.
|
|
71
|
+
if (error instanceof CodexActivityError &&
|
|
72
|
+
(error.detail === 'session_mismatch' ||
|
|
73
|
+
error.detail === 'not_found')) {
|
|
102
74
|
continue;
|
|
103
75
|
}
|
|
104
76
|
throw error;
|
|
105
77
|
}
|
|
106
78
|
}
|
|
107
|
-
throw new
|
|
79
|
+
throw new CodexActivityError('not_found', 'Codex activity is unavailable for this session');
|
|
108
80
|
}
|
|
109
|
-
export async function findCodexRolloutById(roots, rolloutId, budget =
|
|
81
|
+
export async function findCodexRolloutById(roots, rolloutId, budget = createCodexScanBudget()) {
|
|
110
82
|
const candidates = await discoverRollouts(roots, rolloutId, budget);
|
|
111
83
|
for (const candidate of candidates) {
|
|
112
84
|
if (!basename(candidate).toLowerCase().includes(rolloutId.toLowerCase())) {
|
|
113
85
|
continue;
|
|
114
86
|
}
|
|
115
87
|
try {
|
|
116
|
-
return await
|
|
88
|
+
return await validateCodexRollout({
|
|
117
89
|
candidate,
|
|
118
90
|
roots,
|
|
119
91
|
expectedRolloutId: rolloutId,
|
|
120
92
|
});
|
|
121
93
|
}
|
|
122
94
|
catch (error) {
|
|
123
|
-
if (error instanceof
|
|
124
|
-
(error.
|
|
125
|
-
error.
|
|
95
|
+
if (error instanceof CodexActivityError &&
|
|
96
|
+
(error.detail === 'session_mismatch' ||
|
|
97
|
+
error.detail === 'not_found')) {
|
|
126
98
|
continue;
|
|
127
99
|
}
|
|
128
100
|
throw error;
|
|
129
101
|
}
|
|
130
102
|
}
|
|
131
|
-
throw new
|
|
103
|
+
throw new CodexActivityError('not_found', 'Codex activity history is unavailable');
|
|
132
104
|
}
|
|
133
|
-
export async function
|
|
105
|
+
export async function readCodexRolloutText(opened, maxDecodedBytes) {
|
|
134
106
|
if (opened.path.endsWith('.zst') && opened.size > maxDecodedBytes) {
|
|
135
|
-
throw new
|
|
107
|
+
throw new CodexActivityError('scan_unsupported', 'Codex activity requires a native read index');
|
|
136
108
|
}
|
|
137
109
|
const source = opened.handle.createReadStream({
|
|
138
110
|
autoClose: false,
|
|
@@ -148,15 +120,15 @@ export async function readCodexTranscriptText(opened, maxDecodedBytes) {
|
|
|
148
120
|
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
149
121
|
decodedBytes += buffer.length;
|
|
150
122
|
if (decodedBytes > maxDecodedBytes) {
|
|
151
|
-
throw new
|
|
123
|
+
throw new CodexActivityError('scan_unsupported', 'Codex activity exceeds the bounded limit');
|
|
152
124
|
}
|
|
153
125
|
chunks.push(buffer);
|
|
154
126
|
}
|
|
155
127
|
}
|
|
156
128
|
catch (error) {
|
|
157
|
-
if (error instanceof
|
|
129
|
+
if (error instanceof CodexActivityError)
|
|
158
130
|
throw error;
|
|
159
|
-
throw new
|
|
131
|
+
throw new CodexActivityError('unreadable', 'Codex activity is unreadable', { cause: error });
|
|
160
132
|
}
|
|
161
133
|
finally {
|
|
162
134
|
stream.destroy();
|
|
@@ -196,15 +168,15 @@ async function readCodexSessionMetadata(opened) {
|
|
|
196
168
|
}
|
|
197
169
|
}
|
|
198
170
|
catch (error) {
|
|
199
|
-
if (error instanceof
|
|
171
|
+
if (error instanceof CodexActivityError)
|
|
200
172
|
throw error;
|
|
201
|
-
throw new
|
|
173
|
+
throw new CodexActivityError('unreadable', 'Codex activity metadata is unreadable', { cause: error });
|
|
202
174
|
}
|
|
203
175
|
finally {
|
|
204
176
|
stream.destroy();
|
|
205
177
|
source.destroy();
|
|
206
178
|
}
|
|
207
|
-
throw new
|
|
179
|
+
throw new CodexActivityError('invalid', 'Codex activity metadata is invalid');
|
|
208
180
|
}
|
|
209
181
|
async function discoverRollouts(roots, id, budget) {
|
|
210
182
|
const matches = [];
|
|
@@ -219,7 +191,7 @@ async function discoverRollouts(roots, id, budget) {
|
|
|
219
191
|
catch (error) {
|
|
220
192
|
if (error.code === 'ENOENT')
|
|
221
193
|
continue;
|
|
222
|
-
throw new
|
|
194
|
+
throw new CodexActivityError('unreadable', 'Codex activity source is unreadable', { cause: error });
|
|
223
195
|
}
|
|
224
196
|
try {
|
|
225
197
|
for await (const entry of opened) {
|
|
@@ -235,11 +207,11 @@ async function discoverRollouts(roots, id, budget) {
|
|
|
235
207
|
}
|
|
236
208
|
}
|
|
237
209
|
catch (error) {
|
|
238
|
-
if (error instanceof
|
|
210
|
+
if (error instanceof CodexActivityError)
|
|
239
211
|
throw error;
|
|
240
212
|
if (error.code === 'ENOENT')
|
|
241
213
|
continue;
|
|
242
|
-
throw new
|
|
214
|
+
throw new CodexActivityError('unreadable', 'Codex activity source is unreadable', { cause: error });
|
|
243
215
|
}
|
|
244
216
|
}
|
|
245
217
|
}
|
|
@@ -256,11 +228,11 @@ async function existingRepresentation(path) {
|
|
|
256
228
|
}
|
|
257
229
|
catch (error) {
|
|
258
230
|
if (error.code !== 'ENOENT') {
|
|
259
|
-
throw new
|
|
231
|
+
throw new CodexActivityError('unreadable', 'Codex activity source is unreadable', { cause: error });
|
|
260
232
|
}
|
|
261
233
|
}
|
|
262
234
|
}
|
|
263
|
-
throw new
|
|
235
|
+
throw new CodexActivityError('not_found', 'Codex activity is unavailable for this session');
|
|
264
236
|
}
|
|
265
237
|
async function canonicalExistingRoots(roots) {
|
|
266
238
|
const result = [];
|
|
@@ -268,31 +240,31 @@ async function canonicalExistingRoots(roots) {
|
|
|
268
240
|
const canonical = await realpath(root).catch((error) => {
|
|
269
241
|
if (error.code === 'ENOENT')
|
|
270
242
|
return null;
|
|
271
|
-
throw new
|
|
243
|
+
throw new CodexActivityError('unreadable', 'Codex activity source is unreadable', { cause: error });
|
|
272
244
|
});
|
|
273
245
|
if (canonical !== null)
|
|
274
246
|
result.push(canonical);
|
|
275
247
|
}
|
|
276
248
|
if (result.length === 0) {
|
|
277
|
-
throw new
|
|
249
|
+
throw new CodexActivityError('not_found', 'Codex activity is unavailable');
|
|
278
250
|
}
|
|
279
251
|
return result;
|
|
280
252
|
}
|
|
281
|
-
async function
|
|
253
|
+
async function validateCodexRollout(input) {
|
|
282
254
|
assertNativeRolloutPath(input.candidate);
|
|
283
255
|
const existing = await existingRepresentation(input.candidate);
|
|
284
256
|
const canonicalRoots = await canonicalExistingRoots(input.roots);
|
|
285
|
-
const opened = await
|
|
257
|
+
const opened = await openCodexRollout(existing, canonicalRoots);
|
|
286
258
|
try {
|
|
287
259
|
const rolloutId = rolloutIdFromPath(opened.path);
|
|
288
260
|
if (input.expectedRolloutId !== undefined &&
|
|
289
261
|
rolloutId.toLowerCase() !== input.expectedRolloutId.toLowerCase()) {
|
|
290
|
-
throw new
|
|
262
|
+
throw new CodexActivityError('session_mismatch', 'Codex activity identity does not match');
|
|
291
263
|
}
|
|
292
264
|
const metadata = await readCodexSessionMetadata(opened);
|
|
293
265
|
if (input.expectedSessionId !== undefined &&
|
|
294
266
|
metadata.sessionId !== input.expectedSessionId) {
|
|
295
|
-
throw new
|
|
267
|
+
throw new CodexActivityError('session_mismatch', 'Codex activity does not belong to the selected session');
|
|
296
268
|
}
|
|
297
269
|
return {
|
|
298
270
|
path: opened.path,
|
|
@@ -308,11 +280,6 @@ async function validateCodexTranscript(input) {
|
|
|
308
280
|
await opened.handle.close();
|
|
309
281
|
}
|
|
310
282
|
}
|
|
311
|
-
function canonicalRootsForProspectivePath(candidate, roots) {
|
|
312
|
-
return isPathWithin(roots.sessions, candidate)
|
|
313
|
-
? roots.sessions
|
|
314
|
-
: roots.archived;
|
|
315
|
-
}
|
|
316
283
|
function metadataFromLine(line) {
|
|
317
284
|
const value = parseObject(line);
|
|
318
285
|
if (value?.['type'] !== 'session_meta')
|
|
@@ -321,7 +288,7 @@ function metadataFromLine(line) {
|
|
|
321
288
|
const meta = asRecord(payload?.['meta']) ?? payload;
|
|
322
289
|
const id = stringValue(meta?.['id']) ?? stringValue(meta?.['session_id']);
|
|
323
290
|
if (id === null) {
|
|
324
|
-
throw new
|
|
291
|
+
throw new CodexActivityError('invalid', 'Codex activity metadata is invalid');
|
|
325
292
|
}
|
|
326
293
|
const historyBaseRecord = asRecord(meta?.['history_base']);
|
|
327
294
|
const rolloutId = stringValue(historyBaseRecord?.['thread_id']);
|
|
@@ -334,67 +301,30 @@ function metadataFromLine(line) {
|
|
|
334
301
|
};
|
|
335
302
|
}
|
|
336
303
|
function metadataTooLarge() {
|
|
337
|
-
return new
|
|
304
|
+
return new CodexActivityError('invalid', 'Codex activity metadata exceeds its bounded record size');
|
|
338
305
|
}
|
|
339
306
|
function classifyRootError(error) {
|
|
340
|
-
return new
|
|
307
|
+
return new CodexActivityError(error.code === 'ENOENT'
|
|
341
308
|
? 'not_found'
|
|
342
309
|
: 'unreadable', 'Codex home directory is unavailable', { cause: error });
|
|
343
310
|
}
|
|
344
|
-
async function canonicalProspectivePath(candidate, roots) {
|
|
345
|
-
const canonicalCandidate = await canonicalizeProspectivePath(candidate);
|
|
346
|
-
const canonicalRoots = await Promise.all([roots.sessions, roots.archived].map(canonicalizeProspectivePath));
|
|
347
|
-
if (!canonicalRoots.some((root) => isPathWithin(root, canonicalCandidate))) {
|
|
348
|
-
throw new CodexTranscriptError('locator_outside_root', 'Codex transcript locator is outside the native transcript roots');
|
|
349
|
-
}
|
|
350
|
-
return canonicalCandidate;
|
|
351
|
-
}
|
|
352
|
-
async function canonicalizeProspectivePath(path) {
|
|
353
|
-
const absolutePath = resolve(path);
|
|
354
|
-
let ancestor = absolutePath;
|
|
355
|
-
while (true) {
|
|
356
|
-
const canonicalAncestor = await realpathIfExists(ancestor);
|
|
357
|
-
if (canonicalAncestor !== null) {
|
|
358
|
-
return resolve(canonicalAncestor, relative(ancestor, absolutePath));
|
|
359
|
-
}
|
|
360
|
-
const parent = dirname(ancestor);
|
|
361
|
-
if (parent === ancestor) {
|
|
362
|
-
throw new CodexTranscriptError('not_found', 'Codex transcript root is unavailable');
|
|
363
|
-
}
|
|
364
|
-
ancestor = parent;
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async function realpathIfExists(path) {
|
|
368
|
-
try {
|
|
369
|
-
return await realpath(path);
|
|
370
|
-
}
|
|
371
|
-
catch (error) {
|
|
372
|
-
if (error.code === 'ENOENT')
|
|
373
|
-
return null;
|
|
374
|
-
throw new CodexTranscriptError('unreadable', 'Codex transcript path is unreadable', { cause: error });
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
311
|
function rolloutIdFromPath(path) {
|
|
378
312
|
const ids = rolloutIdsFromPath(path);
|
|
379
313
|
return ids.at(-1) ?? basename(path);
|
|
380
314
|
}
|
|
381
|
-
function threadIdFromPath(path) {
|
|
382
|
-
const ids = rolloutIdsFromPath(path);
|
|
383
|
-
return ids[0] ?? basename(path);
|
|
384
|
-
}
|
|
385
315
|
function rolloutIdsFromPath(path) {
|
|
386
316
|
const name = basename(path).replace(/\.jsonl(?:\.zst)?$/, '');
|
|
387
317
|
return name.match(/[0-9a-f]{8}-[0-9a-f-]{27}/gi) ?? [];
|
|
388
318
|
}
|
|
389
319
|
function assertNativeRolloutPath(candidate) {
|
|
390
320
|
if (!isAbsolute(candidate) || !ROLLOUT_FILENAME.test(basename(candidate))) {
|
|
391
|
-
throw new
|
|
321
|
+
throw new CodexActivityError('invalid', 'Codex activity source is not a native rollout path');
|
|
392
322
|
}
|
|
393
323
|
}
|
|
394
324
|
function homeDirectory(env) {
|
|
395
325
|
const value = env['HOME'];
|
|
396
326
|
if (value === undefined || value === '') {
|
|
397
|
-
throw new
|
|
327
|
+
throw new CodexActivityError('not_found', 'Codex home directory is unavailable');
|
|
398
328
|
}
|
|
399
329
|
return value;
|
|
400
330
|
}
|