@letta-ai/letta-code-sdk 0.0.1

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/index.js ADDED
@@ -0,0 +1,548 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/transport.ts
21
+ import { spawn } from "node:child_process";
22
+ import { createInterface } from "node:readline";
23
+
24
+ class SubprocessTransport {
25
+ options;
26
+ process = null;
27
+ stdout = null;
28
+ messageQueue = [];
29
+ messageResolvers = [];
30
+ closed = false;
31
+ agentId;
32
+ constructor(options = {}) {
33
+ this.options = options;
34
+ }
35
+ async connect() {
36
+ const args = this.buildArgs();
37
+ const cliPath = await this.findCli();
38
+ this.process = spawn("node", [cliPath, ...args], {
39
+ cwd: this.options.cwd || process.cwd(),
40
+ stdio: ["pipe", "pipe", "pipe"],
41
+ env: { ...process.env }
42
+ });
43
+ if (!this.process.stdout || !this.process.stdin) {
44
+ throw new Error("Failed to create subprocess pipes");
45
+ }
46
+ this.stdout = createInterface({
47
+ input: this.process.stdout,
48
+ crlfDelay: Infinity
49
+ });
50
+ this.stdout.on("line", (line) => {
51
+ if (!line.trim())
52
+ return;
53
+ try {
54
+ const msg = JSON.parse(line);
55
+ this.handleMessage(msg);
56
+ } catch {}
57
+ });
58
+ this.process.on("close", () => {
59
+ this.closed = true;
60
+ });
61
+ this.process.on("error", (err) => {
62
+ console.error("CLI process error:", err);
63
+ this.closed = true;
64
+ });
65
+ }
66
+ async write(data) {
67
+ if (!this.process?.stdin || this.closed) {
68
+ throw new Error("Transport not connected");
69
+ }
70
+ this.process.stdin.write(JSON.stringify(data) + `
71
+ `);
72
+ }
73
+ async read() {
74
+ if (this.messageQueue.length > 0) {
75
+ return this.messageQueue.shift();
76
+ }
77
+ if (this.closed) {
78
+ return null;
79
+ }
80
+ return new Promise((resolve) => {
81
+ this.messageResolvers.push(resolve);
82
+ });
83
+ }
84
+ async* messages() {
85
+ while (true) {
86
+ const msg = await this.read();
87
+ if (msg === null)
88
+ break;
89
+ yield msg;
90
+ }
91
+ }
92
+ close() {
93
+ if (this.process) {
94
+ this.process.stdin?.end();
95
+ this.process.kill();
96
+ this.process = null;
97
+ }
98
+ this.closed = true;
99
+ for (const resolve of this.messageResolvers) {
100
+ resolve(null);
101
+ }
102
+ this.messageResolvers = [];
103
+ }
104
+ get isClosed() {
105
+ return this.closed;
106
+ }
107
+ handleMessage(msg) {
108
+ if (msg.type === "system" && "subtype" in msg && msg.subtype === "init") {
109
+ this.agentId = msg.agent_id;
110
+ }
111
+ if (this.messageResolvers.length > 0) {
112
+ const resolve = this.messageResolvers.shift();
113
+ resolve(msg);
114
+ } else {
115
+ this.messageQueue.push(msg);
116
+ }
117
+ }
118
+ buildArgs() {
119
+ const args = [
120
+ "--output-format",
121
+ "stream-json",
122
+ "--input-format",
123
+ "stream-json"
124
+ ];
125
+ if (this.options.conversationId && this.options.conversationId !== "default" && this.options.agentId) {
126
+ throw new Error("Cannot use both 'conversationId' and 'agentId'. " + "When resuming a conversation, the agent is derived automatically.");
127
+ }
128
+ if (this.options.conversationId === "default" && !this.options.agentId) {
129
+ throw new Error("conversationId 'default' requires agentId. " + "Use resumeSession(agentId, { defaultConversation: true }) instead.");
130
+ }
131
+ if (this.options.defaultConversation && !this.options.agentId) {
132
+ throw new Error("'defaultConversation' requires agentId. " + "Use resumeSession(agentId, { defaultConversation: true }).");
133
+ }
134
+ if (this.options.newConversation && !this.options.agentId) {
135
+ throw new Error("'newConversation' requires agentId. " + "Use resumeSession(agentId, { newConversation: true }).");
136
+ }
137
+ if (this.options.continue) {
138
+ args.push("--continue");
139
+ } else if (this.options.conversationId) {
140
+ args.push("--conversation", this.options.conversationId);
141
+ } else if (this.options.agentId) {
142
+ args.push("--agent", this.options.agentId);
143
+ if (this.options.newConversation) {
144
+ args.push("--new");
145
+ } else if (this.options.defaultConversation) {
146
+ args.push("--default");
147
+ }
148
+ } else {
149
+ args.push("--new-agent");
150
+ }
151
+ if (this.options.model) {
152
+ args.push("-m", this.options.model);
153
+ }
154
+ if (this.options.systemPrompt !== undefined) {
155
+ if (typeof this.options.systemPrompt === "string") {
156
+ args.push("--system-custom", this.options.systemPrompt);
157
+ } else {
158
+ args.push("--system", this.options.systemPrompt.preset);
159
+ if (this.options.systemPrompt.append) {
160
+ args.push("--system-append", this.options.systemPrompt.append);
161
+ }
162
+ }
163
+ }
164
+ if (this.options.memory !== undefined && !this.options.agentId) {
165
+ if (this.options.memory.length === 0) {
166
+ args.push("--init-blocks", "");
167
+ } else {
168
+ const presetNames = [];
169
+ const memoryBlocksJson = [];
170
+ for (const item of this.options.memory) {
171
+ if (typeof item === "string") {
172
+ presetNames.push(item);
173
+ } else if ("blockId" in item) {
174
+ memoryBlocksJson.push(item);
175
+ } else {
176
+ memoryBlocksJson.push(item);
177
+ }
178
+ }
179
+ if (presetNames.length > 0) {
180
+ args.push("--init-blocks", presetNames.join(","));
181
+ }
182
+ if (memoryBlocksJson.length > 0) {
183
+ args.push("--memory-blocks", JSON.stringify(memoryBlocksJson));
184
+ }
185
+ }
186
+ }
187
+ if (!this.options.agentId) {
188
+ if (this.options.persona !== undefined) {
189
+ args.push("--block-value", `persona=${this.options.persona}`);
190
+ }
191
+ if (this.options.human !== undefined) {
192
+ args.push("--block-value", `human=${this.options.human}`);
193
+ }
194
+ if (this.options.project !== undefined) {
195
+ args.push("--block-value", `project=${this.options.project}`);
196
+ }
197
+ }
198
+ if (this.options.permissionMode === "bypassPermissions") {
199
+ args.push("--yolo");
200
+ } else if (this.options.permissionMode === "acceptEdits") {
201
+ args.push("--accept-edits");
202
+ }
203
+ if (this.options.allowedTools) {
204
+ args.push("--allowedTools", this.options.allowedTools.join(","));
205
+ }
206
+ return args;
207
+ }
208
+ async findCli() {
209
+ const { existsSync } = await import("node:fs");
210
+ const { dirname, join } = await import("node:path");
211
+ const { fileURLToPath } = await import("node:url");
212
+ if (process.env.LETTA_CLI_PATH && existsSync(process.env.LETTA_CLI_PATH)) {
213
+ return process.env.LETTA_CLI_PATH;
214
+ }
215
+ try {
216
+ const { createRequire: createRequire2 } = await import("node:module");
217
+ const require2 = createRequire2(import.meta.url);
218
+ const resolved = require2.resolve("@letta-ai/letta-code/letta.js");
219
+ if (existsSync(resolved)) {
220
+ return resolved;
221
+ }
222
+ } catch {}
223
+ const __filename2 = fileURLToPath(import.meta.url);
224
+ const __dirname2 = dirname(__filename2);
225
+ const localPaths = [
226
+ join(__dirname2, "../../@letta-ai/letta-code/letta.js"),
227
+ join(__dirname2, "../../../letta-code-prod/letta.js"),
228
+ join(__dirname2, "../../../letta-code/letta.js")
229
+ ];
230
+ for (const p of localPaths) {
231
+ if (existsSync(p)) {
232
+ return p;
233
+ }
234
+ }
235
+ throw new Error("Letta Code CLI not found. Set LETTA_CLI_PATH or install @letta-ai/letta-code.");
236
+ }
237
+ }
238
+
239
+ // src/validation.ts
240
+ function getBlockLabels(memory) {
241
+ return memory.map((item) => {
242
+ if (typeof item === "string")
243
+ return item;
244
+ if ("label" in item)
245
+ return item.label;
246
+ return null;
247
+ }).filter((label) => label !== null);
248
+ }
249
+ function validateSessionOptions(options) {
250
+ if (options.memory !== undefined) {
251
+ const blockLabels = getBlockLabels(options.memory);
252
+ if (options.persona !== undefined && !blockLabels.includes("persona")) {
253
+ throw new Error("Cannot set 'persona' value - block not included in 'memory'. " + "Either add 'persona' to memory array or remove the persona option.");
254
+ }
255
+ if (options.human !== undefined && !blockLabels.includes("human")) {
256
+ throw new Error("Cannot set 'human' value - block not included in 'memory'. " + "Either add 'human' to memory array or remove the human option.");
257
+ }
258
+ if (options.project !== undefined && !blockLabels.includes("project")) {
259
+ throw new Error("Cannot set 'project' value - block not included in 'memory'. " + "Either add 'project' to memory array or remove the project option.");
260
+ }
261
+ }
262
+ if (options.systemPrompt !== undefined && typeof options.systemPrompt === "object") {
263
+ const validPresets = [
264
+ "default",
265
+ "letta-claude",
266
+ "letta-codex",
267
+ "letta-gemini",
268
+ "claude",
269
+ "codex",
270
+ "gemini"
271
+ ];
272
+ if (!validPresets.includes(options.systemPrompt.preset)) {
273
+ throw new Error(`Invalid system prompt preset '${options.systemPrompt.preset}'. ` + `Valid presets: ${validPresets.join(", ")}`);
274
+ }
275
+ }
276
+ if (options.conversationId && options.newConversation) {
277
+ throw new Error("Cannot use both 'conversationId' and 'newConversation'. " + "Use conversationId to resume a specific conversation, or newConversation to create a new one.");
278
+ }
279
+ if (options.continue && options.conversationId) {
280
+ throw new Error("Cannot use both 'continue' and 'conversationId'. " + "Use continue to resume the last session, or conversationId to resume a specific conversation.");
281
+ }
282
+ if (options.continue && options.newConversation) {
283
+ throw new Error("Cannot use both 'continue' and 'newConversation'. " + "Use continue to resume the last session, or newConversation to create a new one.");
284
+ }
285
+ if (options.defaultConversation && options.conversationId) {
286
+ throw new Error("Cannot use both 'defaultConversation' and 'conversationId'. " + "Use defaultConversation with agentId, or conversationId alone.");
287
+ }
288
+ if (options.defaultConversation && options.newConversation) {
289
+ throw new Error("Cannot use both 'defaultConversation' and 'newConversation'.");
290
+ }
291
+ }
292
+
293
+ // src/session.ts
294
+ class Session {
295
+ options;
296
+ transport;
297
+ _agentId = null;
298
+ _sessionId = null;
299
+ _conversationId = null;
300
+ initialized = false;
301
+ constructor(options = {}) {
302
+ this.options = options;
303
+ validateSessionOptions(options);
304
+ this.transport = new SubprocessTransport(options);
305
+ }
306
+ async initialize() {
307
+ if (this.initialized) {
308
+ throw new Error("Session already initialized");
309
+ }
310
+ await this.transport.connect();
311
+ await this.transport.write({
312
+ type: "control_request",
313
+ request_id: "init_1",
314
+ request: { subtype: "initialize" }
315
+ });
316
+ for await (const msg of this.transport.messages()) {
317
+ if (msg.type === "system" && "subtype" in msg && msg.subtype === "init") {
318
+ const initMsg = msg;
319
+ this._agentId = initMsg.agent_id;
320
+ this._sessionId = initMsg.session_id;
321
+ this._conversationId = initMsg.conversation_id;
322
+ this.initialized = true;
323
+ return {
324
+ type: "init",
325
+ agentId: initMsg.agent_id,
326
+ sessionId: initMsg.session_id,
327
+ conversationId: initMsg.conversation_id,
328
+ model: initMsg.model,
329
+ tools: initMsg.tools
330
+ };
331
+ }
332
+ }
333
+ throw new Error("Failed to initialize session - no init message received");
334
+ }
335
+ async send(message) {
336
+ if (!this.initialized) {
337
+ await this.initialize();
338
+ }
339
+ await this.transport.write({
340
+ type: "user",
341
+ message: { role: "user", content: message }
342
+ });
343
+ }
344
+ async* stream() {
345
+ for await (const wireMsg of this.transport.messages()) {
346
+ if (wireMsg.type === "control_request") {
347
+ const controlReq = wireMsg;
348
+ if (controlReq.request.subtype === "can_use_tool") {
349
+ await this.handleCanUseTool(controlReq.request_id, controlReq.request);
350
+ continue;
351
+ }
352
+ }
353
+ const sdkMsg = this.transformMessage(wireMsg);
354
+ if (sdkMsg) {
355
+ yield sdkMsg;
356
+ if (sdkMsg.type === "result") {
357
+ break;
358
+ }
359
+ }
360
+ }
361
+ }
362
+ async handleCanUseTool(requestId, req) {
363
+ let response;
364
+ if (this.options.canUseTool) {
365
+ try {
366
+ const result = await this.options.canUseTool(req.tool_name, req.input);
367
+ if (result.allow) {
368
+ response = {
369
+ behavior: "allow",
370
+ updatedInput: null,
371
+ updatedPermissions: []
372
+ };
373
+ } else {
374
+ response = {
375
+ behavior: "deny",
376
+ message: result.reason ?? "Denied by canUseTool callback",
377
+ interrupt: false
378
+ };
379
+ }
380
+ } catch (err) {
381
+ response = {
382
+ behavior: "deny",
383
+ message: err instanceof Error ? err.message : "Callback error",
384
+ interrupt: false
385
+ };
386
+ }
387
+ } else {
388
+ response = {
389
+ behavior: "deny",
390
+ message: "No canUseTool callback registered",
391
+ interrupt: false
392
+ };
393
+ }
394
+ await this.transport.write({
395
+ type: "control_response",
396
+ response: {
397
+ subtype: "success",
398
+ request_id: requestId,
399
+ response
400
+ }
401
+ });
402
+ }
403
+ async abort() {
404
+ await this.transport.write({
405
+ type: "control_request",
406
+ request_id: `interrupt-${Date.now()}`,
407
+ request: { subtype: "interrupt" }
408
+ });
409
+ }
410
+ close() {
411
+ this.transport.close();
412
+ }
413
+ get agentId() {
414
+ return this._agentId;
415
+ }
416
+ get sessionId() {
417
+ return this._sessionId;
418
+ }
419
+ get conversationId() {
420
+ return this._conversationId;
421
+ }
422
+ async[Symbol.asyncDispose]() {
423
+ this.close();
424
+ }
425
+ transformMessage(wireMsg) {
426
+ if (wireMsg.type === "system" && "subtype" in wireMsg && wireMsg.subtype === "init") {
427
+ const msg = wireMsg;
428
+ return {
429
+ type: "init",
430
+ agentId: msg.agent_id,
431
+ sessionId: msg.session_id,
432
+ conversationId: msg.conversation_id,
433
+ model: msg.model,
434
+ tools: msg.tools
435
+ };
436
+ }
437
+ if (wireMsg.type === "message" && "message_type" in wireMsg) {
438
+ const msg = wireMsg;
439
+ if (msg.message_type === "assistant_message" && msg.content) {
440
+ return {
441
+ type: "assistant",
442
+ content: msg.content,
443
+ uuid: msg.uuid
444
+ };
445
+ }
446
+ if (msg.message_type === "tool_call_message") {
447
+ const toolCall = msg.tool_calls?.[0] || msg.tool_call;
448
+ if (toolCall) {
449
+ let toolInput = {};
450
+ try {
451
+ toolInput = JSON.parse(toolCall.arguments);
452
+ } catch {
453
+ toolInput = { raw: toolCall.arguments };
454
+ }
455
+ return {
456
+ type: "tool_call",
457
+ toolCallId: toolCall.tool_call_id,
458
+ toolName: toolCall.name,
459
+ toolInput,
460
+ uuid: msg.uuid
461
+ };
462
+ }
463
+ }
464
+ if (msg.message_type === "tool_return_message" && msg.tool_call_id) {
465
+ return {
466
+ type: "tool_result",
467
+ toolCallId: msg.tool_call_id,
468
+ content: msg.tool_return || "",
469
+ isError: msg.status === "error",
470
+ uuid: msg.uuid
471
+ };
472
+ }
473
+ if (msg.message_type === "reasoning_message" && msg.reasoning) {
474
+ return {
475
+ type: "reasoning",
476
+ content: msg.reasoning,
477
+ uuid: msg.uuid
478
+ };
479
+ }
480
+ }
481
+ if (wireMsg.type === "stream_event") {
482
+ const msg = wireMsg;
483
+ return {
484
+ type: "stream_event",
485
+ event: msg.event,
486
+ uuid: msg.uuid
487
+ };
488
+ }
489
+ if (wireMsg.type === "result") {
490
+ const msg = wireMsg;
491
+ return {
492
+ type: "result",
493
+ success: msg.subtype === "success",
494
+ result: msg.result,
495
+ error: msg.subtype !== "success" ? msg.subtype : undefined,
496
+ durationMs: msg.duration_ms,
497
+ totalCostUsd: msg.total_cost_usd,
498
+ conversationId: msg.conversation_id
499
+ };
500
+ }
501
+ return null;
502
+ }
503
+ }
504
+
505
+ // src/index.ts
506
+ function createSession(options = {}) {
507
+ return new Session(options);
508
+ }
509
+ function resumeSession(agentId, options = {}) {
510
+ return new Session({ ...options, agentId });
511
+ }
512
+ function resumeConversation(conversationId, options = {}) {
513
+ return new Session({ ...options, conversationId });
514
+ }
515
+ async function prompt(message, options = {}) {
516
+ const session = createSession(options);
517
+ try {
518
+ await session.send(message);
519
+ let result = null;
520
+ for await (const msg of session.stream()) {
521
+ if (msg.type === "result") {
522
+ result = msg;
523
+ break;
524
+ }
525
+ }
526
+ if (!result) {
527
+ return {
528
+ type: "result",
529
+ success: false,
530
+ error: "No result received",
531
+ durationMs: 0,
532
+ conversationId: session.conversationId
533
+ };
534
+ }
535
+ return result;
536
+ } finally {
537
+ session.close();
538
+ }
539
+ }
540
+ export {
541
+ resumeSession,
542
+ resumeConversation,
543
+ prompt,
544
+ createSession,
545
+ Session
546
+ };
547
+
548
+ //# debugId=09C34BBA63D0BCBD64756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/transport.ts", "../src/validation.ts", "../src/session.ts", "../src/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * SubprocessTransport\n *\n * Spawns the Letta Code CLI and communicates via stdin/stdout JSON streams.\n */\n\nimport { spawn, type ChildProcess } from \"node:child_process\";\nimport { createInterface, type Interface } from \"node:readline\";\nimport type { SessionOptions, WireMessage } from \"./types.js\";\n\nexport class SubprocessTransport {\n private process: ChildProcess | null = null;\n private stdout: Interface | null = null;\n private messageQueue: WireMessage[] = [];\n private messageResolvers: Array<(msg: WireMessage) => void> = [];\n private closed = false;\n private agentId?: string;\n\n constructor(\n private options: SessionOptions & { agentId?: string } = {}\n ) {}\n\n /**\n * Start the CLI subprocess\n */\n async connect(): Promise<void> {\n const args = this.buildArgs();\n\n // Find the CLI - use the installed letta-code package\n const cliPath = await this.findCli();\n\n this.process = spawn(\"node\", [cliPath, ...args], {\n cwd: this.options.cwd || process.cwd(),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n if (!this.process.stdout || !this.process.stdin) {\n throw new Error(\"Failed to create subprocess pipes\");\n }\n\n // Set up stdout reading\n this.stdout = createInterface({\n input: this.process.stdout,\n crlfDelay: Infinity,\n });\n\n this.stdout.on(\"line\", (line) => {\n if (!line.trim()) return;\n try {\n const msg = JSON.parse(line) as WireMessage;\n this.handleMessage(msg);\n } catch {\n // Ignore non-JSON lines (stderr leakage, etc.)\n }\n });\n\n // Handle process exit\n this.process.on(\"close\", () => {\n this.closed = true;\n });\n\n this.process.on(\"error\", (err) => {\n console.error(\"CLI process error:\", err);\n this.closed = true;\n });\n }\n\n /**\n * Send a message to the CLI via stdin\n */\n async write(data: object): Promise<void> {\n if (!this.process?.stdin || this.closed) {\n throw new Error(\"Transport not connected\");\n }\n this.process.stdin.write(JSON.stringify(data) + \"\\n\");\n }\n\n /**\n * Read the next message from the CLI\n */\n async read(): Promise<WireMessage | null> {\n // Return queued message if available\n if (this.messageQueue.length > 0) {\n return this.messageQueue.shift()!;\n }\n\n // If closed, no more messages\n if (this.closed) {\n return null;\n }\n\n // Wait for next message\n return new Promise((resolve) => {\n this.messageResolvers.push(resolve);\n });\n }\n\n /**\n * Async iterator for messages\n */\n async *messages(): AsyncGenerator<WireMessage> {\n while (true) {\n const msg = await this.read();\n if (msg === null) break;\n yield msg;\n }\n }\n\n /**\n * Close the transport\n */\n close(): void {\n if (this.process) {\n this.process.stdin?.end();\n this.process.kill();\n this.process = null;\n }\n this.closed = true;\n\n // Resolve any pending readers with null\n for (const resolve of this.messageResolvers) {\n resolve(null as unknown as WireMessage);\n }\n this.messageResolvers = [];\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n private handleMessage(msg: WireMessage): void {\n // Track agent_id from init message\n if (msg.type === \"system\" && \"subtype\" in msg && msg.subtype === \"init\") {\n this.agentId = (msg as unknown as { agent_id: string }).agent_id;\n }\n\n // If someone is waiting for a message, give it to them\n if (this.messageResolvers.length > 0) {\n const resolve = this.messageResolvers.shift()!;\n resolve(msg);\n } else {\n // Otherwise queue it\n this.messageQueue.push(msg);\n }\n }\n\n private buildArgs(): string[] {\n const args: string[] = [\n \"--output-format\",\n \"stream-json\",\n \"--input-format\",\n \"stream-json\",\n ];\n\n // Validate conversation + agent combinations\n // (These require agentId context, so can't be in validateSessionOptions)\n \n // conversationId (non-default) cannot be used with agentId\n if (this.options.conversationId && \n this.options.conversationId !== \"default\" && \n this.options.agentId) {\n throw new Error(\n \"Cannot use both 'conversationId' and 'agentId'. \" +\n \"When resuming a conversation, the agent is derived automatically.\"\n );\n }\n\n // conversationId: \"default\" requires agentId\n if (this.options.conversationId === \"default\" && !this.options.agentId) {\n throw new Error(\n \"conversationId 'default' requires agentId. \" +\n \"Use resumeSession(agentId, { defaultConversation: true }) instead.\"\n );\n }\n\n // defaultConversation requires agentId\n if (this.options.defaultConversation && !this.options.agentId) {\n throw new Error(\n \"'defaultConversation' requires agentId. \" +\n \"Use resumeSession(agentId, { defaultConversation: true }).\"\n );\n }\n\n // newConversation requires agentId\n if (this.options.newConversation && !this.options.agentId) {\n throw new Error(\n \"'newConversation' requires agentId. \" +\n \"Use resumeSession(agentId, { newConversation: true }).\"\n );\n }\n\n // Conversation and agent handling\n if (this.options.continue) {\n // Resume last session (agent + conversation)\n args.push(\"--continue\");\n } else if (this.options.conversationId) {\n // Resume specific conversation (derives agent automatically)\n args.push(\"--conversation\", this.options.conversationId);\n } else if (this.options.agentId) {\n // Resume existing agent\n args.push(\"--agent\", this.options.agentId);\n if (this.options.newConversation) {\n // Create new conversation on this agent\n args.push(\"--new\");\n } else if (this.options.defaultConversation) {\n // Use agent's default conversation explicitly\n args.push(\"--default\");\n }\n } else {\n // Create new agent\n args.push(\"--new-agent\");\n }\n\n // Model\n if (this.options.model) {\n args.push(\"-m\", this.options.model);\n }\n\n // System prompt configuration\n if (this.options.systemPrompt !== undefined) {\n if (typeof this.options.systemPrompt === \"string\") {\n // Raw string → --system-custom\n args.push(\"--system-custom\", this.options.systemPrompt);\n } else {\n // Preset object → --system (+ optional --system-append)\n args.push(\"--system\", this.options.systemPrompt.preset);\n if (this.options.systemPrompt.append) {\n args.push(\"--system-append\", this.options.systemPrompt.append);\n }\n }\n }\n\n // Memory blocks (only for new agents)\n if (this.options.memory !== undefined && !this.options.agentId) {\n if (this.options.memory.length === 0) {\n // Empty array → no memory blocks (just core)\n args.push(\"--init-blocks\", \"\");\n } else {\n // Separate preset names from custom/reference blocks\n const presetNames: string[] = [];\n const memoryBlocksJson: Array<\n | { label: string; value: string }\n | { blockId: string }\n > = [];\n\n for (const item of this.options.memory) {\n if (typeof item === \"string\") {\n // Preset name\n presetNames.push(item);\n } else if (\"blockId\" in item) {\n // Block reference - pass to --memory-blocks\n memoryBlocksJson.push(item as { blockId: string });\n } else {\n // CreateBlock\n memoryBlocksJson.push(item as { label: string; value: string });\n }\n }\n\n // Add preset names via --init-blocks\n if (presetNames.length > 0) {\n args.push(\"--init-blocks\", presetNames.join(\",\"));\n }\n\n // Add custom blocks and block references via --memory-blocks\n if (memoryBlocksJson.length > 0) {\n args.push(\"--memory-blocks\", JSON.stringify(memoryBlocksJson));\n }\n }\n }\n\n // Convenience props for block values (only for new agents)\n if (!this.options.agentId) {\n if (this.options.persona !== undefined) {\n args.push(\"--block-value\", `persona=${this.options.persona}`);\n }\n if (this.options.human !== undefined) {\n args.push(\"--block-value\", `human=${this.options.human}`);\n }\n if (this.options.project !== undefined) {\n args.push(\"--block-value\", `project=${this.options.project}`);\n }\n }\n\n // Permission mode\n if (this.options.permissionMode === \"bypassPermissions\") {\n args.push(\"--yolo\");\n } else if (this.options.permissionMode === \"acceptEdits\") {\n args.push(\"--accept-edits\");\n }\n\n // Allowed tools\n if (this.options.allowedTools) {\n args.push(\"--allowedTools\", this.options.allowedTools.join(\",\"));\n }\n\n return args;\n }\n\n private async findCli(): Promise<string> {\n // Try multiple resolution strategies\n const { existsSync } = await import(\"node:fs\");\n const { dirname, join } = await import(\"node:path\");\n const { fileURLToPath } = await import(\"node:url\");\n\n // Strategy 1: Check LETTA_CLI_PATH env var\n if (process.env.LETTA_CLI_PATH && existsSync(process.env.LETTA_CLI_PATH)) {\n return process.env.LETTA_CLI_PATH;\n }\n\n // Strategy 2: Try to resolve from node_modules\n try {\n const { createRequire } = await import(\"node:module\");\n const require = createRequire(import.meta.url);\n const resolved = require.resolve(\"@letta-ai/letta-code/letta.js\");\n if (existsSync(resolved)) {\n return resolved;\n }\n } catch {\n // Continue to next strategy\n }\n\n // Strategy 3: Check relative to this file (for local file: deps)\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const localPaths = [\n join(__dirname, \"../../@letta-ai/letta-code/letta.js\"),\n join(__dirname, \"../../../letta-code-prod/letta.js\"),\n join(__dirname, \"../../../letta-code/letta.js\"),\n ];\n\n for (const p of localPaths) {\n if (existsSync(p)) {\n return p;\n }\n }\n\n throw new Error(\n \"Letta Code CLI not found. Set LETTA_CLI_PATH or install @letta-ai/letta-code.\"\n );\n }\n}\n",
6
+ "/**\n * SDK Validation\n *\n * Validates SessionOptions before spawning the CLI.\n */\n\nimport type { SessionOptions, MemoryItem, CreateBlock } from \"./types.js\";\n\n/**\n * Extract block labels from memory items.\n */\nfunction getBlockLabels(memory: MemoryItem[]): string[] {\n return memory\n .map((item) => {\n if (typeof item === \"string\") return item; // preset name\n if (\"label\" in item) return (item as CreateBlock).label; // CreateBlock\n return null; // blockId - no label to check\n })\n .filter((label): label is string => label !== null);\n}\n\n/**\n * Validate SessionOptions before spawning CLI.\n * Throws an error if validation fails.\n */\nexport function validateSessionOptions(options: SessionOptions): void {\n // If memory is specified, validate that convenience props match included blocks\n if (options.memory !== undefined) {\n const blockLabels = getBlockLabels(options.memory);\n\n if (options.persona !== undefined && !blockLabels.includes(\"persona\")) {\n throw new Error(\n \"Cannot set 'persona' value - block not included in 'memory'. \" +\n \"Either add 'persona' to memory array or remove the persona option.\"\n );\n }\n\n if (options.human !== undefined && !blockLabels.includes(\"human\")) {\n throw new Error(\n \"Cannot set 'human' value - block not included in 'memory'. \" +\n \"Either add 'human' to memory array or remove the human option.\"\n );\n }\n\n if (options.project !== undefined && !blockLabels.includes(\"project\")) {\n throw new Error(\n \"Cannot set 'project' value - block not included in 'memory'. \" +\n \"Either add 'project' to memory array or remove the project option.\"\n );\n }\n }\n\n // Validate systemPrompt preset if provided\n if (\n options.systemPrompt !== undefined &&\n typeof options.systemPrompt === \"object\"\n ) {\n const validPresets = [\n \"default\",\n \"letta-claude\",\n \"letta-codex\",\n \"letta-gemini\",\n \"claude\",\n \"codex\",\n \"gemini\",\n ];\n if (!validPresets.includes(options.systemPrompt.preset)) {\n throw new Error(\n `Invalid system prompt preset '${options.systemPrompt.preset}'. ` +\n `Valid presets: ${validPresets.join(\", \")}`\n );\n }\n }\n\n // Validate conversation options\n if (options.conversationId && options.newConversation) {\n throw new Error(\n \"Cannot use both 'conversationId' and 'newConversation'. \" +\n \"Use conversationId to resume a specific conversation, or newConversation to create a new one.\"\n );\n }\n\n if (options.continue && options.conversationId) {\n throw new Error(\n \"Cannot use both 'continue' and 'conversationId'. \" +\n \"Use continue to resume the last session, or conversationId to resume a specific conversation.\"\n );\n }\n\n if (options.continue && options.newConversation) {\n throw new Error(\n \"Cannot use both 'continue' and 'newConversation'. \" +\n \"Use continue to resume the last session, or newConversation to create a new one.\"\n );\n }\n\n if (options.defaultConversation && options.conversationId) {\n throw new Error(\n \"Cannot use both 'defaultConversation' and 'conversationId'. \" +\n \"Use defaultConversation with agentId, or conversationId alone.\"\n );\n }\n\n if (options.defaultConversation && options.newConversation) {\n throw new Error(\n \"Cannot use both 'defaultConversation' and 'newConversation'.\"\n );\n }\n\n // Note: Validations that require agentId context happen in transport.ts buildArgs()\n // because agentId is passed separately to resumeSession(), not in SessionOptions\n}\n",
7
+ "/**\n * Session\n *\n * Represents a conversation session with a Letta agent.\n * Implements the V2 API pattern: send() / receive()\n */\n\nimport { SubprocessTransport } from \"./transport.js\";\nimport type {\n SessionOptions,\n SDKMessage,\n SDKInitMessage,\n SDKAssistantMessage,\n SDKResultMessage,\n WireMessage,\n ControlRequest,\n CanUseToolControlRequest,\n CanUseToolResponse,\n CanUseToolResponseAllow,\n CanUseToolResponseDeny,\n} from \"./types.js\";\nimport { validateSessionOptions } from \"./validation.js\";\n\nexport class Session implements AsyncDisposable {\n private transport: SubprocessTransport;\n private _agentId: string | null = null;\n private _sessionId: string | null = null;\n private _conversationId: string | null = null;\n private initialized = false;\n\n constructor(\n private options: SessionOptions & { agentId?: string } = {}\n ) {\n // Validate options before creating transport\n validateSessionOptions(options);\n this.transport = new SubprocessTransport(options);\n }\n\n /**\n * Initialize the session (called automatically on first send)\n */\n async initialize(): Promise<SDKInitMessage> {\n if (this.initialized) {\n throw new Error(\"Session already initialized\");\n }\n\n await this.transport.connect();\n\n // Send initialize control request\n await this.transport.write({\n type: \"control_request\",\n request_id: \"init_1\",\n request: { subtype: \"initialize\" },\n });\n\n // Wait for init message\n for await (const msg of this.transport.messages()) {\n if (msg.type === \"system\" && \"subtype\" in msg && msg.subtype === \"init\") {\n const initMsg = msg as WireMessage & {\n agent_id: string;\n session_id: string;\n conversation_id: string;\n model: string;\n tools: string[];\n };\n this._agentId = initMsg.agent_id;\n this._sessionId = initMsg.session_id;\n this._conversationId = initMsg.conversation_id;\n this.initialized = true;\n\n return {\n type: \"init\",\n agentId: initMsg.agent_id,\n sessionId: initMsg.session_id,\n conversationId: initMsg.conversation_id,\n model: initMsg.model,\n tools: initMsg.tools,\n };\n }\n }\n\n throw new Error(\"Failed to initialize session - no init message received\");\n }\n\n /**\n * Send a message to the agent\n */\n async send(message: string): Promise<void> {\n if (!this.initialized) {\n await this.initialize();\n }\n\n await this.transport.write({\n type: \"user\",\n message: { role: \"user\", content: message },\n });\n }\n\n /**\n * Stream messages from the agent\n */\n async *stream(): AsyncGenerator<SDKMessage> {\n for await (const wireMsg of this.transport.messages()) {\n // Handle CLI → SDK control requests (e.g., can_use_tool)\n if (wireMsg.type === \"control_request\") {\n const controlReq = wireMsg as ControlRequest;\n if (controlReq.request.subtype === \"can_use_tool\") {\n await this.handleCanUseTool(\n controlReq.request_id,\n controlReq.request as CanUseToolControlRequest\n );\n continue;\n }\n }\n\n const sdkMsg = this.transformMessage(wireMsg);\n if (sdkMsg) {\n yield sdkMsg;\n\n // Stop on result message\n if (sdkMsg.type === \"result\") {\n break;\n }\n }\n }\n }\n\n /**\n * Handle can_use_tool control request from CLI (Claude SDK compatible format)\n */\n private async handleCanUseTool(\n requestId: string,\n req: CanUseToolControlRequest\n ): Promise<void> {\n let response: CanUseToolResponse;\n\n if (this.options.canUseTool) {\n try {\n const result = await this.options.canUseTool(req.tool_name, req.input);\n if (result.allow) {\n response = {\n behavior: \"allow\",\n updatedInput: null, // TODO: not supported\n updatedPermissions: [], // TODO: not implemented\n } satisfies CanUseToolResponseAllow;\n } else {\n response = {\n behavior: \"deny\",\n message: result.reason ?? \"Denied by canUseTool callback\",\n interrupt: false, // TODO: not wired up yet\n } satisfies CanUseToolResponseDeny;\n }\n } catch (err) {\n response = {\n behavior: \"deny\",\n message: err instanceof Error ? err.message : \"Callback error\",\n interrupt: false,\n };\n }\n } else {\n // No callback registered - deny by default\n response = {\n behavior: \"deny\",\n message: \"No canUseTool callback registered\",\n interrupt: false,\n };\n }\n\n // Send control_response (Claude SDK compatible format)\n await this.transport.write({\n type: \"control_response\",\n response: {\n subtype: \"success\",\n request_id: requestId,\n response,\n },\n });\n }\n\n /**\n * Abort the current operation (interrupt without closing the session)\n */\n async abort(): Promise<void> {\n await this.transport.write({\n type: \"control_request\",\n request_id: `interrupt-${Date.now()}`,\n request: { subtype: \"interrupt\" },\n });\n }\n\n /**\n * Close the session\n */\n close(): void {\n this.transport.close();\n }\n\n /**\n * Get the agent ID (available after initialization)\n */\n get agentId(): string | null {\n return this._agentId;\n }\n\n /**\n * Get the session ID (available after initialization)\n */\n get sessionId(): string | null {\n return this._sessionId;\n }\n\n /**\n * Get the conversation ID (available after initialization)\n */\n get conversationId(): string | null {\n return this._conversationId;\n }\n\n /**\n * AsyncDisposable implementation for `await using`\n */\n async [Symbol.asyncDispose](): Promise<void> {\n this.close();\n }\n\n /**\n * Transform wire message to SDK message\n */\n private transformMessage(wireMsg: WireMessage): SDKMessage | null {\n // Init message\n if (wireMsg.type === \"system\" && \"subtype\" in wireMsg && wireMsg.subtype === \"init\") {\n const msg = wireMsg as WireMessage & {\n agent_id: string;\n session_id: string;\n conversation_id: string;\n model: string;\n tools: string[];\n };\n return {\n type: \"init\",\n agentId: msg.agent_id,\n sessionId: msg.session_id,\n conversationId: msg.conversation_id,\n model: msg.model,\n tools: msg.tools,\n };\n }\n\n // Handle message types (all have type: \"message\" with message_type field)\n if (wireMsg.type === \"message\" && \"message_type\" in wireMsg) {\n const msg = wireMsg as WireMessage & {\n message_type: string;\n uuid: string;\n // assistant_message fields\n content?: string;\n // tool_call_message fields\n tool_call?: { name: string; arguments: string; tool_call_id: string };\n tool_calls?: Array<{ name: string; arguments: string; tool_call_id: string }>;\n // tool_return_message fields\n tool_call_id?: string;\n tool_return?: string;\n status?: \"success\" | \"error\";\n // reasoning_message fields\n reasoning?: string;\n };\n\n // Assistant message\n if (msg.message_type === \"assistant_message\" && msg.content) {\n return {\n type: \"assistant\",\n content: msg.content,\n uuid: msg.uuid,\n };\n }\n\n // Tool call message\n if (msg.message_type === \"tool_call_message\") {\n const toolCall = msg.tool_calls?.[0] || msg.tool_call;\n if (toolCall) {\n let toolInput: Record<string, unknown> = {};\n try {\n toolInput = JSON.parse(toolCall.arguments);\n } catch {\n toolInput = { raw: toolCall.arguments };\n }\n return {\n type: \"tool_call\",\n toolCallId: toolCall.tool_call_id,\n toolName: toolCall.name,\n toolInput,\n uuid: msg.uuid,\n };\n }\n }\n\n // Tool return message\n if (msg.message_type === \"tool_return_message\" && msg.tool_call_id) {\n return {\n type: \"tool_result\",\n toolCallId: msg.tool_call_id,\n content: msg.tool_return || \"\",\n isError: msg.status === \"error\",\n uuid: msg.uuid,\n };\n }\n\n // Reasoning message\n if (msg.message_type === \"reasoning_message\" && msg.reasoning) {\n return {\n type: \"reasoning\",\n content: msg.reasoning,\n uuid: msg.uuid,\n };\n }\n }\n\n // Stream event (partial message updates)\n if (wireMsg.type === \"stream_event\") {\n const msg = wireMsg as WireMessage & {\n event: {\n type: string;\n index?: number;\n delta?: { type?: string; text?: string; reasoning?: string };\n content_block?: { type?: string; text?: string };\n };\n uuid: string;\n };\n return {\n type: \"stream_event\",\n event: msg.event,\n uuid: msg.uuid,\n };\n }\n\n // Result message\n if (wireMsg.type === \"result\") {\n const msg = wireMsg as WireMessage & {\n subtype: string;\n result?: string;\n duration_ms: number;\n total_cost_usd?: number;\n conversation_id: string;\n };\n return {\n type: \"result\",\n success: msg.subtype === \"success\",\n result: msg.result,\n error: msg.subtype !== \"success\" ? msg.subtype : undefined,\n durationMs: msg.duration_ms,\n totalCostUsd: msg.total_cost_usd,\n conversationId: msg.conversation_id,\n };\n }\n\n // Skip other message types (system_message, user_message, etc.)\n return null;\n }\n}\n",
8
+ "/**\n * Letta Code SDK\n *\n * Programmatic control of Letta Code CLI with persistent agent memory.\n *\n * @example\n * ```typescript\n * import { createSession, prompt } from '@letta-ai/letta-code-sdk';\n *\n * // One-shot\n * const result = await prompt('What is 2+2?', { model: 'claude-sonnet-4-20250514' });\n *\n * // Multi-turn session\n * await using session = createSession({ model: 'claude-sonnet-4-20250514' });\n * await session.send('Hello!');\n * for await (const msg of session.stream()) {\n * if (msg.type === 'assistant') console.log(msg.content);\n * }\n *\n * // Resume with persistent memory\n * await using resumed = resumeSession(agentId, { model: 'claude-sonnet-4-20250514' });\n * ```\n */\n\nimport { Session } from \"./session.js\";\nimport type { SessionOptions, SDKMessage, SDKResultMessage } from \"./types.js\";\n\n// Re-export types\nexport type {\n SessionOptions,\n SDKMessage,\n SDKInitMessage,\n SDKAssistantMessage,\n SDKToolCallMessage,\n SDKToolResultMessage,\n SDKReasoningMessage,\n SDKResultMessage,\n SDKStreamEventMessage,\n PermissionMode,\n PermissionResult,\n CanUseToolCallback,\n} from \"./types.js\";\n\nexport { Session } from \"./session.js\";\n\n/**\n * Create a new session with a fresh Letta agent.\n *\n * The agent will have persistent memory that survives across sessions.\n * Use `resumeSession` to continue a conversation with an existing agent.\n *\n * @example\n * ```typescript\n * await using session = createSession({ model: 'claude-sonnet-4-20250514' });\n * await session.send('My name is Alice');\n * for await (const msg of session.stream()) {\n * console.log(msg);\n * }\n * console.log(`Agent ID: ${session.agentId}`); // Save this to resume later\n * ```\n */\nexport function createSession(options: SessionOptions = {}): Session {\n return new Session(options);\n}\n\n/**\n * Resume an existing session with a Letta agent.\n *\n * Unlike Claude Agent SDK (ephemeral sessions), Letta agents have persistent\n * memory. You can resume a conversation days later and the agent will remember.\n *\n * @example\n * ```typescript\n * // Days later...\n * await using session = resumeSession(agentId, { model: 'claude-sonnet-4-20250514' });\n * await session.send('What is my name?');\n * for await (const msg of session.stream()) {\n * // Agent remembers: \"Your name is Alice\"\n * }\n * ```\n */\nexport function resumeSession(\n agentId: string,\n options: SessionOptions = {}\n): Session {\n return new Session({ ...options, agentId });\n}\n\n/**\n * Resume an existing conversation.\n *\n * Conversations are threads within an agent. The agent is derived automatically\n * from the conversation ID. Use this to continue a specific conversation thread.\n *\n * @example\n * ```typescript\n * // Resume a specific conversation\n * await using session = resumeConversation(conversationId);\n * await session.send('Continue our discussion...');\n * for await (const msg of session.stream()) {\n * console.log(msg);\n * }\n * ```\n */\nexport function resumeConversation(\n conversationId: string,\n options: SessionOptions = {}\n): Session {\n return new Session({ ...options, conversationId });\n}\n\n/**\n * One-shot prompt convenience function.\n *\n * Creates a session, sends the prompt, collects the response, and closes.\n * Returns the final result message.\n *\n * @example\n * ```typescript\n * const result = await prompt('What is the capital of France?', {\n * model: 'claude-sonnet-4-20250514'\n * });\n * if (result.success) {\n * console.log(result.result);\n * }\n * ```\n */\nexport async function prompt(\n message: string,\n options: SessionOptions = {}\n): Promise<SDKResultMessage> {\n const session = createSession(options);\n\n try {\n await session.send(message);\n\n let result: SDKResultMessage | null = null;\n for await (const msg of session.stream()) {\n if (msg.type === \"result\") {\n result = msg;\n break;\n }\n }\n\n if (!result) {\n return {\n type: \"result\",\n success: false,\n error: \"No result received\",\n durationMs: 0,\n conversationId: session.conversationId,\n };\n }\n\n return result;\n } finally {\n session.close();\n }\n}\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "09C34BBA63D0BCBD64756E2164756E21",
12
+ "names": []
13
+ }