@soleri/core 2.1.0 → 2.5.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/brain/brain.d.ts +10 -1
- package/dist/brain/brain.d.ts.map +1 -1
- package/dist/brain/brain.js +116 -13
- package/dist/brain/brain.js.map +1 -1
- package/dist/brain/intelligence.d.ts +36 -1
- package/dist/brain/intelligence.d.ts.map +1 -1
- package/dist/brain/intelligence.js +119 -14
- package/dist/brain/intelligence.js.map +1 -1
- package/dist/brain/types.d.ts +34 -2
- package/dist/brain/types.d.ts.map +1 -1
- package/dist/cognee/client.d.ts +3 -0
- package/dist/cognee/client.d.ts.map +1 -1
- package/dist/cognee/client.js +17 -0
- package/dist/cognee/client.js.map +1 -1
- package/dist/cognee/sync-manager.d.ts +94 -0
- package/dist/cognee/sync-manager.d.ts.map +1 -0
- package/dist/cognee/sync-manager.js +293 -0
- package/dist/cognee/sync-manager.js.map +1 -0
- package/dist/control/identity-manager.d.ts +22 -0
- package/dist/control/identity-manager.d.ts.map +1 -0
- package/dist/control/identity-manager.js +233 -0
- package/dist/control/identity-manager.js.map +1 -0
- package/dist/control/intent-router.d.ts +32 -0
- package/dist/control/intent-router.d.ts.map +1 -0
- package/dist/control/intent-router.js +242 -0
- package/dist/control/intent-router.js.map +1 -0
- package/dist/control/types.d.ts +68 -0
- package/dist/control/types.d.ts.map +1 -0
- package/dist/control/types.js +9 -0
- package/dist/control/types.js.map +1 -0
- package/dist/curator/curator.d.ts +37 -1
- package/dist/curator/curator.d.ts.map +1 -1
- package/dist/curator/curator.js +199 -1
- package/dist/curator/curator.js.map +1 -1
- package/dist/errors/classify.d.ts +13 -0
- package/dist/errors/classify.d.ts.map +1 -0
- package/dist/errors/classify.js +97 -0
- package/dist/errors/classify.js.map +1 -0
- package/dist/errors/index.d.ts +6 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/retry.d.ts +40 -0
- package/dist/errors/retry.d.ts.map +1 -0
- package/dist/errors/retry.js +97 -0
- package/dist/errors/retry.js.map +1 -0
- package/dist/errors/types.d.ts +48 -0
- package/dist/errors/types.d.ts.map +1 -0
- package/dist/errors/types.js +59 -0
- package/dist/errors/types.js.map +1 -0
- package/dist/facades/types.d.ts +1 -1
- package/dist/governance/governance.d.ts +42 -0
- package/dist/governance/governance.d.ts.map +1 -0
- package/dist/governance/governance.js +488 -0
- package/dist/governance/governance.js.map +1 -0
- package/dist/governance/index.d.ts +3 -0
- package/dist/governance/index.d.ts.map +1 -0
- package/dist/governance/index.js +2 -0
- package/dist/governance/index.js.map +1 -0
- package/dist/governance/types.d.ts +102 -0
- package/dist/governance/types.d.ts.map +1 -0
- package/dist/governance/types.js +3 -0
- package/dist/governance/types.js.map +1 -0
- package/dist/index.d.ts +52 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +47 -1
- package/dist/index.js.map +1 -1
- package/dist/intake/content-classifier.d.ts +14 -0
- package/dist/intake/content-classifier.d.ts.map +1 -0
- package/dist/intake/content-classifier.js +125 -0
- package/dist/intake/content-classifier.js.map +1 -0
- package/dist/intake/dedup-gate.d.ts +17 -0
- package/dist/intake/dedup-gate.d.ts.map +1 -0
- package/dist/intake/dedup-gate.js +66 -0
- package/dist/intake/dedup-gate.js.map +1 -0
- package/dist/intake/intake-pipeline.d.ts +63 -0
- package/dist/intake/intake-pipeline.d.ts.map +1 -0
- package/dist/intake/intake-pipeline.js +373 -0
- package/dist/intake/intake-pipeline.js.map +1 -0
- package/dist/intake/types.d.ts +65 -0
- package/dist/intake/types.d.ts.map +1 -0
- package/dist/intake/types.js +3 -0
- package/dist/intake/types.js.map +1 -0
- package/dist/intelligence/loader.js +1 -1
- package/dist/intelligence/loader.js.map +1 -1
- package/dist/intelligence/types.d.ts +3 -1
- package/dist/intelligence/types.d.ts.map +1 -1
- package/dist/logging/logger.d.ts +37 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +145 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/logging/types.d.ts +19 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +2 -0
- package/dist/logging/types.js.map +1 -0
- package/dist/loop/loop-manager.d.ts +100 -0
- package/dist/loop/loop-manager.d.ts.map +1 -0
- package/dist/loop/loop-manager.js +379 -0
- package/dist/loop/loop-manager.js.map +1 -0
- package/dist/loop/types.d.ts +103 -0
- package/dist/loop/types.d.ts.map +1 -0
- package/dist/loop/types.js +11 -0
- package/dist/loop/types.js.map +1 -0
- package/dist/persistence/index.d.ts +3 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +2 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/sqlite-provider.d.ts +25 -0
- package/dist/persistence/sqlite-provider.d.ts.map +1 -0
- package/dist/persistence/sqlite-provider.js +59 -0
- package/dist/persistence/sqlite-provider.js.map +1 -0
- package/dist/persistence/types.d.ts +36 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +8 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/planning/gap-analysis.d.ts +72 -0
- package/dist/planning/gap-analysis.d.ts.map +1 -0
- package/dist/planning/gap-analysis.js +442 -0
- package/dist/planning/gap-analysis.js.map +1 -0
- package/dist/planning/gap-types.d.ts +29 -0
- package/dist/planning/gap-types.d.ts.map +1 -0
- package/dist/planning/gap-types.js +28 -0
- package/dist/planning/gap-types.js.map +1 -0
- package/dist/planning/planner.d.ts +421 -4
- package/dist/planning/planner.d.ts.map +1 -1
- package/dist/planning/planner.js +949 -21
- package/dist/planning/planner.js.map +1 -1
- package/dist/playbooks/generic/brainstorming.d.ts +9 -0
- package/dist/playbooks/generic/brainstorming.d.ts.map +1 -0
- package/dist/playbooks/generic/brainstorming.js +105 -0
- package/dist/playbooks/generic/brainstorming.js.map +1 -0
- package/dist/playbooks/generic/code-review.d.ts +11 -0
- package/dist/playbooks/generic/code-review.d.ts.map +1 -0
- package/dist/playbooks/generic/code-review.js +176 -0
- package/dist/playbooks/generic/code-review.js.map +1 -0
- package/dist/playbooks/generic/subagent-execution.d.ts +9 -0
- package/dist/playbooks/generic/subagent-execution.d.ts.map +1 -0
- package/dist/playbooks/generic/subagent-execution.js +68 -0
- package/dist/playbooks/generic/subagent-execution.js.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts +9 -0
- package/dist/playbooks/generic/systematic-debugging.d.ts.map +1 -0
- package/dist/playbooks/generic/systematic-debugging.js +87 -0
- package/dist/playbooks/generic/systematic-debugging.js.map +1 -0
- package/dist/playbooks/generic/tdd.d.ts +9 -0
- package/dist/playbooks/generic/tdd.d.ts.map +1 -0
- package/dist/playbooks/generic/tdd.js +70 -0
- package/dist/playbooks/generic/tdd.js.map +1 -0
- package/dist/playbooks/generic/verification.d.ts +9 -0
- package/dist/playbooks/generic/verification.d.ts.map +1 -0
- package/dist/playbooks/generic/verification.js +74 -0
- package/dist/playbooks/generic/verification.js.map +1 -0
- package/dist/playbooks/index.d.ts +4 -0
- package/dist/playbooks/index.d.ts.map +1 -0
- package/dist/playbooks/index.js +5 -0
- package/dist/playbooks/index.js.map +1 -0
- package/dist/playbooks/playbook-registry.d.ts +42 -0
- package/dist/playbooks/playbook-registry.d.ts.map +1 -0
- package/dist/playbooks/playbook-registry.js +227 -0
- package/dist/playbooks/playbook-registry.js.map +1 -0
- package/dist/playbooks/playbook-seeder.d.ts +47 -0
- package/dist/playbooks/playbook-seeder.d.ts.map +1 -0
- package/dist/playbooks/playbook-seeder.js +104 -0
- package/dist/playbooks/playbook-seeder.js.map +1 -0
- package/dist/playbooks/playbook-types.d.ts +132 -0
- package/dist/playbooks/playbook-types.d.ts.map +1 -0
- package/dist/playbooks/playbook-types.js +12 -0
- package/dist/playbooks/playbook-types.js.map +1 -0
- package/dist/project/project-registry.d.ts +79 -0
- package/dist/project/project-registry.d.ts.map +1 -0
- package/dist/project/project-registry.js +274 -0
- package/dist/project/project-registry.js.map +1 -0
- package/dist/project/types.d.ts +28 -0
- package/dist/project/types.d.ts.map +1 -0
- package/dist/project/types.js +5 -0
- package/dist/project/types.js.map +1 -0
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +3 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/parser.d.ts +17 -0
- package/dist/prompts/parser.d.ts.map +1 -0
- package/dist/prompts/parser.js +47 -0
- package/dist/prompts/parser.js.map +1 -0
- package/dist/prompts/template-manager.d.ts +25 -0
- package/dist/prompts/template-manager.d.ts.map +1 -0
- package/dist/prompts/template-manager.js +71 -0
- package/dist/prompts/template-manager.js.map +1 -0
- package/dist/prompts/types.d.ts +26 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +5 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/runtime/admin-extra-ops.d.ts +15 -0
- package/dist/runtime/admin-extra-ops.d.ts.map +1 -0
- package/dist/runtime/admin-extra-ops.js +595 -0
- package/dist/runtime/admin-extra-ops.js.map +1 -0
- package/dist/runtime/admin-ops.d.ts +15 -0
- package/dist/runtime/admin-ops.d.ts.map +1 -0
- package/dist/runtime/admin-ops.js +329 -0
- package/dist/runtime/admin-ops.js.map +1 -0
- package/dist/runtime/capture-ops.d.ts +15 -0
- package/dist/runtime/capture-ops.d.ts.map +1 -0
- package/dist/runtime/capture-ops.js +363 -0
- package/dist/runtime/capture-ops.js.map +1 -0
- package/dist/runtime/cognee-sync-ops.d.ts +12 -0
- package/dist/runtime/cognee-sync-ops.d.ts.map +1 -0
- package/dist/runtime/cognee-sync-ops.js +55 -0
- package/dist/runtime/cognee-sync-ops.js.map +1 -0
- package/dist/runtime/core-ops.d.ts +9 -3
- package/dist/runtime/core-ops.d.ts.map +1 -1
- package/dist/runtime/core-ops.js +693 -10
- package/dist/runtime/core-ops.js.map +1 -1
- package/dist/runtime/curator-extra-ops.d.ts +9 -0
- package/dist/runtime/curator-extra-ops.d.ts.map +1 -0
- package/dist/runtime/curator-extra-ops.js +71 -0
- package/dist/runtime/curator-extra-ops.js.map +1 -0
- package/dist/runtime/domain-ops.d.ts.map +1 -1
- package/dist/runtime/domain-ops.js +61 -15
- package/dist/runtime/domain-ops.js.map +1 -1
- package/dist/runtime/grading-ops.d.ts +14 -0
- package/dist/runtime/grading-ops.d.ts.map +1 -0
- package/dist/runtime/grading-ops.js +105 -0
- package/dist/runtime/grading-ops.js.map +1 -0
- package/dist/runtime/intake-ops.d.ts +14 -0
- package/dist/runtime/intake-ops.d.ts.map +1 -0
- package/dist/runtime/intake-ops.js +110 -0
- package/dist/runtime/intake-ops.js.map +1 -0
- package/dist/runtime/loop-ops.d.ts +14 -0
- package/dist/runtime/loop-ops.d.ts.map +1 -0
- package/dist/runtime/loop-ops.js +251 -0
- package/dist/runtime/loop-ops.js.map +1 -0
- package/dist/runtime/memory-cross-project-ops.d.ts +12 -0
- package/dist/runtime/memory-cross-project-ops.d.ts.map +1 -0
- package/dist/runtime/memory-cross-project-ops.js +165 -0
- package/dist/runtime/memory-cross-project-ops.js.map +1 -0
- package/dist/runtime/memory-extra-ops.d.ts +13 -0
- package/dist/runtime/memory-extra-ops.d.ts.map +1 -0
- package/dist/runtime/memory-extra-ops.js +173 -0
- package/dist/runtime/memory-extra-ops.js.map +1 -0
- package/dist/runtime/orchestrate-ops.d.ts +17 -0
- package/dist/runtime/orchestrate-ops.d.ts.map +1 -0
- package/dist/runtime/orchestrate-ops.js +246 -0
- package/dist/runtime/orchestrate-ops.js.map +1 -0
- package/dist/runtime/planning-extra-ops.d.ts +25 -0
- package/dist/runtime/planning-extra-ops.d.ts.map +1 -0
- package/dist/runtime/planning-extra-ops.js +663 -0
- package/dist/runtime/planning-extra-ops.js.map +1 -0
- package/dist/runtime/playbook-ops.d.ts +14 -0
- package/dist/runtime/playbook-ops.d.ts.map +1 -0
- package/dist/runtime/playbook-ops.js +141 -0
- package/dist/runtime/playbook-ops.js.map +1 -0
- package/dist/runtime/project-ops.d.ts +15 -0
- package/dist/runtime/project-ops.d.ts.map +1 -0
- package/dist/runtime/project-ops.js +186 -0
- package/dist/runtime/project-ops.js.map +1 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +65 -3
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/types.d.ts +29 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/vault-extra-ops.d.ts +10 -0
- package/dist/runtime/vault-extra-ops.d.ts.map +1 -0
- package/dist/runtime/vault-extra-ops.js +536 -0
- package/dist/runtime/vault-extra-ops.js.map +1 -0
- package/dist/telemetry/telemetry.d.ts +48 -0
- package/dist/telemetry/telemetry.d.ts.map +1 -0
- package/dist/telemetry/telemetry.js +87 -0
- package/dist/telemetry/telemetry.js.map +1 -0
- package/dist/vault/playbook.d.ts +34 -0
- package/dist/vault/playbook.d.ts.map +1 -0
- package/dist/vault/playbook.js +60 -0
- package/dist/vault/playbook.js.map +1 -0
- package/dist/vault/vault.d.ts +97 -4
- package/dist/vault/vault.d.ts.map +1 -1
- package/dist/vault/vault.js +424 -65
- package/dist/vault/vault.js.map +1 -1
- package/package.json +7 -3
- package/src/__tests__/admin-extra-ops.test.ts +467 -0
- package/src/__tests__/admin-ops.test.ts +271 -0
- package/src/__tests__/brain-intelligence.test.ts +205 -0
- package/src/__tests__/brain.test.ts +134 -3
- package/src/__tests__/capture-ops.test.ts +509 -0
- package/src/__tests__/cognee-integration.test.ts +80 -0
- package/src/__tests__/cognee-sync-manager.test.ts +103 -0
- package/src/__tests__/core-ops.test.ts +292 -2
- package/src/__tests__/curator-extra-ops.test.ts +381 -0
- package/src/__tests__/domain-ops.test.ts +66 -0
- package/src/__tests__/errors.test.ts +388 -0
- package/src/__tests__/governance.test.ts +522 -0
- package/src/__tests__/grading-ops.test.ts +361 -0
- package/src/__tests__/identity-manager.test.ts +243 -0
- package/src/__tests__/intake-pipeline.test.ts +162 -0
- package/src/__tests__/intent-router.test.ts +222 -0
- package/src/__tests__/logger.test.ts +200 -0
- package/src/__tests__/loop-ops.test.ts +469 -0
- package/src/__tests__/memory-cross-project-ops.test.ts +248 -0
- package/src/__tests__/memory-extra-ops.test.ts +352 -0
- package/src/__tests__/orchestrate-ops.test.ts +289 -0
- package/src/__tests__/persistence.test.ts +225 -0
- package/src/__tests__/planner.test.ts +416 -7
- package/src/__tests__/planning-extra-ops.test.ts +706 -0
- package/src/__tests__/playbook-registry.test.ts +326 -0
- package/src/__tests__/playbook-seeder.test.ts +163 -0
- package/src/__tests__/playbook.test.ts +389 -0
- package/src/__tests__/project-ops.test.ts +381 -0
- package/src/__tests__/template-manager.test.ts +222 -0
- package/src/__tests__/vault-extra-ops.test.ts +482 -0
- package/src/brain/brain.ts +185 -16
- package/src/brain/intelligence.ts +179 -10
- package/src/brain/types.ts +40 -2
- package/src/cognee/client.ts +18 -0
- package/src/cognee/sync-manager.ts +389 -0
- package/src/control/identity-manager.ts +354 -0
- package/src/control/intent-router.ts +326 -0
- package/src/control/types.ts +102 -0
- package/src/curator/curator.ts +295 -1
- package/src/errors/classify.ts +102 -0
- package/src/errors/index.ts +5 -0
- package/src/errors/retry.ts +132 -0
- package/src/errors/types.ts +81 -0
- package/src/governance/governance.ts +698 -0
- package/src/governance/index.ts +18 -0
- package/src/governance/types.ts +111 -0
- package/src/index.ts +213 -2
- package/src/intake/content-classifier.ts +146 -0
- package/src/intake/dedup-gate.ts +92 -0
- package/src/intake/intake-pipeline.ts +503 -0
- package/src/intake/types.ts +69 -0
- package/src/intelligence/loader.ts +1 -1
- package/src/intelligence/types.ts +3 -1
- package/src/logging/logger.ts +154 -0
- package/src/logging/types.ts +21 -0
- package/src/loop/loop-manager.ts +448 -0
- package/src/loop/types.ts +115 -0
- package/src/persistence/index.ts +7 -0
- package/src/persistence/sqlite-provider.ts +62 -0
- package/src/persistence/types.ts +44 -0
- package/src/planning/gap-analysis.ts +775 -0
- package/src/planning/gap-types.ts +61 -0
- package/src/planning/planner.ts +1273 -24
- package/src/playbooks/generic/brainstorming.ts +110 -0
- package/src/playbooks/generic/code-review.ts +181 -0
- package/src/playbooks/generic/subagent-execution.ts +74 -0
- package/src/playbooks/generic/systematic-debugging.ts +92 -0
- package/src/playbooks/generic/tdd.ts +75 -0
- package/src/playbooks/generic/verification.ts +79 -0
- package/src/playbooks/index.ts +27 -0
- package/src/playbooks/playbook-registry.ts +284 -0
- package/src/playbooks/playbook-seeder.ts +119 -0
- package/src/playbooks/playbook-types.ts +162 -0
- package/src/project/project-registry.ts +370 -0
- package/src/project/types.ts +31 -0
- package/src/prompts/index.ts +3 -0
- package/src/prompts/parser.ts +59 -0
- package/src/prompts/template-manager.ts +77 -0
- package/src/prompts/types.ts +28 -0
- package/src/runtime/admin-extra-ops.ts +652 -0
- package/src/runtime/admin-ops.ts +340 -0
- package/src/runtime/capture-ops.ts +404 -0
- package/src/runtime/cognee-sync-ops.ts +63 -0
- package/src/runtime/core-ops.ts +787 -9
- package/src/runtime/curator-extra-ops.ts +85 -0
- package/src/runtime/domain-ops.ts +67 -15
- package/src/runtime/grading-ops.ts +130 -0
- package/src/runtime/intake-ops.ts +126 -0
- package/src/runtime/loop-ops.ts +277 -0
- package/src/runtime/memory-cross-project-ops.ts +191 -0
- package/src/runtime/memory-extra-ops.ts +186 -0
- package/src/runtime/orchestrate-ops.ts +278 -0
- package/src/runtime/planning-extra-ops.ts +718 -0
- package/src/runtime/playbook-ops.ts +169 -0
- package/src/runtime/project-ops.ts +202 -0
- package/src/runtime/runtime.ts +77 -3
- package/src/runtime/types.ts +29 -0
- package/src/runtime/vault-extra-ops.ts +606 -0
- package/src/telemetry/telemetry.ts +118 -0
- package/src/vault/playbook.ts +87 -0
- package/src/vault/vault.ts +575 -98
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extra vault operations — 20 ops that extend the 4 base vault ops in core-ops.ts.
|
|
3
|
+
*
|
|
4
|
+
* Groups: single-entry CRUD (3), bulk (2), discovery (3), import/export (3),
|
|
5
|
+
* analytics (1), seed canonical (1), knowledge lifecycle (4), temporal (3).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { readFileSync, readdirSync, existsSync } from 'node:fs';
|
|
10
|
+
import { join, basename } from 'node:path';
|
|
11
|
+
import type { OpDefinition } from '../facades/types.js';
|
|
12
|
+
import type { IntelligenceEntry } from '../intelligence/types.js';
|
|
13
|
+
import type { AgentRuntime } from './types.js';
|
|
14
|
+
|
|
15
|
+
const entrySchema = z.object({
|
|
16
|
+
id: z.string(),
|
|
17
|
+
type: z.enum(['pattern', 'anti-pattern', 'rule', 'playbook']),
|
|
18
|
+
domain: z.string(),
|
|
19
|
+
title: z.string(),
|
|
20
|
+
severity: z.enum(['critical', 'warning', 'suggestion']),
|
|
21
|
+
description: z.string(),
|
|
22
|
+
context: z.string().optional(),
|
|
23
|
+
example: z.string().optional(),
|
|
24
|
+
counterExample: z.string().optional(),
|
|
25
|
+
why: z.string().optional(),
|
|
26
|
+
tags: z.array(z.string()),
|
|
27
|
+
appliesTo: z.array(z.string()).optional(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export function createVaultExtraOps(runtime: AgentRuntime): OpDefinition[] {
|
|
31
|
+
const { vault } = runtime;
|
|
32
|
+
|
|
33
|
+
return [
|
|
34
|
+
// ─── Single-Entry CRUD ──────────────────────────────────────────
|
|
35
|
+
{
|
|
36
|
+
name: 'vault_get',
|
|
37
|
+
description: 'Get a single vault entry by ID.',
|
|
38
|
+
auth: 'read',
|
|
39
|
+
schema: z.object({ id: z.string() }),
|
|
40
|
+
handler: async (params) => {
|
|
41
|
+
const entry = vault.get(params.id as string);
|
|
42
|
+
if (!entry) return { error: 'Entry not found: ' + params.id };
|
|
43
|
+
return entry;
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'vault_update',
|
|
48
|
+
description:
|
|
49
|
+
'Update an existing vault entry. Only the fields provided are changed; the rest stay the same.',
|
|
50
|
+
auth: 'write',
|
|
51
|
+
schema: z.object({
|
|
52
|
+
id: z.string(),
|
|
53
|
+
title: z.string().optional(),
|
|
54
|
+
description: z.string().optional(),
|
|
55
|
+
context: z.string().optional(),
|
|
56
|
+
example: z.string().optional(),
|
|
57
|
+
counterExample: z.string().optional(),
|
|
58
|
+
why: z.string().optional(),
|
|
59
|
+
tags: z.array(z.string()).optional(),
|
|
60
|
+
appliesTo: z.array(z.string()).optional(),
|
|
61
|
+
severity: z.enum(['critical', 'warning', 'suggestion']).optional(),
|
|
62
|
+
type: z.enum(['pattern', 'anti-pattern', 'rule', 'playbook']).optional(),
|
|
63
|
+
domain: z.string().optional(),
|
|
64
|
+
}),
|
|
65
|
+
handler: async (params) => {
|
|
66
|
+
const id = params.id as string;
|
|
67
|
+
const { id: _id, ...fields } = params;
|
|
68
|
+
// Strip undefined values so we only pass what was actually provided
|
|
69
|
+
const cleaned: Record<string, unknown> = {};
|
|
70
|
+
for (const [k, v] of Object.entries(fields)) {
|
|
71
|
+
if (v !== undefined) cleaned[k] = v;
|
|
72
|
+
}
|
|
73
|
+
if (Object.keys(cleaned).length === 0) {
|
|
74
|
+
return { error: 'No fields to update' };
|
|
75
|
+
}
|
|
76
|
+
const updated = vault.update(
|
|
77
|
+
id,
|
|
78
|
+
cleaned as Partial<
|
|
79
|
+
Pick<
|
|
80
|
+
IntelligenceEntry,
|
|
81
|
+
| 'title'
|
|
82
|
+
| 'description'
|
|
83
|
+
| 'context'
|
|
84
|
+
| 'example'
|
|
85
|
+
| 'counterExample'
|
|
86
|
+
| 'why'
|
|
87
|
+
| 'tags'
|
|
88
|
+
| 'appliesTo'
|
|
89
|
+
| 'severity'
|
|
90
|
+
| 'type'
|
|
91
|
+
| 'domain'
|
|
92
|
+
>
|
|
93
|
+
>,
|
|
94
|
+
);
|
|
95
|
+
if (!updated) return { error: 'Entry not found: ' + id };
|
|
96
|
+
return { updated: true, entry: updated };
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'vault_remove',
|
|
101
|
+
description: 'Remove a single vault entry by ID.',
|
|
102
|
+
auth: 'admin',
|
|
103
|
+
schema: z.object({ id: z.string() }),
|
|
104
|
+
handler: async (params) => {
|
|
105
|
+
const removed = vault.remove(params.id as string);
|
|
106
|
+
return { removed, id: params.id };
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
// ─── Bulk Operations ────────────────────────────────────────────
|
|
111
|
+
{
|
|
112
|
+
name: 'vault_bulk_add',
|
|
113
|
+
description: 'Add multiple vault entries at once. Uses upsert — existing IDs are updated.',
|
|
114
|
+
auth: 'write',
|
|
115
|
+
schema: z.object({
|
|
116
|
+
entries: z.array(entrySchema),
|
|
117
|
+
}),
|
|
118
|
+
handler: async (params) => {
|
|
119
|
+
const entries = params.entries as IntelligenceEntry[];
|
|
120
|
+
const count = vault.seed(entries);
|
|
121
|
+
return { added: count, total: vault.stats().totalEntries };
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'vault_bulk_remove',
|
|
126
|
+
description: 'Remove multiple vault entries by IDs in a single transaction.',
|
|
127
|
+
auth: 'admin',
|
|
128
|
+
schema: z.object({
|
|
129
|
+
ids: z.array(z.string()),
|
|
130
|
+
}),
|
|
131
|
+
handler: async (params) => {
|
|
132
|
+
const ids = params.ids as string[];
|
|
133
|
+
const removed = vault.bulkRemove(ids);
|
|
134
|
+
return { removed, requested: ids.length, total: vault.stats().totalEntries };
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
// ─── Discovery ──────────────────────────────────────────────────
|
|
139
|
+
{
|
|
140
|
+
name: 'vault_tags',
|
|
141
|
+
description: 'List all unique tags used across vault entries with their occurrence counts.',
|
|
142
|
+
auth: 'read',
|
|
143
|
+
handler: async () => {
|
|
144
|
+
const tags = vault.getTags();
|
|
145
|
+
return { tags, count: tags.length };
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'vault_domains',
|
|
150
|
+
description: 'List all domains in the vault with their entry counts.',
|
|
151
|
+
auth: 'read',
|
|
152
|
+
handler: async () => {
|
|
153
|
+
const domains = vault.getDomains();
|
|
154
|
+
return { domains, count: domains.length };
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'vault_recent',
|
|
159
|
+
description: 'Get recently added or updated vault entries, ordered by most recent first.',
|
|
160
|
+
auth: 'read',
|
|
161
|
+
schema: z.object({
|
|
162
|
+
limit: z.number().optional().describe('Max entries to return (default 20)'),
|
|
163
|
+
}),
|
|
164
|
+
handler: async (params) => {
|
|
165
|
+
const limit = (params.limit as number | undefined) ?? 20;
|
|
166
|
+
const entries = vault.getRecent(limit);
|
|
167
|
+
return { entries, count: entries.length };
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
// ─── Import / Export / Seed ──────────────────────────────────────
|
|
172
|
+
{
|
|
173
|
+
name: 'vault_import',
|
|
174
|
+
description:
|
|
175
|
+
'Import vault entries from a JSON bundle. Uses upsert — existing IDs are updated, new IDs are inserted.',
|
|
176
|
+
auth: 'write',
|
|
177
|
+
schema: z.object({
|
|
178
|
+
entries: z.array(entrySchema),
|
|
179
|
+
}),
|
|
180
|
+
handler: async (params) => {
|
|
181
|
+
const entries = params.entries as IntelligenceEntry[];
|
|
182
|
+
const before = vault.stats().totalEntries;
|
|
183
|
+
const count = vault.seed(entries);
|
|
184
|
+
const after = vault.stats().totalEntries;
|
|
185
|
+
return {
|
|
186
|
+
imported: count,
|
|
187
|
+
newEntries: after - before,
|
|
188
|
+
updatedEntries: count - (after - before),
|
|
189
|
+
total: after,
|
|
190
|
+
};
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'vault_seed',
|
|
195
|
+
description:
|
|
196
|
+
'Seed the vault from intelligence data. Idempotent — safe to call multiple times. Uses upsert.',
|
|
197
|
+
auth: 'write',
|
|
198
|
+
schema: z.object({
|
|
199
|
+
entries: z.array(entrySchema),
|
|
200
|
+
}),
|
|
201
|
+
handler: async (params) => {
|
|
202
|
+
const entries = params.entries as IntelligenceEntry[];
|
|
203
|
+
const count = vault.seed(entries);
|
|
204
|
+
return { seeded: count, total: vault.stats().totalEntries };
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: 'vault_backup',
|
|
209
|
+
description:
|
|
210
|
+
'Export the full vault as a JSON bundle suitable for backup or transfer to another agent.',
|
|
211
|
+
auth: 'read',
|
|
212
|
+
handler: async () => {
|
|
213
|
+
return vault.exportAll();
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
// ─── Analytics ──────────────────────────────────────────────────
|
|
218
|
+
{
|
|
219
|
+
name: 'vault_age_report',
|
|
220
|
+
description:
|
|
221
|
+
'Show vault entry age distribution — how many entries are from today, this week, this month, this quarter, or older.',
|
|
222
|
+
auth: 'read',
|
|
223
|
+
handler: async () => {
|
|
224
|
+
return vault.getAgeReport();
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// ─── Seed Canonical (#153) ───────────────────────────────────
|
|
229
|
+
{
|
|
230
|
+
name: 'vault_seed_canonical',
|
|
231
|
+
description:
|
|
232
|
+
'Seed vault knowledge from structured markdown files with YAML frontmatter. ' +
|
|
233
|
+
'Reads .md files from a directory, parses them into IntelligenceEntry objects, and upserts. Idempotent.',
|
|
234
|
+
auth: 'write',
|
|
235
|
+
schema: z.object({
|
|
236
|
+
directory: z
|
|
237
|
+
.string()
|
|
238
|
+
.describe('Path to directory containing .md files with YAML frontmatter'),
|
|
239
|
+
domain: z
|
|
240
|
+
.string()
|
|
241
|
+
.optional()
|
|
242
|
+
.describe('Override domain for all entries (default: from frontmatter or filename)'),
|
|
243
|
+
}),
|
|
244
|
+
handler: async (params) => {
|
|
245
|
+
try {
|
|
246
|
+
const dir = params.directory as string;
|
|
247
|
+
const domainOverride = params.domain as string | undefined;
|
|
248
|
+
|
|
249
|
+
if (!existsSync(dir)) {
|
|
250
|
+
return { error: `Directory not found: ${dir}` };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const files = readdirSync(dir).filter((f) => f.endsWith('.md'));
|
|
254
|
+
const entries: IntelligenceEntry[] = [];
|
|
255
|
+
const errors: Array<{ file: string; error: string }> = [];
|
|
256
|
+
|
|
257
|
+
for (const file of files) {
|
|
258
|
+
try {
|
|
259
|
+
const content = readFileSync(join(dir, file), 'utf-8');
|
|
260
|
+
const entry = parseMarkdownEntry(content, file, domainOverride);
|
|
261
|
+
if (entry) entries.push(entry);
|
|
262
|
+
} catch (err) {
|
|
263
|
+
errors.push({ file, error: (err as Error).message });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const seeded = entries.length > 0 ? vault.seed(entries) : 0;
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
seeded,
|
|
271
|
+
filesProcessed: files.length,
|
|
272
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
273
|
+
total: vault.stats().totalEntries,
|
|
274
|
+
};
|
|
275
|
+
} catch (err) {
|
|
276
|
+
return { error: (err as Error).message };
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
// ─── Knowledge Audit (#155) ──────────────────────────────────
|
|
282
|
+
{
|
|
283
|
+
name: 'knowledge_audit',
|
|
284
|
+
description:
|
|
285
|
+
'Audit vault quality — coverage gaps, stale entries, tag health, and recommendations.',
|
|
286
|
+
auth: 'read',
|
|
287
|
+
handler: async () => {
|
|
288
|
+
try {
|
|
289
|
+
const stats = vault.stats();
|
|
290
|
+
const tags = vault.getTags();
|
|
291
|
+
const domains = vault.getDomains();
|
|
292
|
+
const ageReport = vault.getAgeReport();
|
|
293
|
+
|
|
294
|
+
// Check coverage
|
|
295
|
+
const entriesWithoutTags = tags.length === 0 ? stats.totalEntries : 0;
|
|
296
|
+
const singletonTags = tags.filter((t) => t.count === 1).length;
|
|
297
|
+
|
|
298
|
+
// Staleness: entries older than 90 days
|
|
299
|
+
const staleCount = ageReport.buckets.find((b) => b.label === 'older')?.count ?? 0;
|
|
300
|
+
|
|
301
|
+
const recommendations: string[] = [];
|
|
302
|
+
if (stats.totalEntries < 10)
|
|
303
|
+
recommendations.push('Vault has few entries — capture more knowledge');
|
|
304
|
+
if (singletonTags > tags.length * 0.5)
|
|
305
|
+
recommendations.push('Many singleton tags — consolidate tagging');
|
|
306
|
+
if (staleCount > stats.totalEntries * 0.3)
|
|
307
|
+
recommendations.push('>30% entries are stale — review and update');
|
|
308
|
+
if (domains.length === 1)
|
|
309
|
+
recommendations.push('Only one domain — consider categorizing by domain');
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
totalEntries: stats.totalEntries,
|
|
313
|
+
domainCount: domains.length,
|
|
314
|
+
tagCount: tags.length,
|
|
315
|
+
singletonTags,
|
|
316
|
+
staleEntries: staleCount,
|
|
317
|
+
entriesWithoutTags,
|
|
318
|
+
recommendations,
|
|
319
|
+
};
|
|
320
|
+
} catch (err) {
|
|
321
|
+
return { error: (err as Error).message };
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
// ─── Knowledge Health (#155) ─────────────────────────────────
|
|
327
|
+
{
|
|
328
|
+
name: 'knowledge_health',
|
|
329
|
+
description:
|
|
330
|
+
'Knowledge base health metrics — entry counts, freshness, staleness, contradiction signals.',
|
|
331
|
+
auth: 'read',
|
|
332
|
+
handler: async () => {
|
|
333
|
+
try {
|
|
334
|
+
const stats = vault.stats();
|
|
335
|
+
const ageReport = vault.getAgeReport();
|
|
336
|
+
const domains = vault.getDomains();
|
|
337
|
+
const tags = vault.getTags();
|
|
338
|
+
|
|
339
|
+
// Detect potential contradictions: entries with same tags but different types (pattern vs anti-pattern)
|
|
340
|
+
const db = vault.getDb();
|
|
341
|
+
const contradictionSignals = db
|
|
342
|
+
.prepare(
|
|
343
|
+
`SELECT t.value as tag, COUNT(DISTINCT e.type) as type_count
|
|
344
|
+
FROM entries e, json_each(e.tags) t
|
|
345
|
+
GROUP BY t.value HAVING type_count > 1 LIMIT 10`,
|
|
346
|
+
)
|
|
347
|
+
.all() as Array<{ tag: string; type_count: number }>;
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
totalEntries: stats.totalEntries,
|
|
351
|
+
freshEntries:
|
|
352
|
+
(ageReport.buckets.find((b) => b.label === 'today')?.count ?? 0) +
|
|
353
|
+
(ageReport.buckets.find((b) => b.label === 'this_week')?.count ?? 0),
|
|
354
|
+
staleEntries: ageReport.buckets.find((b) => b.label === 'older')?.count ?? 0,
|
|
355
|
+
domainCount: domains.length,
|
|
356
|
+
tagCount: tags.length,
|
|
357
|
+
contradictionSignals: contradictionSignals.length,
|
|
358
|
+
contradictionTags: contradictionSignals.map((c) => c.tag),
|
|
359
|
+
oldestTimestamp: ageReport.oldestTimestamp,
|
|
360
|
+
newestTimestamp: ageReport.newestTimestamp,
|
|
361
|
+
};
|
|
362
|
+
} catch (err) {
|
|
363
|
+
return { error: (err as Error).message };
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
|
|
368
|
+
// ─── Merge Patterns (#155) ───────────────────────────────────
|
|
369
|
+
{
|
|
370
|
+
name: 'knowledge_merge',
|
|
371
|
+
description:
|
|
372
|
+
'Merge two similar patterns into one — keeps the best metadata from both, removes the duplicate.',
|
|
373
|
+
auth: 'write',
|
|
374
|
+
schema: z.object({
|
|
375
|
+
keepId: z.string().describe('ID of the entry to keep (will receive merged data)'),
|
|
376
|
+
removeId: z.string().describe('ID of the duplicate entry to remove after merge'),
|
|
377
|
+
}),
|
|
378
|
+
handler: async (params) => {
|
|
379
|
+
try {
|
|
380
|
+
const keep = vault.get(params.keepId as string);
|
|
381
|
+
const remove = vault.get(params.removeId as string);
|
|
382
|
+
if (!keep) return { error: `Entry not found: ${params.keepId}` };
|
|
383
|
+
if (!remove) return { error: `Entry not found: ${params.removeId}` };
|
|
384
|
+
|
|
385
|
+
// Merge tags (deduplicated union)
|
|
386
|
+
const mergedTags = [...new Set([...(keep.tags ?? []), ...(remove.tags ?? [])])];
|
|
387
|
+
|
|
388
|
+
// Merge fields — prefer non-empty from either side
|
|
389
|
+
const updates: Partial<IntelligenceEntry> = {
|
|
390
|
+
tags: mergedTags,
|
|
391
|
+
description: keep.description || remove.description,
|
|
392
|
+
context: keep.context || remove.context,
|
|
393
|
+
example: keep.example || remove.example,
|
|
394
|
+
counterExample: keep.counterExample || remove.counterExample,
|
|
395
|
+
why: keep.why || remove.why,
|
|
396
|
+
appliesTo: keep.appliesTo?.length ? keep.appliesTo : remove.appliesTo,
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
vault.update(keep.id, updates);
|
|
400
|
+
vault.remove(remove.id);
|
|
401
|
+
|
|
402
|
+
return {
|
|
403
|
+
merged: true,
|
|
404
|
+
keptId: keep.id,
|
|
405
|
+
removedId: remove.id,
|
|
406
|
+
mergedTags,
|
|
407
|
+
};
|
|
408
|
+
} catch (err) {
|
|
409
|
+
return { error: (err as Error).message };
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
// ─── Knowledge Reorganize (#155) ─────────────────────────────
|
|
415
|
+
{
|
|
416
|
+
name: 'knowledge_reorganize',
|
|
417
|
+
description:
|
|
418
|
+
'Re-categorize vault entries — reassign domains, clean up tags, deduplicate. Dry-run by default.',
|
|
419
|
+
auth: 'write',
|
|
420
|
+
schema: z.object({
|
|
421
|
+
dryRun: z
|
|
422
|
+
.boolean()
|
|
423
|
+
.optional()
|
|
424
|
+
.describe('If true, only report what would change (default true)'),
|
|
425
|
+
retagRules: z
|
|
426
|
+
.array(
|
|
427
|
+
z.object({
|
|
428
|
+
from: z.string().describe('Tag to rename/remove'),
|
|
429
|
+
to: z.string().optional().describe('New tag (omit to remove the tag)'),
|
|
430
|
+
}),
|
|
431
|
+
)
|
|
432
|
+
.optional()
|
|
433
|
+
.describe('Tag rename/removal rules'),
|
|
434
|
+
domainRules: z
|
|
435
|
+
.array(
|
|
436
|
+
z.object({
|
|
437
|
+
from: z.string().describe('Old domain name'),
|
|
438
|
+
to: z.string().describe('New domain name'),
|
|
439
|
+
}),
|
|
440
|
+
)
|
|
441
|
+
.optional()
|
|
442
|
+
.describe('Domain rename rules'),
|
|
443
|
+
}),
|
|
444
|
+
handler: async (params) => {
|
|
445
|
+
try {
|
|
446
|
+
const dryRun = (params.dryRun as boolean | undefined) ?? true;
|
|
447
|
+
const retagRules = (params.retagRules as Array<{ from: string; to?: string }>) ?? [];
|
|
448
|
+
const domainRules = (params.domainRules as Array<{ from: string; to: string }>) ?? [];
|
|
449
|
+
const changes: Array<{ id: string; field: string; from: string; to: string }> = [];
|
|
450
|
+
|
|
451
|
+
const allEntries = vault.list({});
|
|
452
|
+
|
|
453
|
+
for (const entry of allEntries) {
|
|
454
|
+
// Apply domain rules
|
|
455
|
+
for (const rule of domainRules) {
|
|
456
|
+
if (entry.domain === rule.from) {
|
|
457
|
+
changes.push({ id: entry.id, field: 'domain', from: rule.from, to: rule.to });
|
|
458
|
+
if (!dryRun) vault.update(entry.id, { domain: rule.to });
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Apply retag rules
|
|
463
|
+
if (entry.tags) {
|
|
464
|
+
let tagsChanged = false;
|
|
465
|
+
const newTags = [...entry.tags];
|
|
466
|
+
for (const rule of retagRules) {
|
|
467
|
+
const idx = newTags.indexOf(rule.from);
|
|
468
|
+
if (idx !== -1) {
|
|
469
|
+
if (rule.to) {
|
|
470
|
+
changes.push({ id: entry.id, field: 'tag', from: rule.from, to: rule.to });
|
|
471
|
+
newTags[idx] = rule.to;
|
|
472
|
+
} else {
|
|
473
|
+
changes.push({ id: entry.id, field: 'tag', from: rule.from, to: '(removed)' });
|
|
474
|
+
newTags.splice(idx, 1);
|
|
475
|
+
}
|
|
476
|
+
tagsChanged = true;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
if (tagsChanged && !dryRun) {
|
|
480
|
+
vault.update(entry.id, { tags: [...new Set(newTags)] });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return {
|
|
486
|
+
dryRun,
|
|
487
|
+
changesFound: changes.length,
|
|
488
|
+
changes: changes.slice(0, 100), // cap output
|
|
489
|
+
entriesScanned: allEntries.length,
|
|
490
|
+
};
|
|
491
|
+
} catch (err) {
|
|
492
|
+
return { error: (err as Error).message };
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
},
|
|
496
|
+
|
|
497
|
+
// ─── Temporal (#89) ──────────────────────────────────────────────
|
|
498
|
+
{
|
|
499
|
+
name: 'vault_set_temporal',
|
|
500
|
+
description:
|
|
501
|
+
'Set valid_from and/or valid_until timestamps on a vault entry for bi-temporal validity windows.',
|
|
502
|
+
auth: 'write',
|
|
503
|
+
schema: z.object({
|
|
504
|
+
id: z.string().describe('Entry ID'),
|
|
505
|
+
validFrom: z.number().optional().describe('Unix epoch — when entry becomes active'),
|
|
506
|
+
validUntil: z.number().optional().describe('Unix epoch — when entry expires'),
|
|
507
|
+
}),
|
|
508
|
+
handler: async (params) => {
|
|
509
|
+
const updated = vault.setTemporal(
|
|
510
|
+
params.id as string,
|
|
511
|
+
params.validFrom as number | undefined,
|
|
512
|
+
params.validUntil as number | undefined,
|
|
513
|
+
);
|
|
514
|
+
if (!updated) return { error: 'Entry not found or no fields to update' };
|
|
515
|
+
const entry = vault.get(params.id as string);
|
|
516
|
+
return {
|
|
517
|
+
updated: true,
|
|
518
|
+
id: params.id,
|
|
519
|
+
validFrom: entry?.validFrom ?? null,
|
|
520
|
+
validUntil: entry?.validUntil ?? null,
|
|
521
|
+
};
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: 'vault_find_expiring',
|
|
526
|
+
description:
|
|
527
|
+
'Find vault entries expiring within a given number of days. Useful for proactive knowledge maintenance.',
|
|
528
|
+
auth: 'read',
|
|
529
|
+
schema: z.object({
|
|
530
|
+
withinDays: z.number().describe('Number of days to look ahead'),
|
|
531
|
+
}),
|
|
532
|
+
handler: async (params) => {
|
|
533
|
+
const entries = vault.findExpiring(params.withinDays as number);
|
|
534
|
+
return { entries, count: entries.length };
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: 'vault_find_expired',
|
|
539
|
+
description: 'List expired vault entries (valid_until in the past). Useful for cleanup.',
|
|
540
|
+
auth: 'read',
|
|
541
|
+
schema: z.object({
|
|
542
|
+
limit: z.number().optional().describe('Max results (default 50)'),
|
|
543
|
+
}),
|
|
544
|
+
handler: async (params) => {
|
|
545
|
+
const entries = vault.findExpired((params.limit as number | undefined) ?? 50);
|
|
546
|
+
return { entries, count: entries.length };
|
|
547
|
+
},
|
|
548
|
+
},
|
|
549
|
+
];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Parse a markdown file with YAML frontmatter into an IntelligenceEntry.
|
|
554
|
+
* Expected frontmatter fields: id, type, domain, severity, title, tags.
|
|
555
|
+
*/
|
|
556
|
+
function parseMarkdownEntry(
|
|
557
|
+
content: string,
|
|
558
|
+
filename: string,
|
|
559
|
+
domainOverride?: string,
|
|
560
|
+
): IntelligenceEntry | null {
|
|
561
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
562
|
+
if (!match) return null;
|
|
563
|
+
|
|
564
|
+
const frontmatter = match[1];
|
|
565
|
+
const body = match[2].trim();
|
|
566
|
+
|
|
567
|
+
// Simple YAML parser for flat key-value pairs
|
|
568
|
+
const meta: Record<string, string | string[]> = {};
|
|
569
|
+
for (const line of frontmatter.split('\n')) {
|
|
570
|
+
const kvMatch = line.match(/^(\w+):\s*(.+)$/);
|
|
571
|
+
if (kvMatch) {
|
|
572
|
+
const key = kvMatch[1];
|
|
573
|
+
let value = kvMatch[2].trim();
|
|
574
|
+
// Handle quoted strings
|
|
575
|
+
if (
|
|
576
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
577
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
578
|
+
) {
|
|
579
|
+
value = value.slice(1, -1);
|
|
580
|
+
}
|
|
581
|
+
// Handle arrays: [a, b, c]
|
|
582
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
583
|
+
meta[key] = value
|
|
584
|
+
.slice(1, -1)
|
|
585
|
+
.split(',')
|
|
586
|
+
.map((s) => s.trim().replace(/^["']|["']$/g, ''));
|
|
587
|
+
} else {
|
|
588
|
+
meta[key] = value;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const id = (meta.id as string) || basename(filename, '.md');
|
|
594
|
+
const tags = Array.isArray(meta.tags) ? meta.tags : meta.tags ? [meta.tags as string] : [];
|
|
595
|
+
|
|
596
|
+
return {
|
|
597
|
+
id,
|
|
598
|
+
type: (meta.type as IntelligenceEntry['type']) || 'pattern',
|
|
599
|
+
domain: domainOverride || (meta.domain as string) || 'general',
|
|
600
|
+
title: (meta.title as string) || basename(filename, '.md'),
|
|
601
|
+
severity: (meta.severity as IntelligenceEntry['severity']) || 'suggestion',
|
|
602
|
+
description: body || (meta.description as string) || '',
|
|
603
|
+
context: meta.context as string | undefined,
|
|
604
|
+
tags,
|
|
605
|
+
};
|
|
606
|
+
}
|