@thinkwell/conductor 0.2.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/README.md +140 -0
- package/dist/conductor.d.ts +219 -0
- package/dist/conductor.d.ts.map +1 -0
- package/dist/conductor.js +960 -0
- package/dist/conductor.js.map +1 -0
- package/dist/connectors/channel.d.ts +60 -0
- package/dist/connectors/channel.d.ts.map +1 -0
- package/dist/connectors/channel.js +155 -0
- package/dist/connectors/channel.js.map +1 -0
- package/dist/connectors/index.d.ts +6 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +6 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/stdio.d.ts +36 -0
- package/dist/connectors/stdio.d.ts.map +1 -0
- package/dist/connectors/stdio.js +198 -0
- package/dist/connectors/stdio.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/instantiators.d.ts +129 -0
- package/dist/instantiators.d.ts.map +1 -0
- package/dist/instantiators.js +183 -0
- package/dist/instantiators.js.map +1 -0
- package/dist/logger.d.ts +121 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +162 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-bridge/http-listener.d.ts +35 -0
- package/dist/mcp-bridge/http-listener.d.ts.map +1 -0
- package/dist/mcp-bridge/http-listener.js +204 -0
- package/dist/mcp-bridge/http-listener.js.map +1 -0
- package/dist/mcp-bridge/index.d.ts +9 -0
- package/dist/mcp-bridge/index.d.ts.map +1 -0
- package/dist/mcp-bridge/index.js +8 -0
- package/dist/mcp-bridge/index.js.map +1 -0
- package/dist/mcp-bridge/mcp-bridge.d.ts +80 -0
- package/dist/mcp-bridge/mcp-bridge.d.ts.map +1 -0
- package/dist/mcp-bridge/mcp-bridge.js +170 -0
- package/dist/mcp-bridge/mcp-bridge.js.map +1 -0
- package/dist/mcp-bridge/types.d.ts +69 -0
- package/dist/mcp-bridge/types.d.ts.map +1 -0
- package/dist/mcp-bridge/types.js +8 -0
- package/dist/mcp-bridge/types.js.map +1 -0
- package/dist/message-queue.d.ts +46 -0
- package/dist/message-queue.d.ts.map +1 -0
- package/dist/message-queue.js +90 -0
- package/dist/message-queue.js.map +1 -0
- package/dist/types.d.ts +129 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @thinkwell/conductor - TypeScript conductor for ACP proxy chains
|
|
3
|
+
*
|
|
4
|
+
* The conductor orchestrates message routing between clients, proxies, and agents.
|
|
5
|
+
* It sits between every component, managing process lifecycle and message flow.
|
|
6
|
+
*
|
|
7
|
+
* ## Quick Start
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { Conductor, fromCommands, createChannelPair } from '@thinkwell/conductor';
|
|
11
|
+
*
|
|
12
|
+
* // Create a conductor that spawns an agent subprocess
|
|
13
|
+
* const conductor = new Conductor({
|
|
14
|
+
* instantiator: fromCommands(['my-agent']),
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Connect via a channel (for testing) or stdio (for production)
|
|
18
|
+
* const [clientEnd, conductorEnd] = createChannelPair();
|
|
19
|
+
* await conductor.connect(conductorEnd);
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ## Logging
|
|
23
|
+
*
|
|
24
|
+
* Enable logging to see what the conductor is doing:
|
|
25
|
+
*
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const conductor = new Conductor({
|
|
28
|
+
* instantiator: fromCommands(['my-agent']),
|
|
29
|
+
* logging: {
|
|
30
|
+
* level: 'debug', // 'error' | 'warn' | 'info' | 'debug' | 'trace'
|
|
31
|
+
* name: 'my-app',
|
|
32
|
+
* },
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ## JSONL Tracing
|
|
37
|
+
*
|
|
38
|
+
* Write all messages to a JSONL file for debugging:
|
|
39
|
+
*
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const conductor = new Conductor({
|
|
42
|
+
* instantiator: fromCommands(['my-agent']),
|
|
43
|
+
* trace: {
|
|
44
|
+
* path: '/tmp/conductor-trace.jsonl',
|
|
45
|
+
* },
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* ## Architecture
|
|
50
|
+
*
|
|
51
|
+
* The conductor uses a central message queue to preserve ordering:
|
|
52
|
+
*
|
|
53
|
+
* ```
|
|
54
|
+
* Client ←→ Conductor ←→ [Proxy 0] ←→ [Proxy 1] ←→ ... ←→ Agent
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* All messages flow through the conductor's event loop, ensuring that
|
|
58
|
+
* responses never overtake notifications.
|
|
59
|
+
*
|
|
60
|
+
* @module
|
|
61
|
+
*/
|
|
62
|
+
// Conductor
|
|
63
|
+
export { Conductor } from "./conductor.js";
|
|
64
|
+
// Logging
|
|
65
|
+
export { createLogger, createNoopLogger, getLogger, setLogger, } from "./logger.js";
|
|
66
|
+
// Instantiators
|
|
67
|
+
export { fromCommands, fromConnectors, dynamic, staticInstantiator, } from "./instantiators.js";
|
|
68
|
+
export { ROLE_COUNTERPART } from "./types.js";
|
|
69
|
+
// Message queue
|
|
70
|
+
export { MessageQueue } from "./message-queue.js";
|
|
71
|
+
// Connectors
|
|
72
|
+
export { StdioConnector, stdio, ChannelConnector, createChannelPair, inProcess, echoComponent, } from "./connectors/index.js";
|
|
73
|
+
// MCP Bridge
|
|
74
|
+
export { McpBridge, createHttpListener, } from "./mcp-bridge/index.js";
|
|
75
|
+
export { isJsonRpcRequest, isJsonRpcNotification, isJsonRpcResponse, createRequest, createNotification, createSuccessResponse, createErrorResponse, createResponder, } from "@thinkwell/protocol";
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AAEH,YAAY;AACZ,OAAO,EAAE,SAAS,EAAwB,MAAM,gBAAgB,CAAC;AAEjE,UAAU;AACV,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,SAAS,EACT,SAAS,GAOV,MAAM,aAAa,CAAC;AAErB,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,cAAc,EACd,OAAO,EACP,kBAAkB,GAKnB,MAAM,oBAAoB,CAAC;AAc5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,gBAAgB;AAChB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,aAAa;AACb,OAAO,EACL,cAAc,EACd,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,aAAa,GAId,MAAM,uBAAuB,CAAC;AAE/B,aAAa;AACb,OAAO,EACL,SAAS,EACT,kBAAkB,GASnB,MAAM,uBAAuB,CAAC;AAiB/B,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,GAChB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component instantiator helpers
|
|
3
|
+
*
|
|
4
|
+
* These functions create ComponentInstantiator objects that determine how
|
|
5
|
+
* components are created when the conductor receives an initialize request.
|
|
6
|
+
*
|
|
7
|
+
* ## Instantiation Modes
|
|
8
|
+
*
|
|
9
|
+
* - **Static**: Components are determined at construction time (e.g., from a list of commands)
|
|
10
|
+
* - **Dynamic**: Components are determined at runtime based on the initialize request
|
|
11
|
+
*
|
|
12
|
+
* ## Lazy Instantiation
|
|
13
|
+
*
|
|
14
|
+
* All instantiators are lazy - components are only spawned when the first
|
|
15
|
+
* `initialize` request arrives. This allows the conductor to be constructed
|
|
16
|
+
* before the component processes need to exist.
|
|
17
|
+
*/
|
|
18
|
+
import type { ComponentConnector, ComponentInstantiator, InitializeRequest, InstantiatedComponents } from "./types.js";
|
|
19
|
+
import type { StdioConnectorOptions } from "./connectors/stdio.js";
|
|
20
|
+
/**
|
|
21
|
+
* Options for a component command
|
|
22
|
+
*/
|
|
23
|
+
export interface CommandOptions extends StdioConnectorOptions {
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A command specification - either a string or full options
|
|
27
|
+
*/
|
|
28
|
+
export type CommandSpec = string | CommandOptions;
|
|
29
|
+
/**
|
|
30
|
+
* Static configuration for component instantiation
|
|
31
|
+
*/
|
|
32
|
+
export interface StaticInstantiatorConfig {
|
|
33
|
+
/** Proxy commands to spawn (in order) */
|
|
34
|
+
proxies?: CommandSpec[];
|
|
35
|
+
/** Agent command to spawn (required) */
|
|
36
|
+
agent: CommandSpec;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a component instantiator from static command specifications.
|
|
40
|
+
*
|
|
41
|
+
* This is the most common way to create an instantiator - provide the
|
|
42
|
+
* commands for each component and they will be spawned when needed.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // Simple string commands
|
|
47
|
+
* const instantiator = staticInstantiator({
|
|
48
|
+
* proxies: ['sparkle-acp'],
|
|
49
|
+
* agent: 'claude-agent',
|
|
50
|
+
* });
|
|
51
|
+
*
|
|
52
|
+
* // With options
|
|
53
|
+
* const instantiator = staticInstantiator({
|
|
54
|
+
* agent: {
|
|
55
|
+
* command: 'my-agent',
|
|
56
|
+
* args: ['--mode', 'production'],
|
|
57
|
+
* env: { DEBUG: 'true' },
|
|
58
|
+
* },
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function staticInstantiator(config: StaticInstantiatorConfig): ComponentInstantiator;
|
|
63
|
+
/**
|
|
64
|
+
* Create a component instantiator from a simple list of commands.
|
|
65
|
+
*
|
|
66
|
+
* The last command is treated as the agent, all others as proxies.
|
|
67
|
+
* This is a convenience wrapper around `staticInstantiator`.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* // Single agent (no proxies)
|
|
72
|
+
* const instantiator = fromCommands(['claude-agent']);
|
|
73
|
+
*
|
|
74
|
+
* // Agent with proxies
|
|
75
|
+
* const instantiator = fromCommands(['sparkle-acp', 'claude-agent']);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare function fromCommands(commands: CommandSpec[]): ComponentInstantiator;
|
|
79
|
+
/**
|
|
80
|
+
* Create a component instantiator from explicit connectors.
|
|
81
|
+
*
|
|
82
|
+
* This is useful when you have pre-configured connectors or want to use
|
|
83
|
+
* in-memory connections for testing.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const instantiator = fromConnectors(agentConnector, [proxyConnector]);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare function fromConnectors(agent: ComponentConnector, proxies?: ComponentConnector[]): ComponentInstantiator;
|
|
91
|
+
/**
|
|
92
|
+
* Factory function type for dynamic instantiation.
|
|
93
|
+
*
|
|
94
|
+
* The factory receives the initialize request and returns the components
|
|
95
|
+
* to instantiate. This allows for runtime decisions about what to spawn.
|
|
96
|
+
*/
|
|
97
|
+
export type DynamicInstantiatorFactory = (initRequest: InitializeRequest) => Promise<InstantiatedComponents>;
|
|
98
|
+
/**
|
|
99
|
+
* Create a component instantiator with a dynamic factory function.
|
|
100
|
+
*
|
|
101
|
+
* The factory function is called when the first `initialize` request arrives,
|
|
102
|
+
* allowing you to make decisions about what components to spawn based on
|
|
103
|
+
* the request content.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const instantiator = dynamic(async (initRequest) => {
|
|
108
|
+
* // Choose agent based on client capabilities
|
|
109
|
+
* const capabilities = initRequest.params?.capabilities ?? {};
|
|
110
|
+
* const agentCommand = capabilities.advanced ? 'advanced-agent' : 'basic-agent';
|
|
111
|
+
*
|
|
112
|
+
* const { StdioConnector } = await import('./connectors/stdio.js');
|
|
113
|
+
* return {
|
|
114
|
+
* proxies: [],
|
|
115
|
+
* agent: new StdioConnector(agentCommand),
|
|
116
|
+
* };
|
|
117
|
+
* });
|
|
118
|
+
*
|
|
119
|
+
* // Or use it to inspect MCP servers
|
|
120
|
+
* const instantiator = dynamic(async (initRequest) => {
|
|
121
|
+
* const mcpServers = initRequest.params?.mcpServers ?? [];
|
|
122
|
+
* console.log('Client provided MCP servers:', mcpServers);
|
|
123
|
+
*
|
|
124
|
+
* // ... create appropriate components
|
|
125
|
+
* });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function dynamic(factory: DynamicInstantiatorFactory): ComponentInstantiator;
|
|
129
|
+
//# sourceMappingURL=instantiators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instantiators.d.ts","sourceRoot":"","sources":["../src/instantiators.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AACvH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,qBAAqB;CAE5D;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,cAAc,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,yCAAyC;IACzC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,wCAAwC;IACxC,KAAK,EAAE,WAAW,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,qBAAqB,CAkB1F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAS3E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,kBAAkB,EAAO,GACjC,qBAAqB,CAMvB;AAED;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACvC,WAAW,EAAE,iBAAiB,KAC3B,OAAO,CAAC,sBAAsB,CAAC,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,0BAA0B,GAAG,qBAAqB,CAIlF"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component instantiator helpers
|
|
3
|
+
*
|
|
4
|
+
* These functions create ComponentInstantiator objects that determine how
|
|
5
|
+
* components are created when the conductor receives an initialize request.
|
|
6
|
+
*
|
|
7
|
+
* ## Instantiation Modes
|
|
8
|
+
*
|
|
9
|
+
* - **Static**: Components are determined at construction time (e.g., from a list of commands)
|
|
10
|
+
* - **Dynamic**: Components are determined at runtime based on the initialize request
|
|
11
|
+
*
|
|
12
|
+
* ## Lazy Instantiation
|
|
13
|
+
*
|
|
14
|
+
* All instantiators are lazy - components are only spawned when the first
|
|
15
|
+
* `initialize` request arrives. This allows the conductor to be constructed
|
|
16
|
+
* before the component processes need to exist.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Create a component instantiator from static command specifications.
|
|
20
|
+
*
|
|
21
|
+
* This is the most common way to create an instantiator - provide the
|
|
22
|
+
* commands for each component and they will be spawned when needed.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* // Simple string commands
|
|
27
|
+
* const instantiator = staticInstantiator({
|
|
28
|
+
* proxies: ['sparkle-acp'],
|
|
29
|
+
* agent: 'claude-agent',
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // With options
|
|
33
|
+
* const instantiator = staticInstantiator({
|
|
34
|
+
* agent: {
|
|
35
|
+
* command: 'my-agent',
|
|
36
|
+
* args: ['--mode', 'production'],
|
|
37
|
+
* env: { DEBUG: 'true' },
|
|
38
|
+
* },
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function staticInstantiator(config) {
|
|
43
|
+
return {
|
|
44
|
+
async instantiate() {
|
|
45
|
+
// Dynamic import to avoid circular dependency
|
|
46
|
+
const { StdioConnector } = await import("./connectors/stdio.js");
|
|
47
|
+
const proxyConnectors = (config.proxies ?? []).map((spec) => new StdioConnector(normalizeCommandSpec(spec)));
|
|
48
|
+
const agentConnector = new StdioConnector(normalizeCommandSpec(config.agent));
|
|
49
|
+
return {
|
|
50
|
+
proxies: proxyConnectors,
|
|
51
|
+
agent: agentConnector,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create a component instantiator from a simple list of commands.
|
|
58
|
+
*
|
|
59
|
+
* The last command is treated as the agent, all others as proxies.
|
|
60
|
+
* This is a convenience wrapper around `staticInstantiator`.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* // Single agent (no proxies)
|
|
65
|
+
* const instantiator = fromCommands(['claude-agent']);
|
|
66
|
+
*
|
|
67
|
+
* // Agent with proxies
|
|
68
|
+
* const instantiator = fromCommands(['sparkle-acp', 'claude-agent']);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function fromCommands(commands) {
|
|
72
|
+
if (commands.length === 0) {
|
|
73
|
+
throw new Error("At least one command (the agent) is required");
|
|
74
|
+
}
|
|
75
|
+
return staticInstantiator({
|
|
76
|
+
proxies: commands.slice(0, -1),
|
|
77
|
+
agent: commands[commands.length - 1],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a component instantiator from explicit connectors.
|
|
82
|
+
*
|
|
83
|
+
* This is useful when you have pre-configured connectors or want to use
|
|
84
|
+
* in-memory connections for testing.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* const instantiator = fromConnectors(agentConnector, [proxyConnector]);
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export function fromConnectors(agent, proxies = []) {
|
|
92
|
+
return {
|
|
93
|
+
async instantiate() {
|
|
94
|
+
return { proxies, agent };
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a component instantiator with a dynamic factory function.
|
|
100
|
+
*
|
|
101
|
+
* The factory function is called when the first `initialize` request arrives,
|
|
102
|
+
* allowing you to make decisions about what components to spawn based on
|
|
103
|
+
* the request content.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const instantiator = dynamic(async (initRequest) => {
|
|
108
|
+
* // Choose agent based on client capabilities
|
|
109
|
+
* const capabilities = initRequest.params?.capabilities ?? {};
|
|
110
|
+
* const agentCommand = capabilities.advanced ? 'advanced-agent' : 'basic-agent';
|
|
111
|
+
*
|
|
112
|
+
* const { StdioConnector } = await import('./connectors/stdio.js');
|
|
113
|
+
* return {
|
|
114
|
+
* proxies: [],
|
|
115
|
+
* agent: new StdioConnector(agentCommand),
|
|
116
|
+
* };
|
|
117
|
+
* });
|
|
118
|
+
*
|
|
119
|
+
* // Or use it to inspect MCP servers
|
|
120
|
+
* const instantiator = dynamic(async (initRequest) => {
|
|
121
|
+
* const mcpServers = initRequest.params?.mcpServers ?? [];
|
|
122
|
+
* console.log('Client provided MCP servers:', mcpServers);
|
|
123
|
+
*
|
|
124
|
+
* // ... create appropriate components
|
|
125
|
+
* });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export function dynamic(factory) {
|
|
129
|
+
return {
|
|
130
|
+
instantiate: factory,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Normalize a command specification to full options
|
|
135
|
+
*/
|
|
136
|
+
function normalizeCommandSpec(spec) {
|
|
137
|
+
if (typeof spec === "string") {
|
|
138
|
+
// Parse command string into command and args
|
|
139
|
+
const parts = parseCommand(spec);
|
|
140
|
+
return {
|
|
141
|
+
command: parts[0],
|
|
142
|
+
args: parts.slice(1),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return spec;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Parse a command string into command and arguments.
|
|
149
|
+
* Handles quoted strings.
|
|
150
|
+
*/
|
|
151
|
+
function parseCommand(command) {
|
|
152
|
+
const parts = [];
|
|
153
|
+
let current = "";
|
|
154
|
+
let inQuote = null;
|
|
155
|
+
for (let i = 0; i < command.length; i++) {
|
|
156
|
+
const char = command[i];
|
|
157
|
+
if (inQuote) {
|
|
158
|
+
if (char === inQuote) {
|
|
159
|
+
inQuote = null;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
current += char;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
else if (char === '"' || char === "'") {
|
|
166
|
+
inQuote = char;
|
|
167
|
+
}
|
|
168
|
+
else if (char === " " || char === "\t") {
|
|
169
|
+
if (current) {
|
|
170
|
+
parts.push(current);
|
|
171
|
+
current = "";
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
current += char;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (current) {
|
|
179
|
+
parts.push(current);
|
|
180
|
+
}
|
|
181
|
+
return parts;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=instantiators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instantiators.js","sourceRoot":"","sources":["../src/instantiators.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging module for the conductor
|
|
3
|
+
*
|
|
4
|
+
* Provides structured logging with configurable levels and optional JSONL tracing.
|
|
5
|
+
* All conductor logging goes through this module to enable consistent output
|
|
6
|
+
* formatting and filtering.
|
|
7
|
+
*
|
|
8
|
+
* ## Log Levels
|
|
9
|
+
*
|
|
10
|
+
* - `error`: Errors that affect operation (component crashes, protocol violations)
|
|
11
|
+
* - `warn`: Warnings about potential issues (missing responses, malformed messages)
|
|
12
|
+
* - `info`: Key operational events (component start/stop, connections)
|
|
13
|
+
* - `debug`: Detailed debugging information (message routing, state changes)
|
|
14
|
+
* - `trace`: Very detailed tracing (every message, internal state)
|
|
15
|
+
*
|
|
16
|
+
* ## Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const logger = createLogger({ level: 'debug', name: 'my-conductor' });
|
|
20
|
+
* logger.info('Component started', { component: 'agent', pid: 1234 });
|
|
21
|
+
* logger.error('Failed to connect', { error: err.message });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ## JSONL Tracing
|
|
25
|
+
*
|
|
26
|
+
* When enabled, all messages routed through the conductor are written to a
|
|
27
|
+
* JSONL file for debugging and analysis:
|
|
28
|
+
*
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const logger = createLogger({
|
|
31
|
+
* level: 'info',
|
|
32
|
+
* trace: { path: '/tmp/conductor.jsonl' }
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import type { ConductorMessage } from "./types.js";
|
|
37
|
+
import type { JsonRpcMessage } from "@thinkwell/protocol";
|
|
38
|
+
/**
|
|
39
|
+
* Log level enumeration (lower = more severe)
|
|
40
|
+
*/
|
|
41
|
+
export type LogLevel = "error" | "warn" | "info" | "debug" | "trace";
|
|
42
|
+
/**
|
|
43
|
+
* Log entry structure for structured logging
|
|
44
|
+
*/
|
|
45
|
+
export interface LogEntry {
|
|
46
|
+
timestamp: string;
|
|
47
|
+
level: LogLevel;
|
|
48
|
+
name?: string;
|
|
49
|
+
message: string;
|
|
50
|
+
data?: Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Trace entry for JSONL message tracing
|
|
54
|
+
*/
|
|
55
|
+
export interface TraceEntry {
|
|
56
|
+
timestamp: string;
|
|
57
|
+
direction: "left-to-right" | "right-to-left" | "internal";
|
|
58
|
+
source?: string;
|
|
59
|
+
target?: string;
|
|
60
|
+
message: ConductorMessage | JsonRpcMessage;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Options for JSONL tracing output
|
|
64
|
+
*/
|
|
65
|
+
export interface TraceOptions {
|
|
66
|
+
/** Path to the JSONL trace file */
|
|
67
|
+
path: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Logger configuration
|
|
71
|
+
*/
|
|
72
|
+
export interface LoggerOptions {
|
|
73
|
+
/** Minimum log level to output (default: 'info') */
|
|
74
|
+
level?: LogLevel;
|
|
75
|
+
/** Optional name prefix for log messages */
|
|
76
|
+
name?: string;
|
|
77
|
+
/** Optional JSONL trace output */
|
|
78
|
+
trace?: TraceOptions;
|
|
79
|
+
/** Use JSON output format instead of human-readable (default: false) */
|
|
80
|
+
json?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Logger interface
|
|
84
|
+
*/
|
|
85
|
+
export interface Logger {
|
|
86
|
+
/** Log an error message */
|
|
87
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
88
|
+
/** Log a warning message */
|
|
89
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
90
|
+
/** Log an info message */
|
|
91
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
92
|
+
/** Log a debug message */
|
|
93
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
94
|
+
/** Log a trace message */
|
|
95
|
+
trace(message: string, data?: Record<string, unknown>): void;
|
|
96
|
+
/** Write a trace entry for message inspection */
|
|
97
|
+
traceMessage(entry: Omit<TraceEntry, "timestamp">): void;
|
|
98
|
+
/** Check if a log level is enabled */
|
|
99
|
+
isEnabled(level: LogLevel): boolean;
|
|
100
|
+
/** Create a child logger with additional context */
|
|
101
|
+
child(name: string): Logger;
|
|
102
|
+
/** Close any open resources (trace file, etc.) */
|
|
103
|
+
close(): Promise<void>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create a no-op logger that discards all output
|
|
107
|
+
*/
|
|
108
|
+
export declare function createNoopLogger(): Logger;
|
|
109
|
+
/**
|
|
110
|
+
* Create a logger with the specified options
|
|
111
|
+
*/
|
|
112
|
+
export declare function createLogger(options?: LoggerOptions): Logger;
|
|
113
|
+
/**
|
|
114
|
+
* Get the default logger
|
|
115
|
+
*/
|
|
116
|
+
export declare function getLogger(): Logger;
|
|
117
|
+
/**
|
|
118
|
+
* Set the default logger
|
|
119
|
+
*/
|
|
120
|
+
export declare function setLogger(logger: Logger): void;
|
|
121
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAUrE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,eAAe,GAAG,eAAe,GAAG,UAAU,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,gBAAgB,GAAG,cAAc,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,2BAA2B;IAC3B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,4BAA4B;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,0BAA0B;IAC1B,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,0BAA0B;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAE7D,iDAAiD;IACjD,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IAEzD,sCAAsC;IACtC,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEpC,oDAAoD;IACpD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B,kDAAkD;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAazC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAyFhE;AAOD;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAE9C"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging module for the conductor
|
|
3
|
+
*
|
|
4
|
+
* Provides structured logging with configurable levels and optional JSONL tracing.
|
|
5
|
+
* All conductor logging goes through this module to enable consistent output
|
|
6
|
+
* formatting and filtering.
|
|
7
|
+
*
|
|
8
|
+
* ## Log Levels
|
|
9
|
+
*
|
|
10
|
+
* - `error`: Errors that affect operation (component crashes, protocol violations)
|
|
11
|
+
* - `warn`: Warnings about potential issues (missing responses, malformed messages)
|
|
12
|
+
* - `info`: Key operational events (component start/stop, connections)
|
|
13
|
+
* - `debug`: Detailed debugging information (message routing, state changes)
|
|
14
|
+
* - `trace`: Very detailed tracing (every message, internal state)
|
|
15
|
+
*
|
|
16
|
+
* ## Usage
|
|
17
|
+
*
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const logger = createLogger({ level: 'debug', name: 'my-conductor' });
|
|
20
|
+
* logger.info('Component started', { component: 'agent', pid: 1234 });
|
|
21
|
+
* logger.error('Failed to connect', { error: err.message });
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ## JSONL Tracing
|
|
25
|
+
*
|
|
26
|
+
* When enabled, all messages routed through the conductor are written to a
|
|
27
|
+
* JSONL file for debugging and analysis:
|
|
28
|
+
*
|
|
29
|
+
* ```typescript
|
|
30
|
+
* const logger = createLogger({
|
|
31
|
+
* level: 'info',
|
|
32
|
+
* trace: { path: '/tmp/conductor.jsonl' }
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import { createWriteStream } from "node:fs";
|
|
37
|
+
const LOG_LEVELS = {
|
|
38
|
+
error: 0,
|
|
39
|
+
warn: 1,
|
|
40
|
+
info: 2,
|
|
41
|
+
debug: 3,
|
|
42
|
+
trace: 4,
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Create a no-op logger that discards all output
|
|
46
|
+
*/
|
|
47
|
+
export function createNoopLogger() {
|
|
48
|
+
const noop = () => { };
|
|
49
|
+
return {
|
|
50
|
+
error: noop,
|
|
51
|
+
warn: noop,
|
|
52
|
+
info: noop,
|
|
53
|
+
debug: noop,
|
|
54
|
+
trace: noop,
|
|
55
|
+
traceMessage: noop,
|
|
56
|
+
isEnabled: () => false,
|
|
57
|
+
child: () => createNoopLogger(),
|
|
58
|
+
close: async () => { },
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create a logger with the specified options
|
|
63
|
+
*/
|
|
64
|
+
export function createLogger(options = {}) {
|
|
65
|
+
const level = options.level ?? "info";
|
|
66
|
+
const levelNum = LOG_LEVELS[level];
|
|
67
|
+
const name = options.name;
|
|
68
|
+
const useJson = options.json ?? false;
|
|
69
|
+
// Set up trace file if configured
|
|
70
|
+
let traceStream = null;
|
|
71
|
+
if (options.trace) {
|
|
72
|
+
traceStream = createWriteStream(options.trace.path, { flags: "a" });
|
|
73
|
+
}
|
|
74
|
+
function isEnabled(checkLevel) {
|
|
75
|
+
return LOG_LEVELS[checkLevel] <= levelNum;
|
|
76
|
+
}
|
|
77
|
+
function log(logLevel, message, data) {
|
|
78
|
+
if (!isEnabled(logLevel)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const entry = {
|
|
82
|
+
timestamp: new Date().toISOString(),
|
|
83
|
+
level: logLevel,
|
|
84
|
+
name,
|
|
85
|
+
message,
|
|
86
|
+
data,
|
|
87
|
+
};
|
|
88
|
+
if (useJson) {
|
|
89
|
+
// Output as JSON for machine parsing
|
|
90
|
+
const output = logLevel === "error" || logLevel === "warn" ? console.error : console.log;
|
|
91
|
+
output(JSON.stringify(entry));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Human-readable format
|
|
95
|
+
const prefix = name ? `[${name}]` : "";
|
|
96
|
+
const levelStr = logLevel.toUpperCase().padEnd(5);
|
|
97
|
+
const dataStr = data ? ` ${JSON.stringify(data)}` : "";
|
|
98
|
+
const output = logLevel === "error" || logLevel === "warn" ? console.error : console.log;
|
|
99
|
+
output(`${entry.timestamp} ${levelStr} ${prefix}${prefix ? " " : ""}${message}${dataStr}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function traceMessage(entry) {
|
|
103
|
+
if (!traceStream) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const fullEntry = {
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
...entry,
|
|
109
|
+
};
|
|
110
|
+
traceStream.write(JSON.stringify(fullEntry) + "\n");
|
|
111
|
+
}
|
|
112
|
+
function child(childName) {
|
|
113
|
+
const fullName = name ? `${name}:${childName}` : childName;
|
|
114
|
+
return createLogger({
|
|
115
|
+
...options,
|
|
116
|
+
name: fullName,
|
|
117
|
+
// Share trace stream with parent
|
|
118
|
+
trace: undefined, // Don't create new stream
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async function close() {
|
|
122
|
+
if (traceStream) {
|
|
123
|
+
await new Promise((resolve, reject) => {
|
|
124
|
+
traceStream.end((err) => {
|
|
125
|
+
if (err)
|
|
126
|
+
reject(err);
|
|
127
|
+
else
|
|
128
|
+
resolve();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
traceStream = null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
error: (message, data) => log("error", message, data),
|
|
136
|
+
warn: (message, data) => log("warn", message, data),
|
|
137
|
+
info: (message, data) => log("info", message, data),
|
|
138
|
+
debug: (message, data) => log("debug", message, data),
|
|
139
|
+
trace: (message, data) => log("trace", message, data),
|
|
140
|
+
traceMessage,
|
|
141
|
+
isEnabled,
|
|
142
|
+
child,
|
|
143
|
+
close,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Default logger instance (silent by default, can be replaced)
|
|
148
|
+
*/
|
|
149
|
+
let defaultLogger = createNoopLogger();
|
|
150
|
+
/**
|
|
151
|
+
* Get the default logger
|
|
152
|
+
*/
|
|
153
|
+
export function getLogger() {
|
|
154
|
+
return defaultLogger;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Set the default logger
|
|
158
|
+
*/
|
|
159
|
+
export function setLogger(logger) {
|
|
160
|
+
defaultLogger = logger;
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=logger.js.map
|