@letta-ai/letta-code 0.32.11 → 0.32.13

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.
Files changed (39) hide show
  1. package/dist/channels-slack.js +135 -54
  2. package/dist/channels-slack.js.map +3 -3
  3. package/dist/mcp-client.js +2 -2
  4. package/dist/mcp-client.js.map +1 -1
  5. package/dist/types/agent/message.d.ts.map +1 -1
  6. package/dist/types/agent/subagents/manager.d.ts.map +1 -1
  7. package/dist/types/agent/subagents/subagent-process.d.ts +23 -0
  8. package/dist/types/agent/subagents/subagent-process.d.ts.map +1 -0
  9. package/dist/types/backend/api/metadata.d.ts +12 -0
  10. package/dist/types/backend/api/metadata.d.ts.map +1 -1
  11. package/dist/types/channels/slack/status-controller.d.ts +2 -0
  12. package/dist/types/channels/slack/status-controller.d.ts.map +1 -1
  13. package/dist/types/cli/helpers/error-formatter.d.ts.map +1 -1
  14. package/dist/types/cli/helpers/stream-processor.d.ts +2 -0
  15. package/dist/types/cli/helpers/stream-processor.d.ts.map +1 -1
  16. package/dist/types/telemetry/index.d.ts +16 -1
  17. package/dist/types/telemetry/index.d.ts.map +1 -1
  18. package/dist/types/tools/impl/process_manager.d.ts +2 -0
  19. package/dist/types/tools/impl/process_manager.d.ts.map +1 -1
  20. package/dist/types/tools/impl/task-stop.d.ts.map +1 -1
  21. package/dist/types/tools/impl/task.d.ts.map +1 -1
  22. package/dist/types/utils/cloud-api-shutdown.d.ts +17 -0
  23. package/dist/types/utils/cloud-api-shutdown.d.ts.map +1 -0
  24. package/dist/types/websocket/listener/constants.d.ts +1 -0
  25. package/dist/types/websocket/listener/constants.d.ts.map +1 -1
  26. package/letta.js +2 -2
  27. package/package.json +1 -1
  28. package/scripts/build-pypi.py +172 -0
  29. package/scripts/isolated-unit-tests.json +5 -0
  30. package/scripts/smoke-pypi.py +236 -0
  31. package/scripts/source-file-size-baseline.json +1 -1
  32. package/scripts/stage-pypi-deps.mjs +90 -0
  33. package/skills/finding-agents/SKILL.md +6 -2
  34. package/skills/letta-guide/SKILL.md +21 -2
  35. package/skills/self-configuration/SKILL.md +11 -1
  36. package/skills/converting-mcps-to-skills/SKILL.md +0 -202
  37. package/skills/converting-mcps-to-skills/references/skill-templates.md +0 -141
  38. package/skills/converting-mcps-to-skills/scripts/mcp-http.ts +0 -980
  39. package/skills/converting-mcps-to-skills/scripts/mcp-stdio.ts +0 -494
