@vinkius-core/mcp-fusion 2.6.0 → 2.8.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.
Files changed (140) hide show
  1. package/dist/cli/fusion.d.ts +101 -0
  2. package/dist/cli/fusion.d.ts.map +1 -0
  3. package/dist/cli/fusion.js +333 -0
  4. package/dist/cli/fusion.js.map +1 -0
  5. package/dist/client/FusionClient.d.ts +122 -1
  6. package/dist/client/FusionClient.d.ts.map +1 -1
  7. package/dist/client/FusionClient.js +173 -11
  8. package/dist/client/FusionClient.js.map +1 -1
  9. package/dist/client/index.d.ts +2 -2
  10. package/dist/client/index.d.ts.map +1 -1
  11. package/dist/client/index.js +1 -1
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/core/StandardSchema.d.ts +178 -0
  14. package/dist/core/StandardSchema.d.ts.map +1 -0
  15. package/dist/core/StandardSchema.js +166 -0
  16. package/dist/core/StandardSchema.js.map +1 -0
  17. package/dist/core/createGroup.d.ts +140 -0
  18. package/dist/core/createGroup.d.ts.map +1 -0
  19. package/dist/core/createGroup.js +133 -0
  20. package/dist/core/createGroup.js.map +1 -0
  21. package/dist/core/execution/ExecutionPipeline.d.ts.map +1 -1
  22. package/dist/core/execution/ExecutionPipeline.js +6 -2
  23. package/dist/core/execution/ExecutionPipeline.js.map +1 -1
  24. package/dist/core/index.d.ts +7 -1
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/core/index.js +6 -0
  27. package/dist/core/index.js.map +1 -1
  28. package/dist/core/initFusion.d.ts +201 -0
  29. package/dist/core/initFusion.d.ts.map +1 -0
  30. package/dist/core/initFusion.js +134 -0
  31. package/dist/core/initFusion.js.map +1 -0
  32. package/dist/core/response.d.ts +49 -2
  33. package/dist/core/response.d.ts.map +1 -1
  34. package/dist/core/response.js +27 -5
  35. package/dist/core/response.js.map +1 -1
  36. package/dist/index.d.ts +57 -9
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +30 -4
  39. package/dist/index.js.map +1 -1
  40. package/dist/introspection/BehaviorDigest.d.ts +112 -0
  41. package/dist/introspection/BehaviorDigest.d.ts.map +1 -0
  42. package/dist/introspection/BehaviorDigest.js +146 -0
  43. package/dist/introspection/BehaviorDigest.js.map +1 -0
  44. package/dist/introspection/CapabilityLockfile.d.ts +259 -0
  45. package/dist/introspection/CapabilityLockfile.d.ts.map +1 -0
  46. package/dist/introspection/CapabilityLockfile.js +391 -0
  47. package/dist/introspection/CapabilityLockfile.js.map +1 -0
  48. package/dist/introspection/ContractAwareSelfHealing.d.ts +90 -0
  49. package/dist/introspection/ContractAwareSelfHealing.d.ts.map +1 -0
  50. package/dist/introspection/ContractAwareSelfHealing.js +132 -0
  51. package/dist/introspection/ContractAwareSelfHealing.js.map +1 -0
  52. package/dist/introspection/ContractDiff.d.ts +91 -0
  53. package/dist/introspection/ContractDiff.d.ts.map +1 -0
  54. package/dist/introspection/ContractDiff.js +466 -0
  55. package/dist/introspection/ContractDiff.js.map +1 -0
  56. package/dist/introspection/CryptoAttestation.d.ts +143 -0
  57. package/dist/introspection/CryptoAttestation.d.ts.map +1 -0
  58. package/dist/introspection/CryptoAttestation.js +194 -0
  59. package/dist/introspection/CryptoAttestation.js.map +1 -0
  60. package/dist/introspection/EntitlementScanner.d.ts +124 -0
  61. package/dist/introspection/EntitlementScanner.d.ts.map +1 -0
  62. package/dist/introspection/EntitlementScanner.js +244 -0
  63. package/dist/introspection/EntitlementScanner.js.map +1 -0
  64. package/dist/introspection/GovernanceObserver.d.ts +88 -0
  65. package/dist/introspection/GovernanceObserver.d.ts.map +1 -0
  66. package/dist/introspection/GovernanceObserver.js +132 -0
  67. package/dist/introspection/GovernanceObserver.js.map +1 -0
  68. package/dist/introspection/SemanticProbe.d.ts +207 -0
  69. package/dist/introspection/SemanticProbe.d.ts.map +1 -0
  70. package/dist/introspection/SemanticProbe.js +255 -0
  71. package/dist/introspection/SemanticProbe.js.map +1 -0
  72. package/dist/introspection/TokenEconomics.d.ts +210 -0
  73. package/dist/introspection/TokenEconomics.d.ts.map +1 -0
  74. package/dist/introspection/TokenEconomics.js +286 -0
  75. package/dist/introspection/TokenEconomics.js.map +1 -0
  76. package/dist/introspection/ToolContract.d.ts +159 -0
  77. package/dist/introspection/ToolContract.d.ts.map +1 -0
  78. package/dist/introspection/ToolContract.js +191 -0
  79. package/dist/introspection/ToolContract.js.map +1 -0
  80. package/dist/introspection/canonicalize.d.ts +20 -0
  81. package/dist/introspection/canonicalize.d.ts.map +1 -0
  82. package/dist/introspection/canonicalize.js +51 -0
  83. package/dist/introspection/canonicalize.js.map +1 -0
  84. package/dist/introspection/index.d.ts +20 -0
  85. package/dist/introspection/index.d.ts.map +1 -1
  86. package/dist/introspection/index.js +20 -0
  87. package/dist/introspection/index.js.map +1 -1
  88. package/dist/observability/DebugObserver.d.ts +26 -1
  89. package/dist/observability/DebugObserver.d.ts.map +1 -1
  90. package/dist/observability/DebugObserver.js +8 -1
  91. package/dist/observability/DebugObserver.js.map +1 -1
  92. package/dist/observability/index.d.ts +1 -1
  93. package/dist/observability/index.d.ts.map +1 -1
  94. package/dist/observability/index.js.map +1 -1
  95. package/dist/presenter/ZodDescriptionExtractor.d.ts +54 -0
  96. package/dist/presenter/ZodDescriptionExtractor.d.ts.map +1 -0
  97. package/dist/presenter/ZodDescriptionExtractor.js +131 -0
  98. package/dist/presenter/ZodDescriptionExtractor.js.map +1 -0
  99. package/dist/presenter/definePresenter.d.ts +172 -0
  100. package/dist/presenter/definePresenter.d.ts.map +1 -0
  101. package/dist/presenter/definePresenter.js +96 -0
  102. package/dist/presenter/definePresenter.js.map +1 -0
  103. package/dist/presenter/index.d.ts +3 -0
  104. package/dist/presenter/index.d.ts.map +1 -1
  105. package/dist/presenter/index.js +4 -0
  106. package/dist/presenter/index.js.map +1 -1
  107. package/dist/server/DevServer.d.ts +96 -0
  108. package/dist/server/DevServer.d.ts.map +1 -0
  109. package/dist/server/DevServer.js +187 -0
  110. package/dist/server/DevServer.js.map +1 -0
  111. package/dist/server/ServerAttachment.d.ts +41 -0
  112. package/dist/server/ServerAttachment.d.ts.map +1 -1
  113. package/dist/server/ServerAttachment.js +25 -1
  114. package/dist/server/ServerAttachment.js.map +1 -1
  115. package/dist/server/autoDiscover.d.ts +63 -0
  116. package/dist/server/autoDiscover.d.ts.map +1 -0
  117. package/dist/server/autoDiscover.js +157 -0
  118. package/dist/server/autoDiscover.js.map +1 -0
  119. package/dist/server/index.d.ts +4 -0
  120. package/dist/server/index.d.ts.map +1 -1
  121. package/dist/server/index.js +4 -0
  122. package/dist/server/index.js.map +1 -1
  123. package/dist/state-sync/PolicyValidator.d.ts +36 -0
  124. package/dist/state-sync/PolicyValidator.d.ts.map +1 -1
  125. package/dist/state-sync/PolicyValidator.js +35 -0
  126. package/dist/state-sync/PolicyValidator.js.map +1 -1
  127. package/dist/state-sync/ResponseDecorator.d.ts.map +1 -1
  128. package/dist/state-sync/ResponseDecorator.js +2 -1
  129. package/dist/state-sync/ResponseDecorator.js.map +1 -1
  130. package/dist/state-sync/StateSyncLayer.d.ts +5 -4
  131. package/dist/state-sync/StateSyncLayer.d.ts.map +1 -1
  132. package/dist/state-sync/StateSyncLayer.js +35 -4
  133. package/dist/state-sync/StateSyncLayer.js.map +1 -1
  134. package/dist/state-sync/index.d.ts +3 -1
  135. package/dist/state-sync/index.d.ts.map +1 -1
  136. package/dist/state-sync/index.js +1 -0
  137. package/dist/state-sync/index.js.map +1 -1
  138. package/dist/state-sync/types.d.ts +62 -0
  139. package/dist/state-sync/types.d.ts.map +1 -1
  140. package/package.json +45 -1
