deel-local-cli 1.20.13 → 2.0.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 (155) hide show
  1. package/README.ko.md +96 -78
  2. package/README.md +119 -81
  3. package/bin/deel.js +398 -32
  4. package/package.json +2 -1
  5. package/src/acp/jsonrpc.js +87 -7
  6. package/src/acp/map.js +23 -3
  7. package/src/acp/serve.js +333 -25
  8. package/src/agent/agents.js +110 -12
  9. package/src/agent/askcheck.js +50 -6
  10. package/src/agent/asks.js +59 -5
  11. package/src/agent/budget.js +9 -2
  12. package/src/agent/card.js +8 -2
  13. package/src/agent/commit.js +168 -16
  14. package/src/agent/compact.js +93 -21
  15. package/src/agent/{/354/213/240/353/242/260/353/217/204.js → confidence.js} +1 -1
  16. package/src/agent/effort.js +85 -15
  17. package/src/agent/evidence.js +63 -7
  18. package/src/agent/evolve.js +132 -24
  19. package/src/agent/grade.js +12 -3
  20. package/src/agent/loop.js +408 -81
  21. package/src/agent/memory.js +176 -29
  22. package/src/agent/mention.js +22 -5
  23. package/src/agent/models.js +31 -7
  24. package/src/agent/modes.js +25 -10
  25. package/src/agent/outschema.js +381 -56
  26. package/src/agent/pins.js +33 -2
  27. package/src/agent/project.js +73 -8
  28. package/src/agent/recall.js +40 -9
  29. package/src/agent/{/354/204/261/355/225/234/352/270/260/353/241/235.js → recordshape.js} +19 -8
  30. package/src/agent/review.js +143 -13
  31. package/src/agent/route.js +253 -26
  32. package/src/agent/salvage.js +2 -1
  33. package/src/agent/session.js +457 -31
  34. package/src/agent/store.js +232 -22
  35. package/src/agent/threads.js +52 -3
  36. package/src/backend/adapter.js +508 -85
  37. package/src/backend/azure.js +12 -1
  38. package/src/backend/cachemark.js +31 -5
  39. package/src/backend/clientcert.js +23 -1
  40. package/src/backend/ctxsize.js +56 -9
  41. package/src/backend/detect.js +252 -19
  42. package/src/backend/http.js +383 -42
  43. package/src/backend/learn.js +101 -11
  44. package/src/backend/mcp.js +333 -24
  45. package/src/backend/price.js +61 -13
  46. package/src/backend/probe.js +188 -36
  47. package/src/backend/proxy.js +108 -14
  48. package/src/backend/quota.js +226 -30
  49. package/src/backend/retry.js +46 -3
  50. package/src/backend/scan.js +47 -10
  51. package/src/backend/scanui.js +57 -7
  52. package/src/backend/toolfit.js +204 -22
  53. package/src/backend/vision.js +14 -1
  54. package/src/backend/wire.js +58 -10
  55. package/src/cmdnames.js +16 -0
  56. package/src/commands/common.js +70 -0
  57. package/src/commands/extend.js +300 -0
  58. package/src/commands/model.js +852 -0
  59. package/src/commands/view.js +328 -0
  60. package/src/commands/work.js +823 -0
  61. package/src/commands.js +193 -2082
  62. package/src/completion.js +45 -3
  63. package/src/config.js +452 -39
  64. package/src/configexplain.js +125 -14
  65. package/src/doctor.js +164 -26
  66. package/src/i18n/en.js +22 -0
  67. package/src/i18n/index.js +31 -1
  68. package/src/i18n/ja.js +25 -1
  69. package/src/i18n/ko.js +25 -2
  70. package/src/i18n/zh.js +25 -1
  71. package/src/lsp/client.js +111 -9
  72. package/src/lsp/servers.js +86 -22
  73. package/src/oneshot.js +325 -65
  74. package/src/pack/sbom.js +28 -5
  75. package/src/pack/selfpack.js +54 -5
  76. package/src/pack/sheet.en.js +24 -3
  77. package/src/pack/tar.js +45 -8
  78. package/src/pack/zip.js +103 -8
  79. package/src/plugins/manage.js +165 -14
  80. package/src/preview/serve.js +239 -23
  81. package/src/providers/bedrock.js +30 -5
  82. package/src/providers/gemini.js +8 -0
  83. package/src/providers/index.js +17 -1
  84. package/src/repl.js +254 -61
  85. package/src/report.js +7 -2
  86. package/src/reset.js +151 -25
  87. package/src/safety/audit.js +108 -8
  88. package/src/safety/authcmd.js +75 -5
  89. package/src/safety/guard.js +507 -15
  90. package/src/safety/hooks.js +172 -20
  91. package/src/safety/keystore.js +178 -18
  92. package/src/safety/network.js +209 -6
  93. package/src/safety/policy.js +377 -36
  94. package/src/safety/runmode.js +9 -2
  95. package/src/safety/secrets.js +243 -17
  96. package/src/safety/shellenv.js +64 -3
  97. package/src/safety/trust.js +298 -32
  98. package/src/safety/undo.js +409 -17
  99. package/src/setup.js +175 -17
  100. package/src/skills/discover.js +122 -19
  101. package/src/stats.js +57 -16
  102. package/src/tools/{/355/231/225/354/235/270/353/262/225.js → checkmethods.js} +26 -1
  103. package/src/tools/clipboard.js +53 -20
  104. package/src/tools/convert.js +118 -37
  105. package/src/tools/desc.en.js +48 -5
  106. package/src/tools/doc2md.js +11 -1
  107. package/src/tools/docs.js +94 -18
  108. package/src/tools/edit-match.js +212 -13
  109. package/src/tools/encoding.js +525 -28
  110. package/src/tools/excel-com.js +63 -15
  111. package/src/tools/excel.js +12 -7
  112. package/src/tools/fastgrep.js +444 -36
  113. package/src/tools/fig.js +21 -4
  114. package/src/tools/fsutil.js +235 -21
  115. package/src/tools/hwpxwrite.js +80 -19
  116. package/src/tools/ignore.js +55 -7
  117. package/src/tools/index.js +1029 -145
  118. package/src/tools/jobs.js +325 -50
  119. package/src/tools/kiwi.js +50 -5
  120. package/src/tools/lsp.js +164 -32
  121. package/src/tools/outline.js +52 -12
  122. package/src/tools/pdf.js +366 -56
  123. package/src/tools/shell.js +12 -4
  124. package/src/tools/spawn.js +203 -18
  125. package/src/tools/todo.js +73 -4
  126. package/src/tools/verify.js +312 -43
  127. package/src/tools/webfetch.js +184 -25
  128. package/src/tools/xlsx.js +232 -31
  129. package/src/ui/ansi.js +209 -15
  130. package/src/ui/banner.js +2 -1
  131. package/src/ui/complete.js +46 -4
  132. package/src/ui/diff.js +4 -2
  133. package/src/ui/export.js +91 -17
  134. package/src/ui/inputbox.js +58 -18
  135. package/src/ui/intro.js +9 -2
  136. package/src/ui/level.js +32 -7
  137. package/src/ui/md.js +101 -15
  138. package/src/ui/motion.js +5 -2
  139. package/src/ui/notify.js +7 -1
  140. package/src/ui/office.js +37 -5
  141. package/src/ui/pastechip.js +3 -2
  142. package/src/ui/pick.js +85 -12
  143. package/src/ui/prompt.js +176 -13
  144. package/src/ui/screen.js +2 -1
  145. package/src/ui/spinner.js +6 -1
  146. package/src/ui/status.js +80 -12
  147. package/src/ui/wrap.js +23 -37
  148. /package/src/agent/{/353/213/250/352/263/204.js" → phase.js} +0 -0
  149. /package/src/skills/builtin/{/352/271/212/354/235/264/354/236/210/352/262/214-/353/247/214/353/223/244/352/270/260/SKILL.md" → build-deep/SKILL.md} +0 -0
  150. /package/src/skills/builtin/{/354/260/250/352/267/274/354/260/250/352/267/274-/353/224/224/353/262/204/352/271/205/SKILL.md" → debug-step-by-step/SKILL.md} +0 -0
  151. /package/src/skills/builtin/{/353/201/235/352/271/214/354/247/200-/355/225/230/352/270/260/SKILL.md" → finish-all/SKILL.md} +0 -0
  152. /package/src/skills/builtin/{/354/212/244/354/212/244/353/241/234-/352/262/200/355/206/240/SKILL.md" → self-review/SKILL.md} +0 -0
  153. /package/src/skills/builtin/{/354/275/224/353/223/234-/354/244/204/354/235/264/352/270/260/SKILL.md" → simplify-code/SKILL.md} +0 -0
  154. /package/src/skills/builtin/{/354/260/224/353/237/254/353/263/264/352/270/260/SKILL.md" → spike/SKILL.md} +0 -0
  155. /package/src/skills/builtin/{/352/262/200/354/202/254-/353/250/274/354/240/200/SKILL.md" → test-first/SKILL.md} +0 -0
@@ -80,8 +80,19 @@ export function 줄나누기(한줄) {
80
80
  */
81
81
  let 자리;
82
82
  while ((자리 = 남은것.indexOf('\n')) >= 0) {
83
- const 줄 = 남은것.slice(0, 자리).replace(/\r$/, '');
83
+ let 줄 = 남은것.slice(0, 자리).replace(/\r$/, '');
84
84
  남은것 = 남은것.slice(자리 + 1);
85
+ /*
86
+ * ── 줄 앞의 BOM 을 뗀다 (사냥5 H5-9) ──────────────────────────────────
87
+ *
88
+ * .NET 의 `StreamWriter(Encoding.UTF8)` 처럼 첫 바이트에 BOM(U+FEFF) 을 붙여
89
+ * 쓰는 클라이언트가 있다. 그 글자는 JSON 이 받지 않아서 **첫 줄 = initialize**
90
+ * 가 -32700 · id null 로 떨어졌고, 저쪽은 initialize 답을 영영 기다렸다 —
91
+ * 붙자마자 멈추는데 우리 로그에는 「읽을 수 없는 JSON」 한 줄뿐이다.
92
+ * 줄마다 보는 것은, 메시지마다 새 writer 를 여는 클라이언트면 BOM 이 매 줄 앞에
93
+ * 오기 때문이다. 글자는 번호로 비교한다 — 소스에 보이지 않는 글자를 안 둔다.
94
+ */
95
+ if (줄.charCodeAt(0) === 0xfeff) 줄 = 줄.slice(1);
85
96
  if (줄.trim()) 한줄(줄); // 빈 줄은 그냥 넘긴다. 오류로 칠 것이 아니다
86
97
  }
87
98
  };
@@ -117,12 +128,34 @@ export class 연결 {
117
128
  this.보내기줄(JSON.stringify(덩이) + '\n');
118
129
  }
119
130
 
120
- /** 저쪽에 요청을 걸고 답을 기다린다. */
121
- 요청(방법, 인자) {
131
+ /**
132
+ * 저쪽에 요청을 걸고 답을 기다린다.
133
+ *
134
+ * ── 기다림에도 끊는 줄이 있어야 한다 (사냥5 H5-3) ───────────────────────
135
+ *
136
+ * 승인 창을 띄워 두고 사람이 안 누른 채 턴을 취소하면, 여기 기다림은 끊기는 줄을
137
+ * 몰라서 **답이 올 때까지** 서 있었다. 그 턴은 취소된 뒤에도 살아 있고, 한참 뒤에
138
+ * 옛 창의 「이번만 실행」 이 닿으면 그대로 도구를 돌렸다. signal 을 주면 끊기는
139
+ * 순간 기다림을 거둔다 — 표에서도 지우므로 늦게 온 답은 「이미 포기한 것」 으로
140
+ * 조용히 버려진다.
141
+ *
142
+ * @param {object} [o]
143
+ * @param {AbortSignal|null} [o.signal] 끊기면 기다림을 거두고 `거둠: true` 오류로 깬다
144
+ */
145
+ 요청(방법, 인자, { signal = null } = {}) {
122
146
  const id = this.다음번호++;
123
147
  return new Promise((풀기, 깨기) => {
124
148
  if (this.닫혔나) { 깨기(new Error('관이 닫혔습니다')); return; }
125
- this.기다리는것.set(id, { 풀기, 깨기 });
149
+ const 거둔오류 = () => Object.assign(new Error('기다리던 요청을 거뒀습니다 — 턴이 끊겼습니다'), { 거둠: true });
150
+ // 이미 끊긴 턴의 물음은 내보내지도 않는다. 에디터에 답할 수 없는 창만 남는다.
151
+ if (signal?.aborted) { 깨기(거둔오류()); return; }
152
+ const 거두기 = () => { if (this.기다리는것.delete(id)) 깨기(거둔오류()); };
153
+ signal?.addEventListener?.('abort', 거두기, { once: true });
154
+ const 떼기 = () => signal?.removeEventListener?.('abort', 거두기);
155
+ this.기다리는것.set(id, {
156
+ 풀기: (값) => { 떼기(); 풀기(값); },
157
+ 깨기: (오류) => { 떼기(); 깨기(오류); },
158
+ });
126
159
  this.#쓰기({ jsonrpc: '2.0', id, method: 방법, params: 인자 ?? {} });
127
160
  });
128
161
  }
@@ -148,6 +181,18 @@ export class 연결 {
148
181
  this.#쓰기({ jsonrpc: '2.0', id: null, error: { code: 오류번호.파싱, message: '읽을 수 없는 JSON 입니다' } });
149
182
  return;
150
183
  }
184
+ /*
185
+ * 묶음(batch) — `[{…}, {…}]` 한 줄.
186
+ *
187
+ * 배열도 typeof 로는 'object' 라 바로 아래 갈래를 지나쳤다. 그 뒤로는 method 도
188
+ * id 도 없는 것으로 읽혀 **답이 한 줄도 안 나갔다** — 저쪽은 영영 기다린다.
189
+ * ACP 는 묶음을 쓰지 않고 우리도 안 받는다. 안 받는다고 답한다. 안에 든 id 를
190
+ * 골라 답하지 않는 것은, 받지 않은 요청에 답이 붙으면 저쪽이 된 줄 알기 때문이다.
191
+ */
192
+ if (Array.isArray(온것)) {
193
+ this.#쓰기({ jsonrpc: '2.0', id: null, error: { code: 오류번호.잘못된요청, message: '묶음(batch)은 받지 않습니다 — 한 줄에 요청 하나씩 보내 주세요' } });
194
+ return;
195
+ }
151
196
  if (!온것 || typeof 온것 !== 'object') {
152
197
  this.#쓰기({ jsonrpc: '2.0', id: null, error: { code: 오류번호.잘못된요청, message: '객체가 아닙니다' } });
153
198
  return;
@@ -157,7 +202,18 @@ export class 연결 {
157
202
  //
158
203
  // 'id' in 온것 으로 본다. id 가 0 일 수 있기 때문이다 — ACP 클라이언트는
159
204
  // 실제로 0번부터 센다. 여기서 truthy 로 보면 첫 요청의 답을 통째로 잃는다.
160
- if ('id' in 온것 && !온것.method) {
205
+ //
206
+ // method 도 **칸이 있나**로 본다 (사냥5 H5-10). `!온것.method` 는 빈 글도 거짓으로
207
+ // 쳐서 `{"id":77,"method":""}` 가 이 답 갈래로 왔다 — 77번에는 아무 답도 안 나가
208
+ // 저쪽이 영영 기다렸고, 같은 번호의 우리 요청이 있으면 그게 엉뚱하게 풀렸다.
209
+ // id 와 method 가 같이 있으면 요청이다. 빈 method 는 아래에서 -32600 으로 답한다.
210
+ //
211
+ // 그리고 **result·error 칸이 있어야** 답이다 (8회차 ACP-3). method 칸이 아예
212
+ // 없는 줄은 위 빈 method 검사에 안 걸려 그대로 답 갈래로 갔고, result 가 없으니
213
+ // 기다리던 우리 요청이 `풀기(undefined)` 로 풀렸다 — 승인 묻기가 이 길로 오므로
214
+ // 답이 아닌 줄 하나가 승인 결과를 「아무것도 안 고름」 으로 만든다. 그 id 에는
215
+ // 답도 안 나가 저쪽도 영영 기다렸다. 무엇이 답인가는 규격이 정해 두었다.
216
+ if ('id' in 온것 && !('method' in 온것) && ('result' in 온것 || 'error' in 온것)) {
161
217
  const 기다림 = this.기다리는것.get(온것.id);
162
218
  if (!기다림) return; // 이미 포기한 것. 늦게 온 답은 조용히 버린다
163
219
  this.기다리는것.delete(온것.id);
@@ -172,14 +228,38 @@ export class 연결 {
172
228
  return;
173
229
  }
174
230
 
175
- if (typeof 온것.method !== 'string') {
231
+ if (typeof 온것.method !== 'string' || !온것.method) {
232
+ /*
233
+ * ── 우리 기다림을 **영영 매달아 두지 않는다** (사냥6 막판-뒷단) ───────
234
+ *
235
+ * 위 ACP-3 고침이 「result·error 가 없으면 답이 아니다」 로 막으면서, 그런 줄이
236
+ * 여기로 굴러떨어지게 됐다. 그런데 여기서는 저쪽에만 -32600 을 답하고 끝난다 —
237
+ * 그 번호를 기다리던 **우리** 요청은 아무도 안 깨운다. 요청() 에는 시계가 없어서
238
+ * 턴을 사람이 취소하기 전까지 서 있는다(재 봤다: pending 인 채로 남는다).
239
+ * 승인 묻기가 이 길로 오므로, 규격을 어긴 줄 하나에 화면이 말없이 멎는다 —
240
+ * 바로 위 문단이 「저쪽도 영영 기다렸다」 고 적어 둔 것의 우리 쪽 판이다.
241
+ *
242
+ * 깨뜨리면 serve.js 의 승인묻기 가 받아 「못 물어봐서 거부했습니다」 를 로그에
243
+ * 적고 안 한다. 못 물어본 것을 못 물어봤다고 말하는 것이 이 프로그램의 자세다.
244
+ * 깨뜨리는 것은 **method 칸이 아예 없는** 줄뿐이다. 빈 method 는 H5-10 이 정한
245
+ * 대로 「요청」 이라, 저쪽이 빈 글자 하나로 우리 승인 물음을 마음대로 끊게 된다 —
246
+ * 끊긴 물음의 답은 거부라 위험하진 않지만, 남이 끊을 수 있는 자리를 열어 줄 까닭이
247
+ * 없다. 칸째 없는 줄만 답이 깨진 것으로 본다.
248
+ */
176
249
  if ('id' in 온것) {
250
+ const 기다림 = 'method' in 온것 ? null : this.기다리는것.get(온것.id);
251
+ if (기다림) {
252
+ this.기다리는것.delete(온것.id);
253
+ try { 기다림.깨기(new Error('저쪽 답에 result·error 가 없습니다 — 규격에 맞는 답이 아닙니다')); } catch { /* 이미 정리된 것 */ }
254
+ }
177
255
  this.#쓰기({ jsonrpc: '2.0', id: 온것.id, error: { code: 오류번호.잘못된요청, message: 'method 가 없습니다' } });
178
256
  }
179
257
  return;
180
258
  }
181
259
 
182
- const 알림인가 = !('id' in 온것) || 온것.id === null;
260
+ // 알림은 id **칸이 없는** 요청이다(JSON-RPC 2.0). id 가 null 이어도 요청이라 답한다 —
261
+ // null 을 알림으로 쳤더니 답이 한 줄도 안 나가 저쪽이 영영 기다렸다 (6회차 규약6ai-b J2).
262
+ const 알림인가 = !('id' in 온것);
183
263
 
184
264
  Promise.resolve()
185
265
  .then(() => this.다루기(온것.method, 온것.params ?? {}))
package/src/acp/map.js CHANGED
@@ -313,8 +313,20 @@ export function 되살린것(messages, { 최대내용 = 2000, 뿌리 = null } =
313
313
  const 이름 = String(tc.name ?? '도구');
314
314
  const 인자 = 인자풀기(tc.args);
315
315
 
316
+ /*
317
+ * id 가 붙은 부름은 **id 로만** 찾는다.
318
+ *
319
+ * 못 찾으면 이름 큐로 한 번 더 찾았다. 그 큐에 든 것은 id 를 안 주는 규격의
320
+ * 답이거나 **같은 이름을 쓰는 다른 부름의 답**이다. 그래서 제 답이 안 남은
321
+ * 부름이 남의 답을 뺏어 달고 completed 로 그려졌다 — 바로 아래 머리말이
322
+ * 「성공으로 그리면 안 된다」 고 적어 둔 그 자리다. 게다가 뺏긴 쪽은 큐가
323
+ * 비어 실패로 밀린다. 한 줄 어긋난 것이 아니라 둘 다 틀린 것이다.
324
+ *
325
+ * id 를 주는 규격은 답에도 id 를 적는다(adapter.js 의 toolMessage). 이름으로
326
+ * 짝짓는 것은 id 가 아예 없는 규격(ollama)뿐이고, 그쪽은 부름에도 id 가 없다.
327
+ */
316
328
  let 답;
317
- if (tc?.id != null && id로.has(tc.id)) 답 = id로.get(tc.id);
329
+ if (tc?.id != null) 답 = id로.get(tc.id);
318
330
  else {
319
331
  const q = 이름으로.get(이름);
320
332
  if (q?.length) 답 = q.shift();
@@ -363,8 +375,16 @@ export function 프롬프트글(덩이들) {
363
375
  break;
364
376
  case 'resource': {
365
377
  const r = b.resource ?? {};
366
- if (typeof r.text === 'string' && r.text) {
367
- 조각.push(`--- ${r.uri ?? '붙임'} ---\n${r.text}`);
378
+ /*
379
+ * 빈 글도 **읽은 것**이다.
380
+ *
381
+ * `&& r.text` 로 보던 때는 빈 파일이 알맹이가 아예 안 실려 온 붙임과 같은
382
+ * 갈래로 떨어져 「글이 아니라 못 읽었습니다」 가 붙었다. 모델은 그걸 읽기
383
+ * 실패로 알아듣고 같은 파일을 Read 로 또 연다 — 그리고 또 빈 파일을 본다.
384
+ * 빈 것과 못 읽은 것은 다음에 할 일이 다르다.
385
+ */
386
+ if (typeof r.text === 'string') {
387
+ 조각.push(`--- ${r.uri ?? '붙임'} ---\n${r.text || '(빈 파일입니다)'}`);
368
388
  } else if (r.uri) {
369
389
  조각.push(`(붙임: ${r.uri} — 글이 아니라 못 읽었습니다)`);
370
390
  }