@hasna/assistants 1.1.38 → 1.1.39

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 CHANGED
@@ -11433,6 +11433,66 @@ Safe writable paths include: ${SAFE_WRITE_PATHS.slice(0, 10).join(", ")}... and
11433
11433
  configTools = [configGetTool, configSetTool, configListTool];
11434
11434
  });
11435
11435
 
11436
+ // packages/core/src/identity/system-assistants.ts
11437
+ function buildSystemAssistant(def) {
11438
+ const now2 = new Date().toISOString();
11439
+ return {
11440
+ id: def.id,
11441
+ name: def.name,
11442
+ description: def.description,
11443
+ avatar: def.avatar,
11444
+ isSystem: true,
11445
+ settings: {
11446
+ model: def.model,
11447
+ backend: def.backend,
11448
+ systemPromptAddition: def.systemPromptAddition
11449
+ },
11450
+ createdAt: now2,
11451
+ updatedAt: now2
11452
+ };
11453
+ }
11454
+ function getSystemAssistantDefinitions() {
11455
+ return SYSTEM_ASSISTANT_DEFINITIONS;
11456
+ }
11457
+ function isSystemAssistantId(id) {
11458
+ return Object.values(SYSTEM_ASSISTANT_IDS).includes(id);
11459
+ }
11460
+ var SYSTEM_ASSISTANT_IDS, DEFAULT_SYSTEM_ASSISTANT_ID, SYSTEM_ASSISTANT_DEFINITIONS;
11461
+ var init_system_assistants = __esm(() => {
11462
+ SYSTEM_ASSISTANT_IDS = {
11463
+ marcus: "system-marcus",
11464
+ claude: "system-claude",
11465
+ codex: "system-codex"
11466
+ };
11467
+ DEFAULT_SYSTEM_ASSISTANT_ID = SYSTEM_ASSISTANT_IDS.marcus;
11468
+ SYSTEM_ASSISTANT_DEFINITIONS = [
11469
+ {
11470
+ id: SYSTEM_ASSISTANT_IDS.marcus,
11471
+ name: "Marcus",
11472
+ description: "Your default AI assistant. Friendly, capable, and ready to help with any task.",
11473
+ avatar: "\uD83E\uDD16",
11474
+ backend: "native",
11475
+ model: "claude-opus-4-5"
11476
+ },
11477
+ {
11478
+ id: SYSTEM_ASSISTANT_IDS.claude,
11479
+ name: "Claude",
11480
+ description: "Powered by Claude Agent SDK. Full agentic capabilities with built-in tools (Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch).",
11481
+ avatar: "\uD83D\uDFE3",
11482
+ backend: "claude-agent-sdk",
11483
+ model: "claude-sonnet-4-20250514"
11484
+ },
11485
+ {
11486
+ id: SYSTEM_ASSISTANT_IDS.codex,
11487
+ name: "Codex",
11488
+ description: "Powered by OpenAI Codex SDK. Code-focused agent with deep coding capabilities.",
11489
+ avatar: "\uD83D\uDFE2",
11490
+ backend: "codex-sdk",
11491
+ model: "codex-mini"
11492
+ }
11493
+ ];
11494
+ });
11495
+
11436
11496
  // packages/core/src/tools/assistant.ts
