@hasna/assistants 0.6.18 → 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,
@@ -38775,6 +38828,10 @@ class SchedulerTool {
38775
38828
  type: "string",
38776
38829
  description: "Optional description for this schedule"
38777
38830
  },
38831
+ sessionId: {
38832
+ type: "string",
38833
+ description: "Session id to scope the schedule to"
38834
+ },
38778
38835
  id: {
38779
38836
  type: "string",
38780
38837
  description: "Schedule id (for delete/pause/resume)"
@@ -38819,6 +38876,7 @@ class SchedulerTool {
38819
38876
  createdAt: now2,
38820
38877
  updatedAt: now2,
38821
38878
  createdBy: "agent",
38879
+ sessionId: typeof input.sessionId === "string" ? input.sessionId : undefined,
38822
38880
  command,
38823
38881
  description: input.description,
38824
38882
  status: "active",
@@ -39732,13 +39790,217 @@ ${stderr}`;
39732
39790
  }
39733
39791
  }
39734
39792
  // packages/core/src/commands/builtin.ts
39735
- import { join as join10 } from "path";
39793
+ import { join as join11 } from "path";
39736
39794
  import { homedir as homedir7, platform as platform2, release, arch } from "os";
39737
39795
  import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "fs";
39738
39796
  init_src();
39739
- var VERSION = "0.6.14";
39740
- function resolveAuthTimeout(resolve4) {
39741
- 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: () => "{}" } });
39742
40004
  }
39743
40005
  function splitArgs(input) {
39744
40006
  const args = [];
@@ -39787,6 +40049,8 @@ class BuiltinCommands {
39787
40049
  loader.register(this.statusCommand());
39788
40050
  loader.register(this.tokensCommand());
39789
40051
  loader.register(this.contextCommand());
40052
+ loader.register(this.projectsCommand());
40053
+ loader.register(this.plansCommand());
39790
40054
  loader.register(this.summarizeCommand());
39791
40055
  loader.register(this.restCommand());
39792
40056
  loader.register(this.voiceCommand());
@@ -40392,148 +40656,740 @@ Identities:
40392
40656
  contextCommand() {
40393
40657
  return {
40394
40658
  name: "context",
40395
- description: "Show context summarization status",
40659
+ description: "Manage injected project context (files, connectors, notes) or show status",
40396
40660
  builtin: true,
40397
40661
  selfHandled: true,
40398
40662
  content: "",
40399
40663
  handler: async (args, context) => {
40400
- const info = context.getContextInfo?.();
40401
- 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
+ `);
40402
40680
  context.emit("text", `
40403
- Context summarization is not available.
40681
+ ${usage}
40404
40682
  `);
40405
40683
  context.emit("done");
40406
40684
  return { handled: true };
40407
40685
  }
40408
- const { config, state } = info;
40409
- const usedPercent = Math.round(state.totalTokens / config.maxContextTokens * 100);
40410
- 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 = `
40411
40698
  **Context Status**
40412
40699
 
40413
40700
  `;
40414
- message += `**Messages:** ${state.messageCount}
40701
+ message += `**Messages:** ${state.messageCount}
40415
40702
  `;
40416
- message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40703
+ message += `**Estimated Tokens:** ${state.totalTokens.toLocaleString()} / ${config.maxContextTokens.toLocaleString()} (${usedPercent}%)
40417
40704
  `;
40418
- message += `**Summary Count:** ${state.summaryCount}
40705
+ message += `**Summary Count:** ${state.summaryCount}
40419
40706
  `;
40420
- message += `**Strategy:** ${config.summaryStrategy}
40707
+ message += `**Strategy:** ${config.summaryStrategy}
40421
40708
  `;
40422
- message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40709
+ message += `**Keep Recent Messages:** ${config.keepRecentMessages}
40423
40710
  `;
40424
- if (state.lastSummaryAt) {
40425
- message += `**Last Summary:** ${state.lastSummaryAt}
40711
+ if (state.lastSummaryAt) {
40712
+ message += `**Last Summary:** ${state.lastSummaryAt}
40426
40713
  `;
40427
- if (state.lastSummaryTokensBefore && state.lastSummaryTokensAfter) {
40428
- 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()}
40429
40716
  `;
40717
+ }
40430
40718
  }
40431
- }
40432
- const barLength = 30;
40433
- const filledLength = Math.round(usedPercent / 100 * barLength);
40434
- const bar = "\u2588".repeat(filledLength) + "\u2591".repeat(barLength - filledLength);
40435
- 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 += `
40436
40723
  [${bar}] ${usedPercent}%
40437
40724
  `;
40438
- context.emit("text", message);
40439
- context.emit("done");
40440
- return { handled: true };
40441
- }
40442
- };
40443
- }
40444
- summarizeCommand() {
40445
- return {
40446
- name: "summarize",
40447
- description: "Summarize and compress the current conversation",
40448
- builtin: true,
40449
- selfHandled: true,
40450
- content: "",
40451
- handler: async (args, context) => {
40452
- if (!context.summarizeContext) {
40453
- context.emit("text", `
40454
- Context summarization is not available.
40455
- `);
40725
+ context.emit("text", message);
40456
40726
  context.emit("done");
40457
40727
  return { handled: true };
40458
40728
  }
40459
- const result = await context.summarizeContext();
40460
- if (!result.summarized) {
40461
- context.emit("text", `
40462
- 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.
40463
40732
  `);
40464
40733
  context.emit("done");
40465
40734
  return { handled: true };
40466
40735
  }
40467
- let message = `
40468
- **Context Summary Generated**
40469
-
40470
- `;
40471
- message += `Summarized ${result.summarizedCount} message(s).
40472
- `;
40473
- 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})**
40474
40746
 
40475
40747
  `;
40476
- if (result.summary) {
40477
- 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}
40478
40751
  `;
40752
+ }
40753
+ context.emit("text", output);
40754
+ context.emit("done");
40755
+ return { handled: true };
40479
40756
  }
40480
- 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
+ `);
40481
40837
  context.emit("done");
40482
40838
  return { handled: true };
40483
40839
  }
40484
40840
  };
40485
40841
  }
