reasonix 0.40.0 → 0.43.0

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 (194) hide show
  1. package/README.md +47 -16
  2. package/README.zh-CN.md +19 -13
  3. package/dashboard/app.css +8 -4
  4. package/dashboard/dist/app.js +377 -227
  5. package/dashboard/dist/app.js.map +1 -1
  6. package/dist/cli/acp-DAGPCVFZ.js +713 -0
  7. package/dist/cli/acp-DAGPCVFZ.js.map +1 -0
  8. package/dist/cli/chat-7ES4IBNH.js +50 -0
  9. package/dist/cli/{chunk-E46ECXJD.js → chunk-2425HK6U.js} +2 -1
  10. package/dist/cli/{chunk-E46ECXJD.js.map → chunk-2425HK6U.js.map} +1 -1
  11. package/dist/cli/chunk-25T6CVUP.js +172 -0
  12. package/dist/cli/chunk-25T6CVUP.js.map +1 -0
  13. package/dist/cli/{chunk-7DLHHBGN.js → chunk-2K65GZBT.js} +16 -5
  14. package/dist/cli/chunk-2K65GZBT.js.map +1 -0
  15. package/dist/cli/{chunk-KMWKGPFZ.js → chunk-2KDUS647.js} +14 -4
  16. package/dist/cli/chunk-2KDUS647.js.map +1 -0
  17. package/dist/cli/chunk-2R4QCDOZ.js +11392 -0
  18. package/dist/cli/chunk-2R4QCDOZ.js.map +1 -0
  19. package/dist/cli/{chunk-3Q3C4W66.js → chunk-2UQP6H6T.js} +2 -1
  20. package/dist/cli/{chunk-3Q3C4W66.js.map → chunk-2UQP6H6T.js.map} +1 -1
  21. package/dist/cli/chunk-2Z35JOA4.js +96 -0
  22. package/dist/cli/chunk-2Z35JOA4.js.map +1 -0
  23. package/dist/cli/chunk-32TIKD5U.js +54 -0
  24. package/dist/cli/{chunk-JWCTX5S4.js.map → chunk-32TIKD5U.js.map} +1 -1
  25. package/dist/cli/{chunk-UVRXTSK3.js → chunk-3BXRZFWS.js} +65 -3
  26. package/dist/cli/chunk-3BXRZFWS.js.map +1 -0
  27. package/dist/cli/chunk-3Z6IBU3D.js +249 -0
  28. package/dist/cli/chunk-3Z6IBU3D.js.map +1 -0
  29. package/dist/cli/{chunk-VLNRQMCI.js → chunk-45U62RI3.js} +12 -5
  30. package/dist/cli/chunk-45U62RI3.js.map +1 -0
  31. package/dist/cli/{chunk-5GKJLNP2.js → chunk-4QUNBQQ2.js} +3 -2
  32. package/dist/cli/{chunk-5GKJLNP2.js.map → chunk-4QUNBQQ2.js.map} +1 -1
  33. package/dist/cli/{chunk-R4YTW7PR.js → chunk-5JJRUIPA.js} +57 -12
  34. package/dist/cli/chunk-5JJRUIPA.js.map +1 -0
  35. package/dist/cli/{chunk-HCC42PEI.js → chunk-6AK4EY3D.js} +12 -6
  36. package/dist/cli/chunk-6AK4EY3D.js.map +1 -0
  37. package/dist/cli/chunk-6G3CUUFG.js +34320 -0
  38. package/dist/cli/chunk-6G3CUUFG.js.map +1 -0
  39. package/dist/cli/{chunk-XST7BSZJ.js → chunk-6PBZN4VI.js} +21 -3
  40. package/dist/cli/chunk-6PBZN4VI.js.map +1 -0
  41. package/dist/cli/{chunk-A5LSGEEK.js → chunk-6PZ3CXBP.js} +88 -66
  42. package/dist/cli/chunk-6PZ3CXBP.js.map +1 -0
  43. package/dist/cli/chunk-74EX7SUH.js +25293 -0
  44. package/dist/cli/chunk-74EX7SUH.js.map +1 -0
  45. package/dist/cli/{chunk-FFNOMR32.js → chunk-7O5ALB4C.js} +3 -2
  46. package/dist/cli/{chunk-FFNOMR32.js.map → chunk-7O5ALB4C.js.map} +1 -1
  47. package/dist/cli/{chunk-UCMTWZKU.js → chunk-DOYHN4KB.js} +3 -2
  48. package/dist/cli/{chunk-UCMTWZKU.js.map → chunk-DOYHN4KB.js.map} +1 -1
  49. package/dist/cli/{chunk-XJLZ4HKU.js → chunk-F3PXYSNN.js} +3 -2
  50. package/dist/cli/{chunk-XJLZ4HKU.js.map → chunk-F3PXYSNN.js.map} +1 -1
  51. package/dist/cli/{chunk-XHQIK7B6.js → chunk-FHOGSSCH.js} +4 -3
  52. package/dist/cli/{chunk-XHQIK7B6.js.map → chunk-FHOGSSCH.js.map} +1 -1
  53. package/dist/cli/{chunk-IYF36OCJ.js → chunk-H6PS7IUE.js} +3 -2
  54. package/dist/cli/{chunk-IYF36OCJ.js.map → chunk-H6PS7IUE.js.map} +1 -1
  55. package/dist/cli/{chunk-ZTLZO42A.js → chunk-HFEAY5DT.js} +3 -2
  56. package/dist/cli/{chunk-ZTLZO42A.js.map → chunk-HFEAY5DT.js.map} +1 -1
  57. package/dist/cli/{chunk-FWGEHRB7.js → chunk-J5XJHLWM.js} +2 -1
  58. package/dist/cli/{chunk-FWGEHRB7.js.map → chunk-J5XJHLWM.js.map} +1 -1
  59. package/dist/cli/chunk-JMBMLOBP.js +26 -0
  60. package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
  61. package/dist/cli/{chunk-SZH34P45.js → chunk-O52OLQL3.js} +52 -18
  62. package/dist/cli/chunk-O52OLQL3.js.map +1 -0
  63. package/dist/cli/{chunk-4DCHFFEY.js → chunk-OSZC7C6F.js} +3 -2
  64. package/dist/cli/{chunk-4DCHFFEY.js.map → chunk-OSZC7C6F.js.map} +1 -1
  65. package/dist/cli/chunk-P7EKE5ZQ.js +60641 -0
  66. package/dist/cli/chunk-P7EKE5ZQ.js.map +1 -0
  67. package/dist/cli/{chunk-FM57FNPJ.js → chunk-PLHAZOLZ.js} +2 -1
  68. package/dist/cli/{chunk-FM57FNPJ.js.map → chunk-PLHAZOLZ.js.map} +1 -1
  69. package/dist/cli/{chunk-RFX7TYVV.js → chunk-PQXPXJBJ.js} +16 -2
  70. package/dist/cli/chunk-PQXPXJBJ.js.map +1 -0
  71. package/dist/cli/{chunk-DAEAAVDF.js → chunk-PV55UMTO.js} +2 -1
  72. package/dist/cli/{chunk-DAEAAVDF.js.map → chunk-PV55UMTO.js.map} +1 -1
  73. package/dist/cli/{chunk-H7PHYVPM.js → chunk-RE4RAVFF.js} +85 -14
  74. package/dist/cli/chunk-RE4RAVFF.js.map +1 -0
  75. package/dist/cli/chunk-S4XVGLRW.js +499 -0
  76. package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
  77. package/dist/cli/{chunk-WJ3YX4PZ.js → chunk-SZ5XES2N.js} +3 -2
  78. package/dist/cli/{chunk-WJ3YX4PZ.js.map → chunk-SZ5XES2N.js.map} +1 -1
  79. package/dist/cli/{chunk-4X3NY5ZM.js → chunk-TJX6BFZZ.js} +16 -9
  80. package/dist/cli/{chunk-4X3NY5ZM.js.map → chunk-TJX6BFZZ.js.map} +1 -1
  81. package/dist/cli/chunk-TUK7OWJA.js +51 -0
  82. package/dist/cli/{chunk-WKOMCPXP.js → chunk-VK5HG73G.js} +26 -17
  83. package/dist/cli/chunk-VK5HG73G.js.map +1 -0
  84. package/dist/cli/{chunk-CLAN6PVH.js → chunk-XCGGEJTI.js} +21 -8
  85. package/dist/cli/chunk-XCGGEJTI.js.map +1 -0
  86. package/dist/cli/{chunk-SOZE7V7V.js → chunk-XJXDHAES.js} +3 -2
  87. package/dist/cli/{chunk-SOZE7V7V.js.map → chunk-XJXDHAES.js.map} +1 -1
  88. package/dist/cli/chunk-XPDVG52A.js +2648 -0
  89. package/dist/cli/chunk-XPDVG52A.js.map +1 -0
  90. package/dist/cli/{chunk-CRPQUBP6.js → chunk-XXC2BYTV.js} +2 -1
  91. package/dist/cli/{chunk-CRPQUBP6.js.map → chunk-XXC2BYTV.js.map} +1 -1
  92. package/dist/cli/{chunk-AVB3WZWU.js → chunk-YFGF5NKA.js} +17 -14
  93. package/dist/cli/{chunk-AVB3WZWU.js.map → chunk-YFGF5NKA.js.map} +1 -1
  94. package/dist/cli/{chunk-ORM6PK57.js → chunk-YQ6NTIIE.js} +2 -1
  95. package/dist/cli/{chunk-ORM6PK57.js.map → chunk-YQ6NTIIE.js.map} +1 -1
  96. package/dist/cli/{chunk-ULBW7DYL.js → chunk-YYQAUTTN.js} +3 -2
  97. package/dist/cli/{chunk-ULBW7DYL.js.map → chunk-YYQAUTTN.js.map} +1 -1
  98. package/dist/cli/chunk-ZZM6QJ4W.js +109 -0
  99. package/dist/cli/chunk-ZZM6QJ4W.js.map +1 -0
  100. package/dist/cli/code-SMKEW6CD.js +154 -0
  101. package/dist/cli/code-SMKEW6CD.js.map +1 -0
  102. package/dist/cli/{commands-FQZOBLLZ.js → commands-FVVB5FZF.js} +7 -5
  103. package/dist/cli/{commands-FQZOBLLZ.js.map → commands-FVVB5FZF.js.map} +1 -1
  104. package/dist/cli/{commit-ZS24SHPG.js → commit-HE4VSPZ7.js} +7 -4
  105. package/dist/cli/{commit-ZS24SHPG.js.map → commit-HE4VSPZ7.js.map} +1 -1
  106. package/dist/cli/{desktop-6OLENOOO.js → desktop-Q7NDXCON.js} +379 -72
  107. package/dist/cli/desktop-Q7NDXCON.js.map +1 -0
  108. package/dist/cli/devtools-YECO25QO.js +3719 -0
  109. package/dist/cli/devtools-YECO25QO.js.map +1 -0
  110. package/dist/cli/diff-435UTPC5.js +165 -0
  111. package/dist/cli/{diff-2VUKNGEI.js.map → diff-435UTPC5.js.map} +1 -1
  112. package/dist/cli/doctor-OT7KH75K.js +27 -0
  113. package/dist/cli/{events-APSVNROZ.js → events-XEFAD5VX.js} +6 -4
  114. package/dist/cli/{events-APSVNROZ.js.map → events-XEFAD5VX.js.map} +1 -1
  115. package/dist/cli/index.js +3233 -123
  116. package/dist/cli/index.js.map +1 -1
  117. package/dist/cli/{mcp-DCKOE5RF.js → mcp-WUL2WO75.js} +6 -4
  118. package/dist/cli/{mcp-DCKOE5RF.js.map → mcp-WUL2WO75.js.map} +1 -1
  119. package/dist/cli/{mcp-browse-D6GBP5RQ.js → mcp-browse-RR7R4XET.js} +34 -19
  120. package/dist/cli/mcp-browse-RR7R4XET.js.map +1 -0
  121. package/dist/cli/{mcp-inspect-KFGFPJ3E.js → mcp-inspect-REGLYBWT.js} +9 -8
  122. package/dist/cli/{mcp-inspect-KFGFPJ3E.js.map → mcp-inspect-REGLYBWT.js.map} +1 -1
  123. package/dist/cli/package.json +3 -0
  124. package/dist/cli/prompt-UW6EFLVR.js +16 -0
  125. package/dist/cli/{prune-sessions-LV33R47N.js → prune-sessions-3RWUBYRS.js} +4 -2
  126. package/dist/cli/{prune-sessions-LV33R47N.js.map → prune-sessions-3RWUBYRS.js.map} +1 -1
  127. package/dist/cli/{replay-WFCYX7XF.js → replay-YOURXV4C.js} +42 -30
  128. package/dist/cli/{replay-WFCYX7XF.js.map → replay-YOURXV4C.js.map} +1 -1
  129. package/dist/cli/{run-IUJYEPMT.js → run-Q6BUXV66.js} +28 -27
  130. package/dist/cli/{run-IUJYEPMT.js.map → run-Q6BUXV66.js.map} +1 -1
  131. package/dist/cli/{server-CN4QPPVJ.js → server-XGDBRWMB.js} +44 -43
  132. package/dist/cli/server-XGDBRWMB.js.map +1 -0
  133. package/dist/cli/{sessions-F5GPGTJN.js → sessions-FH7QVYSY.js} +22 -19
  134. package/dist/cli/{sessions-F5GPGTJN.js.map → sessions-FH7QVYSY.js.map} +1 -1
  135. package/dist/cli/setup-VDS6SVEP.js +618 -0
  136. package/dist/cli/setup-VDS6SVEP.js.map +1 -0
  137. package/dist/cli/stats-MQVI2XQH.js +14 -0
  138. package/dist/cli/update-6ITLPRDV.js +15 -0
  139. package/dist/cli/update-6ITLPRDV.js.map +1 -0
  140. package/dist/cli/version-DAHGZY5N.js +33 -0
  141. package/dist/cli/{version-KQUPV6T5.js.map → version-DAHGZY5N.js.map} +1 -1
  142. package/dist/index.d.ts +157 -103
  143. package/dist/index.js +597 -178
  144. package/dist/index.js.map +1 -1
  145. package/package.json +2 -1
  146. package/dist/cli/chat-G7CUW4ZI.js +0 -45
  147. package/dist/cli/chunk-26UDIXLD.js +0 -16481
  148. package/dist/cli/chunk-26UDIXLD.js.map +0 -1
  149. package/dist/cli/chunk-4YV2GBYG.js +0 -5237
  150. package/dist/cli/chunk-4YV2GBYG.js.map +0 -1
  151. package/dist/cli/chunk-5X7LZJDE.js +0 -36
  152. package/dist/cli/chunk-5X7LZJDE.js.map +0 -1
  153. package/dist/cli/chunk-7DLHHBGN.js.map +0 -1
  154. package/dist/cli/chunk-A5LSGEEK.js.map +0 -1
  155. package/dist/cli/chunk-AFFZF3MW.js +0 -36
  156. package/dist/cli/chunk-AFFZF3MW.js.map +0 -1
  157. package/dist/cli/chunk-CLAN6PVH.js.map +0 -1
  158. package/dist/cli/chunk-CPOV2O73.js +0 -39
  159. package/dist/cli/chunk-CPOV2O73.js.map +0 -1
  160. package/dist/cli/chunk-CPTZ5OHX.js +0 -18
  161. package/dist/cli/chunk-CPTZ5OHX.js.map +0 -1
  162. package/dist/cli/chunk-CZSJILQP.js +0 -854
  163. package/dist/cli/chunk-CZSJILQP.js.map +0 -1
  164. package/dist/cli/chunk-H7PHYVPM.js.map +0 -1
  165. package/dist/cli/chunk-HCC42PEI.js.map +0 -1
  166. package/dist/cli/chunk-JWCTX5S4.js +0 -46
  167. package/dist/cli/chunk-KMWKGPFZ.js.map +0 -1
  168. package/dist/cli/chunk-MRLXEMZ7.js +0 -26
  169. package/dist/cli/chunk-MRLXEMZ7.js.map +0 -1
  170. package/dist/cli/chunk-R4YTW7PR.js.map +0 -1
  171. package/dist/cli/chunk-RFX7TYVV.js.map +0 -1
  172. package/dist/cli/chunk-SZH34P45.js.map +0 -1
  173. package/dist/cli/chunk-UVRXTSK3.js.map +0 -1
  174. package/dist/cli/chunk-VLNRQMCI.js.map +0 -1
  175. package/dist/cli/chunk-WKOMCPXP.js.map +0 -1
  176. package/dist/cli/chunk-XST7BSZJ.js.map +0 -1
  177. package/dist/cli/code-YQGVLIT2.js +0 -147
  178. package/dist/cli/code-YQGVLIT2.js.map +0 -1
  179. package/dist/cli/desktop-6OLENOOO.js.map +0 -1
  180. package/dist/cli/diff-2VUKNGEI.js +0 -153
  181. package/dist/cli/doctor-JO2WNN6C.js +0 -24
  182. package/dist/cli/mcp-browse-D6GBP5RQ.js.map +0 -1
  183. package/dist/cli/prompt-PKCCLLAD.js +0 -13
  184. package/dist/cli/server-CN4QPPVJ.js.map +0 -1
  185. package/dist/cli/setup-WWMDBPSB.js +0 -516
  186. package/dist/cli/setup-WWMDBPSB.js.map +0 -1
  187. package/dist/cli/stats-5RJCATCE.js +0 -12
  188. package/dist/cli/update-GUCWB4UN.js +0 -13
  189. package/dist/cli/version-KQUPV6T5.js +0 -30
  190. /package/dist/cli/{chat-G7CUW4ZI.js.map → chat-7ES4IBNH.js.map} +0 -0
  191. /package/dist/cli/{doctor-JO2WNN6C.js.map → chunk-TUK7OWJA.js.map} +0 -0
  192. /package/dist/cli/{prompt-PKCCLLAD.js.map → doctor-OT7KH75K.js.map} +0 -0
  193. /package/dist/cli/{stats-5RJCATCE.js.map → prompt-UW6EFLVR.js.map} +0 -0
  194. /package/dist/cli/{update-GUCWB4UN.js.map → stats-MQVI2XQH.js.map} +0 -0
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+ import {
4
+ formatMcpLifecycleEvent,
5
+ formatMcpSlowToast
6
+ } from "./chunk-H6PS7IUE.js";
7
+ import {
8
+ buildTransportFromSpec,
9
+ preflightStdioSpec
10
+ } from "./chunk-PQXPXJBJ.js";
11
+ import {
12
+ bridgeMcpTools
13
+ } from "./chunk-2R4QCDOZ.js";
14
+ import {
15
+ McpClient,
16
+ inspectMcpServer,
17
+ parseMcpSpec
18
+ } from "./chunk-6AK4EY3D.js";
19
+ import {
20
+ t
21
+ } from "./chunk-RE4RAVFF.js";
22
+ import {
23
+ mcpEnvFor,
24
+ readConfig
25
+ } from "./chunk-XPDVG52A.js";
26
+
27
+ // src/mcp/summary.ts
28
+ function buildMcpServerSummary(opts) {
29
+ return {
30
+ label: opts.label,
31
+ spec: opts.spec,
32
+ toolCount: opts.toolCount,
33
+ report: opts.report,
34
+ host: opts.host,
35
+ bridgeEnv: opts.bridgeEnv,
36
+ readResource(uri) {
37
+ return opts.host.client.readResource(uri);
38
+ },
39
+ getPrompt(name, args) {
40
+ return args !== void 0 ? opts.host.client.getPrompt(name, args) : opts.host.client.getPrompt(name);
41
+ }
42
+ };
43
+ }
44
+
45
+ // src/cli/commands/mcp-runtime.ts
46
+ var stderrLifecycleSink = (n) => {
47
+ if (n.kind === "slow") {
48
+ process.stderr.write(
49
+ `${formatMcpSlowToast({ name: n.serverName, p95Ms: n.p95Ms, sampleSize: n.sampleSize })}
50
+ `
51
+ );
52
+ return;
53
+ }
54
+ if (n.kind === "failed") {
55
+ process.stderr.write(
56
+ `${formatMcpLifecycleEvent({ state: "failed", name: n.name, reason: n.reason })}
57
+ \u2192 ${t("mcpLifecycle.failedSetupHint")}
58
+ `
59
+ );
60
+ return;
61
+ }
62
+ if (n.kind === "connected") {
63
+ process.stderr.write(
64
+ `${formatMcpLifecycleEvent({
65
+ state: "connected",
66
+ name: n.name,
67
+ tools: n.tools,
68
+ resources: n.resources,
69
+ prompts: n.prompts,
70
+ ms: n.ms
71
+ })}
72
+ `
73
+ );
74
+ return;
75
+ }
76
+ process.stderr.write(`${formatMcpLifecycleEvent({ state: n.kind, name: n.name })}
77
+ `);
78
+ };
79
+ function createMcpRuntime(ctx) {
80
+ const records = /* @__PURE__ */ new Map();
81
+ const insertionOrder = [];
82
+ let sink = stderrLifecycleSink;
83
+ async function addSpec(raw, loop) {
84
+ if (records.has(raw)) {
85
+ return { ok: true, summary: records.get(raw).summary };
86
+ }
87
+ const tools = ctx.getTools();
88
+ if (!tools) return { ok: false, reason: "no tool registry available" };
89
+ const disabledNames = new Set(readConfig().mcpDisabled ?? []);
90
+ let label = "anon";
91
+ let mcp;
92
+ let resolveReady;
93
+ let rejectReady;
94
+ const ready = new Promise((resolve, reject) => {
95
+ resolveReady = resolve;
96
+ rejectReady = reject;
97
+ });
98
+ ready.catch(() => void 0);
99
+ try {
100
+ const spec = parseMcpSpec(raw);
101
+ label = spec.name ?? "anon";
102
+ if (spec.name && disabledNames.has(spec.name)) {
103
+ sink({ kind: "disabled", name: label });
104
+ rejectReady(new Error(`MCP server "${label}" is disabled`));
105
+ return { ok: false, reason: "disabled by user" };
106
+ }
107
+ sink({ kind: "handshake", name: label });
108
+ const t0 = Date.now();
109
+ const namePrefix = spec.name ? `${spec.name}_` : ctx.getRequestedCount() === 1 && ctx.getMcpPrefix() ? ctx.getMcpPrefix() : "";
110
+ if (spec.transport === "stdio") preflightStdioSpec(spec);
111
+ const transport = buildTransportFromSpec(spec, { env: mcpEnvFor(spec.name, readConfig()) });
112
+ mcp = new McpClient({ transport });
113
+ await mcp.initialize();
114
+ const host = { client: mcp };
115
+ const bridge = await bridgeMcpTools(mcp, {
116
+ registry: tools,
117
+ namePrefix,
118
+ serverName: label,
119
+ host,
120
+ ready,
121
+ onProgress: (info) => ctx.progressSink.current?.(info),
122
+ onSlow: (info) => sink({
123
+ kind: "slow",
124
+ serverName: info.serverName,
125
+ p95Ms: info.p95Ms,
126
+ sampleSize: info.sampleSize
127
+ })
128
+ });
129
+ let report;
130
+ try {
131
+ report = await inspectMcpServer(mcp);
132
+ } catch {
133
+ report = {
134
+ protocolVersion: mcp.protocolVersion,
135
+ serverInfo: mcp.serverInfo,
136
+ capabilities: mcp.serverCapabilities ?? {},
137
+ tools: { supported: true, items: [] },
138
+ resources: { supported: false, reason: "inspect failed" },
139
+ prompts: { supported: false, reason: "inspect failed" },
140
+ elapsedMs: 0
141
+ };
142
+ }
143
+ const ms = Date.now() - t0;
144
+ const resourceCount = report.resources.supported ? report.resources.items.length : 0;
145
+ const promptCount = report.prompts.supported ? report.prompts.items.length : 0;
146
+ sink({
147
+ kind: "connected",
148
+ name: label,
149
+ tools: bridge.registeredNames.length,
150
+ resources: resourceCount,
151
+ prompts: promptCount,
152
+ ms
153
+ });
154
+ resolveReady();
155
+ const summary = buildMcpServerSummary({
156
+ label,
157
+ spec: raw,
158
+ toolCount: bridge.registeredNames.length,
159
+ report,
160
+ host,
161
+ bridgeEnv: bridge.env
162
+ });
163
+ const allSpecs = tools.specs();
164
+ const registeredSpecs = allSpecs.filter(
165
+ (s) => bridge.registeredNames.includes(s.function.name)
166
+ );
167
+ records.set(raw, {
168
+ spec: raw,
169
+ client: mcp,
170
+ summary,
171
+ registeredNames: bridge.registeredNames,
172
+ registeredSpecs
173
+ });
174
+ insertionOrder.push(raw);
175
+ if (loop) for (const s of registeredSpecs) loop.prefix.addTool(s);
176
+ return { ok: true, summary };
177
+ } catch (err) {
178
+ await mcp?.close().catch(() => void 0);
179
+ const reason = err.message;
180
+ sink({ kind: "failed", name: label, reason });
181
+ rejectReady(new Error(`MCP server "${label}" failed to start: ${reason}`));
182
+ return { ok: false, reason };
183
+ }
184
+ }
185
+ async function removeSpec(raw, loop) {
186
+ const record = records.get(raw);
187
+ if (!record) return false;
188
+ await record.client.close().catch(() => void 0);
189
+ const tools = ctx.getTools();
190
+ for (const name of record.registeredNames) {
191
+ tools?.unregister(name);
192
+ loop?.prefix.removeTool(name);
193
+ }
194
+ records.delete(raw);
195
+ const idx = insertionOrder.indexOf(raw);
196
+ if (idx >= 0) insertionOrder.splice(idx, 1);
197
+ return true;
198
+ }
199
+ async function reloadFromConfig(loop) {
200
+ const desired = readConfig().mcp ?? [];
201
+ const desiredSet = new Set(desired);
202
+ const currentSet = new Set(records.keys());
203
+ const added = [];
204
+ const removed = [];
205
+ const failed = [];
206
+ for (const spec of [...currentSet]) {
207
+ if (!desiredSet.has(spec)) {
208
+ await removeSpec(spec, loop);
209
+ removed.push(spec);
210
+ }
211
+ }
212
+ for (const spec of desired) {
213
+ if (currentSet.has(spec)) continue;
214
+ const result = await addSpec(spec, loop);
215
+ if (result.ok) added.push(spec);
216
+ else failed.push({ spec, reason: result.reason });
217
+ }
218
+ return { added, removed, failed, summaries: summaries() };
219
+ }
220
+ function specs() {
221
+ return [...insertionOrder];
222
+ }
223
+ function summaries() {
224
+ return insertionOrder.map((s) => records.get(s)?.summary).filter((s) => Boolean(s));
225
+ }
226
+ async function closeAll() {
227
+ for (const r of records.values()) await r.client.close().catch(() => void 0);
228
+ records.clear();
229
+ insertionOrder.length = 0;
230
+ }
231
+ function setLifecycleSink(s) {
232
+ sink = s;
233
+ }
234
+ return {
235
+ size: () => records.size,
236
+ specs,
237
+ summaries,
238
+ addSpec,
239
+ removeSpec,
240
+ reloadFromConfig,
241
+ closeAll,
242
+ setLifecycleSink
243
+ };
244
+ }
245
+
246
+ export {
247
+ createMcpRuntime
248
+ };
249
+ //# sourceMappingURL=chunk-3Z6IBU3D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/mcp/summary.ts","../../src/cli/commands/mcp-runtime.ts"],"sourcesContent":["import type { InspectionReport } from \"./inspect.js\";\nimport type { BridgeEnv, McpClientHost } from \"./registry.js\";\nimport type { GetPromptResult, ReadResourceResult } from \"./types.js\";\n\nexport interface McpServerSummary {\n label: string;\n spec: string;\n toolCount: number;\n report: InspectionReport;\n host: McpClientHost;\n bridgeEnv: BridgeEnv;\n readResource(uri: string): Promise<ReadResourceResult>;\n getPrompt(name: string, args?: Record<string, string>): Promise<GetPromptResult>;\n}\n\nexport function buildMcpServerSummary(opts: {\n label: string;\n spec: string;\n toolCount: number;\n report: InspectionReport;\n host: McpClientHost;\n bridgeEnv: BridgeEnv;\n}): McpServerSummary {\n return {\n label: opts.label,\n spec: opts.spec,\n toolCount: opts.toolCount,\n report: opts.report,\n host: opts.host,\n bridgeEnv: opts.bridgeEnv,\n readResource(uri) {\n return opts.host.client.readResource(uri);\n },\n getPrompt(name, args) {\n return args !== undefined\n ? opts.host.client.getPrompt(name, args)\n : opts.host.client.getPrompt(name);\n },\n };\n}\n","import { mcpEnvFor, readConfig } from \"../../config.js\";\nimport { t } from \"../../i18n/index.js\";\nimport type { CacheFirstLoop } from \"../../loop.js\";\nimport { McpClient } from \"../../mcp/client.js\";\nimport { type InspectionReport, inspectMcpServer } from \"../../mcp/inspect.js\";\nimport { preflightStdioSpec } from \"../../mcp/preflight.js\";\nimport { type McpClientHost, bridgeMcpTools } from \"../../mcp/registry.js\";\nimport { parseMcpSpec } from \"../../mcp/spec.js\";\nimport { buildMcpServerSummary } from \"../../mcp/summary.js\";\nimport { buildTransportFromSpec } from \"../../mcp/transport-from-spec.js\";\nimport type { ToolRegistry } from \"../../tools.js\";\nimport type { ToolSpec } from \"../../types.js\";\nimport { formatMcpLifecycleEvent } from \"../ui/mcp-lifecycle.js\";\nimport { formatMcpSlowToast } from \"../ui/mcp-toast.js\";\nimport type { McpServerSummary } from \"../ui/slash.js\";\n\nexport interface ProgressInfo {\n toolName: string;\n progress: number;\n total?: number;\n message?: string;\n}\n\ninterface SpecRecord {\n spec: string;\n client: McpClient;\n summary: McpServerSummary;\n /** Names of bridged tools — used for hot-unbridge. */\n registeredNames: string[];\n /** ToolSpec snapshots captured AFTER bridge — handed to loop.prefix.addTool on hot-add. */\n registeredSpecs: ToolSpec[];\n}\n\nexport interface RuntimeContext {\n getTools: () => ToolRegistry | undefined;\n getMcpPrefix: () => string | undefined;\n getRequestedCount: () => number;\n progressSink: { current: ((info: ProgressInfo) => void) | null };\n}\n\nexport type McpLifecycleNotice =\n | { kind: \"handshake\"; name: string }\n | {\n kind: \"connected\";\n name: string;\n tools: number;\n resources: number;\n prompts: number;\n ms: number;\n }\n | { kind: \"disabled\"; name: string }\n | { kind: \"failed\"; name: string; reason: string }\n | { kind: \"slow\"; serverName: string; p95Ms: number; sampleSize: number };\n\nexport type McpLifecycleSink = (notice: McpLifecycleNotice) => void;\n\nexport const stderrLifecycleSink: McpLifecycleSink = (n) => {\n if (n.kind === \"slow\") {\n process.stderr.write(\n `${formatMcpSlowToast({ name: n.serverName, p95Ms: n.p95Ms, sampleSize: n.sampleSize })}\\n`,\n );\n return;\n }\n if (n.kind === \"failed\") {\n process.stderr.write(\n `${formatMcpLifecycleEvent({ state: \"failed\", name: n.name, reason: n.reason })}\\n → ${t(\"mcpLifecycle.failedSetupHint\")}\\n`,\n );\n return;\n }\n if (n.kind === \"connected\") {\n process.stderr.write(\n `${formatMcpLifecycleEvent({\n state: \"connected\",\n name: n.name,\n tools: n.tools,\n resources: n.resources,\n prompts: n.prompts,\n ms: n.ms,\n })}\\n`,\n );\n return;\n }\n process.stderr.write(`${formatMcpLifecycleEvent({ state: n.kind, name: n.name })}\\n`);\n};\n\nexport interface McpRuntime {\n size(): number;\n specs(): string[];\n summaries(): McpServerSummary[];\n addSpec(\n raw: string,\n loop?: CacheFirstLoop,\n ): Promise<{ ok: true; summary: McpServerSummary } | { ok: false; reason: string }>;\n removeSpec(raw: string, loop?: CacheFirstLoop): Promise<boolean>;\n reloadFromConfig(loop?: CacheFirstLoop): Promise<{\n added: string[];\n removed: string[];\n failed: Array<{ spec: string; reason: string }>;\n summaries: McpServerSummary[];\n }>;\n closeAll(): Promise<void>;\n /** Replace the sink that lifecycle events flow through — App.tsx swaps this in on mount so toasts land in the alt-screen UI instead of corrupting it via stderr. */\n setLifecycleSink(sink: McpLifecycleSink): void;\n}\n\nexport function createMcpRuntime(ctx: RuntimeContext): McpRuntime {\n const records = new Map<string, SpecRecord>();\n const insertionOrder: string[] = [];\n let sink: McpLifecycleSink = stderrLifecycleSink;\n\n async function addSpec(\n raw: string,\n loop?: CacheFirstLoop,\n ): Promise<{ ok: true; summary: McpServerSummary } | { ok: false; reason: string }> {\n if (records.has(raw)) {\n return { ok: true, summary: records.get(raw)!.summary };\n }\n const tools = ctx.getTools();\n if (!tools) return { ok: false, reason: \"no tool registry available\" };\n const disabledNames = new Set(readConfig().mcpDisabled ?? []);\n let label = \"anon\";\n let mcp: McpClient | undefined;\n // Per-server readiness gate — tool dispatches via the bridge await\n // this before calling into `live.callTool`. Resolved on `connected`,\n // rejected on `failed`, so a tool invoked mid-handshake waits\n // (capped by `bridgeMcpTools`'s `readyTimeoutMs`) instead of\n // surfacing a transport error.\n let resolveReady!: () => void;\n let rejectReady!: (err: Error) => void;\n const ready = new Promise<void>((resolve, reject) => {\n resolveReady = resolve;\n rejectReady = reject;\n });\n // Avoid unhandledRejection if no consumer awaits `ready` yet.\n ready.catch(() => undefined);\n try {\n const spec = parseMcpSpec(raw);\n label = spec.name ?? \"anon\";\n if (spec.name && disabledNames.has(spec.name)) {\n sink({ kind: \"disabled\", name: label });\n rejectReady(new Error(`MCP server \"${label}\" is disabled`));\n return { ok: false, reason: \"disabled by user\" };\n }\n sink({ kind: \"handshake\", name: label });\n const t0 = Date.now();\n const namePrefix = spec.name\n ? `${spec.name}_`\n : ctx.getRequestedCount() === 1 && ctx.getMcpPrefix()\n ? (ctx.getMcpPrefix() as string)\n : \"\";\n if (spec.transport === \"stdio\") preflightStdioSpec(spec);\n const transport = buildTransportFromSpec(spec, { env: mcpEnvFor(spec.name, readConfig()) });\n mcp = new McpClient({ transport });\n await mcp.initialize();\n const host: McpClientHost = { client: mcp };\n const bridge = await bridgeMcpTools(mcp, {\n registry: tools,\n namePrefix,\n serverName: label,\n host,\n ready,\n onProgress: (info) => ctx.progressSink.current?.(info),\n onSlow: (info) =>\n sink({\n kind: \"slow\",\n serverName: info.serverName,\n p95Ms: info.p95Ms,\n sampleSize: info.sampleSize,\n }),\n });\n let report: InspectionReport;\n try {\n report = await inspectMcpServer(mcp);\n } catch {\n report = {\n protocolVersion: mcp.protocolVersion,\n serverInfo: mcp.serverInfo,\n capabilities: mcp.serverCapabilities ?? {},\n tools: { supported: true, items: [] },\n resources: { supported: false, reason: \"inspect failed\" },\n prompts: { supported: false, reason: \"inspect failed\" },\n elapsedMs: 0,\n };\n }\n const ms = Date.now() - t0;\n const resourceCount = report.resources.supported ? report.resources.items.length : 0;\n const promptCount = report.prompts.supported ? report.prompts.items.length : 0;\n sink({\n kind: \"connected\",\n name: label,\n tools: bridge.registeredNames.length,\n resources: resourceCount,\n prompts: promptCount,\n ms,\n });\n resolveReady();\n const summary = buildMcpServerSummary({\n label,\n spec: raw,\n toolCount: bridge.registeredNames.length,\n report,\n host,\n bridgeEnv: bridge.env,\n });\n // Snapshot tool specs AFTER bridge so hot-add can replay them into loop.prefix.\n const allSpecs = tools.specs();\n const registeredSpecs = allSpecs.filter((s) =>\n bridge.registeredNames.includes(s.function.name),\n );\n records.set(raw, {\n spec: raw,\n client: mcp,\n summary,\n registeredNames: bridge.registeredNames,\n registeredSpecs,\n });\n insertionOrder.push(raw);\n // Hot-add: shift the prefix so the live loop sees the new tools\n // on the very next turn. Each addTool is one cache-miss turn.\n if (loop) for (const s of registeredSpecs) loop.prefix.addTool(s);\n return { ok: true, summary };\n } catch (err) {\n await mcp?.close().catch(() => undefined);\n const reason = (err as Error).message;\n sink({ kind: \"failed\", name: label, reason });\n rejectReady(new Error(`MCP server \"${label}\" failed to start: ${reason}`));\n return { ok: false, reason };\n }\n }\n\n async function removeSpec(raw: string, loop?: CacheFirstLoop): Promise<boolean> {\n const record = records.get(raw);\n if (!record) return false;\n await record.client.close().catch(() => undefined);\n const tools = ctx.getTools();\n for (const name of record.registeredNames) {\n tools?.unregister(name);\n loop?.prefix.removeTool(name);\n }\n records.delete(raw);\n const idx = insertionOrder.indexOf(raw);\n if (idx >= 0) insertionOrder.splice(idx, 1);\n return true;\n }\n\n async function reloadFromConfig(loop?: CacheFirstLoop): Promise<{\n added: string[];\n removed: string[];\n failed: Array<{ spec: string; reason: string }>;\n summaries: McpServerSummary[];\n }> {\n const desired = readConfig().mcp ?? [];\n const desiredSet = new Set(desired);\n const currentSet = new Set(records.keys());\n const added: string[] = [];\n const removed: string[] = [];\n const failed: Array<{ spec: string; reason: string }> = [];\n\n for (const spec of [...currentSet]) {\n if (!desiredSet.has(spec)) {\n await removeSpec(spec, loop);\n removed.push(spec);\n }\n }\n for (const spec of desired) {\n if (currentSet.has(spec)) continue;\n const result = await addSpec(spec, loop);\n if (result.ok) added.push(spec);\n else failed.push({ spec, reason: result.reason });\n }\n return { added, removed, failed, summaries: summaries() };\n }\n\n function specs(): string[] {\n return [...insertionOrder];\n }\n function summaries(): McpServerSummary[] {\n return insertionOrder\n .map((s) => records.get(s)?.summary)\n .filter((s): s is McpServerSummary => Boolean(s));\n }\n async function closeAll(): Promise<void> {\n for (const r of records.values()) await r.client.close().catch(() => undefined);\n records.clear();\n insertionOrder.length = 0;\n }\n function setLifecycleSink(s: McpLifecycleSink): void {\n sink = s;\n }\n return {\n size: () => records.size,\n specs,\n summaries,\n addSpec,\n removeSpec,\n reloadFromConfig,\n closeAll,\n setLifecycleSink,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
2
3
  import {
3
4
  SkillStore
4
- } from "./chunk-7DLHHBGN.js";
5
+ } from "./chunk-2K65GZBT.js";
5
6
 
