nestjs-apcore 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +304 -0
  2. package/dist/bridge/binding-loader.d.ts +33 -0
  3. package/dist/bridge/binding-loader.d.ts.map +1 -0
  4. package/dist/bridge/binding-loader.js +118 -0
  5. package/dist/bridge/binding-loader.js.map +1 -0
  6. package/dist/bridge/index.d.ts +3 -0
  7. package/dist/bridge/index.d.ts.map +1 -0
  8. package/dist/bridge/index.js +2 -0
  9. package/dist/bridge/index.js.map +1 -0
  10. package/dist/constants.d.ts +6 -0
  11. package/dist/constants.d.ts.map +1 -0
  12. package/dist/constants.js +8 -0
  13. package/dist/constants.js.map +1 -0
  14. package/dist/core/apcore-executor.service.d.ts +42 -0
  15. package/dist/core/apcore-executor.service.d.ts.map +1 -0
  16. package/dist/core/apcore-executor.service.js +68 -0
  17. package/dist/core/apcore-executor.service.js.map +1 -0
  18. package/dist/core/apcore-registry.service.d.ts +52 -0
  19. package/dist/core/apcore-registry.service.d.ts.map +1 -0
  20. package/dist/core/apcore-registry.service.js +181 -0
  21. package/dist/core/apcore-registry.service.js.map +1 -0
  22. package/dist/core/apcore.module.d.ts +27 -0
  23. package/dist/core/apcore.module.d.ts.map +1 -0
  24. package/dist/core/apcore.module.js +105 -0
  25. package/dist/core/apcore.module.js.map +1 -0
  26. package/dist/decorators/ap-context.decorator.d.ts +2 -0
  27. package/dist/decorators/ap-context.decorator.d.ts.map +1 -0
  28. package/dist/decorators/ap-context.decorator.js +9 -0
  29. package/dist/decorators/ap-context.decorator.js.map +1 -0
  30. package/dist/decorators/ap-module.decorator.d.ts +3 -0
  31. package/dist/decorators/ap-module.decorator.d.ts.map +1 -0
  32. package/dist/decorators/ap-module.decorator.js +7 -0
  33. package/dist/decorators/ap-module.decorator.js.map +1 -0
  34. package/dist/decorators/ap-tool-scanner.service.d.ts +28 -0
  35. package/dist/decorators/ap-tool-scanner.service.d.ts.map +1 -0
  36. package/dist/decorators/ap-tool-scanner.service.js +166 -0
  37. package/dist/decorators/ap-tool-scanner.service.js.map +1 -0
  38. package/dist/decorators/ap-tool.decorator.d.ts +3 -0
  39. package/dist/decorators/ap-tool.decorator.d.ts.map +1 -0
  40. package/dist/decorators/ap-tool.decorator.js +7 -0
  41. package/dist/decorators/ap-tool.decorator.js.map +1 -0
  42. package/dist/decorators/index.d.ts +4 -0
  43. package/dist/decorators/index.d.ts.map +1 -0
  44. package/dist/decorators/index.js +4 -0
  45. package/dist/decorators/index.js.map +1 -0
  46. package/dist/index.d.ts +23 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +41 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/mcp/apcore-mcp.module.d.ts +28 -0
  51. package/dist/mcp/apcore-mcp.module.d.ts.map +1 -0
  52. package/dist/mcp/apcore-mcp.module.js +77 -0
  53. package/dist/mcp/apcore-mcp.module.js.map +1 -0
  54. package/dist/mcp/apcore-mcp.service.d.ts +53 -0
  55. package/dist/mcp/apcore-mcp.service.d.ts.map +1 -0
  56. package/dist/mcp/apcore-mcp.service.js +148 -0
  57. package/dist/mcp/apcore-mcp.service.js.map +1 -0
  58. package/dist/schema/adapters/dto.adapter.d.ts +44 -0
  59. package/dist/schema/adapters/dto.adapter.d.ts.map +1 -0
  60. package/dist/schema/adapters/dto.adapter.js +191 -0
  61. package/dist/schema/adapters/dto.adapter.js.map +1 -0
  62. package/dist/schema/adapters/json-schema.adapter.d.ts +30 -0
  63. package/dist/schema/adapters/json-schema.adapter.d.ts.map +1 -0
  64. package/dist/schema/adapters/json-schema.adapter.js +48 -0
  65. package/dist/schema/adapters/json-schema.adapter.js.map +1 -0
  66. package/dist/schema/adapters/schema-adapter.interface.d.ts +21 -0
  67. package/dist/schema/adapters/schema-adapter.interface.d.ts.map +1 -0
  68. package/dist/schema/adapters/schema-adapter.interface.js +2 -0
  69. package/dist/schema/adapters/schema-adapter.interface.js.map +1 -0
  70. package/dist/schema/adapters/typebox.adapter.d.ts +32 -0
  71. package/dist/schema/adapters/typebox.adapter.d.ts.map +1 -0
  72. package/dist/schema/adapters/typebox.adapter.js +46 -0
  73. package/dist/schema/adapters/typebox.adapter.js.map +1 -0
  74. package/dist/schema/adapters/zod.adapter.d.ts +16 -0
  75. package/dist/schema/adapters/zod.adapter.d.ts.map +1 -0
  76. package/dist/schema/adapters/zod.adapter.js +184 -0
  77. package/dist/schema/adapters/zod.adapter.js.map +1 -0
  78. package/dist/schema/schema-extractor.service.d.ts +58 -0
  79. package/dist/schema/schema-extractor.service.d.ts.map +1 -0
  80. package/dist/schema/schema-extractor.service.js +100 -0
  81. package/dist/schema/schema-extractor.service.js.map +1 -0
  82. package/dist/types.d.ts +106 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/types.js +2 -0
  85. package/dist/types.js.map +1 -0
  86. package/dist/utils/id-generator.d.ts +41 -0
  87. package/dist/utils/id-generator.d.ts.map +1 -0
  88. package/dist/utils/id-generator.js +87 -0
  89. package/dist/utils/id-generator.js.map +1 -0
  90. package/package.json +100 -0
