luckerr 0.41.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 (156) hide show
  1. package/README.md +267 -0
  2. package/README.zh-CN.md +237 -0
  3. package/dashboard/app.css +3022 -0
  4. package/dashboard/dist/app.js +30137 -0
  5. package/dashboard/dist/app.js.map +1 -0
  6. package/dashboard/dist/vendor-hljs.css +10 -0
  7. package/dashboard/dist/vendor-uplot.css +1 -0
  8. package/dashboard/index.html +19 -0
  9. package/data/deepseek-tokenizer.json.gz +0 -0
  10. package/dist/cli/acp-EOOAI4F5.js +712 -0
  11. package/dist/cli/acp-EOOAI4F5.js.map +1 -0
  12. package/dist/cli/chat-7J6GJXL2.js +51 -0
  13. package/dist/cli/chat-7J6GJXL2.js.map +1 -0
  14. package/dist/cli/chunk-2425HK6U.js +54 -0
  15. package/dist/cli/chunk-2425HK6U.js.map +1 -0
  16. package/dist/cli/chunk-25T6CVUP.js +172 -0
  17. package/dist/cli/chunk-25T6CVUP.js.map +1 -0
  18. package/dist/cli/chunk-2UQP6H6T.js +31 -0
  19. package/dist/cli/chunk-2UQP6H6T.js.map +1 -0
  20. package/dist/cli/chunk-56OAJILV.js +47 -0
  21. package/dist/cli/chunk-56OAJILV.js.map +1 -0
  22. package/dist/cli/chunk-5FTI4KXH.js +150 -0
  23. package/dist/cli/chunk-5FTI4KXH.js.map +1 -0
  24. package/dist/cli/chunk-5TWQD73O.js +2846 -0
  25. package/dist/cli/chunk-5TWQD73O.js.map +1 -0
  26. package/dist/cli/chunk-653BOCMK.js +40 -0
  27. package/dist/cli/chunk-653BOCMK.js.map +1 -0
  28. package/dist/cli/chunk-6ALJTWWQ.js +2663 -0
  29. package/dist/cli/chunk-6ALJTWWQ.js.map +1 -0
  30. package/dist/cli/chunk-6DRKA2IL.js +341 -0
  31. package/dist/cli/chunk-6DRKA2IL.js.map +1 -0
  32. package/dist/cli/chunk-6LV63NJV.js +634 -0
  33. package/dist/cli/chunk-6LV63NJV.js.map +1 -0
  34. package/dist/cli/chunk-74EX7SUH.js +25293 -0
  35. package/dist/cli/chunk-74EX7SUH.js.map +1 -0
  36. package/dist/cli/chunk-74U5RKTX.js +60611 -0
  37. package/dist/cli/chunk-74U5RKTX.js.map +1 -0
  38. package/dist/cli/chunk-ANJSUESV.js +143 -0
  39. package/dist/cli/chunk-ANJSUESV.js.map +1 -0
  40. package/dist/cli/chunk-DB2Z3DKZ.js +54 -0
  41. package/dist/cli/chunk-DB2Z3DKZ.js.map +1 -0
  42. package/dist/cli/chunk-DDIH3ZAA.js +400 -0
  43. package/dist/cli/chunk-DDIH3ZAA.js.map +1 -0
  44. package/dist/cli/chunk-ELN3Z3B2.js +621 -0
  45. package/dist/cli/chunk-ELN3Z3B2.js.map +1 -0
  46. package/dist/cli/chunk-F6BSQJGV.js +200 -0
  47. package/dist/cli/chunk-F6BSQJGV.js.map +1 -0
  48. package/dist/cli/chunk-FET2UAG5.js +246 -0
  49. package/dist/cli/chunk-FET2UAG5.js.map +1 -0
  50. package/dist/cli/chunk-FFJ342IJ.js +190 -0
  51. package/dist/cli/chunk-FFJ342IJ.js.map +1 -0
  52. package/dist/cli/chunk-GB3247B6.js +130 -0
  53. package/dist/cli/chunk-GB3247B6.js.map +1 -0
  54. package/dist/cli/chunk-HC2J4U3G.js +373 -0
  55. package/dist/cli/chunk-HC2J4U3G.js.map +1 -0
  56. package/dist/cli/chunk-HRUZAIHQ.js +42 -0
  57. package/dist/cli/chunk-HRUZAIHQ.js.map +1 -0
  58. package/dist/cli/chunk-J3ZJFUDL.js +308 -0
  59. package/dist/cli/chunk-J3ZJFUDL.js.map +1 -0
  60. package/dist/cli/chunk-J5XJHLWM.js +55 -0
  61. package/dist/cli/chunk-J5XJHLWM.js.map +1 -0
  62. package/dist/cli/chunk-JFGLMRZ6.js +160 -0
  63. package/dist/cli/chunk-JFGLMRZ6.js.map +1 -0
  64. package/dist/cli/chunk-JMBMLOBP.js +26 -0
  65. package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
  66. package/dist/cli/chunk-JMWHXZEL.js +551 -0
  67. package/dist/cli/chunk-JMWHXZEL.js.map +1 -0
  68. package/dist/cli/chunk-KEQGPJBO.js +209 -0
  69. package/dist/cli/chunk-KEQGPJBO.js.map +1 -0
  70. package/dist/cli/chunk-M4K6U37F.js +232 -0
  71. package/dist/cli/chunk-M4K6U37F.js.map +1 -0
  72. package/dist/cli/chunk-MIJI2WMN.js +95 -0
  73. package/dist/cli/chunk-MIJI2WMN.js.map +1 -0
  74. package/dist/cli/chunk-MPAO3JNR.js +128 -0
  75. package/dist/cli/chunk-MPAO3JNR.js.map +1 -0
  76. package/dist/cli/chunk-PZOFBEDC.js +873 -0
  77. package/dist/cli/chunk-PZOFBEDC.js.map +1 -0
  78. package/dist/cli/chunk-RAILYQLN.js +46 -0
  79. package/dist/cli/chunk-RAILYQLN.js.map +1 -0
  80. package/dist/cli/chunk-RR35VQVT.js +90 -0
  81. package/dist/cli/chunk-RR35VQVT.js.map +1 -0
  82. package/dist/cli/chunk-RRA7VPW4.js +417 -0
  83. package/dist/cli/chunk-RRA7VPW4.js.map +1 -0
  84. package/dist/cli/chunk-RU36QVN3.js +452 -0
  85. package/dist/cli/chunk-RU36QVN3.js.map +1 -0
  86. package/dist/cli/chunk-RUBIINXR.js +1819 -0
  87. package/dist/cli/chunk-RUBIINXR.js.map +1 -0
  88. package/dist/cli/chunk-S4XVGLRW.js +499 -0
  89. package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
  90. package/dist/cli/chunk-TUK7OWJA.js +51 -0
  91. package/dist/cli/chunk-TUK7OWJA.js.map +1 -0
  92. package/dist/cli/chunk-VALDDV76.js +580 -0
  93. package/dist/cli/chunk-VALDDV76.js.map +1 -0
  94. package/dist/cli/chunk-WQOGPYGN.js +11390 -0
  95. package/dist/cli/chunk-WQOGPYGN.js.map +1 -0
  96. package/dist/cli/chunk-WREKDFXT.js +34320 -0
  97. package/dist/cli/chunk-WREKDFXT.js.map +1 -0
  98. package/dist/cli/chunk-Y7XQU2EL.js +270 -0
  99. package/dist/cli/chunk-Y7XQU2EL.js.map +1 -0
  100. package/dist/cli/chunk-YBVCZJU4.js +54 -0
  101. package/dist/cli/chunk-YBVCZJU4.js.map +1 -0
  102. package/dist/cli/chunk-YLIHDXUQ.js +749 -0
  103. package/dist/cli/chunk-YLIHDXUQ.js.map +1 -0
  104. package/dist/cli/chunk-YV5XXFD7.js +767 -0
  105. package/dist/cli/chunk-YV5XXFD7.js.map +1 -0
  106. package/dist/cli/chunk-ZRCNIYRQ.js +101 -0
  107. package/dist/cli/chunk-ZRCNIYRQ.js.map +1 -0
  108. package/dist/cli/code-CRKVCMFZ.js +155 -0
  109. package/dist/cli/code-CRKVCMFZ.js.map +1 -0
  110. package/dist/cli/commands-QLMD3T7B.js +356 -0
  111. package/dist/cli/commands-QLMD3T7B.js.map +1 -0
  112. package/dist/cli/commit-53PP32NC.js +293 -0
  113. package/dist/cli/commit-53PP32NC.js.map +1 -0
  114. package/dist/cli/desktop-R6W5CLJ5.js +1046 -0
  115. package/dist/cli/desktop-R6W5CLJ5.js.map +1 -0
  116. package/dist/cli/devtools-YECO25QO.js +3719 -0
  117. package/dist/cli/devtools-YECO25QO.js.map +1 -0
  118. package/dist/cli/diff-LYNRCJZE.js +166 -0
  119. package/dist/cli/diff-LYNRCJZE.js.map +1 -0
  120. package/dist/cli/doctor-5IBP4R5J.js +28 -0
  121. package/dist/cli/doctor-5IBP4R5J.js.map +1 -0
  122. package/dist/cli/events-QN6KLN2V.js +340 -0
  123. package/dist/cli/events-QN6KLN2V.js.map +1 -0
  124. package/dist/cli/index.js +3500 -0
  125. package/dist/cli/index.js.map +1 -0
  126. package/dist/cli/mcp-FGKEH7RG.js +277 -0
  127. package/dist/cli/mcp-FGKEH7RG.js.map +1 -0
  128. package/dist/cli/mcp-browse-YCND4NWT.js +178 -0
  129. package/dist/cli/mcp-browse-YCND4NWT.js.map +1 -0
  130. package/dist/cli/mcp-inspect-V34J3VX5.js +143 -0
  131. package/dist/cli/mcp-inspect-V34J3VX5.js.map +1 -0
  132. package/dist/cli/package.json +3 -0
  133. package/dist/cli/prompt-I775PNKT.js +16 -0
  134. package/dist/cli/prompt-I775PNKT.js.map +1 -0
  135. package/dist/cli/prune-sessions-KGIIYD3P.js +44 -0
  136. package/dist/cli/prune-sessions-KGIIYD3P.js.map +1 -0
  137. package/dist/cli/replay-RDXLUAOE.js +292 -0
  138. package/dist/cli/replay-RDXLUAOE.js.map +1 -0
  139. package/dist/cli/run-RCAC2RYW.js +223 -0
  140. package/dist/cli/run-RCAC2RYW.js.map +1 -0
  141. package/dist/cli/server-FFU6TLYJ.js +3658 -0
  142. package/dist/cli/server-FFU6TLYJ.js.map +1 -0
  143. package/dist/cli/sessions-QT26MQAE.js +107 -0
  144. package/dist/cli/sessions-QT26MQAE.js.map +1 -0
  145. package/dist/cli/setup-VV4WKXHV.js +767 -0
  146. package/dist/cli/setup-VV4WKXHV.js.map +1 -0
  147. package/dist/cli/stats-JVZPQWAN.js +15 -0
  148. package/dist/cli/stats-JVZPQWAN.js.map +1 -0
  149. package/dist/cli/update-KYI3OVJP.js +15 -0
  150. package/dist/cli/update-KYI3OVJP.js.map +1 -0
  151. package/dist/cli/version-ANYORXTI.js +34 -0
  152. package/dist/cli/version-ANYORXTI.js.map +1 -0
  153. package/dist/index.d.ts +2557 -0
  154. package/dist/index.js +15000 -0
  155. package/dist/index.js.map +1 -0
  156. package/package.json +106 -0