6
7
  // src/core/event-redaction.ts
7
8
  var SECRET_KEY_RE = /(secret|token|password|passphrase|api[-_]?key|authorization|cookie|credential|passwd|pwd)/i;
@@ -322,6 +323,9 @@ function autoResolveVerdict(req, editMode) {
322
323
  if (req.kind === "plan_checkpoint" && shouldAutoResolveCheckpoint(editMode)) {
323
324
  return { type: "continue" };
324
325
  }
326
+ if (req.kind === "path_access" && editMode === "yolo") {
327
+ return { type: "run_once" };
328
+ }
325
329
  return null;
326
330
  }
327
331
 
@@ -396,18 +400,21 @@ function registerSkillTools(registry, opts = {}) {
396
400
  const argsBlock = rawArgs ? `
397
401
 
398
402
  Arguments: ${rawArgs}` : "";
399
- return `${header}
403
+ const inner = `${header}
400
404
 
401
405
  ${skill.body}${argsBlock}`;
406
+ return `<skill-pin name=${JSON.stringify(skill.name)}>
407
+ ${inner}
408
+ </skill-pin>`;
402
409
  }
403
410
  });
404
411
  return registry;
405
412
  }
406
413
 
407
414
  export {
415
+ registerSkillTools,
408
416
  Eventizer,
409
417
  shouldAutoResolveCheckpoint,
410
- autoResolveVerdict,
411
- registerSkillTools
418
+ autoResolveVerdict
412
419
  };
413
- //# sourceMappingURL=chunk-VLNRQMCI.js.map
420
+ //# sourceMappingURL=chunk-45U62RI3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/event-redaction.ts","../../src/core/eventize.ts","../../src/core/pause-policy.ts","../../src/tools/skills.ts"],"sourcesContent":["const SECRET_KEY_RE =\n /(secret|token|password|passphrase|api[-_]?key|authorization|cookie|credential|passwd|pwd)/i;\n\nexport function redactEventValue<T>(value: T): T {\n return redactUnknown(value, null) as T;\n}\n\nfunction redactUnknown(value: unknown, key: string | null): unknown {\n if (Array.isArray(value)) return value.map((item) => redactUnknown(item, null));\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [childKey, childValue] of Object.entries(value)) {\n out[childKey] = redactUnknown(childValue, childKey);\n }\n return out;\n }\n if (typeof value === \"string\") {\n if ((key && SECRET_KEY_RE.test(key)) || /^Bearer\\s+/i.test(value)) return \"[redacted]\";\n }\n return value;\n}\n","import type { LoopEvent } from \"../loop.js\";\nimport type { ChatMessage, RawUsage, ToolCall } from \"../types.js\";\nimport { redactEventValue } from \"./event-redaction.js\";\nimport type {\n Event,\n ErrorEvent as KernelErrorEvent,\n ModelDeltaEvent,\n ModelFinalEvent,\n ModelTurnStartedEvent,\n SessionCompactedEvent,\n SessionOpenedEvent,\n SlashInvokedEvent,\n StatusEvent,\n ToolCallEvent,\n ToolConfirmAllowEvent,\n ToolConfirmAlwaysAllowEvent,\n ToolConfirmDenyEvent,\n ToolDispatchedEvent,\n ToolIntentEvent,\n ToolPreparingEvent,\n ToolResultEvent,\n UserMessageEvent,\n} from \"./events.js\";\n\nexport interface EventizeContext {\n model: string;\n prefixHash: string;\n reasoningEffort: \"high\" | \"max\";\n}\n\nexport class Eventizer {\n private nextId = 0;\n private lastTurn = -1;\n private nextToolSeq = 0;\n /** Tool calls announced via tool_call_delta but not yet dispatched. FIFO upgraded by tool_start. */\n private preparingCallIds: string[] = [];\n /** Tool calls dispatched but not yet finished. FIFO popped by tool result. */\n private inflightCallIds: string[] = [];\n /** Per-turn dedupe so each toolCallIndex emits exactly one tool.preparing. */\n private announcedToolIdx = new Set<string>();\n\n consume(ev: LoopEvent, ctx: EventizeContext): Event[] {\n const out: Event[] = [];\n if (ev.turn !== this.lastTurn) {\n this.lastTurn = ev.turn;\n this.announcedToolIdx.clear();\n out.push(this.turnStartedEvent(ev.turn, ctx));\n }\n switch (ev.role) {\n case \"assistant_delta\":\n if (ev.content) out.push(this.deltaEvent(ev.turn, \"content\", ev.content));\n if (ev.reasoningDelta) out.push(this.deltaEvent(ev.turn, \"reasoning\", ev.reasoningDelta));\n break;\n case \"tool_call_delta\": {\n const idx = ev.toolCallIndex;\n const name = ev.toolName;\n if (idx === undefined || !name) break;\n const key = `${ev.turn}:${idx}`;\n if (this.announcedToolIdx.has(key)) break;\n this.announcedToolIdx.add(key);\n const callId = `tc-${++this.nextToolSeq}`;\n this.preparingCallIds.push(callId);\n out.push(this.toolPreparingEvent(ev.turn, callId, name));\n break;\n }\n case \"assistant_final\":\n out.push(this.finalEvent(ev));\n break;\n case \"tool_start\": {\n const callId = this.preparingCallIds.shift() ?? `tc-${++this.nextToolSeq}`;\n this.inflightCallIds.push(callId);\n out.push(this.toolIntentEvent(ev.turn, callId, ev.toolName ?? \"\", ev.toolArgs ?? \"\"));\n out.push(this.toolDispatchedEvent(ev.turn, callId));\n break;\n }\n case \"tool\": {\n const callId = this.inflightCallIds.shift() ?? `tc-orphan-${++this.nextToolSeq}`;\n const ok = !looksLikeToolError(ev.content, ev.toolName);\n out.push(this.toolResultEvent(ev.turn, callId, ok, ev.content, 0));\n break;\n }\n case \"warning\":\n out.push(this.classifyWarning(ev));\n break;\n case \"error\":\n out.push(this.errorEvent(ev.turn, ev.error ?? ev.content, false));\n break;\n case \"status\":\n out.push(this.statusEvent(ev.turn, ev.content));\n break;\n // `done` / `branch_*` intentionally drop — no kernel-level event.\n default:\n break;\n }\n return out;\n }\n\n emitUserMessage(turn: number, text: string): UserMessageEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"user.message\",\n text,\n };\n }\n\n emitSlashInvoked(turn: number, name: string, args: string): SlashInvokedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"slash.invoked\",\n name,\n args,\n };\n }\n\n emitSessionOpened(turn: number, name: string, resumedFromTurn: number): SessionOpenedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"session.opened\",\n name,\n resumedFromTurn,\n };\n }\n\n emitSessionCompacted(\n turn: number,\n before: number,\n after: number,\n reason: \"user\" | \"auto-context-pressure\",\n replacementMessages: ReadonlyArray<ChatMessage>,\n ): SessionCompactedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"session.compacted\",\n beforeMessages: before,\n afterMessages: after,\n reason,\n replacementMessages,\n };\n }\n\n emitToolCall(turn: number, name: string, args: Record<string, unknown>): ToolCallEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.call\",\n name,\n args: redactEventValue(args),\n };\n }\n\n emitToolConfirmAllow(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n ): ToolConfirmAllowEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.allow\",\n kind,\n payload: redactEventValue(payload),\n };\n }\n\n emitToolConfirmDeny(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n denyContext?: string,\n ): ToolConfirmDenyEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.deny\",\n kind,\n payload: redactEventValue(payload),\n denyContext,\n };\n }\n\n emitToolConfirmAlwaysAllow(\n turn: number,\n kind: \"run_command\" | \"run_background\",\n payload: { command: string },\n prefix: string,\n ): ToolConfirmAlwaysAllowEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.confirm.always_allow\",\n kind,\n payload: redactEventValue(payload),\n prefix,\n };\n }\n\n private turnStartedEvent(turn: number, ctx: EventizeContext): ModelTurnStartedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"model.turn.started\",\n model: ctx.model,\n reasoningEffort: ctx.reasoningEffort,\n prefixHash: ctx.prefixHash,\n };\n }\n\n private deltaEvent(\n turn: number,\n channel: \"content\" | \"reasoning\" | \"tool_args\",\n text: string,\n ): ModelDeltaEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"model.delta\",\n channel,\n text,\n };\n }\n\n private finalEvent(ev: LoopEvent): ModelFinalEvent {\n const usage: RawUsage = ev.stats\n ? {\n prompt_tokens: ev.stats.usage.promptTokens,\n completion_tokens: ev.stats.usage.completionTokens,\n total_tokens: ev.stats.usage.totalTokens,\n prompt_cache_hit_tokens: ev.stats.usage.promptCacheHitTokens,\n prompt_cache_miss_tokens: ev.stats.usage.promptCacheMissTokens,\n }\n : {};\n const costUsd = ev.stats?.cost ?? 0;\n const out: ModelFinalEvent = {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: \"model.final\",\n content: ev.content,\n // toolCalls land later via tool_start → tool.intent — not in this event.\n toolCalls: [] as ReadonlyArray<ToolCall>,\n usage,\n costUsd,\n };\n if (ev.forcedSummary) out.forcedSummary = true;\n return out;\n }\n\n private toolPreparingEvent(turn: number, callId: string, name: string): ToolPreparingEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.preparing\",\n callId,\n name,\n };\n }\n\n private toolIntentEvent(\n turn: number,\n callId: string,\n name: string,\n args: string,\n ): ToolIntentEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.intent\",\n callId,\n name,\n args,\n };\n }\n\n private toolDispatchedEvent(turn: number, callId: string): ToolDispatchedEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.dispatched\",\n callId,\n };\n }\n\n private toolResultEvent(\n turn: number,\n callId: string,\n ok: boolean,\n output: string,\n durationMs: number,\n ): ToolResultEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"tool.result\",\n callId,\n ok,\n output,\n durationMs,\n };\n }\n\n private statusEvent(turn: number, text: string): StatusEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"status\",\n text,\n };\n }\n\n private errorEvent(turn: number, message: string, recoverable: boolean): KernelErrorEvent {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn,\n type: \"error\",\n message,\n recoverable,\n };\n }\n\n /** Pattern-match warning text since LoopEvent doesn't carry a typed kind. */\n private classifyWarning(ev: LoopEvent): Event {\n const c = ev.content;\n if (/\\bauto-escalating to\\b|\\barmed\\b.*pro|NEEDS_PRO/.test(c)) {\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: \"policy.escalated\",\n fromModel: \"\",\n toModel: \"\",\n reason: c.includes(\"armed\") ? \"user-request\" : \"self-report\",\n };\n }\n if (/budget\\b.*\\$|\\$\\d.*\\/\\s*\\$\\d/.test(c)) {\n const blocked = /blocked|exceeded|refus/i.test(c);\n return {\n id: ++this.nextId,\n ts: new Date().toISOString(),\n turn: ev.turn,\n type: blocked ? \"policy.budget.blocked\" : \"policy.budget.warning\",\n spentUsd: 0,\n capUsd: 0,\n };\n }\n return this.errorEvent(ev.turn, c, true);\n }\n}\n\nfunction looksLikeToolError(content: string, _toolName: string | undefined): boolean {\n if (!content) return false;\n if (content.startsWith(\"ERROR:\")) return true;\n if (content.startsWith(\"[hook block]\")) return true;\n if (/^\\{\"error\"\\s*:/.test(content)) return true;\n if (/\\bConfirmationError:|\\bNeedsConfirmationError\\b/.test(content)) return true;\n return false;\n}\n","/** Shared editMode → auto-resolve rules so CLI TUI + Tauri desktop don't drift. */\n\nimport type { EditMode } from \"../config.js\";\nimport type { PauseRequest } from \"./pause-gate.js\";\n\n/** Mirrors shell.ts's allowAll bypass: only review still pauses on checkpoints. */\nexport function shouldAutoResolveCheckpoint(editMode: EditMode): boolean {\n return editMode === \"auto\" || editMode === \"yolo\";\n}\n\n/** null = surface to user; non-null = resolve gate immediately with this verdict. */\nexport function autoResolveVerdict(req: PauseRequest, editMode: EditMode): unknown | null {\n if (req.kind === \"plan_checkpoint\" && shouldAutoResolveCheckpoint(editMode)) {\n return { type: \"continue\" };\n }\n // yolo mirrors shell.ts's allowAll bypass — outside-sandbox reads/writes pass\n // through too. Stays \"run_once\" rather than \"always_allow\" so the YOLO session\n // doesn't pollute the on-disk allowlist with every transient path it touched.\n if (req.kind === \"path_access\" && editMode === \"yolo\") {\n return { type: \"run_once\" };\n }\n return null;\n}\n","/** runAs: inline appends the body to the parent log; subagent spawns an isolated child loop and only returns the final answer. */\n\nimport { type Skill, SkillStore } from \"../skills.js\";\nimport type { ToolRegistry } from \"../tools.js\";\n\n/** Returns serialized tool-result string — dispatch path is pure pass-through. */\nexport type SubagentRunner = (skill: Skill, task: string, signal?: AbortSignal) => Promise<string>;\n\nexport interface SkillToolsOptions {\n /** Override `$HOME` — tests set this to a tmpdir. */\n homeDir?: string;\n projectRoot?: string;\n /** When omitted, subagent skills error rather than silently falling back to inline (loses isolation). */\n subagentRunner?: SubagentRunner;\n /** Hide built-in skills (test-only knob; production callers leave off). */\n disableBuiltins?: boolean;\n}\n\nexport function registerSkillTools(\n registry: ToolRegistry,\n opts: SkillToolsOptions = {},\n): ToolRegistry {\n const store = new SkillStore({\n homeDir: opts.homeDir,\n projectRoot: opts.projectRoot,\n disableBuiltins: opts.disableBuiltins,\n });\n const subagentRunner = opts.subagentRunner;\n\n registry.register({\n name: \"run_skill\",\n description:\n \"Invoke a playbook from the Skills index pinned in the system prompt. Each entry is a self-contained instruction block. Pass `name` as the BARE skill identifier (e.g. 'explore'), NOT the `[🧬 subagent]` tag that appears after it in the index. Entries tagged `[🧬 subagent]` spawn an isolated subagent — only the final distilled answer comes back, the model's tool calls + reasoning during the run never enter your context. Plain skills are inlined: the body becomes a tool result you read and follow. For subagent skills, supply 'arguments' describing the concrete task — they'll be the only context the subagent has.\",\n readOnly: true,\n parallelSafe: true,\n parameters: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Skill identifier as it appears in the pinned Skills index (e.g. 'explore', 'review', 'security-review'). Case-sensitive.\",\n },\n arguments: {\n type: \"string\",\n description:\n \"Free-form arguments the skill should act on. For inline skills: appended to the body as an 'Arguments:' line; the skill's own instructions decide how to consume them. For `[🧬 subagent]` skills: REQUIRED — becomes the entire task description the subagent receives, since it has no other context.\",\n },\n },\n required: [\"name\"],\n },\n fn: async (args: { name?: unknown; arguments?: unknown }, ctx) => {\n const raw = typeof args.name === \"string\" ? args.name.trim() : \"\";\n if (!raw) {\n return JSON.stringify({ error: \"run_skill requires a 'name' argument\" });\n }\n // Defensive: The Skills index writes entries like\n // `explore [🧬 subagent]`, and models sometimes copy the\n // decoration verbatim into the `name` argument instead of just\n // the identifier. Rather than reject those calls:\n // 1. Drop any `[...]` bracketed tag (possibly containing\n // emoji + \"subagent\" label).\n // 2. Find the first whitespace-delimited token whose first\n // char is alphanumeric — that's the skill identifier,\n // whether the tag came before or after the name.\n const stripped = raw.replace(/\\[[^\\]]*\\]/g, \" \").trim();\n const tokens = stripped.split(/\\s+/).filter(Boolean);\n const name = tokens.find((t) => /^[a-zA-Z0-9]/.test(t)) ?? \"\";\n if (!name) {\n return JSON.stringify({\n error: \"run_skill requires a 'name' argument\",\n hint: `'${raw}' is just a marker/tag, not a skill name`,\n });\n }\n const skill = store.read(name);\n if (!skill) {\n const available = store\n .list()\n .map((s) => s.name)\n .join(\", \");\n return JSON.stringify({\n error: `unknown skill: ${JSON.stringify(name)}`,\n available: available || \"(none — user has not defined any skills)\",\n });\n }\n const rawArgs = typeof args.arguments === \"string\" ? args.arguments.trim() : \"\";\n\n if (skill.runAs === \"subagent\") {\n if (!subagentRunner) {\n return JSON.stringify({\n error: `run_skill: skill ${JSON.stringify(name)} is marked runAs=subagent but no subagent runner is configured for this session. Skill authors who need isolation should run inside reasonix code (or a library setup that passes subagentRunner to registerSkillTools).`,\n });\n }\n if (!rawArgs) {\n return JSON.stringify({\n error: `run_skill: skill ${JSON.stringify(name)} is a subagent and requires 'arguments' — the subagent has no other context, so describe the concrete task in the arguments field.`,\n });\n }\n return subagentRunner(skill, rawArgs, ctx?.signal);\n }\n\n const header = [\n `# Skill: ${skill.name}`,\n skill.description ? `> ${skill.description}` : \"\",\n `(scope: ${skill.scope} · ${skill.path})`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n const argsBlock = rawArgs ? `\\n\\nArguments: ${rawArgs}` : \"\";\n const inner = `${header}\\n\\n${skill.body}${argsBlock}`;\n // Sentinel-wrapped so ContextManager.fold preserves the body verbatim instead of paraphrasing it.\n return `<skill-pin name=${JSON.stringify(skill.name)}>\\n${inner}\\n</skill-pin>`;\n },\n });\n\n return registry;\n}\n"],"mappings":"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","names":[]}
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
2
3
  import {
3
4
  sanitizeName,
4
5
  sessionsDir
5
- } from "./chunk-XST7BSZJ.js";
6
+ } from "./chunk-6PBZN4VI.js";
6
7
 