@@ -1,494 +0,0 @@
1
- #!/usr/bin/env npx tsx
2
- /**
3
- * MCP stdio Client - Connect to any MCP server over stdio
4
- *
5
- * Usage:
6
- * npx tsx mcp-stdio.ts "<command>" <action> [args]
7
- *
8
- * Commands:
9
- * list-tools List available tools
10
- * list-resources List available resources
11
- * info <tool> Show tool schema
12
- * call <tool> '<json>' Call a tool with JSON arguments
13
- *
14
- * Options:
15
- * --env "KEY=VALUE" Set environment variable (can be repeated)
16
- * --cwd <path> Set working directory for server
17
- *
18
- * Examples:
19
- * npx tsx mcp-stdio.ts "node server.js" list-tools
20
- * npx tsx mcp-stdio.ts "npx -y @modelcontextprotocol/server-filesystem ." list-tools
21
- * npx tsx mcp-stdio.ts "python server.py" call my_tool '{"arg":"value"}'
22
- * npx tsx mcp-stdio.ts "node server.js" --env "API_KEY=xxx" list-tools
23
- */
24
-
25
- import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
26
-
27
- interface JsonRpcRequest {
28
- jsonrpc: "2.0";
29
- method: string;
30
- params?: object;
31
- id: number;
32
- }
33
-
34
- interface JsonRpcNotification {
35
- jsonrpc: "2.0";
36
- method: string;
37
- params?: object;
38
- }
39
-
40
- interface JsonRpcResponse {
41
- jsonrpc: "2.0";
42
- result?: unknown;
43
- error?: {
44
- code: number;
45
- message: string;
46
- data?: unknown;
47
- };
48
- id: number;
49
- }
50
-
51
- interface ParsedArgs {
52
- serverCommand: string;
53
- action: string;
54
- actionArgs: string[];
55
- env: Record<string, string>;
56
- cwd?: string;
57
- }
58
-
59
- function parseArgs(): ParsedArgs {
60
- const args = process.argv.slice(2);
61
- const env: Record<string, string> = {};
62
- let cwd: string | undefined;
63
- let serverCommand = "";
64
- let action = "";
65
- const actionArgs: string[] = [];
66
-
67
- let i = 0;
68
- while (i < args.length) {
69
- const arg = args[i];
70
- if (!arg) {
71
- i++;
72
- continue;
73
- }
74
-
75
- if (arg === "--env" || arg === "-e") {
76
- const envValue = args[++i];
77
- if (envValue) {
78
- const eqIndex = envValue.indexOf("=");
79
- if (eqIndex > 0) {
80
- const key = envValue.slice(0, eqIndex);
81
- const value = envValue.slice(eqIndex + 1);
82
- env[key] = value;
83
- }
84
- }
85
- } else if (arg === "--cwd") {
86
- cwd = args[++i];
87
- } else if (arg === "--help" || arg === "-h") {
88
- printUsage();
89
- process.exit(0);
90
- } else if (!serverCommand) {
91
- serverCommand = arg;
92
- } else if (!action) {
93
- action = arg;
94
- } else {
95
- actionArgs.push(arg);
96
- }
97
- i++;
98
- }
99
-
100
- return { serverCommand, action, actionArgs, env, cwd };
101
- }
102
-
103
- function parseCommand(commandStr: string): { command: string; args: string[] } {
104
- // Simple parsing - split on spaces, respecting quotes.
105
- const parts: string[] = [];
106
- let current = "";
107
- let inQuote = false;
108
- let quoteChar = "";
109
-
110
- for (const char of commandStr) {
111
- if ((char === '"' || char === "'") && !inQuote) {
112
- inQuote = true;
113
- quoteChar = char;
114
- } else if (char === quoteChar && inQuote) {
115
- inQuote = false;
116
- quoteChar = "";
117
- } else if (char === " " && !inQuote) {
118
- if (current) {
119
- parts.push(current);
120
- current = "";
121
- }
122
- } else {
123
- current += char;
124
- }
125
- }
126
- if (current) {
127
- parts.push(current);
128
- }
129
-
130
- return {
131
- command: parts[0] || "",
132
- args: parts.slice(1),
133
- };
134
- }
135
-
136
- let serverProcess: ChildProcessWithoutNullStreams | null = null;
137
- let stdoutBuffer = "";
138
- let nextRequestId = 1;
139
- const pendingRequests = new Map<
140
- number,
141
- {
142
- resolve: (response: JsonRpcResponse) => void;
143
- reject: (error: Error) => void;
144
- }
145
- >();
146
-
147
- function handleStdout(chunk: Buffer): void {
148
- stdoutBuffer += chunk.toString("utf8");
149
-
150
- while (true) {
151
- const newlineIndex = stdoutBuffer.indexOf("\n");
152
- if (newlineIndex === -1) {
153
- return;
154
- }
155
-
156
- const line = stdoutBuffer.slice(0, newlineIndex).trim();
157
- stdoutBuffer = stdoutBuffer.slice(newlineIndex + 1);
158
-
159
- if (!line) {
160
- continue;
161
- }
162
-
163
- let message: unknown;
164
- try {
165
- message = JSON.parse(line);
166
- } catch {
167
- process.stderr.write(`[server stdout] ${line}\n`);
168
- continue;
169
- }
170
-
171
- if (
172
- typeof message !== "object" ||
173
- message === null ||
174
- !("id" in message) ||
175
- typeof message.id !== "number"
176
- ) {
177
- continue;
178
- }
179
-
180
- const pending = pendingRequests.get(message.id);
181
- if (!pending) {
182
- continue;
183
- }
184
-
185
- pendingRequests.delete(message.id);
186
- pending.resolve(message as JsonRpcResponse);
187
- }
188
- }
189
-
190
- function rejectPendingRequests(error: Error): void {
191
- for (const pending of pendingRequests.values()) {
192
- pending.reject(error);
193
- }
194
- pendingRequests.clear();
195
- }
196
-
197
- async function connect(
198
- serverCommand: string,
199
- env: Record<string, string>,
200
- cwd?: string,
201
- ): Promise<void> {
202
- const { command, args } = parseCommand(serverCommand);
203
-
204
- if (!command) {
205
- throw new Error("No command specified");
206
- }
207
-
208
- // Merge with process.env.
209
- const mergedEnv: Record<string, string> = {};
210
- for (const [key, value] of Object.entries(process.env)) {
211
- if (value !== undefined) {
212
- mergedEnv[key] = value;
213
- }
214
- }
215
- Object.assign(mergedEnv, env);
216
-
217
- serverProcess = spawn(command, args, {
218
- cwd,
219
- env: mergedEnv,
220
- stdio: ["pipe", "pipe", "pipe"],
221
- });
222
-
223
- serverProcess.stdout.on("data", handleStdout);
224
- serverProcess.stderr.on("data", (chunk: Buffer) => {
225
- process.stderr.write(`[server] ${chunk.toString()}`);
226
- });
227
- serverProcess.on("error", (error) => {
228
- rejectPendingRequests(error);
229
- });
230
- serverProcess.on("exit", (code, signal) => {
231
- rejectPendingRequests(
232
- new Error(`MCP server exited with code ${code} signal ${signal}`),
233
- );
234
- });
235
-
236
- const initializeResponse = await sendRequest("initialize", {
237
- protocolVersion: "2024-11-05",
238
- capabilities: {},
239
- clientInfo: {
240
- name: "mcp-stdio-cli",
241
- version: "1.0.0",
242
- },
243
- });
244
-
245
- if (initializeResponse.error) {
246
- throw new Error(
247
- `Initialization failed: ${initializeResponse.error.message}`,
248
- );
249
- }
250
-
251
- sendNotification("notifications/initialized", {});
252
- }
253
-
254
- function sendMessage(message: JsonRpcRequest | JsonRpcNotification): void {
255
- if (!serverProcess) {
256
- throw new Error("MCP server is not connected");
257
- }
258
-
259
- serverProcess.stdin.write(`${JSON.stringify(message)}\n`);
260
- }
261
-
262
- function sendNotification(method: string, params?: object): void {
263
- sendMessage({ jsonrpc: "2.0", method, params });
264
- }
265
-
266
- function sendRequest(
267
- method: string,
268
- params?: object,
269
- ): Promise<JsonRpcResponse> {
270
- const id = nextRequestId++;
271
- const request: JsonRpcRequest = { jsonrpc: "2.0", method, params, id };
272
-
273
- return new Promise((resolve, reject) => {
274
- pendingRequests.set(id, { resolve, reject });
275
- sendMessage(request);
276
- });
277
- }
278
-
279
- async function cleanup(): Promise<void> {
280
- if (serverProcess && !serverProcess.killed) {
281
- serverProcess.kill();
282
- }
283
- serverProcess = null;
284
- }
285
-
286
- async function listTools(): Promise<void> {
287
- const response = await sendRequest("tools/list");
288
-
289
- if (response.error) {
290
- console.error("Error:", response.error.message);
291
- process.exit(1);
292
- }
293
-
294
- const result = response.result as {
295
- tools: Array<{ name: string; description?: string; inputSchema: object }>;
296
- };
297
-
298
- console.log("Available tools:\n");
299
- for (const tool of result.tools) {
300
- console.log(` ${tool.name}`);
301
- if (tool.description) {
302
- console.log(` ${tool.description}\n`);
303
- } else {
304
- console.log();
305
- }
306
- }
307
-
308
- console.log(`\nTotal: ${result.tools.length} tools`);
309
- console.log("\nUse 'call <tool> <json-args>' to invoke a tool");
310
- }
311
-
312
- async function listResources(): Promise<void> {
313
- const response = await sendRequest("resources/list");
314
-
315
- if (response.error) {
316
- console.error("Error:", response.error.message);
317
- process.exit(1);
318
- }
319
-
320
- const result = response.result as {
321
- resources: Array<{ uri: string; name: string; description?: string }>;
322
- };
323
-
324
- if (!result.resources || result.resources.length === 0) {
325
- console.log("No resources available.");
326
- return;
327
- }
328
-
329
- console.log("Available resources:\n");
330
- for (const resource of result.resources) {
331
- console.log(` ${resource.uri}`);
332
- console.log(` ${resource.name}`);
333
- if (resource.description) {
334
- console.log(` ${resource.description}`);
335
- }
336
- console.log();
337
- }
338
- }
339
-
340
- async function getToolSchema(toolName: string): Promise<void> {
341
- const response = await sendRequest("tools/list");
342
-
343
- if (response.error) {
344
- console.error("Error:", response.error.message);
345
- process.exit(1);
346
- }
347
-
348
- const result = response.result as {
349
- tools: Array<{ name: string; description?: string; inputSchema: object }>;
350
- };
351
-
352
- const tool = result.tools.find((t) => t.name === toolName);
353
- if (!tool) {
354
- console.error(`Tool not found: ${toolName}`);
355
- console.error(
356
- `Available tools: ${result.tools.map((t) => t.name).join(", ")}`,
357
- );
358
- process.exit(1);
359
- }
360
-
361
- console.log(`Tool: ${tool.name}\n`);
362
- if (tool.description) {
363
- console.log(`Description: ${tool.description}\n`);
364
- }
365
- console.log("Input Schema:");
366
- console.log(JSON.stringify(tool.inputSchema, null, 2));
367
- }
368
-
369
- async function callTool(toolName: string, argsJson: string): Promise<void> {
370
- let args: Record<string, unknown>;
371
- try {
372
- args = JSON.parse(argsJson || "{}");
373
- } catch {
374
- console.error(`Invalid JSON: ${argsJson}`);
375
- process.exit(1);
376
- }
377
-
378
- const response = await sendRequest("tools/call", {
379
- name: toolName,
380
- arguments: args,
381
- });
382
-
383
- if (response.error) {
384
- console.error("Error:", response.error.message);
385
- if (response.error.data) {
386
- console.error("Details:", JSON.stringify(response.error.data, null, 2));
387
- }
388
- process.exit(1);
389
- }
390
-
391
- console.log(JSON.stringify(response.result, null, 2));
392
- }
393
-
394
- function printUsage(): void {
395
- console.log(`MCP stdio Client - Connect to any MCP server over stdio
396
-
397
- Usage: npx tsx mcp-stdio.ts "<command>" [options] <action> [args]
398
-
399
- Actions:
400
- list-tools List available tools with descriptions
401
- list-resources List available resources
402
- info <tool> Show tool schema/parameters
403
- call <tool> '<json>' Call a tool with JSON arguments
404
-
405
- Options:
406
- --env, -e "KEY=VALUE" Set environment variable (repeatable)
407
- --cwd <path> Set working directory for server
408
- --help, -h Show this help
409
-
410
- Examples:
411
- # List tools from filesystem server
412
- npx tsx mcp-stdio.ts "npx -y @modelcontextprotocol/server-filesystem ." list-tools
413
-
414
- # With environment variable
415
- npx tsx mcp-stdio.ts "node server.js" --env "API_KEY=xxx" list-tools
416
-
417
- # Call a tool
418
- npx tsx mcp-stdio.ts "python server.py" call read_file '{"path":"./README.md"}'
419
- `);
420
- }
421
-
422
- async function main(): Promise<void> {
423
- const { serverCommand, action, actionArgs, env, cwd } = parseArgs();
424
-
425
- if (!serverCommand) {
426
- console.error("Error: Server command is required\n");
427
- printUsage();
428
- process.exit(1);
429
- }
430
-
431
- if (!action) {
432
- console.error("Error: Action is required\n");
433
- printUsage();
434
- process.exit(1);
435
- }
436
-
437
- process.on("SIGINT", async () => {
438
- await cleanup();
439
- process.exit(0);
440
- });
441
-
442
- process.on("SIGTERM", async () => {
443
- await cleanup();
444
- process.exit(0);
445
- });
446
-
447
- try {
448
- await connect(serverCommand, env, cwd);
449
-
450
- switch (action) {
451
- case "list-tools":
452
- await listTools();
453
- break;
454
-
455
- case "list-resources":
456
- await listResources();
457
- break;
458
-
459
- case "info": {
460
- const [toolName] = actionArgs;
461
- if (!toolName) {
462
- console.error("Error: Tool name required");
463
- console.error("Usage: info <tool>");
464
- process.exit(1);
465
- }
466
- await getToolSchema(toolName);
467
- break;
468
- }
469
-
470
- case "call": {
471
- const [toolName, argsJson] = actionArgs;
472
- if (!toolName) {
473
- console.error("Error: Tool name required");
474
- console.error("Usage: call <tool> '<json-args>'");
475
- process.exit(1);
476
- }
477
- await callTool(toolName, argsJson || "{}");
478
- break;
479
- }
480
-
481
- default:
482
- console.error(`Unknown action: ${action}\n`);
483
- printUsage();
484
- process.exit(1);
485
- }
486
- } catch (error) {
487
- console.error("Error:", error instanceof Error ? error.message : error);
488
- process.exit(1);
489
- } finally {
490
- await cleanup();
491
- }
492
- }
493
-
494
- main();