deel-local-cli 1.8.0 → 1.10.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 (49) hide show
  1. package/README.ko.md +1166 -1182
  2. package/README.md +1223 -1232
  3. package/bin/deel.js +55 -12
  4. package/package.json +3 -3
  5. package/src/acp/serve.js +40 -3
  6. package/src/agent/compact.js +314 -296
  7. package/src/agent/effort.js +27 -7
  8. package/src/agent/evidence.js +2 -0
  9. package/src/agent/filemem.js +141 -0
  10. package/src/agent/grade.js +51 -1
  11. package/src/agent/loop.js +202 -35
  12. package/src/agent/session.js +121 -5
  13. package/src/agent/store.js +186 -9
  14. package/src/agent/threads.js +26 -1
  15. package/src/backend/adapter.js +201 -18
  16. package/src/backend/learn.js +24 -0
  17. package/src/backend/mcp.js +96 -5
  18. package/src/backend/probe.js +131 -61
  19. package/src/backend/quota.js +29 -5
  20. package/src/backend/toolfit.js +325 -0
  21. package/src/commands.js +107 -27
  22. package/src/config.js +47 -2
  23. package/src/i18n/en.js +56 -2
  24. package/src/i18n/index.js +18 -0
  25. package/src/i18n/ja.js +58 -2
  26. package/src/i18n/ko.js +103 -2
  27. package/src/i18n/zh.js +58 -2
  28. package/src/lsp/client.js +49 -5
  29. package/src/oneshot.js +81 -3
  30. package/src/pack/sbom.js +30 -4
  31. package/src/pack/selfpack.js +25 -9
  32. package/src/pack/sheet.en.js +288 -0
  33. package/src/pack/tar.js +65 -2
  34. package/src/plugins/manage.js +46 -9
  35. package/src/repl.js +264 -35
  36. package/src/safety/audit.js +92 -8
  37. package/src/safety/authcmd.js +14 -3
  38. package/src/safety/guard.js +143 -0
  39. package/src/safety/keystore.js +62 -39
  40. package/src/safety/undo.js +24 -6
  41. package/src/tools/index.js +239 -34
  42. package/src/tools/jobs.js +158 -29
  43. package/src/tools/verify.js +33 -4
  44. package/src/tools/webfetch.js +92 -9
  45. package/src/ui/md.js +201 -5
  46. package/src/ui/motion.js +0 -1
  47. package/src/ui/pastechip.js +50 -3
  48. package/src/ui/pick.js +115 -0
  49. package/src/ui/screen.js +23 -3
