@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
package/src/queue.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { ProcessEvent, ProcessQueue } from './types/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Process queue for the framework.
|
|
5
|
+
* ProcessEvents from external sources and internal operations flow through here.
|
|
6
|
+
*/
|
|
7
|
+
export class ProcessQueueImpl implements ProcessQueue {
|
|
8
|
+
private queue: ProcessEvent[] = [];
|
|
9
|
+
private waiters: Array<(event: ProcessEvent) => void> = [];
|
|
10
|
+
private closed = false;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Push a process event to the queue.
|
|
14
|
+
*/
|
|
15
|
+
push(event: ProcessEvent): void {
|
|
16
|
+
if (this.closed) {
|
|
17
|
+
throw new Error('Queue is closed');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// If someone is waiting, deliver immediately
|
|
21
|
+
const waiter = this.waiters.shift();
|
|
22
|
+
if (waiter) {
|
|
23
|
+
waiter(event);
|
|
24
|
+
} else if (event.type === 'external-message') {
|
|
25
|
+
// User input jumps to front so it's processed before queued internal events
|
|
26
|
+
this.queue.unshift(event);
|
|
27
|
+
} else {
|
|
28
|
+
this.queue.push(event);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Pop the next process event from the queue.
|
|
34
|
+
* Returns immediately if an event is available, otherwise waits.
|
|
35
|
+
*/
|
|
36
|
+
async pop(): Promise<ProcessEvent> {
|
|
37
|
+
if (this.closed) {
|
|
38
|
+
throw new Error('Queue is closed');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If there's an event waiting, return it
|
|
42
|
+
const event = this.queue.shift();
|
|
43
|
+
if (event) {
|
|
44
|
+
return event;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Otherwise, wait for one
|
|
48
|
+
return new Promise((resolve) => {
|
|
49
|
+
this.waiters.push(resolve);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Try to pop a process event without waiting.
|
|
55
|
+
* Returns null if queue is empty.
|
|
56
|
+
*/
|
|
57
|
+
tryPop(): ProcessEvent | null {
|
|
58
|
+
return this.queue.shift() ?? null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Peek at the next process event without removing it.
|
|
63
|
+
*/
|
|
64
|
+
peek(): ProcessEvent | null {
|
|
65
|
+
return this.queue[0] ?? null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get current queue depth.
|
|
70
|
+
*/
|
|
71
|
+
get depth(): number {
|
|
72
|
+
return this.queue.length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if queue is empty.
|
|
77
|
+
*/
|
|
78
|
+
get isEmpty(): boolean {
|
|
79
|
+
return this.queue.length === 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Clear all events from the queue.
|
|
84
|
+
*/
|
|
85
|
+
clear(): void {
|
|
86
|
+
this.queue = [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Close the queue.
|
|
91
|
+
* Rejects any pending waiters.
|
|
92
|
+
*/
|
|
93
|
+
close(): void {
|
|
94
|
+
this.closed = true;
|
|
95
|
+
// Reject pending waiters by not resolving them
|
|
96
|
+
// In a real implementation, we might want to reject with an error
|
|
97
|
+
this.waiters = [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Check if queue is closed.
|
|
102
|
+
*/
|
|
103
|
+
get isClosed(): boolean {
|
|
104
|
+
return this.closed;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slice a string without splitting surrogate pairs.
|
|
3
|
+
*
|
|
4
|
+
* Regular String.prototype.slice can cut in the middle of a surrogate pair,
|
|
5
|
+
* producing invalid UTF-16. This function adjusts the end index to avoid that.
|
|
6
|
+
*/
|
|
7
|
+
export function safeSlice(str: string, start: number, end: number): string {
|
|
8
|
+
if (end >= str.length) return str.slice(start);
|
|
9
|
+
|
|
10
|
+
// If we're about to cut between a high and low surrogate, back up one char
|
|
11
|
+
const code = str.charCodeAt(end - 1);
|
|
12
|
+
if (code >= 0xd800 && code <= 0xdbff) {
|
|
13
|
+
// end-1 is a high surrogate — don't split the pair
|
|
14
|
+
return str.slice(start, end - 1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return str.slice(start, end);
|
|
18
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { ContentBlock, YieldingStream } from '@animalabs/membrane';
|
|
2
|
+
import type { ContextStrategy } from '@animalabs/context-manager';
|
|
3
|
+
import type { ToolCallId, ToolResult, ToolCall } from './events.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for an agent.
|
|
7
|
+
*/
|
|
8
|
+
export interface AgentConfig {
|
|
9
|
+
/** Unique name for this agent */
|
|
10
|
+
name: string;
|
|
11
|
+
|
|
12
|
+
/** Model to use (e.g., 'claude-sonnet-4-20250514') */
|
|
13
|
+
model: string;
|
|
14
|
+
|
|
15
|
+
/** System prompt */
|
|
16
|
+
systemPrompt: string;
|
|
17
|
+
|
|
18
|
+
/** Context management strategy */
|
|
19
|
+
strategy?: ContextStrategy;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Which tools this agent can use.
|
|
23
|
+
* - 'all': all available tools
|
|
24
|
+
* - string[]: specific tool names (with module prefix)
|
|
25
|
+
*/
|
|
26
|
+
allowedTools?: 'all' | string[];
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Which modules can trigger inference for this agent.
|
|
30
|
+
* - 'all': any module
|
|
31
|
+
* - string[]: specific module names
|
|
32
|
+
*/
|
|
33
|
+
triggerSources?: 'all' | string[];
|
|
34
|
+
|
|
35
|
+
/** Maximum tokens for response */
|
|
36
|
+
maxTokens?: number;
|
|
37
|
+
|
|
38
|
+
/** Temperature for inference */
|
|
39
|
+
temperature?: number;
|
|
40
|
+
|
|
41
|
+
/** Max input tokens before framework breaks a yielding stream and
|
|
42
|
+
* restarts with recompiled (compressed) context. Default: 150000. */
|
|
43
|
+
maxStreamTokens?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Result of running inference.
|
|
48
|
+
*/
|
|
49
|
+
export interface InferenceResult {
|
|
50
|
+
/** Tool calls to execute */
|
|
51
|
+
toolCalls: ToolCall[];
|
|
52
|
+
/** Speech content (text blocks) to send to handlers */
|
|
53
|
+
speechContent: ContentBlock[];
|
|
54
|
+
/** Raw request/response for logging */
|
|
55
|
+
raw?: {
|
|
56
|
+
request: unknown;
|
|
57
|
+
response: unknown;
|
|
58
|
+
};
|
|
59
|
+
/** Usage stats */
|
|
60
|
+
usage?: {
|
|
61
|
+
inputTokens: number;
|
|
62
|
+
outputTokens: number;
|
|
63
|
+
};
|
|
64
|
+
/** Stop reason */
|
|
65
|
+
stopReason?: string;
|
|
66
|
+
/** Whether inference was aborted */
|
|
67
|
+
aborted?: boolean;
|
|
68
|
+
/** Reason for abort, if available */
|
|
69
|
+
abortReason?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Options for running inference.
|
|
74
|
+
*/
|
|
75
|
+
export interface InferenceOptions {
|
|
76
|
+
/** Abort signal for cancellation */
|
|
77
|
+
signal?: AbortSignal;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Internal state of an agent.
|
|
82
|
+
*/
|
|
83
|
+
export type AgentState =
|
|
84
|
+
| { status: 'idle' }
|
|
85
|
+
| { status: 'inferring'; promise: Promise<InferenceResult>; abortController: AbortController }
|
|
86
|
+
| { status: 'streaming'; stream: YieldingStream }
|
|
87
|
+
| { status: 'waiting_for_tools'; pending: Map<ToolCallId, PendingToolCall>; completed: CompletedToolCall[]; stream?: YieldingStream }
|
|
88
|
+
| { status: 'ready'; toolResults: CompletedToolCall[]; stream?: YieldingStream };
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A tool call that's in progress.
|
|
92
|
+
*/
|
|
93
|
+
export interface PendingToolCall {
|
|
94
|
+
id: ToolCallId;
|
|
95
|
+
name: string;
|
|
96
|
+
input: unknown;
|
|
97
|
+
startedAt: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A tool call that has completed.
|
|
102
|
+
*/
|
|
103
|
+
export interface CompletedToolCall {
|
|
104
|
+
id: ToolCallId;
|
|
105
|
+
name: string;
|
|
106
|
+
input: unknown;
|
|
107
|
+
result: ToolResult;
|
|
108
|
+
durationMs: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Inference request for an agent.
|
|
113
|
+
*/
|
|
114
|
+
export interface InferenceRequest {
|
|
115
|
+
agentName: string;
|
|
116
|
+
reason: string;
|
|
117
|
+
source: string;
|
|
118
|
+
timestamp: number;
|
|
119
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type { ContentBlock, ToolDefinition as MembraneToolDefinition } from '@animalabs/membrane';
|
|
2
|
+
import type { MessageId } from '@animalabs/context-manager';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Unique identifier for a tool call.
|
|
6
|
+
*/
|
|
7
|
+
export type ToolCallId = string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Re-export membrane's ToolDefinition for modules to use.
|
|
11
|
+
*/
|
|
12
|
+
export type ToolDefinition = MembraneToolDefinition;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Events that flow through the framework's processing queue.
|
|
16
|
+
*
|
|
17
|
+
* ProcessEvents represent work to be done — modules respond to them via onProcess().
|
|
18
|
+
* They are distinct from TraceEvents, which are observability-only notifications.
|
|
19
|
+
*
|
|
20
|
+
* Modules can define their own namespaced events (e.g., 'api:message', 'discord:reaction').
|
|
21
|
+
*/
|
|
22
|
+
export type ProcessEvent =
|
|
23
|
+
| ExternalMessageEvent
|
|
24
|
+
| ToolCallEvent
|
|
25
|
+
| ToolResultEvent
|
|
26
|
+
| TimerFiredEvent
|
|
27
|
+
| InferenceRequestEvent
|
|
28
|
+
| MessageEditedEvent
|
|
29
|
+
| MessageRemovedEvent
|
|
30
|
+
| ModuleEvent
|
|
31
|
+
| ApiMessageEvent
|
|
32
|
+
| ApiInferenceRequestEvent
|
|
33
|
+
| McplPushEvent
|
|
34
|
+
| McplChannelIncomingEvent
|
|
35
|
+
| CustomEvent;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* API message event - from the API server.
|
|
39
|
+
*/
|
|
40
|
+
export interface ApiMessageEvent {
|
|
41
|
+
type: 'api:message';
|
|
42
|
+
participant: string;
|
|
43
|
+
content: string;
|
|
44
|
+
metadata?: Record<string, unknown>;
|
|
45
|
+
triggerInference?: boolean;
|
|
46
|
+
targetAgents?: string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* API inference request - from the API server.
|
|
51
|
+
*/
|
|
52
|
+
export interface ApiInferenceRequestEvent {
|
|
53
|
+
type: 'api:inference-request';
|
|
54
|
+
agentName?: string;
|
|
55
|
+
reason?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Generic custom event for module-specific namespaced events.
|
|
60
|
+
* Use this for events like 'discord:message', 'slack:reaction', etc.
|
|
61
|
+
*/
|
|
62
|
+
export interface CustomEvent {
|
|
63
|
+
type: `${string}:${string}`;
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Message from an external source (Discord, HTTP, CLI, etc.)
|
|
69
|
+
*/
|
|
70
|
+
export interface ExternalMessageEvent {
|
|
71
|
+
type: 'external-message';
|
|
72
|
+
/** Module that produced this event */
|
|
73
|
+
source: string;
|
|
74
|
+
/** Raw content from external system */
|
|
75
|
+
content: unknown;
|
|
76
|
+
/** External system metadata */
|
|
77
|
+
metadata: Record<string, unknown>;
|
|
78
|
+
/** Whether this should trigger inference */
|
|
79
|
+
triggerInference?: boolean;
|
|
80
|
+
/** Specific agents to trigger (if not all) */
|
|
81
|
+
targetAgents?: string[];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Result of a tool call.
|
|
86
|
+
*/
|
|
87
|
+
export interface ToolResultEvent {
|
|
88
|
+
type: 'tool-result';
|
|
89
|
+
/** ID of the original tool call */
|
|
90
|
+
callId: ToolCallId;
|
|
91
|
+
/** Agent that made the call */
|
|
92
|
+
agentName: string;
|
|
93
|
+
/** Module that handled the call */
|
|
94
|
+
moduleName: string;
|
|
95
|
+
/** Result of the tool call */
|
|
96
|
+
result: ToolResult;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Tool call scheduled for execution.
|
|
101
|
+
*/
|
|
102
|
+
export interface ToolCallEvent {
|
|
103
|
+
type: 'tool-call';
|
|
104
|
+
/** ID of the tool call */
|
|
105
|
+
callId: ToolCallId;
|
|
106
|
+
/** Agent that made the call */
|
|
107
|
+
agentName: string;
|
|
108
|
+
/** Module that will handle the call */
|
|
109
|
+
moduleName: string;
|
|
110
|
+
/** Un-prefixed tool name */
|
|
111
|
+
toolName: string;
|
|
112
|
+
/** Full tool call payload */
|
|
113
|
+
call: ToolCall;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Scheduled timer fired.
|
|
118
|
+
*/
|
|
119
|
+
export interface TimerFiredEvent {
|
|
120
|
+
type: 'timer-fired';
|
|
121
|
+
/** Timer identifier */
|
|
122
|
+
timerId: string;
|
|
123
|
+
/** Reason for the timer */
|
|
124
|
+
reason: string;
|
|
125
|
+
/** Specific agent to wake (if any) */
|
|
126
|
+
agentName?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Explicit request to run inference.
|
|
131
|
+
*/
|
|
132
|
+
export interface InferenceRequestEvent {
|
|
133
|
+
type: 'inference-request';
|
|
134
|
+
/** Agent to run inference for */
|
|
135
|
+
agentName: string;
|
|
136
|
+
/** Reason for the request */
|
|
137
|
+
reason: string;
|
|
138
|
+
/** Module that requested it */
|
|
139
|
+
source: string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* External message was edited.
|
|
144
|
+
*/
|
|
145
|
+
export interface MessageEditedEvent {
|
|
146
|
+
type: 'message-edited';
|
|
147
|
+
/** Module that produced this event */
|
|
148
|
+
source: string;
|
|
149
|
+
/** Our internal message ID */
|
|
150
|
+
messageId: MessageId;
|
|
151
|
+
/** New content */
|
|
152
|
+
newContent: ContentBlock[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* External message was removed.
|
|
157
|
+
*/
|
|
158
|
+
export interface MessageRemovedEvent {
|
|
159
|
+
type: 'message-removed';
|
|
160
|
+
/** Module that produced this event */
|
|
161
|
+
source: string;
|
|
162
|
+
/** Our internal message ID */
|
|
163
|
+
messageId: MessageId;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Generic module-specific event.
|
|
168
|
+
*/
|
|
169
|
+
export interface ModuleEvent {
|
|
170
|
+
type: 'module-event';
|
|
171
|
+
/** Module that produced this event */
|
|
172
|
+
source: string;
|
|
173
|
+
/** Module-specific event type */
|
|
174
|
+
eventType: string;
|
|
175
|
+
/** Module-specific payload */
|
|
176
|
+
payload: unknown;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Result of a tool execution.
|
|
181
|
+
*/
|
|
182
|
+
export interface ToolResult {
|
|
183
|
+
/** Whether the tool succeeded */
|
|
184
|
+
success: boolean;
|
|
185
|
+
/** Result data (if success) */
|
|
186
|
+
data?: unknown;
|
|
187
|
+
/** Error message (if failure) */
|
|
188
|
+
error?: string;
|
|
189
|
+
/** Whether this was an error (for LLM) */
|
|
190
|
+
isError?: boolean;
|
|
191
|
+
/**
|
|
192
|
+
* When true, the framework saves tool_use + tool_result messages to context,
|
|
193
|
+
* cancels the active stream, and resets the agent to idle.
|
|
194
|
+
* This is a "sleep until next event" primitive — the LLM expects the call to block.
|
|
195
|
+
* Adapted from Anarchid/agent-framework@mcpl-module-proto.
|
|
196
|
+
*/
|
|
197
|
+
endTurn?: boolean;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* A tool call from the LLM.
|
|
202
|
+
*/
|
|
203
|
+
export interface ToolCall {
|
|
204
|
+
/** Unique ID for this call */
|
|
205
|
+
id: ToolCallId;
|
|
206
|
+
/** Full tool name (module:tool) */
|
|
207
|
+
name: string;
|
|
208
|
+
/** Tool input */
|
|
209
|
+
input: unknown;
|
|
210
|
+
/** The agent that made this tool call. Set by the framework dispatch layer. */
|
|
211
|
+
callerAgentName?: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ============================================================================
|
|
215
|
+
// MCPL Events (Steps 6-7)
|
|
216
|
+
// ============================================================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Push event from an MCPL server (Section 9).
|
|
220
|
+
* Converted from wire-format McplContentBlock to membrane ContentBlock.
|
|
221
|
+
*/
|
|
222
|
+
export interface McplPushEvent {
|
|
223
|
+
type: 'mcpl:push-event';
|
|
224
|
+
serverId: string;
|
|
225
|
+
featureSet: string;
|
|
226
|
+
eventId: string;
|
|
227
|
+
content: ContentBlock[];
|
|
228
|
+
origin?: Record<string, unknown>;
|
|
229
|
+
timestamp: string;
|
|
230
|
+
inferenceId: string;
|
|
231
|
+
triggerInference?: boolean;
|
|
232
|
+
targetAgents?: string[];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Incoming channel message from an MCPL server (Section 14).
|
|
237
|
+
* Converted from wire-format McplContentBlock to membrane ContentBlock.
|
|
238
|
+
*/
|
|
239
|
+
export interface McplChannelIncomingEvent {
|
|
240
|
+
type: 'mcpl:channel-incoming';
|
|
241
|
+
serverId: string;
|
|
242
|
+
channelId: string;
|
|
243
|
+
messageId: string;
|
|
244
|
+
threadId?: string;
|
|
245
|
+
author: { id: string; name: string };
|
|
246
|
+
content: ContentBlock[];
|
|
247
|
+
timestamp: string;
|
|
248
|
+
metadata?: Record<string, unknown>;
|
|
249
|
+
triggerInference?: boolean;
|
|
250
|
+
targetAgents?: string[];
|
|
251
|
+
}
|
|
252
|
+
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import type { JsStore } from '@animalabs/chronicle';
|
|
2
|
+
import type { Membrane } from '@animalabs/membrane';
|
|
3
|
+
import type { Module, EventResponse } from './module.js';
|
|
4
|
+
import type { AgentConfig, InferenceRequest } from './agent.js';
|
|
5
|
+
import type { ProcessEvent } from './events.js';
|
|
6
|
+
import type { McplServerConfig, InferenceRoutingPolicy } from '../mcpl/types.js';
|
|
7
|
+
import type { GateOptions } from '../gate/types.js';
|
|
8
|
+
|
|
9
|
+
// Re-export trace types
|
|
10
|
+
export type { TraceEvent, TraceEventListener } from './trace.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A module's response to a process event, tagged with the module name.
|
|
14
|
+
*/
|
|
15
|
+
export interface ModuleProcessResponse {
|
|
16
|
+
moduleName: string;
|
|
17
|
+
response: EventResponse;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Configuration for process event logging.
|
|
22
|
+
*/
|
|
23
|
+
export interface ProcessLoggingConfig {
|
|
24
|
+
/** Persist process logs to Chronicle (default: false) */
|
|
25
|
+
persist?: boolean;
|
|
26
|
+
/** Broadcast process:completed trace events (default: false) */
|
|
27
|
+
broadcast?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Configuration for the agent framework.
|
|
32
|
+
*/
|
|
33
|
+
export interface FrameworkConfig {
|
|
34
|
+
/** Path to Chronicle store */
|
|
35
|
+
storePath?: string;
|
|
36
|
+
|
|
37
|
+
/** Or existing store (app-owned) */
|
|
38
|
+
store?: JsStore;
|
|
39
|
+
|
|
40
|
+
/** Membrane instance for LLM calls */
|
|
41
|
+
membrane: Membrane;
|
|
42
|
+
|
|
43
|
+
/** Agent configurations */
|
|
44
|
+
agents: AgentConfig[];
|
|
45
|
+
|
|
46
|
+
/** Modules to load */
|
|
47
|
+
modules: Module[];
|
|
48
|
+
|
|
49
|
+
/** Custom inference policy */
|
|
50
|
+
inferencePolicy?: InferencePolicy;
|
|
51
|
+
|
|
52
|
+
/** Custom error policy */
|
|
53
|
+
errorPolicy?: ErrorPolicy;
|
|
54
|
+
|
|
55
|
+
/** Interval for periodic store sync in milliseconds (default: 1000ms, 0 to disable) */
|
|
56
|
+
syncIntervalMs?: number;
|
|
57
|
+
|
|
58
|
+
/** Process logging configuration (default: disabled) */
|
|
59
|
+
processLogging?: ProcessLoggingConfig;
|
|
60
|
+
|
|
61
|
+
/** MCPL server configurations. If omitted or empty, no MCPL subsystems are created. */
|
|
62
|
+
mcplServers?: McplServerConfig[];
|
|
63
|
+
|
|
64
|
+
/** Inference routing policy for server-initiated inference (optional). */
|
|
65
|
+
inferenceRouting?: InferenceRoutingPolicy;
|
|
66
|
+
|
|
67
|
+
/** EventGate config. If omitted, all events trigger inference (unchanged default). */
|
|
68
|
+
gate?: GateOptions;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Policy for deciding when to run inference.
|
|
73
|
+
*/
|
|
74
|
+
export interface InferencePolicy {
|
|
75
|
+
/**
|
|
76
|
+
* Decide whether to run inference for an agent.
|
|
77
|
+
*/
|
|
78
|
+
shouldInfer(
|
|
79
|
+
agentName: string,
|
|
80
|
+
requests: InferenceRequest[],
|
|
81
|
+
state: FrameworkState
|
|
82
|
+
): boolean;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Policy for handling errors.
|
|
87
|
+
*/
|
|
88
|
+
export interface ErrorPolicy {
|
|
89
|
+
/**
|
|
90
|
+
* Handle an inference error.
|
|
91
|
+
*/
|
|
92
|
+
onInferenceError(
|
|
93
|
+
error: Error,
|
|
94
|
+
agentName: string,
|
|
95
|
+
attempt: number
|
|
96
|
+
): ErrorAction;
|
|
97
|
+
|
|
98
|
+
/** Maximum retry attempts */
|
|
99
|
+
maxRetries: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Action to take after an error.
|
|
104
|
+
*/
|
|
105
|
+
export type ErrorAction =
|
|
106
|
+
| { retry: true; delayMs: number }
|
|
107
|
+
| { retry: false; emit?: ProcessEvent };
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Framework state exposed to policies.
|
|
111
|
+
*/
|
|
112
|
+
export interface FrameworkState {
|
|
113
|
+
/** Get agent status */
|
|
114
|
+
getAgentStatus(name: string): import('./agent.js').AgentState | null;
|
|
115
|
+
|
|
116
|
+
/** Get module by name */
|
|
117
|
+
getModule(name: string): Module | null;
|
|
118
|
+
|
|
119
|
+
/** Get all pending inference requests */
|
|
120
|
+
getPendingRequests(): InferenceRequest[];
|
|
121
|
+
|
|
122
|
+
/** Current queue depth */
|
|
123
|
+
queueDepth: number;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Entry in the inference log.
|
|
128
|
+
*/
|
|
129
|
+
export interface InferenceLogEntry {
|
|
130
|
+
timestamp: number;
|
|
131
|
+
agentName: string;
|
|
132
|
+
requestId: string;
|
|
133
|
+
/** Whether inference succeeded */
|
|
134
|
+
success: boolean;
|
|
135
|
+
/** Error message if failed */
|
|
136
|
+
error?: string;
|
|
137
|
+
/** Request data or blob ID if large */
|
|
138
|
+
request: unknown | { blobId: string };
|
|
139
|
+
/** Response data or blob ID if large (only if successful) */
|
|
140
|
+
response?: unknown | { blobId: string };
|
|
141
|
+
durationMs: number;
|
|
142
|
+
tokenUsage?: {
|
|
143
|
+
input: number;
|
|
144
|
+
output: number;
|
|
145
|
+
cacheCreation?: number;
|
|
146
|
+
cacheRead?: number;
|
|
147
|
+
};
|
|
148
|
+
/** Stop reason from the model */
|
|
149
|
+
stopReason?: string;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Entry in the process log - records a processed event with all module responses.
|
|
154
|
+
*/
|
|
155
|
+
export interface ProcessLogEntry {
|
|
156
|
+
timestamp: number;
|
|
157
|
+
/** The process event that was handled */
|
|
158
|
+
processEvent: ProcessEvent;
|
|
159
|
+
/** Responses from all modules, or blob ID if large */
|
|
160
|
+
responses: ModuleProcessResponse[] | { blobId: string };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Query options for process logs.
|
|
165
|
+
*/
|
|
166
|
+
export interface ProcessLogQuery {
|
|
167
|
+
/** Filter by process event type */
|
|
168
|
+
eventType?: string;
|
|
169
|
+
/** Filter by module name (modules that responded) */
|
|
170
|
+
moduleName?: string;
|
|
171
|
+
/** Max number of logs to return */
|
|
172
|
+
limit?: number;
|
|
173
|
+
/** Skip first N logs (for pagination) */
|
|
174
|
+
offset?: number;
|
|
175
|
+
/** Search pattern for content (regex) */
|
|
176
|
+
pattern?: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Result from querying process logs.
|
|
181
|
+
*/
|
|
182
|
+
export interface ProcessLogQueryResult {
|
|
183
|
+
entries: ProcessLogEntryWithId[];
|
|
184
|
+
total: number;
|
|
185
|
+
hasMore: boolean;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Process log entry with Chronicle sequence ID.
|
|
190
|
+
*/
|
|
191
|
+
export interface ProcessLogEntryWithId {
|
|
192
|
+
sequence: number;
|
|
193
|
+
entry: ProcessLogEntry;
|
|
194
|
+
/** Summary for display without resolving blobs */
|
|
195
|
+
summary?: ProcessLogSummary;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Summary view of a process log (without full responses).
|
|
200
|
+
*/
|
|
201
|
+
export interface ProcessLogSummary {
|
|
202
|
+
timestamp: number;
|
|
203
|
+
eventType: string;
|
|
204
|
+
moduleCount: number;
|
|
205
|
+
/** Modules that requested inference */
|
|
206
|
+
modulesRequestingInference: string[];
|
|
207
|
+
/** Modules that added messages */
|
|
208
|
+
modulesAddingMessages: string[];
|
|
209
|
+
/** Whether responses are stored as blob */
|
|
210
|
+
responsesIsBlob: boolean;
|
|
211
|
+
}
|