@jackchen_me/open-multi-agent 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.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -0
  3. package/dist/agent/agent.d.ts +121 -0
  4. package/dist/agent/agent.d.ts.map +1 -0
  5. package/dist/agent/agent.js +294 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/pool.d.ts +128 -0
  8. package/dist/agent/pool.d.ts.map +1 -0
  9. package/dist/agent/pool.js +236 -0
  10. package/dist/agent/pool.js.map +1 -0
  11. package/dist/agent/runner.d.ts +120 -0
  12. package/dist/agent/runner.d.ts.map +1 -0
  13. package/dist/agent/runner.js +274 -0
  14. package/dist/agent/runner.js.map +1 -0
  15. package/dist/index.d.ts +73 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +87 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/llm/adapter.d.ts +38 -0
  20. package/dist/llm/adapter.d.ts.map +1 -0
  21. package/dist/llm/adapter.js +46 -0
  22. package/dist/llm/adapter.js.map +1 -0
  23. package/dist/llm/anthropic.d.ts +56 -0
  24. package/dist/llm/anthropic.d.ts.map +1 -0
  25. package/dist/llm/anthropic.js +307 -0
  26. package/dist/llm/anthropic.js.map +1 -0
  27. package/dist/llm/openai.d.ts +62 -0
  28. package/dist/llm/openai.d.ts.map +1 -0
  29. package/dist/llm/openai.js +424 -0
  30. package/dist/llm/openai.js.map +1 -0
  31. package/dist/memory/shared.d.ts +86 -0
  32. package/dist/memory/shared.d.ts.map +1 -0
  33. package/dist/memory/shared.js +155 -0
  34. package/dist/memory/shared.js.map +1 -0
  35. package/dist/memory/store.d.ts +64 -0
  36. package/dist/memory/store.d.ts.map +1 -0
  37. package/dist/memory/store.js +103 -0
  38. package/dist/memory/store.js.map +1 -0
  39. package/dist/orchestrator/orchestrator.d.ts +173 -0
  40. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  41. package/dist/orchestrator/orchestrator.js +698 -0
  42. package/dist/orchestrator/orchestrator.js.map +1 -0
  43. package/dist/orchestrator/scheduler.d.ts +112 -0
  44. package/dist/orchestrator/scheduler.d.ts.map +1 -0
  45. package/dist/orchestrator/scheduler.js +282 -0
  46. package/dist/orchestrator/scheduler.js.map +1 -0
  47. package/dist/task/queue.d.ts +160 -0
  48. package/dist/task/queue.d.ts.map +1 -0
  49. package/dist/task/queue.js +337 -0
  50. package/dist/task/queue.js.map +1 -0
  51. package/dist/task/task.d.ts +86 -0
  52. package/dist/task/task.d.ts.map +1 -0
  53. package/dist/task/task.js +201 -0
  54. package/dist/task/task.js.map +1 -0
  55. package/dist/team/messaging.d.ts +106 -0
  56. package/dist/team/messaging.d.ts.map +1 -0
  57. package/dist/team/messaging.js +182 -0
  58. package/dist/team/messaging.js.map +1 -0
  59. package/dist/team/team.d.ts +141 -0
  60. package/dist/team/team.d.ts.map +1 -0
  61. package/dist/team/team.js +282 -0
  62. package/dist/team/team.js.map +1 -0
  63. package/dist/tool/built-in/bash.d.ts +12 -0
  64. package/dist/tool/built-in/bash.d.ts.map +1 -0
  65. package/dist/tool/built-in/bash.js +133 -0
  66. package/dist/tool/built-in/bash.js.map +1 -0
  67. package/dist/tool/built-in/file-edit.d.ts +14 -0
  68. package/dist/tool/built-in/file-edit.d.ts.map +1 -0
  69. package/dist/tool/built-in/file-edit.js +130 -0
  70. package/dist/tool/built-in/file-edit.js.map +1 -0
  71. package/dist/tool/built-in/file-read.d.ts +12 -0
  72. package/dist/tool/built-in/file-read.d.ts.map +1 -0
  73. package/dist/tool/built-in/file-read.js +82 -0
  74. package/dist/tool/built-in/file-read.js.map +1 -0
  75. package/dist/tool/built-in/file-write.d.ts +11 -0
  76. package/dist/tool/built-in/file-write.d.ts.map +1 -0
  77. package/dist/tool/built-in/file-write.js +70 -0
  78. package/dist/tool/built-in/file-write.js.map +1 -0
  79. package/dist/tool/built-in/grep.d.ts +15 -0
  80. package/dist/tool/built-in/grep.d.ts.map +1 -0
  81. package/dist/tool/built-in/grep.js +287 -0
  82. package/dist/tool/built-in/grep.js.map +1 -0
  83. package/dist/tool/built-in/index.d.ts +36 -0
  84. package/dist/tool/built-in/index.d.ts.map +1 -0
  85. package/dist/tool/built-in/index.js +45 -0
  86. package/dist/tool/built-in/index.js.map +1 -0
  87. package/dist/tool/executor.d.ts +71 -0
  88. package/dist/tool/executor.d.ts.map +1 -0
  89. package/dist/tool/executor.js +116 -0
  90. package/dist/tool/executor.js.map +1 -0
  91. package/dist/tool/framework.d.ts +143 -0
  92. package/dist/tool/framework.d.ts.map +1 -0
  93. package/dist/tool/framework.js +371 -0
  94. package/dist/tool/framework.js.map +1 -0
  95. package/dist/types.d.ts +285 -0
  96. package/dist/types.d.ts.map +1 -0
  97. package/dist/types.js +8 -0
  98. package/dist/types.js.map +1 -0
  99. package/dist/utils/semaphore.d.ts +47 -0
  100. package/dist/utils/semaphore.d.ts.map +1 -0
  101. package/dist/utils/semaphore.js +85 -0
  102. package/dist/utils/semaphore.js.map +1 -0
  103. package/examples/01-single-agent.ts +131 -0
  104. package/examples/02-team-collaboration.ts +167 -0
  105. package/examples/03-task-pipeline.ts +201 -0
  106. package/examples/04-multi-model-team.ts +261 -0
  107. package/package.json +49 -0
  108. package/src/agent/agent.ts +364 -0
  109. package/src/agent/pool.ts +278 -0
  110. package/src/agent/runner.ts +413 -0
  111. package/src/index.ts +166 -0
  112. package/src/llm/adapter.ts +74 -0
  113. package/src/llm/anthropic.ts +388 -0
  114. package/src/llm/openai.ts +522 -0
  115. package/src/memory/shared.ts +181 -0
  116. package/src/memory/store.ts +124 -0
  117. package/src/orchestrator/orchestrator.ts +851 -0
  118. package/src/orchestrator/scheduler.ts +352 -0
  119. package/src/task/queue.ts +394 -0
  120. package/src/task/task.ts +232 -0
  121. package/src/team/messaging.ts +230 -0
  122. package/src/team/team.ts +334 -0
  123. package/src/tool/built-in/bash.ts +187 -0
  124. package/src/tool/built-in/file-edit.ts +154 -0
  125. package/src/tool/built-in/file-read.ts +105 -0
  126. package/src/tool/built-in/file-write.ts +81 -0
  127. package/src/tool/built-in/grep.ts +362 -0
  128. package/src/tool/built-in/index.ts +50 -0
  129. package/src/tool/executor.ts +178 -0
  130. package/src/tool/framework.ts +557 -0
  131. package/src/types.ts +362 -0
  132. package/src/utils/semaphore.ts +89 -0
  133. package/tsconfig.json +25 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @fileoverview Shared memory layer for teams of cooperating agents.
