@hasna/assistants 0.6.19 → 0.6.20

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 };
@@ -27292,11 +27292,11 @@ __export(exports_anthropic, {
27292
27292
  });
27293
27293
  import { readFileSync as readFileSync2, existsSync as existsSync7 } 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");
27299
+ const secretsPath = join12(homeDir, ".secrets");
27300
27300
  if (existsSync7(secretsPath)) {
27301
27301
  try {
27302
27302
  const content = readFileSync2(secretsPath, "utf-8");
@@ -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
  }
@@ -36637,6 +36644,10 @@ function resolveTimeout(resolve) {
36637
36644
  class ConnectorBridge {
36638
36645
  connectors = new Map;
36639
36646
  static cache = new Map;
36647
+ cwd;
36648
+ constructor(cwd2) {
36649
+ this.cwd = cwd2;
36650
+ }
36640
36651
  getHomeDir() {
36641
36652
  const envHome = process.env.HOME || process.env.USERPROFILE;
36642
36653
  return envHome && envHome.trim().length > 0 ? envHome : homedir2();
@@ -36644,8 +36655,10 @@ class ConnectorBridge {
36644
36655
  autoDiscoverConnectorNames() {
36645
36656
  const connectorNames = new Set;
36646
36657
  const pathDirs = (process.env.PATH || "").split(delimiter);
36658
+ const baseCwd = this.cwd || process.cwd();
36647
36659
  const homeDir = this.getHomeDir();
36648
36660
  const extraDirs = [
36661
+ join3(baseCwd, "node_modules", ".bin"),
36649
36662
  join3(homeDir, ".bun", "bin"),
36650
36663
  join3(homeDir, ".npm-global", "bin"),
36651
36664
  "/usr/local/bin"
@@ -36888,17 +36901,20 @@ class ConnectorBridge {
36888
36901
  }
36889
36902
  const lowerCommand = command.toLowerCase();
36890
36903
  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) {
36904
+ const combined = [lowerCommand, ...lowerArgs].join(" ");
36905
+ const isAuthLogin = /\bauth\b/.test(combined) && /(login|authorize|authorization|oauth|signin|sign-in|connect)/.test(combined);
36906
+ const runInBackground = options.background === true;
36907
+ if (isAuthLogin || runInBackground) {
36893
36908
  try {
36894
- Bun.spawn(cmdParts, {
36909
+ const proc = Bun.spawn(cmdParts, {
36895
36910
  cwd: cwd2,
36896
36911
  stdin: "ignore",
36897
36912
  stdout: "ignore",
36898
36913
  stderr: "pipe"
36899
36914
  });
36915
+ proc.unref?.();
36900
36916
  } catch {}
36901
- return "Auth login started in the background. Complete it in your browser, then run auth status to confirm.";
36917
+ 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
36918
  }
36903
36919
  try {
36904
36920
  const proc = Bun.spawn(cmdParts, {
@@ -37036,6 +37052,38 @@ function stripQuotedSegments(input) {
37036
37052
  }
37037
37053
  return result;
37038
37054
  }
37055
+ function normalizeNewlinesOutsideQuotes(input) {
37056
+ let result = "";
37057
+ let quote = null;
37058
+ let escaped = false;
37059
+ for (let i = 0;i < input.length; i += 1) {
37060
+ const char = input[i];
37061
+ if (quote) {
37062
+ result += char;
37063
+ if (quote === '"' && !escaped && char === "\\") {
37064
+ escaped = true;
37065
+ continue;
37066
+ }
37067
+ if (!escaped && char === quote) {
37068
+ quote = null;
37069
+ }
37070
+ escaped = false;
37071
+ continue;
37072
+ }
37073
+ if (char === '"' || char === "'") {
37074
+ quote = char;
37075
+ result += char;
37076
+ continue;
37077
+ }
37078
+ if (char === "\r" || char === `
37079
+ `) {
37080
+ result += " ";
37081
+ continue;
37082
+ }
37083
+ result += char;
37084
+ }
37085
+ return result;
37086
+ }
37039
37087
 
37040
37088
  class BashTool {
37041
37089
  static tool = {
@@ -37155,7 +37203,11 @@ class BashTool {
37155
37203
  const command = input.command;
37156
37204
  const cwd2 = input.cwd || process.cwd();
37157
37205
  const timeout = input.timeout || 30000;
37158
- const commandForChecks = command.replace(/\s*2>&1\s*/g, " ");
37206
+ const baseCommand = command.replace(/\s*2>&1\s*/g, " ").trim();
37207
+ const baseTrimmed = baseCommand.toLowerCase();
37208
+ const allowConnectorNewlines = baseTrimmed.startsWith("connect-");
37209
+ const commandForExec = allowConnectorNewlines ? normalizeNewlinesOutsideQuotes(baseCommand).trim() : baseCommand;
37210
+ const commandForChecks = commandForExec;
37159
37211
  const commandSansQuotes = stripQuotedSegments(commandForChecks);
37160
37212
  const securityCheck = validateBashCommand(commandForChecks);
37161
37213
  if (!securityCheck.valid) {
@@ -37229,7 +37281,7 @@ class BashTool {
37229
37281
  });
37230
37282
  }
37231
37283
  try {
37232
- const proc = Bun.spawn(["bash", "-c", command], {
37284
+ const proc = Bun.spawn(["bash", "-c", commandForExec], {
37233
37285
  cwd: cwd2,
37234
37286
  stdout: "pipe",
37235
37287
  stderr: "pipe"
@@ -37356,15 +37408,16 @@ async function isPathSafe(targetPath, operation, options = {}) {
37356
37408
 
37357
37409
  // packages/core/src/tools/filesystem.ts
37358
37410
  var currentSessionId = "default";
37359
- function getScriptsFolder(cwd2) {
37411
+ function getScriptsFolder(cwd2, sessionId) {
37412
+ const resolvedSessionId = sessionId || currentSessionId;
37360
37413
  const legacyDir = join4(cwd2, ".oldpal");
37361
37414
  if (existsSync2(legacyDir)) {
37362
- return join4(legacyDir, "scripts", currentSessionId);
37415
+ return join4(legacyDir, "scripts", resolvedSessionId);
37363
37416
  }
37364
- return join4(getProjectConfigDir(cwd2), "scripts", currentSessionId);
37417
+ return join4(getProjectConfigDir(cwd2), "scripts", resolvedSessionId);
37365
37418
  }
37366
- function isInScriptsFolder(path2, cwd2) {
37367
- const scriptsFolder = resolve3(getScriptsFolder(cwd2));
37419
+ function isInScriptsFolder(path2, cwd2, sessionId) {
37420
+ const scriptsFolder = resolve3(getScriptsFolder(cwd2, sessionId));
37368
37421
  const resolved = resolve3(path2);
37369
37422
  if (resolved === scriptsFolder)
37370
37423
  return true;
@@ -37520,7 +37573,7 @@ class FilesystemTools {
37520
37573
  const filename = input.filename || input.path;
37521
37574
  const content = input.content;
37522
37575
  const baseCwd = input.cwd || process.cwd();
37523
- const scriptsFolder = getScriptsFolder(baseCwd);
37576
+ const scriptsFolder = getScriptsFolder(baseCwd, input.sessionId);
37524
37577
  if (!filename || !filename.trim()) {
37525
37578
  throw new ToolExecutionError("Filename is required", {
37526
37579
  toolName: "write",
@@ -37533,7 +37586,7 @@ class FilesystemTools {
37533
37586
  }
37534
37587
  const sanitizedFilename = filename.replace(/\.\.[/\\]/g, "").replace(/\.\./g, "").replace(/^[/\\]+/, "");
37535
37588
  const path2 = join4(scriptsFolder, sanitizedFilename);
37536
- if (!isInScriptsFolder(path2, baseCwd)) {
37589
+ if (!isInScriptsFolder(path2, baseCwd, input.sessionId)) {
37537
37590
  throw new ToolExecutionError(`Cannot write outside scripts folder. Files are saved to ${scriptsFolder}`, {
37538
37591
  toolName: "write",
37539
37592
  toolInput: input,
@@ -39737,13 +39790,217 @@ ${stderr}`;
39737
39790
  }
39738
39791
  }
39739
39792
  // packages/core/src/commands/builtin.ts
39740
- import { join as join10 } from "path";
39793
+ import { join as join11 } from "path";
39741
39794
  import { homedir as homedir7, platform as platform2, release, arch } from "os";
39742
39795
  import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
39743
39796
  init_src();
39744
- var VERSION = "0.6.14";
39745
- function resolveAuthTimeout(resolve4) {
39746
- resolve4({ exitCode: 1, stdout: { toString: () => "{}" } });
39797
+
39798
+ // packages/core/src/projects/store.ts
39799
+ init_src();
39800
+ import { join as join10 } from "path";
39801
+ import { mkdir as mkdir3, readdir as readdir2, readFile as readFile2, unlink as unlink2, writeFile as writeFile2 } from "fs/promises";
39802
+ function projectsDir(cwd2) {
39803
+ return join10(cwd2, ".oldpal", "projects");
39804
+ }
39805
+ function projectPath(cwd2, id) {
39806
+ return join10(projectsDir(cwd2), `${id}.json`);
39807
+ }
39808
+ async function ensureProjectsDir(cwd2) {
39809
+ await mkdir3(projectsDir(cwd2), { recursive: true });
39810
+ }
39811
+ function normalizeName(name) {
39812
+ return name.trim().toLowerCase();
39813
+ }
39814
+ async function listProjects(cwd2) {
39815
+ try {
39816
+ const dir = projectsDir(cwd2);
39817
+ const files = await readdir2(dir);
39818
+ const projects = [];
39819
+ for (const file of files) {
39820
+ if (!file.endsWith(".json"))
39821
+ continue;
39822
+ try {
39823
+ const raw = await readFile2(join10(dir, file), "utf-8");
39824
+ const parsed = JSON.parse(raw);
39825
+ if (parsed?.id && parsed?.name) {
39826
+ projects.push(parsed);
39827
+ }
39828
+ } catch {}
39829
+ }
39830
+ return projects.sort((a, b) => b.updatedAt - a.updatedAt);
39831
+ } catch {
39832
+ return [];
39833
+ }
39834
+ }
39835
+ async function readProject(cwd2, id) {
39836
+ try {
39837
+ const raw = await readFile2(projectPath(cwd2, id), "utf-8");
39838
+ const project = JSON.parse(raw);
39839
+ if (!project?.id || !project?.name)
39840
+ return null;
39841
+ return project;
39842
+ } catch {
39843
+ return null;
39844
+ }
39845
+ }
39846
+ async function findProjectByName(cwd2, name) {
39847
+ const normalized = normalizeName(name);
39848
+ const projects = await listProjects(cwd2);
39849
+ return projects.find((project) => normalizeName(project.name) === normalized) || null;
39850
+ }
39851
+ async function saveProject(cwd2, project) {
39852
+ await ensureProjectsDir(cwd2);
39853
+ await writeFile2(projectPath(cwd2, project.id), JSON.stringify(project, null, 2), "utf-8");
39854
+ }
39855
+ async function deleteProject(cwd2, id) {
39856
+ try {
39857
+ await unlink2(projectPath(cwd2, id));
39858
+ return true;
39859
+ } catch {
39860
+ return false;
39861
+ }
39862
+ }
39863
+ async function createProject(cwd2, name, description) {
39864
+ const now2 = Date.now();
39865
+ const project = {
39866
+ id: generateId(),
39867
+ name: name.trim(),
39868
+ description: description?.trim() || undefined,
39869
+ createdAt: now2,
39870
+ updatedAt: now2,
39871
+ context: [],
39872
+ plans: []
39873
+ };
39874
+ await saveProject(cwd2, project);
39875
+ return project;
39876
+ }
39877
+ async function updateProject(cwd2, id, updater) {
39878
+ const project = await readProject(cwd2, id);
39879
+ if (!project)
39880
+ return null;
39881
+ const updated = updater(project);
39882
+ await saveProject(cwd2, updated);
39883
+ return updated;
39884
+ }
39885
+ async function ensureDefaultProject(cwd2) {
39886
+ const projects = await listProjects(cwd2);
39887
+ if (projects.length > 0)
39888
+ return projects[0];
39889
+ return createProject(cwd2, "default", "Default project for this folder");
39890
+ }
39891
+ function hasProjectNameConflict(projects, name) {
39892
+ const normalized = normalizeName(name);
39893
+ return projects.some((project) => normalizeName(project.name) === normalized);
39894
+ }
39895
+
39896
+ // packages/core/src/projects/context.ts
39897
+ import { readFile as readFile3 } from "fs/promises";
39898
+ import { resolve as resolve4 } from "path";
39899
+ var DEFAULT_MAX_FILE_BYTES = 12000;
39900
+ function formatPlan(plan) {
39901
+ const lines = [];
39902
+ lines.push(`- ${plan.title} (${plan.steps.length} steps)`);
39903
+ for (const step of plan.steps) {
39904
+ lines.push(` - [${step.status}] ${step.text}`);
39905
+ }
39906
+ return lines.join(`
39907
+ `);
39908
+ }
39909
+ function normalizeEntryLabel(entry) {
39910
+ return entry.label ? entry.label.trim() : entry.value.trim();
39911
+ }
39912
+ async function renderFileEntry(entry, options) {
39913
+ const rawPath = entry.value.trim();
39914
+ const resolved = resolve4(options.cwd, rawPath);
39915
+ const validation = await validatePath(resolved, { allowedPaths: [options.cwd] });
39916
+ if (!validation.valid) {
39917
+ return `- File: ${rawPath} (unavailable: ${validation.error || "invalid path"})`;
39918
+ }
39919
+ let content = "";
39920
+ try {
39921
+ const data = await readFile3(validation.resolved, "utf-8");
39922
+ const limit = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
39923
+ if (data.length > limit) {
39924
+ content = `${data.slice(0, limit)}
39925
+
39926
+ ... [truncated ${data.length - limit} chars]`;
39927
+ } else {
39928
+ content = data;
39929
+ }
39930
+ } catch (error) {
39931
+ return `- File: ${rawPath} (unavailable: ${error instanceof Error ? error.message : String(error)})`;
39932
+ }
39933
+ return `- File: ${rawPath}
39934
+ \`\`\`
39935
+ ${content}
39936
+ \`\`\``;
39937
+ }
39938
+ function renderConnectorEntry(entry, connectors) {
39939
+ const name = entry.value.trim();
39940
+ const connector = connectors?.find((c) => c.name === name);
39941
+ if (!connector) {
39942
+ return `- Connector: ${name}`;
39943
+ }
39944
+ const lines = [];
39945
+ lines.push(`- Connector: ${connector.name}`);
39946
+ if (connector.description) {
39947
+ lines.push(` - ${connector.description}`);
39948
+ }
39949
+ if (connector.cli) {
39950
+ lines.push(` - CLI: ${connector.cli}`);
39951
+ }
39952
+ if (connector.commands && connector.commands.length > 0) {
39953
+ const subset = connector.commands.slice(0, 5);
39954
+ for (const cmd of subset) {
39955
+ lines.push(` - ${cmd.name}: ${cmd.description}`);
39956
+ }
39957
+ if (connector.commands.length > subset.length) {
39958
+ lines.push(` - ... ${connector.commands.length - subset.length} more commands`);
39959
+ }
39960
+ }
39961
+ return lines.join(`
39962
+ `);
39963
+ }
39964
+ function renderGenericEntry(entry) {
39965
+ const label = normalizeEntryLabel(entry);
39966
+ return `- ${entry.type}: ${label}`;
39967
+ }
39968
+ async function buildProjectContext(project, options) {
39969
+ const lines = [];
39970
+ lines.push(`## Project: ${project.name}`);
39971
+ if (project.description) {
39972
+ lines.push(`Description: ${project.description}`);
39973
+ }
39974
+ if (project.context.length > 0) {
39975
+ lines.push("");
39976
+ lines.push("### Project Context");
39977
+ for (const entry of project.context) {
39978
+ if (entry.type === "file") {
39979
+ lines.push(await renderFileEntry(entry, options));
39980
+ continue;
39981
+ }
39982
+ if (entry.type === "connector") {
39983
+ lines.push(renderConnectorEntry(entry, options.connectors));
39984
+ continue;
39985
+ }
39986
+ lines.push(renderGenericEntry(entry));
39987
+ }
39988
+ }
39989
+ if (project.plans.length > 0) {
39990
+ lines.push("");
39991
+ lines.push("### Plans");
39992
+ for (const plan of project.plans) {
39993
+ lines.push(formatPlan(plan));
39994
+ }
39995
+ }
39996
+ return lines.join(`
39997
+ `);
39998
+ }
39999
+
40000
+ // packages/core/src/commands/builtin.ts
40001
+ var VERSION = process.env.ASSISTANTS_VERSION || process.env.npm_package_version || process.env.OLDPAL_VERSION || "unknown";
40002
+ function resolveAuthTimeout(resolve5) {
40003
+ resolve5({ exitCode: 1, stdout: { toString: () => "{}" } });
39747
40004
  }
39748
40005
  function splitArgs(input) {
39749
40006
  const args = [];
@@ -39792,6 +40049,8 @@ class BuiltinCommands {
39792
40049
  loader.register(this.statusCommand());
39793
40050
  loader.register(this.tokensCommand());
39794
40051
  loader.register(this.contextCommand());
40052
+ loader.register(this.projectsCommand());
40053
+ loader.register(this.plansCommand());
39795
40054
  loader.register(this.summarizeCommand());
39796
40055
  loader.register(this.restCommand());
39797
40056
  loader.register(this.voiceCommand());
@@ -40397,151 +40656,743 @@ Identities:
40397
40656
  contextCommand() {
40398
40657
  return {
40399
40658
  name: "context",
40400
- description: "Show context summarization status",
40659
+ description: "Manage injected project context (files, connectors, notes) or show status",
40401
40660
  builtin: true,
40402
40661
  selfHandled: true,
40403
40662
  content: "",
40404
40663
  handler: async (args, context) => {
40405
- const info = context.getContextInfo?.();
40406
- if (!info) {
40664
+ const parts = splitArgs(args);
40665
+ const sub = parts[0] || "status";
40666
+ if (sub === "help") {
40667
+ const usage = [
40668
+ "Usage:",
40669
+ " /context status",
40670
+ " /context list",
40671
+ " /context add file <path>",
40672
+ " /context add connector <name>",
40673
+ " /context add database <name>",
40674
+ " /context add note <text>",
40675
+ " /context add entity <text>",
40676
+ " /context remove <id>",
40677
+ " /context clear"
40678
+ ].join(`
40679
+ `);
40407
40680
  context.emit("text", `
40408
- Context summarization is not available.
40681
+ ${usage}
40409
40682
  `);
40410
40683
  context.emit("done");
40411
40684
  return { handled: true };
40412
40685
  }
40413
- const { config, state } = info;
40414
- const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
40415
- let message = `
40686
+ if (sub === "status") {
40687
+ const info = context.getContextInfo?.();
40688
+ if (!info) {
40689
+ context.emit("text", `
40690
+ Context summarization is not available.
40691
+ `);
40692
+ context.emit("done");
40693
+ return { handled: true };
40694
+ }
40695
+ const { config, state } = info;
40696
+ const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
40697
+ let message = `
40416
40698
  **Context Status**
40417
40699
 
40418
40700
  `;
40419
- message += `**Messages:** ${state.messageCount}
40701
+ message += `**Messages:** ${state.messageCount}
40420
40702
  `;
40421
- message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40703
+ message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40422
40704
  `;
40423
- message += `**Summary Count:** ${state.summaryCount}
40705
+ message += `**Summary Count:** ${state.summaryCount}
40424
40706
  `;
40425
- message += `**Strategy:** ${config.summaryStrategy}
40707
+ message += `**Strategy:** ${config.summaryStrategy}
40426
40708
  `;
40427
- message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40709
+ message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40428
40710
  `;
40429
- if (state.lastSummaryAt) {
40430
- message += `**Last Summary:** ${state.lastSummaryAt}
40711
+ if (state.lastSummaryAt) {
40712
+ message += `**Last Summary:** ${state.lastSummaryAt}
40431
40713
  `;
40432
- if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
40433
- message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
40714
+ if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
40715
+ message += `**Last Summary Tokens:** ${state.lastSummaryTokensBefore.toLocaleString()} -> ${state.lastSummaryTokensAfter.toLocaleString()}
40434
40716
  `;
40717
+ }
40435
40718
  }
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 += `
40719
+ const barLength = 30;
40720
+ const filledLength = Math.round(usedPercent / 100 * barLength);
40721
+ const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
40722
+ message += `
40441
40723
  [${bar}] ${usedPercent}%
40442
40724
  `;
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
- `);
40725
+ context.emit("text", message);
40461
40726
  context.emit("done");
40462
40727
  return { handled: true };
40463
40728
  }
40464
- const result = await context.summarizeContext();
40465
- if (!result.summarized) {
40466
- context.emit("text", `
40467
- Nothing to summarize right now.
40729
+ const project = await this.ensureActiveProject(context, true);
40730
+ if (!project) {
40731
+ context.emit("text", `No project found. Use /projects new <name> first.
40468
40732
  `);
40469
40733
  context.emit("done");
40470
40734
  return { handled: true };
40471
40735
  }
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()}
40736
+ if (sub === "list") {
40737
+ if (project.context.length === 0) {
40738
+ context.emit("text", `
40739
+ No context entries for project "${project.name}".
40740
+ `);
40741
+ context.emit("done");
40742
+ return { handled: true };
40743
+ }
40744
+ let output = `
40745
+ **Context Entries (${project.name})**
40479
40746
 
40480
40747
  `;
40481
- if (result.summary) {
40482
- message += `${result.summary}
40748
+ for (const entry of project.context) {
40749
+ const label = entry.label ? ` (${entry.label})` : "";
40750
+ output += `- ${entry.id} [${entry.type}] ${entry.value}${label}
40483
40751
  `;
40752
+ }
40753
+ context.emit("text", output);
40754
+ context.emit("done");
40755
+ return { handled: true };
40484
40756
  }
40485
- context.emit("text", message);
40757
+ if (sub === "clear") {
40758
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40759
+ ...current,
40760
+ context: [],
40761
+ updatedAt: Date.now()
40762
+ }));
40763
+ if (updated) {
40764
+ await this.applyProjectContext(context, updated);
40765
+ context.emit("text", `Cleared context entries for "${updated.name}".
40766
+ `);
40767
+ context.emit("done");
40768
+ return { handled: true };
40769
+ }
40770
+ }
40771
+ if (sub === "remove") {
40772
+ const id = parts[1];
40773
+ if (!id) {
40774
+ context.emit("text", `Usage: /context remove <id>
40775
+ `);
40776
+ context.emit("done");
40777
+ return { handled: true };
40778
+ }
40779
+ if (!project.context.some((entry) => entry.id === id)) {
40780
+ context.emit("text", `Context entry not found: ${id}
40781
+ `);
40782
+ context.emit("done");
40783
+ return { handled: true };
40784
+ }
40785
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40786
+ ...current,
40787
+ context: current.context.filter((entry) => entry.id !== id),
40788
+ updatedAt: Date.now()
40789
+ }));
40790
+ if (updated) {
40791
+ await this.applyProjectContext(context, updated);
40792
+ context.emit("text", `Removed context entry ${id} from "${updated.name}".
40793
+ `);
40794
+ context.emit("done");
40795
+ return { handled: true };
40796
+ }
40797
+ }
40798
+ if (sub === "add") {
40799
+ const type = parts[1];
40800
+ const value = parts.slice(2).join(" ").trim();
40801
+ if (!type) {
40802
+ context.emit("text", `Usage: /context add <type> <value>
40803
+ `);
40804
+ context.emit("done");
40805
+ return { handled: true };
40806
+ }
40807
+ const allowedTypes = ["file", "connector", "database", "note", "entity"];
40808
+ const entryType = allowedTypes.includes(type) ? type : "note";
40809
+ const entryValue = entryType === "note" && !value ? parts.slice(1).join(" ").trim() : value;
40810
+ if (!entryValue) {
40811
+ context.emit("text", `Error: context value is required.
40812
+ `);
40813
+ context.emit("done");
40814
+ return { handled: true };
40815
+ }
40816
+ const entry = {
40817
+ id: generateId(),
40818
+ type: entryType,
40819
+ value: entryValue,
40820
+ addedAt: Date.now()
40821
+ };
40822
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40823
+ ...current,
40824
+ context: [...current.context, entry],
40825
+ updatedAt: Date.now()
40826
+ }));
40827
+ if (updated) {
40828
+ await this.applyProjectContext(context, updated);
40829
+ context.emit("text", `Added ${entry.type} context to "${updated.name}".
40830
+ `);
40831
+ context.emit("done");
40832
+ return { handled: true };
40833
+ }
40834
+ }
40835
+ context.emit("text", `Unknown /context command. Use /context help.
40836
+ `);
40486
40837
  context.emit("done");
40487
40838
  return { handled: true };
40488
40839
  }
40489
40840
  };
40490
40841
  }
40491
- restCommand() {
40842
+ projectsCommand() {
40492
40843
  return {
40493
- name: "rest",
40494
- description: "Recharge assistant energy",
40844
+ name: "projects",
40845
+ description: "Manage projects inside this folder",
40495
40846
  builtin: true,
40496
40847
  selfHandled: true,
40497
40848
  content: "",
40498
40849
  handler: async (args, context) => {
40499
- if (!context.restEnergy) {
40850
+ const parts = splitArgs(args);
40851
+ const sub = parts[0] || "list";
40852
+ if (sub === "help") {
40853
+ const usage = [
40854
+ "Usage:",
40855
+ " /projects list",
40856
+ " /projects new <name>",
40857
+ " /projects use <id|name>",
40858
+ " /projects show [id|name]",
40859
+ " /projects delete <id|name>",
40860
+ " /projects describe <id|name> <description>"
40861
+ ].join(`
40862
+ `);
40500
40863
  context.emit("text", `
40501
- Energy system is not available.
40864
+ ${usage}
40502
40865
  `);
40503
40866
  context.emit("done");
40504
40867
  return { handled: true };
40505
40868
  }
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.
40869
+ if (sub === "list" || sub === "ls") {
40870
+ const projects = await listProjects(context.cwd);
40871
+ if (projects.length === 0) {
40872
+ context.emit("text", `
40873
+ No projects found. Use /projects new <name>.
40518
40874
  `);
40519
- }
40520
- context.emit("done");
40521
- return { handled: true };
40522
- }
40523
- };
40524
- }
40525
- skillsCommand(loader) {
40526
- return {
40527
- name: "skills",
40528
- description: "List available skills",
40529
- builtin: true,
40530
- selfHandled: true,
40531
- content: "",
40532
- handler: async (args, context) => {
40533
- let message = `
40534
- **Available Skills**
40535
-
40536
- `;
40537
- message += `Skills are invoked with $skill-name [arguments] or /skill-name [arguments]
40875
+ context.emit("done");
40876
+ return { handled: true };
40877
+ }
40878
+ const activeId = context.getActiveProjectId?.();
40879
+ let output = `
40880
+ **Projects**
40538
40881
 
40539
40882
  `;
40540
- if (context.skills.length === 0) {
40541
- message += `No skills loaded.
40883
+ for (const project of projects) {
40884
+ const marker = project.id === activeId ? "*" : " ";
40885
+ output += `${marker} ${project.name} (${project.id})
40542
40886
  `;
40543
- message += `
40544
- Add skills to ~/.assistants/assistants-shared/skills/ or .assistants/skills/
40887
+ }
40888
+ context.emit("text", output);
40889
+ context.emit("done");
40890
+ return { handled: true };
40891
+ }
40892
+ if (sub === "new" || sub === "create") {
40893
+ const name = parts.slice(1).join(" ").trim();
40894
+ if (!name) {
40895
+ context.emit("text", `Usage: /projects new <name>
40896
+ `);
40897
+ context.emit("done");
40898
+ return { handled: true };
40899
+ }
40900
+ const existing = await listProjects(context.cwd);
40901
+ if (hasProjectNameConflict(existing, name)) {
40902
+ context.emit("text", `Project "${name}" already exists.
40903
+ `);
40904
+ context.emit("done");
40905
+ return { handled: true };
40906
+ }
40907
+ const project = await createProject(context.cwd, name);
40908
+ context.setActiveProjectId?.(project.id);
40909
+ await this.applyProjectContext(context, project);
40910
+ context.emit("text", `Created project "${project.name}" (${project.id}).
40911
+ `);
40912
+ context.emit("done");
40913
+ return { handled: true };
40914
+ }
40915
+ if (sub === "use" || sub === "switch") {
40916
+ const target = parts.slice(1).join(" ").trim();
40917
+ if (!target) {
40918
+ context.emit("text", `Usage: /projects use <id|name>
40919
+ `);
40920
+ context.emit("done");
40921
+ return { handled: true };
40922
+ }
40923
+ const project = await this.resolveProject(context, target);
40924
+ if (!project) {
40925
+ context.emit("text", `Project not found: ${target}
40926
+ `);
40927
+ context.emit("done");
40928
+ return { handled: true };
40929
+ }
40930
+ context.setActiveProjectId?.(project.id);
40931
+ await this.applyProjectContext(context, project);
40932
+ context.emit("text", `Switched to project "${project.name}".
40933
+ `);
40934
+ context.emit("done");
40935
+ return { handled: true };
40936
+ }
40937
+ if (sub === "show" || sub === "info") {
40938
+ const target = parts.slice(1).join(" ").trim();
40939
+ const project = target ? await this.resolveProject(context, target) : await this.ensureActiveProject(context, false);
40940
+ if (!project) {
40941
+ context.emit("text", `No project selected. Use /projects use <id|name>.
40942
+ `);
40943
+ context.emit("done");
40944
+ return { handled: true };
40945
+ }
40946
+ let output = `
40947
+ **Project: ${project.name}**
40948
+
40949
+ `;
40950
+ output += `ID: ${project.id}
40951
+ `;
40952
+ if (project.description) {
40953
+ output += `Description: ${project.description}
40954
+ `;
40955
+ }
40956
+ output += `Context entries: ${project.context.length}
40957
+ `;
40958
+ output += `Plans: ${project.plans.length}
40959
+ `;
40960
+ context.emit("text", output);
40961
+ context.emit("done");
40962
+ return { handled: true };
40963
+ }
40964
+ if (sub === "describe" || sub === "desc") {
40965
+ const target = parts[1];
40966
+ const description = parts.slice(2).join(" ").trim();
40967
+ if (!target || !description) {
40968
+ context.emit("text", `Usage: /projects describe <id|name> <description>
40969
+ `);
40970
+ context.emit("done");
40971
+ return { handled: true };
40972
+ }
40973
+ const project = await this.resolveProject(context, target);
40974
+ if (!project) {
40975
+ context.emit("text", `Project not found: ${target}
40976
+ `);
40977
+ context.emit("done");
40978
+ return { handled: true };
40979
+ }
40980
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
40981
+ ...current,
40982
+ description,
40983
+ updatedAt: Date.now()
40984
+ }));
40985
+ if (updated) {
40986
+ await this.applyProjectContext(context, updated);
40987
+ context.emit("text", `Updated project "${updated.name}".
40988
+ `);
40989
+ context.emit("done");
40990
+ return { handled: true };
40991
+ }
40992
+ }
40993
+ if (sub === "delete" || sub === "rm") {
40994
+ const target = parts.slice(1).join(" ").trim();
40995
+ if (!target) {
40996
+ context.emit("text", `Usage: /projects delete <id|name>
40997
+ `);
40998
+ context.emit("done");
40999
+ return { handled: true };
41000
+ }
41001
+ const project = await this.resolveProject(context, target);
41002
+ if (!project) {
41003
+ context.emit("text", `Project not found: ${target}
41004
+ `);
41005
+ context.emit("done");
41006
+ return { handled: true };
41007
+ }
41008
+ const ok = await deleteProject(context.cwd, project.id);
41009
+ if (ok) {
41010
+ if (context.getActiveProjectId?.() === project.id) {
41011
+ context.setActiveProjectId?.(null);
41012
+ context.setProjectContext?.(null);
41013
+ }
41014
+ context.emit("text", `Deleted project "${project.name}".
41015
+ `);
41016
+ context.emit("done");
41017
+ return { handled: true };
41018
+ }
41019
+ }
41020
+ context.emit("text", `Unknown /projects command. Use /projects help.
41021
+ `);
41022
+ context.emit("done");
41023
+ return { handled: true };
41024
+ }
41025
+ };
41026
+ }
41027
+ plansCommand() {
41028
+ return {
41029
+ name: "plans",
41030
+ description: "Manage plans linked to the active project",
41031
+ builtin: true,
41032
+ selfHandled: true,
41033
+ content: "",
41034
+ handler: async (args, context) => {
41035
+ const parts = splitArgs(args);
41036
+ const sub = parts[0] || "list";
41037
+ if (sub === "help") {
41038
+ const usage = [
41039
+ "Usage:",
41040
+ " /plans list",
41041
+ " /plans new <title>",
41042
+ " /plans show <planId>",
41043
+ " /plans add <planId> <step>",
41044
+ " /plans set <planId> <stepId> <todo|doing|done|blocked>",
41045
+ " /plans remove <planId> <stepId>",
41046
+ " /plans delete <planId>"
41047
+ ].join(`
41048
+ `);
41049
+ context.emit("text", `
41050
+ ${usage}
41051
+ `);
41052
+ context.emit("done");
41053
+ return { handled: true };
41054
+ }
41055
+ const project = await this.ensureActiveProject(context, true);
41056
+ if (!project) {
41057
+ context.emit("text", `No project found. Use /projects new <name> first.
41058
+ `);
41059
+ context.emit("done");
41060
+ return { handled: true };
41061
+ }
41062
+ if (sub === "list" || sub === "ls") {
41063
+ if (project.plans.length === 0) {
41064
+ context.emit("text", `
41065
+ No plans for project "${project.name}".
41066
+ `);
41067
+ context.emit("done");
41068
+ return { handled: true };
41069
+ }
41070
+ let output = `
41071
+ **Plans (${project.name})**
41072
+
41073
+ `;
41074
+ for (const plan of project.plans) {
41075
+ output += `- ${plan.id} ${plan.title} (${plan.steps.length} steps)
41076
+ `;
41077
+ }
41078
+ context.emit("text", output);
41079
+ context.emit("done");
41080
+ return { handled: true };
41081
+ }
41082
+ if (sub === "new" || sub === "create") {
41083
+ const title = parts.slice(1).join(" ").trim();
41084
+ if (!title) {
41085
+ context.emit("text", `Usage: /plans new <title>
41086
+ `);
41087
+ context.emit("done");
41088
+ return { handled: true };
41089
+ }
41090
+ const now2 = Date.now();
41091
+ const plan = {
41092
+ id: generateId(),
41093
+ title,
41094
+ createdAt: now2,
41095
+ updatedAt: now2,
41096
+ steps: []
41097
+ };
41098
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41099
+ ...current,
41100
+ plans: [...current.plans, plan],
41101
+ updatedAt: now2
41102
+ }));
41103
+ if (updated) {
41104
+ await this.applyProjectContext(context, updated);
41105
+ context.emit("text", `Created plan "${plan.title}" (${plan.id}).
41106
+ `);
41107
+ context.emit("done");
41108
+ return { handled: true };
41109
+ }
41110
+ }
41111
+ if (sub === "show") {
41112
+ const id = parts[1];
41113
+ if (!id) {
41114
+ context.emit("text", `Usage: /plans show <planId>
41115
+ `);
41116
+ context.emit("done");
41117
+ return { handled: true };
41118
+ }
41119
+ const plan = project.plans.find((p) => p.id === id);
41120
+ if (!plan) {
41121
+ context.emit("text", `Plan not found: ${id}
41122
+ `);
41123
+ context.emit("done");
41124
+ return { handled: true };
41125
+ }
41126
+ let output = `
41127
+ **Plan: ${plan.title}**
41128
+
41129
+ `;
41130
+ output += `ID: ${plan.id}
41131
+ `;
41132
+ if (plan.steps.length === 0) {
41133
+ output += `No steps yet.
41134
+ `;
41135
+ } else {
41136
+ for (const step of plan.steps) {
41137
+ output += `- ${step.id} [${step.status}] ${step.text}
41138
+ `;
41139
+ }
41140
+ }
41141
+ context.emit("text", output);
41142
+ context.emit("done");
41143
+ return { handled: true };
41144
+ }
41145
+ if (sub === "add") {
41146
+ const planId = parts[1];
41147
+ const text = parts.slice(2).join(" ").trim();
41148
+ if (!planId || !text) {
41149
+ context.emit("text", `Usage: /plans add <planId> <step>
41150
+ `);
41151
+ context.emit("done");
41152
+ return { handled: true };
41153
+ }
41154
+ if (!project.plans.some((plan) => plan.id === planId)) {
41155
+ context.emit("text", `Plan not found: ${planId}
41156
+ `);
41157
+ context.emit("done");
41158
+ return { handled: true };
41159
+ }
41160
+ const now2 = Date.now();
41161
+ const step = {
41162
+ id: generateId(),
41163
+ text,
41164
+ status: "todo",
41165
+ createdAt: now2,
41166
+ updatedAt: now2
41167
+ };
41168
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41169
+ ...current,
41170
+ plans: current.plans.map((plan) => plan.id === planId ? { ...plan, steps: [...plan.steps, step], updatedAt: now2 } : plan),
41171
+ updatedAt: now2
41172
+ }));
41173
+ if (updated) {
41174
+ await this.applyProjectContext(context, updated);
41175
+ context.emit("text", `Added step to plan ${planId}.
41176
+ `);
41177
+ context.emit("done");
41178
+ return { handled: true };
41179
+ }
41180
+ }
41181
+ if (sub === "set") {
41182
+ const planId = parts[1];
41183
+ const stepId = parts[2];
41184
+ const status = parts[3];
41185
+ if (!planId || !stepId || !status) {
41186
+ context.emit("text", `Usage: /plans set <planId> <stepId> <todo|doing|done|blocked>
41187
+ `);
41188
+ context.emit("done");
41189
+ return { handled: true };
41190
+ }
41191
+ const plan = project.plans.find((item) => item.id === planId);
41192
+ if (!plan) {
41193
+ context.emit("text", `Plan not found: ${planId}
41194
+ `);
41195
+ context.emit("done");
41196
+ return { handled: true };
41197
+ }
41198
+ if (!plan.steps.some((step) => step.id === stepId)) {
41199
+ context.emit("text", `Step not found: ${stepId}
41200
+ `);
41201
+ context.emit("done");
41202
+ return { handled: true };
41203
+ }
41204
+ const allowed = ["todo", "doing", "done", "blocked"];
41205
+ if (!allowed.includes(status)) {
41206
+ context.emit("text", `Invalid status. Use todo, doing, done, or blocked.
41207
+ `);
41208
+ context.emit("done");
41209
+ return { handled: true };
41210
+ }
41211
+ const now2 = Date.now();
41212
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41213
+ ...current,
41214
+ plans: current.plans.map((plan2) => plan2.id === planId ? {
41215
+ ...plan2,
41216
+ steps: plan2.steps.map((step) => step.id === stepId ? { ...step, status, updatedAt: now2 } : step),
41217
+ updatedAt: now2
41218
+ } : plan2),
41219
+ updatedAt: now2
41220
+ }));
41221
+ if (updated) {
41222
+ await this.applyProjectContext(context, updated);
41223
+ context.emit("text", `Updated step ${stepId} to ${status}.
41224
+ `);
41225
+ context.emit("done");
41226
+ return { handled: true };
41227
+ }
41228
+ }
41229
+ if (sub === "remove") {
41230
+ const planId = parts[1];
41231
+ const stepId = parts[2];
41232
+ if (!planId || !stepId) {
41233
+ context.emit("text", `Usage: /plans remove <planId> <stepId>
41234
+ `);
41235
+ context.emit("done");
41236
+ return { handled: true };
41237
+ }
41238
+ const plan = project.plans.find((item) => item.id === planId);
41239
+ if (!plan) {
41240
+ context.emit("text", `Plan not found: ${planId}
41241
+ `);
41242
+ context.emit("done");
41243
+ return { handled: true };
41244
+ }
41245
+ if (!plan.steps.some((step) => step.id === stepId)) {
41246
+ context.emit("text", `Step not found: ${stepId}
41247
+ `);
41248
+ context.emit("done");
41249
+ return { handled: true };
41250
+ }
41251
+ const now2 = Date.now();
41252
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41253
+ ...current,
41254
+ plans: current.plans.map((plan2) => plan2.id === planId ? { ...plan2, steps: plan2.steps.filter((step) => step.id !== stepId), updatedAt: now2 } : plan2),
41255
+ updatedAt: now2
41256
+ }));
41257
+ if (updated) {
41258
+ await this.applyProjectContext(context, updated);
41259
+ context.emit("text", `Removed step ${stepId} from plan ${planId}.
41260
+ `);
41261
+ context.emit("done");
41262
+ return { handled: true };
41263
+ }
41264
+ }
41265
+ if (sub === "delete" || sub === "rm") {
41266
+ const planId = parts[1];
41267
+ if (!planId) {
41268
+ context.emit("text", `Usage: /plans delete <planId>
41269
+ `);
41270
+ context.emit("done");
41271
+ return { handled: true };
41272
+ }
41273
+ if (!project.plans.some((plan) => plan.id === planId)) {
41274
+ context.emit("text", `Plan not found: ${planId}
41275
+ `);
41276
+ context.emit("done");
41277
+ return { handled: true };
41278
+ }
41279
+ const now2 = Date.now();
41280
+ const updated = await updateProject(context.cwd, project.id, (current) => ({
41281
+ ...current,
41282
+ plans: current.plans.filter((plan) => plan.id !== planId),
41283
+ updatedAt: now2
41284
+ }));
41285
+ if (updated) {
41286
+ await this.applyProjectContext(context, updated);
41287
+ context.emit("text", `Deleted plan ${planId}.
41288
+ `);
41289
+ context.emit("done");
41290
+ return { handled: true };
41291
+ }
41292
+ }
41293
+ context.emit("text", `Unknown /plans command. Use /plans help.
41294
+ `);
41295
+ context.emit("done");
41296
+ return { handled: true };
41297
+ }
41298
+ };
41299
+ }
41300
+ summarizeCommand() {
41301
+ return {
41302
+ name: "summarize",
41303
+ description: "Summarize and compress the current conversation",
41304
+ builtin: true,
41305
+ selfHandled: true,
41306
+ content: "",
41307
+ handler: async (args, context) => {
41308
+ if (!context.summarizeContext) {
41309
+ context.emit("text", `
41310
+ Context summarization is not available.
41311
+ `);
41312
+ context.emit("done");
41313
+ return { handled: true };
41314
+ }
41315
+ const result = await context.summarizeContext();
41316
+ if (!result.summarized) {
41317
+ context.emit("text", `
41318
+ Nothing to summarize right now.
41319
+ `);
41320
+ context.emit("done");
41321
+ return { handled: true };
41322
+ }
41323
+ let message = `
41324
+ **Context Summary Generated**
41325
+
41326
+ `;
41327
+ message += `Summarized ${result.summarizedCount} message(s).
41328
+ `;
41329
+ message += `Tokens: ${result.tokensBefore.toLocaleString()} -> ${result.tokensAfter.toLocaleString()}
41330
+
41331
+ `;
41332
+ if (result.summary) {
41333
+ message += `${result.summary}
41334
+ `;
41335
+ }
41336
+ context.emit("text", message);
41337
+ context.emit("done");
41338
+ return { handled: true };
41339
+ }
41340
+ };
41341
+ }
41342
+ restCommand() {
41343
+ return {
41344
+ name: "rest",
41345
+ description: "Recharge assistant energy",
41346
+ builtin: true,
41347
+ selfHandled: true,
41348
+ content: "",
41349
+ handler: async (args, context) => {
41350
+ if (!context.restEnergy) {
41351
+ context.emit("text", `
41352
+ Energy system is not available.
41353
+ `);
41354
+ context.emit("done");
41355
+ return { handled: true };
41356
+ }
41357
+ const parsed = parseInt(args.trim(), 10);
41358
+ const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
41359
+ context.restEnergy(amount);
41360
+ const state = context.getEnergyState?.();
41361
+ if (state) {
41362
+ const percent = Math.round(state.current / Math.max(1, state.max) * 100);
41363
+ context.emit("text", `
41364
+ Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
41365
+ `);
41366
+ } else {
41367
+ context.emit("text", `
41368
+ Energy restored.
41369
+ `);
41370
+ }
41371
+ context.emit("done");
41372
+ return { handled: true };
41373
+ }
41374
+ };
41375
+ }
41376
+ skillsCommand(loader) {
41377
+ return {
41378
+ name: "skills",
41379
+ description: "List available skills",
41380
+ builtin: true,
41381
+ selfHandled: true,
41382
+ content: "",
41383
+ handler: async (args, context) => {
41384
+ let message = `
41385
+ **Available Skills**
41386
+
41387
+ `;
41388
+ message += `Skills are invoked with $skill-name [arguments] or /skill-name [arguments]
41389
+
41390
+ `;
41391
+ if (context.skills.length === 0) {
41392
+ message += `No skills loaded.
41393
+ `;
41394
+ message += `
41395
+ Add skills to ~/.assistants/assistants-shared/skills/ or .assistants/skills/
40545
41396
  `;
40546
41397
  } else {
40547
41398
  for (const skill of context.skills) {
@@ -40562,7 +41413,7 @@ ${context.skills.length} skill(s) available.
40562
41413
  statusCommand() {
40563
41414
  return {
40564
41415
  name: "status",
40565
- description: "Show current session status and token usage",
41416
+ description: "Show current session status, energy, identity, and token usage",
40566
41417
  builtin: true,
40567
41418
  selfHandled: true,
40568
41419
  content: "",
@@ -40572,11 +41423,46 @@ ${context.skills.length} skill(s) available.
40572
41423
  let message = `
40573
41424
  **Session Status**
40574
41425
 
41426
+ `;
41427
+ message += `**Session ID:** ${context.sessionId}
40575
41428
  `;
40576
41429
  message += `**Working Directory:** ${context.cwd}
40577
41430
  `;
40578
- message += `**Session ID:** ${context.sessionId}
41431
+ const assistant = context.getAssistantManager?.()?.getActive();
41432
+ const identity = context.getIdentityManager?.()?.getActive();
41433
+ if (assistant) {
41434
+ message += `**Assistant:** ${assistant.name}`;
41435
+ if (identity) {
41436
+ message += ` \xB7 ${identity.name}`;
41437
+ }
41438
+ message += `
41439
+ `;
41440
+ }
41441
+ const energyState = context.getEnergyState?.();
41442
+ if (energyState) {
41443
+ const energyPercent = Math.round(energyState.current / Math.max(1, energyState.max) * 100);
41444
+ const energyBar = "\u2588".repeat(Math.round(energyPercent / 10)) + "\u2591".repeat(10 - Math.round(energyPercent / 10));
41445
+ const energyEmoji = energyPercent > 70 ? "\u26A1" : energyPercent > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
41446
+ message += `**Energy:** ${energyEmoji} [${energyBar}] ${energyPercent}% (${energyState.current}/${energyState.max})
41447
+ `;
41448
+ }
41449
+ const voiceState = context.getVoiceState?.();
41450
+ if (voiceState?.enabled) {
41451
+ const voiceActivity = voiceState.isSpeaking ? "speaking" : voiceState.isListening ? "listening" : "idle";
41452
+ message += `**Voice:** ${voiceActivity}`;
41453
+ if (voiceState.sttProvider || voiceState.ttsProvider) {
41454
+ message += ` (STT: ${voiceState.sttProvider || "n/a"}, TTS: ${voiceState.ttsProvider || "n/a"})`;
41455
+ }
41456
+ message += `
41457
+ `;
41458
+ }
41459
+ if (context.getActiveProjectId) {
41460
+ const projectId = context.getActiveProjectId();
41461
+ if (projectId) {
41462
+ message += `**Active Project:** ${projectId}
40579
41463
  `;
41464
+ }
41465
+ }
40580
41466
  message += `**Messages:** ${context.messages.length}
40581
41467
  `;
40582
41468
  message += `**Available Tools:** ${context.tools.length}
@@ -40663,9 +41549,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40663
41549
  content: "",
40664
41550
  handler: async (args, context) => {
40665
41551
  const configPaths = [
40666
- join10(context.cwd, ".assistants", "config.json"),
40667
- join10(context.cwd, ".assistants", "config.local.json"),
40668
- join10(getConfigDir(), "config.json")
41552
+ join11(context.cwd, ".assistants", "config.json"),
41553
+ join11(context.cwd, ".assistants", "config.local.json"),
41554
+ join11(getConfigDir(), "config.json")
40669
41555
  ];
40670
41556
  let message = `
40671
41557
  **Configuration**
@@ -40683,9 +41569,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40683
41569
  message += `
40684
41570
  **Commands Directories:**
40685
41571
  `;
40686
- message += ` - Project: ${join10(context.cwd, ".assistants", "commands")}
41572
+ message += ` - Project: ${join11(context.cwd, ".assistants", "commands")}
40687
41573
  `;
40688
- message += ` - Global: ${join10(homeDir, ".assistants", "commands")}
41574
+ message += ` - Global: ${join11(homeDir, ".assistants", "commands")}
40689
41575
  `;
40690
41576
  context.emit("text", message);
40691
41577
  context.emit("done");
@@ -40701,7 +41587,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40701
41587
  selfHandled: true,
40702
41588
  content: "",
40703
41589
  handler: async (args, context) => {
40704
- const commandsDir = join10(context.cwd, ".assistants", "commands");
41590
+ const commandsDir = join11(context.cwd, ".assistants", "commands");
40705
41591
  mkdirSync2(commandsDir, { recursive: true });
40706
41592
  const exampleCommand = `---
40707
41593
  name: reflect
@@ -40717,7 +41603,7 @@ Please summarize the last interaction and suggest 2-3 next steps.
40717
41603
  - Focus on clarity
40718
41604
  - Ask a follow-up question if needed
40719
41605
  `;
40720
- const examplePath = join10(commandsDir, "reflect.md");
41606
+ const examplePath = join11(commandsDir, "reflect.md");
40721
41607
  if (!existsSync6(examplePath)) {
40722
41608
  writeFileSync3(examplePath, exampleCommand);
40723
41609
  }
@@ -41038,8 +41924,8 @@ Connector "${connectorName}" not found.
41038
41924
  `;
41039
41925
  try {
41040
41926
  let timeoutId = null;
41041
- const timeoutPromise = new Promise((resolve4) => {
41042
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
41927
+ const timeoutPromise = new Promise((resolve5) => {
41928
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41043
41929
  });
41044
41930
  const result = await Promise.race([
41045
41931
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41101,8 +41987,8 @@ Connector "${connectorName}" not found.
41101
41987
  let status = "\u25CB";
41102
41988
  let timeoutId = null;
41103
41989
  try {
41104
- const timeoutPromise = new Promise((resolve4) => {
41105
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
41990
+ const timeoutPromise = new Promise((resolve5) => {
41991
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41106
41992
  });
41107
41993
  const result = await Promise.race([
41108
41994
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41377,6 +42263,35 @@ ${repoUrl}/issues/new
41377
42263
  }
41378
42264
  };
41379
42265
  }
42266
+ async resolveProject(context, target) {
42267
+ const byId = await readProject(context.cwd, target);
42268
+ if (byId)
42269
+ return byId;
42270
+ return findProjectByName(context.cwd, target);
42271
+ }
42272
+ async ensureActiveProject(context, createIfMissing) {
42273
+ const activeId = context.getActiveProjectId?.();
42274
+ if (activeId) {
42275
+ const project2 = await readProject(context.cwd, activeId);
42276
+ if (project2)
42277
+ return project2;
42278
+ }
42279
+ if (!createIfMissing)
42280
+ return null;
42281
+ const project = await ensureDefaultProject(context.cwd);
42282
+ context.setActiveProjectId?.(project.id);
42283
+ await this.applyProjectContext(context, project);
42284
+ return project;
42285
+ }
42286
+ async applyProjectContext(context, project) {
42287
+ if (!context.setProjectContext)
42288
+ return;
42289
+ const projectContext = await buildProjectContext(project, {
42290
+ cwd: context.cwd,
42291
+ connectors: context.connectors
42292
+ });
42293
+ context.setProjectContext(projectContext);
42294
+ }
41380
42295
  }
41381
42296
  // packages/core/src/llm/client.ts
41382
42297
  async function createLLMClient(config) {
@@ -41390,7 +42305,7 @@ async function createLLMClient(config) {
41390
42305
  // packages/core/src/heartbeat/manager.ts
41391
42306
  import { dirname as dirname5 } from "path";
41392
42307
  import { mkdirSync as mkdirSync3 } from "fs";
41393
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
42308
+ import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
41394
42309
 
41395
42310
  class HeartbeatManager {
41396
42311
  config;
@@ -41469,12 +42384,12 @@ class HeartbeatManager {
41469
42384
  }
41470
42385
  async persist(heartbeat) {
41471
42386
  try {
41472
- await writeFile2(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
42387
+ await writeFile3(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
41473
42388
  } catch {}
41474
42389
  }
41475
42390
  static async checkStale(path2, thresholdMs) {
41476
42391
  try {
41477
- const content = await readFile2(path2, "utf-8");
42392
+ const content = await readFile4(path2, "utf-8");
41478
42393
  const heartbeat = JSON.parse(content);
41479
42394
  const age = Date.now() - new Date(heartbeat.timestamp).getTime();
41480
42395
  return { isStale: age > thresholdMs, lastHeartbeat: heartbeat };
@@ -41486,7 +42401,7 @@ class HeartbeatManager {
41486
42401
  // packages/core/src/heartbeat/persistence.ts
41487
42402
  import { dirname as dirname6 } from "path";
41488
42403
  import { mkdirSync as mkdirSync4 } from "fs";
41489
- import { readFile as readFile3, writeFile as writeFile3, unlink as unlink2 } from "fs/promises";
42404
+ import { readFile as readFile5, writeFile as writeFile4, unlink as unlink3 } from "fs/promises";
41490
42405
 
41491
42406
  class StatePersistence {
41492
42407
  path;
@@ -41496,12 +42411,12 @@ class StatePersistence {
41496
42411
  }
41497
42412
  async save(state) {
41498
42413
  try {
41499
- await writeFile3(this.path, JSON.stringify(state, null, 2));
42414
+ await writeFile4(this.path, JSON.stringify(state, null, 2));
41500
42415
  } catch {}
41501
42416
  }
41502
42417
  async load() {
41503
42418
  try {
41504
- const content = await readFile3(this.path, "utf-8");
42419
+ const content = await readFile5(this.path, "utf-8");
41505
42420
  return JSON.parse(content);
41506
42421
  } catch {
41507
42422
  return null;
@@ -41509,7 +42424,7 @@ class StatePersistence {
41509
42424
  }
41510
42425
  async clear() {
41511
42426
  try {
41512
- await unlink2(this.path);
42427
+ await unlink3(this.path);
41513
42428
  } catch {}
41514
42429
  }
41515
42430
  }
@@ -41713,7 +42628,7 @@ class EnergyManager {
41713
42628
  // packages/core/src/energy/storage.ts
41714
42629
  import { dirname as dirname7 } from "path";
41715
42630
  import { mkdirSync as mkdirSync5 } from "fs";
41716
- import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
42631
+ import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
41717
42632
 
41718
42633
  class EnergyStorage {
41719
42634
  path;
@@ -41723,12 +42638,12 @@ class EnergyStorage {
41723
42638
  }
41724
42639
  async save(state) {
41725
42640
  try {
41726
- await writeFile4(this.path, JSON.stringify(state, null, 2));
42641
+ await writeFile5(this.path, JSON.stringify(state, null, 2));
41727
42642
  } catch {}
41728
42643
  }
41729
42644
  async load() {
41730
42645
  try {
41731
- const content = await readFile4(this.path, "utf-8");
42646
+ const content = await readFile6(this.path, "utf-8");
41732
42647
  return JSON.parse(content);
41733
42648
  } catch {
41734
42649
  return null;
@@ -41788,12 +42703,12 @@ function validateToolCalls(toolCalls, tools) {
41788
42703
  // packages/core/src/voice/utils.ts
41789
42704
  import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
41790
42705
  import { homedir as homedir9 } from "os";
41791
- import { join as join12 } from "path";
42706
+ import { join as join13 } from "path";
41792
42707
  import { spawnSync } from "child_process";
41793
42708
  function loadApiKeyFromSecrets2(key) {
41794
42709
  const envHome = process.env.HOME || process.env.USERPROFILE;
41795
42710
  const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
41796
- const secretsPath = join12(homeDir, ".secrets");
42711
+ const secretsPath = join13(homeDir, ".secrets");
41797
42712
  if (!existsSync8(secretsPath))
41798
42713
  return;
41799
42714
  try {
@@ -41867,7 +42782,7 @@ class SystemSTT {
41867
42782
  // packages/core/src/voice/tts.ts
41868
42783
  import { spawnSync as spawnSync2 } from "child_process";
41869
42784
  import { tmpdir as tmpdir2 } from "os";
41870
- import { join as join13 } from "path";
42785
+ import { join as join14 } from "path";
41871
42786
  import { readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
41872
42787
  class ElevenLabsTTS {
41873
42788
  apiKey;
@@ -41971,7 +42886,7 @@ class SystemTTS {
41971
42886
  if (!say) {
41972
42887
  throw new Error('System TTS not available: missing "say" command.');
41973
42888
  }
41974
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
42889
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
41975
42890
  const args = [];
41976
42891
  if (this.voiceId) {
41977
42892
  args.push("-v", this.voiceId);
@@ -41993,7 +42908,7 @@ class SystemTTS {
41993
42908
  }
41994
42909
  const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
41995
42910
  if (espeak) {
41996
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
42911
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
41997
42912
  const args = ["-w", output];
41998
42913
  if (this.voiceId) {
41999
42914
  args.push("-v", this.voiceId);
@@ -42020,32 +42935,32 @@ class SystemTTS {
42020
42935
  // packages/core/src/voice/player.ts
42021
42936
  import { spawn } from "child_process";
42022
42937
  import { tmpdir as tmpdir3 } from "os";
42023
- import { join as join14 } from "path";
42024
- import { unlink as unlink3, writeFileSync as writeFileSync4 } from "fs";
42938
+ import { join as join15 } from "path";
42939
+ import { unlink as unlink4, writeFileSync as writeFileSync4 } from "fs";
42025
42940
  class AudioPlayer {
42026
42941
  currentProcess = null;
42027
42942
  playing = false;
42028
42943
  async play(audio, options = {}) {
42029
42944
  const format = options.format ?? "mp3";
42030
- const tempFile = join14(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
42945
+ const tempFile = join15(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
42031
42946
  writeFileSync4(tempFile, Buffer.from(audio));
42032
42947
  const player = this.resolvePlayer(format);
42033
42948
  if (!player) {
42034
42949
  throw new Error("No supported audio player found. Install afplay, ffplay, mpg123, or aplay.");
42035
42950
  }
42036
- await new Promise((resolve4, reject) => {
42951
+ await new Promise((resolve5, reject) => {
42037
42952
  this.playing = true;
42038
42953
  this.currentProcess = spawn(player.command, [...player.args, tempFile], { stdio: "ignore" });
42039
42954
  this.currentProcess.on("close", () => {
42040
42955
  this.playing = false;
42041
42956
  this.currentProcess = null;
42042
- unlink3(tempFile, () => {});
42043
- resolve4();
42957
+ unlink4(tempFile, () => {});
42958
+ resolve5();
42044
42959
  });
42045
42960
  this.currentProcess.on("error", (error) => {
42046
42961
  this.playing = false;
42047
42962
  this.currentProcess = null;
42048
- unlink3(tempFile, () => {});
42963
+ unlink4(tempFile, () => {});
42049
42964
  reject(error);
42050
42965
  });
42051
42966
  });
@@ -42095,8 +43010,8 @@ class AudioPlayer {
42095
43010
  // packages/core/src/voice/recorder.ts
42096
43011
  import { spawn as spawn2 } from "child_process";
42097
43012
  import { tmpdir as tmpdir4 } from "os";
42098
- import { join as join15 } from "path";
42099
- import { readFileSync as readFileSync5, unlink as unlink4 } from "fs";
43013
+ import { join as join16 } from "path";
43014
+ import { readFileSync as readFileSync5, unlink as unlink5 } from "fs";
42100
43015
  class AudioRecorder {
42101
43016
  currentProcess = null;
42102
43017
  async record(options = {}) {
@@ -42106,17 +43021,17 @@ class AudioRecorder {
42106
43021
  const duration = options.durationSeconds ?? 5;
42107
43022
  const sampleRate = options.sampleRate ?? 16000;
42108
43023
  const channels = options.channels ?? 1;
42109
- const output = join15(tmpdir4(), `assistants-record-${Date.now()}.wav`);
43024
+ const output = join16(tmpdir4(), `assistants-record-${Date.now()}.wav`);
42110
43025
  const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
42111
43026
  if (!recorder) {
42112
43027
  throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
42113
43028
  }
42114
- await new Promise((resolve4, reject) => {
43029
+ await new Promise((resolve5, reject) => {
42115
43030
  this.currentProcess = spawn2(recorder.command, recorder.args, { stdio: "ignore" });
42116
43031
  this.currentProcess.on("close", (code) => {
42117
43032
  this.currentProcess = null;
42118
43033
  if (code === 0) {
42119
- resolve4();
43034
+ resolve5();
42120
43035
  } else {
42121
43036
  reject(new Error("Audio recording failed."));
42122
43037
  }
@@ -42127,7 +43042,7 @@ class AudioRecorder {
42127
43042
  });
42128
43043
  });
42129
43044
  const data = readFileSync5(output);
42130
- unlink4(output, () => {});
43045
+ unlink5(output, () => {});
42131
43046
  return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
42132
43047
  }
42133
43048
  stop() {
@@ -42299,14 +43214,14 @@ class VoiceManager {
42299
43214
  // packages/core/src/identity/assistant-manager.ts
42300
43215
  init_src();
42301
43216
  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";
43217
+ import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile7, rm as rm2 } from "fs/promises";
43218
+ import { join as join18 } from "path";
42304
43219
 
42305
43220
  // packages/core/src/identity/identity-manager.ts
42306
43221
  init_src();
42307
43222
  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";
43223
+ import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile6, rm } from "fs/promises";
43224
+ import { join as join17 } from "path";
42310
43225
  var DEFAULT_PROFILE = {
42311
43226
  displayName: "Assistant",
42312
43227
  timezone: "UTC",
@@ -42336,22 +43251,22 @@ class IdentityManager {
42336
43251
  this.basePath = basePath;
42337
43252
  }
42338
43253
  get identitiesRoot() {
42339
- return join16(this.basePath, "assistants", this.assistantId, "identities");
43254
+ return join17(this.basePath, "assistants", this.assistantId, "identities");
42340
43255
  }
42341
43256
  get indexPath() {
42342
- return join16(this.identitiesRoot, "index.json");
43257
+ return join17(this.identitiesRoot, "index.json");
42343
43258
  }
42344
43259
  get activePath() {
42345
- return join16(this.identitiesRoot, "active.json");
43260
+ return join17(this.identitiesRoot, "active.json");
42346
43261
  }
42347
43262
  identityPath(id) {
42348
- return join16(this.identitiesRoot, `${id}.json`);
43263
+ return join17(this.identitiesRoot, `${id}.json`);
42349
43264
  }
42350
43265
  assistantConfigPath() {
42351
- return join16(this.basePath, "assistants", this.assistantId, "config.json");
43266
+ return join17(this.basePath, "assistants", this.assistantId, "config.json");
42352
43267
  }
42353
43268
  async initialize() {
42354
- await mkdir3(this.identitiesRoot, { recursive: true });
43269
+ await mkdir4(this.identitiesRoot, { recursive: true });
42355
43270
  const index = await this.readIndex();
42356
43271
  for (const id of index.identities) {
42357
43272
  const identity = await this.readIdentity(id);
@@ -42458,7 +43373,7 @@ class IdentityManager {
42458
43373
  return { identities: [] };
42459
43374
  }
42460
43375
  try {
42461
- const raw = await readFile5(this.indexPath, "utf-8");
43376
+ const raw = await readFile7(this.indexPath, "utf-8");
42462
43377
  const data = JSON.parse(raw);
42463
43378
  return { identities: Array.isArray(data.identities) ? data.identities : [] };
42464
43379
  } catch {
@@ -42470,33 +43385,33 @@ class IdentityManager {
42470
43385
  if (!index.identities.includes(id)) {
42471
43386
  index.identities.push(id);
42472
43387
  }
42473
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43388
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42474
43389
  }
42475
43390
  async removeFromIndex(id) {
42476
43391
  const index = await this.readIndex();
42477
43392
  index.identities = index.identities.filter((identityId) => identityId !== id);
42478
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43393
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42479
43394
  }
42480
43395
  async readIdentity(id) {
42481
43396
  const path2 = this.identityPath(id);
42482
43397
  if (!existsSync9(path2))
42483
43398
  return null;
42484
43399
  try {
42485
- const raw = await readFile5(path2, "utf-8");
43400
+ const raw = await readFile7(path2, "utf-8");
42486
43401
  return JSON.parse(raw);
42487
43402
  } catch {
42488
43403
  return null;
42489
43404
  }
42490
43405
  }
42491
43406
  async persistIdentity(identity) {
42492
- await mkdir3(this.identitiesRoot, { recursive: true });
42493
- await writeFile5(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
43407
+ await mkdir4(this.identitiesRoot, { recursive: true });
43408
+ await writeFile6(this.identityPath(identity.id), JSON.stringify(identity, null, 2));
42494
43409
  }
42495
43410
  async readActive() {
42496
43411
  if (!existsSync9(this.activePath))
42497
43412
  return null;
42498
43413
  try {
42499
- const raw = await readFile5(this.activePath, "utf-8");
43414
+ const raw = await readFile7(this.activePath, "utf-8");
42500
43415
  const data = JSON.parse(raw);
42501
43416
  return data.id || null;
42502
43417
  } catch {
@@ -42505,13 +43420,13 @@ class IdentityManager {
42505
43420
  }
42506
43421
  async setActive(id) {
42507
43422
  this.activeId = id;
42508
- await writeFile5(this.activePath, JSON.stringify({ id }, null, 2));
43423
+ await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
42509
43424
  }
42510
43425
  async loadAssistant() {
42511
43426
  if (!existsSync9(this.assistantConfigPath()))
42512
43427
  return null;
42513
43428
  try {
42514
- const raw = await readFile5(this.assistantConfigPath(), "utf-8");
43429
+ const raw = await readFile7(this.assistantConfigPath(), "utf-8");
42515
43430
  return JSON.parse(raw);
42516
43431
  } catch {
42517
43432
  return null;
@@ -42532,19 +43447,19 @@ class AssistantManager {
42532
43447
  this.basePath = basePath;
42533
43448
  }
42534
43449
  get assistantsRoot() {
42535
- return join17(this.basePath, "assistants");
43450
+ return join18(this.basePath, "assistants");
42536
43451
  }
42537
43452
  get indexPath() {
42538
- return join17(this.assistantsRoot, "index.json");
43453
+ return join18(this.assistantsRoot, "index.json");
42539
43454
  }
42540
43455
  get activePath() {
42541
- return join17(this.basePath, "active.json");
43456
+ return join18(this.basePath, "active.json");
42542
43457
  }
42543
43458
  assistantConfigPath(id) {
42544
- return join17(this.assistantsRoot, id, "config.json");
43459
+ return join18(this.assistantsRoot, id, "config.json");
42545
43460
  }
42546
43461
  async initialize() {
42547
- await mkdir4(this.assistantsRoot, { recursive: true });
43462
+ await mkdir5(this.assistantsRoot, { recursive: true });
42548
43463
  const index = await this.readIndex();
42549
43464
  for (const id of index.assistants) {
42550
43465
  const assistant = await this.readAssistant(id);
@@ -42595,7 +43510,7 @@ class AssistantManager {
42595
43510
  if (!this.assistants.has(id)) {
42596
43511
  throw new Error(`Assistant ${id} not found`);
42597
43512
  }
42598
- await rm2(join17(this.assistantsRoot, id), { recursive: true, force: true });
43513
+ await rm2(join18(this.assistantsRoot, id), { recursive: true, force: true });
42599
43514
  this.assistants.delete(id);
42600
43515
  await this.removeFromIndex(id);
42601
43516
  if (this.activeId === id) {
@@ -42630,7 +43545,7 @@ class AssistantManager {
42630
43545
  return { assistants: [] };
42631
43546
  }
42632
43547
  try {
42633
- const raw = await readFile6(this.indexPath, "utf-8");
43548
+ const raw = await readFile8(this.indexPath, "utf-8");
42634
43549
  const data = JSON.parse(raw);
42635
43550
  return { assistants: Array.isArray(data.assistants) ? data.assistants : [] };
42636
43551
  } catch {
@@ -42642,34 +43557,34 @@ class AssistantManager {
42642
43557
  if (!index.assistants.includes(id)) {
42643
43558
  index.assistants.push(id);
42644
43559
  }
42645
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43560
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42646
43561
  }
42647
43562
  async removeFromIndex(id) {
42648
43563
  const index = await this.readIndex();
42649
43564
  index.assistants = index.assistants.filter((assistantId) => assistantId !== id);
42650
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43565
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42651
43566
  }
42652
43567
  async readAssistant(id) {
42653
43568
  const configPath = this.assistantConfigPath(id);
42654
43569
  if (!existsSync10(configPath))
42655
43570
  return null;
42656
43571
  try {
42657
- const raw = await readFile6(configPath, "utf-8");
43572
+ const raw = await readFile8(configPath, "utf-8");
42658
43573
  return JSON.parse(raw);
42659
43574
  } catch {
42660
43575
  return null;
42661
43576
  }
42662
43577
  }
42663
43578
  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));
43579
+ const dir = join18(this.assistantsRoot, assistant.id);
43580
+ await mkdir5(dir, { recursive: true });
43581
+ await writeFile7(this.assistantConfigPath(assistant.id), JSON.stringify(assistant, null, 2));
42667
43582
  }
42668
43583
  async readActive() {
42669
43584
  if (!existsSync10(this.activePath))
42670
43585
  return null;
42671
43586
  try {
42672
- const raw = await readFile6(this.activePath, "utf-8");
43587
+ const raw = await readFile8(this.activePath, "utf-8");
42673
43588
  const data = JSON.parse(raw);
42674
43589
  return data.id || null;
42675
43590
  } catch {
@@ -42678,7 +43593,7 @@ class AssistantManager {
42678
43593
  }
42679
43594
  async setActive(id) {
42680
43595
  this.activeId = id;
42681
- await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
43596
+ await writeFile7(this.activePath, JSON.stringify({ id }, null, 2));
42682
43597
  }
42683
43598
  }
42684
43599
  // packages/core/src/agent/loop.ts
@@ -42723,6 +43638,8 @@ class AgentLoop {
42723
43638
  assistantManager = null;
42724
43639
  identityManager = null;
42725
43640
  identityContext = null;
43641
+ projectContext = null;
43642
+ activeProjectId = null;
42726
43643
  assistantId = null;
42727
43644
  onChunk;
42728
43645
  onToolStart;
@@ -42735,7 +43652,7 @@ class AgentLoop {
42735
43652
  this.context = new AgentContext;
42736
43653
  this.toolRegistry = new ToolRegistry;
42737
43654
  this.toolRegistry.setErrorAggregator(this.errorAggregator);
42738
- this.connectorBridge = new ConnectorBridge;
43655
+ this.connectorBridge = new ConnectorBridge(this.cwd);
42739
43656
  this.skillLoader = new SkillLoader;
42740
43657
  this.skillExecutor = new SkillExecutor;
42741
43658
  this.hookLoader = new HookLoader;
@@ -43038,15 +43955,13 @@ class AgentLoop {
43038
43955
  });
43039
43956
  if (preHookResult?.updatedInput) {
43040
43957
  toolCall.input = { ...preHookResult.updatedInput };
43041
- if (toolCall.input.cwd === undefined) {
43042
- toolCall.input.cwd = this.cwd;
43043
- }
43044
43958
  }
43045
- if (toolCall.name === "schedule") {
43046
- const input = toolCall.input;
43047
- if (input.sessionId === undefined) {
43048
- input.sessionId = this.sessionId;
43049
- }
43959
+ const input = toolCall.input;
43960
+ if (input.cwd === undefined) {
43961
+ input.cwd = this.cwd;
43962
+ }
43963
+ if (input.sessionId === undefined) {
43964
+ input.sessionId = this.sessionId;
43050
43965
  }
43051
43966
  if (preHookResult?.continue === false || preHookResult?.permissionDecision === "deny") {
43052
43967
  const blockedResult = {
@@ -43170,6 +44085,13 @@ class AgentLoop {
43170
44085
  switchIdentity: async (identityId) => {
43171
44086
  await this.switchIdentity(identityId);
43172
44087
  },
44088
+ getActiveProjectId: () => this.activeProjectId,
44089
+ setActiveProjectId: (projectId) => {
44090
+ this.activeProjectId = projectId;
44091
+ },
44092
+ setProjectContext: (content) => {
44093
+ this.setProjectContext(content);
44094
+ },
43173
44095
  getVoiceState: () => this.getVoiceState(),
43174
44096
  enableVoice: () => {
43175
44097
  if (!this.voiceManager) {
@@ -43357,6 +44279,22 @@ class AgentLoop {
43357
44279
  getSessionId() {
43358
44280
  return this.sessionId;
43359
44281
  }
44282
+ getActiveProjectId() {
44283
+ return this.activeProjectId;
44284
+ }
44285
+ setActiveProjectId(projectId) {
44286
+ this.activeProjectId = projectId;
44287
+ }
44288
+ setProjectContext(content) {
44289
+ const tag = "[Project Context]";
44290
+ this.projectContext = content;
44291
+ this.context.removeSystemMessages((message) => message.startsWith(tag));
44292
+ if (content && content.trim()) {
44293
+ this.context.addSystemMessage(`${tag}
44294
+ ${content.trim()}`);
44295
+ }
44296
+ this.contextManager?.refreshState(this.context.getMessages());
44297
+ }
43360
44298
  clearConversation() {
43361
44299
  this.resetContext();
43362
44300
  }
@@ -43368,7 +44306,7 @@ class AgentLoop {
43368
44306
  const heartbeatConfig = this.buildHeartbeatConfig(this.config);
43369
44307
  if (!heartbeatConfig)
43370
44308
  return;
43371
- const statePath = join18(getConfigDir(), "state", `${this.sessionId}.json`);
44309
+ const statePath = join19(getConfigDir(), "state", `${this.sessionId}.json`);
43372
44310
  this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
43373
44311
  this.heartbeatPersistence = new StatePersistence(statePath);
43374
44312
  this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
@@ -43417,7 +44355,7 @@ class AgentLoop {
43417
44355
  async startEnergySystem() {
43418
44356
  if (!this.config || this.config.energy?.enabled === false)
43419
44357
  return;
43420
- const statePath = join18(getConfigDir(), "energy", "state.json");
44358
+ const statePath = join19(getConfigDir(), "energy", "state.json");
43421
44359
  this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
43422
44360
  await this.energyManager.initialize();
43423
44361
  this.refreshEnergyEffects();
@@ -43446,7 +44384,7 @@ ${effects.message}
43446
44384
  const delay = this.energyEffects?.processingDelayMs ?? 0;
43447
44385
  if (delay <= 0)
43448
44386
  return;
43449
- await new Promise((resolve4) => setTimeout(resolve4, delay));
44387
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
43450
44388
  }
43451
44389
  applyEnergyPersonality(systemPrompt) {
43452
44390
  if (!systemPrompt)
@@ -43557,6 +44495,9 @@ ${effects.message}
43557
44495
  if (this.extraSystemPrompt) {
43558
44496
  this.context.addSystemMessage(this.extraSystemPrompt);
43559
44497
  }
44498
+ if (this.projectContext) {
44499
+ this.setProjectContext(this.projectContext);
44500
+ }
43560
44501
  this.contextManager?.refreshState(this.context.getMessages());
43561
44502
  }
43562
44503
  buildSystemPrompt(messages) {
@@ -43643,7 +44584,7 @@ ${this.identityContext}`);
43643
44584
  return null;
43644
44585
  const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
43645
44586
  const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
43646
- const persistPath = config.heartbeat?.persistPath ?? join18(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
44587
+ const persistPath = config.heartbeat?.persistPath ?? join19(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
43647
44588
  return {
43648
44589
  intervalMs,
43649
44590
  staleThresholdMs,
@@ -43735,17 +44676,17 @@ function parseErrorCode(message) {
43735
44676
  init_src();
43736
44677
  // packages/core/src/migration/migrate-to-assistants.ts
43737
44678
  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";
44679
+ import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile8, rename, cp } from "fs/promises";
44680
+ import { join as join20 } from "path";
43740
44681
  import { homedir as homedir10 } from "os";
43741
44682
  var MIGRATION_MARKER = ".migrated-from-oldpal";
43742
44683
  async function ensureDir(path2) {
43743
- await mkdir5(path2, { recursive: true });
44684
+ await mkdir6(path2, { recursive: true });
43744
44685
  }
43745
44686
  async function copyIfExists(source, destination) {
43746
44687
  if (!existsSync11(source))
43747
44688
  return false;
43748
- await ensureDir(join19(destination, ".."));
44689
+ await ensureDir(join20(destination, ".."));
43749
44690
  await cp(source, destination, { recursive: true });
43750
44691
  return true;
43751
44692
  }
@@ -43753,7 +44694,7 @@ async function readJson(path2) {
43753
44694
  if (!existsSync11(path2))
43754
44695
  return null;
43755
44696
  try {
43756
- const raw = await readFile7(path2, "utf-8");
44697
+ const raw = await readFile9(path2, "utf-8");
43757
44698
  return JSON.parse(raw);
43758
44699
  } catch {
43759
44700
  return null;
@@ -43766,14 +44707,14 @@ async function migrateFromOldpal() {
43766
44707
  errors: []
43767
44708
  };
43768
44709
  const home = homedir10();
43769
- const oldPath = join19(home, ".oldpal");
43770
- const newPath = join19(home, ".assistants");
44710
+ const oldPath = join20(home, ".oldpal");
44711
+ const newPath = join20(home, ".assistants");
43771
44712
  if (!existsSync11(oldPath)) {
43772
44713
  result.success = true;
43773
44714
  return result;
43774
44715
  }
43775
44716
  if (existsSync11(newPath)) {
43776
- const marker = join19(newPath, "migration", MIGRATION_MARKER);
44717
+ const marker = join20(newPath, "migration", MIGRATION_MARKER);
43777
44718
  if (existsSync11(marker)) {
43778
44719
  result.success = true;
43779
44720
  return result;
@@ -43783,31 +44724,31 @@ async function migrateFromOldpal() {
43783
44724
  }
43784
44725
  try {
43785
44726
  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"));
44727
+ await ensureDir(join20(newPath, "assistants"));
44728
+ await ensureDir(join20(newPath, "shared", "skills"));
44729
+ await ensureDir(join20(newPath, "logs"));
44730
+ await ensureDir(join20(newPath, "migration"));
44731
+ const config = await readJson(join20(oldPath, "settings.json"));
43791
44732
  if (config) {
43792
- await writeFile7(join19(newPath, "config.json"), JSON.stringify(config, null, 2));
44733
+ await writeFile8(join20(newPath, "config.json"), JSON.stringify(config, null, 2));
43793
44734
  result.migrated.push("config.json");
43794
44735
  }
43795
- if (await copyIfExists(join19(oldPath, "settings.local.json"), join19(newPath, "config.local.json"))) {
44736
+ if (await copyIfExists(join20(oldPath, "settings.local.json"), join20(newPath, "config.local.json"))) {
43796
44737
  result.migrated.push("config.local.json");
43797
44738
  }
43798
- if (await copyIfExists(join19(oldPath, "hooks.json"), join19(newPath, "hooks.json"))) {
44739
+ if (await copyIfExists(join20(oldPath, "hooks.json"), join20(newPath, "hooks.json"))) {
43799
44740
  result.migrated.push("hooks.json");
43800
44741
  }
43801
- if (await copyIfExists(join19(oldPath, "commands"), join19(newPath, "commands"))) {
44742
+ if (await copyIfExists(join20(oldPath, "commands"), join20(newPath, "commands"))) {
43802
44743
  result.migrated.push("commands");
43803
44744
  }
43804
- if (await copyIfExists(join19(oldPath, "OLDPAL.md"), join19(newPath, "ASSISTANTS.md"))) {
44745
+ if (await copyIfExists(join20(oldPath, "OLDPAL.md"), join20(newPath, "ASSISTANTS.md"))) {
43805
44746
  result.migrated.push("ASSISTANTS.md");
43806
44747
  }
43807
- if (await copyIfExists(join19(oldPath, "skills"), join19(newPath, "shared", "skills"))) {
44748
+ if (await copyIfExists(join20(oldPath, "skills"), join20(newPath, "shared", "skills"))) {
43808
44749
  result.migrated.push("skills");
43809
44750
  }
43810
- if (await copyIfExists(join19(oldPath, "logs"), join19(newPath, "logs"))) {
44751
+ if (await copyIfExists(join20(oldPath, "logs"), join20(newPath, "logs"))) {
43811
44752
  result.migrated.push("logs");
43812
44753
  }
43813
44754
  const manager = new AssistantManager(newPath);
@@ -43822,10 +44763,10 @@ async function migrateFromOldpal() {
43822
44763
  const identityManager = manager.getIdentityManager(assistant.id);
43823
44764
  await identityManager.initialize();
43824
44765
  await identityManager.createIdentity({ name: "Default" });
43825
- if (await copyIfExists(join19(oldPath, "sessions"), join19(newPath, "assistants", assistant.id, "sessions"))) {
44766
+ if (await copyIfExists(join20(oldPath, "sessions"), join20(newPath, "assistants", assistant.id, "sessions"))) {
43826
44767
  result.migrated.push("sessions");
43827
44768
  }
43828
- await writeFile7(join19(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
44769
+ await writeFile8(join20(newPath, "migration", MIGRATION_MARKER), JSON.stringify({ migratedAt: new Date().toISOString() }, null, 2));
43829
44770
  const backupPath = `${oldPath}.backup`;
43830
44771
  await rename(oldPath, backupPath);
43831
44772
  result.backupPath = backupPath;
@@ -43843,17 +44784,17 @@ init_src();
43843
44784
 
43844
44785
  // packages/core/src/logger.ts
43845
44786
  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";
44787
+ import { join as join21 } from "path";
43847
44788
  class Logger {
43848
44789
  logDir;
43849
44790
  logFile;
43850
44791
  sessionId;
43851
44792
  constructor(sessionId, basePath) {
43852
44793
  this.sessionId = sessionId;
43853
- this.logDir = join20(basePath || getConfigDir(), "logs");
44794
+ this.logDir = join21(basePath || getConfigDir(), "logs");
43854
44795
  this.ensureDir(this.logDir);
43855
44796
  const date = new Date().toISOString().split("T")[0];
43856
- this.logFile = join20(this.logDir, `${date}.log`);
44797
+ this.logFile = join21(this.logDir, `${date}.log`);
43857
44798
  }
43858
44799
  ensureDir(dir) {
43859
44800
  if (!existsSync12(dir)) {
@@ -43897,9 +44838,9 @@ class SessionStorage {
43897
44838
  constructor(sessionId, basePath, assistantId) {
43898
44839
  this.sessionId = sessionId;
43899
44840
  const root = basePath || getConfigDir();
43900
- this.sessionsDir = assistantId ? join20(root, "assistants", assistantId, "sessions") : join20(root, "sessions");
44841
+ this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
43901
44842
  this.ensureDir(this.sessionsDir);
43902
- this.sessionFile = join20(this.sessionsDir, `${sessionId}.json`);
44843
+ this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
43903
44844
  }
43904
44845
  ensureDir(dir) {
43905
44846
  if (!existsSync12(dir)) {
@@ -43925,7 +44866,7 @@ class SessionStorage {
43925
44866
  }
43926
44867
  static getActiveAssistantId() {
43927
44868
  try {
43928
- const activePath = join20(getConfigDir(), "active.json");
44869
+ const activePath = join21(getConfigDir(), "active.json");
43929
44870
  if (!existsSync12(activePath))
43930
44871
  return null;
43931
44872
  const raw = readFileSync6(activePath, "utf-8");
@@ -43939,12 +44880,12 @@ class SessionStorage {
43939
44880
  const root = getConfigDir();
43940
44881
  const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
43941
44882
  if (resolvedId) {
43942
- const assistantDir = join20(root, "assistants", resolvedId, "sessions");
44883
+ const assistantDir = join21(root, "assistants", resolvedId, "sessions");
43943
44884
  if (existsSync12(assistantDir)) {
43944
44885
  return assistantDir;
43945
44886
  }
43946
44887
  }
43947
- return join20(root, "sessions");
44888
+ return join21(root, "sessions");
43948
44889
  }
43949
44890
  static listSessions(assistantId) {
43950
44891
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
@@ -43956,7 +44897,7 @@ class SessionStorage {
43956
44897
  if (!file.endsWith(".json"))
43957
44898
  continue;
43958
44899
  try {
43959
- const filePath = join20(sessionsDir, file);
44900
+ const filePath = join21(sessionsDir, file);
43960
44901
  const stat = Bun.file(filePath);
43961
44902
  const content = JSON.parse(readFileSync6(filePath, "utf-8"));
43962
44903
  sessions.push({
@@ -43976,7 +44917,7 @@ class SessionStorage {
43976
44917
  }
43977
44918
  static loadSession(sessionId, assistantId) {
43978
44919
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43979
- const sessionFile = join20(sessionsDir, `${sessionId}.json`);
44920
+ const sessionFile = join21(sessionsDir, `${sessionId}.json`);
43980
44921
  try {
43981
44922
  if (!existsSync12(sessionFile))
43982
44923
  return null;
@@ -43990,15 +44931,15 @@ function initAssistantsDir() {
43990
44931
  const baseDir = getConfigDir();
43991
44932
  const dirs = [
43992
44933
  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")
44934
+ join21(baseDir, "logs"),
44935
+ join21(baseDir, "assistants"),
44936
+ join21(baseDir, "shared", "skills"),
44937
+ join21(baseDir, "commands"),
44938
+ join21(baseDir, "temp"),
44939
+ join21(baseDir, "heartbeats"),
44940
+ join21(baseDir, "state"),
44941
+ join21(baseDir, "energy"),
44942
+ join21(baseDir, "migration")
44002
44943
  ];
44003
44944
  for (const dir of dirs) {
44004
44945
  if (!existsSync12(dir)) {
@@ -44041,6 +44982,11 @@ class EmbeddedClient {
44041
44982
  for (const callback of this.chunkCallbacks) {
44042
44983
  callback(chunk);
44043
44984
  }
44985
+ if (chunk.type === "done" || chunk.type === "error") {
44986
+ queueMicrotask(() => {
44987
+ this.drainQueue();
44988
+ });
44989
+ }
44044
44990
  },
44045
44991
  onToolStart: (toolCall) => {
44046
44992
  this.logger.info("Tool started", { tool: toolCall.name, input: toolCall.input });
@@ -44083,12 +45029,11 @@ class EmbeddedClient {
44083
45029
  if (!this.initialized) {
44084
45030
  await this.initialize();
44085
45031
  }
44086
- if (this.agent.isProcessing()) {
44087
- this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length + 1 });
44088
- this.messageQueue.push(message);
45032
+ this.messageQueue.push(message);
45033
+ if (this.agent.isProcessing() || this.processingQueue) {
45034
+ this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length });
44089
45035
  return;
44090
45036
  }
44091
- await this.processMessage(message);
44092
45037
  await this.drainQueue();
44093
45038
  }
44094
45039
  async processMessage(message) {
@@ -44479,10 +45424,13 @@ var COMMANDS = [
44479
45424
  { name: "/model", description: "show model information" },
44480
45425
  { name: "/skills", description: "list available skills" },
44481
45426
  { name: "/config", description: "show configuration" },
45427
+ { name: "/projects", description: "manage projects in this folder" },
45428
+ { name: "/plans", description: "manage project plans" },
44482
45429
  { name: "/connectors", description: "list available connectors" },
44483
45430
  { name: "/init", description: "initialize assistants in project" },
44484
45431
  { name: "/compact", description: "summarize to save context" },
44485
45432
  { name: "/memory", description: "show what AI remembers" },
45433
+ { name: "/context", description: "manage injected project context" },
44486
45434
  { name: "/feedback", description: "submit feedback on GitHub" },
44487
45435
  { name: "/schedule", description: "schedule a command" },
44488
45436
  { name: "/schedules", description: "list scheduled commands" },
@@ -44578,14 +45526,14 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44578
45526
  if (autocompleteMode === "command" && filteredCommands.length > 0 && !submittedValue.includes(" ")) {
44579
45527
  const selected = filteredCommands[selectedIndex] || filteredCommands[0];
44580
45528
  if (selected) {
44581
- onSubmit(selected.name, isProcessing ? "interrupt" : "normal");
45529
+ onSubmit(selected.name, isProcessing ? "inline" : "normal");
44582
45530
  setValue("");
44583
45531
  setSelectedIndex(0);
44584
45532
  return;
44585
45533
  }
44586
45534
  }
44587
45535
  if (isProcessing) {
44588
- onSubmit(submittedValue, "interrupt");
45536
+ onSubmit(submittedValue, "inline");
44589
45537
  } else {
44590
45538
  onSubmit(submittedValue, "normal");
44591
45539
  }
@@ -44596,7 +45544,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44596
45544
  let placeholder = "Type a message...";
44597
45545
  if (isProcessing) {
44598
45546
  prompt = "\u22EF";
44599
- placeholder = queueLength > 0 ? "Type to interrupt (Enter) or queue (Tab)..." : "Type to interrupt (Enter) or queue (Tab)...";
45547
+ 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
45548
  }
44601
45549
  const truncateDescription = (desc, maxLen = 60) => {
44602
45550
  if (desc.length <= maxLen)
@@ -44737,7 +45685,12 @@ var import_react24 = __toESM(require_react(), 1);
44737
45685
 
44738
45686
  // packages/terminal/src/components/Markdown.tsx
44739
45687
  var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
44740
- function Markdown({ content }) {
45688
+ function Markdown({ content, preRendered = false }) {
45689
+ if (preRendered) {
45690
+ return /* @__PURE__ */ jsx_dev_runtime2.jsxDEV(Text, {
45691
+ children: content
45692
+ }, undefined, false, undefined, this);
45693
+ }
44741
45694
  const { columns } = use_stdout_default();
44742
45695
  const maxWidth = columns ? Math.max(20, columns - 2) : undefined;
44743
45696
  const rendered = parseMarkdown(content, { maxWidth });
@@ -44745,6 +45698,9 @@ function Markdown({ content }) {
44745
45698
  children: rendered
44746
45699
  }, undefined, false, undefined, this);
44747
45700
  }
45701
+ function renderMarkdown(text, options) {
45702
+ return parseMarkdown(text, { maxWidth: options?.maxWidth });
45703
+ }
44748
45704
  function parseMarkdown(text, options) {
44749
45705
  let result = text;
44750
45706
  const codeBlocks = [];
@@ -44770,7 +45726,7 @@ function parseMarkdown(text, options) {
44770
45726
  result = result.replace(/\b(Building|Running|Working|Queued|Pending|Connecting)\b/gi, (match) => source_default.yellow(match));
44771
45727
  result = result.replace(/\b(Success|Succeeded|Done|Complete|Completed|Connected|Authenticated)\b/gi, (match) => source_default.green(match));
44772
45728
  result = result.replace(/\b(Error|Failed|Failure|Denied|Blocked)\b/gi, (match) => source_default.red(match));
44773
- result = formatMarkdownTables(result);
45729
+ result = formatMarkdownTables(result, options?.maxWidth);
44774
45730
  result = result.replace(/@@BLOCKSECTION(\d+)@@/g, (_, index) => {
44775
45731
  const section = blockSections[parseInt(index, 10)];
44776
45732
  if (!section)
@@ -44784,6 +45740,7 @@ function parseMarkdown(text, options) {
44784
45740
  });
44785
45741
  return result.trimEnd();
44786
45742
  }
45743
+ var ALLOWED_BLOCK_TYPES = new Set(["info", "success", "warning", "error", "note", "command"]);
44787
45744
  function extractBlockSections(text, blocks) {
44788
45745
  const lines = text.split(`
44789
45746
  `);
@@ -44812,6 +45769,9 @@ function extractBlockSections(text, blocks) {
44812
45769
  i += 1;
44813
45770
  continue;
44814
45771
  }
45772
+ if (parsed.warning) {
45773
+ output.push(createMalformedBlock(blocks, indent, "grid", parsed.warning));
45774
+ }
44815
45775
  const bodyLines = stripIndent(parsed.bodyLines, indent);
44816
45776
  const body = bodyLines.join(`
44817
45777
  `);
@@ -44825,7 +45785,7 @@ function extractBlockSections(text, blocks) {
44825
45785
  const indent = blockMatch[1] ?? "";
44826
45786
  const header = blockMatch[2] ?? "";
44827
45787
  const attrs = parseAttributes(header);
44828
- const type = String(attrs.type || "info");
45788
+ let type = String(attrs.type || "info");
44829
45789
  const title = attrs.title ? String(attrs.title) : undefined;
44830
45790
  const parsed = parseDelimitedBlock(lines, i, indent);
44831
45791
  if (!parsed) {
@@ -44834,6 +45794,14 @@ function extractBlockSections(text, blocks) {
44834
45794
  i += 1;
44835
45795
  continue;
44836
45796
  }
45797
+ const normalizedType = type.toLowerCase();
45798
+ if (!ALLOWED_BLOCK_TYPES.has(normalizedType)) {
45799
+ output.push(createMalformedBlock(blocks, indent, "block", `Unknown block type "${type}". Using info.`));
45800
+ type = "info";
45801
+ }
45802
+ if (parsed.warning) {
45803
+ output.push(createMalformedBlock(blocks, indent, "block", parsed.warning));
45804
+ }
44837
45805
  const body = stripIndent(parsed.bodyLines, indent).join(`
44838
45806
  `);
44839
45807
  blocks.push({ kind: "block", type, title, body, indent });
@@ -44850,6 +45818,9 @@ function extractBlockSections(text, blocks) {
44850
45818
  i += 1;
44851
45819
  continue;
44852
45820
  }
45821
+ if (parsed.warning) {
45822
+ output.push(createMalformedBlock(blocks, indent, "report", parsed.warning));
45823
+ }
44853
45824
  const body = stripIndent(parsed.bodyLines, indent).join(`
44854
45825
  `);
44855
45826
  blocks.push({ kind: "report", body, indent });
@@ -44881,10 +45852,14 @@ function extractCards(body) {
44881
45852
  const title = attrs.title ? String(attrs.title) : undefined;
44882
45853
  const bodyLines = [];
44883
45854
  let closed = false;
45855
+ let indentWarning;
44884
45856
  i += 1;
44885
45857
  while (i < lines.length) {
44886
45858
  const current = lines[i];
44887
- if (current.trim() === ":::" && current.startsWith(indent)) {
45859
+ if (current.trim() === ":::") {
45860
+ if (indent.length > 0 && !current.startsWith(indent)) {
45861
+ indentWarning = "Card closing ::: indentation did not match opening.";
45862
+ }
44888
45863
  closed = true;
44889
45864
  i += 1;
44890
45865
  break;
@@ -44901,6 +45876,13 @@ function extractCards(body) {
44901
45876
  break;
44902
45877
  }
44903
45878
  const stripped = stripIndent(bodyLines, indent);
45879
+ if (indentWarning) {
45880
+ cards.push({
45881
+ type: "warning",
45882
+ title: "Malformed card",
45883
+ body: indentWarning
45884
+ });
45885
+ }
44904
45886
  cards.push({ type, title, body: stripped.join(`
44905
45887
  `) });
44906
45888
  }
@@ -44909,6 +45891,7 @@ function extractCards(body) {
44909
45891
  function parseDelimitedBlock(lines, startIndex, indent) {
44910
45892
  const bodyLines = [];
44911
45893
  let openCards = 0;
45894
+ let warning;
44912
45895
  let i = startIndex + 1;
44913
45896
  while (i < lines.length) {
44914
45897
  const current = lines[i];
@@ -44919,14 +45902,18 @@ function parseDelimitedBlock(lines, startIndex, indent) {
44919
45902
  i += 1;
44920
45903
  continue;
44921
45904
  }
44922
- if (trimmed === ":::" && current.startsWith(indent)) {
45905
+ if (trimmed === ":::") {
45906
+ const indentMismatch = indent.length > 0 && !current.startsWith(indent);
44923
45907
  if (openCards > 0) {
44924
45908
  openCards -= 1;
44925
45909
  bodyLines.push(current);
44926
45910
  i += 1;
44927
45911
  continue;
44928
45912
  }
44929
- return { bodyLines, nextIndex: i + 1 };
45913
+ if (indentMismatch) {
45914
+ warning = "Closing ::: indentation did not match opening. Adjust indentation for consistency.";
45915
+ }
45916
+ return { bodyLines, nextIndex: i + 1, warning };
44930
45917
  }
44931
45918
  bodyLines.push(current);
44932
45919
  i += 1;
@@ -45093,7 +46080,7 @@ function formatBoxRow(line, width) {
45093
46080
  const padded = len < width ? line + " ".repeat(width - len) : line;
45094
46081
  return `\u2502 ${padded} \u2502`;
45095
46082
  }
45096
- function formatMarkdownTables(text) {
46083
+ function formatMarkdownTables(text, maxWidth) {
45097
46084
  const lines = text.split(`
45098
46085
  `);
45099
46086
  const output = [];
@@ -45111,7 +46098,7 @@ function formatMarkdownTables(text) {
45111
46098
  rows.push(parseTableRow(lines[i]));
45112
46099
  i += 1;
45113
46100
  }
45114
- const table = renderTable(header, rows);
46101
+ const table = renderTable(header, rows, maxWidth);
45115
46102
  output.push(...table);
45116
46103
  continue;
45117
46104
  }
@@ -45126,7 +46113,7 @@ function parseTableRow(line) {
45126
46113
  const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
45127
46114
  return withoutEdges.split("|").map((cell) => cell.trim());
45128
46115
  }
45129
- function renderTable(header, rows) {
46116
+ function renderTable(header, rows, maxWidth) {
45130
46117
  const colCount = Math.max(header.length, ...rows.map((r) => r.length));
45131
46118
  const widths = new Array(colCount).fill(0);
45132
46119
  const allRows = [header, ...rows];
@@ -45138,11 +46125,29 @@ function renderTable(header, rows) {
45138
46125
  widths[i] = len;
45139
46126
  }
45140
46127
  }
46128
+ const minCellWidth = 4;
46129
+ const availableCellWidth = maxWidth ? Math.max(colCount * minCellWidth, maxWidth - (colCount - 1) * 3 - 4) : undefined;
46130
+ if (availableCellWidth) {
46131
+ const total = widths.reduce((sum, width) => sum + width, 0);
46132
+ if (total > availableCellWidth) {
46133
+ const minWidth = Math.max(1, Math.floor(availableCellWidth / colCount));
46134
+ while (widths.reduce((sum, width) => sum + width, 0) > availableCellWidth) {
46135
+ const maxWidthValue = Math.max(...widths);
46136
+ const idx = widths.findIndex((width) => width === maxWidthValue);
46137
+ if (idx === -1)
46138
+ break;
46139
+ if (widths[idx] <= minWidth)
46140
+ break;
46141
+ widths[idx] -= 1;
46142
+ }
46143
+ }
46144
+ }
45141
46145
  const pad = (value, width) => {
45142
- const len = stripAnsi2(value).length;
46146
+ const rendered = width > 0 ? truncateAnsi(value, width) : value;
46147
+ const len = stripAnsi2(rendered).length;
45143
46148
  if (len >= width)
45144
- return value;
45145
- return value + " ".repeat(width - len);
46149
+ return rendered;
46150
+ return rendered + " ".repeat(width - len);
45146
46151
  };
45147
46152
  const top = "\u250C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C") + "\u2510";
45148
46153
  const mid = "\u251C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u253C") + "\u2524";
@@ -45220,7 +46225,8 @@ function renderReport(body, maxWidth, indent = "") {
45220
46225
  }
45221
46226
  if (tableLines.length > 0) {
45222
46227
  output.push(indent + source_default.bold("Detailed Status Table"));
45223
- const rendered = renderReportTable(tableLines, indent);
46228
+ const adjustedWidth = maxWidth ? Math.max(20, maxWidth - indent.length) : undefined;
46229
+ const rendered = renderReportTable(tableLines, indent, adjustedWidth);
45224
46230
  output.push(...rendered);
45225
46231
  }
45226
46232
  return output.join(`
@@ -45249,7 +46255,7 @@ function renderProgressLine(label, value, labelWidth, barWidth) {
45249
46255
  const bar = source_default.gray("\u2591".repeat(empty));
45250
46256
  return `${label.padEnd(labelWidth)} [${fill}${bar}] ${value}%`;
45251
46257
  }
45252
- function renderReportTable(lines, indent) {
46258
+ function renderReportTable(lines, indent, maxWidth) {
45253
46259
  const tableLines = lines.map((line) => line.trim()).filter(Boolean);
45254
46260
  if (tableLines.length < 2)
45255
46261
  return [];
@@ -45273,7 +46279,7 @@ function renderReportTable(lines, indent) {
45273
46279
  }
45274
46280
  return next;
45275
46281
  });
45276
- return renderTable(header, styledRows).map((line) => indent + line);
46282
+ return renderTable(header, styledRows, maxWidth).map((line) => indent + line);
45277
46283
  }
45278
46284
  function decoratePriority(value) {
45279
46285
  const normalized = value.toLowerCase();
@@ -45343,6 +46349,23 @@ function wrapAnsiLine(line, width) {
45343
46349
  function truncateAnsi(line, width) {
45344
46350
  if (stripAnsi2(line).length <= width)
45345
46351
  return line;
46352
+ if (width <= 3) {
46353
+ let result = "";
46354
+ let visible2 = 0;
46355
+ let i2 = 0;
46356
+ while (i2 < line.length && visible2 < width) {
46357
+ const match = line.slice(i2).match(/^\x1b\[[0-9;]*m/);
46358
+ if (match) {
46359
+ result += match[0];
46360
+ i2 += match[0].length;
46361
+ continue;
46362
+ }
46363
+ result += line[i2];
46364
+ visible2 += 1;
46365
+ i2 += 1;
46366
+ }
46367
+ return result;
46368
+ }
45346
46369
  const suffix = "...";
45347
46370
  const target = Math.max(0, width - suffix.length);
45348
46371
  let current = "";
@@ -45362,6 +46385,42 @@ function truncateAnsi(line, width) {
45362
46385
  return current + suffix;
45363
46386
  }
45364
46387
 
46388
+ // packages/terminal/src/components/messageLines.ts
46389
+ function estimateToolPanelLines(toolCalls, toolResults, hasContent) {
46390
+ if (!toolCalls || toolCalls.length === 0) {
46391
+ return 0;
46392
+ }
46393
+ const resultMap = new Set;
46394
+ for (const result of toolResults || []) {
46395
+ resultMap.add(result.toolCallId);
46396
+ }
46397
+ let lines = 3;
46398
+ if (hasContent) {
46399
+ lines += 1;
46400
+ }
46401
+ for (const call of toolCalls) {
46402
+ lines += 3;
46403
+ if (resultMap.has(call.id)) {
46404
+ lines += 1;
46405
+ }
46406
+ }
46407
+ return lines;
46408
+ }
46409
+ function estimateMessageLines(message) {
46410
+ if (message.role === "system") {
46411
+ return 0;
46412
+ }
46413
+ const content = message.content ?? "";
46414
+ const contentLines = content.length > 0 ? content.split(`
46415
+ `).length : 0;
46416
+ const hasContent = contentLines > 0;
46417
+ let lines = Math.max(1, contentLines);
46418
+ if (message.role === "assistant" && message.toolCalls?.length) {
46419
+ lines += estimateToolPanelLines(message.toolCalls, message.toolResults, hasContent);
46420
+ }
46421
+ return lines;
46422
+ }
46423
+
45365
46424
  // packages/terminal/src/components/Messages.tsx
45366
46425
  var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
45367
46426
  function Messages4({
@@ -45371,19 +46430,28 @@ function Messages4({
45371
46430
  currentToolCall,
45372
46431
  lastToolResult,
45373
46432
  activityLog = [],
45374
- scrollOffset = 0,
45375
- maxVisible = 10,
46433
+ scrollOffsetLines = 0,
46434
+ maxVisibleLines = 10,
45376
46435
  queuedMessageIds
45377
46436
  }) {
45378
46437
  const [now2, setNow] = import_react24.useState(Date.now());
45379
46438
  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);
46439
+ const lineSpans = import_react24.useMemo(() => {
46440
+ let cursor = 0;
46441
+ return combinedMessages.map((message, index) => {
46442
+ const lines = estimateMessageLines(message);
46443
+ const start = cursor;
46444
+ cursor += lines;
46445
+ return { message, index, start, end: cursor, lines };
46446
+ });
46447
+ }, [combinedMessages]);
46448
+ const totalLines = lineSpans.length > 0 ? lineSpans[lineSpans.length - 1].end : 0;
46449
+ const endLine = Math.max(0, totalLines - scrollOffsetLines);
46450
+ const startLine = Math.max(0, endLine - maxVisibleLines);
46451
+ const visibleSpans = lineSpans.filter((span) => span.end > startLine && span.start < endLine);
45383
46452
  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);
46453
+ const visibleMessages = visibleSpans.filter((span) => span.index < historicalCount).map((span) => span.message);
46454
+ const visibleStreaming = visibleSpans.filter((span) => span.index >= historicalCount).map((span) => span.message);
45387
46455
  const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
45388
46456
  const historicalItems = groupedMessages.map((group) => {
45389
46457
  if (group.type === "single") {
@@ -45631,7 +46699,8 @@ function MessageBubble({ message, queuedMessageIds }) {
45631
46699
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45632
46700
  flexGrow: 1,
45633
46701
  children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
45634
- content: message.content
46702
+ content: message.content,
46703
+ preRendered: Boolean(message.__rendered)
45635
46704
  }, undefined, false, undefined, this)
45636
46705
  }, undefined, false, undefined, this)
45637
46706
  ]
@@ -45652,6 +46721,8 @@ function ToolCallPanel({
45652
46721
  }) {
45653
46722
  if (toolCalls.length === 0)
45654
46723
  return null;
46724
+ const { columns } = use_stdout_default();
46725
+ const panelWidth = columns ? Math.max(24, columns - 4) : undefined;
45655
46726
  const resultMap = new Map;
45656
46727
  for (const result of toolResults || []) {
45657
46728
  resultMap.set(result.toolCallId, result);
@@ -45664,7 +46735,7 @@ function ToolCallPanel({
45664
46735
  borderStyle: "round",
45665
46736
  borderColor,
45666
46737
  paddingX: 1,
45667
- width: "100%",
46738
+ width: panelWidth ?? "100%",
45668
46739
  children: [
45669
46740
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45670
46741
  justifyContent: "space-between",
@@ -45690,6 +46761,8 @@ function ToolCallPanel({
45690
46761
  const statusColor = result ? result.isError ? "red" : "green" : "yellow";
45691
46762
  const displayName = getToolDisplayName(toolCall);
45692
46763
  const context2 = getToolContext(toolCall);
46764
+ const maxLine = panelWidth ? Math.max(20, panelWidth - 8) : 80;
46765
+ const summaryLine = truncate(formatToolCall(toolCall), maxLine);
45693
46766
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45694
46767
  flexDirection: "column",
45695
46768
  marginTop: 1,
@@ -45719,7 +46792,7 @@ function ToolCallPanel({
45719
46792
  }, undefined, true, undefined, this),
45720
46793
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45721
46794
  dimColor: true,
45722
- children: formatToolCall(toolCall)
46795
+ children: summaryLine
45723
46796
  }, undefined, false, undefined, this),
45724
46797
  result && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45725
46798
  marginLeft: 2,
@@ -45754,7 +46827,7 @@ function getToolContext(toolCall) {
45754
46827
  return truncate(String(input.pattern || ""), 20);
45755
46828
  case "schedule":
45756
46829
  return String(input.action || "");
45757
- case "feedback":
46830
+ case "submit_feedback":
45758
46831
  return String(input.type || "feedback");
45759
46832
  case "web_search":
45760
46833
  return truncate(String(input.query || ""), 20);
@@ -46035,46 +47108,7 @@ function formatSearchResult(content) {
46035
47108
 
46036
47109
  // packages/terminal/src/components/Status.tsx
46037
47110
  var import_react25 = __toESM(require_react(), 1);
46038
-
46039
- // packages/terminal/src/components/EnergyBar.tsx
46040
47111
  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
47112
  function Status({
46079
47113
  isProcessing,
46080
47114
  cwd: cwd2,
@@ -46112,74 +47146,51 @@ function Status({
46112
47146
  let contextInfo = "";
46113
47147
  if (tokenUsage && tokenUsage.maxContextTokens > 0) {
46114
47148
  const percent = Math.round(tokenUsage.totalTokens / tokenUsage.maxContextTokens * 100);
46115
- contextInfo = `${percent}% context`;
47149
+ contextInfo = `${percent}%`;
46116
47150
  }
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, {
47151
+ const sessionInfo = sessionIndex && sessionCount && sessionCount > 1 ? `${sessionIndex}/${sessionCount}` : "";
47152
+ const bgIndicator = backgroundProcessingCount > 0 ? ` +${backgroundProcessingCount}` : "";
47153
+ const voiceIcon = voiceState?.enabled ? voiceState.isListening ? "\uD83C\uDFA4" : voiceState.isSpeaking ? "\uD83D\uDD0A" : "\uD83C\uDF99" : "";
47154
+ return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46122
47155
  marginTop: 1,
46123
47156
  justifyContent: "space-between",
46124
47157
  children: [
46125
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47158
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46126
47159
  dimColor: true,
46127
47160
  children: [
46128
- "/help for commands",
46129
- sessionCount && sessionCount > 1 ? " | Ctrl+S sessions" : ""
47161
+ "/help",
47162
+ sessionCount && sessionCount > 1 ? " \xB7 Ctrl+S" : ""
46130
47163
  ]
46131
47164
  }, undefined, true, undefined, this),
46132
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
47165
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46133
47166
  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, {
47167
+ voiceIcon && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46149
47168
  dimColor: true,
46150
47169
  children: [
46151
- voiceInfo,
46152
- " \xB7 "
47170
+ voiceIcon,
47171
+ " "
46153
47172
  ]
46154
47173
  }, undefined, true, undefined, this),
46155
- isProcessing && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47174
+ isProcessing && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46156
47175
  dimColor: true,
46157
- children: "esc to stop \xB7 "
47176
+ children: "esc \xB7 "
46158
47177
  }, undefined, false, undefined, this),
46159
- sessionInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47178
+ sessionInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46160
47179
  dimColor: true,
46161
47180
  children: [
46162
47181
  sessionInfo,
46163
47182
  bgIndicator,
46164
- contextInfo ? " \xB7 " : ""
47183
+ " \xB7 "
46165
47184
  ]
46166
47185
  }, undefined, true, undefined, this),
46167
- contextInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47186
+ contextInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46168
47187
  dimColor: true,
46169
47188
  children: contextInfo
46170
47189
  }, undefined, false, undefined, this),
46171
- sessionId && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46172
- dimColor: true,
46173
- children: [
46174
- sessionInfo || contextInfo ? " \xB7 " : "",
46175
- "id ",
46176
- sessionId
46177
- ]
46178
- }, undefined, true, undefined, this),
46179
- isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47190
+ isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46180
47191
  dimColor: true,
46181
47192
  children: [
46182
- " \xB7 \u273B Worked for ",
47193
+ " \xB7 ",
46183
47194
  formatDuration2(elapsed)
46184
47195
  ]
46185
47196
  }, undefined, true, undefined, this)
@@ -46211,17 +47222,17 @@ function Spinner({ type = "dots" }) {
46211
47222
  var build_default2 = Spinner;
46212
47223
 
46213
47224
  // packages/terminal/src/components/Spinner.tsx
46214
- var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
47225
+ var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
46215
47226
  function Spinner2({ label }) {
46216
- return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
47227
+ return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
46217
47228
  children: [
46218
- /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47229
+ /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46219
47230
  dimColor: true,
46220
- children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(build_default2, {
47231
+ children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(build_default2, {
46221
47232
  type: "dots"
46222
47233
  }, undefined, false, undefined, this)
46223
47234
  }, undefined, false, undefined, this),
46224
- label && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47235
+ label && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46225
47236
  dimColor: true,
46226
47237
  children: [
46227
47238
  " ",
@@ -46234,7 +47245,7 @@ function Spinner2({ label }) {
46234
47245
 
46235
47246
  // packages/terminal/src/components/ProcessingIndicator.tsx
46236
47247
  var import_react27 = __toESM(require_react(), 1);
46237
- var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
47248
+ var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
46238
47249
  function ProcessingIndicator({
46239
47250
  isProcessing,
46240
47251
  startTime,
@@ -46278,14 +47289,14 @@ function ProcessingIndicator({
46278
47289
  parts.push("thinking");
46279
47290
  }
46280
47291
  const label = isThinking ? "Metamorphosing" : "Working";
46281
- return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
47292
+ return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
46282
47293
  marginY: 1,
46283
47294
  children: [
46284
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47295
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46285
47296
  dimColor: true,
46286
47297
  children: "\u2736 "
46287
47298
  }, undefined, false, undefined, this),
46288
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47299
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46289
47300
  dimColor: true,
46290
47301
  children: [
46291
47302
  " ",
@@ -46293,7 +47304,7 @@ function ProcessingIndicator({
46293
47304
  "... "
46294
47305
  ]
46295
47306
  }, undefined, true, undefined, this),
46296
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47307
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46297
47308
  dimColor: true,
46298
47309
  children: [
46299
47310
  "(",
@@ -46306,31 +47317,31 @@ function ProcessingIndicator({
46306
47317
  }
46307
47318
 
46308
47319
  // packages/terminal/src/components/WelcomeBanner.tsx
46309
- var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
47320
+ var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
46310
47321
  function WelcomeBanner({ version, model, directory }) {
46311
47322
  const homeDir = process.env.HOME || "";
46312
47323
  const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
46313
- return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47324
+ return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46314
47325
  flexDirection: "column",
46315
47326
  marginBottom: 1,
46316
47327
  children: [
46317
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47328
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46318
47329
  children: [
46319
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47330
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46320
47331
  color: "cyan",
46321
47332
  bold: true,
46322
47333
  children: ">"
46323
47334
  }, undefined, false, undefined, this),
46324
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47335
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46325
47336
  color: "cyan",
46326
47337
  bold: true,
46327
47338
  children: "_ "
46328
47339
  }, undefined, false, undefined, this),
46329
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47340
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46330
47341
  bold: true,
46331
47342
  children: "assistants"
46332
47343
  }, undefined, false, undefined, this),
46333
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47344
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46334
47345
  dimColor: true,
46335
47346
  children: [
46336
47347
  " (v",
@@ -46340,29 +47351,29 @@ function WelcomeBanner({ version, model, directory }) {
46340
47351
  }, undefined, true, undefined, this)
46341
47352
  ]
46342
47353
  }, undefined, true, undefined, this),
46343
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47354
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46344
47355
  marginTop: 1,
46345
47356
  children: [
46346
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47357
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46347
47358
  dimColor: true,
46348
47359
  children: "model: "
46349
47360
  }, undefined, false, undefined, this),
46350
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47361
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46351
47362
  children: model
46352
47363
  }, undefined, false, undefined, this),
46353
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47364
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46354
47365
  dimColor: true,
46355
47366
  children: " /model to change"
46356
47367
  }, undefined, false, undefined, this)
46357
47368
  ]
46358
47369
  }, undefined, true, undefined, this),
46359
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47370
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46360
47371
  children: [
46361
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47372
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46362
47373
  dimColor: true,
46363
47374
  children: "directory: "
46364
47375
  }, undefined, false, undefined, this),
46365
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47376
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46366
47377
  children: displayDir
46367
47378
  }, undefined, false, undefined, this)
46368
47379
  ]
@@ -46373,7 +47384,7 @@ function WelcomeBanner({ version, model, directory }) {
46373
47384
 
46374
47385
  // packages/terminal/src/components/SessionSelector.tsx
46375
47386
  var import_react28 = __toESM(require_react(), 1);
46376
- var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
47387
+ var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
46377
47388
  function formatSessionTime(timestamp) {
46378
47389
  const date = new Date(timestamp);
46379
47390
  const now2 = new Date;
@@ -46439,13 +47450,13 @@ function SessionSelector({
46439
47450
  return;
46440
47451
  }
46441
47452
  });
46442
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47453
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46443
47454
  flexDirection: "column",
46444
47455
  paddingY: 1,
46445
47456
  children: [
46446
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47457
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46447
47458
  marginBottom: 1,
46448
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47459
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46449
47460
  bold: true,
46450
47461
  children: "Sessions"
46451
47462
  }, undefined, false, undefined, this)
@@ -46457,8 +47468,8 @@ function SessionSelector({
46457
47468
  const time = formatSessionTime(session.updatedAt);
46458
47469
  const path2 = formatPath(session.cwd);
46459
47470
  const processing = session.isProcessing ? " (processing)" : "";
46460
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
46461
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47471
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47472
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46462
47473
  inverse: isSelected,
46463
47474
  color: isActive ? "green" : undefined,
46464
47475
  dimColor: !isSelected && !isActive,
@@ -46475,17 +47486,17 @@ function SessionSelector({
46475
47486
  }, undefined, true, undefined, this)
46476
47487
  }, session.id, false, undefined, this);
46477
47488
  }),
46478
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47489
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46479
47490
  marginTop: 1,
46480
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47491
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46481
47492
  inverse: selectedIndex === sessions.length,
46482
47493
  dimColor: selectedIndex !== sessions.length,
46483
47494
  children: "+ New session (n)"
46484
47495
  }, undefined, false, undefined, this)
46485
47496
  }, undefined, false, undefined, this),
46486
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47497
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46487
47498
  marginTop: 1,
46488
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47499
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46489
47500
  dimColor: true,
46490
47501
  children: [
46491
47502
  "Enter to select | Esc to cancel | 1-",
@@ -46499,32 +47510,8 @@ function SessionSelector({
46499
47510
  }
46500
47511
 
46501
47512
  // packages/terminal/src/components/App.tsx
46502
- var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
47513
+ var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
46503
47514
  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
47515
  function parseErrorMessage(error) {
46529
47516
  const lines = error.split(`
46530
47517
  `);
@@ -46546,7 +47533,65 @@ function parseErrorMessage(error) {
46546
47533
  }
46547
47534
  var MESSAGE_CHUNK_LINES = 12;
46548
47535
  var MESSAGE_WRAP_CHARS = 120;
46549
- function buildDisplayMessages(messages, chunkLines, wrapChars) {
47536
+ function wrapTextLines(text, wrapChars) {
47537
+ const rawLines = text.split(`
47538
+ `);
47539
+ const lines = [];
47540
+ for (const line of rawLines) {
47541
+ if (line.length <= wrapChars) {
47542
+ lines.push(line);
47543
+ continue;
47544
+ }
47545
+ for (let i = 0;i < line.length; i += wrapChars) {
47546
+ lines.push(line.slice(i, i + wrapChars));
47547
+ }
47548
+ }
47549
+ return lines;
47550
+ }
47551
+ function stripAnsi3(text) {
47552
+ return text.replace(/\x1B\[[0-9;]*m/g, "");
47553
+ }
47554
+ function chunkRenderedLines(lines, chunkLines) {
47555
+ const chunks = [];
47556
+ let current = [];
47557
+ let i = 0;
47558
+ const isBoxStart = (line) => stripAnsi3(line).trimStart().startsWith("\u250C");
47559
+ const isBoxEnd = (line) => stripAnsi3(line).trimStart().startsWith("\u2514");
47560
+ while (i < lines.length) {
47561
+ const line = lines[i];
47562
+ if (isBoxStart(line)) {
47563
+ let end = i + 1;
47564
+ while (end < lines.length && !isBoxEnd(lines[end])) {
47565
+ end += 1;
47566
+ }
47567
+ if (end < lines.length)
47568
+ end += 1;
47569
+ const boxLines = lines.slice(i, end);
47570
+ if (current.length > 0 && current.length + boxLines.length > chunkLines) {
47571
+ chunks.push(current);
47572
+ current = [];
47573
+ }
47574
+ if (boxLines.length >= chunkLines) {
47575
+ chunks.push(boxLines);
47576
+ } else {
47577
+ current.push(...boxLines);
47578
+ }
47579
+ i = end;
47580
+ continue;
47581
+ }
47582
+ if (current.length >= chunkLines) {
47583
+ chunks.push(current);
47584
+ current = [];
47585
+ }
47586
+ current.push(line);
47587
+ i += 1;
47588
+ }
47589
+ if (current.length > 0) {
47590
+ chunks.push(current);
47591
+ }
47592
+ return chunks;
47593
+ }
47594
+ function buildDisplayMessages(messages, chunkLines, wrapChars, options) {
46550
47595
  const display = [];
46551
47596
  for (const msg of messages) {
46552
47597
  const content = msg.content ?? "";
@@ -46555,32 +47600,34 @@ function buildDisplayMessages(messages, chunkLines, wrapChars) {
46555
47600
  display.push(msg);
46556
47601
  continue;
46557
47602
  }
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
- }
47603
+ const lines = wrapTextLines(content, wrapChars);
46570
47604
  if (lines.length <= chunkLines) {
46571
- display.push(msg);
47605
+ if (msg.role === "assistant") {
47606
+ const rendered2 = renderMarkdown(lines.join(`
47607
+ `), { maxWidth: options?.maxWidth });
47608
+ display.push({ ...msg, content: rendered2, __rendered: true });
47609
+ } else {
47610
+ display.push(msg);
47611
+ }
46572
47612
  continue;
46573
47613
  }
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(`
47614
+ const baseContent = lines.join(`
47615
+ `);
47616
+ const renderAssistant = msg.role === "assistant";
47617
+ const rendered = renderAssistant ? renderMarkdown(baseContent, { maxWidth: options?.maxWidth }) : baseContent;
47618
+ const renderedLines = rendered.split(`
47619
+ `);
47620
+ const chunks = chunkRenderedLines(renderedLines, chunkLines);
47621
+ for (let i = 0;i < chunks.length; i++) {
47622
+ const chunkContent = chunks[i].join(`
46577
47623
  `);
46578
47624
  display.push({
46579
47625
  ...msg,
46580
47626
  id: `${msg.id}::chunk-${i}`,
46581
47627
  content: chunkContent,
46582
- toolCalls: i === totalChunks - 1 ? msg.toolCalls : undefined,
46583
- toolResults: i === totalChunks - 1 ? msg.toolResults : undefined
47628
+ __rendered: renderAssistant,
47629
+ toolCalls: i === chunks.length - 1 ? msg.toolCalls : undefined,
47630
+ toolResults: i === chunks.length - 1 ? msg.toolResults : undefined
46584
47631
  });
46585
47632
  }
46586
47633
  }
@@ -46615,7 +47662,7 @@ function App2({ cwd: cwd2, version }) {
46615
47662
  const toolCallsRef = import_react29.useRef([]);
46616
47663
  const toolResultsRef = import_react29.useRef([]);
46617
47664
  const activityLogRef = import_react29.useRef([]);
46618
- const prevDisplayCountRef = import_react29.useRef(0);
47665
+ const prevDisplayLineCountRef = import_react29.useRef(0);
46619
47666
  const skipNextDoneRef = import_react29.useRef(false);
46620
47667
  const isProcessingRef = import_react29.useRef(isProcessing);
46621
47668
  import_react29.useEffect(() => {
@@ -46937,9 +47984,10 @@ function App2({ cwd: cwd2, version }) {
46937
47984
  await activeSession2.client.send(nextMessage.content);
46938
47985
  }, [activeSessionId]);
46939
47986
  const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
46940
- const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.map((msg) => msg.id)), [activeQueue]);
47987
+ const queuedMessageIds = import_react29.useMemo(() => new Set(activeQueue.filter((msg) => msg.mode === "queued").map((msg) => msg.id)), [activeQueue]);
46941
47988
  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]);
47989
+ const renderWidth = columns ? Math.max(20, columns - 2) : undefined;
47990
+ const displayMessages = import_react29.useMemo(() => buildDisplayMessages(messages, MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth }), [messages, wrapChars, renderWidth]);
46943
47991
  const streamingMessages = import_react29.useMemo(() => {
46944
47992
  if (!isProcessing || !currentResponse.trim())
46945
47993
  return [];
@@ -46949,9 +47997,12 @@ function App2({ cwd: cwd2, version }) {
46949
47997
  content: currentResponse,
46950
47998
  timestamp: now()
46951
47999
  };
46952
- return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
46953
- }, [currentResponse, isProcessing, wrapChars]);
46954
- const displayCount = displayMessages.length + streamingMessages.length;
48000
+ return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars, { maxWidth: renderWidth });
48001
+ }, [currentResponse, isProcessing, wrapChars, renderWidth]);
48002
+ const displayLineCount = import_react29.useMemo(() => {
48003
+ const combined = [...displayMessages, ...streamingMessages];
48004
+ return combined.reduce((sum, msg) => sum + estimateMessageLines(msg), 0);
48005
+ }, [displayMessages, streamingMessages]);
46955
48006
  import_react29.useEffect(() => {
46956
48007
  if (!isProcessing && activeQueue.length > 0) {
46957
48008
  processQueue();
@@ -46961,23 +48012,21 @@ function App2({ cwd: cwd2, version }) {
46961
48012
  if (autoScroll) {
46962
48013
  setScrollOffset(0);
46963
48014
  }
46964
- }, [displayCount, autoScroll]);
48015
+ }, [displayLineCount, autoScroll]);
46965
48016
  import_react29.useEffect(() => {
46966
- const prevCount = prevDisplayCountRef.current;
46967
- if (!autoScroll && displayCount > prevCount) {
46968
- const delta = displayCount - prevCount;
48017
+ const prevCount = prevDisplayLineCountRef.current;
48018
+ if (!autoScroll && displayLineCount > prevCount) {
48019
+ const delta = displayLineCount - prevCount;
46969
48020
  setScrollOffset((prev) => prev + delta);
46970
48021
  }
46971
- prevDisplayCountRef.current = displayCount;
46972
- }, [displayCount, autoScroll]);
48022
+ prevDisplayLineCountRef.current = displayLineCount;
48023
+ }, [displayLineCount, autoScroll]);
46973
48024
  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);
48025
+ const maxVisibleLines = rows ? Math.max(6, rows - reservedLines) : 20;
46977
48026
  import_react29.useEffect(() => {
46978
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48027
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
46979
48028
  setScrollOffset((prev) => Math.min(prev, maxOffset));
46980
- }, [displayCount, maxVisibleMessages]);
48029
+ }, [displayLineCount, maxVisibleLines]);
46981
48030
  const sessions = registry2.listSessions();
46982
48031
  const activeSession = registry2.getActiveSession();
46983
48032
  const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
@@ -47056,8 +48105,9 @@ function App2({ cwd: cwd2, version }) {
47056
48105
  }
47057
48106
  if (key.pageUp || key.shift && key.upArrow) {
47058
48107
  setScrollOffset((prev) => {
47059
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
47060
- const newOffset = Math.min(prev + 3, maxOffset);
48108
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
48109
+ const step = Math.max(3, Math.floor(maxVisibleLines / 2));
48110
+ const newOffset = Math.min(prev + step, maxOffset);
47061
48111
  if (newOffset > 0)
47062
48112
  setAutoScroll(false);
47063
48113
  return newOffset;
@@ -47065,14 +48115,15 @@ function App2({ cwd: cwd2, version }) {
47065
48115
  }
47066
48116
  if (key.pageDown || key.shift && key.downArrow) {
47067
48117
  setScrollOffset((prev) => {
47068
- const newOffset = Math.max(0, prev - 3);
48118
+ const step = Math.max(3, Math.floor(maxVisibleLines / 2));
48119
+ const newOffset = Math.max(0, prev - step);
47069
48120
  if (newOffset === 0)
47070
48121
  setAutoScroll(true);
47071
48122
  return newOffset;
47072
48123
  });
47073
48124
  }
47074
48125
  if (key.ctrl && input === "u") {
47075
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48126
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
47076
48127
  setScrollOffset(maxOffset);
47077
48128
  setAutoScroll(false);
47078
48129
  }
@@ -47103,13 +48154,19 @@ function App2({ cwd: cwd2, version }) {
47103
48154
  setShowSessionSelector(true);
47104
48155
  return;
47105
48156
  }
47106
- if (mode === "queue") {
48157
+ if (mode === "queue" || mode === "inline") {
47107
48158
  if (!activeSessionId)
47108
48159
  return;
47109
48160
  const queuedId = generateId();
47110
48161
  setMessageQueue((prev) => [
47111
48162
  ...prev,
47112
- { id: queuedId, sessionId: activeSessionId, content: trimmedInput, queuedAt: now() }
48163
+ {
48164
+ id: queuedId,
48165
+ sessionId: activeSessionId,
48166
+ content: trimmedInput,
48167
+ queuedAt: now(),
48168
+ mode: mode === "inline" ? "inline" : "queued"
48169
+ }
47113
48170
  ]);
47114
48171
  setMessages((prev) => [
47115
48172
  ...prev,
@@ -47173,19 +48230,19 @@ function App2({ cwd: cwd2, version }) {
47173
48230
  activeSessionId
47174
48231
  ]);
47175
48232
  if (isInitializing) {
47176
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48233
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47177
48234
  flexDirection: "column",
47178
48235
  padding: 1,
47179
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Spinner2, {
48236
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Spinner2, {
47180
48237
  label: "Initializing..."
47181
48238
  }, undefined, false, undefined, this)
47182
48239
  }, undefined, false, undefined, this);
47183
48240
  }
47184
48241
  if (showSessionSelector) {
47185
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48242
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47186
48243
  flexDirection: "column",
47187
48244
  padding: 1,
47188
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(SessionSelector, {
48245
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SessionSelector, {
47189
48246
  sessions,
47190
48247
  activeSessionId,
47191
48248
  onSelect: handleSessionSwitch,
@@ -47205,19 +48262,21 @@ function App2({ cwd: cwd2, version }) {
47205
48262
  return text;
47206
48263
  return text.slice(0, maxLen - 3) + "...";
47207
48264
  };
48265
+ const queuedCount = activeQueue.filter((msg) => msg.mode === "queued").length;
48266
+ const inlineCount = activeQueue.filter((msg) => msg.mode === "inline").length;
47208
48267
  const showWelcome = messages.length === 0 && !isProcessing;
47209
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48268
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47210
48269
  flexDirection: "column",
47211
48270
  padding: 1,
47212
48271
  children: [
47213
- showWelcome && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(WelcomeBanner, {
47214
- version: version ?? "0.6.13",
48272
+ showWelcome && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(WelcomeBanner, {
48273
+ version: version ?? "unknown",
47215
48274
  model: "claude-sonnet-4",
47216
48275
  directory: activeSession?.cwd || cwd2
47217
48276
  }, undefined, false, undefined, this),
47218
- backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48277
+ backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47219
48278
  marginBottom: 1,
47220
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48279
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47221
48280
  color: "yellow",
47222
48281
  children: [
47223
48282
  backgroundProcessingCount,
@@ -47227,17 +48286,17 @@ function App2({ cwd: cwd2, version }) {
47227
48286
  ]
47228
48287
  }, undefined, true, undefined, this)
47229
48288
  }, undefined, false, undefined, this),
47230
- scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47231
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48289
+ scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
48290
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47232
48291
  dimColor: true,
47233
48292
  children: [
47234
48293
  "\u2191 ",
47235
48294
  scrollOffset,
47236
- " more messages above (Shift+\u2193 or Page Down to scroll down)"
48295
+ " more lines above (Shift+\u2193 or Page Down to scroll down)"
47237
48296
  ]
47238
48297
  }, undefined, true, undefined, this)
47239
48298
  }, undefined, false, undefined, this),
47240
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Messages4, {
48299
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Messages4, {
47241
48300
  messages: displayMessages,
47242
48301
  currentResponse: undefined,
47243
48302
  streamingMessages,
@@ -47245,61 +48304,34 @@ function App2({ cwd: cwd2, version }) {
47245
48304
  lastToolResult: undefined,
47246
48305
  activityLog: isProcessing ? activityLog : [],
47247
48306
  queuedMessageIds,
47248
- scrollOffset,
47249
- maxVisible: maxVisibleMessages
48307
+ scrollOffsetLines: scrollOffset,
48308
+ maxVisibleLines
47250
48309
  }, 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, {
48310
+ activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47280
48311
  marginY: 1,
47281
48312
  flexDirection: "column",
47282
48313
  children: [
47283
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48314
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47284
48315
  dimColor: true,
47285
48316
  children: [
47286
48317
  activeQueue.length,
47287
- " message",
48318
+ " pending message",
47288
48319
  activeQueue.length > 1 ? "s" : "",
47289
- " queued"
48320
+ inlineCount > 0 || queuedCount > 0 ? ` \xB7 ${inlineCount} in-stream \xB7 ${queuedCount} queued` : ""
47290
48321
  ]
47291
48322
  }, undefined, true, undefined, this),
47292
- activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48323
+ activeQueue.slice(0, MAX_QUEUED_PREVIEW).map((queued) => /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47293
48324
  marginLeft: 2,
47294
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48325
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47295
48326
  dimColor: true,
47296
48327
  children: [
47297
- "\u276F ",
48328
+ queued.mode === "inline" ? "\u21B3" : "\u23F3",
48329
+ " ",
47298
48330
  truncateQueued(queued.content)
47299
48331
  ]
47300
48332
  }, undefined, true, undefined, this)
47301
48333
  }, queued.id, false, undefined, this)),
47302
- activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48334
+ activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47303
48335
  dimColor: true,
47304
48336
  children: [
47305
48337
  " ... and ",
@@ -47313,18 +48345,18 @@ function App2({ cwd: cwd2, version }) {
47313
48345
  const parsed = parseErrorMessage(error);
47314
48346
  const severity = parsed.code && /TIMEOUT|RATE_LIMITED/.test(parsed.code) ? "yellow" : "red";
47315
48347
  const prefix = SHOW_ERROR_CODES && parsed.code ? `${parsed.code}: ` : "";
47316
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48348
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47317
48349
  marginY: 1,
47318
48350
  flexDirection: "column",
47319
48351
  children: [
47320
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48352
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47321
48353
  color: severity,
47322
48354
  children: [
47323
48355
  prefix,
47324
48356
  parsed.message
47325
48357
  ]
47326
48358
  }, undefined, true, undefined, this),
47327
- parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48359
+ parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47328
48360
  color: severity,
47329
48361
  children: [
47330
48362
  "Suggestion: ",
@@ -47334,19 +48366,19 @@ function App2({ cwd: cwd2, version }) {
47334
48366
  ]
47335
48367
  }, undefined, true, undefined, this);
47336
48368
  })(),
47337
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ProcessingIndicator, {
48369
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ProcessingIndicator, {
47338
48370
  isProcessing,
47339
48371
  startTime: processingStartTime,
47340
48372
  tokenCount: currentTurnTokens,
47341
48373
  isThinking
47342
48374
  }, undefined, false, undefined, this),
47343
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Input, {
48375
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Input, {
47344
48376
  onSubmit: handleSubmit,
47345
48377
  isProcessing,
47346
48378
  queueLength: activeQueue.length,
47347
48379
  skills
47348
48380
  }, undefined, false, undefined, this),
47349
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Status, {
48381
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Status, {
47350
48382
  isProcessing,
47351
48383
  cwd: activeSession?.cwd || cwd2,
47352
48384
  queueLength: activeQueue.length,
@@ -47538,8 +48570,9 @@ function formatStreamEvent(chunk) {
47538
48570
  }
47539
48571
 
47540
48572
  // packages/terminal/src/index.tsx
47541
- var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
47542
- var VERSION3 = "0.6.19";
48573
+ var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
48574
+ var VERSION3 = "0.6.20";
48575
+ process.env.ASSISTANTS_VERSION ??= VERSION3;
47543
48576
  function parseArgs(argv) {
47544
48577
  const args = argv.slice(2);
47545
48578
  const options = {
@@ -47693,7 +48726,7 @@ if (options.print !== null) {
47693
48726
  process.exit(1);
47694
48727
  });
47695
48728
  } else {
47696
- const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(App2, {
48729
+ const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(App2, {
47697
48730
  cwd: options.cwd,
47698
48731
  version: VERSION3
47699
48732
  }, undefined, false, undefined, this));
@@ -47702,4 +48735,4 @@ if (options.print !== null) {
47702
48735
  });
47703
48736
  }
47704
48737
 
47705
- //# debugId=6BDD2D63CEF73C2464756E2164756E21
48738
+ //# debugId=F2C1A670F9E8793164756E2164756E21