taskmeld 0.1.1

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 (204) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +172 -0
  3. package/README.zh-CN.md +172 -0
  4. package/dist/src/app/app-context-env.js +51 -0
  5. package/dist/src/app/create-app-context.js +127 -0
  6. package/dist/src/app/data-dir.js +29 -0
  7. package/dist/src/app/pipeline-config.js +105 -0
  8. package/dist/src/app/pipeline-plugin-config.js +2 -0
  9. package/dist/src/app/pipeline-registry.js +502 -0
  10. package/dist/src/app/pipeline-runtime.js +202 -0
  11. package/dist/src/app/runtime-store.js +151 -0
  12. package/dist/src/app/user-config.js +37 -0
  13. package/dist/src/artifacts/artifact-cleanup.js +192 -0
  14. package/dist/src/artifacts/artifact-index.js +262 -0
  15. package/dist/src/artifacts/artifact-rebuilder.js +120 -0
  16. package/dist/src/artifacts/storage-service.js +371 -0
  17. package/dist/src/cli/bootstrap.js +226 -0
  18. package/dist/src/cli/commands/agent.js +126 -0
  19. package/dist/src/cli/commands/artifact.js +175 -0
  20. package/dist/src/cli/commands/init.js +150 -0
  21. package/dist/src/cli/commands/pipeline/errors.js +37 -0
  22. package/dist/src/cli/commands/pipeline/result.js +179 -0
  23. package/dist/src/cli/commands/pipeline/selector.js +51 -0
  24. package/dist/src/cli/commands/pipeline/types.js +2 -0
  25. package/dist/src/cli/commands/pipeline/watch.js +67 -0
  26. package/dist/src/cli/commands/pipeline.js +339 -0
  27. package/dist/src/cli/commands/scheduler.js +81 -0
  28. package/dist/src/cli/commands/server.js +70 -0
  29. package/dist/src/cli/commands/system.js +21 -0
  30. package/dist/src/cli/errors.js +71 -0
  31. package/dist/src/cli/help.js +184 -0
  32. package/dist/src/cli/index.js +65 -0
  33. package/dist/src/cli/output.js +19 -0
  34. package/dist/src/cli/renderers/engine/json.js +67 -0
  35. package/dist/src/cli/renderers/engine/markdown.js +95 -0
  36. package/dist/src/cli/renderers/engine/types.js +2 -0
  37. package/dist/src/cli/renderers/engine/utils.js +32 -0
  38. package/dist/src/cli/renderers/index.js +27 -0
  39. package/dist/src/cli/renderers/specs/agent.js +78 -0
  40. package/dist/src/cli/renderers/specs/artifact.js +32 -0
  41. package/dist/src/cli/renderers/specs/index.js +36 -0
  42. package/dist/src/cli/renderers/specs/init.js +25 -0
  43. package/dist/src/cli/renderers/specs/pipeline.js +561 -0
  44. package/dist/src/cli/renderers/specs/scheduler.js +46 -0
  45. package/dist/src/cli/renderers/specs/server.js +38 -0
  46. package/dist/src/cli/renderers/specs/system.js +36 -0
  47. package/dist/src/cli/router.js +199 -0
  48. package/dist/src/cli/server-runtime-client.js +780 -0
  49. package/dist/src/cli/types.js +2 -0
  50. package/dist/src/gateway/frame-sanitizer.js +78 -0
  51. package/dist/src/gateway/gateway-client.js +462 -0
  52. package/dist/src/gateway/index.js +18 -0
  53. package/dist/src/gateway/types.js +2 -0
  54. package/dist/src/index.js +123 -0
  55. package/dist/src/logs/run-log-reader.js +141 -0
  56. package/dist/src/logs/run-log-service.js +42 -0
  57. package/dist/src/logs/run-log-types.js +2 -0
  58. package/dist/src/pipeline/agent-activity.js +191 -0
  59. package/dist/src/pipeline/artifact-storage.js +208 -0
  60. package/dist/src/pipeline/diagnostics/dependency-diagnostic.js +105 -0
  61. package/dist/src/pipeline/diagnostics/index.js +6 -0
  62. package/dist/src/pipeline/dispatch/pipeline-inbound-queue.js +215 -0
  63. package/dist/src/pipeline/dispatch/pipeline-link-dispatcher.js +66 -0
  64. package/dist/src/pipeline/dispatch/pipeline-link-store.js +94 -0
  65. package/dist/src/pipeline/dispatch/pipeline-queue-drainer.js +71 -0
  66. package/dist/src/pipeline/execution/dependency-check.js +52 -0
  67. package/dist/src/pipeline/execution/execution-result.js +2 -0
  68. package/dist/src/pipeline/execution/group-item-executor.js +128 -0
  69. package/dist/src/pipeline/execution/index.js +5 -0
  70. package/dist/src/pipeline/execution/node-item-executor.js +58 -0
  71. package/dist/src/pipeline/execution/node-runner.js +159 -0
  72. package/dist/src/pipeline/execution/readiness-state.js +10 -0
  73. package/dist/src/pipeline/execution/reject-handler.js +94 -0
  74. package/dist/src/pipeline/execution/rejected-artifact-archiver.js +45 -0
  75. package/dist/src/pipeline/execution/route-item-manager.js +253 -0
  76. package/dist/src/pipeline/execution/run-abort-controller.js +66 -0
  77. package/dist/src/pipeline/execution/run-state-helpers.js +257 -0
  78. package/dist/src/pipeline/execution/service.js +165 -0
  79. package/dist/src/pipeline/execution/session-registry.js +96 -0
  80. package/dist/src/pipeline/execution/structured-node-runner.js +411 -0
  81. package/dist/src/pipeline/execution-status.js +96 -0
  82. package/dist/src/pipeline/execution-timeout.js +21 -0
  83. package/dist/src/pipeline/identity/index.js +32 -0
  84. package/dist/src/pipeline/identity/types.js +2 -0
  85. package/dist/src/pipeline/item-batch-controller.js +227 -0
  86. package/dist/src/pipeline/output/pipeline-output-resolver.js +91 -0
  87. package/dist/src/pipeline/output/pipeline-output-store.js +60 -0
  88. package/dist/src/pipeline/runtime-model.js +173 -0
  89. package/dist/src/pipeline/scheduler/dependency-state.js +144 -0
  90. package/dist/src/pipeline/scheduler-service.js +314 -0
  91. package/dist/src/pipeline/state/group-item-state.js +50 -0
  92. package/dist/src/pipeline/state/group-run-state.js +41 -0
  93. package/dist/src/pipeline/state/index.js +20 -0
  94. package/dist/src/pipeline/state/node-item-state.js +67 -0
  95. package/dist/src/pipeline/state/node-run-state.js +51 -0
  96. package/dist/src/pipeline/state/types.js +2 -0
  97. package/dist/src/pipeline/state-machine.js +101 -0
  98. package/dist/src/pipeline/structured-output/contract.js +133 -0
  99. package/dist/src/pipeline/structured-output/index.js +22 -0
  100. package/dist/src/pipeline/structured-output/parser.js +214 -0
  101. package/dist/src/pipeline/structured-output/prompt.js +290 -0
  102. package/dist/src/pipeline/structured-output/waiter.js +139 -0
  103. package/dist/src/pipeline/template.js +135 -0
  104. package/dist/src/pipeline/timeline-log-store.js +57 -0
  105. package/dist/src/pipeline/tool-activity.js +94 -0
  106. package/dist/src/pipeline/types/pipeline-link.js +7 -0
  107. package/dist/src/pipeline/types/pipeline-output.js +11 -0
  108. package/dist/src/pipeline/types/workflow.js +2 -0
  109. package/dist/src/pipeline/workflow/branch-rules.js +74 -0
  110. package/dist/src/pipeline/workflow/defaults.js +48 -0
  111. package/dist/src/pipeline/workflow/io.js +89 -0
  112. package/dist/src/pipeline/workflow/normalize.js +347 -0
  113. package/dist/src/pipeline/workflow/routes.js +16 -0
  114. package/dist/src/pipeline/workflow/template-mapper.js +113 -0
  115. package/dist/src/pipeline/workflow/validate.js +312 -0
  116. package/dist/src/pipeline/workflow-graph.js +165 -0
  117. package/dist/src/server/api-handler.js +163 -0
  118. package/dist/src/server/http-utils.js +34 -0
  119. package/dist/src/server/middleware.js +61 -0
  120. package/dist/src/server/router.js +105 -0
  121. package/dist/src/server/routes/agents.js +189 -0
  122. package/dist/src/server/routes/artifacts.js +163 -0
  123. package/dist/src/server/routes/gateway.js +18 -0
  124. package/dist/src/server/routes/health.js +16 -0
  125. package/dist/src/server/routes/logs.js +73 -0
  126. package/dist/src/server/routes/pipeline-batch.js +163 -0
  127. package/dist/src/server/routes/pipeline-diagnostics.js +33 -0
  128. package/dist/src/server/routes/pipeline-identity.js +24 -0
  129. package/dist/src/server/routes/pipeline-links.js +117 -0
  130. package/dist/src/server/routes/pipeline-outputs.js +27 -0
  131. package/dist/src/server/routes/pipeline-queue.js +62 -0
  132. package/dist/src/server/routes/pipeline-runtime.js +162 -0
  133. package/dist/src/server/routes/pipeline-scheduler.js +69 -0
  134. package/dist/src/server/routes/pipeline-workflow.js +180 -0
  135. package/dist/src/server/routes/pipelines.js +96 -0
  136. package/dist/src/server/routes/sessions.js +244 -0
  137. package/dist/src/server/routes/timeline.js +14 -0
  138. package/dist/src/server/serve-static.js +42 -0
  139. package/dist/src/server/types.js +2 -0
  140. package/dist/src/services/agent-service.js +79 -0
  141. package/dist/src/services/artifact-service.js +74 -0
  142. package/dist/src/services/gateway-read-helpers.js +10 -0
  143. package/dist/src/services/index.js +23 -0
  144. package/dist/src/services/pipeline-service.js +529 -0
  145. package/dist/src/services/pipeline-status.js +93 -0
  146. package/dist/src/services/read-services.js +60 -0
  147. package/dist/src/services/scheduler-service.js +37 -0
  148. package/dist/src/services/session-service.js +227 -0
  149. package/dist/src/services/system-service.js +26 -0
  150. package/dist/src/transport/ws-broker.js +48 -0
  151. package/dist/src/utils/array.js +17 -0
  152. package/dist/src/utils/guards.js +5 -0
  153. package/dist/src/utils/session.js +60 -0
  154. package/dist/src/version.js +5 -0
  155. package/package.json +61 -0
  156. package/web/dist/assets/index-CWnfhkn-.js +65 -0
  157. package/web/dist/assets/index-gZ0xOfSO.css +1 -0
  158. package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  159. package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  160. package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  161. package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  162. package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
  163. package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
  164. package/web/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  165. package/web/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  166. package/web/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  167. package/web/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  168. package/web/dist/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
  169. package/web/dist/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
  170. package/web/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  171. package/web/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  172. package/web/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  173. package/web/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  174. package/web/dist/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
  175. package/web/dist/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
  176. package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  177. package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  178. package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  179. package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  180. package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
  181. package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
  182. package/web/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  183. package/web/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  184. package/web/dist/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
  185. package/web/dist/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
  186. package/web/dist/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
  187. package/web/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
  188. package/web/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
  189. package/web/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
  190. package/web/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
  191. package/web/dist/assets/space-grotesk-latin-ext-400-normal-CfP_5XZW.woff2 +0 -0
  192. package/web/dist/assets/space-grotesk-latin-ext-400-normal-DRPE3kg4.woff +0 -0
  193. package/web/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
  194. package/web/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
  195. package/web/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
  196. package/web/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
  197. package/web/dist/assets/space-grotesk-vietnamese-400-normal-B7xT_GF5.woff2 +0 -0
  198. package/web/dist/assets/space-grotesk-vietnamese-400-normal-BIWiOVfw.woff +0 -0
  199. package/web/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
  200. package/web/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
  201. package/web/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
  202. package/web/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
  203. package/web/dist/favicon.svg +10 -0
  204. package/web/dist/index.html +14 -0
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSchedulerService = void 0;
4
+ const getRuntimeByPipelineId = (app, pipelineId) => app.getPipelineRuntime(pipelineId);
5
+ const ensureSchedulerPluginEnabled = (runtime, pipelineId) => {
6
+ const workflow = runtime.workflow.getWorkflow();
7
+ if (workflow.plugins.scheduler.enabled)
8
+ return { ok: true };
9
+ return { ok: false, pipelineId, error: "pipeline_plugin_disabled", plugin: "scheduler" };
10
+ };
11
+ const createSchedulerService = (app) => {
12
+ const toggleScheduler = (pipelineId, enabled) => {
13
+ const runtime = getRuntimeByPipelineId(app, pipelineId);
14
+ if (!runtime)
15
+ return { ok: false, pipelineId, error: "pipeline_not_found" };
16
+ const pluginState = ensureSchedulerPluginEnabled(runtime, pipelineId);
17
+ if (!pluginState.ok)
18
+ return pluginState;
19
+ runtime.pipeline.setSchedulerEnabled(enabled);
20
+ return { ok: true, pipelineId, scheduler: runtime.pipeline.getSchedulerState() };
21
+ };
22
+ const setSchedulerMode = (pipelineId, mode) => {
23
+ const runtime = getRuntimeByPipelineId(app, pipelineId);
24
+ if (!runtime)
25
+ return { ok: false, pipelineId, error: "pipeline_not_found" };
26
+ const pluginState = ensureSchedulerPluginEnabled(runtime, pipelineId);
27
+ if (!pluginState.ok)
28
+ return pluginState;
29
+ runtime.pipeline.setSchedulerMode(mode);
30
+ return { ok: true, pipelineId, scheduler: runtime.pipeline.getSchedulerState() };
31
+ };
32
+ return {
33
+ toggleScheduler,
34
+ setSchedulerMode,
35
+ };
36
+ };
37
+ exports.createSchedulerService = createSchedulerService;
@@ -0,0 +1,227 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSessionService = void 0;
4
+ const gateway_read_helpers_1 = require("./gateway-read-helpers");
5
+ const asRecord = (value) => value && typeof value === "object" ? value : null;
6
+ const firstText = (value) => {
7
+ if (typeof value === "string")
8
+ return value;
9
+ if (Array.isArray(value)) {
10
+ for (const item of value) {
11
+ const text = firstText(item);
12
+ if (text)
13
+ return text;
14
+ }
15
+ return "";
16
+ }
17
+ if (!value || typeof value !== "object")
18
+ return "";
19
+ const obj = value;
20
+ const direct = obj.text ?? obj.content ?? obj.value ?? obj.message;
21
+ if (typeof direct === "string")
22
+ return direct;
23
+ for (const key of ["parts", "items", "messages", "data", "result"]) {
24
+ const nested = firstText(obj[key]);
25
+ if (nested)
26
+ return nested;
27
+ }
28
+ return "";
29
+ };
30
+ const toSessionListItems = (items) => items.map((session) => ({
31
+ id: session.id,
32
+ title: session.title,
33
+ raw: session.raw,
34
+ }));
35
+ const createSessionService = (app) => {
36
+ const listSessions = async (options) => {
37
+ await (0, gateway_read_helpers_1.ensureGatewayReadyForReadonly)(app);
38
+ const shouldRefresh = options?.refresh ?? true;
39
+ if (shouldRefresh) {
40
+ try {
41
+ const refreshed = await app.gateway.refreshSessionsFromGateway();
42
+ return toSessionListItems(refreshed.items);
43
+ }
44
+ catch {
45
+ // 刷新失败时使用缓存,确保 CLI 在网关抖动时仍可读到会话信息。
46
+ }
47
+ }
48
+ return toSessionListItems(app.gateway.getSessionCache());
49
+ };
50
+ const getSessionHistory = async (sessionId) => {
51
+ await (0, gateway_read_helpers_1.ensureGatewayReadyForReadonly)(app);
52
+ const payload = await app.gateway.client.sendReq("chat.history", { sessionKey: sessionId });
53
+ const rawItems = Array.isArray(payload)
54
+ ? payload
55
+ : Array.isArray(payload?.items)
56
+ ? (payload.items ?? [])
57
+ : app.gateway.pickArray(payload);
58
+ return rawItems
59
+ .map((item) => {
60
+ const raw = asRecord(item) ?? {};
61
+ const tsCandidate = raw.ts ?? raw.createdAt ?? raw.timestamp ?? null;
62
+ return {
63
+ role: String(raw.role ?? raw.author ?? raw.type ?? "unknown"),
64
+ content: firstText(raw.content ?? raw.message ?? raw.text ?? raw),
65
+ ts: typeof tsCandidate === "string" ? tsCandidate : null,
66
+ raw,
67
+ };
68
+ });
69
+ };
70
+ const sendMessage = async (input) => {
71
+ await (0, gateway_read_helpers_1.ensureGatewayReadyForReadonly)(app);
72
+ const sessionId = input.sessionId.trim();
73
+ const message = input.message.trim();
74
+ const mode = input.mode ?? "auto";
75
+ if (!sessionId) {
76
+ throw new Error("invalid_session_id");
77
+ }
78
+ if (!message) {
79
+ throw new Error("message_required");
80
+ }
81
+ const chatAttempts = [
82
+ { method: "chat.send", params: { sessionKey: sessionId, message } },
83
+ ];
84
+ const sessionsAttempts = [
85
+ { method: "sessions.send", params: { key: sessionId, message } },
86
+ ];
87
+ const attempts = mode === "chat"
88
+ ? [...chatAttempts]
89
+ : mode === "sessions"
90
+ ? [...sessionsAttempts]
91
+ : [...chatAttempts, ...sessionsAttempts];
92
+ let lastError = null;
93
+ for (const attempt of attempts) {
94
+ try {
95
+ const payload = await app.gateway.client.sendReq(attempt.method, attempt.params, { sideEffect: true });
96
+ return {
97
+ sessionId,
98
+ mode,
99
+ method: attempt.method,
100
+ params: attempt.params,
101
+ payload,
102
+ };
103
+ }
104
+ catch (error) {
105
+ lastError = error;
106
+ }
107
+ }
108
+ throw new Error(String(lastError ?? "sessions_send_failed"));
109
+ };
110
+ const sendMessageAndWaitForReply = async (input, options) => {
111
+ const sent = await sendMessage(input);
112
+ const sessionId = input.sessionId.trim();
113
+ const timeoutMs = options?.timeoutMs ?? 120_000;
114
+ return new Promise((resolve) => {
115
+ let accumulated = "";
116
+ let emittedLength = 0;
117
+ let settled = false;
118
+ let timer = null;
119
+ const emitIncremental = (full) => {
120
+ if (full.length > emittedLength) {
121
+ const delta = full.slice(emittedLength);
122
+ emittedLength = full.length;
123
+ options?.onChunk?.(delta);
124
+ }
125
+ };
126
+ const cleanup = () => {
127
+ settled = true;
128
+ unsubscribe();
129
+ if (timer) {
130
+ clearTimeout(timer);
131
+ timer = null;
132
+ }
133
+ };
134
+ const unsubscribe = app.gateway.client.onEvent((frame) => {
135
+ if (settled)
136
+ return;
137
+ if (frame.type !== "event")
138
+ return;
139
+ if (frame.event !== "agent")
140
+ return;
141
+ const payload = (frame.payload ?? {});
142
+ const eventSessionKey = String(payload.sessionKey ?? payload.sessionId ?? payload.key ?? "").trim();
143
+ if (eventSessionKey !== sessionId)
144
+ return;
145
+ const stream = String(payload.stream ?? "").toLowerCase();
146
+ const data = (payload.data ?? {});
147
+ // 流式文本片段(累积+增量混合,用 merge 去重)
148
+ if (stream === "assistant") {
149
+ const text = typeof data.text === "string" ? data.text : "";
150
+ if (text) {
151
+ if (!accumulated) {
152
+ accumulated = text;
153
+ }
154
+ else if (text.startsWith(accumulated)) {
155
+ accumulated = text;
156
+ }
157
+ else if (!accumulated.endsWith(text)) {
158
+ accumulated += text;
159
+ }
160
+ emitIncremental(accumulated);
161
+ }
162
+ return;
163
+ }
164
+ // 兼容非 stream 前缀的直接文本
165
+ const role = String(payload.role ?? data.role ?? "").toLowerCase();
166
+ if (role === "assistant") {
167
+ const text = typeof data.text === "string" ? data.text : "";
168
+ if (text) {
169
+ if (!accumulated) {
170
+ accumulated = text;
171
+ }
172
+ else if (text.startsWith(accumulated)) {
173
+ accumulated = text;
174
+ }
175
+ else if (!accumulated.endsWith(text)) {
176
+ accumulated += text;
177
+ }
178
+ emitIncremental(accumulated);
179
+ }
180
+ }
181
+ // 生命周期结束
182
+ if (stream === "lifecycle") {
183
+ const phase = String(data.phase ?? "").toLowerCase();
184
+ if (phase === "end" || phase === "done") {
185
+ cleanup();
186
+ resolve({
187
+ sent,
188
+ reply: accumulated.trim()
189
+ ? { role: "assistant", content: accumulated.trim(), ts: new Date().toISOString() }
190
+ : null,
191
+ });
192
+ }
193
+ }
194
+ });
195
+ // 超时兜底
196
+ timer = setTimeout(() => {
197
+ if (settled)
198
+ return;
199
+ cleanup();
200
+ // 超时时尝试从 history 补一次
201
+ void getSessionHistory(sessionId).then((history) => {
202
+ const items = Array.isArray(history) ? history : [];
203
+ const lastAssistant = [...items].reverse().find((item) => {
204
+ const r = String(item.role ?? "").toLowerCase();
205
+ return r === "assistant" || r === "bot";
206
+ });
207
+ const content = lastAssistant
208
+ ? String(lastAssistant.content ?? "")
209
+ : accumulated.trim();
210
+ resolve({
211
+ sent,
212
+ reply: content ? { role: "assistant", content, ts: null } : null,
213
+ });
214
+ }).catch(() => {
215
+ resolve({ sent, reply: accumulated.trim() ? { role: "assistant", content: accumulated.trim(), ts: null } : null });
216
+ });
217
+ }, timeoutMs);
218
+ });
219
+ };
220
+ return {
221
+ listSessions,
222
+ getSessionHistory,
223
+ sendMessage,
224
+ sendMessageAndWaitForReply,
225
+ };
226
+ };
227
+ exports.createSessionService = createSessionService;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSystemService = void 0;
4
+ const createSystemService = (app) => {
5
+ const getSnapshot = () => {
6
+ // 复用 registry 的 bootstrap 聚合结果,保证 CLI 与现有前端看到的是同一份系统快照。
7
+ const bootstrap = app.getBootstrapPayload();
8
+ return {
9
+ generatedAt: new Date().toISOString(),
10
+ gateway: {
11
+ status: app.gateway.getLatestStatus() ?? app.gateway.client.getStatus(),
12
+ hello: app.gateway.getLatestHello(),
13
+ lastFrame: app.gateway.getLastFrame(),
14
+ },
15
+ pipelines: app.listPipelines().map((definition) => ({
16
+ id: definition.id,
17
+ title: definition.title,
18
+ })),
19
+ bootstrap,
20
+ };
21
+ };
22
+ return {
23
+ getSnapshot,
24
+ };
25
+ };
26
+ exports.createSystemService = createSystemService;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWsBroker = void 0;
4
+ const ws_1 = require("ws");
5
+ const createWsBroker = (options) => {
6
+ const wsServer = new ws_1.WebSocketServer({
7
+ server: options.server,
8
+ path: options.path ?? "/api/ws",
9
+ maxPayload: 8 * 1024 * 1024,
10
+ });
11
+ const peers = new Set();
12
+ const broadcast = (payload) => {
13
+ const event = payload;
14
+ const type = event?.type ?? "";
15
+ const isHighFrequency = type === "gateway.frame" || type === "timeline.updated";
16
+ const message = JSON.stringify(payload);
17
+ for (const peer of peers) {
18
+ if (peer.readyState !== 1)
19
+ continue;
20
+ // 慢消费者保护:高频消息在 buffer 堆积时跳过,避免 Node 进程 OOM
21
+ if (isHighFrequency && peer.bufferedAmount > 64 * 1024)
22
+ continue;
23
+ peer.send(message);
24
+ }
25
+ };
26
+ wsServer.on("connection", (socket) => {
27
+ peers.add(socket);
28
+ socket.send(JSON.stringify({ type: "bootstrap", payload: options.getBootstrapPayload() }));
29
+ socket.on("close", () => {
30
+ peers.delete(socket);
31
+ });
32
+ });
33
+ return {
34
+ broadcast,
35
+ close: () => {
36
+ for (const peer of peers) {
37
+ try {
38
+ peer.close();
39
+ }
40
+ catch {
41
+ // Ignore close failures on shutdown.
42
+ }
43
+ }
44
+ wsServer.close();
45
+ },
46
+ };
47
+ };
48
+ exports.createWsBroker = createWsBroker;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pickArray = void 0;
4
+ const pickArray = (value) => {
5
+ if (Array.isArray(value))
6
+ return value;
7
+ if (!value || typeof value !== "object")
8
+ return [];
9
+ const obj = value;
10
+ const candidates = [obj.items, obj.agents, obj.sessions, obj.list, obj.data, obj.results];
11
+ for (const candidate of candidates) {
12
+ if (Array.isArray(candidate))
13
+ return candidate;
14
+ }
15
+ return [];
16
+ };
17
+ exports.pickArray = pickArray;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRecord = void 0;
4
+ const isRecord = (value) => typeof value === "object" && value !== null;
5
+ exports.isRecord = isRecord;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inferSessionAgentIds = exports.parseAgentSessionMapFromEnv = exports.normalizeSession = void 0;
4
+ const guards_1 = require("./guards");
5
+ const normalizeSession = (value, _index) => {
6
+ const obj = (value ?? {});
7
+ const id = String(obj.sessionKey ??
8
+ obj.key ??
9
+ obj.sessionId ??
10
+ obj.id ??
11
+ obj.uuid ??
12
+ "").trim();
13
+ if (!id) {
14
+ return null;
15
+ }
16
+ const title = String(obj.title ?? obj.name ?? obj.label ?? id);
17
+ return { id, title, raw: obj };
18
+ };
19
+ exports.normalizeSession = normalizeSession;
20
+ const parseAgentSessionMapFromEnv = () => {
21
+ const raw = process.env.OPENCLAW_AGENT_SESSION_MAP;
22
+ if (!raw)
23
+ return {};
24
+ try {
25
+ const parsed = JSON.parse(raw);
26
+ if (!(0, guards_1.isRecord)(parsed))
27
+ return {};
28
+ const output = {};
29
+ for (const [k, v] of Object.entries(parsed)) {
30
+ if (typeof k === "string" && typeof v === "string" && k.trim() && v.trim()) {
31
+ output[k.trim()] = v.trim();
32
+ }
33
+ }
34
+ return output;
35
+ }
36
+ catch {
37
+ return {};
38
+ }
39
+ };
40
+ exports.parseAgentSessionMapFromEnv = parseAgentSessionMapFromEnv;
41
+ const inferSessionAgentIds = (session, knownAgentIds) => {
42
+ const candidates = new Set();
43
+ const raw = session.raw;
44
+ const fields = [raw.agentId, raw.agent_id, raw.executorAgentId, raw.ownerAgentId];
45
+ for (const f of fields) {
46
+ if (typeof f === "string" && f.trim())
47
+ candidates.add(f.trim());
48
+ }
49
+ if (knownAgentIds.has(session.id))
50
+ candidates.add(session.id);
51
+ const bag = `${session.id} ${session.title}`.toLowerCase();
52
+ for (const agentId of knownAgentIds) {
53
+ const needle = agentId.toLowerCase();
54
+ if (bag.includes(needle)) {
55
+ candidates.add(agentId);
56
+ }
57
+ }
58
+ return [...candidates];
59
+ };
60
+ exports.inferSessionAgentIds = inferSessionAgentIds;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APP_VERSION = void 0;
4
+ // 由 scripts/gen-version.ts 自动生成,请勿手动编辑
5
+ exports.APP_VERSION = "0.1.1";
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "taskmeld",
4
+ "version": "0.1.1",
5
+ "description": "Agent pipeline orchestration platform — CLI, HTTP/WS backend, React console",
6
+ "main": "dist/src/index.js",
7
+ "bin": {
8
+ "taskmeld": "dist/src/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist/src",
12
+ "web/dist"
13
+ ],
14
+ "directories": {
15
+ "doc": "docs"
16
+ },
17
+ "scripts": {
18
+ "test": "npm run build && node dist/test/artifact-storage.spec.js && node dist/test/data-dir.spec.js && node dist/test/gateway-client.spec.js && node dist/test/gateway-frame-sanitizer.spec.js && node dist/test/workflow-v2.spec.js && node dist/test/structured-output-contract.spec.js && node dist/test/structured-output-parser.spec.js && node dist/test/run-log-reader.spec.js && node dist/test/runtime-store-timeline-sanitize.spec.js && node dist/test/pipeline-regression.spec.js && node dist/test/pipeline-management.spec.js && node dist/test/pipeline-status-semantics.spec.js && node dist/test/pipeline-routing.spec.js && node dist/test/pipeline-branch-isolation.spec.js && node dist/test/pipeline-diagnostics.spec.js && node dist/test/pipeline-join-policy.spec.js && node dist/test/pipeline-module-boundaries.spec.js && node dist/test/server-lifecycle-client.spec.js && node dist/test/taskmeld-cli.spec.js && node dist/test/taskmeld-cli-error-contract.spec.js && node dist/test/server/router.spec.js && node dist/test/server/middleware.spec.js && node dist/test/server/routes-health.spec.js && node dist/test/server/api-handler-contract.spec.js",
19
+ "dev": "tsx src/index.ts",
20
+ "dev:cli": "tsx src/cli/index.ts",
21
+ "prebuild": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
22
+ "build": "tsx scripts/gen-version.ts && tsc -p tsconfig.json",
23
+ "typecheck": "tsc --noEmit",
24
+ "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
25
+ "test:watch": "npm run test",
26
+ "start": "node dist/src/index.js",
27
+ "cli": "node dist/src/cli/index.js",
28
+ "dev:web": "npm --prefix web run dev",
29
+ "build:web": "npm --prefix web run build",
30
+ "prepublishOnly": "npm run build && npm run build:web"
31
+ },
32
+ "keywords": ["agent", "pipeline", "orchestration", "openclaw", "workflow", "cli"],
33
+ "author": "liaocclucky <1796301524@qq.com>",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/CCLucky-uu/TaskMeld.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/CCLucky-uu/TaskMeld/issues"
41
+ },
42
+ "homepage": "https://taskmeld.com",
43
+ "engines": {
44
+ "node": ">=18"
45
+ },
46
+ "type": "commonjs",
47
+ "dependencies": {
48
+ "dotenv": "^17.4.1",
49
+ "ws": "^8.20.0"
50
+ },
51
+ "devDependencies": {
52
+ "@typescript-eslint/eslint-plugin": "^8.46.1",
53
+ "@typescript-eslint/parser": "^8.46.1",
54
+ "@types/node": "^25.6.0",
55
+ "@types/ws": "^8.18.1",
56
+ "eslint": "^9.37.0",
57
+ "tsx": "^4.21.0",
58
+ "typescript": "^6.0.2",
59
+ "vitest": "^4.1.4"
60
+ }
61
+ }