scream-code 0.13.9 → 0.14.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.
|
@@ -4,7 +4,7 @@ import { dirname as __cjsShimDirname } from 'node:path';
|
|
|
4
4
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = __cjsShimDirname(__filename);
|
|
6
6
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
7
|
-
import { $t as isTodoItemShape, A as renderDiffLinesClustered, An as CLI_COMMAND_NAME, At as ENABLE_TERMINAL_FOCUS_REPORTING, B as BackgroundAgentStatusComponent, Bn as MemoryMemoStore, Bt as TERMINAL_THEME_LIGHT, Cn as loadTuiConfig, Ct as createThemeStyles, D as toggleEmptySessionHint, Dn as getInputHistoryFile, Dt as parseOsc11BackgroundTheme, E as isTurnElapsedEnabled, En as getDataDir, Et as detectTerminalTheme, F as estimateTokens, Fn as fetchCatalog, Ft as OSC11_RESPONSE_PREFIX_NO_ESC, G as getBreathingFrame, Gn as isOrphanedToolCallError, H as AgentGroupComponent, Hn as log, Ht as isStreaming, I as getSharedSpeedTracker, In as saveCatalogCache, It as QUERY_TERMINAL_THEME, J as refineGoal, Jt as printableChar, K as resetBreathingClock, Kn as ErrorCodes, L as SkillActivationComponent, Ln as ScreamHarness, Lt as TERMINAL_FOCUS_IN, M as langFromPath, Mn as CLI_USER_AGENT_PRODUCT, Mt as OSC11_QUERY, N as CachedContainer, Nn as PRODUCT_NAME, Nt as OSC11_RESPONSE, O as ToolCallComponent, On as getLogDir, Ot as DISABLE_TERMINAL_FOCUS_REPORTING, P as ThinkingComponent, Pn as DEFAULT_CATALOG_URL, Pt as OSC11_RESPONSE_PREFIX, Qt as formatErrorMessage, R as ReadGroupComponent, Rt as TERMINAL_FOCUS_OUT, S as getDaemonInstructions, Sn as TuiLikePreferencesSchema, St as createMarkdownTheme, T as isEmptySessionHintDismissed, Tn as detectShellEnvironment, Tt as getColorPalette, U as WelcomeComponent, Un as resolveGlobalLogPath, Ut as FooterComponent, V as AssistantMessageComponent, Vn as flushDiagnosticLogs, Vt as isBusy, W as BREATHE_CYCLE_MS, Wn as isScreamError, Xt as appendStreamingArgsPreview, Yt as STATUS_BULLET, Zt as argsRecord, _ as refreshUpdateCache, _n as isExperimentalFlagEnabled, _t as clearInfoPanelState, an as EMPTY_SESSION_HINT_URL, b as readJsonlFile, bn as PULSE_WAVE_FRAMES, bt as resolveThemeSync, c as hasDispose, cn as SESSION_TIPS, ct as handlePlanCommand, d as formatMemoryMemoForInjection, dn as getCtrlDHint, en as parseStreamingArgs, et as toTerminalHyperlink, fn as getLlmNotSetMessage, g as selectUpdateTarget, gn as sortSlashCommands, gt as supportsBalance, hn as BUILTIN_SLASH_COMMANDS, ht as refreshProviderBalance, i as buildRoleAdditionalText, in as CHARS_PER_TOKEN, j as highlightLines, jn as CLI_UI_MODE, jt as ENABLE_TERMINAL_THEME_REPORTING, k as renderDiffLines, kn as detectInstallSource, kt as DISABLE_TERMINAL_THEME_REPORTING, l as isPlanExpandable, ln as TIP_ROTATION_INTERVAL_MS, mn as buildSkillSlashCommands, n as clearEvalPanelState, nn as stringValue, nt as getModelCycleLevel, on as EXIT_CONFIRM_WINDOW_MS, ot as handleFusionPlanCommand, pn as getNoActiveSessionMessage, q as clearGoalState, qn as SCREAM_ERROR_INFO, r as openUrl, rn as truncateErrorMessage, s as disposeChildren, sn as MAIN_AGENT_ID, t as dispatchInput, tn as serializeToolResultOutput, tt as changeThinkingLevel, u as MoonLoader, un as getCtrlCHint, v as readUpdateCache, vn as setExperimentalFlags, w as UserMessageComponent, wn as saveTuiConfig, wt as contrastTextHex, xn as TuiConfigParseError, xt as createEditorTheme, y as appendJsonlLine, yn as PIXEL_PULSE_FRAMES, z as parseReadGroupOutput, zn as resolveScreamHome, zt as TERMINAL_THEME_DARK } from "./dispatch-
|
|
7
|
+
import { $t as isTodoItemShape, A as renderDiffLinesClustered, An as CLI_COMMAND_NAME, At as ENABLE_TERMINAL_FOCUS_REPORTING, B as BackgroundAgentStatusComponent, Bn as MemoryMemoStore, Bt as TERMINAL_THEME_LIGHT, Cn as loadTuiConfig, Ct as createThemeStyles, D as toggleEmptySessionHint, Dn as getInputHistoryFile, Dt as parseOsc11BackgroundTheme, E as isTurnElapsedEnabled, En as getDataDir, Et as detectTerminalTheme, F as estimateTokens, Fn as fetchCatalog, Ft as OSC11_RESPONSE_PREFIX_NO_ESC, G as getBreathingFrame, Gn as isOrphanedToolCallError, H as AgentGroupComponent, Hn as log, Ht as isStreaming, I as getSharedSpeedTracker, In as saveCatalogCache, It as QUERY_TERMINAL_THEME, J as refineGoal, Jt as printableChar, K as resetBreathingClock, Kn as ErrorCodes, L as SkillActivationComponent, Ln as ScreamHarness, Lt as TERMINAL_FOCUS_IN, M as langFromPath, Mn as CLI_USER_AGENT_PRODUCT, Mt as OSC11_QUERY, N as CachedContainer, Nn as PRODUCT_NAME, Nt as OSC11_RESPONSE, O as ToolCallComponent, On as getLogDir, Ot as DISABLE_TERMINAL_FOCUS_REPORTING, P as ThinkingComponent, Pn as DEFAULT_CATALOG_URL, Pt as OSC11_RESPONSE_PREFIX, Qt as formatErrorMessage, R as ReadGroupComponent, Rt as TERMINAL_FOCUS_OUT, S as getDaemonInstructions, Sn as TuiLikePreferencesSchema, St as createMarkdownTheme, T as isEmptySessionHintDismissed, Tn as detectShellEnvironment, Tt as getColorPalette, U as WelcomeComponent, Un as resolveGlobalLogPath, Ut as FooterComponent, V as AssistantMessageComponent, Vn as flushDiagnosticLogs, Vt as isBusy, W as BREATHE_CYCLE_MS, Wn as isScreamError, Xt as appendStreamingArgsPreview, Yt as STATUS_BULLET, Zt as argsRecord, _ as refreshUpdateCache, _n as isExperimentalFlagEnabled, _t as clearInfoPanelState, an as EMPTY_SESSION_HINT_URL, b as readJsonlFile, bn as PULSE_WAVE_FRAMES, bt as resolveThemeSync, c as hasDispose, cn as SESSION_TIPS, ct as handlePlanCommand, d as formatMemoryMemoForInjection, dn as getCtrlDHint, en as parseStreamingArgs, et as toTerminalHyperlink, fn as getLlmNotSetMessage, g as selectUpdateTarget, gn as sortSlashCommands, gt as supportsBalance, hn as BUILTIN_SLASH_COMMANDS, ht as refreshProviderBalance, i as buildRoleAdditionalText, in as CHARS_PER_TOKEN, j as highlightLines, jn as CLI_UI_MODE, jt as ENABLE_TERMINAL_THEME_REPORTING, k as renderDiffLines, kn as detectInstallSource, kt as DISABLE_TERMINAL_THEME_REPORTING, l as isPlanExpandable, ln as TIP_ROTATION_INTERVAL_MS, mn as buildSkillSlashCommands, n as clearEvalPanelState, nn as stringValue, nt as getModelCycleLevel, on as EXIT_CONFIRM_WINDOW_MS, ot as handleFusionPlanCommand, pn as getNoActiveSessionMessage, q as clearGoalState, qn as SCREAM_ERROR_INFO, r as openUrl, rn as truncateErrorMessage, s as disposeChildren, sn as MAIN_AGENT_ID, t as dispatchInput, tn as serializeToolResultOutput, tt as changeThinkingLevel, u as MoonLoader, un as getCtrlCHint, v as readUpdateCache, vn as setExperimentalFlags, w as UserMessageComponent, wn as saveTuiConfig, wt as contrastTextHex, xn as TuiConfigParseError, xt as createEditorTheme, y as appendJsonlLine, yn as PIXEL_PULSE_FRAMES, z as parseReadGroupOutput, zn as resolveScreamHome, zt as TERMINAL_THEME_DARK } from "./dispatch-202xtik3.mjs";
|
|
8
8
|
import { a as setLocale, o as t } from "./text-input-dialog-BzVVVncg.mjs";
|
|
9
9
|
import { createRequire } from "node:module";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
@@ -30,7 +30,7 @@ function optionalBuildString(value) {
|
|
|
30
30
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
31
31
|
}
|
|
32
32
|
const SCREAM_BUILD_INFO = {
|
|
33
|
-
version: optionalBuildString("0.
|
|
33
|
+
version: optionalBuildString("0.14.0"),
|
|
34
34
|
channel: optionalBuildString(""),
|
|
35
35
|
commit: optionalBuildString(""),
|
|
36
36
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -2909,9 +2909,9 @@ var SessionEventHandler = class {
|
|
|
2909
2909
|
const { name, purpose } = event.candidate;
|
|
2910
2910
|
if (name.length === 0) return;
|
|
2911
2911
|
if (this.promptedSkillCandidates.has(name)) return;
|
|
2912
|
-
this.promptedSkillCandidates.add(name);
|
|
2913
2912
|
const session = this.host.session;
|
|
2914
2913
|
if (session === void 0) return;
|
|
2914
|
+
this.promptedSkillCandidates.add(name);
|
|
2915
2915
|
if (this.host.streamingUI.hasActiveTurn()) {
|
|
2916
2916
|
this.pendingSkillCandidates.push({
|
|
2917
2917
|
name,
|
|
@@ -12192,7 +12192,7 @@ var ScreamTUI = class {
|
|
|
12192
12192
|
const card = new OnboardingCardComponent({
|
|
12193
12193
|
colors: this.state.theme.colors,
|
|
12194
12194
|
onConfigure: () => {
|
|
12195
|
-
import("./dispatch-
|
|
12195
|
+
import("./dispatch-D71h_08g.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
|
|
12196
12196
|
this.restoreEditor();
|
|
12197
12197
|
});
|
|
12198
12198
|
},
|
|
@@ -13237,26 +13237,21 @@ function mapCcConnectMode(mode) {
|
|
|
13237
13237
|
};
|
|
13238
13238
|
}
|
|
13239
13239
|
}
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
|
|
13246
|
-
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
streamTuiConfig = error.fallback;
|
|
13256
|
-
setLocale(streamTuiConfig.language);
|
|
13257
|
-
}
|
|
13258
|
-
const streamSubagentModels = streamTuiConfig.subagentModels;
|
|
13259
|
-
harness.setSubagentModelBindings(() => streamSubagentModels);
|
|
13240
|
+
/**
|
|
13241
|
+
* Install the stdout EPIPE guard and return the line writer handed to
|
|
13242
|
+
* {@link ClaudeStreamJsonWriter}.
|
|
13243
|
+
*
|
|
13244
|
+
* cc-connect closes our stdout when it kills/restarts the agent (idle
|
|
13245
|
+
* timeout, /restart, config change). Writing after that raises EPIPE as an
|
|
13246
|
+
* unhandled error and crashes the process. The pipe is gone — results can
|
|
13247
|
+
* no longer be delivered — so exit quietly instead of burning tokens as a
|
|
13248
|
+
* zombie waiting for a signal that may never come.
|
|
13249
|
+
*
|
|
13250
|
+
* Both the `error` event on stdout and a throw from `stdout.write` are
|
|
13251
|
+
* covered: EPIPE → process.exit(0); any other error is surfaced (rethrown or
|
|
13252
|
+
* logged) so real I/O failures are not masked.
|
|
13253
|
+
*/
|
|
13254
|
+
function installStdoutEpipeGuard() {
|
|
13260
13255
|
const handleStdoutClosed = () => {
|
|
13261
13256
|
log.debug("stream-json: stdout closed (EPIPE), exiting");
|
|
13262
13257
|
process.exit(0);
|
|
@@ -13268,7 +13263,7 @@ async function runStreamJson(opts) {
|
|
|
13268
13263
|
}
|
|
13269
13264
|
log.error("stream-json: stdout error", { error: String(error) });
|
|
13270
13265
|
});
|
|
13271
|
-
|
|
13266
|
+
return (line) => {
|
|
13272
13267
|
try {
|
|
13273
13268
|
process.stdout.write(`${line}\n`);
|
|
13274
13269
|
} catch (error) {
|
|
@@ -13278,7 +13273,29 @@ async function runStreamJson(opts) {
|
|
|
13278
13273
|
}
|
|
13279
13274
|
throw error;
|
|
13280
13275
|
}
|
|
13276
|
+
};
|
|
13277
|
+
}
|
|
13278
|
+
async function runStreamJson(opts) {
|
|
13279
|
+
const homeDir = resolveScreamHome();
|
|
13280
|
+
const workDir = opts.workDir ?? process.cwd();
|
|
13281
|
+
const harness = new ScreamHarness({
|
|
13282
|
+
homeDir,
|
|
13283
|
+
identity: createScreamCodeHostIdentity("dev"),
|
|
13284
|
+
uiMode: "print",
|
|
13285
|
+
skillDirs: opts.skillsDirs
|
|
13281
13286
|
});
|
|
13287
|
+
let streamTuiConfig;
|
|
13288
|
+
try {
|
|
13289
|
+
streamTuiConfig = await loadTuiConfig();
|
|
13290
|
+
setLocale(streamTuiConfig.language);
|
|
13291
|
+
} catch (error) {
|
|
13292
|
+
if (!(error instanceof TuiConfigParseError)) throw error;
|
|
13293
|
+
streamTuiConfig = error.fallback;
|
|
13294
|
+
setLocale(streamTuiConfig.language);
|
|
13295
|
+
}
|
|
13296
|
+
const streamSubagentModels = streamTuiConfig.subagentModels;
|
|
13297
|
+
harness.setSubagentModelBindings(() => streamSubagentModels);
|
|
13298
|
+
const writer = new ClaudeStreamJsonWriter(installStdoutEpipeGuard());
|
|
13282
13299
|
let session;
|
|
13283
13300
|
let currentSessionId;
|
|
13284
13301
|
let sessionKey = "cc-connect-main";
|
|
@@ -64654,7 +64654,23 @@ function renderPrompt(template, vars) {
|
|
|
64654
64654
|
}
|
|
64655
64655
|
//#endregion
|
|
64656
64656
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/skill-tool.md
|
|
64657
|
-
var skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do NOT call the same skill repeatedly inside one turn — recursive depth is capped at {{ MAX_SKILL_QUERY_DEPTH }}.";
|
|
64657
|
+
var skill_tool_default = "Invoke a registered skill from the current skill listing. BLOCKING REQUIREMENT: when a skill from the listing matches the user's request, you MUST call this tool (not free-form text). Do NOT call the same skill repeatedly inside one turn — recursive depth is capped at {{ MAX_SKILL_QUERY_DEPTH }}.\n\n## Currently model-invocable skills\n{{ AVAILABLE_SKILLS }}\nThis list is a construction-time snapshot; for the live catalog inspect the skill registry.";
|
|
64658
|
+
/** Max skills to list inline in the tool description; rest are summarized. */
|
|
64659
|
+
const MAX_INLINE_SKILLS = 15;
|
|
64660
|
+
/** Max description length per skill line. */
|
|
64661
|
+
const MAX_SKILL_DESC_CHARS = 100;
|
|
64662
|
+
function buildSkillToolDescription(agent) {
|
|
64663
|
+
const skills = agent.skills?.registry.listInvocableSkills() ?? [];
|
|
64664
|
+
const lines = skills.slice(0, MAX_INLINE_SKILLS).map((s) => {
|
|
64665
|
+
const desc = s.description.trim().replaceAll(/\n/g, " ").slice(0, MAX_SKILL_DESC_CHARS);
|
|
64666
|
+
return `- ${s.name}: ${desc}`;
|
|
64667
|
+
});
|
|
64668
|
+
if (skills.length > MAX_INLINE_SKILLS) lines.push(`…${String(skills.length - MAX_INLINE_SKILLS)} more (see skill registry)`);
|
|
64669
|
+
return renderPrompt(skill_tool_default, {
|
|
64670
|
+
MAX_SKILL_QUERY_DEPTH: 3,
|
|
64671
|
+
AVAILABLE_SKILLS: lines.length > 0 ? lines.join("\n") : "(none currently registered)"
|
|
64672
|
+
});
|
|
64673
|
+
}
|
|
64658
64674
|
var NestedSkillTooDeepError = class extends Error {
|
|
64659
64675
|
skillName;
|
|
64660
64676
|
depth;
|
|
@@ -64674,11 +64690,12 @@ var SkillTool = class SkillTool {
|
|
|
64674
64690
|
agent;
|
|
64675
64691
|
options;
|
|
64676
64692
|
name = "Skill";
|
|
64677
|
-
description
|
|
64693
|
+
description;
|
|
64678
64694
|
parameters = toInputJsonSchema(SkillToolInputSchema);
|
|
64679
64695
|
constructor(agent, options = {}) {
|
|
64680
64696
|
this.agent = agent;
|
|
64681
64697
|
this.options = options;
|
|
64698
|
+
this.description = buildSkillToolDescription(agent);
|
|
64682
64699
|
}
|
|
64683
64700
|
resolveExecution(args) {
|
|
64684
64701
|
return {
|
|
@@ -76706,10 +76723,10 @@ function stripContextMetadata(message) {
|
|
|
76706
76723
|
}
|
|
76707
76724
|
//#endregion
|
|
76708
76725
|
//#region ../../packages/agent-core/src/agent/compaction/compaction-instruction.md
|
|
76709
|
-
var compaction_instruction_default = "\n--- This message is a direct task, not part of the above conversation ---\n\nYou are now given a task to compact this conversation context according to specific priorities and output requirements.\n\nOutput text only. DO NOT CALL ANY TOOLS. Calling tools will be rejected and fails the task. You already have all the information you need in the conversation history. You have only one chance.\n\nThe goal of compaction is to keep essential code patterns, technical details, and architectural decisions for continuing development without losing context after the above messages are cleared work.\n\n{{ customInstruction }}\n\n<!-- Memory Memo Extraction (PRIORITY — do not skip) -->\n\n## 任务经验提取\n\nAFTER completing the compaction summary below, scan the messages being compacted for **task loops**. A task loop is \"completed\" when:\n- The user made a clear request or asked a specific question\n- You provided a solution or answer\n- The outcome is clear (success, partial success, or failure)\n\n**You MUST output at least one memory-memo block** (or the `{\"none\": true}` marker)
|
|
76726
|
+
var compaction_instruction_default = "\n--- This message is a direct task, not part of the above conversation ---\n\nYou are now given a task to compact this conversation context according to specific priorities and output requirements.\n\nOutput text only. DO NOT CALL ANY TOOLS. Calling tools will be rejected and fails the task. You already have all the information you need in the conversation history. You have only one chance.\n\nThe goal of compaction is to keep essential code patterns, technical details, and architectural decisions for continuing development without losing context after the above messages are cleared work.\n\n{{ customInstruction }}\n\n<!-- Memory Memo Extraction (PRIORITY — do not skip) -->\n\n## 任务经验提取\n\nAFTER completing the compaction summary below, scan the messages being compacted for **task loops**. A task loop is \"completed\" when:\n- The user made a clear request or asked a specific question\n- You provided a solution or answer\n- The outcome is clear (success, partial success, or failure)\n\n**You MUST output at least one memory-memo block** (or the `{\"none\": true}` marker) after the summary — omitting the section entirely is not allowed. Record completed task loops as full experience records; record **in-progress work** as a lower-priority record whose \"outcome\" is \"进行中\" (so the ongoing task survives compaction and can be resumed later).\n\nFor each task loop found, output a structured experience record after the summary (the skill-candidate marker line described below comes after all memory-memo blocks):\n\n```memory-memo\n{\n \"userNeed\": \"<the user's need or goal, one sentence>\",\n \"approach\": \"<what was done — the approach taken, 2-4 sentences>\",\n \"outcome\": \"<final result, e.g. '完成', '部分完成', '失败: reason', or '进行中' for in-progress work>\",\n \"whatFailed\": \"<dead ends tried — things that didn't work, or 'none'>\",\n \"whatWorked\": \"<key actions that ultimately worked, or 'none'>\",\n \"tags\": [\"<tag1>\", \"<tag2>\", \"<tag3>\"],\n \"note\": \"<optional: a soft, AI-readable note/suggestion that makes the record easier for future turns to understand — e.g. '这类任务先查接口可用性再写代码'. Omit if none>\"\n}\n```\n\nGuidelines:\n- Record important failed attempts in \"whatFailed\" to help avoid repeating mistakes.\n- Record key successful actions in \"whatWorked\" to help reuse effective approaches.\n- Include 3-5 semantic \"tags\" summarizing the task domain, tech stack, or action type (e.g. [\"react\", \"auth\", \"部署\"]).\n- \"note\" is optional: a one-sentence advisory note that helps future AI understand/reuse the record faster. It is a soft suggestion, not a user-enforced rule.\n- For in-progress work: record it with \"outcome\": \"进行中\" and describe where the task stands and what remains — this is what lets the agent resume seamlessly after compaction.\n- Merge closely related sub-tasks into a single record.\n- Use the exact field names and JSON format shown above (no extra fields beyond \"note\").\n\nIf no task loops (completed or in-progress) are found in the compacted messages, output:\n```memory-memo\n{\"none\": true}\n```\n\n<!-- Compression Priorities (in order) -->\n\n1. **Current Task State**: What is being worked on RIGHT NOW\n2. **Errors & Solutions**: All encountered errors and their resolutions\n3. **Code Evolution**: Final working versions only (remove intermediate attempts)\n4. **System Context**: Project structure, dependencies, environment setup\n5. **Design Decisions**: Architectural choices and their rationale\n6. **Next Steps**: The ordered, actionable plan going forward\n7. **TODO Items**: Unfinished tasks and known issues\n\n<!-- Required Output Structure -->\n\n## Current Focus\n\n[What we're working on now]\n\n## Environment\n\n- [Key setup/config points]\n- ...\n\n## Completed Tasks\n\n- [Task]: [Brief outcome]\n- ...\n\n## Active Issues\n\n- [Issue]: [Status/Next steps]\n- ...\n\n## Key Decisions\n\n- [Decision]: [rationale] — preserve architectural choices and why they were made\n- ...\n\n## Next Steps\n\n1. [The very next actionable step]\n2. [Then this]\n3. ...\n\n## Code State\n\n### [Critical file name]\n\n[Brief description of the file's purpose and current state]\n\n```\n[The latest version of critical code snippets in this file, <20 lines]\n```\n\n### [Critical file name]\n\n- [Useful classes/methods/functions]: [Brief description/usage]\n- ...\n\n<!-- Omit non-critical code, intermediate attempts, and resolved errors -->\n\n## Important Context\n\n- [Any crucial information not covered above]\n- ...\n\n## All User Messages\n\n- [Detailed non tool use user message]\n- ...\n\n## Skill candidates\n\nScan the compressed messages for reusable processes (project-specific build\nsteps, recurring debugging patterns, or tool workflows). Then output exactly\none marker as the very LAST line of your response — after all memory-memo\nblocks:\n\n- If a process is genuinely worth capturing as a reusable skill (reusable\n beyond this one task — do not emit for one-off actions; the evidence must\n be concrete and verifiable: exact file paths, commands, or step sequences\n from the conversation, e.g. \"run `pnpm vitest run -t compaction` in\n packages/agent-core to reproduce the compaction snapshots\". Vague evidence\n like \"used a script\" is not acceptable):\n\n[[skill-candidate: <name>|<one-line purpose>|<evidence>]]\n\n- If none exists, output instead:\n\n[[skill-candidate: none]]\n\nThis marker line is MANDATORY — never omit it, and output at most one\ncandidate marker.\n";
|
|
76710
76727
|
//#endregion
|
|
76711
76728
|
//#region ../../packages/agent-core/src/agent/compaction/compaction-update-instruction.md
|
|
76712
|
-
var compaction_update_instruction_default = "\n--- This message is a direct task, not part of the above conversation ---\n\nYou are now given a task to UPDATE an existing compaction summary with new messages that came in after the last compaction.\n\nA previous compaction summary already exists at the top of the conversation (the first assistant message). You must NOT discard it. Instead, merge the new information into the existing structure, keeping all previously captured state intact unless explicitly contradicted or resolved by the new messages.\n\nOutput text only. DO NOT CALL ANY TOOLS. Calling tools will be rejected and fails the task. You have only one chance.\n\n{{ customInstruction }}\n\n<!-- Previous Summary Reference -->\n\nThe first assistant message above is the PREVIOUS summary. Treat it as the source of truth for everything that happened before the new messages. Do not restate it verbatim — produce an updated, merged summary.\n\n<!-- Memory Memo Extraction (PRIORITY — do not skip) -->\n\n## 任务经验提取\n\nAFTER completing the updated summary below, scan ONLY the new messages being compacted (not those already covered by the previous summary) for **task loops**. A task loop is \"completed\" when:\n- The user made a clear request or asked a specific question\n- You provided a solution or answer\n- The outcome is clear (success, partial success, or failure)\n\n**You MUST output at least one memory-memo block** (or the `{\"none\": true}` marker)
|
|
76729
|
+
var compaction_update_instruction_default = "\n--- This message is a direct task, not part of the above conversation ---\n\nYou are now given a task to UPDATE an existing compaction summary with new messages that came in after the last compaction.\n\nA previous compaction summary already exists at the top of the conversation (the first assistant message). You must NOT discard it. Instead, merge the new information into the existing structure, keeping all previously captured state intact unless explicitly contradicted or resolved by the new messages.\n\nOutput text only. DO NOT CALL ANY TOOLS. Calling tools will be rejected and fails the task. You have only one chance.\n\n{{ customInstruction }}\n\n<!-- Previous Summary Reference -->\n\nThe first assistant message above is the PREVIOUS summary. Treat it as the source of truth for everything that happened before the new messages. Do not restate it verbatim — produce an updated, merged summary.\n\n<!-- Memory Memo Extraction (PRIORITY — do not skip) -->\n\n## 任务经验提取\n\nAFTER completing the updated summary below, scan ONLY the new messages being compacted (not those already covered by the previous summary) for **task loops**. A task loop is \"completed\" when:\n- The user made a clear request or asked a specific question\n- You provided a solution or answer\n- The outcome is clear (success, partial success, or failure)\n\n**You MUST output at least one memory-memo block** (or the `{\"none\": true}` marker) after the updated summary — omitting the section entirely is not allowed. Record completed task loops as full experience records; record **in-progress work** as a lower-priority record whose \"outcome\" is \"进行中\" (so the ongoing task survives compaction and can be resumed later).\n\nFor each task loop found, output a structured experience record after the updated summary (the skill-candidate marker line described below comes after all memory-memo blocks):\n\n```memory-memo\n{\n \"userNeed\": \"<the user's need or goal, one sentence>\",\n \"approach\": \"<what was done — the approach taken, 2-4 sentences>\",\n \"outcome\": \"<final result, e.g. '完成', '部分完成', '失败: reason', or '进行中' for in-progress work>\",\n \"whatFailed\": \"<dead ends tried — things that didn't work, or 'none'>\",\n \"whatWorked\": \"<key actions that ultimately worked, or 'none'>\",\n \"tags\": [\"<tag1>\", \"<tag2>\", \"<tag3>\"],\n \"note\": \"<optional: a soft, AI-readable note/suggestion that makes the record easier for future turns to understand — e.g. '这类任务先查接口可用性再写代码'. Omit if none>\"\n}\n```\n\nGuidelines:\n- Record important failed attempts in \"whatFailed\" to help avoid repeating mistakes.\n- Record key successful actions in \"whatWorked\" to help reuse effective approaches.\n- Include 3-5 semantic \"tags\" summarizing the task domain, tech stack, or action type.\n- For in-progress work: record it with \"outcome\": \"进行中\" and describe where the task stands and what remains — this is what lets the agent resume seamlessly after compaction.\n- Merge closely related sub-tasks into a single record.\n- Use the exact field names and JSON format shown above.\n\nIf no task loops (completed or in-progress) are found in the new compacted messages, output:\n```memory-memo\n{\"none\": true}\n```\n\n<!-- Skill Candidate Detection (after memory-memo) -->\n\n## Skill candidates\n\nAFTER the memory-memo block(s), scan ONLY the new messages being compacted\n(not the content already covered by the previous summary — candidates from\nolder messages were already considered) for reusable processes\n(project-specific build steps, recurring debugging patterns, or tool\nworkflows). Then output exactly one marker as the very LAST line of your\nresponse — after all memory-memo blocks:\n\n- If a process is genuinely worth capturing as a reusable skill (reusable\n beyond this one task — do not emit for one-off actions; the evidence must\n be concrete and verifiable: exact file paths, commands, or step sequences\n from the new messages):\n\n[[skill-candidate: <name>|<one-line purpose>|<evidence>]]\n\n- If none exists, output instead:\n\n[[skill-candidate: none]]\n\nThis marker line is MANDATORY — never omit it, and output at most one\ncandidate marker.\n\n<!-- Update Rules -->\n\n1. Preserve the section structure of the previous summary (Current Focus, Environment, Completed Tasks, Active Issues, Key Decisions, Next Steps, Code State, Important Context, All User Messages).\n2. Move newly-completed tasks from \"Current Focus\" / \"Active Issues\" into \"Completed Tasks\".\n3. Update \"Current Focus\" to reflect what is being worked on RIGHT NOW.\n4. Append new user messages to \"All User Messages\" — do not repeat those already captured.\n5. Refresh \"Code State\" code snippets only if newer versions exist in the new messages.\n6. Drop resolved issues from \"Active Issues\"; add newly-discovered ones.\n7. Merge new decisions into \"Key Decisions\" (keep prior decisions unless explicitly overturned); merge new steps into \"Next Steps\" (reorder if priorities changed).\n8. Do not invent new information. If the new messages say nothing about a section, carry the previous content forward unchanged.\n\n<!-- Required Output Structure -->\n\n## Current Focus\n\n[What we're working on now]\n\n## Environment\n\n- [Key setup/config points]\n- ...\n\n## Completed Tasks\n\n- [Task]: [Brief outcome]\n- ...\n\n## Active Issues\n\n- [Issue]: [Status/Next steps]\n- ...\n\n## Key Decisions\n\n- [Decision]: [rationale] — preserve architectural choices and why they were made\n- ...\n\n## Next Steps\n\n1. [The very next actionable step]\n2. [Then this]\n3. ...\n\n## Code State\n\n### [Critical file name]\n\n[Brief description of the file's purpose and current state]\n\n```\n[The latest version of critical code snippets in this file, <20 lines]\n```\n\n## Important Context\n\n- [Any crucial information not covered above]\n- ...\n\n## All User Messages\n\n- [Detailed non tool use user message]\n- ...\n";
|
|
76713
76730
|
//#endregion
|
|
76714
76731
|
//#region ../../packages/agent-core/src/agent/compaction/render-messages.ts
|
|
76715
76732
|
const TOOL_RESULT_MAX_CHARS = 2e3;
|
|
@@ -77157,7 +77174,7 @@ var FullCompaction = class {
|
|
|
77157
77174
|
blockedByTurn: false
|
|
77158
77175
|
};
|
|
77159
77176
|
this.compacting = active;
|
|
77160
|
-
active.promise = this.compactionWorker(abortController.signal, data, compactedCount);
|
|
77177
|
+
active.promise = this.compactionWorker(abortController.signal, data, compactedCount, active);
|
|
77161
77178
|
}
|
|
77162
77179
|
cancel() {
|
|
77163
77180
|
this.markCanceled();
|
|
@@ -77186,6 +77203,13 @@ var FullCompaction = class {
|
|
|
77186
77203
|
this.lowWaterMark = 0;
|
|
77187
77204
|
this.reactiveAttempted = false;
|
|
77188
77205
|
}
|
|
77206
|
+
/** The low-water mark is measured against the model's context window, so a
|
|
77207
|
+
* model switch (different max_context_tokens) invalidates it. Without a
|
|
77208
|
+
* reset, a stale mark from a large model can mask the overflow threshold
|
|
77209
|
+
* of a smaller model and suppress compaction until the provider overflows. */
|
|
77210
|
+
resetLowWaterMark() {
|
|
77211
|
+
this.lowWaterMark = 0;
|
|
77212
|
+
}
|
|
77189
77213
|
async handleOverflowError(signal, error) {
|
|
77190
77214
|
if (this.reactiveAttempted) throw error;
|
|
77191
77215
|
if (!this.beginAutoCompaction(false) && !this.compacting) {
|
|
@@ -77197,6 +77221,12 @@ var FullCompaction = class {
|
|
|
77197
77221
|
throw error;
|
|
77198
77222
|
}
|
|
77199
77223
|
this.reactiveAttempted = true;
|
|
77224
|
+
if (this.compacting) try {
|
|
77225
|
+
await this.block(signal);
|
|
77226
|
+
} catch (blockError) {
|
|
77227
|
+
if (signal.aborted || isAbortError$1(blockError)) throw blockError;
|
|
77228
|
+
throw error;
|
|
77229
|
+
}
|
|
77200
77230
|
}
|
|
77201
77231
|
async beforeStep(signal) {
|
|
77202
77232
|
this.agent.microCompaction.detect();
|
|
@@ -77246,13 +77276,14 @@ var FullCompaction = class {
|
|
|
77246
77276
|
async block(signal) {
|
|
77247
77277
|
const active = this.compacting;
|
|
77248
77278
|
if (!active) return;
|
|
77279
|
+
signal.throwIfAborted();
|
|
77249
77280
|
active.blockedByTurn = true;
|
|
77250
77281
|
const timeoutId = setTimeout(() => {
|
|
77251
77282
|
if (this.compacting === active) {
|
|
77252
77283
|
this.compactionTimedOut = true;
|
|
77253
|
-
this.markCanceled("压缩超时(
|
|
77284
|
+
this.markCanceled("压缩超时(120秒),已取消。请使用 /compact 手动重试。");
|
|
77254
77285
|
}
|
|
77255
|
-
},
|
|
77286
|
+
}, 12e4);
|
|
77256
77287
|
const onAbort = () => {
|
|
77257
77288
|
clearTimeout(timeoutId);
|
|
77258
77289
|
if (this.compacting === active) this.cancel();
|
|
@@ -77269,7 +77300,7 @@ var FullCompaction = class {
|
|
|
77269
77300
|
signal.removeEventListener("abort", onAbort);
|
|
77270
77301
|
}
|
|
77271
77302
|
}
|
|
77272
|
-
async compactionWorker(signal, data, compactedCount) {
|
|
77303
|
+
async compactionWorker(signal, data, compactedCount, owner) {
|
|
77273
77304
|
const originalHistory = [...this.agent.context.history];
|
|
77274
77305
|
const systemPromptTokens = estimateTokens$1(this.agent.getRuntimeSystemPrompt());
|
|
77275
77306
|
const toolTokens = estimateTokensForTools(this.agent.tools.loopTools);
|
|
@@ -77309,24 +77340,27 @@ var FullCompaction = class {
|
|
|
77309
77340
|
} catch (error) {
|
|
77310
77341
|
if (error instanceof APIContextOverflowError || error instanceof TruncatedError) {
|
|
77311
77342
|
const reduced = this.strategy.reduceCompactOnOverflow(messagesToCompact);
|
|
77312
|
-
if (reduced < compactedCount)
|
|
77313
|
-
|
|
77314
|
-
|
|
77315
|
-
compactedCount,
|
|
77316
|
-
tokensBefore: estimateTokensForMessages(messagesToCompact)
|
|
77317
|
-
});
|
|
77318
|
-
const result = await summarizeWithFallback(messagesToCompact, summarizeOnce);
|
|
77319
|
-
summary = result.summary;
|
|
77320
|
-
usage = result.usage;
|
|
77321
|
-
break;
|
|
77343
|
+
if (reduced < compactedCount) {
|
|
77344
|
+
compactedCount = reduced;
|
|
77345
|
+
continue;
|
|
77322
77346
|
}
|
|
77323
|
-
|
|
77347
|
+
this.agent.log.warn("compaction overflow at minimum split, falling back to re-summarize", {
|
|
77348
|
+
compactedCount,
|
|
77349
|
+
tokensBefore: estimateTokensForMessages(messagesToCompact)
|
|
77350
|
+
});
|
|
77351
|
+
const result = await summarizeWithFallback(messagesToCompact, summarizeOnce);
|
|
77352
|
+
summary = result.summary;
|
|
77353
|
+
usage = result.usage;
|
|
77354
|
+
break;
|
|
77355
|
+
}
|
|
77356
|
+
if (!isRetryableGenerateError(error)) throw error;
|
|
77324
77357
|
if (retryCount + 1 >= 5) throw error;
|
|
77325
|
-
await sleepForRetry(delays
|
|
77358
|
+
await sleepForRetry(computeDelayMs(error, delays, retryCount + 1), signal);
|
|
77326
77359
|
retryCount += 1;
|
|
77327
77360
|
}
|
|
77328
77361
|
}
|
|
77329
77362
|
if (usage !== null) this.agent.usage.record(model, usage);
|
|
77363
|
+
if (this.compacting !== owner) return void 0;
|
|
77330
77364
|
const newHistory = this.agent.context.history;
|
|
77331
77365
|
for (let i = 0; i < originalHistory.length; i++) if (newHistory[i] !== originalHistory[i]) {
|
|
77332
77366
|
this.markCanceled("上下文已被更改(如 /revoke),压缩已取消");
|
|
@@ -77341,6 +77375,7 @@ var FullCompaction = class {
|
|
|
77341
77375
|
} else this.lastCompactionFiles = void 0;
|
|
77342
77376
|
for (const msg of messagesToCompactForOps) extractFileOpsFromMessage(msg, fileOps);
|
|
77343
77377
|
const toolCallHistory = formatToolCallHistory(messagesToCompactForOps);
|
|
77378
|
+
const skillCandidateSummary = summary;
|
|
77344
77379
|
const processedSummary = this.postProcessSummary(summary, fileOps, toolCallHistory, compactedCount);
|
|
77345
77380
|
const tokensAfter = systemPromptTokens + toolTokens + estimateTokens$1(processedSummary) + estimateTokensForMessages(recent);
|
|
77346
77381
|
const fileLists = computeFileLists(fileOps);
|
|
@@ -77366,20 +77401,23 @@ var FullCompaction = class {
|
|
|
77366
77401
|
this.lowWaterMark = Math.floor(this.effectiveTokenCount * 1.1);
|
|
77367
77402
|
await this.extractAndStoreMemos(processedSummary, messagesToCompactForOps);
|
|
77368
77403
|
this.triggerPostCompactHook(data, result);
|
|
77369
|
-
this.detectSkillCandidates(
|
|
77404
|
+
this.detectSkillCandidates(skillCandidateSummary);
|
|
77370
77405
|
this.consecutiveCompactionFailures = 0;
|
|
77371
77406
|
this._shouldInjectSessionSummary = true;
|
|
77372
77407
|
} catch (error) {
|
|
77373
|
-
const
|
|
77374
|
-
|
|
77408
|
+
const stale = this.compacting !== null && this.compacting !== owner;
|
|
77409
|
+
const wasTimedOut = stale ? false : this.compactionTimedOut;
|
|
77410
|
+
if (!stale) this.compactionTimedOut = false;
|
|
77375
77411
|
if (!isAbortError$1(error) || wasTimedOut) {
|
|
77376
|
-
const blockedByTurn =
|
|
77377
|
-
|
|
77378
|
-
|
|
77379
|
-
|
|
77380
|
-
|
|
77381
|
-
|
|
77382
|
-
|
|
77412
|
+
const blockedByTurn = stale || owner.blockedByTurn === true;
|
|
77413
|
+
if (!stale) {
|
|
77414
|
+
this.consecutiveCompactionFailures += 1;
|
|
77415
|
+
if (this.consecutiveCompactionFailures >= MAX_CONSECUTIVE_FAILURES) this.agent.emitEvent({
|
|
77416
|
+
type: "warning",
|
|
77417
|
+
message: `压缩连续失败 ${String(this.consecutiveCompactionFailures)} 次,已自动暂停本回合的自动压缩。使用 /compact 手动重试。`,
|
|
77418
|
+
code: "compaction_circuit_open"
|
|
77419
|
+
});
|
|
77420
|
+
}
|
|
77383
77421
|
this.agent.log.error("compaction failed", {
|
|
77384
77422
|
code: isScreamError(error) ? error.code : void 0,
|
|
77385
77423
|
error,
|
|
@@ -77388,7 +77426,7 @@ var FullCompaction = class {
|
|
|
77388
77426
|
compactedCount,
|
|
77389
77427
|
tokensBefore
|
|
77390
77428
|
});
|
|
77391
|
-
this.markCanceled();
|
|
77429
|
+
if (!stale) this.markCanceled();
|
|
77392
77430
|
if (!blockedByTurn) {
|
|
77393
77431
|
const details = {
|
|
77394
77432
|
model,
|
|
@@ -77400,7 +77438,7 @@ var FullCompaction = class {
|
|
|
77400
77438
|
...payload
|
|
77401
77439
|
});
|
|
77402
77440
|
}
|
|
77403
|
-
if (blockedByTurn) {
|
|
77441
|
+
if (blockedByTurn && !stale) {
|
|
77404
77442
|
if (isScreamError(error) && error.code === ErrorCodes.AUTH_LOGIN_REQUIRED) throw error;
|
|
77405
77443
|
throw new ScreamError(ErrorCodes.COMPACTION_FAILED, String(error), { cause: error });
|
|
77406
77444
|
}
|
|
@@ -77491,27 +77529,41 @@ var FullCompaction = class {
|
|
|
77491
77529
|
}
|
|
77492
77530
|
/**
|
|
77493
77531
|
* Detects [[skill-candidate: <name>|<purpose>|<evidence>]] markers in the
|
|
77494
|
-
* compaction summary and emits a `skill_candidate` event
|
|
77495
|
-
*
|
|
77496
|
-
*
|
|
77497
|
-
*
|
|
77532
|
+
* compaction summary and emits a `skill_candidate` event (at most one per
|
|
77533
|
+
* compact). Best-effort and fully isolated: a parse failure or a missing
|
|
77534
|
+
* marker never affects compaction or memory extraction — this method only
|
|
77535
|
+
* reads the summary and emits an event.
|
|
77536
|
+
*
|
|
77537
|
+
* Tolerant parsing: the evidence segment may contain `|` characters and
|
|
77538
|
+
* newlines, and the explicit `[[skill-candidate: none]]` marker (emitted
|
|
77539
|
+
* when the model found nothing) is recognized and skipped. When several
|
|
77540
|
+
* markers appear (e.g. an old one carried over into an update summary),
|
|
77541
|
+
* the LAST valid candidate wins — the templates mandate the marker as the
|
|
77542
|
+
* final line of the response, so the trailing one is the model's verdict
|
|
77543
|
+
* for this round.
|
|
77498
77544
|
*/
|
|
77499
77545
|
detectSkillCandidates(summary) {
|
|
77500
77546
|
try {
|
|
77501
|
-
const matches = summary.matchAll(/\[\[skill-candidate:\s*([^|\]]
|
|
77547
|
+
const matches = summary.matchAll(/\[\[skill-candidate:\s*([^|\]]+?)(?:\|([^|\]]*)\|([\s\S]*?))?\]\]/g);
|
|
77548
|
+
let chosen;
|
|
77502
77549
|
for (const m of matches) {
|
|
77503
|
-
const name = m[1]
|
|
77550
|
+
const name = m[1]?.trim() ?? "";
|
|
77504
77551
|
if (name.length === 0) continue;
|
|
77505
|
-
|
|
77506
|
-
|
|
77507
|
-
|
|
77508
|
-
|
|
77509
|
-
|
|
77510
|
-
|
|
77511
|
-
|
|
77512
|
-
|
|
77513
|
-
|
|
77552
|
+
if (name.toLowerCase() === "none") {
|
|
77553
|
+
chosen = void 0;
|
|
77554
|
+
continue;
|
|
77555
|
+
}
|
|
77556
|
+
if (m[2] === void 0) continue;
|
|
77557
|
+
chosen = {
|
|
77558
|
+
name,
|
|
77559
|
+
purpose: m[2].trim(),
|
|
77560
|
+
evidence: (m[3] ?? "").trim()
|
|
77561
|
+
};
|
|
77514
77562
|
}
|
|
77563
|
+
if (chosen !== void 0) this.agent.emitEvent({
|
|
77564
|
+
type: "skill_candidate",
|
|
77565
|
+
candidate: chosen
|
|
77566
|
+
});
|
|
77515
77567
|
} catch (error) {
|
|
77516
77568
|
this.agent.log.warn("Skill candidate detection failed", { error: String(error) });
|
|
77517
77569
|
}
|
|
@@ -77529,7 +77581,7 @@ var FullCompaction = class {
|
|
|
77529
77581
|
*/
|
|
77530
77582
|
postProcessSummary(summary, fileOps, toolCallHistory, compactedCount) {
|
|
77531
77583
|
const todos = this.agent.tools.storeData()["todo"] ?? [];
|
|
77532
|
-
const base = summary.trim().replaceAll(/<files>[\s\S]*?<\/files>\s*/g, "").replace(/^> The conversation before this point was compacted:[\s\S]*?continue from here\.\s*\n+/m, "").trimEnd();
|
|
77584
|
+
const base = summary.trim().replaceAll(/<files>[\s\S]*?<\/files>\s*/g, "").replaceAll(/\[\[skill-candidate:[\s\S]*?\]\]\s*/g, "").replace(/^> The conversation before this point was compacted:[\s\S]*?continue from here\.\s*\n+/m, "").trimEnd();
|
|
77533
77585
|
const sections = [];
|
|
77534
77586
|
if (compactedCount > 0) sections.push(`> The conversation before this point was compacted: ${String(compactedCount)} earlier message(s) were omitted and are covered by this summary. Treat the summary below as working notes, not verbatim history — the messages after it continue from here.`);
|
|
77535
77587
|
if (base.length > 0) sections.push(base);
|
|
@@ -78855,7 +78907,10 @@ var ConfigState = class {
|
|
|
78855
78907
|
this._cwd = changed.cwd;
|
|
78856
78908
|
this.agent.jian.chdir(changed.cwd);
|
|
78857
78909
|
}
|
|
78858
|
-
if (changed.modelAlias
|
|
78910
|
+
if (changed.modelAlias && changed.modelAlias !== this._modelAlias) {
|
|
78911
|
+
this._modelAlias = changed.modelAlias;
|
|
78912
|
+
this.agent.fullCompaction.resetLowWaterMark();
|
|
78913
|
+
}
|
|
78859
78914
|
if (changed.profileName) this._profileName = changed.profileName;
|
|
78860
78915
|
if (changed.thinkingLevel !== void 0) this._thinkingLevel = resolveThinkingEffort(changed.thinkingLevel, this.agent.screamConfig?.thinking);
|
|
78861
78916
|
if (changed.systemPrompt !== void 0) this._systemPrompt = changed.systemPrompt;
|
|
@@ -131524,16 +131579,16 @@ const renderTruncated = (_toolCall, result, ctx) => {
|
|
|
131524
131579
|
var ShellExecutionComponent = class extends Container {
|
|
131525
131580
|
constructor(options) {
|
|
131526
131581
|
super();
|
|
131527
|
-
if (options.showCommand === true) this.addCommandPreview(options.command ?? "", options.commandPreviewLines);
|
|
131582
|
+
if (options.showCommand === true) this.addCommandPreview(options.command ?? "", options.commandPreviewLines, options.colors);
|
|
131528
131583
|
if (options.result !== void 0) this.addResultPreview(options.result, options.colors, options.expanded ?? false, options.resultPreviewLines ?? 15);
|
|
131529
131584
|
}
|
|
131530
|
-
addCommandPreview(command, previewLines) {
|
|
131585
|
+
addCommandPreview(command, previewLines, colors) {
|
|
131531
131586
|
if (command.length === 0) return;
|
|
131532
|
-
const allLines = command
|
|
131587
|
+
const allLines = highlightLines(command, "bash", colors);
|
|
131533
131588
|
const lines = previewLines === void 0 ? allLines : allLines.slice(0, previewLines);
|
|
131534
131589
|
for (const [i, line] of lines.entries()) {
|
|
131535
131590
|
const prefix = i === 0 ? "$ " : " ";
|
|
131536
|
-
this.addChild(new Text(chalk.dim(prefix
|
|
131591
|
+
this.addChild(new Text(`${chalk.dim(prefix)}${line}`, 2, 0));
|
|
131537
131592
|
}
|
|
131538
131593
|
}
|
|
131539
131594
|
addResultPreview(result, colors, expanded, previewLines) {
|
|
@@ -131554,8 +131609,8 @@ const shellExecutionResultRenderer = (toolCall, result, ctx) => [new ShellExecut
|
|
|
131554
131609
|
result,
|
|
131555
131610
|
colors: ctx.colors,
|
|
131556
131611
|
expanded: ctx.expanded,
|
|
131557
|
-
showCommand:
|
|
131558
|
-
commandPreviewLines: void 0
|
|
131612
|
+
showCommand: true,
|
|
131613
|
+
commandPreviewLines: ctx.expanded ? void 0 : 3
|
|
131559
131614
|
})];
|
|
131560
131615
|
//#endregion
|
|
131561
131616
|
//#region src/tui/components/media/image-thumbnail.ts
|
|
@@ -131834,6 +131889,26 @@ function pickChip(toolName) {
|
|
|
131834
131889
|
return REGISTRY[toolName];
|
|
131835
131890
|
}
|
|
131836
131891
|
//#endregion
|
|
131892
|
+
//#region src/tui/components/messages/tool-renderers/glance-lines.ts
|
|
131893
|
+
/**
|
|
131894
|
+
* Renders pre-composed glance lines (ANSI-colored) with hard per-line
|
|
131895
|
+
* truncation to the actual render width. Unlike `Text`, long lines never
|
|
131896
|
+
* wrap — each logical line always occupies exactly one visual row, so
|
|
131897
|
+
* column-aligned samples (Grep matches) never break their alignment on
|
|
131898
|
+
* narrow terminals.
|
|
131899
|
+
*/
|
|
131900
|
+
var GlanceLinesComponent = class {
|
|
131901
|
+
lines;
|
|
131902
|
+
constructor(lines) {
|
|
131903
|
+
this.lines = lines;
|
|
131904
|
+
}
|
|
131905
|
+
invalidate() {}
|
|
131906
|
+
render(width) {
|
|
131907
|
+
const safeWidth = Math.max(width, 1);
|
|
131908
|
+
return this.lines.map((line) => truncateToWidth(` ${line}`, safeWidth, "…"));
|
|
131909
|
+
}
|
|
131910
|
+
};
|
|
131911
|
+
//#endregion
|
|
131837
131912
|
//#region src/tui/components/messages/tool-renderers/summary.ts
|
|
131838
131913
|
const GLANCE_SAMPLES = 3;
|
|
131839
131914
|
const MAX_EXTENSION_COUNTS = 4;
|
|
@@ -131843,11 +131918,13 @@ function withGlance(glance) {
|
|
|
131843
131918
|
if (result.is_error) return renderTruncated(toolCall, result, ctx);
|
|
131844
131919
|
const out = [];
|
|
131845
131920
|
if (glance !== null) {
|
|
131846
|
-
const
|
|
131847
|
-
if (
|
|
131848
|
-
|
|
131849
|
-
|
|
131850
|
-
|
|
131921
|
+
const glanceOut = glance(toolCall, result, ctx.colors);
|
|
131922
|
+
if (typeof glanceOut === "string") {
|
|
131923
|
+
if (glanceOut.length > 0) {
|
|
131924
|
+
const indented = glanceOut.split("\n").map((l) => ` ${l}`).join("\n");
|
|
131925
|
+
out.push(new Text(indented, 0, 0));
|
|
131926
|
+
}
|
|
131927
|
+
} else out.push(glanceOut);
|
|
131851
131928
|
}
|
|
131852
131929
|
if (ctx.expanded && result.output.length > 0) out.push(new Text(chalk.dim(result.output), 4, 0));
|
|
131853
131930
|
return out;
|
|
@@ -131870,29 +131947,35 @@ function readSearchResultsMatches(result) {
|
|
|
131870
131947
|
if (display.kind !== "search_results") return void 0;
|
|
131871
131948
|
return display.matches;
|
|
131872
131949
|
}
|
|
131873
|
-
function
|
|
131874
|
-
|
|
131875
|
-
|
|
131950
|
+
function styleFilePath(path) {
|
|
131951
|
+
const idx = path.lastIndexOf("/");
|
|
131952
|
+
if (idx < 0) return path;
|
|
131953
|
+
return `${chalk.dim(path.slice(0, idx + 1))}${path.slice(idx + 1)}`;
|
|
131876
131954
|
}
|
|
131877
131955
|
const grepGlance = (_toolCall, result, colors) => {
|
|
131878
131956
|
const matches = readSearchResultsMatches(result);
|
|
131879
131957
|
if (matches !== void 0 && matches.length > 0) {
|
|
131880
|
-
const
|
|
131881
|
-
const
|
|
131882
|
-
|
|
131958
|
+
const samples = matches.slice(0, GLANCE_SAMPLES);
|
|
131959
|
+
const plainLocs = samples.map((m) => m.line > 0 ? `${m.file}:${String(m.line)}` : m.file);
|
|
131960
|
+
const colWidth = Math.max(...plainLocs.map((s) => visibleWidth(s)));
|
|
131961
|
+
const lineNoColor = chalk.hex(colors.roleTool);
|
|
131962
|
+
const lines = samples.map((m, i) => {
|
|
131963
|
+
const loc = m.line > 0 ? `${styleFilePath(m.file)}${chalk.dim(":")}${lineNoColor(String(m.line))}` : styleFilePath(m.file);
|
|
131964
|
+
const pad = " ".repeat(Math.max(0, colWidth - visibleWidth(plainLocs[i] ?? "")));
|
|
131965
|
+
const text = m.text.trim();
|
|
131966
|
+
return text.length > 0 ? `${loc}${pad} ${chalk.dim(text)}` : `${loc}${pad}`;
|
|
131883
131967
|
});
|
|
131884
131968
|
const remaining = matches.length - GLANCE_SAMPLES;
|
|
131885
131969
|
if (remaining > 0) lines.push(chalk.dim(`+${String(remaining)} more`));
|
|
131886
|
-
return lines
|
|
131970
|
+
return new GlanceLinesComponent(lines);
|
|
131887
131971
|
}
|
|
131888
131972
|
const lines = nonEmptyLines(result.output);
|
|
131889
131973
|
if (lines.length === 0) return "";
|
|
131890
131974
|
const samples = lines.slice(0, GLANCE_SAMPLES).map(pathFromGrepLine);
|
|
131891
131975
|
const remaining = lines.length - samples.length;
|
|
131892
|
-
const
|
|
131893
|
-
const out = samples.map((s) => fileColor(s));
|
|
131976
|
+
const out = samples.map((s) => styleFilePath(s));
|
|
131894
131977
|
if (remaining > 0) out.push(chalk.dim(`+${String(remaining)} more`));
|
|
131895
|
-
return out
|
|
131978
|
+
return new GlanceLinesComponent(out);
|
|
131896
131979
|
};
|
|
131897
131980
|
function fileBasename(path) {
|
|
131898
131981
|
const idx = path.lastIndexOf("/");
|
|
@@ -136202,7 +136285,7 @@ function buildRoleAdditionalText(prefs) {
|
|
|
136202
136285
|
if (items.length === 0 && (doNot === void 0 || doNot.length === 0) && !hasToolPriority) return "";
|
|
136203
136286
|
lines.push("", ...items);
|
|
136204
136287
|
if (doNot !== void 0 && doNot.length > 0) lines.push("", "## Do NOT (explicit prohibitions — NEVER do these)", doNot);
|
|
136205
|
-
if (hasToolPriority) lines.push("", "## Tool priority (set via /like — HIGHEST PRIORITY)", prefs.toolPriority === "skill" ? "For every user request
|
|
136288
|
+
if (hasToolPriority) lines.push("", "## Tool priority (set via /like — HIGHEST PRIORITY)", prefs.toolPriority === "skill" ? "For every user request: (1) first analyze the intent, (2) then identify whether any installed skill matches THIS request, (3) if one matches, invoke the Skill tool with it as your FIRST action — before MCP tools or doing it yourself, (4) if none matches, proceed with MCP tools or solve it yourself. Consult the skill list shown in the Skill tool description whenever you are unsure what is installed." : "For every user request: (1) first analyze the intent, (2) then identify whether any available MCP tool matches THIS request, (3) if one matches, use it as your FIRST action — before the Skill tool or doing it yourself, (4) if none matches, proceed with the Skill tool or solve it yourself.");
|
|
136206
136289
|
lines.push("", t("like.priority"));
|
|
136207
136290
|
return lines.join("\n");
|
|
136208
136291
|
}
|
|
@@ -3,5 +3,5 @@ import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
|
3
3
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
4
4
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = __cjsShimDirname(__filename);
|
|
6
|
-
import { Kt as handleConnectCommand } from "./dispatch-
|
|
6
|
+
import { Kt as handleConnectCommand } from "./dispatch-202xtik3.mjs";
|
|
7
7
|
export { handleConnectCommand };
|
package/dist/main.mjs
CHANGED
|
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
|
|
|
6
6
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
7
7
|
//#region src/main.ts
|
|
8
8
|
try {
|
|
9
|
-
(await import("./app-
|
|
9
|
+
(await import("./app-BXslKpYT.mjs")).main();
|
|
10
10
|
} catch (error) {
|
|
11
11
|
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
12
12
|
process.exit(1);
|