@ai-setting/roy-agent-core 1.6.12 → 1.6.14

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 (40) hide show
  1. package/dist/env/agent/index.js +3 -3
  2. package/dist/env/event-source/index.js +7 -5
  3. package/dist/env/index.js +19 -19
  4. package/dist/env/prompt/index.js +2 -2
  5. package/dist/env/task/delegate/index.js +4 -4
  6. package/dist/env/task/index.js +5 -5
  7. package/dist/env/task/plugins/index.js +6 -4
  8. package/dist/env/tool/built-in/index.js +2 -2
  9. package/dist/env/tool/index.js +3 -3
  10. package/dist/env/workflow/engine/index.js +5 -5
  11. package/dist/env/workflow/index.js +12 -10
  12. package/dist/env/workflow/service/index.js +1 -1
  13. package/dist/env/workflow/tools/index.js +5 -4
  14. package/dist/env/workflow/types/index.js +3 -1
  15. package/dist/env/workflow/utils/index.js +4 -4
  16. package/dist/index.js +132 -21
  17. package/dist/shared/@ai-setting/{roy-agent-core-jenchn33.js → roy-agent-core-24rmf17n.js} +8 -0
  18. package/dist/shared/@ai-setting/{roy-agent-core-z7f8hyv7.js → roy-agent-core-6jqpdjr4.js} +1 -1
  19. package/dist/shared/@ai-setting/{roy-agent-core-cxdnzn17.js → roy-agent-core-6qbyfzsw.js} +1 -1
  20. package/dist/shared/@ai-setting/{roy-agent-core-8wd3qwx5.js → roy-agent-core-80e4a3g5.js} +1 -1
  21. package/dist/shared/@ai-setting/{roy-agent-core-ms5dp89r.js → roy-agent-core-apz6v22z.js} +81 -40
  22. package/dist/shared/@ai-setting/{roy-agent-core-1bvv6s75.js → roy-agent-core-fvkyv5j6.js} +2 -2
  23. package/dist/shared/@ai-setting/{roy-agent-core-dntkpwqq.js → roy-agent-core-fwxqevpf.js} +4 -1
  24. package/dist/shared/@ai-setting/{roy-agent-core-qnrf2aw6.js → roy-agent-core-jrj30vq3.js} +33 -2
  25. package/dist/shared/@ai-setting/{roy-agent-core-q7rt3x8d.js → roy-agent-core-m0cnmg7b.js} +2 -2
  26. package/dist/shared/@ai-setting/roy-agent-core-mmb9484f.js +458 -0
  27. package/dist/shared/@ai-setting/{roy-agent-core-0n2a8cbn.js → roy-agent-core-nhncpbzz.js} +602 -245
  28. package/dist/shared/@ai-setting/{roy-agent-core-pzeexnhf.js → roy-agent-core-nv4yfy3m.js} +4 -3
  29. package/dist/shared/@ai-setting/{roy-agent-core-w22tzjj5.js → roy-agent-core-psfkwe4g.js} +93 -14
  30. package/dist/shared/@ai-setting/{roy-agent-core-q2bw3cwd.js → roy-agent-core-px8ghk4g.js} +1 -1
  31. package/dist/shared/@ai-setting/{roy-agent-core-mb7b62sm.js → roy-agent-core-r53regz9.js} +2 -2
  32. package/dist/shared/@ai-setting/{roy-agent-core-06574wqa.js → roy-agent-core-ra4y7e4p.js} +4 -4
  33. package/dist/shared/@ai-setting/{roy-agent-core-asp5p3zx.js → roy-agent-core-st9y9z07.js} +1 -1
  34. package/dist/shared/@ai-setting/{roy-agent-core-3bdpnmtg.js → roy-agent-core-v5nknfh0.js} +1 -8
  35. package/dist/shared/@ai-setting/{roy-agent-core-7a3gf3tw.js → roy-agent-core-wpw37qqf.js} +88 -3
  36. package/dist/shared/@ai-setting/{roy-agent-core-p6x6n3k4.js → roy-agent-core-x7fgze6s.js} +1 -1
  37. package/dist/shared/@ai-setting/{roy-agent-core-p2vpsd1d.js → roy-agent-core-ywtmc0bh.js} +166 -6
  38. package/package.json +1 -1
  39. package/dist/shared/@ai-setting/roy-agent-core-4yq23m5g.js +0 -421
  40. /package/dist/shared/@ai-setting/{roy-agent-core-zs31w092.js → roy-agent-core-9nhwdq9r.js} +0 -0
