scream-code 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{app-Bda9iKUb.mjs → app-DVRLAZ8b.mjs} +243 -108
- package/dist/main.mjs +1 -1
- package/dist/{src-DA9VZFf3.mjs → src-B2kaYK-M.mjs} +1 -1
- package/dist/{src-1LHYB0xM.mjs → src-oeUnRY3N.mjs} +62 -7
- package/dist/{text-input-dialog-os5jWxGT.mjs → text-input-dialog-D_xK0DJH.mjs} +4 -0
- package/dist/{text-input-dialog-Yyssn7t3.mjs → text-input-dialog-Dk5xzj4F.mjs} +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img width="
|
|
2
|
+
<img width="200" height="200" alt="welcome_副本" src="https://github.com/user-attachments/assets/11d86774-b308-4cf7-857b-4c313670ade4" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
@@ -5,8 +5,8 @@ const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
|
5
5
|
const __dirname = __cjsShimDirname(__filename);
|
|
6
6
|
import { a as __toESM, i as __require, r as __exportAll, t as __commonJSMin } from "./chunk-apG1qJts.mjs";
|
|
7
7
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
8
|
-
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-
|
|
9
|
-
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-
|
|
8
|
+
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-oeUnRY3N.mjs";
|
|
9
|
+
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-D_xK0DJH.mjs";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
12
12
|
import Jn, { access, appendFile, chmod, copyFile, cp, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, rmdir, stat, unlink, writeFile } from "node:fs/promises";
|
|
@@ -22,7 +22,7 @@ import { finished, pipeline as pipeline$1 } from "node:stream/promises";
|
|
|
22
22
|
import * as vs from "zlib";
|
|
23
23
|
import Qr from "zlib";
|
|
24
24
|
import * as fs$9 from "node:fs";
|
|
25
|
-
import Vt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream as createWriteStream$1, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, readSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
25
|
+
import Vt, { appendFileSync, chmodSync, closeSync, constants, createReadStream, createWriteStream as createWriteStream$1, existsSync, fsyncSync, mkdirSync, openSync, promises, readFileSync, readSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
26
26
|
import * as path$8 from "node:path";
|
|
27
27
|
import path, { basename, dirname as dirname$1, extname, isAbsolute, join, posix, relative, resolve, sep, win32 } from "node:path";
|
|
28
28
|
import { z } from "zod";
|
|
@@ -9190,7 +9190,7 @@ var AnthropicChatProvider = class {
|
|
|
9190
9190
|
const kwargs = {
|
|
9191
9191
|
thinking: {
|
|
9192
9192
|
type: "enabled",
|
|
9193
|
-
budget_tokens: budgetTokensForEffort(effectiveEffort)
|
|
9193
|
+
budget_tokens: budgetTokensForEffort(effectiveEffort === "xhigh" || effectiveEffort === "max" ? "high" : effectiveEffort)
|
|
9194
9194
|
},
|
|
9195
9195
|
betaFeatures: newBetas
|
|
9196
9196
|
};
|
|
@@ -37877,6 +37877,7 @@ function messagesToGoogleGenAIContents(messages) {
|
|
|
37877
37877
|
toolMessages.push(toolMsg);
|
|
37878
37878
|
j += 1;
|
|
37879
37879
|
}
|
|
37880
|
+
if (toolMessages.length === 0) throw new ChatProviderError(`Missing tool responses for ids: ${expectedToolCallIds.join(", ")}`);
|
|
37880
37881
|
if (toolMessages.length > 0) {
|
|
37881
37882
|
const toolMsgById = /* @__PURE__ */ new Map();
|
|
37882
37883
|
const seenToolCallIds = /* @__PURE__ */ new Set();
|
|
@@ -48773,6 +48774,7 @@ var OpenAILegacyChatProvider = class {
|
|
|
48773
48774
|
_defaultHeaders;
|
|
48774
48775
|
_reasoningKey;
|
|
48775
48776
|
_reasoningEffort;
|
|
48777
|
+
_thinkingExplicitlyOff = false;
|
|
48776
48778
|
_generationKwargs;
|
|
48777
48779
|
_toolMessageConversion;
|
|
48778
48780
|
_client;
|
|
@@ -48821,7 +48823,7 @@ var OpenAILegacyChatProvider = class {
|
|
|
48821
48823
|
for (const msg of normalizedHistory) messages.push(convertMessage$1(msg, this._reasoningKey, this._toolMessageConversion));
|
|
48822
48824
|
const kwargs = { ...this._generationKwargs };
|
|
48823
48825
|
let reasoningEffort = this._reasoningEffort;
|
|
48824
|
-
if (reasoningEffort === void 0 && kwargs["reasoning_effort"] === void 0) {
|
|
48826
|
+
if (!this._thinkingExplicitlyOff && reasoningEffort === void 0 && kwargs["reasoning_effort"] === void 0) {
|
|
48825
48827
|
if (history.some((message) => message.content.some((part) => part.type === "think"))) reasoningEffort = "medium";
|
|
48826
48828
|
}
|
|
48827
48829
|
for (const key of Object.keys(kwargs)) if (kwargs[key] === void 0) delete kwargs[key];
|
|
@@ -48844,6 +48846,7 @@ var OpenAILegacyChatProvider = class {
|
|
|
48844
48846
|
const reasoningEffort = thinkingEffortToReasoningEffort(effort);
|
|
48845
48847
|
const clone = this._clone();
|
|
48846
48848
|
clone._reasoningEffort = reasoningEffort;
|
|
48849
|
+
clone._thinkingExplicitlyOff = effort === "off";
|
|
48847
48850
|
return clone;
|
|
48848
48851
|
}
|
|
48849
48852
|
withGenerationKwargs(kwargs) {
|
|
@@ -56837,7 +56840,10 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
56837
56840
|
initPromise = null;
|
|
56838
56841
|
async init() {
|
|
56839
56842
|
if (this.initPromise) return this.initPromise;
|
|
56840
|
-
this.initPromise = this._doInit()
|
|
56843
|
+
this.initPromise = this._doInit().catch((error) => {
|
|
56844
|
+
this.initPromise = null;
|
|
56845
|
+
throw error;
|
|
56846
|
+
});
|
|
56841
56847
|
return this.initPromise;
|
|
56842
56848
|
}
|
|
56843
56849
|
async _doInit() {
|
|
@@ -56853,6 +56859,11 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
56853
56859
|
}
|
|
56854
56860
|
/** Close the database handle and checkpoint WAL. */
|
|
56855
56861
|
close() {
|
|
56862
|
+
if (this.embeddingTimer !== void 0) {
|
|
56863
|
+
clearTimeout(this.embeddingTimer);
|
|
56864
|
+
this.embeddingTimer = void 0;
|
|
56865
|
+
}
|
|
56866
|
+
this.embeddingQueue.clear();
|
|
56856
56867
|
if (this.db !== void 0) {
|
|
56857
56868
|
this.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
56858
56869
|
this.db.close();
|
|
@@ -57126,6 +57137,7 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
57126
57137
|
try {
|
|
57127
57138
|
for (const memo of memos) {
|
|
57128
57139
|
const row = insert.get(memo.id, memo.sourceSessionId, memo.sourceSessionTitle ?? null, memo.userNeed, memo.approach, memo.outcome, memo.whatFailed, memo.whatWorked, memo.extractionSource, memo.recordedAt, memo.projectDir ?? "", JSON.stringify(memo.tags ?? []));
|
|
57140
|
+
if (row === void 0) continue;
|
|
57129
57141
|
insertFts.run(row.rowid, toFtsText(memo.userNeed), toFtsText(memo.approach), toFtsText(memo.whatFailed), toFtsText(memo.whatWorked), toFtsText(memo.sourceSessionTitle ?? ""));
|
|
57130
57142
|
}
|
|
57131
57143
|
this.db.exec("COMMIT");
|
|
@@ -57188,6 +57200,7 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
57188
57200
|
const updateFts = this.db.prepare(`INSERT INTO memos_fts(rowid, user_need, approach, what_failed, what_worked, source_session_title)
|
|
57189
57201
|
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
57190
57202
|
const deleteFts = this.db.prepare("INSERT INTO memos_fts(memos_fts, rowid) VALUES ('delete', ?)");
|
|
57203
|
+
const deleteEmbedding = this.db.prepare("DELETE FROM memory_embeddings WHERE memory_id = ?");
|
|
57191
57204
|
this.db.exec("BEGIN TRANSACTION");
|
|
57192
57205
|
try {
|
|
57193
57206
|
const oldRow = selectRow.get(id);
|
|
@@ -57202,7 +57215,9 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
57202
57215
|
}
|
|
57203
57216
|
deleteFts.run(oldRow.rowid);
|
|
57204
57217
|
updateFts.run(row.rowid, toFtsText(updated.userNeed), toFtsText(updated.approach), toFtsText(updated.whatFailed), toFtsText(updated.whatWorked), toFtsText(updated.sourceSessionTitle ?? ""));
|
|
57218
|
+
deleteEmbedding.run(id);
|
|
57205
57219
|
this.db.exec("COMMIT");
|
|
57220
|
+
this.scheduleEmbedding(updated);
|
|
57206
57221
|
return true;
|
|
57207
57222
|
} catch {
|
|
57208
57223
|
this.db.exec("ROLLBACK");
|
|
@@ -57613,6 +57628,7 @@ async function applyConsolidation(store, plan) {
|
|
|
57613
57628
|
whatWorked: worked || "none",
|
|
57614
57629
|
whatFailed: failed || "none",
|
|
57615
57630
|
tags: normalizeTags(plan.resolved.flatMap((m) => m.tags ?? [])),
|
|
57631
|
+
projectDir: plan.resolved[0].projectDir,
|
|
57616
57632
|
extractionSource: "compaction"
|
|
57617
57633
|
});
|
|
57618
57634
|
await store.append(archive);
|
|
@@ -57631,6 +57647,7 @@ async function applyConsolidation(store, plan) {
|
|
|
57631
57647
|
whatWorked: worked || "none",
|
|
57632
57648
|
whatFailed: failed || "none",
|
|
57633
57649
|
tags: normalizeTags(plan.stale.flatMap((m) => m.tags ?? [])),
|
|
57650
|
+
projectDir: plan.stale[0].projectDir,
|
|
57634
57651
|
extractionSource: "compaction"
|
|
57635
57652
|
});
|
|
57636
57653
|
await store.append(archive);
|
|
@@ -57649,6 +57666,7 @@ async function applyConsolidation(store, plan) {
|
|
|
57649
57666
|
whatFailed: group.merged.whatFailed,
|
|
57650
57667
|
whatWorked: group.merged.whatWorked,
|
|
57651
57668
|
tags: group.merged.tags ?? mergedTags,
|
|
57669
|
+
projectDir: newest.projectDir,
|
|
57652
57670
|
extractionSource: "compaction"
|
|
57653
57671
|
});
|
|
57654
57672
|
await store.append(merged);
|
|
@@ -58334,7 +58352,7 @@ var KnowledgeLookupTool = class {
|
|
|
58334
58352
|
const llm = { generate: async (systemPrompt, userPrompt) => {
|
|
58335
58353
|
return this.agent.generateText(systemPrompt, userPrompt);
|
|
58336
58354
|
} };
|
|
58337
|
-
const { multiSearchWithTrace } = await import("./src-
|
|
58355
|
+
const { multiSearchWithTrace } = await import("./src-B2kaYK-M.mjs");
|
|
58338
58356
|
const { results, trace } = await multiSearchWithTrace(store, llm, query, { topK });
|
|
58339
58357
|
if (results.length === 0) return {
|
|
58340
58358
|
isError: false,
|
|
@@ -76673,7 +76691,8 @@ var ReadTool = class {
|
|
|
76673
76691
|
hasLf: false,
|
|
76674
76692
|
hasLoneCr: false
|
|
76675
76693
|
};
|
|
76676
|
-
const
|
|
76694
|
+
const rawHash = createHash("sha256");
|
|
76695
|
+
const normalizedHash = createHash("sha256");
|
|
76677
76696
|
let currentLineNo = 0;
|
|
76678
76697
|
let maxLinesReached = false;
|
|
76679
76698
|
let collectionClosed = false;
|
|
@@ -76684,7 +76703,8 @@ var ReadTool = class {
|
|
|
76684
76703
|
};
|
|
76685
76704
|
currentLineNo += 1;
|
|
76686
76705
|
updateLineEndingFlags(flags, rawLine);
|
|
76687
|
-
|
|
76706
|
+
rawHash.update(rawLine);
|
|
76707
|
+
normalizedHash.update(rawLine.replaceAll("\r\n", "\n"));
|
|
76688
76708
|
if (collectionClosed) {
|
|
76689
76709
|
if (effectiveLimit >= 1e3 && currentLineNo >= lineOffset) maxLinesReached = true;
|
|
76690
76710
|
continue;
|
|
@@ -76702,7 +76722,7 @@ var ReadTool = class {
|
|
|
76702
76722
|
if (selectedEntries.length >= effectiveLimit) collectionClosed = true;
|
|
76703
76723
|
}
|
|
76704
76724
|
const lineEndingStyle = lineEndingStyleFromFlags(flags);
|
|
76705
|
-
const anchor =
|
|
76725
|
+
const anchor = (lineEndingStyle === "crlf" ? normalizedHash : rawHash).digest("hex").slice(0, 8);
|
|
76706
76726
|
const renderedLines = [];
|
|
76707
76727
|
const truncatedLineNumbers = [];
|
|
76708
76728
|
let bytes = 0;
|
|
@@ -76742,7 +76762,8 @@ var ReadTool = class {
|
|
|
76742
76762
|
hasLf: false,
|
|
76743
76763
|
hasLoneCr: false
|
|
76744
76764
|
};
|
|
76745
|
-
const
|
|
76765
|
+
const rawHash = createHash("sha256");
|
|
76766
|
+
const normalizedHash = createHash("sha256");
|
|
76746
76767
|
let currentLineNo = 0;
|
|
76747
76768
|
for await (const rawLine of this.jian.readLines(safePath, { errors: "strict" })) {
|
|
76748
76769
|
if (containsNulByte(rawLine)) return {
|
|
@@ -76751,7 +76772,8 @@ var ReadTool = class {
|
|
|
76751
76772
|
};
|
|
76752
76773
|
currentLineNo += 1;
|
|
76753
76774
|
updateLineEndingFlags(flags, rawLine);
|
|
76754
|
-
|
|
76775
|
+
rawHash.update(rawLine);
|
|
76776
|
+
normalizedHash.update(rawLine.replaceAll("\r\n", "\n"));
|
|
76755
76777
|
entries.push({
|
|
76756
76778
|
lineNo: currentLineNo,
|
|
76757
76779
|
rawContent: stripTrailingLf(rawLine)
|
|
@@ -76759,7 +76781,7 @@ var ReadTool = class {
|
|
|
76759
76781
|
if (entries.length > tailCount) entries.shift();
|
|
76760
76782
|
}
|
|
76761
76783
|
const lineEndingStyle = lineEndingStyleFromFlags(flags);
|
|
76762
|
-
const anchor =
|
|
76784
|
+
const anchor = (lineEndingStyle === "crlf" ? normalizedHash : rawHash).digest("hex").slice(0, 8);
|
|
76763
76785
|
let renderedCandidates = entries.slice(0, effectiveLimit).map((entry) => {
|
|
76764
76786
|
return {
|
|
76765
76787
|
entry,
|
|
@@ -78086,7 +78108,7 @@ var BashTool = class {
|
|
|
78086
78108
|
const info = backgroundManager.getTask(taskId);
|
|
78087
78109
|
if (info && info.status === "running") backgroundManager.stop(taskId, "Timed out");
|
|
78088
78110
|
})();
|
|
78089
|
-
}, timeoutMs);
|
|
78111
|
+
}, timeoutMs).unref();
|
|
78090
78112
|
const status = backgroundManager.getTask(taskId).status;
|
|
78091
78113
|
const builder = new ToolResultBuilder();
|
|
78092
78114
|
builder.write(`task_id: ${taskId}\npid: ${String(proc.pid)}\ndescription: ${args.description.trim()}\nstatus: ${status}\nautomatic_notification: true\nnext_step: You will be automatically notified when it completes.
|
|
@@ -79152,7 +79174,10 @@ var FullCompaction = class {
|
|
|
79152
79174
|
if (this.compactionCountInTurn > this.strategy.maxCompactionPerTurn) return;
|
|
79153
79175
|
if (this.agent.records.restoring) return;
|
|
79154
79176
|
const compactedCount = this.strategy.computeCompactCount(this.agent.context.history, data.source);
|
|
79155
|
-
if (compactedCount === 0)
|
|
79177
|
+
if (compactedCount === 0) {
|
|
79178
|
+
if (data.source === "manual") throw new ScreamError(ErrorCodes.COMPACTION_UNABLE, "No prefix that can be compacted in current history.");
|
|
79179
|
+
return;
|
|
79180
|
+
}
|
|
79156
79181
|
this.agent.records.logRecord({
|
|
79157
79182
|
type: "full_compaction.begin",
|
|
79158
79183
|
...data
|
|
@@ -80881,7 +80906,8 @@ var ContextMemory = class {
|
|
|
80881
80906
|
toolCalls: [],
|
|
80882
80907
|
origin: { kind: "compaction_summary" }
|
|
80883
80908
|
}, ...this._history.slice(summary.compactedCount)];
|
|
80884
|
-
this.
|
|
80909
|
+
const survivingMessages = new Set(this._history);
|
|
80910
|
+
for (const [uuid, message] of this.openSteps) if (!survivingMessages.has(message)) this.openSteps.delete(uuid);
|
|
80885
80911
|
this.flushDeferredMessagesIfToolExchangeClosed();
|
|
80886
80912
|
this._tokenCount = summary.tokensAfter;
|
|
80887
80913
|
this.tokenCountCoveredMessageCount = this._history.length;
|
|
@@ -92274,8 +92300,7 @@ function parseToolCallArguments(raw) {
|
|
|
92274
92300
|
*/
|
|
92275
92301
|
function repairTruncatedJson(raw) {
|
|
92276
92302
|
let repaired = raw.trimEnd();
|
|
92277
|
-
|
|
92278
|
-
let bracketOpen = 0;
|
|
92303
|
+
const openStack = [];
|
|
92279
92304
|
let inString = false;
|
|
92280
92305
|
let stringHasEscape = false;
|
|
92281
92306
|
let lastNonWhitespace = "";
|
|
@@ -92293,24 +92318,16 @@ function repairTruncatedJson(raw) {
|
|
|
92293
92318
|
}
|
|
92294
92319
|
stringHasEscape = false;
|
|
92295
92320
|
if (inString) continue;
|
|
92296
|
-
if (ch === "{")
|
|
92297
|
-
if (ch === "
|
|
92298
|
-
if (ch === "
|
|
92299
|
-
|
|
92321
|
+
if (ch === "{") openStack.push("}");
|
|
92322
|
+
else if (ch === "[") openStack.push("]");
|
|
92323
|
+
else if (ch === "}" || ch === "]") {
|
|
92324
|
+
if (openStack.length > 0 && openStack[openStack.length - 1] === ch) openStack.pop();
|
|
92325
|
+
}
|
|
92300
92326
|
if (!/\s/.test(ch)) lastNonWhitespace = ch;
|
|
92301
92327
|
}
|
|
92302
92328
|
if (inString) repaired += "\"";
|
|
92303
92329
|
if (lastNonWhitespace === ",") repaired += "null";
|
|
92304
|
-
|
|
92305
|
-
while (bracketOpen > 0) {
|
|
92306
|
-
closers.push("]");
|
|
92307
|
-
bracketOpen--;
|
|
92308
|
-
}
|
|
92309
|
-
while (braceOpen > 0) {
|
|
92310
|
-
closers.push("}");
|
|
92311
|
-
braceOpen--;
|
|
92312
|
-
}
|
|
92313
|
-
if (closers.length > 0) repaired += closers.join("");
|
|
92330
|
+
for (let i = openStack.length - 1; i >= 0; i--) repaired += openStack[i];
|
|
92314
92331
|
return repaired;
|
|
92315
92332
|
}
|
|
92316
92333
|
function validateExecutableToolArgs(tool, args) {
|
|
@@ -97920,7 +97937,7 @@ var TurnFlow = class {
|
|
|
97920
97937
|
});
|
|
97921
97938
|
return null;
|
|
97922
97939
|
}
|
|
97923
|
-
if (this.turnId === -1) this.agent.dreamTracker.init().then(() => this.agent.dreamTracker.recordNewSession());
|
|
97940
|
+
if (this.turnId === -1) this.agent.dreamTracker.init().then(() => this.agent.dreamTracker.recordNewSession()).catch(() => {});
|
|
97924
97941
|
const turnId = this.allocateTurnId();
|
|
97925
97942
|
const controller = new AbortController();
|
|
97926
97943
|
const promise = this.turnWorker(turnId, input, origin, controller.signal);
|
|
@@ -104227,7 +104244,7 @@ var Session$1 = class {
|
|
|
104227
104244
|
});
|
|
104228
104245
|
await this.options.jian.writeText(this.metadataPath, text);
|
|
104229
104246
|
};
|
|
104230
|
-
this.writeMetadataPromise = this.writeMetadataPromise.then(() => write());
|
|
104247
|
+
this.writeMetadataPromise = this.writeMetadataPromise.then(() => write(), () => write());
|
|
104231
104248
|
return this.writeMetadataPromise;
|
|
104232
104249
|
}
|
|
104233
104250
|
async readMetadata() {
|
|
@@ -117201,6 +117218,7 @@ setPrototypeOf(Document, Document$1).prototype = Document$1.prototype;
|
|
|
117201
117218
|
*/
|
|
117202
117219
|
const DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
|
|
117203
117220
|
const DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
|
|
117221
|
+
const FETCH_TIMEOUT_MS = 3e4;
|
|
117204
117222
|
const parseHTML = parseHTML$1;
|
|
117205
117223
|
/**
|
|
117206
117224
|
* SSRF guard — reject non-http(s) schemes and (by default) any hostname
|
|
@@ -117296,7 +117314,8 @@ var LocalFetchURLProvider = class {
|
|
|
117296
117314
|
async fetchFresh(url) {
|
|
117297
117315
|
const response = await this.fetchImpl(url, {
|
|
117298
117316
|
method: "GET",
|
|
117299
|
-
headers: { "User-Agent": this.userAgent }
|
|
117317
|
+
headers: { "User-Agent": this.userAgent },
|
|
117318
|
+
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
117300
117319
|
});
|
|
117301
117320
|
if (response.status >= 400) {
|
|
117302
117321
|
await response.body?.cancel().catch(() => {});
|
|
@@ -117305,7 +117324,10 @@ var LocalFetchURLProvider = class {
|
|
|
117305
117324
|
const contentLengthRaw = response.headers.get("content-length");
|
|
117306
117325
|
if (contentLengthRaw !== null) {
|
|
117307
117326
|
const cl = Number(contentLengthRaw);
|
|
117308
|
-
if (Number.isFinite(cl) && cl > this.maxBytes)
|
|
117327
|
+
if (Number.isFinite(cl) && cl > this.maxBytes) {
|
|
117328
|
+
await response.body?.cancel().catch(() => {});
|
|
117329
|
+
throw new Error(`Response body too large: ${String(cl)} bytes exceeds maxBytes (${String(this.maxBytes)}).`);
|
|
117330
|
+
}
|
|
117309
117331
|
}
|
|
117310
117332
|
const body = await response.text();
|
|
117311
117333
|
const actualBytes = Buffer.byteLength(body, "utf8");
|
|
@@ -122505,7 +122527,7 @@ function optionalBuildString(value) {
|
|
|
122505
122527
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
122506
122528
|
}
|
|
122507
122529
|
const SCREAM_BUILD_INFO = {
|
|
122508
|
-
version: optionalBuildString("0.10.
|
|
122530
|
+
version: optionalBuildString("0.10.1"),
|
|
122509
122531
|
channel: optionalBuildString(""),
|
|
122510
122532
|
commit: optionalBuildString(""),
|
|
122511
122533
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -122991,7 +123013,7 @@ async function resolvePromptSession(harness, opts, workDir, defaultModel, stderr
|
|
|
122991
123013
|
workDir
|
|
122992
123014
|
}))[0];
|
|
122993
123015
|
if (target === void 0) throw new Error(`未找到会话 "${opts.session}"。`);
|
|
122994
|
-
if (target.workDir
|
|
123016
|
+
if (!sameWorkDir(target.workDir, workDir)) {
|
|
122995
123017
|
stderr.write(`${chalk.yellow(`会话 "${opts.session}" 是在其他目录下创建的。\n cd "${target.workDir}" && scream -r ${opts.session}`)}\n\n`);
|
|
122996
123018
|
throw new Error(`会话 "${opts.session}" 是在其他目录下创建的。`);
|
|
122997
123019
|
}
|
|
@@ -123380,6 +123402,23 @@ function formatTurnEndedFailure(event) {
|
|
|
123380
123402
|
if (event.error !== void 0) return `${event.error.code}: ${event.error.message}`;
|
|
123381
123403
|
return `提示回合结束,原因:${event.reason}`;
|
|
123382
123404
|
}
|
|
123405
|
+
/**
|
|
123406
|
+
* Compare two working directories tolerating symlink aliases (/tmp vs
|
|
123407
|
+
* /private/tmp on macOS), trailing separators, and Windows case
|
|
123408
|
+
* differences. Falls back to resolved-string compare when either path
|
|
123409
|
+
* doesn't exist on disk.
|
|
123410
|
+
*/
|
|
123411
|
+
function sameWorkDir(a, b) {
|
|
123412
|
+
const normalize = (p) => {
|
|
123413
|
+
let out = resolve(p);
|
|
123414
|
+
try {
|
|
123415
|
+
out = realpathSync(out);
|
|
123416
|
+
} catch {}
|
|
123417
|
+
out = out.replace(/[/\\]+$/, "");
|
|
123418
|
+
return process.platform === "win32" ? out.toLowerCase() : out;
|
|
123419
|
+
};
|
|
123420
|
+
return normalize(a) === normalize(b);
|
|
123421
|
+
}
|
|
123383
123422
|
//#endregion
|
|
123384
123423
|
//#region src/tui/constant/rendering.ts
|
|
123385
123424
|
const MAX_SHELL_OUTPUT_BYTES = 128 * 1024;
|
|
@@ -127788,7 +127827,7 @@ async function createGoal(host, parsed) {
|
|
|
127788
127827
|
await showGoalConfigWizard(host, session, parsed.objective, parsed.replace);
|
|
127789
127828
|
}
|
|
127790
127829
|
async function showGoalConfigWizard(host, session, objective, replace) {
|
|
127791
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
127830
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-Dk5xzj4F.mjs");
|
|
127792
127831
|
const turnInput = await promptNumber(host, TextInputDialogComponent, {
|
|
127793
127832
|
title: t("goal.wizard_title", { objective }),
|
|
127794
127833
|
subtitle: t("goal.budget_turns_hint"),
|
|
@@ -132341,35 +132380,39 @@ async function handleUpdateCommand(host) {
|
|
|
132341
132380
|
* /mcp — MCP 服务器管理面板。
|
|
132342
132381
|
*
|
|
132343
132382
|
* 查看已安装的 MCP 服务器状态,一键安装推荐服务器。 */
|
|
132344
|
-
|
|
132345
|
-
|
|
132346
|
-
|
|
132347
|
-
|
|
132348
|
-
|
|
132349
|
-
|
|
132350
|
-
|
|
132351
|
-
|
|
132352
|
-
|
|
132353
|
-
|
|
132354
|
-
|
|
132355
|
-
|
|
132356
|
-
|
|
132357
|
-
|
|
132358
|
-
|
|
132359
|
-
|
|
132360
|
-
|
|
132361
|
-
|
|
132362
|
-
|
|
132363
|
-
|
|
132364
|
-
|
|
132365
|
-
|
|
132366
|
-
|
|
132367
|
-
|
|
132368
|
-
|
|
132369
|
-
|
|
132370
|
-
|
|
132371
|
-
|
|
132372
|
-
|
|
132383
|
+
function getRecommended() {
|
|
132384
|
+
return [{
|
|
132385
|
+
name: "peekaboo",
|
|
132386
|
+
displayName: "Peekaboo",
|
|
132387
|
+
description: t("mcp.desktop_desc"),
|
|
132388
|
+
command: "npx",
|
|
132389
|
+
args: [
|
|
132390
|
+
"-y",
|
|
132391
|
+
"@steipete/peekaboo",
|
|
132392
|
+
"mcp"
|
|
132393
|
+
],
|
|
132394
|
+
macOnly: true
|
|
132395
|
+
}, {
|
|
132396
|
+
name: "chrome-devtools",
|
|
132397
|
+
displayName: "Chrome DevTools",
|
|
132398
|
+
description: t("mcp.browser_desc"),
|
|
132399
|
+
command: "npx",
|
|
132400
|
+
args: [
|
|
132401
|
+
"-y",
|
|
132402
|
+
"chrome-devtools-mcp@latest",
|
|
132403
|
+
"--no-usage-statistics"
|
|
132404
|
+
]
|
|
132405
|
+
}];
|
|
132406
|
+
}
|
|
132407
|
+
function getStatusLabels() {
|
|
132408
|
+
return {
|
|
132409
|
+
pending: t("mcp.connecting"),
|
|
132410
|
+
connected: t("mcp.connected"),
|
|
132411
|
+
failed: t("mcp.failed"),
|
|
132412
|
+
disabled: t("mcp.disabled"),
|
|
132413
|
+
"needs-auth": t("mcp.auth_required")
|
|
132414
|
+
};
|
|
132415
|
+
}
|
|
132373
132416
|
async function handleMcpCommand(host, _args) {
|
|
132374
132417
|
if (!host.session) {
|
|
132375
132418
|
host.showError(t("mcp.no_session"));
|
|
@@ -132438,7 +132481,7 @@ function buildRows(servers) {
|
|
|
132438
132481
|
status: "__section"
|
|
132439
132482
|
});
|
|
132440
132483
|
for (const s of servers) {
|
|
132441
|
-
const statusLabel =
|
|
132484
|
+
const statusLabel = getStatusLabels()[s.status] ?? s.status;
|
|
132442
132485
|
const toolInfo = s.status === "connected" ? `${s.toolCount} tools` : "";
|
|
132443
132486
|
const errorInfo = s.error ? ` — ${sanitizeDesc(s.error)}` : "";
|
|
132444
132487
|
rows.push({
|
|
@@ -132467,7 +132510,7 @@ function buildRows(servers) {
|
|
|
132467
132510
|
label: "── " + t("mcp.recommended") + " ──",
|
|
132468
132511
|
status: "__section"
|
|
132469
132512
|
});
|
|
132470
|
-
for (const rec of
|
|
132513
|
+
for (const rec of getRecommended()) {
|
|
132471
132514
|
const alreadyInstalled = installedNames.has(rec.name);
|
|
132472
132515
|
const platformUnavailable = rec.macOnly && process.platform !== "darwin";
|
|
132473
132516
|
rows.push({
|
|
@@ -132486,7 +132529,7 @@ async function handleEnter(host, row) {
|
|
|
132486
132529
|
host.showStatus(t("mcp.already_installed", { name: row.label }));
|
|
132487
132530
|
return;
|
|
132488
132531
|
}
|
|
132489
|
-
const rec =
|
|
132532
|
+
const rec = getRecommended().find((r) => r.name === row.name);
|
|
132490
132533
|
if (!rec) return;
|
|
132491
132534
|
await installMcp(host, rec);
|
|
132492
132535
|
} else if (row.kind === "installed" && row.status && row.status !== "__section" && row.status !== "__empty") if (row.status === "connected") await disableMcp(host, row.name);
|
|
@@ -136492,6 +136535,9 @@ out.join('\n');
|
|
|
136492
136535
|
function isWaylandSession(env) {
|
|
136493
136536
|
return Boolean(env["WAYLAND_DISPLAY"]) || env["XDG_SESSION_TYPE"] === "wayland";
|
|
136494
136537
|
}
|
|
136538
|
+
function isX11Session(env) {
|
|
136539
|
+
return Boolean(env["DISPLAY"]);
|
|
136540
|
+
}
|
|
136495
136541
|
function isWSL(env) {
|
|
136496
136542
|
if (env["WSL_DISTRO_NAME"] !== void 0 || env["WSLENV"] !== void 0) return true;
|
|
136497
136543
|
try {
|
|
@@ -136829,7 +136875,7 @@ async function readClipboardMedia(options) {
|
|
|
136829
136875
|
if (platform === "linux") {
|
|
136830
136876
|
const wayland = isWaylandSession(env);
|
|
136831
136877
|
const wsl = isWSL(env);
|
|
136832
|
-
if (wayland || wsl) {
|
|
136878
|
+
if (wayland || wsl || isX11Session(env)) {
|
|
136833
136879
|
const fileMedia = readClipboardFileMediaViaWlPaste() ?? readClipboardFileMediaViaXclip();
|
|
136834
136880
|
if (fileMedia !== null) return fileMedia;
|
|
136835
136881
|
image = readClipboardImageViaWlPaste() ?? readClipboardImageViaXclip();
|
|
@@ -138122,9 +138168,9 @@ var SessionEventHandler = class {
|
|
|
138122
138168
|
const { streamingUI } = this.host;
|
|
138123
138169
|
const backgroundMeta = this.backgroundAgentMetadata.get(event.subagentId);
|
|
138124
138170
|
if (backgroundMeta !== void 0) {
|
|
138171
|
+
const taskId = this.findAgentTaskId(event.subagentId);
|
|
138125
138172
|
this.backgroundAgentMetadata.delete(event.subagentId);
|
|
138126
138173
|
this.syncBackgroundAgentBadge();
|
|
138127
|
-
const taskId = this.findAgentTaskId(event.subagentId);
|
|
138128
138174
|
if (taskId !== void 0 && this.backgroundTaskTranscriptedTerminal.has(taskId)) return;
|
|
138129
138175
|
if (taskId !== void 0) this.backgroundTaskTranscriptedTerminal.add(taskId);
|
|
138130
138176
|
const extras = event.resultSummary === void 0 ? void 0 : { resultSummary: event.resultSummary };
|
|
@@ -138145,6 +138191,7 @@ var SessionEventHandler = class {
|
|
|
138145
138191
|
const { streamingUI } = this.host;
|
|
138146
138192
|
const backgroundMeta = this.backgroundAgentMetadata.get(event.subagentId);
|
|
138147
138193
|
if (backgroundMeta !== void 0) {
|
|
138194
|
+
const taskId = this.findAgentTaskId(event.subagentId);
|
|
138148
138195
|
this.backgroundAgentMetadata.delete(event.subagentId);
|
|
138149
138196
|
this.syncBackgroundAgentBadge();
|
|
138150
138197
|
streamingUI.applyBackgroundTaskTerminalStatus({
|
|
@@ -138153,7 +138200,6 @@ var SessionEventHandler = class {
|
|
|
138153
138200
|
status: "failed",
|
|
138154
138201
|
errorText: event.error
|
|
138155
138202
|
});
|
|
138156
|
-
const taskId = this.findAgentTaskId(event.subagentId);
|
|
138157
138203
|
if (taskId !== void 0 && this.backgroundTaskTranscriptedTerminal.has(taskId)) return;
|
|
138158
138204
|
if (taskId !== void 0) this.backgroundTaskTranscriptedTerminal.add(taskId);
|
|
138159
138205
|
this.appendBackgroundAgentEntry("failed", backgroundMeta, { error: event.error });
|
|
@@ -138297,18 +138343,21 @@ var SessionEventHandler = class {
|
|
|
138297
138343
|
};
|
|
138298
138344
|
//#endregion
|
|
138299
138345
|
//#region src/tui/utils/media-url.ts
|
|
138300
|
-
|
|
138301
|
-
|
|
138302
|
-
|
|
138303
|
-
|
|
138304
|
-
|
|
138346
|
+
function getMediaKindLabels() {
|
|
138347
|
+
return {
|
|
138348
|
+
audio: t("mediaurl.audio"),
|
|
138349
|
+
image: t("mediaurl.image"),
|
|
138350
|
+
video: t("mediaurl.video")
|
|
138351
|
+
};
|
|
138352
|
+
}
|
|
138305
138353
|
function mediaUrlPartToText(kind, url) {
|
|
138354
|
+
const labels = getMediaKindLabels();
|
|
138306
138355
|
const summary = summarizeDataUrl(url);
|
|
138307
138356
|
if (summary !== void 0) {
|
|
138308
138357
|
const size = summary.bytes !== void 0 ? `, ${formatByteSize(summary.bytes)}` : "";
|
|
138309
|
-
return `[${
|
|
138358
|
+
return `[${labels[kind]} ${summary.mime}${size}]`;
|
|
138310
138359
|
}
|
|
138311
|
-
return `<${
|
|
138360
|
+
return `<${labels[kind]} url="${escapeAttribute$1(url)}">`;
|
|
138312
138361
|
}
|
|
138313
138362
|
function summarizeDataUrl(url) {
|
|
138314
138363
|
if (!url.startsWith("data:")) return void 0;
|
|
@@ -142194,7 +142243,7 @@ function hslToHex(h, s, l) {
|
|
|
142194
142243
|
const toHex = (v) => Math.round((v + m) * 255).toString(16).padStart(2, "0");
|
|
142195
142244
|
return `#${toHex(rf)}${toHex(gf)}${toHex(bf)}`;
|
|
142196
142245
|
}
|
|
142197
|
-
var InputController = class {
|
|
142246
|
+
var InputController = class InputController {
|
|
142198
142247
|
host;
|
|
142199
142248
|
lastHistoryContent;
|
|
142200
142249
|
breatheTimer = null;
|
|
@@ -142215,12 +142264,38 @@ var InputController = class {
|
|
|
142215
142264
|
};
|
|
142216
142265
|
if (this.host.state.appState.planMode === "off") this.#startBreathing();
|
|
142217
142266
|
}
|
|
142267
|
+
pendingLargeInput = null;
|
|
142268
|
+
static LARGE_INPUT_THRESHOLD = 5e3;
|
|
142218
142269
|
handleInput(text) {
|
|
142270
|
+
if (this.pendingLargeInput !== null) {
|
|
142271
|
+
const answer = text.trim().toLowerCase();
|
|
142272
|
+
if (answer === "y" || answer === "yes") {
|
|
142273
|
+
const pending = this.pendingLargeInput;
|
|
142274
|
+
this.pendingLargeInput = null;
|
|
142275
|
+
this.persistInputHistory(pending);
|
|
142276
|
+
dispatchInput(this.host, pending);
|
|
142277
|
+
this.host.stopMemoryIdleTimer();
|
|
142278
|
+
} else {
|
|
142279
|
+
const pending = this.pendingLargeInput;
|
|
142280
|
+
this.pendingLargeInput = null;
|
|
142281
|
+
this.host.showStatus(t("input.large_cancelled"), this.host.state.theme.colors.textDim);
|
|
142282
|
+
if (answer !== "n" && answer !== "no" && text.trim().length > 0) {
|
|
142283
|
+
this.host.state.editor.setText(pending);
|
|
142284
|
+
this.handleInput(text);
|
|
142285
|
+
} else this.host.state.editor.setText(pending);
|
|
142286
|
+
}
|
|
142287
|
+
return;
|
|
142288
|
+
}
|
|
142219
142289
|
if (text.trim().length === 0) return;
|
|
142220
142290
|
if (this.host.state.appState.isReplaying) {
|
|
142221
142291
|
this.host.showError(t("input.replay_blocked"));
|
|
142222
142292
|
return;
|
|
142223
142293
|
}
|
|
142294
|
+
if (text.length > InputController.LARGE_INPUT_THRESHOLD) {
|
|
142295
|
+
this.pendingLargeInput = text;
|
|
142296
|
+
this.host.showStatus(t("input.large_confirm", { count: text.length }), this.host.state.theme.colors.warning);
|
|
142297
|
+
return;
|
|
142298
|
+
}
|
|
142224
142299
|
this.persistInputHistory(text);
|
|
142225
142300
|
dispatchInput(this.host, text);
|
|
142226
142301
|
this.host.stopMemoryIdleTimer();
|
|
@@ -144110,11 +144185,17 @@ var SessionManager = class {
|
|
|
144110
144185
|
}
|
|
144111
144186
|
if (isBusy(this.host.state.appState)) {
|
|
144112
144187
|
this.host.showError(t("session.switch_streaming"));
|
|
144113
|
-
return {
|
|
144188
|
+
return {
|
|
144189
|
+
switched: false,
|
|
144190
|
+
blocked: true
|
|
144191
|
+
};
|
|
144114
144192
|
}
|
|
144115
144193
|
if (this.host.state.appState.isReplaying) {
|
|
144116
144194
|
this.host.showError(t("session.switch_replaying"));
|
|
144117
|
-
return {
|
|
144195
|
+
return {
|
|
144196
|
+
switched: false,
|
|
144197
|
+
blocked: true
|
|
144198
|
+
};
|
|
144118
144199
|
}
|
|
144119
144200
|
let session;
|
|
144120
144201
|
try {
|
|
@@ -146025,12 +146106,12 @@ var DialogManager = class {
|
|
|
146025
146106
|
const row = this.host.getSessions().find((s) => s.id === pickerId);
|
|
146026
146107
|
const isCc = row?.metadata?.["source"] === "cc-connect";
|
|
146027
146108
|
const realId = isCc ? row.metadata["agentSessionId"] : pickerId;
|
|
146028
|
-
this.host.resumeSession(realId).then(async (switched) => {
|
|
146109
|
+
this.host.resumeSession(realId).then(async ({ switched, blocked }) => {
|
|
146029
146110
|
if (switched) {
|
|
146030
146111
|
this.hideSessionPicker();
|
|
146031
146112
|
return;
|
|
146032
146113
|
}
|
|
146033
|
-
if (isCc) try {
|
|
146114
|
+
if (isCc && blocked !== true) try {
|
|
146034
146115
|
const session = await this.host.harness.createSession({
|
|
146035
146116
|
id: realId,
|
|
146036
146117
|
workDir: this.host.getCurrentWorkDir(),
|
|
@@ -146044,6 +146125,8 @@ var DialogManager = class {
|
|
|
146044
146125
|
} catch {
|
|
146045
146126
|
this.host.showError(t("dialog.create_session_failed"));
|
|
146046
146127
|
}
|
|
146128
|
+
}).catch((error) => {
|
|
146129
|
+
this.host.showError(error instanceof Error ? error.message : String(error));
|
|
146047
146130
|
});
|
|
146048
146131
|
},
|
|
146049
146132
|
onCancel,
|
|
@@ -146056,6 +146139,8 @@ var DialogManager = class {
|
|
|
146056
146139
|
await this.host.fetchSessions();
|
|
146057
146140
|
if (this.host.getSessions().length === 0) this.hideSessionPicker();
|
|
146058
146141
|
else if (this.host.state.activeDialog === "session-picker") this.mountSessionPicker(onCancel);
|
|
146142
|
+
}).catch((error) => {
|
|
146143
|
+
this.host.showError(error instanceof Error ? error.message : String(error));
|
|
146059
146144
|
});
|
|
146060
146145
|
}
|
|
146061
146146
|
}));
|
|
@@ -146630,7 +146715,11 @@ var ScreamTUI = class {
|
|
|
146630
146715
|
this.sessionManager.resetSessionRuntime();
|
|
146631
146716
|
}
|
|
146632
146717
|
async resumeSession(targetSessionId) {
|
|
146633
|
-
|
|
146718
|
+
const result = await this.sessionManager.resumeSession(targetSessionId);
|
|
146719
|
+
return {
|
|
146720
|
+
switched: result.switched,
|
|
146721
|
+
blocked: result.blocked
|
|
146722
|
+
};
|
|
146634
146723
|
}
|
|
146635
146724
|
async switchToSession(session, statusMessage) {
|
|
146636
146725
|
await this.sessionManager.switchToSession(session, statusMessage);
|
|
@@ -146775,6 +146864,8 @@ const SHADOW_CHARS = new Set([
|
|
|
146775
146864
|
const SHEEN_STEP = 4;
|
|
146776
146865
|
const SHEEN_INTERVAL_MS = 60;
|
|
146777
146866
|
const LOADING_DURATION_MS = 1500;
|
|
146867
|
+
const FULL_LOGO_MIN_COLS = 87;
|
|
146868
|
+
const COMPACT_LOGO = ["██▄▄▄██", "▐█▄▀▄█▌"];
|
|
146778
146869
|
const THEME_PRIMARY = {
|
|
146779
146870
|
dark: [
|
|
146780
146871
|
204,
|
|
@@ -146963,7 +147054,9 @@ function supportsAnsi() {
|
|
|
146963
147054
|
}
|
|
146964
147055
|
function runLoadingAnimation(theme = "dark") {
|
|
146965
147056
|
if (!supportsAnsi()) {
|
|
146966
|
-
|
|
147057
|
+
const { cols } = getTerminalSize();
|
|
147058
|
+
if (cols >= FULL_LOGO_MIN_COLS) for (const line of LOGO) stdout.write(`${fg(...LOGO_RGB)}${line}${RESET}\n`);
|
|
147059
|
+
else for (const line of COMPACT_LOGO) stdout.write(`${fg(...BLOCK_RGB)}${line}${RESET}\n`);
|
|
146967
147060
|
stdout.write(`${BOLD}${fg(...THEME_PRIMARY[theme])}${t("loading.waking")}${RESET}\n`);
|
|
146968
147061
|
return Promise.resolve();
|
|
146969
147062
|
}
|
|
@@ -146981,15 +147074,20 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
146981
147074
|
function render() {
|
|
146982
147075
|
const { cols, rows } = getTerminalSize();
|
|
146983
147076
|
const lines = [];
|
|
146984
|
-
const
|
|
147077
|
+
const useFullLogo = cols >= FULL_LOGO_MIN_COLS;
|
|
147078
|
+
const contentHeight = useFullLogo ? LOGO.length + 5 : COMPACT_LOGO.length + 5;
|
|
146985
147079
|
const topPad = Math.max(0, Math.floor((rows - contentHeight) / 2));
|
|
146986
147080
|
for (let i = 0; i < topPad; i++) lines.push("");
|
|
146987
147081
|
const breatheColor = breathePalette[breatheFrame] ?? primary;
|
|
146988
|
-
for (const line of LOGO) {
|
|
147082
|
+
if (useFullLogo) for (const line of LOGO) {
|
|
146989
147083
|
let colored = "";
|
|
146990
147084
|
for (let ci = 0; ci < line.length; ci++) colored += renderSheen(line[ci], ci, sheenPos, isReversing, breatheColor);
|
|
146991
147085
|
lines.push(centerPad(colored, cols));
|
|
146992
147086
|
}
|
|
147087
|
+
else for (const line of COMPACT_LOGO) {
|
|
147088
|
+
const colored = `${fg(...BLOCK_RGB)}${line}${RESET}`;
|
|
147089
|
+
lines.push(centerPad(colored, cols));
|
|
147090
|
+
}
|
|
146993
147091
|
lines.push("");
|
|
146994
147092
|
if (phase === "loading") lines.push(centerPad(renderShimmer(shimmerPulse, breatheColor), cols));
|
|
146995
147093
|
else lines.push(centerPad(`${BOLD}${fg(...breatheColor)}${t("loading.press_enter")}${RESET}`, cols));
|
|
@@ -147046,7 +147144,9 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
147046
147144
|
process$1.off("SIGTERM", interrupt);
|
|
147047
147145
|
stdout.write("\x1B[?25h");
|
|
147048
147146
|
if (process$1.platform !== "win32") stdout.write("\x1B[?1049l");
|
|
147049
|
-
|
|
147147
|
+
const { cols: fallbackCols } = getTerminalSize();
|
|
147148
|
+
if (fallbackCols >= FULL_LOGO_MIN_COLS) for (const line of LOGO) stdout.write(`${fg(...LOGO_RGB)}${line}${RESET}\n`);
|
|
147149
|
+
else for (const line of COMPACT_LOGO) stdout.write(`${fg(...BLOCK_RGB)}${line}${RESET}\n`);
|
|
147050
147150
|
stdout.write(`${BOLD}${fg(...primary)}${t("loading.waking")}${RESET}\n`);
|
|
147051
147151
|
resolve();
|
|
147052
147152
|
return;
|
|
@@ -147700,6 +147800,27 @@ async function runStreamJson(opts) {
|
|
|
147700
147800
|
hasAppendPrompt: appendPrompt.length > 0
|
|
147701
147801
|
});
|
|
147702
147802
|
}
|
|
147803
|
+
let cleaned = false;
|
|
147804
|
+
const runCleanup = async () => {
|
|
147805
|
+
if (cleaned) return;
|
|
147806
|
+
cleaned = true;
|
|
147807
|
+
for (const [, pending] of pendingApprovals) pending.resolve({
|
|
147808
|
+
decision: "rejected",
|
|
147809
|
+
feedback: "会话已结束"
|
|
147810
|
+
});
|
|
147811
|
+
pendingApprovals.clear();
|
|
147812
|
+
if (currentSessionId) writer.emitResumeHint(sessionKey);
|
|
147813
|
+
try {
|
|
147814
|
+
if (session) await session.close();
|
|
147815
|
+
await harness.close();
|
|
147816
|
+
} catch {}
|
|
147817
|
+
if (injectedAgentsMd) try {
|
|
147818
|
+
if (originalAgentsMd === void 0) {
|
|
147819
|
+
if (existsSync(agentsMdPath)) unlinkSync(agentsMdPath);
|
|
147820
|
+
} else writeFileSync(agentsMdPath, originalAgentsMd, "utf-8");
|
|
147821
|
+
} catch {}
|
|
147822
|
+
};
|
|
147823
|
+
const uninstallTerminationHandlers = installStreamJsonTerminationHandlers(runCleanup);
|
|
147703
147824
|
try {
|
|
147704
147825
|
await harness.ensureConfigFile();
|
|
147705
147826
|
const config = await harness.getConfig();
|
|
@@ -147934,7 +148055,7 @@ async function runStreamJson(opts) {
|
|
|
147934
148055
|
});
|
|
147935
148056
|
session.prompt(userText).catch((error) => {
|
|
147936
148057
|
const msg = error instanceof Error ? error.message : String(error);
|
|
147937
|
-
if (msg.includes("insufficient tool messages") || msg.includes("tool_calls")) {
|
|
148058
|
+
if (msg.includes("insufficient tool messages") || msg.includes("tool_calls") && msg.includes("followed by tool messages")) {
|
|
147938
148059
|
log.warn("stream-json: resetting session after tool call mismatch", {
|
|
147939
148060
|
sessionId: session?.id,
|
|
147940
148061
|
error: msg
|
|
@@ -147952,7 +148073,9 @@ async function runStreamJson(opts) {
|
|
|
147952
148073
|
}
|
|
147953
148074
|
finish(error instanceof Error ? error : new Error(msg));
|
|
147954
148075
|
});
|
|
147955
|
-
|
|
148076
|
+
try {
|
|
148077
|
+
await turnPromise;
|
|
148078
|
+
} catch {}
|
|
147956
148079
|
}
|
|
147957
148080
|
} catch (error) {
|
|
147958
148081
|
if (process.exitCode === void 0) {
|
|
@@ -147961,23 +148084,35 @@ async function runStreamJson(opts) {
|
|
|
147961
148084
|
process.exitCode = 1;
|
|
147962
148085
|
} else log.error("stream-json: turn error (exitCode already set)", { error });
|
|
147963
148086
|
} finally {
|
|
147964
|
-
|
|
147965
|
-
|
|
147966
|
-
feedback: "会话已结束"
|
|
147967
|
-
});
|
|
147968
|
-
pendingApprovals.clear();
|
|
147969
|
-
if (currentSessionId) writer.emitResumeHint(sessionKey);
|
|
147970
|
-
try {
|
|
147971
|
-
if (session) await session.close();
|
|
147972
|
-
await harness.close();
|
|
147973
|
-
} catch {}
|
|
147974
|
-
if (injectedAgentsMd) try {
|
|
147975
|
-
if (originalAgentsMd === void 0) {
|
|
147976
|
-
if (existsSync(agentsMdPath)) unlinkSync(agentsMdPath);
|
|
147977
|
-
} else writeFileSync(agentsMdPath, originalAgentsMd, "utf-8");
|
|
147978
|
-
} catch {}
|
|
148087
|
+
uninstallTerminationHandlers();
|
|
148088
|
+
await runCleanup();
|
|
147979
148089
|
}
|
|
147980
148090
|
}
|
|
148091
|
+
/** Install termination handlers so we can clean up on SIGINT / SIGTERM. */
|
|
148092
|
+
function installStreamJsonTerminationHandlers(cleanup) {
|
|
148093
|
+
let terminating = false;
|
|
148094
|
+
const handler = async (signal) => {
|
|
148095
|
+
if (terminating) return;
|
|
148096
|
+
terminating = true;
|
|
148097
|
+
try {
|
|
148098
|
+
await cleanup();
|
|
148099
|
+
} finally {
|
|
148100
|
+
process.exit(signal === "SIGINT" ? 130 : 143);
|
|
148101
|
+
}
|
|
148102
|
+
};
|
|
148103
|
+
const onSigint = () => {
|
|
148104
|
+
handler("SIGINT");
|
|
148105
|
+
};
|
|
148106
|
+
const onSigterm = () => {
|
|
148107
|
+
handler("SIGTERM");
|
|
148108
|
+
};
|
|
148109
|
+
process.once("SIGINT", onSigint);
|
|
148110
|
+
process.once("SIGTERM", onSigterm);
|
|
148111
|
+
return () => {
|
|
148112
|
+
process.off("SIGINT", onSigint);
|
|
148113
|
+
process.off("SIGTERM", onSigterm);
|
|
148114
|
+
};
|
|
148115
|
+
}
|
|
147981
148116
|
//#endregion
|
|
147982
148117
|
//#region src/cli/startup-error.ts
|
|
147983
148118
|
function formatUnknownErrorMessage(error) {
|
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-DVRLAZ8b.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);
|
|
@@ -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 { n as multiSearchWithTrace } from "./src-
|
|
6
|
+
import { n as multiSearchWithTrace } from "./src-oeUnRY3N.mjs";
|
|
7
7
|
export { multiSearchWithTrace };
|
|
@@ -214,7 +214,10 @@ var KnowledgeStore = class {
|
|
|
214
214
|
}
|
|
215
215
|
async init() {
|
|
216
216
|
if (this.initPromise) return this.initPromise;
|
|
217
|
-
this.initPromise = this._doInit()
|
|
217
|
+
this.initPromise = this._doInit().catch((error) => {
|
|
218
|
+
this.initPromise = null;
|
|
219
|
+
throw error;
|
|
220
|
+
});
|
|
218
221
|
return this.initPromise;
|
|
219
222
|
}
|
|
220
223
|
async _doInit() {
|
|
@@ -225,8 +228,32 @@ var KnowledgeStore = class {
|
|
|
225
228
|
this.db.exec("PRAGMA foreign_keys = ON;");
|
|
226
229
|
this.db.exec("PRAGMA busy_timeout = 5000;");
|
|
227
230
|
this.createSchema();
|
|
231
|
+
this.migrateFtsTokenization();
|
|
228
232
|
this.initialized = true;
|
|
229
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* One-time migration: FTS rows written before toFtsText pre-tokenization
|
|
236
|
+
* indexed raw text (CJK runs became single tokens and are unsearchable).
|
|
237
|
+
* Rebuild all three FTS tables from the content tables with toFtsText.
|
|
238
|
+
* Tracked via PRAGMA user_version so it runs exactly once.
|
|
239
|
+
*/
|
|
240
|
+
migrateFtsTokenization() {
|
|
241
|
+
if (this.db === void 0) return;
|
|
242
|
+
if (this.db.prepare("PRAGMA user_version").get().user_version >= 1) return;
|
|
243
|
+
this.db.exec("DELETE FROM knowledge_chunks_fts");
|
|
244
|
+
this.db.exec("DELETE FROM knowledge_events_fts");
|
|
245
|
+
this.db.exec("DELETE FROM knowledge_entities_fts");
|
|
246
|
+
const chunks = this.db.prepare("SELECT rowid, heading, content FROM knowledge_chunks").all();
|
|
247
|
+
const insChunk = this.db.prepare("INSERT INTO knowledge_chunks_fts (rowid, heading, content) VALUES (?, ?, ?)");
|
|
248
|
+
for (const c of chunks) insChunk.run(c.rowid, toFtsText(c.heading ?? ""), toFtsText(c.content));
|
|
249
|
+
const events = this.db.prepare("SELECT rowid, title, summary, content FROM knowledge_events").all();
|
|
250
|
+
const insEvent = this.db.prepare("INSERT INTO knowledge_events_fts (rowid, title, summary, content) VALUES (?, ?, ?, ?)");
|
|
251
|
+
for (const e of events) insEvent.run(e.rowid, toFtsText(e.title), toFtsText(e.summary ?? ""), toFtsText(e.content));
|
|
252
|
+
const entities = this.db.prepare("SELECT rowid, name, description FROM knowledge_entities").all();
|
|
253
|
+
const insEntity = this.db.prepare("INSERT INTO knowledge_entities_fts (rowid, name, description) VALUES (?, ?, ?)");
|
|
254
|
+
for (const e of entities) insEntity.run(e.rowid, toFtsText(e.name), toFtsText(e.description ?? ""));
|
|
255
|
+
this.db.exec("PRAGMA user_version = 1");
|
|
256
|
+
}
|
|
230
257
|
close() {
|
|
231
258
|
if (this.db !== void 0) {
|
|
232
259
|
this.db.exec("PRAGMA wal_checkpoint(TRUNCATE)");
|
|
@@ -392,7 +419,19 @@ var KnowledgeStore = class {
|
|
|
392
419
|
async deleteSource(id) {
|
|
393
420
|
await this.init();
|
|
394
421
|
if (this.db === void 0) return false;
|
|
395
|
-
|
|
422
|
+
const chunkRows = this.db.prepare("SELECT rowid, heading, content FROM knowledge_chunks WHERE source_id = ?").all(id);
|
|
423
|
+
const eventRows = this.db.prepare("SELECT rowid, title, summary, content FROM knowledge_events WHERE source_id = ?").all(id);
|
|
424
|
+
const entityRows = this.db.prepare("SELECT rowid, name, description FROM knowledge_entities WHERE source_id = ?").all(id);
|
|
425
|
+
const result = this.db.prepare("DELETE FROM knowledge_sources WHERE id = ?").run(id);
|
|
426
|
+
if (result.changes > 0) {
|
|
427
|
+
const delChunk = this.db.prepare("INSERT INTO knowledge_chunks_fts (knowledge_chunks_fts, rowid, heading, content) VALUES ('delete', ?, ?, ?)");
|
|
428
|
+
for (const row of chunkRows) delChunk.run(row.rowid, toFtsText(row.heading ?? ""), toFtsText(row.content));
|
|
429
|
+
const delEvent = this.db.prepare("INSERT INTO knowledge_events_fts (knowledge_events_fts, rowid, title, summary, content) VALUES ('delete', ?, ?, ?, ?)");
|
|
430
|
+
for (const row of eventRows) delEvent.run(row.rowid, toFtsText(row.title), toFtsText(row.summary ?? ""), toFtsText(row.content));
|
|
431
|
+
const delEntity = this.db.prepare("INSERT INTO knowledge_entities_fts (knowledge_entities_fts, rowid, name, description) VALUES ('delete', ?, ?, ?)");
|
|
432
|
+
for (const row of entityRows) delEntity.run(row.rowid, toFtsText(row.name), toFtsText(row.description ?? ""));
|
|
433
|
+
}
|
|
434
|
+
return result.changes > 0;
|
|
396
435
|
}
|
|
397
436
|
async createDocument(params) {
|
|
398
437
|
if (this.db === void 0) throw new Error("knowledge store not initialized");
|
|
@@ -440,7 +479,7 @@ var KnowledgeStore = class {
|
|
|
440
479
|
(id, source_id, document_id, rank, heading, content, raw_content, embedding_json, created_at)
|
|
441
480
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, params.sourceId, params.documentId, params.rank, params.heading, params.content, params.rawContent, embeddingJson, createdAt);
|
|
442
481
|
this.db.prepare(`INSERT INTO knowledge_chunks_fts (rowid, heading, content)
|
|
443
|
-
VALUES ((SELECT rowid FROM knowledge_chunks WHERE id = ?), ?, ?)`).run(id, params.heading ?? "", params.content);
|
|
482
|
+
VALUES ((SELECT rowid FROM knowledge_chunks WHERE id = ?), ?, ?)`).run(id, toFtsText(params.heading ?? ""), toFtsText(params.content));
|
|
444
483
|
return {
|
|
445
484
|
id,
|
|
446
485
|
sourceId: params.sourceId,
|
|
@@ -488,7 +527,7 @@ var KnowledgeStore = class {
|
|
|
488
527
|
title_embedding_json, content_embedding_json, created_at)
|
|
489
528
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, params.sourceId, params.documentId, params.chunkId, params.rank, params.title, params.summary, params.content, params.category, JSON.stringify(params.keywords), vectorToJson(params.titleEmbedding), vectorToJson(params.contentEmbedding), createdAt);
|
|
490
529
|
this.db.prepare(`INSERT INTO knowledge_events_fts (rowid, title, summary, content)
|
|
491
|
-
VALUES ((SELECT rowid FROM knowledge_events WHERE id = ?), ?, ?, ?)`).run(id, params.title, params.summary ?? "", params.content);
|
|
530
|
+
VALUES ((SELECT rowid FROM knowledge_events WHERE id = ?), ?, ?, ?)`).run(id, toFtsText(params.title), toFtsText(params.summary ?? ""), toFtsText(params.content));
|
|
492
531
|
return {
|
|
493
532
|
id,
|
|
494
533
|
sourceId: params.sourceId,
|
|
@@ -551,8 +590,24 @@ var KnowledgeStore = class {
|
|
|
551
590
|
const normalizedName = normalizeName(params.name);
|
|
552
591
|
const existing = this.db.prepare("SELECT * FROM knowledge_entities WHERE source_id = ? AND type = ? AND normalized_name = ?").get(params.sourceId, params.type, normalizedName);
|
|
553
592
|
if (existing !== void 0) {
|
|
554
|
-
|
|
555
|
-
|
|
593
|
+
const existingId = String(existing["id"]);
|
|
594
|
+
let descriptionChanged = false;
|
|
595
|
+
if (params.description !== null && existing["description"] === null) {
|
|
596
|
+
this.db.prepare("UPDATE knowledge_entities SET description = ? WHERE id = ?").run(params.description, existingId);
|
|
597
|
+
existing["description"] = params.description;
|
|
598
|
+
descriptionChanged = true;
|
|
599
|
+
}
|
|
600
|
+
if (params.embedding !== null && existing["embedding_json"] === null) {
|
|
601
|
+
this.db.prepare("UPDATE knowledge_entities SET embedding_json = ? WHERE id = ?").run(vectorToJson(params.embedding), existingId);
|
|
602
|
+
existing["embedding_json"] = vectorToJson(params.embedding);
|
|
603
|
+
}
|
|
604
|
+
if (descriptionChanged) {
|
|
605
|
+
const ftsRow = this.db.prepare("SELECT rowid, name, description FROM knowledge_entities WHERE id = ?").get(existingId);
|
|
606
|
+
if (ftsRow !== void 0) {
|
|
607
|
+
this.db.prepare("INSERT INTO knowledge_entities_fts (knowledge_entities_fts, rowid, name, description) VALUES ('delete', ?, ?, ?)").run(ftsRow.rowid, toFtsText(ftsRow.name), "");
|
|
608
|
+
this.db.prepare(`INSERT INTO knowledge_entities_fts (rowid, name, description) VALUES (?, ?, ?)`).run(ftsRow.rowid, toFtsText(ftsRow.name), toFtsText(ftsRow.description ?? ""));
|
|
609
|
+
}
|
|
610
|
+
}
|
|
556
611
|
return rowToEntity(existing);
|
|
557
612
|
}
|
|
558
613
|
const id = generateId("ent");
|
|
@@ -561,7 +616,7 @@ var KnowledgeStore = class {
|
|
|
561
616
|
(id, source_id, type, name, normalized_name, description, embedding_json, created_at)
|
|
562
617
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(id, params.sourceId, params.type, params.name, normalizedName, params.description, vectorToJson(params.embedding), createdAt);
|
|
563
618
|
this.db.prepare(`INSERT INTO knowledge_entities_fts (rowid, name, description)
|
|
564
|
-
VALUES ((SELECT rowid FROM knowledge_entities WHERE id = ?), ?, ?)`).run(id, params.name, params.description ?? "");
|
|
619
|
+
VALUES ((SELECT rowid FROM knowledge_entities WHERE id = ?), ?, ?)`).run(id, toFtsText(params.name), toFtsText(params.description ?? ""));
|
|
565
620
|
return {
|
|
566
621
|
id,
|
|
567
622
|
sourceId: params.sourceId,
|
|
@@ -209,6 +209,8 @@ const dictionaries = {
|
|
|
209
209
|
"input.replay_blocked": "会话历史正在回放时无法发送输入。",
|
|
210
210
|
"input.send_failed": "发送失败:{message}",
|
|
211
211
|
"input.guide_failed": "引导失败:{message}",
|
|
212
|
+
"input.large_confirm": "输入内容为 {count} 字符,确认发送?(y/n)",
|
|
213
|
+
"input.large_cancelled": "输入已取消。",
|
|
212
214
|
"welcome.config": "/config 配置模型",
|
|
213
215
|
"welcome.sessions": "/sessions 恢复历史会话",
|
|
214
216
|
"welcome.quick_menu": "/ 输入后打开快捷菜单",
|
|
@@ -1241,6 +1243,8 @@ const dictionaries = {
|
|
|
1241
1243
|
"input.replay_blocked": "Cannot send input while session history is replaying.",
|
|
1242
1244
|
"input.send_failed": "Send failed: {message}",
|
|
1243
1245
|
"input.guide_failed": "Guide failed: {message}",
|
|
1246
|
+
"input.large_confirm": "Input is {count} characters. Send anyway? (y/n)",
|
|
1247
|
+
"input.large_cancelled": "Input cancelled.",
|
|
1244
1248
|
"welcome.config": "/config Configure model",
|
|
1245
1249
|
"welcome.sessions": "/sessions Resume session",
|
|
1246
1250
|
"welcome.quick_menu": "/ Open quick menu",
|
|
@@ -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 { t as TextInputDialogComponent } from "./text-input-dialog-
|
|
6
|
+
import { t as TextInputDialogComponent } from "./text-input-dialog-D_xK0DJH.mjs";
|
|
7
7
|
export { TextInputDialogComponent };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scream-code",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "A terminal-native AI agent for builders",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ScreamCli",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"smoke": "node dist/main.mjs --version"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@liutod-scream/pi-tui": "^0.80.
|
|
60
|
+
"@liutod-scream/pi-tui": "^0.80.13",
|
|
61
61
|
"@mariozechner/clipboard": "^0.3.2",
|
|
62
62
|
"chalk": "^5.4.1",
|
|
63
63
|
"cli-highlight": "^2.1.11",
|