@epoch-agent/core 0.18.0 → 0.20.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 +2 -2
- package/dist/index.d.ts +370 -59
- package/dist/index.js +258 -265
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -650,7 +650,7 @@ var ToolRegistry = class {
|
|
|
650
650
|
this.addTool(tool, source);
|
|
651
651
|
}
|
|
652
652
|
registerTools(tools, source = "builtin") {
|
|
653
|
-
for (const
|
|
653
|
+
for (const t80 of tools) this.addTool(t80, source);
|
|
654
654
|
}
|
|
655
655
|
addTool(tool, source) {
|
|
656
656
|
const existing = this.tools.get(tool.name);
|
|
@@ -699,14 +699,14 @@ var ToolRegistry = class {
|
|
|
699
699
|
return isCodeModeDeferred(tool) ? ToolExposure.Deferred : declared;
|
|
700
700
|
}
|
|
701
701
|
exposed() {
|
|
702
|
-
return this.list().filter((
|
|
702
|
+
return this.list().filter((t80) => this.exposureOf(t80) === ToolExposure.Direct);
|
|
703
703
|
}
|
|
704
704
|
byExposure(exposure) {
|
|
705
|
-
return this.list().filter((
|
|
705
|
+
return this.list().filter((t80) => this.exposureOf(t80) === exposure);
|
|
706
706
|
}
|
|
707
707
|
codeModeDeclared() {
|
|
708
708
|
if (!this.codeMode) return [];
|
|
709
|
-
return this.list().filter((
|
|
709
|
+
return this.list().filter((t80) => isCodeModeDeferred(t80));
|
|
710
710
|
}
|
|
711
711
|
sourceOf(name) {
|
|
712
712
|
return this.tools.get(name)?.source;
|
|
@@ -755,7 +755,7 @@ var ToolRegistry = class {
|
|
|
755
755
|
function staticToolProvider(tools) {
|
|
756
756
|
return {
|
|
757
757
|
list: () => tools,
|
|
758
|
-
get: (name) => tools.find((
|
|
758
|
+
get: (name) => tools.find((t80) => t80.name === name)
|
|
759
759
|
};
|
|
760
760
|
}
|
|
761
761
|
var log = createLogger("tokenizer");
|
|
@@ -1388,7 +1388,7 @@ var DelegateManager = class {
|
|
|
1388
1388
|
}
|
|
1389
1389
|
normalizeTasks(args) {
|
|
1390
1390
|
if (args.tasks && args.tasks.length > 0) {
|
|
1391
|
-
return args.role ? args.tasks.map((
|
|
1391
|
+
return args.role ? args.tasks.map((t80) => ({ ...t80, role: t80.role ?? args.role })) : args.tasks;
|
|
1392
1392
|
}
|
|
1393
1393
|
if (args.goal) return [{ goal: args.goal, ...args.role ? { role: args.role } : {} }];
|
|
1394
1394
|
return [];
|
|
@@ -1398,7 +1398,7 @@ var DelegateManager = class {
|
|
|
1398
1398
|
for (let i = 0; i < tasks.length; i += maxConcurrent) {
|
|
1399
1399
|
const batch = tasks.slice(i, i + maxConcurrent);
|
|
1400
1400
|
const batchResults = await Promise.allSettled(
|
|
1401
|
-
batch.map((
|
|
1401
|
+
batch.map((t80) => this.runSingleTask(t80, parentSessionId, signal))
|
|
1402
1402
|
);
|
|
1403
1403
|
for (const r of batchResults) {
|
|
1404
1404
|
if (r.status === "fulfilled") {
|
|
@@ -1556,21 +1556,21 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1556
1556
|
operation: "command",
|
|
1557
1557
|
describeTarget: (args) => {
|
|
1558
1558
|
const tasks = Array.isArray(args["tasks"]) ? args["tasks"] : [];
|
|
1559
|
-
const goals = tasks.map((
|
|
1559
|
+
const goals = tasks.map((t80) => String(t80["goal"] ?? ""));
|
|
1560
1560
|
const single = typeof args["goal"] === "string" ? args["goal"] : "";
|
|
1561
1561
|
return [...goals, single].filter(Boolean).join(" | ");
|
|
1562
1562
|
},
|
|
1563
1563
|
async execute(args, ctx) {
|
|
1564
1564
|
const start = Date.now();
|
|
1565
1565
|
const rawTasks = Array.isArray(args["tasks"]) ? args["tasks"] : void 0;
|
|
1566
|
-
const tasks = rawTasks?.map((
|
|
1567
|
-
const o =
|
|
1566
|
+
const tasks = rawTasks?.map((t80) => {
|
|
1567
|
+
const o = t80;
|
|
1568
1568
|
return {
|
|
1569
1569
|
goal: String(o["goal"] ?? "").trim(),
|
|
1570
1570
|
context: String(o["context"] ?? ""),
|
|
1571
1571
|
...typeof o["role"] === "string" && o["role"].trim() ? { role: o["role"].trim() } : {}
|
|
1572
1572
|
};
|
|
1573
|
-
}).filter((
|
|
1573
|
+
}).filter((t80) => t80.goal.length > 0);
|
|
1574
1574
|
const goal = typeof args["goal"] === "string" ? args["goal"].trim() : "";
|
|
1575
1575
|
const topRole = typeof args["role"] === "string" ? args["role"].trim() : "";
|
|
1576
1576
|
if ((!tasks || tasks.length === 0) && !goal) {
|
|
@@ -1586,7 +1586,7 @@ function createDelegateTool(runner, config, roles) {
|
|
|
1586
1586
|
};
|
|
1587
1587
|
}
|
|
1588
1588
|
const known = listRoles();
|
|
1589
|
-
const requested = [...(tasks ?? []).map((
|
|
1589
|
+
const requested = [...(tasks ?? []).map((t80) => t80.role), topRole].filter(
|
|
1590
1590
|
(r) => Boolean(r)
|
|
1591
1591
|
);
|
|
1592
1592
|
const unknown = [...new Set(requested)].filter((r) => !known.some((k) => k.name === r));
|
|
@@ -1760,8 +1760,8 @@ function createGoalTool(deps) {
|
|
|
1760
1760
|
}
|
|
1761
1761
|
var VALID_TARGETS = ["memory", "user"];
|
|
1762
1762
|
var VALID_ACTIONS = ["add", "replace", "remove", "search", "read", "budget"];
|
|
1763
|
-
function isValidTarget(
|
|
1764
|
-
return typeof
|
|
1763
|
+
function isValidTarget(t80) {
|
|
1764
|
+
return typeof t80 === "string" && VALID_TARGETS.includes(t80);
|
|
1765
1765
|
}
|
|
1766
1766
|
function isValidAction(a) {
|
|
1767
1767
|
return VALID_ACTIONS.includes(a);
|
|
@@ -4915,7 +4915,7 @@ function available(tools) {
|
|
|
4915
4915
|
if (tools.length === 0) {
|
|
4916
4916
|
return "No deferred tools in this session \u2014 every tool is already in your tool list.";
|
|
4917
4917
|
}
|
|
4918
|
-
const names = tools.map((
|
|
4918
|
+
const names = tools.map((t80) => t80.name).sort();
|
|
4919
4919
|
const shown = names.slice(0, MAX_LISTED);
|
|
4920
4920
|
const rest = names.length - shown.length;
|
|
4921
4921
|
return `Searchable tools: ${shown.join(", ")}${rest > 0 ? ` (\u2026and ${rest} more)` : ""}.`;
|
|
@@ -5035,15 +5035,15 @@ var TrackerDB = class {
|
|
|
5035
5035
|
);
|
|
5036
5036
|
this.db.transaction(() => {
|
|
5037
5037
|
this.db.prepare("DELETE FROM todos WHERE session_id = ?").run(sessionId);
|
|
5038
|
-
for (const
|
|
5038
|
+
for (const t80 of todos) {
|
|
5039
5039
|
insertStmt.run({
|
|
5040
|
-
id:
|
|
5040
|
+
id: t80.id,
|
|
5041
5041
|
session_id: sessionId,
|
|
5042
|
-
content:
|
|
5043
|
-
status:
|
|
5044
|
-
reason:
|
|
5045
|
-
created_at:
|
|
5046
|
-
updated_at:
|
|
5042
|
+
content: t80.content,
|
|
5043
|
+
status: t80.status,
|
|
5044
|
+
reason: t80.reason || null,
|
|
5045
|
+
created_at: t80.created_at,
|
|
5046
|
+
updated_at: t80.updated_at
|
|
5047
5047
|
});
|
|
5048
5048
|
}
|
|
5049
5049
|
})();
|
|
@@ -5065,9 +5065,9 @@ function formatTodoList(todos, pendingCount) {
|
|
|
5065
5065
|
cancelled: "\u5DF2\u53D6\u6D88"
|
|
5066
5066
|
};
|
|
5067
5067
|
lines.push(`[todo] \u72B6\u6001\u6C47\u603B: ${pendingCount} \u4E2A\u5F85\u5B8C\u6210`);
|
|
5068
|
-
for (const
|
|
5069
|
-
const label = statusLabel[
|
|
5070
|
-
lines.push(`- [${label}] ${
|
|
5068
|
+
for (const t80 of todos) {
|
|
5069
|
+
const label = statusLabel[t80.status] || t80.status;
|
|
5070
|
+
lines.push(`- [${label}] ${t80.content}${t80.reason ? ` \u2014\u2014 ${t80.reason}` : ""}`);
|
|
5071
5071
|
}
|
|
5072
5072
|
return lines.join("\n");
|
|
5073
5073
|
}
|
|
@@ -5141,14 +5141,14 @@ function createTodoTool(db) {
|
|
|
5141
5141
|
};
|
|
5142
5142
|
}
|
|
5143
5143
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5144
|
-
const existing = new Map(db.listBySession(ctx.sessionId).map((
|
|
5145
|
-
const todos = rawTodos.map((
|
|
5146
|
-
const prev =
|
|
5147
|
-
const status = isValidStatus(
|
|
5148
|
-
const reason9 = normalizeReason(status,
|
|
5144
|
+
const existing = new Map(db.listBySession(ctx.sessionId).map((t80) => [t80.id, t80]));
|
|
5145
|
+
const todos = rawTodos.map((t80) => {
|
|
5146
|
+
const prev = t80.id ? existing.get(t80.id) : void 0;
|
|
5147
|
+
const status = isValidStatus(t80.status) ? t80.status : "pending";
|
|
5148
|
+
const reason9 = normalizeReason(status, t80.reason);
|
|
5149
5149
|
return {
|
|
5150
|
-
id:
|
|
5151
|
-
content: String(
|
|
5150
|
+
id: t80.id || generateShortId(),
|
|
5151
|
+
content: String(t80.content || "").slice(0, 500),
|
|
5152
5152
|
status,
|
|
5153
5153
|
...reason9 ? { reason: reason9 } : {},
|
|
5154
5154
|
created_at: prev?.created_at || now,
|
|
@@ -5156,7 +5156,7 @@ function createTodoTool(db) {
|
|
|
5156
5156
|
};
|
|
5157
5157
|
});
|
|
5158
5158
|
db.replaceAll(ctx.sessionId, todos);
|
|
5159
|
-
const pendingCount = todos.filter((
|
|
5159
|
+
const pendingCount = todos.filter((t80) => isOpenTodo(t80.status)).length;
|
|
5160
5160
|
return {
|
|
5161
5161
|
success: true,
|
|
5162
5162
|
output: formatTodoList(todos, pendingCount),
|
|
@@ -5491,7 +5491,7 @@ function intersectNames(base, incoming) {
|
|
|
5491
5491
|
if (!base) return incoming ? [...incoming] : void 0;
|
|
5492
5492
|
if (!incoming) return [...base];
|
|
5493
5493
|
const baseSet = new Set(base);
|
|
5494
|
-
return incoming.filter((
|
|
5494
|
+
return incoming.filter((t80) => baseSet.has(t80));
|
|
5495
5495
|
}
|
|
5496
5496
|
function findRole(roles, name) {
|
|
5497
5497
|
return roles.find((r) => r.name === name);
|
|
@@ -5635,7 +5635,7 @@ function roleScopedProvider(base, role, blocked) {
|
|
|
5635
5635
|
return allow ? allow.has(name) : true;
|
|
5636
5636
|
};
|
|
5637
5637
|
return {
|
|
5638
|
-
list: () => base.list().filter((
|
|
5638
|
+
list: () => base.list().filter((t80) => permitted(t80.name)),
|
|
5639
5639
|
get: (name) => permitted(name) ? base.get(name) : void 0
|
|
5640
5640
|
};
|
|
5641
5641
|
}
|
|
@@ -5662,7 +5662,7 @@ function createRoleScope(base, sessionRole, blocked) {
|
|
|
5662
5662
|
}
|
|
5663
5663
|
function unknownRoleTools(base, role, blocked) {
|
|
5664
5664
|
if (!role?.tools) return [];
|
|
5665
|
-
const available2 = new Set(base.list().map((
|
|
5665
|
+
const available2 = new Set(base.list().map((t80) => t80.name));
|
|
5666
5666
|
const blockedSet = new Set(blocked);
|
|
5667
5667
|
return role.tools.filter((name) => !available2.has(name) && !blockedSet.has(name));
|
|
5668
5668
|
}
|
|
@@ -5998,7 +5998,7 @@ function createToolScope(base) {
|
|
|
5998
5998
|
const permitted = (name) => allow ? allow.has(name) : true;
|
|
5999
5999
|
return {
|
|
6000
6000
|
provider: {
|
|
6001
|
-
list: () => base.list().filter((
|
|
6001
|
+
list: () => base.list().filter((t80) => permitted(t80.name)),
|
|
6002
6002
|
get: (name) => permitted(name) ? base.get(name) : void 0
|
|
6003
6003
|
},
|
|
6004
6004
|
enter: (next) => {
|
|
@@ -6168,7 +6168,7 @@ function scanHooks(dir, issues) {
|
|
|
6168
6168
|
return [...parsed.entries].map(([type, list]) => ({
|
|
6169
6169
|
type,
|
|
6170
6170
|
count: list.reduce((sum, entry) => sum + entry.hooks.length, 0)
|
|
6171
|
-
})).filter((
|
|
6171
|
+
})).filter((t80) => t80.count > 0).sort((a, b) => a.type.localeCompare(b.type));
|
|
6172
6172
|
}
|
|
6173
6173
|
function scanMcp(dir, plugin, issues) {
|
|
6174
6174
|
const path = join(dir, PLUGIN_LAYOUT.mcp);
|
|
@@ -7386,11 +7386,12 @@ async function updatePlugin(name, opts) {
|
|
|
7386
7386
|
}
|
|
7387
7387
|
var MARKETPLACE_FILE = "epoch-marketplace.json";
|
|
7388
7388
|
var NAME_PATTERN = PLUGIN_NAME_PATTERN;
|
|
7389
|
-
var
|
|
7389
|
+
var EntryCategoryInput = z.union([z.string().min(1), z.array(z.string().min(1))]).optional().catch(void 0);
|
|
7390
|
+
var EntryShape = z.object({
|
|
7390
7391
|
name: z.string().regex(NAME_PATTERN),
|
|
7391
7392
|
description: z.string().min(1).optional(),
|
|
7392
7393
|
source: z.string().min(1),
|
|
7393
|
-
category:
|
|
7394
|
+
category: EntryCategoryInput,
|
|
7394
7395
|
keywords: z.array(z.string().min(1)).optional(),
|
|
7395
7396
|
author: PluginAuthorSchema.optional(),
|
|
7396
7397
|
downloads: z.number().int().nonnegative().optional(),
|
|
@@ -7404,6 +7405,10 @@ var EntrySchema = z.object({
|
|
|
7404
7405
|
visibility: z.enum(PLUGIN_VISIBILITY).optional().catch(void 0),
|
|
7405
7406
|
status: z.enum(["listed", "reviewing", "rejected", "offline"]).optional().catch(void 0)
|
|
7406
7407
|
});
|
|
7408
|
+
var EntrySchema = EntryShape.transform(({ category, ...rest }) => {
|
|
7409
|
+
const picked = category === void 0 ? [] : typeof category === "string" ? [category] : category;
|
|
7410
|
+
return { ...rest, ...picked.length === 0 ? {} : { category: [...picked] } };
|
|
7411
|
+
});
|
|
7407
7412
|
var MARKETPLACE_DISPLAY_FIELDS = [
|
|
7408
7413
|
"status",
|
|
7409
7414
|
"downloads",
|
|
@@ -7554,7 +7559,7 @@ function searchMarketplaces(keyword, statePath) {
|
|
|
7554
7559
|
const haystack = [
|
|
7555
7560
|
entry.name,
|
|
7556
7561
|
entry.description ?? "",
|
|
7557
|
-
entry.category ??
|
|
7562
|
+
...entry.category ?? [],
|
|
7558
7563
|
entry.author?.name ?? "",
|
|
7559
7564
|
...entry.keywords ?? []
|
|
7560
7565
|
].join(" ").toLowerCase();
|
|
@@ -7926,14 +7931,14 @@ var CheckpointStore = class {
|
|
|
7926
7931
|
}
|
|
7927
7932
|
async enforceTotalSize(protectSession, protectTurnIndex) {
|
|
7928
7933
|
const turns = await this.collectTurns();
|
|
7929
|
-
let total = turns.reduce((sum,
|
|
7934
|
+
let total = turns.reduce((sum, t80) => sum + t80.bytes, 0);
|
|
7930
7935
|
if (total <= this.maxTotalBytes) return;
|
|
7931
7936
|
turns.sort((a, b) => a.createdAt - b.createdAt);
|
|
7932
|
-
for (const
|
|
7937
|
+
for (const t80 of turns) {
|
|
7933
7938
|
if (total <= this.maxTotalBytes) return;
|
|
7934
|
-
if (
|
|
7935
|
-
await this.removeTurn(
|
|
7936
|
-
total -=
|
|
7939
|
+
if (t80.sessionId === protectSession && t80.turnIndex === protectTurnIndex) continue;
|
|
7940
|
+
await this.removeTurn(t80.sessionId, t80.turnIndex);
|
|
7941
|
+
total -= t80.bytes;
|
|
7937
7942
|
}
|
|
7938
7943
|
}
|
|
7939
7944
|
async collectTurns() {
|
|
@@ -10734,11 +10739,11 @@ var PromptBuilder = class {
|
|
|
10734
10739
|
memoryInitialized = false;
|
|
10735
10740
|
projectBlock(tools) {
|
|
10736
10741
|
const permLevel = this.deps.permissionManager?.getLevel() || "default";
|
|
10737
|
-
const hasPlanTool = tools.some((
|
|
10738
|
-
const hasLspTool = tools.some((
|
|
10739
|
-
const hasAskTool = tools.some((
|
|
10740
|
-
const hasTodoTool = tools.some((
|
|
10741
|
-
const hasTerminal = tools.some((
|
|
10742
|
+
const hasPlanTool = tools.some((t80) => t80.name === "enter_plan_mode");
|
|
10743
|
+
const hasLspTool = tools.some((t80) => t80.name === "lsp_diagnostics");
|
|
10744
|
+
const hasAskTool = tools.some((t80) => t80.name === "ask_user_question");
|
|
10745
|
+
const hasTodoTool = tools.some((t80) => t80.name === "todo");
|
|
10746
|
+
const hasTerminal = tools.some((t80) => t80.name === "terminal");
|
|
10742
10747
|
const needsCommandApproval = hasTerminal && permLevel === "default";
|
|
10743
10748
|
const plan = this.deps.approvedPlan?.()?.trim();
|
|
10744
10749
|
const codeSdk = renderSdkDeclaration(this.deps.codeModeTools?.() ?? []);
|
|
@@ -10775,7 +10780,7 @@ ${approvedPlanBlock(plan)}` : "");
|
|
|
10775
10780
|
return systemPromptSegments({
|
|
10776
10781
|
workDir: this.deps.site().workDir,
|
|
10777
10782
|
os: platform(),
|
|
10778
|
-
date: (/* @__PURE__ */ new Date())
|
|
10783
|
+
date: localDateString(/* @__PURE__ */ new Date()),
|
|
10779
10784
|
...role ? { role } : {},
|
|
10780
10785
|
...skillIndex ? { skillIndex } : {},
|
|
10781
10786
|
...model ? { model } : {},
|
|
@@ -11428,8 +11433,8 @@ function imageParts(content) {
|
|
|
11428
11433
|
return typeof content === "string" ? [] : content.filter((p) => p.type === "image");
|
|
11429
11434
|
}
|
|
11430
11435
|
function toolSignatureOf(config, tools) {
|
|
11431
|
-
const direct = tools.map((
|
|
11432
|
-
const declared = (config.codeModeTools?.() ?? []).map((
|
|
11436
|
+
const direct = tools.map((t80) => t80.name).join("\0");
|
|
11437
|
+
const declared = (config.codeModeTools?.() ?? []).map((t80) => t80.name).join("\0");
|
|
11433
11438
|
return declared ? `${direct}|${declared}` : direct;
|
|
11434
11439
|
}
|
|
11435
11440
|
function modelSignatureOf(info) {
|
|
@@ -11676,6 +11681,7 @@ var AgentLoop = class {
|
|
|
11676
11681
|
let toolSignature = toolSignatureOf(this.config, this.toolProvider.list());
|
|
11677
11682
|
let modelSignature = modelSignatureOf(this.modelInfo());
|
|
11678
11683
|
let planSignature = this.config.approvedPlan?.() ?? "";
|
|
11684
|
+
let dateSignature = localDateString(/* @__PURE__ */ new Date());
|
|
11679
11685
|
const streaming = this.config.streaming ?? true;
|
|
11680
11686
|
let totalInput = 0;
|
|
11681
11687
|
let totalOutput = 0;
|
|
@@ -11779,10 +11785,12 @@ var AgentLoop = class {
|
|
|
11779
11785
|
const signature = toolSignatureOf(this.config, tools);
|
|
11780
11786
|
const planNow = this.config.approvedPlan?.() ?? "";
|
|
11781
11787
|
const modelNow = modelSignatureOf(this.modelInfo());
|
|
11782
|
-
|
|
11788
|
+
const dateNow = localDateString(/* @__PURE__ */ new Date());
|
|
11789
|
+
if (signature !== toolSignature || planNow !== planSignature || modelNow !== modelSignature || dateNow !== dateSignature) {
|
|
11783
11790
|
toolSignature = signature;
|
|
11784
11791
|
planSignature = planNow;
|
|
11785
11792
|
modelSignature = modelNow;
|
|
11793
|
+
dateSignature = dateNow;
|
|
11786
11794
|
system = await this.prompt.buildSystem(input.sessionId);
|
|
11787
11795
|
}
|
|
11788
11796
|
if (turn === 1) {
|
|
@@ -11826,6 +11834,9 @@ var AgentLoop = class {
|
|
|
11826
11834
|
};
|
|
11827
11835
|
}
|
|
11828
11836
|
}
|
|
11837
|
+
for (const notice3 of this.config.memory?.takeNotices?.() ?? []) {
|
|
11838
|
+
yield { type: "notice", code: notice3.code, text: notice3.text };
|
|
11839
|
+
}
|
|
11829
11840
|
}
|
|
11830
11841
|
const turnStart = Date.now();
|
|
11831
11842
|
const llmSpan = this.telemetry.startSpan(
|
|
@@ -15068,11 +15079,11 @@ function buildSearchQuery(query) {
|
|
|
15068
15079
|
}
|
|
15069
15080
|
const latinPart = cleaned.replace(CJK_RUN, " ");
|
|
15070
15081
|
for (const w of latinPart.split(/\s+/)) {
|
|
15071
|
-
const
|
|
15072
|
-
if (
|
|
15082
|
+
const t80 = w.trim();
|
|
15083
|
+
if (t80.length >= 2) terms.add(t80);
|
|
15073
15084
|
}
|
|
15074
15085
|
if (terms.size === 0) return null;
|
|
15075
|
-
return [...terms].map((
|
|
15086
|
+
return [...terms].map((t80) => `"${t80.replace(/"/g, "")}"`).join(" OR ");
|
|
15076
15087
|
}
|
|
15077
15088
|
// src/memory/db.ts
|
|
15078
15089
|
var NS2 = "memory";
|
|
@@ -15105,6 +15116,14 @@ var MIGRATIONS2 = [
|
|
|
15105
15116
|
);
|
|
15106
15117
|
`);
|
|
15107
15118
|
}
|
|
15119
|
+
},
|
|
15120
|
+
{
|
|
15121
|
+
id: "memory-blocked-flag",
|
|
15122
|
+
version: 2,
|
|
15123
|
+
description: "\u6761\u76EE\u52A0 blocked \u6807\u8BB0\uFF1A\u547D\u4E2D\u6CE8\u5165\u6A21\u5F0F\u7684\u539F\u6587\u7559\u5728\u76D8\u4E0A\uFF0C\u53EA\u5728\u6E32\u67D3\u7ED9\u6A21\u578B\u65F6\u906E\u7F69",
|
|
15124
|
+
up: (db) => {
|
|
15125
|
+
db.exec("ALTER TABLE memory_entries ADD COLUMN blocked INTEGER NOT NULL DEFAULT 0");
|
|
15126
|
+
}
|
|
15108
15127
|
}
|
|
15109
15128
|
];
|
|
15110
15129
|
var MemoryDB = class {
|
|
@@ -15151,14 +15170,15 @@ var MemoryDB = class {
|
|
|
15151
15170
|
insert(entry) {
|
|
15152
15171
|
this.db.prepare(
|
|
15153
15172
|
`
|
|
15154
|
-
INSERT INTO memory_entries (id, target, content, position, char_length, access_count, last_accessed_at, created_at, updated_at)
|
|
15155
|
-
VALUES (@id, @target, @content, @position, @charLength, @accessCount, @lastAccessedAt, @createdAt, @updatedAt)
|
|
15173
|
+
INSERT INTO memory_entries (id, target, content, position, char_length, access_count, last_accessed_at, created_at, updated_at, blocked)
|
|
15174
|
+
VALUES (@id, @target, @content, @position, @charLength, @accessCount, @lastAccessedAt, @createdAt, @updatedAt, @blocked)
|
|
15156
15175
|
`
|
|
15157
15176
|
).run({
|
|
15158
15177
|
...entry,
|
|
15159
15178
|
createdAt: entry.createdAt.getTime(),
|
|
15160
15179
|
updatedAt: entry.updatedAt.getTime(),
|
|
15161
|
-
lastAccessedAt: entry.lastAccessedAt.getTime()
|
|
15180
|
+
lastAccessedAt: entry.lastAccessedAt.getTime(),
|
|
15181
|
+
blocked: entry.blocked ? 1 : 0
|
|
15162
15182
|
});
|
|
15163
15183
|
if (entry.position >= this.nextPosition[entry.target]) {
|
|
15164
15184
|
this.nextPosition[entry.target] = entry.position + 1;
|
|
@@ -15196,11 +15216,12 @@ var MemoryDB = class {
|
|
|
15196
15216
|
const existing = this.db.prepare("SELECT rowid FROM memory_entries WHERE target = ? AND content = ?").get(target, oldContent);
|
|
15197
15217
|
if (!existing) return;
|
|
15198
15218
|
this.db.prepare(
|
|
15199
|
-
"UPDATE memory_entries SET content = @content, char_length = @charLength, updated_at = @updatedAt WHERE rowid = @rowid"
|
|
15219
|
+
"UPDATE memory_entries SET content = @content, char_length = @charLength, updated_at = @updatedAt, blocked = @blocked WHERE rowid = @rowid"
|
|
15200
15220
|
).run({
|
|
15201
15221
|
content: newEntry.content,
|
|
15202
15222
|
charLength: newEntry.charLength,
|
|
15203
15223
|
updatedAt: newEntry.updatedAt.getTime(),
|
|
15224
|
+
blocked: newEntry.blocked ? 1 : 0,
|
|
15204
15225
|
rowid: existing.rowid
|
|
15205
15226
|
});
|
|
15206
15227
|
this.unsyncFts(existing.rowid);
|
|
@@ -15212,6 +15233,9 @@ var MemoryDB = class {
|
|
|
15212
15233
|
this.db.prepare("DELETE FROM memory_entries WHERE rowid = ?").run(existing.rowid);
|
|
15213
15234
|
this.unsyncFts(existing.rowid);
|
|
15214
15235
|
}
|
|
15236
|
+
setBlocked(id, blocked) {
|
|
15237
|
+
this.db.prepare("UPDATE memory_entries SET blocked = @blocked WHERE id = @id").run({ id, blocked: blocked ? 1 : 0 });
|
|
15238
|
+
}
|
|
15215
15239
|
updatePosition(id, position) {
|
|
15216
15240
|
this.db.prepare("UPDATE memory_entries SET position = @position WHERE id = @id").run({
|
|
15217
15241
|
id,
|
|
@@ -15280,7 +15304,8 @@ var MemoryDB = class {
|
|
|
15280
15304
|
createdAt: new Date(row["created_at"]),
|
|
15281
15305
|
updatedAt: new Date(row["updated_at"]),
|
|
15282
15306
|
accessCount: row["access_count"],
|
|
15283
|
-
lastAccessedAt: new Date(row["last_accessed_at"] ?? 0)
|
|
15307
|
+
lastAccessedAt: new Date(row["last_accessed_at"] ?? 0),
|
|
15308
|
+
blocked: Number(row["blocked"] ?? 0) !== 0
|
|
15284
15309
|
};
|
|
15285
15310
|
}
|
|
15286
15311
|
};
|
|
@@ -15298,6 +15323,7 @@ var MEM_DIR = join(homedir(), ".epoch", "memories");
|
|
|
15298
15323
|
var ENTRY_DELIMITER = "\n\xA7 ";
|
|
15299
15324
|
var MAX_ENTRY_CHARS = 4e3;
|
|
15300
15325
|
var MAX_CONSOLIDATION_FAILURES_PER_TURN = 3;
|
|
15326
|
+
var QUOTA_WARN_PCT = 90;
|
|
15301
15327
|
var SHORT_ID_HEX = 6;
|
|
15302
15328
|
var INDEX_SUMMARY_CHARS = 80;
|
|
15303
15329
|
var INJECTION_PATTERNS = [
|
|
@@ -15309,6 +15335,9 @@ var INJECTION_PATTERNS = [
|
|
|
15309
15335
|
{ pattern: /^assistant:/im, label: "role prefix" },
|
|
15310
15336
|
{ pattern: /^user:/im, label: "role prefix" }
|
|
15311
15337
|
];
|
|
15338
|
+
function injectionLabelOf(content) {
|
|
15339
|
+
return INJECTION_PATTERNS.find((p) => p.pattern.test(content))?.label;
|
|
15340
|
+
}
|
|
15312
15341
|
function contentKey(target, content) {
|
|
15313
15342
|
return `${target}\0${content}`;
|
|
15314
15343
|
}
|
|
@@ -15326,6 +15355,9 @@ var MemoryManager = class {
|
|
|
15326
15355
|
initialized = false;
|
|
15327
15356
|
consolidationFailures = 0;
|
|
15328
15357
|
reviewIssues = [];
|
|
15358
|
+
notices = [];
|
|
15359
|
+
notifiedBlocked = false;
|
|
15360
|
+
notifiedQuota = false;
|
|
15329
15361
|
constructor(dbPath, memDir, config) {
|
|
15330
15362
|
const dp = dbPath ?? DB_PATH;
|
|
15331
15363
|
const md = memDir ?? MEM_DIR;
|
|
@@ -15353,55 +15385,103 @@ var MemoryManager = class {
|
|
|
15353
15385
|
await this.flushToDisk();
|
|
15354
15386
|
}
|
|
15355
15387
|
async reloadFromDisk() {
|
|
15388
|
+
let blockedCount = 0;
|
|
15356
15389
|
for (const target of ["memory", "user"]) {
|
|
15357
15390
|
const file = target === "memory" ? "MEMORY.md" : "USER.md";
|
|
15358
15391
|
const fromDisk = this.readFile(join(this.memDir, file));
|
|
15359
15392
|
const deduped = [...new Set(fromDisk)];
|
|
15360
|
-
const
|
|
15361
|
-
|
|
15393
|
+
const classified = deduped.map((c) => this.classifyEntry(c));
|
|
15394
|
+
blockedCount += classified.filter((e) => e.blocked).length;
|
|
15395
|
+
this.syncTarget(target, classified);
|
|
15362
15396
|
}
|
|
15363
15397
|
this.assignIds();
|
|
15364
15398
|
this.snapshot = this.renderIndexBlock();
|
|
15399
|
+
if (blockedCount > 0 && !this.notifiedBlocked) {
|
|
15400
|
+
this.notifiedBlocked = true;
|
|
15401
|
+
this.notices.push({
|
|
15402
|
+
code: "memory-blocked",
|
|
15403
|
+
text: t("memory_review.blocked_notice", {
|
|
15404
|
+
count: blockedCount,
|
|
15405
|
+
path: join(this.memDir, "MEMORY.md")
|
|
15406
|
+
})
|
|
15407
|
+
});
|
|
15408
|
+
}
|
|
15409
|
+
this.checkQuota();
|
|
15410
|
+
}
|
|
15411
|
+
blockedPlaceholder(content) {
|
|
15412
|
+
return t("memory_review.blocked_placeholder", {
|
|
15413
|
+
pattern: injectionLabelOf(content) ?? "unknown"
|
|
15414
|
+
});
|
|
15415
|
+
}
|
|
15416
|
+
refuseInjection(label) {
|
|
15417
|
+
this.reviewIssues.push({
|
|
15418
|
+
type: "injection",
|
|
15419
|
+
severity: "high",
|
|
15420
|
+
message: t("memory_review.injection", { pattern: label }),
|
|
15421
|
+
suggestion: t("memory_review.injection_suggestion")
|
|
15422
|
+
});
|
|
15423
|
+
return {
|
|
15424
|
+
success: false,
|
|
15425
|
+
done: true,
|
|
15426
|
+
error: t("memory_review.write_blocked", { pattern: label })
|
|
15427
|
+
};
|
|
15428
|
+
}
|
|
15429
|
+
takeNotices() {
|
|
15430
|
+
const out = this.notices;
|
|
15431
|
+
this.notices = [];
|
|
15432
|
+
return out;
|
|
15433
|
+
}
|
|
15434
|
+
checkQuota() {
|
|
15435
|
+
if (this.notifiedQuota) return;
|
|
15436
|
+
const b = this.getBudget().memory;
|
|
15437
|
+
if (b.percent < QUOTA_WARN_PCT) return;
|
|
15438
|
+
this.notifiedQuota = true;
|
|
15439
|
+
this.notices.push({
|
|
15440
|
+
code: "memory-quota",
|
|
15441
|
+
text: t("memory_review.quota", { percent: b.percent, current: b.current, limit: b.limit })
|
|
15442
|
+
});
|
|
15365
15443
|
}
|
|
15366
15444
|
assignIds() {
|
|
15367
15445
|
this.ids.clear();
|
|
15368
15446
|
this.idByContent.clear();
|
|
15369
15447
|
for (const target of ["memory", "user"]) {
|
|
15370
15448
|
const prefix = target === "memory" ? "m" : "u";
|
|
15371
|
-
for (const
|
|
15372
|
-
const hash = createHash("sha256").update(content).digest("hex");
|
|
15449
|
+
for (const entry of this.db.getAll(target)) {
|
|
15450
|
+
const hash = createHash("sha256").update(entry.content).digest("hex");
|
|
15373
15451
|
let id = `${prefix}:${hash.slice(0, SHORT_ID_HEX)}`;
|
|
15374
15452
|
for (let len = SHORT_ID_HEX + 4; this.ids.has(id) && len <= hash.length; len += 4) {
|
|
15375
15453
|
id = `${prefix}:${hash.slice(0, len)}`;
|
|
15376
15454
|
}
|
|
15377
|
-
this.ids.set(id, { target, content });
|
|
15378
|
-
this.idByContent.set(contentKey(target, content), id);
|
|
15455
|
+
this.ids.set(id, { target, content: entry.content, blocked: entry.blocked });
|
|
15456
|
+
this.idByContent.set(contentKey(target, entry.content), id);
|
|
15379
15457
|
}
|
|
15380
15458
|
}
|
|
15381
15459
|
}
|
|
15382
15460
|
syncTarget(target, desired) {
|
|
15383
15461
|
const existing = new Map(this.db.getAll(target).map((e) => [e.content, e]));
|
|
15384
|
-
const desiredSet = new Set(desired);
|
|
15462
|
+
const desiredSet = new Set(desired.map((d) => d.content));
|
|
15385
15463
|
for (const [content, entry] of existing) {
|
|
15386
15464
|
if (!desiredSet.has(content)) this.db.removeById(entry.id);
|
|
15387
15465
|
}
|
|
15388
|
-
for (const [i,
|
|
15389
|
-
const prev = existing.get(content);
|
|
15466
|
+
for (const [i, item] of desired.entries()) {
|
|
15467
|
+
const prev = existing.get(item.content);
|
|
15390
15468
|
if (prev) {
|
|
15391
15469
|
if (prev.position !== i) this.db.updatePosition(prev.id, i);
|
|
15470
|
+
if (prev.blocked !== item.blocked) this.db.setBlocked(prev.id, item.blocked);
|
|
15392
15471
|
continue;
|
|
15393
15472
|
}
|
|
15394
15473
|
const now = /* @__PURE__ */ new Date();
|
|
15395
15474
|
this.db.insert({
|
|
15396
15475
|
id: randomUUID(),
|
|
15397
15476
|
target,
|
|
15398
|
-
content,
|
|
15477
|
+
content: item.content,
|
|
15399
15478
|
position: i,
|
|
15400
|
-
charLength: content.length,
|
|
15479
|
+
charLength: item.content.length,
|
|
15401
15480
|
accessCount: 0,
|
|
15402
15481
|
lastAccessedAt: now,
|
|
15403
15482
|
createdAt: now,
|
|
15404
|
-
updatedAt: now
|
|
15483
|
+
updatedAt: now,
|
|
15484
|
+
blocked: item.blocked
|
|
15405
15485
|
});
|
|
15406
15486
|
}
|
|
15407
15487
|
}
|
|
@@ -15420,7 +15500,7 @@ var MemoryManager = class {
|
|
|
15420
15500
|
for (const r of results) this.db.markAccessed(r.id);
|
|
15421
15501
|
return results.map((r) => ({
|
|
15422
15502
|
id: this.idByContent.get(contentKey(r.target, r.content)) ?? r.id,
|
|
15423
|
-
content: r.content,
|
|
15503
|
+
content: r.blocked ? this.blockedPlaceholder(r.content) : r.content,
|
|
15424
15504
|
target: r.target,
|
|
15425
15505
|
score: r.score
|
|
15426
15506
|
}));
|
|
@@ -15438,22 +15518,27 @@ var MemoryManager = class {
|
|
|
15438
15518
|
missing.push(id);
|
|
15439
15519
|
continue;
|
|
15440
15520
|
}
|
|
15441
|
-
found.push({
|
|
15521
|
+
found.push({
|
|
15522
|
+
id,
|
|
15523
|
+
target: hit.target,
|
|
15524
|
+
content: hit.blocked ? this.blockedPlaceholder(hit.content) : hit.content
|
|
15525
|
+
});
|
|
15442
15526
|
const entry = this.db.findByContent(hit.target, hit.content);
|
|
15443
15527
|
if (entry) this.db.markAccessed(entry.id);
|
|
15444
15528
|
}
|
|
15445
15529
|
return { found, missing };
|
|
15446
15530
|
}
|
|
15447
15531
|
getAllEntries() {
|
|
15448
|
-
return [
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
];
|
|
15532
|
+
return ["memory", "user"].flatMap(
|
|
15533
|
+
(target) => this.db.getAll(target).map((e) => ({ content: e.content, target, blocked: e.blocked }))
|
|
15534
|
+
);
|
|
15452
15535
|
}
|
|
15453
15536
|
async semanticSearch(query, limit) {
|
|
15454
15537
|
return this.search(query, limit);
|
|
15455
15538
|
}
|
|
15456
15539
|
async add(target, content) {
|
|
15540
|
+
const label = injectionLabelOf(content);
|
|
15541
|
+
if (label !== void 0) return this.refuseInjection(label);
|
|
15457
15542
|
const budget = this.getBudget()[target];
|
|
15458
15543
|
if (budget.current + content.length > budget.limit) {
|
|
15459
15544
|
this.consolidationFailures++;
|
|
@@ -15487,7 +15572,8 @@ var MemoryManager = class {
|
|
|
15487
15572
|
accessCount: 0,
|
|
15488
15573
|
lastAccessedAt: /* @__PURE__ */ new Date(),
|
|
15489
15574
|
createdAt: /* @__PURE__ */ new Date(),
|
|
15490
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
15575
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
15576
|
+
blocked: false
|
|
15491
15577
|
};
|
|
15492
15578
|
this.db.insert(entry);
|
|
15493
15579
|
this.consolidationFailures = 0;
|
|
@@ -15499,6 +15585,8 @@ var MemoryManager = class {
|
|
|
15499
15585
|
if (!existing) {
|
|
15500
15586
|
return { success: false, done: true, error: this.notFoundHint(target, oldText) };
|
|
15501
15587
|
}
|
|
15588
|
+
const label = injectionLabelOf(content);
|
|
15589
|
+
if (label !== void 0) return this.refuseInjection(label);
|
|
15502
15590
|
const budget = this.getBudget()[target];
|
|
15503
15591
|
const delta = content.length - existing.charLength;
|
|
15504
15592
|
if (budget.current + delta > budget.limit) {
|
|
@@ -15516,7 +15604,8 @@ var MemoryManager = class {
|
|
|
15516
15604
|
...existing,
|
|
15517
15605
|
content,
|
|
15518
15606
|
charLength: content.length,
|
|
15519
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
15607
|
+
updatedAt: /* @__PURE__ */ new Date(),
|
|
15608
|
+
blocked: false
|
|
15520
15609
|
});
|
|
15521
15610
|
this.consolidationFailures = 0;
|
|
15522
15611
|
await this.flushToDisk();
|
|
@@ -15580,31 +15669,42 @@ var MemoryManager = class {
|
|
|
15580
15669
|
if (current) entries2.push(current.join("\n").trim());
|
|
15581
15670
|
return entries2.filter((e) => e.length > 0);
|
|
15582
15671
|
}
|
|
15583
|
-
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
|
|
15593
|
-
}
|
|
15672
|
+
classifyEntry(content) {
|
|
15673
|
+
const label = injectionLabelOf(content);
|
|
15674
|
+
if (label !== void 0) {
|
|
15675
|
+
this.reviewIssues.push({
|
|
15676
|
+
type: "injection",
|
|
15677
|
+
severity: "high",
|
|
15678
|
+
message: t("memory_review.injection", { pattern: label }),
|
|
15679
|
+
suggestion: t("memory_review.injection_suggestion")
|
|
15680
|
+
});
|
|
15681
|
+
return { content, blocked: true };
|
|
15594
15682
|
}
|
|
15595
15683
|
if (countCodePoints(content) > MAX_ENTRY_CHARS) {
|
|
15596
|
-
return
|
|
15684
|
+
return {
|
|
15685
|
+
content: headCodePoints(content, MAX_ENTRY_CHARS) + " \u2026[\u6761\u76EE\u8FC7\u957F\u5DF2\u622A\u65AD]",
|
|
15686
|
+
blocked: false
|
|
15687
|
+
};
|
|
15597
15688
|
}
|
|
15598
|
-
return content;
|
|
15689
|
+
return { content, blocked: false };
|
|
15599
15690
|
}
|
|
15600
15691
|
indexEntries(target) {
|
|
15601
15692
|
const out = [];
|
|
15602
|
-
for (const
|
|
15603
|
-
const id = this.idByContent.get(contentKey(target, content));
|
|
15693
|
+
for (const entry of this.db.getAll(target)) {
|
|
15694
|
+
const id = this.idByContent.get(contentKey(target, entry.content));
|
|
15604
15695
|
if (!id) continue;
|
|
15605
|
-
|
|
15696
|
+
if (entry.blocked) {
|
|
15697
|
+
out.push({
|
|
15698
|
+
id,
|
|
15699
|
+
target,
|
|
15700
|
+
summary: this.blockedPlaceholder(entry.content),
|
|
15701
|
+
charLength: entry.content.length
|
|
15702
|
+
});
|
|
15703
|
+
continue;
|
|
15704
|
+
}
|
|
15705
|
+
const firstLine4 = (entry.content.split("\n")[0] ?? "").trim();
|
|
15606
15706
|
const summary = countCodePoints(firstLine4) > INDEX_SUMMARY_CHARS ? `${headCodePoints(firstLine4, INDEX_SUMMARY_CHARS)}\u2026` : firstLine4;
|
|
15607
|
-
out.push({ id, target, summary, charLength: content.length });
|
|
15707
|
+
out.push({ id, target, summary, charLength: entry.content.length });
|
|
15608
15708
|
}
|
|
15609
15709
|
return out;
|
|
15610
15710
|
}
|
|
@@ -15696,148 +15796,6 @@ var MemoryManager = class {
|
|
|
15696
15796
|
].join("\n");
|
|
15697
15797
|
}
|
|
15698
15798
|
};
|
|
15699
|
-
var DEFAULT_INTERVAL = 5 * 60 * 1e3;
|
|
15700
|
-
var QUOTA_WARN_PCT = 90;
|
|
15701
|
-
var MemoryReviewer = class {
|
|
15702
|
-
manager;
|
|
15703
|
-
timer = null;
|
|
15704
|
-
issues = [];
|
|
15705
|
-
interval;
|
|
15706
|
-
constructor(manager, interval = DEFAULT_INTERVAL) {
|
|
15707
|
-
this.manager = manager;
|
|
15708
|
-
this.interval = interval;
|
|
15709
|
-
}
|
|
15710
|
-
start() {
|
|
15711
|
-
if (this.timer) return;
|
|
15712
|
-
this.scanForIssues().catch(() => {
|
|
15713
|
-
});
|
|
15714
|
-
this.timer = setInterval(() => {
|
|
15715
|
-
this.scanForIssues().catch(() => {
|
|
15716
|
-
});
|
|
15717
|
-
}, this.interval);
|
|
15718
|
-
}
|
|
15719
|
-
stop() {
|
|
15720
|
-
if (this.timer) {
|
|
15721
|
-
clearInterval(this.timer);
|
|
15722
|
-
this.timer = null;
|
|
15723
|
-
}
|
|
15724
|
-
}
|
|
15725
|
-
getIssues() {
|
|
15726
|
-
return [...this.issues];
|
|
15727
|
-
}
|
|
15728
|
-
clearIssues() {
|
|
15729
|
-
this.issues = [];
|
|
15730
|
-
}
|
|
15731
|
-
async scanForIssues() {
|
|
15732
|
-
const newIssues = [];
|
|
15733
|
-
const dups = await this.checkDuplicates();
|
|
15734
|
-
newIssues.push(...dups);
|
|
15735
|
-
const contras = await this.checkContradictions();
|
|
15736
|
-
newIssues.push(...contras);
|
|
15737
|
-
const warns = this.checkQuota();
|
|
15738
|
-
newIssues.push(...warns);
|
|
15739
|
-
this.issues = newIssues;
|
|
15740
|
-
return newIssues;
|
|
15741
|
-
}
|
|
15742
|
-
async checkDuplicates() {
|
|
15743
|
-
const issues = [];
|
|
15744
|
-
const allEntries = this.manager.getAllEntries();
|
|
15745
|
-
const seen = /* @__PURE__ */ new Set();
|
|
15746
|
-
for (let i = 0; i < allEntries.length; i++) {
|
|
15747
|
-
if (seen.has(i)) continue;
|
|
15748
|
-
const entryI = allEntries[i];
|
|
15749
|
-
if (!entryI) continue;
|
|
15750
|
-
for (let j = i + 1; j < allEntries.length; j++) {
|
|
15751
|
-
if (seen.has(j)) continue;
|
|
15752
|
-
const entryJ = allEntries[j];
|
|
15753
|
-
if (!entryJ) continue;
|
|
15754
|
-
const sim = textSimilarity(entryI.content, entryJ.content);
|
|
15755
|
-
if (sim > 0.7) {
|
|
15756
|
-
seen.add(i);
|
|
15757
|
-
seen.add(j);
|
|
15758
|
-
issues.push({
|
|
15759
|
-
type: "duplicate",
|
|
15760
|
-
severity: sim > 0.95 ? "high" : "medium",
|
|
15761
|
-
message: t("memory_review.duplicate", { percent: (sim * 100).toFixed(0) }),
|
|
15762
|
-
entries: [entryI.content, entryJ.content],
|
|
15763
|
-
suggestion: t("memory_review.duplicate_suggestion")
|
|
15764
|
-
});
|
|
15765
|
-
}
|
|
15766
|
-
}
|
|
15767
|
-
}
|
|
15768
|
-
return issues;
|
|
15769
|
-
}
|
|
15770
|
-
async checkContradictions() {
|
|
15771
|
-
const issues = [];
|
|
15772
|
-
const entries2 = this.manager.getAllEntries();
|
|
15773
|
-
const contents = entries2.map((e) => e.content.toLowerCase());
|
|
15774
|
-
const patterns = [
|
|
15775
|
-
{
|
|
15776
|
-
a: /pnpm|yarn|npm/,
|
|
15777
|
-
b: /pnpm|yarn|npm/,
|
|
15778
|
-
label: t("memory_review.label_package_manager")
|
|
15779
|
-
},
|
|
15780
|
-
{
|
|
15781
|
-
a: /typescript|javascript|ts|js/,
|
|
15782
|
-
b: /typescript|javascript|ts|js/,
|
|
15783
|
-
label: t("memory_review.label_language")
|
|
15784
|
-
},
|
|
15785
|
-
{
|
|
15786
|
-
a: /node\s*(18|20|22)/,
|
|
15787
|
-
b: /node\s*(18|20|22)/,
|
|
15788
|
-
label: t("memory_review.label_node_version")
|
|
15789
|
-
}
|
|
15790
|
-
];
|
|
15791
|
-
for (let i = 0; i < contents.length; i++) {
|
|
15792
|
-
for (let j = i + 1; j < contents.length; j++) {
|
|
15793
|
-
const contI = contents[i];
|
|
15794
|
-
const contJ = contents[j];
|
|
15795
|
-
if (!contI || !contJ) continue;
|
|
15796
|
-
for (const { a, b, label } of patterns) {
|
|
15797
|
-
const ma = a.exec(contI), mb = b.exec(contJ);
|
|
15798
|
-
if (ma && mb && ma[0] !== mb[0]) {
|
|
15799
|
-
issues.push({
|
|
15800
|
-
type: "contradiction",
|
|
15801
|
-
severity: "medium",
|
|
15802
|
-
message: t("memory_review.contradiction", { label }),
|
|
15803
|
-
entries: [entries2[i]?.content ?? "", entries2[j]?.content ?? ""],
|
|
15804
|
-
suggestion: t("memory_review.contradiction_suggestion", { label })
|
|
15805
|
-
});
|
|
15806
|
-
}
|
|
15807
|
-
}
|
|
15808
|
-
}
|
|
15809
|
-
}
|
|
15810
|
-
return issues;
|
|
15811
|
-
}
|
|
15812
|
-
checkQuota() {
|
|
15813
|
-
const budget = this.manager.getBudget();
|
|
15814
|
-
const issues = [];
|
|
15815
|
-
if (budget.memory.percent >= QUOTA_WARN_PCT) {
|
|
15816
|
-
issues.push({
|
|
15817
|
-
type: "quota_warning",
|
|
15818
|
-
severity: budget.memory.percent >= 98 ? "high" : "medium",
|
|
15819
|
-
message: t("memory_review.quota", {
|
|
15820
|
-
percent: budget.memory.percent,
|
|
15821
|
-
current: budget.memory.current,
|
|
15822
|
-
limit: budget.memory.limit
|
|
15823
|
-
}),
|
|
15824
|
-
suggestion: t("memory_review.quota_suggestion")
|
|
15825
|
-
});
|
|
15826
|
-
}
|
|
15827
|
-
return issues;
|
|
15828
|
-
}
|
|
15829
|
-
};
|
|
15830
|
-
function textSimilarity(a, b) {
|
|
15831
|
-
const wordsA = new Set(a.toLowerCase().split(/\s+/));
|
|
15832
|
-
const wordsB = new Set(b.toLowerCase().split(/\s+/));
|
|
15833
|
-
if (wordsA.size === 0 && wordsB.size === 0) return 1;
|
|
15834
|
-
let intersection = 0;
|
|
15835
|
-
for (const w of wordsA) {
|
|
15836
|
-
if (wordsB.has(w)) intersection++;
|
|
15837
|
-
}
|
|
15838
|
-
const union = /* @__PURE__ */ new Set([...wordsA, ...wordsB]);
|
|
15839
|
-
return intersection / union.size;
|
|
15840
|
-
}
|
|
15841
15799
|
var ATTACHMENT_RETENTION_DEFAULTS = {
|
|
15842
15800
|
maxAgeDays: 7,
|
|
15843
15801
|
maxTotalBytes: ATTACHMENT_MAX_TOTAL_BYTES
|
|
@@ -17144,7 +17102,7 @@ function checkFtsHealth(db) {
|
|
|
17144
17102
|
messages,
|
|
17145
17103
|
tables,
|
|
17146
17104
|
missingTriggers,
|
|
17147
|
-
healthy: missingTriggers.length === 0 && tables.every((
|
|
17105
|
+
healthy: missingTriggers.length === 0 && tables.every((t80) => t80.error === null && t80.drift === null && t80.rows === messages),
|
|
17148
17106
|
indexBytes: indexBytesOf(db),
|
|
17149
17107
|
space: spaceOf(db)
|
|
17150
17108
|
};
|
|
@@ -18488,11 +18446,11 @@ var ApprovalCache = class {
|
|
|
18488
18446
|
return !rel.startsWith("..") && !isAbsolute(rel);
|
|
18489
18447
|
}
|
|
18490
18448
|
normalizeTarget(target) {
|
|
18491
|
-
const
|
|
18492
|
-
if (!
|
|
18493
|
-
const unix =
|
|
18449
|
+
const t80 = target.trim();
|
|
18450
|
+
if (!t80) return "";
|
|
18451
|
+
const unix = t80.replace(/\\/g, "/");
|
|
18494
18452
|
if (unix.startsWith("/") || /^[A-Za-z]:\//.test(unix)) return resolve(unix);
|
|
18495
|
-
return
|
|
18453
|
+
return t80;
|
|
18496
18454
|
}
|
|
18497
18455
|
load() {
|
|
18498
18456
|
try {
|
|
@@ -18595,9 +18553,9 @@ function createSharedPermissionState(cache) {
|
|
|
18595
18553
|
};
|
|
18596
18554
|
}
|
|
18597
18555
|
function cacheKeyFor(raw) {
|
|
18598
|
-
const
|
|
18599
|
-
if (!
|
|
18600
|
-
return
|
|
18556
|
+
const t80 = raw.trim();
|
|
18557
|
+
if (!t80) return null;
|
|
18558
|
+
return t80.slice(0, 500);
|
|
18601
18559
|
}
|
|
18602
18560
|
// src/permission/manager.ts
|
|
18603
18561
|
var log3 = createLogger("permission");
|
|
@@ -22044,7 +22002,8 @@ function loadOne(mdFile, catPath, category, dirName, spec, skills, issues) {
|
|
|
22044
22002
|
}
|
|
22045
22003
|
const parsed = parseSkillFrontmatter(raw, label);
|
|
22046
22004
|
issues.push(...parsed.issues);
|
|
22047
|
-
const
|
|
22005
|
+
const declared = parsed.fm.name?.trim();
|
|
22006
|
+
const base = declared ? declared : dirName;
|
|
22048
22007
|
const name = spec.prefix ? `${spec.prefix}:${base}` : base;
|
|
22049
22008
|
const previous = skills.get(name);
|
|
22050
22009
|
if (previous && previous.scope !== scope) {
|
|
@@ -22094,6 +22053,18 @@ function normalizeDirs(input) {
|
|
|
22094
22053
|
}
|
|
22095
22054
|
return dirs.length > 0 ? dirs : [{ dir: SKILLS_DIR, source: "user" }];
|
|
22096
22055
|
}
|
|
22056
|
+
function realpathOfDeepestExisting(target) {
|
|
22057
|
+
const tail = [];
|
|
22058
|
+
let cur = target;
|
|
22059
|
+
while (!existsSync(cur)) {
|
|
22060
|
+
const parent = dirname(cur);
|
|
22061
|
+
if (parent === cur) return target;
|
|
22062
|
+
tail.unshift(basename(cur));
|
|
22063
|
+
cur = parent;
|
|
22064
|
+
}
|
|
22065
|
+
const real = realpathSync(cur);
|
|
22066
|
+
return tail.length === 0 ? real : join(real, ...tail);
|
|
22067
|
+
}
|
|
22097
22068
|
var SkillSystem = class {
|
|
22098
22069
|
dirs;
|
|
22099
22070
|
skillsDir;
|
|
@@ -22186,12 +22157,16 @@ var SkillSystem = class {
|
|
|
22186
22157
|
}
|
|
22187
22158
|
async create(name, content, category = "general") {
|
|
22188
22159
|
this.scanIfNeeded();
|
|
22189
|
-
|
|
22190
|
-
const
|
|
22160
|
+
const declared = parseSkillFrontmatter(content, name).fm.name?.trim();
|
|
22161
|
+
const indexName = declared ? declared : name;
|
|
22162
|
+
if (this.skills.has(indexName)) throw new Error(`Skill "${indexName}" already exists`);
|
|
22163
|
+
const dir = join(this.skillsDir, category, indexName);
|
|
22191
22164
|
const base = resolve(this.skillsDir);
|
|
22192
22165
|
const resolved = resolve(dir);
|
|
22193
22166
|
if (resolved === base || !resolved.startsWith(base + sep)) {
|
|
22194
|
-
throw new Error(
|
|
22167
|
+
throw new Error(
|
|
22168
|
+
`Skill name or category escapes the skills directory: ${category}/${indexName}`
|
|
22169
|
+
);
|
|
22195
22170
|
}
|
|
22196
22171
|
mkdirSync(dir, { recursive: true });
|
|
22197
22172
|
writeFileSync(join(dir, "SKILL.md"), content, "utf-8");
|
|
@@ -22205,7 +22180,7 @@ var SkillSystem = class {
|
|
|
22205
22180
|
}
|
|
22206
22181
|
async patch(name, oldString, newString, filePath) {
|
|
22207
22182
|
const skill = this.requireWritable(name);
|
|
22208
|
-
const targetPath =
|
|
22183
|
+
const targetPath = this.resolveInsideSkill(skill.path, filePath ?? "SKILL.md");
|
|
22209
22184
|
const raw = readFileSync(targetPath, "utf-8");
|
|
22210
22185
|
if (!raw.includes(oldString)) throw new Error("old_string not found");
|
|
22211
22186
|
writeFileSync(targetPath, raw.replace(oldString, newString), "utf-8");
|
|
@@ -22225,21 +22200,30 @@ var SkillSystem = class {
|
|
|
22225
22200
|
`filePath must be under references/templates/scripts/assets, got: ${filePath}`
|
|
22226
22201
|
);
|
|
22227
22202
|
}
|
|
22228
|
-
const resolved =
|
|
22229
|
-
const baseDir = resolve(skill.path);
|
|
22230
|
-
if (resolved !== baseDir && !resolved.startsWith(baseDir + sep)) {
|
|
22231
|
-
throw new Error("Path traversal denied");
|
|
22232
|
-
}
|
|
22203
|
+
const resolved = this.resolveInsideSkill(skill.path, filePath);
|
|
22233
22204
|
mkdirSync(dirname(resolved), { recursive: true });
|
|
22234
22205
|
writeFileSync(resolved, content, "utf-8");
|
|
22235
22206
|
this.invalidateCache();
|
|
22236
22207
|
}
|
|
22237
22208
|
async removeFile(name, filePath) {
|
|
22238
22209
|
const skill = this.requireWritable(name);
|
|
22239
|
-
const resolved =
|
|
22210
|
+
const resolved = this.resolveInsideSkill(skill.path, filePath);
|
|
22240
22211
|
rmSync(resolved);
|
|
22241
22212
|
this.invalidateCache();
|
|
22242
22213
|
}
|
|
22214
|
+
resolveInsideSkill(skillPath, relPath) {
|
|
22215
|
+
const base = resolve(skillPath);
|
|
22216
|
+
const resolved = resolve(join(skillPath, relPath));
|
|
22217
|
+
if (resolved !== base && !resolved.startsWith(base + sep)) {
|
|
22218
|
+
throw new Error("Path traversal denied");
|
|
22219
|
+
}
|
|
22220
|
+
const realBase = realpathSync(base);
|
|
22221
|
+
const realTarget = realpathOfDeepestExisting(resolved);
|
|
22222
|
+
if (realTarget !== realBase && !realTarget.startsWith(realBase + sep)) {
|
|
22223
|
+
throw new Error("Path traversal denied");
|
|
22224
|
+
}
|
|
22225
|
+
return resolved;
|
|
22226
|
+
}
|
|
22243
22227
|
requireWritable(name) {
|
|
22244
22228
|
this.scanIfNeeded();
|
|
22245
22229
|
const skill = this.skills.get(name);
|
|
@@ -22648,12 +22632,21 @@ var SkillLearner = class {
|
|
|
22648
22632
|
if (!parsed.name || !parsed.content) {
|
|
22649
22633
|
return { created: false, reason: "missing-name-or-content" };
|
|
22650
22634
|
}
|
|
22651
|
-
|
|
22635
|
+
const { fm } = parseSkillFrontmatter(parsed.content, parsed.name);
|
|
22636
|
+
const declared = fm.name?.trim();
|
|
22637
|
+
if (!declared) {
|
|
22652
22638
|
return { created: false, reason: "missing-frontmatter" };
|
|
22653
22639
|
}
|
|
22640
|
+
if ((fm.description ?? "").trim() === "") {
|
|
22641
|
+
return { created: false, reason: "missing-description" };
|
|
22642
|
+
}
|
|
22643
|
+
const category = parsed.category?.trim() || "general";
|
|
22644
|
+
if (skillSegmentIssue(declared) !== void 0 || skillSegmentIssue(category) !== void 0) {
|
|
22645
|
+
return { created: false, reason: "invalid-name" };
|
|
22646
|
+
}
|
|
22654
22647
|
try {
|
|
22655
|
-
await this.skillSystem.create(
|
|
22656
|
-
return { created: true, skillName:
|
|
22648
|
+
await this.skillSystem.create(declared, parsed.content, category);
|
|
22649
|
+
return { created: true, skillName: declared };
|
|
22657
22650
|
} catch (err) {
|
|
22658
22651
|
return { created: false, reason: "create-failed", error: messageOf2(err) };
|
|
22659
22652
|
}
|
|
@@ -23804,4 +23797,4 @@ function trunc(stdout, stderr) {
|
|
|
23804
23797
|
* `--tree` 的命令帮助里,让用户自己知道 `--tree` 意味着什么。
|
|
23805
23798
|
*/
|
|
23806
23799
|
|
|
23807
|
-
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,
|
|
23800
|
+
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, 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 };
|