@lmzhen/dsh-evolution-skill-discovery 0.31.0 → 0.32.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/lib/main-entry.js +2519 -7
- package/lib/types/assignment-queue.d.ts +4 -2
- package/lib/types/assignment-sidecar.d.ts +4 -1
- package/lib/types/awareness.d.ts +4 -1
- package/lib/types/catalog-codec.d.ts +5 -0
- package/lib/types/index.d.ts +0 -12
- package/lib/types/main-entry.d.ts +4 -1
- package/lib/types/projection-journal.d.ts +2 -0
- package/lib/types/tool.d.ts +4 -1
- package/package.json +7 -17
- package/lib/domain-description-Dxv-Rcon.js +0 -2104
- package/lib/index.js +0 -764
- package/lib/search-entry.js +0 -88
- package/lib/tool-CvUTwKvW.js +0 -446
- package/lib/types/adapter.d.ts +0 -48
- package/lib/types/domain-metrics.d.ts +0 -41
- package/lib/types/domain-view.d.ts +0 -15
- package/lib/types/features.d.ts +0 -11
- package/lib/types/maintenance.d.ts +0 -62
- package/lib/types/plugin.d.ts +0 -31
- package/lib/types/runtime.d.ts +0 -42
- package/lib/types/search-entry.d.ts +0 -19
- package/lib/types/search-judge.d.ts +0 -26
- package/lib/types/session-projection.d.ts +0 -19
- package/lib/types/session-store.d.ts +0 -22
- package/lib/types/stages.d.ts +0 -6
- package/lib/types/ui.d.ts +0 -69
package/lib/search-entry.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
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 };
|
package/lib/tool-CvUTwKvW.js
DELETED
|
@@ -1,446 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
import MiniSearch from "minisearch";
|
|
4
|
-
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
5
|
-
//#region lib/types/identity.js
|
|
6
|
-
function sha256(value) {
|
|
7
|
-
return createHash("sha256").update(value).digest("hex");
|
|
8
|
-
}
|
|
9
|
-
function canonical(value) {
|
|
10
|
-
if (value instanceof Set) return { $set: [...value].map(canonical).sort((left, right) => JSON.stringify(left) < JSON.stringify(right) ? -1 : JSON.stringify(left) > JSON.stringify(right) ? 1 : 0) };
|
|
11
|
-
if (value instanceof Map) return { $map: [...value.entries()].map(([key, entry]) => [canonical(key), canonical(entry)]).sort((left, right) => JSON.stringify(left) < JSON.stringify(right) ? -1 : JSON.stringify(left) > JSON.stringify(right) ? 1 : 0) };
|
|
12
|
-
if (Array.isArray(value)) return value.map(canonical);
|
|
13
|
-
if (typeof value === "object" && value !== null) return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, entry]) => [key, canonical(entry)]));
|
|
14
|
-
return value;
|
|
15
|
-
}
|
|
16
|
-
function digest(value) {
|
|
17
|
-
return sha256(JSON.stringify(canonical(value)));
|
|
18
|
-
}
|
|
19
|
-
/** @returns stable key for the winning provider/source/name tuple. */
|
|
20
|
-
function skillKeyOf(summary) {
|
|
21
|
-
return JSON.stringify([
|
|
22
|
-
summary.provider,
|
|
23
|
-
summary.source,
|
|
24
|
-
summary.name
|
|
25
|
-
]);
|
|
26
|
-
}
|
|
27
|
-
/** @returns stable hash of the canonical cwd and optional scope key. */
|
|
28
|
-
function viewKeyOf(input) {
|
|
29
|
-
return digest([resolve(input.cwd), input.scopeKey ?? null]);
|
|
30
|
-
}
|
|
31
|
-
/** @returns hash of the three fields used by discovery/retrieval. */
|
|
32
|
-
function threeFieldHashOf(input) {
|
|
33
|
-
return digest([
|
|
34
|
-
input.name,
|
|
35
|
-
input.description,
|
|
36
|
-
input.whenToUse ?? null
|
|
37
|
-
]);
|
|
38
|
-
}
|
|
39
|
-
/** @returns normalized row for one skill summary. */
|
|
40
|
-
function skillIndexRowOf(summary, managed, protectedSkill = false, pinned = false) {
|
|
41
|
-
return {
|
|
42
|
-
skillKey: skillKeyOf(summary),
|
|
43
|
-
name: summary.name,
|
|
44
|
-
description: summary.description,
|
|
45
|
-
...summary.whenToUse === void 0 ? {} : { whenToUse: summary.whenToUse },
|
|
46
|
-
provider: summary.provider,
|
|
47
|
-
source: summary.source,
|
|
48
|
-
managed,
|
|
49
|
-
modelInvocable: summary.invocation.modelInvocable,
|
|
50
|
-
protected: protectedSkill,
|
|
51
|
-
pinned,
|
|
52
|
-
threeFieldHash: threeFieldHashOf(summary)
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/** @returns digest of the sorted rows plus completeness. */
|
|
56
|
-
function catalogRevisionOf(rows, complete) {
|
|
57
|
-
return digest([complete, rows.map((row) => [
|
|
58
|
-
row.skillKey,
|
|
59
|
-
row.name,
|
|
60
|
-
row.description,
|
|
61
|
-
row.whenToUse ?? null,
|
|
62
|
-
row.provider,
|
|
63
|
-
row.source,
|
|
64
|
-
row.managed,
|
|
65
|
-
row.modelInvocable,
|
|
66
|
-
row.protected,
|
|
67
|
-
row.pinned,
|
|
68
|
-
row.threeFieldHash
|
|
69
|
-
])]);
|
|
70
|
-
}
|
|
71
|
-
/** @returns digest of a concrete per-view snapshot. */
|
|
72
|
-
function viewCatalogDigestOf(viewKey, rows, complete) {
|
|
73
|
-
return digest([viewKey, catalogRevisionOf(rows, complete)]);
|
|
74
|
-
}
|
|
75
|
-
/** @returns digest of effective policy plus its revisions. */
|
|
76
|
-
function policyDigestOf(input) {
|
|
77
|
-
return digest([
|
|
78
|
-
input.globalPolicyRevision,
|
|
79
|
-
input.workspaceOverlayRevision ?? null,
|
|
80
|
-
input.scopeOverlayRevision ?? null,
|
|
81
|
-
input.effectivePolicy
|
|
82
|
-
]);
|
|
83
|
-
}
|
|
84
|
-
/** @returns view-cache identity for one projection. */
|
|
85
|
-
function projectionDigestOf(input) {
|
|
86
|
-
return digest([
|
|
87
|
-
input.viewKey,
|
|
88
|
-
input.mapVersion,
|
|
89
|
-
input.policyDigest,
|
|
90
|
-
input.viewCatalogDigest,
|
|
91
|
-
input.adapterVersion,
|
|
92
|
-
input.projectionSchemaVersion,
|
|
93
|
-
input.discoveryMode
|
|
94
|
-
]);
|
|
95
|
-
}
|
|
96
|
-
/** @returns view-cache identity for one search index. */
|
|
97
|
-
function searchIndexKeyOf(input) {
|
|
98
|
-
return digest([
|
|
99
|
-
input.viewKey,
|
|
100
|
-
input.viewCatalogDigest,
|
|
101
|
-
input.policyDigest,
|
|
102
|
-
input.tokenizerVersion,
|
|
103
|
-
input.indexSchemaVersion,
|
|
104
|
-
input.discoveryMode
|
|
105
|
-
]);
|
|
106
|
-
}
|
|
107
|
-
//#endregion
|
|
108
|
-
//#region lib/types/skill-index.js
|
|
109
|
-
function bySkillKey(left, right) {
|
|
110
|
-
return left.skillKey < right.skillKey ? -1 : left.skillKey > right.skillKey ? 1 : 0;
|
|
111
|
-
}
|
|
112
|
-
/** Read-only view model; it does not cache or own a provider. */
|
|
113
|
-
var SkillIndex = class {
|
|
114
|
-
source;
|
|
115
|
-
constructor(source) {
|
|
116
|
-
this.source = source;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Read one view from the source.
|
|
120
|
-
* @param query - cwd/scope and cancellation for this observation.
|
|
121
|
-
* @returns normalized rows and completeness; incomplete data is not hidden.
|
|
122
|
-
*/
|
|
123
|
-
async read(query) {
|
|
124
|
-
const [snapshot, managed, protectedKeys, pinnedKeys] = await Promise.all([
|
|
125
|
-
this.source.snapshot(query),
|
|
126
|
-
this.source.managedSkillKeys(),
|
|
127
|
-
this.source.protectedSkillKeys?.() ?? Promise.resolve(/* @__PURE__ */ new Set()),
|
|
128
|
-
this.source.pinnedSkillKeys?.() ?? Promise.resolve(/* @__PURE__ */ new Set())
|
|
129
|
-
]);
|
|
130
|
-
const rows = snapshot.skills.map((summary) => skillIndexRowOf(summary, managed.has(skillKeyOf(summary)), protectedKeys.has(skillKeyOf(summary)), pinnedKeys.has(skillKeyOf(summary)))).sort(bySkillKey);
|
|
131
|
-
return {
|
|
132
|
-
viewKey: viewKeyOf(query),
|
|
133
|
-
catalogRevision: catalogRevisionOf(rows, snapshot.complete),
|
|
134
|
-
viewCatalogDigest: viewCatalogDigestOf(viewKeyOf(query), rows, snapshot.complete),
|
|
135
|
-
rows,
|
|
136
|
-
complete: snapshot.complete
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region lib/types/search.js
|
|
142
|
-
/** Tokenizer version; changing the algorithm requires rebuilding indexes. */
|
|
143
|
-
const SKILL_SEARCH_TOKENIZER_VERSION = "cjk-bigram-v1";
|
|
144
|
-
/** Fields indexed by skill search; no body/path. */
|
|
145
|
-
const SKILL_SEARCH_FIELDS = [
|
|
146
|
-
"name",
|
|
147
|
-
"description",
|
|
148
|
-
"whenToUse"
|
|
149
|
-
];
|
|
150
|
-
/** Index schema version; bump when indexed fields/options change. */
|
|
151
|
-
const SKILL_SEARCH_INDEX_SCHEMA_VERSION = "skill-search-v1";
|
|
152
|
-
const CJK = String.raw`[[\p{scx=Han}\p{scx=Hira}\p{scx=Kana}\p{scx=Hang}]&&[\p{L}\p{M}\p{N}]]`;
|
|
153
|
-
const RUN = new RegExp(String.raw`${CJK}+|[[\p{L}\p{M}\p{N}]--${CJK}]+`, "gv");
|
|
154
|
-
const CJK_START = new RegExp(String.raw`^${CJK}`, "v");
|
|
155
|
-
/**
|
|
156
|
-
* Split NFKC text into CJK overlapping bigrams plus tail, and ASCII/other runs.
|
|
157
|
-
* Parity source: plugin-market/src/search.ts searchTerms.
|
|
158
|
-
* @param text - indexed or queried text.
|
|
159
|
-
* @returns terms in text order; callers lowercase.
|
|
160
|
-
*/
|
|
161
|
-
function searchTerms(text) {
|
|
162
|
-
return [...text.normalize("NFKC").matchAll(RUN)].flatMap(([run]) => {
|
|
163
|
-
if (!CJK_START.test(run)) return [run];
|
|
164
|
-
const chars = Array.from(run);
|
|
165
|
-
return [...chars.slice(1).map((char, position) => chars[position] + char), chars.at(-1)];
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
function clampLimit(limit) {
|
|
169
|
-
if (limit === void 0) return 3;
|
|
170
|
-
return Math.min(20, Math.max(1, Math.trunc(limit)));
|
|
171
|
-
}
|
|
172
|
-
function build(rows) {
|
|
173
|
-
const engine = new MiniSearch({
|
|
174
|
-
fields: [...SKILL_SEARCH_FIELDS],
|
|
175
|
-
storeFields: [...SKILL_SEARCH_FIELDS],
|
|
176
|
-
tokenize: searchTerms,
|
|
177
|
-
processTerm: (term) => term.toLowerCase(),
|
|
178
|
-
searchOptions: {
|
|
179
|
-
boost: {
|
|
180
|
-
name: 3,
|
|
181
|
-
whenToUse: 2
|
|
182
|
-
},
|
|
183
|
-
prefix: true,
|
|
184
|
-
combineWith: "AND",
|
|
185
|
-
fuzzy: (term) => term.length >= 4 && !CJK_START.test(term) ? .2 : false,
|
|
186
|
-
maxFuzzy: 2
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
const seen = /* @__PURE__ */ new Set();
|
|
190
|
-
const documents = [];
|
|
191
|
-
for (const row of rows) {
|
|
192
|
-
if (!row.modelInvocable || seen.has(row.skillKey)) continue;
|
|
193
|
-
seen.add(row.skillKey);
|
|
194
|
-
documents.push({
|
|
195
|
-
id: row.skillKey,
|
|
196
|
-
name: row.name,
|
|
197
|
-
description: row.description,
|
|
198
|
-
whenToUse: row.whenToUse ?? ""
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
engine.addAll(documents);
|
|
202
|
-
return engine;
|
|
203
|
-
}
|
|
204
|
-
/** Per-view MiniSearch index; no global engine and no projection-only filtering. */
|
|
205
|
-
var SkillSearchIndex = class SkillSearchIndex {
|
|
206
|
-
engine;
|
|
207
|
-
staleState = false;
|
|
208
|
-
viewKey;
|
|
209
|
-
constructor(viewKey, engine) {
|
|
210
|
-
this.viewKey = viewKey;
|
|
211
|
-
this.engine = engine;
|
|
212
|
-
}
|
|
213
|
-
/** @returns an index over every modelInvocable row in this view. */
|
|
214
|
-
static fromRows(viewKey, rows) {
|
|
215
|
-
return new SkillSearchIndex(viewKey, build(rows));
|
|
216
|
-
}
|
|
217
|
-
/** Mark the current index stale before a rebuild finishes. */
|
|
218
|
-
markStale() {
|
|
219
|
-
this.staleState = true;
|
|
220
|
-
}
|
|
221
|
-
/** Rebuild from this view's full rows; a failed rebuild keeps the old engine stale. */
|
|
222
|
-
async rebuild(rows) {
|
|
223
|
-
this.staleState = true;
|
|
224
|
-
try {
|
|
225
|
-
this.engine = build(rows);
|
|
226
|
-
this.staleState = false;
|
|
227
|
-
return true;
|
|
228
|
-
} catch {
|
|
229
|
-
return false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
/** @returns hits, truncation, and whether the index is stale. */
|
|
233
|
-
async search(query, options) {
|
|
234
|
-
const limit = clampLimit(query.limit);
|
|
235
|
-
const terms = searchTerms(query.query);
|
|
236
|
-
if (terms.length === 0) return {
|
|
237
|
-
results: [],
|
|
238
|
-
truncated: false,
|
|
239
|
-
stale: this.staleState
|
|
240
|
-
};
|
|
241
|
-
let fallback = false;
|
|
242
|
-
let hits = this.engine.search(query.query, { combineWith: "AND" });
|
|
243
|
-
if (hits.length === 0 && terms.length > 1) {
|
|
244
|
-
const relaxed = this.engine.search(query.query, { combineWith: "OR" });
|
|
245
|
-
fallback = relaxed.length > 0;
|
|
246
|
-
hits = relaxed;
|
|
247
|
-
}
|
|
248
|
-
const allowed = options?.allowedSkillKeys;
|
|
249
|
-
const filtered = allowed === void 0 ? hits : hits.filter((hit) => allowed.has(String(hit.id)));
|
|
250
|
-
return {
|
|
251
|
-
results: filtered.slice(0, limit).map((hit) => {
|
|
252
|
-
const fields = new Set(Object.values(hit.match).flat());
|
|
253
|
-
return {
|
|
254
|
-
name: String(hit.name),
|
|
255
|
-
description: String(hit.description),
|
|
256
|
-
...hit.whenToUse === void 0 || hit.whenToUse === "" ? {} : { whenToUse: String(hit.whenToUse) },
|
|
257
|
-
matchedBy: fields.has("name") ? "name" : fields.has("whenToUse") ? "whenToUse" : "description"
|
|
258
|
-
};
|
|
259
|
-
}),
|
|
260
|
-
truncated: filtered.length > limit,
|
|
261
|
-
...fallback ? { fallback: true } : {},
|
|
262
|
-
stale: this.staleState
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
/** Per-view cache keyed by searchIndexKey; never shares one engine across views. */
|
|
267
|
-
var SkillSearchCache = class {
|
|
268
|
-
entries = /* @__PURE__ */ new Map();
|
|
269
|
-
/**
|
|
270
|
-
* Get or build one view index. A failed rebuild retains the previous engine
|
|
271
|
-
* and marks it stale; no previous engine means undefined.
|
|
272
|
-
* @param key - identity inputs for searchIndexKey.
|
|
273
|
-
* @param rows - current full rows for the view.
|
|
274
|
-
* @returns index plus stale state, or undefined when no index is available.
|
|
275
|
-
*/
|
|
276
|
-
async get(key, rows) {
|
|
277
|
-
const cacheKey = searchIndexKeyOf({
|
|
278
|
-
viewKey: key.viewKey,
|
|
279
|
-
viewCatalogDigest: key.viewCatalogDigest,
|
|
280
|
-
policyDigest: key.policyDigest,
|
|
281
|
-
tokenizerVersion: SKILL_SEARCH_TOKENIZER_VERSION,
|
|
282
|
-
indexSchemaVersion: SKILL_SEARCH_INDEX_SCHEMA_VERSION,
|
|
283
|
-
discoveryMode: key.discoveryMode
|
|
284
|
-
});
|
|
285
|
-
const existing = this.entries.get(cacheKey);
|
|
286
|
-
if (existing !== void 0) return {
|
|
287
|
-
index: existing.index,
|
|
288
|
-
stale: false
|
|
289
|
-
};
|
|
290
|
-
try {
|
|
291
|
-
const index = SkillSearchIndex.fromRows(key.viewKey, rows);
|
|
292
|
-
this.entries.set(cacheKey, {
|
|
293
|
-
key: cacheKey,
|
|
294
|
-
viewKey: key.viewKey,
|
|
295
|
-
index
|
|
296
|
-
});
|
|
297
|
-
return {
|
|
298
|
-
index,
|
|
299
|
-
stale: false
|
|
300
|
-
};
|
|
301
|
-
} catch {
|
|
302
|
-
const old = [...this.entries.values()].find((entry) => entry.viewKey === key.viewKey);
|
|
303
|
-
if (old === void 0) return void 0;
|
|
304
|
-
old.index.markStale();
|
|
305
|
-
return {
|
|
306
|
-
index: old.index,
|
|
307
|
-
stale: true
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
/** Drop every index for one view. */
|
|
312
|
-
invalidate(viewKey) {
|
|
313
|
-
for (const [cacheKey, entry] of this.entries) if (entry.viewKey === viewKey) this.entries.delete(cacheKey);
|
|
314
|
-
}
|
|
315
|
-
/** Drop every cached view index. */
|
|
316
|
-
clear() {
|
|
317
|
-
this.entries.clear();
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
//#endregion
|
|
321
|
-
//#region lib/types/tool.js
|
|
322
|
-
/** Static model-facing description; no dynamic domain list/tree. */
|
|
323
|
-
const SKILL_SEARCH_DESCRIPTION = "Search skill summaries by name, description, or whenToUse when coverage is uncertain. Results are summaries, not bodies; a matching name can be loaded directly. Empty results are inconclusive; the full catalog remains available.";
|
|
324
|
-
/** @returns response or a degraded hint; never silent empty on failure. */
|
|
325
|
-
async function searchWithDegraded(provider, query, allowedSkillKeys, agent, signal) {
|
|
326
|
-
if (provider === void 0) return {
|
|
327
|
-
results: [],
|
|
328
|
-
truncated: false,
|
|
329
|
-
degraded: true,
|
|
330
|
-
hint: "Skill search is unavailable. Use the full catalog or load an exact skill by name with skill(name)."
|
|
331
|
-
};
|
|
332
|
-
try {
|
|
333
|
-
return await provider.search(query, allowedSkillKeys === void 0 ? void 0 : { allowedSkillKeys }, agent, signal);
|
|
334
|
-
} catch {
|
|
335
|
-
return {
|
|
336
|
-
results: [],
|
|
337
|
-
truncated: false,
|
|
338
|
-
degraded: true,
|
|
339
|
-
hint: "Skill search failed. Use the full catalog or load an exact skill by name with skill(name)."
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
function toToolResponse(response) {
|
|
344
|
-
return {
|
|
345
|
-
results: response.results.map((hit) => ({
|
|
346
|
-
name: hit.name,
|
|
347
|
-
description: hit.description,
|
|
348
|
-
...hit.whenToUse === void 0 ? {} : { whenToUse: hit.whenToUse },
|
|
349
|
-
...hit.matchedBy === void 0 ? {} : { matchedBy: hit.matchedBy }
|
|
350
|
-
})),
|
|
351
|
-
truncated: response.truncated,
|
|
352
|
-
...response.fallback === void 0 ? {} : { fallback: response.fallback },
|
|
353
|
-
...response.stale === void 0 ? {} : { stale: response.stale },
|
|
354
|
-
...response.degraded === void 0 ? {} : { degraded: response.degraded },
|
|
355
|
-
...response.hint === void 0 ? {} : { hint: response.hint }
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Register skill_search on the optional tools service. The description/schema are static; the
|
|
360
|
-
* provider is the only dynamic dependency.
|
|
361
|
-
* platform-declaration anchor: tools is declared in core PLATFORM_SERVICE_PROBES.
|
|
362
|
-
* @param ctx - plugin context.
|
|
363
|
-
* @param provider - search service or undefined when unavailable.
|
|
364
|
-
* @returns tool disposer.
|
|
365
|
-
*/
|
|
366
|
-
function registerSkillSearchTool(ctx, provider) {
|
|
367
|
-
const tools = ctx.get("tools");
|
|
368
|
-
if (tools === void 0) return () => {};
|
|
369
|
-
return tools.register(defineTool({
|
|
370
|
-
name: "skill_search",
|
|
371
|
-
description: SKILL_SEARCH_DESCRIPTION,
|
|
372
|
-
parameters: {
|
|
373
|
-
query: {
|
|
374
|
-
type: "string",
|
|
375
|
-
required: true,
|
|
376
|
-
description: "Search terms; CJK and ASCII are supported."
|
|
377
|
-
},
|
|
378
|
-
limit: {
|
|
379
|
-
type: "integer",
|
|
380
|
-
description: "Maximum results; defaults to 3, capped at 20."
|
|
381
|
-
}
|
|
382
|
-
},
|
|
383
|
-
output: {
|
|
384
|
-
schema: {
|
|
385
|
-
type: "object",
|
|
386
|
-
additionalProperties: false,
|
|
387
|
-
properties: {
|
|
388
|
-
results: {
|
|
389
|
-
type: "array",
|
|
390
|
-
required: true,
|
|
391
|
-
items: {
|
|
392
|
-
type: "object",
|
|
393
|
-
additionalProperties: false,
|
|
394
|
-
properties: {
|
|
395
|
-
name: {
|
|
396
|
-
type: "string",
|
|
397
|
-
required: true
|
|
398
|
-
},
|
|
399
|
-
description: {
|
|
400
|
-
type: "string",
|
|
401
|
-
required: true
|
|
402
|
-
},
|
|
403
|
-
whenToUse: { type: "string" },
|
|
404
|
-
matchedBy: { type: "string" }
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
},
|
|
408
|
-
truncated: {
|
|
409
|
-
type: "boolean",
|
|
410
|
-
required: true
|
|
411
|
-
},
|
|
412
|
-
fallback: { type: "boolean" },
|
|
413
|
-
stale: { type: "boolean" },
|
|
414
|
-
degraded: { type: "boolean" },
|
|
415
|
-
hint: { type: "string" }
|
|
416
|
-
}
|
|
417
|
-
},
|
|
418
|
-
render: (_args, value) => [{
|
|
419
|
-
type: "text",
|
|
420
|
-
text: value.degraded === true ? "Skill search is degraded: " + (value.hint ?? "use the full catalog or skill(name).") : "Found " + value.results.length + " skill result(s)" + (value.fallback === true ? " (OR fallback)." : ".") + (value.stale === true ? " (stale index)." : "") + "\n" + value.results.map((result) => "- " + result.name + ": " + result.description + (result.whenToUse === void 0 ? "" : " | when: " + result.whenToUse)).join("\n")
|
|
421
|
-
}]
|
|
422
|
-
},
|
|
423
|
-
async execute(args, exec) {
|
|
424
|
-
try {
|
|
425
|
-
const allowed = await provider?.allowedSkillKeys?.(exec.agent, exec.signal);
|
|
426
|
-
return toToolResponse(await searchWithDegraded(provider, {
|
|
427
|
-
query: args.query,
|
|
428
|
-
limit: args.limit
|
|
429
|
-
}, allowed, exec.agent, exec.signal));
|
|
430
|
-
} catch (error) {
|
|
431
|
-
return {
|
|
432
|
-
results: [],
|
|
433
|
-
truncated: false,
|
|
434
|
-
degraded: true,
|
|
435
|
-
hint: "Skill search failed: " + (error instanceof Error ? error.message : String(error))
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
}));
|
|
440
|
-
}
|
|
441
|
-
/** @returns true only for a search implementation; used by composition wiring. */
|
|
442
|
-
function isSkillSearch(value) {
|
|
443
|
-
return typeof value === "object" && value !== null && typeof value.search === "function";
|
|
444
|
-
}
|
|
445
|
-
//#endregion
|
|
446
|
-
export { skillKeyOf as _, SKILL_SEARCH_FIELDS as a, viewKeyOf as b, SkillSearchCache as c, SkillIndex as d, catalogRevisionOf as f, skillIndexRowOf as g, searchIndexKeyOf as h, searchWithDegraded as i, SkillSearchIndex as l, projectionDigestOf as m, isSkillSearch as n, SKILL_SEARCH_INDEX_SCHEMA_VERSION as o, policyDigestOf as p, registerSkillSearchTool as r, SKILL_SEARCH_TOKENIZER_VERSION as s, SKILL_SEARCH_DESCRIPTION as t, searchTerms as u, threeFieldHashOf as v, viewCatalogDigestOf as y };
|
package/lib/types/adapter.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import type { Agent, PreStepDecision } from '@deepseek-ai/dsh-agent';
|
|
3
|
-
import type { ContextFormed } from '@deepseek-ai/dsh-llm';
|
|
4
|
-
import type { CatalogEntry, ProjectionResult } from './projection.ts';
|
|
5
|
-
declare module '@deepseek-ai/dsh-llm' {
|
|
6
|
-
interface MessageSourceMap {
|
|
7
|
-
'skill-catalog': {
|
|
8
|
-
readonly kind: 'skill-catalog';
|
|
9
|
-
readonly form: 'catalog';
|
|
10
|
-
readonly entries: readonly CatalogEntry[];
|
|
11
|
-
} & ContextFormed;
|
|
12
|
-
'evolution-skill-projection': {
|
|
13
|
-
readonly kind: 'evolution-skill-projection';
|
|
14
|
-
readonly entries: readonly CatalogEntry[];
|
|
15
|
-
readonly hiddenNames: readonly string[];
|
|
16
|
-
readonly digest: string;
|
|
17
|
-
} & ContextFormed;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
/** Provider the plugin supplies from SkillIndex + DomainMap + policy. */
|
|
21
|
-
export interface ProjectionDigestStore {
|
|
22
|
-
get(agentKey: string): Promise<string | undefined>;
|
|
23
|
-
set(agentKey: string, digest: string): Promise<void>;
|
|
24
|
-
}
|
|
25
|
-
export interface CatalogProjectionProvider {
|
|
26
|
-
/** Optional persisted-session gate; false keeps the full catalog. */
|
|
27
|
-
shouldProject?(agent: Agent): boolean | Promise<boolean>;
|
|
28
|
-
project(input: {
|
|
29
|
-
readonly agent: Agent;
|
|
30
|
-
readonly catalogEntries: readonly CatalogEntry[];
|
|
31
|
-
}): ProjectionResult | Promise<ProjectionResult>;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Atomically replace one platform catalog message with the plugin projection.
|
|
35
|
-
* @param decision - the waterfall decision; only enter decisions are changed.
|
|
36
|
-
* @param result - a complete projection; incomplete results are ignored.
|
|
37
|
-
* @returns a new decision, or the original when no safe replacement exists.
|
|
38
|
-
*/
|
|
39
|
-
export declare function applyCatalogProjection(decision: PreStepDecision, result: ProjectionResult): PreStepDecision;
|
|
40
|
-
/**
|
|
41
|
-
* Install the thin pre-step adapter. The listener is outer; it always calls
|
|
42
|
-
* next, only touches the platform catalog message, and fails open.
|
|
43
|
-
* @param ctx - plugin context.
|
|
44
|
-
* @param provider - projection provider backed by SkillIndex/DomainMap.
|
|
45
|
-
* @returns disposer from ctx.on.
|
|
46
|
-
*/
|
|
47
|
-
export declare function installCatalogProjection(ctx: Context, provider: CatalogProjectionProvider, digestStore?: ProjectionDigestStore): () => void;
|
|
48
|
-
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { DomainMapSnapshot } from './domain-map.ts';
|
|
2
|
-
import type { SkillKey } from './identity.ts';
|
|
3
|
-
/** Optional labels for assignment accuracy; absent means unmeasured. */
|
|
4
|
-
export interface DomainMetricLabels {
|
|
5
|
-
readonly expectedBySkill: Readonly<Record<SkillKey, string>>;
|
|
6
|
-
readonly predictedBySkill: Readonly<Record<SkillKey, string>>;
|
|
7
|
-
readonly newDomainIds?: readonly string[] | undefined;
|
|
8
|
-
readonly predictedNewDomainIds?: readonly string[] | undefined;
|
|
9
|
-
}
|
|
10
|
-
/** Recomputable domain/assignment metrics; no sentence locking. */
|
|
11
|
-
export interface DomainMetricCounters {
|
|
12
|
-
readonly descriptionRewritten?: number | undefined;
|
|
13
|
-
readonly descriptionEligible?: number | undefined;
|
|
14
|
-
readonly refusedAssignments?: number | undefined;
|
|
15
|
-
readonly assignmentAttempts?: number | undefined;
|
|
16
|
-
readonly maxDomainsPerSkill?: number | undefined;
|
|
17
|
-
}
|
|
18
|
-
/** Recomputable domain/assignment metrics; no sentence locking. */
|
|
19
|
-
export interface DomainMetrics {
|
|
20
|
-
readonly measured: boolean;
|
|
21
|
-
readonly visibleSkills: number;
|
|
22
|
-
readonly coverage: number | null;
|
|
23
|
-
readonly unclassifiedRatio: number | null;
|
|
24
|
-
readonly emptyDomainCount: number;
|
|
25
|
-
readonly crossDomainRatio: number | null;
|
|
26
|
-
readonly pendingRate: number | null;
|
|
27
|
-
readonly assignmentAccuracy: number | null;
|
|
28
|
-
readonly newDomainPrecision: number | null;
|
|
29
|
-
readonly descriptionRewriteRate: number | null;
|
|
30
|
-
readonly staleDescriptionRatio: number | null;
|
|
31
|
-
readonly overAssignmentRate: number | null;
|
|
32
|
-
readonly refusalRate: number | null;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* @param snapshot - domain facts.
|
|
36
|
-
* @param visibleSkillKeys - skills visible in this view.
|
|
37
|
-
* @param labels - optional assignment labels.
|
|
38
|
-
* @returns metrics; null means the denominator is zero/unmeasured.
|
|
39
|
-
*/
|
|
40
|
-
export declare function computeDomainMetrics(snapshot: DomainMapSnapshot, visibleSkillKeys: ReadonlySet<SkillKey>, labels?: DomainMetricLabels, counters?: DomainMetricCounters): DomainMetrics;
|
|
41
|
-
//# sourceMappingURL=domain-metrics.d.ts.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { DomainMapSnapshot } from './domain-map.ts';
|
|
2
|
-
import type { SkillKey } from './identity.ts';
|
|
3
|
-
/** Per-view membership counts; unclassified is virtual, never a domain id. */
|
|
4
|
-
export interface DomainViewCounts {
|
|
5
|
-
readonly byDomain: ReadonlyMap<string, number>;
|
|
6
|
-
readonly unclassified: number;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Count visible skills by active domain membership.
|
|
10
|
-
* @param snapshot - global domain facts.
|
|
11
|
-
* @param visibleSkillKeys - skill keys visible in this view.
|
|
12
|
-
* @returns per-domain member counts plus the unclassified virtual count.
|
|
13
|
-
*/
|
|
14
|
-
export declare function domainViewCounts(snapshot: DomainMapSnapshot, visibleSkillKeys: ReadonlySet<SkillKey>): DomainViewCounts;
|
|
15
|
-
//# sourceMappingURL=domain-view.d.ts.map
|
package/lib/types/features.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/** Discovery feature gates; v0 defaults everything off. */
|
|
2
|
-
export type DiscoveryMode = 'off' | 'shadow' | 'on';
|
|
3
|
-
export interface DiscoveryFeatureConfig {
|
|
4
|
-
readonly projectionEnabled: boolean;
|
|
5
|
-
readonly searchEnabled: boolean;
|
|
6
|
-
readonly createClassificationEnabled: boolean;
|
|
7
|
-
readonly discoveryMode: DiscoveryMode;
|
|
8
|
-
}
|
|
9
|
-
export declare const V0_DISCOVERY_FEATURES: DiscoveryFeatureConfig;
|
|
10
|
-
export declare function canClassifyAtCreate(config: DiscoveryFeatureConfig, hasCreateDomainCards: boolean): boolean;
|
|
11
|
-
//# sourceMappingURL=features.d.ts.map
|