@epoch-agent/core 2.7.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 +114 -5
- package/dist/index.d.ts +962 -168
- package/dist/index.js +1686 -674
- 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"
|
|
@@ -2569,7 +3015,7 @@ function narrow(outcome) {
|
|
|
2569
3015
|
function createEnterTool(deps) {
|
|
2570
3016
|
return {
|
|
2571
3017
|
name: "enter_plan_mode",
|
|
2572
|
-
description: "\u8FDB\u5165 plan \u6A21\u5F0F\uFF1A\u63A5\u4E0B\u6765\u53EA\u8BFB\
|
|
3018
|
+
description: "\u8FDB\u5165 plan \u6A21\u5F0F\uFF1A\u63A5\u4E0B\u6765\u53EA\u8BFB\uFF08\u4E0D\u5199\u6587\u4EF6\u3001\u4E0D\u6267\u884C\u547D\u4EE4\u3001\u4E0D\u8054\u7F51\uFF09\uFF0C\u8C03\u7814\u5B8C\u7528 exit_plan_mode \u4EA4\u4E00\u4EFD\u8BA1\u5212\u7ED9\u7528\u6237\u6279\u3002**\u5148\u628A\u8303\u56F4\u6478\u5230\u80FD\u5199\u51FA\u8BA1\u5212\u4E86\u518D\u8C03\u5B83** \u2014\u2014 plan \u7EA7\u522B\u4E0B\u5DE5\u4F5C\u533A\u5916\u7684\u8BFB\u53D6\u8981\u7528\u6237\u9010\u4E2A\u6279\u51C6\uFF0C\u5927\u8303\u56F4\u8C03\u7814\u653E\u8FDB\u53BB\u4F1A\u53D8\u6210\u4E00\u4E32\u786E\u8BA4\u6846\uFF1B\u8FDB plan \u4E4B\u540E\u53EA\u505A\u5B9A\u70B9\u6838\u5B9E\u3002\u4EFB\u52A1\u8981\u52A8\u4E09\u4E2A\u4EE5\u4E0A\u6587\u4EF6\u3001\u6709\u591A\u79CD\u5408\u7406\u5B9E\u73B0\u8DEF\u5F84\u3001\u8981\u52A0/\u6539\u4F9D\u8D56\u3001\u8981\u52A8\u8DE8\u5305\u5951\u7EA6\uFF0C\u6216\u8005\u7528\u6237\u7684\u63CF\u8FF0\u6709\u6B67\u4E49\u4E14\u6B67\u4E49\u4F1A\u6539\u53D8\u5B9E\u73B0\u65F6\uFF0C\u624D\u503C\u5F97\u51FA\u8BA1\u5212\u3002\u5355\u6587\u4EF6\u5C0F\u6539\u52A8\u3001\u53EA\u6709\u4E00\u79CD\u660E\u663E\u505A\u6CD5\u3001\u6539\u6587\u6848\u4FEE typo \u4E0D\u8981\u7528\u3002",
|
|
2573
3019
|
parameters: {
|
|
2574
3020
|
type: "object",
|
|
2575
3021
|
properties: {
|
|
@@ -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",
|
|
@@ -3914,6 +4330,21 @@ function buildFtsMatchQuery(safeQuery) {
|
|
|
3914
4330
|
function buildTrigramMatchQuery(safeQuery) {
|
|
3915
4331
|
return safeQuery.split(/\s+/).filter(Boolean).map((word) => `"${word}"`).join(" ");
|
|
3916
4332
|
}
|
|
4333
|
+
function mergeRankedRows(primary, secondary, limit) {
|
|
4334
|
+
const merged = [];
|
|
4335
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4336
|
+
for (const row of primary) {
|
|
4337
|
+
seen.add(row.id);
|
|
4338
|
+
merged.push(row);
|
|
4339
|
+
if (merged.length >= limit) return merged;
|
|
4340
|
+
}
|
|
4341
|
+
for (const row of secondary) {
|
|
4342
|
+
if (seen.has(row.id)) continue;
|
|
4343
|
+
merged.push(row);
|
|
4344
|
+
if (merged.length >= limit) return merged;
|
|
4345
|
+
}
|
|
4346
|
+
return merged;
|
|
4347
|
+
}
|
|
3917
4348
|
var TRIGRAM_MIN_CHARS = 3;
|
|
3918
4349
|
function belowTrigramFloor(safeQuery) {
|
|
3919
4350
|
const words = safeQuery.split(/\s+/).filter(Boolean);
|
|
@@ -3995,12 +4426,15 @@ function traceSession(db, input) {
|
|
|
3995
4426
|
truncated
|
|
3996
4427
|
};
|
|
3997
4428
|
}
|
|
4429
|
+
// src/session/types.ts
|
|
4430
|
+
var DELEGATE_SESSION_SOURCE = "delegate";
|
|
3998
4431
|
// src/session/query.ts
|
|
3999
4432
|
var SESSION_SEARCH_TOOL = "session_search";
|
|
4000
4433
|
var SESSION_MESSAGES_SEARCH_TOOL = "session_messages_search";
|
|
4001
4434
|
var SESSION_MESSAGES_READ_TOOL = "session_messages_read";
|
|
4002
4435
|
var SESSION_TRACE_TOOL = "session_trace";
|
|
4003
4436
|
var SESSION_LIST_TOOL = "session_list";
|
|
4437
|
+
var DELEGATE_CLAUSE = "AND COALESCE(s.source, '') != @delegateSource";
|
|
4004
4438
|
var SESSION_QUERY_TOOLS = Object.freeze([
|
|
4005
4439
|
SESSION_SEARCH_TOOL,
|
|
4006
4440
|
SESSION_MESSAGES_SEARCH_TOOL,
|
|
@@ -4103,8 +4537,9 @@ var SessionQueries = class {
|
|
|
4103
4537
|
listSessions(input) {
|
|
4104
4538
|
const vis = resolveSessionVisibility({ ...input, db: this.db });
|
|
4105
4539
|
const archivedClause = input.archived === "all" ? "" : input.archived === "only" ? "AND s.archived = 1" : "AND s.archived = 0";
|
|
4106
|
-
const where = `${vis.clause} ${archivedClause}`;
|
|
4107
|
-
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;
|
|
4108
4543
|
const rows = this.db.prepare(
|
|
4109
4544
|
`SELECT s.id,
|
|
4110
4545
|
COALESCE(NULLIF(s.display_name, ''), s.title) AS title,
|
|
@@ -4116,7 +4551,7 @@ var SessionQueries = class {
|
|
|
4116
4551
|
WHERE ${where}
|
|
4117
4552
|
ORDER BY COALESCE(s.updated_at, s.started_at) DESC
|
|
4118
4553
|
LIMIT @limit`
|
|
4119
|
-
).all({ ...
|
|
4554
|
+
).all({ ...params, limit: input.limit });
|
|
4120
4555
|
return {
|
|
4121
4556
|
total,
|
|
4122
4557
|
sessions: rows.map((row) => ({
|
|
@@ -4141,9 +4576,19 @@ var SessionQueries = class {
|
|
|
4141
4576
|
ORDER BY rank
|
|
4142
4577
|
LIMIT @limit`;
|
|
4143
4578
|
const limitRows = limit * CANDIDATE_FACTOR;
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4579
|
+
return this.rankedRows(sql, safe, { ...visParams, limit: limitRows }, limitRows);
|
|
4580
|
+
}
|
|
4581
|
+
rankedRows(sql, safe, params, limit) {
|
|
4582
|
+
const porter = this.db.prepare(sql("messages_fts")).all({
|
|
4583
|
+
...params,
|
|
4584
|
+
query: buildFtsMatchQuery(safe)
|
|
4585
|
+
});
|
|
4586
|
+
if (belowTrigramFloor(safe)) return porter;
|
|
4587
|
+
const trigram = this.db.prepare(sql("messages_fts_trigram")).all({
|
|
4588
|
+
...params,
|
|
4589
|
+
query: buildTrigramMatchQuery(safe)
|
|
4590
|
+
});
|
|
4591
|
+
return mergeRankedRows(porter, trigram, limit);
|
|
4147
4592
|
}
|
|
4148
4593
|
titleRows(safe, limit, visClause, visParams) {
|
|
4149
4594
|
return this.db.prepare(
|
|
@@ -4190,9 +4635,7 @@ var SessionQueries = class {
|
|
|
4190
4635
|
WHERE ${table} MATCH @query AND m.session_id = @sid
|
|
4191
4636
|
ORDER BY rank
|
|
4192
4637
|
LIMIT @limit`;
|
|
4193
|
-
|
|
4194
|
-
if (fts.length > 0) return fts;
|
|
4195
|
-
return this.db.prepare(sql("messages_fts_trigram")).all({ query: buildTrigramMatchQuery(safe), sid: sessionId, limit });
|
|
4638
|
+
return this.rankedRows(sql, safe, { sid: sessionId, limit }, limit);
|
|
4196
4639
|
}
|
|
4197
4640
|
};
|
|
4198
4641
|
// src/tools/builtin/session-list.ts
|
|
@@ -4336,41 +4779,41 @@ function clampWindow(raw, fallback2, max) {
|
|
|
4336
4779
|
function stamp2(ms) {
|
|
4337
4780
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
4338
4781
|
}
|
|
4339
|
-
function
|
|
4782
|
+
function budgetOf(total) {
|
|
4340
4783
|
const shares = ANCHOR_SHARE + Math.max(0, total - 1);
|
|
4341
4784
|
const unit = Math.max(MIN_BODY, Math.floor(BODY_BUDGET / shares));
|
|
4342
4785
|
return { anchor: unit * ANCHOR_SHARE, other: unit };
|
|
4343
4786
|
}
|
|
4344
|
-
function body(text,
|
|
4787
|
+
function body(text, budget) {
|
|
4345
4788
|
const flat = text.replace(/\r\n/g, "\n").trimEnd();
|
|
4346
|
-
if (flat.length <=
|
|
4347
|
-
const rest = flat.length -
|
|
4348
|
-
return `${flat.slice(0,
|
|
4789
|
+
if (flat.length <= budget) return flat;
|
|
4790
|
+
const rest = flat.length - budget;
|
|
4791
|
+
return `${flat.slice(0, budget)}
|
|
4349
4792
|
\u2026[cut ${rest} more chars \u2014 lower before/after to spend the budget on fewer messages]`;
|
|
4350
4793
|
}
|
|
4351
4794
|
function surfaceOf(record, isCurrent) {
|
|
4352
4795
|
if (!isCurrent) return record.surface === "active" ? "active there" : "compacted there";
|
|
4353
4796
|
return record.surface === "active" ? "still in your context" : "compacted out of your context";
|
|
4354
4797
|
}
|
|
4355
|
-
function renderRecord(record, mark,
|
|
4798
|
+
function renderRecord(record, mark, budget, isCurrent) {
|
|
4356
4799
|
const tool = record.toolName ? ` \xB7 ${record.toolName}` : "";
|
|
4357
4800
|
return [
|
|
4358
4801
|
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${stamp2(record.timestamp)} \xB7 ${surfaceOf(record, isCurrent)}]`,
|
|
4359
|
-
` ${body(record.content,
|
|
4802
|
+
` ${body(record.content, budget).split("\n").join("\n ")}`
|
|
4360
4803
|
].join("\n");
|
|
4361
4804
|
}
|
|
4362
4805
|
function renderWindow(out, sessionId, isCurrent) {
|
|
4363
4806
|
const anchor = out.anchor;
|
|
4364
4807
|
if (!anchor) return "";
|
|
4365
4808
|
const count = out.before.length + out.after.length + 1;
|
|
4366
|
-
const
|
|
4809
|
+
const budget = budgetOf(count);
|
|
4367
4810
|
return [
|
|
4368
4811
|
`Session ${sessionId}${isCurrent ? " (this session)" : ""} \u2014 ${out.title || "(untitled)"}`,
|
|
4369
4812
|
`${count} of ${out.total} message(s), around #${anchor.messageId}:`,
|
|
4370
4813
|
"",
|
|
4371
|
-
...out.before.map((r) => renderRecord(r, " ",
|
|
4372
|
-
renderRecord(anchor, "\xBB",
|
|
4373
|
-
...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))
|
|
4374
4817
|
].join("\n");
|
|
4375
4818
|
}
|
|
4376
4819
|
function createSessionMessagesReadTool(deps) {
|
|
@@ -5225,7 +5668,7 @@ function available(tools) {
|
|
|
5225
5668
|
if (tools.length === 0) {
|
|
5226
5669
|
return "No deferred tools in this session \u2014 every tool is already in your tool list.";
|
|
5227
5670
|
}
|
|
5228
|
-
const names = tools.map((
|
|
5671
|
+
const names = tools.map((t83) => t83.name).sort();
|
|
5229
5672
|
const shown = names.slice(0, MAX_LISTED);
|
|
5230
5673
|
const rest = names.length - shown.length;
|
|
5231
5674
|
return `Searchable tools: ${shown.join(", ")}${rest > 0 ? ` (\u2026and ${rest} more)` : ""}.`;
|
|
@@ -5345,19 +5788,22 @@ var TrackerDB = class {
|
|
|
5345
5788
|
);
|
|
5346
5789
|
this.db.transaction(() => {
|
|
5347
5790
|
this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId);
|
|
5348
|
-
for (const
|
|
5791
|
+
for (const t83 of todos) {
|
|
5349
5792
|
insertStmt.run({
|
|
5350
|
-
id:
|
|
5793
|
+
id: t83.id,
|
|
5351
5794
|
session_id: sessionId,
|
|
5352
|
-
content:
|
|
5353
|
-
status:
|
|
5354
|
-
reason:
|
|
5355
|
-
created_at:
|
|
5356
|
-
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
|
|
5357
5800
|
});
|
|
5358
5801
|
}
|
|
5359
5802
|
})();
|
|
5360
5803
|
}
|
|
5804
|
+
deleteBySession(sessionId) {
|
|
5805
|
+
return this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId).changes;
|
|
5806
|
+
}
|
|
5361
5807
|
close() {
|
|
5362
5808
|
releaseDatabase(this.path);
|
|
5363
5809
|
}
|
|
@@ -5375,9 +5821,9 @@ function formatTodoList(todos, pendingCount) {
|
|
|
5375
5821
|
cancelled: "\u5DF2\u53D6\u6D88"
|
|
5376
5822
|
};
|
|
5377
5823
|
lines.push(`[todo] \u72B6\u6001\u6C47\u603B: ${pendingCount} \u4E2A\u5F85\u5B8C\u6210`);
|
|
5378
|
-
for (const
|
|
5379
|
-
const label = statusLabel[
|
|
5380
|
-
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}` : ""}`);
|
|
5381
5827
|
}
|
|
5382
5828
|
return lines.join("\n");
|
|
5383
5829
|
}
|
|
@@ -5451,14 +5897,14 @@ function createTodoTool(db) {
|
|
|
5451
5897
|
};
|
|
5452
5898
|
}
|
|
5453
5899
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5454
|
-
const existing = new Map(db.listBySession(ctx.sessionId).map((
|
|
5455
|
-
const todos = rawTodos.map((
|
|
5456
|
-
const prev =
|
|
5457
|
-
const status = isValidStatus(
|
|
5458
|
-
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);
|
|
5459
5905
|
return {
|
|
5460
|
-
id:
|
|
5461
|
-
content: String(
|
|
5906
|
+
id: t83.id || generateShortId(),
|
|
5907
|
+
content: String(t83.content || "").slice(0, 500),
|
|
5462
5908
|
status,
|
|
5463
5909
|
...reason9 ? { reason: reason9 } : {},
|
|
5464
5910
|
created_at: prev?.created_at || now,
|
|
@@ -5466,7 +5912,7 @@ function createTodoTool(db) {
|
|
|
5466
5912
|
};
|
|
5467
5913
|
});
|
|
5468
5914
|
db.replaceAll(ctx.sessionId, todos);
|
|
5469
|
-
const pendingCount = todos.filter((
|
|
5915
|
+
const pendingCount = todos.filter((t83) => isOpenTodo(t83.status)).length;
|
|
5470
5916
|
return {
|
|
5471
5917
|
success: true,
|
|
5472
5918
|
output: formatTodoList(todos, pendingCount),
|
|
@@ -5813,7 +6259,7 @@ function intersectNames(base2, incoming) {
|
|
|
5813
6259
|
if (!base2) return incoming ? [...incoming] : void 0;
|
|
5814
6260
|
if (!incoming) return [...base2];
|
|
5815
6261
|
const baseSet = new Set(base2);
|
|
5816
|
-
return incoming.filter((
|
|
6262
|
+
return incoming.filter((t83) => baseSet.has(t83));
|
|
5817
6263
|
}
|
|
5818
6264
|
function findRole(roles, name) {
|
|
5819
6265
|
return roles.find((r) => r.name === name);
|
|
@@ -5965,7 +6411,7 @@ function roleScopedProvider(base2, role, blocked) {
|
|
|
5965
6411
|
return allow ? allow.has(name) : true;
|
|
5966
6412
|
};
|
|
5967
6413
|
return {
|
|
5968
|
-
list: () => base2.list().filter((
|
|
6414
|
+
list: () => base2.list().filter((t83) => permitted(t83.name)),
|
|
5969
6415
|
get: (name) => permitted(name) ? base2.get(name) : void 0
|
|
5970
6416
|
};
|
|
5971
6417
|
}
|
|
@@ -5992,7 +6438,7 @@ function createRoleScope(base2, sessionRole, blocked) {
|
|
|
5992
6438
|
}
|
|
5993
6439
|
function unknownRoleTools(base2, role, blocked) {
|
|
5994
6440
|
if (!role?.tools) return [];
|
|
5995
|
-
const available2 = new Set(base2.list().map((
|
|
6441
|
+
const available2 = new Set(base2.list().map((t83) => t83.name));
|
|
5996
6442
|
const blockedSet = new Set(blocked);
|
|
5997
6443
|
return role.tools.filter((name) => !available2.has(name) && !blockedSet.has(name));
|
|
5998
6444
|
}
|
|
@@ -6355,7 +6801,7 @@ function createToolScope(base2) {
|
|
|
6355
6801
|
const permitted = (name) => allow ? allow.has(name) : true;
|
|
6356
6802
|
return {
|
|
6357
6803
|
provider: {
|
|
6358
|
-
list: () => base2.list().filter((
|
|
6804
|
+
list: () => base2.list().filter((t83) => permitted(t83.name)),
|
|
6359
6805
|
get: (name) => permitted(name) ? base2.get(name) : void 0
|
|
6360
6806
|
},
|
|
6361
6807
|
enter: (next) => {
|
|
@@ -6376,6 +6822,8 @@ function createToolScope(base2) {
|
|
|
6376
6822
|
var HOOK_TYPE_FLAGS = {
|
|
6377
6823
|
"session:start": true,
|
|
6378
6824
|
"session:end": true,
|
|
6825
|
+
"subagent:start": true,
|
|
6826
|
+
"subagent:stop": true,
|
|
6379
6827
|
"turn:before": true,
|
|
6380
6828
|
"turn:after": true,
|
|
6381
6829
|
"tool:before": true,
|
|
@@ -6525,7 +6973,7 @@ function scanHooks(dir, issues) {
|
|
|
6525
6973
|
return [...parsed.entries].map(([type, list]) => ({
|
|
6526
6974
|
type,
|
|
6527
6975
|
count: list.reduce((sum, entry) => sum + entry.hooks.length, 0)
|
|
6528
|
-
})).filter((
|
|
6976
|
+
})).filter((t83) => t83.count > 0).sort((a, b) => a.type.localeCompare(b.type));
|
|
6529
6977
|
}
|
|
6530
6978
|
function scanMcp(dir, plugin, issues) {
|
|
6531
6979
|
const path = join(dir, PLUGIN_LAYOUT.mcp);
|
|
@@ -8464,7 +8912,8 @@ async function setPluginEnabled(name, enabled, opts) {
|
|
|
8464
8912
|
const verb = enabled ? t("plugin_lifecycle.verb_enable") : t("plugin_lifecycle.verb_disable");
|
|
8465
8913
|
return {
|
|
8466
8914
|
ok: true,
|
|
8467
|
-
message: changed ? t("plugin_lifecycle.toggled", { verb, name }) : t("plugin_lifecycle.already", { name, verb })
|
|
8915
|
+
message: changed ? t("plugin_lifecycle.toggled", { verb, name }) : t("plugin_lifecycle.already", { name, verb }),
|
|
8916
|
+
changed
|
|
8468
8917
|
};
|
|
8469
8918
|
}
|
|
8470
8919
|
async function updatePlugin(name, opts) {
|
|
@@ -8713,14 +9162,14 @@ var CheckpointStore = class {
|
|
|
8713
9162
|
}
|
|
8714
9163
|
async enforceTotalSize(protectSession, protectTurnIndex) {
|
|
8715
9164
|
const turns = await this.collectTurns();
|
|
8716
|
-
let total = turns.reduce((sum,
|
|
9165
|
+
let total = turns.reduce((sum, t83) => sum + t83.bytes, 0);
|
|
8717
9166
|
if (total <= this.maxTotalBytes) return;
|
|
8718
9167
|
turns.sort((a, b) => a.createdAt - b.createdAt);
|
|
8719
|
-
for (const
|
|
9168
|
+
for (const t83 of turns) {
|
|
8720
9169
|
if (total <= this.maxTotalBytes) return;
|
|
8721
|
-
if (
|
|
8722
|
-
await this.removeTurn(
|
|
8723
|
-
total -=
|
|
9170
|
+
if (t83.sessionId === protectSession && t83.turnIndex === protectTurnIndex) continue;
|
|
9171
|
+
await this.removeTurn(t83.sessionId, t83.turnIndex);
|
|
9172
|
+
total -= t83.bytes;
|
|
8724
9173
|
}
|
|
8725
9174
|
}
|
|
8726
9175
|
async collectTurns() {
|
|
@@ -9040,7 +9489,7 @@ async function snapshotFiles(paths) {
|
|
|
9040
9489
|
}
|
|
9041
9490
|
async function collectDiffs(before, workDir) {
|
|
9042
9491
|
const out = [];
|
|
9043
|
-
let
|
|
9492
|
+
let budget = MAX_CALL_BYTES;
|
|
9044
9493
|
for (const [path, old] of before) {
|
|
9045
9494
|
if (old.kind === "opaque") continue;
|
|
9046
9495
|
const now = await readSnapshot(path);
|
|
@@ -9048,8 +9497,8 @@ async function collectDiffs(before, workDir) {
|
|
|
9048
9497
|
if (old.kind === "absent" && now.kind === "absent") continue;
|
|
9049
9498
|
if (old.kind === "text" && now.kind === "text" && old.text === now.text) continue;
|
|
9050
9499
|
const bytes = (old.kind === "text" ? old.bytes : 0) + (now.kind === "text" ? now.bytes : 0);
|
|
9051
|
-
if (bytes >
|
|
9052
|
-
|
|
9500
|
+
if (bytes > budget) continue;
|
|
9501
|
+
budget -= bytes;
|
|
9053
9502
|
out.push({
|
|
9054
9503
|
filePath: workspaceDisplayPath(path, workDir),
|
|
9055
9504
|
...old.kind === "text" ? { oldContent: old.text } : {},
|
|
@@ -9094,10 +9543,11 @@ var TaskNoticeTracker = class {
|
|
|
9094
9543
|
}
|
|
9095
9544
|
const lines = [];
|
|
9096
9545
|
for (const task of tasks) {
|
|
9097
|
-
if (task.kind
|
|
9546
|
+
if (task.kind === "shell") continue;
|
|
9098
9547
|
const before = this.seen.get(task.id);
|
|
9099
9548
|
if (before === task.status) continue;
|
|
9100
9549
|
this.seen.set(task.id, task.status);
|
|
9550
|
+
if (task.kind === "agent" && task.status === "running") continue;
|
|
9101
9551
|
lines.push(describeBackgroundTask(task));
|
|
9102
9552
|
}
|
|
9103
9553
|
if (lines.length === 0) return null;
|
|
@@ -9107,15 +9557,16 @@ var TaskNoticeTracker = class {
|
|
|
9107
9557
|
function describeBackgroundTask(task) {
|
|
9108
9558
|
const text = task.label;
|
|
9109
9559
|
const cmd = text.length > 60 ? `${text.slice(0, 60)}\u2026` : text;
|
|
9560
|
+
const agent = task.kind === "agent";
|
|
9110
9561
|
switch (task.status) {
|
|
9111
9562
|
case "running":
|
|
9112
9563
|
return `- ${task.id} \u8FD0\u884C\u4E2D\uFF1A${cmd}`;
|
|
9113
9564
|
case "exited":
|
|
9114
|
-
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}`;
|
|
9115
9566
|
case "killed":
|
|
9116
9567
|
return `- ${task.id} \u5DF2\u88AB\u505C\u6B62\uFF1A${cmd}`;
|
|
9117
9568
|
case "failed":
|
|
9118
|
-
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}`;
|
|
9119
9570
|
case "closed":
|
|
9120
9571
|
return `- ${task.id} \u5DF2\u5173\u95ED\uFF1A${cmd}`;
|
|
9121
9572
|
case "reaped":
|
|
@@ -9208,6 +9659,19 @@ function skillNotes(input, skillTokens) {
|
|
|
9208
9659
|
}
|
|
9209
9660
|
return notes;
|
|
9210
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
|
+
}
|
|
9211
9675
|
function buildContextBreakdown(input) {
|
|
9212
9676
|
const toolTokens = input.tools.reduce((sum, { tool }) => sum + toolDefinitionTokens(tool), 0);
|
|
9213
9677
|
const { detail, counts, notes } = toolDetail(input, toolTokens);
|
|
@@ -9229,7 +9693,16 @@ ${input.system.rules}`),
|
|
|
9229
9693
|
notes.push({ code: "near_limit", params: { percent: Math.round(used / input.limit * 100) } });
|
|
9230
9694
|
}
|
|
9231
9695
|
const hints = notes.map((note) => t(NOTE_KEY[note.code], note.params));
|
|
9232
|
-
|
|
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
|
+
};
|
|
9233
9706
|
}
|
|
9234
9707
|
// src/cost/display.ts
|
|
9235
9708
|
var currency;
|
|
@@ -9557,6 +10030,7 @@ function systemPromptSegments(params) {
|
|
|
9557
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",
|
|
9558
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",
|
|
9559
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",
|
|
9560
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",
|
|
9561
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",
|
|
9562
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",
|
|
@@ -9637,10 +10111,10 @@ function renderSettings(s) {
|
|
|
9637
10111
|
bits.push(`\u4E0A\u4E0B\u6587\u7A97\u53E3 ${s.contextLength}`);
|
|
9638
10112
|
bits.push(`\u81EA\u52A8\u538B\u7F29 ${s.compression.enabled ? `\u5F00\uFF08${s.compression.threshold}\uFF09` : "\u5173"}`);
|
|
9639
10113
|
bits.push(`\u7EC8\u7AEF\u6C99\u7BB1 ${s.sandboxTerminal ? "\u5F00" : "\u5173"}`);
|
|
9640
|
-
const
|
|
9641
|
-
if (s.budget?.maxCostUsd !== void 0)
|
|
9642
|
-
if (s.budget?.maxTokens !== void 0)
|
|
9643
|
-
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"}`);
|
|
9644
10118
|
return [
|
|
9645
10119
|
"<settings>",
|
|
9646
10120
|
bits.join(" \xB7 "),
|
|
@@ -10538,6 +11012,111 @@ function getGitStatus(rootDir) {
|
|
|
10538
11012
|
function findProjectInstructions(rootDir, workDir = rootDir) {
|
|
10539
11013
|
return findInstructionFiles(rootDir, workDir)[0];
|
|
10540
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
|
+
}
|
|
10541
11120
|
function persistedUsage(entry) {
|
|
10542
11121
|
return {
|
|
10543
11122
|
...entry.usage,
|
|
@@ -10857,6 +11436,50 @@ ${this.describeWarning(status)}
|
|
|
10857
11436
|
});
|
|
10858
11437
|
}
|
|
10859
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
|
+
}
|
|
10860
11483
|
var ProviderError = class extends Error {
|
|
10861
11484
|
constructor(message, code, recoverable, recovery = "abort") {
|
|
10862
11485
|
super(message);
|
|
@@ -10877,6 +11500,10 @@ function isContextOverflow(err) {
|
|
|
10877
11500
|
if (err instanceof ProviderError) return err.code === PROVIDER_CONTEXT_OVERFLOW;
|
|
10878
11501
|
return classifyProviderError(err).code === PROVIDER_CONTEXT_OVERFLOW;
|
|
10879
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
|
+
}
|
|
10880
11507
|
function isAbortError(err) {
|
|
10881
11508
|
for (let cur = err, depth = 0; cur && depth < 5; depth++) {
|
|
10882
11509
|
if (typeof cur !== "object") return false;
|
|
@@ -10976,16 +11603,17 @@ function classifyProviderError(err) {
|
|
|
10976
11603
|
}
|
|
10977
11604
|
return { code: 9999, recovery: "retry" };
|
|
10978
11605
|
}
|
|
11606
|
+
var EMPTY_REASONING = { providerOptions: { openaiCompatible: { reasoning_content: "" } } };
|
|
10979
11607
|
function toModelMessages(messages, opts = {}) {
|
|
10980
|
-
if (opts.toolMediaInline
|
|
10981
|
-
return
|
|
11608
|
+
if (opts.toolMediaInline === false) return hoistToolMedia(messages, opts);
|
|
11609
|
+
return messages.map((m) => toModelMessage(m, opts));
|
|
10982
11610
|
}
|
|
10983
|
-
function hoistToolMedia(messages) {
|
|
11611
|
+
function hoistToolMedia(messages, opts = {}) {
|
|
10984
11612
|
const out = [];
|
|
10985
11613
|
let pending = [];
|
|
10986
11614
|
for (const [i, m] of messages.entries()) {
|
|
10987
11615
|
if (m.role !== "tool") {
|
|
10988
|
-
out.push(toModelMessage(m));
|
|
11616
|
+
out.push(toModelMessage(m, opts));
|
|
10989
11617
|
continue;
|
|
10990
11618
|
}
|
|
10991
11619
|
const results = (m.toolResults ?? []).map((r) => {
|
|
@@ -11002,7 +11630,7 @@ ${note}` : note,
|
|
|
11002
11630
|
artifacts: (r.artifacts ?? []).map(({ data: _data, ...rest }) => rest)
|
|
11003
11631
|
};
|
|
11004
11632
|
});
|
|
11005
|
-
out.push(toModelMessage({ ...m, toolResults: results }));
|
|
11633
|
+
out.push(toModelMessage({ ...m, toolResults: results }, opts));
|
|
11006
11634
|
if (pending.length > 0 && messages[i + 1]?.role !== "tool") {
|
|
11007
11635
|
out.push({
|
|
11008
11636
|
role: "user",
|
|
@@ -11085,7 +11713,7 @@ function toSdkPart(p) {
|
|
|
11085
11713
|
}
|
|
11086
11714
|
return assertNeverPart(p);
|
|
11087
11715
|
}
|
|
11088
|
-
function toModelMessage(m) {
|
|
11716
|
+
function toModelMessage(m, opts = {}) {
|
|
11089
11717
|
if (m.role === "tool") {
|
|
11090
11718
|
return {
|
|
11091
11719
|
role: "tool",
|
|
@@ -11100,10 +11728,13 @@ function toModelMessage(m) {
|
|
|
11100
11728
|
if (m.role === "user" && m.parts && m.parts.length > 0) {
|
|
11101
11729
|
return { role: "user", content: m.parts.map(toSdkPart) };
|
|
11102
11730
|
}
|
|
11731
|
+
const reasoningPart = opts.reasoning && m.reasoning ? [{ type: "reasoning", text: m.reasoning }] : [];
|
|
11732
|
+
const emptyReasoning = opts.reasoning && !m.reasoning ? EMPTY_REASONING : {};
|
|
11103
11733
|
if (m.role === "assistant" && m.toolCalls && m.toolCalls.length > 0) {
|
|
11104
11734
|
return {
|
|
11105
11735
|
role: "assistant",
|
|
11106
11736
|
content: [
|
|
11737
|
+
...reasoningPart,
|
|
11107
11738
|
...m.content ? [{ type: "text", text: m.content }] : [],
|
|
11108
11739
|
...m.toolCalls.map((tc) => ({
|
|
11109
11740
|
type: "tool-call",
|
|
@@ -11111,19 +11742,35 @@ function toModelMessage(m) {
|
|
|
11111
11742
|
toolName: tc.toolName,
|
|
11112
11743
|
input: tc.input
|
|
11113
11744
|
}))
|
|
11114
|
-
]
|
|
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
|
|
11115
11757
|
};
|
|
11116
11758
|
}
|
|
11117
11759
|
return { role: m.role, content: m.content };
|
|
11118
11760
|
}
|
|
11119
|
-
|
|
11761
|
+
var ANTHROPIC_CACHE_BREAKPOINT = {
|
|
11762
|
+
anthropic: { cacheControl: { type: "ephemeral" } }
|
|
11763
|
+
};
|
|
11764
|
+
function toSdkTools(tools, opts = {}) {
|
|
11120
11765
|
const result = {};
|
|
11121
|
-
|
|
11766
|
+
const breakpointAt = opts.cacheBreakpoint === true ? tools.length - 1 : -1;
|
|
11767
|
+
tools.forEach((et, i) => {
|
|
11122
11768
|
result[et.name] = tool({
|
|
11123
11769
|
description: et.description,
|
|
11124
|
-
inputSchema: jsonSchema(et.parameters)
|
|
11770
|
+
inputSchema: jsonSchema(et.parameters),
|
|
11771
|
+
...i === breakpointAt ? { providerOptions: ANTHROPIC_CACHE_BREAKPOINT } : {}
|
|
11125
11772
|
});
|
|
11126
|
-
}
|
|
11773
|
+
});
|
|
11127
11774
|
return result;
|
|
11128
11775
|
}
|
|
11129
11776
|
function toOutputSpec(rf) {
|
|
@@ -11323,12 +11970,17 @@ function flattenMessage(m) {
|
|
|
11323
11970
|
return {
|
|
11324
11971
|
role: m.role,
|
|
11325
11972
|
content: m.content,
|
|
11326
|
-
...toolCallIds.length > 0 ? { toolCallIds } : {}
|
|
11973
|
+
...toolCallIds.length > 0 ? { toolCallIds } : {},
|
|
11974
|
+
...m.reasoning ? { reasoning: m.reasoning } : {}
|
|
11327
11975
|
};
|
|
11328
11976
|
}
|
|
11329
11977
|
function unflattenMessage(m) {
|
|
11330
11978
|
if (m.role === "assistant") {
|
|
11331
|
-
return {
|
|
11979
|
+
return {
|
|
11980
|
+
role: "assistant",
|
|
11981
|
+
content: m.content || "(\u65E0\u8F93\u51FA)",
|
|
11982
|
+
...m.reasoning ? { reasoning: m.reasoning } : {}
|
|
11983
|
+
};
|
|
11332
11984
|
}
|
|
11333
11985
|
if (m.role === "system") {
|
|
11334
11986
|
return { role: "system", content: m.content };
|
|
@@ -11473,13 +12125,18 @@ var COMMAND_APPROVAL_POLICY = [
|
|
|
11473
12125
|
].join("\n");
|
|
11474
12126
|
var PLAN_MODE_POLICY = [
|
|
11475
12127
|
"<plan_mode>",
|
|
11476
|
-
"\u9047\u5230\u5927\u4EFB\u52A1\u65F6\u5148\
|
|
12128
|
+
"\u9047\u5230\u5927\u4EFB\u52A1\u65F6\uFF0C\u5148\u628A\u8303\u56F4\u6478\u6E05\u695A \u2014\u2014 \u8BFB\u6587\u4EF6\u3001\u641C\u7D22\u3001\u5217\u76EE\u5F55\uFF0C\u8FD9\u4E9B\u5728\u4F60\u73B0\u5728\u7684\u6743\u9650\u7EA7\u522B\u4E0B\u5C31\u80FD\u505A\u3002",
|
|
12129
|
+
"\u6478\u5230\u300C\u8981\u6539\u54EA\u4E9B\u6587\u4EF6\u3001\u52A8\u54EA\u51E0\u5904\u300D\u5FC3\u91CC\u6709\u6570\u4E86\uFF0C\u518D\u8C03 `enter_plan_mode` \u51FA\u8BA1\u5212\uFF0C",
|
|
12130
|
+
"\u7528 `exit_plan_mode` \u628A\u5B83\u4EA4\u7ED9\u7528\u6237\u6279\u3002",
|
|
11477
12131
|
"\u7F16\u7801\u4EFB\u52A1\u6700\u8D35\u7684\u5931\u8D25\u4E0D\u662F\u5199\u9519\u4E00\u884C\uFF0C\u662F\u65B9\u5411\u7406\u89E3\u9519\u4E86\u7136\u540E\u5E72\u4E86\u4E8C\u5341\u5206\u949F\u3002",
|
|
11478
12132
|
"**\u8BE5\u5148\u51FA\u8BA1\u5212**\uFF1A\u9884\u8BA1\u8981\u6539 3 \u4E2A\u4EE5\u4E0A\u6587\u4EF6 \xB7 \u6709\u591A\u79CD\u5408\u7406\u5B9E\u73B0\u8DEF\u5F84 \xB7 \u8981\u65B0\u589E\u6216\u6539\u52A8\u4F9D\u8D56 \xB7",
|
|
11479
12133
|
"\u8981\u52A8\u8DE8\u5305\u5951\u7EA6 \xB7 \u7528\u6237\u7684\u63CF\u8FF0\u6709\u6B67\u4E49\u4E14\u6B67\u4E49\u4F1A\u6539\u53D8\u5B9E\u73B0\u3002",
|
|
11480
12134
|
"**\u4E0D\u8BE5\u51FA\u8BA1\u5212**\uFF1A\u5355\u6587\u4EF6\u6539\u52A8 \xB7 \u53EA\u6709\u4E00\u79CD\u660E\u663E\u505A\u6CD5 \xB7 \u6539\u6587\u6848\u4FEE typo \xB7 \u52A0\u4E00\u6761\u6D4B\u8BD5\u3002",
|
|
12135
|
+
"\u26A0\uFE0F **\u522B\u4E00\u4E0A\u6765\u5C31\u8FDB plan \u6A21\u5F0F\u518D\u5F00\u59CB\u8C03\u7814**\uFF1Aplan \u7EA7\u522B\u4E0B\u5DE5\u4F5C\u533A\u5916\u7684\u8BFB\u53D6\u8981\u7528\u6237\u9010\u4E2A\u6279\u51C6\uFF0C",
|
|
12136
|
+
"\u628A\u5927\u8303\u56F4\u8C03\u7814\u653E\u8FDB\u53BB\uFF0C\u7B49\u4E8E\u8BA9\u4ED6\u4E3A\u6BCF\u4E00\u6B21\u7FFB\u76EE\u5F55\u70B9\u4E00\u6B21\u786E\u8BA4\u6846\u3002",
|
|
12137
|
+
"\u8FDB plan \u4E4B\u540E\u53EA\u505A**\u5B9A\u70B9\u6838\u5B9E**\uFF08\u67D0\u4E2A\u884C\u53F7\u3001\u67D0\u4E2A\u5951\u7EA6\u3001\u67D0\u6761\u7528\u4F8B\uFF09\uFF0C\u4E0D\u8981\u518D\u4ECE\u5934\u626B\u4E00\u904D\u3002",
|
|
11481
12138
|
"\u5728 plan \u6A21\u5F0F\u91CC\u5199\u6587\u4EF6\u3001\u6267\u884C\u547D\u4EE4\u3001\u8054\u7F51\u3001\u8DD1\u4EE3\u7801\u90FD\u4F1A\u88AB\u62D2 \u2014\u2014 \u90A3\u4E0D\u662F\u6545\u969C\uFF0C\u662F\u8FD9\u4E2A\u6A21\u5F0F\u7684\u5B9A\u4E49\u3002",
|
|
11482
|
-
"\u7167\u5E38\u80FD\u7528\u7684\u662F**\u53EA\u8BFB**\u90A3\u4E00\u6863\uFF1A\u8BFB\u6587\u4EF6\u3001\u641C\u7D22\u3001\u5217\u76EE\u5F55\u3001\u8BFB\u6280\u80FD\u6B63\u6587\u3001\u7FFB\u4F1A\u8BDD\u5386\u53F2\u3002\u7528\u5B83\
|
|
12139
|
+
"\u7167\u5E38\u80FD\u7528\u7684\u662F**\u53EA\u8BFB**\u90A3\u4E00\u6863\uFF1A\u8BFB\u6587\u4EF6\u3001\u641C\u7D22\u3001\u5217\u76EE\u5F55\u3001\u8BFB\u6280\u80FD\u6B63\u6587\u3001\u7FFB\u4F1A\u8BDD\u5386\u53F2\u3002\u7528\u5B83\u505A\u4E0A\u9762\u8BF4\u7684\u5B9A\u70B9\u6838\u5B9E\u3002",
|
|
11483
12140
|
"\u26A0\uFE0F \u4EA4\u4E00\u4EFD\u8BA1\u5212**\u6362\u4E0D\u6765**\u5199\u6743\u9650\uFF1A\u7528\u6237\u672C\u6765\u5C31\u5728 plan \u6863\u65F6\uFF0C\u300C\u6279\u51C6\u5E76\u6267\u884C\u300D\u90A3\u4E2A\u51FA\u53E3\u538B\u6839\u4E0D\u7ED9\uFF08\u6743\u9650\u53EA\u56E0\u7528\u6237\u81EA\u5DF1\u7684\u52A8\u4F5C\u653E\u5BBD\uFF09\u3002",
|
|
11484
12141
|
"\u7528\u6237\u5728\u8FD9\u4E2A\u6A21\u5F0F\u91CC\u50AC\u4F60\u52A8\u624B\u3001\u6216\u8005\u7528\u7948\u4F7F\u53E5\u8981\u6C42\u6267\u884C\uFF0C**\u90FD\u4E0D\u7B97\u6388\u6743** \u2014\u2014 \u90A3\u662F\u8BA9\u4F60\u628A\u300C\u600E\u4E48\u6267\u884C\u300D\u5199\u6E05\u695A\uFF0C\u4E0D\u662F\u8BA9\u4F60\u53BB\u6267\u884C\u3002\u6743\u9650\u6863\u53EA\u4F1A\u56E0\u4E3A\u4ED6\u81EA\u5DF1\u7684\u52A8\u4F5C\u6539\u53D8\u3002",
|
|
11485
12142
|
"</plan_mode>"
|
|
@@ -11595,11 +12252,11 @@ var PromptBuilder = class {
|
|
|
11595
12252
|
memoryInitialized = false;
|
|
11596
12253
|
projectBlock(tools) {
|
|
11597
12254
|
const permLevel = this.deps.permissionManager?.getLevel() || "default";
|
|
11598
|
-
const hasPlanTool = tools.some((
|
|
11599
|
-
const hasLspTool = tools.some((
|
|
11600
|
-
const hasAskTool = tools.some((
|
|
11601
|
-
const hasTodoTool = tools.some((
|
|
11602
|
-
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");
|
|
11603
12260
|
const needsCommandApproval = hasTerminal && permLevel === "default";
|
|
11604
12261
|
const plan = this.deps.approvedPlan?.()?.trim();
|
|
11605
12262
|
const codeSdk = renderSdkDeclaration(this.deps.codeModeTools?.() ?? []);
|
|
@@ -11882,9 +12539,50 @@ function toAbsolute2(path, workDir) {
|
|
|
11882
12539
|
const expanded = expandPath(path);
|
|
11883
12540
|
return isAbsolute(expanded) ? resolve(expanded) : resolve(workDir, expanded);
|
|
11884
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
|
+
}
|
|
11885
12583
|
var MAX_TOOL_OUTPUT = 3e4;
|
|
11886
12584
|
var MAX_SUB_CALL_OUTPUT = CODE_MODE_LIMITS.maxValueChars;
|
|
11887
|
-
function
|
|
12585
|
+
function budgetOf2(tool, depth, path = "success") {
|
|
11888
12586
|
if (tool.governsOwnOutput && path === "success") return Number.POSITIVE_INFINITY;
|
|
11889
12587
|
return depth > 0 ? MAX_SUB_CALL_OUTPUT : MAX_TOOL_OUTPUT;
|
|
11890
12588
|
}
|
|
@@ -12120,22 +12818,28 @@ var ToolExecutor = class {
|
|
|
12120
12818
|
if (!gate.allowed) {
|
|
12121
12819
|
return finish({ ...base2, success: false, output: gate.output });
|
|
12122
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);
|
|
12123
12826
|
const targets = this.writeTargets(et, tc.input);
|
|
12124
12827
|
const snapshotted = await this.snapshot(sessionId, targets);
|
|
12125
12828
|
const before = targets.length > 0 ? await snapshotFiles(targets) : void 0;
|
|
12126
12829
|
const extraRoots = this.deps.permissionManager?.getExtraRoots?.();
|
|
12127
12830
|
const homeDir = (this.deps.multimodal?.() ?? resolveMultimodalPolicy()).homeDir;
|
|
12128
|
-
const r = await et.execute(
|
|
12831
|
+
const r = await et.execute(toolArgs, {
|
|
12129
12832
|
sessionId,
|
|
12130
12833
|
workDir: this.deps.workDir(),
|
|
12131
12834
|
...extraRoots?.length ? { extraRoots } : {},
|
|
12132
12835
|
...gate.grantedPaths?.length ? { grantedPaths: gate.grantedPaths } : {},
|
|
12133
12836
|
...homeDir ? { homeDir } : {},
|
|
12134
12837
|
...this.deps.sandboxTerminal !== void 0 ? { sandboxTerminal: this.deps.sandboxTerminal } : {},
|
|
12838
|
+
...escalation.kind === "approved" ? { sandboxEscalation: escalation.target } : {},
|
|
12135
12839
|
permissionLevel: this.deps.permissionManager?.getLevel() || "auto",
|
|
12136
12840
|
...signal ? { signal } : {},
|
|
12137
12841
|
...onOutput ? { onOutput } : {},
|
|
12138
|
-
outputBudget:
|
|
12842
|
+
outputBudget: budgetOf2(et, depth),
|
|
12139
12843
|
...depth < MAX_SUB_CALL_DEPTH ? { callTool: this.subCallChannel(sessionId, signal, span, depth) } : {}
|
|
12140
12844
|
});
|
|
12141
12845
|
if (snapshotted.length > 0) {
|
|
@@ -12167,7 +12871,7 @@ var ToolExecutor = class {
|
|
|
12167
12871
|
success: true,
|
|
12168
12872
|
output: this.renderOutput(
|
|
12169
12873
|
et,
|
|
12170
|
-
appendArtifactSummaries(text, artifacts,
|
|
12874
|
+
appendArtifactSummaries(text, artifacts, budgetOf2(et, depth), shapeOf(r.output))
|
|
12171
12875
|
),
|
|
12172
12876
|
...artifacts.length > 0 ? { artifacts } : {},
|
|
12173
12877
|
...diffs.length > 0 ? { diffs } : {}
|
|
@@ -12178,7 +12882,7 @@ var ToolExecutor = class {
|
|
|
12178
12882
|
success: false,
|
|
12179
12883
|
output: this.renderOutput(
|
|
12180
12884
|
et,
|
|
12181
|
-
truncateForModel(failureText(r),
|
|
12885
|
+
truncateForModel(failureText(r), budgetOf2(et, depth, "failure"), "text")
|
|
12182
12886
|
)
|
|
12183
12887
|
});
|
|
12184
12888
|
} catch (err) {
|
|
@@ -12260,6 +12964,56 @@ var ToolExecutor = class {
|
|
|
12260
12964
|
);
|
|
12261
12965
|
return guessed || argsKey(args);
|
|
12262
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
|
+
}
|
|
12263
13017
|
async checkPermission(et, args, signal) {
|
|
12264
13018
|
const pm = this.deps.permissionManager;
|
|
12265
13019
|
if (!pm) return { allowed: true };
|
|
@@ -12328,15 +13082,16 @@ var ToolExecutor = class {
|
|
|
12328
13082
|
var DEFAULT_CONTEXT_LENGTH = 128e3;
|
|
12329
13083
|
function shrank(before, after) {
|
|
12330
13084
|
const chars = (list) => list.reduce((sum, m) => sum + m.content.length, 0);
|
|
12331
|
-
|
|
13085
|
+
if (chars(after) < chars(before)) return true;
|
|
13086
|
+
return requestImageBytes(after) < requestImageBytes(before);
|
|
12332
13087
|
}
|
|
12333
13088
|
var NO_OUTPUT_TEXT = "(\u65E0\u8F93\u51FA)";
|
|
12334
13089
|
function imageParts(content) {
|
|
12335
13090
|
return typeof content === "string" ? [] : content.filter((p) => p.type === "image");
|
|
12336
13091
|
}
|
|
12337
13092
|
function toolSignatureOf(config, tools) {
|
|
12338
|
-
const direct = tools.map((
|
|
12339
|
-
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");
|
|
12340
13095
|
return declared ? `${direct}|${declared}` : direct;
|
|
12341
13096
|
}
|
|
12342
13097
|
function modelSignatureOf(info) {
|
|
@@ -12355,13 +13110,13 @@ function stripHistoryImages(history) {
|
|
|
12355
13110
|
});
|
|
12356
13111
|
return { messages, stripped };
|
|
12357
13112
|
}
|
|
12358
|
-
function budgetStop(
|
|
12359
|
-
const breach =
|
|
12360
|
-
if (breach) return { message:
|
|
13113
|
+
function budgetStop(budget, messages) {
|
|
13114
|
+
const breach = budget.breachReason();
|
|
13115
|
+
if (breach) return { message: budget.describeBreach(breach), breach };
|
|
12361
13116
|
const imageTokens = pendingImageTokens(messages);
|
|
12362
|
-
const projected =
|
|
13117
|
+
const projected = budget.projectedBreach(imageTokens);
|
|
12363
13118
|
if (!projected) return void 0;
|
|
12364
|
-
return { message:
|
|
13119
|
+
return { message: budget.describeProjectedBreach(projected, imageTokens), breach: projected };
|
|
12365
13120
|
}
|
|
12366
13121
|
var AgentLoop = class {
|
|
12367
13122
|
config;
|
|
@@ -12427,12 +13182,34 @@ var AgentLoop = class {
|
|
|
12427
13182
|
abort() {
|
|
12428
13183
|
this.aborted = true;
|
|
12429
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
|
+
}
|
|
12430
13193
|
multimodal() {
|
|
12431
13194
|
return resolveMultimodalPolicy({
|
|
12432
13195
|
...this.config.multimodal,
|
|
12433
13196
|
supportsImages: this.config.provider.capabilities?.supportsImages ?? false
|
|
12434
13197
|
});
|
|
12435
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
|
+
}
|
|
12436
13213
|
modelInfo() {
|
|
12437
13214
|
const id = this.config.provider.modelId;
|
|
12438
13215
|
if (!id) return void 0;
|
|
@@ -12472,6 +13249,7 @@ var AgentLoop = class {
|
|
|
12472
13249
|
projectBlock: seg2.projectBlock,
|
|
12473
13250
|
memoryBlock: seg2.memoryBlock,
|
|
12474
13251
|
historyText: opts.historyText,
|
|
13252
|
+
...opts.lastUsage ? { lastUsage: opts.lastUsage } : {},
|
|
12475
13253
|
tools: this.toolProvider.list().map((tool) => ({ tool, source: opts.toolSource?.(tool.name) ?? "builtin" })),
|
|
12476
13254
|
skillIndex: this.config.skillSystem?.indexStats?.({
|
|
12477
13255
|
only: this.config.roleSkills?.()
|
|
@@ -12489,6 +13267,7 @@ var AgentLoop = class {
|
|
|
12489
13267
|
let errored;
|
|
12490
13268
|
const started = Date.now();
|
|
12491
13269
|
for await (const ev of this.runTurns(input, turns)) {
|
|
13270
|
+
input.onEvent?.(ev);
|
|
12492
13271
|
if (ev.type === "finish") {
|
|
12493
13272
|
usage = ev.usage;
|
|
12494
13273
|
if (ev.reason === "stalled") stalled = true;
|
|
@@ -12591,13 +13370,15 @@ var AgentLoop = class {
|
|
|
12591
13370
|
let lastText = "";
|
|
12592
13371
|
let imagesDroppedReported = false;
|
|
12593
13372
|
let overflowRescued = false;
|
|
13373
|
+
let imagesRescue = { offloaded: 0 };
|
|
13374
|
+
let imagesOffloaded = false;
|
|
12594
13375
|
let runUsage;
|
|
12595
13376
|
let lastModel;
|
|
12596
13377
|
let lastRequestedModel;
|
|
12597
13378
|
const addRun = (u) => {
|
|
12598
13379
|
runUsage = runUsage ? addUsage(runUsage, u) : u;
|
|
12599
13380
|
};
|
|
12600
|
-
const
|
|
13381
|
+
const budget = new BudgetGuard({
|
|
12601
13382
|
...this.config.budget ? { budget: this.config.budget } : {},
|
|
12602
13383
|
...this.config.modelPricing ? { pricing: this.config.modelPricing } : {},
|
|
12603
13384
|
...input.maxCallCostUsd !== void 0 ? { maxCallCostUsd: input.maxCallCostUsd } : {},
|
|
@@ -12609,7 +13390,7 @@ var AgentLoop = class {
|
|
|
12609
13390
|
const finish = (reason9, breach) => ({
|
|
12610
13391
|
type: "finish",
|
|
12611
13392
|
reason: reason9,
|
|
12612
|
-
usage:
|
|
13393
|
+
usage: budget.snapshot(),
|
|
12613
13394
|
...runUsage ? { runUsage } : {},
|
|
12614
13395
|
...lastModel ? { model: lastModel } : {},
|
|
12615
13396
|
...lastRequestedModel ? { requestedModel: lastRequestedModel } : {},
|
|
@@ -12661,8 +13442,8 @@ var AgentLoop = class {
|
|
|
12661
13442
|
await this.prompt.syncMemory(userText, lastText);
|
|
12662
13443
|
return;
|
|
12663
13444
|
}
|
|
12664
|
-
|
|
12665
|
-
const stop = budgetStop(
|
|
13445
|
+
budget.syncFromStore();
|
|
13446
|
+
const stop = budgetStop(budget, messages);
|
|
12666
13447
|
if (stop) {
|
|
12667
13448
|
yield { type: "text-delta", text: stop.message };
|
|
12668
13449
|
await this.prompt.syncMemory(userText, lastText || stop.message);
|
|
@@ -12714,8 +13495,8 @@ var AgentLoop = class {
|
|
|
12714
13495
|
}
|
|
12715
13496
|
if (rescued.usage) {
|
|
12716
13497
|
addRun(rescued.usage);
|
|
12717
|
-
yield*
|
|
12718
|
-
|
|
13498
|
+
yield* budget.toEvents(
|
|
13499
|
+
budget.add(rescued.usage, this.rateOf(rescued.model)),
|
|
12719
13500
|
runUsage
|
|
12720
13501
|
);
|
|
12721
13502
|
}
|
|
@@ -12747,6 +13528,7 @@ var AgentLoop = class {
|
|
|
12747
13528
|
}
|
|
12748
13529
|
}
|
|
12749
13530
|
const turnStart = Date.now();
|
|
13531
|
+
imagesRescue = { offloaded: 0 };
|
|
12750
13532
|
const llmSpan = this.telemetry.startSpan(
|
|
12751
13533
|
"llm_call",
|
|
12752
13534
|
{
|
|
@@ -12759,6 +13541,24 @@ var AgentLoop = class {
|
|
|
12759
13541
|
);
|
|
12760
13542
|
let guard = this.config.compliance?.outputGuard();
|
|
12761
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
|
+
}
|
|
12762
13562
|
const requestFor = (msgs) => ({
|
|
12763
13563
|
provider: this.config.provider,
|
|
12764
13564
|
input: {
|
|
@@ -12775,34 +13575,59 @@ var AgentLoop = class {
|
|
|
12775
13575
|
});
|
|
12776
13576
|
let result;
|
|
12777
13577
|
try {
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
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
|
+
}
|
|
12795
13630
|
}
|
|
12796
|
-
if (!shrank(messages, rescued.messages)) throw err;
|
|
12797
|
-
messages = rescued.messages;
|
|
12798
|
-
yield {
|
|
12799
|
-
type: "notice",
|
|
12800
|
-
code: "context-compacted",
|
|
12801
|
-
text: t("agent_run.context_compacted")
|
|
12802
|
-
};
|
|
12803
|
-
guard = this.config.compliance?.outputGuard();
|
|
12804
|
-
reasoningGuard = this.config.compliance?.outputGuard();
|
|
12805
|
-
result = yield* runTurn(requestFor(messages));
|
|
12806
13631
|
} finally {
|
|
12807
13632
|
llmSpan.end();
|
|
12808
13633
|
this.telemetry.histogram(METRIC.LLM_CALL_LATENCY, Date.now() - turnStart);
|
|
@@ -12848,14 +13673,14 @@ var AgentLoop = class {
|
|
|
12848
13673
|
"epoch.token_type": "cache_write"
|
|
12849
13674
|
});
|
|
12850
13675
|
}
|
|
12851
|
-
const status =
|
|
13676
|
+
const status = budget.add(usage, this.rateOf(result.model));
|
|
12852
13677
|
input.onTurnUsage?.(
|
|
12853
13678
|
status.turnCostUsd === void 0 ? usage : { ...usage, costUsd: status.turnCostUsd }
|
|
12854
13679
|
);
|
|
12855
13680
|
addRun(usage);
|
|
12856
13681
|
lastModel = result.model;
|
|
12857
13682
|
lastRequestedModel = result.requestedModel;
|
|
12858
|
-
yield*
|
|
13683
|
+
yield* budget.toEvents(status, runUsage);
|
|
12859
13684
|
}
|
|
12860
13685
|
const verdict = mergeVerdicts(guard?.verdict(), reasoningGuard?.verdict());
|
|
12861
13686
|
if (verdict) this.reportCompliance(verdict, "output");
|
|
@@ -12920,7 +13745,11 @@ ${finalText}` };
|
|
|
12920
13745
|
turn
|
|
12921
13746
|
});
|
|
12922
13747
|
if (turn < maxTurns && input.steer?.pending() === true) {
|
|
12923
|
-
messages.push({
|
|
13748
|
+
messages.push({
|
|
13749
|
+
role: "assistant",
|
|
13750
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13751
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13752
|
+
});
|
|
12924
13753
|
yield* this.drainSteer(input, messages);
|
|
12925
13754
|
continue;
|
|
12926
13755
|
}
|
|
@@ -12931,7 +13760,11 @@ ${finalText}` };
|
|
|
12931
13760
|
);
|
|
12932
13761
|
if (wantContinue && turn < maxTurns) {
|
|
12933
13762
|
messages.push(
|
|
12934
|
-
{
|
|
13763
|
+
{
|
|
13764
|
+
role: "assistant",
|
|
13765
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13766
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13767
|
+
},
|
|
12935
13768
|
{
|
|
12936
13769
|
role: "user",
|
|
12937
13770
|
content: systemNote(
|
|
@@ -12951,7 +13784,11 @@ ${finalText}` };
|
|
|
12951
13784
|
text: t("agent_run.blank_response")
|
|
12952
13785
|
};
|
|
12953
13786
|
messages.push(
|
|
12954
|
-
{
|
|
13787
|
+
{
|
|
13788
|
+
role: "assistant",
|
|
13789
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13790
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13791
|
+
},
|
|
12955
13792
|
{ role: "user", content: systemNote(blankResponseNote(finalText.trim().length)) }
|
|
12956
13793
|
);
|
|
12957
13794
|
continue;
|
|
@@ -12963,7 +13800,11 @@ ${finalText}` };
|
|
|
12963
13800
|
if (open !== void 0 && open > 0) {
|
|
12964
13801
|
todoNudged = true;
|
|
12965
13802
|
messages.push(
|
|
12966
|
-
{
|
|
13803
|
+
{
|
|
13804
|
+
role: "assistant",
|
|
13805
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13806
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13807
|
+
},
|
|
12967
13808
|
{
|
|
12968
13809
|
role: "user",
|
|
12969
13810
|
content: systemNote(unfinishedTodoNote(open))
|
|
@@ -12975,7 +13816,11 @@ ${finalText}` };
|
|
|
12975
13816
|
if (!idleNudged && turn < maxTurns && !truncated && announcedNextStep(finalText)) {
|
|
12976
13817
|
idleNudged = true;
|
|
12977
13818
|
messages.push(
|
|
12978
|
-
{
|
|
13819
|
+
{
|
|
13820
|
+
role: "assistant",
|
|
13821
|
+
content: finalText || NO_OUTPUT_TEXT,
|
|
13822
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {}
|
|
13823
|
+
},
|
|
12979
13824
|
{ role: "user", content: systemNote(announcedButIdleNote()) }
|
|
12980
13825
|
);
|
|
12981
13826
|
continue;
|
|
@@ -12993,6 +13838,7 @@ ${finalText}` };
|
|
|
12993
13838
|
messages.push({
|
|
12994
13839
|
role: "assistant",
|
|
12995
13840
|
content: result.text,
|
|
13841
|
+
...result.reasoningText ? { reasoning: result.reasoningText } : {},
|
|
12996
13842
|
toolCalls: toolCalls.map((tc) => ({
|
|
12997
13843
|
toolCallId: tc.toolCallId,
|
|
12998
13844
|
toolName: tc.toolName,
|
|
@@ -13092,8 +13938,8 @@ ${finalText}` };
|
|
|
13092
13938
|
messages = compacted.messages;
|
|
13093
13939
|
if (compacted.usage) {
|
|
13094
13940
|
addRun(compacted.usage);
|
|
13095
|
-
yield*
|
|
13096
|
-
|
|
13941
|
+
yield* budget.toEvents(
|
|
13942
|
+
budget.add(compacted.usage, this.rateOf(compacted.model)),
|
|
13097
13943
|
runUsage
|
|
13098
13944
|
);
|
|
13099
13945
|
}
|
|
@@ -13170,7 +14016,7 @@ ${finalText}` };
|
|
|
13170
14016
|
return { ...result, ran: true };
|
|
13171
14017
|
}
|
|
13172
14018
|
async compressNow(messages, opts = {}) {
|
|
13173
|
-
const { instruction, totalTokens: totalTokens2, promptTokens:
|
|
14019
|
+
const { instruction, totalTokens: totalTokens2, promptTokens: promptTokens3, force } = opts;
|
|
13174
14020
|
const engine = this.config.contextEngine;
|
|
13175
14021
|
if (!engine) return { messages };
|
|
13176
14022
|
try {
|
|
@@ -13180,7 +14026,8 @@ ${finalText}` };
|
|
|
13180
14026
|
contextLength: this.config.contextLength,
|
|
13181
14027
|
...instruction ? { instruction } : {},
|
|
13182
14028
|
...plan ? { plan } : {},
|
|
13183
|
-
...
|
|
14029
|
+
...force ? { force } : {},
|
|
14030
|
+
...promptTokens3 === void 0 ? {} : { promptTokens: promptTokens3 }
|
|
13184
14031
|
});
|
|
13185
14032
|
const bill = {
|
|
13186
14033
|
...compressed.usage ? { usage: compressed.usage } : {},
|
|
@@ -13397,6 +14244,9 @@ var CompressionSchema = z.object({
|
|
|
13397
14244
|
enabled: z.boolean().default(true),
|
|
13398
14245
|
threshold: z.number().gt(0).max(1).default(DEFAULT_COMPRESSION_THRESHOLD)
|
|
13399
14246
|
});
|
|
14247
|
+
var LimitsSchema = z.object({
|
|
14248
|
+
maxRequestImageBytes: z.int().positive().optional()
|
|
14249
|
+
});
|
|
13400
14250
|
var DEFAULT_MEMORY_CHAR_LIMIT = 2e4;
|
|
13401
14251
|
var DEFAULT_USER_CHAR_LIMIT = 6e3;
|
|
13402
14252
|
var DEFAULT_MEMORY_INDEX_CHAR_LIMIT = 4e3;
|
|
@@ -13408,6 +14258,9 @@ var MemorySchema = z.object({
|
|
|
13408
14258
|
var SandboxSchema = z.object({
|
|
13409
14259
|
terminal: z.boolean().default(true)
|
|
13410
14260
|
});
|
|
14261
|
+
var DelegateSchema = z.object({
|
|
14262
|
+
taskTimeoutSec: z.int().nonnegative().default(900)
|
|
14263
|
+
});
|
|
13411
14264
|
var ToolsSchema = z.object({
|
|
13412
14265
|
deferMcp: z.boolean().default(false),
|
|
13413
14266
|
mode: z.enum(["tools", "both", "code"]).default("tools")
|
|
@@ -13484,7 +14337,8 @@ var BlankGreetingSchema = z.object({
|
|
|
13484
14337
|
});
|
|
13485
14338
|
var HostUserSchema = z.object({
|
|
13486
14339
|
label: z.string().min(1),
|
|
13487
|
-
icon: z.string().min(1).optional()
|
|
14340
|
+
icon: z.string().min(1).optional(),
|
|
14341
|
+
avatar: z.string().min(1).optional()
|
|
13488
14342
|
});
|
|
13489
14343
|
var ArtifactsSchema = z.object({
|
|
13490
14344
|
maxAgeDays: z.int().positive().max(3650).default(ARTIFACT_RETENTION_DEFAULTS.maxAgeDays),
|
|
@@ -13515,7 +14369,17 @@ var EpochConfigSchema = z.object({
|
|
|
13515
14369
|
maxOutputTokens: z.int().positive().optional(),
|
|
13516
14370
|
homeDir: z.string().min(1).default(() => resolveHomeDir()),
|
|
13517
14371
|
dbPath: z.string().min(1).default(() => dbPath(resolveHomeDir())),
|
|
13518
|
-
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),
|
|
13519
14383
|
permissions: z.object({
|
|
13520
14384
|
allow: z.array(z.string().min(1)).optional(),
|
|
13521
14385
|
ask: z.array(z.string().min(1)).optional(),
|
|
@@ -13528,9 +14392,11 @@ var EpochConfigSchema = z.object({
|
|
|
13528
14392
|
hooks: z.record(z.string(), z.unknown()).optional(),
|
|
13529
14393
|
trust: TrustSchema.optional(),
|
|
13530
14394
|
sandbox: SandboxSchema.prefault({}),
|
|
14395
|
+
delegate: DelegateSchema.prefault({}),
|
|
13531
14396
|
tools: ToolsSchema.prefault({}),
|
|
13532
14397
|
skills: SkillsSchema.optional(),
|
|
13533
14398
|
compression: CompressionSchema.prefault({}),
|
|
14399
|
+
limits: LimitsSchema.prefault({}),
|
|
13534
14400
|
memory: MemorySchema.prefault({}),
|
|
13535
14401
|
artifacts: ArtifactsSchema.prefault({}),
|
|
13536
14402
|
sessions: SessionsSchema.prefault({}),
|
|
@@ -13562,6 +14428,7 @@ var EpochConfigSchema = z.object({
|
|
|
13562
14428
|
message: "blankCards: id must be unique"
|
|
13563
14429
|
}).optional(),
|
|
13564
14430
|
blankGreeting: BlankGreetingSchema.optional(),
|
|
14431
|
+
scheduleRemoveConfirm: HostTextSchema.optional(),
|
|
13565
14432
|
user: HostUserSchema.optional(),
|
|
13566
14433
|
settingsHidden: z.array(z.string().min(1)).min(1).optional(),
|
|
13567
14434
|
settingsPanes: z.array(
|
|
@@ -13604,6 +14471,22 @@ function settingsPaneBeforeIssues(config) {
|
|
|
13604
14471
|
message: `unknown settings pane id: ${String(pane.before)} (known: ${SETTINGS_PANE_IDS.join(", ")})`
|
|
13605
14472
|
}));
|
|
13606
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
|
+
}
|
|
13607
14490
|
function defaultConfig() {
|
|
13608
14491
|
return EpochConfigSchema.parse({});
|
|
13609
14492
|
}
|
|
@@ -13737,7 +14620,7 @@ var ManagedPolicyError = class extends Error {
|
|
|
13737
14620
|
}
|
|
13738
14621
|
};
|
|
13739
14622
|
function assertLevelAllowed(level, policy) {
|
|
13740
|
-
if (level !== "
|
|
14623
|
+
if (approvalPolicyForLevel(level) !== "never" || !policy.disableBypassPermissionsMode) return;
|
|
13741
14624
|
throw new ManagedPolicyError(
|
|
13742
14625
|
t("managed_settings.bypass_blocked"),
|
|
13743
14626
|
t("managed_settings.bypass_blocked_hint", { path: policy.path })
|
|
@@ -14042,18 +14925,18 @@ function _loadImpl(overrideHomeDir) {
|
|
|
14042
14925
|
if (read.kind === "corrupt" && _lastKnownGood?.homeDir === homeDir) {
|
|
14043
14926
|
_lastIssues = issues;
|
|
14044
14927
|
_lastOrigins = _lastKnownGood.origins;
|
|
14045
|
-
const
|
|
14928
|
+
const cached2 = _lastKnownGood;
|
|
14046
14929
|
_cache = {
|
|
14047
14930
|
homeDir,
|
|
14048
14931
|
mtime,
|
|
14049
14932
|
size,
|
|
14050
14933
|
entriesStamp,
|
|
14051
14934
|
envSnapshot,
|
|
14052
|
-
config:
|
|
14935
|
+
config: cached2.config,
|
|
14053
14936
|
issues,
|
|
14054
|
-
origins:
|
|
14937
|
+
origins: cached2.origins
|
|
14055
14938
|
};
|
|
14056
|
-
return
|
|
14939
|
+
return cached2.config;
|
|
14057
14940
|
}
|
|
14058
14941
|
const config = parseRawConfig(read.raw, issues, track);
|
|
14059
14942
|
reportDroppedEnv(issues);
|
|
@@ -14109,6 +14992,7 @@ function parseRawConfig(raw, issues, track) {
|
|
|
14109
14992
|
issues.push(...outcome.issues);
|
|
14110
14993
|
issues.push(...settingsHiddenIssues(outcome.value));
|
|
14111
14994
|
issues.push(...settingsPaneBeforeIssues(outcome.value));
|
|
14995
|
+
issues.push(...scheduleRemoveConfirmIssues(outcome.value));
|
|
14112
14996
|
if (outcome.issues.length === 0) collectKeyPaths(cleaned, track.file);
|
|
14113
14997
|
return outcome.value;
|
|
14114
14998
|
}
|
|
@@ -14239,8 +15123,9 @@ function applyEnvOverrides(config, issues, track) {
|
|
|
14239
15123
|
} else issues.push(envIssue("EPOCH_LOG_LEVEL", env.EPOCH_LOG_LEVEL, levels.join(" / ")));
|
|
14240
15124
|
}
|
|
14241
15125
|
if (env.EPOCH_PERMISSION) {
|
|
14242
|
-
|
|
14243
|
-
|
|
15126
|
+
const level = resolvePermissionLevel(env.EPOCH_PERMISSION);
|
|
15127
|
+
if (level) {
|
|
15128
|
+
config.permission = level;
|
|
14244
15129
|
track.env.add("permission");
|
|
14245
15130
|
} else {
|
|
14246
15131
|
issues.push(
|
|
@@ -14750,11 +15635,11 @@ function buildPricing(prompt, completion, cacheRead) {
|
|
|
14750
15635
|
const output = Number.parseFloat(completion) * 1e6;
|
|
14751
15636
|
if (!Number.isFinite(input) || !Number.isFinite(output)) return void 0;
|
|
14752
15637
|
if (input <= 0 && output <= 0) return void 0;
|
|
14753
|
-
const
|
|
15638
|
+
const cached2 = cacheRead ? Number.parseFloat(cacheRead) * 1e6 : NaN;
|
|
14754
15639
|
return {
|
|
14755
15640
|
inputPerMTok: input,
|
|
14756
15641
|
outputPerMTok: output,
|
|
14757
|
-
...Number.isFinite(
|
|
15642
|
+
...Number.isFinite(cached2) && cached2 > 0 ? { cachedInputPerMTok: cached2 } : {}
|
|
14758
15643
|
};
|
|
14759
15644
|
}
|
|
14760
15645
|
function matchesWindow(o, at) {
|
|
@@ -14971,6 +15856,30 @@ var TOOL_RESULT_MEDIA = {
|
|
|
14971
15856
|
function acceptsToolResultMedia(type) {
|
|
14972
15857
|
return TOOL_RESULT_MEDIA[type];
|
|
14973
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
|
+
}
|
|
14974
15883
|
function isModuleNotFound(err) {
|
|
14975
15884
|
if (!err || typeof err !== "object") return false;
|
|
14976
15885
|
const code = err.code;
|
|
@@ -14979,9 +15888,10 @@ function isModuleNotFound(err) {
|
|
|
14979
15888
|
return /Cannot find (module|package)|Failed to resolve/i.test(msg);
|
|
14980
15889
|
}
|
|
14981
15890
|
// src/provider/entry-route.ts
|
|
14982
|
-
function buildEntryTable(entries2) {
|
|
15891
|
+
function buildEntryTable(entries2, homeDir) {
|
|
14983
15892
|
return {
|
|
14984
|
-
entries: new Map((entries2 ?? []).map((e) => [e.id, e]))
|
|
15893
|
+
entries: new Map((entries2 ?? []).map((e) => [e.id, e])),
|
|
15894
|
+
...homeDir ? { homeDir } : {}
|
|
14985
15895
|
};
|
|
14986
15896
|
}
|
|
14987
15897
|
function entryProvider(_table, entry) {
|
|
@@ -15016,6 +15926,14 @@ function entryAcceptsToolMedia(table, provider, entry) {
|
|
|
15016
15926
|
if (e?.provider === "openai-compatible" && e.protocol === "anthropic-messages") return true;
|
|
15017
15927
|
return acceptsToolResultMedia(provider);
|
|
15018
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
|
+
}
|
|
15019
15937
|
function capabilityOfRef(config, ref = config.model) {
|
|
15020
15938
|
const parsed = ref ? parseModelRef(ref) : void 0;
|
|
15021
15939
|
const entry = parsed ? config.modelEntries?.find((e) => e.id === parsed.entry) : void 0;
|
|
@@ -15183,7 +16101,7 @@ var ProviderRouter = class {
|
|
|
15183
16101
|
}
|
|
15184
16102
|
constructor(config) {
|
|
15185
16103
|
this.config = config;
|
|
15186
|
-
this.entryTable = buildEntryTable(config.modelEntries);
|
|
16104
|
+
this.entryTable = buildEntryTable(config.modelEntries, config.homeDir);
|
|
15187
16105
|
this.configSelection = this.resolveConfigured(config);
|
|
15188
16106
|
this.initFactories();
|
|
15189
16107
|
this.selection = { ...this.configSelection };
|
|
@@ -15234,7 +16152,7 @@ var ProviderRouter = class {
|
|
|
15234
16152
|
return result;
|
|
15235
16153
|
}
|
|
15236
16154
|
reloadModelEntries(entries2) {
|
|
15237
|
-
this.entryTable = buildEntryTable(entries2);
|
|
16155
|
+
this.entryTable = buildEntryTable(entries2, this.config.homeDir);
|
|
15238
16156
|
for (const [route, opts] of [...this.available]) {
|
|
15239
16157
|
if (!opts.entry) continue;
|
|
15240
16158
|
this.available.delete(route);
|
|
@@ -15383,8 +16301,8 @@ var ProviderRouter = class {
|
|
|
15383
16301
|
return { selection, configured: true };
|
|
15384
16302
|
}
|
|
15385
16303
|
async getModel(route, modelId) {
|
|
15386
|
-
const
|
|
15387
|
-
if (
|
|
16304
|
+
const cached2 = this.factories.get(route);
|
|
16305
|
+
if (cached2) return cached2(modelId ?? this.selection.model);
|
|
15388
16306
|
const opts = this.available.get(route);
|
|
15389
16307
|
if (!opts) {
|
|
15390
16308
|
throw new ProviderError(
|
|
@@ -15494,7 +16412,7 @@ var ProviderRouter = class {
|
|
|
15494
16412
|
const state = this.startPoint(input);
|
|
15495
16413
|
const requestedModel = state.cm;
|
|
15496
16414
|
const messagesFor = messageTranslator(input.messages, this.entryTable);
|
|
15497
|
-
const tools = input.tools ? toSdkTools(input.tools) : void 0;
|
|
16415
|
+
const tools = input.tools ? toSdkTools(input.tools, { cacheBreakpoint: true }) : void 0;
|
|
15498
16416
|
const output = input.responseFormat ? toOutputSpec(input.responseFormat) : void 0;
|
|
15499
16417
|
for (; ; ) {
|
|
15500
16418
|
if (state.attempt > this.config.retry.maxRetries) {
|
|
@@ -15568,7 +16486,7 @@ var ProviderRouter = class {
|
|
|
15568
16486
|
const requestedModel = state.cm;
|
|
15569
16487
|
let emitted = false;
|
|
15570
16488
|
const messagesFor = messageTranslator(input.messages, this.entryTable);
|
|
15571
|
-
const tools = input.tools ? toSdkTools(input.tools) : void 0;
|
|
16489
|
+
const tools = input.tools ? toSdkTools(input.tools, { cacheBreakpoint: true }) : void 0;
|
|
15572
16490
|
const output = input.responseFormat ? toOutputSpec(input.responseFormat) : void 0;
|
|
15573
16491
|
let streamPartError;
|
|
15574
16492
|
for (; ; ) {
|
|
@@ -15705,8 +16623,8 @@ var ProviderRouter = class {
|
|
|
15705
16623
|
async probeImageSupport() {
|
|
15706
16624
|
const { provider, model, entry } = this.selection;
|
|
15707
16625
|
const home = this.config.homeDir;
|
|
15708
|
-
const
|
|
15709
|
-
if (
|
|
16626
|
+
const cached2 = readImageProbe(home, provider, model);
|
|
16627
|
+
if (cached2 !== void 0) return cached2;
|
|
15710
16628
|
let lm;
|
|
15711
16629
|
try {
|
|
15712
16630
|
lm = await this.getModel(this.routeOf(provider, entry), model);
|
|
@@ -15734,10 +16652,12 @@ function messageTranslator(messages, table) {
|
|
|
15734
16652
|
const cache = /* @__PURE__ */ new Map();
|
|
15735
16653
|
return (type, entry) => {
|
|
15736
16654
|
const inline = entryAcceptsToolMedia(table, type, entry);
|
|
15737
|
-
|
|
16655
|
+
const reasoning = entryCarriesReasoningBack(table, type, entry);
|
|
16656
|
+
const key = `${inline}|${reasoning}`;
|
|
16657
|
+
let hit = cache.get(key);
|
|
15738
16658
|
if (!hit) {
|
|
15739
|
-
hit = toModelMessages(messages, { toolMediaInline: inline });
|
|
15740
|
-
cache.set(
|
|
16659
|
+
hit = toModelMessages(messages, { toolMediaInline: inline, reasoning });
|
|
16660
|
+
cache.set(key, hit);
|
|
15741
16661
|
}
|
|
15742
16662
|
return hit;
|
|
15743
16663
|
};
|
|
@@ -15808,12 +16728,12 @@ var PROVIDER_DISCOVERY = {
|
|
|
15808
16728
|
function discoverySpec(provider) {
|
|
15809
16729
|
return PROVIDER_DISCOVERY[provider];
|
|
15810
16730
|
}
|
|
15811
|
-
function
|
|
16731
|
+
function cachePath2(homeDir, provider) {
|
|
15812
16732
|
return join(homeDir, "cache", `models_${provider}.json`);
|
|
15813
16733
|
}
|
|
15814
16734
|
function loadCache2(homeDir, provider) {
|
|
15815
16735
|
try {
|
|
15816
|
-
const path =
|
|
16736
|
+
const path = cachePath2(homeDir, provider);
|
|
15817
16737
|
if (!existsSync(path)) return null;
|
|
15818
16738
|
const data = JSON.parse(readFileSync(path, "utf-8"));
|
|
15819
16739
|
const age = Date.now() - (data._cachedAt ?? 0);
|
|
@@ -15828,7 +16748,7 @@ function saveCache2(homeDir, provider, models) {
|
|
|
15828
16748
|
const dir = join(homeDir, "cache");
|
|
15829
16749
|
mkdirSync(dir, { recursive: true });
|
|
15830
16750
|
writeFileSync(
|
|
15831
|
-
|
|
16751
|
+
cachePath2(homeDir, provider),
|
|
15832
16752
|
JSON.stringify({ models, _cachedAt: Date.now() }),
|
|
15833
16753
|
"utf-8"
|
|
15834
16754
|
);
|
|
@@ -15907,13 +16827,13 @@ async function discoverModels(homeDir, provider, apiKey, baseUrl) {
|
|
|
15907
16827
|
}
|
|
15908
16828
|
}
|
|
15909
16829
|
}
|
|
15910
|
-
const
|
|
15911
|
-
if (
|
|
16830
|
+
const cached2 = loadCache2(homeDir, provider);
|
|
16831
|
+
if (cached2) return { models: cached2, source: "cache" };
|
|
15912
16832
|
return { models: STATIC_MODEL_CATALOG[provider] ?? [], source: "static" };
|
|
15913
16833
|
}
|
|
15914
16834
|
function clearModelCache(homeDir, provider) {
|
|
15915
16835
|
try {
|
|
15916
|
-
const path =
|
|
16836
|
+
const path = cachePath2(homeDir, provider);
|
|
15917
16837
|
if (existsSync(path)) writeFileSync(path, "{}", "utf-8");
|
|
15918
16838
|
} catch {
|
|
15919
16839
|
}
|
|
@@ -16110,7 +17030,10 @@ var VALUE_SCHEMA = {
|
|
|
16110
17030
|
"automation.keepRuns": EpochConfigSchema.shape.automation.unwrap().shape.keepRuns.unwrap(),
|
|
16111
17031
|
"automation.maxRecordingMb": EpochConfigSchema.shape.automation.unwrap().shape.maxRecordingMb.unwrap(),
|
|
16112
17032
|
"sessionSearch.allWorkspaces": EpochConfigSchema.shape.sessionSearch.unwrap().shape.allWorkspaces.unwrap(),
|
|
16113
|
-
permission: EpochConfigSchema.shape.permission
|
|
17033
|
+
permission: EpochConfigSchema.shape.permission
|
|
17034
|
+
};
|
|
17035
|
+
var ENUM_CHOICES = {
|
|
17036
|
+
permission: PERMISSION_LEVELS
|
|
16114
17037
|
};
|
|
16115
17038
|
function settingValueKind(key) {
|
|
16116
17039
|
if (!isWritableSettingKey(key)) return null;
|
|
@@ -16121,6 +17044,8 @@ function settingValueKind(key) {
|
|
|
16121
17044
|
}
|
|
16122
17045
|
function settingValueChoices(key) {
|
|
16123
17046
|
if (!isWritableSettingKey(key)) return null;
|
|
17047
|
+
const explicit = ENUM_CHOICES[key];
|
|
17048
|
+
if (explicit) return explicit;
|
|
16124
17049
|
const schema = VALUE_SCHEMA[key];
|
|
16125
17050
|
if (schema.def.type !== "enum") return null;
|
|
16126
17051
|
return Object.values(schema.def.entries).map(String);
|
|
@@ -16263,6 +17188,7 @@ function commit(path, body2, createMode, value) {
|
|
|
16263
17188
|
}
|
|
16264
17189
|
return { ok: true, value };
|
|
16265
17190
|
}
|
|
17191
|
+
var MACHINE_DEPENDENT_DEFAULTS = ["homeDir", "dbPath"];
|
|
16266
17192
|
var DESCRIPTIONS = {
|
|
16267
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",
|
|
16268
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",
|
|
@@ -16273,7 +17199,112 @@ var DESCRIPTIONS = {
|
|
|
16273
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",
|
|
16274
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",
|
|
16275
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",
|
|
16276
|
-
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"
|
|
16277
17308
|
};
|
|
16278
17309
|
function buildSchemaExports() {
|
|
16279
17310
|
const used = /* @__PURE__ */ new Set();
|
|
@@ -16299,6 +17330,24 @@ function buildSchemaExports() {
|
|
|
16299
17330
|
},
|
|
16300
17331
|
used
|
|
16301
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
|
+
)
|
|
16302
17351
|
}
|
|
16303
17352
|
];
|
|
16304
17353
|
const stale = Object.keys(DESCRIPTIONS).filter((key) => !used.has(key));
|
|
@@ -16309,13 +17358,22 @@ function buildSchemaExports() {
|
|
|
16309
17358
|
}
|
|
16310
17359
|
return exports;
|
|
16311
17360
|
}
|
|
17361
|
+
var EXPLICIT_ENUMS = {
|
|
17362
|
+
permission: PERMISSION_LEVELS
|
|
17363
|
+
};
|
|
16312
17364
|
function document(schema, meta, used) {
|
|
16313
|
-
const generated = z.toJSONSchema(schema);
|
|
17365
|
+
const generated = meta.io ? z.toJSONSchema(schema, { io: meta.io }) : z.toJSONSchema(schema);
|
|
16314
17366
|
const dialect = generated.$schema;
|
|
16315
17367
|
const properties = {
|
|
16316
17368
|
$schema: { type: "string" },
|
|
17369
|
+
...meta.extra,
|
|
16317
17370
|
...generated.properties
|
|
16318
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
|
+
}
|
|
16319
17377
|
const doc = {
|
|
16320
17378
|
$schema: dialect,
|
|
16321
17379
|
title: meta.title,
|
|
@@ -16339,10 +17397,138 @@ function annotate(node, path, used) {
|
|
|
16339
17397
|
);
|
|
16340
17398
|
}
|
|
16341
17399
|
child.description = text;
|
|
17400
|
+
if (MACHINE_DEPENDENT_DEFAULTS.includes(full)) delete child.default;
|
|
16342
17401
|
used.add(full);
|
|
16343
17402
|
annotate(child, full, used);
|
|
16344
17403
|
}
|
|
16345
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
|
+
}
|
|
16346
17532
|
var MODULE2 = "Keybindings";
|
|
16347
17533
|
var VIM_MODE_KEY = "vimMode";
|
|
16348
17534
|
var FileSchema = z.record(z.string(), z.array(z.string()));
|
|
@@ -16537,11 +17723,11 @@ function buildSearchQuery(query) {
|
|
|
16537
17723
|
}
|
|
16538
17724
|
const latinPart = cleaned.replace(CJK_RUN, " ");
|
|
16539
17725
|
for (const w of latinPart.split(/\s+/)) {
|
|
16540
|
-
const
|
|
16541
|
-
if (
|
|
17726
|
+
const t83 = w.trim();
|
|
17727
|
+
if (t83.length >= 2) terms.add(t83);
|
|
16542
17728
|
}
|
|
16543
17729
|
if (terms.size === 0) return null;
|
|
16544
|
-
return [...terms].map((
|
|
17730
|
+
return [...terms].map((t83) => `"${t83.replace(/"/g, "")}"`).join(" OR ");
|
|
16545
17731
|
}
|
|
16546
17732
|
// src/memory/db.ts
|
|
16547
17733
|
var NS2 = "memory";
|
|
@@ -17032,8 +18218,8 @@ var MemoryManager = class {
|
|
|
17032
18218
|
async add(target, content) {
|
|
17033
18219
|
const label = injectionLabelOf(content);
|
|
17034
18220
|
if (label !== void 0) return this.refuseInjection(label);
|
|
17035
|
-
const
|
|
17036
|
-
if (
|
|
18221
|
+
const budget = this.getBudget()[target];
|
|
18222
|
+
if (budget.current + content.length > budget.limit) {
|
|
17037
18223
|
this.consolidationFailures++;
|
|
17038
18224
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
17039
18225
|
return {
|
|
@@ -17080,9 +18266,9 @@ var MemoryManager = class {
|
|
|
17080
18266
|
}
|
|
17081
18267
|
const label = injectionLabelOf(content);
|
|
17082
18268
|
if (label !== void 0) return this.refuseInjection(label);
|
|
17083
|
-
const
|
|
18269
|
+
const budget = this.getBudget()[target];
|
|
17084
18270
|
const delta = content.length - existing.charLength;
|
|
17085
|
-
if (
|
|
18271
|
+
if (budget.current + delta > budget.limit) {
|
|
17086
18272
|
this.consolidationFailures++;
|
|
17087
18273
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
17088
18274
|
return { success: false, done: true, error: "Consolidation limit reached" };
|
|
@@ -17287,11 +18473,11 @@ var MemoryManager = class {
|
|
|
17287
18473
|
for (const target of ["memory", "user"]) {
|
|
17288
18474
|
const rows = kept.filter((e) => e.target === target);
|
|
17289
18475
|
if (rows.length === 0) continue;
|
|
17290
|
-
const
|
|
18476
|
+
const budget = this.getBudget()[target];
|
|
17291
18477
|
const label = target === "user" ? "USER PROFILE (who the user is)" : "MEMORY (your personal notes)";
|
|
17292
18478
|
sections.push(
|
|
17293
18479
|
[
|
|
17294
|
-
`${label} [${rows.length} entries \xB7 ${
|
|
18480
|
+
`${label} [${rows.length} entries \xB7 ${budget.current.toLocaleString()}/${budget.limit.toLocaleString()} chars]`,
|
|
17295
18481
|
...rows.map((e) => this.indexLine(e))
|
|
17296
18482
|
].join("\n")
|
|
17297
18483
|
);
|
|
@@ -17322,7 +18508,7 @@ var MemoryManager = class {
|
|
|
17322
18508
|
return `${e.id} ${e.summary} (${e.charLength} chars)`;
|
|
17323
18509
|
}
|
|
17324
18510
|
buildConsolidateHint(target) {
|
|
17325
|
-
const
|
|
18511
|
+
const budget = this.getBudget()[target];
|
|
17326
18512
|
const heat = /* @__PURE__ */ new Map();
|
|
17327
18513
|
for (const row of this.db.getAll(target)) {
|
|
17328
18514
|
const id = this.idByContent.get(contentKey(row.target, row.content));
|
|
@@ -17330,7 +18516,7 @@ var MemoryManager = class {
|
|
|
17330
18516
|
}
|
|
17331
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);
|
|
17332
18518
|
return [
|
|
17333
|
-
`Memory at ${
|
|
18519
|
+
`Memory at ${budget.current.toLocaleString()}/${budget.limit.toLocaleString()} chars (${budget.percent}%) for ${target}. Cannot add new entry.`,
|
|
17334
18520
|
"",
|
|
17335
18521
|
"To make room, work by id \u2014 NOT by old_text. The MEMORY INDEX only shows a truncated",
|
|
17336
18522
|
"first line, so text copied from it will never match an entry exactly.",
|
|
@@ -18172,6 +19358,10 @@ var SessionDB = class {
|
|
|
18172
19358
|
where += " AND cwd = @cwd";
|
|
18173
19359
|
params["cwd"] = input.cwd;
|
|
18174
19360
|
}
|
|
19361
|
+
if (!input.includeDelegate) {
|
|
19362
|
+
where += " AND COALESCE(source, '') != @delegateSource";
|
|
19363
|
+
params["delegateSource"] = DELEGATE_SESSION_SOURCE;
|
|
19364
|
+
}
|
|
18175
19365
|
if (input.updatedSince !== void 0) {
|
|
18176
19366
|
where += " AND COALESCE(updated_at, started_at) > @updatedSince";
|
|
18177
19367
|
params["updatedSince"] = input.updatedSince;
|
|
@@ -18232,8 +19422,8 @@ var SessionDB = class {
|
|
|
18232
19422
|
const todo = this.db.prepare(
|
|
18233
19423
|
"INSERT INTO todos (id, session_id, content, status, reason, created_at, updated_at) VALUES (@id, @sessionId, @content, @status, @reason, @createdAt, @updatedAt)"
|
|
18234
19424
|
);
|
|
18235
|
-
for (const
|
|
18236
|
-
todo.run({ ...
|
|
19425
|
+
for (const t83 of extras.todos ?? []) {
|
|
19426
|
+
todo.run({ ...t83, sessionId: m.id, reason: t83.reason || null });
|
|
18237
19427
|
}
|
|
18238
19428
|
}
|
|
18239
19429
|
const g = extras.goal;
|
|
@@ -18387,57 +19577,25 @@ var SessionDB = class {
|
|
|
18387
19577
|
searchContent(query, limit) {
|
|
18388
19578
|
const safeQuery = sanitizeFtsQuery(query);
|
|
18389
19579
|
if (!safeQuery) return [];
|
|
18390
|
-
const
|
|
18391
|
-
const ftsRows = this.db.prepare(
|
|
18392
|
-
`
|
|
19580
|
+
const sql = (table) => `
|
|
18393
19581
|
SELECT m.*, s.title as session_title
|
|
18394
|
-
|
|
18395
|
-
JOIN messages m ON f.rowid = m.id
|
|
18396
|
-
JOIN sessions s ON m.session_id = s.id
|
|
18397
|
-
WHERE messages_fts MATCH @query AND s.archived = 0
|
|
18398
|
-
ORDER BY rank
|
|
18399
|
-
LIMIT @limit
|
|
18400
|
-
`
|
|
18401
|
-
).all({
|
|
18402
|
-
query: ftsQuery,
|
|
18403
|
-
limit: limit * 3
|
|
18404
|
-
});
|
|
18405
|
-
if (ftsRows.length === 0) {
|
|
18406
|
-
const trigramRows = this.db.prepare(
|
|
18407
|
-
`
|
|
18408
|
-
SELECT m.*, s.title as session_title
|
|
18409
|
-
FROM messages_fts_trigram f
|
|
19582
|
+
FROM ${table} f
|
|
18410
19583
|
JOIN messages m ON f.rowid = m.id
|
|
18411
19584
|
JOIN sessions s ON m.session_id = s.id
|
|
18412
|
-
|
|
18413
|
-
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18417
|
-
|
|
18418
|
-
|
|
18419
|
-
|
|
18420
|
-
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
if (results2.length >= limit) break;
|
|
18424
|
-
results2.push({
|
|
18425
|
-
session: this.getSessionMeta(sid),
|
|
18426
|
-
matches: [
|
|
18427
|
-
{
|
|
18428
|
-
messageIndex: r["id"],
|
|
18429
|
-
snippet: String(r["content"] ?? "").slice(0, 200),
|
|
18430
|
-
score: 1
|
|
18431
|
-
}
|
|
18432
|
-
],
|
|
18433
|
-
score: 1
|
|
18434
|
-
});
|
|
18435
|
-
}
|
|
18436
|
-
return results2;
|
|
18437
|
-
}
|
|
19585
|
+
WHERE ${table} MATCH @query AND s.archived = 0
|
|
19586
|
+
ORDER BY rank
|
|
19587
|
+
LIMIT @limit`;
|
|
19588
|
+
const candidates2 = limit * 3;
|
|
19589
|
+
const rowsFor = (table, match) => this.db.prepare(sql(table)).all({ query: match, limit: candidates2 });
|
|
19590
|
+
const porter = rowsFor("messages_fts", buildFtsMatchQuery(safeQuery));
|
|
19591
|
+
const rows = belowTrigramFloor(safeQuery) ? porter : mergeRankedRows(
|
|
19592
|
+
porter,
|
|
19593
|
+
rowsFor("messages_fts_trigram", buildTrigramMatchQuery(safeQuery)),
|
|
19594
|
+
candidates2
|
|
19595
|
+
);
|
|
18438
19596
|
const seen = /* @__PURE__ */ new Set();
|
|
18439
19597
|
const results = [];
|
|
18440
|
-
for (const r of
|
|
19598
|
+
for (const r of rows) {
|
|
18441
19599
|
const sid = r["session_id"];
|
|
18442
19600
|
if (seen.has(sid)) continue;
|
|
18443
19601
|
seen.add(sid);
|
|
@@ -18446,7 +19604,7 @@ var SessionDB = class {
|
|
|
18446
19604
|
session: this.getSessionMeta(sid),
|
|
18447
19605
|
matches: [
|
|
18448
19606
|
{
|
|
18449
|
-
messageIndex: r
|
|
19607
|
+
messageIndex: r.id,
|
|
18450
19608
|
snippet: String(r["content"] ?? "").slice(0, 200),
|
|
18451
19609
|
score: 1
|
|
18452
19610
|
}
|
|
@@ -18523,6 +19681,26 @@ var SessionDB = class {
|
|
|
18523
19681
|
duration: 0
|
|
18524
19682
|
};
|
|
18525
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
|
+
}
|
|
18526
19704
|
archiveAndCompact(sessionId, input) {
|
|
18527
19705
|
const run = this.db.transaction(() => {
|
|
18528
19706
|
const rows = this.db.prepare(
|
|
@@ -18745,7 +19923,7 @@ function checkFtsHealth(db) {
|
|
|
18745
19923
|
messages,
|
|
18746
19924
|
tables,
|
|
18747
19925
|
missingTriggers,
|
|
18748
|
-
healthy: missingTriggers.length === 0 && tables.every((
|
|
19926
|
+
healthy: missingTriggers.length === 0 && tables.every((t83) => t83.error === null && t83.drift === null && t83.rows === messages),
|
|
18749
19927
|
indexBytes: indexBytesOf(db),
|
|
18750
19928
|
space: spaceOf(db)
|
|
18751
19929
|
};
|
|
@@ -18895,10 +20073,10 @@ var AUTO_VACUUM_MIN_FREELIST_RATIO = 0.25;
|
|
|
18895
20073
|
var IMPORT_ROLES = /* @__PURE__ */ new Set(["system", "user", "assistant", "tool"]);
|
|
18896
20074
|
var TODO_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
|
|
18897
20075
|
function validateImportExtras(input) {
|
|
18898
|
-
for (const [i,
|
|
18899
|
-
if (typeof
|
|
18900
|
-
if (!TODO_STATUSES.has(
|
|
18901
|
-
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`;
|
|
18902
20080
|
}
|
|
18903
20081
|
const g = input.goal;
|
|
18904
20082
|
if (g === void 0) return void 0;
|
|
@@ -19087,7 +20265,7 @@ var SessionManager = class {
|
|
|
19087
20265
|
converted.push({ ...rest, parts: result.parts });
|
|
19088
20266
|
}
|
|
19089
20267
|
const droppedParentId = meta.parentId !== void 0 && !this.db.hasSession(meta.parentId) ? meta.parentId : void 0;
|
|
19090
|
-
const todos = (input.todos ?? []).map((
|
|
20268
|
+
const todos = (input.todos ?? []).map((t83) => ({ ...t83, id: this.db.freshTodoId() }));
|
|
19091
20269
|
const goal = input.goal === void 0 ? void 0 : { ...input.goal, id: `goal_${randomUUID().replace(/-/g, "")}` };
|
|
19092
20270
|
try {
|
|
19093
20271
|
const newIds = this.db.importSession(
|
|
@@ -19105,7 +20283,7 @@ var SessionManager = class {
|
|
|
19105
20283
|
messageCount: newIds.length,
|
|
19106
20284
|
idMap,
|
|
19107
20285
|
...droppedParentId === void 0 ? {} : { droppedParentId },
|
|
19108
|
-
...input.todos === void 0 ? {} : { todoIds: todos.map((
|
|
20286
|
+
...input.todos === void 0 ? {} : { todoIds: todos.map((t83) => t83.id) },
|
|
19109
20287
|
...goal === void 0 ? {} : { goalId: goal.id }
|
|
19110
20288
|
};
|
|
19111
20289
|
} catch (err) {
|
|
@@ -19252,6 +20430,9 @@ var SessionManager = class {
|
|
|
19252
20430
|
const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize, summarize2) ?? outlineOf(toSummarize);
|
|
19253
20431
|
return this.db.compact(sessionId, summary, beforeCount, IMPORTANT_ROUNDS * 2);
|
|
19254
20432
|
}
|
|
20433
|
+
offloadImageParts(sessionId) {
|
|
20434
|
+
return this.db.offloadImageParts(sessionId);
|
|
20435
|
+
}
|
|
19255
20436
|
archiveAndCompact(sessionId, input) {
|
|
19256
20437
|
return this.db.archiveAndCompact(sessionId, input);
|
|
19257
20438
|
}
|
|
@@ -19447,8 +20628,8 @@ var GoalService = class {
|
|
|
19447
20628
|
const text = objective.trim();
|
|
19448
20629
|
if (!text) return { ok: false, reason: "empty-objective" };
|
|
19449
20630
|
if (text.length > MAX_OBJECTIVE_CHARS) return { ok: false, reason: "objective-too-long" };
|
|
19450
|
-
const
|
|
19451
|
-
if (!Number.isInteger(
|
|
20631
|
+
const budget = maxRounds ?? DEFAULT_GOAL_MAX_ROUNDS;
|
|
20632
|
+
if (!Number.isInteger(budget) || budget < 1 || budget > MAX_GOAL_MAX_ROUNDS) {
|
|
19452
20633
|
return { ok: false, reason: "bad-budget" };
|
|
19453
20634
|
}
|
|
19454
20635
|
const existing = this.current(sessionId);
|
|
@@ -19460,7 +20641,7 @@ var GoalService = class {
|
|
|
19460
20641
|
objective: text,
|
|
19461
20642
|
phase: "active",
|
|
19462
20643
|
block: void 0,
|
|
19463
|
-
maxRounds:
|
|
20644
|
+
maxRounds: budget,
|
|
19464
20645
|
roundsUsed: 0,
|
|
19465
20646
|
completeEvidence: void 0,
|
|
19466
20647
|
createdAt: at,
|
|
@@ -19605,7 +20786,7 @@ function withGoalCompression(engine, view) {
|
|
|
19605
20786
|
if (!now) return engine.compress(messages, config);
|
|
19606
20787
|
return engine.compress(messages, { ...config, goal: now.objective });
|
|
19607
20788
|
},
|
|
19608
|
-
shouldCompress: (
|
|
20789
|
+
shouldCompress: (promptTokens3, contextLength) => engine.shouldCompress(promptTokens3, contextLength),
|
|
19609
20790
|
trackUsage: (usage) => engine.trackUsage(usage),
|
|
19610
20791
|
getTotalTokens: () => engine.getTotalTokens(),
|
|
19611
20792
|
reset: () => engine.reset()
|
|
@@ -20000,7 +21181,7 @@ var AppearanceStore = class {
|
|
|
20000
21181
|
}
|
|
20001
21182
|
};
|
|
20002
21183
|
function ruleAskActive(level) {
|
|
20003
|
-
return level
|
|
21184
|
+
return approvalPolicyForLevel(level) === "ask";
|
|
20004
21185
|
}
|
|
20005
21186
|
function checkCodeExec(isolation) {
|
|
20006
21187
|
if (isolation === "os") {
|
|
@@ -20034,7 +21215,7 @@ function checkPlan(operation, extraRoots) {
|
|
|
20034
21215
|
code: "level-default"
|
|
20035
21216
|
};
|
|
20036
21217
|
}
|
|
20037
|
-
if (operation.type === "file_write"
|
|
21218
|
+
if (operation.type === "file_write") {
|
|
20038
21219
|
return { allowed: false, reason: t("permission_reason.plan_no_write"), code: "level-default" };
|
|
20039
21220
|
}
|
|
20040
21221
|
if (operation.type === "network") {
|
|
@@ -20044,6 +21225,10 @@ function checkPlan(operation, extraRoots) {
|
|
|
20044
21225
|
code: "level-default"
|
|
20045
21226
|
};
|
|
20046
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
|
+
}
|
|
20047
21232
|
return outsideWorkspace(operation, extraRoots) ?? { allowed: true, code: "level-default" };
|
|
20048
21233
|
}
|
|
20049
21234
|
function checkAcceptEdits(operation, isolation, extraRoots) {
|
|
@@ -20069,8 +21254,6 @@ function checkDefault(operation, extraRoots) {
|
|
|
20069
21254
|
}
|
|
20070
21255
|
function decideByLevel(level, operation, isolation, extraRoots = []) {
|
|
20071
21256
|
switch (level) {
|
|
20072
|
-
case "bypass":
|
|
20073
|
-
return { allowed: true, code: "level-default" };
|
|
20074
21257
|
case "auto":
|
|
20075
21258
|
return checkAuto();
|
|
20076
21259
|
case "plan":
|
|
@@ -20250,11 +21433,11 @@ var ApprovalCache = class {
|
|
|
20250
21433
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
20251
21434
|
}
|
|
20252
21435
|
normalizeTarget(target) {
|
|
20253
|
-
const
|
|
20254
|
-
if (!
|
|
20255
|
-
const unix =
|
|
21436
|
+
const t83 = target.trim();
|
|
21437
|
+
if (!t83) return "";
|
|
21438
|
+
const unix = t83.replace(/\\/g, "/");
|
|
20256
21439
|
if (unix.startsWith("/") || /^[A-Za-z]:\//.test(unix)) return resolve(unix);
|
|
20257
|
-
return
|
|
21440
|
+
return t83;
|
|
20258
21441
|
}
|
|
20259
21442
|
load() {
|
|
20260
21443
|
try {
|
|
@@ -20357,9 +21540,9 @@ function createSharedPermissionState(cache) {
|
|
|
20357
21540
|
};
|
|
20358
21541
|
}
|
|
20359
21542
|
function cacheKeyFor(raw) {
|
|
20360
|
-
const
|
|
20361
|
-
if (!
|
|
20362
|
-
return
|
|
21543
|
+
const t83 = raw.trim();
|
|
21544
|
+
if (!t83) return null;
|
|
21545
|
+
return t83.slice(0, 500);
|
|
20363
21546
|
}
|
|
20364
21547
|
// src/permission/manager.ts
|
|
20365
21548
|
var log3 = createLogger("permission");
|
|
@@ -20472,15 +21655,23 @@ var PermissionManager = class _PermissionManager {
|
|
|
20472
21655
|
code: hard.code
|
|
20473
21656
|
};
|
|
20474
21657
|
}
|
|
20475
|
-
|
|
21658
|
+
const neverAsk = approvalPolicyForLevel(this.level) === "never";
|
|
21659
|
+
if (neverAsk && hard.code === "obfuscated") {
|
|
20476
21660
|
return {
|
|
20477
21661
|
allowed: true,
|
|
20478
21662
|
reason: t("permission_reason.bypass_unaskable", { reason: hard.reason ?? "" }),
|
|
20479
21663
|
code: hard.code
|
|
20480
21664
|
};
|
|
20481
21665
|
}
|
|
20482
|
-
const
|
|
20483
|
-
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
|
+
}
|
|
20484
21675
|
if (this.shared.nonInteractive) {
|
|
20485
21676
|
return {
|
|
20486
21677
|
allowed: false,
|
|
@@ -20491,7 +21682,7 @@ var PermissionManager = class _PermissionManager {
|
|
|
20491
21682
|
return null;
|
|
20492
21683
|
}
|
|
20493
21684
|
approvalCacheActive() {
|
|
20494
|
-
return this.level
|
|
21685
|
+
return approvalPolicyForLevel(this.level) === "ask";
|
|
20495
21686
|
}
|
|
20496
21687
|
rememberFlag() {
|
|
20497
21688
|
return this.approvalCacheActive() ? {} : { rememberable: false };
|
|
@@ -20499,15 +21690,15 @@ var PermissionManager = class _PermissionManager {
|
|
|
20499
21690
|
cachedDecision(operation) {
|
|
20500
21691
|
const cacheTool = operation.toolName ?? operation.type;
|
|
20501
21692
|
const cacheKey = cacheKeyFor(operation.target || operation.detail);
|
|
20502
|
-
const
|
|
20503
|
-
if (
|
|
21693
|
+
const cached2 = cacheKey ? this.shared.cache.get(cacheTool, cacheKey) : null;
|
|
21694
|
+
if (cached2 === "allow-always" || cached2 === "allow-session") {
|
|
20504
21695
|
return {
|
|
20505
21696
|
allowed: true,
|
|
20506
21697
|
reason: t("permission_reason.cached_allow"),
|
|
20507
21698
|
code: "approval-cache"
|
|
20508
21699
|
};
|
|
20509
21700
|
}
|
|
20510
|
-
if (
|
|
21701
|
+
if (cached2 === "deny") {
|
|
20511
21702
|
return {
|
|
20512
21703
|
allowed: false,
|
|
20513
21704
|
reason: t("permission_reason.cached_deny"),
|
|
@@ -20530,8 +21721,8 @@ var PermissionManager = class _PermissionManager {
|
|
|
20530
21721
|
if (ruleDecision && !ruleDecision.allowed && !ruleDecision.requireApproval) {
|
|
20531
21722
|
return ruleDecision;
|
|
20532
21723
|
}
|
|
20533
|
-
const
|
|
20534
|
-
if (
|
|
21724
|
+
const cached2 = this.approvalCacheActive() ? this.cachedDecision(operation) : null;
|
|
21725
|
+
if (cached2) return cached2;
|
|
20535
21726
|
const asked = listMatch?.verdict === "ask" ? {
|
|
20536
21727
|
allowed: false,
|
|
20537
21728
|
requireApproval: true,
|
|
@@ -20814,6 +22005,14 @@ var MIGRATIONS3 = [
|
|
|
20814
22005
|
up: (db) => {
|
|
20815
22006
|
db.exec(`ALTER TABLE schedules ADD COLUMN show_in_session_list INTEGER NOT NULL DEFAULT 0;`);
|
|
20816
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
|
+
}
|
|
20817
22016
|
}
|
|
20818
22017
|
];
|
|
20819
22018
|
var ScheduleStore = class {
|
|
@@ -20844,7 +22043,6 @@ var ScheduleStore = class {
|
|
|
20844
22043
|
allowOperations: input.allowOperations ?? [],
|
|
20845
22044
|
allowRules: input.allowRules ?? [],
|
|
20846
22045
|
maxTurns: input.maxTurns ?? SCHEDULE_DEFAULTS.maxTurns,
|
|
20847
|
-
maxBudgetUsd: input.maxBudgetUsd,
|
|
20848
22046
|
timeoutMs: input.timeoutMs ?? SCHEDULE_DEFAULTS.timeoutMs,
|
|
20849
22047
|
...input.showInSessionList === true ? { showInSessionList: true } : {},
|
|
20850
22048
|
trigger: normalizeTrigger(input.trigger),
|
|
@@ -20870,7 +22068,6 @@ var ScheduleStore = class {
|
|
|
20870
22068
|
allowOperations: [...input.allowOperations],
|
|
20871
22069
|
allowRules: [...input.allowRules],
|
|
20872
22070
|
maxTurns: input.maxTurns,
|
|
20873
|
-
maxBudgetUsd: input.maxBudgetUsd,
|
|
20874
22071
|
timeoutMs: input.timeoutMs,
|
|
20875
22072
|
...input.showInSessionList === true ? { showInSessionList: true } : {},
|
|
20876
22073
|
trigger: normalizeTrigger(input.trigger),
|
|
@@ -20912,14 +22109,14 @@ var ScheduleStore = class {
|
|
|
20912
22109
|
`INSERT INTO schedules (
|
|
20913
22110
|
id, name, enabled, created_at, updated_at, prompt, work_dir, model, role,
|
|
20914
22111
|
skills, mcp_servers, permission, allow_tools, allow_operations, allow_rules,
|
|
20915
|
-
max_turns,
|
|
22112
|
+
max_turns, timeout_ms, show_in_session_list,
|
|
20916
22113
|
trigger_kind, trigger_spec,
|
|
20917
22114
|
start_date, end_date, os_backend, os_task_id, os_registered_at, os_command,
|
|
20918
22115
|
last_run_at, last_status
|
|
20919
22116
|
) VALUES (
|
|
20920
22117
|
@id, @name, @enabled, @created_at, @updated_at, @prompt, @work_dir, @model, @role,
|
|
20921
22118
|
@skills, @mcp_servers, @permission, @allow_tools, @allow_operations, @allow_rules,
|
|
20922
|
-
@max_turns, @
|
|
22119
|
+
@max_turns, @timeout_ms, @show_in_session_list,
|
|
20923
22120
|
@trigger_kind, @trigger_spec,
|
|
20924
22121
|
@start_date, @end_date, @os_backend, @os_task_id, @os_registered_at, @os_command,
|
|
20925
22122
|
@last_run_at, @last_status
|
|
@@ -21035,7 +22232,7 @@ var ScheduleStore = class {
|
|
|
21035
22232
|
work_dir = @work_dir, model = @model, role = @role, skills = @skills,
|
|
21036
22233
|
mcp_servers = @mcp_servers, permission = @permission, allow_tools = @allow_tools,
|
|
21037
22234
|
allow_operations = @allow_operations, allow_rules = @allow_rules,
|
|
21038
|
-
max_turns = @max_turns,
|
|
22235
|
+
max_turns = @max_turns, timeout_ms = @timeout_ms,
|
|
21039
22236
|
show_in_session_list = @show_in_session_list,
|
|
21040
22237
|
trigger_kind = @trigger_kind, trigger_spec = @trigger_spec,
|
|
21041
22238
|
start_date = @start_date, end_date = @end_date, os_backend = @os_backend,
|
|
@@ -21057,7 +22254,6 @@ function mergeSchedulePatch(current, patch) {
|
|
|
21057
22254
|
"allowOperations",
|
|
21058
22255
|
"allowRules",
|
|
21059
22256
|
"maxTurns",
|
|
21060
|
-
"maxBudgetUsd",
|
|
21061
22257
|
"timeoutMs",
|
|
21062
22258
|
"showInSessionList",
|
|
21063
22259
|
"trigger",
|
|
@@ -21088,12 +22284,11 @@ function toRow(def) {
|
|
|
21088
22284
|
role: def.role ?? null,
|
|
21089
22285
|
skills: def.skills ? JSON.stringify(def.skills) : null,
|
|
21090
22286
|
mcp_servers: def.mcpServers ? JSON.stringify(def.mcpServers) : null,
|
|
21091
|
-
permission: def.permission,
|
|
22287
|
+
permission: permissionOfRow(def.permission),
|
|
21092
22288
|
allow_tools: JSON.stringify(def.allowTools),
|
|
21093
22289
|
allow_operations: JSON.stringify(def.allowOperations),
|
|
21094
22290
|
allow_rules: JSON.stringify(def.allowRules),
|
|
21095
22291
|
max_turns: def.maxTurns,
|
|
21096
|
-
max_budget_usd: def.maxBudgetUsd,
|
|
21097
22292
|
timeout_ms: def.timeoutMs,
|
|
21098
22293
|
show_in_session_list: def.showInSessionList === true ? 1 : 0,
|
|
21099
22294
|
trigger_kind: def.trigger.kind,
|
|
@@ -21108,6 +22303,9 @@ function toRow(def) {
|
|
|
21108
22303
|
last_status: def.lastStatus ?? null
|
|
21109
22304
|
};
|
|
21110
22305
|
}
|
|
22306
|
+
function permissionOfRow(raw) {
|
|
22307
|
+
return resolvePermissionLevel(raw) ?? SCHEDULE_DEFAULT_PERMISSION;
|
|
22308
|
+
}
|
|
21111
22309
|
function fromRow(row) {
|
|
21112
22310
|
return {
|
|
21113
22311
|
id: row.id,
|
|
@@ -21121,12 +22319,11 @@ function fromRow(row) {
|
|
|
21121
22319
|
...row.role !== null ? { role: row.role } : {},
|
|
21122
22320
|
...row.skills !== null ? { skills: parseArray2(row.skills) } : {},
|
|
21123
22321
|
...row.mcp_servers !== null ? { mcpServers: parseArray2(row.mcp_servers) } : {},
|
|
21124
|
-
permission: row.permission,
|
|
22322
|
+
permission: permissionOfRow(row.permission),
|
|
21125
22323
|
allowTools: parseArray2(row.allow_tools),
|
|
21126
22324
|
allowOperations: parseArray2(row.allow_operations),
|
|
21127
22325
|
allowRules: parseArray2(row.allow_rules),
|
|
21128
22326
|
maxTurns: row.max_turns,
|
|
21129
|
-
maxBudgetUsd: row.max_budget_usd,
|
|
21130
22327
|
timeoutMs: row.timeout_ms,
|
|
21131
22328
|
...row.show_in_session_list !== 0 ? { showInSessionList: true } : {},
|
|
21132
22329
|
trigger: JSON.parse(row.trigger_spec),
|
|
@@ -22572,7 +23769,7 @@ function loadLexiconDir(dir, source) {
|
|
|
22572
23769
|
});
|
|
22573
23770
|
continue;
|
|
22574
23771
|
}
|
|
22575
|
-
|
|
23772
|
+
collect4(content, file, spec, source, out);
|
|
22576
23773
|
}
|
|
22577
23774
|
return out;
|
|
22578
23775
|
}
|
|
@@ -22585,7 +23782,7 @@ function classify2(file) {
|
|
|
22585
23782
|
}
|
|
22586
23783
|
return CATEGORY_SET.has(base2) ? { kind: "terms", category: base2 } : null;
|
|
22587
23784
|
}
|
|
22588
|
-
function
|
|
23785
|
+
function collect4(content, file, spec, source, out) {
|
|
22589
23786
|
const lines = content.split("\n");
|
|
22590
23787
|
for (let i = 0; i < lines.length; i++) {
|
|
22591
23788
|
const line = (lines[i] ?? "").trim();
|
|
@@ -22637,6 +23834,18 @@ function resolveComplianceDirs(opts) {
|
|
|
22637
23834
|
dirs.push({ dir: projectDir, source: "project" });
|
|
22638
23835
|
return { dirs, projectSkipped: false };
|
|
22639
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
|
+
}
|
|
22640
23849
|
function sanitizeEnvironment(env) {
|
|
22641
23850
|
const sensitivePrefixes = [
|
|
22642
23851
|
"EPOCH_API_KEY",
|
|
@@ -22665,6 +23874,15 @@ function runCommandHook(config, event, workDir) {
|
|
|
22665
23874
|
const baseEnv = sanitizeEnvironment(process.env);
|
|
22666
23875
|
const injectedEnv = injectEpochEnv(event, config.pluginRoot);
|
|
22667
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
|
+
};
|
|
22668
23886
|
return new Promise((resolve17) => {
|
|
22669
23887
|
let stdout = "";
|
|
22670
23888
|
let stderr = "";
|
|
@@ -22677,11 +23895,16 @@ function runCommandHook(config, event, workDir) {
|
|
|
22677
23895
|
stdout,
|
|
22678
23896
|
stderr,
|
|
22679
23897
|
blocked: false,
|
|
22680
|
-
rejectReason: t("hook_load.spawn_failed", { message: err.message })
|
|
23898
|
+
rejectReason: t("hook_load.spawn_failed", { message: err.message }),
|
|
23899
|
+
sandbox
|
|
22681
23900
|
});
|
|
22682
23901
|
};
|
|
22683
23902
|
const child = guardSpawn(
|
|
22684
|
-
() => spawn(
|
|
23903
|
+
() => confinement.confined ? spawn(confinement.command, confinement.args, {
|
|
23904
|
+
cwd: workDir,
|
|
23905
|
+
env: hookEnv,
|
|
23906
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
23907
|
+
}) : spawn(config.command, {
|
|
22685
23908
|
shell: true,
|
|
22686
23909
|
cwd: workDir,
|
|
22687
23910
|
env: hookEnv,
|
|
@@ -22699,7 +23922,8 @@ function runCommandHook(config, event, workDir) {
|
|
|
22699
23922
|
stdout,
|
|
22700
23923
|
stderr,
|
|
22701
23924
|
blocked: false,
|
|
22702
|
-
rejectReason: t("hook_load.timeout")
|
|
23925
|
+
rejectReason: t("hook_load.timeout"),
|
|
23926
|
+
sandbox
|
|
22703
23927
|
});
|
|
22704
23928
|
}
|
|
22705
23929
|
}, timeout);
|
|
@@ -22730,13 +23954,21 @@ function runCommandHook(config, event, workDir) {
|
|
|
22730
23954
|
}
|
|
22731
23955
|
} catch {
|
|
22732
23956
|
}
|
|
23957
|
+
const failure = confinement.confined ? classifyFailure({
|
|
23958
|
+
exitCode,
|
|
23959
|
+
stderr,
|
|
23960
|
+
denialSignatures: confinement.denialSignatures,
|
|
23961
|
+
runnerFailureRules: confinement.runnerFailureRules
|
|
23962
|
+
}) : void 0;
|
|
22733
23963
|
resolve17({
|
|
22734
23964
|
exitCode,
|
|
22735
23965
|
stdout: stdout.trim(),
|
|
22736
23966
|
stderr: stderr.trim(),
|
|
22737
23967
|
blocked,
|
|
22738
23968
|
rejectReason,
|
|
22739
|
-
output
|
|
23969
|
+
output,
|
|
23970
|
+
sandbox,
|
|
23971
|
+
...failure ? { failure } : {}
|
|
22740
23972
|
});
|
|
22741
23973
|
});
|
|
22742
23974
|
child.on("error", (err) => {
|
|
@@ -22843,7 +24075,7 @@ var HookManager = class {
|
|
|
22843
24075
|
for (const config of entry.configs) {
|
|
22844
24076
|
try {
|
|
22845
24077
|
const result = await runCommandHook(config, event, workDir);
|
|
22846
|
-
|
|
24078
|
+
reportIfNotRun(this.log, type, config, result);
|
|
22847
24079
|
if (result.blocked) {
|
|
22848
24080
|
return { blocked: true, reason: result.rejectReason || t("hook_load.rejected") };
|
|
22849
24081
|
}
|
|
@@ -22877,7 +24109,7 @@ var HookManager = class {
|
|
|
22877
24109
|
for (const entry of cmdEntries) {
|
|
22878
24110
|
if (!matchesHook(entry.matcher, event)) continue;
|
|
22879
24111
|
for (const config of entry.configs) {
|
|
22880
|
-
runCommandHook(config, event, ctx.workDir).then((result) =>
|
|
24112
|
+
runCommandHook(config, event, ctx.workDir).then((result) => reportIfNotRun(this.log, type, config, result)).catch((err) => {
|
|
22881
24113
|
this.log("warn", `[HookManager] ${type} \u7684 command hook \u5F02\u6B65\u5F02\u5E38: ${describe12(err)}`, {
|
|
22882
24114
|
hookType: type,
|
|
22883
24115
|
command: config.command
|
|
@@ -22933,7 +24165,7 @@ var HookManager = class {
|
|
|
22933
24165
|
for (const config of entry.configs) {
|
|
22934
24166
|
try {
|
|
22935
24167
|
const result = await runCommandHook(config, event, ctx.workDir);
|
|
22936
|
-
|
|
24168
|
+
reportIfNotRun(this.log, type, config, result);
|
|
22937
24169
|
const verdict = verdictOf2(result);
|
|
22938
24170
|
if (verdict) results.push(verdict);
|
|
22939
24171
|
} catch (err) {
|
|
@@ -22967,12 +24199,25 @@ function verdictOf2(result) {
|
|
|
22967
24199
|
}
|
|
22968
24200
|
return void 0;
|
|
22969
24201
|
}
|
|
22970
|
-
function
|
|
22971
|
-
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;
|
|
22972
24213
|
log5(
|
|
22973
24214
|
"warn",
|
|
22974
|
-
|
|
22975
|
-
|
|
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 }
|
|
22976
24221
|
);
|
|
22977
24222
|
}
|
|
22978
24223
|
var MAPPINGS = {
|
|
@@ -23139,6 +24384,8 @@ var EVENT_MAP = {
|
|
|
23139
24384
|
SessionStart: "session:start",
|
|
23140
24385
|
SessionEnd: "session:end",
|
|
23141
24386
|
Stop: "stop",
|
|
24387
|
+
SubagentStart: "subagent:start",
|
|
24388
|
+
SubagentStop: "subagent:stop",
|
|
23142
24389
|
PostCompact: "compress:after"
|
|
23143
24390
|
};
|
|
23144
24391
|
var UNRUNNABLE_EVENTS = {
|
|
@@ -23588,7 +24835,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23588
24835
|
const dir = join(staging, category, name);
|
|
23589
24836
|
mkdirSync(dir, { recursive: true });
|
|
23590
24837
|
copyFileSync(join(source, SKILL_FILE), join(dir, SKILL_FILE));
|
|
23591
|
-
let
|
|
24838
|
+
let budget = MAX_FILES_PER_SKILL - 1;
|
|
23592
24839
|
for (const entry of readEntries2(source, label, issues, lang)) {
|
|
23593
24840
|
if (entry.name === SKILL_FILE) continue;
|
|
23594
24841
|
if (!entry.isDir || !SKILL_ASSET_DIRS.includes(entry.name)) {
|
|
@@ -23598,7 +24845,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23598
24845
|
});
|
|
23599
24846
|
continue;
|
|
23600
24847
|
}
|
|
23601
|
-
|
|
24848
|
+
budget = copyTree(join(source, entry.name), join(dir, entry.name), label, budget, issues, lang);
|
|
23602
24849
|
}
|
|
23603
24850
|
skills.push({ name, category, dir });
|
|
23604
24851
|
}
|
|
@@ -23657,8 +24904,8 @@ function placeOf(root, parts, lang) {
|
|
|
23657
24904
|
const category = parts.at(-2) ?? "general";
|
|
23658
24905
|
return { name, category: skillSegmentIssue(category, lang) === void 0 ? category : "general" };
|
|
23659
24906
|
}
|
|
23660
|
-
function copyTree(from, to, label,
|
|
23661
|
-
let left =
|
|
24907
|
+
function copyTree(from, to, label, budget, issues, lang) {
|
|
24908
|
+
let left = budget;
|
|
23662
24909
|
mkdirSync(to, { recursive: true });
|
|
23663
24910
|
for (const entry of readEntries2(from, label, issues, lang)) {
|
|
23664
24911
|
if (left <= 0) {
|
|
@@ -24204,9 +25451,9 @@ var SkillSystem = class {
|
|
|
24204
25451
|
);
|
|
24205
25452
|
}
|
|
24206
25453
|
};
|
|
24207
|
-
function sameDirs(
|
|
24208
|
-
if (
|
|
24209
|
-
return
|
|
25454
|
+
function sameDirs(cached2, current) {
|
|
25455
|
+
if (cached2.length !== current.length) return false;
|
|
25456
|
+
return cached2.every((dir, i) => dir === current[i]?.dir);
|
|
24210
25457
|
}
|
|
24211
25458
|
var MODULE6 = "Skill";
|
|
24212
25459
|
function resolveSkillDirs(opts) {
|
|
@@ -24722,11 +25969,11 @@ function readOne(path, opts, usedBytes) {
|
|
|
24722
25969
|
}
|
|
24723
25970
|
const remaining = MAX_ATTACH_TOTAL_BYTES - usedBytes;
|
|
24724
25971
|
if (remaining <= 0) return { part: { type: "file", path, omitted: "over-limit", bytes: size } };
|
|
24725
|
-
const
|
|
24726
|
-
if (raw.length <=
|
|
25972
|
+
const budget = Math.min(MAX_ATTACH_BYTES, remaining);
|
|
25973
|
+
if (raw.length <= budget) {
|
|
24727
25974
|
return { part: { type: "file", path, text: raw.toString("utf8"), bytes: size } };
|
|
24728
25975
|
}
|
|
24729
|
-
const { text, truncatedTo } = truncateToBudget(raw,
|
|
25976
|
+
const { text, truncatedTo } = truncateToBudget(raw, budget);
|
|
24730
25977
|
return {
|
|
24731
25978
|
part: { type: "file", path, text, truncatedTo, bytes: size },
|
|
24732
25979
|
notice: t("mentions.truncated", {
|
|
@@ -24940,6 +26187,9 @@ function goalSection(goal) {
|
|
|
24940
26187
|
].join("\n");
|
|
24941
26188
|
}
|
|
24942
26189
|
var DEFAULT_THRESHOLD = DEFAULT_COMPRESSION_THRESHOLD;
|
|
26190
|
+
function messageTokens(m) {
|
|
26191
|
+
return estimateTokens(m.content) + (m.reasoning ? estimateTokens(m.reasoning) : 0);
|
|
26192
|
+
}
|
|
24943
26193
|
var COOLDOWN_TURNS = 5;
|
|
24944
26194
|
var MAX_FAILURES = 3;
|
|
24945
26195
|
var DEFAULT_CONTEXT_LENGTH3 = 128e3;
|
|
@@ -24970,11 +26220,11 @@ var ContextCompressor = class {
|
|
|
24970
26220
|
enabled: opts.enabled !== false
|
|
24971
26221
|
};
|
|
24972
26222
|
}
|
|
24973
|
-
shouldCompress(
|
|
26223
|
+
shouldCompress(promptTokens3, contextLength) {
|
|
24974
26224
|
if (!this.opts.enabled) return false;
|
|
24975
26225
|
if (this.turnsSinceCompress < COOLDOWN_TURNS) return false;
|
|
24976
26226
|
if (this.failureCount >= MAX_FAILURES) return false;
|
|
24977
|
-
return isContextNearlyFull(
|
|
26227
|
+
return isContextNearlyFull(promptTokens3, contextLength, this.opts.threshold);
|
|
24978
26228
|
}
|
|
24979
26229
|
async compress(messages, partial = {}) {
|
|
24980
26230
|
const config = {
|
|
@@ -25016,7 +26266,11 @@ var ContextCompressor = class {
|
|
|
25016
26266
|
};
|
|
25017
26267
|
}
|
|
25018
26268
|
const nl = "\n";
|
|
25019
|
-
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);
|
|
25020
26274
|
const summarized = await this.generateSummary(
|
|
25021
26275
|
middleText,
|
|
25022
26276
|
config.instruction,
|
|
@@ -25073,13 +26327,13 @@ var ContextCompressor = class {
|
|
|
25073
26327
|
determineBoundaries(messages, config) {
|
|
25074
26328
|
const head = messages.slice(0, config.protectFirstN);
|
|
25075
26329
|
const thresholdTokens = config.threshold * config.contextLength;
|
|
25076
|
-
const tailBudget = thresholdTokens * config.targetRatio;
|
|
26330
|
+
const tailBudget = config.force ? 0 : thresholdTokens * config.targetRatio;
|
|
25077
26331
|
let tailTokens = 0;
|
|
25078
26332
|
let tailStart = messages.length;
|
|
25079
26333
|
let userCount = 0;
|
|
25080
26334
|
for (let i = messages.length - 1; i >= config.protectFirstN; i--) {
|
|
25081
26335
|
const msg = messages[i];
|
|
25082
|
-
tailTokens +=
|
|
26336
|
+
tailTokens += messageTokens(msg);
|
|
25083
26337
|
if (msg.role === "user") userCount++;
|
|
25084
26338
|
tailStart = i;
|
|
25085
26339
|
const enoughTokens = tailTokens >= tailBudget;
|
|
@@ -25179,7 +26433,7 @@ ${extra}` : withGoal;
|
|
|
25179
26433
|
return result;
|
|
25180
26434
|
}
|
|
25181
26435
|
estimateTokens(messages) {
|
|
25182
|
-
return messages.reduce((sum, m) => sum +
|
|
26436
|
+
return messages.reduce((sum, m) => sum + messageTokens(m), 0);
|
|
25183
26437
|
}
|
|
25184
26438
|
};
|
|
25185
26439
|
var FILE_VERSION5 = 1;
|
|
@@ -25419,248 +26673,6 @@ function hasExecTierContent(inv) {
|
|
|
25419
26673
|
function hasDedicatedExecContent(inv) {
|
|
25420
26674
|
return inv.hookFiles.includes(EPOCH_HOOKS_RELPATH) || inv.policies > 0;
|
|
25421
26675
|
}
|
|
25422
|
-
function describeIsolation() {
|
|
25423
|
-
const backend = detectBackend();
|
|
25424
|
-
const os = platform();
|
|
25425
|
-
if (backend === "seatbelt") {
|
|
25426
|
-
return {
|
|
25427
|
-
level: "os",
|
|
25428
|
-
backend,
|
|
25429
|
-
detail: t("sandbox_isolation.seatbelt"),
|
|
25430
|
-
reason: "os-isolated",
|
|
25431
|
-
platform: os
|
|
25432
|
-
};
|
|
25433
|
-
}
|
|
25434
|
-
if (backend === "bubblewrap") {
|
|
25435
|
-
return {
|
|
25436
|
-
level: "os",
|
|
25437
|
-
backend,
|
|
25438
|
-
detail: t("sandbox_isolation.bubblewrap"),
|
|
25439
|
-
reason: "os-isolated",
|
|
25440
|
-
platform: os
|
|
25441
|
-
};
|
|
25442
|
-
}
|
|
25443
|
-
const [why, reason9] = os === "darwin" ? [t("sandbox_isolation.no_seatbelt"), "backend-unavailable"] : os === "linux" ? [t("sandbox_isolation.no_bubblewrap"), "backend-missing"] : (
|
|
25444
|
-
[t("sandbox_isolation.by_design", { platform: os }), "platform-unsupported"]
|
|
25445
|
-
);
|
|
25446
|
-
return {
|
|
25447
|
-
level: "process",
|
|
25448
|
-
backend,
|
|
25449
|
-
detail: t("sandbox_isolation.process_only", { why }),
|
|
25450
|
-
reason: reason9,
|
|
25451
|
-
platform: os
|
|
25452
|
-
};
|
|
25453
|
-
}
|
|
25454
|
-
var SANDBOX_COVERS = ["code_exec", "terminal"];
|
|
25455
|
-
var SANDBOX_EXCLUDES = [];
|
|
25456
|
-
// src/sandbox/sandbox.ts
|
|
25457
|
-
var IS_WINDOWS = platform() === "win32";
|
|
25458
|
-
var SANDBOX_ROOT = join(tmpdir(), "epoch-sandbox");
|
|
25459
|
-
var DEFAULT_TIMEOUT = 3e4;
|
|
25460
|
-
var MAX_OUTPUT = 1e5;
|
|
25461
|
-
var MAX_MEMORY = 512;
|
|
25462
|
-
var TRUNCATE_HEAD = 2e3;
|
|
25463
|
-
var TRUNCATE_TAIL = 2e3;
|
|
25464
|
-
var CodeSandbox = class {
|
|
25465
|
-
sandboxDir;
|
|
25466
|
-
readableDirs;
|
|
25467
|
-
constructor(sessionId, workDir) {
|
|
25468
|
-
const safeId = sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || "default";
|
|
25469
|
-
this.sandboxDir = join(SANDBOX_ROOT, safeId);
|
|
25470
|
-
mkdirSync(this.sandboxDir, { recursive: true });
|
|
25471
|
-
this.readableDirs = [];
|
|
25472
|
-
if (workDir) {
|
|
25473
|
-
const abs = resolve(workDir);
|
|
25474
|
-
if (abs !== resolve(homedir()) && abs !== "/") this.readableDirs.push(abs);
|
|
25475
|
-
}
|
|
25476
|
-
}
|
|
25477
|
-
getIsolation() {
|
|
25478
|
-
return describeIsolation();
|
|
25479
|
-
}
|
|
25480
|
-
async execute(req) {
|
|
25481
|
-
const start = Date.now();
|
|
25482
|
-
const timeout = req.timeout ?? DEFAULT_TIMEOUT;
|
|
25483
|
-
const isolation = describeIsolation().level;
|
|
25484
|
-
try {
|
|
25485
|
-
const spec = req.language === "javascript" ? this.jsSpec(req.code) : this.pySpec(req.code);
|
|
25486
|
-
const result = await this.run(spec, {
|
|
25487
|
-
timeout,
|
|
25488
|
-
allowNetwork: req.allowNetwork === true,
|
|
25489
|
-
...req.signal ? { signal: req.signal } : {}
|
|
25490
|
-
});
|
|
25491
|
-
return { ...result, isolation };
|
|
25492
|
-
} catch (err) {
|
|
25493
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
25494
|
-
if (msg.includes("timed out") || msg.includes("killed")) {
|
|
25495
|
-
return {
|
|
25496
|
-
success: false,
|
|
25497
|
-
output: "",
|
|
25498
|
-
error: `[\u8D85\u65F6] \u8D85\u8FC7 ${timeout / 1e3} \u79D2`,
|
|
25499
|
-
errorType: "timeout",
|
|
25500
|
-
duration: Date.now() - start,
|
|
25501
|
-
isolation
|
|
25502
|
-
};
|
|
25503
|
-
}
|
|
25504
|
-
return {
|
|
25505
|
-
success: false,
|
|
25506
|
-
output: "",
|
|
25507
|
-
error: `[\u9519\u8BEF] ${msg}`,
|
|
25508
|
-
errorType: "runtime",
|
|
25509
|
-
duration: Date.now() - start,
|
|
25510
|
-
isolation
|
|
25511
|
-
};
|
|
25512
|
-
}
|
|
25513
|
-
}
|
|
25514
|
-
destroy() {
|
|
25515
|
-
try {
|
|
25516
|
-
rmSync(this.sandboxDir, { recursive: true });
|
|
25517
|
-
} catch {
|
|
25518
|
-
}
|
|
25519
|
-
}
|
|
25520
|
-
getDir() {
|
|
25521
|
-
return this.sandboxDir;
|
|
25522
|
-
}
|
|
25523
|
-
jsSpec(code) {
|
|
25524
|
-
const tmpFile = join(this.sandboxDir, "code.js");
|
|
25525
|
-
writeFileSync(tmpFile, code, "utf-8");
|
|
25526
|
-
return {
|
|
25527
|
-
command: process.execPath,
|
|
25528
|
-
args: [`--max-old-space-size=${MAX_MEMORY}`, tmpFile],
|
|
25529
|
-
env: EXEC_PATH_AS_NODE_ENV
|
|
25530
|
-
};
|
|
25531
|
-
}
|
|
25532
|
-
pySpec(code) {
|
|
25533
|
-
const tmpFile = join(this.sandboxDir, "code.py");
|
|
25534
|
-
writeFileSync(tmpFile, code, "utf-8");
|
|
25535
|
-
return {
|
|
25536
|
-
command: IS_WINDOWS ? "python" : "python3",
|
|
25537
|
-
args: ["-I", tmpFile]
|
|
25538
|
-
};
|
|
25539
|
-
}
|
|
25540
|
-
run(spec, opts) {
|
|
25541
|
-
const start = Date.now();
|
|
25542
|
-
const wrapped = isolate(spec.command, spec.args, {
|
|
25543
|
-
writableDirs: [this.sandboxDir, tmpdir()],
|
|
25544
|
-
readableDirs: this.readableDirs,
|
|
25545
|
-
allowNetwork: opts.allowNetwork,
|
|
25546
|
-
cwd: this.sandboxDir
|
|
25547
|
-
});
|
|
25548
|
-
const { command, args } = wrapped ?? spec;
|
|
25549
|
-
const spawnOpts = {
|
|
25550
|
-
cwd: this.sandboxDir,
|
|
25551
|
-
timeout: opts.timeout,
|
|
25552
|
-
env: {
|
|
25553
|
-
PATH: process.env["PATH"] ?? "",
|
|
25554
|
-
HOME: process.env["HOME"] ?? "",
|
|
25555
|
-
TMPDIR: this.sandboxDir,
|
|
25556
|
-
LANG: process.env["LANG"] ?? "en_US.UTF-8",
|
|
25557
|
-
...spec.env
|
|
25558
|
-
},
|
|
25559
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
25560
|
-
...IS_WINDOWS ? { windowsHide: true } : {}
|
|
25561
|
-
};
|
|
25562
|
-
return new Promise((resolve17) => {
|
|
25563
|
-
let stdout = "";
|
|
25564
|
-
let stderr = "";
|
|
25565
|
-
let killedForOutput = false;
|
|
25566
|
-
let child = null;
|
|
25567
|
-
const onAbort = () => {
|
|
25568
|
-
child?.kill("SIGKILL");
|
|
25569
|
-
};
|
|
25570
|
-
const failToStart = (err) => {
|
|
25571
|
-
opts.signal?.removeEventListener("abort", onAbort);
|
|
25572
|
-
if (err.code === "ENOENT") {
|
|
25573
|
-
resolve17({
|
|
25574
|
-
success: false,
|
|
25575
|
-
output: "",
|
|
25576
|
-
error: `[\u9519\u8BEF] \u627E\u4E0D\u5230\u89E3\u91CA\u5668: ${command}`,
|
|
25577
|
-
errorType: "compile",
|
|
25578
|
-
duration: Date.now() - start
|
|
25579
|
-
});
|
|
25580
|
-
return;
|
|
25581
|
-
}
|
|
25582
|
-
resolve17({
|
|
25583
|
-
success: false,
|
|
25584
|
-
output: "",
|
|
25585
|
-
error: `[\u9519\u8BEF] ${err.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
|
|
25586
|
-
errorType: "runtime",
|
|
25587
|
-
duration: Date.now() - start
|
|
25588
|
-
});
|
|
25589
|
-
};
|
|
25590
|
-
child = guardSpawn(() => spawn(command, args, spawnOpts), failToStart);
|
|
25591
|
-
if (!child) return;
|
|
25592
|
-
const proc = child;
|
|
25593
|
-
let outDecoder = null;
|
|
25594
|
-
let errDecoder = null;
|
|
25595
|
-
proc.stdout?.on("data", (c) => {
|
|
25596
|
-
if (killedForOutput) return;
|
|
25597
|
-
outDecoder ??= createStreamDecoder();
|
|
25598
|
-
stdout += outDecoder.write(c);
|
|
25599
|
-
if (stdout.length >= MAX_OUTPUT) {
|
|
25600
|
-
killedForOutput = true;
|
|
25601
|
-
stdout = stdout.slice(0, MAX_OUTPUT);
|
|
25602
|
-
proc.kill("SIGKILL");
|
|
25603
|
-
}
|
|
25604
|
-
});
|
|
25605
|
-
proc.stderr?.on("data", (c) => {
|
|
25606
|
-
if (stderr.length >= MAX_OUTPUT) return;
|
|
25607
|
-
errDecoder ??= createStreamDecoder();
|
|
25608
|
-
stderr += errDecoder.write(c);
|
|
25609
|
-
});
|
|
25610
|
-
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
25611
|
-
proc.on("error", failToStart);
|
|
25612
|
-
proc.on("close", (code, sig) => {
|
|
25613
|
-
opts.signal?.removeEventListener("abort", onAbort);
|
|
25614
|
-
if (!killedForOutput) stdout += outDecoder?.end() ?? "";
|
|
25615
|
-
if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
|
|
25616
|
-
const duration = Date.now() - start;
|
|
25617
|
-
if (killedForOutput) {
|
|
25618
|
-
resolve17({
|
|
25619
|
-
success: false,
|
|
25620
|
-
output: trunc(stdout, stderr),
|
|
25621
|
-
error: `[\u8F93\u51FA\u8D85\u9650] \u8D85\u8FC7 ${MAX_OUTPUT} \u5B57\u8282\uFF0C\u5DF2\u7EC8\u6B62`,
|
|
25622
|
-
errorType: "runtime",
|
|
25623
|
-
duration
|
|
25624
|
-
});
|
|
25625
|
-
return;
|
|
25626
|
-
}
|
|
25627
|
-
if (sig) {
|
|
25628
|
-
resolve17({
|
|
25629
|
-
success: false,
|
|
25630
|
-
output: trunc(stdout, stderr),
|
|
25631
|
-
error: opts.signal?.aborted ? "[\u5DF2\u53D6\u6D88]" : "[\u8D85\u65F6] \u6267\u884C\u8D85\u65F6",
|
|
25632
|
-
errorType: "timeout",
|
|
25633
|
-
duration
|
|
25634
|
-
});
|
|
25635
|
-
return;
|
|
25636
|
-
}
|
|
25637
|
-
const output = trunc(stdout, stderr);
|
|
25638
|
-
if (code !== 0 && code !== null) {
|
|
25639
|
-
const oom = /heap out of memory|allocation failed/i.test(stderr);
|
|
25640
|
-
resolve17({
|
|
25641
|
-
success: false,
|
|
25642
|
-
output,
|
|
25643
|
-
error: oom ? `[\u5185\u5B58\u8D85\u9650] \u8D85\u8FC7 ${MAX_MEMORY}MB` : `[\u8FD0\u884C\u65F6\u9519\u8BEF] exit ${code}: ${stderr.slice(0, 200)}`,
|
|
25644
|
-
errorType: oom ? "oom" : "runtime",
|
|
25645
|
-
duration
|
|
25646
|
-
});
|
|
25647
|
-
return;
|
|
25648
|
-
}
|
|
25649
|
-
resolve17({ success: true, output, duration });
|
|
25650
|
-
});
|
|
25651
|
-
});
|
|
25652
|
-
}
|
|
25653
|
-
};
|
|
25654
|
-
function trunc(stdout, stderr) {
|
|
25655
|
-
const nl = "\n";
|
|
25656
|
-
let out = stdout;
|
|
25657
|
-
if (stderr) out += (out ? nl : "") + stderr;
|
|
25658
|
-
if (out.length <= MAX_OUTPUT) return out || "(\u65E0\u8F93\u51FA)";
|
|
25659
|
-
const head = out.slice(0, TRUNCATE_HEAD);
|
|
25660
|
-
const tail = out.slice(-TRUNCATE_TAIL);
|
|
25661
|
-
const skipped = out.length - TRUNCATE_HEAD - TRUNCATE_TAIL;
|
|
25662
|
-
return `${head}${nl}...[\u5DF2\u622A\u65AD ${(skipped / 1024).toFixed(1)} KB]...${nl}${tail}`;
|
|
25663
|
-
}
|
|
25664
26676
|
/**
|
|
25665
26677
|
* @license
|
|
25666
26678
|
* Copyright 2025 Google LLC
|
|
@@ -25706,4 +26718,4 @@ function trunc(stdout, stderr) {
|
|
|
25706
26718
|
* `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
|
|
25707
26719
|
*/
|
|
25708
26720
|
|
|
25709
|
-
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 };
|