@happyvertical/smrt-scanner 0.47.0 → 0.47.2

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/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as ManifestAdapter, t as OxcScanner } from "./chunks/scanner-9p-PUN-X.js";
2
+ import { n as ManifestAdapter, t as OxcScanner } from "./chunks/scanner-CxUeI0FI.js";
3
3
  import { readFileSync, writeFileSync } from "node:fs";
4
4
  import { dirname, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
package/dist/index.d.ts CHANGED
@@ -13,10 +13,15 @@ export declare interface AgentSurfaceCapability {
13
13
  }
14
14
 
15
15
  /**
16
- * A recognized declaration that is not emittable.
16
+ * Something a reader of the emitted surface has to know about a declaration.
17
17
  *
18
- * Never a silent omission: every message names `useWebMcpTool`, the escape
19
- * hatch for a genuinely computed tool set.
18
+ * Two kinds, and the difference is whether the entry survived. Every code but
19
+ * `tool-name-collision` reports a declaration that is NOT emitted — never a
20
+ * silent omission, so each of those messages names `useWebMcpTool`, the escape
21
+ * hatch for a genuinely computed tool set. A `tool-name-collision` is
22
+ * advisory: the declaration IS emitted, and the diagnostic records that its
23
+ * derived WebMCP tool name is already spoken for by something outside the
24
+ * declared surface.
20
25
  */
21
26
  export declare interface AgentSurfaceDiagnostic {
22
27
  code: AgentSurfaceDiagnosticCode;
@@ -28,7 +33,7 @@ export declare interface AgentSurfaceDiagnostic {
28
33
  }
29
34
 
30
35
  /** Why a recognized declaration could not be emitted. */
31
- export declare type AgentSurfaceDiagnosticCode = 'non-literal-argument' | 'not-module-scope' | 'argument-count' | 'incomplete-declaration' | 'invalid-identity' | 'svelte-declaration' | 'duplicate-identity';
36
+ export declare type AgentSurfaceDiagnosticCode = 'non-literal-argument' | 'not-module-scope' | 'argument-count' | 'incomplete-declaration' | 'invalid-identity' | 'svelte-declaration' | 'duplicate-identity' | 'tool-name-collision';
32
37
 
33
38
  /**
34
39
  * Effect classification, mirroring `CapabilityEffect` in
@@ -92,6 +97,41 @@ export declare type AgentSurfacePlaybookStep = {
92
97
  id: string;
93
98
  };
94
99
 
100
+ export declare interface AgentSurfaceToolNameOptions {
101
+ /**
102
+ * Generated model tool names for the SAME manifest, already filtered by the
103
+ * exposure policy.
104
+ *
105
+ * Filtered, not enumerated: comparing against every verb a class COULD
106
+ * expose would report collisions with tools that are never registered.
107
+ * `buildWebMcpToolDefinitions` in `@happyvertical/smrt-core/vite-plugin` is
108
+ * the function that emits the runtime definitions, so its output is the only
109
+ * honest input here.
110
+ */
111
+ generatedToolNames?: readonly GeneratedModelToolName[];
112
+ /**
113
+ * Prefixes the fixed UI tools are mounted under, defaulting to the
114
+ * registrar's own `smrt_ui_`.
115
+ *
116
+ * Supplied for the same reason `generatedToolNames` is: a name is compared
117
+ * against tools that will really register. Quantifying over every prefix an
118
+ * app COULD have configured — deriving the would-be prefix from the name —
119
+ * looks like more coverage and is the opposite. Under the default it has no
120
+ * true positive at all, because an id flattening to `smrt_ui_*` is rejected
121
+ * by {@link intentIdentityProblem} before it can become an entry, so every
122
+ * diagnostic such a rule emits for a default-configured app is false. A
123
+ * warning that is always wrong where it fires is worse than silence: it is
124
+ * persisted into the knowledge artifact, counted by `smrt doctor`, and
125
+ * clearable only by renaming an intent that was correct.
126
+ *
127
+ * There is no build-time source for this today — `ui.prefix` is a runtime
128
+ * `<Provider webmcp={{ ui: { prefix } }}>` prop — so the default leaves this
129
+ * half dormant. That is the honest state of it, and the seam is ready for
130
+ * the caller that can fill it.
131
+ */
132
+ uiToolPrefixes?: readonly string[];
133
+ }
134
+
95
135
  declare interface ArrayExpression extends BaseNode {
96
136
  type: 'ArrayExpression';
97
137
  elements: (Expression | SpreadElement | null)[];
@@ -129,6 +169,57 @@ declare interface CallExpression extends BaseNode {
129
169
  typeParameters?: TSTypeParameterInstantiation;
130
170
  }
131
171
 
172
+ /**
173
+ * Report an emitted intent whose derived WebMCP tool name is already spoken
174
+ * for by something OUTSIDE the declared surface (#2725).
175
+ *
176
+ * `mergeAgentSurfaces` resolves the collisions it can see on its own —
177
+ * intent vs intent, where `intentToolName` is not injective. It cannot see the
178
+ * two sources that live outside the declaration set:
179
+ *
180
+ * - **generated model tools**, `${className.toLowerCase()}_${action}`, so
181
+ * `defineIntent({ id: 'product.list' })` lands exactly on `Product.list`;
182
+ * - **the six fixed UI tools** under a CUSTOM `webmcp.ui.prefix`. The default
183
+ * `smrt_ui_` is already a hard rejection in {@link intentIdentityProblem},
184
+ * mirroring `defineIntent`; a custom prefix is not, because `defineIntent`
185
+ * accepts such an id and the intent really does register.
186
+ *
187
+ * ### These are warnings, not drops — unlike intent vs intent
188
+ *
189
+ * The asymmetry is real and it is the whole reason this is a separate pass.
190
+ * Two colliding intents are a closed question: `defineIntent` REJECTS the
191
+ * second declaration, so only one can exist and emitting both would overstate
192
+ * the surface by an entry that cannot be. Neither collision here is closed:
193
+ *
194
+ * - `defineIntent` accepts the intent, so the declaration is real and the
195
+ * entry belongs in the artifact. Dropping it would make the emitted surface
196
+ * disagree with the source, which is the failure this module exists to
197
+ * prevent;
198
+ * - which registration survives is decided at mount by the document-global
199
+ * tool-name lock (#2613), which rejects the second with a
200
+ * `WebMcpToolNameCollisionError` naming the owner. That is a runtime answer
201
+ * to a question the build can already see coming, and it costs whoever loses
202
+ * its tool; the build-time notice is the earlier, cheaper one;
203
+ * - and whether it happens at all depends on runtime values no artifact
204
+ * records: a WebMCP `namespace` moves every generated tool out of the way,
205
+ * an `effects` policy can exclude the action, and a page need not mount
206
+ * both. A build-time drop would be a guess about all three.
207
+ *
208
+ * So the entry stays and the report is advisory. The message names both sides,
209
+ * the consequence, and — because those runtime values are unknowable here and
210
+ * a `namespace` genuinely dissolves the collision — the precondition under
211
+ * which it holds. Without that last part a namespaced app gets a notice that
212
+ * is always wrong where it fires, recommending the very remedy it already
213
+ * applied, with renaming a correct intent as the only clearing action. That is
214
+ * the standard `uiToolPrefixes` exists to meet; the generated half has to meet
215
+ * it too, and it does so in the message because the caller CAN supply
216
+ * namespaced names when it knows them.
217
+ *
218
+ * @param surface - A MERGED surface; intent-vs-intent losers are already gone.
219
+ * @returns Diagnostics only. The caller appends them; nothing is removed.
220
+ */
221
+ export declare function checkAgentSurfaceToolNames(surface: AgentSurface, options?: AgentSurfaceToolNameOptions): AgentSurfaceDiagnostic[];
222
+
132
223
  declare interface ClassBody extends BaseNode {
133
224
  type: 'ClassBody';
134
225
  body: ClassElement[];
@@ -314,6 +405,28 @@ declare interface FunctionExpression extends BaseNode {
314
405
  body: BlockStatement;
315
406
  }
316
407
 
408
+ /**
409
+ * One WebMCP tool name the build will register for a generated model action,
410
+ * supplied by the caller that knows the exposure policy.
411
+ */
412
+ export declare interface GeneratedModelToolName {
413
+ /**
414
+ * The tool name EXACTLY as it will be registered.
415
+ *
416
+ * This pass never derives a generated name and never applies a namespace of
417
+ * its own: it compares the strings it is handed. That is deliberate. The
418
+ * WebMCP `namespace` is a runtime `<Provider webmcp={{ namespace }}>` value
419
+ * that no build artifact records, so inventing a build-time declaration of
420
+ * it here would create a second place to say what the provider already says,
421
+ * free to disagree with it silently. Taking names instead means a caller
422
+ * that ever does know the namespace qualifies them itself and nothing in
423
+ * this module changes.
424
+ */
425
+ name: string;
426
+ /** What owns that name, for the message — e.g. `Product.list`. */
427
+ declaredBy?: string;
428
+ }
429
+
317
430
  declare interface Identifier extends BaseNode {
318
431
  type: 'Identifier';
319
432
  name: string;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { _ as sourceMayDeclareAgentSurface, a as parseFile, c as discoverSourceFiles, d as emptyAgentSurface, f as extractAgentSurface, g as scanSvelteAgentSurface, h as mergeAgentSurfaces, i as parseAgentSurfaceFile, l as normalizeGlobSeparators, m as isPrunedAgentSurfacePath, n as ManifestAdapter, o as parseSource, p as isAgentSurfaceSourcePath, r as extractSmrtImports, s as InheritanceResolver, t as OxcScanner, u as relativeGlobToCwd } from "./chunks/scanner-9p-PUN-X.js";
1
+ import { _ as scanSvelteAgentSurface, a as parseFile, c as discoverSourceFiles, d as checkAgentSurfaceToolNames, f as emptyAgentSurface, g as mergeAgentSurfaces, h as isPrunedAgentSurfacePath, i as parseAgentSurfaceFile, l as normalizeGlobSeparators, m as isAgentSurfaceSourcePath, n as ManifestAdapter, o as parseSource, p as extractAgentSurface, r as extractSmrtImports, s as InheritanceResolver, t as OxcScanner, u as relativeGlobToCwd, v as sourceMayDeclareAgentSurface } from "./chunks/scanner-CxUeI0FI.js";
2
2
  import "./types.js";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { basename, resolve } from "node:path";
@@ -272,6 +272,6 @@ async function verifyManifestCompleteness(options) {
272
272
  };
273
273
  }
274
274
  //#endregion
275
- export { InheritanceResolver, ManifestAdapter, OxcScanner, classifyNumericFieldName, discoverSourceFiles, emptyAgentSurface, extractAgentSurface, extractSmrtImports, isAgentSurfaceSourcePath, isPrunedAgentSurfacePath, lintNumericPrecision, mergeAgentSurfaces, normalizeGlobSeparators, parseAgentSurfaceFile, parseFile, parseSource, relativeGlobToCwd, scanSvelteAgentSurface, sourceMayContainNumericPrecisionIssue, sourceMayDeclareAgentSurface, splitIdentifierWords, verifyManifestCompleteness };
275
+ export { InheritanceResolver, ManifestAdapter, OxcScanner, checkAgentSurfaceToolNames, classifyNumericFieldName, discoverSourceFiles, emptyAgentSurface, extractAgentSurface, extractSmrtImports, isAgentSurfaceSourcePath, isPrunedAgentSurfacePath, lintNumericPrecision, mergeAgentSurfaces, normalizeGlobSeparators, parseAgentSurfaceFile, parseFile, parseSource, relativeGlobToCwd, scanSvelteAgentSurface, sourceMayContainNumericPrecisionIssue, sourceMayDeclareAgentSurface, splitIdentifierWords, verifyManifestCompleteness };
276
276
 
277
277
  //# sourceMappingURL=index.js.map
package/dist/types.d.ts CHANGED
@@ -13,10 +13,15 @@ export declare interface AgentSurfaceCapability {
13
13
  }
14
14
 
15
15
  /**
16
- * A recognized declaration that is not emittable.
16
+ * Something a reader of the emitted surface has to know about a declaration.
17
17
  *
18
- * Never a silent omission: every message names `useWebMcpTool`, the escape
19
- * hatch for a genuinely computed tool set.
18
+ * Two kinds, and the difference is whether the entry survived. Every code but
19
+ * `tool-name-collision` reports a declaration that is NOT emitted — never a
20
+ * silent omission, so each of those messages names `useWebMcpTool`, the escape
21
+ * hatch for a genuinely computed tool set. A `tool-name-collision` is
22
+ * advisory: the declaration IS emitted, and the diagnostic records that its
23
+ * derived WebMCP tool name is already spoken for by something outside the
24
+ * declared surface.
20
25
  */
21
26
  export declare interface AgentSurfaceDiagnostic {
22
27
  code: AgentSurfaceDiagnosticCode;
@@ -28,7 +33,7 @@ export declare interface AgentSurfaceDiagnostic {
28
33
  }
29
34
 
30
35
  /** Why a recognized declaration could not be emitted. */
31
- export declare type AgentSurfaceDiagnosticCode = 'non-literal-argument' | 'not-module-scope' | 'argument-count' | 'incomplete-declaration' | 'invalid-identity' | 'svelte-declaration' | 'duplicate-identity';
36
+ export declare type AgentSurfaceDiagnosticCode = 'non-literal-argument' | 'not-module-scope' | 'argument-count' | 'incomplete-declaration' | 'invalid-identity' | 'svelte-declaration' | 'duplicate-identity' | 'tool-name-collision';
32
37
 
33
38
  /**
34
39
  * Effect classification, mirroring `CapabilityEffect` in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-scanner",
3
- "version": "0.47.0",
3
+ "version": "0.47.2",
4
4
  "description": "High-performance TypeScript scanner using OXC for SMRT manifest generation",
5
5
  "author": "HappyVertical",
6
6
  "type": "module",