@@ -0,0 +1,63 @@
1
+ /** Duck-typed ToolBuilder — avoids circular imports */
2
+ interface ToolBuilderLike {
3
+ getName(): string;
4
+ buildToolDefinition?(): unknown;
5
+ }
6
+ /** Duck-typed ToolRegistry — avoids circular imports */
7
+ interface ToolRegistryLike {
8
+ register(builder: ToolBuilderLike): void;
9
+ }
10
+ /**
11
+ * Options for `autoDiscover()`.
12
+ */
13
+ export interface AutoDiscoverOptions {
14
+ /**
15
+ * Regex pattern to filter files. Only files matching this pattern
16
+ * are imported. Default: matches `.ts`, `.js`, `.mjs`, `.mts` files,
17
+ * excluding `.test.`, `.spec.`, and `.d.ts` files.
18
+ */
19
+ pattern?: RegExp;
20
+ /**
21
+ * Whether to recurse into subdirectories.
22
+ * @default true
23
+ */
24
+ recursive?: boolean;
25
+ /**
26
+ * Module resolution style:
27
+ * - `'esm'` — Uses dynamic `import()` (default for ESM projects)
28
+ * - `'cjs'` — Uses `require()` (for CommonJS projects)
29
+ *
30
+ * @default 'esm'
31
+ */
32
+ loader?: 'esm' | 'cjs';
33
+ /**
34
+ * Custom export resolver. When provided, this function is called
35
+ * with the module's exports and must return the tool builder(s).
36
+ *
37
+ * Default behavior: looks for `default` export or named `tool` export.
38
+ */
39
+ resolve?: (mod: Record<string, unknown>) => ToolBuilderLike | ToolBuilderLike[] | undefined;
40
+ }
41
+ /**
42
+ * Scan a directory and auto-register all discovered tool builders.
43
+ *
44
+ * Eliminates the need for a central `index.ts` that manually imports
45
+ * and registers every tool. New tools are automatically picked up
46
+ * when they are dropped into the scanned directory.
47
+ *
48
+ * @param registry - A ToolRegistry instance to register discovered tools
49
+ * @param dir - Path to the tools directory (absolute or relative to CWD)
50
+ * @param options - Discovery options (pattern, recursive, loader, resolve)
51
+ * @returns Array of discovered file paths (for logging/debugging)
52
+ * @throws If the directory does not exist or is not readable
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const registry = new ToolRegistry<AppContext>();
57
+ * const files = await autoDiscover(registry, './src/tools');
58
+ * console.log(`Discovered ${files.length} tool files`);
59
+ * ```
60
+ */
61
+ export declare function autoDiscover(registry: ToolRegistryLike, dir: string, options?: AutoDiscoverOptions): Promise<string[]>;
62
+ export {};
63
+ //# sourceMappingURL=autoDiscover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoDiscover.d.ts","sourceRoot":"","sources":["../../src/server/autoDiscover.ts"],"names":[],"mappings":"AAkDA,uDAAuD;AACvD,UAAU,eAAe;IACrB,OAAO,IAAI,MAAM,CAAC;IAClB,mBAAmB,CAAC,IAAI,OAAO,CAAC;CACnC;AAED,wDAAwD;AACxD,UAAU,gBAAgB;IACtB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAEvB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,GAAG,eAAe,EAAE,GAAG,SAAS,CAAC;CAC/F;AAmED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAClC,OAAO,CAAC,MAAM,EAAE,CAAC,CA6CnB"}
@@ -0,0 +1,157 @@
1
+ /**
2
+ * File-Based Routing — Auto-Discovery of Tools via Directory Structure
3
+ *
4
+ * Scans a directory at startup and auto-registers tools based on the
5
+ * file-system naming convention:
6
+ *
7
+ * ```
8
+ * src/tools/
9
+ * ├── billing/
10
+ * │ ├── get_invoice.ts → billing.get_invoice
11
+ * │ └── pay.ts → billing.pay
12
+ * └── users/
13
+ * ├── list.ts → users.list
14
+ * └── ban.ts → users.ban
15
+ * ```
16
+ *
17
+ * Each file must export a `GroupedToolBuilder` (via `defineTool()`,
18
+ * `createTool()`, `f.tool()`, etc.) as the **default export** or
19
+ * a named export called `tool`.
20
+ *
21
+ * **Benefits:**
22
+ * - Zero code orchestration — no central `index.ts` with 50 imports
23
+ * - Git-friendly — reduced merge conflicts (no shared import file)
24
+ * - Instant onboarding — "drop a file → it's a tool"
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * import { autoDiscover, ToolRegistry } from '@vinkius-core/mcp-fusion';
29
+ *
30
+ * const registry = new ToolRegistry<AppContext>();
31
+ *
32
+ * // Scan src/tools/ and register everything
33
+ * await autoDiscover(registry, './src/tools');
34
+ *
35
+ * // Or with options
36
+ * await autoDiscover(registry, './src/tools', {
37
+ * pattern: /\.tool\.ts$/, // only files ending in .tool.ts
38
+ * recursive: true, // scan subdirectories (default: true)
39
+ * separator: '.', // directory separator for tool names
40
+ * });
41
+ * ```
42
+ *
43
+ * @module
44
+ */
45
+ import { promises as fs } from 'node:fs';
46
+ import { join, resolve, relative, basename, extname, sep } from 'node:path';
47
+ import { pathToFileURL } from 'node:url';
48
+ // ── Internal ─────────────────────────────────────────────
49
+ const DEFAULT_PATTERN = /\.(ts|js|mjs|mts)$/;
50
+ const EXCLUDED_PATTERN = /\.(test|spec|d)\./;
51
+ /**
52
+ * Walk a directory tree and collect file paths matching the filter.
53
+ * @internal
54
+ */
55
+ async function walkDir(dir, pattern, recursive) {
56
+ const entries = await fs.readdir(dir, { withFileTypes: true });
57
+ const files = [];
58
+ for (const entry of entries) {
59
+ const fullPath = join(dir, entry.name);
60
+ if (entry.isDirectory() && recursive) {
61
+ const nested = await walkDir(fullPath, pattern, recursive);
62
+ files.push(...nested);
63
+ }
64
+ else if (entry.isFile() && pattern.test(entry.name) && !EXCLUDED_PATTERN.test(entry.name)) {
65
+ files.push(fullPath);
66
+ }
67
+ }
68
+ return files;
69
+ }
70
+ /**
71
+ * Check if a value looks like a ToolBuilder (duck typing).
72
+ * @internal
73
+ */
74
+ function isToolBuilder(value) {
75
+ return (typeof value === 'object' &&
76
+ value !== null &&
77
+ typeof value.getName === 'function');
78
+ }
79
+ /**
80
+ * Default export resolver: check default → tool → any exported builder.
81
+ * @internal
82
+ */
83
+ function defaultResolver(mod) {
84
+ // Priority 1: default export
85
+ const defaultExport = mod['default'];
86
+ if (isToolBuilder(defaultExport))
87
+ return defaultExport;
88
+ // Priority 2: named `tool` export
89
+ const toolExport = mod['tool'];
90
+ if (isToolBuilder(toolExport))
91
+ return toolExport;
92
+ // Priority 3: collect all exported builders
93
+ const builders = [];
94
+ for (const value of Object.values(mod)) {
95
+ if (isToolBuilder(value)) {
96
+ builders.push(value);
97
+ }
98
+ }
99
+ return builders.length > 0 ? builders : undefined;
100
+ }
101
+ // ── Public API ───────────────────────────────────────────
102
+ /**
103
+ * Scan a directory and auto-register all discovered tool builders.
104
+ *
105
+ * Eliminates the need for a central `index.ts` that manually imports
106
+ * and registers every tool. New tools are automatically picked up
107
+ * when they are dropped into the scanned directory.
108
+ *
109
+ * @param registry - A ToolRegistry instance to register discovered tools
110
+ * @param dir - Path to the tools directory (absolute or relative to CWD)
111
+ * @param options - Discovery options (pattern, recursive, loader, resolve)
112
+ * @returns Array of discovered file paths (for logging/debugging)
113
+ * @throws If the directory does not exist or is not readable
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const registry = new ToolRegistry<AppContext>();
118
+ * const files = await autoDiscover(registry, './src/tools');
119
+ * console.log(`Discovered ${files.length} tool files`);
120
+ * ```
121
+ */
122
+ export async function autoDiscover(registry, dir, options = {}) {
123
+ const { pattern = DEFAULT_PATTERN, recursive = true, loader = 'esm', resolve: customResolve, } = options;
124
+ const absoluteDir = resolve(dir);
125
+ const files = await walkDir(absoluteDir, pattern, recursive);
126
+ const discoveredFiles = [];
127
+ for (const filePath of files) {
128
+ try {
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ let mod;
131
+ if (loader === 'cjs') {
132
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
133
+ mod = require(filePath);
134
+ }
135
+ else {
136
+ const fileUrl = pathToFileURL(filePath).href;
137
+ mod = await import(fileUrl);
138
+ }
139
+ const resolver = customResolve ?? defaultResolver;
140
+ const result = resolver(mod);
141
+ if (!result)
142
+ continue;
143
+ const builders = Array.isArray(result) ? result : [result];
144
+ for (const builder of builders) {
145
+ registry.register(builder);
146
+ }
147
+ discoveredFiles.push(filePath);
148
+ }
149
+ catch {
150
+ // Skip files that fail to import (syntax errors, missing deps, etc.)
151
+ // In production, this should be logged via the observability layer
152
+ continue;
153
+ }
154
+ }
155
+ return discoveredFiles;
156
+ }
157
+ //# sourceMappingURL=autoDiscover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoDiscover.js","sourceRoot":"","sources":["../../src/server/autoDiscover.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,8 @@ export { resolveServer } from './ServerResolver.js';
3
3
  export { attachToServer, type AttachOptions, type DetachFn, type RegistryDelegate, } from './ServerAttachment.js';
