scream-code 0.13.5 → 0.13.7
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-D0fX3NI6.mjs → app-BEHboK6l.mjs} +79 -20
- package/dist/{dispatch-By74xa3A.mjs → dispatch-B6d7chu6.mjs} +602 -272
- package/dist/{dispatch-BpgfQJj-.mjs → dispatch-BPrqxTsP.mjs} +1 -1
- package/dist/main.mjs +1 -1
- package/dist/public/assets/index-CopRDlgZ.js +90 -0
- package/dist/public/assets/index-CopRDlgZ.js.map +1 -0
- package/dist/public/assets/index-CyGAkekh.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/{text-input-dialog-CYs9xQZi.mjs → text-input-dialog-D8QuZFfe.mjs} +1 -1
- package/dist/{text-input-dialog-ClcJf9pu.mjs → text-input-dialog-DstXBOl9.mjs} +4 -4
- package/package.json +1 -1
- package/dist/public/assets/index-CNfl6ZCL.css +0 -1
- package/dist/public/assets/index-D4xKtk0T.js +0 -90
- package/dist/public/assets/index-D4xKtk0T.js.map +0 -1
|
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
|
|
|
6
6
|
import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } from "./chunk-D90kvbyJ.mjs";
|
|
7
7
|
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-BH9W5k24.mjs";
|
|
8
8
|
import { t as require_base64_js } from "./base64-js-DzVmk6Nb.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-
|
|
9
|
+
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-DstXBOl9.mjs";
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
11
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
12
12
|
import * as fs$1 from "node:fs/promises";
|
|
@@ -9270,7 +9270,8 @@ var AnthropicChatProvider = class {
|
|
|
9270
9270
|
return new Anthropic({
|
|
9271
9271
|
apiKey,
|
|
9272
9272
|
baseURL: this._baseUrl,
|
|
9273
|
-
defaultHeaders: this._defaultHeaders
|
|
9273
|
+
defaultHeaders: this._defaultHeaders,
|
|
9274
|
+
maxRetries: 0
|
|
9274
9275
|
});
|
|
9275
9276
|
}
|
|
9276
9277
|
withThinking(effort) {
|
|
@@ -44625,7 +44626,8 @@ var ScreamFiles = class {
|
|
|
44625
44626
|
this._client = options.apiKey === void 0 || options.apiKey.length === 0 ? void 0 : new OpenAI({
|
|
44626
44627
|
apiKey: options.apiKey,
|
|
44627
44628
|
baseURL: options.baseUrl,
|
|
44628
|
-
defaultHeaders: options.defaultHeaders
|
|
44629
|
+
defaultHeaders: options.defaultHeaders,
|
|
44630
|
+
maxRetries: 0
|
|
44629
44631
|
});
|
|
44630
44632
|
}
|
|
44631
44633
|
/**
|
|
@@ -44684,7 +44686,8 @@ var ScreamFiles = class {
|
|
|
44684
44686
|
return new OpenAI({
|
|
44685
44687
|
apiKey: requireProviderApiKey("ScreamFiles.uploadVideo", a, this._apiKey),
|
|
44686
44688
|
baseURL: this._baseUrl,
|
|
44687
|
-
defaultHeaders
|
|
44689
|
+
defaultHeaders,
|
|
44690
|
+
maxRetries: 0
|
|
44688
44691
|
});
|
|
44689
44692
|
});
|
|
44690
44693
|
}
|
|
@@ -44953,7 +44956,8 @@ var ScreamChatProvider = class {
|
|
|
44953
44956
|
this._client = this._apiKey === void 0 ? void 0 : new OpenAI({
|
|
44954
44957
|
apiKey: this._apiKey,
|
|
44955
44958
|
baseURL: this._baseUrl,
|
|
44956
|
-
defaultHeaders: this._defaultHeaders
|
|
44959
|
+
defaultHeaders: this._defaultHeaders,
|
|
44960
|
+
maxRetries: 0
|
|
44957
44961
|
});
|
|
44958
44962
|
}
|
|
44959
44963
|
get modelName() {
|
|
@@ -45069,7 +45073,8 @@ var ScreamChatProvider = class {
|
|
|
45069
45073
|
return new OpenAI({
|
|
45070
45074
|
apiKey: requireProviderApiKey("ScreamChatProvider", a, this._apiKey),
|
|
45071
45075
|
baseURL: this._baseUrl,
|
|
45072
|
-
defaultHeaders
|
|
45076
|
+
defaultHeaders,
|
|
45077
|
+
maxRetries: 0
|
|
45073
45078
|
});
|
|
45074
45079
|
});
|
|
45075
45080
|
}
|
|
@@ -45338,7 +45343,8 @@ var OpenAILegacyChatProvider = class {
|
|
|
45338
45343
|
_buildClient(apiKey, auth) {
|
|
45339
45344
|
const clientOpts = {
|
|
45340
45345
|
apiKey,
|
|
45341
|
-
baseURL: this._baseUrl
|
|
45346
|
+
baseURL: this._baseUrl,
|
|
45347
|
+
maxRetries: 0
|
|
45342
45348
|
};
|
|
45343
45349
|
const defaultHeaders = mergeRequestHeaders(this._defaultHeaders, auth?.headers);
|
|
45344
45350
|
if (defaultHeaders !== void 0) clientOpts["defaultHeaders"] = defaultHeaders;
|
|
@@ -45985,7 +45991,8 @@ var OpenAIResponsesChatProvider = class {
|
|
|
45985
45991
|
_buildClient(apiKey, auth) {
|
|
45986
45992
|
const clientOpts = {
|
|
45987
45993
|
apiKey,
|
|
45988
|
-
baseURL: this._baseUrl
|
|
45994
|
+
baseURL: this._baseUrl,
|
|
45995
|
+
maxRetries: 0
|
|
45989
45996
|
};
|
|
45990
45997
|
const defaultHeaders = mergeRequestHeaders(this._defaultHeaders, auth?.headers);
|
|
45991
45998
|
if (defaultHeaders !== void 0) clientOpts["defaultHeaders"] = defaultHeaders;
|
|
@@ -47326,6 +47333,236 @@ function resolveGlobalLogPath(homeDir) {
|
|
|
47326
47333
|
return join$1(homeDir, "logs", "scream-code.log");
|
|
47327
47334
|
}
|
|
47328
47335
|
//#endregion
|
|
47336
|
+
//#region ../../node_modules/.pnpm/@antfu+utils@9.3.0/node_modules/@antfu/utils/dist/index.mjs
|
|
47337
|
+
function uniq(array) {
|
|
47338
|
+
return Array.from(new Set(array));
|
|
47339
|
+
}
|
|
47340
|
+
function notNullish(v) {
|
|
47341
|
+
return v != null;
|
|
47342
|
+
}
|
|
47343
|
+
function objectMap(obj, fn) {
|
|
47344
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => fn(k, v)).filter(notNullish));
|
|
47345
|
+
}
|
|
47346
|
+
function sleep$1(ms, callback) {
|
|
47347
|
+
return new Promise((resolve) => setTimeout(async () => {
|
|
47348
|
+
await callback?.();
|
|
47349
|
+
resolve();
|
|
47350
|
+
}, ms));
|
|
47351
|
+
}
|
|
47352
|
+
function createControlledPromise() {
|
|
47353
|
+
let resolve, reject;
|
|
47354
|
+
const promise = new Promise((_resolve, _reject) => {
|
|
47355
|
+
resolve = _resolve;
|
|
47356
|
+
reject = _reject;
|
|
47357
|
+
});
|
|
47358
|
+
promise.resolve = resolve;
|
|
47359
|
+
promise.reject = reject;
|
|
47360
|
+
return promise;
|
|
47361
|
+
}
|
|
47362
|
+
//#endregion
|
|
47363
|
+
//#region ../../packages/agent-core/src/utils/abort.ts
|
|
47364
|
+
function abortError() {
|
|
47365
|
+
const error = /* @__PURE__ */ new Error("Aborted");
|
|
47366
|
+
error.name = "AbortError";
|
|
47367
|
+
return error;
|
|
47368
|
+
}
|
|
47369
|
+
/**
|
|
47370
|
+
* Marks an abort the user triggered deliberately (e.g. pressing ESC to
|
|
47371
|
+
* interrupt the agent), as distinct from a timeout, an internal error, or any
|
|
47372
|
+
* other programmatic abort. It travels as the AbortSignal's `reason`, so code
|
|
47373
|
+
* that settles an interrupted operation can tell a user interruption apart from
|
|
47374
|
+
* a failure and report it to the model accordingly instead of emitting a
|
|
47375
|
+
* neutral "was aborted" that the model mistakes for a system problem.
|
|
47376
|
+
*
|
|
47377
|
+
* `name` stays 'AbortError' so existing `isAbortError()` checks (and
|
|
47378
|
+
* `AbortSignal.throwIfAborted()`) keep treating it as an abort.
|
|
47379
|
+
*/
|
|
47380
|
+
var UserCancellationError = class extends Error {
|
|
47381
|
+
userCancelled = true;
|
|
47382
|
+
constructor() {
|
|
47383
|
+
super("Aborted by the user");
|
|
47384
|
+
this.name = "AbortError";
|
|
47385
|
+
}
|
|
47386
|
+
};
|
|
47387
|
+
function userCancellationReason() {
|
|
47388
|
+
return new UserCancellationError();
|
|
47389
|
+
}
|
|
47390
|
+
function isUserCancellation(value) {
|
|
47391
|
+
return value instanceof UserCancellationError;
|
|
47392
|
+
}
|
|
47393
|
+
function abortable(promise, signal) {
|
|
47394
|
+
signal.throwIfAborted();
|
|
47395
|
+
return new Promise((resolve, reject) => {
|
|
47396
|
+
const onAbort = () => {
|
|
47397
|
+
reject(abortError());
|
|
47398
|
+
};
|
|
47399
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
47400
|
+
promise.then(resolve, reject).finally(() => {
|
|
47401
|
+
signal.removeEventListener("abort", onAbort);
|
|
47402
|
+
});
|
|
47403
|
+
});
|
|
47404
|
+
}
|
|
47405
|
+
function linkAbortSignal(source, target) {
|
|
47406
|
+
const onAbort = () => {
|
|
47407
|
+
target.abort(source.reason);
|
|
47408
|
+
};
|
|
47409
|
+
if (source.aborted) {
|
|
47410
|
+
onAbort();
|
|
47411
|
+
return () => {};
|
|
47412
|
+
}
|
|
47413
|
+
source.addEventListener("abort", onAbort, { once: true });
|
|
47414
|
+
return () => {
|
|
47415
|
+
source.removeEventListener("abort", onAbort);
|
|
47416
|
+
};
|
|
47417
|
+
}
|
|
47418
|
+
function createDeadlineAbortSignal(source, timeoutMs) {
|
|
47419
|
+
const controller = new AbortController();
|
|
47420
|
+
const unlinkAbortSignal = linkAbortSignal(source, controller);
|
|
47421
|
+
let didTimeout = false;
|
|
47422
|
+
let timeout = setTimeout(() => {
|
|
47423
|
+
didTimeout = true;
|
|
47424
|
+
controller.abort(abortError());
|
|
47425
|
+
}, timeoutMs);
|
|
47426
|
+
return {
|
|
47427
|
+
signal: controller.signal,
|
|
47428
|
+
timedOut: () => didTimeout,
|
|
47429
|
+
clear: () => {
|
|
47430
|
+
if (timeout !== void 0) clearTimeout(timeout);
|
|
47431
|
+
timeout = void 0;
|
|
47432
|
+
unlinkAbortSignal();
|
|
47433
|
+
}
|
|
47434
|
+
};
|
|
47435
|
+
}
|
|
47436
|
+
//#endregion
|
|
47437
|
+
//#region ../../packages/agent-core/src/loop/errors.ts
|
|
47438
|
+
/**
|
|
47439
|
+
* Loop-local error helpers.
|
|
47440
|
+
*/
|
|
47441
|
+
function createMaxStepsExceededError(maxSteps, message) {
|
|
47442
|
+
return new ScreamError(ErrorCodes.LOOP_MAX_STEPS_EXCEEDED, message ?? `Turn exceeded maxSteps=${maxSteps}`, { details: { maxSteps } });
|
|
47443
|
+
}
|
|
47444
|
+
function isMaxStepsExceededError(error) {
|
|
47445
|
+
return isScreamError(error) && error.code === ErrorCodes.LOOP_MAX_STEPS_EXCEEDED;
|
|
47446
|
+
}
|
|
47447
|
+
function isAbortError$1(err) {
|
|
47448
|
+
if (err instanceof Error) return err.name === "AbortError";
|
|
47449
|
+
return false;
|
|
47450
|
+
}
|
|
47451
|
+
function errorMessage$4(err) {
|
|
47452
|
+
if (err instanceof Error) return err.message;
|
|
47453
|
+
return String(err);
|
|
47454
|
+
}
|
|
47455
|
+
const BASE_DELAY_MS = 500;
|
|
47456
|
+
const MAX_DELAY_MS = 32e3;
|
|
47457
|
+
const RETRY_FACTOR = 2;
|
|
47458
|
+
const JITTER_FACTOR = .25;
|
|
47459
|
+
async function chatWithRetry(input) {
|
|
47460
|
+
const maxAttempts = input.maxAttempts ?? 10;
|
|
47461
|
+
if (input.llm.isRetryableError === void 0 || maxAttempts <= 1) {
|
|
47462
|
+
const effectiveMaxAttempts = Math.max(maxAttempts, 1);
|
|
47463
|
+
try {
|
|
47464
|
+
return await input.llm.chat(paramsForAttempt(input, 1, effectiveMaxAttempts));
|
|
47465
|
+
} catch (error) {
|
|
47466
|
+
logRequestFailure(input, error, 1, effectiveMaxAttempts);
|
|
47467
|
+
throw error;
|
|
47468
|
+
}
|
|
47469
|
+
}
|
|
47470
|
+
const delays = retryBackoffDelays(maxAttempts);
|
|
47471
|
+
for (let attempt = 1;; attempt += 1) try {
|
|
47472
|
+
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts));
|
|
47473
|
+
} catch (error) {
|
|
47474
|
+
if (error instanceof APIContextOverflowError) {
|
|
47475
|
+
logRequestFailure(input, error, attempt, maxAttempts);
|
|
47476
|
+
throw error;
|
|
47477
|
+
}
|
|
47478
|
+
if (error instanceof APIProviderRateLimitError && error.reason === "QUOTA_EXHAUSTED") {
|
|
47479
|
+
logRequestFailure(input, error, attempt, maxAttempts);
|
|
47480
|
+
throw error;
|
|
47481
|
+
}
|
|
47482
|
+
if (attempt >= maxAttempts || !input.llm.isRetryableError(error)) {
|
|
47483
|
+
logRequestFailure(input, error, attempt, maxAttempts);
|
|
47484
|
+
throw error;
|
|
47485
|
+
}
|
|
47486
|
+
const delayMs = computeDelayMs(error, delays, attempt);
|
|
47487
|
+
input.params.signal.throwIfAborted();
|
|
47488
|
+
input.dispatchEvent({
|
|
47489
|
+
type: "step.retrying",
|
|
47490
|
+
turnId: input.turnId,
|
|
47491
|
+
step: input.currentStep,
|
|
47492
|
+
stepUuid: input.stepUuid,
|
|
47493
|
+
failedAttempt: attempt,
|
|
47494
|
+
nextAttempt: attempt + 1,
|
|
47495
|
+
maxAttempts,
|
|
47496
|
+
delayMs,
|
|
47497
|
+
...retryErrorFields(error)
|
|
47498
|
+
});
|
|
47499
|
+
await sleepForRetry(delayMs, input.params.signal);
|
|
47500
|
+
}
|
|
47501
|
+
}
|
|
47502
|
+
function computeDelayMs(error, delays, attempt) {
|
|
47503
|
+
const retryAfter = readRetryAfterMs(error);
|
|
47504
|
+
if (retryAfter !== null) return retryAfter;
|
|
47505
|
+
if (error instanceof APIProviderRateLimitError) return calculateRateLimitBackoffMs(error.reason);
|
|
47506
|
+
return delays[attempt - 1] ?? 0;
|
|
47507
|
+
}
|
|
47508
|
+
/**
|
|
47509
|
+
* Server-requested backoff carried on an `APIStatusError` (parsed from
|
|
47510
|
+
* the `Retry-After` response header). When present and positive it
|
|
47511
|
+
* overrides the computed backoff - a server `Retry-After` directive
|
|
47512
|
+
* takes precedence over the local exponential delay.
|
|
47513
|
+
*/
|
|
47514
|
+
function readRetryAfterMs(error) {
|
|
47515
|
+
if (typeof error !== "object" || error === null) return null;
|
|
47516
|
+
const value = error.retryAfterMs;
|
|
47517
|
+
return typeof value === "number" && value > 0 ? value : null;
|
|
47518
|
+
}
|
|
47519
|
+
function logRequestFailure(input, error, attempt, maxAttempts) {
|
|
47520
|
+
if (isAbortError$1(error) || input.params.signal.aborted) return;
|
|
47521
|
+
input.log?.warn("llm request failed", {
|
|
47522
|
+
turnStep: `${input.turnId}.${String(input.currentStep)}`,
|
|
47523
|
+
attempt: `${String(attempt)}/${String(maxAttempts)}`,
|
|
47524
|
+
model: input.llm.modelName,
|
|
47525
|
+
...retryErrorFields(error)
|
|
47526
|
+
});
|
|
47527
|
+
}
|
|
47528
|
+
function paramsForAttempt(input, attempt, maxAttempts) {
|
|
47529
|
+
return {
|
|
47530
|
+
...input.params,
|
|
47531
|
+
requestLogContext: {
|
|
47532
|
+
turnId: input.turnId,
|
|
47533
|
+
step: input.currentStep,
|
|
47534
|
+
stepUuid: input.stepUuid,
|
|
47535
|
+
attempt,
|
|
47536
|
+
maxAttempts
|
|
47537
|
+
}
|
|
47538
|
+
};
|
|
47539
|
+
}
|
|
47540
|
+
function retryBackoffDelays(maxAttempts) {
|
|
47541
|
+
const count = Math.max(maxAttempts - 1, 0);
|
|
47542
|
+
const delays = [];
|
|
47543
|
+
for (let i = 0; i < count; i += 1) {
|
|
47544
|
+
const base = Math.min(BASE_DELAY_MS * Math.pow(RETRY_FACTOR, i), MAX_DELAY_MS);
|
|
47545
|
+
delays.push(base + Math.random() * JITTER_FACTOR * base);
|
|
47546
|
+
}
|
|
47547
|
+
return delays;
|
|
47548
|
+
}
|
|
47549
|
+
async function sleepForRetry(delayMs, signal) {
|
|
47550
|
+
signal.throwIfAborted();
|
|
47551
|
+
await abortable(sleep$1(delayMs), signal);
|
|
47552
|
+
}
|
|
47553
|
+
function retryErrorFields(error) {
|
|
47554
|
+
return {
|
|
47555
|
+
errorName: error instanceof Error ? error.name : typeof error,
|
|
47556
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
47557
|
+
statusCode: maybeStatusCode(error)
|
|
47558
|
+
};
|
|
47559
|
+
}
|
|
47560
|
+
function maybeStatusCode(error) {
|
|
47561
|
+
if (typeof error !== "object" || error === null) return void 0;
|
|
47562
|
+
const statusCode = error.statusCode;
|
|
47563
|
+
return typeof statusCode === "number" ? statusCode : void 0;
|
|
47564
|
+
}
|
|
47565
|
+
//#endregion
|
|
47329
47566
|
//#region ../../packages/agent-core/src/utils/tokens.ts
|
|
47330
47567
|
/**
|
|
47331
47568
|
* WeakMap cache for per-message token estimates. Messages are immutable once
|
|
@@ -47382,25 +47619,6 @@ function estimateTokensForContentPart(part) {
|
|
|
47382
47619
|
return 0;
|
|
47383
47620
|
}
|
|
47384
47621
|
//#endregion
|
|
47385
|
-
//#region ../../packages/agent-core/src/loop/errors.ts
|
|
47386
|
-
/**
|
|
47387
|
-
* Loop-local error helpers.
|
|
47388
|
-
*/
|
|
47389
|
-
function createMaxStepsExceededError(maxSteps, message) {
|
|
47390
|
-
return new ScreamError(ErrorCodes.LOOP_MAX_STEPS_EXCEEDED, message ?? `Turn exceeded maxSteps=${maxSteps}`, { details: { maxSteps } });
|
|
47391
|
-
}
|
|
47392
|
-
function isMaxStepsExceededError(error) {
|
|
47393
|
-
return isScreamError(error) && error.code === ErrorCodes.LOOP_MAX_STEPS_EXCEEDED;
|
|
47394
|
-
}
|
|
47395
|
-
function isAbortError$1(err) {
|
|
47396
|
-
if (err instanceof Error) return err.name === "AbortError";
|
|
47397
|
-
return false;
|
|
47398
|
-
}
|
|
47399
|
-
function errorMessage$4(err) {
|
|
47400
|
-
if (err instanceof Error) return err.message;
|
|
47401
|
-
return String(err);
|
|
47402
|
-
}
|
|
47403
|
-
//#endregion
|
|
47404
47622
|
//#region ../../packages/agent-core/src/utils/per-id-json-store.ts
|
|
47405
47623
|
/**
|
|
47406
47624
|
* Per-id JSON record store — write each value as `<rootDir>/<subdir>/<id>.json`.
|
|
@@ -51659,80 +51877,6 @@ function normalizePath$1(path) {
|
|
|
51659
51877
|
return folded;
|
|
51660
51878
|
}
|
|
51661
51879
|
//#endregion
|
|
51662
|
-
//#region ../../packages/agent-core/src/utils/abort.ts
|
|
51663
|
-
function abortError() {
|
|
51664
|
-
const error = /* @__PURE__ */ new Error("Aborted");
|
|
51665
|
-
error.name = "AbortError";
|
|
51666
|
-
return error;
|
|
51667
|
-
}
|
|
51668
|
-
/**
|
|
51669
|
-
* Marks an abort the user triggered deliberately (e.g. pressing ESC to
|
|
51670
|
-
* interrupt the agent), as distinct from a timeout, an internal error, or any
|
|
51671
|
-
* other programmatic abort. It travels as the AbortSignal's `reason`, so code
|
|
51672
|
-
* that settles an interrupted operation can tell a user interruption apart from
|
|
51673
|
-
* a failure and report it to the model accordingly instead of emitting a
|
|
51674
|
-
* neutral "was aborted" that the model mistakes for a system problem.
|
|
51675
|
-
*
|
|
51676
|
-
* `name` stays 'AbortError' so existing `isAbortError()` checks (and
|
|
51677
|
-
* `AbortSignal.throwIfAborted()`) keep treating it as an abort.
|
|
51678
|
-
*/
|
|
51679
|
-
var UserCancellationError = class extends Error {
|
|
51680
|
-
userCancelled = true;
|
|
51681
|
-
constructor() {
|
|
51682
|
-
super("Aborted by the user");
|
|
51683
|
-
this.name = "AbortError";
|
|
51684
|
-
}
|
|
51685
|
-
};
|
|
51686
|
-
function userCancellationReason() {
|
|
51687
|
-
return new UserCancellationError();
|
|
51688
|
-
}
|
|
51689
|
-
function isUserCancellation(value) {
|
|
51690
|
-
return value instanceof UserCancellationError;
|
|
51691
|
-
}
|
|
51692
|
-
function abortable(promise, signal) {
|
|
51693
|
-
signal.throwIfAborted();
|
|
51694
|
-
return new Promise((resolve, reject) => {
|
|
51695
|
-
const onAbort = () => {
|
|
51696
|
-
reject(abortError());
|
|
51697
|
-
};
|
|
51698
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
51699
|
-
promise.then(resolve, reject).finally(() => {
|
|
51700
|
-
signal.removeEventListener("abort", onAbort);
|
|
51701
|
-
});
|
|
51702
|
-
});
|
|
51703
|
-
}
|
|
51704
|
-
function linkAbortSignal(source, target) {
|
|
51705
|
-
const onAbort = () => {
|
|
51706
|
-
target.abort(source.reason);
|
|
51707
|
-
};
|
|
51708
|
-
if (source.aborted) {
|
|
51709
|
-
onAbort();
|
|
51710
|
-
return () => {};
|
|
51711
|
-
}
|
|
51712
|
-
source.addEventListener("abort", onAbort, { once: true });
|
|
51713
|
-
return () => {
|
|
51714
|
-
source.removeEventListener("abort", onAbort);
|
|
51715
|
-
};
|
|
51716
|
-
}
|
|
51717
|
-
function createDeadlineAbortSignal(source, timeoutMs) {
|
|
51718
|
-
const controller = new AbortController();
|
|
51719
|
-
const unlinkAbortSignal = linkAbortSignal(source, controller);
|
|
51720
|
-
let didTimeout = false;
|
|
51721
|
-
let timeout = setTimeout(() => {
|
|
51722
|
-
didTimeout = true;
|
|
51723
|
-
controller.abort(abortError());
|
|
51724
|
-
}, timeoutMs);
|
|
51725
|
-
return {
|
|
51726
|
-
signal: controller.signal,
|
|
51727
|
-
timedOut: () => didTimeout,
|
|
51728
|
-
clear: () => {
|
|
51729
|
-
if (timeout !== void 0) clearTimeout(timeout);
|
|
51730
|
-
timeout = void 0;
|
|
51731
|
-
unlinkAbortSignal();
|
|
51732
|
-
}
|
|
51733
|
-
};
|
|
51734
|
-
}
|
|
51735
|
-
//#endregion
|
|
51736
51880
|
//#region ../../packages/agent-core/src/tools/builtin/collaboration/agent-background-disabled.md
|
|
51737
51881
|
var agent_background_disabled_default = "Background agent execution is disabled for this agent. Do not set `run_in_background=true`.";
|
|
51738
51882
|
//#endregion
|
|
@@ -54938,7 +55082,7 @@ var LspClient = class {
|
|
|
54938
55082
|
while (Date.now() - start < timeoutMs) {
|
|
54939
55083
|
const collected = this.collectedDiagnostics.get(uri);
|
|
54940
55084
|
if (collected !== void 0) return collected;
|
|
54941
|
-
await sleep
|
|
55085
|
+
await sleep(100);
|
|
54942
55086
|
}
|
|
54943
55087
|
return this.collectedDiagnostics.get(uri) ?? [];
|
|
54944
55088
|
}
|
|
@@ -55040,7 +55184,7 @@ function uriToPath(uri) {
|
|
|
55040
55184
|
if (process.platform === "win32" && filePath.startsWith("/") && /^[A-Za-z]:/.test(filePath.slice(1))) filePath = filePath.slice(1);
|
|
55041
55185
|
return filePath;
|
|
55042
55186
|
}
|
|
55043
|
-
function sleep
|
|
55187
|
+
function sleep(ms) {
|
|
55044
55188
|
return new Promise((resolve) => {
|
|
55045
55189
|
setTimeout(resolve, ms);
|
|
55046
55190
|
});
|
|
@@ -66339,6 +66483,7 @@ async function parseManifest(pluginRoot) {
|
|
|
66339
66483
|
if (await isFile$1(path.join(pluginRoot, "SKILL.md"))) skills = [pluginRoot];
|
|
66340
66484
|
}
|
|
66341
66485
|
const skillInstructions = typeof raw["skillInstructions"] === "string" ? raw["skillInstructions"] : void 0;
|
|
66486
|
+
const config = typeof raw["config"] === "object" && raw["config"] !== null && !Array.isArray(raw["config"]) ? raw["config"] : void 0;
|
|
66342
66487
|
recordUnsupportedRuntimeFields(raw, diagnostics);
|
|
66343
66488
|
return {
|
|
66344
66489
|
manifest: {
|
|
@@ -66353,7 +66498,8 @@ async function parseManifest(pluginRoot) {
|
|
|
66353
66498
|
sessionStart: readSessionStart(raw["sessionStart"], diagnostics),
|
|
66354
66499
|
mcpServers: await readMcpServers(pluginRoot, raw["mcpServers"], diagnostics),
|
|
66355
66500
|
interface: readInterface(raw["interface"]),
|
|
66356
|
-
skillInstructions
|
|
66501
|
+
skillInstructions,
|
|
66502
|
+
config
|
|
66357
66503
|
},
|
|
66358
66504
|
manifestKind,
|
|
66359
66505
|
manifestPath,
|
|
@@ -67466,7 +67612,7 @@ var MakeSkillPlanTool = class {
|
|
|
67466
67612
|
}
|
|
67467
67613
|
async generatePlan(args) {
|
|
67468
67614
|
const userPrompt = buildUserPrompt(args, buildTranscript(this.agent.context.history));
|
|
67469
|
-
const response = await this.agent.
|
|
67615
|
+
const response = await this.agent.generateWithRetry(this.agent.config.provider, SYSTEM_PROMPT, [], [{
|
|
67470
67616
|
role: "user",
|
|
67471
67617
|
content: [{
|
|
67472
67618
|
type: "text",
|
|
@@ -76308,143 +76454,6 @@ function buildBackgroundTaskNotificationBody(info, isAgentTask) {
|
|
|
76308
76454
|
].join("\n")}`;
|
|
76309
76455
|
}
|
|
76310
76456
|
//#endregion
|
|
76311
|
-
//#region ../../node_modules/.pnpm/@antfu+utils@9.3.0/node_modules/@antfu/utils/dist/index.mjs
|
|
76312
|
-
function uniq(array) {
|
|
76313
|
-
return Array.from(new Set(array));
|
|
76314
|
-
}
|
|
76315
|
-
function notNullish(v) {
|
|
76316
|
-
return v != null;
|
|
76317
|
-
}
|
|
76318
|
-
function objectMap(obj, fn) {
|
|
76319
|
-
return Object.fromEntries(Object.entries(obj).map(([k, v]) => fn(k, v)).filter(notNullish));
|
|
76320
|
-
}
|
|
76321
|
-
function sleep(ms, callback) {
|
|
76322
|
-
return new Promise((resolve) => setTimeout(async () => {
|
|
76323
|
-
await callback?.();
|
|
76324
|
-
resolve();
|
|
76325
|
-
}, ms));
|
|
76326
|
-
}
|
|
76327
|
-
function createControlledPromise() {
|
|
76328
|
-
let resolve, reject;
|
|
76329
|
-
const promise = new Promise((_resolve, _reject) => {
|
|
76330
|
-
resolve = _resolve;
|
|
76331
|
-
reject = _reject;
|
|
76332
|
-
});
|
|
76333
|
-
promise.resolve = resolve;
|
|
76334
|
-
promise.reject = reject;
|
|
76335
|
-
return promise;
|
|
76336
|
-
}
|
|
76337
|
-
const BASE_DELAY_MS = 500;
|
|
76338
|
-
const MAX_DELAY_MS = 32e3;
|
|
76339
|
-
const RETRY_FACTOR = 2;
|
|
76340
|
-
const JITTER_FACTOR = .25;
|
|
76341
|
-
async function chatWithRetry(input) {
|
|
76342
|
-
const maxAttempts = input.maxAttempts ?? 10;
|
|
76343
|
-
if (input.llm.isRetryableError === void 0 || maxAttempts <= 1) {
|
|
76344
|
-
const effectiveMaxAttempts = Math.max(maxAttempts, 1);
|
|
76345
|
-
try {
|
|
76346
|
-
return await input.llm.chat(paramsForAttempt(input, 1, effectiveMaxAttempts));
|
|
76347
|
-
} catch (error) {
|
|
76348
|
-
logRequestFailure(input, error, 1, effectiveMaxAttempts);
|
|
76349
|
-
throw error;
|
|
76350
|
-
}
|
|
76351
|
-
}
|
|
76352
|
-
const delays = retryBackoffDelays(maxAttempts);
|
|
76353
|
-
for (let attempt = 1;; attempt += 1) try {
|
|
76354
|
-
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts));
|
|
76355
|
-
} catch (error) {
|
|
76356
|
-
if (error instanceof APIContextOverflowError) {
|
|
76357
|
-
logRequestFailure(input, error, attempt, maxAttempts);
|
|
76358
|
-
throw error;
|
|
76359
|
-
}
|
|
76360
|
-
if (error instanceof APIProviderRateLimitError && error.reason === "QUOTA_EXHAUSTED") {
|
|
76361
|
-
logRequestFailure(input, error, attempt, maxAttempts);
|
|
76362
|
-
throw error;
|
|
76363
|
-
}
|
|
76364
|
-
if (attempt >= maxAttempts || !input.llm.isRetryableError(error)) {
|
|
76365
|
-
logRequestFailure(input, error, attempt, maxAttempts);
|
|
76366
|
-
throw error;
|
|
76367
|
-
}
|
|
76368
|
-
const delayMs = computeDelayMs(error, delays, attempt);
|
|
76369
|
-
input.params.signal.throwIfAborted();
|
|
76370
|
-
input.dispatchEvent({
|
|
76371
|
-
type: "step.retrying",
|
|
76372
|
-
turnId: input.turnId,
|
|
76373
|
-
step: input.currentStep,
|
|
76374
|
-
stepUuid: input.stepUuid,
|
|
76375
|
-
failedAttempt: attempt,
|
|
76376
|
-
nextAttempt: attempt + 1,
|
|
76377
|
-
maxAttempts,
|
|
76378
|
-
delayMs,
|
|
76379
|
-
...retryErrorFields(error)
|
|
76380
|
-
});
|
|
76381
|
-
await sleepForRetry(delayMs, input.params.signal);
|
|
76382
|
-
}
|
|
76383
|
-
}
|
|
76384
|
-
function computeDelayMs(error, delays, attempt) {
|
|
76385
|
-
const retryAfter = readRetryAfterMs(error);
|
|
76386
|
-
if (retryAfter !== null) return retryAfter;
|
|
76387
|
-
if (error instanceof APIProviderRateLimitError) return calculateRateLimitBackoffMs(error.reason);
|
|
76388
|
-
return delays[attempt - 1] ?? 0;
|
|
76389
|
-
}
|
|
76390
|
-
/**
|
|
76391
|
-
* Server-requested backoff carried on an `APIStatusError` (parsed from
|
|
76392
|
-
* the `Retry-After` response header). When present and positive it
|
|
76393
|
-
* overrides the computed backoff - a server `Retry-After` directive
|
|
76394
|
-
* takes precedence over the local exponential delay.
|
|
76395
|
-
*/
|
|
76396
|
-
function readRetryAfterMs(error) {
|
|
76397
|
-
if (typeof error !== "object" || error === null) return null;
|
|
76398
|
-
const value = error.retryAfterMs;
|
|
76399
|
-
return typeof value === "number" && value > 0 ? value : null;
|
|
76400
|
-
}
|
|
76401
|
-
function logRequestFailure(input, error, attempt, maxAttempts) {
|
|
76402
|
-
if (isAbortError$1(error) || input.params.signal.aborted) return;
|
|
76403
|
-
input.log?.warn("llm request failed", {
|
|
76404
|
-
turnStep: `${input.turnId}.${String(input.currentStep)}`,
|
|
76405
|
-
attempt: `${String(attempt)}/${String(maxAttempts)}`,
|
|
76406
|
-
model: input.llm.modelName,
|
|
76407
|
-
...retryErrorFields(error)
|
|
76408
|
-
});
|
|
76409
|
-
}
|
|
76410
|
-
function paramsForAttempt(input, attempt, maxAttempts) {
|
|
76411
|
-
return {
|
|
76412
|
-
...input.params,
|
|
76413
|
-
requestLogContext: {
|
|
76414
|
-
turnId: input.turnId,
|
|
76415
|
-
step: input.currentStep,
|
|
76416
|
-
stepUuid: input.stepUuid,
|
|
76417
|
-
attempt,
|
|
76418
|
-
maxAttempts
|
|
76419
|
-
}
|
|
76420
|
-
};
|
|
76421
|
-
}
|
|
76422
|
-
function retryBackoffDelays(maxAttempts) {
|
|
76423
|
-
const count = Math.max(maxAttempts - 1, 0);
|
|
76424
|
-
const delays = [];
|
|
76425
|
-
for (let i = 0; i < count; i += 1) {
|
|
76426
|
-
const base = Math.min(BASE_DELAY_MS * Math.pow(RETRY_FACTOR, i), MAX_DELAY_MS);
|
|
76427
|
-
delays.push(base + Math.random() * JITTER_FACTOR * base);
|
|
76428
|
-
}
|
|
76429
|
-
return delays;
|
|
76430
|
-
}
|
|
76431
|
-
async function sleepForRetry(delayMs, signal) {
|
|
76432
|
-
signal.throwIfAborted();
|
|
76433
|
-
await abortable(sleep(delayMs), signal);
|
|
76434
|
-
}
|
|
76435
|
-
function retryErrorFields(error) {
|
|
76436
|
-
return {
|
|
76437
|
-
errorName: error instanceof Error ? error.name : typeof error,
|
|
76438
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
76439
|
-
statusCode: maybeStatusCode(error)
|
|
76440
|
-
};
|
|
76441
|
-
}
|
|
76442
|
-
function maybeStatusCode(error) {
|
|
76443
|
-
if (typeof error !== "object" || error === null) return void 0;
|
|
76444
|
-
const statusCode = error.statusCode;
|
|
76445
|
-
return typeof statusCode === "number" ? statusCode : void 0;
|
|
76446
|
-
}
|
|
76447
|
-
//#endregion
|
|
76448
76457
|
//#region ../../packages/agent-core/src/agent/context/projector.ts
|
|
76449
76458
|
/** Synthetic error text used when a tool result is missing and must be
|
|
76450
76459
|
* filled in so the provider accepts the message sequence. */
|
|
@@ -76972,6 +76981,14 @@ var FullCompaction = class {
|
|
|
76972
76981
|
get compactedHistory() {
|
|
76973
76982
|
return this._compactedHistory;
|
|
76974
76983
|
}
|
|
76984
|
+
/**
|
|
76985
|
+
* Restore the compaction debug trail from a `context.snapshot` record. During
|
|
76986
|
+
* snapshot replay the pre-fold history is skipped, so `markCompleted` can no
|
|
76987
|
+
* longer re-render it — the snapshot carries the trail instead.
|
|
76988
|
+
*/
|
|
76989
|
+
restoreCompactedHistory(entries) {
|
|
76990
|
+
this._compactedHistory = [...entries];
|
|
76991
|
+
}
|
|
76975
76992
|
/** One-shot: true if session memory summary should be injected at the next step. */
|
|
76976
76993
|
shouldInjectSessionSummary() {
|
|
76977
76994
|
if (this._shouldInjectSessionSummary) {
|
|
@@ -77124,7 +77141,9 @@ var FullCompaction = class {
|
|
|
77124
77141
|
}
|
|
77125
77142
|
async compactionWorker(signal, data, compactedCount) {
|
|
77126
77143
|
const originalHistory = [...this.agent.context.history];
|
|
77127
|
-
const
|
|
77144
|
+
const systemPromptTokens = estimateTokens$1(this.agent.getRuntimeSystemPrompt());
|
|
77145
|
+
const toolTokens = estimateTokensForTools(this.agent.tools.loopTools);
|
|
77146
|
+
const tokensBefore = systemPromptTokens + toolTokens + estimateTokensForMessages(originalHistory);
|
|
77128
77147
|
const model = this.agent.config.model;
|
|
77129
77148
|
const isUpdate = extractPreviousSummary(originalHistory) !== null;
|
|
77130
77149
|
let retryCount = 0;
|
|
@@ -77193,7 +77212,7 @@ var FullCompaction = class {
|
|
|
77193
77212
|
for (const msg of messagesToCompactForOps) extractFileOpsFromMessage(msg, fileOps);
|
|
77194
77213
|
const toolCallHistory = formatToolCallHistory(messagesToCompactForOps);
|
|
77195
77214
|
const processedSummary = this.postProcessSummary(summary, fileOps, toolCallHistory, compactedCount);
|
|
77196
|
-
const tokensAfter = estimateTokens$1(processedSummary) + estimateTokensForMessages(recent);
|
|
77215
|
+
const tokensAfter = systemPromptTokens + toolTokens + estimateTokens$1(processedSummary) + estimateTokensForMessages(recent);
|
|
77197
77216
|
const fileLists = computeFileLists(fileOps);
|
|
77198
77217
|
const MAX_PERSISTED_FILES = 100;
|
|
77199
77218
|
const readFiles = fileLists.readFiles.slice(0, MAX_PERSISTED_FILES);
|
|
@@ -78901,6 +78920,42 @@ var ContextMemory = class {
|
|
|
78901
78920
|
this.pendingToolResultIds = new Set(snapshot.pendingToolResultIds);
|
|
78902
78921
|
this.deferredMessages = [...snapshot.deferredMessages];
|
|
78903
78922
|
}
|
|
78923
|
+
/**
|
|
78924
|
+
* JSON-safe snapshot for wire persistence. `openSteps` values are recorded as
|
|
78925
|
+
* their index into `history` so restoring can rebuild the live reference
|
|
78926
|
+
* identity between history messages and open steps (see
|
|
78927
|
+
* {@link ContextMemoryJSONSnapshot}).
|
|
78928
|
+
*/
|
|
78929
|
+
toJSONSnapshot() {
|
|
78930
|
+
return {
|
|
78931
|
+
history: [...this._history],
|
|
78932
|
+
tokenCount: this._tokenCount,
|
|
78933
|
+
tokenCountCoveredMessageCount: this.tokenCountCoveredMessageCount,
|
|
78934
|
+
openSteps: [...this.openSteps.entries()].map(([uuid, message]) => [uuid, this._history.indexOf(message)]),
|
|
78935
|
+
pendingToolResultIds: [...this.pendingToolResultIds],
|
|
78936
|
+
deferredMessages: [...this.deferredMessages]
|
|
78937
|
+
};
|
|
78938
|
+
}
|
|
78939
|
+
/**
|
|
78940
|
+
* Restore from a JSON-safe snapshot produced by {@link toJSONSnapshot}.
|
|
78941
|
+
* Open steps are re-attached to the exact history message objects they
|
|
78942
|
+
* pointed at, preserving reference identity: later `content.part`/`tool.call`
|
|
78943
|
+
* events and `applyCompaction` pruning operate on the same objects the
|
|
78944
|
+
* history array holds, exactly as they did in the live session.
|
|
78945
|
+
*/
|
|
78946
|
+
restoreJSONSnapshot(snapshot) {
|
|
78947
|
+
this._history = [...snapshot.history];
|
|
78948
|
+
this._tokenCount = snapshot.tokenCount;
|
|
78949
|
+
this.tokenCountCoveredMessageCount = snapshot.tokenCountCoveredMessageCount;
|
|
78950
|
+
const openSteps = /* @__PURE__ */ new Map();
|
|
78951
|
+
for (const [uuid, historyIndex] of snapshot.openSteps) {
|
|
78952
|
+
const message = this._history[historyIndex];
|
|
78953
|
+
if (message !== void 0) openSteps.set(uuid, message);
|
|
78954
|
+
}
|
|
78955
|
+
this.openSteps = openSteps;
|
|
78956
|
+
this.pendingToolResultIds = new Set(snapshot.pendingToolResultIds);
|
|
78957
|
+
this.deferredMessages = [...snapshot.deferredMessages];
|
|
78958
|
+
}
|
|
78904
78959
|
appendUserMessage(content, origin = USER_PROMPT_ORIGIN) {
|
|
78905
78960
|
this.appendMessage({
|
|
78906
78961
|
role: "user",
|
|
@@ -79014,6 +79069,11 @@ var ContextMemory = class {
|
|
|
79014
79069
|
this.agent.injection.onContextCompacted(summary.compactedCount);
|
|
79015
79070
|
this.agent.emitStatusUpdated();
|
|
79016
79071
|
this.agent.microCompaction.reset();
|
|
79072
|
+
if (!this.agent.records.restoring) this.agent.records.logRecord({
|
|
79073
|
+
type: "context.snapshot",
|
|
79074
|
+
snapshot: this.toJSONSnapshot(),
|
|
79075
|
+
compactedHistory: [...this.agent.fullCompaction.compactedHistory]
|
|
79076
|
+
});
|
|
79017
79077
|
}
|
|
79018
79078
|
data() {
|
|
79019
79079
|
return {
|
|
@@ -79071,7 +79131,16 @@ var ContextMemory = class {
|
|
|
79071
79131
|
this.lastSentFingerprints = messages.map(messageFingerprint);
|
|
79072
79132
|
if (prev.length === 0) return;
|
|
79073
79133
|
const appended = messages.length - prev.length;
|
|
79074
|
-
if (stable >= prev.length)
|
|
79134
|
+
if (stable >= prev.length) {
|
|
79135
|
+
if (appended > 0) this.agent.log.debug("prefix-stability: provider prompt cache prefix hit", {
|
|
79136
|
+
stablePrefixLength: stable,
|
|
79137
|
+
cachedPrefixTokens: estimateTokensForMessages(messages.slice(0, stable)),
|
|
79138
|
+
prevMessageCount: prev.length,
|
|
79139
|
+
currentMessageCount: messages.length,
|
|
79140
|
+
appendedSinceLast: appended
|
|
79141
|
+
});
|
|
79142
|
+
return;
|
|
79143
|
+
}
|
|
79075
79144
|
this.agent.log.debug("prefix-stability: provider prompt cache prefix broke", {
|
|
79076
79145
|
stablePrefixLength: stable,
|
|
79077
79146
|
prevMessageCount: prev.length,
|
|
@@ -79192,6 +79261,30 @@ var ContextMemory = class {
|
|
|
79192
79261
|
});
|
|
79193
79262
|
}
|
|
79194
79263
|
}
|
|
79264
|
+
/**
|
|
79265
|
+
* Drop in-flight assistant messages that cannot be serialized into a valid
|
|
79266
|
+
* provider request. An interrupted or empty step leaves an open assistant
|
|
79267
|
+
* message whose content is either empty or only "think" parts; after
|
|
79268
|
+
* projection it serializes to a message with no content and no tool_calls,
|
|
79269
|
+
* which strict OpenAI-compatible gateways reject with a 400 on every later
|
|
79270
|
+
* request. Messages carrying any sendable part (text / image / audio / video)
|
|
79271
|
+
* or tool calls are kept.
|
|
79272
|
+
*/
|
|
79273
|
+
dropVacuousOpenMessages() {
|
|
79274
|
+
for (const [uuid, message] of this.openSteps) {
|
|
79275
|
+
if (message.content.some((part) => part.type !== "think") || message.toolCalls.length > 0) continue;
|
|
79276
|
+
const index = this._history.indexOf(message);
|
|
79277
|
+
if (index !== -1) {
|
|
79278
|
+
this._history.splice(index, 1);
|
|
79279
|
+
this.agent.injection.onContextMessageRemoved(index);
|
|
79280
|
+
if (index < this.tokenCountCoveredMessageCount) {
|
|
79281
|
+
this.tokenCountCoveredMessageCount--;
|
|
79282
|
+
this._tokenCount = Math.max(0, this._tokenCount - estimateTokensForMessages([message]));
|
|
79283
|
+
}
|
|
79284
|
+
}
|
|
79285
|
+
this.openSteps.delete(uuid);
|
|
79286
|
+
}
|
|
79287
|
+
}
|
|
79195
79288
|
};
|
|
79196
79289
|
function toolResultOutputForModel(result) {
|
|
79197
79290
|
const output = result.output;
|
|
@@ -83027,6 +83120,14 @@ const MISSING_MEDIA_PLACEHOLDER = "[media missing]";
|
|
|
83027
83120
|
function isBlobRef(url) {
|
|
83028
83121
|
return url.startsWith(BLOBREF_PROTOCOL);
|
|
83029
83122
|
}
|
|
83123
|
+
/**
|
|
83124
|
+
* Blob storage for large message content (images, files, videos). Content above
|
|
83125
|
+
* the size threshold is offloaded to blobs in `blobsDir` and referenced from
|
|
83126
|
+
* wire records as `blobref:` URLs; `rehydrateParts` resolves them back to
|
|
83127
|
+
* inline data when a session is loaded. A single filesystem implementation is
|
|
83128
|
+
* used across the engine; the class boundary is what keeps blob details out of
|
|
83129
|
+
* the wire/records code.
|
|
83130
|
+
*/
|
|
83030
83131
|
var BlobStore = class {
|
|
83031
83132
|
blobsDir;
|
|
83032
83133
|
threshold;
|
|
@@ -83075,6 +83176,33 @@ var BlobStore = class {
|
|
|
83075
83176
|
}
|
|
83076
83177
|
};
|
|
83077
83178
|
}
|
|
83179
|
+
case "context.snapshot": {
|
|
83180
|
+
const history = await Promise.all(record.snapshot.history.map(async (message) => {
|
|
83181
|
+
const content = await this.offloadParts(message.content);
|
|
83182
|
+
return content === message.content ? message : {
|
|
83183
|
+
...message,
|
|
83184
|
+
content
|
|
83185
|
+
};
|
|
83186
|
+
}));
|
|
83187
|
+
const deferredMessages = await Promise.all(record.snapshot.deferredMessages.map(async (message) => {
|
|
83188
|
+
const content = await this.offloadParts(message.content);
|
|
83189
|
+
return content === message.content ? message : {
|
|
83190
|
+
...message,
|
|
83191
|
+
content
|
|
83192
|
+
};
|
|
83193
|
+
}));
|
|
83194
|
+
const historyChanged = history.some((message, i) => message !== record.snapshot.history[i]);
|
|
83195
|
+
const deferredChanged = deferredMessages.some((message, i) => message !== record.snapshot.deferredMessages[i]);
|
|
83196
|
+
if (!historyChanged && !deferredChanged) return record;
|
|
83197
|
+
return {
|
|
83198
|
+
...record,
|
|
83199
|
+
snapshot: {
|
|
83200
|
+
...record.snapshot,
|
|
83201
|
+
history,
|
|
83202
|
+
deferredMessages
|
|
83203
|
+
}
|
|
83204
|
+
};
|
|
83205
|
+
}
|
|
83078
83206
|
default: return record;
|
|
83079
83207
|
}
|
|
83080
83208
|
}
|
|
@@ -83218,6 +83346,28 @@ function asMediaContainer(value) {
|
|
|
83218
83346
|
}
|
|
83219
83347
|
//#endregion
|
|
83220
83348
|
//#region ../../packages/agent-core/src/agent/records/index.ts
|
|
83349
|
+
/**
|
|
83350
|
+
* Record types whose state is fully captured by a `context.snapshot` record.
|
|
83351
|
+
* When a snapshot exists, every one of these that predates it is skipped during
|
|
83352
|
+
* replay because the snapshot already holds the folded context memory. Note
|
|
83353
|
+
* `micro_compaction.apply` is written with an `as never` cast (it is not part of
|
|
83354
|
+
* the AgentRecord union), so it is matched here by its literal type string.
|
|
83355
|
+
*
|
|
83356
|
+
* `full_compaction.complete` is included because its only lasting effect is
|
|
83357
|
+
* pushing onto `compactedHistory` — a debug trail rendered from the pre-fold
|
|
83358
|
+
* history. Snapshot replay skips that pre-fold history, so the trail would be
|
|
83359
|
+
* re-rendered as empty; the snapshot carries the trail itself instead.
|
|
83360
|
+
*/
|
|
83361
|
+
const SNAPSHOT_FOLDED_CONTEXT_TYPES = new Set([
|
|
83362
|
+
"context.append_message",
|
|
83363
|
+
"context.append_loop_event",
|
|
83364
|
+
"context.apply_compaction",
|
|
83365
|
+
"micro_compaction.apply",
|
|
83366
|
+
"full_compaction.complete"
|
|
83367
|
+
]);
|
|
83368
|
+
function isSnapshotFoldedContextRecord(type) {
|
|
83369
|
+
return SNAPSHOT_FOLDED_CONTEXT_TYPES.has(type);
|
|
83370
|
+
}
|
|
83221
83371
|
function restoreAgentRecord(agent, input) {
|
|
83222
83372
|
switch (input.type) {
|
|
83223
83373
|
case "metadata": return;
|
|
@@ -83300,6 +83450,17 @@ function restoreAgentRecord(agent, input) {
|
|
|
83300
83450
|
case "context.apply_compaction":
|
|
83301
83451
|
agent.context.applyCompaction(input);
|
|
83302
83452
|
return;
|
|
83453
|
+
case "context.snapshot":
|
|
83454
|
+
agent.context.restoreJSONSnapshot(input.snapshot);
|
|
83455
|
+
agent.fullCompaction.restoreCompactedHistory(input.compactedHistory);
|
|
83456
|
+
for (const message of agent.context.history) {
|
|
83457
|
+
if (message.origin?.kind === "background_task") agent.background.markDeliveredNotification(message.origin);
|
|
83458
|
+
agent.replayBuilder.push({
|
|
83459
|
+
type: "message",
|
|
83460
|
+
message
|
|
83461
|
+
});
|
|
83462
|
+
}
|
|
83463
|
+
return;
|
|
83303
83464
|
case "tools.register_user_tool":
|
|
83304
83465
|
agent.tools.registerUserTool(input);
|
|
83305
83466
|
return;
|
|
@@ -83378,8 +83539,19 @@ var AgentRecords = class {
|
|
|
83378
83539
|
protocol_version: "1.4"
|
|
83379
83540
|
};
|
|
83380
83541
|
replayedRecords.push(migratedRecord);
|
|
83381
|
-
this.restore(migratedRecord);
|
|
83382
83542
|
}
|
|
83543
|
+
let snapshotIndex = -1;
|
|
83544
|
+
for (let i = replayedRecords.length - 1; i >= 0; i--) if (replayedRecords[i]?.type === "context.snapshot") {
|
|
83545
|
+
snapshotIndex = i;
|
|
83546
|
+
break;
|
|
83547
|
+
}
|
|
83548
|
+
for (let i = 0; i < replayedRecords.length; i++) {
|
|
83549
|
+
const record = replayedRecords[i];
|
|
83550
|
+
if (!record) continue;
|
|
83551
|
+
if (i < snapshotIndex && isSnapshotFoldedContextRecord(record.type)) continue;
|
|
83552
|
+
this.restore(record);
|
|
83553
|
+
}
|
|
83554
|
+
this.agent.context.dropVacuousOpenMessages();
|
|
83383
83555
|
if (shouldRewrite) {
|
|
83384
83556
|
this.persistence.rewrite(replayedRecords);
|
|
83385
83557
|
await this.persistence.flush();
|
|
@@ -96579,6 +96751,13 @@ var ToolManager = class {
|
|
|
96579
96751
|
getTodos() {
|
|
96580
96752
|
return cloneTodos(this.store.todo ?? []);
|
|
96581
96753
|
}
|
|
96754
|
+
/**
|
|
96755
|
+
* Register a user/plugin tool. This is the public entry point for any
|
|
96756
|
+
* third-party extension (plugins, skills, future harness adapters) to expose
|
|
96757
|
+
* a tool — built-in tools use the internal `builtinTools` map and should not
|
|
96758
|
+
* route through here. Prefer `defineTool()` for the typed high-level API;
|
|
96759
|
+
* this method takes a hand-written registration.
|
|
96760
|
+
*/
|
|
96582
96761
|
registerUserTool(input) {
|
|
96583
96762
|
this.agent.records.logRecord({
|
|
96584
96763
|
type: "tools.register_user_tool",
|
|
@@ -96614,6 +96793,10 @@ var ToolManager = class {
|
|
|
96614
96793
|
this.userTools.delete(name);
|
|
96615
96794
|
this.enabledTools.delete(name);
|
|
96616
96795
|
}
|
|
96796
|
+
/**
|
|
96797
|
+
* Register an MCP server (and its tools). Public entry point for third-party
|
|
96798
|
+
* extensions to expose MCP-backed tools; built-in tooling does not use it.
|
|
96799
|
+
*/
|
|
96617
96800
|
registerMcpServer(serverName, client, tools, enabledTools, options) {
|
|
96618
96801
|
this.unregisterMcpServer(serverName);
|
|
96619
96802
|
const qualifiedNames = [];
|
|
@@ -97716,6 +97899,11 @@ var TurnFlow = class {
|
|
|
97716
97899
|
} catch (error) {
|
|
97717
97900
|
console.error("closeAbandonedToolExchange failed", error);
|
|
97718
97901
|
}
|
|
97902
|
+
try {
|
|
97903
|
+
this.agent.context.dropVacuousOpenMessages();
|
|
97904
|
+
} catch (error) {
|
|
97905
|
+
console.error("dropVacuousOpenMessages failed", error);
|
|
97906
|
+
}
|
|
97719
97907
|
if (this.currentId === turnId) this.agent.usage.endTurn();
|
|
97720
97908
|
this.agent.emitEvent(ended);
|
|
97721
97909
|
if (standalone && this.currentId === turnId) this.activeTurn = null;
|
|
@@ -98466,6 +98654,8 @@ var Agent = class {
|
|
|
98466
98654
|
workingSet;
|
|
98467
98655
|
dreamTracker;
|
|
98468
98656
|
replayBuilder;
|
|
98657
|
+
/** Read-only manifest of the core engine subsystems (see {@link AgentServices}). */
|
|
98658
|
+
services;
|
|
98469
98659
|
lastLlmConfigLogSignature;
|
|
98470
98660
|
sharedEmbeddingEngine;
|
|
98471
98661
|
resolveRuntimeSystemPrompt;
|
|
@@ -98518,6 +98708,25 @@ var Agent = class {
|
|
|
98518
98708
|
this.workingSet = new WorkingSet();
|
|
98519
98709
|
this.dreamTracker = new DreamTracker(screamHomeDir ?? "");
|
|
98520
98710
|
this.replayBuilder = new ReplayBuilder(this);
|
|
98711
|
+
this.services = {
|
|
98712
|
+
records: this.records,
|
|
98713
|
+
context: this.context,
|
|
98714
|
+
config: this.config,
|
|
98715
|
+
turn: this.turn,
|
|
98716
|
+
injection: this.injection,
|
|
98717
|
+
permission: this.permission,
|
|
98718
|
+
planMode: this.planMode,
|
|
98719
|
+
usage: this.usage,
|
|
98720
|
+
tools: this.tools,
|
|
98721
|
+
skills: this.skills,
|
|
98722
|
+
background: this.background,
|
|
98723
|
+
goal: this.goal,
|
|
98724
|
+
sessionMemory: this.sessionMemory,
|
|
98725
|
+
workingSet: this.workingSet,
|
|
98726
|
+
fullCompaction: this.fullCompaction,
|
|
98727
|
+
microCompaction: this.microCompaction,
|
|
98728
|
+
systemPrompt: () => this.getRuntimeSystemPrompt()
|
|
98729
|
+
};
|
|
98521
98730
|
}
|
|
98522
98731
|
/**
|
|
98523
98732
|
* Promise that resolves once the shared memory store (and any legacy migration)
|
|
@@ -98684,6 +98893,26 @@ var Agent = class {
|
|
|
98684
98893
|
});
|
|
98685
98894
|
};
|
|
98686
98895
|
}
|
|
98896
|
+
/**
|
|
98897
|
+
* Bounded-retry wrapper around `generate` for auxiliary LLM calls (exit
|
|
98898
|
+
* memory extraction, side questions, knowledge-base text generation, skill
|
|
98899
|
+
* plan generation). These call the model directly, outside the loop's
|
|
98900
|
+
* step-retry layer, and SDK-level retries are disabled — without this they
|
|
98901
|
+
* would hard-fail on any transient 429/5xx. Mirrors the main loop's policy:
|
|
98902
|
+
* only retryable errors, exponential backoff, bounded attempts.
|
|
98903
|
+
*/
|
|
98904
|
+
async generateWithRetry(provider, systemPrompt, tools, messages, maxAttempts = 3) {
|
|
98905
|
+
const delays = retryBackoffDelays(maxAttempts);
|
|
98906
|
+
for (let attempt = 1;; attempt++) try {
|
|
98907
|
+
return await this.generate(provider, systemPrompt, [...tools], [...messages]);
|
|
98908
|
+
} catch (error) {
|
|
98909
|
+
if (attempt >= maxAttempts || !isRetryableGenerateError(error)) throw error;
|
|
98910
|
+
const delayMs = computeDelayMs(error, delays, attempt);
|
|
98911
|
+
await new Promise((resolve) => {
|
|
98912
|
+
setTimeout(resolve, delayMs);
|
|
98913
|
+
});
|
|
98914
|
+
}
|
|
98915
|
+
}
|
|
98687
98916
|
get llm() {
|
|
98688
98917
|
const model = this.config.model;
|
|
98689
98918
|
const provider = this.config.provider.withThinking(this.config.thinkingLevel);
|
|
@@ -98935,7 +99164,7 @@ var Agent = class {
|
|
|
98935
99164
|
}).join("\n");
|
|
98936
99165
|
const userPrompt = buildExitExtractionPrompt(sessionId, history.length, sampleText);
|
|
98937
99166
|
try {
|
|
98938
|
-
const response = await this.
|
|
99167
|
+
const response = await this.generateWithRetry(this.config.provider, EXIT_EXTRACTION_SYSTEM_PROMPT, [], [{
|
|
98939
99168
|
role: "user",
|
|
98940
99169
|
content: [{
|
|
98941
99170
|
type: "text",
|
|
@@ -98984,7 +99213,7 @@ var Agent = class {
|
|
|
98984
99213
|
const conversationContext = contextParts.join("\n\n");
|
|
98985
99214
|
const system = conversationContext ? `${SIDE_QUESTION_SYSTEM}\n\n<conversation_context>\n${conversationContext}\n</conversation_context>` : SIDE_QUESTION_SYSTEM;
|
|
98986
99215
|
if (!this.config.hasModel) return "No model configured. Run `scream config` or use `/model` to set a default model.";
|
|
98987
|
-
return (await this.
|
|
99216
|
+
return (await this.generateWithRetry(this.config.provider, system, [], [{
|
|
98988
99217
|
role: "user",
|
|
98989
99218
|
content: [{
|
|
98990
99219
|
type: "text",
|
|
@@ -99000,7 +99229,7 @@ var Agent = class {
|
|
|
99000
99229
|
*/
|
|
99001
99230
|
async generateText(systemPrompt, userPrompt) {
|
|
99002
99231
|
if (!this.config.hasModel) throw new Error("No model configured. Run `scream config` or use `/model` to set a default model.");
|
|
99003
|
-
return (await this.
|
|
99232
|
+
return (await this.generateWithRetry(this.config.provider, systemPrompt, [], [{
|
|
99004
99233
|
role: "user",
|
|
99005
99234
|
content: [{
|
|
99006
99235
|
type: "text",
|
|
@@ -123281,8 +123510,8 @@ function getCtrlCHint() {
|
|
|
123281
123510
|
}
|
|
123282
123511
|
const MAIN_AGENT_ID$1 = "main";
|
|
123283
123512
|
const EXIT_CONFIRM_WINDOW_MS = 1500;
|
|
123284
|
-
/**
|
|
123285
|
-
const EMPTY_SESSION_HINT_URL = "https://
|
|
123513
|
+
/** Repository page opened by Ctrl+F while the chat is empty (feedback / star). */
|
|
123514
|
+
const EMPTY_SESSION_HINT_URL = "https://github.com/LIUTod/scream-code";
|
|
123286
123515
|
const SESSION_TIPS = [
|
|
123287
123516
|
{
|
|
123288
123517
|
i18nKey: "editor.tip_ad",
|
|
@@ -123355,6 +123584,7 @@ function isManagedUsageProvider(providerKey) {
|
|
|
123355
123584
|
const STREAMING_ARGS_FIELD_RE = /"(path|file_path|command|pattern|query|url|description|title|name)"\s*:\s*"((?:\\.|[^"\\])*)"/g;
|
|
123356
123585
|
const STREAMING_ARGS_PREVIEW_MAX_CHARS = 8 * 1024;
|
|
123357
123586
|
const STREAMING_ARGS_BUFFER_MAX_CHARS = 1024 * 1024;
|
|
123587
|
+
const CHARS_PER_TOKEN = 2.5;
|
|
123358
123588
|
//#endregion
|
|
123359
123589
|
//#region src/tui/utils/event-payload.ts
|
|
123360
123590
|
function appendStreamingArgsPreview(current, next) {
|
|
@@ -124789,7 +125019,48 @@ function buildTraceCells({ wirePath }) {
|
|
|
124789
125019
|
}
|
|
124790
125020
|
finalizeStep(void 0);
|
|
124791
125021
|
flushPendingSystem(void 0);
|
|
124792
|
-
return cells;
|
|
125022
|
+
return capTraceSize(cells);
|
|
125023
|
+
}
|
|
125024
|
+
/**
|
|
125025
|
+
* Long sessions produce tens of thousands of cells with multi-MB detail
|
|
125026
|
+
* payloads, which previously bloated the trace HTML (up to ~60MB) and froze
|
|
125027
|
+
* the browser. Two mitigations, applied at build time:
|
|
125028
|
+
* 1. Truncate per-cell detail text (thinking/output/input/result) to a cap.
|
|
125029
|
+
* 2. Beyond a cell-count cap, collapse the oldest cells into per-turn
|
|
125030
|
+
* summary rows so the document stays bounded while early turns remain
|
|
125031
|
+
* visible in the ledger.
|
|
125032
|
+
*/
|
|
125033
|
+
const MAX_DETAIL = 4e3;
|
|
125034
|
+
const MAX_CELLS = 4e3;
|
|
125035
|
+
function truncateDetail(value, max = MAX_DETAIL) {
|
|
125036
|
+
if (!value || value.length <= max) return value;
|
|
125037
|
+
return `${value.slice(0, max)}\n…[已截断 ${value.length - max} 字符]`;
|
|
125038
|
+
}
|
|
125039
|
+
function capTraceSize(cells) {
|
|
125040
|
+
for (const cell of cells) {
|
|
125041
|
+
cell.text = truncateDetail(cell.text, 240) ?? "";
|
|
125042
|
+
if (cell.thinkingDetail) cell.thinkingDetail = truncateDetail(cell.thinkingDetail);
|
|
125043
|
+
if (cell.outputDetail) cell.outputDetail = truncateDetail(cell.outputDetail);
|
|
125044
|
+
if (cell.inputDetail) cell.inputDetail = truncateDetail(cell.inputDetail);
|
|
125045
|
+
if (cell.result) cell.result = truncateDetail(cell.result);
|
|
125046
|
+
}
|
|
125047
|
+
if (cells.length <= MAX_CELLS) return cells;
|
|
125048
|
+
const keep = cells.slice(-4e3);
|
|
125049
|
+
const early = cells.slice(0, cells.length - MAX_CELLS);
|
|
125050
|
+
let firstTurn;
|
|
125051
|
+
let lastTurn;
|
|
125052
|
+
for (const cell of early) {
|
|
125053
|
+
if (cell.turn === void 0) continue;
|
|
125054
|
+
if (firstTurn === void 0 || cell.turn < firstTurn) firstTurn = cell.turn;
|
|
125055
|
+
if (lastTurn === void 0 || cell.turn > lastTurn) lastTurn = cell.turn;
|
|
125056
|
+
}
|
|
125057
|
+
return [{
|
|
125058
|
+
index: 1,
|
|
125059
|
+
kind: "system",
|
|
125060
|
+
text: `更早的轨迹已折叠${firstTurn !== void 0 && lastTurn !== void 0 ? `(回合 ${firstTurn}-${lastTurn})` : ""}:${early.length} 条记录`,
|
|
125061
|
+
timeSeconds: null,
|
|
125062
|
+
startedAt: early.find((c) => c.startedAt !== void 0 && c.startedAt !== null)?.startedAt ?? null
|
|
125063
|
+
}, ...keep];
|
|
124793
125064
|
}
|
|
124794
125065
|
function readWireRows(wirePath) {
|
|
124795
125066
|
const content = readFileSync(wirePath, "utf8");
|
|
@@ -124989,6 +125260,15 @@ var collapsedCalls = false;
|
|
|
124989
125260
|
var timeMode = false;
|
|
124990
125261
|
var selectedIndex = -1;
|
|
124991
125262
|
var rowEls = [];
|
|
125263
|
+
var PAGE = 300;
|
|
125264
|
+
var renderedCount = 0;
|
|
125265
|
+
var filtered = [];
|
|
125266
|
+
var shown = 0;
|
|
125267
|
+
var lastTurn = null;
|
|
125268
|
+
var turnCounts = {};
|
|
125269
|
+
function ensureRow(idx) {
|
|
125270
|
+
while (rowEls.length <= idx && renderedCount < filtered.length) renderChunk();
|
|
125271
|
+
}
|
|
124992
125272
|
function showTip(text, x, y) {
|
|
124993
125273
|
tip.innerHTML = text;
|
|
124994
125274
|
tip.style.display = 'block';
|
|
@@ -125044,9 +125324,10 @@ function section(title, value, cls) {
|
|
|
125044
125324
|
return '<div class="section"><h4>' + title + '</h4><div class="payload' + (cls ? ' ' + cls : '') + '">' + esc(value) + '</div></div>';
|
|
125045
125325
|
}
|
|
125046
125326
|
function showDetail(i) {
|
|
125327
|
+
ensureRow(i);
|
|
125047
125328
|
if (selectedIndex === i) { hideDetail(); return; }
|
|
125048
125329
|
selectedIndex = i;
|
|
125049
|
-
var cell =
|
|
125330
|
+
var cell = filtered[i];
|
|
125050
125331
|
for (var k = 0; k < rowEls.length; k++) rowEls[k].classList.remove('selected');
|
|
125051
125332
|
if (rowEls[i]) {
|
|
125052
125333
|
rowEls[i].classList.add('selected');
|
|
@@ -125075,6 +125356,8 @@ function renderTimeline(visible) {
|
|
|
125075
125356
|
timeline.innerHTML = '';
|
|
125076
125357
|
if (visible.length < 2) return;
|
|
125077
125358
|
var n = visible.length;
|
|
125359
|
+
// Sample spans on huge documents so the timeline strip stays light.
|
|
125360
|
+
var sampleStep = Math.max(1, Math.ceil(n / 1500));
|
|
125078
125361
|
if (timeMode && visible.every(function (c) { return c.startedAt !== undefined; })) {
|
|
125079
125362
|
var min = Infinity, max = -Infinity;
|
|
125080
125363
|
for (var i = 0; i < n; i++) {
|
|
@@ -125095,13 +125378,13 @@ function renderTimeline(visible) {
|
|
|
125095
125378
|
scaled.push([cs - min, ce - min]);
|
|
125096
125379
|
}
|
|
125097
125380
|
total = max - min;
|
|
125098
|
-
for (var k = 0; k < n; k
|
|
125381
|
+
for (var k = 0; k < n; k += sampleStep) {
|
|
125099
125382
|
var span = makeSpan(visible[k], k, (scaled[k][0] / total) * 100, (scaled[k][1] - scaled[k][0]) / total * 100);
|
|
125100
125383
|
timeline.appendChild(span);
|
|
125101
125384
|
}
|
|
125102
125385
|
} else {
|
|
125103
125386
|
var widthPct = 100 / n;
|
|
125104
|
-
for (var m = 0; m < n; m
|
|
125387
|
+
for (var m = 0; m < n; m += sampleStep) {
|
|
125105
125388
|
var sp = makeSpan(visible[m], m, m * widthPct, widthPct - 0.4);
|
|
125106
125389
|
timeline.appendChild(sp);
|
|
125107
125390
|
}
|
|
@@ -125161,15 +125444,25 @@ function render() {
|
|
|
125161
125444
|
if (q && !(c.text + ' ' + (c.outputDetail || '') + ' ' + (c.thinkingDetail || '')).toLowerCase().includes(q)) return false;
|
|
125162
125445
|
return true;
|
|
125163
125446
|
});
|
|
125164
|
-
|
|
125447
|
+
filtered = currentFiltered;
|
|
125165
125448
|
renderTimeline(filtered);
|
|
125166
125449
|
tbody.innerHTML = '';
|
|
125167
125450
|
rowEls = [];
|
|
125168
|
-
|
|
125169
|
-
|
|
125170
|
-
|
|
125451
|
+
renderedCount = 0;
|
|
125452
|
+
shown = 0;
|
|
125453
|
+
lastTurn = null;
|
|
125454
|
+
turnCounts = {};
|
|
125171
125455
|
for (var i = 0; i < filtered.length; i++) turnCounts[filtered[i].turn || 0] = (turnCounts[filtered[i].turn || 0] || 0) + 1;
|
|
125172
|
-
|
|
125456
|
+
renderChunk();
|
|
125457
|
+
updateCount();
|
|
125458
|
+
}
|
|
125459
|
+
function updateCount() {
|
|
125460
|
+
var el = document.getElementById('count');
|
|
125461
|
+
if (el) el.textContent = shown + ' / ' + filtered.length + ' 条';
|
|
125462
|
+
}
|
|
125463
|
+
function renderChunk() {
|
|
125464
|
+
var end = Math.min(filtered.length, renderedCount + PAGE);
|
|
125465
|
+
for (var i2 = renderedCount; i2 < end; i2++) {
|
|
125173
125466
|
var cell = filtered[i2];
|
|
125174
125467
|
var turn = cell.turn || 0;
|
|
125175
125468
|
var row;
|
|
@@ -125198,7 +125491,7 @@ function render() {
|
|
|
125198
125491
|
if (turnsBtn) turnsBtn.classList.remove('on');
|
|
125199
125492
|
render();
|
|
125200
125493
|
var idx = currentFiltered.findIndex(function (c) { return c.turn === t; });
|
|
125201
|
-
if (idx >= 0
|
|
125494
|
+
if (idx >= 0) { ensureRow(idx); if (rowEls[idx]) { rowEls[idx].scrollIntoView({ block: 'center' }); showDetail(idx); } }
|
|
125202
125495
|
};
|
|
125203
125496
|
})(turn));
|
|
125204
125497
|
tbody.appendChild(trow);
|
|
@@ -125251,8 +125544,9 @@ function render() {
|
|
|
125251
125544
|
shown++;
|
|
125252
125545
|
lastTurn = turn;
|
|
125253
125546
|
}
|
|
125547
|
+
renderedCount = end;
|
|
125254
125548
|
if (!shown) tbody.innerHTML = '<tr><td colspan="2"><div class="placeholder">无匹配记录</div></td></tr>';
|
|
125255
|
-
|
|
125549
|
+
updateCount();
|
|
125256
125550
|
}
|
|
125257
125551
|
if (searchInput) searchInput.addEventListener('input', render);
|
|
125258
125552
|
if (turnsBtn) turnsBtn.addEventListener('click', function () { collapsedTurns = !collapsedTurns; turnsBtn.classList.toggle('on', collapsedTurns); render(); });
|
|
@@ -125295,6 +125589,7 @@ function locateAt(clientX) {
|
|
|
125295
125589
|
var n = currentFiltered.length;
|
|
125296
125590
|
if (n < 2) return;
|
|
125297
125591
|
var idx = Math.round(p * (n - 1));
|
|
125592
|
+
ensureRow(idx);
|
|
125298
125593
|
if (rowEls[idx] && rowEls[idx].scrollIntoView) rowEls[idx].scrollIntoView({ block: 'center' });
|
|
125299
125594
|
}
|
|
125300
125595
|
function timelineRectLeft() {
|
|
@@ -125317,7 +125612,10 @@ function syncLocatorFromTable() {
|
|
|
125317
125612
|
var trackRect = track.getBoundingClientRect();
|
|
125318
125613
|
locator.style.left = (trackRect.left - timelineRectLeft() + p * trackRect.width - 1) + 'px';
|
|
125319
125614
|
}
|
|
125320
|
-
if (tablePane) tablePane.addEventListener('scroll',
|
|
125615
|
+
if (tablePane) tablePane.addEventListener('scroll', function () {
|
|
125616
|
+
syncLocatorFromTable();
|
|
125617
|
+
if (tablePane.scrollTop + tablePane.clientHeight >= tablePane.scrollHeight - 60 && renderedCount < filtered.length) renderChunk();
|
|
125618
|
+
});
|
|
125321
125619
|
render();
|
|
125322
125620
|
syncLocatorFromTable();
|
|
125323
125621
|
`;
|
|
@@ -125368,9 +125666,9 @@ function renderTraceHtml(doc) {
|
|
|
125368
125666
|
</aside>
|
|
125369
125667
|
</div>
|
|
125370
125668
|
</div>
|
|
125669
|
+
<div class="tip" id="tip"></div>
|
|
125371
125670
|
<script id="data" type="application/json">${dataJson}<\/script>
|
|
125372
125671
|
<script>${RENDER_JS}<\/script>
|
|
125373
|
-
<div class="tip" id="tip"></div>
|
|
125374
125672
|
</body>
|
|
125375
125673
|
</html>`;
|
|
125376
125674
|
}
|
|
@@ -128795,7 +129093,7 @@ async function guidedGoalSetup(host) {
|
|
|
128795
129093
|
host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
|
|
128796
129094
|
return;
|
|
128797
129095
|
}
|
|
128798
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
129096
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-D8QuZFfe.mjs");
|
|
128799
129097
|
const initialDesc = await promptText(host, TextInputDialogComponent, {
|
|
128800
129098
|
title: t("goal.setup_title_initial"),
|
|
128801
129099
|
subtitle: t("goal.setup_desc_hint"),
|
|
@@ -128816,7 +129114,7 @@ async function guidedGoalSetup(host) {
|
|
|
128816
129114
|
await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
|
|
128817
129115
|
}
|
|
128818
129116
|
async function showGoalConfigWizard(host, session, objective, replace) {
|
|
128819
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
129117
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-D8QuZFfe.mjs");
|
|
128820
129118
|
const turnInput = await promptNumber(host, TextInputDialogComponent, {
|
|
128821
129119
|
title: t("goal.wizard_title", { objective }),
|
|
128822
129120
|
subtitle: t("goal.budget_turns_hint"),
|
|
@@ -133631,6 +133929,42 @@ function confirmCcConnectUninstall(host, summary) {
|
|
|
133631
133929
|
});
|
|
133632
133930
|
}
|
|
133633
133931
|
//#endregion
|
|
133932
|
+
//#region src/cli/update/prefix.ts
|
|
133933
|
+
/**
|
|
133934
|
+
* The npm global prefix the running Scream Code was installed into, derived
|
|
133935
|
+
* from the entry script path. Example:
|
|
133936
|
+
*
|
|
133937
|
+
* /Users/tod/.npm-global/lib/node_modules/scream-code/dist/main.mjs
|
|
133938
|
+
* → prefix /Users/tod/.npm-global
|
|
133939
|
+
*
|
|
133940
|
+
* `npm install -g` without `--prefix` uses the user's configured npm prefix,
|
|
133941
|
+
* which may point at a root-owned directory (e.g. /usr/local) and fail with
|
|
133942
|
+
* EACCES even though Scream Code itself lives in a user-writable prefix.
|
|
133943
|
+
* Returns undefined when the layout is unrecognized — the install then falls
|
|
133944
|
+
* back to the default prefix behavior.
|
|
133945
|
+
*/
|
|
133946
|
+
function globalPrefixForScream() {
|
|
133947
|
+
const entry = process.argv[1];
|
|
133948
|
+
if (!entry) return void 0;
|
|
133949
|
+
const parts = entry.split(path.sep);
|
|
133950
|
+
const idx = parts.lastIndexOf("node_modules");
|
|
133951
|
+
if (idx < 2 || parts[idx - 1] !== "lib") return void 0;
|
|
133952
|
+
return parts.slice(0, idx - 1).join(path.sep);
|
|
133953
|
+
}
|
|
133954
|
+
/**
|
|
133955
|
+
* Build the `npm install -g scream-code@latest` argument list, adding
|
|
133956
|
+
* `--prefix` when the running Scream Code's global directory can be resolved.
|
|
133957
|
+
*/
|
|
133958
|
+
function installLatestArgs() {
|
|
133959
|
+
const prefix = globalPrefixForScream();
|
|
133960
|
+
return [
|
|
133961
|
+
"install",
|
|
133962
|
+
"-g",
|
|
133963
|
+
"scream-code@latest",
|
|
133964
|
+
...prefix !== void 0 ? ["--prefix", prefix] : []
|
|
133965
|
+
];
|
|
133966
|
+
}
|
|
133967
|
+
//#endregion
|
|
133634
133968
|
//#region src/utils/persistence.ts
|
|
133635
133969
|
/**
|
|
133636
133970
|
* Small persistence helpers for CLI-owned data files.
|
|
@@ -133893,11 +134227,7 @@ async function handleUpdateCommand(host) {
|
|
|
133893
134227
|
}
|
|
133894
134228
|
host.showStatus(t("update.updating", { version: target.version }));
|
|
133895
134229
|
host.showStatus(t("update.npm_install"));
|
|
133896
|
-
const result = await runInstallStep(npmExecutable(),
|
|
133897
|
-
"install",
|
|
133898
|
-
"-g",
|
|
133899
|
-
"scream-code@latest"
|
|
133900
|
-
], void 0, t("update.install_label"));
|
|
134230
|
+
const result = await runInstallStep(npmExecutable(), installLatestArgs(), void 0, t("update.install_label"));
|
|
133901
134231
|
if (!result.ok) {
|
|
133902
134232
|
host.showError(`❌ ${result.message}`);
|
|
133903
134233
|
return;
|
|
@@ -138184,4 +138514,4 @@ async function handleBuiltInSlashCommand(host, name, args) {
|
|
|
138184
138514
|
}
|
|
138185
138515
|
}
|
|
138186
138516
|
//#endregion
|
|
138187
|
-
export { toTerminalHyperlink as $, parseStreamingArgs as $t, highlightLines as A,
|
|
138517
|
+
export { toTerminalHyperlink as $, parseStreamingArgs as $t, highlightLines as A, CLI_UI_MODE as An, ENABLE_TERMINAL_THEME_REPORTING as At, AssistantMessageComponent as B, flushDiagnosticLogs as Bn, isBusy as Bt, UserMessageComponent as C, saveTuiConfig as Cn, contrastTextHex as Ct, ToolCallComponent as D, getLogDir as Dn, DISABLE_TERMINAL_FOCUS_REPORTING as Dt, toggleEmptySessionHint as E, getInputHistoryFile as En, parseOsc11BackgroundTheme as Et, getSharedSpeedTracker as F, saveCatalogCache as Fn, QUERY_TERMINAL_THEME as Ft, resetBreathingClock as G, ErrorCodes as Gn, handleConnectCommand as Gt, WelcomeComponent as H, resolveGlobalLogPath as Hn, FooterComponent as Ht, SkillActivationComponent as I, ScreamHarness as In, TERMINAL_FOCUS_IN as It, handleExportDebugZipCommand as J, STATUS_BULLET as Jt, clearGoalState as K, SCREAM_ERROR_INFO as Kn, handleLogoutCommand as Kt, ReadGroupComponent as L, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE as Ln, TERMINAL_FOCUS_OUT as Lt, CachedContainer as M, PRODUCT_NAME as Mn, OSC11_RESPONSE as Mt, ThinkingComponent as N, DEFAULT_CATALOG_URL as Nn, OSC11_RESPONSE_PREFIX as Nt, renderDiffLines as O, detectInstallSource as On, DISABLE_TERMINAL_THEME_REPORTING as Ot, estimateTokens as P, fetchCatalog as Pn, OSC11_RESPONSE_PREFIX_NO_ESC as Pt, handleTitleCommand as Q, isTodoItemShape as Qt, parseReadGroupOutput as R, resolveScreamHome as Rn, TERMINAL_THEME_DARK as Rt, handleRevokeCommand as S, loadTuiConfig as Sn, createThemeStyles as St, isTurnElapsedEnabled as T, getDataDir as Tn, detectTerminalTheme as Tt, BREATHE_CYCLE_MS as U, isScreamError as Un, handleTraceCommand as Ut, AgentGroupComponent as V, log as Vn, isStreaming as Vt, getBreathingFrame as W, isOrphanedToolCallError as Wn, handleSearchCommand as Wt, handleForkCommand as X, argsRecord as Xt, handleExportMdCommand as Y, appendStreamingArgsPreview as Yt, handleInitCommand as Z, formatErrorMessage as Zt, readUpdateCache as _, setExperimentalFlags as _n, showStatusReport as _t, handleSkillCommand as a, EXIT_CONFIRM_WINDOW_MS as an, handleFusionPlanCommand as at, handleCcCommand as b, TuiConfigParseError as bn, createEditorTheme as bt, isPlanExpandable as c, TIP_ROTATION_INTERVAL_MS as cn, handleThemeCommand as ct, handleMemoryCommand as d, getLlmNotSetMessage as dn, showModelPicker as dt, serializeToolResultOutput as en, changeThinkingLevel as et, handleChannelCommand as f, getNoActiveSessionMessage as fn, showPermissionPicker as ft, refreshUpdateCache as g, isExperimentalFlagEnabled as gn, clearInfoPanelState as gt, selectUpdateTarget as h, sortSlashCommands as hn, supportsBalance as ht, buildRoleAdditionalText as i, EMPTY_SESSION_HINT_URL as in, handleEditorCommand as it, langFromPath as j, CLI_USER_AGENT_PRODUCT as jn, OSC11_QUERY as jt, renderDiffLinesClustered as k, CLI_COMMAND_NAME as kn, ENABLE_TERMINAL_FOCUS_REPORTING as kt, MoonLoader as l, getCtrlCHint as ln, handleWolfpackCommand as lt, handleUpdateCommand as m, BUILTIN_SLASH_COMMANDS as mn, refreshProviderBalance as mt, clearEvalPanelState as n, truncateErrorMessage as nn, handleAutoCommand as nt, disposeChildren as o, MAIN_AGENT_ID$1 as on, handleModelCommand as ot, handleMcpCommand as p, buildSkillSlashCommands as pn, showSettingsSelector as pt, refineGoal as q, printableChar as qt, openUrl as r, CHARS_PER_TOKEN as rn, handleCompactCommand as rt, hasDispose as s, SESSION_TIPS as sn, handlePlanCommand as st, dispatchInput as t, stringValue as tn, getModelCycleLevel as tt, formatMemoryMemoForInjection as u, getCtrlDHint as un, handleYoloCommand as ut, appendJsonlLine as v, PIXEL_PULSE_FRAMES as vn, showUsage as vt, isEmptySessionHintDismissed as w, detectShellEnvironment as wn, getColorPalette as wt, getDaemonInstructions as x, TuiLikePreferencesSchema as xn, createMarkdownTheme as xt, readJsonlFile as y, PULSE_WAVE_FRAMES as yn, resolveThemeSync as yt, BackgroundAgentStatusComponent as z, MemoryMemoStore as zn, TERMINAL_THEME_LIGHT as zt };
|