40486
- restCommand() {
40842
+ projectsCommand() {
40487
40843
  return {
40488
- name: "rest",
40489
- description: "Recharge assistant energy",
40844
+ name: "projects",
40845
+ description: "Manage projects inside this folder",
40490
40846
  builtin: true,
40491
40847
  selfHandled: true,
40492
40848
  content: "",
40493
40849
  handler: async (args, context) => {
40494
- 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
+ `);
40495
40863
  context.emit("text", `
40496
- Energy system is not available.
40864
+ ${usage}
40497
40865
  `);
40498
40866
  context.emit("done");
40499
40867
  return { handled: true };
40500
40868
  }
40501
- const parsed = parseInt(args.trim(), 10);
40502
- const amount = Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
40503
- context.restEnergy(amount);
40504
- const state = context.getEnergyState?.();
40505
- if (state) {
40506
- const percent = Math.round(state.current / Math.max(1, state.max) * 100);
40507
- context.emit("text", `
40508
- Energy restored. Current level: ${percent}% (${state.current}/${state.max}).
40509
- `);
40510
- } else {
40511
- context.emit("text", `
40512
- 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>.
40513
40874
  `);
40514
- }
40515
- context.emit("done");
40516
- return { handled: true };
40517
- }
40518
- };
40519
- }
40520
- skillsCommand(loader) {
40521
- return {
40522
- name: "skills",
40523
- description: "List available skills",
40524
- builtin: true,
40525
- selfHandled: true,
40526
- content: "",
40527
- handler: async (args, context) => {
40528
- let message = `
40529
- **Available Skills**
40530
-
40531
- `;
40532
- 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**
40533
40881
 
40534
40882
  `;
40535
- if (context.skills.length === 0) {
40536
- message += `No skills loaded.
40883
+ for (const project of projects) {
40884
+ const marker = project.id === activeId ? "*" : " ";
40885
+ output += `${marker} ${project.name} (${project.id})
40886
+ `;
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.
40537
41393
  `;
40538
41394
  message += `
40539
41395
  Add skills to ~/.assistants/assistants-shared/skills/ or .assistants/skills/
@@ -40557,7 +41413,7 @@ ${context.skills.length} skill(s) available.
40557
41413
  statusCommand() {
40558
41414
  return {
40559
41415
  name: "status",
40560
- description: "Show current session status and token usage",
41416
+ description: "Show current session status, energy, identity, and token usage",
40561
41417
  builtin: true,
40562
41418
  selfHandled: true,
40563
41419
  content: "",
@@ -40567,11 +41423,46 @@ ${context.skills.length} skill(s) available.
40567
41423
  let message = `
40568
41424
  **Session Status**
40569
41425
 
41426
+ `;
41427
+ message += `**Session ID:** ${context.sessionId}
40570
41428
  `;
40571
41429
  message += `**Working Directory:** ${context.cwd}
40572
41430
  `;
40573
- 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}
40574
41463
  `;
41464
+ }
41465
+ }
40575
41466
  message += `**Messages:** ${context.messages.length}
40576
41467
  `;
40577
41468
  message += `**Available Tools:** ${context.tools.length}
@@ -40658,9 +41549,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40658
41549
  content: "",
40659
41550
  handler: async (args, context) => {
40660
41551
  const configPaths = [
40661
- join10(context.cwd, ".assistants", "config.json"),
40662
- join10(context.cwd, ".assistants", "config.local.json"),
40663
- join10(getConfigDir(), "config.json")
41552
+ join11(context.cwd, ".assistants", "config.json"),
41553
+ join11(context.cwd, ".assistants", "config.local.json"),
41554
+ join11(getConfigDir(), "config.json")
40664
41555
  ];
40665
41556
  let message = `
40666
41557
  **Configuration**
@@ -40678,9 +41569,9 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40678
41569
  message += `
40679
41570
  **Commands Directories:**
40680
41571
  `;
40681
- message += ` - Project: ${join10(context.cwd, ".assistants", "commands")}
41572
+ message += ` - Project: ${join11(context.cwd, ".assistants", "commands")}
40682
41573
  `;
40683
- message += ` - Global: ${join10(homeDir, ".assistants", "commands")}
41574
+ message += ` - Global: ${join11(homeDir, ".assistants", "commands")}
40684
41575
  `;
40685
41576
  context.emit("text", message);
40686
41577
  context.emit("done");
@@ -40696,7 +41587,7 @@ Format the summary as a brief bullet-point list. This summary will replace the c
40696
41587
  selfHandled: true,
40697
41588
  content: "",
40698
41589
  handler: async (args, context) => {
40699
- const commandsDir = join10(context.cwd, ".assistants", "commands");
41590
+ const commandsDir = join11(context.cwd, ".assistants", "commands");
40700
41591
  mkdirSync2(commandsDir, { recursive: true });
40701
41592
  const exampleCommand = `---
40702
41593
  name: reflect
@@ -40712,7 +41603,7 @@ Please summarize the last interaction and suggest 2-3 next steps.
40712
41603
  - Focus on clarity
40713
41604
  - Ask a follow-up question if needed
40714
41605
  `;
40715
- const examplePath = join10(commandsDir, "reflect.md");
41606
+ const examplePath = join11(commandsDir, "reflect.md");
40716
41607
  if (!existsSync6(examplePath)) {
40717
41608
  writeFileSync3(examplePath, exampleCommand);
40718
41609
  }
@@ -40862,6 +41753,7 @@ Keep it concise but comprehensive.`
40862
41753
  createdAt: now2,
40863
41754
  updatedAt: now2,
40864
41755
  createdBy: "user",
41756
+ sessionId: context.sessionId,
40865
41757
  command,
40866
41758
  status: "active",
40867
41759
  schedule: {
@@ -41032,8 +41924,8 @@ Connector "${connectorName}" not found.
41032
41924
  `;
41033
41925
  try {
41034
41926
  let timeoutId = null;
41035
- const timeoutPromise = new Promise((resolve4) => {
41036
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
41927
+ const timeoutPromise = new Promise((resolve5) => {
41928
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41037
41929
  });
41038
41930
  const result = await Promise.race([
41039
41931
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41095,8 +41987,8 @@ Connector "${connectorName}" not found.
41095
41987
  let status = "\u25CB";
41096
41988
  let timeoutId = null;
41097
41989
  try {
41098
- const timeoutPromise = new Promise((resolve4) => {
41099
- timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve4);
41990
+ const timeoutPromise = new Promise((resolve5) => {
41991
+ timeoutId = setTimeout(resolveAuthTimeout, 1000, resolve5);
41100
41992
  });
41101
41993
  const result = await Promise.race([
41102
41994
  Bun.$`${connector.cli} auth status --format json`.quiet().nothrow(),
@@ -41371,6 +42263,35 @@ ${repoUrl}/issues/new
41371
42263
  }
41372
42264
  };
41373
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
+ }
41374
42295
  }
41375
42296
  // packages/core/src/llm/client.ts
41376
42297
  async function createLLMClient(config) {
@@ -41384,7 +42305,7 @@ async function createLLMClient(config) {
41384
42305
  // packages/core/src/heartbeat/manager.ts
41385
42306
  import { dirname as dirname5 } from "path";
41386
42307
  import { mkdirSync as mkdirSync3 } from "fs";
41387
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
42308
+ import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
41388
42309
 
41389
42310
  class HeartbeatManager {
41390
42311
  config;
@@ -41463,12 +42384,12 @@ class HeartbeatManager {
41463
42384
  }
41464
42385
  async persist(heartbeat) {
41465
42386
  try {
41466
- await writeFile2(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
42387
+ await writeFile3(this.config.persistPath, JSON.stringify(heartbeat, null, 2));
41467
42388
  } catch {}
41468
42389
  }
41469
42390
  static async checkStale(path2, thresholdMs) {
41470
42391
  try {
41471
- const content = await readFile2(path2, "utf-8");
42392
+ const content = await readFile4(path2, "utf-8");
41472
42393
  const heartbeat = JSON.parse(content);
41473
42394
  const age = Date.now() - new Date(heartbeat.timestamp).getTime();
41474
42395
  return { isStale: age > thresholdMs, lastHeartbeat: heartbeat };
@@ -41480,7 +42401,7 @@ class HeartbeatManager {
41480
42401
  // packages/core/src/heartbeat/persistence.ts
41481
42402
  import { dirname as dirname6 } from "path";
41482
42403
  import { mkdirSync as mkdirSync4 } from "fs";
41483
- 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";
41484
42405
 
41485
42406
  class StatePersistence {
41486
42407
  path;
@@ -41490,12 +42411,12 @@ class StatePersistence {
41490
42411
  }
41491
42412
  async save(state) {
41492
42413
  try {
41493
- await writeFile3(this.path, JSON.stringify(state, null, 2));
42414
+ await writeFile4(this.path, JSON.stringify(state, null, 2));
41494
42415
  } catch {}
41495
42416
  }
41496
42417
  async load() {
41497
42418
  try {
41498
- const content = await readFile3(this.path, "utf-8");
42419
+ const content = await readFile5(this.path, "utf-8");
41499
42420
  return JSON.parse(content);
41500
42421
  } catch {
41501
42422
  return null;
@@ -41503,7 +42424,7 @@ class StatePersistence {
41503
42424
  }
41504
42425
  async clear() {
41505
42426
  try {
41506
- await unlink2(this.path);
42427
+ await unlink3(this.path);
41507
42428
  } catch {}
41508
42429
  }
41509
42430
  }
@@ -41707,7 +42628,7 @@ class EnergyManager {
41707
42628
  // packages/core/src/energy/storage.ts
41708
42629
  import { dirname as dirname7 } from "path";
41709
42630
  import { mkdirSync as mkdirSync5 } from "fs";
41710
- import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
42631
+ import { readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
41711
42632
 
41712
42633
  class EnergyStorage {
41713
42634
  path;
@@ -41717,12 +42638,12 @@ class EnergyStorage {
41717
42638
  }
41718
42639
  async save(state) {
41719
42640
  try {
41720
- await writeFile4(this.path, JSON.stringify(state, null, 2));
42641
+ await writeFile5(this.path, JSON.stringify(state, null, 2));
41721
42642
  } catch {}
41722
42643
  }
41723
42644
  async load() {
41724
42645
  try {
41725
- const content = await readFile4(this.path, "utf-8");
42646
+ const content = await readFile6(this.path, "utf-8");
41726
42647
  return JSON.parse(content);
41727
42648
  } catch {
41728
42649
  return null;
@@ -41782,12 +42703,12 @@ function validateToolCalls(toolCalls, tools) {
41782
42703
  // packages/core/src/voice/utils.ts
41783
42704
  import { existsSync as existsSync8, readFileSync as readFileSync3 } from "fs";
41784
42705
  import { homedir as homedir9 } from "os";
41785
- import { join as join12 } from "path";
42706
+ import { join as join13 } from "path";
41786
42707
  import { spawnSync } from "child_process";
41787
42708
  function loadApiKeyFromSecrets2(key) {
41788
42709
  const envHome = process.env.HOME || process.env.USERPROFILE;
41789
42710
  const homeDir = envHome && envHome.trim().length > 0 ? envHome : homedir9();
41790
- const secretsPath = join12(homeDir, ".secrets");
42711
+ const secretsPath = join13(homeDir, ".secrets");
41791
42712
  if (!existsSync8(secretsPath))
41792
42713
  return;
41793
42714
  try {
@@ -41861,7 +42782,7 @@ class SystemSTT {
41861
42782
  // packages/core/src/voice/tts.ts
41862
42783
  import { spawnSync as spawnSync2 } from "child_process";
41863
42784
  import { tmpdir as tmpdir2 } from "os";
41864
- import { join as join13 } from "path";
42785
+ import { join as join14 } from "path";
41865
42786
  import { readFileSync as readFileSync4, unlinkSync as unlinkSync2 } from "fs";
41866
42787
  class ElevenLabsTTS {
41867
42788
  apiKey;
@@ -41965,7 +42886,7 @@ class SystemTTS {
41965
42886
  if (!say) {
41966
42887
  throw new Error('System TTS not available: missing "say" command.');
41967
42888
  }
41968
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
42889
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.aiff`);
41969
42890
  const args = [];
41970
42891
  if (this.voiceId) {
41971
42892
  args.push("-v", this.voiceId);
@@ -41987,7 +42908,7 @@ class SystemTTS {
41987
42908
  }
41988
42909
  const espeak = findExecutable("espeak") || findExecutable("espeak-ng");
41989
42910
  if (espeak) {
41990
- const output = join13(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
42911
+ const output = join14(tmpdir2(), `assistants-tts-${Date.now()}.wav`);
41991
42912
  const args = ["-w", output];
41992
42913
  if (this.voiceId) {
41993
42914
  args.push("-v", this.voiceId);
@@ -42014,32 +42935,32 @@ class SystemTTS {
42014
42935
  // packages/core/src/voice/player.ts
42015
42936
  import { spawn } from "child_process";
42016
42937
  import { tmpdir as tmpdir3 } from "os";
42017
- import { join as join14 } from "path";
42018
- 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";
42019
42940
  class AudioPlayer {
42020
42941
  currentProcess = null;
42021
42942
  playing = false;
42022
42943
  async play(audio, options = {}) {
42023
42944
  const format = options.format ?? "mp3";
42024
- const tempFile = join14(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
42945
+ const tempFile = join15(tmpdir3(), `assistants-audio-${Date.now()}.${format}`);
42025
42946
  writeFileSync4(tempFile, Buffer.from(audio));
42026
42947
  const player = this.resolvePlayer(format);
42027
42948
  if (!player) {
42028
42949
  throw new Error("No supported audio player found. Install afplay, ffplay, mpg123, or aplay.");
42029
42950
  }
42030
- await new Promise((resolve4, reject) => {
42951
+ await new Promise((resolve5, reject) => {
42031
42952
  this.playing = true;
42032
42953
  this.currentProcess = spawn(player.command, [...player.args, tempFile], { stdio: "ignore" });
42033
42954
  this.currentProcess.on("close", () => {
42034
42955
  this.playing = false;
42035
42956
  this.currentProcess = null;
42036
- unlink3(tempFile, () => {});
42037
- resolve4();
42957
+ unlink4(tempFile, () => {});
42958
+ resolve5();
42038
42959
  });
42039
42960
  this.currentProcess.on("error", (error) => {
42040
42961
  this.playing = false;
42041
42962
  this.currentProcess = null;
42042
- unlink3(tempFile, () => {});
42963
+ unlink4(tempFile, () => {});
42043
42964
  reject(error);
42044
42965
  });
42045
42966
  });
@@ -42089,8 +43010,8 @@ class AudioPlayer {
42089
43010
  // packages/core/src/voice/recorder.ts
42090
43011
  import { spawn as spawn2 } from "child_process";
42091
43012
  import { tmpdir as tmpdir4 } from "os";
42092
- import { join as join15 } from "path";
42093
- 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";
42094
43015
  class AudioRecorder {
42095
43016
  currentProcess = null;
42096
43017
  async record(options = {}) {
@@ -42100,17 +43021,17 @@ class AudioRecorder {
42100
43021
  const duration = options.durationSeconds ?? 5;
42101
43022
  const sampleRate = options.sampleRate ?? 16000;
42102
43023
  const channels = options.channels ?? 1;
42103
- const output = join15(tmpdir4(), `assistants-record-${Date.now()}.wav`);
43024
+ const output = join16(tmpdir4(), `assistants-record-${Date.now()}.wav`);
42104
43025
  const recorder = this.resolveRecorder(sampleRate, channels, duration, output);
42105
43026
  if (!recorder) {
42106
43027
  throw new Error("No supported audio recorder found. Install sox or ffmpeg.");
42107
43028
  }
42108
- await new Promise((resolve4, reject) => {
43029
+ await new Promise((resolve5, reject) => {
42109
43030
  this.currentProcess = spawn2(recorder.command, recorder.args, { stdio: "ignore" });
42110
43031
  this.currentProcess.on("close", (code) => {
42111
43032
  this.currentProcess = null;
42112
43033
  if (code === 0) {
42113
- resolve4();
43034
+ resolve5();
42114
43035
  } else {
42115
43036
  reject(new Error("Audio recording failed."));
42116
43037
  }
@@ -42121,7 +43042,7 @@ class AudioRecorder {
42121
43042
  });
42122
43043
  });
42123
43044
  const data = readFileSync5(output);
42124
- unlink4(output, () => {});
43045
+ unlink5(output, () => {});
42125
43046
  return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
42126
43047
  }
42127
43048
  stop() {
@@ -42293,14 +43214,14 @@ class VoiceManager {
42293
43214
  // packages/core/src/identity/assistant-manager.ts
42294
43215
  init_src();
42295
43216
  import { existsSync as existsSync10 } from "fs";
42296
- import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile6, rm as rm2 } from "fs/promises";
42297
- 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";
42298
43219
 
42299
43220
  // packages/core/src/identity/identity-manager.ts
42300
43221
  init_src();
42301
43222
  import { existsSync as existsSync9 } from "fs";
42302
- import { mkdir as mkdir3, readFile as readFile5, writeFile as writeFile5, rm } from "fs/promises";
42303
- 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";
42304
43225
  var DEFAULT_PROFILE = {
42305
43226
  displayName: "Assistant",
42306
43227
  timezone: "UTC",
@@ -42330,22 +43251,22 @@ class IdentityManager {
42330
43251
  this.basePath = basePath;
42331
43252
  }
42332
43253
  get identitiesRoot() {
42333
- return join16(this.basePath, "assistants", this.assistantId, "identities");
43254
+ return join17(this.basePath, "assistants", this.assistantId, "identities");
42334
43255
  }
42335
43256
  get indexPath() {
42336
- return join16(this.identitiesRoot, "index.json");
43257
+ return join17(this.identitiesRoot, "index.json");
42337
43258
  }
42338
43259
  get activePath() {
42339
- return join16(this.identitiesRoot, "active.json");
43260
+ return join17(this.identitiesRoot, "active.json");
42340
43261
  }
42341
43262
  identityPath(id) {
42342
- return join16(this.identitiesRoot, `${id}.json`);
43263
+ return join17(this.identitiesRoot, `${id}.json`);
42343
43264
  }
42344
43265
  assistantConfigPath() {
42345
- return join16(this.basePath, "assistants", this.assistantId, "config.json");
43266
+ return join17(this.basePath, "assistants", this.assistantId, "config.json");
42346
43267
  }
42347
43268
  async initialize() {
42348
- await mkdir3(this.identitiesRoot, { recursive: true });
43269
+ await mkdir4(this.identitiesRoot, { recursive: true });
42349
43270
  const index = await this.readIndex();
42350
43271
  for (const id of index.identities) {
42351
43272
  const identity = await this.readIdentity(id);
@@ -42452,7 +43373,7 @@ class IdentityManager {
42452
43373
  return { identities: [] };
42453
43374
  }
42454
43375
  try {
42455
- const raw = await readFile5(this.indexPath, "utf-8");
43376
+ const raw = await readFile7(this.indexPath, "utf-8");
42456
43377
  const data = JSON.parse(raw);
42457
43378
  return { identities: Array.isArray(data.identities) ? data.identities : [] };
42458
43379
  } catch {
@@ -42464,33 +43385,33 @@ class IdentityManager {
42464
43385
  if (!index.identities.includes(id)) {
42465
43386
  index.identities.push(id);
42466
43387
  }
42467
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43388
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42468
43389
  }
42469
43390
  async removeFromIndex(id) {
42470
43391
  const index = await this.readIndex();
42471
43392
  index.identities = index.identities.filter((identityId) => identityId !== id);
42472
- await writeFile5(this.indexPath, JSON.stringify(index, null, 2));
43393
+ await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
42473
43394
  }
42474
43395
  async readIdentity(id) {
42475
43396
  const path2 = this.identityPath(id);
42476
43397
  if (!existsSync9(path2))
42477
43398
  return null;
42478
43399
  try {
42479
- const raw = await readFile5(path2, "utf-8");
43400
+ const raw = await readFile7(path2, "utf-8");
42480
43401
  return JSON.parse(raw);
42481
43402
  } catch {
42482
43403
  return null;
42483
43404
  }
42484
43405
  }
42485
43406
  async persistIdentity(identity) {
42486
- await mkdir3(this.identitiesRoot, { recursive: true });
42487
- 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));
42488
43409
  }
42489
43410
  async readActive() {
42490
43411
  if (!existsSync9(this.activePath))
42491
43412
  return null;
42492
43413
  try {
42493
- const raw = await readFile5(this.activePath, "utf-8");
43414
+ const raw = await readFile7(this.activePath, "utf-8");
42494
43415
  const data = JSON.parse(raw);
42495
43416
  return data.id || null;
42496
43417
  } catch {
@@ -42499,13 +43420,13 @@ class IdentityManager {
42499
43420
  }
42500
43421
  async setActive(id) {
42501
43422
  this.activeId = id;
42502
- await writeFile5(this.activePath, JSON.stringify({ id }, null, 2));
43423
+ await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
42503
43424
  }
42504
43425
  async loadAssistant() {
42505
43426
  if (!existsSync9(this.assistantConfigPath()))
42506
43427
  return null;
42507
43428
  try {
42508
- const raw = await readFile5(this.assistantConfigPath(), "utf-8");
43429
+ const raw = await readFile7(this.assistantConfigPath(), "utf-8");
42509
43430
  return JSON.parse(raw);
42510
43431
  } catch {
42511
43432
  return null;
@@ -42526,19 +43447,19 @@ class AssistantManager {
42526
43447
  this.basePath = basePath;
42527
43448
  }
42528
43449
  get assistantsRoot() {
42529
- return join17(this.basePath, "assistants");
43450
+ return join18(this.basePath, "assistants");
42530
43451
  }
42531
43452
  get indexPath() {
42532
- return join17(this.assistantsRoot, "index.json");
43453
+ return join18(this.assistantsRoot, "index.json");
42533
43454
  }
42534
43455
  get activePath() {
42535
- return join17(this.basePath, "active.json");
43456
+ return join18(this.basePath, "active.json");
42536
43457
  }
42537
43458
  assistantConfigPath(id) {
42538
- return join17(this.assistantsRoot, id, "config.json");
43459
+ return join18(this.assistantsRoot, id, "config.json");
42539
43460
  }
42540
43461
  async initialize() {
42541
- await mkdir4(this.assistantsRoot, { recursive: true });
43462
+ await mkdir5(this.assistantsRoot, { recursive: true });
42542
43463
  const index = await this.readIndex();
42543
43464
  for (const id of index.assistants) {
42544
43465
  const assistant = await this.readAssistant(id);
@@ -42589,7 +43510,7 @@ class AssistantManager {
42589
43510
  if (!this.assistants.has(id)) {
42590
43511
  throw new Error(`Assistant ${id} not found`);
42591
43512
  }
42592
- await rm2(join17(this.assistantsRoot, id), { recursive: true, force: true });
43513
+ await rm2(join18(this.assistantsRoot, id), { recursive: true, force: true });
42593
43514
  this.assistants.delete(id);
42594
43515
  await this.removeFromIndex(id);
42595
43516
  if (this.activeId === id) {
@@ -42624,7 +43545,7 @@ class AssistantManager {
42624
43545
  return { assistants: [] };
42625
43546
  }
42626
43547
  try {
42627
- const raw = await readFile6(this.indexPath, "utf-8");
43548
+ const raw = await readFile8(this.indexPath, "utf-8");
42628
43549
  const data = JSON.parse(raw);
42629
43550
  return { assistants: Array.isArray(data.assistants) ? data.assistants : [] };
42630
43551
  } catch {
@@ -42636,34 +43557,34 @@ class AssistantManager {
42636
43557
  if (!index.assistants.includes(id)) {
42637
43558
  index.assistants.push(id);
42638
43559
  }
42639
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43560
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42640
43561
  }
42641
43562
  async removeFromIndex(id) {
42642
43563
  const index = await this.readIndex();
42643
43564
  index.assistants = index.assistants.filter((assistantId) => assistantId !== id);
42644
- await writeFile6(this.indexPath, JSON.stringify(index, null, 2));
43565
+ await writeFile7(this.indexPath, JSON.stringify(index, null, 2));
42645
43566
  }
42646
43567
  async readAssistant(id) {
42647
43568
  const configPath = this.assistantConfigPath(id);
42648
43569
  if (!existsSync10(configPath))
42649
43570
  return null;
42650
43571
  try {
42651
- const raw = await readFile6(configPath, "utf-8");
43572
+ const raw = await readFile8(configPath, "utf-8");
42652
43573
  return JSON.parse(raw);
42653
43574
  } catch {
42654
43575
  return null;
42655
43576
  }
42656
43577
  }
42657
43578
  async persistAssistant(assistant) {
42658
- const dir = join17(this.assistantsRoot, assistant.id);
42659
- await mkdir4(dir, { recursive: true });
42660
- 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));
42661
43582
  }
42662
43583
  async readActive() {
42663
43584
  if (!existsSync10(this.activePath))
42664
43585
  return null;
42665
43586
  try {
42666
- const raw = await readFile6(this.activePath, "utf-8");
43587
+ const raw = await readFile8(this.activePath, "utf-8");
42667
43588
  const data = JSON.parse(raw);
42668
43589
  return data.id || null;
42669
43590
  } catch {
@@ -42672,7 +43593,7 @@ class AssistantManager {
42672
43593
  }
42673
43594
  async setActive(id) {
42674
43595
  this.activeId = id;
42675
- await writeFile6(this.activePath, JSON.stringify({ id }, null, 2));
43596
+ await writeFile7(this.activePath, JSON.stringify({ id }, null, 2));
42676
43597
  }
42677
43598
  }
42678
43599
  // packages/core/src/agent/loop.ts
@@ -42717,6 +43638,8 @@ class AgentLoop {
42717
43638
  assistantManager = null;
42718
43639
  identityManager = null;
42719
43640
  identityContext = null;
43641
+ projectContext = null;
43642
+ activeProjectId = null;
42720
43643
  assistantId = null;
42721
43644
  onChunk;
42722
43645
  onToolStart;
@@ -42729,7 +43652,7 @@ class AgentLoop {
42729
43652
  this.context = new AgentContext;
42730
43653
  this.toolRegistry = new ToolRegistry;
42731
43654
  this.toolRegistry.setErrorAggregator(this.errorAggregator);
42732
- this.connectorBridge = new ConnectorBridge;
43655
+ this.connectorBridge = new ConnectorBridge(this.cwd);
42733
43656
  this.skillLoader = new SkillLoader;
42734
43657
  this.skillExecutor = new SkillExecutor;
42735
43658
  this.hookLoader = new HookLoader;
@@ -43032,9 +43955,13 @@ class AgentLoop {
43032
43955
  });
43033
43956
  if (preHookResult?.updatedInput) {
43034
43957
  toolCall.input = { ...preHookResult.updatedInput };
43035
- if (toolCall.input.cwd === undefined) {
43036
- toolCall.input.cwd = this.cwd;
43037
- }
43958
+ }
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;
43038
43965
  }
43039
43966
  if (preHookResult?.continue === false || preHookResult?.permissionDecision === "deny") {
43040
43967
  const blockedResult = {
@@ -43158,6 +44085,13 @@ class AgentLoop {
43158
44085
  switchIdentity: async (identityId) => {
43159
44086
  await this.switchIdentity(identityId);
43160
44087
  },
44088
+ getActiveProjectId: () => this.activeProjectId,
44089
+ setActiveProjectId: (projectId) => {
44090
+ this.activeProjectId = projectId;
44091
+ },
44092
+ setProjectContext: (content) => {
44093
+ this.setProjectContext(content);
44094
+ },
43161
44095
  getVoiceState: () => this.getVoiceState(),
43162
44096
  enableVoice: () => {
43163
44097
  if (!this.voiceManager) {
@@ -43345,6 +44279,22 @@ class AgentLoop {
43345
44279
  getSessionId() {
43346
44280
  return this.sessionId;
43347
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
+ }
43348
44298
  clearConversation() {
43349
44299
  this.resetContext();
43350
44300
  }
@@ -43356,7 +44306,7 @@ class AgentLoop {
43356
44306
  const heartbeatConfig = this.buildHeartbeatConfig(this.config);
43357
44307
  if (!heartbeatConfig)
43358
44308
  return;
43359
- const statePath = join18(getConfigDir(), "state", `${this.sessionId}.json`);
44309
+ const statePath = join19(getConfigDir(), "state", `${this.sessionId}.json`);
43360
44310
  this.heartbeatManager = new HeartbeatManager(heartbeatConfig);
43361
44311
  this.heartbeatPersistence = new StatePersistence(statePath);
43362
44312
  this.heartbeatRecovery = new RecoveryManager(this.heartbeatPersistence, heartbeatConfig.persistPath, heartbeatConfig.staleThresholdMs, {
@@ -43405,7 +44355,7 @@ class AgentLoop {
43405
44355
  async startEnergySystem() {
43406
44356
  if (!this.config || this.config.energy?.enabled === false)
43407
44357
  return;
43408
- const statePath = join18(getConfigDir(), "energy", "state.json");
44358
+ const statePath = join19(getConfigDir(), "energy", "state.json");
43409
44359
  this.energyManager = new EnergyManager(this.config.energy, new EnergyStorage(statePath));
43410
44360
  await this.energyManager.initialize();
43411
44361
  this.refreshEnergyEffects();
@@ -43434,7 +44384,7 @@ ${effects.message}
43434
44384
  const delay = this.energyEffects?.processingDelayMs ?? 0;
43435
44385
  if (delay <= 0)
43436
44386
  return;
43437
- await new Promise((resolve4) => setTimeout(resolve4, delay));
44387
+ await new Promise((resolve5) => setTimeout(resolve5, delay));
43438
44388
  }
43439
44389
  applyEnergyPersonality(systemPrompt) {
43440
44390
  if (!systemPrompt)
@@ -43461,6 +44411,9 @@ ${effects.message}
43461
44411
  const now2 = Date.now();
43462
44412
  const due = await getDueSchedules(this.cwd, now2);
43463
44413
  for (const schedule of due) {
44414
+ if (schedule.sessionId && schedule.sessionId !== this.sessionId) {
44415
+ continue;
44416
+ }
43464
44417
  const locked = await acquireScheduleLock(this.cwd, schedule.id, this.sessionId);
43465
44418
  if (!locked)
43466
44419
  continue;
@@ -43490,7 +44443,7 @@ ${effects.message}
43490
44443
  if (!schedule)
43491
44444
  break;
43492
44445
  const current = await readSchedule(this.cwd, schedule.id);
43493
- if (!current || current.status !== "active" || !current.nextRunAt || current.nextRunAt > Date.now()) {
44446
+ if (!current || current.status !== "active" || !current.nextRunAt || current.nextRunAt > Date.now() || current.sessionId && current.sessionId !== this.sessionId) {
43494
44447
  await releaseScheduleLock(this.cwd, schedule.id, this.sessionId);
43495
44448
  continue;
43496
44449
  }
@@ -43542,6 +44495,9 @@ ${effects.message}
43542
44495
  if (this.extraSystemPrompt) {
43543
44496
  this.context.addSystemMessage(this.extraSystemPrompt);
43544
44497
  }
44498
+ if (this.projectContext) {
44499
+ this.setProjectContext(this.projectContext);
44500
+ }
43545
44501
  this.contextManager?.refreshState(this.context.getMessages());
43546
44502
  }
43547
44503
  buildSystemPrompt(messages) {
@@ -43628,7 +44584,7 @@ ${this.identityContext}`);
43628
44584
  return null;
43629
44585
  const intervalMs = Math.max(1000, config.heartbeat?.intervalMs ?? 15000);
43630
44586
  const staleThresholdMs = Math.max(intervalMs * 2, config.heartbeat?.staleThresholdMs ?? 120000);
43631
- const persistPath = config.heartbeat?.persistPath ?? join18(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
44587
+ const persistPath = config.heartbeat?.persistPath ?? join19(getConfigDir(), "heartbeats", `${this.sessionId}.json`);
43632
44588
  return {
43633
44589
  intervalMs,
43634
44590
  staleThresholdMs,
@@ -43720,17 +44676,17 @@ function parseErrorCode(message) {
43720
44676
  init_src();
43721
44677
  // packages/core/src/migration/migrate-to-assistants.ts
43722
44678
  import { existsSync as existsSync11 } from "fs";
43723
- import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile7, rename, cp } from "fs/promises";
43724
- 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";
43725
44681
  import { homedir as homedir10 } from "os";
43726
44682
  var MIGRATION_MARKER = ".migrated-from-oldpal";
43727
44683
  async function ensureDir(path2) {
43728
- await mkdir5(path2, { recursive: true });
44684
+ await mkdir6(path2, { recursive: true });
43729
44685
  }
43730
44686
  async function copyIfExists(source, destination) {
43731
44687
  if (!existsSync11(source))
43732
44688
  return false;
43733
- await ensureDir(join19(destination, ".."));
44689
+ await ensureDir(join20(destination, ".."));
43734
44690
  await cp(source, destination, { recursive: true });
43735
44691
  return true;
43736
44692
  }
@@ -43738,7 +44694,7 @@ async function readJson(path2) {
43738
44694
  if (!existsSync11(path2))
43739
44695
  return null;
43740
44696
  try {
43741
- const raw = await readFile7(path2, "utf-8");
44697
+ const raw = await readFile9(path2, "utf-8");
43742
44698
  return JSON.parse(raw);
43743
44699
  } catch {
43744
44700
  return null;
@@ -43751,14 +44707,14 @@ async function migrateFromOldpal() {
43751
44707
  errors: []
43752
44708
  };
43753
44709
  const home = homedir10();
43754
- const oldPath = join19(home, ".oldpal");
43755
- const newPath = join19(home, ".assistants");
44710
+ const oldPath = join20(home, ".oldpal");
44711
+ const newPath = join20(home, ".assistants");
43756
44712
  if (!existsSync11(oldPath)) {
43757
44713
  result.success = true;
43758
44714
  return result;
43759
44715
  }
43760
44716
  if (existsSync11(newPath)) {
43761
- const marker = join19(newPath, "migration", MIGRATION_MARKER);
44717
+ const marker = join20(newPath, "migration", MIGRATION_MARKER);
43762
44718
  if (existsSync11(marker)) {
43763
44719
  result.success = true;
43764
44720
  return result;
@@ -43768,31 +44724,31 @@ async function migrateFromOldpal() {
43768
44724
  }
43769
44725
  try {
43770
44726
  await ensureDir(newPath);
43771
- await ensureDir(join19(newPath, "assistants"));
43772
- await ensureDir(join19(newPath, "shared", "skills"));
43773
- await ensureDir(join19(newPath, "logs"));
43774
- await ensureDir(join19(newPath, "migration"));
43775
- 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"));
43776
44732
  if (config) {
43777
- await writeFile7(join19(newPath, "config.json"), JSON.stringify(config, null, 2));
44733
+ await writeFile8(join20(newPath, "config.json"), JSON.stringify(config, null, 2));
43778
44734
  result.migrated.push("config.json");
43779
44735
  }
43780
- 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"))) {
43781
44737
  result.migrated.push("config.local.json");
43782
44738
  }
43783
- if (await copyIfExists(join19(oldPath, "hooks.json"), join19(newPath, "hooks.json"))) {
44739
+ if (await copyIfExists(join20(oldPath, "hooks.json"), join20(newPath, "hooks.json"))) {
43784
44740
  result.migrated.push("hooks.json");
43785
44741
  }
43786
- if (await copyIfExists(join19(oldPath, "commands"), join19(newPath, "commands"))) {
44742
+ if (await copyIfExists(join20(oldPath, "commands"), join20(newPath, "commands"))) {
43787
44743
  result.migrated.push("commands");
43788
44744
  }
43789
- if (await copyIfExists(join19(oldPath, "OLDPAL.md"), join19(newPath, "ASSISTANTS.md"))) {
44745
+ if (await copyIfExists(join20(oldPath, "OLDPAL.md"), join20(newPath, "ASSISTANTS.md"))) {
43790
44746
  result.migrated.push("ASSISTANTS.md");
43791
44747
  }
43792
- if (await copyIfExists(join19(oldPath, "skills"), join19(newPath, "shared", "skills"))) {
44748
+ if (await copyIfExists(join20(oldPath, "skills"), join20(newPath, "shared", "skills"))) {
43793
44749
  result.migrated.push("skills");
43794
44750
  }
43795
- if (await copyIfExists(join19(oldPath, "logs"), join19(newPath, "logs"))) {
44751
+ if (await copyIfExists(join20(oldPath, "logs"), join20(newPath, "logs"))) {
43796
44752
  result.migrated.push("logs");
43797
44753
  }
43798
44754
  const manager = new AssistantManager(newPath);
@@ -43807,10 +44763,10 @@ async function migrateFromOldpal() {
43807
44763
  const identityManager = manager.getIdentityManager(assistant.id);
43808
44764
  await identityManager.initialize();
43809
44765
  await identityManager.createIdentity({ name: "Default" });
43810
- 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"))) {
43811
44767
  result.migrated.push("sessions");
43812
44768
  }
43813
- 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));
43814
44770
  const backupPath = `${oldPath}.backup`;
43815
44771
  await rename(oldPath, backupPath);
43816
44772
  result.backupPath = backupPath;
@@ -43828,17 +44784,17 @@ init_src();
43828
44784
 
43829
44785
  // packages/core/src/logger.ts
43830
44786
  import { existsSync as existsSync12, mkdirSync as mkdirSync6, appendFileSync, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
43831
- import { join as join20 } from "path";
44787
+ import { join as join21 } from "path";
43832
44788
  class Logger {
43833
44789
  logDir;
43834
44790
  logFile;
43835
44791
  sessionId;
43836
44792
  constructor(sessionId, basePath) {
43837
44793
  this.sessionId = sessionId;
43838
- this.logDir = join20(basePath || getConfigDir(), "logs");
44794
+ this.logDir = join21(basePath || getConfigDir(), "logs");
43839
44795
  this.ensureDir(this.logDir);
43840
44796
  const date = new Date().toISOString().split("T")[0];
43841
- this.logFile = join20(this.logDir, `${date}.log`);
44797
+ this.logFile = join21(this.logDir, `${date}.log`);
43842
44798
  }
43843
44799
  ensureDir(dir) {
43844
44800
  if (!existsSync12(dir)) {
@@ -43882,9 +44838,9 @@ class SessionStorage {
43882
44838
  constructor(sessionId, basePath, assistantId) {
43883
44839
  this.sessionId = sessionId;
43884
44840
  const root = basePath || getConfigDir();
43885
- this.sessionsDir = assistantId ? join20(root, "assistants", assistantId, "sessions") : join20(root, "sessions");
44841
+ this.sessionsDir = assistantId ? join21(root, "assistants", assistantId, "sessions") : join21(root, "sessions");
43886
44842
  this.ensureDir(this.sessionsDir);
43887
- this.sessionFile = join20(this.sessionsDir, `${sessionId}.json`);
44843
+ this.sessionFile = join21(this.sessionsDir, `${sessionId}.json`);
43888
44844
  }
43889
44845
  ensureDir(dir) {
43890
44846
  if (!existsSync12(dir)) {
@@ -43910,7 +44866,7 @@ class SessionStorage {
43910
44866
  }
43911
44867
  static getActiveAssistantId() {
43912
44868
  try {
43913
- const activePath = join20(getConfigDir(), "active.json");
44869
+ const activePath = join21(getConfigDir(), "active.json");
43914
44870
  if (!existsSync12(activePath))
43915
44871
  return null;
43916
44872
  const raw = readFileSync6(activePath, "utf-8");
@@ -43924,12 +44880,12 @@ class SessionStorage {
43924
44880
  const root = getConfigDir();
43925
44881
  const resolvedId = assistantId ?? SessionStorage.getActiveAssistantId();
43926
44882
  if (resolvedId) {
43927
- const assistantDir = join20(root, "assistants", resolvedId, "sessions");
44883
+ const assistantDir = join21(root, "assistants", resolvedId, "sessions");
43928
44884
  if (existsSync12(assistantDir)) {
43929
44885
  return assistantDir;
43930
44886
  }
43931
44887
  }
43932
- return join20(root, "sessions");
44888
+ return join21(root, "sessions");
43933
44889
  }
43934
44890
  static listSessions(assistantId) {
43935
44891
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
@@ -43941,7 +44897,7 @@ class SessionStorage {
43941
44897
  if (!file.endsWith(".json"))
43942
44898
  continue;
43943
44899
  try {
43944
- const filePath = join20(sessionsDir, file);
44900
+ const filePath = join21(sessionsDir, file);
43945
44901
  const stat = Bun.file(filePath);
43946
44902
  const content = JSON.parse(readFileSync6(filePath, "utf-8"));
43947
44903
  sessions.push({
@@ -43961,7 +44917,7 @@ class SessionStorage {
43961
44917
  }
43962
44918
  static loadSession(sessionId, assistantId) {
43963
44919
  const sessionsDir = SessionStorage.resolveSessionsDir(assistantId);
43964
- const sessionFile = join20(sessionsDir, `${sessionId}.json`);
44920
+ const sessionFile = join21(sessionsDir, `${sessionId}.json`);
43965
44921
  try {
43966
44922
  if (!existsSync12(sessionFile))
43967
44923
  return null;
@@ -43975,15 +44931,15 @@ function initAssistantsDir() {
43975
44931
  const baseDir = getConfigDir();
43976
44932
  const dirs = [
43977
44933
  baseDir,
43978
- join20(baseDir, "logs"),
43979
- join20(baseDir, "assistants"),
43980
- join20(baseDir, "shared", "skills"),
43981
- join20(baseDir, "commands"),
43982
- join20(baseDir, "temp"),
43983
- join20(baseDir, "heartbeats"),
43984
- join20(baseDir, "state"),
43985
- join20(baseDir, "energy"),
43986
- 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")
43987
44943
  ];
43988
44944
  for (const dir of dirs) {
43989
44945
  if (!existsSync12(dir)) {
@@ -44026,6 +44982,11 @@ class EmbeddedClient {
44026
44982
  for (const callback of this.chunkCallbacks) {
44027
44983
  callback(chunk);
44028
44984
  }
44985
+ if (chunk.type === "done" || chunk.type === "error") {
44986
+ queueMicrotask(() => {
44987
+ this.drainQueue();
44988
+ });
44989
+ }
44029
44990
  },
44030
44991
  onToolStart: (toolCall) => {
44031
44992
  this.logger.info("Tool started", { tool: toolCall.name, input: toolCall.input });
@@ -44068,12 +45029,11 @@ class EmbeddedClient {
44068
45029
  if (!this.initialized) {
44069
45030
  await this.initialize();
44070
45031
  }
44071
- if (this.agent.isProcessing()) {
44072
- this.logger.info("Queuing message (agent busy)", { message, queueLength: this.messageQueue.length + 1 });
44073
- 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 });
44074
45035
  return;
44075
45036
  }
44076
- await this.processMessage(message);
44077
45037
  await this.drainQueue();
44078
45038
  }
44079
45039
  async processMessage(message) {
@@ -44464,10 +45424,13 @@ var COMMANDS = [
44464
45424
  { name: "/model", description: "show model information" },
44465
45425
  { name: "/skills", description: "list available skills" },
44466
45426
  { name: "/config", description: "show configuration" },
45427
+ { name: "/projects", description: "manage projects in this folder" },
45428
+ { name: "/plans", description: "manage project plans" },
44467
45429
  { name: "/connectors", description: "list available connectors" },
44468
45430
  { name: "/init", description: "initialize assistants in project" },
44469
45431
  { name: "/compact", description: "summarize to save context" },
44470
45432
  { name: "/memory", description: "show what AI remembers" },
45433
+ { name: "/context", description: "manage injected project context" },
44471
45434
  { name: "/feedback", description: "submit feedback on GitHub" },
44472
45435
  { name: "/schedule", description: "schedule a command" },
44473
45436
  { name: "/schedules", description: "list scheduled commands" },
@@ -44513,15 +45476,23 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44513
45476
  }, [value, autocompleteMode, skills]);
44514
45477
  const autocompleteItems = autocompleteMode === "skill" ? filteredSkills : filteredCommands;
44515
45478
  use_input_default((input, key) => {
44516
- if (key.tab && autocompleteItems.length > 0) {
44517
- const selected = autocompleteItems[selectedIndex] || autocompleteItems[0];
44518
- if (autocompleteMode === "skill") {
44519
- setValue("$" + selected.name + " ");
44520
- } else {
44521
- setValue(selected.name + " ");
45479
+ if (key.tab) {
45480
+ if (autocompleteItems.length > 0) {
45481
+ const selected = autocompleteItems[selectedIndex] || autocompleteItems[0];
45482
+ if (autocompleteMode === "skill") {
45483
+ setValue("$" + selected.name + " ");
45484
+ } else {
45485
+ setValue(selected.name + " ");
45486
+ }
45487
+ setSelectedIndex(0);
45488
+ return;
45489
+ }
45490
+ if (value.trim()) {
45491
+ onSubmit(value, "queue");
45492
+ setValue("");
45493
+ setSelectedIndex(0);
45494
+ return;
44522
45495
  }
44523
- setSelectedIndex(0);
44524
- return;
44525
45496
  }
44526
45497
  if (autocompleteItems.length > 0) {
44527
45498
  if (key.downArrow) {
@@ -44555,18 +45526,14 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44555
45526
  if (autocompleteMode === "command" && filteredCommands.length > 0 && !submittedValue.includes(" ")) {
44556
45527
  const selected = filteredCommands[selectedIndex] || filteredCommands[0];
44557
45528
  if (selected) {
44558
- if (isProcessing) {
44559
- onSubmit(selected.name, "queue");
44560
- } else {
44561
- onSubmit(selected.name, "normal");
44562
- }
45529
+ onSubmit(selected.name, isProcessing ? "inline" : "normal");
44563
45530
  setValue("");
44564
45531
  setSelectedIndex(0);
44565
45532
  return;
44566
45533
  }
44567
45534
  }
44568
45535
  if (isProcessing) {
44569
- onSubmit(submittedValue, "queue");
45536
+ onSubmit(submittedValue, "inline");
44570
45537
  } else {
44571
45538
  onSubmit(submittedValue, "normal");
44572
45539
  }
@@ -44577,7 +45544,7 @@ function Input({ onSubmit, isProcessing, queueLength = 0, commands, skills = []
44577
45544
  let placeholder = "Type a message...";
44578
45545
  if (isProcessing) {
44579
45546
  prompt = "\u22EF";
44580
- placeholder = queueLength > 0 ? "Type to queue another..." : "Type to queue (Enter) or interrupt (Shift+Enter)...";
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...";
44581
45548
  }
44582
45549
  const truncateDescription = (desc, maxLen = 60) => {
44583
45550
  if (desc.length <= maxLen)
@@ -44718,7 +45685,12 @@ var import_react24 = __toESM(require_react(), 1);
44718
45685
 
44719
45686
  // packages/terminal/src/components/Markdown.tsx
44720
45687
  var jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
44721
- 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
+ }
44722
45694
  const { columns } = use_stdout_default();
44723
45695
  const maxWidth = columns ? Math.max(20, columns - 2) : undefined;
44724
45696
  const rendered = parseMarkdown(content, { maxWidth });
@@ -44726,6 +45698,9 @@ function Markdown({ content }) {
44726
45698
  children: rendered
44727
45699
  }, undefined, false, undefined, this);
44728
45700
  }
45701
+ function renderMarkdown(text, options) {
45702
+ return parseMarkdown(text, { maxWidth: options?.maxWidth });
45703
+ }
44729
45704
  function parseMarkdown(text, options) {
44730
45705
  let result = text;
44731
45706
  const codeBlocks = [];
@@ -44751,7 +45726,7 @@ function parseMarkdown(text, options) {
44751
45726
  result = result.replace(/\b(Building|Running|Working|Queued|Pending|Connecting)\b/gi, (match) => source_default.yellow(match));
44752
45727
  result = result.replace(/\b(Success|Succeeded|Done|Complete|Completed|Connected|Authenticated)\b/gi, (match) => source_default.green(match));
44753
45728
  result = result.replace(/\b(Error|Failed|Failure|Denied|Blocked)\b/gi, (match) => source_default.red(match));
44754
- result = formatMarkdownTables(result);
45729
+ result = formatMarkdownTables(result, options?.maxWidth);
44755
45730
  result = result.replace(/@@BLOCKSECTION(\d+)@@/g, (_, index) => {
44756
45731
  const section = blockSections[parseInt(index, 10)];
44757
45732
  if (!section)
@@ -44765,6 +45740,7 @@ function parseMarkdown(text, options) {
44765
45740
  });
44766
45741
  return result.trimEnd();
44767
45742
  }
45743
+ var ALLOWED_BLOCK_TYPES = new Set(["info", "success", "warning", "error", "note", "command"]);
44768
45744
  function extractBlockSections(text, blocks) {
44769
45745
  const lines = text.split(`
44770
45746
  `);
@@ -44793,6 +45769,9 @@ function extractBlockSections(text, blocks) {
44793
45769
  i += 1;
44794
45770
  continue;
44795
45771
  }
45772
+ if (parsed.warning) {
45773
+ output.push(createMalformedBlock(blocks, indent, "grid", parsed.warning));
45774
+ }
44796
45775
  const bodyLines = stripIndent(parsed.bodyLines, indent);
44797
45776
  const body = bodyLines.join(`
44798
45777
  `);
@@ -44806,7 +45785,7 @@ function extractBlockSections(text, blocks) {
44806
45785
  const indent = blockMatch[1] ?? "";
44807
45786
  const header = blockMatch[2] ?? "";
44808
45787
  const attrs = parseAttributes(header);
44809
- const type = String(attrs.type || "info");
45788
+ let type = String(attrs.type || "info");
44810
45789
  const title = attrs.title ? String(attrs.title) : undefined;
44811
45790
  const parsed = parseDelimitedBlock(lines, i, indent);
44812
45791
  if (!parsed) {
@@ -44815,6 +45794,14 @@ function extractBlockSections(text, blocks) {
44815
45794
  i += 1;
44816
45795
  continue;
44817
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
+ }
44818
45805
  const body = stripIndent(parsed.bodyLines, indent).join(`
44819
45806
  `);
44820
45807
  blocks.push({ kind: "block", type, title, body, indent });
@@ -44831,6 +45818,9 @@ function extractBlockSections(text, blocks) {
44831
45818
  i += 1;
44832
45819
  continue;
44833
45820
  }
45821
+ if (parsed.warning) {
45822
+ output.push(createMalformedBlock(blocks, indent, "report", parsed.warning));
45823
+ }
44834
45824
  const body = stripIndent(parsed.bodyLines, indent).join(`
44835
45825
  `);
44836
45826
  blocks.push({ kind: "report", body, indent });
@@ -44862,10 +45852,14 @@ function extractCards(body) {
44862
45852
  const title = attrs.title ? String(attrs.title) : undefined;
44863
45853
  const bodyLines = [];
44864
45854
  let closed = false;
45855
+ let indentWarning;
44865
45856
  i += 1;
44866
45857
  while (i < lines.length) {
44867
45858
  const current = lines[i];
44868
- 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
+ }
44869
45863
  closed = true;
44870
45864
  i += 1;
44871
45865
  break;
@@ -44882,6 +45876,13 @@ function extractCards(body) {
44882
45876
  break;
44883
45877
  }
44884
45878
  const stripped = stripIndent(bodyLines, indent);
45879
+ if (indentWarning) {
45880
+ cards.push({
45881
+ type: "warning",
45882
+ title: "Malformed card",
45883
+ body: indentWarning
45884
+ });
45885
+ }
44885
45886
  cards.push({ type, title, body: stripped.join(`
44886
45887
  `) });
44887
45888
  }
@@ -44890,6 +45891,7 @@ function extractCards(body) {
44890
45891
  function parseDelimitedBlock(lines, startIndex, indent) {
44891
45892
  const bodyLines = [];
44892
45893
  let openCards = 0;
45894
+ let warning;
44893
45895
  let i = startIndex + 1;
44894
45896
  while (i < lines.length) {
44895
45897
  const current = lines[i];
@@ -44900,14 +45902,18 @@ function parseDelimitedBlock(lines, startIndex, indent) {
44900
45902
  i += 1;
44901
45903
  continue;
44902
45904
  }
44903
- if (trimmed === ":::" && current.startsWith(indent)) {
45905
+ if (trimmed === ":::") {
45906
+ const indentMismatch = indent.length > 0 && !current.startsWith(indent);
44904
45907
  if (openCards > 0) {
44905
45908
  openCards -= 1;
44906
45909
  bodyLines.push(current);
44907
45910
  i += 1;
44908
45911
  continue;
44909
45912
  }
44910
- 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 };
44911
45917
  }
44912
45918
  bodyLines.push(current);
44913
45919
  i += 1;
@@ -45074,7 +46080,7 @@ function formatBoxRow(line, width) {
45074
46080
  const padded = len < width ? line + " ".repeat(width - len) : line;
45075
46081
  return `\u2502 ${padded} \u2502`;
45076
46082
  }
45077
- function formatMarkdownTables(text) {
46083
+ function formatMarkdownTables(text, maxWidth) {
45078
46084
  const lines = text.split(`
45079
46085
  `);
45080
46086
  const output = [];
@@ -45092,7 +46098,7 @@ function formatMarkdownTables(text) {
45092
46098
  rows.push(parseTableRow(lines[i]));
45093
46099
  i += 1;
45094
46100
  }
45095
- const table = renderTable(header, rows);
46101
+ const table = renderTable(header, rows, maxWidth);
45096
46102
  output.push(...table);
45097
46103
  continue;
45098
46104
  }
@@ -45107,7 +46113,7 @@ function parseTableRow(line) {
45107
46113
  const withoutEdges = trimmed.replace(/^\|/, "").replace(/\|$/, "");
45108
46114
  return withoutEdges.split("|").map((cell) => cell.trim());
45109
46115
  }
45110
- function renderTable(header, rows) {
46116
+ function renderTable(header, rows, maxWidth) {
45111
46117
  const colCount = Math.max(header.length, ...rows.map((r) => r.length));
45112
46118
  const widths = new Array(colCount).fill(0);
45113
46119
  const allRows = [header, ...rows];
@@ -45119,11 +46125,29 @@ function renderTable(header, rows) {
45119
46125
  widths[i] = len;
45120
46126
  }
45121
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
+ }
45122
46145
  const pad = (value, width) => {
45123
- const len = stripAnsi2(value).length;
46146
+ const rendered = width > 0 ? truncateAnsi(value, width) : value;
46147
+ const len = stripAnsi2(rendered).length;
45124
46148
  if (len >= width)
45125
- return value;
45126
- return value + " ".repeat(width - len);
46149
+ return rendered;
46150
+ return rendered + " ".repeat(width - len);
45127
46151
  };
45128
46152
  const top = "\u250C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C") + "\u2510";
45129
46153
  const mid = "\u251C" + widths.map((w) => "\u2500".repeat(w + 2)).join("\u253C") + "\u2524";
@@ -45201,7 +46225,8 @@ function renderReport(body, maxWidth, indent = "") {
45201
46225
  }
45202
46226
  if (tableLines.length > 0) {
45203
46227
  output.push(indent + source_default.bold("Detailed Status Table"));
45204
- const rendered = renderReportTable(tableLines, indent);
46228
+ const adjustedWidth = maxWidth ? Math.max(20, maxWidth - indent.length) : undefined;
46229
+ const rendered = renderReportTable(tableLines, indent, adjustedWidth);
45205
46230
  output.push(...rendered);
45206
46231
  }
45207
46232
  return output.join(`
@@ -45230,7 +46255,7 @@ function renderProgressLine(label, value, labelWidth, barWidth) {
45230
46255
  const bar = source_default.gray("\u2591".repeat(empty));
45231
46256
  return `${label.padEnd(labelWidth)} [${fill}${bar}] ${value}%`;
45232
46257
  }
45233
- function renderReportTable(lines, indent) {
46258
+ function renderReportTable(lines, indent, maxWidth) {
45234
46259
  const tableLines = lines.map((line) => line.trim()).filter(Boolean);
45235
46260
  if (tableLines.length < 2)
45236
46261
  return [];
@@ -45254,7 +46279,7 @@ function renderReportTable(lines, indent) {
45254
46279
  }
45255
46280
  return next;
45256
46281
  });
45257
- return renderTable(header, styledRows).map((line) => indent + line);
46282
+ return renderTable(header, styledRows, maxWidth).map((line) => indent + line);
45258
46283
  }
45259
46284
  function decoratePriority(value) {
45260
46285
  const normalized = value.toLowerCase();
@@ -45324,6 +46349,23 @@ function wrapAnsiLine(line, width) {
45324
46349
  function truncateAnsi(line, width) {
45325
46350
  if (stripAnsi2(line).length <= width)
45326
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
+ }
45327
46369
  const suffix = "...";
45328
46370
  const target = Math.max(0, width - suffix.length);
45329
46371
  let current = "";
@@ -45343,6 +46385,42 @@ function truncateAnsi(line, width) {
45343
46385
  return current + suffix;
45344
46386
  }
45345
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
+
45346
46424
  // packages/terminal/src/components/Messages.tsx
45347
46425
  var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
45348
46426
  function Messages4({
@@ -45352,19 +46430,28 @@ function Messages4({
45352
46430
  currentToolCall,
45353
46431
  lastToolResult,
45354
46432
  activityLog = [],
45355
- scrollOffset = 0,
45356
- maxVisible = 10,
46433
+ scrollOffsetLines = 0,
46434
+ maxVisibleLines = 10,
45357
46435
  queuedMessageIds
45358
46436
  }) {
45359
46437
  const [now2, setNow] = import_react24.useState(Date.now());
45360
46438
  const combinedMessages = import_react24.useMemo(() => [...messages, ...streamingMessages], [messages, streamingMessages]);
45361
- const endIndex = combinedMessages.length - scrollOffset;
45362
- const startIndex = Math.max(0, endIndex - maxVisible);
45363
- 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);
45364
46452
  const historicalCount = messages.length;
45365
- const splitIndex = Math.max(0, Math.min(visibleCombined.length, historicalCount - startIndex));
45366
- const visibleMessages = visibleCombined.slice(0, splitIndex);
45367
- 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);
45368
46455
  const groupedMessages = groupConsecutiveToolMessages(visibleMessages);
45369
46456
  const historicalItems = groupedMessages.map((group) => {
45370
46457
  if (group.type === "single") {
@@ -45612,13 +46699,13 @@ function MessageBubble({ message, queuedMessageIds }) {
45612
46699
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45613
46700
  flexGrow: 1,
45614
46701
  children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Markdown, {
45615
- content: message.content
46702
+ content: message.content,
46703
+ preRendered: Boolean(message.__rendered)
45616
46704
  }, undefined, false, undefined, this)
45617
46705
  }, undefined, false, undefined, this)
45618
46706
  ]
45619
46707
  }, undefined, true, undefined, this),
45620
46708
  toolCalls.length > 0 && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45621
- marginLeft: hasContent ? 2 : 0,
45622
46709
  marginTop: hasContent ? 1 : 0,
45623
46710
  children: /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(ToolCallPanel, {
45624
46711
  toolCalls,
@@ -45634,6 +46721,8 @@ function ToolCallPanel({
45634
46721
  }) {
45635
46722
  if (toolCalls.length === 0)
45636
46723
  return null;
46724
+ const { columns } = use_stdout_default();
46725
+ const panelWidth = columns ? Math.max(24, columns - 4) : undefined;
45637
46726
  const resultMap = new Map;
45638
46727
  for (const result of toolResults || []) {
45639
46728
  resultMap.set(result.toolCallId, result);
@@ -45646,7 +46735,7 @@ function ToolCallPanel({
45646
46735
  borderStyle: "round",
45647
46736
  borderColor,
45648
46737
  paddingX: 1,
45649
- width: "100%",
46738
+ width: panelWidth ?? "100%",
45650
46739
  children: [
45651
46740
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45652
46741
  justifyContent: "space-between",
@@ -45672,6 +46761,8 @@ function ToolCallPanel({
45672
46761
  const statusColor = result ? result.isError ? "red" : "green" : "yellow";
45673
46762
  const displayName = getToolDisplayName(toolCall);
45674
46763
  const context2 = getToolContext(toolCall);
46764
+ const maxLine = panelWidth ? Math.max(20, panelWidth - 8) : 80;
46765
+ const summaryLine = truncate(formatToolCall(toolCall), maxLine);
45675
46766
  return /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45676
46767
  flexDirection: "column",
45677
46768
  marginTop: 1,
@@ -45701,7 +46792,7 @@ function ToolCallPanel({
45701
46792
  }, undefined, true, undefined, this),
45702
46793
  /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Text, {
45703
46794
  dimColor: true,
45704
- children: formatToolCall(toolCall)
46795
+ children: summaryLine
45705
46796
  }, undefined, false, undefined, this),
45706
46797
  result && /* @__PURE__ */ jsx_dev_runtime3.jsxDEV(Box_default, {
45707
46798
  marginLeft: 2,
@@ -45736,7 +46827,7 @@ function getToolContext(toolCall) {
45736
46827
  return truncate(String(input.pattern || ""), 20);
45737
46828
  case "schedule":
45738
46829
  return String(input.action || "");
45739
- case "feedback":
46830
+ case "submit_feedback":
45740
46831
  return String(input.type || "feedback");
45741
46832
  case "web_search":
45742
46833
  return truncate(String(input.query || ""), 20);
@@ -46017,46 +47108,7 @@ function formatSearchResult(content) {
46017
47108
 
46018
47109
  // packages/terminal/src/components/Status.tsx
46019
47110
  var import_react25 = __toESM(require_react(), 1);
46020
-
46021
- // packages/terminal/src/components/EnergyBar.tsx
46022
47111
  var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
46023
- function EnergyBar({ current, max }) {
46024
- const safeMax = Math.max(1, max);
46025
- const percentage = Math.round(current / safeMax * 100);
46026
- const barWidth = 16;
46027
- const filled = Math.round(current / safeMax * barWidth);
46028
- const empty = Math.max(0, barWidth - filled);
46029
- const color = percentage > 50 ? "green" : percentage > 20 ? "yellow" : "red";
46030
- const emoji = percentage > 70 ? "\u26A1" : percentage > 30 ? "\uD83D\uDD0B" : "\uD83E\uDEAB";
46031
- return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46032
- children: [
46033
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46034
- children: [
46035
- emoji,
46036
- " "
46037
- ]
46038
- }, undefined, true, undefined, this),
46039
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46040
- color,
46041
- children: "\u2588".repeat(filled)
46042
- }, undefined, false, undefined, this),
46043
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46044
- color: "gray",
46045
- children: "\u2591".repeat(empty)
46046
- }, undefined, false, undefined, this),
46047
- /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46048
- children: [
46049
- " ",
46050
- percentage,
46051
- "%"
46052
- ]
46053
- }, undefined, true, undefined, this)
46054
- ]
46055
- }, undefined, true, undefined, this);
46056
- }
46057
-
46058
- // packages/terminal/src/components/Status.tsx
46059
- var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
46060
47112
  function Status({
46061
47113
  isProcessing,
46062
47114
  cwd: cwd2,
@@ -46094,74 +47146,51 @@ function Status({
46094
47146
  let contextInfo = "";
46095
47147
  if (tokenUsage && tokenUsage.maxContextTokens > 0) {
46096
47148
  const percent = Math.round(tokenUsage.totalTokens / tokenUsage.maxContextTokens * 100);
46097
- contextInfo = `${percent}% context`;
47149
+ contextInfo = `${percent}%`;
46098
47150
  }
46099
- const sessionInfo = sessionIndex && sessionCount ? `Session ${sessionIndex}/${sessionCount}` : "";
46100
- const bgIndicator = backgroundProcessingCount > 0 ? ` (${backgroundProcessingCount} processing)` : "";
46101
- const voiceInfo = voiceState?.enabled ? `voice ${voiceState.isListening ? "listening" : voiceState.isSpeaking ? "speaking" : "on"}` : "";
46102
- const identityLabel = identityInfo?.assistant && identityInfo?.identity ? `${identityInfo.assistant.name} \xB7 ${identityInfo.identity.name}` : "";
46103
- 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, {
46104
47155
  marginTop: 1,
46105
47156
  justifyContent: "space-between",
46106
47157
  children: [
46107
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47158
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46108
47159
  dimColor: true,
46109
47160
  children: [
46110
- "/help for commands",
46111
- sessionCount && sessionCount > 1 ? " | Ctrl+S sessions" : ""
47161
+ "/help",
47162
+ sessionCount && sessionCount > 1 ? " \xB7 Ctrl+S" : ""
46112
47163
  ]
46113
47164
  }, undefined, true, undefined, this),
46114
- /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
47165
+ /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
46115
47166
  children: [
46116
- energyState && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
46117
- marginRight: 2,
46118
- children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(EnergyBar, {
46119
- current: energyState.current,
46120
- max: energyState.max
46121
- }, undefined, false, undefined, this)
46122
- }, undefined, false, undefined, this),
46123
- identityLabel && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46124
- dimColor: true,
46125
- children: [
46126
- identityLabel,
46127
- " \xB7 "
46128
- ]
46129
- }, undefined, true, undefined, this),
46130
- voiceInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47167
+ voiceIcon && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46131
47168
  dimColor: true,
46132
47169
  children: [
46133
- voiceInfo,
46134
- " \xB7 "
47170
+ voiceIcon,
47171
+ " "
46135
47172
  ]
46136
47173
  }, undefined, true, undefined, this),
46137
- isProcessing && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47174
+ isProcessing && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46138
47175
  dimColor: true,
46139
- children: "esc to stop \xB7 "
47176
+ children: "esc \xB7 "
46140
47177
  }, undefined, false, undefined, this),
46141
- sessionInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47178
+ sessionInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46142
47179
  dimColor: true,
46143
47180
  children: [
46144
47181
  sessionInfo,
46145
47182
  bgIndicator,
46146
- contextInfo ? " \xB7 " : ""
47183
+ " \xB7 "
46147
47184
  ]
46148
47185
  }, undefined, true, undefined, this),
46149
- contextInfo && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47186
+ contextInfo && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46150
47187
  dimColor: true,
46151
47188
  children: contextInfo
46152
47189
  }, undefined, false, undefined, this),
46153
- sessionId && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46154
- dimColor: true,
46155
- children: [
46156
- sessionInfo || contextInfo ? " \xB7 " : "",
46157
- "id ",
46158
- sessionId
46159
- ]
46160
- }, undefined, true, undefined, this),
46161
- isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
47190
+ isProcessing && processingStartTime && /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
46162
47191
  dimColor: true,
46163
47192
  children: [
46164
- " \xB7 \u273B Worked for ",
47193
+ " \xB7 ",
46165
47194
  formatDuration2(elapsed)
46166
47195
  ]
46167
47196
  }, undefined, true, undefined, this)
@@ -46193,17 +47222,17 @@ function Spinner({ type = "dots" }) {
46193
47222
  var build_default2 = Spinner;
46194
47223
 
46195
47224
  // packages/terminal/src/components/Spinner.tsx
46196
- var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
47225
+ var jsx_dev_runtime5 = __toESM(require_jsx_dev_runtime(), 1);
46197
47226
  function Spinner2({ label }) {
46198
- return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
47227
+ return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Box_default, {
46199
47228
  children: [
46200
- /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47229
+ /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46201
47230
  dimColor: true,
46202
- children: /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(build_default2, {
47231
+ children: /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(build_default2, {
46203
47232
  type: "dots"
46204
47233
  }, undefined, false, undefined, this)
46205
47234
  }, undefined, false, undefined, this),
46206
- label && /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
47235
+ label && /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(Text, {
46207
47236
  dimColor: true,
46208
47237
  children: [
46209
47238
  " ",
@@ -46216,7 +47245,7 @@ function Spinner2({ label }) {
46216
47245
 
46217
47246
  // packages/terminal/src/components/ProcessingIndicator.tsx
46218
47247
  var import_react27 = __toESM(require_react(), 1);
46219
- var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
47248
+ var jsx_dev_runtime6 = __toESM(require_jsx_dev_runtime(), 1);
46220
47249
  function ProcessingIndicator({
46221
47250
  isProcessing,
46222
47251
  startTime,
@@ -46260,14 +47289,14 @@ function ProcessingIndicator({
46260
47289
  parts.push("thinking");
46261
47290
  }
46262
47291
  const label = isThinking ? "Metamorphosing" : "Working";
46263
- return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
47292
+ return /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Box_default, {
46264
47293
  marginY: 1,
46265
47294
  children: [
46266
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47295
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46267
47296
  dimColor: true,
46268
47297
  children: "\u2736 "
46269
47298
  }, undefined, false, undefined, this),
46270
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47299
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46271
47300
  dimColor: true,
46272
47301
  children: [
46273
47302
  " ",
@@ -46275,7 +47304,7 @@ function ProcessingIndicator({
46275
47304
  "... "
46276
47305
  ]
46277
47306
  }, undefined, true, undefined, this),
46278
- /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
47307
+ /* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
46279
47308
  dimColor: true,
46280
47309
  children: [
46281
47310
  "(",
@@ -46288,31 +47317,31 @@ function ProcessingIndicator({
46288
47317
  }
46289
47318
 
46290
47319
  // packages/terminal/src/components/WelcomeBanner.tsx
46291
- var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
47320
+ var jsx_dev_runtime7 = __toESM(require_jsx_dev_runtime(), 1);
46292
47321
  function WelcomeBanner({ version, model, directory }) {
46293
47322
  const homeDir = process.env.HOME || "";
46294
47323
  const displayDir = directory.startsWith(homeDir) ? "~" + directory.slice(homeDir.length) : directory;
46295
- return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47324
+ return /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46296
47325
  flexDirection: "column",
46297
47326
  marginBottom: 1,
46298
47327
  children: [
46299
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47328
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46300
47329
  children: [
46301
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47330
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46302
47331
  color: "cyan",
46303
47332
  bold: true,
46304
47333
  children: ">"
46305
47334
  }, undefined, false, undefined, this),
46306
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47335
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46307
47336
  color: "cyan",
46308
47337
  bold: true,
46309
47338
  children: "_ "
46310
47339
  }, undefined, false, undefined, this),
46311
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47340
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46312
47341
  bold: true,
46313
47342
  children: "assistants"
46314
47343
  }, undefined, false, undefined, this),
46315
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47344
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46316
47345
  dimColor: true,
46317
47346
  children: [
46318
47347
  " (v",
@@ -46322,29 +47351,29 @@ function WelcomeBanner({ version, model, directory }) {
46322
47351
  }, undefined, true, undefined, this)
46323
47352
  ]
46324
47353
  }, undefined, true, undefined, this),
46325
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47354
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46326
47355
  marginTop: 1,
46327
47356
  children: [
46328
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47357
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46329
47358
  dimColor: true,
46330
47359
  children: "model: "
46331
47360
  }, undefined, false, undefined, this),
46332
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47361
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46333
47362
  children: model
46334
47363
  }, undefined, false, undefined, this),
46335
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47364
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46336
47365
  dimColor: true,
46337
47366
  children: " /model to change"
46338
47367
  }, undefined, false, undefined, this)
46339
47368
  ]
46340
47369
  }, undefined, true, undefined, this),
46341
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47370
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Box_default, {
46342
47371
  children: [
46343
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47372
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46344
47373
  dimColor: true,
46345
47374
  children: "directory: "
46346
47375
  }, undefined, false, undefined, this),
46347
- /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
47376
+ /* @__PURE__ */ jsx_dev_runtime7.jsxDEV(Text, {
46348
47377
  children: displayDir
46349
47378
  }, undefined, false, undefined, this)
46350
47379
  ]
@@ -46355,7 +47384,7 @@ function WelcomeBanner({ version, model, directory }) {
46355
47384
 
46356
47385
  // packages/terminal/src/components/SessionSelector.tsx
46357
47386
  var import_react28 = __toESM(require_react(), 1);
46358
- var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
47387
+ var jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
46359
47388
  function formatSessionTime(timestamp) {
46360
47389
  const date = new Date(timestamp);
46361
47390
  const now2 = new Date;
@@ -46421,13 +47450,13 @@ function SessionSelector({
46421
47450
  return;
46422
47451
  }
46423
47452
  });
46424
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47453
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46425
47454
  flexDirection: "column",
46426
47455
  paddingY: 1,
46427
47456
  children: [
46428
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47457
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46429
47458
  marginBottom: 1,
46430
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47459
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46431
47460
  bold: true,
46432
47461
  children: "Sessions"
46433
47462
  }, undefined, false, undefined, this)
@@ -46439,8 +47468,8 @@ function SessionSelector({
46439
47468
  const time = formatSessionTime(session.updatedAt);
46440
47469
  const path2 = formatPath(session.cwd);
46441
47470
  const processing = session.isProcessing ? " (processing)" : "";
46442
- return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
46443
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47471
+ return /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
47472
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46444
47473
  inverse: isSelected,
46445
47474
  color: isActive ? "green" : undefined,
46446
47475
  dimColor: !isSelected && !isActive,
@@ -46457,17 +47486,17 @@ function SessionSelector({
46457
47486
  }, undefined, true, undefined, this)
46458
47487
  }, session.id, false, undefined, this);
46459
47488
  }),
46460
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47489
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46461
47490
  marginTop: 1,
46462
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47491
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46463
47492
  inverse: selectedIndex === sessions.length,
46464
47493
  dimColor: selectedIndex !== sessions.length,
46465
47494
  children: "+ New session (n)"
46466
47495
  }, undefined, false, undefined, this)
46467
47496
  }, undefined, false, undefined, this),
46468
- /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47497
+ /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Box_default, {
46469
47498
  marginTop: 1,
46470
- children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47499
+ children: /* @__PURE__ */ jsx_dev_runtime8.jsxDEV(Text, {
46471
47500
  dimColor: true,
46472
47501
  children: [
46473
47502
  "Enter to select | Esc to cancel | 1-",
@@ -46481,32 +47510,8 @@ function SessionSelector({
46481
47510
  }
46482
47511
 
46483
47512
  // packages/terminal/src/components/App.tsx
46484
- var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
47513
+ var jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
46485
47514
  var SHOW_ERROR_CODES = process.env.ASSISTANTS_DEBUG === "1" || process.env.OLDPAL_DEBUG === "1";
46486
- function formatToolName(toolCall) {
46487
- const { name, input } = toolCall;
46488
- switch (name) {
46489
- case "bash":
46490
- return `bash`;
46491
- case "read":
46492
- const path2 = String(input.path || input.file_path || "");
46493
- return `read ${path2.split("/").pop() || ""}`;
46494
- case "write":
46495
- const writePath = String(input.filename || input.path || input.file_path || "");
46496
- return `write ${writePath.split("/").pop() || ""}`;
46497
- case "glob":
46498
- return `glob`;
46499
- case "grep":
46500
- return `grep`;
46501
- case "web_search":
46502
- return `search`;
46503
- case "web_fetch":
46504
- case "curl":
46505
- return `fetch`;
46506
- default:
46507
- return name;
46508
- }
46509
- }
46510
47515
  function parseErrorMessage(error) {
46511
47516
  const lines = error.split(`
46512
47517
  `);
@@ -46528,7 +47533,65 @@ function parseErrorMessage(error) {
46528
47533
  }
46529
47534
  var MESSAGE_CHUNK_LINES = 12;
46530
47535
  var MESSAGE_WRAP_CHARS = 120;
46531
- 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) {
46532
47595
  const display = [];
46533
47596
  for (const msg of messages) {
46534
47597
  const content = msg.content ?? "";
@@ -46537,32 +47600,34 @@ function buildDisplayMessages(messages, chunkLines, wrapChars) {
46537
47600
  display.push(msg);
46538
47601
  continue;
46539
47602
  }
46540
- const rawLines = content.split(`
46541
- `);
46542
- const lines = [];
46543
- for (const line of rawLines) {
46544
- if (line.length <= wrapChars) {
46545
- lines.push(line);
46546
- continue;
46547
- }
46548
- for (let i = 0;i < line.length; i += wrapChars) {
46549
- lines.push(line.slice(i, i + wrapChars));
46550
- }
46551
- }
47603
+ const lines = wrapTextLines(content, wrapChars);
46552
47604
  if (lines.length <= chunkLines) {
46553
- 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
+ }
46554
47612
  continue;
46555
47613
  }
46556
- const totalChunks = Math.ceil(lines.length / chunkLines);
46557
- for (let i = 0;i < totalChunks; i++) {
46558
- 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(`
46559
47623
  `);
46560
47624
  display.push({
46561
47625
  ...msg,
46562
47626
  id: `${msg.id}::chunk-${i}`,
46563
47627
  content: chunkContent,
46564
- toolCalls: i === totalChunks - 1 ? msg.toolCalls : undefined,
46565
- 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
46566
47631
  });
46567
47632
  }
46568
47633
  }
@@ -46597,7 +47662,7 @@ function App2({ cwd: cwd2, version }) {
46597
47662
  const toolCallsRef = import_react29.useRef([]);
46598
47663
  const toolResultsRef = import_react29.useRef([]);
46599
47664
  const activityLogRef = import_react29.useRef([]);
46600
- const prevDisplayCountRef = import_react29.useRef(0);
47665
+ const prevDisplayLineCountRef = import_react29.useRef(0);
46601
47666
  const skipNextDoneRef = import_react29.useRef(false);
46602
47667
  const isProcessingRef = import_react29.useRef(isProcessing);
46603
47668
  import_react29.useEffect(() => {
@@ -46919,9 +47984,10 @@ function App2({ cwd: cwd2, version }) {
46919
47984
  await activeSession2.client.send(nextMessage.content);
46920
47985
  }, [activeSessionId]);
46921
47986
  const activeQueue = activeSessionId ? messageQueue.filter((msg) => msg.sessionId === activeSessionId) : [];
46922
- 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]);
46923
47988
  const wrapChars = columns ? Math.max(40, columns - 4) : MESSAGE_WRAP_CHARS;
46924
- 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]);
46925
47991
  const streamingMessages = import_react29.useMemo(() => {
46926
47992
  if (!isProcessing || !currentResponse.trim())
46927
47993
  return [];
@@ -46931,9 +47997,12 @@ function App2({ cwd: cwd2, version }) {
46931
47997
  content: currentResponse,
46932
47998
  timestamp: now()
46933
47999
  };
46934
- return buildDisplayMessages([streamingMessage], MESSAGE_CHUNK_LINES, wrapChars);
46935
- }, [currentResponse, isProcessing, wrapChars]);
46936
- 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]);
46937
48006
  import_react29.useEffect(() => {
46938
48007
  if (!isProcessing && activeQueue.length > 0) {
46939
48008
  processQueue();
@@ -46943,23 +48012,21 @@ function App2({ cwd: cwd2, version }) {
46943
48012
  if (autoScroll) {
46944
48013
  setScrollOffset(0);
46945
48014
  }
46946
- }, [displayCount, autoScroll]);
48015
+ }, [displayLineCount, autoScroll]);
46947
48016
  import_react29.useEffect(() => {
46948
- const prevCount = prevDisplayCountRef.current;
46949
- if (!autoScroll && displayCount > prevCount) {
46950
- const delta = displayCount - prevCount;
48017
+ const prevCount = prevDisplayLineCountRef.current;
48018
+ if (!autoScroll && displayLineCount > prevCount) {
48019
+ const delta = displayLineCount - prevCount;
46951
48020
  setScrollOffset((prev) => prev + delta);
46952
48021
  }
46953
- prevDisplayCountRef.current = displayCount;
46954
- }, [displayCount, autoScroll]);
48022
+ prevDisplayLineCountRef.current = displayLineCount;
48023
+ }, [displayLineCount, autoScroll]);
46955
48024
  const reservedLines = 8;
46956
- const baseMaxVisible = rows ? Math.max(3, rows - reservedLines) : 10;
46957
- const toolCallsHeight = isProcessing ? Math.min(toolCallsRef.current.length, 5) : 0;
46958
- const maxVisibleMessages = Math.max(3, baseMaxVisible - toolCallsHeight);
48025
+ const maxVisibleLines = rows ? Math.max(6, rows - reservedLines) : 20;
46959
48026
  import_react29.useEffect(() => {
46960
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48027
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
46961
48028
  setScrollOffset((prev) => Math.min(prev, maxOffset));
46962
- }, [displayCount, maxVisibleMessages]);
48029
+ }, [displayLineCount, maxVisibleLines]);
46963
48030
  const sessions = registry2.listSessions();
46964
48031
  const activeSession = registry2.getActiveSession();
46965
48032
  const sessionIndex = activeSessionId ? registry2.getSessionIndex(activeSessionId) : 0;
@@ -47038,8 +48105,9 @@ function App2({ cwd: cwd2, version }) {
47038
48105
  }
47039
48106
  if (key.pageUp || key.shift && key.upArrow) {
47040
48107
  setScrollOffset((prev) => {
47041
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
47042
- 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);
47043
48111
  if (newOffset > 0)
47044
48112
  setAutoScroll(false);
47045
48113
  return newOffset;
@@ -47047,14 +48115,15 @@ function App2({ cwd: cwd2, version }) {
47047
48115
  }
47048
48116
  if (key.pageDown || key.shift && key.downArrow) {
47049
48117
  setScrollOffset((prev) => {
47050
- 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);
47051
48120
  if (newOffset === 0)
47052
48121
  setAutoScroll(true);
47053
48122
  return newOffset;
47054
48123
  });
47055
48124
  }
47056
48125
  if (key.ctrl && input === "u") {
47057
- const maxOffset = Math.max(0, displayCount - maxVisibleMessages);
48126
+ const maxOffset = Math.max(0, displayLineCount - maxVisibleLines);
47058
48127
  setScrollOffset(maxOffset);
47059
48128
  setAutoScroll(false);
47060
48129
  }
@@ -47085,13 +48154,19 @@ function App2({ cwd: cwd2, version }) {
47085
48154
  setShowSessionSelector(true);
47086
48155
  return;
47087
48156
  }
47088
- if (mode === "queue" || isProcessing && mode === "normal") {
48157
+ if (mode === "queue" || mode === "inline") {
47089
48158
  if (!activeSessionId)
47090
48159
  return;
47091
48160
  const queuedId = generateId();
47092
48161
  setMessageQueue((prev) => [
47093
48162
  ...prev,
47094
- { 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
+ }
47095
48170
  ]);
47096
48171
  setMessages((prev) => [
47097
48172
  ...prev,
@@ -47155,19 +48230,19 @@ function App2({ cwd: cwd2, version }) {
47155
48230
  activeSessionId
47156
48231
  ]);
47157
48232
  if (isInitializing) {
47158
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48233
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47159
48234
  flexDirection: "column",
47160
48235
  padding: 1,
47161
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Spinner2, {
48236
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Spinner2, {
47162
48237
  label: "Initializing..."
47163
48238
  }, undefined, false, undefined, this)
47164
48239
  }, undefined, false, undefined, this);
47165
48240
  }
47166
48241
  if (showSessionSelector) {
47167
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48242
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47168
48243
  flexDirection: "column",
47169
48244
  padding: 1,
47170
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(SessionSelector, {
48245
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(SessionSelector, {
47171
48246
  sessions,
47172
48247
  activeSessionId,
47173
48248
  onSelect: handleSessionSwitch,
@@ -47187,19 +48262,21 @@ function App2({ cwd: cwd2, version }) {
47187
48262
  return text;
47188
48263
  return text.slice(0, maxLen - 3) + "...";
47189
48264
  };
48265
+ const queuedCount = activeQueue.filter((msg) => msg.mode === "queued").length;
48266
+ const inlineCount = activeQueue.filter((msg) => msg.mode === "inline").length;
47190
48267
  const showWelcome = messages.length === 0 && !isProcessing;
47191
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48268
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47192
48269
  flexDirection: "column",
47193
48270
  padding: 1,
47194
48271
  children: [
47195
- showWelcome && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(WelcomeBanner, {
47196
- version: version ?? "0.6.13",
48272
+ showWelcome && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(WelcomeBanner, {
48273
+ version: version ?? "unknown",
47197
48274
  model: "claude-sonnet-4",
47198
48275
  directory: activeSession?.cwd || cwd2
47199
48276
  }, undefined, false, undefined, this),
47200
- backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48277
+ backgroundProcessingCount > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47201
48278
  marginBottom: 1,
47202
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48279
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47203
48280
  color: "yellow",
47204
48281
  children: [
47205
48282
  backgroundProcessingCount,
@@ -47209,17 +48286,17 @@ function App2({ cwd: cwd2, version }) {
47209
48286
  ]
47210
48287
  }, undefined, true, undefined, this)
47211
48288
  }, undefined, false, undefined, this),
47212
- scrollOffset > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47213
- 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, {
47214
48291
  dimColor: true,
47215
48292
  children: [
47216
48293
  "\u2191 ",
47217
48294
  scrollOffset,
47218
- " more messages above (Shift+\u2193 or Page Down to scroll down)"
48295
+ " more lines above (Shift+\u2193 or Page Down to scroll down)"
47219
48296
  ]
47220
48297
  }, undefined, true, undefined, this)
47221
48298
  }, undefined, false, undefined, this),
47222
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Messages4, {
48299
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Messages4, {
47223
48300
  messages: displayMessages,
47224
48301
  currentResponse: undefined,
47225
48302
  streamingMessages,
@@ -47227,61 +48304,34 @@ function App2({ cwd: cwd2, version }) {
47227
48304
  lastToolResult: undefined,
47228
48305
  activityLog: isProcessing ? activityLog : [],
47229
48306
  queuedMessageIds,
47230
- scrollOffset,
47231
- maxVisible: maxVisibleMessages
48307
+ scrollOffsetLines: scrollOffset,
48308
+ maxVisibleLines
47232
48309
  }, activeSessionId || "default", false, undefined, this),
47233
- isProcessing && toolCallEntries.length > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47234
- marginY: 1,
47235
- flexDirection: "column",
47236
- children: [
47237
- toolCallEntries.slice(-3).map(({ toolCall, result }) => /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
47238
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47239
- dimColor: true,
47240
- children: [
47241
- result ? "\u2713" : "\u2699",
47242
- " ",
47243
- formatToolName(toolCall),
47244
- result?.isError && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47245
- color: "red",
47246
- children: " (error)"
47247
- }, undefined, false, undefined, this)
47248
- ]
47249
- }, undefined, true, undefined, this)
47250
- }, toolCall.id, false, undefined, this)),
47251
- toolCallEntries.length > 3 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
47252
- dimColor: true,
47253
- children: [
47254
- " ... and ",
47255
- toolCallEntries.length - 3,
47256
- " more tools"
47257
- ]
47258
- }, undefined, true, undefined, this)
47259
- ]
47260
- }, undefined, true, undefined, this),
47261
- activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48310
+ activeQueue.length > 0 && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47262
48311
  marginY: 1,
47263
48312
  flexDirection: "column",
47264
48313
  children: [
47265
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48314
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47266
48315
  dimColor: true,
47267
48316
  children: [
47268
48317
  activeQueue.length,
47269
- " message",
48318
+ " pending message",
47270
48319
  activeQueue.length > 1 ? "s" : "",
47271
- " queued"
48320
+ inlineCount > 0 || queuedCount > 0 ? ` \xB7 ${inlineCount} in-stream \xB7 ${queuedCount} queued` : ""
47272
48321
  ]
47273
48322
  }, undefined, true, undefined, this),
47274
- 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, {
47275
48324
  marginLeft: 2,
47276
- children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48325
+ children: /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47277
48326
  dimColor: true,
47278
48327
  children: [
47279
- "\u276F ",
48328
+ queued.mode === "inline" ? "\u21B3" : "\u23F3",
48329
+ " ",
47280
48330
  truncateQueued(queued.content)
47281
48331
  ]
47282
48332
  }, undefined, true, undefined, this)
47283
48333
  }, queued.id, false, undefined, this)),
47284
- activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48334
+ activeQueue.length > MAX_QUEUED_PREVIEW && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47285
48335
  dimColor: true,
47286
48336
  children: [
47287
48337
  " ... and ",
@@ -47295,18 +48345,18 @@ function App2({ cwd: cwd2, version }) {
47295
48345
  const parsed = parseErrorMessage(error);
47296
48346
  const severity = parsed.code && /TIMEOUT|RATE_LIMITED/.test(parsed.code) ? "yellow" : "red";
47297
48347
  const prefix = SHOW_ERROR_CODES && parsed.code ? `${parsed.code}: ` : "";
47298
- return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
48348
+ return /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Box_default, {
47299
48349
  marginY: 1,
47300
48350
  flexDirection: "column",
47301
48351
  children: [
47302
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48352
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47303
48353
  color: severity,
47304
48354
  children: [
47305
48355
  prefix,
47306
48356
  parsed.message
47307
48357
  ]
47308
48358
  }, undefined, true, undefined, this),
47309
- parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
48359
+ parsed.suggestion && /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Text, {
47310
48360
  color: severity,
47311
48361
  children: [
47312
48362
  "Suggestion: ",
@@ -47316,19 +48366,19 @@ function App2({ cwd: cwd2, version }) {
47316
48366
  ]
47317
48367
  }, undefined, true, undefined, this);
47318
48368
  })(),
47319
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(ProcessingIndicator, {
48369
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(ProcessingIndicator, {
47320
48370
  isProcessing,
47321
48371
  startTime: processingStartTime,
47322
48372
  tokenCount: currentTurnTokens,
47323
48373
  isThinking
47324
48374
  }, undefined, false, undefined, this),
47325
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Input, {
48375
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Input, {
47326
48376
  onSubmit: handleSubmit,
47327
48377
  isProcessing,
47328
48378
  queueLength: activeQueue.length,
47329
48379
  skills
47330
48380
  }, undefined, false, undefined, this),
47331
- /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Status, {
48381
+ /* @__PURE__ */ jsx_dev_runtime9.jsxDEV(Status, {
47332
48382
  isProcessing,
47333
48383
  cwd: activeSession?.cwd || cwd2,
47334
48384
  queueLength: activeQueue.length,
@@ -47520,8 +48570,9 @@ function formatStreamEvent(chunk) {
47520
48570
  }
47521
48571
 
47522
48572
  // packages/terminal/src/index.tsx
47523
- var jsx_dev_runtime11 = __toESM(require_jsx_dev_runtime(), 1);
47524
- var VERSION3 = "0.6.18";
48573
+ var jsx_dev_runtime10 = __toESM(require_jsx_dev_runtime(), 1);
48574
+ var VERSION3 = "0.6.20";
48575
+ process.env.ASSISTANTS_VERSION ??= VERSION3;
47525
48576
  function parseArgs(argv) {
47526
48577
  const args = argv.slice(2);
47527
48578
  const options = {
@@ -47675,7 +48726,7 @@ if (options.print !== null) {
47675
48726
  process.exit(1);
47676
48727
  });
47677
48728
  } else {
47678
- const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime11.jsxDEV(App2, {
48729
+ const { waitUntilExit } = render_default(/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(App2, {
47679
48730
  cwd: options.cwd,
47680
48731
  version: VERSION3
47681
48732
  }, undefined, false, undefined, this));
@@ -47684,4 +48735,4 @@ if (options.print !== null) {
47684
48735
  });
47685
48736
  }
47686
48737
 
47687
- //# debugId=EED40350F624F85864756E2164756E21
48738
+ //# debugId=F2C1A670F9E8793164756E2164756E21