11437
11497
  function createAssistantToolExecutors(context) {
11438
11498
  return {
@@ -11451,6 +11511,8 @@ function createAssistantToolExecutors(context) {
11451
11511
  name: a.name,
11452
11512
  description: a.description || null,
11453
11513
  model: a.settings.model,
11514
+ backend: a.settings.backend || "native",
11515
+ isSystem: a.isSystem || false,
11454
11516
  isActive: a.id === activeId,
11455
11517
  createdAt: a.createdAt,
11456
11518
  updatedAt: a.updatedAt
@@ -11631,6 +11693,12 @@ function createAssistantToolExecutors(context) {
11631
11693
  });
11632
11694
  }
11633
11695
  try {
11696
+ if (isSystemAssistantId(id)) {
11697
+ return JSON.stringify({
11698
+ success: false,
11699
+ error: "Cannot delete a system assistant. System assistants (Marcus, Claude, Codex) are built-in and cannot be removed."
11700
+ });
11701
+ }
11634
11702
  const assistants = manager.listAssistants();
11635
11703
  if (assistants.length <= 1) {
11636
11704
  return JSON.stringify({
@@ -11645,6 +11713,12 @@ function createAssistantToolExecutors(context) {
11645
11713
  error: `Assistant "${id}" not found`
11646
11714
  });
11647
11715
  }
11716
+ if (toDelete.isSystem) {
11717
+ return JSON.stringify({
11718
+ success: false,
11719
+ error: `Cannot delete system assistant "${toDelete.name}". System assistants are built-in and cannot be removed.`
11720
+ });
11721
+ }
11648
11722
  await manager.deleteAssistant(id);
11649
11723
  return JSON.stringify({
11650
11724
  success: true,
@@ -11702,6 +11776,7 @@ function registerAssistantTools(registry, context) {
11702
11776
  }
11703
11777
  var assistantListTool, assistantGetTool, assistantCreateTool, assistantUpdateTool, assistantDeleteTool, assistantSwitchTool, assistantTools;
11704
11778
  var init_assistant = __esm(() => {
11779
+ init_system_assistants();
11705
11780
  assistantListTool = {
11706
11781
  name: "assistant_list",
11707
11782
  description: "List all configured assistants with their details (id, name, description, model, active status).",
@@ -78324,7 +78399,7 @@ class BuiltinCommands {
78324
78399
  loader.register(this.webhooksCommand());
78325
78400
  loader.register(this.channelsCommand());
78326
78401
  loader.register(this.peopleCommand());
78327
- loader.register(this.phoneCommand());
78402
+ loader.register(this.communicationCommand());
78328
78403
  loader.register(this.ordersCommand());
78329
78404
  loader.register(this.tasksCommand());
78330
78405
  loader.register(this.setupCommand());
@@ -78422,10 +78497,10 @@ class BuiltinCommands {
78422
78497
  message += " - `/tasks`, `/schedules`, `/jobs`, `/orders`, `/heartbeat`, and `/logs` manage operations.\n\n";
78423
78498
  message += `**Collaboration**
78424
78499
  `;
78425
- message += " - `/assistants`, `/identity`, `/messages`, `/channels`, `/people`, `/telephony`.\n\n";
78500
+ message += " - `/assistants`, `/identity`, `/messages`, `/channels`, `/people`, `/communication`.\n\n";
78426
78501
  message += `**Voice**
78427
78502
  `;
78428
- message += " - `/voice`, `/listen`, `/talk`, `/say`.\n\n";
78503
+ message += " - `/voice`, `/talk`, `/say`.\n\n";
78429
78504
  message += `**Storage**
78430
78505
  `;
78431
78506
  message += " - Project data: `.assistants/`\n";
@@ -81936,10 +82011,11 @@ You are in a group channel with other assistants and people. Respond in #${chann
81936
82011
  }
81937
82012
  };
81938
82013
  }
81939
- phoneCommand() {
82014
+ communicationCommand() {
81940
82015
  return {
81941
- name: "phone",
81942
- description: "Manage telephony: SMS, calls, WhatsApp, routing",
82016
+ name: "communication",
82017
+ aliases: ["phone", "telephony"],
82018
+ description: "Manage communication: SMS, calls, WhatsApp, routing",
81943
82019
  builtin: true,
81944
82020
  selfHandled: true,
81945
82021
  content: "",
@@ -81961,7 +82037,7 @@ You are in a group channel with other assistants and people. Respond in #${chann
81961
82037
  if (subcommand === "numbers") {
81962
82038
  const numbers = manager.listPhoneNumbers();
81963
82039
  if (numbers.length === 0) {
81964
- context.emit("text", `No phone numbers configured. Use /phone sync to import from Twilio.
82040
+ context.emit("text", `No phone numbers configured. Use /communication sync to import from Twilio.
81965
82041
  `);
81966
82042
  } else {
81967
82043
  context.emit("text", `Phone Numbers (${numbers.length}):
@@ -81988,6 +82064,20 @@ You are in a group channel with other assistants and people. Respond in #${chann
81988
82064
  `);
81989
82065
  const result = await manager.syncPhoneNumbers();
81990
82066
  context.emit("text", `${result.success ? result.message : `Error: ${result.message}`}
82067
+ `);
82068
+ context.emit("done");
82069
+ return { handled: true };
82070
+ }
82071
+ if (subcommand === "default") {
82072
+ const number = subArgs.trim();
82073
+ if (!number) {
82074
+ context.emit("text", `Usage: /communication default <phone-number>
82075
+ `);
82076
+ context.emit("done");
82077
+ return { handled: true };
82078
+ }
82079
+ const result = manager.setDefaultPhoneNumber(number);
82080
+ context.emit("text", `${result.success ? result.message : `Error: ${result.message}`}
81991
82081
  `);
81992
82082
  context.emit("done");
81993
82083
  return { handled: true };
@@ -81999,7 +82089,7 @@ You are in a group channel with other assistants and people. Respond in #${chann
81999
82089
  const to = smsParts[1];
82000
82090
  const body = smsParts.slice(2).join(" ");
82001
82091
  if (!to || !body) {
82002
- context.emit("text", `Usage: /phone sms send <to> <body>
82092
+ context.emit("text", `Usage: /communication sms send <to> <body>
82003
82093
  `);
82004
82094
  context.emit("done");
82005
82095
  return { handled: true };
@@ -82023,7 +82113,7 @@ You are in a group channel with other assistants and people. Respond in #${chann
82023
82113
  }
82024
82114
  }
82025
82115
  } else {
82026
- context.emit("text", `Usage: /phone sms [send <to> <body> | list]
82116
+ context.emit("text", `Usage: /communication sms [send <to> <body> | list]
82027
82117
  `);
82028
82118
  }
82029
82119
  context.emit("done");
@@ -82032,7 +82122,7 @@ You are in a group channel with other assistants and people. Respond in #${chann
82032
82122
  if (subcommand === "call") {
82033
82123
  const to = subArgs.trim();
82034
82124
  if (!to) {
82035
- context.emit("text", `Usage: /phone call <to>
82125
+ context.emit("text", `Usage: /communication call <to>
82036
82126
  `);
82037
82127
  context.emit("done");
82038
82128
  return { handled: true };
@@ -82092,6 +82182,8 @@ You are in a group channel with other assistants and people. Respond in #${chann
82092
82182
  context.emit("text", ` Twilio: ${status.twilioConfigured ? "Configured" : "Not configured"}
82093
82183
  `);
82094
82184
  context.emit("text", ` ElevenLabs: ${status.elevenLabsConfigured ? "Configured" : "Not configured"}
82185
+ `);
82186
+ context.emit("text", ` Default #: ${status.defaultPhoneNumber ?? "not set"}${status.defaultPhoneNumberSource ? ` (${status.defaultPhoneNumberSource})` : ""}
82095
82187
  `);
82096
82188
  context.emit("text", ` Numbers: ${status.phoneNumbers}
82097
82189
  `);
@@ -82103,35 +82195,37 @@ You are in a group channel with other assistants and people. Respond in #${chann
82103
82195
  return { handled: true };
82104
82196
  }
82105
82197
  if (subcommand === "help") {
82106
- context.emit("text", `Phone Commands:
82198
+ context.emit("text", `Communication Commands:
82107
82199
 
82108
82200
  `);
82109
- context.emit("text", `/phone Open telephony panel
82201
+ context.emit("text", `/communication Open communication panel
82202
+ `);
82203
+ context.emit("text", `/communication numbers List phone numbers
82110
82204
  `);
82111
- context.emit("text", `/phone numbers List phone numbers
82205
+ context.emit("text", `/communication sync Sync numbers from Twilio
82112
82206
  `);
82113
- context.emit("text", `/phone sync Sync numbers from Twilio
82207
+ context.emit("text", `/communication default <number> Set default phone number
82114
82208
  `);
82115
- context.emit("text", `/phone sms send <to> <body> Send SMS
82209
+ context.emit("text", `/communication sms send <to> <body> Send SMS
82116
82210
  `);
82117
- context.emit("text", `/phone sms list Recent SMS
82211
+ context.emit("text", `/communication sms list Recent SMS
82118
82212
  `);
82119
- context.emit("text", `/phone call <to> Initiate call
82213
+ context.emit("text", `/communication call <to> Initiate call
82120
82214
  `);
82121
- context.emit("text", `/phone calls Recent calls
82215
+ context.emit("text", `/communication calls Recent calls
82122
82216
  `);
82123
- context.emit("text", `/phone routes Routing rules
82217
+ context.emit("text", `/communication routes Routing rules
82124
82218
  `);
82125
- context.emit("text", `/phone status Status summary
82219
+ context.emit("text", `/communication status Status summary
82126
82220
  `);
82127
- context.emit("text", `/phone help Show this help
82221
+ context.emit("text", `/communication help Show this help
82128
82222
  `);
82129
82223
  context.emit("done");
82130
82224
  return { handled: true };
82131
82225
  }
82132
82226
  context.emit("text", `Unknown command: ${subcommand}
82133
82227
  `);
82134
- context.emit("text", `Use /phone help for available commands.
82228
+ context.emit("text", `Use /communication help for available commands.
82135
82229
  `);
82136
82230
  context.emit("done");
82137
82231
  return { handled: true };
@@ -87115,7 +87209,7 @@ Not a git repository or git not available.
87115
87209
  context.setProjectContext(projectContext);
87116
87210
  }
87117
87211
  }
87118
- var VERSION2 = "1.1.38";
87212
+ var VERSION2 = "1.1.39";
87119
87213
  var init_builtin = __esm(async () => {
87120
87214
  init_src2();
87121
87215
  init_store();
@@ -93799,10 +93893,10 @@ class AssistantManager {
93799
93893
  this.assistants.set(id, assistant);
93800
93894
  }
93801
93895
  }
93896
+ await this.seedSystemAssistants();
93802
93897
  this.activeId = await this.readActive();
93803
- if (!this.activeId && this.assistants.size > 0) {
93804
- const first = [...this.assistants.keys()][0];
93805
- await this.setActive(first);
93898
+ if (!this.activeId || !this.assistants.has(this.activeId)) {
93899
+ await this.setActive(DEFAULT_SYSTEM_ASSISTANT_ID);
93806
93900
  }
93807
93901
  }
93808
93902
  async createAssistant(options) {
@@ -93843,6 +93937,10 @@ class AssistantManager {
93843
93937
  if (!this.assistants.has(id)) {
93844
93938
  throw new Error(`Assistant ${id} not found`);
93845
93939
  }
93940
+ const assistant = this.assistants.get(id);
93941
+ if (assistant?.isSystem || isSystemAssistantId(id)) {
93942
+ throw new Error(`Cannot delete system assistant "${assistant?.name || id}". System assistants are built-in and cannot be removed.`);
93943
+ }
93846
93944
  await rm3(join36(this.assistantsRoot, id), { recursive: true, force: true });
93847
93945
  this.assistants.delete(id);
93848
93946
  await this.removeFromIndex(id);
@@ -93873,6 +93971,17 @@ class AssistantManager {
93873
93971
  getIdentityManager(assistantId) {
93874
93972
  return new IdentityManager(assistantId, this.basePath);
93875
93973
  }
93974
+ async seedSystemAssistants() {
93975
+ const definitions = getSystemAssistantDefinitions();
93976
+ for (const def of definitions) {
93977
+ if (!this.assistants.has(def.id)) {
93978
+ const assistant = buildSystemAssistant(def);
93979
+ await this.persistAssistant(assistant);
93980
+ this.assistants.set(def.id, assistant);
93981
+ await this.appendToIndex(def.id);
93982
+ }
93983
+ }
93984
+ }
93876
93985
  async readIndex() {
93877
93986
  if (!existsSync25(this.indexPath)) {
93878
93987
  return { assistants: [] };
@@ -93939,6 +94048,7 @@ var SAFE_ID_PATTERN8, DEFAULT_SETTINGS;
93939
94048
  var init_assistant_manager = __esm(() => {
93940
94049
  init_src2();
93941
94050
  init_identity_manager();
94051
+ init_system_assistants();
93942
94052
  SAFE_ID_PATTERN8 = /^[a-zA-Z0-9_-]+$/;
93943
94053
  DEFAULT_SETTINGS = {
93944
94054
  model: "claude-opus-4-5"
@@ -93950,6 +94060,7 @@ var init_identity2 = __esm(() => {
93950
94060
  init_assistant_manager();
93951
94061
  init_identity_manager();
93952
94062
  init_templates();
94063
+ init_system_assistants();
93953
94064
  });
93954
94065
 
93955
94066
  // node_modules/.bun/@smithy+types@4.12.0/node_modules/@smithy/types/dist-cjs/index.js
@@ -174179,7 +174290,7 @@ class WebhooksManager {
174179
174290
  if (!isTimestampValid(input.timestamp, maxTimestampAge)) {
174180
174291
  return { success: false, message: "Timestamp too old or invalid." };
174181
174292
  }
174182
- const payloadStr = JSON.stringify(input.payload);
174293
+ const payloadStr = typeof input.rawBody === "string" ? input.rawBody : JSON.stringify(input.payload);
174183
174294
  if (!verifySignature(payloadStr, input.signature, registration.secret)) {
174184
174295
  return { success: false, message: "Invalid signature." };
174185
174296
  }
@@ -174241,7 +174352,8 @@ class WebhooksManager {
174241
174352
  payload,
174242
174353
  signature,
174243
174354
  timestamp: new Date().toISOString(),
174244
- eventType: "test"
174355
+ eventType: "test",
174356
+ rawBody: payloadStr
174245
174357
  });
174246
174358
  }
174247
174359
  async listEvents(webhookId, options) {
@@ -175316,6 +175428,670 @@ var init_manager6 = __esm(async () => {
175316
175428
  await init_store7();
175317
175429
  });
175318
175430
 
175431
+ // packages/core/src/agent/tool-bridge.ts
175432
+ function toolPropertyToZodDescriptor(prop) {
175433
+ const baseType = Array.isArray(prop.type) ? prop.type[0] : prop.type;
175434
+ if (prop.enum && prop.enum.length > 0) {
175435
+ return {
175436
+ type: "string",
175437
+ description: prop.description,
175438
+ enum: prop.enum
175439
+ };
175440
+ }
175441
+ switch (baseType) {
175442
+ case "string":
175443
+ return { type: "string", description: prop.description };
175444
+ case "number":
175445
+ return { type: "number", description: prop.description };
175446
+ case "boolean":
175447
+ return { type: "boolean", description: prop.description };
175448
+ case "array":
175449
+ return {
175450
+ type: "array",
175451
+ description: prop.description,
175452
+ items: prop.items ? toolPropertyToZodDescriptor(prop.items) : { type: "string" }
175453
+ };
175454
+ case "object":
175455
+ if (prop.properties) {
175456
+ const properties = {};
175457
+ for (const [key, value] of Object.entries(prop.properties)) {
175458
+ properties[key] = toolPropertyToZodDescriptor(value);
175459
+ }
175460
+ return {
175461
+ type: "object",
175462
+ description: prop.description,
175463
+ properties,
175464
+ required: prop.required
175465
+ };
175466
+ }
175467
+ return { type: "object", description: prop.description };
175468
+ default:
175469
+ return { type: "string", description: prop.description };
175470
+ }
175471
+ }
175472
+ function toolToMcpDescriptor(tool) {
175473
+ const parameters = {};
175474
+ for (const [key, prop] of Object.entries(tool.parameters.properties)) {
175475
+ parameters[key] = toolPropertyToZodDescriptor(prop);
175476
+ }
175477
+ return {
175478
+ name: tool.name,
175479
+ description: tool.description,
175480
+ parameters,
175481
+ required: tool.parameters.required || []
175482
+ };
175483
+ }
175484
+ function getAllMcpDescriptors(registry) {
175485
+ return registry.getTools().map(toolToMcpDescriptor);
175486
+ }
175487
+ function buildToolsSystemPrompt(registry) {
175488
+ const tools = registry.getTools();
175489
+ if (tools.length === 0)
175490
+ return "";
175491
+ const lines = [
175492
+ "You have access to the following custom tools via bash commands.",
175493
+ "To use a tool, run: assistants-tool <tool_name> '<json_input>'",
175494
+ ""
175495
+ ];
175496
+ for (const tool of tools) {
175497
+ const params = Object.entries(tool.parameters.properties).map(([name2, prop]) => {
175498
+ const req = tool.parameters.required?.includes(name2) ? " (required)" : "";
175499
+ return ` ${name2}: ${Array.isArray(prop.type) ? prop.type.join("|") : prop.type}${req} - ${prop.description}`;
175500
+ }).join(`
175501
+ `);
175502
+ lines.push(`- ${tool.name}: ${tool.description}`);
175503
+ if (params)
175504
+ lines.push(params);
175505
+ lines.push("");
175506
+ }
175507
+ return lines.join(`
175508
+ `);
175509
+ }
175510
+
175511
+ // packages/core/src/agent/claude-agent-loop.ts
175512
+ class ClaudeAgentLoop {
175513
+ context;
175514
+ cwd;
175515
+ sessionId;
175516
+ assistantId;
175517
+ model;
175518
+ processing = false;
175519
+ stopped = false;
175520
+ toolRegistry;
175521
+ mcpDescriptors = [];
175522
+ extraSystemPrompt;
175523
+ tokenUsage = {
175524
+ inputTokens: 0,
175525
+ outputTokens: 0,
175526
+ totalTokens: 0,
175527
+ maxContextTokens: 200000
175528
+ };
175529
+ onChunk;
175530
+ onToolStart;
175531
+ onToolEnd;
175532
+ constructor(options) {
175533
+ this.cwd = options.cwd || process.cwd();
175534
+ this.sessionId = options.sessionId || generateId();
175535
+ this.assistantId = options.assistantId || null;
175536
+ this.model = options.model || "claude-sonnet-4-20250514";
175537
+ this.toolRegistry = options.toolRegistry || null;
175538
+ this.extraSystemPrompt = options.extraSystemPrompt || "";
175539
+ this.onChunk = options.onChunk || null;
175540
+ this.onToolStart = options.onToolStart || null;
175541
+ this.onToolEnd = options.onToolEnd || null;
175542
+ this.context = new AssistantContext(100);
175543
+ }
175544
+ async initialize() {
175545
+ if (this.toolRegistry) {
175546
+ this.mcpDescriptors = getAllMcpDescriptors(this.toolRegistry);
175547
+ }
175548
+ }
175549
+ async process(userMessage) {
175550
+ if (this.processing)
175551
+ return;
175552
+ this.processing = true;
175553
+ this.stopped = false;
175554
+ try {
175555
+ this.context.addUserMessage(userMessage);
175556
+ let query;
175557
+ try {
175558
+ const sdk = await import("@anthropic-ai/claude-agent-sdk");
175559
+ query = sdk.query;
175560
+ } catch {
175561
+ this.emitChunk({ type: "error", error: "Claude Agent SDK (@anthropic-ai/claude-agent-sdk) is not installed. Run: pnpm add -F @hasna/assistants-core @anthropic-ai/claude-agent-sdk" });
175562
+ this.emitChunk({ type: "done" });
175563
+ return;
175564
+ }
175565
+ const mcpToolNames = this.mcpDescriptors.map((d5) => `mcp__assistants__${d5.name}`);
175566
+ const builtinTools = [
175567
+ "Read",
175568
+ "Write",
175569
+ "Edit",
175570
+ "Bash",
175571
+ "Glob",
175572
+ "Grep",
175573
+ "WebSearch",
175574
+ "WebFetch"
175575
+ ];
175576
+ const queryOptions = {
175577
+ model: this.model,
175578
+ allowedTools: [...builtinTools, ...mcpToolNames],
175579
+ permissionMode: "bypassPermissions",
175580
+ cwd: this.cwd
175581
+ };
175582
+ if (this.extraSystemPrompt) {
175583
+ queryOptions.systemPrompt = this.extraSystemPrompt;
175584
+ }
175585
+ let fullText = "";
175586
+ for await (const msg of query({ prompt: userMessage, options: queryOptions })) {
175587
+ if (this.stopped)
175588
+ break;
175589
+ if (msg.type === "assistant") {
175590
+ for (const block of msg.message?.content || []) {
175591
+ if (this.stopped)
175592
+ break;
175593
+ if (block.type === "text") {
175594
+ fullText += block.text;
175595
+ this.emitChunk({ type: "text", content: block.text });
175596
+ } else if (block.type === "tool_use") {
175597
+ const toolCall = {
175598
+ id: block.id || generateId(),
175599
+ name: block.name,
175600
+ input: block.input
175601
+ };
175602
+ this.onToolStart?.(toolCall);
175603
+ this.emitChunk({ type: "tool_use", toolCall });
175604
+ if (this.toolRegistry && block.name.startsWith("mcp__assistants__")) {
175605
+ const realToolName = block.name.replace("mcp__assistants__", "");
175606
+ try {
175607
+ const appToolCall = {
175608
+ id: toolCall.id,
175609
+ name: realToolName,
175610
+ input: block.input
175611
+ };
175612
+ const result = await this.toolRegistry.execute(appToolCall);
175613
+ this.onToolEnd?.(toolCall, result);
175614
+ this.emitChunk({ type: "tool_result", toolResult: result });
175615
+ } catch (err) {
175616
+ const result = {
175617
+ toolCallId: toolCall.id,
175618
+ content: err instanceof Error ? err.message : String(err),
175619
+ isError: true,
175620
+ toolName: realToolName
175621
+ };
175622
+ this.onToolEnd?.(toolCall, result);
175623
+ this.emitChunk({ type: "tool_result", toolResult: result });
175624
+ }
175625
+ }
175626
+ }
175627
+ }
175628
+ } else if (msg.type === "result") {
175629
+ if (msg.is_error) {
175630
+ this.emitChunk({ type: "error", error: msg.error || "Claude Agent SDK error" });
175631
+ } else {
175632
+ if (msg.usage) {
175633
+ this.tokenUsage = {
175634
+ inputTokens: this.tokenUsage.inputTokens + (msg.usage.input_tokens || 0),
175635
+ outputTokens: this.tokenUsage.outputTokens + (msg.usage.output_tokens || 0),
175636
+ totalTokens: this.tokenUsage.totalTokens + (msg.usage.input_tokens || 0) + (msg.usage.output_tokens || 0),
175637
+ maxContextTokens: this.tokenUsage.maxContextTokens
175638
+ };
175639
+ this.emitChunk({ type: "usage", usage: this.tokenUsage });
175640
+ }
175641
+ }
175642
+ }
175643
+ }
175644
+ if (fullText) {
175645
+ this.context.addAssistantMessage(fullText);
175646
+ }
175647
+ this.emitChunk({ type: "done" });
175648
+ } catch (error3) {
175649
+ const message = error3 instanceof Error ? error3.message : String(error3);
175650
+ this.emitChunk({ type: "error", error: message });
175651
+ this.emitChunk({ type: "done" });
175652
+ } finally {
175653
+ this.processing = false;
175654
+ }
175655
+ }
175656
+ stop() {
175657
+ this.stopped = true;
175658
+ this.processing = false;
175659
+ }
175660
+ shutdown() {
175661
+ this.stop();
175662
+ }
175663
+ clearConversation() {
175664
+ this.context.clear();
175665
+ this.tokenUsage = {
175666
+ inputTokens: 0,
175667
+ outputTokens: 0,
175668
+ totalTokens: 0,
175669
+ maxContextTokens: 200000
175670
+ };
175671
+ }
175672
+ getContext() {
175673
+ return this.context;
175674
+ }
175675
+ getTools() {
175676
+ return this.toolRegistry?.getTools() || [];
175677
+ }
175678
+ getSkills() {
175679
+ return [];
175680
+ }
175681
+ getSkillLoader() {
175682
+ return null;
175683
+ }
175684
+ getCommands() {
175685
+ return [];
175686
+ }
175687
+ getTokenUsage() {
175688
+ return this.tokenUsage;
175689
+ }
175690
+ getModel() {
175691
+ return this.model;
175692
+ }
175693
+ getContextInfo() {
175694
+ return null;
175695
+ }
175696
+ getEnergyState() {
175697
+ return null;
175698
+ }
175699
+ getVoiceState() {
175700
+ return null;
175701
+ }
175702
+ getHeartbeatState() {
175703
+ return null;
175704
+ }
175705
+ getAssistantManager() {
175706
+ return null;
175707
+ }
175708
+ getIdentityManager() {
175709
+ return null;
175710
+ }
175711
+ getMemoryManager() {
175712
+ return null;
175713
+ }
175714
+ getMessagesManager() {
175715
+ return null;
175716
+ }
175717
+ getWebhooksManager() {
175718
+ return null;
175719
+ }
175720
+ getChannelsManager() {
175721
+ return null;
175722
+ }
175723
+ getChannelAgentPool() {
175724
+ return null;
175725
+ }
175726
+ getPeopleManager() {
175727
+ return null;
175728
+ }
175729
+ getTelephonyManager() {
175730
+ return null;
175731
+ }
175732
+ getOrdersManager() {
175733
+ return null;
175734
+ }
175735
+ getJobManager() {
175736
+ return null;
175737
+ }
175738
+ getWalletManager() {
175739
+ return null;
175740
+ }
175741
+ getSecretsManager() {
175742
+ return null;
175743
+ }
175744
+ getInboxManager() {
175745
+ return null;
175746
+ }
175747
+ getAssistantId() {
175748
+ return this.assistantId;
175749
+ }
175750
+ getIdentityInfo() {
175751
+ return { assistant: null, identity: null };
175752
+ }
175753
+ getActiveProjectId() {
175754
+ return null;
175755
+ }
175756
+ setActiveProjectId(_id) {}
175757
+ getOrCreateSwarmCoordinator() {
175758
+ return null;
175759
+ }
175760
+ isProcessing() {
175761
+ return this.processing;
175762
+ }
175763
+ isBudgetExceeded() {
175764
+ return false;
175765
+ }
175766
+ isPaused() {
175767
+ return false;
175768
+ }
175769
+ getBudgetStatus() {
175770
+ return null;
175771
+ }
175772
+ getSessionId() {
175773
+ return this.sessionId;
175774
+ }
175775
+ setAskUserHandler(_handler) {}
175776
+ importContext(_messages) {}
175777
+ refreshIdentityContext() {}
175778
+ refreshSkills() {}
175779
+ addSystemMessage(content) {
175780
+ this.context.addSystemMessage(content);
175781
+ }
175782
+ emitChunk(chunk) {
175783
+ this.onChunk?.(chunk);
175784
+ }
175785
+ }
175786
+ var init_claude_agent_loop = __esm(() => {
175787
+ init_src2();
175788
+ init_context();
175789
+ });
175790
+
175791
+ // packages/core/src/agent/codex-loop.ts
175792
+ class CodexAgentLoop {
175793
+ context;
175794
+ cwd;
175795
+ sessionId;
175796
+ assistantId;
175797
+ model;
175798
+ processing = false;
175799
+ stopped = false;
175800
+ toolRegistry;
175801
+ extraSystemPrompt;
175802
+ codex = null;
175803
+ thread = null;
175804
+ tokenUsage = {
175805
+ inputTokens: 0,
175806
+ outputTokens: 0,
175807
+ totalTokens: 0,
175808
+ maxContextTokens: 128000
175809
+ };
175810
+ onChunk;
175811
+ onToolStart;
175812
+ onToolEnd;
175813
+ constructor(options) {
175814
+ this.cwd = options.cwd || process.cwd();
175815
+ this.sessionId = options.sessionId || generateId();
175816
+ this.assistantId = options.assistantId || null;
175817
+ this.model = options.model || "codex-mini";
175818
+ this.toolRegistry = options.toolRegistry || null;
175819
+ this.extraSystemPrompt = options.extraSystemPrompt || "";
175820
+ this.onChunk = options.onChunk || null;
175821
+ this.onToolStart = options.onToolStart || null;
175822
+ this.onToolEnd = options.onToolEnd || null;
175823
+ this.context = new AssistantContext(100);
175824
+ }
175825
+ async initialize() {
175826
+ if (this.toolRegistry) {
175827
+ const toolsPrompt = buildToolsSystemPrompt(this.toolRegistry);
175828
+ if (toolsPrompt) {
175829
+ this.extraSystemPrompt = [this.extraSystemPrompt, toolsPrompt].filter(Boolean).join(`
175830
+
175831
+ `);
175832
+ }
175833
+ }
175834
+ }
175835
+ async process(userMessage) {
175836
+ if (this.processing)
175837
+ return;
175838
+ this.processing = true;
175839
+ this.stopped = false;
175840
+ try {
175841
+ this.context.addUserMessage(userMessage);
175842
+ let Codex;
175843
+ try {
175844
+ const sdk = await import("@openai/codex-sdk");
175845
+ Codex = sdk.Codex || sdk.default;
175846
+ } catch {
175847
+ this.emitChunk({ type: "error", error: "OpenAI Codex SDK (@openai/codex-sdk) is not installed. Run: pnpm add -F @hasna/assistants-core @openai/codex-sdk" });
175848
+ this.emitChunk({ type: "done" });
175849
+ return;
175850
+ }
175851
+ if (!this.codex) {
175852
+ this.codex = new Codex({
175853
+ model: this.model,
175854
+ instructions: this.extraSystemPrompt || undefined
175855
+ });
175856
+ }
175857
+ if (!this.thread) {
175858
+ this.thread = this.codex.startThread({
175859
+ workingDirectory: this.cwd
175860
+ });
175861
+ }
175862
+ let fullText = "";
175863
+ const { events } = await this.thread.runStreamed(userMessage);
175864
+ for await (const event of events) {
175865
+ if (this.stopped)
175866
+ break;
175867
+ if (event.type === "item.completed") {
175868
+ const item = event.item;
175869
+ if (item?.type === "message" && item.role === "assistant") {
175870
+ for (const part of item.content || []) {
175871
+ if (part.type === "output_text" || part.type === "text") {
175872
+ const text = part.text || part.content || "";
175873
+ fullText += text;
175874
+ this.emitChunk({ type: "text", content: text });
175875
+ }
175876
+ }
175877
+ } else if (item?.type === "function_call" || item?.type === "tool_use") {
175878
+ const toolCall = {
175879
+ id: item.call_id || item.id || generateId(),
175880
+ name: item.name || item.function?.name || "unknown",
175881
+ input: typeof item.arguments === "string" ? JSON.parse(item.arguments || "{}") : item.input || item.arguments || {}
175882
+ };
175883
+ this.onToolStart?.(toolCall);
175884
+ this.emitChunk({ type: "tool_use", toolCall });
175885
+ } else if (item?.type === "function_call_output") {
175886
+ const result = {
175887
+ toolCallId: item.call_id || generateId(),
175888
+ content: typeof item.output === "string" ? item.output : JSON.stringify(item.output),
175889
+ toolName: item.name
175890
+ };
175891
+ this.emitChunk({ type: "tool_result", toolResult: result });
175892
+ }
175893
+ } else if (event.type === "turn.completed") {
175894
+ if (event.usage) {
175895
+ this.tokenUsage = {
175896
+ inputTokens: this.tokenUsage.inputTokens + (event.usage.input_tokens || 0),
175897
+ outputTokens: this.tokenUsage.outputTokens + (event.usage.output_tokens || 0),
175898
+ totalTokens: this.tokenUsage.totalTokens + (event.usage.input_tokens || 0) + (event.usage.output_tokens || 0),
175899
+ maxContextTokens: this.tokenUsage.maxContextTokens
175900
+ };
175901
+ this.emitChunk({ type: "usage", usage: this.tokenUsage });
175902
+ }
175903
+ }
175904
+ }
175905
+ if (fullText) {
175906
+ this.context.addAssistantMessage(fullText);
175907
+ }
175908
+ this.emitChunk({ type: "done" });
175909
+ } catch (error3) {
175910
+ const message = error3 instanceof Error ? error3.message : String(error3);
175911
+ this.emitChunk({ type: "error", error: message });
175912
+ this.emitChunk({ type: "done" });
175913
+ } finally {
175914
+ this.processing = false;
175915
+ }
175916
+ }
175917
+ stop() {
175918
+ this.stopped = true;
175919
+ this.processing = false;
175920
+ }
175921
+ shutdown() {
175922
+ this.stop();
175923
+ this.thread = null;
175924
+ this.codex = null;
175925
+ }
175926
+ clearConversation() {
175927
+ this.context.clear();
175928
+ this.thread = null;
175929
+ this.tokenUsage = {
175930
+ inputTokens: 0,
175931
+ outputTokens: 0,
175932
+ totalTokens: 0,
175933
+ maxContextTokens: 128000
175934
+ };
175935
+ }
175936
+ getContext() {
175937
+ return this.context;
175938
+ }
175939
+ getTools() {
175940
+ return this.toolRegistry?.getTools() || [];
175941
+ }
175942
+ getSkills() {
175943
+ return [];
175944
+ }
175945
+ getSkillLoader() {
175946
+ return null;
175947
+ }
175948
+ getCommands() {
175949
+ return [];
175950
+ }
175951
+ getTokenUsage() {
175952
+ return this.tokenUsage;
175953
+ }
175954
+ getModel() {
175955
+ return this.model;
175956
+ }
175957
+ getContextInfo() {
175958
+ return null;
175959
+ }
175960
+ getEnergyState() {
175961
+ return null;
175962
+ }
175963
+ getVoiceState() {
175964
+ return null;
175965
+ }
175966
+ getHeartbeatState() {
175967
+ return null;
175968
+ }
175969
+ getAssistantManager() {
175970
+ return null;
175971
+ }
175972
+ getIdentityManager() {
175973
+ return null;
175974
+ }
175975
+ getMemoryManager() {
175976
+ return null;
175977
+ }
175978
+ getMessagesManager() {
175979
+ return null;
175980
+ }
175981
+ getWebhooksManager() {
175982
+ return null;
175983
+ }
175984
+ getChannelsManager() {
175985
+ return null;
175986
+ }
175987
+ getChannelAgentPool() {
175988
+ return null;
175989
+ }
175990
+ getPeopleManager() {
175991
+ return null;
175992
+ }
175993
+ getTelephonyManager() {
175994
+ return null;
175995
+ }
175996
+ getOrdersManager() {
175997
+ return null;
175998
+ }
175999
+ getJobManager() {
176000
+ return null;
176001
+ }
176002
+ getWalletManager() {
176003
+ return null;
176004
+ }
176005
+ getSecretsManager() {
176006
+ return null;
176007
+ }
176008
+ getInboxManager() {
176009
+ return null;
176010
+ }
176011
+ getAssistantId() {
176012
+ return this.assistantId;
176013
+ }
176014
+ getIdentityInfo() {
176015
+ return { assistant: null, identity: null };
176016
+ }
176017
+ getActiveProjectId() {
176018
+ return null;
176019
+ }
176020
+ setActiveProjectId(_id) {}
176021
+ getOrCreateSwarmCoordinator() {
176022
+ return null;
176023
+ }
176024
+ isProcessing() {
176025
+ return this.processing;
176026
+ }
176027
+ isBudgetExceeded() {
176028
+ return false;
176029
+ }
176030
+ isPaused() {
176031
+ return false;
176032
+ }
176033
+ getBudgetStatus() {
176034
+ return null;
176035
+ }
176036
+ getSessionId() {
176037
+ return this.sessionId;
176038
+ }
176039
+ setAskUserHandler(_handler) {}
176040
+ importContext(_messages) {}
176041
+ refreshIdentityContext() {}
176042
+ refreshSkills() {}
176043
+ addSystemMessage(content) {
176044
+ this.context.addSystemMessage(content);
176045
+ }
176046
+ emitChunk(chunk) {
176047
+ this.onChunk?.(chunk);
176048
+ }
176049
+ }
176050
+ var init_codex_loop = __esm(() => {
176051
+ init_src2();
176052
+ init_context();
176053
+ });
176054
+
176055
+ // packages/core/src/agent/factory.ts
176056
+ function createAgentLoop(backend, options = {}) {
176057
+ switch (backend) {
176058
+ case "claude-agent-sdk":
176059
+ return new ClaudeAgentLoop({
176060
+ cwd: options.cwd,
176061
+ sessionId: options.sessionId,
176062
+ assistantId: options.assistantId,
176063
+ model: options.model,
176064
+ storageDir: options.storageDir,
176065
+ workspaceId: options.workspaceId,
176066
+ extraSystemPrompt: options.extraSystemPrompt,
176067
+ onChunk: options.onChunk,
176068
+ onToolStart: options.onToolStart,
176069
+ onToolEnd: options.onToolEnd
176070
+ });
176071
+ case "codex-sdk":
176072
+ return new CodexAgentLoop({
176073
+ cwd: options.cwd,
176074
+ sessionId: options.sessionId,
176075
+ assistantId: options.assistantId,
176076
+ model: options.model,
176077
+ storageDir: options.storageDir,
176078
+ workspaceId: options.workspaceId,
176079
+ extraSystemPrompt: options.extraSystemPrompt,
176080
+ onChunk: options.onChunk,
176081
+ onToolStart: options.onToolStart,
176082
+ onToolEnd: options.onToolEnd
176083
+ });
176084
+ case "native":
176085
+ default:
176086
+ return new AssistantLoop(options);
176087
+ }
176088
+ }
176089
+ var init_factory = __esm(async () => {
176090
+ init_claude_agent_loop();
176091
+ init_codex_loop();
176092
+ await init_loop();
176093
+ });
176094
+
175319
176095
  // packages/core/src/client.ts
175320
176096
  class EmbeddedClient {
175321
176097
  assistantLoop;
@@ -175346,7 +176122,8 @@ class EmbeddedClient {
175346
176122
  this.startedAt = options?.startedAt || new Date().toISOString();
175347
176123
  this.initialMessages = options?.initialMessages || null;
175348
176124
  this.logger.info("Session started", { cwd: this.cwd });
175349
- const createAssistant = options?.assistantFactory ?? ((opts) => new AssistantLoop(opts));
176125
+ const backend = options?.backend;
176126
+ const createAssistant = options?.assistantFactory ?? ((opts) => createAgentLoop(backend, opts));
175350
176127
  this.assistantLoop = createAssistant({
175351
176128
  cwd: this.cwd,
175352
176129
  sessionId,
@@ -175753,7 +176530,7 @@ class EmbeddedClient {
175753
176530
  var init_client4 = __esm(async () => {
175754
176531
  init_src2();
175755
176532
  await __promiseAll([
175756
- init_loop(),
176533
+ init_factory(),
175757
176534
  init_logger2()
175758
176535
  ]);
175759
176536
  });
@@ -176841,6 +177618,12 @@ class TelephonyStore {
176841
177618
  updated_at TEXT NOT NULL
176842
177619
  );
176843
177620
 
177621
+ CREATE TABLE IF NOT EXISTS telephony_settings (
177622
+ key TEXT PRIMARY KEY,
177623
+ value TEXT NOT NULL,
177624
+ updated_at TEXT NOT NULL
177625
+ );
177626
+
176844
177627
  CREATE INDEX IF NOT EXISTS idx_call_logs_assistant ON call_logs(assistant_id);
176845
177628
  CREATE INDEX IF NOT EXISTS idx_call_logs_status ON call_logs(status);
176846
177629
  CREATE INDEX IF NOT EXISTS idx_call_logs_created ON call_logs(created_at);
@@ -176851,6 +177634,22 @@ class TelephonyStore {
176851
177634
  CREATE INDEX IF NOT EXISTS idx_routing_rules_priority ON routing_rules(priority, enabled);
176852
177635
  `);
176853
177636
  }
177637
+ getSetting(key) {
177638
+ const row = this.db.prepare("SELECT value FROM telephony_settings WHERE key = ?").get(key);
177639
+ return row?.value ?? null;
177640
+ }
177641
+ setSetting(key, value) {
177642
+ const now2 = new Date().toISOString();
177643
+ this.db.prepare(`INSERT INTO telephony_settings (key, value, updated_at)
177644
+ VALUES (?, ?, ?)
177645
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`).run(key, value, now2);
177646
+ }
177647
+ getDefaultPhoneNumber() {
177648
+ return this.getSetting("default_phone_number");
177649
+ }
177650
+ setDefaultPhoneNumber(number) {
177651
+ this.setSetting("default_phone_number", number);
177652
+ }
176854
177653
  addPhoneNumber(number, friendlyName, twilioSid, capabilities) {
176855
177654
  const id = generatePhoneId();
176856
177655
  const now2 = new Date().toISOString();
@@ -177816,11 +178615,11 @@ class TelephonyManager {
177816
178615
  message: "Twilio is not configured. Set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN."
177817
178616
  };
177818
178617
  }
177819
- const fromNumber = from || this.config.defaultPhoneNumber || process.env.TWILIO_PHONE_NUMBER;
178618
+ const fromNumber = from || this.getDefaultPhoneNumber();
177820
178619
  if (!fromNumber) {
177821
178620
  return {
177822
178621
  success: false,
177823
- message: "No phone number configured. Set telephony.defaultPhoneNumber or TWILIO_PHONE_NUMBER."
178622
+ message: "No phone number configured. Set telephony.defaultPhoneNumber, TWILIO_PHONE_NUMBER, or /communication default <number>."
177824
178623
  };
177825
178624
  }
177826
178625
  const webhookUrl = this.config.webhookUrl || process.env.TELEPHONY_WEBHOOK_URL;
@@ -177858,11 +178657,11 @@ class TelephonyManager {
177858
178657
  message: "Twilio is not configured. Set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN."
177859
178658
  };
177860
178659
  }
177861
- const fromNumber = from || this.config.defaultPhoneNumber || process.env.TWILIO_PHONE_NUMBER;
178660
+ const fromNumber = from || this.getDefaultPhoneNumber();
177862
178661
  if (!fromNumber) {
177863
178662
  return {
177864
178663
  success: false,
177865
- message: "No phone number configured."
178664
+ message: "No phone number configured. Set telephony.defaultPhoneNumber, TWILIO_PHONE_NUMBER, or /communication default <number>."
177866
178665
  };
177867
178666
  }
177868
178667
  const webhookUrl = this.config.webhookUrl || process.env.TELEPHONY_WEBHOOK_URL;
@@ -177900,11 +178699,11 @@ class TelephonyManager {
177900
178699
  message: "Twilio is not configured. Set TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN."
177901
178700
  };
177902
178701
  }
177903
- const fromNumber = from || this.config.defaultPhoneNumber || process.env.TWILIO_PHONE_NUMBER;
178702
+ const fromNumber = from || this.getDefaultPhoneNumber();
177904
178703
  if (!fromNumber) {
177905
178704
  return {
177906
178705
  success: false,
177907
- message: "No phone number configured."
178706
+ message: "No phone number configured. Set telephony.defaultPhoneNumber, TWILIO_PHONE_NUMBER, or /communication default <number>."
177908
178707
  };
177909
178708
  }
177910
178709
  const webhookUrl = this.config.webhookUrl || process.env.TELEPHONY_WEBHOOK_URL;
@@ -178009,11 +178808,43 @@ class TelephonyManager {
178009
178808
  message: success ? "Routing rule deleted." : "Routing rule not found."
178010
178809
  };
178011
178810
  }
178811
+ setDefaultPhoneNumber(number) {
178812
+ const trimmed = number.trim();
178813
+ if (!trimmed) {
178814
+ return { success: false, message: "Default phone number is required." };
178815
+ }
178816
+ this.store.setDefaultPhoneNumber(trimmed);
178817
+ return { success: true, message: `Default phone number set to ${trimmed}.` };
178818
+ }
178819
+ getDefaultPhoneNumber() {
178820
+ const configDefault = this.config.defaultPhoneNumber?.trim();
178821
+ if (configDefault)
178822
+ return configDefault;
178823
+ const stored = this.store.getDefaultPhoneNumber();
178824
+ if (stored)
178825
+ return stored;
178826
+ const envDefault = process.env.TWILIO_PHONE_NUMBER?.trim();
178827
+ return envDefault || null;
178828
+ }
178829
+ getDefaultPhoneNumberSource() {
178830
+ const configDefault = this.config.defaultPhoneNumber?.trim();
178831
+ if (configDefault)
178832
+ return "config";
178833
+ const stored = this.store.getDefaultPhoneNumber();
178834
+ if (stored)
178835
+ return "local";
178836
+ const envDefault = process.env.TWILIO_PHONE_NUMBER?.trim();
178837
+ if (envDefault)
178838
+ return "env";
178839
+ return null;
178840
+ }
178012
178841
  getStatus() {
178013
178842
  const phoneNumbers = this.store.listPhoneNumbers("active");
178014
178843
  const recentCalls = this.store.listCallLogs({ limit: 100 });
178015
178844
  const recentMessages = this.store.listSmsLogs({ limit: 100 });
178016
178845
  const routingRules = this.store.listRoutingRules();
178846
+ const defaultPhoneNumber = this.getDefaultPhoneNumber();
178847
+ const defaultPhoneNumberSource = this.getDefaultPhoneNumberSource();
178017
178848
  return {
178018
178849
  enabled: this.config.enabled !== false,
178019
178850
  twilioConfigured: this.twilioClient?.isConfigured() ?? false,
@@ -178022,7 +178853,9 @@ class TelephonyManager {
178022
178853
  activeCalls: this.callManager.getActiveCallCount(),
178023
178854
  routingRules: routingRules.length,
178024
178855
  recentCalls: recentCalls.length,
178025
- recentMessages: recentMessages.length
178856
+ recentMessages: recentMessages.length,
178857
+ defaultPhoneNumber,
178858
+ defaultPhoneNumberSource
178026
178859
  };
178027
178860
  }
178028
178861
  getUnreadForInjection() {
@@ -178220,7 +179053,7 @@ function createTelephonyToolExecutors(getTelephonyManager) {
178220
179053
  }
178221
179054
  const numbers = manager.listPhoneNumbers();
178222
179055
  if (numbers.length === 0) {
178223
- return "No phone numbers configured. Use /phone sync to import from Twilio.";
179056
+ return "No phone numbers configured. Use /communication sync to import from Twilio.";
178224
179057
  }
178225
179058
  const lines = [];
178226
179059
  lines.push(`## Phone Numbers (${numbers.length})`);
@@ -178304,6 +179137,7 @@ function createTelephonyToolExecutors(getTelephonyManager) {
178304
179137
  lines.push(`Enabled: ${status.enabled ? "Yes" : "No"}`);
178305
179138
  lines.push(`Twilio configured: ${status.twilioConfigured ? "Yes" : "No (set TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN)"}`);
178306
179139
  lines.push(`ElevenLabs AI: ${status.elevenLabsConfigured ? "Yes" : "No (set ELEVENLABS_API_KEY + ELEVENLABS_AGENT_ID)"}`);
179140
+ lines.push(`Default number: ${status.defaultPhoneNumber ?? "not set"}${status.defaultPhoneNumberSource ? ` (${status.defaultPhoneNumberSource})` : ""}`);
178307
179141
  lines.push(`Phone numbers: ${status.phoneNumbers}`);
178308
179142
  lines.push(`Active calls: ${status.activeCalls}`);
178309
179143
  lines.push(`Routing rules: ${status.routingRules}`);
@@ -179688,6 +180522,7 @@ class SessionRegistry {
179688
180522
  initialMessages: options.initialMessages,
179689
180523
  startedAt: options.startedAt,
179690
180524
  assistantId: options.assistantId,
180525
+ backend: options.backend,
179691
180526
  basePath: this.basePath,
179692
180527
  workspaceId: this.workspaceId ?? undefined
179693
180528
  };
@@ -190321,6 +191156,7 @@ __export(exports_src3, {
190321
191156
  updateJob: () => updateJob,
190322
191157
  twilioToElevenLabs: () => twilioToElevenLabs,
190323
191158
  toolsSearchTool: () => toolsSearchTool,
191159
+ toolToMcpDescriptor: () => toolToMcpDescriptor,
190324
191160
  telephonyTools: () => telephonyTools,
190325
191161
  telephonyStatusTool: () => telephonyStatusTool,
190326
191162
  telephonySmsHistoryTool: () => telephonySmsHistoryTool,
@@ -190485,6 +191321,7 @@ __export(exports_src3, {
190485
191321
  isValidModel: () => isValidModel,
190486
191322
  isTimestampValid: () => isTimestampValid,
190487
191323
  isSystemVoiceAvailable: () => isSystemVoiceAvailable,
191324
+ isSystemAssistantId: () => isSystemAssistantId,
190488
191325
  isPrivateIPv4: () => isPrivateIPv4,
190489
191326
  isPrivateHostOrResolved: () => isPrivateHostOrResolved,
190490
191327
  isPrivateHost: () => isPrivateHost,
@@ -190523,6 +191360,7 @@ __export(exports_src3, {
190523
191360
  getTasks: () => getTasks,
190524
191361
  getTaskCounts: () => getTaskCounts,
190525
191362
  getTask: () => getTask,
191363
+ getSystemAssistantDefinitions: () => getSystemAssistantDefinitions,
190526
191364
  getSecurityLogger: () => getSecurityLogger,
190527
191365
  getSchedule: () => getSchedule,
190528
191366
  getRuntime: () => getRuntime,
@@ -190552,6 +191390,7 @@ __export(exports_src3, {
190552
191390
  getCommandHistory: () => getCommandHistory,
190553
191391
  getCapabilityPreset: () => getCapabilityPreset,
190554
191392
  getAllModelIds: () => getAllModelIds,
191393
+ getAllMcpDescriptors: () => getAllMcpDescriptors,
190555
191394
  getActiveWorkspaceId: () => getActiveWorkspaceId,
190556
191395
  generateWebhookSecret: () => generateWebhookSecret,
190557
191396
  generateWebhookId: () => generateWebhookId,
@@ -190637,6 +191476,7 @@ __export(exports_src3, {
190637
191476
  createAutoScheduleHeartbeatHook: () => createAutoScheduleHeartbeatHook,
190638
191477
  createAssistantToolExecutors: () => createAssistantToolExecutors2,
190639
191478
  createAssistantRegistryToolExecutors: () => createAssistantRegistryToolExecutors,
191479
+ createAgentLoop: () => createAgentLoop,
190640
191480
  contextStatsTool: () => contextStatsTool,
190641
191481
  contextGetTool: () => contextGetTool,
190642
191482
  connectorsSearchTool: () => connectorsSearchTool,
@@ -190665,6 +191505,8 @@ __export(exports_src3, {
190665
191505
  capabilitiesGetTool: () => capabilitiesGetTool,
190666
191506
  capabilitiesCheckTool: () => capabilitiesCheckTool,
190667
191507
  cancelRecurringTask: () => cancelRecurringTask,
191508
+ buildToolsSystemPrompt: () => buildToolsSystemPrompt,
191509
+ buildSystemAssistant: () => buildSystemAssistant,
190668
191510
  buildProjectContext: () => buildProjectContext,
190669
191511
  buildEnergyConfig: () => buildEnergyConfig,
190670
191512
  buildContextInjection: () => buildContextInjection,
@@ -190732,6 +191574,7 @@ __export(exports_src3, {
190732
191574
  SecretsClient: () => SecretsClient,
190733
191575
  ScopeContextManager: () => ScopeContextManager,
190734
191576
  SchedulerTool: () => SchedulerTool,
191577
+ SYSTEM_ASSISTANT_IDS: () => SYSTEM_ASSISTANT_IDS,
190735
191578
  SESProvider: () => SESProvider,
190736
191579
  S3InboxClient: () => S3InboxClient,
190737
191580
  ResendProvider: () => ResendProvider,
@@ -190795,6 +191638,7 @@ __export(exports_src3, {
190795
191638
  DEFAULT_WATCHDOG_INTERVAL_MS: () => DEFAULT_WATCHDOG_INTERVAL_MS,
190796
191639
  DEFAULT_TOOL_RULES: () => DEFAULT_TOOL_RULES,
190797
191640
  DEFAULT_SYSTEM_POLICY: () => DEFAULT_SYSTEM_POLICY,
191641
+ DEFAULT_SYSTEM_ASSISTANT_ID: () => DEFAULT_SYSTEM_ASSISTANT_ID,
190798
191642
  DEFAULT_SWARM_LIMITS: () => DEFAULT_SWARM_LIMITS,
190799
191643
  DEFAULT_SWARM_CONFIG: () => DEFAULT_SWARM_CONFIG,
190800
191644
  DEFAULT_STATUS_CONFIG: () => DEFAULT_STATUS_CONFIG,
@@ -190832,6 +191676,8 @@ __export(exports_src3, {
190832
191676
  CommandLoader: () => CommandLoader,
190833
191677
  CommandHistory: () => CommandHistory,
190834
191678
  CommandExecutor: () => CommandExecutor,
191679
+ CodexAgentLoop: () => CodexAgentLoop,
191680
+ ClaudeAgentLoop: () => ClaudeAgentLoop,
190835
191681
  ChannelsManager: () => ChannelsManager,
190836
191682
  ChannelStore: () => ChannelStore,
190837
191683
  ChannelAgentPool: () => ChannelAgentPool,
@@ -190853,6 +191699,8 @@ __export(exports_src3, {
190853
191699
  });
190854
191700
  var init_src3 = __esm(async () => {
190855
191701
  init_context();
191702
+ init_claude_agent_loop();
191703
+ init_codex_loop();
190856
191704
  init_subagent_manager();
190857
191705
  init_connector_index();
190858
191706
  init_web();
@@ -190888,6 +191736,7 @@ var init_src3 = __esm(async () => {
190888
191736
  await __promiseAll([
190889
191737
  init_runtime(),
190890
191738
  init_loop(),
191739
+ init_factory(),
190891
191740
  init_registry(),
190892
191741
  init_auto_refresh(),
190893
191742
  init_connector(),
@@ -231069,9 +231918,9 @@ var COMMANDS = [
231069
231918
  { name: "/whoami", description: "show current identity" },
231070
231919
  { name: "/voice", description: "toggle voice mode" },
231071
231920
  { name: "/say", description: "speak text aloud" },
231072
- { name: "/listen", description: "start dictation (pause 3s to send)" },
231073
231921
  { name: "/talk", description: "live voice conversation (2s pause to send)" },
231074
231922
  { name: "/messages", description: "assistant messaging and email inbox" },
231923
+ { name: "/communication", description: "manage calls, SMS, WhatsApp, routing" },
231075
231924
  { name: "/wallet", description: "manage assistant wallet" },
231076
231925
  { name: "/secrets", description: "manage assistant secrets" },
231077
231926
  { name: "/jobs", description: "manage background jobs" },
@@ -231120,7 +231969,6 @@ var Input = import_react37.default.forwardRef(function Input2({
231120
231969
  isAskingUser = false,
231121
231970
  askPlaceholder,
231122
231971
  allowBlankAnswer = false,
231123
- footerHints = [],
231124
231972
  assistantName,
231125
231973
  history: historyProp,
231126
231974
  pasteConfig,
@@ -231566,13 +232414,6 @@ var Input = import_react37.default.forwardRef(function Input2({
231566
232414
  const lines = layout.displayLines;
231567
232415
  const lineCount = value.split(`
231568
232416
  `).length;
231569
- const quickHints = [];
231570
- if (isProcessing && !isAskingUser) {
231571
- quickHints.push("[esc] stop");
231572
- }
231573
- if (footerHints.length > 0) {
231574
- quickHints.push(...footerHints);
231575
- }
231576
232417
  return /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
231577
232418
  flexDirection: "column",
231578
232419
  marginTop: 1,
@@ -231732,10 +232573,6 @@ var Input = import_react37.default.forwardRef(function Input2({
231732
232573
  }, undefined, false, undefined, this)
231733
232574
  ]
231734
232575
  }, undefined, true, undefined, this),
231735
- quickHints.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text3, {
231736
- dimColor: true,
231737
- children: quickHints.join(" \xB7 ")
231738
- }, undefined, false, undefined, this),
231739
232576
  autocompleteMode === "skill" && filteredSkills.length > 0 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
231740
232577
  flexDirection: "column",
231741
232578
  children: [
@@ -233091,12 +233928,12 @@ function estimateToolPanelLines(toolCalls, toolResults, hasContent, maxWidth) {
233091
233928
  for (const result of toolResults || []) {
233092
233929
  resultLines.set(result.toolCallId, estimateToolResultLines(result, resultWidth));
233093
233930
  }
233094
- let lines = 3;
233931
+ let lines = 0;
233095
233932
  if (hasContent) {
233096
233933
  lines += 1;
233097
233934
  }
233098
233935
  for (const call of toolCalls) {
233099
- lines += 3;
233936
+ lines += 2;
233100
233937
  const toolResultLines = resultLines.get(call.id);
233101
233938
  if (toolResultLines && toolResultLines > 0) {
233102
233939
  lines += toolResultLines;
@@ -233109,7 +233946,7 @@ function estimateToolResultPanelLines(toolResults, hasContent, maxWidth) {
233109
233946
  return 0;
233110
233947
  const innerWidth = maxWidth ? Math.max(1, maxWidth - 4) : undefined;
233111
233948
  const resultWidth = innerWidth ? Math.max(1, innerWidth - 4) : undefined;
233112
- let lines = 3;
233949
+ let lines = 0;
233113
233950
  if (hasContent) {
233114
233951
  lines += 1;
233115
233952
  }
@@ -233544,9 +234381,6 @@ function MessageBubble({ message, queuedMessageIds, verboseTools }) {
233544
234381
  }, undefined, true, undefined, this);
233545
234382
  }
233546
234383
  function ActiveToolsPanel({ activityLog, now: now2, verboseTools }) {
233547
- const { stdout } = use_stdout_default();
233548
- const columns = stdout?.columns ?? 80;
233549
- const panelWidth = Math.max(1, columns - 2);
233550
234384
  const toolCalls = import_react38.useMemo(() => {
233551
234385
  const calls = [];
233552
234386
  const resultMap = new Map;
@@ -233562,17 +234396,17 @@ function ActiveToolsPanel({ activityLog, now: now2, verboseTools }) {
233562
234396
  for (const entry of activityLog) {
233563
234397
  if (entry.type === "tool_call" && entry.toolCall) {
233564
234398
  const resultInfo = resultMap.get(entry.toolCall.id);
233565
- let status2;
234399
+ let status;
233566
234400
  if (resultInfo) {
233567
- status2 = resultInfo.result.isError ? "failed" : "succeeded";
234401
+ status = resultInfo.result.isError ? "failed" : "succeeded";
233568
234402
  } else {
233569
234403
  const elapsed = now3 - entry.timestamp;
233570
- status2 = elapsed > 60000 ? "failed" : "running";
234404
+ status = elapsed > 60000 ? "failed" : "running";
233571
234405
  }
233572
234406
  calls.push({
233573
234407
  id: entry.toolCall.id,
233574
234408
  toolCall: entry.toolCall,
233575
- status: status2,
234409
+ status,
233576
234410
  startTime: entry.timestamp,
233577
234411
  endTime: resultInfo?.timestamp,
233578
234412
  result: resultInfo?.result
@@ -233581,132 +234415,142 @@ function ActiveToolsPanel({ activityLog, now: now2, verboseTools }) {
233581
234415
  }
233582
234416
  return calls;
233583
234417
  }, [activityLog]);
233584
- const status = import_react38.useMemo(() => {
233585
- const counts = { running: 0, succeeded: 0, failed: 0, total: 0 };
233586
- for (const call of toolCalls) {
233587
- counts.total++;
233588
- counts[call.status]++;
233589
- }
233590
- return counts;
233591
- }, [toolCalls]);
233592
234418
  if (toolCalls.length === 0)
233593
234419
  return null;
233594
- const hasErrors = status.failed > 0;
233595
- const allDone = status.running === 0;
233596
- const borderColor = hasErrors ? "red" : allDone ? "green" : "gray";
233597
- const summaryParts = [];
233598
- if (status.running > 0)
233599
- summaryParts.push(`${status.running} running`);
233600
- if (status.succeeded > 0)
233601
- summaryParts.push(`${status.succeeded} done`);
233602
- if (status.failed > 0)
233603
- summaryParts.push(`${status.failed} failed`);
233604
- const summaryText = summaryParts.join(", ");
234420
+ if (!verboseTools && toolCalls.length >= 2) {
234421
+ const anyRunning = toolCalls.some((c6) => c6.status === "running");
234422
+ const anyError = toolCalls.some((c6) => c6.status === "failed");
234423
+ const summary = buildToolCallSummary(toolCalls.map((c6) => c6.toolCall), anyRunning);
234424
+ const icon = anyRunning ? "\u25D0" : anyError ? "\u2717" : "\u25CF";
234425
+ const iconColor = anyRunning ? "gray" : anyError ? "red" : "green";
234426
+ const suffix2 = anyRunning ? "\u2026" : "";
234427
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234428
+ children: [
234429
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234430
+ color: iconColor,
234431
+ children: [
234432
+ icon,
234433
+ " "
234434
+ ]
234435
+ }, undefined, true, undefined, this),
234436
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234437
+ children: [
234438
+ summary,
234439
+ suffix2
234440
+ ]
234441
+ }, undefined, true, undefined, this),
234442
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234443
+ dimColor: true,
234444
+ children: " (ctrl+o to expand)"
234445
+ }, undefined, false, undefined, this)
234446
+ ]
234447
+ }, undefined, true, undefined, this);
234448
+ }
233605
234449
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233606
234450
  flexDirection: "column",
233607
- borderStyle: "round",
233608
- borderColor: "#d4d4d8",
233609
- borderLeft: false,
233610
- borderRight: false,
233611
- width: panelWidth,
233612
- marginY: 1,
233613
- children: [
233614
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233615
- justifyContent: "space-between",
233616
- children: [
233617
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233618
- color: borderColor,
233619
- bold: true,
233620
- children: "Active Tools"
233621
- }, undefined, false, undefined, this),
233622
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233623
- dimColor: true,
233624
- children: [
233625
- status.total,
233626
- " \xB7 ",
233627
- summaryText
233628
- ]
233629
- }, undefined, true, undefined, this)
233630
- ]
233631
- }, undefined, true, undefined, this),
233632
- toolCalls.map((call) => {
233633
- const statusIcon = call.status === "running" ? "\u25D0" : call.status === "failed" ? "\u2717" : "\u2713";
233634
- const statusColor = call.status === "running" ? "gray" : call.status === "failed" ? "red" : "green";
233635
- const elapsedMs = (call.endTime ?? now2) - call.startTime;
233636
- const elapsedText = formatDuration3(elapsedMs);
233637
- const displayName = getToolDisplayName(call.toolCall);
233638
- const context3 = getToolContext(call.toolCall);
233639
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233640
- flexDirection: "column",
233641
- marginTop: 1,
233642
- children: [
233643
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234451
+ children: toolCalls.map((call) => {
234452
+ const icon = call.status === "running" ? "\u25D0" : call.status === "failed" ? "\u2717" : "\u25CF";
234453
+ const iconColor = call.status === "running" ? "gray" : call.status === "failed" ? "red" : "green";
234454
+ const elapsedMs = (call.endTime ?? now2) - call.startTime;
234455
+ const elapsedText = formatDuration3(elapsedMs);
234456
+ const title = getToolCallTitle(call.toolCall);
234457
+ const prefix2 = call.status === "running" ? "Calling " : "";
234458
+ const params = call.status === "running" ? formatToolParams(call.toolCall) : [];
234459
+ if (call.result && call.toolCall.name === "display_image" && !call.result.isError) {
234460
+ try {
234461
+ const imgData = JSON.parse(call.result.content);
234462
+ if (imgData.path) {
234463
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234464
+ flexDirection: "column",
233644
234465
  children: [
233645
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233646
- color: statusColor,
234466
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233647
234467
  children: [
233648
- statusIcon,
233649
- " "
233650
- ]
233651
- }, undefined, true, undefined, this),
233652
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233653
- color: statusColor,
233654
- bold: true,
233655
- children: displayName
233656
- }, undefined, false, undefined, this),
233657
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233658
- dimColor: true,
233659
- children: [
233660
- " [",
233661
- call.status,
233662
- "]"
233663
- ]
233664
- }, undefined, true, undefined, this),
233665
- context3 && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233666
- dimColor: true,
233667
- children: [
233668
- " \xB7 ",
233669
- context3
234468
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234469
+ color: iconColor,
234470
+ children: [
234471
+ icon,
234472
+ " "
234473
+ ]
234474
+ }, undefined, true, undefined, this),
234475
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234476
+ color: iconColor,
234477
+ bold: true,
234478
+ children: title
234479
+ }, undefined, false, undefined, this),
234480
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234481
+ dimColor: true,
234482
+ children: [
234483
+ " \xB7 ",
234484
+ elapsedText
234485
+ ]
234486
+ }, undefined, true, undefined, this)
233670
234487
  ]
233671
234488
  }, undefined, true, undefined, this),
233672
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233673
- dimColor: true,
233674
- children: [
233675
- " \xB7 ",
233676
- elapsedText
233677
- ]
233678
- }, undefined, true, undefined, this)
234489
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(TerminalImage, {
234490
+ src: imgData.path,
234491
+ width: imgData.width,
234492
+ height: imgData.height,
234493
+ alt: imgData.alt || "image"
234494
+ }, undefined, false, undefined, this)
233679
234495
  ]
233680
- }, undefined, true, undefined, this),
233681
- call.result && call.toolCall.name === "display_image" && !call.result.isError && (() => {
233682
- try {
233683
- const imgData = JSON.parse(call.result.content);
233684
- if (imgData.path) {
233685
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(TerminalImage, {
233686
- src: imgData.path,
233687
- width: imgData.width,
233688
- height: imgData.height,
233689
- alt: imgData.alt || "image"
233690
- }, undefined, false, undefined, this);
233691
- }
233692
- } catch {}
233693
- return null;
233694
- })(),
233695
- call.result && (call.toolCall.name !== "display_image" || call.result.isError) && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233696
- marginLeft: 2,
233697
- children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234496
+ }, call.id, true, undefined, this);
234497
+ }
234498
+ } catch {}
234499
+ }
234500
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234501
+ flexDirection: "column",
234502
+ children: [
234503
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234504
+ children: [
234505
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234506
+ color: iconColor,
234507
+ children: [
234508
+ icon,
234509
+ " "
234510
+ ]
234511
+ }, undefined, true, undefined, this),
234512
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234513
+ color: iconColor,
234514
+ bold: true,
234515
+ children: [
234516
+ prefix2,
234517
+ title
234518
+ ]
234519
+ }, undefined, true, undefined, this),
234520
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233698
234521
  dimColor: true,
233699
234522
  children: [
233700
- "\u21B3 ",
233701
- truncateToolResult(call.result, 2, 200, { verbose: verboseTools })
234523
+ " \xB7 ",
234524
+ elapsedText
233702
234525
  ]
233703
234526
  }, undefined, true, undefined, this)
233704
- }, undefined, false, undefined, this)
233705
- ]
233706
- }, call.id, true, undefined, this);
233707
- })
233708
- ]
233709
- }, undefined, true, undefined, this);
234527
+ ]
234528
+ }, undefined, true, undefined, this),
234529
+ params.length > 0 && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234530
+ marginLeft: 1,
234531
+ flexDirection: "column",
234532
+ children: params.map((param, i5) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234533
+ dimColor: true,
234534
+ children: [
234535
+ i5 === 0 ? "\u2514 " : " ",
234536
+ param
234537
+ ]
234538
+ }, i5, true, undefined, this))
234539
+ }, undefined, false, undefined, this),
234540
+ call.result && (call.toolCall.name !== "display_image" || call.result.isError) && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234541
+ marginLeft: 1,
234542
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234543
+ dimColor: true,
234544
+ children: [
234545
+ "\u2514 ",
234546
+ truncateToolResult(call.result, 2, 200, { verbose: verboseTools })
234547
+ ]
234548
+ }, undefined, true, undefined, this)
234549
+ }, undefined, false, undefined, this)
234550
+ ]
234551
+ }, call.id, true, undefined, this);
234552
+ })
234553
+ }, undefined, false, undefined, this);
233710
234554
  }
233711
234555
  function startsWithListOrTable(content) {
233712
234556
  const lines = content.split(`
@@ -233755,116 +234599,142 @@ function ToolCallPanel({
233755
234599
  }) {
233756
234600
  if (toolCalls.length === 0)
233757
234601
  return null;
233758
- const { stdout } = use_stdout_default();
233759
- const columns = stdout?.columns ?? 80;
233760
- const panelWidth = Math.max(1, columns - 2);
233761
- const innerWidth = Math.max(1, panelWidth - 4);
233762
234602
  const resultMap = new Map;
233763
234603
  for (const result of toolResults || []) {
233764
234604
  resultMap.set(result.toolCallId, result);
233765
234605
  }
233766
- const hasError = toolCalls.some((toolCall) => resultMap.get(toolCall.id)?.isError);
233767
- const allComplete = toolCalls.every((toolCall) => resultMap.has(toolCall.id));
233768
- const borderColor = hasError ? "red" : allComplete ? "green" : "gray";
234606
+ if (!verboseTools && toolCalls.length >= 2) {
234607
+ const allComplete = toolCalls.every((tc) => resultMap.has(tc.id));
234608
+ const anyError = toolCalls.some((tc) => resultMap.get(tc.id)?.isError);
234609
+ const isRunning = !allComplete;
234610
+ const summary = buildToolCallSummary(toolCalls, isRunning);
234611
+ const icon = isRunning ? "\u25D0" : anyError ? "\u2717" : "\u25CF";
234612
+ const iconColor = isRunning ? "gray" : anyError ? "red" : "green";
234613
+ const suffix2 = isRunning ? "\u2026" : "";
234614
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234615
+ children: [
234616
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234617
+ color: iconColor,
234618
+ children: [
234619
+ icon,
234620
+ " "
234621
+ ]
234622
+ }, undefined, true, undefined, this),
234623
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234624
+ children: [
234625
+ summary,
234626
+ suffix2
234627
+ ]
234628
+ }, undefined, true, undefined, this),
234629
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234630
+ dimColor: true,
234631
+ children: " (ctrl+o to expand)"
234632
+ }, undefined, false, undefined, this)
234633
+ ]
234634
+ }, undefined, true, undefined, this);
234635
+ }
233769
234636
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233770
234637
  flexDirection: "column",
233771
- borderStyle: "round",
233772
- borderColor: "#d4d4d8",
233773
- borderLeft: false,
233774
- borderRight: false,
233775
- width: panelWidth,
233776
- children: [
233777
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233778
- justifyContent: "space-between",
233779
- children: [
233780
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233781
- color: borderColor,
233782
- bold: true,
233783
- children: "Tool Calls"
233784
- }, undefined, false, undefined, this),
233785
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233786
- dimColor: true,
233787
- children: [
233788
- toolCalls.length,
233789
- " ",
233790
- allComplete ? "done" : "running"
233791
- ]
233792
- }, undefined, true, undefined, this)
233793
- ]
233794
- }, undefined, true, undefined, this),
233795
- toolCalls.map((toolCall) => {
233796
- const result = resultMap.get(toolCall.id);
233797
- const statusIcon = result ? result.isError ? "\u2717" : "\u2713" : "\u25D0";
233798
- const statusLabel = result ? result.isError ? "failed" : "succeeded" : "running";
233799
- const statusColor = result ? result.isError ? "red" : "green" : "gray";
233800
- const displayName = getToolDisplayName(toolCall);
233801
- const context3 = getToolContext(toolCall);
233802
- const maxLine = Math.max(1, innerWidth - 2);
233803
- const summaryLine = truncate2(formatToolCall(toolCall), maxLine);
233804
- const truncatedResult = result ? truncateToolResultWithInfo(result, 4, 400, { verbose: verboseTools }) : null;
233805
- const resultText = truncatedResult ? indentMultiline(truncatedResult.content, " ") : "";
233806
- const showExpandHint = !verboseTools && truncatedResult?.truncation.wasTruncated;
233807
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233808
- flexDirection: "column",
233809
- marginTop: 1,
233810
- children: [
233811
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234638
+ children: toolCalls.map((toolCall) => {
234639
+ const result = resultMap.get(toolCall.id);
234640
+ const isRunning = !result;
234641
+ const isError = result?.isError;
234642
+ const icon = isRunning ? "\u25D0" : isError ? "\u2717" : "\u25CF";
234643
+ const iconColor = isRunning ? "gray" : isError ? "red" : "green";
234644
+ const title = getToolCallTitle(toolCall);
234645
+ const prefix2 = isRunning ? "Calling " : "";
234646
+ const params = isRunning ? formatToolParams(toolCall) : [];
234647
+ if (result && toolCall.name === "display_image" && !result.isError) {
234648
+ try {
234649
+ const imgData = JSON.parse(result.content);
234650
+ if (imgData.path) {
234651
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234652
+ flexDirection: "column",
233812
234653
  children: [
233813
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233814
- color: statusColor,
234654
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233815
234655
  children: [
233816
- statusIcon,
233817
- " "
233818
- ]
233819
- }, undefined, true, undefined, this),
233820
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233821
- color: statusColor,
233822
- bold: true,
233823
- children: displayName
233824
- }, undefined, false, undefined, this),
233825
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233826
- dimColor: true,
233827
- children: [
233828
- " [",
233829
- statusLabel,
233830
- "]"
234656
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234657
+ color: iconColor,
234658
+ children: [
234659
+ icon,
234660
+ " "
234661
+ ]
234662
+ }, undefined, true, undefined, this),
234663
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234664
+ color: iconColor,
234665
+ bold: true,
234666
+ children: title
234667
+ }, undefined, false, undefined, this)
233831
234668
  ]
233832
234669
  }, undefined, true, undefined, this),
233833
- context3 && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233834
- dimColor: true,
233835
- children: [
233836
- " \xB7 ",
233837
- context3
233838
- ]
233839
- }, undefined, true, undefined, this)
234670
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(TerminalImage, {
234671
+ src: imgData.path,
234672
+ width: imgData.width,
234673
+ height: imgData.height,
234674
+ alt: imgData.alt || "image"
234675
+ }, undefined, false, undefined, this)
233840
234676
  ]
233841
- }, undefined, true, undefined, this),
233842
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233843
- dimColor: true,
233844
- children: summaryLine
233845
- }, undefined, false, undefined, this),
233846
- result && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233847
- marginLeft: 2,
233848
- children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233849
- dimColor: true,
234677
+ }, toolCall.id, true, undefined, this);
234678
+ }
234679
+ } catch {}
234680
+ }
234681
+ const truncatedResult = result ? truncateToolResultWithInfo(result, 4, 400, { verbose: verboseTools }) : null;
234682
+ const resultText = truncatedResult?.content || "";
234683
+ const showExpandHint = !verboseTools && truncatedResult?.truncation.wasTruncated;
234684
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234685
+ flexDirection: "column",
234686
+ children: [
234687
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234688
+ children: [
234689
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234690
+ color: iconColor,
233850
234691
  children: [
233851
- "\u21B3 ",
233852
- resultText
234692
+ icon,
234693
+ " "
234694
+ ]
234695
+ }, undefined, true, undefined, this),
234696
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234697
+ color: iconColor,
234698
+ bold: true,
234699
+ children: [
234700
+ prefix2,
234701
+ title
233853
234702
  ]
233854
234703
  }, undefined, true, undefined, this)
233855
- }, undefined, false, undefined, this),
233856
- showExpandHint && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233857
- marginLeft: 2,
233858
- children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233859
- dimColor: true,
233860
- children: "\u21B3 (Ctrl+O for full output)"
233861
- }, undefined, false, undefined, this)
234704
+ ]
234705
+ }, undefined, true, undefined, this),
234706
+ params.length > 0 && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234707
+ marginLeft: 1,
234708
+ flexDirection: "column",
234709
+ children: params.map((param, i5) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234710
+ dimColor: true,
234711
+ children: [
234712
+ i5 === 0 ? "\u2514 " : " ",
234713
+ param
234714
+ ]
234715
+ }, i5, true, undefined, this))
234716
+ }, undefined, false, undefined, this),
234717
+ result && resultText && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234718
+ marginLeft: 1,
234719
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234720
+ dimColor: true,
234721
+ children: [
234722
+ "\u2514 ",
234723
+ indentMultiline(resultText, " ")
234724
+ ]
234725
+ }, undefined, true, undefined, this)
234726
+ }, undefined, false, undefined, this),
234727
+ showExpandHint && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234728
+ marginLeft: 1,
234729
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234730
+ dimColor: true,
234731
+ children: " (Ctrl+O for full output)"
233862
234732
  }, undefined, false, undefined, this)
233863
- ]
233864
- }, toolCall.id, true, undefined, this);
233865
- })
233866
- ]
233867
- }, undefined, true, undefined, this);
234733
+ }, undefined, false, undefined, this)
234734
+ ]
234735
+ }, toolCall.id, true, undefined, this);
234736
+ })
234737
+ }, undefined, false, undefined, this);
233868
234738
  }
233869
234739
  function ToolResultPanel({
233870
234740
  toolResults,
@@ -233872,143 +234742,179 @@ function ToolResultPanel({
233872
234742
  }) {
233873
234743
  if (toolResults.length === 0)
233874
234744
  return null;
233875
- const { stdout } = use_stdout_default();
233876
- const columns = stdout?.columns ?? 80;
233877
- const panelWidth = Math.max(1, columns - 2);
233878
- const innerWidth = Math.max(1, panelWidth - 4);
233879
- const hasError = toolResults.some((result) => result.isError);
233880
- const borderColor = hasError ? "red" : "green";
233881
234745
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233882
234746
  flexDirection: "column",
233883
- borderStyle: "round",
233884
- borderColor: "#d4d4d8",
233885
- borderLeft: false,
233886
- borderRight: false,
233887
- width: panelWidth,
233888
- children: [
233889
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233890
- justifyContent: "space-between",
233891
- children: [
233892
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233893
- color: borderColor,
233894
- bold: true,
233895
- children: "Tool Results"
233896
- }, undefined, false, undefined, this),
233897
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233898
- dimColor: true,
233899
- children: toolResults.length
233900
- }, undefined, false, undefined, this)
233901
- ]
233902
- }, undefined, true, undefined, this),
233903
- toolResults.map((result, index) => {
233904
- const statusIcon = result.isError ? "\u2717" : "\u2713";
233905
- const statusLabel = result.isError ? "failed" : "succeeded";
233906
- const statusColor = result.isError ? "red" : "green";
233907
- const title = result.toolName ? `${result.toolName}` : `Result ${index + 1}`;
233908
- const maxLine = Math.max(1, innerWidth - 2);
233909
- const summaryLine = truncate2(title, maxLine);
233910
- if (result.toolName === "display_image" && !result.isError) {
233911
- try {
233912
- const data = JSON.parse(result.content);
233913
- if (data.path) {
233914
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233915
- flexDirection: "column",
233916
- marginTop: 1,
233917
- children: [
233918
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233919
- children: [
233920
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233921
- color: statusColor,
233922
- children: [
233923
- statusIcon,
233924
- " "
233925
- ]
233926
- }, undefined, true, undefined, this),
233927
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233928
- color: statusColor,
233929
- bold: true,
233930
- children: summaryLine
233931
- }, undefined, false, undefined, this),
233932
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233933
- dimColor: true,
233934
- children: [
233935
- " [",
233936
- statusLabel,
233937
- "]"
233938
- ]
233939
- }, undefined, true, undefined, this)
233940
- ]
233941
- }, undefined, true, undefined, this),
233942
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(TerminalImage, {
233943
- src: data.path,
233944
- width: data.width,
233945
- height: data.height,
233946
- alt: data.alt || basename7(data.path)
233947
- }, undefined, false, undefined, this)
233948
- ]
233949
- }, `${result.toolCallId}-${index}`, true, undefined, this);
233950
- }
233951
- } catch {}
233952
- }
233953
- const truncatedResult = truncateToolResultWithInfo(result, 4, 400, { verbose: verboseTools });
233954
- const resultText = indentMultiline(truncatedResult.content, " ");
233955
- const showExpandHint = !verboseTools && truncatedResult.truncation.wasTruncated;
233956
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233957
- flexDirection: "column",
233958
- marginTop: 1,
233959
- children: [
233960
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234747
+ children: toolResults.map((result, index) => {
234748
+ const isError = result.isError;
234749
+ const icon = isError ? "\u2717" : "\u25CF";
234750
+ const iconColor = isError ? "red" : "green";
234751
+ const title = result.toolName ? capitalizeToolName(result.toolName) : `Result ${index + 1}`;
234752
+ if (result.toolName === "display_image" && !result.isError) {
234753
+ try {
234754
+ const data = JSON.parse(result.content);
234755
+ if (data.path) {
234756
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234757
+ flexDirection: "column",
233961
234758
  children: [
233962
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233963
- color: statusColor,
234759
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233964
234760
  children: [
233965
- statusIcon,
233966
- " "
234761
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234762
+ color: iconColor,
234763
+ children: [
234764
+ icon,
234765
+ " "
234766
+ ]
234767
+ }, undefined, true, undefined, this),
234768
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234769
+ color: iconColor,
234770
+ bold: true,
234771
+ children: title
234772
+ }, undefined, false, undefined, this)
233967
234773
  ]
233968
234774
  }, undefined, true, undefined, this),
233969
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233970
- color: statusColor,
233971
- bold: true,
233972
- children: summaryLine
233973
- }, undefined, false, undefined, this),
233974
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233975
- dimColor: true,
233976
- children: [
233977
- " [",
233978
- statusLabel,
233979
- "]"
233980
- ]
233981
- }, undefined, true, undefined, this)
234775
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(TerminalImage, {
234776
+ src: data.path,
234777
+ width: data.width,
234778
+ height: data.height,
234779
+ alt: data.alt || basename7(data.path)
234780
+ }, undefined, false, undefined, this)
233982
234781
  ]
233983
- }, undefined, true, undefined, this),
233984
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233985
- marginLeft: 2,
233986
- children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233987
- dimColor: true,
234782
+ }, `${result.toolCallId}-${index}`, true, undefined, this);
234783
+ }
234784
+ } catch {}
234785
+ }
234786
+ const truncatedResult = truncateToolResultWithInfo(result, 4, 400, { verbose: verboseTools });
234787
+ const resultText = indentMultiline(truncatedResult.content, " ");
234788
+ const showExpandHint = !verboseTools && truncatedResult.truncation.wasTruncated;
234789
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234790
+ flexDirection: "column",
234791
+ children: [
234792
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234793
+ children: [
234794
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234795
+ color: iconColor,
233988
234796
  children: [
233989
- "\u21B3 ",
233990
- resultText
234797
+ icon,
234798
+ " "
233991
234799
  ]
233992
- }, undefined, true, undefined, this)
233993
- }, undefined, false, undefined, this),
233994
- showExpandHint && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
233995
- marginLeft: 2,
233996
- children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
233997
- dimColor: true,
233998
- children: "\u21B3 (Ctrl+O for full output)"
234800
+ }, undefined, true, undefined, this),
234801
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234802
+ color: iconColor,
234803
+ bold: true,
234804
+ children: title
233999
234805
  }, undefined, false, undefined, this)
234806
+ ]
234807
+ }, undefined, true, undefined, this),
234808
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234809
+ marginLeft: 1,
234810
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234811
+ dimColor: true,
234812
+ children: [
234813
+ "\u2514 ",
234814
+ resultText
234815
+ ]
234816
+ }, undefined, true, undefined, this)
234817
+ }, undefined, false, undefined, this),
234818
+ showExpandHint && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
234819
+ marginLeft: 1,
234820
+ children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text3, {
234821
+ dimColor: true,
234822
+ children: " (Ctrl+O for full output)"
234000
234823
  }, undefined, false, undefined, this)
234001
- ]
234002
- }, `${result.toolCallId}-${index}`, true, undefined, this);
234003
- })
234004
- ]
234005
- }, undefined, true, undefined, this);
234824
+ }, undefined, false, undefined, this)
234825
+ ]
234826
+ }, `${result.toolCallId}-${index}`, true, undefined, this);
234827
+ })
234828
+ }, undefined, false, undefined, this);
234829
+ }
234830
+ function getToolCallTitle(toolCall) {
234831
+ const name2 = capitalizeToolName(toolCall.name);
234832
+ const context3 = getToolContext(toolCall);
234833
+ return context3 ? `${name2}(${context3})` : name2;
234834
+ }
234835
+ function capitalizeToolName(name2) {
234836
+ const nameMap = {
234837
+ bash: "Bash",
234838
+ read: "Read",
234839
+ write: "Write",
234840
+ glob: "Glob",
234841
+ grep: "Grep",
234842
+ web_fetch: "WebFetch",
234843
+ web_search: "WebSearch",
234844
+ curl: "Curl",
234845
+ display_image: "Image",
234846
+ schedule: "Schedule",
234847
+ submit_feedback: "Feedback",
234848
+ ask_user: "Ask",
234849
+ notion: "Notion",
234850
+ gmail: "Gmail",
234851
+ googledrive: "GoogleDrive",
234852
+ googlecalendar: "GoogleCalendar",
234853
+ linear: "Linear",
234854
+ slack: "Slack"
234855
+ };
234856
+ if (nameMap[name2])
234857
+ return nameMap[name2];
234858
+ return name2.replace(/^connect[_-]/, "").split(/[_-]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
234859
+ }
234860
+ function formatToolParams(toolCall) {
234861
+ const { name: name2, input } = toolCall;
234862
+ const params = [];
234863
+ switch (name2) {
234864
+ case "bash":
234865
+ if (input.command)
234866
+ params.push(`command: ${truncate2(String(input.command), 60)}`);
234867
+ break;
234868
+ case "read":
234869
+ if (input.file_path || input.path)
234870
+ params.push(`file_path: ${truncate2(String(input.file_path || input.path), 60)}`);
234871
+ break;
234872
+ case "write":
234873
+ if (input.file_path || input.path || input.filename)
234874
+ params.push(`file_path: ${truncate2(String(input.file_path || input.path || input.filename), 60)}`);
234875
+ break;
234876
+ case "glob":
234877
+ if (input.pattern)
234878
+ params.push(`pattern: ${truncate2(String(input.pattern), 60)}`);
234879
+ if (input.path)
234880
+ params.push(`path: ${truncate2(String(input.path), 60)}`);
234881
+ break;
234882
+ case "grep":
234883
+ if (input.pattern)
234884
+ params.push(`pattern: ${truncate2(String(input.pattern), 60)}`);
234885
+ if (input.path)
234886
+ params.push(`path: ${truncate2(String(input.path), 60)}`);
234887
+ break;
234888
+ case "web_fetch":
234889
+ case "curl":
234890
+ if (input.url)
234891
+ params.push(`url: ${truncate2(String(input.url), 60)}`);
234892
+ break;
234893
+ case "web_search":
234894
+ if (input.query)
234895
+ params.push(`query: ${truncate2(String(input.query), 60)}`);
234896
+ break;
234897
+ case "schedule":
234898
+ if (input.action)
234899
+ params.push(`action: ${String(input.action)}`);
234900
+ if (input.command)
234901
+ params.push(`command: ${truncate2(String(input.command), 50)}`);
234902
+ break;
234903
+ default: {
234904
+ const entries = Object.entries(input).filter(([_3, v7]) => v7 !== undefined && v7 !== null && v7 !== "").slice(0, 2);
234905
+ for (const [key, value] of entries) {
234906
+ const str2 = typeof value === "string" ? value : JSON.stringify(value);
234907
+ params.push(`${key}: ${truncate2(String(str2), 50)}`);
234908
+ }
234909
+ }
234910
+ }
234911
+ return params;
234006
234912
  }
234007
234913
  function getToolContext(toolCall) {
234008
234914
  const { name: name2, input } = toolCall;
234009
234915
  switch (name2) {
234010
234916
  case "bash":
234011
- return truncate2(String(input.command || ""), 20);
234917
+ return truncate2(String(input.command || ""), 30);
234012
234918
  case "read":
234013
234919
  const path5 = String(input.path || input.file_path || "");
234014
234920
  return basename7(path5) || path5;
@@ -234016,160 +234922,123 @@ function getToolContext(toolCall) {
234016
234922
  const writePath = String(input.filename || input.path || input.file_path || "");
234017
234923
  return basename7(writePath) || writePath;
234018
234924
  case "glob":
234019
- return truncate2(String(input.pattern || ""), 20);
234925
+ return truncate2(String(input.pattern || ""), 30);
234020
234926
  case "grep":
234021
- return truncate2(String(input.pattern || ""), 20);
234927
+ return truncate2(String(input.pattern || ""), 30);
234022
234928
  case "schedule":
234023
234929
  return String(input.action || "");
234024
234930
  case "submit_feedback":
234025
234931
  return String(input.type || "feedback");
234026
234932
  case "web_search":
234027
- return truncate2(String(input.query || ""), 20);
234933
+ return truncate2(String(input.query || ""), 30);
234028
234934
  case "web_fetch":
234029
234935
  case "curl":
234030
234936
  const url = String(input.url || "");
234031
234937
  try {
234032
234938
  return new URL(url).hostname;
234033
234939
  } catch {
234034
- return truncate2(url, 20);
234940
+ return truncate2(url, 30);
234035
234941
  }
234036
234942
  default:
234037
234943
  const action = input.action || input.command || input.operation;
234038
234944
  if (action)
234039
- return truncate2(String(action), 20);
234945
+ return truncate2(String(action), 30);
234040
234946
  return "";
234041
234947
  }
234042
234948
  }
234043
- function getToolDisplayName(toolCall) {
234044
- const { name: name2, input } = toolCall;
234949
+ function truncate2(text, maxLength) {
234950
+ if (text.length <= maxLength)
234951
+ return text;
234952
+ return text.slice(0, maxLength - 3) + "...";
234953
+ }
234954
+ function indentMultiline(text, padding) {
234955
+ const parts = text.split(`
234956
+ `);
234957
+ if (parts.length <= 1)
234958
+ return text;
234959
+ return [parts[0], ...parts.slice(1).map((line) => `${padding}${line}`)].join(`
234960
+ `);
234961
+ }
234962
+ function getToolCategory(name2) {
234045
234963
  switch (name2) {
234046
- case "bash":
234047
- return "bash";
234048
- case "curl":
234049
- case "web_fetch":
234050
- return "fetch";
234964
+ case "grep":
234965
+ case "glob":
234051
234966
  case "web_search":
234052
234967
  return "search";
234053
234968
  case "read":
234054
234969
  return "read";
234055
234970
  case "write":
234056
234971
  return "write";
234057
- case "glob":
234058
- return "glob";
234059
- case "grep":
234060
- return "grep";
234061
- case "display_image":
234062
- return "image";
234063
- case "schedule":
234064
- return "schedule";
234065
- case "submit_feedback":
234066
- return "feedback";
234067
- case "ask_user":
234068
- return "ask";
234069
- case "notion":
234070
- case "gmail":
234071
- case "googledrive":
234072
- case "googlecalendar":
234073
- case "linear":
234074
- case "slack":
234075
- return name2;
234076
- default:
234077
- return name2;
234078
- }
234079
- }
234080
- function formatToolCall(toolCall) {
234081
- const { name: name2, input } = toolCall;
234082
- switch (name2) {
234083
234972
  case "bash":
234084
- return `Running: ${truncate2(String(input.command || ""), 60)}`;
234085
- case "curl":
234086
- return `Fetching: ${truncate2(String(input.url || ""), 60)}`;
234973
+ return "bash";
234087
234974
  case "web_fetch":
234088
- return `Fetching: ${truncate2(String(input.url || ""), 60)}`;
234089
- case "web_search":
234090
- return `Searching: ${truncate2(String(input.query || ""), 60)}`;
234091
- case "read":
234092
- return `Reading: ${truncate2(String(input.path || input.file_path || ""), 60)}`;
234093
- case "write":
234094
- return `Writing: ${truncate2(String(input.filename || input.path || input.file_path || ""), 60)}`;
234095
- case "glob":
234096
- return `Finding: ${truncate2(String(input.pattern || ""), 60)}`;
234097
- case "grep":
234098
- return `Searching: ${truncate2(String(input.pattern || ""), 60)}`;
234099
- case "schedule":
234100
- return formatScheduleCall(input);
234101
- case "submit_feedback":
234102
- return formatFeedbackCall(input);
234103
- case "ask_user": {
234104
- const title = String(input.title || "");
234105
- const question = Array.isArray(input.questions) && input.questions[0]?.question ? String(input.questions[0].question) : "";
234106
- const label = title || question || "asking user";
234107
- return `Asking: ${truncate2(label, 60)}`;
234108
- }
234109
- case "notion":
234110
- return `Notion: ${truncate2(String(input.command || input.action || ""), 60)}`;
234111
- case "gmail":
234112
- return `Gmail: ${truncate2(String(input.command || input.action || ""), 60)}`;
234113
- case "googledrive":
234114
- return `Drive: ${truncate2(String(input.command || input.action || ""), 60)}`;
234115
- case "googlecalendar":
234116
- return `Calendar: ${truncate2(String(input.command || input.action || ""), 60)}`;
234117
- case "linear":
234118
- return `Linear: ${truncate2(String(input.command || input.action || ""), 60)}`;
234119
- case "slack":
234120
- return `Slack: ${truncate2(String(input.command || input.action || ""), 60)}`;
234975
+ case "curl":
234976
+ return "fetch";
234977
+ case "memory_recall":
234978
+ return "memory_recall";
234979
+ case "memory_save":
234980
+ return "memory_save";
234981
+ case "memory_forget":
234982
+ return "memory_forget";
234983
+ case "memory_list":
234984
+ case "memory_stats":
234985
+ case "memory_export":
234986
+ return "memory_query";
234987
+ case "memory_update":
234988
+ case "memory_import":
234989
+ return "memory_update";
234121
234990
  default:
234122
- if (name2.startsWith("connect_") || name2.startsWith("connect-") || name2.includes("_") || name2.includes("-")) {
234123
- const action = String(input.command || input.action || input.operation || "");
234124
- if (action) {
234125
- return `${formatToolDisplayName(name2)}: ${truncate2(action, 50)}`;
234126
- }
234127
- }
234128
- return `${formatToolDisplayName(name2)}: ${truncate2(JSON.stringify(input), 50)}`;
234991
+ return "other";
234129
234992
  }
234130
234993
  }
234131
- function formatToolDisplayName(name2) {
234132
- return name2.replace(/^connect[_-]/, "").replace(/[_-]/g, " ").replace(/\b\w/g, (c6) => c6.toUpperCase());
234133
- }
234134
- function formatScheduleCall(input) {
234135
- const action = String(input.action || "");
234136
- switch (action) {
234137
- case "list":
234138
- return "Listing scheduled tasks";
234139
- case "create":
234140
- const cmd = truncate2(String(input.command || ""), 30);
234141
- const when = input.cron ? `cron ${input.cron}` : String(input.at || "");
234142
- const schedule = when ? ` (${truncate2(String(when), 40)})` : "";
234143
- return `Creating schedule: "${cmd}"${schedule}`;
234144
- case "update":
234145
- return `Updating schedule: ${input.id || "unknown"}`;
234146
- case "delete":
234147
- return `Deleting schedule: ${input.id || "unknown"}`;
234148
- case "pause":
234149
- return `Pausing schedule: ${input.id || "unknown"}`;
234150
- case "resume":
234151
- return `Resuming schedule: ${input.id || "unknown"}`;
234152
- default:
234153
- return `Schedule: ${action || "unknown action"}`;
234994
+ function buildToolCallSummary(toolCalls, isRunning) {
234995
+ const groups = new Map;
234996
+ for (const tc of toolCalls) {
234997
+ const cat = getToolCategory(tc.name);
234998
+ groups.set(cat, (groups.get(cat) || 0) + 1);
234154
234999
  }
234155
- }
234156
- function formatFeedbackCall(input) {
234157
- const type = String(input.type || "feedback");
234158
- const title = truncate2(String(input.title || ""), 40);
234159
- return `Submitting ${type}: ${title}`;
234160
- }
234161
- function truncate2(text, maxLength) {
234162
- if (text.length <= maxLength)
234163
- return text;
234164
- return text.slice(0, maxLength - 3) + "...";
234165
- }
234166
- function indentMultiline(text, padding) {
234167
- const parts = text.split(`
234168
- `);
234169
- if (parts.length <= 1)
234170
- return text;
234171
- return [parts[0], ...parts.slice(1).map((line) => `${padding}${line}`)].join(`
234172
- `);
235000
+ const parts = [];
235001
+ for (const [category, count] of groups) {
235002
+ switch (category) {
235003
+ case "search":
235004
+ parts.push(isRunning ? `Searching for ${count} ${count === 1 ? "pattern" : "patterns"}` : `Searched ${count} ${count === 1 ? "pattern" : "patterns"}`);
235005
+ break;
235006
+ case "read":
235007
+ parts.push(isRunning ? `reading ${count} ${count === 1 ? "file" : "files"}` : `read ${count} ${count === 1 ? "file" : "files"}`);
235008
+ break;
235009
+ case "write":
235010
+ parts.push(isRunning ? `writing ${count} ${count === 1 ? "file" : "files"}` : `wrote ${count} ${count === 1 ? "file" : "files"}`);
235011
+ break;
235012
+ case "bash":
235013
+ parts.push(isRunning ? `running ${count} ${count === 1 ? "command" : "commands"}` : `ran ${count} ${count === 1 ? "command" : "commands"}`);
235014
+ break;
235015
+ case "fetch":
235016
+ parts.push(isRunning ? `fetching ${count} ${count === 1 ? "URL" : "URLs"}` : `fetched ${count} ${count === 1 ? "URL" : "URLs"}`);
235017
+ break;
235018
+ case "memory_recall":
235019
+ parts.push(isRunning ? `recalling ${count} ${count === 1 ? "memory" : "memories"}` : `Recalled ${count} ${count === 1 ? "memory" : "memories"}`);
235020
+ break;
235021
+ case "memory_save":
235022
+ parts.push(isRunning ? `saving ${count} ${count === 1 ? "memory" : "memories"}` : `wrote ${count} ${count === 1 ? "memory" : "memories"}`);
235023
+ break;
235024
+ case "memory_forget":
235025
+ parts.push(isRunning ? `forgetting ${count} ${count === 1 ? "memory" : "memories"}` : `forgot ${count} ${count === 1 ? "memory" : "memories"}`);
235026
+ break;
235027
+ case "memory_query":
235028
+ parts.push(isRunning ? `querying memories` : `queried memories`);
235029
+ break;
235030
+ case "memory_update":
235031
+ parts.push(isRunning ? `updating ${count} ${count === 1 ? "memory" : "memories"}` : `updated ${count} ${count === 1 ? "memory" : "memories"}`);
235032
+ break;
235033
+ default:
235034
+ parts.push(isRunning ? `running ${count} ${count === 1 ? "tool" : "tools"}` : `ran ${count} ${count === 1 ? "tool" : "tools"}`);
235035
+ break;
235036
+ }
235037
+ }
235038
+ if (parts.length > 0) {
235039
+ parts[0] = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);
235040
+ }
235041
+ return parts.join(", ");
234173
235042
  }
234174
235043
 
234175
235044
  // packages/terminal/src/components/messageRender.ts
@@ -237129,6 +237998,17 @@ function formatTime(timestamp) {
237129
237998
  day: "numeric"
237130
237999
  }).toLowerCase();
237131
238000
  }
238001
+ function getBackendLabel(backend) {
238002
+ switch (backend) {
238003
+ case "claude-agent-sdk":
238004
+ return "claude-sdk";
238005
+ case "codex-sdk":
238006
+ return "codex-sdk";
238007
+ case "native":
238008
+ default:
238009
+ return "native";
238010
+ }
238011
+ }
237132
238012
  function AssistantsPanel({
237133
238013
  assistants,
237134
238014
  activeAssistantId,
@@ -237151,9 +238031,14 @@ function AssistantsPanel({
237151
238031
  const [newSystemPrompt, setNewSystemPrompt] = import_react47.useState("");
237152
238032
  const [editingAssistant, setEditingAssistant] = import_react47.useState(null);
237153
238033
  const [editStep, setEditStep] = import_react47.useState("name");
238034
+ const sortedAssistants = import_react47.useMemo(() => {
238035
+ const system = assistants.filter((a5) => a5.isSystem);
238036
+ const user = assistants.filter((a5) => !a5.isSystem);
238037
+ return [...system, ...user];
238038
+ }, [assistants]);
237154
238039
  import_react47.useEffect(() => {
237155
- setSelectedIndex((prev) => Math.min(prev, assistants.length));
237156
- }, [assistants.length]);
238040
+ setSelectedIndex((prev) => Math.min(prev, sortedAssistants.length));
238041
+ }, [sortedAssistants.length]);
237157
238042
  const resetForm = import_react47.useCallback(() => {
237158
238043
  setNewName("");
237159
238044
  setNewDescription("");
@@ -237165,18 +238050,18 @@ function AssistantsPanel({
237165
238050
  setEditStep("name");
237166
238051
  }, []);
237167
238052
  import_react47.useEffect(() => {
237168
- if (mode === "delete-confirm" && (assistants.length === 0 || selectedIndex >= assistants.length)) {
238053
+ if (mode === "delete-confirm" && (sortedAssistants.length === 0 || selectedIndex >= sortedAssistants.length)) {
237169
238054
  setMode("list");
237170
238055
  }
237171
- }, [mode, assistants.length, selectedIndex]);
238056
+ }, [mode, sortedAssistants.length, selectedIndex]);
237172
238057
  import_react47.useEffect(() => {
237173
238058
  if (mode !== "edit")
237174
238059
  return;
237175
- if (!editingAssistant || !assistants.some((a5) => a5.id === editingAssistant.id)) {
238060
+ if (!editingAssistant || !sortedAssistants.some((a5) => a5.id === editingAssistant.id)) {
237176
238061
  resetForm();
237177
238062
  setMode("list");
237178
238063
  }
237179
- }, [mode, editingAssistant, assistants, resetForm]);
238064
+ }, [mode, editingAssistant, sortedAssistants, resetForm]);
237180
238065
  useSafeInput((input, key) => {
237181
238066
  if (mode !== "list")
237182
238067
  return;
@@ -237187,9 +238072,9 @@ function AssistantsPanel({
237187
238072
  return;
237188
238073
  }
237189
238074
  if (input === "e" || input === "E") {
237190
- if (assistants.length > 0 && selectedIndex < assistants.length) {
238075
+ if (sortedAssistants.length > 0 && selectedIndex < sortedAssistants.length) {
237191
238076
  onClearError?.();
237192
- const assistant = assistants[selectedIndex];
238077
+ const assistant = sortedAssistants[selectedIndex];
237193
238078
  setEditingAssistant(assistant);
237194
238079
  setNewName(assistant.name);
237195
238080
  setNewDescription(assistant.description || "");
@@ -237203,7 +238088,11 @@ function AssistantsPanel({
237203
238088
  return;
237204
238089
  }
237205
238090
  if (input === "d" || input === "D") {
237206
- if (assistants.length > 0 && selectedIndex < assistants.length) {
238091
+ if (sortedAssistants.length > 0 && selectedIndex < sortedAssistants.length) {
238092
+ const assistant = sortedAssistants[selectedIndex];
238093
+ if (assistant.isSystem) {
238094
+ return;
238095
+ }
237207
238096
  onClearError?.();
237208
238097
  setMode("delete-confirm");
237209
238098
  }
@@ -237216,24 +238105,24 @@ function AssistantsPanel({
237216
238105
  }
237217
238106
  if (key.return) {
237218
238107
  onClearError?.();
237219
- if (selectedIndex === assistants.length) {
238108
+ if (selectedIndex === sortedAssistants.length) {
237220
238109
  resetForm();
237221
238110
  setMode("create");
237222
238111
  } else {
237223
- onSelect(assistants[selectedIndex].id);
238112
+ onSelect(sortedAssistants[selectedIndex].id);
237224
238113
  }
237225
238114
  return;
237226
238115
  }
237227
238116
  if (key.upArrow) {
237228
- setSelectedIndex((prev) => prev === 0 ? assistants.length : prev - 1);
238117
+ setSelectedIndex((prev) => prev === 0 ? sortedAssistants.length : prev - 1);
237229
238118
  return;
237230
238119
  }
237231
238120
  if (key.downArrow) {
237232
- setSelectedIndex((prev) => prev === assistants.length ? 0 : prev + 1);
238121
+ setSelectedIndex((prev) => prev === sortedAssistants.length ? 0 : prev + 1);
237233
238122
  return;
237234
238123
  }
237235
238124
  const num = parseInt(input, 10);
237236
- if (!isNaN(num) && num >= 1 && num <= assistants.length) {
238125
+ if (!isNaN(num) && num >= 1 && num <= sortedAssistants.length) {
237237
238126
  setSelectedIndex(num - 1);
237238
238127
  return;
237239
238128
  }
@@ -237242,7 +238131,7 @@ function AssistantsPanel({
237242
238131
  if (mode !== "delete-confirm")
237243
238132
  return;
237244
238133
  if (input === "y" || input === "Y") {
237245
- const assistant = assistants[selectedIndex];
238134
+ const assistant = sortedAssistants[selectedIndex];
237246
238135
  if (assistant) {
237247
238136
  setIsSubmitting(true);
237248
238137
  onDelete(assistant.id).finally(() => {
@@ -237819,7 +238708,7 @@ function AssistantsPanel({
237819
238708
  }, undefined, true, undefined, this);
237820
238709
  }
237821
238710
  if (mode === "delete-confirm") {
237822
- const assistant = assistants[selectedIndex];
238711
+ const assistant = sortedAssistants[selectedIndex];
237823
238712
  return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
237824
238713
  flexDirection: "column",
237825
238714
  paddingY: 1,
@@ -237915,18 +238804,20 @@ function AssistantsPanel({
237915
238804
  borderRight: false,
237916
238805
  paddingX: 1,
237917
238806
  children: [
237918
- assistants.length === 0 ? /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
238807
+ sortedAssistants.length === 0 ? /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
237919
238808
  paddingY: 1,
237920
238809
  children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
237921
238810
  dimColor: true,
237922
238811
  children: "No assistants yet. Press n to create one."
237923
238812
  }, undefined, false, undefined, this)
237924
- }, undefined, false, undefined, this) : assistants.map((assistant, index) => {
238813
+ }, undefined, false, undefined, this) : sortedAssistants.map((assistant, index) => {
237925
238814
  const isActive = assistant.id === activeAssistantId;
237926
238815
  const isSelected = index === selectedIndex;
237927
238816
  const modelName = getModelDisplayName(assistant.settings.model);
237928
238817
  const temp = assistant.settings.temperature?.toFixed(1) ?? DEFAULT_TEMPERATURE.toFixed(1);
237929
238818
  const time = formatTime(assistant.updatedAt);
238819
+ const backendLabel = getBackendLabel(assistant.settings.backend);
238820
+ const systemBadge = assistant.isSystem ? "[system] " : "";
237930
238821
  return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
237931
238822
  paddingY: 0,
237932
238823
  children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
@@ -237938,9 +238829,12 @@ function AssistantsPanel({
237938
238829
  " ",
237939
238830
  index + 1,
237940
238831
  ". ",
238832
+ systemBadge,
237941
238833
  assistant.name.padEnd(16),
237942
238834
  " ",
237943
238835
  modelName.padEnd(18),
238836
+ " ",
238837
+ backendLabel.padEnd(10),
237944
238838
  " T:",
237945
238839
  temp,
237946
238840
  " ",
@@ -237953,30 +238847,35 @@ function AssistantsPanel({
237953
238847
  marginTop: 1,
237954
238848
  paddingY: 0,
237955
238849
  children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
237956
- inverse: selectedIndex === assistants.length,
237957
- dimColor: selectedIndex !== assistants.length,
237958
- color: selectedIndex === assistants.length ? "cyan" : undefined,
238850
+ inverse: selectedIndex === sortedAssistants.length,
238851
+ dimColor: selectedIndex !== sortedAssistants.length,
238852
+ color: selectedIndex === sortedAssistants.length ? "cyan" : undefined,
237959
238853
  children: "+ New assistant (n)"
237960
238854
  }, undefined, false, undefined, this)
237961
238855
  }, undefined, false, undefined, this)
237962
238856
  ]
237963
238857
  }, undefined, true, undefined, this),
237964
- assistants.length > 0 && selectedIndex < assistants.length && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
238858
+ sortedAssistants.length > 0 && selectedIndex < sortedAssistants.length && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
237965
238859
  marginTop: 1,
237966
238860
  flexDirection: "column",
237967
238861
  children: [
237968
238862
  /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
237969
238863
  dimColor: true,
237970
- children: assistants[selectedIndex].description || "No description"
238864
+ children: sortedAssistants[selectedIndex].description || "No description"
237971
238865
  }, undefined, false, undefined, this),
237972
- assistants[selectedIndex].settings.systemPromptAddition && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
238866
+ sortedAssistants[selectedIndex].settings.systemPromptAddition && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
237973
238867
  dimColor: true,
237974
238868
  children: [
237975
238869
  "System prompt: ",
237976
- assistants[selectedIndex].settings.systemPromptAddition.slice(0, 50),
237977
- (assistants[selectedIndex].settings.systemPromptAddition?.length || 0) > 50 ? "..." : ""
238870
+ sortedAssistants[selectedIndex].settings.systemPromptAddition.slice(0, 50),
238871
+ (sortedAssistants[selectedIndex].settings.systemPromptAddition?.length || 0) > 50 ? "..." : ""
237978
238872
  ]
237979
- }, undefined, true, undefined, this)
238873
+ }, undefined, true, undefined, this),
238874
+ sortedAssistants[selectedIndex].isSystem && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text3, {
238875
+ dimColor: true,
238876
+ color: "yellow",
238877
+ children: "System assistant \u2014 cannot be deleted"
238878
+ }, undefined, false, undefined, this)
237980
238879
  ]
237981
238880
  }, undefined, true, undefined, this),
237982
238881
  /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
@@ -237985,7 +238884,7 @@ function AssistantsPanel({
237985
238884
  dimColor: true,
237986
238885
  children: [
237987
238886
  "Enter select | e edit | d delete | Esc close | 1-",
237988
- Math.max(1, assistants.length),
238887
+ Math.max(1, sortedAssistants.length),
237989
238888
  " jump"
237990
238889
  ]
237991
238890
  }, undefined, true, undefined, this)
@@ -245733,6 +246632,13 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
245733
246632
  setComposeTo("");
245734
246633
  setComposeStep("to");
245735
246634
  setMode("call-compose");
246635
+ } else if (input === "d" && tab2 === "numbers" && numbers.length > 0) {
246636
+ const target = numbers[selectedIndex];
246637
+ if (target) {
246638
+ const result = manager.setDefaultPhoneNumber(target.number);
246639
+ setStatusMessage(result.success ? result.message : `Error: ${result.message}`);
246640
+ loadData();
246641
+ }
245736
246642
  } else if (input === "r") {
245737
246643
  loadData();
245738
246644
  setStatusMessage("Refreshed");
@@ -245758,6 +246664,7 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
245758
246664
  }, undefined, false, undefined, this)
245759
246665
  }, t9, false, undefined, this))
245760
246666
  }, undefined, false, undefined, this);
246667
+ const headerHint = mode === "sms-compose" || mode === "call-compose" ? "esc cancel" : tab2 === "numbers" ? "q close | 1-5 tabs | s sms | c call | d default | r refresh" : "q close | 1-5 tabs | s sms | c call | r refresh";
245761
246668
  const header = /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
245762
246669
  borderStyle: "round",
245763
246670
  borderColor: "#d4d4d8",
@@ -245777,7 +246684,7 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
245777
246684
  }, undefined, false, undefined, this),
245778
246685
  /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
245779
246686
  color: "gray",
245780
- children: mode === "sms-compose" || mode === "call-compose" ? "esc cancel" : "q close | 1-5 tabs | s sms | c call | r refresh"
246687
+ children: headerHint
245781
246688
  }, undefined, false, undefined, this)
245782
246689
  ]
245783
246690
  }, undefined, true, undefined, this);
@@ -245956,6 +246863,27 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
245956
246863
  }, undefined, false, undefined, this)
245957
246864
  ]
245958
246865
  }, undefined, true, undefined, this),
246866
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246867
+ children: [
246868
+ "Default #: ",
246869
+ status.defaultPhoneNumber ? /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246870
+ color: "cyan",
246871
+ children: status.defaultPhoneNumber
246872
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246873
+ color: "red",
246874
+ children: "Not set"
246875
+ }, undefined, false, undefined, this),
246876
+ " ",
246877
+ status.defaultPhoneNumberSource ? /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246878
+ color: "gray",
246879
+ children: [
246880
+ "(",
246881
+ status.defaultPhoneNumberSource,
246882
+ ")"
246883
+ ]
246884
+ }, undefined, true, undefined, this) : null
246885
+ ]
246886
+ }, undefined, true, undefined, this),
245959
246887
  /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
245960
246888
  children: [
245961
246889
  "Phone #s: ",
@@ -245980,6 +246908,29 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
245980
246908
  /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
245981
246909
  color: "gray",
245982
246910
  children: "Press 's' to send SMS, 'c' to make a call"
246911
+ }, undefined, false, undefined, this),
246912
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246913
+ children: " "
246914
+ }, undefined, false, undefined, this),
246915
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246916
+ bold: true,
246917
+ children: "Quick Setup"
246918
+ }, undefined, false, undefined, this),
246919
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246920
+ color: "gray",
246921
+ children: "1) Set TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN"
246922
+ }, undefined, false, undefined, this),
246923
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246924
+ color: "gray",
246925
+ children: "2) Run /communication sync to import numbers"
246926
+ }, undefined, false, undefined, this),
246927
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246928
+ color: "gray",
246929
+ children: "3) Pick a default number (numbers tab \u2192 'd')"
246930
+ }, undefined, false, undefined, this),
246931
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246932
+ color: "gray",
246933
+ children: "4) Set telephony.webhookUrl for voice calls"
245983
246934
  }, undefined, false, undefined, this)
245984
246935
  ]
245985
246936
  }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
@@ -246047,6 +246998,13 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
246047
246998
  " | ",
246048
246999
  formatRelativeTime6(call.createdAt)
246049
247000
  ]
247001
+ }, undefined, true, undefined, this),
247002
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
247003
+ color: "gray",
247004
+ children: [
247005
+ " | by ",
247006
+ resolveActor(call.assistantId)
247007
+ ]
246050
247008
  }, undefined, true, undefined, this)
246051
247009
  ]
246052
247010
  }, call.id, true, undefined, this))
@@ -246106,6 +247064,13 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
246106
247064
  " | ",
246107
247065
  formatRelativeTime6(msg.createdAt)
246108
247066
  ]
247067
+ }, undefined, true, undefined, this),
247068
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
247069
+ color: "gray",
247070
+ children: [
247071
+ " | by ",
247072
+ resolveActor(msg.assistantId)
247073
+ ]
246109
247074
  }, undefined, true, undefined, this)
246110
247075
  ]
246111
247076
  }, undefined, true, undefined, this),
@@ -246134,7 +247099,7 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
246134
247099
  paddingX: 1,
246135
247100
  children: /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246136
247101
  color: "gray",
246137
- children: "No phone numbers. Run /phone sync to import from Twilio."
247102
+ children: "No phone numbers. Run /communication sync to import from Twilio."
246138
247103
  }, undefined, false, undefined, this)
246139
247104
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
246140
247105
  flexDirection: "column",
@@ -246147,12 +247112,17 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
246147
247112
  caps.push("sms");
246148
247113
  if (num.capabilities.whatsapp)
246149
247114
  caps.push("whatsapp");
247115
+ const isDefault = status?.defaultPhoneNumber === num.number;
246150
247116
  return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
246151
247117
  children: [
246152
247118
  /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246153
247119
  color: i5 === selectedIndex ? "blue" : undefined,
246154
247120
  children: i5 === selectedIndex ? "\u25B8 " : " "
246155
247121
  }, undefined, false, undefined, this),
247122
+ isDefault && /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
247123
+ color: "yellow",
247124
+ children: "\u2605 "
247125
+ }, undefined, false, undefined, this),
246156
247126
  /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text3, {
246157
247127
  bold: i5 === selectedIndex,
246158
247128
  children: num.number
@@ -246170,7 +247140,8 @@ function TelephonyPanel({ manager, assistantLookup, onClose }) {
246170
247140
  children: [
246171
247141
  " [",
246172
247142
  caps.join(", "),
246173
- "]"
247143
+ "]",
247144
+ isDefault ? " default" : ""
246174
247145
  ]
246175
247146
  }, undefined, true, undefined, this)
246176
247147
  ]
@@ -247860,7 +248831,7 @@ var DOCS_SECTIONS = [
247860
248831
  content: [
247861
248832
  "Use /messages for assistant mailbox + email inbox in one panel.",
247862
248833
  "Use /channels to monitor channel streams and cross-assistant conversations.",
247863
- "Use /people and /telephony when those systems are enabled in config.",
248834
+ "Use /people and /communication when those systems are enabled in config.",
247864
248835
  "Use @mentions in channel messages to target specific assistants and avoid duplicate responses."
247865
248836
  ]
247866
248837
  },
@@ -247870,7 +248841,7 @@ var DOCS_SECTIONS = [
247870
248841
  summary: "Dictation and live conversation controls.",
247871
248842
  content: [
247872
248843
  "Use /voice to toggle voice stack status.",
247873
- "Use /listen for persistent dictation mode (pause to submit), and /talk for live conversational mode.",
248844
+ "Use /talk for live conversational mode and /voice to control the stack.",
247874
248845
  "Use /say to synthesize output text aloud.",
247875
248846
  "Push-to-talk is available where configured. During recording, Enter can stop and submit."
247876
248847
  ]
@@ -247908,7 +248879,7 @@ var DOCS_SECTIONS = [
247908
248879
  "Planning: /projects, /plans, /tasks, /schedules",
247909
248880
  "Ops: /jobs, /orders, /logs, /heartbeat",
247910
248881
  "Resources: /wallet, /secrets, /budgets, /cost, /tokens",
247911
- "Collaboration: /assistants, /identity, /messages, /channels, /people, /telephony"
248882
+ "Collaboration: /assistants, /identity, /messages, /channels, /people, /communication"
247912
248883
  ]
247913
248884
  }
247914
248885
  ];
@@ -260142,8 +261113,6 @@ function App2({ cwd: cwd2, version: version4 }) {
260142
261113
  const [processingStartTime, setProcessingStartTime] = import_react81.useState();
260143
261114
  const [currentTurnTokens, setCurrentTurnTokens] = import_react81.useState(0);
260144
261115
  const [lastWorkedFor, setLastWorkedFor] = import_react81.useState();
260145
- const [isListening, setIsListening] = import_react81.useState(false);
260146
- const [listeningDraft, setListeningDraft] = import_react81.useState("");
260147
261116
  const renderedMessageIdsRef = import_react81.useRef(new Set);
260148
261117
  const cachedDisplayMessagesRef = import_react81.useRef(new Map);
260149
261118
  const [pttRecording, setPttRecording] = import_react81.useState(false);
@@ -260198,15 +261167,7 @@ function App2({ cwd: cwd2, version: version4 }) {
260198
261167
  const currentToolCallRef = import_react81.useRef(currentToolCall);
260199
261168
  const hasPendingToolsRef = import_react81.useRef(false);
260200
261169
  const inputRef = import_react81.useRef(null);
260201
- const isListeningRef = import_react81.useRef(isListening);
260202
- const listenLoopRef = import_react81.useRef({
260203
- active: false,
260204
- buffer: "",
260205
- silenceMs: 0,
260206
- manager: null
260207
- });
260208
261170
  const isPanelOpen = showOnboardingPanel || showRecoveryPanel || showConnectorsPanel || showTasksPanel || showSchedulesPanel || showSkillsPanel || showAssistantsPanel || showIdentityPanel || showMemoryPanel || showHooksPanel || showGuardrailsPanel || showBudgetPanel || showModelPanel || showAssistantsRegistryPanel || showConfigPanel || showWebhooksPanel || showChannelsPanel || showPeoplePanel || showTelephonyPanel || showOrdersPanel || showJobsPanel || showDocsPanel || showMessagesPanel || showProjectsPanel || showPlansPanel || showWalletPanel || showSecretsPanel || showWorkspacePanel || showAssistantsDashboard || showSwarmPanel || showLogsPanel || showHeartbeatPanel || showResumePanel;
260209
- const sendListenMessageRef = import_react81.useRef(() => {});
260210
261171
  const processingStartTimeRef = import_react81.useRef(processingStartTime);
260211
261172
  const pendingSendsRef = import_react81.useRef([]);
260212
261173
  const pendingConnectorInstallRef = import_react81.useRef(new Set);
@@ -260280,9 +261241,6 @@ function App2({ cwd: cwd2, version: version4 }) {
260280
261241
  import_react81.useEffect(() => {
260281
261242
  currentToolCallRef.current = currentToolCall;
260282
261243
  }, [currentToolCall]);
260283
- import_react81.useEffect(() => {
260284
- isListeningRef.current = isListening;
260285
- }, [isListening]);
260286
261244
  import_react81.useEffect(() => {
260287
261245
  processingStartTimeRef.current = processingStartTime;
260288
261246
  }, [processingStartTime]);
@@ -260509,108 +261467,6 @@ function App2({ cwd: cwd2, version: version4 }) {
260509
261467
  processingStartTimeRef.current = undefined;
260510
261468
  setCurrentTurnTokens(0);
260511
261469
  }, []);
260512
- const appendTranscript = import_react81.useCallback((base2, chunk) => {
260513
- const trimmed = chunk.trim();
260514
- if (!trimmed)
260515
- return base2;
260516
- if (!base2)
260517
- return trimmed;
260518
- const lastChar = base2[base2.length - 1] || "";
260519
- const needsSpace = lastChar !== " " && !/[.,!?;:]/.test(trimmed[0] || "");
260520
- return `${base2}${needsSpace ? " " : ""}${trimmed}`;
260521
- }, []);
260522
- const updateListenDraft = import_react81.useCallback((next) => {
260523
- setListeningDraft(next);
260524
- inputRef.current?.setValue(next);
260525
- }, []);
260526
- const stopListening = import_react81.useCallback(() => {
260527
- if (!listenLoopRef.current.active)
260528
- return;
260529
- listenLoopRef.current.active = false;
260530
- listenLoopRef.current.silenceMs = 0;
260531
- listenLoopRef.current.buffer = "";
260532
- listenLoopRef.current.manager?.stopListening();
260533
- listenLoopRef.current.manager = null;
260534
- setListeningDraft("");
260535
- setIsListening(false);
260536
- isListeningRef.current = false;
260537
- }, []);
260538
- const startListening = import_react81.useCallback(async () => {
260539
- if (listenLoopRef.current.active)
260540
- return;
260541
- listenLoopRef.current.active = true;
260542
- setIsListening(true);
260543
- isListeningRef.current = true;
260544
- let config;
260545
- try {
260546
- config = currentConfig ?? await loadConfig(cwd2, workspaceBaseDir);
260547
- } catch (err) {
260548
- setError(err instanceof Error ? err.message : "Failed to load config for voice");
260549
- stopListening();
260550
- return;
260551
- }
260552
- if (!listenLoopRef.current.active)
260553
- return;
260554
- const voiceConfig = config.voice;
260555
- if (!voiceConfig) {
260556
- setError("Voice configuration is missing. Add voice settings to config.json.");
260557
- stopListening();
260558
- return;
260559
- }
260560
- if (voiceConfig.stt.provider === "system") {
260561
- setError('System speech-to-text is not available yet. Set voice.stt.provider to "whisper".');
260562
- stopListening();
260563
- return;
260564
- }
260565
- const manager = new VoiceManager({
260566
- ...voiceConfig,
260567
- enabled: true,
260568
- stt: { ...voiceConfig.stt },
260569
- tts: { ...voiceConfig.tts }
260570
- });
260571
- manager.enable();
260572
- listenLoopRef.current.manager = manager;
260573
- listenLoopRef.current.buffer = inputRef.current?.getValue() ?? "";
260574
- listenLoopRef.current.silenceMs = 0;
260575
- updateListenDraft(listenLoopRef.current.buffer);
260576
- const chunkSeconds = 1;
260577
- const silenceThresholdMs = 3500;
260578
- while (listenLoopRef.current.active) {
260579
- let transcript = "";
260580
- try {
260581
- transcript = await manager.listen({ durationSeconds: chunkSeconds });
260582
- } catch (err) {
260583
- if (!listenLoopRef.current.active)
260584
- break;
260585
- setError(err instanceof Error ? err.message : String(err));
260586
- stopListening();
260587
- break;
260588
- }
260589
- if (!listenLoopRef.current.active)
260590
- break;
260591
- const trimmed = transcript.trim();
260592
- if (trimmed) {
260593
- listenLoopRef.current.silenceMs = 0;
260594
- const next = appendTranscript(listenLoopRef.current.buffer, trimmed);
260595
- listenLoopRef.current.buffer = next;
260596
- updateListenDraft(next);
260597
- continue;
260598
- }
260599
- listenLoopRef.current.silenceMs += chunkSeconds * 1000;
260600
- if (listenLoopRef.current.silenceMs >= silenceThresholdMs) {
260601
- const payload = listenLoopRef.current.buffer.trim();
260602
- listenLoopRef.current.buffer = "";
260603
- listenLoopRef.current.silenceMs = 0;
260604
- updateListenDraft("");
260605
- if (payload) {
260606
- sendListenMessageRef.current(payload);
260607
- }
260608
- }
260609
- }
260610
- }, [appendTranscript, cwd2, currentConfig, stopListening, updateListenDraft, workspaceBaseDir]);
260611
- import_react81.useEffect(() => () => {
260612
- stopListening();
260613
- }, [stopListening]);
260614
261470
  const togglePushToTalk = import_react81.useCallback(async () => {
260615
261471
  if (pttTranscribing)
260616
261472
  return;
@@ -261739,11 +262595,7 @@ function App2({ cwd: cwd2, version: version4 }) {
261739
262595
  hasPendingToolsRef.current = hasPendingTools;
261740
262596
  }, [hasPendingTools]);
261741
262597
  const isBusy = isProcessing || hasPendingTools;
261742
- const listenHints = import_react81.useMemo(() => {
261743
- if (!isListening)
261744
- return [];
261745
- return ["listening...", "pause 3s to send", "[ctrl+l] stop"];
261746
- }, [isListening]);
262598
+ const stopHint = isBusy && !activeAskQuestion ? "[esc] to stop" : null;
261747
262599
  const pttStatus = voiceState?.isTalking ? "talking" : pttTranscribing ? "transcribing" : pttRecording ? "recording" : null;
261748
262600
  const showWelcome = messages2.length === 0 && !isProcessing;
261749
262601
  const renderWidth = columns ? Math.max(1, columns - 2) : undefined;
@@ -261781,25 +262633,12 @@ function App2({ cwd: cwd2, version: version4 }) {
261781
262633
  const streamingMessages = streamingTrim.messages;
261782
262634
  const streamingTrimmed = streamingTrim.trimmed;
261783
262635
  const streamingLineCount = import_react81.useMemo(() => estimateDisplayMessagesLines(streamingMessages, renderWidth), [streamingMessages, renderWidth]);
261784
- const listeningDraftMessages = import_react81.useMemo(() => {
261785
- if (!isListening && !listeningDraft.trim())
261786
- return [];
261787
- const content = listeningDraft.trim() || "Listening...";
261788
- const draftMessage = {
261789
- id: "listening-draft",
261790
- role: "user",
261791
- content,
261792
- timestamp: Date.now()
261793
- };
261794
- return buildDisplayMessages([draftMessage], MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth });
261795
- }, [isListening, listeningDraft, wrapChars, renderWidth]);
261796
262636
  const activityTrim = import_react81.useMemo(() => {
261797
262637
  const activityBudget = Math.max(4, dynamicBudget - streamingLineCount);
261798
262638
  return trimActivityLogByLines(activityLog, wrapChars, renderWidth, activityBudget);
261799
262639
  }, [activityLog, wrapChars, renderWidth, dynamicBudget, streamingLineCount]);
261800
- const hasListeningDraft = listeningDraftMessages.length > 0;
261801
- const combinedStreamingMessages = hasListeningDraft ? [...streamingMessages, ...listeningDraftMessages] : streamingMessages;
261802
- const showDynamicPanel = isProcessing || hasListeningDraft || activityTrim.entries.length > 0;
262640
+ const combinedStreamingMessages = streamingMessages;
262641
+ const showDynamicPanel = isProcessing || activityTrim.entries.length > 0;
261803
262642
  import_react81.useEffect(() => {
261804
262643
  if (!isBusy && activeQueue.length > 0 && activeInline.length === 0) {
261805
262644
  processQueue();
@@ -261838,10 +262677,6 @@ function App2({ cwd: cwd2, version: version4 }) {
261838
262677
  return true;
261839
262678
  }, [finalizeResponse2, resetTurnState]);
261840
262679
  useSafeInput((input, key) => {
261841
- if (isListeningRef.current && key.ctrl && input === "l") {
261842
- stopListening();
261843
- return;
261844
- }
261845
262680
  if (key.ctrl && input === "r") {
261846
262681
  togglePushToTalk();
261847
262682
  return;
@@ -261955,19 +262790,6 @@ function App2({ cwd: cwd2, version: version4 }) {
261955
262790
  return;
261956
262791
  }
261957
262792
  }
261958
- if (trimmedInput.startsWith("/listen")) {
261959
- const arg = trimmedInput.slice(7).trim().toLowerCase();
261960
- if (arg === "stop" || arg === "off") {
261961
- stopListening();
261962
- return;
261963
- }
261964
- if (listenLoopRef.current.active) {
261965
- stopListening();
261966
- return;
261967
- }
261968
- startListening();
261969
- return;
261970
- }
261971
262793
  if (trimmedInput === "/exit") {
261972
262794
  registry2.closeAll();
261973
262795
  exit();
@@ -262444,16 +263266,8 @@ function App2({ cwd: cwd2, version: version4 }) {
262444
263266
  activeSessionId,
262445
263267
  submitAskAnswer,
262446
263268
  clearPendingSend,
262447
- startListening,
262448
- stopListening,
262449
263269
  stopActiveProcessing
262450
263270
  ]);
262451
- import_react81.useEffect(() => {
262452
- sendListenMessageRef.current = (text) => {
262453
- const mode = isProcessingRef.current ? "inline" : "normal";
262454
- handleSubmit(text, mode);
262455
- };
262456
- }, [handleSubmit]);
262457
263271
  if (isInitializing && !showRecoveryPanel && !showOnboardingPanel) {
262458
263272
  return /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(Box_default, {
262459
263273
  flexDirection: "column",
@@ -263885,12 +264699,18 @@ You are in a group channel with other assistants and people. Respond in #${chann
263885
264699
  const telephonyManager = activeSession?.client.getTelephonyManager?.();
263886
264700
  if (!telephonyManager) {
263887
264701
  return /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(CloseOnAnyKeyPanel, {
263888
- message: "Telephony is not enabled. Set telephony.enabled: true in config.",
264702
+ message: "Communication is not enabled. Set telephony.enabled: true in config.",
263889
264703
  onClose: () => setShowTelephonyPanel(false)
263890
264704
  }, undefined, false, undefined, this);
263891
264705
  }
264706
+ const assistantManager = activeSession?.client.getAssistantManager?.();
264707
+ const assistantLookup = assistantManager ? assistantManager.listAssistants().reduce((acc, assistant) => {
264708
+ acc[assistant.id] = assistant.name;
264709
+ return acc;
264710
+ }, {}) : undefined;
263892
264711
  return /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(TelephonyPanel, {
263893
264712
  manager: telephonyManager,
264713
+ assistantLookup,
263894
264714
  onClose: () => setShowTelephonyPanel(false)
263895
264715
  }, undefined, false, undefined, this);
263896
264716
  }
@@ -264225,7 +265045,6 @@ ${msg.body || msg.preview}`);
264225
265045
  isAskingUser: Boolean(activeAskQuestion),
264226
265046
  askPlaceholder,
264227
265047
  allowBlankAnswer: activeAskQuestion?.required === false,
264228
- footerHints: listenHints,
264229
265048
  assistantName: identityInfo?.assistant?.name || undefined,
264230
265049
  isRecording: pttRecording,
264231
265050
  recordingStatus: pttStatus,
@@ -264247,6 +265066,13 @@ ${msg.body || msg.preview}`);
264247
265066
  processingStartTime,
264248
265067
  verboseTools,
264249
265068
  gitBranch
265069
+ }, undefined, false, undefined, this),
265070
+ stopHint && /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(Box_default, {
265071
+ marginLeft: 2,
265072
+ children: /* @__PURE__ */ jsx_dev_runtime49.jsxDEV(Text3, {
265073
+ dimColor: true,
265074
+ children: stopHint
265075
+ }, undefined, false, undefined, this)
264250
265076
  }, undefined, false, undefined, this)
264251
265077
  ]
264252
265078
  }, undefined, true, undefined, this);
@@ -264694,7 +265520,7 @@ Interactive Mode:
264694
265520
  // packages/terminal/src/index.tsx
264695
265521
  var jsx_dev_runtime50 = __toESM(require_jsx_dev_runtime(), 1);
264696
265522
  setRuntime(bunRuntime);
264697
- var VERSION4 = "1.1.38";
265523
+ var VERSION4 = "1.1.39";
264698
265524
  var SYNC_START = "\x1B[?2026h";
264699
265525
  var SYNC_END = "\x1B[?2026l";
264700
265526
  function enableSynchronizedOutput() {
@@ -264836,4 +265662,4 @@ export {
264836
265662
  main
264837
265663
  };
264838
265664
 
264839
- //# debugId=1D41C8BF19F4334564756E2164756E21
265665
+ //# debugId=F39728574A99291764756E2164756E21