4
4
  export type { ToolExposition, ExpositionConfig } from '../exposition/index.js';
5
5
  export { compileExposition, type FlatRoute, type ExpositionResult } from '../exposition/index.js';
6
+ export { autoDiscover } from './autoDiscover.js';
7
+ export type { AutoDiscoverOptions } from './autoDiscover.js';
8
+ export { createDevServer } from './DevServer.js';
9
+ export type { DevServerConfig, DevServer } from './DevServer.js';
6
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACH,cAAc,EACd,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,GAC3D,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACH,cAAc,EACd,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,GAC3D,MAAM,uBAAuB,CAAC;AAG/B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAGlG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -2,4 +2,8 @@
2
2
  export { resolveServer } from './ServerResolver.js';
3
3
  export { attachToServer, } from './ServerAttachment.js';
4
4
  export { compileExposition } from '../exposition/index.js';
5
+ // ── File-Based Routing ───────────────────────────────────
6
+ export { autoDiscover } from './autoDiscover.js';
7
+ // ── Dev Server (HMR) ────────────────────────────────────
8
+ export { createDevServer } from './DevServer.js';
5
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACH,cAAc,GAEjB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,iBAAiB,EAAyC,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACH,cAAc,GAEjB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAE,iBAAiB,EAAyC,MAAM,wBAAwB,CAAC;AAElG,4DAA4D;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,2DAA2D;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
@@ -28,4 +28,40 @@ export declare function validatePolicies(policies: readonly SyncPolicy[]): void;
28
28
  export declare function validateDefaults(defaults?: {
29
29
  readonly cacheControl?: CacheDirective;
30
30
  }): void;
