@hasna/assistants 0.6.14 → 0.6.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -27290,14 +27290,14 @@ var exports_anthropic = {};
27290
27290
  __export(exports_anthropic, {
27291
27291
  AnthropicClient: () => AnthropicClient
27292
27292
  });
27293
- import { readFileSync as readFileSync2, existsSync as existsSync5 } from "fs";
27293
+ import { readFileSync as readFileSync2, existsSync as existsSync7 } from "fs";
27294
27294
  import { homedir as homedir8 } from "os";
27295
27295
  import { join as join11 } from "path";
27296
27296
  function loadApiKeyFromSecrets() {
27297
27297
  const envHome = process.env.HOME || process.env.USERPROFILE;
27298
27298
  const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir8();
27299
27299
  const secretsPath = join11(homeDir, ".secrets");
27300
- if (existsSync5(secretsPath)) {
27300
+ if (existsSync7(secretsPath)) {
27301
27301
  try {
27302
27302
  const content = readFileSync2(secretsPath, "utf-8");
27303
27303
  const match = content.match(/export\s+ANTHROPIC_API_KEY\s*=\s*["']?([^"'\n]+)["']?/);
@@ -36989,6 +36989,34 @@ function validateBashCommand(command) {
36989
36989
  function killProcess(proc) {
36990
36990
  proc.kill();
36991
36991
  }
36992
+ function stripQuotedSegments(input) {
36993
+ let result = "";
36994
+ let quote = null;
36995
+ let escaped = false;
36996
+ for (let i = 0;i < input.length; i += 1) {
36997
+ const char = input[i];
36998
+ if (quote) {
36999
+ if (quote === '"' && !escaped && char === "\\") {
37000
+ escaped = true;
37001
+ continue;
37002
+ }
37003
+ if (!escaped && char === quote) {
37004
+ quote = null;
37005
+ result += char;
37006
+ continue;
37007
+ }
37008
+ escaped = false;
37009
+ continue;
37010
+ }
37011
+ if (char === '"' || char === "'") {
37012
+ quote = char;
37013
+ result += char;
37014
+ continue;
37015
+ }
37016
+ result += char;
37017
+ }
37018
+ return result;
37019
+ }
36992
37020
 
36993
37021
  class BashTool {
36994
37022
  static tool = {
@@ -37109,6 +37137,7 @@ class BashTool {
37109
37137
  const cwd2 = input.cwd || process.cwd();
37110
37138
  const timeout = input.timeout || 30000;
37111
37139
  const commandForChecks = command.replace(/\s*2>&1\s*/g, " ");
37140
+ const commandSansQuotes = stripQuotedSegments(commandForChecks);
37112
37141
  const securityCheck = validateBashCommand(commandForChecks);
37113
37142
  if (!securityCheck.valid) {
37114
37143
  getSecurityLogger().log({
@@ -37131,7 +37160,7 @@ class BashTool {
37131
37160
  });
37132
37161
  }
37133
37162
  for (const pattern of this.BLOCKED_PATTERNS) {
37134
- if (pattern.test(commandForChecks)) {
37163
+ if (pattern.test(commandSansQuotes)) {
37135
37164
  getSecurityLogger().log({
37136
37165
  eventType: "blocked_command",
37137
37166
  severity: "high",
@@ -37220,6 +37249,7 @@ ${stderr || stdout}`.trim(), {
37220
37249
 
37221
37250
  // packages/core/src/tools/filesystem.ts
37222
37251
  import { join as join4, resolve as resolve3, dirname as dirname2, sep } from "path";
37252
+ import { existsSync as existsSync2 } from "fs";
37223
37253
  init_errors();
37224
37254
  var {Glob } = globalThis.Bun;
37225
37255
 
@@ -37308,6 +37338,10 @@ async function isPathSafe(targetPath, operation, options = {}) {
37308
37338
  // packages/core/src/tools/filesystem.ts
37309
37339
  var currentSessionId = "default";
37310
37340
  function getScriptsFolder(cwd2) {
37341
+ const legacyDir = join4(cwd2, ".oldpal");
37342
+ if (existsSync2(legacyDir)) {
37343
+ return join4(legacyDir, "scripts", currentSessionId);
37344
+ }
37311
37345
  return join4(getProjectConfigDir(cwd2), "scripts", currentSessionId);
37312
37346
  }
37313
37347
  function isInScriptsFolder(path2, cwd2) {
@@ -37443,13 +37477,13 @@ class FilesystemTools {
37443
37477
  };
37444
37478
  static writeTool = {
37445
37479
  name: "write",
37446
- description: "Write content to a file. RESTRICTED: Can only write to .assistants/scripts/{session}/ in the current project. Provide a filename and it will be saved under the scripts folder.",
37480
+ description: "Write content to a file. RESTRICTED: Can only write to the project scripts folder (.oldpal/scripts/{session} or .assistants/scripts/{session}). Provide a filename and it will be saved under the scripts folder.",
37447
37481
  parameters: {
37448
37482
  type: "object",
37449
37483
  properties: {
37450
37484
  filename: {
37451
37485
  type: "string",
37452
- description: "The filename to write to (will be saved in .assistants/scripts)"
37486
+ description: "The filename to write to (saved in the project scripts folder)"
37453
37487
  },
37454
37488
  content: {
37455
37489
  type: "string",
@@ -37487,7 +37521,7 @@ class FilesystemTools {
37487
37521
  code: ErrorCodes.TOOL_PERMISSION_DENIED,
37488
37522
  recoverable: false,
37489
37523
  retryable: false,
37490
- suggestion: "Write only within the .assistants/scripts/ folder."
37524
+ suggestion: "Write only within the project scripts folder."
37491
37525
  });
37492
37526
  }
37493
37527
  try {
@@ -38230,7 +38264,7 @@ function isPrivateIPv4(octets) {
38230
38264
  // packages/core/src/tools/feedback.ts
38231
38265
  init_src();
38232
38266
  import { join as join5 } from "path";
38233
- import { mkdirSync, writeFileSync } from "fs";
38267
+ import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
38234
38268
  function normalizeTags(value) {
38235
38269
  if (Array.isArray(value)) {
38236
38270
  const tags = value.map((t) => String(t).trim()).filter(Boolean);
@@ -38242,8 +38276,16 @@ function normalizeTags(value) {
38242
38276
  }
38243
38277
  return;
38244
38278
  }
38245
- function saveFeedbackEntry(entry) {
38246
- const feedbackDir = join5(getConfigDir(), "feedback");
38279
+ function resolveFeedbackDir(cwd2) {
38280
+ const baseCwd = cwd2 && cwd2.trim().length > 0 ? cwd2 : process.cwd();
38281
+ const legacyDir = join5(baseCwd, ".oldpal");
38282
+ if (existsSync3(legacyDir)) {
38283
+ return join5(legacyDir, "feedback");
38284
+ }
38285
+ return join5(getConfigDir(), "feedback");
38286
+ }
38287
+ function saveFeedbackEntry(entry, cwd2) {
38288
+ const feedbackDir = resolveFeedbackDir(cwd2);
38247
38289
  mkdirSync(feedbackDir, { recursive: true });
38248
38290
  const path2 = join5(feedbackDir, `${entry.id}.json`);
38249
38291
  writeFileSync(path2, JSON.stringify(entry, null, 2));
@@ -38330,7 +38372,7 @@ class FeedbackTool {
38330
38372
  static executor = async (input) => {
38331
38373
  try {
38332
38374
  const entry = buildEntry(input, { source: input.source || "tool" });
38333
- const { path: path2 } = saveFeedbackEntry(entry);
38375
+ const { path: path2 } = saveFeedbackEntry(entry, typeof input.cwd === "string" ? input.cwd : undefined);
38334
38376
  return `Feedback saved locally.
38335
38377
  ID: ${entry.id}
38336
38378
  Path: ${path2}`;
@@ -38802,7 +38844,7 @@ class SchedulerTool {
38802
38844
 
38803
38845
  // packages/core/src/tools/image.ts
38804
38846
  init_src();
38805
- import { existsSync as existsSync2, writeFileSync as writeFileSync2, unlinkSync } from "fs";
38847
+ import { existsSync as existsSync4, writeFileSync as writeFileSync2, unlinkSync } from "fs";
38806
38848
  import { tmpdir } from "os";
38807
38849
  import { join as join7 } from "path";
38808
38850
  import { homedir as homedir4 } from "os";
@@ -38889,7 +38931,7 @@ class ImageDisplayTool {
38889
38931
  return `Error: Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`;
38890
38932
  }
38891
38933
  }
38892
- if (!existsSync2(localPath)) {
38934
+ if (!existsSync4(localPath)) {
38893
38935
  return `Error: Image file not found: ${localPath}`;
38894
38936
  }
38895
38937
  try {
@@ -38914,7 +38956,7 @@ class ImageDisplayTool {
38914
38956
  } catch (error) {
38915
38957
  return `Error: ${error instanceof Error ? error.message : String(error)}`;
38916
38958
  } finally {
38917
- if (tempFile && existsSync2(tempFile)) {
38959
+ if (tempFile && existsSync4(tempFile)) {
38918
38960
  try {
38919
38961
  unlinkSync(tempFile);
38920
38962
  } catch {}
@@ -39418,7 +39460,7 @@ Respond with JSON only: {"allow": boolean, "reason": string}`;
39418
39460
  }
39419
39461
  }
39420
39462
  // packages/core/src/commands/loader.ts
39421
- import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39463
+ import { existsSync as existsSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39422
39464
  import { join as join9, basename as basename2, extname } from "path";
39423
39465
  import { homedir as homedir6 } from "os";
39424
39466
 
@@ -39442,7 +39484,7 @@ class CommandLoader {
39442
39484
  await this.loadFromDirectory(legacyProjectDir, "project");
39443
39485
  }
39444
39486
  async loadFromDirectory(dir, source, prefix = "") {
39445
- if (!existsSync3(dir))
39487
+ if (!existsSync5(dir))
39446
39488
  return;
39447
39489
  const entries = readdirSync2(dir);
39448
39490
  for (const entry of entries) {
@@ -39673,7 +39715,7 @@ ${stderr}`;
39673
39715
  // packages/core/src/commands/builtin.ts
39674
39716
  import { join as join10 } from "path";
39675
39717
  import { homedir as homedir7, platform as platform2, release, arch } from "os";
39676
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
39718
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
39677
39719
  init_src();
39678
39720
  var VERSION = "0.6.14";
39679
39721
  function resolveAuthTimeout(resolve4) {
@@ -40608,7 +40650,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40608
40650
  message += `**Config File Locations:**
40609
40651
  `;
40610
40652
  for (const path2 of configPaths) {
40611
- const exists = existsSync4(path2);
40653
+ const exists = existsSync6(path2);
40612
40654
  message += ` ${exists ? "\u2713" : "\u25CB"} ${path2}
40613
40655
  `;
40614
40656
  }
@@ -40652,7 +40694,7 @@ Please summarize the last interaction and suggest 2-3 next steps.
40652
40694
  - Ask a follow-up question if needed
40653
40695
  `;
40654
40696
  const examplePath = join10(commandsDir, "reflect.md");
40655
- if (!existsSync4(examplePath)) {
40697
+ if (!existsSync6(examplePath)) {
40656
40698
  writeFileSync3(examplePath, exampleCommand);
40657
40699
  }
40658
40700
  let message = `
@@ -41230,7 +41272,7 @@ No security events recorded.
41230
41272
  };
41231
41273
  let localPath = "";
41232
41274
  try {
41233
- const saved = saveFeedbackEntry(localEntry);
41275
+ const saved = saveFeedbackEntry(localEntry, context.cwd);
41234
41276
  localPath = saved.path;
41235
41277
  } catch {
41236
41278
  localPath = "";
@@ -41719,7 +41761,7 @@ function validateToolCalls(toolCalls, tools) {
41719
41761
  }
41720
41762
 
41721
41763
  // packages/core/src/voice/utils.ts
41722
- import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
41764
+ import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
41723
41765
  import { homedir as homedir9 } from "os";
41724
41766
  import { join as join12 } from "path";
41725
41767
  import { spawnSync } from "child_process";
@@ -41727,7 +41769,7 @@ function loadApiKeyFromSecrets2(key) {
41727
41769
  const envHome = process.env.HOME || process.env.USERPROFILE;
41728
41770
  const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
41729
41771
  const secretsPath = join12(homeDir, ".secrets");
41730
- if (!existsSync6(secretsPath))
41772
+ if (!existsSync8(secretsPath))
41731
41773
  return;
41732
41774
  try {
41733
41775
  const content = readFileSync3(secretsPath, "utf-8");
@@ -42231,13 +42273,13 @@ class VoiceManager {
42231
42273
  }
42232
42274
  // packages/core/src/identity/assistant-manager.ts
42233
42275
  init_src();
42234
- import { existsSync as existsSync8 } from "fs";
42276
+ import { existsSync as existsSync10 } from "fs";
42235
42277
  import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile6, rm as rm2 } from "fs/promises";
42236
42278
  import { join as join17 } from "path";
42237
42279
 
42238
42280
  // packages/core/src/identity/identity-manager.ts
42239
42281
  init_src();
42240
- import { existsSync as existsSync7 } from "fs";
42282
+ import { existsSync as existsSync9 } from "fs";
42241
42283
  import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile5, rm } from "fs/promises";
42242
42284
  import { join as join16 } from "path";
42243
42285
  var DEFAULT_PROFILE = {
@@ -42387,7 +42429,7 @@ class IdentityManager {
42387
42429
  `);
42388
42430
  }
42389
42431
  async readIndex() {
42390
- if (!existsSync7(this.indexPath)) {
42432
+ if (!existsSync9(this.indexPath)) {
42391
42433
  return { identities: [] };
42392
42434
  }
42393
42435
  try {
@@ -42412,7 +42454,7 @@ class IdentityManager {
42412
42454
  }
42413
42455
  async readIdentity(id) {
42414
42456
  const path2 = this.identityPath(id);
42415
- if (!existsSync7(path2))
42457
+ if (!existsSync9(path2))
42416
42458
  return null;
42417
42459
  try {
42418
42460
  const raw = await readFile5(path2, "utf-8");
@@ -42426,7 +42468,7 @@ class IdentityManager {
42426
42468
  await writeFile5(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
42427
42469
  }
42428
42470
  async readActive() {
42429
- if (!existsSync7(this.activePath))
42471
+ if (!existsSync9(this.activePath))
42430
42472
  return null;
42431
42473
  try {
42432
42474
  const raw = await readFile5(this.activePath, "utf-8");
@@ -42441,7 +42483,7 @@ class IdentityManager {
42441
42483
  await writeFile5(this.activePath, JSON.stringify({ id }, null, 2));
42442
42484
  }
42443
42485
  async loadAssistant() {
42444
- if (!existsSync7(this.assistantConfigPath()))
42486
+ if (!existsSync9(this.assistantConfigPath()))
42445
42487
  return null;
42446
42488
  try {
42447
42489
  const raw = await readFile5(this.assistantConfigPath(), "utf-8");
@@ -42559,7 +42601,7 @@ class AssistantManager {
42559
42601
  return new IdentityManager(assistantId, this.basePath);
42560
42602
  }
42561
42603
  async readIndex() {
42562
- if (!existsSync8(this.indexPath)) {
42604
+ if (!existsSync10(this.indexPath)) {
42563
42605
  return { assistants: [] };
42564
42606
  }
42565
42607
  try {
@@ -42584,7 +42626,7 @@ class AssistantManager {
42584
42626
  }
42585
42627
  async readAssistant(id) {
42586
42628
  const configPath = this.assistantConfigPath(id);
42587
- if (!existsSync8(configPath))
42629
+ if (!existsSync10(configPath))
42588
42630
  return null;
42589
42631
  try {
42590
42632
  const raw = await readFile6(configPath, "utf-8");
@@ -42599,7 +42641,7 @@ class AssistantManager {
42599
42641
  await writeFile6(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
42600
42642
  }
42601
42643
  async readActive() {
42602
- if (!existsSync8(this.activePath))
42644
+ if (!existsSync10(this.activePath))
42603
42645
  return null;
42604
42646
  try {
42605
42647
  const raw = await readFile6(this.activePath, "utf-8");
@@ -42700,6 +42742,7 @@ class AgentLoop {
42700
42742
  await this.initializeIdentitySystem();
42701
42743
  const connectorNames = this.config.connectors && this.config.connectors.length > 0 && !this.config.connectors.includes("*") ? this.config.connectors : undefined;
42702
42744
  this.connectorBridge.fastDiscover(connectorNames);
42745
+ this.connectorBridge.registerAll(this.toolRegistry);
42703
42746
  this.connectorDiscovery = this.connectorBridge.discover(connectorNames).then(() => {
42704
42747
  this.connectorBridge.registerAll(this.toolRegistry);
42705
42748
  }).catch(() => {});
@@ -43657,7 +43700,7 @@ function parseErrorCode(message) {
43657
43700
  // packages/core/src/memory/sessions.ts
43658
43701
  init_src();
43659
43702
  // packages/core/src/migration/migrate-to-assistants.ts
43660
- import { existsSync as existsSync9 } from "fs";
43703
+ import { existsSync as existsSync11 } from "fs";
43661
43704
  import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile7, rename, cp } from "fs/promises";
43662
43705
  import { join as join19 } from "path";
43663
43706
  import { homedir as homedir10 } from "os";
@@ -43666,14 +43709,14 @@ async function ensureDir(path2) {
43666
43709
  await mkdir5(path2, { recursive: true });
43667
43710
  }
43668
43711
  async function copyIfExists(source, destination) {
43669
- if (!existsSync9(source))
43712
+ if (!existsSync11(source))
43670
43713
  return false;
43671
43714
  await ensureDir(join19(destination, ".."));
43672
43715
  await cp(source, destination, { recursive: true });
43673
43716
  return true;
43674
43717
  }
43675
43718
  async function readJson(path2) {
43676
- if (!existsSync9(path2))
43719
+ if (!existsSync11(path2))
43677
43720
  return null;
43678
43721
  try {
43679
43722
  const raw = await readFile7(path2, "utf-8");
@@ -43691,13 +43734,13 @@ async function migrateFromOldpal() {
43691
43734
  const home = homedir10();
43692
43735
  const oldPath = join19(home, ".oldpal");
43693
43736
  const newPath = join19(home, ".assistants");
43694
- if (!existsSync9(oldPath)) {
43737
+ if (!existsSync11(oldPath)) {
43695
43738
  result.success = true;
43696
43739
  return result;
43697
43740
  }
43698
- if (existsSync9(newPath)) {
43741
+ if (existsSync11(newPath)) {
43699
43742
  const marker = join19(newPath, "migration", MIGRATION_MARKER);
43700
- if (existsSync9(marker)) {
43743
+ if (existsSync11(marker)) {
43701
43744
  result.success = true;
43702
43745
  return result;
43703
43746
  }
@@ -43715,9 +43758,18 @@ async function migrateFromOldpal() {
43715
43758
  await writeFile7(join19(newPath, "config.json"), JSON.stringify(config, null, 2));
43716
43759
  result.migrated.push("config.json");
43717
43760
  }
43761
+ if (await copyIfExists(join19(oldPath, "settings.local.json"), join19(newPath, "config.local.json"))) {
43762
+ result.migrated.push("config.local.json");
43763
+ }
43718
43764
  if (await copyIfExists(join19(oldPath, "hooks.json"), join19(newPath, "hooks.json"))) {
43719
43765
  result.migrated.push("hooks.json");
43720
43766
  }
43767
+ if (await copyIfExists(join19(oldPath, "commands"), join19(newPath, "commands"))) {
43768
+ result.migrated.push("commands");
43769
+ }
43770
+ if (await copyIfExists(join19(oldPath, "OLDPAL.md"), join19(newPath, "ASSISTANTS.md"))) {
43771
+ result.migrated.push("ASSISTANTS.md");
43772
+ }
43721
43773
  if (await copyIfExists(join19(oldPath, "skills"), join19(newPath, "shared", "skills"))) {
43722
43774
  result.migrated.push("skills");
43723
43775
  }
@@ -43756,7 +43808,7 @@ init_anthropic();
43756
43808
  init_src();
43757
43809
 
43758
43810
  // packages/core/src/logger.ts
43759
- import { existsSync as existsSync10, mkdirSync as mkdirSync6, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
43811
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
43760
43812
  import { join as join20 } from "path";
43761
43813
  class Logger {
43762
43814
  logDir;
@@ -43770,7 +43822,7 @@ class Logger {
43770
43822
  this.logFile = join20(this.logDir, `${date}.log`);
43771
43823
  }
43772
43824
  ensureDir(dir) {
43773
- if (!existsSync10(dir)) {
43825
+ if (!existsSync12(dir)) {
43774
43826
  mkdirSync6(dir, { recursive: true });
43775
43827
  }
43776
43828
  }
@@ -43816,7 +43868,7 @@ class SessionStorage {
43816
43868
  this.sessionFile = join20(this.sessionsDir, `${sessionId}.json`);
43817
43869
  }
43818
43870
  ensureDir(dir) {
43819
- if (!existsSync10(dir)) {
43871
+ if (!existsSync12(dir)) {
43820
43872
  mkdirSync6(dir, { recursive: true });
43821
43873
  }
43822
43874
  }
@@ -43830,7 +43882,7 @@ class SessionStorage {
43830
43882
  }
43831
43883
  load() {
43832
43884
  try {
43833
- if (!existsSync10(this.sessionFile))
43885
+ if (!existsSync12(this.sessionFile))
43834
43886
  return null;
43835
43887
  return JSON.parse(readFileSync6(this.sessionFile, "utf-8"));
43836
43888
  } catch {
@@ -43840,7 +43892,7 @@ class SessionStorage {
43840
43892
  static getActiveAssistantId() {
43841
43893
  try {
43842
43894
  const activePath = join20(getConfigDir(), "active.json");
43843
- if (!existsSync10(activePath))
43895
+ if (!existsSync12(activePath))
43844
43896
  return null;
43845
43897
  const raw = readFileSync6(activePath, "utf-8");
43846
43898
  const data = JSON.parse(raw);
@@ -43854,7 +43906,7 @@ class SessionStorage {
43854
43906
  const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
43855
43907
  if (resolvedId) {
43856
43908
  const assistantDir = join20(root, "assistants", resolvedId, "sessions");
43857
- if (existsSync10(assistantDir)) {
43909
+ if (existsSync12(assistantDir)) {
43858
43910
  return assistantDir;
43859
43911
  }
43860
43912
  }
@@ -43862,7 +43914,7 @@ class SessionStorage {
43862
43914
  }
43863
43915
  static listSessions(assistantId) {
43864
43916
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43865
- if (!existsSync10(sessionsDir))
43917
+ if (!existsSync12(sessionsDir))
43866
43918
  return [];
43867
43919
  const sessions = [];
43868
43920
  const files = readdirSync3(sessionsDir);
@@ -43892,7 +43944,7 @@ class SessionStorage {
43892
43944
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43893
43945
  const sessionFile = join20(sessionsDir, `${sessionId}.json`);
43894
43946
  try {
43895
- if (!existsSync10(sessionFile))
43947
+ if (!existsSync12(sessionFile))
43896
43948
  return null;
43897
43949
  return JSON.parse(readFileSync6(sessionFile, "utf-8"));
43898
43950
  } catch {
@@ -43915,7 +43967,7 @@ function initAssistantsDir() {
43915
43967
  join20(baseDir, "migration")
43916
43968
  ];
43917
43969
  for (const dir of dirs) {
43918
- if (!existsSync10(dir)) {
43970
+ if (!existsSync12(dir)) {
43919
43971
  mkdirSync6(dir, { recursive: true });
43920
43972
  }
43921
43973
  }
@@ -43934,6 +43986,8 @@ class EmbeddedClient {
43934
43986
  startedAt;
43935
43987
  initialMessages = null;
43936
43988
  assistantId = null;
43989
+ messageQueue = [];
43990
+ processingQueue = false;
43937
43991
  constructor(cwd2, options) {
43938
43992
  initAssistantsDir();
43939
43993
  const sessionId = options?.sessionId || generateId();
@@ -43995,6 +44049,15 @@ class EmbeddedClient {
43995
44049
  if (!this.initialized) {
43996
44050
  await this.initialize();
43997
44051
  }
44052
+ if (this.agent.isProcessing()) {
44053
+ this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length + 1 });
44054
+ this.messageQueue.push(message);
44055
+ return;
44056
+ }
44057
+ await this.processMessage(message);
44058
+ await this.drainQueue();
44059
+ }
44060
+ async processMessage(message) {
43998
44061
  this.logger.info("User message", { message });
43999
44062
  try {
44000
44063
  await this.agent.process(message);
@@ -44019,6 +44082,21 @@ class EmbeddedClient {
44019
44082
  }
44020
44083
  }
44021
44084
  }
44085
+ async drainQueue() {
44086
+ if (this.processingQueue)
44087
+ return;
44088
+ this.processingQueue = true;
44089
+ try {
44090
+ while (this.messageQueue.length > 0 && !this.agent.isProcessing()) {
44091
+ const nextMessage = this.messageQueue.shift();
44092
+ if (nextMessage) {
44093
+ await this.processMessage(nextMessage);
44094
+ }
44095
+ }
44096
+ } finally {
44097
+ this.processingQueue = false;
44098
+ }
44099
+ }
44022
44100
  saveSession() {
44023
44101
  this.session.save({
44024
44102
  messages: this.messages,
@@ -44100,6 +44178,13 @@ class EmbeddedClient {
44100
44178
  getMessages() {
44101
44179
  return [...this.messages];
44102
44180
  }
44181
+ getQueueLength() {
44182
+ return this.messageQueue.length;
44183
+ }
44184
+ clearQueue() {
44185
+ this.messageQueue = [];
44186
+ this.logger.info("Message queue cleared");
44187
+ }
44103
44188
  }
44104
44189
  // packages/core/src/sessions/registry.ts
44105
44190
  class SessionRegistry {
@@ -44675,7 +44760,13 @@ function extractBlockSections(text, blocks) {
44675
44760
  const indent = gridMatch[1] ?? "";
44676
44761
  const header = gridMatch[2] ?? "";
44677
44762
  const attrs = parseAttributes(header);
44678
- const columns = Math.max(1, Math.min(4, Number(attrs.columns || attrs.cols || 2)));
44763
+ const rawColumns = attrs.columns || attrs.cols;
44764
+ let columns = Number(rawColumns ?? 2);
44765
+ if (!Number.isFinite(columns) || columns <= 0) {
44766
+ output.push(createMalformedBlock(blocks, indent, "grid", `Invalid columns value "${rawColumns ?? ""}". Using 2.`));
44767
+ columns = 2;
44768
+ }
44769
+ columns = Math.max(1, Math.min(4, Math.round(columns)));
44679
44770
  const parsed = parseDelimitedBlock(lines, i, indent);
44680
44771
  if (!parsed) {
44681
44772
  output.push(line);
@@ -44741,24 +44832,38 @@ function extractCards(body) {
44741
44832
  let i = 0;
44742
44833
  while (i < lines.length) {
44743
44834
  const line = lines[i];
44744
- const match = line.match(/^\s*:::card(.*)$/);
44835
+ const match = line.match(/^(\s*):::card(.*)$/);
44745
44836
  if (!match) {
44746
44837
  i += 1;
44747
44838
  continue;
44748
44839
  }
44749
- const attrs = parseAttributes(match[1] ?? "");
44840
+ const indent = match[1] ?? "";
44841
+ const attrs = parseAttributes(match[2] ?? "");
44750
44842
  const type = String(attrs.type || "note");
44751
44843
  const title = attrs.title ? String(attrs.title) : undefined;
44752
44844
  const bodyLines = [];
44845
+ let closed = false;
44753
44846
  i += 1;
44754
- while (i < lines.length && lines[i].trim() !== ":::") {
44755
- bodyLines.push(lines[i]);
44847
+ while (i < lines.length) {
44848
+ const current = lines[i];
44849
+ if (current.trim() === ":::" && current.startsWith(indent)) {
44850
+ closed = true;
44851
+ i += 1;
44852
+ break;
44853
+ }
44854
+ bodyLines.push(current);
44756
44855
  i += 1;
44757
44856
  }
44758
- if (i < lines.length && lines[i].trim() === ":::") {
44759
- i += 1;
44857
+ if (!closed) {
44858
+ cards.push({
44859
+ type: "warning",
44860
+ title: "Malformed card",
44861
+ body: "Missing closing ::: for card."
44862
+ });
44863
+ break;
44760
44864
  }
44761
- cards.push({ type, title, body: bodyLines.join(`
44865
+ const stripped = stripIndent(bodyLines, indent);
44866
+ cards.push({ type, title, body: stripped.join(`
44762
44867
  `) });
44763
44868
  }
44764
44869
  return cards;
@@ -44795,12 +44900,12 @@ function stripIndent(lines, indent) {
44795
44900
  return lines;
44796
44901
  return lines.map((line) => line.startsWith(indent) ? line.slice(indent.length) : line);
44797
44902
  }
44798
- function createMalformedBlock(blocks, indent, kind2) {
44903
+ function createMalformedBlock(blocks, indent, kind2, message) {
44799
44904
  blocks.push({
44800
44905
  kind: "block",
44801
44906
  type: "warning",
44802
44907
  title: "Malformed block",
44803
- body: `Missing closing ::: for ${kind2}.`,
44908
+ body: message || `Missing closing ::: for ${kind2}.`,
44804
44909
  indent
44805
44910
  });
44806
44911
  return `@@BLOCKSECTION${blocks.length - 1}@@`;
@@ -44839,7 +44944,7 @@ function renderBlock(type, title, body, maxWidth, indent = "") {
44839
44944
  const content = parseMarkdown(body, { skipBlocks: true, maxWidth });
44840
44945
  const lines = content ? content.split(`
44841
44946
  `) : [];
44842
- return renderBox(header, lines, type, maxWidth, indent);
44947
+ return renderBox(header, lines, type, maxWidth, indent, Boolean(maxWidth));
44843
44948
  }
44844
44949
  function renderCard(card, maxWidth, indent = "", forceWidth = false) {
44845
44950
  const header = formatBlockHeader(card.type, card.title);
@@ -44851,11 +44956,17 @@ function renderCard(card, maxWidth, indent = "", forceWidth = false) {
44851
44956
  function renderCardGrid(cards, columns, maxWidth, indent = "") {
44852
44957
  const gap = 2;
44853
44958
  const totalWidth = maxWidth ? Math.max(20, maxWidth) : undefined;
44854
- const cardTotalWidth = totalWidth ? Math.max(20, Math.floor((totalWidth - gap * (columns - 1)) / columns)) : undefined;
44959
+ let effectiveColumns = columns;
44960
+ if (totalWidth) {
44961
+ const minCardWidth = 18;
44962
+ const maxColumns = Math.max(1, Math.floor((totalWidth + gap) / (minCardWidth + gap)));
44963
+ effectiveColumns = Math.min(columns, maxColumns);
44964
+ }
44965
+ const cardTotalWidth = totalWidth ? Math.max(8, Math.floor((totalWidth - gap * (effectiveColumns - 1)) / effectiveColumns)) : undefined;
44855
44966
  const cardLines = cards.map((card) => renderCard(card, cardTotalWidth, "", true));
44856
44967
  const rows = [];
44857
- for (let i = 0;i < cardLines.length; i += columns) {
44858
- rows.push(cardLines.slice(i, i + columns));
44968
+ for (let i = 0;i < cardLines.length; i += effectiveColumns) {
44969
+ rows.push(cardLines.slice(i, i + effectiveColumns));
44859
44970
  }
44860
44971
  const output = [];
44861
44972
  for (const row of rows) {
@@ -44898,8 +45009,8 @@ function getBlockIcon(type) {
44898
45009
  return "\u2139";
44899
45010
  }
44900
45011
  }
44901
- function renderBox(header, lines, type, maxWidth, indent = "") {
44902
- return renderBoxLines(header, lines, type, maxWidth, indent).join(`
45012
+ function renderBox(header, lines, type, maxWidth, indent = "", forceWidth = false) {
45013
+ return renderBoxLines(header, lines, type, maxWidth, indent, forceWidth).join(`
44903
45014
  `);
44904
45015
  }
44905
45016
  function renderBoxLines(header, lines, type, maxWidth, indent = "", forceWidth = false) {
@@ -45218,6 +45329,7 @@ var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
45218
45329
  function Messages4({
45219
45330
  messages,
45220
45331
  currentResponse,
45332
+ streamingMessages = [],
45221
45333
  currentToolCall,
45222
45334
  lastToolResult,
45223
45335
  activityLog = [],
@@ -45226,9 +45338,14 @@ function Messages4({
45226
45338
  queuedMessageIds
45227
45339
  }) {
45228
45340
  const [now2, setNow] = import_react24.useState(Date.now());
45229
- const endIndex = messages.length - scrollOffset;
45341
+ const combinedMessages = import_react24.useMemo(() => [...messages, ...streamingMessages], [messages, streamingMessages]);
45342
+ const endIndex = combinedMessages.length - scrollOffset;
45230
45343
  const startIndex = Math.max(0, endIndex - maxVisible);
45231
- const visibleMessages = messages.slice(startIndex, endIndex);
45344
+ const visibleCombined = combinedMessages.slice(startIndex, endIndex);
45345
+ const historicalCount = messages.length;
45346
+ const splitIndex = Math.max(0, Math.min(visibleCombined.length, historicalCount - startIndex));
45347
+ const visibleMessages = visibleCombined.slice(0, splitIndex);
45348
+ const visibleStreaming = visibleCombined.slice(splitIndex);
45232
45349
  const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
45233
45350
  const historicalItems = groupedMessages.map((group) => {
45234
45351
  if (group.type === "single") {
@@ -45302,19 +45419,30 @@ function Messages4({
45302
45419
  const elapsedText = formatDuration(elapsedMs);
45303
45420
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45304
45421
  marginY: 1,
45422
+ flexDirection: "column",
45305
45423
  children: [
45306
- /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45307
- dimColor: true,
45308
- children: "\u2699 "
45309
- }, undefined, false, undefined, this),
45310
- /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45311
- dimColor: true,
45424
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45312
45425
  children: [
45313
- formatToolCall(entry.toolCall),
45314
- " \xB7 ",
45315
- elapsedText
45426
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45427
+ dimColor: true,
45428
+ children: "\u2699 "
45429
+ }, undefined, false, undefined, this),
45430
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45431
+ dimColor: true,
45432
+ children: formatToolCall(entry.toolCall)
45433
+ }, undefined, false, undefined, this)
45316
45434
  ]
45317
- }, undefined, true, undefined, this)
45435
+ }, undefined, true, undefined, this),
45436
+ /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45437
+ marginLeft: 2,
45438
+ children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45439
+ dimColor: true,
45440
+ children: [
45441
+ elapsedText,
45442
+ " elapsed"
45443
+ ]
45444
+ }, undefined, true, undefined, this)
45445
+ }, undefined, false, undefined, this)
45318
45446
  ]
45319
45447
  }, entry.id, true, undefined, this);
45320
45448
  }
@@ -45339,6 +45467,10 @@ function Messages4({
45339
45467
  }
45340
45468
  return null;
45341
45469
  }),
45470
+ visibleStreaming.map((message) => /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(MessageBubble, {
45471
+ message,
45472
+ queuedMessageIds
45473
+ }, message.id, false, undefined, this)),
45342
45474
  currentResponse && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45343
45475
  marginY: 1,
45344
45476
  children: [
@@ -46190,7 +46322,7 @@ function parseErrorMessage(error) {
46190
46322
  }
46191
46323
  var MESSAGE_CHUNK_LINES = 12;
46192
46324
  var MESSAGE_WRAP_CHARS = 120;
46193
- function buildDisplayMessages(messages, chunkLines) {
46325
+ function buildDisplayMessages(messages, chunkLines, wrapChars) {
46194
46326
  const display = [];
46195
46327
  for (const msg of messages) {
46196
46328
  const content = msg.content ?? "";
@@ -46203,12 +46335,12 @@ function buildDisplayMessages(messages, chunkLines) {
46203
46335
  `);
46204
46336
  const lines = [];
46205
46337
  for (const line of rawLines) {
46206
- if (line.length <= MESSAGE_WRAP_CHARS) {
46338
+ if (line.length <= wrapChars) {
46207
46339
  lines.push(line);
46208
46340
  continue;
46209
46341
  }
46210
- for (let i = 0;i < line.length; i += MESSAGE_WRAP_CHARS) {
46211
- lines.push(line.slice(i, i + MESSAGE_WRAP_CHARS));
46342
+ for (let i = 0;i < line.length; i += wrapChars) {
46343
+ lines.push(line.slice(i, i + wrapChars));
46212
46344
  }
46213
46345
  }
46214
46346
  if (lines.length <= chunkLines) {
@@ -46230,9 +46362,9 @@ function buildDisplayMessages(messages, chunkLines) {
46230
46362
  }
46231
46363
  return display;
46232
46364
  }
46233
- function App2({ cwd: cwd2 }) {
46365
+ function App2({ cwd: cwd2, version }) {
46234
46366
  const { exit } = use_app_default();
46235
- const { rows } = use_stdout_default();
46367
+ const { rows, columns } = use_stdout_default();
46236
46368
  const [registry2] = import_react29.useState(() => new SessionRegistry);
46237
46369
  const registryRef = import_react29.useRef(registry2);
46238
46370
  const [activeSessionId, setActiveSessionId] = import_react29.useState(null);
@@ -46463,6 +46595,10 @@ function App2({ cwd: cwd2 }) {
46463
46595
  setError(chunk.error);
46464
46596
  setIsProcessing(false);
46465
46597
  isProcessingRef.current = false;
46598
+ const active = registryRef.current.getActiveSession();
46599
+ if (active) {
46600
+ registryRef.current.setProcessing(active.id, false);
46601
+ }
46466
46602
  } else if (chunk.type === "exit") {
46467
46603
  registry2.closeAll();
46468
46604
  exit();
@@ -46477,6 +46613,10 @@ function App2({ cwd: cwd2 }) {
46477
46613
  }
46478
46614
  setIsProcessing(false);
46479
46615
  isProcessingRef.current = false;
46616
+ const active = registryRef.current.getActiveSession();
46617
+ if (active) {
46618
+ registryRef.current.setProcessing(active.id, false);
46619
+ }
46480
46620
  queueMicrotask(() => {
46481
46621
  resetTurnState();
46482
46622
  });
@@ -46502,6 +46642,10 @@ function App2({ cwd: cwd2 }) {
46502
46642
  setError(err.message);
46503
46643
  setIsProcessing(false);
46504
46644
  isProcessingRef.current = false;
46645
+ const active = registryRef.current.getActiveSession();
46646
+ if (active) {
46647
+ registryRef.current.setProcessing(active.id, false);
46648
+ }
46505
46649
  });
46506
46650
  const session = await registry2.createSession(cwd2);
46507
46651
  setActiveSessionId(session.id);
@@ -46570,7 +46714,20 @@ function App2({ cwd: cwd2 }) {
46570
46714
  }, [activeSessionId]);
46571
46715
  const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
46572
46716
  const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.map((msg) => msg.id)), [activeQueue]);
46573
- const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES), [messages]);
46717
+ const wrapChars = columns ? Math.max(40, columns - 4) : MESSAGE_WRAP_CHARS;
46718
+ const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars), [messages, wrapChars]);
46719
+ const streamingMessages = import_react29.useMemo(() => {
46720
+ if (!isProcessing || !currentResponse.trim())
46721
+ return [];
46722
+ const streamingMessage = {
46723
+ id: "streaming-response",
46724
+ role: "assistant",
46725
+ content: currentResponse,
46726
+ timestamp: now()
46727
+ };
46728
+ return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
46729
+ }, [currentResponse, isProcessing, wrapChars]);
46730
+ const displayCount = displayMessages.length + streamingMessages.length;
46574
46731
  import_react29.useEffect(() => {
46575
46732
  if (!isProcessing && activeQueue.length > 0) {
46576
46733
  processQueue();
@@ -46580,23 +46737,23 @@ function App2({ cwd: cwd2 }) {
46580
46737
  if (autoScroll) {
46581
46738
  setScrollOffset(0);
46582
46739
  }
46583
- }, [displayMessages.length, autoScroll]);
46740
+ }, [displayCount, autoScroll]);
46584
46741
  import_react29.useEffect(() => {
46585
46742
  const prevCount = prevDisplayCountRef.current;
46586
- if (!autoScroll && displayMessages.length > prevCount) {
46587
- const delta = displayMessages.length - prevCount;
46743
+ if (!autoScroll && displayCount > prevCount) {
46744
+ const delta = displayCount - prevCount;
46588
46745
  setScrollOffset((prev) => prev + delta);
46589
46746
  }
46590
- prevDisplayCountRef.current = displayMessages.length;
46591
- }, [displayMessages.length, autoScroll]);
46747
+ prevDisplayCountRef.current = displayCount;
46748
+ }, [displayCount, autoScroll]);
46592
46749
  const reservedLines = 8;
46593
46750
  const baseMaxVisible = rows ? Math.max(3, rows - reservedLines) : 10;
46594
46751
  const toolCallsHeight = isProcessing ? Math.min(toolCallsRef.current.length, 5) : 0;
46595
46752
  const maxVisibleMessages = Math.max(3, baseMaxVisible - toolCallsHeight);
46596
46753
  import_react29.useEffect(() => {
46597
- const maxOffset = Math.max(0, displayMessages.length - maxVisibleMessages);
46754
+ const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
46598
46755
  setScrollOffset((prev) => Math.min(prev, maxOffset));
46599
- }, [displayMessages.length, maxVisibleMessages]);
46756
+ }, [displayCount, maxVisibleMessages]);
46600
46757
  const sessions = registry2.listSessions();
46601
46758
  const activeSession = registry2.getActiveSession();
46602
46759
  const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
@@ -46675,7 +46832,7 @@ function App2({ cwd: cwd2 }) {
46675
46832
  }
46676
46833
  if (key.pageUp || key.shift && key.upArrow) {
46677
46834
  setScrollOffset((prev) => {
46678
- const maxOffset = Math.max(0, displayMessages.length - maxVisibleMessages);
46835
+ const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
46679
46836
  const newOffset = Math.min(prev + 3, maxOffset);
46680
46837
  if (newOffset > 0)
46681
46838
  setAutoScroll(false);
@@ -46691,7 +46848,7 @@ function App2({ cwd: cwd2 }) {
46691
46848
  });
46692
46849
  }
46693
46850
  if (key.ctrl && input === "u") {
46694
- const maxOffset = Math.max(0, displayMessages.length - maxVisibleMessages);
46851
+ const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
46695
46852
  setScrollOffset(maxOffset);
46696
46853
  setAutoScroll(false);
46697
46854
  }
@@ -46750,6 +46907,7 @@ function App2({ cwd: cwd2 }) {
46750
46907
  resetTurnState();
46751
46908
  setIsProcessing(false);
46752
46909
  isProcessingRef.current = false;
46910
+ registry2.setProcessing(activeSession.id, false);
46753
46911
  await new Promise((r) => setTimeout(r, 100));
46754
46912
  }
46755
46913
  const userMessage = {
@@ -46829,7 +46987,7 @@ function App2({ cwd: cwd2 }) {
46829
46987
  padding: 1,
46830
46988
  children: [
46831
46989
  showWelcome && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(WelcomeBanner, {
46832
- version: "0.6.12",
46990
+ version: version ?? "0.6.13",
46833
46991
  model: "claude-sonnet-4",
46834
46992
  directory: activeSession?.cwd || cwd2
46835
46993
  }, undefined, false, undefined, this),
@@ -46851,13 +47009,14 @@ function App2({ cwd: cwd2 }) {
46851
47009
  children: [
46852
47010
  "\u2191 ",
46853
47011
  scrollOffset,
46854
- " more messages above (Shift+\u2193 or Ctrl+D to scroll down)"
47012
+ " more messages above (Shift+\u2193 or Page Down to scroll down)"
46855
47013
  ]
46856
47014
  }, undefined, true, undefined, this)
46857
47015
  }, undefined, false, undefined, this),
46858
47016
  /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Messages4, {
46859
47017
  messages: displayMessages,
46860
- currentResponse: isProcessing ? currentResponse : undefined,
47018
+ currentResponse: undefined,
47019
+ streamingMessages,
46861
47020
  currentToolCall: undefined,
46862
47021
  lastToolResult: undefined,
46863
47022
  activityLog: isProcessing ? activityLog : [],
@@ -47156,7 +47315,7 @@ function formatStreamEvent(chunk) {
47156
47315
 
47157
47316
  // packages/terminal/src/index.tsx
47158
47317
  var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
47159
- var VERSION3 = "0.6.14";
47318
+ var VERSION3 = "0.6.16";
47160
47319
  function parseArgs(argv) {
47161
47320
  const args = argv.slice(2);
47162
47321
  const options = {
@@ -47311,11 +47470,12 @@ if (options.print !== null) {
47311
47470
  });
47312
47471
  } else {
47313
47472
  const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(App2, {
47314
- cwd: options.cwd
47473
+ cwd: options.cwd,
47474
+ version: VERSION3
47315
47475
  }, undefined, false, undefined, this));
47316
47476
  waitUntilExit().then(() => {
47317
47477
  process.exit(0);
47318
47478
  });
47319
47479
  }
47320
47480
 
47321
- //# debugId=3893B298BF198EB564756E2164756E21
47481
+ //# debugId=4013F70DB4CACA3C64756E2164756E21