@hasna/assistants 0.6.31 → 0.6.34

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
@@ -28328,12 +28328,12 @@ __export(exports_anthropic, {
28328
28328
  AnthropicClient: () => AnthropicClient
28329
28329
  });
28330
28330
  import { readFileSync as readFileSync4, existsSync as existsSync8 } from "fs";
28331
- import { homedir as homedir8 } from "os";
28332
- import { join as join13 } from "path";
28331
+ import { homedir as homedir9 } from "os";
28332
+ import { join as join14 } from "path";
28333
28333
  function loadApiKeyFromSecrets() {
28334
28334
  const envHome = process.env.HOME || process.env.USERPROFILE;
28335
- const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir8();
28336
- const secretsPath = join13(homeDir, ".secrets");
28335
+ const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
28336
+ const secretsPath = join14(homeDir, ".secrets");
28337
28337
  if (existsSync8(secretsPath)) {
28338
28338
  try {
28339
28339
  const content = readFileSync4(secretsPath, "utf-8");
@@ -36578,7 +36578,7 @@ var import_react29 = __toESM(require_react(), 1);
36578
36578
 
36579
36579
  // packages/core/src/agent/loop.ts
36580
36580
  init_src();
36581
- import { join as join20 } from "path";
36581
+ import { join as join21 } from "path";
36582
36582
 
36583
36583
  // packages/core/src/agent/context.ts
36584
36584
  init_src();
@@ -36645,9 +36645,14 @@ class AgentContext {
36645
36645
  return message;
36646
36646
  }
36647
36647
  extractPdfAttachment(content) {
36648
+ if (!content)
36649
+ return null;
36648
36650
  try {
36649
36651
  const parsed = JSON.parse(content);
36650
36652
  if (parsed && parsed.__pdf_attachment__ === true) {
36653
+ if (!parsed.data || typeof parsed.data !== "string") {
36654
+ return null;
36655
+ }
36651
36656
  return {
36652
36657
  type: "pdf",
36653
36658
  source: {
@@ -36682,7 +36687,8 @@ class AgentContext {
36682
36687
  this.messages = this.messages.filter((msg) => {
36683
36688
  if (msg.role !== "system")
36684
36689
  return true;
36685
- return !predicate(msg.content);
36690
+ const content = msg.content ?? "";
36691
+ return !predicate(content);
36686
36692
  });
36687
36693
  }
36688
36694
  getMessages() {
@@ -36698,15 +36704,18 @@ class AgentContext {
36698
36704
  if (this.messages.length <= this.maxMessages) {
36699
36705
  return;
36700
36706
  }
36701
- const systemMessages = this.messages.filter((m) => m.role === "system");
36707
+ let systemMessages = this.messages.filter((m) => m.role === "system");
36702
36708
  const nonSystemMessages = this.messages.filter((m) => m.role !== "system");
36703
- const targetCount = this.maxMessages - systemMessages.length;
36704
- let recentMessages = nonSystemMessages.slice(-targetCount);
36709
+ if (systemMessages.length > this.maxMessages) {
36710
+ systemMessages = systemMessages.slice(-this.maxMessages);
36711
+ }
36712
+ const targetCount = Math.max(0, this.maxMessages - systemMessages.length);
36713
+ let recentMessages = targetCount > 0 ? nonSystemMessages.slice(-targetCount) : [];
36705
36714
  while (recentMessages.length > 0 && recentMessages[0].toolResults) {
36706
36715
  const firstIndex = nonSystemMessages.indexOf(recentMessages[0]);
36707
36716
  if (firstIndex > 0) {
36708
36717
  recentMessages = nonSystemMessages.slice(firstIndex - 1);
36709
- if (recentMessages.length > targetCount + 1) {
36718
+ if (recentMessages.length > targetCount + 1 && targetCount > 0) {
36710
36719
  recentMessages = recentMessages.slice(-(targetCount + 1));
36711
36720
  }
36712
36721
  } else {
@@ -36868,7 +36877,33 @@ class ContextManager {
36868
36877
  summarizedCount: 0
36869
36878
  };
36870
36879
  }
36871
- const summary = await this.summarizer.summarize(toSummarize);
36880
+ let summary = "";
36881
+ try {
36882
+ summary = await this.summarizer.summarize(toSummarize);
36883
+ } catch {
36884
+ const tokens = this.tokenCounter.countMessages(messages);
36885
+ this.state.totalTokens = tokens;
36886
+ this.state.messageCount = messages.length;
36887
+ return {
36888
+ messages,
36889
+ summarized: false,
36890
+ tokensBefore: tokens,
36891
+ tokensAfter: tokens,
36892
+ summarizedCount: 0
36893
+ };
36894
+ }
36895
+ if (!summary.trim()) {
36896
+ const tokens = this.tokenCounter.countMessages(messages);
36897
+ this.state.totalTokens = tokens;
36898
+ this.state.messageCount = messages.length;
36899
+ return {
36900
+ messages,
36901
+ summarized: false,
36902
+ tokensBefore: tokens,
36903
+ tokensAfter: tokens,
36904
+ summarizedCount: 0
36905
+ };
36906
+ }
36872
36907
  const summaryMessage = {
36873
36908
  id: generateId(),
36874
36909
  role: "system",
@@ -36903,7 +36938,8 @@ ${summary}`,
36903
36938
  };
36904
36939
  }
36905
36940
  isSummaryMessage(message) {
36906
- return message.role === "system" && message.content.trim().startsWith(SUMMARY_TAG);
36941
+ const content = message.content ?? "";
36942
+ return message.role === "system" && content.trim().startsWith(SUMMARY_TAG);
36907
36943
  }
36908
36944
  partitionMessages(messages) {
36909
36945
  const keepRecent = Math.max(0, this.config.keepRecentMessages);
@@ -37047,7 +37083,8 @@ class HybridSummarizer {
37047
37083
  const paths = new Set;
37048
37084
  const pathRegex = /(?:\.?\/|[A-Za-z]:\\)[\w\-.\/\\]+\.[A-Za-z0-9]+/g;
37049
37085
  for (const msg of messages) {
37050
- const matches = msg.content.match(pathRegex);
37086
+ const content = msg.content ?? "";
37087
+ const matches = content.match(pathRegex);
37051
37088
  if (matches) {
37052
37089
  for (const match of matches) {
37053
37090
  paths.add(match.replace(/\\/g, "/"));
@@ -37059,7 +37096,8 @@ class HybridSummarizer {
37059
37096
  extractCommands(messages) {
37060
37097
  const commands = new Set;
37061
37098
  for (const msg of messages) {
37062
- const lines = msg.content.split(`
37099
+ const content = msg.content ?? "";
37100
+ const lines = content.split(`
37063
37101
  `);
37064
37102
  for (const line of lines) {
37065
37103
  const trimmed = line.trim();
@@ -37084,7 +37122,8 @@ class HybridSummarizer {
37084
37122
  extractErrors(messages) {
37085
37123
  const errors = new Set;
37086
37124
  for (const msg of messages) {
37087
- const lines = msg.content.split(`
37125
+ const content = msg.content ?? "";
37126
+ const lines = content.split(`
37088
37127
  `);
37089
37128
  for (const line of lines) {
37090
37129
  if (/error|failed|exception/i.test(line)) {
@@ -38516,12 +38555,10 @@ async function isPathSafe(targetPath, operation, options = {}) {
38516
38555
  for (const protectedPath of PROTECTED_PATHS) {
38517
38556
  const expanded = protectedPath.replace("~", home);
38518
38557
  if (resolved.startsWith(expanded)) {
38519
- if (operation === "write" || operation === "delete") {
38520
- return {
38521
- safe: false,
38522
- reason: `Cannot ${operation} protected path: ${protectedPath}`
38523
- };
38524
- }
38558
+ return {
38559
+ safe: false,
38560
+ reason: `Cannot ${operation} protected path: ${protectedPath}`
38561
+ };
38525
38562
  }
38526
38563
  }
38527
38564
  try {
@@ -38596,9 +38633,21 @@ class FilesystemTools {
38596
38633
  };
38597
38634
  static readExecutor = async (input) => {
38598
38635
  const baseCwd = input.cwd || process.cwd();
38599
- const path = resolve3(baseCwd, input.path);
38636
+ const rawPath = String(input.path || "").trim();
38637
+ if (!rawPath) {
38638
+ throw new ToolExecutionError("File path is required", {
38639
+ toolName: "read",
38640
+ toolInput: input,
38641
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
38642
+ recoverable: false,
38643
+ retryable: false,
38644
+ suggestion: "Provide a valid file path."
38645
+ });
38646
+ }
38647
+ const path = resolve3(baseCwd, rawPath);
38600
38648
  const offset = (input.offset || 1) - 1;
38601
- const limit = input.limit;
38649
+ const limitRaw = input.limit;
38650
+ const limit = typeof limitRaw === "number" && limitRaw > 0 ? Math.floor(limitRaw) : undefined;
38602
38651
  try {
38603
38652
  const safety = await isPathSafe(path, "read", { cwd: baseCwd });
38604
38653
  if (!safety.safe) {
@@ -38704,6 +38753,16 @@ class FilesystemTools {
38704
38753
  const filename = input.filename || input.path;
38705
38754
  const content = input.content;
38706
38755
  const baseCwd = input.cwd || process.cwd();
38756
+ if (typeof content !== "string") {
38757
+ throw new ToolExecutionError("Content must be a string", {
38758
+ toolName: "write",
38759
+ toolInput: input,
38760
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
38761
+ recoverable: false,
38762
+ retryable: false,
38763
+ suggestion: "Provide string content to write."
38764
+ });
38765
+ }
38707
38766
  const scriptsFolder = getScriptsFolder(baseCwd, input.sessionId);
38708
38767
  if (!filename || !filename.trim()) {
38709
38768
  throw new ToolExecutionError("Filename is required", {
@@ -38798,13 +38857,55 @@ class FilesystemTools {
38798
38857
  }
38799
38858
  };
38800
38859
  static globExecutor = async (input) => {
38801
- const pattern = input.pattern;
38860
+ const pattern = String(input.pattern || "").trim();
38802
38861
  const baseCwd = input.cwd || process.cwd();
38803
38862
  const searchPath = resolve3(baseCwd, input.path || ".");
38804
38863
  try {
38864
+ if (!pattern) {
38865
+ throw new ToolExecutionError("Pattern is required", {
38866
+ toolName: "glob",
38867
+ toolInput: input,
38868
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
38869
+ recoverable: false,
38870
+ retryable: false
38871
+ });
38872
+ }
38873
+ const safety = await isPathSafe(searchPath, "read", { cwd: baseCwd });
38874
+ if (!safety.safe) {
38875
+ getSecurityLogger().log({
38876
+ eventType: "path_violation",
38877
+ severity: "high",
38878
+ details: {
38879
+ tool: "glob",
38880
+ path: searchPath,
38881
+ reason: safety.reason || "Blocked path"
38882
+ },
38883
+ sessionId: input.sessionId || "unknown"
38884
+ });
38885
+ throw new ToolExecutionError(safety.reason || "Blocked path", {
38886
+ toolName: "glob",
38887
+ toolInput: input,
38888
+ code: ErrorCodes.TOOL_PERMISSION_DENIED,
38889
+ recoverable: false,
38890
+ retryable: false
38891
+ });
38892
+ }
38893
+ const validated = await validatePath(searchPath, {
38894
+ allowSymlinks: true,
38895
+ allowedPaths: [baseCwd, searchPath]
38896
+ });
38897
+ if (!validated.valid) {
38898
+ throw new ToolExecutionError(validated.error || "Invalid path", {
38899
+ toolName: "glob",
38900
+ toolInput: input,
38901
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
38902
+ recoverable: false,
38903
+ retryable: false
38904
+ });
38905
+ }
38805
38906
  const glob = new Glob(pattern);
38806
38907
  const matches = [];
38807
- for await (const file of glob.scan({ cwd: searchPath })) {
38908
+ for await (const file of glob.scan({ cwd: validated.resolved })) {
38808
38909
  matches.push(file);
38809
38910
  if (matches.length >= 1000)
38810
38911
  break;
@@ -38857,18 +38958,60 @@ class FilesystemTools {
38857
38958
  }
38858
38959
  };
38859
38960
  static grepExecutor = async (input) => {
38860
- const pattern = input.pattern;
38961
+ const pattern = String(input.pattern || "").trim();
38861
38962
  const baseCwd = input.cwd || process.cwd();
38862
38963
  const searchPath = resolve3(baseCwd, input.path || ".");
38863
38964
  const globPattern = input.glob || "**/*";
38864
38965
  const caseSensitive = input.caseSensitive || false;
38865
38966
  try {
38967
+ if (!pattern) {
38968
+ throw new ToolExecutionError("Pattern is required", {
38969
+ toolName: "grep",
38970
+ toolInput: input,
38971
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
38972
+ recoverable: false,
38973
+ retryable: false
38974
+ });
38975
+ }
38976
+ const safety = await isPathSafe(searchPath, "read", { cwd: baseCwd });
38977
+ if (!safety.safe) {
38978
+ getSecurityLogger().log({
38979
+ eventType: "path_violation",
38980
+ severity: "high",
38981
+ details: {
38982
+ tool: "grep",
38983
+ path: searchPath,
38984
+ reason: safety.reason || "Blocked path"
38985
+ },
38986
+ sessionId: input.sessionId || "unknown"
38987
+ });
38988
+ throw new ToolExecutionError(safety.reason || "Blocked path", {
38989
+ toolName: "grep",
38990
+ toolInput: input,
38991
+ code: ErrorCodes.TOOL_PERMISSION_DENIED,
38992
+ recoverable: false,
38993
+ retryable: false
38994
+ });
38995
+ }
38996
+ const validated = await validatePath(searchPath, {
38997
+ allowSymlinks: true,
38998
+ allowedPaths: [baseCwd, searchPath]
38999
+ });
39000
+ if (!validated.valid) {
39001
+ throw new ToolExecutionError(validated.error || "Invalid path", {
39002
+ toolName: "grep",
39003
+ toolInput: input,
39004
+ code: ErrorCodes.VALIDATION_OUT_OF_RANGE,
39005
+ recoverable: false,
39006
+ retryable: false
39007
+ });
39008
+ }
38866
39009
  const flags = caseSensitive ? "" : "i";
38867
39010
  const regex2 = new RegExp(pattern, flags);
38868
39011
  const results = [];
38869
39012
  const glob = new Glob(globPattern);
38870
- for await (const file of glob.scan({ cwd: searchPath })) {
38871
- const filePath = join4(searchPath, file);
39013
+ for await (const file of glob.scan({ cwd: validated.resolved })) {
39014
+ const filePath = join4(validated.resolved, file);
38872
39015
  try {
38873
39016
  const content = await Bun.file(filePath).text();
38874
39017
  const lines = content.split(`
@@ -39895,7 +40038,10 @@ function computeNextRun(schedule, fromTime) {
39895
40038
  if (schedule.schedule.kind === "once") {
39896
40039
  if (!schedule.schedule.at)
39897
40040
  return;
39898
- return parseScheduledTime(schedule.schedule.at, validTimezone);
40041
+ const next = parseScheduledTime(schedule.schedule.at, validTimezone);
40042
+ if (!next || next <= fromTime)
40043
+ return;
40044
+ return next;
39899
40045
  }
39900
40046
  if (schedule.schedule.kind === "cron") {
39901
40047
  if (!schedule.schedule.cron)
@@ -39911,6 +40057,8 @@ async function getDueSchedules(cwd2, nowTime) {
39911
40057
  return false;
39912
40058
  if (!schedule.nextRunAt)
39913
40059
  return false;
40060
+ if (!Number.isFinite(schedule.nextRunAt))
40061
+ return false;
39914
40062
  return schedule.nextRunAt <= nowTime;
39915
40063
  });
39916
40064
  }
@@ -40026,6 +40174,9 @@ function parseDateTime(value) {
40026
40174
  if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day) || !Number.isFinite(hour) || !Number.isFinite(minute) || !Number.isFinite(second)) {
40027
40175
  return null;
40028
40176
  }
40177
+ if (month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
40178
+ return null;
40179
+ }
40029
40180
  return { year, month, day, hour, minute, second };
40030
40181
  }
40031
40182
  function hasTimeZoneOffset(value) {
@@ -40164,11 +40315,21 @@ class SchedulerTool {
40164
40315
  const id = String(input.id || "").trim();
40165
40316
  if (!id)
40166
40317
  return "Error: id is required.";
40318
+ let nextRunAt;
40319
+ if (action === "resume") {
40320
+ const schedule = await readSchedule(cwd2, id);
40321
+ if (!schedule)
40322
+ return `Schedule ${id} not found.`;
40323
+ nextRunAt = computeNextRun(schedule, Date.now());
40324
+ if (!nextRunAt) {
40325
+ return `Error: unable to compute next run for schedule ${id}.`;
40326
+ }
40327
+ }
40167
40328
  const updated = await updateSchedule(cwd2, id, (s) => ({
40168
40329
  ...s,
40169
40330
  status: action === "pause" ? "paused" : "active",
40170
40331
  updatedAt: Date.now(),
40171
- nextRunAt: action === "resume" ? computeNextRun(s, Date.now()) : s.nextRunAt
40332
+ nextRunAt: action === "resume" ? nextRunAt : s.nextRunAt
40172
40333
  }));
40173
40334
  if (!updated)
40174
40335
  return `Schedule ${id} not found.`;
@@ -40653,6 +40814,7 @@ class HookExecutor {
40653
40814
  return null;
40654
40815
  try {
40655
40816
  const proc = Bun.spawn(["bash", "-c", hook.command], {
40817
+ cwd: input.cwd || process.cwd(),
40656
40818
  stdin: "pipe",
40657
40819
  stdout: "pipe",
40658
40820
  stderr: "pipe"
@@ -41187,11 +41349,11 @@ function summarizeConversation(messages) {
41187
41349
  if (msg.role === "user") {
41188
41350
  if (msg.toolResults && msg.toolResults.length > 0) {
41189
41351
  for (const result of msg.toolResults) {
41190
- const content = result.content.slice(0, 500);
41352
+ const content = (result.content || "").slice(0, 500);
41191
41353
  summary.push(`[Tool Result - ${result.toolName || "unknown"}]: ${content}`);
41192
41354
  }
41193
41355
  } else {
41194
- summary.push(`User: ${msg.content.slice(0, 300)}`);
41356
+ summary.push(`User: ${(msg.content ?? "").slice(0, 300)}`);
41195
41357
  }
41196
41358
  } else if (msg.role === "assistant") {
41197
41359
  if (msg.toolCalls && msg.toolCalls.length > 0) {
@@ -41200,8 +41362,9 @@ function summarizeConversation(messages) {
41200
41362
  summary.push(`[Tool Call - ${call.name}]: ${input}`);
41201
41363
  }
41202
41364
  }
41203
- if (msg.content.trim()) {
41204
- summary.push(`Assistant: ${msg.content.slice(0, 300)}`);
41365
+ const assistantContent = msg.content ?? "";
41366
+ if (assistantContent.trim()) {
41367
+ summary.push(`Assistant: ${assistantContent.slice(0, 300)}`);
41205
41368
  }
41206
41369
  }
41207
41370
  }
@@ -41559,8 +41722,8 @@ ${stderr}`;
41559
41722
  }
41560
41723
  }
41561
41724
  // packages/core/src/commands/builtin.ts
41562
- import { join as join12 } from "path";
41563
- import { homedir as homedir7, platform as platform2, release, arch } from "os";
41725
+ import { join as join13 } from "path";
41726
+ import { homedir as homedir8, platform as platform2, release, arch } from "os";
41564
41727
  import { existsSync as existsSync7, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
41565
41728
  init_src();
41566
41729
 
@@ -41664,23 +41827,28 @@ function hasProjectNameConflict(projects, name) {
41664
41827
 
41665
41828
  // packages/core/src/projects/context.ts
41666
41829
  import { readFile as readFile3 } from "fs/promises";
41667
- import { resolve as resolve4 } from "path";
41830
+ import { homedir as homedir7 } from "os";
41831
+ import { resolve as resolve4, join as join12 } from "path";
41668
41832
  var DEFAULT_MAX_FILE_BYTES = 12000;
41833
+ function singleLine(value) {
41834
+ return value.replace(/[\r\n]+/g, " ").trim();
41835
+ }
41669
41836
  function formatPlan(plan) {
41670
41837
  const lines = [];
41671
- lines.push(`- ${plan.title} (${plan.steps.length} steps)`);
41838
+ lines.push(`- ${singleLine(plan.title)} (${plan.steps.length} steps)`);
41672
41839
  for (const step of plan.steps) {
41673
- lines.push(` - [${step.status}] ${step.text}`);
41840
+ lines.push(` - [${step.status}] ${singleLine(step.text)}`);
41674
41841
  }
41675
41842
  return lines.join(`
41676
41843
  `);
41677
41844
  }
41678
41845
  function normalizeEntryLabel(entry) {
41679
- return entry.label ? entry.label.trim() : entry.value.trim();
41846
+ return entry.label ? singleLine(entry.label) : singleLine(entry.value);
41680
41847
  }
41681
41848
  async function renderFileEntry(entry, options) {
41682
41849
  const rawPath = entry.value.trim();
41683
- const resolved = resolve4(options.cwd, rawPath);
41850
+ const expandedPath = rawPath === "~" ? homedir7() : rawPath.startsWith("~/") ? join12(homedir7(), rawPath.slice(2)) : rawPath;
41851
+ const resolved = resolve4(options.cwd, expandedPath);
41684
41852
  const validation = await validatePath(resolved, { allowedPaths: [options.cwd] });
41685
41853
  if (!validation.valid) {
41686
41854
  return `- File: ${rawPath} (unavailable: ${validation.error || "invalid path"})`;
@@ -41812,7 +41980,7 @@ function splitArgs(input) {
41812
41980
  args.push(current);
41813
41981
  return args;
41814
41982
  }
41815
- function singleLine(value) {
41983
+ function singleLine2(value) {
41816
41984
  return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
41817
41985
  }
41818
41986
 
@@ -42651,12 +42819,12 @@ No context entries for project "${project.name}".
42651
42819
  return { handled: true };
42652
42820
  }
42653
42821
  let output = `
42654
- **Context Entries (${singleLine(project.name)})**
42822
+ **Context Entries (${singleLine2(project.name)})**
42655
42823
 
42656
42824
  `;
42657
42825
  for (const entry of project.context) {
42658
- const label = entry.label ? ` (${singleLine(entry.label)})` : "";
42659
- output += `- ${entry.id} [${entry.type}] ${singleLine(entry.value)}${label}
42826
+ const label = entry.label ? ` (${singleLine2(entry.label)})` : "";
42827
+ output += `- ${entry.id} [${entry.type}] ${singleLine2(entry.value)}${label}
42660
42828
  `;
42661
42829
  }
42662
42830
  context.emit("text", output);
@@ -42803,7 +42971,7 @@ No projects found. Use /projects new <name>.
42803
42971
  `;
42804
42972
  for (const project of projects) {
42805
42973
  const marker = project.id === activeId ? "*" : " ";
42806
- output += `${marker} ${singleLine(project.name)} (${project.id})
42974
+ output += `${marker} ${singleLine2(project.name)} (${project.id})
42807
42975
  `;
42808
42976
  }
42809
42977
  context.emit("text", output);
@@ -42865,13 +43033,13 @@ No projects found. Use /projects new <name>.
42865
43033
  return { handled: true };
42866
43034
  }
42867
43035
  let output = `
42868
- **Project: ${singleLine(project.name)}**
43036
+ **Project: ${singleLine2(project.name)}**
42869
43037
 
42870
43038
  `;
42871
43039
  output += `ID: ${project.id}
42872
43040
  `;
42873
43041
  if (project.description) {
42874
- output += `Description: ${singleLine(project.description)}
43042
+ output += `Description: ${singleLine2(project.description)}
42875
43043
  `;
42876
43044
  }
42877
43045
  output += `Context entries: ${project.context.length}
@@ -42997,11 +43165,11 @@ No plans for project "${project.name}".
42997
43165
  return { handled: true };
42998
43166
  }
42999
43167
  let output = `
43000
- **Plans (${singleLine(project.name)})**
43168
+ **Plans (${singleLine2(project.name)})**
43001
43169
 
43002
43170
  `;
43003
43171
  for (const plan of project.plans) {
43004
- output += `- ${plan.id} ${singleLine(plan.title)} (${plan.steps.length} steps)
43172
+ output += `- ${plan.id} ${singleLine2(plan.title)} (${plan.steps.length} steps)
43005
43173
  `;
43006
43174
  }
43007
43175
  context.emit("text", output);
@@ -43057,7 +43225,7 @@ No plans for project "${project.name}".
43057
43225
  return { handled: true };
43058
43226
  }
43059
43227
  let output = `
43060
- **Plan: ${singleLine(plan.title)}**
43228
+ **Plan: ${singleLine2(plan.title)}**
43061
43229
 
43062
43230
  `;
43063
43231
  output += `ID: ${plan.id}
@@ -43067,7 +43235,7 @@ No plans for project "${project.name}".
43067
43235
  `;
43068
43236
  } else {
43069
43237
  for (const step of plan.steps) {
43070
- output += `- ${step.id} [${step.status}] ${singleLine(step.text)}
43238
+ output += `- ${step.id} [${step.status}] ${singleLine2(step.text)}
43071
43239
  `;
43072
43240
  }
43073
43241
  }
@@ -43500,9 +43668,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
43500
43668
  content: "",
43501
43669
  handler: async (args, context) => {
43502
43670
  const configPaths = [
43503
- join12(context.cwd, ".assistants", "config.json"),
43504
- join12(context.cwd, ".assistants", "config.local.json"),
43505
- join12(getConfigDir(), "config.json")
43671
+ join13(context.cwd, ".assistants", "config.json"),
43672
+ join13(context.cwd, ".assistants", "config.local.json"),
43673
+ join13(getConfigDir(), "config.json")
43506
43674
  ];
43507
43675
  let message = `
43508
43676
  **Configuration**
@@ -43516,13 +43684,13 @@ Format the summary as a brief bullet-point list. This summary will replace the c
43516
43684
  `;
43517
43685
  }
43518
43686
  const envHome = process.env.HOME || process.env.USERPROFILE;
43519
- const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir7();
43687
+ const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir8();
43520
43688
  message += `
43521
43689
  **Commands Directories:**
43522
43690
  `;
43523
- message += ` - Project: ${join12(context.cwd, ".assistants", "commands")}
43691
+ message += ` - Project: ${join13(context.cwd, ".assistants", "commands")}
43524
43692
  `;
43525
- message += ` - Global: ${join12(homeDir, ".assistants", "commands")}
43693
+ message += ` - Global: ${join13(homeDir, ".assistants", "commands")}
43526
43694
  `;
43527
43695
  context.emit("text", message);
43528
43696
  context.emit("done");
@@ -43538,7 +43706,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
43538
43706
  selfHandled: true,
43539
43707
  content: "",
43540
43708
  handler: async (args, context) => {
43541
- const commandsDir = join12(context.cwd, ".assistants", "commands");
43709
+ const commandsDir = join13(context.cwd, ".assistants", "commands");
43542
43710
  mkdirSync4(commandsDir, { recursive: true });
43543
43711
  const exampleCommand = `---
43544
43712
  name: reflect
@@ -43554,7 +43722,7 @@ Please summarize the last interaction and suggest 2-3 next steps.
43554
43722
  - Focus on clarity
43555
43723
  - Ask a follow-up question if needed
43556
43724
  `;
43557
- const examplePath = join12(commandsDir, "reflect.md");
43725
+ const examplePath = join13(commandsDir, "reflect.md");
43558
43726
  if (!existsSync7(examplePath)) {
43559
43727
  writeFileSync5(examplePath, exampleCommand);
43560
43728
  }
@@ -44720,13 +44888,13 @@ function validateToolCalls(toolCalls, tools) {
44720
44888
 
44721
44889
  // packages/core/src/voice/utils.ts
44722
44890
  import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
44723
- import { homedir as homedir9 } from "os";
44724
- import { join as join14 } from "path";
44891
+ import { homedir as homedir10 } from "os";
44892
+ import { join as join15 } from "path";
44725
44893
  import { spawnSync } from "child_process";
44726
44894
  function loadApiKeyFromSecrets2(key) {
44727
44895
  const envHome = process.env.HOME || process.env.USERPROFILE;
44728
- const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
44729
- const secretsPath = join14(homeDir, ".secrets");
44896
+ const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir10();
44897
+ const secretsPath = join15(homeDir, ".secrets");
44730
44898
  if (!existsSync9(secretsPath))
44731
44899
  return;
44732
44900
  try {
@@ -44800,7 +44968,7 @@ class SystemSTT {
44800
44968
  // packages/core/src/voice/tts.ts
44801
44969
  import { spawnSync as spawnSync2 } from "child_process";
44802
44970
  import { tmpdir as tmpdir2 } from "os";
44803
- import { join as join15 } from "path";
44971
+ import { join as join16 } from "path";
44804
44972
  import { readFileSync as readFileSync6, unlinkSync as unlinkSync2 } from "fs";
44805
44973
  class ElevenLabsTTS {
44806
44974
  apiKey;
@@ -44904,7 +45072,7 @@ class SystemTTS {
44904
45072
  if (!say) {
44905
45073
  throw new Error('System TTS not available: missing "say" command.');
44906
45074
  }
44907
- const output = join15(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
45075
+ const output = join16(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
44908
45076
  const args = [];
44909
45077
  if (this.voiceId) {
44910
45078
  args.push("-v", this.voiceId);
@@ -44926,7 +45094,7 @@ class SystemTTS {
44926
45094
  }
44927
45095
  const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
44928
45096
  if (espeak) {
44929
- const output = join15(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
45097
+ const output = join16(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
44930
45098
  const args = ["-w", output];
44931
45099
  if (this.voiceId) {
44932
45100
  args.push("-v", this.voiceId);
@@ -44953,14 +45121,14 @@ class SystemTTS {
44953
45121
  // packages/core/src/voice/player.ts
44954
45122
  import { spawn } from "child_process";
44955
45123
  import { tmpdir as tmpdir3 } from "os";
44956
- import { join as join16 } from "path";
45124
+ import { join as join17 } from "path";
44957
45125
  import { unlink as unlink4, writeFileSync as writeFileSync6 } from "fs";
44958
45126
  class AudioPlayer {
44959
45127
  currentProcess = null;
44960
45128
  playing = false;
44961
45129
  async play(audio, options = {}) {
44962
45130
  const format = options.format ?? "mp3";
44963
- const tempFile = join16(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
45131
+ const tempFile = join17(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
44964
45132
  writeFileSync6(tempFile, Buffer.from(audio));
44965
45133
  const player = this.resolvePlayer(format);
44966
45134
  if (!player) {
@@ -45028,7 +45196,7 @@ class AudioPlayer {
45028
45196
  // packages/core/src/voice/recorder.ts
45029
45197
  import { spawn as spawn2 } from "child_process";
45030
45198
  import { tmpdir as tmpdir4 } from "os";
45031
- import { join as join17 } from "path";
45199
+ import { join as join18 } from "path";
45032
45200
  import { readFileSync as readFileSync7, unlink as unlink5 } from "fs";
45033
45201
  class AudioRecorder {
45034
45202
  currentProcess = null;
@@ -45039,7 +45207,7 @@ class AudioRecorder {
45039
45207
  const duration = options.durationSeconds ?? 5;
45040
45208
  const sampleRate = options.sampleRate ?? 16000;
45041
45209
  const channels = options.channels ?? 1;
45042
- const output = join17(tmpdir4(), `assistants-record-${Date.now()}.wav`);
45210
+ const output = join18(tmpdir4(), `assistants-record-${Date.now()}.wav`);
45043
45211
  const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
45044
45212
  if (!recorder) {
45045
45213
  throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
@@ -45233,13 +45401,13 @@ class VoiceManager {
45233
45401
  init_src();
45234
45402
  import { existsSync as existsSync11 } from "fs";
45235
45403
  import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile7, rm as rm2 } from "fs/promises";
45236
- import { join as join19 } from "path";
45404
+ import { join as join20 } from "path";
45237
45405
 
45238
45406
  // packages/core/src/identity/identity-manager.ts
45239
45407
  init_src();
45240
45408
  import { existsSync as existsSync10 } from "fs";
45241
45409
  import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile6, rm } from "fs/promises";
45242
- import { join as join18 } from "path";
45410
+ import { join as join19 } from "path";
45243
45411
  var DEFAULT_PROFILE = {
45244
45412
  displayName: "Assistant",
45245
45413
  timezone: "UTC",
@@ -45269,19 +45437,19 @@ class IdentityManager {
45269
45437
  this.basePath = basePath;
45270
45438
  }
45271
45439
  get identitiesRoot() {
45272
- return join18(this.basePath, "assistants", this.assistantId, "identities");
45440
+ return join19(this.basePath, "assistants", this.assistantId, "identities");
45273
45441
  }
45274
45442
  get indexPath() {
45275
- return join18(this.identitiesRoot, "index.json");
45443
+ return join19(this.identitiesRoot, "index.json");
45276
45444
  }
45277
45445
  get activePath() {
45278
- return join18(this.identitiesRoot, "active.json");
45446
+ return join19(this.identitiesRoot, "active.json");
45279
45447
  }
45280
45448
  identityPath(id) {
45281
- return join18(this.identitiesRoot, `${id}.json`);
45449
+ return join19(this.identitiesRoot, `${id}.json`);
45282
45450
  }
45283
45451
  assistantConfigPath() {
45284
- return join18(this.basePath, "assistants", this.assistantId, "config.json");
45452
+ return join19(this.basePath, "assistants", this.assistantId, "config.json");
45285
45453
  }
45286
45454
  async initialize() {
45287
45455
  await mkdir4(this.identitiesRoot, { recursive: true });
@@ -45465,16 +45633,16 @@ class AssistantManager {
45465
45633
  this.basePath = basePath;
45466
45634
  }
45467
45635
  get assistantsRoot() {
45468
- return join19(this.basePath, "assistants");
45636
+ return join20(this.basePath, "assistants");
45469
45637
  }
45470
45638
  get indexPath() {
45471
- return join19(this.assistantsRoot, "index.json");
45639
+ return join20(this.assistantsRoot, "index.json");
45472
45640
  }
45473
45641
  get activePath() {
45474
- return join19(this.basePath, "active.json");
45642
+ return join20(this.basePath, "active.json");
45475
45643
  }
45476
45644
  assistantConfigPath(id) {
45477
- return join19(this.assistantsRoot, id, "config.json");
45645
+ return join20(this.assistantsRoot, id, "config.json");
45478
45646
  }
45479
45647
  async initialize() {
45480
45648
  await mkdir5(this.assistantsRoot, { recursive: true });
@@ -45528,7 +45696,7 @@ class AssistantManager {
45528
45696
  if (!this.assistants.has(id)) {
45529
45697
  throw new Error(`Assistant ${id} not found`);
45530
45698
  }
45531
- await rm2(join19(this.assistantsRoot, id), { recursive: true, force: true });
45699
+ await rm2(join20(this.assistantsRoot, id), { recursive: true, force: true });
45532
45700
  this.assistants.delete(id);
45533
45701
  await this.removeFromIndex(id);
45534
45702
  if (this.activeId === id) {
@@ -45594,7 +45762,7 @@ class AssistantManager {
45594
45762
  }
45595
45763
  }
45596
45764
  async persistAssistant(assistant) {
45597
- const dir = join19(this.assistantsRoot, assistant.id);
45765
+ const dir = join20(this.assistantsRoot, assistant.id);
45598
45766
  await mkdir5(dir, { recursive: true });
45599
45767
  await writeFile7(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
45600
45768
  }
@@ -46436,7 +46604,7 @@ ${content.trim()}`);
46436
46604
  const heartbeatConfig = this.buildHeartbeatConfig(this.config);
46437
46605
  if (!heartbeatConfig)
46438
46606
  return;
46439
- const statePath = join20(getConfigDir(), "state", `${this.sessionId}.json`);
46607
+ const statePath = join21(getConfigDir(), "state", `${this.sessionId}.json`);
46440
46608
  this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
46441
46609
  this.heartbeatPersistence = new StatePersistence(statePath);
46442
46610
  this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
@@ -46485,7 +46653,7 @@ ${content.trim()}`);
46485
46653
  async startEnergySystem() {
46486
46654
  if (!this.config || this.config.energy?.enabled === false)
46487
46655
  return;
46488
- const statePath = join20(getConfigDir(), "energy", "state.json");
46656
+ const statePath = join21(getConfigDir(), "energy", "state.json");
46489
46657
  this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
46490
46658
  await this.energyManager.initialize();
46491
46659
  this.refreshEnergyEffects();
@@ -46662,7 +46830,7 @@ ${this.identityContext}`);
46662
46830
  for (const msg of messages) {
46663
46831
  if (msg.role !== "system")
46664
46832
  continue;
46665
- const content = msg.content.trim();
46833
+ const content = (msg.content ?? "").trim();
46666
46834
  if (!content)
46667
46835
  continue;
46668
46836
  if (parts.includes(content))
@@ -46731,7 +46899,7 @@ ${this.identityContext}`);
46731
46899
  return null;
46732
46900
  const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
46733
46901
  const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
46734
- const persistPath = config.heartbeat?.persistPath ?? join20(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
46902
+ const persistPath = config.heartbeat?.persistPath ?? join21(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
46735
46903
  return {
46736
46904
  intervalMs,
46737
46905
  staleThresholdMs,
@@ -46828,17 +46996,17 @@ init_src();
46828
46996
 
46829
46997
  // packages/core/src/logger.ts
46830
46998
  import { existsSync as existsSync12, mkdirSync as mkdirSync8, appendFileSync, readdirSync as readdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
46831
- import { join as join21 } from "path";
46999
+ import { join as join22 } from "path";
46832
47000
  class Logger {
46833
47001
  logDir;
46834
47002
  logFile;
46835
47003
  sessionId;
46836
47004
  constructor(sessionId, basePath) {
46837
47005
  this.sessionId = sessionId;
46838
- this.logDir = join21(basePath || getConfigDir(), "logs");
47006
+ this.logDir = join22(basePath || getConfigDir(), "logs");
46839
47007
  this.ensureDir(this.logDir);
46840
47008
  const date = new Date().toISOString().split("T")[0];
46841
- this.logFile = join21(this.logDir, `${date}.log`);
47009
+ this.logFile = join22(this.logDir, `${date}.log`);
46842
47010
  }
46843
47011
  ensureDir(dir) {
46844
47012
  if (!existsSync12(dir)) {
@@ -46882,9 +47050,9 @@ class SessionStorage {
46882
47050
  constructor(sessionId, basePath, assistantId) {
46883
47051
  this.sessionId = sessionId;
46884
47052
  const root = basePath || getConfigDir();
46885
- this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
47053
+ this.sessionsDir = assistantId ? join22(root, "assistants", assistantId, "sessions") : join22(root, "sessions");
46886
47054
  this.ensureDir(this.sessionsDir);
46887
- this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
47055
+ this.sessionFile = join22(this.sessionsDir, `${sessionId}.json`);
46888
47056
  }
46889
47057
  ensureDir(dir) {
46890
47058
  if (!existsSync12(dir)) {
@@ -46910,7 +47078,7 @@ class SessionStorage {
46910
47078
  }
46911
47079
  static getActiveAssistantId() {
46912
47080
  try {
46913
- const activePath = join21(getConfigDir(), "active.json");
47081
+ const activePath = join22(getConfigDir(), "active.json");
46914
47082
  if (!existsSync12(activePath))
46915
47083
  return null;
46916
47084
  const raw = readFileSync8(activePath, "utf-8");
@@ -46924,12 +47092,12 @@ class SessionStorage {
46924
47092
  const root = getConfigDir();
46925
47093
  const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
46926
47094
  if (resolvedId) {
46927
- const assistantDir = join21(root, "assistants", resolvedId, "sessions");
47095
+ const assistantDir = join22(root, "assistants", resolvedId, "sessions");
46928
47096
  if (existsSync12(assistantDir)) {
46929
47097
  return assistantDir;
46930
47098
  }
46931
47099
  }
46932
- return join21(root, "sessions");
47100
+ return join22(root, "sessions");
46933
47101
  }
46934
47102
  static listSessions(assistantId) {
46935
47103
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
@@ -46941,7 +47109,7 @@ class SessionStorage {
46941
47109
  if (!file.endsWith(".json"))
46942
47110
  continue;
46943
47111
  try {
46944
- const filePath = join21(sessionsDir, file);
47112
+ const filePath = join22(sessionsDir, file);
46945
47113
  const stat = Bun.file(filePath);
46946
47114
  const content = JSON.parse(readFileSync8(filePath, "utf-8"));
46947
47115
  sessions.push({
@@ -46961,7 +47129,7 @@ class SessionStorage {
46961
47129
  }
46962
47130
  static loadSession(sessionId, assistantId) {
46963
47131
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
46964
- const sessionFile = join21(sessionsDir, `${sessionId}.json`);
47132
+ const sessionFile = join22(sessionsDir, `${sessionId}.json`);
46965
47133
  try {
46966
47134
  if (!existsSync12(sessionFile))
46967
47135
  return null;
@@ -46975,15 +47143,15 @@ function initAssistantsDir() {
46975
47143
  const baseDir = getConfigDir();
46976
47144
  const dirs = [
46977
47145
  baseDir,
46978
- join21(baseDir, "logs"),
46979
- join21(baseDir, "assistants"),
46980
- join21(baseDir, "shared", "skills"),
46981
- join21(baseDir, "commands"),
46982
- join21(baseDir, "temp"),
46983
- join21(baseDir, "heartbeats"),
46984
- join21(baseDir, "state"),
46985
- join21(baseDir, "energy"),
46986
- join21(baseDir, "migration")
47146
+ join22(baseDir, "logs"),
47147
+ join22(baseDir, "assistants"),
47148
+ join22(baseDir, "shared", "skills"),
47149
+ join22(baseDir, "commands"),
47150
+ join22(baseDir, "temp"),
47151
+ join22(baseDir, "heartbeats"),
47152
+ join22(baseDir, "state"),
47153
+ join22(baseDir, "energy"),
47154
+ join22(baseDir, "migration")
46987
47155
  ];
46988
47156
  for (const dir of dirs) {
46989
47157
  if (!existsSync12(dir)) {
@@ -47543,6 +47711,13 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
47543
47711
  return skills.filter((skill) => skill.name.toLowerCase().startsWith(search));
47544
47712
  }, [value, autocompleteMode, skills]);
47545
47713
  const autocompleteItems = autocompleteMode === "skill" ? filteredSkills : filteredCommands;
47714
+ import_react23.useEffect(() => {
47715
+ if (autocompleteItems.length === 0) {
47716
+ setSelectedIndex(0);
47717
+ return;
47718
+ }
47719
+ setSelectedIndex((prev) => Math.min(prev, autocompleteItems.length - 1));
47720
+ }, [autocompleteItems.length]);
47546
47721
  use_input_default((input, key) => {
47547
47722
  if (key.tab) {
47548
47723
  if (autocompleteItems.length > 0) {
@@ -47632,7 +47807,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
47632
47807
  const visibleSkills = getVisibleItems(filteredSkills);
47633
47808
  const visibleCommands = getVisibleItems(filteredCommands);
47634
47809
  const { stdout } = use_stdout_default();
47635
- const terminalWidth = stdout?.columns ?? 80;
47810
+ const terminalWidth = Math.max(10, (stdout?.columns ?? 80) - 2);
47636
47811
  const lines = value.split(`
47637
47812
  `);
47638
47813
  const lineCount = lines.length;
@@ -47642,16 +47817,15 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
47642
47817
  children: [
47643
47818
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
47644
47819
  children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
47645
- dimColor: true,
47646
- children: "\u2500".repeat(terminalWidth)
47820
+ color: "#666666",
47821
+ children: "-".repeat(terminalWidth)
47647
47822
  }, undefined, false, undefined, this)
47648
47823
  }, undefined, false, undefined, this),
47649
47824
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
47650
47825
  paddingY: 0,
47651
47826
  children: [
47652
47827
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
47653
- dimColor: isProcessing,
47654
- color: isProcessing ? undefined : "cyan",
47828
+ color: isProcessing ? "gray" : "cyan",
47655
47829
  children: "> "
47656
47830
  }, undefined, false, undefined, this),
47657
47831
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
@@ -47668,7 +47842,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
47668
47842
  lineCount > 1 && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
47669
47843
  marginLeft: 2,
47670
47844
  children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
47671
- dimColor: true,
47845
+ color: "gray",
47672
47846
  children: [
47673
47847
  "(",
47674
47848
  lineCount,
@@ -47678,8 +47852,8 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
47678
47852
  }, undefined, false, undefined, this),
47679
47853
  /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
47680
47854
  children: /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Text, {
47681
- dimColor: true,
47682
- children: "\u2500".repeat(terminalWidth)
47855
+ color: "#666666",
47856
+ children: "-".repeat(terminalWidth)
47683
47857
  }, undefined, false, undefined, this)
47684
47858
  }, undefined, false, undefined, this),
47685
47859
  isProcessing && /* @__PURE__ */ jsx_dev_runtime.jsxDEV(Box_default, {
@@ -48228,7 +48402,7 @@ function formatMarkdownTables(text, maxWidth) {
48228
48402
  function parseTableRow(line) {
48229
48403
  const trimmed = line.trim();
48230
48404
  const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
48231
- return withoutEdges.split("|").map((cell) => cell.trim());
48405
+ return withoutEdges.split("|").map((cell) => cell.replace(/[\r\n]+/g, " ").trim());
48232
48406
  }
48233
48407
  function renderTable(header, rows, maxWidth) {
48234
48408
  const colCount = Math.max(header.length, ...rows.map((r) => r.length));
@@ -48523,7 +48697,7 @@ function truncateToolResult(toolResult, maxLines = 15, maxChars = 3000) {
48523
48697
  if (content.length > maxChars) {
48524
48698
  content = content.slice(0, maxChars) + "...";
48525
48699
  }
48526
- return prefix + content.trim();
48700
+ return prefix + content.trimEnd();
48527
48701
  }
48528
48702
  function formatToolResultNicely(toolName, content, isError) {
48529
48703
  if (isError) {
@@ -49575,7 +49749,7 @@ function ProcessingIndicator({
49575
49749
  var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
49576
49750
  function WelcomeBanner({ version, model, directory }) {
49577
49751
  const homeDir = process.env.HOME || "";
49578
- const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
49752
+ const displayDir = homeDir && directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
49579
49753
  return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
49580
49754
  flexDirection: "column",
49581
49755
  marginBottom: 1,
@@ -49661,7 +49835,7 @@ function formatSessionTime(timestamp) {
49661
49835
  }
49662
49836
  function formatPath(cwd2) {
49663
49837
  const home = process.env.HOME || "";
49664
- if (cwd2.startsWith(home)) {
49838
+ if (home && cwd2.startsWith(home)) {
49665
49839
  return "~" + cwd2.slice(home.length);
49666
49840
  }
49667
49841
  return cwd2;
@@ -49867,7 +50041,8 @@ function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
49867
50041
  continue;
49868
50042
  }
49869
50043
  if (msg.role === "assistant") {
49870
- const rendered = renderMarkdown(content, { maxWidth: options?.maxWidth });
50044
+ const assistantWidth = options?.maxWidth ? Math.max(1, options.maxWidth - 2) : undefined;
50045
+ const rendered = renderMarkdown(content, { maxWidth: assistantWidth });
49871
50046
  const renderedLines = rendered.split(`
49872
50047
  `);
49873
50048
  if (renderedLines.length <= chunkLines) {
@@ -49889,7 +50064,8 @@ function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
49889
50064
  }
49890
50065
  continue;
49891
50066
  }
49892
- const lines = wrapTextLines(content, wrapChars);
50067
+ const effectiveWrap = msg.role === "user" ? Math.max(1, wrapChars - 2) : wrapChars;
50068
+ const lines = wrapTextLines(content, effectiveWrap);
49893
50069
  if (lines.length <= chunkLines) {
49894
50070
  display.push(msg);
49895
50071
  continue;
@@ -50964,7 +51140,7 @@ function formatStreamEvent(chunk) {
50964
51140
 
50965
51141
  // packages/terminal/src/index.tsx
50966
51142
  var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
50967
- var VERSION3 = "0.6.31";
51143
+ var VERSION3 = "0.6.34";
50968
51144
  process.env.ASSISTANTS_VERSION ??= VERSION3;
50969
51145
  function parseArgs(argv) {
50970
51146
  const args = argv.slice(2);
@@ -51120,4 +51296,4 @@ if (options.print !== null) {
51120
51296
  });
51121
51297
  }
51122
51298
 
51123
- //# debugId=656AEF3B850A245D64756E2164756E21
51299
+ //# debugId=83E7550093AA9F2D64756E2164756E21