@silkweave/nestjs 3.1.0 → 3.2.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/README.md +34 -3
- package/build/index.d.mts +54 -10
- package/build/index.d.mts.map +1 -1
- package/build/index.mjs +108 -16
- package/build/index.mjs.map +1 -1
- package/build/mcp.d.mts +11 -1
- package/build/mcp.d.mts.map +1 -1
- package/build/mcp.mjs +5 -2
- package/build/mcp.mjs.map +1 -1
- package/build/trpc.d.mts +1 -1
- package/build/typegen.d.mts +1 -1
- package/build/{types-wmI5n_7i.d.mts → types-6rbW7fLE.d.mts} +34 -5
- package/build/{types-wmI5n_7i.d.mts.map → types-6rbW7fLE.d.mts.map} +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -132,7 +132,10 @@ Exposes the decorated controller route as an MCP tool. Every option is optional.
|
|
|
132
132
|
| `description` | `string` | `@ApiOperation` summary/description, else generated | Tool description |
|
|
133
133
|
| `input` | `Record<string, z.ZodType> \| z.ZodObject` | - | Zod override merged over the reflected fields (per-field). A raw shape (`{ field: z.string() }`) **or** a whole `z.object({ ... })` (its `.shape` is unwrapped). The escape hatch for shapes reflection can't express - discriminated unions, custom validators, `@Transform`. It **adds to** the reflected fields; it does not replace them (see the warning below) |
|
|
134
134
|
| `pipes` | `'apply' \| 'skip'` | `'apply'` | Whether to run parameter-bound pipes (`@Param('id', ParseIntPipe)`) when re-binding |
|
|
135
|
-
| `result` | `'json' \| 'smart'` | `'
|
|
135
|
+
| `result` | `'json' \| 'smart' \| 'structured'` | `'json'` | MCP result format - `'json'` returns compact JSON text (`jsonToolResult`); `'smart'` inlines small payloads and offloads large ones to an embedded resource (`smartToolResult`); `'structured'` declares the tool's output schema as an MCP `outputSchema` contract and ships schema-parsed `structuredContent`. A client `_meta.disposition` overrides `'json'`/`'smart'` but never `'structured'`. `'structured'` **requires an explicit output schema** (`@Mcp({ output })` or `@Trpc({ output })`) - a reflected `@ApiOkResponse` is not accepted and boot-errors, since reflection is one level deep and must not silently become a hard, call-failing contract |
|
|
136
|
+
| `output` | `z.ZodType \| Type \| Record<string, z.ZodType>` | - | Explicit output schema backing `result: 'structured'` - a Zod type, DTO class, or raw shape (like `@Trpc({ output })`; wins over it when both are set). The parsed (extra-fields-stripped) result ships as `structuredContent`, so returning a wider object than the schema is safe |
|
|
137
|
+
| `annotations` | `ToolAnnotations` | verb-derived | MCP tool annotations merged over the verb-derived defaults: `@Get` ⇒ `{ readOnlyHint: true, idempotentHint: true }`, `@Put` ⇒ `{ readOnlyHint: false, idempotentHint: true }`, `@Delete` ⇒ `{ readOnlyHint: false, destructiveHint: true, idempotentHint: true }`, else `{ readOnlyHint: false }`. Set a field to override its derived value (e.g. `{ destructiveHint: true }` on a POST that deletes) |
|
|
138
|
+
| `tags` | `string[]` | - | Free-form grouping labels carried on the synthesized action (e.g. `['leads', 'write']`) for the `mcp({ filterActions })` per-request filter to match on |
|
|
136
139
|
|
|
137
140
|
### Result format
|
|
138
141
|
|
|
@@ -142,11 +145,11 @@ Exposes the decorated controller route as an MCP tool. Every option is optional.
|
|
|
142
145
|
SilkweaveModule.forRoot({
|
|
143
146
|
silkweave: { name: 'my-api', version: '1.0.0' },
|
|
144
147
|
adapters: [mcp()],
|
|
145
|
-
defaultResult: '
|
|
148
|
+
defaultResult: 'smart' // module-wide default; a per-method @Mcp({ result }) still wins
|
|
146
149
|
})
|
|
147
150
|
```
|
|
148
151
|
|
|
149
|
-
Precedence (highest first): a client's per-call `_meta.disposition` → `@Mcp({ result })` → module `defaultResult` → `'smart'
|
|
152
|
+
Precedence (highest first): a client's per-call `_meta.disposition` → `@Mcp({ result })` → module `defaultResult` → `'json'`. (Before 3.2 the fallback was `'smart'`; set `defaultResult: 'smart'` to restore payload sideloading module-wide.) `result: 'structured'` sits outside this chain - a structured tool's contract cannot be demoted per-call.
|
|
150
153
|
|
|
151
154
|
## How reflection works
|
|
152
155
|
|
|
@@ -204,6 +207,7 @@ Mounts the MCP Streamable HTTP transport directly at `basePath`, with sideload (
|
|
|
204
207
|
| `cors` | `CorsOptions \| boolean` | `true` | CORS config |
|
|
205
208
|
| `sideloadResources` | `boolean` | `true` | Mount `{basePath}/resource/:id` |
|
|
206
209
|
| `resourceDir` | `string` | `'resources'` | Directory the sideload route reads from |
|
|
210
|
+
| `filterActions` | `FilterActions` | - | Per-request tool filter, applied before tools are registered on every `POST {basePath}` (the stateless transport recomputes the tool list per request, so e.g. API-key permission changes apply on the next `tools/list`). Receives the synthesized actions (with their `@Mcp({ tags })`) and a request stand-in `{ headers, url, method, toolName }`; may be async. A throw surfaces as its `SilkweaveError.statusCode` (e.g. 401 for an invalid key) with a JSON-RPC error body, or 500 for other errors - never an empty tool list |
|
|
207
211
|
|
|
208
212
|
## tRPC
|
|
209
213
|
|
|
@@ -353,6 +357,33 @@ The allow-list is explicit-by-class on purpose - a blanket "run every global" wo
|
|
|
353
357
|
|
|
354
358
|
Controllers are normal Nest providers - inject services via the constructor as usual.
|
|
355
359
|
|
|
360
|
+
## Telemetry
|
|
361
|
+
|
|
362
|
+
Pass a `SilkweaveTelemetry` **class token** to `forRoot` and every MCP tool call and tRPC procedure invocation reports one `ToolCallEvent` - the service is a regular injectable (resolved through DI at call time), so it can use your logger, config, or repositories:
|
|
363
|
+
|
|
364
|
+
```ts
|
|
365
|
+
@Injectable()
|
|
366
|
+
export class ToolTelemetryService implements SilkweaveTelemetry {
|
|
367
|
+
constructor(private readonly logger: MyLogger) {}
|
|
368
|
+
onToolCall(event: ToolCallEvent) {
|
|
369
|
+
// { action, tool, transport: 'mcp' | 'trpc', durationMs, ok, errorCode?, errorMessage?, resultBytes?, sideloaded?, context }
|
|
370
|
+
const auth = event.context.getOptional('auth')
|
|
371
|
+
this.logger.info('tool_call', { tool: event.tool, transport: event.transport, durationMs: event.durationMs, ok: event.ok, userId: auth?.userId })
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
SilkweaveModule.forRoot({
|
|
376
|
+
silkweave: { name: 'app', description: 'My App', version: '1.0.0' },
|
|
377
|
+
adapters: [mcp({ basePath: '/mcp' }), trpc({ basePath: '/trpc' })],
|
|
378
|
+
telemetry: ToolTelemetryService // must also be a provider in one of your modules
|
|
379
|
+
})
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
- **Exactly one event per call.** MCP events are emitted from the MCP registrar (and carry `resultBytes`/`sideloaded` - metrics only that layer knows); tRPC events from the synthesized action wrapper. Guard denials count as failed calls (`ok: false`, `errorCode: 'http_error'`, message from the mapped `HttpException`) on either transport.
|
|
383
|
+
- **Fire-and-forget.** The hook is never awaited on the call path; throws/rejections are logged and swallowed - telemetry can never fail, slow, or reorder a call.
|
|
384
|
+
- Subscriptions (`async *` routes) report `durationMs` across full stream consumption.
|
|
385
|
+
- The event carries the tool's **wire name** (`LeadsBulkUpdate` over MCP, `leadsBulkUpdate` over tRPC) plus the action name, so one dashboard can group across transports.
|
|
386
|
+
|
|
356
387
|
## What does *not* run
|
|
357
388
|
|
|
358
389
|
Because the handler is invoked directly (not through Nest's HTTP request pipeline), the following do **not** apply on a tool call - only `@UseGuards()` (plus any opted-in `globalGuards`) and parameter-bound pipes do:
|
package/build/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as openapiSchemaToField, a as SilkweaveTelemetry, b as typeTokenToBase, c as buildOpenApiLookup, d as apiPropertyToField, f as classValidatorToField, g as normalizeEnum, h as mergeField, i as SilkweaveModuleOptions, l as openApiFields, m as fieldToZod, n as NestSilkweaveAdapter, o as OpenApiDocument, p as designTypeToField, r as SILKWEAVE_MODULE_OPTIONS, s as OpenApiLookup, t as NestAdapterRegisterContext, u as FieldDesc, v as reflectDtoFields, x as unreflectedFields, y as swaggerParamToField } from "./types-6rbW7fLE.mjs";
|
|
2
2
|
import { CanActivate, DynamicModule, MiddlewareConsumer, NestModule, Type } from "@nestjs/common";
|
|
3
3
|
import { ApplicationConfig, DiscoveryService, HttpAdapterHost, MetadataScanner, ModuleRef, Reflector } from "@nestjs/core";
|
|
4
|
-
import { Action } from "@silkweave/core";
|
|
4
|
+
import { Action, OnToolCall, ToolAnnotations } from "@silkweave/core";
|
|
5
5
|
import { z } from "zod/v4";
|
|
6
6
|
|
|
7
7
|
//#region src/lib/metadata.d.ts
|
|
@@ -47,13 +47,41 @@ interface McpMetadata {
|
|
|
47
47
|
*/
|
|
48
48
|
pipes?: 'apply' | 'skip';
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
51
|
-
* (`jsonToolResult`); `'smart'`
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
50
|
+
* MCP result format for this tool. `'json'` (the default when unset) returns
|
|
51
|
+
* compact JSON text (`jsonToolResult`); `'smart'` inlines small payloads and
|
|
52
|
+
* offloads large ones to an embedded resource (`smartToolResult`);
|
|
53
|
+
* `'structured'` declares the tool's output schema as an MCP `outputSchema`
|
|
54
|
+
* contract and ships schema-parsed `structuredContent`. `'json'`/`'smart'`
|
|
55
|
+
* are defaults a client's `_meta.disposition` overrides; `'structured'`
|
|
56
|
+
* ignores `_meta.disposition` and **requires an explicit output schema** -
|
|
57
|
+
* `@Mcp({ output })` or `@Trpc({ output })` on the same method (a reflected
|
|
58
|
+
* `@ApiOkResponse` is not accepted as a structured contract; reflection is
|
|
59
|
+
* one level deep and must not silently become a hard, call-failing schema).
|
|
55
60
|
*/
|
|
56
|
-
result?: 'json' | 'smart';
|
|
61
|
+
result?: 'json' | 'smart' | 'structured';
|
|
62
|
+
/**
|
|
63
|
+
* Explicit output schema backing `result: 'structured'` - a Zod type, a DTO
|
|
64
|
+
* class (flattened one level like `@ApiOkResponse` reflection), or a raw
|
|
65
|
+
* shape (wrapped in `z.object`). Wins over `@Trpc({ output })` when both are
|
|
66
|
+
* set. The parsed (extra-fields-stripped) result ships as
|
|
67
|
+
* `structuredContent`, so returning a wider object than the schema is safe.
|
|
68
|
+
*/
|
|
69
|
+
output?: z.ZodType | Type | Record<string, z.ZodType>;
|
|
70
|
+
/**
|
|
71
|
+
* MCP tool annotations (read-only/destructive/idempotent hints) merged over
|
|
72
|
+
* the verb-derived defaults: `@Get` ⇒ `{ readOnlyHint: true, idempotentHint:
|
|
73
|
+
* true }`, `@Put` ⇒ `{ idempotentHint: true }`, `@Delete` ⇒
|
|
74
|
+
* `{ destructiveHint: true, idempotentHint: true }`, anything else ⇒
|
|
75
|
+
* `{ readOnlyHint: false }`. Set a field here to override its derived value
|
|
76
|
+
* (e.g. `{ destructiveHint: true }` on a POST that deletes).
|
|
77
|
+
*/
|
|
78
|
+
annotations?: ToolAnnotations;
|
|
79
|
+
/**
|
|
80
|
+
* Free-form grouping labels carried on the synthesized action (e.g.
|
|
81
|
+
* `['leads', 'write']`) for the `mcp({ filterActions })` per-request filter
|
|
82
|
+
* (or any other consumer) to match on. No behavior on their own.
|
|
83
|
+
*/
|
|
84
|
+
tags?: string[];
|
|
57
85
|
}
|
|
58
86
|
/** tRPC procedure kind for a `@Trpc`-decorated route. */
|
|
59
87
|
type TrpcKind = 'query' | 'mutation' | 'subscription';
|
|
@@ -192,6 +220,14 @@ interface DiscoverOptions {
|
|
|
192
220
|
openapi?: OpenApiDocument;
|
|
193
221
|
globalGuards?: Type<CanActivate>[];
|
|
194
222
|
defaultResult?: 'json' | 'smart';
|
|
223
|
+
/**
|
|
224
|
+
* Telemetry emitter for `@Trpc` procedure invocations (guard denials
|
|
225
|
+
* included). MCP tool calls are NOT emitted here - the `mcp()` adapter
|
|
226
|
+
* instruments the MCP registrar instead, where result metadata
|
|
227
|
+
* (`resultBytes`/`sideloaded`) is known - so exactly one event fires per
|
|
228
|
+
* call on either transport.
|
|
229
|
+
*/
|
|
230
|
+
onToolCall?: OnToolCall;
|
|
195
231
|
}
|
|
196
232
|
declare class ControllerDiscovery {
|
|
197
233
|
private readonly discovery;
|
|
@@ -344,10 +380,18 @@ declare class SilkweaveModule implements NestModule {
|
|
|
344
380
|
private readonly options;
|
|
345
381
|
private readonly discovery;
|
|
346
382
|
private readonly httpAdapterHost;
|
|
347
|
-
|
|
383
|
+
private readonly moduleRef;
|
|
384
|
+
constructor(options: SilkweaveModuleOptions, discovery: ControllerDiscovery, httpAdapterHost: HttpAdapterHost, moduleRef: ModuleRef);
|
|
385
|
+
/**
|
|
386
|
+
* Build the telemetry emitter from the configured class token. The instance
|
|
387
|
+
* is resolved through DI lazily on first event (and memoized) - `configure()`
|
|
388
|
+
* runs before providers are guaranteed ready, same reason global guards
|
|
389
|
+
* resolve at call time.
|
|
390
|
+
*/
|
|
391
|
+
private telemetryEmitter;
|
|
348
392
|
static forRoot(options: SilkweaveModuleOptions): DynamicModule;
|
|
349
393
|
configure(_consumer: MiddlewareConsumer): void;
|
|
350
394
|
}
|
|
351
395
|
//#endregion
|
|
352
|
-
export { Binding, ControllerDiscovery, DiscoverOptions, FieldDesc, MCP_METADATA, Mcp, McpMetadata, NestAdapterRegisterContext, NestSilkweaveAdapter, OpenApiDocument, OpenApiLookup, SILKWEAVE_MODULE_OPTIONS, SilkweaveModule, SilkweaveModuleOptions, TRPC_METADATA, Trpc, TrpcKind, TrpcMetadata, apiPropertyToField, buildOpenApiLookup, classValidatorToField, collectGlobalGuards, collectGuards, designTypeToField, fieldToZod, invokeRebound, mergeField, normalizeEnum, openApiFields, openapiSchemaToField, reflectDtoFields, runGuards, specialBinding, swaggerParamToField, typeTokenToBase, unreflectedFields };
|
|
396
|
+
export { Binding, ControllerDiscovery, DiscoverOptions, FieldDesc, MCP_METADATA, Mcp, McpMetadata, NestAdapterRegisterContext, NestSilkweaveAdapter, OpenApiDocument, OpenApiLookup, SILKWEAVE_MODULE_OPTIONS, SilkweaveModule, SilkweaveModuleOptions, SilkweaveTelemetry, TRPC_METADATA, Trpc, TrpcKind, TrpcMetadata, apiPropertyToField, buildOpenApiLookup, classValidatorToField, collectGlobalGuards, collectGuards, designTypeToField, fieldToZod, invokeRebound, mergeField, normalizeEnum, openApiFields, openapiSchemaToField, reflectDtoFields, runGuards, specialBinding, swaggerParamToField, typeTokenToBase, unreflectedFields };
|
|
353
397
|
//# sourceMappingURL=index.d.mts.map
|
package/build/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/controllerDiscovery.ts","../src/lib/guards.ts","../src/lib/rebind.ts","../src/lib/silkweave.module.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/controllerDiscovery.ts","../src/lib/guards.ts","../src/lib/rebind.ts","../src/lib/silkweave.module.ts"],"mappings":"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"}
|
package/build/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { ForbiddenException, HttpException, Inject, Injectable, Logger, Module, SetMetadata } from "@nestjs/common";
|
|
3
3
|
import { ApplicationConfig, DiscoveryModule, DiscoveryService, HttpAdapterHost, MetadataScanner, ModuleRef, Reflector } from "@nestjs/core";
|
|
4
|
-
import { SilkweaveError, createContext } from "@silkweave/core";
|
|
4
|
+
import { SilkweaveError, createContext, emitToolCall } from "@silkweave/core";
|
|
5
5
|
import { z } from "zod/v4";
|
|
6
6
|
import { GUARDS_METADATA, METHOD_METADATA, PATH_METADATA, ROUTE_ARGS_METADATA } from "@nestjs/common/constants.js";
|
|
7
7
|
import { isObservable, lastValueFrom } from "rxjs";
|
|
@@ -863,7 +863,7 @@ function __decorate(decorators, target, key, desc) {
|
|
|
863
863
|
}
|
|
864
864
|
//#endregion
|
|
865
865
|
//#region src/lib/controllerDiscovery.ts
|
|
866
|
-
var _ref$1, _ref2$1, _ref3, _ref4, _ref5;
|
|
866
|
+
var _ref$1, _ref2$1, _ref3$1, _ref4, _ref5;
|
|
867
867
|
/** Discovery-time diagnostics (unreflectable params, degraded outputs). */
|
|
868
868
|
const logger = new Logger("Silkweave");
|
|
869
869
|
let ControllerDiscovery = class ControllerDiscovery {
|
|
@@ -914,7 +914,7 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
914
914
|
for (const d of discovered) {
|
|
915
915
|
const shared = this.reflect(d, lookup);
|
|
916
916
|
if (d.mcp) actions.push(this.mcpAction(d, shared, globalGuards, options.defaultResult));
|
|
917
|
-
if (d.trpc) actions.push(this.trpcAction(d, shared, globalGuards));
|
|
917
|
+
if (d.trpc) actions.push(this.trpcAction(d, shared, globalGuards, options.onToolCall));
|
|
918
918
|
}
|
|
919
919
|
return actions;
|
|
920
920
|
}
|
|
@@ -971,11 +971,23 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
971
971
|
const applyGuards = this.guardRunner(d, shared, globalGuards);
|
|
972
972
|
const { method, instance } = d;
|
|
973
973
|
const { bindings, streaming } = shared;
|
|
974
|
+
const disposition = meta.result ?? defaultResult;
|
|
975
|
+
const output = resolveSchema(meta.output) ?? resolveSchema(d.trpc?.output);
|
|
976
|
+
if (disposition === "structured") {
|
|
977
|
+
if (streaming) throw new SilkweaveError(`${d.classRef.name}.${d.methodName}: @Mcp({ result: 'structured' }) is not supported on a streaming (async *) route - there is no single result to validate`, "invalid_action");
|
|
978
|
+
if (!output) throw new SilkweaveError(`${d.classRef.name}.${d.methodName}: @Mcp({ result: 'structured' }) requires an explicit output schema - set @Mcp({ output }) or @Trpc({ output }). Reflected @ApiOkResponse schemas are not accepted as structured contracts.`, "invalid_action");
|
|
979
|
+
}
|
|
974
980
|
return {
|
|
975
981
|
name,
|
|
976
982
|
description,
|
|
977
983
|
input: z.object(shape),
|
|
978
|
-
...
|
|
984
|
+
...disposition ? { disposition } : {},
|
|
985
|
+
...disposition === "structured" && output ? { output } : {},
|
|
986
|
+
...meta.tags ? { tags: meta.tags } : {},
|
|
987
|
+
annotations: {
|
|
988
|
+
...verbAnnotations(shared.route.method),
|
|
989
|
+
...meta.annotations
|
|
990
|
+
},
|
|
979
991
|
isEnabled: (ctx) => ctx.getOptional("adapter") === "mcp",
|
|
980
992
|
...streaming ? {
|
|
981
993
|
chunk: z.unknown(),
|
|
@@ -987,7 +999,7 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
987
999
|
};
|
|
988
1000
|
}
|
|
989
1001
|
/** Synthesize the tRPC-targeted action (kind/output/subscription + httpStatus errors). */
|
|
990
|
-
trpcAction(d, shared, globalGuards) {
|
|
1002
|
+
trpcAction(d, shared, globalGuards, onToolCall) {
|
|
991
1003
|
const meta = d.trpc;
|
|
992
1004
|
const shape = {
|
|
993
1005
|
...shared.baseShape,
|
|
@@ -1009,7 +1021,10 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
1009
1021
|
input: z.object(shape),
|
|
1010
1022
|
chunk: resolveSchema(meta.chunk) ?? z.unknown(),
|
|
1011
1023
|
isEnabled,
|
|
1012
|
-
run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true
|
|
1024
|
+
run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true, onToolCall ? {
|
|
1025
|
+
hook: onToolCall,
|
|
1026
|
+
name
|
|
1027
|
+
} : void 0)
|
|
1013
1028
|
};
|
|
1014
1029
|
const kind = meta.kind === "query" || meta.kind === "mutation" ? meta.kind : shared.route.method === "GET" ? "query" : "mutation";
|
|
1015
1030
|
const output = resolveOutput(meta, method);
|
|
@@ -1023,11 +1038,16 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
1023
1038
|
kind,
|
|
1024
1039
|
isEnabled,
|
|
1025
1040
|
run: async (input, context) => {
|
|
1041
|
+
const started = Date.now();
|
|
1026
1042
|
try {
|
|
1027
1043
|
await applyGuards(context, input);
|
|
1028
|
-
|
|
1044
|
+
const result = await invokeRebound(method, instance, input, bindings, context.getOptional("request"), context.getOptional("response"), applyParamPipes);
|
|
1045
|
+
emitTrpcEvent(onToolCall, name, context, started);
|
|
1046
|
+
return result ?? {};
|
|
1029
1047
|
} catch (error) {
|
|
1030
|
-
|
|
1048
|
+
const mapped = toSilkweaveError(error);
|
|
1049
|
+
emitTrpcEvent(onToolCall, name, context, started, mapped);
|
|
1050
|
+
throw mapped;
|
|
1031
1051
|
}
|
|
1032
1052
|
}
|
|
1033
1053
|
};
|
|
@@ -1036,19 +1056,70 @@ let ControllerDiscovery = class ControllerDiscovery {
|
|
|
1036
1056
|
ControllerDiscovery = __decorate([Injectable(), __decorateMetadata("design:paramtypes", [
|
|
1037
1057
|
typeof (_ref$1 = typeof DiscoveryService !== "undefined" && DiscoveryService) === "function" ? _ref$1 : Object,
|
|
1038
1058
|
typeof (_ref2$1 = typeof MetadataScanner !== "undefined" && MetadataScanner) === "function" ? _ref2$1 : Object,
|
|
1039
|
-
typeof (_ref3 = typeof Reflector !== "undefined" && Reflector) === "function" ? _ref3 : Object,
|
|
1059
|
+
typeof (_ref3$1 = typeof Reflector !== "undefined" && Reflector) === "function" ? _ref3$1 : Object,
|
|
1040
1060
|
typeof (_ref4 = typeof ModuleRef !== "undefined" && ModuleRef) === "function" ? _ref4 : Object,
|
|
1041
1061
|
typeof (_ref5 = typeof ApplicationConfig !== "undefined" && ApplicationConfig) === "function" ? _ref5 : Object
|
|
1042
1062
|
])], ControllerDiscovery);
|
|
1063
|
+
/** Procedure key the tRPC router exposes for an action name (`Users.listBySpace` → `usersListBySpace`). */
|
|
1064
|
+
function camelKey(name) {
|
|
1065
|
+
return name.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part, index) => index === 0 ? part[0].toLowerCase() + part.slice(1) : part[0].toUpperCase() + part.slice(1)).join("");
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Emit a tRPC-side telemetry event (fire-and-forget). Gated to the `trpc`
|
|
1069
|
+
* adapter context so a `typegen`-driven evaluation never counts as a call.
|
|
1070
|
+
*/
|
|
1071
|
+
function emitTrpcEvent(hook, name, context, started, error) {
|
|
1072
|
+
if (!hook || context.getOptional("adapter") !== "trpc") return;
|
|
1073
|
+
const meta = error == null ? {} : error instanceof SilkweaveError ? {
|
|
1074
|
+
errorCode: error.code,
|
|
1075
|
+
errorMessage: error.message
|
|
1076
|
+
} : error instanceof Error ? {
|
|
1077
|
+
errorCode: error.name,
|
|
1078
|
+
errorMessage: error.message
|
|
1079
|
+
} : { errorCode: "unknown" };
|
|
1080
|
+
emitToolCall(hook, {
|
|
1081
|
+
action: name,
|
|
1082
|
+
tool: camelKey(name),
|
|
1083
|
+
transport: "trpc",
|
|
1084
|
+
durationMs: Date.now() - started,
|
|
1085
|
+
ok: error == null,
|
|
1086
|
+
...meta,
|
|
1087
|
+
context
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Verb-derived MCP annotation defaults for a controller route. Explicit
|
|
1092
|
+
* `@Mcp({ annotations })` fields are merged over these by the caller.
|
|
1093
|
+
*/
|
|
1094
|
+
function verbAnnotations(method) {
|
|
1095
|
+
if (method === "GET") return {
|
|
1096
|
+
readOnlyHint: true,
|
|
1097
|
+
idempotentHint: true
|
|
1098
|
+
};
|
|
1099
|
+
if (method === "PUT") return {
|
|
1100
|
+
readOnlyHint: false,
|
|
1101
|
+
idempotentHint: true
|
|
1102
|
+
};
|
|
1103
|
+
if (method === "DELETE") return {
|
|
1104
|
+
readOnlyHint: false,
|
|
1105
|
+
destructiveHint: true,
|
|
1106
|
+
idempotentHint: true
|
|
1107
|
+
};
|
|
1108
|
+
return { readOnlyHint: false };
|
|
1109
|
+
}
|
|
1043
1110
|
/** Build a streaming (`async *`) run that applies guards then yields the method's chunks. */
|
|
1044
|
-
function streamingRun(applyGuards, method, instance, bindings, applyParamPipes, mapErrors) {
|
|
1111
|
+
function streamingRun(applyGuards, method, instance, bindings, applyParamPipes, mapErrors, telemetry) {
|
|
1045
1112
|
return async function* (input, context) {
|
|
1113
|
+
const started = Date.now();
|
|
1046
1114
|
try {
|
|
1047
1115
|
await applyGuards(context, input);
|
|
1048
1116
|
const gen = await invokeRebound(method, instance, input, bindings, context.getOptional("request"), context.getOptional("response"), applyParamPipes);
|
|
1049
1117
|
for await (const chunk of gen) yield chunk;
|
|
1118
|
+
if (telemetry) emitTrpcEvent(telemetry.hook, telemetry.name, context, started);
|
|
1050
1119
|
} catch (error) {
|
|
1051
|
-
|
|
1120
|
+
const mapped = mapErrors ? toSilkweaveError(error) : error;
|
|
1121
|
+
if (telemetry) emitTrpcEvent(telemetry.hook, telemetry.name, context, started, mapped);
|
|
1122
|
+
throw mapped;
|
|
1052
1123
|
}
|
|
1053
1124
|
};
|
|
1054
1125
|
}
|
|
@@ -1220,12 +1291,29 @@ function __decorateParam(paramIndex, decorator) {
|
|
|
1220
1291
|
}
|
|
1221
1292
|
//#endregion
|
|
1222
1293
|
//#region src/lib/silkweave.module.ts
|
|
1223
|
-
var _ref, _ref2, _SilkweaveModule;
|
|
1294
|
+
var _ref, _ref2, _ref3, _SilkweaveModule;
|
|
1224
1295
|
let SilkweaveModule = _SilkweaveModule = class SilkweaveModule {
|
|
1225
|
-
constructor(options, discovery, httpAdapterHost) {
|
|
1296
|
+
constructor(options, discovery, httpAdapterHost, moduleRef) {
|
|
1226
1297
|
this.options = options;
|
|
1227
1298
|
this.discovery = discovery;
|
|
1228
1299
|
this.httpAdapterHost = httpAdapterHost;
|
|
1300
|
+
this.moduleRef = moduleRef;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Build the telemetry emitter from the configured class token. The instance
|
|
1304
|
+
* is resolved through DI lazily on first event (and memoized) - `configure()`
|
|
1305
|
+
* runs before providers are guaranteed ready, same reason global guards
|
|
1306
|
+
* resolve at call time.
|
|
1307
|
+
*/
|
|
1308
|
+
telemetryEmitter() {
|
|
1309
|
+
const token = this.options.telemetry;
|
|
1310
|
+
if (!token) return;
|
|
1311
|
+
let instance;
|
|
1312
|
+
return (event) => {
|
|
1313
|
+
const resolved = instance ?? this.moduleRef.get(token, { strict: false });
|
|
1314
|
+
instance = resolved;
|
|
1315
|
+
return resolved.onToolCall(event);
|
|
1316
|
+
};
|
|
1229
1317
|
}
|
|
1230
1318
|
static forRoot(options) {
|
|
1231
1319
|
return {
|
|
@@ -1242,10 +1330,12 @@ let SilkweaveModule = _SilkweaveModule = class SilkweaveModule {
|
|
|
1242
1330
|
configure(_consumer) {
|
|
1243
1331
|
const httpAdapter = this.httpAdapterHost.httpAdapter;
|
|
1244
1332
|
if (!httpAdapter) throw new Error("@silkweave/nestjs: HttpAdapterHost.httpAdapter is not available.");
|
|
1333
|
+
const onToolCall = this.telemetryEmitter();
|
|
1245
1334
|
const allActions = this.discovery.discover({
|
|
1246
1335
|
openapi: this.options.openapi,
|
|
1247
1336
|
globalGuards: this.options.globalGuards,
|
|
1248
|
-
defaultResult: this.options.defaultResult
|
|
1337
|
+
defaultResult: this.options.defaultResult,
|
|
1338
|
+
onToolCall
|
|
1249
1339
|
});
|
|
1250
1340
|
for (const adapter of this.options.adapters) {
|
|
1251
1341
|
const baseContext = createContext({
|
|
@@ -1257,7 +1347,8 @@ let SilkweaveModule = _SilkweaveModule = class SilkweaveModule {
|
|
|
1257
1347
|
httpAdapter,
|
|
1258
1348
|
silkweaveOptions: this.options.silkweave,
|
|
1259
1349
|
baseContext,
|
|
1260
|
-
actions
|
|
1350
|
+
actions,
|
|
1351
|
+
onToolCall
|
|
1261
1352
|
});
|
|
1262
1353
|
}
|
|
1263
1354
|
}
|
|
@@ -1268,7 +1359,8 @@ SilkweaveModule = _SilkweaveModule = __decorate([
|
|
|
1268
1359
|
__decorateMetadata("design:paramtypes", [
|
|
1269
1360
|
Object,
|
|
1270
1361
|
typeof (_ref = typeof ControllerDiscovery !== "undefined" && ControllerDiscovery) === "function" ? _ref : Object,
|
|
1271
|
-
typeof (_ref2 = typeof HttpAdapterHost !== "undefined" && HttpAdapterHost) === "function" ? _ref2 : Object
|
|
1362
|
+
typeof (_ref2 = typeof HttpAdapterHost !== "undefined" && HttpAdapterHost) === "function" ? _ref2 : Object,
|
|
1363
|
+
typeof (_ref3 = typeof ModuleRef !== "undefined" && ModuleRef) === "function" ? _ref3 : Object
|
|
1272
1364
|
])
|
|
1273
1365
|
], SilkweaveModule);
|
|
1274
1366
|
//#endregion
|
package/build/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/executionContext.ts","../src/lib/guards.ts","../src/lib/reflect/params.ts","../src/lib/rebind.ts","../src/lib/requestSlots.ts","../src/lib/reflect/classValidator.ts","../src/lib/reflect/schema.ts","../src/lib/reflect/openapi.ts","../src/lib/reflect/response.ts","../src/lib/reflect/route.ts","../src/lib/reflect/swagger.ts","../src/lib/controllerDiscovery.ts","../src/lib/types.ts","../src/lib/silkweave.module.ts"],"sourcesContent":["import type { Type } from '@nestjs/common'\nimport type { z } from 'zod/v4'\n\n/** Reflect-metadata key carrying `@Mcp` options on a controller method. */\nexport const MCP_METADATA = '__silkweave_mcp__'\n\n/** Reflect-metadata key carrying `@Trpc` options on a controller method. */\nexport const TRPC_METADATA = '__silkweave_trpc__'\n\n/**\n * Options for the `@Mcp()` method decorator. Every field is optional - an empty\n * `@Mcp()` exposes the decorated controller route as an MCP tool with its name,\n * description, and input schema fully reflected from the method's route\n * (`@Get`/`@Post`/...), parameter decorators (`@Param`/`@Query`/`@Body`), and\n * any `@nestjs/swagger` (`@ApiOperation`/`@ApiParam`/`@ApiProperty`) or\n * `class-validator` metadata it carries.\n */\nexport interface McpMetadata {\n /**\n * MCP tool name override. When unset it is derived from the controller class\n * and method name (e.g. `ChannelsController.findOne` → `ChannelsFindOne`).\n */\n name?: string\n /**\n * Tool description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts either a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` - the object's `.shape` is unwrapped. The escape hatch\n * for shapes reflection can't express losslessly - discriminated unions,\n * custom validators, `@Transform`, etc. Note it *adds to* the reflected\n * fields; it does not replace them, so a field reflection silently dropped\n * (see the unreflectable-param warning) is not recovered by listing the\n * others here.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Whether to apply the controller method's parameter-bound pipes\n * (`@Param('id', ParseIntPipe)`) when re-binding the call. Default `'apply'`.\n * Global/`ValidationPipe`, interceptors, and exception filters never run -\n * the method is invoked directly, not through Nest's HTTP request pipeline.\n */\n pipes?: 'apply' | 'skip'\n /**\n * Default MCP result format for this tool. `'json'` returns compact JSON text\n * (`jsonToolResult`); `'smart'` (the default when unset) inlines small\n * payloads and offloads large ones to an embedded resource (`smartToolResult`).\n * This is only a default - a client that sends `_meta.disposition` on the tool\n * call overrides it.\n */\n result?: 'json' | 'smart'\n}\n\n/** tRPC procedure kind for a `@Trpc`-decorated route. */\nexport type TrpcKind = 'query' | 'mutation' | 'subscription'\n\n/**\n * Options for the `@Trpc()` method decorator - the tRPC sibling of `@Mcp`. An\n * empty `@Trpc()` exposes the decorated controller route as a tRPC procedure\n * with its key, input schema, and kind reflected from the route + parameter\n * decorators + swagger/class-validator metadata (identically to `@Mcp`).\n *\n * Unlike MCP, tRPC carries precise *output* types into the generated router, so\n * `@Trpc` adds an `output`/`chunk` hatch and a `kind` override on top of the\n * shared reflection. The two decorators compose on the same method.\n */\nexport interface TrpcMetadata {\n /**\n * Procedure-name override (before camelCasing). When unset it is derived from\n * the controller class + method name (e.g. `UsersController.listBySpace` →\n * `Users.listBySpace`, camelCased by the router to `usersListBySpace`).\n */\n name?: string\n /**\n * Procedure description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` (its `.shape` is unwrapped). Same escape hatch as\n * `@Mcp({ input })`.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Explicit output schema driving the generated procedure's output type - a Zod\n * type, a DTO class (reflected like `@ApiOkResponse`), or a raw shape (wrapped\n * in `z.object`). Wins over `@ApiOkResponse` reflection. The biggest reason to\n * set this is when the return shape can't be reflected losslessly from a DTO.\n */\n output?: z.ZodType | Type | Record<string, z.ZodType>\n /**\n * Chunk schema for an async-generator route exposed as a tRPC **subscription**.\n * A Zod type or a DTO class. Drives the emitted\n * `TRPCSubscriptionProcedure<{ output }>` type. When unset the chunk type falls\n * back to `unknown`.\n */\n chunk?: z.ZodType | Type\n /**\n * Procedure kind. When unset it is inferred: an `async *` route ⇒\n * `'subscription'`, a `@Get` route ⇒ `'query'`, anything else ⇒ `'mutation'`.\n * Set this to expose a verb-less route (no `@Get`/`@Post`) as a query or\n * subscription - `@Trpc({ kind })` works without an HTTP-verb decorator, so the\n * route is served over tRPC (and/or MCP) without becoming a public REST route.\n */\n kind?: TrpcKind\n /**\n * Whether to apply the method's parameter-bound pipes when re-binding the call.\n * Default `'apply'`. Same semantics as `@Mcp({ pipes })`.\n */\n pipes?: 'apply' | 'skip'\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { MCP_METADATA, type McpMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes an existing NestJS controller route as an MCP\n * tool. It is **additive** - the route keeps serving HTTP exactly as before;\n * `@Mcp()` just opts the method into MCP discovery.\n *\n * The tool's name, description, and input schema are reflected from the\n * method's own metadata:\n * - **fields** from the parameter decorators (`@Param`/`@Query`/`@Body`) - a\n * `@Param('id')` becomes an `id` field; a whole-DTO `@Body() dto: CreateDto`\n * is flattened to its properties,\n * - **types/constraints/descriptions** from `@nestjs/swagger`\n * (`@ApiParam`/`@ApiQuery`/`@ApiProperty`/`@ApiOperation`) and, when present,\n * `class-validator` decorators on the DTOs,\n * - optionally refined by an OpenAPI document passed to `SilkweaveModule`.\n *\n * On a tool call the input is split back into the method's positional arguments\n * and the method is invoked directly (with `@UseGuards` guards applied first).\n *\n * @example\n * ```ts\n * @Controller('sessions/:sessionId/channels')\n * export class ChannelsController {\n * @Get(':channelId')\n * @ApiOperation({ summary: 'Get a specific channel by ID' })\n * @ApiParam({ name: 'sessionId', description: 'Session ID' })\n * @ApiParam({ name: 'channelId', description: 'Channel ID' })\n * @Mcp()\n * findOne(@Param('sessionId') sessionId: string, @Param('channelId') channelId: string) {\n * return this.service.get(sessionId, channelId)\n * }\n * }\n * ```\n */\nexport function Mcp(options: McpMetadata = {}): MethodDecorator {\n return SetMetadata(MCP_METADATA, options)\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { TRPC_METADATA, type TrpcMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes a NestJS controller route as a **tRPC\n * procedure** - the sibling of `@Mcp`. Like `@Mcp` it is additive and reflects\n * the procedure's input from the method's own metadata (route + `@Param`/\n * `@Query`/`@Body` + swagger/class-validator), so a single method can carry both\n * `@Trpc()` and `@Mcp()` and `@UseGuards()`.\n *\n * Two things differ from MCP because tRPC consumers need them:\n * - **kind** - inferred from the route (`@Get` ⇒ query, others ⇒ mutation) or an\n * `async *` body (⇒ subscription); override with `@Trpc({ kind })`.\n * - **output** - the generated `AppRouter` carries precise output types. Drive\n * them with `@ApiOkResponse({ type: Dto })` reflection or `@Trpc({ output })`.\n *\n * `@Trpc()` works **without** an HTTP-verb decorator: with no `@Get`/`@Post` the\n * route is never mapped as REST, so `@Trpc({ kind })` exposes it over tRPC (and\n * `@Mcp` over MCP) while keeping it off the public REST surface.\n *\n * @example\n * ```ts\n * @Controller('users')\n * export class UsersController {\n * @Get('list-by-space')\n * @ApiOperation({ summary: 'List users in a space' })\n * @ApiOkResponse({ type: ListUsersResponse }) // drives the output type\n * @UseGuards(AuthGuard)\n * @Trpc() // → procedure `usersListBySpace` (query)\n * @Mcp() // → MCP tool `UsersListBySpace`\n * listBySpace(@Query() q: ListBySpaceQuery, @Req() req: AppRequest) {\n * return this.service.list(req.user, q.spaceId)\n * }\n * }\n * ```\n */\nexport function Trpc(options: TrpcMetadata = {}): MethodDecorator {\n return SetMetadata(TRPC_METADATA, options)\n}\n","import type { ArgumentsHost, ContextType, ExecutionContext, Type } from '@nestjs/common'\n\n/** Subset of `HttpArgumentsHost` we need - re-declared inline to avoid deep `@nestjs/common/interfaces` imports. */\ninterface HttpHost {\n getRequest<T = unknown>(): T\n getResponse<T = unknown>(): T\n getNext<T = unknown>(): T\n}\n\ninterface RpcHost {\n getData<T = unknown>(): T\n getContext<T = unknown>(): T\n}\n\ninterface WsHost {\n getClient<T = unknown>(): T\n getData<T = unknown>(): T\n getPattern(): string\n}\n\n/**\n * Minimal `ExecutionContext` impl Nest guards can consume. We only need\n * `switchToHttp()` to work for our HTTP-backed transports; the RPC/WS shims are\n * stubbed so guards that introspect type can still call them without crashing.\n */\nexport class SilkweaveExecutionContext implements ExecutionContext, ArgumentsHost {\n constructor(\n private readonly args: unknown[],\n private readonly classRef: Type<unknown>,\n private readonly handler: (...handlerArgs: unknown[]) => unknown,\n private readonly contextType = 'http'\n ) { }\n\n getType<T extends string = ContextType>(): T {\n return this.contextType as T\n }\n\n getClass<T = unknown>(): Type<T> {\n return this.classRef as Type<T>\n }\n\n getHandler(): (...handlerArgs: unknown[]) => unknown {\n return this.handler\n }\n\n getArgs<T extends unknown[] = unknown[]>(): T {\n return this.args as T\n }\n\n getArgByIndex<T = unknown>(index: number): T {\n return this.args[index] as T\n }\n\n switchToHttp(): HttpHost {\n return {\n getRequest: <T = unknown>(): T => this.args[0] as T,\n getResponse: <T = unknown>(): T => this.args[1] as T,\n getNext: <T = unknown>(): T => this.args[2] as T\n }\n }\n\n switchToRpc(): RpcHost {\n return {\n getData: <T = unknown>(): T => this.args[0] as T,\n getContext: <T = unknown>(): T => this.args[1] as T\n }\n }\n\n switchToWs(): WsHost {\n return {\n getClient: <T = unknown>(): T => this.args[0] as T,\n getData: <T = unknown>(): T => this.args[1] as T,\n getPattern: (): string => ''\n }\n }\n}\n","import { ForbiddenException, type CanActivate, type Type } from '@nestjs/common'\nimport { GUARDS_METADATA } from '@nestjs/common/constants.js'\nimport { ApplicationConfig, ModuleRef, Reflector } from '@nestjs/core'\nimport { isObservable, lastValueFrom } from 'rxjs'\nimport { SilkweaveExecutionContext } from './executionContext.js'\n\ntype GuardRef = Type<CanActivate> | CanActivate\n\n/**\n * Collect the app's global guards that match an opt-in allow-list of classes.\n *\n * Reads both registration styles Nest exposes via `ApplicationConfig`:\n * `useGlobalGuards(new X())` instances (`getGlobalGuards()`) and\n * `{ provide: APP_GUARD, useClass }` DI guards (`getGlobalRequestGuards()`,\n * which yields `InstanceWrapper`s - we read `.instance` off each).\n *\n * The allow-list is intentionally explicit-by-class: a blanket \"run every\n * global\" would also fire unrelated globals (e.g. a `ThrottlerGuard` that\n * assumes a writable response) on every tool call. An empty allow-list runs\n * no globals, preserving the prior behavior.\n *\n * Call this at tool-call time, not at discovery time: `APP_GUARD` instances\n * aren't populated until `app.init()` finishes.\n */\nexport function collectGlobalGuards(\n appConfig: ApplicationConfig,\n allowList: Type<CanActivate>[]\n): CanActivate[] {\n if (allowList.length === 0) { return [] }\n const globals: CanActivate[] = [\n ...appConfig.getGlobalGuards(),\n ...appConfig.getGlobalRequestGuards().map((w) => w.instance)\n ].filter((g): g is CanActivate => g != null)\n return globals.filter((g) => allowList.some((c) => g instanceof c))\n}\n\n/**\n * Read `@UseGuards(...)` metadata for both the method and its class and merge\n * the two lists. Method-level guards run AFTER class-level guards (matching\n * Nest's own behavior).\n */\nexport function collectGuards(\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown\n): GuardRef[] {\n const classGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, classRef) ?? []\n const methodGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, handler) ?? []\n return [...classGuards, ...methodGuards]\n}\n\nasync function resolveGuard(ref: GuardRef, moduleRef: ModuleRef): Promise<CanActivate> {\n if (typeof ref === 'function') {\n try {\n return await moduleRef.get(ref, { strict: false })\n } catch {\n return moduleRef.create(ref)\n }\n }\n return ref\n}\n\n/**\n * Run the configured guards against a request. Throws `ForbiddenException`\n * if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.\n *\n * Pass `null` for `response` when running on top of a tRPC or MCP request that\n * doesn't surface a raw response object; guards that introspect the response\n * will receive `null`.\n *\n * `contextType` is reflected through `ExecutionContext.getType()` so guards can\n * branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP\n * (where a header-bearing request stand-in is available); transports without any\n * HTTP request (e.g. MCP stdio) pass `'rpc'`.\n */\nexport async function runGuards(\n guards: GuardRef[],\n moduleRef: ModuleRef,\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown,\n request: unknown,\n response: unknown,\n contextType: 'http' | 'rpc' = 'http'\n): Promise<void> {\n if (guards.length === 0) { return }\n const context = new SilkweaveExecutionContext([request, response], classRef, handler, contextType)\n for (const ref of guards) {\n const guard = await resolveGuard(ref, moduleRef)\n const result = guard.canActivate(context)\n const allowed = isObservable(result) ? await lastValueFrom(result) : await Promise.resolve(result)\n if (!allowed) {\n throw new ForbiddenException('Forbidden resource')\n }\n }\n // Reflector kept in the signature for future use (e.g., per-guard metadata) - unused here.\n void reflector\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ROUTE_ARGS_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RouteParamtypes` numeric values from `@nestjs/common` (re-declared to avoid a\n * value import of an internal enum). These are how `@Param`/`@Query`/`@Body`/...\n * tag each handler argument in `ROUTE_ARGS_METADATA`.\n */\nexport const PARAMTYPE = {\n REQUEST: 0,\n RESPONSE: 1,\n NEXT: 2,\n BODY: 3,\n QUERY: 4,\n PARAM: 5,\n HEADERS: 6,\n SESSION: 7,\n FILE: 8,\n FILES: 9,\n HOST: 10,\n IP: 11,\n RAW_BODY: 12\n} as const\n\nexport interface ParamSlot {\n /** `PARAMTYPE` value - which decorator tagged this argument. */\n paramtype: number\n /** Handler argument position. */\n index: number\n /** Decorator sub-key: `@Param('id')` → `'id'`; a bare `@Body()` → `undefined`. */\n data?: string\n /** Parameter-bound pipes (`@Param('id', ParseIntPipe)`). */\n pipes: unknown[]\n /** TypeScript-emitted constructor at this position (e.g. `String`, `CreateDto`). */\n designType?: unknown\n}\n\n/**\n * Read and normalise the route-argument metadata for a controller method.\n * Returns one {@link ParamSlot} per decorated handler argument, sorted by\n * argument index.\n */\nexport function readParamSlots(classRef: any, methodName: string, proto: any): ParamSlot[] {\n const raw = Reflect.getMetadata(ROUTE_ARGS_METADATA, classRef, methodName) as\n Record<string, { index: number; data?: unknown; pipes?: unknown[] }> | undefined\n if (!raw) { return [] }\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n\n const slots: ParamSlot[] = []\n for (const key of Object.keys(raw)) {\n const entry = raw[key]\n const paramtype = Number(key.split(':')[0])\n if (Number.isNaN(paramtype)) { continue }\n slots.push({\n paramtype,\n index: entry.index,\n data: typeof entry.data === 'string' ? entry.data : undefined,\n pipes: entry.pipes ?? [],\n designType: designTypes[entry.index]\n })\n }\n return slots.sort((a, b) => a.index - b.index)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { PARAMTYPE } from './reflect/params.js'\n\n/**\n * Instruction for reconstructing one positional handler argument from the flat\n * MCP tool input. Built at discovery time, consumed by {@link invokeRebound}.\n */\nexport type Binding =\n | { kind: 'value'; field: string; source: 'path' | 'query' | 'body'; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'object'; source: 'query' | 'body'; fields: string[]; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'params'; fields: string[] }\n | { kind: 'request' }\n | { kind: 'response' }\n | { kind: 'headers'; data?: string }\n | { kind: 'ip' }\n | { kind: 'host'; data?: string }\n | { kind: 'missing' }\n\ninterface RequestLike {\n headers?: Record<string, unknown>\n ip?: unknown\n hosts?: Record<string, unknown>\n}\n\nfunction newInstance(P: any): any | null {\n try { return new P() } catch { return null }\n}\n\nasync function applyPipes(value: unknown, pipes: unknown[] | undefined, metatype: unknown, type: 'param' | 'query' | 'body', data: string | undefined): Promise<unknown> {\n if (!pipes || pipes.length === 0) { return value }\n let current = value\n for (const p of pipes) {\n const pipe = typeof p === 'function' ? newInstance(p) : p\n if (pipe && typeof (pipe).transform === 'function') {\n current = await (pipe).transform(current, { type, metatype, data })\n }\n }\n return current\n}\n\n/** Pick a subset of keys (skipping `undefined`) into a fresh object. */\nfunction pickFields(input: Record<string, unknown>, fields: string[]): Record<string, unknown> {\n const obj: Record<string, unknown> = {}\n for (const f of fields) {\n if (input[f] !== undefined) { obj[f] = input[f] }\n }\n return obj\n}\n\n/** Resolve a single positional argument from one binding. */\nasync function resolveArg(\n b: Binding,\n input: Record<string, unknown>,\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n switch (b.kind) {\n case 'value': {\n const raw = input[b.field]\n const type = b.source === 'path' ? 'param' : b.source\n return applyParamPipes ? applyPipes(raw, b.pipes, b.metatype, type, b.field) : raw\n }\n case 'object': {\n const obj = pickFields(input, b.fields)\n return applyParamPipes ? applyPipes(obj, b.pipes, b.metatype, b.source, undefined) : obj\n }\n case 'params':\n return pickFields(input, b.fields)\n case 'headers':\n return b.data ? request?.headers?.[b.data.toLowerCase()] : (request?.headers ?? {})\n case 'request':\n return request ?? { headers: {} }\n case 'response':\n // The real Express response over tRPC (so `@Res({ passthrough: true })`\n // can set cookies/headers); `undefined` over MCP (no HTTP response).\n return response\n case 'ip':\n return request?.ip\n case 'host':\n return b.data ? request?.hosts?.[b.data] : request?.hosts\n default:\n return undefined\n }\n}\n\n/**\n * Reconstruct the controller method's positional arguments from the validated\n * tool `input` (and the request stand-in for `@Req`/`@Headers`/...), then call\n * it. `applyParamPipes` controls whether parameter-bound pipes run.\n */\nexport async function invokeRebound(\n method: (...args: any[]) => any,\n instance: object,\n input: Record<string, unknown>,\n bindings: Binding[],\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n const args: unknown[] = []\n for (let i = 0; i < bindings.length; i += 1) {\n args[i] = await resolveArg(bindings[i], input, request, response, applyParamPipes)\n }\n return await method.apply(instance, args)\n}\n\n/** Map a non-input parameter slot (`@Req`/`@Headers`/`@Ip`/...) to its runtime binding. */\nexport function specialBinding(paramtype: number, data: string | undefined): Binding | null {\n switch (paramtype) {\n case PARAMTYPE.REQUEST: return { kind: 'request' }\n case PARAMTYPE.RESPONSE:\n case PARAMTYPE.NEXT: return { kind: 'response' }\n case PARAMTYPE.HEADERS: return { kind: 'headers', data }\n case PARAMTYPE.IP: return { kind: 'ip' }\n case PARAMTYPE.HOST: return { kind: 'host', data }\n case PARAMTYPE.SESSION:\n case PARAMTYPE.FILE:\n case PARAMTYPE.FILES:\n case PARAMTYPE.RAW_BODY: return { kind: 'missing' }\n default: return null\n }\n}\n","import type { Binding } from './rebind.js'\n\n/**\n * Request-slot reconstruction: route the validated tool input back into the\n * `request.params`/`query`/`body` slots Express would populate over REST, so a\n * host guard reading any of them decides identically over MCP and REST. Kept in\n * its own module (not re-exported from the package root) so these helpers stay\n * internal while remaining unit-testable.\n */\n\n/** Input field names grouped by the REST request slot Express would source them from. */\nexport interface RequestSlots {\n /** `@Param`/path-template fields -> `request.params` (raw strings). */\n params: string[]\n /** `@Query` fields -> `request.query` (raw strings). */\n query: string[]\n /** `@Body` fields -> `request.body` (parsed values). */\n body: string[]\n}\n\n/**\n * Classify every input field by the REST request slot it would occupy, reading\n * the discovery-time {@link Binding}s. A whole-DTO `@Query()`/`@Body()` (`object`\n * binding) contributes all its fields to the matching slot; a bare `@Param()`\n * (`params` binding) and a path-sourced `value` go to `params`.\n */\nexport function requestSlotFields(bindings: Binding[]): RequestSlots {\n const slots: RequestSlots = { params: [], query: [], body: [] }\n for (const b of bindings) {\n if (b.kind === 'params') { slots.params.push(...b.fields) } else if (b.kind === 'object') { slots[b.source].push(...b.fields) } else if (b.kind === 'value') { slots[b.source === 'path' ? 'params' : b.source].push(b.field) }\n }\n return slots\n}\n\n/** Fill one request slot from the validated input, only adding absent keys. */\nfunction fillSlot(bag: Record<string, unknown>, fields: string[], input: Record<string, unknown>, stringify: boolean): void {\n for (const field of fields) {\n if (!(field in bag) && input[field] !== undefined) {\n bag[field] = stringify ? String(input[field]) : input[field]\n }\n }\n}\n\n/**\n * Fill `request.params`/`query`/`body` from the validated input, mirroring the\n * slots Express would populate over REST (path -> `params`, `@Query` -> `query`,\n * `@Body` -> `body`). Path/query values are stringified to match how Express\n * delivers them (a guard reading `req.query.limit` sees `'10'`, not `10`); body\n * keeps the parsed values. Only absent keys are added, so a real REST/tRPC\n * request's own params/query/body are never overwritten. This is what lets a\n * scope-enforcing guard (`req.params.sessionId`, `req.body.sessionId`, ...)\n * decide identically over MCP and REST.\n */\nexport function populateRequestSlots(request: unknown, slots: RequestSlots, input: Record<string, unknown>): void {\n if (typeof request !== 'object' || request === null) { return }\n const req = request as { params?: Record<string, unknown>; query?: Record<string, unknown>; body?: Record<string, unknown> }\n if (slots.params.length > 0) { fillSlot((req.params ??= {}), slots.params, input, true) }\n if (slots.query.length > 0) { fillSlot((req.query ??= {}), slots.query, input, true) }\n if (slots.body.length > 0) { fillSlot((req.body ??= {}), slots.body, input, false) }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { createRequire } from 'node:module'\nimport { join } from 'node:path'\n\nlet cached: any | null | undefined\n\n/**\n * Lazily resolve the optional `class-validator` peer; `null` when not installed.\n * Resolution is attempted both from this package and from the app's working\n * directory - the latter is what finds it in a pnpm install where the optional\n * peer lives in the consumer app rather than alongside `@silkweave/nestjs`. A\n * pnpm-deduped install shares one physical copy, so the metadata singleton the\n * app's decorators wrote to is the same one we read.\n */\nfunction loadClassValidator(): any | null {\n if (cached !== undefined) { return cached }\n for (const base of [import.meta.url, join(process.cwd(), 'noop.js')]) {\n try {\n cached = createRequire(base)('class-validator')\n return cached\n } catch { /* try the next resolution base */ }\n }\n cached = null\n return cached\n}\n\nexport interface ValidationMeta {\n /** `ValidationTypes` discriminator (e.g. `customValidation`, `conditionalValidation`). */\n type?: string\n /** Validator name - the actionable identity for built-ins (`isString`, `minLength`, ...). */\n name?: string\n constraints?: unknown[]\n}\n\n/**\n * Read `class-validator` metadata for a DTO class, grouped by property name.\n * Returns an empty map when `class-validator` is not installed or the class\n * carries no validation decorators - so callers degrade gracefully to swagger /\n * `design:type` reflection.\n */\nexport function classValidatorMetas(dtoType: any): Record<string, ValidationMeta[]> {\n const cv = loadClassValidator()\n if (!cv?.getMetadataStorage) { return {} }\n let metas: Array<{ propertyName?: string; type?: string; name?: string; constraints?: unknown[] }>\n try {\n metas = cv.getMetadataStorage().getTargetValidationMetadatas(dtoType, null, false, false)\n } catch {\n return {}\n }\n const out: Record<string, ValidationMeta[]> = {}\n for (const m of metas) {\n if (!m.propertyName) { continue }\n (out[m.propertyName] ??= []).push({ type: m.type, name: m.name, constraints: m.constraints })\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { classValidatorMetas } from './classValidator.js'\n\n/** `@nestjs/swagger` reflect-metadata keys. Read directly so swagger stays an optional peer. */\nconst API_MODEL_PROPERTIES = 'swagger/apiModelProperties'\nconst API_MODEL_PROPERTIES_ARRAY = 'swagger/apiModelPropertiesArray'\n\n/**\n * A transport-neutral description of a single input field. Every metadata\n * source (swagger decorators, class-validator, an OpenAPI document, TypeScript\n * `design:type`) is mapped to this shape, the shapes are merged by precedence,\n * and the result is converted to Zod once. Keeping a single intermediate keeps\n * the per-source mappers small and the Zod construction in one place.\n */\nexport interface FieldDesc {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown'\n required?: boolean\n /** Field accepts `null` (`@ApiProperty({ nullable: true })` / OpenAPI `nullable`). */\n nullable?: boolean\n description?: string\n enum?: (string | number)[]\n items?: FieldDesc\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n format?: string\n default?: unknown\n}\n\n/** Strip `undefined` values so a later source never clobbers an earlier one with a hole. */\nfunction defined<T extends object>(obj: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) { out[k] = v }\n }\n return out as Partial<T>\n}\n\n/** Merge `over` onto `base` - defined keys of `over` win. */\nexport function mergeField(base: FieldDesc, over: FieldDesc): FieldDesc {\n return { ...base, ...defined(over) }\n}\n\nfunction enumToZod(values: (string | number)[]): z.ZodType {\n const strings = values.filter((v): v is string => typeof v === 'string')\n if (strings.length === values.length && strings.length > 0) {\n return z.enum(strings as [string, ...string[]])\n }\n const literals = values.map((v) => z.literal(v))\n if (literals.length === 0) { return z.unknown() }\n if (literals.length === 1) { return literals[0] }\n return z.union(literals as unknown as [z.ZodType, z.ZodType, ...z.ZodType[]])\n}\n\nfunction baseToZod(d: FieldDesc): z.ZodType {\n switch (d.type) {\n case 'string': {\n let s = z.string()\n if (d.minLength != null) { s = s.min(d.minLength) }\n if (d.maxLength != null) { s = s.max(d.maxLength) }\n return s\n }\n case 'integer':\n case 'number': {\n let n = z.number()\n if (d.type === 'integer') { n = n.int() }\n if (d.min != null) { n = n.min(d.min) }\n if (d.max != null) { n = n.max(d.max) }\n return n\n }\n case 'boolean':\n return z.boolean()\n case 'array':\n return z.array(d.items ? fieldToZod({ ...d.items, required: true }) : z.unknown())\n case 'object':\n return z.record(z.string(), z.unknown())\n default:\n return z.unknown()\n }\n}\n\n/** Convert a merged {@link FieldDesc} to a Zod schema. */\nexport function fieldToZod(d: FieldDesc): z.ZodType {\n let schema = (d.enum?.length) ? enumToZod(d.enum) : baseToZod(d)\n if (d.description) { schema = schema.describe(d.description) }\n if (d.nullable) { schema = schema.nullable() }\n if (d.default !== undefined) {\n schema = (schema as any).default(d.default)\n } else if (d.required === false) {\n schema = schema.optional()\n }\n return schema\n}\n\n// --- per-source mappers ---------------------------------------------------\n\n/** Normalise a TS-enum object or an array literal to a flat value list. */\nexport function normalizeEnum(value: unknown): (string | number)[] | undefined {\n if (Array.isArray(value)) {\n return value.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n if (value && typeof value === 'object') {\n return Object.values(value).filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n return undefined\n}\n\n/** Map a swagger/`design:type` type token (constructor, `[Type]`, or string) to a base type. */\nexport function typeTokenToBase(type: unknown): FieldDesc['type'] | undefined {\n if (type == null) { return undefined }\n if (type === String) { return 'string' }\n if (type === Number) { return 'number' }\n if (type === Boolean) { return 'boolean' }\n if (type === Array) { return 'array' }\n if (type === Date) { return 'string' }\n if (Array.isArray(type)) { return 'array' }\n if (typeof type === 'string') {\n const t = type.toLowerCase()\n if (t === 'string' || t === 'number' || t === 'integer' || t === 'boolean' || t === 'array' || t === 'object') {\n return t\n }\n }\n return undefined\n}\n\n/** From the constructor TypeScript emits via `emitDecoratorMetadata`. */\nexport function designTypeToField(ctor: unknown): FieldDesc {\n const type = typeTokenToBase(ctor)\n const f: FieldDesc = {}\n if (type) { f.type = type }\n return f\n}\n\n/** From an `@ApiParam`/`@ApiQuery` entry stored under `swagger/apiParameters`. */\nexport function swaggerParamToField(p: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (p['description']) { f.description = p['description'] }\n if (typeof p['required'] === 'boolean') { f.required = p['required'] }\n const type = typeTokenToBase(p['type'])\n if (type) { f.type = type }\n if (p['isArray']) { f.type = 'array' }\n const en = normalizeEnum(p['enum'])\n if (en) { f.enum = en }\n if (p['schema'] && typeof p['schema'] === 'object') {\n return mergeField(f, openapiSchemaToField(p['schema']))\n }\n return f\n}\n\n/** From an `@ApiProperty` options object stored under `swagger/apiModelProperties`. */\nexport function apiPropertyToField(o: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (o['description']) { f.description = o['description'] }\n if (typeof o['required'] === 'boolean') { f.required = o['required'] }\n const type = typeTokenToBase(o['type'])\n if (type) { f.type = type }\n if (o['isArray']) {\n f.items = { type: type && type !== 'array' ? type : 'unknown' }\n f.type = 'array'\n }\n const en = normalizeEnum(o['enum'])\n if (en) { f.enum = en }\n if (o['minimum'] != null) { f.min = o['minimum'] }\n if (o['maximum'] != null) { f.max = o['maximum'] }\n if (o['minLength'] != null) { f.minLength = o['minLength'] }\n if (o['maxLength'] != null) { f.maxLength = o['maxLength'] }\n if (o['format']) { f.format = o['format'] }\n if (o['nullable'] === true) { f.nullable = true }\n if (o['default'] !== undefined) { f.default = o['default'] }\n return f\n}\n\n/** `class-validator` decorator type → field base type. */\nconst CV_TYPE: Record<string, FieldDesc['type']> = {\n isString: 'string',\n isInt: 'integer',\n isBoolean: 'boolean',\n isArray: 'array'\n}\n\n/** `class-validator` decorator type → numeric-constraint field key. */\nconst CV_NUMERIC: Record<string, 'min' | 'max' | 'minLength' | 'maxLength'> = {\n min: 'min',\n max: 'max',\n minLength: 'minLength',\n maxLength: 'maxLength'\n}\n\n/**\n * Fold one `class-validator` metadata entry into the field descriptor. Built-in\n * validators record their identity in `name` (`isString`, `minLength`, ...) with\n * `type: 'customValidation'`; `@IsOptional` uses `name: 'isOptional'`. We key off\n * `name`, falling back to `type`.\n */\nfunction applyValidationMeta(f: FieldDesc, meta: { type?: string; name?: string; constraints?: unknown[] }): void {\n const key = meta.name ?? meta.type\n if (!key) { return }\n if (key in CV_TYPE) { f.type = CV_TYPE[key]; return }\n const c0 = meta.constraints?.[0]\n if (key in CV_NUMERIC) {\n if (typeof c0 === 'number') { f[CV_NUMERIC[key]] = c0 }\n return\n }\n if (key === 'isNumber') { if (!f.type) { f.type = 'number' } return }\n if (key === 'isEmail') { if (!f.type) { f.type = 'string' } f.format = 'email'; return }\n if (key === 'isDate' || key === 'isDateString') { f.type = 'string'; f.format = 'date-time'; return }\n if (key === 'isEnum') { const e = normalizeEnum(c0); if (e) { f.enum = e } return }\n if (key === 'isOptional') { f.required = false }\n}\n\n/** From an array of `class-validator` validation-metadata entries for one property. */\nexport function classValidatorToField(metas: Array<{ type?: string; name?: string; constraints?: unknown[] }>): FieldDesc {\n const f: FieldDesc = {}\n for (const meta of metas) { applyValidationMeta(f, meta) }\n return f\n}\n\n/** From an OpenAPI Schema Object (used by both the doc and `@ApiParam({ schema })`). */\nexport function openapiSchemaToField(schema: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n const type = typeof schema['type'] === 'string' ? schema['type'].toLowerCase() : undefined\n if (type === 'string' || type === 'number' || type === 'integer' || type === 'boolean' || type === 'array' || type === 'object') {\n f.type = type\n }\n if (schema['description']) { f.description = schema['description'] }\n const en = normalizeEnum(schema['enum'])\n if (en) { f.enum = en }\n if (schema['minimum'] != null) { f.min = schema['minimum'] }\n if (schema['maximum'] != null) { f.max = schema['maximum'] }\n if (schema['minLength'] != null) { f.minLength = schema['minLength'] }\n if (schema['maxLength'] != null) { f.maxLength = schema['maxLength'] }\n if (schema['format']) { f.format = schema['format'] }\n if (schema['nullable'] === true) { f.nullable = true }\n if (schema['default'] !== undefined) { f.default = schema['default'] }\n if (schema['items'] && typeof schema['items'] === 'object') {\n f.items = openapiSchemaToField(schema['items'])\n }\n return f\n}\n\n/**\n * Reflect a whole-DTO class (`@Body() dto: CreateDto`) into per-property\n * {@link FieldDesc}s. Property names are the union of `@ApiProperty` and\n * `class-validator` decorated fields; each field merges `design:type` (base),\n * then `class-validator` constraints, then `@ApiProperty` (highest). Properties\n * default to required unless a source marks them optional.\n */\nexport function reflectDtoFields(dtoType: any): Record<string, FieldDesc> {\n const proto = dtoType?.prototype\n if (!proto) { return {} }\n const cvMetas = classValidatorMetas(dtoType)\n\n const names = new Set<string>()\n const swaggerArray = (Reflect.getMetadata(API_MODEL_PROPERTIES_ARRAY, proto) as string[] | undefined) ?? []\n for (const entry of swaggerArray) { names.add(entry.replace(/^:/, '')) }\n for (const name of Object.keys(cvMetas)) { names.add(name) }\n\n const out: Record<string, FieldDesc> = {}\n for (const name of names) {\n let f = designTypeToField(Reflect.getMetadata('design:type', proto, name))\n if (cvMetas[name]) { f = mergeField(f, classValidatorToField(cvMetas[name])) }\n const apiProp = Reflect.getMetadata(API_MODEL_PROPERTIES, proto, name) as Record<string, any> | undefined\n if (apiProp) {\n const fromApi = apiPropertyToField(apiProp)\n // `@ApiProperty` is required unless `required: false` is explicit.\n if (fromApi.required === undefined && apiProp['required'] === undefined) { fromApi.required = true }\n f = mergeField(f, fromApi)\n }\n if (f.required === undefined) { f.required = true }\n out[name] = f\n }\n return out\n}\n\n/**\n * Names of fields that could not be reflected into a concrete type - they will\n * become `z.unknown()` (or `z.array(z.unknown())`). This is how a nested DTO or a\n * `Dto[]` property silently degrades (reflection is one level deep), so the\n * adapters surface these as a build-time warning pointing at `@Trpc({ output })`\n * / `@Mcp({ input })`. Enum and `object` (record) fields are not degraded.\n */\nexport function unreflectedFields(fields: Record<string, FieldDesc>): string[] {\n const out: string[] = []\n for (const [name, f] of Object.entries(fields)) {\n if (f.enum?.length) { continue }\n if (!f.type || f.type === 'unknown') { out.push(name) } else if (f.type === 'array' && (!f.items?.type || f.items.type === 'unknown')) { out.push(name) }\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { type FieldDesc, mergeField, openapiSchemaToField } from './schema.js'\n\n/**\n * A minimal view of an OpenAPI document - the subset we read. Matches the shape\n * `SwaggerModule.createDocument()` returns, but typed loosely so callers can\n * pass any compatible object without a hard `@nestjs/swagger` dependency.\n */\nexport interface OpenApiDocument {\n paths?: Record<string, Record<string, any>>\n components?: { schemas?: Record<string, any> }\n}\n\nexport interface OpenApiLookup {\n doc: OpenApiDocument\n /** `${METHOD} ${path}` → operation object. */\n operations: Map<string, any>\n}\n\n/** Index a document's operations by `${METHOD} ${path}` for fast matching. */\nexport function buildOpenApiLookup(doc: OpenApiDocument): OpenApiLookup {\n const operations = new Map<string, any>()\n for (const [path, item] of Object.entries(doc.paths ?? {})) {\n for (const [verb, op] of Object.entries(item ?? {})) {\n operations.set(`${verb.toUpperCase()} ${path}`, op)\n }\n }\n return { doc, operations }\n}\n\n/** Locate the operation for a route, tolerating a global path prefix on the document side. */\nfunction findOperation(lookup: OpenApiLookup, method: string, openapiPath: string): any | undefined {\n const exact = lookup.operations.get(`${method} ${openapiPath}`)\n if (exact) { return exact }\n // Fall back to a suffix match so a `setGlobalPrefix('api')` document still resolves.\n for (const [key, op] of lookup.operations) {\n const [verb, path] = key.split(' ')\n if (verb === method && (path.endsWith(openapiPath) || openapiPath.endsWith(path))) { return op }\n }\n return undefined\n}\n\nfunction resolveRef(doc: OpenApiDocument, schema: any): any {\n let current = schema\n let guard = 0\n while (current && typeof current === 'object' && typeof current['$ref'] === 'string' && guard < 10) {\n const match = /^#\\/components\\/schemas\\/(.+)$/.exec(current['$ref'])\n if (!match) { break }\n current = doc.components?.schemas?.[match[1]]\n guard += 1\n }\n return current\n}\n\n/**\n * Resolve the per-field descriptors for a route from an ingested OpenAPI\n * document. Merges `parameters` (path/query/header) and the JSON request-body\n * schema's properties into a single field map. Returns `{}` when the operation\n * isn't found - callers fall back to decorator reflection.\n */\nexport function openApiFields(lookup: OpenApiLookup, method: string, openapiPath: string): Record<string, FieldDesc> {\n const op = findOperation(lookup, method, openapiPath)\n if (!op) { return {} }\n const out: Record<string, FieldDesc> = {}\n\n for (const param of (op['parameters'] as Array<Record<string, any>> | undefined) ?? []) {\n const name = typeof param['name'] === 'string' ? param['name'] : undefined\n if (!name) { continue }\n const schema = param['schema'] ? resolveRef(lookup.doc, param['schema']) : undefined\n let field = schema ? openapiSchemaToField(schema) : {}\n if (param['description']) { field = mergeField(field, { description: param['description'] }) }\n if (typeof param['required'] === 'boolean') { field = mergeField(field, { required: param['required'] }) }\n out[name] = field\n }\n\n const bodySchema = resolveRef(lookup.doc, op['requestBody']?.['content']?.['application/json']?.['schema'])\n if (bodySchema && typeof bodySchema === 'object' && bodySchema['properties']) {\n const required = new Set<string>(Array.isArray(bodySchema['required']) ? bodySchema['required'] : [])\n for (const [name, propSchema] of Object.entries(bodySchema['properties'] as Record<string, any>)) {\n const field = openapiSchemaToField(resolveRef(lookup.doc, propSchema))\n field.required = required.has(name)\n out[name] = field\n }\n }\n\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { type FieldDesc, fieldToZod, reflectDtoFields } from './schema.js'\n\n/** `@nestjs/swagger` response metadata key (read directly - swagger is an optional peer). */\nconst API_RESPONSE = 'swagger/apiResponse'\n\n/** Status keys we treat as the \"success\" response, in preference order. */\nconst SUCCESS_KEYS = ['200', '201', '202', '204', '2XX', 'default']\n\n/** The 2xx (or first) `@ApiResponse` entry for a method, if any. */\nfunction successEntry(method: (...args: any[]) => any): { type?: unknown; isArray?: boolean } | undefined {\n const responses = Reflect.getMetadata(API_RESPONSE, method) as Record<string, { type?: unknown; isArray?: boolean }> | undefined\n if (!responses) { return undefined }\n const key = SUCCESS_KEYS.find((k) => responses[k]) ?? Object.keys(responses)[0]\n return key ? responses[key] : undefined\n}\n\n/**\n * Reflect a `@Trpc` procedure's output schema from the method's\n * `@ApiOkResponse({ type: Dto })` (or any 2xx `@ApiResponse`) metadata. The\n * response DTO is flattened with {@link reflectDtoFields} into a Zod object,\n * wrapped in `z.array(...)` when the response is `isArray`.\n *\n * Returns `undefined` when there is no response DTO to reflect (e.g. a primitive\n * return type or no `@ApiResponse` decorator) - the caller then falls back to an\n * explicit `@Trpc({ output })` or an `unknown` output type.\n */\nexport function reflectResponseSchema(method: (...args: any[]) => any): z.ZodType | undefined {\n const entry = successEntry(method)\n const dtoType = entry?.type\n if (typeof dtoType !== 'function') { return undefined }\n\n const schema = reflectDtoSchema(dtoType)\n if (!schema) { return undefined }\n return entry?.isArray ? z.array(schema) : schema\n}\n\n/**\n * The reflected `FieldDesc` map for a method's response DTO (the same fields\n * {@link reflectResponseSchema} builds its schema from), or `undefined` when\n * there is no DTO to reflect. Used to detect fields that degraded to `unknown`\n * (nested DTO / `Dto[]`) so the caller can warn.\n */\nexport function reflectResponseFields(method: (...args: any[]) => any): Record<string, FieldDesc> | undefined {\n const dtoType = successEntry(method)?.type\n if (typeof dtoType !== 'function') { return undefined }\n return reflectDtoFields(dtoType)\n}\n\n/**\n * Reflect a DTO class (its `@ApiProperty`/`class-validator`-decorated properties)\n * into a Zod object schema. Returns `undefined` when the type isn't a class or\n * has no reflectable properties. Used for `@Trpc({ output })`/`@Trpc({ chunk })`\n * when given a DTO class instead of a Zod schema.\n */\nexport function reflectDtoSchema(dtoType: unknown): z.ZodType | undefined {\n if (typeof dtoType !== 'function') { return undefined }\n const fields = reflectDtoFields(dtoType)\n const names = Object.keys(fields)\n if (names.length === 0) { return undefined }\n const shape: Record<string, z.ZodType> = {}\n for (const name of names) { shape[name] = fieldToZod(fields[name]) }\n return z.object(shape)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RequestMethod` numeric values (from `@nestjs/common`) mapped to verbs. We\n * map our own table rather than importing the enum to avoid pulling a value\n * import for a handful of constants.\n */\nconst REQUEST_METHOD: Record<number, string> = {\n 0: 'GET',\n 1: 'POST',\n 2: 'PUT',\n 3: 'DELETE',\n 4: 'PATCH',\n 6: 'OPTIONS',\n 7: 'HEAD'\n}\n\nexport interface RouteInfo {\n /** HTTP verb (`GET`/`POST`/...). `PATCH` and others outside the REST set fall back to `POST`-ish handling by callers. */\n method: string\n /** Full route template in Nest form, e.g. `sessions/:sessionId/channels/:channelId` (no leading slash). */\n path: string\n /** Full route template in OpenAPI form, e.g. `/sessions/{sessionId}/channels/{channelId}`. */\n openapiPath: string\n /** Names of the `:param` placeholders across controller + method path. */\n pathParams: string[]\n}\n\nfunction normalizeSegment(value: unknown): string {\n if (typeof value !== 'string') { return '' }\n return value.replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction joinPath(...segments: string[]): string {\n return segments.map(normalizeSegment).filter(Boolean).join('/')\n}\n\n/**\n * Resolve the composed route (controller prefix + method path), HTTP verb, and\n * path-param names for a decorated controller method, reading Nest's own\n * `PATH_METADATA`/`METHOD_METADATA` reflection.\n */\nexport function reflectRoute(classRef: any, method: (...args: any[]) => any): RouteInfo {\n const classPath = Reflect.getMetadata(PATH_METADATA, classRef) as string | string[] | undefined\n const methodPath = Reflect.getMetadata(PATH_METADATA, method) as string | string[] | undefined\n const verbCode = Reflect.getMetadata(METHOD_METADATA, method) as number | undefined\n\n const classSeg = Array.isArray(classPath) ? (classPath[0] ?? '') : (classPath ?? '')\n const methodSeg = Array.isArray(methodPath) ? (methodPath[0] ?? '') : (methodPath ?? '')\n const path = joinPath(classSeg, methodSeg)\n const httpMethod = REQUEST_METHOD[verbCode ?? 0] ?? 'GET'\n\n const pathParams = [...path.matchAll(/:([A-Za-z0-9_]+)/g)].map((m) => m[1])\n const openapiPath = `/${path.replace(/:([A-Za-z0-9_]+)/g, '{$1}')}`\n\n return { method: httpMethod, path, openapiPath, pathParams }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { FieldDesc } from './schema.js'\nimport { swaggerParamToField } from './schema.js'\n\n/** `@nestjs/swagger` reflect-metadata keys (read directly - swagger is an optional peer). */\nconst API_OPERATION = 'swagger/apiOperation'\nconst API_PARAMETERS = 'swagger/apiParameters'\n\nexport interface OperationMeta {\n /** Tool-description candidate from `@ApiOperation({ summary | description })`. */\n description?: string\n /** Per-name `FieldDesc` reflected from `@ApiParam`/`@ApiQuery` entries. */\n params: Record<string, FieldDesc>\n}\n\n/**\n * Read operation-level `@nestjs/swagger` metadata off a controller method:\n * `@ApiOperation` (summary/description) and the `@ApiParam`/`@ApiQuery` array\n * (each describing one path/query field). Returns empty data when swagger\n * decorators are absent.\n */\nexport function reflectOperation(method: (...args: any[]) => any): OperationMeta {\n const operation = Reflect.getMetadata(API_OPERATION, method) as Record<string, any> | undefined\n const description = operation\n ? (typeof operation['summary'] === 'string' && operation['summary']\n ? operation['summary']\n : (typeof operation['description'] === 'string' ? operation['description'] : undefined))\n : undefined\n\n const parameters = (Reflect.getMetadata(API_PARAMETERS, method) as Array<Record<string, any>> | undefined) ?? []\n const params: Record<string, FieldDesc> = {}\n for (const p of parameters) {\n const name = typeof p['name'] === 'string' ? p['name'] : undefined\n if (!name) { continue }\n params[name] = swaggerParamToField(p)\n }\n\n return { description, params }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { HttpException, Injectable, Logger, type CanActivate, type Type } from '@nestjs/common'\nimport { ApplicationConfig, DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core'\nimport { SilkweaveError, type Action, type ActionKind, type SilkweaveContext } from '@silkweave/core'\nimport { z } from 'zod/v4'\nimport { collectGlobalGuards, collectGuards, runGuards } from './guards.js'\nimport { MCP_METADATA, TRPC_METADATA, type McpMetadata, type TrpcMetadata } from './metadata.js'\nimport { invokeRebound, specialBinding, type Binding } from './rebind.js'\nimport { populateRequestSlots, requestSlotFields, type RequestSlots } from './requestSlots.js'\nimport { buildOpenApiLookup, openApiFields, type OpenApiDocument, type OpenApiLookup } from './reflect/openapi.js'\nimport { PARAMTYPE, type ParamSlot, readParamSlots } from './reflect/params.js'\nimport { reflectDtoSchema, reflectResponseFields, reflectResponseSchema } from './reflect/response.js'\nimport { reflectRoute, type RouteInfo } from './reflect/route.js'\nimport { type FieldDesc, fieldToZod, mergeField, reflectDtoFields, unreflectedFields } from './reflect/schema.js'\nimport { reflectOperation } from './reflect/swagger.js'\n\n/** Discovery-time diagnostics (unreflectable params, degraded outputs). */\nconst logger = new Logger('Silkweave')\n\ninterface Discovered {\n instance: object\n classRef: Type<unknown>\n method: (...args: unknown[]) => unknown\n methodName: string\n mcp?: McpMetadata\n trpc?: TrpcMetadata\n}\n\ninterface BuiltInput {\n shape: Record<string, z.ZodType>\n bindings: Binding[]\n /** Human-readable notes about params reflection could not turn into fields. */\n warnings: string[]\n}\n\n/** Shared reflection computed once per discovered method, reused across targets. */\ninterface Reflected {\n route: RouteInfo\n base: string\n description?: string\n baseShape: Record<string, z.ZodType>\n bindings: Binding[]\n guards: ReturnType<typeof collectGuards>\n requestSlots: RequestSlots\n streaming: boolean\n}\n\nexport interface DiscoverOptions {\n openapi?: OpenApiDocument\n globalGuards?: Type<CanActivate>[]\n defaultResult?: 'json' | 'smart'\n}\n\n@Injectable()\nexport class ControllerDiscovery {\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly moduleRef: ModuleRef,\n private readonly appConfig: ApplicationConfig\n ) { }\n\n /**\n * Walk every Nest provider/controller, find methods annotated with `@Mcp`\n * and/or `@Trpc`, and build a core `Action` per decorator present on each\n * method. The input schema is reflected from the route + parameter decorators\n * (+ optional OpenAPI document) and the `run` re-binds the validated input back\n * into the method's positional arguments (with `@UseGuards` guards applied\n * first). A method carrying both decorators yields two actions - one gated to\n * the `mcp` adapter, one to the `trpc`/`typegen` adapters - sharing the same\n * reflected input, bindings, and guards.\n */\n discover(options: DiscoverOptions = {}): Action[] {\n const lookup = options.openapi ? buildOpenApiLookup(options.openapi) : undefined\n const discovered: Discovered[] = []\n for (const wrapper of this.discovery.getProviders().concat(this.discovery.getControllers())) {\n const { instance } = wrapper\n if (!instance || typeof instance !== 'object') { continue }\n const proto = Object.getPrototypeOf(instance) as object | null\n if (!proto) { continue }\n const classRef = instance.constructor as Type<unknown>\n for (const methodName of this.scanner.getAllMethodNames(proto)) {\n const method = (proto as Record<string, unknown>)[methodName] as ((...args: unknown[]) => unknown) | undefined\n if (typeof method !== 'function') { continue }\n const mcp = this.reflector.get<McpMetadata>(MCP_METADATA, method)\n const trpc = this.reflector.get<TrpcMetadata>(TRPC_METADATA, method)\n if (!mcp && !trpc) { continue }\n discovered.push({ instance, classRef, method, methodName, mcp, trpc })\n }\n }\n\n const globalGuards = options.globalGuards ?? []\n const actions: Action[] = []\n for (const d of discovered) {\n const shared = this.reflect(d, lookup)\n if (d.mcp) { actions.push(this.mcpAction(d, shared, globalGuards, options.defaultResult)) }\n if (d.trpc) { actions.push(this.trpcAction(d, shared, globalGuards)) }\n }\n return actions\n }\n\n /** Compute the per-method reflection shared by the `mcp` and `trpc` builders. */\n private reflect(d: Discovered, lookup: OpenApiLookup | undefined): Reflected {\n const proto = Object.getPrototypeOf(d.instance) as object\n const route = reflectRoute(d.classRef, d.method)\n const slots = readParamSlots(d.classRef, d.methodName, proto)\n const operation = reflectOperation(d.method)\n const docFields = lookup ? openApiFields(lookup, route.method, route.openapiPath) : {}\n\n const { shape, bindings, warnings } = buildInput(proto, d.methodName, route.pathParams, slots, operation.params, docFields)\n for (const w of warnings) { logger.warn(`${d.classRef.name}.${d.methodName}: ${w}`) }\n\n return {\n route,\n base: d.classRef.name.replace(/Controller$/, ''),\n description: operation.description,\n baseShape: shape,\n bindings,\n guards: collectGuards(this.reflector, d.classRef, d.method),\n requestSlots: requestSlotFields(bindings),\n streaming: isAsyncGeneratorFn(d.method)\n }\n }\n\n /** Build a guard-application closure shared by both run shapes. */\n private guardRunner(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]) {\n const { moduleRef, reflector, appConfig } = this\n const { guards, requestSlots } = shared\n const { classRef, method } = d\n return async (context: SilkweaveContext, input: object): Promise<void> => {\n // Resolved at call time - `APP_GUARD` instances aren't populated until\n // `app.init()` finishes. Globals run before the route/class guards.\n const all = [...collectGlobalGuards(appConfig, globalGuards), ...guards]\n if (all.length === 0) { return }\n const request = context.getOptional<unknown>('request')\n const response = context.getOptional<unknown>('response') ?? null\n const hasRequest = request != null\n const guardRequest = hasRequest ? request : { headers: {}, params: {}, query: {} }\n populateRequestSlots(guardRequest, requestSlots, input as Record<string, unknown>)\n await runGuards(all, moduleRef, reflector, classRef, method, guardRequest, response, hasRequest ? 'http' : 'rpc')\n }\n }\n\n /** Synthesize the MCP-targeted action (unchanged behavior from v2.4). */\n private mcpAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[], defaultResult?: 'json' | 'smart'): Action {\n const meta = d.mcp!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n return {\n name,\n description,\n input: z.object(shape),\n ...((meta.result ?? defaultResult) ? { disposition: meta.result ?? defaultResult } : {}),\n isEnabled: (ctx) => ctx.getOptional<string>('adapter') === 'mcp',\n ...(streaming\n ? { chunk: z.unknown(), run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, false) }\n : {\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n }\n })\n } as Action\n }\n\n /** Synthesize the tRPC-targeted action (kind/output/subscription + httpStatus errors). */\n private trpcAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]): Action {\n const meta = d.trpc!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n // tRPC and typegen both consume `@Trpc` actions; MCP never does.\n const isEnabled = (ctx: SilkweaveContext): boolean => {\n const adapter = ctx.getOptional<string>('adapter')\n return adapter === 'trpc' || adapter === 'typegen'\n }\n\n if (streaming) {\n return {\n name,\n description,\n input: z.object(shape),\n chunk: resolveSchema(meta.chunk) ?? z.unknown(),\n isEnabled,\n run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true)\n } as Action\n }\n\n const kind: ActionKind = meta.kind === 'query' || meta.kind === 'mutation'\n ? meta.kind\n : (shared.route.method === 'GET' ? 'query' : 'mutation')\n const output = resolveOutput(meta, method)\n\n // Reflection is one level deep, so a nested DTO or `Dto[]` output property\n // degrades to `unknown`/`unknown[]`. Surface it - the fix is `@Trpc({ output })`.\n const degraded = outputDegradedFields(meta, method)\n if (output && degraded.length > 0) {\n logger.warn(\n `${d.classRef.name}.${d.methodName}: tRPC output field(s) ${degraded.join(', ')} reflected to 'unknown' ` +\n '(nested DTO or Dto[] - reflection is one level deep). Supply @Trpc({ output }) with a Zod schema for precise types.'\n )\n }\n\n return {\n name,\n description,\n input: z.object(shape),\n ...(output ? { output } : {}),\n kind,\n isEnabled,\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n } catch (error) {\n throw toSilkweaveError(error)\n }\n }\n } as Action\n }\n}\n\n/** Build a streaming (`async *`) run that applies guards then yields the method's chunks. */\nfunction streamingRun(\n applyGuards: (context: SilkweaveContext, input: object) => Promise<void>,\n method: (...args: unknown[]) => unknown,\n instance: object,\n bindings: Binding[],\n applyParamPipes: boolean,\n mapErrors: boolean\n) {\n return async function* (input: object, context: SilkweaveContext): AsyncGenerator<unknown, void, void> {\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const gen = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes) as AsyncIterable<unknown>\n for await (const chunk of gen) { yield chunk }\n } catch (error) {\n throw mapErrors ? toSilkweaveError(error) : error\n }\n }\n}\n\n/** Resolve a `@Trpc` action's output schema: explicit override wins over `@ApiOkResponse` reflection. */\nfunction resolveOutput(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): z.ZodType | undefined {\n return resolveSchema(meta.output) ?? reflectResponseSchema(method)\n}\n\n/**\n * Output field names that reflected to `unknown` (nested DTO / `Dto[]`). Only the\n * reflected paths are inspected - an explicit Zod or raw-shape `@Trpc({ output })`\n * is the caller's own typing and is never flagged.\n */\nfunction outputDegradedFields(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): string[] {\n if (meta.output != null && isZodSchema(meta.output)) { return [] }\n const fields = typeof meta.output === 'function'\n ? reflectDtoFields(meta.output)\n : meta.output != null ? undefined : reflectResponseFields(method)\n return fields ? unreflectedFields(fields) : []\n}\n\n/**\n * Normalise an `@Mcp`/`@Trpc({ input })` override to a raw Zod shape. Accepts a\n * plain `Record<string, ZodType>` or a whole `z.object({ ... })` (duck-typed by\n * `safeParse` + `shape`, so a different zod copy's object still unwraps).\n */\nfunction inputShape(input: McpMetadata['input']): Record<string, z.ZodType> {\n if (!input) { return {} }\n const maybe = input as { safeParse?: unknown; shape?: unknown }\n if (typeof maybe.safeParse === 'function' && maybe.shape != null && typeof maybe.shape === 'object') {\n return maybe.shape as Record<string, z.ZodType>\n }\n return input as Record<string, z.ZodType>\n}\n\n/**\n * Coerce an `output`/`chunk` override to a Zod schema: a Zod schema passes\n * through, a DTO class is reflected, and a raw shape is wrapped in `z.object`.\n */\nfunction resolveSchema(value: TrpcMetadata['output']): z.ZodType | undefined {\n if (value == null) { return undefined }\n if (isZodSchema(value)) { return value }\n if (typeof value === 'function') { return reflectDtoSchema(value) }\n return z.object(value)\n}\n\nfunction isZodSchema(value: unknown): value is z.ZodType {\n return Boolean(value) && typeof value === 'object' && typeof (value as { safeParse?: unknown }).safeParse === 'function'\n}\n\nfunction isAsyncGeneratorFn(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as { constructor?: { name?: string } }).constructor?.name === 'AsyncGeneratorFunction'\n}\n\n/**\n * Convert a thrown Nest `HttpException` into a `SilkweaveError` carrying its HTTP\n * status, so the tRPC adapter's `mapError` maps it to the right `TRPCError` code\n * (and `data.httpStatus`) - e.g. a denying `AuthGuard`'s `UnauthorizedException`\n * surfaces to the client as a `401`. Non-HTTP errors pass through unchanged.\n */\nfunction toSilkweaveError(error: unknown): unknown {\n if (error instanceof HttpException) {\n const status = error.getStatus()\n const response = error.getResponse()\n const raw = typeof response === 'string'\n ? response\n : (response as { message?: unknown })?.message ?? error.message\n const message = Array.isArray(raw) ? raw.join(', ') : String(raw)\n return new SilkweaveError(message, 'http_error', status)\n }\n return error\n}\n\n/** Build the merged Zod input shape and the per-argument re-bind plan. */\nfunction buildInput(\n proto: object,\n methodName: string,\n pathParams: string[],\n slots: ReturnType<typeof readParamSlots>,\n operationParams: Record<string, FieldDesc>,\n docFields: Record<string, FieldDesc>\n): BuiltInput {\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n const fields: Record<string, FieldDesc> = {}\n const warnings: string[] = []\n const maxIndex = slots.reduce((m, s) => Math.max(m, s.index), -1)\n const bindings: Binding[] = Array.from({ length: maxIndex + 1 }, () => ({ kind: 'missing' as const }))\n\n const addField = (name: string, desc: FieldDesc): void => {\n fields[name] = name in fields ? mergeField(fields[name], desc) : desc\n }\n\n for (const slot of slots) {\n const { binding, fields: contributed } = contributeSlot(slot, pathParams, designTypes)\n bindings[slot.index] = binding\n for (const [name, desc] of Object.entries(contributed)) { addField(name, desc) }\n // A whole-DTO `@Body()`/`@Query()` that reflected to zero fields: the type\n // was unreflectable (an interface, or an intersection/union TypeScript\n // erases to `Object`/`Array` under `design:type`). Its fields are silently\n // absent unless declared via `@Mcp`/`@Trpc({ input })`.\n if (binding.kind === 'object' && binding.fields.length === 0) {\n const typeName = (designTypes[slot.index] as { name?: string } | undefined)?.name ?? 'unknown'\n warnings.push(\n `whole-${binding.source} parameter #${slot.index} (type '${typeName}') reflected no input fields. ` +\n `If it is an intersection/union (e.g. 'A & B'), TypeScript erases it to '${typeName}' so the DTO is lost - ` +\n 'use a single DTO class or declare the fields via @Mcp/@Trpc({ input }).'\n )\n }\n }\n\n // Layer operation-level (`@ApiParam`/`@ApiQuery`) then OpenAPI-document\n // metadata over the structural fields (later sources win per field).\n for (const [name, desc] of Object.entries(operationParams)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n for (const [name, desc] of Object.entries(docFields)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n\n const shape: Record<string, z.ZodType> = {}\n for (const [name, desc] of Object.entries(fields)) { shape[name] = fieldToZod(desc) }\n\n return { shape, bindings, warnings }\n}\n\nfunction designTypeAt(designTypes: unknown[], index: number): FieldDesc {\n const ctor = designTypes[index]\n if (ctor === String) { return { type: 'string' } }\n if (ctor === Number) { return { type: 'number' } }\n if (ctor === Boolean) { return { type: 'boolean' } }\n return {}\n}\n\ninterface SlotContribution {\n binding: Binding\n /** Input fields this slot contributes, keyed by field name. */\n fields: Record<string, FieldDesc>\n}\n\n/** A `@Param('id')` scalar or a bare `@Param()` covering all path params. */\nfunction paramContribution(slot: ParamSlot, pathParams: string[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source: 'path', metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: { type: 'string', required: true } }\n }\n }\n const fields: Record<string, FieldDesc> = {}\n for (const p of pathParams) { fields[p] = { type: 'string', required: true } }\n return { binding: { kind: 'params', fields: pathParams }, fields }\n}\n\n/** A `@Query('x')`/`@Body('x')` scalar or a whole-DTO `@Query()`/`@Body()`. */\nfunction bodyOrQueryContribution(slot: ParamSlot, source: 'query' | 'body', requiredScalar: boolean, designTypes: unknown[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source, metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: mergeField(designTypeAt(designTypes, slot.index), { required: requiredScalar }) }\n }\n }\n const dtoFields = reflectDtoFields(slot.designType)\n return {\n binding: { kind: 'object', source, fields: Object.keys(dtoFields), metatype: slot.designType, pipes: slot.pipes },\n fields: dtoFields\n }\n}\n\n/** Map one parameter slot to its input-field contribution and re-bind instruction. */\nfunction contributeSlot(slot: ParamSlot, pathParams: string[], designTypes: unknown[]): SlotContribution {\n switch (slot.paramtype) {\n case PARAMTYPE.PARAM: return paramContribution(slot, pathParams)\n case PARAMTYPE.QUERY: return bodyOrQueryContribution(slot, 'query', false, designTypes)\n case PARAMTYPE.BODY: return bodyOrQueryContribution(slot, 'body', true, designTypes)\n default: return { binding: specialBinding(slot.paramtype, slot.data) ?? { kind: 'missing' }, fields: {} }\n }\n}\n","import type { CanActivate, Type } from '@nestjs/common'\nimport type { HttpAdapterHost } from '@nestjs/core'\nimport type { Action, SilkweaveContext, SilkweaveOptions } from '@silkweave/core'\nimport type { OpenApiDocument } from './reflect/openapi.js'\n\n/**\n * Context passed to a Nest Silkweave adapter when `SilkweaveModule` wires it\n * up. Adapters register their routes directly on `httpAdapter` (no\n * placeholder middleware, no `silkweave()` builder), so they only fire\n * `register()` once and own the rest of their lifecycle implicitly through\n * Nest.\n */\nexport interface NestAdapterRegisterContext {\n /** Nest's underlying HTTP adapter (Express or Fastify). */\n httpAdapter: NonNullable<HttpAdapterHost['httpAdapter']>\n /** Identity the adapter surfaces to clients (e.g. MCP server name). */\n silkweaveOptions: SilkweaveOptions\n /** Per-adapter context - already forked with `{ adapter: adapter.name, ...userContext }`. */\n baseContext: SilkweaveContext\n /** Actions filtered to those enabled on this adapter. */\n actions: Action[]\n}\n\n/**\n * A Silkweave Nest adapter. Each transport (REST, tRPC, MCP) implements this\n * shape. `register()` is called from `SilkweaveModule.configure()` - which\n * runs *before* Nest's controller routes are mapped - so adapter routes\n * always sit ahead of any catch-all controllers in the framework's request\n * pipeline.\n */\nexport interface NestSilkweaveAdapter {\n /** Adapter discriminator - set on the silkweave context as `ctx.get('adapter')`. */\n readonly name: 'mcp' | 'trpc' | 'typegen'\n /** URL prefix the adapter mounts on (e.g. `'/mcp'`). Surfaced for introspection. */\n readonly basePath?: string\n /**\n * When `true`, the adapter receives every discovered action regardless of\n * each action's `isEnabled` gate. Reserved for non-runtime adapters that need\n * the entire action surface.\n */\n readonly allActions?: boolean\n /** Register this adapter's routes on Nest's HTTP server. */\n register(ctx: NestAdapterRegisterContext): void\n}\n\nexport interface SilkweaveModuleOptions {\n /** Identity for the silkweave instance - surfaced to MCP clients, OpenAPI, etc. */\n silkweave: SilkweaveOptions\n /** Adapters to mount - any of `mcp()`, `trpc()`, `typegen()`. */\n adapters: NestSilkweaveAdapter[]\n /** Initial context keys merged into every adapter's `baseContext`. */\n context?: Record<string, unknown>\n /**\n * Optional OpenAPI document (e.g. from `SwaggerModule.createDocument(app, cfg)`)\n * used as an authoritative source when reflecting `@Mcp` tool input schemas.\n * Matched to each method by HTTP verb + path; falls back to decorator\n * reflection when an operation or field isn't present.\n */\n openapi?: OpenApiDocument\n /**\n * Opt-in allow-list of app-global guard classes (registered via\n * `app.useGlobalGuards()` or `{ provide: APP_GUARD, useClass }`) to run on\n * every MCP tool call, before each method/class `@UseGuards`. Listed by\n * class - a blanket \"run all globals\" is deliberately not offered, since\n * unrelated globals (e.g. a `ThrottlerGuard` that needs a writable response)\n * would misbehave over MCP. Empty/omitted ⇒ no global guards run.\n *\n * Note: over MCP the request stand-in is headers-only (`params`/`query` are\n * empty), so per-session or IP-derived guard logic won't apply; header-based\n * authentication still works.\n */\n globalGuards?: Type<CanActivate>[]\n /**\n * Default MCP result format for every `@Mcp` tool - `'json'` (compact JSON,\n * `jsonToolResult`) or `'smart'` (inline small / embedded-resource large,\n * `smartToolResult`). Defaults to `'smart'`. A per-method `@Mcp({ result })`\n * overrides this, and a client's per-call `_meta.disposition` overrides both.\n */\n defaultResult?: 'json' | 'smart'\n}\n\nexport const SILKWEAVE_MODULE_OPTIONS = '__silkweave_module_options__'\n","import { Inject, Module, type DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common'\nimport { DiscoveryModule, HttpAdapterHost } from '@nestjs/core'\nimport { createContext } from '@silkweave/core'\nimport { ControllerDiscovery } from './controllerDiscovery.js'\nimport { SILKWEAVE_MODULE_OPTIONS, type SilkweaveModuleOptions } from './types.js'\n\n/**\n * Root module for `@silkweave/nestjs`.\n *\n * Discovers every `@Mcp`/`@Trpc`-decorated **controller method** via\n * `DiscoveryService`, reflects each into a Silkweave action (input schema from\n * the route + parameter decorators + optional OpenAPI document; invocation by\n * re-binding the validated input back into the method), and registers the\n * configured adapter(s) - `mcp()`, `trpc()`, `typegen()` - directly on Nest's\n * HTTP adapter inside `configure()`.\n *\n * Because `configure()` runs during `registerModules` - before Nest's\n * `registerRouter()` step - Silkweave's routes always sit ahead of every\n * controller in the Express stack. The controllers keep serving HTTP exactly as\n * before; `@Mcp` is purely additive.\n *\n * @example\n * ```ts\n * @Module({\n * imports: [\n * SilkweaveModule.forRoot({\n * silkweave: { name: 'app', description: 'My App', version: '1.0.0' },\n * adapters: [mcp({ basePath: '/mcp' })]\n * })\n * ],\n * controllers: [ChannelsController]\n * })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class SilkweaveModule implements NestModule {\n constructor(\n @Inject(SILKWEAVE_MODULE_OPTIONS) private readonly options: SilkweaveModuleOptions,\n private readonly discovery: ControllerDiscovery,\n private readonly httpAdapterHost: HttpAdapterHost\n ) { }\n\n static forRoot(options: SilkweaveModuleOptions): DynamicModule {\n return {\n module: SilkweaveModule,\n global: true,\n imports: [DiscoveryModule],\n providers: [\n { provide: SILKWEAVE_MODULE_OPTIONS, useValue: options },\n ControllerDiscovery\n ],\n exports: []\n }\n }\n\n configure(_consumer: MiddlewareConsumer): void {\n const httpAdapter = this.httpAdapterHost.httpAdapter\n if (!httpAdapter) {\n throw new Error('@silkweave/nestjs: HttpAdapterHost.httpAdapter is not available.')\n }\n const allActions = this.discovery.discover({\n openapi: this.options.openapi,\n globalGuards: this.options.globalGuards,\n defaultResult: this.options.defaultResult\n })\n for (const adapter of this.options.adapters) {\n const baseContext = createContext({ ...(this.options.context ?? {}), adapter: adapter.name })\n const actions = adapter.allActions\n ? allActions\n : allActions.filter((a) => !a.isEnabled || a.isEnabled(baseContext))\n adapter.register({\n httpAdapter,\n silkweaveOptions: this.options.silkweave,\n baseContext,\n actions\n })\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/lib/metadata.ts","../src/decorator/mcp.ts","../src/decorator/trpc.ts","../src/lib/executionContext.ts","../src/lib/guards.ts","../src/lib/reflect/params.ts","../src/lib/rebind.ts","../src/lib/requestSlots.ts","../src/lib/reflect/classValidator.ts","../src/lib/reflect/schema.ts","../src/lib/reflect/openapi.ts","../src/lib/reflect/response.ts","../src/lib/reflect/route.ts","../src/lib/reflect/swagger.ts","../src/lib/controllerDiscovery.ts","../src/lib/types.ts","../src/lib/silkweave.module.ts"],"sourcesContent":["import type { Type } from '@nestjs/common'\nimport type { ToolAnnotations } from '@silkweave/core'\nimport type { z } from 'zod/v4'\n\n/** Reflect-metadata key carrying `@Mcp` options on a controller method. */\nexport const MCP_METADATA = '__silkweave_mcp__'\n\n/** Reflect-metadata key carrying `@Trpc` options on a controller method. */\nexport const TRPC_METADATA = '__silkweave_trpc__'\n\n/**\n * Options for the `@Mcp()` method decorator. Every field is optional - an empty\n * `@Mcp()` exposes the decorated controller route as an MCP tool with its name,\n * description, and input schema fully reflected from the method's route\n * (`@Get`/`@Post`/...), parameter decorators (`@Param`/`@Query`/`@Body`), and\n * any `@nestjs/swagger` (`@ApiOperation`/`@ApiParam`/`@ApiProperty`) or\n * `class-validator` metadata it carries.\n */\nexport interface McpMetadata {\n /**\n * MCP tool name override. When unset it is derived from the controller class\n * and method name (e.g. `ChannelsController.findOne` → `ChannelsFindOne`).\n */\n name?: string\n /**\n * Tool description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts either a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` - the object's `.shape` is unwrapped. The escape hatch\n * for shapes reflection can't express losslessly - discriminated unions,\n * custom validators, `@Transform`, etc. Note it *adds to* the reflected\n * fields; it does not replace them, so a field reflection silently dropped\n * (see the unreflectable-param warning) is not recovered by listing the\n * others here.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Whether to apply the controller method's parameter-bound pipes\n * (`@Param('id', ParseIntPipe)`) when re-binding the call. Default `'apply'`.\n * Global/`ValidationPipe`, interceptors, and exception filters never run -\n * the method is invoked directly, not through Nest's HTTP request pipeline.\n */\n pipes?: 'apply' | 'skip'\n /**\n * MCP result format for this tool. `'json'` (the default when unset) returns\n * compact JSON text (`jsonToolResult`); `'smart'` inlines small payloads and\n * offloads large ones to an embedded resource (`smartToolResult`);\n * `'structured'` declares the tool's output schema as an MCP `outputSchema`\n * contract and ships schema-parsed `structuredContent`. `'json'`/`'smart'`\n * are defaults a client's `_meta.disposition` overrides; `'structured'`\n * ignores `_meta.disposition` and **requires an explicit output schema** -\n * `@Mcp({ output })` or `@Trpc({ output })` on the same method (a reflected\n * `@ApiOkResponse` is not accepted as a structured contract; reflection is\n * one level deep and must not silently become a hard, call-failing schema).\n */\n result?: 'json' | 'smart' | 'structured'\n /**\n * Explicit output schema backing `result: 'structured'` - a Zod type, a DTO\n * class (flattened one level like `@ApiOkResponse` reflection), or a raw\n * shape (wrapped in `z.object`). Wins over `@Trpc({ output })` when both are\n * set. The parsed (extra-fields-stripped) result ships as\n * `structuredContent`, so returning a wider object than the schema is safe.\n */\n output?: z.ZodType | Type | Record<string, z.ZodType>\n /**\n * MCP tool annotations (read-only/destructive/idempotent hints) merged over\n * the verb-derived defaults: `@Get` ⇒ `{ readOnlyHint: true, idempotentHint:\n * true }`, `@Put` ⇒ `{ idempotentHint: true }`, `@Delete` ⇒\n * `{ destructiveHint: true, idempotentHint: true }`, anything else ⇒\n * `{ readOnlyHint: false }`. Set a field here to override its derived value\n * (e.g. `{ destructiveHint: true }` on a POST that deletes).\n */\n annotations?: ToolAnnotations\n /**\n * Free-form grouping labels carried on the synthesized action (e.g.\n * `['leads', 'write']`) for the `mcp({ filterActions })` per-request filter\n * (or any other consumer) to match on. No behavior on their own.\n */\n tags?: string[]\n}\n\n/** tRPC procedure kind for a `@Trpc`-decorated route. */\nexport type TrpcKind = 'query' | 'mutation' | 'subscription'\n\n/**\n * Options for the `@Trpc()` method decorator - the tRPC sibling of `@Mcp`. An\n * empty `@Trpc()` exposes the decorated controller route as a tRPC procedure\n * with its key, input schema, and kind reflected from the route + parameter\n * decorators + swagger/class-validator metadata (identically to `@Mcp`).\n *\n * Unlike MCP, tRPC carries precise *output* types into the generated router, so\n * `@Trpc` adds an `output`/`chunk` hatch and a `kind` override on top of the\n * shared reflection. The two decorators compose on the same method.\n */\nexport interface TrpcMetadata {\n /**\n * Procedure-name override (before camelCasing). When unset it is derived from\n * the controller class + method name (e.g. `UsersController.listBySpace` →\n * `Users.listBySpace`, camelCased by the router to `usersListBySpace`).\n */\n name?: string\n /**\n * Procedure description override. When unset it falls back to the method's\n * `@ApiOperation({ summary | description })`, then a generated default.\n */\n description?: string\n /**\n * Zod override merged over the reflected input fields (override wins per\n * field). Accepts a raw shape (`{ field: z.string() }`) or a whole\n * `z.object({ ... })` (its `.shape` is unwrapped). Same escape hatch as\n * `@Mcp({ input })`.\n */\n input?: Record<string, z.ZodType> | z.ZodObject\n /**\n * Explicit output schema driving the generated procedure's output type - a Zod\n * type, a DTO class (reflected like `@ApiOkResponse`), or a raw shape (wrapped\n * in `z.object`). Wins over `@ApiOkResponse` reflection. The biggest reason to\n * set this is when the return shape can't be reflected losslessly from a DTO.\n */\n output?: z.ZodType | Type | Record<string, z.ZodType>\n /**\n * Chunk schema for an async-generator route exposed as a tRPC **subscription**.\n * A Zod type or a DTO class. Drives the emitted\n * `TRPCSubscriptionProcedure<{ output }>` type. When unset the chunk type falls\n * back to `unknown`.\n */\n chunk?: z.ZodType | Type\n /**\n * Procedure kind. When unset it is inferred: an `async *` route ⇒\n * `'subscription'`, a `@Get` route ⇒ `'query'`, anything else ⇒ `'mutation'`.\n * Set this to expose a verb-less route (no `@Get`/`@Post`) as a query or\n * subscription - `@Trpc({ kind })` works without an HTTP-verb decorator, so the\n * route is served over tRPC (and/or MCP) without becoming a public REST route.\n */\n kind?: TrpcKind\n /**\n * Whether to apply the method's parameter-bound pipes when re-binding the call.\n * Default `'apply'`. Same semantics as `@Mcp({ pipes })`.\n */\n pipes?: 'apply' | 'skip'\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { MCP_METADATA, type McpMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes an existing NestJS controller route as an MCP\n * tool. It is **additive** - the route keeps serving HTTP exactly as before;\n * `@Mcp()` just opts the method into MCP discovery.\n *\n * The tool's name, description, and input schema are reflected from the\n * method's own metadata:\n * - **fields** from the parameter decorators (`@Param`/`@Query`/`@Body`) - a\n * `@Param('id')` becomes an `id` field; a whole-DTO `@Body() dto: CreateDto`\n * is flattened to its properties,\n * - **types/constraints/descriptions** from `@nestjs/swagger`\n * (`@ApiParam`/`@ApiQuery`/`@ApiProperty`/`@ApiOperation`) and, when present,\n * `class-validator` decorators on the DTOs,\n * - optionally refined by an OpenAPI document passed to `SilkweaveModule`.\n *\n * On a tool call the input is split back into the method's positional arguments\n * and the method is invoked directly (with `@UseGuards` guards applied first).\n *\n * @example\n * ```ts\n * @Controller('sessions/:sessionId/channels')\n * export class ChannelsController {\n * @Get(':channelId')\n * @ApiOperation({ summary: 'Get a specific channel by ID' })\n * @ApiParam({ name: 'sessionId', description: 'Session ID' })\n * @ApiParam({ name: 'channelId', description: 'Channel ID' })\n * @Mcp()\n * findOne(@Param('sessionId') sessionId: string, @Param('channelId') channelId: string) {\n * return this.service.get(sessionId, channelId)\n * }\n * }\n * ```\n */\nexport function Mcp(options: McpMetadata = {}): MethodDecorator {\n return SetMetadata(MCP_METADATA, options)\n}\n","import { SetMetadata } from '@nestjs/common'\nimport { TRPC_METADATA, type TrpcMetadata } from '../lib/metadata.js'\n\n/**\n * Method decorator that exposes a NestJS controller route as a **tRPC\n * procedure** - the sibling of `@Mcp`. Like `@Mcp` it is additive and reflects\n * the procedure's input from the method's own metadata (route + `@Param`/\n * `@Query`/`@Body` + swagger/class-validator), so a single method can carry both\n * `@Trpc()` and `@Mcp()` and `@UseGuards()`.\n *\n * Two things differ from MCP because tRPC consumers need them:\n * - **kind** - inferred from the route (`@Get` ⇒ query, others ⇒ mutation) or an\n * `async *` body (⇒ subscription); override with `@Trpc({ kind })`.\n * - **output** - the generated `AppRouter` carries precise output types. Drive\n * them with `@ApiOkResponse({ type: Dto })` reflection or `@Trpc({ output })`.\n *\n * `@Trpc()` works **without** an HTTP-verb decorator: with no `@Get`/`@Post` the\n * route is never mapped as REST, so `@Trpc({ kind })` exposes it over tRPC (and\n * `@Mcp` over MCP) while keeping it off the public REST surface.\n *\n * @example\n * ```ts\n * @Controller('users')\n * export class UsersController {\n * @Get('list-by-space')\n * @ApiOperation({ summary: 'List users in a space' })\n * @ApiOkResponse({ type: ListUsersResponse }) // drives the output type\n * @UseGuards(AuthGuard)\n * @Trpc() // → procedure `usersListBySpace` (query)\n * @Mcp() // → MCP tool `UsersListBySpace`\n * listBySpace(@Query() q: ListBySpaceQuery, @Req() req: AppRequest) {\n * return this.service.list(req.user, q.spaceId)\n * }\n * }\n * ```\n */\nexport function Trpc(options: TrpcMetadata = {}): MethodDecorator {\n return SetMetadata(TRPC_METADATA, options)\n}\n","import type { ArgumentsHost, ContextType, ExecutionContext, Type } from '@nestjs/common'\n\n/** Subset of `HttpArgumentsHost` we need - re-declared inline to avoid deep `@nestjs/common/interfaces` imports. */\ninterface HttpHost {\n getRequest<T = unknown>(): T\n getResponse<T = unknown>(): T\n getNext<T = unknown>(): T\n}\n\ninterface RpcHost {\n getData<T = unknown>(): T\n getContext<T = unknown>(): T\n}\n\ninterface WsHost {\n getClient<T = unknown>(): T\n getData<T = unknown>(): T\n getPattern(): string\n}\n\n/**\n * Minimal `ExecutionContext` impl Nest guards can consume. We only need\n * `switchToHttp()` to work for our HTTP-backed transports; the RPC/WS shims are\n * stubbed so guards that introspect type can still call them without crashing.\n */\nexport class SilkweaveExecutionContext implements ExecutionContext, ArgumentsHost {\n constructor(\n private readonly args: unknown[],\n private readonly classRef: Type<unknown>,\n private readonly handler: (...handlerArgs: unknown[]) => unknown,\n private readonly contextType = 'http'\n ) { }\n\n getType<T extends string = ContextType>(): T {\n return this.contextType as T\n }\n\n getClass<T = unknown>(): Type<T> {\n return this.classRef as Type<T>\n }\n\n getHandler(): (...handlerArgs: unknown[]) => unknown {\n return this.handler\n }\n\n getArgs<T extends unknown[] = unknown[]>(): T {\n return this.args as T\n }\n\n getArgByIndex<T = unknown>(index: number): T {\n return this.args[index] as T\n }\n\n switchToHttp(): HttpHost {\n return {\n getRequest: <T = unknown>(): T => this.args[0] as T,\n getResponse: <T = unknown>(): T => this.args[1] as T,\n getNext: <T = unknown>(): T => this.args[2] as T\n }\n }\n\n switchToRpc(): RpcHost {\n return {\n getData: <T = unknown>(): T => this.args[0] as T,\n getContext: <T = unknown>(): T => this.args[1] as T\n }\n }\n\n switchToWs(): WsHost {\n return {\n getClient: <T = unknown>(): T => this.args[0] as T,\n getData: <T = unknown>(): T => this.args[1] as T,\n getPattern: (): string => ''\n }\n }\n}\n","import { ForbiddenException, type CanActivate, type Type } from '@nestjs/common'\nimport { GUARDS_METADATA } from '@nestjs/common/constants.js'\nimport { ApplicationConfig, ModuleRef, Reflector } from '@nestjs/core'\nimport { isObservable, lastValueFrom } from 'rxjs'\nimport { SilkweaveExecutionContext } from './executionContext.js'\n\ntype GuardRef = Type<CanActivate> | CanActivate\n\n/**\n * Collect the app's global guards that match an opt-in allow-list of classes.\n *\n * Reads both registration styles Nest exposes via `ApplicationConfig`:\n * `useGlobalGuards(new X())` instances (`getGlobalGuards()`) and\n * `{ provide: APP_GUARD, useClass }` DI guards (`getGlobalRequestGuards()`,\n * which yields `InstanceWrapper`s - we read `.instance` off each).\n *\n * The allow-list is intentionally explicit-by-class: a blanket \"run every\n * global\" would also fire unrelated globals (e.g. a `ThrottlerGuard` that\n * assumes a writable response) on every tool call. An empty allow-list runs\n * no globals, preserving the prior behavior.\n *\n * Call this at tool-call time, not at discovery time: `APP_GUARD` instances\n * aren't populated until `app.init()` finishes.\n */\nexport function collectGlobalGuards(\n appConfig: ApplicationConfig,\n allowList: Type<CanActivate>[]\n): CanActivate[] {\n if (allowList.length === 0) { return [] }\n const globals: CanActivate[] = [\n ...appConfig.getGlobalGuards(),\n ...appConfig.getGlobalRequestGuards().map((w) => w.instance)\n ].filter((g): g is CanActivate => g != null)\n return globals.filter((g) => allowList.some((c) => g instanceof c))\n}\n\n/**\n * Read `@UseGuards(...)` metadata for both the method and its class and merge\n * the two lists. Method-level guards run AFTER class-level guards (matching\n * Nest's own behavior).\n */\nexport function collectGuards(\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown\n): GuardRef[] {\n const classGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, classRef) ?? []\n const methodGuards = reflector.get<GuardRef[]>(GUARDS_METADATA, handler) ?? []\n return [...classGuards, ...methodGuards]\n}\n\nasync function resolveGuard(ref: GuardRef, moduleRef: ModuleRef): Promise<CanActivate> {\n if (typeof ref === 'function') {\n try {\n return await moduleRef.get(ref, { strict: false })\n } catch {\n return moduleRef.create(ref)\n }\n }\n return ref\n}\n\n/**\n * Run the configured guards against a request. Throws `ForbiddenException`\n * if any guard rejects, mirroring Nest's HTTP request-pipeline behavior.\n *\n * Pass `null` for `response` when running on top of a tRPC or MCP request that\n * doesn't surface a raw response object; guards that introspect the response\n * will receive `null`.\n *\n * `contextType` is reflected through `ExecutionContext.getType()` so guards can\n * branch on the transport. It is `'http'` for REST/tRPC and for MCP-over-HTTP\n * (where a header-bearing request stand-in is available); transports without any\n * HTTP request (e.g. MCP stdio) pass `'rpc'`.\n */\nexport async function runGuards(\n guards: GuardRef[],\n moduleRef: ModuleRef,\n reflector: Reflector,\n classRef: Type<unknown>,\n handler: (...args: unknown[]) => unknown,\n request: unknown,\n response: unknown,\n contextType: 'http' | 'rpc' = 'http'\n): Promise<void> {\n if (guards.length === 0) { return }\n const context = new SilkweaveExecutionContext([request, response], classRef, handler, contextType)\n for (const ref of guards) {\n const guard = await resolveGuard(ref, moduleRef)\n const result = guard.canActivate(context)\n const allowed = isObservable(result) ? await lastValueFrom(result) : await Promise.resolve(result)\n if (!allowed) {\n throw new ForbiddenException('Forbidden resource')\n }\n }\n // Reflector kept in the signature for future use (e.g., per-guard metadata) - unused here.\n void reflector\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { ROUTE_ARGS_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RouteParamtypes` numeric values from `@nestjs/common` (re-declared to avoid a\n * value import of an internal enum). These are how `@Param`/`@Query`/`@Body`/...\n * tag each handler argument in `ROUTE_ARGS_METADATA`.\n */\nexport const PARAMTYPE = {\n REQUEST: 0,\n RESPONSE: 1,\n NEXT: 2,\n BODY: 3,\n QUERY: 4,\n PARAM: 5,\n HEADERS: 6,\n SESSION: 7,\n FILE: 8,\n FILES: 9,\n HOST: 10,\n IP: 11,\n RAW_BODY: 12\n} as const\n\nexport interface ParamSlot {\n /** `PARAMTYPE` value - which decorator tagged this argument. */\n paramtype: number\n /** Handler argument position. */\n index: number\n /** Decorator sub-key: `@Param('id')` → `'id'`; a bare `@Body()` → `undefined`. */\n data?: string\n /** Parameter-bound pipes (`@Param('id', ParseIntPipe)`). */\n pipes: unknown[]\n /** TypeScript-emitted constructor at this position (e.g. `String`, `CreateDto`). */\n designType?: unknown\n}\n\n/**\n * Read and normalise the route-argument metadata for a controller method.\n * Returns one {@link ParamSlot} per decorated handler argument, sorted by\n * argument index.\n */\nexport function readParamSlots(classRef: any, methodName: string, proto: any): ParamSlot[] {\n const raw = Reflect.getMetadata(ROUTE_ARGS_METADATA, classRef, methodName) as\n Record<string, { index: number; data?: unknown; pipes?: unknown[] }> | undefined\n if (!raw) { return [] }\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n\n const slots: ParamSlot[] = []\n for (const key of Object.keys(raw)) {\n const entry = raw[key]\n const paramtype = Number(key.split(':')[0])\n if (Number.isNaN(paramtype)) { continue }\n slots.push({\n paramtype,\n index: entry.index,\n data: typeof entry.data === 'string' ? entry.data : undefined,\n pipes: entry.pipes ?? [],\n designType: designTypes[entry.index]\n })\n }\n return slots.sort((a, b) => a.index - b.index)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { PARAMTYPE } from './reflect/params.js'\n\n/**\n * Instruction for reconstructing one positional handler argument from the flat\n * MCP tool input. Built at discovery time, consumed by {@link invokeRebound}.\n */\nexport type Binding =\n | { kind: 'value'; field: string; source: 'path' | 'query' | 'body'; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'object'; source: 'query' | 'body'; fields: string[]; metatype?: unknown; pipes?: unknown[] }\n | { kind: 'params'; fields: string[] }\n | { kind: 'request' }\n | { kind: 'response' }\n | { kind: 'headers'; data?: string }\n | { kind: 'ip' }\n | { kind: 'host'; data?: string }\n | { kind: 'missing' }\n\ninterface RequestLike {\n headers?: Record<string, unknown>\n ip?: unknown\n hosts?: Record<string, unknown>\n}\n\nfunction newInstance(P: any): any | null {\n try { return new P() } catch { return null }\n}\n\nasync function applyPipes(value: unknown, pipes: unknown[] | undefined, metatype: unknown, type: 'param' | 'query' | 'body', data: string | undefined): Promise<unknown> {\n if (!pipes || pipes.length === 0) { return value }\n let current = value\n for (const p of pipes) {\n const pipe = typeof p === 'function' ? newInstance(p) : p\n if (pipe && typeof (pipe).transform === 'function') {\n current = await (pipe).transform(current, { type, metatype, data })\n }\n }\n return current\n}\n\n/** Pick a subset of keys (skipping `undefined`) into a fresh object. */\nfunction pickFields(input: Record<string, unknown>, fields: string[]): Record<string, unknown> {\n const obj: Record<string, unknown> = {}\n for (const f of fields) {\n if (input[f] !== undefined) { obj[f] = input[f] }\n }\n return obj\n}\n\n/** Resolve a single positional argument from one binding. */\nasync function resolveArg(\n b: Binding,\n input: Record<string, unknown>,\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n switch (b.kind) {\n case 'value': {\n const raw = input[b.field]\n const type = b.source === 'path' ? 'param' : b.source\n return applyParamPipes ? applyPipes(raw, b.pipes, b.metatype, type, b.field) : raw\n }\n case 'object': {\n const obj = pickFields(input, b.fields)\n return applyParamPipes ? applyPipes(obj, b.pipes, b.metatype, b.source, undefined) : obj\n }\n case 'params':\n return pickFields(input, b.fields)\n case 'headers':\n return b.data ? request?.headers?.[b.data.toLowerCase()] : (request?.headers ?? {})\n case 'request':\n return request ?? { headers: {} }\n case 'response':\n // The real Express response over tRPC (so `@Res({ passthrough: true })`\n // can set cookies/headers); `undefined` over MCP (no HTTP response).\n return response\n case 'ip':\n return request?.ip\n case 'host':\n return b.data ? request?.hosts?.[b.data] : request?.hosts\n default:\n return undefined\n }\n}\n\n/**\n * Reconstruct the controller method's positional arguments from the validated\n * tool `input` (and the request stand-in for `@Req`/`@Headers`/...), then call\n * it. `applyParamPipes` controls whether parameter-bound pipes run.\n */\nexport async function invokeRebound(\n method: (...args: any[]) => any,\n instance: object,\n input: Record<string, unknown>,\n bindings: Binding[],\n request: RequestLike | undefined,\n response: unknown,\n applyParamPipes: boolean\n): Promise<unknown> {\n const args: unknown[] = []\n for (let i = 0; i < bindings.length; i += 1) {\n args[i] = await resolveArg(bindings[i], input, request, response, applyParamPipes)\n }\n return await method.apply(instance, args)\n}\n\n/** Map a non-input parameter slot (`@Req`/`@Headers`/`@Ip`/...) to its runtime binding. */\nexport function specialBinding(paramtype: number, data: string | undefined): Binding | null {\n switch (paramtype) {\n case PARAMTYPE.REQUEST: return { kind: 'request' }\n case PARAMTYPE.RESPONSE:\n case PARAMTYPE.NEXT: return { kind: 'response' }\n case PARAMTYPE.HEADERS: return { kind: 'headers', data }\n case PARAMTYPE.IP: return { kind: 'ip' }\n case PARAMTYPE.HOST: return { kind: 'host', data }\n case PARAMTYPE.SESSION:\n case PARAMTYPE.FILE:\n case PARAMTYPE.FILES:\n case PARAMTYPE.RAW_BODY: return { kind: 'missing' }\n default: return null\n }\n}\n","import type { Binding } from './rebind.js'\n\n/**\n * Request-slot reconstruction: route the validated tool input back into the\n * `request.params`/`query`/`body` slots Express would populate over REST, so a\n * host guard reading any of them decides identically over MCP and REST. Kept in\n * its own module (not re-exported from the package root) so these helpers stay\n * internal while remaining unit-testable.\n */\n\n/** Input field names grouped by the REST request slot Express would source them from. */\nexport interface RequestSlots {\n /** `@Param`/path-template fields -> `request.params` (raw strings). */\n params: string[]\n /** `@Query` fields -> `request.query` (raw strings). */\n query: string[]\n /** `@Body` fields -> `request.body` (parsed values). */\n body: string[]\n}\n\n/**\n * Classify every input field by the REST request slot it would occupy, reading\n * the discovery-time {@link Binding}s. A whole-DTO `@Query()`/`@Body()` (`object`\n * binding) contributes all its fields to the matching slot; a bare `@Param()`\n * (`params` binding) and a path-sourced `value` go to `params`.\n */\nexport function requestSlotFields(bindings: Binding[]): RequestSlots {\n const slots: RequestSlots = { params: [], query: [], body: [] }\n for (const b of bindings) {\n if (b.kind === 'params') { slots.params.push(...b.fields) } else if (b.kind === 'object') { slots[b.source].push(...b.fields) } else if (b.kind === 'value') { slots[b.source === 'path' ? 'params' : b.source].push(b.field) }\n }\n return slots\n}\n\n/** Fill one request slot from the validated input, only adding absent keys. */\nfunction fillSlot(bag: Record<string, unknown>, fields: string[], input: Record<string, unknown>, stringify: boolean): void {\n for (const field of fields) {\n if (!(field in bag) && input[field] !== undefined) {\n bag[field] = stringify ? String(input[field]) : input[field]\n }\n }\n}\n\n/**\n * Fill `request.params`/`query`/`body` from the validated input, mirroring the\n * slots Express would populate over REST (path -> `params`, `@Query` -> `query`,\n * `@Body` -> `body`). Path/query values are stringified to match how Express\n * delivers them (a guard reading `req.query.limit` sees `'10'`, not `10`); body\n * keeps the parsed values. Only absent keys are added, so a real REST/tRPC\n * request's own params/query/body are never overwritten. This is what lets a\n * scope-enforcing guard (`req.params.sessionId`, `req.body.sessionId`, ...)\n * decide identically over MCP and REST.\n */\nexport function populateRequestSlots(request: unknown, slots: RequestSlots, input: Record<string, unknown>): void {\n if (typeof request !== 'object' || request === null) { return }\n const req = request as { params?: Record<string, unknown>; query?: Record<string, unknown>; body?: Record<string, unknown> }\n if (slots.params.length > 0) { fillSlot((req.params ??= {}), slots.params, input, true) }\n if (slots.query.length > 0) { fillSlot((req.query ??= {}), slots.query, input, true) }\n if (slots.body.length > 0) { fillSlot((req.body ??= {}), slots.body, input, false) }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { createRequire } from 'node:module'\nimport { join } from 'node:path'\n\nlet cached: any | null | undefined\n\n/**\n * Lazily resolve the optional `class-validator` peer; `null` when not installed.\n * Resolution is attempted both from this package and from the app's working\n * directory - the latter is what finds it in a pnpm install where the optional\n * peer lives in the consumer app rather than alongside `@silkweave/nestjs`. A\n * pnpm-deduped install shares one physical copy, so the metadata singleton the\n * app's decorators wrote to is the same one we read.\n */\nfunction loadClassValidator(): any | null {\n if (cached !== undefined) { return cached }\n for (const base of [import.meta.url, join(process.cwd(), 'noop.js')]) {\n try {\n cached = createRequire(base)('class-validator')\n return cached\n } catch { /* try the next resolution base */ }\n }\n cached = null\n return cached\n}\n\nexport interface ValidationMeta {\n /** `ValidationTypes` discriminator (e.g. `customValidation`, `conditionalValidation`). */\n type?: string\n /** Validator name - the actionable identity for built-ins (`isString`, `minLength`, ...). */\n name?: string\n constraints?: unknown[]\n}\n\n/**\n * Read `class-validator` metadata for a DTO class, grouped by property name.\n * Returns an empty map when `class-validator` is not installed or the class\n * carries no validation decorators - so callers degrade gracefully to swagger /\n * `design:type` reflection.\n */\nexport function classValidatorMetas(dtoType: any): Record<string, ValidationMeta[]> {\n const cv = loadClassValidator()\n if (!cv?.getMetadataStorage) { return {} }\n let metas: Array<{ propertyName?: string; type?: string; name?: string; constraints?: unknown[] }>\n try {\n metas = cv.getMetadataStorage().getTargetValidationMetadatas(dtoType, null, false, false)\n } catch {\n return {}\n }\n const out: Record<string, ValidationMeta[]> = {}\n for (const m of metas) {\n if (!m.propertyName) { continue }\n (out[m.propertyName] ??= []).push({ type: m.type, name: m.name, constraints: m.constraints })\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { classValidatorMetas } from './classValidator.js'\n\n/** `@nestjs/swagger` reflect-metadata keys. Read directly so swagger stays an optional peer. */\nconst API_MODEL_PROPERTIES = 'swagger/apiModelProperties'\nconst API_MODEL_PROPERTIES_ARRAY = 'swagger/apiModelPropertiesArray'\n\n/**\n * A transport-neutral description of a single input field. Every metadata\n * source (swagger decorators, class-validator, an OpenAPI document, TypeScript\n * `design:type`) is mapped to this shape, the shapes are merged by precedence,\n * and the result is converted to Zod once. Keeping a single intermediate keeps\n * the per-source mappers small and the Zod construction in one place.\n */\nexport interface FieldDesc {\n type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'unknown'\n required?: boolean\n /** Field accepts `null` (`@ApiProperty({ nullable: true })` / OpenAPI `nullable`). */\n nullable?: boolean\n description?: string\n enum?: (string | number)[]\n items?: FieldDesc\n min?: number\n max?: number\n minLength?: number\n maxLength?: number\n format?: string\n default?: unknown\n}\n\n/** Strip `undefined` values so a later source never clobbers an earlier one with a hole. */\nfunction defined<T extends object>(obj: T): Partial<T> {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) { out[k] = v }\n }\n return out as Partial<T>\n}\n\n/** Merge `over` onto `base` - defined keys of `over` win. */\nexport function mergeField(base: FieldDesc, over: FieldDesc): FieldDesc {\n return { ...base, ...defined(over) }\n}\n\nfunction enumToZod(values: (string | number)[]): z.ZodType {\n const strings = values.filter((v): v is string => typeof v === 'string')\n if (strings.length === values.length && strings.length > 0) {\n return z.enum(strings as [string, ...string[]])\n }\n const literals = values.map((v) => z.literal(v))\n if (literals.length === 0) { return z.unknown() }\n if (literals.length === 1) { return literals[0] }\n return z.union(literals as unknown as [z.ZodType, z.ZodType, ...z.ZodType[]])\n}\n\nfunction baseToZod(d: FieldDesc): z.ZodType {\n switch (d.type) {\n case 'string': {\n let s = z.string()\n if (d.minLength != null) { s = s.min(d.minLength) }\n if (d.maxLength != null) { s = s.max(d.maxLength) }\n return s\n }\n case 'integer':\n case 'number': {\n let n = z.number()\n if (d.type === 'integer') { n = n.int() }\n if (d.min != null) { n = n.min(d.min) }\n if (d.max != null) { n = n.max(d.max) }\n return n\n }\n case 'boolean':\n return z.boolean()\n case 'array':\n return z.array(d.items ? fieldToZod({ ...d.items, required: true }) : z.unknown())\n case 'object':\n return z.record(z.string(), z.unknown())\n default:\n return z.unknown()\n }\n}\n\n/** Convert a merged {@link FieldDesc} to a Zod schema. */\nexport function fieldToZod(d: FieldDesc): z.ZodType {\n let schema = (d.enum?.length) ? enumToZod(d.enum) : baseToZod(d)\n if (d.description) { schema = schema.describe(d.description) }\n if (d.nullable) { schema = schema.nullable() }\n if (d.default !== undefined) {\n schema = (schema as any).default(d.default)\n } else if (d.required === false) {\n schema = schema.optional()\n }\n return schema\n}\n\n// --- per-source mappers ---------------------------------------------------\n\n/** Normalise a TS-enum object or an array literal to a flat value list. */\nexport function normalizeEnum(value: unknown): (string | number)[] | undefined {\n if (Array.isArray(value)) {\n return value.filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n if (value && typeof value === 'object') {\n return Object.values(value).filter((v): v is string | number => typeof v === 'string' || typeof v === 'number')\n }\n return undefined\n}\n\n/** Map a swagger/`design:type` type token (constructor, `[Type]`, or string) to a base type. */\nexport function typeTokenToBase(type: unknown): FieldDesc['type'] | undefined {\n if (type == null) { return undefined }\n if (type === String) { return 'string' }\n if (type === Number) { return 'number' }\n if (type === Boolean) { return 'boolean' }\n if (type === Array) { return 'array' }\n if (type === Date) { return 'string' }\n if (Array.isArray(type)) { return 'array' }\n if (typeof type === 'string') {\n const t = type.toLowerCase()\n if (t === 'string' || t === 'number' || t === 'integer' || t === 'boolean' || t === 'array' || t === 'object') {\n return t\n }\n }\n return undefined\n}\n\n/** From the constructor TypeScript emits via `emitDecoratorMetadata`. */\nexport function designTypeToField(ctor: unknown): FieldDesc {\n const type = typeTokenToBase(ctor)\n const f: FieldDesc = {}\n if (type) { f.type = type }\n return f\n}\n\n/** From an `@ApiParam`/`@ApiQuery` entry stored under `swagger/apiParameters`. */\nexport function swaggerParamToField(p: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (p['description']) { f.description = p['description'] }\n if (typeof p['required'] === 'boolean') { f.required = p['required'] }\n const type = typeTokenToBase(p['type'])\n if (type) { f.type = type }\n if (p['isArray']) { f.type = 'array' }\n const en = normalizeEnum(p['enum'])\n if (en) { f.enum = en }\n if (p['schema'] && typeof p['schema'] === 'object') {\n return mergeField(f, openapiSchemaToField(p['schema']))\n }\n return f\n}\n\n/** From an `@ApiProperty` options object stored under `swagger/apiModelProperties`. */\nexport function apiPropertyToField(o: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n if (o['description']) { f.description = o['description'] }\n if (typeof o['required'] === 'boolean') { f.required = o['required'] }\n const type = typeTokenToBase(o['type'])\n if (type) { f.type = type }\n if (o['isArray']) {\n f.items = { type: type && type !== 'array' ? type : 'unknown' }\n f.type = 'array'\n }\n const en = normalizeEnum(o['enum'])\n if (en) { f.enum = en }\n if (o['minimum'] != null) { f.min = o['minimum'] }\n if (o['maximum'] != null) { f.max = o['maximum'] }\n if (o['minLength'] != null) { f.minLength = o['minLength'] }\n if (o['maxLength'] != null) { f.maxLength = o['maxLength'] }\n if (o['format']) { f.format = o['format'] }\n if (o['nullable'] === true) { f.nullable = true }\n if (o['default'] !== undefined) { f.default = o['default'] }\n return f\n}\n\n/** `class-validator` decorator type → field base type. */\nconst CV_TYPE: Record<string, FieldDesc['type']> = {\n isString: 'string',\n isInt: 'integer',\n isBoolean: 'boolean',\n isArray: 'array'\n}\n\n/** `class-validator` decorator type → numeric-constraint field key. */\nconst CV_NUMERIC: Record<string, 'min' | 'max' | 'minLength' | 'maxLength'> = {\n min: 'min',\n max: 'max',\n minLength: 'minLength',\n maxLength: 'maxLength'\n}\n\n/**\n * Fold one `class-validator` metadata entry into the field descriptor. Built-in\n * validators record their identity in `name` (`isString`, `minLength`, ...) with\n * `type: 'customValidation'`; `@IsOptional` uses `name: 'isOptional'`. We key off\n * `name`, falling back to `type`.\n */\nfunction applyValidationMeta(f: FieldDesc, meta: { type?: string; name?: string; constraints?: unknown[] }): void {\n const key = meta.name ?? meta.type\n if (!key) { return }\n if (key in CV_TYPE) { f.type = CV_TYPE[key]; return }\n const c0 = meta.constraints?.[0]\n if (key in CV_NUMERIC) {\n if (typeof c0 === 'number') { f[CV_NUMERIC[key]] = c0 }\n return\n }\n if (key === 'isNumber') { if (!f.type) { f.type = 'number' } return }\n if (key === 'isEmail') { if (!f.type) { f.type = 'string' } f.format = 'email'; return }\n if (key === 'isDate' || key === 'isDateString') { f.type = 'string'; f.format = 'date-time'; return }\n if (key === 'isEnum') { const e = normalizeEnum(c0); if (e) { f.enum = e } return }\n if (key === 'isOptional') { f.required = false }\n}\n\n/** From an array of `class-validator` validation-metadata entries for one property. */\nexport function classValidatorToField(metas: Array<{ type?: string; name?: string; constraints?: unknown[] }>): FieldDesc {\n const f: FieldDesc = {}\n for (const meta of metas) { applyValidationMeta(f, meta) }\n return f\n}\n\n/** From an OpenAPI Schema Object (used by both the doc and `@ApiParam({ schema })`). */\nexport function openapiSchemaToField(schema: Record<string, any>): FieldDesc {\n const f: FieldDesc = {}\n const type = typeof schema['type'] === 'string' ? schema['type'].toLowerCase() : undefined\n if (type === 'string' || type === 'number' || type === 'integer' || type === 'boolean' || type === 'array' || type === 'object') {\n f.type = type\n }\n if (schema['description']) { f.description = schema['description'] }\n const en = normalizeEnum(schema['enum'])\n if (en) { f.enum = en }\n if (schema['minimum'] != null) { f.min = schema['minimum'] }\n if (schema['maximum'] != null) { f.max = schema['maximum'] }\n if (schema['minLength'] != null) { f.minLength = schema['minLength'] }\n if (schema['maxLength'] != null) { f.maxLength = schema['maxLength'] }\n if (schema['format']) { f.format = schema['format'] }\n if (schema['nullable'] === true) { f.nullable = true }\n if (schema['default'] !== undefined) { f.default = schema['default'] }\n if (schema['items'] && typeof schema['items'] === 'object') {\n f.items = openapiSchemaToField(schema['items'])\n }\n return f\n}\n\n/**\n * Reflect a whole-DTO class (`@Body() dto: CreateDto`) into per-property\n * {@link FieldDesc}s. Property names are the union of `@ApiProperty` and\n * `class-validator` decorated fields; each field merges `design:type` (base),\n * then `class-validator` constraints, then `@ApiProperty` (highest). Properties\n * default to required unless a source marks them optional.\n */\nexport function reflectDtoFields(dtoType: any): Record<string, FieldDesc> {\n const proto = dtoType?.prototype\n if (!proto) { return {} }\n const cvMetas = classValidatorMetas(dtoType)\n\n const names = new Set<string>()\n const swaggerArray = (Reflect.getMetadata(API_MODEL_PROPERTIES_ARRAY, proto) as string[] | undefined) ?? []\n for (const entry of swaggerArray) { names.add(entry.replace(/^:/, '')) }\n for (const name of Object.keys(cvMetas)) { names.add(name) }\n\n const out: Record<string, FieldDesc> = {}\n for (const name of names) {\n let f = designTypeToField(Reflect.getMetadata('design:type', proto, name))\n if (cvMetas[name]) { f = mergeField(f, classValidatorToField(cvMetas[name])) }\n const apiProp = Reflect.getMetadata(API_MODEL_PROPERTIES, proto, name) as Record<string, any> | undefined\n if (apiProp) {\n const fromApi = apiPropertyToField(apiProp)\n // `@ApiProperty` is required unless `required: false` is explicit.\n if (fromApi.required === undefined && apiProp['required'] === undefined) { fromApi.required = true }\n f = mergeField(f, fromApi)\n }\n if (f.required === undefined) { f.required = true }\n out[name] = f\n }\n return out\n}\n\n/**\n * Names of fields that could not be reflected into a concrete type - they will\n * become `z.unknown()` (or `z.array(z.unknown())`). This is how a nested DTO or a\n * `Dto[]` property silently degrades (reflection is one level deep), so the\n * adapters surface these as a build-time warning pointing at `@Trpc({ output })`\n * / `@Mcp({ input })`. Enum and `object` (record) fields are not degraded.\n */\nexport function unreflectedFields(fields: Record<string, FieldDesc>): string[] {\n const out: string[] = []\n for (const [name, f] of Object.entries(fields)) {\n if (f.enum?.length) { continue }\n if (!f.type || f.type === 'unknown') { out.push(name) } else if (f.type === 'array' && (!f.items?.type || f.items.type === 'unknown')) { out.push(name) }\n }\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */\nimport { type FieldDesc, mergeField, openapiSchemaToField } from './schema.js'\n\n/**\n * A minimal view of an OpenAPI document - the subset we read. Matches the shape\n * `SwaggerModule.createDocument()` returns, but typed loosely so callers can\n * pass any compatible object without a hard `@nestjs/swagger` dependency.\n */\nexport interface OpenApiDocument {\n paths?: Record<string, Record<string, any>>\n components?: { schemas?: Record<string, any> }\n}\n\nexport interface OpenApiLookup {\n doc: OpenApiDocument\n /** `${METHOD} ${path}` → operation object. */\n operations: Map<string, any>\n}\n\n/** Index a document's operations by `${METHOD} ${path}` for fast matching. */\nexport function buildOpenApiLookup(doc: OpenApiDocument): OpenApiLookup {\n const operations = new Map<string, any>()\n for (const [path, item] of Object.entries(doc.paths ?? {})) {\n for (const [verb, op] of Object.entries(item ?? {})) {\n operations.set(`${verb.toUpperCase()} ${path}`, op)\n }\n }\n return { doc, operations }\n}\n\n/** Locate the operation for a route, tolerating a global path prefix on the document side. */\nfunction findOperation(lookup: OpenApiLookup, method: string, openapiPath: string): any | undefined {\n const exact = lookup.operations.get(`${method} ${openapiPath}`)\n if (exact) { return exact }\n // Fall back to a suffix match so a `setGlobalPrefix('api')` document still resolves.\n for (const [key, op] of lookup.operations) {\n const [verb, path] = key.split(' ')\n if (verb === method && (path.endsWith(openapiPath) || openapiPath.endsWith(path))) { return op }\n }\n return undefined\n}\n\nfunction resolveRef(doc: OpenApiDocument, schema: any): any {\n let current = schema\n let guard = 0\n while (current && typeof current === 'object' && typeof current['$ref'] === 'string' && guard < 10) {\n const match = /^#\\/components\\/schemas\\/(.+)$/.exec(current['$ref'])\n if (!match) { break }\n current = doc.components?.schemas?.[match[1]]\n guard += 1\n }\n return current\n}\n\n/**\n * Resolve the per-field descriptors for a route from an ingested OpenAPI\n * document. Merges `parameters` (path/query/header) and the JSON request-body\n * schema's properties into a single field map. Returns `{}` when the operation\n * isn't found - callers fall back to decorator reflection.\n */\nexport function openApiFields(lookup: OpenApiLookup, method: string, openapiPath: string): Record<string, FieldDesc> {\n const op = findOperation(lookup, method, openapiPath)\n if (!op) { return {} }\n const out: Record<string, FieldDesc> = {}\n\n for (const param of (op['parameters'] as Array<Record<string, any>> | undefined) ?? []) {\n const name = typeof param['name'] === 'string' ? param['name'] : undefined\n if (!name) { continue }\n const schema = param['schema'] ? resolveRef(lookup.doc, param['schema']) : undefined\n let field = schema ? openapiSchemaToField(schema) : {}\n if (param['description']) { field = mergeField(field, { description: param['description'] }) }\n if (typeof param['required'] === 'boolean') { field = mergeField(field, { required: param['required'] }) }\n out[name] = field\n }\n\n const bodySchema = resolveRef(lookup.doc, op['requestBody']?.['content']?.['application/json']?.['schema'])\n if (bodySchema && typeof bodySchema === 'object' && bodySchema['properties']) {\n const required = new Set<string>(Array.isArray(bodySchema['required']) ? bodySchema['required'] : [])\n for (const [name, propSchema] of Object.entries(bodySchema['properties'] as Record<string, any>)) {\n const field = openapiSchemaToField(resolveRef(lookup.doc, propSchema))\n field.required = required.has(name)\n out[name] = field\n }\n }\n\n return out\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { z } from 'zod/v4'\nimport { type FieldDesc, fieldToZod, reflectDtoFields } from './schema.js'\n\n/** `@nestjs/swagger` response metadata key (read directly - swagger is an optional peer). */\nconst API_RESPONSE = 'swagger/apiResponse'\n\n/** Status keys we treat as the \"success\" response, in preference order. */\nconst SUCCESS_KEYS = ['200', '201', '202', '204', '2XX', 'default']\n\n/** The 2xx (or first) `@ApiResponse` entry for a method, if any. */\nfunction successEntry(method: (...args: any[]) => any): { type?: unknown; isArray?: boolean } | undefined {\n const responses = Reflect.getMetadata(API_RESPONSE, method) as Record<string, { type?: unknown; isArray?: boolean }> | undefined\n if (!responses) { return undefined }\n const key = SUCCESS_KEYS.find((k) => responses[k]) ?? Object.keys(responses)[0]\n return key ? responses[key] : undefined\n}\n\n/**\n * Reflect a `@Trpc` procedure's output schema from the method's\n * `@ApiOkResponse({ type: Dto })` (or any 2xx `@ApiResponse`) metadata. The\n * response DTO is flattened with {@link reflectDtoFields} into a Zod object,\n * wrapped in `z.array(...)` when the response is `isArray`.\n *\n * Returns `undefined` when there is no response DTO to reflect (e.g. a primitive\n * return type or no `@ApiResponse` decorator) - the caller then falls back to an\n * explicit `@Trpc({ output })` or an `unknown` output type.\n */\nexport function reflectResponseSchema(method: (...args: any[]) => any): z.ZodType | undefined {\n const entry = successEntry(method)\n const dtoType = entry?.type\n if (typeof dtoType !== 'function') { return undefined }\n\n const schema = reflectDtoSchema(dtoType)\n if (!schema) { return undefined }\n return entry?.isArray ? z.array(schema) : schema\n}\n\n/**\n * The reflected `FieldDesc` map for a method's response DTO (the same fields\n * {@link reflectResponseSchema} builds its schema from), or `undefined` when\n * there is no DTO to reflect. Used to detect fields that degraded to `unknown`\n * (nested DTO / `Dto[]`) so the caller can warn.\n */\nexport function reflectResponseFields(method: (...args: any[]) => any): Record<string, FieldDesc> | undefined {\n const dtoType = successEntry(method)?.type\n if (typeof dtoType !== 'function') { return undefined }\n return reflectDtoFields(dtoType)\n}\n\n/**\n * Reflect a DTO class (its `@ApiProperty`/`class-validator`-decorated properties)\n * into a Zod object schema. Returns `undefined` when the type isn't a class or\n * has no reflectable properties. Used for `@Trpc({ output })`/`@Trpc({ chunk })`\n * when given a DTO class instead of a Zod schema.\n */\nexport function reflectDtoSchema(dtoType: unknown): z.ZodType | undefined {\n if (typeof dtoType !== 'function') { return undefined }\n const fields = reflectDtoFields(dtoType)\n const names = Object.keys(fields)\n if (names.length === 0) { return undefined }\n const shape: Record<string, z.ZodType> = {}\n for (const name of names) { shape[name] = fieldToZod(fields[name]) }\n return z.object(shape)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { PATH_METADATA, METHOD_METADATA } from '@nestjs/common/constants.js'\n\n/**\n * `RequestMethod` numeric values (from `@nestjs/common`) mapped to verbs. We\n * map our own table rather than importing the enum to avoid pulling a value\n * import for a handful of constants.\n */\nconst REQUEST_METHOD: Record<number, string> = {\n 0: 'GET',\n 1: 'POST',\n 2: 'PUT',\n 3: 'DELETE',\n 4: 'PATCH',\n 6: 'OPTIONS',\n 7: 'HEAD'\n}\n\nexport interface RouteInfo {\n /** HTTP verb (`GET`/`POST`/...). `PATCH` and others outside the REST set fall back to `POST`-ish handling by callers. */\n method: string\n /** Full route template in Nest form, e.g. `sessions/:sessionId/channels/:channelId` (no leading slash). */\n path: string\n /** Full route template in OpenAPI form, e.g. `/sessions/{sessionId}/channels/{channelId}`. */\n openapiPath: string\n /** Names of the `:param` placeholders across controller + method path. */\n pathParams: string[]\n}\n\nfunction normalizeSegment(value: unknown): string {\n if (typeof value !== 'string') { return '' }\n return value.replace(/^\\/+/, '').replace(/\\/+$/, '')\n}\n\nfunction joinPath(...segments: string[]): string {\n return segments.map(normalizeSegment).filter(Boolean).join('/')\n}\n\n/**\n * Resolve the composed route (controller prefix + method path), HTTP verb, and\n * path-param names for a decorated controller method, reading Nest's own\n * `PATH_METADATA`/`METHOD_METADATA` reflection.\n */\nexport function reflectRoute(classRef: any, method: (...args: any[]) => any): RouteInfo {\n const classPath = Reflect.getMetadata(PATH_METADATA, classRef) as string | string[] | undefined\n const methodPath = Reflect.getMetadata(PATH_METADATA, method) as string | string[] | undefined\n const verbCode = Reflect.getMetadata(METHOD_METADATA, method) as number | undefined\n\n const classSeg = Array.isArray(classPath) ? (classPath[0] ?? '') : (classPath ?? '')\n const methodSeg = Array.isArray(methodPath) ? (methodPath[0] ?? '') : (methodPath ?? '')\n const path = joinPath(classSeg, methodSeg)\n const httpMethod = REQUEST_METHOD[verbCode ?? 0] ?? 'GET'\n\n const pathParams = [...path.matchAll(/:([A-Za-z0-9_]+)/g)].map((m) => m[1])\n const openapiPath = `/${path.replace(/:([A-Za-z0-9_]+)/g, '{$1}')}`\n\n return { method: httpMethod, path, openapiPath, pathParams }\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { FieldDesc } from './schema.js'\nimport { swaggerParamToField } from './schema.js'\n\n/** `@nestjs/swagger` reflect-metadata keys (read directly - swagger is an optional peer). */\nconst API_OPERATION = 'swagger/apiOperation'\nconst API_PARAMETERS = 'swagger/apiParameters'\n\nexport interface OperationMeta {\n /** Tool-description candidate from `@ApiOperation({ summary | description })`. */\n description?: string\n /** Per-name `FieldDesc` reflected from `@ApiParam`/`@ApiQuery` entries. */\n params: Record<string, FieldDesc>\n}\n\n/**\n * Read operation-level `@nestjs/swagger` metadata off a controller method:\n * `@ApiOperation` (summary/description) and the `@ApiParam`/`@ApiQuery` array\n * (each describing one path/query field). Returns empty data when swagger\n * decorators are absent.\n */\nexport function reflectOperation(method: (...args: any[]) => any): OperationMeta {\n const operation = Reflect.getMetadata(API_OPERATION, method) as Record<string, any> | undefined\n const description = operation\n ? (typeof operation['summary'] === 'string' && operation['summary']\n ? operation['summary']\n : (typeof operation['description'] === 'string' ? operation['description'] : undefined))\n : undefined\n\n const parameters = (Reflect.getMetadata(API_PARAMETERS, method) as Array<Record<string, any>> | undefined) ?? []\n const params: Record<string, FieldDesc> = {}\n for (const p of parameters) {\n const name = typeof p['name'] === 'string' ? p['name'] : undefined\n if (!name) { continue }\n params[name] = swaggerParamToField(p)\n }\n\n return { description, params }\n}\n","/* eslint-disable @typescript-eslint/no-unsafe-assignment */\nimport { HttpException, Injectable, Logger, type CanActivate, type Type } from '@nestjs/common'\nimport { ApplicationConfig, DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core'\nimport { emitToolCall, SilkweaveError, type Action, type ActionKind, type OnToolCall, type SilkweaveContext, type ToolAnnotations } from '@silkweave/core'\nimport { z } from 'zod/v4'\nimport { collectGlobalGuards, collectGuards, runGuards } from './guards.js'\nimport { MCP_METADATA, TRPC_METADATA, type McpMetadata, type TrpcMetadata } from './metadata.js'\nimport { invokeRebound, specialBinding, type Binding } from './rebind.js'\nimport { populateRequestSlots, requestSlotFields, type RequestSlots } from './requestSlots.js'\nimport { buildOpenApiLookup, openApiFields, type OpenApiDocument, type OpenApiLookup } from './reflect/openapi.js'\nimport { PARAMTYPE, type ParamSlot, readParamSlots } from './reflect/params.js'\nimport { reflectDtoSchema, reflectResponseFields, reflectResponseSchema } from './reflect/response.js'\nimport { reflectRoute, type RouteInfo } from './reflect/route.js'\nimport { type FieldDesc, fieldToZod, mergeField, reflectDtoFields, unreflectedFields } from './reflect/schema.js'\nimport { reflectOperation } from './reflect/swagger.js'\n\n/** Discovery-time diagnostics (unreflectable params, degraded outputs). */\nconst logger = new Logger('Silkweave')\n\ninterface Discovered {\n instance: object\n classRef: Type<unknown>\n method: (...args: unknown[]) => unknown\n methodName: string\n mcp?: McpMetadata\n trpc?: TrpcMetadata\n}\n\ninterface BuiltInput {\n shape: Record<string, z.ZodType>\n bindings: Binding[]\n /** Human-readable notes about params reflection could not turn into fields. */\n warnings: string[]\n}\n\n/** Shared reflection computed once per discovered method, reused across targets. */\ninterface Reflected {\n route: RouteInfo\n base: string\n description?: string\n baseShape: Record<string, z.ZodType>\n bindings: Binding[]\n guards: ReturnType<typeof collectGuards>\n requestSlots: RequestSlots\n streaming: boolean\n}\n\nexport interface DiscoverOptions {\n openapi?: OpenApiDocument\n globalGuards?: Type<CanActivate>[]\n defaultResult?: 'json' | 'smart'\n /**\n * Telemetry emitter for `@Trpc` procedure invocations (guard denials\n * included). MCP tool calls are NOT emitted here - the `mcp()` adapter\n * instruments the MCP registrar instead, where result metadata\n * (`resultBytes`/`sideloaded`) is known - so exactly one event fires per\n * call on either transport.\n */\n onToolCall?: OnToolCall\n}\n\n@Injectable()\nexport class ControllerDiscovery {\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly scanner: MetadataScanner,\n private readonly reflector: Reflector,\n private readonly moduleRef: ModuleRef,\n private readonly appConfig: ApplicationConfig\n ) { }\n\n /**\n * Walk every Nest provider/controller, find methods annotated with `@Mcp`\n * and/or `@Trpc`, and build a core `Action` per decorator present on each\n * method. The input schema is reflected from the route + parameter decorators\n * (+ optional OpenAPI document) and the `run` re-binds the validated input back\n * into the method's positional arguments (with `@UseGuards` guards applied\n * first). A method carrying both decorators yields two actions - one gated to\n * the `mcp` adapter, one to the `trpc`/`typegen` adapters - sharing the same\n * reflected input, bindings, and guards.\n */\n discover(options: DiscoverOptions = {}): Action[] {\n const lookup = options.openapi ? buildOpenApiLookup(options.openapi) : undefined\n const discovered: Discovered[] = []\n for (const wrapper of this.discovery.getProviders().concat(this.discovery.getControllers())) {\n const { instance } = wrapper\n if (!instance || typeof instance !== 'object') { continue }\n const proto = Object.getPrototypeOf(instance) as object | null\n if (!proto) { continue }\n const classRef = instance.constructor as Type<unknown>\n for (const methodName of this.scanner.getAllMethodNames(proto)) {\n const method = (proto as Record<string, unknown>)[methodName] as ((...args: unknown[]) => unknown) | undefined\n if (typeof method !== 'function') { continue }\n const mcp = this.reflector.get<McpMetadata>(MCP_METADATA, method)\n const trpc = this.reflector.get<TrpcMetadata>(TRPC_METADATA, method)\n if (!mcp && !trpc) { continue }\n discovered.push({ instance, classRef, method, methodName, mcp, trpc })\n }\n }\n\n const globalGuards = options.globalGuards ?? []\n const actions: Action[] = []\n for (const d of discovered) {\n const shared = this.reflect(d, lookup)\n if (d.mcp) { actions.push(this.mcpAction(d, shared, globalGuards, options.defaultResult)) }\n if (d.trpc) { actions.push(this.trpcAction(d, shared, globalGuards, options.onToolCall)) }\n }\n return actions\n }\n\n /** Compute the per-method reflection shared by the `mcp` and `trpc` builders. */\n private reflect(d: Discovered, lookup: OpenApiLookup | undefined): Reflected {\n const proto = Object.getPrototypeOf(d.instance) as object\n const route = reflectRoute(d.classRef, d.method)\n const slots = readParamSlots(d.classRef, d.methodName, proto)\n const operation = reflectOperation(d.method)\n const docFields = lookup ? openApiFields(lookup, route.method, route.openapiPath) : {}\n\n const { shape, bindings, warnings } = buildInput(proto, d.methodName, route.pathParams, slots, operation.params, docFields)\n for (const w of warnings) { logger.warn(`${d.classRef.name}.${d.methodName}: ${w}`) }\n\n return {\n route,\n base: d.classRef.name.replace(/Controller$/, ''),\n description: operation.description,\n baseShape: shape,\n bindings,\n guards: collectGuards(this.reflector, d.classRef, d.method),\n requestSlots: requestSlotFields(bindings),\n streaming: isAsyncGeneratorFn(d.method)\n }\n }\n\n /** Build a guard-application closure shared by both run shapes. */\n private guardRunner(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[]) {\n const { moduleRef, reflector, appConfig } = this\n const { guards, requestSlots } = shared\n const { classRef, method } = d\n return async (context: SilkweaveContext, input: object): Promise<void> => {\n // Resolved at call time - `APP_GUARD` instances aren't populated until\n // `app.init()` finishes. Globals run before the route/class guards.\n const all = [...collectGlobalGuards(appConfig, globalGuards), ...guards]\n if (all.length === 0) { return }\n const request = context.getOptional<unknown>('request')\n const response = context.getOptional<unknown>('response') ?? null\n const hasRequest = request != null\n const guardRequest = hasRequest ? request : { headers: {}, params: {}, query: {} }\n populateRequestSlots(guardRequest, requestSlots, input as Record<string, unknown>)\n await runGuards(all, moduleRef, reflector, classRef, method, guardRequest, response, hasRequest ? 'http' : 'rpc')\n }\n }\n\n /** Synthesize the MCP-targeted action (unchanged behavior from v2.4). */\n private mcpAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[], defaultResult?: 'json' | 'smart'): Action {\n const meta = d.mcp!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n // `result: 'structured'` turns the output schema into a hard MCP contract,\n // so it must be author-asserted: @Mcp({ output }) or an explicit\n // @Trpc({ output }) on the same method. Reflected @ApiOkResponse schemas\n // (one level deep, null-vs-optional gaps) are deliberately NOT accepted.\n const disposition = meta.result ?? defaultResult\n const output = resolveSchema(meta.output) ?? resolveSchema(d.trpc?.output)\n if (disposition === 'structured') {\n if (streaming) {\n throw new SilkweaveError(\n `${d.classRef.name}.${d.methodName}: @Mcp({ result: 'structured' }) is not supported on a streaming (async *) route - there is no single result to validate`,\n 'invalid_action'\n )\n }\n if (!output) {\n throw new SilkweaveError(\n `${d.classRef.name}.${d.methodName}: @Mcp({ result: 'structured' }) requires an explicit output schema - set @Mcp({ output }) or @Trpc({ output }). Reflected @ApiOkResponse schemas are not accepted as structured contracts.`,\n 'invalid_action'\n )\n }\n }\n\n return {\n name,\n description,\n input: z.object(shape),\n ...(disposition ? { disposition } : {}),\n ...(disposition === 'structured' && output ? { output } : {}),\n ...(meta.tags ? { tags: meta.tags } : {}),\n annotations: { ...verbAnnotations(shared.route.method), ...meta.annotations },\n isEnabled: (ctx) => ctx.getOptional<string>('adapter') === 'mcp',\n ...(streaming\n ? { chunk: z.unknown(), run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, false) }\n : {\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n return result ?? {}\n }\n })\n } as Action\n }\n\n /** Synthesize the tRPC-targeted action (kind/output/subscription + httpStatus errors). */\n private trpcAction(d: Discovered, shared: Reflected, globalGuards: Type<CanActivate>[], onToolCall?: OnToolCall): Action {\n const meta = d.trpc!\n const shape = { ...shared.baseShape, ...inputShape(meta.input) }\n const name = meta.name ?? `${shared.base}.${d.methodName}`\n const description = meta.description ?? shared.description ?? `${d.methodName} (${shared.route.method} /${shared.route.path})`\n const applyParamPipes = meta.pipes !== 'skip'\n const applyGuards = this.guardRunner(d, shared, globalGuards)\n const { method, instance } = d\n const { bindings, streaming } = shared\n\n // tRPC and typegen both consume `@Trpc` actions; MCP never does.\n const isEnabled = (ctx: SilkweaveContext): boolean => {\n const adapter = ctx.getOptional<string>('adapter')\n return adapter === 'trpc' || adapter === 'typegen'\n }\n\n if (streaming) {\n return {\n name,\n description,\n input: z.object(shape),\n chunk: resolveSchema(meta.chunk) ?? z.unknown(),\n isEnabled,\n run: streamingRun(applyGuards, method, instance, bindings, applyParamPipes, true, onToolCall ? { hook: onToolCall, name } : undefined)\n } as Action\n }\n\n const kind: ActionKind = meta.kind === 'query' || meta.kind === 'mutation'\n ? meta.kind\n : (shared.route.method === 'GET' ? 'query' : 'mutation')\n const output = resolveOutput(meta, method)\n\n // Reflection is one level deep, so a nested DTO or `Dto[]` output property\n // degrades to `unknown`/`unknown[]`. Surface it - the fix is `@Trpc({ output })`.\n const degraded = outputDegradedFields(meta, method)\n if (output && degraded.length > 0) {\n logger.warn(\n `${d.classRef.name}.${d.methodName}: tRPC output field(s) ${degraded.join(', ')} reflected to 'unknown' ` +\n '(nested DTO or Dto[] - reflection is one level deep). Supply @Trpc({ output }) with a Zod schema for precise types.'\n )\n }\n\n return {\n name,\n description,\n input: z.object(shape),\n ...(output ? { output } : {}),\n kind,\n isEnabled,\n run: async (input: object, context: SilkweaveContext): Promise<object> => {\n const started = Date.now()\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const result = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes)\n emitTrpcEvent(onToolCall, name, context, started)\n return result ?? {}\n } catch (error) {\n const mapped = toSilkweaveError(error)\n emitTrpcEvent(onToolCall, name, context, started, mapped)\n throw mapped\n }\n }\n } as Action\n }\n}\n\n/** Procedure key the tRPC router exposes for an action name (`Users.listBySpace` → `usersListBySpace`). */\nfunction camelKey(name: string): string {\n const parts = name.split(/[^a-zA-Z0-9]+/).filter(Boolean)\n return parts\n .map((part, index) => index === 0 ? part[0].toLowerCase() + part.slice(1) : part[0].toUpperCase() + part.slice(1))\n .join('')\n}\n\n/**\n * Emit a tRPC-side telemetry event (fire-and-forget). Gated to the `trpc`\n * adapter context so a `typegen`-driven evaluation never counts as a call.\n */\nfunction emitTrpcEvent(hook: OnToolCall | undefined, name: string, context: SilkweaveContext, started: number, error?: unknown): void {\n if (!hook || context.getOptional<string>('adapter') !== 'trpc') { return }\n const meta = error == null\n ? {}\n : error instanceof SilkweaveError\n ? { errorCode: error.code, errorMessage: error.message }\n : error instanceof Error\n ? { errorCode: error.name, errorMessage: error.message }\n : { errorCode: 'unknown' }\n emitToolCall(hook, {\n action: name,\n tool: camelKey(name),\n transport: 'trpc',\n durationMs: Date.now() - started,\n ok: error == null,\n ...meta,\n context\n })\n}\n\n/**\n * Verb-derived MCP annotation defaults for a controller route. Explicit\n * `@Mcp({ annotations })` fields are merged over these by the caller.\n */\nfunction verbAnnotations(method: string): ToolAnnotations {\n if (method === 'GET') { return { readOnlyHint: true, idempotentHint: true } }\n if (method === 'PUT') { return { readOnlyHint: false, idempotentHint: true } }\n if (method === 'DELETE') { return { readOnlyHint: false, destructiveHint: true, idempotentHint: true } }\n return { readOnlyHint: false }\n}\n\n/** Build a streaming (`async *`) run that applies guards then yields the method's chunks. */\nfunction streamingRun(\n applyGuards: (context: SilkweaveContext, input: object) => Promise<void>,\n method: (...args: unknown[]) => unknown,\n instance: object,\n bindings: Binding[],\n applyParamPipes: boolean,\n mapErrors: boolean,\n telemetry?: { hook: OnToolCall; name: string }\n) {\n return async function* (input: object, context: SilkweaveContext): AsyncGenerator<unknown, void, void> {\n const started = Date.now()\n try {\n await applyGuards(context, input)\n const request = context.getOptional<{ headers?: Record<string, unknown> }>('request')\n const response = context.getOptional<unknown>('response')\n const gen = await invokeRebound(method, instance, input as Record<string, unknown>, bindings, request, response, applyParamPipes) as AsyncIterable<unknown>\n for await (const chunk of gen) { yield chunk }\n if (telemetry) { emitTrpcEvent(telemetry.hook, telemetry.name, context, started) }\n } catch (error) {\n const mapped = mapErrors ? toSilkweaveError(error) : error\n if (telemetry) { emitTrpcEvent(telemetry.hook, telemetry.name, context, started, mapped) }\n throw mapped\n }\n }\n}\n\n/** Resolve a `@Trpc` action's output schema: explicit override wins over `@ApiOkResponse` reflection. */\nfunction resolveOutput(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): z.ZodType | undefined {\n return resolveSchema(meta.output) ?? reflectResponseSchema(method)\n}\n\n/**\n * Output field names that reflected to `unknown` (nested DTO / `Dto[]`). Only the\n * reflected paths are inspected - an explicit Zod or raw-shape `@Trpc({ output })`\n * is the caller's own typing and is never flagged.\n */\nfunction outputDegradedFields(meta: TrpcMetadata, method: (...args: unknown[]) => unknown): string[] {\n if (meta.output != null && isZodSchema(meta.output)) { return [] }\n const fields = typeof meta.output === 'function'\n ? reflectDtoFields(meta.output)\n : meta.output != null ? undefined : reflectResponseFields(method)\n return fields ? unreflectedFields(fields) : []\n}\n\n/**\n * Normalise an `@Mcp`/`@Trpc({ input })` override to a raw Zod shape. Accepts a\n * plain `Record<string, ZodType>` or a whole `z.object({ ... })` (duck-typed by\n * `safeParse` + `shape`, so a different zod copy's object still unwraps).\n */\nfunction inputShape(input: McpMetadata['input']): Record<string, z.ZodType> {\n if (!input) { return {} }\n const maybe = input as { safeParse?: unknown; shape?: unknown }\n if (typeof maybe.safeParse === 'function' && maybe.shape != null && typeof maybe.shape === 'object') {\n return maybe.shape as Record<string, z.ZodType>\n }\n return input as Record<string, z.ZodType>\n}\n\n/**\n * Coerce an `output`/`chunk` override to a Zod schema: a Zod schema passes\n * through, a DTO class is reflected, and a raw shape is wrapped in `z.object`.\n */\nfunction resolveSchema(value: TrpcMetadata['output']): z.ZodType | undefined {\n if (value == null) { return undefined }\n if (isZodSchema(value)) { return value }\n if (typeof value === 'function') { return reflectDtoSchema(value) }\n return z.object(value)\n}\n\nfunction isZodSchema(value: unknown): value is z.ZodType {\n return Boolean(value) && typeof value === 'object' && typeof (value as { safeParse?: unknown }).safeParse === 'function'\n}\n\nfunction isAsyncGeneratorFn(fn: unknown): boolean {\n return typeof fn === 'function' && (fn as { constructor?: { name?: string } }).constructor?.name === 'AsyncGeneratorFunction'\n}\n\n/**\n * Convert a thrown Nest `HttpException` into a `SilkweaveError` carrying its HTTP\n * status, so the tRPC adapter's `mapError` maps it to the right `TRPCError` code\n * (and `data.httpStatus`) - e.g. a denying `AuthGuard`'s `UnauthorizedException`\n * surfaces to the client as a `401`. Non-HTTP errors pass through unchanged.\n */\nfunction toSilkweaveError(error: unknown): unknown {\n if (error instanceof HttpException) {\n const status = error.getStatus()\n const response = error.getResponse()\n const raw = typeof response === 'string'\n ? response\n : (response as { message?: unknown })?.message ?? error.message\n const message = Array.isArray(raw) ? raw.join(', ') : String(raw)\n return new SilkweaveError(message, 'http_error', status)\n }\n return error\n}\n\n/** Build the merged Zod input shape and the per-argument re-bind plan. */\nfunction buildInput(\n proto: object,\n methodName: string,\n pathParams: string[],\n slots: ReturnType<typeof readParamSlots>,\n operationParams: Record<string, FieldDesc>,\n docFields: Record<string, FieldDesc>\n): BuiltInput {\n const designTypes = (Reflect.getMetadata('design:paramtypes', proto, methodName) as unknown[] | undefined) ?? []\n const fields: Record<string, FieldDesc> = {}\n const warnings: string[] = []\n const maxIndex = slots.reduce((m, s) => Math.max(m, s.index), -1)\n const bindings: Binding[] = Array.from({ length: maxIndex + 1 }, () => ({ kind: 'missing' as const }))\n\n const addField = (name: string, desc: FieldDesc): void => {\n fields[name] = name in fields ? mergeField(fields[name], desc) : desc\n }\n\n for (const slot of slots) {\n const { binding, fields: contributed } = contributeSlot(slot, pathParams, designTypes)\n bindings[slot.index] = binding\n for (const [name, desc] of Object.entries(contributed)) { addField(name, desc) }\n // A whole-DTO `@Body()`/`@Query()` that reflected to zero fields: the type\n // was unreflectable (an interface, or an intersection/union TypeScript\n // erases to `Object`/`Array` under `design:type`). Its fields are silently\n // absent unless declared via `@Mcp`/`@Trpc({ input })`.\n if (binding.kind === 'object' && binding.fields.length === 0) {\n const typeName = (designTypes[slot.index] as { name?: string } | undefined)?.name ?? 'unknown'\n warnings.push(\n `whole-${binding.source} parameter #${slot.index} (type '${typeName}') reflected no input fields. ` +\n `If it is an intersection/union (e.g. 'A & B'), TypeScript erases it to '${typeName}' so the DTO is lost - ` +\n 'use a single DTO class or declare the fields via @Mcp/@Trpc({ input }).'\n )\n }\n }\n\n // Layer operation-level (`@ApiParam`/`@ApiQuery`) then OpenAPI-document\n // metadata over the structural fields (later sources win per field).\n for (const [name, desc] of Object.entries(operationParams)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n for (const [name, desc] of Object.entries(docFields)) {\n if (name in fields) { fields[name] = mergeField(fields[name], desc) }\n }\n\n const shape: Record<string, z.ZodType> = {}\n for (const [name, desc] of Object.entries(fields)) { shape[name] = fieldToZod(desc) }\n\n return { shape, bindings, warnings }\n}\n\nfunction designTypeAt(designTypes: unknown[], index: number): FieldDesc {\n const ctor = designTypes[index]\n if (ctor === String) { return { type: 'string' } }\n if (ctor === Number) { return { type: 'number' } }\n if (ctor === Boolean) { return { type: 'boolean' } }\n return {}\n}\n\ninterface SlotContribution {\n binding: Binding\n /** Input fields this slot contributes, keyed by field name. */\n fields: Record<string, FieldDesc>\n}\n\n/** A `@Param('id')` scalar or a bare `@Param()` covering all path params. */\nfunction paramContribution(slot: ParamSlot, pathParams: string[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source: 'path', metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: { type: 'string', required: true } }\n }\n }\n const fields: Record<string, FieldDesc> = {}\n for (const p of pathParams) { fields[p] = { type: 'string', required: true } }\n return { binding: { kind: 'params', fields: pathParams }, fields }\n}\n\n/** A `@Query('x')`/`@Body('x')` scalar or a whole-DTO `@Query()`/`@Body()`. */\nfunction bodyOrQueryContribution(slot: ParamSlot, source: 'query' | 'body', requiredScalar: boolean, designTypes: unknown[]): SlotContribution {\n if (slot.data) {\n return {\n binding: { kind: 'value', field: slot.data, source, metatype: slot.designType, pipes: slot.pipes },\n fields: { [slot.data]: mergeField(designTypeAt(designTypes, slot.index), { required: requiredScalar }) }\n }\n }\n const dtoFields = reflectDtoFields(slot.designType)\n return {\n binding: { kind: 'object', source, fields: Object.keys(dtoFields), metatype: slot.designType, pipes: slot.pipes },\n fields: dtoFields\n }\n}\n\n/** Map one parameter slot to its input-field contribution and re-bind instruction. */\nfunction contributeSlot(slot: ParamSlot, pathParams: string[], designTypes: unknown[]): SlotContribution {\n switch (slot.paramtype) {\n case PARAMTYPE.PARAM: return paramContribution(slot, pathParams)\n case PARAMTYPE.QUERY: return bodyOrQueryContribution(slot, 'query', false, designTypes)\n case PARAMTYPE.BODY: return bodyOrQueryContribution(slot, 'body', true, designTypes)\n default: return { binding: specialBinding(slot.paramtype, slot.data) ?? { kind: 'missing' }, fields: {} }\n }\n}\n","import type { CanActivate, Type } from '@nestjs/common'\nimport type { HttpAdapterHost } from '@nestjs/core'\nimport type { Action, OnToolCall, SilkweaveContext, SilkweaveOptions, ToolCallEvent } from '@silkweave/core'\nimport type { OpenApiDocument } from './reflect/openapi.js'\n\n/**\n * Telemetry service contract for `SilkweaveModuleOptions.telemetry`. Implement\n * it as a regular injectable provider (it can inject your logger, config,\n * repositories) and pass the **class token** to `forRoot` - it is resolved\n * through DI at call time.\n *\n * `onToolCall` fires once per tool/procedure invocation, fire-and-forget:\n * never awaited on the call path, errors logged and swallowed. MCP events are\n * emitted from the MCP registrar (and carry `resultBytes`/`sideloaded`); tRPC\n * events from the synthesized action wrapper (guard denials included) -\n * exactly one event per call either way.\n */\nexport interface SilkweaveTelemetry {\n onToolCall(event: ToolCallEvent): void | Promise<void>\n}\n\n/**\n * Context passed to a Nest Silkweave adapter when `SilkweaveModule` wires it\n * up. Adapters register their routes directly on `httpAdapter` (no\n * placeholder middleware, no `silkweave()` builder), so they only fire\n * `register()` once and own the rest of their lifecycle implicitly through\n * Nest.\n */\nexport interface NestAdapterRegisterContext {\n /** Nest's underlying HTTP adapter (Express or Fastify). */\n httpAdapter: NonNullable<HttpAdapterHost['httpAdapter']>\n /** Identity the adapter surfaces to clients (e.g. MCP server name). */\n silkweaveOptions: SilkweaveOptions\n /** Per-adapter context - already forked with `{ adapter: adapter.name, ...userContext }`. */\n baseContext: SilkweaveContext\n /** Actions filtered to those enabled on this adapter. */\n actions: Action[]\n /**\n * Telemetry emitter resolved from `SilkweaveModuleOptions.telemetry` (when\n * configured). The `mcp()` adapter threads it into the MCP registrar so MCP\n * events carry the result metadata only that layer knows.\n */\n onToolCall?: OnToolCall\n}\n\n/**\n * A Silkweave Nest adapter. Each transport (REST, tRPC, MCP) implements this\n * shape. `register()` is called from `SilkweaveModule.configure()` - which\n * runs *before* Nest's controller routes are mapped - so adapter routes\n * always sit ahead of any catch-all controllers in the framework's request\n * pipeline.\n */\nexport interface NestSilkweaveAdapter {\n /** Adapter discriminator - set on the silkweave context as `ctx.get('adapter')`. */\n readonly name: 'mcp' | 'trpc' | 'typegen'\n /** URL prefix the adapter mounts on (e.g. `'/mcp'`). Surfaced for introspection. */\n readonly basePath?: string\n /**\n * When `true`, the adapter receives every discovered action regardless of\n * each action's `isEnabled` gate. Reserved for non-runtime adapters that need\n * the entire action surface.\n */\n readonly allActions?: boolean\n /** Register this adapter's routes on Nest's HTTP server. */\n register(ctx: NestAdapterRegisterContext): void\n}\n\nexport interface SilkweaveModuleOptions {\n /** Identity for the silkweave instance - surfaced to MCP clients, OpenAPI, etc. */\n silkweave: SilkweaveOptions\n /** Adapters to mount - any of `mcp()`, `trpc()`, `typegen()`. */\n adapters: NestSilkweaveAdapter[]\n /** Initial context keys merged into every adapter's `baseContext`. */\n context?: Record<string, unknown>\n /**\n * Optional OpenAPI document (e.g. from `SwaggerModule.createDocument(app, cfg)`)\n * used as an authoritative source when reflecting `@Mcp` tool input schemas.\n * Matched to each method by HTTP verb + path; falls back to decorator\n * reflection when an operation or field isn't present.\n */\n openapi?: OpenApiDocument\n /**\n * Opt-in allow-list of app-global guard classes (registered via\n * `app.useGlobalGuards()` or `{ provide: APP_GUARD, useClass }`) to run on\n * every MCP tool call, before each method/class `@UseGuards`. Listed by\n * class - a blanket \"run all globals\" is deliberately not offered, since\n * unrelated globals (e.g. a `ThrottlerGuard` that needs a writable response)\n * would misbehave over MCP. Empty/omitted ⇒ no global guards run.\n *\n * Note: over MCP the request stand-in is headers-only (`params`/`query` are\n * empty), so per-session or IP-derived guard logic won't apply; header-based\n * authentication still works.\n */\n globalGuards?: Type<CanActivate>[]\n /**\n * Default MCP result format for every `@Mcp` tool - `'json'` (compact JSON,\n * `jsonToolResult`) or `'smart'` (inline small / embedded-resource large,\n * `smartToolResult`). Defaults to `'json'` (since 3.2; was `'smart'`). A\n * per-method `@Mcp({ result })` overrides this, and a client's per-call\n * `_meta.disposition` overrides both.\n */\n defaultResult?: 'json' | 'smart'\n /**\n * Class token of a `SilkweaveTelemetry` provider, resolved through DI at\n * call time (so it can inject your logger/config). One `onToolCall` event\n * fires per tool/procedure invocation across MCP and tRPC - see\n * `SilkweaveTelemetry` for the seam split and event fields.\n */\n telemetry?: Type<SilkweaveTelemetry>\n}\n\nexport const SILKWEAVE_MODULE_OPTIONS = '__silkweave_module_options__'\n","import { Inject, Module, type DynamicModule, type MiddlewareConsumer, type NestModule } from '@nestjs/common'\nimport { DiscoveryModule, HttpAdapterHost, ModuleRef } from '@nestjs/core'\nimport { createContext, type OnToolCall } from '@silkweave/core'\nimport { ControllerDiscovery } from './controllerDiscovery.js'\nimport { SILKWEAVE_MODULE_OPTIONS, type SilkweaveModuleOptions, type SilkweaveTelemetry } from './types.js'\n\n/**\n * Root module for `@silkweave/nestjs`.\n *\n * Discovers every `@Mcp`/`@Trpc`-decorated **controller method** via\n * `DiscoveryService`, reflects each into a Silkweave action (input schema from\n * the route + parameter decorators + optional OpenAPI document; invocation by\n * re-binding the validated input back into the method), and registers the\n * configured adapter(s) - `mcp()`, `trpc()`, `typegen()` - directly on Nest's\n * HTTP adapter inside `configure()`.\n *\n * Because `configure()` runs during `registerModules` - before Nest's\n * `registerRouter()` step - Silkweave's routes always sit ahead of every\n * controller in the Express stack. The controllers keep serving HTTP exactly as\n * before; `@Mcp` is purely additive.\n *\n * @example\n * ```ts\n * @Module({\n * imports: [\n * SilkweaveModule.forRoot({\n * silkweave: { name: 'app', description: 'My App', version: '1.0.0' },\n * adapters: [mcp({ basePath: '/mcp' })]\n * })\n * ],\n * controllers: [ChannelsController]\n * })\n * export class AppModule {}\n * ```\n */\n@Module({})\nexport class SilkweaveModule implements NestModule {\n constructor(\n @Inject(SILKWEAVE_MODULE_OPTIONS) private readonly options: SilkweaveModuleOptions,\n private readonly discovery: ControllerDiscovery,\n private readonly httpAdapterHost: HttpAdapterHost,\n private readonly moduleRef: ModuleRef\n ) { }\n\n /**\n * Build the telemetry emitter from the configured class token. The instance\n * is resolved through DI lazily on first event (and memoized) - `configure()`\n * runs before providers are guaranteed ready, same reason global guards\n * resolve at call time.\n */\n private telemetryEmitter(): OnToolCall | undefined {\n const token = this.options.telemetry\n if (!token) { return undefined }\n let instance: SilkweaveTelemetry | undefined\n return (event) => {\n const resolved = instance ?? this.moduleRef.get<SilkweaveTelemetry>(token, { strict: false })\n instance = resolved\n return resolved.onToolCall(event)\n }\n }\n\n static forRoot(options: SilkweaveModuleOptions): DynamicModule {\n return {\n module: SilkweaveModule,\n global: true,\n imports: [DiscoveryModule],\n providers: [\n { provide: SILKWEAVE_MODULE_OPTIONS, useValue: options },\n ControllerDiscovery\n ],\n exports: []\n }\n }\n\n configure(_consumer: MiddlewareConsumer): void {\n const httpAdapter = this.httpAdapterHost.httpAdapter\n if (!httpAdapter) {\n throw new Error('@silkweave/nestjs: HttpAdapterHost.httpAdapter is not available.')\n }\n const onToolCall = this.telemetryEmitter()\n const allActions = this.discovery.discover({\n openapi: this.options.openapi,\n globalGuards: this.options.globalGuards,\n defaultResult: this.options.defaultResult,\n // tRPC events come from the synthesized action wrapper; MCP events from\n // the MCP registrar (via each adapter's register context) - one per call.\n onToolCall\n })\n for (const adapter of this.options.adapters) {\n const baseContext = createContext({ ...(this.options.context ?? {}), adapter: adapter.name })\n const actions = adapter.allActions\n ? allActions\n : allActions.filter((a) => !a.isEnabled || a.isEnabled(baseContext))\n adapter.register({\n httpAdapter,\n silkweaveOptions: this.options.silkweave,\n baseContext,\n actions,\n onToolCall\n })\n }\n }\n}\n"],"mappings":"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"}
|
package/build/mcp.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { n as NestSilkweaveAdapter } from "./types-
|
|
1
|
+
import { n as NestSilkweaveAdapter } from "./types-6rbW7fLE.mjs";
|
|
2
2
|
import { t as AuthConfig } from "./index-ByAnTJu5.mjs";
|
|
3
|
+
import { FilterActions } from "@silkweave/mcp";
|
|
3
4
|
import { CorsOptions } from "cors";
|
|
4
5
|
|
|
5
6
|
//#region src/adapter/mcp.d.ts
|
|
@@ -14,6 +15,15 @@ interface McpAdapterOptions {
|
|
|
14
15
|
sideloadResources?: boolean;
|
|
15
16
|
/** Directory the sideload route reads from. Default `'resources'`. */
|
|
16
17
|
resourceDir?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Per-request tool filter, applied before tools are registered on every
|
|
20
|
+
* `POST ${basePath}` (the stateless transport recomputes the tool list per
|
|
21
|
+
* request, so e.g. API-key permission changes apply on the next
|
|
22
|
+
* `tools/list`). Receives the synthesized actions (with their `tags`) and a
|
|
23
|
+
* request stand-in (`headers`/`url`/`method`/`toolName`). A throw surfaces
|
|
24
|
+
* as its `SilkweaveError.statusCode` (else 500) - never an empty tool list.
|
|
25
|
+
*/
|
|
26
|
+
filterActions?: FilterActions;
|
|
17
27
|
}
|
|
18
28
|
/**
|
|
19
29
|
* MCP adapter for `@silkweave/nestjs`. Registers the MCP Streamable HTTP
|
package/build/mcp.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.d.mts","names":[],"sources":["../src/adapter/mcp.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcp.d.mts","names":[],"sources":["../src/adapter/mcp.ts"],"mappings":";;;;;;UAciB,iBAAA;;EAEf,QAAA;EAFgC;EAIhC,IAAA,GAAO,UAAA;EAAA;EAEP,IAAA,GAAO,WAAA;EAaS;EAXhB,iBAAA;EAW6B;EAT7B,WAAA;EANA;;;;;;;;EAeA,aAAA,GAAgB,aAAA;AAAA;AA6BlB;;;;;;;;;;;;;;AAAA,iBAAgB,GAAA,CAAI,OAAA,GAAS,iBAAA,GAAyB,oBAAA"}
|
package/build/mcp.mjs
CHANGED
|
@@ -29,7 +29,7 @@ function compose(...handlers) {
|
|
|
29
29
|
function mcp(options = {}) {
|
|
30
30
|
return {
|
|
31
31
|
name: "mcp",
|
|
32
|
-
register({ httpAdapter, silkweaveOptions, baseContext, actions }) {
|
|
32
|
+
register({ httpAdapter, silkweaveOptions, baseContext, actions, onToolCall }) {
|
|
33
33
|
const basePath = (options.basePath ?? "/mcp").replace(/\/$/, "");
|
|
34
34
|
if (!basePath) throw new Error("@silkweave/nestjs mcp(): basePath cannot be empty or \"/\" - pick a path like \"/mcp\".");
|
|
35
35
|
const adapter = httpAdapter;
|
|
@@ -48,7 +48,10 @@ function mcp(options = {}) {
|
|
|
48
48
|
}
|
|
49
49
|
const protect = guard ? (h) => compose(guard, h) : (h) => h;
|
|
50
50
|
if (options.sideloadResources !== false) adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))));
|
|
51
|
-
const transport = mcpTransport(silkweaveOptions, baseContext, actions
|
|
51
|
+
const transport = mcpTransport(silkweaveOptions, baseContext, actions, {
|
|
52
|
+
filterActions: options.filterActions,
|
|
53
|
+
onToolCall
|
|
54
|
+
});
|
|
52
55
|
adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)));
|
|
53
56
|
}
|
|
54
57
|
};
|
package/build/mcp.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.mjs","names":[],"sources":["../src/adapter/mcp.ts"],"sourcesContent":["import { AuthConfig } from '@silkweave/auth'\nimport {\n authMiddleware,\n mcpCors,\n mcpTransport,\n oauthRoutes,\n protectedResourceMetadata,\n sideloadResource\n} from '@silkweave/mcp'\nimport { type CorsOptions } from 'cors'\nimport express, { type RequestHandler } from 'express'\nimport type { NestAdapterRegisterContext, NestSilkweaveAdapter } from '../lib/types.js'\n\nexport interface McpAdapterOptions {\n /** URL prefix the MCP namespace lives under - the transport itself is at this exact path. Default `'/mcp'`. */\n basePath?: string\n /** Optional bearer-token / OAuth 2.1 config. */\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/omitted for permissive defaults, or a `CorsOptions` object. */\n cors?: CorsOptions | boolean\n /** Mount the sideload resource route at `${basePath}/resource/:id`. Default `true`. */\n sideloadResources?: boolean\n /** Directory the sideload route reads from. Default `'resources'`. */\n resourceDir?: string\n}\n\nfunction compose(...handlers: RequestHandler[]): RequestHandler {\n return (req, res, next) => {\n let i = 0\n const dispatch: () => void = () => {\n const h = handlers[i++]\n if (!h) { return next() }\n h(req, res, (err) => err ? next(err) : dispatch())\n }\n dispatch()\n }\n}\n\n/**\n * MCP adapter for `@silkweave/nestjs`. Registers the MCP Streamable HTTP\n * transport, sideload, well-known and OAuth routes individually on Nest's\n * HTTP adapter at the configured `basePath` (default `/mcp`):\n *\n * - `POST/GET/DELETE ${basePath}` - Streamable HTTP transport\n * - `GET ${basePath}/resource/:id` - sideload (`sideloadResources` opt-out)\n * - `GET ${basePath}/.well-known/oauth-protected-resource` - RFC 9728 metadata (when `auth.resourceUrl`/`auth.authorizationServers` set)\n * - `GET ${basePath}/authorize`, `POST ${basePath}/token`, `POST ${basePath}/register`, `GET ${basePath}${callbackPath}` (when `auth.provider` set)\n *\n * Each route is a real Nest-level route - they show up in\n * `RoutesResolver`'s log and there is no sub-app or middleware-slot\n * indirection.\n */\nexport function mcp(options: McpAdapterOptions = {}): NestSilkweaveAdapter {\n return {\n name: 'mcp',\n register({ httpAdapter, silkweaveOptions, baseContext, actions }: NestAdapterRegisterContext): void {\n const basePath = (options.basePath ?? '/mcp').replace(/\\/$/, '')\n if (!basePath) { throw new Error('@silkweave/nestjs mcp(): basePath cannot be empty or \"/\" - pick a path like \"/mcp\".') }\n\n const adapter = httpAdapter as unknown as {\n get: (path: string, ...h: RequestHandler[]) => unknown\n post: (path: string, ...h: RequestHandler[]) => unknown\n delete: (path: string, ...h: RequestHandler[]) => unknown\n }\n\n const corsHandler = mcpCors(options.cors ?? true)\n const auth = options.auth\n const guard = auth ? authMiddleware(auth, baseContext) : null\n const prefix = (...handlers: (RequestHandler | null)[]): RequestHandler[] =>\n handlers.filter((h): h is RequestHandler => Boolean(h))\n\n // Public auth-discovery / OAuth routes - registered first so they're\n // never inadvertently guarded by the auth middleware.\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n adapter.get(\n `${basePath}/.well-known/oauth-protected-resource`,\n ...prefix(corsHandler, protectedResourceMetadata(auth))\n )\n }\n if (auth?.provider) {\n const oauth = oauthRoutes(auth)\n adapter.get(`${basePath}/.well-known/oauth-authorization-server`, ...prefix(corsHandler, oauth.wellKnownAuthServer))\n adapter.get(`${basePath}/authorize`, ...prefix(corsHandler, oauth.authorize))\n adapter.get(`${basePath}${oauth.callbackPath}`, ...prefix(corsHandler, oauth.callback))\n adapter.post(`${basePath}/token`, ...prefix(corsHandler, ...oauth.token))\n adapter.post(`${basePath}/register`, ...prefix(corsHandler, ...oauth.register))\n }\n\n // Protected routes - wrapped with auth middleware (when configured).\n const protect = guard ? (h: RequestHandler) => compose(guard, h) : (h: RequestHandler) => h\n\n if (options.sideloadResources !== false) {\n adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))))\n }\n\n const transport = mcpTransport(silkweaveOptions, baseContext, actions)\n adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)))\n }\n }\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"mcp.mjs","names":[],"sources":["../src/adapter/mcp.ts"],"sourcesContent":["import { AuthConfig } from '@silkweave/auth'\nimport {\n authMiddleware,\n mcpCors,\n mcpTransport,\n oauthRoutes,\n protectedResourceMetadata,\n sideloadResource,\n type FilterActions\n} from '@silkweave/mcp'\nimport { type CorsOptions } from 'cors'\nimport express, { type RequestHandler } from 'express'\nimport type { NestAdapterRegisterContext, NestSilkweaveAdapter } from '../lib/types.js'\n\nexport interface McpAdapterOptions {\n /** URL prefix the MCP namespace lives under - the transport itself is at this exact path. Default `'/mcp'`. */\n basePath?: string\n /** Optional bearer-token / OAuth 2.1 config. */\n auth?: AuthConfig\n /** CORS configuration. `false` to disable, `true`/omitted for permissive defaults, or a `CorsOptions` object. */\n cors?: CorsOptions | boolean\n /** Mount the sideload resource route at `${basePath}/resource/:id`. Default `true`. */\n sideloadResources?: boolean\n /** Directory the sideload route reads from. Default `'resources'`. */\n resourceDir?: string\n /**\n * Per-request tool filter, applied before tools are registered on every\n * `POST ${basePath}` (the stateless transport recomputes the tool list per\n * request, so e.g. API-key permission changes apply on the next\n * `tools/list`). Receives the synthesized actions (with their `tags`) and a\n * request stand-in (`headers`/`url`/`method`/`toolName`). A throw surfaces\n * as its `SilkweaveError.statusCode` (else 500) - never an empty tool list.\n */\n filterActions?: FilterActions\n}\n\nfunction compose(...handlers: RequestHandler[]): RequestHandler {\n return (req, res, next) => {\n let i = 0\n const dispatch: () => void = () => {\n const h = handlers[i++]\n if (!h) { return next() }\n h(req, res, (err) => err ? next(err) : dispatch())\n }\n dispatch()\n }\n}\n\n/**\n * MCP adapter for `@silkweave/nestjs`. Registers the MCP Streamable HTTP\n * transport, sideload, well-known and OAuth routes individually on Nest's\n * HTTP adapter at the configured `basePath` (default `/mcp`):\n *\n * - `POST/GET/DELETE ${basePath}` - Streamable HTTP transport\n * - `GET ${basePath}/resource/:id` - sideload (`sideloadResources` opt-out)\n * - `GET ${basePath}/.well-known/oauth-protected-resource` - RFC 9728 metadata (when `auth.resourceUrl`/`auth.authorizationServers` set)\n * - `GET ${basePath}/authorize`, `POST ${basePath}/token`, `POST ${basePath}/register`, `GET ${basePath}${callbackPath}` (when `auth.provider` set)\n *\n * Each route is a real Nest-level route - they show up in\n * `RoutesResolver`'s log and there is no sub-app or middleware-slot\n * indirection.\n */\nexport function mcp(options: McpAdapterOptions = {}): NestSilkweaveAdapter {\n return {\n name: 'mcp',\n register({ httpAdapter, silkweaveOptions, baseContext, actions, onToolCall }: NestAdapterRegisterContext): void {\n const basePath = (options.basePath ?? '/mcp').replace(/\\/$/, '')\n if (!basePath) { throw new Error('@silkweave/nestjs mcp(): basePath cannot be empty or \"/\" - pick a path like \"/mcp\".') }\n\n const adapter = httpAdapter as unknown as {\n get: (path: string, ...h: RequestHandler[]) => unknown\n post: (path: string, ...h: RequestHandler[]) => unknown\n delete: (path: string, ...h: RequestHandler[]) => unknown\n }\n\n const corsHandler = mcpCors(options.cors ?? true)\n const auth = options.auth\n const guard = auth ? authMiddleware(auth, baseContext) : null\n const prefix = (...handlers: (RequestHandler | null)[]): RequestHandler[] =>\n handlers.filter((h): h is RequestHandler => Boolean(h))\n\n // Public auth-discovery / OAuth routes - registered first so they're\n // never inadvertently guarded by the auth middleware.\n if (auth?.authorizationServers?.length && auth.resourceUrl) {\n adapter.get(\n `${basePath}/.well-known/oauth-protected-resource`,\n ...prefix(corsHandler, protectedResourceMetadata(auth))\n )\n }\n if (auth?.provider) {\n const oauth = oauthRoutes(auth)\n adapter.get(`${basePath}/.well-known/oauth-authorization-server`, ...prefix(corsHandler, oauth.wellKnownAuthServer))\n adapter.get(`${basePath}/authorize`, ...prefix(corsHandler, oauth.authorize))\n adapter.get(`${basePath}${oauth.callbackPath}`, ...prefix(corsHandler, oauth.callback))\n adapter.post(`${basePath}/token`, ...prefix(corsHandler, ...oauth.token))\n adapter.post(`${basePath}/register`, ...prefix(corsHandler, ...oauth.register))\n }\n\n // Protected routes - wrapped with auth middleware (when configured).\n const protect = guard ? (h: RequestHandler) => compose(guard, h) : (h: RequestHandler) => h\n\n if (options.sideloadResources !== false) {\n adapter.get(`${basePath}/resource/:id`, ...prefix(corsHandler, protect(sideloadResource({ resourceDir: options.resourceDir }))))\n }\n\n const transport = mcpTransport(silkweaveOptions, baseContext, actions, { filterActions: options.filterActions, onToolCall })\n adapter.post(basePath, ...prefix(corsHandler, express.json(), protect(transport.post)))\n }\n }\n}\n"],"mappings":";;;AAoCA,SAAS,QAAQ,GAAG,UAA4C;AAC9D,SAAQ,KAAK,KAAK,SAAS;EACzB,IAAI,IAAI;EACR,MAAM,iBAA6B;GACjC,MAAM,IAAI,SAAS;AACnB,OAAI,CAAC,EAAK,QAAO,MAAM;AACvB,KAAE,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,GAAG,UAAU,CAAC;;AAEpD,YAAU;;;;;;;;;;;;;;;;;AAkBd,SAAgB,IAAI,UAA6B,EAAE,EAAwB;AACzE,QAAO;EACL,MAAM;EACN,SAAS,EAAE,aAAa,kBAAkB,aAAa,SAAS,cAAgD;GAC9G,MAAM,YAAY,QAAQ,YAAY,QAAQ,QAAQ,OAAO,GAAG;AAChE,OAAI,CAAC,SAAY,OAAM,IAAI,MAAM,0FAAsF;GAEvH,MAAM,UAAU;GAMhB,MAAM,cAAc,QAAQ,QAAQ,QAAQ,KAAK;GACjD,MAAM,OAAO,QAAQ;GACrB,MAAM,QAAQ,OAAO,eAAe,MAAM,YAAY,GAAG;GACzD,MAAM,UAAU,GAAG,aACjB,SAAS,QAAQ,MAA2B,QAAQ,EAAE,CAAC;AAIzD,OAAI,MAAM,sBAAsB,UAAU,KAAK,YAC7C,SAAQ,IACN,GAAG,SAAS,wCACZ,GAAG,OAAO,aAAa,0BAA0B,KAAK,CAAC,CACxD;AAEH,OAAI,MAAM,UAAU;IAClB,MAAM,QAAQ,YAAY,KAAK;AAC/B,YAAQ,IAAI,GAAG,SAAS,0CAA0C,GAAG,OAAO,aAAa,MAAM,oBAAoB,CAAC;AACpH,YAAQ,IAAI,GAAG,SAAS,aAAa,GAAG,OAAO,aAAa,MAAM,UAAU,CAAC;AAC7E,YAAQ,IAAI,GAAG,WAAW,MAAM,gBAAgB,GAAG,OAAO,aAAa,MAAM,SAAS,CAAC;AACvF,YAAQ,KAAK,GAAG,SAAS,SAAS,GAAG,OAAO,aAAa,GAAG,MAAM,MAAM,CAAC;AACzE,YAAQ,KAAK,GAAG,SAAS,YAAY,GAAG,OAAO,aAAa,GAAG,MAAM,SAAS,CAAC;;GAIjF,MAAM,UAAU,SAAS,MAAsB,QAAQ,OAAO,EAAE,IAAI,MAAsB;AAE1F,OAAI,QAAQ,sBAAsB,MAChC,SAAQ,IAAI,GAAG,SAAS,gBAAgB,GAAG,OAAO,aAAa,QAAQ,iBAAiB,EAAE,aAAa,QAAQ,aAAa,CAAC,CAAC,CAAC,CAAC;GAGlI,MAAM,YAAY,aAAa,kBAAkB,aAAa,SAAS;IAAE,eAAe,QAAQ;IAAe;IAAY,CAAC;AAC5H,WAAQ,KAAK,UAAU,GAAG,OAAO,aAAa,QAAQ,MAAM,EAAE,QAAQ,UAAU,KAAK,CAAC,CAAC;;EAE1F"}
|
package/build/trpc.d.mts
CHANGED
package/build/typegen.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CanActivate, Type } from "@nestjs/common";
|
|
2
2
|
import { HttpAdapterHost } from "@nestjs/core";
|
|
3
|
-
import { Action, SilkweaveContext, SilkweaveOptions } from "@silkweave/core";
|
|
3
|
+
import { Action, OnToolCall, SilkweaveContext, SilkweaveOptions, ToolCallEvent } from "@silkweave/core";
|
|
4
4
|
import { z } from "zod/v4";
|
|
5
5
|
|
|
6
6
|
//#region src/lib/reflect/schema.d.ts
|
|
@@ -93,6 +93,21 @@ declare function buildOpenApiLookup(doc: OpenApiDocument): OpenApiLookup;
|
|
|
93
93
|
declare function openApiFields(lookup: OpenApiLookup, method: string, openapiPath: string): Record<string, FieldDesc>;
|
|
94
94
|
//#endregion
|
|
95
95
|
//#region src/lib/types.d.ts
|
|
96
|
+
/**
|
|
97
|
+
* Telemetry service contract for `SilkweaveModuleOptions.telemetry`. Implement
|
|
98
|
+
* it as a regular injectable provider (it can inject your logger, config,
|
|
99
|
+
* repositories) and pass the **class token** to `forRoot` - it is resolved
|
|
100
|
+
* through DI at call time.
|
|
101
|
+
*
|
|
102
|
+
* `onToolCall` fires once per tool/procedure invocation, fire-and-forget:
|
|
103
|
+
* never awaited on the call path, errors logged and swallowed. MCP events are
|
|
104
|
+
* emitted from the MCP registrar (and carry `resultBytes`/`sideloaded`); tRPC
|
|
105
|
+
* events from the synthesized action wrapper (guard denials included) -
|
|
106
|
+
* exactly one event per call either way.
|
|
107
|
+
*/
|
|
108
|
+
interface SilkweaveTelemetry {
|
|
109
|
+
onToolCall(event: ToolCallEvent): void | Promise<void>;
|
|
110
|
+
}
|
|
96
111
|
/**
|
|
97
112
|
* Context passed to a Nest Silkweave adapter when `SilkweaveModule` wires it
|
|
98
113
|
* up. Adapters register their routes directly on `httpAdapter` (no
|
|
@@ -109,6 +124,12 @@ interface NestAdapterRegisterContext {
|
|
|
109
124
|
baseContext: SilkweaveContext;
|
|
110
125
|
/** Actions filtered to those enabled on this adapter. */
|
|
111
126
|
actions: Action[];
|
|
127
|
+
/**
|
|
128
|
+
* Telemetry emitter resolved from `SilkweaveModuleOptions.telemetry` (when
|
|
129
|
+
* configured). The `mcp()` adapter threads it into the MCP registrar so MCP
|
|
130
|
+
* events carry the result metadata only that layer knows.
|
|
131
|
+
*/
|
|
132
|
+
onToolCall?: OnToolCall;
|
|
112
133
|
}
|
|
113
134
|
/**
|
|
114
135
|
* A Silkweave Nest adapter. Each transport (REST, tRPC, MCP) implements this
|
|
@@ -161,12 +182,20 @@ interface SilkweaveModuleOptions {
|
|
|
161
182
|
/**
|
|
162
183
|
* Default MCP result format for every `@Mcp` tool - `'json'` (compact JSON,
|
|
163
184
|
* `jsonToolResult`) or `'smart'` (inline small / embedded-resource large,
|
|
164
|
-
* `smartToolResult`). Defaults to `'
|
|
165
|
-
* overrides this, and a client's per-call
|
|
185
|
+
* `smartToolResult`). Defaults to `'json'` (since 3.2; was `'smart'`). A
|
|
186
|
+
* per-method `@Mcp({ result })` overrides this, and a client's per-call
|
|
187
|
+
* `_meta.disposition` overrides both.
|
|
166
188
|
*/
|
|
167
189
|
defaultResult?: 'json' | 'smart';
|
|
190
|
+
/**
|
|
191
|
+
* Class token of a `SilkweaveTelemetry` provider, resolved through DI at
|
|
192
|
+
* call time (so it can inject your logger/config). One `onToolCall` event
|
|
193
|
+
* fires per tool/procedure invocation across MCP and tRPC - see
|
|
194
|
+
* `SilkweaveTelemetry` for the seam split and event fields.
|
|
195
|
+
*/
|
|
196
|
+
telemetry?: Type<SilkweaveTelemetry>;
|
|
168
197
|
}
|
|
169
198
|
declare const SILKWEAVE_MODULE_OPTIONS = "__silkweave_module_options__";
|
|
170
199
|
//#endregion
|
|
171
|
-
export {
|
|
172
|
-
//# sourceMappingURL=types-
|
|
200
|
+
export { openapiSchemaToField as _, SilkweaveTelemetry as a, typeTokenToBase as b, buildOpenApiLookup as c, apiPropertyToField as d, classValidatorToField as f, normalizeEnum as g, mergeField as h, SilkweaveModuleOptions as i, openApiFields as l, fieldToZod as m, NestSilkweaveAdapter as n, OpenApiDocument as o, designTypeToField as p, SILKWEAVE_MODULE_OPTIONS as r, OpenApiLookup as s, NestAdapterRegisterContext as t, FieldDesc as u, reflectDtoFields as v, unreflectedFields as x, swaggerParamToField as y };
|
|
201
|
+
//# sourceMappingURL=types-6rbW7fLE.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-6rbW7fLE.d.mts","names":[],"sources":["../src/lib/reflect/schema.ts","../src/lib/reflect/openapi.ts","../src/lib/types.ts"],"mappings":";;;;;;;;;;;AAeA;;UAAiB,SAAA;EACf,IAAA;EACA,QAAA;EAAA;EAEA,QAAA;EACA,WAAA;EACA,IAAA;EACA,KAAA,GAAQ,SAAA;EACR,GAAA;EACA,GAAA;EACA,SAAA;EACA,SAAA;EACA,MAAA;EACA,OAAA;AAAA;;iBAac,UAAA,CAAW,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,SAAA,GAAY,SAAA;AAA9D;AAAA,iBA2CgB,UAAA,CAAW,CAAA,EAAG,SAAA,GAAY,CAAA,CAAE,OAAA;;iBAe5B,aAAA,CAAc,KAAA;;iBAWd,eAAA,CAAgB,IAAA,YAAgB,SAAA;;iBAkBhC,iBAAA,CAAkB,IAAA,YAAgB,SAAA;;iBAQlC,mBAAA,CAAoB,CAAA,EAAG,MAAA,gBAAsB,SAAA;;iBAgB7C,kBAAA,CAAmB,CAAA,EAAG,MAAA,gBAAsB,SAAA;;iBA6D5C,qBAAA,CAAsB,KAAA,EAAO,KAAA;EAAQ,IAAA;EAAe,IAAA;EAAe,WAAA;AAAA,KAA6B,SAAA;;iBAOhG,oBAAA,CAAqB,MAAA,EAAQ,MAAA,gBAAsB,SAAA;;;;;;AAzHnE;;iBAsJgB,gBAAA,CAAiB,OAAA,QAAe,MAAA,SAAe,SAAA;;;AA3I/D;;;;;iBA6KgB,iBAAA,CAAkB,MAAA,EAAQ,MAAA,SAAe,SAAA;;;;;;;;UCnRxC,eAAA;EACf,KAAA,GAAQ,MAAA,SAAe,MAAA;EACvB,UAAA;IAAe,OAAA,GAAU,MAAA;EAAA;AAAA;AAAA,UAGV,aAAA;EACf,GAAA,EAAK,eAAA;EDOL;ECLA,UAAA,EAAY,GAAA;AAAA;;iBAIE,kBAAA,CAAmB,GAAA,EAAK,eAAA,GAAkB,aAAA;;;;;;;iBAwC1C,aAAA,CAAc,MAAA,EAAQ,aAAA,EAAe,MAAA,UAAgB,WAAA,WAAsB,MAAA,SAAe,SAAA;;;;;AD7C1G;;;;;;;;;;UEEiB,kBAAA;EACf,UAAA,CAAW,KAAA,EAAO,aAAA,UAAuB,OAAA;AAAA;;;;;;;AFuB3C;UEbiB,0BAAA;;EAEf,WAAA,EAAa,WAAA,CAAY,eAAA;EFWuB;EEThD,gBAAA,EAAkB,gBAAA;EFSmD;EEPrE,WAAA,EAAa,gBAAA;EFOkB;EEL/B,OAAA,EAAS,MAAA;EFKuC;;;;;EEChD,UAAA,GAAa,UAAA;AAAA;;;;;;;;UAUE,oBAAA;EF+CD;EAAA,SE7CL,IAAA;;WAEA,QAAA;EF2CiC;AAW5C;;;;EAX4C,SErCjC,UAAA;EFkEK;EEhEd,QAAA,CAAS,GAAA,EAAK,0BAAA;AAAA;AAAA,UAGC,sBAAA;EF6D0C;EE3DzD,SAAA,EAAW,gBAAA;EFmEsB;EEjEjC,QAAA,EAAU,oBAAA;EFiE0D;EE/DpE,OAAA,GAAU,MAAA;EF+DwB;;;;AAgBpC;;EExEE,OAAA,GAAU,eAAA;EFwEyD;;;;;;AA6DrE;;;;;;EExHE,YAAA,GAAe,IAAA,CAAK,WAAA;EFwH6D;;;;;AAOnF;;EEvHE,aAAA;EFuH0E;;;;;;EEhH1E,SAAA,GAAY,IAAA,CAAK,kBAAA;AAAA;AAAA,cAGN,wBAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silkweave/nestjs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Silkweave NestJS Adapter",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://www.silkweave.dev",
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"@trpc/server": "^11.7.1",
|
|
48
48
|
"class-validator": "^0.14.0 || ^0.15.0",
|
|
49
49
|
"rxjs": "^7.0.0",
|
|
50
|
-
"@silkweave/mcp": "^3.
|
|
51
|
-
"@silkweave/trpc": "^3.
|
|
52
|
-
"@silkweave/typegen": "^3.
|
|
50
|
+
"@silkweave/mcp": "^3.2.0",
|
|
51
|
+
"@silkweave/trpc": "^3.2.0",
|
|
52
|
+
"@silkweave/typegen": "^3.2.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@nestjs/swagger": {
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"cors": "^2.8.6",
|
|
76
76
|
"express": "^5.2.1",
|
|
77
77
|
"zod": "^3.25.0",
|
|
78
|
-
"@silkweave/core": "3.
|
|
78
|
+
"@silkweave/core": "3.2.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@eslint/js": "^10.0.1",
|
|
@@ -96,10 +96,10 @@
|
|
|
96
96
|
"typescript": "^5.9.3",
|
|
97
97
|
"typescript-eslint": "^8.56.1",
|
|
98
98
|
"vitest": "^4.1.9",
|
|
99
|
-
"@silkweave/
|
|
100
|
-
"@silkweave/trpc": "3.
|
|
101
|
-
"@silkweave/typegen": "3.
|
|
102
|
-
"@silkweave/
|
|
99
|
+
"@silkweave/auth": "3.2.0",
|
|
100
|
+
"@silkweave/trpc": "3.2.0",
|
|
101
|
+
"@silkweave/typegen": "3.2.0",
|
|
102
|
+
"@silkweave/mcp": "3.2.0"
|
|
103
103
|
},
|
|
104
104
|
"scripts": {
|
|
105
105
|
"clean": "rimraf build",
|