3
+ *
4
+ * Each agent writes under its own namespace (`<agentName>/<key>`) so entries
5
+ * remain attributable, while any agent may read any entry. The
6
+ * {@link SharedMemory.getSummary} method produces a human-readable digest
7
+ * suitable for injecting into an agent's context window.
8
+ */
9
+ import { InMemoryStore } from './store.js';
10
+ // ---------------------------------------------------------------------------
11
+ // SharedMemory
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Namespaced shared memory for a team of agents.
15
+ *
16
+ * Writes are namespaced as `<agentName>/<key>` so that entries from different
17
+ * agents never collide and are always attributable. Reads are namespace-aware
18
+ * but also accept fully-qualified keys, making cross-agent reads straightforward.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const mem = new SharedMemory()
23
+ *
24
+ * await mem.write('researcher', 'findings', 'TypeScript 5.5 ships const type params')
25
+ * await mem.write('coder', 'plan', 'Implement feature X using const type params')
26
+ *
27
+ * const entry = await mem.read('researcher/findings')
28
+ * const all = await mem.listByAgent('researcher')
29
+ * const summary = await mem.getSummary()
30
+ * ```
31
+ */
32
+ export class SharedMemory {
33
+ store;
34
+ constructor() {
35
+ this.store = new InMemoryStore();
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Write
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Write `value` under the namespaced key `<agentName>/<key>`.
42
+ *
43
+ * Metadata is merged with a `{ agent: agentName }` marker so consumers can
44
+ * identify provenance when iterating all entries.
45
+ *
46
+ * @param agentName - The writing agent's name (used as a namespace prefix).
47
+ * @param key - Logical key within the agent's namespace.
48
+ * @param value - String value to store (serialise objects before writing).
49
+ * @param metadata - Optional extra metadata stored alongside the entry.
50
+ */
51
+ async write(agentName, key, value, metadata) {
52
+ const namespacedKey = SharedMemory.namespaceKey(agentName, key);
53
+ await this.store.set(namespacedKey, value, {
54
+ ...metadata,
55
+ agent: agentName,
56
+ });
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Read
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Read an entry by its fully-qualified key (`<agentName>/<key>`).
63
+ *
64
+ * Returns `null` when the key is absent.
65
+ */
66
+ async read(key) {
67
+ return this.store.get(key);
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // List
71
+ // ---------------------------------------------------------------------------
72
+ /** Returns every entry in the shared store, regardless of agent. */
73
+ async listAll() {
74
+ return this.store.list();
75
+ }
76
+ /**
77
+ * Returns all entries written by `agentName` (i.e. those whose key starts
78
+ * with `<agentName>/`).
79
+ */
80
+ async listByAgent(agentName) {
81
+ const prefix = SharedMemory.namespaceKey(agentName, '');
82
+ const all = await this.store.list();
83
+ return all.filter((entry) => entry.key.startsWith(prefix));
84
+ }
85
+ // ---------------------------------------------------------------------------
86
+ // Summary
87
+ // ---------------------------------------------------------------------------
88
+ /**
89
+ * Produces a human-readable summary of all entries in the store.
90
+ *
91
+ * The output is structured as a markdown-style block, grouped by agent, and
92
+ * is designed to be prepended to an agent's system prompt or injected as a
93
+ * user turn so the agent has context about what its teammates know.
94
+ *
95
+ * Returns an empty string when the store is empty.
96
+ *
97
+ * @example
98
+ * ```
99
+ * ## Shared Team Memory
100
+ *
101
+ * ### researcher
102
+ * - findings: TypeScript 5.5 ships const type params
103
+ *
104
+ * ### coder
105
+ * - plan: Implement feature X using const type params
106
+ * ```
107
+ */
108
+ async getSummary() {
109
+ const all = await this.store.list();
110
+ if (all.length === 0)
111
+ return '';
112
+ // Group entries by agent name.
113
+ const byAgent = new Map();
114
+ for (const entry of all) {
115
+ const slashIdx = entry.key.indexOf('/');
116
+ const agent = slashIdx === -1 ? '_unknown' : entry.key.slice(0, slashIdx);
117
+ const localKey = slashIdx === -1 ? entry.key : entry.key.slice(slashIdx + 1);
118
+ let group = byAgent.get(agent);
119
+ if (!group) {
120
+ group = [];
121
+ byAgent.set(agent, group);
122
+ }
123
+ group.push({ localKey, value: entry.value });
124
+ }
125
+ const lines = ['## Shared Team Memory', ''];
126
+ for (const [agent, entries] of byAgent) {
127
+ lines.push(`### ${agent}`);
128
+ for (const { localKey, value } of entries) {
129
+ // Truncate long values so the summary stays readable in a context window.
130
+ const displayValue = value.length > 200 ? `${value.slice(0, 197)}…` : value;
131
+ lines.push(`- ${localKey}: ${displayValue}`);
132
+ }
133
+ lines.push('');
134
+ }
135
+ return lines.join('\n').trimEnd();
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Store access
139
+ // ---------------------------------------------------------------------------
140
+ /**
141
+ * Returns the underlying {@link MemoryStore} so callers that only need the
142
+ * raw key-value interface can receive a properly typed reference without
143
+ * accessing private fields via bracket notation.
144
+ */
145
+ getStore() {
146
+ return this.store;
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // Private helpers
150
+ // ---------------------------------------------------------------------------
151
+ static namespaceKey(agentName, key) {
152
+ return `${agentName}/${key}`;
153
+ }
154
+ }
155
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/memory/shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @fileoverview In-memory implementation of {@link MemoryStore}.
3
+ *
4
+ * All data lives in a plain `Map` and is never persisted to disk. This is the
5
+ * default store used by {@link SharedMemory} and is suitable for testing and
6
+ * single-process use-cases. Swap it for a Redis or SQLite-backed implementation
7
+ * in production by satisfying the same {@link MemoryStore} interface.
8
+ */
9
+ import type { MemoryEntry, MemoryStore } from '../types.js';
10
+ /**
11
+ * Synchronous-under-the-hood key/value store that exposes an `async` surface
12
+ * so implementations can be swapped for async-native backends without changing
13
+ * callers.
14
+ *
15
+ * All keys are treated as opaque strings. Values are always strings; structured
16
+ * data must be serialised by the caller (e.g. `JSON.stringify`).
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const store = new InMemoryStore()
21
+ * await store.set('config', JSON.stringify({ model: 'claude-opus-4-6' }))
22
+ * const entry = await store.get('config')
23
+ * ```
24
+ */
25
+ export declare class InMemoryStore implements MemoryStore {
26
+ private readonly data;
27
+ /** Returns the entry for `key`, or `null` if not present. */
28
+ get(key: string): Promise<MemoryEntry | null>;
29
+ /**
30
+ * Upserts `key` with `value` and optional `metadata`.
31
+ *
32
+ * If the key already exists its `createdAt` is **preserved** so callers can
33
+ * detect when a value was first written.
34
+ */
35
+ set(key: string, value: string, metadata?: Record<string, unknown>): Promise<void>;
36
+ /** Returns a snapshot of all entries in insertion order. */
37
+ list(): Promise<MemoryEntry[]>;
38
+ /**
39
+ * Removes the entry for `key`.
40
+ * Deleting a non-existent key is a no-op.
41
+ */
42
+ delete(key: string): Promise<void>;
43
+ /** Removes **all** entries from the store. */
44
+ clear(): Promise<void>;
45
+ /**
46
+ * Returns entries whose `key` starts with `query` **or** whose `value`
47
+ * contains `query` (case-insensitive substring match).
48
+ *
49
+ * This is a simple linear scan; it is not suitable for very large stores
50
+ * without an index layer on top.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * // Find all entries related to "research"
55
+ * const hits = await store.search('research')
56
+ * ```
57
+ */
58
+ search(query: string): Promise<MemoryEntry[]>;
59
+ /** Returns the number of entries currently held in the store. */
60
+ get size(): number;
61
+ /** Returns `true` if `key` exists in the store. */
62
+ has(key: string): boolean;
63
+ }
64
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAM3D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;IAMtD,6DAA6D;IACvD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAInD;;;;;OAKG;IACG,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC;IAWhB,4DAA4D;IACtD,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAIpC;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,8CAA8C;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ5B;;;;;;;;;;;;OAYG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAgBnD,iEAAiE;IACjE,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,mDAAmD;IACnD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;CAG1B"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @fileoverview In-memory implementation of {@link MemoryStore}.
3
+ *
4
+ * All data lives in a plain `Map` and is never persisted to disk. This is the
5
+ * default store used by {@link SharedMemory} and is suitable for testing and
6
+ * single-process use-cases. Swap it for a Redis or SQLite-backed implementation
7
+ * in production by satisfying the same {@link MemoryStore} interface.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // InMemoryStore
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Synchronous-under-the-hood key/value store that exposes an `async` surface
14
+ * so implementations can be swapped for async-native backends without changing
15
+ * callers.
16
+ *
17
+ * All keys are treated as opaque strings. Values are always strings; structured
18
+ * data must be serialised by the caller (e.g. `JSON.stringify`).
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const store = new InMemoryStore()
23
+ * await store.set('config', JSON.stringify({ model: 'claude-opus-4-6' }))
24
+ * const entry = await store.get('config')
25
+ * ```
26
+ */
27
+ export class InMemoryStore {
28
+ data = new Map();
29
+ // ---------------------------------------------------------------------------
30
+ // MemoryStore interface
31
+ // ---------------------------------------------------------------------------
32
+ /** Returns the entry for `key`, or `null` if not present. */
33
+ async get(key) {
34
+ return this.data.get(key) ?? null;
35
+ }
36
+ /**
37
+ * Upserts `key` with `value` and optional `metadata`.
38
+ *
39
+ * If the key already exists its `createdAt` is **preserved** so callers can
40
+ * detect when a value was first written.
41
+ */
42
+ async set(key, value, metadata) {
43
+ const existing = this.data.get(key);
44
+ const entry = {
45
+ key,
46
+ value,
47
+ metadata: metadata !== undefined ? { ...metadata } : undefined,
48
+ createdAt: existing?.createdAt ?? new Date(),
49
+ };
50
+ this.data.set(key, entry);
51
+ }
52
+ /** Returns a snapshot of all entries in insertion order. */
53
+ async list() {
54
+ return Array.from(this.data.values());
55
+ }
56
+ /**
57
+ * Removes the entry for `key`.
58
+ * Deleting a non-existent key is a no-op.
59
+ */
60
+ async delete(key) {
61
+ this.data.delete(key);
62
+ }
63
+ /** Removes **all** entries from the store. */
64
+ async clear() {
65
+ this.data.clear();
66
+ }
67
+ // ---------------------------------------------------------------------------
68
+ // Extensions beyond the base MemoryStore interface
69
+ // ---------------------------------------------------------------------------
70
+ /**
71
+ * Returns entries whose `key` starts with `query` **or** whose `value`
72
+ * contains `query` (case-insensitive substring match).
73
+ *
74
+ * This is a simple linear scan; it is not suitable for very large stores
75
+ * without an index layer on top.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * // Find all entries related to "research"
80
+ * const hits = await store.search('research')
81
+ * ```
82
+ */
83
+ async search(query) {
84
+ if (query.length === 0) {
85
+ return this.list();
86
+ }
87
+ const lower = query.toLowerCase();
88
+ return Array.from(this.data.values()).filter((entry) => entry.key.toLowerCase().includes(lower) ||
89
+ entry.value.toLowerCase().includes(lower));
90
+ }
91
+ // ---------------------------------------------------------------------------
92
+ // Convenience helpers (not part of MemoryStore)
93
+ // ---------------------------------------------------------------------------
94
+ /** Returns the number of entries currently held in the store. */
95
+ get size() {
96
+ return this.data.size;
97
+ }
98
+ /** Returns `true` if `key` exists in the store. */
99
+ has(key) {
100
+ return this.data.has(key);
101
+ }
102
+ }
103
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/memory/store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,aAAa;IACP,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAA;IAEtD,8EAA8E;IAC9E,wBAAwB;IACxB,8EAA8E;IAE9E,6DAA6D;IAC7D,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;IACnC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,GAAG,CACP,GAAW,EACX,KAAa,EACb,QAAkC;QAElC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,KAAK,GAAgB;YACzB,GAAG;YACH,KAAK;YACL,QAAQ,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;YAC9D,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;SAC7C,CAAA;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAC3B,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,IAAI;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;IACvC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACvB,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAA;IACnB,CAAC;IAED,8EAA8E;IAC9E,mDAAmD;IACnD,8EAA8E;IAE9E;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa;QACxB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;QACjC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAC1C,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YACvC,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC5C,CAAA;IACH,CAAC;IAED,8EAA8E;IAC9E,gDAAgD;IAChD,8EAA8E;IAE9E,iEAAiE;IACjE,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;IACvB,CAAC;IAED,mDAAmD;IACnD,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,CAAC;CACF"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * @fileoverview OpenMultiAgent — the top-level multi-agent orchestration class.
3
+ *
4
+ * {@link OpenMultiAgent} is the primary public API of the open-multi-agent framework.
5
+ * It ties together every subsystem:
6
+ *
7
+ * - {@link Team} — Agent roster, shared memory, inter-agent messaging
8
+ * - {@link TaskQueue} — Dependency-aware work queue
9
+ * - {@link Scheduler} — Task-to-agent assignment strategies
10
+ * - {@link AgentPool} — Concurrency-controlled execution pool
11
+ * - {@link Agent} — Conversation + tool-execution loop
12
+ *
13
+ * ## Quick start
14
+ *
15
+ * ```ts
16
+ * const orchestrator = new OpenMultiAgent({ defaultModel: 'claude-opus-4-6' })
17
+ *
18
+ * const team = orchestrator.createTeam('research', {
19
+ * name: 'research',
20
+ * agents: [
21
+ * { name: 'researcher', model: 'claude-opus-4-6', systemPrompt: 'You are a researcher.' },
22
+ * { name: 'writer', model: 'claude-opus-4-6', systemPrompt: 'You are a technical writer.' },
23
+ * ],
24
+ * sharedMemory: true,
25
+ * })
26
+ *
27
+ * const result = await orchestrator.runTeam(team, 'Produce a report on TypeScript 5.5.')
28
+ * console.log(result.agentResults.get('coordinator')?.output)
29
+ * ```
30
+ *
31
+ * ## Key design decisions
32
+ *
33
+ * - **Coordinator pattern** — `runTeam()` spins up a temporary "coordinator" agent
34
+ * that breaks the high-level goal into tasks, assigns them, and synthesises the
35
+ * final answer. This is the framework's killer feature.
36
+ * - **Parallel-by-default** — Independent tasks (no shared dependency) run in
37
+ * parallel up to `maxConcurrency`.
38
+ * - **Graceful failure** — A failed task marks itself `'failed'` and its direct
39
+ * dependents remain `'blocked'` indefinitely; all non-dependent tasks continue.
40
+ * - **Progress callbacks** — Callers can pass `onProgress` in the config to receive
41
+ * structured {@link OrchestratorEvent}s without polling.
42
+ */
43
+ import type { AgentConfig, AgentRunResult, OrchestratorConfig, TeamConfig, TeamRunResult } from '../types.js';
44
+ import { Team } from '../team/team.js';
45
+ /**
46
+ * Top-level orchestrator for the open-multi-agent framework.
47
+ *
48
+ * Manages teams, coordinates task execution, and surfaces progress events.
49
+ * Most users will interact with this class exclusively.
50
+ */
51
+ export declare class OpenMultiAgent {
52
+ private readonly config;
53
+ private readonly teams;
54
+ private completedTaskCount;
55
+ /**
56
+ * @param config - Optional top-level configuration.
57
+ *
58
+ * Sensible defaults:
59
+ * - `maxConcurrency`: 5
60
+ * - `defaultModel`: `'claude-opus-4-6'`
61
+ * - `defaultProvider`: `'anthropic'`
62
+ */
63
+ constructor(config?: OrchestratorConfig);
64
+ /**
65
+ * Create and register a {@link Team} with the orchestrator.
66
+ *
67
+ * The team is stored internally so {@link getStatus} can report aggregate
68
+ * agent counts. Returns the new {@link Team} for further configuration.
69
+ *
70
+ * @param name - Unique team identifier. Throws if already registered.
71
+ * @param config - Team configuration (agents, shared memory, concurrency).
72
+ */
73
+ createTeam(name: string, config: TeamConfig): Team;
74
+ /**
75
+ * Run a single prompt with a one-off agent.
76
+ *
77
+ * Constructs a fresh agent from `config`, runs `prompt` in a single turn,
78
+ * and returns the result. The agent is not registered with any pool or team.
79
+ *
80
+ * Useful for simple one-shot queries that do not need team orchestration.
81
+ *
82
+ * @param config - Agent configuration.
83
+ * @param prompt - The user prompt to send.
84
+ */
85
+ runAgent(config: AgentConfig, prompt: string): Promise<AgentRunResult>;
86
+ /**
87
+ * Run a team on a high-level goal with full automatic orchestration.
88
+ *
89
+ * This is the flagship method of the framework. It works as follows:
90
+ *
91
+ * 1. A temporary "coordinator" agent receives the goal and the team's agent
92
+ * roster, and is asked to decompose it into an ordered list of tasks with
93
+ * JSON output.
94
+ * 2. The tasks are loaded into a {@link TaskQueue}. Title-based dependency
95
+ * tokens in the coordinator's output are resolved to task IDs.
96
+ * 3. The {@link Scheduler} assigns unassigned tasks to team agents.
97
+ * 4. Tasks are executed in dependency order, with independent tasks running
98
+ * in parallel up to `maxConcurrency`.
99
+ * 5. Results are persisted to shared memory after each task so subsequent
100
+ * agents can read them.
101
+ * 6. The coordinator synthesises a final answer from all task outputs.
102
+ * 7. A {@link TeamRunResult} is returned.
103
+ *
104
+ * @param team - A team created via {@link createTeam} (or `new Team(...)`).
105
+ * @param goal - High-level natural-language goal for the team.
106
+ */
107
+ runTeam(team: Team, goal: string): Promise<TeamRunResult>;
108
+ /**
109
+ * Run a team with an explicitly provided task list.
110
+ *
111
+ * Simpler than {@link runTeam}: no coordinator agent is involved. Tasks are
112
+ * loaded directly into the queue, unassigned tasks are auto-assigned via the
113
+ * {@link Scheduler}, and execution proceeds in dependency order.
114
+ *
115
+ * @param team - A team created via {@link createTeam}.
116
+ * @param tasks - Array of task descriptors.
117
+ */
118
+ runTasks(team: Team, tasks: ReadonlyArray<{
119
+ title: string;
120
+ description: string;
121
+ assignee?: string;
122
+ dependsOn?: string[];
123
+ }>): Promise<TeamRunResult>;
124
+ /**
125
+ * Returns a lightweight status snapshot.
126
+ *
127
+ * - `teams` — Number of teams registered with this orchestrator.
128
+ * - `activeAgents` — Total agents currently in `running` state.
129
+ * - `completedTasks` — Cumulative count of successfully completed tasks
130
+ * (coordinator meta-steps excluded).
131
+ */
132
+ getStatus(): {
133
+ teams: number;
134
+ activeAgents: number;
135
+ completedTasks: number;
136
+ };
137
+ /**
138
+ * Deregister all teams and reset internal counters.
139
+ *
140
+ * Does not cancel in-flight runs. Call this when you want to reuse the
141
+ * orchestrator instance for a fresh set of teams.
142
+ *
143
+ * Async for forward compatibility — shutdown may need to perform async
144
+ * cleanup (e.g. graceful agent drain) in future versions.
145
+ */
146
+ shutdown(): Promise<void>;
147
+ /** Build the system prompt given to the coordinator agent. */
148
+ private buildCoordinatorSystemPrompt;
149
+ /** Build the decomposition prompt for the coordinator. */
150
+ private buildDecompositionPrompt;
151
+ /** Build the synthesis prompt shown to the coordinator after all tasks complete. */
152
+ private buildSynthesisPrompt;
153
+ /**
154
+ * Load a list of task specs into a queue.
155
+ *
156
+ * Handles title-based `dependsOn` references by building a title→id map first,
157
+ * then resolving them to real IDs before adding tasks to the queue.
158
+ */
159
+ private loadSpecsIntoQueue;
160
+ /** Build an {@link AgentPool} from a list of agent configurations. */
161
+ private buildPool;
162
+ /**
163
+ * Aggregate the per-run `agentResults` map into a {@link TeamRunResult}.
164
+ *
165
+ * Merges results keyed as `agentName:taskId` back into a per-agent map
166
+ * by agent name for the public result surface.
167
+ *
168
+ * Only non-coordinator entries are counted toward `completedTaskCount` to
169
+ * avoid double-counting the coordinator's internal decompose/synthesis steps.
170
+ */
171
+ private buildTeamRunResult;
172
+ }
173
+ //# sourceMappingURL=orchestrator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/orchestrator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,kBAAkB,EAIlB,UAAU,EACV,aAAa,EAEd,MAAM,aAAa,CAAA;AAMpB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAoRtC;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAEmB;IAE1C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,kBAAkB,CAAI;IAE9B;;;;;;;OAOG;gBACS,MAAM,GAAE,kBAAuB;IAa3C;;;;;;;;OAQG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAgBlD;;;;;;;;;;OAUG;IACG,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA2B5E;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA+F/D;;;;;;;;;OASG;IACG,QAAQ,CACZ,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,aAAa,CAAC;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;KACrB,CAAC,GACD,OAAO,CAAC,aAAa,CAAC;IAqCzB;;;;;;;OAOG;IACH,SAAS,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;IAY5E;;;;;;;;OAQG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,8DAA8D;IAC9D,OAAO,CAAC,4BAA4B;IAgCpC,0DAA0D;IAC1D,OAAO,CAAC,wBAAwB;IAYhC,oFAAoF;YACtE,oBAAoB;IAuClC;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAoD1B,sEAAsE;IACtE,OAAO,CAAC,SAAS;IAajB;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;CAyC3B"}