package/README.md ADDED
@@ -0,0 +1,304 @@
1
+ # nestjs-apcore
2
+
3
+ NestJS adapter for the [apcore](https://github.com/aipartnerup/apcore-js) AI-Perceivable module ecosystem. Turn your existing NestJS services into AI-callable [MCP](https://modelcontextprotocol.io/) tools and OpenAI-compatible function definitions — with zero changes to your business logic.
4
+
5
+ ## Features
6
+
7
+ - **Decorator-driven** — Mark methods with `@ApTool` and classes with `@ApModule` to expose them as AI tools
8
+ - **Auto-discovery** — `ApToolScannerService` scans all providers at startup and registers decorated methods automatically
9
+ - **Multi-schema support** — TypeBox, Zod, class-validator DTOs, and plain JSON Schema, auto-detected via a priority chain
10
+ - **MCP server built-in** — Serve tools over stdio, Streamable HTTP, or SSE transports with optional Tool Explorer UI
11
+ - **OpenAI-compatible** — Convert registered tools to OpenAI function-calling format with `toOpenaiTools()`
12
+ - **YAML bindings** — Register tools declaratively from YAML files without touching source code
13
+ - **Dual access** — Services remain injectable into REST controllers while simultaneously available as MCP tools
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install nestjs-apcore apcore-js apcore-mcp @modelcontextprotocol/sdk js-yaml
19
+ ```
20
+
21
+ **Peer dependencies** (required):
22
+
23
+ ```bash
24
+ npm install @nestjs/common @nestjs/core reflect-metadata rxjs
25
+ ```
26
+
27
+ **Optional** (for schema adapters):
28
+
29
+ ```bash
30
+ npm install zod # ZodAdapter
31
+ npm install class-validator class-transformer # DtoAdapter
32
+ npm install @sinclair/typebox # TypeBoxAdapter (recommended)
33
+ ```
34
+
35
+ **Requirements:** Node.js >= 18, NestJS >= 10
36
+
37
+ ## Quick Start
38
+
39
+ ### 1. Wire up modules
40
+
41
+ ```typescript
42
+ // app.module.ts
43
+ import { Module } from '@nestjs/common';
44
+ import { ApcoreModule, ApcoreMcpModule, ApToolScannerService } from 'nestjs-apcore';
45
+
46
+ @Module({
47
+ imports: [
48
+ ApcoreModule.forRoot({}),
49
+ ApcoreMcpModule.forRoot({
50
+ transport: 'streamable-http',
51
+ port: 8000,
52
+ name: 'my-app',
53
+ version: '1.0.0',
54
+ explorer: true,
55
+ }),
56
+ TodoModule,
57
+ ],
58
+ providers: [ApToolScannerService],
59
+ })
60
+ export class AppModule {}
61
+ ```
62
+
63
+ ### 2. Decorate your services
64
+
65
+ ```typescript
66
+ // todo.service.ts
67
+ import { Injectable } from '@nestjs/common';
68
+ import { Type } from '@sinclair/typebox';
69
+ import { ApModule, ApTool } from 'nestjs-apcore';
70
+
71
+ @ApModule({ namespace: 'todo', description: 'Todo list management' })
72
+ @Injectable()
73
+ export class TodoService {
74
+ private todos = [];
75
+
76
+ @ApTool({
77
+ description: 'List all todos, optionally filtered by status',
78
+ inputSchema: Type.Object({
79
+ done: Type.Optional(Type.Boolean()),
80
+ }),
81
+ annotations: { readonly: true, idempotent: true },
82
+ tags: ['todo', 'query'],
83
+ })
84
+ list(inputs: Record<string, unknown>) {
85
+ const { done } = inputs;
86
+ const filtered = done !== undefined
87
+ ? this.todos.filter((t) => t.done === done)
88
+ : this.todos;
89
+ return { todos: filtered, count: filtered.length };
90
+ }
91
+
92
+ @ApTool({
93
+ description: 'Create a new todo item',
94
+ inputSchema: Type.Object({
95
+ title: Type.String(),
96
+ }),
97
+ annotations: { readonly: false },
98
+ tags: ['todo', 'mutate'],
99
+ })
100
+ create(inputs: Record<string, unknown>) {
101
+ const todo = { id: this.todos.length + 1, title: inputs.title, done: false };
102
+ this.todos.push(todo);
103
+ return todo;
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### 3. Boot the app
109
+
110
+ ```typescript
111
+ // main.ts
112
+ import { NestFactory } from '@nestjs/core';
113
+ import { AppModule } from './app.module';
114
+
115
+ async function bootstrap() {
116
+ const app = await NestFactory.create(AppModule);
117
+ await app.listen(3000);
118
+ // MCP server starts automatically on port 8000
119
+ }
120
+ bootstrap();
121
+ ```
122
+
123
+ Your service is now available as:
124
+ - **REST API** at `http://localhost:3000` (via NestJS controllers)
125
+ - **MCP server** at `http://localhost:8000` (for AI agents)
126
+ - **Tool Explorer** at `http://localhost:8000/explorer/` (interactive web UI)
127
+
128
+ ## API Reference
129
+
130
+ ### Modules
131
+
132
+ #### `ApcoreModule`
133
+
134
+ Provides the core `Registry` and `Executor` as NestJS singletons.
135
+
136
+ ```typescript
137
+ // Sync
138
+ ApcoreModule.forRoot({ extensionsDir?, acl?, middleware?, bindings? })
139
+
140
+ // Async (e.g. inject ConfigService)
141
+ ApcoreModule.forRootAsync({ imports, useFactory, inject })
142
+ ```
143
+
144
+ #### `ApcoreMcpModule`
145
+
146
+ Configures and starts the MCP server.
147
+
148
+ The MCP server runs **standalone on its own port** (e.g. 8000), separate from NestJS's REST server (e.g. 3000). Both share the same Registry and Executor instances.
149
+
150
+ ```typescript
151
+ ApcoreMcpModule.forRoot({
152
+ transport: 'stdio' | 'streamable-http' | 'sse',
153
+ host?: string,
154
+ port?: number,
155
+ name?: string,
156
+ version?: string,
157
+ tags?: string[], // only expose tools matching these tags
158
+ prefix?: string, // only expose tools with this ID prefix
159
+ explorer?: boolean, // enable Tool Explorer web UI
160
+ explorerPrefix?: string, // URL prefix for the Explorer
161
+ allowExecute?: boolean, // allow execution from Explorer
162
+ dynamic?: boolean, // enable dynamic tool list updates
163
+ validateInputs?: boolean,
164
+ logLevel?: 'DEBUG' | 'INFO' | 'WARNING' | 'ERROR' | 'CRITICAL',
165
+ authenticator?: Authenticator, // JWT or custom auth
166
+ exemptPaths?: string[], // paths that bypass auth (default: ['/health', '/metrics'])
167
+ metricsCollector?: { exportPrometheus(): string },
168
+ onStartup?: () => void | Promise<void>,
169
+ onShutdown?: () => void | Promise<void>,
170
+ })
171
+ ```
172
+
173
+ ### Decorators
174
+
175
+ | Decorator | Target | Description |
176
+ |---|---|---|
177
+ | `@ApModule(opts)` | Class | Sets namespace for all `@ApTool` methods (e.g. `todo`) |
178
+ | `@ApTool(opts)` | Method | Registers the method as an AI-callable tool |
179
+ | `@ApContext()` | Parameter | Injects the apcore `Context` object (callerId, trace info) |
180
+
181
+ #### `@ApTool` options
182
+
183
+ ```typescript
184
+ @ApTool({
185
+ description: string, // required
186
+ id?: string, // auto-generated in snake_case if omitted (e.g. 'email.send_batch')
187
+ inputSchema?: any, // TypeBox, Zod, DTO class, or JSON Schema
188
+ outputSchema?: any,
189
+ annotations?: {
190
+ readonly?: boolean,
191
+ destructive?: boolean,
192
+ idempotent?: boolean,
193
+ requiresApproval?: boolean,
194
+ openWorld?: boolean,
195
+ streaming?: boolean,
196
+ },
197
+ tags?: string[],
198
+ documentation?: string,
199
+ examples?: ApToolExample[],
200
+ })
201
+ ```
202
+
203
+ ### Services
204
+
205
+ | Service | Description |
206
+ |---|---|
207
+ | `ApcoreRegistryService` | Register/unregister tools, query the registry |
208
+ | `ApcoreExecutorService` | Execute tools: `call()`, `stream()`, `validate()` |
209
+ | `ApcoreMcpService` | MCP server lifecycle: `start()`, `stop()`, `restart()`, `toOpenaiTools()` |
210
+ | `ApToolScannerService` | Auto-discovers and registers `@ApTool` decorated methods at startup |
211
+
212
+ ### Schema Adapters
213
+
214
+ Schemas are auto-detected and converted via a priority chain:
215
+
216
+ | Adapter | Priority | Input |
217
+ |---|---|---|
218
+ | TypeBoxAdapter | 100 | `@sinclair/typebox` schemas |
219
+ | ZodAdapter | 50 | Zod schemas |
220
+ | JsonSchemaAdapter | 30 | Plain JSON Schema objects |
221
+ | DtoAdapter | 20 | `class-validator` decorated DTO classes |
222
+
223
+ ### YAML Bindings
224
+
225
+ Register tools without decorators:
226
+
227
+ ```yaml
228
+ bindings:
229
+ - module_id: email.send
230
+ target: EmailService.send
231
+ description: Send an email
232
+ input_schema:
233
+ type: object
234
+ properties:
235
+ to: { type: string }
236
+ subject: { type: string }
237
+ body: { type: string }
238
+ tags: [email, mutate]
239
+ annotations:
240
+ readonly: false
241
+ ```
242
+
243
+ ### JWT Authentication
244
+
245
+ Enable JWT auth by passing a `JWTAuthenticator` to `ApcoreMcpModule`. The Explorer UI and `/health` endpoint are always exempt.
246
+
247
+ ```typescript
248
+ import { JWTAuthenticator, getCurrentIdentity } from 'nestjs-apcore';
249
+
250
+ // In app.module.ts
251
+ const jwtSecret = process.env.JWT_SECRET;
252
+ ApcoreMcpModule.forRoot({
253
+ transport: 'streamable-http',
254
+ port: 8000,
255
+ authenticator: jwtSecret ? new JWTAuthenticator({ secret: jwtSecret }) : undefined,
256
+ })
257
+
258
+ // Inside any @ApTool method
259
+ list(inputs: Record<string, unknown>) {
260
+ const caller = getCurrentIdentity()?.id ?? 'anonymous';
261
+ return { items: [...], caller };
262
+ }
263
+ ```
264
+
265
+ `JWTAuthenticator` options: `secret`, `algorithms` (default `['HS256']`), `audience`, `issuer`, `claimMapping`, `requireClaims`, `requireAuth` (default `true`).
266
+
267
+ ### Re-exported Utilities
268
+
269
+ From `apcore-mcp`:
270
+ - `reportProgress`, `elicit`, `createBridgeContext`
271
+ - `JWTAuthenticator`, `getCurrentIdentity`, `identityStorage`
272
+
273
+ ## Examples
274
+
275
+ The `demo/` directory contains a full working app with Todo and Weather services:
276
+
277
+ ```bash
278
+ cd demo
279
+ npm install
280
+ npx tsx src/main.ts
281
+ ```
282
+
283
+ Or with Docker:
284
+
285
+ ```bash
286
+ cd demo
287
+ docker compose up --build
288
+ ```
289
+
290
+ ## Scripts
291
+
292
+ | Command | Description |
293
+ |---|---|
294
+ | `npm run build` | Compile TypeScript |
295
+ | `npm run dev` | Watch mode compilation |
296
+ | `npm test` | Run tests (vitest) |
297
+ | `npm run test:watch` | Run tests in watch mode |
298
+ | `npm run test:coverage` | Run tests with coverage |
299
+ | `npm run typecheck` | Type-check without emitting |
300
+ | `npm run lint` | Lint source and tests |
301
+
302
+ ## License
303
+
304
+ Apache-2.0
@@ -0,0 +1,33 @@
1
+ import { ApcoreRegistryService } from '../core/apcore-registry.service.js';
2
+ /**
3
+ * A function that resolves a class name to a service instance.
4
+ */
5
+ export type InstanceProvider = (className: string) => object | undefined;
6
+ /**
7
+ * NestJS injectable service that loads YAML binding files and registers
8
+ * modules with the ApcoreRegistryService.
9
+ *
10
+ * Each binding maps a module_id to a "ClassName.methodName" target,
11
+ * optionally providing schema, annotations, tags, and documentation.
12
+ */
13
+ export declare class ApBindingLoader {
14
+ private readonly registry;
15
+ private readonly instanceProvider?;
16
+ constructor(registry: ApcoreRegistryService, instanceProvider?: InstanceProvider | undefined);
17
+ /**
18
+ * Parse YAML content describing bindings and register each as a
19
+ * FunctionModule with the registry.
20
+ *
21
+ * @param content - Raw YAML string
22
+ * @returns Array of registered module IDs
23
+ */
24
+ loadFromString(content: string): string[];
25
+ /**
26
+ * Read a YAML file from disk and register its bindings.
27
+ *
28
+ * @param filePath - Absolute or relative path to the YAML file
29
+ * @returns Array of registered module IDs
30
+ */
31
+ loadFromFile(filePath: string): Promise<string[]>;
32
+ }
33
+ //# sourceMappingURL=binding-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-loader.d.ts","sourceRoot":"","sources":["../../src/bridge/binding-loader.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAuB3E;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAmBzE;;;;;;GAMG;AACH,qBACa,eAAe;IAGxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAGzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAHjB,QAAQ,EAAE,qBAAqB,EAG/B,gBAAgB,CAAC,EAAE,gBAAgB,YAAA;IAGtD;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAkDzC;;;;;OAKG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAIxD"}
@@ -0,0 +1,118 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Injectable, Inject, Optional } from '@nestjs/common';
14
+ import * as yaml from 'js-yaml';
15
+ import { readFile } from 'node:fs/promises';
16
+ import { Type as t } from '@sinclair/typebox';
17
+ import { FunctionModule } from 'apcore-js';
18
+ import { ApcoreRegistryService } from '../core/apcore-registry.service.js';
19
+ /**
20
+ * Normalize a method return value to a Record<string, unknown>.
21
+ *
22
+ * - null / undefined -> {}
23
+ * - non-object (string, number, boolean) or array -> { result: value }
24
+ * - object -> returned as-is
25
+ */
26
+ function normalizeReturnValue(value) {
27
+ if (value == null) {
28
+ return {};
29
+ }
30
+ if (typeof value !== 'object' || Array.isArray(value)) {
31
+ return { result: value };
32
+ }
33
+ return value;
34
+ }
35
+ /**
36
+ * NestJS injectable service that loads YAML binding files and registers
37
+ * modules with the ApcoreRegistryService.
38
+ *
39
+ * Each binding maps a module_id to a "ClassName.methodName" target,
40
+ * optionally providing schema, annotations, tags, and documentation.
41
+ */
42
+ let ApBindingLoader = class ApBindingLoader {
43
+ registry;
44
+ instanceProvider;
45
+ constructor(registry, instanceProvider) {
46
+ this.registry = registry;
47
+ this.instanceProvider = instanceProvider;
48
+ }
49
+ /**
50
+ * Parse YAML content describing bindings and register each as a
51
+ * FunctionModule with the registry.
52
+ *
53
+ * @param content - Raw YAML string
54
+ * @returns Array of registered module IDs
55
+ */
56
+ loadFromString(content) {
57
+ const parsed = yaml.load(content);
58
+ const bindings = parsed?.bindings ?? [];
59
+ const ids = [];
60
+ for (const binding of bindings) {
61
+ const moduleId = binding.module_id;
62
+ const [className, methodName] = binding.target.split('.');
63
+ // Attempt to resolve the service instance
64
+ let instance;
65
+ if (this.instanceProvider) {
66
+ instance = this.instanceProvider(className);
67
+ }
68
+ // Build the execute function
69
+ let execute;
70
+ if (instance && methodName in instance) {
71
+ execute = async (inputs) => {
72
+ const raw = await instance[methodName](inputs);
73
+ return normalizeReturnValue(raw);
74
+ };
75
+ }
76
+ else {
77
+ execute = async () => {
78
+ return {
79
+ error: `No instance available for ${className}.${methodName}`,
80
+ };
81
+ };
82
+ }
83
+ const funcModule = new FunctionModule({
84
+ moduleId,
85
+ description: binding.description,
86
+ inputSchema: binding.input_schema ?? t.Object({}),
87
+ outputSchema: binding.output_schema ?? t.Object({}),
88
+ tags: binding.tags ?? null,
89
+ annotations: binding.annotations ?? null,
90
+ documentation: binding.documentation ?? null,
91
+ examples: null,
92
+ execute,
93
+ });
94
+ this.registry.register(moduleId, funcModule);
95
+ ids.push(moduleId);
96
+ }
97
+ return ids;
98
+ }
99
+ /**
100
+ * Read a YAML file from disk and register its bindings.
101
+ *
102
+ * @param filePath - Absolute or relative path to the YAML file
103
+ * @returns Array of registered module IDs
104
+ */
105
+ async loadFromFile(filePath) {
106
+ const content = await readFile(filePath, 'utf-8');
107
+ return this.loadFromString(content);
108
+ }
109
+ };
110
+ ApBindingLoader = __decorate([
111
+ Injectable(),
112
+ __param(0, Inject(ApcoreRegistryService)),
113
+ __param(1, Optional()),
114
+ __param(1, Inject('APCORE_INSTANCE_PROVIDER')),
115
+ __metadata("design:paramtypes", [ApcoreRegistryService, Function])
116
+ ], ApBindingLoader);
117
+ export { ApBindingLoader };
118
+ //# sourceMappingURL=binding-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding-loader.js","sourceRoot":"","sources":["../../src/bridge/binding-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ApBindingLoader } from './binding-loader.js';
2
+ export type { InstanceProvider } from './binding-loader.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ApBindingLoader } from './binding-loader.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bridge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const APCORE_MODULE_OPTIONS: "APCORE_MODULE_OPTIONS";
2
+ export declare const APCORE_MCP_MODULE_OPTIONS: "APCORE_MCP_MODULE_OPTIONS";
3
+ export declare const AP_TOOL_METADATA_KEY: "apcore:tool";
4
+ export declare const AP_MODULE_METADATA_KEY: "apcore:module";
5
+ export declare const AP_CONTEXT_METADATA_KEY: "apcore:context";
6
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,qBAAqB,EAAG,uBAAgC,CAAC;AACtE,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AAG9E,eAAO,MAAM,oBAAoB,EAAG,aAAsB,CAAC;AAC3D,eAAO,MAAM,sBAAsB,EAAG,eAAwB,CAAC;AAC/D,eAAO,MAAM,uBAAuB,EAAG,gBAAyB,CAAC"}
@@ -0,0 +1,8 @@
1
+ // NestJS dependency-injection tokens
2
+ export const APCORE_MODULE_OPTIONS = 'APCORE_MODULE_OPTIONS';
3
+ export const APCORE_MCP_MODULE_OPTIONS = 'APCORE_MCP_MODULE_OPTIONS';
4
+ // Reflect metadata keys used by decorators
5
+ export const AP_TOOL_METADATA_KEY = 'apcore:tool';
6
+ export const AP_MODULE_METADATA_KEY = 'apcore:module';
7
+ export const AP_CONTEXT_METADATA_KEY = 'apcore:context';
8
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AACtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,2BAAoC,CAAC;AAE9E,2CAA2C;AAC3C,MAAM,CAAC,MAAM,oBAAoB,GAAG,aAAsB,CAAC;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAwB,CAAC;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,gBAAyB,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { Executor } from 'apcore-js';
2
+ import type { Context, ValidationResult } from 'apcore-js';
3
+ /**
4
+ * NestJS-injectable wrapper around the upstream apcore-js {@link Executor}.
5
+ *
6
+ * All mutation-free delegation methods normalise `null` / `undefined` inputs
7
+ * to an empty object (`{}`) so callers never need to worry about nullability.
8
+ */
9
+ export declare class ApcoreExecutorService {
10
+ private readonly executor;
11
+ constructor(executor: Executor);
12
+ /** Access the underlying apcore-js Executor directly. */
13
+ get raw(): Executor;
14
+ /**
15
+ * Execute a module by ID.
16
+ *
17
+ * @param moduleId Fully-qualified module identifier (e.g. `"email.send"`).
18
+ * @param inputs Key/value inputs for the module. `null` and `undefined`
19
+ * are normalised to `{}`.
20
+ * @param context Optional execution context (identity, trace, etc.).
21
+ */
22
+ call(moduleId: string, inputs?: Record<string, unknown> | null, context?: Context | null): Promise<Record<string, unknown>>;
23
+ /**
24
+ * Stream execution results from a module.
25
+ *
26
+ * Yields each chunk produced by the upstream `executor.stream()` generator.
27
+ *
28
+ * @param moduleId Fully-qualified module identifier.
29
+ * @param inputs Key/value inputs for the module. `null` and `undefined`
30
+ * are normalised to `{}`.
31
+ * @param context Optional execution context.
32
+ */
33
+ stream(moduleId: string, inputs?: Record<string, unknown> | null, context?: Context | null): AsyncGenerator<Record<string, unknown>>;
34
+ /**
35
+ * Validate inputs against a module's input schema without executing it.
36
+ *
37
+ * @param moduleId Fully-qualified module identifier.
38
+ * @param inputs Key/value inputs to validate.
39
+ */
40
+ validate(moduleId: string, inputs: Record<string, unknown>): ValidationResult;
41
+ }
42
+ //# sourceMappingURL=apcore-executor.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apcore-executor.service.d.ts","sourceRoot":"","sources":["../../src/core/apcore-executor.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE3D;;;;;GAKG;AACH,qBACa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,QAAQ;IAM/C,yDAAyD;IACzD,IAAI,GAAG,IAAI,QAAQ,CAElB;IAED;;;;;;;OAOG;IACG,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACvB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAInC;;;;;;;;;OASG;IACI,MAAM,CACX,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACvB,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI1C;;;;;OAKG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,gBAAgB;CAGpB"}
@@ -0,0 +1,68 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable } from '@nestjs/common';
11
+ /**
12
+ * NestJS-injectable wrapper around the upstream apcore-js {@link Executor}.
13
+ *
14
+ * All mutation-free delegation methods normalise `null` / `undefined` inputs
15
+ * to an empty object (`{}`) so callers never need to worry about nullability.
16
+ */
17
+ let ApcoreExecutorService = class ApcoreExecutorService {
18
+ executor;
19
+ constructor(executor) {
20
+ this.executor = executor;
21
+ }
22
+ // -----------------------------------------------------------------------
23
+ // Public API
24
+ // -----------------------------------------------------------------------
25
+ /** Access the underlying apcore-js Executor directly. */
26
+ get raw() {
27
+ return this.executor;
28
+ }
29
+ /**
30
+ * Execute a module by ID.
31
+ *
32
+ * @param moduleId Fully-qualified module identifier (e.g. `"email.send"`).
33
+ * @param inputs Key/value inputs for the module. `null` and `undefined`
34
+ * are normalised to `{}`.
35
+ * @param context Optional execution context (identity, trace, etc.).
36
+ */
37
+ async call(moduleId, inputs, context) {
38
+ return this.executor.call(moduleId, inputs ?? {}, context);
39
+ }
40
+ /**
41
+ * Stream execution results from a module.
42
+ *
43
+ * Yields each chunk produced by the upstream `executor.stream()` generator.
44
+ *
45
+ * @param moduleId Fully-qualified module identifier.
46
+ * @param inputs Key/value inputs for the module. `null` and `undefined`
47
+ * are normalised to `{}`.
48
+ * @param context Optional execution context.
49
+ */
50
+ async *stream(moduleId, inputs, context) {
51
+ yield* this.executor.stream(moduleId, inputs ?? {}, context);
52
+ }
53
+ /**
54
+ * Validate inputs against a module's input schema without executing it.
55
+ *
56
+ * @param moduleId Fully-qualified module identifier.
57
+ * @param inputs Key/value inputs to validate.
58
+ */
59
+ validate(moduleId, inputs) {
60
+ return this.executor.validate(moduleId, inputs);
61
+ }
62
+ };
63
+ ApcoreExecutorService = __decorate([
64
+ Injectable(),
65
+ __metadata("design:paramtypes", [Function])
66
+ ], ApcoreExecutorService);
67
+ export { ApcoreExecutorService };
68
+ //# sourceMappingURL=apcore-executor.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apcore-executor.service.js","sourceRoot":"","sources":["../../src/core/apcore-executor.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAI5C;;;;;GAKG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IACH;IAA7B,YAA6B,QAAkB;QAAlB,aAAQ,GAAR,QAAQ,CAAU;IAAG,CAAC;IAEnD,0EAA0E;IAC1E,aAAa;IACb,0EAA0E;IAE1E,yDAAyD;IACzD,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,IAAI,CACR,QAAgB,EAChB,MAAuC,EACvC,OAAwB;QAExB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IAC7D,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,CAAC,MAAM,CACX,QAAgB,EAChB,MAAuC,EACvC,OAAwB;QAExB,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IAC/D,CAAC;IAED;;;;;OAKG;IACH,QAAQ,CACN,QAAgB,EAChB,MAA+B;QAE/B,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;CACF,CAAA;AA1DY,qBAAqB;IADjC,UAAU,EAAE;;GACA,qBAAqB,CA0DjC"}