toolroll 0.9.67 → 0.9.68

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.
Files changed (236) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/acp-client.js +1 -3
  3. package/dist/agent-board.d.ts +0 -1
  4. package/dist/agent-board.js +0 -1
  5. package/dist/agent-fence.js +3 -0
  6. package/dist/browser/workspace.css +1 -1
  7. package/dist/browser/workspace.js +31 -29
  8. package/dist/builder.js +3 -26
  9. package/dist/canonical-json.d.ts +14 -0
  10. package/dist/canonical-json.js +36 -0
  11. package/dist/chat-actions.js +1 -2
  12. package/dist/chat-admission.d.ts +19 -0
  13. package/dist/chat-admission.js +22 -0
  14. package/dist/chat-channel.js +1 -1
  15. package/dist/chat-delivery.js +0 -1
  16. package/dist/chat-follow.d.ts +17 -0
  17. package/dist/chat-follow.js +32 -0
  18. package/dist/chat-messages.js +0 -1
  19. package/dist/chat-settings-page.d.ts +23 -0
  20. package/dist/chat-settings-page.js +41 -0
  21. package/dist/claim.js +3 -6
  22. package/dist/claude-print.d.ts +12 -0
  23. package/dist/claude-print.js +34 -0
  24. package/dist/cli-http.d.ts +0 -7
  25. package/dist/cli-http.js +0 -21
  26. package/dist/cli.d.ts +3 -10
  27. package/dist/cli.js +15 -24
  28. package/dist/coding-provider.js +2 -1
  29. package/dist/coding-workspace.js +1 -1
  30. package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
  31. package/dist/connect-cli.js +331 -0
  32. package/dist/containment.d.ts +0 -2
  33. package/dist/containment.js +2 -6
  34. package/dist/contracts/chat-actions.d.ts +0 -1
  35. package/dist/contracts/chat-content.d.ts +0 -4
  36. package/dist/contracts/chat-content.js +0 -2
  37. package/dist/contracts/chat-tables.d.ts +0 -1
  38. package/dist/contracts/cli.d.ts +0 -62
  39. package/dist/contracts/cli.js +0 -4
  40. package/dist/contracts/coding-workspace.js +1 -1
  41. package/dist/contracts/contract.js +1 -1
  42. package/dist/contracts/flow-card.d.ts +0 -1
  43. package/dist/contracts/flow-propose.d.ts +0 -1
  44. package/dist/contracts/flow-send.js +1 -1
  45. package/dist/contracts/gateway-tools.d.ts +0 -1
  46. package/dist/contracts/integration-metadata.js +1 -1
  47. package/dist/contracts/lead-tools.d.ts +0 -1
  48. package/dist/contracts/memory-pass.d.ts +0 -1
  49. package/dist/contracts/memory-pass.js +1 -1
  50. package/dist/contracts/plan.js +1 -1
  51. package/dist/contracts/project-knowledge.js +1 -1
  52. package/dist/contracts/project-skills.d.ts +0 -1
  53. package/dist/contracts/proof.js +1 -1
  54. package/dist/contracts/recipes.js +1 -1
  55. package/dist/contracts/scope.js +1 -1
  56. package/dist/contracts/scout-report.js +1 -1
  57. package/dist/contracts/teams-callback.d.ts +0 -1
  58. package/dist/converse.d.ts +0 -6
  59. package/dist/converse.js +0 -19
  60. package/dist/daemon.js +3 -2
  61. package/dist/decision.d.ts +1 -3
  62. package/dist/deprecations.d.ts +12 -4
  63. package/dist/deprecations.js +27 -4
  64. package/dist/desktop-update-recovery.js +1 -1
  65. package/dist/desktop-update.js +3 -2
  66. package/dist/discord-chat.js +4 -15
  67. package/dist/discord-settings.d.ts +2 -6
  68. package/dist/discord-settings.js +10 -38
  69. package/dist/discord.js +12 -23
  70. package/dist/evidence.d.ts +0 -1
  71. package/dist/evidence.js +0 -3
  72. package/dist/exec.d.ts +0 -9
  73. package/dist/exec.js +3 -81
  74. package/dist/flow-actions.js +0 -3
  75. package/dist/flow-draft.d.ts +1 -3
  76. package/dist/flow-draft.js +15 -28
  77. package/dist/flow-scripts.d.ts +1 -8
  78. package/dist/flow-scripts.js +0 -13
  79. package/dist/flow-send.js +1 -1
  80. package/dist/flow-share.d.ts +0 -2
  81. package/dist/flow-share.js +1 -6
  82. package/dist/flow-steps.js +1 -1
  83. package/dist/flow-triggers.d.ts +0 -1
  84. package/dist/flow-triggers.js +1 -2
  85. package/dist/flow-unattended.js +1 -12
  86. package/dist/flows.js +1 -1
  87. package/dist/health-cli.d.ts +2 -2
  88. package/dist/health-cli.js +1 -1
  89. package/dist/invoke.d.ts +0 -3
  90. package/dist/invoke.js +5 -3
  91. package/dist/is-record.d.ts +2 -0
  92. package/dist/is-record.js +2 -0
  93. package/dist/lead-doors.d.ts +1 -5
  94. package/dist/lead-doors.js +0 -4
  95. package/dist/lead-tools.js +3 -6
  96. package/dist/live-detail.d.ts +0 -1
  97. package/dist/live-detail.js +0 -6
  98. package/dist/live-terminal.js +2 -1
  99. package/dist/live.d.ts +0 -1
  100. package/dist/live.js +1 -2
  101. package/dist/mcp-core.js +0 -2
  102. package/dist/memory-pass.js +1 -1
  103. package/dist/model-catalog.js +1 -1
  104. package/dist/modes.js +1 -12
  105. package/dist/operate.js +383 -750
  106. package/dist/password-bearer.d.ts +0 -2
  107. package/dist/password-bearer.js +0 -4
  108. package/dist/peek-cli.js +2 -1
  109. package/dist/peek.d.ts +2 -26
  110. package/dist/peek.js +2 -168
  111. package/dist/phase-routing.d.ts +0 -4
  112. package/dist/phase-routing.js +2 -21
  113. package/dist/planner-source.d.ts +2 -1
  114. package/dist/planner-source.js +2 -12
  115. package/dist/planner.js +2 -14
  116. package/dist/process-tree.d.ts +0 -2
  117. package/dist/process-tree.js +0 -10
  118. package/dist/project-delete.d.ts +0 -2
  119. package/dist/project-delete.js +1 -3
  120. package/dist/project-learning.d.ts +0 -14
  121. package/dist/project-skills.d.ts +0 -1
  122. package/dist/project-skills.js +0 -14
  123. package/dist/project-tools.js +2 -10
  124. package/dist/provider.d.ts +0 -17
  125. package/dist/provider.js +0 -26
  126. package/dist/pulls.d.ts +0 -2
  127. package/dist/pulls.js +0 -9
  128. package/dist/release-adapters.d.ts +3 -0
  129. package/dist/release-adapters.js +15 -5
  130. package/dist/remote-exec.d.ts +3 -2
  131. package/dist/remote-exec.js +3 -2
  132. package/dist/repos.d.ts +0 -5
  133. package/dist/repos.js +2 -10
  134. package/dist/repository-context.d.ts +0 -2
  135. package/dist/repository-context.js +0 -4
  136. package/dist/restart-certification.d.ts +0 -2
  137. package/dist/restart-certification.js +1 -5
  138. package/dist/result-follow-ups.d.ts +1 -4
  139. package/dist/result-follow-ups.js +1 -6
  140. package/dist/result-review.d.ts +0 -2
  141. package/dist/result-review.js +0 -2
  142. package/dist/retention.d.ts +0 -1
  143. package/dist/retention.js +0 -1
  144. package/dist/review-context.d.ts +0 -1
  145. package/dist/review-context.js +1 -12
  146. package/dist/reviewer.d.ts +0 -16
  147. package/dist/reviewer.js +0 -18
  148. package/dist/run-closeout.js +2 -1
  149. package/dist/scope.js +1 -13
  150. package/dist/scout-browser.js +2 -1
  151. package/dist/serve.js +2 -2
  152. package/dist/server/console.css +5 -133
  153. package/dist/server/flows.js +2 -2
  154. package/dist/server/http.d.ts +2 -0
  155. package/dist/server/http.js +5 -0
  156. package/dist/server/pages.js +2 -2
  157. package/dist/server/people-tokens.js +3 -4
  158. package/dist/server/remote.js +1 -6
  159. package/dist/server/render-chat.d.ts +9 -2
  160. package/dist/server/render-chat.js +53 -7
  161. package/dist/server/render-results.d.ts +0 -6
  162. package/dist/server/render-results.js +3 -9
  163. package/dist/server/render-tasks.js +4 -5
  164. package/dist/server/route-table.d.ts +0 -4
  165. package/dist/server/route-table.js +0 -6
  166. package/dist/server/settings.js +23 -23
  167. package/dist/server/task-views.js +1 -1
  168. package/dist/server/tasks.js +3 -3
  169. package/dist/setup-guide.d.ts +2 -2
  170. package/dist/skills.d.ts +0 -6
  171. package/dist/skills.js +0 -8
  172. package/dist/slack-chat.d.ts +1 -7
  173. package/dist/slack-chat.js +5 -18
  174. package/dist/slack-settings.d.ts +2 -6
  175. package/dist/slack-settings.js +10 -38
  176. package/dist/slack.js +12 -23
  177. package/dist/sleep.d.ts +2 -0
  178. package/dist/sleep.js +2 -0
  179. package/dist/store.d.ts +0 -73
  180. package/dist/store.js +3 -177
  181. package/dist/structured-output.d.ts +0 -1
  182. package/dist/structured-output.js +0 -1
  183. package/dist/subagent-work.d.ts +0 -2
  184. package/dist/subagent-work.js +0 -2
  185. package/dist/subagents.d.ts +1 -3
  186. package/dist/subagents.js +20 -33
  187. package/dist/subscription-chat.d.ts +1 -3
  188. package/dist/subscription-chat.js +2 -3
  189. package/dist/task-sizing.d.ts +1 -4
  190. package/dist/task-sizing.js +3 -10
  191. package/dist/teams-chat.js +4 -11
  192. package/dist/teams.js +12 -19
  193. package/dist/telegram-lead.js +2 -2
  194. package/dist/telegram.js +1 -1
  195. package/dist/token-notices.d.ts +0 -11
  196. package/dist/token-notices.js +1 -5
  197. package/dist/tool-secret-store.d.ts +0 -3
  198. package/dist/tool-secret-store.js +2 -11
  199. package/dist/toolroll-update.d.ts +0 -2
  200. package/dist/toolroll-update.js +2 -2
  201. package/dist/verification-evidence.d.ts +0 -1
  202. package/dist/verification-evidence.js +0 -1
  203. package/dist/webhooks.d.ts +0 -1
  204. package/dist/webhooks.js +0 -1
  205. package/dist/workspace-ui.d.ts +0 -8
  206. package/dist/workspace-ui.js +1 -6
  207. package/package.json +1 -1
  208. package/dist/contracts/native-census.d.ts +0 -42
  209. package/dist/contracts/native-census.js +0 -36
  210. package/dist/process-recovery-anchor.d.ts +0 -75
  211. package/dist/process-recovery-anchor.js +0 -188
  212. package/dist/process-recovery-coalition.d.ts +0 -25
  213. package/dist/process-recovery-coalition.js +0 -105
  214. package/dist/process-recovery-eligibility.d.ts +0 -179
  215. package/dist/process-recovery-eligibility.js +0 -174
  216. package/dist/process-recovery-native.d.ts +0 -161
  217. package/dist/process-recovery-native.js +0 -595
  218. package/dist/process-recovery-provenance.d.ts +0 -163
  219. package/dist/process-recovery-provenance.js +0 -292
  220. package/dist/process-recovery-services.d.ts +0 -56
  221. package/dist/process-recovery-services.js +0 -191
  222. package/dist/process-recovery-settlement.d.ts +0 -32
  223. package/dist/process-recovery-settlement.js +0 -133
  224. package/dist/process-recovery.d.ts +0 -41
  225. package/dist/process-recovery.js +0 -91
  226. package/dist/session-brief.d.ts +0 -8
  227. package/dist/session-brief.js +0 -24
  228. package/dist/session-cli.d.ts +0 -42
  229. package/dist/session-cli.js +0 -271
  230. package/dist/session-contract.d.ts +0 -183
  231. package/dist/session-contract.js +0 -122
  232. package/dist/session-remote.d.ts +0 -19
  233. package/dist/session-remote.js +0 -86
  234. package/dist/session-service.d.ts +0 -22
  235. package/dist/session-service.js +0 -157
  236. package/dist/team-cli.js +0 -692
