@animalabs/agent-framework 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 (212) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/dist/src/agent.d.ts +130 -0
  4. package/dist/src/agent.d.ts.map +1 -0
  5. package/dist/src/agent.js +406 -0
  6. package/dist/src/agent.js.map +1 -0
  7. package/dist/src/api/mcp-server.d.ts +37 -0
  8. package/dist/src/api/mcp-server.d.ts.map +1 -0
  9. package/dist/src/api/mcp-server.js +598 -0
  10. package/dist/src/api/mcp-server.js.map +1 -0
  11. package/dist/src/api/server.d.ts +83 -0
  12. package/dist/src/api/server.d.ts.map +1 -0
  13. package/dist/src/api/server.js +785 -0
  14. package/dist/src/api/server.js.map +1 -0
  15. package/dist/src/api/types.d.ts +395 -0
  16. package/dist/src/api/types.d.ts.map +1 -0
  17. package/dist/src/api/types.js +5 -0
  18. package/dist/src/api/types.js.map +1 -0
  19. package/dist/src/framework.d.ts +309 -0
  20. package/dist/src/framework.d.ts.map +1 -0
  21. package/dist/src/framework.js +2309 -0
  22. package/dist/src/framework.js.map +1 -0
  23. package/dist/src/gate/event-gate.d.ts +75 -0
  24. package/dist/src/gate/event-gate.d.ts.map +1 -0
  25. package/dist/src/gate/event-gate.js +503 -0
  26. package/dist/src/gate/event-gate.js.map +1 -0
  27. package/dist/src/gate/index.d.ts +3 -0
  28. package/dist/src/gate/index.d.ts.map +1 -0
  29. package/dist/src/gate/index.js +2 -0
  30. package/dist/src/gate/index.js.map +1 -0
  31. package/dist/src/gate/types.d.ts +82 -0
  32. package/dist/src/gate/types.d.ts.map +1 -0
  33. package/dist/src/gate/types.js +9 -0
  34. package/dist/src/gate/types.js.map +1 -0
  35. package/dist/src/index.d.ts +17 -0
  36. package/dist/src/index.d.ts.map +1 -0
  37. package/dist/src/index.js +18 -0
  38. package/dist/src/index.js.map +1 -0
  39. package/dist/src/mcpl/channel-registry.d.ts +141 -0
  40. package/dist/src/mcpl/channel-registry.d.ts.map +1 -0
  41. package/dist/src/mcpl/channel-registry.js +647 -0
  42. package/dist/src/mcpl/channel-registry.js.map +1 -0
  43. package/dist/src/mcpl/checkpoint-manager.d.ts +79 -0
  44. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -0
  45. package/dist/src/mcpl/checkpoint-manager.js +430 -0
  46. package/dist/src/mcpl/checkpoint-manager.js.map +1 -0
  47. package/dist/src/mcpl/errors.d.ts +52 -0
  48. package/dist/src/mcpl/errors.d.ts.map +1 -0
  49. package/dist/src/mcpl/errors.js +93 -0
  50. package/dist/src/mcpl/errors.js.map +1 -0
  51. package/dist/src/mcpl/feature-set-manager.d.ts +91 -0
  52. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -0
  53. package/dist/src/mcpl/feature-set-manager.js +250 -0
  54. package/dist/src/mcpl/feature-set-manager.js.map +1 -0
  55. package/dist/src/mcpl/hook-orchestrator.d.ts +51 -0
  56. package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -0
  57. package/dist/src/mcpl/hook-orchestrator.js +217 -0
  58. package/dist/src/mcpl/hook-orchestrator.js.map +1 -0
  59. package/dist/src/mcpl/index.d.ts +14 -0
  60. package/dist/src/mcpl/index.d.ts.map +1 -0
  61. package/dist/src/mcpl/index.js +21 -0
  62. package/dist/src/mcpl/index.js.map +1 -0
  63. package/dist/src/mcpl/inference-router.d.ts +67 -0
  64. package/dist/src/mcpl/inference-router.d.ts.map +1 -0
  65. package/dist/src/mcpl/inference-router.js +249 -0
  66. package/dist/src/mcpl/inference-router.js.map +1 -0
  67. package/dist/src/mcpl/push-handler.d.ts +60 -0
  68. package/dist/src/mcpl/push-handler.d.ts.map +1 -0
  69. package/dist/src/mcpl/push-handler.js +162 -0
  70. package/dist/src/mcpl/push-handler.js.map +1 -0
  71. package/dist/src/mcpl/scope-manager.d.ts +76 -0
  72. package/dist/src/mcpl/scope-manager.d.ts.map +1 -0
  73. package/dist/src/mcpl/scope-manager.js +213 -0
  74. package/dist/src/mcpl/scope-manager.js.map +1 -0
  75. package/dist/src/mcpl/server-connection.d.ts +174 -0
  76. package/dist/src/mcpl/server-connection.d.ts.map +1 -0
  77. package/dist/src/mcpl/server-connection.js +559 -0
  78. package/dist/src/mcpl/server-connection.js.map +1 -0
  79. package/dist/src/mcpl/server-registry.d.ts +63 -0
  80. package/dist/src/mcpl/server-registry.d.ts.map +1 -0
  81. package/dist/src/mcpl/server-registry.js +119 -0
  82. package/dist/src/mcpl/server-registry.js.map +1 -0
  83. package/dist/src/mcpl/types.d.ts +755 -0
  84. package/dist/src/mcpl/types.d.ts.map +1 -0
  85. package/dist/src/mcpl/types.js +48 -0
  86. package/dist/src/mcpl/types.js.map +1 -0
  87. package/dist/src/module-registry.d.ts +93 -0
  88. package/dist/src/module-registry.d.ts.map +1 -0
  89. package/dist/src/module-registry.js +386 -0
  90. package/dist/src/module-registry.js.map +1 -0
  91. package/dist/src/modules/api/index.d.ts +22 -0
  92. package/dist/src/modules/api/index.d.ts.map +1 -0
  93. package/dist/src/modules/api/index.js +63 -0
  94. package/dist/src/modules/api/index.js.map +1 -0
  95. package/dist/src/modules/discord/discord-js-client.d.ts +58 -0
  96. package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -0
  97. package/dist/src/modules/discord/discord-js-client.js +273 -0
  98. package/dist/src/modules/discord/discord-js-client.js.map +1 -0
  99. package/dist/src/modules/discord/index.d.ts +82 -0
  100. package/dist/src/modules/discord/index.d.ts.map +1 -0
  101. package/dist/src/modules/discord/index.js +959 -0
  102. package/dist/src/modules/discord/index.js.map +1 -0
  103. package/dist/src/modules/discord/types.d.ts +327 -0
  104. package/dist/src/modules/discord/types.d.ts.map +1 -0
  105. package/dist/src/modules/discord/types.js +5 -0
  106. package/dist/src/modules/discord/types.js.map +1 -0
  107. package/dist/src/modules/index.d.ts +11 -0
  108. package/dist/src/modules/index.d.ts.map +1 -0
  109. package/dist/src/modules/index.js +7 -0
  110. package/dist/src/modules/index.js.map +1 -0
  111. package/dist/src/modules/workspace/index.d.ts +59 -0
  112. package/dist/src/modules/workspace/index.d.ts.map +1 -0
  113. package/dist/src/modules/workspace/index.js +831 -0
  114. package/dist/src/modules/workspace/index.js.map +1 -0
  115. package/dist/src/modules/workspace/sync.d.ts +48 -0
  116. package/dist/src/modules/workspace/sync.d.ts.map +1 -0
  117. package/dist/src/modules/workspace/sync.js +253 -0
  118. package/dist/src/modules/workspace/sync.js.map +1 -0
  119. package/dist/src/modules/workspace/types.d.ts +166 -0
  120. package/dist/src/modules/workspace/types.d.ts.map +1 -0
  121. package/dist/src/modules/workspace/types.js +5 -0
  122. package/dist/src/modules/workspace/types.js.map +1 -0
  123. package/dist/src/modules/workspace/watcher.d.ts +43 -0
  124. package/dist/src/modules/workspace/watcher.d.ts.map +1 -0
  125. package/dist/src/modules/workspace/watcher.js +120 -0
  126. package/dist/src/modules/workspace/watcher.js.map +1 -0
  127. package/dist/src/queue.d.ts +50 -0
  128. package/dist/src/queue.d.ts.map +1 -0
  129. package/dist/src/queue.js +95 -0
  130. package/dist/src/queue.js.map +1 -0
  131. package/dist/src/safe-slice.d.ts +8 -0
  132. package/dist/src/safe-slice.d.ts.map +1 -0
  133. package/dist/src/safe-slice.js +18 -0
  134. package/dist/src/safe-slice.js.map +1 -0
  135. package/dist/src/types/agent.d.ts +118 -0
  136. package/dist/src/types/agent.d.ts.map +1 -0
  137. package/dist/src/types/agent.js +2 -0
  138. package/dist/src/types/agent.js.map +1 -0
  139. package/dist/src/types/events.d.ts +220 -0
  140. package/dist/src/types/events.d.ts.map +1 -0
  141. package/dist/src/types/events.js +2 -0
  142. package/dist/src/types/events.js.map +1 -0
  143. package/dist/src/types/framework.d.ts +184 -0
  144. package/dist/src/types/framework.d.ts.map +1 -0
  145. package/dist/src/types/framework.js +2 -0
  146. package/dist/src/types/framework.js.map +1 -0
  147. package/dist/src/types/index.d.ts +7 -0
  148. package/dist/src/types/index.d.ts.map +1 -0
  149. package/dist/src/types/index.js +7 -0
  150. package/dist/src/types/index.js.map +1 -0
  151. package/dist/src/types/inference-log.d.ts +64 -0
  152. package/dist/src/types/inference-log.d.ts.map +1 -0
  153. package/dist/src/types/inference-log.js +5 -0
  154. package/dist/src/types/inference-log.js.map +1 -0
  155. package/dist/src/types/module.d.ts +302 -0
  156. package/dist/src/types/module.d.ts.map +1 -0
  157. package/dist/src/types/module.js +2 -0
  158. package/dist/src/types/module.js.map +1 -0
  159. package/dist/src/types/trace.d.ts +173 -0
  160. package/dist/src/types/trace.d.ts.map +1 -0
  161. package/dist/src/types/trace.js +2 -0
  162. package/dist/src/types/trace.js.map +1 -0
  163. package/dist/test/event-gate.test.d.ts +2 -0
  164. package/dist/test/event-gate.test.d.ts.map +1 -0
  165. package/dist/test/event-gate.test.js +535 -0
  166. package/dist/test/event-gate.test.js.map +1 -0
  167. package/dist/test/framework.test.d.ts +5 -0
  168. package/dist/test/framework.test.d.ts.map +1 -0
  169. package/dist/test/framework.test.js +738 -0
  170. package/dist/test/framework.test.js.map +1 -0
  171. package/dist/tsconfig.tsbuildinfo +1 -0
  172. package/package.json +58 -0
  173. package/src/agent.ts +512 -0
  174. package/src/api/mcp-server.ts +687 -0
  175. package/src/api/server.ts +1023 -0
  176. package/src/api/types.ts +542 -0
  177. package/src/framework.ts +2784 -0
  178. package/src/gate/event-gate.ts +623 -0
  179. package/src/gate/index.ts +12 -0
  180. package/src/gate/types.ts +112 -0
  181. package/src/index.ts +63 -0
  182. package/src/mcpl/channel-registry.ts +824 -0
  183. package/src/mcpl/checkpoint-manager.ts +545 -0
  184. package/src/mcpl/errors.ts +114 -0
  185. package/src/mcpl/feature-set-manager.ts +333 -0
  186. package/src/mcpl/hook-orchestrator.ts +281 -0
  187. package/src/mcpl/index.ts +134 -0
  188. package/src/mcpl/inference-router.ts +335 -0
  189. package/src/mcpl/push-handler.ts +232 -0
  190. package/src/mcpl/scope-manager.ts +262 -0
  191. package/src/mcpl/server-connection.ts +694 -0
  192. package/src/mcpl/server-registry.ts +144 -0
  193. package/src/mcpl/types.ts +991 -0
  194. package/src/module-registry.ts +547 -0
  195. package/src/modules/api/index.ts +94 -0
  196. package/src/modules/discord/discord-js-client.ts +353 -0
  197. package/src/modules/discord/index.ts +1146 -0
  198. package/src/modules/discord/types.ts +465 -0
  199. package/src/modules/index.ts +43 -0
  200. package/src/modules/workspace/index.ts +969 -0
  201. package/src/modules/workspace/sync.ts +314 -0
  202. package/src/modules/workspace/types.ts +202 -0
  203. package/src/modules/workspace/watcher.ts +142 -0
  204. package/src/queue.ts +106 -0
  205. package/src/safe-slice.ts +18 -0
  206. package/src/types/agent.ts +119 -0
  207. package/src/types/events.ts +252 -0
  208. package/src/types/framework.ts +211 -0
  209. package/src/types/index.ts +6 -0
  210. package/src/types/inference-log.ts +64 -0
  211. package/src/types/module.ts +367 -0
  212. package/src/types/trace.ts +196 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * HookOrchestrator — manages before/after inference fan-out to MCPL servers.