31
+ /**
32
+ * Warning produced when two policies potentially overlap.
33
+ *
34
+ * Overlapping policies are not an error (first-match-wins is deterministic),
35
+ * but they can cause subtle configuration bugs when the user expects a
36
+ * more-specific policy to fire but a broader one shadows it.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const warnings = detectOverlaps(policies);
41
+ * warnings.forEach(w => console.warn(`[StateSync] ${w.message}`));
42
+ * ```
43
+ */
44
+ export interface OverlapWarning {
45
+ /** Human-readable description of the overlap. */
46
+ readonly message: string;
47
+ /** Index of the shadowing (earlier) policy. */
48
+ readonly shadowingIndex: number;
49
+ /** Index of the shadowed (later) policy. */
50
+ readonly shadowedIndex: number;
51
+ }
52
+ /**
53
+ * Detect potentially overlapping glob policies.
54
+ *
55
+ * Checks if a broader policy at index `i` could shadow a more-specific
56
+ * policy at index `j > i`. Uses GlobMatcher to test if the earlier
57
+ * pattern matches the later pattern's literal segments.
58
+ *
59
+ * This is a heuristic: it only catches cases where the later policy's
60
+ * `match` string (treated as a literal tool name) would match the
61
+ * earlier policy's glob. It does NOT do full set-intersection analysis.
62
+ *
63
+ * @param policies - The policies array to analyze
64
+ * @returns Array of overlap warnings (empty if no overlaps detected)
65
+ */
66
+ export declare function detectOverlaps(policies: readonly SyncPolicy[]): readonly OverlapWarning[];
31
67
  //# sourceMappingURL=PolicyValidator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PolicyValidator.d.ts","sourceRoot":"","sources":["../../src/state-sync/PolicyValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI7D,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAsC,CAAC;AAiExF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAetE;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC5B,QAAQ,CAAC,EAAE;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAA;CAAE,GACtD,IAAI,CAON"}
