@cuylabs/agent-runtime-dapr 0.5.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.
- package/LICENSE +201 -0
- package/README.md +260 -0
- package/dist/chunk-2CEICSJH.js +809 -0
- package/dist/chunk-2FMHOZLU.js +1997 -0
- package/dist/chunk-A34CHK2E.js +283 -0
- package/dist/chunk-DILON56B.js +668 -0
- package/dist/execution/index.d.ts +126 -0
- package/dist/execution/index.js +17 -0
- package/dist/host/index.d.ts +7 -0
- package/dist/host/index.js +27 -0
- package/dist/index-CKTP36vE.d.ts +533 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +65 -0
- package/dist/store-pRLGfYhN.d.ts +97 -0
- package/dist/workflow/index.d.ts +216 -0
- package/dist/workflow/index.js +23 -0
- package/dist/workflow-bridge-C8Z1yr0Y.d.ts +83 -0
- package/package.json +99 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DaprSidecarClient
|
|
3
|
+
} from "./chunk-A34CHK2E.js";
|
|
4
|
+
|
|
5
|
+
// src/workflow/types.ts
|
|
6
|
+
var TERMINAL_DAPR_WORKFLOW_STATUSES = /* @__PURE__ */ new Set([
|
|
7
|
+
"COMPLETED",
|
|
8
|
+
"FAILED",
|
|
9
|
+
"TERMINATED"
|
|
10
|
+
]);
|
|
11
|
+
function isTerminalDaprWorkflowStatus(status) {
|
|
12
|
+
return TERMINAL_DAPR_WORKFLOW_STATUSES.has(status);
|
|
13
|
+
}
|
|
14
|
+
function hasStartedDaprWorkflow(status) {
|
|
15
|
+
return status !== "PENDING";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/workflow/client.ts
|
|
19
|
+
var DEFAULT_WORKFLOW_API_VERSION = "v1.0";
|
|
20
|
+
var DEFAULT_WORKFLOW_POLL_INTERVAL_MS = 1e3;
|
|
21
|
+
var MIN_WORKFLOW_POLL_INTERVAL_MS = 50;
|
|
22
|
+
var DEFAULT_WORKFLOW_WAIT_TIMEOUT_MS = 6e4;
|
|
23
|
+
function ensureNonEmpty(input, label) {
|
|
24
|
+
const trimmed = input.trim();
|
|
25
|
+
if (!trimmed) {
|
|
26
|
+
throw new Error(`${label} must not be empty`);
|
|
27
|
+
}
|
|
28
|
+
return trimmed;
|
|
29
|
+
}
|
|
30
|
+
function normalizePollInterval(input) {
|
|
31
|
+
if (input === void 0) {
|
|
32
|
+
return DEFAULT_WORKFLOW_POLL_INTERVAL_MS;
|
|
33
|
+
}
|
|
34
|
+
if (!Number.isFinite(input)) {
|
|
35
|
+
throw new Error("workflowPollIntervalMs must be a finite number");
|
|
36
|
+
}
|
|
37
|
+
return Math.max(MIN_WORKFLOW_POLL_INTERVAL_MS, Math.floor(input));
|
|
38
|
+
}
|
|
39
|
+
function normalizeTimeout(input) {
|
|
40
|
+
if (input === void 0) {
|
|
41
|
+
return DEFAULT_WORKFLOW_WAIT_TIMEOUT_MS;
|
|
42
|
+
}
|
|
43
|
+
if (!Number.isFinite(input)) {
|
|
44
|
+
throw new Error("timeoutMs must be a finite number");
|
|
45
|
+
}
|
|
46
|
+
return Math.max(0, Math.floor(input));
|
|
47
|
+
}
|
|
48
|
+
function sleep(ms) {
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
setTimeout(resolve, ms);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function serializeWorkflowBody(value) {
|
|
54
|
+
if (value === void 0) {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
if (typeof value === "string") {
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
return JSON.stringify(value);
|
|
61
|
+
}
|
|
62
|
+
function normalizeWorkflowState(payload) {
|
|
63
|
+
return {
|
|
64
|
+
instanceId: payload.instanceId ?? payload.instanceID ?? "",
|
|
65
|
+
workflowName: payload.workflowName ?? "",
|
|
66
|
+
createdAt: payload.createdAt,
|
|
67
|
+
lastUpdatedAt: payload.lastUpdatedAt,
|
|
68
|
+
runtimeStatus: payload.runtimeStatus ?? "PENDING",
|
|
69
|
+
properties: payload.properties ?? {}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
var DaprWorkflowClient = class {
|
|
73
|
+
client;
|
|
74
|
+
workflowComponent;
|
|
75
|
+
workflowApiVersion;
|
|
76
|
+
workflowPollIntervalMs;
|
|
77
|
+
constructor(options) {
|
|
78
|
+
this.client = new DaprSidecarClient(options);
|
|
79
|
+
this.workflowComponent = ensureNonEmpty(
|
|
80
|
+
options.workflowComponent,
|
|
81
|
+
"workflowComponent"
|
|
82
|
+
);
|
|
83
|
+
this.workflowApiVersion = options.workflowApiVersion ?? DEFAULT_WORKFLOW_API_VERSION;
|
|
84
|
+
this.workflowPollIntervalMs = normalizePollInterval(
|
|
85
|
+
options.workflowPollIntervalMs
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
async verifySidecar() {
|
|
89
|
+
await this.client.verifySidecar();
|
|
90
|
+
}
|
|
91
|
+
async startWorkflow(workflowName, options = {}) {
|
|
92
|
+
const normalizedWorkflowName = ensureNonEmpty(workflowName, "workflowName");
|
|
93
|
+
const query = options.instanceId ? `?instanceID=${encodeURIComponent(options.instanceId)}` : "";
|
|
94
|
+
const payload = serializeWorkflowBody(options.input);
|
|
95
|
+
const response = await this.client.requestJson(
|
|
96
|
+
`/${this.workflowApiVersion}/workflows/${encodeURIComponent(this.workflowComponent)}/${encodeURIComponent(normalizedWorkflowName)}/start${query}`,
|
|
97
|
+
{
|
|
98
|
+
method: "POST",
|
|
99
|
+
...payload !== void 0 ? { body: payload } : {}
|
|
100
|
+
},
|
|
101
|
+
[202]
|
|
102
|
+
);
|
|
103
|
+
const instanceId = response?.instanceId ?? response?.instanceID ?? options.instanceId;
|
|
104
|
+
if (!instanceId) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Dapr workflow start did not return an instanceId for workflow '${normalizedWorkflowName}'`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return { instanceId };
|
|
110
|
+
}
|
|
111
|
+
async getWorkflow(instanceId) {
|
|
112
|
+
const normalizedInstanceId = ensureNonEmpty(instanceId, "instanceId");
|
|
113
|
+
const response = await this.client.requestJson(
|
|
114
|
+
`/${this.workflowApiVersion}/workflows/${encodeURIComponent(this.workflowComponent)}/${encodeURIComponent(normalizedInstanceId)}`,
|
|
115
|
+
{ method: "GET" },
|
|
116
|
+
[200, 404]
|
|
117
|
+
);
|
|
118
|
+
if (!response) {
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
if (response.errorCode) {
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
if (!response.instanceId && !response.instanceID && !response.workflowName && !response.runtimeStatus) {
|
|
125
|
+
return void 0;
|
|
126
|
+
}
|
|
127
|
+
return normalizeWorkflowState(response);
|
|
128
|
+
}
|
|
129
|
+
async waitForWorkflowStart(instanceId, options = {}) {
|
|
130
|
+
return this.waitForWorkflowState(instanceId, {
|
|
131
|
+
...options,
|
|
132
|
+
predicate: (state) => hasStartedDaprWorkflow(state.runtimeStatus)
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
async waitForWorkflowCompletion(instanceId, options = {}) {
|
|
136
|
+
return this.waitForWorkflowState(instanceId, {
|
|
137
|
+
...options,
|
|
138
|
+
predicate: (state) => isTerminalDaprWorkflowStatus(state.runtimeStatus)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async pauseWorkflow(instanceId) {
|
|
142
|
+
await this.controlWorkflow(instanceId, "pause");
|
|
143
|
+
}
|
|
144
|
+
async resumeWorkflow(instanceId) {
|
|
145
|
+
await this.controlWorkflow(instanceId, "resume");
|
|
146
|
+
}
|
|
147
|
+
async terminateWorkflow(instanceId) {
|
|
148
|
+
await this.controlWorkflow(instanceId, "terminate");
|
|
149
|
+
}
|
|
150
|
+
async purgeWorkflow(instanceId) {
|
|
151
|
+
await this.controlWorkflow(instanceId, "purge");
|
|
152
|
+
}
|
|
153
|
+
async raiseWorkflowEvent(instanceId, eventName, options = {}) {
|
|
154
|
+
const normalizedInstanceId = ensureNonEmpty(instanceId, "instanceId");
|
|
155
|
+
const normalizedEventName = ensureNonEmpty(eventName, "eventName");
|
|
156
|
+
const payload = serializeWorkflowBody(options.eventData);
|
|
157
|
+
await this.client.request(
|
|
158
|
+
`/${this.workflowApiVersion}/workflows/${encodeURIComponent(this.workflowComponent)}/${encodeURIComponent(normalizedInstanceId)}/raiseEvent/${encodeURIComponent(normalizedEventName)}`,
|
|
159
|
+
{
|
|
160
|
+
method: "POST",
|
|
161
|
+
...payload !== void 0 ? { body: payload } : {}
|
|
162
|
+
},
|
|
163
|
+
[202]
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
async controlWorkflow(instanceId, action) {
|
|
167
|
+
const normalizedInstanceId = ensureNonEmpty(instanceId, "instanceId");
|
|
168
|
+
await this.client.request(
|
|
169
|
+
`/${this.workflowApiVersion}/workflows/${encodeURIComponent(this.workflowComponent)}/${encodeURIComponent(normalizedInstanceId)}/${action}`,
|
|
170
|
+
{ method: "POST" },
|
|
171
|
+
[202]
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
async waitForWorkflowState(instanceId, options) {
|
|
175
|
+
const timeoutMs = normalizeTimeout(options.timeoutMs);
|
|
176
|
+
const pollIntervalMs = normalizePollInterval(
|
|
177
|
+
options.pollIntervalMs ?? this.workflowPollIntervalMs
|
|
178
|
+
);
|
|
179
|
+
const deadline = Date.now() + timeoutMs;
|
|
180
|
+
while (Date.now() <= deadline) {
|
|
181
|
+
const state = await this.getWorkflow(instanceId);
|
|
182
|
+
if (state && options.predicate(state)) {
|
|
183
|
+
return state;
|
|
184
|
+
}
|
|
185
|
+
if (Date.now() >= deadline) {
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
await sleep(pollIntervalMs);
|
|
189
|
+
}
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/workflow/runtime.ts
|
|
195
|
+
import {
|
|
196
|
+
applyAgentWorkflowCommitResult,
|
|
197
|
+
applyAgentWorkflowModelStepResult,
|
|
198
|
+
applyAgentWorkflowToolCallResult,
|
|
199
|
+
advanceAgentTurnState,
|
|
200
|
+
convertAgentMessagesToModelMessages,
|
|
201
|
+
createAgentTurnEngine,
|
|
202
|
+
createAgentTurnStepCommitBatch,
|
|
203
|
+
executeAgentToolCall,
|
|
204
|
+
failAgentWorkflowTurnState,
|
|
205
|
+
normalizeToolReplayPolicy,
|
|
206
|
+
planNextAgentWorkflowOperation,
|
|
207
|
+
prepareModelStep,
|
|
208
|
+
recordAgentWorkflowReplayDecision,
|
|
209
|
+
restoreAgentWorkflowMessages,
|
|
210
|
+
runModelStep,
|
|
211
|
+
snapshotAgentWorkflowMessages
|
|
212
|
+
} from "@cuylabs/agent-core";
|
|
213
|
+
var DEFAULT_WORKFLOW_NAME = "agent-turn";
|
|
214
|
+
function defaultActivityNames(workflowName, overrides = {}) {
|
|
215
|
+
return {
|
|
216
|
+
modelStep: overrides.modelStep ?? `${workflowName}:model-step`,
|
|
217
|
+
toolCall: overrides.toolCall ?? `${workflowName}:tool-call`,
|
|
218
|
+
stepCommit: overrides.stepCommit ?? `${workflowName}:step-commit`,
|
|
219
|
+
outputCommit: overrides.outputCommit ?? `${workflowName}:output-commit`
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function normalizeError(error) {
|
|
223
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
224
|
+
}
|
|
225
|
+
function renameActivity(activity, name) {
|
|
226
|
+
return {
|
|
227
|
+
name,
|
|
228
|
+
handler: activity.handler
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async function* emptyCommitApplier() {
|
|
232
|
+
yield* [];
|
|
233
|
+
}
|
|
234
|
+
async function withObserverContext(bridge, sessionId, fn) {
|
|
235
|
+
const parentCtx = bridge?.getOtelContext(sessionId);
|
|
236
|
+
if (!parentCtx) return fn();
|
|
237
|
+
try {
|
|
238
|
+
const otelApi = await import("@opentelemetry/api");
|
|
239
|
+
return await otelApi.context.with(
|
|
240
|
+
parentCtx,
|
|
241
|
+
fn
|
|
242
|
+
);
|
|
243
|
+
} catch {
|
|
244
|
+
return fn();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function summarizeWorkflowState(state) {
|
|
248
|
+
return JSON.stringify({
|
|
249
|
+
sessionId: state.sessionId,
|
|
250
|
+
phase: state.phase,
|
|
251
|
+
step: state.step,
|
|
252
|
+
finalResponse: state.finalResponse,
|
|
253
|
+
error: state.error
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
function ensureReplayDecision(state, plan, now) {
|
|
257
|
+
if (plan.replayDecision) {
|
|
258
|
+
return { state, decision: plan.replayDecision };
|
|
259
|
+
}
|
|
260
|
+
const mode = plan.toolCall.replayPolicy?.mode;
|
|
261
|
+
if (!mode) {
|
|
262
|
+
return { state };
|
|
263
|
+
}
|
|
264
|
+
if (mode === "manual") {
|
|
265
|
+
const decision2 = {
|
|
266
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
267
|
+
toolName: plan.toolCall.toolName,
|
|
268
|
+
action: "replay",
|
|
269
|
+
source: "runtime",
|
|
270
|
+
decidedAt: now,
|
|
271
|
+
reason: "auto-decided by Dapr workflow runtime (activity-level checkpoint)"
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
state: recordAgentWorkflowReplayDecision(state, decision2, now),
|
|
275
|
+
decision: decision2
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const decision = {
|
|
279
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
280
|
+
toolName: plan.toolCall.toolName,
|
|
281
|
+
action: mode === "skip" ? "skip" : "replay",
|
|
282
|
+
source: "policy",
|
|
283
|
+
decidedAt: now,
|
|
284
|
+
...plan.toolCall.replayPolicy?.reason ? { reason: plan.toolCall.replayPolicy.reason } : {}
|
|
285
|
+
};
|
|
286
|
+
return {
|
|
287
|
+
state: recordAgentWorkflowReplayDecision(state, decision, now),
|
|
288
|
+
decision
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function createDaprAgentTurnWorkflowDefinition(options) {
|
|
292
|
+
const workflowName = options.workflowName ?? DEFAULT_WORKFLOW_NAME;
|
|
293
|
+
const activityNames = defaultActivityNames(
|
|
294
|
+
workflowName,
|
|
295
|
+
options.activityNames
|
|
296
|
+
);
|
|
297
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
298
|
+
const bridge = options.observerBridge;
|
|
299
|
+
const workflow = async function* (context, input) {
|
|
300
|
+
let state = structuredClone(input);
|
|
301
|
+
if (!context.isReplaying?.()) {
|
|
302
|
+
await bridge?.notifyTaskStart(state);
|
|
303
|
+
}
|
|
304
|
+
try {
|
|
305
|
+
while (true) {
|
|
306
|
+
context.setCustomStatus?.(summarizeWorkflowState(state));
|
|
307
|
+
const plan = planNextAgentWorkflowOperation(state);
|
|
308
|
+
if (!plan) {
|
|
309
|
+
if (!context.isReplaying?.()) {
|
|
310
|
+
await bridge?.notifyTaskComplete(state);
|
|
311
|
+
}
|
|
312
|
+
return state;
|
|
313
|
+
}
|
|
314
|
+
switch (plan.kind) {
|
|
315
|
+
case "model-step": {
|
|
316
|
+
const result = yield context.callActivity(
|
|
317
|
+
activityNames.modelStep,
|
|
318
|
+
plan
|
|
319
|
+
);
|
|
320
|
+
state = applyAgentWorkflowModelStepResult(state, result, now());
|
|
321
|
+
if (!context.isReplaying?.()) {
|
|
322
|
+
await bridge?.notifyCheckpoint("step-finish", state);
|
|
323
|
+
}
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
case "tool-call": {
|
|
327
|
+
const decisionState = ensureReplayDecision(state, plan, now());
|
|
328
|
+
state = decisionState.state;
|
|
329
|
+
if (decisionState.decision?.action === "skip") {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`Cannot skip unresolved tool call '${plan.toolCall.toolCallId}' without a previously persisted tool result`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
const result = yield context.callActivity(activityNames.toolCall, {
|
|
335
|
+
...plan,
|
|
336
|
+
...decisionState.decision ? { replayDecision: decisionState.decision } : {}
|
|
337
|
+
});
|
|
338
|
+
state = applyAgentWorkflowToolCallResult(state, result, now());
|
|
339
|
+
if (!context.isReplaying?.()) {
|
|
340
|
+
await bridge?.notifyCheckpoint("tool-result", state);
|
|
341
|
+
}
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case "step-commit": {
|
|
345
|
+
const result = yield context.callActivity(
|
|
346
|
+
activityNames.stepCommit,
|
|
347
|
+
plan
|
|
348
|
+
);
|
|
349
|
+
state = applyAgentWorkflowCommitResult(state, result, now());
|
|
350
|
+
if (!context.isReplaying?.()) {
|
|
351
|
+
await bridge?.notifyCheckpoint("step-commit-finish", state);
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
case "output-commit": {
|
|
356
|
+
const result = yield context.callActivity(
|
|
357
|
+
activityNames.outputCommit,
|
|
358
|
+
plan
|
|
359
|
+
);
|
|
360
|
+
state = applyAgentWorkflowCommitResult(state, result, now());
|
|
361
|
+
if (!context.isReplaying?.()) {
|
|
362
|
+
await bridge?.notifyCheckpoint("output-commit-finish", state);
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
} catch (error) {
|
|
369
|
+
const normalized = normalizeError(error);
|
|
370
|
+
state = failAgentWorkflowTurnState(state, normalized, now());
|
|
371
|
+
context.setCustomStatus?.(summarizeWorkflowState(state));
|
|
372
|
+
if (!context.isReplaying?.()) {
|
|
373
|
+
await bridge?.notifyTaskError(state, normalized);
|
|
374
|
+
}
|
|
375
|
+
throw normalized;
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
return {
|
|
379
|
+
workflowName,
|
|
380
|
+
activityNames,
|
|
381
|
+
workflow
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function createDaprAgentTurnModelStepActivity(options) {
|
|
385
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
386
|
+
return {
|
|
387
|
+
name: "model-step",
|
|
388
|
+
handler: async (_context, plan) => {
|
|
389
|
+
const runActivity = async () => {
|
|
390
|
+
if (options.middleware?.hasMiddleware) {
|
|
391
|
+
await options.middleware.runChatStart(
|
|
392
|
+
plan.sessionId,
|
|
393
|
+
`[workflow model-step ${plan.step}]`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
let stepResult;
|
|
397
|
+
let stepError;
|
|
398
|
+
try {
|
|
399
|
+
const restoredMessages = restoreAgentWorkflowMessages(plan.messages);
|
|
400
|
+
const turnEngine = createAgentTurnEngine({
|
|
401
|
+
sessionId: plan.sessionId,
|
|
402
|
+
startedAt: now(),
|
|
403
|
+
getToolReplayPolicy: (toolName) => options.tools[toolName]?.replayPolicy ? normalizeToolReplayPolicy(options.tools[toolName].replayPolicy) : void 0
|
|
404
|
+
});
|
|
405
|
+
const preparedStep = prepareModelStep({
|
|
406
|
+
sessionId: plan.sessionId,
|
|
407
|
+
step: plan.step,
|
|
408
|
+
systemPrompts: plan.systemPrompts,
|
|
409
|
+
messages: restoredMessages,
|
|
410
|
+
toModelMessages: options.toModelMessages ?? convertAgentMessagesToModelMessages,
|
|
411
|
+
abort: options.createAbortSignal?.() ?? new AbortController().signal,
|
|
412
|
+
tools: options.tools,
|
|
413
|
+
mcpTools: typeof options.mcpTools === "function" ? await options.mcpTools() : options.mcpTools,
|
|
414
|
+
config: options.runtime,
|
|
415
|
+
...options.host ? { host: options.host } : {},
|
|
416
|
+
...options.turnTracker ? { turnTracker: options.turnTracker } : {},
|
|
417
|
+
...options.middleware ? { middleware: options.middleware } : {},
|
|
418
|
+
...options.reasoningLevel ? { reasoningLevel: options.reasoningLevel } : {},
|
|
419
|
+
toolExecutionMode: "plan"
|
|
420
|
+
});
|
|
421
|
+
const iterator = runModelStep({
|
|
422
|
+
preparedStep,
|
|
423
|
+
turnEngine,
|
|
424
|
+
applyCommitBatch: () => emptyCommitApplier()
|
|
425
|
+
});
|
|
426
|
+
while (true) {
|
|
427
|
+
const item = await iterator.next();
|
|
428
|
+
if (item.done) {
|
|
429
|
+
const stepCommit = turnEngine.createStepCommitSnapshot();
|
|
430
|
+
stepResult = {
|
|
431
|
+
text: item.value.text,
|
|
432
|
+
...item.value.usage ? { usage: item.value.usage } : {},
|
|
433
|
+
...item.value.finishReason ? { finishReason: item.value.finishReason } : {},
|
|
434
|
+
turnState: turnEngine.getState(),
|
|
435
|
+
...stepCommit ? { stepCommit } : {}
|
|
436
|
+
};
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
if (options.onEvent) {
|
|
440
|
+
await options.onEvent(item.value);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
} catch (err) {
|
|
444
|
+
stepError = err instanceof Error ? err : new Error(String(err));
|
|
445
|
+
}
|
|
446
|
+
if (options.middleware?.hasMiddleware) {
|
|
447
|
+
await options.middleware.runChatEnd(plan.sessionId, {
|
|
448
|
+
usage: stepResult?.usage,
|
|
449
|
+
error: stepError,
|
|
450
|
+
output: stepResult?.text
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
if (stepError) throw stepError;
|
|
454
|
+
return stepResult;
|
|
455
|
+
};
|
|
456
|
+
return withObserverContext(
|
|
457
|
+
options.observerBridge,
|
|
458
|
+
plan.sessionId,
|
|
459
|
+
runActivity
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
function createDaprAgentTurnToolCallActivity(options) {
|
|
465
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
466
|
+
return {
|
|
467
|
+
name: "tool-call",
|
|
468
|
+
handler: async (_context, plan) => {
|
|
469
|
+
const runActivity = async () => {
|
|
470
|
+
if (plan.replayDecision?.action === "skip") {
|
|
471
|
+
throw new Error(
|
|
472
|
+
`Tool call '${plan.toolCall.toolCallId}' cannot be skipped without a persisted result`
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
const updatedAt = now();
|
|
476
|
+
const tool = options.tools[plan.toolCall.toolName];
|
|
477
|
+
if (!tool) {
|
|
478
|
+
const event = {
|
|
479
|
+
type: "tool-error",
|
|
480
|
+
toolName: plan.toolCall.toolName,
|
|
481
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
482
|
+
error: `Tool '${plan.toolCall.toolName}' is not registered`
|
|
483
|
+
};
|
|
484
|
+
return {
|
|
485
|
+
toolResult: {
|
|
486
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
487
|
+
toolName: plan.toolCall.toolName,
|
|
488
|
+
result: `Error: Tool '${plan.toolCall.toolName}' is not registered`,
|
|
489
|
+
...plan.toolCall.replayPolicy ? { replayPolicy: plan.toolCall.replayPolicy } : {}
|
|
490
|
+
},
|
|
491
|
+
...plan.turnState ? {
|
|
492
|
+
turnState: advanceAgentTurnState(
|
|
493
|
+
plan.turnState,
|
|
494
|
+
event,
|
|
495
|
+
updatedAt,
|
|
496
|
+
{
|
|
497
|
+
...plan.toolCall.replayPolicy ? { toolReplayPolicy: plan.toolCall.replayPolicy } : {}
|
|
498
|
+
}
|
|
499
|
+
)
|
|
500
|
+
} : {}
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const executed = await executeAgentToolCall({
|
|
505
|
+
toolName: plan.toolCall.toolName,
|
|
506
|
+
tool,
|
|
507
|
+
params: plan.toolCall.args,
|
|
508
|
+
cwd: options.cwd,
|
|
509
|
+
abort: options.createAbortSignal?.() ?? new AbortController().signal,
|
|
510
|
+
sessionID: plan.sessionId,
|
|
511
|
+
messageID: plan.toolCall.toolCallId,
|
|
512
|
+
...options.host ? { host: options.host } : {},
|
|
513
|
+
...options.turnTracker ? { turnTracker: options.turnTracker } : {},
|
|
514
|
+
...options.middleware ? { middleware: options.middleware } : {}
|
|
515
|
+
});
|
|
516
|
+
const event = {
|
|
517
|
+
type: "tool-result",
|
|
518
|
+
toolName: plan.toolCall.toolName,
|
|
519
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
520
|
+
result: executed.output
|
|
521
|
+
};
|
|
522
|
+
return {
|
|
523
|
+
toolResult: {
|
|
524
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
525
|
+
toolName: plan.toolCall.toolName,
|
|
526
|
+
result: executed.output,
|
|
527
|
+
...plan.toolCall.replayPolicy ? { replayPolicy: plan.toolCall.replayPolicy } : {}
|
|
528
|
+
},
|
|
529
|
+
...plan.turnState ? {
|
|
530
|
+
turnState: advanceAgentTurnState(
|
|
531
|
+
plan.turnState,
|
|
532
|
+
event,
|
|
533
|
+
updatedAt,
|
|
534
|
+
{
|
|
535
|
+
...plan.toolCall.replayPolicy ? { toolReplayPolicy: plan.toolCall.replayPolicy } : {}
|
|
536
|
+
}
|
|
537
|
+
)
|
|
538
|
+
} : {}
|
|
539
|
+
};
|
|
540
|
+
} catch (error) {
|
|
541
|
+
const message = normalizeError(error).message;
|
|
542
|
+
const event = {
|
|
543
|
+
type: "tool-error",
|
|
544
|
+
toolName: plan.toolCall.toolName,
|
|
545
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
546
|
+
error: message
|
|
547
|
+
};
|
|
548
|
+
return {
|
|
549
|
+
toolResult: {
|
|
550
|
+
toolCallId: plan.toolCall.toolCallId,
|
|
551
|
+
toolName: plan.toolCall.toolName,
|
|
552
|
+
result: `Error: ${message}`,
|
|
553
|
+
...plan.toolCall.replayPolicy ? { replayPolicy: plan.toolCall.replayPolicy } : {}
|
|
554
|
+
},
|
|
555
|
+
...plan.turnState ? {
|
|
556
|
+
turnState: advanceAgentTurnState(
|
|
557
|
+
plan.turnState,
|
|
558
|
+
event,
|
|
559
|
+
updatedAt,
|
|
560
|
+
{
|
|
561
|
+
...plan.toolCall.replayPolicy ? { toolReplayPolicy: plan.toolCall.replayPolicy } : {}
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
} : {}
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
};
|
|
568
|
+
return withObserverContext(
|
|
569
|
+
options.observerBridge,
|
|
570
|
+
plan.sessionId,
|
|
571
|
+
runActivity
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
function createDaprAgentTurnStepCommitActivity(options) {
|
|
577
|
+
return {
|
|
578
|
+
name: "step-commit",
|
|
579
|
+
handler: async (_context, plan) => {
|
|
580
|
+
const batch = createAgentTurnStepCommitBatch(plan.step, plan.snapshot);
|
|
581
|
+
if (!batch) {
|
|
582
|
+
return { messages: [] };
|
|
583
|
+
}
|
|
584
|
+
await options.persistMessages(plan.sessionId, batch.messages);
|
|
585
|
+
return { messages: snapshotAgentWorkflowMessages(batch.messages) };
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
function createDaprAgentTurnOutputCommitActivity(options) {
|
|
590
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
591
|
+
return {
|
|
592
|
+
name: "output-commit",
|
|
593
|
+
handler: async (_context, plan) => {
|
|
594
|
+
const turnEngine = createAgentTurnEngine({
|
|
595
|
+
sessionId: plan.sessionId,
|
|
596
|
+
startedAt: now()
|
|
597
|
+
});
|
|
598
|
+
const batch = turnEngine.createOutputCommit({
|
|
599
|
+
text: plan.text,
|
|
600
|
+
usage: plan.usage
|
|
601
|
+
});
|
|
602
|
+
if (!batch) {
|
|
603
|
+
return { messages: [] };
|
|
604
|
+
}
|
|
605
|
+
await options.persistMessages(plan.sessionId, batch.messages);
|
|
606
|
+
return { messages: snapshotAgentWorkflowMessages(batch.messages) };
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
function createDaprAgentTurnWorkflowKit(options) {
|
|
611
|
+
const modelStepActivity = createDaprAgentTurnModelStepActivity({
|
|
612
|
+
...options.modelStepActivity,
|
|
613
|
+
observerBridge: options.observerBridge
|
|
614
|
+
});
|
|
615
|
+
const toolCallActivity = createDaprAgentTurnToolCallActivity({
|
|
616
|
+
...options.toolCallActivity,
|
|
617
|
+
observerBridge: options.observerBridge
|
|
618
|
+
});
|
|
619
|
+
const stepCommitActivity = createDaprAgentTurnStepCommitActivity(
|
|
620
|
+
options.commitActivity
|
|
621
|
+
);
|
|
622
|
+
const outputCommitActivity = createDaprAgentTurnOutputCommitActivity(
|
|
623
|
+
options.commitActivity
|
|
624
|
+
);
|
|
625
|
+
const registration = createDaprAgentTurnWorkflowDefinition({
|
|
626
|
+
workflowName: options.workflowName,
|
|
627
|
+
activityNames: options.activityNames,
|
|
628
|
+
now: options.now,
|
|
629
|
+
observerBridge: options.observerBridge,
|
|
630
|
+
modelStep: (input) => modelStepActivity.handler(void 0, input),
|
|
631
|
+
toolCall: (input) => toolCallActivity.handler(void 0, input),
|
|
632
|
+
stepCommit: (input) => stepCommitActivity.handler(void 0, input),
|
|
633
|
+
outputCommit: (input) => outputCommitActivity.handler(void 0, input)
|
|
634
|
+
});
|
|
635
|
+
return {
|
|
636
|
+
...registration,
|
|
637
|
+
activities: {
|
|
638
|
+
modelStep: renameActivity(
|
|
639
|
+
modelStepActivity,
|
|
640
|
+
registration.activityNames.modelStep
|
|
641
|
+
),
|
|
642
|
+
toolCall: renameActivity(
|
|
643
|
+
toolCallActivity,
|
|
644
|
+
registration.activityNames.toolCall
|
|
645
|
+
),
|
|
646
|
+
stepCommit: renameActivity(
|
|
647
|
+
stepCommitActivity,
|
|
648
|
+
registration.activityNames.stepCommit
|
|
649
|
+
),
|
|
650
|
+
outputCommit: renameActivity(
|
|
651
|
+
outputCommitActivity,
|
|
652
|
+
registration.activityNames.outputCommit
|
|
653
|
+
)
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
export {
|
|
659
|
+
isTerminalDaprWorkflowStatus,
|
|
660
|
+
hasStartedDaprWorkflow,
|
|
661
|
+
DaprWorkflowClient,
|
|
662
|
+
createDaprAgentTurnWorkflowDefinition,
|
|
663
|
+
createDaprAgentTurnModelStepActivity,
|
|
664
|
+
createDaprAgentTurnToolCallActivity,
|
|
665
|
+
createDaprAgentTurnStepCommitActivity,
|
|
666
|
+
createDaprAgentTurnOutputCommitActivity,
|
|
667
|
+
createDaprAgentTurnWorkflowKit
|
|
668
|
+
};
|