@animalabs/agent-framework 0.1.0 → 0.3.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/dist/src/framework.d.ts +13 -0
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +133 -10
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts +5 -0
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/event-gate.js +104 -6
- package/dist/src/gate/event-gate.js.map +1 -1
- package/dist/src/gate/types.d.ts +31 -0
- package/dist/src/gate/types.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +16 -2
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +101 -6
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/push-handler.js +1 -1
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +17 -2
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +66 -3
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/tool-policy.d.ts +24 -0
- package/dist/src/mcpl/tool-policy.d.ts.map +1 -0
- package/dist/src/mcpl/tool-policy.js +46 -0
- package/dist/src/mcpl/tool-policy.js.map +1 -0
- package/dist/src/mcpl/types.d.ts +31 -0
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +43 -1
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +246 -32
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/sync.d.ts +7 -2
- package/dist/src/modules/workspace/sync.d.ts.map +1 -1
- package/dist/src/modules/workspace/sync.js +2 -2
- package/dist/src/modules/workspace/sync.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +55 -3
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js +8 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts +40 -3
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js +80 -13
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/types/trace.d.ts +20 -0
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/src/usage/index.d.ts +3 -0
- package/dist/src/usage/index.d.ts.map +1 -0
- package/dist/src/usage/index.js +2 -0
- package/dist/src/usage/index.js.map +1 -0
- package/dist/src/usage/types.d.ts +28 -0
- package/dist/src/usage/types.d.ts.map +1 -0
- package/dist/src/usage/types.js +2 -0
- package/dist/src/usage/types.js.map +1 -0
- package/dist/src/usage/usage-tracker.d.ts +33 -0
- package/dist/src/usage/usage-tracker.d.ts.map +1 -0
- package/dist/src/usage/usage-tracker.js +115 -0
- package/dist/src/usage/usage-tracker.js.map +1 -0
- package/dist/test/channel-registry-typing.test.d.ts +2 -0
- package/dist/test/channel-registry-typing.test.d.ts.map +1 -0
- package/dist/test/channel-registry-typing.test.js +82 -0
- package/dist/test/channel-registry-typing.test.js.map +1 -0
- package/dist/test/event-gate.test.js +135 -16
- package/dist/test/event-gate.test.js.map +1 -1
- package/dist/test/mcpl-gate-roundtrip.test.d.ts +2 -0
- package/dist/test/mcpl-gate-roundtrip.test.d.ts.map +1 -0
- package/dist/test/mcpl-gate-roundtrip.test.js +140 -0
- package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -0
- package/dist/test/tool-policy.test.d.ts +2 -0
- package/dist/test/tool-policy.test.d.ts.map +1 -0
- package/dist/test/tool-policy.test.js +51 -0
- package/dist/test/tool-policy.test.js.map +1 -0
- package/dist/test/usage-tracker.test.d.ts +2 -0
- package/dist/test/usage-tracker.test.d.ts.map +1 -0
- package/dist/test/usage-tracker.test.js +129 -0
- package/dist/test/usage-tracker.test.js.map +1 -0
- package/dist/test/workspace-watcher.test.d.ts +2 -0
- package/dist/test/workspace-watcher.test.d.ts.map +1 -0
- package/dist/test/workspace-watcher.test.js +117 -0
- package/dist/test/workspace-watcher.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/framework.ts +148 -10
- package/src/gate/event-gate.ts +106 -6
- package/src/gate/types.ts +28 -0
- package/src/index.ts +7 -0
- package/src/mcpl/channel-registry.ts +120 -8
- package/src/mcpl/push-handler.ts +1 -1
- package/src/mcpl/server-connection.ts +78 -3
- package/src/mcpl/tool-policy.ts +52 -0
- package/src/mcpl/types.ts +34 -0
- package/src/modules/workspace/index.ts +269 -38
- package/src/modules/workspace/sync.ts +11 -4
- package/src/modules/workspace/types.ts +70 -3
- package/src/modules/workspace/watcher.ts +104 -15
- package/src/types/trace.ts +26 -1
- package/src/usage/index.ts +2 -0
- package/src/usage/types.ts +27 -0
- package/src/usage/usage-tracker.ts +141 -0
package/dist/src/framework.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ import type { Membrane } from '@animalabs/membrane';
|
|
|
3
3
|
import { ContextManager } from '@animalabs/context-manager';
|
|
4
4
|
import type { FrameworkConfig, TraceEventListener, InferenceLogQuery, InferenceLogQueryResult, InferenceLogEntryWithId, ProcessLogQuery, ProcessLogQueryResult, ProcessLogEntryWithId, ProcessEvent, ToolCall, ToolResult, AgentConfig, Module } from './types/index.js';
|
|
5
5
|
import { Agent } from './agent.js';
|
|
6
|
+
import { ChannelRegistry } from './mcpl/channel-registry.js';
|
|
7
|
+
import type { SessionUsageSnapshot } from './usage/types.js';
|
|
6
8
|
/**
|
|
7
9
|
* The main agent framework.
|
|
8
10
|
*/
|
|
@@ -46,6 +48,7 @@ export declare class AgentFramework {
|
|
|
46
48
|
/** Maps serverId → McplServerConfig for prefix lookup. */
|
|
47
49
|
private mcplServerConfigs;
|
|
48
50
|
private eventGate;
|
|
51
|
+
private usageTracker;
|
|
49
52
|
private constructor();
|
|
50
53
|
/**
|
|
51
54
|
* Create and start the framework.
|
|
@@ -67,6 +70,13 @@ export declare class AgentFramework {
|
|
|
67
70
|
* Add a trace event listener for observability.
|
|
68
71
|
*/
|
|
69
72
|
onTrace(listener: TraceEventListener): void;
|
|
73
|
+
/**
|
|
74
|
+
* Public accessor for the MCPL channel registry.
|
|
75
|
+
* Null when no MCPL servers are configured.
|
|
76
|
+
* Modules that need channel-level operations (typing indicators, default publish channel,
|
|
77
|
+
* etc.) obtain them here.
|
|
78
|
+
*/
|
|
79
|
+
get channels(): ChannelRegistry | null;
|
|
70
80
|
/**
|
|
71
81
|
* Remove a trace event listener.
|
|
72
82
|
*/
|
|
@@ -118,6 +128,9 @@ export declare class AgentFramework {
|
|
|
118
128
|
* Get the Membrane instance.
|
|
119
129
|
*/
|
|
120
130
|
getMembrane(): Membrane;
|
|
131
|
+
getSessionUsage(): SessionUsageSnapshot;
|
|
132
|
+
private restoreUsageState;
|
|
133
|
+
private persistUsageState;
|
|
121
134
|
/**
|
|
122
135
|
* Create an ephemeral agent that is NOT registered in the main event loop.
|
|
123
136
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../src/framework.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAqF,MAAM,qBAAqB,CAAC;AACvI,OAAO,EAAE,cAAc,EAAuB,MAAM,4BAA4B,CAAC;AAQjF,OAAO,KAAK,EACV,eAAe,EAMf,kBAAkB,EAElB,iBAAiB,EACjB,uBAAuB,EACvB,uBAAuB,EAGvB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EAErB,YAAY,EAGZ,QAAQ,EAER,UAAU,EACV,WAAW,EAGX,MAAM,EAEP,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"framework.d.ts","sourceRoot":"","sources":["../../src/framework.ts"],"names":[],"mappings":"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"}
|
package/dist/src/framework.js
CHANGED
|
@@ -13,7 +13,9 @@ import { InferenceRouter } from './mcpl/inference-router.js';
|
|
|
13
13
|
import { ChannelRegistry } from './mcpl/channel-registry.js';
|
|
14
14
|
import { safeSlice } from './safe-slice.js';
|
|
15
15
|
import { CheckpointManager } from './mcpl/checkpoint-manager.js';
|
|
16
|
+
import { isToolAllowed } from './mcpl/tool-policy.js';
|
|
16
17
|
import { EventGate } from './gate/event-gate.js';
|
|
18
|
+
import { UsageTracker } from './usage/usage-tracker.js';
|
|
17
19
|
const FRAMEWORK_STATE_ID = 'framework/state';
|
|
18
20
|
const INFERENCE_LOG_ID = 'framework/inference-log';
|
|
19
21
|
const PROCESS_LOG_ID = 'framework/process-log';
|
|
@@ -42,6 +44,37 @@ class DefaultErrorPolicy {
|
|
|
42
44
|
}
|
|
43
45
|
/** Default sync interval in milliseconds */
|
|
44
46
|
const DEFAULT_SYNC_INTERVAL_MS = 1000;
|
|
47
|
+
/**
|
|
48
|
+
* Extract fields the EventGate cares about from a ProcessEvent. The set of
|
|
49
|
+
* event variants that carry `content`/`mount`/`paths`/`metadata` is open-ended
|
|
50
|
+
* (modules can define CustomEvents), so we read by name rather than match the
|
|
51
|
+
* discriminant. Centralizing this lets new gate-visible fields be added in one
|
|
52
|
+
* place instead of retyping the narrowing at every call site.
|
|
53
|
+
*/
|
|
54
|
+
function extractGateFields(event) {
|
|
55
|
+
const rec = event;
|
|
56
|
+
const rawContent = rec.content;
|
|
57
|
+
let content = '';
|
|
58
|
+
if (typeof rawContent === 'string') {
|
|
59
|
+
content = rawContent;
|
|
60
|
+
}
|
|
61
|
+
else if (Array.isArray(rawContent)) {
|
|
62
|
+
// ContentBlock[] — concatenate text blocks so gate content filters match
|
|
63
|
+
content = rawContent
|
|
64
|
+
.filter((b) => !!b && typeof b === 'object' && b.type === 'text'
|
|
65
|
+
&& typeof b.text === 'string')
|
|
66
|
+
.map(b => b.text)
|
|
67
|
+
.join('\n');
|
|
68
|
+
}
|
|
69
|
+
const metadata = (rec.metadata && typeof rec.metadata === 'object')
|
|
70
|
+
? rec.metadata
|
|
71
|
+
: {};
|
|
72
|
+
const mount = typeof rec.mount === 'string' ? rec.mount : undefined;
|
|
73
|
+
const paths = Array.isArray(rec.paths)
|
|
74
|
+
? rec.paths.filter((p) => typeof p === 'string')
|
|
75
|
+
: undefined;
|
|
76
|
+
return { content, metadata, mount, paths };
|
|
77
|
+
}
|
|
45
78
|
/**
|
|
46
79
|
* The main agent framework.
|
|
47
80
|
*/
|
|
@@ -90,6 +123,8 @@ export class AgentFramework {
|
|
|
90
123
|
mcplServerConfigs = new Map();
|
|
91
124
|
// EventGate (null when FrameworkConfig.gate is omitted)
|
|
92
125
|
eventGate = null;
|
|
126
|
+
// Session-level token usage tracking (always-on)
|
|
127
|
+
usageTracker;
|
|
93
128
|
constructor(store, ownsStore, membrane, inferencePolicy, errorPolicy, syncIntervalMs, processLoggingPersist, processLoggingBroadcast) {
|
|
94
129
|
this.store = store;
|
|
95
130
|
this.ownsStore = ownsStore;
|
|
@@ -100,6 +135,9 @@ export class AgentFramework {
|
|
|
100
135
|
this.processLoggingPersist = processLoggingPersist;
|
|
101
136
|
this.processLoggingBroadcast = processLoggingBroadcast;
|
|
102
137
|
this.queue = new ProcessQueueImpl();
|
|
138
|
+
this.usageTracker = new UsageTracker({
|
|
139
|
+
emitTrace: (e) => this.emitTrace({ ...e }),
|
|
140
|
+
});
|
|
103
141
|
// Initialize module registry with callbacks
|
|
104
142
|
this.moduleRegistry = new ModuleRegistry(store, this.queue, {
|
|
105
143
|
getAgents: () => Array.from(this.agents.values()),
|
|
@@ -171,6 +209,8 @@ export class AgentFramework {
|
|
|
171
209
|
}
|
|
172
210
|
}
|
|
173
211
|
const framework = new AgentFramework(store, ownsStore, config.membrane, config.inferencePolicy ?? new DefaultInferencePolicy(), config.errorPolicy ?? new DefaultErrorPolicy(), config.syncIntervalMs ?? DEFAULT_SYNC_INTERVAL_MS, processLoggingPersist, processLoggingBroadcast);
|
|
212
|
+
// Restore persisted usage data (if any) from prior session
|
|
213
|
+
framework.restoreUsageState();
|
|
174
214
|
// Create agents
|
|
175
215
|
for (const agentConfig of config.agents) {
|
|
176
216
|
await framework.createAgent(agentConfig);
|
|
@@ -296,6 +336,15 @@ export class AgentFramework {
|
|
|
296
336
|
onTrace(listener) {
|
|
297
337
|
this.traceListeners.push(listener);
|
|
298
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* Public accessor for the MCPL channel registry.
|
|
341
|
+
* Null when no MCPL servers are configured.
|
|
342
|
+
* Modules that need channel-level operations (typing indicators, default publish channel,
|
|
343
|
+
* etc.) obtain them here.
|
|
344
|
+
*/
|
|
345
|
+
get channels() {
|
|
346
|
+
return this.channelRegistry;
|
|
347
|
+
}
|
|
299
348
|
/**
|
|
300
349
|
* Remove a trace event listener.
|
|
301
350
|
*/
|
|
@@ -390,6 +439,35 @@ export class AgentFramework {
|
|
|
390
439
|
getMembrane() {
|
|
391
440
|
return this.membrane;
|
|
392
441
|
}
|
|
442
|
+
getSessionUsage() {
|
|
443
|
+
return this.usageTracker.getSnapshot();
|
|
444
|
+
}
|
|
445
|
+
restoreUsageState() {
|
|
446
|
+
try {
|
|
447
|
+
const data = this.store.getStateJson(FRAMEWORK_STATE_ID);
|
|
448
|
+
if (data && typeof data === 'object' && data.usage) {
|
|
449
|
+
const restored = data.usage;
|
|
450
|
+
this.usageTracker = new UsageTracker({
|
|
451
|
+
emitTrace: (e) => this.emitTrace({ ...e }),
|
|
452
|
+
restored,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch {
|
|
457
|
+
// No prior state or corrupt — start fresh (already initialized in constructor)
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
persistUsageState() {
|
|
461
|
+
try {
|
|
462
|
+
const data = this.store.getStateJson(FRAMEWORK_STATE_ID);
|
|
463
|
+
const state = (data && typeof data === 'object' ? data : {});
|
|
464
|
+
state.usage = this.usageTracker.toJSON();
|
|
465
|
+
this.store.setStateJson(FRAMEWORK_STATE_ID, state);
|
|
466
|
+
}
|
|
467
|
+
catch {
|
|
468
|
+
// Non-fatal — usage tracking is best-effort
|
|
469
|
+
}
|
|
470
|
+
}
|
|
393
471
|
/**
|
|
394
472
|
* Create an ephemeral agent that is NOT registered in the main event loop.
|
|
395
473
|
*
|
|
@@ -1141,13 +1219,11 @@ export class AgentFramework {
|
|
|
1141
1219
|
const source = 'source' in event ? event.source : 'unknown';
|
|
1142
1220
|
// Gate non-MCPL events (MCPL events are already gated in PushHandler/ChannelRegistry)
|
|
1143
1221
|
if (this.eventGate && event.type !== 'mcpl:push-event' && event.type !== 'mcpl:channel-incoming') {
|
|
1144
|
-
const content = 'content' in event ? String(event.content) : '';
|
|
1145
1222
|
const decision = this.eventGate.evaluate({
|
|
1146
|
-
|
|
1223
|
+
...extractGateFields(event),
|
|
1147
1224
|
eventType: event.type,
|
|
1148
1225
|
serverId: source,
|
|
1149
1226
|
channelId: '',
|
|
1150
|
-
metadata: 'metadata' in event ? event.metadata : {},
|
|
1151
1227
|
});
|
|
1152
1228
|
if (!decision.trigger)
|
|
1153
1229
|
return;
|
|
@@ -1483,12 +1559,13 @@ export class AgentFramework {
|
|
|
1483
1559
|
const allText = response.content.filter(isTextBlock);
|
|
1484
1560
|
const speechContent = hadToolCalls ? [] : allText;
|
|
1485
1561
|
const thoughts = hadToolCalls ? allText : [];
|
|
1486
|
-
const
|
|
1562
|
+
const du = response.details?.usage;
|
|
1563
|
+
const tokenUsage = du
|
|
1487
1564
|
? {
|
|
1488
|
-
input:
|
|
1489
|
-
output:
|
|
1490
|
-
cacheCreation:
|
|
1491
|
-
cacheRead:
|
|
1565
|
+
input: du.inputTokens,
|
|
1566
|
+
output: du.outputTokens,
|
|
1567
|
+
cacheCreation: du.cacheCreationTokens,
|
|
1568
|
+
cacheRead: du.cacheReadTokens,
|
|
1492
1569
|
}
|
|
1493
1570
|
: undefined;
|
|
1494
1571
|
this.emitTrace({
|
|
@@ -1497,6 +1574,15 @@ export class AgentFramework {
|
|
|
1497
1574
|
durationMs,
|
|
1498
1575
|
tokenUsage,
|
|
1499
1576
|
});
|
|
1577
|
+
if (du) {
|
|
1578
|
+
this.usageTracker.onInferenceCompleted(agent.name, {
|
|
1579
|
+
inputTokens: du.inputTokens,
|
|
1580
|
+
outputTokens: du.outputTokens,
|
|
1581
|
+
cacheCreationTokens: du.cacheCreationTokens,
|
|
1582
|
+
cacheReadTokens: du.cacheReadTokens,
|
|
1583
|
+
}, du.estimatedCost ? { total: du.estimatedCost.total, currency: du.estimatedCost.currency } : undefined);
|
|
1584
|
+
this.persistUsageState();
|
|
1585
|
+
}
|
|
1500
1586
|
// Log inference
|
|
1501
1587
|
this.logInference({
|
|
1502
1588
|
timestamp: startTime,
|
|
@@ -1590,6 +1676,8 @@ export class AgentFramework {
|
|
|
1590
1676
|
tokenUsage: {
|
|
1591
1677
|
input: event.usage.inputTokens,
|
|
1592
1678
|
output: event.usage.outputTokens,
|
|
1679
|
+
cacheCreation: event.usage.cacheCreationTokens,
|
|
1680
|
+
cacheRead: event.usage.cacheReadTokens,
|
|
1593
1681
|
},
|
|
1594
1682
|
});
|
|
1595
1683
|
break;
|
|
@@ -1657,6 +1745,13 @@ export class AgentFramework {
|
|
|
1657
1745
|
}
|
|
1658
1746
|
const prefix = config.toolPrefix ?? `mcpl--${config.id}`;
|
|
1659
1747
|
const toolName = call.name.slice(prefix.length + 2); // Strip prefix + '--'
|
|
1748
|
+
if (!isToolAllowed(toolName, config)) {
|
|
1749
|
+
return {
|
|
1750
|
+
success: false,
|
|
1751
|
+
error: `Tool '${call.name}' is not permitted by this server's tool policy.`,
|
|
1752
|
+
isError: true,
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1660
1755
|
try {
|
|
1661
1756
|
const result = await server.sendToolsCall(toolName, call.input);
|
|
1662
1757
|
return {
|
|
@@ -1948,10 +2043,10 @@ export class AgentFramework {
|
|
|
1948
2043
|
this.checkpointManager = new CheckpointManager(this.store, (event) => this.emitTrace(event));
|
|
1949
2044
|
// Channel registry (Step 7)
|
|
1950
2045
|
this.channelRegistry = new ChannelRegistry(this.mcplServerRegistry, this.featureSetManager, (event) => this.pushEvent(event), (event) => this.emitTrace(event), {
|
|
1951
|
-
sendTypingFn: (serverId, channelId) => {
|
|
2046
|
+
sendTypingFn: (serverId, channelId, metadata, op) => {
|
|
1952
2047
|
const server = this.mcplServerRegistry.getServer(serverId);
|
|
1953
2048
|
if (server) {
|
|
1954
|
-
server.sendChannelsTyping(channelId);
|
|
2049
|
+
server.sendChannelsTyping(channelId, metadata, op);
|
|
1955
2050
|
}
|
|
1956
2051
|
},
|
|
1957
2052
|
shouldTriggerInference: triggerFilter,
|
|
@@ -1968,6 +2063,11 @@ export class AgentFramework {
|
|
|
1968
2063
|
};
|
|
1969
2064
|
for (const config of serverConfigs) {
|
|
1970
2065
|
try {
|
|
2066
|
+
// Record per-server channel subscription policy before the server
|
|
2067
|
+
// registers channels — handleRegister fires during the handshake.
|
|
2068
|
+
if (config.channelSubscription !== undefined && this.channelRegistry) {
|
|
2069
|
+
this.channelRegistry.setSubscriptionPolicy(config.id, config.channelSubscription);
|
|
2070
|
+
}
|
|
1971
2071
|
const connection = await this.mcplServerRegistry.addServer(config, hostCapabilities);
|
|
1972
2072
|
// Wire event listeners then flush any events that arrived during the
|
|
1973
2073
|
// handshake window (between setupMessageRouting and now).
|
|
@@ -2018,6 +2118,11 @@ export class AgentFramework {
|
|
|
2018
2118
|
* Push events and inference requests are deferred to Steps 6/7.
|
|
2019
2119
|
*/
|
|
2020
2120
|
wireMcplEvents(connection) {
|
|
2121
|
+
// Forward subprocess stderr lines as trace events so consumers (conhost,
|
|
2122
|
+
// log sinks, TUI badges) can persist and surface them.
|
|
2123
|
+
connection.on('stderr', (params) => {
|
|
2124
|
+
this.emitTrace({ type: 'mcpl:server-stderr', serverId: connection.id, line: params.line });
|
|
2125
|
+
});
|
|
2021
2126
|
// Handle dynamic feature set changes from server
|
|
2022
2127
|
connection.on('feature-sets-changed', (params) => {
|
|
2023
2128
|
this.featureSetManager?.handleFeatureSetsChanged(connection.id, params);
|
|
@@ -2090,6 +2195,8 @@ export class AgentFramework {
|
|
|
2090
2195
|
try {
|
|
2091
2196
|
const result = await server.sendToolsList();
|
|
2092
2197
|
for (const tool of result.tools) {
|
|
2198
|
+
if (!isToolAllowed(tool.name, config))
|
|
2199
|
+
continue;
|
|
2093
2200
|
// MCP tool schemas are generic JSON Schema; cast to membrane's ToolDefinition format
|
|
2094
2201
|
const schema = tool.inputSchema;
|
|
2095
2202
|
tools.push({
|
|
@@ -2170,6 +2277,22 @@ export class AgentFramework {
|
|
|
2170
2277
|
});
|
|
2171
2278
|
return;
|
|
2172
2279
|
}
|
|
2280
|
+
const config = this.mcplServerConfigs.get(serverId);
|
|
2281
|
+
if (!isToolAllowed(toolName, config)) {
|
|
2282
|
+
this.emitTrace({ type: 'tool:failed', module: `mcpl:${serverId}`, tool: toolName, callId: call.id, error: 'denied by tool policy' });
|
|
2283
|
+
this.pushEvent({
|
|
2284
|
+
type: 'tool-result',
|
|
2285
|
+
callId: call.id,
|
|
2286
|
+
agentName,
|
|
2287
|
+
moduleName: `mcpl:${serverId}`,
|
|
2288
|
+
result: {
|
|
2289
|
+
success: false,
|
|
2290
|
+
error: `Tool '${call.name}' is not permitted by this server's tool policy.`,
|
|
2291
|
+
isError: true,
|
|
2292
|
+
},
|
|
2293
|
+
});
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2173
2296
|
this.emitTrace({ type: 'tool:started', module: `mcpl:${serverId}`, tool: toolName, callId: call.id, input: call.input });
|
|
2174
2297
|
const startTime = Date.now();
|
|
2175
2298
|
const args = (call.input && typeof call.input === 'object') ? call.input : {};
|