@epoch-agent/core 0.14.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 +446 -12
- package/dist/index.js +477 -99
- 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, guardSpawn, 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, countCodePoints, headCodePoints, 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';
|
|
@@ -542,6 +542,7 @@ var INTERNAL_TOOLS = /* @__PURE__ */ new Set([
|
|
|
542
542
|
"session_messages_search",
|
|
543
543
|
"session_messages_read",
|
|
544
544
|
"session_trace",
|
|
545
|
+
"session_list",
|
|
545
546
|
"goal",
|
|
546
547
|
"skill_view",
|
|
547
548
|
"tool_search",
|
|
@@ -1117,6 +1118,7 @@ var BLOCKED_TOOLS = Object.freeze([
|
|
|
1117
1118
|
"session_messages_search",
|
|
1118
1119
|
"session_messages_read",
|
|
1119
1120
|
"session_trace",
|
|
1121
|
+
"session_list",
|
|
1120
1122
|
"goal"
|
|
1121
1123
|
]);
|
|
1122
1124
|
var DelegateManager = class {
|
|
@@ -3438,11 +3440,13 @@ var SESSION_SEARCH_TOOL = "session_search";
|
|
|
3438
3440
|
var SESSION_MESSAGES_SEARCH_TOOL = "session_messages_search";
|
|
3439
3441
|
var SESSION_MESSAGES_READ_TOOL = "session_messages_read";
|
|
3440
3442
|
var SESSION_TRACE_TOOL = "session_trace";
|
|
3443
|
+
var SESSION_LIST_TOOL = "session_list";
|
|
3441
3444
|
var SESSION_QUERY_TOOLS = Object.freeze([
|
|
3442
3445
|
SESSION_SEARCH_TOOL,
|
|
3443
3446
|
SESSION_MESSAGES_SEARCH_TOOL,
|
|
3444
3447
|
SESSION_MESSAGES_READ_TOOL,
|
|
3445
|
-
SESSION_TRACE_TOOL
|
|
3448
|
+
SESSION_TRACE_TOOL,
|
|
3449
|
+
SESSION_LIST_TOOL
|
|
3446
3450
|
]);
|
|
3447
3451
|
var MAX_SNIPPET = 160;
|
|
3448
3452
|
var CANDIDATE_FACTOR = 4;
|
|
@@ -3536,6 +3540,36 @@ var SessionQueries = class {
|
|
|
3536
3540
|
trace(input) {
|
|
3537
3541
|
return traceSession(this.db, input);
|
|
3538
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
|
+
}
|
|
3539
3573
|
contentRows(safe, limit, visClause, visParams) {
|
|
3540
3574
|
const sql = (table) => `
|
|
3541
3575
|
SELECT m.id, m.session_id, m.role, m.content, m.timestamp, m.active,
|
|
@@ -3601,7 +3635,123 @@ var SessionQueries = class {
|
|
|
3601
3635
|
return this.db.prepare(sql("messages_fts_trigram")).all({ query: buildTrigramMatchQuery(safe), sid: sessionId, limit });
|
|
3602
3636
|
}
|
|
3603
3637
|
};
|
|
3604
|
-
// 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
|
+
}
|
|
3605
3755
|
var DEFAULT_WINDOW = 2;
|
|
3606
3756
|
var MAX_WINDOW = 10;
|
|
3607
3757
|
var DEFAULT_TRACE_LIMIT = 20;
|
|
@@ -3609,7 +3759,7 @@ var MAX_TRACE_LIMIT = 50;
|
|
|
3609
3759
|
var BODY_BUDGET = 1500;
|
|
3610
3760
|
var MIN_BODY = 60;
|
|
3611
3761
|
var ANCHOR_SHARE = 4;
|
|
3612
|
-
function
|
|
3762
|
+
function fail4(message, start, code, suggestion) {
|
|
3613
3763
|
return {
|
|
3614
3764
|
success: false,
|
|
3615
3765
|
output: "",
|
|
@@ -3623,7 +3773,7 @@ function clampWindow(raw, fallback2, max) {
|
|
|
3623
3773
|
if (!Number.isFinite(n) || n < 0) return fallback2;
|
|
3624
3774
|
return Math.min(Math.floor(n), max);
|
|
3625
3775
|
}
|
|
3626
|
-
function
|
|
3776
|
+
function stamp2(ms) {
|
|
3627
3777
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
3628
3778
|
}
|
|
3629
3779
|
function budgetOf(total) {
|
|
@@ -3645,7 +3795,7 @@ function surfaceOf(record, isCurrent) {
|
|
|
3645
3795
|
function renderRecord(record, mark, budget, isCurrent) {
|
|
3646
3796
|
const tool = record.toolName ? ` \xB7 ${record.toolName}` : "";
|
|
3647
3797
|
return [
|
|
3648
|
-
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${
|
|
3798
|
+
`${mark} #${record.messageId} [${record.role}${tool} \xB7 ${stamp2(record.timestamp)} \xB7 ${surfaceOf(record, isCurrent)}]`,
|
|
3649
3799
|
` ${body(record.content, budget).split("\n").join("\n ")}`
|
|
3650
3800
|
].join("\n");
|
|
3651
3801
|
}
|
|
@@ -3711,11 +3861,11 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3711
3861
|
execute(args, ctx) {
|
|
3712
3862
|
const start = Date.now();
|
|
3713
3863
|
const sessionId = String(args["sessionId"] ?? "").trim();
|
|
3714
|
-
if (!sessionId) return Promise.resolve(
|
|
3864
|
+
if (!sessionId) return Promise.resolve(fail4("sessionId must not be empty", start, 8007));
|
|
3715
3865
|
const messageId = Number(args["messageId"]);
|
|
3716
3866
|
if (!Number.isInteger(messageId) || messageId <= 0) {
|
|
3717
3867
|
return Promise.resolve(
|
|
3718
|
-
|
|
3868
|
+
fail4(
|
|
3719
3869
|
"messageId must be a positive integer",
|
|
3720
3870
|
start,
|
|
3721
3871
|
8008,
|
|
@@ -3736,7 +3886,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3736
3886
|
});
|
|
3737
3887
|
if (!out.authorized) {
|
|
3738
3888
|
return Promise.resolve(
|
|
3739
|
-
|
|
3889
|
+
fail4(
|
|
3740
3890
|
`session ${sessionId} is out of readable scope`,
|
|
3741
3891
|
start,
|
|
3742
3892
|
8009,
|
|
@@ -3746,7 +3896,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3746
3896
|
}
|
|
3747
3897
|
if (!out.anchor) {
|
|
3748
3898
|
return Promise.resolve(
|
|
3749
|
-
|
|
3899
|
+
fail4(
|
|
3750
3900
|
`session ${sessionId} has no message #${messageId} (it has ${out.total})`,
|
|
3751
3901
|
start,
|
|
3752
3902
|
8010,
|
|
@@ -3760,7 +3910,7 @@ before / after \u5404\u9ED8\u8BA4 ${DEFAULT_WINDOW}\u3001\u4E0A\u9650 ${MAX_WIND
|
|
|
3760
3910
|
duration: Date.now() - start
|
|
3761
3911
|
});
|
|
3762
3912
|
} catch (err) {
|
|
3763
|
-
return Promise.resolve(
|
|
3913
|
+
return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8011));
|
|
3764
3914
|
}
|
|
3765
3915
|
}
|
|
3766
3916
|
};
|
|
@@ -3774,7 +3924,7 @@ function renderNode(node, isCurrent) {
|
|
|
3774
3924
|
const where = node.cwd ? ` \xB7 ${node.cwd}` : "";
|
|
3775
3925
|
const archived = node.archived ? " \xB7 archived" : "";
|
|
3776
3926
|
return `${indent}${node.sessionId}${self} \u2014 ${node.title || "(untitled)"}
|
|
3777
|
-
${indent} ${
|
|
3927
|
+
${indent} ${stamp2(node.startedAt ?? 0)} \xB7 ${node.messageCount ?? 0} messages${where}${archived}`;
|
|
3778
3928
|
}
|
|
3779
3929
|
function renderTrace(trace, currentSessionId) {
|
|
3780
3930
|
const anchor = trace.anchor;
|
|
@@ -3853,7 +4003,7 @@ function createSessionTraceTool(deps) {
|
|
|
3853
4003
|
});
|
|
3854
4004
|
if (!trace.authorized) {
|
|
3855
4005
|
return Promise.resolve(
|
|
3856
|
-
|
|
4006
|
+
fail4(
|
|
3857
4007
|
`session ${sessionId} is out of readable scope`,
|
|
3858
4008
|
start,
|
|
3859
4009
|
8012,
|
|
@@ -3867,14 +4017,14 @@ function createSessionTraceTool(deps) {
|
|
|
3867
4017
|
duration: Date.now() - start
|
|
3868
4018
|
});
|
|
3869
4019
|
} catch (err) {
|
|
3870
|
-
return Promise.resolve(
|
|
4020
|
+
return Promise.resolve(fail4(err instanceof Error ? err.message : String(err), start, 8013));
|
|
3871
4021
|
}
|
|
3872
4022
|
}
|
|
3873
4023
|
};
|
|
3874
4024
|
}
|
|
3875
|
-
var
|
|
3876
|
-
var
|
|
3877
|
-
function
|
|
4025
|
+
var DEFAULT_LIMIT2 = 5;
|
|
4026
|
+
var MAX_LIMIT2 = 20;
|
|
4027
|
+
function fail5(message, start, code, suggestion) {
|
|
3878
4028
|
return {
|
|
3879
4029
|
success: false,
|
|
3880
4030
|
output: "",
|
|
@@ -3885,12 +4035,12 @@ function fail4(message, start, code, suggestion) {
|
|
|
3885
4035
|
function emptyHint(query) {
|
|
3886
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.";
|
|
3887
4037
|
}
|
|
3888
|
-
function
|
|
4038
|
+
function clampLimit2(raw) {
|
|
3889
4039
|
const n = Number(raw);
|
|
3890
|
-
if (!Number.isFinite(n) || n <= 0) return
|
|
3891
|
-
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);
|
|
3892
4042
|
}
|
|
3893
|
-
function
|
|
4043
|
+
function stamp3(ms) {
|
|
3894
4044
|
return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
|
|
3895
4045
|
}
|
|
3896
4046
|
function surfaceNote(hit, isCurrent) {
|
|
@@ -3904,14 +4054,14 @@ function renderSessionHit(hit, index) {
|
|
|
3904
4054
|
const self = hit.isCurrent ? " (this session)" : "";
|
|
3905
4055
|
return [
|
|
3906
4056
|
`${index + 1}. ${hit.sessionId}${self} \u2014 ${hit.title || "(untitled)"}`,
|
|
3907
|
-
` ${
|
|
4057
|
+
` ${stamp3(hit.startedAt)} \xB7 ${hit.messageCount} messages${where}`,
|
|
3908
4058
|
` best match [${hit.best.role} #${hit.best.messageId}, ${surfaceNote(hit.best, hit.isCurrent)}]:`,
|
|
3909
4059
|
` ${hit.best.snippet}`
|
|
3910
4060
|
].join("\n");
|
|
3911
4061
|
}
|
|
3912
4062
|
function renderMessageHit(hit, isCurrent) {
|
|
3913
4063
|
return [
|
|
3914
|
-
`#${hit.messageId} [${hit.role} \xB7 ${
|
|
4064
|
+
`#${hit.messageId} [${hit.role} \xB7 ${stamp3(hit.timestamp)} \xB7 ${surfaceNote(hit, isCurrent)}]`,
|
|
3915
4065
|
` ${hit.snippet}`
|
|
3916
4066
|
].join("\n");
|
|
3917
4067
|
}
|
|
@@ -3929,7 +4079,7 @@ function createSessionSearchTool(deps) {
|
|
|
3929
4079
|
},
|
|
3930
4080
|
limit: {
|
|
3931
4081
|
type: "number",
|
|
3932
|
-
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}`
|
|
3933
4083
|
},
|
|
3934
4084
|
scope: {
|
|
3935
4085
|
type: "string",
|
|
@@ -3959,13 +4109,13 @@ function createSessionSearchTool(deps) {
|
|
|
3959
4109
|
execute(args, ctx) {
|
|
3960
4110
|
const start = Date.now();
|
|
3961
4111
|
const query = String(args["query"] ?? "").trim();
|
|
3962
|
-
if (!query) return Promise.resolve(
|
|
4112
|
+
if (!query) return Promise.resolve(fail5("query must not be empty", start, 8001));
|
|
3963
4113
|
const allWorkspaces = deps.allowAllWorkspaces === true && args["allWorkspaces"] === true;
|
|
3964
4114
|
const scope = args["scope"] === "title" ? "title" : "all";
|
|
3965
4115
|
try {
|
|
3966
4116
|
const hits = deps.queries.searchSessions({
|
|
3967
4117
|
query,
|
|
3968
|
-
limit:
|
|
4118
|
+
limit: clampLimit2(args["limit"]),
|
|
3969
4119
|
scope,
|
|
3970
4120
|
currentSessionId: ctx.sessionId,
|
|
3971
4121
|
workspaceCwd: deps.workspaceCwd,
|
|
@@ -3992,7 +4142,7 @@ function createSessionSearchTool(deps) {
|
|
|
3992
4142
|
});
|
|
3993
4143
|
} catch (err) {
|
|
3994
4144
|
return Promise.resolve(
|
|
3995
|
-
|
|
4145
|
+
fail5(
|
|
3996
4146
|
err instanceof Error ? err.message : String(err),
|
|
3997
4147
|
start,
|
|
3998
4148
|
8002,
|
|
@@ -4021,7 +4171,7 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4021
4171
|
},
|
|
4022
4172
|
limit: {
|
|
4023
4173
|
type: "number",
|
|
4024
|
-
description: `\u8FD4\u56DE\u51E0\u6761\uFF0C\u9ED8\u8BA4 ${
|
|
4174
|
+
description: `\u8FD4\u56DE\u51E0\u6761\uFF0C\u9ED8\u8BA4 ${DEFAULT_LIMIT2}\uFF0C\u4E0A\u9650 ${MAX_LIMIT2}`
|
|
4025
4175
|
},
|
|
4026
4176
|
...deps.allowAllWorkspaces ? {
|
|
4027
4177
|
allWorkspaces: {
|
|
@@ -4047,21 +4197,21 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4047
4197
|
const start = Date.now();
|
|
4048
4198
|
const sessionId = String(args["sessionId"] ?? "").trim();
|
|
4049
4199
|
const query = String(args["query"] ?? "").trim();
|
|
4050
|
-
if (!sessionId) return Promise.resolve(
|
|
4051
|
-
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));
|
|
4052
4202
|
const allWorkspaces = deps.allowAllWorkspaces === true && args["allWorkspaces"] === true;
|
|
4053
4203
|
try {
|
|
4054
4204
|
const out = deps.queries.searchMessages({
|
|
4055
4205
|
sessionId,
|
|
4056
4206
|
query,
|
|
4057
|
-
limit:
|
|
4207
|
+
limit: clampLimit2(args["limit"]),
|
|
4058
4208
|
currentSessionId: ctx.sessionId,
|
|
4059
4209
|
workspaceCwd: deps.workspaceCwd,
|
|
4060
4210
|
allWorkspaces
|
|
4061
4211
|
});
|
|
4062
4212
|
if (!out.authorized) {
|
|
4063
4213
|
return Promise.resolve(
|
|
4064
|
-
|
|
4214
|
+
fail5(
|
|
4065
4215
|
`session ${sessionId} is out of searchable scope`,
|
|
4066
4216
|
start,
|
|
4067
4217
|
8005,
|
|
@@ -4088,7 +4238,7 @@ function createSessionMessagesSearchTool(deps) {
|
|
|
4088
4238
|
});
|
|
4089
4239
|
} catch (err) {
|
|
4090
4240
|
return Promise.resolve(
|
|
4091
|
-
|
|
4241
|
+
fail5(
|
|
4092
4242
|
err instanceof Error ? err.message : String(err),
|
|
4093
4243
|
start,
|
|
4094
4244
|
8006,
|
|
@@ -4104,12 +4254,13 @@ function createSessionSearchTools(deps) {
|
|
|
4104
4254
|
createSessionSearchTool(deps),
|
|
4105
4255
|
createSessionMessagesSearchTool(deps),
|
|
4106
4256
|
createSessionMessagesReadTool(deps),
|
|
4107
|
-
createSessionTraceTool(deps)
|
|
4257
|
+
createSessionTraceTool(deps),
|
|
4258
|
+
createSessionListTool(deps)
|
|
4108
4259
|
];
|
|
4109
4260
|
}
|
|
4110
4261
|
var SKILL_VIEW_TOOL = "skill_view";
|
|
4111
4262
|
var MAX_SUGGESTED = 20;
|
|
4112
|
-
function
|
|
4263
|
+
function fail6(message, start, code, suggestion) {
|
|
4113
4264
|
return {
|
|
4114
4265
|
success: false,
|
|
4115
4266
|
output: "",
|
|
@@ -4154,18 +4305,18 @@ function createSkillViewTool(deps) {
|
|
|
4154
4305
|
const name = String(args["name"] ?? "").trim();
|
|
4155
4306
|
if (!name) {
|
|
4156
4307
|
return Promise.resolve(
|
|
4157
|
-
|
|
4308
|
+
fail6("name must not be empty", start, 3001, describeAvailableSkills(deps.skills))
|
|
4158
4309
|
);
|
|
4159
4310
|
}
|
|
4160
4311
|
const body2 = deps.skills.view(name);
|
|
4161
4312
|
if (body2 === null) {
|
|
4162
4313
|
return Promise.resolve(
|
|
4163
|
-
|
|
4314
|
+
fail6(`skill "${name}" not found`, start, 3002, describeAvailableSkills(deps.skills))
|
|
4164
4315
|
);
|
|
4165
4316
|
}
|
|
4166
4317
|
if (body2.trim() === "") {
|
|
4167
4318
|
return Promise.resolve(
|
|
4168
|
-
|
|
4319
|
+
fail6(
|
|
4169
4320
|
`skill "${name}" has an empty body \u2014 its SKILL.md is missing or empty`,
|
|
4170
4321
|
start,
|
|
4171
4322
|
3003,
|
|
@@ -4292,7 +4443,7 @@ var SKILL_EDIT_TOOL = "skill_edit";
|
|
|
4292
4443
|
var SKILL_PATCH_TOOL = "skill_patch";
|
|
4293
4444
|
var SKILL_WRITE_FILE_TOOL = "skill_write_file";
|
|
4294
4445
|
var WRITABLE_SKILL_NAME = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
|
|
4295
|
-
function
|
|
4446
|
+
function fail7(message, start, code, suggestion) {
|
|
4296
4447
|
return {
|
|
4297
4448
|
success: false,
|
|
4298
4449
|
output: "",
|
|
@@ -4304,7 +4455,7 @@ function done(output, start) {
|
|
|
4304
4455
|
return { success: true, output, duration: Date.now() - start };
|
|
4305
4456
|
}
|
|
4306
4457
|
function fromThrow(err, start, suggestion) {
|
|
4307
|
-
return
|
|
4458
|
+
return fail7(err instanceof Error ? err.message : String(err), start, 3102, suggestion);
|
|
4308
4459
|
}
|
|
4309
4460
|
function str2(args, key) {
|
|
4310
4461
|
const raw = args[key];
|
|
@@ -4360,13 +4511,13 @@ function createTool(deps) {
|
|
|
4360
4511
|
const content = str2(args, "content");
|
|
4361
4512
|
const category = str2(args, "category").trim() || "general";
|
|
4362
4513
|
if (!WRITABLE_SKILL_NAME.test(name)) {
|
|
4363
|
-
return
|
|
4514
|
+
return fail7(`invalid skill name: ${JSON.stringify(name)}`, start, 3101, WRITABLE_HINT);
|
|
4364
4515
|
}
|
|
4365
4516
|
if (!WRITABLE_SKILL_NAME.test(category)) {
|
|
4366
|
-
return
|
|
4517
|
+
return fail7(`invalid category: ${JSON.stringify(category)}`, start, 3101, WRITABLE_HINT);
|
|
4367
4518
|
}
|
|
4368
4519
|
const bad2 = checkFrontmatter(name, content);
|
|
4369
|
-
if (bad2 !== null) return
|
|
4520
|
+
if (bad2 !== null) return fail7(bad2, start, 3103);
|
|
4370
4521
|
try {
|
|
4371
4522
|
const path = await deps.skills.create(name, content, category);
|
|
4372
4523
|
return done(`created skill "${name}" at ${path}`, start);
|
|
@@ -4398,10 +4549,10 @@ function editTool(deps) {
|
|
|
4398
4549
|
const name = str2(args, "name").trim();
|
|
4399
4550
|
const content = str2(args, "content");
|
|
4400
4551
|
if (!name) {
|
|
4401
|
-
return
|
|
4552
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4402
4553
|
}
|
|
4403
4554
|
const bad2 = checkFrontmatter(name, content);
|
|
4404
|
-
if (bad2 !== null) return
|
|
4555
|
+
if (bad2 !== null) return fail7(bad2, start, 3103);
|
|
4405
4556
|
try {
|
|
4406
4557
|
await deps.skills.edit(name, content);
|
|
4407
4558
|
return done(`rewrote SKILL.md of skill "${name}"`, start);
|
|
@@ -4439,10 +4590,10 @@ function patchTool(deps) {
|
|
|
4439
4590
|
const oldString = str2(args, "old_string");
|
|
4440
4591
|
const filePath = str2(args, "file_path").trim();
|
|
4441
4592
|
if (!name) {
|
|
4442
|
-
return
|
|
4593
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4443
4594
|
}
|
|
4444
4595
|
if (oldString === "") {
|
|
4445
|
-
return
|
|
4596
|
+
return fail7("old_string must not be empty", start, 3101);
|
|
4446
4597
|
}
|
|
4447
4598
|
try {
|
|
4448
4599
|
await deps.skills.patch(
|
|
@@ -4484,9 +4635,9 @@ function writeFileTool(deps) {
|
|
|
4484
4635
|
const name = str2(args, "name").trim();
|
|
4485
4636
|
const filePath = str2(args, "file_path").trim();
|
|
4486
4637
|
if (!name) {
|
|
4487
|
-
return
|
|
4638
|
+
return fail7("name must not be empty", start, 3101, describeAvailableSkills(deps.skills));
|
|
4488
4639
|
}
|
|
4489
|
-
if (!filePath) return
|
|
4640
|
+
if (!filePath) return fail7("file_path must not be empty", start, 3101);
|
|
4490
4641
|
try {
|
|
4491
4642
|
await deps.skills.writeFile(name, filePath, str2(args, "content"));
|
|
4492
4643
|
return done(`wrote ${filePath} into skill "${name}"`, start);
|
|
@@ -4502,7 +4653,7 @@ function createSkillWriteTools(deps) {
|
|
|
4502
4653
|
var TOOL_SEARCH_TOOL = "tool_search";
|
|
4503
4654
|
var MAX_LISTED = 40;
|
|
4504
4655
|
var MAX_REVEAL_PER_CALL = 10;
|
|
4505
|
-
function
|
|
4656
|
+
function fail8(message, start, code, suggestion) {
|
|
4506
4657
|
return {
|
|
4507
4658
|
success: false,
|
|
4508
4659
|
output: "",
|
|
@@ -4552,12 +4703,12 @@ function createToolSearchTool(deps) {
|
|
|
4552
4703
|
const pool = deps.deferred();
|
|
4553
4704
|
const raw = String(args["query"] ?? "").trim();
|
|
4554
4705
|
if (!raw) {
|
|
4555
|
-
return Promise.resolve(
|
|
4706
|
+
return Promise.resolve(fail8("query must not be empty", start, 3101, available(pool)));
|
|
4556
4707
|
}
|
|
4557
4708
|
const terms = raw.toLowerCase().split(/\s+/).filter(Boolean);
|
|
4558
4709
|
const hits = pool.filter((tool) => matches(tool, terms));
|
|
4559
4710
|
if (hits.length === 0) {
|
|
4560
|
-
return Promise.resolve(
|
|
4711
|
+
return Promise.resolve(fail8(`No tool matches "${raw}"`, start, 3102, available(pool)));
|
|
4561
4712
|
}
|
|
4562
4713
|
const picked = hits.slice(0, MAX_REVEAL_PER_CALL);
|
|
4563
4714
|
for (const tool of picked) deps.reveal.reveal(tool.name);
|
|
@@ -5113,7 +5264,7 @@ function createRoleFile(input, opts) {
|
|
|
5113
5264
|
const detail = checked.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
|
|
5114
5265
|
return { ok: false, reason: "invalid-field", detail };
|
|
5115
5266
|
}
|
|
5116
|
-
const text =
|
|
5267
|
+
const text = render2(fm, input.prompt ?? "");
|
|
5117
5268
|
const file = `${name}.md`;
|
|
5118
5269
|
const back = parseRoleDefinition(text, file, opts.source ?? "user");
|
|
5119
5270
|
if (!back.role) {
|
|
@@ -5145,7 +5296,7 @@ function frontmatterOf(name, input) {
|
|
|
5145
5296
|
...input.maxTurns === void 0 ? {} : { maxTurns: input.maxTurns }
|
|
5146
5297
|
};
|
|
5147
5298
|
}
|
|
5148
|
-
function
|
|
5299
|
+
function render2(fm, prompt) {
|
|
5149
5300
|
const head = dump(fm, { lineWidth: -1, noRefs: true });
|
|
5150
5301
|
const body2 = prompt.trim();
|
|
5151
5302
|
return `---
|
|
@@ -7017,11 +7168,29 @@ var MARKETPLACE_DISPLAY_FIELDS = [
|
|
|
7017
7168
|
var DisplaySchema = z.object({
|
|
7018
7169
|
fields: z.array(z.string().min(1)).optional()
|
|
7019
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
|
+
}
|
|
7020
7188
|
var CatalogSchema = z.object({
|
|
7021
7189
|
name: z.string().regex(NAME_PATTERN),
|
|
7022
7190
|
description: z.string().min(1).optional(),
|
|
7023
7191
|
owner: z.object({ name: z.string().min(1), url: z.string().min(1).optional() }).optional(),
|
|
7024
7192
|
display: DisplaySchema.optional(),
|
|
7193
|
+
categories: CategoriesSchema,
|
|
7025
7194
|
plugins: z.array(EntrySchema)
|
|
7026
7195
|
});
|
|
7027
7196
|
var RecordSchema2 = z.object({
|
|
@@ -7037,13 +7206,17 @@ var StateSchema2 = z.object({
|
|
|
7037
7206
|
function projectEntryForDisplay(entry, display) {
|
|
7038
7207
|
const allowed = display?.fields;
|
|
7039
7208
|
if (allowed === void 0) return entry;
|
|
7040
|
-
const keep = new Set(allowed);
|
|
7041
7209
|
const out = { ...entry };
|
|
7042
7210
|
for (const field of MARKETPLACE_DISPLAY_FIELDS) {
|
|
7043
|
-
if (!
|
|
7211
|
+
if (!displayAllows(display, field)) delete out[field];
|
|
7044
7212
|
}
|
|
7045
7213
|
return out;
|
|
7046
7214
|
}
|
|
7215
|
+
function displayAllows(display, field) {
|
|
7216
|
+
const allowed = display?.fields;
|
|
7217
|
+
if (allowed === void 0) return true;
|
|
7218
|
+
return allowed.includes(field);
|
|
7219
|
+
}
|
|
7047
7220
|
function readMarketplaces(statePath) {
|
|
7048
7221
|
if (!existsSync(statePath)) return { records: [], issues: [] };
|
|
7049
7222
|
let raw;
|
|
@@ -9264,7 +9437,18 @@ function gitProbeEnv() {
|
|
|
9264
9437
|
delete env.GIT_WORK_TREE;
|
|
9265
9438
|
return env;
|
|
9266
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
|
+
}
|
|
9267
9449
|
function getGitStatus(rootDir) {
|
|
9450
|
+
if (!insideGitRepo(rootDir)) return void 0;
|
|
9451
|
+
if (!canProbeGit()) return void 0;
|
|
9268
9452
|
const quiet = ["ignore", "pipe", "ignore"];
|
|
9269
9453
|
const env = gitProbeEnv();
|
|
9270
9454
|
try {
|
|
@@ -14280,6 +14464,7 @@ var SETTING_WRITE_KEYS = [
|
|
|
14280
14464
|
"sessions.vacuumAfterPrune",
|
|
14281
14465
|
"automation.keepRuns",
|
|
14282
14466
|
"automation.maxRecordingMb",
|
|
14467
|
+
"sessionSearch.allWorkspaces",
|
|
14283
14468
|
"permission"
|
|
14284
14469
|
];
|
|
14285
14470
|
function isWritableSettingKey(value) {
|
|
@@ -14349,6 +14534,7 @@ var VALUE_SCHEMA = {
|
|
|
14349
14534
|
"sessions.vacuumAfterPrune": EpochConfigSchema.shape.sessions.unwrap().shape.vacuumAfterPrune.unwrap(),
|
|
14350
14535
|
"automation.keepRuns": EpochConfigSchema.shape.automation.unwrap().shape.keepRuns.unwrap(),
|
|
14351
14536
|
"automation.maxRecordingMb": EpochConfigSchema.shape.automation.unwrap().shape.maxRecordingMb.unwrap(),
|
|
14537
|
+
"sessionSearch.allWorkspaces": EpochConfigSchema.shape.sessionSearch.unwrap().shape.allWorkspaces.unwrap(),
|
|
14352
14538
|
permission: EpochConfigSchema.shape.permission.unwrap()
|
|
14353
14539
|
};
|
|
14354
14540
|
function settingValueKind(key) {
|
|
@@ -15527,6 +15713,17 @@ function textSimilarity(a, b) {
|
|
|
15527
15713
|
const union = /* @__PURE__ */ new Set([...wordsA, ...wordsB]);
|
|
15528
15714
|
return intersection / union.size;
|
|
15529
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
|
+
}
|
|
15530
15727
|
// src/goal/store.ts
|
|
15531
15728
|
function toGoal(row) {
|
|
15532
15729
|
const phase = isGoalPhase(row.phase) ? row.phase : "blocked";
|
|
@@ -15680,6 +15877,52 @@ function restoreParts(parts, opts) {
|
|
|
15680
15877
|
}
|
|
15681
15878
|
});
|
|
15682
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
|
+
}
|
|
15683
15926
|
function stripArtifactData(artifacts) {
|
|
15684
15927
|
return artifacts.map(({ data: _data, ...rest }) => rest);
|
|
15685
15928
|
}
|
|
@@ -16178,13 +16421,11 @@ var FTS_EXTERNAL_MIGRATIONS = [
|
|
|
16178
16421
|
var SessionDB = class {
|
|
16179
16422
|
db;
|
|
16180
16423
|
path;
|
|
16181
|
-
msgId = 0;
|
|
16182
16424
|
constructor(dbPath$1) {
|
|
16183
16425
|
this.path = dbPath$1 ?? dbPath();
|
|
16184
16426
|
this.db = openDatabase(this.path);
|
|
16185
16427
|
migrate(this.db, NS3, SESSION_MIGRATIONS);
|
|
16186
16428
|
this.migrateFtsIndex();
|
|
16187
|
-
this.refreshMsgId();
|
|
16188
16429
|
}
|
|
16189
16430
|
migrateFtsIndex() {
|
|
16190
16431
|
try {
|
|
@@ -16196,9 +16437,8 @@ var SessionDB = class {
|
|
|
16196
16437
|
);
|
|
16197
16438
|
}
|
|
16198
16439
|
}
|
|
16199
|
-
|
|
16200
|
-
|
|
16201
|
-
this.msgId = row?.maxId ?? 0;
|
|
16440
|
+
transaction(fn) {
|
|
16441
|
+
return this.db.transaction(fn)();
|
|
16202
16442
|
}
|
|
16203
16443
|
insertSession(meta) {
|
|
16204
16444
|
this.db.prepare(
|
|
@@ -16252,7 +16492,7 @@ var SessionDB = class {
|
|
|
16252
16492
|
const dir = input.direction ?? "desc";
|
|
16253
16493
|
let where = "1=1";
|
|
16254
16494
|
const params = {};
|
|
16255
|
-
if (input.archived !== void 0) {
|
|
16495
|
+
if (input.archived === "any") ; else if (input.archived !== void 0) {
|
|
16256
16496
|
where += " AND archived = @archived";
|
|
16257
16497
|
params["archived"] = input.archived ? 1 : 0;
|
|
16258
16498
|
} else {
|
|
@@ -16265,6 +16505,10 @@ var SessionDB = class {
|
|
|
16265
16505
|
where += " AND cwd = @cwd";
|
|
16266
16506
|
params["cwd"] = input.cwd;
|
|
16267
16507
|
}
|
|
16508
|
+
if (input.updatedSince !== void 0) {
|
|
16509
|
+
where += " AND COALESCE(updated_at, started_at) > @updatedSince";
|
|
16510
|
+
params["updatedSince"] = input.updatedSince;
|
|
16511
|
+
}
|
|
16268
16512
|
if (input.cursor) {
|
|
16269
16513
|
where += ` AND ${cursorCol} < @cursor`;
|
|
16270
16514
|
params["cursor"] = Number(input.cursor);
|
|
@@ -16308,11 +16552,20 @@ var SessionDB = class {
|
|
|
16308
16552
|
unarchiveSession(id) {
|
|
16309
16553
|
this.db.prepare("UPDATE sessions SET archived = 0 WHERE id = ?").run(id);
|
|
16310
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
|
+
}
|
|
16311
16564
|
insertMessage(msg) {
|
|
16312
|
-
this.db.prepare(
|
|
16565
|
+
const info = this.db.prepare(
|
|
16313
16566
|
`
|
|
16314
|
-
INSERT INTO messages (
|
|
16315
|
-
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)
|
|
16316
16569
|
`
|
|
16317
16570
|
).run({
|
|
16318
16571
|
...msg,
|
|
@@ -16330,7 +16583,7 @@ var SessionDB = class {
|
|
|
16330
16583
|
this.db.prepare(
|
|
16331
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`
|
|
16332
16585
|
).run({ id: msg.sessionId, toolCalls, timestamp: msg.timestamp });
|
|
16333
|
-
|
|
16586
|
+
return Number(info.lastInsertRowid);
|
|
16334
16587
|
}
|
|
16335
16588
|
recordUsage(sessionId, usage) {
|
|
16336
16589
|
const priced = usage.costUsd !== void 0;
|
|
@@ -16392,9 +16645,6 @@ var SessionDB = class {
|
|
|
16392
16645
|
}
|
|
16393
16646
|
return info.changes;
|
|
16394
16647
|
}
|
|
16395
|
-
nextMessageId() {
|
|
16396
|
-
return ++this.msgId;
|
|
16397
|
-
}
|
|
16398
16648
|
search(input) {
|
|
16399
16649
|
const limit = input.limit ?? 5;
|
|
16400
16650
|
const scope = input.scope ?? "all";
|
|
@@ -16559,10 +16809,8 @@ var SessionDB = class {
|
|
|
16559
16809
|
if (middle.length === 0) return null;
|
|
16560
16810
|
const mark = this.db.prepare("UPDATE messages SET active = 0, compacted = 1 WHERE id = ?");
|
|
16561
16811
|
for (const row of middle) mark.run(row.id);
|
|
16562
|
-
const summaryId = this.
|
|
16563
|
-
this.insertMessage({
|
|
16812
|
+
const summaryId = this.insertMessage({
|
|
16564
16813
|
sessionId,
|
|
16565
|
-
id: summaryId,
|
|
16566
16814
|
role: "user",
|
|
16567
16815
|
content: input.summary,
|
|
16568
16816
|
timestamp: middle[0].timestamp
|
|
@@ -16918,6 +17166,61 @@ var SessionReferences = class {
|
|
|
16918
17166
|
};
|
|
16919
17167
|
// src/session/manager.ts
|
|
16920
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
|
+
}
|
|
16921
17224
|
var SessionManager = class {
|
|
16922
17225
|
db;
|
|
16923
17226
|
touched = /* @__PURE__ */ new Set();
|
|
@@ -17008,6 +17311,56 @@ var SessionManager = class {
|
|
|
17008
17311
|
list(input) {
|
|
17009
17312
|
return this.db.listSessions(input ?? {});
|
|
17010
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
|
+
}
|
|
17011
17364
|
updateMeta(id, patch) {
|
|
17012
17365
|
this.db.updateSessionMeta(id, patch);
|
|
17013
17366
|
}
|
|
@@ -17062,6 +17415,16 @@ var SessionManager = class {
|
|
|
17062
17415
|
return { ...result, error: cause instanceof Error ? cause.message : String(cause) };
|
|
17063
17416
|
}
|
|
17064
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
|
+
}
|
|
17065
17428
|
delete(id) {
|
|
17066
17429
|
return this.db.deleteSession(id);
|
|
17067
17430
|
}
|
|
@@ -17081,15 +17444,16 @@ var SessionManager = class {
|
|
|
17081
17444
|
}
|
|
17082
17445
|
appendMessage(sessionId, msg) {
|
|
17083
17446
|
this.touched.add(sessionId);
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
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
|
+
});
|
|
17093
17457
|
}
|
|
17094
17458
|
attachTurnFacts(sessionId, messageId, input) {
|
|
17095
17459
|
this.db.attachTurnFacts(sessionId, messageId, input);
|
|
@@ -17268,6 +17632,30 @@ function firstSentence(text, maxLen) {
|
|
|
17268
17632
|
const lastSpace = cut.lastIndexOf(" ");
|
|
17269
17633
|
return (lastSpace > maxLen * 0.6 ? cut.slice(0, lastSpace) : cut) + "\u2026";
|
|
17270
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
|
+
}
|
|
17271
17659
|
function isSettled(phase) {
|
|
17272
17660
|
return phase === "complete";
|
|
17273
17661
|
}
|
|
@@ -20083,9 +20471,9 @@ function buildAutomaton(patterns) {
|
|
|
20083
20471
|
while (queue.length > 0) {
|
|
20084
20472
|
const cur = queue.shift();
|
|
20085
20473
|
for (const [ch, child] of nodes[cur].next) {
|
|
20086
|
-
let
|
|
20087
|
-
while (
|
|
20088
|
-
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);
|
|
20089
20477
|
nodes[child].fail = target !== void 0 && target !== child ? target : 0;
|
|
20090
20478
|
nodes[child].out.push(...nodes[nodes[child].fail].out);
|
|
20091
20479
|
queue.push(child);
|
|
@@ -22150,6 +22538,7 @@ function listWorkspaceFiles(root) {
|
|
|
22150
22538
|
}
|
|
22151
22539
|
function listFromGit(root) {
|
|
22152
22540
|
if (!existsSync(join(root, ".git"))) return null;
|
|
22541
|
+
if (!canProbeGit()) return null;
|
|
22153
22542
|
try {
|
|
22154
22543
|
const out = execFileSync("git", ["ls-files", "-co", "--exclude-standard", "-z"], {
|
|
22155
22544
|
cwd: root,
|
|
@@ -22358,17 +22747,6 @@ function readSession(ref, opts, usedBytes) {
|
|
|
22358
22747
|
})
|
|
22359
22748
|
};
|
|
22360
22749
|
}
|
|
22361
|
-
var ATTACHMENT_RETENTION_DEFAULTS = {
|
|
22362
|
-
maxAgeDays: 7,
|
|
22363
|
-
maxTotalBytes: ATTACHMENT_MAX_TOTAL_BYTES
|
|
22364
|
-
};
|
|
22365
|
-
function pruneAttachments(root, keepSession, retention = ATTACHMENT_RETENTION_DEFAULTS, now = Date.now()) {
|
|
22366
|
-
const shared = retention;
|
|
22367
|
-
return pruneArtifacts(root, keepSession, shared, now);
|
|
22368
|
-
}
|
|
22369
|
-
async function removeSessionAttachments(sessionId, homeDir) {
|
|
22370
|
-
await rm(attachmentsDir(sessionId, homeDir), { recursive: true, force: true });
|
|
22371
|
-
}
|
|
22372
22750
|
var OPENABLE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
|
|
22373
22751
|
function artifactOpenRefusal(path, homeDir) {
|
|
22374
22752
|
const root = homeDir === void 0 ? artifactsDir() : artifactsDir(void 0, homeDir);
|
|
@@ -22403,12 +22781,12 @@ async function openArtifact(path, homeDir) {
|
|
|
22403
22781
|
if (refusal2) throw new Error(describeArtifactRefusal(refusal2));
|
|
22404
22782
|
const launch = artifactLaunchArgv(path, process.platform, homeDir);
|
|
22405
22783
|
if (!launch) throw new Error(describeArtifactRefusal("launch-failed"));
|
|
22406
|
-
await new Promise((done2,
|
|
22784
|
+
await new Promise((done2, fail9) => {
|
|
22407
22785
|
try {
|
|
22408
22786
|
const child = spawn(launch.command, launch.args, { stdio: "ignore", detached: true });
|
|
22409
22787
|
child.on(
|
|
22410
22788
|
"error",
|
|
22411
|
-
(err) =>
|
|
22789
|
+
(err) => fail9(
|
|
22412
22790
|
new Error(
|
|
22413
22791
|
t("artifact.open_launch_failed_detail", {
|
|
22414
22792
|
reason: describeArtifactRefusal("launch-failed"),
|
|
@@ -22422,7 +22800,7 @@ async function openArtifact(path, homeDir) {
|
|
|
22422
22800
|
done2();
|
|
22423
22801
|
});
|
|
22424
22802
|
} catch (err) {
|
|
22425
|
-
|
|
22803
|
+
fail9(
|
|
22426
22804
|
new Error(
|
|
22427
22805
|
t("artifact.open_launch_failed_detail", {
|
|
22428
22806
|
reason: describeArtifactRefusal("launch-failed"),
|
|
@@ -23279,4 +23657,4 @@ function trunc(stdout, stderr) {
|
|
|
23279
23657
|
* `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
|
|
23280
23658
|
*/
|
|
23281
23659
|
|
|
23282
|
-
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, 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 };
|