package/src/i18n/en.js CHANGED
@@ -38,6 +38,28 @@ export const en = {
38
38
  'cmd.model.arg': '[name|list|models|card]',
39
39
  'cmd.think.desc': 'reasoning effort (off/low/medium/high/max)',
40
40
  'cmd.think.arg': '<level>',
41
+
42
+ // ── /think screen ──────────────────────────────────────────────────
43
+ 'run.noTools': 'Tool calling is unconfirmed — check with deel diagnose',
44
+ 'think.effort': 'Effort',
45
+ 'think.profile': 'Profile',
46
+ 'think.detail': 'detail',
47
+ 'think.harder': 'harder',
48
+ 'think.faster': 'faster',
49
+ 'think.eg': 'e.g.',
50
+ 'think.col.stage': 'Stage',
51
+ 'think.col.level': 'Effort',
52
+ 'think.col.cap': 'Out cap',
53
+ 'think.col.when': 'When',
54
+ 'think.cap.head': 'Caps are shared inside',
55
+ 'think.cap.tail': ' —',
56
+ 'think.cap.you': '(you set this)',
57
+ 'think.cap.server': '(read from the server)',
58
+ 'think.cap.guess': '(unknown, so a default)',
59
+ 'think.ctx': 'Context',
60
+ 'think.ctx.used': ' · used ',
61
+ 'think.nomodel': 'This connection does not apply effort at the model layer.',
62
+ 'think.nomodel.note': 'Only the per-stage output cap applies.',
41
63
  'cmd.mode.desc': 'approval policy — how much it asks first (auto/confirm/strict)',
42
64
  'cmd.mode.arg': '<mode>',
43
65
  'cmd.work.desc': 'work mode — what kind of job this is (picked for you in auto)',
@@ -111,6 +133,8 @@ export const en = {
111
133
  'consult.failed': 'Could not ask — {왜}',
112
134
  'consult.empty': 'The reply came back empty. That model may not answer without tools.',
113
135
  'consult.added': 'Added that answer to the conversation, labelled with who said it.',
136
+ // ── Connection check ──────────────────────────────────────────────────
137
+ 'probe.codexOnly': 'The {모델} family is not served through this endpoint (/chat/completions) — OpenAI serves it only through the Responses API (/responses), which deel cannot speak yet. Pick a different model for now.',
114
138
  // ── Startup header ────────────────────────────────────────────────────
115
139
  'head.spec.ollama': "Ollama's own API",
116
140
  'head.spec.openai': 'OpenAI-compatible API',
@@ -183,6 +207,7 @@ export const en = {
183
207
  'undo.alsoTalk': 'Rolled back {n} message(s) too — if the model still thinks the reverted code is there, it keeps building on it.',
184
208
  'undo.repaired': '({n} orphaned tool call(s) cleaned up as well)',
185
209
  'undo.saidWas': 'You had asked:',
210
+ 'undo.failed': '{n} file(s) could not be restored — they are still modified. The snapshots were kept, so try /undo again.',
186
211
  'undo.talkKept': 'The conversation is left as is — that turn had already been folded away.',
187
212
  'undo.talkKeptWhy': 'The model may still think the reverted work exists, so mention it in your next message.',
188
213
 
@@ -295,11 +320,19 @@ export const en = {
295
320
  'level.developer.hint': 'everything by hand',
296
321
 
297
322
  // ── Ask box (the Ask tool) ────────────────────────────────────────────
323
+ 'plan.ask': 'Go ahead with this?',
324
+ 'plan.hint': '⏎ go · y with a note · 3 a note on that step · n cancel',
325
+ 'plan.cancelled': 'Stopped. The plan is still above — just say what you want next.',
326
+ 'plan.going': 'Going ahead with the plan.',
327
+ 'plan.goingWith': 'Going ahead, with your note — {말}',
328
+ 'plan.replan': 'Redoing the plan with that in mind.',
329
+ 'plan.replanStep': 'Redoing the plan with your note on step {단계}.',
298
330
  'ask.title': 'A question for you',
299
- 'ask.pickHint': 'Pick a number, or type your own answer',
331
+ 'ask.pickHint': 'Pick a number. Add a note after it if you have one (2 split the files)',
300
332
  'ask.freeHint': 'Type your answer',
301
- 'ask.pickPrompt': '1-{끝}, or type your own',
333
+ 'ask.pickPrompt': '1-{끝} (a note may follow), or type your own',
302
334
  'ask.freePrompt': 'Answer',
335
+ 'ask.stopped': 'Stopped — treating it as unanswered.',
303
336
 
304
337
  // ── When the server pushes back (backend/retry.js) ────────────────────
305
338
  'loop.backoff': 'The server pushed back ({무엇}) — calling again in {초}s ({n}/{max})',
@@ -330,6 +363,8 @@ export const en = {
330
363
  'sum.ok': 'ok',
331
364
  'sum.exitCode': 'exit {code}',
332
365
  'sum.killedBy': 'killed by {시그널}',
366
+ 'sum.tooMuchOut': 'output too large — capture cut short',
367
+ 'sum.cantRun': 'could not run ({왜})',
333
368
  'sum.partial': 'partial',
334
369
  'sum.cut': 'truncated',
335
370
  'sum.notAllSeen': 'not all scanned',
@@ -346,6 +381,7 @@ export const en = {
346
381
  'sum.noChange': 'unchanged',
347
382
  'sum.verified': '{n} checked',
348
383
  'sum.readAs': 'read via {쓴것}',
384
+ 'sum.encGuess': '{인코딩} (guessed)',
349
385
  'sum.linesOf': '{준}/{전체} lines',
350
386
  'sum.countOf': '{n}/{전체}',
351
387
  'sum.remembered': 'remembered ({n} lines)',
@@ -354,6 +390,7 @@ export const en = {
354
390
  'sum.jobStarted': 'started as job {n}',
355
391
  'sum.jobRunning': 'running',
356
392
  'sum.jobEndedAlready': 'already finished',
393
+ 'sum.jobNotStopped': 'still running — could not stop it',
357
394
  'sum.jobStopped': 'stopped',
358
395
 
359
396
  'tier.exact': 'exact match',
@@ -388,12 +425,27 @@ export const en = {
388
425
  'run.hintHelp': '/help commands',
389
426
  'run.hintEsc': 'ESC stop',
390
427
  'run.hintQuit': 'Ctrl+C stop / quit',
428
+ 'run.stopping': 'stopping…',
429
+ 'run.errKept': 'What arrived before the failure was kept in the conversation — you can carry on from there.',
430
+ 'ev.capped': 'The answer was cut off at {한계} tokens — raise the cap with /out, or have files written in parts',
431
+ 'ev.cutoff': 'The server stopped the answer without saying it had finished — it may have been cut mid-way',
432
+ 'ev.nudgeMissed': 'It was about to finish leaving {n} of the things you asked for undone — pushed back once',
433
+ 'ev.nudgeRead': 'It was about to finish having only read things — pushed back once',
434
+ 'ev.learnedCtx': 'Setting the context limit to {한계} as the server reported, and calling again',
435
+ 'ev.learnedOut': 'Setting the answer-length limit to {한계} as the server reported, and calling again',
436
+ 'ev.reset': 'Out of room — cleared {버린수} earlier messages and carrying on, {할일} to-do items left',
437
+ 'ev.resetBare': 'Out of room — cleared {버린수} earlier messages and carrying on',
438
+ 'paste.chip': 'pasted',
439
+ 'paste.chipLines': '{n} lines',
440
+ 'paste.folded': '{표} — folded away. It expands back verbatim when sent.',
441
+ 'paste.pasted': 'Pasted {n} lines — Enter sends them all at once',
391
442
  'run.thinking': 'thinking…',
392
443
  'run.thinkingChars': 'thinking… {n} chars',
393
444
  'run.turnFoot': '{초}s · {n} tool calls · ↑{입력} ↓{출력}',
394
445
  'run.bye': 'Bye.',
395
446
  'run.byeStats': '{n} model calls · {초}s in tools · ↑{입력} ↓{출력}',
396
447
  'run.notMade': '— was not created',
448
+ 'store.notSaving': 'This conversation is not being written to disk ({까닭}) — {n} lines lost. Close this window and you cannot resume it.',
397
449
 
398
450
  'stage.plan': 'deciding',
399
451
  'stage.work': 'continuing',
@@ -413,6 +465,7 @@ export const en = {
413
465
  'status.keyStore': 'Key store',
414
466
  'status.rules': 'Rules',
415
467
  'status.noRules': 'none (/init creates one)',
468
+ 'status.rulesUnread': '{이름} exists but could not be read ({까닭}) — this folder\'s rules are not in effect',
416
469
  'status.caps': 'Supports',
417
470
  'status.capTools': 'tools',
418
471
  'status.capStream': 'stream',
@@ -463,4 +516,5 @@ export const en = {
463
516
  'common.seeHelp': 'Run /help for the list',
464
517
  'common.yes': 'yes',
465
518
  'common.no': 'no',
519
+ 'common.cfgSaveFailed': 'Could not write the setting to disk ({왜}) — it applies now but reverts on restart.',
466
520
  };
package/src/i18n/index.js CHANGED
@@ -201,6 +201,24 @@ export function 말(열쇠, 채움 = null) {
201
201
  });
202
202
  }
203
203
 
204
+ /**
205
+ * 이 열쇠의 **모든 말**. 겹치는 것은 한 번만.
206
+ *
207
+ * 화면에 찍은 뒤 그 글자를 **다시 알아봐야 하는** 자리에만 쓴다.
208
+ * 붙여넣기 표가 그렇다 — `[붙여넣기 #1 · 40줄 · 2.1KB]` 를 찍어 놓고,
209
+ * 보낼 때 그 표를 도로 찾아 원문으로 편다. 지금 말로만 찾으면 `/lang en`
210
+ * 한 번에 앞서 찍어 둔 표를 못 알아본다 — 사람이 붙인 40줄이 표 글자
211
+ * 그대로 모델에게 가고, 그게 조용히 벌어진다.
212
+ */
213
+ export function 말모두(열쇠) {
214
+ const k = String(열쇠 ?? '');
215
+ const 본것 = [];
216
+ for (const L of 언어들) {
217
+ const v = 표[L]?.[k];
218
+ if (v !== undefined && !본것.includes(v)) 본것.push(v);
219
+ }
220
+ return 본것.length ? 본것 : [k];
221
+ }
204
222
  /*
205
223
  * 세는 말 한 조각 — `3개 파일` · `1건` · `12줄`.
206
224
  *
package/src/i18n/ja.js CHANGED
@@ -22,6 +22,31 @@ export const ja = {
22
22
  'cmd.model.arg': '[名前|list|models|card]',
23
23
  'cmd.think.desc': '思考の量 (off/low/medium/high/max)',
24
24
  'cmd.think.arg': '<段階>',
25
+
26
+ // ── /think 画面 ─────────────────────────────────────────────────────
27
+ // 表の枠だけ訳して中身(段階の名前)を訳さないと何も読めない。
28
+ // 段階名・配分名は agent/effort.js が持っている — modes.js と同じやり方。
29
+ 'run.noTools': 'ツール呼び出しが確認できていません — deel diagnose で点検してください',
30
+ 'think.effort': '思考の強さ',
31
+ 'think.profile': '配分',
32
+ 'think.detail': '詳しく',
33
+ 'think.harder': 'もっと強く',
34
+ 'think.faster': 'もっと速く',
35
+ 'think.eg': '例',
36
+ 'think.col.stage': '段階',
37
+ 'think.col.level': '強さ',
38
+ 'think.col.cap': '出力上限',
39
+ 'think.col.when': 'いつ',
40
+ 'think.cap.head': '出力上限は',
41
+ 'think.cap.tail': ' の中で分け合います —',
42
+ 'think.cap.you': '(ご自分で決めた値)',
43
+ 'think.cap.server': '(サーバーから読み取った値)',
44
+ 'think.cap.guess': '(分からないので既定値)',
45
+ 'think.ctx': 'コンテキスト',
46
+ 'think.ctx.used': ' · 使用中 ',
47
+ 'think.nomodel': 'この接続ではモデル側の思考量の調整が効きません。',
48
+ 'think.nomodel.note': '段階ごとの出力上限だけが効きます。',
49
+
25
50
  'cmd.mode.desc': '承認の方針 — どこまで先に訊くか (auto/confirm/strict)',
26
51
  'cmd.mode.arg': '<モード>',
27
52
  'cmd.work.desc': '作業モード — どんな仕事か (auto では自動で選ばれる)',
@@ -94,6 +119,7 @@ export const ja = {
94
119
  'consult.failed': '訊けませんでした — {왜}',
95
120
  'consult.empty': '返答が空でした。そのモデルは道具なしでは答えないのかもしれません。',
96
121
  'consult.added': 'その答えを、誰が言ったか付けて会話に足しました。',
122
+ 'probe.codexOnly': '{모델} 系列はこの窓口(/chat/completions)では出てきません — OpenAI が Responses API(/responses)でのみ提供しているモデルで、deel はまだその窓口を使えません。今は別のモデルを選んでください。',
97
123
  'head.spec.ollama': 'Ollama 独自規格',
98
124
  'head.spec.openai': 'OpenAI 互換 API',
99
125
  'head.spec.anthropic': 'Anthropic API',
@@ -158,6 +184,7 @@ export const ja = {
158
184
  'undo.alsoTalk': 'メッセージも {n} 件戻しました — 戻したコードがまだあるとモデルが思っていると、その上に積み上げてしまいます。',
159
185
  'undo.repaired': '(宙に浮いた道具呼び出し {n} 件も片づけました)',
160
186
  'undo.saidWas': 'あなたはこう頼んでいました:',
187
+ 'undo.failed': '{n}個は戻せませんでした — そのファイルは直したままです。控えは残してあるので /undo をもう一度試してください。',
161
188
  'undo.talkKept': '会話はそのままです — そのターンはすでに畳まれていました。',
162
189
  'undo.talkKeptWhy': '戻した作業がまだあるとモデルが思っている可能性があるので、次の一言で触れてください。',
163
190
  'bell.stateOn': 'オン',
@@ -258,11 +285,19 @@ export const ja = {
258
285
  'level.beginner.hint': '勧められた設定のまま始めます',
259
286
  'level.developer.name': '開発者',
260
287
  'level.developer.hint': '全部自分で決めます',
288
+ 'plan.ask': 'この通り進めますか?',
289
+ 'plan.hint': '⏎ 進む · y 一言添えて進む · 3 その段階に一言 · n やめる',
290
+ 'plan.cancelled': 'やめました。計画は上に残っているので、続きから言ってください。',
291
+ 'plan.going': '計画どおり進めます。',
292
+ 'plan.goingWith': '一言を添えて進めます — {말}',
293
+ 'plan.replan': 'その点を踏まえて計画を出し直します。',
294
+ 'plan.replanStep': '{단계}段階についての言葉を踏まえて計画を出し直します。',
261
295
  'ask.title': 'お訊きします',
262
- 'ask.pickHint': '番号を選ぶか、自分で書いてください',
296
+ 'ask.pickHint': '番号を選んでください。言いたいことがあれば後ろに付けられます (2 ファイルは分けて)',
263
297
  'ask.freeHint': '答えを書いてください',
264
- 'ask.pickPrompt': '1-{끝}、または自分で書く',
298
+ 'ask.pickPrompt': '1-{끝}(後ろに一言添えても可)、または自分で書く',
265
299
  'ask.freePrompt': '答え',
300
+ 'ask.stopped': '止めました — 答えなかったものとして進みます。',
266
301
  'loop.backoff': 'サーバーに押し返されました ({무엇}) — {초} 秒後にもう一度 ({n}/{max})',
267
302
  'cost.retries': '再試行',
268
303
  // ── 数える言葉 ────────────────────────────────────────────────────────
@@ -288,6 +323,8 @@ export const ja = {
288
323
  'sum.ok': '成功',
289
324
  'sum.exitCode': '終了コード {code}',
290
325
  'sum.killedBy': '{시그널} で終了',
326
+ 'sum.tooMuchOut': '出力が多すぎて途中で打ち切りました',
327
+ 'sum.cantRun': '実行できませんでした ({왜})',
291
328
  'sum.partial': '一部のみ',
292
329
  'sum.cut': '一部省略',
293
330
  'sum.notAllSeen': '全部は見ていない',
@@ -304,6 +341,7 @@ export const ja = {
304
341
  'sum.noChange': '変更なし',
305
342
  'sum.verified': '確認{n}個',
306
343
  'sum.readAs': '{쓴것} で変換して読み込み',
344
+ 'sum.encGuess': '{인코딩}(推定)',
307
345
  'sum.linesOf': '{준}/{전체}行',
308
346
  'sum.countOf': '{n}/{전체}個',
309
347
  'sum.remembered': '覚えました({n}行)',
@@ -312,6 +350,7 @@ export const ja = {
312
350
  'sum.jobStarted': '{n}番で起動',
313
351
  'sum.jobRunning': '実行中',
314
352
  'sum.jobEndedAlready': 'すでに終了',
353
+ 'sum.jobNotStopped': '終わっていません — まだ生きています',
315
354
  'sum.jobStopped': '終了',
316
355
 
317
356
  'tier.exact': '完全一致',
@@ -344,12 +383,27 @@ export const ja = {
344
383
  'run.hintHelp': '/help コマンド一覧',
345
384
  'run.hintEsc': 'ESC 中断',
346
385
  'run.hintQuit': 'Ctrl+C 中断・終了',
386
+ 'run.stopping': '止めています…',
387
+ 'run.errKept': 'ここまで届いた分は会話に残しました — このまま続けて話せます。',
388
+ 'ev.capped': '答えが {한계} トークンで切れました — /out で上限を上げるか、ファイルは分けて書かせてください',
389
+ 'ev.cutoff': 'サーバーが終わったとも言わずに答えを止めました — 途中で切れた可能性があります',
390
+ 'ev.nudgeMissed': '頼んだこと {n} 件を残したまま終えようとしたので、一度押し戻しました',
391
+ 'ev.nudgeRead': '読むだけで終えようとしたので、一度押し戻しました',
392
+ 'ev.learnedCtx': 'サーバーが教えてくれたコンテキスト上限 {한계} に合わせて呼び直します',
393
+ 'ev.learnedOut': 'サーバーが教えてくれた答えの長さ上限 {한계} に合わせて呼び直します',
394
+ 'ev.reset': '場所が足りず、前の会話 {버린수} 件を消して続けます — 残りのやること {할일} 件',
395
+ 'ev.resetBare': '場所が足りず、前の会話 {버린수} 件を消して続けます',
396
+ 'paste.chip': '貼り付け',
397
+ 'paste.chipLines': '{n}行',
398
+ 'paste.folded': '{표} — たたんでおきました。送るときにそのまま開きます。',
399
+ 'paste.pasted': '{n}行を貼り付けました — Enter で一度に送ります',
347
400
  'run.thinking': '考え中…',
348
401
  'run.thinkingChars': '考え中… {n}文字',
349
402
  'run.turnFoot': '{초}秒 · ツール{n}回 · ↑{입력} ↓{출력}',
350
403
  'run.bye': '終了します。',
351
404
  'run.byeStats': 'モデル呼び出し{n}回 · ツール時間{초}秒 · ↑{입력} ↓{출력}',
352
405
  'run.notMade': '— 作られませんでした',
406
+ 'store.notSaving': 'この会話がファイルに書けていません ({까닭}) — {n}行を失いました。このまま閉じると再開できません。',
353
407
 
354
408
  'stage.plan': '最初の判断',
355
409
  'stage.work': '続き',
@@ -368,6 +422,7 @@ export const ja = {
368
422
  'status.keyStore': '鍵の保管',
369
423
  'status.rules': 'ルール',
370
424
  'status.noRules': 'なし(/init で作れます)',
425
+ 'status.rulesUnread': '{이름} はありますが読めませんでした({까닭})— このフォルダのルールは効いていません',
371
426
  'status.caps': '対応',
372
427
  'status.capTools': 'ツール',
373
428
  'status.capStream': 'ストリーム',
@@ -414,4 +469,5 @@ export const ja = {
414
469
  'common.seeHelp': '/help で一覧が出ます',
415
470
  'common.yes': 'はい',
416
471
  'common.no': 'いいえ',
472
+ 'common.cfgSaveFailed': '設定をファイルに保存できませんでした({왜})— 今回は効きますが、開き直すと元に戻ります。',
417
473
  };
package/src/i18n/ko.js CHANGED
@@ -25,6 +25,30 @@ export const ko = {
25
25
  'cmd.model.arg': '[이름|list|models|카드]',
26
26
  'cmd.think.desc': '추론 강도 (off/low/medium/high/max)',
27
27
  'cmd.think.arg': '<수준>',
28
+
29
+ // ── /think 화면 ────────────────────────────────────────────────────
30
+ // 표의 틀만 옮기고 알맹이(단계 이름)를 안 옮기면 아무것도 안 읽힌다.
31
+ // 단계 이름·배분 이름은 agent/effort.js 가 들고 있다 — modes.js 와 같은 방식.
32
+ 'run.noTools': '도구 호출이 확인되지 않았습니다 — deel diagnose 로 점검하세요',
33
+ 'think.effort': '추론 강도',
34
+ 'think.profile': '배분',
35
+ 'think.detail': '자세히',
36
+ 'think.harder': '더 세게',
37
+ 'think.faster': '더 빠르게',
38
+ 'think.eg': '예',
39
+ 'think.col.stage': '단계',
40
+ 'think.col.level': '강도',
41
+ 'think.col.cap': '출력상한',
42
+ 'think.col.when': '언제',
43
+ 'think.cap.head': '출력 상한은',
44
+ 'think.cap.tail': ' 안에서 나눕니다 —',
45
+ 'think.cap.you': '(직접 정하신 값)',
46
+ 'think.cap.server': '(서버에서 알아낸 값)',
47
+ 'think.cap.guess': '(모르는 값이라 기본값)',
48
+ 'think.ctx': '컨텍스트',
49
+ 'think.ctx.used': ' · 지금 찬 양 ',
50
+ 'think.nomodel': '이 연결은 모델 층 강도 조절이 적용되지 않습니다.',
51
+ 'think.nomodel.note': '출력 상한만 단계별로 적용됩니다.',
28
52
  'cmd.mode.desc': '승인 정책 — 얼마나 물어보나 (auto/confirm/strict)',
29
53
  'cmd.mode.arg': '<모드>',
30
54
  'cmd.work.desc': '작업 모드 — 무슨 일을 하는 중인가 (종합이면 저절로)',
@@ -98,6 +122,8 @@ export const ko = {
98
122
  'consult.failed': '못 물어봤습니다 — {왜}',
99
123
  'consult.empty': '빈 답이 왔습니다. 그 모델이 도구 없이 답을 못 내는 것일 수 있습니다.',
100
124
  'consult.added': '이 답을 대화에도 넣었습니다 — 누가 한 말인지 표를 달아서.',
125
+ // ── 연결 진단 ─────────────────────────────────────────────────────────
126
+ 'probe.codexOnly': '{모델} 계열은 이 문(/chat/completions)으로는 안 나옵니다 — OpenAI 가 Responses API(/responses)로만 내주는 모델인데, deel 은 아직 그 문을 못 씁니다. 지금은 다른 모델을 고르세요.',
101
127
  // ── 켤 때 머리말 ──────────────────────────────────────────────────────
102
128
  'head.spec.ollama': 'Ollama 자체 규격',
103
129
  'head.spec.openai': 'OpenAI 호환 규격',
@@ -170,6 +196,7 @@ export const ko = {
170
196
  'undo.alsoTalk': '대화도 {n}개 걷어냈습니다 — 모델이 되돌린 코드를 아직 있는 줄 알면 그 위에 이어 일합니다.',
171
197
  'undo.repaired': '(짝 없는 도구 호출 {n}개도 같이 정리)',
172
198
  'undo.saidWas': '시켰던 말:',
199
+ 'undo.failed': '{n}개는 못 되돌렸습니다 — 그 파일은 고쳐진 그대로입니다. 기록을 남겨 뒀으니 /undo 를 다시 해 보세요.',
173
200
  'undo.talkKept': '대화는 그대로 둡니다 — 그 턴의 말이 이미 접혀 없어졌습니다.',
174
201
  'undo.talkKeptWhy': '모델이 되돌린 것을 아직 있는 줄 알 수 있으니, 이어 시킬 때 한 번 짚어 주세요.',
175
202
 
@@ -282,11 +309,38 @@ export const ko = {
282
309
  'level.developer.hint': '전부 직접 만짐',
283
310
 
284
311
  // ── 되묻기 상자 (Ask 도구) ────────────────────────────────────────────
312
+ /*
313
+ * 계획 상자.
314
+ *
315
+ * 여태 이 줄은 한국어가 글자 그대로 박혀 있었다 — `/lang en` 을 켠
316
+ * 사람이 계획을 승인하는 자리에서만 한글을 봤다. 하필 「무엇을 치면
317
+ * 되나」 를 말하는 줄이라, 못 읽으면 그 자리에서 막힌다.
318
+ *
319
+ * 셋을 한 줄에 보여 준다. ⏎ 하나로 진행되는 것을 맨 앞에 둔다 —
320
+ * 그게 열에 아홉이고, 여기서 뭘 더 치게 하면 사람은 애초에 계획
321
+ * 같은 걸 안 보려 든다.
322
+ */
323
+ 'plan.ask': '이대로 진행할까요?',
324
+ 'plan.hint': '⏎ 진행 · y 한마디 붙여 진행 · 3 그 단계에 한마디 · n 취소',
325
+ 'plan.cancelled': '그만뒀습니다. 계획은 위에 남아 있으니 이어서 말씀하셔도 됩니다.',
326
+ 'plan.going': '계획대로 진행합니다.',
327
+ 'plan.goingWith': '한마디를 얹어 진행합니다 — {말}',
328
+ 'plan.replan': '그 점을 반영해 계획을 다시 냅니다.',
329
+ 'plan.replanStep': '{단계}단계에 대한 말을 반영해 계획을 다시 냅니다.',
285
330
  'ask.title': '물어봅니다',
286
- 'ask.pickHint': '숫자로 고르거나, 그냥 쳐서 답하세요',
331
+ /*
332
+ * 「번호 + 하고 싶은 말」 을 여기서 한 줄로 알려 준다.
333
+ *
334
+ * 되는 줄 모르면 아무도 안 쓴다. 그렇다고 세 줄로 적으면 물음보다
335
+ * 안내가 길어져서 정작 물음을 안 읽는다. 보기 하나로 보여 준다 —
336
+ * 보기 하나가 설명 세 줄보다 잘 읽힌다.
337
+ */
338
+ 'ask.pickHint': '숫자로 고르세요. 하고 싶은 말이 있으면 뒤에 붙이면 됩니다 (2 파일은 나눠서)',
287
339
  'ask.freeHint': '답을 쳐 주세요',
288
- 'ask.pickPrompt': '1-{끝} 또는 직접 입력',
340
+ 'ask.pickPrompt': '1-{끝} (뒤에 의견을 붙여도 됩니다) 또는 직접 입력',
289
341
  'ask.freePrompt': '답',
342
+ // 물어보는 도중에 ESC 를 눌렀다. 물음이 화면에 걸린 채로 남으면 안 된다.
343
+ 'ask.stopped': '멈췄습니다 — 답하지 않은 것으로 넘어갑니다.',
290
344
 
291
345
  // ── 잠깐 막혔을 때 (backend/retry.js) ─────────────────────────────────
292
346
  'loop.backoff': '서버가 잠시 막았습니다 ({무엇}) — {초}초 뒤 다시 부릅니다 ({n}/{max})',
@@ -328,6 +382,8 @@ export const ko = {
328
382
  'sum.ok': '성공',
329
383
  'sum.exitCode': '종료코드 {code}',
330
384
  'sum.killedBy': '{시그널} 로 죽음',
385
+ 'sum.tooMuchOut': '출력이 너무 많아 받다 말았습니다',
386
+ 'sum.cantRun': '못 돌렸습니다 ({왜})',
331
387
  'sum.partial': '일부만',
332
388
  'sum.cut': '일부 잘림',
333
389
  'sum.notAllSeen': '다 못 봄',
@@ -344,6 +400,7 @@ export const ko = {
344
400
  'sum.noChange': '그대로 (바뀐 것 없음)',
345
401
  'sum.verified': '확인 {n}개',
346
402
  'sum.readAs': '{쓴것} 로 바꿔 읽음',
403
+ 'sum.encGuess': '{인코딩} (추정)',
347
404
  'sum.linesOf': '{준}/{전체}줄',
348
405
  'sum.countOf': '{n}/{전체}개',
349
406
  'sum.remembered': '기억했습니다 ({n}줄)',
@@ -352,6 +409,7 @@ export const ko = {
352
409
  'sum.jobStarted': '{n}번으로 띄움',
353
410
  'sum.jobRunning': '도는중',
354
411
  'sum.jobEndedAlready': '이미 끝남',
412
+ 'sum.jobNotStopped': '안 끝났습니다 — 아직 살아 있습니다',
355
413
  'sum.jobStopped': '끝냄',
356
414
 
357
415
  // Edit 이 어떤 느슨함으로 자리를 찾았나 (tools/edit-match.js 의 TIERS).
@@ -387,12 +445,53 @@ export const ko = {
387
445
  'run.hintHelp': '/help 명령 목록',
388
446
  'run.hintEsc': 'ESC 중단',
389
447
  'run.hintQuit': 'Ctrl+C 중단·끝내기',
448
+ // 줄 화면에는 상자가 없다. 눌린 것이 닿았다는 신호를 여기 한 줄로 낸다.
449
+ 'run.stopping': '멈추는 중…',
450
+ // 탈이 나기 전까지 흘러온 반쪽을 대화에 남겼다. 안 말하면 다시 처음부터 친다.
451
+ 'run.errKept': '여기까지 받은 것은 대화에 남겼습니다 — 이어서 말씀하셔도 됩니다.',
452
+
453
+ /*
454
+ * ── 대화창 말고 다른 앞면이 쓰는 한 줄 (한 방 실행 · ACP) ─────────────
455
+ *
456
+ * 대화창은 이 소식들을 저마다 여러 줄로 풀어 쓴다. 한 방 실행과 에디터
457
+ * 붙임에는 그럴 자리가 없어서 한 줄짜리가 따로 있어야 했는데, 그게
458
+ * 없어서 **아예 아무 말도 안 하고 있었다.** 잘린 답이 온전한 답인 척
459
+ * `deel -p` 뒤 스크립트로 넘어가던 것이 그 탓이다.
460
+ */
461
+ 'ev.capped': '답이 {한계} 토큰에서 잘렸습니다 — /out 으로 상한을 올리거나, 파일은 나눠 쓰게 하세요',
462
+ 'ev.cutoff': '서버가 끝났다는 말 없이 답을 멈췄습니다 — 중간에서 끊겼을 수 있습니다',
463
+ 'ev.nudgeMissed': '시킨 것 {n}가지를 빼놓고 끝내려고 해서 한 번 되밀었습니다',
464
+ 'ev.nudgeRead': '읽기만 하고 끝내려고 해서 한 번 되밀었습니다',
465
+ 'ev.learnedCtx': '서버가 알려 준 컨텍스트 한계 {한계} 로 맞추고 다시 부릅니다',
466
+ 'ev.learnedOut': '서버가 알려 준 답 길이 한계 {한계} 로 맞추고 다시 부릅니다',
467
+ /*
468
+ * 자리가 다 차서 기억을 비운 자리. **오류가 아니다.**
469
+ *
470
+ * 붉게 말하면 사람은 하던 일이 엎어진 줄 알고 /clear 를 친다 — 정작
471
+ * 지금은 시킨 말과 남은 할 일을 들고 그대로 이어 가는 중인데도.
472
+ * 무엇을 버렸고 무엇을 들고 가는지 한 줄로 사실대로 말한다.
473
+ */
474
+ 'ev.reset': '자리가 모자라 앞선 대화 {버린수}개를 비우고 이어갑니다 — 남은 할 일 {할일}개',
475
+ 'ev.resetBare': '자리가 모자라 앞선 대화 {버린수}개를 비우고 이어갑니다',
476
+ /*
477
+ * 붙여넣기 표에 쓰는 낱말.
478
+ *
479
+ * 이 말은 화면에 찍고 **다시 찾아 읽는다.** 보낼 때 표를 원문으로
480
+ * 펴야 하기 때문이다. 그래서 낱말을 바꾸면 무늬(pastechip.js 의 표무늬)가
481
+ * 저절로 따라간다 — 네 말을 다 넣어 짓는다. 옛 말로 찍어 둔 표도
482
+ * 계속 알아본다.
483
+ */
484
+ 'paste.chip': '붙여넣기',
485
+ 'paste.chipLines': '{n}줄',
486
+ 'paste.folded': '{표} — 접어 뒀습니다. 보낼 때 그대로 펴집니다.',
487
+ 'paste.pasted': '{n}줄을 붙여넣었습니다 — Enter 로 한 번에 보냅니다',
390
488
  'run.thinking': '생각 중…',
391
489
  'run.thinkingChars': '생각 중… {n}자',
392
490
  'run.turnFoot': '{초}초 · 도구 {n}회 · ↑{입력} ↓{출력}',
393
491
  'run.bye': '끝냅니다.',
394
492
  'run.byeStats': '모델 호출 {n}회 · 도구 시간 {초}초 · ↑{입력} ↓{출력}',
395
493
  'run.notMade': '— 만들어지지 않았습니다',
494
+ 'store.notSaving': '이 대화가 파일에 안 적히고 있습니다 ({까닭}) — {n}줄을 잃었습니다. 지금 창을 닫으면 이어할 수 없습니다.',
396
495
 
397
496
  // 생각 중 앞에 붙는 단계 꼬리표 (agent/effort.js 의 STAGES).
398
497
  'stage.plan': '첫 판단',
@@ -413,6 +512,7 @@ export const ko = {
413
512
  'status.keyStore': '열쇠 보관',
414
513
  'status.rules': '규칙',
415
514
  'status.noRules': '없음 (/init 으로 만들 수 있습니다)',
515
+ 'status.rulesUnread': '{이름} 이 있는데 못 읽었습니다 ({까닭}) — 이 폴더 규칙이 안 걸려 있습니다',
416
516
  'status.caps': '지원',
417
517
  'status.capTools': '도구',
418
518
  'status.capStream': '스트림',
@@ -463,4 +563,5 @@ export const ko = {
463
563
  'common.seeHelp': '명령 목록은 /help',
464
564
  'common.yes': '네',
465
565
  'common.no': '아니요',
566
+ 'common.cfgSaveFailed': '설정을 파일에 남기지 못했습니다 ({왜}) — 이번 판에는 먹지만 다시 켜면 돌아갑니다.',
466
567
  };
package/src/i18n/zh.js CHANGED
@@ -22,6 +22,31 @@ export const zh = {
22
22
  'cmd.model.arg': '[名称|list|models|card]',
23
23
  'cmd.think.desc': '推理力度 (off/low/medium/high/max)',
24
24
  'cmd.think.arg': '<级别>',
25
+
26
+ // ── /think 画面 ─────────────────────────────────────────────────────
27
+ // 只译表格的框、不译里面的内容(阶段名),就等于什么都读不懂。
28
+ // 阶段名·分配名在 agent/effort.js 里 — 和 modes.js 一样的做法。
29
+ 'run.noTools': '尚未确认工具调用 — 请用 deel diagnose 检查',
30
+ 'think.effort': '推理力度',
31
+ 'think.profile': '分配',
32
+ 'think.detail': '详细',
33
+ 'think.harder': '更用力',
34
+ 'think.faster': '更快',
35
+ 'think.eg': '例',
36
+ 'think.col.stage': '阶段',
37
+ 'think.col.level': '力度',
38
+ 'think.col.cap': '输出上限',
39
+ 'think.col.when': '何时',
40
+ 'think.cap.head': '输出上限在',
41
+ 'think.cap.tail': ' 之内分配 —',
42
+ 'think.cap.you': '(您自己定的值)',
43
+ 'think.cap.server': '(从服务器读到的值)',
44
+ 'think.cap.guess': '(不知道,所以用默认值)',
45
+ 'think.ctx': '上下文',
46
+ 'think.ctx.used': ' · 已用 ',
47
+ 'think.nomodel': '这个连接不会在模型那一层调节推理力度。',
48
+ 'think.nomodel.note': '只有各阶段的输出上限会生效。',
49
+
25
50
  'cmd.mode.desc': '批准策略 — 先问到什么程度 (auto/confirm/strict)',
26
51
  'cmd.mode.arg': '<模式>',
27
52
  'cmd.work.desc': '工作模式 — 这是哪一类活儿 (auto 会替你选)',
@@ -94,6 +119,7 @@ export const zh = {
94
119
  'consult.failed': '问不成 — {왜}',
95
120
  'consult.empty': '返回是空的。那个模型可能不带工具就不回答。',
96
121
  'consult.added': '已把那个回答加进对话,并标明是谁说的。',
122
+ 'probe.codexOnly': '{모델} 系列无法通过这个接口(/chat/completions)使用 — OpenAI 只通过 Responses API(/responses) 提供该系列,而 deel 还不会说那个接口。请暂时改选别的模型。',
97
123
  'head.spec.ollama': 'Ollama 自有规格',
98
124
  'head.spec.openai': 'OpenAI 兼容 API',
99
125
  'head.spec.anthropic': 'Anthropic API',
@@ -158,6 +184,7 @@ export const zh = {
158
184
  'undo.alsoTalk': '同时撤回了 {n} 条消息 — 如果模型还以为被撤销的代码在,它会继续往上搭。',
159
185
  'undo.repaired': '(另外清理了 {n} 个悬空的工具调用)',
160
186
  'undo.saidWas': '你当时说的是:',
187
+ 'undo.failed': '有 {n} 个没能还原 — 那些文件还是改过的样子。备份留着,请再试一次 /undo。',
161
188
  'undo.talkKept': '对话保持原样 — 那一轮早就被折叠了。',
162
189
  'undo.talkKeptWhy': '模型可能仍以为撤销掉的工作还在,下一句里提一下。',
163
190
  'bell.stateOn': '开',
@@ -258,11 +285,19 @@ export const zh = {
258
285
  'level.beginner.hint': '按推荐设置开始',
259
286
  'level.developer.name': '开发者',
260
287
  'level.developer.hint': '全部自己来',
288
+ 'plan.ask': '就按这个做吗?',
289
+ 'plan.hint': '⏎ 开始 · y 加一句再开始 · 3 对那一步说一句 · n 取消',
290
+ 'plan.cancelled': '停下了。计划还在上面,接着说就行。',
291
+ 'plan.going': '按计划开始。',
292
+ 'plan.goingWith': '带上你这句话开始 — {말}',
293
+ 'plan.replan': '按这一点重新出计划。',
294
+ 'plan.replanStep': '按你对第 {단계} 步的说法重新出计划。',
261
295
  'ask.title': '有个问题问你',
262
- 'ask.pickHint': '选一个编号,或者自己写',
296
+ 'ask.pickHint': '选一个编号。有话要说就写在编号后面 (2 文件分开写)',
263
297
  'ask.freeHint': '写下你的回答',
264
- 'ask.pickPrompt': '1-{끝},或者自己写',
298
+ 'ask.pickPrompt': '1-{끝}(后面可以加一句话),或者自己写',
265
299
  'ask.freePrompt': '回答',
300
+ 'ask.stopped': '已停止 — 按没有回答继续。',
266
301
  'loop.backoff': '服务端把请求推回来了 ({무엇}) — {초} 秒后再试 ({n}/{max})',
267
302
  'cost.retries': '重试',
268
303
  // ── 计数词 ────────────────────────────────────────────────────────────
@@ -288,6 +323,8 @@ export const zh = {
288
323
  'sum.ok': '成功',
289
324
  'sum.exitCode': '退出码 {code}',
290
325
  'sum.killedBy': '被 {시그널} 结束',
326
+ 'sum.tooMuchOut': '输出太多,接到一半就停了',
327
+ 'sum.cantRun': '没能运行({왜})',
291
328
  'sum.partial': '仅部分',
292
329
  'sum.cut': '已截断',
293
330
  'sum.notAllSeen': '未全部扫描',
@@ -304,6 +341,7 @@ export const zh = {
304
341
  'sum.noChange': '没有变化',
305
342
  'sum.verified': '核对{n}项',
306
343
  'sum.readAs': '用 {쓴것} 转换后读取',
344
+ 'sum.encGuess': '{인코딩}(推测)',
307
345
  'sum.linesOf': '{준}/{전체}行',
308
346
  'sum.countOf': '{n}/{전체}个',
309
347
  'sum.remembered': '已记住({n}行)',
@@ -312,6 +350,7 @@ export const zh = {
312
350
  'sum.jobStarted': '以{n}号启动',
313
351
  'sum.jobRunning': '运行中',
314
352
  'sum.jobEndedAlready': '已经结束',
353
+ 'sum.jobNotStopped': '没有结束 — 还活着',
315
354
  'sum.jobStopped': '已结束',
316
355
 
317
356
  'tier.exact': '完全匹配',
@@ -344,12 +383,27 @@ export const zh = {
344
383
  'run.hintHelp': '/help 命令列表',
345
384
  'run.hintEsc': 'ESC 中断',
346
385
  'run.hintQuit': 'Ctrl+C 中断·退出',
386
+ 'run.stopping': '正在停止…',
387
+ 'run.errKept': '出错前收到的内容已经留在对话里 — 可以直接接着说。',
388
+ 'ev.capped': '回答在 {한계} 个 token 处被截断 — 用 /out 调高上限,或者让文件分次写',
389
+ 'ev.cutoff': '服务端没说结束就停下了 — 回答可能是中途断的',
390
+ 'ev.nudgeMissed': '还剩你交代的 {n} 件事没做就要收尾,已经推回去一次',
391
+ 'ev.nudgeRead': '只看不动就要收尾,已经推回去一次',
392
+ 'ev.learnedCtx': '按服务端给出的上下文上限 {한계} 重新调用',
393
+ 'ev.learnedOut': '按服务端给出的回答长度上限 {한계} 重新调用',
394
+ 'ev.reset': '位置不够,已清掉前面 {버린수} 条对话继续做 — 还剩 {할일} 件待办',
395
+ 'ev.resetBare': '位置不够,已清掉前面 {버린수} 条对话继续做',
396
+ 'paste.chip': '粘贴',
397
+ 'paste.chipLines': '{n}行',
398
+ 'paste.folded': '{표} — 已折起。发送时会原样展开。',
399
+ 'paste.pasted': '已粘贴 {n} 行 — 按 Enter 一次发送',
347
400
  'run.thinking': '思考中…',
348
401
  'run.thinkingChars': '思考中… {n}字',
349
402
  'run.turnFoot': '{초}秒 · 工具{n}次 · ↑{입력} ↓{출력}',
350
403
  'run.bye': '结束。',
351
404
  'run.byeStats': '模型调用{n}次 · 工具耗时{초}秒 · ↑{입력} ↓{출력}',
352
405
  'run.notMade': '— 没有被创建',
406
+ 'store.notSaving': '这次对话没有写入文件({까닭})— 已丢失 {n} 行。现在关闭窗口就无法继续。',
353
407
 
354
408
  'stage.plan': '先做判断',
355
409
  'stage.work': '接着做',
@@ -368,6 +422,7 @@ export const zh = {
368
422
  'status.keyStore': '密钥存放',
369
423
  'status.rules': '规则',
370
424
  'status.noRules': '无(可用 /init 建一个)',
425
+ 'status.rulesUnread': '{이름} 存在但读不了({까닭})— 本文件夹的规则没有生效',
371
426
  'status.caps': '支持',
372
427
  'status.capTools': '工具',
373
428
  'status.capStream': '流式',
@@ -414,4 +469,5 @@ export const zh = {
414
469
  'common.seeHelp': '用 /help 看命令列表',
415
470
  'common.yes': '是',
416
471
  'common.no': '否',
472
+ 'common.cfgSaveFailed': '设置没能写入文件({왜})— 本次有效,重开就会恢复原样。',
417
473
  };