@qwen-code/qwen-code 0.6.0-preview.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +1262 -824
- package/locales/en.js +8 -0
- package/locales/ru.js +8 -1
- package/locales/zh.js +8 -0
- package/package.json +2 -2
package/cli.js
CHANGED
|
@@ -154418,7 +154418,7 @@ __export(geminiContentGenerator_exports, {
|
|
|
154418
154418
|
createGeminiContentGenerator: () => createGeminiContentGenerator
|
|
154419
154419
|
});
|
|
154420
154420
|
function createGeminiContentGenerator(config2, gcConfig) {
|
|
154421
|
-
const version2 = "0.6.0
|
|
154421
|
+
const version2 = "0.6.0";
|
|
154422
154422
|
const userAgent2 = config2.userAgent || `QwenCode/${version2} (${process.platform}; ${process.arch})`;
|
|
154423
154423
|
const baseHeaders = {
|
|
154424
154424
|
"User-Agent": userAgent2
|
|
@@ -287291,6 +287291,7 @@ var init_en3 = __esm({
|
|
|
287291
287291
|
"(Use Enter to select{{tabText}})": "(Use Enter to select{{tabText}})",
|
|
287292
287292
|
", Tab to change focus": ", Tab to change focus",
|
|
287293
287293
|
"To see changes, Qwen Code must be restarted. Press r to exit and apply changes now.": "To see changes, Qwen Code must be restarted. Press r to exit and apply changes now.",
|
|
287294
|
+
'The command "/{{command}}" is not supported in non-interactive mode.': 'The command "/{{command}}" is not supported in non-interactive mode.',
|
|
287294
287295
|
// ============================================================================
|
|
287295
287296
|
// Settings Labels
|
|
287296
287297
|
// ============================================================================
|
|
@@ -287523,6 +287524,10 @@ var init_en3 = __esm({
|
|
|
287523
287524
|
"Already generating summary, wait for previous request to complete": "Already generating summary, wait for previous request to complete",
|
|
287524
287525
|
"No conversation found to summarize.": "No conversation found to summarize.",
|
|
287525
287526
|
"Failed to generate project context summary: {{error}}": "Failed to generate project context summary: {{error}}",
|
|
287527
|
+
"Saved project summary to {{filePathForDisplay}}.": "Saved project summary to {{filePathForDisplay}}.",
|
|
287528
|
+
"Saving project summary...": "Saving project summary...",
|
|
287529
|
+
"Generating project summary...": "Generating project summary...",
|
|
287530
|
+
"Failed to generate summary - no text content received from LLM response": "Failed to generate summary - no text content received from LLM response",
|
|
287526
287531
|
// ============================================================================
|
|
287527
287532
|
// Commands - Model
|
|
287528
287533
|
// ============================================================================
|
|
@@ -288118,6 +288123,7 @@ var init_ru = __esm({
|
|
|
288118
288123
|
"(Use Enter to select{{tabText}})": "(Enter \u0434\u043B\u044F \u0432\u044B\u0431\u043E\u0440\u0430{{tabText}})",
|
|
288119
288124
|
", Tab to change focus": ", Tab \u0434\u043B\u044F \u0441\u043C\u0435\u043D\u044B \u0444\u043E\u043A\u0443\u0441\u0430",
|
|
288120
288125
|
"To see changes, Qwen Code must be restarted. Press r to exit and apply changes now.": "\u0414\u043B\u044F \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C Qwen Code. \u041D\u0430\u0436\u043C\u0438\u0442\u0435 r \u0434\u043B\u044F \u0432\u044B\u0445\u043E\u0434\u0430 \u0438 \u043F\u0440\u0438\u043C\u0435\u043D\u0435\u043D\u0438\u044F \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439.",
|
|
288126
|
+
'The command "/{{command}}" is not supported in non-interactive mode.': '\u041A\u043E\u043C\u0430\u043D\u0434\u0430 "/{{command}}" \u043D\u0435 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F \u0432 \u043D\u0435\u0438\u043D\u0442\u0435\u0440\u0430\u043A\u0442\u0438\u0432\u043D\u043E\u043C \u0440\u0435\u0436\u0438\u043C\u0435.',
|
|
288121
288127
|
// ============================================================================
|
|
288122
288128
|
// Метки настроек
|
|
288123
288129
|
// ============================================================================
|
|
@@ -288350,6 +288356,10 @@ var init_ru = __esm({
|
|
|
288350
288356
|
"Already generating summary, wait for previous request to complete": "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0441\u0432\u043E\u0434\u043A\u0438 \u0443\u0436\u0435 \u0432\u044B\u043F\u043E\u043B\u043D\u044F\u0435\u0442\u0441\u044F, \u0434\u043E\u0436\u0434\u0438\u0442\u0435\u0441\u044C \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043D\u0438\u044F \u043F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0435\u0433\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0430",
|
|
288351
288357
|
"No conversation found to summarize.": "\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0434\u0438\u0430\u043B\u043E\u0433\u043E\u0432 \u0434\u043B\u044F \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u0441\u0432\u043E\u0434\u043A\u0438.",
|
|
288352
288358
|
"Failed to generate project context summary: {{error}}": "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0441\u0432\u043E\u0434\u043A\u0443 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u0430 \u043F\u0440\u043E\u0435\u043A\u0442\u0430: {{error}}",
|
|
288359
|
+
"Saved project summary to {{filePathForDisplay}}.": "\u0421\u0432\u043E\u0434\u043A\u0430 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0430 \u0432 {{filePathForDisplay}}",
|
|
288360
|
+
"Saving project summary...": "\u0421\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u0438\u0435 \u0441\u0432\u043E\u0434\u043A\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430...",
|
|
288361
|
+
"Generating project summary...": "\u0413\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u0441\u0432\u043E\u0434\u043A\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430...",
|
|
288362
|
+
"Failed to generate summary - no text content received from LLM response": "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0441\u0432\u043E\u0434\u043A\u0443 - \u043D\u0435 \u043F\u043E\u043B\u0443\u0447\u0435\u043D \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0439 \u043A\u043E\u043D\u0442\u0435\u043D\u0442 \u0438\u0437 \u043E\u0442\u0432\u0435\u0442\u0430 LLM",
|
|
288353
288363
|
// ============================================================================
|
|
288354
288364
|
// Команды - Модель
|
|
288355
288365
|
// ============================================================================
|
|
@@ -288944,6 +288954,7 @@ var init_zh = __esm({
|
|
|
288944
288954
|
"(Use Enter to select{{tabText}})": "\uFF08\u4F7F\u7528 Enter \u9009\u62E9{{tabText}}\uFF09",
|
|
288945
288955
|
", Tab to change focus": "\uFF0CTab \u5207\u6362\u7126\u70B9",
|
|
288946
288956
|
"To see changes, Qwen Code must be restarted. Press r to exit and apply changes now.": "\u8981\u67E5\u770B\u66F4\u6539\uFF0C\u5FC5\u987B\u91CD\u542F Qwen Code\u3002\u6309 r \u9000\u51FA\u5E76\u7ACB\u5373\u5E94\u7528\u66F4\u6539\u3002",
|
|
288957
|
+
'The command "/{{command}}" is not supported in non-interactive mode.': '\u4E0D\u652F\u6301\u5728\u975E\u4EA4\u4E92\u6A21\u5F0F\u4E0B\u4F7F\u7528\u547D\u4EE4 "/{{command}}"\u3002',
|
|
288947
288958
|
// ============================================================================
|
|
288948
288959
|
// Settings Labels
|
|
288949
288960
|
// ============================================================================
|
|
@@ -289176,6 +289187,10 @@ var init_zh = __esm({
|
|
|
289176
289187
|
"Already generating summary, wait for previous request to complete": "\u6B63\u5728\u751F\u6210\u6458\u8981\uFF0C\u8BF7\u7B49\u5F85\u4E0A\u4E00\u4E2A\u8BF7\u6C42\u5B8C\u6210",
|
|
289177
289188
|
"No conversation found to summarize.": "\u672A\u627E\u5230\u8981\u603B\u7ED3\u7684\u5BF9\u8BDD",
|
|
289178
289189
|
"Failed to generate project context summary: {{error}}": "\u751F\u6210\u9879\u76EE\u4E0A\u4E0B\u6587\u6458\u8981\u5931\u8D25\uFF1A{{error}}",
|
|
289190
|
+
"Saved project summary to {{filePathForDisplay}}.": "\u9879\u76EE\u6458\u8981\u5DF2\u4FDD\u5B58\u5230 {{filePathForDisplay}}",
|
|
289191
|
+
"Saving project summary...": "\u6B63\u5728\u4FDD\u5B58\u9879\u76EE\u6458\u8981...",
|
|
289192
|
+
"Generating project summary...": "\u6B63\u5728\u751F\u6210\u9879\u76EE\u6458\u8981...",
|
|
289193
|
+
"Failed to generate summary - no text content received from LLM response": "\u751F\u6210\u6458\u8981\u5931\u8D25 - \u672A\u4ECE LLM \u54CD\u5E94\u4E2D\u63A5\u6536\u5230\u6587\u672C\u5185\u5BB9",
|
|
289179
289194
|
// ============================================================================
|
|
289180
289195
|
// Commands - Model
|
|
289181
289196
|
// ============================================================================
|
|
@@ -355471,7 +355486,7 @@ __name(getPackageJson, "getPackageJson");
|
|
|
355471
355486
|
// packages/cli/src/utils/version.ts
|
|
355472
355487
|
async function getCliVersion() {
|
|
355473
355488
|
const pkgJson = await getPackageJson();
|
|
355474
|
-
return "0.6.0
|
|
355489
|
+
return "0.6.0";
|
|
355475
355490
|
}
|
|
355476
355491
|
__name(getCliVersion, "getCliVersion");
|
|
355477
355492
|
|
|
@@ -362878,6 +362893,110 @@ import { randomUUID as randomUUID6 } from "node:crypto";
|
|
|
362878
362893
|
// packages/cli/src/utils/nonInteractiveHelpers.ts
|
|
362879
362894
|
init_esbuild_shims();
|
|
362880
362895
|
|
|
362896
|
+
// packages/cli/src/ui/utils/computeStats.ts
|
|
362897
|
+
init_esbuild_shims();
|
|
362898
|
+
function calculateErrorRate(metrics2) {
|
|
362899
|
+
if (metrics2.api.totalRequests === 0) {
|
|
362900
|
+
return 0;
|
|
362901
|
+
}
|
|
362902
|
+
return metrics2.api.totalErrors / metrics2.api.totalRequests * 100;
|
|
362903
|
+
}
|
|
362904
|
+
__name(calculateErrorRate, "calculateErrorRate");
|
|
362905
|
+
function calculateAverageLatency(metrics2) {
|
|
362906
|
+
if (metrics2.api.totalRequests === 0) {
|
|
362907
|
+
return 0;
|
|
362908
|
+
}
|
|
362909
|
+
return metrics2.api.totalLatencyMs / metrics2.api.totalRequests;
|
|
362910
|
+
}
|
|
362911
|
+
__name(calculateAverageLatency, "calculateAverageLatency");
|
|
362912
|
+
function calculateCacheHitRate(metrics2) {
|
|
362913
|
+
if (metrics2.tokens.prompt === 0) {
|
|
362914
|
+
return 0;
|
|
362915
|
+
}
|
|
362916
|
+
return metrics2.tokens.cached / metrics2.tokens.prompt * 100;
|
|
362917
|
+
}
|
|
362918
|
+
__name(calculateCacheHitRate, "calculateCacheHitRate");
|
|
362919
|
+
var computeSessionStats = /* @__PURE__ */ __name((metrics2) => {
|
|
362920
|
+
const { models, tools, files } = metrics2;
|
|
362921
|
+
const totalApiTime = Object.values(models).reduce(
|
|
362922
|
+
(acc, model) => acc + model.api.totalLatencyMs,
|
|
362923
|
+
0
|
|
362924
|
+
);
|
|
362925
|
+
const totalToolTime = tools.totalDurationMs;
|
|
362926
|
+
const agentActiveTime = totalApiTime + totalToolTime;
|
|
362927
|
+
const apiTimePercent = agentActiveTime > 0 ? totalApiTime / agentActiveTime * 100 : 0;
|
|
362928
|
+
const toolTimePercent = agentActiveTime > 0 ? totalToolTime / agentActiveTime * 100 : 0;
|
|
362929
|
+
const totalCachedTokens = Object.values(models).reduce(
|
|
362930
|
+
(acc, model) => acc + model.tokens.cached,
|
|
362931
|
+
0
|
|
362932
|
+
);
|
|
362933
|
+
const totalPromptTokens = Object.values(models).reduce(
|
|
362934
|
+
(acc, model) => acc + model.tokens.prompt,
|
|
362935
|
+
0
|
|
362936
|
+
);
|
|
362937
|
+
const cacheEfficiency = totalPromptTokens > 0 ? totalCachedTokens / totalPromptTokens * 100 : 0;
|
|
362938
|
+
const totalDecisions = tools.totalDecisions.accept + tools.totalDecisions.reject + tools.totalDecisions.modify;
|
|
362939
|
+
const successRate = tools.totalCalls > 0 ? tools.totalSuccess / tools.totalCalls * 100 : 0;
|
|
362940
|
+
const agreementRate = totalDecisions > 0 ? tools.totalDecisions.accept / totalDecisions * 100 : 0;
|
|
362941
|
+
return {
|
|
362942
|
+
totalApiTime,
|
|
362943
|
+
totalToolTime,
|
|
362944
|
+
agentActiveTime,
|
|
362945
|
+
apiTimePercent,
|
|
362946
|
+
toolTimePercent,
|
|
362947
|
+
cacheEfficiency,
|
|
362948
|
+
totalDecisions,
|
|
362949
|
+
successRate,
|
|
362950
|
+
agreementRate,
|
|
362951
|
+
totalCachedTokens,
|
|
362952
|
+
totalPromptTokens,
|
|
362953
|
+
totalLinesAdded: files.totalLinesAdded,
|
|
362954
|
+
totalLinesRemoved: files.totalLinesRemoved
|
|
362955
|
+
};
|
|
362956
|
+
}, "computeSessionStats");
|
|
362957
|
+
|
|
362958
|
+
// packages/cli/src/nonInteractiveCliCommands.ts
|
|
362959
|
+
init_esbuild_shims();
|
|
362960
|
+
|
|
362961
|
+
// packages/cli/src/utils/commands.ts
|
|
362962
|
+
init_esbuild_shims();
|
|
362963
|
+
|
|
362964
|
+
// packages/cli/src/ui/commands/types.ts
|
|
362965
|
+
init_esbuild_shims();
|
|
362966
|
+
|
|
362967
|
+
// packages/cli/src/utils/commands.ts
|
|
362968
|
+
var parseSlashCommand = /* @__PURE__ */ __name((query, commands) => {
|
|
362969
|
+
const trimmed2 = query.trim();
|
|
362970
|
+
const parts = trimmed2.substring(1).trim().split(/\s+/);
|
|
362971
|
+
const commandPath = parts.filter((p2) => p2);
|
|
362972
|
+
let currentCommands = commands;
|
|
362973
|
+
let commandToExecute;
|
|
362974
|
+
let pathIndex = 0;
|
|
362975
|
+
const canonicalPath = [];
|
|
362976
|
+
for (const part of commandPath) {
|
|
362977
|
+
let foundCommand = currentCommands.find((cmd) => cmd.name === part);
|
|
362978
|
+
if (!foundCommand) {
|
|
362979
|
+
foundCommand = currentCommands.find(
|
|
362980
|
+
(cmd) => cmd.altNames?.includes(part)
|
|
362981
|
+
);
|
|
362982
|
+
}
|
|
362983
|
+
if (foundCommand) {
|
|
362984
|
+
commandToExecute = foundCommand;
|
|
362985
|
+
canonicalPath.push(foundCommand.name);
|
|
362986
|
+
pathIndex++;
|
|
362987
|
+
if (foundCommand.subCommands) {
|
|
362988
|
+
currentCommands = foundCommand.subCommands;
|
|
362989
|
+
} else {
|
|
362990
|
+
break;
|
|
362991
|
+
}
|
|
362992
|
+
} else {
|
|
362993
|
+
break;
|
|
362994
|
+
}
|
|
362995
|
+
}
|
|
362996
|
+
const args = parts.slice(pathIndex).join(" ");
|
|
362997
|
+
return { commandToExecute, args, canonicalPath };
|
|
362998
|
+
}, "parseSlashCommand");
|
|
362999
|
+
|
|
362881
363000
|
// packages/cli/src/services/CommandService.ts
|
|
362882
363001
|
init_esbuild_shims();
|
|
362883
363002
|
var CommandService = class _CommandService {
|
|
@@ -362961,9 +363080,6 @@ init_esbuild_shims();
|
|
|
362961
363080
|
// packages/cli/src/ui/commands/aboutCommand.ts
|
|
362962
363081
|
init_esbuild_shims();
|
|
362963
363082
|
|
|
362964
|
-
// packages/cli/src/ui/commands/types.ts
|
|
362965
|
-
init_esbuild_shims();
|
|
362966
|
-
|
|
362967
363083
|
// packages/cli/src/ui/types.ts
|
|
362968
363084
|
init_esbuild_shims();
|
|
362969
363085
|
var import_react26 = __toESM(require_react(), 1);
|
|
@@ -363046,7 +363162,7 @@ var formatDuration = /* @__PURE__ */ __name((milliseconds) => {
|
|
|
363046
363162
|
|
|
363047
363163
|
// packages/cli/src/generated/git-commit.ts
|
|
363048
363164
|
init_esbuild_shims();
|
|
363049
|
-
var GIT_COMMIT_INFO2 = "
|
|
363165
|
+
var GIT_COMMIT_INFO2 = "17eb20c1";
|
|
363050
363166
|
|
|
363051
363167
|
// packages/cli/src/utils/systemInfo.ts
|
|
363052
363168
|
async function getNpmVersion() {
|
|
@@ -363381,7 +363497,8 @@ var compressCommand = {
|
|
|
363381
363497
|
kind: "built-in" /* BUILT_IN */,
|
|
363382
363498
|
action: /* @__PURE__ */ __name(async (context2) => {
|
|
363383
363499
|
const { ui: ui2 } = context2;
|
|
363384
|
-
|
|
363500
|
+
const executionMode = context2.executionMode ?? "interactive";
|
|
363501
|
+
if (executionMode === "interactive" && ui2.pendingItem) {
|
|
363385
363502
|
ui2.addItem(
|
|
363386
363503
|
{
|
|
363387
363504
|
type: "error" /* ERROR */,
|
|
@@ -363400,11 +363517,72 @@ var compressCommand = {
|
|
|
363400
363517
|
compressionStatus: null
|
|
363401
363518
|
}
|
|
363402
363519
|
};
|
|
363403
|
-
|
|
363404
|
-
|
|
363520
|
+
const config2 = context2.services.config;
|
|
363521
|
+
const geminiClient = config2?.getGeminiClient();
|
|
363522
|
+
if (!config2 || !geminiClient) {
|
|
363523
|
+
return {
|
|
363524
|
+
type: "message",
|
|
363525
|
+
messageType: "error",
|
|
363526
|
+
content: t4("Config not loaded.")
|
|
363527
|
+
};
|
|
363528
|
+
}
|
|
363529
|
+
const doCompress = /* @__PURE__ */ __name(async () => {
|
|
363405
363530
|
const promptId = `compress-${Date.now()}`;
|
|
363406
|
-
|
|
363407
|
-
|
|
363531
|
+
return await geminiClient.tryCompressChat(promptId, true);
|
|
363532
|
+
}, "doCompress");
|
|
363533
|
+
if (executionMode === "acp") {
|
|
363534
|
+
const messages = /* @__PURE__ */ __name(async function* () {
|
|
363535
|
+
try {
|
|
363536
|
+
yield {
|
|
363537
|
+
messageType: "info",
|
|
363538
|
+
content: "Compressing context..."
|
|
363539
|
+
};
|
|
363540
|
+
const compressed = await doCompress();
|
|
363541
|
+
if (!compressed) {
|
|
363542
|
+
yield {
|
|
363543
|
+
messageType: "error",
|
|
363544
|
+
content: t4("Failed to compress chat history.")
|
|
363545
|
+
};
|
|
363546
|
+
return;
|
|
363547
|
+
}
|
|
363548
|
+
yield {
|
|
363549
|
+
messageType: "info",
|
|
363550
|
+
content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
|
|
363551
|
+
};
|
|
363552
|
+
} catch (e4) {
|
|
363553
|
+
yield {
|
|
363554
|
+
messageType: "error",
|
|
363555
|
+
content: t4("Failed to compress chat history: {{error}}", {
|
|
363556
|
+
error: e4 instanceof Error ? e4.message : String(e4)
|
|
363557
|
+
})
|
|
363558
|
+
};
|
|
363559
|
+
}
|
|
363560
|
+
}, "messages");
|
|
363561
|
+
return { type: "stream_messages", messages: messages() };
|
|
363562
|
+
}
|
|
363563
|
+
try {
|
|
363564
|
+
if (executionMode === "interactive") {
|
|
363565
|
+
ui2.setPendingItem(pendingMessage);
|
|
363566
|
+
}
|
|
363567
|
+
const compressed = await doCompress();
|
|
363568
|
+
if (!compressed) {
|
|
363569
|
+
if (executionMode === "interactive") {
|
|
363570
|
+
ui2.addItem(
|
|
363571
|
+
{
|
|
363572
|
+
type: "error" /* ERROR */,
|
|
363573
|
+
text: t4("Failed to compress chat history.")
|
|
363574
|
+
},
|
|
363575
|
+
Date.now()
|
|
363576
|
+
);
|
|
363577
|
+
return;
|
|
363578
|
+
}
|
|
363579
|
+
return {
|
|
363580
|
+
type: "message",
|
|
363581
|
+
messageType: "error",
|
|
363582
|
+
content: t4("Failed to compress chat history.")
|
|
363583
|
+
};
|
|
363584
|
+
}
|
|
363585
|
+
if (executionMode === "interactive") {
|
|
363408
363586
|
ui2.addItem(
|
|
363409
363587
|
{
|
|
363410
363588
|
type: "compression" /* COMPRESSION */,
|
|
@@ -363417,27 +363595,37 @@ var compressCommand = {
|
|
|
363417
363595
|
},
|
|
363418
363596
|
Date.now()
|
|
363419
363597
|
);
|
|
363420
|
-
|
|
363598
|
+
return;
|
|
363599
|
+
}
|
|
363600
|
+
return {
|
|
363601
|
+
type: "message",
|
|
363602
|
+
messageType: "info",
|
|
363603
|
+
content: `Context compressed (${compressed.originalTokenCount} -> ${compressed.newTokenCount}).`
|
|
363604
|
+
};
|
|
363605
|
+
} catch (e4) {
|
|
363606
|
+
if (executionMode === "interactive") {
|
|
363421
363607
|
ui2.addItem(
|
|
363422
363608
|
{
|
|
363423
363609
|
type: "error" /* ERROR */,
|
|
363424
|
-
text: t4("Failed to compress chat history
|
|
363610
|
+
text: t4("Failed to compress chat history: {{error}}", {
|
|
363611
|
+
error: e4 instanceof Error ? e4.message : String(e4)
|
|
363612
|
+
})
|
|
363425
363613
|
},
|
|
363426
363614
|
Date.now()
|
|
363427
363615
|
);
|
|
363616
|
+
return;
|
|
363428
363617
|
}
|
|
363429
|
-
|
|
363430
|
-
|
|
363431
|
-
|
|
363432
|
-
|
|
363433
|
-
|
|
363434
|
-
|
|
363435
|
-
|
|
363436
|
-
},
|
|
363437
|
-
Date.now()
|
|
363438
|
-
);
|
|
363618
|
+
return {
|
|
363619
|
+
type: "message",
|
|
363620
|
+
messageType: "error",
|
|
363621
|
+
content: t4("Failed to compress chat history: {{error}}", {
|
|
363622
|
+
error: e4 instanceof Error ? e4.message : String(e4)
|
|
363623
|
+
})
|
|
363624
|
+
};
|
|
363439
363625
|
} finally {
|
|
363440
|
-
|
|
363626
|
+
if (executionMode === "interactive") {
|
|
363627
|
+
ui2.setPendingItem(null);
|
|
363628
|
+
}
|
|
363441
363629
|
}
|
|
363442
363630
|
}, "action")
|
|
363443
363631
|
};
|
|
@@ -365618,6 +365806,7 @@ var summaryCommand = {
|
|
|
365618
365806
|
action: /* @__PURE__ */ __name(async (context2) => {
|
|
365619
365807
|
const { config: config2 } = context2.services;
|
|
365620
365808
|
const { ui: ui2 } = context2;
|
|
365809
|
+
const executionMode = context2.executionMode ?? "interactive";
|
|
365621
365810
|
if (!config2) {
|
|
365622
365811
|
return {
|
|
365623
365812
|
type: "message",
|
|
@@ -365633,7 +365822,7 @@ var summaryCommand = {
|
|
|
365633
365822
|
content: t4("No chat client available to generate summary.")
|
|
365634
365823
|
};
|
|
365635
365824
|
}
|
|
365636
|
-
if (ui2.pendingItem) {
|
|
365825
|
+
if (executionMode === "interactive" && ui2.pendingItem) {
|
|
365637
365826
|
ui2.addItem(
|
|
365638
365827
|
{
|
|
365639
365828
|
type: "error",
|
|
@@ -365651,25 +365840,17 @@ var summaryCommand = {
|
|
|
365651
365840
|
)
|
|
365652
365841
|
};
|
|
365653
365842
|
}
|
|
365654
|
-
|
|
365843
|
+
const getChatHistory = /* @__PURE__ */ __name(() => {
|
|
365655
365844
|
const chat = geminiClient.getChat();
|
|
365656
|
-
|
|
365657
|
-
|
|
365658
|
-
|
|
365659
|
-
|
|
365660
|
-
|
|
365661
|
-
|
|
365662
|
-
|
|
365663
|
-
|
|
365664
|
-
const
|
|
365665
|
-
type: "summary",
|
|
365666
|
-
summary: {
|
|
365667
|
-
isPending: true,
|
|
365668
|
-
stage: "generating"
|
|
365669
|
-
}
|
|
365670
|
-
};
|
|
365671
|
-
ui2.setPendingItem(pendingMessage);
|
|
365672
|
-
const conversationContext = history.map((message) => ({
|
|
365845
|
+
return chat.getHistory();
|
|
365846
|
+
}, "getChatHistory");
|
|
365847
|
+
const validateChatHistory = /* @__PURE__ */ __name((history2) => {
|
|
365848
|
+
if (history2.length <= 2) {
|
|
365849
|
+
throw new Error(t4("No conversation found to summarize."));
|
|
365850
|
+
}
|
|
365851
|
+
}, "validateChatHistory");
|
|
365852
|
+
const generateSummaryMarkdown = /* @__PURE__ */ __name(async (history2) => {
|
|
365853
|
+
const conversationContext = history2.map((message) => ({
|
|
365673
365854
|
role: message.role,
|
|
365674
365855
|
parts: message.parts
|
|
365675
365856
|
}));
|
|
@@ -365693,16 +365874,14 @@ var summaryCommand = {
|
|
|
365693
365874
|
const markdownSummary = parts?.map((part) => part.text).filter((text) => typeof text === "string").join("") || "";
|
|
365694
365875
|
if (!markdownSummary) {
|
|
365695
365876
|
throw new Error(
|
|
365696
|
-
|
|
365877
|
+
t4(
|
|
365878
|
+
"Failed to generate summary - no text content received from LLM response"
|
|
365879
|
+
)
|
|
365697
365880
|
);
|
|
365698
365881
|
}
|
|
365699
|
-
|
|
365700
|
-
|
|
365701
|
-
|
|
365702
|
-
isPending: true,
|
|
365703
|
-
stage: "saving"
|
|
365704
|
-
}
|
|
365705
|
-
});
|
|
365882
|
+
return markdownSummary;
|
|
365883
|
+
}, "generateSummaryMarkdown");
|
|
365884
|
+
const saveSummaryToDisk = /* @__PURE__ */ __name(async (markdownSummary) => {
|
|
365706
365885
|
const projectRoot = config2.getProjectRoot();
|
|
365707
365886
|
const qwenDir = path87.join(projectRoot, ".qwen");
|
|
365708
365887
|
try {
|
|
@@ -365718,42 +365897,137 @@ var summaryCommand = {
|
|
|
365718
365897
|
**Update time**: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
365719
365898
|
`;
|
|
365720
365899
|
await fsPromises5.writeFile(summaryPath, summaryContent, "utf8");
|
|
365900
|
+
return {
|
|
365901
|
+
filePathForDisplay: ".qwen/PROJECT_SUMMARY.md",
|
|
365902
|
+
fullPath: summaryPath
|
|
365903
|
+
};
|
|
365904
|
+
}, "saveSummaryToDisk");
|
|
365905
|
+
const emitInteractivePending = /* @__PURE__ */ __name((stage) => {
|
|
365906
|
+
if (executionMode !== "interactive") {
|
|
365907
|
+
return;
|
|
365908
|
+
}
|
|
365909
|
+
const pendingMessage = {
|
|
365910
|
+
type: "summary",
|
|
365911
|
+
summary: {
|
|
365912
|
+
isPending: true,
|
|
365913
|
+
stage
|
|
365914
|
+
}
|
|
365915
|
+
};
|
|
365916
|
+
ui2.setPendingItem(pendingMessage);
|
|
365917
|
+
}, "emitInteractivePending");
|
|
365918
|
+
const completeInteractive = /* @__PURE__ */ __name((filePathForDisplay) => {
|
|
365919
|
+
if (executionMode !== "interactive") {
|
|
365920
|
+
return;
|
|
365921
|
+
}
|
|
365721
365922
|
ui2.setPendingItem(null);
|
|
365722
365923
|
const completedSummaryItem = {
|
|
365723
365924
|
type: "summary",
|
|
365724
365925
|
summary: {
|
|
365725
365926
|
isPending: false,
|
|
365726
365927
|
stage: "completed",
|
|
365727
|
-
filePath:
|
|
365928
|
+
filePath: filePathForDisplay
|
|
365728
365929
|
}
|
|
365729
365930
|
};
|
|
365730
365931
|
ui2.addItem(completedSummaryItem, Date.now());
|
|
365731
|
-
|
|
365732
|
-
|
|
365733
|
-
|
|
365734
|
-
|
|
365735
|
-
|
|
365736
|
-
|
|
365737
|
-
|
|
365932
|
+
}, "completeInteractive");
|
|
365933
|
+
const formatErrorMessage = /* @__PURE__ */ __name((error2) => t4("Failed to generate project context summary: {{error}}", {
|
|
365934
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
365935
|
+
}), "formatErrorMessage");
|
|
365936
|
+
const failInteractive = /* @__PURE__ */ __name((error2) => {
|
|
365937
|
+
if (executionMode !== "interactive") {
|
|
365938
|
+
return;
|
|
365939
|
+
}
|
|
365738
365940
|
ui2.setPendingItem(null);
|
|
365739
365941
|
ui2.addItem(
|
|
365740
365942
|
{
|
|
365741
365943
|
type: "error",
|
|
365742
|
-
text: `\u274C ${
|
|
365743
|
-
"Failed to generate project context summary: {{error}}",
|
|
365744
|
-
{
|
|
365745
|
-
error: error2 instanceof Error ? error2.message : String(error2)
|
|
365746
|
-
}
|
|
365747
|
-
)}`
|
|
365944
|
+
text: `\u274C ${formatErrorMessage(error2)}`
|
|
365748
365945
|
},
|
|
365749
365946
|
Date.now()
|
|
365750
365947
|
);
|
|
365948
|
+
}, "failInteractive");
|
|
365949
|
+
const formatSuccessMessage = /* @__PURE__ */ __name((filePathForDisplay) => t4("Saved project summary to {{filePathForDisplay}}.", {
|
|
365950
|
+
filePathForDisplay
|
|
365951
|
+
}), "formatSuccessMessage");
|
|
365952
|
+
const returnNoConversationMessage = /* @__PURE__ */ __name(() => {
|
|
365953
|
+
const msg = t4("No conversation found to summarize.");
|
|
365954
|
+
if (executionMode === "acp") {
|
|
365955
|
+
const messages = /* @__PURE__ */ __name(async function* () {
|
|
365956
|
+
yield {
|
|
365957
|
+
messageType: "info",
|
|
365958
|
+
content: msg
|
|
365959
|
+
};
|
|
365960
|
+
}, "messages");
|
|
365961
|
+
return {
|
|
365962
|
+
type: "stream_messages",
|
|
365963
|
+
messages: messages()
|
|
365964
|
+
};
|
|
365965
|
+
}
|
|
365966
|
+
return {
|
|
365967
|
+
type: "message",
|
|
365968
|
+
messageType: "info",
|
|
365969
|
+
content: msg
|
|
365970
|
+
};
|
|
365971
|
+
}, "returnNoConversationMessage");
|
|
365972
|
+
const executeSummaryGeneration = /* @__PURE__ */ __name(async (history2) => {
|
|
365973
|
+
emitInteractivePending("generating");
|
|
365974
|
+
const markdownSummary = await generateSummaryMarkdown(history2);
|
|
365975
|
+
emitInteractivePending("saving");
|
|
365976
|
+
const { filePathForDisplay } = await saveSummaryToDisk(markdownSummary);
|
|
365977
|
+
completeInteractive(filePathForDisplay);
|
|
365978
|
+
return { markdownSummary, filePathForDisplay };
|
|
365979
|
+
}, "executeSummaryGeneration");
|
|
365980
|
+
const history = getChatHistory();
|
|
365981
|
+
try {
|
|
365982
|
+
validateChatHistory(history);
|
|
365983
|
+
} catch (_error) {
|
|
365984
|
+
return returnNoConversationMessage();
|
|
365985
|
+
}
|
|
365986
|
+
if (executionMode === "acp") {
|
|
365987
|
+
const messages = /* @__PURE__ */ __name(async function* () {
|
|
365988
|
+
try {
|
|
365989
|
+
yield {
|
|
365990
|
+
messageType: "info",
|
|
365991
|
+
content: t4("Generating project summary...")
|
|
365992
|
+
};
|
|
365993
|
+
const { filePathForDisplay } = await executeSummaryGeneration(history);
|
|
365994
|
+
yield {
|
|
365995
|
+
messageType: "info",
|
|
365996
|
+
content: formatSuccessMessage(filePathForDisplay)
|
|
365997
|
+
};
|
|
365998
|
+
} catch (error2) {
|
|
365999
|
+
failInteractive(error2);
|
|
366000
|
+
yield {
|
|
366001
|
+
messageType: "error",
|
|
366002
|
+
content: formatErrorMessage(error2)
|
|
366003
|
+
};
|
|
366004
|
+
}
|
|
366005
|
+
}, "messages");
|
|
366006
|
+
return {
|
|
366007
|
+
type: "stream_messages",
|
|
366008
|
+
messages: messages()
|
|
366009
|
+
};
|
|
366010
|
+
}
|
|
366011
|
+
try {
|
|
366012
|
+
const { filePathForDisplay } = await executeSummaryGeneration(history);
|
|
366013
|
+
if (executionMode === "non_interactive") {
|
|
366014
|
+
return {
|
|
366015
|
+
type: "message",
|
|
366016
|
+
messageType: "info",
|
|
366017
|
+
content: formatSuccessMessage(filePathForDisplay)
|
|
366018
|
+
};
|
|
366019
|
+
}
|
|
366020
|
+
return {
|
|
366021
|
+
type: "message",
|
|
366022
|
+
messageType: "info",
|
|
366023
|
+
content: ""
|
|
366024
|
+
};
|
|
366025
|
+
} catch (error2) {
|
|
366026
|
+
failInteractive(error2);
|
|
365751
366027
|
return {
|
|
365752
366028
|
type: "message",
|
|
365753
366029
|
messageType: "error",
|
|
365754
|
-
content:
|
|
365755
|
-
error: error2 instanceof Error ? error2.message : String(error2)
|
|
365756
|
-
})
|
|
366030
|
+
content: formatErrorMessage(error2)
|
|
365757
366031
|
};
|
|
365758
366032
|
}
|
|
365759
366033
|
}, "action")
|
|
@@ -366517,67 +366791,720 @@ var BuiltinCommandLoader = class {
|
|
|
366517
366791
|
}
|
|
366518
366792
|
};
|
|
366519
366793
|
|
|
366520
|
-
// packages/cli/src/
|
|
366794
|
+
// packages/cli/src/services/FileCommandLoader.ts
|
|
366521
366795
|
init_esbuild_shims();
|
|
366522
|
-
|
|
366523
|
-
|
|
366524
|
-
|
|
366796
|
+
var import_toml = __toESM(require_toml(), 1);
|
|
366797
|
+
init_esm11();
|
|
366798
|
+
init_zod();
|
|
366799
|
+
import { promises as fs81 } from "node:fs";
|
|
366800
|
+
import path90 from "node:path";
|
|
366801
|
+
|
|
366802
|
+
// packages/cli/src/services/prompt-processors/argumentProcessor.ts
|
|
366803
|
+
init_esbuild_shims();
|
|
366804
|
+
var DefaultArgumentProcessor = class {
|
|
366805
|
+
static {
|
|
366806
|
+
__name(this, "DefaultArgumentProcessor");
|
|
366525
366807
|
}
|
|
366526
|
-
|
|
366808
|
+
async process(prompt, context2) {
|
|
366809
|
+
if (context2.invocation?.args) {
|
|
366810
|
+
return appendToLastTextPart(prompt, context2.invocation.raw);
|
|
366811
|
+
}
|
|
366812
|
+
return prompt;
|
|
366813
|
+
}
|
|
366814
|
+
};
|
|
366815
|
+
|
|
366816
|
+
// packages/cli/src/services/prompt-processors/types.ts
|
|
366817
|
+
init_esbuild_shims();
|
|
366818
|
+
var SHORTHAND_ARGS_PLACEHOLDER = "{{args}}";
|
|
366819
|
+
var SHELL_INJECTION_TRIGGER = "!{";
|
|
366820
|
+
var AT_FILE_INJECTION_TRIGGER = "@{";
|
|
366821
|
+
|
|
366822
|
+
// packages/cli/src/services/prompt-processors/shellProcessor.ts
|
|
366823
|
+
init_esbuild_shims();
|
|
366824
|
+
|
|
366825
|
+
// packages/cli/src/services/prompt-processors/injectionParser.ts
|
|
366826
|
+
init_esbuild_shims();
|
|
366827
|
+
function extractInjections(prompt, trigger, contextName) {
|
|
366828
|
+
const injections = [];
|
|
366829
|
+
let index = 0;
|
|
366830
|
+
while (index < prompt.length) {
|
|
366831
|
+
const startIndex = prompt.indexOf(trigger, index);
|
|
366832
|
+
if (startIndex === -1) {
|
|
366833
|
+
break;
|
|
366834
|
+
}
|
|
366835
|
+
let currentIndex = startIndex + trigger.length;
|
|
366836
|
+
let braceCount = 1;
|
|
366837
|
+
let foundEnd = false;
|
|
366838
|
+
while (currentIndex < prompt.length) {
|
|
366839
|
+
const char = prompt[currentIndex];
|
|
366840
|
+
if (char === "{") {
|
|
366841
|
+
braceCount++;
|
|
366842
|
+
} else if (char === "}") {
|
|
366843
|
+
braceCount--;
|
|
366844
|
+
if (braceCount === 0) {
|
|
366845
|
+
const injectionContent = prompt.substring(
|
|
366846
|
+
startIndex + trigger.length,
|
|
366847
|
+
currentIndex
|
|
366848
|
+
);
|
|
366849
|
+
const endIndex = currentIndex + 1;
|
|
366850
|
+
injections.push({
|
|
366851
|
+
content: injectionContent.trim(),
|
|
366852
|
+
startIndex,
|
|
366853
|
+
endIndex
|
|
366854
|
+
});
|
|
366855
|
+
index = endIndex;
|
|
366856
|
+
foundEnd = true;
|
|
366857
|
+
break;
|
|
366858
|
+
}
|
|
366859
|
+
}
|
|
366860
|
+
currentIndex++;
|
|
366861
|
+
}
|
|
366862
|
+
if (!foundEnd) {
|
|
366863
|
+
const contextInfo = contextName ? ` in command '${contextName}'` : "";
|
|
366864
|
+
throw new Error(
|
|
366865
|
+
`Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`
|
|
366866
|
+
);
|
|
366867
|
+
}
|
|
366868
|
+
}
|
|
366869
|
+
return injections;
|
|
366527
366870
|
}
|
|
366528
|
-
__name(
|
|
366529
|
-
|
|
366530
|
-
|
|
366531
|
-
|
|
366871
|
+
__name(extractInjections, "extractInjections");
|
|
366872
|
+
|
|
366873
|
+
// packages/cli/src/services/prompt-processors/shellProcessor.ts
|
|
366874
|
+
var ConfirmationRequiredError = class extends Error {
|
|
366875
|
+
constructor(message, commandsToConfirm) {
|
|
366876
|
+
super(message);
|
|
366877
|
+
this.commandsToConfirm = commandsToConfirm;
|
|
366878
|
+
this.name = "ConfirmationRequiredError";
|
|
366532
366879
|
}
|
|
366533
|
-
|
|
366880
|
+
static {
|
|
366881
|
+
__name(this, "ConfirmationRequiredError");
|
|
366882
|
+
}
|
|
366883
|
+
};
|
|
366884
|
+
var ShellProcessor = class {
|
|
366885
|
+
constructor(commandName) {
|
|
366886
|
+
this.commandName = commandName;
|
|
366887
|
+
}
|
|
366888
|
+
static {
|
|
366889
|
+
__name(this, "ShellProcessor");
|
|
366890
|
+
}
|
|
366891
|
+
async process(prompt, context2) {
|
|
366892
|
+
return flatMapTextParts(
|
|
366893
|
+
prompt,
|
|
366894
|
+
(text) => this.processString(text, context2)
|
|
366895
|
+
);
|
|
366896
|
+
}
|
|
366897
|
+
async processString(prompt, context2) {
|
|
366898
|
+
const userArgsRaw = context2.invocation?.args || "";
|
|
366899
|
+
if (!prompt.includes(SHELL_INJECTION_TRIGGER)) {
|
|
366900
|
+
return [
|
|
366901
|
+
{ text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
|
|
366902
|
+
];
|
|
366903
|
+
}
|
|
366904
|
+
const config2 = context2.services.config;
|
|
366905
|
+
if (!config2) {
|
|
366906
|
+
throw new Error(
|
|
366907
|
+
`Security configuration not loaded. Cannot verify shell command permissions for '${this.commandName}'. Aborting.`
|
|
366908
|
+
);
|
|
366909
|
+
}
|
|
366910
|
+
const { sessionShellAllowlist } = context2.session;
|
|
366911
|
+
const injections = extractInjections(
|
|
366912
|
+
prompt,
|
|
366913
|
+
SHELL_INJECTION_TRIGGER,
|
|
366914
|
+
this.commandName
|
|
366915
|
+
);
|
|
366916
|
+
if (injections.length === 0) {
|
|
366917
|
+
return [
|
|
366918
|
+
{ text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
|
|
366919
|
+
];
|
|
366920
|
+
}
|
|
366921
|
+
const { shell: shell2 } = getShellConfiguration();
|
|
366922
|
+
const userArgsEscaped = escapeShellArg(userArgsRaw, shell2);
|
|
366923
|
+
const resolvedInjections = injections.map(
|
|
366924
|
+
(injection) => {
|
|
366925
|
+
const command2 = injection.content;
|
|
366926
|
+
if (command2 === "") {
|
|
366927
|
+
return { ...injection, resolvedCommand: void 0 };
|
|
366928
|
+
}
|
|
366929
|
+
const resolvedCommand = command2.replaceAll(
|
|
366930
|
+
SHORTHAND_ARGS_PLACEHOLDER,
|
|
366931
|
+
userArgsEscaped
|
|
366932
|
+
);
|
|
366933
|
+
return { ...injection, resolvedCommand };
|
|
366934
|
+
}
|
|
366935
|
+
);
|
|
366936
|
+
const commandsToConfirm = /* @__PURE__ */ new Set();
|
|
366937
|
+
for (const injection of resolvedInjections) {
|
|
366938
|
+
const command2 = injection.resolvedCommand;
|
|
366939
|
+
if (!command2) continue;
|
|
366940
|
+
const { allAllowed, disallowedCommands, blockReason, isHardDenial } = checkCommandPermissions(command2, config2, sessionShellAllowlist);
|
|
366941
|
+
if (!allAllowed) {
|
|
366942
|
+
if (isHardDenial) {
|
|
366943
|
+
throw new Error(
|
|
366944
|
+
`${this.commandName} cannot be run. Blocked command: "${command2}". Reason: ${blockReason || "Blocked by configuration."}`
|
|
366945
|
+
);
|
|
366946
|
+
}
|
|
366947
|
+
if (config2.getApprovalMode() !== ApprovalMode.YOLO) {
|
|
366948
|
+
disallowedCommands.forEach((uc) => commandsToConfirm.add(uc));
|
|
366949
|
+
}
|
|
366950
|
+
}
|
|
366951
|
+
}
|
|
366952
|
+
if (commandsToConfirm.size > 0) {
|
|
366953
|
+
throw new ConfirmationRequiredError(
|
|
366954
|
+
"Shell command confirmation required",
|
|
366955
|
+
Array.from(commandsToConfirm)
|
|
366956
|
+
);
|
|
366957
|
+
}
|
|
366958
|
+
let processedPrompt = "";
|
|
366959
|
+
let lastIndex = 0;
|
|
366960
|
+
for (const injection of resolvedInjections) {
|
|
366961
|
+
const segment = prompt.substring(lastIndex, injection.startIndex);
|
|
366962
|
+
processedPrompt += segment.replaceAll(
|
|
366963
|
+
SHORTHAND_ARGS_PLACEHOLDER,
|
|
366964
|
+
userArgsRaw
|
|
366965
|
+
);
|
|
366966
|
+
if (injection.resolvedCommand) {
|
|
366967
|
+
const activeTheme = themeManager.getActiveTheme();
|
|
366968
|
+
const shellExecutionConfig = {
|
|
366969
|
+
...config2.getShellExecutionConfig(),
|
|
366970
|
+
defaultFg: activeTheme.colors.Foreground,
|
|
366971
|
+
defaultBg: activeTheme.colors.Background
|
|
366972
|
+
};
|
|
366973
|
+
const { result } = await ShellExecutionService.execute(
|
|
366974
|
+
injection.resolvedCommand,
|
|
366975
|
+
config2.getTargetDir(),
|
|
366976
|
+
() => {
|
|
366977
|
+
},
|
|
366978
|
+
new AbortController().signal,
|
|
366979
|
+
config2.getShouldUseNodePtyShell(),
|
|
366980
|
+
shellExecutionConfig
|
|
366981
|
+
);
|
|
366982
|
+
const executionResult = await result;
|
|
366983
|
+
if (executionResult.error && !executionResult.aborted) {
|
|
366984
|
+
throw new Error(
|
|
366985
|
+
`Failed to start shell command in '${this.commandName}': ${executionResult.error.message}. Command: ${injection.resolvedCommand}`
|
|
366986
|
+
);
|
|
366987
|
+
}
|
|
366988
|
+
processedPrompt += executionResult.output;
|
|
366989
|
+
if (executionResult.aborted) {
|
|
366990
|
+
processedPrompt += `
|
|
366991
|
+
[Shell command '${injection.resolvedCommand}' aborted]`;
|
|
366992
|
+
} else if (executionResult.exitCode !== 0 && executionResult.exitCode !== null) {
|
|
366993
|
+
processedPrompt += `
|
|
366994
|
+
[Shell command '${injection.resolvedCommand}' exited with code ${executionResult.exitCode}]`;
|
|
366995
|
+
} else if (executionResult.signal !== null) {
|
|
366996
|
+
processedPrompt += `
|
|
366997
|
+
[Shell command '${injection.resolvedCommand}' terminated by signal ${executionResult.signal}]`;
|
|
366998
|
+
}
|
|
366999
|
+
}
|
|
367000
|
+
lastIndex = injection.endIndex;
|
|
367001
|
+
}
|
|
367002
|
+
const finalSegment = prompt.substring(lastIndex);
|
|
367003
|
+
processedPrompt += finalSegment.replaceAll(
|
|
367004
|
+
SHORTHAND_ARGS_PLACEHOLDER,
|
|
367005
|
+
userArgsRaw
|
|
367006
|
+
);
|
|
367007
|
+
return [{ text: processedPrompt }];
|
|
367008
|
+
}
|
|
367009
|
+
};
|
|
367010
|
+
|
|
367011
|
+
// packages/cli/src/services/prompt-processors/atFileProcessor.ts
|
|
367012
|
+
init_esbuild_shims();
|
|
367013
|
+
var AtFileProcessor = class {
|
|
367014
|
+
constructor(commandName) {
|
|
367015
|
+
this.commandName = commandName;
|
|
367016
|
+
}
|
|
367017
|
+
static {
|
|
367018
|
+
__name(this, "AtFileProcessor");
|
|
367019
|
+
}
|
|
367020
|
+
async process(input, context2) {
|
|
367021
|
+
const config2 = context2.services.config;
|
|
367022
|
+
if (!config2) {
|
|
367023
|
+
return input;
|
|
367024
|
+
}
|
|
367025
|
+
return flatMapTextParts(input, async (text) => {
|
|
367026
|
+
if (!text.includes(AT_FILE_INJECTION_TRIGGER)) {
|
|
367027
|
+
return [{ text }];
|
|
367028
|
+
}
|
|
367029
|
+
const injections = extractInjections(
|
|
367030
|
+
text,
|
|
367031
|
+
AT_FILE_INJECTION_TRIGGER,
|
|
367032
|
+
this.commandName
|
|
367033
|
+
);
|
|
367034
|
+
if (injections.length === 0) {
|
|
367035
|
+
return [{ text }];
|
|
367036
|
+
}
|
|
367037
|
+
const output = [];
|
|
367038
|
+
let lastIndex = 0;
|
|
367039
|
+
for (const injection of injections) {
|
|
367040
|
+
const prefix = text.substring(lastIndex, injection.startIndex);
|
|
367041
|
+
if (prefix) {
|
|
367042
|
+
output.push({ text: prefix });
|
|
367043
|
+
}
|
|
367044
|
+
const pathStr = injection.content;
|
|
367045
|
+
try {
|
|
367046
|
+
const fileContentParts = await readPathFromWorkspace(pathStr, config2);
|
|
367047
|
+
if (fileContentParts.length === 0) {
|
|
367048
|
+
const uiMessage = `File '@{${pathStr}}' was ignored by .gitignore or .qwenignore and was not included in the prompt.`;
|
|
367049
|
+
context2.ui.addItem(
|
|
367050
|
+
{ type: "info" /* INFO */, text: uiMessage },
|
|
367051
|
+
Date.now()
|
|
367052
|
+
);
|
|
367053
|
+
}
|
|
367054
|
+
output.push(...fileContentParts);
|
|
367055
|
+
} catch (error2) {
|
|
367056
|
+
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
367057
|
+
const uiMessage = `Failed to inject content for '@{${pathStr}}': ${message}`;
|
|
367058
|
+
console.error(
|
|
367059
|
+
`[AtFileProcessor] ${uiMessage}. Leaving placeholder in prompt.`
|
|
367060
|
+
);
|
|
367061
|
+
context2.ui.addItem(
|
|
367062
|
+
{ type: "error" /* ERROR */, text: uiMessage },
|
|
367063
|
+
Date.now()
|
|
367064
|
+
);
|
|
367065
|
+
const placeholder = text.substring(
|
|
367066
|
+
injection.startIndex,
|
|
367067
|
+
injection.endIndex
|
|
367068
|
+
);
|
|
367069
|
+
output.push({ text: placeholder });
|
|
367070
|
+
}
|
|
367071
|
+
lastIndex = injection.endIndex;
|
|
367072
|
+
}
|
|
367073
|
+
const suffix = text.substring(lastIndex);
|
|
367074
|
+
if (suffix) {
|
|
367075
|
+
output.push({ text: suffix });
|
|
367076
|
+
}
|
|
367077
|
+
return output;
|
|
367078
|
+
});
|
|
367079
|
+
}
|
|
367080
|
+
};
|
|
367081
|
+
|
|
367082
|
+
// packages/cli/src/services/FileCommandLoader.ts
|
|
367083
|
+
var TomlCommandDefSchema = external_exports.object({
|
|
367084
|
+
prompt: external_exports.string({
|
|
367085
|
+
required_error: "The 'prompt' field is required.",
|
|
367086
|
+
invalid_type_error: "The 'prompt' field must be a string."
|
|
367087
|
+
}),
|
|
367088
|
+
description: external_exports.string().optional()
|
|
367089
|
+
});
|
|
367090
|
+
var FileCommandLoader = class {
|
|
367091
|
+
constructor(config2) {
|
|
367092
|
+
this.config = config2;
|
|
367093
|
+
this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
|
|
367094
|
+
this.folderTrust = !!config2?.getFolderTrust();
|
|
367095
|
+
this.projectRoot = config2?.getProjectRoot() || process.cwd();
|
|
367096
|
+
}
|
|
367097
|
+
static {
|
|
367098
|
+
__name(this, "FileCommandLoader");
|
|
367099
|
+
}
|
|
367100
|
+
projectRoot;
|
|
367101
|
+
folderTrustEnabled;
|
|
367102
|
+
folderTrust;
|
|
367103
|
+
/**
|
|
367104
|
+
* Loads all commands from user, project, and extension directories.
|
|
367105
|
+
* Returns commands in order: user → project → extensions (alphabetically).
|
|
367106
|
+
*
|
|
367107
|
+
* Order is important for conflict resolution in CommandService:
|
|
367108
|
+
* - User/project commands (without extensionName) use "last wins" strategy
|
|
367109
|
+
* - Extension commands (with extensionName) get renamed if conflicts exist
|
|
367110
|
+
*
|
|
367111
|
+
* @param signal An AbortSignal to cancel the loading process.
|
|
367112
|
+
* @returns A promise that resolves to an array of all loaded SlashCommands.
|
|
367113
|
+
*/
|
|
367114
|
+
async loadCommands(signal) {
|
|
367115
|
+
const allCommands = [];
|
|
367116
|
+
const globOptions = {
|
|
367117
|
+
nodir: true,
|
|
367118
|
+
dot: true,
|
|
367119
|
+
signal,
|
|
367120
|
+
follow: true
|
|
367121
|
+
};
|
|
367122
|
+
const commandDirs = this.getCommandDirectories();
|
|
367123
|
+
for (const dirInfo of commandDirs) {
|
|
367124
|
+
try {
|
|
367125
|
+
const files = await glob("**/*.toml", {
|
|
367126
|
+
...globOptions,
|
|
367127
|
+
cwd: dirInfo.path
|
|
367128
|
+
});
|
|
367129
|
+
if (this.folderTrustEnabled && !this.folderTrust) {
|
|
367130
|
+
return [];
|
|
367131
|
+
}
|
|
367132
|
+
const commandPromises = files.map(
|
|
367133
|
+
(file) => this.parseAndAdaptFile(
|
|
367134
|
+
path90.join(dirInfo.path, file),
|
|
367135
|
+
dirInfo.path,
|
|
367136
|
+
dirInfo.extensionName
|
|
367137
|
+
)
|
|
367138
|
+
);
|
|
367139
|
+
const commands = (await Promise.all(commandPromises)).filter(
|
|
367140
|
+
(cmd) => cmd !== null
|
|
367141
|
+
);
|
|
367142
|
+
allCommands.push(...commands);
|
|
367143
|
+
} catch (error2) {
|
|
367144
|
+
const isEnoent = error2.code === "ENOENT";
|
|
367145
|
+
const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
|
|
367146
|
+
if (!isEnoent && !isAbortError2) {
|
|
367147
|
+
console.error(
|
|
367148
|
+
`[FileCommandLoader] Error loading commands from ${dirInfo.path}:`,
|
|
367149
|
+
error2
|
|
367150
|
+
);
|
|
367151
|
+
}
|
|
367152
|
+
}
|
|
367153
|
+
}
|
|
367154
|
+
return allCommands;
|
|
367155
|
+
}
|
|
367156
|
+
/**
|
|
367157
|
+
* Get all command directories in order for loading.
|
|
367158
|
+
* User commands → Project commands → Extension commands
|
|
367159
|
+
* This order ensures extension commands can detect all conflicts.
|
|
367160
|
+
*/
|
|
367161
|
+
getCommandDirectories() {
|
|
367162
|
+
const dirs = [];
|
|
367163
|
+
const storage = this.config?.storage ?? new Storage(this.projectRoot);
|
|
367164
|
+
dirs.push({ path: Storage.getUserCommandsDir() });
|
|
367165
|
+
dirs.push({ path: storage.getProjectCommandsDir() });
|
|
367166
|
+
if (this.config) {
|
|
367167
|
+
const activeExtensions = this.config.getExtensions().filter((ext2) => ext2.isActive).sort((a2, b2) => a2.name.localeCompare(b2.name));
|
|
367168
|
+
const extensionCommandDirs = activeExtensions.map((ext2) => ({
|
|
367169
|
+
path: path90.join(ext2.path, "commands"),
|
|
367170
|
+
extensionName: ext2.name
|
|
367171
|
+
}));
|
|
367172
|
+
dirs.push(...extensionCommandDirs);
|
|
367173
|
+
}
|
|
367174
|
+
return dirs;
|
|
367175
|
+
}
|
|
367176
|
+
/**
|
|
367177
|
+
* Parses a single .toml file and transforms it into a SlashCommand object.
|
|
367178
|
+
* @param filePath The absolute path to the .toml file.
|
|
367179
|
+
* @param baseDir The root command directory for name calculation.
|
|
367180
|
+
* @param extensionName Optional extension name to prefix commands with.
|
|
367181
|
+
* @returns A promise resolving to a SlashCommand, or null if the file is invalid.
|
|
367182
|
+
*/
|
|
367183
|
+
async parseAndAdaptFile(filePath, baseDir, extensionName) {
|
|
367184
|
+
let fileContent;
|
|
367185
|
+
try {
|
|
367186
|
+
fileContent = await fs81.readFile(filePath, "utf-8");
|
|
367187
|
+
} catch (error2) {
|
|
367188
|
+
console.error(
|
|
367189
|
+
`[FileCommandLoader] Failed to read file ${filePath}:`,
|
|
367190
|
+
error2 instanceof Error ? error2.message : String(error2)
|
|
367191
|
+
);
|
|
367192
|
+
return null;
|
|
367193
|
+
}
|
|
367194
|
+
let parsed;
|
|
367195
|
+
try {
|
|
367196
|
+
parsed = import_toml.default.parse(fileContent);
|
|
367197
|
+
} catch (error2) {
|
|
367198
|
+
console.error(
|
|
367199
|
+
`[FileCommandLoader] Failed to parse TOML file ${filePath}:`,
|
|
367200
|
+
error2 instanceof Error ? error2.message : String(error2)
|
|
367201
|
+
);
|
|
367202
|
+
return null;
|
|
367203
|
+
}
|
|
367204
|
+
const validationResult = TomlCommandDefSchema.safeParse(parsed);
|
|
367205
|
+
if (!validationResult.success) {
|
|
367206
|
+
console.error(
|
|
367207
|
+
`[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
|
|
367208
|
+
validationResult.error.flatten()
|
|
367209
|
+
);
|
|
367210
|
+
return null;
|
|
367211
|
+
}
|
|
367212
|
+
const validDef = validationResult.data;
|
|
367213
|
+
const relativePathWithExt = path90.relative(baseDir, filePath);
|
|
367214
|
+
const relativePath = relativePathWithExt.substring(
|
|
367215
|
+
0,
|
|
367216
|
+
relativePathWithExt.length - 5
|
|
367217
|
+
// length of '.toml'
|
|
367218
|
+
);
|
|
367219
|
+
const baseCommandName = relativePath.split(path90.sep).map((segment) => segment.replaceAll(":", "_")).join(":");
|
|
367220
|
+
const defaultDescription = `Custom command from ${path90.basename(filePath)}`;
|
|
367221
|
+
let description = validDef.description || defaultDescription;
|
|
367222
|
+
if (extensionName) {
|
|
367223
|
+
description = `[${extensionName}] ${description}`;
|
|
367224
|
+
}
|
|
367225
|
+
const processors = [];
|
|
367226
|
+
const usesArgs = validDef.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER);
|
|
367227
|
+
const usesShellInjection = validDef.prompt.includes(
|
|
367228
|
+
SHELL_INJECTION_TRIGGER
|
|
367229
|
+
);
|
|
367230
|
+
const usesAtFileInjection = validDef.prompt.includes(
|
|
367231
|
+
AT_FILE_INJECTION_TRIGGER
|
|
367232
|
+
);
|
|
367233
|
+
if (usesAtFileInjection) {
|
|
367234
|
+
processors.push(new AtFileProcessor(baseCommandName));
|
|
367235
|
+
}
|
|
367236
|
+
if (usesShellInjection || usesArgs) {
|
|
367237
|
+
processors.push(new ShellProcessor(baseCommandName));
|
|
367238
|
+
}
|
|
367239
|
+
if (!usesArgs) {
|
|
367240
|
+
processors.push(new DefaultArgumentProcessor());
|
|
367241
|
+
}
|
|
367242
|
+
return {
|
|
367243
|
+
name: baseCommandName,
|
|
367244
|
+
description,
|
|
367245
|
+
kind: "file" /* FILE */,
|
|
367246
|
+
extensionName,
|
|
367247
|
+
action: /* @__PURE__ */ __name(async (context2, _args) => {
|
|
367248
|
+
if (!context2.invocation) {
|
|
367249
|
+
console.error(
|
|
367250
|
+
`[FileCommandLoader] Critical error: Command '${baseCommandName}' was executed without invocation context.`
|
|
367251
|
+
);
|
|
367252
|
+
return {
|
|
367253
|
+
type: "submit_prompt",
|
|
367254
|
+
content: [{ text: validDef.prompt }]
|
|
367255
|
+
// Fallback to unprocessed prompt
|
|
367256
|
+
};
|
|
367257
|
+
}
|
|
367258
|
+
try {
|
|
367259
|
+
let processedContent = [
|
|
367260
|
+
{ text: validDef.prompt }
|
|
367261
|
+
];
|
|
367262
|
+
for (const processor of processors) {
|
|
367263
|
+
processedContent = await processor.process(
|
|
367264
|
+
processedContent,
|
|
367265
|
+
context2
|
|
367266
|
+
);
|
|
367267
|
+
}
|
|
367268
|
+
return {
|
|
367269
|
+
type: "submit_prompt",
|
|
367270
|
+
content: processedContent
|
|
367271
|
+
};
|
|
367272
|
+
} catch (e4) {
|
|
367273
|
+
if (e4 instanceof ConfirmationRequiredError) {
|
|
367274
|
+
return {
|
|
367275
|
+
type: "confirm_shell_commands",
|
|
367276
|
+
commandsToConfirm: e4.commandsToConfirm,
|
|
367277
|
+
originalInvocation: {
|
|
367278
|
+
raw: context2.invocation.raw
|
|
367279
|
+
}
|
|
367280
|
+
};
|
|
367281
|
+
}
|
|
367282
|
+
throw e4;
|
|
367283
|
+
}
|
|
367284
|
+
}, "action")
|
|
367285
|
+
};
|
|
367286
|
+
}
|
|
367287
|
+
};
|
|
367288
|
+
|
|
367289
|
+
// packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
|
|
367290
|
+
init_esbuild_shims();
|
|
367291
|
+
function createNonInteractiveUI() {
|
|
367292
|
+
return {
|
|
367293
|
+
addItem: /* @__PURE__ */ __name((_item, _timestamp) => 0, "addItem"),
|
|
367294
|
+
clear: /* @__PURE__ */ __name(() => {
|
|
367295
|
+
}, "clear"),
|
|
367296
|
+
setDebugMessage: /* @__PURE__ */ __name((_message) => {
|
|
367297
|
+
}, "setDebugMessage"),
|
|
367298
|
+
loadHistory: /* @__PURE__ */ __name((_newHistory) => {
|
|
367299
|
+
}, "loadHistory"),
|
|
367300
|
+
pendingItem: null,
|
|
367301
|
+
setPendingItem: /* @__PURE__ */ __name((_item) => {
|
|
367302
|
+
}, "setPendingItem"),
|
|
367303
|
+
toggleVimEnabled: /* @__PURE__ */ __name(async () => false, "toggleVimEnabled"),
|
|
367304
|
+
setGeminiMdFileCount: /* @__PURE__ */ __name((_count) => {
|
|
367305
|
+
}, "setGeminiMdFileCount"),
|
|
367306
|
+
reloadCommands: /* @__PURE__ */ __name(() => {
|
|
367307
|
+
}, "reloadCommands"),
|
|
367308
|
+
extensionsUpdateState: /* @__PURE__ */ new Map(),
|
|
367309
|
+
dispatchExtensionStateUpdate: /* @__PURE__ */ __name((_action) => {
|
|
367310
|
+
}, "dispatchExtensionStateUpdate"),
|
|
367311
|
+
addConfirmUpdateExtensionRequest: /* @__PURE__ */ __name((_request) => {
|
|
367312
|
+
}, "addConfirmUpdateExtensionRequest")
|
|
367313
|
+
};
|
|
366534
367314
|
}
|
|
366535
|
-
__name(
|
|
366536
|
-
|
|
366537
|
-
|
|
366538
|
-
|
|
367315
|
+
__name(createNonInteractiveUI, "createNonInteractiveUI");
|
|
367316
|
+
|
|
367317
|
+
// packages/cli/src/nonInteractiveCliCommands.ts
|
|
367318
|
+
var ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE = [
|
|
367319
|
+
"init",
|
|
367320
|
+
"summary",
|
|
367321
|
+
"compress"
|
|
367322
|
+
];
|
|
367323
|
+
function handleCommandResult(result) {
|
|
367324
|
+
switch (result.type) {
|
|
367325
|
+
case "submit_prompt":
|
|
367326
|
+
return {
|
|
367327
|
+
type: "submit_prompt",
|
|
367328
|
+
content: result.content
|
|
367329
|
+
};
|
|
367330
|
+
case "message":
|
|
367331
|
+
return {
|
|
367332
|
+
type: "message",
|
|
367333
|
+
messageType: result.messageType,
|
|
367334
|
+
content: result.content
|
|
367335
|
+
};
|
|
367336
|
+
case "stream_messages":
|
|
367337
|
+
return {
|
|
367338
|
+
type: "stream_messages",
|
|
367339
|
+
messages: result.messages
|
|
367340
|
+
};
|
|
367341
|
+
/**
|
|
367342
|
+
* Currently return types below are never generated due to the
|
|
367343
|
+
* whitelist of allowed slash commands in ACP and non-interactive mode.
|
|
367344
|
+
* We'll try to add more supported return types in the future.
|
|
367345
|
+
*/
|
|
367346
|
+
case "tool":
|
|
367347
|
+
return {
|
|
367348
|
+
type: "unsupported",
|
|
367349
|
+
reason: "Tool execution from slash commands is not supported in non-interactive mode.",
|
|
367350
|
+
originalType: "tool"
|
|
367351
|
+
};
|
|
367352
|
+
case "quit":
|
|
367353
|
+
return {
|
|
367354
|
+
type: "unsupported",
|
|
367355
|
+
reason: "Quit command is not supported in non-interactive mode. The process will exit naturally after completion.",
|
|
367356
|
+
originalType: "quit"
|
|
367357
|
+
};
|
|
367358
|
+
case "dialog":
|
|
367359
|
+
return {
|
|
367360
|
+
type: "unsupported",
|
|
367361
|
+
reason: `Dialog '${result.dialog}' cannot be opened in non-interactive mode.`,
|
|
367362
|
+
originalType: "dialog"
|
|
367363
|
+
};
|
|
367364
|
+
case "load_history":
|
|
367365
|
+
return {
|
|
367366
|
+
type: "unsupported",
|
|
367367
|
+
reason: "Loading history is not supported in non-interactive mode. Each invocation starts with a fresh context.",
|
|
367368
|
+
originalType: "load_history"
|
|
367369
|
+
};
|
|
367370
|
+
case "confirm_shell_commands":
|
|
367371
|
+
return {
|
|
367372
|
+
type: "unsupported",
|
|
367373
|
+
reason: "Shell command confirmation is not supported in non-interactive mode. Use YOLO mode or pre-approve commands.",
|
|
367374
|
+
originalType: "confirm_shell_commands"
|
|
367375
|
+
};
|
|
367376
|
+
case "confirm_action":
|
|
367377
|
+
return {
|
|
367378
|
+
type: "unsupported",
|
|
367379
|
+
reason: "Action confirmation is not supported in non-interactive mode. Commands requiring confirmation cannot be executed.",
|
|
367380
|
+
originalType: "confirm_action"
|
|
367381
|
+
};
|
|
367382
|
+
default: {
|
|
367383
|
+
const _exhaustive = result;
|
|
367384
|
+
return {
|
|
367385
|
+
type: "unsupported",
|
|
367386
|
+
reason: `Unknown command result type: ${_exhaustive.type}`,
|
|
367387
|
+
originalType: "unknown"
|
|
367388
|
+
};
|
|
367389
|
+
}
|
|
366539
367390
|
}
|
|
366540
|
-
return metrics2.tokens.cached / metrics2.tokens.prompt * 100;
|
|
366541
367391
|
}
|
|
366542
|
-
__name(
|
|
366543
|
-
|
|
366544
|
-
|
|
366545
|
-
|
|
366546
|
-
|
|
366547
|
-
|
|
367392
|
+
__name(handleCommandResult, "handleCommandResult");
|
|
367393
|
+
function filterCommandsForNonInteractive(commands, allowedBuiltinCommandNames) {
|
|
367394
|
+
return commands.filter((cmd) => {
|
|
367395
|
+
if (cmd.kind === "file" /* FILE */) {
|
|
367396
|
+
return true;
|
|
367397
|
+
}
|
|
367398
|
+
if (cmd.kind === "built-in" /* BUILT_IN */) {
|
|
367399
|
+
return allowedBuiltinCommandNames.has(cmd.name);
|
|
367400
|
+
}
|
|
367401
|
+
return false;
|
|
367402
|
+
});
|
|
367403
|
+
}
|
|
367404
|
+
__name(filterCommandsForNonInteractive, "filterCommandsForNonInteractive");
|
|
367405
|
+
var handleSlashCommand = /* @__PURE__ */ __name(async (rawQuery, abortController, config2, settings, allowedBuiltinCommandNames = [
|
|
367406
|
+
...ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE
|
|
367407
|
+
]) => {
|
|
367408
|
+
const trimmed2 = rawQuery.trim();
|
|
367409
|
+
if (!trimmed2.startsWith("/")) {
|
|
367410
|
+
return { type: "no_command" };
|
|
367411
|
+
}
|
|
367412
|
+
const isAcpMode = config2.getExperimentalZedIntegration();
|
|
367413
|
+
const isInteractive = config2.isInteractive();
|
|
367414
|
+
const executionMode = isAcpMode ? "acp" : isInteractive ? "interactive" : "non_interactive";
|
|
367415
|
+
const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
|
|
367416
|
+
const allLoaders = [
|
|
367417
|
+
new BuiltinCommandLoader(config2),
|
|
367418
|
+
new FileCommandLoader(config2)
|
|
367419
|
+
];
|
|
367420
|
+
const commandService = await CommandService.create(
|
|
367421
|
+
allLoaders,
|
|
367422
|
+
abortController.signal
|
|
366548
367423
|
);
|
|
366549
|
-
const
|
|
366550
|
-
const
|
|
366551
|
-
|
|
366552
|
-
|
|
366553
|
-
const totalCachedTokens = Object.values(models).reduce(
|
|
366554
|
-
(acc, model) => acc + model.tokens.cached,
|
|
366555
|
-
0
|
|
367424
|
+
const allCommands = commandService.getCommands();
|
|
367425
|
+
const filteredCommands = filterCommandsForNonInteractive(
|
|
367426
|
+
allCommands,
|
|
367427
|
+
allowedBuiltinSet
|
|
366556
367428
|
);
|
|
366557
|
-
const
|
|
366558
|
-
|
|
366559
|
-
|
|
367429
|
+
const { commandToExecute, args } = parseSlashCommand(
|
|
367430
|
+
rawQuery,
|
|
367431
|
+
filteredCommands
|
|
366560
367432
|
);
|
|
366561
|
-
|
|
366562
|
-
|
|
366563
|
-
|
|
366564
|
-
|
|
366565
|
-
|
|
366566
|
-
|
|
366567
|
-
|
|
366568
|
-
|
|
366569
|
-
|
|
366570
|
-
|
|
366571
|
-
|
|
366572
|
-
|
|
366573
|
-
|
|
366574
|
-
|
|
366575
|
-
|
|
366576
|
-
|
|
366577
|
-
|
|
366578
|
-
|
|
367433
|
+
if (!commandToExecute) {
|
|
367434
|
+
const { commandToExecute: knownCommand } = parseSlashCommand(
|
|
367435
|
+
rawQuery,
|
|
367436
|
+
allCommands
|
|
367437
|
+
);
|
|
367438
|
+
if (knownCommand) {
|
|
367439
|
+
return {
|
|
367440
|
+
type: "unsupported",
|
|
367441
|
+
reason: t4(
|
|
367442
|
+
'The command "/{{command}}" is not supported in non-interactive mode.',
|
|
367443
|
+
{ command: knownCommand.name }
|
|
367444
|
+
),
|
|
367445
|
+
originalType: "filtered_command"
|
|
367446
|
+
};
|
|
367447
|
+
}
|
|
367448
|
+
return { type: "no_command" };
|
|
367449
|
+
}
|
|
367450
|
+
if (!commandToExecute.action) {
|
|
367451
|
+
return { type: "no_command" };
|
|
367452
|
+
}
|
|
367453
|
+
const sessionStats = {
|
|
367454
|
+
sessionId: config2?.getSessionId(),
|
|
367455
|
+
sessionStartTime: /* @__PURE__ */ new Date(),
|
|
367456
|
+
metrics: uiTelemetryService.getMetrics(),
|
|
367457
|
+
lastPromptTokenCount: 0,
|
|
367458
|
+
promptCount: 1
|
|
366579
367459
|
};
|
|
366580
|
-
|
|
367460
|
+
const logger6 = new Logger(config2?.getSessionId() || "", config2?.storage);
|
|
367461
|
+
const context2 = {
|
|
367462
|
+
executionMode,
|
|
367463
|
+
services: {
|
|
367464
|
+
config: config2,
|
|
367465
|
+
settings,
|
|
367466
|
+
git: void 0,
|
|
367467
|
+
logger: logger6
|
|
367468
|
+
},
|
|
367469
|
+
ui: createNonInteractiveUI(),
|
|
367470
|
+
session: {
|
|
367471
|
+
stats: sessionStats,
|
|
367472
|
+
sessionShellAllowlist: /* @__PURE__ */ new Set()
|
|
367473
|
+
},
|
|
367474
|
+
invocation: {
|
|
367475
|
+
raw: trimmed2,
|
|
367476
|
+
name: commandToExecute.name,
|
|
367477
|
+
args
|
|
367478
|
+
}
|
|
367479
|
+
};
|
|
367480
|
+
const result = await commandToExecute.action(context2, args);
|
|
367481
|
+
if (!result) {
|
|
367482
|
+
return {
|
|
367483
|
+
type: "message",
|
|
367484
|
+
messageType: "info",
|
|
367485
|
+
content: "Command executed successfully."
|
|
367486
|
+
};
|
|
367487
|
+
}
|
|
367488
|
+
return handleCommandResult(result);
|
|
367489
|
+
}, "handleSlashCommand");
|
|
367490
|
+
var getAvailableCommands = /* @__PURE__ */ __name(async (config2, abortSignal, allowedBuiltinCommandNames = [
|
|
367491
|
+
...ALLOWED_BUILTIN_COMMANDS_NON_INTERACTIVE
|
|
367492
|
+
]) => {
|
|
367493
|
+
try {
|
|
367494
|
+
const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
|
|
367495
|
+
const loaders = allowedBuiltinSet.size > 0 ? [new BuiltinCommandLoader(config2), new FileCommandLoader(config2)] : [new FileCommandLoader(config2)];
|
|
367496
|
+
const commandService = await CommandService.create(loaders, abortSignal);
|
|
367497
|
+
const commands = commandService.getCommands();
|
|
367498
|
+
const filteredCommands = filterCommandsForNonInteractive(
|
|
367499
|
+
commands,
|
|
367500
|
+
allowedBuiltinSet
|
|
367501
|
+
);
|
|
367502
|
+
return filteredCommands.filter((cmd) => !cmd.hidden);
|
|
367503
|
+
} catch (error2) {
|
|
367504
|
+
console.error("Error loading available commands:", error2);
|
|
367505
|
+
return [];
|
|
367506
|
+
}
|
|
367507
|
+
}, "getAvailableCommands");
|
|
366581
367508
|
|
|
366582
367509
|
// packages/cli/src/utils/nonInteractiveHelpers.ts
|
|
366583
367510
|
function normalizePartList(parts) {
|
|
@@ -366642,19 +367569,15 @@ function computeUsageFromMetrics(metrics2) {
|
|
|
366642
367569
|
return usage2;
|
|
366643
367570
|
}
|
|
366644
367571
|
__name(computeUsageFromMetrics, "computeUsageFromMetrics");
|
|
366645
|
-
async function loadSlashCommandNames(config2) {
|
|
367572
|
+
async function loadSlashCommandNames(config2, allowedBuiltinCommandNames) {
|
|
366646
367573
|
const controller = new AbortController();
|
|
366647
367574
|
try {
|
|
366648
|
-
const
|
|
366649
|
-
|
|
366650
|
-
controller.signal
|
|
367575
|
+
const commands = await getAvailableCommands(
|
|
367576
|
+
config2,
|
|
367577
|
+
controller.signal,
|
|
367578
|
+
allowedBuiltinCommandNames
|
|
366651
367579
|
);
|
|
366652
|
-
|
|
366653
|
-
const commands = service.getCommands();
|
|
366654
|
-
for (const command2 of commands) {
|
|
366655
|
-
names.add(command2.name);
|
|
366656
|
-
}
|
|
366657
|
-
return Array.from(names).sort();
|
|
367580
|
+
return commands.map((cmd) => cmd.name).sort();
|
|
366658
367581
|
} catch (error2) {
|
|
366659
367582
|
if (config2.getDebugMode()) {
|
|
366660
367583
|
console.error(
|
|
@@ -366668,7 +367591,7 @@ async function loadSlashCommandNames(config2) {
|
|
|
366668
367591
|
}
|
|
366669
367592
|
}
|
|
366670
367593
|
__name(loadSlashCommandNames, "loadSlashCommandNames");
|
|
366671
|
-
async function buildSystemMessage(config2, sessionId, permissionMode) {
|
|
367594
|
+
async function buildSystemMessage(config2, sessionId, permissionMode, allowedBuiltinCommandNames) {
|
|
366672
367595
|
const toolRegistry = config2.getToolRegistry();
|
|
366673
367596
|
const tools = toolRegistry ? toolRegistry.getAllToolNames() : [];
|
|
366674
367597
|
const mcpServers = config2.getMcpServers();
|
|
@@ -366676,7 +367599,10 @@ async function buildSystemMessage(config2, sessionId, permissionMode) {
|
|
|
366676
367599
|
name: name3,
|
|
366677
367600
|
status: getMCPServerStatus(name3)
|
|
366678
367601
|
})) : [];
|
|
366679
|
-
const slashCommands = await loadSlashCommandNames(
|
|
367602
|
+
const slashCommands = await loadSlashCommandNames(
|
|
367603
|
+
config2,
|
|
367604
|
+
allowedBuiltinCommandNames
|
|
367605
|
+
);
|
|
366680
367606
|
let agentNames = [];
|
|
366681
367607
|
try {
|
|
366682
367608
|
const subagentManager = config2.getSubagentManager();
|
|
@@ -367929,663 +368855,6 @@ var StreamJsonOutputAdapter = class extends BaseJsonOutputAdapter {
|
|
|
367929
368855
|
}
|
|
367930
368856
|
};
|
|
367931
368857
|
|
|
367932
|
-
// packages/cli/src/nonInteractiveCliCommands.ts
|
|
367933
|
-
init_esbuild_shims();
|
|
367934
|
-
|
|
367935
|
-
// packages/cli/src/utils/commands.ts
|
|
367936
|
-
init_esbuild_shims();
|
|
367937
|
-
var parseSlashCommand = /* @__PURE__ */ __name((query, commands) => {
|
|
367938
|
-
const trimmed2 = query.trim();
|
|
367939
|
-
const parts = trimmed2.substring(1).trim().split(/\s+/);
|
|
367940
|
-
const commandPath = parts.filter((p2) => p2);
|
|
367941
|
-
let currentCommands = commands;
|
|
367942
|
-
let commandToExecute;
|
|
367943
|
-
let pathIndex = 0;
|
|
367944
|
-
const canonicalPath = [];
|
|
367945
|
-
for (const part of commandPath) {
|
|
367946
|
-
let foundCommand = currentCommands.find((cmd) => cmd.name === part);
|
|
367947
|
-
if (!foundCommand) {
|
|
367948
|
-
foundCommand = currentCommands.find(
|
|
367949
|
-
(cmd) => cmd.altNames?.includes(part)
|
|
367950
|
-
);
|
|
367951
|
-
}
|
|
367952
|
-
if (foundCommand) {
|
|
367953
|
-
commandToExecute = foundCommand;
|
|
367954
|
-
canonicalPath.push(foundCommand.name);
|
|
367955
|
-
pathIndex++;
|
|
367956
|
-
if (foundCommand.subCommands) {
|
|
367957
|
-
currentCommands = foundCommand.subCommands;
|
|
367958
|
-
} else {
|
|
367959
|
-
break;
|
|
367960
|
-
}
|
|
367961
|
-
} else {
|
|
367962
|
-
break;
|
|
367963
|
-
}
|
|
367964
|
-
}
|
|
367965
|
-
const args = parts.slice(pathIndex).join(" ");
|
|
367966
|
-
return { commandToExecute, args, canonicalPath };
|
|
367967
|
-
}, "parseSlashCommand");
|
|
367968
|
-
|
|
367969
|
-
// packages/cli/src/services/FileCommandLoader.ts
|
|
367970
|
-
init_esbuild_shims();
|
|
367971
|
-
var import_toml = __toESM(require_toml(), 1);
|
|
367972
|
-
init_esm11();
|
|
367973
|
-
init_zod();
|
|
367974
|
-
import { promises as fs81 } from "node:fs";
|
|
367975
|
-
import path90 from "node:path";
|
|
367976
|
-
|
|
367977
|
-
// packages/cli/src/services/prompt-processors/argumentProcessor.ts
|
|
367978
|
-
init_esbuild_shims();
|
|
367979
|
-
var DefaultArgumentProcessor = class {
|
|
367980
|
-
static {
|
|
367981
|
-
__name(this, "DefaultArgumentProcessor");
|
|
367982
|
-
}
|
|
367983
|
-
async process(prompt, context2) {
|
|
367984
|
-
if (context2.invocation?.args) {
|
|
367985
|
-
return appendToLastTextPart(prompt, context2.invocation.raw);
|
|
367986
|
-
}
|
|
367987
|
-
return prompt;
|
|
367988
|
-
}
|
|
367989
|
-
};
|
|
367990
|
-
|
|
367991
|
-
// packages/cli/src/services/prompt-processors/types.ts
|
|
367992
|
-
init_esbuild_shims();
|
|
367993
|
-
var SHORTHAND_ARGS_PLACEHOLDER = "{{args}}";
|
|
367994
|
-
var SHELL_INJECTION_TRIGGER = "!{";
|
|
367995
|
-
var AT_FILE_INJECTION_TRIGGER = "@{";
|
|
367996
|
-
|
|
367997
|
-
// packages/cli/src/services/prompt-processors/shellProcessor.ts
|
|
367998
|
-
init_esbuild_shims();
|
|
367999
|
-
|
|
368000
|
-
// packages/cli/src/services/prompt-processors/injectionParser.ts
|
|
368001
|
-
init_esbuild_shims();
|
|
368002
|
-
function extractInjections(prompt, trigger, contextName) {
|
|
368003
|
-
const injections = [];
|
|
368004
|
-
let index = 0;
|
|
368005
|
-
while (index < prompt.length) {
|
|
368006
|
-
const startIndex = prompt.indexOf(trigger, index);
|
|
368007
|
-
if (startIndex === -1) {
|
|
368008
|
-
break;
|
|
368009
|
-
}
|
|
368010
|
-
let currentIndex = startIndex + trigger.length;
|
|
368011
|
-
let braceCount = 1;
|
|
368012
|
-
let foundEnd = false;
|
|
368013
|
-
while (currentIndex < prompt.length) {
|
|
368014
|
-
const char = prompt[currentIndex];
|
|
368015
|
-
if (char === "{") {
|
|
368016
|
-
braceCount++;
|
|
368017
|
-
} else if (char === "}") {
|
|
368018
|
-
braceCount--;
|
|
368019
|
-
if (braceCount === 0) {
|
|
368020
|
-
const injectionContent = prompt.substring(
|
|
368021
|
-
startIndex + trigger.length,
|
|
368022
|
-
currentIndex
|
|
368023
|
-
);
|
|
368024
|
-
const endIndex = currentIndex + 1;
|
|
368025
|
-
injections.push({
|
|
368026
|
-
content: injectionContent.trim(),
|
|
368027
|
-
startIndex,
|
|
368028
|
-
endIndex
|
|
368029
|
-
});
|
|
368030
|
-
index = endIndex;
|
|
368031
|
-
foundEnd = true;
|
|
368032
|
-
break;
|
|
368033
|
-
}
|
|
368034
|
-
}
|
|
368035
|
-
currentIndex++;
|
|
368036
|
-
}
|
|
368037
|
-
if (!foundEnd) {
|
|
368038
|
-
const contextInfo = contextName ? ` in command '${contextName}'` : "";
|
|
368039
|
-
throw new Error(
|
|
368040
|
-
`Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`
|
|
368041
|
-
);
|
|
368042
|
-
}
|
|
368043
|
-
}
|
|
368044
|
-
return injections;
|
|
368045
|
-
}
|
|
368046
|
-
__name(extractInjections, "extractInjections");
|
|
368047
|
-
|
|
368048
|
-
// packages/cli/src/services/prompt-processors/shellProcessor.ts
|
|
368049
|
-
var ConfirmationRequiredError = class extends Error {
|
|
368050
|
-
constructor(message, commandsToConfirm) {
|
|
368051
|
-
super(message);
|
|
368052
|
-
this.commandsToConfirm = commandsToConfirm;
|
|
368053
|
-
this.name = "ConfirmationRequiredError";
|
|
368054
|
-
}
|
|
368055
|
-
static {
|
|
368056
|
-
__name(this, "ConfirmationRequiredError");
|
|
368057
|
-
}
|
|
368058
|
-
};
|
|
368059
|
-
var ShellProcessor = class {
|
|
368060
|
-
constructor(commandName) {
|
|
368061
|
-
this.commandName = commandName;
|
|
368062
|
-
}
|
|
368063
|
-
static {
|
|
368064
|
-
__name(this, "ShellProcessor");
|
|
368065
|
-
}
|
|
368066
|
-
async process(prompt, context2) {
|
|
368067
|
-
return flatMapTextParts(
|
|
368068
|
-
prompt,
|
|
368069
|
-
(text) => this.processString(text, context2)
|
|
368070
|
-
);
|
|
368071
|
-
}
|
|
368072
|
-
async processString(prompt, context2) {
|
|
368073
|
-
const userArgsRaw = context2.invocation?.args || "";
|
|
368074
|
-
if (!prompt.includes(SHELL_INJECTION_TRIGGER)) {
|
|
368075
|
-
return [
|
|
368076
|
-
{ text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
|
|
368077
|
-
];
|
|
368078
|
-
}
|
|
368079
|
-
const config2 = context2.services.config;
|
|
368080
|
-
if (!config2) {
|
|
368081
|
-
throw new Error(
|
|
368082
|
-
`Security configuration not loaded. Cannot verify shell command permissions for '${this.commandName}'. Aborting.`
|
|
368083
|
-
);
|
|
368084
|
-
}
|
|
368085
|
-
const { sessionShellAllowlist } = context2.session;
|
|
368086
|
-
const injections = extractInjections(
|
|
368087
|
-
prompt,
|
|
368088
|
-
SHELL_INJECTION_TRIGGER,
|
|
368089
|
-
this.commandName
|
|
368090
|
-
);
|
|
368091
|
-
if (injections.length === 0) {
|
|
368092
|
-
return [
|
|
368093
|
-
{ text: prompt.replaceAll(SHORTHAND_ARGS_PLACEHOLDER, userArgsRaw) }
|
|
368094
|
-
];
|
|
368095
|
-
}
|
|
368096
|
-
const { shell: shell2 } = getShellConfiguration();
|
|
368097
|
-
const userArgsEscaped = escapeShellArg(userArgsRaw, shell2);
|
|
368098
|
-
const resolvedInjections = injections.map(
|
|
368099
|
-
(injection) => {
|
|
368100
|
-
const command2 = injection.content;
|
|
368101
|
-
if (command2 === "") {
|
|
368102
|
-
return { ...injection, resolvedCommand: void 0 };
|
|
368103
|
-
}
|
|
368104
|
-
const resolvedCommand = command2.replaceAll(
|
|
368105
|
-
SHORTHAND_ARGS_PLACEHOLDER,
|
|
368106
|
-
userArgsEscaped
|
|
368107
|
-
);
|
|
368108
|
-
return { ...injection, resolvedCommand };
|
|
368109
|
-
}
|
|
368110
|
-
);
|
|
368111
|
-
const commandsToConfirm = /* @__PURE__ */ new Set();
|
|
368112
|
-
for (const injection of resolvedInjections) {
|
|
368113
|
-
const command2 = injection.resolvedCommand;
|
|
368114
|
-
if (!command2) continue;
|
|
368115
|
-
const { allAllowed, disallowedCommands, blockReason, isHardDenial } = checkCommandPermissions(command2, config2, sessionShellAllowlist);
|
|
368116
|
-
if (!allAllowed) {
|
|
368117
|
-
if (isHardDenial) {
|
|
368118
|
-
throw new Error(
|
|
368119
|
-
`${this.commandName} cannot be run. Blocked command: "${command2}". Reason: ${blockReason || "Blocked by configuration."}`
|
|
368120
|
-
);
|
|
368121
|
-
}
|
|
368122
|
-
if (config2.getApprovalMode() !== ApprovalMode.YOLO) {
|
|
368123
|
-
disallowedCommands.forEach((uc) => commandsToConfirm.add(uc));
|
|
368124
|
-
}
|
|
368125
|
-
}
|
|
368126
|
-
}
|
|
368127
|
-
if (commandsToConfirm.size > 0) {
|
|
368128
|
-
throw new ConfirmationRequiredError(
|
|
368129
|
-
"Shell command confirmation required",
|
|
368130
|
-
Array.from(commandsToConfirm)
|
|
368131
|
-
);
|
|
368132
|
-
}
|
|
368133
|
-
let processedPrompt = "";
|
|
368134
|
-
let lastIndex = 0;
|
|
368135
|
-
for (const injection of resolvedInjections) {
|
|
368136
|
-
const segment = prompt.substring(lastIndex, injection.startIndex);
|
|
368137
|
-
processedPrompt += segment.replaceAll(
|
|
368138
|
-
SHORTHAND_ARGS_PLACEHOLDER,
|
|
368139
|
-
userArgsRaw
|
|
368140
|
-
);
|
|
368141
|
-
if (injection.resolvedCommand) {
|
|
368142
|
-
const activeTheme = themeManager.getActiveTheme();
|
|
368143
|
-
const shellExecutionConfig = {
|
|
368144
|
-
...config2.getShellExecutionConfig(),
|
|
368145
|
-
defaultFg: activeTheme.colors.Foreground,
|
|
368146
|
-
defaultBg: activeTheme.colors.Background
|
|
368147
|
-
};
|
|
368148
|
-
const { result } = await ShellExecutionService.execute(
|
|
368149
|
-
injection.resolvedCommand,
|
|
368150
|
-
config2.getTargetDir(),
|
|
368151
|
-
() => {
|
|
368152
|
-
},
|
|
368153
|
-
new AbortController().signal,
|
|
368154
|
-
config2.getShouldUseNodePtyShell(),
|
|
368155
|
-
shellExecutionConfig
|
|
368156
|
-
);
|
|
368157
|
-
const executionResult = await result;
|
|
368158
|
-
if (executionResult.error && !executionResult.aborted) {
|
|
368159
|
-
throw new Error(
|
|
368160
|
-
`Failed to start shell command in '${this.commandName}': ${executionResult.error.message}. Command: ${injection.resolvedCommand}`
|
|
368161
|
-
);
|
|
368162
|
-
}
|
|
368163
|
-
processedPrompt += executionResult.output;
|
|
368164
|
-
if (executionResult.aborted) {
|
|
368165
|
-
processedPrompt += `
|
|
368166
|
-
[Shell command '${injection.resolvedCommand}' aborted]`;
|
|
368167
|
-
} else if (executionResult.exitCode !== 0 && executionResult.exitCode !== null) {
|
|
368168
|
-
processedPrompt += `
|
|
368169
|
-
[Shell command '${injection.resolvedCommand}' exited with code ${executionResult.exitCode}]`;
|
|
368170
|
-
} else if (executionResult.signal !== null) {
|
|
368171
|
-
processedPrompt += `
|
|
368172
|
-
[Shell command '${injection.resolvedCommand}' terminated by signal ${executionResult.signal}]`;
|
|
368173
|
-
}
|
|
368174
|
-
}
|
|
368175
|
-
lastIndex = injection.endIndex;
|
|
368176
|
-
}
|
|
368177
|
-
const finalSegment = prompt.substring(lastIndex);
|
|
368178
|
-
processedPrompt += finalSegment.replaceAll(
|
|
368179
|
-
SHORTHAND_ARGS_PLACEHOLDER,
|
|
368180
|
-
userArgsRaw
|
|
368181
|
-
);
|
|
368182
|
-
return [{ text: processedPrompt }];
|
|
368183
|
-
}
|
|
368184
|
-
};
|
|
368185
|
-
|
|
368186
|
-
// packages/cli/src/services/prompt-processors/atFileProcessor.ts
|
|
368187
|
-
init_esbuild_shims();
|
|
368188
|
-
var AtFileProcessor = class {
|
|
368189
|
-
constructor(commandName) {
|
|
368190
|
-
this.commandName = commandName;
|
|
368191
|
-
}
|
|
368192
|
-
static {
|
|
368193
|
-
__name(this, "AtFileProcessor");
|
|
368194
|
-
}
|
|
368195
|
-
async process(input, context2) {
|
|
368196
|
-
const config2 = context2.services.config;
|
|
368197
|
-
if (!config2) {
|
|
368198
|
-
return input;
|
|
368199
|
-
}
|
|
368200
|
-
return flatMapTextParts(input, async (text) => {
|
|
368201
|
-
if (!text.includes(AT_FILE_INJECTION_TRIGGER)) {
|
|
368202
|
-
return [{ text }];
|
|
368203
|
-
}
|
|
368204
|
-
const injections = extractInjections(
|
|
368205
|
-
text,
|
|
368206
|
-
AT_FILE_INJECTION_TRIGGER,
|
|
368207
|
-
this.commandName
|
|
368208
|
-
);
|
|
368209
|
-
if (injections.length === 0) {
|
|
368210
|
-
return [{ text }];
|
|
368211
|
-
}
|
|
368212
|
-
const output = [];
|
|
368213
|
-
let lastIndex = 0;
|
|
368214
|
-
for (const injection of injections) {
|
|
368215
|
-
const prefix = text.substring(lastIndex, injection.startIndex);
|
|
368216
|
-
if (prefix) {
|
|
368217
|
-
output.push({ text: prefix });
|
|
368218
|
-
}
|
|
368219
|
-
const pathStr = injection.content;
|
|
368220
|
-
try {
|
|
368221
|
-
const fileContentParts = await readPathFromWorkspace(pathStr, config2);
|
|
368222
|
-
if (fileContentParts.length === 0) {
|
|
368223
|
-
const uiMessage = `File '@{${pathStr}}' was ignored by .gitignore or .qwenignore and was not included in the prompt.`;
|
|
368224
|
-
context2.ui.addItem(
|
|
368225
|
-
{ type: "info" /* INFO */, text: uiMessage },
|
|
368226
|
-
Date.now()
|
|
368227
|
-
);
|
|
368228
|
-
}
|
|
368229
|
-
output.push(...fileContentParts);
|
|
368230
|
-
} catch (error2) {
|
|
368231
|
-
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
368232
|
-
const uiMessage = `Failed to inject content for '@{${pathStr}}': ${message}`;
|
|
368233
|
-
console.error(
|
|
368234
|
-
`[AtFileProcessor] ${uiMessage}. Leaving placeholder in prompt.`
|
|
368235
|
-
);
|
|
368236
|
-
context2.ui.addItem(
|
|
368237
|
-
{ type: "error" /* ERROR */, text: uiMessage },
|
|
368238
|
-
Date.now()
|
|
368239
|
-
);
|
|
368240
|
-
const placeholder = text.substring(
|
|
368241
|
-
injection.startIndex,
|
|
368242
|
-
injection.endIndex
|
|
368243
|
-
);
|
|
368244
|
-
output.push({ text: placeholder });
|
|
368245
|
-
}
|
|
368246
|
-
lastIndex = injection.endIndex;
|
|
368247
|
-
}
|
|
368248
|
-
const suffix = text.substring(lastIndex);
|
|
368249
|
-
if (suffix) {
|
|
368250
|
-
output.push({ text: suffix });
|
|
368251
|
-
}
|
|
368252
|
-
return output;
|
|
368253
|
-
});
|
|
368254
|
-
}
|
|
368255
|
-
};
|
|
368256
|
-
|
|
368257
|
-
// packages/cli/src/services/FileCommandLoader.ts
|
|
368258
|
-
var TomlCommandDefSchema = external_exports.object({
|
|
368259
|
-
prompt: external_exports.string({
|
|
368260
|
-
required_error: "The 'prompt' field is required.",
|
|
368261
|
-
invalid_type_error: "The 'prompt' field must be a string."
|
|
368262
|
-
}),
|
|
368263
|
-
description: external_exports.string().optional()
|
|
368264
|
-
});
|
|
368265
|
-
var FileCommandLoader = class {
|
|
368266
|
-
constructor(config2) {
|
|
368267
|
-
this.config = config2;
|
|
368268
|
-
this.folderTrustEnabled = !!config2?.getFolderTrustFeature();
|
|
368269
|
-
this.folderTrust = !!config2?.getFolderTrust();
|
|
368270
|
-
this.projectRoot = config2?.getProjectRoot() || process.cwd();
|
|
368271
|
-
}
|
|
368272
|
-
static {
|
|
368273
|
-
__name(this, "FileCommandLoader");
|
|
368274
|
-
}
|
|
368275
|
-
projectRoot;
|
|
368276
|
-
folderTrustEnabled;
|
|
368277
|
-
folderTrust;
|
|
368278
|
-
/**
|
|
368279
|
-
* Loads all commands from user, project, and extension directories.
|
|
368280
|
-
* Returns commands in order: user → project → extensions (alphabetically).
|
|
368281
|
-
*
|
|
368282
|
-
* Order is important for conflict resolution in CommandService:
|
|
368283
|
-
* - User/project commands (without extensionName) use "last wins" strategy
|
|
368284
|
-
* - Extension commands (with extensionName) get renamed if conflicts exist
|
|
368285
|
-
*
|
|
368286
|
-
* @param signal An AbortSignal to cancel the loading process.
|
|
368287
|
-
* @returns A promise that resolves to an array of all loaded SlashCommands.
|
|
368288
|
-
*/
|
|
368289
|
-
async loadCommands(signal) {
|
|
368290
|
-
const allCommands = [];
|
|
368291
|
-
const globOptions = {
|
|
368292
|
-
nodir: true,
|
|
368293
|
-
dot: true,
|
|
368294
|
-
signal,
|
|
368295
|
-
follow: true
|
|
368296
|
-
};
|
|
368297
|
-
const commandDirs = this.getCommandDirectories();
|
|
368298
|
-
for (const dirInfo of commandDirs) {
|
|
368299
|
-
try {
|
|
368300
|
-
const files = await glob("**/*.toml", {
|
|
368301
|
-
...globOptions,
|
|
368302
|
-
cwd: dirInfo.path
|
|
368303
|
-
});
|
|
368304
|
-
if (this.folderTrustEnabled && !this.folderTrust) {
|
|
368305
|
-
return [];
|
|
368306
|
-
}
|
|
368307
|
-
const commandPromises = files.map(
|
|
368308
|
-
(file) => this.parseAndAdaptFile(
|
|
368309
|
-
path90.join(dirInfo.path, file),
|
|
368310
|
-
dirInfo.path,
|
|
368311
|
-
dirInfo.extensionName
|
|
368312
|
-
)
|
|
368313
|
-
);
|
|
368314
|
-
const commands = (await Promise.all(commandPromises)).filter(
|
|
368315
|
-
(cmd) => cmd !== null
|
|
368316
|
-
);
|
|
368317
|
-
allCommands.push(...commands);
|
|
368318
|
-
} catch (error2) {
|
|
368319
|
-
const isEnoent = error2.code === "ENOENT";
|
|
368320
|
-
const isAbortError2 = error2 instanceof Error && error2.name === "AbortError";
|
|
368321
|
-
if (!isEnoent && !isAbortError2) {
|
|
368322
|
-
console.error(
|
|
368323
|
-
`[FileCommandLoader] Error loading commands from ${dirInfo.path}:`,
|
|
368324
|
-
error2
|
|
368325
|
-
);
|
|
368326
|
-
}
|
|
368327
|
-
}
|
|
368328
|
-
}
|
|
368329
|
-
return allCommands;
|
|
368330
|
-
}
|
|
368331
|
-
/**
|
|
368332
|
-
* Get all command directories in order for loading.
|
|
368333
|
-
* User commands → Project commands → Extension commands
|
|
368334
|
-
* This order ensures extension commands can detect all conflicts.
|
|
368335
|
-
*/
|
|
368336
|
-
getCommandDirectories() {
|
|
368337
|
-
const dirs = [];
|
|
368338
|
-
const storage = this.config?.storage ?? new Storage(this.projectRoot);
|
|
368339
|
-
dirs.push({ path: Storage.getUserCommandsDir() });
|
|
368340
|
-
dirs.push({ path: storage.getProjectCommandsDir() });
|
|
368341
|
-
if (this.config) {
|
|
368342
|
-
const activeExtensions = this.config.getExtensions().filter((ext2) => ext2.isActive).sort((a2, b2) => a2.name.localeCompare(b2.name));
|
|
368343
|
-
const extensionCommandDirs = activeExtensions.map((ext2) => ({
|
|
368344
|
-
path: path90.join(ext2.path, "commands"),
|
|
368345
|
-
extensionName: ext2.name
|
|
368346
|
-
}));
|
|
368347
|
-
dirs.push(...extensionCommandDirs);
|
|
368348
|
-
}
|
|
368349
|
-
return dirs;
|
|
368350
|
-
}
|
|
368351
|
-
/**
|
|
368352
|
-
* Parses a single .toml file and transforms it into a SlashCommand object.
|
|
368353
|
-
* @param filePath The absolute path to the .toml file.
|
|
368354
|
-
* @param baseDir The root command directory for name calculation.
|
|
368355
|
-
* @param extensionName Optional extension name to prefix commands with.
|
|
368356
|
-
* @returns A promise resolving to a SlashCommand, or null if the file is invalid.
|
|
368357
|
-
*/
|
|
368358
|
-
async parseAndAdaptFile(filePath, baseDir, extensionName) {
|
|
368359
|
-
let fileContent;
|
|
368360
|
-
try {
|
|
368361
|
-
fileContent = await fs81.readFile(filePath, "utf-8");
|
|
368362
|
-
} catch (error2) {
|
|
368363
|
-
console.error(
|
|
368364
|
-
`[FileCommandLoader] Failed to read file ${filePath}:`,
|
|
368365
|
-
error2 instanceof Error ? error2.message : String(error2)
|
|
368366
|
-
);
|
|
368367
|
-
return null;
|
|
368368
|
-
}
|
|
368369
|
-
let parsed;
|
|
368370
|
-
try {
|
|
368371
|
-
parsed = import_toml.default.parse(fileContent);
|
|
368372
|
-
} catch (error2) {
|
|
368373
|
-
console.error(
|
|
368374
|
-
`[FileCommandLoader] Failed to parse TOML file ${filePath}:`,
|
|
368375
|
-
error2 instanceof Error ? error2.message : String(error2)
|
|
368376
|
-
);
|
|
368377
|
-
return null;
|
|
368378
|
-
}
|
|
368379
|
-
const validationResult = TomlCommandDefSchema.safeParse(parsed);
|
|
368380
|
-
if (!validationResult.success) {
|
|
368381
|
-
console.error(
|
|
368382
|
-
`[FileCommandLoader] Skipping invalid command file: ${filePath}. Validation errors:`,
|
|
368383
|
-
validationResult.error.flatten()
|
|
368384
|
-
);
|
|
368385
|
-
return null;
|
|
368386
|
-
}
|
|
368387
|
-
const validDef = validationResult.data;
|
|
368388
|
-
const relativePathWithExt = path90.relative(baseDir, filePath);
|
|
368389
|
-
const relativePath = relativePathWithExt.substring(
|
|
368390
|
-
0,
|
|
368391
|
-
relativePathWithExt.length - 5
|
|
368392
|
-
// length of '.toml'
|
|
368393
|
-
);
|
|
368394
|
-
const baseCommandName = relativePath.split(path90.sep).map((segment) => segment.replaceAll(":", "_")).join(":");
|
|
368395
|
-
const defaultDescription = `Custom command from ${path90.basename(filePath)}`;
|
|
368396
|
-
let description = validDef.description || defaultDescription;
|
|
368397
|
-
if (extensionName) {
|
|
368398
|
-
description = `[${extensionName}] ${description}`;
|
|
368399
|
-
}
|
|
368400
|
-
const processors = [];
|
|
368401
|
-
const usesArgs = validDef.prompt.includes(SHORTHAND_ARGS_PLACEHOLDER);
|
|
368402
|
-
const usesShellInjection = validDef.prompt.includes(
|
|
368403
|
-
SHELL_INJECTION_TRIGGER
|
|
368404
|
-
);
|
|
368405
|
-
const usesAtFileInjection = validDef.prompt.includes(
|
|
368406
|
-
AT_FILE_INJECTION_TRIGGER
|
|
368407
|
-
);
|
|
368408
|
-
if (usesAtFileInjection) {
|
|
368409
|
-
processors.push(new AtFileProcessor(baseCommandName));
|
|
368410
|
-
}
|
|
368411
|
-
if (usesShellInjection || usesArgs) {
|
|
368412
|
-
processors.push(new ShellProcessor(baseCommandName));
|
|
368413
|
-
}
|
|
368414
|
-
if (!usesArgs) {
|
|
368415
|
-
processors.push(new DefaultArgumentProcessor());
|
|
368416
|
-
}
|
|
368417
|
-
return {
|
|
368418
|
-
name: baseCommandName,
|
|
368419
|
-
description,
|
|
368420
|
-
kind: "file" /* FILE */,
|
|
368421
|
-
extensionName,
|
|
368422
|
-
action: /* @__PURE__ */ __name(async (context2, _args) => {
|
|
368423
|
-
if (!context2.invocation) {
|
|
368424
|
-
console.error(
|
|
368425
|
-
`[FileCommandLoader] Critical error: Command '${baseCommandName}' was executed without invocation context.`
|
|
368426
|
-
);
|
|
368427
|
-
return {
|
|
368428
|
-
type: "submit_prompt",
|
|
368429
|
-
content: [{ text: validDef.prompt }]
|
|
368430
|
-
// Fallback to unprocessed prompt
|
|
368431
|
-
};
|
|
368432
|
-
}
|
|
368433
|
-
try {
|
|
368434
|
-
let processedContent = [
|
|
368435
|
-
{ text: validDef.prompt }
|
|
368436
|
-
];
|
|
368437
|
-
for (const processor of processors) {
|
|
368438
|
-
processedContent = await processor.process(
|
|
368439
|
-
processedContent,
|
|
368440
|
-
context2
|
|
368441
|
-
);
|
|
368442
|
-
}
|
|
368443
|
-
return {
|
|
368444
|
-
type: "submit_prompt",
|
|
368445
|
-
content: processedContent
|
|
368446
|
-
};
|
|
368447
|
-
} catch (e4) {
|
|
368448
|
-
if (e4 instanceof ConfirmationRequiredError) {
|
|
368449
|
-
return {
|
|
368450
|
-
type: "confirm_shell_commands",
|
|
368451
|
-
commandsToConfirm: e4.commandsToConfirm,
|
|
368452
|
-
originalInvocation: {
|
|
368453
|
-
raw: context2.invocation.raw
|
|
368454
|
-
}
|
|
368455
|
-
};
|
|
368456
|
-
}
|
|
368457
|
-
throw e4;
|
|
368458
|
-
}
|
|
368459
|
-
}, "action")
|
|
368460
|
-
};
|
|
368461
|
-
}
|
|
368462
|
-
};
|
|
368463
|
-
|
|
368464
|
-
// packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
|
|
368465
|
-
init_esbuild_shims();
|
|
368466
|
-
function createNonInteractiveUI() {
|
|
368467
|
-
return {
|
|
368468
|
-
addItem: /* @__PURE__ */ __name((_item, _timestamp) => 0, "addItem"),
|
|
368469
|
-
clear: /* @__PURE__ */ __name(() => {
|
|
368470
|
-
}, "clear"),
|
|
368471
|
-
setDebugMessage: /* @__PURE__ */ __name((_message) => {
|
|
368472
|
-
}, "setDebugMessage"),
|
|
368473
|
-
loadHistory: /* @__PURE__ */ __name((_newHistory) => {
|
|
368474
|
-
}, "loadHistory"),
|
|
368475
|
-
pendingItem: null,
|
|
368476
|
-
setPendingItem: /* @__PURE__ */ __name((_item) => {
|
|
368477
|
-
}, "setPendingItem"),
|
|
368478
|
-
toggleVimEnabled: /* @__PURE__ */ __name(async () => false, "toggleVimEnabled"),
|
|
368479
|
-
setGeminiMdFileCount: /* @__PURE__ */ __name((_count) => {
|
|
368480
|
-
}, "setGeminiMdFileCount"),
|
|
368481
|
-
reloadCommands: /* @__PURE__ */ __name(() => {
|
|
368482
|
-
}, "reloadCommands"),
|
|
368483
|
-
extensionsUpdateState: /* @__PURE__ */ new Map(),
|
|
368484
|
-
dispatchExtensionStateUpdate: /* @__PURE__ */ __name((_action) => {
|
|
368485
|
-
}, "dispatchExtensionStateUpdate"),
|
|
368486
|
-
addConfirmUpdateExtensionRequest: /* @__PURE__ */ __name((_request) => {
|
|
368487
|
-
}, "addConfirmUpdateExtensionRequest")
|
|
368488
|
-
};
|
|
368489
|
-
}
|
|
368490
|
-
__name(createNonInteractiveUI, "createNonInteractiveUI");
|
|
368491
|
-
|
|
368492
|
-
// packages/cli/src/nonInteractiveCliCommands.ts
|
|
368493
|
-
function filterCommandsForNonInteractive(commands, allowedBuiltinCommandNames) {
|
|
368494
|
-
return commands.filter((cmd) => {
|
|
368495
|
-
if (cmd.kind === "file" /* FILE */) {
|
|
368496
|
-
return true;
|
|
368497
|
-
}
|
|
368498
|
-
if (cmd.kind === "built-in" /* BUILT_IN */) {
|
|
368499
|
-
return allowedBuiltinCommandNames.has(cmd.name);
|
|
368500
|
-
}
|
|
368501
|
-
return false;
|
|
368502
|
-
});
|
|
368503
|
-
}
|
|
368504
|
-
__name(filterCommandsForNonInteractive, "filterCommandsForNonInteractive");
|
|
368505
|
-
var handleSlashCommand = /* @__PURE__ */ __name(async (rawQuery, abortController, config2, settings, allowedBuiltinCommandNames) => {
|
|
368506
|
-
const trimmed2 = rawQuery.trim();
|
|
368507
|
-
if (!trimmed2.startsWith("/")) {
|
|
368508
|
-
return;
|
|
368509
|
-
}
|
|
368510
|
-
const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
|
|
368511
|
-
const loaders = allowedBuiltinSet.size > 0 ? [new BuiltinCommandLoader(config2), new FileCommandLoader(config2)] : [new FileCommandLoader(config2)];
|
|
368512
|
-
const commandService = await CommandService.create(
|
|
368513
|
-
loaders,
|
|
368514
|
-
abortController.signal
|
|
368515
|
-
);
|
|
368516
|
-
const commands = commandService.getCommands();
|
|
368517
|
-
const filteredCommands = filterCommandsForNonInteractive(
|
|
368518
|
-
commands,
|
|
368519
|
-
allowedBuiltinSet
|
|
368520
|
-
);
|
|
368521
|
-
const { commandToExecute, args } = parseSlashCommand(
|
|
368522
|
-
rawQuery,
|
|
368523
|
-
filteredCommands
|
|
368524
|
-
);
|
|
368525
|
-
if (commandToExecute) {
|
|
368526
|
-
if (commandToExecute.action) {
|
|
368527
|
-
const sessionStats = {
|
|
368528
|
-
sessionId: config2?.getSessionId(),
|
|
368529
|
-
sessionStartTime: /* @__PURE__ */ new Date(),
|
|
368530
|
-
metrics: uiTelemetryService.getMetrics(),
|
|
368531
|
-
lastPromptTokenCount: 0,
|
|
368532
|
-
promptCount: 1
|
|
368533
|
-
};
|
|
368534
|
-
const logger6 = new Logger(config2?.getSessionId() || "", config2?.storage);
|
|
368535
|
-
const context2 = {
|
|
368536
|
-
services: {
|
|
368537
|
-
config: config2,
|
|
368538
|
-
settings,
|
|
368539
|
-
git: void 0,
|
|
368540
|
-
logger: logger6
|
|
368541
|
-
},
|
|
368542
|
-
ui: createNonInteractiveUI(),
|
|
368543
|
-
session: {
|
|
368544
|
-
stats: sessionStats,
|
|
368545
|
-
sessionShellAllowlist: /* @__PURE__ */ new Set()
|
|
368546
|
-
},
|
|
368547
|
-
invocation: {
|
|
368548
|
-
raw: trimmed2,
|
|
368549
|
-
name: commandToExecute.name,
|
|
368550
|
-
args
|
|
368551
|
-
}
|
|
368552
|
-
};
|
|
368553
|
-
const result = await commandToExecute.action(context2, args);
|
|
368554
|
-
if (result) {
|
|
368555
|
-
switch (result.type) {
|
|
368556
|
-
case "submit_prompt":
|
|
368557
|
-
return result.content;
|
|
368558
|
-
case "confirm_shell_commands":
|
|
368559
|
-
throw new FatalInputError(
|
|
368560
|
-
"Exiting due to a confirmation prompt requested by the command."
|
|
368561
|
-
);
|
|
368562
|
-
default:
|
|
368563
|
-
throw new FatalInputError(
|
|
368564
|
-
"Exiting due to command result that is not supported in non-interactive mode."
|
|
368565
|
-
);
|
|
368566
|
-
}
|
|
368567
|
-
}
|
|
368568
|
-
}
|
|
368569
|
-
}
|
|
368570
|
-
return;
|
|
368571
|
-
}, "handleSlashCommand");
|
|
368572
|
-
var getAvailableCommands = /* @__PURE__ */ __name(async (config2, settings, abortSignal, allowedBuiltinCommandNames) => {
|
|
368573
|
-
try {
|
|
368574
|
-
const allowedBuiltinSet = new Set(allowedBuiltinCommandNames ?? []);
|
|
368575
|
-
const loaders = allowedBuiltinSet.size > 0 ? [new BuiltinCommandLoader(config2), new FileCommandLoader(config2)] : [new FileCommandLoader(config2)];
|
|
368576
|
-
const commandService = await CommandService.create(loaders, abortSignal);
|
|
368577
|
-
const commands = commandService.getCommands();
|
|
368578
|
-
const filteredCommands = filterCommandsForNonInteractive(
|
|
368579
|
-
commands,
|
|
368580
|
-
allowedBuiltinSet
|
|
368581
|
-
);
|
|
368582
|
-
return filteredCommands.filter((cmd) => !cmd.hidden);
|
|
368583
|
-
} catch (error2) {
|
|
368584
|
-
console.error("Error loading available commands:", error2);
|
|
368585
|
-
return [];
|
|
368586
|
-
}
|
|
368587
|
-
}, "getAvailableCommands");
|
|
368588
|
-
|
|
368589
368858
|
// packages/cli/src/ui/hooks/atCommandProcessor.ts
|
|
368590
368859
|
init_esbuild_shims();
|
|
368591
368860
|
import * as fs82 from "node:fs/promises";
|
|
@@ -368925,6 +369194,36 @@ Content from @${filePathSpecInContent}:
|
|
|
368925
369194
|
__name(handleAtCommand, "handleAtCommand");
|
|
368926
369195
|
|
|
368927
369196
|
// packages/cli/src/nonInteractiveCli.ts
|
|
369197
|
+
async function emitNonInteractiveFinalMessage(params) {
|
|
369198
|
+
const { message, isError, adapter, config: config2 } = params;
|
|
369199
|
+
if (!adapter) {
|
|
369200
|
+
const target = isError ? process.stderr : process.stdout;
|
|
369201
|
+
target.write(`${message}
|
|
369202
|
+
`);
|
|
369203
|
+
return;
|
|
369204
|
+
}
|
|
369205
|
+
adapter.startAssistantMessage();
|
|
369206
|
+
adapter.processEvent({
|
|
369207
|
+
type: GeminiEventType.Content,
|
|
369208
|
+
value: message
|
|
369209
|
+
});
|
|
369210
|
+
adapter.finalizeAssistantMessage();
|
|
369211
|
+
const metrics2 = uiTelemetryService.getMetrics();
|
|
369212
|
+
const usage2 = computeUsageFromMetrics(metrics2);
|
|
369213
|
+
const outputFormat = config2.getOutputFormat();
|
|
369214
|
+
const stats = outputFormat === OutputFormat.JSON ? uiTelemetryService.getMetrics() : void 0;
|
|
369215
|
+
adapter.emitResult({
|
|
369216
|
+
isError,
|
|
369217
|
+
durationMs: Date.now() - params.startTimeMs,
|
|
369218
|
+
apiDurationMs: 0,
|
|
369219
|
+
numTurns: 0,
|
|
369220
|
+
errorMessage: isError ? message : void 0,
|
|
369221
|
+
usage: usage2,
|
|
369222
|
+
stats,
|
|
369223
|
+
summary: message
|
|
369224
|
+
});
|
|
369225
|
+
}
|
|
369226
|
+
__name(emitNonInteractiveFinalMessage, "emitNonInteractiveFinalMessage");
|
|
368928
369227
|
async function runNonInteractive(config2, settings, input, prompt_id, options2 = {}) {
|
|
368929
369228
|
return promptIdContext.run(prompt_id, async () => {
|
|
368930
369229
|
let adapter;
|
|
@@ -368962,6 +369261,14 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
|
|
|
368962
369261
|
process.stdout.on("error", stdoutErrorHandler);
|
|
368963
369262
|
process.on("SIGINT", shutdownHandler);
|
|
368964
369263
|
process.on("SIGTERM", shutdownHandler);
|
|
369264
|
+
if (adapter) {
|
|
369265
|
+
const systemMessage = await buildSystemMessage(
|
|
369266
|
+
config2,
|
|
369267
|
+
sessionId,
|
|
369268
|
+
permissionMode
|
|
369269
|
+
);
|
|
369270
|
+
adapter.emitMessage(systemMessage);
|
|
369271
|
+
}
|
|
368965
369272
|
let initialPartList = extractPartsFromUserMessage(
|
|
368966
369273
|
options2.userMessage
|
|
368967
369274
|
);
|
|
@@ -368974,9 +369281,43 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
|
|
|
368974
369281
|
config2,
|
|
368975
369282
|
settings
|
|
368976
369283
|
);
|
|
368977
|
-
|
|
368978
|
-
|
|
368979
|
-
|
|
369284
|
+
switch (slashCommandResult.type) {
|
|
369285
|
+
case "submit_prompt":
|
|
369286
|
+
initialPartList = slashCommandResult.content;
|
|
369287
|
+
slashHandled = true;
|
|
369288
|
+
break;
|
|
369289
|
+
case "message": {
|
|
369290
|
+
await emitNonInteractiveFinalMessage({
|
|
369291
|
+
message: slashCommandResult.content,
|
|
369292
|
+
isError: slashCommandResult.messageType === "error",
|
|
369293
|
+
adapter,
|
|
369294
|
+
config: config2,
|
|
369295
|
+
startTimeMs: startTime
|
|
369296
|
+
});
|
|
369297
|
+
return;
|
|
369298
|
+
}
|
|
369299
|
+
case "stream_messages":
|
|
369300
|
+
throw new FatalInputError(
|
|
369301
|
+
"Stream messages mode is not supported in non-interactive CLI"
|
|
369302
|
+
);
|
|
369303
|
+
case "unsupported": {
|
|
369304
|
+
await emitNonInteractiveFinalMessage({
|
|
369305
|
+
message: slashCommandResult.reason,
|
|
369306
|
+
isError: true,
|
|
369307
|
+
adapter,
|
|
369308
|
+
config: config2,
|
|
369309
|
+
startTimeMs: startTime
|
|
369310
|
+
});
|
|
369311
|
+
return;
|
|
369312
|
+
}
|
|
369313
|
+
case "no_command":
|
|
369314
|
+
break;
|
|
369315
|
+
default: {
|
|
369316
|
+
const _exhaustive = slashCommandResult;
|
|
369317
|
+
throw new FatalInputError(
|
|
369318
|
+
`Unhandled slash command result type: ${_exhaustive.type}`
|
|
369319
|
+
);
|
|
369320
|
+
}
|
|
368980
369321
|
}
|
|
368981
369322
|
}
|
|
368982
369323
|
if (!slashHandled) {
|
|
@@ -369002,14 +369343,6 @@ async function runNonInteractive(config2, settings, input, prompt_id, options2 =
|
|
|
369002
369343
|
}
|
|
369003
369344
|
const initialParts = normalizePartList(initialPartList);
|
|
369004
369345
|
let currentMessages = [{ role: "user", parts: initialParts }];
|
|
369005
|
-
if (adapter) {
|
|
369006
|
-
const systemMessage = await buildSystemMessage(
|
|
369007
|
-
config2,
|
|
369008
|
-
sessionId,
|
|
369009
|
-
permissionMode
|
|
369010
|
-
);
|
|
369011
|
-
adapter.emitMessage(systemMessage);
|
|
369012
|
-
}
|
|
369013
369346
|
let isFirstTurn = true;
|
|
369014
369347
|
while (true) {
|
|
369015
369348
|
turnCount++;
|
|
@@ -369689,7 +370022,7 @@ var SystemController = class extends BaseController {
|
|
|
369689
370022
|
};
|
|
369690
370023
|
}
|
|
369691
370024
|
/**
|
|
369692
|
-
* Load slash command names using
|
|
370025
|
+
* Load slash command names using getAvailableCommands
|
|
369693
370026
|
*
|
|
369694
370027
|
* @param signal - AbortSignal to respect for cancellation
|
|
369695
370028
|
* @returns Promise resolving to array of slash command names
|
|
@@ -369699,19 +370032,11 @@ var SystemController = class extends BaseController {
|
|
|
369699
370032
|
return [];
|
|
369700
370033
|
}
|
|
369701
370034
|
try {
|
|
369702
|
-
const
|
|
369703
|
-
[new BuiltinCommandLoader(this.context.config)],
|
|
369704
|
-
signal
|
|
369705
|
-
);
|
|
370035
|
+
const commands = await getAvailableCommands(this.context.config, signal);
|
|
369706
370036
|
if (signal.aborted) {
|
|
369707
370037
|
return [];
|
|
369708
370038
|
}
|
|
369709
|
-
|
|
369710
|
-
const commands = service.getCommands();
|
|
369711
|
-
for (const command2 of commands) {
|
|
369712
|
-
names.add(command2.name);
|
|
369713
|
-
}
|
|
369714
|
-
return Array.from(names).sort();
|
|
370039
|
+
return commands.map((cmd) => cmd.name).sort();
|
|
369715
370040
|
} catch (error2) {
|
|
369716
370041
|
if (signal.aborted) {
|
|
369717
370042
|
return [];
|
|
@@ -403285,6 +403610,11 @@ var useSlashCommandProcessor = /* @__PURE__ */ __name((config2, settings, addIte
|
|
|
403285
403610
|
true
|
|
403286
403611
|
);
|
|
403287
403612
|
}
|
|
403613
|
+
case "stream_messages": {
|
|
403614
|
+
throw new Error(
|
|
403615
|
+
"stream_messages result type is not supported in interactive mode"
|
|
403616
|
+
);
|
|
403617
|
+
}
|
|
403288
403618
|
default: {
|
|
403289
403619
|
const unhandled = result;
|
|
403290
403620
|
throw new Error(
|
|
@@ -412068,8 +412398,22 @@ var authenticateUpdateSchema = external_exports.object({
|
|
|
412068
412398
|
authUri: external_exports.string()
|
|
412069
412399
|
})
|
|
412070
412400
|
});
|
|
412401
|
+
var acpMetaSchema = external_exports.record(external_exports.unknown()).nullable().optional();
|
|
412402
|
+
var modelIdSchema = external_exports.string();
|
|
412403
|
+
var modelInfoSchema = external_exports.object({
|
|
412404
|
+
_meta: acpMetaSchema,
|
|
412405
|
+
description: external_exports.string().nullable().optional(),
|
|
412406
|
+
modelId: modelIdSchema,
|
|
412407
|
+
name: external_exports.string()
|
|
412408
|
+
});
|
|
412409
|
+
var sessionModelStateSchema = external_exports.object({
|
|
412410
|
+
_meta: acpMetaSchema,
|
|
412411
|
+
availableModels: external_exports.array(modelInfoSchema),
|
|
412412
|
+
currentModelId: modelIdSchema
|
|
412413
|
+
});
|
|
412071
412414
|
var newSessionResponseSchema = external_exports.object({
|
|
412072
|
-
sessionId: external_exports.string()
|
|
412415
|
+
sessionId: external_exports.string(),
|
|
412416
|
+
models: sessionModelStateSchema
|
|
412073
412417
|
});
|
|
412074
412418
|
var loadSessionResponseSchema = external_exports.null();
|
|
412075
412419
|
var sessionListItemSchema = external_exports.object({
|
|
@@ -412283,6 +412627,10 @@ var currentModeUpdateSchema = external_exports.object({
|
|
|
412283
412627
|
sessionUpdate: external_exports.literal("current_mode_update"),
|
|
412284
412628
|
modeId: approvalModeValueSchema
|
|
412285
412629
|
});
|
|
412630
|
+
var currentModelUpdateSchema = external_exports.object({
|
|
412631
|
+
sessionUpdate: external_exports.literal("current_model_update"),
|
|
412632
|
+
model: modelInfoSchema
|
|
412633
|
+
});
|
|
412286
412634
|
var sessionUpdateSchema = external_exports.union([
|
|
412287
412635
|
external_exports.object({
|
|
412288
412636
|
content: contentBlockSchema,
|
|
@@ -412324,6 +412672,7 @@ var sessionUpdateSchema = external_exports.union([
|
|
|
412324
412672
|
sessionUpdate: external_exports.literal("plan")
|
|
412325
412673
|
}),
|
|
412326
412674
|
currentModeUpdateSchema,
|
|
412675
|
+
currentModelUpdateSchema,
|
|
412327
412676
|
availableCommandsUpdateSchema
|
|
412328
412677
|
]);
|
|
412329
412678
|
var agentResponseSchema = external_exports.union([
|
|
@@ -412437,6 +412786,13 @@ var AgentSideConnection = class {
|
|
|
412437
412786
|
params
|
|
412438
412787
|
);
|
|
412439
412788
|
}
|
|
412789
|
+
/**
|
|
412790
|
+
* Sends a custom notification to the client.
|
|
412791
|
+
* Used for extension-specific notifications that are not part of the core ACP protocol.
|
|
412792
|
+
*/
|
|
412793
|
+
async sendCustomNotification(method, params) {
|
|
412794
|
+
return await this.#connection.sendNotification(method, params);
|
|
412795
|
+
}
|
|
412440
412796
|
/**
|
|
412441
412797
|
* Request permission before running a tool
|
|
412442
412798
|
*
|
|
@@ -413426,7 +413782,6 @@ var SubAgentTracker = class {
|
|
|
413426
413782
|
};
|
|
413427
413783
|
|
|
413428
413784
|
// packages/cli/src/acp-integration/session/Session.ts
|
|
413429
|
-
var ALLOWED_BUILTIN_COMMANDS_FOR_ACP = ["init"];
|
|
413430
413785
|
var Session3 = class {
|
|
413431
413786
|
constructor(id, chat, config2, client, settings) {
|
|
413432
413787
|
this.chat = chat;
|
|
@@ -413497,13 +413852,14 @@ var Session3 = class {
|
|
|
413497
413852
|
inputText,
|
|
413498
413853
|
pendingSend,
|
|
413499
413854
|
this.config,
|
|
413500
|
-
this.settings
|
|
413501
|
-
ALLOWED_BUILTIN_COMMANDS_FOR_ACP
|
|
413855
|
+
this.settings
|
|
413502
413856
|
);
|
|
413503
|
-
|
|
413504
|
-
|
|
413505
|
-
|
|
413506
|
-
|
|
413857
|
+
parts = await this.#processSlashCommandResult(
|
|
413858
|
+
slashCommandResult,
|
|
413859
|
+
params.prompt
|
|
413860
|
+
);
|
|
413861
|
+
if (parts === null) {
|
|
413862
|
+
return { stopReason: "end_turn" };
|
|
413507
413863
|
}
|
|
413508
413864
|
} else {
|
|
413509
413865
|
parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
|
|
@@ -413593,9 +413949,7 @@ var Session3 = class {
|
|
|
413593
413949
|
try {
|
|
413594
413950
|
const slashCommands = await getAvailableCommands(
|
|
413595
413951
|
this.config,
|
|
413596
|
-
|
|
413597
|
-
abortController.signal,
|
|
413598
|
-
ALLOWED_BUILTIN_COMMANDS_FOR_ACP
|
|
413952
|
+
abortController.signal
|
|
413599
413953
|
);
|
|
413600
413954
|
const availableCommands = slashCommands.map(
|
|
413601
413955
|
(cmd) => ({
|
|
@@ -413842,6 +414196,71 @@ var Session3 = class {
|
|
|
413842
414196
|
return errorResponse(error2);
|
|
413843
414197
|
}
|
|
413844
414198
|
}
|
|
414199
|
+
/**
|
|
414200
|
+
* Processes the result of a slash command execution.
|
|
414201
|
+
*
|
|
414202
|
+
* Supported result types in ACP mode:
|
|
414203
|
+
* - submit_prompt: Submits content to the model
|
|
414204
|
+
* - stream_messages: Streams multiple messages to the client (ACP-specific)
|
|
414205
|
+
* - unsupported: Command cannot be executed in ACP mode
|
|
414206
|
+
* - no_command: No command was found, use original prompt
|
|
414207
|
+
*
|
|
414208
|
+
* Note: 'message' type is not supported in ACP mode - commands should use
|
|
414209
|
+
* 'stream_messages' instead for consistent async handling.
|
|
414210
|
+
*
|
|
414211
|
+
* @param result The result from handleSlashCommand
|
|
414212
|
+
* @param originalPrompt The original prompt blocks
|
|
414213
|
+
* @returns Parts to use for the prompt, or null if command was handled without needing model interaction
|
|
414214
|
+
*/
|
|
414215
|
+
async #processSlashCommandResult(result, originalPrompt) {
|
|
414216
|
+
switch (result.type) {
|
|
414217
|
+
case "submit_prompt":
|
|
414218
|
+
return normalizePartList(result.content);
|
|
414219
|
+
case "message": {
|
|
414220
|
+
await this.client.sendCustomNotification("_qwencode/slash_command", {
|
|
414221
|
+
sessionId: this.sessionId,
|
|
414222
|
+
command: originalPrompt.filter((block2) => block2.type === "text").map((block2) => block2.type === "text" ? block2.text : "").join(" "),
|
|
414223
|
+
messageType: result.messageType,
|
|
414224
|
+
message: result.content || ""
|
|
414225
|
+
});
|
|
414226
|
+
if (result.messageType === "error") {
|
|
414227
|
+
throw new Error(result.content || "Slash command failed.");
|
|
414228
|
+
}
|
|
414229
|
+
return null;
|
|
414230
|
+
}
|
|
414231
|
+
case "stream_messages": {
|
|
414232
|
+
const command2 = originalPrompt.filter((block2) => block2.type === "text").map((block2) => block2.type === "text" ? block2.text : "").join(" ");
|
|
414233
|
+
for await (const msg of result.messages) {
|
|
414234
|
+
await this.client.sendCustomNotification("_qwencode/slash_command", {
|
|
414235
|
+
sessionId: this.sessionId,
|
|
414236
|
+
command: command2,
|
|
414237
|
+
messageType: msg.messageType,
|
|
414238
|
+
message: msg.content
|
|
414239
|
+
});
|
|
414240
|
+
if (msg.messageType === "error") {
|
|
414241
|
+
throw new Error(msg.content || "Slash command failed.");
|
|
414242
|
+
}
|
|
414243
|
+
}
|
|
414244
|
+
return null;
|
|
414245
|
+
}
|
|
414246
|
+
case "unsupported": {
|
|
414247
|
+
const unsupportedError = `Slash command not supported in ACP integration: ${result.reason}`;
|
|
414248
|
+
throw new Error(unsupportedError);
|
|
414249
|
+
}
|
|
414250
|
+
case "no_command":
|
|
414251
|
+
return originalPrompt.map((block2) => {
|
|
414252
|
+
if (block2.type === "text") {
|
|
414253
|
+
return { text: block2.text };
|
|
414254
|
+
}
|
|
414255
|
+
throw new Error(`Unsupported block type: ${block2.type}`);
|
|
414256
|
+
});
|
|
414257
|
+
default: {
|
|
414258
|
+
const _exhaustive = result;
|
|
414259
|
+
const unknownError = `Unknown slash command result type: ${_exhaustive.type}`;
|
|
414260
|
+
throw new Error(unknownError);
|
|
414261
|
+
}
|
|
414262
|
+
}
|
|
414263
|
+
}
|
|
413845
414264
|
async #resolvePrompt(message, abortSignal) {
|
|
413846
414265
|
const FILE_URI_SCHEME = "file://";
|
|
413847
414266
|
const embeddedContext = [];
|
|
@@ -414181,7 +414600,7 @@ var GeminiAgent = class {
|
|
|
414181
414600
|
name: APPROVAL_MODE_INFO[mode].name,
|
|
414182
414601
|
description: APPROVAL_MODE_INFO[mode].description
|
|
414183
414602
|
}));
|
|
414184
|
-
const version2 = "0.6.0
|
|
414603
|
+
const version2 = "0.6.0";
|
|
414185
414604
|
return {
|
|
414186
414605
|
protocolVersion: PROTOCOL_VERSION,
|
|
414187
414606
|
agentInfo: {
|
|
@@ -414237,8 +414656,25 @@ var GeminiAgent = class {
|
|
|
414237
414656
|
await this.ensureAuthenticated(config2);
|
|
414238
414657
|
this.setupFileSystem(config2);
|
|
414239
414658
|
const session = await this.createAndStoreSession(config2);
|
|
414659
|
+
const configuredModel = (config2.getModel() || this.config.getModel() || "").trim();
|
|
414660
|
+
const modelId = configuredModel || "default";
|
|
414661
|
+
const modelName = configuredModel || modelId;
|
|
414240
414662
|
return {
|
|
414241
|
-
sessionId: session.getId()
|
|
414663
|
+
sessionId: session.getId(),
|
|
414664
|
+
models: {
|
|
414665
|
+
currentModelId: modelId,
|
|
414666
|
+
availableModels: [
|
|
414667
|
+
{
|
|
414668
|
+
modelId,
|
|
414669
|
+
name: modelName,
|
|
414670
|
+
description: null,
|
|
414671
|
+
_meta: {
|
|
414672
|
+
contextLimit: tokenLimit(modelId)
|
|
414673
|
+
}
|
|
414674
|
+
}
|
|
414675
|
+
],
|
|
414676
|
+
_meta: null
|
|
414677
|
+
}
|
|
414242
414678
|
};
|
|
414243
414679
|
}
|
|
414244
414680
|
async newSessionConfig(cwd7, mcpServers, sessionId) {
|
|
@@ -414364,8 +414800,10 @@ var GeminiAgent = class {
|
|
|
414364
414800
|
async createAndStoreSession(config2, conversation) {
|
|
414365
414801
|
const sessionId = config2.getSessionId();
|
|
414366
414802
|
const geminiClient = config2.getGeminiClient();
|
|
414367
|
-
|
|
414368
|
-
|
|
414803
|
+
if (!geminiClient.isInitialized()) {
|
|
414804
|
+
await geminiClient.initialize();
|
|
414805
|
+
}
|
|
414806
|
+
const chat = geminiClient.getChat();
|
|
414369
414807
|
const session = new Session3(
|
|
414370
414808
|
sessionId,
|
|
414371
414809
|
chat,
|