archymedes-cli 3.4.0 → 3.5.1

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.
@@ -7,7 +7,7 @@ import {
7
7
  eventJournalPath,
8
8
  readEventJournal,
9
9
  runtimeEventForJournal
10
- } from "./archymedes-cfwtgnjx.mjs";
10
+ } from "./archymedes-qm9bwbe7.mjs";
11
11
  import {
12
12
  APIConnectionError,
13
13
  BoundedAgentRuntime,
@@ -17,6 +17,7 @@ import {
17
17
  OpenAIAgentTurnProvider,
18
18
  StreamTimeoutError,
19
19
  TASK_KINDS,
20
+ VENDOR_DIALECTS,
20
21
  WANDER_GRADES,
21
22
  WANDER_LAB_FILES,
22
23
  WANDER_MARKER,
@@ -44,18 +45,18 @@ import {
44
45
  wanderGradeCounts,
45
46
  wanderPlannerInstructions,
46
47
  withOpenRouterCacheControl
47
- } from "./archymedes-ds224xzf.mjs";
48
+ } from "./archymedes-82ay2983.mjs";
48
49
  import {
49
50
  __require
50
51
  } from "./archymedes-x67v3n58.mjs";
51
52
 
52
- // src/archymedes.ts
53
+ // packages/archymedes-cli/src/archymedes.ts
53
54
  import { createInterface as createInterface5 } from "readline/promises";
54
55
  import path30 from "path";
55
56
  import { realpathSync } from "fs";
56
57
  import { pathToFileURL as pathToFileURL2 } from "url";
57
58
 
58
- // ../core/src/cli/acp.ts
59
+ // packages/core/src/cli/acp.ts
59
60
  var ACP_PROTOCOL_VERSION = 1;
60
61
  var JSON_RPC = { parseError: -32700, invalidRequest: -32600, methodNotFound: -32601, invalidParams: -32602, internalError: -32603 };
61
62
  var ARCHYMEDES_EVENT_METHOD = "_archymedes/event";
@@ -404,7 +405,7 @@ function toolCallTitle(toolName, argumentsValue) {
404
405
  return subject ? `${label}: ${String(subject).slice(0, 120)}` : label;
405
406
  }
406
407
 
407
- // ../core/src/cli/image-attachments.ts
408
+ // packages/core/src/cli/image-attachments.ts
408
409
  var MAX_IMAGES_PER_TURN = 4;
409
410
  var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
410
411
  var MENTION = /(?:^|\s)@((?:[\w.-]+\/)*[\w.-]+\.(?:png|jpe?g|gif|webp))(?=$|[\s,;:!?)])/gi;
@@ -469,7 +470,7 @@ function withoutImageData(messages) {
469
470
  });
470
471
  }
471
472
 
472
- // ../core/src/cli/hosted-recovery.ts
473
+ // packages/core/src/cli/hosted-recovery.ts
473
474
  import { createHash, randomUUID } from "node:crypto";
474
475
  import { promises as fs } from "node:fs";
475
476
  import path from "node:path";
@@ -728,12 +729,12 @@ ${entry.response.content}` });
728
729
  }
729
730
  }
730
731
 
731
- // ../core/src/cli/agent.ts
732
+ // packages/core/src/cli/agent.ts
732
733
  import { randomUUID as randomUUID4 } from "node:crypto";
733
734
  import path15 from "node:path";
734
735
  import { access as access3 } from "node:fs/promises";
735
736
 
736
- // ../core/src/cli/checkpoints.ts
737
+ // packages/core/src/cli/checkpoints.ts
737
738
  import { spawn } from "node:child_process";
738
739
  import { randomUUID as randomUUID2 } from "node:crypto";
739
740
  import { promises as fs2 } from "node:fs";
@@ -857,10 +858,10 @@ class CheckpointStore {
857
858
  }
858
859
  }
859
860
 
860
- // ../core/src/cli/permissions.ts
861
+ // packages/core/src/cli/permissions.ts
861
862
  import { createHash as createHash2 } from "node:crypto";
862
863
 
863
- // ../core/src/cli/command.ts
864
+ // packages/core/src/cli/command.ts
864
865
  import { spawn as spawn2 } from "node:child_process";
865
866
  import { constants } from "node:os";
866
867
  var ARCHYMEDES_CREDENTIAL_ENV_NAMES = [
@@ -1209,13 +1210,13 @@ Command cancelled and its process tree was terminated.`;
1209
1210
  return;
1210
1211
  forcedExitCode = 124;
1211
1212
  stderr += `
1212
- Command exceeded ${options.timeoutMs}ms and was killed.`;
1213
+ Command exceeded its ${options.timeoutMs >= 1000 ? `${Math.round(options.timeoutMs / 1000)}s` : `${options.timeoutMs}ms`} limit and was killed. If it needs longer, run it again with a larger timeoutSeconds.`;
1213
1214
  terminate();
1214
1215
  }, options.timeoutMs);
1215
1216
  });
1216
1217
  };
1217
1218
 
1218
- // ../core/src/cli/safety.ts
1219
+ // packages/core/src/cli/safety.ts
1219
1220
  var TASK_RULES = [
1220
1221
  { category: "credentials", reason: "credential disclosure or high-impact credential change", pattern: /\b(?:export|expose|reveal|print|show|share|send|upload|publish|rotate|revoke)\b.{0,60}\b(?:api[ _-]?key|api[ _-]?token|access[ _-]?token|auth[ _-]?token|password|private[ _-]?key|secret|credential)s?\b|\b(?:set|add|store|save|replace)\b.{0,45}\b(?:production|prod|live)\b.{0,45}\b(?:api[ _-]?key|api[ _-]?token|access[ _-]?token|auth[ _-]?token|password|private[ _-]?key|secret|credential)s?\b/i },
1221
1222
  { category: "destructive", reason: "destructive data or repository operation", pattern: /(?:(?<!git\s)\brm\s+[^\n]*(?:-[^\n]*[rf]\b|--recursive|--force)|\bfind\s+[^\n]*-delete\b|\b(?:delete|drop|erase|purge|truncate|wipe|destroy|reset)\b.{0,45}\b(?:all|database|table|records?|history|account|branch|repository|production|live)\b)/i },
@@ -1277,7 +1278,7 @@ function assessToolSafety(call, tool) {
1277
1278
  };
1278
1279
  }
1279
1280
 
1280
- // ../core/src/cli/permissions.ts
1281
+ // packages/core/src/cli/permissions.ts
1281
1282
  var ARCHYMEDES_CAPABILITIES = {
1282
1283
  read: "workspace.files.read",
1283
1284
  write: "workspace.files",
@@ -1722,7 +1723,7 @@ function describeToolCall(call, tool) {
1722
1723
  }
1723
1724
  }
1724
1725
 
1725
- // ../core/src/cli/memory.ts
1726
+ // packages/core/src/cli/memory.ts
1726
1727
  import { promises as fs3 } from "node:fs";
1727
1728
  import os from "node:os";
1728
1729
  import path3 from "node:path";
@@ -1888,7 +1889,7 @@ function memoryPromptBlock(entries) {
1888
1889
  `);
1889
1890
  }
1890
1891
 
1891
- // ../core/src/cli/environment.ts
1892
+ // packages/core/src/cli/environment.ts
1892
1893
  import os2 from "node:os";
1893
1894
  var BASE_PROBES = ["git", "node", "bun", "npm", "pnpm", "yarn", "rg", "python3"];
1894
1895
  var MARKER_PROBES = [
@@ -1986,13 +1987,13 @@ function describeEnvironment(report) {
1986
1987
  `);
1987
1988
  }
1988
1989
 
1989
- // ../core/src/cli/prompt.ts
1990
+ // packages/core/src/cli/prompt.ts
1990
1991
  import { createHash as createHash4 } from "node:crypto";
1991
1992
  import { promises as fs5 } from "node:fs";
1992
1993
  import os3 from "node:os";
1993
1994
  import path5 from "node:path";
1994
1995
 
1995
- // ../core/src/cli/workspace.ts
1996
+ // packages/core/src/cli/workspace.ts
1996
1997
  import { constants as fsConstants, promises as fs4 } from "node:fs";
1997
1998
  import { spawn as spawn3 } from "node:child_process";
1998
1999
  import { createHash as createHash3 } from "node:crypto";
@@ -2639,7 +2640,7 @@ async function grepWorkspace(root, query, options = {}) {
2639
2640
  return matches;
2640
2641
  }
2641
2642
 
2642
- // ../core/src/cli/defender-playbooks.ts
2643
+ // packages/core/src/cli/defender-playbooks.ts
2643
2644
  var INJECTION_PLAYBOOK = `
2644
2645
  ## Injection
2645
2646
 
@@ -3341,7 +3342,7 @@ function playbookFor(id) {
3341
3342
  return DEFENDER_PLAYBOOK_CATALOG.find((entry) => entry.id === wanted || entry.title.toLowerCase() === wanted);
3342
3343
  }
3343
3344
 
3344
- // ../core/src/cli/token-saver.ts
3345
+ // packages/core/src/cli/token-saver.ts
3345
3346
  var TOKEN_SAVER_CONTEXT_LIMIT = 16384;
3346
3347
  var TOKEN_SAVER_TOOL_RESULT_CHARS = 3000;
3347
3348
  var TOKEN_SAVER_TOTAL_TOOL_RESULT_CHARS = 24000;
@@ -3446,7 +3447,7 @@ function restoreFullHistory(messages, original, sent) {
3446
3447
  return [messages[0], ...original, ...messages.slice(1 + sent.length)];
3447
3448
  }
3448
3449
 
3449
- // ../core/src/cli/prompt.ts
3450
+ // packages/core/src/cli/prompt.ts
3450
3451
  var INSTRUCTION_FILES = ["AGENTS.override.md", "ARCHYMEDES.md", "AGENTS.md", "CLAUDE.md", ".archymedesrules"];
3451
3452
  async function instructionBoundary(root) {
3452
3453
  const requestedRoot = path5.resolve(root);
@@ -3712,7 +3713,7 @@ ${instructions}`);
3712
3713
  `);
3713
3714
  }
3714
3715
 
3715
- // ../core/src/cli/session.ts
3716
+ // packages/core/src/cli/session.ts
3716
3717
  import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
3717
3718
  import { promises as fs6 } from "node:fs";
3718
3719
  import path6 from "node:path";
@@ -4121,17 +4122,17 @@ ${summary.trim()}` },
4121
4122
  ];
4122
4123
  }
4123
4124
 
4124
- // ../core/src/hooks/command.ts
4125
+ // packages/core/src/hooks/command.ts
4125
4126
  function hookCommand(scriptPath, payload, platform) {
4126
4127
  if (platform !== "win32")
4127
4128
  return `env ARCHYMEDES_HOOK_EVENT_B64=${payload} ${scriptPath}`;
4128
4129
  return `set "ARCHYMEDES_HOOK_EVENT_B64=${payload}"&& call "${scriptPath.split("/").join("\\")}"`;
4129
4130
  }
4130
4131
 
4131
- // ../core/src/hooks/types.ts
4132
+ // packages/core/src/hooks/types.ts
4132
4133
  var HOOK_PHASES = ["pre-session", "pre-turn", "pre-tool-use", "post-tool-use", "post-turn", "post-session"];
4133
4134
 
4134
- // ../core/src/hooks/registry.ts
4135
+ // packages/core/src/hooks/registry.ts
4135
4136
  var HOOKS_DIRECTORY = ".archymedes/hooks";
4136
4137
  var HOOK_TIMEOUT_MS = 5000;
4137
4138
  async function scriptsIn(workspace, phaseDirectory) {
@@ -4234,7 +4235,7 @@ class HookRegistry {
4234
4235
  return warnings;
4235
4236
  }
4236
4237
  }
4237
- // ../core/src/mcp/config.ts
4238
+ // packages/core/src/mcp/config.ts
4238
4239
  var MCP_CONFIG_PATH = ".archymedes/mcp.json";
4239
4240
  function isPlainObject(value) {
4240
4241
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4289,7 +4290,7 @@ async function discoverMcpServers(workspace) {
4289
4290
  }
4290
4291
  return servers;
4291
4292
  }
4292
- // ../core/src/mcp/http-transport.ts
4293
+ // packages/core/src/mcp/http-transport.ts
4293
4294
  class HttpMcpTransport {
4294
4295
  config;
4295
4296
  requestTimeoutMs;
@@ -4445,7 +4446,7 @@ function isJsonRpcNotification(value) {
4445
4446
  return isPlainObject2(value) && "jsonrpc" in value && !("id" in value) && typeof value.method === "string";
4446
4447
  }
4447
4448
 
4448
- // ../core/src/mcp/stdio-transport.ts
4449
+ // packages/core/src/mcp/stdio-transport.ts
4449
4450
  import { spawn as spawn4 } from "node:child_process";
4450
4451
  import { createInterface } from "node:readline";
4451
4452
  class StdioMcpTransport {
@@ -4547,7 +4548,7 @@ function isJsonRpcNotification2(value) {
4547
4548
  return typeof value === "object" && value !== null && "jsonrpc" in value && !("id" in value) && typeof value.method === "string";
4548
4549
  }
4549
4550
 
4550
- // ../core/src/mcp/connection.ts
4551
+ // packages/core/src/mcp/connection.ts
4551
4552
  class McpConnection {
4552
4553
  config;
4553
4554
  transport;
@@ -4609,7 +4610,7 @@ class McpConnection {
4609
4610
  }
4610
4611
  var MCP_PROTOCOL_VERSION = "2024-11-05";
4611
4612
  var REQUEST_TIMEOUT_MS = 15000;
4612
- // ../core/src/mcp/client.ts
4613
+ // packages/core/src/mcp/client.ts
4613
4614
  class McpToolProvider {
4614
4615
  connection;
4615
4616
  kind = "mcp";
@@ -4634,7 +4635,7 @@ class McpToolProvider {
4634
4635
  this.connection.close();
4635
4636
  }
4636
4637
  }
4637
- // ../core/src/cli/plugins.ts
4638
+ // packages/core/src/cli/plugins.ts
4638
4639
  var PLUGINS_DIRECTORY = ".archymedes/plugins";
4639
4640
  function isPlainObject3(value) {
4640
4641
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4683,7 +4684,7 @@ async function discoverPlugins(workspace) {
4683
4684
  return plugins;
4684
4685
  }
4685
4686
 
4686
- // ../core/src/cli/tool-schema.ts
4687
+ // packages/core/src/cli/tool-schema.ts
4687
4688
  class ToolArgumentError extends Error {
4688
4689
  constructor(message) {
4689
4690
  super(message);
@@ -4727,6 +4728,44 @@ function assertSupportedSchema(toolName, schema) {
4727
4728
  }
4728
4729
  }
4729
4730
  }
4731
+ var PARAMETER_SYNONYMS = {
4732
+ path: ["file_path", "filePath", "filepath", "file", "filename", "target_file", "absolute_path", "relative_path", "dir", "directory"],
4733
+ content: ["contents", "file_text", "text", "data"],
4734
+ oldText: ["old_string", "old_str", "oldString", "old_text", "search"],
4735
+ newText: ["new_string", "new_str", "newString", "new_text", "replacement"],
4736
+ replaceAll: ["replace_all"],
4737
+ command: ["cmd", "shell_command", "script"],
4738
+ timeoutMs: ["timeout_ms"],
4739
+ timeoutSeconds: ["timeout", "timeout_seconds", "timeout_secs", "timeoutSecs"],
4740
+ query: ["q", "search_query"],
4741
+ pattern: ["glob"],
4742
+ include: ["include_pattern", "file_pattern"],
4743
+ url: ["uri", "link"]
4744
+ };
4745
+ function coerceScalar(type, value) {
4746
+ if (type === "string") {
4747
+ if (typeof value === "object" && value !== null)
4748
+ return JSON.stringify(value);
4749
+ if (typeof value === "number" && Number.isFinite(value))
4750
+ return String(value);
4751
+ if (typeof value === "boolean")
4752
+ return String(value);
4753
+ return;
4754
+ }
4755
+ if (type === "integer") {
4756
+ if (typeof value === "number" && Number.isFinite(value) && Math.abs(value - Math.round(value)) < 0.000000001)
4757
+ return Math.round(value);
4758
+ if (typeof value === "string" && /^\s*-?\d+\s*$/.test(value))
4759
+ return Number(value.trim());
4760
+ return;
4761
+ }
4762
+ if (typeof value === "string" && /^\s*(true|false)\s*$/i.test(value))
4763
+ return value.trim().toLowerCase() === "true";
4764
+ return;
4765
+ }
4766
+ function describe(value) {
4767
+ return Array.isArray(value) ? "an array" : value === null ? "null" : typeof value === "object" ? "an object" : `a ${typeof value}`;
4768
+ }
4730
4769
  function checkScalar(type, value, label) {
4731
4770
  if (type === "string") {
4732
4771
  if (typeof value !== "string")
@@ -4741,17 +4780,36 @@ function checkScalar(type, value, label) {
4741
4780
  if (typeof value !== "boolean")
4742
4781
  throw new ToolArgumentError(`${label} must be true or false`);
4743
4782
  }
4744
- function validateToolArguments(toolName, schema, args) {
4745
- if (!isPlainObject4(args))
4783
+ function normalizeToolArguments(toolName, schema, args) {
4784
+ let input = args;
4785
+ const notes = [];
4786
+ if (typeof input === "string") {
4787
+ try {
4788
+ const parsed = JSON.parse(input);
4789
+ if (isPlainObject4(parsed)) {
4790
+ input = parsed;
4791
+ notes.push("arguments were JSON text; read as an object");
4792
+ }
4793
+ } catch {}
4794
+ }
4795
+ if (!isPlainObject4(input))
4746
4796
  throw new ToolArgumentError(`${toolName} arguments must be a JSON object`);
4747
4797
  const properties = schema.properties ?? {};
4748
4798
  const required = new Set(schema.required ?? []);
4749
4799
  const present = {};
4750
- for (const [key, value] of Object.entries(args)) {
4800
+ for (const [given, value] of Object.entries(input)) {
4801
+ let key = given;
4802
+ if (!properties[key]) {
4803
+ const meant = Object.entries(PARAMETER_SYNONYMS).find(([target, synonyms]) => properties[target] && synonyms.includes(given) && !(target in input));
4804
+ if (meant) {
4805
+ key = meant[0];
4806
+ notes.push(`${given} read as ${key}`);
4807
+ }
4808
+ }
4751
4809
  const property = properties[key];
4752
4810
  if (!property) {
4753
4811
  const known = Object.keys(properties);
4754
- throw new ToolArgumentError(`${toolName} has no parameter "${key}". It accepts: ${known.length > 0 ? known.join(", ") : "no parameters"}.`);
4812
+ throw new ToolArgumentError(`${toolName} has no parameter "${given}". It accepts: ${known.length > 0 ? known.join(", ") : "no parameters"}.`);
4755
4813
  }
4756
4814
  if (value === undefined || value === null) {
4757
4815
  if (required.has(key))
@@ -4760,21 +4818,34 @@ function validateToolArguments(toolName, schema, args) {
4760
4818
  }
4761
4819
  if (property.type === "array") {
4762
4820
  const items = Array.isArray(value) ? value : [value];
4763
- items.forEach((item, index) => checkScalar(property.items.type, item, `${toolName}.${key}[${index}]`));
4764
- present[key] = items;
4821
+ present[key] = items.map((item, index) => scalar(property.items.type, item, `${toolName}.${key}[${index}]`, notes));
4765
4822
  continue;
4766
4823
  }
4767
- checkScalar(property.type, value, `${toolName}.${key}`);
4768
- present[key] = value;
4824
+ present[key] = scalar(property.type, value, `${toolName}.${key}`, notes);
4769
4825
  }
4770
4826
  for (const key of required) {
4771
4827
  if (!(key in present))
4772
4828
  throw new ToolArgumentError(`${toolName} requires ${key}`);
4773
4829
  }
4774
- return present;
4830
+ return { value: present, notes };
4831
+ }
4832
+ function scalar(type, value, label, notes) {
4833
+ try {
4834
+ checkScalar(type, value, label);
4835
+ return value;
4836
+ } catch (error) {
4837
+ const repaired = coerceScalar(type, value);
4838
+ if (repaired === undefined)
4839
+ throw error;
4840
+ notes.push(`${label} was ${describe(value)}; read as ${type === "string" && typeof value === "object" ? "JSON text" : `${type === "integer" ? "an" : "a"} ${type}`}`);
4841
+ return repaired;
4842
+ }
4843
+ }
4844
+ function validateToolArguments(toolName, schema, args) {
4845
+ return normalizeToolArguments(toolName, schema, args).value;
4775
4846
  }
4776
4847
 
4777
- // ../core/src/skills/manifest.ts
4848
+ // packages/core/src/skills/manifest.ts
4778
4849
  var SKILLS_DIRECTORY = ".archymedes/skills";
4779
4850
  function isPlainObject5(value) {
4780
4851
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4830,7 +4901,7 @@ function shellQuote(value, platform) {
4830
4901
  return `'${value.replace(/'/g, `'\\''`)}'`;
