@epoch-agent/core 2.8.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -5
- package/dist/index.d.ts +909 -163
- package/dist/index.js +1630 -625
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { REASONING_EFFORTS, MODEL_ENTRY_PROTOCOLS, PROVIDER_TYPES, isModelEntryId, parseModelRef, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, BRAND_WHEN_SIDEBAR_COLLAPSED, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MIN_OPTIONS, MAX_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS,
|
|
2
|
-
export { API_KEY_ENV_VARS, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, OPERATION_TYPES, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, ToolExposure, apiKeyEnvVar, extractAllMentions, extractMentions, extractSessionMentions, getProviderInfo, isOperationType, isPermissionLevel, isPlanOutcome, isProviderType, normalizeApproval } from '@epoch-agent/protocol';
|
|
3
|
-
import { existsSync,
|
|
4
|
-
import {
|
|
5
|
-
import { join,
|
|
6
|
-
import { execFile, execSync, execFileSync
|
|
7
|
-
import { createLogger, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, guardSpawn,
|
|
1
|
+
import { REASONING_EFFORTS, MODEL_ENTRY_PROTOCOLS, PROVIDER_TYPES, isModelEntryId, parseModelRef, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, isSettingsPaneId, SETTINGS_PANE_IDS, BRAND_WHEN_SIDEBAR_COLLAPSED, DEFAULT_PERMISSION_LEVEL, resolvePermissionLevel, PERMISSION_LEVELS, SHELL_KINDS, cronTimes, SCHEDULE_MAX_TIMES_PER_DAY, SCHEDULE_INTERVAL_MIN_MINUTES, SCHEDULE_INTERVAL_MAX_MINUTES, ToolExposure, MIN_OPTIONS, MAX_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, SCHEDULE_DEFAULT_PERMISSION, approvalPolicyForLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, OFFLOADED_IMAGE_NOTE, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, entrySecretName, isEntrySecretName, entryRef, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, normalizeAppearanceTranslucent, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, SCHEDULE_DRAFT_SAVED_MARK, imagePartOmittedSummary, ENTRY_REF_PREFIX, placeholdersOf, SCHEDULE_CONFIRM_PLACEHOLDER, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
|
|
2
|
+
export { API_KEY_ENV_VARS, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, LEGACY_LEVEL_ALIASES, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, OPERATION_TYPES, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, ToolExposure, apiKeyEnvVar, approvalPolicyForLevel, extractAllMentions, extractMentions, extractSessionMentions, getProviderInfo, isOperationType, isPermissionLevel, isPlanOutcome, isProviderType, normalizeApproval, resolvePermissionLevel } from '@epoch-agent/protocol';
|
|
3
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync, statSync, readdirSync, readFileSync, renameSync, realpathSync, symlinkSync, cpSync, lstatSync, unlinkSync, rmdirSync, mkdtempSync, copyFileSync, openSync, writeSync, closeSync, readSync } from 'fs';
|
|
4
|
+
import { platform, tmpdir, homedir, hostname } from 'os';
|
|
5
|
+
import { join, resolve, dirname, relative, isAbsolute, extname, sep, basename, delimiter } from 'path';
|
|
6
|
+
import { execFile, spawn, execSync, execFileSync } from 'child_process';
|
|
7
|
+
import { createLogger, t, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, guardSpawn, detectBackend, EXEC_PATH_AS_NODE_ENV, isolate, createStreamDecoder, registerJob, JOB_OUTPUT_LIMIT, artifactsDir, suggestKey, misspelledKeyIssues, openDatabase, migrate, releaseDatabase, parseLenient, issueDetails, splitWords, unknownKeyIssues, checkpointsDir, expandPath, pluginsDir, projectHooksPath, projectClaudeSettingsPath, projectClaudeLocalSettingsPath, projectSettingsPath, projectLocalSettingsPath, projectPoliciesDir, trustedImportsPath, canProbeGit, budgetStatePath, isInWorkspace, UNLIMITED_TURNS, turnLimitOf, configPath, managedSettingsPath, listStoredSecretNames, maskApiKey, unsetSectionField, setSectionField, countCodePoints, headCodePoints, attachmentsDir, workspacesPath, samePath, lastSessionsPath, appearancePath, automationLogsDir, projectComplianceDir, projectSkillsDir, trustPath, projectCommandsDir, parseShellCommand, writeArtifact, sandboxModeForLevel, planEscalation, getSecretValues, envPath, checkDangerousCommand, checkObfuscation, shellSpawnArgs, confine, classifyFailure, keepHeadAndTail, SANDBOX_PERMISSIONS_PARAM, JUSTIFICATION_PARAM, widerTargets, normalizeForMatch, isReadOnlyCommand, CODE_EXEC_ROOTS, tailCodePoints } from '@epoch-agent/infra';
|
|
8
8
|
export { IS_WINDOWS, WINDOWS_HIDE_FLAGS, buildBwrapArgs, buildProfile, checkDangerousCommand, checkObfuscation, createLogger, detectBackend, getDefaultShell, getPythonCommand, isInWorkspace, isReadOnlyCommand, isolate, maskApiKey, probeBubblewrap, probeSeatbelt, complianceDir as resolveComplianceDir, policiesDir as resolvePoliciesDir, setLogLevel } from '@epoch-agent/infra';
|
|
9
9
|
import { createRequire } from 'module';
|
|
10
10
|
import { randomUUID, createHash, randomBytes } from 'crypto';
|
|
@@ -932,7 +932,7 @@ var ToolRegistry = class {
|
|
|
932
932
|
this.addTool(tool, source);
|
|
933
933
|
}
|
|
934
934
|
registerTools(tools, source = "builtin") {
|
|
935
|
-
for (const
|
|
935
|
+
for (const t83 of tools) this.addTool(t83, source);
|
|
936
936
|
}
|
|
937
937
|
addTool(tool, source) {
|
|
938
938
|
const existing = this.tools.get(tool.name);
|
|
@@ -942,6 +942,30 @@ var ToolRegistry = class {
|
|
|
942
942
|
}
|
|
943
943
|
this.tools.set(tool.name, { tool, source });
|
|
944
944
|
}
|
|
945
|
+
replaceBySource(tools, source = "builtin") {
|
|
946
|
+
const incoming = /* @__PURE__ */ new Map();
|
|
947
|
+
for (const tool of tools) {
|
|
948
|
+
if (!incoming.has(tool.name)) incoming.set(tool.name, tool);
|
|
949
|
+
}
|
|
950
|
+
let removed = 0;
|
|
951
|
+
for (const [name, entry] of this.tools) {
|
|
952
|
+
if (entry.source !== source || incoming.has(name)) continue;
|
|
953
|
+
this.tools.delete(name);
|
|
954
|
+
removed++;
|
|
955
|
+
}
|
|
956
|
+
this.conflicts = this.conflicts.filter(
|
|
957
|
+
(c) => c.keptFrom !== source && c.droppedFrom !== source
|
|
958
|
+
);
|
|
959
|
+
for (const tool of incoming.values()) {
|
|
960
|
+
const existing = this.tools.get(tool.name);
|
|
961
|
+
if (existing && existing.source === source) {
|
|
962
|
+
this.tools.set(tool.name, { tool, source });
|
|
963
|
+
continue;
|
|
964
|
+
}
|
|
965
|
+
this.addTool(tool, source);
|
|
966
|
+
}
|
|
967
|
+
return removed;
|
|
968
|
+
}
|
|
945
969
|
unregisterBySource(source) {
|
|
946
970
|
let removed = 0;
|
|
947
971
|
for (const [name, entry] of this.tools) {
|
|
@@ -981,14 +1005,14 @@ var ToolRegistry = class {
|
|
|
981
1005
|
return isCodeModeDeferred(tool) ? ToolExposure.Deferred : declared;
|
|
982
1006
|
}
|
|
983
1007
|
exposed() {
|
|
984
|
-
return this.list().filter((
|
|
1008
|
+
return this.list().filter((t83) => this.exposureOf(t83) === ToolExposure.Direct);
|
|
985
1009
|
}
|
|
986
1010
|
byExposure(exposure) {
|
|
987
|
-
return this.list().filter((
|
|
1011
|
+
return this.list().filter((t83) => this.exposureOf(t83) === exposure);
|
|
988
1012
|
}
|
|
989
1013
|
codeModeDeclared() {
|
|
990
1014
|
if (!this.codeMode) return [];
|
|
991
|
-
return this.list().filter((
|
|
1015
|
+
return this.list().filter((t83) => isCodeModeDeferred(t83));
|
|
992
1016
|
}
|
|
993
1017
|
sourceOf(name) {
|
|
994
1018
|
return this.tools.get(name)?.source;
|
|
@@ -1037,7 +1061,7 @@ var ToolRegistry = class {
|
|
|
1037
1061
|
function staticToolProvider(tools) {
|
|
1038
1062
|
return {
|
|
1039
1063
|
list: () => tools,
|
|
1040
|
-
get: (name) => tools.find((
|
|
1064
|
+
get: (name) => tools.find((t83) => t83.name === name)
|
|
1041
1065
|
};
|
|
1042
1066
|
}
|
|
1043
1067
|
var log = createLogger("tokenizer");
|
|
@@ -1054,8 +1078,8 @@ function fallbackCount(text) {
|
|
|
1054
1078
|
return Math.ceil(text.length / 4);
|
|
1055
1079
|
}
|
|
1056
1080
|
function encoderFor(encoding) {
|
|
1057
|
-
const
|
|
1058
|
-
if (
|
|
1081
|
+
const cached2 = encoders.get(encoding);
|
|
1082
|
+
if (cached2) return cached2;
|
|
1059
1083
|
const entry = { counter: null, memo: /* @__PURE__ */ new Map(), memoChars: 0 };
|
|
1060
1084
|
try {
|
|
1061
1085
|
const mod = loadEncoding(encoding);
|
|
@@ -1339,6 +1363,285 @@ function createAskQuestionTool(deps) {
|
|
|
1339
1363
|
function isAbortSignal(signal) {
|
|
1340
1364
|
return !!signal && typeof signal.addEventListener === "function" && typeof signal.removeEventListener === "function";
|
|
1341
1365
|
}
|
|
1366
|
+
function describeIsolation() {
|
|
1367
|
+
const backend = detectBackend();
|
|
1368
|
+
const os = platform();
|
|
1369
|
+
if (backend === "seatbelt") {
|
|
1370
|
+
return {
|
|
1371
|
+
level: "os",
|
|
1372
|
+
backend,
|
|
1373
|
+
detail: t("sandbox_isolation.seatbelt"),
|
|
1374
|
+
reason: "os-isolated",
|
|
1375
|
+
platform: os
|
|
1376
|
+
};
|
|
1377
|
+
}
|
|
1378
|
+
if (backend === "bubblewrap") {
|
|
1379
|
+
return {
|
|
1380
|
+
level: "os",
|
|
1381
|
+
backend,
|
|
1382
|
+
detail: t("sandbox_isolation.bubblewrap"),
|
|
1383
|
+
reason: "os-isolated",
|
|
1384
|
+
platform: os
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
const [why, reason9] = os === "darwin" ? [t("sandbox_isolation.no_seatbelt"), "backend-unavailable"] : os === "linux" ? [t("sandbox_isolation.no_bubblewrap"), "backend-missing"] : (
|
|
1388
|
+
[t("sandbox_isolation.by_design", { platform: os }), "platform-unsupported"]
|
|
1389
|
+
);
|
|
1390
|
+
return {
|
|
1391
|
+
level: "process",
|
|
1392
|
+
backend,
|
|
1393
|
+
detail: t("sandbox_isolation.process_only", { why }),
|
|
1394
|
+
reason: reason9,
|
|
1395
|
+
platform: os
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
var SANDBOX_COVERS = ["code_exec", "terminal"];
|
|
1399
|
+
var SANDBOX_EXCLUDES = [];
|
|
1400
|
+
// src/sandbox/node-permission.ts
|
|
1401
|
+
var NODE_PERMISSION_MIN = [22, 5];
|
|
1402
|
+
function nodePermissionSupported(platformName, nodeVersion) {
|
|
1403
|
+
if (platformName !== "win32") return false;
|
|
1404
|
+
const [major = Number.NaN, minor = Number.NaN] = nodeVersion.split(".").map((part) => Number.parseInt(part, 10));
|
|
1405
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor)) return false;
|
|
1406
|
+
if (major > NODE_PERMISSION_MIN[0]) return true;
|
|
1407
|
+
if (major < NODE_PERMISSION_MIN[0]) return false;
|
|
1408
|
+
return minor >= NODE_PERMISSION_MIN[1];
|
|
1409
|
+
}
|
|
1410
|
+
function nodePermissionArgs(input) {
|
|
1411
|
+
if (!nodePermissionSupported(input.platformName, input.nodeVersion)) return [];
|
|
1412
|
+
const readable = [.../* @__PURE__ */ new Set([input.sandboxDir, ...input.readableDirs])];
|
|
1413
|
+
return [
|
|
1414
|
+
"--permission",
|
|
1415
|
+
`--allow-fs-read=${readable.join(",")}`,
|
|
1416
|
+
`--allow-fs-write=${input.sandboxDir}`
|
|
1417
|
+
];
|
|
1418
|
+
}
|
|
1419
|
+
// src/sandbox/sandbox.ts
|
|
1420
|
+
var IS_WINDOWS = platform() === "win32";
|
|
1421
|
+
var SANDBOX_ROOT = join(tmpdir(), "epoch-sandbox");
|
|
1422
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
1423
|
+
var MAX_OUTPUT = 1e5;
|
|
1424
|
+
var MAX_MEMORY = 512;
|
|
1425
|
+
var TRUNCATE_HEAD = 2e3;
|
|
1426
|
+
var TRUNCATE_TAIL = 2e3;
|
|
1427
|
+
function resolveExecutable(name) {
|
|
1428
|
+
if (IS_WINDOWS || name.includes("/") || name.includes("\\")) return name;
|
|
1429
|
+
for (const dir of (process.env["PATH"] ?? "").split(delimiter)) {
|
|
1430
|
+
if (!dir) continue;
|
|
1431
|
+
const candidate = join(dir, name);
|
|
1432
|
+
if (existsSync(candidate)) return candidate;
|
|
1433
|
+
}
|
|
1434
|
+
return name;
|
|
1435
|
+
}
|
|
1436
|
+
var CodeSandbox = class {
|
|
1437
|
+
sandboxDir;
|
|
1438
|
+
readableDirs;
|
|
1439
|
+
constructor(sessionId, workDir) {
|
|
1440
|
+
const safeId = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
1441
|
+
this.sandboxDir = join(SANDBOX_ROOT, safeId);
|
|
1442
|
+
mkdirSync(this.sandboxDir, { recursive: true });
|
|
1443
|
+
this.readableDirs = [];
|
|
1444
|
+
if (workDir) {
|
|
1445
|
+
const abs = resolve(workDir);
|
|
1446
|
+
if (abs !== resolve(homedir()) && abs !== "/") this.readableDirs.push(abs);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
getIsolation() {
|
|
1450
|
+
return describeIsolation();
|
|
1451
|
+
}
|
|
1452
|
+
async execute(req) {
|
|
1453
|
+
const start = Date.now();
|
|
1454
|
+
const timeout = req.timeout ?? DEFAULT_TIMEOUT;
|
|
1455
|
+
const isolation = describeIsolation().level;
|
|
1456
|
+
try {
|
|
1457
|
+
const spec = req.language === "javascript" ? this.jsSpec(req.code) : this.pySpec(req.code);
|
|
1458
|
+
const result = await this.run(spec, {
|
|
1459
|
+
timeout,
|
|
1460
|
+
allowNetwork: req.allowNetwork === true,
|
|
1461
|
+
...req.signal ? { signal: req.signal } : {}
|
|
1462
|
+
});
|
|
1463
|
+
return { ...result, isolation };
|
|
1464
|
+
} catch (err) {
|
|
1465
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1466
|
+
if (msg.includes("timed out") || msg.includes("killed")) {
|
|
1467
|
+
return {
|
|
1468
|
+
success: false,
|
|
1469
|
+
output: "",
|
|
1470
|
+
error: `[\u8D85\u65F6] \u8D85\u8FC7 ${timeout / 1e3} \u79D2`,
|
|
1471
|
+
errorType: "timeout",
|
|
1472
|
+
duration: Date.now() - start,
|
|
1473
|
+
isolation
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
return {
|
|
1477
|
+
success: false,
|
|
1478
|
+
output: "",
|
|
1479
|
+
error: `[\u9519\u8BEF] ${msg}`,
|
|
1480
|
+
errorType: "runtime",
|
|
1481
|
+
duration: Date.now() - start,
|
|
1482
|
+
isolation
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
destroy() {
|
|
1487
|
+
try {
|
|
1488
|
+
rmSync(this.sandboxDir, { recursive: true });
|
|
1489
|
+
} catch {
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
getDir() {
|
|
1493
|
+
return this.sandboxDir;
|
|
1494
|
+
}
|
|
1495
|
+
jsSpec(code) {
|
|
1496
|
+
const tmpFile = join(this.sandboxDir, "code.js");
|
|
1497
|
+
writeFileSync(tmpFile, code, "utf-8");
|
|
1498
|
+
return {
|
|
1499
|
+
command: process.execPath,
|
|
1500
|
+
args: [
|
|
1501
|
+
`--max-old-space-size=${MAX_MEMORY}`,
|
|
1502
|
+
...nodePermissionArgs({
|
|
1503
|
+
platformName: platform(),
|
|
1504
|
+
nodeVersion: process.versions.node,
|
|
1505
|
+
sandboxDir: this.sandboxDir,
|
|
1506
|
+
readableDirs: this.readableDirs
|
|
1507
|
+
}),
|
|
1508
|
+
tmpFile
|
|
1509
|
+
],
|
|
1510
|
+
env: EXEC_PATH_AS_NODE_ENV
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
pySpec(code) {
|
|
1514
|
+
const tmpFile = join(this.sandboxDir, "code.py");
|
|
1515
|
+
writeFileSync(tmpFile, code, "utf-8");
|
|
1516
|
+
return {
|
|
1517
|
+
command: resolveExecutable(IS_WINDOWS ? "python" : "python3"),
|
|
1518
|
+
args: ["-I", tmpFile]
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
run(spec, opts) {
|
|
1522
|
+
const start = Date.now();
|
|
1523
|
+
const wrapped = isolate(spec.command, spec.args, {
|
|
1524
|
+
writableDirs: [this.sandboxDir, tmpdir()],
|
|
1525
|
+
readableDirs: this.readableDirs,
|
|
1526
|
+
allowNetwork: opts.allowNetwork,
|
|
1527
|
+
cwd: this.sandboxDir
|
|
1528
|
+
});
|
|
1529
|
+
const { command, args } = wrapped ?? spec;
|
|
1530
|
+
const spawnOpts = {
|
|
1531
|
+
cwd: this.sandboxDir,
|
|
1532
|
+
timeout: opts.timeout,
|
|
1533
|
+
env: {
|
|
1534
|
+
PATH: process.env["PATH"] ?? "",
|
|
1535
|
+
HOME: process.env["HOME"] ?? "",
|
|
1536
|
+
TMPDIR: this.sandboxDir,
|
|
1537
|
+
LANG: process.env["LANG"] ?? "en_US.UTF-8",
|
|
1538
|
+
...spec.env
|
|
1539
|
+
},
|
|
1540
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1541
|
+
...IS_WINDOWS ? { windowsHide: true } : {}
|
|
1542
|
+
};
|
|
1543
|
+
return new Promise((resolve17) => {
|
|
1544
|
+
let stdout = "";
|
|
1545
|
+
let stderr = "";
|
|
1546
|
+
let killedForOutput = false;
|
|
1547
|
+
let child = null;
|
|
1548
|
+
const onAbort = () => {
|
|
1549
|
+
child?.kill("SIGKILL");
|
|
1550
|
+
};
|
|
1551
|
+
const failToStart = (err) => {
|
|
1552
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
1553
|
+
if (err.code === "ENOENT") {
|
|
1554
|
+
resolve17({
|
|
1555
|
+
success: false,
|
|
1556
|
+
output: "",
|
|
1557
|
+
error: `[\u9519\u8BEF] \u627E\u4E0D\u5230\u89E3\u91CA\u5668: ${command}`,
|
|
1558
|
+
errorType: "compile",
|
|
1559
|
+
duration: Date.now() - start
|
|
1560
|
+
});
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
resolve17({
|
|
1564
|
+
success: false,
|
|
1565
|
+
output: "",
|
|
1566
|
+
error: `[\u9519\u8BEF] ${err.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
|
|
1567
|
+
errorType: "runtime",
|
|
1568
|
+
duration: Date.now() - start
|
|
1569
|
+
});
|
|
1570
|
+
};
|
|
1571
|
+
child = guardSpawn(() => spawn(command, args, spawnOpts), failToStart);
|
|
1572
|
+
if (!child) return;
|
|
1573
|
+
const proc = child;
|
|
1574
|
+
let outDecoder = null;
|
|
1575
|
+
let errDecoder = null;
|
|
1576
|
+
proc.stdout?.on("data", (c) => {
|
|
1577
|
+
if (killedForOutput) return;
|
|
1578
|
+
outDecoder ??= createStreamDecoder();
|
|
1579
|
+
stdout += outDecoder.write(c);
|
|
1580
|
+
if (stdout.length >= MAX_OUTPUT) {
|
|
1581
|
+
killedForOutput = true;
|
|
1582
|
+
stdout = stdout.slice(0, MAX_OUTPUT);
|
|
1583
|
+
proc.kill("SIGKILL");
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1586
|
+
proc.stderr?.on("data", (c) => {
|
|
1587
|
+
if (stderr.length >= MAX_OUTPUT) return;
|
|
1588
|
+
errDecoder ??= createStreamDecoder();
|
|
1589
|
+
stderr += errDecoder.write(c);
|
|
1590
|
+
});
|
|
1591
|
+
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
1592
|
+
proc.on("error", failToStart);
|
|
1593
|
+
proc.on("close", (code, sig) => {
|
|
1594
|
+
opts.signal?.removeEventListener("abort", onAbort);
|
|
1595
|
+
if (!killedForOutput) stdout += outDecoder?.end() ?? "";
|
|
1596
|
+
if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
|
|
1597
|
+
const duration = Date.now() - start;
|
|
1598
|
+
if (killedForOutput) {
|
|
1599
|
+
resolve17({
|
|
1600
|
+
success: false,
|
|
1601
|
+
output: trunc(stdout, stderr),
|
|
1602
|
+
error: `[\u8F93\u51FA\u8D85\u9650] \u8D85\u8FC7 ${MAX_OUTPUT} \u5B57\u8282\uFF0C\u5DF2\u7EC8\u6B62`,
|
|
1603
|
+
errorType: "runtime",
|
|
1604
|
+
duration
|
|
1605
|
+
});
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
if (sig) {
|
|
1609
|
+
resolve17({
|
|
1610
|
+
success: false,
|
|
1611
|
+
output: trunc(stdout, stderr),
|
|
1612
|
+
error: opts.signal?.aborted ? "[\u5DF2\u53D6\u6D88]" : "[\u8D85\u65F6] \u6267\u884C\u8D85\u65F6",
|
|
1613
|
+
errorType: "timeout",
|
|
1614
|
+
duration
|
|
1615
|
+
});
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
const output = trunc(stdout, stderr);
|
|
1619
|
+
if (code !== 0 && code !== null) {
|
|
1620
|
+
const oom = /heap out of memory|allocation failed/i.test(stderr);
|
|
1621
|
+
resolve17({
|
|
1622
|
+
success: false,
|
|
1623
|
+
output,
|
|
1624
|
+
error: oom ? `[\u5185\u5B58\u8D85\u9650] \u8D85\u8FC7 ${MAX_MEMORY}MB` : `[\u8FD0\u884C\u65F6\u9519\u8BEF] exit ${code}: ${stderr.slice(0, 200)}`,
|
|
1625
|
+
errorType: oom ? "oom" : "runtime",
|
|
1626
|
+
duration
|
|
1627
|
+
});
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
resolve17({ success: true, output, duration });
|
|
1631
|
+
});
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
function trunc(stdout, stderr) {
|
|
1636
|
+
const nl = "\n";
|
|
1637
|
+
let out = stdout;
|
|
1638
|
+
if (stderr) out += (out ? nl : "") + stderr;
|
|
1639
|
+
if (out.length <= MAX_OUTPUT) return out || "(\u65E0\u8F93\u51FA)";
|
|
1640
|
+
const head = out.slice(0, TRUNCATE_HEAD);
|
|
1641
|
+
const tail = out.slice(-TRUNCATE_TAIL);
|
|
1642
|
+
const skipped = out.length - TRUNCATE_HEAD - TRUNCATE_TAIL;
|
|
1643
|
+
return `${head}${nl}...[\u5DF2\u622A\u65AD ${(skipped / 1024).toFixed(1)} KB]...${nl}${tail}`;
|
|
1644
|
+
}
|
|
1342
1645
|
// src/tools/builtin/code-exec.ts
|
|
1343
1646
|
var MAX_CODE_LENGTH = 1e5;
|
|
1344
1647
|
function createCodeExecTool(sandbox) {
|
|
@@ -1349,7 +1652,9 @@ function createCodeExecTool(sandbox) {
|
|
|
1349
1652
|
"\u5728\u9694\u79BB\u73AF\u5883\u91CC\u6267\u884C\u4E00\u6BB5 JavaScript \u6216 Python\uFF0C\u8FD4\u56DE stdout/stderr\u3002",
|
|
1350
1653
|
"\u9002\u5408\uFF1A\u7B97\u6570\u503C\u3001\u9A8C\u8BC1\u4E00\u6BB5\u903B\u8F91\u3001\u5904\u7406\u6570\u636E\u3001\u5FEB\u901F\u8BD5\u8BED\u6CD5\u3002",
|
|
1351
1654
|
`\u5F53\u524D\u9694\u79BB\u7EA7\u522B\uFF1A${iso.level === "os" ? "OS \u7EA7" : "\u4EC5\u8FDB\u7A0B\u7EA7"}\u2014\u2014${iso.detail}`,
|
|
1352
|
-
iso.level === "os" ? "\u9694\u79BB\u5F71\u54CD\uFF1A\u9ED8\u8BA4\u65E0\u7F51\u7EDC\uFF1B\u786E\u5B9E\u9700\u8981\u8054\u7F51\u65F6\u4F20 allow_network=true\uFF08\u4F1A\u653E\u5F00\u7F51\u7EDC\u9650\u5236\uFF09\u3002" :
|
|
1655
|
+
iso.level === "os" ? "\u9694\u79BB\u5F71\u54CD\uFF1A\u9ED8\u8BA4\u65E0\u7F51\u7EDC\uFF1B\u786E\u5B9E\u9700\u8981\u8054\u7F51\u65F6\u4F20 allow_network=true\uFF08\u4F1A\u653E\u5F00\u7F51\u7EDC\u9650\u5236\uFF09\u3002" : (
|
|
1656
|
+
nodePermissionSupported(iso.platform, process.versions.node) ? "\u9694\u79BB\u5F71\u54CD\uFF1AJavaScript \u90A3\u6863\u7531 Node \u6743\u9650\u6A21\u578B\u6536\u7A84 \u2014\u2014 \u5199\u4E0D\u51FA\u6C99\u7BB1\u76EE\u5F55\u3001\u8D77\u4E0D\u4E86\u5B50\u8FDB\u7A0B\uFF0C\u8BFB\u53D6\u9650\u4E8E\u6C99\u7BB1\u76EE\u5F55\u548C\u5DE5\u4F5C\u533A\uFF1B\u7F51\u7EDC\u4ECD\u7136\u901A\uFF0CPython \u90A3\u6863\u6CA1\u6709\u8FD9\u5C42\u9650\u5236\u3002" : "\u9694\u79BB\u5F71\u54CD\uFF1A\u672C\u5E73\u53F0\u6CA1\u6709 OS \u7EA7\u9694\u79BB\uFF0C\u4EE3\u7801\u80FD\u8BFB\u5199\u6574\u4E2A\u6587\u4EF6\u7CFB\u7EDF\u5E76\u8054\u7F51\uFF0C\u522B\u6267\u884C\u4E0D\u53EF\u4FE1\u4EE3\u7801\u3002"
|
|
1657
|
+
),
|
|
1353
1658
|
"\u5DE5\u4F5C\u76EE\u5F55\u662F\u4E00\u4E2A\u4E34\u65F6\u6C99\u7BB1\u76EE\u5F55\uFF0C\u8FDB\u7A0B\u7ED3\u675F\u540E\u76EE\u5F55\u4F1A\u88AB\u6E05\u7406\u2014\u2014\u9700\u8981\u7559\u5B58\u7684\u7ED3\u679C\u8BF7\u6253\u5370\u51FA\u6765\u3002"
|
|
1354
1659
|
].join("\n"),
|
|
1355
1660
|
parameters: {
|
|
@@ -1660,6 +1965,15 @@ function filterWhole(guard, text) {
|
|
|
1660
1965
|
}
|
|
1661
1966
|
// src/delegate/manager.ts
|
|
1662
1967
|
var ABORTED = "\u5DF2\u4E2D\u6B62\uFF1A\u7528\u6237\u7EC8\u6B62\u4E86\u8FD9\u4E00\u8F6E";
|
|
1968
|
+
var LABEL_LIMIT = 80;
|
|
1969
|
+
function backgroundNotice(id, count) {
|
|
1970
|
+
return [
|
|
1971
|
+
`\u5DF2\u6D3E\u5230\u540E\u53F0\uFF1A${id}\uFF08${count} \u4E2A\u5B50\u4EFB\u52A1\uFF09\u3002\u8FD9\u4E00\u8F6E\u4F60\u53EF\u4EE5\u63A5\u7740\u5E72\u522B\u7684\u3002`,
|
|
1972
|
+
`\u53D6\u7ED3\u8BBA\uFF1Atask_wait ${id}\uFF08\u963B\u585E\u7B49\u5B83\u7ED3\u675F\uFF09\u6216 task_output ${id}\uFF08\u770B\u8FDB\u5EA6\uFF09\u3002`,
|
|
1973
|
+
`\u5B83\u4EEC\u8DD1\u5B8C\u4F1A\u5728\u4E0B\u4E00\u8F6E\u63D0\u793A\u4F60\u3002`,
|
|
1974
|
+
`\u26A0\uFE0F \u7528\u6237\u6309\u505C\u6B62\u53EA\u505C\u4F60\u81EA\u5DF1\u8FD9\u4E00\u8F6E\uFF0C**\u4E0D\u4F1A**\u505C\u6389\u5B83\u4EEC\uFF1B\u8981\u6536\u8D70\u7528 task_stop ${id}\u3002`
|
|
1975
|
+
].join("\n");
|
|
1976
|
+
}
|
|
1663
1977
|
var BLOCKED_TOOLS = Object.freeze([
|
|
1664
1978
|
"delegate_task",
|
|
1665
1979
|
"clarify",
|
|
@@ -1685,7 +1999,7 @@ var DelegateManager = class {
|
|
|
1685
1999
|
this.config = {
|
|
1686
2000
|
max_concurrent_children: 3,
|
|
1687
2001
|
max_spawn_depth: 1,
|
|
1688
|
-
task_timeout:
|
|
2002
|
+
task_timeout: 9e5,
|
|
1689
2003
|
...config
|
|
1690
2004
|
};
|
|
1691
2005
|
}
|
|
@@ -1700,27 +2014,93 @@ var DelegateManager = class {
|
|
|
1700
2014
|
duration: 0
|
|
1701
2015
|
};
|
|
1702
2016
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
duration:
|
|
1709
|
-
}
|
|
2017
|
+
if (tasks.length === 0) {
|
|
2018
|
+
return { success: true, output: this.buildSummary([], Date.now() - start), duration: 0 };
|
|
2019
|
+
}
|
|
2020
|
+
const background = args.background === true;
|
|
2021
|
+
if (signal?.aborted) {
|
|
2022
|
+
return { success: false, output: ABORTED, duration: 0 };
|
|
2023
|
+
}
|
|
2024
|
+
const controller = new AbortController();
|
|
2025
|
+
const job = background ? this.registerJob(parentSessionId, tasks, controller) : void 0;
|
|
2026
|
+
const unlink = background ? () => {
|
|
2027
|
+
} : linkAbort(isAbortSignal(signal) ? signal : void 0, controller);
|
|
2028
|
+
const run = this.runWithConcurrency(
|
|
2029
|
+
tasks,
|
|
2030
|
+
maxConcurrent,
|
|
2031
|
+
parentSessionId,
|
|
2032
|
+
controller.signal,
|
|
2033
|
+
job ? (r) => job.append(`${r.success ? "\u2705" : "\u274C"} ${this.describeResult(r)}
|
|
2034
|
+
`) : void 0,
|
|
2035
|
+
job ? (line) => job.append(`${line}
|
|
2036
|
+
`) : void 0
|
|
2037
|
+
).then((results) => {
|
|
2038
|
+
const total = Date.now() - start;
|
|
2039
|
+
const summary = this.buildSummary(results, total);
|
|
2040
|
+
const ok2 = results.every((r) => r.success);
|
|
2041
|
+
if (job) {
|
|
2042
|
+
job.append(`
|
|
2043
|
+
${summary}`);
|
|
2044
|
+
job.finish(ok2 ? "exited" : "failed");
|
|
2045
|
+
}
|
|
2046
|
+
return { results, summary, total, ok: ok2 };
|
|
2047
|
+
});
|
|
2048
|
+
if (background && job) {
|
|
2049
|
+
void run.catch(() => void 0);
|
|
2050
|
+
return {
|
|
2051
|
+
success: true,
|
|
2052
|
+
output: backgroundNotice(job.id, tasks.length),
|
|
2053
|
+
duration: Date.now() - start,
|
|
2054
|
+
jobId: job.id,
|
|
2055
|
+
background: true
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
try {
|
|
2059
|
+
const r = await run;
|
|
2060
|
+
return {
|
|
2061
|
+
success: r.ok,
|
|
2062
|
+
output: r.summary,
|
|
2063
|
+
duration: r.total,
|
|
2064
|
+
...job ? { jobId: job.id } : {}
|
|
2065
|
+
};
|
|
2066
|
+
} finally {
|
|
2067
|
+
unlink();
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
registerJob(parentSessionId, tasks, controller) {
|
|
2071
|
+
const label = tasks.map((t83) => t83.goal).join(" | ");
|
|
2072
|
+
return registerJob({
|
|
2073
|
+
sessionId: parentSessionId,
|
|
2074
|
+
kind: "agent",
|
|
2075
|
+
label: label.length > LABEL_LIMIT ? `${label.slice(0, LABEL_LIMIT)}\u2026` : label,
|
|
2076
|
+
maxOutput: JOB_OUTPUT_LIMIT,
|
|
2077
|
+
artifactsDir: artifactsDir(parentSessionId),
|
|
2078
|
+
artifactLabel: "agent",
|
|
2079
|
+
stop: async () => {
|
|
2080
|
+
controller.abort();
|
|
2081
|
+
},
|
|
2082
|
+
terminates: true,
|
|
2083
|
+
detail: { abort: controller }
|
|
2084
|
+
});
|
|
1710
2085
|
}
|
|
1711
2086
|
normalizeTasks(args) {
|
|
1712
2087
|
if (args.tasks && args.tasks.length > 0) {
|
|
1713
|
-
return args.role ? args.tasks.map((
|
|
2088
|
+
return args.role ? args.tasks.map((t83) => ({ ...t83, role: t83.role ?? args.role })) : args.tasks;
|
|
1714
2089
|
}
|
|
1715
2090
|
if (args.goal) return [{ goal: args.goal, ...args.role ? { role: args.role } : {} }];
|
|
1716
2091
|
return [];
|
|
1717
2092
|
}
|
|
1718
|
-
async runWithConcurrency(tasks, maxConcurrent, parentSessionId, signal) {
|
|
2093
|
+
async runWithConcurrency(tasks, maxConcurrent, parentSessionId, signal, onDone, onProgress) {
|
|
1719
2094
|
const results = [];
|
|
1720
2095
|
for (let i = 0; i < tasks.length; i += maxConcurrent) {
|
|
1721
2096
|
const batch = tasks.slice(i, i + maxConcurrent);
|
|
1722
2097
|
const batchResults = await Promise.allSettled(
|
|
1723
|
-
batch.map(
|
|
2098
|
+
batch.map(
|
|
2099
|
+
(t83) => this.runSingleTask(t83, parentSessionId, signal, onProgress).then((r) => {
|
|
2100
|
+
onDone?.(r);
|
|
2101
|
+
return r;
|
|
2102
|
+
})
|
|
2103
|
+
)
|
|
1724
2104
|
);
|
|
1725
2105
|
for (const r of batchResults) {
|
|
1726
2106
|
if (r.status === "fulfilled") {
|
|
@@ -1738,7 +2118,7 @@ var DelegateManager = class {
|
|
|
1738
2118
|
}
|
|
1739
2119
|
return results;
|
|
1740
2120
|
}
|
|
1741
|
-
async runSingleTask(task, parentSessionId, signal) {
|
|
2121
|
+
async runSingleTask(task, parentSessionId, signal, onProgress) {
|
|
1742
2122
|
const start = Date.now();
|
|
1743
2123
|
const sessionId = `delegate-${randomUUID().slice(0, 8)}`;
|
|
1744
2124
|
const failed = (error, summary = "") => ({
|
|
@@ -1755,22 +2135,24 @@ var DelegateManager = class {
|
|
|
1755
2135
|
const ms = this.config.task_timeout;
|
|
1756
2136
|
let timer;
|
|
1757
2137
|
try {
|
|
1758
|
-
const
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
2138
|
+
const work = this.runner(
|
|
2139
|
+
task.goal,
|
|
2140
|
+
task.context ?? "",
|
|
2141
|
+
sessionId,
|
|
2142
|
+
task.role,
|
|
2143
|
+
parentSessionId,
|
|
2144
|
+
controller.signal,
|
|
2145
|
+
onProgress
|
|
2146
|
+
);
|
|
2147
|
+
const result = await (ms > 0 ? Promise.race([
|
|
2148
|
+
work,
|
|
1767
2149
|
new Promise((_, reject2) => {
|
|
1768
2150
|
timer = setTimeout(() => {
|
|
1769
2151
|
reject2(new Error(`\u8D85\u65F6 (${ms / 1e3}s)`));
|
|
1770
2152
|
controller.abort();
|
|
1771
2153
|
}, ms);
|
|
1772
2154
|
})
|
|
1773
|
-
]);
|
|
2155
|
+
]) : work);
|
|
1774
2156
|
if (controller.signal.aborted) return failed(ABORTED, result.text);
|
|
1775
2157
|
return {
|
|
1776
2158
|
goal: task.goal,
|
|
@@ -1789,6 +2171,10 @@ var DelegateManager = class {
|
|
|
1789
2171
|
unlink();
|
|
1790
2172
|
}
|
|
1791
2173
|
}
|
|
2174
|
+
describeResult(r) {
|
|
2175
|
+
const who = r.role ? `[${r.role}] ` : "";
|
|
2176
|
+
return `${who}${r.goal} (${r.duration}ms)`;
|
|
2177
|
+
}
|
|
1792
2178
|
buildSummary(results, totalDuration) {
|
|
1793
2179
|
const lines = [];
|
|
1794
2180
|
const succeeded = results.filter((r) => r.success).length;
|
|
@@ -1835,8 +2221,15 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1835
2221
|
"\u628A\u4E00\u6279\u76F8\u4E92\u72EC\u7ACB\u7684\u5B50\u4EFB\u52A1\u6D3E\u7ED9\u5B50 agent \u5E76\u884C\u6267\u884C\uFF0C\u62FF\u56DE\u5404\u81EA\u7684\u7ED3\u8BBA\u3002",
|
|
1836
2222
|
"\u9002\u5408\uFF1A\u9700\u8981\u5206\u522B\u8C03\u7814\u591A\u4E2A\u6A21\u5757\u3001\u540C\u65F6\u9A8C\u8BC1\u591A\u4E2A\u5047\u8BBE\u3001\u6279\u91CF\u5904\u7406\u4E92\u4E0D\u4F9D\u8D56\u7684\u6539\u52A8\u3002",
|
|
1837
2223
|
"\u4E0D\u9002\u5408\uFF1A\u6709\u5148\u540E\u4F9D\u8D56\u7684\u6B65\u9AA4\uFF08\u81EA\u5DF1\u6309\u987A\u5E8F\u505A\u5C31\u884C\uFF09\u3001\u9700\u8981\u6765\u56DE\u8FFD\u95EE\u7684\u4EFB\u52A1\u3002",
|
|
2224
|
+
"\u9ED8\u8BA4**\u7B49\u5B83\u4EEC\u5168\u90E8\u8DD1\u5B8C**\u518D\u8FD4\u56DE\uFF08\u5341\u51E0\u6B21\u5DE5\u5177\u8C03\u7528\u5C31\u56DE\u6765\u4E86\uFF0C\u5E38\u89C1\u60C5\u5F62\u7528\u8FD9\u4E2A\uFF09\u3002",
|
|
2225
|
+
"\u4F60\u81EA\u5DF1\u8FD8\u6709\u522B\u7684\u6D3B\u8981\u5E72\u3001\u4E0D\u5FC5\u7B49\u7ED3\u8BBA\u65F6\u4F20 background: true\uFF1A\u7ACB\u523B\u8FD4\u56DE\u4E00\u4E2A\u4F5C\u4E1A id\uFF08\u6BD4\u5982 a1\uFF09\uFF0C",
|
|
2226
|
+
"\u8FD9\u4E00\u8F6E\u63A5\u7740\u5E72\u522B\u7684\u3002\u4E4B\u540E\u7528 task_wait a1 \u7B49\u7ED3\u679C\u3001task_output a1 \u770B\u8FDB\u5EA6\u3001task_stop a1 \u6536\u6389\u5B83\uFF1B",
|
|
2227
|
+
"\u5B83\u4EEC\u8DD1\u5B8C\u4E5F\u4F1A\u5728\u4E0B\u4E00\u8F6E\u63D0\u793A\u4F60\u3002",
|
|
2228
|
+
"\u26A0\uFE0F \u540E\u53F0\u5B50\u4EFB\u52A1\u4E0D\u8DDF\u7740\u7236\u56DE\u5408\u8D70 \u2014\u2014 \u7528\u6237\u6309\u505C\u6B62\u53EA\u505C\u7236\u56DE\u5408\uFF0C\u5B83\u4EEC\u4F1A\u7EE7\u7EED\u8DD1\uFF08\u8981\u6536\u5F97 task_stop\uFF09\u3002",
|
|
1838
2229
|
`\u5B50 agent \u62FF\u4E0D\u5230\u8FD9\u4E9B\u5DE5\u5177\uFF1A${BLOCKED_TOOLS.join(", ")}\uFF0C\u4E5F\u4E0D\u80FD\u518D\u5F80\u4E0B\u6D3E\u6D3B\u3002`,
|
|
1839
2230
|
"\u5B50 agent \u770B\u4E0D\u5230\u5F53\u524D\u5BF9\u8BDD\uFF0C\u6240\u6709\u5FC5\u8981\u4FE1\u606F\u90FD\u8981\u5199\u8FDB goal \u548C context\u3002",
|
|
2231
|
+
"\u8D85\u65F6\uFF1A\u5355\u4E2A\u5B50\u4EFB\u52A1\u9ED8\u8BA4 15 \u5206\u949F\uFF08\u914D\u7F6E delegate.taskTimeoutSec \u53EF\u8C03\uFF0C0 = \u4E0D\u9650\u65F6\uFF09\uFF1B\u649E\u4E0A\u5C31\u6390\u6389\uFF0C\u90A3\u534A\u622A\u7ED3\u8BBA\u4E0D\u4FDD\u7559\u3002",
|
|
2232
|
+
"\u5B83\u8DD1\u5B8C\u4E4B\u540E\u8FD9\u4E00\u8F6E\u4F1A\u843D\u8FDB\u4F1A\u8BDD\u5E93\uFF08\u5E26 parent_id\uFF09\uFF1A\u60F3\u77E5\u9053\u5B83\u4E2D\u95F4\u8BFB\u4E86\u4EC0\u4E48\u3001\u8BD5\u8FC7\u54EA\u4E9B\u8DEF\uFF0C\u7528 session_trace \u627E\u5230\u5B83\u7684\u4F1A\u8BDD\u518D session_messages_read \u8FDB\u53BB\u770B\u3002",
|
|
1840
2233
|
...renderRoles(listRoles())
|
|
1841
2234
|
].join("\n");
|
|
1842
2235
|
},
|
|
@@ -1863,7 +2256,11 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1863
2256
|
},
|
|
1864
2257
|
goal: { type: "string", description: "\u5355\u4E2A\u4EFB\u52A1\u7684\u76EE\u6807\uFF08tasks \u7684\u7B80\u5199\u5F62\u5F0F\uFF09" },
|
|
1865
2258
|
...role ? { role } : {},
|
|
1866
|
-
max_concurrent: { type: "number", description: "\u6700\u5927\u5E76\u53D1\u6570\uFF08\u9ED8\u8BA4 3\uFF09" }
|
|
2259
|
+
max_concurrent: { type: "number", description: "\u6700\u5927\u5E76\u53D1\u6570\uFF08\u9ED8\u8BA4 3\uFF09" },
|
|
2260
|
+
background: {
|
|
2261
|
+
type: "boolean",
|
|
2262
|
+
description: "true = \u6D3E\u5230\u540E\u53F0\u7ACB\u523B\u8FD4\u56DE\u4F5C\u4E1A id\uFF08a1\uFF09\uFF1B\u4E0D\u7ED9 = \u7B49\u5B83\u4EEC\u5168\u90E8\u8DD1\u5B8C\u518D\u8FD4\u56DE\u3002"
|
|
2263
|
+
}
|
|
1867
2264
|
}
|
|
1868
2265
|
};
|
|
1869
2266
|
},
|
|
@@ -1878,21 +2275,21 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1878
2275
|
operation: "command",
|
|
1879
2276
|
describeTarget: (args) => {
|
|
1880
2277
|
const tasks = Array.isArray(args["tasks"]) ? args["tasks"] : [];
|
|
1881
|
-
const goals = tasks.map((
|
|
2278
|
+
const goals = tasks.map((t83) => String(t83["goal"] ?? ""));
|
|
1882
2279
|
const single = typeof args["goal"] === "string" ? args["goal"] : "";
|
|
1883
2280
|
return [...goals, single].filter(Boolean).join(" | ");
|
|
1884
2281
|
},
|
|
1885
2282
|
async execute(args, ctx) {
|
|
1886
2283
|
const start = Date.now();
|
|
1887
2284
|
const rawTasks = Array.isArray(args["tasks"]) ? args["tasks"] : void 0;
|
|
1888
|
-
const tasks = rawTasks?.map((
|
|
1889
|
-
const o =
|
|
2285
|
+
const tasks = rawTasks?.map((t83) => {
|
|
2286
|
+
const o = t83;
|
|
1890
2287
|
return {
|
|
1891
2288
|
goal: String(o["goal"] ?? "").trim(),
|
|
1892
2289
|
context: String(o["context"] ?? ""),
|
|
1893
2290
|
...typeof o["role"] === "string" && o["role"].trim() ? { role: o["role"].trim() } : {}
|
|
1894
2291
|
};
|
|
1895
|
-
}).filter((
|
|
2292
|
+
}).filter((t83) => t83.goal.length > 0);
|
|
1896
2293
|
const goal = typeof args["goal"] === "string" ? args["goal"].trim() : "";
|
|
1897
2294
|
const topRole = typeof args["role"] === "string" ? args["role"].trim() : "";
|
|
1898
2295
|
if ((!tasks || tasks.length === 0) && !goal) {
|
|
@@ -1908,7 +2305,7 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1908
2305
|
};
|
|
1909
2306
|
}
|
|
1910
2307
|
const known = listRoles();
|
|
1911
|
-
const requested = [...(tasks ?? []).map((
|
|
2308
|
+
const requested = [...(tasks ?? []).map((t83) => t83.role), topRole].filter(
|
|
1912
2309
|
(r) => Boolean(r)
|
|
1913
2310
|
);
|
|
1914
2311
|
const unknown = [...new Set(requested)].filter((r) => !known.some((k) => k.name === r));
|
|
@@ -1930,7 +2327,8 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1930
2327
|
...tasks && tasks.length > 0 ? { tasks } : {},
|
|
1931
2328
|
...goal ? { goal } : {},
|
|
1932
2329
|
...topRole ? { role: topRole } : {},
|
|
1933
|
-
...maxConcurrent ? { max_concurrent: maxConcurrent } : {}
|
|
2330
|
+
...maxConcurrent ? { max_concurrent: maxConcurrent } : {},
|
|
2331
|
+
...args["background"] === true ? { background: true } : {}
|
|
1934
2332
|
},
|
|
1935
2333
|
ctx.sessionId,
|
|
1936
2334
|
ctx.signal
|
|
@@ -2082,8 +2480,8 @@ function createGoalTool(deps) {
|
|
|
2082
2480
|
}
|
|
2083
2481
|
var VALID_TARGETS = ["memory", "user"];
|
|
2084
2482
|
var VALID_ACTIONS = ["add", "replace", "remove", "search", "read", "budget"];
|
|
2085
|
-
function isValidTarget(
|
|
2086
|
-
return typeof
|
|
2483
|
+
function isValidTarget(t83) {
|
|
2484
|
+
return typeof t83 === "string" && VALID_TARGETS.includes(t83);
|
|
2087
2485
|
}
|
|
2088
2486
|
function isValidAction(a) {
|
|
2089
2487
|
return VALID_ACTIONS.includes(a);
|
|
@@ -2278,6 +2676,9 @@ function unknownToolNotice(name) {
|
|
|
2278
2676
|
function codeModeDeclaredNotice(name) {
|
|
2279
2677
|
return `\u5DE5\u5177 ${name} \u4E0D\u5728\u4F60\u7684\u5DE5\u5177\u8868\u91CC\uFF0C\u4F46\u5B83**\u5B58\u5728** \u2014\u2014 \u5F53\u524D\u662F code \u6863\uFF0C\u5B83\u548C\u5176\u4F59\u8BFB\u7C7B\u5DE5\u5177\u4E00\u8D77\u6539\u4EE5 <code_mode_sdk> \u90A3\u6BB5\u58F0\u660E\u5B58\u5728\u3002\u8BF7\u7528 run_code \u5199\u4E00\u6BB5\u7A0B\u5E8F\u3001\u5728\u91CC\u9762 \`await tools.${name}({ ... })\` \u8C03\u5B83\u3002`;
|
|
2280
2678
|
}
|
|
2679
|
+
function policyNotice() {
|
|
2680
|
+
return "run_code \u7684\u8FD0\u884C\u65F6\u6743\u9650\u7B56\u7565\u6CA1\u80FD\u542F\u52A8\u5B83\u81EA\u5DF1\u7684\u5165\u53E3\uFF08\u5185\u90E8\u914D\u7F6E\u95EE\u9898\uFF09\u3002\u8FD9\u4E0D\u662F\u4F60\u7684\u7A0B\u5E8F\u7684\u95EE\u9898\uFF0C\u8BF7\u6539\u7528\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u3002";
|
|
2681
|
+
}
|
|
2281
2682
|
function noChannelNotice() {
|
|
2282
2683
|
return "run_code \u5728\u5F53\u524D\u5BBF\u4E3B\u91CC\u4E0D\u53EF\u7528\uFF1A\u5B50\u8C03\u7528\u901A\u9053\u6CA1\u6709\u63A5\u4E0A\u3002\u8BF7\u6539\u7528\u76F4\u63A5\u8C03\u7528\u5DE5\u5177\u3002";
|
|
2283
2684
|
}
|
|
@@ -2297,6 +2698,47 @@ ${outcome.value}`);
|
|
|
2297
2698
|
if (parts.length === 1 && outcome.ok) parts.push("(\u7A0B\u5E8F\u6CA1\u6709\u6253\u5370\u4E5F\u6CA1\u6709\u8FD4\u56DE\u4EFB\u4F55\u4E1C\u897F)");
|
|
2298
2699
|
return parts.join("\n");
|
|
2299
2700
|
}
|
|
2701
|
+
function workerExecArgv(input) {
|
|
2702
|
+
const flag = permissionFlag();
|
|
2703
|
+
if (!flag) return void 0;
|
|
2704
|
+
const entryDirs = bothForms(parentOf(realOrSame(input.entry)));
|
|
2705
|
+
const cwds = bothForms(input.cwd);
|
|
2706
|
+
const tmps = bothForms(tmpdir());
|
|
2707
|
+
const args = [flag];
|
|
2708
|
+
for (const dir of unique([...entryDirs, ...cwds, ...tmps])) args.push(`--allow-fs-read=${dir}`);
|
|
2709
|
+
for (const dir of unique([...cwds, ...tmps])) args.push(`--allow-fs-write=${dir}`);
|
|
2710
|
+
return args;
|
|
2711
|
+
}
|
|
2712
|
+
function bothForms(path) {
|
|
2713
|
+
const real = realOrSame(path);
|
|
2714
|
+
return real === path ? [path] : [path, real];
|
|
2715
|
+
}
|
|
2716
|
+
function workerEnv() {
|
|
2717
|
+
const kept = {};
|
|
2718
|
+
for (const key of TEMP_ENV_KEYS) {
|
|
2719
|
+
const value = process.env[key];
|
|
2720
|
+
if (value) kept[key] = value;
|
|
2721
|
+
}
|
|
2722
|
+
return kept;
|
|
2723
|
+
}
|
|
2724
|
+
var TEMP_ENV_KEYS = ["TMPDIR", "TMP", "TEMP"];
|
|
2725
|
+
function permissionFlag() {
|
|
2726
|
+
return process.allowedNodeEnvironmentFlags.has("--permission") ? "--permission" : void 0;
|
|
2727
|
+
}
|
|
2728
|
+
function realOrSame(path) {
|
|
2729
|
+
try {
|
|
2730
|
+
return realpathSync(path);
|
|
2731
|
+
} catch {
|
|
2732
|
+
return path;
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
function parentOf(path) {
|
|
2736
|
+
const cut = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));
|
|
2737
|
+
return cut > 0 ? path.slice(0, cut) : path;
|
|
2738
|
+
}
|
|
2739
|
+
function unique(paths) {
|
|
2740
|
+
return [...new Set(paths.filter((p) => p.length > 0))];
|
|
2741
|
+
}
|
|
2300
2742
|
var WORKER_BASENAME = "worker";
|
|
2301
2743
|
var WORKER_DIR = "code-mode";
|
|
2302
2744
|
function resolveCodeModeWorker(baseDir, exists2 = existsSync) {
|
|
@@ -2330,11 +2772,14 @@ async function runCode(input) {
|
|
|
2330
2772
|
maxValueChars: limits.maxValueChars,
|
|
2331
2773
|
cwd: input.cwd
|
|
2332
2774
|
};
|
|
2775
|
+
const execArgv = workerExecArgv({ entry, cwd: input.cwd });
|
|
2333
2776
|
const worker = new Worker(entry, {
|
|
2334
2777
|
workerData,
|
|
2335
2778
|
stdout: true,
|
|
2336
2779
|
stderr: true,
|
|
2337
|
-
resourceLimits: { maxOldGenerationSizeMb: limits.maxMemoryMb }
|
|
2780
|
+
resourceLimits: { maxOldGenerationSizeMb: limits.maxMemoryMb },
|
|
2781
|
+
env: workerEnv(),
|
|
2782
|
+
...execArgv ? { execArgv } : {}
|
|
2338
2783
|
});
|
|
2339
2784
|
let printed = "";
|
|
2340
2785
|
const take = (text) => {
|
|
@@ -2394,7 +2839,7 @@ async function runCode(input) {
|
|
|
2394
2839
|
});
|
|
2395
2840
|
worker.on("error", (err) => {
|
|
2396
2841
|
if (settled) return;
|
|
2397
|
-
ending = err.code === "ERR_WORKER_OUT_OF_MEMORY" ? { kind: "oom", message: oomNotice(limits.maxMemoryMb) } : { kind: "failed", message: err.message };
|
|
2842
|
+
ending = err.code === "ERR_WORKER_OUT_OF_MEMORY" ? { kind: "oom", message: oomNotice(limits.maxMemoryMb) } : err.code === "ERR_ACCESS_DENIED" ? { kind: "policy", message: policyNotice() } : { kind: "failed", message: err.message };
|
|
2398
2843
|
finish();
|
|
2399
2844
|
});
|
|
2400
2845
|
worker.on("exit", () => {
|
|
@@ -2482,6 +2927,7 @@ function createRunCodeTool(deps = {}) {
|
|
|
2482
2927
|
"**\u53EA\u6709\u4F60 print \u51FA\u6765\u7684\u548C return \u7684\u4F1A\u56DE\u5230\u5BF9\u8BDD\u91CC** \u2014\u2014 \u81EA\u5DF1\u7B5B\u3002",
|
|
2483
2928
|
"",
|
|
2484
2929
|
`\u9650\u5236\uFF1A\`tools.*\` \u53EA\u653E\u884C**\u53EA\u8BFB**\u5DE5\u5177\uFF08\u5199\u6587\u4EF6\u3001\u8DD1\u547D\u4EE4\u8BF7\u5728\u7A0B\u5E8F\u5916\u76F4\u63A5\u8C03\u90A3\u4E9B\u5DE5\u5177\uFF09\uFF1B\u6700\u591A ${limits.maxToolCalls} \u6B21\u5B50\u8C03\u7528\uFF1B\u9ED8\u8BA4 ${Math.round(limits.timeoutMs / 1e3)} \u79D2\u8D85\u65F6\uFF08timeout \u53C2\u6570\u53EF\u8C03\uFF09\u3002`,
|
|
2930
|
+
"\u7A0B\u5E8F\u672C\u8EAB\u4E5F\u53D7\u9650\u5236\uFF1A\u53EA\u80FD\u8BFB\u5199\u8FD9\u6BB5\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u76EE\u5F55\uFF08\u548C\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55\uFF09\uFF0C\u8D77\u4E0D\u4E86\u5B50\u8FDB\u7A0B\uFF0C\u770B\u4E0D\u5230\u73AF\u5883\u53D8\u91CF\uFF1B\u8054\u7F51\u4ECD\u7136\u53EF\u4EE5\u3002",
|
|
2485
2931
|
"\u6BCF\u4E00\u6B21 `tools.*` \u5B50\u8C03\u7528\u90FD\u7167\u5E38\u8D70\u6743\u9650\u5224\u5B9A\u548C\u5BA1\u6279\u3002",
|
|
2486
2932
|
"**\u6574\u6BB5\u7A0B\u5E8F\u81EA\u5DF1\u4E5F\u8981\u5148\u8FC7\u4E00\u6B21\u5BA1\u6279** \u2014\u2014 \u7528\u6237\u770B\u5230\u7684\u662F\u7A0B\u5E8F\u5168\u6587\uFF0C\u6279\u7684\u662F\u300C\u8FD9\u6BB5\u7A0B\u5E8F\u53EF\u4EE5\u8DD1\u300D\u3002",
|
|
2487
2933
|
"\u7A0B\u5E8F\u91CC\u7684\u5B50\u8C03\u7528**\u770B\u5F97\u5230\u5B8C\u6574\u8F93\u51FA**\uFF08\u6BD4\u4F60\u76F4\u63A5\u8C03\u90A3\u4E2A\u5DE5\u5177\u770B\u5230\u7684\u591A\u5F97\u591A\uFF09\u2014\u2014 \u6240\u4EE5\u7B5B\u5728\u7A0B\u5E8F\u91CC\u505A\u3002"
|
|
@@ -2707,48 +3153,13 @@ function createExitTool(deps) {
|
|
|
2707
3153
|
function createPlanModeTools(deps) {
|
|
2708
3154
|
return [createEnterTool(deps), createExitTool(deps)];
|
|
2709
3155
|
}
|
|
2710
|
-
var SCHEDULE_ISSUE_CODES = [
|
|
2711
|
-
"name-empty",
|
|
2712
|
-
"prompt-empty",
|
|
2713
|
-
"permission-unknown",
|
|
2714
|
-
"work-dir-missing",
|
|
2715
|
-
"budget-missing",
|
|
2716
|
-
"max-turns-invalid",
|
|
2717
|
-
"timeout-invalid",
|
|
2718
|
-
"trigger-time-invalid",
|
|
2719
|
-
"trigger-times-too-many",
|
|
2720
|
-
"trigger-weekdays-empty",
|
|
2721
|
-
"trigger-days-invalid",
|
|
2722
|
-
"trigger-interval-invalid",
|
|
2723
|
-
"trigger-once-date-invalid",
|
|
2724
|
-
"trigger-once-past",
|
|
2725
|
-
"date-range-invalid",
|
|
2726
|
-
"date-range-on-once",
|
|
2727
|
-
"rule-invalid",
|
|
2728
|
-
"bypass-needs-workdir",
|
|
2729
|
-
"bypass-workdir-too-broad",
|
|
2730
|
-
"bypass-needs-limits",
|
|
2731
|
-
"bypass-not-confirmed"
|
|
2732
|
-
];
|
|
2733
|
-
var SCHEDULE_DEFAULTS = {
|
|
2734
|
-
maxTurns: DEFAULT_MAX_TURNS,
|
|
2735
|
-
timeoutMs: 60 * 60 * 1e3
|
|
2736
|
-
};
|
|
2737
|
-
var SCHEDULE_FORM_BUDGET_USD = 200;
|
|
2738
|
-
var SCHEDULE_DEFAULT_ALLOWLIST = {
|
|
2739
|
-
allowTools: [],
|
|
2740
|
-
allowOperations: ["file_read"],
|
|
2741
|
-
allowRules: []
|
|
2742
|
-
};
|
|
2743
|
-
// src/schedule/draft.ts
|
|
2744
3156
|
var bad = (message) => ({ ok: false, message });
|
|
2745
3157
|
var good = (value) => ({ ok: true, value });
|
|
2746
3158
|
var PERMISSION_ORDER = [
|
|
2747
3159
|
"plan",
|
|
2748
3160
|
"default",
|
|
2749
3161
|
"acceptEdits",
|
|
2750
|
-
"auto"
|
|
2751
|
-
"bypass"
|
|
3162
|
+
"auto"
|
|
2752
3163
|
];
|
|
2753
3164
|
var OPERATION_TYPES = [
|
|
2754
3165
|
"file_read",
|
|
@@ -2790,17 +3201,11 @@ function operationList(v) {
|
|
|
2790
3201
|
function permission(v) {
|
|
2791
3202
|
const s = str(v);
|
|
2792
3203
|
if (s === void 0) return bad("permission \u662F\u7A7A\u7684");
|
|
2793
|
-
|
|
3204
|
+
const normalized = resolvePermissionLevel(s) ?? s;
|
|
3205
|
+
if (!PERMISSION_ORDER.includes(normalized)) {
|
|
2794
3206
|
return bad(`permission \u53EA\u80FD\u662F ${PERMISSION_ORDER.join(" / ")} \u4E4B\u4E00\uFF0C\u6536\u5230\u7684\u662F ${s}`);
|
|
2795
3207
|
}
|
|
2796
|
-
return good(
|
|
2797
|
-
}
|
|
2798
|
-
function budget(v) {
|
|
2799
|
-
if (v === void 0) return good(void 0);
|
|
2800
|
-
if (typeof v !== "number" || !Number.isFinite(v) || v <= 0) {
|
|
2801
|
-
return bad("maxBudgetUsd \u8981\u662F\u5927\u4E8E 0 \u7684\u6570\uFF08\u5355\u4F4D\u7F8E\u5143\uFF09\u3002\u4E0D\u7ED9\u5C31\u6309\u65B0\u5EFA\u8868\u5355\u90A3\u4E2A\u7F3A\u7701\uFF08200\uFF09");
|
|
2802
|
-
}
|
|
2803
|
-
return good(v);
|
|
3208
|
+
return good(normalized);
|
|
2804
3209
|
}
|
|
2805
3210
|
function clock(v) {
|
|
2806
3211
|
const s = str(v);
|
|
@@ -2913,13 +3318,11 @@ function parseCreate(raw, note) {
|
|
|
2913
3318
|
}
|
|
2914
3319
|
const trigger = parseTrigger(raw["trigger"]);
|
|
2915
3320
|
if (!trigger.ok) return trigger;
|
|
2916
|
-
const level = permission(raw["permission"]);
|
|
3321
|
+
const level = raw["permission"] === void 0 ? good(SCHEDULE_DEFAULT_PERMISSION) : permission(raw["permission"]);
|
|
2917
3322
|
if (!level.ok) return level;
|
|
2918
3323
|
const allow = parseAllowlist(raw);
|
|
2919
3324
|
if (!allow.ok) return allow;
|
|
2920
3325
|
const workDir = str(raw["workDir"]);
|
|
2921
|
-
const usd = budget(raw["maxBudgetUsd"]);
|
|
2922
|
-
if (!usd.ok) return usd;
|
|
2923
3326
|
return good({
|
|
2924
3327
|
action: "create",
|
|
2925
3328
|
name,
|
|
@@ -2928,7 +3331,6 @@ function parseCreate(raw, note) {
|
|
|
2928
3331
|
permission: level.value,
|
|
2929
3332
|
note,
|
|
2930
3333
|
...workDir === void 0 ? {} : { workDir },
|
|
2931
|
-
...usd.value === void 0 ? {} : { maxBudgetUsd: usd.value },
|
|
2932
3334
|
...allow.value
|
|
2933
3335
|
});
|
|
2934
3336
|
}
|
|
@@ -2963,9 +3365,6 @@ function parseUpdate(raw, note) {
|
|
|
2963
3365
|
const timeout = posInt(raw["timeoutMs"], "timeoutMs");
|
|
2964
3366
|
if (!timeout.ok) return timeout;
|
|
2965
3367
|
if (timeout.value !== void 0) patch.timeoutMs = timeout.value;
|
|
2966
|
-
const usd = budget(raw["maxBudgetUsd"]);
|
|
2967
|
-
if (!usd.ok) return usd;
|
|
2968
|
-
if (usd.value !== void 0) patch.maxBudgetUsd = usd.value;
|
|
2969
3368
|
if (Object.keys(patch).length === 0) {
|
|
2970
3369
|
return bad(
|
|
2971
3370
|
"update \u4E00\u683C\u90FD\u6CA1\u6539\u3002\u4E00\u4EFD\u4EC0\u4E48\u90FD\u4E0D\u6539\u7684\u63D0\u6848\u4F1A\u767D\u5360\u7528\u6237\u4E00\u6B21\u70B9\u51FB \u2014\u2014 \u8981\u4E48\u7ED9\u51FA\u5177\u4F53\u6539\u54EA\u51E0\u683C\uFF0C\u8981\u4E48\u522B\u63D0"
|
|
@@ -2991,7 +3390,7 @@ function parseScheduleDraft(raw) {
|
|
|
2991
3390
|
}
|
|
2992
3391
|
function draftWidening(draft, current) {
|
|
2993
3392
|
const out = [];
|
|
2994
|
-
const base2 = draft.action === "update" && current ? current.permission :
|
|
3393
|
+
const base2 = draft.action === "update" && current ? current.permission : SCHEDULE_DEFAULT_PERMISSION;
|
|
2995
3394
|
const level = draft.permission;
|
|
2996
3395
|
if (level !== void 0 && PERMISSION_ORDER.indexOf(level) > PERMISSION_ORDER.indexOf(base2)) {
|
|
2997
3396
|
out.push("permission");
|
|
@@ -3045,9 +3444,39 @@ function draftCommandLine(draft) {
|
|
|
3045
3444
|
for (const tool of draft.allowTools ?? []) argv.push("--allow-tool", shellArg(tool));
|
|
3046
3445
|
for (const op2 of draft.allowOperations ?? []) argv.push("--allow-operation", op2);
|
|
3047
3446
|
for (const rule of draft.allowRules ?? []) argv.push("--allow-rule", shellArg(rule));
|
|
3048
|
-
argv.push("--budget", String(draft.maxBudgetUsd ?? SCHEDULE_FORM_BUDGET_USD));
|
|
3049
3447
|
return argv.join(" ");
|
|
3050
3448
|
}
|
|
3449
|
+
var SCHEDULE_ISSUE_CODES = [
|
|
3450
|
+
"name-empty",
|
|
3451
|
+
"prompt-empty",
|
|
3452
|
+
"permission-unknown",
|
|
3453
|
+
"work-dir-missing",
|
|
3454
|
+
"max-turns-invalid",
|
|
3455
|
+
"timeout-invalid",
|
|
3456
|
+
"trigger-time-invalid",
|
|
3457
|
+
"trigger-times-too-many",
|
|
3458
|
+
"trigger-weekdays-empty",
|
|
3459
|
+
"trigger-days-invalid",
|
|
3460
|
+
"trigger-interval-invalid",
|
|
3461
|
+
"trigger-once-date-invalid",
|
|
3462
|
+
"trigger-once-past",
|
|
3463
|
+
"date-range-invalid",
|
|
3464
|
+
"date-range-on-once",
|
|
3465
|
+
"rule-invalid",
|
|
3466
|
+
"bypass-needs-workdir",
|
|
3467
|
+
"bypass-workdir-too-broad",
|
|
3468
|
+
"bypass-needs-limits",
|
|
3469
|
+
"bypass-not-confirmed"
|
|
3470
|
+
];
|
|
3471
|
+
var SCHEDULE_DEFAULTS = {
|
|
3472
|
+
maxTurns: DEFAULT_MAX_TURNS,
|
|
3473
|
+
timeoutMs: 60 * 60 * 1e3
|
|
3474
|
+
};
|
|
3475
|
+
var SCHEDULE_DEFAULT_ALLOWLIST = {
|
|
3476
|
+
allowTools: [],
|
|
3477
|
+
allowOperations: ["file_read"],
|
|
3478
|
+
allowRules: []
|
|
3479
|
+
};
|
|
3051
3480
|
// src/schedule/unattended-lint.ts
|
|
3052
3481
|
var ANCHORS = [
|
|
3053
3482
|
{ kind: "asks-human", zh: /问(?:一下|下)?我/, en: /\bask\s+(?:me|us)\b/i },
|
|
@@ -3477,15 +3906,12 @@ function validateSchedule(input) {
|
|
|
3477
3906
|
const now = input.now ?? Date.now();
|
|
3478
3907
|
if (!input.name.trim()) issues.push({ code: "name-empty" });
|
|
3479
3908
|
if (!input.prompt.trim()) issues.push({ code: "prompt-empty" });
|
|
3480
|
-
if (!
|
|
3909
|
+
if (!resolvePermissionLevel(input.permission)) {
|
|
3481
3910
|
issues.push({ code: "permission-unknown", detail: input.permission });
|
|
3482
3911
|
}
|
|
3483
3912
|
if (input.workDir && !isExistingDir(input.workDir)) {
|
|
3484
3913
|
issues.push({ code: "work-dir-missing", detail: input.workDir });
|
|
3485
3914
|
}
|
|
3486
|
-
if (!Number.isFinite(input.maxBudgetUsd) || input.maxBudgetUsd <= 0) {
|
|
3487
|
-
issues.push({ code: "budget-missing", detail: String(input.maxBudgetUsd) });
|
|
3488
|
-
}
|
|
3489
3915
|
if (!Number.isInteger(input.maxTurns) || input.maxTurns < 0) {
|
|
3490
3916
|
issues.push({ code: "max-turns-invalid", detail: String(input.maxTurns) });
|
|
3491
3917
|
}
|
|
@@ -3498,7 +3924,8 @@ function validateSchedule(input) {
|
|
|
3498
3924
|
for (const issue of rules.issues) {
|
|
3499
3925
|
issues.push({ code: "rule-invalid", detail: issue.message });
|
|
3500
3926
|
}
|
|
3501
|
-
|
|
3927
|
+
const level = resolvePermissionLevel(input.permission);
|
|
3928
|
+
if (level && approvalPolicyForLevel(level) === "never") {
|
|
3502
3929
|
issues.push(...bypassIssues(input));
|
|
3503
3930
|
}
|
|
3504
3931
|
return {
|
|
@@ -3511,7 +3938,7 @@ function bypassIssues(input) {
|
|
|
3511
3938
|
if (input.workDir.trim() && isTooBroad(input.workDir, input.homeDir)) {
|
|
3512
3939
|
issues.push({ code: "bypass-workdir-too-broad", detail: input.workDir });
|
|
3513
3940
|
}
|
|
3514
|
-
const missingRuler = !(input.
|
|
3941
|
+
const missingRuler = !(input.timeoutMs > 0);
|
|
3515
3942
|
if (missingRuler) issues.push({ code: "bypass-needs-limits" });
|
|
3516
3943
|
if (input.bypassAcknowledged !== true) issues.push({ code: "bypass-not-confirmed" });
|
|
3517
3944
|
return issues;
|
|
@@ -3529,7 +3956,7 @@ function isExistingDir(path) {
|
|
|
3529
3956
|
}
|
|
3530
3957
|
}
|
|
3531
3958
|
function needsAllowlist(permission2) {
|
|
3532
|
-
return permission2 !== "plan" && permission2 !== "
|
|
3959
|
+
return permission2 !== "plan" && approvalPolicyForLevel(permission2) !== "never";
|
|
3533
3960
|
}
|
|
3534
3961
|
// src/tools/builtin/schedule-draft.ts
|
|
3535
3962
|
function say4(text, ok2, startedAt) {
|
|
@@ -3545,22 +3972,18 @@ var WIDENING_TEXT = {
|
|
|
3545
3972
|
allowlist: "\u6E05\u5355\u591A\u4E86\u6761\u76EE\uFF08= \u591A\u4E86\u51E0\u4EF6\u4E0D\u7ECF\u786E\u8BA4\u5C31\u4F1A\u505A\u7684\u4E8B\uFF09",
|
|
3546
3973
|
enabled: "\u628A\u4E00\u6761\u505C\u7528\u7684\u4EFB\u52A1\u6539\u6210\u542F\u7528"
|
|
3547
3974
|
};
|
|
3548
|
-
function budgetOf(draft, current) {
|
|
3549
|
-
return draft.maxBudgetUsd ?? current?.maxBudgetUsd ?? SCHEDULE_FORM_BUDGET_USD;
|
|
3550
|
-
}
|
|
3551
3975
|
function validateDraft(draft, homeDir, current) {
|
|
3552
|
-
const permission2 = draft.permission ?? current?.permission ??
|
|
3976
|
+
const permission2 = draft.permission ?? current?.permission ?? SCHEDULE_DEFAULT_PERMISSION;
|
|
3553
3977
|
const merged = draft.action === "create" ? {
|
|
3554
3978
|
name: draft.name,
|
|
3555
3979
|
prompt: draft.prompt,
|
|
3556
3980
|
permission: permission2,
|
|
3557
3981
|
workDir: draft.workDir ?? "",
|
|
3558
3982
|
maxTurns: SCHEDULE_DEFAULTS.maxTurns,
|
|
3559
|
-
maxBudgetUsd: budgetOf(draft),
|
|
3560
3983
|
timeoutMs: SCHEDULE_DEFAULTS.timeoutMs,
|
|
3561
3984
|
trigger: draft.trigger,
|
|
3562
3985
|
allowRules: draft.allowRules ?? [],
|
|
3563
|
-
bypassAcknowledged: permission2 === "
|
|
3986
|
+
bypassAcknowledged: approvalPolicyForLevel(permission2) === "never",
|
|
3564
3987
|
homeDir
|
|
3565
3988
|
} : {
|
|
3566
3989
|
name: draft.name ?? current?.name ?? "",
|
|
@@ -3568,11 +3991,10 @@ function validateDraft(draft, homeDir, current) {
|
|
|
3568
3991
|
permission: permission2,
|
|
3569
3992
|
workDir: draft.workDir ?? current?.workDir ?? "",
|
|
3570
3993
|
maxTurns: draft.maxTurns ?? current?.maxTurns ?? SCHEDULE_DEFAULTS.maxTurns,
|
|
3571
|
-
maxBudgetUsd: budgetOf(draft, current),
|
|
3572
3994
|
timeoutMs: draft.timeoutMs ?? current?.timeoutMs ?? SCHEDULE_DEFAULTS.timeoutMs,
|
|
3573
3995
|
trigger: draft.trigger ?? current?.trigger ?? { kind: "cron", cycle: "daily", at: "09:00" },
|
|
3574
3996
|
allowRules: draft.allowRules ?? current?.allowRules ?? [],
|
|
3575
|
-
bypassAcknowledged: permission2 === "
|
|
3997
|
+
bypassAcknowledged: approvalPolicyForLevel(permission2) === "never",
|
|
3576
3998
|
homeDir
|
|
3577
3999
|
};
|
|
3578
4000
|
return validateSchedule(merged).issues.map(
|
|
@@ -3666,15 +4088,14 @@ function summarizeSaved(draft, def, registration, current) {
|
|
|
3666
4088
|
return lines.join("\n");
|
|
3667
4089
|
}
|
|
3668
4090
|
async function persist(save, draft, current) {
|
|
3669
|
-
const permission2 = draft.permission ?? current?.permission ??
|
|
3670
|
-
const acknowledged = { bypassAcknowledged: permission2 === "
|
|
4091
|
+
const permission2 = draft.permission ?? current?.permission ?? SCHEDULE_DEFAULT_PERMISSION;
|
|
4092
|
+
const acknowledged = { bypassAcknowledged: approvalPolicyForLevel(permission2) === "never" };
|
|
3671
4093
|
if (draft.action === "create") {
|
|
3672
4094
|
return save.create(
|
|
3673
4095
|
{
|
|
3674
4096
|
name: draft.name,
|
|
3675
4097
|
prompt: draft.prompt,
|
|
3676
|
-
permission:
|
|
3677
|
-
maxBudgetUsd: budgetOf(draft),
|
|
4098
|
+
permission: permission2,
|
|
3678
4099
|
trigger: draft.trigger,
|
|
3679
4100
|
...draft.workDir === void 0 ? {} : { workDir: draft.workDir },
|
|
3680
4101
|
...draft.allowTools === void 0 ? {} : { allowTools: draft.allowTools },
|
|
@@ -3695,7 +4116,6 @@ async function persist(save, draft, current) {
|
|
|
3695
4116
|
...draft.enabled === void 0 ? {} : { enabled: draft.enabled },
|
|
3696
4117
|
...draft.maxTurns === void 0 ? {} : { maxTurns: draft.maxTurns },
|
|
3697
4118
|
...draft.timeoutMs === void 0 ? {} : { timeoutMs: draft.timeoutMs },
|
|
3698
|
-
...draft.maxBudgetUsd === void 0 ? {} : { maxBudgetUsd: draft.maxBudgetUsd },
|
|
3699
4119
|
...draft.allowTools === void 0 ? {} : { allowTools: draft.allowTools },
|
|
3700
4120
|
...draft.allowOperations === void 0 ? {} : { allowOperations: draft.allowOperations },
|
|
3701
4121
|
...draft.allowRules === void 0 ? {} : { allowRules: draft.allowRules }
|
|
@@ -3706,7 +4126,7 @@ async function persist(save, draft, current) {
|
|
|
3706
4126
|
function createScheduleDraftTool(deps) {
|
|
3707
4127
|
return {
|
|
3708
4128
|
name: SCHEDULE_DRAFT_TOOL,
|
|
3709
|
-
description: "\u5EFA\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\uFF0C\u6216\u8005\u6539\u4E00\u6761\u5DF2\u6709\u7684\u3002\u5B9A\u65F6\u4EFB\u52A1\u662F\u300C\u5230\u70B9\u4E86\u81EA\u5DF1\u8DD1\u4E00\u6B21\u300D\u2014\u2014\u7528\u6237\u8BF4\u300C\u4EE5\u540E\u6BCF\u5929/\u6BCF\u5468\u5E2E\u6211\u505A\u67D0\u4EF6\u4E8B\u300D\u300C\u5B9A\u671F\u68C0\u67E5\u67D0\u67D0\u300D\uFF0C\u6216\u8005\u4F60\u53D1\u73B0\u67D0\u4EF6\u4E8B\u4ED6\u6BCF\u6B21\u90FD\u8981\u624B\u52A8\u505A\u4E00\u904D\u65F6\uFF0C\u7528\u5B83\u3002action=list \u770B\u73B0\u6709\u4EFB\u52A1\uFF08\u8981\u6539\u67D0\u6761\u5FC5\u987B\u5148 list \u62FF\u5230 id\uFF09\uFF1Baction=create \u76F4\u63A5\u5EFA\u4E00\u6761\uFF1Baction=update \u76F4\u63A5\u6539\u4E00\u6761\u3002\u26A0\uFE0F **\u5B83\u4EA4\u4E0A\u53BB\u5C31\u751F\u6548**\uFF08plan \u53EA\u8BFB\u6863\u4E0B\u9664\u5916\uFF0C\u90A3\u4E00\u6863\u53EA\u4EA4\u63D0\u6848\uFF09\u2014\u2014 \u5EFA\u5B8C\u5728\u4F60\u7684\u56DE\u590D\u91CC\u4EA4\u4EE3\u4E00\u53E5\u5C31\u884C\uFF0C\u522B\u95EE\u300C\u8981\u4E0D\u8981\u6211\u5EFA\u300D\u3002\
|
|
4129
|
+
description: "\u5EFA\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\uFF0C\u6216\u8005\u6539\u4E00\u6761\u5DF2\u6709\u7684\u3002\u5B9A\u65F6\u4EFB\u52A1\u662F\u300C\u5230\u70B9\u4E86\u81EA\u5DF1\u8DD1\u4E00\u6B21\u300D\u2014\u2014\u7528\u6237\u8BF4\u300C\u4EE5\u540E\u6BCF\u5929/\u6BCF\u5468\u5E2E\u6211\u505A\u67D0\u4EF6\u4E8B\u300D\u300C\u5B9A\u671F\u68C0\u67E5\u67D0\u67D0\u300D\uFF0C\u6216\u8005\u4F60\u53D1\u73B0\u67D0\u4EF6\u4E8B\u4ED6\u6BCF\u6B21\u90FD\u8981\u624B\u52A8\u505A\u4E00\u904D\u65F6\uFF0C\u7528\u5B83\u3002action=list \u770B\u73B0\u6709\u4EFB\u52A1\uFF08\u8981\u6539\u67D0\u6761\u5FC5\u987B\u5148 list \u62FF\u5230 id\uFF09\uFF1Baction=create \u76F4\u63A5\u5EFA\u4E00\u6761\uFF1Baction=update \u76F4\u63A5\u6539\u4E00\u6761\u3002\u26A0\uFE0F **\u5B83\u4EA4\u4E0A\u53BB\u5C31\u751F\u6548**\uFF08plan \u53EA\u8BFB\u6863\u4E0B\u9664\u5916\uFF0C\u90A3\u4E00\u6863\u53EA\u4EA4\u63D0\u6848\uFF09\u2014\u2014 \u5EFA\u5B8C\u5728\u4F60\u7684\u56DE\u590D\u91CC\u4EA4\u4EE3\u4E00\u53E5\u5C31\u884C\uFF0C\u522B\u95EE\u300C\u8981\u4E0D\u8981\u6211\u5EFA\u300D\u3002\u6743\u9650\u6863\u4E0D\u7ED9\u5C31\u662F auto\uFF08\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701\uFF09\u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\u3002\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u300C\u53EA\u8BFB / \u522B\u52A8\u4E1C\u897F\u300D\u65F6\u624D\u7528 plan\uFF0C\u90A3\u7C7B\u4EFB\u52A1\u5929\u7136\u96F6\u6388\u6743\u9762\u3002",
|
|
3710
4130
|
parameters: {
|
|
3711
4131
|
type: "object",
|
|
3712
4132
|
properties: {
|
|
@@ -3750,12 +4170,8 @@ function createScheduleDraftTool(deps) {
|
|
|
3750
4170
|
},
|
|
3751
4171
|
permission: {
|
|
3752
4172
|
type: "string",
|
|
3753
|
-
description: "\u6743\u9650\u6863\
|
|
3754
|
-
enum: ["plan", "default", "acceptEdits", "auto"
|
|
3755
|
-
},
|
|
3756
|
-
maxBudgetUsd: {
|
|
3757
|
-
type: "number",
|
|
3758
|
-
description: "\u6BCF\u6B21\u6700\u591A\u82B1\u591A\u5C11\u94B1\uFF08\u7F8E\u5143\uFF0C\u8981\u5927\u4E8E 0\uFF09\u3002\u4E0D\u7ED9\u5C31\u662F 200\u3002\u8FD9\u6D3B\u660E\u663E\u66F4\u8F7B\uFF08\u8BFB\u4E00\u4E2A\u6587\u4EF6\u3001\u53D1\u4E00\u6761\u6D88\u606F\uFF09\u5C31\u7ED9\u5C0F\u4E00\u70B9\uFF0C\u660E\u663E\u66F4\u91CD\uFF08\u626B\u5927\u4ED3\u3001\u591A\u8F6E\u8C03\u7814\uFF09\u5C31\u653E\u5927 \u2014\u2014 \u82B1\u8D85\u4E86\u90A3\u4E00\u8F6E\u4F1A\u505C\u4F4F"
|
|
4173
|
+
description: "\u6743\u9650\u6863\u3002\u4E0D\u7ED9\u5C31\u662F auto\uFF08**\u65B0\u5EFA\u4EFB\u52A1\u7684\u7F3A\u7701**\uFF0C2026-10-27 \u8D77\uFF1A\u5B9A\u65F6\u4EFB\u52A1\u6CA1\u4EBA\u53EF\u95EE\uFF0C\u4F4E\u6863\u5728\u8FD9\u91CC\u7B49\u4E8E\u300C\u5230\u70B9\u5FC5\u7136\u5931\u8D25\u300D\uFF09\u3002auto=\u5B8C\u5168\u8BBF\u95EE\uFF08\u4E0D\u518D\u786E\u8BA4\uFF0C\u53EA\u5269\u707E\u96BE\u7EA7\u4F1A\u88AB\u62E6\u4E0B\uFF09\uFF1BacceptEdits=\u8BF7\u6C42\u6279\u51C6\uFF1Bdefault=\u9010\u6761\u786E\u8BA4\uFF1Bplan=\u53EA\u8BFB\uFF08\u8BFB\u4E00\u904D\u5199\u4EFD\u62A5\u544A\u7684\u4EFB\u52A1\u7528\u5B83\uFF0C\u5929\u7136\u96F6\u6388\u6743\u9762\uFF09\u3002**\u53EA\u6709\u5728\u7528\u6237\u660E\u786E\u8BF4\u4E86\u8981\u7A84\u4E00\u6863\u65F6\u624D\u964D**",
|
|
4174
|
+
enum: ["plan", "default", "acceptEdits", "auto"]
|
|
3759
4175
|
},
|
|
3760
4176
|
allowTools: {
|
|
3761
4177
|
type: "array",
|
|
@@ -4010,12 +4426,15 @@ function traceSession(db, input) {
|
|
|
4010
4426
|
truncated
|
|
4011
4427
|
};
|
|
4012
4428
|
}
|
|
4429
|
+
// src/session/types.ts
|
|
4430
|
+
var DELEGATE_SESSION_SOURCE = "delegate";
|
|
4013
4431
|
// src/session/query.ts
|
|
4014
4432
|
var SESSION_SEARCH_TOOL = "session_search";
|
|
4015
4433
|
var SESSION_MESSAGES_SEARCH_TOOL = "session_messages_search";
|
|
4016
4434
|
var SESSION_MESSAGES_READ_TOOL = "session_messages_read";
|
|
4017
4435
|
var SESSION_TRACE_TOOL = "session_trace";
|
|
4018
4436
|
var SESSION_LIST_TOOL = "session_list";
|
|
4437
|
+
var DELEGATE_CLAUSE = "AND COALESCE(s.source, '') != @delegateSource";
|
|
4019
4438
|
var SESSION_QUERY_TOOLS = Object.freeze([
|
|
4020
4439
|
SESSION_SEARCH_TOOL,
|
|
4021
4440
|
SESSION_MESSAGES_SEARCH_TOOL,
|
|
@@ -4118,8 +4537,9 @@ var SessionQueries = class {
|
|
|
4118
4537
|
listSessions(input) {
|
|
4119
4538
|
const vis = resolveSessionVisibility({ ...input, db: this.db });
|
|
4120
4539
|
const archivedClause = input.archived === "all" ? "" : input.archived === "only" ? "AND s.archived = 1" : "AND s.archived = 0";
|
|
4121
|
-
const where = `${vis.clause} ${archivedClause}`;
|
|
4122
|
-
const
|
|
4540
|
+
const where = `${vis.clause} ${archivedClause} ${DELEGATE_CLAUSE}`;
|
|
4541
|
+
const params = { ...vis.params, delegateSource: DELEGATE_SESSION_SOURCE };
|
|
4542
|
+
const total = this.db.prepare(`SELECT count(*) AS n FROM sessions s WHERE ${where}`).get(params).n;
|
|
4123
4543
|
const rows = this.db.prepare(
|
|
4124
4544
|
`SELECT s.id,
|
|
4125
4545
|
COALESCE(NULLIF(s.display_name, ''), s.title) AS title,
|
|
@@ -4131,7 +4551,7 @@ var SessionQueries = class {
|
|
|
4131
4551
|
WHERE ${where}
|
|
4132
4552
|
ORDER BY COALESCE(s.updated_at, s.started_at) DESC
|
|
4133
4553
|
LIMIT @limit`
|
|
4134
|
-
).all({ ...
|
|
4554
|
+
).all({ ...params, limit: input.limit });
|
|
4135
4555
|
return {
|
|
4136
4556
|
total,
|
|
4137
4557
|
sessions: rows.map((row) => ({
|
|
@@ -4359,41 +4779,41 @@ function clampWindow(raw, fallback2, max) {
|
|
|
4359
4779
|
function stamp2(ms) {
|
|
4360
4780
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
4361
4781
|
}
|
|
4362
|
-
function
|
|
4782
|
+
function budgetOf(total) {
|
|
4363
4783
|
const shares = ANCHOR_SHARE + Math.max(0, total - 1);
|
|
4364
4784
|
const unit = Math.max(MIN_BODY, Math.floor(BODY_BUDGET / shares));
|
|
4365
4785
|
return { anchor: unit * ANCHOR_SHARE, other: unit };
|
|
4366
4786
|
}
|
|
4367
|
-
function body(text,
|
|
4787
|
+
function body(text, budget) {
|
|
4368
4788
|
const flat = text.replace(/\r\n/g, "\n").trimEnd();
|
|
4369
|
-
if (flat.length <=
|
|
4370
|
-
const rest = flat.length -
|
|
4371
|
-
return `${flat.slice(0,
|
|
4789
|
+
if (flat.length <= budget) return flat;
|
|
4790
|
+
const rest = flat.length - budget;
|
|
4791
|
+
return `${flat.slice(0, budget)}
|
|
4372
4792
|
\u2026[cut ${rest} more chars \u2014 lower before/after to spend the budget on fewer messages]`;
|
|
4373
4793
|
}
|
|
4374
4794
|
function surfaceOf(record, isCurrent) {
|
|
4375
4795
|
if (!isCurrent) return record.surface === "active" ? "active there" : "compacted there";
|
|
4376
4796
|
return record.surface === "active" ? "still in your context" : "compacted out of your context";
|
|
4377
4797
|
}
|
|
4378
|
-
function renderRecord(record, mark,
|
|
4798
|
+
function renderRecord(record, mark, budget, isCurrent) {
|
|
4379
4799
|
const tool = record.toolName ? ` \xB7 ${record.toolName}` : "";
|
|
4380
4800
|
return [
|
|
4381
4801
|
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${stamp2(record.timestamp)} \xB7 ${surfaceOf(record, isCurrent)}]`,
|
|
4382
|
-
` ${body(record.content,
|
|
4802
|
+
` ${body(record.content, budget).split("\n").join("\n ")}`
|
|
4383
4803
|
].join("\n");
|
|
4384
4804
|
}
|
|
4385
4805
|
function renderWindow(out, sessionId, isCurrent) {
|
|
4386
4806
|
const anchor = out.anchor;
|
|
4387
4807
|
if (!anchor) return "";
|
|
4388
4808
|
const count = out.before.length + out.after.length + 1;
|
|
4389
|
-
const
|
|
4809
|
+
const budget = budgetOf(count);
|
|
4390
4810
|
return [
|
|
4391
4811
|
`Session ${sessionId}${isCurrent ? " (this session)" : ""} \u2014 ${out.title || "(untitled)"}`,
|
|
4392
4812
|
`${count} of ${out.total} message(s), around #${anchor.messageId}:`,
|
|
4393
4813
|
"",
|
|
4394
|
-
...out.before.map((r) => renderRecord(r, " ",
|
|
4395
|
-
renderRecord(anchor, "\xBB",
|
|
4396
|
-
...out.after.map((r) => renderRecord(r, " ",
|
|
4814
|
+
...out.before.map((r) => renderRecord(r, " ", budget.other, isCurrent)),
|
|
4815
|
+
renderRecord(anchor, "\xBB", budget.anchor, isCurrent),
|
|
4816
|
+
...out.after.map((r) => renderRecord(r, " ", budget.other, isCurrent))
|
|
4397
4817
|
].join("\n");
|
|
4398
4818
|
}
|
|
4399
4819
|
function createSessionMessagesReadTool(deps) {
|
|
@@ -5248,7 +5668,7 @@ function available(tools) {
|
|
|
5248
5668
|
if (tools.length === 0) {
|
|
5249
5669
|
return "No deferred tools in this session \u2014 every tool is already in your tool list.";
|
|
5250
5670
|
}
|
|
5251
|
-
const names = tools.map((
|
|
5671
|
+
const names = tools.map((t83) => t83.name).sort();
|
|
5252
5672
|
const shown = names.slice(0, MAX_LISTED);
|
|
5253
5673
|
const rest = names.length - shown.length;
|
|
5254
5674
|
return `Searchable tools: ${shown.join(", ")}${rest > 0 ? ` (\u2026and ${rest} more)` : ""}.`;
|
|
@@ -5368,19 +5788,22 @@ var TrackerDB = class {
|
|
|
5368
5788
|
);
|
|
5369
5789
|
this.db.transaction(() => {
|
|
5370
5790
|
this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId);
|
|
5371
|
-
for (const
|
|
5791
|
+
for (const t83 of todos) {
|
|
5372
5792
|
insertStmt.run({
|
|
5373
|
-
id:
|
|
5793
|
+
id: t83.id,
|
|
5374
5794
|
session_id: sessionId,
|
|
5375
|
-
content:
|
|
5376
|
-
status:
|
|
5377
|
-
reason:
|
|
5378
|
-
created_at:
|
|
5379
|
-
updated_at:
|
|
5795
|
+
content: t83.content,
|
|
5796
|
+
status: t83.status,
|
|
5797
|
+
reason: t83.reason || null,
|
|
5798
|
+
created_at: t83.created_at,
|
|
5799
|
+
updated_at: t83.updated_at
|
|
5380
5800
|
});
|
|
5381
5801
|
}
|
|
5382
5802
|
})();
|
|
5383
5803
|
}
|
|
5804
|
+
deleteBySession(sessionId) {
|
|
5805
|
+
return this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId).changes;
|
|
5806
|
+
}
|
|
5384
5807
|
close() {
|
|
5385
5808
|
releaseDatabase(this.path);
|
|
5386
5809
|
}
|
|
@@ -5398,9 +5821,9 @@ function formatTodoList(todos, pendingCount) {
|
|
|
5398
5821
|
cancelled: "\u5DF2\u53D6\u6D88"
|
|
5399
5822
|
};
|
|
5400
5823
|
lines.push(`[todo] \u72B6\u6001\u6C47\u603B: ${pendingCount} \u4E2A\u5F85\u5B8C\u6210`);
|
|
5401
|
-
for (const
|
|
5402
|
-
const label = statusLabel[
|
|
5403
|
-
lines.push(`- [${label}] ${
|
|
5824
|
+
for (const t83 of todos) {
|
|
5825
|
+
const label = statusLabel[t83.status] || t83.status;
|
|
5826
|
+
lines.push(`- [${label}] ${t83.content}${t83.reason ? ` \u2014\u2014 ${t83.reason}` : ""}`);
|
|
5404
5827
|
}
|
|
5405
5828
|
return lines.join("\n");
|
|
5406
5829
|
}
|
|
@@ -5474,14 +5897,14 @@ function createTodoTool(db) {
|
|
|
5474
5897
|
};
|
|
5475
5898
|
}
|
|
5476
5899
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5477
|
-
const existing = new Map(db.listBySession(ctx.sessionId).map((
|
|
5478
|
-
const todos = rawTodos.map((
|
|
5479
|
-
const prev =
|
|
5480
|
-
const status = isValidStatus(
|
|
5481
|
-
const reason9 = normalizeReason(status,
|
|
5900
|
+
const existing = new Map(db.listBySession(ctx.sessionId).map((t83) => [t83.id, t83]));
|
|
5901
|
+
const todos = rawTodos.map((t83) => {
|
|
5902
|
+
const prev = t83.id ? existing.get(t83.id) : void 0;
|
|
5903
|
+
const status = isValidStatus(t83.status) ? t83.status : "pending";
|
|
5904
|
+
const reason9 = normalizeReason(status, t83.reason);
|
|
5482
5905
|
return {
|
|
5483
|
-
id:
|
|
5484
|
-
content: String(
|
|
5906
|
+
id: t83.id || generateShortId(),
|
|
5907
|
+
content: String(t83.content || "").slice(0, 500),
|
|
5485
5908
|
status,
|
|
5486
5909
|
...reason9 ? { reason: reason9 } : {},
|
|
5487
5910
|
created_at: prev?.created_at || now,
|
|
@@ -5489,7 +5912,7 @@ function createTodoTool(db) {
|
|
|
5489
5912
|
};
|
|
5490
5913
|
});
|
|
5491
5914
|
db.replaceAll(ctx.sessionId, todos);
|
|
5492
|
-
const pendingCount = todos.filter((
|
|
5915
|
+
const pendingCount = todos.filter((t83) => isOpenTodo(t83.status)).length;
|
|
5493
5916
|
return {
|
|
5494
5917
|
success: true,
|
|
5495
5918
|
output: formatTodoList(todos, pendingCount),
|
|
@@ -5836,7 +6259,7 @@ function intersectNames(base2, incoming) {
|
|
|
5836
6259
|
if (!base2) return incoming ? [...incoming] : void 0;
|
|
5837
6260
|
if (!incoming) return [...base2];
|
|
5838
6261
|
const baseSet = new Set(base2);
|
|
5839
|
-
return incoming.filter((
|
|
6262
|
+
return incoming.filter((t83) => baseSet.has(t83));
|
|
5840
6263
|
}
|
|
5841
6264
|
function findRole(roles, name) {
|
|
5842
6265
|
return roles.find((r) => r.name === name);
|
|
@@ -5988,7 +6411,7 @@ function roleScopedProvider(base2, role, blocked) {
|
|
|
5988
6411
|
return allow ? allow.has(name) : true;
|
|
5989
6412
|
};
|
|
5990
6413
|
return {
|
|
5991
|
-
list: () => base2.list().filter((
|
|
6414
|
+
list: () => base2.list().filter((t83) => permitted(t83.name)),
|
|
5992
6415
|
get: (name) => permitted(name) ? base2.get(name) : void 0
|
|
5993
6416
|
};
|
|
5994
6417
|
}
|
|
@@ -6015,7 +6438,7 @@ function createRoleScope(base2, sessionRole, blocked) {
|
|
|
6015
6438
|
}
|
|
6016
6439
|
function unknownRoleTools(base2, role, blocked) {
|
|
6017
6440
|
if (!role?.tools) return [];
|
|
6018
|
-
const available2 = new Set(base2.list().map((
|
|
6441
|
+
const available2 = new Set(base2.list().map((t83) => t83.name));
|
|
6019
6442
|
const blockedSet = new Set(blocked);
|
|
6020
6443
|
return role.tools.filter((name) => !available2.has(name) && !blockedSet.has(name));
|
|
6021
6444
|
}
|
|
@@ -6378,7 +6801,7 @@ function createToolScope(base2) {
|
|
|
6378
6801
|
const permitted = (name) => allow ? allow.has(name) : true;
|
|
6379
6802
|
return {
|
|
6380
6803
|
provider: {
|
|
6381
|
-
list: () => base2.list().filter((
|
|
6804
|
+
list: () => base2.list().filter((t83) => permitted(t83.name)),
|
|
6382
6805
|
get: (name) => permitted(name) ? base2.get(name) : void 0
|
|
6383
6806
|
},
|
|
6384
6807
|
enter: (next) => {
|
|
@@ -6399,6 +6822,8 @@ function createToolScope(base2) {
|
|
|
6399
6822
|
var HOOK_TYPE_FLAGS = {
|
|
6400
6823
|
"session:start": true,
|
|
6401
6824
|
"session:end": true,
|
|
6825
|
+
"subagent:start": true,
|
|
6826
|
+
"subagent:stop": true,
|
|
6402
6827
|
"turn:before": true,
|
|
6403
6828
|
"turn:after": true,
|
|
6404
6829
|
"tool:before": true,
|
|
@@ -6548,7 +6973,7 @@ function scanHooks(dir, issues) {
|
|
|
6548
6973
|
return [...parsed.entries].map(([type, list]) => ({
|
|
6549
6974
|
type,
|
|
6550
6975
|
count: list.reduce((sum, entry) => sum + entry.hooks.length, 0)
|
|
6551
|
-
})).filter((
|
|
6976
|
+
})).filter((t83) => t83.count > 0).sort((a, b) => a.type.localeCompare(b.type));
|
|
6552
6977
|
}
|
|
6553
6978
|
function scanMcp(dir, plugin, issues) {
|
|
6554
6979
|
const path = join(dir, PLUGIN_LAYOUT.mcp);
|
|
@@ -8737,14 +9162,14 @@ var CheckpointStore = class {
|
|
|
8737
9162
|
}
|
|
8738
9163
|
async enforceTotalSize(protectSession, protectTurnIndex) {
|
|
8739
9164
|
const turns = await this.collectTurns();
|
|
8740
|
-
let total = turns.reduce((sum,
|
|
9165
|
+
let total = turns.reduce((sum, t83) => sum + t83.bytes, 0);
|
|
8741
9166
|
if (total <= this.maxTotalBytes) return;
|
|
8742
9167
|
turns.sort((a, b) => a.createdAt - b.createdAt);
|
|
8743
|
-
for (const
|
|
9168
|
+
for (const t83 of turns) {
|
|
8744
9169
|
if (total <= this.maxTotalBytes) return;
|
|
8745
|
-
if (
|
|
8746
|
-
await this.removeTurn(
|
|
8747
|
-
total -=
|
|
9170
|
+
if (t83.sessionId === protectSession && t83.turnIndex === protectTurnIndex) continue;
|
|
9171
|
+
await this.removeTurn(t83.sessionId, t83.turnIndex);
|
|
9172
|
+
total -= t83.bytes;
|
|
8748
9173
|
}
|
|
8749
9174
|
}
|
|
8750
9175
|
async collectTurns() {
|
|
@@ -9064,7 +9489,7 @@ async function snapshotFiles(paths) {
|
|
|
9064
9489
|
}
|
|
9065
9490
|
async function collectDiffs(before, workDir) {
|
|
9066
9491
|
const out = [];
|
|
9067
|
-
let
|
|
9492
|
+
let budget = MAX_CALL_BYTES;
|
|
9068
9493
|
for (const [path, old] of before) {
|
|
9069
9494
|
if (old.kind === "opaque") continue;
|
|
9070
9495
|
const now = await readSnapshot(path);
|
|
@@ -9072,8 +9497,8 @@ async function collectDiffs(before, workDir) {
|
|
|
9072
9497
|
if (old.kind === "absent" && now.kind === "absent") continue;
|
|
9073
9498
|
if (old.kind === "text" && now.kind === "text" && old.text === now.text) continue;
|
|
9074
9499
|
const bytes = (old.kind === "text" ? old.bytes : 0) + (now.kind === "text" ? now.bytes : 0);
|
|
9075
|
-
if (bytes >
|
|
9076
|
-
|
|
9500
|
+
if (bytes > budget) continue;
|
|
9501
|
+
budget -= bytes;
|
|
9077
9502
|
out.push({
|
|
9078
9503
|
filePath: workspaceDisplayPath(path, workDir),
|
|
9079
9504
|
...old.kind === "text" ? { oldContent: old.text } : {},
|
|
@@ -9118,10 +9543,11 @@ var TaskNoticeTracker = class {
|
|
|
9118
9543
|
}
|
|
9119
9544
|
const lines = [];
|
|
9120
9545
|
for (const task of tasks) {
|
|
9121
|
-
if (task.kind
|
|
9546
|
+
if (task.kind === "shell") continue;
|
|
9122
9547
|
const before = this.seen.get(task.id);
|
|
9123
9548
|
if (before === task.status) continue;
|
|
9124
9549
|
this.seen.set(task.id, task.status);
|
|
9550
|
+
if (task.kind === "agent" && task.status === "running") continue;
|
|
9125
9551
|
lines.push(describeBackgroundTask(task));
|
|
9126
9552
|
}
|
|
9127
9553
|
if (lines.length === 0) return null;
|
|
@@ -9131,15 +9557,16 @@ var TaskNoticeTracker = class {
|
|
|
9131
9557
|
function describeBackgroundTask(task) {
|
|
9132
9558
|
const text = task.label;
|
|
9133
9559
|
const cmd = text.length > 60 ? `${text.slice(0, 60)}\u2026` : text;
|
|
9560
|
+
const agent = task.kind === "agent";
|
|
9134
9561
|
switch (task.status) {
|
|
9135
9562
|
case "running":
|
|
9136
9563
|
return `- ${task.id} \u8FD0\u884C\u4E2D\uFF1A${cmd}`;
|
|
9137
9564
|
case "exited":
|
|
9138
|
-
return `- ${task.id} \u5DF2\u7ED3\u675F\uFF0C\u9000\u51FA\u7801 ${task.exitCode}\uFF1A${cmd}`;
|
|
9565
|
+
return agent ? `- ${task.id} \u5DF2\u7ED3\u675F\uFF1A${cmd}` : `- ${task.id} \u5DF2\u7ED3\u675F\uFF0C\u9000\u51FA\u7801 ${task.exitCode}\uFF1A${cmd}`;
|
|
9139
9566
|
case "killed":
|
|
9140
9567
|
return `- ${task.id} \u5DF2\u88AB\u505C\u6B62\uFF1A${cmd}`;
|
|
9141
9568
|
case "failed":
|
|
9142
|
-
return `- ${task.id} \u542F\u52A8\u5931\u8D25\uFF1A${cmd}`;
|
|
9569
|
+
return agent ? `- ${task.id} \u5931\u8D25\uFF1A${cmd}` : `- ${task.id} \u542F\u52A8\u5931\u8D25\uFF1A${cmd}`;
|
|
9143
9570
|
case "closed":
|
|
9144
9571
|
return `- ${task.id} \u5DF2\u5173\u95ED\uFF1A${cmd}`;
|
|
9145
9572
|
case "reaped":
|
|
@@ -9232,6 +9659,19 @@ function skillNotes(input, skillTokens) {
|
|
|
9232
9659
|
}
|
|
9233
9660
|
return notes;
|
|
9234
9661
|
}
|
|
9662
|
+
function cacheStats(usage) {
|
|
9663
|
+
if (!usage) return void 0;
|
|
9664
|
+
const hit = usage.cacheHitTokens;
|
|
9665
|
+
const write = usage.cacheWriteTokens;
|
|
9666
|
+
if (hit === void 0 && write === void 0) return void 0;
|
|
9667
|
+
const prompt = promptTokens(usage);
|
|
9668
|
+
return {
|
|
9669
|
+
hit: hit ?? 0,
|
|
9670
|
+
write: write ?? 0,
|
|
9671
|
+
prompt,
|
|
9672
|
+
hitPercent: prompt > 0 ? Math.round((hit ?? 0) / prompt * 100) : 0
|
|
9673
|
+
};
|
|
9674
|
+
}
|
|
9235
9675
|
function buildContextBreakdown(input) {
|
|
9236
9676
|
const toolTokens = input.tools.reduce((sum, { tool }) => sum + toolDefinitionTokens(tool), 0);
|
|
9237
9677
|
const { detail, counts, notes } = toolDetail(input, toolTokens);
|
|
@@ -9253,7 +9693,16 @@ ${input.system.rules}`),
|
|
|
9253
9693
|
notes.push({ code: "near_limit", params: { percent: Math.round(used / input.limit * 100) } });
|
|
9254
9694
|
}
|
|
9255
9695
|
const hints = notes.map((note) => t(NOTE_KEY[note.code], note.params));
|
|
9256
|
-
|
|
9696
|
+
const cache = cacheStats(input.lastUsage);
|
|
9697
|
+
return {
|
|
9698
|
+
limit: input.limit,
|
|
9699
|
+
used,
|
|
9700
|
+
remaining,
|
|
9701
|
+
segments,
|
|
9702
|
+
hints,
|
|
9703
|
+
notes,
|
|
9704
|
+
...cache ? { cache } : {}
|
|
9705
|
+
};
|
|
9257
9706
|
}
|
|
9258
9707
|
// src/cost/display.ts
|
|
9259
9708
|
var currency;
|
|
@@ -9581,6 +10030,7 @@ function systemPromptSegments(params) {
|
|
|
9581
10030
|
"- \u505A\u6CD5\u6709\u4E24\u79CD\u5408\u7406\u8D70\u6CD5\u3001\u4E14\u9009\u9519\u4E86\u8981\u767D\u5E72\u65F6\uFF0C\u624D\u505C\u4E0B\u6765\u95EE\u4E00\u53E5\uFF1B\u6D3B\u591A\u3001\u8981\u82B1\u65F6\u95F4\u3001\u6B65\u9AA4\u91CD\u590D\u90FD\u4E0D\u662F\u8981\u95EE\u7684\u7406\u7531",
|
|
9582
10031
|
"- \u6539\u5B8C\u4EE3\u7801\u522B\u76F4\u63A5\u8BF4\u300C\u5B8C\u6210\u4E86\u300D\uFF1A\u5148\u8DD1\u4E00\u904D\u8FD9\u4E2A\u9879\u76EE\u81EA\u5DF1\u7684\u68C0\u67E5\uFF08\u6D4B\u8BD5 / \u6784\u5EFA / \u7C7B\u578B\u68C0\u67E5\uFF0C\u547D\u4EE4\u4E00\u822C\u5728 README \u6216 package.json \u91CC\uFF09\u3002\u8DD1\u4E0D\u4E86\u6216\u8005\u6CA1\u8DD1\u5C31\u7167\u5B9E\u8BF4\u4F60\u6CA1\u9A8C\u8BC1\u8FC7\uFF0C\u522B\u5199\u300C\u5E94\u8BE5\u6CA1\u95EE\u9898\u300D",
|
|
9583
10032
|
"- \u88AB\u6743\u9650\u62E6\u4E0B\u4E4B\u540E**\u522B\u6362\u6761\u8DEF\u518D\u6765**\uFF1A\u4E0D\u8BB8\u6539\u7528 terminal / code_exec \u53BB\u5199\u540C\u4E00\u6837\u4E1C\u897F\uFF0C\u4E5F\u4E0D\u8BB8\u62FF\u300C\u4EA4\u4E00\u4EFD\u8BA1\u5212\u300D\u53BB\u6362\u6743\u9650\u3002\u5C31\u5730\u6536\u624B\uFF0C\u8BF4\u6E05\u4F60\u8981\u505A\u4EC0\u4E48\u3001\u5361\u5728\u54EA\uFF0C\u8BF7\u7528\u6237\u653E\u6743\u3002\u7ED5\u8FC7\u5BA1\u6279\u6BD4\u8FD9\u4EF6\u4E8B\u505A\u4E0D\u6210\u4E25\u91CD\u5F97\u591A",
|
|
10033
|
+
"- \u547D\u4EE4\u88AB**\u6C99\u7BB1**\u6321\u4E0B\uFF08\u9519\u8BEF\u7801 2008 / 2009\uFF0C\u4E0D\u662F\u5BA1\u6279\u62D2\u7EDD\uFF09\u65F6\u6709\u4E00\u6B21\u6B63\u89C4\u7684\u51FA\u8DEF\uFF1A\u786E\u8BA4\u8FD9\u4E00\u6B21\u5FC5\u987B\u8D8A\u754C\uFF0C\u5C31\u5E26\u4E0A `sandbox_permissions` \u548C `justification`\uFF08\u4E00\u53E5\u8BDD\u8BF4\u660E\u4E3A\u4EC0\u4E48\uFF09\u518D\u8C03\u4E00\u6B21\uFF0C\u7528\u6237\u4F1A\u5355\u72EC\u6279 \u2014\u2014 \u53EA\u653E\u5F00\u8FD9\u4E00\u6B21\u3002\u522B\u62FF\u5B83\u5F53\u4E07\u7528\u5F00\u5173\uFF1A\u80FD\u632A\u8FDB\u5DE5\u4F5C\u533A\u3001\u80FD\u6362\u4E2A\u4E0D\u9700\u8981\u8D8A\u754C\u7684\u5199\u6CD5\uFF0C\u5C31\u5148\u90A3\u4E48\u529E\uFF0C\u88AB\u7528\u6237\u62D2\u4E86\u5C31\u6536\u624B",
|
|
9584
10034
|
"- \u7528\u6237\u7ED9\u4E86\u8303\u56F4\u5C31\u628A\u90A3\u4E2A\u8303\u56F4\u505A\u5B8C\uFF1A\u8BF4 100 \u6761\u5C31\u662F 100 \u6761\u3002\u505A 3 \u6761\u518D\u95EE\u300C\u8981\u4E0D\u8981\u7EE7\u7EED\u300D\u662F\u6CA1\u505A\u5B8C\uFF0C\u4E0D\u662F\u8C28\u614E",
|
|
9585
10035
|
"- \u8BE5\u7701\u7684\u662F\u91CD\u590D\u8C03\u540C\u4E00\u6B21\u5DE5\u5177\uFF08\u540C\u6837\u7684\u53C2\u6570\u95EE\u7B2C\u4E8C\u904D\uFF09\uFF0C\u4E0D\u662F\u5C11\u505A\u51E0\u4EF6\u4E8B \u2014\u2014 \u5DE5\u5177\u8C03\u7528\u6B21\u6570\u4ECE\u6765\u4E0D\u662F\u8981\u538B\u7684\u6307\u6807",
|
|
9586
10036
|
"- \u8BF4\u4E86\u4E0B\u4E00\u6B65\u5C31\u5F53\u573A\u505A\uFF1A\u300C\u6211\u5148\u53BB\u67E5\u4E00\u4E0B\u300D\u300Clet me \u68C0\u67E5\u4E00\u4E0B\u300D\u8FD9\u79CD\u8BDD\u540E\u9762\u5FC5\u987B\u7D27\u8DDF\u4E00\u6B21\u5DE5\u5177\u8C03\u7528\uFF0C\u522B\u62FF\u5B83\u5F53\u4E00\u8F6E\u56DE\u590D\u7684\u7ED3\u5C3E",
|
|
@@ -9661,10 +10111,10 @@ function renderSettings(s) {
|
|
|
9661
10111
|
bits.push(`\u4E0A\u4E0B\u6587\u7A97\u53E3 ${s.contextLength}`);
|
|
9662
10112
|
bits.push(`\u81EA\u52A8\u538B\u7F29 ${s.compression.enabled ? `\u5F00\uFF08${s.compression.threshold}\uFF09` : "\u5173"}`);
|
|
9663
10113
|
bits.push(`\u7EC8\u7AEF\u6C99\u7BB1 ${s.sandboxTerminal ? "\u5F00" : "\u5173"}`);
|
|
9664
|
-
const
|
|
9665
|
-
if (s.budget?.maxCostUsd !== void 0)
|
|
9666
|
-
if (s.budget?.maxTokens !== void 0)
|
|
9667
|
-
bits.push(`\u9884\u7B97\u4E0A\u9650 ${
|
|
10114
|
+
const budget = [];
|
|
10115
|
+
if (s.budget?.maxCostUsd !== void 0) budget.push(`$${s.budget.maxCostUsd}`);
|
|
10116
|
+
if (s.budget?.maxTokens !== void 0) budget.push(`${s.budget.maxTokens} tokens`);
|
|
10117
|
+
bits.push(`\u9884\u7B97\u4E0A\u9650 ${budget.length > 0 ? budget.join(" / ") : "\u672A\u8BBE"}`);
|
|
9668
10118
|
return [
|
|
9669
10119
|
"<settings>",
|
|
9670
10120
|
bits.join(" \xB7 "),
|
|
@@ -10562,6 +11012,111 @@ function getGitStatus(rootDir) {
|
|
|
10562
11012
|
function findProjectInstructions(rootDir, workDir = rootDir) {
|
|
10563
11013
|
return findInstructionFiles(rootDir, workDir)[0];
|
|
10564
11014
|
}
|
|
11015
|
+
var DATA_URL_PREFIX2 = /^data:[^;,]*;base64,/i;
|
|
11016
|
+
var encoder = new TextEncoder();
|
|
11017
|
+
function imageBytes(image) {
|
|
11018
|
+
if (/^https?:/i.test(image)) return 0;
|
|
11019
|
+
return encoder.encode(image.replace(DATA_URL_PREFIX2, "")).length;
|
|
11020
|
+
}
|
|
11021
|
+
function requestImageBytes(messages) {
|
|
11022
|
+
let total = 0;
|
|
11023
|
+
for (const message of messages) {
|
|
11024
|
+
for (const part of message.parts ?? []) {
|
|
11025
|
+
if (part.type !== "image") continue;
|
|
11026
|
+
total += imageBytes(part.image);
|
|
11027
|
+
}
|
|
11028
|
+
for (const result of message.toolResults ?? []) {
|
|
11029
|
+
for (const artifact of result.artifacts ?? []) {
|
|
11030
|
+
if (!artifact.data) continue;
|
|
11031
|
+
total += encoder.encode(artifact.data).length;
|
|
11032
|
+
}
|
|
11033
|
+
}
|
|
11034
|
+
}
|
|
11035
|
+
return total;
|
|
11036
|
+
}
|
|
11037
|
+
function imageSites(messages) {
|
|
11038
|
+
const sites = [];
|
|
11039
|
+
for (const [messageIndex, message] of messages.entries()) {
|
|
11040
|
+
const parts = message.parts ?? [];
|
|
11041
|
+
for (const [partIndex, part] of parts.entries()) {
|
|
11042
|
+
if (part.type !== "image") continue;
|
|
11043
|
+
sites.push({ messageIndex, partIndex, bytes: imageBytes(part.image) });
|
|
11044
|
+
}
|
|
11045
|
+
const results = message.toolResults ?? [];
|
|
11046
|
+
for (const [resultIndex, result] of results.entries()) {
|
|
11047
|
+
const artifacts = result.artifacts ?? [];
|
|
11048
|
+
for (const [artifactIndex, artifact] of artifacts.entries()) {
|
|
11049
|
+
if (!artifact.data) continue;
|
|
11050
|
+
sites.push({
|
|
11051
|
+
messageIndex,
|
|
11052
|
+
resultIndex,
|
|
11053
|
+
artifactIndex,
|
|
11054
|
+
bytes: encoder.encode(artifact.data).length
|
|
11055
|
+
});
|
|
11056
|
+
}
|
|
11057
|
+
}
|
|
11058
|
+
}
|
|
11059
|
+
return sites;
|
|
11060
|
+
}
|
|
11061
|
+
function offloadOldestImages(messages, opts = { budgetBytes: 0 }) {
|
|
11062
|
+
const keepFresh = Math.max(1, opts.keepFresh ?? 1);
|
|
11063
|
+
const sites = imageSites(messages);
|
|
11064
|
+
const total = sites.reduce((sum, s) => sum + s.bytes, 0);
|
|
11065
|
+
if (total <= opts.budgetBytes) {
|
|
11066
|
+
return { messages: [...messages], offloaded: 0, remainingBytes: total };
|
|
11067
|
+
}
|
|
11068
|
+
const freshFrom = Math.max(0, messages.length - keepFresh);
|
|
11069
|
+
const picked = { parts: /* @__PURE__ */ new Set(), artifacts: /* @__PURE__ */ new Set() };
|
|
11070
|
+
let running = total;
|
|
11071
|
+
for (const site of sites) {
|
|
11072
|
+
if (running <= opts.budgetBytes) break;
|
|
11073
|
+
if (site.messageIndex >= freshFrom) continue;
|
|
11074
|
+
if (site.partIndex !== void 0) {
|
|
11075
|
+
picked.parts.add(`${site.messageIndex}:${site.partIndex}`);
|
|
11076
|
+
} else {
|
|
11077
|
+
picked.artifacts.add(`${site.messageIndex}:${site.resultIndex}:${site.artifactIndex}`);
|
|
11078
|
+
}
|
|
11079
|
+
running -= site.bytes;
|
|
11080
|
+
}
|
|
11081
|
+
const count = picked.parts.size + picked.artifacts.size;
|
|
11082
|
+
if (count === 0) return { messages: [...messages], offloaded: 0, remainingBytes: total };
|
|
11083
|
+
const out = messages.map((message, messageIndex) => {
|
|
11084
|
+
const parts = message.parts ?? [];
|
|
11085
|
+
const results = message.toolResults ?? [];
|
|
11086
|
+
const hitParts = parts.some((_, i) => picked.parts.has(`${messageIndex}:${i}`));
|
|
11087
|
+
const hitArtifacts = results.some(
|
|
11088
|
+
(r, ri) => (r.artifacts ?? []).some((_, ai) => picked.artifacts.has(`${messageIndex}:${ri}:${ai}`))
|
|
11089
|
+
);
|
|
11090
|
+
if (!hitParts && !hitArtifacts) return message;
|
|
11091
|
+
const nextResults = hitArtifacts ? results.map((result, ri) => {
|
|
11092
|
+
const artifacts = result.artifacts ?? [];
|
|
11093
|
+
if (!artifacts.some((_, ai) => picked.artifacts.has(`${messageIndex}:${ri}:${ai}`))) {
|
|
11094
|
+
return result;
|
|
11095
|
+
}
|
|
11096
|
+
return {
|
|
11097
|
+
...result,
|
|
11098
|
+
artifacts: artifacts.map(
|
|
11099
|
+
(artifact, ai) => picked.artifacts.has(`${messageIndex}:${ri}:${ai}`) ? withoutData(artifact) : artifact
|
|
11100
|
+
)
|
|
11101
|
+
};
|
|
11102
|
+
}) : message.toolResults;
|
|
11103
|
+
const nextParts = hitParts ? parts.map(
|
|
11104
|
+
(part, i) => picked.parts.has(`${messageIndex}:${i}`) ? (
|
|
11105
|
+
{ type: "text", text: OFFLOADED_IMAGE_NOTE }
|
|
11106
|
+
) : part
|
|
11107
|
+
) : message.parts;
|
|
11108
|
+
return {
|
|
11109
|
+
...message,
|
|
11110
|
+
...nextParts ? { parts: nextParts } : {},
|
|
11111
|
+
...nextResults ? { toolResults: nextResults } : {}
|
|
11112
|
+
};
|
|
11113
|
+
});
|
|
11114
|
+
return { messages: out, offloaded: count, remainingBytes: requestImageBytes(out) };
|
|
11115
|
+
}
|
|
11116
|
+
function withoutData(artifact) {
|
|
11117
|
+
const { data: _data, ...rest } = artifact;
|
|
11118
|
+
return rest;
|
|
11119
|
+
}
|
|
10565
11120
|
function persistedUsage(entry) {
|
|
10566
11121
|
return {
|
|
10567
11122
|
...entry.usage,
|
|
@@ -10881,6 +11436,50 @@ ${this.describeWarning(status)}
|
|
|
10881
11436
|
});
|
|
10882
11437
|
}
|
|
10883
11438
|
};
|
|
11439
|
+
var DEFAULT_MAX_REQUEST_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
11440
|
+
var LEARN_SHRINK = 0.8;
|
|
11441
|
+
var TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
11442
|
+
var BODY_LIMIT_VERSION = 1;
|
|
11443
|
+
function cachePath(homeDir) {
|
|
11444
|
+
return join(homeDir, "cache", "body_limit.json");
|
|
11445
|
+
}
|
|
11446
|
+
function limitKey(provider, model) {
|
|
11447
|
+
return `${provider}:${model}`;
|
|
11448
|
+
}
|
|
11449
|
+
function loadFile(homeDir) {
|
|
11450
|
+
const empty = { version: BODY_LIMIT_VERSION, entries: {} };
|
|
11451
|
+
try {
|
|
11452
|
+
const path = cachePath(homeDir);
|
|
11453
|
+
if (!existsSync(path)) return empty;
|
|
11454
|
+
const data = JSON.parse(readFileSync(path, "utf-8"));
|
|
11455
|
+
if (data.version !== BODY_LIMIT_VERSION) return empty;
|
|
11456
|
+
return { version: BODY_LIMIT_VERSION, entries: data.entries ?? {} };
|
|
11457
|
+
} catch {
|
|
11458
|
+
return empty;
|
|
11459
|
+
}
|
|
11460
|
+
}
|
|
11461
|
+
function readLearnedImageBudget(homeDir, provider, model) {
|
|
11462
|
+
const entry = loadFile(homeDir).entries[limitKey(provider, model)];
|
|
11463
|
+
if (!entry) return void 0;
|
|
11464
|
+
if (Date.now() - entry.at > TTL_MS) return void 0;
|
|
11465
|
+
return entry.bytes;
|
|
11466
|
+
}
|
|
11467
|
+
function learnImageBudget(homeDir, provider, model, usedBytes) {
|
|
11468
|
+
if (!(usedBytes > 0)) return;
|
|
11469
|
+
try {
|
|
11470
|
+
const file = loadFile(homeDir);
|
|
11471
|
+
const learned = Math.max(1, Math.floor(usedBytes * LEARN_SHRINK));
|
|
11472
|
+
const prev = file.entries[limitKey(provider, model)];
|
|
11473
|
+
if (prev && prev.bytes <= learned && Date.now() - prev.at <= TTL_MS) return;
|
|
11474
|
+
file.entries[limitKey(provider, model)] = { bytes: learned, at: Date.now() };
|
|
11475
|
+
mkdirSync(join(homeDir, "cache"), { recursive: true });
|
|
11476
|
+
writeFileSync(cachePath(homeDir), JSON.stringify(file, null, 2), "utf-8");
|
|
11477
|
+
} catch {
|
|
11478
|
+
}
|
|
11479
|
+
}
|
|
11480
|
+
function effectiveImageBudget(configured, learned) {
|
|
11481
|
+
return learned !== void 0 && learned < configured ? learned : configured;
|
|
11482
|
+
}
|
|
10884
11483
|
var ProviderError = class extends Error {
|
|
10885
11484
|
constructor(message, code, recoverable, recovery = "abort") {
|
|
10886
11485
|
super(message);
|
|
@@ -10901,6 +11500,10 @@ function isContextOverflow(err) {
|
|
|
10901
11500
|
if (err instanceof ProviderError) return err.code === PROVIDER_CONTEXT_OVERFLOW;
|
|
10902
11501
|
return classifyProviderError(err).code === PROVIDER_CONTEXT_OVERFLOW;
|
|
10903
11502
|
}
|
|
11503
|
+
function isBodyTooLarge(err) {
|
|
11504
|
+
if (err instanceof ProviderError) return err.code === PROVIDER_BODY_TOO_LARGE;
|
|
11505
|
+
return classifyProviderError(err).code === PROVIDER_BODY_TOO_LARGE;
|
|
11506
|
+
}
|
|
10904
11507
|
function isAbortError(err) {
|
|
10905
11508
|
for (let cur = err, depth = 0; cur && depth < 5; depth++) {
|
|
10906
11509
|
if (typeof cur !== "object") return false;
|
|
@@ -11000,16 +11603,17 @@ function classifyProviderError(err) {
|
|
|
11000
11603
|
}
|
|
11001
11604
|
return { code: 9999, recovery: "retry" };
|
|
11002
11605
|
}
|
|
11606
|
+
var EMPTY_REASONING = { providerOptions: { openaiCompatible: { reasoning_content: "" } } };
|
|
11003
11607
|
function toModelMessages(messages, opts = {}) {
|
|
11004
|
-
if (opts.toolMediaInline
|
|
11005
|
-
return
|
|
11608
|
+
if (opts.toolMediaInline === false) return hoistToolMedia(messages, opts);
|
|
11609
|
+
return messages.map((m) => toModelMessage(m, opts));
|
|
11006
11610
|
}
|
|
11007
|
-
function hoistToolMedia(messages) {
|
|
11611
|
+
function hoistToolMedia(messages, opts = {}) {
|
|
11008
11612
|
const out = [];
|
|
11009
11613
|
let pending = [];
|
|
11010
11614
|
for (const [i, m] of messages.entries()) {
|
|
11011
11615
|
if (m.role !== "tool") {
|
|
11012
|
-
out.push(toModelMessage(m));
|
|
11616
|
+
out.push(toModelMessage(m, opts));
|
|
11013
11617
|
continue;
|
|
11014
11618
|
}
|
|
11015
11619
|
const results = (m.toolResults ?? []).map((r) => {
|
|
@@ -11026,7 +11630,7 @@ ${note}` : note,
|
|
|
11026
11630
|
artifacts: (r.artifacts ?? []).map(({ data: _data, ...rest }) => rest)
|
|
11027
11631
|
};
|
|
11028
11632
|
});
|
|
11029
|
-
out.push(toModelMessage({ ...m, toolResults: results }));
|
|
11633
|
+
out.push(toModelMessage({ ...m, toolResults: results }, opts));
|
|
11030
11634
|
if (pending.length > 0 && messages[i + 1]?.role !== "tool") {
|
|
11031
11635
|
out.push({
|
|
11032
11636
|
role: "user",
|
|
@@ -11109,7 +11713,7 @@ function toSdkPart(p) {
|
|
|
11109
11713
|
}
|
|
11110
11714
|
return assertNeverPart(p);
|
|
11111
11715
|
}
|
|
11112
|
-
function toModelMessage(m) {
|
|
11716
|
+
function toModelMessage(m, opts = {}) {
|
|
11113
11717
|
if (m.role === "tool") {
|
|
11114
11718
|
return {
|
|
11115
11719
|
role: "tool",
|
|
@@ -11124,10 +11728,13 @@ function toModelMessage(m) {
|
|
|
11124
11728
|
if (m.role === "user" && m.parts && m.parts.length > 0) {
|
|
11125
11729
|
return { role: "user", content: m.parts.map(toSdkPart) };
|
|
11126
11730
|
}
|
|
11731
|
+
const reasoningPart = opts.reasoning && m.reasoning ? [{ type: "reasoning", text: m.reasoning }] : [];
|
|
11732
|
+
const emptyReasoning = opts.reasoning && !m.reasoning ? EMPTY_REASONING : {};
|
|
11127
11733
|
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
|
|
11128
11734
|
return {
|
|
11129
11735
|
role: "assistant",
|
|
11130
11736
|
content: [
|
|
11737
|
+
...reasoningPart,
|
|
11131
11738
|
...m.content ? [{ type: "text", text: m.content }] : [],
|
|
11132
11739
|
...m.toolCalls.map((tc) => ({
|
|
11133
11740
|
type: "tool-call",
|
|
@@ -11135,19 +11742,35 @@ function toModelMessage(m) {
|
|
|
11135
11742
|
toolName: tc.toolName,
|
|
11136
11743
|
input: tc.input
|
|
11137
11744
|
}))
|
|
11138
|
-
]
|
|
11745
|
+
],
|
|
11746
|
+
...emptyReasoning
|
|
11747
|
+
};
|
|
11748
|
+
}
|
|
11749
|
+
if (m.role === "assistant" && (reasoningPart.length > 0 || opts.reasoning)) {
|
|
11750
|
+
return {
|
|
11751
|
+
role: "assistant",
|
|
11752
|
+
content: [
|
|
11753
|
+
...reasoningPart,
|
|
11754
|
+
...m.content ? [{ type: "text", text: m.content }] : []
|
|
11755
|
+
],
|
|
11756
|
+
...emptyReasoning
|
|
11139
11757
|
};
|
|
11140
11758
|
}
|
|
11141
11759
|
return { role: m.role, content: m.content };
|
|
11142
11760
|
}
|
|
11143
|
-
|
|
11761
|
+
var ANTHROPIC_CACHE_BREAKPOINT = {
|
|
11762
|
+
anthropic: { cacheControl: { type: "ephemeral" } }
|
|
11763
|
+
};
|
|
11764
|
+
function toSdkTools(tools, opts = {}) {
|
|
11144
11765
|
const result = {};
|
|
11145
|
-
|
|
11766
|
+
const breakpointAt = opts.cacheBreakpoint === true ? tools.length - 1 : -1;
|
|
11767
|
+
tools.forEach((et, i) => {
|
|
11146
11768
|
result[et.name] = tool({
|
|
11147
11769
|
description: et.description,
|
|
11148
|
-
inputSchema: jsonSchema(et.parameters)
|
|
11770
|
+
inputSchema: jsonSchema(et.parameters),
|
|
11771
|
+
...i === breakpointAt ? { providerOptions: ANTHROPIC_CACHE_BREAKPOINT } : {}
|
|
11149
11772
|
});
|
|
11150
|
-
}
|
|
11773
|
+
});
|
|
11151
11774
|
return result;
|
|
11152
11775
|
}
|
|
11153
11776
|
function toOutputSpec(rf) {
|
|
@@ -11347,12 +11970,17 @@ function flattenMessage(m) {
|
|
|
11347
11970
|
return {
|
|
11348
11971
|
role: m.role,
|
|
11349
11972
|
content: m.content,
|
|
11350
|
-
...toolCallIds.length > 0 ? { toolCallIds } : {}
|
|
11973
|
+
...toolCallIds.length > 0 ? { toolCallIds } : {},
|
|
11974
|
+
...m.reasoning ? { reasoning: m.reasoning } : {}
|
|
11351
11975
|
};
|
|
11352
11976
|
}
|
|
11353
11977
|
function unflattenMessage(m) {
|
|
11354
11978
|
if (m.role === "assistant") {
|
|
11355
|
-
return {
|
|
11979
|
+
return {
|
|
11980
|
+
role: "assistant",
|
|
11981
|
+
content: m.content || "(\u65E0\u8F93\u51FA)",
|
|
11982
|
+
...m.reasoning ? { reasoning: m.reasoning } : {}
|
|
11983
|
+
};
|
|
11356
11984
|
}
|
|
11357
11985
|
if (m.role === "system") {
|
|
11358
11986
|
return { role: "system", content: m.content };
|
|
@@ -11624,11 +12252,11 @@ var PromptBuilder = class {
|
|
|
11624
12252
|
memoryInitialized = false;
|
|
11625
12253
|
projectBlock(tools) {
|
|
11626
12254
|
const permLevel = this.deps.permissionManager?.getLevel() || "default";
|
|
11627
|
-
const hasPlanTool = tools.some((
|
|
11628
|
-
const hasLspTool = tools.some((
|
|
11629
|
-
const hasAskTool = tools.some((
|
|
11630
|
-
const hasTodoTool = tools.some((
|
|
11631
|
-
const hasTerminal = tools.some((
|
|
12255
|
+
const hasPlanTool = tools.some((t83) => t83.name === "enter_plan_mode");
|
|
12256
|
+
const hasLspTool = tools.some((t83) => t83.name === "lsp_diagnostics");
|
|
12257
|
+
const hasAskTool = tools.some((t83) => t83.name === "ask_user_question");
|
|
12258
|
+
const hasTodoTool = tools.some((t83) => t83.name === "todo");
|
|
12259
|
+
const hasTerminal = tools.some((t83) => t83.name === "terminal");
|
|
11632
12260
|
const needsCommandApproval = hasTerminal && permLevel === "default";
|
|
11633
12261
|
const plan = this.deps.approvedPlan?.()?.trim();
|
|
11634
12262
|
const codeSdk = renderSdkDeclaration(this.deps.codeModeTools?.() ?? []);
|
|
@@ -11911,9 +12539,50 @@ function toAbsolute2(path, workDir) {
|
|
|
11911
12539
|
const expanded = expandPath(path);
|
|
11912
12540
|
return isAbsolute(expanded) ? resolve(expanded) : resolve(workDir, expanded);
|
|
11913
12541
|
}
|
|
12542
|
+
function declaresEscalation(et) {
|
|
12543
|
+
return Boolean(et.parameters.properties?.[SANDBOX_PERMISSIONS_PARAM]);
|
|
12544
|
+
}
|
|
12545
|
+
function stripEscalationArgs(args) {
|
|
12546
|
+
if (!(SANDBOX_PERMISSIONS_PARAM in args) && !(JUSTIFICATION_PARAM in args)) return args;
|
|
12547
|
+
const rest = { ...args };
|
|
12548
|
+
delete rest[SANDBOX_PERMISSIONS_PARAM];
|
|
12549
|
+
delete rest[JUSTIFICATION_PARAM];
|
|
12550
|
+
return rest;
|
|
12551
|
+
}
|
|
12552
|
+
var PARAM_HINT = `${SANDBOX_PERMISSIONS_PARAM} \u548C ${JUSTIFICATION_PARAM}`;
|
|
12553
|
+
function escalationRefusal(rejection, current) {
|
|
12554
|
+
const reason9 = rejection.reason;
|
|
12555
|
+
const target = rejection.target ?? "";
|
|
12556
|
+
switch (reason9) {
|
|
12557
|
+
case "unpaired":
|
|
12558
|
+
return {
|
|
12559
|
+
message: `\u5347\u6743\u8BF7\u6C42\u65E0\u6548\uFF1A${PARAM_HINT} \u5FC5\u987B\u6210\u5BF9\u51FA\u73B0\uFF0C\u8FD9\u6B21\u53EA\u7ED9\u4E86\u5176\u4E2D\u4E00\u4E2A\u3002\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002`,
|
|
12560
|
+
suggestion: "\u8981\u4E48\u4E24\u683C\u90FD\u7ED9\uFF08sandbox_permissions \u5199\u76EE\u6807\u6863\u3001justification \u5199\u4E3A\u4EC0\u4E48\u5FC5\u987B\u8D8A\u754C\uFF09\uFF0C\u8981\u4E48\u4E24\u683C\u90FD\u4E0D\u7ED9\u3002\u53EA\u7ED9 justification \u4E5F\u4E00\u6837\u4F1A\u88AB\u62D2 \u2014\u2014 \u5F15\u64CE\u4E0D\u4F1A\u66FF\u4F60\u731C\u4E00\u4E2A\u76EE\u6807\u3002"
|
|
12561
|
+
};
|
|
12562
|
+
case "unknown-target":
|
|
12563
|
+
return {
|
|
12564
|
+
message: `\u5347\u6743\u8BF7\u6C42\u65E0\u6548\uFF1A\u4E0D\u8BA4\u8BC6\u7684\u6C99\u7BB1\u76EE\u6807\u300C${target}\u300D\u3002\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002`,
|
|
12565
|
+
suggestion: `\u5F53\u524D\u6863\uFF08${current}\uFF09\u80FD\u5347\u5230\u7684\u76EE\u6807\u53EA\u6709\uFF1A${widerTargets(current).join(" / ") || "(\u6CA1\u6709 \u2014\u2014 \u8FD9\u4E00\u6863\u5DF2\u7ECF\u662F\u6700\u5BBD\u7684)"}\u3002`
|
|
12566
|
+
};
|
|
12567
|
+
case "not-wider":
|
|
12568
|
+
return {
|
|
12569
|
+
message: `\u5347\u6743\u8BF7\u6C42\u65E0\u6548\uFF1A\u76EE\u6807\u300C${target}\u300D\u4E0D\u6BD4\u5F53\u524D\u6863\uFF08${current}\uFF09\u66F4\u5BBD\uFF0C\u800C\u5347\u6743\u53EA\u80FD\u5F80\u66F4\u5BBD\u7684\u65B9\u5411\u8D70\u3002\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002`,
|
|
12570
|
+
suggestion: "\u7B49\u4E8E\u5F53\u524D\u6863\u7684\u8BF7\u6C42\u4E0D\u4F1A\u751F\u6548\uFF08\u5B83\u53EA\u4F1A\u8BA9\u7528\u6237\u591A\u70B9\u4E00\u6B21\u5F39\u7A97\uFF09\u3002\u5F53\u524D\u6863\u5DF2\u7ECF\u591F\u7528\u65F6\uFF0C\u76F4\u63A5\u53BB\u6389\u8FD9\u4E24\u683C\u91CD\u8DD1\u8FD9\u6761\u547D\u4EE4\u3002"
|
|
12571
|
+
};
|
|
12572
|
+
case "no-wider":
|
|
12573
|
+
default:
|
|
12574
|
+
return {
|
|
12575
|
+
message: `\u5347\u6743\u8BF7\u6C42\u65E0\u6548\uFF1A\u5F53\u524D\u6863\uFF08${current}\uFF09\u672C\u6765\u5C31\u4E0D\u4E0A\u6C99\u7BB1\uFF0C\u6CA1\u6709\u66F4\u5BBD\u7684\u8FB9\u754C\u53EF\u5347\u3002\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002`,
|
|
12576
|
+
suggestion: "\u8FD9\u4E00\u6863\u4E0B\u6C99\u7BB1\u4E0D\u662F\u62E6\u4F4F\u4F60\u7684\u539F\u56E0 \u2014\u2014 \u56DE\u53BB\u770B\u4F60\u90A3\u6761\u547D\u4EE4\u672C\u8EAB\uFF08\u8DEF\u5F84\u5B58\u4E0D\u5B58\u5728\u3001\u6743\u9650\u591F\u4E0D\u591F\uFF09\uFF0C\u6216\u8005\u8BFB\u4E00\u4E0B\u4E0A\u4E00\u6B21\u7684\u9519\u8BEF\u7801\u3002"
|
|
12577
|
+
};
|
|
12578
|
+
}
|
|
12579
|
+
}
|
|
12580
|
+
function escalationApprovalReason(from, to, justification) {
|
|
12581
|
+
return t("permission_reason.sandbox_escalation", { from, to, justification });
|
|
12582
|
+
}
|
|
11914
12583
|
var MAX_TOOL_OUTPUT = 3e4;
|
|
11915
12584
|
var MAX_SUB_CALL_OUTPUT = CODE_MODE_LIMITS.maxValueChars;
|
|
11916
|
-
function
|
|
12585
|
+
function budgetOf2(tool, depth, path = "success") {
|
|
11917
12586
|
if (tool.governsOwnOutput && path === "success") return Number.POSITIVE_INFINITY;
|
|
11918
12587
|
return depth > 0 ? MAX_SUB_CALL_OUTPUT : MAX_TOOL_OUTPUT;
|
|
11919
12588
|
}
|
|
@@ -12149,22 +12818,28 @@ var ToolExecutor = class {
|
|
|
12149
12818
|
if (!gate.allowed) {
|
|
12150
12819
|
return finish({ ...base2, success: false, output: gate.output });
|
|
12151
12820
|
}
|
|
12821
|
+
const escalation = await this.resolveEscalation(et, tc.input, signal);
|
|
12822
|
+
if (escalation.kind === "refused") {
|
|
12823
|
+
return finish({ ...base2, success: false, output: escalation.output });
|
|
12824
|
+
}
|
|
12825
|
+
const toolArgs = stripEscalationArgs(tc.input);
|
|
12152
12826
|
const targets = this.writeTargets(et, tc.input);
|
|
12153
12827
|
const snapshotted = await this.snapshot(sessionId, targets);
|
|
12154
12828
|
const before = targets.length > 0 ? await snapshotFiles(targets) : void 0;
|
|
12155
12829
|
const extraRoots = this.deps.permissionManager?.getExtraRoots?.();
|
|
12156
12830
|
const homeDir = (this.deps.multimodal?.() ?? resolveMultimodalPolicy()).homeDir;
|
|
12157
|
-
const r = await et.execute(
|
|
12831
|
+
const r = await et.execute(toolArgs, {
|
|
12158
12832
|
sessionId,
|
|
12159
12833
|
workDir: this.deps.workDir(),
|
|
12160
12834
|
...extraRoots?.length ? { extraRoots } : {},
|
|
12161
12835
|
...gate.grantedPaths?.length ? { grantedPaths: gate.grantedPaths } : {},
|
|
12162
12836
|
...homeDir ? { homeDir } : {},
|
|
12163
12837
|
...this.deps.sandboxTerminal !== void 0 ? { sandboxTerminal: this.deps.sandboxTerminal } : {},
|
|
12838
|
+
...escalation.kind === "approved" ? { sandboxEscalation: escalation.target } : {},
|
|
12164
12839
|
permissionLevel: this.deps.permissionManager?.getLevel() || "auto",
|
|
12165
12840
|
...signal ? { signal } : {},
|
|
12166
12841
|
...onOutput ? { onOutput } : {},
|
|
12167
|
-
outputBudget:
|
|
12842
|
+
outputBudget: budgetOf2(et, depth),
|
|
12168
12843
|
...depth < MAX_SUB_CALL_DEPTH ? { callTool: this.subCallChannel(sessionId, signal, span, depth) } : {}
|
|
12169
12844
|
});
|
|
12170
12845
|
if (snapshotted.length > 0) {
|
|
@@ -12196,7 +12871,7 @@ var ToolExecutor = class {
|
|
|
12196
12871
|
success: true,
|
|
12197
12872
|
output: this.renderOutput(
|
|
12198
12873
|
et,
|
|
12199
|
-
appendArtifactSummaries(text, artifacts,
|
|
12874
|
+
appendArtifactSummaries(text, artifacts, budgetOf2(et, depth), shapeOf(r.output))
|
|
12200
12875
|
),
|
|
12201
12876
|
...artifacts.length > 0 ? { artifacts } : {},
|
|
12202
12877
|
...diffs.length > 0 ? { diffs } : {}
|
|
@@ -12207,7 +12882,7 @@ var ToolExecutor = class {
|
|
|
12207
12882
|
success: false,
|
|
12208
12883
|
output: this.renderOutput(
|
|
12209
12884
|
et,
|
|
12210
|
-
truncateForModel(failureText(r),
|
|
12885
|
+
truncateForModel(failureText(r), budgetOf2(et, depth, "failure"), "text")
|
|
12211
12886
|
)
|
|
12212
12887
|
});
|
|
12213
12888
|
} catch (err) {
|
|
@@ -12289,6 +12964,56 @@ var ToolExecutor = class {
|
|
|
12289
12964
|
);
|
|
12290
12965
|
return guessed || argsKey(args);
|
|
12291
12966
|
}
|
|
12967
|
+
async resolveEscalation(et, args, signal) {
|
|
12968
|
+
const level = this.deps.permissionManager?.getLevel() ?? "auto";
|
|
12969
|
+
const current = sandboxModeForLevel(level);
|
|
12970
|
+
const plan = planEscalation(args, current);
|
|
12971
|
+
if (plan.kind === "none") return { kind: "none" };
|
|
12972
|
+
if (plan.kind === "rejected") {
|
|
12973
|
+
const { message, suggestion } = escalationRefusal(plan, current);
|
|
12974
|
+
return { kind: "refused", output: `\u5347\u6743\u88AB\u62D2 [\u6C99\u7BB1]: ${message}
|
|
12975
|
+
${suggestion}` };
|
|
12976
|
+
}
|
|
12977
|
+
if (!declaresEscalation(et)) {
|
|
12978
|
+
return {
|
|
12979
|
+
kind: "refused",
|
|
12980
|
+
output: `\u5347\u6743\u88AB\u62D2 [\u6C99\u7BB1]: \u5DE5\u5177 ${et.name} \u4E0D\u63A5\u53D7 sandbox_permissions \u2014\u2014 \u5B83\u7684\u6C99\u7BB1\u8FB9\u754C\u4E0D\u7531\u8FD9\u4E00\u683C\u63A7\u5236\u3002
|
|
12981
|
+
\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002\u53BB\u6389\u8FD9\u4E24\u683C\u91CD\u8DD1\uFF1B\u5982\u679C\u5B83\u786E\u5B9E\u9700\u8981\u8D8A\u754C\uFF0C\u90A3\u8BF4\u660E\u8BE5\u6362\u4E00\u4E2A\u80FD\u8868\u8FBE\u8FD9\u4EF6\u4E8B\u7684\u5DE5\u5177\u3002`
|
|
12982
|
+
};
|
|
12983
|
+
}
|
|
12984
|
+
if (!this.deps.onApprovalRequest || this.deps.permissionManager?.isNonInteractive?.()) {
|
|
12985
|
+
return {
|
|
12986
|
+
kind: "refused",
|
|
12987
|
+
output: "\u5347\u6743\u88AB\u62D2 [\u6C99\u7BB1]: \u5F53\u524D\u73AF\u5883\u65E0\u6CD5\u4EA4\u4E92\u786E\u8BA4\uFF0C\u800C\u5347\u6743\u6309\u5B9A\u4E49\u9700\u8981\u4EBA\u70B9\u4E00\u6B21\u3002\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002\n\u65E0\u4EBA\u503C\u5B88\u4E0B\u6CA1\u6709\u522B\u7684\u8DEF\uFF1A\u628A\u8981\u505A\u7684\u6539\u52A8\u632A\u8FDB\u5DE5\u4F5C\u533A\uFF0C\u6216\u8005\u8BA9\u7528\u6237\u5728\u4EA4\u4E92\u4F1A\u8BDD\u91CC\u8DD1\u3002"
|
|
12988
|
+
};
|
|
12989
|
+
}
|
|
12990
|
+
const opType = mapOperation(et);
|
|
12991
|
+
const opTarget = this.resolveTarget(et, args);
|
|
12992
|
+
const { outcome } = normalizeApproval(
|
|
12993
|
+
await this.deps.onApprovalRequest({
|
|
12994
|
+
toolName: et.name,
|
|
12995
|
+
type: opType,
|
|
12996
|
+
target: opTarget,
|
|
12997
|
+
detail: typeof args["command"] === "string" ? String(args["command"]) : opTarget,
|
|
12998
|
+
reason: escalationApprovalReason(current, plan.target, plan.justification),
|
|
12999
|
+
rememberable: false
|
|
13000
|
+
})
|
|
13001
|
+
);
|
|
13002
|
+
if (signal?.aborted) {
|
|
13003
|
+
return { kind: "refused", output: "\u64CD\u4F5C\u5DF2\u4E2D\u6B62\uFF1A\u7528\u6237\u7EC8\u6B62\u4E86\u8FD9\u4E00\u8F6E\u3002" };
|
|
13004
|
+
}
|
|
13005
|
+
this.deps.permissionManager?.auditUserDecision?.(
|
|
13006
|
+
{ type: opType, target: opTarget, toolName: et.name },
|
|
13007
|
+
outcome
|
|
13008
|
+
);
|
|
13009
|
+
if (outcome !== "allow-once" && outcome !== "allow-session" && outcome !== "allow-always") {
|
|
13010
|
+
return {
|
|
13011
|
+
kind: "refused",
|
|
13012
|
+
output: "\u5347\u6743\u88AB\u62D2 [\u6C99\u7BB1]: \u7528\u6237\u6CA1\u6709\u6279\u51C6\u8FD9\u4E00\u6B21\u653E\u5F00\u8FB9\u754C\uFF0C\u547D\u4EE4\u6CA1\u6709\u6267\u884C\u3002\n\u522B\u6362\u4E2A\u5199\u6CD5\u518D\u8BD5\uFF0C\u4E5F\u522B\u5207\u6863\uFF08\u90A3\u662F\u6574\u4E2A\u4F1A\u8BDD\u7684\u4E8B\uFF09\u3002\u628A\u8FD9\u4EF6\u4E8B\u4F5C\u4E3A\u300C\u9700\u8981\u4ED6\u653E\u6743\u624D\u80FD\u505A\u300D\u62A5\u7ED9\u4ED6\uFF0C\u6216\u8005\u6362\u4E00\u6761\u4E0D\u9700\u8981\u8D8A\u754C\u7684\u505A\u6CD5\u3002"
|
|
13013
|
+
};
|
|
13014
|
+
}
|
|
13015
|
+
return { kind: "approved", target: plan.target };
|
|
13016
|
+
}
|
|
12292
13017
|
async checkPermission(et, args, signal) {
|
|
12293
13018
|
const pm = this.deps.permissionManager;
|
|
12294
13019
|
if (!pm) return { allowed: true };
|
|
@@ -12357,15 +13082,16 @@ var ToolExecutor = class {
|
|
|
12357
13082
|
var DEFAULT_CONTEXT_LENGTH = 128e3;
|
|
12358
13083
|
function shrank(before, after) {
|
|
12359
13084
|
const chars = (list) => list.reduce((sum, m) => sum + m.content.length, 0);
|
|
12360
|
-
|
|
13085
|
+
if (chars(after) < chars(before)) return true;
|
|
13086
|
+
return requestImageBytes(after) < requestImageBytes(before);
|
|
12361
13087
|
}
|
|
12362
13088
|
var NO_OUTPUT_TEXT = "(\u65E0\u8F93\u51FA)";
|
|
12363
13089
|
function imageParts(content) {
|
|
12364
13090
|
return typeof content === "string" ? [] : content.filter((p) => p.type === "image");
|
|
12365
13091
|
}
|
|
12366
13092
|
function toolSignatureOf(config, tools) {
|
|
12367
|
-
const direct = tools.map((
|
|
12368
|
-
const declared = (config.codeModeTools?.() ?? []).map((
|
|
13093
|
+
const direct = tools.map((t83) => t83.name).join("\0");
|
|
13094
|
+
const declared = (config.codeModeTools?.() ?? []).map((t83) => t83.name).join("\0");
|
|
12369
13095
|
return declared ? `${direct}|${declared}` : direct;
|
|
12370
13096
|
}
|
|
12371
13097
|
function modelSignatureOf(info) {
|
|
@@ -12384,13 +13110,13 @@ function stripHistoryImages(history) {
|
|
|
12384
13110
|
});
|
|
12385
13111
|
return { messages, stripped };
|
|
12386
13112
|
}
|
|
12387
|
-
function budgetStop(
|
|
12388
|
-
const breach =
|
|
12389
|
-
if (breach) return { message:
|
|
13113
|
+
function budgetStop(budget, messages) {
|
|
13114
|
+
const breach = budget.breachReason();
|
|
13115
|
+
if (breach) return { message: budget.describeBreach(breach), breach };
|
|
12390
13116
|
const imageTokens = pendingImageTokens(messages);
|
|
12391
|
-
const projected =
|
|
13117
|
+
const projected = budget.projectedBreach(imageTokens);
|
|
12392
13118
|
if (!projected) return void 0;
|
|
12393
|
-
return { message:
|
|
13119
|
+
return { message: budget.describeProjectedBreach(projected, imageTokens), breach: projected };
|
|
12394
13120
|
}
|
|
12395
13121
|
var AgentLoop = class {
|
|
12396
13122
|
config;
|
|
@@ -12456,12 +13182,34 @@ var AgentLoop = class {
|
|
|
12456
13182
|
abort() {
|
|
12457
13183
|
this.aborted = true;
|
|
12458
13184
|
}
|
|
13185
|
+
tryOffloadForBodyLimit(messages) {
|
|
13186
|
+
const sent = requestImageBytes(messages);
|
|
13187
|
+
this.learnBodyLimit(sent);
|
|
13188
|
+
const saved = offloadOldestImages(messages, {
|
|
13189
|
+
budgetBytes: Math.max(1, Math.floor(sent * 0.8))
|
|
13190
|
+
});
|
|
13191
|
+
return saved.offloaded > 0 ? { messages: saved.messages, offloaded: saved.offloaded } : null;
|
|
13192
|
+
}
|
|
12459
13193
|
multimodal() {
|
|
12460
13194
|
return resolveMultimodalPolicy({
|
|
12461
13195
|
...this.config.multimodal,
|
|
12462
13196
|
supportsImages: this.config.provider.capabilities?.supportsImages ?? false
|
|
12463
13197
|
});
|
|
12464
13198
|
}
|
|
13199
|
+
imageBudget() {
|
|
13200
|
+
const configured = this.config.maxRequestImageBytes ?? DEFAULT_MAX_REQUEST_IMAGE_BYTES;
|
|
13201
|
+
const key = this.imageLimitKey();
|
|
13202
|
+
return key ? effectiveImageBudget(configured, readLearnedImageBudget(...key)) : configured;
|
|
13203
|
+
}
|
|
13204
|
+
learnBodyLimit(sentBytes) {
|
|
13205
|
+
const key = this.imageLimitKey();
|
|
13206
|
+
if (key) learnImageBudget(...key, sentBytes);
|
|
13207
|
+
}
|
|
13208
|
+
imageLimitKey() {
|
|
13209
|
+
const homeDir = this.config.homeDir;
|
|
13210
|
+
if (!homeDir) return void 0;
|
|
13211
|
+
return [homeDir, "", this.config.provider.modelId ?? "unknown"];
|
|
13212
|
+
}
|
|
12465
13213
|
modelInfo() {
|
|
12466
13214
|
const id = this.config.provider.modelId;
|
|
12467
13215
|
if (!id) return void 0;
|
|
@@ -12501,6 +13249,7 @@ var AgentLoop = class {
|
|
|
12501
13249
|
projectBlock: seg2.projectBlock,
|
|
12502
13250
|
memoryBlock: seg2.memoryBlock,
|
|
12503
13251
|
historyText: opts.historyText,
|
|
13252
|
+
...opts.lastUsage ? { lastUsage: opts.lastUsage } : {},
|
|
12504
13253
|
tools: this.toolProvider.list().map((tool) => ({ tool, source: opts.toolSource?.(tool.name) ?? "builtin" })),
|
|
12505
13254
|
skillIndex: this.config.skillSystem?.indexStats?.({
|
|
12506
13255
|
only: this.config.roleSkills?.()
|
|
@@ -12518,6 +13267,7 @@ var AgentLoop = class {
|
|
|
12518
13267
|
let errored;
|
|
12519
13268
|
const started = Date.now();
|
|
12520
13269
|
for await (const ev of this.runTurns(input, turns)) {
|
|
13270
|
+
input.onEvent?.(ev);
|
|
12521
13271
|
if (ev.type === "finish") {
|
|
12522
13272
|
usage = ev.usage;
|
|
12523
13273
|
if (ev.reason === "stalled") stalled = true;
|
|
@@ -12620,13 +13370,15 @@ var AgentLoop = class {
|
|
|
12620
13370
|
let lastText = "";
|
|
12621
13371
|
let imagesDroppedReported = false;
|
|
12622
13372
|
let overflowRescued = false;
|
|
13373
|
+
let imagesRescue = { offloaded: 0 };
|
|
13374
|
+
let imagesOffloaded = false;
|
|
12623
13375
|
let runUsage;
|
|
12624
13376
|
let lastModel;
|
|
12625
13377
|
let lastRequestedModel;
|
|
12626
13378
|
const addRun = (u) => {
|
|
12627
13379
|
runUsage = runUsage ? addUsage(runUsage, u) : u;
|
|
12628
13380
|
};
|
|
12629
|
-
const
|
|
13381
|
+
const budget = new BudgetGuard({
|
|
12630
13382
|
...this.config.budget ? { budget: this.config.budget } : {},
|
|
12631
13383
|
...this.config.modelPricing ? { pricing: this.config.modelPricing } : {},
|
|
12632
13384
|
...input.maxCallCostUsd !== void 0 ? { maxCallCostUsd: input.maxCallCostUsd } : {},
|
|
@@ -12638,7 +13390,7 @@ var AgentLoop = class {
|
|
|
12638
13390
|
const finish = (reason9, breach) => ({
|
|
12639
13391
|
type: "finish",
|
|
12640
13392
|
reason: reason9,
|
|
12641
|
-
usage:
|
|
13393
|
+
usage: budget.snapshot(),
|
|
12642
13394
|
...runUsage ? { runUsage } : {},
|
|
12643
13395
|
...lastModel ? { model: lastModel } : {},
|
|
12644
13396
|
...lastRequestedModel ? { requestedModel: lastRequestedModel } : {},
|
|
@@ -12690,8 +13442,8 @@ var AgentLoop = class {
|
|
|
12690
13442
|
await this.prompt.syncMemory(userText, lastText);
|
|
12691
13443
|
return;
|
|
12692
13444
|
}
|
|
12693
|
-
|
|
12694
|
-
const stop = budgetStop(
|
|
13445
|
+
budget.syncFromStore();
|
|
13446
|
+
const stop = budgetStop(budget, messages);
|
|
12695
13447
|
if (stop) {
|
|
12696
13448
|
yield { type: "text-delta", text: stop.message };
|
|
12697
13449
|
await this.prompt.syncMemory(userText, lastText || stop.message);
|
|
@@ -12743,8 +13495,8 @@ var AgentLoop = class {
|
|
|
12743
13495
|
}
|
|
12744
13496
|
if (rescued.usage) {
|
|
12745
13497
|
addRun(rescued.usage);
|
|
12746
|
-
yield*
|
|
12747
|
-
|
|
13498
|
+
yield* budget.toEvents(
|
|
13499
|
+
budget.add(rescued.usage, this.rateOf(rescued.model)),
|
|
12748
13500
|
runUsage
|
|
12749
13501
|
);
|
|
12750
13502
|
}
|
|
@@ -12776,6 +13528,7 @@ var AgentLoop = class {
|
|
|
12776
13528
|
}
|
|
12777
13529
|
}
|
|
12778
13530
|
const turnStart = Date.now();
|
|
13531
|
+
imagesRescue = { offloaded: 0 };
|
|
12779
13532
|
const llmSpan = this.telemetry.startSpan(
|
|
12780
13533
|
"llm_call",
|
|
12781
13534
|
{
|
|
@@ -12788,6 +13541,24 @@ var AgentLoop = class {
|
|
|
12788
13541
|
);
|
|
12789
13542
|
let guard = this.config.compliance?.outputGuard();
|
|
12790
13543
|
let reasoningGuard = this.config.compliance?.outputGuard();
|
|
13544
|
+
const imageBudget = this.imageBudget();
|
|
13545
|
+
const beforeBytes = requestImageBytes(messages);
|
|
13546
|
+
if (beforeBytes > imageBudget) {
|
|
13547
|
+
const offloadedResult = offloadOldestImages(messages, { budgetBytes: imageBudget });
|
|
13548
|
+
if (offloadedResult.offloaded > 0) {
|
|
13549
|
+
messages = offloadedResult.messages;
|
|
13550
|
+
if (!imagesOffloaded) {
|
|
13551
|
+
imagesOffloaded = true;
|
|
13552
|
+
yield {
|
|
13553
|
+
type: "notice",
|
|
13554
|
+
code: "images-offloaded",
|
|
13555
|
+
text: t("agent_run.images_offloaded", {
|
|
13556
|
+
count: offloadedResult.offloaded
|
|
13557
|
+
})
|
|
13558
|
+
};
|
|
13559
|
+
}
|
|
13560
|
+
}
|
|
13561
|
+
}
|
|
12791
13562
|
const requestFor = (msgs) => ({
|
|
12792
13563
|
provider: this.config.provider,
|
|
12793
13564
|
input: {
|
|
@@ -12804,34 +13575,59 @@ var AgentLoop = class {
|
|
|
12804
13575
|
});
|
|
12805
13576
|
let result;
|
|
12806
13577
|
try {
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
|
|
12813
|
-
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
13578
|
+
for (; ; ) {
|
|
13579
|
+
try {
|
|
13580
|
+
result = yield* runTurn(requestFor(messages));
|
|
13581
|
+
if (result.usage) {
|
|
13582
|
+
llmSpan.setAttribute(GEN_AI.USAGE_INPUT_TOKENS, result.usage.inputTokens);
|
|
13583
|
+
llmSpan.setAttribute(GEN_AI.USAGE_OUTPUT_TOKENS, result.usage.outputTokens);
|
|
13584
|
+
}
|
|
13585
|
+
llmSpan.setAttribute("epoch.finish_reason", result.finishReason);
|
|
13586
|
+
break;
|
|
13587
|
+
} catch (err) {
|
|
13588
|
+
llmSpan.recordError(err);
|
|
13589
|
+
if (isBodyTooLarge(err) && imagesRescue.offloaded === 0) {
|
|
13590
|
+
const saved = this.tryOffloadForBodyLimit(messages);
|
|
13591
|
+
if (saved) {
|
|
13592
|
+
messages = saved.messages;
|
|
13593
|
+
imagesRescue = { offloaded: saved.offloaded };
|
|
13594
|
+
yield {
|
|
13595
|
+
type: "notice",
|
|
13596
|
+
code: "images-offloaded",
|
|
13597
|
+
text: t("agent_run.images_offloaded", { count: saved.offloaded })
|
|
13598
|
+
};
|
|
13599
|
+
guard = this.config.compliance?.outputGuard();
|
|
13600
|
+
reasoningGuard = this.config.compliance?.outputGuard();
|
|
13601
|
+
continue;
|
|
13602
|
+
}
|
|
13603
|
+
}
|
|
13604
|
+
const engine = this.config.contextEngine;
|
|
13605
|
+
const retriable = isContextOverflow(err) || isBodyTooLarge(err);
|
|
13606
|
+
if (overflowRescued || !engine || !retriable) throw err;
|
|
13607
|
+
overflowRescued = true;
|
|
13608
|
+
const rescued = await this.compressNow(messages, {
|
|
13609
|
+
totalTokens: totalInput + totalOutput,
|
|
13610
|
+
force: true
|
|
13611
|
+
});
|
|
13612
|
+
if (rescued.usage) {
|
|
13613
|
+
addRun(rescued.usage);
|
|
13614
|
+
yield* budget.toEvents(
|
|
13615
|
+
budget.add(rescued.usage, this.rateOf(rescued.model)),
|
|
13616
|
+
runUsage
|
|
13617
|
+
);
|
|
13618
|
+
}
|
|
13619
|
+
if (!shrank(messages, rescued.messages)) throw err;
|
|
13620
|
+
messages = rescued.messages;
|
|
13621
|
+
yield {
|
|
13622
|
+
type: "notice",
|
|
13623
|
+
code: "context-compacted",
|
|
13624
|
+
text: t("agent_run.context_compacted")
|
|
13625
|
+
};
|
|
13626
|
+
guard = this.config.compliance?.outputGuard();
|
|
13627
|
+
reasoningGuard = this.config.compliance?.outputGuard();
|
|
13628
|
+
continue;
|
|
13629
|
+
}
|
|
12824
13630
|
}
|
|
12825
|
-
if (!shrank(messages, rescued.messages)) throw err;
|
|
12826
|
-
messages = rescued.messages;
|
|
12827
|
-
yield {
|
|
12828
|
-
type: "notice",
|
|
12829
|
-
code: "context-compacted",
|
|
12830
|
-
text: t("agent_run.context_compacted")
|
|
12831
|
-
};
|
|
12832
|
-
guard = this.config.compliance?.outputGuard();
|
|
12833
|
-
reasoningGuard = this.config.compliance?.outputGuard();
|
|
12834
|
-
result = yield* runTurn(requestFor(messages));
|
|
12835
13631
|
} finally {
|
|
12836
13632
|
llmSpan.end();
|
|
12837
13633
|
this.telemetry.histogram(METRIC.LLM_CALL_LATENCY, Date.now() - turnStart);
|
|
@@ -12877,14 +13673,14 @@ var AgentLoop = class {
|
|
|
12877
13673
|
"epoch.token_type": "cache_write"
|
|
12878
13674
|
});
|
|
12879
13675
|
}
|
|
12880
|
-
const status =
|
|
13676
|
+
const status = budget.add(usage, this.rateOf(result.model));
|
|
12881
13677
|
input.onTurnUsage?.(
|
|
12882
13678
|
status.turnCostUsd === void 0 ? usage : { ...usage, costUsd: status.turnCostUsd }
|
|
12883
13679
|
);
|
|
12884
13680
|
addRun(usage);
|
|
12885
13681
|
lastModel = result.model;
|
|
12886
13682
|
lastRequestedModel = result.requestedModel;
|
|
12887
|
-
yield*
|
|
13683
|
+
yield* budget.toEvents(status, runUsage);
|
|
12888
13684
|
}
|
|
12889
13685
|
const verdict = mergeVerdicts(guard?.verdict(), reasoningGuard?.verdict());
|
|
12890
13686
|
if (verdict) this.reportCompliance(verdict, "output");
|
|
@@ -12949,7 +13745,11 @@ ${finalText}` };
|
|
|
12949
13745
|
turn
|
|
12950
13746
|
});
|
|
12951
13747
|
if (turn < maxTurns && input.steer?.pending() === true) {
|
|
12952
|
-
messages.push({
|
|
13748
|
+
messages.push({
|
|
13749
|
+
role: "assistant",
|
|
13750
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13751
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13752
|
+
});
|
|
12953
13753
|
yield* this.drainSteer(input, messages);
|
|
12954
13754
|
continue;
|
|
12955
13755
|
}
|
|
@@ -12960,7 +13760,11 @@ ${finalText}` };
|
|
|
12960
13760
|
);
|
|
12961
13761
|
if (wantContinue && turn < maxTurns) {
|
|
12962
13762
|
messages.push(
|
|
12963
|
-
{
|
|
13763
|
+
{
|
|
13764
|
+
role: "assistant",
|
|
13765
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13766
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13767
|
+
},
|
|
12964
13768
|
{
|
|
12965
13769
|
role: "user",
|
|
12966
13770
|
content: systemNote(
|
|
@@ -12980,7 +13784,11 @@ ${finalText}` };
|
|
|
12980
13784
|
text: t("agent_run.blank_response")
|
|
12981
13785
|
};
|
|
12982
13786
|
messages.push(
|
|
12983
|
-
{
|
|
13787
|
+
{
|
|
13788
|
+
role: "assistant",
|
|
13789
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13790
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13791
|
+
},
|
|
12984
13792
|
{ role: "user", content: systemNote(blankResponseNote(finalText.trim().length)) }
|
|
12985
13793
|
);
|
|
12986
13794
|
continue;
|
|
@@ -12992,7 +13800,11 @@ ${finalText}` };
|
|
|
12992
13800
|
if (open !== void 0 && open > 0) {
|
|
12993
13801
|
todoNudged = true;
|
|
12994
13802
|
messages.push(
|
|
12995
|
-
{
|
|
13803
|
+
{
|
|
13804
|
+
role: "assistant",
|
|
13805
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13806
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13807
|
+
},
|
|
12996
13808
|
{
|
|
12997
13809
|
role: "user",
|
|
12998
13810
|
content: systemNote(unfinishedTodoNote(open))
|
|
@@ -13004,7 +13816,11 @@ ${finalText}` };
|
|
|
13004
13816
|
if (!idleNudged && turn < maxTurns && !truncated && announcedNextStep(finalText)) {
|
|
13005
13817
|
idleNudged = true;
|
|
13006
13818
|
messages.push(
|
|
13007
|
-
{
|
|
13819
|
+
{
|
|
13820
|
+
role: "assistant",
|
|
13821
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13822
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13823
|
+
},
|
|
13008
13824
|
{ role: "user", content: systemNote(announcedButIdleNote()) }
|
|
13009
13825
|
);
|
|
13010
13826
|
continue;
|
|
@@ -13022,6 +13838,7 @@ ${finalText}` };
|
|
|
13022
13838
|
messages.push({
|
|
13023
13839
|
role: "assistant",
|
|
13024
13840
|
content: result.text,
|
|
13841
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {},
|
|
13025
13842
|
toolCalls: toolCalls.map((tc) => ({
|
|
13026
13843
|
toolCallId: tc.toolCallId,
|
|
13027
13844
|
toolName: tc.toolName,
|
|
@@ -13121,8 +13938,8 @@ ${finalText}` };
|
|
|
13121
13938
|
messages = compacted.messages;
|
|
13122
13939
|
if (compacted.usage) {
|
|
13123
13940
|
addRun(compacted.usage);
|
|
13124
|
-
yield*
|
|
13125
|
-
|
|
13941
|
+
yield* budget.toEvents(
|
|
13942
|
+
budget.add(compacted.usage, this.rateOf(compacted.model)),
|
|
13126
13943
|
runUsage
|
|
13127
13944
|
);
|
|
13128
13945
|
}
|
|
@@ -13199,7 +14016,7 @@ ${finalText}` };
|
|
|
13199
14016
|
return { ...result, ran: true };
|
|
13200
14017
|
}
|
|
13201
14018
|
async compressNow(messages, opts = {}) {
|
|
13202
|
-
const { instruction, totalTokens: totalTokens2, promptTokens:
|
|
14019
|
+
const { instruction, totalTokens: totalTokens2, promptTokens: promptTokens3, force } = opts;
|
|
13203
14020
|
const engine = this.config.contextEngine;
|
|
13204
14021
|
if (!engine) return { messages };
|
|
13205
14022
|
try {
|
|
@@ -13209,7 +14026,8 @@ ${finalText}` };
|
|
|
13209
14026
|
contextLength: this.config.contextLength,
|
|
13210
14027
|
...instruction ? { instruction } : {},
|
|
13211
14028
|
...plan ? { plan } : {},
|
|
13212
|
-
...
|
|
14029
|
+
...force ? { force } : {},
|
|
14030
|
+
...promptTokens3 === void 0 ? {} : { promptTokens: promptTokens3 }
|
|
13213
14031
|
});
|
|
13214
14032
|
const bill = {
|
|
13215
14033
|
...compressed.usage ? { usage: compressed.usage } : {},
|
|
@@ -13426,6 +14244,9 @@ var CompressionSchema = z.object({
|
|
|
13426
14244
|
enabled: z.boolean().default(true),
|
|
13427
14245
|
threshold: z.number().gt(0).max(1).default(DEFAULT_COMPRESSION_THRESHOLD)
|
|
13428
14246
|
});
|
|
14247
|
+
var LimitsSchema = z.object({
|
|
14248
|
+
maxRequestImageBytes: z.int().positive().optional()
|
|
14249
|
+
});
|
|
13429
14250
|
var DEFAULT_MEMORY_CHAR_LIMIT = 2e4;
|
|
13430
14251
|
var DEFAULT_USER_CHAR_LIMIT = 6e3;
|
|
13431
14252
|
var DEFAULT_MEMORY_INDEX_CHAR_LIMIT = 4e3;
|
|
@@ -13437,6 +14258,9 @@ var MemorySchema = z.object({
|
|
|
13437
14258
|
var SandboxSchema = z.object({
|
|
13438
14259
|
terminal: z.boolean().default(true)
|
|
13439
14260
|
});
|
|
14261
|
+
var DelegateSchema = z.object({
|
|
14262
|
+
taskTimeoutSec: z.int().nonnegative().default(900)
|
|
14263
|
+
});
|
|
13440
14264
|
var ToolsSchema = z.object({
|
|
13441
14265
|
deferMcp: z.boolean().default(false),
|
|
13442
14266
|
mode: z.enum(["tools", "both", "code"]).default("tools")
|
|
@@ -13545,7 +14369,17 @@ var EpochConfigSchema = z.object({
|
|
|
13545
14369
|
maxOutputTokens: z.int().positive().optional(),
|
|
13546
14370
|
homeDir: z.string().min(1).default(() => resolveHomeDir()),
|
|
13547
14371
|
dbPath: z.string().min(1).default(() => dbPath(resolveHomeDir())),
|
|
13548
|
-
permission: z.
|
|
14372
|
+
permission: z.string().default(DEFAULT_PERMISSION_LEVEL).superRefine((raw, ctx) => {
|
|
14373
|
+
if (resolvePermissionLevel(raw) === void 0) {
|
|
14374
|
+
ctx.addIssue({
|
|
14375
|
+
code: "custom",
|
|
14376
|
+
message: t("config_load.bad_permission_level", {
|
|
14377
|
+
raw,
|
|
14378
|
+
levels: PERMISSION_LEVELS.join(" / ")
|
|
14379
|
+
})
|
|
14380
|
+
});
|
|
14381
|
+
}
|
|
14382
|
+
}).transform((raw) => resolvePermissionLevel(raw) ?? DEFAULT_PERMISSION_LEVEL),
|
|
13549
14383
|
permissions: z.object({
|
|
13550
14384
|
allow: z.array(z.string().min(1)).optional(),
|
|
13551
14385
|
ask: z.array(z.string().min(1)).optional(),
|
|
@@ -13558,9 +14392,11 @@ var EpochConfigSchema = z.object({
|
|
|
13558
14392
|
hooks: z.record(z.string(), z.unknown()).optional(),
|
|
13559
14393
|
trust: TrustSchema.optional(),
|
|
13560
14394
|
sandbox: SandboxSchema.prefault({}),
|
|
14395
|
+
delegate: DelegateSchema.prefault({}),
|
|
13561
14396
|
tools: ToolsSchema.prefault({}),
|
|
13562
14397
|
skills: SkillsSchema.optional(),
|
|
13563
14398
|
compression: CompressionSchema.prefault({}),
|
|
14399
|
+
limits: LimitsSchema.prefault({}),
|
|
13564
14400
|
memory: MemorySchema.prefault({}),
|
|
13565
14401
|
artifacts: ArtifactsSchema.prefault({}),
|
|
13566
14402
|
sessions: SessionsSchema.prefault({}),
|
|
@@ -13592,6 +14428,7 @@ var EpochConfigSchema = z.object({
|
|
|
13592
14428
|
message: "blankCards: id must be unique"
|
|
13593
14429
|
}).optional(),
|
|
13594
14430
|
blankGreeting: BlankGreetingSchema.optional(),
|
|
14431
|
+
scheduleRemoveConfirm: HostTextSchema.optional(),
|
|
13595
14432
|
user: HostUserSchema.optional(),
|
|
13596
14433
|
settingsHidden: z.array(z.string().min(1)).min(1).optional(),
|
|
13597
14434
|
settingsPanes: z.array(
|
|
@@ -13634,6 +14471,22 @@ function settingsPaneBeforeIssues(config) {
|
|
|
13634
14471
|
message: `unknown settings pane id: ${String(pane.before)} (known: ${SETTINGS_PANE_IDS.join(", ")})`
|
|
13635
14472
|
}));
|
|
13636
14473
|
}
|
|
14474
|
+
function scheduleRemoveConfirmIssues(config) {
|
|
14475
|
+
const texts = config.scheduleRemoveConfirm;
|
|
14476
|
+
if (texts === void 0) return [];
|
|
14477
|
+
const issues = [];
|
|
14478
|
+
for (const [lang, text] of Object.entries(texts)) {
|
|
14479
|
+
if (text === void 0) continue;
|
|
14480
|
+
for (const name of placeholdersOf(text)) {
|
|
14481
|
+
if (name === SCHEDULE_CONFIRM_PLACEHOLDER) continue;
|
|
14482
|
+
issues.push({
|
|
14483
|
+
path: `scheduleRemoveConfirm.${lang}`,
|
|
14484
|
+
message: `unknown placeholder: {${name}} (only {${SCHEDULE_CONFIRM_PLACEHOLDER}} is substituted; write {{${SCHEDULE_CONFIRM_PLACEHOLDER}}} if you meant it literally)`
|
|
14485
|
+
});
|
|
14486
|
+
}
|
|
14487
|
+
}
|
|
14488
|
+
return issues;
|
|
14489
|
+
}
|
|
13637
14490
|
function defaultConfig() {
|
|
13638
14491
|
return EpochConfigSchema.parse({});
|
|
13639
14492
|
}
|
|
@@ -13767,7 +14620,7 @@ var ManagedPolicyError = class extends Error {
|
|
|
13767
14620
|
}
|
|
13768
14621
|
};
|
|
13769
14622
|
function assertLevelAllowed(level, policy) {
|
|
13770
|
-
if (level !== "
|
|
14623
|
+
if (approvalPolicyForLevel(level) !== "never" || !policy.disableBypassPermissionsMode) return;
|
|
13771
14624
|
throw new ManagedPolicyError(
|
|
13772
14625
|
t("managed_settings.bypass_blocked"),
|
|
13773
14626
|
t("managed_settings.bypass_blocked_hint", { path: policy.path })
|
|
@@ -14072,18 +14925,18 @@ function _loadImpl(overrideHomeDir) {
|
|
|
14072
14925
|
if (read.kind === "corrupt" && _lastKnownGood?.homeDir === homeDir) {
|
|
14073
14926
|
_lastIssues = issues;
|
|
14074
14927
|
_lastOrigins = _lastKnownGood.origins;
|
|
14075
|
-
const
|
|
14928
|
+
const cached2 = _lastKnownGood;
|
|
14076
14929
|
_cache = {
|
|
14077
14930
|
homeDir,
|
|
14078
14931
|
mtime,
|
|
14079
14932
|
size,
|
|
14080
14933
|
entriesStamp,
|
|
14081
14934
|
envSnapshot,
|
|
14082
|
-
config:
|
|
14935
|
+
config: cached2.config,
|
|
14083
14936
|
issues,
|
|
14084
|
-
origins:
|
|
14937
|
+
origins: cached2.origins
|
|
14085
14938
|
};
|
|
14086
|
-
return
|
|
14939
|
+
return cached2.config;
|
|
14087
14940
|
}
|
|
14088
14941
|
const config = parseRawConfig(read.raw, issues, track);
|
|
14089
14942
|
reportDroppedEnv(issues);
|
|
@@ -14139,6 +14992,7 @@ function parseRawConfig(raw, issues, track) {
|
|
|
14139
14992
|
issues.push(...outcome.issues);
|
|
14140
14993
|
issues.push(...settingsHiddenIssues(outcome.value));
|
|
14141
14994
|
issues.push(...settingsPaneBeforeIssues(outcome.value));
|
|
14995
|
+
issues.push(...scheduleRemoveConfirmIssues(outcome.value));
|
|
14142
14996
|
if (outcome.issues.length === 0) collectKeyPaths(cleaned, track.file);
|
|
14143
14997
|
return outcome.value;
|
|
14144
14998
|
}
|
|
@@ -14269,8 +15123,9 @@ function applyEnvOverrides(config, issues, track) {
|
|
|
14269
15123
|
} else issues.push(envIssue("EPOCH_LOG_LEVEL", env.EPOCH_LOG_LEVEL, levels.join(" / ")));
|
|
14270
15124
|
}
|
|
14271
15125
|
if (env.EPOCH_PERMISSION) {
|
|
14272
|
-
|
|
14273
|
-
|
|
15126
|
+
const level = resolvePermissionLevel(env.EPOCH_PERMISSION);
|
|
15127
|
+
if (level) {
|
|
15128
|
+
config.permission = level;
|
|
14274
15129
|
track.env.add("permission");
|
|
14275
15130
|
} else {
|
|
14276
15131
|
issues.push(
|
|
@@ -14780,11 +15635,11 @@ function buildPricing(prompt, completion, cacheRead) {
|
|
|
14780
15635
|
const output = Number.parseFloat(completion) * 1e6;
|
|
14781
15636
|
if (!Number.isFinite(input) || !Number.isFinite(output)) return void 0;
|
|
14782
15637
|
if (input <= 0 && output <= 0) return void 0;
|
|
14783
|
-
const
|
|
15638
|
+
const cached2 = cacheRead ? Number.parseFloat(cacheRead) * 1e6 : NaN;
|
|
14784
15639
|
return {
|
|
14785
15640
|
inputPerMTok: input,
|
|
14786
15641
|
outputPerMTok: output,
|
|
14787
|
-
...Number.isFinite(
|
|
15642
|
+
...Number.isFinite(cached2) && cached2 > 0 ? { cachedInputPerMTok: cached2 } : {}
|
|
14788
15643
|
};
|
|
14789
15644
|
}
|
|
14790
15645
|
function matchesWindow(o, at) {
|
|
@@ -15001,6 +15856,30 @@ var TOOL_RESULT_MEDIA = {
|
|
|
15001
15856
|
function acceptsToolResultMedia(type) {
|
|
15002
15857
|
return TOOL_RESULT_MEDIA[type];
|
|
15003
15858
|
}
|
|
15859
|
+
var CARRIES_REASONING_BACK = {
|
|
15860
|
+
"openai-compatible": true,
|
|
15861
|
+
deepseek: true,
|
|
15862
|
+
openai: false,
|
|
15863
|
+
anthropic: false,
|
|
15864
|
+
google: false,
|
|
15865
|
+
groq: false,
|
|
15866
|
+
mistral: false,
|
|
15867
|
+
moonshotai: false,
|
|
15868
|
+
zhipu: true,
|
|
15869
|
+
dashscope: false,
|
|
15870
|
+
bytedance: true,
|
|
15871
|
+
qianfan: true,
|
|
15872
|
+
cohere: false,
|
|
15873
|
+
xai: false,
|
|
15874
|
+
perplexity: false,
|
|
15875
|
+
togetherai: false,
|
|
15876
|
+
azure: false,
|
|
15877
|
+
"amazon-bedrock": false,
|
|
15878
|
+
ollama: false
|
|
15879
|
+
};
|
|
15880
|
+
function carriesReasoningBack(type) {
|
|
15881
|
+
return CARRIES_REASONING_BACK[type];
|
|
15882
|
+
}
|
|
15004
15883
|
function isModuleNotFound(err) {
|
|
15005
15884
|
if (!err || typeof err !== "object") return false;
|
|
15006
15885
|
const code = err.code;
|
|
@@ -15009,9 +15888,10 @@ function isModuleNotFound(err) {
|
|
|
15009
15888
|
return /Cannot find (module|package)|Failed to resolve/i.test(msg);
|
|
15010
15889
|
}
|
|
15011
15890
|
// src/provider/entry-route.ts
|
|
15012
|
-
function buildEntryTable(entries2) {
|
|
15891
|
+
function buildEntryTable(entries2, homeDir) {
|
|
15013
15892
|
return {
|
|
15014
|
-
entries: new Map((entries2 ?? []).map((e) => [e.id, e]))
|
|
15893
|
+
entries: new Map((entries2 ?? []).map((e) => [e.id, e])),
|
|
15894
|
+
...homeDir ? { homeDir } : {}
|
|
15015
15895
|
};
|
|
15016
15896
|
}
|
|
15017
15897
|
function entryProvider(_table, entry) {
|
|
@@ -15046,6 +15926,14 @@ function entryAcceptsToolMedia(table, provider, entry) {
|
|
|
15046
15926
|
if (e?.provider === "openai-compatible" && e.protocol === "anthropic-messages") return true;
|
|
15047
15927
|
return acceptsToolResultMedia(provider);
|
|
15048
15928
|
}
|
|
15929
|
+
function entryCarriesReasoningBack(table, provider, entry) {
|
|
15930
|
+
const e = table.entries.get(entry);
|
|
15931
|
+
if (e?.provider === "openai-compatible" && e.protocol === "anthropic-messages") return false;
|
|
15932
|
+
if (!carriesReasoningBack(provider)) return false;
|
|
15933
|
+
if (!e) return false;
|
|
15934
|
+
if (!table.homeDir) return false;
|
|
15935
|
+
return applyEntryCapability(getCapability(e.model, table.homeDir, e.provider), e).supportsReasoning;
|
|
15936
|
+
}
|
|
15049
15937
|
function capabilityOfRef(config, ref = config.model) {
|
|
15050
15938
|
const parsed = ref ? parseModelRef(ref) : void 0;
|
|
15051
15939
|
const entry = parsed ? config.modelEntries?.find((e) => e.id === parsed.entry) : void 0;
|
|
@@ -15213,7 +16101,7 @@ var ProviderRouter = class {
|
|
|
15213
16101
|
}
|
|
15214
16102
|
constructor(config) {
|
|
15215
16103
|
this.config = config;
|
|
15216
|
-
this.entryTable = buildEntryTable(config.modelEntries);
|
|
16104
|
+
this.entryTable = buildEntryTable(config.modelEntries, config.homeDir);
|
|
15217
16105
|
this.configSelection = this.resolveConfigured(config);
|
|
15218
16106
|
this.initFactories();
|
|
15219
16107
|
this.selection = { ...this.configSelection };
|
|
@@ -15264,7 +16152,7 @@ var ProviderRouter = class {
|
|
|
15264
16152
|
return result;
|
|
15265
16153
|
}
|
|
15266
16154
|
reloadModelEntries(entries2) {
|
|
15267
|
-
this.entryTable = buildEntryTable(entries2);
|
|
16155
|
+
this.entryTable = buildEntryTable(entries2, this.config.homeDir);
|
|
15268
16156
|
for (const [route, opts] of [...this.available]) {
|
|
15269
16157
|
if (!opts.entry) continue;
|
|
15270
16158
|
this.available.delete(route);
|
|
@@ -15413,8 +16301,8 @@ var ProviderRouter = class {
|
|
|
15413
16301
|
return { selection, configured: true };
|
|
15414
16302
|
}
|
|
15415
16303
|
async getModel(route, modelId) {
|
|
15416
|
-
const
|
|
15417
|
-
if (
|
|
16304
|
+
const cached2 = this.factories.get(route);
|
|
16305
|
+
if (cached2) return cached2(modelId ?? this.selection.model);
|
|
15418
16306
|
const opts = this.available.get(route);
|
|
15419
16307
|
if (!opts) {
|
|
15420
16308
|
throw new ProviderError(
|
|
@@ -15524,7 +16412,7 @@ var ProviderRouter = class {
|
|
|
15524
16412
|
const state = this.startPoint(input);
|
|
15525
16413
|
const requestedModel = state.cm;
|
|
15526
16414
|
const messagesFor = messageTranslator(input.messages, this.entryTable);
|
|
15527
|
-
const tools = input.tools ? toSdkTools(input.tools) : void 0;
|
|
16415
|
+
const tools = input.tools ? toSdkTools(input.tools, { cacheBreakpoint: true }) : void 0;
|
|
15528
16416
|
const output = input.responseFormat ? toOutputSpec(input.responseFormat) : void 0;
|
|
15529
16417
|
for (; ; ) {
|
|
15530
16418
|
if (state.attempt > this.config.retry.maxRetries) {
|
|
@@ -15598,7 +16486,7 @@ var ProviderRouter = class {
|
|
|
15598
16486
|
const requestedModel = state.cm;
|
|
15599
16487
|
let emitted = false;
|
|
15600
16488
|
const messagesFor = messageTranslator(input.messages, this.entryTable);
|
|
15601
|
-
const tools = input.tools ? toSdkTools(input.tools) : void 0;
|
|
16489
|
+
const tools = input.tools ? toSdkTools(input.tools, { cacheBreakpoint: true }) : void 0;
|
|
15602
16490
|
const output = input.responseFormat ? toOutputSpec(input.responseFormat) : void 0;
|
|
15603
16491
|
let streamPartError;
|
|
15604
16492
|
for (; ; ) {
|
|
@@ -15735,8 +16623,8 @@ var ProviderRouter = class {
|
|
|
15735
16623
|
async probeImageSupport() {
|
|
15736
16624
|
const { provider, model, entry } = this.selection;
|
|
15737
16625
|
const home = this.config.homeDir;
|
|
15738
|
-
const
|
|
15739
|
-
if (
|
|
16626
|
+
const cached2 = readImageProbe(home, provider, model);
|
|
16627
|
+
if (cached2 !== void 0) return cached2;
|
|
15740
16628
|
let lm;
|
|
15741
16629
|
try {
|
|
15742
16630
|
lm = await this.getModel(this.routeOf(provider, entry), model);
|
|
@@ -15764,10 +16652,12 @@ function messageTranslator(messages, table) {
|
|
|
15764
16652
|
const cache = /* @__PURE__ */ new Map();
|
|
15765
16653
|
return (type, entry) => {
|
|
15766
16654
|
const inline = entryAcceptsToolMedia(table, type, entry);
|
|
15767
|
-
|
|
16655
|
+
const reasoning = entryCarriesReasoningBack(table, type, entry);
|
|
16656
|
+
const key = `${inline}|${reasoning}`;
|
|
16657
|
+
let hit = cache.get(key);
|
|
15768
16658
|
if (!hit) {
|
|
15769
|
-
hit = toModelMessages(messages, { toolMediaInline: inline });
|
|
15770
|
-
cache.set(
|
|
16659
|
+
hit = toModelMessages(messages, { toolMediaInline: inline, reasoning });
|
|
16660
|
+
cache.set(key, hit);
|
|
15771
16661
|
}
|
|
15772
16662
|
return hit;
|
|
15773
16663
|
};
|
|
@@ -15838,12 +16728,12 @@ var PROVIDER_DISCOVERY = {
|
|
|
15838
16728
|
function discoverySpec(provider) {
|
|
15839
16729
|
return PROVIDER_DISCOVERY[provider];
|
|
15840
16730
|
}
|
|
15841
|
-
function
|
|
16731
|
+
function cachePath2(homeDir, provider) {
|
|
15842
16732
|
return join(homeDir, "cache", `models_${provider}.json`);
|
|
15843
16733
|
}
|
|
15844
16734
|
function loadCache2(homeDir, provider) {
|
|
15845
16735
|
try {
|
|
15846
|
-
const path =
|
|
16736
|
+
const path = cachePath2(homeDir, provider);
|
|
15847
16737
|
if (!existsSync(path)) return null;
|
|
15848
16738
|
const data = JSON.parse(readFileSync(path, "utf-8"));
|
|
15849
16739
|
const age = Date.now() - (data._cachedAt ?? 0);
|
|
@@ -15858,7 +16748,7 @@ function saveCache2(homeDir, provider, models) {
|
|
|
15858
16748
|
const dir = join(homeDir, "cache");
|
|
15859
16749
|
mkdirSync(dir, { recursive: true });
|
|
15860
16750
|
writeFileSync(
|
|
15861
|
-
|
|
16751
|
+
cachePath2(homeDir, provider),
|
|
15862
16752
|
JSON.stringify({ models, _cachedAt: Date.now() }),
|
|
15863
16753
|
"utf-8"
|
|
15864
16754
|
);
|
|
@@ -15937,13 +16827,13 @@ async function discoverModels(homeDir, provider, apiKey, baseUrl) {
|
|
|
15937
16827
|
}
|
|
15938
16828
|
}
|
|
15939
16829
|
}
|
|
15940
|
-
const
|
|
15941
|
-
if (
|
|
16830
|
+
const cached2 = loadCache2(homeDir, provider);
|
|
16831
|
+
if (cached2) return { models: cached2, source: "cache" };
|
|
15942
16832
|
return { models: STATIC_MODEL_CATALOG[provider] ?? [], source: "static" };
|
|
15943
16833
|
}
|
|
15944
16834
|
function clearModelCache(homeDir, provider) {
|
|
15945
16835
|
try {
|
|
15946
|
-
const path =
|
|
16836
|
+
const path = cachePath2(homeDir, provider);
|
|
15947
16837
|
if (existsSync(path)) writeFileSync(path, "{}", "utf-8");
|
|
15948
16838
|
} catch {
|
|
15949
16839
|
}
|
|
@@ -16140,7 +17030,10 @@ var VALUE_SCHEMA = {
|
|
|
16140
17030
|
"automation.keepRuns": EpochConfigSchema.shape.automation.unwrap().shape.keepRuns.unwrap(),
|
|
16141
17031
|
"automation.maxRecordingMb": EpochConfigSchema.shape.automation.unwrap().shape.maxRecordingMb.unwrap(),
|
|
16142
17032
|
"sessionSearch.allWorkspaces": EpochConfigSchema.shape.sessionSearch.unwrap().shape.allWorkspaces.unwrap(),
|
|
16143
|
-
permission: EpochConfigSchema.shape.permission
|
|
17033
|
+
permission: EpochConfigSchema.shape.permission
|
|
17034
|
+
};
|
|
17035
|
+
var ENUM_CHOICES = {
|
|
17036
|
+
permission: PERMISSION_LEVELS
|
|
16144
17037
|
};
|
|
16145
17038
|
function settingValueKind(key) {
|
|
16146
17039
|
if (!isWritableSettingKey(key)) return null;
|
|
@@ -16151,6 +17044,8 @@ function settingValueKind(key) {
|
|
|
16151
17044
|
}
|
|
16152
17045
|
function settingValueChoices(key) {
|
|
16153
17046
|
if (!isWritableSettingKey(key)) return null;
|
|
17047
|
+
const explicit = ENUM_CHOICES[key];
|
|
17048
|
+
if (explicit) return explicit;
|
|
16154
17049
|
const schema = VALUE_SCHEMA[key];
|
|
16155
17050
|
if (schema.def.type !== "enum") return null;
|
|
16156
17051
|
return Object.values(schema.def.entries).map(String);
|
|
@@ -16293,6 +17188,7 @@ function commit(path, body2, createMode, value) {
|
|
|
16293
17188
|
}
|
|
16294
17189
|
return { ok: true, value };
|
|
16295
17190
|
}
|
|
17191
|
+
var MACHINE_DEPENDENT_DEFAULTS = ["homeDir", "dbPath"];
|
|
16296
17192
|
var DESCRIPTIONS = {
|
|
16297
17193
|
$schema: "\u8FD9\u4EFD\u6587\u4EF6\u7684 JSON Schema \u5730\u5740\u3002\u53EA\u5F71\u54CD\u7F16\u8F91\u5668\u7684\u8865\u5168\u4E0E\u6821\u9A8C\uFF0Cepoch \u672C\u8EAB\u5FFD\u7565\u5B83\uFF08\u4E0D\u7B97\u672A\u77E5\u914D\u7F6E\u9879\uFF09\u3002",
|
|
16298
17194
|
permissions: "\u6743\u9650\u89C4\u5219\u7684\u4E09\u5F20\u5217\u8868\u3002\u4F18\u5148\u7EA7 deny > ask > allow\uFF0C\u4E14\u4E24\u4E2A deny \u90FD\u538B\u8FC7\u5BA1\u6279\u5F39\u7A97\u91CC\u70B9\u8FC7\u7684\u300C\u603B\u662F\u5141\u8BB8\u300D\u3002",
|
|
@@ -16303,7 +17199,112 @@ var DESCRIPTIONS = {
|
|
|
16303
17199
|
maxTurns: "\u5355\u6B21\u4F1A\u8BDD\u6700\u591A\u51E0\u8F6E\uFF08\u4E00\u8F6E = \u4E00\u6B21\u6A21\u578B\u8C03\u7528 + \u5B83\u89E6\u53D1\u7684\u5DE5\u5177\u6267\u884C\uFF09\u30020 \u6216\u6B63\u6574\u6570\uFF0C**0 = \u4E0D\u8BBE\u4E0A\u9650**\uFF08\u7F3A\u7701\uFF09\u3002",
|
|
16304
17200
|
allowManagedPermissionRulesOnly: "\u6253\u5F00\u540E\uFF0C\u5176\u4F59\u5404\u5C42\uFF08\u7528\u6237\u7EA7 / \u9879\u76EE\u7EA7 / \u9879\u76EE\u672C\u5730 / --settings\uFF09\u7684 allow / ask / deny **\u6574\u4EFD\u5FFD\u7565**\uFF0C\u53EA\u6709\u8FD9\u4EFD\u6258\u7BA1\u6587\u4EF6\u91CC\u7684\u89C4\u5219\u7B97\u6570\u3002\u8FD9\u662F\u5168\u6D41\u7A0B\u552F\u4E00\u4E00\u5904\u66FF\u6362\u8BED\u4E49\uFF0C\u4E0D\u662F\u5E76\u96C6\u3002\u9ED8\u8BA4 false\u3002",
|
|
16305
17201
|
allowManagedHooksOnly: "\u6253\u5F00\u540E\uFF0C\u7528\u6237\u7EA7 hook \u4E00\u6761\u90FD\u4E0D\u52A0\u8F7D\uFF08hook \u80FD spawn \u4EFB\u610F\u5B50\u8FDB\u7A0B\uFF09\u3002\u9ED8\u8BA4 false\u3002",
|
|
16306
|
-
disableBypassPermissionsMode: "\u6253\u5F00\u540E\uFF0C`permission: bypass` **\u62D2\u7EDD\u542F\u52A8**\uFF08\u9000\u51FA\u7801 4\uFF09\uFF0C\u8FD0\u884C\u671F\u5207\u5230 bypass \u4E5F\u4F1A\u88AB\u6321\u4E0B\u3002\u9ED8\u8BA4 false\u3002"
|
|
17202
|
+
disableBypassPermissionsMode: "\u6253\u5F00\u540E\uFF0C`permission: bypass` **\u62D2\u7EDD\u542F\u52A8**\uFF08\u9000\u51FA\u7801 4\uFF09\uFF0C\u8FD0\u884C\u671F\u5207\u5230 bypass \u4E5F\u4F1A\u88AB\u6321\u4E0B\u3002\u9ED8\u8BA4 false\u3002",
|
|
17203
|
+
version: "\u914D\u7F6E\u6587\u4EF6\u7684\u683C\u5F0F\u7248\u672C\uFF0C\u7531\u8FC1\u79FB\u6D41\u7A0B\u8BFB\u8D70\uFF08\u4E0D\u8FDB EpochConfig\uFF09\u3002\u4E00\u822C\u4E0D\u7528\u624B\u5199 \u2014\u2014 \u8001\u6587\u4EF6\u6CA1\u6709\u8FD9\u4E00\u884C\u65F6\u6309\u5F53\u524D\u7248\u672C\u5904\u7406\u3002",
|
|
17204
|
+
models: "\u5185\u90E8\u4EFB\u52A1\u4E13\u7528\u7684\u6A21\u578B\u3002\u7F3A\u7701 = \u5168\u90E8\u8D70\u4E3B\u6A21\u578B\u3002",
|
|
17205
|
+
"models.utility": "\u5C0F\u5DE5\u5177\u4EFB\u52A1\uFF08\u751F\u6210\u6807\u9898\u3001\u6458\u8981\u8FD9\u7C7B\uFF09\u7528\u7684\u6A21\u578B\uFF0C\u5199 `@<id>`\uFF08\u300C\u6211\u7684\u6A21\u578B\u300D\u91CC\u7684\u4E00\u6761\uFF09\u3002\u4E0D\u914D = \u7528\u4E3B\u6A21\u578B\u3002",
|
|
17206
|
+
modelEntries: "\u300C\u6211\u7684\u6A21\u578B\u300D\u7684\u6761\u76EE\u6E05\u5355\u3002**\u5199\u5728 config.yaml \u91CC\u4E0D\u751F\u6548** \u2014\u2014 \u771F\u6E90\u662F `models.json`\uFF0C\u8FD9\u4E00\u683C\u8BFB\u5230\u53EA\u4F1A\u62A5\u4E00\u6761 `legacy_ignored`\u3002",
|
|
17207
|
+
shell: "`terminal` \u7528\u54EA\u79CD shell\uFF1A`cmd` / `powershell` / `pwsh`\u3002\u4E0D\u5199 = \u81EA\u52A8\u63A2\u6D4B\uFF08Windows \u4E0A\u4F18\u5148 pwsh\uFF09\u3002",
|
|
17208
|
+
contextLength: "\u6A21\u578B\u7684\u4E0A\u4E0B\u6587\u7A97\u53E3\u5927\u5C0F\uFF08token\uFF09\u3002\u7F3A\u7701 200000\u3002",
|
|
17209
|
+
maxOutputTokens: "\u5355\u6B21\u6A21\u578B\u8BF7\u6C42\u6700\u591A\u751F\u6210\u591A\u5C11 token\u3002\u4E0D\u914D = \u4E0D\u53D1 `max_tokens`\uFF0C\u7528\u5404\u5BB6\u670D\u52A1\u7AEF\u81EA\u5DF1\u7684\u9ED8\u8BA4\u503C\u3002",
|
|
17210
|
+
homeDir: "\u6570\u636E\u76EE\u5F55\u3002\u26A0\uFE0F **\u8BF7\u6539\u7528\u73AF\u5883\u53D8\u91CF `EPOCH_HOME`** \u2014\u2014 \u8FD9\u4E00\u683C\u6709\u4E24\u5957\u89E3\u6790\u771F\u6E90\uFF08`paths.ts` \u53EA\u770B\u73AF\u5883\u53D8\u91CF\uFF0Cruntime \u8BFB `config.homeDir`\uFF09\uFF0C\u5199\u5B83\u53EA\u4F1A\u8BA9\u6570\u636E\u8DD1\u53BB\u65B0\u76EE\u5F55\u800C\u914D\u7F6E\u6587\u4EF6\u7559\u5728\u65E7\u5BB6\u3002",
|
|
17211
|
+
dbPath: "\u4F1A\u8BDD\u5E93\u8DEF\u5F84\uFF08\u7F3A\u7701 `<homeDir>/sessions.db`\uFF09\u3002\u26A0\uFE0F \u540C `homeDir` \u4E00\u65CF\uFF0C\u800C\u4E14\u5207\u5F97\u66F4\u788E\uFF1Aruntime \u7684\u4F1A\u8BDD\u5E93\u8BFB\u5B83\uFF0C\u5B9A\u65F6\u4EFB\u52A1\u90A3\u8FB9\u6309 `homeDir` \u63A8\u3002",
|
|
17212
|
+
permission: "\u65B0\u4F1A\u8BDD\u7684\u9ED8\u8BA4\u6743\u9650\u6863\uFF1A`plan` / `default` / `acceptEdits` / `auto`\u3002\u4E0D\u5199\u65F6\u662F `acceptEdits`\uFF08\u8BF7\u6C42\u6279\u51C6\uFF09\u3002\u8001\u540D\u5B57 `bypass` \u4ECD\u80FD\u8BFB\uFF0C\u4F1A\u9759\u9ED8\u5F53\u4F5C `auto`\u3002\u5DE5\u4F5C\u533A\u4FE1\u4EFB\u90A3\u4E00\u5C42\u4E0D\u6539\u53D8\u8FD9\u4E00\u683C\u3002",
|
|
17213
|
+
logLevel: "\u65E5\u5FD7\u7EA7\u522B\uFF1A`debug` / `info` / `warn` / `error`\u3002",
|
|
17214
|
+
profile: "\u5F53\u524D\u914D\u7F6E\u6863\u540D\u3002\u26A0\uFE0F **\u8FD9\u4E00\u683C\u53EA\u7528\u4E8E\u5C55\u793A** \u2014\u2014 \u771F\u6B63\u51B3\u5B9A\u76EE\u5F55\u7684\u662F\u73AF\u5883\u53D8\u91CF `EPOCH_PROFILE`\uFF0C\u5199\u5728\u8FD9\u91CC\u4E0D\u4F1A\u5207\u6362\u3002",
|
|
17215
|
+
retry: "\u6A21\u578B\u8BF7\u6C42\u7684\u91CD\u8BD5\u7B56\u7565\u3002",
|
|
17216
|
+
"retry.maxRetries": "\u6700\u591A\u91CD\u8BD5\u51E0\u6B21\uFF08\u7F3A\u7701 3\uFF09\u3002",
|
|
17217
|
+
"retry.baseBackoffMs": "\u7B2C\u4E00\u6B21\u91CD\u8BD5\u7B49\u591A\u4E45\uFF08\u6BEB\u79D2\uFF0C\u7F3A\u7701 1000\uFF09\uFF0C\u4E4B\u540E\u6307\u6570\u9000\u907F\u3002",
|
|
17218
|
+
"retry.maxBackoffMs": "\u9000\u907F\u7684\u4E0A\u9650\uFF08\u6BEB\u79D2\uFF0C\u7F3A\u7701 30000\uFF09\u3002",
|
|
17219
|
+
fallback: "\u4E3B\u6A21\u578B\u5931\u8D25\u65F6\u7684\u964D\u7EA7\u76EE\u6807\u3002",
|
|
17220
|
+
"fallback.model": "\u964D\u7EA7\u7528\u7684\u6A21\u578B\uFF0C\u5199 `@<id>`\uFF08\u300C\u6211\u7684\u6A21\u578B\u300D\u91CC\u7684\u4E00\u6761\uFF09\u3002",
|
|
17221
|
+
hooks: "\u65E7\u683C\u5F0F\u7684 hook \u914D\u7F6E\uFF0C\u5DF2\u642C\u53BB `~/.epoch/hooks.json`\u3002\u8FD9\u91CC\u4ECD\u7136\u7167\u5E38\u52A0\u8F7D\uFF08\u5220\u6389\u8FD9\u4E00\u952E\u7B49\u4E8E\u8BA9\u6240\u6709\u4EBA\u7684 hook \u9759\u9ED8\u5931\u6548\uFF09\uFF0C\u53EA\u662F\u542F\u52A8\u65F6\u591A\u4E00\u6761\u8FC1\u79FB\u63D0\u793A\u3002",
|
|
17222
|
+
trust: "\u5DE5\u4F5C\u533A\u4FE1\u4EFB\u95F8\u95E8\u3002\u26A0\uFE0F \u7F3A\u7701\u662F**\u5F00\u7740**\u7684 \u2014\u2014 `enabled: false` \u624D\u662F\u5173\u6389\u3002",
|
|
17223
|
+
"trust.enabled": "`false` = \u5173\u6389\u5DE5\u4F5C\u533A\u4FE1\u4EFB\u6821\u9A8C\u3002**\u4E0D\u5199\u8FD9\u4E2A\u952E = \u4FE1\u4EFB\u95F8\u95E8\u5F00\u7740**\uFF0C\u522B\u7528\u771F\u5047\u503C\u5224\u65AD\u8FD9\u4E00\u683C\u3002",
|
|
17224
|
+
sandbox: "OS \u7EA7\u6C99\u7BB1\u3002",
|
|
17225
|
+
"sandbox.terminal": "`terminal` \u5BB6\u65CF\u7684\u5199\u5165\u6C99\u7BB1\u5F00\u5173\uFF08\u7F3A\u7701 true\uFF09\u3002\u5173\u6389\u4E4B\u540E\u547D\u4EE4\u80FD\u5199\u6574\u4E2A\u6587\u4EF6\u7CFB\u7EDF \u2014\u2014 \u6B63\u5F53\u7406\u7531\u53EA\u6709\u300C\u7F13\u5B58\u76EE\u5F55\u8868\u6CA1\u8986\u76D6\u5230\u3001\u628A\u80FD\u8DD1\u7684\u547D\u4EE4\u6321\u4F4F\u4E86\u300D\u3002",
|
|
17226
|
+
delegate: "`delegate_task` \u6D3E\u51FA\u53BB\u7684\u5B50\u4EFB\u52A1\u3002",
|
|
17227
|
+
"delegate.taskTimeoutSec": "\u4E00\u4E2A\u5B50\u4EFB\u52A1\u6700\u591A\u8DD1\u591A\u4E45\uFF08\u79D2\uFF0C\u7F3A\u7701 900\uFF09\u3002`0` = \u4E0D\u9650\u65F6\u3002\u649E\u4E0A\u53BB\u4E4B\u540E\u5B50 agent \u5F53\u573A\u88AB\u6390\uFF0C\u534A\u622A\u7ED3\u8BBA\u4E0D\u4FDD\u7559\u3002",
|
|
17228
|
+
tools: "\u6309\u9700\u53D1\u73B0\u5DE5\u5177\u3002",
|
|
17229
|
+
"tools.deferMcp": "MCP \u5DE5\u5177\u4E0D\u8FDB\u521D\u59CB\u5DE5\u5177\u5217\u8868\uFF0C\u6A21\u578B\u8981\u7528 `tool_search` \u624D\u627E\u5F97\u56DE\u6765\uFF08\u7F3A\u7701 false\uFF09\u3002\u6253\u5F00\u662F\u4E00\u6B21\u9759\u9ED8\u7684\u80FD\u529B\u7F29\u51CF\u3002",
|
|
17230
|
+
"tools.mode": "code mode \u4E09\u6863\uFF1A`tools`\uFF08\u6CA1\u6709 `run_code`\uFF09/ `both`\uFF08\u5168\u90E8\u5DE5\u5177 + `run_code`\uFF09/ `code`\uFF08\u80FD\u7A0B\u5E8F\u8C03\u7684\u5207\u8D70\uFF09\u3002\u7F3A\u7701 `tools`\u3002",
|
|
17231
|
+
skills: "\u6280\u80FD\u7D22\u5F15\u3002",
|
|
17232
|
+
"skills.maxIndexed": "\u7D22\u5F15\u91CC\u6700\u591A\u5217\u51E0\u6761\u6280\u80FD\u3002\u4E0D\u914D = \u4E0D\u5C01\u9876\uFF08\u88AB\u622A\u6389\u7684\u6280\u80FD\u6A21\u578B\u6C38\u8FDC\u4E0D\u77E5\u9053\u5B83\u5B58\u5728\uFF0C\u6240\u4EE5\u9ED8\u8BA4\u4E0D\u5C01\uFF09\u3002",
|
|
17233
|
+
compression: "\u4E0A\u4E0B\u6587\u5FEB\u6EE1\u65F6\u81EA\u52A8\u538B\u7F29\u3002",
|
|
17234
|
+
"compression.enabled": "\u5F00\u5173\uFF08\u7F3A\u7701 true\uFF09\u3002",
|
|
17235
|
+
"compression.threshold": "\u63D0\u793A\u8BCD\u5360\u5230\u4E0A\u4E0B\u6587\u7A97\u53E3\u7684\u51E0\u6210\u65F6\u5F00\u59CB\u538B\uFF0C\u53D6\u503C (0, 1]\uFF0C\u7F3A\u7701 0.8\u30020 \u7B49\u4E8E\u6BCF\u8F6E\u90FD\u538B\uFF08\u4E00\u53F0\u70E7\u94B1\u673A\u5668\uFF09\uFF0C\u6240\u4EE5\u4E0D\u542B 0\u3002",
|
|
17236
|
+
limits: "\u5355\u6B21\u8BF7\u6C42\u7684\u4F53\u79EF\u4E0A\u9650\uFF08**\u5B57\u8282**\u8FD9\u6761\u7EBF\uFF0C\u548C\u4E0A\u9762 compression \u7684 token \u90A3\u6761\u662F\u4E24\u4E2A\u91CF\u7EB2\uFF09\u3002",
|
|
17237
|
+
"limits.maxRequestImageBytes": "\u5355\u6B21\u8BF7\u6C42\u91CC\u6240\u6709\u56FE\u7247 base64 \u7684\u5408\u8BA1\u4E0A\u9650\uFF08\u5B57\u8282\uFF09\u3002\u8D85\u4E86\u5C31\u81EA\u52A8\u628A\u6700\u8001\u7684\u51E0\u5F20\u56FE\u4E0B\u653E\u6210\u5360\u4F4D\u3001\u4F1A\u8BDD\u7EE7\u7EED\u3002\u4E0D\u914D = 8 MiB\uFF08\u8FD9\u4E2A\u6570\u6CA1\u6709\u6743\u5A01\u51FA\u5904\uFF0C\u649E\u4E00\u6B21\u4E4B\u540E\u4F1A\u6309\u5B9E\u6D4B\u6536\u7D27\uFF09\u3002",
|
|
17238
|
+
memory: "\u957F\u671F\u8BB0\u5FC6\u7684\u914D\u989D\u3002",
|
|
17239
|
+
"memory.memoryCharLimit": "\u8BB0\u5FC6\u6B63\u6587\u7684\u5B58\u50A8\u914D\u989D\uFF08\u5B57\u7B26\uFF0C\u7F3A\u7701 20000\uFF09\u3002**\u8FD9\u662F\u5B58\u50A8\uFF0C\u4E0D\u662F\u6BCF\u8F6E\u5F00\u9500\u3002**",
|
|
17240
|
+
"memory.userCharLimit": "\u7528\u6237\u753B\u50CF\u7684\u5B58\u50A8\u914D\u989D\uFF08\u5B57\u7B26\uFF0C\u7F3A\u7701 6000\uFF09\u3002\u540C\u6837\u662F\u5B58\u50A8\u3002",
|
|
17241
|
+
"memory.indexCharLimit": "\u8BB0\u5FC6\u7D22\u5F15\u5757\u7684\u914D\u989D\uFF08\u5B57\u7B26\uFF0C\u7F3A\u7701 4000\uFF09\u3002\u4E09\u4E2A\u91CC\u552F\u4E00\u6309\u8F6E\u8BA1\u8D39\u7684 \u2014\u2014 \u8FD9\u4E00\u5757\u6BCF\u8F6E\u90FD\u5728 system prompt \u91CC\u3002",
|
|
17242
|
+
artifacts: "artifact \u7684\u4FDD\u7559\u7B56\u7565\u3002",
|
|
17243
|
+
"artifacts.maxAgeDays": "\u591A\u5C11\u5929\u6CA1\u52A8\u8FC7\u7684 artifact \u5220\u6389\uFF08\u7F3A\u7701 7\uFF0C\u4E0A\u9650 3650\uFF09\u3002",
|
|
17244
|
+
"artifacts.maxTotalBytes": "artifact \u603B\u91CF\u4E0A\u9650\uFF08\u5B57\u8282\uFF0C\u7F3A\u7701 512MB\uFF09\u3002\u8D85\u4E86\u6309\u5E74\u9F84\u4ECE\u65E7\u5230\u65B0\u5220\uFF0C\u5F53\u524D\u4F1A\u8BDD\u7684\u76EE\u5F55\u6C38\u4E0D\u5220\u3002",
|
|
17245
|
+
sessions: "\u4F1A\u8BDD\u5E93\u7684\u4FDD\u7559\u671F\u6E05\u7406\u3002",
|
|
17246
|
+
"sessions.autoPrune": "\u6BCF\u6B21\u542F\u52A8\u65F6\u81EA\u52A8\u6E05\u7406\u4E00\u6B21\uFF0C\u81F3\u591A\u4E00\u5929\u4E00\u6B21\uFF08\u7F3A\u7701 false\uFF09\u3002\u5173\u7740\u65F6\u624B\u52A8\u7684 `epoch sessions prune` \u7167\u5E38\u80FD\u7528\u3002",
|
|
17247
|
+
"sessions.retentionDays": "\u591A\u5C11\u5929\u6CA1\u52A8\u8FC7\u7B97\u65E7\uFF08\u7F3A\u7701 90\uFF0C\u4E0A\u9650 3650\uFF09\u3002",
|
|
17248
|
+
"sessions.vacuumAfterPrune": "\u6E05\u5B8C\u4E4B\u540E `VACUUM` \u56DE\u6536\u78C1\u76D8\uFF08\u7F3A\u7701 true\uFF09\u3002\u8FD8\u8981\u8FC7\u300C\u771F\u5220\u6389\u4E86\u4E1C\u897F\u300D\u548C\u300C\u7A7A\u9875\u8D85\u8FC7 25%\u300D\u4E24\u9053\u624D\u771F\u8DD1\u3002",
|
|
17249
|
+
automation: "\u5B9A\u65F6\u4EFB\u52A1\u3002",
|
|
17250
|
+
"automation.keepRuns": "\u4E00\u4E2A\u4EFB\u52A1\u7559\u6700\u8FD1\u591A\u5C11\u6B21\u8FD0\u884C\u7684\u5F55\u50CF\uFF08\u7F3A\u7701 200\uFF0C\u4E0A\u9650 10000\uFF09\u3002",
|
|
17251
|
+
"automation.maxRecordingMb": "\u5355\u4E2A\u4EFB\u52A1\u7684\u5F55\u50CF\u603B\u91CF\u4E0A\u9650\uFF08MB\uFF0C\u7F3A\u7701 64\uFF09\u3002\u548C `keepRuns` \u5148\u649E\u54EA\u6761\u7B97\u54EA\u6761\u3002",
|
|
17252
|
+
budget: "\u82B1\u8D39\u4E0E token \u7684\u95F8\u95E8\u3002**\u7F3A\u7701\u65E0\u4E0A\u9650**\uFF08\u7B49\u4E8E\u4E0D\u542F\u7528\uFF09\u3002",
|
|
17253
|
+
"budget.maxCostUsd": "\u4E00\u6B21\u4F1A\u8BDD\u6700\u591A\u82B1\u591A\u5C11\u7F8E\u5143\u3002\u4E0D\u914D = \u4E0D\u8BBE\u4E0A\u9650\u3002",
|
|
17254
|
+
"budget.maxTokens": "\u4E00\u6B21\u4F1A\u8BDD\u6700\u591A\u7528\u591A\u5C11 token\u3002\u4E0D\u914D = \u4E0D\u8BBE\u4E0A\u9650\u3002",
|
|
17255
|
+
"budget.warnAtPercent": "\u82B1\u5230\u4E0A\u9650\u7684\u767E\u5206\u4E4B\u51E0\u65F6\u5F00\u59CB\u63D0\u9192\uFF080~100\uFF09\u3002",
|
|
17256
|
+
"budget.onUnknownPricing": "\u9047\u5230\u4EF7\u683C\u672A\u77E5\u7684\u6A21\u578B\u600E\u4E48\u529E\uFF1A`block`\uFF08\u62D2\u7EDD\u8C03\u7528\uFF09/ `warn`\uFF08\u7167\u8DD1\uFF0C\u53EA\u8BB0\u4E00\u6761\uFF09\u3002",
|
|
17257
|
+
compliance: "\u5185\u5BB9\u5408\u89C4\u68C0\u67E5\u3002",
|
|
17258
|
+
"compliance.enabled": "\u603B\u5F00\u5173\u3002\u7F3A\u7701 = \u5F00\uFF08\u8FD9\u662F\u4EA7\u54C1\u8981\u6C42\uFF0C\u4E0D\u662F\u53EF\u9009\u589E\u5F3A\uFF09\u3002",
|
|
17259
|
+
"compliance.scope": "\u68C0\u67E5\u54EA\u51E0\u6761\u8DEF\u3002\u4E09\u683C\u5404\u81EA\u7684\u7F3A\u7701\u4E0D\u540C\uFF0C\u89C1\u4E0B\u9762\u4E09\u6761\u3002",
|
|
17260
|
+
"compliance.scope.output": "\u6A21\u578B\u8F93\u51FA\u3002\u7F3A\u7701\u5173 \u2014\u2014 \u8BEF\u4F24\u548C\u6D41\u5F0F\u5EF6\u8FDF\u7684\u5927\u5934\u3002",
|
|
17261
|
+
"compliance.scope.input": "\u7528\u6237\u8F93\u5165\u3002\u7F3A\u7701\u5F00\uFF0C\u8FD9\u4E00\u4FA7\u662F\u5408\u89C4\u7684\u4E3B\u6218\u573A\u3002",
|
|
17262
|
+
"compliance.scope.toolArgs": "\u6A21\u578B\u751F\u6210\u7684\u5DE5\u5177\u5165\u53C2\u3002\u7F3A\u7701\u5173 \u2014\u2014 \u62E6\u4E00\u6B21 `file_write` \u7684\u8BEF\u4F24\u4EE3\u4EF7\u592A\u5927\u3002",
|
|
17263
|
+
"compliance.skipCodeBlocks": "\u56F4\u680F\u4EE3\u7801\u5757\u548C\u884C\u5185 code \u4E0D\u5224\uFF08\u7F3A\u7701\u5F00\uFF09\u3002",
|
|
17264
|
+
"compliance.maxHoldChars": "\u6D41\u5F0F\u68C0\u67E5\u7684\u7F13\u51B2\u533A\u4E0A\u9650\uFF08\u5B57\u7B26\uFF0C\u4E0A\u9650 10000\uFF09\u3002\u8D85\u8FC7\u5C31\u5F3A\u5236\u5224\u4E00\u6B21\uFF0C\u522B\u4E3A\u4E86\u7B49\u4E00\u4E2A\u53E5\u53F7\u628A\u6574\u6BB5\u618B\u4F4F\u3002",
|
|
17265
|
+
"compliance.actions": "\u7C7B\u522B \u2192 \u52A8\u4F5C\u3002\u6CA1\u5217\u5230\u7684\u7C7B\u522B\u8D70\u9ED8\u8BA4\u6863 \u2014\u2014 \u53EA\u5199\u4E86\u4E00\u884C\u4E0D\u4F1A\u628A\u5176\u4F59\u7C7B\u522B\u4E00\u8D77\u53D8\u6210\u7A7A\u3002",
|
|
17266
|
+
headless: "`epoch --print` \u8FD9\u7C7B\u975E\u4EA4\u4E92\u6A21\u5F0F\u7684\u5DE5\u5177\u767D\u540D\u5355\u3002\u7F3A\u7701 = \u8D70\u5404\u81EA\u7684\u5185\u7F6E\u9ED8\u8BA4\u6E05\u5355\u3002",
|
|
17267
|
+
"headless.allowTools": "\u5141\u8BB8\u5728\u975E\u4EA4\u4E92\u6A21\u5F0F\u4E0B\u4F7F\u7528\u7684\u5DE5\u5177\u540D\u6E05\u5355\u3002",
|
|
17268
|
+
"headless.allowOperations": "\u5141\u8BB8\u5728\u975E\u4EA4\u4E92\u6A21\u5F0F\u4E0B\u4F7F\u7528\u7684\u64CD\u4F5C\u7C7B\u522B\u6E05\u5355\u3002",
|
|
17269
|
+
telemetry: "\u8FD0\u884C\u9065\u6D4B\u3002\u7F3A\u7701 = \u4E0D\u542F\u7528\u3002",
|
|
17270
|
+
"telemetry.enabled": "\u5F00\u5173\u3002",
|
|
17271
|
+
"telemetry.target": "\u8F93\u51FA\u5230\u54EA\u513F\uFF1A`file` / `console` / `otlp`\u3002",
|
|
17272
|
+
"telemetry.outfile": "`target: file` \u65F6\u5199\u5230\u54EA\u4E2A\u6587\u4EF6\u3002",
|
|
17273
|
+
"telemetry.endpoint": "`target: otlp` \u65F6\u7684\u4E0A\u62A5\u5730\u5740\u3002",
|
|
17274
|
+
search: "web \u641C\u7D22\u3002\u7F3A\u7701 = \u4E0D\u542F\u7528\uFF08`web_search` \u5DE5\u5177\u6839\u672C\u4E0D\u4F1A\u6CE8\u518C\uFF09\u3002",
|
|
17275
|
+
"search.provider": "\u7528\u54EA\u5BB6\uFF1A`native` / `tavily` / `brave` / `searxng` / `keyless`\u3002\u4E0D\u914D = \u6309\u624B\u91CC\u6709\u54EA\u4E9B\u51ED\u636E\u81EA\u52A8\u6311\u3002",
|
|
17276
|
+
"search.baseUrl": "`searxng` \u8FD9\u4E00\u7C7B\u81EA\u5EFA\u670D\u52A1\u7684\u57FA\u7840\u5730\u5740\u3002",
|
|
17277
|
+
"search.maxResults": "\u4E00\u6B21\u6700\u591A\u8FD4\u56DE\u51E0\u6761\uFF08\u4E0A\u9650 20\uFF09\u3002",
|
|
17278
|
+
sessionSearch: "\u8DE8\u4F1A\u8BDD\u68C0\u7D22\uFF08`session_search`\uFF09\u3002",
|
|
17279
|
+
"sessionSearch.allWorkspaces": "\u5141\u8BB8\u68C0\u7D22\u5176\u4ED6\u5DE5\u4F5C\u533A\u7684\u4F1A\u8BDD\uFF08\u7F3A\u7701 false = \u53EA\u641C\u5F53\u524D\u5DE5\u4F5C\u533A\uFF09\u3002\u26A0\uFE0F \u653E\u5F00\u5B83\u7B49\u4E8E\u8BA9\u540C\u4E00\u4E2A agent \u8BFB\u5230\u4F60\u522B\u7684\u9879\u76EE\u7684\u5BF9\u8BDD\u3002",
|
|
17280
|
+
statusLine: "\u81EA\u5B9A\u4E49\u72B6\u6001\u680F\u3002\u7F3A\u7701 = \u4E0D\u663E\u793A\u3002",
|
|
17281
|
+
"statusLine.command": "\u53D6\u72B6\u6001\u7684\u90A3\u6761\u547D\u4EE4\u3002\u5B83\u6BCF\u6B21\u5237\u65B0\u90FD\u4F1A spawn \u4E00\u4E2A shell\uFF0C\u522B\u5199\u6210\u5E38\u9A7B\u8FDB\u7A0B\u3002",
|
|
17282
|
+
"statusLine.intervalMs": "\u5237\u65B0\u95F4\u9694\uFF08\u6BEB\u79D2\uFF0C500~300000\uFF09\u3002\u4F4E\u4E8E 500 \u53EA\u662F\u5728\u70E7\u5B50\u8FDB\u7A0B\u3002",
|
|
17283
|
+
display: "\u754C\u9762\u4E0A\u7684\u663E\u793A\u504F\u597D\u3002",
|
|
17284
|
+
"display.language": "\u754C\u9762\u8BED\u8A00\uFF1A`zh` / `en`\u3002\u4E0D\u914D = \u6309\u7CFB\u7EDF locale \u63A2\u6D4B\uFF08\u522B\u9ED8\u8BA4\u5199\u6210 zh\uFF0C\u90A3\u4F1A\u628A\u975E\u4E2D\u6587\u7528\u6237\u63A8\u8FDB\u4E2D\u6587\u754C\u9762\uFF09\u3002",
|
|
17285
|
+
"display.currency": "\u5C4F\u5E55\u4E0A\u90A3\u4E9B\u91D1\u989D\u5370\u6210\u4EC0\u4E48\u5E01\u79CD\u3002**\u53EA\u7BA1\u5370\uFF0C\u4E0D\u6539\u53D8\u4EFB\u4F55\u8BA1\u7B97** \u2014\u2014 \u5355\u4EF7\u8868\u3001\u95F8\u95E8\u6BD4\u8F83\u3001\u843D\u76D8\u7684\u6BCF\u4E00\u5217\u3001\u4F60\u8F93\u8FDB\u6765\u7684\u6BCF\u4E00\u683C\u5168\u662F\u7F8E\u5143\u3002",
|
|
17286
|
+
"display.currency.code": "\u5E01\u79CD\u4EE3\u7801\uFF1A`USD` / `CNY`\u3002",
|
|
17287
|
+
"display.currency.rate": "1 \u7F8E\u5143\u7B49\u4E8E\u591A\u5C11\u8FD9\u4E2A\u5E01\u79CD\u3002**\u6CA1\u6709\u9ED8\u8BA4\u503C\uFF0C\u4E5F\u4E0D\u8054\u7F51\u6293** \u2014\u2014 \u6309 1 \u7B97\u7B49\u4E8E\u628A\u7F8E\u5143\u6570\u5B57\u6362\u4E0A\u4EBA\u6C11\u5E01\u7B26\u53F7\uFF0C\u6BD4\u4E0D\u6362\u66F4\u7CDF\u3002",
|
|
17288
|
+
brand: "\u5BBF\u4E3B\u54C1\u724C\u8BCD\u6807\uFF08\u4FA7\u680F\u90A3\u4E00\u683C\uFF09\u3002\u7F3A\u7701 = \u4EC0\u4E48\u90FD\u4E0D\u663E\u793A\uFF0C\u4E0D\u662F\u56DE\u843D\u5230 `epoch`\u3002",
|
|
17289
|
+
brandWhenSidebarCollapsed: "\u4FA7\u680F\u6536\u8D77\u65F6\u54C1\u724C\u90A3\u4E00\u683C\u7684\u53BB\u7559\uFF1A`hide` / `show`\uFF08\u7F3A\u7701 hide\uFF09\u3002",
|
|
17290
|
+
brandMenuId: "\u70B9\u54C1\u724C\u90A3\u4E00\u683C\u56DE\u7ED9\u5BBF\u4E3B\u7684 `id`\u3002\u6CA1\u914D `brand` \u65F6\u5199\u4E86\u4E5F\u4E0D\u7B97\u9519\uFF0C\u53EA\u662F\u4E0D\u8D77\u4F5C\u7528\u3002",
|
|
17291
|
+
sidebarMenu: "\u5BBF\u4E3B\u81EA\u5B9A\u4E49\u7684\u4FA7\u680F\u5E95\u90E8\u5E38\u9A7B\u6309\u94AE\u3002\u7F3A\u7701 = \u4E00\u884C\u90FD\u4E0D\u591A\u3002`id` \u4E0D\u8BB8\u91CD\u590D\uFF0C`primary: true` \u6700\u591A\u4E00\u9879\u3002",
|
|
17292
|
+
userMenuHost: "\u300C\u7528\u6237\u300D\u90A3\u4E00\u683C\u6574\u5F20\u83DC\u5355\u5F52\u5BBF\u4E3B\u81EA\u5DF1\u753B\u3002\u7F3A\u7701 false = \u7167\u65E7\u6211\u4EEC\u753B\u3002",
|
|
17293
|
+
sidebarHeadMenu: "\u5BBF\u4E3B\u81EA\u5B9A\u4E49\u7684\u4FA7\u680F\u5934\u90A3\u51E0\u679A\u56FE\u6807\u3002\u7F3A\u7701 = \u4E00\u679A\u90FD\u4E0D\u591A\uFF1B`id` \u4E0D\u8BB8\u91CD\u590D\uFF08\u90A3\u4E00\u6392\u4E0D\u5206\u91CC\u5916\uFF0C\u5199 `primary` \u4F1A\u88AB\u5265\u6389\uFF09\u3002",
|
|
17294
|
+
topbarMenu: "\u5BBF\u4E3B\u81EA\u5B9A\u4E49\u7684\u9876\u680F\u53F3\u4E0A\u56FE\u6807\u3002\u7F3A\u7701 = \u4E00\u679A\u90FD\u4E0D\u591A\uFF1B\u754C\u9762\u4E0A\u53EA\u628A\u7B2C\u4E00\u9879\u9732\u5728\u5916\u9762\uFF0C\u5176\u4F59\u6536\u8FDB\u300C\u22EF\u300D\u3002",
|
|
17295
|
+
blankCards: "\u5BBF\u4E3B\u81EA\u5B9A\u4E49\u7684\u5F00\u573A\u5361\u7247\u3002\u7F3A\u7701 = \u65B0\u4F1A\u8BDD\u7A7A\u5C4F\u4E0A\u4E00\u5F20\u90FD\u6CA1\u6709\u3002",
|
|
17296
|
+
blankGreeting: "\u5BBF\u4E3B\u81EA\u5B9A\u4E49\u7684\u90A3\u53E5\u5F00\u573A\u62DB\u547C\u3002\u7F3A\u7701 = \u7528\u6211\u4EEC\u90A3\u53E5\uFF08\u548C\u4E0A\u9762\u51E0\u4E2A\u5BBF\u4E3B\u952E\u7684\u9ED8\u8BA4\u6863\u76F8\u53CD\uFF09\u3002",
|
|
17297
|
+
"blankGreeting.eyebrow": "\u62DB\u547C\u4E0A\u65B9\u90A3\u884C\u5C0F\u5B57\uFF0C\u6309\u8BED\u8A00\u7ED9\uFF08`zh` / `en`\uFF09\uFF0C\u81F3\u5C11\u7ED9\u4E00\u79CD\u3002",
|
|
17298
|
+
"blankGreeting.title": "\u62DB\u547C\u7684\u6807\u9898\uFF0C\u6309\u8BED\u8A00\u7ED9\uFF08`zh` / `en`\uFF09\u3002",
|
|
17299
|
+
"blankGreeting.subtitle": "\u62DB\u547C\u7684\u526F\u6807\u9898\uFF0C\u6309\u8BED\u8A00\u7ED9\uFF08`zh` / `en`\uFF09\u3002",
|
|
17300
|
+
"blankGreeting.hidden": "`true` = \u4E0D\u663E\u793A\u90A3\u53E5\u62DB\u547C\uFF08\u6587\u6848\u53EF\u4EE5\u7559\u7740\uFF0C\u4E0D\u4F1A\u56E0\u4E3A\u85CF\u8D77\u6765\u5C31\u903C\u4EBA\u5220\u6389\uFF09\u3002",
|
|
17301
|
+
scheduleRemoveConfirm: "\u5220\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\u65F6\u90A3\u53E5\u786E\u8BA4\uFF0C\u6574\u53E5\u5F52\u4F60\uFF08\u6309\u8BED\u8A00\u7ED9 `zh` / `en`\uFF0C`{name}` \u4F1A\u6362\u6210\u4EFB\u52A1\u540D\uFF09\u3002\u7F3A\u7701 = \u6211\u4EEC\u90A3\u53E5\u3002\u26A0\uFE0F \u8FDE\u540C\u300C\u8BB0\u5F55\u548C\u5F55\u50CF\u627E\u4E0D\u56DE\u6765\u300D\u90A3\u534A\u53E5\u4E5F\u4E00\u8D77\u5F52\u4F60\u3002",
|
|
17302
|
+
user: "\u4FA7\u680F\u6700\u4E0B\u9762\u90A3\u4E00\u884C\u300C\u7528\u6237\u300D\u7684\u540D\u5B57\u548C\u5934\u50CF\u3002\u7F3A\u7701 = \u300C\u7528\u6237\u300D+ \u4E00\u679A `user-round`\uFF0C\u90A3\u4E00\u884C\u6C38\u8FDC\u5728\u3002",
|
|
17303
|
+
"user.label": "\u90A3\u4E00\u884C\u663E\u793A\u7684\u540D\u5B57\u3002\u5FC5\u586B \u2014\u2014 \u53EA\u7ED9\u56FE\u6807\u4E0D\u5199\u5B83\u6CA1\u6CD5\u56DE\u7B54\u300C\u8C01\u5728\u7528\u8FD9\u4E2A agent\u300D\u3002",
|
|
17304
|
+
"user.icon": "\u56FE\u6807\u540D\u3002\u53EA\u6821\u9A8C\u975E\u7A7A\u5B57\u7B26\u4E32\uFF0C\u8BA4\u4E0D\u51FA\u6765\u7684\u843D\u4E00\u679A\u515C\u5E95\u7684\u3002",
|
|
17305
|
+
"user.avatar": "\u5934\u50CF\uFF1A`data:image/\u2026` \u6216 `https://\u2026`\u3002\u8D85\u5927\u7684\u56FE\u5F53\u6CA1\u7ED9\u3001\u753B\u56FE\u6807\uFF0C\u4E0D\u4F1A\u5224\u6210\u914D\u7F6E\u9519\u8BEF\u3002",
|
|
17306
|
+
settingsHidden: "\u8BBE\u7F6E\u9875\u91CC\u4E0D\u753B\u54EA\u51E0\u4E2A\u5206\u533A\u3002\u7F3A\u7701 = \u5341\u4E2A\u5168\u753B\u3002\u62FC\u9519\u7684 id \u53EA\u4EA7\u4E00\u6761\u8B66\u544A\uFF0C\u4E0D\u4F1A\u8BA9\u6574\u4EFD\u914D\u7F6E\u5931\u6548\u3002",
|
|
17307
|
+
settingsPanes: "\u5BBF\u4E3B\u81EA\u5DF1\u7684\u8BBE\u7F6E\u5206\u533A\uFF08\u4F1A\u51FA\u73B0\u5728\u8BBE\u7F6E\u9875\u91CC\uFF09\u3002`id` \u4E0D\u8BB8\u548C\u5185\u7F6E\u5341\u4E2A\u649E\u540D\uFF1B`url` \u53EA\u6536 http(s) \u2014\u2014 \u5B83\u662F\u4E00\u6761\u6267\u884C\u5165\u53E3\u3002"
|
|
16307
17308
|
};
|
|
16308
17309
|
function buildSchemaExports() {
|
|
16309
17310
|
const used = /* @__PURE__ */ new Set();
|
|
@@ -16329,6 +17330,24 @@ function buildSchemaExports() {
|
|
|
16329
17330
|
},
|
|
16330
17331
|
used
|
|
16331
17332
|
)
|
|
17333
|
+
},
|
|
17334
|
+
{
|
|
17335
|
+
file: "config.schema.json",
|
|
17336
|
+
document: document(
|
|
17337
|
+
EpochConfigSchema,
|
|
17338
|
+
{
|
|
17339
|
+
title: "epoch \u7528\u6237\u7EA7\u914D\u7F6E\uFF08config.yaml\uFF09",
|
|
17340
|
+
description: "\u7528\u6237\u7EA7\u4E3B\u914D\u7F6E `~/.epoch/config.yaml`\uFF08\u591A profile \u65F6\u5728 `~/.epoch/profiles/<\u540D\u5B57>/`\uFF09\u3002\u4F18\u5148\u7EA7\u89C1 docs/SETTINGS.md \u90A3\u5F20\u5C42\u8868\uFF1A\u73AF\u5883\u53D8\u91CF\u538B\u8FC7\u8FD9\u4E00\u4EFD\uFF0C\u8FD9\u4E00\u4EFD\u538B\u8FC7\u5185\u7F6E\u9ED8\u8BA4\u503C\uFF1B\u9879\u76EE\u7EA7 `settings.json` \u53EA\u8BA4\u5F97\u5176\u4E2D\u4E09\u4E2A\u952E\u3002",
|
|
17341
|
+
io: "input",
|
|
17342
|
+
extra: {
|
|
17343
|
+
version: {
|
|
17344
|
+
type: "integer",
|
|
17345
|
+
description: `\u914D\u7F6E\u6587\u4EF6\u7684\u683C\u5F0F\u7248\u672C\uFF0C\u7531\u8FC1\u79FB\u6D41\u7A0B\u8BFB\u8D70\uFF08\u5F53\u524D ${CURRENT_CONFIG_VERSION}\uFF09\u3002\u4E00\u822C\u4E0D\u7528\u624B\u5199 \u2014\u2014 \u8001\u6587\u4EF6\u6CA1\u6709\u8FD9\u4E00\u884C\u65F6\u6309\u5F53\u524D\u7248\u672C\u5904\u7406\u3002`
|
|
17346
|
+
}
|
|
17347
|
+
}
|
|
17348
|
+
},
|
|
17349
|
+
used
|
|
17350
|
+
)
|
|
16332
17351
|
}
|
|
16333
17352
|
];
|
|
16334
17353
|
const stale = Object.keys(DESCRIPTIONS).filter((key) => !used.has(key));
|
|
@@ -16339,13 +17358,22 @@ function buildSchemaExports() {
|
|
|
16339
17358
|
}
|
|
16340
17359
|
return exports;
|
|
16341
17360
|
}
|
|
17361
|
+
var EXPLICIT_ENUMS = {
|
|
17362
|
+
permission: PERMISSION_LEVELS
|
|
17363
|
+
};
|
|
16342
17364
|
function document(schema, meta, used) {
|
|
16343
|
-
const generated = z.toJSONSchema(schema);
|
|
17365
|
+
const generated = meta.io ? z.toJSONSchema(schema, { io: meta.io }) : z.toJSONSchema(schema);
|
|
16344
17366
|
const dialect = generated.$schema;
|
|
16345
17367
|
const properties = {
|
|
16346
17368
|
$schema: { type: "string" },
|
|
17369
|
+
...meta.extra,
|
|
16347
17370
|
...generated.properties
|
|
16348
17371
|
};
|
|
17372
|
+
for (const [key, values] of Object.entries(EXPLICIT_ENUMS)) {
|
|
17373
|
+
const node = properties[key];
|
|
17374
|
+
if (node === void 0 || node.type !== "string") continue;
|
|
17375
|
+
properties[key] = { ...node, enum: [...values] };
|
|
17376
|
+
}
|
|
16349
17377
|
const doc = {
|
|
16350
17378
|
$schema: dialect,
|
|
16351
17379
|
title: meta.title,
|
|
@@ -16369,10 +17397,138 @@ function annotate(node, path, used) {
|
|
|
16369
17397
|
);
|
|
16370
17398
|
}
|
|
16371
17399
|
child.description = text;
|
|
17400
|
+
if (MACHINE_DEPENDENT_DEFAULTS.includes(full)) delete child.default;
|
|
16372
17401
|
used.add(full);
|
|
16373
17402
|
annotate(child, full, used);
|
|
16374
17403
|
}
|
|
16375
17404
|
}
|
|
17405
|
+
var BLOCKED = /* @__PURE__ */ new Set(["homeDir", "dbPath", "profile"]);
|
|
17406
|
+
var cached;
|
|
17407
|
+
function configKeyTable() {
|
|
17408
|
+
cached ??= buildTable();
|
|
17409
|
+
return cached;
|
|
17410
|
+
}
|
|
17411
|
+
function configKeyByPath(path) {
|
|
17412
|
+
return configKeyTable().find((entry) => entry.path === path);
|
|
17413
|
+
}
|
|
17414
|
+
function writableConfigKeys() {
|
|
17415
|
+
return configKeyTable().filter((entry) => entry.write === "scalar");
|
|
17416
|
+
}
|
|
17417
|
+
function buildTable() {
|
|
17418
|
+
const tree = z.toJSONSchema(EpochConfigSchema, { io: "input" });
|
|
17419
|
+
const top = tree.properties;
|
|
17420
|
+
const permission2 = top?.["permission"];
|
|
17421
|
+
if (permission2 !== void 0) permission2.enum = [...PERMISSION_LEVELS];
|
|
17422
|
+
const out = [];
|
|
17423
|
+
collect3(tree, "", 0, out);
|
|
17424
|
+
return out;
|
|
17425
|
+
}
|
|
17426
|
+
function collect3(node, path, depth, out) {
|
|
17427
|
+
const properties = node.properties;
|
|
17428
|
+
if (properties) {
|
|
17429
|
+
for (const [key, child] of Object.entries(properties)) {
|
|
17430
|
+
collect3(child, path ? `${path}.${key}` : key, depth + 1, out);
|
|
17431
|
+
}
|
|
17432
|
+
return;
|
|
17433
|
+
}
|
|
17434
|
+
const kind = scalarKindOf(node.type);
|
|
17435
|
+
const entry = baseEntry(node, path, depth, kind);
|
|
17436
|
+
out.push(entry);
|
|
17437
|
+
}
|
|
17438
|
+
function scalarKindOf(type) {
|
|
17439
|
+
const kinds = Array.isArray(type) ? type : [type];
|
|
17440
|
+
for (const kind of kinds) {
|
|
17441
|
+
if (kind === "string" || kind === "integer" || kind === "number" || kind === "boolean") {
|
|
17442
|
+
return kind;
|
|
17443
|
+
}
|
|
17444
|
+
}
|
|
17445
|
+
return void 0;
|
|
17446
|
+
}
|
|
17447
|
+
function baseEntry(node, path, depth, kind) {
|
|
17448
|
+
const dot = depth === 2 ? path.indexOf(".") : -1;
|
|
17449
|
+
const entry = {
|
|
17450
|
+
path,
|
|
17451
|
+
...dot < 0 ? {} : { section: path.slice(0, dot), field: path.slice(dot + 1) },
|
|
17452
|
+
kind: kind ?? "string",
|
|
17453
|
+
write: "manual",
|
|
17454
|
+
...numericBounds(node),
|
|
17455
|
+
...node.minLength === void 0 ? {} : { minLength: node.minLength },
|
|
17456
|
+
...Array.isArray(node.enum) ? {
|
|
17457
|
+
choices: node.enum.filter((v) => typeof v === "string")
|
|
17458
|
+
} : {},
|
|
17459
|
+
...isSettingValue(node.default) ? { builtin: node.default } : {}
|
|
17460
|
+
};
|
|
17461
|
+
if (BLOCKED.has(path)) return { ...entry, write: "blocked", reason: "position" };
|
|
17462
|
+
if (kind === void 0) return { ...entry, reason: "structured" };
|
|
17463
|
+
if (depth > 2) return { ...entry, reason: "nested" };
|
|
17464
|
+
return { ...entry, write: "scalar" };
|
|
17465
|
+
}
|
|
17466
|
+
function numericBounds(node) {
|
|
17467
|
+
return {
|
|
17468
|
+
...typeof node.minimum === "number" ? { minimum: node.minimum } : {},
|
|
17469
|
+
...typeof node.exclusiveMinimum === "number" ? { exclusiveMinimum: node.exclusiveMinimum } : {},
|
|
17470
|
+
...typeof node.maximum === "number" ? { maximum: node.maximum } : {},
|
|
17471
|
+
...typeof node.exclusiveMaximum === "number" ? { exclusiveMaximum: node.exclusiveMaximum } : {}
|
|
17472
|
+
};
|
|
17473
|
+
}
|
|
17474
|
+
function isSettingValue(value) {
|
|
17475
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
17476
|
+
}
|
|
17477
|
+
function checkConfigValue(entry, raw) {
|
|
17478
|
+
const text = raw.trim();
|
|
17479
|
+
switch (entry.kind) {
|
|
17480
|
+
case "boolean": {
|
|
17481
|
+
if (text !== "true" && text !== "false") {
|
|
17482
|
+
return { ok: false, problem: { code: "not-a-kind", kind: "boolean" } };
|
|
17483
|
+
}
|
|
17484
|
+
return { ok: true, literal: text };
|
|
17485
|
+
}
|
|
17486
|
+
case "integer":
|
|
17487
|
+
case "number": {
|
|
17488
|
+
const value = Number(text);
|
|
17489
|
+
if (text === "" || !Number.isFinite(value)) {
|
|
17490
|
+
return { ok: false, problem: { code: "not-a-kind", kind: entry.kind } };
|
|
17491
|
+
}
|
|
17492
|
+
if (entry.kind === "integer" && !Number.isInteger(value)) {
|
|
17493
|
+
return { ok: false, problem: { code: "not-a-kind", kind: "integer" } };
|
|
17494
|
+
}
|
|
17495
|
+
const bounds = checkBounds(entry, value);
|
|
17496
|
+
if (bounds) return { ok: false, problem: bounds };
|
|
17497
|
+
return { ok: true, literal: String(value) };
|
|
17498
|
+
}
|
|
17499
|
+
}
|
|
17500
|
+
const choices = entry.choices;
|
|
17501
|
+
if (choices !== void 0) {
|
|
17502
|
+
if (!choices.includes(text)) {
|
|
17503
|
+
return { ok: false, problem: { code: "not-in-choices", choices } };
|
|
17504
|
+
}
|
|
17505
|
+
return { ok: true, literal: text };
|
|
17506
|
+
}
|
|
17507
|
+
const minLength = entry.minLength ?? 1;
|
|
17508
|
+
if (text.length < minLength) {
|
|
17509
|
+
return { ok: false, problem: { code: "too-short", minLength } };
|
|
17510
|
+
}
|
|
17511
|
+
return { ok: true, literal: quoteIfNeeded(text) };
|
|
17512
|
+
}
|
|
17513
|
+
function checkBounds(entry, value) {
|
|
17514
|
+
if (entry.exclusiveMinimum !== void 0 && value <= entry.exclusiveMinimum) {
|
|
17515
|
+
return { code: "below-minimum", bound: entry.exclusiveMinimum, exclusive: true };
|
|
17516
|
+
}
|
|
17517
|
+
if (entry.minimum !== void 0 && value < entry.minimum) {
|
|
17518
|
+
return { code: "below-minimum", bound: entry.minimum, exclusive: false };
|
|
17519
|
+
}
|
|
17520
|
+
if (entry.exclusiveMaximum !== void 0 && value >= entry.exclusiveMaximum) {
|
|
17521
|
+
return { code: "above-maximum", bound: entry.exclusiveMaximum, exclusive: true };
|
|
17522
|
+
}
|
|
17523
|
+
if (entry.maximum !== void 0 && value > entry.maximum) {
|
|
17524
|
+
return { code: "above-maximum", bound: entry.maximum, exclusive: false };
|
|
17525
|
+
}
|
|
17526
|
+
return void 0;
|
|
17527
|
+
}
|
|
17528
|
+
function quoteIfNeeded(value) {
|
|
17529
|
+
if (/^[A-Za-z0-9_][A-Za-z0-9_./+=:-]*$/.test(value)) return value;
|
|
17530
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
17531
|
+
}
|
|
16376
17532
|
var MODULE2 = "Keybindings";
|
|
16377
17533
|
var VIM_MODE_KEY = "vimMode";
|
|
16378
17534
|
var FileSchema = z.record(z.string(), z.array(z.string()));
|
|
@@ -16567,11 +17723,11 @@ function buildSearchQuery(query) {
|
|
|
16567
17723
|
}
|
|
16568
17724
|
const latinPart = cleaned.replace(CJK_RUN, " ");
|
|
16569
17725
|
for (const w of latinPart.split(/\s+/)) {
|
|
16570
|
-
const
|
|
16571
|
-
if (
|
|
17726
|
+
const t83 = w.trim();
|
|
17727
|
+
if (t83.length >= 2) terms.add(t83);
|
|
16572
17728
|
}
|
|
16573
17729
|
if (terms.size === 0) return null;
|
|
16574
|
-
return [...terms].map((
|
|
17730
|
+
return [...terms].map((t83) => `"${t83.replace(/"/g, "")}"`).join(" OR ");
|
|
16575
17731
|
}
|
|
16576
17732
|
// src/memory/db.ts
|
|
16577
17733
|
var NS2 = "memory";
|
|
@@ -17062,8 +18218,8 @@ var MemoryManager = class {
|
|
|
17062
18218
|
async add(target, content) {
|
|
17063
18219
|
const label = injectionLabelOf(content);
|
|
17064
18220
|
if (label !== void 0) return this.refuseInjection(label);
|
|
17065
|
-
const
|
|
17066
|
-
if (
|
|
18221
|
+
const budget = this.getBudget()[target];
|
|
18222
|
+
if (budget.current + content.length > budget.limit) {
|
|
17067
18223
|
this.consolidationFailures++;
|
|
17068
18224
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
17069
18225
|
return {
|
|
@@ -17110,9 +18266,9 @@ var MemoryManager = class {
|
|
|
17110
18266
|
}
|
|
17111
18267
|
const label = injectionLabelOf(content);
|
|
17112
18268
|
if (label !== void 0) return this.refuseInjection(label);
|
|
17113
|
-
const
|
|
18269
|
+
const budget = this.getBudget()[target];
|
|
17114
18270
|
const delta = content.length - existing.charLength;
|
|
17115
|
-
if (
|
|
18271
|
+
if (budget.current + delta > budget.limit) {
|
|
17116
18272
|
this.consolidationFailures++;
|
|
17117
18273
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
17118
18274
|
return { success: false, done: true, error: "Consolidation limit reached" };
|
|
@@ -17317,11 +18473,11 @@ var MemoryManager = class {
|
|
|
17317
18473
|
for (const target of ["memory", "user"]) {
|
|
17318
18474
|
const rows = kept.filter((e) => e.target === target);
|
|
17319
18475
|
if (rows.length === 0) continue;
|
|
17320
|
-
const
|
|
18476
|
+
const budget = this.getBudget()[target];
|
|
17321
18477
|
const label = target === "user" ? "USER PROFILE (who the user is)" : "MEMORY (your personal notes)";
|
|
17322
18478
|
sections.push(
|
|
17323
18479
|
[
|
|
17324
|
-
`${label} [${rows.length} entries \xB7 ${
|
|
18480
|
+
`${label} [${rows.length} entries \xB7 ${budget.current.toLocaleString()}/${budget.limit.toLocaleString()} chars]`,
|
|
17325
18481
|
...rows.map((e) => this.indexLine(e))
|
|
17326
18482
|
].join("\n")
|
|
17327
18483
|
);
|
|
@@ -17352,7 +18508,7 @@ var MemoryManager = class {
|
|
|
17352
18508
|
return `${e.id} ${e.summary} (${e.charLength} chars)`;
|
|
17353
18509
|
}
|
|
17354
18510
|
buildConsolidateHint(target) {
|
|
17355
|
-
const
|
|
18511
|
+
const budget = this.getBudget()[target];
|
|
17356
18512
|
const heat = /* @__PURE__ */ new Map();
|
|
17357
18513
|
for (const row of this.db.getAll(target)) {
|
|
17358
18514
|
const id = this.idByContent.get(contentKey(row.target, row.content));
|
|
@@ -17360,7 +18516,7 @@ var MemoryManager = class {
|
|
|
17360
18516
|
}
|
|
17361
18517
|
const candidates2 = this.indexEntries(target).sort((a, b) => (heat.get(a.id) ?? 0) - (heat.get(b.id) ?? 0) || b.charLength - a.charLength).slice(0, 5);
|
|
17362
18518
|
return [
|
|
17363
|
-
`Memory at ${
|
|
18519
|
+
`Memory at ${budget.current.toLocaleString()}/${budget.limit.toLocaleString()} chars (${budget.percent}%) for ${target}. Cannot add new entry.`,
|
|
17364
18520
|
"",
|
|
17365
18521
|
"To make room, work by id \u2014 NOT by old_text. The MEMORY INDEX only shows a truncated",
|
|
17366
18522
|
"first line, so text copied from it will never match an entry exactly.",
|
|
@@ -18202,6 +19358,10 @@ var SessionDB = class {
|
|
|
18202
19358
|
where += " AND cwd = @cwd";
|
|
18203
19359
|
params["cwd"] = input.cwd;
|
|
18204
19360
|
}
|
|
19361
|
+
if (!input.includeDelegate) {
|
|
19362
|
+
where += " AND COALESCE(source, '') != @delegateSource";
|
|
19363
|
+
params["delegateSource"] = DELEGATE_SESSION_SOURCE;
|
|
19364
|
+
}
|
|
18205
19365
|
if (input.updatedSince !== void 0) {
|
|
18206
19366
|
where += " AND COALESCE(updated_at, started_at) > @updatedSince";
|
|
18207
19367
|
params["updatedSince"] = input.updatedSince;
|
|
@@ -18262,8 +19422,8 @@ var SessionDB = class {
|
|
|
18262
19422
|
const todo = this.db.prepare(
|
|
18263
19423
|
"INSERT INTO todos (id, session_id, content, status, reason, created_at, updated_at) VALUES (@id, @sessionId, @content, @status, @reason, @createdAt, @updatedAt)"
|
|
18264
19424
|
);
|
|
18265
|
-
for (const
|
|
18266
|
-
todo.run({ ...
|
|
19425
|
+
for (const t83 of extras.todos ?? []) {
|
|
19426
|
+
todo.run({ ...t83, sessionId: m.id, reason: t83.reason || null });
|
|
18267
19427
|
}
|
|
18268
19428
|
}
|
|
18269
19429
|
const g = extras.goal;
|
|
@@ -18521,6 +19681,26 @@ var SessionDB = class {
|
|
|
18521
19681
|
duration: 0
|
|
18522
19682
|
};
|
|
18523
19683
|
}
|
|
19684
|
+
offloadImageParts(sessionId) {
|
|
19685
|
+
const rows = this.db.prepare(
|
|
19686
|
+
`SELECT id, parts FROM messages WHERE session_id = ? AND active = 1 AND parts IS NOT NULL AND parts LIKE '%"image"%'`
|
|
19687
|
+
).all(sessionId);
|
|
19688
|
+
const update = this.db.prepare("UPDATE messages SET parts = @parts WHERE id = @id");
|
|
19689
|
+
let changed = 0;
|
|
19690
|
+
const run = this.db.transaction(() => {
|
|
19691
|
+
for (const row of rows) {
|
|
19692
|
+
const parts = parseParts(row.parts);
|
|
19693
|
+
if (!parts || !parts.some((p) => p.type === "image")) continue;
|
|
19694
|
+
const next = parts.map(
|
|
19695
|
+
(p) => p.type === "image" ? { type: "text", text: OFFLOADED_IMAGE_NOTE } : p
|
|
19696
|
+
);
|
|
19697
|
+
update.run({ parts: JSON.stringify(next), id: row.id });
|
|
19698
|
+
changed += 1;
|
|
19699
|
+
}
|
|
19700
|
+
});
|
|
19701
|
+
run();
|
|
19702
|
+
return changed;
|
|
19703
|
+
}
|
|
18524
19704
|
archiveAndCompact(sessionId, input) {
|
|
18525
19705
|
const run = this.db.transaction(() => {
|
|
18526
19706
|
const rows = this.db.prepare(
|
|
@@ -18743,7 +19923,7 @@ function checkFtsHealth(db) {
|
|
|
18743
19923
|
messages,
|
|
18744
19924
|
tables,
|
|
18745
19925
|
missingTriggers,
|
|
18746
|
-
healthy: missingTriggers.length === 0 && tables.every((
|
|
19926
|
+
healthy: missingTriggers.length === 0 && tables.every((t83) => t83.error === null && t83.drift === null && t83.rows === messages),
|
|
18747
19927
|
indexBytes: indexBytesOf(db),
|
|
18748
19928
|
space: spaceOf(db)
|
|
18749
19929
|
};
|
|
@@ -18893,10 +20073,10 @@ var AUTO_VACUUM_MIN_FREELIST_RATIO = 0.25;
|
|
|
18893
20073
|
var IMPORT_ROLES = /* @__PURE__ */ new Set(["system", "user", "assistant", "tool"]);
|
|
18894
20074
|
var TODO_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
|
|
18895
20075
|
function validateImportExtras(input) {
|
|
18896
|
-
for (const [i,
|
|
18897
|
-
if (typeof
|
|
18898
|
-
if (!TODO_STATUSES.has(
|
|
18899
|
-
if (typeof
|
|
20076
|
+
for (const [i, t83] of (input.todos ?? []).entries()) {
|
|
20077
|
+
if (typeof t83.content !== "string" || t83.content === "") return `todos[${i}].content`;
|
|
20078
|
+
if (!TODO_STATUSES.has(t83.status)) return `todos[${i}].status`;
|
|
20079
|
+
if (typeof t83.createdAt !== "string" || typeof t83.updatedAt !== "string") return `todos[${i}].at`;
|
|
18900
20080
|
}
|
|
18901
20081
|
const g = input.goal;
|
|
18902
20082
|
if (g === void 0) return void 0;
|
|
@@ -19085,7 +20265,7 @@ var SessionManager = class {
|
|
|
19085
20265
|
converted.push({ ...rest, parts: result.parts });
|
|
19086
20266
|
}
|
|
19087
20267
|
const droppedParentId = meta.parentId !== void 0 && !this.db.hasSession(meta.parentId) ? meta.parentId : void 0;
|
|
19088
|
-
const todos = (input.todos ?? []).map((
|
|
20268
|
+
const todos = (input.todos ?? []).map((t83) => ({ ...t83, id: this.db.freshTodoId() }));
|
|
19089
20269
|
const goal = input.goal === void 0 ? void 0 : { ...input.goal, id: `goal_${randomUUID().replace(/-/g, "")}` };
|
|
19090
20270
|
try {
|
|
19091
20271
|
const newIds = this.db.importSession(
|
|
@@ -19103,7 +20283,7 @@ var SessionManager = class {
|
|
|
19103
20283
|
messageCount: newIds.length,
|
|
19104
20284
|
idMap,
|
|
19105
20285
|
...droppedParentId === void 0 ? {} : { droppedParentId },
|
|
19106
|
-
...input.todos === void 0 ? {} : { todoIds: todos.map((
|
|
20286
|
+
...input.todos === void 0 ? {} : { todoIds: todos.map((t83) => t83.id) },
|
|
19107
20287
|
...goal === void 0 ? {} : { goalId: goal.id }
|
|
19108
20288
|
};
|
|
19109
20289
|
} catch (err) {
|
|
@@ -19250,6 +20430,9 @@ var SessionManager = class {
|
|
|
19250
20430
|
const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize, summarize2) ?? outlineOf(toSummarize);
|
|
19251
20431
|
return this.db.compact(sessionId, summary, beforeCount, IMPORTANT_ROUNDS * 2);
|
|
19252
20432
|
}
|
|
20433
|
+
offloadImageParts(sessionId) {
|
|
20434
|
+
return this.db.offloadImageParts(sessionId);
|
|
20435
|
+
}
|
|
19253
20436
|
archiveAndCompact(sessionId, input) {
|
|
19254
20437
|
return this.db.archiveAndCompact(sessionId, input);
|
|
19255
20438
|
}
|
|
@@ -19445,8 +20628,8 @@ var GoalService = class {
|
|
|
19445
20628
|
const text = objective.trim();
|
|
19446
20629
|
if (!text) return { ok: false, reason: "empty-objective" };
|
|
19447
20630
|
if (text.length > MAX_OBJECTIVE_CHARS) return { ok: false, reason: "objective-too-long" };
|
|
19448
|
-
const
|
|
19449
|
-
if (!Number.isInteger(
|
|
20631
|
+
const budget = maxRounds ?? DEFAULT_GOAL_MAX_ROUNDS;
|
|
20632
|
+
if (!Number.isInteger(budget) || budget < 1 || budget > MAX_GOAL_MAX_ROUNDS) {
|
|
19450
20633
|
return { ok: false, reason: "bad-budget" };
|
|
19451
20634
|
}
|
|
19452
20635
|
const existing = this.current(sessionId);
|
|
@@ -19458,7 +20641,7 @@ var GoalService = class {
|
|
|
19458
20641
|
objective: text,
|
|
19459
20642
|
phase: "active",
|
|
19460
20643
|
block: void 0,
|
|
19461
|
-
maxRounds:
|
|
20644
|
+
maxRounds: budget,
|
|
19462
20645
|
roundsUsed: 0,
|
|
19463
20646
|
completeEvidence: void 0,
|
|
19464
20647
|
createdAt: at,
|
|
@@ -19603,7 +20786,7 @@ function withGoalCompression(engine, view) {
|
|
|
19603
20786
|
if (!now) return engine.compress(messages, config);
|
|
19604
20787
|
return engine.compress(messages, { ...config, goal: now.objective });
|
|
19605
20788
|
},
|
|
19606
|
-
shouldCompress: (
|
|
20789
|
+
shouldCompress: (promptTokens3, contextLength) => engine.shouldCompress(promptTokens3, contextLength),
|
|
19607
20790
|
trackUsage: (usage) => engine.trackUsage(usage),
|
|
19608
20791
|
getTotalTokens: () => engine.getTotalTokens(),
|
|
19609
20792
|
reset: () => engine.reset()
|
|
@@ -19998,7 +21181,7 @@ var AppearanceStore = class {
|
|
|
19998
21181
|
}
|
|
19999
21182
|
};
|
|
20000
21183
|
function ruleAskActive(level) {
|
|
20001
|
-
return level
|
|
21184
|
+
return approvalPolicyForLevel(level) === "ask";
|
|
20002
21185
|
}
|
|
20003
21186
|
function checkCodeExec(isolation) {
|
|
20004
21187
|
if (isolation === "os") {
|
|
@@ -20032,7 +21215,7 @@ function checkPlan(operation, extraRoots) {
|
|
|
20032
21215
|
code: "level-default"
|
|
20033
21216
|
};
|
|
20034
21217
|
}
|
|
20035
|
-
if (operation.type === "file_write"
|
|
21218
|
+
if (operation.type === "file_write") {
|
|
20036
21219
|
return { allowed: false, reason: t("permission_reason.plan_no_write"), code: "level-default" };
|
|
20037
21220
|
}
|
|
20038
21221
|
if (operation.type === "network") {
|
|
@@ -20042,6 +21225,10 @@ function checkPlan(operation, extraRoots) {
|
|
|
20042
21225
|
code: "level-default"
|
|
20043
21226
|
};
|
|
20044
21227
|
}
|
|
21228
|
+
if (operation.type === "command") {
|
|
21229
|
+
if (isReadOnlyCommand(operation.detail)) return { allowed: true, code: "level-default" };
|
|
21230
|
+
return { allowed: false, reason: t("permission_reason.plan_no_write"), code: "level-default" };
|
|
21231
|
+
}
|
|
20045
21232
|
return outsideWorkspace(operation, extraRoots) ?? { allowed: true, code: "level-default" };
|
|
20046
21233
|
}
|
|
20047
21234
|
function checkAcceptEdits(operation, isolation, extraRoots) {
|
|
@@ -20067,8 +21254,6 @@ function checkDefault(operation, extraRoots) {
|
|
|
20067
21254
|
}
|
|
20068
21255
|
function decideByLevel(level, operation, isolation, extraRoots = []) {
|
|
20069
21256
|
switch (level) {
|
|
20070
|
-
case "bypass":
|
|
20071
|
-
return { allowed: true, code: "level-default" };
|
|
20072
21257
|
case "auto":
|
|
20073
21258
|
return checkAuto();
|
|
20074
21259
|
case "plan":
|
|
@@ -20248,11 +21433,11 @@ var ApprovalCache = class {
|
|
|
20248
21433
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
20249
21434
|
}
|
|
20250
21435
|
normalizeTarget(target) {
|
|
20251
|
-
const
|
|
20252
|
-
if (!
|
|
20253
|
-
const unix =
|
|
21436
|
+
const t83 = target.trim();
|
|
21437
|
+
if (!t83) return "";
|
|
21438
|
+
const unix = t83.replace(/\\/g, "/");
|
|
20254
21439
|
if (unix.startsWith("/") || /^[A-Za-z]:\//.test(unix)) return resolve(unix);
|
|
20255
|
-
return
|
|
21440
|
+
return t83;
|
|
20256
21441
|
}
|
|
20257
21442
|
load() {
|
|
20258
21443
|
try {
|
|
@@ -20355,9 +21540,9 @@ function createSharedPermissionState(cache) {
|
|
|
20355
21540
|
};
|
|
20356
21541
|
}
|
|
20357
21542
|
function cacheKeyFor(raw) {
|
|
20358
|
-
const
|
|
20359
|
-
if (!
|
|
20360
|
-
return
|
|
21543
|
+
const t83 = raw.trim();
|
|
21544
|
+
if (!t83) return null;
|
|
21545
|
+
return t83.slice(0, 500);
|
|
20361
21546
|
}
|
|
20362
21547
|
// src/permission/manager.ts
|
|
20363
21548
|
var log3 = createLogger("permission");
|
|
@@ -20470,15 +21655,23 @@ var PermissionManager = class _PermissionManager {
|
|
|
20470
21655
|
code: hard.code
|
|
20471
21656
|
};
|
|
20472
21657
|
}
|
|
20473
|
-
|
|
21658
|
+
const neverAsk = approvalPolicyForLevel(this.level) === "never";
|
|
21659
|
+
if (neverAsk && hard.code === "obfuscated") {
|
|
20474
21660
|
return {
|
|
20475
21661
|
allowed: true,
|
|
20476
21662
|
reason: t("permission_reason.bypass_unaskable", { reason: hard.reason ?? "" }),
|
|
20477
21663
|
code: hard.code
|
|
20478
21664
|
};
|
|
20479
21665
|
}
|
|
20480
|
-
const
|
|
20481
|
-
if (
|
|
21666
|
+
const cached2 = this.cachedDecision(operation);
|
|
21667
|
+
if (cached2) return cached2;
|
|
21668
|
+
if (neverAsk) {
|
|
21669
|
+
return {
|
|
21670
|
+
allowed: false,
|
|
21671
|
+
reason: t("permission_reason.forbidden_unaskable", { reason: hard.reason ?? "" }),
|
|
21672
|
+
code: hard.code
|
|
21673
|
+
};
|
|
21674
|
+
}
|
|
20482
21675
|
if (this.shared.nonInteractive) {
|
|
20483
21676
|
return {
|
|
20484
21677
|
allowed: false,
|
|
@@ -20489,7 +21682,7 @@ var PermissionManager = class _PermissionManager {
|
|
|
20489
21682
|
return null;
|
|
20490
21683
|
}
|
|
20491
21684
|
approvalCacheActive() {
|
|
20492
|
-
return this.level
|
|
21685
|
+
return approvalPolicyForLevel(this.level) === "ask";
|
|
20493
21686
|
}
|
|
20494
21687
|
rememberFlag() {
|
|
20495
21688
|
return this.approvalCacheActive() ? {} : { rememberable: false };
|
|
@@ -20497,15 +21690,15 @@ var PermissionManager = class _PermissionManager {
|
|
|
20497
21690
|
cachedDecision(operation) {
|
|
20498
21691
|
const cacheTool = operation.toolName ?? operation.type;
|
|
20499
21692
|
const cacheKey = cacheKeyFor(operation.target || operation.detail);
|
|
20500
|
-
const
|
|
20501
|
-
if (
|
|
21693
|
+
const cached2 = cacheKey ? this.shared.cache.get(cacheTool, cacheKey) : null;
|
|
21694
|
+
if (cached2 === "allow-always" || cached2 === "allow-session") {
|
|
20502
21695
|
return {
|
|
20503
21696
|
allowed: true,
|
|
20504
21697
|
reason: t("permission_reason.cached_allow"),
|
|
20505
21698
|
code: "approval-cache"
|
|
20506
21699
|
};
|
|
20507
21700
|
}
|
|
20508
|
-
if (
|
|
21701
|
+
if (cached2 === "deny") {
|
|
20509
21702
|
return {
|
|
20510
21703
|
allowed: false,
|
|
20511
21704
|
reason: t("permission_reason.cached_deny"),
|
|
@@ -20528,8 +21721,8 @@ var PermissionManager = class _PermissionManager {
|
|
|
20528
21721
|
if (ruleDecision && !ruleDecision.allowed && !ruleDecision.requireApproval) {
|
|
20529
21722
|
return ruleDecision;
|
|
20530
21723
|
}
|
|
20531
|
-
const
|
|
20532
|
-
if (
|
|
21724
|
+
const cached2 = this.approvalCacheActive() ? this.cachedDecision(operation) : null;
|
|
21725
|
+
if (cached2) return cached2;
|
|
20533
21726
|
const asked = listMatch?.verdict === "ask" ? {
|
|
20534
21727
|
allowed: false,
|
|
20535
21728
|
requireApproval: true,
|
|
@@ -20812,6 +22005,14 @@ var MIGRATIONS3 = [
|
|
|
20812
22005
|
up: (db) => {
|
|
20813
22006
|
db.exec(`ALTER TABLE schedules ADD COLUMN show_in_session_list INTEGER NOT NULL DEFAULT 0;`);
|
|
20814
22007
|
}
|
|
22008
|
+
},
|
|
22009
|
+
{
|
|
22010
|
+
id: "schedule-drop-budget",
|
|
22011
|
+
version: 3,
|
|
22012
|
+
description: "\u64A4\u6389\u300C\u8FD9\u4E00\u6B21\u6700\u591A\u82B1\u591A\u5C11\u300D\u90A3\u4E00\u5217\uFF08\u9884\u7B97\u4E0D\u518D\u662F\u4E00\u628A\u5C3A\u5B50\uFF09",
|
|
22013
|
+
up: (db) => {
|
|
22014
|
+
db.exec(`ALTER TABLE schedules DROP COLUMN max_budget_usd;`);
|
|
22015
|
+
}
|
|
20815
22016
|
}
|
|
20816
22017
|
];
|
|
20817
22018
|
var ScheduleStore = class {
|
|
@@ -20842,7 +22043,6 @@ var ScheduleStore = class {
|
|
|
20842
22043
|
allowOperations: input.allowOperations ?? [],
|
|
20843
22044
|
allowRules: input.allowRules ?? [],
|
|
20844
22045
|
maxTurns: input.maxTurns ?? SCHEDULE_DEFAULTS.maxTurns,
|
|
20845
|
-
maxBudgetUsd: input.maxBudgetUsd,
|
|
20846
22046
|
timeoutMs: input.timeoutMs ?? SCHEDULE_DEFAULTS.timeoutMs,
|
|
20847
22047
|
...input.showInSessionList === true ? { showInSessionList: true } : {},
|
|
20848
22048
|
trigger: normalizeTrigger(input.trigger),
|
|
@@ -20868,7 +22068,6 @@ var ScheduleStore = class {
|
|
|
20868
22068
|
allowOperations: [...input.allowOperations],
|
|
20869
22069
|
allowRules: [...input.allowRules],
|
|
20870
22070
|
maxTurns: input.maxTurns,
|
|
20871
|
-
maxBudgetUsd: input.maxBudgetUsd,
|
|
20872
22071
|
timeoutMs: input.timeoutMs,
|
|
20873
22072
|
...input.showInSessionList === true ? { showInSessionList: true } : {},
|
|
20874
22073
|
trigger: normalizeTrigger(input.trigger),
|
|
@@ -20910,14 +22109,14 @@ var ScheduleStore = class {
|
|
|
20910
22109
|
`INSERT INTO schedules (
|
|
20911
22110
|
id, name, enabled, created_at, updated_at, prompt, work_dir, model, role,
|
|
20912
22111
|
skills, mcp_servers, permission, allow_tools, allow_operations, allow_rules,
|
|
20913
|
-
max_turns,
|
|
22112
|
+
max_turns, timeout_ms, show_in_session_list,
|
|
20914
22113
|
trigger_kind, trigger_spec,
|
|
20915
22114
|
start_date, end_date, os_backend, os_task_id, os_registered_at, os_command,
|
|
20916
22115
|
last_run_at, last_status
|
|
20917
22116
|
) VALUES (
|
|
20918
22117
|
@id, @name, @enabled, @created_at, @updated_at, @prompt, @work_dir, @model, @role,
|
|
20919
22118
|
@skills, @mcp_servers, @permission, @allow_tools, @allow_operations, @allow_rules,
|
|
20920
|
-
@max_turns, @
|
|
22119
|
+
@max_turns, @timeout_ms, @show_in_session_list,
|
|
20921
22120
|
@trigger_kind, @trigger_spec,
|
|
20922
22121
|
@start_date, @end_date, @os_backend, @os_task_id, @os_registered_at, @os_command,
|
|
20923
22122
|
@last_run_at, @last_status
|
|
@@ -21033,7 +22232,7 @@ var ScheduleStore = class {
|
|
|
21033
22232
|
work_dir = @work_dir, model = @model, role = @role, skills = @skills,
|
|
21034
22233
|
mcp_servers = @mcp_servers, permission = @permission, allow_tools = @allow_tools,
|
|
21035
22234
|
allow_operations = @allow_operations, allow_rules = @allow_rules,
|
|
21036
|
-
max_turns = @max_turns,
|
|
22235
|
+
max_turns = @max_turns, timeout_ms = @timeout_ms,
|
|
21037
22236
|
show_in_session_list = @show_in_session_list,
|
|
21038
22237
|
trigger_kind = @trigger_kind, trigger_spec = @trigger_spec,
|
|
21039
22238
|
start_date = @start_date, end_date = @end_date, os_backend = @os_backend,
|
|
@@ -21055,7 +22254,6 @@ function mergeSchedulePatch(current, patch) {
|
|
|
21055
22254
|
"allowOperations",
|
|
21056
22255
|
"allowRules",
|
|
21057
22256
|
"maxTurns",
|
|
21058
|
-
"maxBudgetUsd",
|
|
21059
22257
|
"timeoutMs",
|
|
21060
22258
|
"showInSessionList",
|
|
21061
22259
|
"trigger",
|
|
@@ -21086,12 +22284,11 @@ function toRow(def) {
|
|
|
21086
22284
|
role: def.role ?? null,
|
|
21087
22285
|
skills: def.skills ? JSON.stringify(def.skills) : null,
|
|
21088
22286
|
mcp_servers: def.mcpServers ? JSON.stringify(def.mcpServers) : null,
|
|
21089
|
-
permission: def.permission,
|
|
22287
|
+
permission: permissionOfRow(def.permission),
|
|
21090
22288
|
allow_tools: JSON.stringify(def.allowTools),
|
|
21091
22289
|
allow_operations: JSON.stringify(def.allowOperations),
|
|
21092
22290
|
allow_rules: JSON.stringify(def.allowRules),
|
|
21093
22291
|
max_turns: def.maxTurns,
|
|
21094
|
-
max_budget_usd: def.maxBudgetUsd,
|
|
21095
22292
|
timeout_ms: def.timeoutMs,
|
|
21096
22293
|
show_in_session_list: def.showInSessionList === true ? 1 : 0,
|
|
21097
22294
|
trigger_kind: def.trigger.kind,
|
|
@@ -21106,6 +22303,9 @@ function toRow(def) {
|
|
|
21106
22303
|
last_status: def.lastStatus ?? null
|
|
21107
22304
|
};
|
|
21108
22305
|
}
|
|
22306
|
+
function permissionOfRow(raw) {
|
|
22307
|
+
return resolvePermissionLevel(raw) ?? SCHEDULE_DEFAULT_PERMISSION;
|
|
22308
|
+
}
|
|
21109
22309
|
function fromRow(row) {
|
|
21110
22310
|
return {
|
|
21111
22311
|
id: row.id,
|
|
@@ -21119,12 +22319,11 @@ function fromRow(row) {
|
|
|
21119
22319
|
...row.role !== null ? { role: row.role } : {},
|
|
21120
22320
|
...row.skills !== null ? { skills: parseArray2(row.skills) } : {},
|
|
21121
22321
|
...row.mcp_servers !== null ? { mcpServers: parseArray2(row.mcp_servers) } : {},
|
|
21122
|
-
permission: row.permission,
|
|
22322
|
+
permission: permissionOfRow(row.permission),
|
|
21123
22323
|
allowTools: parseArray2(row.allow_tools),
|
|
21124
22324
|
allowOperations: parseArray2(row.allow_operations),
|
|
21125
22325
|
allowRules: parseArray2(row.allow_rules),
|
|
21126
22326
|
maxTurns: row.max_turns,
|
|
21127
|
-
maxBudgetUsd: row.max_budget_usd,
|
|
21128
22327
|
timeoutMs: row.timeout_ms,
|
|
21129
22328
|
...row.show_in_session_list !== 0 ? { showInSessionList: true } : {},
|
|
21130
22329
|
trigger: JSON.parse(row.trigger_spec),
|
|
@@ -22570,7 +23769,7 @@ function loadLexiconDir(dir, source) {
|
|
|
22570
23769
|
});
|
|
22571
23770
|
continue;
|
|
22572
23771
|
}
|
|
22573
|
-
|
|
23772
|
+
collect4(content, file, spec, source, out);
|
|
22574
23773
|
}
|
|
22575
23774
|
return out;
|
|
22576
23775
|
}
|
|
@@ -22583,7 +23782,7 @@ function classify2(file) {
|
|
|
22583
23782
|
}
|
|
22584
23783
|
return CATEGORY_SET.has(base2) ? { kind: "terms", category: base2 } : null;
|
|
22585
23784
|
}
|
|
22586
|
-
function
|
|
23785
|
+
function collect4(content, file, spec, source, out) {
|
|
22587
23786
|
const lines = content.split("\n");
|
|
22588
23787
|
for (let i = 0; i < lines.length; i++) {
|
|
22589
23788
|
const line = (lines[i] ?? "").trim();
|
|
@@ -22635,6 +23834,18 @@ function resolveComplianceDirs(opts) {
|
|
|
22635
23834
|
dirs.push({ dir: projectDir, source: "project" });
|
|
22636
23835
|
return { dirs, projectSkipped: false };
|
|
22637
23836
|
}
|
|
23837
|
+
function hookSkipReason(reason9) {
|
|
23838
|
+
if (reason9 === "escalated") return "mode-disabled";
|
|
23839
|
+
return reason9;
|
|
23840
|
+
}
|
|
23841
|
+
function hookSandboxPolicy(workDir) {
|
|
23842
|
+
return {
|
|
23843
|
+
mode: "workspace-write",
|
|
23844
|
+
workspaceRoot: workDir,
|
|
23845
|
+
allowNetwork: true,
|
|
23846
|
+
cwd: workDir
|
|
23847
|
+
};
|
|
23848
|
+
}
|
|
22638
23849
|
function sanitizeEnvironment(env) {
|
|
22639
23850
|
const sensitivePrefixes = [
|
|
22640
23851
|
"EPOCH_API_KEY",
|
|
@@ -22663,6 +23874,15 @@ function runCommandHook(config, event, workDir) {
|
|
|
22663
23874
|
const baseEnv = sanitizeEnvironment(process.env);
|
|
22664
23875
|
const injectedEnv = injectEpochEnv(event, config.pluginRoot);
|
|
22665
23876
|
const hookEnv = { ...baseEnv, ...injectedEnv, ...config.env };
|
|
23877
|
+
const policy = hookSandboxPolicy(workDir);
|
|
23878
|
+
const raw = shellSpawnArgs(config.command);
|
|
23879
|
+
const confinement = confine(raw.file, raw.args, policy);
|
|
23880
|
+
const sandbox = confinement.confined ? { confined: true, mode: confinement.mode, backend: confinement.backend } : {
|
|
23881
|
+
confined: false,
|
|
23882
|
+
mode: confinement.mode,
|
|
23883
|
+
backend: confinement.backend,
|
|
23884
|
+
skipped: hookSkipReason(confinement.reason)
|
|
23885
|
+
};
|
|
22666
23886
|
return new Promise((resolve17) => {
|
|
22667
23887
|
let stdout = "";
|
|
22668
23888
|
let stderr = "";
|
|
@@ -22675,11 +23895,16 @@ function runCommandHook(config, event, workDir) {
|
|
|
22675
23895
|
stdout,
|
|
22676
23896
|
stderr,
|
|
22677
23897
|
blocked: false,
|
|
22678
|
-
rejectReason: t("hook_load.spawn_failed", { message: err.message })
|
|
23898
|
+
rejectReason: t("hook_load.spawn_failed", { message: err.message }),
|
|
23899
|
+
sandbox
|
|
22679
23900
|
});
|
|
22680
23901
|
};
|
|
22681
23902
|
const child = guardSpawn(
|
|
22682
|
-
() => spawn(
|
|
23903
|
+
() => confinement.confined ? spawn(confinement.command, confinement.args, {
|
|
23904
|
+
cwd: workDir,
|
|
23905
|
+
env: hookEnv,
|
|
23906
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
23907
|
+
}) : spawn(config.command, {
|
|
22683
23908
|
shell: true,
|
|
22684
23909
|
cwd: workDir,
|
|
22685
23910
|
env: hookEnv,
|
|
@@ -22697,7 +23922,8 @@ function runCommandHook(config, event, workDir) {
|
|
|
22697
23922
|
stdout,
|
|
22698
23923
|
stderr,
|
|
22699
23924
|
blocked: false,
|
|
22700
|
-
rejectReason: t("hook_load.timeout")
|
|
23925
|
+
rejectReason: t("hook_load.timeout"),
|
|
23926
|
+
sandbox
|
|
22701
23927
|
});
|
|
22702
23928
|
}
|
|
22703
23929
|
}, timeout);
|
|
@@ -22728,13 +23954,21 @@ function runCommandHook(config, event, workDir) {
|
|
|
22728
23954
|
}
|
|
22729
23955
|
} catch {
|
|
22730
23956
|
}
|
|
23957
|
+
const failure = confinement.confined ? classifyFailure({
|
|
23958
|
+
exitCode,
|
|
23959
|
+
stderr,
|
|
23960
|
+
denialSignatures: confinement.denialSignatures,
|
|
23961
|
+
runnerFailureRules: confinement.runnerFailureRules
|
|
23962
|
+
}) : void 0;
|
|
22731
23963
|
resolve17({
|
|
22732
23964
|
exitCode,
|
|
22733
23965
|
stdout: stdout.trim(),
|
|
22734
23966
|
stderr: stderr.trim(),
|
|
22735
23967
|
blocked,
|
|
22736
23968
|
rejectReason,
|
|
22737
|
-
output
|
|
23969
|
+
output,
|
|
23970
|
+
sandbox,
|
|
23971
|
+
...failure ? { failure } : {}
|
|
22738
23972
|
});
|
|
22739
23973
|
});
|
|
22740
23974
|
child.on("error", (err) => {
|
|
@@ -22841,7 +24075,7 @@ var HookManager = class {
|
|
|
22841
24075
|
for (const config of entry.configs) {
|
|
22842
24076
|
try {
|
|
22843
24077
|
const result = await runCommandHook(config, event, workDir);
|
|
22844
|
-
|
|
24078
|
+
reportIfNotRun(this.log, type, config, result);
|
|
22845
24079
|
if (result.blocked) {
|
|
22846
24080
|
return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
|
|
22847
24081
|
}
|
|
@@ -22875,7 +24109,7 @@ var HookManager = class {
|
|
|
22875
24109
|
for (const entry of cmdEntries) {
|
|
22876
24110
|
if (!matchesHook(entry.matcher, event)) continue;
|
|
22877
24111
|
for (const config of entry.configs) {
|
|
22878
|
-
runCommandHook(config, event, ctx.workDir).then((result) =>
|
|
24112
|
+
runCommandHook(config, event, ctx.workDir).then((result) => reportIfNotRun(this.log, type, config, result)).catch((err) => {
|
|
22879
24113
|
this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe12(err)}`, {
|
|
22880
24114
|
hookType: type,
|
|
22881
24115
|
command: config.command
|
|
@@ -22931,7 +24165,7 @@ var HookManager = class {
|
|
|
22931
24165
|
for (const config of entry.configs) {
|
|
22932
24166
|
try {
|
|
22933
24167
|
const result = await runCommandHook(config, event, ctx.workDir);
|
|
22934
|
-
|
|
24168
|
+
reportIfNotRun(this.log, type, config, result);
|
|
22935
24169
|
const verdict = verdictOf2(result);
|
|
22936
24170
|
if (verdict) results.push(verdict);
|
|
22937
24171
|
} catch (err) {
|
|
@@ -22965,12 +24199,25 @@ function verdictOf2(result) {
|
|
|
22965
24199
|
}
|
|
22966
24200
|
return void 0;
|
|
22967
24201
|
}
|
|
22968
|
-
function
|
|
22969
|
-
if (result.exitCode
|
|
24202
|
+
function reportIfNotRun(log5, type, config, result) {
|
|
24203
|
+
if (result.exitCode === -1) {
|
|
24204
|
+
log5(
|
|
24205
|
+
"warn",
|
|
24206
|
+
`[HookManager] ${type} \u7684 command hook \u6CA1\u80FD\u6267\u884C\uFF0C\u672C\u6B21\u6309\u653E\u884C\u5904\u7406: ${result.rejectReason ?? t("hook_load.unknown_reason")}`,
|
|
24207
|
+
{ hookType: type, command: config.command }
|
|
24208
|
+
);
|
|
24209
|
+
return;
|
|
24210
|
+
}
|
|
24211
|
+
const kind = result.failure?.kind;
|
|
24212
|
+
if (kind !== "sandbox-denied" && kind !== "runner-failed") return;
|
|
22970
24213
|
log5(
|
|
22971
24214
|
"warn",
|
|
22972
|
-
|
|
22973
|
-
|
|
24215
|
+
t(kind === "sandbox-denied" ? "hook_load.sandbox_denied" : "hook_load.sandbox_runner_failed", {
|
|
24216
|
+
type,
|
|
24217
|
+
command: config.command,
|
|
24218
|
+
detail: result.failure?.evidence ?? result.stderr.split("\n")[0] ?? ""
|
|
24219
|
+
}),
|
|
24220
|
+
{ hookType: type, command: config.command, failure: kind }
|
|
22974
24221
|
);
|
|
22975
24222
|
}
|
|
22976
24223
|
var MAPPINGS = {
|
|
@@ -23137,6 +24384,8 @@ var EVENT_MAP = {
|
|
|
23137
24384
|
SessionStart: "session:start",
|
|
23138
24385
|
SessionEnd: "session:end",
|
|
23139
24386
|
Stop: "stop",
|
|
24387
|
+
SubagentStart: "subagent:start",
|
|
24388
|
+
SubagentStop: "subagent:stop",
|
|
23140
24389
|
PostCompact: "compress:after"
|
|
23141
24390
|
};
|
|
23142
24391
|
var UNRUNNABLE_EVENTS = {
|
|
@@ -23586,7 +24835,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23586
24835
|
const dir = join(staging, category, name);
|
|
23587
24836
|
mkdirSync(dir, { recursive: true });
|
|
23588
24837
|
copyFileSync(join(source, SKILL_FILE), join(dir, SKILL_FILE));
|
|
23589
|
-
let
|
|
24838
|
+
let budget = MAX_FILES_PER_SKILL - 1;
|
|
23590
24839
|
for (const entry of readEntries2(source, label, issues, lang)) {
|
|
23591
24840
|
if (entry.name === SKILL_FILE) continue;
|
|
23592
24841
|
if (!entry.isDir || !SKILL_ASSET_DIRS.includes(entry.name)) {
|
|
@@ -23596,7 +24845,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23596
24845
|
});
|
|
23597
24846
|
continue;
|
|
23598
24847
|
}
|
|
23599
|
-
|
|
24848
|
+
budget = copyTree(join(source, entry.name), join(dir, entry.name), label, budget, issues, lang);
|
|
23600
24849
|
}
|
|
23601
24850
|
skills.push({ name, category, dir });
|
|
23602
24851
|
}
|
|
@@ -23655,8 +24904,8 @@ function placeOf(root, parts, lang) {
|
|
|
23655
24904
|
const category = parts.at(-2) ?? "general";
|
|
23656
24905
|
return { name, category: skillSegmentIssue(category, lang) === void 0 ? category : "general" };
|
|
23657
24906
|
}
|
|
23658
|
-
function copyTree(from, to, label,
|
|
23659
|
-
let left =
|
|
24907
|
+
function copyTree(from, to, label, budget, issues, lang) {
|
|
24908
|
+
let left = budget;
|
|
23660
24909
|
mkdirSync(to, { recursive: true });
|
|
23661
24910
|
for (const entry of readEntries2(from, label, issues, lang)) {
|
|
23662
24911
|
if (left <= 0) {
|
|
@@ -24202,9 +25451,9 @@ var SkillSystem = class {
|
|
|
24202
25451
|
);
|
|
24203
25452
|
}
|
|
24204
25453
|
};
|
|
24205
|
-
function sameDirs(
|
|
24206
|
-
if (
|
|
24207
|
-
return
|
|
25454
|
+
function sameDirs(cached2, current) {
|
|
25455
|
+
if (cached2.length !== current.length) return false;
|
|
25456
|
+
return cached2.every((dir, i) => dir === current[i]?.dir);
|
|
24208
25457
|
}
|
|
24209
25458
|
var MODULE6 = "Skill";
|
|
24210
25459
|
function resolveSkillDirs(opts) {
|
|
@@ -24720,11 +25969,11 @@ function readOne(path, opts, usedBytes) {
|
|
|
24720
25969
|
}
|
|
24721
25970
|
const remaining = MAX_ATTACH_TOTAL_BYTES - usedBytes;
|
|
24722
25971
|
if (remaining <= 0) return { part: { type: "file", path, omitted: "over-limit", bytes: size } };
|
|
24723
|
-
const
|
|
24724
|
-
if (raw.length <=
|
|
25972
|
+
const budget = Math.min(MAX_ATTACH_BYTES, remaining);
|
|
25973
|
+
if (raw.length <= budget) {
|
|
24725
25974
|
return { part: { type: "file", path, text: raw.toString("utf8"), bytes: size } };
|
|
24726
25975
|
}
|
|
24727
|
-
const { text, truncatedTo } = truncateToBudget(raw,
|
|
25976
|
+
const { text, truncatedTo } = truncateToBudget(raw, budget);
|
|
24728
25977
|
return {
|
|
24729
25978
|
part: { type: "file", path, text, truncatedTo, bytes: size },
|
|
24730
25979
|
notice: t("mentions.truncated", {
|
|
@@ -24938,6 +26187,9 @@ function goalSection(goal) {
|
|
|
24938
26187
|
].join("\n");
|
|
24939
26188
|
}
|
|
24940
26189
|
var DEFAULT_THRESHOLD = DEFAULT_COMPRESSION_THRESHOLD;
|
|
26190
|
+
function messageTokens(m) {
|
|
26191
|
+
return estimateTokens(m.content) + (m.reasoning ? estimateTokens(m.reasoning) : 0);
|
|
26192
|
+
}
|
|
24941
26193
|
var COOLDOWN_TURNS = 5;
|
|
24942
26194
|
var MAX_FAILURES = 3;
|
|
24943
26195
|
var DEFAULT_CONTEXT_LENGTH3 = 128e3;
|
|
@@ -24968,11 +26220,11 @@ var ContextCompressor = class {
|
|
|
24968
26220
|
enabled: opts.enabled !== false
|
|
24969
26221
|
};
|
|
24970
26222
|
}
|
|
24971
|
-
shouldCompress(
|
|
26223
|
+
shouldCompress(promptTokens3, contextLength) {
|
|
24972
26224
|
if (!this.opts.enabled) return false;
|
|
24973
26225
|
if (this.turnsSinceCompress < COOLDOWN_TURNS) return false;
|
|
24974
26226
|
if (this.failureCount >= MAX_FAILURES) return false;
|
|
24975
|
-
return isContextNearlyFull(
|
|
26227
|
+
return isContextNearlyFull(promptTokens3, contextLength, this.opts.threshold);
|
|
24976
26228
|
}
|
|
24977
26229
|
async compress(messages, partial = {}) {
|
|
24978
26230
|
const config = {
|
|
@@ -25014,7 +26266,11 @@ var ContextCompressor = class {
|
|
|
25014
26266
|
};
|
|
25015
26267
|
}
|
|
25016
26268
|
const nl = "\n";
|
|
25017
|
-
const middleText = middle.map((m) =>
|
|
26269
|
+
const middleText = middle.map((m) => {
|
|
26270
|
+
const body2 = `${m.role}: ${m.content}`;
|
|
26271
|
+
return m.reasoning ? `${body2}
|
|
26272
|
+
[thinking] ${m.reasoning}` : body2;
|
|
26273
|
+
}).join(nl);
|
|
25018
26274
|
const summarized = await this.generateSummary(
|
|
25019
26275
|
middleText,
|
|
25020
26276
|
config.instruction,
|
|
@@ -25071,13 +26327,13 @@ var ContextCompressor = class {
|
|
|
25071
26327
|
determineBoundaries(messages, config) {
|
|
25072
26328
|
const head = messages.slice(0, config.protectFirstN);
|
|
25073
26329
|
const thresholdTokens = config.threshold * config.contextLength;
|
|
25074
|
-
const tailBudget = thresholdTokens * config.targetRatio;
|
|
26330
|
+
const tailBudget = config.force ? 0 : thresholdTokens * config.targetRatio;
|
|
25075
26331
|
let tailTokens = 0;
|
|
25076
26332
|
let tailStart = messages.length;
|
|
25077
26333
|
let userCount = 0;
|
|
25078
26334
|
for (let i = messages.length - 1; i >= config.protectFirstN; i--) {
|
|
25079
26335
|
const msg = messages[i];
|
|
25080
|
-
tailTokens +=
|
|
26336
|
+
tailTokens += messageTokens(msg);
|
|
25081
26337
|
if (msg.role === "user") userCount++;
|
|
25082
26338
|
tailStart = i;
|
|
25083
26339
|
const enoughTokens = tailTokens >= tailBudget;
|
|
@@ -25177,7 +26433,7 @@ ${extra}` : withGoal;
|
|
|
25177
26433
|
return result;
|
|
25178
26434
|
}
|
|
25179
26435
|
estimateTokens(messages) {
|
|
25180
|
-
return messages.reduce((sum, m) => sum +
|
|
26436
|
+
return messages.reduce((sum, m) => sum + messageTokens(m), 0);
|
|
25181
26437
|
}
|
|
25182
26438
|
};
|
|
25183
26439
|
var FILE_VERSION5 = 1;
|
|
@@ -25417,257 +26673,6 @@ function hasExecTierContent(inv) {
|
|
|
25417
26673
|
function hasDedicatedExecContent(inv) {
|
|
25418
26674
|
return inv.hookFiles.includes(EPOCH_HOOKS_RELPATH) || inv.policies > 0;
|
|
25419
26675
|
}
|
|
25420
|
-
function describeIsolation() {
|
|
25421
|
-
const backend = detectBackend();
|
|
25422
|
-
const os = platform();
|
|
25423
|
-
if (backend === "seatbelt") {
|
|
25424
|
-
return {
|
|
25425
|
-
level: "os",
|
|
25426
|
-
backend,
|
|
25427
|
-
detail: t("sandbox_isolation.seatbelt"),
|
|
25428
|
-
reason: "os-isolated",
|
|
25429
|
-
platform: os
|
|
25430
|
-
};
|
|
25431
|
-
}
|
|
25432
|
-
if (backend === "bubblewrap") {
|
|
25433
|
-
return {
|
|
25434
|
-
level: "os",
|
|
25435
|
-
backend,
|
|
25436
|
-
detail: t("sandbox_isolation.bubblewrap"),
|
|
25437
|
-
reason: "os-isolated",
|
|
25438
|
-
platform: os
|
|
25439
|
-
};
|
|
25440
|
-
}
|
|
25441
|
-
const [why, reason9] = os === "darwin" ? [t("sandbox_isolation.no_seatbelt"), "backend-unavailable"] : os === "linux" ? [t("sandbox_isolation.no_bubblewrap"), "backend-missing"] : (
|
|
25442
|
-
[t("sandbox_isolation.by_design", { platform: os }), "platform-unsupported"]
|
|
25443
|
-
);
|
|
25444
|
-
return {
|
|
25445
|
-
level: "process",
|
|
25446
|
-
backend,
|
|
25447
|
-
detail: t("sandbox_isolation.process_only", { why }),
|
|
25448
|
-
reason: reason9,
|
|
25449
|
-
platform: os
|
|
25450
|
-
};
|
|
25451
|
-
}
|
|
25452
|
-
var SANDBOX_COVERS = ["code_exec", "terminal"];
|
|
25453
|
-
var SANDBOX_EXCLUDES = [];
|
|
25454
|
-
// src/sandbox/sandbox.ts
|
|
25455
|
-
var IS_WINDOWS = platform() === "win32";
|
|
25456
|
-
var SANDBOX_ROOT = join(tmpdir(), "epoch-sandbox");
|
|
25457
|
-
var DEFAULT_TIMEOUT = 3e4;
|
|
25458
|
-
var MAX_OUTPUT = 1e5;
|
|
25459
|
-
var MAX_MEMORY = 512;
|
|
25460
|
-
var TRUNCATE_HEAD = 2e3;
|
|
25461
|
-
var TRUNCATE_TAIL = 2e3;
|
|
25462
|
-
function resolveExecutable(name) {
|
|
25463
|
-
if (IS_WINDOWS || name.includes("/") || name.includes("\\")) return name;
|
|
25464
|
-
for (const dir of (process.env["PATH"] ?? "").split(delimiter)) {
|
|
25465
|
-
if (!dir) continue;
|
|
25466
|
-
const candidate = join(dir, name);
|
|
25467
|
-
if (existsSync(candidate)) return candidate;
|
|
25468
|
-
}
|
|
25469
|
-
return name;
|
|
25470
|
-
}
|
|
25471
|
-
var CodeSandbox = class {
|
|
25472
|
-
sandboxDir;
|
|
25473
|
-
readableDirs;
|
|
25474
|
-
constructor(sessionId, workDir) {
|
|
25475
|
-
const safeId = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
25476
|
-
this.sandboxDir = join(SANDBOX_ROOT, safeId);
|
|
25477
|
-
mkdirSync(this.sandboxDir, { recursive: true });
|
|
25478
|
-
this.readableDirs = [];
|
|
25479
|
-
if (workDir) {
|
|
25480
|
-
const abs = resolve(workDir);
|
|
25481
|
-
if (abs !== resolve(homedir()) && abs !== "/") this.readableDirs.push(abs);
|
|
25482
|
-
}
|
|
25483
|
-
}
|
|
25484
|
-
getIsolation() {
|
|
25485
|
-
return describeIsolation();
|
|
25486
|
-
}
|
|
25487
|
-
async execute(req) {
|
|
25488
|
-
const start = Date.now();
|
|
25489
|
-
const timeout = req.timeout ?? DEFAULT_TIMEOUT;
|
|
25490
|
-
const isolation = describeIsolation().level;
|
|
25491
|
-
try {
|
|
25492
|
-
const spec = req.language === "javascript" ? this.jsSpec(req.code) : this.pySpec(req.code);
|
|
25493
|
-
const result = await this.run(spec, {
|
|
25494
|
-
timeout,
|
|
25495
|
-
allowNetwork: req.allowNetwork === true,
|
|
25496
|
-
...req.signal ? { signal: req.signal } : {}
|
|
25497
|
-
});
|
|
25498
|
-
return { ...result, isolation };
|
|
25499
|
-
} catch (err) {
|
|
25500
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
25501
|
-
if (msg.includes("timed out") || msg.includes("killed")) {
|
|
25502
|
-
return {
|
|
25503
|
-
success: false,
|
|
25504
|
-
output: "",
|
|
25505
|
-
error: `[\u8D85\u65F6] \u8D85\u8FC7 ${timeout / 1e3} \u79D2`,
|
|
25506
|
-
errorType: "timeout",
|
|
25507
|
-
duration: Date.now() - start,
|
|
25508
|
-
isolation
|
|
25509
|
-
};
|
|
25510
|
-
}
|
|
25511
|
-
return {
|
|
25512
|
-
success: false,
|
|
25513
|
-
output: "",
|
|
25514
|
-
error: `[\u9519\u8BEF] ${msg}`,
|
|
25515
|
-
errorType: "runtime",
|
|
25516
|
-
duration: Date.now() - start,
|
|
25517
|
-
isolation
|
|
25518
|
-
};
|
|
25519
|
-
}
|
|
25520
|
-
}
|
|
25521
|
-
destroy() {
|
|
25522
|
-
try {
|
|
25523
|
-
rmSync(this.sandboxDir, { recursive: true });
|
|
25524
|
-
} catch {
|
|
25525
|
-
}
|
|
25526
|
-
}
|
|
25527
|
-
getDir() {
|
|
25528
|
-
return this.sandboxDir;
|
|
25529
|
-
}
|
|
25530
|
-
jsSpec(code) {
|
|
25531
|
-
const tmpFile = join(this.sandboxDir, "code.js");
|
|
25532
|
-
writeFileSync(tmpFile, code, "utf-8");
|
|
25533
|
-
return {
|
|
25534
|
-
command: process.execPath,
|
|
25535
|
-
args: [`--max-old-space-size=${MAX_MEMORY}`, tmpFile],
|
|
25536
|
-
env: EXEC_PATH_AS_NODE_ENV
|
|
25537
|
-
};
|
|
25538
|
-
}
|
|
25539
|
-
pySpec(code) {
|
|
25540
|
-
const tmpFile = join(this.sandboxDir, "code.py");
|
|
25541
|
-
writeFileSync(tmpFile, code, "utf-8");
|
|
25542
|
-
return {
|
|
25543
|
-
command: resolveExecutable(IS_WINDOWS ? "python" : "python3"),
|
|
25544
|
-
args: ["-I", tmpFile]
|
|
25545
|
-
};
|
|
25546
|
-
}
|
|
25547
|
-
run(spec, opts) {
|
|
25548
|
-
const start = Date.now();
|
|
25549
|
-
const wrapped = isolate(spec.command, spec.args, {
|
|
25550
|
-
writableDirs: [this.sandboxDir, tmpdir()],
|
|
25551
|
-
readableDirs: this.readableDirs,
|
|
25552
|
-
allowNetwork: opts.allowNetwork,
|
|
25553
|
-
cwd: this.sandboxDir
|
|
25554
|
-
});
|
|
25555
|
-
const { command, args } = wrapped ?? spec;
|
|
25556
|
-
const spawnOpts = {
|
|
25557
|
-
cwd: this.sandboxDir,
|
|
25558
|
-
timeout: opts.timeout,
|
|
25559
|
-
env: {
|
|
25560
|
-
PATH: process.env["PATH"] ?? "",
|
|
25561
|
-
HOME: process.env["HOME"] ?? "",
|
|
25562
|
-
TMPDIR: this.sandboxDir,
|
|
25563
|
-
LANG: process.env["LANG"] ?? "en_US.UTF-8",
|
|
25564
|
-
...spec.env
|
|
25565
|
-
},
|
|
25566
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
25567
|
-
...IS_WINDOWS ? { windowsHide: true } : {}
|
|
25568
|
-
};
|
|
25569
|
-
return new Promise((resolve17) => {
|
|
25570
|
-
let stdout = "";
|
|
25571
|
-
let stderr = "";
|
|
25572
|
-
let killedForOutput = false;
|
|
25573
|
-
let child = null;
|
|
25574
|
-
const onAbort = () => {
|
|
25575
|
-
child?.kill("SIGKILL");
|
|
25576
|
-
};
|
|
25577
|
-
const failToStart = (err) => {
|
|
25578
|
-
opts.signal?.removeEventListener("abort", onAbort);
|
|
25579
|
-
if (err.code === "ENOENT") {
|
|
25580
|
-
resolve17({
|
|
25581
|
-
success: false,
|
|
25582
|
-
output: "",
|
|
25583
|
-
error: `[\u9519\u8BEF] \u627E\u4E0D\u5230\u89E3\u91CA\u5668: ${command}`,
|
|
25584
|
-
errorType: "compile",
|
|
25585
|
-
duration: Date.now() - start
|
|
25586
|
-
});
|
|
25587
|
-
return;
|
|
25588
|
-
}
|
|
25589
|
-
resolve17({
|
|
25590
|
-
success: false,
|
|
25591
|
-
output: "",
|
|
25592
|
-
error: `[\u9519\u8BEF] ${err.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
|
|
25593
|
-
errorType: "runtime",
|
|
25594
|
-
duration: Date.now() - start
|
|
25595
|
-
});
|
|
25596
|
-
};
|
|
25597
|
-
child = guardSpawn(() => spawn(command, args, spawnOpts), failToStart);
|
|
25598
|
-
if (!child) return;
|
|
25599
|
-
const proc = child;
|
|
25600
|
-
let outDecoder = null;
|
|
25601
|
-
let errDecoder = null;
|
|
25602
|
-
proc.stdout?.on("data", (c) => {
|
|
25603
|
-
if (killedForOutput) return;
|
|
25604
|
-
outDecoder ??= createStreamDecoder();
|
|
25605
|
-
stdout += outDecoder.write(c);
|
|
25606
|
-
if (stdout.length >= MAX_OUTPUT) {
|
|
25607
|
-
killedForOutput = true;
|
|
25608
|
-
stdout = stdout.slice(0, MAX_OUTPUT);
|
|
25609
|
-
proc.kill("SIGKILL");
|
|
25610
|
-
}
|
|
25611
|
-
});
|
|
25612
|
-
proc.stderr?.on("data", (c) => {
|
|
25613
|
-
if (stderr.length >= MAX_OUTPUT) return;
|
|
25614
|
-
errDecoder ??= createStreamDecoder();
|
|
25615
|
-
stderr += errDecoder.write(c);
|
|
25616
|
-
});
|
|
25617
|
-
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
25618
|
-
proc.on("error", failToStart);
|
|
25619
|
-
proc.on("close", (code, sig) => {
|
|
25620
|
-
opts.signal?.removeEventListener("abort", onAbort);
|
|
25621
|
-
if (!killedForOutput) stdout += outDecoder?.end() ?? "";
|
|
25622
|
-
if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
|
|
25623
|
-
const duration = Date.now() - start;
|
|
25624
|
-
if (killedForOutput) {
|
|
25625
|
-
resolve17({
|
|
25626
|
-
success: false,
|
|
25627
|
-
output: trunc(stdout, stderr),
|
|
25628
|
-
error: `[\u8F93\u51FA\u8D85\u9650] \u8D85\u8FC7 ${MAX_OUTPUT} \u5B57\u8282\uFF0C\u5DF2\u7EC8\u6B62`,
|
|
25629
|
-
errorType: "runtime",
|
|
25630
|
-
duration
|
|
25631
|
-
});
|
|
25632
|
-
return;
|
|
25633
|
-
}
|
|
25634
|
-
if (sig) {
|
|
25635
|
-
resolve17({
|
|
25636
|
-
success: false,
|
|
25637
|
-
output: trunc(stdout, stderr),
|
|
25638
|
-
error: opts.signal?.aborted ? "[\u5DF2\u53D6\u6D88]" : "[\u8D85\u65F6] \u6267\u884C\u8D85\u65F6",
|
|
25639
|
-
errorType: "timeout",
|
|
25640
|
-
duration
|
|
25641
|
-
});
|
|
25642
|
-
return;
|
|
25643
|
-
}
|
|
25644
|
-
const output = trunc(stdout, stderr);
|
|
25645
|
-
if (code !== 0 && code !== null) {
|
|
25646
|
-
const oom = /heap out of memory|allocation failed/i.test(stderr);
|
|
25647
|
-
resolve17({
|
|
25648
|
-
success: false,
|
|
25649
|
-
output,
|
|
25650
|
-
error: oom ? `[\u5185\u5B58\u8D85\u9650] \u8D85\u8FC7 ${MAX_MEMORY}MB` : `[\u8FD0\u884C\u65F6\u9519\u8BEF] exit ${code}: ${stderr.slice(0, 200)}`,
|
|
25651
|
-
errorType: oom ? "oom" : "runtime",
|
|
25652
|
-
duration
|
|
25653
|
-
});
|
|
25654
|
-
return;
|
|
25655
|
-
}
|
|
25656
|
-
resolve17({ success: true, output, duration });
|
|
25657
|
-
});
|
|
25658
|
-
});
|
|
25659
|
-
}
|
|
25660
|
-
};
|
|
25661
|
-
function trunc(stdout, stderr) {
|
|
25662
|
-
const nl = "\n";
|
|
25663
|
-
let out = stdout;
|
|
25664
|
-
if (stderr) out += (out ? nl : "") + stderr;
|
|
25665
|
-
if (out.length <= MAX_OUTPUT) return out || "(\u65E0\u8F93\u51FA)";
|
|
25666
|
-
const head = out.slice(0, TRUNCATE_HEAD);
|
|
25667
|
-
const tail = out.slice(-TRUNCATE_TAIL);
|
|
25668
|
-
const skipped = out.length - TRUNCATE_HEAD - TRUNCATE_TAIL;
|
|
25669
|
-
return `${head}${nl}...[\u5DF2\u622A\u65AD ${(skipped / 1024).toFixed(1)} KB]...${nl}${tail}`;
|
|
25670
|
-
}
|
|
25671
26676
|
/**
|
|
25672
26677
|
* @license
|
|
25673
26678
|
* Copyright 2025 Google LLC
|
|
@@ -25713,4 +26718,4 @@ function trunc(stdout, stderr) {
|
|
|
25713
26718
|
* `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
|
|
25714
26719
|
*/
|
|
25715
26720
|
|
|
25716
|
-
export { ABOUT_DESC_MAX_CHARS, ABOUT_README_MAX_CHARS, AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, AppearanceStore, ApprovalCache, BLOCKED_TOOLS, BudgetGuard, BudgetStore, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, CheckpointManager, CheckpointStore, CodeSandbox, ComplianceEngine, ContextCompressor, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_MAX_HOLD_CHARS, DelegateManager, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, FTS_TABLES, FTS_TRIGGERS, GOAL_BLOCK_CODES, GoalService, GoalStore, HEADLESS_AUDIT_CODES, HookManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, ImageLoadError, ImportTrustStore, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, LastOpenSessions, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_ENTRIES_FILE, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PERMISSION_AUDIT_CODES, PLUGIN_ICON_MAX_BYTES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, PermissionManager, PlanModeState, PluginAuthorSchema, PluginStore, PolicyRuleSchema, ProviderError, ProviderRouter, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, RecentWorkspaces, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST,
|
|
26721
|
+
export { ABOUT_DESC_MAX_CHARS, ABOUT_README_MAX_CHARS, AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, AppearanceStore, ApprovalCache, BLOCKED_TOOLS, BudgetGuard, BudgetStore, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, CheckpointManager, CheckpointStore, CodeSandbox, ComplianceEngine, ContextCompressor, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_MAX_HOLD_CHARS, DELEGATE_SESSION_SOURCE, DelegateManager, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, FTS_TABLES, FTS_TRIGGERS, GOAL_BLOCK_CODES, GoalService, GoalStore, HEADLESS_AUDIT_CODES, HookManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, ImageLoadError, ImportTrustStore, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, LastOpenSessions, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_ENTRIES_FILE, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PERMISSION_AUDIT_CODES, PLUGIN_ICON_MAX_BYTES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, PermissionManager, PlanModeState, PluginAuthorSchema, PluginStore, PolicyRuleSchema, ProviderError, ProviderRouter, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, RecentWorkspaces, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST, SCHEDULE_ISSUE_CODES, SCHTASKS_FOLDER, SESSION_MESSAGES_READ_TOOL, SESSION_MESSAGES_SEARCH_TOOL, SESSION_QUERY_TOOLS, SESSION_SEARCH_TOOL, SESSION_TRACE_TOOL, SETTINGS_LAYER_ORDER, SETTING_WRITE_KEYS, SETTING_WRITE_LAYERS, SKILL_ASSET_DIRS, SKILL_CREATE_TOOL, SKILL_EDIT_TOOL, SKILL_FILE, SKILL_PATCH_TOOL, SKILL_VIEW_TOOL, SKILL_WRITE_FILE_TOOL, SLASH_COMMANDS_DIAG_MODULE, ScheduleRecorder, ScheduleRegistrar, ScheduleStore, SessionManager, SessionQueries, SessionReferences, SettingsFileError, SettingsFileSchema, SkillLearner, SkillSystem, TOOL_SEARCH_TOOL, TaskNoticeTracker, ToolRegistry, TrackerDB, TrustManager, UNSETTABLE_USER_KEYS, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, approvalEntryFor, approvalRootFor, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, capabilityOfRef, checkConfigValue, checkEpochVersion, checkFtsHealth, checkShadowing, classifyPersistFailure, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, configKeyByPath, configKeyTable, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createPluginScope, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, discoverySpec, displayAllows, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, grantedPathsFor, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, hasUsableModel, imageFromBase64, imageFromPath, imagePartTokens, importParts, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isTransientPersistFailure, isValidInterval, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listEntryModels, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadModelEntries, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelEntriesPath, modelListCandidates, needsAllowlist, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, normalizeModelEntry, normalizeTrigger, offloadOldestImages, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelEntry, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistFailureCode, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readEntryKey, readImageSize, readMarketplaces, readPluginAbout, readPluginIcon, readPluginManifest, readPluginRecords, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, requestImageBytes, resolveArtifactRetention, resolveCodeModeWorker, resolveComplianceDirs, resolveEntrySource, resolveInWorkspace, resolveMarketplaceRef, resolveMentions, resolveMultimodalPolicy, resolvePolicyDirs, resolvePricingAt, resolveProjectRoot, resolveScheduleBackend, resolveSessionReference, resolveSessionVisibility, resolveSettings, resolveSkillDirs, resolveSource, resolveTar, resolveWorkspace, restoreParts, revealScopedProvider, roleScopedProvider, roleSourceLabel, ruleCovers, ruleFromString, ruleToString, runCode, runCommand2 as runCommand, sanitizeArgNames, sanitizeCommand, sanitizeFtsQuery, sanitizePath, sanitizeToolOutput, saveModelEntries, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, testModelEntry, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, unsetUserSetting, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writableConfigKeys, writeSettingValue };
|