@excitedjs/agent-runtime-codex 0.2.0-alpha.g0ddd418597ca
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/LICENSE +21 -0
- package/README.md +44 -0
- package/dist/approval.d.ts +30 -0
- package/dist/approval.d.ts.map +1 -0
- package/dist/approval.js +42 -0
- package/dist/approval.js.map +1 -0
- package/dist/args.d.ts +55 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +113 -0
- package/dist/args.js.map +1 -0
- package/dist/bin.d.ts +14 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +18 -0
- package/dist/bin.js.map +1 -0
- package/dist/codex-home.d.ts +42 -0
- package/dist/codex-home.d.ts.map +1 -0
- package/dist/codex-home.js +112 -0
- package/dist/codex-home.js.map +1 -0
- package/dist/config.d.ts +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +106 -0
- package/dist/config.js.map +1 -0
- package/dist/diagnostic.d.ts +14 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +58 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/events.d.ts +88 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +225 -0
- package/dist/events.js.map +1 -0
- package/dist/handshake.d.ts +44 -0
- package/dist/handshake.d.ts.map +1 -0
- package/dist/handshake.js +85 -0
- package/dist/handshake.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/completion-body.d.ts +38 -0
- package/dist/internal/completion-body.d.ts.map +1 -0
- package/dist/internal/completion-body.js +62 -0
- package/dist/internal/completion-body.js.map +1 -0
- package/dist/internal/config-validate.d.ts +23 -0
- package/dist/internal/config-validate.d.ts.map +1 -0
- package/dist/internal/config-validate.js +122 -0
- package/dist/internal/config-validate.js.map +1 -0
- package/dist/internal/os.d.ts +30 -0
- package/dist/internal/os.d.ts.map +1 -0
- package/dist/internal/os.js +81 -0
- package/dist/internal/os.js.map +1 -0
- package/dist/internal/socket.d.ts +23 -0
- package/dist/internal/socket.d.ts.map +1 -0
- package/dist/internal/socket.js +74 -0
- package/dist/internal/socket.js.map +1 -0
- package/dist/internal/turn-render.d.ts +22 -0
- package/dist/internal/turn-render.d.ts.map +1 -0
- package/dist/internal/turn-render.js +40 -0
- package/dist/internal/turn-render.js.map +1 -0
- package/dist/mcp-config.d.ts +9 -0
- package/dist/mcp-config.d.ts.map +1 -0
- package/dist/mcp-config.js +21 -0
- package/dist/mcp-config.js.map +1 -0
- package/dist/paths.d.ts +7 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +26 -0
- package/dist/paths.js.map +1 -0
- package/dist/provider-ref.d.ts +8 -0
- package/dist/provider-ref.d.ts.map +1 -0
- package/dist/provider-ref.js +8 -0
- package/dist/provider-ref.js.map +1 -0
- package/dist/provider.d.ts +71 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +137 -0
- package/dist/provider.js.map +1 -0
- package/dist/rpc.d.ts +65 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +200 -0
- package/dist/rpc.js.map +1 -0
- package/dist/runtime-support.d.ts +27 -0
- package/dist/runtime-support.d.ts.map +1 -0
- package/dist/runtime-support.js +57 -0
- package/dist/runtime-support.js.map +1 -0
- package/dist/runtime.d.ts +246 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +648 -0
- package/dist/runtime.js.map +1 -0
- package/dist/supervisor.d.ts +55 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +183 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/turn-manager.d.ts +92 -0
- package/dist/turn-manager.d.ts.map +1 -0
- package/dist/turn-manager.js +271 -0
- package/dist/turn-manager.js.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +16 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +33 -0
- package/dist/version.js.map +1 -0
- package/package.json +56 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builtin `builtin:codex` runtime config: schema type, defaults, reader, and
|
|
3
|
+
* the typed accessor.
|
|
4
|
+
*
|
|
5
|
+
* Codex runtime config is owned by this package (the `builtin:codex` provider),
|
|
6
|
+
* not by the Dreamux host config module. It depends only on the shared neutral
|
|
7
|
+
* validation primitives (`@excitedjs/dreamux-utils`) and the package-local
|
|
8
|
+
* provider ref, never on `@excitedjs/dreamux` core. The Dreamux host config
|
|
9
|
+
* module re-exports these so
|
|
10
|
+
* the non-builtin callers (doctor, daemon, tests) keep their import paths.
|
|
11
|
+
*/
|
|
12
|
+
import { BUILTIN_CODEX_PROVIDER_REF } from './provider-ref.js';
|
|
13
|
+
import { readOptionalString, rejectUnknownKeys, requirePositiveInt, requireStringArray, requireStringRecord, } from '@excitedjs/dreamux-utils';
|
|
14
|
+
/**
|
|
15
|
+
* Default `dispatchers[].runtime.config.bin`. The Codex binary path is
|
|
16
|
+
* dispatcher-local; `CODEX_HOST_CODEX_BIN` is a host-level override above it,
|
|
17
|
+
* not the source.
|
|
18
|
+
*/
|
|
19
|
+
export const DEFAULT_CODEX_BIN = 'codex';
|
|
20
|
+
/** Default `dispatchers[].runtime.config.initialize_timeout_ms` (handshake timeout, ms). */
|
|
21
|
+
export const DEFAULT_INITIALIZE_TIMEOUT_MS = 10_000;
|
|
22
|
+
/**
|
|
23
|
+
* Default per-turn deadline for a `builtin:codex` TeamMate worker (ms).
|
|
24
|
+
* Generous enough not to interrupt a legitimately long tool-using turn, but
|
|
25
|
+
* finite so a worker whose turn stalls after start cannot sit `running` with no
|
|
26
|
+
* visible outcome (issue #126). Operators override via
|
|
27
|
+
* `dispatchers[].runtime.config.turn_timeout_ms`.
|
|
28
|
+
*/
|
|
29
|
+
export const DEFAULT_CODEX_TURN_TIMEOUT_MS = 600_000;
|
|
30
|
+
/** Default `dispatchers[].runtime.config.approval_policy` when omitted. */
|
|
31
|
+
export const DEFAULT_APPROVAL_POLICY = 'never';
|
|
32
|
+
/** Default `dispatchers[].runtime.config.sandbox_mode` when omitted. */
|
|
33
|
+
export const DEFAULT_SANDBOX_MODE = 'workspace-write';
|
|
34
|
+
export const ALLOWED_APPROVAL_POLICIES = new Set([
|
|
35
|
+
'never',
|
|
36
|
+
'auto',
|
|
37
|
+
'auto-approve',
|
|
38
|
+
'on-failure',
|
|
39
|
+
]);
|
|
40
|
+
export const ALLOWED_SANDBOX_MODES = new Set([
|
|
41
|
+
'read-only',
|
|
42
|
+
'workspace-write',
|
|
43
|
+
'danger-full-access',
|
|
44
|
+
]);
|
|
45
|
+
export function defaultDispatcherCodexConfig() {
|
|
46
|
+
return {
|
|
47
|
+
bin: DEFAULT_CODEX_BIN,
|
|
48
|
+
approval_policy: DEFAULT_APPROVAL_POLICY,
|
|
49
|
+
sandbox_mode: DEFAULT_SANDBOX_MODE,
|
|
50
|
+
extra_args: [],
|
|
51
|
+
extra_env: {},
|
|
52
|
+
initialize_timeout_ms: DEFAULT_INITIALIZE_TIMEOUT_MS,
|
|
53
|
+
turn_timeout_ms: DEFAULT_CODEX_TURN_TIMEOUT_MS,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function readDispatcherCodexConfig(rawCodex, file, prefix) {
|
|
57
|
+
rejectUnknownKeys(rawCodex, new Set([
|
|
58
|
+
'bin',
|
|
59
|
+
'approval_policy',
|
|
60
|
+
'sandbox_mode',
|
|
61
|
+
'extra_args',
|
|
62
|
+
'extra_env',
|
|
63
|
+
'initialize_timeout_ms',
|
|
64
|
+
'turn_timeout_ms',
|
|
65
|
+
]), file, prefix);
|
|
66
|
+
// An omitted (or explicitly null) field falls back to the dispatcher-local
|
|
67
|
+
// default. Before the top-level block was removed, `null` meant "inherit the
|
|
68
|
+
// global default"; with no global, it simply means "use the built-in".
|
|
69
|
+
const defaults = defaultDispatcherCodexConfig();
|
|
70
|
+
const bin = readOptionalString(rawCodex, 'bin', file, prefix) ?? defaults.bin;
|
|
71
|
+
if (bin.trim() === '') {
|
|
72
|
+
throw new Error(`dreamux config error in ${file}: ${prefix}bin must be a non-empty string`);
|
|
73
|
+
}
|
|
74
|
+
const approvalPolicy = readOptionalString(rawCodex, 'approval_policy', file, prefix) ??
|
|
75
|
+
defaults.approval_policy;
|
|
76
|
+
if (!ALLOWED_APPROVAL_POLICIES.has(approvalPolicy)) {
|
|
77
|
+
throw new Error(`dreamux config error in ${file}: ${prefix}approval_policy='${approvalPolicy}' is not one of ${Array.from(ALLOWED_APPROVAL_POLICIES).join(' | ')}`);
|
|
78
|
+
}
|
|
79
|
+
const sandboxMode = readOptionalString(rawCodex, 'sandbox_mode', file, prefix) ??
|
|
80
|
+
defaults.sandbox_mode;
|
|
81
|
+
if (!ALLOWED_SANDBOX_MODES.has(sandboxMode)) {
|
|
82
|
+
throw new Error(`dreamux config error in ${file}: ${prefix}sandbox_mode='${sandboxMode}' is not one of ${Array.from(ALLOWED_SANDBOX_MODES).join(' | ')}`);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
bin,
|
|
86
|
+
approval_policy: approvalPolicy,
|
|
87
|
+
sandbox_mode: sandboxMode,
|
|
88
|
+
extra_args: requireStringArray(rawCodex, 'extra_args', defaults.extra_args, file, prefix),
|
|
89
|
+
extra_env: requireStringRecord(rawCodex, 'extra_env', defaults.extra_env, file, prefix),
|
|
90
|
+
initialize_timeout_ms: requirePositiveInt(rawCodex, 'initialize_timeout_ms', defaults.initialize_timeout_ms, file, prefix),
|
|
91
|
+
turn_timeout_ms: requirePositiveInt(rawCodex, 'turn_timeout_ms', defaults.turn_timeout_ms, file, prefix),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Typed accessor for a dispatcher's resolved codex runtime config. Typed
|
|
96
|
+
* structurally (not against `DispatcherConfig`) so this module never imports
|
|
97
|
+
* the host config type — a full `DispatcherConfig` still satisfies it at the
|
|
98
|
+
* call sites.
|
|
99
|
+
*/
|
|
100
|
+
export function dispatcherCodexConfig(dispatcher) {
|
|
101
|
+
if (dispatcher.runtime.provider !== BUILTIN_CODEX_PROVIDER_REF) {
|
|
102
|
+
throw new Error(`dispatcher '${dispatcher.id}' runtime provider ${JSON.stringify(dispatcher.runtime.provider)} is not wired to Codex`);
|
|
103
|
+
}
|
|
104
|
+
return dispatcher.runtime.config;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `builtin:codex` self-reported doctor surface (issue #146 fold; relocated
|
|
3
|
+
* into the owning package by the issue #209 cleanup).
|
|
4
|
+
*
|
|
5
|
+
* Declares the codex bin check (deduped + executed by Dreamux core's doctor) and
|
|
6
|
+
* runs the codex-home validation plus the codex version gate (#147) itself,
|
|
7
|
+
* entirely against the neutral `@excitedjs/dreamux-types` diagnostic context. The
|
|
8
|
+
* representative app-server socket sample is derived from the neutral path
|
|
9
|
+
* context's `runtimeSocketDirs()`, so the package never names `~/.dreamux`.
|
|
10
|
+
*/
|
|
11
|
+
import type { AgentRuntimeDiagnostic } from '@excitedjs/dreamux-types';
|
|
12
|
+
import { type DispatcherCodexConfig } from './config.js';
|
|
13
|
+
export declare const codexAgentRuntimeDiagnostic: AgentRuntimeDiagnostic<DispatcherCodexConfig>;
|
|
14
|
+
//# sourceMappingURL=diagnostic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic.d.ts","sourceRoot":"","sources":["../src/diagnostic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAEV,sBAAsB,EAIvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAkCzD,eAAO,MAAM,2BAA2B,EAAE,sBAAsB,CAAC,qBAAqB,CAiCnF,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { codexArgsFromConfig, codexArgsToCli } from './args.js';
|
|
2
|
+
import { dispatcherCodexHomeDoctorContext, validateDispatcherCodexHome, } from './codex-home.js';
|
|
3
|
+
import { representativeCodexSocketPath } from './internal/socket.js';
|
|
4
|
+
import { resolveCodexBinPath } from './bin.js';
|
|
5
|
+
import { MIN_CODEX_VERSION, codexVersionSatisfies } from './version.js';
|
|
6
|
+
function codexBinCheckName(scope) {
|
|
7
|
+
return scope === 'managedService' ? 'managed service Codex binary' : 'codex binary';
|
|
8
|
+
}
|
|
9
|
+
async function checkCodexVersion(context, runner) {
|
|
10
|
+
const bin = resolveCodexBinPath(context.config.bin, context.env);
|
|
11
|
+
let raw;
|
|
12
|
+
try {
|
|
13
|
+
raw = await runner.capture(bin, ['--version'], { env: context.env });
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
17
|
+
return `could not determine Codex version from ${bin}: ${cause}; requires codex >= ${MIN_CODEX_VERSION}`;
|
|
18
|
+
}
|
|
19
|
+
if (codexVersionSatisfies(raw))
|
|
20
|
+
return null;
|
|
21
|
+
return (`Codex at ${bin} reported ${raw.trim() || '<empty>'}; requires codex >= ` +
|
|
22
|
+
`${MIN_CODEX_VERSION} for teammate completion delivery (thread/inject_items)`);
|
|
23
|
+
}
|
|
24
|
+
export const codexAgentRuntimeDiagnostic = {
|
|
25
|
+
binChecks(context) {
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
name: codexBinCheckName(context.scope),
|
|
29
|
+
bin: resolveCodexBinPath(context.config.bin, context.env),
|
|
30
|
+
args: ['--help'],
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
},
|
|
34
|
+
async runDiagnostic(context, runner) {
|
|
35
|
+
const cliArgs = codexArgsToCli(codexArgsFromConfig(context.config));
|
|
36
|
+
const socketDirs = context.paths?.runtimeSocketDirs() ?? [];
|
|
37
|
+
const homeContext = dispatcherCodexHomeDoctorContext(context.runtime_id, {
|
|
38
|
+
codexCliArgs: cliArgs,
|
|
39
|
+
socketPath: representativeCodexSocketPath(socketDirs, context.runtime_id),
|
|
40
|
+
});
|
|
41
|
+
const home = await validateDispatcherCodexHome(homeContext, {
|
|
42
|
+
env: context.env,
|
|
43
|
+
codexCliArgs: cliArgs,
|
|
44
|
+
});
|
|
45
|
+
const errors = [...home.errors];
|
|
46
|
+
const versionError = await checkCodexVersion(context, runner);
|
|
47
|
+
if (versionError !== null)
|
|
48
|
+
errors.push(versionError);
|
|
49
|
+
// Detail mirrors the old printCodexHomeDoctor line (the codex home path);
|
|
50
|
+
// per-problem lines live in `errors`.
|
|
51
|
+
return {
|
|
52
|
+
ok: errors.length === 0,
|
|
53
|
+
detail: homeContext.codexHome,
|
|
54
|
+
errors,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=diagnostic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic.js","sourceRoot":"","sources":["../src/diagnostic.ts"],"names":[],"mappings":"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"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collects a Codex turn from the JSON-RPC notification stream.
|
|
3
|
+
*
|
|
4
|
+
* Adapted from claudemux's `plugins/claudemux/core/src/engines/codex/events.ts`.
|
|
5
|
+
* We drop token-usage bookkeeping and `notLoaded` item merging. Feishu
|
|
6
|
+
* outbound delivery is MCP reply-only, so collected assistant text is for
|
|
7
|
+
* diagnostics and tests rather than channel forwarding.
|
|
8
|
+
*/
|
|
9
|
+
import type { CodexWsClient } from './rpc.js';
|
|
10
|
+
import type { ThreadItem, TurnStartResponse } from './types.js';
|
|
11
|
+
export interface CollectedTurn {
|
|
12
|
+
threadId: string;
|
|
13
|
+
turnId: string;
|
|
14
|
+
items: ThreadItem[];
|
|
15
|
+
}
|
|
16
|
+
export interface TurnCollector {
|
|
17
|
+
awaitTurn(turnId?: string): Promise<CollectedTurn>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* One observed Codex notification, redacted to method + ids + item type — never
|
|
21
|
+
* prompt/assistant text. Emitted to {@link TurnSubscriptionOptions.onTrace} for
|
|
22
|
+
* every notification so a caller can see what Codex emitted after `turn/start`
|
|
23
|
+
* (issue #126 PR8): the dispatcher never awaits completion, so the worker is the
|
|
24
|
+
* only consumer of this stream, and an empty/abnormal trace is the diagnostic
|
|
25
|
+
* that distinguishes an environment stall (auth/network/quota) from a missed
|
|
26
|
+
* terminal event.
|
|
27
|
+
*/
|
|
28
|
+
export interface TurnTraceEvent {
|
|
29
|
+
method: string;
|
|
30
|
+
/** `params.threadId` if present, else null (reveals a field-shape mismatch). */
|
|
31
|
+
threadId: string | null;
|
|
32
|
+
turnId: string | null;
|
|
33
|
+
/** `item.type` for `item/completed`; never the item text. */
|
|
34
|
+
itemType: string | null;
|
|
35
|
+
/** Whether this notification counted toward THIS subscription's thread. */
|
|
36
|
+
matched: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface TurnSubscriptionOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Accept `turn/completed` / `item/completed` even when the notification's
|
|
41
|
+
* `threadId` field does not match. A per-task worker app-server hosts exactly
|
|
42
|
+
* one thread, so any completion on its socket IS this task's completion;
|
|
43
|
+
* leniency makes the worker robust to a `threadId` field-shape drift in the
|
|
44
|
+
* Codex protocol that the strict dispatcher path never exercises. Default
|
|
45
|
+
* false preserves the strict, thread-scoped dispatcher behaviour.
|
|
46
|
+
*/
|
|
47
|
+
acceptAnyThread?: boolean;
|
|
48
|
+
/** Diagnostic hook fired for EVERY notification, before any filtering. */
|
|
49
|
+
onTrace?: (event: TurnTraceEvent) => void;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Subscribe to turn notifications for one thread. Returns a collector whose
|
|
53
|
+
* `awaitTurn()` resolves on `turn/completed` and REJECTS on a terminal turn
|
|
54
|
+
* failure — either an `error` notification with `willRetry === false` (a fatal
|
|
55
|
+
* error that interrupts the turn; codex emits no `turn/completed` after it, so a
|
|
56
|
+
* resolve-only collector would hang forever) or a `turn/completed` carrying a
|
|
57
|
+
* `turn.error`. Items arriving on the parallel `item/completed` stream are
|
|
58
|
+
* buffered and merged into the resolved turn.
|
|
59
|
+
*/
|
|
60
|
+
export declare function subscribeTurnCollection(client: CodexWsClient, threadId: string, options?: TurnSubscriptionOptions): TurnCollector;
|
|
61
|
+
/**
|
|
62
|
+
* Append raw Responses API items to a thread's model-visible history without
|
|
63
|
+
* starting a turn (`thread/inject_items`, codex 0.137+). codex folds the items
|
|
64
|
+
* onto the active turn when one is running and otherwise records them against a
|
|
65
|
+
* default turn context (codex_thread.rs `inject_response_items` →
|
|
66
|
+
* `inject_no_new_turn`); either way it never rejects on a busy thread, so a
|
|
67
|
+
* rejection here is a genuine RPC error. Persisted to the rollout, so injected
|
|
68
|
+
* items survive resume.
|
|
69
|
+
*/
|
|
70
|
+
export declare function injectThreadItems(client: CodexWsClient, threadId: string, items: ReadonlyArray<Record<string, unknown>>): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Send a `turn/start` request and resolve once Codex accepts the submission.
|
|
73
|
+
* This is the production Feishu inbound primitive: it intentionally does not
|
|
74
|
+
* wait for `turn/completed`.
|
|
75
|
+
*/
|
|
76
|
+
export declare function submitTurnStart(client: CodexWsClient, threadId: string, prompt: string, cwd: string | null): Promise<TurnStartResponse>;
|
|
77
|
+
/**
|
|
78
|
+
* Send a `turn/start` request and await `turn/completed`.
|
|
79
|
+
* Returns the collected turn, or throws on RPC failure.
|
|
80
|
+
*/
|
|
81
|
+
export declare function runTurn(client: CodexWsClient, threadId: string, prompt: string, cwd: string | null): Promise<CollectedTurn>;
|
|
82
|
+
/**
|
|
83
|
+
* Extract the final assistant message text from a collected turn.
|
|
84
|
+
* Returns null if the turn had no assistant message — caller decides
|
|
85
|
+
* what to surface to the user (see issue #2 §"开放问题 Q4").
|
|
86
|
+
*/
|
|
87
|
+
export declare function extractAssistantText(turn: CollectedTurn): string | null;
|
|
88
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAEV,UAAU,EAGV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACpD;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,uBAA4B,GACpC,aAAa,CAyJf;AAaD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAQ5B;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC,aAAa,CAAC,CAIxB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAOvE"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collects a Codex turn from the JSON-RPC notification stream.
|
|
3
|
+
*
|
|
4
|
+
* Adapted from claudemux's `plugins/claudemux/core/src/engines/codex/events.ts`.
|
|
5
|
+
* We drop token-usage bookkeeping and `notLoaded` item merging. Feishu
|
|
6
|
+
* outbound delivery is MCP reply-only, so collected assistant text is for
|
|
7
|
+
* diagnostics and tests rather than channel forwarding.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Subscribe to turn notifications for one thread. Returns a collector whose
|
|
11
|
+
* `awaitTurn()` resolves on `turn/completed` and REJECTS on a terminal turn
|
|
12
|
+
* failure — either an `error` notification with `willRetry === false` (a fatal
|
|
13
|
+
* error that interrupts the turn; codex emits no `turn/completed` after it, so a
|
|
14
|
+
* resolve-only collector would hang forever) or a `turn/completed` carrying a
|
|
15
|
+
* `turn.error`. Items arriving on the parallel `item/completed` stream are
|
|
16
|
+
* buffered and merged into the resolved turn.
|
|
17
|
+
*/
|
|
18
|
+
export function subscribeTurnCollection(client, threadId, options = {}) {
|
|
19
|
+
const acceptAnyThread = options.acceptAnyThread === true;
|
|
20
|
+
const itemsByTurn = new Map();
|
|
21
|
+
const completedByTurn = new Map();
|
|
22
|
+
const failuresByTurn = new Map();
|
|
23
|
+
let firstCompleted = null;
|
|
24
|
+
let firstFailure = null;
|
|
25
|
+
let unscopedFailure = null;
|
|
26
|
+
let closed = false;
|
|
27
|
+
let awaiting = null;
|
|
28
|
+
const closeCollector = () => {
|
|
29
|
+
closed = true;
|
|
30
|
+
itemsByTurn.clear();
|
|
31
|
+
};
|
|
32
|
+
const resolveAwaiting = () => {
|
|
33
|
+
if (awaiting === null)
|
|
34
|
+
return;
|
|
35
|
+
const expectedTurnId = awaiting.turnId;
|
|
36
|
+
if (unscopedFailure !== null) {
|
|
37
|
+
awaiting.reject(unscopedFailure);
|
|
38
|
+
awaiting = null;
|
|
39
|
+
closeCollector();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (expectedTurnId !== null) {
|
|
43
|
+
const failure = failuresByTurn.get(expectedTurnId);
|
|
44
|
+
if (failure !== undefined) {
|
|
45
|
+
awaiting.reject(failure);
|
|
46
|
+
awaiting = null;
|
|
47
|
+
closeCollector();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const completed = completedByTurn.get(expectedTurnId);
|
|
51
|
+
if (completed !== undefined) {
|
|
52
|
+
awaiting.resolve(completed);
|
|
53
|
+
awaiting = null;
|
|
54
|
+
closeCollector();
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (firstFailure !== null) {
|
|
59
|
+
awaiting.reject(firstFailure);
|
|
60
|
+
awaiting = null;
|
|
61
|
+
closeCollector();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (firstCompleted !== null) {
|
|
65
|
+
awaiting.resolve(firstCompleted);
|
|
66
|
+
awaiting = null;
|
|
67
|
+
closeCollector();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
client.onNotification((notif) => {
|
|
71
|
+
const p = (notif.params ?? {});
|
|
72
|
+
const nThreadId = typeof p['threadId'] === 'string' ? p['threadId'] : null;
|
|
73
|
+
const matches = acceptAnyThread || nThreadId === threadId;
|
|
74
|
+
if (options.onTrace !== undefined) {
|
|
75
|
+
options.onTrace({
|
|
76
|
+
method: notif.method,
|
|
77
|
+
threadId: nThreadId,
|
|
78
|
+
turnId: traceTurnId(p),
|
|
79
|
+
itemType: traceItemType(p),
|
|
80
|
+
matched: matches,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (closed || !matches)
|
|
84
|
+
return;
|
|
85
|
+
if (notif.method === 'item/completed') {
|
|
86
|
+
const params = notif.params;
|
|
87
|
+
const bucket = itemsByTurn.get(params.turnId) ?? [];
|
|
88
|
+
bucket.push(params.item);
|
|
89
|
+
itemsByTurn.set(params.turnId, bucket);
|
|
90
|
+
}
|
|
91
|
+
else if (notif.method === 'turn/completed') {
|
|
92
|
+
const params = notif.params;
|
|
93
|
+
if (params.turn.error != null) {
|
|
94
|
+
const failure = new Error(params.turn.error.message || 'codex turn failed');
|
|
95
|
+
failuresByTurn.set(params.turn.id, failure);
|
|
96
|
+
firstFailure ??= failure;
|
|
97
|
+
resolveAwaiting();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const items = itemsByTurn.get(params.turn.id) ?? params.turn.items ?? [];
|
|
101
|
+
const completed = { threadId, turnId: params.turn.id, items };
|
|
102
|
+
completedByTurn.set(params.turn.id, completed);
|
|
103
|
+
firstCompleted ??= completed;
|
|
104
|
+
resolveAwaiting();
|
|
105
|
+
}
|
|
106
|
+
else if (notif.method === 'error') {
|
|
107
|
+
const params = notif.params;
|
|
108
|
+
// Only a fatal (non-retried) error terminates the turn. A transient
|
|
109
|
+
// `willRetry: true` error is followed by codex's own retry and an
|
|
110
|
+
// eventual `turn/completed`, so we ignore it here.
|
|
111
|
+
if (params.willRetry === false) {
|
|
112
|
+
const failure = new Error(params.error?.message ?? 'codex turn error');
|
|
113
|
+
if (typeof params.turnId === 'string')
|
|
114
|
+
failuresByTurn.set(params.turnId, failure);
|
|
115
|
+
else
|
|
116
|
+
unscopedFailure = failure;
|
|
117
|
+
firstFailure ??= failure;
|
|
118
|
+
resolveAwaiting();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return {
|
|
123
|
+
awaitTurn(turnId) {
|
|
124
|
+
const expectedTurnId = turnId ?? null;
|
|
125
|
+
if (unscopedFailure !== null) {
|
|
126
|
+
closeCollector();
|
|
127
|
+
return Promise.reject(unscopedFailure);
|
|
128
|
+
}
|
|
129
|
+
if (expectedTurnId !== null) {
|
|
130
|
+
const failure = failuresByTurn.get(expectedTurnId);
|
|
131
|
+
if (failure !== undefined) {
|
|
132
|
+
closeCollector();
|
|
133
|
+
return Promise.reject(failure);
|
|
134
|
+
}
|
|
135
|
+
const completed = completedByTurn.get(expectedTurnId);
|
|
136
|
+
if (completed !== undefined) {
|
|
137
|
+
closeCollector();
|
|
138
|
+
return Promise.resolve(completed);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
if (firstFailure !== null) {
|
|
143
|
+
closeCollector();
|
|
144
|
+
return Promise.reject(firstFailure);
|
|
145
|
+
}
|
|
146
|
+
if (firstCompleted !== null) {
|
|
147
|
+
closeCollector();
|
|
148
|
+
return Promise.resolve(firstCompleted);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (awaiting !== null)
|
|
152
|
+
return awaiting.promise;
|
|
153
|
+
let resolveTurn;
|
|
154
|
+
let rejectTurn;
|
|
155
|
+
const promise = new Promise((res, rej) => {
|
|
156
|
+
resolveTurn = res;
|
|
157
|
+
rejectTurn = rej;
|
|
158
|
+
});
|
|
159
|
+
awaiting = {
|
|
160
|
+
turnId: expectedTurnId,
|
|
161
|
+
promise,
|
|
162
|
+
resolve: resolveTurn,
|
|
163
|
+
reject: rejectTurn,
|
|
164
|
+
};
|
|
165
|
+
return promise;
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
function traceTurnId(params) {
|
|
170
|
+
if (typeof params['turnId'] === 'string')
|
|
171
|
+
return params['turnId'];
|
|
172
|
+
const turn = params['turn'];
|
|
173
|
+
return turn !== undefined && typeof turn.id === 'string' ? turn.id : null;
|
|
174
|
+
}
|
|
175
|
+
function traceItemType(params) {
|
|
176
|
+
const item = params['item'];
|
|
177
|
+
return item !== undefined && typeof item.type === 'string' ? item.type : null;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Append raw Responses API items to a thread's model-visible history without
|
|
181
|
+
* starting a turn (`thread/inject_items`, codex 0.137+). codex folds the items
|
|
182
|
+
* onto the active turn when one is running and otherwise records them against a
|
|
183
|
+
* default turn context (codex_thread.rs `inject_response_items` →
|
|
184
|
+
* `inject_no_new_turn`); either way it never rejects on a busy thread, so a
|
|
185
|
+
* rejection here is a genuine RPC error. Persisted to the rollout, so injected
|
|
186
|
+
* items survive resume.
|
|
187
|
+
*/
|
|
188
|
+
export async function injectThreadItems(client, threadId, items) {
|
|
189
|
+
await client.request('thread/inject_items', { threadId, items });
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Send a `turn/start` request and resolve once Codex accepts the submission.
|
|
193
|
+
* This is the production Feishu inbound primitive: it intentionally does not
|
|
194
|
+
* wait for `turn/completed`.
|
|
195
|
+
*/
|
|
196
|
+
export async function submitTurnStart(client, threadId, prompt, cwd) {
|
|
197
|
+
const input = [
|
|
198
|
+
{ type: 'text', text: prompt, text_elements: [] },
|
|
199
|
+
];
|
|
200
|
+
return client.request('turn/start', cwd === null ? { threadId, input } : { threadId, input, cwd });
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Send a `turn/start` request and await `turn/completed`.
|
|
204
|
+
* Returns the collected turn, or throws on RPC failure.
|
|
205
|
+
*/
|
|
206
|
+
export async function runTurn(client, threadId, prompt, cwd) {
|
|
207
|
+
const collector = subscribeTurnCollection(client, threadId);
|
|
208
|
+
const res = await submitTurnStart(client, threadId, prompt, cwd);
|
|
209
|
+
return collector.awaitTurn(res.turn.id);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Extract the final assistant message text from a collected turn.
|
|
213
|
+
* Returns null if the turn had no assistant message — caller decides
|
|
214
|
+
* what to surface to the user (see issue #2 §"开放问题 Q4").
|
|
215
|
+
*/
|
|
216
|
+
export function extractAssistantText(turn) {
|
|
217
|
+
const messages = turn.items.filter((it) => it.type === 'agentMessage');
|
|
218
|
+
if (messages.length === 0)
|
|
219
|
+
return null;
|
|
220
|
+
const last = messages[messages.length - 1];
|
|
221
|
+
return typeof last?.text === 'string' && last.text.length > 0
|
|
222
|
+
? last.text
|
|
223
|
+
: null;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex app-server LSP-style init handshake (required by codex 0.134+).
|
|
3
|
+
*
|
|
4
|
+
* Without this, every business RPC (`thread/start`, `turn/start`, …) is
|
|
5
|
+
* answered with `Not initialized` and the daemon never moves. The sequence
|
|
6
|
+
* is the canonical LSP one:
|
|
7
|
+
*
|
|
8
|
+
* 1. client → `initialize` request with ClientInfo + capabilities
|
|
9
|
+
* 2. server → InitializeResponse (userAgent, codexHome, platform info)
|
|
10
|
+
* 3. client → `initialized` notification (no params)
|
|
11
|
+
*
|
|
12
|
+
* Steps 1 + 3 are both required: codex's `Not initialized` guard is cleared
|
|
13
|
+
* only once the notification arrives. Capabilities can be omitted (the spec
|
|
14
|
+
* accepts `null`) — we pass an explicit default so the negotiation choices
|
|
15
|
+
* are visible in the source.
|
|
16
|
+
*/
|
|
17
|
+
import type { CodexWsClient } from './rpc.js';
|
|
18
|
+
import type { ClientInfo, InitializeCapabilities, InitializeResponse } from './types.js';
|
|
19
|
+
export interface HandshakeOptions {
|
|
20
|
+
clientInfo?: ClientInfo;
|
|
21
|
+
capabilities?: InitializeCapabilities | null;
|
|
22
|
+
/**
|
|
23
|
+
* Hard ceiling on how long to wait for the daemon's InitializeResponse
|
|
24
|
+
* before failing the handshake. Without this, a codex that accepts the
|
|
25
|
+
* WebSocket upgrade but never replies (hang, crash mid-response, wrong
|
|
26
|
+
* protocol version, …) would deadlock dispatcher startup indefinitely,
|
|
27
|
+
* blocking both server boot and any retry path. Default: 10_000 ms,
|
|
28
|
+
* which matches the spawn-readiness budget in CodexProcess.
|
|
29
|
+
*/
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Drive the full `initialize` + `initialized` exchange. Returns the
|
|
34
|
+
* server's InitializeResponse (userAgent, codexHome, platform) so callers
|
|
35
|
+
* can log it or surface it via admin.
|
|
36
|
+
*
|
|
37
|
+
* Times out (rejects) if the daemon does not reply within
|
|
38
|
+
* `options.timeoutMs`. The pending request stays in the client's `pending`
|
|
39
|
+
* map after timeout — callers that recover by tearing down the client
|
|
40
|
+
* (e.g. CodexRuntime's cleanupOnFailure) will then drop those
|
|
41
|
+
* pending entries when the WS connection closes.
|
|
42
|
+
*/
|
|
43
|
+
export declare function performInitializeHandshake(client: CodexWsClient, options?: HandshakeOptions): Promise<InitializeResponse>;
|
|
44
|
+
//# sourceMappingURL=handshake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../src/handshake.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EACV,UAAU,EACV,sBAAsB,EAEtB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAuBpB,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC7C;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAmB7B"}
|