1
+ {"version":3,"file":"PolicyValidator.d.ts","sourceRoot":"","sources":["../../src/state-sync/PolicyValidator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAK7D,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAsC,CAAC;AAiExF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAetE;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC5B,QAAQ,CAAC,EAAE;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAA;CAAE,GACtD,IAAI,CAON;AAID;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,4CAA4C;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,GAAG,SAAS,cAAc,EAAE,CAuBzF"}
@@ -1,3 +1,4 @@
1
+ import { matchGlob } from './GlobMatcher.js';
1
2
  // ── Constants ────────────────────────────────────────────
2
3
  /** Valid cache directives — binary vocabulary, no max-age. */
3
4
  export const VALID_DIRECTIVES = new Set(['no-store', 'immutable']);
@@ -84,4 +85,38 @@ export function validateDefaults(defaults) {
84
85
  `Allowed: "no-store", "immutable".`);
85
86
  }
86
87
  }
88
+ /**
89
+ * Detect potentially overlapping glob policies.
90
+ *
91
+ * Checks if a broader policy at index `i` could shadow a more-specific
92
+ * policy at index `j > i`. Uses GlobMatcher to test if the earlier
93
+ * pattern matches the later pattern's literal segments.
94
+ *
95
+ * This is a heuristic: it only catches cases where the later policy's
96
+ * `match` string (treated as a literal tool name) would match the
97
+ * earlier policy's glob. It does NOT do full set-intersection analysis.
98
+ *
99
+ * @param policies - The policies array to analyze
100
+ * @returns Array of overlap warnings (empty if no overlaps detected)
101
+ */
102
+ export function detectOverlaps(policies) {
103
+ const warnings = [];
104
+ for (let i = 0; i < policies.length; i++) {
105
+ for (let j = i + 1; j < policies.length; j++) {
106
+ const earlier = policies[i].match;
107
+ const later = policies[j].match;
108
+ // If the later policy's match pattern (as a literal name)
109
+ // would be caught by the earlier policy's glob, it's shadowed.
110
+ if (matchGlob(earlier, later)) {
111
+ warnings.push({
112
+ message: `policy[${i}] (match: "${earlier}") shadows policy[${j}] (match: "${later}"). ` +
113
+ `The later policy will never match because first-match-wins applies.`,
114
+ shadowingIndex: i,
115
+ shadowedIndex: j,
116
+ });
117
+ }
118
+ }
119
+ }
120
+ return warnings;
121
+ }
87
122
  //# sourceMappingURL=PolicyValidator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PolicyValidator.js","sourceRoot":"","sources":["../../src/state-sync/PolicyValidator.ts"],"names":[],"mappings":"AAaA,4DAA4D;AAE5D,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAExF,6DAA6D;AAC7D,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAEnD,4DAA4D;AAE5D;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,OAAe,EAAE,KAAa,EAAE,MAAc;IACnE,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,KAAK,KAAK,8BAA8B,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACX,GAAG,MAAM,KAAK,KAAK,aAAa,OAAO,0BAA0B,GAAG,KAAK;gBACzE,6CAA6C,CAChD,CAAC;QACN,CAAC;IACL,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,SAAiB,EAAE,MAAc;IAC3D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACX,GAAG,MAAM,2BAA2B,SAAS,KAAK;YAClD,mCAAmC,CACtC,CAAC;IACN,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,sBAAsB,CAAC,WAAoB,EAAE,MAAc;IAChE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,mCAAmC,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,WAAuB,EAAE,CAAC;QAC5C,eAAe,CAAC,OAAO,EAAE,wDAAwD,EAAE,MAAM,CAAC,CAAC;IAC/F,CAAC;AACL,CAAC;AAED,4DAA4D;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAA+B;IAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,CAAC;QAExC,eAAe,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAE5C,IAAI,CAAC,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,oBAAoB,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,sBAAsB,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;IACL,CAAC;AACL,CAAC;AAED,4DAA4D;AAE5D;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC5B,QAAqD;IAErD,IAAI,QAAQ,EAAE,YAAY,KAAK,SAAS,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QACvF,MAAM,IAAI,KAAK,CACX,mCAAmC,QAAQ,CAAC,YAAY,gBAAgB;YACxE,mCAAmC,CACtC,CAAC;IACN,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"PolicyValidator.js","sourceRoot":"","sources":["../../src/state-sync/PolicyValidator.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseDecorator.d.ts","sourceRoot":"","sources":["../../src/state-sync/ResponseDecorator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,MAAM,GACjB,YAAY,CAUd"}