7
8
  // src/adapters/event-sink-jsonl.ts
8
9
  import { chmodSync, createWriteStream, mkdirSync } from "fs";
@@ -50,4 +51,4 @@ export {
50
51
  eventLogPath,
51
52
  openEventSink
52
53
  };
53
- //# sourceMappingURL=chunk-5GKJLNP2.js.map
54
+ //# sourceMappingURL=chunk-4QUNBQQ2.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/event-sink-jsonl.ts"],"sourcesContent":["import { type WriteStream, chmodSync, createWriteStream, mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Event } from \"../core/events.js\";\nimport { sanitizeName, sessionsDir } from \"../memory/session.js\";\nimport type { EventSink } from \"../ports/event-sink.js\";\n\nexport function eventLogPath(sessionName: string): string {\n return join(sessionsDir(), `${sanitizeName(sessionName)}.events.jsonl`);\n}\n\nexport class JsonlEventSink implements EventSink {\n private buffered = 0;\n\n constructor(private readonly stream: WriteStream) {}\n\n append(ev: Event): void {\n // Skip model.delta — recoverable from model.final.text, would balloon sidecar.\n if (ev.type === \"model.delta\") return;\n this.stream.write(`${JSON.stringify(ev)}\\n`);\n this.buffered++;\n }\n\n flush(): Promise<void> {\n return new Promise((resolve) => {\n if (this.buffered === 0) return resolve();\n this.stream.uncork();\n this.buffered = 0;\n resolve();\n });\n }\n\n close(): Promise<void> {\n return new Promise((resolve) => {\n this.stream.end(() => resolve());\n });\n }\n}\n\nexport function openEventSink(path: string): JsonlEventSink {\n mkdirSync(dirname(path), { recursive: true });\n const stream = createWriteStream(path, { flags: \"a\" });\n try {\n chmodSync(path, 0o600);\n } catch {\n /* chmod no-op on Windows */\n }\n return new JsonlEventSink(stream);\n}\n"],"mappings":";;;;;;;AAAA,SAA2B,WAAW,mBAAmB,iBAAiB;AAC1E,SAAS,SAAS,YAAY;AAKvB,SAAS,aAAa,aAA6B;AACxD,SAAO,KAAK,YAAY,GAAG,GAAG,aAAa,WAAW,CAAC,eAAe;AACxE;AAEO,IAAM,iBAAN,MAA0C;AAAA,EAG/C,YAA6B,QAAqB;AAArB;AAAA,EAAsB;AAAA,EAAtB;AAAA,EAFrB,WAAW;AAAA,EAInB,OAAO,IAAiB;AAEtB,QAAI,GAAG,SAAS,cAAe;AAC/B,SAAK,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,CAAC;AAAA,CAAI;AAC3C,SAAK;AAAA,EACP;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,KAAK,aAAa,EAAG,QAAO,QAAQ;AACxC,WAAK,OAAO,OAAO;AACnB,WAAK,WAAW;AAChB,cAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,OAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,IACjC,CAAC;AAAA,EACH;AACF;AAEO,SAAS,cAAc,MAA8B;AAC1D,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,QAAM,SAAS,kBAAkB,MAAM,EAAE,OAAO,IAAI,CAAC;AACrD,MAAI;AACF,cAAU,MAAM,GAAK;AAAA,EACvB,QAAQ;AAAA,EAER;AACA,SAAO,IAAI,eAAe,MAAM;AAClC;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/event-sink-jsonl.ts"],"sourcesContent":["import { type WriteStream, chmodSync, createWriteStream, mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Event } from \"../core/events.js\";\nimport { sanitizeName, sessionsDir } from \"../memory/session.js\";\nimport type { EventSink } from \"../ports/event-sink.js\";\n\nexport function eventLogPath(sessionName: string): string {\n return join(sessionsDir(), `${sanitizeName(sessionName)}.events.jsonl`);\n}\n\nexport class JsonlEventSink implements EventSink {\n private buffered = 0;\n\n constructor(private readonly stream: WriteStream) {}\n\n append(ev: Event): void {\n // Skip model.delta — recoverable from model.final.text, would balloon sidecar.\n if (ev.type === \"model.delta\") return;\n this.stream.write(`${JSON.stringify(ev)}\\n`);\n this.buffered++;\n }\n\n flush(): Promise<void> {\n return new Promise((resolve) => {\n if (this.buffered === 0) return resolve();\n this.stream.uncork();\n this.buffered = 0;\n resolve();\n });\n }\n\n close(): Promise<void> {\n return new Promise((resolve) => {\n this.stream.end(() => resolve());\n });\n }\n}\n\nexport function openEventSink(path: string): JsonlEventSink {\n mkdirSync(dirname(path), { recursive: true });\n const stream = createWriteStream(path, { flags: \"a\" });\n try {\n chmodSync(path, 0o600);\n } catch {\n /* chmod no-op on Windows */\n }\n return new JsonlEventSink(stream);\n}\n"],"mappings":";;;;;;;;AAAA,SAA2B,WAAW,mBAAmB,iBAAiB;AAC1E,SAAS,SAAS,YAAY;AAKvB,SAAS,aAAa,aAA6B;AACxD,SAAO,KAAK,YAAY,GAAG,GAAG,aAAa,WAAW,CAAC,eAAe;AACxE;AAEO,IAAM,iBAAN,MAA0C;AAAA,EAG/C,YAA6B,QAAqB;AAArB;AAAA,EAAsB;AAAA,EAAtB;AAAA,EAFrB,WAAW;AAAA,EAInB,OAAO,IAAiB;AAEtB,QAAI,GAAG,SAAS,cAAe;AAC/B,SAAK,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,CAAC;AAAA,CAAI;AAC3C,SAAK;AAAA,EACP;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,KAAK,aAAa,EAAG,QAAO,QAAQ;AACxC,WAAK,OAAO,OAAO;AACnB,WAAK,WAAW;AAChB,cAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,OAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,IACjC,CAAC;AAAA,EACH;AACF;AAEO,SAAS,cAAc,MAA8B;AAC1D,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,QAAM,SAAS,kBAAkB,MAAM,EAAE,OAAO,IAAI,CAAC;AACrD,MAAI;AACF,cAAU,MAAM,GAAK;AAAA,EACvB,QAAQ;AAAA,EAER;AACA,SAAO,IAAI,eAAe,MAAM;AAClC;","names":[]}
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
2
3
  import {
3
4
  TUI_FORMATTING_RULES,
4
5
  applyProjectMemory,
@@ -6,7 +7,10 @@ import {
6
7
  escalationContract,
7
8
  memoryEnabled,
8
9
  parseFrontmatter
9
- } from "./chunk-7DLHHBGN.js";
10
+ } from "./chunk-2K65GZBT.js";
11
+ import {
12
+ memoryTypeDefaults
13
+ } from "./chunk-XPDVG52A.js";
10
14
 
