mister-wolf 2.11.0 → 2.12.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/dist/adapters/cli/cli-entry.d.ts.map +1 -1
- package/dist/adapters/cli/cli-entry.js +337 -94
- package/dist/adapters/cli/cli-entry.js.map +1 -1
- package/dist/adapters/cli/commands/analytics.d.ts +1 -1
- package/dist/adapters/cli/commands/analytics.d.ts.map +1 -1
- package/dist/adapters/cli/commands/analytics.js +30 -1
- package/dist/adapters/cli/commands/analytics.js.map +1 -1
- package/dist/adapters/cli/commands/memory-brief.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-brief.js +13 -3
- package/dist/adapters/cli/commands/memory-brief.js.map +1 -1
- package/dist/adapters/cli/commands/memory-call.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-call.js +54 -3
- package/dist/adapters/cli/commands/memory-call.js.map +1 -1
- package/dist/adapters/cli/commands/memory-recap.d.ts.map +1 -1
- package/dist/adapters/cli/commands/memory-recap.js +16 -1
- package/dist/adapters/cli/commands/memory-recap.js.map +1 -1
- package/dist/adapters/fs/config-file.d.ts +8 -0
- package/dist/adapters/fs/config-file.d.ts.map +1 -1
- package/dist/adapters/fs/config-file.js +57 -2
- package/dist/adapters/fs/config-file.js.map +1 -1
- package/dist/adapters/fs/scan-snapshot-cache.d.ts +23 -0
- package/dist/adapters/fs/scan-snapshot-cache.d.ts.map +1 -0
- package/dist/adapters/fs/scan-snapshot-cache.js +36 -0
- package/dist/adapters/fs/scan-snapshot-cache.js.map +1 -0
- package/dist/adapters/fs/session-delivery-registry.d.ts +31 -0
- package/dist/adapters/fs/session-delivery-registry.d.ts.map +1 -0
- package/dist/adapters/fs/session-delivery-registry.js +104 -0
- package/dist/adapters/fs/session-delivery-registry.js.map +1 -0
- package/dist/adapters/fs/session-metrics-log.d.ts +15 -3
- package/dist/adapters/fs/session-metrics-log.d.ts.map +1 -1
- package/dist/adapters/fs/session-metrics-log.js +150 -29
- package/dist/adapters/fs/session-metrics-log.js.map +1 -1
- package/dist/adapters/mcp/mcp-schemas.d.ts +1 -1
- package/dist/adapters/mcp/mcp-tools.d.ts.map +1 -1
- package/dist/adapters/mcp/mcp-tools.js +5 -3
- package/dist/adapters/mcp/mcp-tools.js.map +1 -1
- package/dist/adapters/sqlite/sqlite-search-index.d.ts +6 -1
- package/dist/adapters/sqlite/sqlite-search-index.d.ts.map +1 -1
- package/dist/adapters/sqlite/sqlite-search-index.js +47 -25
- package/dist/adapters/sqlite/sqlite-search-index.js.map +1 -1
- package/dist/app/use-cases/build-analytics.d.ts +64 -1
- package/dist/app/use-cases/build-analytics.d.ts.map +1 -1
- package/dist/app/use-cases/build-analytics.js +157 -0
- package/dist/app/use-cases/build-analytics.js.map +1 -1
- package/dist/app/use-cases/generate-recap.d.ts +14 -0
- package/dist/app/use-cases/generate-recap.d.ts.map +1 -1
- package/dist/app/use-cases/generate-recap.js +37 -0
- package/dist/app/use-cases/generate-recap.js.map +1 -1
- package/dist/app/use-cases/get-call-injections.d.ts +6 -0
- package/dist/app/use-cases/get-call-injections.d.ts.map +1 -1
- package/dist/app/use-cases/get-call-injections.js +26 -8
- package/dist/app/use-cases/get-call-injections.js.map +1 -1
- package/dist/app/use-cases/scan-project.d.ts +26 -1
- package/dist/app/use-cases/scan-project.d.ts.map +1 -1
- package/dist/app/use-cases/scan-project.js +80 -49
- package/dist/app/use-cases/scan-project.js.map +1 -1
- package/dist/domain/router-log.d.ts +8 -2
- package/dist/domain/router-log.d.ts.map +1 -1
- package/dist/domain/router-log.js +14 -2
- package/dist/domain/router-log.js.map +1 -1
- package/dist/domain/schemas/relation-schema.d.ts +1 -1
- package/package.json +1 -1
- package/templates/opencode/plugins/wolf-router.ts +80 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan-project.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/scan-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAI9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"scan-project.d.ts","sourceRoot":"","sources":["../../../src/app/use-cases/scan-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAI9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,YAAY,EAAE,CAAC;CAC3B;AAED,gFAAgF;AAChF,MAAM,MAAM,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC1C,KAAK,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE;IACJ,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,aAAa,CAAC,EAAE,iBAAiB,CAAC;CACnC,EACD,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAa5B;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE;IACJ,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB,EACD,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,OAAO,CAAC,iBAAiB,CAAC,CAc5B;AAwID,wBAAgB,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAQhE"}
|
|
@@ -1,72 +1,93 @@
|
|
|
1
1
|
import { governanceDefaults } from '../../domain/governance.js';
|
|
2
2
|
import { documentRefId, withTieBreak } from '../../adapters/fs/document-id.js';
|
|
3
3
|
/**
|
|
4
|
-
* Кэш скана по сигнатуре дерева (T013
|
|
5
|
-
* без
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Кэш скана по сигнатуре дерева (T013 → P105: кэш персистный). sig совпал →
|
|
5
|
+
* результат из кэша без обхода дерева и побочных эффектов; не совпал →
|
|
6
|
+
* полный scanProject (diff-before-save внутри) и перезапись кэша.
|
|
7
|
+
* treeSignature отсутствует → всегда полный скан (обратная совместимость портов
|
|
8
|
+
* в тестах); snapshotCache отсутствует → скан без кэширования.
|
|
9
9
|
* Инвалидация — см. projectTreeSignature в heuristic-project-scanner.ts:
|
|
10
10
|
* dir mtime (добавление/удаление/переименование файлов), package.json, .git/HEAD;
|
|
11
11
|
* контентные правки существующих файлов НЕ инвалидируют (brief не зависит от
|
|
12
12
|
* содержимого файлов).
|
|
13
13
|
*/
|
|
14
|
-
const scanCache = new Map();
|
|
15
14
|
export async function scanProjectCached(deps, root) {
|
|
16
15
|
if (!deps.treeSignature)
|
|
17
16
|
return scanProject(deps, root);
|
|
18
17
|
const sig = await deps.treeSignature(root);
|
|
19
|
-
const
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
const cache = deps.snapshotCache;
|
|
19
|
+
if (cache) {
|
|
20
|
+
const hit = await cache.read();
|
|
21
|
+
if (hit && hit.sig === sig)
|
|
22
|
+
return { object: hit.object, snapshot: hit.snapshot, documents: hit.documents };
|
|
23
|
+
}
|
|
24
|
+
// P105: запись кэша — под lock скана (хук выполняется внутри run)
|
|
25
|
+
const persist = cache
|
|
26
|
+
? async (result) => cache.write({ ...result, sig })
|
|
27
|
+
: undefined;
|
|
28
|
+
return scanProject(deps, root, persist);
|
|
25
29
|
}
|
|
26
|
-
export async function scanProject(deps, root) {
|
|
30
|
+
export async function scanProject(deps, root, afterScan) {
|
|
27
31
|
const run = async () => {
|
|
28
32
|
const snapshot = await deps.scanner.scan(root);
|
|
29
33
|
const now = deps.clock.now();
|
|
30
34
|
const actor = 'agent:mr-wolf';
|
|
31
|
-
const
|
|
32
|
-
const object = {
|
|
33
|
-
id: 'project-scan-latest',
|
|
34
|
-
type: 'context',
|
|
35
|
-
title: `Project scan for ${snapshot.projectName}`,
|
|
36
|
-
body: renderScanBody(snapshot),
|
|
37
|
-
status: 'active',
|
|
38
|
-
review_state: 'accepted',
|
|
39
|
-
confidence: 'high',
|
|
40
|
-
importance: 0.7,
|
|
41
|
-
created_at: now.toISOString(),
|
|
42
|
-
updated_at: now.toISOString(),
|
|
43
|
-
created_by: actor,
|
|
44
|
-
schema_version: 1,
|
|
45
|
-
source: { kind: 'scan', path: snapshot.root },
|
|
46
|
-
related: { files: [], docs: [], decisions: [] },
|
|
47
|
-
tags: ['scan'],
|
|
48
|
-
superseded_by: null,
|
|
49
|
-
memory_class: defaults.memory_class,
|
|
50
|
-
truth_role: defaults.truth_role,
|
|
51
|
-
lifetime: defaults.lifetime,
|
|
52
|
-
};
|
|
53
|
-
const existingScan = await deps.store.get(object.id);
|
|
54
|
-
await deps.store.save(object);
|
|
55
|
-
await deps.log.append({
|
|
56
|
-
id: deps.idGen.generateEventId(now),
|
|
57
|
-
type: existingScan ? 'memory.scan.updated' : 'memory.added',
|
|
58
|
-
timestamp: now.toISOString(),
|
|
59
|
-
actor,
|
|
60
|
-
payload: { memory_id: object.id, type: object.type },
|
|
61
|
-
});
|
|
62
|
-
if (deps.index) {
|
|
63
|
-
await deps.index.indexObject(object);
|
|
64
|
-
}
|
|
35
|
+
const object = await upsertScanObject(deps, snapshot, now, actor);
|
|
65
36
|
const documents = await registerDocuments(deps, snapshot, now, actor);
|
|
66
|
-
|
|
37
|
+
const result = { object, snapshot, documents };
|
|
38
|
+
if (afterScan)
|
|
39
|
+
await afterScan(result);
|
|
40
|
+
return result;
|
|
67
41
|
};
|
|
68
42
|
return deps.lock ? deps.lock.withLock(run) : run();
|
|
69
43
|
}
|
|
44
|
+
const SCAN_OBJECT_ID = 'project-scan-latest';
|
|
45
|
+
/**
|
|
46
|
+
* Scan-объект project-scan-latest с diff-before-save (P105): title+body
|
|
47
|
+
* (renderScanBody детерминирован) не изменились → ни save, ни event, ни index;
|
|
48
|
+
* возвращается existing, updated_at не тикает.
|
|
49
|
+
*/
|
|
50
|
+
async function upsertScanObject(deps, snapshot, now, actor) {
|
|
51
|
+
const title = `Project scan for ${snapshot.projectName}`;
|
|
52
|
+
const body = renderScanBody(snapshot);
|
|
53
|
+
const existing = await deps.store.get(SCAN_OBJECT_ID);
|
|
54
|
+
if (existing && existing.title === title && existing.body === body)
|
|
55
|
+
return existing;
|
|
56
|
+
const defaults = governanceDefaults(actor);
|
|
57
|
+
const object = {
|
|
58
|
+
id: SCAN_OBJECT_ID,
|
|
59
|
+
type: 'context',
|
|
60
|
+
title,
|
|
61
|
+
body,
|
|
62
|
+
status: 'active',
|
|
63
|
+
review_state: 'accepted',
|
|
64
|
+
confidence: 'high',
|
|
65
|
+
importance: 0.7,
|
|
66
|
+
created_at: existing?.created_at ?? now.toISOString(),
|
|
67
|
+
updated_at: now.toISOString(),
|
|
68
|
+
created_by: actor,
|
|
69
|
+
schema_version: 1,
|
|
70
|
+
source: { kind: 'scan', path: snapshot.root },
|
|
71
|
+
related: { files: [], docs: [], decisions: [] },
|
|
72
|
+
tags: ['scan'],
|
|
73
|
+
superseded_by: null,
|
|
74
|
+
memory_class: defaults.memory_class,
|
|
75
|
+
truth_role: defaults.truth_role,
|
|
76
|
+
lifetime: defaults.lifetime,
|
|
77
|
+
};
|
|
78
|
+
await deps.store.save(object);
|
|
79
|
+
await deps.log.append({
|
|
80
|
+
id: deps.idGen.generateEventId(now),
|
|
81
|
+
type: existing ? 'memory.scan.updated' : 'memory.added',
|
|
82
|
+
timestamp: now.toISOString(),
|
|
83
|
+
actor,
|
|
84
|
+
payload: { memory_id: object.id, type: object.type },
|
|
85
|
+
});
|
|
86
|
+
if (deps.index) {
|
|
87
|
+
await deps.index.indexObject(object);
|
|
88
|
+
}
|
|
89
|
+
return object;
|
|
90
|
+
}
|
|
70
91
|
async function registerDocuments(deps, snapshot, now, actor) {
|
|
71
92
|
const results = [];
|
|
72
93
|
const defaults = governanceDefaults(actor);
|
|
@@ -80,6 +101,16 @@ async function registerDocuments(deps, snapshot, now, actor) {
|
|
|
80
101
|
const takenIds = new Set((await deps.store.list()).map((o) => o.id));
|
|
81
102
|
for (const doc of snapshot.docs) {
|
|
82
103
|
const existing = existingByPath.get(doc.path);
|
|
104
|
+
const createdAt = existing?.created_at ?? now.toISOString();
|
|
105
|
+
// P105 diff-before-save: title/path/created_at не изменились → ни save, ни
|
|
106
|
+
// event, ни index; возвращается existing, updated_at не тикает.
|
|
107
|
+
if (existing &&
|
|
108
|
+
existing.title === doc.title &&
|
|
109
|
+
existing.source?.path === doc.path &&
|
|
110
|
+
existing.created_at === createdAt) {
|
|
111
|
+
results.push(existing);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
83
114
|
// Скан не мигрирует (§2.1): у существующего объекта id сохраняется как есть
|
|
84
115
|
// (даже легаси doc_*); канонический id — только для новых объектов.
|
|
85
116
|
const id = existing ? existing.id : withTieBreak(documentRefId(doc.path, now.toISOString()), takenIds);
|
|
@@ -93,7 +124,7 @@ async function registerDocuments(deps, snapshot, now, actor) {
|
|
|
93
124
|
review_state: 'accepted',
|
|
94
125
|
confidence: 'high',
|
|
95
126
|
importance: 0.6,
|
|
96
|
-
created_at:
|
|
127
|
+
created_at: createdAt,
|
|
97
128
|
updated_at: now.toISOString(),
|
|
98
129
|
created_by: existing?.created_by ?? actor,
|
|
99
130
|
schema_version: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan-project.js","sourceRoot":"","sources":["../../../src/app/use-cases/scan-project.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"scan-project.js","sourceRoot":"","sources":["../../../src/app/use-cases/scan-project.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* Пишет плагин wolf-router (templates/opencode/plugins/wolf-router.ts):
|
|
4
4
|
* `<ISO> agent-id=<id> playbook=hit name=<mem-id> variant=canonical injected=yes`
|
|
5
5
|
* `<ISO> agent-id=<id> playbook=miss injected=no`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* P106 (волна 2.12): строка дополняется `ms=<resolve>` и `bytes=<playbook bytes>`
|
|
7
|
+
* (nullable — старые строки полей не имеют). Старые файлы могут не иметь
|
|
8
|
+
* name/variant. Парсинг k=v парами (не позиционно), чтобы пережить будущие
|
|
9
|
+
* поля; строка валидна ⇔ есть agent-id И playbook=hit|miss.
|
|
8
10
|
* Битая строка не роняет аналитику — только malformedLines (прецедент readJsonl).
|
|
9
11
|
*/
|
|
10
12
|
export interface RouterLogRow {
|
|
@@ -13,6 +15,10 @@ export interface RouterLogRow {
|
|
|
13
15
|
hit: boolean;
|
|
14
16
|
playbookId: string | null;
|
|
15
17
|
variant: string | null;
|
|
18
|
+
/** P106: длительность resolve, мс (нет в старых строках). */
|
|
19
|
+
ms: number | null;
|
|
20
|
+
/** P106: размер инъекции playbook, байты (нет в старых строках). */
|
|
21
|
+
bytes: number | null;
|
|
16
22
|
}
|
|
17
23
|
export declare function parseRouterLog(text: string): {
|
|
18
24
|
rows: RouterLogRow[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-log.d.ts","sourceRoot":"","sources":["../../src/domain/router-log.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"router-log.d.ts","sourceRoot":"","sources":["../../src/domain/router-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,6DAA6D;IAC7D,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,oEAAoE;IACpE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAW7F"}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* Пишет плагин wolf-router (templates/opencode/plugins/wolf-router.ts):
|
|
4
4
|
* `<ISO> agent-id=<id> playbook=hit name=<mem-id> variant=canonical injected=yes`
|
|
5
5
|
* `<ISO> agent-id=<id> playbook=miss injected=no`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* P106 (волна 2.12): строка дополняется `ms=<resolve>` и `bytes=<playbook bytes>`
|
|
7
|
+
* (nullable — старые строки полей не имеют). Старые файлы могут не иметь
|
|
8
|
+
* name/variant. Парсинг k=v парами (не позиционно), чтобы пережить будущие
|
|
9
|
+
* поля; строка валидна ⇔ есть agent-id И playbook=hit|miss.
|
|
8
10
|
* Битая строка не роняет аналитику — только malformedLines (прецедент readJsonl).
|
|
9
11
|
*/
|
|
10
12
|
export function parseRouterLog(text) {
|
|
@@ -40,12 +42,22 @@ function parseLine(line) {
|
|
|
40
42
|
return null;
|
|
41
43
|
const name = kv.get('name');
|
|
42
44
|
const variant = kv.get('variant');
|
|
45
|
+
// P106: ms/bytes — целые числа; нечисловое/отсутствующее → null (толерантность)
|
|
46
|
+
const num = (key) => {
|
|
47
|
+
const v = kv.get(key);
|
|
48
|
+
if (v === undefined || !/^\d+$/.test(v))
|
|
49
|
+
return null;
|
|
50
|
+
const n = Number(v);
|
|
51
|
+
return Number.isSafeInteger(n) ? n : null;
|
|
52
|
+
};
|
|
43
53
|
return {
|
|
44
54
|
ts,
|
|
45
55
|
agentId,
|
|
46
56
|
hit: playbook === 'hit',
|
|
47
57
|
playbookId: name !== undefined && name !== '' ? name : null,
|
|
48
58
|
variant: variant !== undefined && variant !== '' ? variant : null,
|
|
59
|
+
ms: num('ms'),
|
|
60
|
+
bytes: num('bytes'),
|
|
49
61
|
};
|
|
50
62
|
}
|
|
51
63
|
//# sourceMappingURL=router-log.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-log.js","sourceRoot":"","sources":["../../src/domain/router-log.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"router-log.js","sourceRoot":"","sources":["../../src/domain/router-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,10 +4,10 @@ export declare const RelationSchema: z.ZodObject<{
|
|
|
4
4
|
id: z.ZodString;
|
|
5
5
|
subject: z.ZodString;
|
|
6
6
|
predicate: z.ZodEnum<{
|
|
7
|
+
superseded_by: "superseded_by";
|
|
7
8
|
answers: "answers";
|
|
8
9
|
supports: "supports";
|
|
9
10
|
owner_skill: "owner_skill";
|
|
10
|
-
superseded_by: "superseded_by";
|
|
11
11
|
answered_by: "answered_by";
|
|
12
12
|
supported_by: "supported_by";
|
|
13
13
|
based_on: "based_on";
|
package/package.json
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
* доставка вместо вероятностного wolf search агентом. Маркер
|
|
6
6
|
* `agent-id: <id>` В ТЕЛЕ рамки агента (frontmatter в system-промпт не
|
|
7
7
|
* попадает — известная грабля) → wolf search --type playbook → get +
|
|
8
|
-
* гвард owner_skill === agentId | `skill:${agentId}` (legacy) →
|
|
9
|
-
*
|
|
8
|
+
* гвард owner_skill === agentId | `skill:${agentId}` (legacy) → первый
|
|
9
|
+
* прошедший гвард кандидат (ранний стоп, A2-б) → инжект в system-промпт
|
|
10
|
+
* на каждое сообщение.
|
|
10
11
|
*
|
|
11
12
|
* Fallback (T012, волна 1.1): канон приоритетен; при miss для ЛЮБОГО
|
|
12
13
|
* agent-id инъецируется встроенный универсальный FALLBACK_PLAYBOOK —
|
|
@@ -16,8 +17,8 @@
|
|
|
16
17
|
*
|
|
17
18
|
* Ноль зависимостей (Node stdlib; ai-sdk НЕ используется). Fail-safe: всё в
|
|
18
19
|
* try/catch — плагин не имеет права уронить сессию (лог: .wolf/router.log —
|
|
19
|
-
* agent-id, name, variant, injected). Через этот файл при рендере
|
|
20
|
-
* подстановка {{tool.*}} и штамп `// wolf:rendered` (ставит рендерер).
|
|
20
|
+
* agent-id, name, variant, injected, ms, bytes). Через этот файл при рендере
|
|
21
|
+
* проходят подстановка {{tool.*}} и штамп `// wolf:rendered` (ставит рендерер).
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
24
|
import path from 'path';
|
|
@@ -52,19 +53,22 @@ const FALLBACK_PLAYBOOK = `# Универсальный playbook (fallback)
|
|
|
52
53
|
причина; обошёл через <что сработало>\`), не молча и не ретраи в стол.`;
|
|
53
54
|
// [ \t] вместо \s: \s съедает переводы строк и вытаскивает id с чужой строки.
|
|
54
55
|
const AGENT_ID_RE = /^agent-id:[ \t]*([\w-]+)[ \t]*$/m;
|
|
55
|
-
|
|
56
|
+
// Спека A2: playbook — canonical-память, Стюард мутирует редко → TTL 5 минут.
|
|
57
|
+
// Негативный кэш (null) живёт тем же TTL — повторный miss не спавнит CLI.
|
|
58
|
+
const CACHE_TTL_MS = 300_000;
|
|
59
|
+
|
|
60
|
+
// agent-id последней рамки, пропущенной через system.transform (для skill-метрики B3)
|
|
61
|
+
let lastAgentId: string | null = null;
|
|
56
62
|
|
|
57
63
|
const run = promisify(execFile);
|
|
58
64
|
// execFile: args array, no shell. Целевой проект — глобальный `wolf`;
|
|
59
65
|
// догфуд в репо Wolf — локальный dist. Ошибка обоих → исключение наверх (fail-safe).
|
|
60
|
-
//
|
|
61
|
-
//
|
|
66
|
+
// WOLF_SESSION (4.C): ключ ставится фабрикой ОДИН раз на процесс opencode —
|
|
67
|
+
// спавны и bash-вызовы волка наследуют его из process.env (execFile без
|
|
68
|
+
// env-поля наследует сам). Известный потолок: несколько чатов одного процесса
|
|
69
|
+
// opencode шарят ключ — консервативная недо-дедупликация, не ошибка.
|
|
62
70
|
const runWolf = (args: string[]): Promise<{ stdout: string }> => {
|
|
63
|
-
const opts = {
|
|
64
|
-
cwd: PROJECT_ROOT,
|
|
65
|
-
timeout: 5000,
|
|
66
|
-
env: { ...process.env, WOLF_SESSION: 'opc-' + randomUUID() },
|
|
67
|
-
};
|
|
71
|
+
const opts = { cwd: PROJECT_ROOT, timeout: 5000 };
|
|
68
72
|
return run('wolf', args, opts).catch(() => run('node', [LOCAL_CLI, ...args], opts));
|
|
69
73
|
};
|
|
70
74
|
|
|
@@ -77,7 +81,8 @@ function logRoute(line: string): void {
|
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
|
|
80
|
-
// ponytail: per-agent кэш
|
|
84
|
+
// ponytail: per-agent кэш на TTL 5 мин — canonical-память мутируется редко,
|
|
85
|
+
// CLI-спавн не на каждое сообщение.
|
|
81
86
|
const cache = new Map<string, { value: { id: string; body: string } | null; at: number }>();
|
|
82
87
|
|
|
83
88
|
async function resolvePlaybook(agentId: string): Promise<{ id: string; body: string } | null> {
|
|
@@ -87,20 +92,17 @@ async function resolvePlaybook(agentId: string): Promise<{ id: string; body: str
|
|
|
87
92
|
try {
|
|
88
93
|
const { stdout } = await runWolf(['search', agentId, '--type', 'playbook', '--hide-superseded']);
|
|
89
94
|
const ids = [...stdout.matchAll(/^([\w-]+) \[playbook\]/gm)].map((m) => m[1]);
|
|
90
|
-
|
|
91
|
-
|
|
95
|
+
// Ранний стоп (спека A2-б): релевантность поиска уже отсортировала,
|
|
96
|
+
// --hide-superseded отсекает старые версии — первый кандидат, прошедший
|
|
97
|
+
// гвард владельца, и есть результат (один get при miss вместо K подряд).
|
|
92
98
|
for (const id of ids) {
|
|
93
99
|
const { stdout: json } = await runWolf(['get', id]);
|
|
94
100
|
const obj = JSON.parse(json);
|
|
95
101
|
const owner = obj.owner_skill ?? obj.extra?.owner_skill;
|
|
96
102
|
if (owner !== agentId && owner !== `skill:${agentId}`) continue; // гвард владельца
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
bestVersion = version;
|
|
100
|
-
best = obj;
|
|
101
|
-
}
|
|
103
|
+
if (obj.body) found = { id: String(obj.id ?? id), body: obj.body };
|
|
104
|
+
break;
|
|
102
105
|
}
|
|
103
|
-
found = best?.body ? { id: String(best.id ?? ''), body: best.body } : null;
|
|
104
106
|
} catch {
|
|
105
107
|
/* fail-safe: без playbook — рамка работает через wolf search */
|
|
106
108
|
}
|
|
@@ -108,25 +110,61 @@ async function resolvePlaybook(agentId: string): Promise<{ id: string; body: str
|
|
|
108
110
|
return found;
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
export const WolfPlaybookPlugin = async () =>
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
export const WolfPlaybookPlugin = async () => {
|
|
114
|
+
// 4.C: один WOLF_SESSION на процесс opencode — спавны волка и bash-вызовы
|
|
115
|
+
// наследуют ключ. Известный потолок: несколько чатов одного процесса
|
|
116
|
+
// opencode шарят ключ — консервативная недо-дедупликация.
|
|
117
|
+
if (!process.env.WOLF_SESSION) process.env.WOLF_SESSION = 'opc-' + randomUUID();
|
|
118
|
+
return {
|
|
119
|
+
'experimental.chat.system.transform': async (_input, output) => {
|
|
120
|
+
try {
|
|
121
|
+
const joined = output.system.join('\n');
|
|
122
|
+
const m = joined.match(AGENT_ID_RE);
|
|
123
|
+
if (!m) return; // рамка без маркера — не наша забота
|
|
124
|
+
if (joined.includes(INJECT_HEADER)) return; // идемпотентность: не вставляем дважды
|
|
125
|
+
const agentId = m[1];
|
|
126
|
+
lastAgentId = agentId; // агент известен хуку skill-метрики (B3)
|
|
127
|
+
const startedAt = Date.now();
|
|
128
|
+
const resolved = await resolvePlaybook(agentId);
|
|
129
|
+
const ms = Date.now() - startedAt;
|
|
130
|
+
if (resolved) {
|
|
131
|
+
output.system.push(`\n\n${INJECT_HEADER}\n\n${resolved.body}`);
|
|
132
|
+
logRoute(
|
|
133
|
+
`agent-id=${agentId} playbook=hit name=${resolved.id} variant=canonical injected=yes` +
|
|
134
|
+
` ms=${ms} bytes=${Buffer.byteLength(resolved.body)}`
|
|
135
|
+
);
|
|
136
|
+
} else {
|
|
137
|
+
// T012: miss канона → универсальный fallback; инъекция для любого agent-id
|
|
138
|
+
output.system.push(`\n\n${INJECT_HEADER}\n\n${FALLBACK_PLAYBOOK}`);
|
|
139
|
+
logRoute(
|
|
140
|
+
`agent-id=${agentId} playbook=hit name=fallback variant=fallback injected=yes` +
|
|
141
|
+
` ms=${ms} bytes=${Buffer.byteLength(FALLBACK_PLAYBOOK)}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
/* fail-safe: не роняем сессию */
|
|
127
146
|
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
147
|
+
},
|
|
148
|
+
// B3: метрика вызовов скиллов. Форма входа по докам opencode: input.tool —
|
|
149
|
+
// имя тула, output.args — объект аргументов (name | skill — фолбэк).
|
|
150
|
+
// Отдельный JSONL-файл — инвариант: enum событий SignalEventSchema закрытый,
|
|
151
|
+
// в общий router.log эти события класть нельзя. WOLF_SKILL_LOG — тест-шов
|
|
152
|
+
// (читается на каждый вызов: env ставится тестами уже после импорта модуля).
|
|
153
|
+
'tool.execute.before': async (input: unknown, output: unknown) => {
|
|
154
|
+
try {
|
|
155
|
+
if ((input as { tool?: string } | null)?.tool !== 'skill') return;
|
|
156
|
+
const args = (output as { args?: { name?: string; skill?: string } } | null)?.args;
|
|
157
|
+
const skill = args?.name ?? args?.skill;
|
|
158
|
+
if (!skill) return;
|
|
159
|
+
const file =
|
|
160
|
+
process.env.WOLF_SKILL_LOG ?? path.join(PROJECT_ROOT, '.wolf', 'metrics', 'skill-invocations.jsonl');
|
|
161
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
162
|
+
const entry: { ts: string; skill: string; agent?: string } = { ts: new Date().toISOString(), skill };
|
|
163
|
+
if (lastAgentId) entry.agent = lastAgentId;
|
|
164
|
+
fs.appendFileSync(file, `${JSON.stringify(entry)}\n`);
|
|
165
|
+
} catch {
|
|
166
|
+
/* fail-safe: падение метрики не роняет сессию */
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
};
|