@telora/daemon 0.16.7 → 0.16.16
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/build-info.json +7 -3
- package/dist/audit-phase.d.ts +14 -0
- package/dist/audit-phase.d.ts.map +1 -1
- package/dist/audit-phase.js +52 -12
- package/dist/audit-phase.js.map +1 -1
- package/dist/backends/agent-backend.d.ts +63 -0
- package/dist/backends/agent-backend.d.ts.map +1 -0
- package/dist/backends/agent-backend.js +19 -0
- package/dist/backends/agent-backend.js.map +1 -0
- package/dist/backends/availability.d.ts +28 -0
- package/dist/backends/availability.d.ts.map +1 -0
- package/dist/backends/availability.js +49 -0
- package/dist/backends/availability.js.map +1 -0
- package/dist/backends/claude/claude-backend.d.ts +12 -0
- package/dist/backends/claude/claude-backend.d.ts.map +1 -0
- package/dist/backends/claude/claude-backend.js +86 -0
- package/dist/backends/claude/claude-backend.js.map +1 -0
- package/dist/backends/codex/codex-backend.d.ts +23 -0
- package/dist/backends/codex/codex-backend.d.ts.map +1 -0
- package/dist/backends/codex/codex-backend.js +116 -0
- package/dist/backends/codex/codex-backend.js.map +1 -0
- package/dist/backends/index.d.ts +13 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +20 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/registry.d.ts +29 -0
- package/dist/backends/registry.d.ts.map +1 -0
- package/dist/backends/registry.js +45 -0
- package/dist/backends/registry.js.map +1 -0
- package/dist/backends/resolve.d.ts +44 -0
- package/dist/backends/resolve.d.ts.map +1 -0
- package/dist/backends/resolve.js +57 -0
- package/dist/backends/resolve.js.map +1 -0
- package/dist/completion-detector.d.ts +18 -16
- package/dist/completion-detector.d.ts.map +1 -1
- package/dist/completion-detector.js +36 -36
- package/dist/completion-detector.js.map +1 -1
- package/dist/directive-executor.d.ts +6 -1
- package/dist/directive-executor.d.ts.map +1 -1
- package/dist/directive-executor.js +26 -11
- package/dist/directive-executor.js.map +1 -1
- package/dist/focus-completion-event.d.ts +20 -7
- package/dist/focus-completion-event.d.ts.map +1 -1
- package/dist/focus-completion-event.js +29 -10
- package/dist/focus-completion-event.js.map +1 -1
- package/dist/focus-executor.d.ts +15 -1
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +129 -62
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-spawn-helpers.d.ts +2 -0
- package/dist/focus-spawn-helpers.d.ts.map +1 -1
- package/dist/focus-spawn-helpers.js +42 -37
- package/dist/focus-spawn-helpers.js.map +1 -1
- package/dist/git-merge.d.ts.map +1 -1
- package/dist/git-merge.js +42 -16
- package/dist/git-merge.js.map +1 -1
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +7 -0
- package/dist/heartbeat.js.map +1 -1
- package/dist/listener.d.ts.map +1 -1
- package/dist/listener.js +4 -1
- package/dist/listener.js.map +1 -1
- package/dist/merge-back-loop.d.ts.map +1 -1
- package/dist/merge-back-loop.js +1 -0
- package/dist/merge-back-loop.js.map +1 -1
- package/dist/output-monitor.d.ts +11 -6
- package/dist/output-monitor.d.ts.map +1 -1
- package/dist/output-monitor.js +53 -41
- package/dist/output-monitor.js.map +1 -1
- package/dist/queries/deliveries.d.ts +15 -0
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js +6 -0
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/focuses.d.ts +13 -1
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +17 -1
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/schemas.d.ts +12 -0
- package/dist/queries/schemas.d.ts.map +1 -1
- package/dist/queries/schemas.js +15 -0
- package/dist/queries/schemas.js.map +1 -1
- package/dist/session-lifecycle.d.ts.map +1 -1
- package/dist/session-lifecycle.js +4 -2
- package/dist/session-lifecycle.js.map +1 -1
- package/dist/session-lineage.d.ts +68 -0
- package/dist/session-lineage.d.ts.map +1 -0
- package/dist/session-lineage.js +63 -0
- package/dist/session-lineage.js.map +1 -0
- package/dist/spawn-environment.d.ts +11 -0
- package/dist/spawn-environment.d.ts.map +1 -1
- package/dist/spawn-environment.js +27 -0
- package/dist/spawn-environment.js.map +1 -1
- package/dist/spawner-lifecycle.d.ts +27 -7
- package/dist/spawner-lifecycle.d.ts.map +1 -1
- package/dist/spawner-lifecycle.js +40 -21
- package/dist/spawner-lifecycle.js.map +1 -1
- package/dist/spawner-stream-handlers.d.ts +3 -2
- package/dist/spawner-stream-handlers.d.ts.map +1 -1
- package/dist/spawner-stream-handlers.js +37 -34
- package/dist/spawner-stream-handlers.js.map +1 -1
- package/dist/spawner.d.ts +8 -17
- package/dist/spawner.d.ts.map +1 -1
- package/dist/spawner.js +8 -319
- package/dist/spawner.js.map +1 -1
- package/dist/team-prompt-base.d.ts +35 -2
- package/dist/team-prompt-base.d.ts.map +1 -1
- package/dist/team-prompt-base.js +93 -9
- package/dist/team-prompt-base.js.map +1 -1
- package/dist/team-spawner.d.ts +21 -3
- package/dist/team-spawner.d.ts.map +1 -1
- package/dist/team-spawner.js +49 -34
- package/dist/team-spawner.js.map +1 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/focus.d.ts +10 -0
- package/dist/types/focus.d.ts.map +1 -1
- package/dist/types/session.d.ts +4 -4
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/workflow.d.ts +17 -0
- package/dist/types/workflow.d.ts.map +1 -1
- package/package.json +3 -3
package/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commitSha": "
|
|
3
|
-
"builtAt": "2026-05-
|
|
2
|
+
"commitSha": "f1330817",
|
|
3
|
+
"builtAt": "2026-05-26T14:53:55.053Z",
|
|
4
4
|
"expectedMigrations": [
|
|
5
5
|
"20250829113330_create_org_nodes_table.sql",
|
|
6
6
|
"20250829113402_fix_function_security_search_path.sql",
|
|
@@ -588,6 +588,10 @@
|
|
|
588
588
|
"20260524122441_create_focus_token_detail_views.sql",
|
|
589
589
|
"20260524163802_drop_delivery_scoped_security_workflow_assignment.sql",
|
|
590
590
|
"20260524165444_resolve_effective_workflow_deterministic_builtin_fallback.sql",
|
|
591
|
-
"
|
|
591
|
+
"20260525092825_focus_lineage_session_ids.sql",
|
|
592
|
+
"20260525094853_focus_directive_lineage_continuity.sql",
|
|
593
|
+
"20260525095445_review_lineage_resume.sql",
|
|
594
|
+
"20260525124226_coding_stage_delivery_index.sql",
|
|
595
|
+
"20260526025901_engine_selection_columns.sql"
|
|
592
596
|
]
|
|
593
597
|
}
|
package/dist/audit-phase.d.ts
CHANGED
|
@@ -28,6 +28,12 @@ export declare const AUDIT_MCP_TOOLS: readonly string[];
|
|
|
28
28
|
export declare const AUDIT_DEFAULT_MODEL = "sonnet";
|
|
29
29
|
/** Default timeout for the assessor session (15 minutes). */
|
|
30
30
|
export declare const AUDIT_DEFAULT_TIMEOUT_MS: number;
|
|
31
|
+
/**
|
|
32
|
+
* Session lineage key for the audit assessor (INJ-E). The audit loop phase
|
|
33
|
+
* declares continuity 'resume' so the differential receiver accumulates
|
|
34
|
+
* cross-cycle memory of the gap's trajectory (convergence vs oscillation).
|
|
35
|
+
*/
|
|
36
|
+
export declare const AUDIT_LINEAGE = "audit";
|
|
31
37
|
/**
|
|
32
38
|
* Audit prompt. The assessor is told its role, given the assembled context
|
|
33
39
|
* via stdin/CLI, and instructed to emit a fenced audit-summary tail block
|
|
@@ -67,6 +73,14 @@ export interface AuditPhaseDeps {
|
|
|
67
73
|
spawnAuditAgent: (opts: AuditSpawnOptions) => Promise<AuditSpawnResult>;
|
|
68
74
|
parseAuditSummary?: (stdout: string) => AuditSummary;
|
|
69
75
|
getConfig: () => DaemonConfig;
|
|
76
|
+
/**
|
|
77
|
+
* Resolve the prior session id for a focus's lineage (INJ-E). Returns null
|
|
78
|
+
* when there is no recorded session (first cycle). Optional so existing
|
|
79
|
+
* callers/tests that omit it simply get a fresh (non-resumed) assessor.
|
|
80
|
+
*/
|
|
81
|
+
getResumeSessionId?: (focusId: string, lineage: string) => Promise<string | null>;
|
|
82
|
+
/** Persist the assessor's session id under the focus's lineage (INJ-E). */
|
|
83
|
+
persistSessionId?: (focusId: string, lineage: string, sessionId: string) => Promise<void>;
|
|
70
84
|
}
|
|
71
85
|
/**
|
|
72
86
|
* Parse the audit-summary tail block from assessor stdout. Returns null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-phase.d.ts","sourceRoot":"","sources":["../src/audit-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"audit-phase.d.ts","sourceRoot":"","sources":["../src/audit-phase.ts"],"names":[],"mappings":"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"}
|
package/dist/audit-phase.js
CHANGED
|
@@ -15,7 +15,8 @@ import { resolveAssemblyRecipe } from './assembly-engine.js';
|
|
|
15
15
|
import './assembly-resolvers.js';
|
|
16
16
|
import { getRecentFocusCycleEvaluation, } from './queries/focus-cycle-evaluations.js';
|
|
17
17
|
import { insertAuditRun, updateAuditRun } from './queries/audit-runs.js';
|
|
18
|
-
import { getFocusDeliveries } from './queries/focuses.js';
|
|
18
|
+
import { getFocusDeliveries, getFocusSessionIds, updateFocusClaudeSessionId } from './queries/focuses.js';
|
|
19
|
+
import { resolveResumeId } from './session-lineage.js';
|
|
19
20
|
import { getConfig } from './queries/shared.js';
|
|
20
21
|
import { spawnAuditAgent as spawnerSpawnAuditAgent, } from './spawner.js';
|
|
21
22
|
// ---------------------------------------------------------------------------
|
|
@@ -47,6 +48,12 @@ export const AUDIT_MCP_TOOLS = [
|
|
|
47
48
|
export const AUDIT_DEFAULT_MODEL = 'sonnet';
|
|
48
49
|
/** Default timeout for the assessor session (15 minutes). */
|
|
49
50
|
export const AUDIT_DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
|
|
51
|
+
/**
|
|
52
|
+
* Session lineage key for the audit assessor (INJ-E). The audit loop phase
|
|
53
|
+
* declares continuity 'resume' so the differential receiver accumulates
|
|
54
|
+
* cross-cycle memory of the gap's trajectory (convergence vs oscillation).
|
|
55
|
+
*/
|
|
56
|
+
export const AUDIT_LINEAGE = 'audit';
|
|
50
57
|
/**
|
|
51
58
|
* Audit prompt. The assessor is told its role, given the assembled context
|
|
52
59
|
* via stdin/CLI, and instructed to emit a fenced audit-summary tail block
|
|
@@ -165,6 +172,13 @@ export const defaultAuditDeps = {
|
|
|
165
172
|
spawnAuditAgent: (opts) => spawnerSpawnAuditAgent(opts),
|
|
166
173
|
parseAuditSummary,
|
|
167
174
|
getConfig,
|
|
175
|
+
getResumeSessionId: async (focusId, lineage) => {
|
|
176
|
+
const map = await getFocusSessionIds(focusId);
|
|
177
|
+
// The audit phase declares continuity 'resume' (it is a loop phase, not a
|
|
178
|
+
// workflow stage); resolveResumeId keeps the resume rule uniform.
|
|
179
|
+
return resolveResumeId({ sessionMap: map, lineage, continuity: 'resume' });
|
|
180
|
+
},
|
|
181
|
+
persistSessionId: (focusId, lineage, sessionId) => updateFocusClaudeSessionId(focusId, lineage, sessionId),
|
|
168
182
|
};
|
|
169
183
|
// ---------------------------------------------------------------------------
|
|
170
184
|
// Core phase
|
|
@@ -193,21 +207,22 @@ export async function runAuditPhase(focusId, deps = defaultAuditDeps) {
|
|
|
193
207
|
catch (err) {
|
|
194
208
|
errors.push(`assembly: ${err.message}`);
|
|
195
209
|
}
|
|
196
|
-
let auditRunId = null;
|
|
197
|
-
try {
|
|
198
|
-
const row = await deps.insertAuditRun({
|
|
199
|
-
focusId, cycleNumber, model: AUDIT_DEFAULT_MODEL, sessionId: null,
|
|
200
|
-
});
|
|
201
|
-
auditRunId = row.id;
|
|
202
|
-
metadata.auditRunId = row.id;
|
|
203
|
-
}
|
|
204
|
-
catch (err) {
|
|
205
|
-
errors.push(`insert_audit_run: ${err.message}`);
|
|
206
|
-
}
|
|
207
210
|
const config = deps.getConfig();
|
|
208
211
|
const prompt = assembled
|
|
209
212
|
? `${assembled}\n\n---\n\n${AUDIT_PROMPT}`
|
|
210
213
|
: AUDIT_PROMPT;
|
|
214
|
+
// Resolve the prior audit-lineage session id to resume (INJ-E). Best-effort:
|
|
215
|
+
// a lookup failure or an empty slot (first cycle) just yields a fresh session.
|
|
216
|
+
let resumeSessionId = null;
|
|
217
|
+
if (deps.getResumeSessionId) {
|
|
218
|
+
try {
|
|
219
|
+
resumeSessionId = await deps.getResumeSessionId(focusId, AUDIT_LINEAGE);
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
errors.push(`resume_lookup: ${err.message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
metadata.resumed = !!resumeSessionId;
|
|
211
226
|
let spawnResult;
|
|
212
227
|
try {
|
|
213
228
|
spawnResult = await deps.spawnAuditAgent({
|
|
@@ -219,12 +234,37 @@ export async function runAuditPhase(focusId, deps = defaultAuditDeps) {
|
|
|
219
234
|
model: AUDIT_DEFAULT_MODEL,
|
|
220
235
|
timeoutMs: AUDIT_DEFAULT_TIMEOUT_MS,
|
|
221
236
|
allowedTools: AUDIT_MCP_TOOLS,
|
|
237
|
+
resumeSessionId,
|
|
222
238
|
});
|
|
223
239
|
}
|
|
224
240
|
catch (err) {
|
|
225
241
|
errors.push(`spawn: ${err.message}`);
|
|
226
242
|
spawnResult = { exitCode: null, stdout: '', stderr: '', errorMessage: err.message };
|
|
227
243
|
}
|
|
244
|
+
// Persist the assessor's session id under the focus's 'audit' lineage so the
|
|
245
|
+
// next cycle resumes it (INJ-E). Best-effort -- a persist failure only loses
|
|
246
|
+
// continuity for the next cycle, it never fails the audit.
|
|
247
|
+
if (spawnResult.sessionId && deps.persistSessionId) {
|
|
248
|
+
metadata.auditSessionId = spawnResult.sessionId;
|
|
249
|
+
try {
|
|
250
|
+
await deps.persistSessionId(focusId, AUDIT_LINEAGE, spawnResult.sessionId);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
errors.push(`persist_session_id: ${err.message}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Record the audit run (after spawn, so the row carries the session id).
|
|
257
|
+
let auditRunId = null;
|
|
258
|
+
try {
|
|
259
|
+
const row = await deps.insertAuditRun({
|
|
260
|
+
focusId, cycleNumber, model: AUDIT_DEFAULT_MODEL, sessionId: spawnResult.sessionId ?? null,
|
|
261
|
+
});
|
|
262
|
+
auditRunId = row.id;
|
|
263
|
+
metadata.auditRunId = row.id;
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
errors.push(`insert_audit_run: ${err.message}`);
|
|
267
|
+
}
|
|
228
268
|
if (spawnResult.errorMessage) {
|
|
229
269
|
errors.push(`spawn: ${spawnResult.errorMessage}`);
|
|
230
270
|
}
|
package/dist/audit-phase.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-phase.js","sourceRoot":"","sources":["../src/audit-phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,qBAAqB,EAAwB,MAAM,sBAAsB,CAAC;AACnF,oEAAoE;AACpE,OAAO,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,GAE9B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAoB,MAAM,yBAAyB,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"audit-phase.js","sourceRoot":"","sources":["../src/audit-phase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentBackend interface -- the engine-agnostic seam for spawning coding agents.
|
|
3
|
+
*
|
|
4
|
+
* The daemon's focus-execution path used to be welded to Claude Code (the
|
|
5
|
+
* `claude` binary, stream-json I/O, `--resume` session ids). An `AgentBackend`
|
|
6
|
+
* abstracts the four engine-specific concerns behind one interface so the daemon
|
|
7
|
+
* can run a focus on any registered engine:
|
|
8
|
+
*
|
|
9
|
+
* 1. spawn-arg / resume-arg construction (CLI invocation per engine)
|
|
10
|
+
* 2. input encoding (how a prompt/message is written to the process)
|
|
11
|
+
* 3. an event-parser factory (engine stream -> neutral AgentEvent stream)
|
|
12
|
+
* 4. an availability probe (is this engine installed + authenticated here?)
|
|
13
|
+
*
|
|
14
|
+
* Session-id capture rides on the parser (`AgentEventParser.sessionId`, set from
|
|
15
|
+
* the engine's neutral `session_started` event). Backends are looked up by id
|
|
16
|
+
* from the registry (./registry.ts); `claude` is the only one registered in D1.
|
|
17
|
+
*/
|
|
18
|
+
import type { AgentEventParser } from '@telora/daemon-core';
|
|
19
|
+
import type { DaemonConfig } from '../types.js';
|
|
20
|
+
/** Inputs that vary per fresh spawn. */
|
|
21
|
+
export interface AgentSpawnContext {
|
|
22
|
+
/** Daemon config -- backends read what they need (paths, tracker id, URL). */
|
|
23
|
+
config: DaemonConfig;
|
|
24
|
+
/** Worktree the agent runs in. Claude uses the spawn cwd; Codex needs `--cd`. */
|
|
25
|
+
worktreePath: string;
|
|
26
|
+
/** Model override (e.g. from pipeline config or a stage directive). */
|
|
27
|
+
model?: string | null;
|
|
28
|
+
}
|
|
29
|
+
/** Inputs for resuming a prior session. */
|
|
30
|
+
export interface AgentResumeContext extends AgentSpawnContext {
|
|
31
|
+
/** The engine session id to resume (captured from a prior session_started). */
|
|
32
|
+
resumeSessionId: string;
|
|
33
|
+
}
|
|
34
|
+
/** Result of probing whether a backend is usable on the current daemon host. */
|
|
35
|
+
export interface BackendAvailability {
|
|
36
|
+
/** True when the engine CLI is present (and, where checkable, authenticated). */
|
|
37
|
+
available: boolean;
|
|
38
|
+
/** Human-readable reason when unavailable (drives picker help text in D4). */
|
|
39
|
+
detail?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* One coding-agent engine (Claude Code, Codex, ...). Implementations are
|
|
43
|
+
* registered in the backend registry and resolved by `id`.
|
|
44
|
+
*/
|
|
45
|
+
export interface AgentBackend {
|
|
46
|
+
/** Stable engine id used as the registry key (e.g. "claude", "codex"). */
|
|
47
|
+
readonly id: string;
|
|
48
|
+
/** Human-friendly name for UI/logs (e.g. "Claude Code"). */
|
|
49
|
+
readonly displayName: string;
|
|
50
|
+
/** Resolve the executable command for this engine from daemon config. */
|
|
51
|
+
resolveCommand(config: DaemonConfig): string;
|
|
52
|
+
/** Build CLI args for a fresh (non-resume) spawn. */
|
|
53
|
+
buildSpawnArgs(ctx: AgentSpawnContext): string[];
|
|
54
|
+
/** Build CLI args for resuming a prior session. */
|
|
55
|
+
buildResumeArgs(ctx: AgentResumeContext): string[];
|
|
56
|
+
/** Encode a prompt/message into the exact bytes to write to the process stdin. */
|
|
57
|
+
encodeInput(content: string): string;
|
|
58
|
+
/** Create a fresh parser that maps this engine's stream to AgentEvents. */
|
|
59
|
+
createParser(): AgentEventParser;
|
|
60
|
+
/** Probe whether this engine is available on the current daemon host. */
|
|
61
|
+
probeAvailability(config: DaemonConfig): Promise<BackendAvailability>;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=agent-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-backend.d.ts","sourceRoot":"","sources":["../../src/backends/agent-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC,8EAA8E;IAC9E,MAAM,EAAE,YAAY,CAAC;IACrB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAmB,SAAQ,iBAAiB;IAC3D,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,gFAAgF;AAChF,MAAM,WAAW,mBAAmB;IAClC,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,yEAAyE;IACzE,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC;IAE7C,qDAAqD;IACrD,cAAc,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAAC;IAEjD,mDAAmD;IACnD,eAAe,CAAC,GAAG,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAAC;IAEnD,kFAAkF;IAClF,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAErC,2EAA2E;IAC3E,YAAY,IAAI,gBAAgB,CAAC;IAEjC,yEAAyE;IACzE,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACvE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentBackend interface -- the engine-agnostic seam for spawning coding agents.
|
|
3
|
+
*
|
|
4
|
+
* The daemon's focus-execution path used to be welded to Claude Code (the
|
|
5
|
+
* `claude` binary, stream-json I/O, `--resume` session ids). An `AgentBackend`
|
|
6
|
+
* abstracts the four engine-specific concerns behind one interface so the daemon
|
|
7
|
+
* can run a focus on any registered engine:
|
|
8
|
+
*
|
|
9
|
+
* 1. spawn-arg / resume-arg construction (CLI invocation per engine)
|
|
10
|
+
* 2. input encoding (how a prompt/message is written to the process)
|
|
11
|
+
* 3. an event-parser factory (engine stream -> neutral AgentEvent stream)
|
|
12
|
+
* 4. an availability probe (is this engine installed + authenticated here?)
|
|
13
|
+
*
|
|
14
|
+
* Session-id capture rides on the parser (`AgentEventParser.sessionId`, set from
|
|
15
|
+
* the engine's neutral `session_started` event). Backends are looked up by id
|
|
16
|
+
* from the registry (./registry.ts); `claude` is the only one registered in D1.
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=agent-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-backend.js","sourceRoot":"","sources":["../../src/backends/agent-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine availability probing for the daemon host.
|
|
3
|
+
*
|
|
4
|
+
* On connect (via the heartbeat metadata), the daemon publishes which
|
|
5
|
+
* registered engines are usable on its host so the app's engine picker can
|
|
6
|
+
* grey out the rest. The probe runs once per daemon process and is cached:
|
|
7
|
+
* installed CLIs don't change during a run, and a restart re-probes.
|
|
8
|
+
*/
|
|
9
|
+
import type { DaemonConfig } from '../types.js';
|
|
10
|
+
/** One engine's availability on this host, as published to the app. */
|
|
11
|
+
export interface BackendAvailabilityReport {
|
|
12
|
+
/** Registry id (e.g. 'claude', 'codex'). */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Human-friendly name. */
|
|
15
|
+
displayName: string;
|
|
16
|
+
/** True when the engine CLI is present (and, where checkable, authenticated). */
|
|
17
|
+
available: boolean;
|
|
18
|
+
/** Why unavailable (host + fix command); drives the picker's help text. */
|
|
19
|
+
detail?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Probe every registered backend's availability on this host. Cached after the
|
|
23
|
+
* first call (the result is stable for the life of the daemon process).
|
|
24
|
+
*/
|
|
25
|
+
export declare function probeAllBackends(config: DaemonConfig): Promise<BackendAvailabilityReport[]>;
|
|
26
|
+
/** Test-only: clear the cached probe so the next call re-probes. */
|
|
27
|
+
export declare function _resetAvailabilityCache(): void;
|
|
28
|
+
//# sourceMappingURL=availability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../../src/backends/availability.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,uEAAuE;AACvE,MAAM,WAAW,yBAAyB;IACxC,4CAA4C;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAK3F;AAED,oEAAoE;AACpE,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine availability probing for the daemon host.
|
|
3
|
+
*
|
|
4
|
+
* On connect (via the heartbeat metadata), the daemon publishes which
|
|
5
|
+
* registered engines are usable on its host so the app's engine picker can
|
|
6
|
+
* grey out the rest. The probe runs once per daemon process and is cached:
|
|
7
|
+
* installed CLIs don't change during a run, and a restart re-probes.
|
|
8
|
+
*/
|
|
9
|
+
import { listBackends } from './registry.js';
|
|
10
|
+
let cached = null;
|
|
11
|
+
async function doProbe(config) {
|
|
12
|
+
const results = [];
|
|
13
|
+
for (const backend of listBackends()) {
|
|
14
|
+
try {
|
|
15
|
+
const availability = await backend.probeAvailability(config);
|
|
16
|
+
results.push({
|
|
17
|
+
id: backend.id,
|
|
18
|
+
displayName: backend.displayName,
|
|
19
|
+
available: availability.available,
|
|
20
|
+
detail: availability.detail,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
// A probe must never break the heartbeat -- report the engine unavailable.
|
|
25
|
+
results.push({
|
|
26
|
+
id: backend.id,
|
|
27
|
+
displayName: backend.displayName,
|
|
28
|
+
available: false,
|
|
29
|
+
detail: err instanceof Error ? err.message : 'availability probe failed',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Probe every registered backend's availability on this host. Cached after the
|
|
37
|
+
* first call (the result is stable for the life of the daemon process).
|
|
38
|
+
*/
|
|
39
|
+
export function probeAllBackends(config) {
|
|
40
|
+
if (!cached) {
|
|
41
|
+
cached = doProbe(config);
|
|
42
|
+
}
|
|
43
|
+
return cached;
|
|
44
|
+
}
|
|
45
|
+
/** Test-only: clear the cached probe so the next call re-probes. */
|
|
46
|
+
export function _resetAvailabilityCache() {
|
|
47
|
+
cached = null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.js","sourceRoot":"","sources":["../../src/backends/availability.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAe7C,IAAI,MAAM,GAAgD,IAAI,CAAC;AAE/D,KAAK,UAAU,OAAO,CAAC,MAAoB;IACzC,MAAM,OAAO,GAAgC,EAAE,CAAC;IAChD,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC7D,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,YAAY,CAAC,SAAS;gBACjC,MAAM,EAAE,YAAY,CAAC,MAAM;aAC5B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,2EAA2E;YAC3E,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,KAAK;gBAChB,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,2BAA2B;aACzE,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,uBAAuB;IACrC,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code backend -- the built-in `AgentBackend` implementation.
|
|
3
|
+
*
|
|
4
|
+
* Owns everything Claude-Code-specific that used to be inlined across the spawn
|
|
5
|
+
* paths: the `--teammate-mode in-process` + stream-json flag set, the `--resume`
|
|
6
|
+
* arg shape, the stream-json stdin encoding, and the StreamJsonParser-based
|
|
7
|
+
* event stream (via the `ClaudeAgentParser` adapter). The rest of the daemon
|
|
8
|
+
* now talks to this through the engine-agnostic interface.
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentBackend } from '../agent-backend.js';
|
|
11
|
+
export declare const claudeBackend: AgentBackend;
|
|
12
|
+
//# sourceMappingURL=claude-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/claude/claude-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,qBAAqB,CAAC;AAoC7B,eAAO,MAAM,aAAa,EAAE,YA8C3B,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code backend -- the built-in `AgentBackend` implementation.
|
|
3
|
+
*
|
|
4
|
+
* Owns everything Claude-Code-specific that used to be inlined across the spawn
|
|
5
|
+
* paths: the `--teammate-mode in-process` + stream-json flag set, the `--resume`
|
|
6
|
+
* arg shape, the stream-json stdin encoding, and the StreamJsonParser-based
|
|
7
|
+
* event stream (via the `ClaudeAgentParser` adapter). The rest of the daemon
|
|
8
|
+
* now talks to this through the engine-agnostic interface.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { join, isAbsolute } from 'node:path';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { ClaudeAgentParser } from '@telora/daemon-core';
|
|
14
|
+
/**
|
|
15
|
+
* Build the Claude Code stream-json flag set shared by fresh + resume spawns.
|
|
16
|
+
* Mirrors the previous `buildTeamLeadArgs` body (minus the leading `--resume`,
|
|
17
|
+
* which `buildResumeArgs` prepends): teammate mode + stream-json + the optional
|
|
18
|
+
* model override.
|
|
19
|
+
*/
|
|
20
|
+
function buildBaseArgs(ctx) {
|
|
21
|
+
const args = [];
|
|
22
|
+
args.push('--dangerously-skip-permissions');
|
|
23
|
+
args.push('--setting-sources', 'project,local');
|
|
24
|
+
args.push('--input-format', 'stream-json');
|
|
25
|
+
args.push('--output-format', 'stream-json');
|
|
26
|
+
args.push('--verbose');
|
|
27
|
+
// Enable in-process teammate mode for the team lead.
|
|
28
|
+
args.push('--teammate-mode', 'in-process');
|
|
29
|
+
if (ctx.model) {
|
|
30
|
+
args.push('--model', ctx.model);
|
|
31
|
+
}
|
|
32
|
+
return args;
|
|
33
|
+
}
|
|
34
|
+
/** Resolve whether an executable name/path exists on the host. */
|
|
35
|
+
function commandExists(command) {
|
|
36
|
+
if (isAbsolute(command) || command.includes('/')) {
|
|
37
|
+
return existsSync(command);
|
|
38
|
+
}
|
|
39
|
+
const pathEnv = process.env.PATH ?? '';
|
|
40
|
+
return pathEnv
|
|
41
|
+
.split(':')
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.some((dir) => existsSync(join(dir, command)));
|
|
44
|
+
}
|
|
45
|
+
export const claudeBackend = {
|
|
46
|
+
id: 'claude',
|
|
47
|
+
displayName: 'Claude Code',
|
|
48
|
+
resolveCommand(config) {
|
|
49
|
+
return config.claudeCodePath;
|
|
50
|
+
},
|
|
51
|
+
buildSpawnArgs(ctx) {
|
|
52
|
+
return buildBaseArgs(ctx);
|
|
53
|
+
},
|
|
54
|
+
buildResumeArgs(ctx) {
|
|
55
|
+
// --resume must come early, before --input-format stream-json.
|
|
56
|
+
return ['--resume', ctx.resumeSessionId, ...buildBaseArgs(ctx)];
|
|
57
|
+
},
|
|
58
|
+
encodeInput(content) {
|
|
59
|
+
// Identical wire format to daemon-core's `sendMessage`: a single
|
|
60
|
+
// stream-json user message line.
|
|
61
|
+
return JSON.stringify({ type: 'user', message: { role: 'user', content } }) + '\n';
|
|
62
|
+
},
|
|
63
|
+
createParser() {
|
|
64
|
+
return new ClaudeAgentParser();
|
|
65
|
+
},
|
|
66
|
+
async probeAvailability(config) {
|
|
67
|
+
const command = config.claudeCodePath;
|
|
68
|
+
if (!commandExists(command)) {
|
|
69
|
+
return {
|
|
70
|
+
available: false,
|
|
71
|
+
detail: `Claude Code CLI not found (looked for "${command}" on PATH). Install it and ensure it is on the daemon host's PATH.`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
75
|
+
return { available: true };
|
|
76
|
+
}
|
|
77
|
+
if (existsSync(join(homedir(), '.claude.json'))) {
|
|
78
|
+
return { available: true };
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
available: false,
|
|
82
|
+
detail: `Claude Code found at "${command}" but not authenticated. Run \`claude auth login\` or set ANTHROPIC_API_KEY on the daemon host.`,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=claude-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-backend.js","sourceRoot":"","sources":["../../../src/backends/claude/claude-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI backend -- runs a focus on OpenAI Codex (`codex exec`).
|
|
3
|
+
*
|
|
4
|
+
* Recipe validated against Codex CLI 0.133.0 (spike: /tmp/codex-spike):
|
|
5
|
+
* - spawn: `codex exec --json --dangerously-bypass-approvals-and-sandbox
|
|
6
|
+
* --cd <worktree> -c mcp_servers.telora.* -` (prompt on stdin)
|
|
7
|
+
* - resume: `codex exec resume <sessionId> --json --dangerously-bypass-...`
|
|
8
|
+
* NO `--cd` (the resume subcommand rejects it; workspace is recovered
|
|
9
|
+
* from the session). NEVER `--ephemeral` (it skips session persistence
|
|
10
|
+
* and breaks resume).
|
|
11
|
+
*
|
|
12
|
+
* Bypass mode matches the Claude `--dangerously-skip-permissions` posture (the
|
|
13
|
+
* daemon runs in isolated worktrees) and is also what makes headless MCP work
|
|
14
|
+
* without an approval prompt. The Telora MCP server is wired in as a config
|
|
15
|
+
* override so each Codex agent spawns its own MCP subprocess.
|
|
16
|
+
*
|
|
17
|
+
* Auth: Codex uses the host `~/.codex` OAuth login by default; a `CODEX_API_KEY`
|
|
18
|
+
* in the spawn environment overrides it (org-secret injection rides the spawn
|
|
19
|
+
* environment, not this backend).
|
|
20
|
+
*/
|
|
21
|
+
import type { AgentBackend } from '../agent-backend.js';
|
|
22
|
+
export declare const codexBackend: AgentBackend;
|
|
23
|
+
//# sourceMappingURL=codex-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/codex/codex-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,qBAAqB,CAAC;AAyC7B,eAAO,MAAM,YAAY,EAAE,YAwD1B,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex CLI backend -- runs a focus on OpenAI Codex (`codex exec`).
|
|
3
|
+
*
|
|
4
|
+
* Recipe validated against Codex CLI 0.133.0 (spike: /tmp/codex-spike):
|
|
5
|
+
* - spawn: `codex exec --json --dangerously-bypass-approvals-and-sandbox
|
|
6
|
+
* --cd <worktree> -c mcp_servers.telora.* -` (prompt on stdin)
|
|
7
|
+
* - resume: `codex exec resume <sessionId> --json --dangerously-bypass-...`
|
|
8
|
+
* NO `--cd` (the resume subcommand rejects it; workspace is recovered
|
|
9
|
+
* from the session). NEVER `--ephemeral` (it skips session persistence
|
|
10
|
+
* and breaks resume).
|
|
11
|
+
*
|
|
12
|
+
* Bypass mode matches the Claude `--dangerously-skip-permissions` posture (the
|
|
13
|
+
* daemon runs in isolated worktrees) and is also what makes headless MCP work
|
|
14
|
+
* without an approval prompt. The Telora MCP server is wired in as a config
|
|
15
|
+
* override so each Codex agent spawns its own MCP subprocess.
|
|
16
|
+
*
|
|
17
|
+
* Auth: Codex uses the host `~/.codex` OAuth login by default; a `CODEX_API_KEY`
|
|
18
|
+
* in the spawn environment overrides it (org-secret injection rides the spawn
|
|
19
|
+
* environment, not this backend).
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync } from 'node:fs';
|
|
22
|
+
import { join, isAbsolute } from 'node:path';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { CodexAgentParser, resolveMcpServerPath } from '@telora/daemon-core';
|
|
25
|
+
/** Bypass approvals + sandbox -- matches Claude's --dangerously-skip-permissions. */
|
|
26
|
+
const BYPASS_FLAG = '--dangerously-bypass-approvals-and-sandbox';
|
|
27
|
+
function codexCommand(config) {
|
|
28
|
+
return config.codexPath ?? 'codex';
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Build `-c mcp_servers.telora.*` config overrides wiring the Telora MCP server
|
|
32
|
+
* into the Codex run. Values are TOML literals, so strings are quoted.
|
|
33
|
+
* Best-effort: if the MCP package can't be resolved, MCP is omitted (the run
|
|
34
|
+
* still starts; the gap surfaces at runtime).
|
|
35
|
+
*/
|
|
36
|
+
function mcpConfigFlags(config) {
|
|
37
|
+
let mcpServerPath;
|
|
38
|
+
try {
|
|
39
|
+
mcpServerPath = resolveMcpServerPath(import.meta.url);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
console.warn('[codex-backend] Could not resolve Telora MCP server path; running without MCP:', err.message);
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const flags = [
|
|
46
|
+
'-c', `mcp_servers.telora.command="node"`,
|
|
47
|
+
'-c', `mcp_servers.telora.args=[${JSON.stringify(mcpServerPath)}]`,
|
|
48
|
+
'-c', `mcp_servers.telora.env.TELORA_MCP_PROFILE="execution"`,
|
|
49
|
+
'-c', `mcp_servers.telora.required=true`,
|
|
50
|
+
];
|
|
51
|
+
if (config.teloraUrl)
|
|
52
|
+
flags.push('-c', `mcp_servers.telora.env.TELORA_URL=${JSON.stringify(config.teloraUrl)}`);
|
|
53
|
+
if (config.trackerId)
|
|
54
|
+
flags.push('-c', `mcp_servers.telora.env.TELORA_TRACKER_ID=${JSON.stringify(config.trackerId)}`);
|
|
55
|
+
return flags;
|
|
56
|
+
}
|
|
57
|
+
function commandExists(command) {
|
|
58
|
+
if (isAbsolute(command) || command.includes('/'))
|
|
59
|
+
return existsSync(command);
|
|
60
|
+
const pathEnv = process.env.PATH ?? '';
|
|
61
|
+
return pathEnv.split(':').filter(Boolean).some((dir) => existsSync(join(dir, command)));
|
|
62
|
+
}
|
|
63
|
+
export const codexBackend = {
|
|
64
|
+
id: 'codex',
|
|
65
|
+
displayName: 'Codex CLI',
|
|
66
|
+
resolveCommand(config) {
|
|
67
|
+
return codexCommand(config);
|
|
68
|
+
},
|
|
69
|
+
buildSpawnArgs(ctx) {
|
|
70
|
+
const args = ['exec', '--json', BYPASS_FLAG, '--cd', ctx.worktreePath];
|
|
71
|
+
if (ctx.model)
|
|
72
|
+
args.push('--model', ctx.model);
|
|
73
|
+
args.push(...mcpConfigFlags(ctx.config));
|
|
74
|
+
// Trailing '-' tells codex exec to read the prompt from stdin.
|
|
75
|
+
args.push('-');
|
|
76
|
+
return args;
|
|
77
|
+
},
|
|
78
|
+
buildResumeArgs(ctx) {
|
|
79
|
+
// resume recovers the workspace from the session -- NO --cd, NEVER --ephemeral.
|
|
80
|
+
const args = ['exec', 'resume', ctx.resumeSessionId, '--json', BYPASS_FLAG];
|
|
81
|
+
if (ctx.model)
|
|
82
|
+
args.push('--model', ctx.model);
|
|
83
|
+
// MCP config overrides are global `-c` flags (accepted by the resume
|
|
84
|
+
// subcommand) so the resumed agent keeps Telora MCP access.
|
|
85
|
+
args.push(...mcpConfigFlags(ctx.config));
|
|
86
|
+
args.push('-');
|
|
87
|
+
return args;
|
|
88
|
+
},
|
|
89
|
+
encodeInput(content) {
|
|
90
|
+
// Codex reads the prompt as plain text on stdin (not stream-json).
|
|
91
|
+
return content.endsWith('\n') ? content : content + '\n';
|
|
92
|
+
},
|
|
93
|
+
createParser() {
|
|
94
|
+
return new CodexAgentParser();
|
|
95
|
+
},
|
|
96
|
+
async probeAvailability(config) {
|
|
97
|
+
const command = codexCommand(config);
|
|
98
|
+
if (!commandExists(command)) {
|
|
99
|
+
return {
|
|
100
|
+
available: false,
|
|
101
|
+
detail: `Codex CLI not found (looked for "${command}" on PATH). Install it (npm i -g @openai/codex) and run \`codex login\` on the daemon host.`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (process.env.CODEX_API_KEY) {
|
|
105
|
+
return { available: true };
|
|
106
|
+
}
|
|
107
|
+
if (existsSync(join(homedir(), '.codex', 'auth.json'))) {
|
|
108
|
+
return { available: true };
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
available: false,
|
|
112
|
+
detail: `Codex CLI found at "${command}" but not authenticated. Run \`codex login\` or set CODEX_API_KEY on the daemon host.`,
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=codex-backend.js.map
|