@serjm/deepseek-code 0.3.2 → 0.4.1
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.
- package/CHANGELOG.md +29 -0
- package/README.md +12 -0
- package/README.ru.md +12 -0
- package/dist/cli/headless.d.ts.map +1 -1
- package/dist/cli/headless.js +2 -0
- package/dist/cli/headless.js.map +1 -1
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +248 -21
- package/dist/commands/index.js.map +1 -1
- package/dist/core/agent-loop.d.ts +26 -1
- package/dist/core/agent-loop.d.ts.map +1 -1
- package/dist/core/agent-loop.js +157 -4
- package/dist/core/agent-loop.js.map +1 -1
- package/dist/core/i18n.d.ts +2 -0
- package/dist/core/i18n.d.ts.map +1 -1
- package/dist/core/i18n.js +6 -0
- package/dist/core/i18n.js.map +1 -1
- package/dist/core/metrics.d.ts +43 -0
- package/dist/core/metrics.d.ts.map +1 -1
- package/dist/core/metrics.js +170 -6
- package/dist/core/metrics.js.map +1 -1
- package/dist/tools/chrome.js +53 -53
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +30 -8
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/types.d.ts +28 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +10 -0
- package/dist/tools/types.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +13 -1
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/app.d.ts.map +1 -1
- package/dist/ui/app.js +46 -1
- package/dist/ui/app.js.map +1 -1
- package/dist/ui/input-bar.d.ts.map +1 -1
- package/dist/ui/input-bar.js +268 -70
- package/dist/ui/input-bar.js.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.4.1 — Update Visibility
|
|
4
|
+
|
|
5
|
+
### New Features
|
|
6
|
+
- Added `/changelog` command to show release notes inside the CLI.
|
|
7
|
+
- Added `/update-check` command to check the latest published npm version.
|
|
8
|
+
|
|
9
|
+
### Improvements
|
|
10
|
+
- Updated changelog notes now reflect that `/changelog` and `/update-check` are available.
|
|
11
|
+
|
|
12
|
+
## 0.4.0 — Stability & UX Release
|
|
13
|
+
|
|
14
|
+
### New Features
|
|
15
|
+
- **Task Budget Guard**: `/budget audit`, `/budget small`, `/budget status`, `/budget off`.
|
|
16
|
+
- **Git Files section in Execution Summary**: changed during run, new untracked, dirty before run.
|
|
17
|
+
- **Interactive `/lang` picker** with Русский, English, 中文.
|
|
18
|
+
- **Runtime language enforcement** based on selected locale.
|
|
19
|
+
|
|
20
|
+
### Improvements
|
|
21
|
+
- **Russian `/help`** output.
|
|
22
|
+
- **Honest reports**: tool results now include `changed`/`verified`/`changedFiles` metadata.
|
|
23
|
+
- **InputBar Home/End** navigation.
|
|
24
|
+
- **Alt+Enter** newline fallback for Windows terminals.
|
|
25
|
+
- **Improved multiline paste/cursor editing** stability.
|
|
26
|
+
|
|
27
|
+
### Notes
|
|
28
|
+
- `Shift+Enter` may be indistinguishable from `Enter` in some Windows terminals. Use `Alt+Enter` for a new line.
|
|
29
|
+
- `/changelog` and `/update-check` are now available in the CLI.
|
package/README.md
CHANGED
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
+
## What's new in 0.4.0
|
|
24
|
+
|
|
25
|
+
- Stability and honest reporting improvements.
|
|
26
|
+
- `/budget` commands to limit runaway agent loops.
|
|
27
|
+
- Git Files section in Execution Summary.
|
|
28
|
+
- Interactive `/lang` picker and runtime response language.
|
|
29
|
+
- InputBar Home/End and Alt+Enter newline fallback.
|
|
30
|
+
|
|
31
|
+
See [CHANGELOG.md](./CHANGELOG.md) for details.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
23
35
|
## The Short Version
|
|
24
36
|
|
|
25
37
|
DeepSeek Code is a terminal-first AI coding agent. It reads your project, edits files, runs commands, reviews code, remembers context, and can automate Chrome when a task needs a browser.
|
package/README.ru.md
CHANGED
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
+
## Что нового в 0.4.0
|
|
24
|
+
|
|
25
|
+
- Улучшена стабильность и честность отчётов.
|
|
26
|
+
- `/budget` команды ограничивают runaway tool/API calls.
|
|
27
|
+
- Execution Summary показывает Files: changed/untracked/dirty before run.
|
|
28
|
+
- `/lang` picker и ответы на выбранном языке.
|
|
29
|
+
- InputBar: Home/End и Alt+Enter для новой строки.
|
|
30
|
+
|
|
31
|
+
Подробнее в [CHANGELOG.md](./CHANGELOG.md).
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
23
35
|
## Коротко
|
|
24
36
|
|
|
25
37
|
DeepSeek Code — это AI-агент для разработки прямо в терминале. Он читает проект, редактирует файлы, запускает команды, делает code review, запоминает контекст и умеет управлять Chrome, когда задача выходит за пределы кода.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.d.ts","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headless.d.ts","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CA6HzB"}
|
package/dist/cli/headless.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { loadConfig } from '../config/loader.js';
|
|
2
2
|
import { AgentLoop } from '../core/agent-loop.js';
|
|
3
3
|
import { saveSession, writeExecutionBundle, writeSessionHandoff } from '../core/session.js';
|
|
4
|
+
import { AUDIT_BUDGET_PRESET } from '../tools/types.js';
|
|
4
5
|
export async function headlessMode(prompt, options) {
|
|
5
6
|
const startTime = Date.now();
|
|
6
7
|
const config = await loadConfig();
|
|
@@ -12,6 +13,7 @@ export async function headlessMode(prompt, options) {
|
|
|
12
13
|
const agent = new AgentLoop(config, {
|
|
13
14
|
approvalMode,
|
|
14
15
|
cwd: process.cwd(),
|
|
16
|
+
budget: AUDIT_BUDGET_PRESET,
|
|
15
17
|
onApprovalRequest: async (toolName) => {
|
|
16
18
|
if (approvalMode === 'plan') {
|
|
17
19
|
// In plan mode, only reject tools that need approval (write/edit/bash)
|
package/dist/cli/headless.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.js","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"headless.js","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ChatMessage } from '../api/index.js';
|
|
|
2
2
|
import type { DeepSeekConfig, ApprovalMode } from '../config/defaults.js';
|
|
3
3
|
import type { MetricsCollector } from '../core/metrics.js';
|
|
4
4
|
import type { SetupStep } from '../ui/setup-wizard.js';
|
|
5
|
+
import type { TaskBudget } from '../tools/types.js';
|
|
5
6
|
export interface SlashCommandContext {
|
|
6
7
|
config: DeepSeekConfig;
|
|
7
8
|
approvalMode: ApprovalMode;
|
|
@@ -13,10 +14,16 @@ export interface SlashCommandContext {
|
|
|
13
14
|
onThemePicker?: () => void;
|
|
14
15
|
/** Called when /model is entered without arguments — opens interactive picker */
|
|
15
16
|
onModelPicker?: () => void;
|
|
17
|
+
/** Called when /lang is entered without arguments — opens interactive picker */
|
|
18
|
+
onLangPicker?: () => void;
|
|
16
19
|
/** Show a transient service notice (does NOT add to chat messages, does NOT break empty-state) */
|
|
17
20
|
addServiceNotice?: (text: string) => void;
|
|
18
21
|
/** Returns current session metrics (tokens, cost, tool calls) */
|
|
19
22
|
getMetrics?: () => MetricsCollector | undefined;
|
|
23
|
+
/** Returns current budget (undefined means unlimited) */
|
|
24
|
+
getBudget?: () => TaskBudget | undefined;
|
|
25
|
+
/** Sets the budget for the next agent run */
|
|
26
|
+
setBudget?: (budget: TaskBudget | undefined) => void;
|
|
20
27
|
}
|
|
21
28
|
export interface CommandEntry {
|
|
22
29
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAgBlD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAgBlD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAItD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAKnD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,cAAc,CAAA;IACtB,YAAY,EAAE,YAAY,CAAA;IAC1B,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,WAAW,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;IAChE,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3D,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,gFAAgF;IAChF,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,kGAAkG;IAClG,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,iEAAiE;IACjE,UAAU,CAAC,EAAE,MAAM,gBAAgB,GAAG,SAAS,CAAA;IAC/C,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,UAAU,GAAG,SAAS,CAAA;IACxC,6CAA6C;IAC7C,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,KAAK,IAAI,CAAA;CACrD;AA0pCD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,CAAC,GAAG,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACvE;AAED,eAAO,MAAM,QAAQ,EAAE,YAAY,EAkClC,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,EAA8B,CAAA;AAEhE,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAEnD,CAAA;AAgBD,wBAAsB,mBAAmB,CAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAapG"}
|
package/dist/commands/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { saveConfig } from '../config/loader.js';
|
|
|
18
18
|
import { getDefaultTools, getToolsForMode } from '../tools/registry.js';
|
|
19
19
|
import { browserTest, getLastBrowserTestResult, browserRealTest } from '../tools/chrome.js';
|
|
20
20
|
import { chromeManager } from '../tools/chrome-manager.js';
|
|
21
|
+
import { AUDIT_BUDGET_PRESET } from '../tools/types.js';
|
|
21
22
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
22
23
|
function generateFollowups(lastContent) {
|
|
23
24
|
const suggestions = [];
|
|
@@ -43,28 +44,87 @@ function generateFollowups(lastContent) {
|
|
|
43
44
|
}
|
|
44
45
|
return suggestions;
|
|
45
46
|
}
|
|
47
|
+
// ─── Russian descriptions for commands ──────────────────────────────────────
|
|
48
|
+
const RU_DESCRIPTIONS = {
|
|
49
|
+
'/help': 'Показать эту справку',
|
|
50
|
+
'/setup': 'Настройки: язык, API-ключ, тема, режим',
|
|
51
|
+
'/remember': 'Сохранить в память: /remember <текст>',
|
|
52
|
+
'/forget': 'Удалить из памяти по поиску',
|
|
53
|
+
'/memory': 'Показать все сохранённые записи',
|
|
54
|
+
'/compress': 'Сжать историю чата',
|
|
55
|
+
'/checkpoint': 'Создать git-чекпоинт',
|
|
56
|
+
'/restore': 'Список или восстановление чекпоинта: /restore [id]',
|
|
57
|
+
'/mcp': 'MCP-серверы: /mcp list | connect',
|
|
58
|
+
'/skills': 'Список или описание навыка',
|
|
59
|
+
'/agents': 'Список активных под-агентов',
|
|
60
|
+
'/review': 'Ревью кода: /review all|diff|auto',
|
|
61
|
+
'/sandbox': 'Запустить команду в sandbox',
|
|
62
|
+
'/git': 'Git: /git commit|branch|diff|status',
|
|
63
|
+
'/loop': 'Планировщик: /loop <интервал> <задача>',
|
|
64
|
+
'/stats': 'Статистика сессии с токенами',
|
|
65
|
+
'/theme': 'Сменить тему или открыть выбор',
|
|
66
|
+
'/model': 'Сменить модель или открыть выбор: /model [id]',
|
|
67
|
+
'/lang': 'Сменить язык: /lang en|ru|zh',
|
|
68
|
+
'/extensions': 'Список установленных расширений',
|
|
69
|
+
'/followup': 'Сгенерировать предложения продолжения',
|
|
70
|
+
'/logs': 'Показать последние логи',
|
|
71
|
+
'/plan': 'Обзор возможностей',
|
|
72
|
+
'/tools': 'Показать доступные инструменты и статус',
|
|
73
|
+
'/capabilities': 'Полная матрица возможностей',
|
|
74
|
+
'/browser-test': 'Запустить тест Chrome',
|
|
75
|
+
'/browser-real-test': 'Smoke-тест реальных сайтов',
|
|
76
|
+
'/last-browser-test': 'Показать последний отчёт browser-test',
|
|
77
|
+
'/chrome': 'Режим Chrome: --headed|--headless|-s',
|
|
78
|
+
'/budget': 'Бюджет: /budget status|off|audit|small',
|
|
79
|
+
'/changelog': 'Показать список изменений',
|
|
80
|
+
'/update-check': 'Проверить новую версию',
|
|
81
|
+
};
|
|
82
|
+
function getDescription(name) {
|
|
83
|
+
if (i18n.getLocale() === 'ru') {
|
|
84
|
+
return RU_DESCRIPTIONS[name] ?? COMMANDS.find(c => c.name === name)?.description ?? '';
|
|
85
|
+
}
|
|
86
|
+
return COMMANDS.find(c => c.name === name)?.description ?? '';
|
|
87
|
+
}
|
|
46
88
|
// ─── Command handlers ────────────────────────────────────────────────────────
|
|
47
89
|
async function cmdHelp(ctx) {
|
|
48
|
-
const
|
|
90
|
+
const locale = i18n.getLocale();
|
|
91
|
+
const helpLine = (left, right) => `${left}\n ${right}`;
|
|
92
|
+
const lines = [`${i18n.t('helpCommands')}:`];
|
|
49
93
|
for (const cmd of COMMANDS) {
|
|
50
94
|
if (cmd.name === '/language')
|
|
51
95
|
continue;
|
|
52
|
-
lines.push(
|
|
53
|
-
}
|
|
54
|
-
lines.push('', '
|
|
55
|
-
lines.push('', '
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
96
|
+
lines.push('', helpLine(cmd.name, getDescription(cmd.name)));
|
|
97
|
+
}
|
|
98
|
+
lines.push('', helpLine('/clear', locale === 'ru' ? 'Очистить историю чата (с подтверждением)' : 'Clear chat history (with confirmation)'));
|
|
99
|
+
lines.push('', `${i18n.t('helpKeyboard')}:`);
|
|
100
|
+
if (locale === 'ru') {
|
|
101
|
+
lines.push('', helpLine('Ctrl+L', 'Очистить чат (открывает диалог подтверждения)'));
|
|
102
|
+
lines.push('', helpLine('Ctrl+C', 'Отменить выполнение / двойное нажатие для выхода'));
|
|
103
|
+
lines.push('', helpLine('Alt+V', 'Вставить изображение из буфера (только vision модели)'));
|
|
104
|
+
if (platform() === 'win32') {
|
|
105
|
+
lines.push('', ' Для Windows: Если Alt+V не работает, убедитесь, что терминал передаёт');
|
|
106
|
+
lines.push(' правильные Alt/Meta-последовательности. Windows Terminal ≥ 1.14 работает корректно.');
|
|
107
|
+
lines.push(' В старых терминалах попробуйте: Настройки → Совместимость → "Использовать Alt как Meta".');
|
|
108
|
+
}
|
|
109
|
+
lines.push('', helpLine('Tab', 'Цикл режимов: plan → default → auto-edit → turbo'));
|
|
110
|
+
lines.push('', helpLine('PageUp / PageDown', 'Прокрутка истории чата'));
|
|
111
|
+
lines.push('', helpLine('End', 'Перейти к последнему сообщению'));
|
|
112
|
+
lines.push('', helpLine('Shift+Enter / Alt+Enter', 'Новая строка в поле ввода'));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
lines.push('', helpLine('Ctrl+L', 'Clear chat (opens confirmation dialog)'));
|
|
116
|
+
lines.push('', helpLine('Ctrl+C', 'Cancel running agent / double-tap to exit'));
|
|
117
|
+
lines.push('', helpLine('Alt+V', 'Paste image from clipboard (vision models only)'));
|
|
118
|
+
if (platform() === 'win32') {
|
|
119
|
+
lines.push('', ' Windows note: If Alt+V does not work, ensure your terminal sends');
|
|
120
|
+
lines.push(' proper Alt/Meta sequences. Windows Terminal ≥ 1.14 works correctly.');
|
|
121
|
+
lines.push(' In older terminals try: Settings → Compatibility → "Use Alt as Meta key".');
|
|
122
|
+
}
|
|
123
|
+
lines.push('', helpLine('Tab', 'Cycle approval mode: plan → default → auto-edit → turbo'));
|
|
124
|
+
lines.push('', helpLine('PageUp / PageDown', 'Scroll chat history'));
|
|
125
|
+
lines.push('', helpLine('End', 'Jump to latest message'));
|
|
126
|
+
lines.push('', helpLine('Shift+Enter / Alt+Enter', 'Insert newline in input'));
|
|
127
|
+
}
|
|
68
128
|
ctx.setMessages(prev => [...prev, { role: 'assistant', content: lines.join('\n') }]);
|
|
69
129
|
return true;
|
|
70
130
|
}
|
|
@@ -617,10 +677,16 @@ async function cmdModel(ctx, input) {
|
|
|
617
677
|
async function cmdLang(ctx, input) {
|
|
618
678
|
const code = input.split(/\s+/).pop()?.toLowerCase();
|
|
619
679
|
if (!code || !['en', 'ru', 'zh'].includes(code)) {
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
680
|
+
// Open interactive picker if available, fallback to usage text
|
|
681
|
+
if (ctx.onLangPicker) {
|
|
682
|
+
ctx.onLangPicker();
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
ctx.setMessages(prev => [...prev, {
|
|
686
|
+
role: 'assistant',
|
|
687
|
+
content: 'Usage: `/lang en|ru|zh`',
|
|
688
|
+
}]);
|
|
689
|
+
}
|
|
624
690
|
return true;
|
|
625
691
|
}
|
|
626
692
|
i18n.setLocale(code);
|
|
@@ -904,6 +970,164 @@ async function cmdCapabilities(ctx) {
|
|
|
904
970
|
}]);
|
|
905
971
|
return true;
|
|
906
972
|
}
|
|
973
|
+
// ─── Budget command handler ──────────────────────────────────────────────────
|
|
974
|
+
async function cmdBudget(ctx, input) {
|
|
975
|
+
const sub = input.slice('/budget'.length).trim();
|
|
976
|
+
const notice = ctx.addServiceNotice ?? ((text) => {
|
|
977
|
+
ctx.setMessages(prev => [...prev, { role: 'assistant', content: text }]);
|
|
978
|
+
});
|
|
979
|
+
if (sub === 'status') {
|
|
980
|
+
const budget = ctx.getBudget?.();
|
|
981
|
+
if (!budget) {
|
|
982
|
+
notice('Budget: off');
|
|
983
|
+
}
|
|
984
|
+
else {
|
|
985
|
+
const prefix = 'Budget: active';
|
|
986
|
+
const lines = [
|
|
987
|
+
prefix,
|
|
988
|
+
`maxToolCalls: ${budget.maxToolCalls}`,
|
|
989
|
+
`maxApiCalls: ${budget.maxApiCalls}`,
|
|
990
|
+
`maxReadFiles: ${budget.maxReadFiles}`,
|
|
991
|
+
`maxShellCommands: ${budget.maxShellCommands}`,
|
|
992
|
+
];
|
|
993
|
+
notice(lines.join('\n'));
|
|
994
|
+
}
|
|
995
|
+
return true;
|
|
996
|
+
}
|
|
997
|
+
if (sub === 'off') {
|
|
998
|
+
ctx.setBudget?.(undefined);
|
|
999
|
+
notice('Budget: off');
|
|
1000
|
+
return true;
|
|
1001
|
+
}
|
|
1002
|
+
if (sub === 'audit' || sub === 'small') {
|
|
1003
|
+
ctx.setBudget?.({ ...AUDIT_BUDGET_PRESET });
|
|
1004
|
+
const lines = [
|
|
1005
|
+
'Budget: audit enabled',
|
|
1006
|
+
`maxToolCalls: ${AUDIT_BUDGET_PRESET.maxToolCalls}`,
|
|
1007
|
+
`maxApiCalls: ${AUDIT_BUDGET_PRESET.maxApiCalls}`,
|
|
1008
|
+
`maxReadFiles: ${AUDIT_BUDGET_PRESET.maxReadFiles}`,
|
|
1009
|
+
`maxShellCommands: ${AUDIT_BUDGET_PRESET.maxShellCommands}`,
|
|
1010
|
+
];
|
|
1011
|
+
notice(lines.join('\n'));
|
|
1012
|
+
return true;
|
|
1013
|
+
}
|
|
1014
|
+
notice('Usage: /budget status|off|audit|small');
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
// ─── Changelog and Update Check ──────────────────────────────────────────────
|
|
1018
|
+
function semverCompare(a, b) {
|
|
1019
|
+
const pa = a.split('.').map(Number);
|
|
1020
|
+
const pb = b.split('.').map(Number);
|
|
1021
|
+
for (let i = 0; i < 3; i++) {
|
|
1022
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
1023
|
+
return 1;
|
|
1024
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
1025
|
+
return -1;
|
|
1026
|
+
}
|
|
1027
|
+
return 0;
|
|
1028
|
+
}
|
|
1029
|
+
async function cmdChangelog(ctx) {
|
|
1030
|
+
const { readFileSync } = await import('node:fs');
|
|
1031
|
+
const { resolve, dirname } = await import('node:path');
|
|
1032
|
+
const { fileURLToPath } = await import('node:url');
|
|
1033
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
1034
|
+
const __dirname = dirname(__filename);
|
|
1035
|
+
const changelogPath = resolve(__dirname, '../../CHANGELOG.md');
|
|
1036
|
+
try {
|
|
1037
|
+
const content = readFileSync(changelogPath, 'utf-8');
|
|
1038
|
+
// Show up to 4000 chars to avoid overwhelming the chat
|
|
1039
|
+
const truncated = content.length > 4000 ? content.slice(0, 3997) + '...' : content;
|
|
1040
|
+
ctx.setMessages(prev => [...prev, {
|
|
1041
|
+
role: 'assistant',
|
|
1042
|
+
content: truncated,
|
|
1043
|
+
}]);
|
|
1044
|
+
}
|
|
1045
|
+
catch {
|
|
1046
|
+
ctx.setMessages(prev => [...prev, {
|
|
1047
|
+
role: 'assistant',
|
|
1048
|
+
content: 'CHANGELOG.md not found. Reinstall the package or check your installation.',
|
|
1049
|
+
}]);
|
|
1050
|
+
}
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
async function cmdUpdateCheck(ctx) {
|
|
1054
|
+
const { readFileSync } = await import('node:fs');
|
|
1055
|
+
const { resolve, dirname } = await import('node:path');
|
|
1056
|
+
const { fileURLToPath } = await import('node:url');
|
|
1057
|
+
const { get } = await import('node:https');
|
|
1058
|
+
// Get current version from package.json
|
|
1059
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
1060
|
+
const __dirname = dirname(__filename);
|
|
1061
|
+
const pkgPath = resolve(__dirname, '../../package.json');
|
|
1062
|
+
let currentVersion;
|
|
1063
|
+
try {
|
|
1064
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
1065
|
+
currentVersion = pkg.version;
|
|
1066
|
+
}
|
|
1067
|
+
catch {
|
|
1068
|
+
ctx.setMessages(prev => [...prev, {
|
|
1069
|
+
role: 'assistant',
|
|
1070
|
+
content: 'Could not read package version. Check your installation.',
|
|
1071
|
+
}]);
|
|
1072
|
+
return true;
|
|
1073
|
+
}
|
|
1074
|
+
// Check npm registry for latest version
|
|
1075
|
+
try {
|
|
1076
|
+
const latest = await new Promise((resolve, reject) => {
|
|
1077
|
+
const url = 'https://registry.npmjs.org/@serjm%2Fdeepseek-code/latest';
|
|
1078
|
+
const req = get(url, { timeout: 10000 }, (res) => {
|
|
1079
|
+
let data = '';
|
|
1080
|
+
res.on('data', chunk => { data += chunk; });
|
|
1081
|
+
res.on('end', () => {
|
|
1082
|
+
try {
|
|
1083
|
+
const json = JSON.parse(data);
|
|
1084
|
+
resolve(json.version);
|
|
1085
|
+
}
|
|
1086
|
+
catch {
|
|
1087
|
+
reject(new Error('Invalid response from registry'));
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
});
|
|
1091
|
+
req.on('error', reject);
|
|
1092
|
+
req.on('timeout', () => {
|
|
1093
|
+
req.destroy();
|
|
1094
|
+
reject(new Error('Request timed out'));
|
|
1095
|
+
});
|
|
1096
|
+
});
|
|
1097
|
+
const cmp = semverCompare(latest, currentVersion);
|
|
1098
|
+
if (cmp > 0) {
|
|
1099
|
+
ctx.setMessages(prev => [...prev, {
|
|
1100
|
+
role: 'assistant',
|
|
1101
|
+
content: [
|
|
1102
|
+
'## Update available',
|
|
1103
|
+
'',
|
|
1104
|
+
`**Current:** ${currentVersion}`,
|
|
1105
|
+
`**Latest:** ${latest}`,
|
|
1106
|
+
'',
|
|
1107
|
+
'Run:',
|
|
1108
|
+
'```',
|
|
1109
|
+
'npm install -g @serjm/deepseek-code@latest',
|
|
1110
|
+
'```',
|
|
1111
|
+
'',
|
|
1112
|
+
'Run `/changelog` to see what\'s new.',
|
|
1113
|
+
].join('\n'),
|
|
1114
|
+
}]);
|
|
1115
|
+
}
|
|
1116
|
+
else {
|
|
1117
|
+
ctx.setMessages(prev => [...prev, {
|
|
1118
|
+
role: 'assistant',
|
|
1119
|
+
content: `You are up to date: **${currentVersion}**`,
|
|
1120
|
+
}]);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
catch {
|
|
1124
|
+
ctx.setMessages(prev => [...prev, {
|
|
1125
|
+
role: 'assistant',
|
|
1126
|
+
content: 'Could not check for updates. Try again later.',
|
|
1127
|
+
}]);
|
|
1128
|
+
}
|
|
1129
|
+
return true;
|
|
1130
|
+
}
|
|
907
1131
|
export const COMMANDS = [
|
|
908
1132
|
{ name: '/help', description: 'Show this help', handler: cmdHelp },
|
|
909
1133
|
{ name: '/setup', description: 'Settings: language, API key, theme, mode', handler: cmdSetup },
|
|
@@ -935,6 +1159,9 @@ export const COMMANDS = [
|
|
|
935
1159
|
{ name: '/browser-real-test', description: 'Smoke test on real websites', handler: cmdBrowserRealTest },
|
|
936
1160
|
{ name: '/last-browser-test', description: 'Show last browser test report', handler: cmdLastBrowserTest },
|
|
937
1161
|
{ name: '/chrome', description: 'Chrome mode: --headed|--headless|-s', handler: cmdChrome },
|
|
1162
|
+
{ name: '/budget', description: 'Budget: /budget status|off|audit|small', handler: cmdBudget },
|
|
1163
|
+
{ name: '/changelog', description: 'Show changelog', handler: cmdChangelog },
|
|
1164
|
+
{ name: '/update-check', description: 'Check latest npm version', handler: cmdUpdateCheck },
|
|
938
1165
|
];
|
|
939
1166
|
export const COMMAND_NAMES = COMMANDS.map(c => c.name);
|
|
940
1167
|
export const COMMAND_MAP = new Map(COMMANDS.map(c => [c.name, c.description]));
|