@@ -173,12 +173,13 @@ class ProcessRegistry {
173
173
  try {
174
174
  const result = await killProcessTree(pid, { retry: 3, retryDelayMs: 500 });
175
175
  if (result.stillAlive) {
176
- logger2.error(`进程 PID ${pid} 经过 ${result.attempts} 次重试后仍未杀死!可能存在孤儿进程泄漏!`);
176
+ logger2.error(`进程 PID ${pid} 经过 ${result.attempts} 次重试后仍未杀死!保留 PID 供后续 forceStopAll 重试。`);
177
+ } else {
178
+ this.pids.delete(pid);
177
179
  }
178
180
  } catch {}
179
181
  }
180
- this.pids.clear();
181
- logger2.info(`[bg-process:killAll-done]`);
182
+ logger2.info(`[bg-process:killAll-done] remaining=${this.pids.size}`);
182
183
  }
183
184
  }
184
185
  var processRegistryStorage = new AsyncLocalStorage;
@@ -7,7 +7,7 @@ import {
7
7
  nodeNotFound,
8
8
  pathNotFound,
9
9
  unresolvedVariable
10
- } from "./roy-agent-core-qnrf2aw6.js";
10
+ } from "./roy-agent-core-jrj30vq3.js";
11
11
  import {
12
12
  TracedAs,
13
13
  init_decorator
@@ -81,25 +81,104 @@ var init_template_resolver = __esm(() => {
81
81
  const value = this.resolveTemplateContent(templateContent);
82
82
  return value;
83
83
  }
84
- resolveTemplateContent(templateContent) {
85
- const trimmed = templateContent.trim();
86
- if (trimmed.startsWith("input.")) {
87
- return this.getNestedValue(this.input, trimmed.slice(6));
84
+ resolvePath(path) {
85
+ if (typeof path !== "string")
86
+ return;
87
+ const trimmed = path.trim();
88
+ if (trimmed === "")
89
+ return;
90
+ let inner = trimmed;
91
+ if (inner.startsWith("{{") && inner.endsWith("}}")) {
92
+ inner = inner.slice(2, -2).trim();
88
93
  }
89
- if (trimmed.startsWith("inputs.")) {
90
- return this.getNestedValue(this.input, trimmed.slice(7));
94
+ if (inner === "")
95
+ return;
96
+ return this.resolveTemplateContent(inner);
97
+ }
98
+ tokenizePath(path) {
99
+ const tokens = [];
100
+ const re = /([^.\[\]]+)|\[(-?\d+)\]/g;
101
+ let m;
102
+ while ((m = re.exec(path)) !== null) {
103
+ if (m[1] !== undefined) {
104
+ tokens.push(m[1]);
105
+ } else if (m[2] !== undefined) {
106
+ tokens.push(parseInt(m[2], 10));
107
+ }
91
108
  }
92
- if (trimmed.startsWith("nodes.")) {
93
- return this.resolveNodePath(trimmed.slice(6));
109
+ return tokens;
110
+ }
111
+ navigateTokens(root, tokens) {
112
+ let current = root;
113
+ for (const token of tokens) {
114
+ if (current === null || current === undefined)
115
+ return;
116
+ if (typeof token === "number") {
117
+ if (!Array.isArray(current))
118
+ return;
119
+ const idx = token < 0 ? current.length + token : token;
120
+ if (idx < 0 || idx >= current.length)
121
+ return;
122
+ current = current[idx];
123
+ } else {
124
+ if (typeof current !== "object")
125
+ return;
126
+ current = current[token];
127
+ }
128
+ }
129
+ return current;
130
+ }
131
+ resolveTemplateContent(templateContent) {
132
+ const trimmed = templateContent.trim();
133
+ const tokens = this.tokenizePath(trimmed);
134
+ if (tokens.length === 0)
135
+ return;
136
+ const head = tokens[0];
137
+ if (head === "input" || head === "inputs") {
138
+ const rest = tokens.slice(1);
139
+ if (rest.length === 0)
140
+ return this.input;
141
+ return this.navigateTokens(this.input, rest);
142
+ }
143
+ if (head === "nodes") {
144
+ const rest = tokens.slice(1);
145
+ if (rest.length === 0)
146
+ return;
147
+ const nodeId = rest[0];
148
+ if (typeof nodeId !== "string")
149
+ return;
150
+ const nodeValue = getFromMapWithNormalization(this.previousOutputs, nodeId);
151
+ if (nodeValue === undefined)
152
+ return;
153
+ const pathTokens = rest.slice(1);
154
+ if (pathTokens.length === 0)
155
+ return this.unwrapAgentNodeResult(nodeValue);
156
+ if (pathTokens[0] === "output") {
157
+ if (pathTokens.length === 1) {
158
+ return this.unwrapAgentNodeResult(nodeValue);
159
+ }
160
+ return this.navigateTokens(nodeValue, pathTokens.slice(1));
161
+ }
162
+ return this.navigateTokens(nodeValue, pathTokens);
94
163
  }
95
- if (trimmed !== "input" && trimmed !== "inputs" && trimmed !== "nodes") {
96
- const segments = trimmed.split(".");
97
- const nodeId = segments[0];
98
- const restPath = segments.slice(1).join(".") || undefined;
99
- return this.resolveNodePath(`${nodeId}${restPath ? "." + restPath : ""}`);
164
+ if (typeof head === "string" && head !== "nodes") {
165
+ const nodeId = head;
166
+ const nodeValue = getFromMapWithNormalization(this.previousOutputs, nodeId);
167
+ if (nodeValue === undefined)
168
+ return;
169
+ const pathTokens = tokens.slice(1);
170
+ if (pathTokens.length === 0)
171
+ return this.unwrapAgentNodeResult(nodeValue);
172
+ return this.navigateTokens(nodeValue, pathTokens);
100
173
  }
101
174
  return;
102
175
  }
176
+ unwrapAgentNodeResult(value) {
177
+ if (value && typeof value === "object" && "result" in value && !("nodes" in value)) {
178
+ return value.result;
179
+ }
180
+ return value;
181
+ }
103
182
  resolveString(template) {
104
183
  if (!template || typeof template !== "string") {
105
184
  return template;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  TaskTagPlugin,
3
3
  createLarkCliTaskNotifyHook
4
- } from "./roy-agent-core-q7rt3x8d.js";
4
+ } from "./roy-agent-core-m0cnmg7b.js";
5
5
  import {
6
6
  envKeyToConfigKey
7
7
  } from "./roy-agent-core-7hh0brvs.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  TAG_MAX_COUNT,
3
3
  TAG_MIN_COUNT
4
- } from "./roy-agent-core-p2vpsd1d.js";
4
+ } from "./roy-agent-core-ywtmc0bh.js";
5
5
  import {
6
6
  validateWorkflowDefinition
7
- } from "./roy-agent-core-8wd3qwx5.js";
7
+ } from "./roy-agent-core-80e4a3g5.js";
8
8
  import {
9
9
  AskUserError,
10
10
  init_workflow_hil
@@ -6,7 +6,7 @@ import {
6
6
  WorkflowEngine,
7
7
  exports_engine,
8
8
  init_engine
9
- } from "./roy-agent-core-0n2a8cbn.js";
9
+ } from "./roy-agent-core-nhncpbzz.js";
10
10
  import {
11
11
  askUserTool,
12
12
  createRunWorkflowTool,
@@ -18,10 +18,10 @@ import {
18
18
  createWorkflowSearchTool,
19
19
  createWorkflowTagListTool,
20
20
  createWorkflowValidateTool
21
- } from "./roy-agent-core-mb7b62sm.js";
21
+ } from "./roy-agent-core-r53regz9.js";
22
22
  import {
23
23
  WorkflowService
24
- } from "./roy-agent-core-p2vpsd1d.js";
24
+ } from "./roy-agent-core-ywtmc0bh.js";
25
25
  import {
26
26
  BaseComponent
27
27
  } from "./roy-agent-core-j62bjagf.js";
@@ -141,7 +141,7 @@ class WorkflowComponent extends BaseComponent {
141
141
  if (!agentRunner && this._workflowEnv) {
142
142
  const agentComponent = this._workflowEnv.getComponent("agent");
143
143
  if (agentComponent) {
144
- const { AgentComponentAdapter } = await import("./roy-agent-core-z7f8hyv7.js");
144
+ const { AgentComponentAdapter } = await import("./roy-agent-core-6jqpdjr4.js");
145
145
  agentRunner = new AgentComponentAdapter(agentComponent, {}, this.sessionComponent);
146
146
  }
147
147
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createAutoTaskPlugin
3
- } from "./roy-agent-core-q7rt3x8d.js";
3
+ } from "./roy-agent-core-m0cnmg7b.js";
4
4
  import {
5
5
  ContextError,
6
6
  ErrorCodes
@@ -165,15 +165,8 @@ class AgentRegistry {
165
165
  const agent = {
166
166
  name,
167
167
  type: "sub",
168
- description: "Workflow runner — 负责调用 workflow_run 启动 workflow,支持 session resume 和 stop",
168
+ description: "Workflow runner — 负责调用 workflow_run 启动 workflow,支持 session resume 和 stop;失败接管由 prompt 推理触发 (Task #2251 简化版)。",
169
169
  systemPromptRef: "workflow-runner",
170
- allowedTools: [
171
- "workflow_get",
172
- "workflow_list",
173
- "workflow_run",
174
- "workflow_run_status",
175
- "workflow_run_stop"
176
- ],
177
170
  deniedTools: ["delegate_task", "stop_task"],
178
171
  maxIterations: 30
179
172
  };
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  ProcessRegistry,
3
3
  runWithProcessRegistryAsync
4
- } from "./roy-agent-core-pzeexnhf.js";
4
+ } from "./roy-agent-core-nv4yfy3m.js";
5
5
  import {
6
6
  builtInPrompts
7
- } from "./roy-agent-core-ms5dp89r.js";
7
+ } from "./roy-agent-core-apz6v22z.js";
8
8
  import {
9
9
  runWithBgTaskIdAsync
10
10
  } from "./roy-agent-core-c1v263jn.js";
11
11
  import {
12
12
  DEFAULT_SUBAGENT_PROMPT
13
- } from "./roy-agent-core-3bdpnmtg.js";
13
+ } from "./roy-agent-core-v5nknfh0.js";
14
14
  import {
15
15
  TaskHookPoints
16
16
  } from "./roy-agent-core-1pg0fepg.js";
@@ -808,6 +808,77 @@ Use these as guidance to improve task execution efficiency.`;
808
808
  listTasks() {
809
809
  return Array.from(this.tasks.values());
810
810
  }
811
+ hasActiveTaskForParent(parentSessionId) {
812
+ if (!parentSessionId)
813
+ return false;
814
+ for (const task of this.tasks.values()) {
815
+ if (task.parentSessionId === parentSessionId && (task.status === "pending" || task.status === "running")) {
816
+ return true;
817
+ }
818
+ }
819
+ return false;
820
+ }
821
+ async stopAllForParent(parentSessionId) {
822
+ if (!parentSessionId) {
823
+ return { stoppedTaskIds: [] };
824
+ }
825
+ const stoppedTaskIds = [];
826
+ for (const [taskId, task] of this.tasks) {
827
+ if (task.parentSessionId === parentSessionId && (task.status === "running" || task.status === "pending")) {
828
+ try {
829
+ const res = await this.stopTask(taskId);
830
+ if (res?.success) {
831
+ stoppedTaskIds.push(taskId);
832
+ }
833
+ } catch (err) {
834
+ logger.warn(`[BackgroundTaskManager] stopAllForParent failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`);
835
+ }
836
+ }
837
+ }
838
+ return { stoppedTaskIds };
839
+ }
840
+ async forceStopAllAcrossParents() {
841
+ for (const [taskId, task] of this.tasks) {
842
+ try {
843
+ await this.processRegistries.get(taskId)?.killAll();
844
+ } catch (err) {
845
+ logger.warn(`[BackgroundTaskManager] forceStopAllAcrossParents killAll failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`);
846
+ }
847
+ try {
848
+ await this.propagateStopToWorkflowRuns(taskId, "force stop all");
849
+ } catch (err) {
850
+ logger.warn(`[BackgroundTaskManager] forceStopAllAcrossParents propagateStopToWorkflowRuns failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`);
851
+ }
852
+ let justMarkedStopped = false;
853
+ if (task.status === "running" || task.status === "pending") {
854
+ try {
855
+ task.status = "stopped";
856
+ task.completedAt = Date.now();
857
+ task.lastUpdatedAt = task.completedAt;
858
+ task.abortController?.abort();
859
+ justMarkedStopped = true;
860
+ } catch (err) {
861
+ logger.warn(`[BackgroundTaskManager] forceStopAllAcrossParents mark stopped failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`);
862
+ }
863
+ }
864
+ if (justMarkedStopped) {
865
+ const stoppedPayload = {
866
+ backgroundTaskId: task.id,
867
+ subSessionId: task.subSessionId,
868
+ parentSessionId: task.parentSessionId,
869
+ status: "stopped",
870
+ description: task.description,
871
+ error: "force stop all",
872
+ executionTimeMs: task.startedAt && task.completedAt ? task.completedAt - task.startedAt : 0,
873
+ associatedTaskId: task.associatedTaskId
874
+ };
875
+ this.publishBackgroundEvent(BackgroundTaskEventTypes.STOPPED, stoppedPayload, task.parentSessionId);
876
+ }
877
+ }
878
+ }
879
+ async forceStopAll() {
880
+ return this.forceStopAllAcrossParents();
881
+ }
811
882
  async dispose() {
812
883
  for (const [taskId, controller] of this.abortControllers) {
813
884
  controller.abort();
@@ -878,6 +949,20 @@ __legacyDecorateClassTS([
878
949
  __legacyDecorateClassTS([
879
950
  TracedAs("delegate.executeWithAbort", { recordParams: true, recordResult: true, log: true })
880
951
  ], BackgroundTaskManager.prototype, "executeWithAbort", null);
952
+ __legacyDecorateClassTS([
953
+ TracedAs("task.background.stopAllForParent", {
954
+ recordParams: true,
955
+ recordResult: true,
956
+ log: true
957
+ })
958
+ ], BackgroundTaskManager.prototype, "stopAllForParent", null);
959
+ __legacyDecorateClassTS([
960
+ TracedAs("task.background.forceStopAllAcrossParents", {
961
+ recordParams: false,
962
+ recordResult: true,
963
+ log: true
964
+ })
965
+ ], BackgroundTaskManager.prototype, "forceStopAllAcrossParents", null);
881
966
  function getAgentRegistry(taskComponent) {
882
967
  const agentComponent = taskComponent.env?.getComponent?.("agent");
883
968
  return agentComponent?.getRegistry?.();
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  getCurrentProcessRegistry,
9
9
  killProcessTree
10
- } from "./roy-agent-core-pzeexnhf.js";
10
+ } from "./roy-agent-core-nv4yfy3m.js";
11
11
  import {
12
12
  init_decorator,
13
13
  wrapFunction
@@ -2,12 +2,18 @@ import {
2
2
  TracedAs,
3
3
  init_decorator
4
4
  } from "./roy-agent-core-fdm579b1.js";
5
+ import {
6
+ createLogger,
7
+ init_logger
8
+ } from "./roy-agent-core-vyygk314.js";
5
9
  import {
6
10
  __legacyDecorateClassTS
7
11
  } from "./roy-agent-core-fs0mn2jk.js";
8
12
 
9
13
  // src/env/workflow/service/workflow-service.ts
14
+ init_logger();
10
15
  init_decorator();
16
+ var logger = createLogger("WorkflowService");
11
17
  var TAG_MIN_COUNT = 1;
12
18
  var TAG_MAX_COUNT = 3;
13
19
  class TagValidationError extends Error {
@@ -27,7 +33,27 @@ class WorkflowService {
27
33
  this.engineFactory = engineFactory;
28
34
  this.sessionComponent = sessionComponent;
29
35
  this.tagRepository = tagRepository;
36
+ this.engineInstances = new Map;
37
+ }
38
+ async listAllSessions() {
39
+ if (!this.sessionComponent?.list)
40
+ return [];
41
+ const PAGE = 1000;
42
+ const HARD_CAP = 50000;
43
+ const collected = [];
44
+ let offset = 0;
45
+ while (collected.length < HARD_CAP) {
46
+ const batch = await this.sessionComponent.list({ limit: PAGE, offset });
47
+ collected.push(...batch);
48
+ if (batch.length < PAGE)
49
+ break;
50
+ offset += PAGE;
51
+ }
52
+ return collected;
30
53
  }
54
+ engineInstances;
55
+ sessionToEngine = new Map;
56
+ sessionToParent = new Map;
31
57
  validateTags(tags) {
32
58
  const effective = tags ?? [];
33
59
  if (effective.length < TAG_MIN_COUNT) {
@@ -233,14 +259,24 @@ class WorkflowService {
233
259
  };
234
260
  }
235
261
  }
236
- const engine = this.engineFactory(workflow, {
237
- ...options,
238
- input
239
- });
262
+ let engine = this.engineInstances.get(workflow.name);
263
+ if (!engine) {
264
+ engine = this.engineFactory(workflow, {
265
+ ...options,
266
+ input
267
+ });
268
+ this.engineInstances.set(workflow.name, engine);
269
+ }
240
270
  const result = await engine.runWorkflow(workflow, {
241
271
  ...options,
242
272
  input
243
273
  });
274
+ const resolvedSessionId = result.sessionId || result.runId;
275
+ if (resolvedSessionId) {
276
+ this.sessionToEngine.set(resolvedSessionId, engine);
277
+ const parentSid = options?.parentSessionId;
278
+ this.sessionToParent.set(resolvedSessionId, typeof parentSid === "string" ? parentSid : undefined);
279
+ }
244
280
  return {
245
281
  ...result,
246
282
  runId: result.runId || result.sessionId || "",
@@ -267,8 +303,111 @@ class WorkflowService {
267
303
  if (!workflow) {
268
304
  throw new Error(`Workflow not found: ${metadata.workflowName}`);
269
305
  }
270
- const engine = this.engineFactory(workflow);
271
- await engine.stop(sessionId, reason);
306
+ const cachedBySession = this.sessionToEngine.get(sessionId);
307
+ const cachedByName = this.engineInstances.get(metadata.workflowName);
308
+ const engine = cachedBySession ?? cachedByName ?? this.engineFactory(workflow);
309
+ try {
310
+ await engine.stop(sessionId, reason);
311
+ } finally {
312
+ this.sessionToEngine.delete(sessionId);
313
+ this.sessionToParent.delete(sessionId);
314
+ this.pruneStaleEngines();
315
+ }
316
+ }
317
+ pruneStaleEngines() {
318
+ for (const [workflowName, engine] of this.engineInstances) {
319
+ if (!engine?.activeSessions || engine.activeSessions.size === 0) {
320
+ this.engineInstances.delete(workflowName);
321
+ }
322
+ }
323
+ }
324
+ async dispose() {
325
+ for (const [, engine] of this.engineInstances) {
326
+ if (engine?.activeSessions) {
327
+ for (const sessionId of engine.activeSessions.keys()) {
328
+ try {
329
+ await engine.stop(sessionId, "WorkflowService disposed");
330
+ } catch {}
331
+ }
332
+ }
333
+ }
334
+ this.engineInstances.clear();
335
+ this.sessionToEngine.clear();
336
+ }
337
+ hasActiveWorkflowForParent(parentSessionId) {
338
+ if (!parentSessionId)
339
+ return false;
340
+ for (const [sessionId, recordedParent] of this.sessionToParent) {
341
+ if (recordedParent === undefined)
342
+ continue;
343
+ if (recordedParent === parentSessionId) {
344
+ const engine = this.sessionToEngine.get(sessionId);
345
+ const active = engine?.activeSessions;
346
+ if (active && active.has(sessionId))
347
+ return true;
348
+ }
349
+ }
350
+ return false;
351
+ }
352
+ async stopAllForParent(parentSessionId) {
353
+ if (!parentSessionId || !this.sessionComponent?.list) {
354
+ return { stoppedSessionIds: [], errors: [] };
355
+ }
356
+ const allSessions = await this.listAllSessions();
357
+ const stoppedSessionIds = [];
358
+ const errors = [];
359
+ for (const session of allSessions) {
360
+ const meta = session.metadata;
361
+ if (session.parentSessionId === parentSessionId && meta?.type === "workflow" && (meta?.status === "running" || meta?.status === "paused")) {
362
+ try {
363
+ await this.stopRun(session.id, "ESC cascade stop");
364
+ stoppedSessionIds.push(session.id);
365
+ } catch (err) {
366
+ const errorMsg = err instanceof Error ? err.message : String(err);
367
+ const stack = err instanceof Error ? err.stack : undefined;
368
+ logger.warn(`[WorkflowService] stopAllForParent failed for ${session.id}: ${errorMsg}`);
369
+ errors.push({ sessionId: session.id, error: errorMsg, stack });
370
+ }
371
+ }
372
+ }
373
+ return { stoppedSessionIds, errors };
374
+ }
375
+ async forceStopAll() {
376
+ if (!this.sessionComponent?.list || !this.sessionComponent.update) {
377
+ return;
378
+ }
379
+ const allSessions = await this.listAllSessions();
380
+ const evictedSessionIds = [];
381
+ for (const session of allSessions) {
382
+ const meta = session.metadata;
383
+ if (meta?.type === "workflow" && (meta?.status === "running" || meta?.status === "paused")) {
384
+ const cachedEngine = this.sessionToEngine.get(session.id);
385
+ if (cachedEngine && typeof cachedEngine.stop === "function") {
386
+ try {
387
+ await cachedEngine.stop(session.id, "force stop all");
388
+ } catch (err) {
389
+ logger.warn(`[WorkflowService] forceStopAll engine.stop failed for ${session.id}: ${err instanceof Error ? err.message : String(err)}`);
390
+ }
391
+ }
392
+ try {
393
+ await this.sessionComponent.update(session.id, {
394
+ metadata: { ...meta, status: "stopped" }
395
+ });
396
+ evictedSessionIds.push(session.id);
397
+ } catch (err) {
398
+ logger.warn(`[WorkflowService] forceStopAll update failed for ${session.id}: ${err instanceof Error ? err.message : String(err)}`);
399
+ }
400
+ }
401
+ }
402
+ for (const sid of evictedSessionIds) {
403
+ const engine = this.sessionToEngine.get(sid);
404
+ if (engine?.activeSessions) {
405
+ engine.activeSessions.delete(sid);
406
+ }
407
+ this.sessionToEngine.delete(sid);
408
+ this.sessionToParent.delete(sid);
409
+ }
410
+ this.pruneStaleEngines();
272
411
  }
273
412
  async resumeSession(sessionId, options) {
274
413
  if (!this.sessionComponent) {
@@ -364,6 +503,27 @@ __legacyDecorateClassTS([
364
503
  log: false
365
504
  })
366
505
  ], WorkflowService.prototype, "getTag", null);
506
+ __legacyDecorateClassTS([
507
+ TracedAs("workflow.service.hasActiveWorkflowForParent", {
508
+ recordParams: true,
509
+ recordResult: true,
510
+ log: false
511
+ })
512
+ ], WorkflowService.prototype, "hasActiveWorkflowForParent", null);
513
+ __legacyDecorateClassTS([
514
+ TracedAs("workflow.service.stopAllForParent", {
515
+ recordParams: true,
516
+ recordResult: true,
517
+ log: true
518
+ })
519
+ ], WorkflowService.prototype, "stopAllForParent", null);
520
+ __legacyDecorateClassTS([
521
+ TracedAs("workflow.service.forceStopAll", {
522
+ recordParams: false,
523
+ recordResult: true,
524
+ log: true
525
+ })
526
+ ], WorkflowService.prototype, "forceStopAll", null);
367
527
  __legacyDecorateClassTS([
368
528
  TracedAs("workflow.service.resumeSession", {
369
529
  recordParams: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.6.12",
3
+ "version": "1.6.14",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",