@hasna/assistants 0.6.19 → 0.6.21

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
@@ -25630,7 +25630,7 @@ var __classPrivateFieldSet = function(receiver, state, value, kind2, f) {
25630
25630
  }
25631
25631
  }, startsWithSchemeRegexp, isAbsoluteURL = (url) => {
25632
25632
  return startsWithSchemeRegexp.test(url);
25633
- }, sleep2 = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms)), validatePositiveInteger = (name, n) => {
25633
+ }, sleep2 = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms)), validatePositiveInteger = (name, n) => {
25634
25634
  if (typeof n !== "number" || !Number.isInteger(n)) {
25635
25635
  throw new AnthropicError(`${name} must be an integer`);
25636
25636
  }
@@ -25696,8 +25696,8 @@ var init_core = __esm(() => {
25696
25696
  init_uploads();
25697
25697
  APIPromise = class APIPromise extends Promise {
25698
25698
  constructor(responsePromise, parseResponse = defaultParseResponse) {
25699
- super((resolve4) => {
25700
- resolve4(null);
25699
+ super((resolve5) => {
25700
+ resolve5(null);
25701
25701
  });
25702
25702
  this.responsePromise = responsePromise;
25703
25703
  this.parseResponse = parseResponse;
@@ -26295,12 +26295,12 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
26295
26295
  }
26296
26296
  return this._emit("error", new AnthropicError(String(error)));
26297
26297
  });
26298
- __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve4, reject) => {
26299
- __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve4, "f");
26298
+ __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_connectedPromise, new Promise((resolve5, reject) => {
26299
+ __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveConnectedPromise, resolve5, "f");
26300
26300
  __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_rejectConnectedPromise, reject, "f");
26301
26301
  }), "f");
26302
- __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve4, reject) => {
26303
- __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve4, "f");
26302
+ __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_endPromise, new Promise((resolve5, reject) => {
26303
+ __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_resolveEndPromise, resolve5, "f");
26304
26304
  __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_rejectEndPromise, reject, "f");
26305
26305
  }), "f");
26306
26306
  __classPrivateFieldGet2(this, _PromptCachingBetaMessageStream_connectedPromise, "f").catch(() => {});
@@ -26390,11 +26390,11 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
26390
26390
  return this;
26391
26391
  }
