@epoch-agent/core 2.1.0 → 2.3.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 +1 -1
- package/dist/index.d.ts +12363 -12342
- package/dist/index.js +254 -147
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, 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, imagePartOmittedSummary, ENTRY_REF_PREFIX, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
|
|
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, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, 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, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
|
|
2
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
3
|
import { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSync, rmSync, renameSync, realpathSync, symlinkSync, cpSync, lstatSync, unlinkSync, rmdirSync, mkdtempSync, copyFileSync, openSync, writeSync, closeSync, readSync } from 'fs';
|
|
4
4
|
import { homedir, platform, tmpdir, hostname } from 'os';
|
|
@@ -2707,13 +2707,48 @@ function createExitTool(deps) {
|
|
|
2707
2707
|
function createPlanModeTools(deps) {
|
|
2708
2708
|
return [createEnterTool(deps), createExitTool(deps)];
|
|
2709
2709
|
}
|
|
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
|
|
2710
2744
|
var bad = (message) => ({ ok: false, message });
|
|
2711
2745
|
var good = (value) => ({ ok: true, value });
|
|
2712
2746
|
var PERMISSION_ORDER = [
|
|
2713
2747
|
"plan",
|
|
2714
2748
|
"default",
|
|
2715
2749
|
"acceptEdits",
|
|
2716
|
-
"auto"
|
|
2750
|
+
"auto",
|
|
2751
|
+
"bypass"
|
|
2717
2752
|
];
|
|
2718
2753
|
var OPERATION_TYPES = [
|
|
2719
2754
|
"file_read",
|
|
@@ -2755,16 +2790,18 @@ function operationList(v) {
|
|
|
2755
2790
|
function permission(v) {
|
|
2756
2791
|
const s = str(v);
|
|
2757
2792
|
if (s === void 0) return bad("permission \u662F\u7A7A\u7684");
|
|
2758
|
-
if (s === "bypass") {
|
|
2759
|
-
return bad(
|
|
2760
|
-
"\u8349\u7A3F\u4E0D\u8BB8\u7528 bypass\uFF08\u8DF3\u8FC7\u5168\u90E8\u68C0\u67E5\uFF09\u3002\u65E0\u4EBA\u503C\u5B88\u4E0B\u90A3\u4E00\u6863\u8981\u4EBA\u4EB2\u624B\u52FE\u4E00\u6B21\u786E\u8BA4\uFF0C\u8BA9\u8349\u7A3F\u63D0\u8BAE\u5B83\u7B49\u4E8E\u628A\u90A3\u6B21\u786E\u8BA4\u53D8\u6210\u4F8B\u884C\u624B\u7EED\u3002\u8981\u653E\u5F00\u67D0\u51E0\u4EF6\u4E8B\uFF0C\u7528 permission: default \u52A0\u4E00\u4EFD\u7CBE\u786E\u7684 allowRules"
|
|
2761
|
-
);
|
|
2762
|
-
}
|
|
2763
2793
|
if (!PERMISSION_ORDER.includes(s)) {
|
|
2764
2794
|
return bad(`permission \u53EA\u80FD\u662F ${PERMISSION_ORDER.join(" / ")} \u4E4B\u4E00\uFF0C\u6536\u5230\u7684\u662F ${s}`);
|
|
2765
2795
|
}
|
|
2766
2796
|
return good(s);
|
|
2767
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);
|
|
2804
|
+
}
|
|
2768
2805
|
function clock(v) {
|
|
2769
2806
|
const s = str(v);
|
|
2770
2807
|
if (s === void 0 || !/^\d{1,2}:\d{2}$/.test(s))
|
|
@@ -2881,6 +2918,8 @@ function parseCreate(raw, note) {
|
|
|
2881
2918
|
const allow = parseAllowlist(raw);
|
|
2882
2919
|
if (!allow.ok) return allow;
|
|
2883
2920
|
const workDir = str(raw["workDir"]);
|
|
2921
|
+
const usd = budget(raw["maxBudgetUsd"]);
|
|
2922
|
+
if (!usd.ok) return usd;
|
|
2884
2923
|
return good({
|
|
2885
2924
|
action: "create",
|
|
2886
2925
|
name,
|
|
@@ -2889,6 +2928,7 @@ function parseCreate(raw, note) {
|
|
|
2889
2928
|
permission: level.value,
|
|
2890
2929
|
note,
|
|
2891
2930
|
...workDir === void 0 ? {} : { workDir },
|
|
2931
|
+
...usd.value === void 0 ? {} : { maxBudgetUsd: usd.value },
|
|
2892
2932
|
...allow.value
|
|
2893
2933
|
});
|
|
2894
2934
|
}
|
|
@@ -2923,6 +2963,9 @@ function parseUpdate(raw, note) {
|
|
|
2923
2963
|
const timeout = posInt(raw["timeoutMs"], "timeoutMs");
|
|
2924
2964
|
if (!timeout.ok) return timeout;
|
|
2925
2965
|
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;
|
|
2926
2969
|
if (Object.keys(patch).length === 0) {
|
|
2927
2970
|
return bad(
|
|
2928
2971
|
"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"
|
|
@@ -2948,7 +2991,7 @@ function parseScheduleDraft(raw) {
|
|
|
2948
2991
|
}
|
|
2949
2992
|
function draftWidening(draft, current) {
|
|
2950
2993
|
const out = [];
|
|
2951
|
-
const base2 = draft.action === "update" && current ? current.permission
|
|
2994
|
+
const base2 = draft.action === "update" && current ? current.permission : "default";
|
|
2952
2995
|
const level = draft.permission;
|
|
2953
2996
|
if (level !== void 0 && PERMISSION_ORDER.indexOf(level) > PERMISSION_ORDER.indexOf(base2)) {
|
|
2954
2997
|
out.push("permission");
|
|
@@ -3002,42 +3045,9 @@ function draftCommandLine(draft) {
|
|
|
3002
3045
|
for (const tool of draft.allowTools ?? []) argv.push("--allow-tool", shellArg(tool));
|
|
3003
3046
|
for (const op2 of draft.allowOperations ?? []) argv.push("--allow-operation", op2);
|
|
3004
3047
|
for (const rule of draft.allowRules ?? []) argv.push("--allow-rule", shellArg(rule));
|
|
3005
|
-
argv.push("--budget",
|
|
3048
|
+
argv.push("--budget", String(draft.maxBudgetUsd ?? SCHEDULE_FORM_BUDGET_USD));
|
|
3006
3049
|
return argv.join(" ");
|
|
3007
3050
|
}
|
|
3008
|
-
var SCHEDULE_ISSUE_CODES = [
|
|
3009
|
-
"name-empty",
|
|
3010
|
-
"prompt-empty",
|
|
3011
|
-
"permission-unknown",
|
|
3012
|
-
"work-dir-missing",
|
|
3013
|
-
"budget-missing",
|
|
3014
|
-
"max-turns-invalid",
|
|
3015
|
-
"timeout-invalid",
|
|
3016
|
-
"trigger-time-invalid",
|
|
3017
|
-
"trigger-times-too-many",
|
|
3018
|
-
"trigger-weekdays-empty",
|
|
3019
|
-
"trigger-days-invalid",
|
|
3020
|
-
"trigger-interval-invalid",
|
|
3021
|
-
"trigger-once-date-invalid",
|
|
3022
|
-
"trigger-once-past",
|
|
3023
|
-
"date-range-invalid",
|
|
3024
|
-
"date-range-on-once",
|
|
3025
|
-
"rule-invalid",
|
|
3026
|
-
"bypass-needs-workdir",
|
|
3027
|
-
"bypass-workdir-too-broad",
|
|
3028
|
-
"bypass-needs-limits",
|
|
3029
|
-
"bypass-not-confirmed"
|
|
3030
|
-
];
|
|
3031
|
-
var SCHEDULE_DEFAULTS = {
|
|
3032
|
-
maxTurns: DEFAULT_MAX_TURNS,
|
|
3033
|
-
timeoutMs: 60 * 60 * 1e3
|
|
3034
|
-
};
|
|
3035
|
-
var SCHEDULE_FORM_BUDGET_USD = 200;
|
|
3036
|
-
var SCHEDULE_DEFAULT_ALLOWLIST = {
|
|
3037
|
-
allowTools: [],
|
|
3038
|
-
allowOperations: ["file_read"],
|
|
3039
|
-
allowRules: []
|
|
3040
|
-
};
|
|
3041
3051
|
// src/schedule/unattended-lint.ts
|
|
3042
3052
|
var ANCHORS = [
|
|
3043
3053
|
{ kind: "asks-human", zh: /问(?:一下|下)?我/, en: /\bask\s+(?:me|us)\b/i },
|
|
@@ -3473,7 +3483,7 @@ function validateSchedule(input) {
|
|
|
3473
3483
|
if (input.workDir && !isExistingDir(input.workDir)) {
|
|
3474
3484
|
issues.push({ code: "work-dir-missing", detail: input.workDir });
|
|
3475
3485
|
}
|
|
3476
|
-
if (!
|
|
3486
|
+
if (!Number.isFinite(input.maxBudgetUsd) || input.maxBudgetUsd <= 0) {
|
|
3477
3487
|
issues.push({ code: "budget-missing", detail: String(input.maxBudgetUsd) });
|
|
3478
3488
|
}
|
|
3479
3489
|
if (!Number.isInteger(input.maxTurns) || input.maxTurns < 0) {
|
|
@@ -3535,29 +3545,34 @@ var WIDENING_TEXT = {
|
|
|
3535
3545
|
allowlist: "\u6E05\u5355\u591A\u4E86\u6761\u76EE\uFF08= \u591A\u4E86\u51E0\u4EF6\u4E0D\u7ECF\u786E\u8BA4\u5C31\u4F1A\u505A\u7684\u4E8B\uFF09",
|
|
3536
3546
|
enabled: "\u628A\u4E00\u6761\u505C\u7528\u7684\u4EFB\u52A1\u6539\u6210\u542F\u7528"
|
|
3537
3547
|
};
|
|
3548
|
+
function budgetOf(draft, current) {
|
|
3549
|
+
return draft.maxBudgetUsd ?? current?.maxBudgetUsd ?? SCHEDULE_FORM_BUDGET_USD;
|
|
3550
|
+
}
|
|
3538
3551
|
function validateDraft(draft, homeDir, current) {
|
|
3552
|
+
const permission2 = draft.permission ?? current?.permission ?? "default";
|
|
3539
3553
|
const merged = draft.action === "create" ? {
|
|
3540
3554
|
name: draft.name,
|
|
3541
3555
|
prompt: draft.prompt,
|
|
3542
|
-
permission:
|
|
3556
|
+
permission: permission2,
|
|
3543
3557
|
workDir: draft.workDir ?? "",
|
|
3544
3558
|
maxTurns: SCHEDULE_DEFAULTS.maxTurns,
|
|
3545
|
-
maxBudgetUsd:
|
|
3559
|
+
maxBudgetUsd: budgetOf(draft),
|
|
3546
3560
|
timeoutMs: SCHEDULE_DEFAULTS.timeoutMs,
|
|
3547
3561
|
trigger: draft.trigger,
|
|
3548
3562
|
allowRules: draft.allowRules ?? [],
|
|
3549
|
-
|
|
3563
|
+
bypassAcknowledged: permission2 === "bypass",
|
|
3550
3564
|
homeDir
|
|
3551
3565
|
} : {
|
|
3552
3566
|
name: draft.name ?? current?.name ?? "",
|
|
3553
3567
|
prompt: draft.prompt ?? current?.prompt ?? "",
|
|
3554
|
-
permission:
|
|
3568
|
+
permission: permission2,
|
|
3555
3569
|
workDir: draft.workDir ?? current?.workDir ?? "",
|
|
3556
3570
|
maxTurns: draft.maxTurns ?? current?.maxTurns ?? SCHEDULE_DEFAULTS.maxTurns,
|
|
3557
|
-
maxBudgetUsd: current
|
|
3571
|
+
maxBudgetUsd: budgetOf(draft, current),
|
|
3558
3572
|
timeoutMs: draft.timeoutMs ?? current?.timeoutMs ?? SCHEDULE_DEFAULTS.timeoutMs,
|
|
3559
3573
|
trigger: draft.trigger ?? current?.trigger ?? { kind: "cron", cycle: "daily", at: "09:00" },
|
|
3560
3574
|
allowRules: draft.allowRules ?? current?.allowRules ?? [],
|
|
3575
|
+
bypassAcknowledged: permission2 === "bypass",
|
|
3561
3576
|
homeDir
|
|
3562
3577
|
};
|
|
3563
3578
|
return validateSchedule(merged).issues.map(
|
|
@@ -3590,13 +3605,27 @@ function structuralNotes(draft, current) {
|
|
|
3590
3605
|
}
|
|
3591
3606
|
return out;
|
|
3592
3607
|
}
|
|
3593
|
-
function
|
|
3608
|
+
function registrationLine(outcome) {
|
|
3609
|
+
if (outcome === void 0) return void 0;
|
|
3610
|
+
if (outcome.ok) {
|
|
3611
|
+
return "\u5DF2\u7ECF\u6CE8\u518C\u8FDB\u64CD\u4F5C\u7CFB\u7EDF\uFF0C\u5230\u70B9\u4F1A\u81EA\u5DF1\u8DD1\uFF08\u5173\u6389\u8FD9\u4E2A\u5E94\u7528\u4E5F\u8DD1\uFF09\u3002";
|
|
3612
|
+
}
|
|
3613
|
+
switch (outcome.reason) {
|
|
3614
|
+
case "unsupported-platform":
|
|
3615
|
+
return "\u26A0\uFE0F \u8FD9\u53F0\u673A\u5668\uFF08Linux\uFF09\u6682\u4E0D\u652F\u6301\u81EA\u52A8\u89E6\u53D1 \u2014\u2014 \u4EFB\u52A1\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u5230\u70B9\u4E0D\u4F1A\u81EA\u5DF1\u8DD1\u3002";
|
|
3616
|
+
case "refused":
|
|
3617
|
+
return outcome.refusal === "npx" ? "\u26A0\uFE0F \u6CA1\u6CE8\u518C\u8FDB\u64CD\u4F5C\u7CFB\u7EDF\uFF1A\u8FD9\u4E00\u4EFD\u662F npx \u4E34\u65F6\u8DD1\u8D77\u6765\u7684\uFF0C\u7F13\u5B58\u76EE\u5F55\u4E00\u6E05\u90A3\u6761\u4EFB\u52A1\u5C31\u5E9F\u3002\u88C5\u6210\u5168\u5C40\uFF08`npm i -g`\uFF09\u4E4B\u540E\u91CD\u5EFA\u4E00\u6B21\u624D\u6CE8\u518C\u5F97\u4E0A\u3002\u4EFB\u52A1\u672C\u8EAB\u5B58\u4E0B\u6765\u4E86\u3002" : "\u26A0\uFE0F \u6CA1\u6CE8\u518C\u8FDB\u64CD\u4F5C\u7CFB\u7EDF\uFF1A\u8FD9\u4E2A\u5BBF\u4E3B\u6CA1\u7ED9\u300C\u5230\u70B9\u4E86\u600E\u4E48\u8D77\u4E00\u6B21\u300D\u7684\u5165\u53E3\u3002\u4EFB\u52A1\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u5E94\u7528\u5173\u7740\u7684\u65F6\u5019\u5B83\u4E0D\u4F1A\u8DD1\u3002";
|
|
3618
|
+
case "backend-error":
|
|
3619
|
+
return `\u26A0\uFE0F \u6CE8\u518C\u8FDB\u64CD\u4F5C\u7CFB\u7EDF\u5931\u8D25\u4E86\uFF1A${outcome.detail}\u3002\u4EFB\u52A1\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u5230\u70B9\u4E0D\u4F1A\u81EA\u5DF1\u8DD1\u3002`;
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
function summarizeProposal(draft, current, readOnly) {
|
|
3594
3623
|
const lines = [];
|
|
3595
3624
|
lines.push(
|
|
3596
3625
|
draft.action === "create" ? `\u8349\u7A3F\u5DF2\u7ECF\u6446\u5230\u7528\u6237\u773C\u524D\u4E86\uFF08\u4E00\u5F20\u5361\u7247\uFF0C\u6807\u9898\u300C${draft.name}\u300D\uFF09\u3002` : `\u6539\u52A8\u63D0\u6848\u5DF2\u7ECF\u6446\u5230\u7528\u6237\u773C\u524D\u4E86\uFF08\u9488\u5BF9\u300C${current?.name ?? draft.id}\u300D\uFF09\u3002`
|
|
3597
3626
|
);
|
|
3598
3627
|
lines.push(
|
|
3599
|
-
"\u5B83**\u8FD8\u6CA1\u6709\u751F\u6548\uFF0C\u4E5F\u6CA1\u6709\u843D\u5E93** \u2014\u2014 \u8981\u7528\u6237\
|
|
3628
|
+
readOnly ? "\u5B83**\u8FD8\u6CA1\u6709\u751F\u6548\uFF0C\u4E5F\u6CA1\u6709\u843D\u5E93** \u2014\u2014 \u4F60\u5728\u53EA\u8BFB\u8C03\u7814\u6A21\u5F0F\uFF08plan\uFF09\u4E0B\uFF0C\u8FD9\u4E00\u6863\u4E0D\u5199\u76D8\u3002\u8981\u7528\u6237\u81EA\u5DF1\u5BA1\u4E00\u904D\u3001\u70B9\u300C\u5BA1\u9605\u5E76\u4FDD\u5B58\u300D\u624D\u662F\u771F\u7684\u5EFA\u7ACB\u3002" : "\u5B83**\u8FD8\u6CA1\u6709\u843D\u5E93** \u2014\u2014 \u8FD9\u4E2A\u5BBF\u4E3B\u6CA1\u6709\u63A5\u5199\u5165\u8DEF\uFF0C\u8981\u7528\u6237\u81EA\u5DF1\u5BA1\u4E00\u904D\u3001\u70B9\u300C\u5BA1\u9605\u5E76\u4FDD\u5B58\u300D\u624D\u662F\u771F\u7684\u5EFA\u7ACB\u3002"
|
|
3600
3629
|
);
|
|
3601
3630
|
const widening = draftWidening(draft, current);
|
|
3602
3631
|
if (widening.length > 0) {
|
|
@@ -3607,16 +3636,77 @@ function summarize(draft, current) {
|
|
|
3607
3636
|
for (const note of structuralNotes(draft, current)) lines.push(`\u26A0\uFE0F ${note}`);
|
|
3608
3637
|
const cli = draftCommandLine(draft);
|
|
3609
3638
|
lines.push(
|
|
3610
|
-
cli === void 0 ? "\uFF08\u6CA1\u6709\u754C\u9762\u7684\u5BBF\u4E3B\u4E0A\uFF1A\u6539\u4E00\u6761\u5DF2\u6709\u4EFB\u52A1\u4ECA\u5929\u53EA\u6709\u754C\u9762\u90A3\u6761\u8DEF \u2014\u2014 `epoch schedule` \u5E95\u4E0B\u6CA1\u6709\u6539\u5B57\u6BB5\u7684\u5B50\u547D\u4EE4\uFF0C\u53EA\u6709 enable / disable / rm\u3002\u522B\u7F16\u4E00\u6761 update \u51FA\u6765\u3002\uFF09" : `\u6CA1\u6709\u754C\u9762\u7684\u5BBF\u4E3B\u4E0A\uFF0C\u7B49\u4EF7\u7684\u547D\u4EE4\u884C\u662F\
|
|
3639
|
+
cli === void 0 ? "\uFF08\u6CA1\u6709\u754C\u9762\u7684\u5BBF\u4E3B\u4E0A\uFF1A\u6539\u4E00\u6761\u5DF2\u6709\u4EFB\u52A1\u4ECA\u5929\u53EA\u6709\u754C\u9762\u90A3\u6761\u8DEF \u2014\u2014 `epoch schedule` \u5E95\u4E0B\u6CA1\u6709\u6539\u5B57\u6BB5\u7684\u5B50\u547D\u4EE4\uFF0C\u53EA\u6709 enable / disable / rm\u3002\u522B\u7F16\u4E00\u6761 update \u51FA\u6765\u3002\uFF09" : `\u6CA1\u6709\u754C\u9762\u7684\u5BBF\u4E3B\u4E0A\uFF0C\u7B49\u4EF7\u7684\u547D\u4EE4\u884C\u662F\uFF1A
|
|
3611
3640
|
${cli}`
|
|
3612
3641
|
);
|
|
3613
|
-
lines.push("\u522B\u91CD\u590D\u63D0\u4EA4\u540C\u4E00\u4EFD\u8349\u7A3F\u7B49\u5B83\u300C\u751F\u6548\u300D\u2014\u2014 \u7528\u6237\u4EC0\u4E48\u65F6\u5019\u5BA1\u662F\u4ED6\u7684\u4E8B\uFF0C\u4F60\u8FD9\u4E00\u8F6E\u5230\u6B64\u4E3A\u6B62\u3002");
|
|
3614
3642
|
return lines.join("\n");
|
|
3615
3643
|
}
|
|
3644
|
+
function summarizeSaved(draft, def, registration, current) {
|
|
3645
|
+
const lines = [];
|
|
3646
|
+
lines.push(
|
|
3647
|
+
`${SCHEDULE_DRAFT_SAVED_MARK}${def.id}`,
|
|
3648
|
+
draft.action === "create" ? `\u5DF2\u7ECF\u5EFA\u7ACB\u5E76\u751F\u6548\uFF1A\u300C${def.name}\u300D\u3002` : `\u5DF2\u7ECF\u6539\u597D\u4E86\uFF1A\u300C${current?.name ?? def.name}\u300D\u3002`
|
|
3649
|
+
);
|
|
3650
|
+
const when = draft.action === "create" ? draft.trigger : draft.trigger ?? current?.trigger;
|
|
3651
|
+
if (when !== void 0) lines.push(`\u5230\u70B9\uFF1A${JSON.stringify(when)}`);
|
|
3652
|
+
const permission2 = draft.permission ?? current?.permission;
|
|
3653
|
+
if (permission2 !== void 0) lines.push(`\u6743\u9650\u6863\uFF1A${permission2}`);
|
|
3654
|
+
const registered = registrationLine(registration);
|
|
3655
|
+
if (registered !== void 0) lines.push(registered);
|
|
3656
|
+
const widening = draftWidening(draft, current);
|
|
3657
|
+
if (widening.length > 0) {
|
|
3658
|
+
lines.push(
|
|
3659
|
+
`\u26A0\uFE0F \u8FD9\u6B21\u6539\u52A8\u653E\u5BBD\u4E86\u6388\u6743\u9762\uFF1A${widening.map((k) => WIDENING_TEXT[k]).join("\uFF1B")}\u3002\u5728\u4F60\u7684\u56DE\u590D\u91CC**\u4E3B\u52A8**\u628A\u8FD9\u4E00\u70B9\u8BF4\u7ED9\u7528\u6237\u542C \u2014\u2014 \u5B83\u5DF2\u7ECF\u751F\u6548\u4E86\uFF0C\u90A3\u4E2A\u4EBA\u53EA\u6709\u9760\u4F60\u8FD9\u53E5\u8BDD\u624D\u77E5\u9053\u521A\u624D\u591A\u653E\u884C\u4E86\u4EC0\u4E48\u3002`
|
|
3660
|
+
);
|
|
3661
|
+
}
|
|
3662
|
+
for (const note of structuralNotes(draft, current)) lines.push(`\u26A0\uFE0F ${note}`);
|
|
3663
|
+
lines.push(
|
|
3664
|
+
"\u5728\u4F60\u7684\u56DE\u590D\u91CC\u7528\u4E00\u53E5\u8BDD\u4EA4\u4EE3\u300C\u5EFA\u4E86\u4EC0\u4E48\u3001\u4EC0\u4E48\u65F6\u5019\u8DD1\u300D\u5C31\u591F\u4E86\u3002**\u522B\u518D\u8BF4\u300C\u8981\u4E0D\u8981\u6211\u5EFA\u4E00\u6761\u300D** \u2014\u2014 \u5B83\u5DF2\u7ECF\u5728\u4E86\uFF1B\u7528\u6237\u60F3\u64A4\u6389\uFF0C\u5361\u7247\u4E0A\u6709\u64A4\u9500\u952E\uFF0C\u4E5F\u53EF\u4EE5\u53BB\u81EA\u52A8\u5316\u9762\u677F\u5220\u3002"
|
|
3665
|
+
);
|
|
3666
|
+
return lines.join("\n");
|
|
3667
|
+
}
|
|
3668
|
+
async function persist(save, draft, current) {
|
|
3669
|
+
const permission2 = draft.permission ?? current?.permission ?? "default";
|
|
3670
|
+
const acknowledged = { bypassAcknowledged: permission2 === "bypass" };
|
|
3671
|
+
if (draft.action === "create") {
|
|
3672
|
+
return save.create(
|
|
3673
|
+
{
|
|
3674
|
+
name: draft.name,
|
|
3675
|
+
prompt: draft.prompt,
|
|
3676
|
+
permission: draft.permission,
|
|
3677
|
+
maxBudgetUsd: budgetOf(draft),
|
|
3678
|
+
trigger: draft.trigger,
|
|
3679
|
+
...draft.workDir === void 0 ? {} : { workDir: draft.workDir },
|
|
3680
|
+
...draft.allowTools === void 0 ? {} : { allowTools: draft.allowTools },
|
|
3681
|
+
...draft.allowOperations === void 0 ? {} : { allowOperations: draft.allowOperations },
|
|
3682
|
+
...draft.allowRules === void 0 ? {} : { allowRules: draft.allowRules }
|
|
3683
|
+
},
|
|
3684
|
+
acknowledged
|
|
3685
|
+
);
|
|
3686
|
+
}
|
|
3687
|
+
return save.update(
|
|
3688
|
+
draft.id,
|
|
3689
|
+
{
|
|
3690
|
+
...draft.name === void 0 ? {} : { name: draft.name },
|
|
3691
|
+
...draft.prompt === void 0 ? {} : { prompt: draft.prompt },
|
|
3692
|
+
...draft.permission === void 0 ? {} : { permission: draft.permission },
|
|
3693
|
+
...draft.trigger === void 0 ? {} : { trigger: draft.trigger },
|
|
3694
|
+
...draft.workDir === void 0 ? {} : { workDir: draft.workDir },
|
|
3695
|
+
...draft.enabled === void 0 ? {} : { enabled: draft.enabled },
|
|
3696
|
+
...draft.maxTurns === void 0 ? {} : { maxTurns: draft.maxTurns },
|
|
3697
|
+
...draft.timeoutMs === void 0 ? {} : { timeoutMs: draft.timeoutMs },
|
|
3698
|
+
...draft.maxBudgetUsd === void 0 ? {} : { maxBudgetUsd: draft.maxBudgetUsd },
|
|
3699
|
+
...draft.allowTools === void 0 ? {} : { allowTools: draft.allowTools },
|
|
3700
|
+
...draft.allowOperations === void 0 ? {} : { allowOperations: draft.allowOperations },
|
|
3701
|
+
...draft.allowRules === void 0 ? {} : { allowRules: draft.allowRules }
|
|
3702
|
+
},
|
|
3703
|
+
acknowledged
|
|
3704
|
+
);
|
|
3705
|
+
}
|
|
3616
3706
|
function createScheduleDraftTool(deps) {
|
|
3617
3707
|
return {
|
|
3618
3708
|
name: SCHEDULE_DRAFT_TOOL,
|
|
3619
|
-
description: "\
|
|
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\u9884\u7B97\u4E0D\u7ED9\u5C31\u662F 200 \u7F8E\u5143\uFF1B\u8FD9\u6D3B\u660E\u663E\u66F4\u8F7B\u6216\u66F4\u91CD\u65F6\u81EA\u5DF1\u7ED9 maxBudgetUsd\u3002\u6743\u9650\u6863 plan/default/acceptEdits/auto/bypass \u90FD\u80FD\u63D0 \u2014\u2014 \u4F46**\u9ED8\u8BA4\u7528 plan**\uFF1A\u53EA\u8BFB\u6863\u5929\u7136\u96F6\u6388\u6743\u9762\uFF0C\u9700\u8981\u5199\u4E1C\u897F\u518D\u7528 default \u52A0\u4E00\u4EFD\u7CBE\u786E\u7684 allowRules\uFF08\u6BD4\u5982 terminal(git status)\uFF09\uFF0C\u522B\u4E00\u4E0A\u6765\u5C31 bypass\u3002",
|
|
3620
3710
|
parameters: {
|
|
3621
3711
|
type: "object",
|
|
3622
3712
|
properties: {
|
|
@@ -3627,7 +3717,7 @@ function createScheduleDraftTool(deps) {
|
|
|
3627
3717
|
},
|
|
3628
3718
|
note: {
|
|
3629
3719
|
type: "string",
|
|
3630
|
-
description: "\u4E3A\u4EC0\u4E48\u5EFA\
|
|
3720
|
+
description: "\u4E3A\u4EC0\u4E48\u5EFA\u8FD9\u6761\uFF0C\u4E00\u53E5\u8BDD\u3002create / update \u5FC5\u586B\uFF0C\u4F1A\u5370\u5728\u7528\u6237\u770B\u5230\u7684\u5361\u7247\u4E0A\uFF1B\u8BF4\u4E0D\u51FA\u771F\u5B9E\u7406\u7531\u5C31\u522B\u63D0\u8FD9\u4E2A\u5EFA\u8BAE"
|
|
3631
3721
|
},
|
|
3632
3722
|
id: { type: "string", description: "\u6539\u54EA\u4E00\u6761\u3002update \u5FC5\u586B\uFF0C\u4ECE action=list \u91CC\u62FF" },
|
|
3633
3723
|
name: { type: "string", description: "\u4EFB\u52A1\u540D\uFF0C\u7528\u6237\u5728\u5217\u8868\u91CC\u770B\u5230\u7684\u5C31\u662F\u5B83" },
|
|
@@ -3660,8 +3750,12 @@ function createScheduleDraftTool(deps) {
|
|
|
3660
3750
|
},
|
|
3661
3751
|
permission: {
|
|
3662
3752
|
type: "string",
|
|
3663
|
-
description: "\u6743\u9650\u6863\u3002plan=\u53EA\u8BFB\uFF08\u8BFB\u4E00\u904D\u5199\u4EFD\u62A5\u544A\u7684\u4EFB\u52A1\u5C31\u8BE5\u7528\u5B83\uFF0C\u5929\u7136\u96F6\u6388\u6743\u9762\uFF09\uFF1Bdefault=\u6309\u9700\u786E\u8BA4\uFF1BacceptEdits=\u81EA\u52A8\u63A5\u53D7\u6539\u52A8\uFF1Bauto=\u4E0D\u518D\u786E\u8BA4",
|
|
3664
|
-
enum: ["plan", "default", "acceptEdits", "auto"]
|
|
3753
|
+
description: "\u6743\u9650\u6863\u3002plan=\u53EA\u8BFB\uFF08\u8BFB\u4E00\u904D\u5199\u4EFD\u62A5\u544A\u7684\u4EFB\u52A1\u5C31\u8BE5\u7528\u5B83\uFF0C\u5929\u7136\u96F6\u6388\u6743\u9762\uFF09\uFF1Bdefault=\u6309\u9700\u786E\u8BA4\uFF1BacceptEdits=\u81EA\u52A8\u63A5\u53D7\u6539\u52A8\uFF1Bauto=\u4E0D\u518D\u786E\u8BA4\uFF1Bbypass=\u8DF3\u8FC7\u5168\u90E8\u68C0\u67E5\uFF08**\u6700\u540E\u624B\u6BB5**\uFF1A\u5230\u70B9\u4E86\u5B83\u60F3\u8DD1\u4EC0\u4E48\u5C31\u8DD1\u4EC0\u4E48\uFF09",
|
|
3754
|
+
enum: ["plan", "default", "acceptEdits", "auto", "bypass"]
|
|
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"
|
|
3665
3759
|
},
|
|
3666
3760
|
allowTools: {
|
|
3667
3761
|
type: "array",
|
|
@@ -3687,58 +3781,71 @@ function createScheduleDraftTool(deps) {
|
|
|
3687
3781
|
exposure: ToolExposure.Direct,
|
|
3688
3782
|
supportsParallel: false,
|
|
3689
3783
|
annotations: {
|
|
3690
|
-
readOnlyHint:
|
|
3691
|
-
destructiveHint:
|
|
3692
|
-
idempotentHint:
|
|
3784
|
+
readOnlyHint: false,
|
|
3785
|
+
destructiveHint: true,
|
|
3786
|
+
idempotentHint: false,
|
|
3693
3787
|
openWorldHint: false
|
|
3694
3788
|
},
|
|
3695
3789
|
operation: "file_read",
|
|
3696
3790
|
describeTarget: (args) => `schedule_draft:${String(args["action"] ?? "list")}`,
|
|
3697
|
-
execute(rawArgs,
|
|
3791
|
+
async execute(rawArgs, ctx) {
|
|
3698
3792
|
const startedAt = Date.now();
|
|
3699
3793
|
const action = rawArgs["action"];
|
|
3700
3794
|
if (action === "list") {
|
|
3701
3795
|
const rows = deps.list();
|
|
3702
|
-
return
|
|
3703
|
-
|
|
3704
|
-
rows.length === 0 ? "\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\u90FD\u8FD8\u6CA1\u6709\u3002\u8981\u65B0\u5EFA\u5C31\u7528 action=create\u3002" : `\u73B0\u6709 ${rows.length} \u6761\uFF1A
|
|
3796
|
+
return say4(
|
|
3797
|
+
rows.length === 0 ? "\u4E00\u6761\u5B9A\u65F6\u4EFB\u52A1\u90FD\u8FD8\u6CA1\u6709\u3002\u8981\u65B0\u5EFA\u5C31\u7528 action=create\u3002" : `\u73B0\u6709 ${rows.length} \u6761\uFF1A
|
|
3705
3798
|
${rows.map(describeRow).join("\n")}`,
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
)
|
|
3799
|
+
true,
|
|
3800
|
+
startedAt
|
|
3709
3801
|
);
|
|
3710
3802
|
}
|
|
3711
3803
|
const parsed = parseScheduleDraft(rawArgs);
|
|
3712
|
-
if (!parsed.ok) return
|
|
3804
|
+
if (!parsed.ok) return say4(parsed.message, false, startedAt);
|
|
3713
3805
|
const draft = parsed.value;
|
|
3714
3806
|
const current = draft.action === "update" ? deps.get(draft.id) : void 0;
|
|
3715
3807
|
if (draft.action === "update" && current === void 0) {
|
|
3716
|
-
return
|
|
3717
|
-
|
|
3808
|
+
return say4(
|
|
3809
|
+
`\u6CA1\u6709 id \u4E3A ${draft.id} \u7684\u4EFB\u52A1\u3002\u5148\u7528 action=list \u770B\u4E00\u773C\u73B0\u6709\u7684\u3002`,
|
|
3810
|
+
false,
|
|
3811
|
+
startedAt
|
|
3718
3812
|
);
|
|
3719
3813
|
}
|
|
3720
3814
|
const issues = validateDraft(draft, deps.homeDir, current);
|
|
3721
3815
|
if (issues.length > 0) {
|
|
3722
|
-
return
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
startedAt
|
|
3727
|
-
)
|
|
3816
|
+
return say4(
|
|
3817
|
+
`\u8FD9\u4EFD\u63D0\u6848\u5B58\u4E0D\u4E0B\u6765\uFF0C\u5148\u6539\u8FD9\u51E0\u5904\u518D\u8BF4\uFF1A${issues.join("\u3001")}\u3002\uFF08\u8FD9\u4E9B\u662F\u6821\u9A8C\u7801\uFF0C\u542B\u4E49\u770B\u5B57\u9762\uFF1Bdetail \u62EC\u5728\u540E\u9762\uFF09`,
|
|
3818
|
+
false,
|
|
3819
|
+
startedAt
|
|
3728
3820
|
);
|
|
3729
3821
|
}
|
|
3730
3822
|
const unattended = unattendedIssues(draft);
|
|
3731
3823
|
if (unattended.length > 0) {
|
|
3732
|
-
return
|
|
3733
|
-
|
|
3734
|
-
`\u8FD9\u4EFD\u8349\u7A3F\u4FDD\u5B58\u5F97\u4E86\uFF0C\u4F46\u5B83\u5230\u70B9\u4E86**\u8DD1\u4E0D\u51FA\u7ED3\u679C** \u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u662F\u65E0\u4EBA\u503C\u5B88\u7684\uFF0C\u6CA1\u4EBA\u5728\u65C1\u8FB9\u56DE\u8BDD\u3002\u6539\u5B8C\u518D\u4EA4\uFF1A
|
|
3824
|
+
return say4(
|
|
3825
|
+
`\u8FD9\u4EFD\u63D0\u6848\u5B58\u5F97\u4E0B\u6765\uFF0C\u4F46\u5B83\u5230\u70B9\u4E86**\u8DD1\u4E0D\u51FA\u7ED3\u679C** \u2014\u2014 \u5B9A\u65F6\u4EFB\u52A1\u662F\u65E0\u4EBA\u503C\u5B88\u7684\uFF0C\u6CA1\u4EBA\u5728\u65C1\u8FB9\u56DE\u8BDD\u3002\u6539\u5B8C\u518D\u4EA4\uFF1A
|
|
3735
3826
|
${unattended.map((x) => `\xB7 ${x}`).join("\n")}`,
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3827
|
+
false,
|
|
3828
|
+
startedAt
|
|
3829
|
+
);
|
|
3830
|
+
}
|
|
3831
|
+
const readOnly = ctx.permissionLevel === "plan";
|
|
3832
|
+
if (readOnly || deps.save === void 0) {
|
|
3833
|
+
return say4(summarizeProposal(draft, current, readOnly), true, startedAt);
|
|
3834
|
+
}
|
|
3835
|
+
const saved = await persist(deps.save, draft, current);
|
|
3836
|
+
if (saved.issues.length > 0) {
|
|
3837
|
+
const codes = saved.issues.map((x) => x.detail ? `${x.code}\uFF08${x.detail}\uFF09` : x.code);
|
|
3838
|
+
return say4(`\u5F15\u64CE\u62D2\u7EDD\u4E86\u8FD9\u4EFD\u63D0\u6848\uFF0C\u4E00\u4E2A\u5B57\u90FD\u6CA1\u5199\uFF1A${codes.join("\u3001")}\u3002`, false, startedAt);
|
|
3839
|
+
}
|
|
3840
|
+
const def = saved.schedule;
|
|
3841
|
+
if (def === void 0) {
|
|
3842
|
+
return say4(
|
|
3843
|
+
"\u5F15\u64CE\u8BF4\u5B58\u4E0B\u6765\u4E86\uFF0C\u4F46\u6CA1\u56DE\u90A3\u6761\u4EFB\u52A1 \u2014\u2014 \u53BB\u81EA\u52A8\u5316\u9762\u677F\u770B\u4E00\u773C\u5B83\u5230\u5E95\u5728\u4E0D\u5728\u3002",
|
|
3844
|
+
false,
|
|
3845
|
+
startedAt
|
|
3739
3846
|
);
|
|
3740
3847
|
}
|
|
3741
|
-
return
|
|
3848
|
+
return say4(summarizeSaved(draft, def, saved.registration, current), true, startedAt);
|
|
3742
3849
|
}
|
|
3743
3850
|
};
|
|
3744
3851
|
}
|
|
@@ -4229,41 +4336,41 @@ function clampWindow(raw, fallback2, max) {
|
|
|
4229
4336
|
function stamp2(ms) {
|
|
4230
4337
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
4231
4338
|
}
|
|
4232
|
-
function
|
|
4339
|
+
function budgetOf2(total) {
|
|
4233
4340
|
const shares = ANCHOR_SHARE + Math.max(0, total - 1);
|
|
4234
4341
|
const unit = Math.max(MIN_BODY, Math.floor(BODY_BUDGET / shares));
|
|
4235
4342
|
return { anchor: unit * ANCHOR_SHARE, other: unit };
|
|
4236
4343
|
}
|
|
4237
|
-
function body(text,
|
|
4344
|
+
function body(text, budget2) {
|
|
4238
4345
|
const flat = text.replace(/\r\n/g, "\n").trimEnd();
|
|
4239
|
-
if (flat.length <=
|
|
4240
|
-
const rest = flat.length -
|
|
4241
|
-
return `${flat.slice(0,
|
|
4346
|
+
if (flat.length <= budget2) return flat;
|
|
4347
|
+
const rest = flat.length - budget2;
|
|
4348
|
+
return `${flat.slice(0, budget2)}
|
|
4242
4349
|
\u2026[cut ${rest} more chars \u2014 lower before/after to spend the budget on fewer messages]`;
|
|
4243
4350
|
}
|
|
4244
4351
|
function surfaceOf(record, isCurrent) {
|
|
4245
4352
|
if (!isCurrent) return record.surface === "active" ? "active there" : "compacted there";
|
|
4246
4353
|
return record.surface === "active" ? "still in your context" : "compacted out of your context";
|
|
4247
4354
|
}
|
|
4248
|
-
function renderRecord(record, mark,
|
|
4355
|
+
function renderRecord(record, mark, budget2, isCurrent) {
|
|
4249
4356
|
const tool = record.toolName ? ` \xB7 ${record.toolName}` : "";
|
|
4250
4357
|
return [
|
|
4251
4358
|
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${stamp2(record.timestamp)} \xB7 ${surfaceOf(record, isCurrent)}]`,
|
|
4252
|
-
` ${body(record.content,
|
|
4359
|
+
` ${body(record.content, budget2).split("\n").join("\n ")}`
|
|
4253
4360
|
].join("\n");
|
|
4254
4361
|
}
|
|
4255
4362
|
function renderWindow(out, sessionId, isCurrent) {
|
|
4256
4363
|
const anchor = out.anchor;
|
|
4257
4364
|
if (!anchor) return "";
|
|
4258
4365
|
const count = out.before.length + out.after.length + 1;
|
|
4259
|
-
const
|
|
4366
|
+
const budget2 = budgetOf2(count);
|
|
4260
4367
|
return [
|
|
4261
4368
|
`Session ${sessionId}${isCurrent ? " (this session)" : ""} \u2014 ${out.title || "(untitled)"}`,
|
|
4262
4369
|
`${count} of ${out.total} message(s), around #${anchor.messageId}:`,
|
|
4263
4370
|
"",
|
|
4264
|
-
...out.before.map((r) => renderRecord(r, " ",
|
|
4265
|
-
renderRecord(anchor, "\xBB",
|
|
4266
|
-
...out.after.map((r) => renderRecord(r, " ",
|
|
4371
|
+
...out.before.map((r) => renderRecord(r, " ", budget2.other, isCurrent)),
|
|
4372
|
+
renderRecord(anchor, "\xBB", budget2.anchor, isCurrent),
|
|
4373
|
+
...out.after.map((r) => renderRecord(r, " ", budget2.other, isCurrent))
|
|
4267
4374
|
].join("\n");
|
|
4268
4375
|
}
|
|
4269
4376
|
function createSessionMessagesReadTool(deps) {
|
|
@@ -6156,7 +6263,7 @@ function loadCommandDefinitions(opts) {
|
|
|
6156
6263
|
}
|
|
6157
6264
|
diags?.ok(
|
|
6158
6265
|
SLASH_COMMANDS_DIAG_MODULE,
|
|
6159
|
-
|
|
6266
|
+
summarize(commands.length, plugin.commands.length, user, project)
|
|
6160
6267
|
);
|
|
6161
6268
|
return {
|
|
6162
6269
|
commands,
|
|
@@ -6167,7 +6274,7 @@ function loadCommandDefinitions(opts) {
|
|
|
6167
6274
|
issues: [...plugin.issues, ...user.issues, ...project.issues]
|
|
6168
6275
|
};
|
|
6169
6276
|
}
|
|
6170
|
-
function
|
|
6277
|
+
function summarize(total, pluginCount, user, project) {
|
|
6171
6278
|
if (total === 0) return t("custom_command.none");
|
|
6172
6279
|
const parts = [
|
|
6173
6280
|
t("custom_command.count_user", { count: user.commands.length }),
|
|
@@ -8924,7 +9031,7 @@ async function snapshotFiles(paths) {
|
|
|
8924
9031
|
}
|
|
8925
9032
|
async function collectDiffs(before, workDir) {
|
|
8926
9033
|
const out = [];
|
|
8927
|
-
let
|
|
9034
|
+
let budget2 = MAX_CALL_BYTES;
|
|
8928
9035
|
for (const [path, old] of before) {
|
|
8929
9036
|
if (old.kind === "opaque") continue;
|
|
8930
9037
|
const now = await readSnapshot(path);
|
|
@@ -8932,8 +9039,8 @@ async function collectDiffs(before, workDir) {
|
|
|
8932
9039
|
if (old.kind === "absent" && now.kind === "absent") continue;
|
|
8933
9040
|
if (old.kind === "text" && now.kind === "text" && old.text === now.text) continue;
|
|
8934
9041
|
const bytes = (old.kind === "text" ? old.bytes : 0) + (now.kind === "text" ? now.bytes : 0);
|
|
8935
|
-
if (bytes >
|
|
8936
|
-
|
|
9042
|
+
if (bytes > budget2) continue;
|
|
9043
|
+
budget2 -= bytes;
|
|
8937
9044
|
out.push({
|
|
8938
9045
|
filePath: workspaceDisplayPath(path, workDir),
|
|
8939
9046
|
...old.kind === "text" ? { oldContent: old.text } : {},
|
|
@@ -9521,10 +9628,10 @@ function renderSettings(s) {
|
|
|
9521
9628
|
bits.push(`\u4E0A\u4E0B\u6587\u7A97\u53E3 ${s.contextLength}`);
|
|
9522
9629
|
bits.push(`\u81EA\u52A8\u538B\u7F29 ${s.compression.enabled ? `\u5F00\uFF08${s.compression.threshold}\uFF09` : "\u5173"}`);
|
|
9523
9630
|
bits.push(`\u7EC8\u7AEF\u6C99\u7BB1 ${s.sandboxTerminal ? "\u5F00" : "\u5173"}`);
|
|
9524
|
-
const
|
|
9525
|
-
if (s.budget?.maxCostUsd !== void 0)
|
|
9526
|
-
if (s.budget?.maxTokens !== void 0)
|
|
9527
|
-
bits.push(`\u9884\u7B97\u4E0A\u9650 ${
|
|
9631
|
+
const budget2 = [];
|
|
9632
|
+
if (s.budget?.maxCostUsd !== void 0) budget2.push(`$${s.budget.maxCostUsd}`);
|
|
9633
|
+
if (s.budget?.maxTokens !== void 0) budget2.push(`${s.budget.maxTokens} tokens`);
|
|
9634
|
+
bits.push(`\u9884\u7B97\u4E0A\u9650 ${budget2.length > 0 ? budget2.join(" / ") : "\u672A\u8BBE"}`);
|
|
9528
9635
|
return [
|
|
9529
9636
|
"<settings>",
|
|
9530
9637
|
bits.join(" \xB7 "),
|
|
@@ -9641,7 +9748,7 @@ function extensionFor(mediaType) {
|
|
|
9641
9748
|
if (sub === "jpeg") return ".jpg";
|
|
9642
9749
|
return /^[a-z0-9]{1,8}$/.test(sub) ? `.${sub}` : ".bin";
|
|
9643
9750
|
}
|
|
9644
|
-
function
|
|
9751
|
+
function persist2(bytes, mediaType, dir, hint) {
|
|
9645
9752
|
const digest2 = createHash("sha256").update(bytes).digest("hex").slice(0, 16);
|
|
9646
9753
|
const safeHint = (hint ?? "").replace(/[^A-Za-z0-9_-]/g, "").slice(0, 40);
|
|
9647
9754
|
const stem = safeHint ? `${safeHint}-${digest2}` : digest2;
|
|
@@ -9682,7 +9789,7 @@ function admitArtifact(raw, policy) {
|
|
|
9682
9789
|
const bytes = Buffer.from(raw.base64, "base64");
|
|
9683
9790
|
const byteLen = bytes.length;
|
|
9684
9791
|
const size = raw.kind === "image" ? readImageSize(bytes) : void 0;
|
|
9685
|
-
const path = policy.artifactsDir ?
|
|
9792
|
+
const path = policy.artifactsDir ? persist2(bytes, raw.mediaType, policy.artifactsDir, raw.filename) : void 0;
|
|
9686
9793
|
const dims = size ? ` ${size.width}\xD7${size.height}` : "";
|
|
9687
9794
|
const head = raw.note ? `${raw.note} ` : "";
|
|
9688
9795
|
const reason9 = rejectionReason(raw, policy, byteLen, size);
|
|
@@ -11768,7 +11875,7 @@ function toAbsolute2(path, workDir) {
|
|
|
11768
11875
|
}
|
|
11769
11876
|
var MAX_TOOL_OUTPUT = 3e4;
|
|
11770
11877
|
var MAX_SUB_CALL_OUTPUT = CODE_MODE_LIMITS.maxValueChars;
|
|
11771
|
-
function
|
|
11878
|
+
function budgetOf3(tool, depth, path = "success") {
|
|
11772
11879
|
if (tool.governsOwnOutput && path === "success") return Number.POSITIVE_INFINITY;
|
|
11773
11880
|
return depth > 0 ? MAX_SUB_CALL_OUTPUT : MAX_TOOL_OUTPUT;
|
|
11774
11881
|
}
|
|
@@ -12019,7 +12126,7 @@ var ToolExecutor = class {
|
|
|
12019
12126
|
permissionLevel: this.deps.permissionManager?.getLevel() || "auto",
|
|
12020
12127
|
...signal ? { signal } : {},
|
|
12021
12128
|
...onOutput ? { onOutput } : {},
|
|
12022
|
-
outputBudget:
|
|
12129
|
+
outputBudget: budgetOf3(et, depth),
|
|
12023
12130
|
...depth < MAX_SUB_CALL_DEPTH ? { callTool: this.subCallChannel(sessionId, signal, span, depth) } : {}
|
|
12024
12131
|
});
|
|
12025
12132
|
if (snapshotted.length > 0) {
|
|
@@ -12051,7 +12158,7 @@ var ToolExecutor = class {
|
|
|
12051
12158
|
success: true,
|
|
12052
12159
|
output: this.renderOutput(
|
|
12053
12160
|
et,
|
|
12054
|
-
appendArtifactSummaries(text, artifacts,
|
|
12161
|
+
appendArtifactSummaries(text, artifacts, budgetOf3(et, depth), shapeOf(r.output))
|
|
12055
12162
|
),
|
|
12056
12163
|
...artifacts.length > 0 ? { artifacts } : {},
|
|
12057
12164
|
...diffs.length > 0 ? { diffs } : {}
|
|
@@ -12062,7 +12169,7 @@ var ToolExecutor = class {
|
|
|
12062
12169
|
success: false,
|
|
12063
12170
|
output: this.renderOutput(
|
|
12064
12171
|
et,
|
|
12065
|
-
truncateForModel(failureText(r),
|
|
12172
|
+
truncateForModel(failureText(r), budgetOf3(et, depth, "failure"), "text")
|
|
12066
12173
|
)
|
|
12067
12174
|
});
|
|
12068
12175
|
} catch (err) {
|
|
@@ -12239,13 +12346,13 @@ function stripHistoryImages(history) {
|
|
|
12239
12346
|
});
|
|
12240
12347
|
return { messages, stripped };
|
|
12241
12348
|
}
|
|
12242
|
-
function budgetStop(
|
|
12243
|
-
const breach =
|
|
12244
|
-
if (breach) return { message:
|
|
12349
|
+
function budgetStop(budget2, messages) {
|
|
12350
|
+
const breach = budget2.breachReason();
|
|
12351
|
+
if (breach) return { message: budget2.describeBreach(breach), breach };
|
|
12245
12352
|
const imageTokens = pendingImageTokens(messages);
|
|
12246
|
-
const projected =
|
|
12353
|
+
const projected = budget2.projectedBreach(imageTokens);
|
|
12247
12354
|
if (!projected) return void 0;
|
|
12248
|
-
return { message:
|
|
12355
|
+
return { message: budget2.describeProjectedBreach(projected, imageTokens), breach: projected };
|
|
12249
12356
|
}
|
|
12250
12357
|
var AgentLoop = class {
|
|
12251
12358
|
config;
|
|
@@ -12481,7 +12588,7 @@ var AgentLoop = class {
|
|
|
12481
12588
|
const addRun = (u) => {
|
|
12482
12589
|
runUsage = runUsage ? addUsage(runUsage, u) : u;
|
|
12483
12590
|
};
|
|
12484
|
-
const
|
|
12591
|
+
const budget2 = new BudgetGuard({
|
|
12485
12592
|
...this.config.budget ? { budget: this.config.budget } : {},
|
|
12486
12593
|
...this.config.modelPricing ? { pricing: this.config.modelPricing } : {},
|
|
12487
12594
|
...input.maxCallCostUsd !== void 0 ? { maxCallCostUsd: input.maxCallCostUsd } : {},
|
|
@@ -12493,7 +12600,7 @@ var AgentLoop = class {
|
|
|
12493
12600
|
const finish = (reason9, breach) => ({
|
|
12494
12601
|
type: "finish",
|
|
12495
12602
|
reason: reason9,
|
|
12496
|
-
usage:
|
|
12603
|
+
usage: budget2.snapshot(),
|
|
12497
12604
|
...runUsage ? { runUsage } : {},
|
|
12498
12605
|
...lastModel ? { model: lastModel } : {},
|
|
12499
12606
|
...lastRequestedModel ? { requestedModel: lastRequestedModel } : {},
|
|
@@ -12545,8 +12652,8 @@ var AgentLoop = class {
|
|
|
12545
12652
|
await this.prompt.syncMemory(userText, lastText);
|
|
12546
12653
|
return;
|
|
12547
12654
|
}
|
|
12548
|
-
|
|
12549
|
-
const stop = budgetStop(
|
|
12655
|
+
budget2.syncFromStore();
|
|
12656
|
+
const stop = budgetStop(budget2, messages);
|
|
12550
12657
|
if (stop) {
|
|
12551
12658
|
yield { type: "text-delta", text: stop.message };
|
|
12552
12659
|
await this.prompt.syncMemory(userText, lastText || stop.message);
|
|
@@ -12598,8 +12705,8 @@ var AgentLoop = class {
|
|
|
12598
12705
|
}
|
|
12599
12706
|
if (rescued.usage) {
|
|
12600
12707
|
addRun(rescued.usage);
|
|
12601
|
-
yield*
|
|
12602
|
-
|
|
12708
|
+
yield* budget2.toEvents(
|
|
12709
|
+
budget2.add(rescued.usage, this.rateOf(rescued.model)),
|
|
12603
12710
|
runUsage
|
|
12604
12711
|
);
|
|
12605
12712
|
}
|
|
@@ -12675,7 +12782,7 @@ var AgentLoop = class {
|
|
|
12675
12782
|
});
|
|
12676
12783
|
if (rescued.usage) {
|
|
12677
12784
|
addRun(rescued.usage);
|
|
12678
|
-
yield*
|
|
12785
|
+
yield* budget2.toEvents(budget2.add(rescued.usage, this.rateOf(rescued.model)), runUsage);
|
|
12679
12786
|
}
|
|
12680
12787
|
if (!shrank(messages, rescued.messages)) throw err;
|
|
12681
12788
|
messages = rescued.messages;
|
|
@@ -12732,14 +12839,14 @@ var AgentLoop = class {
|
|
|
12732
12839
|
"epoch.token_type": "cache_write"
|
|
12733
12840
|
});
|
|
12734
12841
|
}
|
|
12735
|
-
const status =
|
|
12842
|
+
const status = budget2.add(usage, this.rateOf(result.model));
|
|
12736
12843
|
input.onTurnUsage?.(
|
|
12737
12844
|
status.turnCostUsd === void 0 ? usage : { ...usage, costUsd: status.turnCostUsd }
|
|
12738
12845
|
);
|
|
12739
12846
|
addRun(usage);
|
|
12740
12847
|
lastModel = result.model;
|
|
12741
12848
|
lastRequestedModel = result.requestedModel;
|
|
12742
|
-
yield*
|
|
12849
|
+
yield* budget2.toEvents(status, runUsage);
|
|
12743
12850
|
}
|
|
12744
12851
|
const verdict = mergeVerdicts(guard?.verdict(), reasoningGuard?.verdict());
|
|
12745
12852
|
if (verdict) this.reportCompliance(verdict, "output");
|
|
@@ -12976,8 +13083,8 @@ ${finalText}` };
|
|
|
12976
13083
|
messages = compacted.messages;
|
|
12977
13084
|
if (compacted.usage) {
|
|
12978
13085
|
addRun(compacted.usage);
|
|
12979
|
-
yield*
|
|
12980
|
-
|
|
13086
|
+
yield* budget2.toEvents(
|
|
13087
|
+
budget2.add(compacted.usage, this.rateOf(compacted.model)),
|
|
12981
13088
|
runUsage
|
|
12982
13089
|
);
|
|
12983
13090
|
}
|
|
@@ -16916,8 +17023,8 @@ var MemoryManager = class {
|
|
|
16916
17023
|
async add(target, content) {
|
|
16917
17024
|
const label = injectionLabelOf(content);
|
|
16918
17025
|
if (label !== void 0) return this.refuseInjection(label);
|
|
16919
|
-
const
|
|
16920
|
-
if (
|
|
17026
|
+
const budget2 = this.getBudget()[target];
|
|
17027
|
+
if (budget2.current + content.length > budget2.limit) {
|
|
16921
17028
|
this.consolidationFailures++;
|
|
16922
17029
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
16923
17030
|
return {
|
|
@@ -16964,9 +17071,9 @@ var MemoryManager = class {
|
|
|
16964
17071
|
}
|
|
16965
17072
|
const label = injectionLabelOf(content);
|
|
16966
17073
|
if (label !== void 0) return this.refuseInjection(label);
|
|
16967
|
-
const
|
|
17074
|
+
const budget2 = this.getBudget()[target];
|
|
16968
17075
|
const delta = content.length - existing.charLength;
|
|
16969
|
-
if (
|
|
17076
|
+
if (budget2.current + delta > budget2.limit) {
|
|
16970
17077
|
this.consolidationFailures++;
|
|
16971
17078
|
if (this.consolidationFailures > MAX_CONSOLIDATION_FAILURES_PER_TURN) {
|
|
16972
17079
|
return { success: false, done: true, error: "Consolidation limit reached" };
|
|
@@ -17171,11 +17278,11 @@ var MemoryManager = class {
|
|
|
17171
17278
|
for (const target of ["memory", "user"]) {
|
|
17172
17279
|
const rows = kept.filter((e) => e.target === target);
|
|
17173
17280
|
if (rows.length === 0) continue;
|
|
17174
|
-
const
|
|
17281
|
+
const budget2 = this.getBudget()[target];
|
|
17175
17282
|
const label = target === "user" ? "USER PROFILE (who the user is)" : "MEMORY (your personal notes)";
|
|
17176
17283
|
sections.push(
|
|
17177
17284
|
[
|
|
17178
|
-
`${label} [${rows.length} entries \xB7 ${
|
|
17285
|
+
`${label} [${rows.length} entries \xB7 ${budget2.current.toLocaleString()}/${budget2.limit.toLocaleString()} chars]`,
|
|
17179
17286
|
...rows.map((e) => this.indexLine(e))
|
|
17180
17287
|
].join("\n")
|
|
17181
17288
|
);
|
|
@@ -17206,7 +17313,7 @@ var MemoryManager = class {
|
|
|
17206
17313
|
return `${e.id} ${e.summary} (${e.charLength} chars)`;
|
|
17207
17314
|
}
|
|
17208
17315
|
buildConsolidateHint(target) {
|
|
17209
|
-
const
|
|
17316
|
+
const budget2 = this.getBudget()[target];
|
|
17210
17317
|
const heat = /* @__PURE__ */ new Map();
|
|
17211
17318
|
for (const row of this.db.getAll(target)) {
|
|
17212
17319
|
const id = this.idByContent.get(contentKey(row.target, row.content));
|
|
@@ -17214,7 +17321,7 @@ var MemoryManager = class {
|
|
|
17214
17321
|
}
|
|
17215
17322
|
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);
|
|
17216
17323
|
return [
|
|
17217
|
-
`Memory at ${
|
|
17324
|
+
`Memory at ${budget2.current.toLocaleString()}/${budget2.limit.toLocaleString()} chars (${budget2.percent}%) for ${target}. Cannot add new entry.`,
|
|
17218
17325
|
"",
|
|
17219
17326
|
"To make room, work by id \u2014 NOT by old_text. The MEMORY INDEX only shows a truncated",
|
|
17220
17327
|
"first line, so text copied from it will never match an entry exactly.",
|
|
@@ -19087,7 +19194,7 @@ var SessionManager = class {
|
|
|
19087
19194
|
search(input) {
|
|
19088
19195
|
return this.db.search(input);
|
|
19089
19196
|
}
|
|
19090
|
-
async compact(sessionId,
|
|
19197
|
+
async compact(sessionId, summarize2) {
|
|
19091
19198
|
const messages = this.db.getMessages(sessionId);
|
|
19092
19199
|
const beforeCount = messages.length;
|
|
19093
19200
|
const IMPORTANT_ROUNDS = 5;
|
|
@@ -19098,17 +19205,17 @@ var SessionManager = class {
|
|
|
19098
19205
|
0,
|
|
19099
19206
|
Math.max(0, keyMessages.length - IMPORTANT_ROUNDS * 2)
|
|
19100
19207
|
);
|
|
19101
|
-
const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize,
|
|
19208
|
+
const summary = toSummarize.length === 0 ? "" : await this.buildSummary(toSummarize, summarize2) ?? outlineOf(toSummarize);
|
|
19102
19209
|
return this.db.compact(sessionId, summary, beforeCount, IMPORTANT_ROUNDS * 2);
|
|
19103
19210
|
}
|
|
19104
19211
|
archiveAndCompact(sessionId, input) {
|
|
19105
19212
|
return this.db.archiveAndCompact(sessionId, input);
|
|
19106
19213
|
}
|
|
19107
|
-
async buildSummary(msgs,
|
|
19108
|
-
if (!
|
|
19214
|
+
async buildSummary(msgs, summarize2) {
|
|
19215
|
+
if (!summarize2) return null;
|
|
19109
19216
|
const transcript = msgs.map((m) => `[${m.role}] ${m.content}`).join("\n\n");
|
|
19110
19217
|
try {
|
|
19111
|
-
const result = await
|
|
19218
|
+
const result = await summarize2(transcript);
|
|
19112
19219
|
return result?.trim() ? result.trim() : null;
|
|
19113
19220
|
} catch {
|
|
19114
19221
|
return null;
|
|
@@ -19296,8 +19403,8 @@ var GoalService = class {
|
|
|
19296
19403
|
const text = objective.trim();
|
|
19297
19404
|
if (!text) return { ok: false, reason: "empty-objective" };
|
|
19298
19405
|
if (text.length > MAX_OBJECTIVE_CHARS) return { ok: false, reason: "objective-too-long" };
|
|
19299
|
-
const
|
|
19300
|
-
if (!Number.isInteger(
|
|
19406
|
+
const budget2 = maxRounds ?? DEFAULT_GOAL_MAX_ROUNDS;
|
|
19407
|
+
if (!Number.isInteger(budget2) || budget2 < 1 || budget2 > MAX_GOAL_MAX_ROUNDS) {
|
|
19301
19408
|
return { ok: false, reason: "bad-budget" };
|
|
19302
19409
|
}
|
|
19303
19410
|
const existing = this.current(sessionId);
|
|
@@ -19309,7 +19416,7 @@ var GoalService = class {
|
|
|
19309
19416
|
objective: text,
|
|
19310
19417
|
phase: "active",
|
|
19311
19418
|
block: void 0,
|
|
19312
|
-
maxRounds:
|
|
19419
|
+
maxRounds: budget2,
|
|
19313
19420
|
roundsUsed: 0,
|
|
19314
19421
|
completeEvidence: void 0,
|
|
19315
19422
|
createdAt: at,
|
|
@@ -23437,7 +23544,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23437
23544
|
const dir = join(staging, category, name);
|
|
23438
23545
|
mkdirSync(dir, { recursive: true });
|
|
23439
23546
|
copyFileSync(join(source, SKILL_FILE), join(dir, SKILL_FILE));
|
|
23440
|
-
let
|
|
23547
|
+
let budget2 = MAX_FILES_PER_SKILL - 1;
|
|
23441
23548
|
for (const entry of readEntries2(source, label, issues, lang)) {
|
|
23442
23549
|
if (entry.name === SKILL_FILE) continue;
|
|
23443
23550
|
if (!entry.isDir || !SKILL_ASSET_DIRS.includes(entry.name)) {
|
|
@@ -23447,7 +23554,7 @@ function stageSkillDir(source, staging, category, name, skills, issues, lang) {
|
|
|
23447
23554
|
});
|
|
23448
23555
|
continue;
|
|
23449
23556
|
}
|
|
23450
|
-
|
|
23557
|
+
budget2 = copyTree(join(source, entry.name), join(dir, entry.name), label, budget2, issues, lang);
|
|
23451
23558
|
}
|
|
23452
23559
|
skills.push({ name, category, dir });
|
|
23453
23560
|
}
|
|
@@ -23506,8 +23613,8 @@ function placeOf(root, parts, lang) {
|
|
|
23506
23613
|
const category = parts.at(-2) ?? "general";
|
|
23507
23614
|
return { name, category: skillSegmentIssue(category, lang) === void 0 ? category : "general" };
|
|
23508
23615
|
}
|
|
23509
|
-
function copyTree(from, to, label,
|
|
23510
|
-
let left =
|
|
23616
|
+
function copyTree(from, to, label, budget2, issues, lang) {
|
|
23617
|
+
let left = budget2;
|
|
23511
23618
|
mkdirSync(to, { recursive: true });
|
|
23512
23619
|
for (const entry of readEntries2(from, label, issues, lang)) {
|
|
23513
23620
|
if (left <= 0) {
|
|
@@ -24571,11 +24678,11 @@ function readOne(path, opts, usedBytes) {
|
|
|
24571
24678
|
}
|
|
24572
24679
|
const remaining = MAX_ATTACH_TOTAL_BYTES - usedBytes;
|
|
24573
24680
|
if (remaining <= 0) return { part: { type: "file", path, omitted: "over-limit", bytes: size } };
|
|
24574
|
-
const
|
|
24575
|
-
if (raw.length <=
|
|
24681
|
+
const budget2 = Math.min(MAX_ATTACH_BYTES, remaining);
|
|
24682
|
+
if (raw.length <= budget2) {
|
|
24576
24683
|
return { part: { type: "file", path, text: raw.toString("utf8"), bytes: size } };
|
|
24577
24684
|
}
|
|
24578
|
-
const { text, truncatedTo } = truncateToBudget(raw,
|
|
24685
|
+
const { text, truncatedTo } = truncateToBudget(raw, budget2);
|
|
24579
24686
|
return {
|
|
24580
24687
|
part: { type: "file", path, text, truncatedTo, bytes: size },
|
|
24581
24688
|
notice: t("mentions.truncated", {
|