@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.
Files changed (54) hide show
  1. package/README.md +140 -0
  2. package/dist/conductor.d.ts +219 -0
  3. package/dist/conductor.d.ts.map +1 -0
  4. package/dist/conductor.js +960 -0
  5. package/dist/conductor.js.map +1 -0
  6. package/dist/connectors/channel.d.ts +60 -0
  7. package/dist/connectors/channel.d.ts.map +1 -0
  8. package/dist/connectors/channel.js +155 -0
  9. package/dist/connectors/channel.js.map +1 -0
  10. package/dist/connectors/index.d.ts +6 -0
  11. package/dist/connectors/index.d.ts.map +1 -0
  12. package/dist/connectors/index.js +6 -0
  13. package/dist/connectors/index.js.map +1 -0
  14. package/dist/connectors/stdio.d.ts +36 -0
  15. package/dist/connectors/stdio.d.ts.map +1 -0
  16. package/dist/connectors/stdio.js +198 -0
  17. package/dist/connectors/stdio.js.map +1 -0
  18. package/dist/index.d.ts +72 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +76 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/instantiators.d.ts +129 -0
  23. package/dist/instantiators.d.ts.map +1 -0
  24. package/dist/instantiators.js +183 -0
  25. package/dist/instantiators.js.map +1 -0
  26. package/dist/logger.d.ts +121 -0
  27. package/dist/logger.d.ts.map +1 -0
  28. package/dist/logger.js +162 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/mcp-bridge/http-listener.d.ts +35 -0
  31. package/dist/mcp-bridge/http-listener.d.ts.map +1 -0
  32. package/dist/mcp-bridge/http-listener.js +204 -0
  33. package/dist/mcp-bridge/http-listener.js.map +1 -0
  34. package/dist/mcp-bridge/index.d.ts +9 -0
  35. package/dist/mcp-bridge/index.d.ts.map +1 -0
  36. package/dist/mcp-bridge/index.js +8 -0
  37. package/dist/mcp-bridge/index.js.map +1 -0
  38. package/dist/mcp-bridge/mcp-bridge.d.ts +80 -0
  39. package/dist/mcp-bridge/mcp-bridge.d.ts.map +1 -0
  40. package/dist/mcp-bridge/mcp-bridge.js +170 -0
  41. package/dist/mcp-bridge/mcp-bridge.js.map +1 -0
  42. package/dist/mcp-bridge/types.d.ts +69 -0
  43. package/dist/mcp-bridge/types.d.ts.map +1 -0
  44. package/dist/mcp-bridge/types.js +8 -0
  45. package/dist/mcp-bridge/types.js.map +1 -0
  46. package/dist/message-queue.d.ts +46 -0
  47. package/dist/message-queue.d.ts.map +1 -0
  48. package/dist/message-queue.js +90 -0
  49. package/dist/message-queue.js.map +1 -0
  50. package/dist/types.d.ts +129 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +13 -0
  53. package/dist/types.js.map +1 -0
  54. package/package.json +40 -0
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Central message queue for the conductor
3
+ *
4
+ * All routing flows through this queue, preserving message ordering.
5
+ * The queue supports async iteration, allowing the conductor's main loop
6
+ * to consume messages as they arrive.
7
+ */
8
+ import type { ConductorMessage } from "./types.js";
9
+ /**
10
+ * A message queue with async iteration support.
11
+ *
12
+ * Messages can be pushed from multiple sources (client, proxies, agent)
13
+ * and are consumed in order by the conductor's event loop.
14
+ */
15
+ export declare class MessageQueue {
16
+ private queue;
17
+ private resolvers;
18
+ private closed;
19
+ /**
20
+ * Push a message onto the queue.
21
+ *
22
+ * If there's a waiting consumer, the message is delivered immediately.
23
+ * Otherwise, it's buffered until the next consumer is ready.
24
+ */
25
+ push(message: ConductorMessage): void;
26
+ /**
27
+ * Close the queue, causing the async iterator to complete.
28
+ */
29
+ close(): void;
30
+ /**
31
+ * Check if the queue has been closed
32
+ */
33
+ isClosed(): boolean;
34
+ /**
35
+ * Async iterator for consuming messages.
36
+ *
37
+ * This allows the conductor to use `for await` to process messages:
38
+ * ```typescript
39
+ * for await (const msg of messageQueue) {
40
+ * await handleMessage(msg);
41
+ * }
42
+ * ```
43
+ */
44
+ [Symbol.asyncIterator](): AsyncIterator<ConductorMessage>;
45
+ }
46
+ //# sourceMappingURL=message-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-queue.d.ts","sourceRoot":"","sources":["../src/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;;OAKG;IACH,IAAI,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAarC;;OAEG;IACH,KAAK,IAAI,IAAI;IAUb;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;;;;;;;;OASG;IACI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,gBAAgB,CAAC;CA4BjE"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Central message queue for the conductor
3
+ *
4
+ * All routing flows through this queue, preserving message ordering.
5
+ * The queue supports async iteration, allowing the conductor's main loop
6
+ * to consume messages as they arrive.
7
+ */
8
+ /**
9
+ * A message queue with async iteration support.
10
+ *
11
+ * Messages can be pushed from multiple sources (client, proxies, agent)
12
+ * and are consumed in order by the conductor's event loop.
13
+ */
14
+ export class MessageQueue {
15
+ queue = [];
16
+ resolvers = [];
17
+ closed = false;
18
+ /**
19
+ * Push a message onto the queue.
20
+ *
21
+ * If there's a waiting consumer, the message is delivered immediately.
22
+ * Otherwise, it's buffered until the next consumer is ready.
23
+ */
24
+ push(message) {
25
+ if (this.closed) {
26
+ return;
27
+ }
28
+ if (this.resolvers.length > 0) {
29
+ const resolve = this.resolvers.shift();
30
+ resolve(message);
31
+ }
32
+ else {
33
+ this.queue.push(message);
34
+ }
35
+ }
36
+ /**
37
+ * Close the queue, causing the async iterator to complete.
38
+ */
39
+ close() {
40
+ this.closed = true;
41
+ // Wake up any waiting consumers so they can exit
42
+ for (const resolve of this.resolvers) {
43
+ // Push a shutdown message to signal completion
44
+ resolve({ type: "shutdown" });
45
+ }
46
+ this.resolvers = [];
47
+ }
48
+ /**
49
+ * Check if the queue has been closed
50
+ */
51
+ isClosed() {
52
+ return this.closed;
53
+ }
54
+ /**
55
+ * Async iterator for consuming messages.
56
+ *
57
+ * This allows the conductor to use `for await` to process messages:
58
+ * ```typescript
59
+ * for await (const msg of messageQueue) {
60
+ * await handleMessage(msg);
61
+ * }
62
+ * ```
63
+ */
64
+ async *[Symbol.asyncIterator]() {
65
+ while (!this.closed) {
66
+ let message;
67
+ if (this.queue.length > 0) {
68
+ message = this.queue.shift();
69
+ }
70
+ else {
71
+ message = await new Promise((resolve) => {
72
+ this.resolvers.push(resolve);
73
+ });
74
+ }
75
+ // Check for shutdown message
76
+ if (message.type === "shutdown") {
77
+ return;
78
+ }
79
+ yield message;
80
+ }
81
+ // Drain any remaining messages in the queue
82
+ while (this.queue.length > 0) {
83
+ const message = this.queue.shift();
84
+ if (message.type !== "shutdown") {
85
+ yield message;
86
+ }
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=message-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-queue.js","sourceRoot":"","sources":["../src/message-queue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACf,KAAK,GAAuB,EAAE,CAAC;IAC/B,SAAS,GAA2C,EAAE,CAAC;IACvD,MAAM,GAAG,KAAK,CAAC;IAEvB;;;;;OAKG;IACH,IAAI,CAAC,OAAyB;QAC5B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAG,CAAC;YACxC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,iDAAiD;QACjD,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,+CAA+C;YAC/C,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpB,IAAI,OAAyB,CAAC;YAE9B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YAChC,CAAC;iBAAM,CAAC;gBACN,OAAO,GAAG,MAAM,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;oBACxD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC/B,CAAC,CAAC,CAAC;YACL,CAAC;YAED,6BAA6B;YAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAChC,OAAO;YACT,CAAC;YAED,MAAM,OAAO,CAAC;QAChB,CAAC;QAED,4CAA4C;QAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YACpC,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAChC,MAAM,OAAO,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Internal types for the conductor
3
+ */
4
+ import type { JsonRpcMessage, Dispatch } from "@thinkwell/protocol";
5
+ /**
6
+ * Role identifiers for the conductor's connections
7
+ */
8
+ export type RoleId = "client" | "agent" | "proxy" | "conductor";
9
+ /**
10
+ * Role relationships - encode at runtime what Rust does at compile time
11
+ */
12
+ export declare const ROLE_COUNTERPART: Record<RoleId, RoleId>;
13
+ /**
14
+ * Index identifying a source component for right-to-left messages
15
+ */
16
+ export type SourceIndex = {
17
+ type: "proxy";
18
+ index: number;
19
+ } | {
20
+ type: "successor";
21
+ };
22
+ /**
23
+ * Messages flowing through the conductor's central queue
24
+ */
25
+ export type ConductorMessage = {
26
+ type: "left-to-right";
27
+ targetIndex: number;
28
+ dispatch: Dispatch;
29
+ } | {
30
+ type: "right-to-left";
31
+ sourceIndex: SourceIndex;
32
+ dispatch: Dispatch;
33
+ } | {
34
+ type: "mcp-connection-received";
35
+ acpUrl: string;
36
+ connectionId: string;
37
+ } | {
38
+ type: "mcp-connection-established";
39
+ connectionId: string;
40
+ serverInfo: {
41
+ name: string;
42
+ version: string;
43
+ };
44
+ } | {
45
+ type: "mcp-client-to-server";
46
+ connectionId: string;
47
+ dispatch: Dispatch;
48
+ } | {
49
+ type: "mcp-connection-disconnected";
50
+ connectionId: string;
51
+ } | {
52
+ type: "shutdown";
53
+ };
54
+ /**
55
+ * A bidirectional connection to a component (client, proxy, or agent)
56
+ */
57
+ export interface ComponentConnection {
58
+ /** Send a message to this component */
59
+ send(message: JsonRpcMessage): void;
60
+ /** Receive messages from this component */
61
+ messages: AsyncIterable<JsonRpcMessage>;
62
+ /** Close the connection */
63
+ close(): Promise<void>;
64
+ }
65
+ /**
66
+ * Factory for creating component connections
67
+ */
68
+ export interface ComponentConnector {
69
+ /** Open a bidirectional JSON-RPC connection */
70
+ connect(): Promise<ComponentConnection>;
71
+ }
72
+ /**
73
+ * ACP initialize request structure
74
+ */
75
+ export interface InitializeRequest {
76
+ method: "initialize" | "acp/initialize";
77
+ params?: {
78
+ clientInfo?: {
79
+ name?: string;
80
+ version?: string;
81
+ };
82
+ capabilities?: {
83
+ mcp_acp_transport?: boolean;
84
+ [key: string]: unknown;
85
+ };
86
+ _meta?: {
87
+ proxy?: boolean;
88
+ [key: string]: unknown;
89
+ };
90
+ mcpServers?: Array<{
91
+ name: string;
92
+ url: string;
93
+ type?: string;
94
+ }>;
95
+ [key: string]: unknown;
96
+ };
97
+ }
98
+ /**
99
+ * ACP initialize response structure
100
+ */
101
+ export interface InitializeResponse {
102
+ serverInfo?: {
103
+ name?: string;
104
+ version?: string;
105
+ };
106
+ capabilities?: {
107
+ mcp_acp_transport?: boolean;
108
+ [key: string]: unknown;
109
+ };
110
+ _meta?: {
111
+ proxy?: boolean;
112
+ [key: string]: unknown;
113
+ };
114
+ [key: string]: unknown;
115
+ }
116
+ /**
117
+ * Result of component instantiation
118
+ */
119
+ export interface InstantiatedComponents {
120
+ proxies: ComponentConnector[];
121
+ agent: ComponentConnector;
122
+ }
123
+ /**
124
+ * Interface for instantiating components when the first initialize request arrives
125
+ */
126
+ export interface ComponentInstantiator {
127
+ instantiate(initRequest: InitializeRequest): Promise<InstantiatedComponents>;
128
+ }
129
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Internal types for the conductor
3
+ */
4
+ /**
5
+ * Role relationships - encode at runtime what Rust does at compile time
6
+ */
7
+ export const ROLE_COUNTERPART = {
8
+ client: "agent",
9
+ agent: "client",
10
+ proxy: "conductor",
11
+ conductor: "proxy",
12
+ };
13
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,MAAM,EAAE,OAAO;IACf,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,WAAW;IAClB,SAAS,EAAE,OAAO;CACnB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@thinkwell/conductor",
3
+ "version": "0.2.0",
4
+ "description": "TypeScript conductor for ACP proxy chains - orchestrates message routing between clients, proxies, and agents",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "keywords": [
18
+ "acp",
19
+ "mcp",
20
+ "thinkwell",
21
+ "conductor",
22
+ "proxy",
23
+ "agent"
24
+ ],
25
+ "author": "David Herman",
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@thinkwell/protocol": "0.2.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^24.10.4",
32
+ "tsx": "^4.19.2",
33
+ "typescript": "^5.7.2"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc",
37
+ "clean": "rm -rf dist",
38
+ "test": "node --test --import tsx src/**/*.test.ts"
39
+ }
40
+ }