@aiwayds/dsh-mcp-adapter 0.5.0 → 0.6.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/usage.js ADDED
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Per-tool usage statistics and the keep-suggestion document (seam A — the
3
+ * self-evolution core).
4
+ *
5
+ * WHAT THIS MODULE OWNS: the durable facts only.
6
+ * - `usage.json` — `{ tools: { <name>: { calls, errors, firstUsedAt,
7
+ * lastUsedAt } } }`, one document in the plugin's own gate directory
8
+ * (beside gate.json / decisions.jsonl / suggestions.json);
9
+ * - `suggestions.json` — the last jev keep-suggestion batch.
10
+ *
11
+ * WHAT IT DELIBERATELY DOES NOT OWN: any jev call. The batch that fills
12
+ * suggestions.json lives in `jev/seams.ts`; this module only knows the shape
13
+ * of its result (so the command surface can render it without importing the
14
+ * client). Keeping the decision out of here is what makes the record path
15
+ * synchronous and remote-free: `record()` updates memory and schedules a
16
+ * write, and returns. Red line ① (no jev on the hot path) holds structurally
17
+ * because this file cannot call out at all.
18
+ *
19
+ * FAIL-OPEN (red line ②): a corrupt or unreadable document is warned about
20
+ * once and degrades to zero statistics — never to a crash and never to a
21
+ * wedged dispatch. Suggestions that cannot be read degrade to "no
22
+ * suggestions yet", which is exactly what an empty file means.
23
+ *
24
+ * @module usage
25
+ */
26
+ import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
27
+ import { existsSync, readFileSync } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ import { RANK_CANDIDATE_LIMIT } from "./rank.js";
30
+ /** The usage document file name inside the plugin's gate directory. */
31
+ export const USAGE_FILE_NAME = 'usage.json';
32
+ /** The keep-suggestion document file name inside the plugin's gate directory. */
33
+ export const SUGGESTIONS_FILE_NAME = 'suggestions.json';
34
+ /** Absolute usage.json path for one gate directory. */
35
+ export function usageFile(dir) {
36
+ return join(dir, USAGE_FILE_NAME);
37
+ }
38
+ /** Absolute suggestions.json path for one gate directory. */
39
+ export function suggestionsFile(dir) {
40
+ return join(dir, SUGGESTIONS_FILE_NAME);
41
+ }
42
+ /** Fresh-install zero state. */
43
+ export const EMPTY_USAGE = { tools: {} };
44
+ /** Coerce one counter to a non-negative integer; anything else is zero. */
45
+ function counter(value) {
46
+ return typeof value === 'number' && Number.isFinite(value) && value > 0
47
+ ? Math.floor(value)
48
+ : 0;
49
+ }
50
+ /** Keep only string timestamps (hand-edited documents can hold anything). */
51
+ function timestamp(value) {
52
+ return typeof value === 'string' ? value : '';
53
+ }
54
+ /**
55
+ * Sanitize any parsed usage document. Entry-by-entry: a corrupt counter
56
+ * becomes zero, a corrupt timestamp becomes `''`, and a non-object document
57
+ * becomes the empty one. Hand-edited or half-written files therefore cost
58
+ * precision, never correctness.
59
+ *
60
+ * @param raw - the parsed JSON (or anything at all).
61
+ * @returns a fresh document; the input is never retained.
62
+ */
63
+ export function normalizeUsage(raw) {
64
+ if (typeof raw !== 'object' || raw === null)
65
+ return { tools: {} };
66
+ const rawTools = raw.tools;
67
+ if (typeof rawTools !== 'object' || rawTools === null || Array.isArray(rawTools))
68
+ return { tools: {} };
69
+ const tools = {};
70
+ for (const [name, value] of Object.entries(rawTools)) {
71
+ if (name === '' || typeof value !== 'object' || value === null)
72
+ continue;
73
+ const entry = value;
74
+ const stats = {
75
+ calls: counter(entry.calls),
76
+ errors: Math.min(counter(entry.errors), counter(entry.calls)),
77
+ firstUsedAt: timestamp(entry.firstUsedAt),
78
+ lastUsedAt: timestamp(entry.lastUsedAt),
79
+ };
80
+ tools[name] = stats;
81
+ }
82
+ return { tools };
83
+ }
84
+ /**
85
+ * Fold one dispatch into a document and return the NEXT document (pure — the
86
+ * input object and its stats are never mutated, so a caller holding a snapshot
87
+ * keeps it). `firstUsedAt` is stamped on the tool's first call only, so it
88
+ * stays a true "when did this tool start being used" answer.
89
+ *
90
+ * @param doc - the current document.
91
+ * @param tool - the dispatched tool name.
92
+ * @param failed - whether the dispatch came back as a structured error.
93
+ * @param now - ISO timestamp to stamp (default: now).
94
+ * @returns the next document.
95
+ */
96
+ export function recordUsageCall(doc, tool, failed, now = new Date().toISOString()) {
97
+ if (tool === '')
98
+ return doc;
99
+ const previous = doc.tools[tool];
100
+ const tools = { ...doc.tools };
101
+ tools[tool] = {
102
+ calls: (previous?.calls ?? 0) + 1,
103
+ errors: (previous?.errors ?? 0) + (failed ? 1 : 0),
104
+ firstUsedAt: previous?.firstUsedAt !== undefined && previous.firstUsedAt !== ''
105
+ ? previous.firstUsedAt
106
+ : (previous === undefined ? now : previous.firstUsedAt),
107
+ lastUsedAt: now,
108
+ };
109
+ return { tools };
110
+ }
111
+ /** Total dispatches recorded across every tool. */
112
+ export function usageTotalCalls(doc) {
113
+ let total = 0;
114
+ for (const stats of Object.values(doc.tools))
115
+ total += stats.calls;
116
+ return total;
117
+ }
118
+ /** Number of tools carrying at least one recorded call. */
119
+ export function usageToolCount(doc) {
120
+ let total = 0;
121
+ for (const stats of Object.values(doc.tools))
122
+ if (stats.calls > 0)
123
+ total += 1;
124
+ return total;
125
+ }
126
+ /**
127
+ * How many total calls pass before a suggestion batch may fire.
128
+ * Deliberately coarse: the batch is a remote round trip whose answers are
129
+ * about prompt economics, not correctness, so it runs on a slow cadence
130
+ * instead of per call.
131
+ */
132
+ export const SUGGEST_BATCH_EVERY = 20;
133
+ /**
134
+ * Whether crossing into `totalCalls` opens a new suggestion batch. True only
135
+ * on the call that MAKES a multiple (20, 40, …), so N calls trigger exactly
136
+ * floor(N/20) batches and never more — the threshold predicate is a pure
137
+ * function precisely so the hot path can ask it without any jev work.
138
+ *
139
+ * @param totalCalls - total calls AFTER the just-recorded one.
140
+ * @param every - batch cadence (default {@link SUGGEST_BATCH_EVERY}).
141
+ * @returns whether a batch should be started.
142
+ */
143
+ export function shouldRunSuggestBatch(totalCalls, every = SUGGEST_BATCH_EVERY) {
144
+ // `totalCalls < every` also rules out zero/negative totals, which would
145
+ // otherwise look like a crossing (0 is a multiple of every).
146
+ if (every < 1 || totalCalls < every)
147
+ return false;
148
+ return Math.floor(totalCalls / every) > Math.floor((totalCalls - 1) / every);
149
+ }
150
+ /**
151
+ * Build the usage store over one gate directory. The initial read is
152
+ * synchronous (boot-time, once, mirroring the gate store); writes land
153
+ * atomically (tmp file + rename) so a crash mid-write can never leave a torn
154
+ * document.
155
+ *
156
+ * @param dir - the plugin's gate directory (`resolveGateDir(...)`).
157
+ * @param warn - warning seam for a corrupt document / failed write.
158
+ * @returns the store handle.
159
+ */
160
+ export function createUsageStore(dir, warn) {
161
+ const file = usageFile(dir);
162
+ let mirror = loadInitialUsage(file, warn);
163
+ let writing = null;
164
+ let dirty = false;
165
+ let writeWarned = false;
166
+ async function writeNow() {
167
+ try {
168
+ await mkdir(dir, { recursive: true });
169
+ const payload = JSON.stringify({ tools: { ...mirror.tools } }, null, 2) + '\n';
170
+ const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
171
+ await writeFile(tmp, payload, 'utf8');
172
+ await rename(tmp, file);
173
+ }
174
+ catch (error) {
175
+ // One warning per process, not per call: an unwritable directory would
176
+ // otherwise turn every dispatch into a log line. Statistics are
177
+ // best-effort by construction (fail-open extends to the stats).
178
+ if (!writeWarned) {
179
+ writeWarned = true;
180
+ warn(`mcp-adapter: the usage statistics at ${file} could not be written `
181
+ + `(${error instanceof Error ? error.message : String(error)}) — tracking continues in memory only`);
182
+ }
183
+ }
184
+ }
185
+ function schedule() {
186
+ dirty = true;
187
+ if (writing !== null)
188
+ return;
189
+ const run = (async () => {
190
+ try {
191
+ while (dirty) {
192
+ dirty = false;
193
+ await writeNow();
194
+ }
195
+ }
196
+ finally {
197
+ writing = null;
198
+ }
199
+ })();
200
+ writing = run;
201
+ void run.catch(() => undefined);
202
+ }
203
+ return {
204
+ get: () => mirror,
205
+ total: () => usageTotalCalls(mirror),
206
+ record(tool, failed) {
207
+ mirror = recordUsageCall(mirror, tool, failed);
208
+ schedule();
209
+ return usageTotalCalls(mirror);
210
+ },
211
+ async flush() {
212
+ while (writing !== null)
213
+ await writing.catch(() => undefined);
214
+ },
215
+ };
216
+ }
217
+ /**
218
+ * Boot-time read. A missing file is the fresh-install zero state (silent); an
219
+ * unreadable or unparseable one is warned about ONCE here and degrades to
220
+ * zero statistics, so the only visible effect of a corrupt file is that
221
+ * suggestions start collecting from scratch again.
222
+ */
223
+ function loadInitialUsage(file, warn) {
224
+ if (!existsSync(file))
225
+ return { tools: {} };
226
+ try {
227
+ return normalizeUsage(JSON.parse(readFileSync(file, 'utf8')));
228
+ }
229
+ catch (error) {
230
+ warn(`mcp-adapter: the usage statistics at ${file} are unreadable `
231
+ + `(${error instanceof Error ? error.message : String(error)}) — starting from zero statistics`);
232
+ return { tools: {} };
233
+ }
234
+ }
235
+ /** A probability is usable only when it is a finite 0..1 number. */
236
+ function probability(value) {
237
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1
238
+ ? value : undefined;
239
+ }
240
+ /**
241
+ * Sanitize a parsed suggestions document into rows that are safe to render.
242
+ * Rows without a name or a usable probability are dropped rather than shown as
243
+ * "0%" — a fabricated number is worse than a missing row.
244
+ *
245
+ * @param raw - the parsed JSON (an array of rows, or anything at all).
246
+ * @returns the renderable rows, in document order.
247
+ */
248
+ export function normalizeSuggestions(raw) {
249
+ if (!Array.isArray(raw))
250
+ return [];
251
+ const out = [];
252
+ for (const entry of raw) {
253
+ if (typeof entry !== 'object' || entry === null)
254
+ continue;
255
+ const row = entry;
256
+ const p = probability(row.probability);
257
+ if (typeof row.tool !== 'string' || row.tool === '' || p === undefined)
258
+ continue;
259
+ out.push({
260
+ tool: row.tool,
261
+ probability: p,
262
+ band: row.band === 'adopt' || row.band === 'record' || row.band === 'fallback' ? row.band : 'record',
263
+ basis: typeof row.basis === 'string' ? row.basis : '',
264
+ _at: typeof row._at === 'string' ? row._at : '',
265
+ });
266
+ }
267
+ return out;
268
+ }
269
+ /**
270
+ * Replace the whole suggestion document with one batch (atomic tmp+rename;
271
+ * a crash leaves either the previous batch or the new one, never a mix).
272
+ * Throws on failure — the caller is the fire-and-forget seam, which contains
273
+ * it; a failed write means "this round's suggestions are lost", never a broken
274
+ * caller.
275
+ *
276
+ * @param dir - the plugin's gate directory.
277
+ * @param records - the batch rows.
278
+ */
279
+ export async function writeSuggestions(dir, records) {
280
+ const file = suggestionsFile(dir);
281
+ const payload = JSON.stringify(records, null, 2) + '\n';
282
+ await mkdir(dir, { recursive: true });
283
+ const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
284
+ await writeFile(tmp, payload, 'utf8');
285
+ await rename(tmp, file);
286
+ }
287
+ /**
288
+ * Read the current suggestions (empty when there are none, unreadable, or
289
+ * corrupt — the display layer's "no suggestions yet" is the same shape as
290
+ * "the file was lost", so the operator is never shown a half-truth).
291
+ *
292
+ * @param dir - the plugin's gate directory.
293
+ * @param warn - optional warning seam for an unreadable document.
294
+ * @returns the renderable rows.
295
+ */
296
+ export async function readSuggestions(dir, warn) {
297
+ try {
298
+ return normalizeSuggestions(JSON.parse(await readFile(suggestionsFile(dir), 'utf8')));
299
+ }
300
+ catch (error) {
301
+ if (warn !== undefined && error?.code !== 'ENOENT') {
302
+ warn(`mcp-adapter: the keep suggestions at ${suggestionsFile(dir)} are unreadable `
303
+ + `(${error instanceof Error ? error.message : String(error)}) — showing none`);
304
+ }
305
+ return [];
306
+ }
307
+ }
308
+ /** How much of a tool's description travels into the jev state text. */
309
+ export const SUGGEST_DESCRIPTION_CHARS = 200;
310
+ /**
311
+ * The candidate set for one keep-suggestion batch: the tools that are
312
+ * CURRENTLY FOLDED OUT of the prompt (the fold predicate is injected, so this
313
+ * function stays free of config plumbing) AND have at least one recorded call.
314
+ *
315
+ * A folded tool nobody ever called is deliberately excluded: it has no usage
316
+ * evidence to build a "keep this in every prompt" claim on, and burning a
317
+ * remote question on it would put the least informative tools first. Ordered
318
+ * by calls descending (the tools that already earn their place come first),
319
+ * name ascending as the tie-break, capped at {@link RANK_CANDIDATE_LIMIT}.
320
+ *
321
+ * @param doc - the usage mirror.
322
+ * @param schemas - visible schemas (production: `ctx.tools.schemas()`).
323
+ * @param isFolded - the live fold predicate for one name.
324
+ * @param limit - max candidates (default {@link RANK_CANDIDATE_LIMIT}).
325
+ * @returns the candidates, most-used first.
326
+ */
327
+ export function usageSuggestCandidates(doc, schemas, isFolded, limit = RANK_CANDIDATE_LIMIT) {
328
+ const byName = new Map(schemas.map(schema => [schema.name, schema]));
329
+ const out = [];
330
+ for (const [tool, stats] of Object.entries(doc.tools)) {
331
+ if (stats.calls <= 0)
332
+ continue;
333
+ if (!isFolded(tool))
334
+ continue;
335
+ const schema = byName.get(tool);
336
+ out.push({
337
+ tool,
338
+ calls: stats.calls,
339
+ errors: stats.errors,
340
+ lastUsedAt: stats.lastUsedAt,
341
+ description: (schema?.description ?? '').slice(0, SUGGEST_DESCRIPTION_CHARS),
342
+ });
343
+ }
344
+ out.sort((left, right) => (right.calls - left.calls) || left.tool.localeCompare(right.tool));
345
+ return out.slice(0, limit === Number.POSITIVE_INFINITY ? undefined : limit);
346
+ }
347
+ /** The usage evidence rendered next to a suggestion, in one line. */
348
+ export function suggestionBasis(candidate) {
349
+ const when = candidate.lastUsedAt === '' ? 'unknown' : candidate.lastUsedAt.slice(0, 10);
350
+ return `${candidate.calls} call(s), ${candidate.errors} error(s), last used ${when}`;
351
+ }
352
+ /**
353
+ * The exact `keep` config fragment a suggestion would translate to. Rendered
354
+ * as TEXT for the operator — nothing writes it (red line ③).
355
+ *
356
+ * @param tool - the suggested tool name.
357
+ * @returns a copy-pasteable keep-pattern line.
358
+ */
359
+ export function keepSuggestionFragment(tool) {
360
+ return `keep: ["${tool}"]`;
361
+ }
362
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwayds/dsh-mcp-adapter",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "dsh plugin: token-efficient prompt-side shim for the official MCP client — folds mcp__* tool schemas out of every assembled prompt and exposes two constant meta-tools (mcp_list / mcp_call) instead",
5
5
  "keywords": [
6
6
  "dsh",