@agent-link/agent 0.1.204 → 0.1.207
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/backends/claude.d.ts +90 -0
- package/dist/backends/claude.js +356 -0
- package/dist/backends/claude.js.map +1 -0
- package/dist/backends/index.d.ts +27 -0
- package/dist/backends/index.js +52 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/types.d.ts +379 -0
- package/dist/backends/types.js +120 -0
- package/dist/backends/types.js.map +1 -0
- package/dist/claude.d.ts +22 -2
- package/dist/claude.js +54 -6
- package/dist/claude.js.map +1 -1
- package/dist/cli.js +62 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/connection.d.ts +4 -1
- package/dist/connection.js +304 -136
- package/dist/connection.js.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/recap.d.ts +1 -0
- package/dist/recap.js.map +1 -1
- package/dist/runtime.d.ts +176 -0
- package/dist/runtime.js +286 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudeBackend — adapter implementing AgentBackend over the existing
|
|
3
|
+
* agent/src/claude.ts subprocess driver and agent/src/history.ts JSONL reader.
|
|
4
|
+
*
|
|
5
|
+
* Design (locked decisions, see docs/2026-05-09-pr3-claude-backend.md):
|
|
6
|
+
* - claude.ts is unchanged; this class wraps it.
|
|
7
|
+
* - For Claude, `backendThreadId === backendSessionId` (single-thread sessions).
|
|
8
|
+
* - Emits NormalizedEvents only via on(listener). In PR3 the runtime
|
|
9
|
+
* facade does NOT yet subscribe to these events or translate them back
|
|
10
|
+
* to legacy wire frames — connection.ts still uses the re-exported
|
|
11
|
+
* claude.ts surface directly. PR4 wires the runtime to call
|
|
12
|
+
* getBackend().on(...) and routes outbound traffic through the
|
|
13
|
+
* translation pipeline; the NormalizedEvents emitted here are currently
|
|
14
|
+
* consumed only by the contract tests.
|
|
15
|
+
* - listSessions / readSession / deleteSession / renameSession delegate
|
|
16
|
+
* to history.ts directly.
|
|
17
|
+
*
|
|
18
|
+
* The class subscribes to claude.ts's outbound traffic via the multi-listener
|
|
19
|
+
* `addSendFn` / `addOnSessionStarted` hooks (returning unsubscribe handles
|
|
20
|
+
* stored on the instance). Because these hooks support fanout, multiple
|
|
21
|
+
* ClaudeBackend instances can coexist with the legacy connection.ts
|
|
22
|
+
* subscribers without clobbering each other; shutdown() detaches cleanly.
|
|
23
|
+
*/
|
|
24
|
+
import { type AgentBackend, type ApprovalAnswer, type BackendCapabilities, type BackendHistoryMessage, type BackendRestartResult, type BackendSessionInfo, type BackendSessionRef, type EnsureSessionOpts, type EventListener, type RestartOpts, type StartOpts, type UserInputAnswer, type UserTurnInput } from './types.js';
|
|
25
|
+
export declare class ClaudeBackend implements AgentBackend {
|
|
26
|
+
readonly type: "claude";
|
|
27
|
+
readonly capabilities: BackendCapabilities;
|
|
28
|
+
private readonly listeners;
|
|
29
|
+
/** Map from conversationId → most-recent backendSessionId we've observed.
|
|
30
|
+
* Lets us tag events that don't carry a session id (e.g. turn_completed). */
|
|
31
|
+
private readonly convToSession;
|
|
32
|
+
/** Map from placeholder ref id (e.g. 'pending:c1') → conversationId. Used
|
|
33
|
+
* to resolve startTurn() before session_started has populated convToSession. */
|
|
34
|
+
private readonly pendingRefToConv;
|
|
35
|
+
/** Map from conversationId → workDir provided to ensureSession(). Used as a
|
|
36
|
+
* fallback in startTurn() when claude.ts has no live ConversationState yet
|
|
37
|
+
* (e.g. first turn before session_started). */
|
|
38
|
+
private readonly convToWorkDir;
|
|
39
|
+
/** Unsubscribe handles for the multi-subscriber claude.ts hooks. */
|
|
40
|
+
private readonly unsubSend;
|
|
41
|
+
private readonly unsubSessionStarted;
|
|
42
|
+
readonly compact?: undefined;
|
|
43
|
+
readonly fork?: undefined;
|
|
44
|
+
readonly listModels?: undefined;
|
|
45
|
+
readonly renameSession: (workDir: string, session: BackendSessionRef, title: string) => Promise<boolean>;
|
|
46
|
+
readonly deleteSession: (workDir: string, session: BackendSessionRef) => Promise<boolean>;
|
|
47
|
+
constructor(_opts?: StartOpts);
|
|
48
|
+
on(listener: EventListener): () => void;
|
|
49
|
+
private emit;
|
|
50
|
+
start(_opts: StartOpts): Promise<void>;
|
|
51
|
+
shutdown(): Promise<void>;
|
|
52
|
+
ensureSession(opts: EnsureSessionOpts): Promise<BackendSessionRef>;
|
|
53
|
+
startTurn(session: BackendSessionRef, input: UserTurnInput): Promise<void>;
|
|
54
|
+
interruptTurn(session: BackendSessionRef): Promise<void>;
|
|
55
|
+
answerUserInput(answer: UserInputAnswer): void;
|
|
56
|
+
answerApproval(answer: ApprovalAnswer): void;
|
|
57
|
+
setModel(conversationId: string | null, model: string | null): void;
|
|
58
|
+
getEffectiveModel(conversationId?: string): string | null;
|
|
59
|
+
isCompacting(conversationId?: string): boolean;
|
|
60
|
+
hasConversation(conversationId: string): boolean;
|
|
61
|
+
restartSession(conversationId: string, opts?: RestartOpts): BackendRestartResult | null;
|
|
62
|
+
createPlaceholderSession(conversationId: string, _workDir: string, opts?: RestartOpts): void;
|
|
63
|
+
listSessions(workDir: string): Promise<BackendSessionInfo[]>;
|
|
64
|
+
readSession(workDir: string, session: BackendSessionRef): Promise<BackendHistoryMessage[]>;
|
|
65
|
+
/** Reverse-lookup: find the conversationId we associated with a session ref. */
|
|
66
|
+
private findConvId;
|
|
67
|
+
/**
|
|
68
|
+
* Translate a legacy outbound wire frame (as produced by claude.ts via the
|
|
69
|
+
* SendFn closure) into a NormalizedEvent and fan out to listeners.
|
|
70
|
+
*
|
|
71
|
+
* In PR3 the runtime facade does NOT yet perform the reverse translation
|
|
72
|
+
* back to legacy frames — connection.ts still uses the re-exported claude.ts
|
|
73
|
+
* surface directly (see runtime.ts header comment). The NormalizedEvents
|
|
74
|
+
* emitted here are currently consumed only by the contract tests; the raw
|
|
75
|
+
* frame fanout below preserves wire fidelity for when PR4 wires the runtime
|
|
76
|
+
* to translate. The `runtime.test.ts` suite verifies only that runtime.ts
|
|
77
|
+
* re-exports the expected surface, not round-trip correctness.
|
|
78
|
+
*
|
|
79
|
+
* For frames that don't have a NormalizedEvent equivalent (or that the
|
|
80
|
+
* runtime should pass through unchanged), we emit a `process_output`-shaped
|
|
81
|
+
* event carrying the raw frame so the runtime can forward it verbatim.
|
|
82
|
+
*/
|
|
83
|
+
private onClaudeSend;
|
|
84
|
+
/**
|
|
85
|
+
* Special-purpose event used internally to ferry untranslated/raw frames
|
|
86
|
+
* through to the runtime facade without losing fidelity. Encoded as a
|
|
87
|
+
* `process_output` NormalizedEvent for now; PR4+ may add a dedicated kind.
|
|
88
|
+
*/
|
|
89
|
+
private emitRawFrame;
|
|
90
|
+
}
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudeBackend — adapter implementing AgentBackend over the existing
|
|
3
|
+
* agent/src/claude.ts subprocess driver and agent/src/history.ts JSONL reader.
|
|
4
|
+
*
|
|
5
|
+
* Design (locked decisions, see docs/2026-05-09-pr3-claude-backend.md):
|
|
6
|
+
* - claude.ts is unchanged; this class wraps it.
|
|
7
|
+
* - For Claude, `backendThreadId === backendSessionId` (single-thread sessions).
|
|
8
|
+
* - Emits NormalizedEvents only via on(listener). In PR3 the runtime
|
|
9
|
+
* facade does NOT yet subscribe to these events or translate them back
|
|
10
|
+
* to legacy wire frames — connection.ts still uses the re-exported
|
|
11
|
+
* claude.ts surface directly. PR4 wires the runtime to call
|
|
12
|
+
* getBackend().on(...) and routes outbound traffic through the
|
|
13
|
+
* translation pipeline; the NormalizedEvents emitted here are currently
|
|
14
|
+
* consumed only by the contract tests.
|
|
15
|
+
* - listSessions / readSession / deleteSession / renameSession delegate
|
|
16
|
+
* to history.ts directly.
|
|
17
|
+
*
|
|
18
|
+
* The class subscribes to claude.ts's outbound traffic via the multi-listener
|
|
19
|
+
* `addSendFn` / `addOnSessionStarted` hooks (returning unsubscribe handles
|
|
20
|
+
* stored on the instance). Because these hooks support fanout, multiple
|
|
21
|
+
* ClaudeBackend instances can coexist with the legacy connection.ts
|
|
22
|
+
* subscribers without clobbering each other; shutdown() detaches cleanly.
|
|
23
|
+
*/
|
|
24
|
+
import * as claude from '../claude.js';
|
|
25
|
+
import * as history from '../history.js';
|
|
26
|
+
import { claudeCapabilities, } from './types.js';
|
|
27
|
+
/** Internal: wrap a claudeSessionId into a BackendSessionRef. */
|
|
28
|
+
function refFor(sessionId) {
|
|
29
|
+
const id = sessionId ?? '';
|
|
30
|
+
return {
|
|
31
|
+
backendType: 'claude',
|
|
32
|
+
backendSessionId: id,
|
|
33
|
+
backendThreadId: id,
|
|
34
|
+
providerSessionId: id || null,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export class ClaudeBackend {
|
|
38
|
+
type = 'claude';
|
|
39
|
+
// claudeCapabilities() now reflects this adapter's actual surface (fork &
|
|
40
|
+
// compaction = false, since claude.ts has no programmatic compact API and
|
|
41
|
+
// restartConversation's signature doesn't match AgentBackend.fork). No need
|
|
42
|
+
// to override the capability flags here.
|
|
43
|
+
capabilities = claudeCapabilities();
|
|
44
|
+
listeners = new Set();
|
|
45
|
+
/** Map from conversationId → most-recent backendSessionId we've observed.
|
|
46
|
+
* Lets us tag events that don't carry a session id (e.g. turn_completed). */
|
|
47
|
+
convToSession = new Map();
|
|
48
|
+
/** Map from placeholder ref id (e.g. 'pending:c1') → conversationId. Used
|
|
49
|
+
* to resolve startTurn() before session_started has populated convToSession. */
|
|
50
|
+
pendingRefToConv = new Map();
|
|
51
|
+
/** Map from conversationId → workDir provided to ensureSession(). Used as a
|
|
52
|
+
* fallback in startTurn() when claude.ts has no live ConversationState yet
|
|
53
|
+
* (e.g. first turn before session_started). */
|
|
54
|
+
convToWorkDir = new Map();
|
|
55
|
+
/** Unsubscribe handles for the multi-subscriber claude.ts hooks. */
|
|
56
|
+
unsubSend;
|
|
57
|
+
unsubSessionStarted;
|
|
58
|
+
// Optional methods from AgentBackend — only present if capability declares it.
|
|
59
|
+
compact; // claude.ts has no programmatic compact API
|
|
60
|
+
fork; // restartConversation acts as fork but signature differs
|
|
61
|
+
listModels; // capability says no
|
|
62
|
+
renameSession;
|
|
63
|
+
deleteSession;
|
|
64
|
+
constructor(_opts) {
|
|
65
|
+
// Wire interceptors. claude.ts now supports multi-subscriber fanout; we
|
|
66
|
+
// capture the unsubscribe handles so shutdown() can detach cleanly without
|
|
67
|
+
// racing the legacy connection.ts subscribers.
|
|
68
|
+
this.unsubSend = claude.addSendFn((msg) => this.onClaudeSend(msg));
|
|
69
|
+
this.unsubSessionStarted = claude.addOnSessionStarted((conversationId, claudeSessionId) => {
|
|
70
|
+
if (conversationId) {
|
|
71
|
+
this.convToSession.set(conversationId, claudeSessionId);
|
|
72
|
+
// Keep pendingRefToConv entry alive until shutdown so callers that
|
|
73
|
+
// still hold the original placeholder ref can resolve it later.
|
|
74
|
+
}
|
|
75
|
+
this.emit({ type: 'session_started', session: refFor(claudeSessionId) });
|
|
76
|
+
});
|
|
77
|
+
// Bind capability-gated methods.
|
|
78
|
+
this.renameSession = async (workDir, session, title) => {
|
|
79
|
+
// PR4-D: forward history.renameSession's boolean so AgentRuntime /
|
|
80
|
+
// connection.ts can drive the BRAIN_DATA_DIR fallback + retry on false.
|
|
81
|
+
return history.renameSession(workDir, session.backendSessionId, title);
|
|
82
|
+
};
|
|
83
|
+
this.deleteSession = async (workDir, session) => {
|
|
84
|
+
return history.deleteSession(workDir, session.backendSessionId);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// ── Event subscription ─────────────────────────────────────────────────
|
|
88
|
+
on(listener) {
|
|
89
|
+
this.listeners.add(listener);
|
|
90
|
+
return () => { this.listeners.delete(listener); };
|
|
91
|
+
}
|
|
92
|
+
emit(event) {
|
|
93
|
+
for (const fn of this.listeners) {
|
|
94
|
+
try {
|
|
95
|
+
fn(event);
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
console.error('[ClaudeBackend] listener threw', e);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
103
|
+
async start(_opts) {
|
|
104
|
+
// claude.ts has no global start step — process spawn is lazy per-conversation.
|
|
105
|
+
}
|
|
106
|
+
async shutdown() {
|
|
107
|
+
claude.abortAll();
|
|
108
|
+
try {
|
|
109
|
+
this.unsubSend();
|
|
110
|
+
}
|
|
111
|
+
catch { /* ignore */ }
|
|
112
|
+
try {
|
|
113
|
+
this.unsubSessionStarted();
|
|
114
|
+
}
|
|
115
|
+
catch { /* ignore */ }
|
|
116
|
+
this.listeners.clear();
|
|
117
|
+
this.convToSession.clear();
|
|
118
|
+
this.pendingRefToConv.clear();
|
|
119
|
+
this.convToWorkDir.clear();
|
|
120
|
+
}
|
|
121
|
+
// ── Session lifecycle ──────────────────────────────────────────────────
|
|
122
|
+
async ensureSession(opts) {
|
|
123
|
+
// Remember workDir so startTurn() can spawn Claude in the right directory
|
|
124
|
+
// even before claude.ts has a live ConversationState for this conversation.
|
|
125
|
+
if (opts.workDir) {
|
|
126
|
+
this.convToWorkDir.set(opts.conversationId, opts.workDir);
|
|
127
|
+
}
|
|
128
|
+
// Claude's session is established lazily on the first chat message via
|
|
129
|
+
// handleChat → startQuery. We can return a placeholder ref that carries
|
|
130
|
+
// the resumeSessionId if provided; otherwise an empty ref that gets
|
|
131
|
+
// filled in by the session_started event.
|
|
132
|
+
const existing = claude.getConversation(opts.conversationId);
|
|
133
|
+
const sid = opts.resumeSessionId ?? existing?.claudeSessionId ?? existing?.lastClaudeSessionId ?? '';
|
|
134
|
+
if (sid) {
|
|
135
|
+
this.convToSession.set(opts.conversationId, sid);
|
|
136
|
+
return refFor(sid);
|
|
137
|
+
}
|
|
138
|
+
// No real session yet — emit a placeholder ref and remember the mapping
|
|
139
|
+
// so startTurn() can recover the original conversationId from it.
|
|
140
|
+
const placeholder = `pending:${opts.conversationId}`;
|
|
141
|
+
this.pendingRefToConv.set(placeholder, opts.conversationId);
|
|
142
|
+
return refFor(placeholder);
|
|
143
|
+
}
|
|
144
|
+
async startTurn(session, input) {
|
|
145
|
+
// The conversationId is the AgentLink convId; we don't have it on
|
|
146
|
+
// BackendSessionRef directly. For backwards compat we use backendSessionId
|
|
147
|
+
// as the conversationId fallback when the runtime didn't supply a mapping.
|
|
148
|
+
// (The runtime facade will pass a richer call signature in PR3 follow-up;
|
|
149
|
+
// for the contract test the placeholder ref convention is sufficient.)
|
|
150
|
+
const convId = this.findConvId(session) ?? session.backendSessionId;
|
|
151
|
+
// Plumb resumeSessionId when the ref carries a real (non-placeholder) session
|
|
152
|
+
// id and claude.ts has no live ConversationState yet — that's the only
|
|
153
|
+
// scenario where we actually need to ask the CLI to resume. If a live
|
|
154
|
+
// ConversationState already exists, claude.ts will reuse it and the
|
|
155
|
+
// resumeSessionId would be ignored anyway. Placeholder ids ('pending:*')
|
|
156
|
+
// are explicitly excluded so we never pass them to the CLI as a resume target.
|
|
157
|
+
const sid = session.backendSessionId;
|
|
158
|
+
const isPlaceholder = !sid || sid.startsWith('pending:');
|
|
159
|
+
const hasLive = !!claude.getConversation(convId);
|
|
160
|
+
const baseOptions = !isPlaceholder && !hasLive
|
|
161
|
+
? { resumeSessionId: sid }
|
|
162
|
+
: undefined;
|
|
163
|
+
// Merge per-turn metadata (brainMode, recapId, briefingDate, devops*,
|
|
164
|
+
// projectName, icmId, extraArgs) into HandleChatOptions. The runtime
|
|
165
|
+
// passes these through opaquely; only ClaudeBackend interprets them.
|
|
166
|
+
const meta = input.metadata;
|
|
167
|
+
const options = (baseOptions || meta)
|
|
168
|
+
? { ...(meta ?? {}), ...(baseOptions ?? {}) }
|
|
169
|
+
: undefined;
|
|
170
|
+
claude.handleChat(convId, input.text,
|
|
171
|
+
// workDir must come from existing conversation state; if absent, claude.ts
|
|
172
|
+
// will throw when it tries to spawn — caller must ensureSession first.
|
|
173
|
+
claude.getConversation(convId)?.workDir ?? this.convToWorkDir.get(convId) ?? process.cwd(), options, input.files);
|
|
174
|
+
this.emit({ type: 'turn_started', session });
|
|
175
|
+
}
|
|
176
|
+
async interruptTurn(session) {
|
|
177
|
+
const convId = this.findConvId(session) ?? session.backendSessionId;
|
|
178
|
+
claude.cancelExecution(convId);
|
|
179
|
+
}
|
|
180
|
+
// ── User input / approval ──────────────────────────────────────────────
|
|
181
|
+
answerUserInput(answer) {
|
|
182
|
+
claude.handleUserAnswer(answer.requestId, answer.answers);
|
|
183
|
+
}
|
|
184
|
+
answerApproval(answer) {
|
|
185
|
+
claude.handleToolPermissionResponse(answer.requestId, answer.decision);
|
|
186
|
+
}
|
|
187
|
+
// ── PR4-C user-action surface (keyed by conversationId) ────────────────
|
|
188
|
+
setModel(conversationId, model) {
|
|
189
|
+
// claude.setModel takes (conversationId | undefined, model). null convId
|
|
190
|
+
// means "global default"; null model means clear/default — claude.setModel
|
|
191
|
+
// expects a string for model, so coerce null to '' (claude.ts treats empty
|
|
192
|
+
// as "no override").
|
|
193
|
+
claude.setModel(conversationId ?? undefined, model ?? '');
|
|
194
|
+
}
|
|
195
|
+
getEffectiveModel(conversationId) {
|
|
196
|
+
return claude.getEffectiveModel(conversationId);
|
|
197
|
+
}
|
|
198
|
+
isCompacting(conversationId) {
|
|
199
|
+
return claude.getIsCompacting(conversationId);
|
|
200
|
+
}
|
|
201
|
+
hasConversation(conversationId) {
|
|
202
|
+
return claude.getConversation(conversationId) != null;
|
|
203
|
+
}
|
|
204
|
+
restartSession(conversationId, opts) {
|
|
205
|
+
// claude.restartConversation returns { claudeSessionId: null, wasTurnActive: false }
|
|
206
|
+
// when there's no live conversation. Map that to null per AgentBackend
|
|
207
|
+
// contract (caller falls back to createPlaceholderSession).
|
|
208
|
+
if (!claude.getConversation(conversationId))
|
|
209
|
+
return null;
|
|
210
|
+
const result = claude.restartConversation(conversationId, opts);
|
|
211
|
+
return {
|
|
212
|
+
claudeSessionId: result.claudeSessionId,
|
|
213
|
+
wasTurnActive: result.wasTurnActive,
|
|
214
|
+
history: result.history,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
createPlaceholderSession(conversationId, _workDir, opts) {
|
|
218
|
+
// Claude ignores workDir — claude.ts:898 sets workDir: '' and the next
|
|
219
|
+
// handleChat overrides it. The param is kept in the AgentBackend API for
|
|
220
|
+
// future backends that need it (e.g. CodexBackend).
|
|
221
|
+
claude.createPlaceholderConversation(conversationId, opts);
|
|
222
|
+
}
|
|
223
|
+
// ── History ────────────────────────────────────────────────────────────
|
|
224
|
+
async listSessions(workDir) {
|
|
225
|
+
const items = history.listSessions(workDir);
|
|
226
|
+
return items.map((s) => ({
|
|
227
|
+
session: refFor(s.sessionId),
|
|
228
|
+
title: s.title,
|
|
229
|
+
customTitle: s.customTitle,
|
|
230
|
+
preview: s.preview,
|
|
231
|
+
lastModified: s.lastModified,
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
async readSession(workDir, session) {
|
|
235
|
+
const msgs = history.readSessionMessages(workDir, session.backendSessionId);
|
|
236
|
+
return msgs;
|
|
237
|
+
}
|
|
238
|
+
// ── Internals ──────────────────────────────────────────────────────────
|
|
239
|
+
/** Reverse-lookup: find the conversationId we associated with a session ref. */
|
|
240
|
+
findConvId(session) {
|
|
241
|
+
const sid = session.backendSessionId;
|
|
242
|
+
if (!sid)
|
|
243
|
+
return null;
|
|
244
|
+
// Placeholder refs (returned by ensureSession before session_started) carry
|
|
245
|
+
// the conversationId in pendingRefToConv. Resolve them first so we don't
|
|
246
|
+
// accidentally pass 'pending:c1' as a conversationId to claude.handleChat.
|
|
247
|
+
if (sid.startsWith('pending:')) {
|
|
248
|
+
return this.pendingRefToConv.get(sid) ?? null;
|
|
249
|
+
}
|
|
250
|
+
for (const [conv, observedSid] of this.convToSession) {
|
|
251
|
+
if (observedSid === sid)
|
|
252
|
+
return conv;
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Translate a legacy outbound wire frame (as produced by claude.ts via the
|
|
258
|
+
* SendFn closure) into a NormalizedEvent and fan out to listeners.
|
|
259
|
+
*
|
|
260
|
+
* In PR3 the runtime facade does NOT yet perform the reverse translation
|
|
261
|
+
* back to legacy frames — connection.ts still uses the re-exported claude.ts
|
|
262
|
+
* surface directly (see runtime.ts header comment). The NormalizedEvents
|
|
263
|
+
* emitted here are currently consumed only by the contract tests; the raw
|
|
264
|
+
* frame fanout below preserves wire fidelity for when PR4 wires the runtime
|
|
265
|
+
* to translate. The `runtime.test.ts` suite verifies only that runtime.ts
|
|
266
|
+
* re-exports the expected surface, not round-trip correctness.
|
|
267
|
+
*
|
|
268
|
+
* For frames that don't have a NormalizedEvent equivalent (or that the
|
|
269
|
+
* runtime should pass through unchanged), we emit a `process_output`-shaped
|
|
270
|
+
* event carrying the raw frame so the runtime can forward it verbatim.
|
|
271
|
+
*/
|
|
272
|
+
onClaudeSend(msg) {
|
|
273
|
+
const t = String(msg.type ?? '');
|
|
274
|
+
const convId = typeof msg.conversationId === 'string' ? msg.conversationId : undefined;
|
|
275
|
+
const sid = (convId && this.convToSession.get(convId)) || '';
|
|
276
|
+
const session = refFor(sid);
|
|
277
|
+
switch (t) {
|
|
278
|
+
case 'session_started':
|
|
279
|
+
// Already emitted via setOnSessionStarted callback; skip to avoid double-fire.
|
|
280
|
+
return;
|
|
281
|
+
case 'turn_completed':
|
|
282
|
+
this.emit({ type: 'turn_completed', session });
|
|
283
|
+
// Also forward the raw frame so the runtime can preserve fields like
|
|
284
|
+
// conversationId / usage that connection.ts expects on the wire.
|
|
285
|
+
this.emitRawFrame(msg);
|
|
286
|
+
return;
|
|
287
|
+
case 'execution_cancelled':
|
|
288
|
+
this.emit({ type: 'turn_cancelled', session });
|
|
289
|
+
this.emitRawFrame(msg);
|
|
290
|
+
return;
|
|
291
|
+
case 'context_compaction': {
|
|
292
|
+
const status = msg.status === 'started' ? 'compact_started' : 'compact_completed';
|
|
293
|
+
this.emit({ type: status, session });
|
|
294
|
+
this.emitRawFrame(msg);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
case 'ask_user_question': {
|
|
298
|
+
const requestId = String(msg.requestId ?? '');
|
|
299
|
+
const questions = msg.questions ?? [];
|
|
300
|
+
this.emit({
|
|
301
|
+
type: 'user_input_requested',
|
|
302
|
+
session,
|
|
303
|
+
requestId,
|
|
304
|
+
request: {
|
|
305
|
+
source: 'ask_user_question',
|
|
306
|
+
questions: questions.map((q) => ({
|
|
307
|
+
question: String(q.question ?? ''),
|
|
308
|
+
header: q.header ? String(q.header) : undefined,
|
|
309
|
+
options: q.options ?? [],
|
|
310
|
+
multiSelect: Boolean(q.multiSelect),
|
|
311
|
+
})),
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
this.emitRawFrame(msg);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
case 'tool_permission_request': {
|
|
318
|
+
const requestId = String(msg.requestId ?? '');
|
|
319
|
+
const toolName = String(msg.toolName ?? '');
|
|
320
|
+
this.emit({
|
|
321
|
+
type: 'approval_requested',
|
|
322
|
+
session,
|
|
323
|
+
requestId,
|
|
324
|
+
request: { kind: 'tool', toolName, input: msg.input },
|
|
325
|
+
});
|
|
326
|
+
this.emitRawFrame(msg);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
case 'error':
|
|
330
|
+
this.emit({ type: 'error', session, message: String(msg.message ?? '') });
|
|
331
|
+
this.emitRawFrame(msg);
|
|
332
|
+
return;
|
|
333
|
+
default:
|
|
334
|
+
// Pass-through for everything else (claude_output, plan_mode_changed,
|
|
335
|
+
// permission_mode_changed, btw_answer, etc). The runtime forwards raw.
|
|
336
|
+
this.emitRawFrame(msg);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Special-purpose event used internally to ferry untranslated/raw frames
|
|
342
|
+
* through to the runtime facade without losing fidelity. Encoded as a
|
|
343
|
+
* `process_output` NormalizedEvent for now; PR4+ may add a dedicated kind.
|
|
344
|
+
*/
|
|
345
|
+
emitRawFrame(msg) {
|
|
346
|
+
const convId = typeof msg.conversationId === 'string' ? msg.conversationId : undefined;
|
|
347
|
+
const sid = (convId && this.convToSession.get(convId)) || '';
|
|
348
|
+
this.emit({
|
|
349
|
+
type: 'process_output',
|
|
350
|
+
session: refFor(sid),
|
|
351
|
+
processId: '__raw__',
|
|
352
|
+
chunk: JSON.stringify(msg),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/backends/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend factory.
|
|
3
|
+
*
|
|
4
|
+
* `'claude'` is wired to `ClaudeBackend` (a thin adapter over the existing
|
|
5
|
+
* `agent/src/claude.ts` driver). `'codex'` is recognized but not implemented
|
|
6
|
+
* yet (PR4).
|
|
7
|
+
*/
|
|
8
|
+
import { type BackendType, type AgentBackend, type StartOpts } from './types.js';
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
export { ClaudeBackend } from './claude.js';
|
|
11
|
+
export declare class UnknownBackendError extends Error {
|
|
12
|
+
constructor(type: string);
|
|
13
|
+
}
|
|
14
|
+
export declare class BackendNotImplementedError extends Error {
|
|
15
|
+
constructor(type: BackendType);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate that a string is a known BackendType.
|
|
19
|
+
* Throws UnknownBackendError for unknown values.
|
|
20
|
+
*/
|
|
21
|
+
export declare function assertKnownBackendType(type: string): asserts type is BackendType;
|
|
22
|
+
/**
|
|
23
|
+
* Factory entry point. For recognized-but-not-yet-implemented backends
|
|
24
|
+
* (currently: codex), throws BackendNotImplementedError. Throws
|
|
25
|
+
* UnknownBackendError for unknown types.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createBackend(type: string, _opts?: StartOpts): AgentBackend;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend factory.
|
|
3
|
+
*
|
|
4
|
+
* `'claude'` is wired to `ClaudeBackend` (a thin adapter over the existing
|
|
5
|
+
* `agent/src/claude.ts` driver). `'codex'` is recognized but not implemented
|
|
6
|
+
* yet (PR4).
|
|
7
|
+
*/
|
|
8
|
+
import { KNOWN_BACKEND_TYPES } from './types.js';
|
|
9
|
+
import { ClaudeBackend } from './claude.js';
|
|
10
|
+
export * from './types.js';
|
|
11
|
+
export { ClaudeBackend } from './claude.js';
|
|
12
|
+
export class UnknownBackendError extends Error {
|
|
13
|
+
constructor(type) {
|
|
14
|
+
super(`Unknown backend type: "${type}". Known types: ${KNOWN_BACKEND_TYPES.join(', ')}.`);
|
|
15
|
+
this.name = 'UnknownBackendError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class BackendNotImplementedError extends Error {
|
|
19
|
+
constructor(type) {
|
|
20
|
+
super(`Backend "${type}" is recognized but not yet implemented in this version.`);
|
|
21
|
+
this.name = 'BackendNotImplementedError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validate that a string is a known BackendType.
|
|
26
|
+
* Throws UnknownBackendError for unknown values.
|
|
27
|
+
*/
|
|
28
|
+
export function assertKnownBackendType(type) {
|
|
29
|
+
if (!KNOWN_BACKEND_TYPES.includes(type)) {
|
|
30
|
+
throw new UnknownBackendError(type);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Factory entry point. For recognized-but-not-yet-implemented backends
|
|
35
|
+
* (currently: codex), throws BackendNotImplementedError. Throws
|
|
36
|
+
* UnknownBackendError for unknown types.
|
|
37
|
+
*/
|
|
38
|
+
export function createBackend(type, _opts) {
|
|
39
|
+
assertKnownBackendType(type);
|
|
40
|
+
switch (type) {
|
|
41
|
+
case 'claude':
|
|
42
|
+
return new ClaudeBackend(_opts);
|
|
43
|
+
case 'codex':
|
|
44
|
+
throw new BackendNotImplementedError('codex');
|
|
45
|
+
default: {
|
|
46
|
+
// exhaustiveness guard
|
|
47
|
+
const _exhaustive = type;
|
|
48
|
+
throw new UnknownBackendError(_exhaustive);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,mBAAmB,EAAuD,MAAM,YAAY,CAAC;AACtG,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,IAAY;QACtB,KAAK,CACH,0BAA0B,IAAI,mBAAmB,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CACnF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,IAAiB;QAC3B,KAAK,CACH,YAAY,IAAI,0DAA0D,CAC3E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,IAAI,CAAE,mBAAyC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,KAAiB;IAC3D,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,OAAO;YACV,MAAM,IAAI,0BAA0B,CAAC,OAAO,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC,CAAC;YACR,uBAAuB;YACvB,MAAM,WAAW,GAAU,IAAI,CAAC;YAChC,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;AACH,CAAC"}
|