@open-multi-agent/core 1.4.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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +373 -0
  3. package/dist/agent/agent.d.ts +153 -0
  4. package/dist/agent/agent.d.ts.map +1 -0
  5. package/dist/agent/agent.js +559 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/loop-detector.d.ts +39 -0
  8. package/dist/agent/loop-detector.d.ts.map +1 -0
  9. package/dist/agent/loop-detector.js +122 -0
  10. package/dist/agent/loop-detector.js.map +1 -0
  11. package/dist/agent/pool.d.ts +158 -0
  12. package/dist/agent/pool.d.ts.map +1 -0
  13. package/dist/agent/pool.js +320 -0
  14. package/dist/agent/pool.js.map +1 -0
  15. package/dist/agent/runner.d.ts +242 -0
  16. package/dist/agent/runner.d.ts.map +1 -0
  17. package/dist/agent/runner.js +943 -0
  18. package/dist/agent/runner.js.map +1 -0
  19. package/dist/agent/structured-output.d.ts +33 -0
  20. package/dist/agent/structured-output.d.ts.map +1 -0
  21. package/dist/agent/structured-output.js +116 -0
  22. package/dist/agent/structured-output.js.map +1 -0
  23. package/dist/cli/oma.d.ts +30 -0
  24. package/dist/cli/oma.d.ts.map +1 -0
  25. package/dist/cli/oma.js +433 -0
  26. package/dist/cli/oma.js.map +1 -0
  27. package/dist/dashboard/layout-tasks.d.ts +23 -0
  28. package/dist/dashboard/layout-tasks.d.ts.map +1 -0
  29. package/dist/dashboard/layout-tasks.js +79 -0
  30. package/dist/dashboard/layout-tasks.js.map +1 -0
  31. package/dist/dashboard/render-team-run-dashboard.d.ts +11 -0
  32. package/dist/dashboard/render-team-run-dashboard.d.ts.map +1 -0
  33. package/dist/dashboard/render-team-run-dashboard.js +456 -0
  34. package/dist/dashboard/render-team-run-dashboard.js.map +1 -0
  35. package/dist/errors.d.ts +14 -0
  36. package/dist/errors.d.ts.map +1 -0
  37. package/dist/errors.js +20 -0
  38. package/dist/errors.js.map +1 -0
  39. package/dist/index.d.ts +79 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +92 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/llm/adapter.d.ts +54 -0
  44. package/dist/llm/adapter.d.ts.map +1 -0
  45. package/dist/llm/adapter.js +101 -0
  46. package/dist/llm/adapter.js.map +1 -0
  47. package/dist/llm/anthropic.d.ts +57 -0
  48. package/dist/llm/anthropic.d.ts.map +1 -0
  49. package/dist/llm/anthropic.js +432 -0
  50. package/dist/llm/anthropic.js.map +1 -0
  51. package/dist/llm/azure-openai.d.ts +74 -0
  52. package/dist/llm/azure-openai.d.ts.map +1 -0
  53. package/dist/llm/azure-openai.js +267 -0
  54. package/dist/llm/azure-openai.js.map +1 -0
  55. package/dist/llm/bedrock.d.ts +41 -0
  56. package/dist/llm/bedrock.d.ts.map +1 -0
  57. package/dist/llm/bedrock.js +345 -0
  58. package/dist/llm/bedrock.js.map +1 -0
  59. package/dist/llm/copilot.d.ts +92 -0
  60. package/dist/llm/copilot.d.ts.map +1 -0
  61. package/dist/llm/copilot.js +433 -0
  62. package/dist/llm/copilot.js.map +1 -0
  63. package/dist/llm/deepseek.d.ts +21 -0
  64. package/dist/llm/deepseek.d.ts.map +1 -0
  65. package/dist/llm/deepseek.js +24 -0
  66. package/dist/llm/deepseek.js.map +1 -0
  67. package/dist/llm/gemini.d.ts +65 -0
  68. package/dist/llm/gemini.d.ts.map +1 -0
  69. package/dist/llm/gemini.js +427 -0
  70. package/dist/llm/gemini.js.map +1 -0
  71. package/dist/llm/grok.d.ts +21 -0
  72. package/dist/llm/grok.d.ts.map +1 -0
  73. package/dist/llm/grok.js +24 -0
  74. package/dist/llm/grok.js.map +1 -0
  75. package/dist/llm/minimax.d.ts +21 -0
  76. package/dist/llm/minimax.d.ts.map +1 -0
  77. package/dist/llm/minimax.js +24 -0
  78. package/dist/llm/minimax.js.map +1 -0
  79. package/dist/llm/openai-common.d.ts +65 -0
  80. package/dist/llm/openai-common.d.ts.map +1 -0
  81. package/dist/llm/openai-common.js +286 -0
  82. package/dist/llm/openai-common.js.map +1 -0
  83. package/dist/llm/openai.d.ts +63 -0
  84. package/dist/llm/openai.d.ts.map +1 -0
  85. package/dist/llm/openai.js +256 -0
  86. package/dist/llm/openai.js.map +1 -0
  87. package/dist/llm/qiniu.d.ts +21 -0
  88. package/dist/llm/qiniu.d.ts.map +1 -0
  89. package/dist/llm/qiniu.js +24 -0
  90. package/dist/llm/qiniu.js.map +1 -0
  91. package/dist/mcp.d.ts +3 -0
  92. package/dist/mcp.d.ts.map +1 -0
  93. package/dist/mcp.js +2 -0
  94. package/dist/mcp.js.map +1 -0
  95. package/dist/memory/shared.d.ts +162 -0
  96. package/dist/memory/shared.d.ts.map +1 -0
  97. package/dist/memory/shared.js +294 -0
  98. package/dist/memory/shared.js.map +1 -0
  99. package/dist/memory/store.d.ts +72 -0
  100. package/dist/memory/store.d.ts.map +1 -0
  101. package/dist/memory/store.js +121 -0
  102. package/dist/memory/store.js.map +1 -0
  103. package/dist/orchestrator/orchestrator.d.ts +245 -0
  104. package/dist/orchestrator/orchestrator.d.ts.map +1 -0
  105. package/dist/orchestrator/orchestrator.js +1400 -0
  106. package/dist/orchestrator/orchestrator.js.map +1 -0
  107. package/dist/orchestrator/scheduler.d.ts +112 -0
  108. package/dist/orchestrator/scheduler.d.ts.map +1 -0
  109. package/dist/orchestrator/scheduler.js +256 -0
  110. package/dist/orchestrator/scheduler.js.map +1 -0
  111. package/dist/task/queue.d.ts +191 -0
  112. package/dist/task/queue.d.ts.map +1 -0
  113. package/dist/task/queue.js +408 -0
  114. package/dist/task/queue.js.map +1 -0
  115. package/dist/task/task.d.ts +90 -0
  116. package/dist/task/task.d.ts.map +1 -0
  117. package/dist/task/task.js +206 -0
  118. package/dist/task/task.js.map +1 -0
  119. package/dist/team/messaging.d.ts +106 -0
  120. package/dist/team/messaging.d.ts.map +1 -0
  121. package/dist/team/messaging.js +183 -0
  122. package/dist/team/messaging.js.map +1 -0
  123. package/dist/team/team.d.ts +141 -0
  124. package/dist/team/team.d.ts.map +1 -0
  125. package/dist/team/team.js +293 -0
  126. package/dist/team/team.js.map +1 -0
  127. package/dist/tool/built-in/bash.d.ts +12 -0
  128. package/dist/tool/built-in/bash.d.ts.map +1 -0
  129. package/dist/tool/built-in/bash.js +133 -0
  130. package/dist/tool/built-in/bash.js.map +1 -0
  131. package/dist/tool/built-in/delegate.d.ts +29 -0
  132. package/dist/tool/built-in/delegate.d.ts.map +1 -0
  133. package/dist/tool/built-in/delegate.js +92 -0
  134. package/dist/tool/built-in/delegate.js.map +1 -0
  135. package/dist/tool/built-in/file-edit.d.ts +14 -0
  136. package/dist/tool/built-in/file-edit.d.ts.map +1 -0
  137. package/dist/tool/built-in/file-edit.js +130 -0
  138. package/dist/tool/built-in/file-edit.js.map +1 -0
  139. package/dist/tool/built-in/file-read.d.ts +12 -0
  140. package/dist/tool/built-in/file-read.d.ts.map +1 -0
  141. package/dist/tool/built-in/file-read.js +82 -0
  142. package/dist/tool/built-in/file-read.js.map +1 -0
  143. package/dist/tool/built-in/file-write.d.ts +11 -0
  144. package/dist/tool/built-in/file-write.d.ts.map +1 -0
  145. package/dist/tool/built-in/file-write.js +70 -0
  146. package/dist/tool/built-in/file-write.js.map +1 -0
  147. package/dist/tool/built-in/fs-walk.d.ts +23 -0
  148. package/dist/tool/built-in/fs-walk.d.ts.map +1 -0
  149. package/dist/tool/built-in/fs-walk.js +78 -0
  150. package/dist/tool/built-in/fs-walk.js.map +1 -0
  151. package/dist/tool/built-in/glob.d.ts +12 -0
  152. package/dist/tool/built-in/glob.d.ts.map +1 -0
  153. package/dist/tool/built-in/glob.js +82 -0
  154. package/dist/tool/built-in/glob.js.map +1 -0
  155. package/dist/tool/built-in/grep.d.ts +15 -0
  156. package/dist/tool/built-in/grep.d.ts.map +1 -0
  157. package/dist/tool/built-in/grep.js +218 -0
  158. package/dist/tool/built-in/grep.js.map +1 -0
  159. package/dist/tool/built-in/index.d.ts +48 -0
  160. package/dist/tool/built-in/index.d.ts.map +1 -0
  161. package/dist/tool/built-in/index.js +56 -0
  162. package/dist/tool/built-in/index.js.map +1 -0
  163. package/dist/tool/executor.d.ts +100 -0
  164. package/dist/tool/executor.d.ts.map +1 -0
  165. package/dist/tool/executor.js +184 -0
  166. package/dist/tool/executor.js.map +1 -0
  167. package/dist/tool/framework.d.ts +167 -0
  168. package/dist/tool/framework.d.ts.map +1 -0
  169. package/dist/tool/framework.js +402 -0
  170. package/dist/tool/framework.js.map +1 -0
  171. package/dist/tool/mcp.d.ts +31 -0
  172. package/dist/tool/mcp.d.ts.map +1 -0
  173. package/dist/tool/mcp.js +175 -0
  174. package/dist/tool/mcp.js.map +1 -0
  175. package/dist/tool/text-tool-extractor.d.ts +32 -0
  176. package/dist/tool/text-tool-extractor.d.ts.map +1 -0
  177. package/dist/tool/text-tool-extractor.js +195 -0
  178. package/dist/tool/text-tool-extractor.js.map +1 -0
  179. package/dist/types.d.ts +916 -0
  180. package/dist/types.d.ts.map +1 -0
  181. package/dist/types.js +8 -0
  182. package/dist/types.js.map +1 -0
  183. package/dist/utils/keywords.d.ts +18 -0
  184. package/dist/utils/keywords.d.ts.map +1 -0
  185. package/dist/utils/keywords.js +32 -0
  186. package/dist/utils/keywords.js.map +1 -0
  187. package/dist/utils/semaphore.d.ts +49 -0
  188. package/dist/utils/semaphore.d.ts.map +1 -0
  189. package/dist/utils/semaphore.js +89 -0
  190. package/dist/utils/semaphore.js.map +1 -0
  191. package/dist/utils/tokens.d.ts +7 -0
  192. package/dist/utils/tokens.d.ts.map +1 -0
  193. package/dist/utils/tokens.js +30 -0
  194. package/dist/utils/tokens.js.map +1 -0
  195. package/dist/utils/trace.d.ts +12 -0
  196. package/dist/utils/trace.d.ts.map +1 -0
  197. package/dist/utils/trace.js +30 -0
  198. package/dist/utils/trace.js.map +1 -0
  199. package/docs/DECISIONS.md +49 -0
  200. package/docs/cli.md +265 -0
  201. package/docs/context-management.md +24 -0
  202. package/docs/featured-partner.md +28 -0
  203. package/docs/observability.md +56 -0
  204. package/docs/providers.md +78 -0
  205. package/docs/shared-memory.md +27 -0
  206. package/docs/tool-configuration.md +152 -0
  207. package/package.json +96 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/task/queue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAOnD,sDAAsD;AACtD,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,eAAe,GACf,aAAa,GACb,cAAc,GACd,cAAc,CAAA;AAElB,2EAA2E;AAC3E,KAAK,WAAW,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAA;AACvC,uDAAuD;AACvD,KAAK,kBAAkB,GAAG,MAAM,IAAI,CAAA;AAEpC,KAAK,UAAU,CAAC,CAAC,SAAS,cAAc,IAAI,CAAC,SAAS,cAAc,GAChE,kBAAkB,GAClB,WAAW,CAAA;AAMf;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAEhD,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAGvB;IAMH;;;;;OAKG;IACH,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAQrB;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IAU7B;;;;;;;OAOG;IACH,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC,CAAC,GAC5D,IAAI;IAWP;;;;;;;;OAQG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAU/C;;;;;;;;OAQG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAUzC;;;;;;;;;OASG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAU1C;;;;;;;;;;OAUG;IACH,aAAa,CAAC,MAAM,SAAgC,GAAG,IAAI;IAc3D;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAetB;;;OAGG;IACH,OAAO,CAAC,WAAW;IAkBnB;;;;;OAKG;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAWzC;;;OAGG;IACH,aAAa,IAAI,IAAI,GAAG,SAAS;IAYjC,0DAA0D;IAC1D,IAAI,IAAI,IAAI,EAAE;IAId,yDAAyD;IACzD,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE;IAIvC,wCAAwC;IACxC,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIrC;;;OAGG;IACH,UAAU,IAAI,OAAO;IAOrB;;;;;;;;OAQG;IACH,WAAW,IAAI;QACb,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAA;QACf,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;KAChB;IA8CD;;;;;;;;;;;OAWG;IACH,EAAE,CAAC,CAAC,SAAS,cAAc,EACzB,KAAK,EAAE,CAAC,EACR,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,GACrB,MAAM,IAAI;IAiBb;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAU5B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAwBzB,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,WAAW;CAKpB"}
