letta-code-acp 0.0.2
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 +202 -0
- package/README.md +226 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +569 -0
- package/dist/cli.js.map +1 -0
- package/dist/letta-process.d.ts +57 -0
- package/dist/letta-process.js +151 -0
- package/dist/letta-process.js.map +1 -0
- package/dist/mapping.d.ts +43 -0
- package/dist/mapping.js +444 -0
- package/dist/mapping.js.map +1 -0
- package/dist/wire.d.ts +90 -0
- package/dist/wire.js +16 -0
- package/dist/wire.js.map +1 -0
- package/package.json +44 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,569 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { AgentSideConnection, ndJsonStream, } from "@agentclientprotocol/sdk";
|
|
3
|
+
import { Readable, Writable } from "node:stream";
|
|
4
|
+
import { LettaProcess } from "./letta-process.js";
|
|
5
|
+
import { wireToSessionUpdate, decorateMemoryToolCall, decorateFileEditToolCall, descriptiveTitle, stripReadLineNumbers, } from "./mapping.js";
|
|
6
|
+
const PROTOCOL_VERSION = 1;
|
|
7
|
+
class LettaAcpAgent {
|
|
8
|
+
conn;
|
|
9
|
+
sessions = new Map();
|
|
10
|
+
clientCwd = null;
|
|
11
|
+
constructor(conn) {
|
|
12
|
+
this.conn = conn;
|
|
13
|
+
}
|
|
14
|
+
async initialize(_params) {
|
|
15
|
+
return {
|
|
16
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
17
|
+
agentCapabilities: {
|
|
18
|
+
loadSession: false,
|
|
19
|
+
promptCapabilities: {
|
|
20
|
+
image: false,
|
|
21
|
+
audio: false,
|
|
22
|
+
embeddedContext: true,
|
|
23
|
+
},
|
|
24
|
+
sessionCapabilities: {
|
|
25
|
+
// v0: we accept the call but always return an empty list.
|
|
26
|
+
// This silences agent-shell's startup probe ("Method not found: session/list").
|
|
27
|
+
// Real persistence (mapping ACP sessionIds to Letta agent/conversation
|
|
28
|
+
// tuples across adapter restarts) is a v1 task.
|
|
29
|
+
list: {},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
authMethods: [
|
|
33
|
+
{
|
|
34
|
+
id: "letta-cloud",
|
|
35
|
+
name: "Letta Cloud",
|
|
36
|
+
description: "Use Letta Cloud (set LETTA_API_KEY in adapter env).",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "letta-local",
|
|
40
|
+
name: "Local backend",
|
|
41
|
+
description: "Use the local Letta backend (run `letta connect <provider>` first).",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async authenticate(_params) {
|
|
47
|
+
// No-op: real auth lives in the `letta` CLI's own credential cache.
|
|
48
|
+
// For cloud, LETTA_API_KEY must be present in the adapter's environment.
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
async newSession(params) {
|
|
52
|
+
const cwd = params.cwd ?? process.cwd();
|
|
53
|
+
this.clientCwd = cwd;
|
|
54
|
+
const meta = params._meta ?? {};
|
|
55
|
+
const agentId = meta.lettaAgentId ?? process.env.LETTA_AGENT_ID;
|
|
56
|
+
const model = meta.lettaModel ?? process.env.LETTA_MODEL;
|
|
57
|
+
const permissionMode = meta.lettaPermissionMode ?? process.env.LETTA_PERMISSION_MODE;
|
|
58
|
+
const conversationId = meta.lettaConversationId ?? process.env.LETTA_CONVERSATION_ID;
|
|
59
|
+
const reflectionTrigger = meta.lettaReflectionTrigger ?? process.env.LETTA_REFLECTION_TRIGGER;
|
|
60
|
+
const reflectionStepCountRaw = meta.lettaReflectionStepCount ?? process.env.LETTA_REFLECTION_STEP_COUNT;
|
|
61
|
+
const reflectionStepCount = reflectionStepCountRaw !== undefined && reflectionStepCountRaw !== null
|
|
62
|
+
? Number(reflectionStepCountRaw)
|
|
63
|
+
: undefined;
|
|
64
|
+
if (reflectionStepCount !== undefined &&
|
|
65
|
+
(!Number.isFinite(reflectionStepCount) || reflectionStepCount <= 0)) {
|
|
66
|
+
throw rpcError(-32602, `lettaReflectionStepCount must be a positive integer, got ${reflectionStepCountRaw}`);
|
|
67
|
+
}
|
|
68
|
+
const proc = new LettaProcess({
|
|
69
|
+
cwd,
|
|
70
|
+
agentId,
|
|
71
|
+
model,
|
|
72
|
+
permissionMode,
|
|
73
|
+
conversationId,
|
|
74
|
+
newConversation: !!meta.newConversation,
|
|
75
|
+
reflectionTrigger,
|
|
76
|
+
reflectionStepCount,
|
|
77
|
+
});
|
|
78
|
+
const init = await proc.start();
|
|
79
|
+
const sessionId = init.session_id ?? init.agent_id ?? `letta-${Date.now()}`;
|
|
80
|
+
const state = {
|
|
81
|
+
id: sessionId,
|
|
82
|
+
proc,
|
|
83
|
+
seenToolCalls: new Set(),
|
|
84
|
+
inflightTools: new Set(),
|
|
85
|
+
memoryDiffs: new Map(),
|
|
86
|
+
titlesById: new Map(),
|
|
87
|
+
toolNamesById: new Map(),
|
|
88
|
+
argsAccum: new Map(),
|
|
89
|
+
};
|
|
90
|
+
this.sessions.set(sessionId, state);
|
|
91
|
+
proc.onWire((msg) => this.dispatchWire(state, msg));
|
|
92
|
+
proc.on("exit", (info) => {
|
|
93
|
+
const pending = state.pending;
|
|
94
|
+
if (pending) {
|
|
95
|
+
state.pending = undefined;
|
|
96
|
+
if (info.code === 0) {
|
|
97
|
+
pending.resolve({ stopReason: "end_turn" });
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
pending.reject(new Error(`letta exited: ${info.stderr.trim() || `code ${info.code}`}`));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
this.sessions.delete(sessionId);
|
|
104
|
+
});
|
|
105
|
+
return { sessionId };
|
|
106
|
+
}
|
|
107
|
+
async loadSession(_params) {
|
|
108
|
+
throw rpcError(-32601, "session/load not implemented in v0");
|
|
109
|
+
}
|
|
110
|
+
async listSessions(_params) {
|
|
111
|
+
return { sessions: [] };
|
|
112
|
+
}
|
|
113
|
+
async prompt(params) {
|
|
114
|
+
const state = this.sessions.get(params.sessionId);
|
|
115
|
+
if (!state)
|
|
116
|
+
throw rpcError(-32602, `unknown sessionId: ${params.sessionId}`);
|
|
117
|
+
if (state.pending)
|
|
118
|
+
throw rpcError(-32000, "another prompt is already in flight");
|
|
119
|
+
const text = extractText(params);
|
|
120
|
+
state.proc.sendUserPrompt(text);
|
|
121
|
+
return new Promise((resolve, reject) => {
|
|
122
|
+
state.pending = { resolve, reject };
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async cancel(params) {
|
|
126
|
+
const state = this.sessions.get(params.sessionId);
|
|
127
|
+
state?.proc.cancel();
|
|
128
|
+
}
|
|
129
|
+
async setSessionMode(_params) {
|
|
130
|
+
// v0: we can't change Letta's --permission-mode mid-process. Accept the
|
|
131
|
+
// request so ACP hosts (Zed, agent-shell) stop erroring; ignore the
|
|
132
|
+
// requested mode. Mid-session change is a Phase 2 item requiring a Letta
|
|
133
|
+
// control_request we haven't seen on the wire yet - at that point persist
|
|
134
|
+
// the chosen mode and forward it. Today there's no reader, so no store.
|
|
135
|
+
return {};
|
|
136
|
+
}
|
|
137
|
+
dispatchWire(state, msg) {
|
|
138
|
+
if (msg.type === "result") {
|
|
139
|
+
const subtype = msg.subtype;
|
|
140
|
+
this.completeInflightTools(state, {
|
|
141
|
+
// result.subtype="success" means the agent's turn ended normally.
|
|
142
|
+
// Any tool that streamed args but never returned was likely a
|
|
143
|
+
// server-side tool whose `tool_return_message` didn't reach the
|
|
144
|
+
// wire - surface as `completed` with a soft note, not `failed`.
|
|
145
|
+
// result.subtype !== "success" (error / interrupted) → mark failed.
|
|
146
|
+
treatOrphansAs: subtype === "success" ? "completed" : "failed",
|
|
147
|
+
note: subtype === "success"
|
|
148
|
+
? "(no tool_return on wire - likely a server-side tool; agent may still have received the result)"
|
|
149
|
+
: "(no tool_return - turn ended in error or was interrupted)",
|
|
150
|
+
});
|
|
151
|
+
this.resolvePrompt(state, msg);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (msg.type === "error") {
|
|
155
|
+
// Run-level error: tools in flight aren't going to complete. Mark them
|
|
156
|
+
// failed with the actual run error message so the user can see WHY.
|
|
157
|
+
const errText = String(msg.message ?? "Letta run error");
|
|
158
|
+
this.completeInflightTools(state, {
|
|
159
|
+
treatOrphansAs: "failed",
|
|
160
|
+
note: `Run error: ${errText.slice(0, 400)}${errText.length > 400 ? "…" : ""}`,
|
|
161
|
+
});
|
|
162
|
+
this.rejectPrompt(state, msg);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (msg.type === "control_request") {
|
|
166
|
+
this.handleControlRequest(state, msg).catch((err) => {
|
|
167
|
+
process.stderr.write(`[letta-acp] control_request handler failed: ${err}\n`);
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// Accumulate streamed arg fragments so we can emit one refined
|
|
172
|
+
// tool_call_update with full rawInput (+ memory diff) when the cumulative
|
|
173
|
+
// JSON parses. Each Letta delta carries a fragment string.
|
|
174
|
+
if (msg.type === "stream_event") {
|
|
175
|
+
const ev = msg.event ?? {};
|
|
176
|
+
const mt = ev.message_type;
|
|
177
|
+
const tc = ev.tool_call;
|
|
178
|
+
const id = tc?.tool_call_id;
|
|
179
|
+
const frag = tc?.arguments;
|
|
180
|
+
if ((mt === "tool_call_message" || mt === "approval_request_message") &&
|
|
181
|
+
typeof id === "string" &&
|
|
182
|
+
typeof frag === "string" &&
|
|
183
|
+
frag.length > 0) {
|
|
184
|
+
const accum = (state.argsAccum.get(id) ?? "") + frag;
|
|
185
|
+
state.argsAccum.set(id, accum);
|
|
186
|
+
try {
|
|
187
|
+
const parsed = JSON.parse(accum);
|
|
188
|
+
// Complete JSON. Emit one refined tool_call_update and stop
|
|
189
|
+
// accumulating for this id.
|
|
190
|
+
state.argsAccum.delete(id);
|
|
191
|
+
const toolName = state.titlesById.get(id) ?? tc.name ?? "";
|
|
192
|
+
const base = {
|
|
193
|
+
sessionUpdate: "tool_call_update",
|
|
194
|
+
toolCallId: id,
|
|
195
|
+
rawInput: parsed,
|
|
196
|
+
};
|
|
197
|
+
// Add a descriptive title (e.g. "Read ~/path/file.el") once we
|
|
198
|
+
// have full args. agent-shell upgrades titles when a non-empty
|
|
199
|
+
// new title arrives on tool_call_update.
|
|
200
|
+
const nicer = descriptiveTitle(String(toolName), parsed);
|
|
201
|
+
if (nicer)
|
|
202
|
+
base.title = nicer;
|
|
203
|
+
const refined = decorateFileEditToolCall(decorateMemoryToolCall(base, String(toolName), parsed), String(toolName), parsed);
|
|
204
|
+
if (Array.isArray(refined.content)) {
|
|
205
|
+
const diff = refined.content.find((c) => c?.type === "diff");
|
|
206
|
+
if (diff)
|
|
207
|
+
state.memoryDiffs.set(id, diff);
|
|
208
|
+
}
|
|
209
|
+
void this.conn
|
|
210
|
+
.sessionUpdate({ sessionId: state.id, update: refined })
|
|
211
|
+
.catch(() => { });
|
|
212
|
+
// For TodoWrite/UpdatePlan, also emit an ACP `plan` notification.
|
|
213
|
+
// agent-shell has dedicated plan rendering (see agent-shell.el line
|
|
214
|
+
// ~1697), which is far more useful than a generic tool_call row.
|
|
215
|
+
const isPlanTool = String(toolName) === "TodoWrite" || String(toolName) === "UpdatePlan";
|
|
216
|
+
if (isPlanTool && Array.isArray(parsed.todos)) {
|
|
217
|
+
const entries = parsed.todos.map((t) => ({
|
|
218
|
+
content: String(t?.content ?? t?.text ?? "(unnamed task)"),
|
|
219
|
+
priority: String(t?.priority ?? "medium"),
|
|
220
|
+
status: String(t?.status ?? "pending"),
|
|
221
|
+
}));
|
|
222
|
+
void this.conn
|
|
223
|
+
.sessionUpdate({
|
|
224
|
+
sessionId: state.id,
|
|
225
|
+
update: { sessionUpdate: "plan", entries },
|
|
226
|
+
})
|
|
227
|
+
.catch(() => { });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// not yet complete; keep accumulating
|
|
232
|
+
}
|
|
233
|
+
// Suppress per-fragment downstream mapping for this delta - the
|
|
234
|
+
// initial tool_call already fired on the name-bearing delta.
|
|
235
|
+
if (!tc.name)
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// Note: Letta does not emit `tool_return_message` over the wire in cloud
|
|
240
|
+
// headless mode for auto-approved tools, and the relative ordering of
|
|
241
|
+
// `auto_approval` vs the per-turn `stop_reason` is not stable. We therefore
|
|
242
|
+
// defer the final "completed" flip to the terminating `result` message and
|
|
243
|
+
// let `auto_approval` carry the tool from pending → in_progress in between.
|
|
244
|
+
const update = wireToSessionUpdate(msg, state.id);
|
|
245
|
+
if (!update)
|
|
246
|
+
return;
|
|
247
|
+
const u = update.update;
|
|
248
|
+
if (u?.sessionUpdate === "tool_call" && typeof u.toolCallId === "string") {
|
|
249
|
+
const id = u.toolCallId;
|
|
250
|
+
// Stash any diff content block so we can re-attach it when the tool
|
|
251
|
+
// completes (the completion update carries the tool return text, which
|
|
252
|
+
// would otherwise clobber the diff).
|
|
253
|
+
if (Array.isArray(u.content)) {
|
|
254
|
+
const diff = u.content.find((c) => c?.type === "diff");
|
|
255
|
+
if (diff)
|
|
256
|
+
state.memoryDiffs.set(id, diff);
|
|
257
|
+
}
|
|
258
|
+
// Dedupe: Letta streams the same id across many arg deltas. Only the
|
|
259
|
+
// first delta carries a real tool name; subsequent ones have name=null
|
|
260
|
+
// and would clobber the title in the host UI. Convert later sightings
|
|
261
|
+
// to tool_call_update so rawInput keeps refining without resetting the
|
|
262
|
+
// row.
|
|
263
|
+
if (state.seenToolCalls.has(id)) {
|
|
264
|
+
// Coalesce: Letta streams 15–25 deltas per tool while args are
|
|
265
|
+
// assembled. Drop the intermediate ones and only emit a refinement
|
|
266
|
+
// when the rawInput is a complete JSON object (heuristic: not a
|
|
267
|
+
// string, since complete args parse from the JSON string in
|
|
268
|
+
// mapping.ts's safeParseJson). This cuts viewport churn dramatically.
|
|
269
|
+
if (u.rawInput && typeof u.rawInput === "object") {
|
|
270
|
+
// Memory + file-edit tools: the title-only initial tool_call had
|
|
271
|
+
// args=null, so the diff couldn't be computed. Re-run decoration
|
|
272
|
+
// here once args are complete and stash the diff for the eventual
|
|
273
|
+
// completion. Both decorators need the RAW tool name (e.g. "Read",
|
|
274
|
+
// "memory_replace") - titlesById may have been overwritten with a
|
|
275
|
+
// descriptive title ("Read ~/foo.ts") by an earlier refinement, so
|
|
276
|
+
// we prefer toolNamesById (set once on first sighting) for both.
|
|
277
|
+
const rawName = state.toolNamesById.get(id) ?? u.title ?? "";
|
|
278
|
+
const enriched = decorateFileEditToolCall(decorateMemoryToolCall({ ...u, sessionUpdate: "tool_call_update" }, rawName, u.rawInput), rawName, u.rawInput);
|
|
279
|
+
if (Array.isArray(enriched.content)) {
|
|
280
|
+
const diff = enriched.content.find((c) => c?.type === "diff");
|
|
281
|
+
if (diff)
|
|
282
|
+
state.memoryDiffs.set(id, diff);
|
|
283
|
+
}
|
|
284
|
+
const refined = {
|
|
285
|
+
sessionId: state.id,
|
|
286
|
+
update: {
|
|
287
|
+
sessionUpdate: "tool_call_update",
|
|
288
|
+
toolCallId: id,
|
|
289
|
+
rawInput: enriched.rawInput ?? u.rawInput,
|
|
290
|
+
...(enriched.content ? { content: enriched.content } : {}),
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
void this.conn.sessionUpdate(refined).catch(() => { });
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
state.seenToolCalls.add(id);
|
|
298
|
+
state.inflightTools.add(id);
|
|
299
|
+
if (typeof u.title === "string") {
|
|
300
|
+
state.titlesById.set(id, u.title);
|
|
301
|
+
// First tool_call carries the raw tool name as the title (descriptive
|
|
302
|
+
// titles are applied later via tool_call_update); stash it for content
|
|
303
|
+
// post-processing on completion.
|
|
304
|
+
if (!state.toolNamesById.has(id))
|
|
305
|
+
state.toolNamesById.set(id, u.title);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (u?.sessionUpdate === "tool_call_update") {
|
|
309
|
+
const id = String(u.toolCallId);
|
|
310
|
+
const rawName = state.toolNamesById.get(id) ?? "";
|
|
311
|
+
// Strip ` 42→` line-number prefixes from Read tool returns so the
|
|
312
|
+
// host renders file contents without the model-facing decoration.
|
|
313
|
+
if (rawName === "Read" && Array.isArray(u.content)) {
|
|
314
|
+
u.content = u.content.map((c) => {
|
|
315
|
+
if (c?.type === "content" && c.content?.type === "text") {
|
|
316
|
+
return {
|
|
317
|
+
...c,
|
|
318
|
+
content: { ...c.content, text: stripReadLineNumbers(String(c.content.text ?? "")) },
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return c;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
if (u.status === "completed" || u.status === "failed") {
|
|
325
|
+
state.inflightTools.delete(id);
|
|
326
|
+
const isFileEdit = rawName === "Edit" ||
|
|
327
|
+
rawName === "Write" ||
|
|
328
|
+
rawName === "MultiEdit" ||
|
|
329
|
+
rawName === "ApplyPatch";
|
|
330
|
+
// Re-attach the stashed diff so the host UI shows what changed even
|
|
331
|
+
// after the tool return body lands. For filesystem edits on success,
|
|
332
|
+
// the tool return is just a noisy `{"message":"Successfully replaced
|
|
333
|
+
// ..."}` JSON blob with no useful information - replace it with the
|
|
334
|
+
// diff. For memory tools and for any failure, keep the return body
|
|
335
|
+
// alongside the diff so the user can see status / error text.
|
|
336
|
+
const diff = state.memoryDiffs.get(id);
|
|
337
|
+
if (diff) {
|
|
338
|
+
const existing = Array.isArray(u.content) ? u.content : [];
|
|
339
|
+
const alreadyHasDiff = existing.some((c) => c?.type === "diff" && c?.path === diff.path);
|
|
340
|
+
if (isFileEdit && u.status === "completed") {
|
|
341
|
+
u.content = [diff];
|
|
342
|
+
}
|
|
343
|
+
else if (!alreadyHasDiff) {
|
|
344
|
+
u.content = [diff, ...existing];
|
|
345
|
+
}
|
|
346
|
+
state.memoryDiffs.delete(id);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
void this.conn.sessionUpdate(update).catch(() => { });
|
|
351
|
+
}
|
|
352
|
+
async handleControlRequest(state, msg) {
|
|
353
|
+
const reqId = String(msg.request_id ?? "");
|
|
354
|
+
const inner = msg.request ?? {};
|
|
355
|
+
if (inner.subtype === "can_use_tool") {
|
|
356
|
+
await this.handleCanUseTool(state, reqId, inner);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
// Unknown subtype: reply with error so Letta doesn't hang.
|
|
360
|
+
state.proc.sendRaw({
|
|
361
|
+
type: "control_response",
|
|
362
|
+
response: {
|
|
363
|
+
subtype: "error",
|
|
364
|
+
request_id: reqId,
|
|
365
|
+
error: `unsupported control_request subtype: ${inner.subtype}`,
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
async handleCanUseTool(state, requestId, req) {
|
|
370
|
+
const toolName = String(req.tool_name ?? "tool");
|
|
371
|
+
const toolCallId = String(req.tool_call_id ?? `call-${Date.now()}`);
|
|
372
|
+
const input = req.input ?? {};
|
|
373
|
+
const diffs = Array.isArray(req.diffs) ? req.diffs : [];
|
|
374
|
+
// Build ACP request_permission. Surface diffs as ToolDiffContent when present;
|
|
375
|
+
// otherwise show the raw input under a text block.
|
|
376
|
+
const content = [];
|
|
377
|
+
for (const d of diffs) {
|
|
378
|
+
const diff = lettaDiffToAcp(d);
|
|
379
|
+
if (diff)
|
|
380
|
+
content.push({ type: "resource_link", uri: `diff:${diff.path}` });
|
|
381
|
+
}
|
|
382
|
+
if (content.length === 0) {
|
|
383
|
+
content.push({
|
|
384
|
+
type: "text",
|
|
385
|
+
text: `${toolName} ${JSON.stringify(input)}`,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
const acpReq = {
|
|
389
|
+
sessionId: state.id,
|
|
390
|
+
toolCall: {
|
|
391
|
+
toolCallId,
|
|
392
|
+
title: toolName,
|
|
393
|
+
kind: inferKindForName(toolName),
|
|
394
|
+
status: "pending",
|
|
395
|
+
rawInput: input,
|
|
396
|
+
content: content.map((c) => ({ type: "content", content: c })),
|
|
397
|
+
},
|
|
398
|
+
options: [
|
|
399
|
+
{ optionId: "allow-once", name: "Allow once", kind: "allow_once" },
|
|
400
|
+
{ optionId: "allow-always", name: "Always allow this tool", kind: "allow_always" },
|
|
401
|
+
{ optionId: "reject", name: "Reject", kind: "reject_once" },
|
|
402
|
+
],
|
|
403
|
+
};
|
|
404
|
+
let allow = false;
|
|
405
|
+
let denyMessage = "User rejected the tool call.";
|
|
406
|
+
try {
|
|
407
|
+
const resp = await this.conn.requestPermission(acpReq);
|
|
408
|
+
const outcome = resp.outcome ?? {};
|
|
409
|
+
if (outcome.outcome === "selected") {
|
|
410
|
+
const id = String(outcome.optionId ?? "");
|
|
411
|
+
allow = id === "allow-once" || id === "allow-always";
|
|
412
|
+
}
|
|
413
|
+
else if (outcome.outcome === "cancelled") {
|
|
414
|
+
denyMessage = "User cancelled the permission request.";
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch (err) {
|
|
418
|
+
denyMessage = `permission request failed: ${err}`;
|
|
419
|
+
}
|
|
420
|
+
// Letta wire shape - see src/types/protocol.ts (ControlResponse +
|
|
421
|
+
// ControlResponseBody). Envelope wraps a ControlResponseBody under
|
|
422
|
+
// `response`; the success-variant body carries `request_id` and the
|
|
423
|
+
// CanUseToolResponse payload as a nested `response`. Asymmetry vs
|
|
424
|
+
// ControlRequest (which puts `request_id` on the envelope) is by design
|
|
425
|
+
// upstream - don't "flatten" without re-reading the types.
|
|
426
|
+
const body = allow
|
|
427
|
+
? { subtype: "success", request_id: requestId, response: { behavior: "allow" } }
|
|
428
|
+
: {
|
|
429
|
+
subtype: "success",
|
|
430
|
+
request_id: requestId,
|
|
431
|
+
response: { behavior: "deny", message: denyMessage },
|
|
432
|
+
};
|
|
433
|
+
state.proc.sendRaw({ type: "control_response", response: body });
|
|
434
|
+
}
|
|
435
|
+
completeInflightTools(state, opts) {
|
|
436
|
+
if (state.inflightTools.size === 0)
|
|
437
|
+
return;
|
|
438
|
+
const ids = [...state.inflightTools];
|
|
439
|
+
state.inflightTools.clear();
|
|
440
|
+
for (const id of ids) {
|
|
441
|
+
void this.conn
|
|
442
|
+
.sessionUpdate({
|
|
443
|
+
sessionId: state.id,
|
|
444
|
+
update: {
|
|
445
|
+
sessionUpdate: "tool_call_update",
|
|
446
|
+
toolCallId: id,
|
|
447
|
+
status: opts.treatOrphansAs,
|
|
448
|
+
content: [
|
|
449
|
+
{
|
|
450
|
+
type: "content",
|
|
451
|
+
content: { type: "text", text: opts.note },
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
},
|
|
455
|
+
})
|
|
456
|
+
.catch(() => { });
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
resolvePrompt(state, msg) {
|
|
460
|
+
const pending = state.pending;
|
|
461
|
+
if (!pending)
|
|
462
|
+
return;
|
|
463
|
+
state.pending = undefined;
|
|
464
|
+
if (msg.subtype === "error") {
|
|
465
|
+
// Surface the run error text instead of a silent "refusal" with no
|
|
466
|
+
// content. Letta carries the detail in `result`; without this the user
|
|
467
|
+
// just sees a bare stop with no explanation (e.g. after a turn was
|
|
468
|
+
// cancelled mid-tool-call and the next turn errors on stale state).
|
|
469
|
+
const detail = (msg.result ?? "").trim() || "Letta run ended in error.";
|
|
470
|
+
void this.conn
|
|
471
|
+
.sessionUpdate({
|
|
472
|
+
sessionId: state.id,
|
|
473
|
+
update: {
|
|
474
|
+
sessionUpdate: "agent_message_chunk",
|
|
475
|
+
content: { type: "text", text: `⚠️ ${detail}` },
|
|
476
|
+
},
|
|
477
|
+
})
|
|
478
|
+
.catch(() => { });
|
|
479
|
+
}
|
|
480
|
+
const stopReason = msg.subtype === "success"
|
|
481
|
+
? "end_turn"
|
|
482
|
+
: msg.subtype === "interrupted"
|
|
483
|
+
? "cancelled"
|
|
484
|
+
: "refusal";
|
|
485
|
+
pending.resolve({ stopReason });
|
|
486
|
+
}
|
|
487
|
+
rejectPrompt(state, msg) {
|
|
488
|
+
const pending = state.pending;
|
|
489
|
+
if (!pending) {
|
|
490
|
+
// Surface unsolicited errors via stderr.
|
|
491
|
+
process.stderr.write(`[letta-acp] error: ${msg.message}\n`);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
state.pending = undefined;
|
|
495
|
+
pending.reject(new Error(msg.message));
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
function extractText(params) {
|
|
499
|
+
// Concatenate text blocks from ACP ContentBlock[].
|
|
500
|
+
const parts = [];
|
|
501
|
+
for (const block of params.prompt ?? []) {
|
|
502
|
+
if (block.type === "text")
|
|
503
|
+
parts.push(block.text);
|
|
504
|
+
else if (block.type === "resource_link" && block.uri)
|
|
505
|
+
parts.push(block.uri);
|
|
506
|
+
}
|
|
507
|
+
return parts.join("\n");
|
|
508
|
+
}
|
|
509
|
+
function rpcError(code, message) {
|
|
510
|
+
const e = new Error(message);
|
|
511
|
+
e.code = code;
|
|
512
|
+
return e;
|
|
513
|
+
}
|
|
514
|
+
function inferKindForName(name) {
|
|
515
|
+
const n = name.toLowerCase();
|
|
516
|
+
if (n.includes("read") || n.includes("view") || n.includes("grep") || n.includes("glob"))
|
|
517
|
+
return "read";
|
|
518
|
+
if (n.includes("edit") || n.includes("write") || n.includes("patch") || n.includes("apply"))
|
|
519
|
+
return "edit";
|
|
520
|
+
if (n.includes("shell") || n.includes("bash") || n.includes("exec") || n.includes("run"))
|
|
521
|
+
return "execute";
|
|
522
|
+
if (n.includes("search"))
|
|
523
|
+
return "search";
|
|
524
|
+
if (n.includes("plan") || n.includes("todo") || n.includes("task"))
|
|
525
|
+
return "think";
|
|
526
|
+
return "other";
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Translate a Letta DiffPreview into a best-effort ACP Diff.
|
|
530
|
+
* Letta's "advanced" mode carries hunks; "fallback" and "unpreviewable" only
|
|
531
|
+
* carry a reason string. We render those as a single empty-hunk diff so the
|
|
532
|
+
* host still sees the file path.
|
|
533
|
+
*/
|
|
534
|
+
function lettaDiffToAcp(d) {
|
|
535
|
+
if (!d || typeof d !== "object")
|
|
536
|
+
return null;
|
|
537
|
+
const path = String(d.fileName ?? "");
|
|
538
|
+
if (!path)
|
|
539
|
+
return null;
|
|
540
|
+
if (d.mode === "advanced" && Array.isArray(d.hunks)) {
|
|
541
|
+
const oldLines = [];
|
|
542
|
+
const newLines = [];
|
|
543
|
+
for (const h of d.hunks) {
|
|
544
|
+
for (const line of h.lines ?? []) {
|
|
545
|
+
if (line.type === "context") {
|
|
546
|
+
oldLines.push(line.content);
|
|
547
|
+
newLines.push(line.content);
|
|
548
|
+
}
|
|
549
|
+
else if (line.type === "remove") {
|
|
550
|
+
oldLines.push(line.content);
|
|
551
|
+
}
|
|
552
|
+
else if (line.type === "add") {
|
|
553
|
+
newLines.push(line.content);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return { path, oldText: oldLines.join("\n"), newText: newLines.join("\n") };
|
|
558
|
+
}
|
|
559
|
+
return { path, oldText: "", newText: `(${d.mode}: ${d.reason ?? "no preview"})` };
|
|
560
|
+
}
|
|
561
|
+
function main() {
|
|
562
|
+
const inputWeb = Readable.toWeb(process.stdin);
|
|
563
|
+
const outputWeb = Writable.toWeb(process.stdout);
|
|
564
|
+
const stream = ndJsonStream(outputWeb, inputWeb);
|
|
565
|
+
new AgentSideConnection((conn) => new LettaAcpAgent(conn), stream);
|
|
566
|
+
process.stdin.resume();
|
|
567
|
+
}
|
|
568
|
+
main();
|
|
569
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { type WireMessage, type SystemInit } from "./wire.js";
|
|
3
|
+
export interface LettaProcessOptions {
|
|
4
|
+
cwd: string;
|
|
5
|
+
agentId?: string;
|
|
6
|
+
model?: string;
|
|
7
|
+
/** Letta permission mode: standard | acceptEdits | unrestricted | memory */
|
|
8
|
+
permissionMode?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Resume a specific conversation by id. Pass "default" for the agent's main
|
|
11
|
+
* chat (primary message history). Headless rejects `--conversation <id>`
|
|
12
|
+
* combined with `--agent` UNLESS the id is exactly "default" - so we only
|
|
13
|
+
* forward `agentId` when the conversation is either absent or "default".
|
|
14
|
+
*/
|
|
15
|
+
conversationId?: string;
|
|
16
|
+
newConversation?: boolean;
|
|
17
|
+
/** Reflection ("dreaming") trigger: off | step-count | compaction-event. */
|
|
18
|
+
reflectionTrigger?: string;
|
|
19
|
+
/** Steps between reflections when trigger=step-count. */
|
|
20
|
+
reflectionStepCount?: number;
|
|
21
|
+
lettaBin?: string;
|
|
22
|
+
extraArgs?: string[];
|
|
23
|
+
env?: NodeJS.ProcessEnv;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Owns a single `letta -p --input-format stream-json --output-format stream-json`
|
|
27
|
+
* subprocess. Emits parsed wire messages and accepts JSON inputs on stdin.
|
|
28
|
+
*
|
|
29
|
+
* Lifecycle: construct -> start() -> waits for system/init -> ready.
|
|
30
|
+
* One LettaProcess per ACP session.
|
|
31
|
+
*/
|
|
32
|
+
export declare class LettaProcess extends EventEmitter {
|
|
33
|
+
private opts;
|
|
34
|
+
private child;
|
|
35
|
+
private initMsg;
|
|
36
|
+
private exited;
|
|
37
|
+
private stderrBuf;
|
|
38
|
+
/** Cap stderr ring-buffer so long-running verbose agents don't leak memory. */
|
|
39
|
+
private static readonly STDERR_TAIL_LIMIT;
|
|
40
|
+
constructor(opts: LettaProcessOptions);
|
|
41
|
+
start(): Promise<SystemInit>;
|
|
42
|
+
/** Send a user prompt over stdin in the UserInput shape. */
|
|
43
|
+
sendUserPrompt(text: string): void;
|
|
44
|
+
/** Send a raw control request (e.g. interrupt). */
|
|
45
|
+
sendRaw(obj: unknown): void;
|
|
46
|
+
/**
|
|
47
|
+
* Cancel the in-flight turn (if any). Letta's `interrupt` control_request
|
|
48
|
+
* aborts the current operation but keeps the process alive so future
|
|
49
|
+
* prompts on the same session continue to work. We intentionally do NOT
|
|
50
|
+
* fall back to SIGINT - that would kill the subprocess and orphan the
|
|
51
|
+
* adapter's session map.
|
|
52
|
+
*/
|
|
53
|
+
cancel(): void;
|
|
54
|
+
kill(): void;
|
|
55
|
+
get init(): SystemInit | null;
|
|
56
|
+
onWire(fn: (m: WireMessage) => void): void;
|
|
57
|
+
}
|