@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/dist/tools/chrome.js
CHANGED
|
@@ -576,26 +576,26 @@ export function getLastBrowserTestResult() {
|
|
|
576
576
|
* Returns the server and the URL.
|
|
577
577
|
*/
|
|
578
578
|
async function startTestServer() {
|
|
579
|
-
const html = `<!DOCTYPE html>
|
|
580
|
-
<html lang="en">
|
|
581
|
-
<head><meta charset="UTF-8"><title>Browser Test Page</title></head>
|
|
582
|
-
<body>
|
|
583
|
-
<h1 id="test-title">Browser Test</h1>
|
|
584
|
-
<p id="test-paragraph">Hello, world!</p>
|
|
585
|
-
<button id="test-button" onclick="document.getElementById('test-output').textContent='clicked'">Click Me</button>
|
|
586
|
-
<input id="test-input" type="text" placeholder="Type here">
|
|
587
|
-
<label><input type="checkbox" id="test-checkbox" checked> Checkbox</label>
|
|
588
|
-
<label><input type="radio" name="test-radio" id="radio-1" checked> Radio 1</label>
|
|
589
|
-
<label><input type="radio" name="test-radio" id="radio-2"> Radio 2</label>
|
|
590
|
-
<div id="test-output"></div>
|
|
591
|
-
<script>
|
|
592
|
-
console.log('Browser test page loaded');
|
|
593
|
-
console.error('Test error message');
|
|
594
|
-
localStorage.setItem('test-key', 'test-value');
|
|
595
|
-
sessionStorage.setItem('session-key', 'session-value');
|
|
596
|
-
document.cookie = 'test-cookie=chocolate-chip; path=/';
|
|
597
|
-
</script>
|
|
598
|
-
</body>
|
|
579
|
+
const html = `<!DOCTYPE html>
|
|
580
|
+
<html lang="en">
|
|
581
|
+
<head><meta charset="UTF-8"><title>Browser Test Page</title></head>
|
|
582
|
+
<body>
|
|
583
|
+
<h1 id="test-title">Browser Test</h1>
|
|
584
|
+
<p id="test-paragraph">Hello, world!</p>
|
|
585
|
+
<button id="test-button" onclick="document.getElementById('test-output').textContent='clicked'">Click Me</button>
|
|
586
|
+
<input id="test-input" type="text" placeholder="Type here">
|
|
587
|
+
<label><input type="checkbox" id="test-checkbox" checked> Checkbox</label>
|
|
588
|
+
<label><input type="radio" name="test-radio" id="radio-1" checked> Radio 1</label>
|
|
589
|
+
<label><input type="radio" name="test-radio" id="radio-2"> Radio 2</label>
|
|
590
|
+
<div id="test-output"></div>
|
|
591
|
+
<script>
|
|
592
|
+
console.log('Browser test page loaded');
|
|
593
|
+
console.error('Test error message');
|
|
594
|
+
localStorage.setItem('test-key', 'test-value');
|
|
595
|
+
sessionStorage.setItem('session-key', 'session-value');
|
|
596
|
+
document.cookie = 'test-cookie=chocolate-chip; path=/';
|
|
597
|
+
</script>
|
|
598
|
+
</body>
|
|
599
599
|
</html>`;
|
|
600
600
|
return new Promise((resolve, reject) => {
|
|
601
601
|
const server = createServer((_req, res) => {
|
|
@@ -668,23 +668,23 @@ export async function browserTest(options) {
|
|
|
668
668
|
}
|
|
669
669
|
if (!testUrl) {
|
|
670
670
|
// Fall back to data: URL for basic tests, skip storage/network
|
|
671
|
-
const dataUrl = `data:text/html,<!DOCTYPE html>
|
|
672
|
-
<html lang="en">
|
|
673
|
-
<head><meta charset="UTF-8"><title>Browser Test Page</title></head>
|
|
674
|
-
<body>
|
|
675
|
-
<h1 id="test-title">Browser Test</h1>
|
|
676
|
-
<p id="test-paragraph">Hello, world!</p>
|
|
677
|
-
<button id="test-button" onclick="document.getElementById('test-output').textContent='clicked'">Click Me</button>
|
|
678
|
-
<input id="test-input" type="text" placeholder="Type here">
|
|
679
|
-
<label><input type="checkbox" id="test-checkbox" checked> Checkbox</label>
|
|
680
|
-
<label><input type="radio" name="test-radio" id="radio-1" checked> Radio 1</label>
|
|
681
|
-
<label><input type="radio" name="test-radio" id="radio-2"> Radio 2</label>
|
|
682
|
-
<div id="test-output"></div>
|
|
683
|
-
<script>
|
|
684
|
-
console.log('Browser test page loaded');
|
|
685
|
-
console.error('Test error message');
|
|
686
|
-
</script>
|
|
687
|
-
</body>
|
|
671
|
+
const dataUrl = `data:text/html,<!DOCTYPE html>
|
|
672
|
+
<html lang="en">
|
|
673
|
+
<head><meta charset="UTF-8"><title>Browser Test Page</title></head>
|
|
674
|
+
<body>
|
|
675
|
+
<h1 id="test-title">Browser Test</h1>
|
|
676
|
+
<p id="test-paragraph">Hello, world!</p>
|
|
677
|
+
<button id="test-button" onclick="document.getElementById('test-output').textContent='clicked'">Click Me</button>
|
|
678
|
+
<input id="test-input" type="text" placeholder="Type here">
|
|
679
|
+
<label><input type="checkbox" id="test-checkbox" checked> Checkbox</label>
|
|
680
|
+
<label><input type="radio" name="test-radio" id="radio-1" checked> Radio 1</label>
|
|
681
|
+
<label><input type="radio" name="test-radio" id="radio-2"> Radio 2</label>
|
|
682
|
+
<div id="test-output"></div>
|
|
683
|
+
<script>
|
|
684
|
+
console.log('Browser test page loaded');
|
|
685
|
+
console.error('Test error message');
|
|
686
|
+
</script>
|
|
687
|
+
</body>
|
|
688
688
|
</html>`;
|
|
689
689
|
const baseArgs = { url: dataUrl, sameTab: true, timeout: 30000 };
|
|
690
690
|
async function runDataStep(name, action, extraArgs) {
|
|
@@ -1026,22 +1026,22 @@ function buildRealTestReport(results, totalCalls, totalSites) {
|
|
|
1026
1026
|
}
|
|
1027
1027
|
export const chromeTool = {
|
|
1028
1028
|
name: 'chrome',
|
|
1029
|
-
description: `Control a real browser through a native Chrome runtime.
|
|
1030
|
-
Use it for UI validation, rendered DOM inspection, console and network debugging,
|
|
1031
|
-
screenshots, and multi-step browser workflows when terminal tools are not enough.
|
|
1032
|
-
If the task mentions localhost pages, forms, browser bugs, screenshots, rendered state,
|
|
1033
|
-
console output, or network requests, this is the primary tool.
|
|
1034
|
-
|
|
1035
|
-
Examples:
|
|
1036
|
-
- { "action": "open", "url": "https://example.com" }
|
|
1037
|
-
- { "action": "text", "url": "https://example.com", "selector": "h1" }
|
|
1038
|
-
- { "action": "click", "url": "https://example.com", "selector": ".submit-btn" }
|
|
1039
|
-
- { "action": "fill", "url": "https://example.com/login", "selector": "#email", "text": "user@example.com" }
|
|
1040
|
-
- { "action": "eval", "url": "https://example.com", "code": "document.title" }
|
|
1041
|
-
- { "action": "network", "url": "https://example.com", "api": true }
|
|
1042
|
-
- { "action": "state" }
|
|
1043
|
-
- { "action": "shot", "url": "https://example.com", "output": "screenshot.png", "full": true }
|
|
1044
|
-
- Use "sameTab": true for multi-step flows in one tab.
|
|
1029
|
+
description: `Control a real browser through a native Chrome runtime.
|
|
1030
|
+
Use it for UI validation, rendered DOM inspection, console and network debugging,
|
|
1031
|
+
screenshots, and multi-step browser workflows when terminal tools are not enough.
|
|
1032
|
+
If the task mentions localhost pages, forms, browser bugs, screenshots, rendered state,
|
|
1033
|
+
console output, or network requests, this is the primary tool.
|
|
1034
|
+
|
|
1035
|
+
Examples:
|
|
1036
|
+
- { "action": "open", "url": "https://example.com" }
|
|
1037
|
+
- { "action": "text", "url": "https://example.com", "selector": "h1" }
|
|
1038
|
+
- { "action": "click", "url": "https://example.com", "selector": ".submit-btn" }
|
|
1039
|
+
- { "action": "fill", "url": "https://example.com/login", "selector": "#email", "text": "user@example.com" }
|
|
1040
|
+
- { "action": "eval", "url": "https://example.com", "code": "document.title" }
|
|
1041
|
+
- { "action": "network", "url": "https://example.com", "api": true }
|
|
1042
|
+
- { "action": "state" }
|
|
1043
|
+
- { "action": "shot", "url": "https://example.com", "output": "screenshot.png", "full": true }
|
|
1044
|
+
- Use "sameTab": true for multi-step flows in one tab.
|
|
1045
1045
|
- Use "headless": true for automation or CI-safe browser execution.`,
|
|
1046
1046
|
parameters: chromeParameters,
|
|
1047
1047
|
execute: async (args) => {
|
package/dist/tools/edit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAmB,MAAM,YAAY,CAAA;AAGvD,eAAO,MAAM,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAmB,MAAM,YAAY,CAAA;AAGvD,eAAO,MAAM,QAAQ,EAAE,IAoGtB,CAAA"}
|
package/dist/tools/edit.js
CHANGED
|
@@ -37,6 +37,18 @@ export const editTool = {
|
|
|
37
37
|
try {
|
|
38
38
|
assertPathInWorkspace(filePath);
|
|
39
39
|
const content = await readFile(filePath, 'utf-8');
|
|
40
|
+
// Check if old_string exists
|
|
41
|
+
const index = content.indexOf(oldString);
|
|
42
|
+
if (index === -1) {
|
|
43
|
+
return {
|
|
44
|
+
success: false,
|
|
45
|
+
output: '',
|
|
46
|
+
error: 'String not found in file',
|
|
47
|
+
changed: false,
|
|
48
|
+
verified: false,
|
|
49
|
+
changedFiles: [],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
40
52
|
if (replaceAll) {
|
|
41
53
|
const replaced = content.replaceAll(oldString, newString);
|
|
42
54
|
if (replaced === content) {
|
|
@@ -44,28 +56,35 @@ export const editTool = {
|
|
|
44
56
|
success: false,
|
|
45
57
|
output: '',
|
|
46
58
|
error: 'String not found in file',
|
|
59
|
+
changed: false,
|
|
60
|
+
verified: false,
|
|
61
|
+
changedFiles: [],
|
|
47
62
|
};
|
|
48
63
|
}
|
|
49
64
|
await writeFile(filePath, replaced, 'utf-8');
|
|
65
|
+
// Verify by re-reading
|
|
66
|
+
const writtenContent = await readFile(filePath, 'utf-8');
|
|
67
|
+
const verified = writtenContent === replaced;
|
|
50
68
|
return {
|
|
51
69
|
success: true,
|
|
52
70
|
output: `Replaced all occurrences in ${filePath}`,
|
|
71
|
+
changed: true,
|
|
72
|
+
verified,
|
|
73
|
+
changedFiles: [filePath],
|
|
53
74
|
};
|
|
54
75
|
}
|
|
55
76
|
else {
|
|
56
|
-
const index = content.indexOf(oldString);
|
|
57
|
-
if (index === -1) {
|
|
58
|
-
return {
|
|
59
|
-
success: false,
|
|
60
|
-
output: '',
|
|
61
|
-
error: 'String not found in file',
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
77
|
const replaced = content.replace(oldString, newString);
|
|
65
78
|
await writeFile(filePath, replaced, 'utf-8');
|
|
79
|
+
// Verify by re-reading
|
|
80
|
+
const writtenContent = await readFile(filePath, 'utf-8');
|
|
81
|
+
const verified = writtenContent === replaced;
|
|
66
82
|
return {
|
|
67
83
|
success: true,
|
|
68
84
|
output: `Successfully edited ${filePath}`,
|
|
85
|
+
changed: true,
|
|
86
|
+
verified,
|
|
87
|
+
changedFiles: [filePath],
|
|
69
88
|
};
|
|
70
89
|
}
|
|
71
90
|
}
|
|
@@ -74,6 +93,9 @@ export const editTool = {
|
|
|
74
93
|
success: false,
|
|
75
94
|
output: '',
|
|
76
95
|
error: `Failed to edit file: ${err.message}`,
|
|
96
|
+
changed: false,
|
|
97
|
+
verified: false,
|
|
98
|
+
changedFiles: [],
|
|
77
99
|
};
|
|
78
100
|
}
|
|
79
101
|
},
|
package/dist/tools/edit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,iFAAiF;IAC9F,UAAU,EAAE;QACV;YACE,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,uCAAuC;YACpD,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,2BAA2B;YACxC,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,sBAAsB;YACnC,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,mDAAmD;YAChE,QAAQ,EAAE,KAAK;SAChB;KACF;IACD,KAAK,CAAC,OAAO,CAAE,IAA6B;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAmB,CAAA;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAoB,CAAA;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAoB,CAAA;QAC3C,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAA;QAErC,IAAI,CAAC;YACH,qBAAqB,CAAC,QAAQ,CAAC,CAAA;YAC/B,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAEjD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;gBACzD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;oBACzB,OAAO;wBACL,OAAO,EAAE,KAAK;wBACd,MAAM,EAAE,EAAE;wBACV,KAAK,EAAE,0BAA0B;
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/types.d.ts
CHANGED
|
@@ -14,12 +14,40 @@ export interface ToolResult {
|
|
|
14
14
|
success: boolean;
|
|
15
15
|
output: string;
|
|
16
16
|
error?: string;
|
|
17
|
+
/** Whether the tool actually changed something (e.g., file written/modified) */
|
|
18
|
+
changed?: boolean;
|
|
19
|
+
/** Whether the change was verified by re-reading from disk */
|
|
20
|
+
verified?: boolean;
|
|
21
|
+
/** List of files that were changed */
|
|
22
|
+
changedFiles?: string[];
|
|
17
23
|
}
|
|
18
24
|
export type ApprovalRequirement = 'always' | 'auto' | 'never';
|
|
25
|
+
/**
|
|
26
|
+
* Budget limits for a task session.
|
|
27
|
+
* All values are optional — unset means unlimited.
|
|
28
|
+
* 0 is treated as "no limit" (falsy check).
|
|
29
|
+
*/
|
|
30
|
+
export interface TaskBudget {
|
|
31
|
+
/** Maximum total tool calls across all iterations */
|
|
32
|
+
maxToolCalls?: number;
|
|
33
|
+
/** Maximum API calls (round trips to model) */
|
|
34
|
+
maxApiCalls?: number;
|
|
35
|
+
/** Maximum iterations (overrides AgentLoopOptions.maxIterations if set) */
|
|
36
|
+
maxIterations?: number;
|
|
37
|
+
/** Maximum calls to read_file tool */
|
|
38
|
+
maxReadFiles?: number;
|
|
39
|
+
/** Maximum calls to shell/bash/run_shell_command tools */
|
|
40
|
+
maxShellCommands?: number;
|
|
41
|
+
}
|
|
19
42
|
export interface ToolDefinition {
|
|
20
43
|
tool: Tool;
|
|
21
44
|
approval: ApprovalRequirement;
|
|
22
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Preset budget for small/audit tasks (headless mode).
|
|
48
|
+
* Limits tool calls, API calls, read_file, and shell commands.
|
|
49
|
+
*/
|
|
50
|
+
export declare const AUDIT_BUDGET_PRESET: TaskBudget;
|
|
23
51
|
/**
|
|
24
52
|
* OpenAI-compatible tool format for DeepSeek API function calling.
|
|
25
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;AAE7D;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,mBAAmB,CAAC;CAC/B;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAKjC,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ,CAAC;YACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;SACpB,CAAC;KACH,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAE,WAAW,EAAE,cAAc,EAAE,GAAG,UAAU,EAAE,CA4B1E;AAKD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,aAAa,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyDzB"}
|
package/dist/tools/types.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset budget for small/audit tasks (headless mode).
|
|
3
|
+
* Limits tool calls, API calls, read_file, and shell commands.
|
|
4
|
+
*/
|
|
5
|
+
export const AUDIT_BUDGET_PRESET = {
|
|
6
|
+
maxToolCalls: 12,
|
|
7
|
+
maxApiCalls: 6,
|
|
8
|
+
maxReadFiles: 5,
|
|
9
|
+
maxShellCommands: 4,
|
|
10
|
+
};
|
|
1
11
|
/**
|
|
2
12
|
* Convert our internal ToolDefinition[] to OpenAI-compatible tool format.
|
|
3
13
|
*/
|
package/dist/tools/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAmB,MAAM,YAAY,CAAA;AAKvD,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,IAAI,EAAmB,MAAM,YAAY,CAAA;AAKvD,eAAO,MAAM,SAAS,EAAE,IA4DvB,CAAA"}
|
package/dist/tools/write.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { writeFile, mkdir } from 'node:fs/promises';
|
|
1
|
+
import { writeFile, readFile, mkdir } from 'node:fs/promises';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
3
|
import { assertPathInWorkspace } from './path-safety.js';
|
|
4
4
|
const MAX_FILE_SIZE = 1_048_576; // 1MB limit
|
|
@@ -28,15 +28,24 @@ export const writeTool = {
|
|
|
28
28
|
success: false,
|
|
29
29
|
output: '',
|
|
30
30
|
error: `File too large: ${content.length} bytes exceeds the maximum of ${MAX_FILE_SIZE} bytes (1MB). Use run_shell_command to write large files.`,
|
|
31
|
+
changed: false,
|
|
32
|
+
verified: false,
|
|
33
|
+
changedFiles: [],
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
try {
|
|
34
37
|
assertPathInWorkspace(filePath);
|
|
35
38
|
await mkdir(dirname(filePath), { recursive: true });
|
|
36
39
|
await writeFile(filePath, content, 'utf-8');
|
|
40
|
+
// Verify by re-reading the file
|
|
41
|
+
const writtenContent = await readFile(filePath, 'utf-8');
|
|
42
|
+
const verified = writtenContent === content;
|
|
37
43
|
return {
|
|
38
44
|
success: true,
|
|
39
45
|
output: `Successfully wrote ${content.length} bytes to ${filePath}`,
|
|
46
|
+
changed: true,
|
|
47
|
+
verified,
|
|
48
|
+
changedFiles: [filePath],
|
|
40
49
|
};
|
|
41
50
|
}
|
|
42
51
|
catch (err) {
|
|
@@ -44,6 +53,9 @@ export const writeTool = {
|
|
|
44
53
|
success: false,
|
|
45
54
|
output: '',
|
|
46
55
|
error: `Failed to write file: ${err.message}`,
|
|
56
|
+
changed: false,
|
|
57
|
+
verified: false,
|
|
58
|
+
changedFiles: [],
|
|
47
59
|
};
|
|
48
60
|
}
|
|
49
61
|
},
|
package/dist/tools/write.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,aAAa,GAAG,SAAS,CAAA,CAAC,YAAY;AAE5C,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,iFAAiF;IAC9F,UAAU,EAAE;QACV;YACE,IAAI,EAAE,WAAW;YACjB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,wCAAwC;YACrD,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,kCAAkC;YAC/C,QAAQ,EAAE,IAAI;SACf;KACF;IACD,KAAK,CAAC,OAAO,CAAE,IAA6B;QAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAmB,CAAA;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAiB,CAAA;QAEtC,mBAAmB;QACnB,IAAI,OAAO,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YACnC,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,mBAAmB,OAAO,CAAC,MAAM,iCAAiC,aAAa,2DAA2D;gBACjJ,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,KAAK;gBACf,YAAY,EAAE,EAAE;aACjB,CAAA;QACH,CAAC;QAED,IAAI,CAAC;YACH,qBAAqB,CAAC,QAAQ,CAAC,CAAA;YAC/B,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACnD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;YAE3C,gCAAgC;YAChC,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YACxD,MAAM,QAAQ,GAAG,cAAc,KAAK,OAAO,CAAA;YAE3C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,sBAAsB,OAAO,CAAC,MAAM,aAAa,QAAQ,EAAE;gBACnE,OAAO,EAAE,IAAI;gBACb,QAAQ;gBACR,YAAY,EAAE,CAAC,QAAQ,CAAC;aACzB,CAAA;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,EAAE;gBACV,KAAK,EAAE,yBAA0B,GAAa,CAAC,OAAO,EAAE;gBACxD,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,KAAK;gBACf,YAAY,EAAE,EAAE;aACjB,CAAA;QACH,CAAC;IACH,CAAC;CACF,CAAA"}
|
package/dist/ui/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/ui/app.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,uBAAuB,CAAA;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/ui/app.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,uBAAuB,CAAA;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAmB3D,UAAU,QAAQ;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,cAAc,CAAC;CACzB;AA4BD,wBAAgB,GAAG,CAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,QAAQ,2CAm/BjD"}
|
package/dist/ui/app.js
CHANGED
|
@@ -76,8 +76,10 @@ export function App({ config, options }) {
|
|
|
76
76
|
const [pendingImage, setPendingImage] = useState(null);
|
|
77
77
|
const [themePicker, setThemePicker] = useState(null);
|
|
78
78
|
const [modelPicker, setModelPicker] = useState(null);
|
|
79
|
+
const [langPicker, setLangPicker] = useState(null);
|
|
79
80
|
const [serviceNotice, setServiceNotice] = useState(null);
|
|
80
81
|
const serviceNoticeTimerRef = useRef(null);
|
|
82
|
+
const budgetRef = useRef(undefined);
|
|
81
83
|
const addServiceNotice = useCallback((text) => {
|
|
82
84
|
setServiceNotice(text);
|
|
83
85
|
if (serviceNoticeTimerRef.current)
|
|
@@ -209,6 +211,8 @@ export function App({ config, options }) {
|
|
|
209
211
|
setSetupStep,
|
|
210
212
|
addServiceNotice,
|
|
211
213
|
getMetrics: () => agentLoopRef.current?.getMetrics(),
|
|
214
|
+
getBudget: () => budgetRef.current,
|
|
215
|
+
setBudget: (budget) => { budgetRef.current = budget; },
|
|
212
216
|
onThemePicker: () => {
|
|
213
217
|
const themes = themeManager.listThemes();
|
|
214
218
|
const currentName = themeManager.theme.name;
|
|
@@ -219,6 +223,11 @@ export function App({ config, options }) {
|
|
|
219
223
|
const idx = DEEPSEEK_MODELS.findIndex(m => m.id === config.model);
|
|
220
224
|
setModelPicker({ selectedIndex: Math.max(0, idx) });
|
|
221
225
|
},
|
|
226
|
+
onLangPicker: () => {
|
|
227
|
+
const loc = i18n.listLocales();
|
|
228
|
+
const idx = loc.findIndex(l => l.code === i18n.getLocale());
|
|
229
|
+
setLangPicker({ selectedIndex: Math.max(0, idx) });
|
|
230
|
+
},
|
|
222
231
|
};
|
|
223
232
|
return executeSlashCommand(input, ctx);
|
|
224
233
|
}, [config, approvalMode, messages, addServiceNotice]);
|
|
@@ -282,6 +291,13 @@ export function App({ config, options }) {
|
|
|
282
291
|
];
|
|
283
292
|
setPendingImage(null);
|
|
284
293
|
}
|
|
294
|
+
// Show local diagnostic notice for large prompts (not sent to model)
|
|
295
|
+
const charCount = input.length;
|
|
296
|
+
const lineCount = (input.match(/\r\n|\r|\n/g) || []).length + 1;
|
|
297
|
+
if (charCount > 500 || lineCount > 5) {
|
|
298
|
+
const msg = i18n.t('promptSending').replace('{chars}', String(charCount)).replace('{lines}', String(lineCount));
|
|
299
|
+
addServiceNotice(msg);
|
|
300
|
+
}
|
|
285
301
|
const userMessage = { role: 'user', content: userContent };
|
|
286
302
|
setMessages(prev => [...prev, userMessage]);
|
|
287
303
|
setIsProcessing(true);
|
|
@@ -301,6 +317,7 @@ export function App({ config, options }) {
|
|
|
301
317
|
approvalMode,
|
|
302
318
|
cwd: process.cwd(),
|
|
303
319
|
signal: abortController.signal,
|
|
320
|
+
budget: budgetRef.current,
|
|
304
321
|
onToolCall: (tc) => {
|
|
305
322
|
const updatedCalls = [...prevToolCallsRef.current, tc];
|
|
306
323
|
prevToolCallsRef.current = updatedCalls;
|
|
@@ -672,6 +689,34 @@ export function App({ config, options }) {
|
|
|
672
689
|
}
|
|
673
690
|
return;
|
|
674
691
|
}
|
|
692
|
+
// Language picker: interactive selection
|
|
693
|
+
if (langPicker) {
|
|
694
|
+
if (key.escape) {
|
|
695
|
+
setLangPicker(null);
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
if (key.upArrow) {
|
|
699
|
+
setLangPicker(prev => prev ? { selectedIndex: Math.max(0, prev.selectedIndex - 1) } : null);
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
if (key.downArrow) {
|
|
703
|
+
const locales = i18n.listLocales();
|
|
704
|
+
setLangPicker(prev => prev ? { selectedIndex: Math.min(locales.length - 1, prev.selectedIndex + 1) } : null);
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
if (key.return) {
|
|
708
|
+
const locales = i18n.listLocales();
|
|
709
|
+
const chosen = locales[langPicker.selectedIndex];
|
|
710
|
+
if (chosen) {
|
|
711
|
+
i18n.setLocale(chosen.code);
|
|
712
|
+
saveConfig({ ...config, language: chosen.code }).catch(() => { });
|
|
713
|
+
setLangPicker(null);
|
|
714
|
+
addServiceNotice(`[lang] Язык изменён: ${chosen.name} (${chosen.code})`);
|
|
715
|
+
}
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
675
720
|
// ArrowUp/ArrowDown: scroll by 1 line, but only when InputBar is disabled (processing)
|
|
676
721
|
// When InputBar is active, arrows belong to input history/suggestions.
|
|
677
722
|
if (key.upArrow && isProcessing) {
|
|
@@ -832,7 +877,7 @@ export function App({ config, options }) {
|
|
|
832
877
|
langOptions,
|
|
833
878
|
modeOptions,
|
|
834
879
|
} })
|
|
835
|
-
: (_jsxs(Box, { flexDirection: 'column', flexGrow: 1, children: [_jsx(Logo, {}), _jsx(ChatView, { messages: messages, scrollOffset: chatScrollOffset, hasNewMessages: newMessagesWhilePaused }), serviceNotice && (_jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsx(Text, { color: colors.primary, children: serviceNotice }) })), themePicker && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.primary, children: [_jsx(Box, { marginLeft: 1, marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u043C\u0443" }) }), _jsx(Box, { marginLeft: 1, marginTop: 1, flexDirection: 'column', children: themePicker.themes.map((t, i) => (_jsx(Box, { children: _jsxs(Text, { color: i === themePicker.selectedIndex ? colors.primary : colors.textMuted, children: [i === themePicker.selectedIndex ? '▸ ' : ' ', t.name, t.name === themeManager.theme.name ? ' (текущая)' : ''] }) }, t.name))) }), _jsx(Box, { marginLeft: 1, marginBottom: 1, marginTop: 1, children: _jsx(Text, { color: colors.textMuted, children: "\u2191\u2193 \u2014 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430" }) })] })), modelPicker && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.primary, children: [_jsx(Box, { marginLeft: 1, marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u043E\u0434\u0435\u043B\u044C" }) }), _jsx(Box, { marginLeft: 1, marginTop: 1, flexDirection: 'column', children: DEEPSEEK_MODELS.map((m, i) => (_jsxs(Box, { flexDirection: 'column', children: [_jsxs(Text, { color: i === modelPicker.selectedIndex ? colors.primary : colors.textMuted, children: [i === modelPicker.selectedIndex ? '▸ ' : ' ', _jsx(Text, { bold: i === modelPicker.selectedIndex, children: m.label }), m.id === config.model ? _jsx(Text, { dimColor: true, children: " (\u0442\u0435\u043A\u0443\u0449\u0430\u044F)" }) : null] }), _jsxs(Text, { dimColor: true, children: [' ', m.description] })] }, m.id))) }), _jsx(Box, { marginLeft: 1, marginBottom: 1, marginTop: 1, children: _jsx(Text, { color: colors.textMuted, children: "\u2191\u2193 \u2014 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430" }) })] })), pendingApproval && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.warning, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: colors.warning, children: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u0432\u044B\u0437\u043E\u0432 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0430?" }) }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { bold: true, color: colors.text, children: pendingApproval.toolName }) }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { color: colors.textMuted, children: JSON.stringify(pendingApproval.args, null, 2).slice(0, 200) }) }), _jsxs(Box, { flexDirection: 'column', marginTop: 1, children: [[
|
|
880
|
+
: (_jsxs(Box, { flexDirection: 'column', flexGrow: 1, children: [_jsx(Logo, {}), _jsx(ChatView, { messages: messages, scrollOffset: chatScrollOffset, hasNewMessages: newMessagesWhilePaused }), serviceNotice && (_jsx(Box, { marginLeft: 2, marginBottom: 1, children: _jsx(Text, { color: colors.primary, children: serviceNotice }) })), themePicker && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.primary, children: [_jsx(Box, { marginLeft: 1, marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0435\u043C\u0443" }) }), _jsx(Box, { marginLeft: 1, marginTop: 1, flexDirection: 'column', children: themePicker.themes.map((t, i) => (_jsx(Box, { children: _jsxs(Text, { color: i === themePicker.selectedIndex ? colors.primary : colors.textMuted, children: [i === themePicker.selectedIndex ? '▸ ' : ' ', t.name, t.name === themeManager.theme.name ? ' (текущая)' : ''] }) }, t.name))) }), _jsx(Box, { marginLeft: 1, marginBottom: 1, marginTop: 1, children: _jsx(Text, { color: colors.textMuted, children: "\u2191\u2193 \u2014 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430" }) })] })), modelPicker && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.primary, children: [_jsx(Box, { marginLeft: 1, marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u043E\u0434\u0435\u043B\u044C" }) }), _jsx(Box, { marginLeft: 1, marginTop: 1, flexDirection: 'column', children: DEEPSEEK_MODELS.map((m, i) => (_jsxs(Box, { flexDirection: 'column', children: [_jsxs(Text, { color: i === modelPicker.selectedIndex ? colors.primary : colors.textMuted, children: [i === modelPicker.selectedIndex ? '▸ ' : ' ', _jsx(Text, { bold: i === modelPicker.selectedIndex, children: m.label }), m.id === config.model ? _jsx(Text, { dimColor: true, children: " (\u0442\u0435\u043A\u0443\u0449\u0430\u044F)" }) : null] }), _jsxs(Text, { dimColor: true, children: [' ', m.description] })] }, m.id))) }), _jsx(Box, { marginLeft: 1, marginBottom: 1, marginTop: 1, children: _jsx(Text, { color: colors.textMuted, children: "\u2191\u2193 \u2014 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430" }) })] })), langPicker && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.primary, children: [_jsx(Box, { marginLeft: 1, marginTop: 1, children: _jsx(Text, { bold: true, color: colors.primary, children: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u044F\u0437\u044B\u043A / Select language / \u9009\u62E9\u8BED\u8A00" }) }), _jsx(Box, { marginLeft: 1, marginTop: 1, flexDirection: 'column', children: i18n.listLocales().map((loc, i) => (_jsx(Box, { children: _jsxs(Text, { color: i === langPicker.selectedIndex ? colors.primary : colors.textMuted, children: [i === langPicker.selectedIndex ? '▸ ' : ' ', loc.name, loc.code === i18n.getLocale() ? _jsx(Text, { dimColor: true, children: " (\u0442\u0435\u043A\u0443\u0449\u0438\u0439)" }) : null] }) }, loc.code))) }), _jsx(Box, { marginLeft: 1, marginBottom: 1, marginTop: 1, children: _jsx(Text, { color: colors.textMuted, children: "\u2191\u2193 \u2014 \u043D\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044F Enter \u2014 \u043F\u0440\u0438\u043C\u0435\u043D\u0438\u0442\u044C Esc \u2014 \u043E\u0442\u043C\u0435\u043D\u0430" }) })] })), pendingApproval && (_jsxs(Box, { flexDirection: 'column', marginLeft: 2, marginBottom: 1, borderStyle: 'round', borderColor: colors.warning, children: [_jsx(Box, { children: _jsx(Text, { bold: true, color: colors.warning, children: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C \u0432\u044B\u0437\u043E\u0432 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u0430?" }) }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { bold: true, color: colors.text, children: pendingApproval.toolName }) }), _jsx(Box, { marginLeft: 1, children: _jsx(Text, { color: colors.textMuted, children: JSON.stringify(pendingApproval.args, null, 2).slice(0, 200) }) }), _jsxs(Box, { flexDirection: 'column', marginTop: 1, children: [[
|
|
836
881
|
'[ok] Подтвердить',
|
|
837
882
|
'[no] Отклонить',
|
|
838
883
|
`[mute] Не спрашивать для "${pendingApproval.toolName}"`,
|