3
+ *
4
+ * This is the bridge between the MCPL protocol and the agent-framework inference
5
+ * pipeline. It collects ContextInjection[] from MCPL servers via beforeInference
6
+ * and feeds them into context-manager's compile(). After inference, it notifies
7
+ * servers of the result via afterInference.
8
+ *
9
+ * Design principles:
10
+ * - Fail-open: timeouts and errors never block inference
11
+ * - Parallel fan-out with per-server timeouts
12
+ * - Loop prevention: rejects inference/request while inside a hook
13
+ */
14
+ /** Timeout for beforeInference per server (fail-open). */
15
+ const BEFORE_INFERENCE_TIMEOUT_MS = 5_000;
16
+ /** Timeout for blocking afterInference per server. */
17
+ const AFTER_INFERENCE_BLOCKING_TIMEOUT_MS = 10_000;
18
+ /**
19
+ * Races a promise against a timeout. Rejects with a descriptive error on timeout.
20
+ */
21
+ function withTimeout(promise, ms, label) {
22
+ return Promise.race([
23
+ promise,
24
+ new Promise((_resolve, reject) => setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms)),
25
+ ]);
26
+ }
27
+ // ============================================================================
28
+ // Content conversion: McplContentBlock / McplContextInjection → membrane types
29
+ // ============================================================================
30
+ /**
31
+ * Convert a single MCPL wire-format content block to a membrane ContentBlock.
32
+ */
33
+ function convertBlock(block) {
34
+ switch (block.type) {
35
+ case 'text':
36
+ return { type: 'text', text: block.text };
37
+ case 'image':
38
+ if (block.data && block.mimeType) {
39
+ return {
40
+ type: 'image',
41
+ source: { type: 'base64', data: block.data, mediaType: block.mimeType },
42
+ };
43
+ }
44
+ if (block.uri) {
45
+ return {
46
+ type: 'image',
47
+ source: { type: 'url', url: block.uri },
48
+ };
49
+ }
50
+ // Malformed image block — degrade to text
51
+ return { type: 'text', text: '[Image: missing data]' };
52
+ case 'audio':
53
+ if (block.data && block.mimeType) {
54
+ return {
55
+ type: 'audio',
56
+ source: { type: 'base64', data: block.data, mediaType: block.mimeType },
57
+ };
58
+ }
59
+ // Audio without inline data — degrade to text
60
+ return { type: 'text', text: `[Audio: ${block.uri ?? 'missing data'}]` };
61
+ case 'resource':
62
+ // Resources don't have a direct membrane equivalent — degrade to text
63
+ return { type: 'text', text: `[Resource: ${block.uri}]` };
64
+ }
65
+ }
66
+ /**
67
+ * Convert MCPL injection content (string shorthand or block array) to membrane ContentBlock[].
68
+ */
69
+ function convertContent(content) {
70
+ if (typeof content === 'string') {
71
+ return [{ type: 'text', text: content }];
72
+ }
73
+ return content.map(convertBlock);
74
+ }
75
+ /**
76
+ * Convert an MCPL wire-format context injection to a context-manager ContextInjection.
77
+ */
78
+ function convertMcplInjection(mcplInj) {
79
+ return {
80
+ namespace: mcplInj.namespace,
81
+ position: mcplInj.position,
82
+ content: convertContent(mcplInj.content),
83
+ metadata: mcplInj.metadata,
84
+ };
85
+ }
86
+ // ============================================================================
87
+ // HookOrchestrator
88
+ // ============================================================================
89
+ export class HookOrchestrator {
90
+ registry;
91
+ featureSetManager;
92
+ _isInHook = false;
93
+ constructor(registry, featureSetManager) {
94
+ this.registry = registry;
95
+ this.featureSetManager = featureSetManager;
96
+ }
97
+ /**
98
+ * Whether a hook is currently executing.
99
+ * Used for loop prevention: inference/request from servers should be rejected
100
+ * while this is true (enforced by Step 6's InferenceRouter).
101
+ */
102
+ get isInHook() {
103
+ return this._isInHook;
104
+ }
105
+ /**
106
+ * Fan out `context/beforeInference` to all capable MCPL servers in parallel.
107
+ *
108
+ * Returns aggregated ContextInjection[] ready for context-manager's compile().
109
+ * Fail-open: servers that time out or error are silently skipped.
110
+ */
111
+ async beforeInference(params) {
112
+ const servers = this.registry.getServersWithCapability('contextHooks.beforeInference');
113
+ if (servers.length === 0) {
114
+ return [];
115
+ }
116
+ this._isInHook = true;
117
+ try {
118
+ return await this.fanOutBeforeInference(servers, params);
119
+ }
120
+ finally {
121
+ this._isInHook = false;
122
+ }
123
+ }
124
+ /**
125
+ * Fan out `context/afterInference` to all capable MCPL servers.
126
+ *
127
+ * Non-blocking servers receive a notification (fire-and-forget).
128
+ * Blocking servers receive a request with a 10s timeout.
129
+ * Returns the first valid AfterInferenceResult from a blocking server, or null.
130
+ */
131
+ async afterInference(params) {
132
+ const servers = this.registry.getServersWithCapability('contextHooks.afterInference');
133
+ if (servers.length === 0) {
134
+ return null;
135
+ }
136
+ this._isInHook = true;
137
+ try {
138
+ return await this.fanOutAfterInference(servers, params);
139
+ }
140
+ finally {
141
+ this._isInHook = false;
142
+ }
143
+ }
144
+ // ==========================================================================
145
+ // Private: beforeInference fan-out
146
+ // ==========================================================================
147
+ async fanOutBeforeInference(servers, params) {
148
+ const results = await Promise.allSettled(servers.map((server) => withTimeout(server.sendBeforeInference(params), BEFORE_INFERENCE_TIMEOUT_MS, `beforeInference to "${server.id}"`).then((result) => ({ server, result }))));
149
+ const injections = [];
150
+ for (const settled of results) {
151
+ if (settled.status === 'rejected') {
152
+ // Fail-open: timeout or transport error — skip this server
153
+ continue;
154
+ }
155
+ const { server, result } = settled.value;
156
+ // Validate feature set
157
+ try {
158
+ this.featureSetManager.validateInbound(server.id, result.featureSet);
159
+ }
160
+ catch {
161
+ // Feature set not enabled or unknown — skip injections from this server
162
+ continue;
163
+ }
164
+ // Convert wire-format injections to context-manager format
165
+ if (result.contextInjections && result.contextInjections.length > 0) {
166
+ for (const mcplInj of result.contextInjections) {
167
+ injections.push(convertMcplInjection(mcplInj));
168
+ }
169
+ }
170
+ }
171
+ return injections;
172
+ }
173
+ // ==========================================================================
174
+ // Private: afterInference fan-out
175
+ // ==========================================================================
176
+ async fanOutAfterInference(servers, params) {
177
+ const blockingPromises = [];
178
+ for (const server of servers) {
179
+ const isBlocking = this.isBlockingAfterInference(server);
180
+ if (isBlocking) {
181
+ // Send as request, await response with timeout
182
+ const promise = withTimeout(server.sendAfterInference(params, true), AFTER_INFERENCE_BLOCKING_TIMEOUT_MS, `afterInference (blocking) to "${server.id}"`).catch(() => {
183
+ // Fail-open: timeout or error — treat as no modification
184
+ return null;
185
+ });
186
+ blockingPromises.push(promise);
187
+ }
188
+ else {
189
+ // Send as notification (fire-and-forget)
190
+ server.sendAfterInference(params, false);
191
+ }
192
+ }
193
+ if (blockingPromises.length === 0) {
194
+ return null;
195
+ }
196
+ // Await all blocking responses and return the first valid result
197
+ const results = await Promise.all(blockingPromises);
198
+ for (const result of results) {
199
+ if (result && result.modifiedResponse) {
200
+ return result;
201
+ }
202
+ }
203
+ return null;
204
+ }
205
+ /**
206
+ * Check if a server's afterInference capability is blocking.
207
+ */
208
+ isBlockingAfterInference(server) {
209
+ const caps = server.capabilities;
210
+ if (!caps?.contextHooks?.afterInference) {
211
+ return false;
212
+ }
213
+ const afterCap = caps.contextHooks.afterInference;
214
+ return typeof afterCap === 'object' && afterCap !== null && 'blocking' in afterCap && afterCap.blocking === true;
215
+ }
216
+ }
217
+ //# sourceMappingURL=hook-orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-orchestrator.js","sourceRoot":"","sources":["../../../src/mcpl/hook-orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export type { JsonRpcRequest, JsonRpcResponse, JsonRpcError, McplContentBlock, McplTextContent, McplImageContent, McplAudioContent, McplResourceContent, McplCapabilities, McplHostCapabilities, McplChannelCapabilities, McplServerConfig, FeatureSetUse, FeatureSetDeclaration, FeatureSetsUpdateParams, FeatureSetsChangedParams, ScopeConfig, ScopeLabel, ScopeElevateParams, ScopeElevateResult, StateCheckpoint, JsonPatchOperation, StateRollbackParams, StateRollbackResult, PushEventParams, PushEventResult, McplModelInfo, BeforeInferenceParams, McplContextInjection, BeforeInferenceResult, AfterInferenceParams, AfterInferenceResult, McplMessage, McplInferenceRequestParams, McplInferencePreferences, McplInferenceRequestResult, InferenceChunkParams, ChannelDescriptor, ChannelContext, ChannelsRegisterParams, ChannelsRegisterResult, ChannelsChangedParams, ChannelsListResult, ChannelsOpenParams, ChannelsOpenResult, ChannelsCloseParams, ChannelsCloseResult, ChannelsOutgoingChunkParams, ChannelsOutgoingCompleteParams, ChannelsPublishParams, ChannelsPublishResult, ChannelIncomingMessage, ChannelsIncomingParams, ChannelsIncomingResult, ChannelIncomingMessageResult, InferenceRoutingPolicy, McplMethodName, McpToolDefinition, McpToolCallResult, McpToolResultContent, } from './types.js';
2
+ export { McplMethod } from './types.js';
3
+ export { FEATURE_SET_NOT_ENABLED, UNKNOWN_FEATURE_SET, CHECKPOINT_NOT_FOUND, CHANNEL_NOT_PERMITTED, UNKNOWN_CHANNEL, CHANNEL_OPEN_FAILED, featureSetNotEnabled, unknownFeatureSet, checkpointNotFound, channelNotPermitted, unknownChannel, channelOpenFailed, } from './errors.js';
4
+ export { McplServerConnection } from './server-connection.js';
5
+ export { McplServerRegistry, type McplCapabilityQuery } from './server-registry.js';
6
+ export { FeatureSetManager, McplFeatureSetError } from './feature-set-manager.js';
7
+ export { ScopeManager, type ElevationHandler } from './scope-manager.js';
8
+ export { HookOrchestrator } from './hook-orchestrator.js';
9
+ export { PushHandler } from './push-handler.js';
10
+ export type { McplPushEvent } from './push-handler.js';
11
+ export { InferenceRouter } from './inference-router.js';
12
+ export { ChannelRegistry } from './channel-registry.js';
13
+ export { CheckpointManager, applyJsonPatch } from './checkpoint-manager.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/mcpl/index.ts"],"names":[],"mappings":"AACA,YAAY,EAEV,cAAc,EACd,eAAe,EACf,YAAY,EAGZ,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EAGnB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EAGvB,gBAAgB,EAGhB,aAAa,EACb,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,EAGxB,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAGlB,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EAGnB,eAAe,EACf,eAAe,EAGf,aAAa,EACb,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EAGpB,WAAW,EACX,0BAA0B,EAC1B,wBAAwB,EACxB,0BAA0B,EAC1B,oBAAoB,EAGpB,iBAAiB,EACjB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,2BAA2B,EAC3B,8BAA8B,EAC9B,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,4BAA4B,EAG5B,sBAAsB,EAGtB,cAAc,EAGd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGpF,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGlF,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,21 @@
1
+ export { McplMethod } from './types.js';
2
+ // Error codes and factories
3
+ export { FEATURE_SET_NOT_ENABLED, UNKNOWN_FEATURE_SET, CHECKPOINT_NOT_FOUND, CHANNEL_NOT_PERMITTED, UNKNOWN_CHANNEL, CHANNEL_OPEN_FAILED, featureSetNotEnabled, unknownFeatureSet, checkpointNotFound, channelNotPermitted, unknownChannel, channelOpenFailed, } from './errors.js';
4
+ // Server connection and registry
5
+ export { McplServerConnection } from './server-connection.js';
6
+ export { McplServerRegistry } from './server-registry.js';
7
+ // Feature set management (permission layer)
8
+ export { FeatureSetManager, McplFeatureSetError } from './feature-set-manager.js';
9
+ // Scope management (whitelist/blacklist enforcement)
10
+ export { ScopeManager } from './scope-manager.js';
11
+ // Hook orchestration (beforeInference/afterInference fan-out)
12
+ export { HookOrchestrator } from './hook-orchestrator.js';
13
+ // Push events (Section 9)
14
+ export { PushHandler } from './push-handler.js';
15
+ // Server-initiated inference (Section 11)
16
+ export { InferenceRouter } from './inference-router.js';
17
+ // Channel registry (channel lifecycle, incoming messages, synthesized tools)
18
+ export { ChannelRegistry } from './channel-registry.js';
19
+ // State management (Section 8, checkpoint trees + JSON Patch)
20
+ export { CheckpointManager, applyJsonPatch } from './checkpoint-manager.js';
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcpl/index.ts"],"names":[],"mappings":"AA2FA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,4BAA4B;AAC5B,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,iCAAiC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAA4B,MAAM,sBAAsB,CAAC;AAEpF,4CAA4C;AAC5C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAElF,qDAAqD;AACrD,OAAO,EAAE,YAAY,EAAyB,MAAM,oBAAoB,CAAC;AAEzE,8DAA8D;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,0BAA0B;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,6EAA6E;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,8DAA8D;AAC9D,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * InferenceRouter — handles inference/request from MCPL servers.
3
+ *
4
+ * Servers can ask the host to run inference on their behalf. This router
5
+ * validates permissions, resolves the target model via routing policy,
6
+ * runs inference through membrane, and optionally streams chunks back.
7
+ *
8
+ * Spec reference: Section 11 (Server-Initiated Inference).
9
+ */
10
+ import type { Membrane } from '@animalabs/membrane';
11
+ import type { McplInferenceRequestParams, McplInferenceRequestResult, InferenceChunkParams, InferenceRoutingPolicy } from './types.js';
12
+ import type { FeatureSetManager } from './feature-set-manager.js';
13
+ import type { HookOrchestrator } from './hook-orchestrator.js';
14
+ /** Minimal responder interface for sending JSON-RPC results back. */
15
+ interface Responder {
16
+ respond(result: McplInferenceRequestResult): void;
17
+ respondError(code: number, message: string, data?: unknown): void;
18
+ /** The JSON-RPC request ID, used for streaming chunk correlation. */
19
+ requestId?: string | number;
20
+ }
21
+ export declare class InferenceRouter {
22
+ private membrane;
23
+ private hookOrchestrator;
24
+ private featureSetManager;
25
+ private routingPolicy;
26
+ private emitTraceFn;
27
+ private sendChunkFn?;
28
+ constructor(membrane: Membrane, hookOrchestrator: HookOrchestrator, featureSetManager: FeatureSetManager, routingPolicy: InferenceRoutingPolicy | null, emitTraceFn: (event: {
29
+ type: string;
30
+ [key: string]: unknown;
31
+ }) => void, sendChunkFn?: (serverId: string, params: InferenceChunkParams) => void);
32
+ /**
33
+ * Handle an inference/request from an MCPL server.
34
+ *
35
+ * 1. Validate feature set
36
+ * 2. Check loop prevention (reject if inside a hook)
37
+ * 3. Resolve model from routing policy
38
+ * 4. Build membrane request and run inference
39
+ * 5. Optionally stream chunks
40
+ * 6. Return result via responder
41
+ */
42
+ handleInferenceRequest(serverId: string, params: McplInferenceRequestParams, responder: Responder): Promise<void>;
43
+ /**
44
+ * Resolve the model to use for an inference request based on routing policy.
45
+ *
46
+ * Priority:
47
+ * 1. Per-conversation override
48
+ * 2. Exact feature set match
49
+ * 3. Wildcard pattern match (first match wins)
50
+ * 4. Default from policy
51
+ * 5. Fallback string 'default'
52
+ */
53
+ private resolveModel;
54
+ /**
55
+ * Handle streaming inference by sending chunks back to the server.
56
+ *
57
+ * Uses membrane.streamYielding when available; falls back to non-streaming
58
+ * membrane.complete otherwise.
59
+ */
60
+ private handleStreaming;
61
+ /**
62
+ * Map membrane's stopReason string to MCPL's finishReason enum.
63
+ */
64
+ private mapStopReason;
65
+ }
66
+ export {};
67
+ //# sourceMappingURL=inference-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-router.d.ts","sourceRoot":"","sources":["../../../src/mcpl/inference-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAmC,MAAM,qBAAqB,CAAC;AAErF,OAAO,KAAK,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAM/D,qEAAqE;AACrE,UAAU,SAAS;IACjB,OAAO,CAAC,MAAM,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAClE,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAyCD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,WAAW,CAA4D;IAC/E,OAAO,CAAC,WAAW,CAAC,CAA2D;gBAG7E,QAAQ,EAAE,QAAQ,EAClB,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,EAAE,iBAAiB,EACpC,aAAa,EAAE,sBAAsB,GAAG,IAAI,EAC5C,WAAW,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK,IAAI,EACtE,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,KAAK,IAAI;IAUxE;;;;;;;;;OASG;IACG,sBAAsB,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,0BAA0B,EAClC,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC;IA4GhB;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAmCpB;;;;;OAKG;YACW,eAAe;IAgD7B;;OAEG;IACH,OAAO,CAAC,aAAa;CAatB"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * InferenceRouter — handles inference/request from MCPL servers.
3
+ *
4
+ * Servers can ask the host to run inference on their behalf. This router
5
+ * validates permissions, resolves the target model via routing policy,
6
+ * runs inference through membrane, and optionally streams chunks back.
7
+ *
8
+ * Spec reference: Section 11 (Server-Initiated Inference).
9
+ */
10
+ import { McplFeatureSetError } from './feature-set-manager.js';
11
+ // ============================================================================
12
+ // Wildcard matching (same logic as feature-set-manager)
13
+ // ============================================================================
14
+ /**
15
+ * Simple glob match: split on `.`, `*` matches any single segment.
16
+ */
17
+ function wildcardMatch(pattern, name) {
18
+ const patternParts = pattern.split('.');
19
+ const nameParts = name.split('.');
20
+ if (patternParts.length !== nameParts.length) {
21
+ return false;
22
+ }
23
+ for (let i = 0; i < patternParts.length; i++) {
24
+ const p = patternParts[i];
25
+ if (p === '*') {
26
+ continue;
27
+ }
28
+ if (p !== nameParts[i]) {
29
+ return false;
30
+ }
31
+ }
32
+ return true;
33
+ }
34
+ // ============================================================================
35
+ // Constants
36
+ // ============================================================================
37
+ /** Default max tokens when not specified in preferences. */
38
+ const DEFAULT_MAX_TOKENS = 4096;
39
+ // ============================================================================
40
+ // InferenceRouter
41
+ // ============================================================================
42
+ export class InferenceRouter {
43
+ membrane;
44
+ hookOrchestrator;
45
+ featureSetManager;
46
+ routingPolicy;
47
+ emitTraceFn;
48
+ sendChunkFn;
49
+ constructor(membrane, hookOrchestrator, featureSetManager, routingPolicy, emitTraceFn, sendChunkFn) {
50
+ this.membrane = membrane;
51
+ this.hookOrchestrator = hookOrchestrator;
52
+ this.featureSetManager = featureSetManager;
53
+ this.routingPolicy = routingPolicy;
54
+ this.emitTraceFn = emitTraceFn;
55
+ this.sendChunkFn = sendChunkFn;
56
+ }
57
+ /**
58
+ * Handle an inference/request from an MCPL server.
59
+ *
60
+ * 1. Validate feature set
61
+ * 2. Check loop prevention (reject if inside a hook)
62
+ * 3. Resolve model from routing policy
63
+ * 4. Build membrane request and run inference
64
+ * 5. Optionally stream chunks
65
+ * 6. Return result via responder
66
+ */
67
+ async handleInferenceRequest(serverId, params, responder) {
68
+ // 1. Validate feature set
69
+ try {
70
+ this.featureSetManager.validateInbound(serverId, params.featureSet);
71
+ }
72
+ catch (err) {
73
+ const message = err instanceof McplFeatureSetError
74
+ ? err.message
75
+ : 'Feature set validation failed';
76
+ const code = err instanceof McplFeatureSetError ? err.code : -32600;
77
+ responder.respondError(code, message);
78
+ return;
79
+ }
80
+ // 2. Loop prevention: reject if inside a hook
81
+ if (this.hookOrchestrator.isInHook) {
82
+ responder.respondError(-32600, 'Cannot process inference request during hook execution');
83
+ return;
84
+ }
85
+ // 3. Resolve model
86
+ const model = this.resolveModel(params.featureSet, params.conversationId);
87
+ // Emit trace: inference start
88
+ this.emitTraceFn({
89
+ type: 'mcpl:inference_start',
90
+ serverId,
91
+ featureSet: params.featureSet,
92
+ model,
93
+ stream: params.stream ?? false,
94
+ });
95
+ // 4. Build membrane-compatible request
96
+ const messages = params.messages.map((msg) => ({
97
+ participant: msg.role === 'assistant' ? 'assistant' : 'user',
98
+ content: [{ type: 'text', text: msg.content }],
99
+ }));
100
+ const request = {
101
+ messages,
102
+ config: {
103
+ model,
104
+ maxTokens: params.preferences?.maxTokens ?? DEFAULT_MAX_TOKENS,
105
+ temperature: params.preferences?.temperature,
106
+ },
107
+ };
108
+ try {
109
+ // 5. Run inference
110
+ if (params.stream && this.sendChunkFn && responder.requestId != null) {
111
+ // Streaming mode
112
+ await this.handleStreaming(serverId, model, request, responder);
113
+ }
114
+ else {
115
+ // Non-streaming mode
116
+ const response = await this.membrane.complete(request);
117
+ // Extract text content from response
118
+ const contentText = response.content
119
+ .filter((b) => b.type === 'text')
120
+ .map((b) => b.text)
121
+ .join('');
122
+ const result = {
123
+ content: contentText,
124
+ model,
125
+ finishReason: this.mapStopReason(response.stopReason),
126
+ usage: {
127
+ inputTokens: response.usage.inputTokens,
128
+ outputTokens: response.usage.outputTokens,
129
+ },
130
+ };
131
+ // Emit trace: inference complete
132
+ this.emitTraceFn({
133
+ type: 'mcpl:inference_complete',
134
+ serverId,
135
+ model,
136
+ inputTokens: result.usage.inputTokens,
137
+ outputTokens: result.usage.outputTokens,
138
+ });
139
+ responder.respond(result);
140
+ }
141
+ }
142
+ catch (err) {
143
+ // Emit trace: inference failed
144
+ this.emitTraceFn({
145
+ type: 'mcpl:inference_fail',
146
+ serverId,
147
+ model,
148
+ error: err instanceof Error ? err.message : String(err),
149
+ });
150
+ responder.respondError(-32603, err instanceof Error ? err.message : 'Inference failed');
151
+ }
152
+ }
153
+ // ==========================================================================
154
+ // Private: Model resolution
155
+ // ==========================================================================
156
+ /**
157
+ * Resolve the model to use for an inference request based on routing policy.
158
+ *
159
+ * Priority:
160
+ * 1. Per-conversation override
161
+ * 2. Exact feature set match
162
+ * 3. Wildcard pattern match (first match wins)
163
+ * 4. Default from policy
164
+ * 5. Fallback string 'default'
165
+ */
166
+ resolveModel(featureSet, conversationId) {
167
+ if (!this.routingPolicy) {
168
+ return 'default';
169
+ }
170
+ // Check per-conversation override
171
+ if (conversationId && this.routingPolicy.overrides?.[conversationId]) {
172
+ return this.routingPolicy.overrides[conversationId];
173
+ }
174
+ // Check exact feature set match
175
+ if (this.routingPolicy.byFeature?.[featureSet]) {
176
+ return this.routingPolicy.byFeature[featureSet];
177
+ }
178
+ // Check wildcard patterns
179
+ if (this.routingPolicy.wildcards) {
180
+ for (const [pattern, matchedModel] of Object.entries(this.routingPolicy.wildcards)) {
181
+ if (wildcardMatch(pattern, featureSet)) {
182
+ return matchedModel;
183
+ }
184
+ }
185
+ }
186
+ // Default
187
+ return this.routingPolicy.default;
188
+ }
189
+ // ==========================================================================
190
+ // Private: Streaming
191
+ // ==========================================================================
192
+ /**
193
+ * Handle streaming inference by sending chunks back to the server.
194
+ *
195
+ * Uses membrane.streamYielding when available; falls back to non-streaming
196
+ * membrane.complete otherwise.
197
+ */
198
+ async handleStreaming(serverId, model, request, responder) {
199
+ const requestId = responder.requestId;
200
+ // Check if streamYielding is available on the membrane instance.
201
+ // We use streamYielding to iterate events and forward text deltas as chunks.
202
+ const stream = this.membrane.streamYielding(request);
203
+ let chunkIndex = 0;
204
+ let fullContent = '';
205
+ for await (const event of stream) {
206
+ if (event.type === 'tokens' && 'content' in event) {
207
+ const delta = event.content;
208
+ fullContent += delta;
209
+ this.sendChunkFn(serverId, {
210
+ requestId,
211
+ index: chunkIndex++,
212
+ delta,
213
+ });
214
+ }
215
+ }
216
+ // After streaming completes, send the final result
217
+ const result = {
218
+ content: fullContent,
219
+ model,
220
+ finishReason: 'end_turn',
221
+ usage: { inputTokens: 0, outputTokens: 0 },
222
+ };
223
+ this.emitTraceFn({
224
+ type: 'mcpl:inference_complete',
225
+ serverId,
226
+ model,
227
+ streamed: true,
228
+ });
229
+ responder.respond(result);
230
+ }
231
+ // ==========================================================================
232
+ // Private: Helpers
233
+ // ==========================================================================
234
+ /**
235
+ * Map membrane's stopReason string to MCPL's finishReason enum.
236
+ */
237
+ mapStopReason(stopReason) {
238
+ switch (stopReason) {
239
+ case 'max_tokens':
240
+ return 'max_tokens';
241
+ case 'stop_sequence':
242
+ return 'stop_sequence';
243
+ case 'end_turn':
244
+ default:
245
+ return 'end_turn';
246
+ }
247
+ }
248
+ }
249
+ //# sourceMappingURL=inference-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-router.js","sourceRoot":"","sources":["../../../src/mcpl/inference-router.ts"],"names":[],"mappings":"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"}