4831
4902
  return `"${value.replace(/"/g, '""').replace(/%/g, "%%")}"`;
4832
4903
  }
4833
- // ../core/src/skills/provider.ts
4904
+ // packages/core/src/skills/provider.ts
4834
4905
  class SkillToolProvider {
4835
4906
  id;
4836
4907
  skillsDirectory;
@@ -4860,7 +4931,7 @@ ${body}`, isError: result.exitCode !== 0 };
4860
4931
  }
4861
4932
  }
4862
4933
  var DEFAULT_SKILL_TIMEOUT_MS = 60000;
4863
- // ../core/src/cli/external-tools.ts
4934
+ // packages/core/src/cli/external-tools.ts
4864
4935
  var IMPLICIT_SKILL_PROVIDER_ID = "local-skills";
4865
4936
  async function loadLocalExternalTooling(workspace) {
4866
4937
  const providers = [new SkillToolProvider(IMPLICIT_SKILL_PROVIDER_ID, SKILLS_DIRECTORY, workspace)];
@@ -4901,7 +4972,7 @@ async function loadLocalExternalTooling(workspace) {
4901
4972
  };
4902
4973
  }
4903
4974
 
4904
- // ../core/src/cli/nested-instructions.ts
4975
+ // packages/core/src/cli/nested-instructions.ts
4905
4976
  class NestedInstructionTracker {
4906
4977
  workspace;
4907
4978
  seenDirectories = new Set;
@@ -4950,7 +5021,7 @@ ${blocks}`;
4950
5021
  }
4951
5022
  }
4952
5023
 
4953
- // ../core/src/cli/safe-fetch.ts
5024
+ // packages/core/src/cli/safe-fetch.ts
4954
5025
  import { lookup } from "node:dns/promises";
4955
5026
  import { isIP } from "node:net";
4956
5027
  var defaultResolveHost = async (hostname) => (await lookup(hostname, { all: true, verbatim: true })).map((entry) => entry.address);
@@ -5112,7 +5183,7 @@ async function fetchPublicText(input, options = {}) {
5112
5183
  return { ok: false, error: "too many redirects" };
5113
5184
  }
5114
5185
 
