@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.
- package/dist/env/agent/index.js +3 -3
- package/dist/env/event-source/index.js +7 -5
- package/dist/env/index.js +19 -19
- package/dist/env/prompt/index.js +2 -2
- package/dist/env/task/delegate/index.js +4 -4
- package/dist/env/task/index.js +5 -5
- package/dist/env/task/plugins/index.js +6 -4
- package/dist/env/tool/built-in/index.js +2 -2
- package/dist/env/tool/index.js +3 -3
- package/dist/env/workflow/engine/index.js +5 -5
- package/dist/env/workflow/index.js +12 -10
- package/dist/env/workflow/service/index.js +1 -1
- package/dist/env/workflow/tools/index.js +5 -4
- package/dist/env/workflow/types/index.js +3 -1
- package/dist/env/workflow/utils/index.js +4 -4
- package/dist/index.js +132 -21
- package/dist/shared/@ai-setting/{roy-agent-core-jenchn33.js → roy-agent-core-24rmf17n.js} +8 -0
- package/dist/shared/@ai-setting/{roy-agent-core-z7f8hyv7.js → roy-agent-core-6jqpdjr4.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-cxdnzn17.js → roy-agent-core-6qbyfzsw.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-8wd3qwx5.js → roy-agent-core-80e4a3g5.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-ms5dp89r.js → roy-agent-core-apz6v22z.js} +81 -40
- package/dist/shared/@ai-setting/{roy-agent-core-1bvv6s75.js → roy-agent-core-fvkyv5j6.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-dntkpwqq.js → roy-agent-core-fwxqevpf.js} +4 -1
- package/dist/shared/@ai-setting/{roy-agent-core-qnrf2aw6.js → roy-agent-core-jrj30vq3.js} +33 -2
- package/dist/shared/@ai-setting/{roy-agent-core-q7rt3x8d.js → roy-agent-core-m0cnmg7b.js} +2 -2
- package/dist/shared/@ai-setting/roy-agent-core-mmb9484f.js +458 -0
- package/dist/shared/@ai-setting/{roy-agent-core-0n2a8cbn.js → roy-agent-core-nhncpbzz.js} +602 -245
- package/dist/shared/@ai-setting/{roy-agent-core-pzeexnhf.js → roy-agent-core-nv4yfy3m.js} +4 -3
- package/dist/shared/@ai-setting/{roy-agent-core-w22tzjj5.js → roy-agent-core-psfkwe4g.js} +93 -14
- package/dist/shared/@ai-setting/{roy-agent-core-q2bw3cwd.js → roy-agent-core-px8ghk4g.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-mb7b62sm.js → roy-agent-core-r53regz9.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-06574wqa.js → roy-agent-core-ra4y7e4p.js} +4 -4
- package/dist/shared/@ai-setting/{roy-agent-core-asp5p3zx.js → roy-agent-core-st9y9z07.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-3bdpnmtg.js → roy-agent-core-v5nknfh0.js} +1 -8
- package/dist/shared/@ai-setting/{roy-agent-core-7a3gf3tw.js → roy-agent-core-wpw37qqf.js} +88 -3
- package/dist/shared/@ai-setting/{roy-agent-core-p6x6n3k4.js → roy-agent-core-x7fgze6s.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-p2vpsd1d.js → roy-agent-core-ywtmc0bh.js} +166 -6
- package/package.json +1 -1
- package/dist/shared/@ai-setting/roy-agent-core-4yq23m5g.js +0 -421
- /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.
|
|
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-
|
|
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
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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 (
|
|
90
|
-
return
|
|
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
|
-
|
|
93
|
-
|
|
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 (
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
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,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TAG_MAX_COUNT,
|
|
3
3
|
TAG_MIN_COUNT
|
|
4
|
-
} from "./roy-agent-core-
|
|
4
|
+
} from "./roy-agent-core-ywtmc0bh.js";
|
|
5
5
|
import {
|
|
6
6
|
validateWorkflowDefinition
|
|
7
|
-
} from "./roy-agent-core-
|
|
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-
|
|
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-
|
|
21
|
+
} from "./roy-agent-core-r53regz9.js";
|
|
22
22
|
import {
|
|
23
23
|
WorkflowService
|
|
24
|
-
} from "./roy-agent-core-
|
|
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-
|
|
144
|
+
const { AgentComponentAdapter } = await import("./roy-agent-core-6jqpdjr4.js");
|
|
145
145
|
agentRunner = new AgentComponentAdapter(agentComponent, {}, this.sessionComponent);
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -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-
|
|
4
|
+
} from "./roy-agent-core-nv4yfy3m.js";
|
|
5
5
|
import {
|
|
6
6
|
builtInPrompts
|
|
7
|
-
} from "./roy-agent-core-
|
|
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-
|
|
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?.();
|
|
@@ -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
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
|
271
|
-
|
|
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,
|