@epoch-agent/core 0.13.0 → 0.15.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 +36 -0
- package/dist/index.d.ts +681 -68
- package/dist/index.js +666 -175
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync, statSync, readdirSync, readFileSync, mkdirSync, writeFileSy
|
|
|
2
2
|
import { homedir, platform, tmpdir, hostname } from 'os';
|
|
3
3
|
import { join, dirname, resolve, relative, isAbsolute, sep, extname, basename } from 'path';
|
|
4
4
|
import { execFile, execSync, execFileSync, spawn } from 'child_process';
|
|
5
|
-
import { createLogger, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, t, suggestKey, misspelledKeyIssues, openDatabase, migrate, releaseDatabase, parseLenient, issueDetails, splitWords, unknownKeyIssues, checkpointsDir, pluginsDir, projectHooksPath, projectClaudeSettingsPath, projectClaudeLocalSettingsPath, projectSettingsPath, projectLocalSettingsPath, projectPoliciesDir, trustedImportsPath, budgetStatePath, artifactsDir, UNLIMITED_TURNS, turnLimitOf, configPath, managedSettingsPath, getSecretValues, listStoredSecretNames, maskApiKey, setSectionField, isInWorkspace, workspacesPath, samePath, lastSessionsPath, automationLogsDir, projectComplianceDir, projectSkillsDir,
|
|
5
|
+
import { createLogger, dbPath, resolveHomeDir, DEFAULT_MAX_TURNS, PROJECT_DIR_NAME, guardSpawn, t, suggestKey, misspelledKeyIssues, openDatabase, migrate, releaseDatabase, parseLenient, issueDetails, splitWords, unknownKeyIssues, checkpointsDir, pluginsDir, projectHooksPath, projectClaudeSettingsPath, projectClaudeLocalSettingsPath, projectSettingsPath, projectLocalSettingsPath, projectPoliciesDir, trustedImportsPath, canProbeGit, budgetStatePath, artifactsDir, UNLIMITED_TURNS, turnLimitOf, configPath, managedSettingsPath, getSecretValues, listStoredSecretNames, maskApiKey, setSectionField, countCodePoints, headCodePoints, attachmentsDir, isInWorkspace, workspacesPath, samePath, lastSessionsPath, automationLogsDir, projectComplianceDir, projectSkillsDir, trustPath, projectCommandsDir, detectBackend, EXEC_PATH_AS_NODE_ENV, isolate, createStreamDecoder, parseShellCommand, writeArtifact, envPath, checkDangerousCommand, checkObfuscation, keepHeadAndTail, normalizeForMatch, isReadOnlyCommand, CODE_EXEC_ROOTS, tailCodePoints } from '@epoch-agent/infra';
|
|
6
6
|
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';
|
|
7
7
|
import { PROVIDER_TYPES, OPERATION_TYPES as OPERATION_TYPES$1, COMPLIANCE_CATEGORIES, COMPLIANCE_ACTIONS, SEARCH_PROVIDER_TYPES, CURRENCIES, LANGS, PERMISSION_LEVELS, SHELL_KINDS, ToolExposure, MAX_OPTIONS, MIN_OPTIONS, MAX_HEADER_CHARS, MAX_QUESTIONS, SCHEDULE_INTERVAL_MINUTES, isPermissionLevel, SCHEDULE_DRAFT_TOOL, isValidAgentRoleName, DEFAULT_AGENT_ROLE, isValidCommandName, RESERVED_COMMAND_NAMES, parseModelRef, isWirePluginArchiveName, systemNote, formatMoney, totalUsageTokens, NOOP_TELEMETRY, METRIC, contentToText, GEN_AI, isPromptOversize, promptTokens, apiKeyEnvVar, PROVIDER_INFOS, isProviderType, API_KEY_ENV_VARS, KEY_ACTIONS, tableOf, perAction, isKeyAction, parseSequence, RESERVED_CHORDS, chordId, sequenceId, ACTION_CONTEXTS, SEQUENCE_CONTEXTS, assertNeverPart, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_SESSION_REFS, utf8ByteLength, truncateToBudget, attachSessionSurface, isContextNearlyFull, isOperationType, normalizeApproval, imagePartOmittedSummary, MAX_ATTACH_BYTES, SIMULTANEOUS_CONTEXTS, SESSION_REFERENCE_ERROR_CODES, filePartSummary, sessionPartSummary } from '@epoch-agent/protocol';
|
|
8
8
|
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';
|
|
@@ -476,10 +476,18 @@ var runCommand2;
|
|
|
476
476
|
var init_backend = __esm({
|
|
477
477
|
"src/schedule/os/backend.ts"() {
|
|
478
478
|
runCommand2 = (file, args) => new Promise((resolve16) => {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
479
|
+
guardSpawn(
|
|
480
|
+
() => execFile(
|
|
481
|
+
file,
|
|
482
|
+
[...args],
|
|
483
|
+
{ encoding: "buffer", windowsHide: true },
|
|
484
|
+
(err, stdout, stderr) => {
|
|
485
|
+
const code = err && typeof err.code === "number" ? err.code ?? 1 : err ? 1 : 0;
|
|
486
|
+
resolve16({ code, stdout: decodeOutput(stdout), stderr: decodeOutput(stderr) });
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
(err) => resolve16({ code: 1, stdout: "", stderr: `${file}: ${err.message}` })
|
|
490
|
+
);
|
|
483
491
|
});
|
|
484
492
|
}
|
|
485
493
|
});
|
|
@@ -534,6 +542,7 @@ var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
|
|
|
534
542
|
"session_messages_search",
|
|
535
543
|
"session_messages_read",
|
|
536
544
|
"session_trace",
|
|
545
|
+
"session_list",
|
|
537
546
|
"goal",
|
|
538
547
|
"skill_view",
|
|
539
548
|
"tool_search",
|
|
@@ -1109,6 +1118,7 @@ var BLOCKED_TOOLS = Object.freeze([
|
|
|
1109
1118
|
"session_messages_search",
|
|
1110
1119
|
"session_messages_read",
|
|
1111
1120
|
"session_trace",
|
|
1121
|
+
"session_list",
|
|
1112
1122
|
"goal"
|
|
1113
1123
|
]);
|
|
1114
1124
|
var DelegateManager = class {
|
|
@@ -2430,8 +2440,9 @@ var SCHEDULE_ISSUE_CODES = [
|
|
|
2430
2440
|
];
|
|
2431
2441
|
var SCHEDULE_DEFAULTS = {
|
|
2432
2442
|
maxTurns: DEFAULT_MAX_TURNS,
|
|
2433
|
-
timeoutMs:
|
|
2443
|
+
timeoutMs: 60 * 60 * 1e3
|
|
2434
2444
|
};
|
|
2445
|
+
var SCHEDULE_FORM_BUDGET_USD = 200;
|
|
2435
2446
|
var SCHEDULE_DEFAULT_ALLOWLIST = {
|
|
2436
2447
|
allowTools: [],
|
|
2437
2448
|
allowOperations: ["file_read"],
|
|
@@ -3039,9 +3050,7 @@ function validateSchedule(input) {
|
|
|
3039
3050
|
}
|
|
3040
3051
|
function bypassIssues(input) {
|
|
3041
3052
|
const issues = [];
|
|
3042
|
-
if (
|
|
3043
|
-
issues.push({ code: "bypass-needs-workdir" });
|
|
3044
|
-
} else if (isTooBroad(input.workDir, input.homeDir)) {
|
|
3053
|
+
if (input.workDir.trim() && isTooBroad(input.workDir, input.homeDir)) {
|
|
3045
3054
|
issues.push({ code: "bypass-workdir-too-broad", detail: input.workDir });
|
|
3046
3055
|
}
|
|
3047
3056
|
const missingRuler = !(input.maxBudgetUsd > 0) || !(input.timeoutMs > 0);
|
|
@@ -3431,11 +3440,13 @@ var SESSION_SEARCH_TOOL = "session_search";
|
|
|
3431
3440
|
var SESSION_MESSAGES_SEARCH_TOOL = "session_messages_search";
|
|
3432
3441
|
var SESSION_MESSAGES_READ_TOOL = "session_messages_read";
|
|
3433
3442
|
var SESSION_TRACE_TOOL = "session_trace";
|
|
3443
|
+
var SESSION_LIST_TOOL = "session_list";
|
|
3434
3444
|
var SESSION_QUERY_TOOLS = Object.freeze([
|
|
3435
3445
|
SESSION_SEARCH_TOOL,
|
|
3436
3446
|
SESSION_MESSAGES_SEARCH_TOOL,
|
|
3437
3447
|
SESSION_MESSAGES_READ_TOOL,
|
|
3438
|
-
SESSION_TRACE_TOOL
|
|
3448
|
+
SESSION_TRACE_TOOL,
|
|
3449
|
+
SESSION_LIST_TOOL
|
|
3439
3450
|
]);
|
|
3440
3451
|
var MAX_SNIPPET = 160;
|
|
3441
3452
|
var CANDIDATE_FACTOR = 4;
|
|
@@ -3529,6 +3540,36 @@ var SessionQueries = class {
|
|
|
3529
3540
|
trace(input) {
|
|
3530
3541
|
return traceSession(this.db, input);
|
|
3531
3542
|
}
|
|
3543
|
+
listSessions(input) {
|
|
3544
|
+
const vis = resolveSessionVisibility({ ...input, db: this.db });
|
|
3545
|
+
const archivedClause = input.archived === "all" ? "" : input.archived === "only" ? "AND s.archived = 1" : "AND s.archived = 0";
|
|
3546
|
+
const where = `${vis.clause} ${archivedClause}`;
|
|
3547
|
+
const total = this.db.prepare(`SELECT count(*) AS n FROM sessions s WHERE ${where}`).get(vis.params).n;
|
|
3548
|
+
const rows = this.db.prepare(
|
|
3549
|
+
`SELECT s.id,
|
|
3550
|
+
COALESCE(NULLIF(s.display_name, ''), s.title) AS title,
|
|
3551
|
+
s.cwd,
|
|
3552
|
+
COALESCE(s.updated_at, s.started_at) AS updated_at,
|
|
3553
|
+
s.message_count,
|
|
3554
|
+
s.archived
|
|
3555
|
+
FROM sessions s
|
|
3556
|
+
WHERE ${where}
|
|
3557
|
+
ORDER BY COALESCE(s.updated_at, s.started_at) DESC
|
|
3558
|
+
LIMIT @limit`
|
|
3559
|
+
).all({ ...vis.params, limit: input.limit });
|
|
3560
|
+
return {
|
|
3561
|
+
total,
|
|
3562
|
+
sessions: rows.map((row) => ({
|
|
3563
|
+
sessionId: row.id,
|
|
3564
|
+
title: row.title,
|
|
3565
|
+
cwd: row.cwd ?? void 0,
|
|
3566
|
+
updatedAt: row.updated_at,
|
|
3567
|
+
messageCount: row.message_count,
|
|
3568
|
+
archived: row.archived === 1,
|
|
3569
|
+
isCurrent: row.id === input.currentSessionId
|
|
3570
|
+
}))
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3532
3573
|
contentRows(safe, limit, visClause, visParams) {
|
|
3533
3574
|
const sql = (table) => `
|
|
3534
3575
|
SELECT m.id, m.session_id, m.role, m.content, m.timestamp, m.active,
|
|
@@ -3594,7 +3635,123 @@ var SessionQueries = class {
|
|
|
3594
3635
|
return this.db.prepare(sql("messages_fts_trigram")).all({ query: buildTrigramMatchQuery(safe), sid: sessionId, limit });
|
|
3595
3636
|
}
|
|
3596
3637
|
};
|
|
3597
|
-
// src/tools/builtin/session-
|
|
3638
|
+
// src/tools/builtin/session-list.ts
|
|
3639
|
+
var DEFAULT_LIMIT = 10;
|
|
3640
|
+
var MAX_LIMIT = 30;
|
|
3641
|
+
var MAX_TITLE = 80;
|
|
3642
|
+
function fail3(message, start, code, suggestion) {
|
|
3643
|
+
return {
|
|
3644
|
+
success: false,
|
|
3645
|
+
output: "",
|
|
3646
|
+
error: { code, message, ...{} },
|
|
3647
|
+
duration: Date.now() - start
|
|
3648
|
+
};
|
|
3649
|
+
}
|
|
3650
|
+
function clampLimit(raw) {
|
|
3651
|
+
const n = Number(raw);
|
|
3652
|
+
if (!Number.isFinite(n) || n <= 0) return DEFAULT_LIMIT;
|
|
3653
|
+
return Math.min(Math.floor(n), MAX_LIMIT);
|
|
3654
|
+
}
|
|
3655
|
+
function stamp(ms) {
|
|
3656
|
+
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
3657
|
+
}
|
|
3658
|
+
function archivedScopeOf(raw) {
|
|
3659
|
+
return raw === "only" || raw === "all" ? raw : "exclude";
|
|
3660
|
+
}
|
|
3661
|
+
function scopeNote(allWorkspaces, archived) {
|
|
3662
|
+
const where = allWorkspaces ? "all workspaces" : "current workspace + this session lineage";
|
|
3663
|
+
const which = archived === "only" ? "archived only" : archived === "all" ? "archived included" : "archived excluded";
|
|
3664
|
+
return `${where}, ${which}`;
|
|
3665
|
+
}
|
|
3666
|
+
function renderEntry(entry, index) {
|
|
3667
|
+
const self = entry.isCurrent ? " (this session)" : "";
|
|
3668
|
+
const title = entry.title.length > MAX_TITLE ? `${entry.title.slice(0, MAX_TITLE)}\u2026` : entry.title;
|
|
3669
|
+
const where = entry.cwd ? ` \xB7 ${entry.cwd}` : "";
|
|
3670
|
+
const archived = entry.archived ? " \xB7 archived" : "";
|
|
3671
|
+
return [
|
|
3672
|
+
`${index + 1}. ${entry.sessionId}${self} \u2014 ${title || "(untitled)"}`,
|
|
3673
|
+
` ${stamp(entry.updatedAt)} \xB7 ${entry.messageCount} messages${where}${archived}`
|
|
3674
|
+
].join("\n");
|
|
3675
|
+
}
|
|
3676
|
+
function render(out, note) {
|
|
3677
|
+
const shown = out.sessions.length;
|
|
3678
|
+
const head = shown < out.total ? `${out.total} session(s) (${note}), showing the ${shown} most recently active:` : `${out.total} session(s) (${note}):`;
|
|
3679
|
+
return [
|
|
3680
|
+
head,
|
|
3681
|
+
"",
|
|
3682
|
+
...out.sessions.map(renderEntry),
|
|
3683
|
+
"",
|
|
3684
|
+
"Next: session_messages_search({ sessionId, query }) to look inside one, or session_messages_read({ sessionId, messageId }) once you have a hit."
|
|
3685
|
+
].join("\n");
|
|
3686
|
+
}
|
|
3687
|
+
function createSessionListTool(deps) {
|
|
3688
|
+
return {
|
|
3689
|
+
name: SESSION_LIST_TOOL,
|
|
3690
|
+
description: "\u5217\u51FA\u4F60\u80FD\u8BFB\u5230\u7684\u5386\u53F2\u4F1A\u8BDD \u2014\u2014 \u68C0\u7D22\u90A3\u51E0\u4E2A\u90FD\u8981\u5148\u60F3\u51FA\u4E00\u4E2A\u8BCD\uFF0C\u8FD9\u4E2A\u4E0D\u8981\u3002\n\u7528\u5B83\u56DE\u7B54\u300C\u6211\u90FD\u6709\u54EA\u4E9B\u4F1A\u8BDD\u300D\u300C\u4E0A\u6B21\u90A3\u6BB5\u804A\u7684\u662F\u4EC0\u4E48\u300D\uFF0C\u4EE5\u53CA\u7528\u6237\u63D0\u8D77\u67D0\u6BB5\u8FC7\u53BB\u7684\u4F1A\u8BDD\u5374\u6CA1\u7ED9 id \u7684\u65F6\u5019\u3002\n\u6309\u6700\u540E\u6D3B\u52A8\u5012\u5E8F\uFF0C\u6BCF\u6BB5\u7ED9 sessionId + \u6807\u9898 + \u65F6\u95F4 + \u6D88\u606F\u6570\uFF1B\u62FF\u5230 id \u518D\u7528 session_messages_search \u8FDB\u53BB\u770B\u3002\n\u9ED8\u8BA4\u4E0D\u5217\u5F52\u6863\u7684\u4F1A\u8BDD\uFF08\u5F52\u6863\u662F\u300C\u7528\u6237\u628A\u5B83\u6536\u8D77\u6765\u4E86\u300D\uFF09\u2014\u2014 \u8981\u627E\u5F52\u6863\u7684\u5C31\u4F20 archived\u3002\n\u9ED8\u8BA4\u53EA\u5217\u5F53\u524D\u5DE5\u4F5C\u533A\u7684\u4F1A\u8BDD\uFF0C\u5916\u52A0\u672C\u4F1A\u8BDD fork \u51FA\u6765\u7684\u90A3\u6761\u8840\u7F18\u94FE\u3002",
|
|
3691
|
+
get parameters() {
|
|
3692
|
+
return {
|
|
3693
|
+
type: "object",
|
|
3694
|
+
properties: {
|
|
3695
|
+
limit: {
|
|
3696
|
+
type: "number",
|
|
3697
|
+
description: `\u56DE\u51E0\u6BB5\uFF0C\u9ED8\u8BA4 ${DEFAULT_LIMIT}\uFF0C\u4E0A\u9650 ${MAX_LIMIT}\uFF08\u4F20\u5927\u4E86\u81EA\u52A8\u5939\u7D27\uFF0C\u4E0D\u62A5\u9519\uFF09`
|
|
3698
|
+
},
|
|
3699
|
+
archived: {
|
|
3700
|
+
type: "string",
|
|
3701
|
+
enum: ["exclude", "only", "all"],
|
|
3702
|
+
description: "exclude \u4E0D\u5217\u5F52\u6863\u7684\uFF08\u9ED8\u8BA4\uFF09\uFF1Bonly \u53EA\u5217\u5F52\u6863\u7684\uFF1Ball \u4E24\u8FB9\u90FD\u5217\u3002\u7528\u6237\u63D0\u8D77\u4E00\u6BB5\u300C\u4EE5\u524D\u5F52\u6863\u6389\u7684\u4F1A\u8BDD\u300D\u65F6\u7528 only"
|
|
3703
|
+
},
|
|
3704
|
+
...deps.allowAllWorkspaces ? {
|
|
3705
|
+
allWorkspaces: {
|
|
3706
|
+
type: "boolean",
|
|
3707
|
+
description: "\u5217\u5168\u90E8\u5DE5\u4F5C\u533A\u7684\u4F1A\u8BDD\uFF08\u9ED8\u8BA4 false\uFF0C\u53EA\u5217\u5F53\u524D\u5DE5\u4F5C\u533A\uFF09"
|
|
3708
|
+
}
|
|
3709
|
+
} : {}
|
|
3710
|
+
},
|
|
3711
|
+
required: []
|
|
3712
|
+
};
|
|
3713
|
+
},
|
|
3714
|
+
exposure: ToolExposure.Direct,
|
|
3715
|
+
supportsParallel: true,
|
|
3716
|
+
annotations: {
|
|
3717
|
+
readOnlyHint: true,
|
|
3718
|
+
destructiveHint: false,
|
|
3719
|
+
idempotentHint: true,
|
|
3720
|
+
openWorldHint: true
|
|
3721
|
+
},
|
|
3722
|
+
operation: "file_read",
|
|
3723
|
+
describeTarget: (args) => `${SESSION_LIST_TOOL}:${archivedScopeOf(args["archived"])}`,
|
|
3724
|
+
execute(args, ctx) {
|
|
3725
|
+
const start = Date.now();
|
|
3726
|
+
const allWorkspaces = deps.allowAllWorkspaces === true && args["allWorkspaces"] === true;
|
|
3727
|
+
const archived = archivedScopeOf(args["archived"]);
|
|
3728
|
+
try {
|
|
3729
|
+
const out = deps.queries.listSessions({
|
|
3730
|
+
limit: clampLimit(args["limit"]),
|
|
3731
|
+
archived,
|
|
3732
|
+
currentSessionId: ctx.sessionId,
|
|
3733
|
+
workspaceCwd: deps.workspaceCwd,
|
|
3734
|
+
allWorkspaces
|
|
3735
|
+
});
|
|
3736
|
+
if (out.sessions.length === 0) {
|
|
3737
|
+
const hint = archived === "exclude" ? ' If the user is asking about a session they archived, retry with archived: "only".' : "";
|
|
3738
|
+
return Promise.resolve({
|
|
3739
|
+
success: true,
|
|
3740
|
+
output: `No session in readable scope (${scopeNote(allWorkspaces, archived)}).${hint}`,
|
|
3741
|
+
duration: Date.now() - start
|
|
3742
|
+
});
|
|
3743
|
+
}
|
|
3744
|
+
return Promise.resolve({
|
|
3745
|
+
success: true,
|
|
3746
|
+
output: render(out, scopeNote(allWorkspaces, archived)),
|
|
3747
|
+
duration: Date.now() - start
|
|
3748
|
+
});
|
|
3749
|
+
} catch (err) {
|
|
3750
|
+
return Promise.resolve(fail3(err instanceof Error ? err.message : String(err), start, 8014));
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
};
|
|
3754
|
+
}
|
|
3598
3755
|
var DEFAULT_WINDOW = 2;
|
|
3599
3756
|
var MAX_WINDOW = 10;
|
|
3600
3757
|
var DEFAULT_TRACE_LIMIT = 20;
|
|
@@ -3602,7 +3759,7 @@ var MAX_TRACE_LIMIT = 50;
|
|
|
3602
3759
|
var BODY_BUDGET = 1500;
|
|
3603
3760
|
var MIN_BODY = 60;
|
|
3604
3761
|
var ANCHOR_SHARE = 4;
|
|
3605
|
-
function
|
|
3762
|
+
function fail4(message, start, code, suggestion) {
|
|
3606
3763
|
return {
|
|
3607
3764
|
success: false,
|
|
3608
3765
|
output: "",
|
|
@@ -3616,7 +3773,7 @@ function clampWindow(raw, fallback2, max) {
|
|
|
3616
3773
|
if (!Number.isFinite(n) || n < 0) return fallback2;
|
|
3617
3774
|
return Math.min(Math.floor(n), max);
|
|
3618
3775
|
}
|
|
3619
|
-
function
|
|
3776
|
+
function stamp2(ms) {
|
|
3620
3777
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
3621
3778
|
}
|
|
3622
3779
|
function budgetOf(total) {
|
|
@@ -3638,7 +3795,7 @@ function surfaceOf(record, isCurrent) {
|
|
|
3638
3795
|
function renderRecord(record, mark, budget, isCurrent) {
|
|
3639
3796
|
const tool = record.toolName ? ` \xB7 ${record.toolName}` : "";
|
|
3640
3797
|
return [
|
|
3641
|
-
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${
|
|
3798
|
+
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${stamp2(record.timestamp)} \xB7 ${surfaceOf(record, isCurrent)}]`,
|
|
3642
3799
|
` ${body(record.content, budget).split("\n").join("\n ")}`
|
|
3643
3800
|
].join("\n");
|
|
3644
3801
|
}
|
|
@@ -3704,11 +3861,11 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3704
3861
|
execute(args, ctx) {
|
|
3705
3862
|
const start = Date.now();
|
|
3706
3863
|
const sessionId = String(args["sessionId"] ?? "").trim();
|
|
3707
|
-
if (!sessionId) return Promise.resolve(
|
|
3864
|
+
if (!sessionId) return Promise.resolve(fail4("sessionId must not be empty", start, 8007));
|
|
3708
3865
|
const messageId = Number(args["messageId"]);
|
|
3709
3866
|
if (!Number.isInteger(messageId) || messageId <= 0) {
|
|
3710
3867
|
return Promise.resolve(
|
|
3711
|
-
|
|
3868
|
+
fail4(
|
|
3712
3869
|
"messageId must be a positive integer",
|
|
3713
3870
|
start,
|
|
3714
3871
|
8008,
|
|
@@ -3729,7 +3886,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3729
3886
|
});
|
|
3730
3887
|
if (!out.authorized) {
|
|
3731
3888
|
return Promise.resolve(
|
|
3732
|
-
|
|
3889
|
+
fail4(
|
|
3733
3890
|
`session ${sessionId} is out of readable scope`,
|
|
3734
3891
|
start,
|
|
3735
3892
|
8009,
|
|
@@ -3739,7 +3896,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3739
3896
|
}
|
|
3740
3897
|
if (!out.anchor) {
|
|
3741
3898
|
return Promise.resolve(
|
|
3742
|
-
|
|
3899
|
+
fail4(
|
|
3743
3900
|
`session ${sessionId} has no message #${messageId} (it has ${out.total})`,
|
|
3744
3901
|
start,
|
|
3745
3902
|
8010,
|
|
@@ -3753,7 +3910,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3753
3910
|
duration: Date.now() - start
|
|
3754
3911
|
});
|
|
3755
3912
|
} catch (err) {
|
|
3756
|
-
return Promise.resolve(
|
|
3913
|
+
return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8011));
|
|
3757
3914
|
}
|
|
3758
3915
|
}
|
|
3759
3916
|
};
|
|
@@ -3767,7 +3924,7 @@ function renderNode(node, isCurrent) {
|
|
|
3767
3924
|
const where = node.cwd ? ` \xB7 ${node.cwd}` : "";
|
|
3768
3925
|
const archived = node.archived ? " \xB7 archived" : "";
|
|
3769
3926
|
return `${indent}${node.sessionId}${self} \u2014 ${node.title || "(untitled)"}
|
|
3770
|
-
${indent} ${
|
|
3927
|
+
${indent} ${stamp2(node.startedAt ?? 0)} \xB7 ${node.messageCount ?? 0} messages${where}${archived}`;
|
|
3771
3928
|
}
|
|
3772
3929
|
function renderTrace(trace, currentSessionId) {
|
|
3773
3930
|
const anchor = trace.anchor;
|
|
@@ -3846,7 +4003,7 @@ function createSessionTraceTool(deps) {
|
|
|
3846
4003
|
});
|
|
3847
4004
|
if (!trace.authorized) {
|
|
3848
4005
|
return Promise.resolve(
|
|
3849
|
-
|
|
4006
|
+
fail4(
|
|
3850
4007
|
`session ${sessionId} is out of readable scope`,
|
|
3851
4008
|
start,
|
|
3852
4009
|
8012,
|
|
@@ -3860,14 +4017,14 @@ function createSessionTraceTool(deps) {
|
|
|
3860
4017
|
duration: Date.now() - start
|
|
3861
4018
|
});
|
|
3862
4019
|
} catch (err) {
|
|
3863
|
-
return Promise.resolve(
|
|
4020
|
+
return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8013));
|
|
3864
4021
|
}
|
|
3865
4022
|
}
|
|
3866
4023
|
};
|
|
3867
4024
|
}
|
|
3868
|
-
var
|
|
3869
|
-
var
|
|
3870
|
-
function
|
|
4025
|
+
var DEFAULT_LIMIT2 = 5;
|
|
4026
|
+
var MAX_LIMIT2 = 20;
|
|
4027
|
+
function fail5(message, start, code, suggestion) {
|
|
3871
4028
|
return {
|
|
3872
4029
|
success: false,
|
|
3873
4030
|
output: "",
|
|
@@ -3878,12 +4035,12 @@ function fail4(message, start, code, suggestion) {
|
|
|
3878
4035
|
function emptyHint(query) {
|
|
3879
4036
|
return belowTrigramFloor(sanitizeFtsQuery(query)) ? ` Note: every word here is shorter than ${TRIGRAM_MIN_CHARS} characters, which the substring index cannot match at all \u2014 this is "cannot search", not "not found". Retry with a longer phrase.` : " Try fewer or different words.";
|
|
3880
4037
|
}
|
|
3881
|
-
function
|
|
4038
|
+
function clampLimit2(raw) {
|
|
3882
4039
|
const n = Number(raw);
|
|
3883
|
-
if (!Number.isFinite(n) || n <= 0) return
|
|
3884
|
-
return Math.min(Math.floor(n),
|
|
4040
|
+
if (!Number.isFinite(n) || n <= 0) return DEFAULT_LIMIT2;
|
|
4041
|
+
return Math.min(Math.floor(n), MAX_LIMIT2);
|
|
3885
4042
|
}
|
|
3886
|
-
function
|
|
4043
|
+
function stamp3(ms) {
|
|
3887
4044
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
3888
4045
|
}
|
|
3889
4046
|
function surfaceNote(hit, isCurrent) {
|
|
@@ -3897,14 +4054,14 @@ function renderSessionHit(hit, index) {
|
|
|
3897
4054
|
const self = hit.isCurrent ? " (this session)" : "";
|
|
3898
4055
|
return [
|
|
3899
4056
|
`${index + 1}. ${hit.sessionId}${self} \u2014 ${hit.title || "(untitled)"}`,
|
|
3900
|
-
` ${
|
|
4057
|
+
` ${stamp3(hit.startedAt)} \xB7 ${hit.messageCount} messages${where}`,
|
|
3901
4058
|
` best match [${hit.best.role} #${hit.best.messageId}, ${surfaceNote(hit.best, hit.isCurrent)}]:`,
|
|
3902
4059
|
` ${hit.best.snippet}`
|
|
3903
4060
|
].join("\n");
|
|
3904
4061
|
}
|
|
3905
4062
|
function renderMessageHit(hit, isCurrent) {
|
|
3906
4063
|
return [
|
|
3907
|
-
`#${hit.messageId} [${hit.role} \xB7 ${
|
|
4064
|
+
`#${hit.messageId} [${hit.role} \xB7 ${stamp3(hit.timestamp)} \xB7 ${surfaceNote(hit, isCurrent)}]`,
|
|
3908
4065
|
` ${hit.snippet}`
|
|
3909
4066
|
].join("\n");
|
|
3910
4067
|
}
|
|
@@ -3922,7 +4079,7 @@ function createSessionSearchTool(deps) {
|
|
|
3922
4079
|
},
|
|
3923
4080
|
limit: {
|
|
3924
4081
|
type: "number",
|
|
3925
|
-
description: `\u8FD4\u56DE\u51E0\u6BB5\u4F1A\u8BDD\uFF0C\u9ED8\u8BA4 ${
|
|
4082
|
+
description: `\u8FD4\u56DE\u51E0\u6BB5\u4F1A\u8BDD\uFF0C\u9ED8\u8BA4 ${DEFAULT_LIMIT2}\uFF0C\u4E0A\u9650 ${MAX_LIMIT2}`
|
|
3926
4083
|
},
|
|
3927
4084
|
scope: {
|
|
3928
4085
|
type: "string",
|
|
@@ -3952,13 +4109,13 @@ function createSessionSearchTool(deps) {
|
|
|
3952
4109
|
execute(args, ctx) {
|
|
3953
4110
|
const start = Date.now();
|
|
3954
4111
|
const query = String(args["query"] ?? "").trim();
|
|
3955
|
-
if (!query) return Promise.resolve(
|
|
4112
|
+
if (!query) return Promise.resolve(fail5("query must not be empty", start, 8001));
|
|
3956
4113
|
const allWorkspaces = deps.allowAllWorkspaces === true && args["allWorkspaces"] === true;
|
|
3957
4114
|
const scope = args["scope"] === "title" ? "title" : "all";
|
|
3958
4115
|
try {
|
|
3959
4116
|
const hits = deps.queries.searchSessions({
|
|
3960
4117
|
query,
|
|
3961
|
-
limit:
|
|
4118
|
+
limit: clampLimit2(args["limit"]),
|
|
3962
4119
|
scope,
|
|
3963
4120
|
currentSessionId: ctx.sessionId,
|
|
3964
4121
|
workspaceCwd: deps.workspaceCwd,
|
|
@@ -3985,7 +4142,7 @@ function createSessionSearchTool(deps) {
|
|
|
3985
4142
|
});
|
|
3986
4143
|
} catch (err) {
|
|
3987
4144
|
return Promise.resolve(
|
|
3988
|
-
|
|
4145
|
+
fail5(
|
|
3989
4146
|
err instanceof Error ? err.message : String(err),
|
|
3990
4147
|
start,
|
|
3991
4148
|
8002,
|
|
@@ -4014,7 +4171,7 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4014
4171
|
},
|
|
4015
4172
|
limit: {
|
|
4016
4173
|
type: "number",
|
|
4017
|
-
description: `\u8FD4\u56DE\u51E0\u6761\uFF0C\u9ED8\u8BA4 ${
|
|
4174
|
+
description: `\u8FD4\u56DE\u51E0\u6761\uFF0C\u9ED8\u8BA4 ${DEFAULT_LIMIT2}\uFF0C\u4E0A\u9650 ${MAX_LIMIT2}`
|
|
4018
4175
|
},
|
|
4019
4176
|
...deps.allowAllWorkspaces ? {
|
|
4020
4177
|
allWorkspaces: {
|
|
@@ -4040,21 +4197,21 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4040
4197
|
const start = Date.now();
|
|
4041
4198
|
const sessionId = String(args["sessionId"] ?? "").trim();
|
|
4042
4199
|
const query = String(args["query"] ?? "").trim();
|
|
4043
|
-
if (!sessionId) return Promise.resolve(
|
|
4044
|
-
if (!query) return Promise.resolve(
|
|
4200
|
+
if (!sessionId) return Promise.resolve(fail5("sessionId must not be empty", start, 8003));
|
|
4201
|
+
if (!query) return Promise.resolve(fail5("query must not be empty", start, 8004));
|
|
4045
4202
|
const allWorkspaces = deps.allowAllWorkspaces === true && args["allWorkspaces"] === true;
|
|
4046
4203
|
try {
|
|
4047
4204
|
const out = deps.queries.searchMessages({
|
|
4048
4205
|
sessionId,
|
|
4049
4206
|
query,
|
|
4050
|
-
limit:
|
|
4207
|
+
limit: clampLimit2(args["limit"]),
|
|
4051
4208
|
currentSessionId: ctx.sessionId,
|
|
4052
4209
|
workspaceCwd: deps.workspaceCwd,
|
|
4053
4210
|
allWorkspaces
|
|
4054
4211
|
});
|
|
4055
4212
|
if (!out.authorized) {
|
|
4056
4213
|
return Promise.resolve(
|
|
4057
|
-
|
|
4214
|
+
fail5(
|
|
4058
4215
|
`session ${sessionId} is out of searchable scope`,
|
|
4059
4216
|
start,
|
|
4060
4217
|
8005,
|
|
@@ -4081,7 +4238,7 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4081
4238
|
});
|
|
4082
4239
|
} catch (err) {
|
|
4083
4240
|
return Promise.resolve(
|
|
4084
|
-
|
|
4241
|
+
fail5(
|
|
4085
4242
|
err instanceof Error ? err.message : String(err),
|
|
4086
4243
|
start,
|
|
4087
4244
|
8006,
|
|
@@ -4097,12 +4254,13 @@ function createSessionSearchTools(deps) {
|
|
|
4097
4254
|
createSessionSearchTool(deps),
|
|
4098
4255
|
createSessionMessagesSearchTool(deps),
|
|
4099
4256
|
createSessionMessagesReadTool(deps),
|
|
4100
|
-
createSessionTraceTool(deps)
|
|
4257
|
+
createSessionTraceTool(deps),
|
|
4258
|
+
createSessionListTool(deps)
|
|
4101
4259
|
];
|
|
4102
4260
|
}
|
|
4103
4261
|
var SKILL_VIEW_TOOL = "skill_view";
|
|
4104
4262
|
var MAX_SUGGESTED = 20;
|
|
4105
|
-
function
|
|
4263
|
+
function fail6(message, start, code, suggestion) {
|
|
4106
4264
|
return {
|
|
4107
4265
|
success: false,
|
|
4108
4266
|
output: "",
|
|
@@ -4147,18 +4305,18 @@ function createSkillViewTool(deps) {
|
|
|
4147
4305
|
const name = String(args["name"] ?? "").trim();
|
|
4148
4306
|
if (!name) {
|
|
4149
4307
|
return Promise.resolve(
|
|
4150
|
-
|
|
4308
|
+
fail6("name must not be empty", start, 3001, describeAvailableSkills(deps.skills))
|
|
4151
4309
|
);
|
|
4152
4310
|
}
|
|
4153
4311
|
const body2 = deps.skills.view(name);
|
|
4154
4312
|
if (body2 === null) {
|
|
4155
4313
|
return Promise.resolve(
|
|
4156
|
-
|
|
4314
|
+
fail6(`skill "${name}" not found`, start, 3002, describeAvailableSkills(deps.skills))
|
|
4157
4315
|
);
|
|
4158
4316
|
}
|
|
4159
4317
|
if (body2.trim() === "") {
|
|
4160
4318
|
return Promise.resolve(
|
|
4161
|
-
|
|
4319
|
+
fail6(
|
|
4162
4320
|
`skill "${name}" has an empty body \u2014 its SKILL.md is missing or empty`,
|
|
4163
4321
|
start,
|
|
4164
4322
|
3003,
|
|
@@ -4285,7 +4443,7 @@ var SKILL_EDIT_TOOL = "skill_edit";
|
|
|
4285
4443
|
var SKILL_PATCH_TOOL = "skill_patch";
|
|
4286
4444
|
var SKILL_WRITE_FILE_TOOL = "skill_write_file";
|
|
4287
4445
|
var WRITABLE_SKILL_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
4288
|
-
function
|
|
4446
|
+
function fail7(message, start, code, suggestion) {
|
|
4289
4447
|
return {
|
|
4290
4448
|
success: false,
|
|
4291
4449
|
output: "",
|
|
@@ -4297,7 +4455,7 @@ function done(output, start) {
|
|
|
4297
4455
|
return { success: true, output, duration: Date.now() - start };
|
|
4298
4456
|
}
|
|
4299
4457
|
function fromThrow(err, start, suggestion) {
|
|
4300
|
-
return
|
|
4458
|
+
return fail7(err instanceof Error ? err.message : String(err), start, 3102, suggestion);
|
|
4301
4459
|
}
|
|
4302
4460
|
function str2(args, key) {
|
|
4303
4461
|
const raw = args[key];
|
|
@@ -4353,13 +4511,13 @@ function createTool(deps) {
|
|
|
4353
4511
|
const content = str2(args, "content");
|
|
4354
4512
|
const category = str2(args, "category").trim() || "general";
|
|
4355
4513
|
if (!WRITABLE_SKILL_NAME.test(name)) {
|
|
4356
|
-
return
|
|
4514
|
+
return fail7(`invalid skill name: ${JSON.stringify(name)}`, start, 3101, WRITABLE_HINT);
|
|
4357
4515
|
}
|
|
4358
4516
|
if (!WRITABLE_SKILL_NAME.test(category)) {
|
|
4359
|
-
return
|
|
4517
|
+
return fail7(`invalid category: ${JSON.stringify(category)}`, start, 3101, WRITABLE_HINT);
|
|
4360
4518
|
}
|
|
4361
4519
|
const bad2 = checkFrontmatter(name, content);
|
|
4362
|
-
if (bad2 !== null) return
|
|
4520
|
+
if (bad2 !== null) return fail7(bad2, start, 3103);
|
|
4363
4521
|
try {
|
|
4364
4522
|
const path = await deps.skills.create(name, content, category);
|
|
4365
4523
|
return done(`created skill "${name}" at ${path}`, start);
|
|
@@ -4391,10 +4549,10 @@ function editTool(deps) {
|
|
|
4391
4549
|
const name = str2(args, "name").trim();
|
|
4392
4550
|
const content = str2(args, "content");
|
|
4393
4551
|
if (!name) {
|
|
4394
|
-
return
|
|
4552
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4395
4553
|
}
|
|
4396
4554
|
const bad2 = checkFrontmatter(name, content);
|
|
4397
|
-
if (bad2 !== null) return
|
|
4555
|
+
if (bad2 !== null) return fail7(bad2, start, 3103);
|
|
4398
4556
|
try {
|
|
4399
4557
|
await deps.skills.edit(name, content);
|
|
4400
4558
|
return done(`rewrote SKILL.md of skill "${name}"`, start);
|
|
@@ -4432,10 +4590,10 @@ function patchTool(deps) {
|
|
|
4432
4590
|
const oldString = str2(args, "old_string");
|
|
4433
4591
|
const filePath = str2(args, "file_path").trim();
|
|
4434
4592
|
if (!name) {
|
|
4435
|
-
return
|
|
4593
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4436
4594
|
}
|
|
4437
4595
|
if (oldString === "") {
|
|
4438
|
-
return
|
|
4596
|
+
return fail7("old_string must not be empty", start, 3101);
|
|
4439
4597
|
}
|
|
4440
4598
|
try {
|
|
4441
4599
|
await deps.skills.patch(
|
|
@@ -4477,9 +4635,9 @@ function writeFileTool(deps) {
|
|
|
4477
4635
|
const name = str2(args, "name").trim();
|
|
4478
4636
|
const filePath = str2(args, "file_path").trim();
|
|
4479
4637
|
if (!name) {
|
|
4480
|
-
return
|
|
4638
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4481
4639
|
}
|
|
4482
|
-
if (!filePath) return
|
|
4640
|
+
if (!filePath) return fail7("file_path must not be empty", start, 3101);
|
|
4483
4641
|
try {
|
|
4484
4642
|
await deps.skills.writeFile(name, filePath, str2(args, "content"));
|
|
4485
4643
|
return done(`wrote ${filePath} into skill "${name}"`, start);
|
|
@@ -4495,7 +4653,7 @@ function createSkillWriteTools(deps) {
|
|
|
4495
4653
|
var TOOL_SEARCH_TOOL = "tool_search";
|
|
4496
4654
|
var MAX_LISTED = 40;
|
|
4497
4655
|
var MAX_REVEAL_PER_CALL = 10;
|
|
4498
|
-
function
|
|
4656
|
+
function fail8(message, start, code, suggestion) {
|
|
4499
4657
|
return {
|
|
4500
4658
|
success: false,
|
|
4501
4659
|
output: "",
|
|
@@ -4545,12 +4703,12 @@ function createToolSearchTool(deps) {
|
|
|
4545
4703
|
const pool = deps.deferred();
|
|
4546
4704
|
const raw = String(args["query"] ?? "").trim();
|
|
4547
4705
|
if (!raw) {
|
|
4548
|
-
return Promise.resolve(
|
|
4706
|
+
return Promise.resolve(fail8("query must not be empty", start, 3101, available(pool)));
|
|
4549
4707
|
}
|
|
4550
4708
|
const terms = raw.toLowerCase().split(/\s+/).filter(Boolean);
|
|
4551
4709
|
const hits = pool.filter((tool) => matches(tool, terms));
|
|
4552
4710
|
if (hits.length === 0) {
|
|
4553
|
-
return Promise.resolve(
|
|
4711
|
+
return Promise.resolve(fail8(`No tool matches "${raw}"`, start, 3102, available(pool)));
|
|
4554
4712
|
}
|
|
4555
4713
|
const picked = hits.slice(0, MAX_REVEAL_PER_CALL);
|
|
4556
4714
|
for (const tool of picked) deps.reveal.reveal(tool.name);
|
|
@@ -5106,7 +5264,7 @@ function createRoleFile(input, opts) {
|
|
|
5106
5264
|
const detail = checked.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
|
|
5107
5265
|
return { ok: false, reason: "invalid-field", detail };
|
|
5108
5266
|
}
|
|
5109
|
-
const text =
|
|
5267
|
+
const text = render2(fm, input.prompt ?? "");
|
|
5110
5268
|
const file = `${name}.md`;
|
|
5111
5269
|
const back = parseRoleDefinition(text, file, opts.source ?? "user");
|
|
5112
5270
|
if (!back.role) {
|
|
@@ -5138,7 +5296,7 @@ function frontmatterOf(name, input) {
|
|
|
5138
5296
|
...input.maxTurns === void 0 ? {} : { maxTurns: input.maxTurns }
|
|
5139
5297
|
};
|
|
5140
5298
|
}
|
|
5141
|
-
function
|
|
5299
|
+
function render2(fm, prompt) {
|
|
5142
5300
|
const head = dump(fm, { lineWidth: -1, noRefs: true });
|
|
5143
5301
|
const body2 = prompt.trim();
|
|
5144
5302
|
return `---
|
|
@@ -6363,30 +6521,41 @@ function runCommand(file, args, opts = {}) {
|
|
|
6363
6521
|
const spawnFile = viaCmd ? process.env["ComSpec"] ?? "cmd.exe" : file;
|
|
6364
6522
|
const spawnArgs = viaCmd ? ["/d", "/s", "/c", cmdLine(file, args)] : [...args];
|
|
6365
6523
|
return new Promise((resolvePromise) => {
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6524
|
+
guardSpawn(
|
|
6525
|
+
() => execFile(
|
|
6526
|
+
spawnFile,
|
|
6527
|
+
spawnArgs,
|
|
6528
|
+
{
|
|
6529
|
+
timeout: opts.timeoutMs ?? COMMAND_TIMEOUT_MS,
|
|
6530
|
+
maxBuffer: MAX_OUTPUT_BYTES,
|
|
6531
|
+
windowsHide: true,
|
|
6532
|
+
windowsVerbatimArguments: viaCmd,
|
|
6533
|
+
...opts.cwd ? { cwd: opts.cwd } : {}
|
|
6534
|
+
},
|
|
6535
|
+
(err, stdout, stderr) => {
|
|
6536
|
+
const out = String(stdout ?? "");
|
|
6537
|
+
const errOut = String(stderr ?? "");
|
|
6538
|
+
if (!err) {
|
|
6539
|
+
resolvePromise({ ok: true, stdout: out, stderr: errOut });
|
|
6540
|
+
return;
|
|
6541
|
+
}
|
|
6542
|
+
const detail = describe3(file, err, errOut);
|
|
6543
|
+
resolvePromise({
|
|
6544
|
+
ok: false,
|
|
6545
|
+
detail,
|
|
6546
|
+
stdout: out,
|
|
6547
|
+
stderr: errOut,
|
|
6548
|
+
...err.code === "ENOENT" ? { notFound: true } : {}
|
|
6549
|
+
});
|
|
6382
6550
|
}
|
|
6383
|
-
|
|
6551
|
+
),
|
|
6552
|
+
(err) => {
|
|
6384
6553
|
resolvePromise({
|
|
6385
6554
|
ok: false,
|
|
6386
|
-
detail,
|
|
6387
|
-
stdout:
|
|
6388
|
-
stderr:
|
|
6389
|
-
...err.code === "ENOENT" ? { notFound: true } : {}
|
|
6555
|
+
detail: describe3(file, err, ""),
|
|
6556
|
+
stdout: "",
|
|
6557
|
+
stderr: "",
|
|
6558
|
+
...err.code === "ENOENT" || err.code === "ENOTDIR" ? { notFound: true } : {}
|
|
6390
6559
|
});
|
|
6391
6560
|
}
|
|
6392
6561
|
);
|
|
@@ -6999,11 +7168,29 @@ var MARKETPLACE_DISPLAY_FIELDS = [
|
|
|
6999
7168
|
var DisplaySchema = z.object({
|
|
7000
7169
|
fields: z.array(z.string().min(1)).optional()
|
|
7001
7170
|
});
|
|
7171
|
+
var CategoryNodeSchema = z.lazy(
|
|
7172
|
+
() => z.object({
|
|
7173
|
+
id: z.string().min(1),
|
|
7174
|
+
label: z.string().min(1).optional(),
|
|
7175
|
+
children: z.array(CategoryNodeSchema).optional()
|
|
7176
|
+
})
|
|
7177
|
+
);
|
|
7178
|
+
var CategoriesSchema = z.array(CategoryNodeSchema).refine(hasUniqueCategoryIds, { message: "category ids must be unique across the whole tree" }).optional().catch(void 0);
|
|
7179
|
+
function hasUniqueCategoryIds(nodes) {
|
|
7180
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7181
|
+
const walk3 = (list) => list.every((node) => {
|
|
7182
|
+
if (seen.has(node.id)) return false;
|
|
7183
|
+
seen.add(node.id);
|
|
7184
|
+
return node.children === void 0 || walk3(node.children);
|
|
7185
|
+
});
|
|
7186
|
+
return walk3(nodes);
|
|
7187
|
+
}
|
|
7002
7188
|
var CatalogSchema = z.object({
|
|
7003
7189
|
name: z.string().regex(NAME_PATTERN),
|
|
7004
7190
|
description: z.string().min(1).optional(),
|
|
7005
7191
|
owner: z.object({ name: z.string().min(1), url: z.string().min(1).optional() }).optional(),
|
|
7006
7192
|
display: DisplaySchema.optional(),
|
|
7193
|
+
categories: CategoriesSchema,
|
|
7007
7194
|
plugins: z.array(EntrySchema)
|
|
7008
7195
|
});
|
|
7009
7196
|
var RecordSchema2 = z.object({
|
|
@@ -7019,13 +7206,17 @@ var StateSchema2 = z.object({
|
|
|
7019
7206
|
function projectEntryForDisplay(entry, display) {
|
|
7020
7207
|
const allowed = display?.fields;
|
|
7021
7208
|
if (allowed === void 0) return entry;
|
|
7022
|
-
const keep = new Set(allowed);
|
|
7023
7209
|
const out = { ...entry };
|
|
7024
7210
|
for (const field of MARKETPLACE_DISPLAY_FIELDS) {
|
|
7025
|
-
if (!
|
|
7211
|
+
if (!displayAllows(display, field)) delete out[field];
|
|
7026
7212
|
}
|
|
7027
7213
|
return out;
|
|
7028
7214
|
}
|
|
7215
|
+
function displayAllows(display, field) {
|
|
7216
|
+
const allowed = display?.fields;
|
|
7217
|
+
if (allowed === void 0) return true;
|
|
7218
|
+
return allowed.includes(field);
|
|
7219
|
+
}
|
|
7029
7220
|
function readMarketplaces(statePath) {
|
|
7030
7221
|
if (!existsSync(statePath)) return { records: [], issues: [] };
|
|
7031
7222
|
let raw;
|
|
@@ -9246,7 +9437,18 @@ function gitProbeEnv() {
|
|
|
9246
9437
|
delete env.GIT_WORK_TREE;
|
|
9247
9438
|
return env;
|
|
9248
9439
|
}
|
|
9440
|
+
function insideGitRepo(rootDir) {
|
|
9441
|
+
let dir = rootDir;
|
|
9442
|
+
for (; ; ) {
|
|
9443
|
+
if (existsSync(join(dir, ".git"))) return true;
|
|
9444
|
+
const parent = dirname(dir);
|
|
9445
|
+
if (parent === dir) return false;
|
|
9446
|
+
dir = parent;
|
|
9447
|
+
}
|
|
9448
|
+
}
|
|
9249
9449
|
function getGitStatus(rootDir) {
|
|
9450
|
+
if (!insideGitRepo(rootDir)) return void 0;
|
|
9451
|
+
if (!canProbeGit()) return void 0;
|
|
9250
9452
|
const quiet = ["ignore", "pipe", "ignore"];
|
|
9251
9453
|
const env = gitProbeEnv();
|
|
9252
9454
|
try {
|
|
@@ -11471,6 +11673,9 @@ var AgentLoop = class {
|
|
|
11471
11673
|
let blankAfterNudge = false;
|
|
11472
11674
|
for (let turn = 1; turn <= maxTurns; turn++) {
|
|
11473
11675
|
if (this.isAborted(input.signal)) {
|
|
11676
|
+
if (turns.length > 0 || lastText) {
|
|
11677
|
+
yield { type: "notice", code: "aborted", text: t("agent_run.aborted") };
|
|
11678
|
+
}
|
|
11474
11679
|
yield finish("aborted");
|
|
11475
11680
|
await this.prompt.syncMemory(userText, lastText);
|
|
11476
11681
|
return;
|
|
@@ -11902,6 +12107,12 @@ ${finalText}` };
|
|
|
11902
12107
|
});
|
|
11903
12108
|
yield finish("max-turns");
|
|
11904
12109
|
} catch (err) {
|
|
12110
|
+
if (this.isAborted(input.signal)) {
|
|
12111
|
+
await this.prompt.syncMemory(userText, lastText);
|
|
12112
|
+
yield { type: "notice", code: "aborted", text: t("agent_run.aborted") };
|
|
12113
|
+
yield finish("aborted");
|
|
12114
|
+
return;
|
|
12115
|
+
}
|
|
11905
12116
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11906
12117
|
runSpan.recordError(err);
|
|
11907
12118
|
await this.prompt.syncMemory(userText, "");
|
|
@@ -12148,6 +12359,10 @@ var SessionsSchema = z.object({
|
|
|
12148
12359
|
retentionDays: z.int().positive().max(3650).default(90),
|
|
12149
12360
|
vacuumAfterPrune: z.boolean().default(true)
|
|
12150
12361
|
});
|
|
12362
|
+
var AutomationSchema = z.object({
|
|
12363
|
+
keepRuns: z.int().positive().max(1e4).default(200),
|
|
12364
|
+
maxRecordingMb: z.int().positive().max(1e5).default(64)
|
|
12365
|
+
});
|
|
12151
12366
|
var TelemetrySchema = z.object({
|
|
12152
12367
|
enabled: z.boolean().optional(),
|
|
12153
12368
|
target: z.enum(["file", "console", "otlp"]).optional(),
|
|
@@ -12186,6 +12401,7 @@ var EpochConfigSchema = z.object({
|
|
|
12186
12401
|
memory: MemorySchema.prefault({}),
|
|
12187
12402
|
artifacts: ArtifactsSchema.prefault({}),
|
|
12188
12403
|
sessions: SessionsSchema.prefault({}),
|
|
12404
|
+
automation: AutomationSchema.prefault({}),
|
|
12189
12405
|
budget: BudgetSchema.optional(),
|
|
12190
12406
|
compliance: ComplianceSchema.optional(),
|
|
12191
12407
|
headless: HeadlessSchema.optional(),
|
|
@@ -14246,6 +14462,9 @@ var SETTING_WRITE_KEYS = [
|
|
|
14246
14462
|
"sessions.autoPrune",
|
|
14247
14463
|
"sessions.retentionDays",
|
|
14248
14464
|
"sessions.vacuumAfterPrune",
|
|
14465
|
+
"automation.keepRuns",
|
|
14466
|
+
"automation.maxRecordingMb",
|
|
14467
|
+
"sessionSearch.allWorkspaces",
|
|
14249
14468
|
"permission"
|
|
14250
14469
|
];
|
|
14251
14470
|
function isWritableSettingKey(value) {
|
|
@@ -14313,6 +14532,9 @@ var VALUE_SCHEMA = {
|
|
|
14313
14532
|
"sessions.autoPrune": EpochConfigSchema.shape.sessions.unwrap().shape.autoPrune.unwrap(),
|
|
14314
14533
|
"sessions.retentionDays": EpochConfigSchema.shape.sessions.unwrap().shape.retentionDays.unwrap(),
|
|
14315
14534
|
"sessions.vacuumAfterPrune": EpochConfigSchema.shape.sessions.unwrap().shape.vacuumAfterPrune.unwrap(),
|
|
14535
|
+
"automation.keepRuns": EpochConfigSchema.shape.automation.unwrap().shape.keepRuns.unwrap(),
|
|
14536
|
+
"automation.maxRecordingMb": EpochConfigSchema.shape.automation.unwrap().shape.maxRecordingMb.unwrap(),
|
|
14537
|
+
"sessionSearch.allWorkspaces": EpochConfigSchema.shape.sessionSearch.unwrap().shape.allWorkspaces.unwrap(),
|
|
14316
14538
|
permission: EpochConfigSchema.shape.permission.unwrap()
|
|
14317
14539
|
};
|
|
14318
14540
|
function settingValueKind(key) {
|
|
@@ -15245,8 +15467,8 @@ var MemoryManager = class {
|
|
|
15245
15467
|
return "";
|
|
15246
15468
|
}
|
|
15247
15469
|
}
|
|
15248
|
-
if (content
|
|
15249
|
-
return content
|
|
15470
|
+
if (countCodePoints(content) > MAX_ENTRY_CHARS) {
|
|
15471
|
+
return headCodePoints(content, MAX_ENTRY_CHARS) + " \u2026[\u6761\u76EE\u8FC7\u957F\u5DF2\u622A\u65AD]";
|
|
15250
15472
|
}
|
|
15251
15473
|
return content;
|
|
15252
15474
|
}
|
|
@@ -15256,7 +15478,7 @@ var MemoryManager = class {
|
|
|
15256
15478
|
const id = this.idByContent.get(contentKey(target, content));
|
|
15257
15479
|
if (!id) continue;
|
|
15258
15480
|
const firstLine4 = (content.split("\n")[0] ?? "").trim();
|
|
15259
|
-
const summary = firstLine4
|
|
15481
|
+
const summary = countCodePoints(firstLine4) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine4, INDEX_SUMMARY_CHARS)}\u2026` : firstLine4;
|
|
15260
15482
|
out.push({ id, target, summary, charLength: content.length });
|
|
15261
15483
|
}
|
|
15262
15484
|
return out;
|
|
@@ -15491,6 +15713,17 @@ function textSimilarity(a, b) {
|
|
|
15491
15713
|
const union = /* @__PURE__ */ new Set([...wordsA, ...wordsB]);
|
|
15492
15714
|
return intersection / union.size;
|
|
15493
15715
|
}
|
|
15716
|
+
var ATTACHMENT_RETENTION_DEFAULTS = {
|
|
15717
|
+
maxAgeDays: 7,
|
|
15718
|
+
maxTotalBytes: ATTACHMENT_MAX_TOTAL_BYTES
|
|
15719
|
+
};
|
|
15720
|
+
function pruneAttachments(root, keepSession, retention = ATTACHMENT_RETENTION_DEFAULTS, now = Date.now()) {
|
|
15721
|
+
const shared = retention;
|
|
15722
|
+
return pruneArtifacts(root, keepSession, shared, now);
|
|
15723
|
+
}
|
|
15724
|
+
async function removeSessionAttachments(sessionId, homeDir) {
|
|
15725
|
+
await rm(attachmentsDir(sessionId, homeDir), { recursive: true, force: true });
|
|
15726
|
+
}
|
|
15494
15727
|
// src/goal/store.ts
|
|
15495
15728
|
function toGoal(row) {
|
|
15496
15729
|
const phase = isGoalPhase(row.phase) ? row.phase : "blocked";
|
|
@@ -15644,6 +15877,52 @@ function restoreParts(parts, opts) {
|
|
|
15644
15877
|
}
|
|
15645
15878
|
});
|
|
15646
15879
|
}
|
|
15880
|
+
function importParts(parts) {
|
|
15881
|
+
const out = [];
|
|
15882
|
+
for (const part of parts) {
|
|
15883
|
+
if (part.type === "text") {
|
|
15884
|
+
out.push({ type: "text", text: part.text });
|
|
15885
|
+
continue;
|
|
15886
|
+
}
|
|
15887
|
+
if (part.type === "file") {
|
|
15888
|
+
out.push({
|
|
15889
|
+
type: "file",
|
|
15890
|
+
path: part.path,
|
|
15891
|
+
...part.omitted ? { omitted: part.omitted } : {},
|
|
15892
|
+
...part.bytes === void 0 ? {} : { bytes: part.bytes }
|
|
15893
|
+
});
|
|
15894
|
+
continue;
|
|
15895
|
+
}
|
|
15896
|
+
if (part.type === "session") {
|
|
15897
|
+
out.push({
|
|
15898
|
+
type: "session",
|
|
15899
|
+
ref: part.ref,
|
|
15900
|
+
...part.sessionId ? { sessionId: part.sessionId } : {},
|
|
15901
|
+
...part.title ? { title: part.title } : {},
|
|
15902
|
+
...part.omitted ? { omitted: part.omitted } : {},
|
|
15903
|
+
...part.messageCount === void 0 ? {} : { messageCount: part.messageCount },
|
|
15904
|
+
...part.totalMessages === void 0 ? {} : { totalMessages: part.totalMessages }
|
|
15905
|
+
});
|
|
15906
|
+
continue;
|
|
15907
|
+
}
|
|
15908
|
+
if (part.type !== "image") {
|
|
15909
|
+
assertNeverPart(part);
|
|
15910
|
+
continue;
|
|
15911
|
+
}
|
|
15912
|
+
const { image, mediaType } = part;
|
|
15913
|
+
const media = mediaType ? { mediaType } : {};
|
|
15914
|
+
if (/^https?:/i.test(image)) {
|
|
15915
|
+
out.push({ type: "image", url: image, ...media });
|
|
15916
|
+
continue;
|
|
15917
|
+
}
|
|
15918
|
+
if (isAbsolute(image)) {
|
|
15919
|
+
out.push({ type: "image", path: image, ...media });
|
|
15920
|
+
continue;
|
|
15921
|
+
}
|
|
15922
|
+
return { ok: false, detail: DATA_URL.test(image) ? "image:data-url" : "image:base64" };
|
|
15923
|
+
}
|
|
15924
|
+
return { ok: true, parts: out };
|
|
15925
|
+
}
|
|
15647
15926
|
function stripArtifactData(artifacts) {
|
|
15648
15927
|
return artifacts.map(({ data: _data, ...rest }) => rest);
|
|
15649
15928
|
}
|
|
@@ -16142,13 +16421,11 @@ var FTS_EXTERNAL_MIGRATIONS = [
|
|
|
16142
16421
|
var SessionDB = class {
|
|
16143
16422
|
db;
|
|
16144
16423
|
path;
|
|
16145
|
-
msgId = 0;
|
|
16146
16424
|
constructor(dbPath$1) {
|
|
16147
16425
|
this.path = dbPath$1 ?? dbPath();
|
|
16148
16426
|
this.db = openDatabase(this.path);
|
|
16149
16427
|
migrate(this.db, NS3, SESSION_MIGRATIONS);
|
|
16150
16428
|
this.migrateFtsIndex();
|
|
16151
|
-
this.refreshMsgId();
|
|
16152
16429
|
}
|
|
16153
16430
|
migrateFtsIndex() {
|
|
16154
16431
|
try {
|
|
@@ -16160,9 +16437,8 @@ var SessionDB = class {
|
|
|
16160
16437
|
);
|
|
16161
16438
|
}
|
|
16162
16439
|
}
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
this.msgId = row?.maxId ?? 0;
|
|
16440
|
+
transaction(fn) {
|
|
16441
|
+
return this.db.transaction(fn)();
|
|
16166
16442
|
}
|
|
16167
16443
|
insertSession(meta) {
|
|
16168
16444
|
this.db.prepare(
|
|
@@ -16204,6 +16480,9 @@ var SessionDB = class {
|
|
|
16204
16480
|
if (!row) return null;
|
|
16205
16481
|
return this.rowToMeta(row);
|
|
16206
16482
|
}
|
|
16483
|
+
hasSession(id) {
|
|
16484
|
+
return this.db.prepare("SELECT 1 FROM sessions WHERE id = ? LIMIT 1").get(id) !== void 0;
|
|
16485
|
+
}
|
|
16207
16486
|
listSessions(input) {
|
|
16208
16487
|
const limit = input.limit ?? 20;
|
|
16209
16488
|
const key = input.sortKey ?? "startedAt";
|
|
@@ -16213,7 +16492,7 @@ var SessionDB = class {
|
|
|
16213
16492
|
const dir = input.direction ?? "desc";
|
|
16214
16493
|
let where = "1=1";
|
|
16215
16494
|
const params = {};
|
|
16216
|
-
if (input.archived !== void 0) {
|
|
16495
|
+
if (input.archived === "any") ; else if (input.archived !== void 0) {
|
|
16217
16496
|
where += " AND archived = @archived";
|
|
16218
16497
|
params["archived"] = input.archived ? 1 : 0;
|
|
16219
16498
|
} else {
|
|
@@ -16226,6 +16505,10 @@ var SessionDB = class {
|
|
|
16226
16505
|
where += " AND cwd = @cwd";
|
|
16227
16506
|
params["cwd"] = input.cwd;
|
|
16228
16507
|
}
|
|
16508
|
+
if (input.updatedSince !== void 0) {
|
|
16509
|
+
where += " AND COALESCE(updated_at, started_at) > @updatedSince";
|
|
16510
|
+
params["updatedSince"] = input.updatedSince;
|
|
16511
|
+
}
|
|
16229
16512
|
if (input.cursor) {
|
|
16230
16513
|
where += ` AND ${cursorCol} < @cursor`;
|
|
16231
16514
|
params["cursor"] = Number(input.cursor);
|
|
@@ -16269,11 +16552,20 @@ var SessionDB = class {
|
|
|
16269
16552
|
unarchiveSession(id) {
|
|
16270
16553
|
this.db.prepare("UPDATE sessions SET archived = 0 WHERE id = ?").run(id);
|
|
16271
16554
|
}
|
|
16555
|
+
importSession(meta, messages) {
|
|
16556
|
+
const run = this.db.transaction(
|
|
16557
|
+
(m, list) => {
|
|
16558
|
+
this.insertSession(m);
|
|
16559
|
+
return list.map((msg) => this.insertMessage({ ...msg, sessionId: m.id }));
|
|
16560
|
+
}
|
|
16561
|
+
);
|
|
16562
|
+
return run(meta, messages);
|
|
16563
|
+
}
|
|
16272
16564
|
insertMessage(msg) {
|
|
16273
|
-
this.db.prepare(
|
|
16565
|
+
const info = this.db.prepare(
|
|
16274
16566
|
`
|
|
16275
|
-
INSERT INTO messages (
|
|
16276
|
-
VALUES (@
|
|
16567
|
+
INSERT INTO messages (session_id, role, content, tool_call_id, tool_calls, tool_results, parts, tool_name, timestamp, token_count, finish_reason, reasoning, turn_facts, active, compacted, observed)
|
|
16568
|
+
VALUES (@sessionId, @role, @content, @toolCallId, @toolCalls, @toolResults, @parts, @toolName, @timestamp, @tokenCount, @finishReason, @reasoning, @turnFacts, 1, 0, 0)
|
|
16277
16569
|
`
|
|
16278
16570
|
).run({
|
|
16279
16571
|
...msg,
|
|
@@ -16291,7 +16583,7 @@ var SessionDB = class {
|
|
|
16291
16583
|
this.db.prepare(
|
|
16292
16584
|
`UPDATE sessions SET message_count = message_count + 1, tool_call_count = tool_call_count + @toolCalls, updated_at = MAX(COALESCE(updated_at, 0), @timestamp) WHERE id = @id`
|
|
16293
16585
|
).run({ id: msg.sessionId, toolCalls, timestamp: msg.timestamp });
|
|
16294
|
-
|
|
16586
|
+
return Number(info.lastInsertRowid);
|
|
16295
16587
|
}
|
|
16296
16588
|
recordUsage(sessionId, usage) {
|
|
16297
16589
|
const priced = usage.costUsd !== void 0;
|
|
@@ -16353,9 +16645,6 @@ var SessionDB = class {
|
|
|
16353
16645
|
}
|
|
16354
16646
|
return info.changes;
|
|
16355
16647
|
}
|
|
16356
|
-
nextMessageId() {
|
|
16357
|
-
return ++this.msgId;
|
|
16358
|
-
}
|
|
16359
16648
|
search(input) {
|
|
16360
16649
|
const limit = input.limit ?? 5;
|
|
16361
16650
|
const scope = input.scope ?? "all";
|
|
@@ -16444,7 +16733,7 @@ var SessionDB = class {
|
|
|
16444
16733
|
return { results };
|
|
16445
16734
|
}
|
|
16446
16735
|
pruneCandidates(input) {
|
|
16447
|
-
const clauses = ["ended_at IS NOT NULL", "updated_at < @cutoff"];
|
|
16736
|
+
const clauses = ["ended_at IS NOT NULL", "updated_at < @cutoff", "ended_at < @cutoff"];
|
|
16448
16737
|
const params = { cutoff: input.olderThanMs };
|
|
16449
16738
|
if (typeof input.archived === "boolean") {
|
|
16450
16739
|
clauses.push("archived = @archived");
|
|
@@ -16454,6 +16743,15 @@ var SessionDB = class {
|
|
|
16454
16743
|
const rows = this.db.prepare(`SELECT * FROM sessions WHERE ${clauses.join(" AND ")} ORDER BY updated_at ASC`).all(params);
|
|
16455
16744
|
return rows.map((r) => this.rowToMeta(r));
|
|
16456
16745
|
}
|
|
16746
|
+
sweepOrphanedSessions(input) {
|
|
16747
|
+
const info = this.db.prepare(
|
|
16748
|
+
"UPDATE sessions SET ended_at = @now, end_reason = 'orphan_sweep' WHERE ended_at IS NULL AND updated_at < @cutoff"
|
|
16749
|
+
).run({ now: input.now, cutoff: input.olderThanMs });
|
|
16750
|
+
return info.changes;
|
|
16751
|
+
}
|
|
16752
|
+
reopenSession(id) {
|
|
16753
|
+
this.db.prepare("UPDATE sessions SET ended_at = NULL, end_reason = NULL WHERE id = ?").run(id);
|
|
16754
|
+
}
|
|
16457
16755
|
openPruneMatches(input) {
|
|
16458
16756
|
const clauses = ["ended_at IS NULL", "updated_at < @cutoff"];
|
|
16459
16757
|
if (!input.includePinned) clauses.push("COALESCE(pinned, 0) = 0");
|
|
@@ -16511,10 +16809,8 @@ var SessionDB = class {
|
|
|
16511
16809
|
if (middle.length === 0) return null;
|
|
16512
16810
|
const mark = this.db.prepare("UPDATE messages SET active = 0, compacted = 1 WHERE id = ?");
|
|
16513
16811
|
for (const row of middle) mark.run(row.id);
|
|
16514
|
-
const summaryId = this.
|
|
16515
|
-
this.insertMessage({
|
|
16812
|
+
const summaryId = this.insertMessage({
|
|
16516
16813
|
sessionId,
|
|
16517
|
-
id: summaryId,
|
|
16518
16814
|
role: "user",
|
|
16519
16815
|
content: input.summary,
|
|
16520
16816
|
timestamp: middle[0].timestamp
|
|
@@ -16870,8 +17166,64 @@ var SessionReferences = class {
|
|
|
16870
17166
|
};
|
|
16871
17167
|
// src/session/manager.ts
|
|
16872
17168
|
var AUTO_VACUUM_MIN_FREELIST_RATIO = 0.25;
|
|
17169
|
+
var IMPORT_ROLES = /* @__PURE__ */ new Set(["system", "user", "assistant", "tool"]);
|
|
17170
|
+
function validateImport(input) {
|
|
17171
|
+
const { meta, messages } = input;
|
|
17172
|
+
if (typeof meta.id !== "string" || meta.id.length === 0) return "meta.id";
|
|
17173
|
+
if (!Number.isFinite(meta.startedAt)) return "meta.startedAt";
|
|
17174
|
+
if (!Number.isFinite(meta.updatedAt)) return "meta.updatedAt";
|
|
17175
|
+
if (meta.endedAt !== void 0 && !Number.isFinite(meta.endedAt)) return "meta.endedAt";
|
|
17176
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17177
|
+
for (const [i, msg] of messages.entries()) {
|
|
17178
|
+
if (!IMPORT_ROLES.has(msg.role)) return `messages[${i}].role`;
|
|
17179
|
+
if (typeof msg.content !== "string") return `messages[${i}].content`;
|
|
17180
|
+
if (!Number.isFinite(msg.timestamp)) return `messages[${i}].timestamp`;
|
|
17181
|
+
if (!Number.isFinite(msg.id) || seen.has(msg.id)) return `messages[${i}].id`;
|
|
17182
|
+
seen.add(msg.id);
|
|
17183
|
+
}
|
|
17184
|
+
return void 0;
|
|
17185
|
+
}
|
|
17186
|
+
function buildImportedMeta(meta, keepParent) {
|
|
17187
|
+
return {
|
|
17188
|
+
id: meta.id,
|
|
17189
|
+
title: meta.title,
|
|
17190
|
+
displayName: meta.displayName,
|
|
17191
|
+
source: meta.source ?? "import",
|
|
17192
|
+
cwd: meta.cwd,
|
|
17193
|
+
workspaceState: meta.workspaceState,
|
|
17194
|
+
workspaceRoot: meta.workspaceRoot,
|
|
17195
|
+
gitBranch: meta.gitBranch,
|
|
17196
|
+
gitRepoRoot: meta.gitRepoRoot,
|
|
17197
|
+
model: meta.model,
|
|
17198
|
+
tags: [],
|
|
17199
|
+
preview: "",
|
|
17200
|
+
pinned: meta.pinned ?? false,
|
|
17201
|
+
archived: meta.archived ?? false,
|
|
17202
|
+
rewindCount: 0,
|
|
17203
|
+
parentId: keepParent ? meta.parentId : void 0,
|
|
17204
|
+
messageCount: 0,
|
|
17205
|
+
toolCallCount: 0,
|
|
17206
|
+
apiCallCount: 0,
|
|
17207
|
+
inputTokens: 0,
|
|
17208
|
+
outputTokens: 0,
|
|
17209
|
+
cacheReadTokens: 0,
|
|
17210
|
+
cacheWriteTokens: 0,
|
|
17211
|
+
reasoningTokens: 0,
|
|
17212
|
+
estimatedCostUsd: void 0,
|
|
17213
|
+
actualCostUsd: void 0,
|
|
17214
|
+
compressionIneffectiveCount: 0,
|
|
17215
|
+
expiryFinalized: 0,
|
|
17216
|
+
summary: null,
|
|
17217
|
+
plan: null,
|
|
17218
|
+
startedAt: new Date(meta.startedAt),
|
|
17219
|
+
updatedAt: new Date(meta.updatedAt),
|
|
17220
|
+
endedAt: meta.endedAt === void 0 ? void 0 : new Date(meta.endedAt),
|
|
17221
|
+
endReason: meta.endReason
|
|
17222
|
+
};
|
|
17223
|
+
}
|
|
16873
17224
|
var SessionManager = class {
|
|
16874
17225
|
db;
|
|
17226
|
+
touched = /* @__PURE__ */ new Set();
|
|
16875
17227
|
queries;
|
|
16876
17228
|
goals;
|
|
16877
17229
|
references;
|
|
@@ -16930,6 +17282,7 @@ var SessionManager = class {
|
|
|
16930
17282
|
endReason: void 0
|
|
16931
17283
|
};
|
|
16932
17284
|
this.db.insertSession(meta);
|
|
17285
|
+
this.touched.add(id);
|
|
16933
17286
|
if (input?.systemPrompt) {
|
|
16934
17287
|
this.appendMessage(id, { role: "system", content: input.systemPrompt });
|
|
16935
17288
|
}
|
|
@@ -16942,6 +17295,9 @@ var SessionManager = class {
|
|
|
16942
17295
|
const messages = this.db.getMessages(id);
|
|
16943
17296
|
return this.buildSession(id, messages);
|
|
16944
17297
|
}
|
|
17298
|
+
has(id) {
|
|
17299
|
+
return this.db.hasSession(id);
|
|
17300
|
+
}
|
|
16945
17301
|
getLatest() {
|
|
16946
17302
|
const result = this.db.listSessions({ limit: 1, sortKey: "updatedAt", direction: "desc" });
|
|
16947
17303
|
if (result.sessions.length === 0) return void 0;
|
|
@@ -16955,6 +17311,56 @@ var SessionManager = class {
|
|
|
16955
17311
|
list(input) {
|
|
16956
17312
|
return this.db.listSessions(input ?? {});
|
|
16957
17313
|
}
|
|
17314
|
+
importSession(input) {
|
|
17315
|
+
const { meta, messages } = input;
|
|
17316
|
+
const id = meta.id;
|
|
17317
|
+
const bad2 = validateImport(input);
|
|
17318
|
+
if (bad2) return { ok: false, id, reason: "invalid", detail: bad2 };
|
|
17319
|
+
if (this.db.hasSession(id)) return { ok: false, id, reason: "exists" };
|
|
17320
|
+
const converted = [];
|
|
17321
|
+
for (const [i, msg] of messages.entries()) {
|
|
17322
|
+
const { id: _sourceId, parts, ...rest } = msg;
|
|
17323
|
+
if (!parts) {
|
|
17324
|
+
converted.push(rest);
|
|
17325
|
+
continue;
|
|
17326
|
+
}
|
|
17327
|
+
const result = importParts(parts);
|
|
17328
|
+
if (!result.ok) {
|
|
17329
|
+
return {
|
|
17330
|
+
ok: false,
|
|
17331
|
+
id,
|
|
17332
|
+
reason: "invalid",
|
|
17333
|
+
detail: `messages[${i}].parts.${result.detail}`
|
|
17334
|
+
};
|
|
17335
|
+
}
|
|
17336
|
+
converted.push({ ...rest, parts: result.parts });
|
|
17337
|
+
}
|
|
17338
|
+
const droppedParentId = meta.parentId !== void 0 && !this.db.hasSession(meta.parentId) ? meta.parentId : void 0;
|
|
17339
|
+
try {
|
|
17340
|
+
const newIds = this.db.importSession(
|
|
17341
|
+
buildImportedMeta(meta, droppedParentId === void 0),
|
|
17342
|
+
converted
|
|
17343
|
+
);
|
|
17344
|
+
const idMap = {};
|
|
17345
|
+
messages.forEach((msg, i) => {
|
|
17346
|
+
idMap[msg.id] = newIds[i];
|
|
17347
|
+
});
|
|
17348
|
+
return {
|
|
17349
|
+
ok: true,
|
|
17350
|
+
id,
|
|
17351
|
+
messageCount: newIds.length,
|
|
17352
|
+
idMap,
|
|
17353
|
+
...droppedParentId === void 0 ? {} : { droppedParentId }
|
|
17354
|
+
};
|
|
17355
|
+
} catch (err) {
|
|
17356
|
+
return {
|
|
17357
|
+
ok: false,
|
|
17358
|
+
id,
|
|
17359
|
+
reason: "failed",
|
|
17360
|
+
...err instanceof Error ? { detail: err.name } : {}
|
|
17361
|
+
};
|
|
17362
|
+
}
|
|
17363
|
+
}
|
|
16958
17364
|
updateMeta(id, patch) {
|
|
16959
17365
|
this.db.updateSessionMeta(id, patch);
|
|
16960
17366
|
}
|
|
@@ -16970,11 +17376,17 @@ var SessionManager = class {
|
|
|
16970
17376
|
openPruneMatches(input) {
|
|
16971
17377
|
return this.db.openPruneMatches(input);
|
|
16972
17378
|
}
|
|
17379
|
+
sweepOrphans(input) {
|
|
17380
|
+
return this.db.sweepOrphanedSessions(input);
|
|
17381
|
+
}
|
|
17382
|
+
reopen(id) {
|
|
17383
|
+
this.db.reopenSession(id);
|
|
17384
|
+
}
|
|
16973
17385
|
freelistRatio() {
|
|
16974
17386
|
return this.db.freelistRatio();
|
|
16975
17387
|
}
|
|
16976
17388
|
maybeAutoPrune(opts) {
|
|
16977
|
-
const result = { skipped: false, pruned: 0, vacuumed: false };
|
|
17389
|
+
const result = { skipped: false, swept: 0, pruned: 0, vacuumed: false };
|
|
16978
17390
|
if (!opts.enabled) return { ...result, skipped: true };
|
|
16979
17391
|
const now = opts.now?.() ?? Date.now();
|
|
16980
17392
|
const minInterval = opts.minIntervalMs ?? 24 * 60 * 60 * 1e3;
|
|
@@ -16984,6 +17396,7 @@ var SessionManager = class {
|
|
|
16984
17396
|
return { ...result, skipped: true };
|
|
16985
17397
|
}
|
|
16986
17398
|
const cutoff = now - opts.retentionDays * 24 * 60 * 60 * 1e3;
|
|
17399
|
+
const swept = this.db.sweepOrphanedSessions({ olderThanMs: cutoff, now });
|
|
16987
17400
|
const victims = this.db.pruneCandidates({ olderThanMs: cutoff });
|
|
16988
17401
|
let pruned = 0;
|
|
16989
17402
|
for (const s of victims) if (this.db.deleteSession(s.id)) pruned++;
|
|
@@ -16997,27 +17410,50 @@ var SessionManager = class {
|
|
|
16997
17410
|
if (vacuumed) this.db.setMeta("last_vacuum", String(now));
|
|
16998
17411
|
}
|
|
16999
17412
|
}
|
|
17000
|
-
return { skipped: false, pruned, vacuumed };
|
|
17413
|
+
return { skipped: false, swept, pruned, vacuumed };
|
|
17001
17414
|
} catch (cause) {
|
|
17002
17415
|
return { ...result, error: cause instanceof Error ? cause.message : String(cause) };
|
|
17003
17416
|
}
|
|
17004
17417
|
}
|
|
17418
|
+
maybePruneAttachments(root, keepSession, opts = {}) {
|
|
17419
|
+
const now = opts.now?.() ?? Date.now();
|
|
17420
|
+
const minInterval = opts.minIntervalMs ?? 24 * 60 * 60 * 1e3;
|
|
17421
|
+
try {
|
|
17422
|
+
if (!this.db.claimMaintenanceSlot("last_attachment_prune", minInterval, now)) return 0;
|
|
17423
|
+
return pruneAttachments(root, keepSession, ATTACHMENT_RETENTION_DEFAULTS, now);
|
|
17424
|
+
} catch {
|
|
17425
|
+
return 0;
|
|
17426
|
+
}
|
|
17427
|
+
}
|
|
17005
17428
|
delete(id) {
|
|
17006
17429
|
return this.db.deleteSession(id);
|
|
17007
17430
|
}
|
|
17008
17431
|
endSession(id, reason9 = "user_stop") {
|
|
17009
17432
|
this.db.updateSessionMeta(id, { endedAt: /* @__PURE__ */ new Date(), endReason: reason9 });
|
|
17010
17433
|
}
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17434
|
+
endTouchedSessions(reason9 = "process_exit") {
|
|
17435
|
+
let ended = 0;
|
|
17436
|
+
for (const id of this.touched) {
|
|
17437
|
+
try {
|
|
17438
|
+
this.endSession(id, reason9);
|
|
17439
|
+
ended++;
|
|
17440
|
+
} catch {
|
|
17441
|
+
}
|
|
17019
17442
|
}
|
|
17020
|
-
return
|
|
17443
|
+
return ended;
|
|
17444
|
+
}
|
|
17445
|
+
appendMessage(sessionId, msg) {
|
|
17446
|
+
this.touched.add(sessionId);
|
|
17447
|
+
return this.db.transaction(() => {
|
|
17448
|
+
const id = this.db.insertMessage({ ...msg, sessionId, timestamp: Date.now() });
|
|
17449
|
+
const meta = this.db.getSessionMeta(sessionId);
|
|
17450
|
+
if (!meta) return id;
|
|
17451
|
+
if (!meta.title && msg.role === "user") {
|
|
17452
|
+
const title = msg.content.slice(0, 50).replace(/\n/g, " ");
|
|
17453
|
+
this.db.updateSessionMeta(sessionId, { title });
|
|
17454
|
+
}
|
|
17455
|
+
return id;
|
|
17456
|
+
});
|
|
17021
17457
|
}
|
|
17022
17458
|
attachTurnFacts(sessionId, messageId, input) {
|
|
17023
17459
|
this.db.attachTurnFacts(sessionId, messageId, input);
|
|
@@ -17026,6 +17462,7 @@ var SessionManager = class {
|
|
|
17026
17462
|
this.db.setOpenTurn(sessionId, from);
|
|
17027
17463
|
}
|
|
17028
17464
|
recordUsage(sessionId, usage) {
|
|
17465
|
+
this.touched.add(sessionId);
|
|
17029
17466
|
this.db.recordUsage(sessionId, usage);
|
|
17030
17467
|
}
|
|
17031
17468
|
markObserved(sessionId, messageId) {
|
|
@@ -17195,6 +17632,30 @@ function firstSentence(text, maxLen) {
|
|
|
17195
17632
|
const lastSpace = cut.lastIndexOf(" ");
|
|
17196
17633
|
return (lastSpace > maxLen * 0.6 ? cut.slice(0, lastSpace) : cut) + "\u2026";
|
|
17197
17634
|
}
|
|
17635
|
+
// src/session/persist-failure.ts
|
|
17636
|
+
function codeOf(cause) {
|
|
17637
|
+
if (typeof cause !== "object" || cause === null) return "";
|
|
17638
|
+
const code = cause.code;
|
|
17639
|
+
return typeof code === "string" ? code : "";
|
|
17640
|
+
}
|
|
17641
|
+
function classifyPersistFailure(cause) {
|
|
17642
|
+
const code = codeOf(cause);
|
|
17643
|
+
if (!code) return "unknown";
|
|
17644
|
+
if (code.startsWith("SQLITE_FULL") || code === "ENOSPC") return "disk-full";
|
|
17645
|
+
if (code.startsWith("SQLITE_BUSY") || code.startsWith("SQLITE_LOCKED")) return "locked";
|
|
17646
|
+
if (code.startsWith("SQLITE_READONLY") || code.startsWith("SQLITE_PERM") || code.startsWith("SQLITE_CANTOPEN") || code === "EACCES" || code === "EPERM" || code === "EROFS") {
|
|
17647
|
+
return "read-only";
|
|
17648
|
+
}
|
|
17649
|
+
if (code.startsWith("SQLITE_CORRUPT") || code === "SQLITE_NOTADB") return "corrupt";
|
|
17650
|
+
if (code.startsWith("SQLITE_IOERR") || code === "EIO") return "io-error";
|
|
17651
|
+
return "unknown";
|
|
17652
|
+
}
|
|
17653
|
+
function isTransientPersistFailure(kind) {
|
|
17654
|
+
return kind === "locked";
|
|
17655
|
+
}
|
|
17656
|
+
function persistFailureCode(cause) {
|
|
17657
|
+
return codeOf(cause);
|
|
17658
|
+
}
|
|
17198
17659
|
function isSettled(phase) {
|
|
17199
17660
|
return phase === "complete";
|
|
17200
17661
|
}
|
|
@@ -18456,6 +18917,14 @@ var MIGRATIONS3 = [
|
|
|
18456
18917
|
);
|
|
18457
18918
|
`);
|
|
18458
18919
|
}
|
|
18920
|
+
},
|
|
18921
|
+
{
|
|
18922
|
+
id: "schedule-show-in-session-list",
|
|
18923
|
+
version: 2,
|
|
18924
|
+
description: "\u4EFB\u52A1\u591A\u4E00\u683C\uFF1A\u8DD1\u5B8C\u7684\u4F1A\u8BDD\u76F4\u63A5\u8FDB\u4F1A\u8BDD\u5217\u8868\u5417\uFF08\u7F3A\u7701\u4E0D\u8FDB\uFF09",
|
|
18925
|
+
up: (db) => {
|
|
18926
|
+
db.exec(`ALTER TABLE schedules ADD COLUMN show_in_session_list INTEGER NOT NULL DEFAULT 0;`);
|
|
18927
|
+
}
|
|
18459
18928
|
}
|
|
18460
18929
|
];
|
|
18461
18930
|
var ScheduleStore = class {
|
|
@@ -18480,6 +18949,7 @@ var ScheduleStore = class {
|
|
|
18480
18949
|
prompt: input.prompt,
|
|
18481
18950
|
workDir: input.workDir,
|
|
18482
18951
|
...input.model !== void 0 ? { model: input.model } : {},
|
|
18952
|
+
...input.role !== void 0 ? { role: input.role } : {},
|
|
18483
18953
|
permission: input.permission,
|
|
18484
18954
|
allowTools: input.allowTools ?? [],
|
|
18485
18955
|
allowOperations: input.allowOperations ?? [],
|
|
@@ -18487,6 +18957,7 @@ var ScheduleStore = class {
|
|
|
18487
18957
|
maxTurns: input.maxTurns ?? SCHEDULE_DEFAULTS.maxTurns,
|
|
18488
18958
|
maxBudgetUsd: input.maxBudgetUsd,
|
|
18489
18959
|
timeoutMs: input.timeoutMs ?? SCHEDULE_DEFAULTS.timeoutMs,
|
|
18960
|
+
...input.showInSessionList === true ? { showInSessionList: true } : {},
|
|
18490
18961
|
trigger: input.trigger,
|
|
18491
18962
|
...input.startDate !== void 0 ? { startDate: input.startDate } : {},
|
|
18492
18963
|
...input.endDate !== void 0 ? { endDate: input.endDate } : {},
|
|
@@ -18498,13 +18969,15 @@ var ScheduleStore = class {
|
|
|
18498
18969
|
`INSERT INTO schedules (
|
|
18499
18970
|
id, name, enabled, created_at, updated_at, prompt, work_dir, model, role,
|
|
18500
18971
|
skills, mcp_servers, permission, allow_tools, allow_operations, allow_rules,
|
|
18501
|
-
max_turns, max_budget_usd, timeout_ms,
|
|
18972
|
+
max_turns, max_budget_usd, timeout_ms, show_in_session_list,
|
|
18973
|
+
trigger_kind, trigger_spec,
|
|
18502
18974
|
start_date, end_date, os_backend, os_task_id, os_registered_at, os_command,
|
|
18503
18975
|
last_run_at, last_status
|
|
18504
18976
|
) VALUES (
|
|
18505
18977
|
@id, @name, @enabled, @created_at, @updated_at, @prompt, @work_dir, @model, @role,
|
|
18506
18978
|
@skills, @mcp_servers, @permission, @allow_tools, @allow_operations, @allow_rules,
|
|
18507
|
-
@max_turns, @max_budget_usd, @timeout_ms, @
|
|
18979
|
+
@max_turns, @max_budget_usd, @timeout_ms, @show_in_session_list,
|
|
18980
|
+
@trigger_kind, @trigger_spec,
|
|
18508
18981
|
@start_date, @end_date, @os_backend, @os_task_id, @os_registered_at, @os_command,
|
|
18509
18982
|
@last_run_at, @last_status
|
|
18510
18983
|
)`
|
|
@@ -18590,6 +19063,16 @@ var ScheduleStore = class {
|
|
|
18590
19063
|
const rows = this.db.prepare("SELECT * FROM schedule_runs WHERE schedule_id = ? ORDER BY started_at DESC LIMIT ?").all(scheduleId, limit);
|
|
18591
19064
|
return rows.map(runFromRow);
|
|
18592
19065
|
}
|
|
19066
|
+
recordedSessions(scheduleId, limit = 2) {
|
|
19067
|
+
if (limit <= 0) return [];
|
|
19068
|
+
const rows = this.db.prepare(
|
|
19069
|
+
`SELECT session_id FROM schedule_runs
|
|
19070
|
+
WHERE schedule_id = ? AND session_id IS NOT NULL
|
|
19071
|
+
ORDER BY started_at DESC
|
|
19072
|
+
LIMIT ?`
|
|
19073
|
+
).all(scheduleId, limit);
|
|
19074
|
+
return rows.map((r) => r.session_id);
|
|
19075
|
+
}
|
|
18593
19076
|
listRecentRuns(limit = 50) {
|
|
18594
19077
|
const rows = this.db.prepare("SELECT * FROM schedule_runs ORDER BY started_at DESC LIMIT ?").all(limit);
|
|
18595
19078
|
return rows.map(runFromRow);
|
|
@@ -18611,6 +19094,7 @@ var ScheduleStore = class {
|
|
|
18611
19094
|
mcp_servers = @mcp_servers, permission = @permission, allow_tools = @allow_tools,
|
|
18612
19095
|
allow_operations = @allow_operations, allow_rules = @allow_rules,
|
|
18613
19096
|
max_turns = @max_turns, max_budget_usd = @max_budget_usd, timeout_ms = @timeout_ms,
|
|
19097
|
+
show_in_session_list = @show_in_session_list,
|
|
18614
19098
|
trigger_kind = @trigger_kind, trigger_spec = @trigger_spec,
|
|
18615
19099
|
start_date = @start_date, end_date = @end_date, os_backend = @os_backend,
|
|
18616
19100
|
os_task_id = @os_task_id, os_registered_at = @os_registered_at,
|
|
@@ -18633,6 +19117,7 @@ function mergeSchedulePatch(current, patch) {
|
|
|
18633
19117
|
"maxTurns",
|
|
18634
19118
|
"maxBudgetUsd",
|
|
18635
19119
|
"timeoutMs",
|
|
19120
|
+
"showInSessionList",
|
|
18636
19121
|
"trigger",
|
|
18637
19122
|
"enabled"
|
|
18638
19123
|
])
|
|
@@ -18643,9 +19128,10 @@ function mergeSchedulePatch(current, patch) {
|
|
|
18643
19128
|
if (value === null) delete next[key];
|
|
18644
19129
|
else next[key] = value;
|
|
18645
19130
|
}
|
|
19131
|
+
if (next.showInSessionList !== true) delete next.showInSessionList;
|
|
18646
19132
|
return next;
|
|
18647
19133
|
}
|
|
18648
|
-
var CLEARABLE = ["model", "startDate", "endDate"];
|
|
19134
|
+
var CLEARABLE = ["model", "role", "startDate", "endDate"];
|
|
18649
19135
|
function toRow(def) {
|
|
18650
19136
|
return {
|
|
18651
19137
|
id: def.id,
|
|
@@ -18666,6 +19152,7 @@ function toRow(def) {
|
|
|
18666
19152
|
max_turns: def.maxTurns,
|
|
18667
19153
|
max_budget_usd: def.maxBudgetUsd,
|
|
18668
19154
|
timeout_ms: def.timeoutMs,
|
|
19155
|
+
show_in_session_list: def.showInSessionList === true ? 1 : 0,
|
|
18669
19156
|
trigger_kind: def.trigger.kind,
|
|
18670
19157
|
trigger_spec: JSON.stringify(def.trigger),
|
|
18671
19158
|
start_date: def.startDate ?? null,
|
|
@@ -18698,6 +19185,7 @@ function fromRow(row) {
|
|
|
18698
19185
|
maxTurns: row.max_turns,
|
|
18699
19186
|
maxBudgetUsd: row.max_budget_usd,
|
|
18700
19187
|
timeoutMs: row.timeout_ms,
|
|
19188
|
+
...row.show_in_session_list !== 0 ? { showInSessionList: true } : {},
|
|
18701
19189
|
trigger: JSON.parse(row.trigger_spec),
|
|
18702
19190
|
...row.start_date !== null ? { startDate: row.start_date } : {},
|
|
18703
19191
|
...row.end_date !== null ? { endDate: row.end_date } : {},
|
|
@@ -19983,9 +20471,9 @@ function buildAutomaton(patterns) {
|
|
|
19983
20471
|
while (queue.length > 0) {
|
|
19984
20472
|
const cur = queue.shift();
|
|
19985
20473
|
for (const [ch, child] of nodes[cur].next) {
|
|
19986
|
-
let
|
|
19987
|
-
while (
|
|
19988
|
-
const target = nodes[
|
|
20474
|
+
let fail9 = nodes[cur].fail;
|
|
20475
|
+
while (fail9 !== 0 && !nodes[fail9].next.has(ch)) fail9 = nodes[fail9].fail;
|
|
20476
|
+
const target = nodes[fail9].next.get(ch);
|
|
19989
20477
|
nodes[child].fail = target !== void 0 && target !== child ? target : 0;
|
|
19990
20478
|
nodes[child].out.push(...nodes[nodes[child].fail].out);
|
|
19991
20479
|
queue.push(child);
|
|
@@ -20210,15 +20698,30 @@ function runCommandHook(config, event, workDir) {
|
|
|
20210
20698
|
const injectedEnv = injectEpochEnv(event, config.pluginRoot);
|
|
20211
20699
|
const hookEnv = { ...baseEnv, ...injectedEnv, ...config.env };
|
|
20212
20700
|
return new Promise((resolve16) => {
|
|
20213
|
-
const child = spawn(config.command, {
|
|
20214
|
-
shell: true,
|
|
20215
|
-
cwd: workDir,
|
|
20216
|
-
env: hookEnv,
|
|
20217
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
20218
|
-
});
|
|
20219
20701
|
let stdout = "";
|
|
20220
20702
|
let stderr = "";
|
|
20221
20703
|
let settled = false;
|
|
20704
|
+
const failToStart = (err) => {
|
|
20705
|
+
if (settled) return;
|
|
20706
|
+
settled = true;
|
|
20707
|
+
resolve16({
|
|
20708
|
+
exitCode: -1,
|
|
20709
|
+
stdout,
|
|
20710
|
+
stderr,
|
|
20711
|
+
blocked: false,
|
|
20712
|
+
rejectReason: t("hook_load.spawn_failed", { message: err.message })
|
|
20713
|
+
});
|
|
20714
|
+
};
|
|
20715
|
+
const child = guardSpawn(
|
|
20716
|
+
() => spawn(config.command, {
|
|
20717
|
+
shell: true,
|
|
20718
|
+
cwd: workDir,
|
|
20719
|
+
env: hookEnv,
|
|
20720
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
20721
|
+
}),
|
|
20722
|
+
failToStart
|
|
20723
|
+
);
|
|
20724
|
+
if (!child) return;
|
|
20222
20725
|
const timer = setTimeout(() => {
|
|
20223
20726
|
if (!settled) {
|
|
20224
20727
|
settled = true;
|
|
@@ -20270,15 +20773,7 @@ function runCommandHook(config, event, workDir) {
|
|
|
20270
20773
|
});
|
|
20271
20774
|
child.on("error", (err) => {
|
|
20272
20775
|
clearTimeout(timer);
|
|
20273
|
-
|
|
20274
|
-
settled = true;
|
|
20275
|
-
resolve16({
|
|
20276
|
-
exitCode: -1,
|
|
20277
|
-
stdout,
|
|
20278
|
-
stderr,
|
|
20279
|
-
blocked: false,
|
|
20280
|
-
rejectReason: t("hook_load.spawn_failed", { message: err.message })
|
|
20281
|
-
});
|
|
20776
|
+
failToStart(err);
|
|
20282
20777
|
});
|
|
20283
20778
|
const input = JSON.stringify({
|
|
20284
20779
|
session_id: event.sessionId,
|
|
@@ -22043,6 +22538,7 @@ function listWorkspaceFiles(root) {
|
|
|
22043
22538
|
}
|
|
22044
22539
|
function listFromGit(root) {
|
|
22045
22540
|
if (!existsSync(join(root, ".git"))) return null;
|
|
22541
|
+
if (!canProbeGit()) return null;
|
|
22046
22542
|
try {
|
|
22047
22543
|
const out = execFileSync("git", ["ls-files", "-co", "--exclude-standard", "-z"], {
|
|
22048
22544
|
cwd: root,
|
|
@@ -22251,17 +22747,6 @@ function readSession(ref, opts, usedBytes) {
|
|
|
22251
22747
|
})
|
|
22252
22748
|
};
|
|
22253
22749
|
}
|
|
22254
|
-
var ATTACHMENT_RETENTION_DEFAULTS = {
|
|
22255
|
-
maxAgeDays: 7,
|
|
22256
|
-
maxTotalBytes: ATTACHMENT_MAX_TOTAL_BYTES
|
|
22257
|
-
};
|
|
22258
|
-
function pruneAttachments(root, keepSession, retention = ATTACHMENT_RETENTION_DEFAULTS, now = Date.now()) {
|
|
22259
|
-
const shared = retention;
|
|
22260
|
-
return pruneArtifacts(root, keepSession, shared, now);
|
|
22261
|
-
}
|
|
22262
|
-
async function removeSessionAttachments(sessionId, homeDir) {
|
|
22263
|
-
await rm(attachmentsDir(sessionId, homeDir), { recursive: true, force: true });
|
|
22264
|
-
}
|
|
22265
22750
|
var OPENABLE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
|
|
22266
22751
|
function artifactOpenRefusal(path, homeDir) {
|
|
22267
22752
|
const root = homeDir === void 0 ? artifactsDir() : artifactsDir(void 0, homeDir);
|
|
@@ -22296,12 +22781,12 @@ async function openArtifact(path, homeDir) {
|
|
|
22296
22781
|
if (refusal2) throw new Error(describeArtifactRefusal(refusal2));
|
|
22297
22782
|
const launch = artifactLaunchArgv(path, process.platform, homeDir);
|
|
22298
22783
|
if (!launch) throw new Error(describeArtifactRefusal("launch-failed"));
|
|
22299
|
-
await new Promise((done2,
|
|
22784
|
+
await new Promise((done2, fail9) => {
|
|
22300
22785
|
try {
|
|
22301
22786
|
const child = spawn(launch.command, launch.args, { stdio: "ignore", detached: true });
|
|
22302
22787
|
child.on(
|
|
22303
22788
|
"error",
|
|
22304
|
-
(err) =>
|
|
22789
|
+
(err) => fail9(
|
|
22305
22790
|
new Error(
|
|
22306
22791
|
t("artifact.open_launch_failed_detail", {
|
|
22307
22792
|
reason: describeArtifactRefusal("launch-failed"),
|
|
@@ -22315,7 +22800,7 @@ async function openArtifact(path, homeDir) {
|
|
|
22315
22800
|
done2();
|
|
22316
22801
|
});
|
|
22317
22802
|
} catch (err) {
|
|
22318
|
-
|
|
22803
|
+
fail9(
|
|
22319
22804
|
new Error(
|
|
22320
22805
|
t("artifact.open_launch_failed_detail", {
|
|
22321
22806
|
reason: describeArtifactRefusal("launch-failed"),
|
|
@@ -23025,31 +23510,15 @@ var CodeSandbox = class {
|
|
|
23025
23510
|
stdio: ["ignore", "pipe", "pipe"],
|
|
23026
23511
|
...IS_WINDOWS ? { windowsHide: true } : {}
|
|
23027
23512
|
};
|
|
23028
|
-
const child = spawn(command, args, spawnOpts);
|
|
23029
23513
|
return new Promise((resolve16) => {
|
|
23030
23514
|
let stdout = "";
|
|
23031
23515
|
let stderr = "";
|
|
23032
23516
|
let killedForOutput = false;
|
|
23033
|
-
let
|
|
23034
|
-
|
|
23035
|
-
|
|
23036
|
-
|
|
23037
|
-
|
|
23038
|
-
stdout += outDecoder.write(c);
|
|
23039
|
-
if (stdout.length >= MAX_OUTPUT) {
|
|
23040
|
-
killedForOutput = true;
|
|
23041
|
-
stdout = stdout.slice(0, MAX_OUTPUT);
|
|
23042
|
-
child.kill("SIGKILL");
|
|
23043
|
-
}
|
|
23044
|
-
});
|
|
23045
|
-
child.stderr?.on("data", (c) => {
|
|
23046
|
-
if (stderr.length >= MAX_OUTPUT) return;
|
|
23047
|
-
errDecoder ??= createStreamDecoder();
|
|
23048
|
-
stderr += errDecoder.write(c);
|
|
23049
|
-
});
|
|
23050
|
-
const onAbort = () => child.kill("SIGKILL");
|
|
23051
|
-
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
23052
|
-
child.on("error", (err) => {
|
|
23517
|
+
let child = null;
|
|
23518
|
+
const onAbort = () => {
|
|
23519
|
+
child?.kill("SIGKILL");
|
|
23520
|
+
};
|
|
23521
|
+
const failToStart = (err) => {
|
|
23053
23522
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
23054
23523
|
if (err.code === "ENOENT") {
|
|
23055
23524
|
resolve16({
|
|
@@ -23064,12 +23533,34 @@ var CodeSandbox = class {
|
|
|
23064
23533
|
resolve16({
|
|
23065
23534
|
success: false,
|
|
23066
23535
|
output: "",
|
|
23067
|
-
error: `[\u9519\u8BEF] ${err.message}`,
|
|
23536
|
+
error: `[\u9519\u8BEF] ${err.message}\uFF08command=${command}\uFF0Ccwd=${spawnOpts.cwd ?? ""}\uFF09`,
|
|
23068
23537
|
errorType: "runtime",
|
|
23069
23538
|
duration: Date.now() - start
|
|
23070
23539
|
});
|
|
23540
|
+
};
|
|
23541
|
+
child = guardSpawn(() => spawn(command, args, spawnOpts), failToStart);
|
|
23542
|
+
if (!child) return;
|
|
23543
|
+
const proc = child;
|
|
23544
|
+
let outDecoder = null;
|
|
23545
|
+
let errDecoder = null;
|
|
23546
|
+
proc.stdout?.on("data", (c) => {
|
|
23547
|
+
if (killedForOutput) return;
|
|
23548
|
+
outDecoder ??= createStreamDecoder();
|
|
23549
|
+
stdout += outDecoder.write(c);
|
|
23550
|
+
if (stdout.length >= MAX_OUTPUT) {
|
|
23551
|
+
killedForOutput = true;
|
|
23552
|
+
stdout = stdout.slice(0, MAX_OUTPUT);
|
|
23553
|
+
proc.kill("SIGKILL");
|
|
23554
|
+
}
|
|
23071
23555
|
});
|
|
23072
|
-
|
|
23556
|
+
proc.stderr?.on("data", (c) => {
|
|
23557
|
+
if (stderr.length >= MAX_OUTPUT) return;
|
|
23558
|
+
errDecoder ??= createStreamDecoder();
|
|
23559
|
+
stderr += errDecoder.write(c);
|
|
23560
|
+
});
|
|
23561
|
+
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
23562
|
+
proc.on("error", failToStart);
|
|
23563
|
+
proc.on("close", (code, sig) => {
|
|
23073
23564
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
23074
23565
|
if (!killedForOutput) stdout += outDecoder?.end() ?? "";
|
|
23075
23566
|
if (stderr.length < MAX_OUTPUT) stderr += errDecoder?.end() ?? "";
|
|
@@ -23166,4 +23657,4 @@ function trunc(stdout, stderr) {
|
|
|
23166
23657
|
* `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
|
|
23167
23658
|
*/
|
|
23168
23659
|
|
|
23169
|
-
export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, 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_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, MemoryReviewer, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, 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_CREATE_TOOL, SKILL_EDIT_TOOL, 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, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, 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, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };
|
|
23660
|
+
export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, AgentLoop, 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_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, ManagedPolicyError, ManagedSettingsSchema, MemoryManager, MemoryReviewer, ModelFailureTracker, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, 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_FORM_BUDGET_USD, 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_CREATE_TOOL, SKILL_EDIT_TOOL, 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, Workspace, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyPersistFailure, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, 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, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importParts, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isTransientPersistFailure, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistFailureCode, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, 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, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };
|