5115
- // ../core/src/cli/secret-scan.ts
5186
+ // packages/core/src/cli/secret-scan.ts
5116
5187
  var SECRET_PATTERNS = [
5117
5188
  { name: "AWS access key", regex: /AKIA[0-9A-Z]{16}/, severity: "critical" },
5118
5189
  { name: "GitHub token", regex: /gh[pousr]_[A-Za-z0-9]{36,255}/, severity: "critical" },
@@ -5143,7 +5214,7 @@ function findSecretsInLine(line) {
5143
5214
  return found;
5144
5215
  }
5145
5216
 
5146
- // ../core/src/cli/tool-providers.ts
5217
+ // packages/core/src/cli/tool-providers.ts
5147
5218
  var DEFAULT_EXTERNAL_TOOL_TIMEOUT_MS = 30000;
5148
5219
  async function toolsFromProvider(provider, timeoutMs = DEFAULT_EXTERNAL_TOOL_TIMEOUT_MS) {
5149
5220
  const externalTools = await provider.listTools();
@@ -5185,7 +5256,7 @@ async function collectExternalTools(providers, timeoutMs) {
5185
5256
  return collected;
5186
5257
  }
5187
5258
 
5188
- // ../core/src/cli/deploy.ts
5259
+ // packages/core/src/cli/deploy.ts
5189
5260
  var DEPLOY_PROVIDERS = {
5190
5261
  vercel: {
5191
5262
  id: "vercel",
@@ -5309,7 +5380,7 @@ function deployPlan(target, detection, options = {}) {
5309
5380
  return { commands, notes };
5310
5381
  }
5311
5382
 
5312
- // ../core/src/cli/compute.ts
5383
+ // packages/core/src/cli/compute.ts
5313
5384
  var MAX_INPUT = 2000;
5314
5385
  var MAX_DEPTH = 64;
5315
5386
  var FACTORIAL_LIMIT = 170;
@@ -5861,11 +5932,11 @@ function compute(expression, options = {}) {
5861
5932
  return { value: result, exact, rendered, radixRendered, warnings };
5862
5933
  }
5863
5934
 
5864
- // ../core/src/cli/tools-extra/git.ts
5935
+ // packages/core/src/cli/tools-extra/git.ts
5865
5936
  import { execFile } from "node:child_process";
5866
5937
  import path7 from "node:path";
5867
5938
 
5868
- // ../core/src/cli/tools-extra/shared.ts
5939
+ // packages/core/src/cli/tools-extra/shared.ts
5869
5940
  import { promises as fs7 } from "node:fs";
5870
5941
  function resolvedLimits(options) {
5871
5942
  return options.limits ?? DEFAULT_WORKSPACE_LIMITS;
@@ -5920,7 +5991,7 @@ function truncateText(text, maxChars, hint) {
5920
5991
  [truncated: showed ${cut.length} of ${text.length} chars. ${hint}]`, truncated: true };
5921
5992
  }
5922
5993
 
5923
- // ../core/src/cli/tools-extra/git.ts
5994
+ // packages/core/src/cli/tools-extra/git.ts
5924
5995
  var GIT_BASE_ARGS = ["--no-pager", "-c", "core.fsmonitor=false", "-c", "core.quotepath=false", "-c", "color.ui=false"];
5925
5996
  var MAX_GIT_OUTPUT = 16 * 1024 * 1024;
5926
5997
  function runGit2(root, args, timeoutMs) {
@@ -6034,7 +6105,7 @@ function renderStatus(status) {
6034
6105
  const head = branch.head ?? `detached at ${branch.oid?.slice(0, 12) ?? "unknown"}`;
6035
6106
  const tracking = branch.upstream ? ` → ${branch.upstream} (ahead ${branch.ahead}, behind ${branch.behind})` : "";
6036
6107
  const lines = [`On ${head}${branch.oid ? "" : " (no commits yet)"}${tracking}`];
6037
- const describe = (entry, letter) => ` ${STATE_WORDS[letter] ?? letter}: ${entry.originalPath ? `${entry.originalPath} -> ` : ""}${entry.path}`;
6108
+ const describe2 = (entry, letter) => ` ${STATE_WORDS[letter] ?? letter}: ${entry.originalPath ? `${entry.originalPath} -> ` : ""}${entry.path}`;
6038
6109
  const staged = status.entries.filter((entry) => (entry.kind === "changed" || entry.kind === "renamed") && entry.index !== ".");
6039
6110
  const unstaged = status.entries.filter((entry) => (entry.kind === "changed" || entry.kind === "renamed") && entry.worktree !== ".");
6040
6111
  const conflicts = status.entries.filter((entry) => entry.kind === "unmerged");
@@ -6042,9 +6113,9 @@ function renderStatus(status) {
6042
6113
  if (conflicts.length > 0)
6043
6114
  lines.push(`Conflicts (${conflicts.length}):`, ...conflicts.map((entry) => ` both ${entry.index}${entry.worktree}: ${entry.path}`));
6044
6115
  if (staged.length > 0)
6045
- lines.push(`Staged (${staged.length}):`, ...staged.map((entry) => describe(entry, entry.index)));
6116
+ lines.push(`Staged (${staged.length}):`, ...staged.map((entry) => describe2(entry, entry.index)));
6046
6117
  if (unstaged.length > 0)
6047
- lines.push(`Not staged (${unstaged.length}):`, ...unstaged.map((entry) => describe(entry, entry.worktree)));
6118
+ lines.push(`Not staged (${unstaged.length}):`, ...unstaged.map((entry) => describe2(entry, entry.worktree)));
6048
6119
  if (untracked.length > 0)
6049
6120
  lines.push(`Untracked (${untracked.length}):`, ...untracked.map((entry) => ` ${entry.path}`));
6050
6121
  if (status.entries.length === 0)
@@ -6202,7 +6273,7 @@ function createGitTools(options) {
6202
6273
  ];
6203
6274
  }
6204
6275
 
6205
- // ../core/src/cli/tools-extra/image.ts
6276
+ // packages/core/src/cli/tools-extra/image.ts
6206
6277
  function createImageTools(options) {
6207
6278
  const { root } = options;
6208
6279
  const limits = { ...resolvedLimits(options), maxReadBytes: MAX_IMAGE_BYTES };
@@ -6237,7 +6308,7 @@ function createImageTools(options) {
6237
6308
  ];
6238
6309
  }
6239
6310
 
6240
- // ../core/src/cli/tools-extra/notebook.ts
6311
+ // packages/core/src/cli/tools-extra/notebook.ts
6241
6312
  import { randomBytes } from "node:crypto";
6242
6313
  function toSourceLines(source) {
6243
6314
  if (source === "")
@@ -6418,7 +6489,7 @@ function createNotebookTools(options) {
6418
6489
  ];
6419
6490
  }
6420
6491
 
6421
- // ../core/src/cli/tools-extra/repo-map.ts
6492
+ // packages/core/src/cli/tools-extra/repo-map.ts
6422
6493
  var REPO_MAP_DEFAULT_CHARS = 12000;
6423
6494
  var REPO_MAP_MAX_CHARS = 60000;
6424
6495
  var ENTRY_NAMES = /(?:^|\/)(?:index|main|app|lib|mod|__init__|server|cli|program)\.[^/]+$/i;
@@ -6688,7 +6759,7 @@ ${lines.join(`
6688
6759
  ];
6689
6760
  }
6690
6761
 
6691
- // ../core/src/cli/tools-extra/symbols.ts
6762
+ // packages/core/src/cli/tools-extra/symbols.ts
6692
6763
  import { promises as fs8 } from "node:fs";
6693
6764
  import path8 from "node:path";
6694
6765
  var EXTENSIONS = {
@@ -7022,13 +7093,13 @@ class SymbolIndex {
7022
7093
  }
7023
7094
  }
7024
7095
 
7025
- // ../core/src/cli/tools-extra/index.ts
7096
+ // packages/core/src/cli/tools-extra/index.ts
7026
7097
  function createExtraTools(options) {
7027
7098
  const index = options.symbolIndex ?? new SymbolIndex(options.root, resolvedLimits(options));
7028
7099
  return [...createRepoMapTools(options, index), ...createGitTools(options), ...createNotebookTools(options), ...createImageTools(options)];
7029
7100
  }
7030
7101
 
7031
- // ../core/src/cli/tools.ts
7102
+ // packages/core/src/cli/tools.ts
7032
7103
  class TodoList {
7033
7104
  items = [];
7034
7105
  nextId = 1;
@@ -7299,6 +7370,7 @@ ${content}`,
7299
7370
  const updated = applyTextEdits(existing.content, edits, existing.path);
7300
7371
  await workspace.writeFile(filePath, updated.content);
7301
7372
  tracker.record(existing.path, updated.content);
7373
+ writtenFiles.add(existing.path);
7302
7374
  return {
7303
7375
  content: `Edited ${existing.path} (${updated.replacements} replacement${updated.replacements === 1 ? "" : "s"}).`,
7304
7376
  data: { path: existing.path, replacements: updated.replacements }
@@ -7310,7 +7382,11 @@ ${content}`,
7310
7382
  description: `Run a bounded command in the project root (builds, tests, linters). Dev servers go through start_application. ${workspace.commandGuidance}`,
7311
7383
  inputSchema: {
7312
7384
  type: "object",
7313
- properties: { command: { type: "string" }, timeoutMs: { type: "integer" } },
7385
+ properties: {
7386
+ command: { type: "string" },
7387
+ timeoutSeconds: { type: "integer", description: `Default and most: ${Math.round(commandTimeoutMs / 1000)}.` },
7388
+ timeoutMs: { type: "integer" }
7389
+ },
7314
7390
  required: ["command"],
7315
7391
  additionalProperties: false
7316
7392
  },
@@ -7330,7 +7406,7 @@ ${content}`,
7330
7406
  data: { command, reason: "persistent_foreground_command" }
7331
7407
  };
7332
7408
  }
7333
- const timeoutMs = Math.min(optionalInteger(args.timeoutMs, "timeoutMs") ?? commandTimeoutMs, commandTimeoutMs);
7409
+ const { timeoutMs, note: timeoutNote } = commandTimeout(args, commandTimeoutMs);
7334
7410
  const result = await workspace.runCommand(command, timeoutMs, context.signal);
7335
7411
  const body = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join(`
7336
7412
  `) || "(no output)";
@@ -7338,21 +7414,25 @@ ${content}`,
7338
7414
  if (missing) {
7339
7415
  return {
7340
7416
  content: `exit ${result.exitCode}
7341
- ${body}
7417
+ ${body}${timeoutNote ? `
7418
+
7419
+ [${timeoutNote}]` : ""}
7342
7420
 
7343
7421
  '${missing}' is not available in this environment. Do not retry this command. Use a program listed as available in the environment section, or check for an alternative with 'command -v' before running it.`,
7344
7422
  isError: true,
7345
7423
  data: { command, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr, missingProgram: missing }
7346
7424
  };
7347
7425
  }
7348
- const kind = classifyVerification(command) ?? (runsWrittenScript(command, writtenFiles) ? "smoke" : null);
7426
+ const kind = classifyVerification(command) ?? (runsWrittenScript(command, writtenFiles) ? "smoke" : null) ?? (runsInlineAssertion(command) ? "tests" : null);
7349
7427
  const rejectedVerification = kind && result.exitCode === 0 ? rejectedVerificationReason(command, result) : null;
7350
7428
  const verificationNote = rejectedVerification ? `
7351
7429
 
7352
7430
  Archymedes did not accept this as verification: ${rejectedVerification}` : "";
7353
7431
  return {
7354
7432
  content: `exit ${result.exitCode}
7355
- ${body}${verificationNote}`,
7433
+ ${body}${verificationNote}${timeoutNote ? `
7434
+
7435
+ [${timeoutNote}]` : ""}`,
7356
7436
  isError: result.exitCode !== 0,
7357
7437
  data: { command, exitCode: result.exitCode, stdout: result.stdout, stderr: result.stderr, ...kind && !rejectedVerification ? { verificationKind: kind } : {}, ...rejectedVerification ? { verificationRejectedReason: rejectedVerification } : {} },
7358
7438
  verification: kind && result.exitCode === 0 && !rejectedVerification ? { passed: true, kind, scope: "targeted", summary: `${command} exited 0` } : undefined
@@ -7959,10 +8039,16 @@ Written to ${scope === "project" ? ".archymedes/memory.md" : result.file} — th
7959
8039
  assertSupportedSchema(tool.name, tool.inputSchema);
7960
8040
  const schema = tool.inputSchema;
7961
8041
  const execute = tool.execute.bind(tool);
7962
- const withValidatedArguments = async (argumentsValue, context) => execute(validateToolArguments(tool.name, schema, argumentsValue), context);
8042
+ const withValidatedArguments = async (argumentsValue, context) => {
8043
+ const { value, notes } = normalizeToolArguments(tool.name, schema, argumentsValue);
8044
+ const result = await execute(value, context);
8045
+ return notes.length === 0 ? result : { ...result, content: `${result.content}
8046
+
8047
+ [Archymedes adjusted this call: ${notes.join("; ")}.]` };
8048
+ };
7963
8049
  const withInstructions = !instructions || !PATH_TOOLS.has(tool.name) ? withValidatedArguments : async (argumentsValue, context) => {
7964
8050
  const result = await withValidatedArguments(argumentsValue, context);
7965
- const touchedPath = typeof argumentsValue.path === "string" ? argumentsValue.path : undefined;
8051
+ const touchedPath = pathArgument(tool.name, schema, argumentsValue);
7966
8052
  if (!touchedPath || result.isError)
7967
8053
  return result;
7968
8054
  const note = NestedInstructionTracker.render(await instructions.discover(touchedPath));
@@ -7989,6 +8075,33 @@ ${warnings.join(`
7989
8075
  };
7990
8076
  });
7991
8077
  }
8078
+ function commandTimeout(args, ceilingMs) {
8079
+ const seconds = optionalInteger(args.timeoutSeconds, "timeoutSeconds");
8080
+ const millis = optionalInteger(args.timeoutMs, "timeoutMs");
8081
+ let asked;
8082
+ let note;
8083
+ if (seconds !== undefined)
8084
+ asked = seconds * 1000;
8085
+ else if (millis !== undefined && millis < 1000) {
8086
+ asked = millis * 1000;
8087
+ note = `timeoutMs ${millis} read as ${millis} seconds; use timeoutSeconds`;
8088
+ } else
8089
+ asked = millis;
8090
+ if (asked === undefined)
8091
+ return { timeoutMs: ceilingMs };
8092
+ if (asked > ceilingMs) {
8093
+ return { timeoutMs: ceilingMs, note: `${note ? `${note}; ` : ""}limited to the ${Math.round(ceilingMs / 1000)}s most a command may run` };
8094
+ }
8095
+ return { timeoutMs: Math.max(asked, 1000), ...note ? { note } : {} };
8096
+ }
8097
+ function pathArgument(toolName, schema, args) {
8098
+ try {
8099
+ const path9 = normalizeToolArguments(toolName, schema, args).value.path;
8100
+ return typeof path9 === "string" ? path9 : undefined;
8101
+ } catch {
8102
+ return;
8103
+ }
8104
+ }
7992
8105
  var PATH_TOOLS = new Set(["read_file", "write_file", "edit_file"]);
7993
8106
  function idList(value, name) {
7994
8107
  if (value === undefined || value === null)
@@ -8078,6 +8191,18 @@ function runsWrittenScript(command, written) {
8078
8191
  const clean = file.replace(/^(\.\/)+/, "");
8079
8192
  return [...written].some((path9) => clean === path9 || clean.endsWith(`/${path9}`));
8080
8193
  }
8194
+ function runsInlineAssertion(command) {
8195
+ let tokens;
8196
+ try {
8197
+ tokens = tokenizeCommand(verificationTarget(command));
8198
+ } catch {
8199
+ return false;
8200
+ }
8201
+ if (tokens.length < 3 || !SCRIPT_INTERPRETER.test(tokens[0].split("/").pop() ?? ""))
8202
+ return false;
8203
+ const flag = tokens.findIndex((token) => token === "-c" || token === "-e" || token === "--eval");
8204
+ return flag > 0 && flag + 1 < tokens.length && /\bassert\b|console\.assert|assert\.(?:equal|strictEqual|deepEqual|ok)\b/.test(tokens[flag + 1]);
8205
+ }
8081
8206
  function classifyVerification(command) {
8082
8207
  const target = verificationTarget(command);
8083
8208
  if (BEHAVIOR_COMMAND.test(target))
@@ -8095,7 +8220,7 @@ function stripMarkup(html) {
8095
8220
  `).replace(/[ \t]{2,}/g, " ").trim();
8096
8221
  }
8097
8222
 
8098
- // ../core/src/money.ts
8223
+ // packages/core/src/money.ts
8099
8224
  var CURRENCIES = (() => {
8100
8225
  try {
8101
8226
  return Intl.supportedValuesOf("currency");
@@ -8185,7 +8310,7 @@ function priceUsage(usage, prices) {
8185
8310
  return money(micros, prices.currency);
8186
8311
  }
8187
8312
 
8188
- // ../core/src/pricing.ts
8313
+ // packages/core/src/pricing.ts
8189
8314
  var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
8190
8315
  function assertDate(value, label) {
8191
8316
  if (!ISO_DATE.test(value) || Number.isNaN(Date.parse(value)))
@@ -8274,7 +8399,7 @@ function priceUnits(record, quantities) {
8274
8399
  return money(units * 1e6, record.currency);
8275
8400
  }
8276
8401
 
8277
- // ../core/src/providers/free-usage.ts
8402
+ // packages/core/src/providers/free-usage.ts
8278
8403
  import { promises as fs9 } from "node:fs";
8279
8404
  import path9 from "node:path";
8280
8405
  var FREE_REMAINING_TOKENS_HEADER = "x-free-remaining-tokens";
@@ -8414,7 +8539,7 @@ class FreeUsageMeter {
8414
8539
  }
8415
8540
  }
8416
8541
 
8417
- // ../core/src/cli/cost.ts
8542
+ // packages/core/src/cli/cost.ts
8418
8543
  function formatTokenFlow(usage) {
8419
8544
  return `↑${compactTokenCount(usage.inputTokens)} ↓${compactTokenCount(usage.outputTokens)} tok`;
8420
8545
  }
@@ -8690,10 +8815,10 @@ class CostLedger {
8690
8815
  }
8691
8816
  }
8692
8817
 
8693
- // ../core/src/cli/backends.ts
8818
+ // packages/core/src/cli/backends.ts
8694
8819
  import path11 from "node:path";
8695
8820
 
8696
- // ../core/src/sandbox-search.ts
8821
+ // packages/core/src/sandbox-search.ts
8697
8822
  var DEFAULT_IGNORED_DIRECTORIES = [".git", "node_modules", ".next", "dist", "build", "target", "__pycache__", ".venv", "venv", ".pytest_cache", ".mypy_cache", ".ruff_cache", ".turbo", "vendor", ".archymedes"];
8698
8823
  async function listSandboxFiles(sandbox, sandboxId, root, ignoredDirectories = DEFAULT_IGNORED_DIRECTORIES) {
8699
8824
  const result = await sandbox.runCommand(sandboxId, {
@@ -8767,7 +8892,7 @@ function relativeTo(root, absolute) {
8767
8892
  return absolute.startsWith(`${root}/`) ? absolute.slice(root.length + 1) : absolute;
8768
8893
  }
8769
8894
 
8770
- // ../core/src/cli/applications.ts
8895
+ // packages/core/src/cli/applications.ts
8771
8896
  import { spawn as spawn5 } from "node:child_process";
8772
8897
  import { stat } from "node:fs/promises";
8773
8898
  import http from "node:http";
@@ -8955,7 +9080,7 @@ The process produced no logs.`;
8955
9080
  }
8956
9081
  }
8957
9082
 
8958
- // ../core/src/cli/backends.ts
9083
+ // packages/core/src/cli/backends.ts
8959
9084
  var CONFIG_FILE_SCAN_LIMIT = 500;
8960
9085
  function localCommandGuidance(platform) {
8961
9086
  if (platform !== "win32")
@@ -9270,7 +9395,7 @@ async function downloadProject(workspace, localRoot, options = {}) {
9270
9395
  return { written, failed };
9271
9396
  }
9272
9397
 
9273
- // ../core/src/cli/artifacts.ts
9398
+ // packages/core/src/cli/artifacts.ts
9274
9399
  import { createHash as createHash6 } from "node:crypto";
9275
9400
  var ARTIFACT_DIRECTORY = ".archymedes/artifacts";
9276
9401
  var MAX_ARTIFACT_BYTES = 480000;
@@ -9314,12 +9439,12 @@ function countLines(content) {
9314
9439
  return lines;
9315
9440
  }
9316
9441
 
9317
- // ../core/src/cli/defender-brain.ts
9442
+ // packages/core/src/cli/defender-brain.ts
9318
9443
  import { access as access2 } from "node:fs/promises";
9319
9444
  import path14 from "node:path";
9320
9445
  import { fileURLToPath } from "node:url";
9321
9446
 
9322
- // ../core/src/cli/state-client.ts
9447
+ // packages/core/src/cli/state-client.ts
9323
9448
  import { spawn as spawn6 } from "node:child_process";
9324
9449
  import { access } from "node:fs/promises";
9325
9450
  import { createRequire } from "node:module";
@@ -9533,7 +9658,7 @@ async function tryConnectArchymedesState(options = {}) {
9533
9658
  return binary ? ArchymedesStateClient.connect({ ...options, binary }) : null;
9534
9659
  }
9535
9660
 
9536
- // ../core/src/cli/defender-feed.ts
9661
+ // packages/core/src/cli/defender-feed.ts
9537
9662
  import { createHash as createHash7, createPublicKey, verify as verifySignature } from "node:crypto";
9538
9663
  import { promises as fs10 } from "node:fs";
9539
9664
  import path13 from "node:path";
@@ -9762,7 +9887,7 @@ async function refreshDefenderFeed(options) {
9762
9887
  }
9763
9888
  }
9764
9889
 
9765
- // ../core/src/cli/defender-brain.ts
9890
+ // packages/core/src/cli/defender-brain.ts
9766
9891
  async function existingDirectory(candidates) {
9767
9892
  for (const candidate of candidates) {
9768
9893
  try {
@@ -9848,7 +9973,7 @@ class DefenderBrain {
9848
9973
  }
9849
9974
  }
9850
9975
 
9851
- // ../core/src/cli/tool-profile.ts
9976
+ // packages/core/src/cli/tool-profile.ts
9852
9977
  var MUTATING = /\b(create|write|edit|change|modify|fix|implement|build|install|delete|remove|rename|move|run|test|commit|push|deploy|publish|send|continue|resume|update|add|refactor|replace|rewrite|append|insert|generate|format|upgrade|bump|revert|patch|migrate|scaffold|save|set up|setup)\b/i;
9853
9978
  var REPOSITORY_READING = /\b(review|inspect|audit|analy[sz]e|diagnose|explain|find|locate|search|read|why|error|bug|code|repo(?:sitory)?|project|file|folder|function|class|test|diff)\b/i;
9854
9979
  var DIRECT_CHAT = /^(?:hi|hello|hey|thanks|thank you|who are you|what can you do)[.!?\s]*$/i;
@@ -9875,7 +10000,7 @@ function toolsForProfile(tools, profile) {
9875
10000
  return tools.filter((tool) => tool.effect === "none");
9876
10001
  }
9877
10002
 
9878
- // ../core/src/cli/jev.ts
10003
+ // packages/core/src/cli/jev.ts
9879
10004
  var JEV_API_URL = "https://api.typesafe.ai/v1/systemone";
9880
10005
  var JEV_DEFAULT_MODEL = "jev-latest";
9881
10006
  var JEV_TIMEOUT_MS = 30000;
@@ -10118,7 +10243,7 @@ function verdictFromResponse(response) {
10118
10243
  };
10119
10244
  }
10120
10245
 
10121
- // ../core/src/cli/agent.ts
10246
+ // packages/core/src/cli/agent.ts
10122
10247
  var DELEGATION_TOOLS = new Set(["delegate_task", "delegate_readonly_task"]);
10123
10248
  var EDIT_DIAGNOSTIC_TOOLS = new Set(["edit_file", "write_file"]);
10124
10249
  var EDIT_DIAGNOSTICS_TIMEOUT_MS = 3000;
@@ -10951,15 +11076,15 @@ function isActiveTurnStatus(status) {
10951
11076
  return status === "queued" || status === "running" || status === "waiting_approval";
10952
11077
  }
10953
11078
 
10954
- // ../core/src/cli/edit-diagnostics.ts
11079
+ // packages/core/src/cli/edit-diagnostics.ts
10955
11080
  import { promises as fs11 } from "node:fs";
10956
11081
  import path16 from "node:path";
10957
11082
  import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
10958
11083
 
10959
- // ../core/src/lsp/client.ts
11084
+ // packages/core/src/lsp/client.ts
10960
11085
  import { spawn as spawn7, spawnSync } from "node:child_process";
10961
11086
 
10962
- // ../core/src/lsp/diagnostics.ts
11087
+ // packages/core/src/lsp/diagnostics.ts
10963
11088
  function severityName(severity) {
10964
11089
  switch (severity) {
10965
11090
  case 1:
@@ -11065,7 +11190,7 @@ class DiagnosticsCollection {
11065
11190
  }
11066
11191
  }
11067
11192
 
11068
- // ../core/src/lsp/protocol.ts
11193
+ // packages/core/src/lsp/protocol.ts
11069
11194
  var HEADER_SEPARATOR = `\r
11070
11195
  \r
11071
11196
  `;
@@ -11111,7 +11236,7 @@ function isJsonRpcNotification3(value) {
11111
11236
  return typeof value === "object" && value !== null && "jsonrpc" in value && !("id" in value) && typeof value.method === "string";
11112
11237
  }
11113
11238
 
11114
- // ../core/src/lsp/client.ts
11239
+ // packages/core/src/lsp/client.ts
11115
11240
  class LspClientError extends Error {
11116
11241
  constructor(message) {
11117
11242
  super(message);
@@ -11322,7 +11447,7 @@ function toLocations(result) {
11322
11447
  return candidates.filter((candidate) => typeof candidate === "object" && candidate !== null && typeof candidate.uri === "string" && typeof candidate.range === "object");
11323
11448
  }
11324
11449
 
11325
- // ../core/src/lsp/servers.ts
11450
+ // packages/core/src/lsp/servers.ts
11326
11451
  import { spawnSync as spawnSync2 } from "node:child_process";
11327
11452
  var LANGUAGE_SERVERS = [
11328
11453
  {
@@ -11463,7 +11588,7 @@ function defaultProbe(command) {
11463
11588
  });
11464
11589
  }
11465
11590
 
11466
- // ../core/src/cli/edit-diagnostics.ts
11591
+ // packages/core/src/cli/edit-diagnostics.ts
11467
11592
  var DEFAULT_TIMEOUT_MS = 1500;
11468
11593
  var DEFAULT_REFINE_MS = 250;
11469
11594
  var DEFAULT_MAX_LINES = 20;
@@ -11684,7 +11809,7 @@ function createLspEditDiagnostics(root, options = {}) {
11684
11809
  });
11685
11810
  }
11686
11811
 
11687
- // ../core/src/providers/price-catalog.ts
11812
+ // packages/core/src/providers/price-catalog.ts
11688
11813
  var ANTHROPIC_VERIFIED = "2026-06-24";
11689
11814
  var ANTHROPIC_SOURCE = "anthropic.com/pricing, recorded 2026-06-24";
11690
11815
  var ANTHROPIC = [
@@ -11736,7 +11861,7 @@ var SERVICES = [
11736
11861
  ];
11737
11862
  var PRICE_CATALOG = definePrices([...ANTHROPIC, ...OAI_COMPAT_LABS, ...SERVICES]);
11738
11863
 
11739
- // ../core/src/providers/free-catalog.ts
11864
+ // packages/core/src/providers/free-catalog.ts
11740
11865
  var FREE_ROUTER = "openrouter/free";
11741
11866
  var FREE_BASE_URL = "https://openrouter.ai/api/v1";
11742
11867
  var FREE_GATEWAY_URL = "";
@@ -11886,7 +12011,7 @@ function isSmallModel(model) {
11886
12011
  return size !== null && size <= SMALL_MODEL_BILLIONS;
11887
12012
  }
11888
12013
 
11889
- // ../core/src/providers/provider-specs.ts
12014
+ // packages/core/src/providers/provider-specs.ts
11890
12015
  var PROVIDER_IDS = [
11891
12016
  "anthropic",
11892
12017
  "openai",
@@ -11947,7 +12072,7 @@ var PROVIDER_INFO = {
11947
12072
  }
11948
12073
  };
11949
12074
 
11950
- // ../core/src/providers/anthropic-agent.ts
12075
+ // packages/core/src/providers/anthropic-agent.ts
11951
12076
  async function collectAnthropicStream(stream, onTextDelta, onOutputProgress) {
11952
12077
  let id = "";
11953
12078
  let model = "";
@@ -12106,7 +12231,7 @@ class AnthropicAgentTurnProvider {
12106
12231
  let client;
12107
12232
  this.call = async (body, signal) => {
12108
12233
  if (!client) {
12109
- const { default: Anthropic } = await import("./index-qvgcwsvm.mjs").catch(() => {
12234
+ const { default: Anthropic } = await import("./index-teq1cta4.mjs").catch(() => {
12110
12235
  throw new Error("The Anthropic provider needs the @anthropic-ai/sdk package. Install it with: npm install @anthropic-ai/sdk");
12111
12236
  });
12112
12237
  client = new Anthropic({ apiKey: options.apiKey, ...options.baseURL ? { baseURL: options.baseURL } : {}, maxRetries: 0 });
@@ -12168,10 +12293,10 @@ class AnthropicAgentTurnProvider {
12168
12293
  }
12169
12294
  }
12170
12295
 
12171
- // ../core/src/providers/archymedes-cloud-agent.ts
12296
+ // packages/core/src/providers/archymedes-cloud-agent.ts
12172
12297
  import { createHash as createHash8, randomUUID as randomUUID5 } from "node:crypto";
12173
12298
 
12174
- // ../core/src/providers/routing-plan.ts
12299
+ // packages/core/src/providers/routing-plan.ts
12175
12300
  function isRecord2(value) {
12176
12301
  return typeof value === "object" && value !== null;
12177
12302
  }
@@ -12243,7 +12368,7 @@ function planCurrency(ranked) {
12243
12368
  return;
12244
12369
  }
12245
12370
 
12246
- // ../core/src/providers/credit-balance.ts
12371
+ // packages/core/src/providers/credit-balance.ts
12247
12372
  function isRecord3(value) {
12248
12373
  return typeof value === "object" && value !== null;
12249
12374
  }
@@ -12278,7 +12403,7 @@ function parseCreditBalance(value) {
12278
12403
  };
12279
12404
  }
12280
12405
 
12281
- // ../core/src/providers/archymedes-cloud-agent.ts
12406
+ // packages/core/src/providers/archymedes-cloud-agent.ts
12282
12407
  class ArchymedesCloudError extends Error {
12283
12408
  status;
12284
12409
  code;
@@ -12495,7 +12620,7 @@ async function readBody(response) {
12495
12620
  }
12496
12621
  }
12497
12622
 
12498
- // ../core/src/providers/request-pacer.ts
12623
+ // packages/core/src/providers/request-pacer.ts
12499
12624
  var MIN_LEARNABLE_CAP = 8;
12500
12625
  var LEARNED_CAP_LIFETIME_WINDOWS = 5;
12501
12626
  var DEFAULTS = { baseGapMs: 2000, maxGapMs: 120000, releaseMs: 500 };
@@ -12597,7 +12722,7 @@ class RequestPacer {
12597
12722
  }
12598
12723
  }
12599
12724
 
12600
- // ../core/src/providers/free-catalog-fetch.ts
12725
+ // packages/core/src/providers/free-catalog-fetch.ts
12601
12726
  var MAX_BYTES = 8 * 1024 * 1024;
12602
12727
  async function boundedJson(fetchImpl, url, signal) {
12603
12728
  const response = await fetchImpl(url, { signal, redirect: "error", headers: { accept: "application/json" } });
@@ -12661,7 +12786,7 @@ async function fetchFreeCatalog(options = {}) {
12661
12786
  }
12662
12787
  }
12663
12788
 
12664
- // ../core/src/providers/free-install.ts
12789
+ // packages/core/src/providers/free-install.ts
12665
12790
  import { promises as fs12 } from "node:fs";
12666
12791
  import path17 from "node:path";
12667
12792
  var FREE_INSTALL_HEADER = "x-archymedes-install";
@@ -12839,7 +12964,7 @@ class FreeInstallToken {
12839
12964
  }
12840
12965
  }
12841
12966
 
12842
- // ../core/src/providers/free-errors.ts
12967
+ // packages/core/src/providers/free-errors.ts
12843
12968
  var OPENROUTER_PRIVACY_SETTINGS_URL = "https://openrouter.ai/settings/privacy";
12844
12969
  var OPENROUTER_KEYS_URL = "https://openrouter.ai/keys";
12845
12970
  var OPENROUTER_CREDITS_URL = "https://openrouter.ai/settings/credits";
@@ -12915,7 +13040,7 @@ function describeFreeFailure(input) {
12915
13040
  return { message, retryable: transient, ...retryAfterMs2 ? { retryAfterMs: retryAfterMs2 } : {} };
12916
13041
  }
12917
13042
 
12918
- // ../core/src/providers/free-health.ts
13043
+ // packages/core/src/providers/free-health.ts
12919
13044
  import { promises as fs13 } from "node:fs";
12920
13045
  import path18 from "node:path";
12921
13046
  var FREE_HEALTH_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
@@ -13024,7 +13149,7 @@ class FreeHealthTracker {
13024
13149
  }
13025
13150
  }
13026
13151
 
13027
- // ../core/src/providers/openrouter-key-info.ts
13152
+ // packages/core/src/providers/openrouter-key-info.ts
13028
13153
  var OPENROUTER_KEY_URL = `${FREE_BASE_URL}/key`;
13029
13154
  var OPENROUTER_KEY_INFO_TTL_MS = 60000;
13030
13155
  var KEY_INFO_TIMEOUT_MS = 5000;
@@ -13127,7 +13252,7 @@ function nextUtcMidnight(now) {
13127
13252
  return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + 1)).toISOString();
13128
13253
  }
13129
13254
 
13130
- // ../core/src/providers/tool-call-repair.ts
13255
+ // packages/core/src/providers/tool-call-repair.ts
13131
13256
  function isObject(value) {
13132
13257
  return typeof value === "object" && value !== null && !Array.isArray(value);
13133
13258
  }
@@ -13237,7 +13362,7 @@ function repairToolCalls(calls) {
13237
13362
  });
13238
13363
  }
13239
13364
 
13240
- // ../core/src/providers/free-agent.ts
13365
+ // packages/core/src/providers/free-agent.ts
13241
13366
  var RETRYABLE_UPSTREAM_TYPES = new Set(["upstream_timeout", "upstream_idle_timeout", "upstream_unreachable", "upstream_stream_failed"]);
13242
13367
  function freeFailureStatus(error) {
13243
13368
  const record2 = error;
@@ -13289,6 +13414,8 @@ class FreeAccessError extends Error {
13289
13414
  this.status = status ?? undefined;
13290
13415
  }
13291
13416
  }
13417
+ var FREE_FIT_MARGIN = 1.5;
13418
+ var MIN_FREE_REPLY_TOKENS = 1024;
13292
13419
 
13293
13420
  class FreeAgentTurnProvider {
13294
13421
  options;
@@ -13376,11 +13503,13 @@ class FreeAgentTurnProvider {
13376
13503
  if (!candidates.length)
13377
13504
  throw new FreeAccessError("No eligible free tool model is available. Run /models refresh or try again later.");
13378
13505
  const messages = toWireMessages(request.messages);
13379
- const input = approximateInputTokens([JSON.stringify(messages), JSON.stringify(request.tools)]).maximumInputTokens;
13506
+ const input = Math.ceil(approximateInputTokens([JSON.stringify(messages), JSON.stringify(request.tools)]).expectedInputTokens * FREE_FIT_MARGIN);
13380
13507
  const output = Math.min(request.maxOutputTokens, this.capabilities.maxOutputTokens, ...candidates.map((model) => model.max_output ?? 4096));
13381
13508
  if (!Number.isSafeInteger(output) || output < 1)
13382
13509
  throw new FreeAccessError("Free mode requires a positive output token limit");
13383
- const fitting = candidates.filter((model) => model.context_window !== null && input + output <= model.context_window);
13510
+ const floor = Math.min(output, MIN_FREE_REPLY_TOKENS);
13511
+ const fitting = candidates.filter((model) => model.context_window !== null && input + floor <= model.context_window);
13512
+ const outputFor = (model) => Math.min(output, (model.context_window ?? input + output) - input);
13384
13513
  if (!fitting.length)
13385
13514
  throw new FreeAccessError("The conversation exceeds the available free model context. Start a new session or select a larger free model.");
13386
13515
  const preferred = this.options.model === FREE_ROUTER ? fitting.filter((model) => !this.refused.has(model.id)).sort((a, b) => rank(a.id) - rank(b.id) || (b.context_window ?? 0) - (a.context_window ?? 0) || a.id.localeCompare(b.id)) : fitting;
@@ -13409,7 +13538,7 @@ class FreeAgentTurnProvider {
13409
13538
  signal: userSignal
13410
13539
  });
13411
13540
  try {
13412
- const turn = await this.attempt(candidate.id, messages, output, request, onTextDelta, onOutputProgress, deadline);
13541
+ const turn = await this.attempt(candidate.id, messages, outputFor(candidate), request, onTextDelta, onOutputProgress, deadline);
13413
13542
  this.health?.record(candidate.id, { ok: true });
13414
13543
  this.pacer.reportSuccess();
13415
13544
  return turn;
@@ -13512,7 +13641,7 @@ class FreeAgentTurnProvider {
13512
13641
  }
13513
13642
  }
13514
13643
 
13515
- // ../core/src/providers/openrouter-agent.ts
13644
+ // packages/core/src/providers/openrouter-agent.ts
13516
13645
  var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
13517
13646
 
13518
13647
  class OpenRouterAgentTurnProvider {
@@ -13561,7 +13690,7 @@ function withHint(error) {
13561
13690
  return wrapped;
13562
13691
  }
13563
13692
 
13564
- // ../core/src/providers/agent-matrix.ts
13693
+ // packages/core/src/providers/agent-matrix.ts
13565
13694
  var OPENAI_COMPATIBLE_BASE_URL = {
13566
13695
  google: "https://generativelanguage.googleapis.com/v1beta/openai/",
13567
13696
  xai: "https://api.x.ai/v1",
@@ -13581,7 +13710,8 @@ function openAiCompatibleSpec(id) {
13581
13710
  create: (environment, model) => new OpenAIAgentTurnProvider({
13582
13711
  apiKey: environment[`${prefix}_API_KEY`]?.trim() || "local",
13583
13712
  model,
13584
- baseURL: environment[`${prefix}_BASE_URL`]?.trim() || fallbackBase
13713
+ baseURL: environment[`${prefix}_BASE_URL`]?.trim() || fallbackBase,
13714
+ dialect: VENDOR_DIALECTS[id]
13585
13715
  })
13586
13716
  };
13587
13717
  }
@@ -13726,7 +13856,7 @@ function describeProviders(environment) {
13726
13856
  }
13727
13857
  var PRICE_ENVIRONMENT_HINT = "MODEL_INPUT_PER_MILLION, MODEL_OUTPUT_PER_MILLION (and optionally MODEL_CACHED_INPUT_PER_MILLION, MODEL_PRICE_CURRENCY, MODEL_PRICE_MODEL)";
13728
13858
 
13729
- // src/app/session-provider.ts
13859
+ // packages/archymedes-cli/src/app/session-provider.ts
13730
13860
  async function resolveSessionProvider(environment, options) {
13731
13861
  if (options.provider || !options.resume)
13732
13862
  return resolveProvider(environment, options);
@@ -13735,12 +13865,12 @@ async function resolveSessionProvider(environment, options) {
13735
13865
  return resolveProvider(environment, selection?.provider === "free" ? { provider: "free", model: options.model ?? selection.model } : options);
13736
13866
  }
13737
13867
 
13738
- // src/platform/settings.ts
13868
+ // packages/archymedes-cli/src/platform/settings.ts
13739
13869
  import { promises as fs15 } from "node:fs";
13740
13870
  import os4 from "node:os";
13741
13871
  import path20 from "node:path";
13742
13872
 
13743
- // src/platform/i18n.ts
13873
+ // packages/archymedes-cli/src/platform/i18n.ts
13744
13874
  var CONTROL_LANGUAGES = {
13745
13875
  en: "English",
13746
13876
  zh: "中文 (Mandarin)",
@@ -14207,11 +14337,11 @@ function t(language, key) {
14207
14337
  return MESSAGES[key][language] ?? MESSAGES[key].en;
14208
14338
  }
14209
14339
 
14210
- // src/platform/local-currency.ts
14340
+ // packages/archymedes-cli/src/platform/local-currency.ts
14211
14341
  import { promises as fs14 } from "node:fs";
14212
14342
  import path19 from "node:path";
14213
14343
 
14214
- // src/platform/endpoints.ts
14344
+ // packages/archymedes-cli/src/platform/endpoints.ts
14215
14345
  var FX_ENDPOINTS = [
14216
14346
  "https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies",
14217
14347
  "https://latest.currency-api.pages.dev/v1/currencies"
@@ -14255,7 +14385,7 @@ function hostOf(url) {
14255
14385
  }
14256
14386
  }
14257
14387
 
14258
- // src/platform/network.ts
14388
+ // packages/archymedes-cli/src/platform/network.ts
14259
14389
  var CODES = {
14260
14390
  dns: ["ENOTFOUND", "EAI_AGAIN", "EAI_NONAME", "EAI_FAIL", "EAI_MEMORY", "EAI_SYSTEM", "DNS_E_NAME_NOT_FOUND", "DNS_E_QUERY_PENDING"],
14261
14391
  timeout: ["ETIMEDOUT", "UND_ERR_CONNECT_TIMEOUT", "UND_ERR_HEADERS_TIMEOUT", "UND_ERR_BODY_TIMEOUT", "ERR_SOCKET_CONNECTION_TIMEOUT", "connection_timeout"],
@@ -14504,7 +14634,7 @@ function classifyNetworkError(error, options = {}) {
14504
14634
  return null;
14505
14635
  }
14506
14636
 
14507
- // src/platform/local-currency.ts
14637
+ // packages/archymedes-cli/src/platform/local-currency.ts
14508
14638
  var COUNTRY_CURRENCIES = {
14509
14639
  RW: "RWF",
14510
14640
  EG: "EGP",
@@ -14632,7 +14762,7 @@ async function startFxRateLookup(from, to, options) {
14632
14762
  return { immediate: cached?.rate ?? null, refresh };
14633
14763
  }
14634
14764
 
14635
- // src/theme/theme.ts
14765
+ // packages/archymedes-cli/src/theme/theme.ts
14636
14766
  var BLUEPRINT = `
14637
14767
  /* Blueprint navy, chalk-white ink and an amber pencil — the original drafting table. */
14638
14768
  @theme blueprint {
@@ -14934,7 +15064,7 @@ function roleCode(role, palette, depth) {
14934
15064
  }
14935
15065
  var NO_COLOR_PALETTE = buildPalette(findBuiltinTheme(DEFAULT_THEME_NAME) ?? { name: DEFAULT_THEME_NAME, description: "", tokens: DEFAULT_TOKENS }, "none");
14936
15066
 
14937
- // src/platform/settings.ts
15067
+ // packages/archymedes-cli/src/platform/settings.ts
14938
15068
  var LANGUAGE_NAMES = {
14939
15069
  en: "English",
14940
15070
  zh: "中文",
@@ -15318,14 +15448,14 @@ async function runSettingsMenu(current, prompts, options = {}) {
15318
15448
  for (;; ) {
15319
15449
  const language = resolveControlLanguage(settings.ARCHYMEDES_LANGUAGE);
15320
15450
  const fields = focused ? PROVIDER_KEY_FIELDS : SETTING_FIELDS;
15321
- const describe = (field2) => {
15451
+ const describe2 = (field2) => {
15322
15452
  const value = settings[field2.key];
15323
15453
  return "secret" in field2 && field2.secret ? maskSetting(value) : value || "not set";
15324
15454
  };
15325
15455
  let selection;
15326
15456
  if (prompts.choose) {
15327
15457
  const items = [
15328
- ...fields.map((field2) => ({ value: { kind: "field", key: field2.key }, label: field2.label, hint: describe(field2), ...focused ? {} : { header: sectionOf(field2.key) } })),
15458
+ ...fields.map((field2) => ({ value: { kind: "field", key: field2.key }, label: field2.label, hint: describe2(field2), ...focused ? {} : { header: sectionOf(field2.key) } })),
15329
15459
  ...focused ? [{ value: { kind: "expand" }, label: "Everything else", description: "base URLs, models, pricing, voice, keys", pinned: true }] : [],
15330
15460
  { value: { kind: "done" }, label: `${controlLabel(language, "saved")} / ${controlLabel(language, "exit")}`, pinned: true }
15331
15461
  ];
@@ -15351,7 +15481,7 @@ Archymedes ${controlLabel(language, "settings")}
15351
15481
  prompts.write(` ${section}
15352
15482
  `);
15353
15483
  lastSection = section;
15354
- prompts.write(` ${String(index + 1).padStart(2)}. ${field2.label}: ${describe(field2)}
15484
+ prompts.write(` ${String(index + 1).padStart(2)}. ${field2.label}: ${describe2(field2)}
15355
15485
  `);
15356
15486
  });
15357
15487
  if (focused)
@@ -15435,7 +15565,7 @@ Archymedes ${controlLabel(language, "settings")}
15435
15565
  }
15436
15566
  }
15437
15567
 
15438
- // src/app/free-setup.ts
15568
+ // packages/archymedes-cli/src/app/free-setup.ts
15439
15569
  var OPENROUTER_KEYS_URL2 = "https://openrouter.ai/keys";
15440
15570
  var FREE_PRIVACY_NOTICE = "Free models may log your prompts and code; don't send secrets. Use a paid provider for private code.";
15441
15571
  function needsFreePrivacyNotice(environment) {
@@ -15454,11 +15584,11 @@ async function showFreePrivacyNoticeOnce(options) {
15454
15584
  return next;
15455
15585
  }
15456
15586
 
15457
- // ../core/src/providers/model-fetch.ts
15587
+ // packages/core/src/providers/model-fetch.ts
15458
15588
  import { promises as fs16 } from "node:fs";
15459
15589
  import path21 from "node:path";
15460
15590
 
15461
- // ../core/src/providers/model-list.ts
15591
+ // packages/core/src/providers/model-list.ts
15462
15592
  function modelsUrl(base) {
15463
15593
  const trimmed = base.replace(/\/+$/, "");
15464
15594
  return trimmed.endsWith("/v1") ? `${trimmed}/models` : `${trimmed}/v1/models`;
@@ -15541,7 +15671,8 @@ var NON_CHAT = [
15541
15671
  /embed/i,
15542
15672
  /moderation/i,
15543
15673
  /whisper/i,
15544
- /^tts/i,
15674
+ /tts/i,
15675
+ /orpheus/i,
15545
15676
  /audio/i,
15546
15677
  /dall-?e/i,
15547
15678
  /^stable-/i,
@@ -15568,7 +15699,7 @@ function mergeModelLists(known, live) {
15568
15699
  const added = live.filter((model) => !seen.has(model)).sort();
15569
15700
  return [...known, ...added];
15570
15701
  }
15571
- // ../core/src/providers/model-fetch.ts
15702
+ // packages/core/src/providers/model-fetch.ts
15572
15703
  async function fetchProviderModels(provider, environment, fetchImpl, timeoutMs = 4000) {
15573
15704
  if (provider === "free") {
15574
15705
  try {
@@ -15656,7 +15787,7 @@ function fetchableProviders(environment, providers) {
15656
15787
  return providers.filter((provider) => provider !== "archymedes-cloud" && missingRequirements(provider, environment).length === 0);
15657
15788
  }
15658
15789
 
15659
- // src/app/acp-connect.ts
15790
+ // packages/archymedes-cli/src/app/acp-connect.ts
15660
15791
  var DEFAULT_BASE_URLS = {
15661
15792
  anthropic: "https://api.anthropic.com",
15662
15793
  openai: "https://api.openai.com/v1",
@@ -15783,7 +15914,7 @@ async function rememberModel(params, deps) {
15783
15914
  return { ok: true };
15784
15915
  }
15785
15916
 
15786
- // src/app/acp-setup.ts
15917
+ // packages/archymedes-cli/src/app/acp-setup.ts
15787
15918
  var KEY_URLS = {
15788
15919
  free: OPENROUTER_KEYS_URL2,
15789
15920
  openrouter: OPENROUTER_KEYS_URL2,
@@ -15855,7 +15986,7 @@ function providerOverview(environment) {
15855
15986
  });
15856
15987
  }
15857
15988
 
15858
- // src/session/models.ts
15989
+ // packages/archymedes-cli/src/session/models.ts
15859
15990
  function modelsForProvider(provider, asOf) {
15860
15991
  const seen = new Set;
15861
15992
  for (const record2 of PRICE_CATALOG) {
@@ -15879,7 +16010,7 @@ function describePrice(prices, display, convert2) {
15879
16010
  return `${formatMoney(input)}/${formatMoney(output)} per Mtok`;
15880
16011
  }
15881
16012
 
15882
- // src/app/acp-models.ts
16013
+ // packages/archymedes-cli/src/app/acp-models.ts
15883
16014
  var PUBLIC_LISTINGS = ["free", "openrouter"];
15884
16015
  async function modelList(environment, params, options = {}) {
15885
16016
  const offline = /^(1|true|on|yes)$/i.test(environment.ARCHYMEDES_MODELS_OFFLINE?.trim() ?? "");
@@ -15931,7 +16062,7 @@ async function modelList(environment, params, options = {}) {
15931
16062
  return { choices: [...ready, ...locked], unconfigured, errors, providers: PROVIDER_IDS.length };
15932
16063
  }
15933
16064
 
15934
- // src/app/acp-commands.ts
16065
+ // packages/archymedes-cli/src/app/acp-commands.ts
15935
16066
  async function runSessionCommand(command, argument, session) {
15936
16067
  switch (command) {
15937
16068
  case "cost":
@@ -16009,7 +16140,7 @@ async function memoryCommand(argument, root) {
16009
16140
  }
16010
16141
  }
16011
16142
 
16012
- // src/app/acp-settings.ts
16143
+ // packages/archymedes-cli/src/app/acp-settings.ts
16013
16144
  async function listSettings(processEnvironment) {
16014
16145
  const stored = await loadSettings(processEnvironment);
16015
16146
  const rows = SETTING_FIELDS.map((field) => {
@@ -16061,10 +16192,10 @@ async function setSetting(params, deps) {
16061
16192
  return { ok: true, file, value: secret && stored ? maskSetting(stored) : stored, isSet: stored !== "" };
16062
16193
  }
16063
16194
 
16064
- // src/app/startup-update.ts
16195
+ // packages/archymedes-cli/src/app/startup-update.ts
16065
16196
  import { spawn as spawn8 } from "node:child_process";
16066
16197
 
16067
- // src/platform/auto-update.ts
16198
+ // packages/archymedes-cli/src/platform/auto-update.ts
16068
16199
  import { promises as fs17 } from "node:fs";
16069
16200
  import path22 from "node:path";
16070
16201
  var AUTO_UPDATE_INTERVAL_MS = 24 * 60 * 60 * 1000;
@@ -16177,7 +16308,7 @@ async function runAutoUpdate(options) {
16177
16308
  return { notice: [], decision };
16178
16309
  }
16179
16310
 
16180
- // src/platform/defender-feed-update.ts
16311
+ // packages/archymedes-cli/src/platform/defender-feed-update.ts
16181
16312
  var OFFICIAL_DEFENDER_FEED_URL = "https://circuit-archymedes.vercel.app/api/defender-brain/manifest";
16182
16313
  var OFFICIAL_DEFENDER_FEED_KEYS = Object.freeze({
16183
16314
  "release-2026-01": "MCowBQYDK2VwAyEA4/jb1zd6f+jIPAFja1bPNtroXV8MtAZFrKt5BSY+ngI="
@@ -16205,12 +16336,12 @@ async function updateDefenderFeed(environment) {
16205
16336
  });
16206
16337
  }
16207
16338
 
16208
- // src/platform/update.ts
16339
+ // packages/archymedes-cli/src/platform/update.ts
16209
16340
  import { spawnSync as spawnSync3 } from "node:child_process";
16210
16341
  import { tmpdir } from "node:os";
16211
16342
  import { createInterface as createInterface3 } from "node:readline/promises";
16212
16343
 
16213
- // src/catalog/commands.ts
16344
+ // packages/archymedes-cli/src/catalog/commands.ts
16214
16345
  function defineCommands(table) {
16215
16346
  return Object.entries(table).map(([name, command]) => ({ name, ...command }));
16216
16347
  }
@@ -16283,7 +16414,7 @@ function renderCommandHelp(language = "en", shortcuts = new Map, options = {}) {
16283
16414
  `);
16284
16415
  }
16285
16416
 
16286
- // src/terminal/keybindings.ts
16417
+ // packages/archymedes-cli/src/terminal/keybindings.ts
16287
16418
  var FUNCTION_KEY = /^f([1-9]|1[0-2])$/;
16288
16419
  var NAMED_KEYS = new Set(["tab", "enter", "escape", "space", "up", "down", "left", "right", "home", "end", "pageup", "pagedown", "backspace", "delete"]);
16289
16420
  function isKeyName(value) {
@@ -16533,10 +16664,10 @@ function escapeCodeTimeoutMs(environment = process.env) {
16533
16664
  const parsed = raw ? Number(raw) : NaN;
16534
16665
  return Number.isInteger(parsed) && parsed >= 10 && parsed <= 2000 ? parsed : DEFAULT_ESCAPE_CODE_TIMEOUT_MS;
16535
16666
  }
16536
- // package.json
16667
+ // packages/archymedes-cli/package.json
16537
16668
  var package_default = {
16538
16669
  name: "archymedes-cli",
16539
- version: "3.4.0",
16670
+ version: "3.5.1",
16540
16671
  description: "Archymedes CLI — a coding agent that shows its work. Runs against your working tree or an isolated remote sandbox, with guarded approvals, git checkpoints, and exact, measured cost accounting.",
16541
16672
  keywords: [
16542
16673
  "cli",
@@ -16582,12 +16713,12 @@ var package_default = {
16582
16713
  prepublishOnly: "bun run ../../tooling/build/build-packages.ts"
16583
16714
  },
16584
16715
  optionalDependencies: {
16585
- "@archymedes/cli-darwin-arm64": "3.4.0",
16586
- "@archymedes/cli-darwin-x64": "3.4.0",
16587
- "@archymedes/cli-linux-arm64": "3.4.0",
16588
- "@archymedes/cli-linux-x64": "3.4.0",
16589
- "@archymedes/cli-win32-arm64": "3.4.0",
16590
- "@archymedes/cli-win32-x64": "3.4.0",
16716
+ "@archymedes/cli-darwin-arm64": "3.5.1",
16717
+ "@archymedes/cli-darwin-x64": "3.5.1",
16718
+ "@archymedes/cli-linux-arm64": "3.5.1",
16719
+ "@archymedes/cli-linux-x64": "3.5.1",
16720
+ "@archymedes/cli-win32-arm64": "3.5.1",
16721
+ "@archymedes/cli-win32-x64": "3.5.1",
16591
16722
  "@archymedes/state-darwin-arm64": "0.4.0",
16592
16723
  "@archymedes/state-darwin-x64": "0.4.0",
16593
16724
  "@archymedes/state-linux-arm64-gnu": "0.4.0",
@@ -16599,7 +16730,7 @@ var package_default = {
16599
16730
  }
16600
16731
  };
16601
16732
 
16602
- // src/platform/update.ts
16733
+ // packages/archymedes-cli/src/platform/update.ts
16603
16734
  var ARCHYMEDES_CLI_PACKAGE = "archymedes-cli";
16604
16735
  var ARCHYMEDES_CLI_VERSION = package_default.version;
16605
16736
  var DEFAULT_REGISTRY = "https://registry.npmjs.org";
@@ -16817,7 +16948,7 @@ async function runSelfUpdate(options = {}) {
16817
16948
  return { status: "updated", currentVersion, latestVersion, code: 0 };
16818
16949
  }
16819
16950
 
16820
- // src/text/ansi.ts
16951
+ // packages/archymedes-cli/src/text/ansi.ts
16821
16952
  var RESET = "\x1B[0m";
16822
16953
  var BOLD = "\x1B[1m";
16823
16954
  var DIM = "\x1B[2m";
@@ -16830,7 +16961,7 @@ function paintAll(text, codes, depth) {
16830
16961
  return depth === "none" || codes.length === 0 ? text : `${codes.join("")}${text}${RESET}`;
16831
16962
  }
16832
16963
 
16833
- // src/terminal/output.ts
16964
+ // packages/archymedes-cli/src/terminal/output.ts
16834
16965
  var terminalStream = {
16835
16966
  write(text) {
16836
16967
  process.stdout.write(text);
@@ -16864,7 +16995,7 @@ class OutputRouter {
16864
16995
  }
16865
16996
  }
16866
16997
 
16867
- // src/text/glyphs.ts
16998
+ // packages/archymedes-cli/src/text/glyphs.ts
16868
16999
  var UNICODE_GLYPHS = {
16869
17000
  starGlyphs: [".", "·", "✧", "✦", "✶"],
16870
17001
  spinnerFrames: [" ◜ ", " ◠ ", " ◝ ", " ◞ ", " ◡ ", " ◟ "],
@@ -16971,7 +17102,7 @@ function borderGlyphsFor(style, glyphs) {
16971
17102
  return ROUND_BORDER;
16972
17103
  }
16973
17104
 
16974
- // src/text/text-width.ts
17105
+ // packages/archymedes-cli/src/text/text-width.ts
16975
17106
  var ANSI = /\x1b\[[0-9;]*m/g;
16976
17107
  var PRINTABLE_ASCII = /^[\x20-\x7e]*$/;
16977
17108
  function visibleWidth(text) {
@@ -17006,7 +17137,7 @@ function clipTo(text, width, glyphs = UNICODE_GLYPHS) {
17006
17137
  return `${out}${mark}`;
17007
17138
  }
17008
17139
 
17009
- // src/render/syntax.ts
17140
+ // packages/archymedes-cli/src/render/syntax.ts
17010
17141
  function newSyntaxState() {
17011
17142
  return {};
17012
17143
  }
@@ -17653,7 +17784,7 @@ function highlightSyntax(line, options) {
17653
17784
  return `${out}${RESET}`;
17654
17785
  }
17655
17786
 
17656
- // src/render/markdown.ts
17787
+ // packages/archymedes-cli/src/render/markdown.ts
17657
17788
  var colour = (role, palette) => palette?.[role] || ANSI_PALETTE[role];
17658
17789
  var INLINE_PATTERN = /(?<!\\)(`[^`\n]+`)|(?<!\\)(\*\*[^*\n]+\*\*)|(?<!\\)(__[^_\n]+__)|(?<!\\)(~~[^~\n]+~~)|(?<!\\)(\*[^*\n]+\*)|(?<!\\)(_[^_\n]+_)|(!?\[([^\]\n]+)\]\((https?:\/\/[^\s)\n]+)\))|(<(https?:\/\/[^>\s]+)>)/g;
17659
17790
  var unescapeMarkdown = (text) => text.replace(/\\([\\`*_[\]{}()#+.!~>-])/g, "$1");
@@ -17874,7 +18005,7 @@ function renderMarkdown(text, options) {
17874
18005
  `);
17875
18006
  }
17876
18007
 
17877
- // src/render/tui.ts
18008
+ // packages/archymedes-cli/src/render/tui.ts
17878
18009
  function archymedesSpinnerFrame(index, glyphs = UNICODE_GLYPHS) {
17879
18010
  const frames = glyphs.spinnerFrames;
17880
18011
  const normalized = Number.isFinite(index) ? Math.max(0, Math.floor(index)) : 0;
@@ -18462,7 +18593,7 @@ function wrapPlain(text, width) {
18462
18593
  return lines.length === 0 ? [""] : lines;
18463
18594
  }
18464
18595
 
18465
- // src/render/transcript.ts
18596
+ // packages/archymedes-cli/src/render/transcript.ts
18466
18597
  function truncateMiddle(value, maximum) {
18467
18598
  const clean = value.replace(/\s+/g, " ").trim();
18468
18599
  if (clean.length <= maximum)
@@ -18625,7 +18756,7 @@ function summarizeToolResult(toolName, content, isError) {
18625
18756
  }
18626
18757
  }
18627
18758
 
18628
- // src/render/sections.ts
18759
+ // packages/archymedes-cli/src/render/sections.ts
18629
18760
  var TONE_ROLE = {
18630
18761
  good: "success",
18631
18762
  bad: "error",
@@ -18752,7 +18883,7 @@ function outcomeMark(outcome, style) {
18752
18883
  }
18753
18884
  }
18754
18885
 
18755
- // src/render/code-view.ts
18886
+ // packages/archymedes-cli/src/render/code-view.ts
18756
18887
  var MAX_DIFF_CELLS = 250000;
18757
18888
  function diffLines(before, after) {
18758
18889
  const left = before === "" ? [] : before.split(`
@@ -19049,7 +19180,7 @@ function renderFileChange(change, style, options = {}) {
19049
19180
  };
19050
19181
  }
19051
19182
 
19052
- // src/render/test-report.ts
19183
+ // packages/archymedes-cli/src/render/test-report.ts
19053
19184
  function toMs(value) {
19054
19185
  if (!value)
19055
19186
  return;
@@ -19324,7 +19455,7 @@ function renderTestReport(report, style, options = {}) {
19324
19455
  `);
19325
19456
  }
19326
19457
 
19327
- // src/render/expandable.ts
19458
+ // packages/archymedes-cli/src/render/expandable.ts
19328
19459
  var MAX_ENTRIES = 64;
19329
19460
 
19330
19461
  class ExpandableStore {
@@ -19358,7 +19489,7 @@ function expandHint(id, hidden, depth, glyphs = UNICODE_GLYPHS) {
19358
19489
  return paint(`${glyphs.collapsed} ${hidden} more line${hidden === 1 ? "" : "s"} hidden ${glyphs.middot} /expand ${id}`, DIM, depth);
19359
19490
  }
19360
19491
 
19361
- // src/app/transcript.ts
19492
+ // packages/archymedes-cli/src/app/transcript.ts
19362
19493
  var colorEnabled = false;
19363
19494
  var wrap = (code) => (value) => colorEnabled ? `${code}${value}${RESET}` : value;
19364
19495
  var palette = NO_COLOR_PALETTE;
@@ -19438,7 +19569,7 @@ function beginTranscriptTurn() {
19438
19569
  markdown.reset();
19439
19570
  }
19440
19571
 
19441
- // src/app/startup-update.ts
19572
+ // packages/archymedes-cli/src/app/startup-update.ts
19442
19573
  async function startupMaintenance(environment, interactive, install) {
19443
19574
  updateDefenderFeed(environment).catch(() => {
19444
19575
  return;
@@ -19477,7 +19608,7 @@ function installInChildProcess(entry, environment) {
19477
19608
  });
19478
19609
  }
19479
19610
 
19480
- // src/app/jev.ts
19611
+ // packages/archymedes-cli/src/app/jev.ts
19481
19612
  function jevOptionsFromEnvironment(environment) {
19482
19613
  if ((environment.ARCHYMEDES_JEV ?? "").trim().toLowerCase() === "off")
19483
19614
  return;
@@ -19488,7 +19619,7 @@ function jevOptionsFromEnvironment(environment) {
19488
19619
  return { apiKey, ...model ? { model } : {}, ...environment.ARCHYMEDES_JEV_REVIEW?.trim().toLowerCase() === "off" ? { review: false } : {} };
19489
19620
  }
19490
19621
 
19491
- // ../core/src/providers/exa.ts
19622
+ // packages/core/src/providers/exa.ts
19492
19623
  var LATENCY_CEILING = {
19493
19624
  instant: 5000,
19494
19625
  fast: 1e4,
@@ -19694,7 +19825,7 @@ function createExaClient(environment, fetchImpl) {
19694
19825
  });
19695
19826
  }
19696
19827
 
19697
- // src/acp-server.ts
19828
+ // packages/archymedes-cli/src/acp-server.ts
19698
19829
  function splitFrames(buffer) {
19699
19830
  const parts = buffer.split(`
19700
19831
  `);
@@ -19865,10 +19996,10 @@ function priceCatalogFor(prices) {
19865
19996
  };
19866
19997
  }
19867
19998
 
19868
- // src/app/args.ts
19999
+ // packages/archymedes-cli/src/app/args.ts
19869
20000
  import path23 from "node:path";
19870
20001
 
19871
- // src/render/charts.ts
20002
+ // packages/archymedes-cli/src/render/charts.ts
19872
20003
  function barChart(data, options) {
19873
20004
  if (data.length === 0)
19874
20005
  return [];
@@ -19893,7 +20024,7 @@ function barChart(data, options) {
19893
20024
  });
19894
20025
  }
19895
20026
 
19896
- // src/commands/chat-history.ts
20027
+ // packages/archymedes-cli/src/commands/chat-history.ts
19897
20028
  function countTurns(messages) {
19898
20029
  return messages.filter((message) => message.role === "user" && !message.internal).length;
19899
20030
  }
@@ -20086,7 +20217,7 @@ function parseHistoryCommand(input) {
20086
20217
  return { kind: "invalid", reason: `/history takes "list", a session id, "search <text>", "delete <id>", "status", or "resume" — not "${verb}".` };
20087
20218
  }
20088
20219
 
20089
- // src/commands/pacing.ts
20220
+ // packages/archymedes-cli/src/commands/pacing.ts
20090
20221
  var PACE_PROFILES = {
20091
20222
  off: {
20092
20223
  level: "off",
@@ -20148,7 +20279,7 @@ function paceBadge(level, glyphs2 = UNICODE_GLYPHS) {
20148
20279
  return `${glyphs2.paused} ${profileFor(level).label}`;
20149
20280
  }
20150
20281
 
20151
- // src/app/args.ts
20282
+ // packages/archymedes-cli/src/app/args.ts
20152
20283
  var SESSION_ID2 = /^\d{8}T\d{6}Z-[a-z0-9]{6}$/;
20153
20284
  var DEFAULT_DOCKER_IMAGE = "debian:stable-slim";
20154
20285
  function parseArgs(argv) {
@@ -20346,7 +20477,7 @@ function parseArgs(argv) {
20346
20477
  return parsed;
20347
20478
  }
20348
20479
 
20349
- // src/app/session-provider.ts
20480
+ // packages/archymedes-cli/src/app/session-provider.ts
20350
20481
  async function resolveSessionProvider2(environment, options) {
20351
20482
  if (options.provider || !options.resume)
20352
20483
  return resolveProvider(environment, options);
@@ -20355,7 +20486,7 @@ async function resolveSessionProvider2(environment, options) {
20355
20486
  return resolveProvider(environment, selection?.provider === "free" ? { provider: "free", model: options.model ?? selection.model } : options);
20356
20487
  }
20357
20488
 
20358
- // src/app/transcript.ts
20489
+ // packages/archymedes-cli/src/app/transcript.ts
20359
20490
  var colorEnabled2 = false;
20360
20491
  var liveTerminal2 = false;
20361
20492
  var wrap2 = (code) => (value) => colorEnabled2 ? `${code}${value}${RESET}` : value;
@@ -20669,7 +20800,7 @@ ${rule(sectionStyle2(), { label: "tool activity", tone: "neutral" })}
20669
20800
  }
20670
20801
  }
20671
20802
 
20672
- // ../core/src/cli/suggestions.ts
20803
+ // packages/core/src/cli/suggestions.ts
20673
20804
  var CATEGORY_ORDER = ["blocked", "recovery", "next", "discover", "starter"];
20674
20805
  function defaultSignals(overrides = {}) {
20675
20806
  return {
@@ -21066,7 +21197,7 @@ async function askModelForSuggestions(model, signals, context = {}) {
21066
21197
  }
21067
21198
  }
21068
21199
 
21069
- // src/ui/chooser.ts
21200
+ // packages/archymedes-cli/src/ui/chooser.ts
21070
21201
  var ALL_CHROME = { title: true, status: true, pagination: true, help: true };
21071
21202
  function chromeOf(chrome) {
21072
21203
  return { ...ALL_CHROME, ...chrome };
@@ -21294,7 +21425,7 @@ async function runChooser(keys, items, paint2, options) {
21294
21425
  return;
21295
21426
  }
21296
21427
 
21297
- // src/ui/navigation.ts
21428
+ // packages/archymedes-cli/src/ui/navigation.ts
21298
21429
  class CommandUsage {
21299
21430
  limit;
21300
21431
  order = [];
@@ -21317,7 +21448,7 @@ class CommandUsage {
21317
21448
  }
21318
21449
  }
21319
21450
 
21320
- // ../core/src/cli/daemon.ts
21451
+ // packages/core/src/cli/daemon.ts
21321
21452
  import { randomUUID as randomUUID6 } from "node:crypto";
21322
21453
  var ARCHYMEDES_DAEMON_PROTOCOL_VERSION = 1;
21323
21454
  var PREVIEW_HUNK_SEPARATOR = `
@@ -21715,7 +21846,7 @@ class ArchymedesDaemonClient {
21715
21846
  }
21716
21847
  }
21717
21848
 
21718
- // ../core/src/money.ts
21849
+ // packages/core/src/money.ts
21719
21850
  var CURRENCIES2 = (() => {
21720
21851
  try {
21721
21852
  return Intl.supportedValuesOf("currency");
@@ -21758,7 +21889,7 @@ function formatMoney2(value) {
21758
21889
  return value.currency === "USD" ? `${format.symbol}${rendered}` : `${format.symbol} ${rendered}`;
21759
21890
  }
21760
21891
 
21761
- // ../core/src/cli/backends.ts
21892
+ // packages/core/src/cli/backends.ts
21762
21893
  import path24 from "node:path";
21763
21894
  var CONFIG_FILE_SCAN_LIMIT2 = 500;
21764
21895
  function localCommandGuidance2(platform) {
@@ -21852,7 +21983,7 @@ class LocalWorkspace2 {
21852
21983
  }
21853
21984
  }
21854
21985
 
21855
- // ../core/src/cli/cost.ts
21986
+ // packages/core/src/cli/cost.ts
21856
21987
  function formatTokenFlow2(usage) {
21857
21988
  return `↑${compactTokenCount(usage.inputTokens)} ↓${compactTokenCount(usage.outputTokens)} tok`;
21858
21989
  }
@@ -22104,7 +22235,7 @@ class CostLedger2 {
22104
22235
  }
22105
22236
  }
22106
22237
 
22107
- // src/headless.ts
22238
+ // packages/archymedes-cli/src/headless.ts
22108
22239
  var HEADLESS_PROTOCOL_VERSION = 1;
22109
22240
  var EXIT_CODES = {
22110
22241
  completed: 0,
@@ -22220,6 +22351,14 @@ class HeadlessEmitter {
22220
22351
  });
22221
22352
  return;
22222
22353
  }
22354
+ if (safe.type === "context_shrunk") {
22355
+ this.emit("context_shrunk", { iteration: safe.iteration, step: safe.step });
22356
+ return;
22357
+ }
22358
+ if (safe.type === "tool_name") {
22359
+ this.emit("tool_name", { iteration: safe.iteration, requested: safe.requested, ...safe.resolved ? { resolved: safe.resolved } : {} });
22360
+ return;
22361
+ }
22223
22362
  this.emit("runtime_stop", { status: safe.status, summary: safe.summary });
22224
22363
  }
22225
22364
  turnEnd(result) {
@@ -22230,7 +22369,7 @@ class HeadlessEmitter {
22230
22369
  }
22231
22370
  }
22232
22371
 
22233
- // ../core/src/providers/price-catalog.ts
22372
+ // packages/core/src/providers/price-catalog.ts
22234
22373
  var ANTHROPIC_VERIFIED2 = "2026-06-24";
22235
22374
  var ANTHROPIC_SOURCE2 = "anthropic.com/pricing, recorded 2026-06-24";
22236
22375
  var ANTHROPIC2 = [
@@ -22282,7 +22421,7 @@ var SERVICES2 = [
22282
22421
  ];
22283
22422
  var PRICE_CATALOG2 = definePrices([...ANTHROPIC2, ...OAI_COMPAT_LABS2, ...SERVICES2]);
22284
22423
 
22285
- // src/text/color-depth.ts
22424
+ // packages/archymedes-cli/src/text/color-depth.ts
22286
22425
  function detectColorDepth(environment, isTTY) {
22287
22426
  if (!isTTY || environment.NO_COLOR !== undefined || environment.TERM === "dumb")
22288
22427
  return "none";
@@ -22291,7 +22430,7 @@ function detectColorDepth(environment, isTTY) {
22291
22430
  return "ansi256";
22292
22431
  }
22293
22432
 
22294
- // src/terminal/keybindings.ts
22433
+ // packages/archymedes-cli/src/terminal/keybindings.ts
22295
22434
  var FUNCTION_KEY2 = /^f([1-9]|1[0-2])$/;
22296
22435
  var NAMED_KEYS2 = new Set(["tab", "enter", "escape", "space", "up", "down", "left", "right", "home", "end", "pageup", "pagedown", "backspace", "delete"]);
22297
22436
  function isKeyName2(value) {
@@ -22533,7 +22672,7 @@ function escapeCodeTimeoutMs2(environment = process.env) {
22533
22672
  return Number.isInteger(parsed) && parsed >= 10 && parsed <= 2000 ? parsed : DEFAULT_ESCAPE_CODE_TIMEOUT_MS2;
22534
22673
  }
22535
22674
 
22536
- // src/platform/local-currency.ts
22675
+ // packages/archymedes-cli/src/platform/local-currency.ts
22537
22676
  var COUNTRY_CURRENCIES2 = {
22538
22677
  RW: "RWF",
22539
22678
  EG: "EGP",
@@ -22659,7 +22798,7 @@ function resolveCurrencyPreference(options) {
22659
22798
  }
22660
22799
  var FX_CACHE_MAX_AGE_MS2 = 24 * 60 * 60 * 1000;
22661
22800
 
22662
- // src/platform/settings.ts
22801
+ // packages/archymedes-cli/src/platform/settings.ts
22663
22802
  import { promises as fs18 } from "node:fs";
22664
22803
  import os5 from "node:os";
22665
22804
  import path25 from "node:path";
@@ -22912,7 +23051,7 @@ function mergedEnvironment2(settings, environment = process.env) {
22912
23051
  var PROVIDER_REQUIRED_NAMES2 = new Set(PROVIDER_IDS.flatMap((id) => PROVIDER_INFO[id].requires));
22913
23052
  var PROVIDER_KEY_FIELDS2 = SETTING_FIELDS2.filter((field) => PROVIDER_REQUIRED_NAMES2.has(field.key));
22914
23053
 
22915
- // src/app/free-setup.ts
23054
+ // packages/archymedes-cli/src/app/free-setup.ts
22916
23055
  var OPENROUTER_KEYS_URL3 = "https://openrouter.ai/keys";
22917
23056
  var FREE_SETUP_INTRO = [
22918
23057
  "Free mode runs zero-priced models through OpenRouter and never falls back to a paid one.",
@@ -22978,7 +23117,7 @@ ${style3.bold("Free mode setup")}
22978
23117
  return;
22979
23118
  }
22980
23119
 
22981
- // src/session/tabs.ts
23120
+ // packages/archymedes-cli/src/session/tabs.ts
22982
23121
  class WorkspaceController {
22983
23122
  limit;
22984
23123
  tabs = [];
@@ -23055,19 +23194,19 @@ class WorkspaceController {
23055
23194
  if (tab)
23056
23195
  tab.status = "running";
23057
23196
  }
23058
- views(describe) {
23197
+ views(describe2) {
23059
23198
  return this.tabs.map((tab) => ({
23060
23199
  id: tab.id,
23061
23200
  title: tab.title,
23062
23201
  status: tab.status,
23063
23202
  unread: tab.unread,
23064
23203
  active: tab.id === this.activeId,
23065
- ...describe ? describe(tab.payload) : {}
23204
+ ...describe2 ? describe2(tab.payload) : {}
23066
23205
  }));
23067
23206
  }
23068
23207
  }
23069
23208
 
23070
- // src/terminal/output.ts
23209
+ // packages/archymedes-cli/src/terminal/output.ts
23071
23210
  var terminalStream2 = {
23072
23211
  write(text) {
23073
23212
  process.stdout.write(text);
@@ -23163,7 +23302,7 @@ class TabSink {
23163
23302
  }
23164
23303
  }
23165
23304
 
23166
- // src/terminal/job-stream.ts
23305
+ // packages/archymedes-cli/src/terminal/job-stream.ts
23167
23306
  var TERMINAL_STATUSES = new Set(["completed", "failed", "cancelled"]);
23168
23307
  class WatchRegistry {
23169
23308
  watched = new Map;
@@ -23198,7 +23337,7 @@ class WatchRegistry {
23198
23337
  }
23199
23338
  }
23200
23339
 
23201
- // src/theme/theme.ts
23340
+ // packages/archymedes-cli/src/theme/theme.ts
23202
23341
  var BLUEPRINT2 = `
23203
23342
  /* Blueprint navy, chalk-white ink and an amber pencil — the original drafting table. */
23204
23343
  @theme blueprint {
@@ -23499,7 +23638,7 @@ function detectPreferredTheme(environment) {
23499
23638
  return DEFAULT_THEME_NAME2;
23500
23639
  }
23501
23640
 
23502
- // src/theme/theme-files.ts
23641
+ // packages/archymedes-cli/src/theme/theme-files.ts
23503
23642
  import { promises as fs19 } from "node:fs";
23504
23643
  import path26 from "node:path";
23505
23644
  function themeDirectory(scope, root, environment) {
@@ -23537,7 +23676,7 @@ async function findTheme(name, root, environment) {
23537
23676
  return (await discoverThemes(root, environment)).find((theme) => theme.name.toLowerCase() === wanted);
23538
23677
  }
23539
23678
 
23540
- // src/render/syntax.ts
23679
+ // packages/archymedes-cli/src/render/syntax.ts
23541
23680
  var DEFAULT_CODE_STYLE2 = { colors: "vscode", lineNumbers: true };
23542
23681
  var currentCodeStyle2 = { ...DEFAULT_CODE_STYLE2 };
23543
23682
  function codeStyleFromEnvironment(environment) {
@@ -23595,7 +23734,7 @@ var GRAMMARS2 = {
23595
23734
  };
23596
23735
  var PUNCTUATION2 = new Set([..."{}[]()<>;,.:=+-*/%!&|^~?\\"]);
23597
23736
 
23598
- // src/platform/i18n.ts
23737
+ // packages/archymedes-cli/src/platform/i18n.ts
23599
23738
  var CONTROL_LANGUAGES2 = {
23600
23739
  en: "English",
23601
23740
  zh: "中文 (Mandarin)",
@@ -23620,7 +23759,7 @@ function resolveControlLanguage2(value) {
23620
23759
  return base in CONTROL_LANGUAGES2 ? base : "en";
23621
23760
  }
23622
23761
 
23623
- // src/text/glyphs.ts
23762
+ // packages/archymedes-cli/src/text/glyphs.ts
23624
23763
  var UNICODE_GLYPHS2 = {
23625
23764
  starGlyphs: [".", "·", "✧", "✦", "✶"],
23626
23765
  spinnerFrames: [" ◜ ", " ◠ ", " ◝ ", " ◞ ", " ◡ ", " ◟ "],
@@ -23736,7 +23875,7 @@ function glyphsFor(mode) {
23736
23875
  function resolveGlyphs(environment, platform = process.platform) {
23737
23876
  return glyphsFor(detectGlyphMode(environment, platform));
23738
23877
  }
23739
- // src/session/state-history.ts
23878
+ // packages/archymedes-cli/src/session/state-history.ts
23740
23879
  class CliStateHistory {
23741
23880
  root;
23742
23881
  environment;
@@ -23847,7 +23986,7 @@ class CliStateHistory {
23847
23986
  }
23848
23987
  }
23849
23988
 
23850
- // src/ui/borrowed-keyboard.ts
23989
+ // packages/archymedes-cli/src/ui/borrowed-keyboard.ts
23851
23990
  function painter(output) {
23852
23991
  let rows = 0;
23853
23992
  const erase = () => {
@@ -23928,7 +24067,7 @@ async function openChooser(host, items, options, self) {
23928
24067
  return withBorrowedKeyboard(host, self, (keys, paint2) => runChooser(keys, items, paint2, sized));
23929
24068
  }
23930
24069
 
23931
- // src/app/prompts.ts
24070
+ // packages/archymedes-cli/src/app/prompts.ts
23932
24071
  function renderApprovalPreview(preview2) {
23933
24072
  if (!preview2)
23934
24073
  return;
@@ -24066,7 +24205,7 @@ async function hiddenQuestion(readline, question, signal) {
24066
24205
  }
24067
24206
  }
24068
24207
 
24069
- // src/app/providers.ts
24208
+ // packages/archymedes-cli/src/app/providers.ts
24070
24209
  function readFxRates(environment) {
24071
24210
  const genericRate = Number(environment.ARCHYMEDES_FX_RATE);
24072
24211
  const genericFrom = environment.ARCHYMEDES_FX_FROM?.trim().toUpperCase();
@@ -24083,11 +24222,11 @@ function readFxRates(environment) {
24083
24222
  }
24084
24223
  return configured;
24085
24224
  }
24086
- // ../core/src/cli/job-store.ts
24225
+ // packages/core/src/cli/job-store.ts
24087
24226
  import { promises as fs20 } from "node:fs";
24088
24227
  import path27 from "node:path";
24089
24228
 
24090
- // ../core/src/cli/jobs.ts
24229
+ // packages/core/src/cli/jobs.ts
24091
24230
  var JOB_STATUSES = ["queued", "running", "paused", "completed", "failed", "cancelled"];
24092
24231
  var DECISIONS = ["allow", "allow_always", "allow_pattern", "deny", "deny_always"];
24093
24232
  function parseJobRecord(value, index) {
@@ -24262,7 +24401,7 @@ function recoverStale(store, now) {
24262
24401
  return { store: { jobs }, recovered };
24263
24402
  }
24264
24403
 
24265
- // ../core/src/cli/job-store.ts
24404
+ // packages/core/src/cli/job-store.ts
24266
24405
  function jobStoreFile(root) {
24267
24406
  return path27.join(root, ".archymedes", "jobs.json");
24268
24407
  }
@@ -24382,10 +24521,10 @@ async function appendJobLog(root, id, line) {
24382
24521
  await fs20.appendFile(file, `${line}
24383
24522
  `, "utf8");
24384
24523
  }
24385
- // src/job-worker.ts
24524
+ // packages/archymedes-cli/src/job-worker.ts
24386
24525
  import os6 from "node:os";
24387
24526
 
24388
- // src/commands/wander.ts
24527
+ // packages/archymedes-cli/src/commands/wander.ts
24389
24528
  async function gatherWanderEvidence(topic, search, numResults = 8) {
24390
24529
  if (!search) {
24391
24530
  return {
@@ -24481,7 +24620,7 @@ function renderWanderChart(results, style3, width) {
24481
24620
  `);
24482
24621
  }
24483
24622
 
24484
- // src/job-worker.ts
24623
+ // packages/archymedes-cli/src/job-worker.ts
24485
24624
  function workerId(hostname = os6.hostname(), pid = process.pid) {
24486
24625
  return `${hostname}:${pid}`;
24487
24626
  }
@@ -24659,7 +24798,7 @@ async function runJobWorkerForever(deps) {
24659
24798
  }
24660
24799
  }
24661
24800
 
24662
- // src/app/providers.ts
24801
+ // packages/archymedes-cli/src/app/providers.ts
24663
24802
  function renderProviders(environment, depth) {
24664
24803
  const paint2 = (text, apply) => depth === "none" ? text : apply(text);
24665
24804
  const statuses = describeProviders(environment);
@@ -24730,7 +24869,7 @@ function modelPriceCatalogFor(prices, exact) {
24730
24869
  return { ...rates, ...prices.largeContext ? { largeContext: prices.largeContext } : {} };
24731
24870
  }
24732
24871
 
24733
- // src/app/job-launch.ts
24872
+ // packages/archymedes-cli/src/app/job-launch.ts
24734
24873
  async function runJobWorkerProcess(root, jobId) {
24735
24874
  const savedSettings = await loadSettings(process.env);
24736
24875
  const environment = mergedEnvironment(savedSettings, process.env);
@@ -24767,10 +24906,10 @@ async function runJobWorkerProcess(root, jobId) {
24767
24906
  }
24768
24907
  }
24769
24908
 
24770
- // src/app/startup-commands.ts
24909
+ // packages/archymedes-cli/src/app/startup-commands.ts
24771
24910
  import { createInterface as createInterface4 } from "node:readline/promises";
24772
24911
 
24773
- // src/headless.ts
24912
+ // packages/archymedes-cli/src/headless.ts
24774
24913
  var EXIT_CODES2 = {
24775
24914
  completed: 0,
24776
24915
  failed: 1,
@@ -24794,7 +24933,7 @@ function exitCodeForStatus2(status) {
24794
24933
  return STATUS_EXIT2[status];
24795
24934
  }
24796
24935
 
24797
- // src/platform/doctor.ts
24936
+ // packages/archymedes-cli/src/platform/doctor.ts
24798
24937
  var DEFAULT_PROBE_TIMEOUT_MS = 5000;
24799
24938
  function modelEndpoints(environment) {
24800
24939
  return providerEndpoints(environment).map((provider) => {
@@ -24924,7 +25063,7 @@ function doctorReport(probes, context) {
24924
25063
  };
24925
25064
  }
24926
25065
 
24927
- // src/text/color-depth.ts
25066
+ // packages/archymedes-cli/src/text/color-depth.ts
24928
25067
  function detectColorDepth2(environment, isTTY) {
24929
25068
  if (!isTTY || environment.NO_COLOR !== undefined || environment.TERM === "dumb")
24930
25069
  return "none";
@@ -24933,7 +25072,7 @@ function detectColorDepth2(environment, isTTY) {
24933
25072
  return "ansi256";
24934
25073
  }
24935
25074
 
24936
- // src/session/delete-session.ts
25075
+ // packages/archymedes-cli/src/session/delete-session.ts
24937
25076
  import { promises as fs21 } from "node:fs";
24938
25077
  import path28 from "node:path";
24939
25078
  var SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
@@ -24953,7 +25092,7 @@ async function clearProjection(root, id) {
24953
25092
  if (!exists)
24954
25093
  return;
24955
25094
  try {
24956
- const { SessionProjection } = await import("./projection-ndr3t77h.mjs");
25095
+ const { SessionProjection } = await import("./projection-4jjdaf41.mjs");
24957
25096
  const projection = await SessionProjection.open(root);
24958
25097
  try {
24959
25098
  await projection.rebuild(id);
@@ -24979,7 +25118,7 @@ async function deleteSession(root, id, options = {}) {
24979
25118
  return { deleted: true };
24980
25119
  }
24981
25120
 
24982
- // src/ui/navigation.ts
25121
+ // packages/archymedes-cli/src/ui/navigation.ts
24983
25122
  var ESSENTIAL_COMMANDS = ["/help", "/history", "/model", "/mode", "/diff", "/undo", "/settings", "/exit"];
24984
25123
  function isEssential(command) {
24985
25124
  return ESSENTIAL_COMMANDS.includes(command);
@@ -25046,7 +25185,7 @@ function renderAsks(suggestions, style3) {
25046
25185
  `);
25047
25186
  }
25048
25187
 
25049
- // src/app/help.ts
25188
+ // packages/archymedes-cli/src/app/help.ts
25050
25189
  function helpText(language = "en", shortcuts = new Map) {
25051
25190
  const star = glyphs.star;
25052
25191
  const mark = (command) => isEssential(command) ? `${star} ` : " ";
@@ -25151,7 +25290,7 @@ ${renderCommandHelp(language, shortcuts, { mark })}
25151
25290
  `;
25152
25291
  }
25153
25292
 
25154
- // src/app/prompts.ts
25293
+ // packages/archymedes-cli/src/app/prompts.ts
25155
25294
  function settingsChooser(readline) {
25156
25295
  return (request) => openChooser({ readline, input: process.stdin, output: process.stdout }, request.items.map((item) => ({ ...item })), {
25157
25296
  title: request.title,
@@ -25224,7 +25363,7 @@ async function hiddenQuestion2(readline, question, signal) {
25224
25363
  }
25225
25364
  }
25226
25365
 
25227
- // src/app/startup-commands.ts
25366
+ // packages/archymedes-cli/src/app/startup-commands.ts
25228
25367
  function runInformationFlag(context) {
25229
25368
  const { args, environment, language, earlyDepth } = context;
25230
25369
  if (args.help) {
@@ -25428,7 +25567,7 @@ ${status.reason ?? "native state engine unavailable"}
25428
25567
  return 0;
25429
25568
  }
25430
25569
 
25431
- // src/app/display-currency.ts
25570
+ // packages/archymedes-cli/src/app/display-currency.ts
25432
25571
  async function settleDisplayCurrency(options) {
25433
25572
  const { args, environment, prices, rates, state } = options;
25434
25573
  if (prices && state.display !== prices.currency) {
@@ -25485,7 +25624,7 @@ async function settleDisplayCurrency(options) {
25485
25624
  return;
25486
25625
  }
25487
25626
 
25488
- // src/app/workspaces.ts
25627
+ // packages/archymedes-cli/src/app/workspaces.ts
25489
25628
  function createWorkspaceFactory(args, environment) {
25490
25629
  return async (request) => {
25491
25630
  const announce = (text) => {
@@ -25495,8 +25634,8 @@ function createWorkspaceFactory(args, environment) {
25495
25634
  };
25496
25635
  const minutes = Math.max(1, Math.min(args.sandboxMinutes, 60));
25497
25636
  if (request.backend === "e2b") {
25498
- const { findWorkspacePreset } = await import("./sandbox-templates-9jcjws23.mjs");
25499
- const { createE2BProvider } = await import("./factory-xpqqcyqq.mjs");
25637
+ const { findWorkspacePreset } = await import("./sandbox-templates-8sd1psez.mjs");
25638
+ const { createE2BProvider } = await import("./factory-3jav5ecj.mjs");
25500
25639
  const preset = findWorkspacePreset(request.preset ?? args.preset);
25501
25640
  const sandbox = createE2BProvider(environment, preset.templateAlias);
25502
25641
  if (!sandbox)
@@ -25522,7 +25661,7 @@ function createWorkspaceFactory(args, environment) {
25522
25661
  return { workspace: created };
25523
25662
  }
25524
25663
  if (request.backend === "docker") {
25525
- const { createDockerProvider } = await import("./factory-xpqqcyqq.mjs");
25664
+ const { createDockerProvider } = await import("./factory-3jav5ecj.mjs");
25526
25665
  const image = request.dockerImage || args.dockerImage || environment.DOCKER_CODING_IMAGE;
25527
25666
  const sandbox = createDockerProvider({ ...environment, DOCKER_CODING_IMAGE: image });
25528
25667
  if (!sandbox)
@@ -25551,11 +25690,11 @@ function createWorkspaceFactory(args, environment) {
25551
25690
  };
25552
25691
  }
25553
25692
 
25554
- // ../core/src/cli/balance.ts
25693
+ // packages/core/src/cli/balance.ts
25555
25694
  var CRITICAL_BALANCE_USD2 = 0.5;
25556
25695
  var LOW_BALANCE_USD2 = 2;
25557
25696
 
25558
- // src/commands/balance.ts
25697
+ // packages/archymedes-cli/src/commands/balance.ts
25559
25698
  function formatBalance(amount, currency) {
25560
25699
  return formatMoney(fromUnits(amount, currency));
25561
25700
  }
@@ -25658,7 +25797,7 @@ class BalanceWatch {
25658
25797
  }
25659
25798
  }
25660
25799
 
25661
- // src/session/resumed-spend.ts
25800
+ // packages/archymedes-cli/src/session/resumed-spend.ts
25662
25801
  async function readSessionModelTurns(root, sessionId) {
25663
25802
  const events = await readEventJournal(root, sessionId);
25664
25803
  const turns = [];
@@ -25690,7 +25829,7 @@ function priceSessionModelTurns(turns, options) {
25690
25829
  return { spent: total, unpriced: [...unpriced].sort() };
25691
25830
  }
25692
25831
 
25693
- // src/app/balance-tracking.ts
25832
+ // packages/archymedes-cli/src/app/balance-tracking.ts
25694
25833
  function createBalanceTracking(options) {
25695
25834
  const { environment, processEnvironment, rates, state } = options;
25696
25835
  const usdInDisplay = (usd) => {
@@ -25779,7 +25918,7 @@ function createBalanceTracking(options) {
25779
25918
  return { lowBalance, criticalBalance, balanceWatch, parseManualBalance, currentBalance, persistManualBalance, sessionSpend, balanceHeader, checkBalance, carryResumedSpend };
25780
25919
  }
25781
25920
 
25782
- // src/app/agent-factory.ts
25921
+ // packages/archymedes-cli/src/app/agent-factory.ts
25783
25922
  function createClientFactory(options) {
25784
25923
  const { args, environment, daemon, approvalPrompt, rates, approvedBudget, state } = options;
25785
25924
  return async (record2, runtime = {}) => {
@@ -25820,14 +25959,14 @@ function closeWithClient(client, hook) {
25820
25959
  client.dispose = () => dispose().finally(close);
25821
25960
  }
25822
25961
 
25823
- // src/app/live-models.ts
25962
+ // packages/archymedes-cli/src/app/live-models.ts
25824
25963
  async function readCachedLiveModels(environment, state) {
25825
25964
  const cached = await readModelCache(environment);
25826
25965
  if (isCacheFresh(cached))
25827
25966
  state.liveModels = cached.models;
25828
25967
  }
25829
25968
 
25830
- // src/app/session-hints.ts
25969
+ // packages/archymedes-cli/src/app/session-hints.ts
25831
25970
  function createSessionHints(options) {
25832
25971
  const { state, watched, tabs, usage } = options;
25833
25972
  const navContext = () => ({
@@ -25856,7 +25995,7 @@ function createSessionHints(options) {
25856
25995
  return { navContext, writeHint };
25857
25996
  }
25858
25997
 
25859
- // src/render/completion-card.ts
25998
+ // packages/archymedes-cli/src/render/completion-card.ts
25860
25999
  var CHECK_LABELS = {
25861
26000
  tests: "tests",
25862
26001
  typecheck: "typecheck",
@@ -25886,7 +26025,7 @@ function renderCompletionCard(input, style3) {
25886
26025
  return panel(lines, style3, { title, tone: failed2 ? "bad" : verified ? "good" : "warn" });
25887
26026
  }
25888
26027
 
25889
- // src/render/routing-receipt.ts
26028
+ // packages/archymedes-cli/src/render/routing-receipt.ts
25890
26029
  function formatMicros(micros, currency = "USD") {
25891
26030
  if (micros === undefined || !Number.isFinite(micros))
25892
26031
  return "—";
@@ -25978,10 +26117,10 @@ ${rule(cell, { label: badge })}` : out3.join(`
25978
26117
  `);
25979
26118
  }
25980
26119
 
25981
- // src/app/session-hints.ts
26120
+ // packages/archymedes-cli/src/app/session-hints.ts
25982
26121
  var failureStatus = (status) => status === "needs_approval" ? "waiting_approval" : status;
25983
26122
 
25984
- // src/app/turn-failure.ts
26123
+ // packages/archymedes-cli/src/app/turn-failure.ts
25985
26124
  async function handleTurnFailure(error, request, context) {
25986
26125
  const { args, environment, interactive, headless, recoveryState, state, navContext } = context;
25987
26126
  if (recoveryState.last?.request === request) {
@@ -26036,7 +26175,7 @@ ${style.yellow(`Stopped at the ${formatMoney(fromUnits(args.budget, state.displa
26036
26175
  return false;
26037
26176
  }
26038
26177
 
26039
- // src/app/turn-preflight.ts
26178
+ // packages/archymedes-cli/src/app/turn-preflight.ts
26040
26179
  async function runTurnPreflight(request, context) {
26041
26180
  const { args, readline, interactive, approvedBudget, rates, state } = context;
26042
26181
  const { currentBalance, balanceWatch, sessionSpend } = context.balance;
@@ -26134,7 +26273,7 @@ async function runTurnPreflight(request, context) {
26134
26273
  return true;
26135
26274
  }
26136
26275
 
26137
- // src/app/turn-runner.ts
26276
+ // packages/archymedes-cli/src/app/turn-runner.ts
26138
26277
  var addModelUsage2 = (left, right) => ({
26139
26278
  inputTokens: left.inputTokens + right.inputTokens,
26140
26279
  outputTokens: left.outputTokens + right.outputTokens,
@@ -26342,7 +26481,7 @@ ${result.status === "completed" ? asMarkdown(result.summary) : style.yellow(resu
26342
26481
  };
26343
26482
  }
26344
26483
 
26345
- // src/app/interrupts.ts
26484
+ // packages/archymedes-cli/src/app/interrupts.ts
26346
26485
  function createSigintHandling(options) {
26347
26486
  const { readline, state } = options;
26348
26487
  const handleSigint = () => {
@@ -26383,7 +26522,7 @@ function createSigintHandling(options) {
26383
26522
  return { bindSigint, unbindSigint };
26384
26523
  }
26385
26524
 
26386
- // src/app/session-start.ts
26525
+ // packages/archymedes-cli/src/app/session-start.ts
26387
26526
  import path29 from "node:path";
26388
26527
  async function resumeAtStartup(context) {
26389
26528
  const { args, interactive, stateHistory, state, openClient } = context;
@@ -26456,7 +26595,7 @@ async function runOneShot(context) {
26456
26595
  return args.json ? exitCodeForStatus2(state.lastTurnStatus) : ran ? 0 : 1;
26457
26596
  }
26458
26597
 
26459
- // src/archymedes.ts
26598
+ // packages/archymedes-cli/src/archymedes.ts
26460
26599
  async function main() {
26461
26600
  process.stdout.on("error", (error) => {
26462
26601
  if (error.code === "EPIPE")