@letta-ai/letta-code 0.14.15 → 0.14.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/letta.js CHANGED
@@ -3122,7 +3122,7 @@ var package_default;
3122
3122
  var init_package = __esm(() => {
3123
3123
  package_default = {
3124
3124
  name: "@letta-ai/letta-code",
3125
- version: "0.14.15",
3125
+ version: "0.14.16",
3126
3126
  description: "Letta Code is a CLI tool for interacting with stateful Letta agents from the terminal.",
3127
3127
  type: "module",
3128
3128
  bin: {
@@ -38464,6 +38464,10 @@ var init_EnterPlanMode2 = __esm(() => {
38464
38464
 
38465
38465
  // src/tools/impl/ExitPlanMode.ts
38466
38466
  async function exit_plan_mode() {
38467
+ if (permissionMode2.getMode() === "plan") {
38468
+ const restoredMode = permissionMode2.getModeBeforePlan() ?? "default";
38469
+ permissionMode2.setMode(restoredMode);
38470
+ }
38467
38471
  return {
38468
38472
  message: `User has approved your plan. You can now start coding.
38469
38473
  ` + `Start with updating your todo list if applicable.
@@ -38471,6 +38475,9 @@ async function exit_plan_mode() {
38471
38475
  ` + "Tip: If this plan will be referenced in the future by your future-self, " + "other agents, or humans, consider renaming the plan file to something easily " + "identifiable with a timestamp (e.g., `2026-01-auth-refactor.md`) rather than the random name."
38472
38476
  };
38473
38477
  }
38478
+ var init_ExitPlanMode2 = __esm(() => {
38479
+ init_mode();
38480
+ });
38474
38481
 
38475
38482
  // src/tools/impl/Glob.ts
38476
38483
  import { execFile } from "node:child_process";
@@ -55625,7 +55632,7 @@ var init_EnterPlanMode3 = __esm(() => {
55625
55632
 
55626
55633
  // src/tools/schemas/ExitPlanMode.json
55627
55634
  var ExitPlanMode_default2;
55628
- var init_ExitPlanMode2 = __esm(() => {
55635
+ var init_ExitPlanMode3 = __esm(() => {
55629
55636
  ExitPlanMode_default2 = {
55630
55637
  type: "object",
55631
55638
  properties: {},
@@ -56576,6 +56583,7 @@ var init_toolDefinitions = __esm(async () => {
56576
56583
  init_BashOutput2();
56577
56584
  init_Edit2();
56578
56585
  init_EnterPlanMode2();
56586
+ init_ExitPlanMode2();
56579
56587
  init_Glob2();
56580
56588
  init_GlobGemini2();
56581
56589
  init_Grep2();
@@ -56600,7 +56608,7 @@ var init_toolDefinitions = __esm(async () => {
56600
56608
  init_BashOutput3();
56601
56609
  init_Edit3();
56602
56610
  init_EnterPlanMode3();
56603
- init_ExitPlanMode2();
56611
+ init_ExitPlanMode3();
56604
56612
  init_Glob3();
56605
56613
  init_GlobGemini3();
56606
56614
  init_Grep3();
@@ -59127,25 +59135,32 @@ var init_filter = __esm(() => {
59127
59135
  var exports_manager2 = {};
59128
59136
  __export(exports_manager2, {
59129
59137
  waitForToolsetReady: () => waitForToolsetReady,
59138
+ setExternalToolExecutor: () => setExternalToolExecutor,
59130
59139
  savePermissionRule: () => savePermissionRule2,
59131
59140
  requiresApproval: () => requiresApproval,
59141
+ registerExternalTools: () => registerExternalTools,
59132
59142
  loadTools: () => loadTools,
59133
59143
  loadSpecificTools: () => loadSpecificTools,
59134
59144
  isToolsetSwitchInProgress: () => isToolsetSwitchInProgress,
59135
59145
  isOpenAIModel: () => isOpenAIModel,
59136
59146
  isGeminiModel: () => isGeminiModel,
59147
+ isExternalTool: () => isExternalTool,
59137
59148
  getToolSchemas: () => getToolSchemas,
59138
59149
  getToolSchema: () => getToolSchema,
59139
59150
  getToolPermissions: () => getToolPermissions,
59140
59151
  getToolNames: () => getToolNames,
59141
59152
  getServerToolName: () => getServerToolName,
59142
59153
  getInternalToolName: () => getInternalToolName,
59154
+ getExternalToolsAsClientTools: () => getExternalToolsAsClientTools,
59155
+ getExternalToolDefinition: () => getExternalToolDefinition,
59143
59156
  getClientToolsFromRegistry: () => getClientToolsFromRegistry,
59144
59157
  getAllLettaToolNames: () => getAllLettaToolNames,
59145
59158
  executeTool: () => executeTool,
59159
+ executeExternalTool: () => executeExternalTool,
59146
59160
  clipToolReturn: () => clipToolReturn,
59147
59161
  clearToolsWithLock: () => clearToolsWithLock,
59148
59162
  clearTools: () => clearTools,
59163
+ clearExternalTools: () => clearExternalTools,
59149
59164
  checkToolPermission: () => checkToolPermission,
59150
59165
  analyzeToolApproval: () => analyzeToolApproval,
59151
59166
  TOOL_NAMES: () => TOOL_NAMES,
@@ -59219,8 +59234,65 @@ function resolveInternalToolName(name) {
59219
59234
  }
59220
59235
  return;
59221
59236
  }
59237
+ function getExternalToolsRegistry() {
59238
+ const global2 = globalThis;
59239
+ if (!global2[EXTERNAL_TOOLS_KEY]) {
59240
+ global2[EXTERNAL_TOOLS_KEY] = new Map;
59241
+ }
59242
+ return global2[EXTERNAL_TOOLS_KEY];
59243
+ }
59244
+ function registerExternalTools(tools) {
59245
+ const registry = getExternalToolsRegistry();
59246
+ for (const tool of tools) {
59247
+ registry.set(tool.name, tool);
59248
+ }
59249
+ }
59250
+ function setExternalToolExecutor(executor) {
59251
+ globalThis[EXTERNAL_EXECUTOR_KEY] = executor;
59252
+ }
59253
+ function clearExternalTools() {
59254
+ getExternalToolsRegistry().clear();
59255
+ delete globalThis[EXTERNAL_EXECUTOR_KEY];
59256
+ }
59257
+ function isExternalTool(name) {
59258
+ return getExternalToolsRegistry().has(name);
59259
+ }
59260
+ function getExternalToolDefinition(name) {
59261
+ return getExternalToolsRegistry().get(name);
59262
+ }
59263
+ function getExternalToolsAsClientTools() {
59264
+ return Array.from(getExternalToolsRegistry().values()).map((tool) => ({
59265
+ name: tool.name,
59266
+ description: tool.description,
59267
+ parameters: tool.parameters
59268
+ }));
59269
+ }
59270
+ async function executeExternalTool(toolCallId, toolName, input) {
59271
+ const executor = globalThis[EXTERNAL_EXECUTOR_KEY];
59272
+ if (!executor) {
59273
+ return {
59274
+ toolReturn: `External tool executor not set for tool: ${toolName}`,
59275
+ status: "error"
59276
+ };
59277
+ }
59278
+ try {
59279
+ const result = await executor(toolCallId, toolName, input);
59280
+ const textContent = result.content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join(`
59281
+ `);
59282
+ return {
59283
+ toolReturn: textContent || JSON.stringify(result.content),
59284
+ status: result.isError ? "error" : "success"
59285
+ };
59286
+ } catch (error) {
59287
+ const errorMessage = error instanceof Error ? error.message : String(error);
59288
+ return {
59289
+ toolReturn: `External tool execution error: ${errorMessage}`,
59290
+ status: "error"
59291
+ };
59292
+ }
59293
+ }
59222
59294
  function getClientToolsFromRegistry() {
59223
- return Array.from(toolRegistry.entries()).map(([name, tool]) => {
59295
+ const builtInTools = Array.from(toolRegistry.entries()).map(([name, tool]) => {
59224
59296
  const serverName = getServerToolName(name);
59225
59297
  return {
59226
59298
  name: serverName,
@@ -59228,6 +59300,8 @@ function getClientToolsFromRegistry() {
59228
59300
  parameters: tool.schema.input_schema
59229
59301
  };
59230
59302
  });
59303
+ const externalTools = getExternalToolsAsClientTools();
59304
+ return [...builtInTools, ...externalTools];
59231
59305
  }
59232
59306
  function getToolPermissions(toolName) {
59233
59307
  return TOOL_PERMISSIONS[toolName] || { requiresApproval: false };
@@ -59489,6 +59563,9 @@ ${files.join(`
59489
59563
  return JSON.stringify(result);
59490
59564
  }
59491
59565
  async function executeTool(name, args, options) {
59566
+ if (isExternalTool(name)) {
59567
+ return executeExternalTool(options?.toolCallId ?? `ext-${Date.now()}`, name, args);
59568
+ }
59492
59569
  const internalName = resolveInternalToolName(name);
59493
59570
  if (!internalName) {
59494
59571
  return {
@@ -59655,7 +59732,7 @@ function clearToolsWithLock() {
59655
59732
  releaseSwitchLock();
59656
59733
  }
59657
59734
  }
59658
- var TOOL_NAMES, STREAMING_SHELL_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, TOOL_PERMISSIONS, REGISTRY_KEY, SWITCH_LOCK_KEY, toolRegistry;
59735
+ var TOOL_NAMES, STREAMING_SHELL_TOOLS, TOOL_NAME_MAPPINGS, ANTHROPIC_DEFAULT_TOOLS, OPENAI_DEFAULT_TOOLS, GEMINI_DEFAULT_TOOLS, OPENAI_PASCAL_TOOLS, GEMINI_PASCAL_TOOLS, TOOL_PERMISSIONS, REGISTRY_KEY, SWITCH_LOCK_KEY, toolRegistry, EXTERNAL_TOOLS_KEY, EXTERNAL_EXECUTOR_KEY;
59659
59736
  var init_manager3 = __esm(async () => {
59660
59737
  init_model();
59661
59738
  init_subagents();
@@ -59817,6 +59894,8 @@ var init_manager3 = __esm(async () => {
59817
59894
  REGISTRY_KEY = Symbol.for("@letta/toolRegistry");
59818
59895
  SWITCH_LOCK_KEY = Symbol.for("@letta/toolSwitchLock");
59819
59896
  toolRegistry = getRegistry();
59897
+ EXTERNAL_TOOLS_KEY = Symbol.for("@letta/externalTools");
59898
+ EXTERNAL_EXECUTOR_KEY = Symbol.for("@letta/externalToolExecutor");
59820
59899
  });
59821
59900
 
59822
59901
  // src/agent/approval-execution.ts
@@ -62112,6 +62191,23 @@ function isConversationBusyError(detail) {
62112
62191
  return false;
62113
62192
  return detail.toLowerCase().includes(CONVERSATION_BUSY_DETAIL_FRAGMENT);
62114
62193
  }
62194
+ function classifyPreStreamConflict(detail) {
62195
+ if (isApprovalPendingError(detail))
62196
+ return "approval_pending";
62197
+ if (isConversationBusyError(detail))
62198
+ return "conversation_busy";
62199
+ return null;
62200
+ }
62201
+ function getPreStreamErrorAction(detail, conversationBusyRetries, maxConversationBusyRetries) {
62202
+ const kind = classifyPreStreamConflict(detail);
62203
+ if (kind === "approval_pending") {
62204
+ return "resolve_approval_pending";
62205
+ }
62206
+ if (kind === "conversation_busy" && conversationBusyRetries < maxConversationBusyRetries) {
62207
+ return "retry_conversation_busy";
62208
+ }
62209
+ return "rethrow";
62210
+ }
62115
62211
  async function fetchRunErrorDetail(runId) {
62116
62212
  if (!runId)
62117
62213
  return null;
@@ -62124,7 +62220,7 @@ async function fetchRunErrorDetail(runId) {
62124
62220
  return null;
62125
62221
  }
62126
62222
  }
62127
- var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "cannot send a new message", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed";
62223
+ var INVALID_TOOL_CALL_IDS_FRAGMENT = "invalid tool call ids", APPROVAL_PENDING_DETAIL_FRAGMENT = "waiting for approval", CONVERSATION_BUSY_DETAIL_FRAGMENT = "another request is currently being processed";
62128
62224
  var init_approval_recovery = __esm(async () => {
62129
62225
  await init_client2();
62130
62226
  });
@@ -62356,7 +62452,7 @@ function buildModelSettings(modelHandle, updateArgs) {
62356
62452
  } else {
62357
62453
  settings = {};
62358
62454
  }
62359
- if (typeof updateArgs?.max_output_tokens === "number") {
62455
+ if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
62360
62456
  settings.max_output_tokens = updateArgs.max_output_tokens;
62361
62457
  }
62362
62458
  return settings;
@@ -62369,7 +62465,10 @@ async function updateAgentLLMConfig(agentId, modelHandle, updateArgs) {
62369
62465
  await client.agents.update(agentId, {
62370
62466
  model: modelHandle,
62371
62467
  ...hasModelSettings && { model_settings: modelSettings },
62372
- ...contextWindow && { context_window_limit: contextWindow }
62468
+ ...contextWindow && { context_window_limit: contextWindow },
62469
+ ...typeof updateArgs?.max_output_tokens === "number" && {
62470
+ max_tokens: updateArgs.max_output_tokens
62471
+ }
62373
62472
  });
62374
62473
  const finalAgent = await client.agents.retrieve(agentId);
62375
62474
  return finalAgent.llm_config;
@@ -63249,6 +63348,181 @@ function findLastSafeSplitPoint(content) {
63249
63348
  }
63250
63349
  var MIN_SPLIT_LENGTH = 1500;
63251
63350
 
63351
+ // src/tools/interactivePolicy.ts
63352
+ function isInteractiveApprovalTool(toolName) {
63353
+ return INTERACTIVE_APPROVAL_TOOLS.has(toolName);
63354
+ }
63355
+ function isHeadlessAutoAllowTool(toolName) {
63356
+ return HEADLESS_AUTO_ALLOW_TOOLS.has(toolName);
63357
+ }
63358
+ var INTERACTIVE_APPROVAL_TOOLS, RUNTIME_USER_INPUT_TOOLS, HEADLESS_AUTO_ALLOW_TOOLS;
63359
+ var init_interactivePolicy = __esm(() => {
63360
+ INTERACTIVE_APPROVAL_TOOLS = new Set([
63361
+ "AskUserQuestion",
63362
+ "EnterPlanMode",
63363
+ "ExitPlanMode"
63364
+ ]);
63365
+ RUNTIME_USER_INPUT_TOOLS = new Set(["AskUserQuestion", "ExitPlanMode"]);
63366
+ HEADLESS_AUTO_ALLOW_TOOLS = new Set(["EnterPlanMode"]);
63367
+ });
63368
+
63369
+ // src/tools/toolset.ts
63370
+ var exports_toolset = {};
63371
+ __export(exports_toolset, {
63372
+ switchToolsetForModel: () => switchToolsetForModel,
63373
+ reattachMemoryTool: () => reattachMemoryTool,
63374
+ forceToolsetSwitch: () => forceToolsetSwitch,
63375
+ ensureCorrectMemoryTool: () => ensureCorrectMemoryTool,
63376
+ detachMemoryTools: () => detachMemoryTools,
63377
+ MEMORY_TOOL_NAMES: () => MEMORY_TOOL_NAMES
63378
+ });
63379
+ async function ensureCorrectMemoryTool(agentId, modelIdentifier, useMemoryPatch) {
63380
+ const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
63381
+ const client = await getClient2();
63382
+ const shouldUsePatch = useMemoryPatch !== undefined ? useMemoryPatch : isOpenAIModel(resolvedModel);
63383
+ try {
63384
+ const agentWithTools = await client.agents.retrieve(agentId, {
63385
+ include: ["agent.tools"]
63386
+ });
63387
+ const currentTools = agentWithTools.tools || [];
63388
+ const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
63389
+ const hasAnyMemoryTool = mapByName.has("memory") || mapByName.has("memory_apply_patch");
63390
+ if (!hasAnyMemoryTool) {
63391
+ return;
63392
+ }
63393
+ const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
63394
+ const otherMemoryTool = desiredMemoryTool === "memory" ? "memory_apply_patch" : "memory";
63395
+ let desiredId = mapByName.get(desiredMemoryTool);
63396
+ if (!desiredId) {
63397
+ const resp = await client.tools.list({ name: desiredMemoryTool });
63398
+ desiredId = resp.items[0]?.id;
63399
+ }
63400
+ if (!desiredId) {
63401
+ return;
63402
+ }
63403
+ const otherId = mapByName.get(otherMemoryTool);
63404
+ if (mapByName.has(desiredMemoryTool) && !otherId) {
63405
+ return;
63406
+ }
63407
+ const currentIds = currentTools.map((t) => t.id).filter((id) => typeof id === "string");
63408
+ const newIds = new Set(currentIds);
63409
+ if (otherId)
63410
+ newIds.delete(otherId);
63411
+ newIds.add(desiredId);
63412
+ const updatedRules = (agentWithTools.tool_rules || []).map((r) => r.tool_name === otherMemoryTool ? { ...r, tool_name: desiredMemoryTool } : r);
63413
+ await client.agents.update(agentId, {
63414
+ tool_ids: Array.from(newIds),
63415
+ tool_rules: updatedRules
63416
+ });
63417
+ } catch (err) {
63418
+ console.warn(`Warning: Failed to sync memory tool: ${err instanceof Error ? err.message : String(err)}`);
63419
+ }
63420
+ }
63421
+ async function detachMemoryTools(agentId) {
63422
+ const client = await getClient2();
63423
+ try {
63424
+ const agentWithTools = await client.agents.retrieve(agentId, {
63425
+ include: ["agent.tools"]
63426
+ });
63427
+ const currentTools = agentWithTools.tools || [];
63428
+ let detachedAny = false;
63429
+ for (const tool of currentTools) {
63430
+ if (tool.name && MEMORY_TOOL_NAMES.has(tool.name)) {
63431
+ if (tool.id) {
63432
+ await client.agents.tools.detach(tool.id, { agent_id: agentId });
63433
+ detachedAny = true;
63434
+ }
63435
+ }
63436
+ }
63437
+ return detachedAny;
63438
+ } catch (err) {
63439
+ console.warn(`Warning: Failed to detach memory tools: ${err instanceof Error ? err.message : String(err)}`);
63440
+ return false;
63441
+ }
63442
+ }
63443
+ async function reattachMemoryTool(agentId, modelIdentifier) {
63444
+ const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
63445
+ const client = await getClient2();
63446
+ const shouldUsePatch = isOpenAIModel(resolvedModel);
63447
+ try {
63448
+ const agentWithTools = await client.agents.retrieve(agentId, {
63449
+ include: ["agent.tools"]
63450
+ });
63451
+ const currentTools = agentWithTools.tools || [];
63452
+ const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
63453
+ const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
63454
+ if (mapByName.has(desiredMemoryTool)) {
63455
+ return;
63456
+ }
63457
+ const resp = await client.tools.list({ name: desiredMemoryTool });
63458
+ const toolId = resp.items[0]?.id;
63459
+ if (!toolId) {
63460
+ console.warn(`Memory tool "${desiredMemoryTool}" not found on server`);
63461
+ return;
63462
+ }
63463
+ await client.agents.tools.attach(toolId, { agent_id: agentId });
63464
+ } catch (err) {
63465
+ console.warn(`Warning: Failed to reattach memory tool: ${err instanceof Error ? err.message : String(err)}`);
63466
+ }
63467
+ }
63468
+ async function forceToolsetSwitch(toolsetName, agentId) {
63469
+ let modelForLoading;
63470
+ if (toolsetName === "none") {
63471
+ clearToolsWithLock();
63472
+ return;
63473
+ } else if (toolsetName === "codex") {
63474
+ await loadSpecificTools([...CODEX_TOOLS]);
63475
+ modelForLoading = "openai/gpt-4";
63476
+ } else if (toolsetName === "codex_snake") {
63477
+ await loadTools("openai/gpt-4");
63478
+ modelForLoading = "openai/gpt-4";
63479
+ } else if (toolsetName === "gemini") {
63480
+ await loadSpecificTools([...GEMINI_TOOLS]);
63481
+ modelForLoading = "google_ai/gemini-3-pro-preview";
63482
+ } else if (toolsetName === "gemini_snake") {
63483
+ await loadTools("google_ai/gemini-3-pro-preview");
63484
+ modelForLoading = "google_ai/gemini-3-pro-preview";
63485
+ } else {
63486
+ await loadTools("anthropic/claude-sonnet-4");
63487
+ modelForLoading = "anthropic/claude-sonnet-4";
63488
+ }
63489
+ const useMemoryPatch = toolsetName === "codex" || toolsetName === "codex_snake";
63490
+ await ensureCorrectMemoryTool(agentId, modelForLoading, useMemoryPatch);
63491
+ }
63492
+ async function switchToolsetForModel(modelIdentifier, agentId) {
63493
+ const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
63494
+ await loadTools(resolvedModel);
63495
+ const loadedAfterPrimary = getToolNames().length;
63496
+ if (loadedAfterPrimary === 0 && !toolFilter.isActive()) {
63497
+ await loadTools();
63498
+ if (getToolNames().length === 0) {
63499
+ throw new Error(`Failed to load any Letta tools for model "${resolvedModel}".`);
63500
+ }
63501
+ }
63502
+ await ensureCorrectMemoryTool(agentId, resolvedModel);
63503
+ const { isGeminiModel: isGeminiModel3 } = await init_manager3().then(() => exports_manager2);
63504
+ const toolsetName = isOpenAIModel(resolvedModel) ? "codex" : isGeminiModel3(resolvedModel) ? "gemini" : "default";
63505
+ return toolsetName;
63506
+ }
63507
+ var CODEX_TOOLS, GEMINI_TOOLS, MEMORY_TOOL_NAMES;
63508
+ var init_toolset = __esm(async () => {
63509
+ init_model();
63510
+ init_filter();
63511
+ await __promiseAll([
63512
+ init_client2(),
63513
+ init_manager3()
63514
+ ]);
63515
+ CODEX_TOOLS = OPENAI_PASCAL_TOOLS;
63516
+ GEMINI_TOOLS = GEMINI_PASCAL_TOOLS;
63517
+ MEMORY_TOOL_NAMES = new Set([
63518
+ "memory",
63519
+ "memory_apply_patch",
63520
+ "memory_insert",
63521
+ "memory_replace",
63522
+ "memory_rethink"
63523
+ ]);
63524
+ });
63525
+
63252
63526
  // src/cli/helpers/toolNameMapping.ts
63253
63527
  function getDisplayToolName(rawName) {
63254
63528
  if (rawName === "write")
@@ -63351,10 +63625,10 @@ function isPlanTool(rawName, displayName) {
63351
63625
  return rawName === "update_plan" || rawName === "UpdatePlan" || displayName === "Planning";
63352
63626
  }
63353
63627
  function alwaysRequiresUserInput(name) {
63354
- return name === "AskUserQuestion" || name === "EnterPlanMode" || name === "ExitPlanMode";
63628
+ return isInteractiveApprovalTool(name);
63355
63629
  }
63356
63630
  function isMemoryTool(name) {
63357
- return name === "memory" || name === "memory_apply_patch";
63631
+ return MEMORY_TOOL_NAMES.has(name);
63358
63632
  }
63359
63633
  function isFileEditTool(name) {
63360
63634
  return name === "edit" || name === "Edit" || name === "multi_edit" || name === "MultiEdit" || name === "Replace" || name === "replace";
@@ -63378,6 +63652,10 @@ function isSearchTool(name) {
63378
63652
  function isGlobTool(name) {
63379
63653
  return name === "glob" || name === "Glob" || name === "glob_gemini" || name === "GlobGemini";
63380
63654
  }
63655
+ var init_toolNameMapping = __esm(async () => {
63656
+ init_interactivePolicy();
63657
+ await init_toolset();
63658
+ });
63381
63659
 
63382
63660
  // src/cli/helpers/accumulator.ts
63383
63661
  function appendStreamingOutput(state, chunk, startTime, isStderr = false) {
@@ -63837,6 +64115,11 @@ function onChunk(b, chunk, ctx) {
63837
64115
  eventData: eventChunk.event_data || {},
63838
64116
  phase: "running"
63839
64117
  }));
64118
+ if (eventType === "compaction") {
64119
+ runPreCompactHooks(ctx?.lastContextTokens, undefined, b.agentId, undefined).catch((error) => {
64120
+ debugLog("hooks", "PreCompact hook error (accumulator)", error);
64121
+ });
64122
+ }
63840
64123
  break;
63841
64124
  }
63842
64125
  break;
@@ -63881,7 +64164,10 @@ var init_accumulator = __esm(async () => {
63881
64164
  init_constants();
63882
64165
  init_debug();
63883
64166
  init_backfill();
63884
- await init_hooks();
64167
+ await __promiseAll([
64168
+ init_hooks(),
64169
+ init_toolNameMapping()
64170
+ ]);
63885
64171
  CANCEL_REASON_TEXT = {
63886
64172
  user_interrupt: INTERRUPTED_BY_USER,
63887
64173
  stream_error: "Stream error",
@@ -64102,8 +64388,69 @@ function isCreditExhaustedError(e, reasons) {
64102
64388
  return false;
64103
64389
  return hasErrorReason(e, "not-enough-credits", reasons);
64104
64390
  }
64391
+ function findEncryptedContentDetail(e) {
64392
+ if (typeof e !== "object" || e === null)
64393
+ return;
64394
+ const obj = e;
64395
+ if (typeof obj.detail === "string" && obj.detail.includes("invalid_encrypted_content")) {
64396
+ return obj.detail;
64397
+ }
64398
+ if (obj.error && typeof obj.error === "object") {
64399
+ const errObj = obj.error;
64400
+ if (errObj.error && typeof errObj.error === "object") {
64401
+ const inner = errObj.error;
64402
+ if (typeof inner.detail === "string" && inner.detail.includes("invalid_encrypted_content")) {
64403
+ return inner.detail;
64404
+ }
64405
+ }
64406
+ if (typeof errObj.detail === "string" && errObj.detail.includes("invalid_encrypted_content")) {
64407
+ return errObj.detail;
64408
+ }
64409
+ }
64410
+ return;
64411
+ }
64412
+ function checkEncryptedContentError(e) {
64413
+ const detail = findEncryptedContentDetail(e);
64414
+ if (!detail) {
64415
+ try {
64416
+ const errorStr = typeof e === "string" ? e : JSON.stringify(e);
64417
+ if (!errorStr.includes("invalid_encrypted_content"))
64418
+ return;
64419
+ } catch {
64420
+ return;
64421
+ }
64422
+ return "OpenAI error: Encrypted content could not be verified — organization mismatch." + ENCRYPTED_CONTENT_HINT;
64423
+ }
64424
+ try {
64425
+ const jsonStart = detail.indexOf("{");
64426
+ if (jsonStart >= 0) {
64427
+ const parsed = JSON.parse(detail.slice(jsonStart));
64428
+ const innerError = parsed.error || parsed;
64429
+ if (innerError.code === "invalid_encrypted_content") {
64430
+ const msg = String(innerError.message || "Encrypted content verification failed.").replaceAll('"', "\\\"");
64431
+ return [
64432
+ "OpenAI error:",
64433
+ " {",
64434
+ ` type: "${innerError.type || "invalid_request_error"}",`,
64435
+ ` code: "${innerError.code}",`,
64436
+ ` message: "${msg}"`,
64437
+ " }",
64438
+ ENCRYPTED_CONTENT_HINT
64439
+ ].join(`
64440
+ `);
64441
+ }
64442
+ }
64443
+ } catch {}
64444
+ return "OpenAI error: Encrypted content could not be verified — organization mismatch." + ENCRYPTED_CONTENT_HINT;
64445
+ }
64446
+ function isEncryptedContentError(e) {
64447
+ return findEncryptedContentDetail(e) !== undefined;
64448
+ }
64105
64449
  function formatErrorDetails(e, agentId, conversationId) {
64106
64450
  let runId;
64451
+ const encryptedContentMsg = checkEncryptedContentError(e);
64452
+ if (encryptedContentMsg)
64453
+ return encryptedContentMsg;
64107
64454
  if (e instanceof APIError2) {
64108
64455
  const reasons = getErrorReasons(e);
64109
64456
  const rateLimitResetMs = getRateLimitResetMs(e);
@@ -64202,10 +64549,18 @@ function createAgentLink(runId, agentId, conversationId) {
64202
64549
  const url = `https://app.letta.com/agents/${agentId}${conversationId ? `?conversation=${conversationId}` : ""}`;
64203
64550
  return `View agent: \x1B]8;;${url}\x1B\\${agentId}\x1B]8;;\x1B\\ (run: ${runId})`;
64204
64551
  }
64205
- var LETTA_USAGE_URL = "https://app.letta.com/settings/organization/usage", LETTA_AGENTS_URL = "https://app.letta.com/projects/default-project/agents";
64552
+ var LETTA_USAGE_URL = "https://app.letta.com/settings/organization/usage", LETTA_AGENTS_URL = "https://app.letta.com/projects/default-project/agents", ENCRYPTED_CONTENT_HINT;
64206
64553
  var init_errorFormatter = __esm(() => {
64207
64554
  init_error();
64208
64555
  init_errorContext();
64556
+ ENCRYPTED_CONTENT_HINT = [
64557
+ "",
64558
+ "This occurs when the conversation contains messages with encrypted",
64559
+ "reasoning from a different OpenAI authentication scope (e.g. switching",
64560
+ "between ChatGPT OAuth and an OpenAI API key).",
64561
+ "Use /clear to start a new conversation."
64562
+ ].join(`
64563
+ `);
64209
64564
  });
64210
64565
 
64211
64566
  // src/cli/helpers/streamProcessor.ts
@@ -64478,155 +64833,6 @@ var init_stream = __esm(async () => {
64478
64833
  ]);
64479
64834
  });
64480
64835
 
64481
- // src/tools/toolset.ts
64482
- var exports_toolset = {};
64483
- __export(exports_toolset, {
64484
- switchToolsetForModel: () => switchToolsetForModel,
64485
- reattachMemoryTool: () => reattachMemoryTool,
64486
- forceToolsetSwitch: () => forceToolsetSwitch,
64487
- ensureCorrectMemoryTool: () => ensureCorrectMemoryTool,
64488
- detachMemoryTools: () => detachMemoryTools
64489
- });
64490
- async function ensureCorrectMemoryTool(agentId, modelIdentifier, useMemoryPatch) {
64491
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
64492
- const client = await getClient2();
64493
- const shouldUsePatch = useMemoryPatch !== undefined ? useMemoryPatch : isOpenAIModel(resolvedModel);
64494
- try {
64495
- const agentWithTools = await client.agents.retrieve(agentId, {
64496
- include: ["agent.tools"]
64497
- });
64498
- const currentTools = agentWithTools.tools || [];
64499
- const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
64500
- const hasAnyMemoryTool = mapByName.has("memory") || mapByName.has("memory_apply_patch");
64501
- if (!hasAnyMemoryTool) {
64502
- return;
64503
- }
64504
- const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
64505
- const otherMemoryTool = desiredMemoryTool === "memory" ? "memory_apply_patch" : "memory";
64506
- let desiredId = mapByName.get(desiredMemoryTool);
64507
- if (!desiredId) {
64508
- const resp = await client.tools.list({ name: desiredMemoryTool });
64509
- desiredId = resp.items[0]?.id;
64510
- }
64511
- if (!desiredId) {
64512
- return;
64513
- }
64514
- const otherId = mapByName.get(otherMemoryTool);
64515
- if (mapByName.has(desiredMemoryTool) && !otherId) {
64516
- return;
64517
- }
64518
- const currentIds = currentTools.map((t) => t.id).filter((id) => typeof id === "string");
64519
- const newIds = new Set(currentIds);
64520
- if (otherId)
64521
- newIds.delete(otherId);
64522
- newIds.add(desiredId);
64523
- const updatedRules = (agentWithTools.tool_rules || []).map((r) => r.tool_name === otherMemoryTool ? { ...r, tool_name: desiredMemoryTool } : r);
64524
- await client.agents.update(agentId, {
64525
- tool_ids: Array.from(newIds),
64526
- tool_rules: updatedRules
64527
- });
64528
- } catch (err) {
64529
- console.warn(`Warning: Failed to sync memory tool: ${err instanceof Error ? err.message : String(err)}`);
64530
- }
64531
- }
64532
- async function detachMemoryTools(agentId) {
64533
- const client = await getClient2();
64534
- try {
64535
- const agentWithTools = await client.agents.retrieve(agentId, {
64536
- include: ["agent.tools"]
64537
- });
64538
- const currentTools = agentWithTools.tools || [];
64539
- let detachedAny = false;
64540
- for (const tool of currentTools) {
64541
- if (tool.name === "memory" || tool.name === "memory_apply_patch") {
64542
- if (tool.id) {
64543
- await client.agents.tools.detach(tool.id, { agent_id: agentId });
64544
- detachedAny = true;
64545
- }
64546
- }
64547
- }
64548
- return detachedAny;
64549
- } catch (err) {
64550
- console.warn(`Warning: Failed to detach memory tools: ${err instanceof Error ? err.message : String(err)}`);
64551
- return false;
64552
- }
64553
- }
64554
- async function reattachMemoryTool(agentId, modelIdentifier) {
64555
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
64556
- const client = await getClient2();
64557
- const shouldUsePatch = isOpenAIModel(resolvedModel);
64558
- try {
64559
- const agentWithTools = await client.agents.retrieve(agentId, {
64560
- include: ["agent.tools"]
64561
- });
64562
- const currentTools = agentWithTools.tools || [];
64563
- const mapByName = new Map(currentTools.map((t) => [t.name, t.id]));
64564
- const desiredMemoryTool = shouldUsePatch ? "memory_apply_patch" : "memory";
64565
- if (mapByName.has(desiredMemoryTool)) {
64566
- return;
64567
- }
64568
- const resp = await client.tools.list({ name: desiredMemoryTool });
64569
- const toolId = resp.items[0]?.id;
64570
- if (!toolId) {
64571
- console.warn(`Memory tool "${desiredMemoryTool}" not found on server`);
64572
- return;
64573
- }
64574
- await client.agents.tools.attach(toolId, { agent_id: agentId });
64575
- } catch (err) {
64576
- console.warn(`Warning: Failed to reattach memory tool: ${err instanceof Error ? err.message : String(err)}`);
64577
- }
64578
- }
64579
- async function forceToolsetSwitch(toolsetName, agentId) {
64580
- let modelForLoading;
64581
- if (toolsetName === "none") {
64582
- clearToolsWithLock();
64583
- return;
64584
- } else if (toolsetName === "codex") {
64585
- await loadSpecificTools([...CODEX_TOOLS]);
64586
- modelForLoading = "openai/gpt-4";
64587
- } else if (toolsetName === "codex_snake") {
64588
- await loadTools("openai/gpt-4");
64589
- modelForLoading = "openai/gpt-4";
64590
- } else if (toolsetName === "gemini") {
64591
- await loadSpecificTools([...GEMINI_TOOLS]);
64592
- modelForLoading = "google_ai/gemini-3-pro-preview";
64593
- } else if (toolsetName === "gemini_snake") {
64594
- await loadTools("google_ai/gemini-3-pro-preview");
64595
- modelForLoading = "google_ai/gemini-3-pro-preview";
64596
- } else {
64597
- await loadTools("anthropic/claude-sonnet-4");
64598
- modelForLoading = "anthropic/claude-sonnet-4";
64599
- }
64600
- const useMemoryPatch = toolsetName === "codex" || toolsetName === "codex_snake";
64601
- await ensureCorrectMemoryTool(agentId, modelForLoading, useMemoryPatch);
64602
- }
64603
- async function switchToolsetForModel(modelIdentifier, agentId) {
64604
- const resolvedModel = resolveModel(modelIdentifier) ?? modelIdentifier;
64605
- await loadTools(resolvedModel);
64606
- const loadedAfterPrimary = getToolNames().length;
64607
- if (loadedAfterPrimary === 0 && !toolFilter.isActive()) {
64608
- await loadTools();
64609
- if (getToolNames().length === 0) {
64610
- throw new Error(`Failed to load any Letta tools for model "${resolvedModel}".`);
64611
- }
64612
- }
64613
- await ensureCorrectMemoryTool(agentId, resolvedModel);
64614
- const { isGeminiModel: isGeminiModel3 } = await init_manager3().then(() => exports_manager2);
64615
- const toolsetName = isOpenAIModel(resolvedModel) ? "codex" : isGeminiModel3(resolvedModel) ? "gemini" : "default";
64616
- return toolsetName;
64617
- }
64618
- var CODEX_TOOLS, GEMINI_TOOLS;
64619
- var init_toolset = __esm(async () => {
64620
- init_model();
64621
- init_filter();
64622
- await __promiseAll([
64623
- init_client2(),
64624
- init_manager3()
64625
- ]);
64626
- CODEX_TOOLS = OPENAI_PASCAL_TOOLS;
64627
- GEMINI_TOOLS = GEMINI_PASCAL_TOOLS;
64628
- });
64629
-
64630
64836
  // src/agent/github-utils.ts
64631
64837
  var exports_github_utils = {};
64632
64838
  __export(exports_github_utils, {
@@ -64662,6 +64868,7 @@ function parseDirNames(entries) {
64662
64868
  // src/agent/import.ts
64663
64869
  var exports_import = {};
64664
64870
  __export(exports_import, {
64871
+ importAgentFromRegistry: () => importAgentFromRegistry,
64665
64872
  importAgentFromFile: () => importAgentFromFile,
64666
64873
  extractSkillsFromAf: () => extractSkillsFromAf
64667
64874
  });
@@ -64769,6 +64976,45 @@ async function downloadGitHubDirectory(entries, destDir, owner, repo, branch, ba
64769
64976
  }
64770
64977
  }
64771
64978
  }
64979
+ function parseRegistryHandle(handle) {
64980
+ const normalized = handle.startsWith("@") ? handle.slice(1) : handle;
64981
+ const parts = normalized.split("/");
64982
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
64983
+ throw new Error(`Invalid import handle "${handle}". Use format: @author/agentname`);
64984
+ }
64985
+ return { author: parts[0], name: parts[1] };
64986
+ }
64987
+ async function importAgentFromRegistry(options) {
64988
+ const { tmpdir: tmpdir2 } = await import("node:os");
64989
+ const { join: join20 } = await import("node:path");
64990
+ const { writeFile: writeFile5, unlink: unlink2 } = await import("node:fs/promises");
64991
+ const { author, name } = parseRegistryHandle(options.handle);
64992
+ const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/refs/heads/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}/${name}.af`;
64993
+ const response = await fetch(rawUrl);
64994
+ if (!response.ok) {
64995
+ if (response.status === 404) {
64996
+ throw new Error(`Agent @${author}/${name} not found in registry. Check that the agent exists at https://github.com/${AGENT_REGISTRY_OWNER}/${AGENT_REGISTRY_REPO}/tree/${AGENT_REGISTRY_BRANCH}/agents/@${author}/${name}`);
64997
+ }
64998
+ throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
64999
+ }
65000
+ const afContent = await response.text();
65001
+ const tempPath = join20(tmpdir2(), `letta-import-${author}-${name}-${Date.now()}.af`);
65002
+ await writeFile5(tempPath, afContent, "utf-8");
65003
+ try {
65004
+ const result = await importAgentFromFile({
65005
+ filePath: tempPath,
65006
+ modelOverride: options.modelOverride,
65007
+ stripMessages: options.stripMessages ?? true,
65008
+ stripSkills: options.stripSkills ?? false
65009
+ });
65010
+ return result;
65011
+ } finally {
65012
+ try {
65013
+ await unlink2(tempPath);
65014
+ } catch {}
65015
+ }
65016
+ }
65017
+ var AGENT_REGISTRY_OWNER = "letta-ai", AGENT_REGISTRY_REPO = "agent-file", AGENT_REGISTRY_BRANCH = "main";
64772
65018
  var init_import = __esm(async () => {
64773
65019
  init_model();
64774
65020
  await __promiseAll([
@@ -65220,6 +65466,7 @@ In headless mode, use:
65220
65466
  process.exit(1);
65221
65467
  }
65222
65468
  }
65469
+ let isRegistryImport = false;
65223
65470
  if (fromAfFile) {
65224
65471
  if (specifiedAgentId) {
65225
65472
  console.error("Error: --from-af cannot be used with --agent");
@@ -65233,6 +65480,15 @@ In headless mode, use:
65233
65480
  console.error("Error: --from-af cannot be used with --new");
65234
65481
  process.exit(1);
65235
65482
  }
65483
+ if (fromAfFile.startsWith("@")) {
65484
+ isRegistryImport = true;
65485
+ const normalized = fromAfFile.slice(1);
65486
+ const parts = normalized.split("/");
65487
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
65488
+ console.error(`Error: Invalid registry handle "${fromAfFile}". Use format: @author/agentname`);
65489
+ process.exit(1);
65490
+ }
65491
+ }
65236
65492
  }
65237
65493
  if (initBlocksRaw && !forceNew) {
65238
65494
  console.error("Error: --init-blocks can only be used together with --new to control initial memory blocks.");
@@ -65315,13 +65571,24 @@ In headless mode, use:
65315
65571
  }
65316
65572
  }
65317
65573
  if (!agent && fromAfFile) {
65318
- const { importAgentFromFile: importAgentFromFile2 } = await init_import().then(() => exports_import);
65319
- const result = await importAgentFromFile2({
65320
- filePath: fromAfFile,
65321
- modelOverride: model,
65322
- stripMessages: true,
65323
- stripSkills: false
65324
- });
65574
+ let result;
65575
+ if (isRegistryImport) {
65576
+ const { importAgentFromRegistry: importAgentFromRegistry2 } = await init_import().then(() => exports_import);
65577
+ result = await importAgentFromRegistry2({
65578
+ handle: fromAfFile,
65579
+ modelOverride: model,
65580
+ stripMessages: true,
65581
+ stripSkills: false
65582
+ });
65583
+ } else {
65584
+ const { importAgentFromFile: importAgentFromFile2 } = await init_import().then(() => exports_import);
65585
+ result = await importAgentFromFile2({
65586
+ filePath: fromAfFile,
65587
+ modelOverride: model,
65588
+ stripMessages: true,
65589
+ stripSkills: false
65590
+ });
65591
+ }
65325
65592
  agent = result.agent;
65326
65593
  isNewlyCreatedAgent = true;
65327
65594
  if (result.skills && result.skills.length > 0) {
@@ -65524,8 +65791,11 @@ In headless mode, use:
65524
65791
  console.error(`Error: Invalid input format "${inputFormat}". Valid formats: stream-json`);
65525
65792
  process.exit(1);
65526
65793
  }
65794
+ const { getClientToolsFromRegistry: getClientToolsFromRegistry2 } = await init_manager3().then(() => exports_manager2);
65795
+ const loadedToolNames = getClientToolsFromRegistry2().map((t) => t.name);
65796
+ const availableTools = loadedToolNames.length > 0 ? loadedToolNames : agent.tools?.map((t) => t.name).filter((n) => !!n) || [];
65527
65797
  if (isBidirectionalMode) {
65528
- await runBidirectionalMode(agent, conversationId, client, outputFormat, includePartialMessages);
65798
+ await runBidirectionalMode(agent, conversationId, client, outputFormat, includePartialMessages, availableTools);
65529
65799
  return;
65530
65800
  }
65531
65801
  const buffers = createBuffers(agent.id);
@@ -65539,7 +65809,7 @@ In headless mode, use:
65539
65809
  agent_id: agent.id,
65540
65810
  conversation_id: conversationId,
65541
65811
  model: agent.llm_config?.model ?? "",
65542
- tools: agent.tools?.map((t) => t.name).filter((n) => !!n) || [],
65812
+ tools: availableTools,
65543
65813
  cwd: process.cwd(),
65544
65814
  mcp_servers: [],
65545
65815
  permission_mode: "",
@@ -65565,6 +65835,7 @@ In headless mode, use:
65565
65835
  if (pendingApprovals.length === 0)
65566
65836
  break;
65567
65837
  const { autoAllowed, autoDenied } = await classifyApprovals(pendingApprovals, {
65838
+ alwaysRequiresUserInput: isInteractiveApprovalTool,
65568
65839
  treatAskAsDeny: true,
65569
65840
  denyReasonForAsk: "Tool requires approval (headless mode)",
65570
65841
  requireArgsForAutoApprove: true,
@@ -65744,7 +66015,24 @@ ${SYSTEM_REMINDER_CLOSE}
65744
66015
  if (!errorDetail && preStreamError instanceof Error) {
65745
66016
  errorDetail = preStreamError.message;
65746
66017
  }
65747
- if (isConversationBusyError(errorDetail) && conversationBusyRetries < CONVERSATION_BUSY_MAX_RETRIES) {
66018
+ const preStreamAction = getPreStreamErrorAction(errorDetail, conversationBusyRetries, CONVERSATION_BUSY_MAX_RETRIES);
66019
+ if (preStreamAction === "resolve_approval_pending") {
66020
+ if (outputFormat === "stream-json") {
66021
+ const recoveryMsg = {
66022
+ type: "recovery",
66023
+ recovery_type: "approval_pending",
66024
+ message: "Detected pending approval conflict on send; resolving before retry",
66025
+ session_id: sessionId,
66026
+ uuid: `recovery-pre-stream-${crypto.randomUUID()}`
66027
+ };
66028
+ console.log(JSON.stringify(recoveryMsg));
66029
+ } else {
66030
+ console.error("Pending approval detected, resolving before retry...");
66031
+ }
66032
+ await resolveAllPendingApprovals();
66033
+ continue;
66034
+ }
66035
+ if (preStreamAction === "retry_conversation_busy") {
65748
66036
  conversationBusyRetries += 1;
65749
66037
  if (outputFormat === "stream-json") {
65750
66038
  const retryMsg = {
@@ -65817,6 +66105,7 @@ ${SYSTEM_REMINDER_CLOSE}
65817
66105
  }
65818
66106
  if (updatedApproval && !autoApprovalEmitted.has(updatedApproval.toolCallId)) {
65819
66107
  const { autoAllowed } = await classifyApprovals([updatedApproval], {
66108
+ alwaysRequiresUserInput: isInteractiveApprovalTool,
65820
66109
  requireArgsForAutoApprove: true,
65821
66110
  missingNameReason: "Tool call incomplete - missing name"
65822
66111
  });
@@ -65895,9 +66184,8 @@ ${SYSTEM_REMINDER_CLOSE}
65895
66184
  console.error("Unexpected empty approvals array");
65896
66185
  process.exit(1);
65897
66186
  }
65898
- const { autoAllowed, autoDenied } = await classifyApprovals(approvals, {
65899
- treatAskAsDeny: true,
65900
- denyReasonForAsk: "Tool requires approval (headless mode)",
66187
+ const { autoAllowed, autoDenied, needsUserInput } = await classifyApprovals(approvals, {
66188
+ alwaysRequiresUserInput: isInteractiveApprovalTool,
65901
66189
  requireArgsForAutoApprove: true,
65902
66190
  missingNameReason: "Tool call incomplete - missing name"
65903
66191
  });
@@ -65906,6 +66194,19 @@ ${SYSTEM_REMINDER_CLOSE}
65906
66194
  type: "approve",
65907
66195
  approval: ac.approval
65908
66196
  })),
66197
+ ...needsUserInput.map((ac) => {
66198
+ if (isHeadlessAutoAllowTool(ac.approval.toolName)) {
66199
+ return {
66200
+ type: "approve",
66201
+ approval: ac.approval
66202
+ };
66203
+ }
66204
+ return {
66205
+ type: "deny",
66206
+ approval: ac.approval,
66207
+ reason: "Tool requires approval (headless mode)"
66208
+ };
66209
+ }),
65909
66210
  ...autoDenied.map((ac) => {
65910
66211
  const fallback = "matchedRule" in ac.permission && ac.permission.matchedRule ? `Permission denied: ${ac.permission.matchedRule}` : ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : "Permission denied: Unknown reason";
65911
66212
  return {
@@ -66168,7 +66469,7 @@ ${SYSTEM_REMINDER_CLOSE}
66168
66469
  markMilestone("HEADLESS_COMPLETE");
66169
66470
  reportAllMilestones();
66170
66471
  }
66171
- async function runBidirectionalMode(agent, conversationId, _client, _outputFormat, includePartialMessages) {
66472
+ async function runBidirectionalMode(agent, conversationId, client, _outputFormat, includePartialMessages, availableTools) {
66172
66473
  const sessionId = agent.id;
66173
66474
  const readline = await import("node:readline");
66174
66475
  const initEvent = {
@@ -66178,12 +66479,74 @@ async function runBidirectionalMode(agent, conversationId, _client, _outputForma
66178
66479
  agent_id: agent.id,
66179
66480
  conversation_id: conversationId,
66180
66481
  model: agent.llm_config?.model,
66181
- tools: agent.tools?.map((t) => t.name) || [],
66482
+ tools: availableTools,
66182
66483
  cwd: process.cwd(),
66183
66484
  uuid: `init-${agent.id}`
66184
66485
  };
66185
66486
  console.log(JSON.stringify(initEvent));
66186
66487
  let currentAbortController = null;
66488
+ const resolveAllPendingApprovals = async () => {
66489
+ const { getResumeData: getResumeData3 } = await Promise.resolve().then(() => (init_check_approval(), exports_check_approval));
66490
+ while (true) {
66491
+ const freshAgent = await client.agents.retrieve(agent.id);
66492
+ let resume;
66493
+ try {
66494
+ resume = await getResumeData3(client, freshAgent, conversationId);
66495
+ } catch (error) {
66496
+ if (error instanceof APIError2 && (error.status === 404 || error.status === 422)) {
66497
+ break;
66498
+ }
66499
+ throw error;
66500
+ }
66501
+ const pendingApprovals = resume.pendingApprovals || [];
66502
+ if (pendingApprovals.length === 0)
66503
+ break;
66504
+ const { autoAllowed, autoDenied } = await classifyApprovals(pendingApprovals, {
66505
+ treatAskAsDeny: true,
66506
+ denyReasonForAsk: "Tool requires approval (headless mode)",
66507
+ requireArgsForAutoApprove: true,
66508
+ missingNameReason: "Tool call incomplete - missing name"
66509
+ });
66510
+ const decisions = [
66511
+ ...autoAllowed.map((ac) => ({
66512
+ type: "approve",
66513
+ approval: ac.approval,
66514
+ reason: ac.permission.reason || "Allowed by permission rule",
66515
+ matchedRule: "matchedRule" in ac.permission && ac.permission.matchedRule ? ac.permission.matchedRule : "auto-approved"
66516
+ })),
66517
+ ...autoDenied.map((ac) => {
66518
+ const fallback = "matchedRule" in ac.permission && ac.permission.matchedRule ? `Permission denied: ${ac.permission.matchedRule}` : ac.permission.reason ? `Permission denied: ${ac.permission.reason}` : "Permission denied: Unknown reason";
66519
+ return {
66520
+ type: "deny",
66521
+ approval: ac.approval,
66522
+ reason: ac.denyReason ?? fallback
66523
+ };
66524
+ })
66525
+ ];
66526
+ const { executeApprovalBatch: executeApprovalBatch2 } = await init_approval_execution().then(() => exports_approval_execution);
66527
+ const executedResults = await executeApprovalBatch2(decisions);
66528
+ const approvalInput = {
66529
+ type: "approval",
66530
+ approvals: executedResults
66531
+ };
66532
+ const approvalMessages = [approvalInput];
66533
+ {
66534
+ const { consumeQueuedSkillContent: consumeQueuedSkillContent2 } = await Promise.resolve().then(() => (init_skillContentRegistry(), exports_skillContentRegistry));
66535
+ const skillContents = consumeQueuedSkillContent2();
66536
+ if (skillContents.length > 0) {
66537
+ approvalMessages.push({
66538
+ role: "user",
66539
+ content: skillContents.map((sc) => ({
66540
+ type: "text",
66541
+ text: sc.content
66542
+ }))
66543
+ });
66544
+ }
66545
+ }
66546
+ const approvalStream = await sendMessageStream(conversationId, approvalMessages, { agentId: agent.id });
66547
+ await drainStreamWithResume(approvalStream, createBuffers(agent.id), () => {});
66548
+ }
66549
+ };
66187
66550
  const rl = readline.createInterface({
66188
66551
  input: process.stdin,
66189
66552
  terminal: false
@@ -66303,7 +66666,7 @@ async function runBidirectionalMode(agent, conversationId, _client, _outputForma
66303
66666
  response: {
66304
66667
  agent_id: agent.id,
66305
66668
  model: agent.llm_config?.model,
66306
- tools: agent.tools?.map((t) => t.name) || []
66669
+ tools: availableTools
66307
66670
  }
66308
66671
  },
66309
66672
  session_id: sessionId,
@@ -66325,6 +66688,54 @@ async function runBidirectionalMode(agent, conversationId, _client, _outputForma
66325
66688
  uuid: crypto.randomUUID()
66326
66689
  };
66327
66690
  console.log(JSON.stringify(interruptResponse));
66691
+ } else if (subtype === "register_external_tools") {
66692
+ const toolsRequest = message.request;
66693
+ const tools = toolsRequest.tools ?? [];
66694
+ registerExternalTools(tools);
66695
+ setExternalToolExecutor(async (toolCallId, toolName, input) => {
66696
+ const execRequest = {
66697
+ type: "control_request",
66698
+ request_id: `ext-${toolCallId}`,
66699
+ request: {
66700
+ subtype: "execute_external_tool",
66701
+ tool_call_id: toolCallId,
66702
+ tool_name: toolName,
66703
+ input
66704
+ }
66705
+ };
66706
+ console.log(JSON.stringify(execRequest));
66707
+ while (true) {
66708
+ const line2 = await getNextLine();
66709
+ if (line2 === null) {
66710
+ return {
66711
+ content: [{ type: "text", text: "stdin closed" }],
66712
+ isError: true
66713
+ };
66714
+ }
66715
+ if (!line2.trim())
66716
+ continue;
66717
+ try {
66718
+ const msg = JSON.parse(line2);
66719
+ if (msg.type === "control_response" && msg.response?.subtype === "external_tool_result" && msg.response?.tool_call_id === toolCallId) {
66720
+ return {
66721
+ content: msg.response.content ?? [{ type: "text", text: "" }],
66722
+ isError: msg.response.is_error ?? false
66723
+ };
66724
+ }
66725
+ } catch {}
66726
+ }
66727
+ });
66728
+ const registerResponse = {
66729
+ type: "control_response",
66730
+ response: {
66731
+ subtype: "success",
66732
+ request_id: requestId ?? "",
66733
+ response: { registered: tools.length }
66734
+ },
66735
+ session_id: sessionId,
66736
+ uuid: crypto.randomUUID()
66737
+ };
66738
+ console.log(JSON.stringify(registerResponse));
66328
66739
  } else {
66329
66740
  const errorResponse = {
66330
66741
  type: "control_response",
@@ -66393,9 +66804,40 @@ ${enrichedContent}`;
66393
66804
  ];
66394
66805
  }
66395
66806
  }
66396
- const stream2 = await sendMessageStream(conversationId, currentInput, {
66397
- agentId: agent.id
66398
- });
66807
+ let stream2;
66808
+ try {
66809
+ stream2 = await sendMessageStream(conversationId, currentInput, {
66810
+ agentId: agent.id
66811
+ });
66812
+ } catch (preStreamError) {
66813
+ let errorDetail = "";
66814
+ if (preStreamError instanceof APIError2 && preStreamError.error && typeof preStreamError.error === "object") {
66815
+ const errObj = preStreamError.error;
66816
+ if (errObj.error && typeof errObj.error === "object" && "detail" in errObj.error) {
66817
+ const nested = errObj.error;
66818
+ errorDetail = typeof nested.detail === "string" ? nested.detail : "";
66819
+ }
66820
+ if (!errorDetail && typeof errObj.detail === "string") {
66821
+ errorDetail = errObj.detail;
66822
+ }
66823
+ }
66824
+ if (!errorDetail && preStreamError instanceof Error) {
66825
+ errorDetail = preStreamError.message;
66826
+ }
66827
+ if (isApprovalPendingError(errorDetail)) {
66828
+ const recoveryMsg = {
66829
+ type: "recovery",
66830
+ recovery_type: "approval_pending",
66831
+ message: "Detected pending approval conflict on send; resolving before retry",
66832
+ session_id: sessionId,
66833
+ uuid: `recovery-bidir-${crypto.randomUUID()}`
66834
+ };
66835
+ console.log(JSON.stringify(recoveryMsg));
66836
+ await resolveAllPendingApprovals();
66837
+ continue;
66838
+ }
66839
+ throw preStreamError;
66840
+ }
66399
66841
  const streamJsonHook = ({
66400
66842
  chunk,
66401
66843
  shouldOutput,
@@ -66463,6 +66905,7 @@ ${enrichedContent}`;
66463
66905
  break;
66464
66906
  }
66465
66907
  const { autoAllowed, autoDenied, needsUserInput } = await classifyApprovals(approvals, {
66908
+ alwaysRequiresUserInput: isInteractiveApprovalTool,
66466
66909
  requireArgsForAutoApprove: true,
66467
66910
  missingNameReason: "Tool call incomplete - missing name"
66468
66911
  });
@@ -66620,6 +67063,7 @@ var init_headless = __esm(async () => {
66620
67063
  init_model();
66621
67064
  init_errorFormatter();
66622
67065
  init_constants();
67066
+ init_interactivePolicy();
66623
67067
  init_timing();
66624
67068
  await __promiseAll([
66625
67069
  init_approval_recovery(),
@@ -66630,7 +67074,8 @@ var init_headless = __esm(async () => {
66630
67074
  init_accumulator(),
66631
67075
  init_approvalClassification(),
66632
67076
  init_stream(),
66633
- init_settings_manager()
67077
+ init_settings_manager(),
67078
+ init_manager3()
66634
67079
  ]);
66635
67080
  });
66636
67081
 
@@ -68532,7 +68977,9 @@ function formatArgsDisplay(argsJson, toolName) {
68532
68977
  return { display, parsed };
68533
68978
  }
68534
68979
  var isRecord3 = (v) => typeof v === "object" && v !== null;
68535
- var init_formatArgsDisplay = () => {};
68980
+ var init_formatArgsDisplay = __esm(async () => {
68981
+ await init_toolNameMapping();
68982
+ });
68536
68983
 
68537
68984
  // node_modules/diff/libesm/diff/base.js
68538
68985
  class Diff {
@@ -70410,11 +70857,11 @@ function getFileEditHeader(toolName, toolArgs) {
70410
70857
  }
70411
70858
  var import_react33, jsx_dev_runtime14, SOLID_LINE5 = "─", DOTTED_LINE2 = "╌", ApprovalPreview;
70412
70859
  var init_ApprovalPreview = __esm(async () => {
70413
- init_formatArgsDisplay();
70414
70860
  init_useTerminalWidth();
70415
70861
  init_colors();
70416
70862
  await __promiseAll([
70417
70863
  init_build2(),
70864
+ init_formatArgsDisplay(),
70418
70865
  init_AdvancedDiffRenderer(),
70419
70866
  init_BashPreview(),
70420
70867
  init_PlanPreview(),
@@ -71123,13 +71570,13 @@ function getDiffKind(toolName) {
71123
71570
  var import_react38, jsx_dev_runtime17, SOLID_LINE8 = "─", DOTTED_LINE3 = "╌", InlineFileEditApproval;
71124
71571
  var init_InlineFileEditApproval = __esm(async () => {
71125
71572
  init_diff2();
71126
- init_formatArgsDisplay();
71127
71573
  init_useProgressIndicator();
71128
71574
  init_useTerminalWidth();
71129
71575
  init_useTextInputCursor();
71130
71576
  init_colors();
71131
71577
  await __promiseAll([
71132
71578
  init_build2(),
71579
+ init_formatArgsDisplay(),
71133
71580
  init_AdvancedDiffRenderer(),
71134
71581
  init_Text2()
71135
71582
  ]);
@@ -72704,6 +73151,7 @@ function getQuestions(approval) {
72704
73151
  var import_react43, jsx_dev_runtime22, ApprovalSwitch;
72705
73152
  var init_ApprovalSwitch = __esm(async () => {
72706
73153
  await __promiseAll([
73154
+ init_toolNameMapping(),
72707
73155
  init_InlineBashApproval(),
72708
73156
  init_InlineEnterPlanModeApproval(),
72709
73157
  init_InlineFileEditApproval(),
@@ -80690,9 +81138,15 @@ function SlashCommandAutocomplete({
80690
81138
  manageActiveState: false
80691
81139
  });
80692
81140
  import_react64.useLayoutEffect(() => {
80693
- const isActive = matches.length > 0 || showNoMatches;
81141
+ const queryLength = queryInfo?.query.length ?? 0;
81142
+ const isActive = !hideAutocomplete && (matches.length > 0 || queryLength > 0);
80694
81143
  onActiveChange?.(isActive);
80695
- }, [matches.length, showNoMatches, onActiveChange]);
81144
+ }, [
81145
+ hideAutocomplete,
81146
+ matches.length,
81147
+ onActiveChange,
81148
+ queryInfo?.query.length
81149
+ ]);
80696
81150
  if (!currentInput.startsWith("/")) {
80697
81151
  return null;
80698
81152
  }
@@ -88777,13 +89231,14 @@ function isShellTool2(name) {
88777
89231
  var import_react85, jsx_dev_runtime65, ToolCallMessage;
88778
89232
  var init_ToolCallMessageRich = __esm(async () => {
88779
89233
  init_constants();
88780
- init_formatArgsDisplay();
88781
89234
  init_subagentState();
88782
89235
  init_useTerminalWidth();
88783
89236
  init_colors();
88784
89237
  await __promiseAll([
88785
89238
  init_build2(),
88786
89239
  init_manager3(),
89240
+ init_formatArgsDisplay(),
89241
+ init_toolNameMapping(),
88787
89242
  init_Text2(),
88788
89243
  init_AdvancedDiffRenderer(),
88789
89244
  init_BlinkDot(),
@@ -90612,8 +91067,9 @@ function createSubagentGroupItem(taskToolCalls) {
90612
91067
  agents
90613
91068
  };
90614
91069
  }
90615
- var init_subagentAggregation = __esm(() => {
91070
+ var init_subagentAggregation = __esm(async () => {
90616
91071
  init_subagentState();
91072
+ await init_toolNameMapping();
90617
91073
  });
90618
91074
 
90619
91075
  // src/cli/helpers/subagentTurnStart.ts
@@ -93322,7 +93778,7 @@ function App2({
93322
93778
  continue;
93323
93779
  if (!line.toolCallId || !line.name)
93324
93780
  continue;
93325
- if (line.name !== "memory" && line.name !== "memory_apply_patch")
93781
+ if (!isMemoryTool(line.name))
93326
93782
  continue;
93327
93783
  if (memorySyncProcessedToolCallsRef.current.has(line.toolCallId))
93328
93784
  continue;
@@ -94393,7 +94849,9 @@ ${feedback}
94393
94849
  };
94394
94850
  const errorDetails = formatErrorDetails(errorObject, agentIdRef.current);
94395
94851
  appendError(errorDetails, true);
94396
- appendError(getErrorHintForStopReason(stopReasonToHandle, currentModelId), true);
94852
+ if (!isEncryptedContentError(errorObject)) {
94853
+ appendError(getErrorHintForStopReason(stopReasonToHandle, currentModelId), true);
94854
+ }
94397
94855
  } else {
94398
94856
  appendError(`An error occurred during agent execution
94399
94857
  (run_id: ${lastRunId}, stop_reason: ${stopReason})`, true);
@@ -98775,12 +99233,10 @@ var init_App2 = __esm(async () => {
98775
99233
  init_diff2();
98776
99234
  init_errorContext();
98777
99235
  init_errorFormatter();
98778
- init_formatArgsDisplay();
98779
99236
  init_messageQueueBridge();
98780
99237
  init_pasteRegistry();
98781
99238
  init_planName();
98782
99239
  init_queuedMessageParts();
98783
- init_subagentAggregation();
98784
99240
  init_subagentState();
98785
99241
  init_thinkingMessages();
98786
99242
  init_useSyncedState();
@@ -98838,9 +99294,13 @@ var init_App2 = __esm(async () => {
98838
99294
  init_WelcomeScreen(),
98839
99295
  init_accumulator(),
98840
99296
  init_approvalClassification(),
99297
+ init_formatArgsDisplay(),
98841
99298
  init_memoryReminder(),
98842
99299
  init_sessionContext(),
98843
99300
  init_stream(),
99301
+ init_subagentAggregation(),
99302
+ init_toolNameMapping(),
99303
+ init_toolNameMapping(),
98844
99304
  init_useSuspend()
98845
99305
  ]);
98846
99306
  import_react91 = __toESM(require_react(), 1);
@@ -99712,6 +100172,7 @@ var init_create3 = __esm(async () => {
99712
100172
  // src/agent/import.ts
99713
100173
  var exports_import2 = {};
99714
100174
  __export(exports_import2, {
100175
+ importAgentFromRegistry: () => importAgentFromRegistry2,
99715
100176
  importAgentFromFile: () => importAgentFromFile2,
99716
100177
  extractSkillsFromAf: () => extractSkillsFromAf2
99717
100178
  });
@@ -99819,6 +100280,45 @@ async function downloadGitHubDirectory2(entries, destDir, owner, repo, branch, b
99819
100280
  }
99820
100281
  }
99821
100282
  }
100283
+ function parseRegistryHandle2(handle) {
100284
+ const normalized = handle.startsWith("@") ? handle.slice(1) : handle;
100285
+ const parts = normalized.split("/");
100286
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
100287
+ throw new Error(`Invalid import handle "${handle}". Use format: @author/agentname`);
100288
+ }
100289
+ return { author: parts[0], name: parts[1] };
100290
+ }
100291
+ async function importAgentFromRegistry2(options) {
100292
+ const { tmpdir: tmpdir4 } = await import("node:os");
100293
+ const { join: join31 } = await import("node:path");
100294
+ const { writeFile: writeFile6, unlink: unlink2 } = await import("node:fs/promises");
100295
+ const { author, name } = parseRegistryHandle2(options.handle);
100296
+ const rawUrl = `https://raw.githubusercontent.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/refs/heads/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}/${name}.af`;
100297
+ const response = await fetch(rawUrl);
100298
+ if (!response.ok) {
100299
+ if (response.status === 404) {
100300
+ throw new Error(`Agent @${author}/${name} not found in registry. Check that the agent exists at https://github.com/${AGENT_REGISTRY_OWNER2}/${AGENT_REGISTRY_REPO2}/tree/${AGENT_REGISTRY_BRANCH2}/agents/@${author}/${name}`);
100301
+ }
100302
+ throw new Error(`Failed to download agent @${author}/${name}: ${response.statusText}`);
100303
+ }
100304
+ const afContent = await response.text();
100305
+ const tempPath = join31(tmpdir4(), `letta-import-${author}-${name}-${Date.now()}.af`);
100306
+ await writeFile6(tempPath, afContent, "utf-8");
100307
+ try {
100308
+ const result = await importAgentFromFile2({
100309
+ filePath: tempPath,
100310
+ modelOverride: options.modelOverride,
100311
+ stripMessages: options.stripMessages ?? true,
100312
+ stripSkills: options.stripSkills ?? false
100313
+ });
100314
+ return result;
100315
+ } finally {
100316
+ try {
100317
+ await unlink2(tempPath);
100318
+ } catch {}
100319
+ }
100320
+ }
100321
+ var AGENT_REGISTRY_OWNER2 = "letta-ai", AGENT_REGISTRY_REPO2 = "agent-file", AGENT_REGISTRY_BRANCH2 = "main";
99822
100322
  var init_import2 = __esm(async () => {
99823
100323
  init_model();
99824
100324
  await __promiseAll([
@@ -99919,7 +100419,7 @@ function buildModelSettings2(modelHandle, updateArgs) {
99919
100419
  } else {
99920
100420
  settings = {};
99921
100421
  }
99922
- if (typeof updateArgs?.max_output_tokens === "number") {
100422
+ if (typeof updateArgs?.max_output_tokens === "number" && "provider_type" in settings) {
99923
100423
  settings.max_output_tokens = updateArgs.max_output_tokens;
99924
100424
  }
99925
100425
  return settings;
@@ -99932,7 +100432,10 @@ async function updateAgentLLMConfig2(agentId, modelHandle, updateArgs) {
99932
100432
  await client.agents.update(agentId, {
99933
100433
  model: modelHandle,
99934
100434
  ...hasModelSettings && { model_settings: modelSettings },
99935
- ...contextWindow && { context_window_limit: contextWindow }
100435
+ ...contextWindow && { context_window_limit: contextWindow },
100436
+ ...typeof updateArgs?.max_output_tokens === "number" && {
100437
+ max_tokens: updateArgs.max_output_tokens
100438
+ }
99936
100439
  });
99937
100440
  const finalAgent = await client.agents.retrieve(agentId);
99938
100441
  return finalAgent.llm_config;
@@ -103760,6 +104263,8 @@ function releaseSwitchLock2() {
103760
104263
  lock.resolve = null;
103761
104264
  }
103762
104265
  }
104266
+ var EXTERNAL_TOOLS_KEY2 = Symbol.for("@letta/externalTools");
104267
+ var EXTERNAL_EXECUTOR_KEY2 = Symbol.for("@letta/externalToolExecutor");
103763
104268
  function replaceRegistry2(newTools) {
103764
104269
  toolRegistry2.clear();
103765
104270
  for (const [key, value] of newTools) {
@@ -103958,6 +104463,7 @@ OPTIONS
103958
104463
  --skills <path> Custom path to skills directory (default: .skills in current directory)
103959
104464
  --sleeptime Enable sleeptime memory management (only for new agents)
103960
104465
  --from-af <path> Create agent from an AgentFile (.af) template
104466
+ Use @author/name to import from the agent registry
103961
104467
  --memfs Enable memory filesystem for this agent
103962
104468
  --no-memfs Disable memory filesystem for this agent
103963
104469
 
@@ -104407,6 +104913,7 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
104407
104913
  process.exit(1);
104408
104914
  }
104409
104915
  }
104916
+ let isRegistryImport = false;
104410
104917
  if (fromAfFile) {
104411
104918
  if (specifiedAgentId) {
104412
104919
  console.error("Error: --from-af cannot be used with --agent");
@@ -104424,12 +104931,22 @@ Note: Flags should use double dashes for full names (e.g., --yolo, not -yolo)`);
104424
104931
  console.error("Error: --from-af cannot be used with --new");
104425
104932
  process.exit(1);
104426
104933
  }
104427
- const { resolve: resolve23 } = await import("path");
104428
- const { existsSync: existsSync19 } = await import("fs");
104429
- const resolvedPath = resolve23(fromAfFile);
104430
- if (!existsSync19(resolvedPath)) {
104431
- console.error(`Error: AgentFile not found: ${resolvedPath}`);
104432
- process.exit(1);
104934
+ if (fromAfFile.startsWith("@")) {
104935
+ isRegistryImport = true;
104936
+ const normalized = fromAfFile.slice(1);
104937
+ const parts = normalized.split("/");
104938
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
104939
+ console.error(`Error: Invalid registry handle "${fromAfFile}". Use format: @author/agentname`);
104940
+ process.exit(1);
104941
+ }
104942
+ } else {
104943
+ const { resolve: resolve23 } = await import("path");
104944
+ const { existsSync: existsSync19 } = await import("fs");
104945
+ const resolvedPath = resolve23(fromAfFile);
104946
+ if (!existsSync19(resolvedPath)) {
104947
+ console.error(`Error: AgentFile not found: ${resolvedPath}`);
104948
+ process.exit(1);
104949
+ }
104433
104950
  }
104434
104951
  }
104435
104952
  if (specifiedAgentName) {
@@ -104573,7 +105090,8 @@ Error: ${message}`);
104573
105090
  systemPromptPreset: systemPromptPreset2,
104574
105091
  toolset,
104575
105092
  skillsDirectory: skillsDirectory2,
104576
- fromAfFile: fromAfFile2
105093
+ fromAfFile: fromAfFile2,
105094
+ isRegistryImport: isRegistryImport2
104577
105095
  }) {
104578
105096
  const [showKeybindingSetup, setShowKeybindingSetup] = useState45(null);
104579
105097
  const [loadingState, setLoadingState] = useState45("selecting");
@@ -104870,13 +105388,24 @@ Error: ${message}`);
104870
105388
  let isNewlyCreatedAgent = false;
104871
105389
  if (fromAfFile2) {
104872
105390
  setLoadingState("importing");
104873
- const { importAgentFromFile: importAgentFromFile3 } = await init_import2().then(() => exports_import2);
104874
- const result = await importAgentFromFile3({
104875
- filePath: fromAfFile2,
104876
- modelOverride: model,
104877
- stripMessages: true,
104878
- stripSkills: false
104879
- });
105391
+ let result;
105392
+ if (isRegistryImport2) {
105393
+ const { importAgentFromRegistry: importAgentFromRegistry3 } = await init_import2().then(() => exports_import2);
105394
+ result = await importAgentFromRegistry3({
105395
+ handle: fromAfFile2,
105396
+ modelOverride: model,
105397
+ stripMessages: true,
105398
+ stripSkills: false
105399
+ });
105400
+ } else {
105401
+ const { importAgentFromFile: importAgentFromFile3 } = await init_import2().then(() => exports_import2);
105402
+ result = await importAgentFromFile3({
105403
+ filePath: fromAfFile2,
105404
+ modelOverride: model,
105405
+ stripMessages: true,
105406
+ stripSkills: false
105407
+ });
105408
+ }
104880
105409
  agent = result.agent;
104881
105410
  isNewlyCreatedAgent = true;
104882
105411
  setAgentProvenance({
@@ -105236,11 +105765,12 @@ Error during initialization: ${message}`);
105236
105765
  systemPromptPreset,
105237
105766
  toolset: specifiedToolset,
105238
105767
  skillsDirectory,
105239
- fromAfFile
105768
+ fromAfFile,
105769
+ isRegistryImport
105240
105770
  }), {
105241
105771
  exitOnCtrlC: false
105242
105772
  });
105243
105773
  }
105244
105774
  main();
105245
105775
 
105246
- //# debugId=F0DE08B3E2B6D4FD64756E2164756E21
105776
+ //# debugId=333508E0ED33A45564756E2164756E21