1
+ {"version":3,"file":"ResponseDecorator.d.ts","sourceRoot":"","sources":["../../src/state-sync/ResponseDecorator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,MAAM,GACjB,YAAY,CAUd"}
@@ -1,3 +1,4 @@
1
+ import { escapeXmlAttr } from '../core/response.js';
1
2
  /**
2
3
  * Prepend a System invalidation content block to a tool call response.
3
4
  *
@@ -11,7 +12,7 @@ export function decorateResponse(result, patterns, causedBy) {
11
12
  return {
12
13
  ...result,
13
14
  content: [
14
- { type: 'text', text: `<cache_invalidation cause="${causedBy}" domains="${domains}" />` },
15
+ { type: 'text', text: `<cache_invalidation cause="${escapeXmlAttr(causedBy)}" domains="${escapeXmlAttr(domains)}" />` },
15
16
  ...result.content,
16
17
  ],
17
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ResponseDecorator.js","sourceRoot":"","sources":["../../src/state-sync/ResponseDecorator.ts"],"names":[],"mappings":"AAwBA;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC5B,MAAoB,EACpB,QAA2B,EAC3B,QAAgB;IAEhB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpC,OAAO;QACH,GAAG,MAAM;QACT,OAAO,EAAE;YACL,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,8BAA8B,QAAQ,cAAc,OAAO,MAAM,EAAE;YAClG,GAAG,MAAM,CAAC,OAAO;SACpB;KACJ,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"ResponseDecorator.js","sourceRoot":"","sources":["../../src/state-sync/ResponseDecorator.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC5B,MAAoB,EACpB,QAA2B,EAC3B,QAAgB;IAEhB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEpC,OAAO;QACH,GAAG,MAAM;QACT,OAAO,EAAE;YACL,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,8BAA8B,aAAa,CAAC,QAAQ,CAAC,cAAc,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE;YAChI,GAAG,MAAM,CAAC,OAAO;SACpB;KACJ,CAAC;AACN,CAAC"}
@@ -40,6 +40,8 @@ import type { ToolResponse } from '../core/response.js';
40
40
  import type { StateSyncConfig } from './types.js';
41
41
  export declare class StateSyncLayer {
42
42
  private readonly _engine;
43
+ private readonly _onInvalidation?;
44
+ private readonly _notificationSink?;
43
45
  /**
44
46
  * Per-tool-name cache of decorated McpTool objects.
45
47
  *
@@ -49,10 +51,9 @@ export declare class StateSyncLayer {
49
51
  * on every `tools/list` request — which is the hottest path since
50
52
  * it runs at the start of every LLM conversation.
51
53
  *
52
- * The cache key is the tool name + JSON input schema hash to detect
53
- * changes in the underlying tool definition. In practice, tool
54
- * definitions are immutable after registration, so the cache
55
- * hit rate approaches 100%.
54
+ * The cache key is the tool name tool definitions are immutable
55
+ * after registration, so the name alone is sufficient.
56
+ * Cache hit rate approaches 100%.
56
57
  */
57
58
  private readonly _decoratedToolCache;
58
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"StateSyncLayer.d.ts","sourceRoot":"","sources":["../../src/state-sync/StateSyncLayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAMlD,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA8B;IAElE;;;;;;;;;OASG;gBACS,MAAM,EAAE,eAAe;IAInC;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE;IAI1C;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY;IAapE;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAQ9B"}
1
+ {"version":3,"file":"StateSyncLayer.d.ts","sourceRoot":"","sources":["../../src/state-sync/StateSyncLayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,KAAK,IAAI,IAAI,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAA2C,MAAM,YAAY,CAAC;AAM3F,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAmD;IACpF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAA6E;IAEhH;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA8B;IAElE;;;;;;;;;OASG;gBACS,MAAM,EAAE,eAAe;IAMnC;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE;IAI1C;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY;IAuCpE;;;;;;;;OAQG;IACH,OAAO,CAAC,mBAAmB;CAQ9B"}
@@ -42,6 +42,8 @@ import { resolveInvalidations } from './CausalEngine.js';
42
42
  import { decorateResponse } from './ResponseDecorator.js';
43
43
  export class StateSyncLayer {
44
44
  _engine;
45
+ _onInvalidation;
46
+ _notificationSink;
45
47
  /**
46
48
  * Per-tool-name cache of decorated McpTool objects.
47
49
  *
@@ -51,10 +53,9 @@ export class StateSyncLayer {
51
53
  * on every `tools/list` request — which is the hottest path since
52
54
  * it runs at the start of every LLM conversation.
53
55
  *
54
- * The cache key is the tool name + JSON input schema hash to detect
55
- * changes in the underlying tool definition. In practice, tool
56
- * definitions are immutable after registration, so the cache
57
- * hit rate approaches 100%.
56
+ * The cache key is the tool name tool definitions are immutable
57
+ * after registration, so the name alone is sufficient.
58
+ * Cache hit rate approaches 100%.
58
59
  */
59
60
  _decoratedToolCache = new Map();
60
61
  /**
@@ -69,6 +70,8 @@ export class StateSyncLayer {
69
70
  */
70
71
  constructor(config) {
71
72
  this._engine = new PolicyEngine(config.policies, config.defaults);
73
+ this._onInvalidation = config.onInvalidation;
74
+ this._notificationSink = config.notificationSink;
72
75
  }
73
76
  /**
74
77
  * Decorate all tool descriptions with their resolved Cache-Control directives.
@@ -101,6 +104,34 @@ export class StateSyncLayer {
101
104
  const policy = this._engine.resolve(toolName);
102
105
  const invalidations = resolveInvalidations(policy, result.isError ?? false);
103
106
  if (invalidations.length > 0) {
107
+ // Fire observability hook (sync, fire-and-forget)
108
+ if (this._onInvalidation) {
109
+ const event = {
110
+ causedBy: toolName,
111
+ patterns: invalidations,
112
+ timestamp: new Date().toISOString(),
113
+ };
114
+ try {
115
+ this._onInvalidation(event);
116
+ }
117
+ catch { /* observer must not break the pipeline */ }
118
+ }
119
+ // Emit protocol-level notifications (fire-and-forget, safe for async sinks)
120
+ if (this._notificationSink) {
121
+ for (const pattern of invalidations) {
122
+ const notification = {
123
+ method: 'notifications/resources/updated',
124
+ params: { uri: `fusion://stale/${pattern}` },
125
+ };
126
+ try {
127
+ const maybePromise = this._notificationSink(notification);
128
+ if (maybePromise instanceof Promise) {
129
+ maybePromise.catch(() => { });
130
+ }
131
+ }
132
+ catch { /* swallow sync errors — best-effort */ }
133
+ }
134
+ }
104
135
  return decorateResponse(result, invalidations, toolName);
105
136
  }
