deepcode-ai 1.0.2 → 1.0.3
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/dist/index.js +383 -182
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -374,7 +374,7 @@ var DeepCodeConfigSchema = z.object({
|
|
|
374
374
|
maxIterations: z.number().int().positive().default(20),
|
|
375
375
|
providerRetries: z.number().int().min(0).max(5).default(2),
|
|
376
376
|
temperature: z.number().min(0).max(2).default(0.2),
|
|
377
|
-
maxTokens: z.number().int().positive().default(
|
|
377
|
+
maxTokens: z.number().int().positive().default(2048),
|
|
378
378
|
cache: z.object({
|
|
379
379
|
enabled: z.boolean().default(true),
|
|
380
380
|
ttlSeconds: z.number().int().positive().max(86400).default(300)
|
|
@@ -621,6 +621,58 @@ import { Effect as Effect8 } from "effect";
|
|
|
621
621
|
import { z as z9 } from "zod";
|
|
622
622
|
import { Effect as Effect9 } from "effect";
|
|
623
623
|
import { z as z10 } from "zod";
|
|
624
|
+
var DeepCodeError = class extends Error {
|
|
625
|
+
constructor(message, code, cause) {
|
|
626
|
+
super(message);
|
|
627
|
+
this.code = code;
|
|
628
|
+
this.cause = cause;
|
|
629
|
+
this.name = "DeepCodeError";
|
|
630
|
+
}
|
|
631
|
+
code;
|
|
632
|
+
cause;
|
|
633
|
+
};
|
|
634
|
+
var ConfigError = class extends DeepCodeError {
|
|
635
|
+
constructor(message, cause) {
|
|
636
|
+
super(message, "CONFIG_ERROR", cause);
|
|
637
|
+
this.name = "ConfigError";
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
var PermissionDeniedError = class extends DeepCodeError {
|
|
641
|
+
constructor(message) {
|
|
642
|
+
super(message, "PERMISSION_DENIED");
|
|
643
|
+
this.name = "PermissionDeniedError";
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
var PathNotAllowedError = class extends DeepCodeError {
|
|
647
|
+
constructor(path122, reason) {
|
|
648
|
+
super(`Path is not allowed: ${path122}. ${reason}`, "PATH_NOT_ALLOWED");
|
|
649
|
+
this.name = "PathNotAllowedError";
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
var ToolExecutionError = class extends DeepCodeError {
|
|
653
|
+
constructor(message, cause) {
|
|
654
|
+
super(message, "TOOL_EXECUTION_ERROR", cause);
|
|
655
|
+
this.name = "ToolExecutionError";
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
var ProviderError = class extends DeepCodeError {
|
|
659
|
+
constructor(message, provider, cause, options) {
|
|
660
|
+
super(message, "PROVIDER_ERROR", cause);
|
|
661
|
+
this.provider = provider;
|
|
662
|
+
this.name = "ProviderError";
|
|
663
|
+
this.statusCode = options?.statusCode;
|
|
664
|
+
this.retryAfterMs = options?.retryAfterMs;
|
|
665
|
+
}
|
|
666
|
+
provider;
|
|
667
|
+
statusCode;
|
|
668
|
+
retryAfterMs;
|
|
669
|
+
};
|
|
670
|
+
var BudgetExceededError = class extends DeepCodeError {
|
|
671
|
+
constructor(message) {
|
|
672
|
+
super(message, "TOKEN_BUDGET_EXCEEDED");
|
|
673
|
+
this.name = "BudgetExceededError";
|
|
674
|
+
}
|
|
675
|
+
};
|
|
624
676
|
function resolveModelExecutionProfile(provider, model) {
|
|
625
677
|
const normalized = model?.toLowerCase() ?? "";
|
|
626
678
|
const openAIFamily = matchesAny(normalized, ["gpt-", "/gpt-", "o1", "o3", "o4", "o5"]);
|
|
@@ -1084,6 +1136,42 @@ function stripDisallowedControlChars(input) {
|
|
|
1084
1136
|
}).join("");
|
|
1085
1137
|
}
|
|
1086
1138
|
var MAX_TOOL_OUTPUT_LENGTH = 16e3;
|
|
1139
|
+
var TOOL_CALL_OPEN = "<tool_call>";
|
|
1140
|
+
var TOOL_CALL_CLOSE = "</tool_call>";
|
|
1141
|
+
var XmlToolCallStreamFilter = class {
|
|
1142
|
+
buffer = "";
|
|
1143
|
+
inToolCall = false;
|
|
1144
|
+
filter(text) {
|
|
1145
|
+
this.buffer += text;
|
|
1146
|
+
let result = "";
|
|
1147
|
+
while (true) {
|
|
1148
|
+
if (!this.inToolCall) {
|
|
1149
|
+
const start = this.buffer.indexOf(TOOL_CALL_OPEN);
|
|
1150
|
+
if (start === -1) {
|
|
1151
|
+
const safe = Math.max(0, this.buffer.length - TOOL_CALL_OPEN.length);
|
|
1152
|
+
result += this.buffer.slice(0, safe);
|
|
1153
|
+
this.buffer = this.buffer.slice(safe);
|
|
1154
|
+
break;
|
|
1155
|
+
}
|
|
1156
|
+
result += this.buffer.slice(0, start);
|
|
1157
|
+
this.buffer = this.buffer.slice(start);
|
|
1158
|
+
this.inToolCall = true;
|
|
1159
|
+
} else {
|
|
1160
|
+
const end = this.buffer.indexOf(TOOL_CALL_CLOSE);
|
|
1161
|
+
if (end === -1) break;
|
|
1162
|
+
this.buffer = this.buffer.slice(end + TOOL_CALL_CLOSE.length);
|
|
1163
|
+
this.inToolCall = false;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
return result;
|
|
1167
|
+
}
|
|
1168
|
+
flush() {
|
|
1169
|
+
if (this.inToolCall) return "";
|
|
1170
|
+
const result = this.buffer.trim();
|
|
1171
|
+
this.buffer = "";
|
|
1172
|
+
return result;
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1087
1175
|
function compactToolDescription(description, schemaMode) {
|
|
1088
1176
|
const maxLength = schemaMode === "full" ? 240 : schemaMode === "compact" ? 140 : 96;
|
|
1089
1177
|
if (description.length <= maxLength) {
|
|
@@ -1259,12 +1347,23 @@ var DIRECT_SHELL_COMMAND_PATTERN = /^(?:ls|dir|pwd|date|tree|find|rg|grep|cat|st
|
|
|
1259
1347
|
var DIRECT_UTILITY_PATH_PATTERN = /(?:^|\s)(?:~\/|\.{1,2}\/|\/)[^\s]*/;
|
|
1260
1348
|
var DIRECT_UTILITY_VERB_PATTERN = /\b(?:list|lista|liste|listar|mostre|mostrar|show|display|open|abrir|abra|read|leia|print|imprima|exiba)\b/i;
|
|
1261
1349
|
var DATE_TIME_QUESTION_PATTERN = /\b(?:que dia e hoje|que dia é hoje|data de hoje|dia de hoje|what day is it|what day is today|today'?s date|current date|que horas sao|que horas são|hora atual|current time|what time is it)\b/i;
|
|
1350
|
+
var SIMPLE_SHELL_COMMAND_PATTERN = /^(?:mkdir|touch|rmdir|cp|mv|chmod|chown|echo|ln|git\s+(?:init|clone|add|commit|push|pull|checkout|branch|stash|tag))\b/i;
|
|
1351
|
+
var SIMPLE_ACTION_VERB_RE = /^(?:cria|crie|criar|apaga|apague|apagar|deleta|delete|deletar|remove|mova|move|renomeia|renomeie|renomear|create|rename|mkdir|make)\b/;
|
|
1352
|
+
var COMPOUND_CONNECTOR_RE = /\b(?:entao|depois|tambem|alem|seguida|and then|also|afterwards|next step|subsequently)\b/;
|
|
1262
1353
|
function resolveTurnStrategy(input, mode, policy) {
|
|
1263
1354
|
if (mode === "build") {
|
|
1355
|
+
if (isDirectUtilityRequest(input, policy)) {
|
|
1356
|
+
return {
|
|
1357
|
+
allowTools: true,
|
|
1358
|
+
shouldPlan: false,
|
|
1359
|
+
systemPrompt: UTILITY_SYSTEM_PROMPT,
|
|
1360
|
+
kind: "utility"
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1264
1363
|
if (policy.mode === "always-tools") {
|
|
1265
1364
|
return {
|
|
1266
1365
|
allowTools: true,
|
|
1267
|
-
shouldPlan:
|
|
1366
|
+
shouldPlan: false,
|
|
1268
1367
|
systemPrompt: BUILD_SYSTEM_PROMPT_ALWAYS_TOOLS,
|
|
1269
1368
|
kind: "task"
|
|
1270
1369
|
};
|
|
@@ -1277,12 +1376,12 @@ function resolveTurnStrategy(input, mode, policy) {
|
|
|
1277
1376
|
kind: "chat"
|
|
1278
1377
|
};
|
|
1279
1378
|
}
|
|
1280
|
-
if (
|
|
1379
|
+
if (isSimpleDirectCommand(input)) {
|
|
1281
1380
|
return {
|
|
1282
1381
|
allowTools: true,
|
|
1283
1382
|
shouldPlan: false,
|
|
1284
|
-
systemPrompt:
|
|
1285
|
-
kind: "
|
|
1383
|
+
systemPrompt: BUILD_SYSTEM_PROMPT,
|
|
1384
|
+
kind: "task"
|
|
1286
1385
|
};
|
|
1287
1386
|
}
|
|
1288
1387
|
const looksLikeWorkspace = looksLikeWorkspaceRequest(input, policy);
|
|
@@ -1464,6 +1563,14 @@ function normalizeTurnInput(input) {
|
|
|
1464
1563
|
function escapeRegex(input) {
|
|
1465
1564
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1466
1565
|
}
|
|
1566
|
+
function isSimpleDirectCommand(input) {
|
|
1567
|
+
const trimmed = input.trim();
|
|
1568
|
+
if (SIMPLE_SHELL_COMMAND_PATTERN.test(trimmed)) return true;
|
|
1569
|
+
const normalized = normalizeTurnInput(trimmed);
|
|
1570
|
+
if (!SIMPLE_ACTION_VERB_RE.test(normalized)) return false;
|
|
1571
|
+
if (COMPOUND_CONNECTOR_RE.test(normalized)) return false;
|
|
1572
|
+
return normalized.split(/\s+/).length <= 20;
|
|
1573
|
+
}
|
|
1467
1574
|
function resolveExecutionTarget(config, session, mode, explicitProvider) {
|
|
1468
1575
|
const modeOverride = config.modeDefaults?.[mode];
|
|
1469
1576
|
const provider = explicitProvider ?? modeOverride?.provider ?? session.provider ?? config.defaultProvider;
|
|
@@ -1536,42 +1643,55 @@ var Agent = class {
|
|
|
1536
1643
|
session.status = "planning";
|
|
1537
1644
|
session.metadata.plan = void 0;
|
|
1538
1645
|
session.metadata.planError = void 0;
|
|
1539
|
-
const planningProvider = this.providerManager.get(resolvedTarget.provider);
|
|
1540
|
-
let plan;
|
|
1541
|
-
if (turnStrategy.shouldPlan) {
|
|
1542
|
-
try {
|
|
1543
|
-
plan = await this.planner.plan(
|
|
1544
|
-
options.input,
|
|
1545
|
-
(prompt) => planningProvider.complete(prompt, {
|
|
1546
|
-
model: resolvedModel,
|
|
1547
|
-
maxTokens: Math.min(this.config.maxTokens, 2048),
|
|
1548
|
-
temperature: 0,
|
|
1549
|
-
signal: options.signal
|
|
1550
|
-
})
|
|
1551
|
-
);
|
|
1552
|
-
session.metadata.plan = plan;
|
|
1553
|
-
} catch (error) {
|
|
1554
|
-
session.metadata.planError = error instanceof Error ? error.message : String(error);
|
|
1555
|
-
this.eventBus.emit("app:warn", { message: `Task planning failed: ${session.metadata.planError}. Continuing without structured plan.` });
|
|
1556
|
-
}
|
|
1557
|
-
}
|
|
1558
1646
|
this.activeBudgets.set(session.id, new SessionBudget(this.config.tokenBudget));
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1647
|
+
try {
|
|
1648
|
+
const planningProvider = this.providerManager.get(resolvedTarget.provider);
|
|
1649
|
+
let plan;
|
|
1650
|
+
if (turnStrategy.shouldPlan) {
|
|
1651
|
+
try {
|
|
1652
|
+
plan = await this.planner.plan(
|
|
1653
|
+
options.input,
|
|
1654
|
+
(prompt) => planningProvider.complete(prompt, {
|
|
1655
|
+
model: resolvedModel,
|
|
1656
|
+
maxTokens: Math.min(this.config.maxTokens, 512),
|
|
1657
|
+
temperature: 0,
|
|
1658
|
+
signal: options.signal,
|
|
1659
|
+
onUsage: (inputTokens, outputTokens) => {
|
|
1660
|
+
this.recordUsage(session.id, inputTokens, outputTokens);
|
|
1661
|
+
}
|
|
1662
|
+
})
|
|
1663
|
+
);
|
|
1664
|
+
session.metadata.plan = plan;
|
|
1665
|
+
} catch (error) {
|
|
1666
|
+
if (error instanceof BudgetExceededError) {
|
|
1667
|
+
throw error;
|
|
1668
|
+
}
|
|
1669
|
+
session.metadata.planError = error instanceof Error ? error.message : String(error);
|
|
1670
|
+
this.eventBus.emit("app:warn", { message: `Task planning failed: ${session.metadata.planError}. Continuing without structured plan.` });
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
let finalText = "";
|
|
1674
|
+
let iterations = 0;
|
|
1675
|
+
const maxIterations = this.config.maxIterations;
|
|
1676
|
+
session.status = "executing";
|
|
1677
|
+
if (turnStrategy.kind === "utility") {
|
|
1678
|
+
finalText = await this.executeUtilityTurn(session, options.input, mode, options);
|
|
1679
|
+
} else if (plan && mode === "build") {
|
|
1680
|
+
finalText = await this.executePlan(plan, session, mode, options);
|
|
1681
|
+
} else {
|
|
1682
|
+
finalText = await this.executeTraditional(session, mode, maxIterations, iterations, options, turnStrategy);
|
|
1683
|
+
}
|
|
1684
|
+
session.status = "idle";
|
|
1685
|
+
this.sessions.save(session);
|
|
1686
|
+
await this.sessions.persist(session.id);
|
|
1687
|
+
return finalText.trim();
|
|
1688
|
+
} catch (error) {
|
|
1689
|
+
session.status = "error";
|
|
1690
|
+
this.sessions.save(session);
|
|
1691
|
+
throw error;
|
|
1692
|
+
} finally {
|
|
1693
|
+
this.activeBudgets.delete(session.id);
|
|
1569
1694
|
}
|
|
1570
|
-
session.status = "idle";
|
|
1571
|
-
this.sessions.save(session);
|
|
1572
|
-
await this.sessions.persist(session.id);
|
|
1573
|
-
this.activeBudgets.delete(session.id);
|
|
1574
|
-
return finalText.trim();
|
|
1575
1695
|
}
|
|
1576
1696
|
/**
|
|
1577
1697
|
* Execute tasks from plan in parallel rounds, respecting dependencies
|
|
@@ -1603,7 +1723,7 @@ var Agent = class {
|
|
|
1603
1723
|
const progress = this.planner.getProgress(plan);
|
|
1604
1724
|
const parallel = runnableTasks.length > 1;
|
|
1605
1725
|
const taskLines = await Promise.all(
|
|
1606
|
-
runnableTasks.map(async (task) => {
|
|
1726
|
+
runnableTasks.map(async (task, taskIndex) => {
|
|
1607
1727
|
const taskPrompt = this.buildTaskPrompt(plan, task, progress);
|
|
1608
1728
|
const executionSession = parallel ? this.createChildSession(session, task.id) : session;
|
|
1609
1729
|
const maxAttempts = 1 + this.config.taskRetries;
|
|
@@ -1618,14 +1738,17 @@ Try a different approach.` : taskPrompt;
|
|
|
1618
1738
|
const result = await this.executeTaskWithLLM(prompt, executionSession, mode, taskOptions, task.type);
|
|
1619
1739
|
this.planner.updateTaskStatus(plan, task.id, "completed", result);
|
|
1620
1740
|
options.onTaskUpdate?.(task, plan);
|
|
1621
|
-
return `[${progress.completed + 1}/${progress.total}] \u2713 ${task.description}`;
|
|
1741
|
+
return `[${progress.completed + taskIndex + 1}/${progress.total}] \u2713 ${task.description}`;
|
|
1622
1742
|
} catch (error) {
|
|
1743
|
+
if (error instanceof BudgetExceededError) {
|
|
1744
|
+
throw error;
|
|
1745
|
+
}
|
|
1623
1746
|
lastError = error instanceof Error ? error.message : String(error);
|
|
1624
1747
|
}
|
|
1625
1748
|
}
|
|
1626
1749
|
this.planner.updateTaskStatus(plan, task.id, "failed", void 0, lastError);
|
|
1627
1750
|
options.onTaskUpdate?.(task, plan);
|
|
1628
|
-
return `[${progress.completed + 1}/${progress.total}] \u2717 ${task.description} \u2014 ${lastError}`;
|
|
1751
|
+
return `[${progress.completed + taskIndex + 1}/${progress.total}] \u2717 ${task.description} \u2014 ${lastError}`;
|
|
1629
1752
|
})
|
|
1630
1753
|
);
|
|
1631
1754
|
finalText += `${taskLines.join("\n")}
|
|
@@ -1680,6 +1803,7 @@ Execute this task using the available tools. Return a summary of what was done.`
|
|
|
1680
1803
|
let finalAssistantText = "";
|
|
1681
1804
|
while (taskIterations < maxTaskIterations) {
|
|
1682
1805
|
taskIterations++;
|
|
1806
|
+
this.enforceBudget(session.id);
|
|
1683
1807
|
const chunks = this.providerManager.chat(
|
|
1684
1808
|
this.messagesForSystemPrompt(
|
|
1685
1809
|
session,
|
|
@@ -1705,10 +1829,14 @@ Execute this task using the available tools. Return a summary of what was done.`
|
|
|
1705
1829
|
);
|
|
1706
1830
|
let assistantText = "";
|
|
1707
1831
|
const toolCalls = [];
|
|
1832
|
+
const xmlFilter = textToolFallbackEnabled ? new XmlToolCallStreamFilter() : null;
|
|
1708
1833
|
for await (const chunk of chunks) {
|
|
1709
1834
|
if (chunk.type === "delta") {
|
|
1710
1835
|
assistantText += chunk.content;
|
|
1711
|
-
if (
|
|
1836
|
+
if (textToolFallbackEnabled) {
|
|
1837
|
+
const visible = xmlFilter.filter(chunk.content);
|
|
1838
|
+
if (visible) options.onChunk?.(visible);
|
|
1839
|
+
} else {
|
|
1712
1840
|
options.onChunk?.(chunk.content);
|
|
1713
1841
|
}
|
|
1714
1842
|
}
|
|
@@ -1717,17 +1845,18 @@ Execute this task using the available tools. Return a summary of what was done.`
|
|
|
1717
1845
|
}
|
|
1718
1846
|
if (chunk.type === "usage") {
|
|
1719
1847
|
options.onUsage?.(chunk.inputTokens, chunk.outputTokens);
|
|
1720
|
-
this.
|
|
1848
|
+
this.recordUsage(session.id, chunk.inputTokens, chunk.outputTokens);
|
|
1721
1849
|
}
|
|
1722
1850
|
}
|
|
1851
|
+
if (textToolFallbackEnabled) {
|
|
1852
|
+
const flushed = xmlFilter.flush();
|
|
1853
|
+
if (flushed) options.onChunk?.(flushed);
|
|
1854
|
+
}
|
|
1723
1855
|
const turnResult = textToolFallbackEnabled ? applyFallbackToolCallParsing(assistantText, toolCalls, allowedToolNames) : { assistantText, toolCalls };
|
|
1724
1856
|
assistantText = turnResult.assistantText;
|
|
1725
1857
|
const nextToolCalls = [...turnResult.toolCalls];
|
|
1726
1858
|
toolCalls.length = 0;
|
|
1727
1859
|
toolCalls.push(...nextToolCalls);
|
|
1728
|
-
if (textToolFallbackEnabled && assistantText) {
|
|
1729
|
-
options.onChunk?.(assistantText);
|
|
1730
|
-
}
|
|
1731
1860
|
if (assistantText.trim() || toolCalls.length > 0) {
|
|
1732
1861
|
this.sessions.addMessage(session.id, {
|
|
1733
1862
|
role: "assistant",
|
|
@@ -1767,19 +1896,7 @@ ${assistantText}` : assistantText;
|
|
|
1767
1896
|
while (iterations < maxIterations) {
|
|
1768
1897
|
iterations += 1;
|
|
1769
1898
|
options.onIteration?.(iterations, maxIterations);
|
|
1770
|
-
|
|
1771
|
-
if (budget) {
|
|
1772
|
-
const budgetStatus = budget.check();
|
|
1773
|
-
if (budgetStatus.status === "exceeded") {
|
|
1774
|
-
this.eventBus.emit("budget:exceeded", budgetStatus);
|
|
1775
|
-
throw new Error(
|
|
1776
|
-
`Token budget exceeded (${budgetStatus.kind}): used ${budgetStatus.used.toFixed(budgetStatus.kind === "cost" ? 4 : 0)}, limit ${budgetStatus.limit}`
|
|
1777
|
-
);
|
|
1778
|
-
}
|
|
1779
|
-
if (budgetStatus.status === "warning") {
|
|
1780
|
-
this.eventBus.emit("budget:warning", budgetStatus);
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1899
|
+
this.enforceBudget(session.id);
|
|
1783
1900
|
await this.compressContextIfNeeded(session, turnStrategy.systemPrompt, options);
|
|
1784
1901
|
const chunks = this.providerManager.chat(
|
|
1785
1902
|
this.messagesForSystemPrompt(
|
|
@@ -1808,10 +1925,17 @@ ${assistantText}` : assistantText;
|
|
|
1808
1925
|
);
|
|
1809
1926
|
let assistantText = "";
|
|
1810
1927
|
const toolCalls = [];
|
|
1928
|
+
const xmlFilter = textToolFallbackEnabled ? new XmlToolCallStreamFilter() : null;
|
|
1811
1929
|
for await (const chunk of chunks) {
|
|
1812
1930
|
if (chunk.type === "delta") {
|
|
1813
1931
|
assistantText += chunk.content;
|
|
1814
|
-
if (
|
|
1932
|
+
if (textToolFallbackEnabled) {
|
|
1933
|
+
const visible = xmlFilter.filter(chunk.content);
|
|
1934
|
+
if (visible) {
|
|
1935
|
+
finalText += visible;
|
|
1936
|
+
options.onChunk?.(visible);
|
|
1937
|
+
}
|
|
1938
|
+
} else {
|
|
1815
1939
|
finalText += chunk.content;
|
|
1816
1940
|
options.onChunk?.(chunk.content);
|
|
1817
1941
|
}
|
|
@@ -1821,7 +1945,14 @@ ${assistantText}` : assistantText;
|
|
|
1821
1945
|
}
|
|
1822
1946
|
if (chunk.type === "usage") {
|
|
1823
1947
|
options.onUsage?.(chunk.inputTokens, chunk.outputTokens);
|
|
1824
|
-
this.
|
|
1948
|
+
this.recordUsage(session.id, chunk.inputTokens, chunk.outputTokens);
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
if (textToolFallbackEnabled) {
|
|
1952
|
+
const flushed = xmlFilter.flush();
|
|
1953
|
+
if (flushed) {
|
|
1954
|
+
finalText += flushed;
|
|
1955
|
+
options.onChunk?.(flushed);
|
|
1825
1956
|
}
|
|
1826
1957
|
}
|
|
1827
1958
|
const turnResult = textToolFallbackEnabled ? applyFallbackToolCallParsing(assistantText, toolCalls, allowedToolNames) : { assistantText, toolCalls };
|
|
@@ -1829,10 +1960,6 @@ ${assistantText}` : assistantText;
|
|
|
1829
1960
|
const nextToolCalls = [...turnResult.toolCalls];
|
|
1830
1961
|
toolCalls.length = 0;
|
|
1831
1962
|
toolCalls.push(...nextToolCalls);
|
|
1832
|
-
if (textToolFallbackEnabled && assistantText) {
|
|
1833
|
-
finalText += assistantText;
|
|
1834
|
-
options.onChunk?.(assistantText);
|
|
1835
|
-
}
|
|
1836
1963
|
if (assistantText.trim() || toolCalls.length > 0) {
|
|
1837
1964
|
this.sessions.addMessage(session.id, {
|
|
1838
1965
|
role: "assistant",
|
|
@@ -2010,7 +2137,7 @@ ${assistantText}` : assistantText;
|
|
|
2010
2137
|
}
|
|
2011
2138
|
allowedToolNamesForTaskType(mode, taskType) {
|
|
2012
2139
|
if (taskType === "research") return /* @__PURE__ */ new Set([...PLAN_ALLOWED_TOOLS]);
|
|
2013
|
-
if (taskType === "verify") return /* @__PURE__ */ new Set(["read_file", "analyze_code", "search_text"]);
|
|
2140
|
+
if (taskType === "verify") return /* @__PURE__ */ new Set(["read_file", "list_dir", "analyze_code", "search_text", "bash"]);
|
|
2014
2141
|
return this.allowedToolNamesForMode(mode);
|
|
2015
2142
|
}
|
|
2016
2143
|
toolDefinitionsForNames(names, schemaMode = "full") {
|
|
@@ -2110,6 +2237,9 @@ ${assistantText}` : assistantText;
|
|
|
2110
2237
|
);
|
|
2111
2238
|
for await (const chunk of summaryChunks) {
|
|
2112
2239
|
if (chunk.type === "delta") summary += chunk.content;
|
|
2240
|
+
if (chunk.type === "usage") {
|
|
2241
|
+
this.recordUsage(session.id, chunk.inputTokens, chunk.outputTokens);
|
|
2242
|
+
}
|
|
2113
2243
|
}
|
|
2114
2244
|
const summaryMessage = buildSummaryMessage(summary);
|
|
2115
2245
|
this.sessions.replaceMessages(session.id, [summaryMessage, ...toKeep, ...rest]);
|
|
@@ -2190,28 +2320,55 @@ ${assistantText}` : assistantText;
|
|
|
2190
2320
|
utilityDateResponse() {
|
|
2191
2321
|
return utilityDateResponse();
|
|
2192
2322
|
}
|
|
2323
|
+
recordUsage(sessionId, inputTokens, outputTokens) {
|
|
2324
|
+
const budget = this.activeBudgets.get(sessionId);
|
|
2325
|
+
if (!budget) return;
|
|
2326
|
+
budget.add(inputTokens, outputTokens);
|
|
2327
|
+
this.reportBudgetStatus(budget.check());
|
|
2328
|
+
}
|
|
2329
|
+
enforceBudget(sessionId) {
|
|
2330
|
+
const budget = this.activeBudgets.get(sessionId);
|
|
2331
|
+
if (!budget) return;
|
|
2332
|
+
this.reportBudgetStatus(budget.check());
|
|
2333
|
+
}
|
|
2334
|
+
reportBudgetStatus(status) {
|
|
2335
|
+
if (status.status === "warning") {
|
|
2336
|
+
this.eventBus.emit("budget:warning", status);
|
|
2337
|
+
return;
|
|
2338
|
+
}
|
|
2339
|
+
if (status.status === "exceeded") {
|
|
2340
|
+
this.eventBus.emit("budget:exceeded", status);
|
|
2341
|
+
throw new BudgetExceededError(
|
|
2342
|
+
`Token budget exceeded (${status.kind}): used ${status.used.toFixed(status.kind === "cost" ? 4 : 0)}, limit ${status.limit}`
|
|
2343
|
+
);
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2193
2346
|
};
|
|
2194
2347
|
function truncateForMetadata(value, maxLength = 2e3) {
|
|
2195
2348
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
2196
2349
|
}
|
|
2197
2350
|
var McpClient = class {
|
|
2198
2351
|
process;
|
|
2352
|
+
ready;
|
|
2199
2353
|
nextId = 1;
|
|
2200
2354
|
pending = /* @__PURE__ */ new Map();
|
|
2201
|
-
constructor(command, args, env) {
|
|
2202
|
-
this.process =
|
|
2355
|
+
constructor(command, args, env, spawnProcess = spawn) {
|
|
2356
|
+
this.process = spawnProcess(command, args, {
|
|
2203
2357
|
stdio: ["pipe", "pipe", "pipe"],
|
|
2204
2358
|
env: { ...process.env, ...env }
|
|
2205
2359
|
});
|
|
2360
|
+
this.ready = new Promise((resolve, reject) => {
|
|
2361
|
+
this.process.once("spawn", () => resolve());
|
|
2362
|
+
this.process.once("error", reject);
|
|
2363
|
+
});
|
|
2364
|
+
let exitCode = null;
|
|
2206
2365
|
const rejectAll = (error) => {
|
|
2207
2366
|
for (const { reject } of this.pending.values()) reject(error);
|
|
2208
2367
|
this.pending.clear();
|
|
2209
2368
|
};
|
|
2210
2369
|
this.process.on("error", (err) => rejectAll(err));
|
|
2211
2370
|
this.process.on("exit", (code) => {
|
|
2212
|
-
|
|
2213
|
-
rejectAll(new Error(`MCP server exited unexpectedly (code ${code ?? "null"})`));
|
|
2214
|
-
}
|
|
2371
|
+
exitCode = code ?? null;
|
|
2215
2372
|
});
|
|
2216
2373
|
const rl = createInterface({ input: this.process.stdout, terminal: false });
|
|
2217
2374
|
rl.on("line", (line) => {
|
|
@@ -2230,8 +2387,14 @@ var McpClient = class {
|
|
|
2230
2387
|
} catch {
|
|
2231
2388
|
}
|
|
2232
2389
|
});
|
|
2390
|
+
rl.on("close", () => {
|
|
2391
|
+
if (this.pending.size > 0) {
|
|
2392
|
+
rejectAll(new Error(`MCP server exited unexpectedly (code ${exitCode ?? this.process.exitCode ?? "null"})`));
|
|
2393
|
+
}
|
|
2394
|
+
});
|
|
2233
2395
|
}
|
|
2234
2396
|
async initialize() {
|
|
2397
|
+
await this.ready;
|
|
2235
2398
|
await this.request("initialize", {
|
|
2236
2399
|
protocolVersion: "2024-11-05",
|
|
2237
2400
|
capabilities: { tools: {} },
|
|
@@ -2258,7 +2421,8 @@ var McpClient = class {
|
|
|
2258
2421
|
}
|
|
2259
2422
|
this.pending.clear();
|
|
2260
2423
|
}
|
|
2261
|
-
request(method, params) {
|
|
2424
|
+
async request(method, params) {
|
|
2425
|
+
await this.ready;
|
|
2262
2426
|
const id = this.nextId++;
|
|
2263
2427
|
return new Promise((resolve, reject) => {
|
|
2264
2428
|
this.pending.set(id, { resolve, reject });
|
|
@@ -2308,16 +2472,18 @@ function adaptMcpTool(client, tool, serverName) {
|
|
|
2308
2472
|
});
|
|
2309
2473
|
}
|
|
2310
2474
|
var McpManager = class {
|
|
2311
|
-
constructor(events) {
|
|
2475
|
+
constructor(events, clientFactory = (server) => new McpClient(server.command, server.args, server.env)) {
|
|
2312
2476
|
this.events = events;
|
|
2477
|
+
this.clientFactory = clientFactory;
|
|
2313
2478
|
}
|
|
2314
2479
|
events;
|
|
2480
|
+
clientFactory;
|
|
2315
2481
|
clients = [];
|
|
2316
2482
|
async connect(servers) {
|
|
2317
2483
|
const tools = [];
|
|
2318
2484
|
for (const server of servers) {
|
|
2319
2485
|
try {
|
|
2320
|
-
const client =
|
|
2486
|
+
const client = this.clientFactory(server);
|
|
2321
2487
|
await client.initialize();
|
|
2322
2488
|
const mcpTools = await client.listTools();
|
|
2323
2489
|
this.clients.push({ name: server.name, client });
|
|
@@ -2453,52 +2619,6 @@ var ToolCache = class {
|
|
|
2453
2619
|
function cacheKey(namespace, keyParts) {
|
|
2454
2620
|
return createHash("sha256").update(JSON.stringify([namespace, ...keyParts])).digest("hex");
|
|
2455
2621
|
}
|
|
2456
|
-
var DeepCodeError = class extends Error {
|
|
2457
|
-
constructor(message, code, cause) {
|
|
2458
|
-
super(message);
|
|
2459
|
-
this.code = code;
|
|
2460
|
-
this.cause = cause;
|
|
2461
|
-
this.name = "DeepCodeError";
|
|
2462
|
-
}
|
|
2463
|
-
code;
|
|
2464
|
-
cause;
|
|
2465
|
-
};
|
|
2466
|
-
var ConfigError = class extends DeepCodeError {
|
|
2467
|
-
constructor(message, cause) {
|
|
2468
|
-
super(message, "CONFIG_ERROR", cause);
|
|
2469
|
-
this.name = "ConfigError";
|
|
2470
|
-
}
|
|
2471
|
-
};
|
|
2472
|
-
var PermissionDeniedError = class extends DeepCodeError {
|
|
2473
|
-
constructor(message) {
|
|
2474
|
-
super(message, "PERMISSION_DENIED");
|
|
2475
|
-
this.name = "PermissionDeniedError";
|
|
2476
|
-
}
|
|
2477
|
-
};
|
|
2478
|
-
var PathNotAllowedError = class extends DeepCodeError {
|
|
2479
|
-
constructor(path122, reason) {
|
|
2480
|
-
super(`Path is not allowed: ${path122}. ${reason}`, "PATH_NOT_ALLOWED");
|
|
2481
|
-
this.name = "PathNotAllowedError";
|
|
2482
|
-
}
|
|
2483
|
-
};
|
|
2484
|
-
var ToolExecutionError = class extends DeepCodeError {
|
|
2485
|
-
constructor(message, cause) {
|
|
2486
|
-
super(message, "TOOL_EXECUTION_ERROR", cause);
|
|
2487
|
-
this.name = "ToolExecutionError";
|
|
2488
|
-
}
|
|
2489
|
-
};
|
|
2490
|
-
var ProviderError = class extends DeepCodeError {
|
|
2491
|
-
constructor(message, provider, cause, options) {
|
|
2492
|
-
super(message, "PROVIDER_ERROR", cause);
|
|
2493
|
-
this.provider = provider;
|
|
2494
|
-
this.name = "ProviderError";
|
|
2495
|
-
this.statusCode = options?.statusCode;
|
|
2496
|
-
this.retryAfterMs = options?.retryAfterMs;
|
|
2497
|
-
}
|
|
2498
|
-
provider;
|
|
2499
|
-
statusCode;
|
|
2500
|
-
retryAfterMs;
|
|
2501
|
-
};
|
|
2502
2622
|
var ConfigLoader = class {
|
|
2503
2623
|
resolveConfigPath(options) {
|
|
2504
2624
|
return options.configPath ? path22.resolve(options.configPath) : path22.join(options.cwd, ".deepcode", "config.json");
|
|
@@ -3565,6 +3685,7 @@ var AnthropicProvider = class {
|
|
|
3565
3685
|
];
|
|
3566
3686
|
for await (const chunk of this.chat(messages, options)) {
|
|
3567
3687
|
if (chunk.type === "delta") output += chunk.content;
|
|
3688
|
+
if (chunk.type === "usage") options.onUsage?.(chunk.inputTokens, chunk.outputTokens);
|
|
3568
3689
|
}
|
|
3569
3690
|
return output;
|
|
3570
3691
|
}
|
|
@@ -3886,6 +4007,7 @@ var OpenAICompatibleProvider = class {
|
|
|
3886
4007
|
];
|
|
3887
4008
|
for await (const chunk of this.chat(messages, options)) {
|
|
3888
4009
|
if (chunk.type === "delta") output += chunk.content;
|
|
4010
|
+
if (chunk.type === "usage") options.onUsage?.(chunk.inputTokens, chunk.outputTokens);
|
|
3889
4011
|
}
|
|
3890
4012
|
return output;
|
|
3891
4013
|
}
|
|
@@ -3959,11 +4081,15 @@ var OpenAICompatibleProvider = class {
|
|
|
3959
4081
|
}
|
|
3960
4082
|
}
|
|
3961
4083
|
async fetchJson(url, init) {
|
|
4084
|
+
const connectionTimeout = AbortSignal.timeout(3e4);
|
|
4085
|
+
const signal = init.signal ? AbortSignal.any([init.signal, connectionTimeout]) : connectionTimeout;
|
|
3962
4086
|
try {
|
|
3963
|
-
return await fetch(url, init);
|
|
4087
|
+
return await fetch(url, { ...init, signal });
|
|
3964
4088
|
} catch (error) {
|
|
3965
4089
|
if (isAbortError(error)) {
|
|
3966
|
-
|
|
4090
|
+
const timedOut = connectionTimeout.aborted;
|
|
4091
|
+
const msg = timedOut ? `${this.name} connection timed out after 30s. Check the provider URL and network connectivity.` : `${this.name} request timed out or was cancelled`;
|
|
4092
|
+
throw new ProviderError(msg, this.id, error);
|
|
3967
4093
|
}
|
|
3968
4094
|
const message = `${this.name} network request failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
3969
4095
|
throw new ProviderError(redactText(message, this.secretValues()), this.id, error);
|
|
@@ -4411,13 +4537,11 @@ var PermissionGateway = class {
|
|
|
4411
4537
|
await this.audit.log({ operation: check.operation, path: check.path, result: "allowed", reason: "session_allow" });
|
|
4412
4538
|
return { allowed: true };
|
|
4413
4539
|
}
|
|
4414
|
-
|
|
4415
|
-
if (mode === "allow" && (pathAccess === "allowed" || autoAllowedDirectoryListing)) {
|
|
4540
|
+
if (mode === "allow" && pathAccess === "allowed") {
|
|
4416
4541
|
await this.audit.log({
|
|
4417
4542
|
operation: check.operation,
|
|
4418
4543
|
path: check.path,
|
|
4419
|
-
result: "allowed"
|
|
4420
|
-
reason: autoAllowedDirectoryListing ? "directory_probe" : void 0
|
|
4544
|
+
result: "allowed"
|
|
4421
4545
|
});
|
|
4422
4546
|
return { allowed: true };
|
|
4423
4547
|
}
|
|
@@ -4589,9 +4713,6 @@ function isShellWhitelisted(allowList, operation) {
|
|
|
4589
4713
|
(allowedOperation) => normalizeShellPermissionOperation(allowedOperation) === normalizedOperation
|
|
4590
4714
|
);
|
|
4591
4715
|
}
|
|
4592
|
-
function isAutoAllowedDirectoryListing(check, pathAccess) {
|
|
4593
|
-
return pathAccess === "outside_whitelist" && check.kind === "read" && check.operation === "list_dir";
|
|
4594
|
-
}
|
|
4595
4716
|
function configDeniedReason(check) {
|
|
4596
4717
|
switch (check.kind) {
|
|
4597
4718
|
case "read":
|
|
@@ -7797,7 +7918,7 @@ var en = {
|
|
|
7797
7918
|
modelSelectorFree: "free",
|
|
7798
7919
|
emptyChatSlashHint: "/provider \u2022 /model \u2022 /config \u2022 /help",
|
|
7799
7920
|
deepCodeLabel: "DeepCode",
|
|
7800
|
-
scrollHint: "PgUp/PgDn to scroll",
|
|
7921
|
+
scrollHint: "PgUp/PgDn \xB7 Ctrl+\u2191/\u2193 to scroll",
|
|
7801
7922
|
normalModeIndicator: "NORMAL",
|
|
7802
7923
|
normalModeHint: "press i to insert",
|
|
7803
7924
|
streamingIndicator: "generating...",
|
|
@@ -8204,7 +8325,7 @@ var ptBR = {
|
|
|
8204
8325
|
modelSelectorFree: "gr\xE1tis",
|
|
8205
8326
|
emptyChatSlashHint: "/provider \u2022 /model \u2022 /config \u2022 /help",
|
|
8206
8327
|
deepCodeLabel: "DeepCode",
|
|
8207
|
-
scrollHint: "PgUp/PgDn para rolar",
|
|
8328
|
+
scrollHint: "PgUp/PgDn \xB7 Ctrl+\u2191/\u2193 para rolar",
|
|
8208
8329
|
normalModeIndicator: "NORMAL",
|
|
8209
8330
|
normalModeHint: "pressione i para inserir",
|
|
8210
8331
|
streamingIndicator: "gerando...",
|
|
@@ -9023,9 +9144,9 @@ function ModeRoute({
|
|
|
9023
9144
|
] });
|
|
9024
9145
|
}
|
|
9025
9146
|
var DEFAULT_PANELS = {
|
|
9026
|
-
context: { widthPercent:
|
|
9027
|
-
execution: { widthPercent:
|
|
9028
|
-
detail: { widthPercent: 28, collapsed:
|
|
9147
|
+
context: { widthPercent: 22, collapsed: false },
|
|
9148
|
+
execution: { widthPercent: 50, collapsed: false },
|
|
9149
|
+
detail: { widthPercent: 28, collapsed: false }
|
|
9029
9150
|
};
|
|
9030
9151
|
var MIN_WIDTH = 15;
|
|
9031
9152
|
var RESIZE_STEP = 5;
|
|
@@ -11513,11 +11634,11 @@ function useVirtualScroll(items, viewportHeight, estimateHeight, isActive = true
|
|
|
11513
11634
|
const halfPage = Math.max(1, Math.floor(viewportHeight / 4));
|
|
11514
11635
|
useInput7(
|
|
11515
11636
|
(inputChar, key) => {
|
|
11516
|
-
if (key.pageUp) {
|
|
11637
|
+
if (key.pageUp || key.ctrl && key.upArrow) {
|
|
11517
11638
|
scrollUp();
|
|
11518
11639
|
return;
|
|
11519
11640
|
}
|
|
11520
|
-
if (key.pageDown) {
|
|
11641
|
+
if (key.pageDown || key.ctrl && key.downArrow) {
|
|
11521
11642
|
scrollDown();
|
|
11522
11643
|
return;
|
|
11523
11644
|
}
|
|
@@ -12796,34 +12917,82 @@ function ConfigEditor({
|
|
|
12796
12917
|
/* @__PURE__ */ jsx15(Text14, { children: runtime.config.github.token ? t("appPanelsGithubTokenSet") : t("appPanelsGithubTokenMissing") })
|
|
12797
12918
|
] });
|
|
12798
12919
|
}
|
|
12920
|
+
var CMD_W = 20;
|
|
12921
|
+
function HelpRow({ keys, desc, theme, accent = false }) {
|
|
12922
|
+
return /* @__PURE__ */ jsxs15(Box14, { flexDirection: "row", children: [
|
|
12923
|
+
/* @__PURE__ */ jsx15(Box14, { width: CMD_W, flexShrink: 0, children: /* @__PURE__ */ jsx15(Text14, { color: accent ? theme.accent : theme.primary, bold: accent, children: keys }) }),
|
|
12924
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.fgMuted, children: desc })
|
|
12925
|
+
] });
|
|
12926
|
+
}
|
|
12927
|
+
function HelpSection({ label, theme }) {
|
|
12928
|
+
return /* @__PURE__ */ jsxs15(Box14, { flexDirection: "row", gap: 1, marginTop: 1, children: [
|
|
12929
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.accent, bold: true, children: "\u258C" }),
|
|
12930
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.fg, bold: true, children: label })
|
|
12931
|
+
] });
|
|
12932
|
+
}
|
|
12799
12933
|
function HelpView({ theme }) {
|
|
12800
|
-
return /* @__PURE__ */ jsxs15(Box14, {
|
|
12801
|
-
/* @__PURE__ */
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
/* @__PURE__ */ jsx15(
|
|
12807
|
-
/* @__PURE__ */ jsx15(
|
|
12808
|
-
/* @__PURE__ */ jsx15(
|
|
12809
|
-
/* @__PURE__ */ jsx15(
|
|
12810
|
-
/* @__PURE__ */ jsx15(
|
|
12811
|
-
/* @__PURE__ */ jsx15(
|
|
12812
|
-
/* @__PURE__ */ jsx15(
|
|
12813
|
-
/* @__PURE__ */ jsx15(
|
|
12814
|
-
/* @__PURE__ */ jsx15(
|
|
12815
|
-
/* @__PURE__ */ jsx15(
|
|
12816
|
-
/* @__PURE__ */ jsx15(
|
|
12817
|
-
/* @__PURE__ */ jsx15(
|
|
12818
|
-
/* @__PURE__ */ jsx15(
|
|
12819
|
-
/* @__PURE__ */ jsx15(
|
|
12820
|
-
/* @__PURE__ */ jsx15(
|
|
12821
|
-
/* @__PURE__ */ jsx15(
|
|
12822
|
-
/* @__PURE__ */ jsx15(
|
|
12823
|
-
/* @__PURE__ */ jsx15(
|
|
12824
|
-
/* @__PURE__ */ jsx15(
|
|
12825
|
-
/* @__PURE__ */ jsx15(
|
|
12826
|
-
/* @__PURE__ */ jsx15(
|
|
12934
|
+
return /* @__PURE__ */ jsxs15(Box14, { flexDirection: "column", borderStyle: "single", paddingX: 1, borderColor: theme.border, children: [
|
|
12935
|
+
/* @__PURE__ */ jsxs15(Box14, { flexDirection: "row", gap: 1, children: [
|
|
12936
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.primary, bold: true, children: "\u25C6" }),
|
|
12937
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.fg, bold: true, children: "Ajuda \u2014 DeepCode" }),
|
|
12938
|
+
/* @__PURE__ */ jsx15(Text14, { color: theme.fgMuted, dimColor: true, children: " Esc \xB7 Enter \xB7 q para fechar" })
|
|
12939
|
+
] }),
|
|
12940
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "COMANDOS SLASH", theme }),
|
|
12941
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/help", desc: "Abre esta ajuda", theme }),
|
|
12942
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/provider", desc: "Configura provider e API key", theme }),
|
|
12943
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/model", desc: "Seleciona modelo ativo", theme }),
|
|
12944
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/mode plan", desc: "Modo PLAN \u2014 analisa sem editar arquivos", theme }),
|
|
12945
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/mode build", desc: "Modo BUILD \u2014 edita, executa e valida", theme }),
|
|
12946
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/config", desc: "Abre editor de configura\xE7\xE3o", theme }),
|
|
12947
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/sessions", desc: "Lista e troca entre sess\xF5es salvas", theme }),
|
|
12948
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/new", desc: "Cria uma sess\xE3o nova", theme }),
|
|
12949
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/clear", desc: "Limpa o chat sem apagar a sess\xE3o", theme }),
|
|
12950
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/undo", desc: "Reverte a \xFAltima altera\xE7\xE3o de arquivo", theme }),
|
|
12951
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/diff", desc: "Mostra resumo de todas as altera\xE7\xF5es pendentes", theme }),
|
|
12952
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/timeline", desc: "Linha do tempo de a\xE7\xF5es da sess\xE3o", theme }),
|
|
12953
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "/github-login", desc: "Autenticar GitHub via OAuth", theme }),
|
|
12954
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "ATALHOS GLOBAIS", theme }),
|
|
12955
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+C", desc: "Cancelar execu\xE7\xE3o em curso \xB7 Ctrl+Q para sair", theme, accent: true }),
|
|
12956
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+H", desc: "Abrir esta ajuda", theme, accent: true }),
|
|
12957
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+O", desc: "Seletor de sess\xF5es", theme, accent: true }),
|
|
12958
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+N", desc: "Nova sess\xE3o", theme, accent: true }),
|
|
12959
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+P", desc: "Modal de provider", theme, accent: true }),
|
|
12960
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+M", desc: "Seletor de modelo", theme, accent: true }),
|
|
12961
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+T", desc: "Painel de telemetria", theme, accent: true }),
|
|
12962
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+R", desc: "Buscar no hist\xF3rico de prompts", theme, accent: true }),
|
|
12963
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Tab", desc: "Alternar entre modos PLAN \u2194 BUILD", theme, accent: true }),
|
|
12964
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "PAIN\xC9IS (L=esquerdo C=central D=direito)", theme }),
|
|
12965
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+1/2/3", desc: "Fechar/abrir painel L / C / D", theme, accent: true }),
|
|
12966
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+B", desc: "Toggle sidebar (painel L)", theme, accent: true }),
|
|
12967
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+F", desc: "Alternar sidebar \u2194 \xE1rvore de arquivos", theme, accent: true }),
|
|
12968
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+L", desc: "Toggle timeline no painel D", theme, accent: true }),
|
|
12969
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+,", desc: "Toggle configura\xE7\xE3o no painel D", theme, accent: true }),
|
|
12970
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+\u2190/\u2192", desc: "Redimensionar painel ativo", theme, accent: true }),
|
|
12971
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "SCROLL DO CHAT", theme }),
|
|
12972
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "PgUp / PgDn", desc: "Rolar para cima/baixo", theme }),
|
|
12973
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Ctrl+\u2191 / Ctrl+\u2193", desc: "Rolar para cima/baixo (alternativo)", theme }),
|
|
12974
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Esc \u2192 j / k", desc: "Vim normal mode: j baixo \xB7 k cima", theme }),
|
|
12975
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Esc \u2192 G / gg", desc: "Ir ao fim / topo da conversa", theme }),
|
|
12976
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "Esc \u2192 Ctrl+D/U", desc: "Meio-p\xE1gina para baixo / cima", theme }),
|
|
12977
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "VIM (Esc = insert\u2192normal \xB7 i = normal\u2192insert)", theme }),
|
|
12978
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "i / a / A", desc: "Insert: na pos / ap\xF3s cursor / no fim", theme }),
|
|
12979
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "I / S", desc: "Insert: no in\xEDcio / limpar tudo + insert", theme }),
|
|
12980
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "h / l", desc: "Mover cursor \u2190 / \u2192", theme }),
|
|
12981
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "w / b / e", desc: "Palavra: pr\xF3xima / anterior / fim", theme }),
|
|
12982
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "0 / $ / ^", desc: "In\xEDcio / fim / 1\xBA char n\xE3o-vazio da linha", theme }),
|
|
12983
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "x / X", desc: "Deletar char sob cursor / \xE0 esquerda", theme }),
|
|
12984
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "D / C", desc: "Deletar / mudar at\xE9 o fim da linha", theme }),
|
|
12985
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "dd / dw", desc: "Deletar linha inteira / palavra", theme }),
|
|
12986
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "cc / cw / cb", desc: "Mudar linha / palavra / tr\xE1s", theme }),
|
|
12987
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "r<c>", desc: "Substituir o char sob o cursor", theme }),
|
|
12988
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "APROVA\xC7\xD5ES (quando o agente pede permiss\xE3o)", theme }),
|
|
12989
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "a", desc: "Aprovar uma vez", theme }),
|
|
12990
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "l", desc: "Aprovar sempre (adicionar ao allow-list)", theme }),
|
|
12991
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "s", desc: "Aprovar nesta sess\xE3o", theme }),
|
|
12992
|
+
/* @__PURE__ */ jsx15(HelpRow, { keys: "d / n / Esc", desc: "Negar", theme }),
|
|
12993
|
+
/* @__PURE__ */ jsx15(HelpSection, { label: "TEMAS", theme }),
|
|
12994
|
+
/* @__PURE__ */ jsx15(Box14, { paddingLeft: 2, marginBottom: 1, children: /* @__PURE__ */ jsx15(Text14, { color: theme.fgMuted, children: themeNames.join(" \xB7 ") }) }),
|
|
12995
|
+
/* @__PURE__ */ jsx15(Box14, { paddingLeft: 2, children: /* @__PURE__ */ jsx15(Text14, { color: theme.fgMuted, dimColor: true, children: "Alterar: /config \u2192 tui.theme" }) })
|
|
12827
12996
|
] });
|
|
12828
12997
|
}
|
|
12829
12998
|
function EmptyChatState({
|
|
@@ -13108,8 +13277,8 @@ function MessageList({
|
|
|
13108
13277
|
return /* @__PURE__ */ jsxs17(Box16, { flexDirection: "column", flexGrow: 1, children: [
|
|
13109
13278
|
vimMode === "normal" && /* @__PURE__ */ jsx17(Box16, { paddingX: 1, children: /* @__PURE__ */ jsx17(Text16, { color: theme.fgMuted, dimColor: true, children: "j/k scroll \xB7 gg top \xB7 G bottom \xB7 Ctrl+d/u half-page \xB7 i insert" }) }),
|
|
13110
13279
|
canScrollUp && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "row", gap: 1, paddingX: 1, children: [
|
|
13111
|
-
/* @__PURE__ */ jsx17(Text16, { color: theme.fgMuted,
|
|
13112
|
-
/* @__PURE__ */ jsxs17(Text16, { color: theme.
|
|
13280
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.fgMuted, children: "\u2574\u2574\u2574" }),
|
|
13281
|
+
/* @__PURE__ */ jsxs17(Text16, { color: theme.accent, children: [
|
|
13113
13282
|
"\u2191 ",
|
|
13114
13283
|
t("scrollHint")
|
|
13115
13284
|
] })
|
|
@@ -13132,8 +13301,8 @@ function MessageList({
|
|
|
13132
13301
|
/* @__PURE__ */ jsx17(Box16, { paddingLeft: 2, children: /* @__PURE__ */ jsx17(MarkdownText, { text: assistantDraft, theme }) })
|
|
13133
13302
|
] }),
|
|
13134
13303
|
canScrollDown && /* @__PURE__ */ jsxs17(Box16, { flexDirection: "row", gap: 1, paddingX: 1, children: [
|
|
13135
|
-
/* @__PURE__ */ jsx17(Text16, { color: theme.fgMuted,
|
|
13136
|
-
/* @__PURE__ */ jsxs17(Text16, { color: theme.
|
|
13304
|
+
/* @__PURE__ */ jsx17(Text16, { color: theme.fgMuted, children: "\u2574\u2574\u2574" }),
|
|
13305
|
+
/* @__PURE__ */ jsxs17(Text16, { color: theme.accent, children: [
|
|
13137
13306
|
"\u2193 ",
|
|
13138
13307
|
t("scrollHint")
|
|
13139
13308
|
] })
|
|
@@ -14097,6 +14266,26 @@ function formatValue(v, max = 60) {
|
|
|
14097
14266
|
const s = typeof v === "string" ? v : JSON.stringify(v) ?? "";
|
|
14098
14267
|
return s.length > max ? `${s.slice(0, max)}\u2026` : s;
|
|
14099
14268
|
}
|
|
14269
|
+
function toolIcon(name) {
|
|
14270
|
+
if (name === "bash" || name === "shell" || name.includes("bash")) return "\u26A1";
|
|
14271
|
+
if (name.includes("read") || name.includes("file")) return "\u{1F4C4}";
|
|
14272
|
+
if (name.includes("write") || name.includes("edit")) return "\u270F";
|
|
14273
|
+
if (name.includes("search") || name.includes("grep")) return "\u{1F50D}";
|
|
14274
|
+
if (name.includes("git")) return "\u2387";
|
|
14275
|
+
if (name.includes("web") || name.includes("fetch")) return "\u{1F310}";
|
|
14276
|
+
return "\u25C6";
|
|
14277
|
+
}
|
|
14278
|
+
function toolPreview(name, args) {
|
|
14279
|
+
if (name === "bash" || name === "shell") {
|
|
14280
|
+
const cmd = args.command ?? args.cmd ?? args.input;
|
|
14281
|
+
return typeof cmd === "string" ? cmd.slice(0, 40) : "";
|
|
14282
|
+
}
|
|
14283
|
+
const path42 = args.path ?? args.file_path ?? args.filePath ?? args.filename;
|
|
14284
|
+
if (typeof path42 === "string") return path42.split("/").slice(-2).join("/");
|
|
14285
|
+
const query = args.query ?? args.pattern ?? args.search ?? args.command;
|
|
14286
|
+
if (typeof query === "string") return query.slice(0, 40);
|
|
14287
|
+
return "";
|
|
14288
|
+
}
|
|
14100
14289
|
function ToolInspector({
|
|
14101
14290
|
toolCalls,
|
|
14102
14291
|
toolExecuting,
|
|
@@ -14128,36 +14317,48 @@ function ToolInspector({
|
|
|
14128
14317
|
parsedArgs = JSON.parse(selected?.args ?? "{}");
|
|
14129
14318
|
} catch {
|
|
14130
14319
|
}
|
|
14320
|
+
const preview = selected ? toolPreview(selected.name, parsedArgs) : "";
|
|
14131
14321
|
return /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
|
|
14132
14322
|
/* @__PURE__ */ jsxs32(Box31, { flexDirection: "row", justifyContent: "space-between", marginBottom: 1, children: [
|
|
14133
14323
|
/* @__PURE__ */ jsx32(Text31, { bold: true, color: theme.primary, children: t("toolInspectorTitle") }),
|
|
14134
|
-
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, dimColor: true, children:
|
|
14324
|
+
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, dimColor: true, children: toolCalls.length > 0 ? `${toolCalls.length}` : "" })
|
|
14135
14325
|
] }),
|
|
14136
14326
|
toolCalls.length === 0 ? /* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, dimColor: true, children: toolExecuting ? t("toolInspectorExecuting") : t("toolInspectorEmpty") }) : /* @__PURE__ */ jsxs32(Fragment6, { children: [
|
|
14137
14327
|
/* @__PURE__ */ jsx32(Box31, { flexDirection: "column", marginBottom: 1, children: visible.map((tc, i) => {
|
|
14138
14328
|
const absIdx = windowStart + i;
|
|
14139
14329
|
const sel = absIdx === clamped;
|
|
14140
14330
|
const done = tc.result !== void 0;
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14331
|
+
const running = toolExecuting && absIdx === toolCalls.length - 1;
|
|
14332
|
+
let tcArgs = {};
|
|
14333
|
+
try {
|
|
14334
|
+
tcArgs = JSON.parse(tc.args ?? "{}");
|
|
14335
|
+
} catch {
|
|
14336
|
+
}
|
|
14337
|
+
const linePreview = toolPreview(tc.name, tcArgs);
|
|
14338
|
+
return /* @__PURE__ */ jsx32(Box31, { flexDirection: "column", children: /* @__PURE__ */ jsxs32(Box31, { flexDirection: "row", gap: 1, children: [
|
|
14339
|
+
/* @__PURE__ */ jsx32(Text31, { color: done ? theme.success : running ? theme.warning : theme.fgMuted, children: done ? "\u2713" : running ? "\u2026" : "\u25CB" }),
|
|
14340
|
+
/* @__PURE__ */ jsx32(Text31, { color: theme.accent, children: toolIcon(tc.name) }),
|
|
14341
|
+
/* @__PURE__ */ jsx32(Text31, { color: sel ? theme.fg : theme.fgMuted, bold: sel, children: tc.name }),
|
|
14342
|
+
linePreview && /* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, dimColor: true, wrap: "truncate", children: linePreview })
|
|
14343
|
+
] }) }, tc.id);
|
|
14146
14344
|
}) }),
|
|
14147
14345
|
selected && /* @__PURE__ */ jsxs32(Box31, { flexDirection: "column", borderStyle: "single", borderColor: theme.border, paddingX: 1, children: [
|
|
14148
|
-
/* @__PURE__ */
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14346
|
+
/* @__PURE__ */ jsxs32(Box31, { flexDirection: "row", gap: 1, children: [
|
|
14347
|
+
/* @__PURE__ */ jsx32(Text31, { color: theme.accent, children: toolIcon(selected.name) }),
|
|
14348
|
+
/* @__PURE__ */ jsx32(Text31, { bold: true, color: theme.fg, children: selected.name })
|
|
14349
|
+
] }),
|
|
14350
|
+
preview && /* @__PURE__ */ jsx32(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text31, { color: theme.warning, wrap: "wrap", children: preview }) }),
|
|
14351
|
+
Object.entries(parsedArgs).slice(0, 4).map(([k, v]) => /* @__PURE__ */ jsxs32(Box31, { flexDirection: "row", gap: 1, children: [
|
|
14352
|
+
/* @__PURE__ */ jsxs32(Text31, { color: theme.fgMuted, children: [
|
|
14152
14353
|
k,
|
|
14153
14354
|
":"
|
|
14154
14355
|
] }),
|
|
14155
|
-
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, wrap: "truncate", children: formatValue(v) })
|
|
14356
|
+
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, dimColor: true, wrap: "truncate", children: formatValue(v) })
|
|
14156
14357
|
] }, k)),
|
|
14157
14358
|
selected.result !== void 0 && /* @__PURE__ */ jsxs32(Fragment6, { children: [
|
|
14158
14359
|
/* @__PURE__ */ jsx32(Text31, { children: " " }),
|
|
14159
14360
|
/* @__PURE__ */ jsx32(Text31, { bold: true, color: theme.fg, children: t("toolInspectorResult") }),
|
|
14160
|
-
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, wrap: "wrap", children: formatValue(selected.result,
|
|
14361
|
+
/* @__PURE__ */ jsx32(Text31, { color: theme.fgMuted, wrap: "wrap", children: formatValue(selected.result, 200) })
|
|
14161
14362
|
] })
|
|
14162
14363
|
] }),
|
|
14163
14364
|
toolCalls.length > LIST_SIZE && /* @__PURE__ */ jsx32(Box31, { marginTop: 1, children: /* @__PURE__ */ jsxs32(Text31, { color: theme.fgMuted, dimColor: true, children: [
|
|
@@ -14730,7 +14931,7 @@ function App(props) {
|
|
|
14730
14931
|
return /* @__PURE__ */ jsx33(Text32, { children: t("loadingDeepCode") });
|
|
14731
14932
|
}
|
|
14732
14933
|
const activeApproval = approvals[0];
|
|
14733
|
-
const hasParallelTasks = Object.keys(taskBuffers).length >
|
|
14934
|
+
const hasParallelTasks = Object.keys(taskBuffers).length > 0;
|
|
14734
14935
|
const approvalHasDiff = Boolean(activeApproval?.diff);
|
|
14735
14936
|
const detailPanelContent = detailContent === "timeline" ? /* @__PURE__ */ jsx33(
|
|
14736
14937
|
SessionTimeline,
|
|
@@ -14775,7 +14976,7 @@ function App(props) {
|
|
|
14775
14976
|
toolCalls,
|
|
14776
14977
|
toolExecuting,
|
|
14777
14978
|
theme,
|
|
14778
|
-
isActive:
|
|
14979
|
+
isActive: false,
|
|
14779
14980
|
onClose: () => useUIStore.getState().closePanel("detail")
|
|
14780
14981
|
}
|
|
14781
14982
|
);
|