scream-code 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -76030,6 +76030,52 @@ function canSplitAfterContext(messages, index) {
|
|
|
76030
76030
|
/** Max consecutive compaction failures before auto-compaction is
|
|
76031
76031
|
* disabled for the remainder of the turn. Resets each turn. */
|
|
76032
76032
|
const MAX_CONSECUTIVE_FAILURES = 3;
|
|
76033
|
+
/** Truncate tool call arguments to a brief summary for the compaction history. */
|
|
76034
|
+
function truncateArgsForSummary(args) {
|
|
76035
|
+
if (args === null || args === void 0) return "";
|
|
76036
|
+
try {
|
|
76037
|
+
const parsed = JSON.parse(args);
|
|
76038
|
+
if (typeof parsed !== "object" || parsed === null) return "";
|
|
76039
|
+
const entries = Object.entries(parsed);
|
|
76040
|
+
const parts = [];
|
|
76041
|
+
for (const [key, value] of entries) {
|
|
76042
|
+
const valStr = typeof value === "string" ? value.length > 50 ? `"${value.slice(0, 50)}…"` : `"${value}"` : String(value);
|
|
76043
|
+
parts.push(`${key}=${valStr}`);
|
|
76044
|
+
}
|
|
76045
|
+
return parts.slice(0, 3).join(", ");
|
|
76046
|
+
} catch {
|
|
76047
|
+
return args.slice(0, 80);
|
|
76048
|
+
}
|
|
76049
|
+
}
|
|
76050
|
+
/** Extract a brief tool-call history from compacted messages so the model
|
|
76051
|
+
* knows what was already tried after compaction. Prevents repeating
|
|
76052
|
+
* failed approaches. */
|
|
76053
|
+
function formatToolCallHistory(messages) {
|
|
76054
|
+
const resultStatus = /* @__PURE__ */ new Map();
|
|
76055
|
+
for (const msg of messages) if (msg.role === "tool" && msg.toolCallId !== void 0) resultStatus.set(msg.toolCallId, msg.isError === true);
|
|
76056
|
+
const entries = [];
|
|
76057
|
+
for (const msg of messages) {
|
|
76058
|
+
if (msg.role !== "assistant" || msg.toolCalls.length === 0) continue;
|
|
76059
|
+
for (const tc of msg.toolCalls) {
|
|
76060
|
+
const isError = resultStatus.get(tc.id) ?? false;
|
|
76061
|
+
const argsSummary = truncateArgsForSummary(tc.arguments);
|
|
76062
|
+
entries.push({
|
|
76063
|
+
name: tc.name,
|
|
76064
|
+
argsSummary,
|
|
76065
|
+
isError
|
|
76066
|
+
});
|
|
76067
|
+
}
|
|
76068
|
+
}
|
|
76069
|
+
if (entries.length === 0) return "";
|
|
76070
|
+
return [
|
|
76071
|
+
"## Recent Tool Calls",
|
|
76072
|
+
"",
|
|
76073
|
+
...entries.slice(-15).map((e) => {
|
|
76074
|
+
const status = e.isError ? "error" : "success";
|
|
76075
|
+
return `- ${e.name}(${e.argsSummary}) -> ${status}`;
|
|
76076
|
+
})
|
|
76077
|
+
].join("\n");
|
|
76078
|
+
}
|
|
76033
76079
|
/** Minimal system prompt used during compaction. The full agent system
|
|
76034
76080
|
* prompt contains tool descriptions and runtime injections that contradict
|
|
76035
76081
|
* the compaction instruction ("DO NOT CALL ANY TOOLS"). This compact prompt
|
|
@@ -76284,7 +76330,8 @@ var FullCompaction = class {
|
|
|
76284
76330
|
const messagesToCompactForOps = originalHistory.slice(0, compactedCount);
|
|
76285
76331
|
const fileOps = createFileOps();
|
|
76286
76332
|
for (const msg of messagesToCompactForOps) extractFileOpsFromMessage(msg, fileOps);
|
|
76287
|
-
const
|
|
76333
|
+
const toolCallHistory = formatToolCallHistory(messagesToCompactForOps);
|
|
76334
|
+
const processedSummary = this.postProcessSummary(summary, fileOps, toolCallHistory);
|
|
76288
76335
|
const tokensAfter = estimateTokens$1(processedSummary) + estimateTokensForMessages(recent);
|
|
76289
76336
|
const result = {
|
|
76290
76337
|
summary: processedSummary,
|
|
@@ -76397,7 +76444,7 @@ var FullCompaction = class {
|
|
|
76397
76444
|
* compression. Without this, both are lost after compaction because the
|
|
76398
76445
|
* original messages containing them are removed from the context window.
|
|
76399
76446
|
*/
|
|
76400
|
-
postProcessSummary(summary, fileOps) {
|
|
76447
|
+
postProcessSummary(summary, fileOps, toolCallHistory) {
|
|
76401
76448
|
const todos = this.agent.tools.storeData()["todo"] ?? [];
|
|
76402
76449
|
const sections = [summary.trim()];
|
|
76403
76450
|
if (todos.length > 0) {
|
|
@@ -76412,6 +76459,7 @@ var FullCompaction = class {
|
|
|
76412
76459
|
}
|
|
76413
76460
|
const filesSection = formatFileOperations(fileOps);
|
|
76414
76461
|
if (filesSection.length > 0) sections.push(filesSection);
|
|
76462
|
+
if (toolCallHistory.length > 0) sections.push(toolCallHistory);
|
|
76415
76463
|
return sections.join("\n\n");
|
|
76416
76464
|
}
|
|
76417
76465
|
};
|
|
@@ -76518,7 +76566,7 @@ const DEFAULT_CONFIG = {
|
|
|
76518
76566
|
keepRecentTokens: 4e4,
|
|
76519
76567
|
pruneMinReclaimTokens: 2e4,
|
|
76520
76568
|
minContentTokens: 100,
|
|
76521
|
-
minContextUsageRatio: .
|
|
76569
|
+
minContextUsageRatio: .3,
|
|
76522
76570
|
truncatedMarker: "[Old tool result content cleared]",
|
|
76523
76571
|
uselessMarker: "[Uneventful result elided]",
|
|
76524
76572
|
noMatchesMarker: "[no matches]"
|
|
@@ -77865,8 +77913,15 @@ const TOOL_OUTPUT_EMPTY_TEXT = "Tool output is empty.";
|
|
|
77865
77913
|
/** Maximum token count for tool results persisted in conversation history.
|
|
77866
77914
|
* Results exceeding this limit are truncated to avoid bloating every
|
|
77867
77915
|
* subsequent API request with stale data. The model can re-read the
|
|
77868
|
-
* full content via read_file when needed.
|
|
77869
|
-
|
|
77916
|
+
* full content via read_file when needed.
|
|
77917
|
+
*
|
|
77918
|
+
* Lowered from 8000 to 5000 to reduce input-context pressure on long
|
|
77919
|
+
* sessions. When input grows large, the available output space
|
|
77920
|
+
* (context_window - input_tokens) shrinks, causing the model to hit
|
|
77921
|
+
* max_tokens before emitting a tool call. Smaller tool-result footprints
|
|
77922
|
+
* leave more room for output. The current turn always sees the full
|
|
77923
|
+
* result via streaming; only the history copy is truncated. */
|
|
77924
|
+
const MAX_TOOL_RESULT_TOKENS = 5e3;
|
|
77870
77925
|
const TOOL_TRUNCATION_NOTICE = "\n[content truncated — use read_file to re-read if needed]";
|
|
77871
77926
|
var ContextMemory = class {
|
|
77872
77927
|
agent;
|
|
@@ -96038,10 +96093,25 @@ function parseEnvBudget(raw) {
|
|
|
96038
96093
|
}
|
|
96039
96094
|
/**
|
|
96040
96095
|
* Compute the effective `max_completion_tokens` cap.
|
|
96041
|
-
|
|
96096
|
+
*
|
|
96097
|
+
* Aligned with oh-my-pi's approach: use a reasonable output-token cap
|
|
96098
|
+
* instead of the full context window. `max_context_tokens` is the total
|
|
96099
|
+
* (input + output) budget, not the output-only budget. Using it as
|
|
96100
|
+
* max_tokens tells the API "generate up to 128K output tokens", which is
|
|
96101
|
+
* incorrect - the actual max output is much smaller. The API server
|
|
96102
|
+
* clamps it to context_window - input_tokens, which shrinks as context
|
|
96103
|
+
* grows, causing "max_tokens limit - no tool call" errors on long
|
|
96104
|
+
* sessions.
|
|
96105
|
+
*
|
|
96106
|
+
* The 64K cap matches oh-my-pi's OUTPUT_CAP_WHEN_UNKNOWN and is well
|
|
96107
|
+
* above any current model's real output limit (typically 8K-32K), so it
|
|
96108
|
+
* never artificially limits output while preventing the context-window
|
|
96109
|
+
* value from being used directly.
|
|
96110
|
+
*/
|
|
96111
|
+
const OUTPUT_TOKEN_CAP = 64e3;
|
|
96042
96112
|
function computeCompletionBudgetCap(args) {
|
|
96043
96113
|
const maxCtx = args.capability?.max_context_tokens ?? 0;
|
|
96044
|
-
const cap = args.budget.hardCap ?? (maxCtx > 0 ? maxCtx : args.budget.fallback ?? DEFAULT_UNKNOWN_CONTEXT_FALLBACK);
|
|
96114
|
+
const cap = args.budget.hardCap ?? (maxCtx > 0 ? Math.min(maxCtx, OUTPUT_TOKEN_CAP) : args.budget.fallback ?? DEFAULT_UNKNOWN_CONTEXT_FALLBACK);
|
|
96045
96115
|
return Math.max(MIN_FLOOR, cap);
|
|
96046
96116
|
}
|
|
96047
96117
|
/**
|
|
@@ -120218,7 +120288,7 @@ function optionalBuildString(value) {
|
|
|
120218
120288
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
120219
120289
|
}
|
|
120220
120290
|
const SCREAM_BUILD_INFO = {
|
|
120221
|
-
version: optionalBuildString("0.11.
|
|
120291
|
+
version: optionalBuildString("0.11.3"),
|
|
120222
120292
|
channel: optionalBuildString(""),
|
|
120223
120293
|
commit: optionalBuildString(""),
|
|
120224
120294
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -125398,13 +125468,17 @@ function findProjectRoot(startDir) {
|
|
|
125398
125468
|
let dir = resolve(startDir);
|
|
125399
125469
|
let markerDir;
|
|
125400
125470
|
while (true) {
|
|
125401
|
-
|
|
125471
|
+
const hasGit = existsSync(resolve(dir, ".git"));
|
|
125402
125472
|
if (markerDir === void 0) {
|
|
125403
125473
|
for (const marker of PROJECT_ROOT_MARKERS) if (existsSync(resolve(dir, marker))) {
|
|
125404
125474
|
markerDir = dir;
|
|
125405
125475
|
break;
|
|
125406
125476
|
}
|
|
125407
125477
|
}
|
|
125478
|
+
if (hasGit) {
|
|
125479
|
+
if (markerDir === void 0 || markerDir === dir) return dir;
|
|
125480
|
+
return PROJECT_ROOT_MARKERS.some((m) => existsSync(resolve(dir, m))) ? dir : markerDir;
|
|
125481
|
+
}
|
|
125408
125482
|
const parent = dirname$1(dir);
|
|
125409
125483
|
if (parent === dir) break;
|
|
125410
125484
|
dir = parent;
|
|
@@ -126958,7 +127032,7 @@ var ThinkingComponent = class {
|
|
|
126958
127032
|
this.stopSpinner();
|
|
126959
127033
|
}
|
|
126960
127034
|
dispose() {
|
|
126961
|
-
this.
|
|
127035
|
+
this.finalize();
|
|
126962
127036
|
}
|
|
126963
127037
|
setExpanded(expanded) {
|
|
126964
127038
|
if (this.expanded === expanded) return;
|
|
@@ -148086,7 +148160,11 @@ async function runWebServer(opts) {
|
|
|
148086
148160
|
}
|
|
148087
148161
|
ws.send(JSON.stringify({ type: "server_empty" }));
|
|
148088
148162
|
});
|
|
148089
|
-
await new Promise((resolve) => {
|
|
148163
|
+
await new Promise((resolve, reject) => {
|
|
148164
|
+
httpServer.once("error", (err) => {
|
|
148165
|
+
if (err.code === "EADDRINUSE") reject(/* @__PURE__ */ new Error(`端口 ${opts.port} 已被占用,请先关闭占用该端口的进程,或使用 --port <port> 指定其他端口。`));
|
|
148166
|
+
else reject(err);
|
|
148167
|
+
});
|
|
148090
148168
|
httpServer.listen(opts.port, "127.0.0.1", resolve);
|
|
148091
148169
|
});
|
|
148092
148170
|
const url = `http://localhost:${opts.port}`;
|
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-D6B25mE5.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);
|