11
15
  // src/code/prompt.ts
12
16
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
@@ -54,16 +58,24 @@ function ensureDir(p) {
54
58
  if (!existsSync(p)) mkdirSync(p, { recursive: true });
55
59
  }
56
60
  function formatFrontmatter(e) {
57
- return [
61
+ const lines = [
58
62
  "---",
59
63
  `name: ${e.name}`,
60
64
  `description: ${e.description.replace(/\n/g, " ")}`,
61
65
  `type: ${e.type}`,
62
66
  `scope: ${e.scope}`,
63
- `created: ${e.createdAt}`,
64
- "---",
65
- ""
66
- ].join("\n");
67
+ `created: ${e.createdAt}`
68
+ ];
69
+ if (e.priority) lines.push(`priority: ${e.priority}`);
70
+ if (e.expires) lines.push(`expires: ${e.expires}`);
71
+ lines.push("---", "");
72
+ return lines.join("\n");
73
+ }
74
+ function coercePriority(v) {
75
+ return v === "low" || v === "medium" || v === "high" ? v : void 0;
76
+ }
77
+ function coerceExpires(v) {
78
+ return v === "project_end" ? v : void 0;
67
79
  }
68
80
  function todayIso() {
69
81
  const d = /* @__PURE__ */ new Date();
@@ -125,7 +137,7 @@ var MemoryStore = class {
125
137
  }
126
138
  const raw = readFileSync(file, "utf8");
127
139
  const { data, body } = parseFrontmatter(raw);
128
- return {
140
+ const entry = {
129
141
  name: data.name ?? name,
130
142
  type: data.type ?? "project",
131
143
  scope: data.scope ?? scope,
@@ -133,6 +145,11 @@ var MemoryStore = class {
133
145
  body: body.trim(),
134
146
  createdAt: data.created ?? ""
135
147
  };
148
+ const priority = coercePriority(data.priority);
149
+ if (priority) entry.priority = priority;
150
+ const expires = coerceExpires(data.expires);
151
+ if (expires) entry.expires = expires;
152
+ return entry;
136
153
  }
137
154
  /** Skips malformed files — index stays queryable even if one file is hand-edited into nonsense. */
138
155
  list() {
@@ -175,6 +192,8 @@ var MemoryStore = class {
175
192
  body,
176
193
  createdAt: todayIso()
177
194
  };
195
+ if (input.priority) entry.priority = input.priority;
196
+ if (input.expires) entry.expires = input.expires;
178
197
  const dir = this.dir(input.scope);
179
198
  const file = join(dir, `${name}.md`);
180
199
  const content = `${formatFrontmatter(entry)}${body}
@@ -258,13 +277,36 @@ function applyGlobalReasonixMemory(basePrompt, homeDir) {
258
277
  "```"
259
278
  ].join("\n");
260
279
  }
280
+ function effectivePriority(entry, cfg) {
281
+ if (entry.priority) return entry.priority;
282
+ return memoryTypeDefaults(entry.type, cfg).priority;
283
+ }
284
+ function highPriorityBlock(entries, cfg) {
285
+ const high = entries.filter((e) => effectivePriority(e, cfg) === "high");
286
+ if (high.length === 0) return null;
287
+ const lines = [
288
+ "# HIGH PRIORITY constraints (must observe)",
289
+ "",
290
+ "These memories were declared `priority: high` (via config.memory.customTypes or the memory file itself). Treat them as hard rules \u2014 violations override any other guidance below.",
291
+ ""
292
+ ];
293
+ for (const e of high) {
294
+ const head = `!!! [${e.scope}/${e.type}/${e.name}] ${e.description || "(no description)"}`;
295
+ lines.push(head);
296
+ if (e.body) lines.push("", e.body);
297
+ lines.push("");
298
+ }
299
+ return lines.join("\n").trimEnd();
300
+ }
261
301
  function applyUserMemory(basePrompt, opts = {}) {
262
302
  if (!memoryEnabled()) return basePrompt;
263
303
  const store = new MemoryStore(opts);
264
304
  const global = store.loadIndex("global");
265
305
  const project = store.hasProjectScope() ? store.loadIndex("project") : null;
266
- if (!global && !project) return basePrompt;
306
+ const high = highPriorityBlock(store.list(), opts.cfg);
307
+ if (!global && !project && !high) return basePrompt;
267
308
  const parts = [basePrompt];
309
+ if (high) parts.push("", high);
268
310
  if (global) {
269
311
  parts.push(
270
312
  "",
@@ -488,13 +530,15 @@ Do NOT try to switch via \`run_command\` (\`cd\`, \`pushd\`, etc.) \u2014 your t
488
530
  You have TWO tools for running shell commands, and picking the right one is non-negotiable:
489
531
 
490
532
  - \`run_command\` \u2014 blocks until the process exits. Use for: **tests, builds, lints, typechecks, git operations, one-shot scripts**. Anything that naturally returns in under a minute.
491
- - \`run_background\` \u2014 spawns and detaches after a brief startup window. Use for: **dev servers, watchers, any command with "dev" / "serve" / "watch" / "start" in the name**. Examples: \`npm run dev\`, \`pnpm dev\`, \`yarn start\`, \`vite\`, \`next dev\`, \`uvicorn app:app --reload\`, \`flask run\`, \`python -m http.server\`, \`cargo watch\`, \`tsc --watch\`, \`webpack serve\`.
533
+ - \`run_background\` \u2014 spawns and detaches after a brief startup window. Use for:
534
+ - **Dev servers / watchers / anything with "dev" / "serve" / "watch" / "start" in the name.** Examples: \`npm run dev\`, \`pnpm dev\`, \`yarn start\`, \`vite\`, \`next dev\`, \`uvicorn app:app --reload\`, \`flask run\`, \`python -m http.server\`, \`cargo watch\`, \`tsc --watch\`, \`webpack serve\`.
535
+ - **One-shot long jobs that would blow run_command's 60s ceiling.** Examples: \`curl -L -O <big-url>\`, \`wget\`, \`huggingface-cli download\`, multi-GB \`pip install\` / \`npm install\`, big \`cargo build\` / \`docker build\`. Start with \`run_background\`, then call \`wait_for_job\` ONCE with a long \`timeoutMs\` \u2014 that costs one tool call total, not one per poll.
492
536
 
493
- **Never use run_command for a dev server.** It will block for 60s, time out, and the user will see a frozen tool call while the server was actually running fine. Always \`run_background\`, then \`job_output\` to peek at the logs when you need to verify something.
537
+ **Never use run_command for a dev server or a download likely to exceed a minute.** It will block, time out, and the user will see a frozen tool call while the work was actually running fine. Always \`run_background\` + \`wait_for_job\` / \`job_output\`.
494
538
 
495
539
  After \`run_background\`, tools available to you:
496
540
  - \`job_output(jobId, tailLines?)\` \u2014 read recent logs to verify startup / debug errors.
497
- - \`wait_for_job(jobId, timeoutMs?)\` \u2014 block until the job exits or emits new output. Prefer this over repeating identical \`job_output\` calls while you're intentionally waiting.
541
+ - \`wait_for_job(jobId, timeoutMs?, waitFor?)\` \u2014 block server-side until the job finishes (or, with \`waitFor: 'output-or-exit'\`, until it writes a new line). ONE tool call per wait regardless of duration. \`timeoutMs\` clamps at 300_000. For downloads / installs / builds: leave \`waitFor\` at the default \`'exit'\` and set \`timeoutMs\` to the slowest reasonable end-to-end. For tailing a dev server and reacting to a specific log line: pass \`waitFor: 'output-or-exit'\` with a short \`timeoutMs\`.
498
542
  - \`list_jobs\` \u2014 see every job this session (running + exited).
499
543
  - \`stop_job(jobId)\` \u2014 SIGTERM \u2192 SIGKILL after grace. Stop before switching port / config.
500
544
 
@@ -581,9 +625,10 @@ ${appendParts.join("\n\n")}`;
581
625
  export {
582
626
  sanitizeMemoryName,
583
627
  MemoryStore,
628
+ effectivePriority,
584
629
  applyMemoryStack,
585
630
  codeSystemBase,
586
631
  CODE_SYSTEM_PROMPT,
587
632
  codeSystemPrompt
588
633
  };
589
- //# sourceMappingURL=chunk-R4YTW7PR.js.map
634
+ //# sourceMappingURL=chunk-5JJRUIPA.js.map