scream-code 0.15.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-CPu6R7nd.mjs → app-6Hcxs2tP.mjs} +607 -9
- package/dist/{dispatch-D8ovLbmr.mjs → dispatch-B_ViYZer.mjs} +113 -10
- package/dist/{dispatch-BPcn43Vw.mjs → dispatch-Dur5jHVw.mjs} +1 -1
- package/dist/main.mjs +1 -1
- package/dist/public/assets/index-B9I4PIWR.js +93 -0
- package/dist/public/assets/index-B9I4PIWR.js.map +1 -0
- package/dist/public/index.html +1 -1
- package/package.json +1 -1
- package/dist/public/assets/index-CYmwuyd8.js +0 -93
- package/dist/public/assets/index-CYmwuyd8.js.map +0 -1
|
@@ -34205,14 +34205,27 @@ function convertMediaUrl(url, fallbackMimeType) {
|
|
|
34205
34205
|
function createAbortError() {
|
|
34206
34206
|
return new DOMException("The operation was aborted.", "AbortError");
|
|
34207
34207
|
}
|
|
34208
|
-
|
|
34209
|
-
|
|
34208
|
+
/**
|
|
34209
|
+
* Race async work against an abort signal, ALWAYS detaching the listener.
|
|
34210
|
+
* The Google GenAI SDK does not accept an AbortSignal, so callers race the
|
|
34211
|
+
* SDK call against the signal manually. A bare `addEventListener({ once })`
|
|
34212
|
+
* inside a losing promise leaks the listener on the caller's signal for the
|
|
34213
|
+
* rest of its lifetime - with a session-scoped signal that accumulates one
|
|
34214
|
+
* listener per request. This wrapper guarantees cleanup in both outcomes.
|
|
34215
|
+
*/
|
|
34216
|
+
async function abortRace(signal, work) {
|
|
34217
|
+
if (signal === void 0) return work;
|
|
34210
34218
|
if (signal.aborted) throw createAbortError();
|
|
34211
|
-
|
|
34212
|
-
|
|
34213
|
-
|
|
34214
|
-
|
|
34219
|
+
let onAbort = void 0;
|
|
34220
|
+
const abortPromise = new Promise((_, reject) => {
|
|
34221
|
+
onAbort = () => reject(createAbortError());
|
|
34222
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
34215
34223
|
});
|
|
34224
|
+
try {
|
|
34225
|
+
return await Promise.race([work, abortPromise]);
|
|
34226
|
+
} finally {
|
|
34227
|
+
if (onAbort !== void 0) signal.removeEventListener("abort", onAbort);
|
|
34228
|
+
}
|
|
34216
34229
|
}
|
|
34217
34230
|
function messageToGoogleGenAI(message) {
|
|
34218
34231
|
if (message.role === "tool") throw new ChatProviderError("Tool messages must be converted via messagesToGoogleGenAIContents.");
|
|
@@ -34582,8 +34595,8 @@ var GoogleGenAIChatProvider = class {
|
|
|
34582
34595
|
contents,
|
|
34583
34596
|
config
|
|
34584
34597
|
};
|
|
34585
|
-
if (this._stream) return new GoogleGenAIStreamedMessage(await
|
|
34586
|
-
return new GoogleGenAIStreamedMessage(await
|
|
34598
|
+
if (this._stream) return new GoogleGenAIStreamedMessage(await abortRace(options?.signal, models.generateContentStream(params)), true, options?.signal);
|
|
34599
|
+
return new GoogleGenAIStreamedMessage(await abortRace(options?.signal, models.generateContent(params)), false, options?.signal);
|
|
34587
34600
|
} catch (error) {
|
|
34588
34601
|
if (error instanceof DOMException && error.name === "AbortError") throw error;
|
|
34589
34602
|
throw convertGoogleGenAIError(error);
|
|
@@ -53403,6 +53416,17 @@ var MemoryMemoStore = class MemoryMemoStore {
|
|
|
53403
53416
|
async append(entry) {
|
|
53404
53417
|
return this.withWriteLock(() => this.appendInternal(entry));
|
|
53405
53418
|
}
|
|
53419
|
+
/**
|
|
53420
|
+
* True when a memo with the same source session + user need + approach
|
|
53421
|
+
* already exists. Used by compaction-summary recovery to re-store memos
|
|
53422
|
+
* idempotently after a crash between compaction apply and extraction.
|
|
53423
|
+
* The approach field keeps two distinct memos that happen to share the
|
|
53424
|
+
* same user need from being collapsed into one.
|
|
53425
|
+
*/
|
|
53426
|
+
existsBySourceAndNeed(sourceSessionId, userNeed, approach) {
|
|
53427
|
+
if (this.db === void 0) return false;
|
|
53428
|
+
return this.db.prepare("SELECT 1 FROM memos WHERE source_session_id = ? AND user_need = ? AND approach = ? LIMIT 1").get(sourceSessionId, userNeed, approach) !== void 0;
|
|
53429
|
+
}
|
|
53406
53430
|
/** Delete a memo by id. */
|
|
53407
53431
|
async delete(id) {
|
|
53408
53432
|
return this.withWriteLock(() => this.deleteInternal(id));
|
|
@@ -79164,6 +79188,31 @@ function extractPreviousSummary(history) {
|
|
|
79164
79188
|
const text = head.content.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
79165
79189
|
return text.length > 0 ? text : null;
|
|
79166
79190
|
}
|
|
79191
|
+
/**
|
|
79192
|
+
* Crash-recovery path for compaction memos. `context.apply_compaction` is
|
|
79193
|
+
* written to wire before the extraction step runs; if the process dies in
|
|
79194
|
+
* that window the memos are lost forever (nothing re-extracts them). On wire
|
|
79195
|
+
* replay the summary is available again, so re-parse it and store anything
|
|
79196
|
+
* missing. Idempotent: a healthy replay finds the memos already stored
|
|
79197
|
+
* (existsBySourceAndNeed) and skips them, so recovery never duplicates.
|
|
79198
|
+
*/
|
|
79199
|
+
async function recoverMemosFromCompactionSummary(agent, summary) {
|
|
79200
|
+
const memoStore = agent.memoStore;
|
|
79201
|
+
if (!memoStore || summary === void 0 || summary.trim().length === 0) return;
|
|
79202
|
+
const memos = parseMemoryMemos(summary);
|
|
79203
|
+
if (memos.length === 0) return;
|
|
79204
|
+
const sessionId = agent.homedir ? basename$1(dirname$2(dirname$2(agent.homedir))) : "unknown";
|
|
79205
|
+
const sessionTitle = await agent.getSessionTitle().catch(() => void 0);
|
|
79206
|
+
const projectDir = agent.config.cwd;
|
|
79207
|
+
const failed = (await Promise.allSettled(memos.map(async (memo) => {
|
|
79208
|
+
if (memoStore.existsBySourceAndNeed(sessionId, memo.userNeed, memo.approach)) return;
|
|
79209
|
+
memo.sourceSessionId = sessionId;
|
|
79210
|
+
memo.sourceSessionTitle = sessionTitle ?? "";
|
|
79211
|
+
memo.projectDir = projectDir;
|
|
79212
|
+
await memoStore.append(memo);
|
|
79213
|
+
}))).filter((result) => result.status === "rejected").length;
|
|
79214
|
+
if (failed > 0) agent.log.warn("Some recovered memory memos failed to store", { failed });
|
|
79215
|
+
}
|
|
79167
79216
|
//#endregion
|
|
79168
79217
|
//#region ../../packages/agent-core/src/flags/registry.ts
|
|
79169
79218
|
/**
|
|
@@ -84844,6 +84893,7 @@ var FileSystemAgentRecordPersistence = class {
|
|
|
84844
84893
|
pendingRecords = [];
|
|
84845
84894
|
shouldClear = false;
|
|
84846
84895
|
directorySynced = false;
|
|
84896
|
+
rewriteSeq = 0;
|
|
84847
84897
|
flushPromise;
|
|
84848
84898
|
error;
|
|
84849
84899
|
constructor(filePath, options = {}) {
|
|
@@ -84953,7 +85003,21 @@ var FileSystemAgentRecordPersistence = class {
|
|
|
84953
85003
|
const content = (this.options.blobStore !== void 0 ? await Promise.all(batch.map((record) => this.options.blobStore.offload(record))) : batch).map((e) => JSON.stringify(e) + "\n").join("");
|
|
84954
85004
|
const directory = dirname$2(this.filePath);
|
|
84955
85005
|
await mkdir(directory, { recursive: true });
|
|
84956
|
-
|
|
85006
|
+
if (shouldClear) {
|
|
85007
|
+
const tmpPath = `${this.filePath}.${process.pid}.${this.rewriteSeq++}.tmp`;
|
|
85008
|
+
const tmp = await open(tmpPath, "w");
|
|
85009
|
+
try {
|
|
85010
|
+
if (content.length > 0) await tmp.writeFile(content, "utf8");
|
|
85011
|
+
await tmp.sync();
|
|
85012
|
+
} finally {
|
|
85013
|
+
await tmp.close();
|
|
85014
|
+
}
|
|
85015
|
+
await rename(tmpPath, this.filePath);
|
|
85016
|
+
await syncDir(directory);
|
|
85017
|
+
this.directorySynced = true;
|
|
85018
|
+
return;
|
|
85019
|
+
}
|
|
85020
|
+
const fh = await open(this.filePath, "a");
|
|
84957
85021
|
try {
|
|
84958
85022
|
if (content.length > 0) await fh.writeFile(content, "utf8");
|
|
84959
85023
|
await fh.sync();
|
|
@@ -85310,6 +85374,7 @@ function restoreAgentRecord(agent, input) {
|
|
|
85310
85374
|
return;
|
|
85311
85375
|
case "context.apply_compaction":
|
|
85312
85376
|
agent.context.applyCompaction(input);
|
|
85377
|
+
recoverMemosFromCompactionSummary(agent, input.summary);
|
|
85313
85378
|
return;
|
|
85314
85379
|
case "context.snapshot":
|
|
85315
85380
|
agent.context.restoreJSONSnapshot(input.snapshot);
|
|
@@ -85406,11 +85471,19 @@ var AgentRecords = class {
|
|
|
85406
85471
|
snapshotIndex = i;
|
|
85407
85472
|
break;
|
|
85408
85473
|
}
|
|
85474
|
+
let foldedCompactionSummary;
|
|
85409
85475
|
for (let i = 0; i < replayedRecords.length; i++) {
|
|
85410
85476
|
const record = replayedRecords[i];
|
|
85411
85477
|
if (!record) continue;
|
|
85412
|
-
if (i < snapshotIndex && isSnapshotFoldedContextRecord(record.type))
|
|
85478
|
+
if (i < snapshotIndex && isSnapshotFoldedContextRecord(record.type)) {
|
|
85479
|
+
if (record.type === "context.apply_compaction") foldedCompactionSummary = record.summary;
|
|
85480
|
+
continue;
|
|
85481
|
+
}
|
|
85413
85482
|
this.restore(record);
|
|
85483
|
+
if (record.type === "context.snapshot" && foldedCompactionSummary !== void 0) {
|
|
85484
|
+
recoverMemosFromCompactionSummary(this.agent, foldedCompactionSummary);
|
|
85485
|
+
foldedCompactionSummary = void 0;
|
|
85486
|
+
}
|
|
85414
85487
|
}
|
|
85415
85488
|
this.agent.context.dropVacuousOpenMessages();
|
|
85416
85489
|
if (shouldRewrite) {
|
|
@@ -105566,6 +105639,9 @@ var SessionSubagentHost = class {
|
|
|
105566
105639
|
backgroundTaskTimeoutMs;
|
|
105567
105640
|
modelBindings;
|
|
105568
105641
|
activeChildren = /* @__PURE__ */ new Map();
|
|
105642
|
+
/** Per-child per-model usage already folded into the parent totals, so a
|
|
105643
|
+
* resumed child's aggregation only adds the delta. */
|
|
105644
|
+
aggregatedChildUsage = /* @__PURE__ */ new WeakMap();
|
|
105569
105645
|
constructor(session, ownerAgentId, backgroundTaskTimeoutMs, modelBindings) {
|
|
105570
105646
|
this.session = session;
|
|
105571
105647
|
this.ownerAgentId = ownerAgentId;
|
|
@@ -105709,6 +105785,21 @@ var SessionSubagentHost = class {
|
|
|
105709
105785
|
result = lastAssistantText$1(child);
|
|
105710
105786
|
}
|
|
105711
105787
|
const usage = child.usage.data().total;
|
|
105788
|
+
const childByModel = child.usage.data().byModel ?? {};
|
|
105789
|
+
const previous = this.aggregatedChildUsage.get(child) ?? {};
|
|
105790
|
+
for (const [model, childUsage] of Object.entries(childByModel)) {
|
|
105791
|
+
const delta = previous[model] === void 0 ? childUsage : subtractUsage(childUsage, previous[model]);
|
|
105792
|
+
if (isZeroUsage(delta)) continue;
|
|
105793
|
+
try {
|
|
105794
|
+
parent.usage.record(model, delta, "session");
|
|
105795
|
+
} catch (error) {
|
|
105796
|
+
parent.log.warn("Failed to aggregate subagent usage", {
|
|
105797
|
+
model,
|
|
105798
|
+
error: String(error)
|
|
105799
|
+
});
|
|
105800
|
+
}
|
|
105801
|
+
}
|
|
105802
|
+
this.aggregatedChildUsage.set(child, childByModel);
|
|
105712
105803
|
let findingsBlock = "";
|
|
105713
105804
|
if (profileName === "reviewer") {
|
|
105714
105805
|
const findings = getFindingsFromStore(child.tools.toolStore);
|
|
@@ -105813,6 +105904,18 @@ var SessionSubagentHost = class {
|
|
|
105813
105904
|
});
|
|
105814
105905
|
}
|
|
105815
105906
|
};
|
|
105907
|
+
/** Element-wise subtraction clamped at zero (usage can never go negative). */
|
|
105908
|
+
function subtractUsage(current, previous) {
|
|
105909
|
+
return {
|
|
105910
|
+
inputOther: Math.max(0, current.inputOther - previous.inputOther),
|
|
105911
|
+
output: Math.max(0, current.output - previous.output),
|
|
105912
|
+
inputCacheRead: Math.max(0, current.inputCacheRead - previous.inputCacheRead),
|
|
105913
|
+
inputCacheCreation: Math.max(0, current.inputCacheCreation - previous.inputCacheCreation)
|
|
105914
|
+
};
|
|
105915
|
+
}
|
|
105916
|
+
function isZeroUsage(usage) {
|
|
105917
|
+
return usage.inputOther === 0 && usage.output === 0 && usage.inputCacheRead === 0 && usage.inputCacheCreation === 0;
|
|
105918
|
+
}
|
|
105816
105919
|
async function runChildTurnToCompletion(child, signal) {
|
|
105817
105920
|
const completion = await child.turn.waitForCurrentTurn(signal);
|
|
105818
105921
|
const turnEnded = completion.event;
|
|
@@ -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-B_ViYZer.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-6Hcxs2tP.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);
|