@@ -0,0 +1,408 @@
1
+ /**
2
+ * @fileoverview Dependency-aware task queue.
3
+ *
4
+ * {@link TaskQueue} owns the mutable lifecycle of every task it holds.
5
+ * Completing a task automatically unblocks dependents and fires events so
6
+ * orchestrators can react without polling.
7
+ */
8
+ import { isTaskReady } from './task.js';
9
+ // ---------------------------------------------------------------------------
10
+ // TaskQueue
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Mutable, event-driven queue with topological dependency resolution.
14
+ *
15
+ * Tasks enter in `'pending'` state. The queue promotes them to `'blocked'`
16
+ * when unresolved dependencies exist, and back to `'pending'` (firing
17
+ * `'task:ready'`) when those dependencies complete. Callers drive execution by
18
+ * calling {@link next} / {@link nextAvailable} and updating task state via
19
+ * {@link complete} or {@link fail}.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const queue = new TaskQueue()
24
+ * queue.on('task:ready', (task) => scheduleExecution(task))
25
+ * queue.on('all:complete', () => shutdown())
26
+ *
27
+ * queue.addBatch(tasks)
28
+ * ```
29
+ */
30
+ export class TaskQueue {
31
+ tasks = new Map();
32
+ /** Listeners keyed by event type, stored as symbol → handler pairs. */
33
+ listeners = new Map();
34
+ // ---------------------------------------------------------------------------
35
+ // Mutation: add
36
+ // ---------------------------------------------------------------------------
37
+ /**
38
+ * Adds a single task.
39
+ *
40
+ * If the task has unresolved dependencies it is immediately promoted to
41
+ * `'blocked'`; otherwise it stays `'pending'` and `'task:ready'` fires.
42
+ */
43
+ add(task) {
44
+ const resolved = this.resolveInitialStatus(task);
45
+ this.tasks.set(resolved.id, resolved);
46
+ if (resolved.status === 'pending') {
47
+ this.emit('task:ready', resolved);
48
+ }
49
+ }
50
+ /**
51
+ * Adds multiple tasks at once.
52
+ *
53
+ * Processing each task re-evaluates the current map state, so inserting a
54
+ * batch where some tasks satisfy others' dependencies produces correct initial
55
+ * statuses when the dependencies appear first in the array. Use
56
+ * {@link getTaskDependencyOrder} from `task.ts` to pre-sort if needed.
57
+ */
58
+ addBatch(tasks) {
59
+ for (const task of tasks) {
60
+ this.add(task);
61
+ }
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Mutation: update / complete / fail
65
+ // ---------------------------------------------------------------------------
66
+ /**
67
+ * Applies a partial update to an existing task.
68
+ *
69
+ * Only `status`, `result`, and `assignee` are accepted to keep the update
70
+ * surface narrow. Use {@link complete} and {@link fail} for terminal states.
71
+ *
72
+ * @throws {Error} when `taskId` is not found.
73
+ */
74
+ update(taskId, update) {
75
+ const task = this.requireTask(taskId);
76
+ const updated = {
77
+ ...task,
78
+ ...update,
79
+ updatedAt: new Date(),
80
+ };
81
+ this.tasks.set(taskId, updated);
82
+ return updated;
83
+ }
84
+ /**
85
+ * Marks `taskId` as `'completed'`, records an optional `result` string, and
86
+ * unblocks any dependents that are now ready to run.
87
+ *
88
+ * Fires `'task:complete'`, then `'task:ready'` for each newly-unblocked task,
89
+ * then `'all:complete'` when the queue is fully resolved.
90
+ *
91
+ * @throws {Error} when `taskId` is not found.
92
+ */
93
+ complete(taskId, result) {
94
+ const completed = this.update(taskId, { status: 'completed', result });
95
+ this.emit('task:complete', completed);
96
+ this.unblockDependents(taskId);
97
+ if (this.isComplete()) {
98
+ this.emitAllComplete();
99
+ }
100
+ return completed;
101
+ }
102
+ /**
103
+ * Marks `taskId` as `'failed'` and records `error` in the `result` field.
104
+ *
105
+ * Fires `'task:failed'` for the failed task and for every downstream task
106
+ * that transitively depended on it (cascade failure). This prevents blocked
107
+ * tasks from remaining stuck indefinitely when an upstream dependency fails.
108
+ *
109
+ * @throws {Error} when `taskId` is not found.
110
+ */
111
+ fail(taskId, error) {
112
+ const failed = this.update(taskId, { status: 'failed', result: error });
113
+ this.emit('task:failed', failed);
114
+ this.cascadeFailure(taskId);
115
+ if (this.isComplete()) {
116
+ this.emitAllComplete();
117
+ }
118
+ return failed;
119
+ }
120
+ /**
121
+ * Marks `taskId` as `'skipped'` and records `reason` in the `result` field.
122
+ *
123
+ * Fires `'task:skipped'` for the skipped task and cascades to every
124
+ * downstream task that transitively depended on it — even if the dependent
125
+ * has other dependencies that are still pending or completed. A skipped
126
+ * upstream is treated as permanently unsatisfiable, mirroring `fail()`.
127
+ *
128
+ * @throws {Error} when `taskId` is not found.
129
+ */
130
+ skip(taskId, reason) {
131
+ const skipped = this.update(taskId, { status: 'skipped', result: reason });
132
+ this.emit('task:skipped', skipped);
133
+ this.cascadeSkip(taskId);
134
+ if (this.isComplete()) {
135
+ this.emitAllComplete();
136
+ }
137
+ return skipped;
138
+ }
139
+ /**
140
+ * Marks all non-terminal tasks as `'skipped'`.
141
+ *
142
+ * Used when an approval gate rejects continuation — every pending, blocked,
143
+ * or in-progress task is skipped with the given reason.
144
+ *
145
+ * **Important:** Call only when no tasks are actively executing. The
146
+ * orchestrator invokes this after `await Promise.all()`, so no tasks are
147
+ * in-flight. Calling while agents are running may mark an in-progress task
148
+ * as skipped while its agent continues executing.
149
+ */
150
+ skipRemaining(reason = 'Skipped: approval rejected.') {
151
+ // Snapshot first — update() mutates the live map, which is unsafe to
152
+ // iterate over during modification.
153
+ const snapshot = Array.from(this.tasks.values());
154
+ for (const task of snapshot) {
155
+ if (task.status === 'completed' || task.status === 'failed' || task.status === 'skipped')
156
+ continue;
157
+ const skipped = this.update(task.id, { status: 'skipped', result: reason });
158
+ this.emit('task:skipped', skipped);
159
+ }
160
+ if (this.isComplete()) {
161
+ this.emitAllComplete();
162
+ }
163
+ }
164
+ /**
165
+ * Recursively marks all tasks that (transitively) depend on `failedTaskId`
166
+ * as `'failed'` with an informative message, firing `'task:failed'` for each.
167
+ *
168
+ * Only tasks in `'blocked'` or `'pending'` state are affected; tasks already
169
+ * in a terminal state are left untouched.
170
+ */
171
+ cascadeFailure(failedTaskId) {
172
+ for (const task of this.tasks.values()) {
173
+ if (task.status !== 'blocked' && task.status !== 'pending')
174
+ continue;
175
+ if (!task.dependsOn?.includes(failedTaskId))
176
+ continue;
177
+ const cascaded = this.update(task.id, {
178
+ status: 'failed',
179
+ result: `Cancelled: dependency "${failedTaskId}" failed.`,
180
+ });
181
+ this.emit('task:failed', cascaded);
182
+ // Recurse to handle transitive dependents.
183
+ this.cascadeFailure(task.id);
184
+ }
185
+ }
186
+ /**
187
+ * Recursively marks all tasks that (transitively) depend on `skippedTaskId`
188
+ * as `'skipped'`, firing `'task:skipped'` for each.
189
+ */
190
+ cascadeSkip(skippedTaskId) {
191
+ for (const task of this.tasks.values()) {
192
+ if (task.status !== 'blocked' && task.status !== 'pending')
193
+ continue;
194
+ if (!task.dependsOn?.includes(skippedTaskId))
195
+ continue;
196
+ const cascaded = this.update(task.id, {
197
+ status: 'skipped',
198
+ result: `Skipped: dependency "${skippedTaskId}" was skipped.`,
199
+ });
200
+ this.emit('task:skipped', cascaded);
201
+ this.cascadeSkip(task.id);
202
+ }
203
+ }
204
+ // ---------------------------------------------------------------------------
205
+ // Queries
206
+ // ---------------------------------------------------------------------------
207
+ /**
208
+ * Returns the next `'pending'` task for `assignee` (matched against
209
+ * `task.assignee`), or `undefined` if none exists.
210
+ *
211
+ * If `assignee` is omitted, behaves like {@link nextAvailable}.
212
+ */
213
+ next(assignee) {
214
+ if (assignee === undefined)
215
+ return this.nextAvailable();
216
+ for (const task of this.tasks.values()) {
217
+ if (task.status === 'pending' && task.assignee === assignee) {
218
+ return task;
219
+ }
220
+ }
221
+ return undefined;
222
+ }
223
+ /**
224
+ * Returns the next `'pending'` task that has no `assignee` restriction, or
225
+ * the first `'pending'` task overall when all pending tasks have an assignee.
226
+ */
227
+ nextAvailable() {
228
+ let fallback;
229
+ for (const task of this.tasks.values()) {
230
+ if (task.status !== 'pending')
231
+ continue;
232
+ if (!task.assignee)
233
+ return task;
234
+ if (!fallback)
235
+ fallback = task;
236
+ }
237
+ return fallback;
238
+ }
239
+ /** Returns a snapshot array of all tasks (any status). */
240
+ list() {
241
+ return Array.from(this.tasks.values());
242
+ }
243
+ /** Returns all tasks whose `status` matches `status`. */
244
+ getByStatus(status) {
245
+ return this.list().filter((t) => t.status === status);
246
+ }
247
+ /** Returns a task by ID, if present. */
248
+ get(taskId) {
249
+ return this.tasks.get(taskId);
250
+ }
251
+ /**
252
+ * Returns `true` when every task in the queue has reached a terminal state
253
+ * (`'completed'`, `'failed'`, or `'skipped'`), **or** the queue is empty.
254
+ */
255
+ isComplete() {
256
+ for (const task of this.tasks.values()) {
257
+ if (task.status !== 'completed' && task.status !== 'failed' && task.status !== 'skipped')
258
+ return false;
259
+ }
260
+ return true;
261
+ }
262
+ /**
263
+ * Returns a progress snapshot.
264
+ *
265
+ * @example
266
+ * ```ts
267
+ * const { completed, total } = queue.getProgress()
268
+ * console.log(`${completed}/${total} tasks done`)
269
+ * ```
270
+ */
271
+ getProgress() {
272
+ let completed = 0;
273
+ let failed = 0;
274
+ let skipped = 0;
275
+ let inProgress = 0;
276
+ let pending = 0;
277
+ let blocked = 0;
278
+ for (const task of this.tasks.values()) {
279
+ switch (task.status) {
280
+ case 'completed':
281
+ completed++;
282
+ break;
283
+ case 'failed':
284
+ failed++;
285
+ break;
286
+ case 'skipped':
287
+ skipped++;
288
+ break;
289
+ case 'in_progress':
290
+ inProgress++;
291
+ break;
292
+ case 'pending':
293
+ pending++;
294
+ break;
295
+ case 'blocked':
296
+ blocked++;
297
+ break;
298
+ }
299
+ }
300
+ return {
301
+ total: this.tasks.size,
302
+ completed,
303
+ failed,
304
+ skipped,
305
+ inProgress,
306
+ pending,
307
+ blocked,
308
+ };
309
+ }
310
+ // ---------------------------------------------------------------------------
311
+ // Events
312
+ // ---------------------------------------------------------------------------
313
+ /**
314
+ * Subscribes to a queue event.
315
+ *
316
+ * @returns An unsubscribe function. Calling it is idempotent.
317
+ *
318
+ * @example
319
+ * ```ts
320
+ * const off = queue.on('task:ready', (task) => execute(task))
321
+ * // later…
322
+ * off()
323
+ * ```
324
+ */
325
+ on(event, handler) {
326
+ let map = this.listeners.get(event);
327
+ if (!map) {
328
+ map = new Map();
329
+ this.listeners.set(event, map);
330
+ }
331
+ const id = Symbol();
332
+ map.set(id, handler);
333
+ return () => {
334
+ map.delete(id);
335
+ };
336
+ }
337
+ // ---------------------------------------------------------------------------
338
+ // Private helpers
339
+ // ---------------------------------------------------------------------------
340
+ /**
341
+ * Evaluates whether `task` should start as `'blocked'` based on the tasks
342
+ * already registered in the queue.
343
+ */
344
+ resolveInitialStatus(task) {
345
+ if (!task.dependsOn || task.dependsOn.length === 0)
346
+ return task;
347
+ const allCurrent = Array.from(this.tasks.values());
348
+ const ready = isTaskReady(task, allCurrent);
349
+ if (ready)
350
+ return task;
351
+ return { ...task, status: 'blocked', updatedAt: new Date() };
352
+ }
353
+ /**
354
+ * After a task completes, scan all `'blocked'` tasks and promote any that are
355
+ * now fully satisfied to `'pending'`, firing `'task:ready'` for each.
356
+ *
357
+ * The task array and lookup map are built once for the entire scan to keep
358
+ * the operation O(n) rather than O(n²).
359
+ */
360
+ unblockDependents(completedId) {
361
+ const allTasks = Array.from(this.tasks.values());
362
+ const taskById = new Map(allTasks.map((t) => [t.id, t]));
363
+ for (const task of allTasks) {
364
+ if (task.status !== 'blocked')
365
+ continue;
366
+ if (!task.dependsOn?.includes(completedId))
367
+ continue;
368
+ // Re-check against the current state of the whole task set.
369
+ // Pass the pre-built map to avoid rebuilding it for every candidate task.
370
+ if (isTaskReady({ ...task, status: 'pending' }, allTasks, taskById)) {
371
+ const unblocked = {
372
+ ...task,
373
+ status: 'pending',
374
+ updatedAt: new Date(),
375
+ };
376
+ this.tasks.set(task.id, unblocked);
377
+ // Update the map so subsequent iterations in the same call see the new status.
378
+ taskById.set(task.id, unblocked);
379
+ this.emit('task:ready', unblocked);
380
+ }
381
+ }
382
+ }
383
+ emit(event, task) {
384
+ const map = this.listeners.get(event);
385
+ if (!map)
386
+ return;
387
+ for (const handler of map.values()) {
388
+ ;
389
+ handler(task);
390
+ }
391
+ }
392
+ emitAllComplete() {
393
+ const map = this.listeners.get('all:complete');
394
+ if (!map)
395
+ return;
396
+ for (const handler of map.values()) {
397
+ ;
398
+ handler();
399
+ }
400
+ }
401
+ requireTask(taskId) {
402
+ const task = this.tasks.get(taskId);
403
+ if (!task)
404
+ throw new Error(`TaskQueue: task "${taskId}" not found.`);
405
+ return task;
406
+ }
407
+ }
408
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/task/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * @fileoverview Pure task utility functions.
3
+ *
4
+ * These helpers operate on plain {@link Task} values without any mutable
5
+ * state, making them safe to use in reducers, tests, and reactive pipelines.
6
+ * Stateful orchestration belongs in {@link TaskQueue}.
7
+ */
8
+ import type { Task } from '../types.js';
9
+ /**
10
+ * Creates a new {@link Task} with a generated UUID, `'pending'` status, and
11
+ * `createdAt`/`updatedAt` timestamps set to the current instant.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const task = createTask({
16
+ * title: 'Research competitors',
17
+ * description: 'Identify the top 5 competitors and their pricing',
18
+ * assignee: 'researcher',
19
+ * })
20
+ * ```
21
+ */
22
+ export declare function createTask(input: {
23
+ title: string;
24
+ description: string;
25
+ assignee?: string;
26
+ dependsOn?: string[];
27
+ memoryScope?: 'dependencies' | 'all';
28
+ maxRetries?: number;
29
+ retryDelayMs?: number;
30
+ retryBackoff?: number;
31
+ }): Task;
32
+ /**
33
+ * Returns `true` when `task` can be started immediately.
34
+ *
35
+ * A task is considered ready when:
36
+ * 1. Its status is `'pending'`.
37
+ * 2. Every task listed in `task.dependsOn` has status `'completed'`.
38
+ *
39
+ * Tasks whose dependencies are missing from `allTasks` are treated as
40
+ * unresolvable and therefore **not** ready.
41
+ *
42
+ * @param task - The task to evaluate.
43
+ * @param allTasks - The full collection of tasks in the current queue/plan.
44
+ * @param taskById - Optional pre-built id→task map. When provided the function
45
+ * skips rebuilding the map, reducing the complexity of
46
+ * call-sites that invoke `isTaskReady` inside a loop from
47
+ * O(n²) to O(n).
48
+ */
49
+ export declare function isTaskReady(task: Task, allTasks: Task[], taskById?: Map<string, Task>): boolean;
50
+ /**
51
+ * Returns `tasks` sorted so that each task appears after all of its
52
+ * dependencies — a standard topological (Kahn's algorithm) ordering.
53
+ *
54
+ * Tasks with no dependencies come first. If the graph contains a cycle the
55
+ * function returns a partial result containing only the tasks that could be
56
+ * ordered; use {@link validateTaskDependencies} to detect cycles before calling
57
+ * this function in production paths.
58
+ *
59
+ * @example
60
+ * ```ts
61
+ * const ordered = getTaskDependencyOrder(tasks)
62
+ * for (const task of ordered) {
63
+ * await run(task)
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function getTaskDependencyOrder(tasks: Task[]): Task[];
68
+ /**
69
+ * Validates the dependency graph of a task collection.
70
+ *
71
+ * Checks for:
72
+ * - References to unknown task IDs in `dependsOn`.
73
+ * - Cycles (a task depending on itself, directly or transitively).
74
+ * - Self-dependencies (`task.dependsOn` includes its own `id`).
75
+ *
76
+ * @returns An object with `valid: true` when no issues were found, or
77
+ * `valid: false` with a non-empty `errors` array describing each
78
+ * problem.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * const { valid, errors } = validateTaskDependencies(tasks)
83
+ * if (!valid) throw new Error(errors.join('\n'))
84
+ * ```
85
+ */
86
+ export declare function validateTaskDependencies(tasks: Task[]): {
87
+ valid: boolean;
88
+ errors: string[];
89
+ };
90
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/task/task.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,aAAa,CAAA;AAMnD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,WAAW,CAAC,EAAE,cAAc,GAAG,KAAK,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,IAAI,CAiBP;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,IAAI,EAAE,EAChB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,GAC3B,OAAO,CAYT;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,CA6C5D;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG;IACvD,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAoDA"}