26392
26392
  emitted(event) {
26393
- return new Promise((resolve4, reject) => {
26393
+ return new Promise((resolve5, reject) => {
26394
26394
  __classPrivateFieldSet2(this, _PromptCachingBetaMessageStream_catchingPromiseCreated, true, "f");
26395
26395
  if (event !== "error")
26396
26396
  this.once("error", reject);
26397
- this.once(event, resolve4);
26397
+ this.once(event, resolve5);
26398
26398
  });
26399
26399
  }
26400
26400
  async done() {
@@ -26612,7 +26612,7 @@ var init_PromptCachingBetaMessageStream = __esm(() => {
26612
26612
  if (done) {
26613
26613
  return { value: undefined, done: true };
26614
26614
  }
26615
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
26615
+ return new Promise((resolve5, reject) => readQueue.push({ resolve: resolve5, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
26616
26616
  }
26617
26617
  const chunk = pushQueue.shift();
26618
26618
  return { value: chunk, done: false };
@@ -26758,12 +26758,12 @@ var init_MessageStream = __esm(() => {
26758
26758
  }
26759
26759
  return this._emit("error", new AnthropicError(String(error)));
26760
26760
  });
26761
- __classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((resolve4, reject) => {
26762
- __classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise, resolve4, "f");
26761
+ __classPrivateFieldSet3(this, _MessageStream_connectedPromise, new Promise((resolve5, reject) => {
26762
+ __classPrivateFieldSet3(this, _MessageStream_resolveConnectedPromise, resolve5, "f");
26763
26763
  __classPrivateFieldSet3(this, _MessageStream_rejectConnectedPromise, reject, "f");
26764
26764
  }), "f");
26765
- __classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((resolve4, reject) => {
26766
- __classPrivateFieldSet3(this, _MessageStream_resolveEndPromise, resolve4, "f");
26765
+ __classPrivateFieldSet3(this, _MessageStream_endPromise, new Promise((resolve5, reject) => {
26766
+ __classPrivateFieldSet3(this, _MessageStream_resolveEndPromise, resolve5, "f");
26767
26767
  __classPrivateFieldSet3(this, _MessageStream_rejectEndPromise, reject, "f");
26768
26768
  }), "f");
26769
26769
  __classPrivateFieldGet3(this, _MessageStream_connectedPromise, "f").catch(() => {});
@@ -26853,11 +26853,11 @@ var init_MessageStream = __esm(() => {
26853
26853
  return this;
26854
26854
  }
26855
26855
  emitted(event) {
26856
- return new Promise((resolve4, reject) => {
26856
+ return new Promise((resolve5, reject) => {
26857
26857
  __classPrivateFieldSet3(this, _MessageStream_catchingPromiseCreated, true, "f");
26858
26858
  if (event !== "error")
26859
26859
  this.once("error", reject);
26860
- this.once(event, resolve4);
26860
+ this.once(event, resolve5);
26861
26861
  });
26862
26862
  }
26863
26863
  async done() {
@@ -27075,7 +27075,7 @@ var init_MessageStream = __esm(() => {
27075
27075
  if (done) {
27076
27076
  return { value: undefined, done: true };
27077
27077
  }
27078
- return new Promise((resolve4, reject) => readQueue.push({ resolve: resolve4, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
27078
+ return new Promise((resolve5, reject) => readQueue.push({ resolve: resolve5, reject })).then((chunk2) => chunk2 ? { value: chunk2, done: false } : { value: undefined, done: true });
27079
27079
  }
27080
27080
  const chunk = pushQueue.shift();
27081
27081
  return { value: chunk, done: false };
@@ -27290,16 +27290,16 @@ var exports_anthropic = {};
27290
27290
  __export(exports_anthropic, {
27291
27291
  AnthropicClient: () => AnthropicClient
27292
27292
  });
27293
- import { readFileSync as readFileSync2, existsSync as existsSync7 } from "fs";
27293
+ import { readFileSync as readFileSync3, existsSync as existsSync8 } from "fs";
27294
27294
  import { homedir as homedir8 } from "os";
27295
- import { join as join11 } from "path";
27295
+ import { join as join12 } 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
- const secretsPath = join11(homeDir, ".secrets");
27300
- if (existsSync7(secretsPath)) {
27299
+ const secretsPath = join12(homeDir, ".secrets");
27300
+ if (existsSync8(secretsPath)) {
27301
27301
  try {
27302
- const content = readFileSync2(secretsPath, "utf-8");
27302
+ const content = readFileSync3(secretsPath, "utf-8");
27303
27303
  const match = content.match(/export\s+ANTHROPIC_API_KEY\s*=\s*["']?([^"'\n]+)["']?/);
27304
27304
  if (match) {
27305
27305
  return match[1];
@@ -35507,7 +35507,7 @@ var import_react20 = __toESM(require_react(), 1);
35507
35507
  var import_react21 = __toESM(require_react(), 1);
35508
35508
  // packages/core/src/agent/loop.ts
35509
35509
  init_src();
35510
- import { join as join18 } from "path";
35510
+ import { join as join19 } from "path";
35511
35511
 
35512
35512
  // packages/core/src/agent/context.ts
35513
35513
  init_src();
@@ -35567,6 +35567,13 @@ class AgentContext {
35567
35567
  this.messages.push(message);
35568
35568
  return message;
35569
35569
  }
35570
+ removeSystemMessages(predicate) {
35571
+ this.messages = this.messages.filter((msg) => {
35572
+ if (msg.role !== "system")
35573
+ return true;
35574
+ return !predicate(msg.content);
35575
+ });
35576
+ }
35570
35577
  getMessages() {
35571
35578
  return [...this.messages];
35572
35579
  }
@@ -36629,23 +36636,71 @@ function isErrorResult(result) {
36629
36636
  init_errors();
36630
36637
  import { homedir as homedir2 } from "os";
36631
36638
  import { join as join3, delimiter } from "path";
36632
- import { readdirSync, statSync } from "fs";
36639
+ import { readdirSync, statSync, existsSync as existsSync2, mkdirSync, writeFileSync, readFileSync as readFileSync2 } from "fs";
36633
36640
  function resolveTimeout(resolve) {
36634
36641
  resolve({ exitCode: 1 });
36635
36642
  }
36643
+ var CACHE_VERSION = 1;
36644
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1000;
36636
36645
 
36637
36646
  class ConnectorBridge {
36638
36647
  connectors = new Map;
36639
36648
  static cache = new Map;
36649
+ static diskCacheLoaded = false;
36650
+ cwd;
36651
+ constructor(cwd2) {
36652
+ this.cwd = cwd2;
36653
+ if (!ConnectorBridge.diskCacheLoaded) {
36654
+ ConnectorBridge.loadDiskCache();
36655
+ }
36656
+ }
36640
36657
  getHomeDir() {
36641
36658
  const envHome = process.env.HOME || process.env.USERPROFILE;
36642
36659
  return envHome && envHome.trim().length > 0 ? envHome : homedir2();
36643
36660
  }
36661
+ static getCachePath() {
36662
+ const envHome = process.env.HOME || process.env.USERPROFILE;
36663
+ const home = envHome && envHome.trim().length > 0 ? envHome : homedir2();
36664
+ return join3(home, ".assistants", "cache", "connectors.json");
36665
+ }
36666
+ static loadDiskCache() {
36667
+ ConnectorBridge.diskCacheLoaded = true;
36668
+ try {
36669
+ const cachePath = ConnectorBridge.getCachePath();
36670
+ if (!existsSync2(cachePath))
36671
+ return;
36672
+ const data = JSON.parse(readFileSync2(cachePath, "utf-8"));
36673
+ if (data.version !== CACHE_VERSION)
36674
+ return;
36675
+ if (Date.now() - data.timestamp > CACHE_TTL_MS)
36676
+ return;
36677
+ for (const [name, connector] of Object.entries(data.connectors)) {
36678
+ ConnectorBridge.cache.set(name, connector);
36679
+ }
36680
+ } catch {}
36681
+ }
36682
+ static saveDiskCache() {
36683
+ try {
36684
+ const cachePath = ConnectorBridge.getCachePath();
36685
+ const cacheDir = join3(cachePath, "..");
36686
+ if (!existsSync2(cacheDir)) {
36687
+ mkdirSync(cacheDir, { recursive: true });
36688
+ }
36689
+ const data = {
36690
+ version: CACHE_VERSION,
36691
+ timestamp: Date.now(),
36692
+ connectors: Object.fromEntries(ConnectorBridge.cache)
36693
+ };
36694
+ writeFileSync(cachePath, JSON.stringify(data));
36695
+ } catch {}
36696
+ }
36644
36697
  autoDiscoverConnectorNames() {
36645
36698
  const connectorNames = new Set;
36646
36699
  const pathDirs = (process.env.PATH || "").split(delimiter);
36700
+ const baseCwd = this.cwd || process.cwd();
36647
36701
  const homeDir = this.getHomeDir();
36648
36702
  const extraDirs = [
36703
+ join3(baseCwd, "node_modules", ".bin"),
36649
36704
  join3(homeDir, ".bun", "bin"),
36650
36705
  join3(homeDir, ".npm-global", "bin"),
36651
36706
  "/usr/local/bin"
@@ -36678,6 +36733,19 @@ class ConnectorBridge {
36678
36733
  return Array.from(connectorNames);
36679
36734
  }
36680
36735
  fastDiscover(connectorNames) {
36736
+ if (ConnectorBridge.cache.size > 0) {
36737
+ const connectors2 = [];
36738
+ const allowList2 = connectorNames && connectorNames.length > 0 ? new Set(connectorNames) : null;
36739
+ for (const [name, connector] of ConnectorBridge.cache) {
36740
+ if (connector && (!allowList2 || allowList2.has(name))) {
36741
+ this.connectors.set(connector.name, connector);
36742
+ connectors2.push(connector);
36743
+ }
36744
+ }
36745
+ if (connectors2.length > 0) {
36746
+ return connectors2;
36747
+ }
36748
+ }
36681
36749
  const discoveredNames = this.autoDiscoverConnectorNames();
36682
36750
  const allowList = connectorNames && connectorNames.length > 0 ? new Set(connectorNames) : null;
36683
36751
  const names = allowList ? discoveredNames.filter((name) => allowList.has(name)) : discoveredNames;
@@ -36700,6 +36768,9 @@ class ConnectorBridge {
36700
36768
  this.connectors.set(connector.name, connector);
36701
36769
  connectors.push(connector);
36702
36770
  }
36771
+ if (connectors.length > 0) {
36772
+ ConnectorBridge.saveDiskCache();
36773
+ }
36703
36774
  return connectors;
36704
36775
  }
36705
36776
  async discover(connectorNames) {
@@ -36719,6 +36790,7 @@ class ConnectorBridge {
36719
36790
  tasks.push(this.populateCache(name));
36720
36791
  }
36721
36792
  await Promise.all(tasks);
36793
+ ConnectorBridge.saveDiskCache();
36722
36794
  }
36723
36795
  const discovered = [];
36724
36796
  for (const name of names) {
@@ -36888,17 +36960,20 @@ class ConnectorBridge {
36888
36960
  }
36889
36961
  const lowerCommand = command.toLowerCase();
36890
36962
  const lowerArgs = args.map((arg) => arg.toLowerCase());
36891
- const isAuthLogin = lowerCommand.includes("auth") && (lowerCommand.includes("login") || lowerCommand.includes("authorize")) || lowerCommand.includes("auth") && (lowerArgs.includes("login") || lowerArgs.includes("authorize")) || lowerArgs.includes("auth") && (lowerArgs.includes("login") || lowerArgs.includes("authorize"));
36892
- if (isAuthLogin) {
36963
+ const combined = [lowerCommand, ...lowerArgs].join(" ");
36964
+ const isAuthLogin = /\bauth\b/.test(combined) && /(login|authorize|authorization|oauth|signin|sign-in|connect)/.test(combined);
36965
+ const runInBackground = options.background === true;
36966
+ if (isAuthLogin || runInBackground) {
36893
36967
  try {
36894
- Bun.spawn(cmdParts, {
36968
+ const proc = Bun.spawn(cmdParts, {
36895
36969
  cwd: cwd2,
36896
36970
  stdin: "ignore",
36897
36971
  stdout: "ignore",
36898
- stderr: "pipe"
36972
+ stderr: "ignore"
36899
36973
  });
36974
+ proc.unref?.();
36900
36975
  } catch {}
36901
- return "Auth login started in the background. Complete it in your browser, then run auth status to confirm.";
36976
+ return isAuthLogin ? "Auth login started in the background. Complete it in your browser, then run auth status to confirm." : "Command started in the background.";
36902
36977
  }
36903
36978
  try {
36904
36979
  const proc = Bun.spawn(cmdParts, {
@@ -37036,6 +37111,38 @@ function stripQuotedSegments(input) {
37036
37111
  }
37037
37112
  return result;
37038
37113
  }
37114
+ function normalizeNewlinesOutsideQuotes(input) {
37115
+ let result = "";
37116
+ let quote = null;
37117
+ let escaped = false;
37118
+ for (let i = 0;i < input.length; i += 1) {
37119
+ const char = input[i];
37120
+ if (quote) {
37121
+ result += char;
37122
+ if (quote === '"' && !escaped && char === "\\") {
37123
+ escaped = true;
37124
+ continue;
37125
+ }
37126
+ if (!escaped && char === quote) {
37127
+ quote = null;
37128
+ }
37129
+ escaped = false;
37130
+ continue;
37131
+ }
37132
+ if (char === '"' || char === "'") {
37133
+ quote = char;
37134
+ result += char;
37135
+ continue;
37136
+ }
37137
+ if (char === "\r" || char === `
37138
+ `) {
37139
+ result += " ";
37140
+ continue;
37141
+ }
37142
+ result += char;
37143
+ }
37144
+ return result;
37145
+ }
37039
37146
 
37040
37147
  class BashTool {
37041
37148
  static tool = {
@@ -37155,7 +37262,11 @@ class BashTool {
37155
37262
  const command = input.command;
37156
37263
  const cwd2 = input.cwd || process.cwd();
37157
37264
  const timeout = input.timeout || 30000;
37158
- const commandForChecks = command.replace(/\s*2>&1\s*/g, " ");
37265
+ const baseCommand = command.replace(/\s*2>&1\s*/g, " ").trim();
37266
+ const baseTrimmed = baseCommand.toLowerCase();
37267
+ const allowConnectorNewlines = baseTrimmed.startsWith("connect-");
37268
+ const commandForExec = allowConnectorNewlines ? normalizeNewlinesOutsideQuotes(baseCommand).trim() : baseCommand;
37269
+ const commandForChecks = commandForExec;
37159
37270
  const commandSansQuotes = stripQuotedSegments(commandForChecks);
37160
37271
  const securityCheck = validateBashCommand(commandForChecks);
37161
37272
  if (!securityCheck.valid) {
@@ -37229,7 +37340,7 @@ class BashTool {
37229
37340
  });
37230
37341
  }
37231
37342
  try {
37232
- const proc = Bun.spawn(["bash", "-c", command], {
37343
+ const proc = Bun.spawn(["bash", "-c", commandForExec], {
37233
37344
  cwd: cwd2,
37234
37345
  stdout: "pipe",
37235
37346
  stderr: "pipe"
@@ -37268,7 +37379,7 @@ ${stderr || stdout}`.trim(), {
37268
37379
 
37269
37380
  // packages/core/src/tools/filesystem.ts
37270
37381
  import { join as join4, resolve as resolve3, dirname as dirname2, sep } from "path";
37271
- import { existsSync as existsSync2 } from "fs";
37382
+ import { existsSync as existsSync3 } from "fs";
37272
37383
  init_errors();
37273
37384
  var {Glob } = globalThis.Bun;
37274
37385
 
@@ -37356,15 +37467,16 @@ async function isPathSafe(targetPath, operation, options = {}) {
37356
37467
 
37357
37468
  // packages/core/src/tools/filesystem.ts
37358
37469
  var currentSessionId = "default";
37359
- function getScriptsFolder(cwd2) {
37470
+ function getScriptsFolder(cwd2, sessionId) {
37471
+ const resolvedSessionId = sessionId || currentSessionId;
37360
37472
  const legacyDir = join4(cwd2, ".oldpal");
37361
- if (existsSync2(legacyDir)) {
37362
- return join4(legacyDir, "scripts", currentSessionId);
37473
+ if (existsSync3(legacyDir)) {
37474
+ return join4(legacyDir, "scripts", resolvedSessionId);
37363
37475
  }
37364
- return join4(getProjectConfigDir(cwd2), "scripts", currentSessionId);
37476
+ return join4(getProjectConfigDir(cwd2), "scripts", resolvedSessionId);
37365
37477
  }
37366
- function isInScriptsFolder(path2, cwd2) {
37367
- const scriptsFolder = resolve3(getScriptsFolder(cwd2));
37478
+ function isInScriptsFolder(path2, cwd2, sessionId) {
37479
+ const scriptsFolder = resolve3(getScriptsFolder(cwd2, sessionId));
37368
37480
  const resolved = resolve3(path2);
37369
37481
  if (resolved === scriptsFolder)
37370
37482
  return true;
@@ -37520,7 +37632,7 @@ class FilesystemTools {
37520
37632
  const filename = input.filename || input.path;
37521
37633
  const content = input.content;
37522
37634
  const baseCwd = input.cwd || process.cwd();
37523
- const scriptsFolder = getScriptsFolder(baseCwd);
37635
+ const scriptsFolder = getScriptsFolder(baseCwd, input.sessionId);
37524
37636
  if (!filename || !filename.trim()) {
37525
37637
  throw new ToolExecutionError("Filename is required", {
37526
37638
  toolName: "write",
@@ -37533,7 +37645,7 @@ class FilesystemTools {
37533
37645
  }
37534
37646
  const sanitizedFilename = filename.replace(/\.\.[/\\]/g, "").replace(/\.\./g, "").replace(/^[/\\]+/, "");
37535
37647
  const path2 = join4(scriptsFolder, sanitizedFilename);
37536
- if (!isInScriptsFolder(path2, baseCwd)) {
37648
+ if (!isInScriptsFolder(path2, baseCwd, input.sessionId)) {
37537
37649
  throw new ToolExecutionError(`Cannot write outside scripts folder. Files are saved to ${scriptsFolder}`, {
37538
37650
  toolName: "write",
37539
37651
  toolInput: input,
@@ -38283,7 +38395,7 @@ function isPrivateIPv4(octets) {
38283
38395
  // packages/core/src/tools/feedback.ts
38284
38396
  init_src();
38285
38397
  import { join as join5 } from "path";
38286
- import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
38398
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
38287
38399
  function normalizeTags(value) {
38288
38400
  if (Array.isArray(value)) {
38289
38401
  const tags = value.map((t) => String(t).trim()).filter(Boolean);
@@ -38298,16 +38410,16 @@ function normalizeTags(value) {
38298
38410
  function resolveFeedbackDir(cwd2) {
38299
38411
  const baseCwd = cwd2 && cwd2.trim().length > 0 ? cwd2 : process.cwd();
38300
38412
  const legacyDir = join5(baseCwd, ".oldpal");
38301
- if (existsSync3(legacyDir)) {
38413
+ if (existsSync4(legacyDir)) {
38302
38414
  return join5(legacyDir, "feedback");
38303
38415
  }
38304
38416
  return join5(getConfigDir(), "feedback");
38305
38417
  }
38306
38418
  function saveFeedbackEntry(entry, cwd2) {
38307
38419
  const feedbackDir = resolveFeedbackDir(cwd2);
38308
- mkdirSync(feedbackDir, { recursive: true });
38420
+ mkdirSync2(feedbackDir, { recursive: true });
38309
38421
  const path2 = join5(feedbackDir, `${entry.id}.json`);
38310
- writeFileSync(path2, JSON.stringify(entry, null, 2));
38422
+ writeFileSync2(path2, JSON.stringify(entry, null, 2));
38311
38423
  return { path: path2 };
38312
38424
  }
38313
38425
  function buildEntry(input, overrides) {
@@ -38868,7 +38980,7 @@ class SchedulerTool {
38868
38980
 
38869
38981
  // packages/core/src/tools/image.ts
38870
38982
  init_src();
38871
- import { existsSync as existsSync4, writeFileSync as writeFileSync2, unlinkSync } from "fs";
38983
+ import { existsSync as existsSync5, writeFileSync as writeFileSync3, unlinkSync } from "fs";
38872
38984
  import { tmpdir } from "os";
38873
38985
  import { join as join7 } from "path";
38874
38986
  import { homedir as homedir4 } from "os";
@@ -38949,13 +39061,13 @@ class ImageDisplayTool {
38949
39061
  const buffer = await response.arrayBuffer();
38950
39062
  const ext = contentType.split("/")[1]?.split(";")[0] || "png";
38951
39063
  tempFile = join7(tmpdir(), `assistants-image-${generateId()}.${ext}`);
38952
- writeFileSync2(tempFile, Buffer.from(buffer));
39064
+ writeFileSync3(tempFile, Buffer.from(buffer));
38953
39065
  localPath = tempFile;
38954
39066
  } catch (error) {
38955
39067
  return `Error: Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`;
38956
39068
  }
38957
39069
  }
38958
- if (!existsSync4(localPath)) {
39070
+ if (!existsSync5(localPath)) {
38959
39071
  return `Error: Image file not found: ${localPath}`;
38960
39072
  }
38961
39073
  try {
@@ -38980,7 +39092,7 @@ class ImageDisplayTool {
38980
39092
  } catch (error) {
38981
39093
  return `Error: ${error instanceof Error ? error.message : String(error)}`;
38982
39094
  } finally {
38983
- if (tempFile && existsSync4(tempFile)) {
39095
+ if (tempFile && existsSync5(tempFile)) {
38984
39096
  try {
38985
39097
  unlinkSync(tempFile);
38986
39098
  } catch {}
@@ -39484,7 +39596,7 @@ Respond with JSON only: {"allow": boolean, "reason": string}`;
39484
39596
  }
39485
39597
  }
39486
39598
  // packages/core/src/commands/loader.ts
39487
- import { existsSync as existsSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39599
+ import { existsSync as existsSync6, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
39488
39600
  import { join as join9, basename as basename2, extname } from "path";
39489
39601
  import { homedir as homedir6 } from "os";
39490
39602
 
@@ -39508,7 +39620,7 @@ class CommandLoader {
39508
39620
  await this.loadFromDirectory(legacyProjectDir, "project");
39509
39621
  }
39510
39622
  async loadFromDirectory(dir, source, prefix = "") {
39511
- if (!existsSync5(dir))
39623
+ if (!existsSync6(dir))
39512
39624
  return;
39513
39625
  const entries = readdirSync2(dir);
39514
39626
  for (const entry of entries) {
@@ -39737,13 +39849,217 @@ ${stderr}`;
39737
39849
  }
39738
39850
  }
39739
39851
  // packages/core/src/commands/builtin.ts
39740
- import { join as join10 } from "path";
39852
+ import { join as join11 } from "path";
39741
39853
  import { homedir as homedir7, platform as platform2, release, arch } from "os";
39742
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
39854
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
39743
39855
  init_src();
39744
- var VERSION = "0.6.14";
39745
- function resolveAuthTimeout(resolve4) {
39746
- resolve4({ exitCode: 1, stdout: { toString: () => "{}" } });
39856
+
39857
+ // packages/core/src/projects/store.ts
39858
+ init_src();
39859
+ import { join as join10 } from "path";
39860
+ import { mkdir as mkdir3, readdir as readdir2, readFile as readFile2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
39861
+ function projectsDir(cwd2) {
39862
+ return join10(cwd2, ".oldpal", "projects");
39863
+ }
39864
+ function projectPath(cwd2, id) {
39865
+ return join10(projectsDir(cwd2), `${id}.json`);
39866
+ }
39867
+ async function ensureProjectsDir(cwd2) {
39868
+ await mkdir3(projectsDir(cwd2), { recursive: true });
39869
+ }
39870
+ function normalizeName(name) {
39871
+ return name.trim().toLowerCase();
39872
+ }
39873
+ async function listProjects(cwd2) {
39874
+ try {
39875
+ const dir = projectsDir(cwd2);
39876
+ const files = await readdir2(dir);
39877
+ const projects = [];
39878
+ for (const file of files) {
39879
+ if (!file.endsWith(".json"))
39880
+ continue;
39881
+ try {
39882
+ const raw = await readFile2(join10(dir, file), "utf-8");
39883
+ const parsed = JSON.parse(raw);
39884
+ if (parsed?.id && parsed?.name) {
39885
+ projects.push(parsed);
39886
+ }
39887
+ } catch {}
39888
+ }
39889
+ return projects.sort((a, b) => b.updatedAt - a.updatedAt);
39890
+ } catch {
39891
+ return [];
39892
+ }
39893
+ }
39894
+ async function readProject(cwd2, id) {
39895
+ try {
39896
+ const raw = await readFile2(projectPath(cwd2, id), "utf-8");
39897
+ const project = JSON.parse(raw);
39898
+ if (!project?.id || !project?.name)
39899
+ return null;
39900
+ return project;
39901
+ } catch {
39902
+ return null;
39903
+ }
39904
+ }
39905
+ async function findProjectByName(cwd2, name) {
39906
+ const normalized = normalizeName(name);
39907
+ const projects = await listProjects(cwd2);
39908
+ return projects.find((project) => normalizeName(project.name) === normalized) || null;
39909
+ }
39910
+ async function saveProject(cwd2, project) {
39911
+ await ensureProjectsDir(cwd2);
39912
+ await writeFile2(projectPath(cwd2, project.id), JSON.stringify(project, null, 2), "utf-8");
39913
+ }
39914
+ async function deleteProject(cwd2, id) {
39915
+ try {
39916
+ await unlink2(projectPath(cwd2, id));
39917
+ return true;
39918
+ } catch {
39919
+ return false;
39920
+ }
39921
+ }
39922
+ async function createProject(cwd2, name, description) {
39923
+ const now2 = Date.now();
39924
+ const project = {
39925
+ id: generateId(),
39926
+ name: name.trim(),
39927
+ description: description?.trim() || undefined,
39928
+ createdAt: now2,
39929
+ updatedAt: now2,
39930
+ context: [],
39931
+ plans: []
39932
+ };
39933
+ await saveProject(cwd2, project);
39934
+ return project;
39935
+ }
39936
+ async function updateProject(cwd2, id, updater) {
39937
+ const project = await readProject(cwd2, id);
39938
+ if (!project)
39939
+ return null;
39940
+ const updated = updater(project);
39941
+ await saveProject(cwd2, updated);
39942
+ return updated;
39943
+ }
39944
+ async function ensureDefaultProject(cwd2) {
39945
+ const projects = await listProjects(cwd2);
39946
+ if (projects.length > 0)
39947
+ return projects[0];
39948
+ return createProject(cwd2, "default", "Default project for this folder");
39949
+ }
39950
+ function hasProjectNameConflict(projects, name) {
39951
+ const normalized = normalizeName(name);
39952
+ return projects.some((project) => normalizeName(project.name) === normalized);
39953
+ }
39954
+
39955
+ // packages/core/src/projects/context.ts
39956
+ import { readFile as readFile3 } from "fs/promises";
39957
+ import { resolve as resolve4 } from "path";
39958
+ var DEFAULT_MAX_FILE_BYTES = 12000;
39959
+ function formatPlan(plan) {
39960
+ const lines = [];
39961
+ lines.push(`- ${plan.title} (${plan.steps.length} steps)`);
39962
+ for (const step of plan.steps) {
39963
+ lines.push(` - [${step.status}] ${step.text}`);
39964
+ }
39965
+ return lines.join(`
39966
+ `);
39967
+ }
39968
+ function normalizeEntryLabel(entry) {
39969
+ return entry.label ? entry.label.trim() : entry.value.trim();
39970
+ }
39971
+ async function renderFileEntry(entry, options) {
39972
+ const rawPath = entry.value.trim();
39973
+ const resolved = resolve4(options.cwd, rawPath);
39974
+ const validation = await validatePath(resolved, { allowedPaths: [options.cwd] });
39975
+ if (!validation.valid) {
39976
+ return `- File: ${rawPath} (unavailable: ${validation.error || "invalid path"})`;
39977
+ }
39978
+ let content = "";
39979
+ try {
39980
+ const data = await readFile3(validation.resolved, "utf-8");
39981
+ const limit = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
39982
+ if (data.length > limit) {
39983
+ content = `${data.slice(0, limit)}
39984
+
39985
+ ... [truncated ${data.length - limit} chars]`;
39986
+ } else {
39987
+ content = data;
39988
+ }
39989
+ } catch (error) {
39990
+ return `- File: ${rawPath} (unavailable: ${error instanceof Error ? error.message : String(error)})`;
39991
+ }
39992
+ return `- File: ${rawPath}
39993
+ \`\`\`
39994
+ ${content}
39995
+ \`\`\``;
39996
+ }
39997
+ function renderConnectorEntry(entry, connectors) {
39998
+ const name = entry.value.trim();
39999
+ const connector = connectors?.find((c) => c.name === name);
40000
+ if (!connector) {
40001
+ return `- Connector: ${name}`;
40002
+ }
40003
+ const lines = [];
40004
+ lines.push(`- Connector: ${connector.name}`);
40005
+ if (connector.description) {
40006
+ lines.push(` - ${connector.description}`);
40007
+ }
40008
+ if (connector.cli) {
40009
+ lines.push(` - CLI: ${connector.cli}`);
40010
+ }
40011
+ if (connector.commands && connector.commands.length > 0) {
40012
+ const subset = connector.commands.slice(0, 5);
40013
+ for (const cmd of subset) {
40014
+ lines.push(` - ${cmd.name}: ${cmd.description}`);
40015
+ }
40016
+ if (connector.commands.length > subset.length) {
40017
+ lines.push(` - ... ${connector.commands.length - subset.length} more commands`);
40018
+ }
40019
+ }
40020
+ return lines.join(`
40021
+ `);
40022
+ }
40023
+ function renderGenericEntry(entry) {
40024
+ const label = normalizeEntryLabel(entry);
40025
+ return `- ${entry.type}: ${label}`;
40026
+ }
40027
+ async function buildProjectContext(project, options) {
40028
+ const lines = [];
40029
+ lines.push(`## Project: ${project.name}`);
40030
+ if (project.description) {
40031
+ lines.push(`Description: ${project.description}`);
40032
+ }
40033
+ if (project.context.length > 0) {
40034
+ lines.push("");
40035
+ lines.push("### Project Context");
40036
+ for (const entry of project.context) {
40037
+ if (entry.type === "file") {
40038
+ lines.push(await renderFileEntry(entry, options));
40039
+ continue;
40040
+ }
40041
+ if (entry.type === "connector") {
40042
+ lines.push(renderConnectorEntry(entry, options.connectors));
40043
+ continue;
40044
+ }
40045
+ lines.push(renderGenericEntry(entry));
40046
+ }
40047
+ }
40048
+ if (project.plans.length > 0) {
40049
+ lines.push("");
40050
+ lines.push("### Plans");
40051
+ for (const plan of project.plans) {
40052
+ lines.push(formatPlan(plan));
40053
+ }
40054
+ }
40055
+ return lines.join(`
40056
+ `);
40057
+ }
40058
+
40059
+ // packages/core/src/commands/builtin.ts
40060
+ var VERSION = process.env.ASSISTANTS_VERSION || process.env.npm_package_version || process.env.OLDPAL_VERSION || "unknown";
40061
+ function resolveAuthTimeout(resolve5) {
40062
+ resolve5({ exitCode: 1, stdout: { toString: () => "{}" } });
39747
40063
  }
39748
40064
  function splitArgs(input) {
39749
40065
  const args = [];
@@ -39792,6 +40108,8 @@ class BuiltinCommands {
39792
40108
  loader.register(this.statusCommand());
39793
40109
  loader.register(this.tokensCommand());
39794
40110
  loader.register(this.contextCommand());
40111
+ loader.register(this.projectsCommand());
40112
+ loader.register(this.plansCommand());
39795
40113
  loader.register(this.summarizeCommand());
39796
40114
  loader.register(this.restCommand());
39797
40115
  loader.register(this.voiceCommand());
@@ -40397,130 +40715,722 @@ Identities:
40397
40715
  contextCommand() {
40398
40716
  return {
40399
40717
  name: "context",
40400
- description: "Show context summarization status",
40718
+ description: "Manage injected project context (files, connectors, notes) or show status",
40401
40719
  builtin: true,
40402
40720
  selfHandled: true,
40403
40721
  content: "",
40404
40722
  handler: async (args, context) => {
40405
- const info = context.getContextInfo?.();
40406
- if (!info) {
40723
+ const parts = splitArgs(args);
40724
+ const sub = parts[0] || "status";
40725
+ if (sub === "help") {
40726
+ const usage = [
40727
+ "Usage:",
40728
+ " /context status",
40729
+ " /context list",
40730
+ " /context add file <path>",
40731
+ " /context add connector <name>",
40732
+ " /context add database <name>",
40733
+ " /context add note <text>",
40734
+ " /context add entity <text>",
40735
+ " /context remove <id>",
40736
+ " /context clear"
40737
+ ].join(`
40738
+ `);
40407
40739
  context.emit("text", `
40408
- Context summarization is not available.
40740
+ ${usage}
40409
40741
  `);
40410
40742
  context.emit("done");
40411
40743
  return { handled: true };
40412
40744
  }
40413
- const { config, state } = info;
40414
- const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
40415
- let message = `
40745
+ if (sub === "status") {
40746
+ const info = context.getContextInfo?.();
40747
+ if (!info) {
40748
+ context.emit("text", `
40749
+ Context summarization is not available.
40750
+ `);
40751
+ context.emit("done");
40752
+ return { handled: true };
40753
+ }
40754
+ const { config, state } = info;
40755
+ const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
40756
+ let message = `
40416
40757
  **Context Status**
40417
40758
 
40418
40759
  `;
40419
- message += `**Messages:** ${state.messageCount}
40760
+ message += `**Messages:** ${state.messageCount}
40420
40761
  `;
40421
- message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40762
+ message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40422
40763
  `;
40423
- message += `**Summary Count:** ${state.summaryCount}
40764
+ message += `**Summary Count:** ${state.summaryCount}
40424
40765
  `;
40425
- message += `**Strategy:** ${config.summaryStrategy}
40766
+ message += `**Strategy:** ${config.summaryStrategy}
40426
40767
  `;
40427
- message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40768
+ message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40428
40769
  `;
40429
- if (state.lastSummaryAt) {
40430
- message += `**Last Summary:** ${state.lastSummaryAt}
40770
+ if (state.lastSummaryAt) {
40771
+ message += `**Last Summary:** ${state.lastSummaryAt}
40431
40772
  `;
40432
- if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
40433
- message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
40773
+ if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
40774
+ message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
40434
40775
  `;
40776
+ }
40435
40777
  }
40436
- }
40437
- const barLength = 30;
40438
- const filledLength = Math.round(usedPercent / 100 * barLength);
40439
- const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
40440
- message += `
40778
+ const barLength = 30;
40779
+ const filledLength = Math.round(usedPercent / 100 * barLength);
40780
+ const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
40781
+ message += `
40441
40782
  [${bar}] ${usedPercent}%
40442
40783
  `;
40443
- context.emit("text", message);
40444
- context.emit("done");
40445
- return { handled: true };
40446
- }
40447
- };
40448
- }
40449
- summarizeCommand() {
40450
- return {
40451
- name: "summarize",
40452
- description: "Summarize and compress the current conversation",
40453
- builtin: true,
40454
- selfHandled: true,
40455
- content: "",
40456
- handler: async (args, context) => {
40457
- if (!context.summarizeContext) {
40458
- context.emit("text", `
40459
- Context summarization is not available.
40460
- `);
40784
+ context.emit("text", message);
40461
40785
  context.emit("done");
40462
40786
  return { handled: true };
40463
40787
  }
40464
- const result = await context.summarizeContext();
40465
- if (!result.summarized) {
40466
- context.emit("text", `
40467
- Nothing to summarize right now.
40788
+ const project = await this.ensureActiveProject(context, true);
40789
+ if (!project) {
40790
+ context.emit("text", `No project found. Use /projects new <name> first.
40468
40791
  `);
40469
40792
  context.emit("done");
40470
40793
  return { handled: true };
40471
40794
  }
40472
- let message = `
40473
- **Context Summary Generated**
40474
-
40475
- `;
40476
- message += `Summarized ${result.summarizedCount} message(s).
40477
- `;
40478
- message += `Tokens: ${result.tokensBefore.toLocaleString()} -> ${result.tokensAfter.toLocaleString()}
40795
+ if (sub === "list") {
40796
+ if (project.context.length === 0) {
40797
+ context.emit("text", `
40798
+ No context entries for project "${project.name}".
40799
+ `);
40800
+ context.emit("done");
40801
+ return { handled: true };
40802
+ }
40803
+ let output = `
40804
+ **Context Entries (${project.name})**
40479
40805
 
40480
40806
  `;
40481
- if (result.summary) {
40482
- message += `${result.summary}
40807
+ for (const entry of project.context) {
40808
+ const label = entry.label ? ` (${entry.label})` : "";
40809
+ output += `- ${entry.id} [${entry.type}] ${entry.value}${label}
40483
40810
  `;
40811
+ }
40812
+ context.emit("text", output);
40813
+ context.emit("done");
40814
+ return { handled: true };
40484
40815
  }
40485
- context.emit("text", message);
40816
+ if (sub === "clear") {
40817
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40818
+ ...current,
40819
+ context: [],
40820
+ updatedAt: Date.now()
40821
+ }));
40822
+ if (updated) {
40823
+ await this.applyProjectContext(context, updated);
40824
+ context.emit("text", `Cleared context entries for "${updated.name}".
40825
+ `);
40826
+ context.emit("done");
40827
+ return { handled: true };
40828
+ }
40829
+ }
40830
+ if (sub === "remove") {
40831
+ const id = parts[1];
40832
+ if (!id) {
40833
+ context.emit("text", `Usage: /context remove <id>
40834
+ `);
40835
+ context.emit("done");
40836
+ return { handled: true };
40837
+ }
40838
+ if (!project.context.some((entry) => entry.id === id)) {
40839
+ context.emit("text", `Context entry not found: ${id}
40840
+ `);
40841
+ context.emit("done");
40842
+ return { handled: true };
40843
+ }
40844
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40845
+ ...current,
40846
+ context: current.context.filter((entry) => entry.id !== id),
40847
+ updatedAt: Date.now()
40848
+ }));
40849
+ if (updated) {
40850
+ await this.applyProjectContext(context, updated);
40851
+ context.emit("text", `Removed context entry ${id} from "${updated.name}".
40852
+ `);
40853
+ context.emit("done");
40854
+ return { handled: true };
40855
+ }
40856
+ }
40857
+ if (sub === "add") {
40858
+ const type = parts[1];
40859
+ const value = parts.slice(2).join(" ").trim();
40860
+ if (!type) {
40861
+ context.emit("text", `Usage: /context add <type> <value>
40862
+ `);
40863
+ context.emit("done");
40864
+ return { handled: true };
40865
+ }
40866
+ const allowedTypes = ["file", "connector", "database", "note", "entity"];
40867
+ const entryType = allowedTypes.includes(type) ? type : "note";
40868
+ const entryValue = entryType === "note" && !value ? parts.slice(1).join(" ").trim() : value;
40869
+ if (!entryValue) {
40870
+ context.emit("text", `Error: context value is required.
40871
+ `);
40872
+ context.emit("done");
40873
+ return { handled: true };
40874
+ }
40875
+ const entry = {
40876
+ id: generateId(),
40877
+ type: entryType,
40878
+ value: entryValue,
40879
+ addedAt: Date.now()
40880
+ };
40881
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40882
+ ...current,
40883
+ context: [...current.context, entry],
40884
+ updatedAt: Date.now()
40885
+ }));
40886
+ if (updated) {
40887
+ await this.applyProjectContext(context, updated);
40888
+ context.emit("text", `Added ${entry.type} context to "${updated.name}".
40889
+ `);
40890
+ context.emit("done");
40891
+ return { handled: true };
40892
+ }
40893
+ }
40894
+ context.emit("text", `Unknown /context command. Use /context help.
40895
+ `);
40486
40896
  context.emit("done");
40487
40897
  return { handled: true };
40488
40898
  }
40489
40899
  };
40490
40900
  }
40491
- restCommand() {
40901
+ projectsCommand() {
40492
40902
  return {
40493
- name: "rest",
40494
- description: "Recharge assistant energy",
40903
+ name: "projects",
40904
+ description: "Manage projects inside this folder",
40495
40905
  builtin: true,
40496
40906
  selfHandled: true,
40497
40907
  content: "",
40498
40908
  handler: async (args, context) => {
40499
- if (!context.restEnergy) {
40909
+ const parts = splitArgs(args);
40910
+ const sub = parts[0] || "list";
40911
+ if (sub === "help") {
40912
+ const usage = [
40913
+ "Usage:",
40914
+ " /projects list",
40915
+ " /projects new <name>",
40916
+ " /projects use <id|name>",
40917
+ " /projects show [id|name]",
40918
+ " /projects delete <id|name>",
40919
+ " /projects describe <id|name> <description>"
40920
+ ].join(`
40921
+ `);
40500
40922
  context.emit("text", `
40501
- Energy system is not available.
40923
+ ${usage}
40502
40924
  `);
40503
40925
  context.emit("done");
40504
40926
  return { handled: true };
40505
40927
  }
40506
- const parsed = parseInt(args.trim(), 10);
40507
- const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
40508
- context.restEnergy(amount);
40509
- const state = context.getEnergyState?.();
40510
- if (state) {
40511
- const percent = Math.round(state.current / Math.max(1, state.max) * 100);
40512
- context.emit("text", `
40513
- Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
40514
- `);
40515
- } else {
40516
- context.emit("text", `
40517
- Energy restored.
40928
+ if (sub === "list" || sub === "ls") {
40929
+ const projects = await listProjects(context.cwd);
40930
+ if (projects.length === 0) {
40931
+ context.emit("text", `
40932
+ No projects found. Use /projects new <name>.
40518
40933
  `);
40519
- }
40520
- context.emit("done");
40521
- return { handled: true };
40522
- }
40523
- };
40934
+ context.emit("done");
40935
+ return { handled: true };
40936
+ }
40937
+ const activeId = context.getActiveProjectId?.();
40938
+ let output = `
40939
+ **Projects**
40940
+
40941
+ `;
40942
+ for (const project of projects) {
40943
+ const marker = project.id === activeId ? "*" : " ";
40944
+ output += `${marker} ${project.name} (${project.id})
40945
+ `;
40946
+ }
40947
+ context.emit("text", output);
40948
+ context.emit("done");
40949
+ return { handled: true };
40950
+ }
40951
+ if (sub === "new" || sub === "create") {
40952
+ const name = parts.slice(1).join(" ").trim();
40953
+ if (!name) {
40954
+ context.emit("text", `Usage: /projects new <name>
40955
+ `);
40956
+ context.emit("done");
40957
+ return { handled: true };
40958
+ }
40959
+ const existing = await listProjects(context.cwd);
40960
+ if (hasProjectNameConflict(existing, name)) {
40961
+ context.emit("text", `Project "${name}" already exists.
40962
+ `);
40963
+ context.emit("done");
40964
+ return { handled: true };
40965
+ }
40966
+ const project = await createProject(context.cwd, name);
40967
+ context.setActiveProjectId?.(project.id);
40968
+ await this.applyProjectContext(context, project);
40969
+ context.emit("text", `Created project "${project.name}" (${project.id}).
40970
+ `);
40971
+ context.emit("done");
40972
+ return { handled: true };
40973
+ }
40974
+ if (sub === "use" || sub === "switch") {
40975
+ const target = parts.slice(1).join(" ").trim();
40976
+ if (!target) {
40977
+ context.emit("text", `Usage: /projects use <id|name>
40978
+ `);
40979
+ context.emit("done");
40980
+ return { handled: true };
40981
+ }
40982
+ const project = await this.resolveProject(context, target);
40983
+ if (!project) {
40984
+ context.emit("text", `Project not found: ${target}
40985
+ `);
40986
+ context.emit("done");
40987
+ return { handled: true };
40988
+ }
40989
+ context.setActiveProjectId?.(project.id);
40990
+ await this.applyProjectContext(context, project);
40991
+ context.emit("text", `Switched to project "${project.name}".
40992
+ `);
40993
+ context.emit("done");
40994
+ return { handled: true };
40995
+ }
40996
+ if (sub === "show" || sub === "info") {
40997
+ const target = parts.slice(1).join(" ").trim();
40998
+ const project = target ? await this.resolveProject(context, target) : await this.ensureActiveProject(context, false);
40999
+ if (!project) {
41000
+ context.emit("text", `No project selected. Use /projects use <id|name>.
41001
+ `);
41002
+ context.emit("done");
41003
+ return { handled: true };
41004
+ }
41005
+ let output = `
41006
+ **Project: ${project.name}**
41007
+
41008
+ `;
41009
+ output += `ID: ${project.id}
41010
+ `;
41011
+ if (project.description) {
41012
+ output += `Description: ${project.description}
41013
+ `;
41014
+ }
41015
+ output += `Context entries: ${project.context.length}
41016
+ `;
41017
+ output += `Plans: ${project.plans.length}
41018
+ `;
41019
+ context.emit("text", output);
41020
+ context.emit("done");
41021
+ return { handled: true };
41022
+ }
41023
+ if (sub === "describe" || sub === "desc") {
41024
+ const target = parts[1];
41025
+ const description = parts.slice(2).join(" ").trim();
41026
+ if (!target || !description) {
41027
+ context.emit("text", `Usage: /projects describe <id|name> <description>
41028
+ `);
41029
+ context.emit("done");
41030
+ return { handled: true };
41031
+ }
41032
+ const project = await this.resolveProject(context, target);
41033
+ if (!project) {
41034
+ context.emit("text", `Project not found: ${target}
41035
+ `);
41036
+ context.emit("done");
41037
+ return { handled: true };
41038
+ }
41039
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41040
+ ...current,
41041
+ description,
41042
+ updatedAt: Date.now()
41043
+ }));
41044
+ if (updated) {
41045
+ await this.applyProjectContext(context, updated);
41046
+ context.emit("text", `Updated project "${updated.name}".
41047
+ `);
41048
+ context.emit("done");
41049
+ return { handled: true };
41050
+ }
41051
+ }
41052
+ if (sub === "delete" || sub === "rm") {
41053
+ const target = parts.slice(1).join(" ").trim();
41054
+ if (!target) {
41055
+ context.emit("text", `Usage: /projects delete <id|name>
41056
+ `);
41057
+ context.emit("done");
41058
+ return { handled: true };
41059
+ }
41060
+ const project = await this.resolveProject(context, target);
41061
+ if (!project) {
41062
+ context.emit("text", `Project not found: ${target}
41063
+ `);
41064
+ context.emit("done");
41065
+ return { handled: true };
41066
+ }
41067
+ const ok = await deleteProject(context.cwd, project.id);
41068
+ if (ok) {
41069
+ if (context.getActiveProjectId?.() === project.id) {
41070
+ context.setActiveProjectId?.(null);
41071
+ context.setProjectContext?.(null);
41072
+ }
41073
+ context.emit("text", `Deleted project "${project.name}".
41074
+ `);
41075
+ context.emit("done");
41076
+ return { handled: true };
41077
+ }
41078
+ }
41079
+ context.emit("text", `Unknown /projects command. Use /projects help.
41080
+ `);
41081
+ context.emit("done");
41082
+ return { handled: true };
41083
+ }
41084
+ };
41085
+ }
41086
+ plansCommand() {
41087
+ return {
41088
+ name: "plans",
41089
+ description: "Manage plans linked to the active project",
41090
+ builtin: true,
41091
+ selfHandled: true,
41092
+ content: "",
41093
+ handler: async (args, context) => {
41094
+ const parts = splitArgs(args);
41095
+ const sub = parts[0] || "list";
41096
+ if (sub === "help") {
41097
+ const usage = [
41098
+ "Usage:",
41099
+ " /plans list",
41100
+ " /plans new <title>",
41101
+ " /plans show <planId>",
41102
+ " /plans add <planId> <step>",
41103
+ " /plans set <planId> <stepId> <todo|doing|done|blocked>",
41104
+ " /plans remove <planId> <stepId>",
41105
+ " /plans delete <planId>"
41106
+ ].join(`
41107
+ `);
41108
+ context.emit("text", `
41109
+ ${usage}
41110
+ `);
41111
+ context.emit("done");
41112
+ return { handled: true };
41113
+ }
41114
+ const project = await this.ensureActiveProject(context, true);
41115
+ if (!project) {
41116
+ context.emit("text", `No project found. Use /projects new <name> first.
41117
+ `);
41118
+ context.emit("done");
41119
+ return { handled: true };
41120
+ }
41121
+ if (sub === "list" || sub === "ls") {
41122
+ if (project.plans.length === 0) {
41123
+ context.emit("text", `
41124
+ No plans for project "${project.name}".
41125
+ `);
41126
+ context.emit("done");
41127
+ return { handled: true };
41128
+ }
41129
+ let output = `
41130
+ **Plans (${project.name})**
41131
+
41132
+ `;
41133
+ for (const plan of project.plans) {
41134
+ output += `- ${plan.id} ${plan.title} (${plan.steps.length} steps)
41135
+ `;
41136
+ }
41137
+ context.emit("text", output);
41138
+ context.emit("done");
41139
+ return { handled: true };
41140
+ }
41141
+ if (sub === "new" || sub === "create") {
41142
+ const title = parts.slice(1).join(" ").trim();
41143
+ if (!title) {
41144
+ context.emit("text", `Usage: /plans new <title>
41145
+ `);
41146
+ context.emit("done");
41147
+ return { handled: true };
41148
+ }
41149
+ const now2 = Date.now();
41150
+ const plan = {
41151
+ id: generateId(),
41152
+ title,
41153
+ createdAt: now2,
41154
+ updatedAt: now2,
41155
+ steps: []
41156
+ };
41157
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41158
+ ...current,
41159
+ plans: [...current.plans, plan],
41160
+ updatedAt: now2
41161
+ }));
41162
+ if (updated) {
41163
+ await this.applyProjectContext(context, updated);
41164
+ context.emit("text", `Created plan "${plan.title}" (${plan.id}).
41165
+ `);
41166
+ context.emit("done");
41167
+ return { handled: true };
41168
+ }
41169
+ }
41170
+ if (sub === "show") {
41171
+ const id = parts[1];
41172
+ if (!id) {
41173
+ context.emit("text", `Usage: /plans show <planId>
41174
+ `);
41175
+ context.emit("done");
41176
+ return { handled: true };
41177
+ }
41178
+ const plan = project.plans.find((p) => p.id === id);
41179
+ if (!plan) {
41180
+ context.emit("text", `Plan not found: ${id}
41181
+ `);
41182
+ context.emit("done");
41183
+ return { handled: true };
41184
+ }
41185
+ let output = `
41186
+ **Plan: ${plan.title}**
41187
+
41188
+ `;
41189
+ output += `ID: ${plan.id}
41190
+ `;
41191
+ if (plan.steps.length === 0) {
41192
+ output += `No steps yet.
41193
+ `;
41194
+ } else {
41195
+ for (const step of plan.steps) {
41196
+ output += `- ${step.id} [${step.status}] ${step.text}
41197
+ `;
41198
+ }
41199
+ }
41200
+ context.emit("text", output);
41201
+ context.emit("done");
41202
+ return { handled: true };
41203
+ }
41204
+ if (sub === "add") {
41205
+ const planId = parts[1];
41206
+ const text = parts.slice(2).join(" ").trim();
41207
+ if (!planId || !text) {
41208
+ context.emit("text", `Usage: /plans add <planId> <step>
41209
+ `);
41210
+ context.emit("done");
41211
+ return { handled: true };
41212
+ }
41213
+ if (!project.plans.some((plan) => plan.id === planId)) {
41214
+ context.emit("text", `Plan not found: ${planId}
41215
+ `);
41216
+ context.emit("done");
41217
+ return { handled: true };
41218
+ }
41219
+ const now2 = Date.now();
41220
+ const step = {
41221
+ id: generateId(),
41222
+ text,
41223
+ status: "todo",
41224
+ createdAt: now2,
41225
+ updatedAt: now2
41226
+ };
41227
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41228
+ ...current,
41229
+ plans: current.plans.map((plan) => plan.id === planId ? { ...plan, steps: [...plan.steps, step], updatedAt: now2 } : plan),
41230
+ updatedAt: now2
41231
+ }));
41232
+ if (updated) {
41233
+ await this.applyProjectContext(context, updated);
41234
+ context.emit("text", `Added step to plan ${planId}.
41235
+ `);
41236
+ context.emit("done");
41237
+ return { handled: true };
41238
+ }
41239
+ }
41240
+ if (sub === "set") {
41241
+ const planId = parts[1];
41242
+ const stepId = parts[2];
41243
+ const status = parts[3];
41244
+ if (!planId || !stepId || !status) {
41245
+ context.emit("text", `Usage: /plans set <planId> <stepId> <todo|doing|done|blocked>
41246
+ `);
41247
+ context.emit("done");
41248
+ return { handled: true };
41249
+ }
41250
+ const plan = project.plans.find((item) => item.id === planId);
41251
+ if (!plan) {
41252
+ context.emit("text", `Plan not found: ${planId}
41253
+ `);
41254
+ context.emit("done");
41255
+ return { handled: true };
41256
+ }
41257
+ if (!plan.steps.some((step) => step.id === stepId)) {
41258
+ context.emit("text", `Step not found: ${stepId}
41259
+ `);
41260
+ context.emit("done");
41261
+ return { handled: true };
41262
+ }
41263
+ const allowed = ["todo", "doing", "done", "blocked"];
41264
+ if (!allowed.includes(status)) {
41265
+ context.emit("text", `Invalid status. Use todo, doing, done, or blocked.
41266
+ `);
41267
+ context.emit("done");
41268
+ return { handled: true };
41269
+ }
41270
+ const now2 = Date.now();
41271
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41272
+ ...current,
41273
+ plans: current.plans.map((plan2) => plan2.id === planId ? {
41274
+ ...plan2,
41275
+ steps: plan2.steps.map((step) => step.id === stepId ? { ...step, status, updatedAt: now2 } : step),
41276
+ updatedAt: now2
41277
+ } : plan2),
41278
+ updatedAt: now2
41279
+ }));
41280
+ if (updated) {
41281
+ await this.applyProjectContext(context, updated);
41282
+ context.emit("text", `Updated step ${stepId} to ${status}.
41283
+ `);
41284
+ context.emit("done");
41285
+ return { handled: true };
41286
+ }
41287
+ }
41288
+ if (sub === "remove") {
41289
+ const planId = parts[1];
41290
+ const stepId = parts[2];
41291
+ if (!planId || !stepId) {
41292
+ context.emit("text", `Usage: /plans remove <planId> <stepId>
41293
+ `);
41294
+ context.emit("done");
41295
+ return { handled: true };
41296
+ }
41297
+ const plan = project.plans.find((item) => item.id === planId);
41298
+ if (!plan) {
41299
+ context.emit("text", `Plan not found: ${planId}
41300
+ `);
41301
+ context.emit("done");
41302
+ return { handled: true };
41303
+ }
41304
+ if (!plan.steps.some((step) => step.id === stepId)) {
41305
+ context.emit("text", `Step not found: ${stepId}
41306
+ `);
41307
+ context.emit("done");
41308
+ return { handled: true };
41309
+ }
41310
+ const now2 = Date.now();
41311
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41312
+ ...current,
41313
+ plans: current.plans.map((plan2) => plan2.id === planId ? { ...plan2, steps: plan2.steps.filter((step) => step.id !== stepId), updatedAt: now2 } : plan2),
41314
+ updatedAt: now2
41315
+ }));
41316
+ if (updated) {
41317
+ await this.applyProjectContext(context, updated);
41318
+ context.emit("text", `Removed step ${stepId} from plan ${planId}.
41319
+ `);
41320
+ context.emit("done");
41321
+ return { handled: true };
41322
+ }
41323
+ }
41324
+ if (sub === "delete" || sub === "rm") {
41325
+ const planId = parts[1];
41326
+ if (!planId) {
41327
+ context.emit("text", `Usage: /plans delete <planId>
41328
+ `);
41329
+ context.emit("done");
41330
+ return { handled: true };
41331
+ }
41332
+ if (!project.plans.some((plan) => plan.id === planId)) {
41333
+ context.emit("text", `Plan not found: ${planId}
41334
+ `);
41335
+ context.emit("done");
41336
+ return { handled: true };
41337
+ }
41338
+ const now2 = Date.now();
41339
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41340
+ ...current,
41341
+ plans: current.plans.filter((plan) => plan.id !== planId),
41342
+ updatedAt: now2
41343
+ }));
41344
+ if (updated) {
41345
+ await this.applyProjectContext(context, updated);
41346
+ context.emit("text", `Deleted plan ${planId}.
41347
+ `);
41348
+ context.emit("done");
41349
+ return { handled: true };
41350
+ }
41351
+ }
41352
+ context.emit("text", `Unknown /plans command. Use /plans help.
41353
+ `);
41354
+ context.emit("done");
41355
+ return { handled: true };
41356
+ }
41357
+ };
41358
+ }
41359
+ summarizeCommand() {
41360
+ return {
41361
+ name: "summarize",
41362
+ description: "Summarize and compress the current conversation",
41363
+ builtin: true,
41364
+ selfHandled: true,
41365
+ content: "",
41366
+ handler: async (args, context) => {
41367
+ if (!context.summarizeContext) {
41368
+ context.emit("text", `
41369
+ Context summarization is not available.
41370
+ `);
41371
+ context.emit("done");
41372
+ return { handled: true };
41373
+ }
41374
+ const result = await context.summarizeContext();
41375
+ if (!result.summarized) {
41376
+ context.emit("text", `
41377
+ Nothing to summarize right now.
41378
+ `);
41379
+ context.emit("done");
41380
+ return { handled: true };
41381
+ }
41382
+ let message = `
41383
+ **Context Summary Generated**
41384
+
41385
+ `;
41386
+ message += `Summarized ${result.summarizedCount} message(s).
41387
+ `;
41388
+ message += `Tokens: ${result.tokensBefore.toLocaleString()} -> ${result.tokensAfter.toLocaleString()}
41389
+
41390
+ `;
41391
+ if (result.summary) {
41392
+ message += `${result.summary}
41393
+ `;
41394
+ }
41395
+ context.emit("text", message);
41396
+ context.emit("done");
41397
+ return { handled: true };
41398
+ }
41399
+ };
41400
+ }
41401
+ restCommand() {
41402
+ return {
41403
+ name: "rest",
41404
+ description: "Recharge assistant energy",
41405
+ builtin: true,
41406
+ selfHandled: true,
41407
+ content: "",
41408
+ handler: async (args, context) => {
41409
+ if (!context.restEnergy) {
41410
+ context.emit("text", `
41411
+ Energy system is not available.
41412
+ `);
41413
+ context.emit("done");
41414
+ return { handled: true };
41415
+ }
41416
+ const parsed = parseInt(args.trim(), 10);
41417
+ const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
41418
+ context.restEnergy(amount);
41419
+ const state = context.getEnergyState?.();
41420
+ if (state) {
41421
+ const percent = Math.round(state.current / Math.max(1, state.max) * 100);
41422
+ context.emit("text", `
41423
+ Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
41424
+ `);
41425
+ } else {
41426
+ context.emit("text", `
41427
+ Energy restored.
41428
+ `);
41429
+ }
41430
+ context.emit("done");
41431
+ return { handled: true };
41432
+ }
41433
+ };
40524
41434
  }
40525
41435
  skillsCommand(loader) {
40526
41436
  return {
@@ -40562,7 +41472,7 @@ ${context.skills.length} skill(s) available.
40562
41472
  statusCommand() {
40563
41473
  return {
40564
41474
  name: "status",
40565
- description: "Show current session status and token usage",
41475
+ description: "Show current session status, energy, identity, and token usage",
40566
41476
  builtin: true,
40567
41477
  selfHandled: true,
40568
41478
  content: "",
@@ -40572,11 +41482,46 @@ ${context.skills.length} skill(s) available.
40572
41482
  let message = `
40573
41483
  **Session Status**
40574
41484
 
41485
+ `;
41486
+ message += `**Session ID:** ${context.sessionId}
40575
41487
  `;
40576
41488
  message += `**Working Directory:** ${context.cwd}
40577
41489
  `;
40578
- message += `**Session ID:** ${context.sessionId}
41490
+ const assistant = context.getAssistantManager?.()?.getActive();
41491
+ const identity = context.getIdentityManager?.()?.getActive();
41492
+ if (assistant) {
41493
+ message += `**Assistant:** ${assistant.name}`;
41494
+ if (identity) {
41495
+ message += ` \xB7 ${identity.name}`;
41496
+ }
41497
+ message += `
40579
41498
  `;
41499
+ }
41500
+ const energyState = context.getEnergyState?.();
41501
+ if (energyState) {
41502
+ const energyPercent = Math.round(energyState.current / Math.max(1, energyState.max) * 100);
41503
+ const energyBar = "\u2588".repeat(Math.round(energyPercent / 10)) + "\u2591".repeat(10 - Math.round(energyPercent / 10));
41504
+ const energyEmoji = energyPercent > 70 ? "\u26A1" : energyPercent > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
41505
+ message += `**Energy:** ${energyEmoji} [${energyBar}] ${energyPercent}% (${energyState.current}/${energyState.max})
41506
+ `;
41507
+ }
41508
+ const voiceState = context.getVoiceState?.();
41509
+ if (voiceState?.enabled) {
41510
+ const voiceActivity = voiceState.isSpeaking ? "speaking" : voiceState.isListening ? "listening" : "idle";
41511
+ message += `**Voice:** ${voiceActivity}`;
41512
+ if (voiceState.sttProvider || voiceState.ttsProvider) {
41513
+ message += ` (STT: ${voiceState.sttProvider || "n/a"}, TTS: ${voiceState.ttsProvider || "n/a"})`;
41514
+ }
41515
+ message += `
41516
+ `;
41517
+ }
41518
+ if (context.getActiveProjectId) {
41519
+ const projectId = context.getActiveProjectId();
41520
+ if (projectId) {
41521
+ message += `**Active Project:** ${projectId}
41522
+ `;
41523
+ }
41524
+ }
40580
41525
  message += `**Messages:** ${context.messages.length}
40581
41526
  `;
40582
41527
  message += `**Available Tools:** ${context.tools.length}
@@ -40663,9 +41608,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40663
41608
  content: "",
40664
41609
  handler: async (args, context) => {
40665
41610
  const configPaths = [
40666
- join10(context.cwd, ".assistants", "config.json"),
40667
- join10(context.cwd, ".assistants", "config.local.json"),
40668
- join10(getConfigDir(), "config.json")
41611
+ join11(context.cwd, ".assistants", "config.json"),
41612
+ join11(context.cwd, ".assistants", "config.local.json"),
41613
+ join11(getConfigDir(), "config.json")
40669
41614
  ];
40670
41615
  let message = `
40671
41616
  **Configuration**
@@ -40674,7 +41619,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40674
41619
  message += `**Config File Locations:**
40675
41620
  `;
40676
41621
  for (const path2 of configPaths) {
40677
- const exists = existsSync6(path2);
41622
+ const exists = existsSync7(path2);
40678
41623
  message += ` ${exists ? "\u2713" : "\u25CB"} ${path2}
40679
41624
  `;
40680
41625
  }
@@ -40683,9 +41628,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40683
41628
  message += `
40684
41629
  **Commands Directories:**
40685
41630
  `;
40686
- message += ` - Project: ${join10(context.cwd, ".assistants", "commands")}
41631
+ message += ` - Project: ${join11(context.cwd, ".assistants", "commands")}
40687
41632
  `;
40688
- message += ` - Global: ${join10(homeDir, ".assistants", "commands")}
41633
+ message += ` - Global: ${join11(homeDir, ".assistants", "commands")}
40689
41634
  `;
40690
41635
  context.emit("text", message);
40691
41636
  context.emit("done");
@@ -40701,8 +41646,8 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40701
41646
  selfHandled: true,
40702
41647
  content: "",
40703
41648
  handler: async (args, context) => {
40704
- const commandsDir = join10(context.cwd, ".assistants", "commands");
40705
- mkdirSync2(commandsDir, { recursive: true });
41649
+ const commandsDir = join11(context.cwd, ".assistants", "commands");
41650
+ mkdirSync3(commandsDir, { recursive: true });
40706
41651
  const exampleCommand = `---
40707
41652
  name: reflect
40708
41653
  description: Reflect on the conversation and suggest next steps
@@ -40717,9 +41662,9 @@ Please summarize the last interaction and suggest 2-3 next steps.
40717
41662
  - Focus on clarity
40718
41663
  - Ask a follow-up question if needed
40719
41664
  `;
40720
- const examplePath = join10(commandsDir, "reflect.md");
40721
- if (!existsSync6(examplePath)) {
40722
- writeFileSync3(examplePath, exampleCommand);
41665
+ const examplePath = join11(commandsDir, "reflect.md");
41666
+ if (!existsSync7(examplePath)) {
41667
+ writeFileSync4(examplePath, exampleCommand);
40723
41668
  }
40724
41669
  let message = `
40725
41670
  **Initialized assistants**
@@ -41038,8 +41983,8 @@ Connector "${connectorName}" not found.
41038
41983
  `;
41039
41984
  try {
41040
41985
  let timeoutId = null;
41041
- const timeoutPromise = new Promise((resolve4) => {
41042
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
41986
+ const timeoutPromise = new Promise((resolve5) => {
41987
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41043
41988
  });
41044
41989
  const result = await Promise.race([
41045
41990
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41101,8 +42046,8 @@ Connector "${connectorName}" not found.
41101
42046
  let status = "\u25CB";
41102
42047
  let timeoutId = null;
41103
42048
  try {
41104
- const timeoutPromise = new Promise((resolve4) => {
41105
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
42049
+ const timeoutPromise = new Promise((resolve5) => {
42050
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41106
42051
  });
41107
42052
  const result = await Promise.race([
41108
42053
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41377,6 +42322,35 @@ ${repoUrl}/issues/new
41377
42322
  }
41378
42323
  };
41379
42324
  }
42325
+ async resolveProject(context, target) {
42326
+ const byId = await readProject(context.cwd, target);
42327
+ if (byId)
42328
+ return byId;
42329
+ return findProjectByName(context.cwd, target);
42330
+ }
42331
+ async ensureActiveProject(context, createIfMissing) {
42332
+ const activeId = context.getActiveProjectId?.();
42333
+ if (activeId) {
42334
+ const project2 = await readProject(context.cwd, activeId);
42335
+ if (project2)
42336
+ return project2;
42337
+ }
42338
+ if (!createIfMissing)
42339
+ return null;
42340
+ const project = await ensureDefaultProject(context.cwd);
42341
+ context.setActiveProjectId?.(project.id);
42342
+ await this.applyProjectContext(context, project);
42343
+ return project;
42344
+ }
42345
+ async applyProjectContext(context, project) {
42346
+ if (!context.setProjectContext)
42347
+ return;
42348
+ const projectContext = await buildProjectContext(project, {
42349
+ cwd: context.cwd,
42350
+ connectors: context.connectors
42351
+ });
42352
+ context.setProjectContext(projectContext);
42353
+ }
41380
42354
  }
41381
42355
  // packages/core/src/llm/client.ts
41382
42356
  async function createLLMClient(config) {
@@ -41389,8 +42363,8 @@ async function createLLMClient(config) {
41389
42363
 
41390
42364
  // packages/core/src/heartbeat/manager.ts
41391
42365
  import { dirname as dirname5 } from "path";
41392
- import { mkdirSync as mkdirSync3 } from "fs";
41393
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
42366
+ import { mkdirSync as mkdirSync4 } from "fs";
42367
+ import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
41394
42368
 
41395
42369
  class HeartbeatManager {
41396
42370
  config;
@@ -41411,7 +42385,7 @@ class HeartbeatManager {
41411
42385
  uptimeSeconds: 0
41412
42386
  };
41413
42387
  const dir = dirname5(config.persistPath);
41414
- mkdirSync3(dir, { recursive: true });
42388
+ mkdirSync4(dir, { recursive: true });
41415
42389
  }
41416
42390
  start(sessionId) {
41417
42391
  if (this.intervalId)
@@ -41469,12 +42443,12 @@ class HeartbeatManager {
41469
42443
  }
41470
42444
  async persist(heartbeat) {
41471
42445
  try {
41472
- await writeFile2(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
42446
+ await writeFile3(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
41473
42447
  } catch {}
41474
42448
  }
41475
42449
  static async checkStale(path2, thresholdMs) {
41476
42450
  try {
41477
- const content = await readFile2(path2, "utf-8");
42451
+ const content = await readFile4(path2, "utf-8");
41478
42452
  const heartbeat = JSON.parse(content);
41479
42453
  const age = Date.now() - new Date(heartbeat.timestamp).getTime();
41480
42454
  return { isStale: age > thresholdMs, lastHeartbeat: heartbeat };
@@ -41485,23 +42459,23 @@ class HeartbeatManager {
41485
42459
  }
41486
42460
  // packages/core/src/heartbeat/persistence.ts
41487
42461
  import { dirname as dirname6 } from "path";
41488
- import { mkdirSync as mkdirSync4 } from "fs";
41489
- import { readFile as readFile3, writeFile as writeFile3, unlink as unlink2 } from "fs/promises";
42462
+ import { mkdirSync as mkdirSync5 } from "fs";
42463
+ import { readFile as readFile5, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
41490
42464
 
41491
42465
  class StatePersistence {
41492
42466
  path;
41493
42467
  constructor(path2) {
41494
42468
  this.path = path2;
41495
- mkdirSync4(dirname6(path2), { recursive: true });
42469
+ mkdirSync5(dirname6(path2), { recursive: true });
41496
42470
  }
41497
42471
  async save(state) {
41498
42472
  try {
41499
- await writeFile3(this.path, JSON.stringify(state, null, 2));
42473
+ await writeFile4(this.path, JSON.stringify(state, null, 2));
41500
42474
  } catch {}
41501
42475
  }
41502
42476
  async load() {
41503
42477
  try {
41504
- const content = await readFile3(this.path, "utf-8");
42478
+ const content = await readFile5(this.path, "utf-8");
41505
42479
  return JSON.parse(content);
41506
42480
  } catch {
41507
42481
  return null;
@@ -41509,7 +42483,7 @@ class StatePersistence {
41509
42483
  }
41510
42484
  async clear() {
41511
42485
  try {
41512
- await unlink2(this.path);
42486
+ await unlink3(this.path);
41513
42487
  } catch {}
41514
42488
  }
41515
42489
  }
@@ -41712,23 +42686,23 @@ class EnergyManager {
41712
42686
  }
41713
42687
  // packages/core/src/energy/storage.ts
41714
42688
  import { dirname as dirname7 } from "path";
41715
- import { mkdirSync as mkdirSync5 } from "fs";
41716
- import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
42689
+ import { mkdirSync as mkdirSync6 } from "fs";
42690
+ import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
41717
42691
 
41718
42692
  class EnergyStorage {
41719
42693
  path;
41720
42694
  constructor(path2) {
41721
42695
  this.path = path2;
41722
- mkdirSync5(dirname7(path2), { recursive: true });
42696
+ mkdirSync6(dirname7(path2), { recursive: true });
41723
42697
  }
41724
42698
  async save(state) {
41725
42699
  try {
41726
- await writeFile4(this.path, JSON.stringify(state, null, 2));
42700
+ await writeFile5(this.path, JSON.stringify(state, null, 2));
41727
42701
  } catch {}
41728
42702
  }
41729
42703
  async load() {
41730
42704
  try {
41731
- const content = await readFile4(this.path, "utf-8");
42705
+ const content = await readFile6(this.path, "utf-8");
41732
42706
  return JSON.parse(content);
41733
42707
  } catch {
41734
42708
  return null;
@@ -41786,18 +42760,18 @@ function validateToolCalls(toolCalls, tools) {
41786
42760
  }
41787
42761
 
41788
42762
  // packages/core/src/voice/utils.ts
41789
- import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
42763
+ import { existsSync as existsSync9, readFileSync as readFileSync4 } from "fs";
41790
42764
  import { homedir as homedir9 } from "os";
41791
- import { join as join12 } from "path";
42765
+ import { join as join13 } from "path";
41792
42766
  import { spawnSync } from "child_process";
41793
42767
  function loadApiKeyFromSecrets2(key) {
41794
42768
  const envHome = process.env.HOME || process.env.USERPROFILE;
41795
42769
  const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
41796
- const secretsPath = join12(homeDir, ".secrets");
41797
- if (!existsSync8(secretsPath))
42770
+ const secretsPath = join13(homeDir, ".secrets");
42771
+ if (!existsSync9(secretsPath))
41798
42772
  return;
41799
42773
  try {
41800
- const content = readFileSync3(secretsPath, "utf-8");
42774
+ const content = readFileSync4(secretsPath, "utf-8");
41801
42775
  const match = content.match(new RegExp(`export\\s+${key}\\s*=\\s*['"]?([^'"\\n]+)['"]?`));
41802
42776
  return match?.[1];
41803
42777
  } catch {
@@ -41867,8 +42841,8 @@ class SystemSTT {
41867
42841
  // packages/core/src/voice/tts.ts
41868
42842
  import { spawnSync as spawnSync2 } from "child_process";
41869
42843
  import { tmpdir as tmpdir2 } from "os";
41870
- import { join as join13 } from "path";
41871
- import { readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
42844
+ import { join as join14 } from "path";
42845
+ import { readFileSync as readFileSync5, unlinkSync as unlinkSync2 } from "fs";
41872
42846
  class ElevenLabsTTS {
41873
42847
  apiKey;
41874
42848
  voiceId;
@@ -41971,7 +42945,7 @@ class SystemTTS {
41971
42945
  if (!say) {
41972
42946
  throw new Error('System TTS not available: missing "say" command.');
41973
42947
  }
41974
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
42948
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
41975
42949
  const args = [];
41976
42950
  if (this.voiceId) {
41977
42951
  args.push("-v", this.voiceId);
@@ -41984,7 +42958,7 @@ class SystemTTS {
41984
42958
  if (result.status !== 0) {
41985
42959
  throw new Error(`System TTS failed: ${result.stderr || "unknown error"}`);
41986
42960
  }
41987
- const audio = readFileSync4(output);
42961
+ const audio = readFileSync5(output);
41988
42962
  unlinkSync2(output);
41989
42963
  return {
41990
42964
  audio: audio.buffer.slice(audio.byteOffset, audio.byteOffset + audio.byteLength),
@@ -41993,7 +42967,7 @@ class SystemTTS {
41993
42967
  }
41994
42968
  const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
41995
42969
  if (espeak) {
41996
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
42970
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
41997
42971
  const args = ["-w", output];
41998
42972
  if (this.voiceId) {
41999
42973
  args.push("-v", this.voiceId);
@@ -42006,7 +42980,7 @@ class SystemTTS {
42006
42980
  if (result.status !== 0) {
42007
42981
  throw new Error(`System TTS failed: ${result.stderr || "unknown error"}`);
42008
42982
  }
42009
- const audio = readFileSync4(output);
42983
+ const audio = readFileSync5(output);
42010
42984
  unlinkSync2(output);
42011
42985
  return {
42012
42986
  audio: audio.buffer.slice(audio.byteOffset, audio.byteOffset + audio.byteLength),
@@ -42020,32 +42994,32 @@ class SystemTTS {
42020
42994
  // packages/core/src/voice/player.ts
42021
42995
  import { spawn } from "child_process";
42022
42996
  import { tmpdir as tmpdir3 } from "os";
42023
- import { join as join14 } from "path";
42024
- import { unlink as unlink3, writeFileSync as writeFileSync4 } from "fs";
42997
+ import { join as join15 } from "path";
42998
+ import { unlink as unlink4, writeFileSync as writeFileSync5 } from "fs";
42025
42999
  class AudioPlayer {
42026
43000
  currentProcess = null;
42027
43001
  playing = false;
42028
43002
  async play(audio, options = {}) {
42029
43003
  const format = options.format ?? "mp3";
42030
- const tempFile = join14(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
42031
- writeFileSync4(tempFile, Buffer.from(audio));
43004
+ const tempFile = join15(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
43005
+ writeFileSync5(tempFile, Buffer.from(audio));
42032
43006
  const player = this.resolvePlayer(format);
42033
43007
  if (!player) {
42034
43008
  throw new Error("No supported audio player found. Install afplay, ffplay, mpg123, or aplay.");
42035
43009
  }
42036
- await new Promise((resolve4, reject) => {
43010
+ await new Promise((resolve5, reject) => {
42037
43011
  this.playing = true;
42038
43012
  this.currentProcess = spawn(player.command, [...player.args, tempFile], { stdio: "ignore" });
42039
43013
  this.currentProcess.on("close", () => {
42040
43014
  this.playing = false;
42041
43015
  this.currentProcess = null;
42042
- unlink3(tempFile, () => {});
42043
- resolve4();
43016
+ unlink4(tempFile, () => {});
43017
+ resolve5();
42044
43018
  });
42045
43019
  this.currentProcess.on("error", (error) => {
42046
43020
  this.playing = false;
42047
43021
  this.currentProcess = null;
42048
- unlink3(tempFile, () => {});
43022
+ unlink4(tempFile, () => {});
42049
43023
  reject(error);
42050
43024
  });
42051
43025
  });
@@ -42095,8 +43069,8 @@ class AudioPlayer {
42095
43069
  // packages/core/src/voice/recorder.ts
42096
43070
  import { spawn as spawn2 } from "child_process";
42097
43071
  import { tmpdir as tmpdir4 } from "os";
42098
- import { join as join15 } from "path";
42099
- import { readFileSync as readFileSync5, unlink as unlink4 } from "fs";
43072
+ import { join as join16 } from "path";
43073
+ import { readFileSync as readFileSync6, unlink as unlink5 } from "fs";
42100
43074
  class AudioRecorder {
42101
43075
  currentProcess = null;
42102
43076
  async record(options = {}) {
@@ -42106,17 +43080,17 @@ class AudioRecorder {
42106
43080
  const duration = options.durationSeconds ?? 5;
42107
43081
  const sampleRate = options.sampleRate ?? 16000;
42108
43082
  const channels = options.channels ?? 1;
42109
- const output = join15(tmpdir4(), `assistants-record-${Date.now()}.wav`);
43083
+ const output = join16(tmpdir4(), `assistants-record-${Date.now()}.wav`);
42110
43084
  const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
42111
43085
  if (!recorder) {
42112
43086
  throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
42113
43087
  }
42114
- await new Promise((resolve4, reject) => {
43088
+ await new Promise((resolve5, reject) => {
42115
43089
  this.currentProcess = spawn2(recorder.command, recorder.args, { stdio: "ignore" });
42116
43090
  this.currentProcess.on("close", (code) => {
42117
43091
  this.currentProcess = null;
42118
43092
  if (code === 0) {
42119
- resolve4();
43093
+ resolve5();
42120
43094
  } else {
42121
43095
  reject(new Error("Audio recording failed."));
42122
43096
  }
@@ -42126,8 +43100,8 @@ class AudioRecorder {
42126
43100
  reject(error);
42127
43101
  });
42128
43102
  });
42129
- const data = readFileSync5(output);
42130
- unlink4(output, () => {});
43103
+ const data = readFileSync6(output);
43104
+ unlink5(output, () => {});
42131
43105
  return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
42132
43106
  }
42133
43107
  stop() {
@@ -42298,15 +43272,15 @@ class VoiceManager {
42298
43272
  }
42299
43273
  // packages/core/src/identity/assistant-manager.ts
42300
43274
  init_src();
42301
- import { existsSync as existsSync10 } from "fs";
42302
- import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile6, rm as rm2 } from "fs/promises";
42303
- import { join as join17 } from "path";
43275
+ import { existsSync as existsSync11 } from "fs";
43276
+ import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile7, rm as rm2 } from "fs/promises";
43277
+ import { join as join18 } from "path";
42304
43278
 
42305
43279
  // packages/core/src/identity/identity-manager.ts
42306
43280
  init_src();
42307
- import { existsSync as existsSync9 } from "fs";
42308
- import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile5, rm } from "fs/promises";
42309
- import { join as join16 } from "path";
43281
+ import { existsSync as existsSync10 } from "fs";
43282
+ import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile6, rm } from "fs/promises";
43283
+ import { join as join17 } from "path";
42310
43284
  var DEFAULT_PROFILE = {
42311
43285
  displayName: "Assistant",
42312
43286
  timezone: "UTC",
@@ -42336,22 +43310,22 @@ class IdentityManager {
42336
43310
  this.basePath = basePath;
42337
43311
  }
42338
43312
  get identitiesRoot() {
42339
- return join16(this.basePath, "assistants", this.assistantId, "identities");
43313
+ return join17(this.basePath, "assistants", this.assistantId, "identities");
42340
43314
  }
42341
43315
  get indexPath() {
42342
- return join16(this.identitiesRoot, "index.json");
43316
+ return join17(this.identitiesRoot, "index.json");
42343
43317
  }
42344
43318
  get activePath() {
42345
- return join16(this.identitiesRoot, "active.json");
43319
+ return join17(this.identitiesRoot, "active.json");
42346
43320
  }
42347
43321
  identityPath(id) {
42348
- return join16(this.identitiesRoot, `${id}.json`);
43322
+ return join17(this.identitiesRoot, `${id}.json`);
42349
43323
  }
42350
43324
  assistantConfigPath() {
42351
- return join16(this.basePath, "assistants", this.assistantId, "config.json");
43325
+ return join17(this.basePath, "assistants", this.assistantId, "config.json");
42352
43326
  }
42353
43327
  async initialize() {
42354
- await mkdir3(this.identitiesRoot, { recursive: true });
43328
+ await mkdir4(this.identitiesRoot, { recursive: true });
42355
43329
  const index = await this.readIndex();
42356
43330
  for (const id of index.identities) {
42357
43331
  const identity = await this.readIdentity(id);
@@ -42454,11 +43428,11 @@ class IdentityManager {
42454
43428
  `);
42455
43429
  }
42456
43430
  async readIndex() {
42457
- if (!existsSync9(this.indexPath)) {
43431
+ if (!existsSync10(this.indexPath)) {
42458
43432
  return { identities: [] };
42459
43433
  }
42460
43434
  try {
42461
- const raw = await readFile5(this.indexPath, "utf-8");
43435
+ const raw = await readFile7(this.indexPath, "utf-8");
42462
43436
  const data = JSON.parse(raw);
42463
43437
  return { identities: Array.isArray(data.identities) ? data.identities : [] };
42464
43438
  } catch {
@@ -42470,33 +43444,33 @@ class IdentityManager {
42470
43444
  if (!index.identities.includes(id)) {
42471
43445
  index.identities.push(id);
42472
43446
  }
42473
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43447
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42474
43448
  }
42475
43449
  async removeFromIndex(id) {
42476
43450
  const index = await this.readIndex();
42477
43451
  index.identities = index.identities.filter((identityId) => identityId !== id);
42478
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43452
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42479
43453
  }
42480
43454
  async readIdentity(id) {
42481
43455
  const path2 = this.identityPath(id);
42482
- if (!existsSync9(path2))
43456
+ if (!existsSync10(path2))
42483
43457
  return null;
42484
43458
  try {
42485
- const raw = await readFile5(path2, "utf-8");
43459
+ const raw = await readFile7(path2, "utf-8");
42486
43460
  return JSON.parse(raw);
42487
43461
  } catch {
42488
43462
  return null;
42489
43463
  }
42490
43464
  }
42491
43465
  async persistIdentity(identity) {
42492
- await mkdir3(this.identitiesRoot, { recursive: true });
42493
- await writeFile5(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
43466
+ await mkdir4(this.identitiesRoot, { recursive: true });
43467
+ await writeFile6(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
42494
43468
  }
42495
43469
  async readActive() {
42496
- if (!existsSync9(this.activePath))
43470
+ if (!existsSync10(this.activePath))
42497
43471
  return null;
42498
43472
  try {
42499
- const raw = await readFile5(this.activePath, "utf-8");
43473
+ const raw = await readFile7(this.activePath, "utf-8");
42500
43474
  const data = JSON.parse(raw);
42501
43475
  return data.id || null;
42502
43476
  } catch {
@@ -42505,13 +43479,13 @@ class IdentityManager {
42505
43479
  }
42506
43480
  async setActive(id) {
42507
43481
  this.activeId = id;
42508
- await writeFile5(this.activePath, JSON.stringify({ id }, null, 2));
43482
+ await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
42509
43483
  }
42510
43484
  async loadAssistant() {
42511
- if (!existsSync9(this.assistantConfigPath()))
43485
+ if (!existsSync10(this.assistantConfigPath()))
42512
43486
  return null;
42513
43487
  try {
42514
- const raw = await readFile5(this.assistantConfigPath(), "utf-8");
43488
+ const raw = await readFile7(this.assistantConfigPath(), "utf-8");
42515
43489
  return JSON.parse(raw);
42516
43490
  } catch {
42517
43491
  return null;
@@ -42532,19 +43506,19 @@ class AssistantManager {
42532
43506
  this.basePath = basePath;
42533
43507
  }
42534
43508
  get assistantsRoot() {
42535
- return join17(this.basePath, "assistants");
43509
+ return join18(this.basePath, "assistants");
42536
43510
  }
42537
43511
  get indexPath() {
42538
- return join17(this.assistantsRoot, "index.json");
43512
+ return join18(this.assistantsRoot, "index.json");
42539
43513
  }
42540
43514
  get activePath() {
42541
- return join17(this.basePath, "active.json");
43515
+ return join18(this.basePath, "active.json");
42542
43516
  }
42543
43517
  assistantConfigPath(id) {
42544
- return join17(this.assistantsRoot, id, "config.json");
43518
+ return join18(this.assistantsRoot, id, "config.json");
42545
43519
  }
42546
43520
  async initialize() {
42547
- await mkdir4(this.assistantsRoot, { recursive: true });
43521
+ await mkdir5(this.assistantsRoot, { recursive: true });
42548
43522
  const index = await this.readIndex();
42549
43523
  for (const id of index.assistants) {
42550
43524
  const assistant = await this.readAssistant(id);
@@ -42595,7 +43569,7 @@ class AssistantManager {
42595
43569
  if (!this.assistants.has(id)) {
42596
43570
  throw new Error(`Assistant ${id} not found`);
42597
43571
  }
42598
- await rm2(join17(this.assistantsRoot, id), { recursive: true, force: true });
43572
+ await rm2(join18(this.assistantsRoot, id), { recursive: true, force: true });
42599
43573
  this.assistants.delete(id);
42600
43574
  await this.removeFromIndex(id);
42601
43575
  if (this.activeId === id) {
@@ -42626,11 +43600,11 @@ class AssistantManager {
42626
43600
  return new IdentityManager(assistantId, this.basePath);
42627
43601
  }
42628
43602
  async readIndex() {
42629
- if (!existsSync10(this.indexPath)) {
43603
+ if (!existsSync11(this.indexPath)) {
42630
43604
  return { assistants: [] };
42631
43605
  }
42632
43606
  try {
42633
- const raw = await readFile6(this.indexPath, "utf-8");
43607
+ const raw = await readFile8(this.indexPath, "utf-8");
42634
43608
  const data = JSON.parse(raw);
42635
43609
  return { assistants: Array.isArray(data.assistants) ? data.assistants : [] };
42636
43610
  } catch {
@@ -42642,34 +43616,34 @@ class AssistantManager {
42642
43616
  if (!index.assistants.includes(id)) {
42643
43617
  index.assistants.push(id);
42644
43618
  }
42645
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43619
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42646
43620
  }
42647
43621
  async removeFromIndex(id) {
42648
43622
  const index = await this.readIndex();
42649
43623
  index.assistants = index.assistants.filter((assistantId) => assistantId !== id);
42650
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43624
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42651
43625
  }
42652
43626
  async readAssistant(id) {
42653
43627
  const configPath = this.assistantConfigPath(id);
42654
- if (!existsSync10(configPath))
43628
+ if (!existsSync11(configPath))
42655
43629
  return null;
42656
43630
  try {
42657
- const raw = await readFile6(configPath, "utf-8");
43631
+ const raw = await readFile8(configPath, "utf-8");
42658
43632
  return JSON.parse(raw);
42659
43633
  } catch {
42660
43634
  return null;
42661
43635
  }
42662
43636
  }
42663
43637
  async persistAssistant(assistant) {
42664
- const dir = join17(this.assistantsRoot, assistant.id);
42665
- await mkdir4(dir, { recursive: true });
42666
- await writeFile6(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
43638
+ const dir = join18(this.assistantsRoot, assistant.id);
43639
+ await mkdir5(dir, { recursive: true });
43640
+ await writeFile7(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
42667
43641
  }
42668
43642
  async readActive() {
42669
- if (!existsSync10(this.activePath))
43643
+ if (!existsSync11(this.activePath))
42670
43644
  return null;
42671
43645
  try {
42672
- const raw = await readFile6(this.activePath, "utf-8");
43646
+ const raw = await readFile8(this.activePath, "utf-8");
42673
43647
  const data = JSON.parse(raw);
42674
43648
  return data.id || null;
42675
43649
  } catch {
@@ -42678,7 +43652,7 @@ class AssistantManager {
42678
43652
  }
42679
43653
  async setActive(id) {
42680
43654
  this.activeId = id;
42681
- await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
43655
+ await writeFile7(this.activePath, JSON.stringify({ id }, null, 2));
42682
43656
  }
42683
43657
  }
42684
43658
  // packages/core/src/agent/loop.ts
@@ -42723,6 +43697,8 @@ class AgentLoop {
42723
43697
  assistantManager = null;
42724
43698
  identityManager = null;
42725
43699
  identityContext = null;
43700
+ projectContext = null;
43701
+ activeProjectId = null;
42726
43702
  assistantId = null;
42727
43703
  onChunk;
42728
43704
  onToolStart;
@@ -42735,7 +43711,7 @@ class AgentLoop {
42735
43711
  this.context = new AgentContext;
42736
43712
  this.toolRegistry = new ToolRegistry;
42737
43713
  this.toolRegistry.setErrorAggregator(this.errorAggregator);
42738
- this.connectorBridge = new ConnectorBridge;
43714
+ this.connectorBridge = new ConnectorBridge(this.cwd);
42739
43715
  this.skillLoader = new SkillLoader;
42740
43716
  this.skillExecutor = new SkillExecutor;
42741
43717
  this.hookLoader = new HookLoader;
@@ -43038,15 +44014,13 @@ class AgentLoop {
43038
44014
  });
43039
44015
  if (preHookResult?.updatedInput) {
43040
44016
  toolCall.input = { ...preHookResult.updatedInput };
43041
- if (toolCall.input.cwd === undefined) {
43042
- toolCall.input.cwd = this.cwd;
43043
- }
43044
44017
  }
43045
- if (toolCall.name === "schedule") {
43046
- const input = toolCall.input;
43047
- if (input.sessionId === undefined) {
43048
- input.sessionId = this.sessionId;
43049
- }
44018
+ const input = toolCall.input;
44019
+ if (input.cwd === undefined) {
44020
+ input.cwd = this.cwd;
44021
+ }
44022
+ if (input.sessionId === undefined) {
44023
+ input.sessionId = this.sessionId;
43050
44024
  }
43051
44025
  if (preHookResult?.continue === false || preHookResult?.permissionDecision === "deny") {
43052
44026
  const blockedResult = {
@@ -43170,6 +44144,13 @@ class AgentLoop {
43170
44144
  switchIdentity: async (identityId) => {
43171
44145
  await this.switchIdentity(identityId);
43172
44146
  },
44147
+ getActiveProjectId: () => this.activeProjectId,
44148
+ setActiveProjectId: (projectId) => {
44149
+ this.activeProjectId = projectId;
44150
+ },
44151
+ setProjectContext: (content) => {
44152
+ this.setProjectContext(content);
44153
+ },
43173
44154
  getVoiceState: () => this.getVoiceState(),
43174
44155
  enableVoice: () => {
43175
44156
  if (!this.voiceManager) {
@@ -43357,6 +44338,22 @@ class AgentLoop {
43357
44338
  getSessionId() {
43358
44339
  return this.sessionId;
43359
44340
  }
44341
+ getActiveProjectId() {
44342
+ return this.activeProjectId;
44343
+ }
44344
+ setActiveProjectId(projectId) {
44345
+ this.activeProjectId = projectId;
44346
+ }
44347
+ setProjectContext(content) {
44348
+ const tag = "[Project Context]";
44349
+ this.projectContext = content;
44350
+ this.context.removeSystemMessages((message) => message.startsWith(tag));
44351
+ if (content && content.trim()) {
44352
+ this.context.addSystemMessage(`${tag}
44353
+ ${content.trim()}`);
44354
+ }
44355
+ this.contextManager?.refreshState(this.context.getMessages());
44356
+ }
43360
44357
  clearConversation() {
43361
44358
  this.resetContext();
43362
44359
  }
@@ -43368,7 +44365,7 @@ class AgentLoop {
43368
44365
  const heartbeatConfig = this.buildHeartbeatConfig(this.config);
43369
44366
  if (!heartbeatConfig)
43370
44367
  return;
43371
- const statePath = join18(getConfigDir(), "state", `${this.sessionId}.json`);
44368
+ const statePath = join19(getConfigDir(), "state", `${this.sessionId}.json`);
43372
44369
  this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
43373
44370
  this.heartbeatPersistence = new StatePersistence(statePath);
43374
44371
  this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
@@ -43417,7 +44414,7 @@ class AgentLoop {
43417
44414
  async startEnergySystem() {
43418
44415
  if (!this.config || this.config.energy?.enabled === false)
43419
44416
  return;
43420
- const statePath = join18(getConfigDir(), "energy", "state.json");
44417
+ const statePath = join19(getConfigDir(), "energy", "state.json");
43421
44418
  this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
43422
44419
  await this.energyManager.initialize();
43423
44420
  this.refreshEnergyEffects();
@@ -43446,7 +44443,7 @@ ${effects.message}
43446
44443
  const delay = this.energyEffects?.processingDelayMs ?? 0;
43447
44444
  if (delay <= 0)
43448
44445
  return;
43449
- await new Promise((resolve4) => setTimeout(resolve4, delay));
44446
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
43450
44447
  }
43451
44448
  applyEnergyPersonality(systemPrompt) {
43452
44449
  if (!systemPrompt)
@@ -43557,6 +44554,9 @@ ${effects.message}
43557
44554
  if (this.extraSystemPrompt) {
43558
44555
  this.context.addSystemMessage(this.extraSystemPrompt);
43559
44556
  }
44557
+ if (this.projectContext) {
44558
+ this.setProjectContext(this.projectContext);
44559
+ }
43560
44560
  this.contextManager?.refreshState(this.context.getMessages());
43561
44561
  }
43562
44562
  buildSystemPrompt(messages) {
@@ -43643,7 +44643,7 @@ ${this.identityContext}`);
43643
44643
  return null;
43644
44644
  const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
43645
44645
  const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
43646
- const persistPath = config.heartbeat?.persistPath ?? join18(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
44646
+ const persistPath = config.heartbeat?.persistPath ?? join19(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
43647
44647
  return {
43648
44648
  intervalMs,
43649
44649
  staleThresholdMs,
@@ -43734,26 +44734,26 @@ function parseErrorCode(message) {
43734
44734
  // packages/core/src/memory/sessions.ts
43735
44735
  init_src();
43736
44736
  // packages/core/src/migration/migrate-to-assistants.ts
43737
- import { existsSync as existsSync11 } from "fs";
43738
- import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile7, rename, cp } from "fs/promises";
43739
- import { join as join19 } from "path";
44737
+ import { existsSync as existsSync12 } from "fs";
44738
+ import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile8, rename, cp } from "fs/promises";
44739
+ import { join as join20 } from "path";
43740
44740
  import { homedir as homedir10 } from "os";
43741
44741
  var MIGRATION_MARKER = ".migrated-from-oldpal";
43742
44742
  async function ensureDir(path2) {
43743
- await mkdir5(path2, { recursive: true });
44743
+ await mkdir6(path2, { recursive: true });
43744
44744
  }
43745
44745
  async function copyIfExists(source, destination) {
43746
- if (!existsSync11(source))
44746
+ if (!existsSync12(source))
43747
44747
  return false;
43748
- await ensureDir(join19(destination, ".."));
44748
+ await ensureDir(join20(destination, ".."));
43749
44749
  await cp(source, destination, { recursive: true });
43750
44750
  return true;
43751
44751
  }
43752
44752
  async function readJson(path2) {
43753
- if (!existsSync11(path2))
44753
+ if (!existsSync12(path2))
43754
44754
  return null;
43755
44755
  try {
43756
- const raw = await readFile7(path2, "utf-8");
44756
+ const raw = await readFile9(path2, "utf-8");
43757
44757
  return JSON.parse(raw);
43758
44758
  } catch {
43759
44759
  return null;
@@ -43766,15 +44766,15 @@ async function migrateFromOldpal() {
43766
44766
  errors: []
43767
44767
  };
43768
44768
  const home = homedir10();
43769
- const oldPath = join19(home, ".oldpal");
43770
- const newPath = join19(home, ".assistants");
43771
- if (!existsSync11(oldPath)) {
44769
+ const oldPath = join20(home, ".oldpal");
44770
+ const newPath = join20(home, ".assistants");
44771
+ if (!existsSync12(oldPath)) {
43772
44772
  result.success = true;
43773
44773
  return result;
43774
44774
  }
43775
- if (existsSync11(newPath)) {
43776
- const marker = join19(newPath, "migration", MIGRATION_MARKER);
43777
- if (existsSync11(marker)) {
44775
+ if (existsSync12(newPath)) {
44776
+ const marker = join20(newPath, "migration", MIGRATION_MARKER);
44777
+ if (existsSync12(marker)) {
43778
44778
  result.success = true;
43779
44779
  return result;
43780
44780
  }
@@ -43783,31 +44783,31 @@ async function migrateFromOldpal() {
43783
44783
  }
43784
44784
  try {
43785
44785
  await ensureDir(newPath);
43786
- await ensureDir(join19(newPath, "assistants"));
43787
- await ensureDir(join19(newPath, "shared", "skills"));
43788
- await ensureDir(join19(newPath, "logs"));
43789
- await ensureDir(join19(newPath, "migration"));
43790
- const config = await readJson(join19(oldPath, "settings.json"));
44786
+ await ensureDir(join20(newPath, "assistants"));
44787
+ await ensureDir(join20(newPath, "shared", "skills"));
44788
+ await ensureDir(join20(newPath, "logs"));
44789
+ await ensureDir(join20(newPath, "migration"));
44790
+ const config = await readJson(join20(oldPath, "settings.json"));
43791
44791
  if (config) {
43792
- await writeFile7(join19(newPath, "config.json"), JSON.stringify(config, null, 2));
44792
+ await writeFile8(join20(newPath, "config.json"), JSON.stringify(config, null, 2));
43793
44793
  result.migrated.push("config.json");
43794
44794
  }
43795
- if (await copyIfExists(join19(oldPath, "settings.local.json"), join19(newPath, "config.local.json"))) {
44795
+ if (await copyIfExists(join20(oldPath, "settings.local.json"), join20(newPath, "config.local.json"))) {
43796
44796
  result.migrated.push("config.local.json");
43797
44797
  }
43798
- if (await copyIfExists(join19(oldPath, "hooks.json"), join19(newPath, "hooks.json"))) {
44798
+ if (await copyIfExists(join20(oldPath, "hooks.json"), join20(newPath, "hooks.json"))) {
43799
44799
  result.migrated.push("hooks.json");
43800
44800
  }
43801
- if (await copyIfExists(join19(oldPath, "commands"), join19(newPath, "commands"))) {
44801
+ if (await copyIfExists(join20(oldPath, "commands"), join20(newPath, "commands"))) {
43802
44802
  result.migrated.push("commands");
43803
44803
  }
43804
- if (await copyIfExists(join19(oldPath, "OLDPAL.md"), join19(newPath, "ASSISTANTS.md"))) {
44804
+ if (await copyIfExists(join20(oldPath, "OLDPAL.md"), join20(newPath, "ASSISTANTS.md"))) {
43805
44805
  result.migrated.push("ASSISTANTS.md");
43806
44806
  }
43807
- if (await copyIfExists(join19(oldPath, "skills"), join19(newPath, "shared", "skills"))) {
44807
+ if (await copyIfExists(join20(oldPath, "skills"), join20(newPath, "shared", "skills"))) {
43808
44808
  result.migrated.push("skills");
43809
44809
  }
43810
- if (await copyIfExists(join19(oldPath, "logs"), join19(newPath, "logs"))) {
44810
+ if (await copyIfExists(join20(oldPath, "logs"), join20(newPath, "logs"))) {
43811
44811
  result.migrated.push("logs");
43812
44812
  }
43813
44813
  const manager = new AssistantManager(newPath);
@@ -43822,10 +44822,10 @@ async function migrateFromOldpal() {
43822
44822
  const identityManager = manager.getIdentityManager(assistant.id);
43823
44823
  await identityManager.initialize();
43824
44824
  await identityManager.createIdentity({ name: "Default" });
43825
- if (await copyIfExists(join19(oldPath, "sessions"), join19(newPath, "assistants", assistant.id, "sessions"))) {
44825
+ if (await copyIfExists(join20(oldPath, "sessions"), join20(newPath, "assistants", assistant.id, "sessions"))) {
43826
44826
  result.migrated.push("sessions");
43827
44827
  }
43828
- await writeFile7(join19(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
44828
+ await writeFile8(join20(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
43829
44829
  const backupPath = `${oldPath}.backup`;
43830
44830
  await rename(oldPath, backupPath);
43831
44831
  result.backupPath = backupPath;
@@ -43842,22 +44842,22 @@ init_anthropic();
43842
44842
  init_src();
43843
44843
 
43844
44844
  // packages/core/src/logger.ts
43845
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
43846
- import { join as join20 } from "path";
44845
+ import { existsSync as existsSync13, mkdirSync as mkdirSync7, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
44846
+ import { join as join21 } from "path";
43847
44847
  class Logger {
43848
44848
  logDir;
43849
44849
  logFile;
43850
44850
  sessionId;
43851
44851
  constructor(sessionId, basePath) {
43852
44852
  this.sessionId = sessionId;
43853
- this.logDir = join20(basePath || getConfigDir(), "logs");
44853
+ this.logDir = join21(basePath || getConfigDir(), "logs");
43854
44854
  this.ensureDir(this.logDir);
43855
44855
  const date = new Date().toISOString().split("T")[0];
43856
- this.logFile = join20(this.logDir, `${date}.log`);
44856
+ this.logFile = join21(this.logDir, `${date}.log`);
43857
44857
  }
43858
44858
  ensureDir(dir) {
43859
- if (!existsSync12(dir)) {
43860
- mkdirSync6(dir, { recursive: true });
44859
+ if (!existsSync13(dir)) {
44860
+ mkdirSync7(dir, { recursive: true });
43861
44861
  }
43862
44862
  }
43863
44863
  write(level, message, data) {
@@ -43897,18 +44897,18 @@ class SessionStorage {
43897
44897
  constructor(sessionId, basePath, assistantId) {
43898
44898
  this.sessionId = sessionId;
43899
44899
  const root = basePath || getConfigDir();
43900
- this.sessionsDir = assistantId ? join20(root, "assistants", assistantId, "sessions") : join20(root, "sessions");
44900
+ this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
43901
44901
  this.ensureDir(this.sessionsDir);
43902
- this.sessionFile = join20(this.sessionsDir, `${sessionId}.json`);
44902
+ this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
43903
44903
  }
43904
44904
  ensureDir(dir) {
43905
- if (!existsSync12(dir)) {
43906
- mkdirSync6(dir, { recursive: true });
44905
+ if (!existsSync13(dir)) {
44906
+ mkdirSync7(dir, { recursive: true });
43907
44907
  }
43908
44908
  }
43909
44909
  save(data) {
43910
44910
  try {
43911
- writeFileSync5(this.sessionFile, JSON.stringify(data, null, 2));
44911
+ writeFileSync6(this.sessionFile, JSON.stringify(data, null, 2));
43912
44912
  } catch {}
43913
44913
  }
43914
44914
  getSessionId() {
@@ -43916,19 +44916,19 @@ class SessionStorage {
43916
44916
  }
43917
44917
  load() {
43918
44918
  try {
43919
- if (!existsSync12(this.sessionFile))
44919
+ if (!existsSync13(this.sessionFile))
43920
44920
  return null;
43921
- return JSON.parse(readFileSync6(this.sessionFile, "utf-8"));
44921
+ return JSON.parse(readFileSync7(this.sessionFile, "utf-8"));
43922
44922
  } catch {
43923
44923
  return null;
43924
44924
  }
43925
44925
  }
43926
44926
  static getActiveAssistantId() {
43927
44927
  try {
43928
- const activePath = join20(getConfigDir(), "active.json");
43929
- if (!existsSync12(activePath))
44928
+ const activePath = join21(getConfigDir(), "active.json");
44929
+ if (!existsSync13(activePath))
43930
44930
  return null;
43931
- const raw = readFileSync6(activePath, "utf-8");
44931
+ const raw = readFileSync7(activePath, "utf-8");
43932
44932
  const data = JSON.parse(raw);
43933
44933
  return data.id || null;
43934
44934
  } catch {
@@ -43939,16 +44939,16 @@ class SessionStorage {
43939
44939
  const root = getConfigDir();
43940
44940
  const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
43941
44941
  if (resolvedId) {
43942
- const assistantDir = join20(root, "assistants", resolvedId, "sessions");
43943
- if (existsSync12(assistantDir)) {
44942
+ const assistantDir = join21(root, "assistants", resolvedId, "sessions");
44943
+ if (existsSync13(assistantDir)) {
43944
44944
  return assistantDir;
43945
44945
  }
43946
44946
  }
43947
- return join20(root, "sessions");
44947
+ return join21(root, "sessions");
43948
44948
  }
43949
44949
  static listSessions(assistantId) {
43950
44950
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43951
- if (!existsSync12(sessionsDir))
44951
+ if (!existsSync13(sessionsDir))
43952
44952
  return [];
43953
44953
  const sessions = [];
43954
44954
  const files = readdirSync3(sessionsDir);
@@ -43956,9 +44956,9 @@ class SessionStorage {
43956
44956
  if (!file.endsWith(".json"))
43957
44957
  continue;
43958
44958
  try {
43959
- const filePath = join20(sessionsDir, file);
44959
+ const filePath = join21(sessionsDir, file);
43960
44960
  const stat = Bun.file(filePath);
43961
- const content = JSON.parse(readFileSync6(filePath, "utf-8"));
44961
+ const content = JSON.parse(readFileSync7(filePath, "utf-8"));
43962
44962
  sessions.push({
43963
44963
  id: file.replace(".json", ""),
43964
44964
  cwd: content.cwd,
@@ -43976,11 +44976,11 @@ class SessionStorage {
43976
44976
  }
43977
44977
  static loadSession(sessionId, assistantId) {
43978
44978
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43979
- const sessionFile = join20(sessionsDir, `${sessionId}.json`);
44979
+ const sessionFile = join21(sessionsDir, `${sessionId}.json`);
43980
44980
  try {
43981
- if (!existsSync12(sessionFile))
44981
+ if (!existsSync13(sessionFile))
43982
44982
  return null;
43983
- return JSON.parse(readFileSync6(sessionFile, "utf-8"));
44983
+ return JSON.parse(readFileSync7(sessionFile, "utf-8"));
43984
44984
  } catch {
43985
44985
  return null;
43986
44986
  }
@@ -43990,19 +44990,19 @@ function initAssistantsDir() {
43990
44990
  const baseDir = getConfigDir();
43991
44991
  const dirs = [
43992
44992
  baseDir,
43993
- join20(baseDir, "logs"),
43994
- join20(baseDir, "assistants"),
43995
- join20(baseDir, "shared", "skills"),
43996
- join20(baseDir, "commands"),
43997
- join20(baseDir, "temp"),
43998
- join20(baseDir, "heartbeats"),
43999
- join20(baseDir, "state"),
44000
- join20(baseDir, "energy"),
44001
- join20(baseDir, "migration")
44993
+ join21(baseDir, "logs"),
44994
+ join21(baseDir, "assistants"),
44995
+ join21(baseDir, "shared", "skills"),
44996
+ join21(baseDir, "commands"),
44997
+ join21(baseDir, "temp"),
44998
+ join21(baseDir, "heartbeats"),
44999
+ join21(baseDir, "state"),
45000
+ join21(baseDir, "energy"),
45001
+ join21(baseDir, "migration")
44002
45002
  ];
44003
45003
  for (const dir of dirs) {
44004
- if (!existsSync12(dir)) {
44005
- mkdirSync6(dir, { recursive: true });
45004
+ if (!existsSync13(dir)) {
45005
+ mkdirSync7(dir, { recursive: true });
44006
45006
  }
44007
45007
  }
44008
45008
  }
@@ -44041,6 +45041,11 @@ class EmbeddedClient {
44041
45041
  for (const callback of this.chunkCallbacks) {
44042
45042
  callback(chunk);
44043
45043
  }
45044
+ if (chunk.type === "done" || chunk.type === "error") {
45045
+ queueMicrotask(() => {
45046
+ this.drainQueue();
45047
+ });
45048
+ }
44044
45049
  },
44045
45050
  onToolStart: (toolCall) => {
44046
45051
  this.logger.info("Tool started", { tool: toolCall.name, input: toolCall.input });
@@ -44083,12 +45088,11 @@ class EmbeddedClient {
44083
45088
  if (!this.initialized) {
44084
45089
  await this.initialize();
44085
45090
  }
44086
- if (this.agent.isProcessing()) {
44087
- this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length + 1 });
44088
- this.messageQueue.push(message);
45091
+ this.messageQueue.push(message);
45092
+ if (this.agent.isProcessing() || this.processingQueue) {
45093
+ this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length });
44089
45094
  return;
44090
45095
  }
44091
- await this.processMessage(message);
44092
45096
  await this.drainQueue();
44093
45097
  }
44094
45098
  async processMessage(message) {
@@ -44479,10 +45483,13 @@ var COMMANDS = [
44479
45483
  { name: "/model", description: "show model information" },
44480
45484
  { name: "/skills", description: "list available skills" },
44481
45485
  { name: "/config", description: "show configuration" },
45486
+ { name: "/projects", description: "manage projects in this folder" },
45487
+ { name: "/plans", description: "manage project plans" },
44482
45488
  { name: "/connectors", description: "list available connectors" },
44483
45489
  { name: "/init", description: "initialize assistants in project" },
44484
45490
  { name: "/compact", description: "summarize to save context" },
44485
45491
  { name: "/memory", description: "show what AI remembers" },
45492
+ { name: "/context", description: "manage injected project context" },
44486
45493
  { name: "/feedback", description: "submit feedback on GitHub" },
44487
45494
  { name: "/schedule", description: "schedule a command" },
44488
45495
  { name: "/schedules", description: "list scheduled commands" },
@@ -44578,14 +45585,14 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44578
45585
  if (autocompleteMode === "command" && filteredCommands.length > 0 && !submittedValue.includes(" ")) {
44579
45586
  const selected = filteredCommands[selectedIndex] || filteredCommands[0];
44580
45587
  if (selected) {
44581
- onSubmit(selected.name, isProcessing ? "interrupt" : "normal");
45588
+ onSubmit(selected.name, isProcessing ? "inline" : "normal");
44582
45589
  setValue("");
44583
45590
  setSelectedIndex(0);
44584
45591
  return;
44585
45592
  }
44586
45593
  }
44587
45594
  if (isProcessing) {
44588
- onSubmit(submittedValue, "interrupt");
45595
+ onSubmit(submittedValue, "inline");
44589
45596
  } else {
44590
45597
  onSubmit(submittedValue, "normal");
44591
45598
  }
@@ -44596,7 +45603,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44596
45603
  let placeholder = "Type a message...";
44597
45604
  if (isProcessing) {
44598
45605
  prompt = "\u22EF";
44599
- placeholder = queueLength > 0 ? "Type to interrupt (Enter) or queue (Tab)..." : "Type to interrupt (Enter) or queue (Tab)...";
45606
+ placeholder = queueLength > 0 ? "Type to send (Enter) or queue (Tab) \xB7 Shift+Enter to interrupt..." : "Type to send (Enter) or queue (Tab) \xB7 Shift+Enter to interrupt...";
44600
45607
  }
44601
45608
  const truncateDescription = (desc, maxLen = 60) => {
44602
45609
  if (desc.length <= maxLen)
@@ -44737,7 +45744,12 @@ var import_react24 = __toESM(require_react(), 1);
44737
45744
 
44738
45745
  // packages/terminal/src/components/Markdown.tsx
44739
45746
  var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
44740
- function Markdown({ content }) {
45747
+ function Markdown({ content, preRendered = false }) {
45748
+ if (preRendered) {
45749
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
45750
+ children: content
45751
+ }, undefined, false, undefined, this);
45752
+ }
44741
45753
  const { columns } = use_stdout_default();
44742
45754
  const maxWidth = columns ? Math.max(20, columns - 2) : undefined;
44743
45755
  const rendered = parseMarkdown(content, { maxWidth });
@@ -44745,6 +45757,9 @@ function Markdown({ content }) {
44745
45757
  children: rendered
44746
45758
  }, undefined, false, undefined, this);
44747
45759
  }
45760
+ function renderMarkdown(text, options) {
45761
+ return parseMarkdown(text, { maxWidth: options?.maxWidth });
45762
+ }
44748
45763
  function parseMarkdown(text, options) {
44749
45764
  let result = text;
44750
45765
  const codeBlocks = [];
@@ -44770,7 +45785,7 @@ function parseMarkdown(text, options) {
44770
45785
  result = result.replace(/\b(Building|Running|Working|Queued|Pending|Connecting)\b/gi, (match) => source_default.yellow(match));
44771
45786
  result = result.replace(/\b(Success|Succeeded|Done|Complete|Completed|Connected|Authenticated)\b/gi, (match) => source_default.green(match));
44772
45787
  result = result.replace(/\b(Error|Failed|Failure|Denied|Blocked)\b/gi, (match) => source_default.red(match));
44773
- result = formatMarkdownTables(result);
45788
+ result = formatMarkdownTables(result, options?.maxWidth);
44774
45789
  result = result.replace(/@@BLOCKSECTION(\d+)@@/g, (_, index) => {
44775
45790
  const section = blockSections[parseInt(index, 10)];
44776
45791
  if (!section)
@@ -44784,6 +45799,7 @@ function parseMarkdown(text, options) {
44784
45799
  });
44785
45800
  return result.trimEnd();
44786
45801
  }
45802
+ var ALLOWED_BLOCK_TYPES = new Set(["info", "success", "warning", "error", "note", "command"]);
44787
45803
  function extractBlockSections(text, blocks) {
44788
45804
  const lines = text.split(`
44789
45805
  `);
@@ -44812,6 +45828,9 @@ function extractBlockSections(text, blocks) {
44812
45828
  i += 1;
44813
45829
  continue;
44814
45830
  }
45831
+ if (parsed.warning) {
45832
+ output.push(createMalformedBlock(blocks, indent, "grid", parsed.warning));
45833
+ }
44815
45834
  const bodyLines = stripIndent(parsed.bodyLines, indent);
44816
45835
  const body = bodyLines.join(`
44817
45836
  `);
@@ -44825,7 +45844,7 @@ function extractBlockSections(text, blocks) {
44825
45844
  const indent = blockMatch[1] ?? "";
44826
45845
  const header = blockMatch[2] ?? "";
44827
45846
  const attrs = parseAttributes(header);
44828
- const type = String(attrs.type || "info");
45847
+ let type = String(attrs.type || "info");
44829
45848
  const title = attrs.title ? String(attrs.title) : undefined;
44830
45849
  const parsed = parseDelimitedBlock(lines, i, indent);
44831
45850
  if (!parsed) {
@@ -44834,6 +45853,14 @@ function extractBlockSections(text, blocks) {
44834
45853
  i += 1;
44835
45854
  continue;
44836
45855
  }
45856
+ const normalizedType = type.toLowerCase();
45857
+ if (!ALLOWED_BLOCK_TYPES.has(normalizedType)) {
45858
+ output.push(createMalformedBlock(blocks, indent, "block", `Unknown block type "${type}". Using info.`));
45859
+ type = "info";
45860
+ }
45861
+ if (parsed.warning) {
45862
+ output.push(createMalformedBlock(blocks, indent, "block", parsed.warning));
45863
+ }
44837
45864
  const body = stripIndent(parsed.bodyLines, indent).join(`
44838
45865
  `);
44839
45866
  blocks.push({ kind: "block", type, title, body, indent });
@@ -44850,6 +45877,9 @@ function extractBlockSections(text, blocks) {
44850
45877
  i += 1;
44851
45878
  continue;
44852
45879
  }
45880
+ if (parsed.warning) {
45881
+ output.push(createMalformedBlock(blocks, indent, "report", parsed.warning));
45882
+ }
44853
45883
  const body = stripIndent(parsed.bodyLines, indent).join(`
44854
45884
  `);
44855
45885
  blocks.push({ kind: "report", body, indent });
@@ -44881,10 +45911,14 @@ function extractCards(body) {
44881
45911
  const title = attrs.title ? String(attrs.title) : undefined;
44882
45912
  const bodyLines = [];
44883
45913
  let closed = false;
45914
+ let indentWarning;
44884
45915
  i += 1;
44885
45916
  while (i < lines.length) {
44886
45917
  const current = lines[i];
44887
- if (current.trim() === ":::" && current.startsWith(indent)) {
45918
+ if (current.trim() === ":::") {
45919
+ if (indent.length > 0 && !current.startsWith(indent)) {
45920
+ indentWarning = "Card closing ::: indentation did not match opening.";
45921
+ }
44888
45922
  closed = true;
44889
45923
  i += 1;
44890
45924
  break;
@@ -44901,6 +45935,13 @@ function extractCards(body) {
44901
45935
  break;
44902
45936
  }
44903
45937
  const stripped = stripIndent(bodyLines, indent);
45938
+ if (indentWarning) {
45939
+ cards.push({
45940
+ type: "warning",
45941
+ title: "Malformed card",
45942
+ body: indentWarning
45943
+ });
45944
+ }
44904
45945
  cards.push({ type, title, body: stripped.join(`
44905
45946
  `) });
44906
45947
  }
@@ -44909,6 +45950,7 @@ function extractCards(body) {
44909
45950
  function parseDelimitedBlock(lines, startIndex, indent) {
44910
45951
  const bodyLines = [];
44911
45952
  let openCards = 0;
45953
+ let warning;
44912
45954
  let i = startIndex + 1;
44913
45955
  while (i < lines.length) {
44914
45956
  const current = lines[i];
@@ -44919,14 +45961,18 @@ function parseDelimitedBlock(lines, startIndex, indent) {
44919
45961
  i += 1;
44920
45962
  continue;
44921
45963
  }
44922
- if (trimmed === ":::" && current.startsWith(indent)) {
45964
+ if (trimmed === ":::") {
45965
+ const indentMismatch = indent.length > 0 && !current.startsWith(indent);
44923
45966
  if (openCards > 0) {
44924
45967
  openCards -= 1;
44925
45968
  bodyLines.push(current);
44926
45969
  i += 1;
44927
45970
  continue;
44928
45971
  }
44929
- return { bodyLines, nextIndex: i + 1 };
45972
+ if (indentMismatch) {
45973
+ warning = "Closing ::: indentation did not match opening. Adjust indentation for consistency.";
45974
+ }
45975
+ return { bodyLines, nextIndex: i + 1, warning };
44930
45976
  }
44931
45977
  bodyLines.push(current);
44932
45978
  i += 1;
@@ -45093,7 +46139,7 @@ function formatBoxRow(line, width) {
45093
46139
  const padded = len < width ? line + " ".repeat(width - len) : line;
45094
46140
  return `\u2502 ${padded} \u2502`;
45095
46141
  }
45096
- function formatMarkdownTables(text) {
46142
+ function formatMarkdownTables(text, maxWidth) {
45097
46143
  const lines = text.split(`
45098
46144
  `);
45099
46145
  const output = [];
@@ -45111,7 +46157,7 @@ function formatMarkdownTables(text) {
45111
46157
  rows.push(parseTableRow(lines[i]));
45112
46158
  i += 1;
45113
46159
  }
45114
- const table = renderTable(header, rows);
46160
+ const table = renderTable(header, rows, maxWidth);
45115
46161
  output.push(...table);
45116
46162
  continue;
45117
46163
  }
@@ -45126,7 +46172,7 @@ function parseTableRow(line) {
45126
46172
  const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
45127
46173
  return withoutEdges.split("|").map((cell) => cell.trim());
45128
46174
  }
45129
- function renderTable(header, rows) {
46175
+ function renderTable(header, rows, maxWidth) {
45130
46176
  const colCount = Math.max(header.length, ...rows.map((r) => r.length));
45131
46177
  const widths = new Array(colCount).fill(0);
45132
46178
  const allRows = [header, ...rows];
@@ -45138,11 +46184,29 @@ function renderTable(header, rows) {
45138
46184
  widths[i] = len;
45139
46185
  }
45140
46186
  }
46187
+ const minCellWidth = 4;
46188
+ const availableCellWidth = maxWidth ? Math.max(colCount * minCellWidth, maxWidth - (colCount - 1) * 3 - 4) : undefined;
46189
+ if (availableCellWidth) {
46190
+ const total = widths.reduce((sum, width) => sum + width, 0);
46191
+ if (total > availableCellWidth) {
46192
+ const minWidth = Math.max(1, Math.floor(availableCellWidth / colCount));
46193
+ while (widths.reduce((sum, width) => sum + width, 0) > availableCellWidth) {
46194
+ const maxWidthValue = Math.max(...widths);
46195
+ const idx = widths.findIndex((width) => width === maxWidthValue);
46196
+ if (idx === -1)
46197
+ break;
46198
+ if (widths[idx] <= minWidth)
46199
+ break;
46200
+ widths[idx] -= 1;
46201
+ }
46202
+ }
46203
+ }
45141
46204
  const pad = (value, width) => {
45142
- const len = stripAnsi2(value).length;
46205
+ const rendered = width > 0 ? truncateAnsi(value, width) : value;
46206
+ const len = stripAnsi2(rendered).length;
45143
46207
  if (len >= width)
45144
- return value;
45145
- return value + " ".repeat(width - len);
46208
+ return rendered;
46209
+ return rendered + " ".repeat(width - len);
45146
46210
  };
45147
46211
  const top = "\u250C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C") + "\u2510";
45148
46212
  const mid = "\u251C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u253C") + "\u2524";
@@ -45220,7 +46284,8 @@ function renderReport(body, maxWidth, indent = "") {
45220
46284
  }
45221
46285
  if (tableLines.length > 0) {
45222
46286
  output.push(indent + source_default.bold("Detailed Status Table"));
45223
- const rendered = renderReportTable(tableLines, indent);
46287
+ const adjustedWidth = maxWidth ? Math.max(20, maxWidth - indent.length) : undefined;
46288
+ const rendered = renderReportTable(tableLines, indent, adjustedWidth);
45224
46289
  output.push(...rendered);
45225
46290
  }
45226
46291
  return output.join(`
@@ -45249,7 +46314,7 @@ function renderProgressLine(label, value, labelWidth, barWidth) {
45249
46314
  const bar = source_default.gray("\u2591".repeat(empty));
45250
46315
  return `${label.padEnd(labelWidth)} [${fill}${bar}] ${value}%`;
45251
46316
  }
45252
- function renderReportTable(lines, indent) {
46317
+ function renderReportTable(lines, indent, maxWidth) {
45253
46318
  const tableLines = lines.map((line) => line.trim()).filter(Boolean);
45254
46319
  if (tableLines.length < 2)
45255
46320
  return [];
@@ -45273,7 +46338,7 @@ function renderReportTable(lines, indent) {
45273
46338
  }
45274
46339
  return next;
45275
46340
  });
45276
- return renderTable(header, styledRows).map((line) => indent + line);
46341
+ return renderTable(header, styledRows, maxWidth).map((line) => indent + line);
45277
46342
  }
45278
46343
  function decoratePriority(value) {
45279
46344
  const normalized = value.toLowerCase();
@@ -45343,6 +46408,23 @@ function wrapAnsiLine(line, width) {
45343
46408
  function truncateAnsi(line, width) {
45344
46409
  if (stripAnsi2(line).length <= width)
45345
46410
  return line;
46411
+ if (width <= 3) {
46412
+ let result = "";
46413
+ let visible2 = 0;
46414
+ let i2 = 0;
46415
+ while (i2 < line.length && visible2 < width) {
46416
+ const match = line.slice(i2).match(/^\x1b\[[0-9;]*m/);
46417
+ if (match) {
46418
+ result += match[0];
46419
+ i2 += match[0].length;
46420
+ continue;
46421
+ }
46422
+ result += line[i2];
46423
+ visible2 += 1;
46424
+ i2 += 1;
46425
+ }
46426
+ return result;
46427
+ }
45346
46428
  const suffix = "...";
45347
46429
  const target = Math.max(0, width - suffix.length);
45348
46430
  let current = "";
@@ -45362,6 +46444,42 @@ function truncateAnsi(line, width) {
45362
46444
  return current + suffix;
45363
46445
  }
45364
46446
 
46447
+ // packages/terminal/src/components/messageLines.ts
46448
+ function estimateToolPanelLines(toolCalls, toolResults, hasContent) {
46449
+ if (!toolCalls || toolCalls.length === 0) {
46450
+ return 0;
46451
+ }
46452
+ const resultMap = new Set;
46453
+ for (const result of toolResults || []) {
46454
+ resultMap.add(result.toolCallId);
46455
+ }
46456
+ let lines = 3;
46457
+ if (hasContent) {
46458
+ lines += 1;
46459
+ }
46460
+ for (const call of toolCalls) {
46461
+ lines += 3;
46462
+ if (resultMap.has(call.id)) {
46463
+ lines += 1;
46464
+ }
46465
+ }
46466
+ return lines;
46467
+ }
46468
+ function estimateMessageLines(message) {
46469
+ if (message.role === "system") {
46470
+ return 0;
46471
+ }
46472
+ const content = message.content ?? "";
46473
+ const contentLines = content.length > 0 ? content.split(`
46474
+ `).length : 0;
46475
+ const hasContent = contentLines > 0;
46476
+ let lines = Math.max(1, contentLines);
46477
+ if (message.role === "assistant" && message.toolCalls?.length) {
46478
+ lines += estimateToolPanelLines(message.toolCalls, message.toolResults, hasContent);
46479
+ }
46480
+ return lines;
46481
+ }
46482
+
45365
46483
  // packages/terminal/src/components/Messages.tsx
45366
46484
  var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
45367
46485
  function Messages4({
@@ -45371,19 +46489,28 @@ function Messages4({
45371
46489
  currentToolCall,
45372
46490
  lastToolResult,
45373
46491
  activityLog = [],
45374
- scrollOffset = 0,
45375
- maxVisible = 10,
46492
+ scrollOffsetLines = 0,
46493
+ maxVisibleLines = 10,
45376
46494
  queuedMessageIds
45377
46495
  }) {
45378
46496
  const [now2, setNow] = import_react24.useState(Date.now());
45379
46497
  const combinedMessages = import_react24.useMemo(() => [...messages, ...streamingMessages], [messages, streamingMessages]);
45380
- const endIndex = combinedMessages.length - scrollOffset;
45381
- const startIndex = Math.max(0, endIndex - maxVisible);
45382
- const visibleCombined = combinedMessages.slice(startIndex, endIndex);
46498
+ const lineSpans = import_react24.useMemo(() => {
46499
+ let cursor = 0;
46500
+ return combinedMessages.map((message, index) => {
46501
+ const lines = estimateMessageLines(message);
46502
+ const start = cursor;
46503
+ cursor += lines;
46504
+ return { message, index, start, end: cursor, lines };
46505
+ });
46506
+ }, [combinedMessages]);
46507
+ const totalLines = lineSpans.length > 0 ? lineSpans[lineSpans.length - 1].end : 0;
46508
+ const endLine = Math.max(0, totalLines - scrollOffsetLines);
46509
+ const startLine = Math.max(0, endLine - maxVisibleLines);
46510
+ const visibleSpans = lineSpans.filter((span) => span.end > startLine && span.start < endLine);
45383
46511
  const historicalCount = messages.length;
45384
- const splitIndex = Math.max(0, Math.min(visibleCombined.length, historicalCount - startIndex));
45385
- const visibleMessages = visibleCombined.slice(0, splitIndex);
45386
- const visibleStreaming = visibleCombined.slice(splitIndex);
46512
+ const visibleMessages = visibleSpans.filter((span) => span.index < historicalCount).map((span) => span.message);
46513
+ const visibleStreaming = visibleSpans.filter((span) => span.index >= historicalCount).map((span) => span.message);
45387
46514
  const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
45388
46515
  const historicalItems = groupedMessages.map((group) => {
45389
46516
  if (group.type === "single") {
@@ -45586,6 +46713,8 @@ function MessageBubble({ message, queuedMessageIds }) {
45586
46713
  const chunkMatch = message.id.match(/::chunk-(\d+)$/);
45587
46714
  const chunkIndex = chunkMatch ? Number(chunkMatch[1]) : -1;
45588
46715
  const isContinuation = chunkIndex > 0;
46716
+ const content = message.content ?? "";
46717
+ const leadingBullet = !isContinuation && !startsWithListOrTable(content);
45589
46718
  if (isSystem) {
45590
46719
  return null;
45591
46720
  }
@@ -45614,7 +46743,7 @@ function MessageBubble({ message, queuedMessageIds }) {
45614
46743
  }
45615
46744
  const toolCalls = message.toolCalls || [];
45616
46745
  const toolResults = message.toolResults || [];
45617
- const hasContent = message.content && message.content.trim();
46746
+ const hasContent = content && content.trim();
45618
46747
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45619
46748
  marginY: isContinuation ? 0 : 1,
45620
46749
  flexDirection: "column",
@@ -45624,14 +46753,15 @@ function MessageBubble({ message, queuedMessageIds }) {
45624
46753
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45625
46754
  dimColor: true,
45626
46755
  children: [
45627
- isContinuation ? " " : "\u25CF ",
46756
+ isContinuation || !leadingBullet ? " " : "\u25CF ",
45628
46757
  " "
45629
46758
  ]
45630
46759
  }, undefined, true, undefined, this),
45631
46760
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45632
46761
  flexGrow: 1,
45633
46762
  children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
45634
- content: message.content
46763
+ content: message.content,
46764
+ preRendered: Boolean(message.__rendered)
45635
46765
  }, undefined, false, undefined, this)
45636
46766
  }, undefined, false, undefined, this)
45637
46767
  ]
@@ -45646,12 +46776,31 @@ function MessageBubble({ message, queuedMessageIds }) {
45646
46776
  ]
45647
46777
  }, undefined, true, undefined, this);
45648
46778
  }
46779
+ function startsWithListOrTable(content) {
46780
+ const lines = content.split(`
46781
+ `);
46782
+ for (const line of lines) {
46783
+ const trimmed = line.trimStart();
46784
+ if (!trimmed)
46785
+ continue;
46786
+ if (/^[-*\u2022]\s+/.test(trimmed))
46787
+ return true;
46788
+ if (/^\d+\.\s+/.test(trimmed))
46789
+ return true;
46790
+ if (trimmed.startsWith("|"))
46791
+ return true;
46792
+ return false;
46793
+ }
46794
+ return false;
46795
+ }
45649
46796
  function ToolCallPanel({
45650
46797
  toolCalls,
45651
46798
  toolResults
45652
46799
  }) {
45653
46800
  if (toolCalls.length === 0)
45654
46801
  return null;
46802
+ const { columns } = use_stdout_default();
46803
+ const panelWidth = columns ? Math.max(24, columns - 4) : undefined;
45655
46804
  const resultMap = new Map;
45656
46805
  for (const result of toolResults || []) {
45657
46806
  resultMap.set(result.toolCallId, result);
@@ -45690,6 +46839,8 @@ function ToolCallPanel({
45690
46839
  const statusColor = result ? result.isError ? "red" : "green" : "yellow";
45691
46840
  const displayName = getToolDisplayName(toolCall);
45692
46841
  const context2 = getToolContext(toolCall);
46842
+ const maxLine = panelWidth ? Math.max(20, panelWidth - 8) : 80;
46843
+ const summaryLine = truncate(formatToolCall(toolCall), maxLine);
45693
46844
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45694
46845
  flexDirection: "column",
45695
46846
  marginTop: 1,
@@ -45719,7 +46870,7 @@ function ToolCallPanel({
45719
46870
  }, undefined, true, undefined, this),
45720
46871
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45721
46872
  dimColor: true,
45722
- children: formatToolCall(toolCall)
46873
+ children: summaryLine
45723
46874
  }, undefined, false, undefined, this),
45724
46875
  result && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45725
46876
  marginLeft: 2,
@@ -45754,7 +46905,7 @@ function getToolContext(toolCall) {
45754
46905
  return truncate(String(input.pattern || ""), 20);
45755
46906
  case "schedule":
45756
46907
  return String(input.action || "");
45757
- case "feedback":
46908
+ case "submit_feedback":
45758
46909
  return String(input.type || "feedback");
45759
46910
  case "web_search":
45760
46911
  return truncate(String(input.query || ""), 20);
@@ -45795,7 +46946,7 @@ function getToolDisplayName(toolCall) {
45795
46946
  return "image";
45796
46947
  case "schedule":
45797
46948
  return "schedule";
45798
- case "feedback":
46949
+ case "submit_feedback":
45799
46950
  return "feedback";
45800
46951
  case "notion":
45801
46952
  case "gmail":
@@ -45829,7 +46980,7 @@ function formatToolCall(toolCall) {
45829
46980
  return `Searching: ${truncate(String(input.pattern || ""), 60)}`;
45830
46981
  case "schedule":
45831
46982
  return formatScheduleCall(input);
45832
- case "feedback":
46983
+ case "submit_feedback":
45833
46984
  return formatFeedbackCall(input);
45834
46985
  case "notion":
45835
46986
  return `Notion: ${truncate(String(input.command || input.action || ""), 60)}`;
@@ -45925,7 +47076,7 @@ function formatToolResultNicely(toolName, content, isError) {
45925
47076
  switch (toolName) {
45926
47077
  case "schedule":
45927
47078
  return formatScheduleResult(content);
45928
- case "feedback":
47079
+ case "submit_feedback":
45929
47080
  return formatFeedbackResult(content);
45930
47081
  case "read":
45931
47082
  return formatReadResult(content);
@@ -46035,46 +47186,7 @@ function formatSearchResult(content) {
46035
47186
 
46036
47187
  // packages/terminal/src/components/Status.tsx
46037
47188
  var import_react25 = __toESM(require_react(), 1);
46038
-
46039
- // packages/terminal/src/components/EnergyBar.tsx
46040
47189
  var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
46041
- function EnergyBar({ current, max }) {
46042
- const safeMax = Math.max(1, max);
46043
- const percentage = Math.round(current / safeMax * 100);
46044
- const barWidth = 16;
46045
- const filled = Math.round(current / safeMax * barWidth);
46046
- const empty = Math.max(0, barWidth - filled);
46047
- const color = percentage > 50 ? "green" : percentage > 20 ? "yellow" : "red";
46048
- const emoji = percentage > 70 ? "\u26A1" : percentage > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
46049
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46050
- children: [
46051
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46052
- children: [
46053
- emoji,
46054
- " "
46055
- ]
46056
- }, undefined, true, undefined, this),
46057
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46058
- color,
46059
- children: "\u2588".repeat(filled)
46060
- }, undefined, false, undefined, this),
46061
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46062
- color: "gray",
46063
- children: "\u2591".repeat(empty)
46064
- }, undefined, false, undefined, this),
46065
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46066
- children: [
46067
- " ",
46068
- percentage,
46069
- "%"
46070
- ]
46071
- }, undefined, true, undefined, this)
46072
- ]
46073
- }, undefined, true, undefined, this);
46074
- }
46075
-
46076
- // packages/terminal/src/components/Status.tsx
46077
- var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
46078
47190
  function Status({
46079
47191
  isProcessing,
46080
47192
  cwd: cwd2,
@@ -46112,75 +47224,60 @@ function Status({
46112
47224
  let contextInfo = "";
46113
47225
  if (tokenUsage && tokenUsage.maxContextTokens > 0) {
46114
47226
  const percent = Math.round(tokenUsage.totalTokens / tokenUsage.maxContextTokens * 100);
46115
- contextInfo = `${percent}% context`;
47227
+ contextInfo = `${percent}%`;
46116
47228
  }
46117
- const sessionInfo = sessionIndex && sessionCount ? `Session ${sessionIndex}/${sessionCount}` : "";
46118
- const bgIndicator = backgroundProcessingCount > 0 ? ` (${backgroundProcessingCount} processing)` : "";
46119
- const voiceInfo = voiceState?.enabled ? `voice ${voiceState.isListening ? "listening" : voiceState.isSpeaking ? "speaking" : "on"}` : "";
46120
- const identityLabel = identityInfo?.assistant && identityInfo?.identity ? `${identityInfo.assistant.name} \xB7 ${identityInfo.identity.name}` : "";
46121
- return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
47229
+ const sessionInfo = sessionIndex && sessionCount && sessionCount > 1 ? `${sessionIndex}/${sessionCount}` : "";
47230
+ const bgIndicator = backgroundProcessingCount > 0 ? ` +${backgroundProcessingCount}` : "";
47231
+ const voiceIcon = voiceState?.enabled ? voiceState.isListening ? "\uD83C\uDFA4" : voiceState.isSpeaking ? "\uD83D\uDD0A" : "\uD83C\uDF99" : "";
47232
+ const sessionLabel = sessionId ? `id ${sessionId}` : "";
47233
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46122
47234
  marginTop: 1,
46123
47235
  justifyContent: "space-between",
46124
47236
  children: [
46125
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47237
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46126
47238
  dimColor: true,
46127
47239
  children: [
46128
- "/help for commands",
46129
- sessionCount && sessionCount > 1 ? " | Ctrl+S sessions" : ""
47240
+ "/help",
47241
+ sessionCount && sessionCount > 1 ? " \xB7 Ctrl+S" : ""
46130
47242
  ]
46131
47243
  }, undefined, true, undefined, this),
46132
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
47244
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46133
47245
  children: [
46134
- energyState && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
46135
- marginRight: 2,
46136
- children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(EnergyBar, {
46137
- current: energyState.current,
46138
- max: energyState.max
46139
- }, undefined, false, undefined, this)
46140
- }, undefined, false, undefined, this),
46141
- identityLabel && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46142
- dimColor: true,
46143
- children: [
46144
- identityLabel,
46145
- " \xB7 "
46146
- ]
46147
- }, undefined, true, undefined, this),
46148
- voiceInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47246
+ voiceIcon && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46149
47247
  dimColor: true,
46150
47248
  children: [
46151
- voiceInfo,
46152
- " \xB7 "
47249
+ voiceIcon,
47250
+ " "
46153
47251
  ]
46154
47252
  }, undefined, true, undefined, this),
46155
- isProcessing && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47253
+ isProcessing && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46156
47254
  dimColor: true,
46157
- children: "esc to stop \xB7 "
47255
+ children: "esc \xB7 "
46158
47256
  }, undefined, false, undefined, this),
46159
- sessionInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47257
+ sessionInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46160
47258
  dimColor: true,
46161
47259
  children: [
46162
47260
  sessionInfo,
46163
47261
  bgIndicator,
46164
- contextInfo ? " \xB7 " : ""
47262
+ " \xB7 "
46165
47263
  ]
46166
47264
  }, undefined, true, undefined, this),
46167
- contextInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47265
+ contextInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46168
47266
  dimColor: true,
46169
47267
  children: contextInfo
46170
47268
  }, undefined, false, undefined, this),
46171
- sessionId && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47269
+ isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46172
47270
  dimColor: true,
46173
47271
  children: [
46174
- sessionInfo || contextInfo ? " \xB7 " : "",
46175
- "id ",
46176
- sessionId
47272
+ " \xB7 ",
47273
+ formatDuration2(elapsed)
46177
47274
  ]
46178
47275
  }, undefined, true, undefined, this),
46179
- isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47276
+ sessionLabel && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46180
47277
  dimColor: true,
46181
47278
  children: [
46182
- " \xB7 \u273B Worked for ",
46183
- formatDuration2(elapsed)
47279
+ contextInfo || isProcessing && processingStartTime || sessionInfo ? " \xB7 " : "",
47280
+ sessionLabel
46184
47281
  ]
46185
47282
  }, undefined, true, undefined, this)
46186
47283
  ]
@@ -46211,17 +47308,17 @@ function Spinner({ type = "dots" }) {
46211
47308
  var build_default2 = Spinner;
46212
47309
 
46213
47310
  // packages/terminal/src/components/Spinner.tsx
46214
- var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
47311
+ var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
46215
47312
  function Spinner2({ label }) {
46216
- return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
47313
+ return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
46217
47314
  children: [
46218
- /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47315
+ /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46219
47316
  dimColor: true,
46220
- children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(build_default2, {
47317
+ children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(build_default2, {
46221
47318
  type: "dots"
46222
47319
  }, undefined, false, undefined, this)
46223
47320
  }, undefined, false, undefined, this),
46224
- label && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47321
+ label && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46225
47322
  dimColor: true,
46226
47323
  children: [
46227
47324
  " ",
@@ -46234,7 +47331,7 @@ function Spinner2({ label }) {
46234
47331
 
46235
47332
  // packages/terminal/src/components/ProcessingIndicator.tsx
46236
47333
  var import_react27 = __toESM(require_react(), 1);
46237
- var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
47334
+ var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
46238
47335
  function ProcessingIndicator({
46239
47336
  isProcessing,
46240
47337
  startTime,
@@ -46278,14 +47375,14 @@ function ProcessingIndicator({
46278
47375
  parts.push("thinking");
46279
47376
  }
46280
47377
  const label = isThinking ? "Metamorphosing" : "Working";
46281
- return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
47378
+ return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
46282
47379
  marginY: 1,
46283
47380
  children: [
46284
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47381
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46285
47382
  dimColor: true,
46286
47383
  children: "\u2736 "
46287
47384
  }, undefined, false, undefined, this),
46288
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47385
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46289
47386
  dimColor: true,
46290
47387
  children: [
46291
47388
  " ",
@@ -46293,7 +47390,7 @@ function ProcessingIndicator({
46293
47390
  "... "
46294
47391
  ]
46295
47392
  }, undefined, true, undefined, this),
46296
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47393
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46297
47394
  dimColor: true,
46298
47395
  children: [
46299
47396
  "(",
@@ -46306,31 +47403,31 @@ function ProcessingIndicator({
46306
47403
  }
46307
47404
 
46308
47405
  // packages/terminal/src/components/WelcomeBanner.tsx
46309
- var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
47406
+ var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
46310
47407
  function WelcomeBanner({ version, model, directory }) {
46311
47408
  const homeDir = process.env.HOME || "";
46312
47409
  const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
46313
- return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47410
+ return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46314
47411
  flexDirection: "column",
46315
47412
  marginBottom: 1,
46316
47413
  children: [
46317
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47414
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46318
47415
  children: [
46319
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47416
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46320
47417
  color: "cyan",
46321
47418
  bold: true,
46322
47419
  children: ">"
46323
47420
  }, undefined, false, undefined, this),
46324
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47421
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46325
47422
  color: "cyan",
46326
47423
  bold: true,
46327
47424
  children: "_ "
46328
47425
  }, undefined, false, undefined, this),
46329
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47426
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46330
47427
  bold: true,
46331
47428
  children: "assistants"
46332
47429
  }, undefined, false, undefined, this),
46333
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47430
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46334
47431
  dimColor: true,
46335
47432
  children: [
46336
47433
  " (v",
@@ -46340,29 +47437,29 @@ function WelcomeBanner({ version, model, directory }) {
46340
47437
  }, undefined, true, undefined, this)
46341
47438
  ]
46342
47439
  }, undefined, true, undefined, this),
46343
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47440
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46344
47441
  marginTop: 1,
46345
47442
  children: [
46346
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47443
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46347
47444
  dimColor: true,
46348
47445
  children: "model: "
46349
47446
  }, undefined, false, undefined, this),
46350
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47447
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46351
47448
  children: model
46352
47449
  }, undefined, false, undefined, this),
46353
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47450
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46354
47451
  dimColor: true,
46355
47452
  children: " /model to change"
46356
47453
  }, undefined, false, undefined, this)
46357
47454
  ]
46358
47455
  }, undefined, true, undefined, this),
46359
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47456
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46360
47457
  children: [
46361
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47458
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46362
47459
  dimColor: true,
46363
47460
  children: "directory: "
46364
47461
  }, undefined, false, undefined, this),
46365
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47462
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46366
47463
  children: displayDir
46367
47464
  }, undefined, false, undefined, this)
46368
47465
  ]
@@ -46373,7 +47470,7 @@ function WelcomeBanner({ version, model, directory }) {
46373
47470
 
46374
47471
  // packages/terminal/src/components/SessionSelector.tsx
46375
47472
  var import_react28 = __toESM(require_react(), 1);
46376
- var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
47473
+ var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
46377
47474
  function formatSessionTime(timestamp) {
46378
47475
  const date = new Date(timestamp);
46379
47476
  const now2 = new Date;
@@ -46439,13 +47536,13 @@ function SessionSelector({
46439
47536
  return;
46440
47537
  }
46441
47538
  });
46442
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47539
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46443
47540
  flexDirection: "column",
46444
47541
  paddingY: 1,
46445
47542
  children: [
46446
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47543
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46447
47544
  marginBottom: 1,
46448
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47545
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46449
47546
  bold: true,
46450
47547
  children: "Sessions"
46451
47548
  }, undefined, false, undefined, this)
@@ -46457,8 +47554,8 @@ function SessionSelector({
46457
47554
  const time = formatSessionTime(session.updatedAt);
46458
47555
  const path2 = formatPath(session.cwd);
46459
47556
  const processing = session.isProcessing ? " (processing)" : "";
46460
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
46461
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47557
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47558
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46462
47559
  inverse: isSelected,
46463
47560
  color: isActive ? "green" : undefined,
46464
47561
  dimColor: !isSelected && !isActive,
@@ -46475,17 +47572,17 @@ function SessionSelector({
46475
47572
  }, undefined, true, undefined, this)
46476
47573
  }, session.id, false, undefined, this);
46477
47574
  }),
46478
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47575
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46479
47576
  marginTop: 1,
46480
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47577
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46481
47578
  inverse: selectedIndex === sessions.length,
46482
47579
  dimColor: selectedIndex !== sessions.length,
46483
47580
  children: "+ New session (n)"
46484
47581
  }, undefined, false, undefined, this)
46485
47582
  }, undefined, false, undefined, this),
46486
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47583
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46487
47584
  marginTop: 1,
46488
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47585
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46489
47586
  dimColor: true,
46490
47587
  children: [
46491
47588
  "Enter to select | Esc to cancel | 1-",
@@ -46499,32 +47596,8 @@ function SessionSelector({
46499
47596
  }
46500
47597
 
46501
47598
  // packages/terminal/src/components/App.tsx
46502
- var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
47599
+ var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
46503
47600
  var SHOW_ERROR_CODES = process.env.ASSISTANTS_DEBUG === "1" || process.env.OLDPAL_DEBUG === "1";
46504
- function formatToolName(toolCall) {
46505
- const { name, input } = toolCall;
46506
- switch (name) {
46507
- case "bash":
46508
- return `bash`;
46509
- case "read":
46510
- const path2 = String(input.path || input.file_path || "");
46511
- return `read ${path2.split("/").pop() || ""}`;
46512
- case "write":
46513
- const writePath = String(input.filename || input.path || input.file_path || "");
46514
- return `write ${writePath.split("/").pop() || ""}`;
46515
- case "glob":
46516
- return `glob`;
46517
- case "grep":
46518
- return `grep`;
46519
- case "web_search":
46520
- return `search`;
46521
- case "web_fetch":
46522
- case "curl":
46523
- return `fetch`;
46524
- default:
46525
- return name;
46526
- }
46527
- }
46528
47601
  function parseErrorMessage(error) {
46529
47602
  const lines = error.split(`
46530
47603
  `);
@@ -46544,9 +47617,75 @@ function parseErrorMessage(error) {
46544
47617
  }
46545
47618
  return { code, message, suggestion };
46546
47619
  }
47620
+ function formatElapsedDuration(ms) {
47621
+ const totalSeconds = Math.max(0, Math.floor(ms / 1000));
47622
+ if (totalSeconds < 60)
47623
+ return `${totalSeconds}s`;
47624
+ const mins = Math.floor(totalSeconds / 60);
47625
+ const secs = totalSeconds % 60;
47626
+ return `${mins}m ${secs}s`;
47627
+ }
46547
47628
  var MESSAGE_CHUNK_LINES = 12;
46548
47629
  var MESSAGE_WRAP_CHARS = 120;
46549
- function buildDisplayMessages(messages, chunkLines, wrapChars) {
47630
+ function wrapTextLines(text, wrapChars) {
47631
+ const rawLines = text.split(`
47632
+ `);
47633
+ const lines = [];
47634
+ for (const line of rawLines) {
47635
+ if (line.length <= wrapChars) {
47636
+ lines.push(line);
47637
+ continue;
47638
+ }
47639
+ for (let i = 0;i < line.length; i += wrapChars) {
47640
+ lines.push(line.slice(i, i + wrapChars));
47641
+ }
47642
+ }
47643
+ return lines;
47644
+ }
47645
+ function stripAnsi3(text) {
47646
+ return text.replace(/\x1B\[[0-9;]*m/g, "");
47647
+ }
47648
+ function chunkRenderedLines(lines, chunkLines) {
47649
+ const chunks = [];
47650
+ let current = [];
47651
+ let i = 0;
47652
+ const isBoxStart = (line) => stripAnsi3(line).trimStart().startsWith("\u250C");
47653
+ const isBoxEnd = (line) => stripAnsi3(line).trimStart().startsWith("\u2514");
47654
+ while (i < lines.length) {
47655
+ const line = lines[i];
47656
+ if (isBoxStart(line)) {
47657
+ let end = i + 1;
47658
+ while (end < lines.length && !isBoxEnd(lines[end])) {
47659
+ end += 1;
47660
+ }
47661
+ if (end < lines.length)
47662
+ end += 1;
47663
+ const boxLines = lines.slice(i, end);
47664
+ if (current.length > 0 && current.length + boxLines.length > chunkLines) {
47665
+ chunks.push(current);
47666
+ current = [];
47667
+ }
47668
+ if (boxLines.length >= chunkLines) {
47669
+ chunks.push(boxLines);
47670
+ } else {
47671
+ current.push(...boxLines);
47672
+ }
47673
+ i = end;
47674
+ continue;
47675
+ }
47676
+ if (current.length >= chunkLines) {
47677
+ chunks.push(current);
47678
+ current = [];
47679
+ }
47680
+ current.push(line);
47681
+ i += 1;
47682
+ }
47683
+ if (current.length > 0) {
47684
+ chunks.push(current);
47685
+ }
47686
+ return chunks;
47687
+ }
47688
+ function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
46550
47689
  const display = [];
46551
47690
  for (const msg of messages) {
46552
47691
  const content = msg.content ?? "";
@@ -46555,32 +47694,34 @@ function buildDisplayMessages(messages, chunkLines, wrapChars) {
46555
47694
  display.push(msg);
46556
47695
  continue;
46557
47696
  }
46558
- const rawLines = content.split(`
46559
- `);
46560
- const lines = [];
46561
- for (const line of rawLines) {
46562
- if (line.length <= wrapChars) {
46563
- lines.push(line);
46564
- continue;
46565
- }
46566
- for (let i = 0;i < line.length; i += wrapChars) {
46567
- lines.push(line.slice(i, i + wrapChars));
46568
- }
46569
- }
47697
+ const lines = wrapTextLines(content, wrapChars);
46570
47698
  if (lines.length <= chunkLines) {
46571
- display.push(msg);
47699
+ if (msg.role === "assistant") {
47700
+ const rendered2 = renderMarkdown(lines.join(`
47701
+ `), { maxWidth: options?.maxWidth });
47702
+ display.push({ ...msg, content: rendered2, __rendered: true });
47703
+ } else {
47704
+ display.push(msg);
47705
+ }
46572
47706
  continue;
46573
47707
  }
46574
- const totalChunks = Math.ceil(lines.length / chunkLines);
46575
- for (let i = 0;i < totalChunks; i++) {
46576
- const chunkContent = lines.slice(i * chunkLines, (i + 1) * chunkLines).join(`
47708
+ const baseContent = lines.join(`
47709
+ `);
47710
+ const renderAssistant = msg.role === "assistant";
47711
+ const rendered = renderAssistant ? renderMarkdown(baseContent, { maxWidth: options?.maxWidth }) : baseContent;
47712
+ const renderedLines = rendered.split(`
47713
+ `);
47714
+ const chunks = chunkRenderedLines(renderedLines, chunkLines);
47715
+ for (let i = 0;i < chunks.length; i++) {
47716
+ const chunkContent = chunks[i].join(`
46577
47717
  `);
46578
47718
  display.push({
46579
47719
  ...msg,
46580
47720
  id: `${msg.id}::chunk-${i}`,
46581
47721
  content: chunkContent,
46582
- toolCalls: i === totalChunks - 1 ? msg.toolCalls : undefined,
46583
- toolResults: i === totalChunks - 1 ? msg.toolResults : undefined
47722
+ __rendered: renderAssistant,
47723
+ toolCalls: i === chunks.length - 1 ? msg.toolCalls : undefined,
47724
+ toolResults: i === chunks.length - 1 ? msg.toolResults : undefined
46584
47725
  });
46585
47726
  }
46586
47727
  }
@@ -46601,6 +47742,7 @@ function App2({ cwd: cwd2, version }) {
46601
47742
  const [isProcessing, setIsProcessing] = import_react29.useState(false);
46602
47743
  const [error, setError] = import_react29.useState(null);
46603
47744
  const [messageQueue, setMessageQueue] = import_react29.useState([]);
47745
+ const [inlinePending, setInlinePending] = import_react29.useState([]);
46604
47746
  const [activityLog, setActivityLog] = import_react29.useState([]);
46605
47747
  const [tokenUsage, setTokenUsage] = import_react29.useState();
46606
47748
  const [energyState, setEnergyState] = import_react29.useState();
@@ -46615,7 +47757,7 @@ function App2({ cwd: cwd2, version }) {
46615
47757
  const toolCallsRef = import_react29.useRef([]);
46616
47758
  const toolResultsRef = import_react29.useRef([]);
46617
47759
  const activityLogRef = import_react29.useRef([]);
46618
- const prevDisplayCountRef = import_react29.useRef(0);
47760
+ const prevDisplayLineCountRef = import_react29.useRef(0);
46619
47761
  const skipNextDoneRef = import_react29.useRef(false);
46620
47762
  const isProcessingRef = import_react29.useRef(isProcessing);
46621
47763
  import_react29.useEffect(() => {
@@ -46672,6 +47814,12 @@ function App2({ cwd: cwd2, version }) {
46672
47814
  content = content ? `${content}
46673
47815
 
46674
47816
  [error]` : "[error]";
47817
+ }
47818
+ if (processingStartTime) {
47819
+ const workedFor = formatElapsedDuration(Date.now() - processingStartTime);
47820
+ content = content ? `${content}
47821
+
47822
+ \u273B Worked for ${workedFor}` : `\u273B Worked for ${workedFor}`;
46675
47823
  }
46676
47824
  setMessages((prev) => [
46677
47825
  ...prev,
@@ -46685,7 +47833,7 @@ function App2({ cwd: cwd2, version }) {
46685
47833
  }
46686
47834
  ]);
46687
47835
  return true;
46688
- }, [buildFullResponse]);
47836
+ }, [buildFullResponse, processingStartTime]);
46689
47837
  const resetTurnState = import_react29.useCallback(() => {
46690
47838
  setCurrentResponse("");
46691
47839
  responseRef.current = "";
@@ -46754,6 +47902,21 @@ function App2({ cwd: cwd2, version }) {
46754
47902
  setAutoScroll(true);
46755
47903
  }, []);
46756
47904
  const handleChunk = import_react29.useCallback((chunk) => {
47905
+ if (!isProcessingRef.current && (chunk.type === "text" || chunk.type === "tool_use" || chunk.type === "tool_result")) {
47906
+ const active = registryRef.current.getActiveSession();
47907
+ if (active) {
47908
+ registryRef.current.setProcessing(active.id, true);
47909
+ setIsProcessing(true);
47910
+ isProcessingRef.current = true;
47911
+ setProcessingStartTime(Date.now());
47912
+ setInlinePending((prev) => {
47913
+ const idx = prev.findIndex((msg) => msg.sessionId === active.id);
47914
+ if (idx === -1)
47915
+ return prev;
47916
+ return [...prev.slice(0, idx), ...prev.slice(idx + 1)];
47917
+ });
47918
+ }
47919
+ }
46757
47920
  if (chunk.type === "text" && chunk.content) {
46758
47921
  responseRef.current += chunk.content;
46759
47922
  setCurrentResponse(responseRef.current);
@@ -46937,9 +48100,11 @@ function App2({ cwd: cwd2, version }) {
46937
48100
  await activeSession2.client.send(nextMessage.content);
46938
48101
  }, [activeSessionId]);
46939
48102
  const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
46940
- const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.map((msg) => msg.id)), [activeQueue]);
48103
+ const activeInline = activeSessionId ? inlinePending.filter((msg) => msg.sessionId === activeSessionId) : [];
48104
+ const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.filter((msg) => msg.mode === "queued").map((msg) => msg.id)), [activeQueue]);
46941
48105
  const wrapChars = columns ? Math.max(40, columns - 4) : MESSAGE_WRAP_CHARS;
46942
- const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars), [messages, wrapChars]);
48106
+ const renderWidth = columns ? Math.max(20, columns - 2) : undefined;
48107
+ const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth }), [messages, wrapChars, renderWidth]);
46943
48108
  const streamingMessages = import_react29.useMemo(() => {
46944
48109
  if (!isProcessing || !currentResponse.trim())
46945
48110
  return [];
@@ -46949,9 +48114,12 @@ function App2({ cwd: cwd2, version }) {
46949
48114
  content: currentResponse,
46950
48115
  timestamp: now()
46951
48116
  };
46952
- return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
46953
- }, [currentResponse, isProcessing, wrapChars]);
46954
- const displayCount = displayMessages.length + streamingMessages.length;
48117
+ return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth });
48118
+ }, [currentResponse, isProcessing, wrapChars, renderWidth]);
48119
+ const displayLineCount = import_react29.useMemo(() => {
48120
+ const combined = [...displayMessages, ...streamingMessages];
48121
+ return combined.reduce((sum, msg) => sum + estimateMessageLines(msg), 0);
48122
+ }, [displayMessages, streamingMessages]);
46955
48123
  import_react29.useEffect(() => {
46956
48124
  if (!isProcessing && activeQueue.length > 0) {
46957
48125
  processQueue();
@@ -46961,23 +48129,21 @@ function App2({ cwd: cwd2, version }) {
46961
48129
  if (autoScroll) {
46962
48130
  setScrollOffset(0);
46963
48131
  }
46964
- }, [displayCount, autoScroll]);
48132
+ }, [displayLineCount, autoScroll]);
46965
48133
  import_react29.useEffect(() => {
46966
- const prevCount = prevDisplayCountRef.current;
46967
- if (!autoScroll && displayCount > prevCount) {
46968
- const delta = displayCount - prevCount;
48134
+ const prevCount = prevDisplayLineCountRef.current;
48135
+ if (!autoScroll && displayLineCount > prevCount) {
48136
+ const delta = displayLineCount - prevCount;
46969
48137
  setScrollOffset((prev) => prev + delta);
46970
48138
  }
46971
- prevDisplayCountRef.current = displayCount;
46972
- }, [displayCount, autoScroll]);
48139
+ prevDisplayLineCountRef.current = displayLineCount;
48140
+ }, [displayLineCount, autoScroll]);
46973
48141
  const reservedLines = 8;
46974
- const baseMaxVisible = rows ? Math.max(3, rows - reservedLines) : 10;
46975
- const toolCallsHeight = isProcessing ? Math.min(toolCallsRef.current.length, 5) : 0;
46976
- const maxVisibleMessages = Math.max(3, baseMaxVisible - toolCallsHeight);
48142
+ const maxVisibleLines = rows ? Math.max(6, rows - reservedLines) : 20;
46977
48143
  import_react29.useEffect(() => {
46978
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48144
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
46979
48145
  setScrollOffset((prev) => Math.min(prev, maxOffset));
46980
- }, [displayCount, maxVisibleMessages]);
48146
+ }, [displayLineCount, maxVisibleLines]);
46981
48147
  const sessions = registry2.listSessions();
46982
48148
  const activeSession = registry2.getActiveSession();
46983
48149
  const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
@@ -47056,8 +48222,9 @@ function App2({ cwd: cwd2, version }) {
47056
48222
  }
47057
48223
  if (key.pageUp || key.shift && key.upArrow) {
47058
48224
  setScrollOffset((prev) => {
47059
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
47060
- const newOffset = Math.min(prev + 3, maxOffset);
48225
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
48226
+ const step = Math.max(3, Math.floor(maxVisibleLines / 2));
48227
+ const newOffset = Math.min(prev + step, maxOffset);
47061
48228
  if (newOffset > 0)
47062
48229
  setAutoScroll(false);
47063
48230
  return newOffset;
@@ -47065,14 +48232,15 @@ function App2({ cwd: cwd2, version }) {
47065
48232
  }
47066
48233
  if (key.pageDown || key.shift && key.downArrow) {
47067
48234
  setScrollOffset((prev) => {
47068
- const newOffset = Math.max(0, prev - 3);
48235
+ const step = Math.max(3, Math.floor(maxVisibleLines / 2));
48236
+ const newOffset = Math.max(0, prev - step);
47069
48237
  if (newOffset === 0)
47070
48238
  setAutoScroll(true);
47071
48239
  return newOffset;
47072
48240
  });
47073
48241
  }
47074
48242
  if (key.ctrl && input === "u") {
47075
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48243
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
47076
48244
  setScrollOffset(maxOffset);
47077
48245
  setAutoScroll(false);
47078
48246
  }
@@ -47109,7 +48277,13 @@ function App2({ cwd: cwd2, version }) {
47109
48277
  const queuedId = generateId();
47110
48278
  setMessageQueue((prev) => [
47111
48279
  ...prev,
47112
- { id: queuedId, sessionId: activeSessionId, content: trimmedInput, queuedAt: now() }
48280
+ {
48281
+ id: queuedId,
48282
+ sessionId: activeSessionId,
48283
+ content: trimmedInput,
48284
+ queuedAt: now(),
48285
+ mode: "queued"
48286
+ }
47113
48287
  ]);
47114
48288
  setMessages((prev) => [
47115
48289
  ...prev,
@@ -47122,6 +48296,32 @@ function App2({ cwd: cwd2, version }) {
47122
48296
  ]);
47123
48297
  return;
47124
48298
  }
48299
+ if (mode === "inline") {
48300
+ if (!activeSessionId)
48301
+ return;
48302
+ const inlineId = generateId();
48303
+ setInlinePending((prev) => [
48304
+ ...prev,
48305
+ {
48306
+ id: inlineId,
48307
+ sessionId: activeSessionId,
48308
+ content: trimmedInput,
48309
+ queuedAt: now(),
48310
+ mode: "inline"
48311
+ }
48312
+ ]);
48313
+ setMessages((prev) => [
48314
+ ...prev,
48315
+ {
48316
+ id: inlineId,
48317
+ role: "user",
48318
+ content: trimmedInput,
48319
+ timestamp: now()
48320
+ }
48321
+ ]);
48322
+ await activeSession.client.send(trimmedInput);
48323
+ return;
48324
+ }
47125
48325
  if (mode === "interrupt" && isProcessing) {
47126
48326
  activeSession.client.stop();
47127
48327
  const finalized = finalizeResponse("interrupted");
@@ -47173,19 +48373,19 @@ function App2({ cwd: cwd2, version }) {
47173
48373
  activeSessionId
47174
48374
  ]);
47175
48375
  if (isInitializing) {
47176
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48376
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47177
48377
  flexDirection: "column",
47178
48378
  padding: 1,
47179
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Spinner2, {
48379
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Spinner2, {
47180
48380
  label: "Initializing..."
47181
48381
  }, undefined, false, undefined, this)
47182
48382
  }, undefined, false, undefined, this);
47183
48383
  }
47184
48384
  if (showSessionSelector) {
47185
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48385
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47186
48386
  flexDirection: "column",
47187
48387
  padding: 1,
47188
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(SessionSelector, {
48388
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SessionSelector, {
47189
48389
  sessions,
47190
48390
  activeSessionId,
47191
48391
  onSelect: handleSessionSwitch,
@@ -47205,19 +48405,21 @@ function App2({ cwd: cwd2, version }) {
47205
48405
  return text;
47206
48406
  return text.slice(0, maxLen - 3) + "...";
47207
48407
  };
48408
+ const queuedCount = activeQueue.filter((msg) => msg.mode === "queued").length;
48409
+ const inlineCount = activeInline.length;
47208
48410
  const showWelcome = messages.length === 0 && !isProcessing;
47209
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48411
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47210
48412
  flexDirection: "column",
47211
48413
  padding: 1,
47212
48414
  children: [
47213
- showWelcome && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(WelcomeBanner, {
47214
- version: version ?? "0.6.13",
48415
+ showWelcome && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(WelcomeBanner, {
48416
+ version: version ?? "unknown",
47215
48417
  model: "claude-sonnet-4",
47216
48418
  directory: activeSession?.cwd || cwd2
47217
48419
  }, undefined, false, undefined, this),
47218
- backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48420
+ backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47219
48421
  marginBottom: 1,
47220
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48422
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47221
48423
  color: "yellow",
47222
48424
  children: [
47223
48425
  backgroundProcessingCount,
@@ -47227,17 +48429,17 @@ function App2({ cwd: cwd2, version }) {
47227
48429
  ]
47228
48430
  }, undefined, true, undefined, this)
47229
48431
  }, undefined, false, undefined, this),
47230
- scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47231
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48432
+ scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
48433
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47232
48434
  dimColor: true,
47233
48435
  children: [
47234
48436
  "\u2191 ",
47235
48437
  scrollOffset,
47236
- " more messages above (Shift+\u2193 or Page Down to scroll down)"
48438
+ " more lines above (Shift+\u2193 or Page Down to scroll down)"
47237
48439
  ]
47238
48440
  }, undefined, true, undefined, this)
47239
48441
  }, undefined, false, undefined, this),
47240
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Messages4, {
48442
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Messages4, {
47241
48443
  messages: displayMessages,
47242
48444
  currentResponse: undefined,
47243
48445
  streamingMessages,
@@ -47245,65 +48447,38 @@ function App2({ cwd: cwd2, version }) {
47245
48447
  lastToolResult: undefined,
47246
48448
  activityLog: isProcessing ? activityLog : [],
47247
48449
  queuedMessageIds,
47248
- scrollOffset,
47249
- maxVisible: maxVisibleMessages
48450
+ scrollOffsetLines: scrollOffset,
48451
+ maxVisibleLines
47250
48452
  }, activeSessionId || "default", false, undefined, this),
47251
- isProcessing && toolCallEntries.length > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47252
- marginY: 1,
47253
- flexDirection: "column",
47254
- children: [
47255
- toolCallEntries.slice(-3).map(({ toolCall, result }) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47256
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47257
- dimColor: true,
47258
- children: [
47259
- result ? "\u2713" : "\u2699",
47260
- " ",
47261
- formatToolName(toolCall),
47262
- result?.isError && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47263
- color: "red",
47264
- children: " (error)"
47265
- }, undefined, false, undefined, this)
47266
- ]
47267
- }, undefined, true, undefined, this)
47268
- }, toolCall.id, false, undefined, this)),
47269
- toolCallEntries.length > 3 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47270
- dimColor: true,
47271
- children: [
47272
- " ... and ",
47273
- toolCallEntries.length - 3,
47274
- " more tools"
47275
- ]
47276
- }, undefined, true, undefined, this)
47277
- ]
47278
- }, undefined, true, undefined, this),
47279
- activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48453
+ (activeQueue.length > 0 || inlineCount > 0) && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47280
48454
  marginY: 1,
47281
48455
  flexDirection: "column",
47282
48456
  children: [
47283
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48457
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47284
48458
  dimColor: true,
47285
48459
  children: [
47286
- activeQueue.length,
47287
- " message",
47288
- activeQueue.length > 1 ? "s" : "",
47289
- " queued"
48460
+ activeQueue.length + inlineCount,
48461
+ " pending message",
48462
+ activeQueue.length + inlineCount > 1 ? "s" : "",
48463
+ inlineCount > 0 || queuedCount > 0 ? ` \xB7 ${inlineCount} in-stream \xB7 ${queuedCount} queued` : ""
47290
48464
  ]
47291
48465
  }, undefined, true, undefined, this),
47292
- activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48466
+ [...activeInline, ...activeQueue].slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47293
48467
  marginLeft: 2,
47294
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48468
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47295
48469
  dimColor: true,
47296
48470
  children: [
47297
- "\u276F ",
48471
+ queued.mode === "inline" ? "\u21B3" : "\u23F3",
48472
+ " ",
47298
48473
  truncateQueued(queued.content)
47299
48474
  ]
47300
48475
  }, undefined, true, undefined, this)
47301
48476
  }, queued.id, false, undefined, this)),
47302
- activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48477
+ activeQueue.length + inlineCount > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47303
48478
  dimColor: true,
47304
48479
  children: [
47305
48480
  " ... and ",
47306
- activeQueue.length - MAX_QUEUED_PREVIEW,
48481
+ activeQueue.length + inlineCount - MAX_QUEUED_PREVIEW,
47307
48482
  " more"
47308
48483
  ]
47309
48484
  }, undefined, true, undefined, this)
@@ -47313,18 +48488,18 @@ function App2({ cwd: cwd2, version }) {
47313
48488
  const parsed = parseErrorMessage(error);
47314
48489
  const severity = parsed.code && /TIMEOUT|RATE_LIMITED/.test(parsed.code) ? "yellow" : "red";
47315
48490
  const prefix = SHOW_ERROR_CODES && parsed.code ? `${parsed.code}: ` : "";
47316
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48491
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47317
48492
  marginY: 1,
47318
48493
  flexDirection: "column",
47319
48494
  children: [
47320
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48495
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47321
48496
  color: severity,
47322
48497
  children: [
47323
48498
  prefix,
47324
48499
  parsed.message
47325
48500
  ]
47326
48501
  }, undefined, true, undefined, this),
47327
- parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48502
+ parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47328
48503
  color: severity,
47329
48504
  children: [
47330
48505
  "Suggestion: ",
@@ -47334,22 +48509,22 @@ function App2({ cwd: cwd2, version }) {
47334
48509
  ]
47335
48510
  }, undefined, true, undefined, this);
47336
48511
  })(),
47337
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ProcessingIndicator, {
48512
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ProcessingIndicator, {
47338
48513
  isProcessing,
47339
48514
  startTime: processingStartTime,
47340
48515
  tokenCount: currentTurnTokens,
47341
48516
  isThinking
47342
48517
  }, undefined, false, undefined, this),
47343
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Input, {
48518
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Input, {
47344
48519
  onSubmit: handleSubmit,
47345
48520
  isProcessing,
47346
- queueLength: activeQueue.length,
48521
+ queueLength: activeQueue.length + inlineCount,
47347
48522
  skills
47348
48523
  }, undefined, false, undefined, this),
47349
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Status, {
48524
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Status, {
47350
48525
  isProcessing,
47351
48526
  cwd: activeSession?.cwd || cwd2,
47352
- queueLength: activeQueue.length,
48527
+ queueLength: activeQueue.length + inlineCount,
47353
48528
  tokenUsage,
47354
48529
  energyState,
47355
48530
  voiceState,
@@ -47538,8 +48713,9 @@ function formatStreamEvent(chunk) {
47538
48713
  }
47539
48714
 
47540
48715
  // packages/terminal/src/index.tsx
47541
- var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
47542
- var VERSION3 = "0.6.19";
48716
+ var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
48717
+ var VERSION3 = "0.6.21";
48718
+ process.env.ASSISTANTS_VERSION ??= VERSION3;
47543
48719
  function parseArgs(argv) {
47544
48720
  const args = argv.slice(2);
47545
48721
  const options = {
@@ -47665,14 +48841,7 @@ Interactive Mode:
47665
48841
  `);
47666
48842
  process.exit(0);
47667
48843
  }
47668
- try {
47669
- const result = await migrateFromOldpal();
47670
- if (!result.success && result.errors.length > 0) {
47671
- console.error(`Migration warning: ${result.errors.join("; ")}`);
47672
- }
47673
- } catch (error) {
47674
- console.error(`Migration warning: ${error instanceof Error ? error.message : String(error)}`);
47675
- }
48844
+ migrateFromOldpal().catch(() => {});
47676
48845
  if (options.print !== null) {
47677
48846
  if (!options.print.trim()) {
47678
48847
  console.error("Error: Prompt is required with -p/--print flag");
@@ -47693,7 +48862,7 @@ if (options.print !== null) {
47693
48862
  process.exit(1);
47694
48863
  });
47695
48864
  } else {
47696
- const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(App2, {
48865
+ const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(App2, {
47697
48866
  cwd: options.cwd,
47698
48867
  version: VERSION3
47699
48868
  }, undefined, false, undefined, this));
@@ -47702,4 +48871,4 @@ if (options.print !== null) {
47702
48871
  });
47703
48872
  }
47704
48873
 
47705
- //# debugId=6BDD2D63CEF73C2464756E2164756E21
48874
+ //# debugId=9F87F41E551C4D1964756E2164756E21