@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.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/dist/src/agent.d.ts +130 -0
- package/dist/src/agent.d.ts.map +1 -0
- package/dist/src/agent.js +406 -0
- package/dist/src/agent.js.map +1 -0
- package/dist/src/api/mcp-server.d.ts +37 -0
- package/dist/src/api/mcp-server.d.ts.map +1 -0
- package/dist/src/api/mcp-server.js +598 -0
- package/dist/src/api/mcp-server.js.map +1 -0
- package/dist/src/api/server.d.ts +83 -0
- package/dist/src/api/server.d.ts.map +1 -0
- package/dist/src/api/server.js +785 -0
- package/dist/src/api/server.js.map +1 -0
- package/dist/src/api/types.d.ts +395 -0
- package/dist/src/api/types.d.ts.map +1 -0
- package/dist/src/api/types.js +5 -0
- package/dist/src/api/types.js.map +1 -0
- package/dist/src/framework.d.ts +309 -0
- package/dist/src/framework.d.ts.map +1 -0
- package/dist/src/framework.js +2309 -0
- package/dist/src/framework.js.map +1 -0
- package/dist/src/gate/event-gate.d.ts +75 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -0
- package/dist/src/gate/event-gate.js +503 -0
- package/dist/src/gate/event-gate.js.map +1 -0
- package/dist/src/gate/index.d.ts +3 -0
- package/dist/src/gate/index.d.ts.map +1 -0
- package/dist/src/gate/index.js +2 -0
- package/dist/src/gate/index.js.map +1 -0
- package/dist/src/gate/types.d.ts +82 -0
- package/dist/src/gate/types.d.ts.map +1 -0
- package/dist/src/gate/types.js +9 -0
- package/dist/src/gate/types.js.map +1 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcpl/channel-registry.d.ts +141 -0
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -0
- package/dist/src/mcpl/channel-registry.js +647 -0
- package/dist/src/mcpl/channel-registry.js.map +1 -0
- package/dist/src/mcpl/checkpoint-manager.d.ts +79 -0
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -0
- package/dist/src/mcpl/checkpoint-manager.js +430 -0
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -0
- package/dist/src/mcpl/errors.d.ts +52 -0
- package/dist/src/mcpl/errors.d.ts.map +1 -0
- package/dist/src/mcpl/errors.js +93 -0
- package/dist/src/mcpl/errors.js.map +1 -0
- package/dist/src/mcpl/feature-set-manager.d.ts +91 -0
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -0
- package/dist/src/mcpl/feature-set-manager.js +250 -0
- package/dist/src/mcpl/feature-set-manager.js.map +1 -0
- package/dist/src/mcpl/hook-orchestrator.d.ts +51 -0
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -0
- package/dist/src/mcpl/hook-orchestrator.js +217 -0
- package/dist/src/mcpl/hook-orchestrator.js.map +1 -0
- package/dist/src/mcpl/index.d.ts +14 -0
- package/dist/src/mcpl/index.d.ts.map +1 -0
- package/dist/src/mcpl/index.js +21 -0
- package/dist/src/mcpl/index.js.map +1 -0
- package/dist/src/mcpl/inference-router.d.ts +67 -0
- package/dist/src/mcpl/inference-router.d.ts.map +1 -0
- package/dist/src/mcpl/inference-router.js +249 -0
- package/dist/src/mcpl/inference-router.js.map +1 -0
- package/dist/src/mcpl/push-handler.d.ts +60 -0
- package/dist/src/mcpl/push-handler.d.ts.map +1 -0
- package/dist/src/mcpl/push-handler.js +162 -0
- package/dist/src/mcpl/push-handler.js.map +1 -0
- package/dist/src/mcpl/scope-manager.d.ts +76 -0
- package/dist/src/mcpl/scope-manager.d.ts.map +1 -0
- package/dist/src/mcpl/scope-manager.js +213 -0
- package/dist/src/mcpl/scope-manager.js.map +1 -0
- package/dist/src/mcpl/server-connection.d.ts +174 -0
- package/dist/src/mcpl/server-connection.d.ts.map +1 -0
- package/dist/src/mcpl/server-connection.js +559 -0
- package/dist/src/mcpl/server-connection.js.map +1 -0
- package/dist/src/mcpl/server-registry.d.ts +63 -0
- package/dist/src/mcpl/server-registry.d.ts.map +1 -0
- package/dist/src/mcpl/server-registry.js +119 -0
- package/dist/src/mcpl/server-registry.js.map +1 -0
- package/dist/src/mcpl/types.d.ts +755 -0
- package/dist/src/mcpl/types.d.ts.map +1 -0
- package/dist/src/mcpl/types.js +48 -0
- package/dist/src/mcpl/types.js.map +1 -0
- package/dist/src/module-registry.d.ts +93 -0
- package/dist/src/module-registry.d.ts.map +1 -0
- package/dist/src/module-registry.js +386 -0
- package/dist/src/module-registry.js.map +1 -0
- package/dist/src/modules/api/index.d.ts +22 -0
- package/dist/src/modules/api/index.d.ts.map +1 -0
- package/dist/src/modules/api/index.js +63 -0
- package/dist/src/modules/api/index.js.map +1 -0
- package/dist/src/modules/discord/discord-js-client.d.ts +58 -0
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -0
- package/dist/src/modules/discord/discord-js-client.js +273 -0
- package/dist/src/modules/discord/discord-js-client.js.map +1 -0
- package/dist/src/modules/discord/index.d.ts +82 -0
- package/dist/src/modules/discord/index.d.ts.map +1 -0
- package/dist/src/modules/discord/index.js +959 -0
- package/dist/src/modules/discord/index.js.map +1 -0
- package/dist/src/modules/discord/types.d.ts +327 -0
- package/dist/src/modules/discord/types.d.ts.map +1 -0
- package/dist/src/modules/discord/types.js +5 -0
- package/dist/src/modules/discord/types.js.map +1 -0
- package/dist/src/modules/index.d.ts +11 -0
- package/dist/src/modules/index.d.ts.map +1 -0
- package/dist/src/modules/index.js +7 -0
- package/dist/src/modules/index.js.map +1 -0
- package/dist/src/modules/workspace/index.d.ts +59 -0
- package/dist/src/modules/workspace/index.d.ts.map +1 -0
- package/dist/src/modules/workspace/index.js +831 -0
- package/dist/src/modules/workspace/index.js.map +1 -0
- package/dist/src/modules/workspace/sync.d.ts +48 -0
- package/dist/src/modules/workspace/sync.d.ts.map +1 -0
- package/dist/src/modules/workspace/sync.js +253 -0
- package/dist/src/modules/workspace/sync.js.map +1 -0
- package/dist/src/modules/workspace/types.d.ts +166 -0
- package/dist/src/modules/workspace/types.d.ts.map +1 -0
- package/dist/src/modules/workspace/types.js +5 -0
- package/dist/src/modules/workspace/types.js.map +1 -0
- package/dist/src/modules/workspace/watcher.d.ts +43 -0
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -0
- package/dist/src/modules/workspace/watcher.js +120 -0
- package/dist/src/modules/workspace/watcher.js.map +1 -0
- package/dist/src/queue.d.ts +50 -0
- package/dist/src/queue.d.ts.map +1 -0
- package/dist/src/queue.js +95 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/src/safe-slice.d.ts +8 -0
- package/dist/src/safe-slice.d.ts.map +1 -0
- package/dist/src/safe-slice.js +18 -0
- package/dist/src/safe-slice.js.map +1 -0
- package/dist/src/types/agent.d.ts +118 -0
- package/dist/src/types/agent.d.ts.map +1 -0
- package/dist/src/types/agent.js +2 -0
- package/dist/src/types/agent.js.map +1 -0
- package/dist/src/types/events.d.ts +220 -0
- package/dist/src/types/events.d.ts.map +1 -0
- package/dist/src/types/events.js +2 -0
- package/dist/src/types/events.js.map +1 -0
- package/dist/src/types/framework.d.ts +184 -0
- package/dist/src/types/framework.d.ts.map +1 -0
- package/dist/src/types/framework.js +2 -0
- package/dist/src/types/framework.js.map +1 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +7 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/inference-log.d.ts +64 -0
- package/dist/src/types/inference-log.d.ts.map +1 -0
- package/dist/src/types/inference-log.js +5 -0
- package/dist/src/types/inference-log.js.map +1 -0
- package/dist/src/types/module.d.ts +302 -0
- package/dist/src/types/module.d.ts.map +1 -0
- package/dist/src/types/module.js +2 -0
- package/dist/src/types/module.js.map +1 -0
- package/dist/src/types/trace.d.ts +173 -0
- package/dist/src/types/trace.d.ts.map +1 -0
- package/dist/src/types/trace.js +2 -0
- package/dist/src/types/trace.js.map +1 -0
- package/dist/test/event-gate.test.d.ts +2 -0
- package/dist/test/event-gate.test.d.ts.map +1 -0
- package/dist/test/event-gate.test.js +535 -0
- package/dist/test/event-gate.test.js.map +1 -0
- package/dist/test/framework.test.d.ts +5 -0
- package/dist/test/framework.test.d.ts.map +1 -0
- package/dist/test/framework.test.js +738 -0
- package/dist/test/framework.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +58 -0
- package/src/agent.ts +512 -0
- package/src/api/mcp-server.ts +687 -0
- package/src/api/server.ts +1023 -0
- package/src/api/types.ts +542 -0
- package/src/framework.ts +2784 -0
- package/src/gate/event-gate.ts +623 -0
- package/src/gate/index.ts +12 -0
- package/src/gate/types.ts +112 -0
- package/src/index.ts +63 -0
- package/src/mcpl/channel-registry.ts +824 -0
- package/src/mcpl/checkpoint-manager.ts +545 -0
- package/src/mcpl/errors.ts +114 -0
- package/src/mcpl/feature-set-manager.ts +333 -0
- package/src/mcpl/hook-orchestrator.ts +281 -0
- package/src/mcpl/index.ts +134 -0
- package/src/mcpl/inference-router.ts +335 -0
- package/src/mcpl/push-handler.ts +232 -0
- package/src/mcpl/scope-manager.ts +262 -0
- package/src/mcpl/server-connection.ts +694 -0
- package/src/mcpl/server-registry.ts +144 -0
- package/src/mcpl/types.ts +991 -0
- package/src/module-registry.ts +547 -0
- package/src/modules/api/index.ts +94 -0
- package/src/modules/discord/discord-js-client.ts +353 -0
- package/src/modules/discord/index.ts +1146 -0
- package/src/modules/discord/types.ts +465 -0
- package/src/modules/index.ts +43 -0
- package/src/modules/workspace/index.ts +969 -0
- package/src/modules/workspace/sync.ts +314 -0
- package/src/modules/workspace/types.ts +202 -0
- package/src/modules/workspace/watcher.ts +142 -0
- package/src/queue.ts +106 -0
- package/src/safe-slice.ts +18 -0
- package/src/types/agent.ts +119 -0
- package/src/types/events.ts +252 -0
- package/src/types/framework.ts +211 -0
- package/src/types/index.ts +6 -0
- package/src/types/inference-log.ts +64 -0
- package/src/types/module.ts +367 -0
- package/src/types/trace.ts +196 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PushHandler — handles push/event messages from MCPL servers.
|
|
3
|
+
*
|
|
4
|
+
* Validates feature sets, deduplicates by eventId, converts MCPL content blocks
|
|
5
|
+
* to membrane ContentBlock[], and pushes McplPushEvents into the processing queue.
|
|
6
|
+
*
|
|
7
|
+
* Spec reference: Section 9 (Push Events).
|
|
8
|
+
*/
|
|
9
|
+
import type { ContentBlock } from '@animalabs/membrane';
|
|
10
|
+
import type { PushEventParams, PushEventResult } from './types.js';
|
|
11
|
+
import type { FeatureSetManager } from './feature-set-manager.js';
|
|
12
|
+
/**
|
|
13
|
+
* A push event converted for the framework processing queue.
|
|
14
|
+
*
|
|
15
|
+
* NOTE: This interface should be added to src/types/events.ts and included
|
|
16
|
+
* in the ProcessEvent union. It is defined here for reference but the actual
|
|
17
|
+
* events.ts modification is deferred.
|
|
18
|
+
*/
|
|
19
|
+
export interface McplPushEvent {
|
|
20
|
+
type: 'mcpl:push-event';
|
|
21
|
+
serverId: string;
|
|
22
|
+
featureSet: string;
|
|
23
|
+
eventId: string;
|
|
24
|
+
content: ContentBlock[];
|
|
25
|
+
origin?: Record<string, unknown>;
|
|
26
|
+
timestamp: string;
|
|
27
|
+
inferenceId: string;
|
|
28
|
+
triggerInference?: boolean;
|
|
29
|
+
targetAgents?: string[];
|
|
30
|
+
}
|
|
31
|
+
/** Minimal responder interface for sending JSON-RPC results back. */
|
|
32
|
+
interface Responder {
|
|
33
|
+
respond(result: PushEventResult): void;
|
|
34
|
+
respondError?(code: number, message: string, data?: unknown): void;
|
|
35
|
+
}
|
|
36
|
+
export declare class PushHandler {
|
|
37
|
+
private featureSetManager;
|
|
38
|
+
private pushEventFn;
|
|
39
|
+
private emitTraceFn;
|
|
40
|
+
private shouldTriggerInference?;
|
|
41
|
+
private dedup;
|
|
42
|
+
constructor(featureSetManager: FeatureSetManager, pushEventFn: (event: McplPushEvent) => void, emitTraceFn: (event: {
|
|
43
|
+
type: string;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}) => void, shouldTriggerInference?: (content: string, metadata: Record<string, unknown>) => boolean);
|
|
46
|
+
/**
|
|
47
|
+
* Handle a push/event message from an MCPL server.
|
|
48
|
+
*
|
|
49
|
+
* 1. Validate feature set
|
|
50
|
+
* 2. Deduplicate by eventId
|
|
51
|
+
* 3. Optionally check shouldTriggerInference callback
|
|
52
|
+
* 4. Convert content blocks
|
|
53
|
+
* 5. Push event to queue
|
|
54
|
+
* 6. Emit trace
|
|
55
|
+
* 7. Respond with accepted + inferenceId
|
|
56
|
+
*/
|
|
57
|
+
handlePushEvent(serverId: string, params: PushEventParams, responder?: Responder): void;
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=push-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-handler.d.ts","sourceRoot":"","sources":["../../../src/mcpl/push-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAEV,eAAe,EACf,eAAe,EAChB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAOlE;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAgFD,qEAAqE;AACrE,UAAU,SAAS;IACjB,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACvC,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CACpE;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,WAAW,CAA4D;IAC/E,OAAO,CAAC,sBAAsB,CAAC,CAAkE;IACjG,OAAO,CAAC,KAAK,CAAsB;gBAGjC,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAC3C,WAAW,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,KAAK,IAAI,EACtE,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO;IAQ1F;;;;;;;;;;OAUG;IACH,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE,SAAS,GACpB,IAAI;CAkER"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PushHandler — handles push/event messages from MCPL servers.
|
|
3
|
+
*
|
|
4
|
+
* Validates feature sets, deduplicates by eventId, converts MCPL content blocks
|
|
5
|
+
* to membrane ContentBlock[], and pushes McplPushEvents into the processing queue.
|
|
6
|
+
*
|
|
7
|
+
* Spec reference: Section 9 (Push Events).
|
|
8
|
+
*/
|
|
9
|
+
import { McplFeatureSetError } from './feature-set-manager.js';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Content conversion: McplContentBlock → membrane ContentBlock
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Convert a single MCPL wire-format content block to a membrane ContentBlock.
|
|
15
|
+
* Same logic as hook-orchestrator.ts.
|
|
16
|
+
*/
|
|
17
|
+
function convertBlock(block) {
|
|
18
|
+
switch (block.type) {
|
|
19
|
+
case 'text':
|
|
20
|
+
return { type: 'text', text: block.text };
|
|
21
|
+
case 'image':
|
|
22
|
+
if (block.data && block.mimeType) {
|
|
23
|
+
return {
|
|
24
|
+
type: 'image',
|
|
25
|
+
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (block.uri) {
|
|
29
|
+
return {
|
|
30
|
+
type: 'image',
|
|
31
|
+
source: { type: 'url', url: block.uri },
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return { type: 'text', text: '[Image: no data]' };
|
|
35
|
+
case 'audio':
|
|
36
|
+
if (block.data && block.mimeType) {
|
|
37
|
+
return {
|
|
38
|
+
type: 'audio',
|
|
39
|
+
source: { type: 'base64', data: block.data, mediaType: block.mimeType },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return { type: 'text', text: '[Audio: no data]' };
|
|
43
|
+
case 'resource':
|
|
44
|
+
return { type: 'text', text: `[Resource: ${block.uri}]` };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// LRU Dedup Set
|
|
49
|
+
// ============================================================================
|
|
50
|
+
/**
|
|
51
|
+
* Simple dedup set with a max capacity. When full, clears and starts fresh.
|
|
52
|
+
* Good enough for a deduplication window — exact LRU is overkill here.
|
|
53
|
+
*/
|
|
54
|
+
class DedupSet {
|
|
55
|
+
set = new Set();
|
|
56
|
+
maxSize;
|
|
57
|
+
constructor(maxSize = 1000) {
|
|
58
|
+
this.maxSize = maxSize;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns true if the key was already present (duplicate).
|
|
62
|
+
* Otherwise adds it and returns false.
|
|
63
|
+
*/
|
|
64
|
+
checkAndAdd(key) {
|
|
65
|
+
if (this.set.has(key)) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (this.set.size >= this.maxSize) {
|
|
69
|
+
this.set.clear();
|
|
70
|
+
}
|
|
71
|
+
this.set.add(key);
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// PushHandler
|
|
77
|
+
// ============================================================================
|
|
78
|
+
export class PushHandler {
|
|
79
|
+
featureSetManager;
|
|
80
|
+
pushEventFn;
|
|
81
|
+
emitTraceFn;
|
|
82
|
+
shouldTriggerInference;
|
|
83
|
+
dedup = new DedupSet(1000);
|
|
84
|
+
constructor(featureSetManager, pushEventFn, emitTraceFn, shouldTriggerInference) {
|
|
85
|
+
this.featureSetManager = featureSetManager;
|
|
86
|
+
this.pushEventFn = pushEventFn;
|
|
87
|
+
this.emitTraceFn = emitTraceFn;
|
|
88
|
+
this.shouldTriggerInference = shouldTriggerInference;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Handle a push/event message from an MCPL server.
|
|
92
|
+
*
|
|
93
|
+
* 1. Validate feature set
|
|
94
|
+
* 2. Deduplicate by eventId
|
|
95
|
+
* 3. Optionally check shouldTriggerInference callback
|
|
96
|
+
* 4. Convert content blocks
|
|
97
|
+
* 5. Push event to queue
|
|
98
|
+
* 6. Emit trace
|
|
99
|
+
* 7. Respond with accepted + inferenceId
|
|
100
|
+
*/
|
|
101
|
+
handlePushEvent(serverId, params, responder) {
|
|
102
|
+
// 1. Validate feature set
|
|
103
|
+
try {
|
|
104
|
+
this.featureSetManager.validateInbound(serverId, params.featureSet);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const reason = err instanceof McplFeatureSetError
|
|
108
|
+
? err.message
|
|
109
|
+
: 'Feature set validation failed';
|
|
110
|
+
responder?.respond({ accepted: false, reason });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// 2. Deduplicate by eventId
|
|
114
|
+
if (this.dedup.checkAndAdd(params.eventId)) {
|
|
115
|
+
responder?.respond({ accepted: false, reason: 'duplicate' });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// 3. Convert content blocks
|
|
119
|
+
const content = params.payload.content.map(convertBlock);
|
|
120
|
+
// 4. Check shouldTriggerInference callback
|
|
121
|
+
let triggerInference = true;
|
|
122
|
+
if (this.shouldTriggerInference) {
|
|
123
|
+
const textContent = content
|
|
124
|
+
.filter((b) => b.type === 'text')
|
|
125
|
+
.map((b) => b.text)
|
|
126
|
+
.join('\n');
|
|
127
|
+
const metadata = {
|
|
128
|
+
serverId,
|
|
129
|
+
featureSet: params.featureSet,
|
|
130
|
+
eventId: params.eventId,
|
|
131
|
+
eventType: 'push:event',
|
|
132
|
+
...(params.origin ?? {}),
|
|
133
|
+
};
|
|
134
|
+
triggerInference = this.shouldTriggerInference(textContent, metadata);
|
|
135
|
+
}
|
|
136
|
+
// 5. Generate inferenceId
|
|
137
|
+
const inferenceId = `${serverId}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
138
|
+
// 6. Push event to queue
|
|
139
|
+
const pushEvent = {
|
|
140
|
+
type: 'mcpl:push-event',
|
|
141
|
+
serverId,
|
|
142
|
+
featureSet: params.featureSet,
|
|
143
|
+
eventId: params.eventId,
|
|
144
|
+
content,
|
|
145
|
+
origin: params.origin,
|
|
146
|
+
timestamp: params.timestamp,
|
|
147
|
+
inferenceId,
|
|
148
|
+
triggerInference,
|
|
149
|
+
};
|
|
150
|
+
this.pushEventFn(pushEvent);
|
|
151
|
+
// 7. Emit trace
|
|
152
|
+
this.emitTraceFn({
|
|
153
|
+
type: 'mcpl:push_event',
|
|
154
|
+
serverId,
|
|
155
|
+
eventId: params.eventId,
|
|
156
|
+
featureSet: params.featureSet,
|
|
157
|
+
});
|
|
158
|
+
// 8. Respond
|
|
159
|
+
responder?.respond({ accepted: true, inferenceId });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=push-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-handler.js","sourceRoot":"","sources":["../../../src/mcpl/push-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScopeManager — Whitelist/blacklist enforcement and scope elevation for MCPL.
|
|
3
|
+
*
|
|
4
|
+
* Manages per-feature-set scope configurations and evaluates whether actions
|
|
5
|
+
* are approved, denied, or require user prompting. Handles `scope/elevate`
|
|
6
|
+
* requests from servers.
|
|
7
|
+
*
|
|
8
|
+
* Spec references: Section 7 (Scoped Access).
|
|
9
|
+
*/
|
|
10
|
+
import type { ScopeConfig, ScopeLabel, ScopeElevateParams, ScopeElevateResult } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Callback invoked when a scope elevation requires user approval.
|
|
13
|
+
* Returns true if the user approves, false otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export type ElevationHandler = (featureSet: string, scope: ScopeLabel) => Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Manages whitelist/blacklist enforcement and scope elevation for feature sets.
|
|
18
|
+
*
|
|
19
|
+
* Evaluation order (per spec Section 7.6):
|
|
20
|
+
* 1. Check approval cache (session-level)
|
|
21
|
+
* 2. Check blacklist (if any pattern matches -> denied)
|
|
22
|
+
* 3. Check whitelist (if any pattern matches -> approved)
|
|
23
|
+
* 4. Otherwise -> prompt
|
|
24
|
+
*/
|
|
25
|
+
export declare class ScopeManager {
|
|
26
|
+
/** Scope configs keyed by feature set name. */
|
|
27
|
+
private configs;
|
|
28
|
+
/** Cached approvals: Set of `${featureSet}\0${label}` keys. */
|
|
29
|
+
private approvalCache;
|
|
30
|
+
/** Optional handler for user-approval prompts. */
|
|
31
|
+
private elevationHandler;
|
|
32
|
+
/**
|
|
33
|
+
* Set scope configuration for a single feature set.
|
|
34
|
+
*/
|
|
35
|
+
configure(featureSet: string, config: ScopeConfig): void;
|
|
36
|
+
/**
|
|
37
|
+
* Set scope configurations for multiple feature sets at once.
|
|
38
|
+
*/
|
|
39
|
+
configureAll(scopes: Record<string, ScopeConfig>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Check whether a label is approved, denied, or needs prompting
|
|
42
|
+
* for the given feature set.
|
|
43
|
+
*
|
|
44
|
+
* Evaluation order:
|
|
45
|
+
* 1. Approval cache hit -> 'approved'
|
|
46
|
+
* 2. Blacklist match -> 'denied'
|
|
47
|
+
* 3. Whitelist match -> 'approved'
|
|
48
|
+
* 4. No config or no match -> 'prompt'
|
|
49
|
+
*/
|
|
50
|
+
checkScope(featureSet: string, label: string): 'approved' | 'denied' | 'prompt';
|
|
51
|
+
/**
|
|
52
|
+
* Handle a `scope/elevate` request from a server.
|
|
53
|
+
*
|
|
54
|
+
* Checks scope against whitelist/blacklist, then:
|
|
55
|
+
* - 'approved' -> return approved with payload
|
|
56
|
+
* - 'denied' -> return denied with reason
|
|
57
|
+
* - 'prompt' -> invoke elevation handler if registered, otherwise deny
|
|
58
|
+
*/
|
|
59
|
+
handleElevation(params: ScopeElevateParams): Promise<ScopeElevateResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Register a custom elevation handler for user-approval prompts.
|
|
62
|
+
* The handler is called when a scope check returns 'prompt'.
|
|
63
|
+
*/
|
|
64
|
+
setElevationHandler(handler: ElevationHandler): void;
|
|
65
|
+
/**
|
|
66
|
+
* Cache an approval for the session.
|
|
67
|
+
* Subsequent `checkScope()` calls with the same feature set and label
|
|
68
|
+
* will return 'approved' without re-evaluating patterns.
|
|
69
|
+
*/
|
|
70
|
+
cacheApproval(featureSet: string, label: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Clear all cached approvals.
|
|
73
|
+
*/
|
|
74
|
+
clearCache(): void;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=scope-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-manager.d.ts","sourceRoot":"","sources":["../../../src/mcpl/scope-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,KACd,OAAO,CAAC,OAAO,CAAC,CAAC;AAkEtB;;;;;;;;GAQG;AACH,qBAAa,YAAY;IACvB,+CAA+C;IAC/C,OAAO,CAAC,OAAO,CAAkC;IAEjD,+DAA+D;IAC/D,OAAO,CAAC,aAAa,CAAqB;IAE1C,kDAAkD;IAClD,OAAO,CAAC,gBAAgB,CAAiC;IAEzD;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI;IAIxD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,IAAI;IAMvD;;;;;;;;;OASG;IACH,UAAU,CACR,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,UAAU,GAAG,QAAQ,GAAG,QAAQ;IAmCnC;;;;;;;OAOG;IACG,eAAe,CACnB,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,kBAAkB,CAAC;IA0C9B;;;OAGG;IACH,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAIpD;;;;OAIG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAItD;;OAEG;IACH,UAAU,IAAI,IAAI;CAGnB"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScopeManager — Whitelist/blacklist enforcement and scope elevation for MCPL.
|
|
3
|
+
*
|
|
4
|
+
* Manages per-feature-set scope configurations and evaluates whether actions
|
|
5
|
+
* are approved, denied, or require user prompting. Handles `scope/elevate`
|
|
6
|
+
* requests from servers.
|
|
7
|
+
*
|
|
8
|
+
* Spec references: Section 7 (Scoped Access).
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Glob Matching
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Simple glob-style pattern matching.
|
|
15
|
+
*
|
|
16
|
+
* Supported syntax:
|
|
17
|
+
* - `*` matches any sequence of characters except `/`
|
|
18
|
+
* - `**` matches any sequence of characters including `/`
|
|
19
|
+
* - All other characters are matched literally
|
|
20
|
+
*
|
|
21
|
+
* The pattern must match the entire text (anchored at both ends).
|
|
22
|
+
*/
|
|
23
|
+
function globMatch(pattern, text) {
|
|
24
|
+
// Convert glob pattern to a RegExp
|
|
25
|
+
let regexStr = '^';
|
|
26
|
+
let i = 0;
|
|
27
|
+
while (i < pattern.length) {
|
|
28
|
+
if (pattern[i] === '*' && pattern[i + 1] === '*') {
|
|
29
|
+
// `**` matches any characters including `/`
|
|
30
|
+
regexStr += '.*';
|
|
31
|
+
i += 2;
|
|
32
|
+
// Skip a trailing `/` after `**` if present (e.g., `**/foo`)
|
|
33
|
+
if (i < pattern.length && pattern[i] === '/') {
|
|
34
|
+
regexStr += '(?:/|$)';
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (pattern[i] === '*') {
|
|
39
|
+
// `*` matches any characters except `/`
|
|
40
|
+
regexStr += '[^/]*';
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
// Escape regex special characters
|
|
45
|
+
regexStr += escapeRegex(pattern[i]);
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
regexStr += '$';
|
|
50
|
+
try {
|
|
51
|
+
const regex = new RegExp(regexStr);
|
|
52
|
+
return regex.test(text);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// If the pattern produces an invalid regex, fall back to exact match
|
|
56
|
+
return pattern === text;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Escape a character for use in a RegExp. */
|
|
60
|
+
function escapeRegex(char) {
|
|
61
|
+
const special = /[.+?^${}()|[\]\\]/;
|
|
62
|
+
if (special.test(char)) {
|
|
63
|
+
return '\\' + char;
|
|
64
|
+
}
|
|
65
|
+
return char;
|
|
66
|
+
}
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// ScopeManager
|
|
69
|
+
// ============================================================================
|
|
70
|
+
/**
|
|
71
|
+
* Manages whitelist/blacklist enforcement and scope elevation for feature sets.
|
|
72
|
+
*
|
|
73
|
+
* Evaluation order (per spec Section 7.6):
|
|
74
|
+
* 1. Check approval cache (session-level)
|
|
75
|
+
* 2. Check blacklist (if any pattern matches -> denied)
|
|
76
|
+
* 3. Check whitelist (if any pattern matches -> approved)
|
|
77
|
+
* 4. Otherwise -> prompt
|
|
78
|
+
*/
|
|
79
|
+
export class ScopeManager {
|
|
80
|
+
/** Scope configs keyed by feature set name. */
|
|
81
|
+
configs = new Map();
|
|
82
|
+
/** Cached approvals: Set of `${featureSet}\0${label}` keys. */
|
|
83
|
+
approvalCache = new Set();
|
|
84
|
+
/** Optional handler for user-approval prompts. */
|
|
85
|
+
elevationHandler = null;
|
|
86
|
+
/**
|
|
87
|
+
* Set scope configuration for a single feature set.
|
|
88
|
+
*/
|
|
89
|
+
configure(featureSet, config) {
|
|
90
|
+
this.configs.set(featureSet, config);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Set scope configurations for multiple feature sets at once.
|
|
94
|
+
*/
|
|
95
|
+
configureAll(scopes) {
|
|
96
|
+
for (const [featureSet, config] of Object.entries(scopes)) {
|
|
97
|
+
this.configs.set(featureSet, config);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Check whether a label is approved, denied, or needs prompting
|
|
102
|
+
* for the given feature set.
|
|
103
|
+
*
|
|
104
|
+
* Evaluation order:
|
|
105
|
+
* 1. Approval cache hit -> 'approved'
|
|
106
|
+
* 2. Blacklist match -> 'denied'
|
|
107
|
+
* 3. Whitelist match -> 'approved'
|
|
108
|
+
* 4. No config or no match -> 'prompt'
|
|
109
|
+
*/
|
|
110
|
+
checkScope(featureSet, label) {
|
|
111
|
+
// 1. Check approval cache
|
|
112
|
+
if (this.approvalCache.has(cacheKey(featureSet, label))) {
|
|
113
|
+
return 'approved';
|
|
114
|
+
}
|
|
115
|
+
const config = this.configs.get(featureSet);
|
|
116
|
+
// No config for this feature set -> prompt
|
|
117
|
+
if (!config) {
|
|
118
|
+
return 'prompt';
|
|
119
|
+
}
|
|
120
|
+
// 2. Check blacklist first (deny wins)
|
|
121
|
+
if (config.blacklist) {
|
|
122
|
+
for (const pattern of config.blacklist) {
|
|
123
|
+
if (globMatch(pattern, label)) {
|
|
124
|
+
return 'denied';
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// 3. Check whitelist
|
|
129
|
+
if (config.whitelist) {
|
|
130
|
+
for (const pattern of config.whitelist) {
|
|
131
|
+
if (globMatch(pattern, label)) {
|
|
132
|
+
return 'approved';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// 4. Neither matched
|
|
137
|
+
return 'prompt';
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Handle a `scope/elevate` request from a server.
|
|
141
|
+
*
|
|
142
|
+
* Checks scope against whitelist/blacklist, then:
|
|
143
|
+
* - 'approved' -> return approved with payload
|
|
144
|
+
* - 'denied' -> return denied with reason
|
|
145
|
+
* - 'prompt' -> invoke elevation handler if registered, otherwise deny
|
|
146
|
+
*/
|
|
147
|
+
async handleElevation(params) {
|
|
148
|
+
const { featureSet, scope } = params;
|
|
149
|
+
const result = this.checkScope(featureSet, scope.label);
|
|
150
|
+
if (result === 'approved') {
|
|
151
|
+
return {
|
|
152
|
+
approved: true,
|
|
153
|
+
payload: scope.payload,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
if (result === 'denied') {
|
|
157
|
+
return {
|
|
158
|
+
approved: false,
|
|
159
|
+
reason: 'Scope denied by blacklist',
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// result === 'prompt'
|
|
163
|
+
if (this.elevationHandler) {
|
|
164
|
+
const approved = await this.elevationHandler(featureSet, scope);
|
|
165
|
+
if (approved) {
|
|
166
|
+
// Cache the approval for the session
|
|
167
|
+
this.cacheApproval(featureSet, scope.label);
|
|
168
|
+
return {
|
|
169
|
+
approved: true,
|
|
170
|
+
payload: scope.payload,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
approved: false,
|
|
175
|
+
reason: 'User denied the elevation request',
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// No handler registered — default to denied
|
|
179
|
+
return {
|
|
180
|
+
approved: false,
|
|
181
|
+
reason: 'User approval required',
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Register a custom elevation handler for user-approval prompts.
|
|
186
|
+
* The handler is called when a scope check returns 'prompt'.
|
|
187
|
+
*/
|
|
188
|
+
setElevationHandler(handler) {
|
|
189
|
+
this.elevationHandler = handler;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Cache an approval for the session.
|
|
193
|
+
* Subsequent `checkScope()` calls with the same feature set and label
|
|
194
|
+
* will return 'approved' without re-evaluating patterns.
|
|
195
|
+
*/
|
|
196
|
+
cacheApproval(featureSet, label) {
|
|
197
|
+
this.approvalCache.add(cacheKey(featureSet, label));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Clear all cached approvals.
|
|
201
|
+
*/
|
|
202
|
+
clearCache() {
|
|
203
|
+
this.approvalCache.clear();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// ============================================================================
|
|
207
|
+
// Helpers
|
|
208
|
+
// ============================================================================
|
|
209
|
+
/** Build a cache key from feature set and label. */
|
|
210
|
+
function cacheKey(featureSet, label) {
|
|
211
|
+
return `${featureSet}\0${label}`;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=scope-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-manager.js","sourceRoot":"","sources":["../../../src/mcpl/scope-manager.ts"],"names":[],"mappings":"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"}
|