@lmzhen/dsh-evolution-skill-discovery 0.30.43 → 0.31.1
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/lib/domain-description-3MIOYgVH.js +2105 -0
- package/lib/index.js +13 -1714
- package/lib/main-entry.js +360 -0
- package/lib/search-entry.js +88 -0
- package/lib/tool-CvUTwKvW.js +446 -0
- package/lib/types/assignment-queue.d.ts +1 -1
- package/lib/types/catalog-codec.d.ts +35 -0
- package/lib/types/description-refresh.d.ts +8 -0
- package/lib/types/domain-bootstrap.d.ts +24 -6
- package/lib/types/domain-generation-coordinator.d.ts +33 -0
- package/lib/types/domain-generation-llm.d.ts +56 -0
- package/lib/types/domain-policy-store.d.ts +24 -0
- package/lib/types/domain-projection.d.ts +1 -6
- package/lib/types/generation-composition.d.ts +38 -0
- package/lib/types/generation-input.d.ts +9 -0
- package/lib/types/index.d.ts +12 -41
- package/lib/types/main-entry.d.ts +36 -0
- package/lib/types/plugin.d.ts +0 -6
- package/lib/types/projection-adapter.d.ts +60 -0
- package/lib/types/projection-journal.d.ts +32 -0
- package/lib/types/projection-runtime.d.ts +63 -0
- package/lib/types/projection.d.ts +1 -2
- package/lib/types/search-entry.d.ts +19 -0
- package/lib/types/skill-index.d.ts +41 -0
- package/lib/types/tool.d.ts +3 -3
- package/lib/types/view-snapshot-store.d.ts +30 -0
- package/lib/types/view-state.d.ts +59 -0
- package/package.json +16 -9
- package/lib/types/shadow-evidence.d.ts +0 -22
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { O as buildDomainGenerationPrompt, Z as ProjectionJournal, _ as buildGenerationRequest, c as AssignmentWorker, et as DomainMapFileStore, g as ViewSnapshotStore, k as ProjectionRuntime, l as JsonAssignmentQueue, o as installDiscoveryAwareness, ot as DomainGenerationCoordinator, r as renderDomainDescription, rt as DomainPolicyStore, s as installAssignmentSidecar, t as descriptionHashOf, u as DomainAssignmentService, v as resolveGenerationPort } from "./domain-description-3MIOYgVH.js";
|
|
2
|
+
import { _ as skillKeyOf, c as SkillSearchCache, d as SkillIndex, r as registerSkillSearchTool } from "./tool-CvUTwKvW.js";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { authorityFrom, evolutionIoAdapter, evolutionRoot, newSkillLibrary } from "@lmzhen/dsh-evolution-core";
|
|
6
|
+
//#region lib/types/description-refresh.js
|
|
7
|
+
function nextMapVersion(version) {
|
|
8
|
+
const numeric = Number(version);
|
|
9
|
+
return Number.isSafeInteger(numeric) && numeric >= 0 ? String(numeric + 1) : version + ".1";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Re-render stale domain descriptions from their definition fields.
|
|
13
|
+
* @param store - domain map store.
|
|
14
|
+
* @returns number of refreshed domains.
|
|
15
|
+
*/
|
|
16
|
+
async function refreshStaleDescriptions(store) {
|
|
17
|
+
const snapshot = await store.read();
|
|
18
|
+
const stale = snapshot.domains.filter((node) => node.descriptionStatus === "stale");
|
|
19
|
+
if (stale.length === 0) return 0;
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const domains = snapshot.domains.map((node) => node.descriptionStatus !== "stale" ? node : {
|
|
22
|
+
...node,
|
|
23
|
+
description: renderDomainDescription(node),
|
|
24
|
+
descriptionHash: descriptionHashOf(node, snapshot.domains.filter((child) => child.parentIds.includes(node.id))),
|
|
25
|
+
descriptionVersion: node.descriptionVersion + 1,
|
|
26
|
+
descriptionStatus: "fresh",
|
|
27
|
+
updatedAt: now
|
|
28
|
+
});
|
|
29
|
+
await store.commit(snapshot.mapVersion, {
|
|
30
|
+
mapVersion: nextMapVersion(snapshot.mapVersion),
|
|
31
|
+
domains,
|
|
32
|
+
edges: snapshot.edges
|
|
33
|
+
});
|
|
34
|
+
return stale.length;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region lib/types/main-entry.js
|
|
38
|
+
const name = "evolution-skill-discovery";
|
|
39
|
+
const inject = [
|
|
40
|
+
"skills",
|
|
41
|
+
"workingDirectory",
|
|
42
|
+
"tools",
|
|
43
|
+
"evolutionIo",
|
|
44
|
+
"systemPrompt"
|
|
45
|
+
];
|
|
46
|
+
var PlatformSource = class {
|
|
47
|
+
ctx;
|
|
48
|
+
library;
|
|
49
|
+
constructor(ctx, library) {
|
|
50
|
+
this.ctx = ctx;
|
|
51
|
+
this.library = library;
|
|
52
|
+
}
|
|
53
|
+
async snapshot(query) {
|
|
54
|
+
const snapshot = await this.ctx.skills.snapshot({
|
|
55
|
+
cwd: query.cwd,
|
|
56
|
+
...query.scope === void 0 ? {} : { scope: query.scope }
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
skills: snapshot.skills,
|
|
60
|
+
complete: snapshot.complete
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async managedSkillKeys() {
|
|
64
|
+
return new Set((await this.library.list()).filter((summary) => summary.managed).map((summary) => skillKeyOf({
|
|
65
|
+
provider: "dsh-evolution",
|
|
66
|
+
source: "user-dsh",
|
|
67
|
+
name: summary.name
|
|
68
|
+
})));
|
|
69
|
+
}
|
|
70
|
+
async protectedSkillKeys() {
|
|
71
|
+
return new Set((await this.library.list()).filter((summary) => summary.protectedBy !== null || summary.protectionUnknown).map((summary) => skillKeyOf({
|
|
72
|
+
provider: "dsh-evolution",
|
|
73
|
+
source: "user-dsh",
|
|
74
|
+
name: summary.name
|
|
75
|
+
})));
|
|
76
|
+
}
|
|
77
|
+
async pinnedSkillKeys() {
|
|
78
|
+
return new Set((await this.library.list()).filter((summary) => summary.protectedBy === "pinned").map((summary) => skillKeyOf({
|
|
79
|
+
provider: "dsh-evolution",
|
|
80
|
+
source: "user-dsh",
|
|
81
|
+
name: summary.name
|
|
82
|
+
})));
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
function searchUnavailable() {
|
|
86
|
+
return {
|
|
87
|
+
results: [],
|
|
88
|
+
truncated: false,
|
|
89
|
+
degraded: true,
|
|
90
|
+
hint: "Skill search is unavailable without a session working directory."
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Apply the full production discovery composition. */
|
|
94
|
+
function apply(ctx, config) {
|
|
95
|
+
if (typeof config.featureEpoch !== "string" || config.featureEpoch.length === 0) throw new Error("evolution-skill-discovery: featureEpoch is required");
|
|
96
|
+
const evolutionIo = ctx.evolutionIo;
|
|
97
|
+
const io = evolutionIoAdapter(() => evolutionIo.provider());
|
|
98
|
+
const source = new PlatformSource(ctx, newSkillLibrary({
|
|
99
|
+
config: {},
|
|
100
|
+
io,
|
|
101
|
+
ctx,
|
|
102
|
+
authority: authorityFrom({ origin: "foreground" })
|
|
103
|
+
}));
|
|
104
|
+
const index = new SkillIndex(source);
|
|
105
|
+
const workingDirectory = ctx.get("workingDirectory");
|
|
106
|
+
if (workingDirectory === void 0) throw new Error("evolution-skill-discovery: workingDirectory service is required");
|
|
107
|
+
const root = evolutionRoot();
|
|
108
|
+
let mode = config.mode ?? "off";
|
|
109
|
+
let generation = void 0;
|
|
110
|
+
if (mode !== "off") generation = resolveGenerationPort({
|
|
111
|
+
mode,
|
|
112
|
+
...ctx.get("llm") === void 0 ? {} : { llm: ctx.get("llm") },
|
|
113
|
+
provider: config.generationProvider ?? "deepseek-official",
|
|
114
|
+
model: config.generationModel ?? "deepseek-flash",
|
|
115
|
+
...config.generationTimeoutMs === void 0 ? {} : { timeoutMs: config.generationTimeoutMs },
|
|
116
|
+
...config.generationMaxTokens === void 0 ? {} : { maxTokens: config.generationMaxTokens },
|
|
117
|
+
...config.generationAttempts === void 0 ? {} : { attempts: config.generationAttempts }
|
|
118
|
+
});
|
|
119
|
+
const searchCache = new SkillSearchCache();
|
|
120
|
+
let searchHealthy = true;
|
|
121
|
+
const search = {
|
|
122
|
+
async allowedSkillKeys(agent, signal) {
|
|
123
|
+
if (mode === "off" || agent === void 0) return void 0;
|
|
124
|
+
const cwd = await workingDirectory.ensure(agent, signal);
|
|
125
|
+
const view = await index.read({
|
|
126
|
+
cwd,
|
|
127
|
+
scopeKey: String(agent.id),
|
|
128
|
+
scope: agent,
|
|
129
|
+
signal
|
|
130
|
+
});
|
|
131
|
+
let snapshot;
|
|
132
|
+
try {
|
|
133
|
+
snapshot = await map.read();
|
|
134
|
+
} catch {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const known = new Set(snapshot.domains.map((node) => node.id));
|
|
138
|
+
const effective = (await policyFor(cwd)).resolve(known);
|
|
139
|
+
const blocked = new Set(snapshot.edges.filter((edge) => edge.status === "active" && effective.disabled.has(edge.domainId)).map((edge) => edge.skillKey));
|
|
140
|
+
return new Set(view.rows.filter((row) => row.modelInvocable && !blocked.has(row.skillKey)).map((row) => row.skillKey));
|
|
141
|
+
},
|
|
142
|
+
async search(query, options, agent, signal) {
|
|
143
|
+
if (agent === void 0) return searchUnavailable();
|
|
144
|
+
const cwd = await workingDirectory.ensure(agent, signal);
|
|
145
|
+
const view = await index.read({
|
|
146
|
+
cwd,
|
|
147
|
+
scopeKey: String(agent.id),
|
|
148
|
+
scope: agent,
|
|
149
|
+
signal
|
|
150
|
+
});
|
|
151
|
+
const viewPolicy = mode === "off" ? void 0 : await policyFor(cwd);
|
|
152
|
+
const cached = await searchCache.get({
|
|
153
|
+
viewKey: view.viewKey,
|
|
154
|
+
viewCatalogDigest: view.viewCatalogDigest,
|
|
155
|
+
policyDigest: viewPolicy?.digest() ?? "off",
|
|
156
|
+
discoveryMode: mode
|
|
157
|
+
}, view.rows);
|
|
158
|
+
if (cached === void 0) {
|
|
159
|
+
searchHealthy = false;
|
|
160
|
+
return {
|
|
161
|
+
results: [],
|
|
162
|
+
truncated: false,
|
|
163
|
+
degraded: true,
|
|
164
|
+
hint: "Skill search index is unavailable. Use the full catalog or skill(name)."
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
searchHealthy = true;
|
|
168
|
+
const result = await cached.index.search(query, options);
|
|
169
|
+
return result.stale || cached.stale ? {
|
|
170
|
+
...result,
|
|
171
|
+
stale: true
|
|
172
|
+
} : result;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
if (config.searchEnabled !== false) ctx.effect(() => registerSkillSearchTool(ctx, search));
|
|
176
|
+
ctx.on("evolution/skill-mutated", () => {
|
|
177
|
+
searchCache.clear();
|
|
178
|
+
});
|
|
179
|
+
if (mode === "off") return;
|
|
180
|
+
const map = new DomainMapFileStore(io, config.domainMapPath ?? join(root, "evolution", "domain-map.json"));
|
|
181
|
+
const journal = new ProjectionJournal(io, config.projectionJournalPath ?? join(root, "evolution", "projection-journal.json"));
|
|
182
|
+
const snapshots = new ViewSnapshotStore(io, config.viewSnapshotPath ?? join(root, "evolution", "view-snapshots.json"));
|
|
183
|
+
const globalPolicy = {
|
|
184
|
+
mode: mode === "shadow" ? "auto" : mode,
|
|
185
|
+
pinDomains: config.pinDomains,
|
|
186
|
+
disableDomains: config.disableDomains
|
|
187
|
+
};
|
|
188
|
+
const policy = new DomainPolicyStore({
|
|
189
|
+
global: globalPolicy,
|
|
190
|
+
...config.workspacePolicy === void 0 ? {} : { workspace: config.workspacePolicy },
|
|
191
|
+
...config.scopePolicy === void 0 ? {} : { scope: config.scopePolicy }
|
|
192
|
+
});
|
|
193
|
+
const readLayer = async (cwd, path) => {
|
|
194
|
+
if (path === void 0) return void 0;
|
|
195
|
+
try {
|
|
196
|
+
const text = await io.readText(isAbsolute(path) ? path : resolve(cwd, path));
|
|
197
|
+
return text === null ? void 0 : JSON.parse(text);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
ctx.logger.warn("evolution-skill-discovery: policy layer unreadable: " + (error instanceof Error ? error.message : String(error)));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
const policyFor = async (cwd) => {
|
|
204
|
+
const workspace = await readLayer(cwd, config.workspacePolicyPath) ?? config.workspacePolicy;
|
|
205
|
+
const scope = await readLayer(cwd, config.scopePolicyPath) ?? config.scopePolicy;
|
|
206
|
+
return new DomainPolicyStore({
|
|
207
|
+
global: globalPolicy,
|
|
208
|
+
...workspace === void 0 ? {} : { workspace },
|
|
209
|
+
...scope === void 0 ? {} : { scope }
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
const runtime = new ProjectionRuntime({
|
|
213
|
+
skillIndexSource: source,
|
|
214
|
+
map,
|
|
215
|
+
policy,
|
|
216
|
+
policyFor,
|
|
217
|
+
journal,
|
|
218
|
+
workingDirectory,
|
|
219
|
+
featureEpoch: config.featureEpoch,
|
|
220
|
+
codecVersion: "1",
|
|
221
|
+
adapterVersion: "1",
|
|
222
|
+
projectionSchemaVersion: "1",
|
|
223
|
+
mode,
|
|
224
|
+
...config.maxCards === void 0 ? {} : { maxCards: config.maxCards },
|
|
225
|
+
...config.tokenBudget === void 0 ? {} : { tokenBudget: config.tokenBudget },
|
|
226
|
+
searchAvailable: () => searchHealthy && config.searchEnabled !== false,
|
|
227
|
+
...config.staleAfterHours === void 0 ? {} : { staleAfterHours: config.staleAfterHours },
|
|
228
|
+
...config.descriptionStaleAfterHours === void 0 ? {} : { descriptionStaleAfterHours: config.descriptionStaleAfterHours },
|
|
229
|
+
isFrozen: async (agent) => snapshots.isFrozen(String(agent.session.id), config.featureEpoch)
|
|
230
|
+
});
|
|
231
|
+
const queue = new JsonAssignmentQueue(io, config.assignmentQueuePath ?? join(root, "evolution", "assignment-queue.json"));
|
|
232
|
+
const assignment = new DomainAssignmentService(queue, map, {
|
|
233
|
+
createClassificationEnabled: config.createClassificationEnabled ?? false,
|
|
234
|
+
...config.provisionalThreshold === void 0 ? {} : { provisionalThreshold: config.provisionalThreshold },
|
|
235
|
+
now: Date.now
|
|
236
|
+
});
|
|
237
|
+
const worker = new AssignmentWorker(assignment, queue);
|
|
238
|
+
queue.load().then(() => worker.drain()).catch(() => {
|
|
239
|
+
ctx.logger.warn("evolution-skill-discovery: assignment queue load failed; queued work stays for the next start");
|
|
240
|
+
});
|
|
241
|
+
installAssignmentSidecar(ctx, assignment, { onSubmitted: () => {
|
|
242
|
+
worker.drain().catch((error) => {
|
|
243
|
+
ctx.logger.warn("evolution-skill-discovery: assignment drain failed: " + (error instanceof Error ? error.message : String(error)));
|
|
244
|
+
});
|
|
245
|
+
} });
|
|
246
|
+
ctx.on("agent/created", async ({ agent, source: start }) => {
|
|
247
|
+
try {
|
|
248
|
+
installDiscoveryAwareness(agent.ctx);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
ctx.logger.warn("evolution-skill-discovery: awareness install failed: " + (error instanceof Error ? error.message : String(error)));
|
|
251
|
+
}
|
|
252
|
+
if (start !== "startup") return;
|
|
253
|
+
try {
|
|
254
|
+
const cwd = await workingDirectory.ensure(agent);
|
|
255
|
+
const view = await index.read({
|
|
256
|
+
cwd,
|
|
257
|
+
scopeKey: String(agent.id),
|
|
258
|
+
scope: agent
|
|
259
|
+
});
|
|
260
|
+
await snapshots.put({
|
|
261
|
+
sessionId: String(agent.session.id),
|
|
262
|
+
viewKey: view.viewKey,
|
|
263
|
+
cwd,
|
|
264
|
+
viewCatalogDigest: view.viewCatalogDigest,
|
|
265
|
+
mapVersion: "0",
|
|
266
|
+
configDigest: "production",
|
|
267
|
+
featureEpoch: config.featureEpoch,
|
|
268
|
+
createdAt: Date.now()
|
|
269
|
+
});
|
|
270
|
+
const refreshed = await refreshStaleDescriptions(map);
|
|
271
|
+
if (refreshed > 0) ctx.logger.info("evolution-skill-discovery: refreshed " + refreshed + " stale domain descriptions");
|
|
272
|
+
} catch (error) {
|
|
273
|
+
ctx.logger.warn("evolution-skill-discovery: initial view snapshot failed: " + (error instanceof Error ? error.message : String(error)));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
ctx.on("agent/pre-step", async ({ agent, signal }, next) => {
|
|
277
|
+
const decision = await next();
|
|
278
|
+
try {
|
|
279
|
+
return await runtime.project(agent, decision, signal);
|
|
280
|
+
} catch (error) {
|
|
281
|
+
ctx.logger.warn("evolution-skill-discovery: projection failed open: " + (error instanceof Error ? error.message : String(error)));
|
|
282
|
+
return decision;
|
|
283
|
+
}
|
|
284
|
+
}, { prepend: true });
|
|
285
|
+
const coordinator = generation === void 0 ? void 0 : new DomainGenerationCoordinator(map, generation);
|
|
286
|
+
const commandRuntime = ctx.get("commands");
|
|
287
|
+
if (commandRuntime !== void 0) ctx.effect(() => commandRuntime.register({
|
|
288
|
+
name: "skill-domain",
|
|
289
|
+
description: "Generate or inspect the skill domain map.",
|
|
290
|
+
async handler({ rawInput, agent }) {
|
|
291
|
+
const [action] = rawInput.trim().split(/\s+/);
|
|
292
|
+
if (action === "status") {
|
|
293
|
+
const statusCwd = await workingDirectory.ensure(agent);
|
|
294
|
+
const view = await index.read({
|
|
295
|
+
cwd: statusCwd,
|
|
296
|
+
scopeKey: String(agent.id),
|
|
297
|
+
scope: agent
|
|
298
|
+
});
|
|
299
|
+
const rows = view.rows.slice(0, 12).map((row) => row.name + " | provider=" + row.provider + " source=" + row.source + " managed=" + String(row.managed) + " invocable=" + String(row.modelInvocable) + " protected=" + String(row.protected) + " pinned=" + String(row.pinned) + " key=" + row.skillKey + " hash=" + row.threeFieldHash);
|
|
300
|
+
const state = await runtime.inspect(agent);
|
|
301
|
+
const report = runtime.report(agent);
|
|
302
|
+
return {
|
|
303
|
+
kind: "success",
|
|
304
|
+
text: "discovery mode=" + mode + "; view=" + view.viewKey + "; phase=" + state.phase + " map=" + state.map + " search=" + state.search + " policy=" + state.policy + " last=" + report.action + (state.reasons.length === 0 ? "" : " reasons=" + state.reasons.join(",")) + "\n" + rows.join("\n")
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
if (action === "confirm") {
|
|
308
|
+
const domainId = rawInput.trim().split(/\s+/)[1];
|
|
309
|
+
if (domainId === void 0) return {
|
|
310
|
+
kind: "error",
|
|
311
|
+
text: "Usage: /skill-domain confirm <id>"
|
|
312
|
+
};
|
|
313
|
+
return await assignment.confirm(domainId) ? {
|
|
314
|
+
kind: "success",
|
|
315
|
+
text: "Confirmed domain " + domainId + "."
|
|
316
|
+
} : {
|
|
317
|
+
kind: "error",
|
|
318
|
+
text: "Unknown or non-provisional domain: " + domainId
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (action !== "generate") return {
|
|
322
|
+
kind: "error",
|
|
323
|
+
text: "Usage: /skill-domain status | generate | confirm <id>"
|
|
324
|
+
};
|
|
325
|
+
if (coordinator === void 0) return {
|
|
326
|
+
kind: "error",
|
|
327
|
+
text: "Generation is unavailable: no llm/generation port is mounted."
|
|
328
|
+
};
|
|
329
|
+
if (config.mapReferenceCwd === void 0) return {
|
|
330
|
+
kind: "error",
|
|
331
|
+
text: "No mapReferenceCwd configured; refusing to generate a global map from the caller view."
|
|
332
|
+
};
|
|
333
|
+
const view = await index.read({
|
|
334
|
+
cwd: config.mapReferenceCwd,
|
|
335
|
+
scopeKey: config.mapReferenceScope ?? String(agent.id),
|
|
336
|
+
scope: agent
|
|
337
|
+
});
|
|
338
|
+
const request = buildGenerationRequest({
|
|
339
|
+
mapScope: "global",
|
|
340
|
+
sourceDigest: view.viewCatalogDigest,
|
|
341
|
+
mapVersion: (await map.read()).mapVersion,
|
|
342
|
+
rows: view.rows,
|
|
343
|
+
prompt: buildDomainGenerationPrompt({
|
|
344
|
+
minDomains: 8,
|
|
345
|
+
maxDomains: 8
|
|
346
|
+
}),
|
|
347
|
+
promptVersion: "v2",
|
|
348
|
+
model: config.generationModel ?? "deepseek-flash",
|
|
349
|
+
runId: randomUUID()
|
|
350
|
+
});
|
|
351
|
+
const result = await coordinator.ensure(request);
|
|
352
|
+
return {
|
|
353
|
+
kind: "success",
|
|
354
|
+
text: "Domain map generated: " + result.domains.length + " domains, mapVersion=" + result.mapVersion
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
}));
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
360
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { c as SkillSearchCache, d as SkillIndex, r as registerSkillSearchTool } from "./tool-CvUTwKvW.js";
|
|
2
|
+
//#region lib/types/search-entry.js
|
|
3
|
+
const name = "evolution-skill-discovery";
|
|
4
|
+
const inject = [
|
|
5
|
+
"skills",
|
|
6
|
+
"workingDirectory",
|
|
7
|
+
"tools"
|
|
8
|
+
];
|
|
9
|
+
var PlatformSearchIndexSource = class {
|
|
10
|
+
ctx;
|
|
11
|
+
constructor(ctx) {
|
|
12
|
+
this.ctx = ctx;
|
|
13
|
+
}
|
|
14
|
+
async snapshot(query) {
|
|
15
|
+
const snapshot = await this.ctx.skills.snapshot({
|
|
16
|
+
cwd: query.cwd,
|
|
17
|
+
...query.scope === void 0 ? {} : { scope: query.scope }
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
skills: snapshot.skills,
|
|
21
|
+
complete: snapshot.complete
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async managedSkillKeys() {
|
|
25
|
+
return /* @__PURE__ */ new Set();
|
|
26
|
+
}
|
|
27
|
+
async protectedSkillKeys() {
|
|
28
|
+
return /* @__PURE__ */ new Set();
|
|
29
|
+
}
|
|
30
|
+
async pinnedSkillKeys() {
|
|
31
|
+
return /* @__PURE__ */ new Set();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
function unavailable() {
|
|
35
|
+
return {
|
|
36
|
+
results: [],
|
|
37
|
+
truncated: false,
|
|
38
|
+
degraded: true,
|
|
39
|
+
hint: "Skill search is unavailable without a session working directory."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compose the search-only discovery surface.
|
|
44
|
+
* @param ctx - plugin context with skills, workingDirectory, and tools.
|
|
45
|
+
* @param config - search-only configuration.
|
|
46
|
+
*/
|
|
47
|
+
function apply(ctx, config) {
|
|
48
|
+
if (typeof config.featureEpoch !== "string" || config.featureEpoch.length === 0) throw new Error("evolution-skill-discovery: featureEpoch is required");
|
|
49
|
+
if (config.mode !== void 0 && config.mode !== "off") ctx.logger.warn("evolution-skill-discovery: mode=" + config.mode + " is temporarily search-only; domain/projection is disabled until its producer is installed");
|
|
50
|
+
if (config.searchEnabled === false) return;
|
|
51
|
+
const source = new PlatformSearchIndexSource(ctx);
|
|
52
|
+
const cache = new SkillSearchCache();
|
|
53
|
+
const index = new SkillIndex(source);
|
|
54
|
+
ctx.effect(() => registerSkillSearchTool(ctx, { async search(query, options, agent, signal) {
|
|
55
|
+
if (agent === void 0) return unavailable();
|
|
56
|
+
const workingDirectory = ctx.get("workingDirectory");
|
|
57
|
+
if (workingDirectory === void 0) return unavailable();
|
|
58
|
+
const cwd = await workingDirectory.ensure(agent, signal);
|
|
59
|
+
const view = await index.read({
|
|
60
|
+
cwd,
|
|
61
|
+
scopeKey: String(agent.id),
|
|
62
|
+
scope: agent,
|
|
63
|
+
signal
|
|
64
|
+
});
|
|
65
|
+
const cached = await cache.get({
|
|
66
|
+
viewKey: view.viewKey,
|
|
67
|
+
viewCatalogDigest: view.viewCatalogDigest,
|
|
68
|
+
policyDigest: "search-only",
|
|
69
|
+
discoveryMode: "off"
|
|
70
|
+
}, view.rows);
|
|
71
|
+
if (cached === void 0) return {
|
|
72
|
+
results: [],
|
|
73
|
+
truncated: false,
|
|
74
|
+
degraded: true,
|
|
75
|
+
hint: "Skill search index is unavailable. Use the full catalog or skill(name)."
|
|
76
|
+
};
|
|
77
|
+
const result = await cached.index.search(query, options);
|
|
78
|
+
return result.stale || cached.stale ? {
|
|
79
|
+
...result,
|
|
80
|
+
stale: true
|
|
81
|
+
} : result;
|
|
82
|
+
} }));
|
|
83
|
+
ctx.on("evolution/skill-mutated", () => {
|
|
84
|
+
cache.clear();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { apply, inject, name };
|