106
137
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"StateSyncLayer.js","sourceRoot":"","sources":["../../src/state-sync/StateSyncLayer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAwB,MAAM,oCAAoC,CAAC;AAG1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,MAAM,OAAO,cAAc;IACN,OAAO,CAAe;IAEvC;;;;;;;;;;;;;OAaG;IACc,mBAAmB,GAAG,IAAI,GAAG,EAAmB,CAAC;IAElE;;;;;;;;;OASG;IACH,YAAY,MAAuB;QAC/B,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACtE,CAAC;IAED;;;;;;;;;;;OAWG;IACH,aAAa,CAAC,KAAgB;QAC1B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,QAAgB,EAAE,MAAoB;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,aAAa,GAAG,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;QAE5E,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,wDAAwD;IAExD;;;;;;;;OAQG;IACK,mBAAmB,CAAC,IAAa;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAE1B,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7E,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnD,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ"}
1
+ {"version":3,"file":"StateSyncLayer.js","sourceRoot":"","sources":["../../src/state-sync/StateSyncLayer.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,9 @@
18
18
  * @module
19
19
  */
20
20
  export { StateSyncLayer } from './StateSyncLayer.js';
21
- export type { CacheDirective, SyncPolicy, StateSyncConfig, ResolvedPolicy, } from './types.js';
21
+ export type { CacheDirective, SyncPolicy, StateSyncConfig, ResolvedPolicy, InvalidationEvent, ResourceNotification, } from './types.js';
22
22
  export { PolicyEngine } from './PolicyEngine.js';
23
23
  export { matchGlob } from './GlobMatcher.js';
24
+ export { detectOverlaps } from './PolicyValidator.js';
25
+ export type { OverlapWarning } from './PolicyValidator.js';
24
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,YAAY,EACR,cAAc,EACd,UAAU,EACV,eAAe,EACf,cAAc,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,YAAY,EACR,cAAc,EACd,UAAU,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -22,4 +22,5 @@ export { StateSyncLayer } from './StateSyncLayer.js';
22
22
  // ── Infrastructure (advanced usage) ──────────────────────
23
23
  export { PolicyEngine } from './PolicyEngine.js';
24
24
  export { matchGlob } from './GlobMatcher.js';
25
+ export { detectOverlaps } from './PolicyValidator.js';
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4DAA4D;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAUrD,4DAA4D;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/state-sync/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4DAA4D;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAYrD,4DAA4D;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -96,6 +96,68 @@ export interface StateSyncConfig {
96
96
  readonly defaults?: {
97
97
  readonly cacheControl?: CacheDirective;
98
98
  };
99
+ /**
100
+ * Observability hook invoked after each causal invalidation event.
101
+ *
102
+ * Use this to log, trace, or count invalidation events without
103
+ * coupling the state-sync engine to a specific observability backend.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * stateSync: {
108
+ * policies: [...],
109
+ * onInvalidation: (event) => {
110
+ * console.log(`[StateSync] ${event.causedBy} invalidated ${event.patterns.join(', ')}`);
111
+ * metrics.increment('statesync.invalidation', { tool: event.causedBy });
112
+ * },
113
+ * }
114
+ * ```
115
+ */
116
+ readonly onInvalidation?: (event: InvalidationEvent) => void;
117
+ /**
118
+ * Protocol-level notification sink for MCP resource change events.
119
+ *
120
+ * When provided, causal invalidation also emits
121
+ * `notifications/resources/updated` MCP protocol messages
122
+ * in addition to the in-band XML signal.
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * stateSync: {
127
+ * policies: [...],
128
+ * notificationSink: async (notification) => {
129
+ * await server.sendNotification(notification);
130
+ * },
131
+ * }
132
+ * ```
133
+ */
134
+ readonly notificationSink?: (notification: ResourceNotification) => void | Promise<void>;
135
+ }
136
+ /**
137
+ * Event emitted when causal invalidation is triggered.
138
+ *
139
+ * @see {@link StateSyncConfig.onInvalidation}
140
+ */
141
+ export interface InvalidationEvent {
142
+ /** The tool that caused the invalidation (fully qualified name). */
143
+ readonly causedBy: string;
144
+ /** Glob patterns that were invalidated. */
145
+ readonly patterns: readonly string[];
146
+ /** ISO-8601 timestamp of the event. */
147
+ readonly timestamp: string;
148
+ }
149
+ /**
150
+ * MCP protocol notification for resource changes.
151
+ *
152
+ * Mirrors the `notifications/resources/updated` JSON-RPC message.
153
+ *
154
+ * @see {@link StateSyncConfig.notificationSink}
155
+ */
156
+ export interface ResourceNotification {
157
+ readonly method: 'notifications/resources/updated';
158
+ readonly params: {
159
+ readonly uri: string;
160
+ };
99
161
  }
100
162
  /**
101
163
  * Result of resolving a policy for a specific tool name.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state-sync/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAItD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,UAAU;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IAEvC;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IAEzC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAChB,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;KAC1C,CAAC;CACL;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/state-sync/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAItD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,UAAU;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IAEvC;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAID;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,eAAe;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IAEzC,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAChB,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;KAC1C,CAAC;IAEF;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAE7D;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5F;AAID;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,uCAAuC;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACjC,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE;QACb,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;KACxB,CAAC;CACL;AAID;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC;IACvC,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C"}