package/dist/exec.js CHANGED
@@ -9,12 +9,12 @@
9
9
  import { ACP_LINE_CAP, createAcpConversation } from "./acp-client.js";
10
10
  import { linuxFenceAvailable, linuxFenced, macosFenceAvailable, macosFenced } from "./agent-fence.js";
11
11
  import { execFile, execFileSync, spawn } from "node:child_process";
12
- import { readFileSync, realpathSync } from "node:fs";
13
- import { join } from "node:path";
12
+ import { realpathSync } from "node:fs";
14
13
  import { observeProcessTree, stopProcessTree } from "./process-tree.js";
15
14
  import { jsonlDiscriminants } from "./jsonl-discriminants.js";
16
15
  import { createContainer, currentContainment } from "./containment.js";
17
16
  import { claudeLimitsOf, noteLimits } from "./provider-limits.js";
17
+ import { sleep as defaultSleep } from "./sleep.js";
18
18
  /** Shell convention for "could not be executed": the refusal before any target ran. */
19
19
  export const CONTAINMENT_REFUSED_CODE = 126;
20
20
  /** Live provider children, for the deterministic stop. Registered only when `processGroup` was set. */
@@ -508,7 +508,7 @@ export function isTransientSpawnFailure(error) {
508
508
  * A non-transient answer — success, a real exit code, not found, timeout —
509
509
  * is returned at once: only the never-started case is retried.
510
510
  */
511
- export async function retryTransientSpawn(attempt, delays = SPAWN_RETRY_DELAYS_MS, sleep = ms => new Promise(resolve => setTimeout(resolve, ms))) {
511
+ export async function retryTransientSpawn(attempt, delays = SPAWN_RETRY_DELAYS_MS, sleep = defaultSleep) {
512
512
  let last = await attempt();
513
513
  for (const delay of delays) {
514
514
  if (!last.transient)
@@ -942,81 +942,6 @@ function leadingClaudeSystemSubtype(prefix) {
942
942
  }
943
943
  /** How much of an oversized Claude result's end is kept to read its cost and usage (they follow the words). */
944
944
  const CLAUDE_RESULT_TAIL_CAP = 64 * 1024;
945
- /**
946
- * Where a key's value starts in a fragment of JSON text, once and only once. `"key":` never occurs inside a JSON
947
- * string (every quote there is escaped, so `y":` cannot appear), so each match is a real key, though possibly of a
948
- * nested object. A key seen more than once is ambiguous and reads as absent.
949
- */
950
- function soleKeyValueAt(texts, key) {
951
- const pattern = new RegExp(`"${key}"\\s*:\\s*`, "g");
952
- let found = null;
953
- for (const text of texts) {
954
- for (const match of text.matchAll(pattern)) {
955
- if (found !== null)
956
- return null;
957
- found = { text, at: match.index + match[0].length };
958
- }
959
- }
960
- return found;
961
- }
962
- /** The JSON object starting at `at`, read to its matching brace (strings and escapes respected), or null. */
963
- function jsonObjectAt(text, at) {
964
- if (text[at] !== "{")
965
- return null;
966
- let depth = 0, inString = false;
967
- for (let i = at; i < text.length && i - at < CLAUDE_RESULT_TAIL_CAP; i += 1) {
968
- const c = text[i];
969
- if (inString) {
970
- if (c === "\\")
971
- i += 1;
972
- else if (c === '"')
973
- inString = false;
974
- }
975
- else if (c === '"')
976
- inString = true;
977
- else if (c === "{")
978
- depth += 1;
979
- else if (c === "}" && --depth === 0) {
980
- try {
981
- const value = JSON.parse(text.slice(at, i + 1));
982
- return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
983
- }
984
- catch {
985
- return null;
986
- }
987
- }
988
- }
989
- return null;
990
- }
991
- /**
992
- * The accounting an oversized Claude result still carries, read by a bounded scan of its kept prefix and tail: the
993
- * session's running `total_cost_usd`, its `usage` and `num_turns`, and whether it is a main result at all (an
994
- * `origin` naming anything but a person makes it a background task's). Anything unreadable or seen twice is absent.
995
- */
996
- export function scanOversizedClaudeResult(prefix, tail) {
997
- const texts = [prefix.toString("utf8"), ...(tail === undefined ? [] : [tail.toString("utf8")])];
998
- const origin = soleKeyValueAt(texts, "origin");
999
- const originObject = origin === null ? null : jsonObjectAt(origin.text, origin.at);
1000
- const primary = originObject === null || String(originObject["kind"] ?? "") === "human";
1001
- const account = {};
1002
- const number = (key) => {
1003
- const at = soleKeyValueAt(texts, key);
1004
- const match = at === null ? null : /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/.exec(at.text.slice(at.at, at.at + 64));
1005
- const value = match === null ? NaN : Number(match[0]);
1006
- return Number.isFinite(value) && value >= 0 ? value : null;
1007
- };
1008
- const cost = number("total_cost_usd");
1009
- if (cost !== null)
1010
- account["total_cost_usd"] = cost;
1011
- const turns = number("num_turns");
1012
- if (turns !== null)
1013
- account["num_turns"] = turns;
1014
- const usageAt = soleKeyValueAt(texts, "usage");
1015
- const usage = usageAt === null ? null : jsonObjectAt(usageAt.text, usageAt.at);
1016
- if (usage !== null)
1017
- account["usage"] = usage;
1018
- return { primary, account };
1019
- }
1020
945
  /** Marks a Claude result whose session cost could not be read: the gateway charges the run's dollar cap instead. */
1021
946
  export const CLAUDE_COST_UNKNOWN = "standing_orders_cost_unknown";
1022
947
  function malformedCodexEventIsLoadBearing(prefix) {
@@ -1036,7 +961,6 @@ function malformedGeminiEventIsLoadBearing(prefix) {
1036
961
  return type === "init" || type === "result";
1037
962
  }
1038
963
  export function runStreamJsonl(file, args, options = {}) {
1039
- const { cwd } = options;
1040
964
  const childEnv = resolveChildEnv(options);
1041
965
  return new Promise(resolve => {
1042
966
  let child;
@@ -1249,7 +1173,6 @@ export function runStreamJsonl(file, args, options = {}) {
1249
1173
  * semantics match `runStreamJsonl`.
1250
1174
  */
1251
1175
  export function runGeminiStreamJsonl(file, args, options = {}) {
1252
- const { cwd } = options;
1253
1176
  const childEnv = resolveChildEnv(options);
1254
1177
  return new Promise(resolve => {
1255
1178
  let child;
@@ -1843,7 +1766,6 @@ export const STREAM_INPUT = Symbol.for("toolroll.streamInput");
1843
1766
  /** Whether a runner declares it keeps stdin open for a live session; an injected runner opts in by carrying the mark. */
1844
1767
  export const streamsInput = (runner) => typeof runner === "function" && runner[STREAM_INPUT] === true;
1845
1768
  export function runClaudeStreamJsonl(file, args, options = {}) {
1846
- const { cwd } = options;
1847
1769
  const childEnv = resolveChildEnv(options);
1848
1770
  const live = options.liveInput ?? null;
1849
1771
  return new Promise(resolve => {
@@ -18,9 +18,6 @@
18
18
  * answer: the card takes its failure path. Trouble reaching a service is
19
19
  * tried again, like every step.
20
20
  */
21
- import { createHash } from "node:crypto";
22
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
23
- import { join } from "node:path";
24
21
  import { redactSecretAssignments } from "./builder.js";
25
22
  import { redactSecretLines, scanForSecrets } from "./evidence.js";
26
23
  import { fillFlowText } from "./flows.js";
@@ -1,4 +1,4 @@
1
- import { run, type ExecResult } from "./exec.js";
1
+ import { type CommandRunner } from "./claude-print.js";
2
2
  import { type FlowDefinition, type FlowStage } from "./flows.js";
3
3
  export declare const DRAFT_CHARS: 12000;
4
4
  export type DraftCard = {
@@ -37,8 +37,6 @@ export declare function draftPrompt(stage: FlowStage, card: DraftCard, definitio
37
37
  export declare function wholeDraft(text: string): string;
38
38
  /** A draft a person edited, as kept: trimmed, whole (one over DRAFT_CHARS is refused where it is written, never cut), and never holding a key-shaped line. */
39
39
  export declare function keptDraft(text: string): string;
40
- type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
41
40
  /** The production runner: Claude through the sign-in on this computer, with no tools, no MCP servers and no repository. */
42
41
  export declare function claudeDraftRunner(runner?: CommandRunner): DraftRunner;
43
42
  export declare const DRAFT_TIMEOUT = 180000;
44
- export {};
@@ -7,13 +7,9 @@
7
7
  * nothing is sent: a later zone shows it to a person, and a later step posts
8
8
  * it ({{stage.<id>}}).
9
9
  */
10
- import { Buffer } from "node:buffer";
11
- import { mkdtempSync, rmSync } from "node:fs";
12
- import { tmpdir } from "node:os";
13
- import { join } from "node:path";
14
- import { strictJsonParse } from "./converse.js";
15
10
  import { redactSecretLines, scanForSecrets } from "./evidence.js";
16
11
  import { run } from "./exec.js";
12
+ import { CLAUDE_NO_TOOLS_ARGS, CLAUDE_SIGNED_OUT, claudeJsonBody, claudeModelArgs, inScratchDir } from "./claude-print.js";
17
13
  import { fillFlowText } from "./flows.js";
18
14
  import { ALL_CREDENTIAL_ENV } from "./provider.js";
19
15
  import { LIMITS } from "./decision.js";
@@ -62,30 +58,21 @@ export function keptDraft(text) {
62
58
  }
63
59
  /** The production runner: Claude through the sign-in on this computer, with no tools, no MCP servers and no repository. */
64
60
  export function claudeDraftRunner(runner = run) {
65
- return async (request) => {
66
- const dir = mkdtempSync(join(tmpdir(), "standing-orders-draft-"));
61
+ return request => inScratchDir("standing-orders-draft-", async (dir) => {
67
62
  const started = Date.now();
68
- try {
69
- const result = await runner("claude", [
70
- "-p", "--output-format", "json", "--safe-mode", "--no-session-persistence", "--tools", "", "--permission-mode", "dontAsk",
71
- "--permission-prompts", "none", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}',
72
- ...(request.model === "default" ? [] : ["--model", request.model]),
73
- ], { cwd: dir, stdin: request.prompt, timeoutMs: request.timeoutMs, maxBuffer: 256 * 1024, omitEnv: ALL_CREDENTIAL_ENV, processGroup: true });
74
- if (result.notFound)
75
- return { ok: false, said: "Claude isn't installed on this computer." };
76
- if (result.timedOut)
77
- return { ok: false, said: "Claude took too long to write the draft." };
78
- const parsed = strictJsonParse(Buffer.from(result.stdout, "utf8"), 256 * 1024, 12);
79
- const body = parsed.ok && typeof parsed.value === "object" && parsed.value !== null && !Array.isArray(parsed.value) ? parsed.value : null;
80
- if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success" || typeof body["result"] !== "string") {
81
- return { ok: false, said: /not logged in|login|authenticat/i.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : "Claude couldn't write the draft." };
82
- }
83
- const cost = body["total_cost_usd"];
84
- return { ok: true, text: body["result"], ms: Date.now() - started, ...(typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? { costUsd: cost } : {}) };
63
+ const result = await runner("claude", [
64
+ "-p", "--output-format", "json", ...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
65
+ ], { cwd: dir, stdin: request.prompt, timeoutMs: request.timeoutMs, maxBuffer: 256 * 1024, omitEnv: ALL_CREDENTIAL_ENV, processGroup: true });
66
+ if (result.notFound)
67
+ return { ok: false, said: "Claude isn't installed on this computer." };
68
+ if (result.timedOut)
69
+ return { ok: false, said: "Claude took too long to write the draft." };
70
+ const body = claudeJsonBody(result.stdout, 256 * 1024);
71
+ if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success" || typeof body["result"] !== "string") {
72
+ return { ok: false, said: CLAUDE_SIGNED_OUT.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : "Claude couldn't write the draft." };
85
73
  }
86
- finally {
87
- rmSync(dir, { recursive: true, force: true });
88
- }
89
- };
74
+ const cost = body["total_cost_usd"];
75
+ return { ok: true, text: body["result"], ms: Date.now() - started, ...(typeof cost === "number" && Number.isFinite(cost) && cost >= 0 ? { costUsd: cost } : {}) };
76
+ });
90
77
  }
91
78
  export const DRAFT_TIMEOUT = DRAFT_TIMEOUT_MS;
@@ -1,5 +1,5 @@
1
1
  import { type ScriptLanguage } from "./flows.js";
2
- import type { FlowScriptRow, Store } from "./store.js";
2
+ import type { Store } from "./store.js";
3
3
  export type ScriptDraft = {
4
4
  name: string;
5
5
  about: string;
@@ -29,10 +29,3 @@ export type ScriptSaved = {
29
29
  };
30
30
  /** Save a script (a new version when it exists). */
31
31
  export declare function saveScript(store: Store, repo: string, input: Parameters<typeof validateScript>[0], actor: string, now: Date): ScriptSaved;
32
- /** The flows and zones in a project that run each script. */
33
- export declare function scriptUses(store: Store, repo: string): Map<string, {
34
- flow: number;
35
- flowName: string;
36
- zone: string;
37
- }[]>;
38
- export declare function scriptWords(script: FlowScriptRow): string;
@@ -10,7 +10,6 @@
10
10
  */
11
11
  import { createHash } from "node:crypto";
12
12
  import { scanForSecrets } from "./evidence.js";
13
- import { flowDefinitionOf } from "./flow-engine.js";
14
13
  import { SCRIPT_LANGUAGES, SCRIPT_NAME } from "./flows.js";
15
14
  /** A script as it would be saved, checked in plain words. Throws. */
16
15
  export function validateScript(input) {
@@ -59,15 +58,3 @@ export function saveScript(store, repo, input, actor, now) {
59
58
  const version = store.saveFlowScript({ repo, ...draft, digest: scriptDigest(draft), by: actor }, now);
60
59
  return { ok: true, said: current === null ? `Saved the ${draft.name} script. Any flow in this project can run it.` : `Saved version ${version} of ${draft.name}. Every flow that runs it uses this version from now on.`, version };
61
60
  }
62
- /** The flows and zones in a project that run each script. */
63
- export function scriptUses(store, repo) {
64
- const uses = new Map();
65
- for (const flow of store.listFlows([repo]))
66
- for (const stage of flowDefinitionOf(flow)?.stages ?? [])
67
- if (stage.kind === "check" && stage.script !== null)
68
- uses.set(stage.script, [...uses.get(stage.script) ?? [], { flow: flow.id, flowName: flow.name, zone: stage.title }]);
69
- return uses;
70
- }
71
- export function scriptWords(script) {
72
- return `${script.name} (version ${script.version}, up to ${script.timeoutMinutes} min): ${script.about}`;
73
- }
package/dist/flow-send.js CHANGED
@@ -19,7 +19,7 @@ import { withActor } from "./actor.js";
19
19
  import { flowCardHref, flowDefinitionOf, revisionWithNote } from "./flow-engine.js";
20
20
  import { itemPlug, itemSource } from "./flow-items.js";
21
21
  import { withStageHandoff } from "./contracts/stage-output.js";
22
- import { flowSendForStore, readFlowChoiceAnswer, readFlowItems, readFlowSendPayload } from "./contracts/flow-send.js";
22
+ import { flowSendForStore, readFlowChoiceAnswer, readFlowSendPayload } from "./contracts/flow-send.js";
23
23
  import { notifyPeople } from "./flow-people.js";
24
24
  import { readVerifiedReport } from "./evidence.js";
25
25
  import { FLOW_END, replyTarget } from "./flows.js";
@@ -59,8 +59,6 @@ export declare function importFlow(store: Store, plan: FlowImportPlan, actor: st
59
59
  id: number;
60
60
  said: string;
61
61
  };
62
- /** What a flow's zones and paths are, without where they sit on the canvas: what a round trip keeps. */
63
- export declare function flowShape(definition: FlowDefinition): string;
64
62
  /** A gist or GitHub file page as the address of its raw text; null when it isn't one Toolroll fetches. */
65
63
  export declare function rawFlowUrl(address: string): string | null;
66
64
  export type FetchLike = (url: string, init: {
@@ -15,7 +15,6 @@
15
15
  * a person approves them, and its instructions are shown as the untrusted
16
16
  * text they are.
17
17
  */
18
- import { createHash } from "node:crypto";
19
18
  import { scanForSecrets } from "./evidence.js";
20
19
  import { flowDefinitionOf } from "./flow-engine.js";
21
20
  import { readFlowSecrets } from "./flow-secrets.js";
@@ -24,7 +23,7 @@ import { addFlowTriggerTo, describeTrigger, HOOK_PATH, readHooksBase, triggerCon
24
23
  import { durationMinutes, durationWords, FlowContractError, flowTerms, inStepWords, LANGUAGE_WORDS, validateFlowDefinition } from "./flows.js";
25
24
  import { stageReferenceProblems } from "./contracts/stage-output.js";
26
25
  import { readVersioned } from "./contracts/contract.js";
27
- import { FLOW_ALIASES, WEBHOOK_SENDERS, FLOW_FILE_FORMAT, legacyFlowNeed, legacySubagentStep, FLOW_FILE_VERSION, flowFileSchema, PARAMETER_ID } from "./contracts/flow.js";
26
+ import { FLOW_ALIASES, WEBHOOK_SENDERS, FLOW_FILE_FORMAT, legacyFlowNeed, legacySubagentStep, FLOW_FILE_VERSION, flowFileSchema } from "./contracts/flow.js";
28
27
  import { parseSchedule } from "./flow-schedule.js";
29
28
  export { FLOW_FILE_FORMAT, FLOW_FILE_VERSION };
30
29
  /** The largest flow file Toolroll reads or fetches. */
@@ -550,10 +549,6 @@ export function importFlow(store, plan, actor, now, dir) {
550
549
  return { id, said: `Imported ${plan.name}.${off === 0 ? "" : ` Its ${off === 1 ? "trigger is" : `${off} triggers are`} off until you turn ${off === 1 ? "it" : "them"} on.`}${held === 0 ? "" : ` Approve its ${held === 1 ? "script" : `${held} scripts`} on the Scripts panel before ${held === 1 ? "it runs" : "they run"}.`}` };
551
550
  });
552
551
  }
553
- /** What a flow's zones and paths are, without where they sit on the canvas: what a round trip keeps. */
554
- export function flowShape(definition) {
555
- return createHash("sha256").update(JSON.stringify({ start: definition.start, stages: definition.stages.map(one => ({ ...one, zone: null })) })).digest("hex");
556
- }
557
552
  // ------------------------------------------------------------------ fetching
558
553
  const FETCH_HOSTS = new Set(["github.com", "gist.github.com", "raw.githubusercontent.com", "gist.githubusercontent.com"]);
559
554
  /** A gist or GitHub file page as the address of its raw text; null when it isn't one Toolroll fetches. */
@@ -22,7 +22,7 @@
22
22
  * twice. Trouble reaching a service is retried three times, 5 then 15
23
23
  * minutes apart; a check that fails is an answer, not trouble.
24
24
  */
25
- import { chmodSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
25
+ import { mkdirSync, rmSync } from "node:fs";
26
26
  import { join } from "node:path";
27
27
  import { approvedCommandShell, redactSecretAssignments, SETUP_ENV_ALLOWLIST, SETUP_ENV_DENYLIST } from "./builder.js";
28
28
  import { assignmentOf } from "./assignment.js";
@@ -62,7 +62,6 @@ export declare function takesDeliveries(config: TriggerConfig): boolean;
62
62
  export declare function saveHookSecret(dir: string, trigger: number, secret: string, credential?: string): void;
63
63
  /** Exactly this credential's secret, or null: never another's. */
64
64
  export declare function readHookSecret(dir: string, trigger: number, credential?: string): string | null;
65
- export declare const LINEAR_ENV = "TOOLROLL_LINEAR_KEY";
66
65
  /** The Linear API key the worker checks Linear with: the environment, or kept by Toolroll (the keychain, or an owner-only file beside the database). */
67
66
  export declare function readLinearKey(dir: string | null): string | null;
68
67
  export declare function saveLinearKey(dir: string, key: string): {
@@ -50,6 +50,7 @@ import { prepareUnattendedCandidates, grantSignsScriptOf, scriptProvenanceOf, sc
50
50
  import { tmpdir } from "node:os";
51
51
  import { envValue } from "./names.js";
52
52
  import { linearLabelNames, readFormSubmission, readGithubEvent, readGithubIssue, readGithubIssueEventList, readGithubIssueList, readGithubRun, readGithubRunList, readInboundMail, readLinearAnswer, readLinearEvent, readLinearIssue, readWebhookPayload } from "./contracts/trigger-payloads.js";
53
+ import { isRecord } from "./is-record.js";
53
54
  export { FLOW_TRIGGER_KINDS };
54
55
  export const CHAT_APP_NAMES = { slack: "Slack", discord: "Discord", teams: "Teams", telegram: "Telegram" };
55
56
  /** What each kind is called on the canvas. */
@@ -66,7 +67,6 @@ const HOOK_BYTES = 1_000_000;
66
67
  const TEAM = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
67
68
  // ------------------------------------------------------------ the terms
68
69
  const HIDDEN = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f\u200b-\u200f\u202a-\u202e\u2066-\u2069]/;
69
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
70
70
  /**
71
71
  * A trigger's settings read by their one schema (`label: required`, `unknown key 'flows'`). A setting given as null is
72
72
  * left out, and a button's blank question lines are dropped, as every release has read them. Then what the schema can't
@@ -414,7 +414,6 @@ function dropHookSecret(dir, trigger, credential) {
414
414
  catch { /* never read: nothing points at it */ }
415
415
  }
416
416
  const LINEAR = { name: "linear-key", file: ["linear-key"] };
417
- export const LINEAR_ENV = "TOOLROLL_LINEAR_KEY";
418
417
  /** The Linear API key the worker checks Linear with: the environment, or kept by Toolroll (the keychain, or an owner-only file beside the database). */
419
418
  export function readLinearKey(dir) {
420
419
  const env = envValue(process.env, "LINEAR_KEY")?.trim();
@@ -33,6 +33,7 @@ import { isProtectedWork } from "./approval-policy.js";
33
33
  import { dollarWords as dollars, scheduleWords, UNATTENDED_RULE_WORDS, unattendedCoverWords, unattendedEndWords, unattendedHeadWords, unattendedLimitWords, untilWords } from "./flow-unattended-words.js";
34
34
  import { MODE_MAX_DAYS } from "./modes.js";
35
35
  import { accountReachesSql } from "./project-access.js";
36
+ import { canonicalJson } from "./canonical-json.js";
36
37
  /** Grant history, run reservations and the last prepared script snapshots shared by UI/worker processes. Additive only. */
37
38
  export const FLOW_UNATTENDED_SCHEMA = `
38
39
  CREATE TABLE IF NOT EXISTS flow_script_provenance (
@@ -72,18 +73,6 @@ export const FLOW_ACCEPTANCE = {
72
73
  export const UNATTENDED_MAX_RUNS = 50;
73
74
  /** The largest per-attempt budget a grant may name: $100. */
74
75
  export const UNATTENDED_MAX_BUDGET_MICROUSD = 100_000_000;
75
- function canonicalJson(value) {
76
- if (Array.isArray(value))
77
- return `[${value.map(canonicalJson).join(",")}]`;
78
- if (value !== null && typeof value === "object") {
79
- const entries = Object.entries(value)
80
- .filter(([, v]) => v !== undefined)
81
- .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
82
- .map(([k, v]) => `${JSON.stringify(k)}:${canonicalJson(v)}`);
83
- return `{${entries.join(",")}}`;
84
- }
85
- return JSON.stringify(value);
86
- }
87
76
  export const unattendedTermsJson = (terms) => canonicalJson(terms);
88
77
  /** sha256 over a domain-separated canonical encoding, 32 hex like the mode digest. */
89
78
  export function unattendedDigestOf(terms) {
package/dist/flows.js CHANGED
@@ -54,6 +54,7 @@ import { cardReference } from "./task-source.js";
54
54
  import { parseContract, readVersioned } from "./contracts/contract.js";
55
55
  import { stageReferenceProblems } from "./contracts/stage-output.js";
56
56
  import { CHOICES_MAX, CHOICES_MIN, FLOW_ALIASES, FLOW_COLORS, FLOW_DEFINITION_VERSION, FLOW_END, FLOW_MERGE_METHODS, FLOW_STAGE_KINDS, flowDefinitionSchema, flowStepsSchema, HEADERS_MAX, legacySubagentStep, LONGEST_WAIT_MINUTES, savedFlowDefinitionSchema, SCRIPT_LANGUAGES, SCRIPT_NAME, sortKeyOf, SURE_AT_MAX, SURE_AT_MIN, ZONE_ID, } from "./contracts/flow.js";
57
+ import { isRecord } from "./is-record.js";
57
58
  export { CHOICES_MAX, CHOICES_MIN, FLOW_COLORS, FLOW_END, FLOW_MERGE_METHODS, FLOW_STAGE_KINDS, LONGEST_WAIT_MINUTES, SCRIPT_LANGUAGES, SCRIPT_NAME, sortKeyOf };
58
59
  /** What each kind is called and does, in the words the canvas uses. */
59
60
  export const FLOW_KIND_WORDS = {
@@ -137,7 +138,6 @@ export class FlowContractError extends Error {
137
138
  }
138
139
  }
139
140
  // ------------------------------------------------------------------ reading a drawing
140
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
141
141
  /** Text as every release has kept it: trimmed, and blank as none. Anything else is left for the schema to name. */
142
142
  const said = (value) => value === undefined || value === null ? null : typeof value === "string" ? value.trim() === "" ? null : value.trim() : value;
143
143
  const coordinate = (value, min, max, fallback) => typeof value === "number" && Number.isFinite(value) ? Math.round(Math.min(max, Math.max(min, value))) : fallback;
@@ -1,3 +1,3 @@
1
- import { type TeamCliOptions } from './team-cli.js';
1
+ import { type ConnectOptions } from './connect-cli.js';
2
2
  /** Read the running server, never a fresh CLI process's empty counters or the local database. */
3
- export declare function runHealthCommand(argv: readonly string[], write: (line: string) => void, options?: TeamCliOptions): Promise<number>;
3
+ export declare function runHealthCommand(argv: readonly string[], write: (line: string) => void, options?: ConnectOptions): Promise<number>;
@@ -1,4 +1,4 @@
1
- import { bearerOf, centralProfile } from './team-cli.js';
1
+ import { bearerOf, centralProfile } from './connect-cli.js';
2
2
  import { envelopeJson } from './envelope.js';
3
3
  import { healthSnapshotSchema } from './contracts/health.js';
4
4
  /** Read the running server, never a fresh CLI process's empty counters or the local database. */
package/dist/invoke.d.ts CHANGED
@@ -24,9 +24,6 @@ import type { Runner } from "./worktree.js";
24
24
  import { type WritesMode } from "./agent-fence.js";
25
25
  import { type NetworkProfile } from "./egress.js";
26
26
  export type { ProviderRunner } from "./provider.js";
27
- /** The claude binary name — kept for the legacy quota rows and tests that
28
- * describe history; new code carries a resolved AgentSpec instead. */
29
- export declare const PROVIDER_BINARY = "claude";
30
27
  export type ProviderUsage = {
31
28
  tokensIn: number | null;
32
29
  tokensOut: number | null;
package/dist/invoke.js CHANGED
@@ -39,9 +39,6 @@ import { proxyEnv, providerOnlyNetwork, startEgressProxy } from "./egress.js";
39
39
  import { bridgeFits, startEgressBridge } from "./egress-bridge.js";
40
40
  import { claudeConfigDir, claudeDefaults, codexDefaults, codexHomeDir, isolatedCodexHome } from "./provider-home.js";
41
41
  import { billingOf, claudeBillingFrom, seenBilling } from "./spend.js";
42
- /** The claude binary name — kept for the legacy quota rows and tests that
43
- * describe history; new code carries a resolved AgentSpec instead. */
44
- export const PROVIDER_BINARY = "claude";
45
42
  /** "Within seconds": how soon a silent failed run must end for its stderr to
46
43
  * be read for the sign-in signal. */
47
44
  const AUTH_EARLY_EXIT_MS = 30_000;
@@ -64,6 +61,11 @@ function claudeSettingsAuthProblem(configDir) {
64
61
  catch (error) {
65
62
  if (error.code === "ENOENT")
66
63
  return null;
64
+ // A sandbox around the plane (a project check's fence, say) may hide the file while the CLI still signs in from its
65
+ // keychain. Isolated builds never load it, and a login that needed it fails within seconds and is reported as one.
66
+ const code = error.code;
67
+ if (code === "EPERM" || code === "EACCES")
68
+ return null;
67
69
  return "Can't read your Claude settings.json to check sign-in. Restore access to that file and try again. Isolated builds do not load it.";
68
70
  }
69
71
  let settings;
@@ -0,0 +1,2 @@
1
+ /** A plain object: not null, not an array. */
2
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
@@ -0,0 +1,2 @@
1
+ /** A plain object: not null, not an array. */
2
+ export const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1,5 +1,5 @@
1
1
  import { type SharedActionOptions } from './chat-actions.js';
2
- import { type CoordinatorProposal, type LeadProposal, type Store } from "./store.js";
2
+ import { type LeadProposal, type Store } from "./store.js";
3
3
  import type { VerifiedApprover } from "./principal.js";
4
4
  import { type TeamChatProviderResolver } from './team-chat-authorization.js';
5
5
  export type ProposalKind = LeadProposal["kind"];
@@ -78,7 +78,3 @@ export declare function dismissLeadProposal(store: Store, who: VerifiedApprover,
78
78
  */
79
79
  export declare function confirmCoordinatorProposal(store: Store, who: VerifiedApprover, proposalId: number, now: Date, options: DoorOptions): DoorOutcome;
80
80
  export declare function dismissCoordinatorProposal(store: Store, who: VerifiedApprover, proposalId: number, now: Date): boolean;
81
- /** Which door renders a coordinator proposal for this reader: the repo must be admitted. */
82
- export declare function coordinatorProposalVisible(who: {
83
- repos: readonly string[];
84
- }, proposal: CoordinatorProposal): boolean;
@@ -260,10 +260,6 @@ export function dismissCoordinatorProposal(store, who, proposalId, now) {
260
260
  return store.casCoordinatorProposal(proposalId, "pending", "dismissed", who.name, null, now);
261
261
  });
262
262
  }
263
- /** Which door renders a coordinator proposal for this reader: the repo must be admitted. */
264
- export function coordinatorProposalVisible(who, proposal) {
265
- return who.repos.includes(proposal.repo);
266
- }
267
263
  /**
268
264
  * The shared executor: one kind, one payload, the operator's own act
269
265
  * through the primitive that owns it. Module-private (v3 review, finding
@@ -1,5 +1,4 @@
1
1
  import { sweepLine, sweepTable } from "./lead-sweep.js";
2
- import { TEXT_LIMITS } from "./text-limits.js";
3
2
  import { connectionsOf, oneClickOf } from "./mcp-connect.js";
4
3
  import { checkLevelFromWords, isCheckLevel } from "./check-levels.js";
5
4
  import { policyParts } from "./policy.js";
@@ -39,9 +38,9 @@ import { CHAT_TASK_ACTIONS, chatTaskRun, chatTaskStamp, isChatTaskAction } from
39
38
  import { Buffer } from "node:buffer";
40
39
  import { LEAD_ASK_OTHER } from "./store.js";
41
40
  import { hasDisguisedText, hasForbiddenControls } from "./decision.js";
42
- import { readVerifiedArtifact, readVerifiedReport, scanForSecrets } from "./evidence.js";
41
+ import { readVerifiedArtifact, scanForSecrets } from "./evidence.js";
43
42
  import { parseAcceptanceCriteria } from "./scope.js";
44
- import { diagnoseTaskDispatch, withDispatchDiagnoses } from "./dispatch.js";
43
+ import { diagnoseTaskDispatch } from "./dispatch.js";
45
44
  import { agentChoicesFor, routeOfTask, INSTALLATION_SCOPE } from "./agentconfig.js";
46
45
  import { isNewModel, modelWords, priceWords, runtimeStates, seenModels } from "./model-catalog.js";
47
46
  import { agentsSummary, chosenWords, PHASES, postureWords, routeProblems, sameSpec, sizeSourceWords, sizeWords, specWords } from "./phase-routing.js";
@@ -55,7 +54,7 @@ import { planInChat } from "./chat-decide.js";
55
54
  import { flowDecisionAt } from "./telegram-flow.js";
56
55
  import { flowPersonOf } from "./flow-send.js";
57
56
  import { flowInsights } from "./flow-insights.js";
58
- import { describeTrigger, FLOW_TRIGGER_KINDS, triggerConfigOf } from "./flow-triggers.js";
57
+ import { describeTrigger, triggerConfigOf } from "./flow-triggers.js";
59
58
  export const LEAD_MAX_PROPOSALS_PER_TURN = 5;
60
59
  export { reportSummaryFor } from "./report-summary.js";
61
60
  import { reportSummaryFor } from "./report-summary.js";
@@ -63,8 +62,6 @@ import { labelOf, nameOf, summaryOf, zonesOf } from "./subagent-admin.js";
63
62
  import { SUBAGENT_TEMPLATES, withSection } from "./subagents.js";
64
63
  import { callOutcome, callWords, defaultRule, ruleWords } from "./subagent-tools.js";
65
64
  import { deskOf, routinesOf } from "./subagent-desk.js";
66
- import { KITS } from "./kits.js";
67
- import { STARTER_IDS } from "./flow-starters.js";
68
65
  import { undoFor, weekOf, weekWords } from "./subagent-week.js";
69
66
  import { PERSON_ID, personEntry, teamRoomOf } from "./lead-people.js";
70
67
  import { aboutYouOf, checkAboutYouLine } from "./lead-about.js";
@@ -10,7 +10,6 @@ export type LiveDetailSetting = {
10
10
  };
11
11
  /** Whether this project's live conversations show commands. Unknown or absent is off. */
12
12
  export declare function liveCommandsShown(store: Store, repo: string | null): boolean;
13
- export declare function liveDetailSetting(store: Store, repo: string): LiveDetailSetting | null;
14
13
  /** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
15
14
  export declare function setLiveCommands(store: Store, change: {
16
15
  repo: string;
@@ -26,12 +26,6 @@ export function liveCommandsShown(store, repo) {
26
26
  return false;
27
27
  }
28
28
  }
29
- export function liveDetailSetting(store, repo) {
30
- const row = store.handle.prepare("SELECT repo, commands, updated_by, updated_at FROM live_detail_setting WHERE repo = ?").get(repo);
31
- if (row === undefined)
32
- return null;
33
- return { repo: String(row["repo"]), commands: Number(row["commands"]) === 1, updatedBy: String(row["updated_by"]), updatedAt: String(row["updated_at"]) };
34
- }
35
29
  /** Save the setting and its ledger line in one transaction. The caller has proved who is asking (and, to turn it on, their password). */
36
30
  export function setLiveCommands(store, change, now) {
37
31
  store.transact(() => {
@@ -13,6 +13,7 @@ import { existsSync, mkdirSync, readlinkSync, realpathSync, statSync } from "nod
13
13
  import { delimiter, isAbsolute, join } from "node:path";
14
14
  import { codingEnvironment } from "./coding-provider.js";
15
15
  import { teardownGit, refusal } from "./teardown-git.js";
16
+ import { sleep } from "./sleep.js";
16
17
  export const TERMINAL_PROGRAMS = ["claude", "codex", "shell"];
17
18
  /** At most this many running sessions per console, and this many kept at all (ended ones count until removed). */
18
19
  export const MAX_LIVE_TERMINALS = 8;
@@ -404,7 +405,7 @@ export class TerminalHost {
404
405
  }
405
406
  async sweep(session) {
406
407
  const grace = this.options.closeGraceMs ?? CLOSE_GRACE_MS;
407
- const pause = (ms) => new Promise(resolve => setTimeout(resolve, ms));
408
+ const pause = sleep;
408
409
  const leaderGone = () => session.pty === null;
409
410
  let readable = true;
410
411
  const members = () => {
package/dist/live.d.ts CHANGED
@@ -16,7 +16,6 @@
16
16
  import { type KeyState, type LiveActivityKind, type LiveRecord, type LiveRecorderOptions } from "./live-records.js";
17
17
  export declare const LIVE_LINE_CAP: number;
18
18
  export declare const LIVE_FILE_CAP: number;
19
- export declare const LIVE_CAP_MARKER = "[the live view stopped at its size cap \u2014 the run record continues]";
20
19
  export declare const LIVE_REDACTED_LINE = "[a credential-shaped line was redacted]";
21
20
  /** Finalized runs keep their live file this long for the final drain. */
22
21
  export declare const LIVE_RETAIN_MS: number;
package/dist/live.js CHANGED
@@ -16,10 +16,9 @@
16
16
  import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, readSync, readdirSync, statSync, unlinkSync, writeSync } from "node:fs";
17
17
  import { join } from "node:path";
18
18
  import { scanForSecrets } from "./evidence.js";
19
- import { createLiveRecorder, LIVE_CAP_WORDS, parseLiveRecords, redactLiveLines, projectLiveText, serializeLiveRecord } from "./live-records.js";
19
+ import { createLiveRecorder, parseLiveRecords, redactLiveLines, projectLiveText, serializeLiveRecord } from "./live-records.js";
20
20
  export const LIVE_LINE_CAP = 2 * 1024;
21
21
  export const LIVE_FILE_CAP = 4 * 1024 * 1024;
22
- export const LIVE_CAP_MARKER = LIVE_CAP_WORDS;
23
22
  export const LIVE_REDACTED_LINE = "[a credential-shaped line was redacted]";
24
23
  /** Finalized runs keep their live file this long for the final drain. */
25
24
  export const LIVE_RETAIN_MS = 24 * 60 * 60 * 1000;
package/dist/mcp-core.js CHANGED
@@ -9,13 +9,11 @@
9
9
  * `tools/call` results with `isError: true`.
10
10
  */
11
11
  import { dirname, join } from 'node:path';
12
- import { statSync } from 'node:fs';
13
12
  import { repositoryContextRead } from './repository-context.js';
14
13
  import { ASSIGNMENT_TOOLS, assignmentForCoordinator } from "./assignment-adapters.js";
15
14
  import { parseContract, toModelSchema } from "./contracts/contract.js";
16
15
  import { GATEWAY_TOOL_INPUTS, GATEWAY_TOOL_OUTPUTS } from "./contracts/gateway-tools.js";
17
16
  import { reportToolOutput } from "./contracts/lead-tools.js";
18
- import { PACKAGE_VERSION } from "./version.js";
19
17
  import { authenticateCoordinator, fileCoordinatorProposal, statusFor, listTasksFor, taskDetailFor, } from "./coordinator.js";
20
18
  import { ISO_STAMP_RULE, decisionOver, decisionsOver, labelRepos, queueOver, recapOver } from "./lead-tools.js";
21
19
  import { proposeAsCoordinator } from "./coordinator-proposals.js";
@@ -13,7 +13,7 @@
13
13
  import { createHash } from 'node:crypto';
14
14
  import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
15
15
  import { homedir } from 'node:os';
16
- import { basename, join } from 'node:path';
16
+ import { join } from 'node:path';
17
17
  import { scanForSecrets, readVerifiedArtifact } from './evidence.js';
18
18
  import { changeKnowledge, knowledgeView } from './project-knowledge.js';
19
19
  import { listDecisions, recordDecision } from './project-memory.js';
@@ -14,7 +14,7 @@ import { delimiter, join } from "node:path";
14
14
  import { fetchOpenRouterModels } from "./openrouter-models.js";
15
15
  import { codexModelSchema, codexModelsCacheSchema, npmLatestSchema } from "./contracts/model-catalog.js";
16
16
  import { readCappedBody } from "./converse.js";
17
- import { validModelId } from "./provider.js";
17
+ import {} from "./provider.js";
18
18
  import { activeUpdateWork } from "./desktop-update-gate.js";
19
19
  export const MODELS_SCHEMA = `
20
20
  CREATE TABLE IF NOT EXISTS model_seen (