@@ -0,0 +1,712 @@
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
+ buildCodeToolset
5
+ } from "./chunk-HC2J4U3G.js";
6
+ import {
7
+ Eventizer,
8
+ autoResolveVerdict
9
+ } from "./chunk-RRA7VPW4.js";
10
+ import {
11
+ formatMcpLifecycleEvent,
12
+ formatMcpSlowToast
13
+ } from "./chunk-RAILYQLN.js";
14
+ import {
15
+ buildTransportFromSpec,
16
+ preflightStdioSpec
17
+ } from "./chunk-HRUZAIHQ.js";
18
+ import {
19
+ CacheFirstLoop,
20
+ ImmutablePrefix,
21
+ bridgeMcpTools
22
+ } from "./chunk-WQOGPYGN.js";
23
+ import "./chunk-J3ZJFUDL.js";
24
+ import {
25
+ openTranscriptFile,
26
+ recordFromLoopEvent,
27
+ writeRecord
28
+ } from "./chunk-FFJ342IJ.js";
29
+ import {
30
+ McpClient,
31
+ parseMcpSpec
32
+ } from "./chunk-YV5XXFD7.js";
33
+ import {
34
+ codeSystemPrompt
35
+ } from "./chunk-6LV63NJV.js";
36
+ import {
37
+ canonicalPresetName,
38
+ resolvePreset
39
+ } from "./chunk-2425HK6U.js";
40
+ import "./chunk-F6BSQJGV.js";
41
+ import {
42
+ loadDotenv
43
+ } from "./chunk-2UQP6H6T.js";
44
+ import "./chunk-MIJI2WMN.js";
45
+ import {
46
+ pauseGate
47
+ } from "./chunk-RUBIINXR.js";
48
+ import "./chunk-VALDDV76.js";
49
+ import "./chunk-56OAJILV.js";
50
+ import "./chunk-PZOFBEDC.js";
51
+ import "./chunk-KEQGPJBO.js";
52
+ import "./chunk-S4XVGLRW.js";
53
+ import {
54
+ DeepSeekClient
55
+ } from "./chunk-DDIH3ZAA.js";
56
+ import "./chunk-25T6CVUP.js";
57
+ import {
58
+ timestampSuffix
59
+ } from "./chunk-Y7XQU2EL.js";
60
+ import "./chunk-5TWQD73O.js";
61
+ import {
62
+ loadApiKey,
63
+ loadBaseUrl,
64
+ loadEditMode,
65
+ loadPreset,
66
+ loadReasoningEffort,
67
+ mcpEnvFor,
68
+ readConfig
69
+ } from "./chunk-6ALJTWWQ.js";
70
+ import "./chunk-M4K6U37F.js";
71
+ import "./chunk-ANJSUESV.js";
72
+ import "./chunk-JMWHXZEL.js";
73
+ import {
74
+ VERSION
75
+ } from "./chunk-MPAO3JNR.js";
76
+ import "./chunk-TUK7OWJA.js";
77
+
78
+ // src/cli/commands/acp.ts
79
+ import { AsyncLocalStorage } from "async_hooks";
80
+ import { existsSync, statSync } from "fs";
81
+ import { resolve } from "path";
82
+
83
+ // src/acp/dispatch.ts
84
+ var READ_TOOLS = /* @__PURE__ */ new Set([
85
+ "read_file",
86
+ "list_directory",
87
+ "directory_tree",
88
+ "get_file_info",
89
+ "glob"
90
+ ]);
91
+ var EDIT_TOOLS = /* @__PURE__ */ new Set([
92
+ "write_file",
93
+ "edit_file",
94
+ "multi_edit",
95
+ "create_directory",
96
+ "delete_file",
97
+ "delete_directory",
98
+ "move_file",
99
+ "copy_file"
100
+ ]);
101
+ var SEARCH_TOOLS = /* @__PURE__ */ new Set(["search_content", "search_files"]);
102
+ var EXECUTE_TOOLS = /* @__PURE__ */ new Set(["run_command", "run_background"]);
103
+ function toolKindFor(name) {
104
+ if (READ_TOOLS.has(name)) return "read";
105
+ if (EDIT_TOOLS.has(name)) return "edit";
106
+ if (SEARCH_TOOLS.has(name)) return "search";
107
+ if (EXECUTE_TOOLS.has(name)) return "execute";
108
+ return "other";
109
+ }
110
+ function tryParseJson(raw) {
111
+ if (!raw) return void 0;
112
+ try {
113
+ return JSON.parse(raw);
114
+ } catch {
115
+ return raw;
116
+ }
117
+ }
118
+ function dispatchKernelEvent(server, sessionId, ev) {
119
+ switch (ev.type) {
120
+ case "model.delta": {
121
+ if (!ev.text) return;
122
+ const variant = ev.channel === "reasoning" ? "agent_thought_chunk" : "agent_message_chunk";
123
+ emit(server, {
124
+ sessionId,
125
+ update: { sessionUpdate: variant, content: { type: "text", text: ev.text } }
126
+ });
127
+ return;
128
+ }
129
+ case "tool.preparing": {
130
+ emit(server, {
131
+ sessionId,
132
+ update: {
133
+ sessionUpdate: "tool_call",
134
+ toolCallId: ev.callId,
135
+ title: ev.name,
136
+ kind: toolKindFor(ev.name),
137
+ status: "pending"
138
+ }
139
+ });
140
+ return;
141
+ }
142
+ case "tool.intent": {
143
+ emit(server, {
144
+ sessionId,
145
+ update: {
146
+ sessionUpdate: "tool_call_update",
147
+ toolCallId: ev.callId,
148
+ status: "in_progress"
149
+ }
150
+ });
151
+ const rawInput = tryParseJson(ev.args);
152
+ if (rawInput !== void 0) {
153
+ emit(server, {
154
+ sessionId,
155
+ update: {
156
+ sessionUpdate: "tool_call",
157
+ toolCallId: ev.callId,
158
+ title: ev.name,
159
+ kind: toolKindFor(ev.name),
160
+ status: "in_progress",
161
+ rawInput
162
+ }
163
+ });
164
+ }
165
+ return;
166
+ }
167
+ case "tool.result": {
168
+ emit(server, {
169
+ sessionId,
170
+ update: {
171
+ sessionUpdate: "tool_call_update",
172
+ toolCallId: ev.callId,
173
+ status: ev.ok ? "completed" : "failed",
174
+ content: [
175
+ {
176
+ type: "content",
177
+ content: { type: "text", text: clip(ev.output) }
178
+ }
179
+ ]
180
+ }
181
+ });
182
+ return;
183
+ }
184
+ default:
185
+ return;
186
+ }
187
+ }
188
+ var MAX_RESULT_CHARS = 8e3;
189
+ function clip(text) {
190
+ if (text.length <= MAX_RESULT_CHARS) return text;
191
+ return `${text.slice(0, MAX_RESULT_CHARS)}
192
+ \u2026(${text.length - MAX_RESULT_CHARS} more chars truncated)`;
193
+ }
194
+ function emit(server, params) {
195
+ server.sendNotification("session/update", params);
196
+ }
197
+
198
+ // src/acp/gates.ts
199
+ var ID_ALLOW_ONCE = "allow_once";
200
+ var ID_ALLOW_ALWAYS = "allow_always";
201
+ var ID_REJECT = "reject";
202
+ var ID_REFINE = "refine";
203
+ var ID_REVISE = "revise";
204
+ var ID_STOP = "stop";
205
+ var ID_CANCEL = "cancel";
206
+ var ID_ACCEPT = "accept";
207
+ function permissionOptionsFor(req) {
208
+ switch (req.kind) {
209
+ case "run_command":
210
+ case "run_background":
211
+ case "path_access":
212
+ return [
213
+ { optionId: ID_ALLOW_ONCE, name: "Allow once", kind: "allow_once" },
214
+ { optionId: ID_ALLOW_ALWAYS, name: "Allow always", kind: "allow_always" },
215
+ { optionId: ID_REJECT, name: "Reject", kind: "reject_once" }
216
+ ];
217
+ case "plan_proposed":
218
+ return [
219
+ { optionId: ID_ALLOW_ONCE, name: "Approve plan", kind: "allow_once" },
220
+ { optionId: ID_REFINE, name: "Refine", kind: "allow_once" },
221
+ { optionId: ID_CANCEL, name: "Cancel", kind: "reject_once" }
222
+ ];
223
+ case "plan_checkpoint":
224
+ return [
225
+ { optionId: ID_ALLOW_ONCE, name: "Continue", kind: "allow_once" },
226
+ { optionId: ID_REVISE, name: "Revise", kind: "allow_once" },
227
+ { optionId: ID_STOP, name: "Stop", kind: "reject_once" }
228
+ ];
229
+ case "plan_revision":
230
+ return [
231
+ { optionId: ID_ACCEPT, name: "Accept revision", kind: "allow_once" },
232
+ { optionId: ID_REJECT, name: "Keep original plan", kind: "reject_once" }
233
+ ];
234
+ case "choice": {
235
+ const payload = req.payload;
236
+ const opts = (payload.options ?? []).map((o) => ({
237
+ optionId: o.id,
238
+ name: o.title ?? o.id,
239
+ kind: "allow_once"
240
+ }));
241
+ opts.push({ optionId: ID_CANCEL, name: "Cancel", kind: "reject_once" });
242
+ return opts;
243
+ }
244
+ }
245
+ }
246
+ function commandPrefix(command) {
247
+ const first = command.trim().split(/\s+/)[0] ?? command.trim();
248
+ return `${first} *`;
249
+ }
250
+ function pathPrefix(p) {
251
+ return p;
252
+ }
253
+ function verdictFor(req, result) {
254
+ const cancelled = result.outcome.outcome === "cancelled";
255
+ const optionId = result.outcome.outcome === "selected" ? result.outcome.optionId : null;
256
+ switch (req.kind) {
257
+ case "run_command":
258
+ case "run_background": {
259
+ if (cancelled || optionId === ID_REJECT) return { type: "deny" };
260
+ if (optionId === ID_ALLOW_ALWAYS) {
261
+ const payload = req.payload;
262
+ return { type: "always_allow", prefix: commandPrefix(payload.command ?? "") };
263
+ }
264
+ return { type: "run_once" };
265
+ }
266
+ case "path_access": {
267
+ if (cancelled || optionId === ID_REJECT) return { type: "deny" };
268
+ if (optionId === ID_ALLOW_ALWAYS) {
269
+ const payload = req.payload;
270
+ return { type: "always_allow", prefix: pathPrefix(payload.allowPrefix) };
271
+ }
272
+ return { type: "run_once" };
273
+ }
274
+ case "plan_proposed": {
275
+ if (cancelled || optionId === ID_CANCEL) return { type: "cancel" };
276
+ if (optionId === ID_REFINE) return { type: "refine" };
277
+ return { type: "approve" };
278
+ }
279
+ case "plan_checkpoint": {
280
+ if (cancelled || optionId === ID_STOP) return { type: "stop" };
281
+ if (optionId === ID_REVISE) return { type: "revise" };
282
+ return { type: "continue" };
283
+ }
284
+ case "plan_revision": {
285
+ if (cancelled) return { type: "cancelled" };
286
+ if (optionId === ID_ACCEPT) return { type: "accepted" };
287
+ return { type: "rejected" };
288
+ }
289
+ case "choice": {
290
+ if (cancelled || optionId === ID_CANCEL || !optionId) return { type: "cancel" };
291
+ return { type: "pick", optionId };
292
+ }
293
+ }
294
+ }
295
+ function permissionTitleFor(req) {
296
+ switch (req.kind) {
297
+ case "run_command":
298
+ case "run_background":
299
+ return `Run command \u2014 ${(req.payload.command ?? "").slice(0, 80)}`;
300
+ case "path_access":
301
+ return `Access path \u2014 ${req.payload.path}`;
302
+ case "plan_proposed":
303
+ return "Approve plan";
304
+ case "plan_checkpoint":
305
+ return `Checkpoint \u2014 ${req.payload.title ?? "step complete"}`;
306
+ case "plan_revision":
307
+ return "Approve plan revision";
308
+ case "choice":
309
+ return req.payload.question ?? "Choose an option";
310
+ }
311
+ }
312
+ function permissionKindFor(req) {
313
+ if (req.kind === "run_command" || req.kind === "run_background") return "execute";
314
+ if (req.kind === "path_access") {
315
+ return req.payload.intent === "write" ? "edit" : "other";
316
+ }
317
+ return "other";
318
+ }
319
+ async function requestPermissionForGate(server, sessionId, req) {
320
+ const params = {
321
+ sessionId,
322
+ toolCall: {
323
+ toolCallId: `gate-${req.id}`,
324
+ title: permissionTitleFor(req),
325
+ kind: permissionKindFor(req),
326
+ status: "pending",
327
+ rawInput: req.payload
328
+ },
329
+ options: permissionOptionsFor(req)
330
+ };
331
+ let result;
332
+ try {
333
+ result = await server.sendRequest(
334
+ "session/request_permission",
335
+ params
336
+ );
337
+ } catch {
338
+ result = { outcome: { outcome: "cancelled" } };
339
+ }
340
+ return verdictFor(req, result);
341
+ }
342
+
343
+ // src/acp/protocol.ts
344
+ var ACP_PROTOCOL_VERSION = 1;
345
+ var ERR_PARSE = -32700;
346
+ var ERR_METHOD_NOT_FOUND = -32601;
347
+ var ERR_INVALID_PARAMS = -32602;
348
+ var ERR_INTERNAL = -32603;
349
+ function flattenPrompt(blocks) {
350
+ const parts = [];
351
+ for (const b of blocks) {
352
+ if (b.type === "text") parts.push(b.text);
353
+ else if (b.type === "resource" && b.resource.text) parts.push(b.resource.text);
354
+ }
355
+ return parts.join("\n\n").trim();
356
+ }
357
+
358
+ // src/acp/server.ts
359
+ import { createInterface } from "readline";
360
+ var AcpServer = class {
361
+ requestHandlers = /* @__PURE__ */ new Map();
362
+ notificationHandlers = /* @__PURE__ */ new Map();
363
+ pending = /* @__PURE__ */ new Map();
364
+ nextOutboundId = 1;
365
+ output;
366
+ rl;
367
+ closed = false;
368
+ constructor(opts = {}) {
369
+ this.output = opts.output ?? process.stdout;
370
+ const input = opts.input ?? process.stdin;
371
+ this.rl = createInterface({ input });
372
+ this.rl.on("line", (line) => {
373
+ void this.handleLine(line);
374
+ });
375
+ }
376
+ onRequest(method, handler) {
377
+ this.requestHandlers.set(method, handler);
378
+ }
379
+ onNotification(method, handler) {
380
+ this.notificationHandlers.set(method, handler);
381
+ }
382
+ sendNotification(method, params) {
383
+ this.write({ jsonrpc: "2.0", method, params });
384
+ }
385
+ /** Send an outbound JSON-RPC request and resolve when the peer responds. */
386
+ sendRequest(method, params) {
387
+ const id = this.nextOutboundId++;
388
+ return new Promise((resolve2, reject) => {
389
+ this.pending.set(id, {
390
+ resolve: resolve2,
391
+ reject
392
+ });
393
+ this.write({ jsonrpc: "2.0", id, method, params });
394
+ });
395
+ }
396
+ close() {
397
+ if (this.closed) return;
398
+ this.closed = true;
399
+ for (const p of this.pending.values()) p.reject(new Error("server closed"));
400
+ this.pending.clear();
401
+ this.rl.close();
402
+ }
403
+ /** Wait for the input stream to end. */
404
+ done() {
405
+ return new Promise((resolve2) => this.rl.once("close", () => resolve2()));
406
+ }
407
+ write(msg) {
408
+ this.output.write(`${JSON.stringify(msg)}
409
+ `);
410
+ }
411
+ writeError(id, code, message) {
412
+ this.write({ jsonrpc: "2.0", id, error: { code, message } });
413
+ }
414
+ async handleLine(raw) {
415
+ const line = raw.trim();
416
+ if (!line) return;
417
+ let parsed;
418
+ try {
419
+ parsed = JSON.parse(line);
420
+ } catch {
421
+ this.writeError(null, ERR_PARSE, "parse error");
422
+ return;
423
+ }
424
+ if (!parsed || typeof parsed !== "object") {
425
+ this.writeError(null, ERR_PARSE, "expected JSON object");
426
+ return;
427
+ }
428
+ const msg = parsed;
429
+ if (typeof msg.method === "string" && msg.id !== void 0) {
430
+ const id = msg.id;
431
+ const handler = this.requestHandlers.get(msg.method);
432
+ if (!handler) {
433
+ this.writeError(id, ERR_METHOD_NOT_FOUND, `method not found: ${msg.method}`);
434
+ return;
435
+ }
436
+ try {
437
+ const result = await handler(msg.params);
438
+ this.write({ jsonrpc: "2.0", id, result });
439
+ } catch (err) {
440
+ this.writeError(id, ERR_INTERNAL, err.message);
441
+ }
442
+ return;
443
+ }
444
+ if (typeof msg.method === "string" && msg.id === void 0) {
445
+ const handler = this.notificationHandlers.get(msg.method);
446
+ if (!handler) return;
447
+ try {
448
+ await handler(msg.params);
449
+ } catch {
450
+ }
451
+ return;
452
+ }
453
+ if (msg.id !== void 0 && msg.method === void 0) {
454
+ const response = parsed;
455
+ const pending = this.pending.get(response.id);
456
+ if (!pending) return;
457
+ this.pending.delete(response.id);
458
+ if (response.error) {
459
+ pending.reject(new Error(response.error.message));
460
+ } else {
461
+ pending.resolve(response.result);
462
+ }
463
+ }
464
+ }
465
+ };
466
+
467
+ // src/cli/commands/acp.ts
468
+ function resolveMcpPrefix(specName, specCount, globalPrefix) {
469
+ if (specName) return `${specName}_`;
470
+ if (specCount === 1 && globalPrefix) return globalPrefix;
471
+ return "";
472
+ }
473
+ async function loadMcpServers(tools, specs, globalPrefix) {
474
+ const clients = [];
475
+ if (specs.length === 0) return clients;
476
+ const cfg = readConfig();
477
+ const disabledNames = new Set(cfg.mcpDisabled ?? []);
478
+ for (const raw of specs) {
479
+ let label = "anon";
480
+ let mcp;
481
+ try {
482
+ const spec = parseMcpSpec(raw);
483
+ label = spec.name ?? "anon";
484
+ if (spec.name && disabledNames.has(spec.name)) {
485
+ process.stderr.write(`${formatMcpLifecycleEvent({ state: "disabled", name: label })}
486
+ `);
487
+ continue;
488
+ }
489
+ process.stderr.write(`${formatMcpLifecycleEvent({ state: "handshake", name: label })}
490
+ `);
491
+ const t0 = Date.now();
492
+ const prefix = resolveMcpPrefix(spec.name, specs.length, globalPrefix);
493
+ if (spec.transport === "stdio") preflightStdioSpec(spec);
494
+ const transport = buildTransportFromSpec(spec, { env: mcpEnvFor(spec.name, cfg) });
495
+ mcp = new McpClient({ transport });
496
+ await mcp.initialize();
497
+ const bridge = await bridgeMcpTools(mcp, {
498
+ registry: tools,
499
+ namePrefix: prefix,
500
+ serverName: label,
501
+ onSlow: (info) => process.stderr.write(
502
+ `${formatMcpSlowToast({ name: info.serverName, p95Ms: info.p95Ms, sampleSize: info.sampleSize })}
503
+ `
504
+ )
505
+ });
506
+ process.stderr.write(
507
+ `${formatMcpLifecycleEvent({
508
+ state: "connected",
509
+ name: label,
510
+ tools: bridge.registeredNames.length,
511
+ ms: Date.now() - t0
512
+ })}
513
+ `
514
+ );
515
+ clients.push(mcp);
516
+ } catch (err) {
517
+ await mcp?.close().catch(() => void 0);
518
+ process.stderr.write(
519
+ `${formatMcpLifecycleEvent({ state: "failed", name: label, reason: err.message })}
520
+ \u2192 run \`luckerr setup\` to remove broken entries from your saved config.
521
+ `
522
+ );
523
+ }
524
+ }
525
+ return clients;
526
+ }
527
+ function resolveDir(raw, fallback) {
528
+ if (!raw) return fallback;
529
+ const abs = resolve(raw);
530
+ if (!existsSync(abs) || !statSync(abs).isDirectory()) {
531
+ throw new Error(`workspace directory not found: ${abs}`);
532
+ }
533
+ return abs;
534
+ }
535
+ async function buildSession(opts) {
536
+ const preset = canonicalPresetName(loadPreset());
537
+ const resolved = resolvePreset(preset);
538
+ const model = opts.modelOverride || resolved.model;
539
+ const toolset = await buildCodeToolset({ rootDir: opts.rootDir });
540
+ const mcpClients = await loadMcpServers(toolset.tools, opts.mcpSpecs ?? [], opts.mcpPrefix);
541
+ const system = codeSystemPrompt(opts.rootDir, {
542
+ hasSemanticSearch: toolset.semantic.enabled,
543
+ modelId: model
544
+ });
545
+ const client = new DeepSeekClient({ baseUrl: loadBaseUrl() });
546
+ const prefix = new ImmutablePrefix({ system, toolSpecs: toolset.tools.specs() });
547
+ const loop = new CacheFirstLoop({
548
+ client,
549
+ prefix,
550
+ tools: toolset.tools,
551
+ model,
552
+ budgetUsd: opts.budgetUsd,
553
+ session: `acp-${timestampSuffix()}`
554
+ });
555
+ return {
556
+ id: `sess_${timestampSuffix()}-${Math.random().toString(36).slice(2, 8)}`,
557
+ rootDir: opts.rootDir,
558
+ model,
559
+ toolset,
560
+ mcpClients,
561
+ loop,
562
+ eventizer: new Eventizer(),
563
+ ctx: {
564
+ model,
565
+ prefixHash: prefix.fingerprint,
566
+ reasoningEffort: loadReasoningEffort()
567
+ },
568
+ aborter: null
569
+ };
570
+ }
571
+ async function acpCommand(opts) {
572
+ loadDotenv();
573
+ if (loadApiKey()) {
574
+ process.env.DEEPSEEK_API_KEY = loadApiKey();
575
+ }
576
+ const defaultDir = resolveDir(opts.dir, process.cwd());
577
+ const sessions = /* @__PURE__ */ new Map();
578
+ const sessionContext = new AsyncLocalStorage();
579
+ const server = new AcpServer();
580
+ let transcriptStream = null;
581
+ if (opts.transcript) {
582
+ const defaultModel = opts.model || resolvePreset(canonicalPresetName(loadPreset())).model;
583
+ transcriptStream = openTranscriptFile(opts.transcript, {
584
+ version: 1,
585
+ source: "luckerr acp",
586
+ model: defaultModel,
587
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
588
+ });
589
+ }
590
+ pauseGate.on((req) => {
591
+ const editMode = opts.yolo ? "yolo" : loadEditMode();
592
+ const auto = autoResolveVerdict(req, editMode);
593
+ if (auto !== null) {
594
+ pauseGate.resolve(req.id, auto);
595
+ return;
596
+ }
597
+ const activeSessionId = sessionContext.getStore();
598
+ if (!activeSessionId || !sessions.has(activeSessionId)) {
599
+ pauseGate.cancel(req.id);
600
+ return;
601
+ }
602
+ void (async () => {
603
+ const verdict = await requestPermissionForGate(server, activeSessionId, req);
604
+ pauseGate.resolve(req.id, verdict);
605
+ })();
606
+ });
607
+ server.onRequest("initialize", (params) => {
608
+ if (!params || typeof params !== "object") {
609
+ throw Object.assign(new Error("initialize: missing params"), { code: ERR_INVALID_PARAMS });
610
+ }
611
+ return {
612
+ protocolVersion: ACP_PROTOCOL_VERSION,
613
+ agentCapabilities: {
614
+ loadSession: false,
615
+ promptCapabilities: { image: false, audio: false, embeddedContext: true },
616
+ mcpCapabilities: { http: false, sse: false }
617
+ },
618
+ agentInfo: { name: "luckerr", title: "Luckerr", version: VERSION },
619
+ authMethods: []
620
+ };
621
+ });
622
+ server.onRequest("session/new", async (params) => {
623
+ const rootDir = resolveDir(params?.cwd, defaultDir);
624
+ const session = await buildSession({
625
+ rootDir,
626
+ modelOverride: opts.model,
627
+ budgetUsd: opts.budgetUsd,
628
+ mcpSpecs: opts.mcpSpecs,
629
+ mcpPrefix: opts.mcpPrefix
630
+ });
631
+ sessions.set(session.id, session);
632
+ return { sessionId: session.id };
633
+ });
634
+ server.onRequest("session/prompt", async (params) => {
635
+ if (!params?.sessionId) {
636
+ throw Object.assign(new Error("session/prompt: missing sessionId"), {
637
+ code: ERR_INVALID_PARAMS
638
+ });
639
+ }
640
+ const session = sessions.get(params.sessionId);
641
+ if (!session) {
642
+ throw Object.assign(new Error(`session/prompt: unknown session ${params.sessionId}`), {
643
+ code: ERR_INVALID_PARAMS
644
+ });
645
+ }
646
+ const text = flattenPrompt(params.prompt);
647
+ if (!text) {
648
+ throw Object.assign(new Error("session/prompt: empty prompt"), { code: ERR_INVALID_PARAMS });
649
+ }
650
+ session.aborter = new AbortController();
651
+ let stopReason = "end_turn";
652
+ try {
653
+ await sessionContext.run(session.id, async () => {
654
+ for await (const ev of session.loop.step(text)) {
655
+ if (session.aborter?.signal.aborted) {
656
+ stopReason = "cancelled";
657
+ break;
658
+ }
659
+ if (transcriptStream) {
660
+ writeRecord(
661
+ transcriptStream,
662
+ recordFromLoopEvent(ev, {
663
+ model: session.ctx.model,
664
+ prefixHash: session.ctx.prefixHash
665
+ })
666
+ );
667
+ }
668
+ for (const kev of session.eventizer.consume(ev, session.ctx)) {
669
+ dispatchKernelEvent(server, session.id, kev);
670
+ if (kev.type === "error") stopReason = "error";
671
+ }
672
+ }
673
+ });
674
+ } catch (err) {
675
+ const message = err.message;
676
+ server.sendNotification("session/update", {
677
+ sessionId: session.id,
678
+ update: {
679
+ sessionUpdate: "agent_message_chunk",
680
+ content: { type: "text", text: `
681
+
682
+ [error] ${message}` }
683
+ }
684
+ });
685
+ stopReason = "error";
686
+ } finally {
687
+ session.aborter = null;
688
+ }
689
+ return { stopReason };
690
+ });
691
+ server.onNotification("session/cancel", (params) => {
692
+ const session = params?.sessionId ? sessions.get(params.sessionId) : void 0;
693
+ session?.aborter?.abort();
694
+ });
695
+ try {
696
+ await server.done();
697
+ } finally {
698
+ transcriptStream?.end();
699
+ const closes = [];
700
+ for (const session of sessions.values()) {
701
+ for (const mcp of session.mcpClients) {
702
+ closes.push(mcp.close().catch(() => void 0));
703
+ }
704
+ }
705
+ await Promise.all(closes);
706
+ }
707
+ }
708
+ export {
709
+ acpCommand,
710
+ loadMcpServers
711
+ };
712
+ //# sourceMappingURL=acp-EOOAI4F5.js.map