@xopcai/xopc 0.0.88 → 0.0.90
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/README.md +8 -1
- package/README.zh-CN.md +8 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-cPvvYLXo.js +222 -0
- package/dist/gateway/static/root/assets/apps-page-Bk1_P5FJ.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-CZoeQwHz.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-DIsl75Y3.js → channels-status-swr-BrtH2VzC.js} +1 -1
- package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +1 -0
- package/dist/gateway/static/root/assets/cron-api-CyqbgfHM.js +1 -0
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-Ip703-qM.js +2 -0
- package/dist/gateway/static/root/assets/cron-page-BpLdiQN8.js +1 -0
- package/dist/gateway/static/root/assets/dist-BpAiK86n.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BVJohZoZ.js → extension-debug-page-D6Ak0STa.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BT2tmElC.js → extension-page-Q0P3d6DW.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BSS47c2j.js → extension-settings-page-CL55LwU_.js} +1 -1
- package/dist/gateway/static/root/assets/eye-DAfL1U7M.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-BaFNUtkE.js → fetch-Dqa9iTWl.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-QwYEq6Hz.js → field-primitives-HUR6JElP.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BVSidEDJ.js → heartbeat-config-api-DusckjUX.js} +1 -1
- package/dist/gateway/static/root/assets/{index-qNrVJp-y.js → index-BYcGfwcE.js} +97 -97
- package/dist/gateway/static/root/assets/index-V7MQ7834.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-DDonPVLn.js → logs-page-_HcZ2fgK.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-iezSMjho.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-B8N3A3Zo.js → settings-form-section-a0qGVOlr.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-C9_nYQwM.js +3 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Q7KqkO-u.js → share-preview-page-DExl7CJy.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-BlgGD93t.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-BbRc5ugR.js → theme-store-C0Ehmdo5.js} +1 -1
- package/dist/gateway/static/root/assets/url-fxyYANfA.js +3 -0
- package/dist/gateway/static/root/assets/{utils-CxDGduqK.js → utils-DRQryzdn.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-D0viACE2.js +1 -0
- package/dist/gateway/static/root/assets/workflow-page.utils-DnG8JBhV.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-BvMobnJP.js +27 -0
- package/dist/gateway/static/root/index.html +7 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +2 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/service.js +2 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +3 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +20 -18
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/tools/cronjob-tool.d.ts +6 -0
- package/dist/src/agent/tools/cronjob-tool.js +76 -10
- package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
- package/dist/src/agent/tools/edit.d.ts +5 -1
- package/dist/src/agent/tools/edit.js +7 -5
- package/dist/src/agent/tools/edit.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -0
- package/dist/src/agent/tools/factory.js +4 -25
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/workflow-tool.d.ts +6 -28
- package/dist/src/agent/tools/workflow-tool.js +60 -260
- package/dist/src/agent/tools/workflow-tool.js.map +1 -1
- package/dist/src/agent/tools/write.d.ts +5 -1
- package/dist/src/agent/tools/write.js +7 -5
- package/dist/src/agent/tools/write.js.map +1 -1
- package/dist/src/agent/workflow/agent-progress.js +2 -0
- package/dist/src/agent/workflow/agent-progress.js.map +1 -1
- package/dist/src/agent/workflow/builtins/client-proposal.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/client-proposal.js +155 -0
- package/dist/src/agent/workflow/builtins/client-proposal.js.map +1 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.js +150 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.js.map +1 -0
- package/dist/src/agent/workflow/builtins/content-draft.d.ts +13 -0
- package/dist/src/agent/workflow/builtins/content-draft.js +146 -0
- package/dist/src/agent/workflow/builtins/content-draft.js.map +1 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +11 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.js +137 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.js.map +1 -0
- package/dist/src/agent/workflow/builtins/decision-compare.d.ts +13 -0
- package/dist/src/agent/workflow/builtins/decision-compare.js +173 -0
- package/dist/src/agent/workflow/builtins/decision-compare.js.map +1 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +11 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.js +148 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.js.map +1 -0
- package/dist/src/agent/workflow/builtins/index.d.ts +10 -1
- package/dist/src/agent/workflow/builtins/index.js +46 -1
- package/dist/src/agent/workflow/builtins/index.js.map +1 -1
- package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/meeting-prep.js +144 -0
- package/dist/src/agent/workflow/builtins/meeting-prep.js.map +1 -0
- package/dist/src/agent/workflow/builtins/offer-design.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/offer-design.js +161 -0
- package/dist/src/agent/workflow/builtins/offer-design.js.map +1 -0
- package/dist/src/agent/workflow/builtins/weekly-review.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/weekly-review.js +131 -0
- package/dist/src/agent/workflow/builtins/weekly-review.js.map +1 -0
- package/dist/src/agent/workflow/step-labels.js +2 -2
- package/dist/src/agent/workflow/step-labels.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.js +3 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +4 -0
- package/dist/src/agent/workflow/workflow-child-tools.d.ts +4 -0
- package/dist/src/agent/workflow/workflow-child-tools.js +21 -0
- package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -0
- package/dist/src/auth/credentials.d.ts +14 -2
- package/dist/src/auth/credentials.js +38 -13
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/auth/oauth/types.d.ts +16 -0
- package/dist/src/chat-commands/agent-edit.d.ts +4 -0
- package/dist/src/chat-commands/agent-edit.js +136 -0
- package/dist/src/chat-commands/agent-edit.js.map +1 -0
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/cli/bin.js +2 -0
- package/dist/src/cli/bin.js.map +1 -1
- package/dist/src/cli/commands/auth.js +6 -0
- package/dist/src/cli/commands/auth.js.map +1 -1
- package/dist/src/cli/commands/cron.js +42 -3
- package/dist/src/cli/commands/cron.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +79 -56
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/cli/commands/onboard/model.js +6 -0
- package/dist/src/cli/commands/onboard/model.js.map +1 -1
- package/dist/src/cli/commands/update.js +86 -79
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/commands/agents.config.d.ts +3 -2
- package/dist/src/commands/agents.config.js +5 -2
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-typed-models.d.ts +2 -7
- package/dist/src/config/agent-typed-models.js +3 -14
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/localized-text.d.ts +6 -0
- package/dist/src/config/localized-text.js +42 -0
- package/dist/src/config/localized-text.js.map +1 -0
- package/dist/src/config/models-json.d.ts +6 -6
- package/dist/src/config/schema.d.ts +6 -21
- package/dist/src/config/schema.js +4 -4
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/executor.d.ts +4 -0
- package/dist/src/cron/executor.js +169 -5
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/cron/job-content.js +2 -1
- package/dist/src/cron/job-content.js.map +1 -1
- package/dist/src/cron/types.d.ts +28 -1
- package/dist/src/cron/validation.d.ts +80 -0
- package/dist/src/cron/validation.js +30 -4
- package/dist/src/cron/validation.js.map +1 -1
- package/dist/src/cron/workflow-run-completion.d.ts +23 -0
- package/dist/src/cron/workflow-run-completion.js +72 -0
- package/dist/src/cron/workflow-run-completion.js.map +1 -0
- package/dist/src/extensions/update.d.ts +51 -0
- package/dist/src/extensions/update.js +260 -0
- package/dist/src/extensions/update.js.map +1 -0
- package/dist/src/gateway/agents-admin.d.ts +15 -8
- package/dist/src/gateway/agents-admin.js +77 -28
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/gateway-workflow-host.types.d.ts +17 -0
- package/dist/src/gateway/gateway-workflow-host.types.js +1 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -0
- package/dist/src/gateway/hono/lib/config-payload.js +2 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +2 -0
- package/dist/src/gateway/hono/middleware/auth.js +12 -7
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +40 -15
- package/dist/src/gateway/hono/oauth-async.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +31 -6
- package/dist/src/gateway/hono/oauth.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +55 -12
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +11 -5
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.js +55 -107
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +72 -191
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/server.js +2 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +5 -0
- package/dist/src/gateway/service.js +24 -3
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/brew.d.ts +4 -0
- package/dist/src/infra/brew.js +20 -0
- package/dist/src/infra/brew.js.map +1 -0
- package/dist/src/infra/package-json.d.ts +2 -0
- package/dist/src/infra/package-json.js +23 -0
- package/dist/src/infra/package-json.js.map +1 -0
- package/dist/src/infra/package-update-steps.d.ts +35 -0
- package/dist/src/infra/package-update-steps.js +304 -0
- package/dist/src/infra/package-update-steps.js.map +1 -0
- package/dist/src/infra/path-env.d.ts +11 -0
- package/dist/src/infra/path-env.js +90 -0
- package/dist/src/infra/path-env.js.map +1 -0
- package/dist/src/infra/path-prepend.d.ts +7 -0
- package/dist/src/infra/path-prepend.js +44 -0
- package/dist/src/infra/path-prepend.js.map +1 -0
- package/dist/src/infra/stable-node-path.d.ts +2 -0
- package/dist/src/infra/stable-node-path.js +28 -0
- package/dist/src/infra/stable-node-path.js.map +1 -0
- package/dist/src/infra/update-global.d.ts +30 -23
- package/dist/src/infra/update-global.js +113 -64
- package/dist/src/infra/update-global.js.map +1 -1
- package/dist/src/infra/update-log.d.ts +1 -0
- package/dist/src/infra/update-log.js +12 -0
- package/dist/src/infra/update-log.js.map +1 -0
- package/dist/src/infra/update-restart.d.ts +20 -0
- package/dist/src/infra/update-restart.js +165 -0
- package/dist/src/infra/update-restart.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +89 -1
- package/dist/src/infra/update-runner.js +604 -173
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.d.ts +3 -0
- package/dist/src/infra/update-startup.js +8 -4
- package/dist/src/infra/update-startup.js.map +1 -1
- package/dist/src/providers/index.d.ts +8 -0
- package/dist/src/providers/index.js +51 -12
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/routing/resolve-route.d.ts +3 -1
- package/dist/src/routing/resolve-route.js.map +1 -1
- package/dist/src/session/store.d.ts +5 -3
- package/dist/src/session/store.js +66 -20
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/share/site-share-config.d.ts +3 -2
- package/dist/src/share/site-share-config.js.map +1 -1
- package/dist/src/utils/logger/stats.d.ts +1 -1
- package/dist/src/workflows/domain/command.d.ts +2 -1
- package/dist/src/workflows/domain/definition-utils.d.ts +14 -0
- package/dist/src/workflows/domain/definition-utils.js +50 -0
- package/dist/src/workflows/domain/definition-utils.js.map +1 -0
- package/dist/src/workflows/domain/event.d.ts +3 -0
- package/dist/src/workflows/domain/index.d.ts +2 -0
- package/dist/src/workflows/domain/index.js +3 -1
- package/dist/src/workflows/domain/run.d.ts +60 -0
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/domain/validation.d.ts +19 -0
- package/dist/src/workflows/domain/validation.js +66 -0
- package/dist/src/workflows/domain/validation.js.map +1 -0
- package/dist/src/workflows/engine/projector.js +17 -0
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +2 -1
- package/dist/src/workflows/engine/workflow-engine.js +128 -0
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.d.ts +4 -0
- package/dist/src/workflows/index.js +9 -2
- package/dist/src/workflows/service/run-view-to-snapshot.d.ts +4 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js +63 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.d.ts +37 -0
- package/dist/src/workflows/service/workflow-run-service.js +282 -0
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +47 -0
- package/dist/src/workflows/service/workflow-run-service.types.js +1 -0
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +29 -0
- package/dist/src/workflows/service/workflow-session-bridge.js +177 -0
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -0
- package/dist/src/workflows/service/workflow-session-key.d.ts +3 -0
- package/dist/src/workflows/service/workflow-session-key.js +21 -0
- package/dist/src/workflows/service/workflow-session-key.js.map +1 -0
- package/dist/src/workflows/store/run-store.js +1 -0
- package/dist/src/workflows/store/run-store.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-CRxETUZx.js +0 -222
- package/dist/gateway/static/root/assets/apps-page-wKWf3l57.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +0 -1
- package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +0 -1
- package/dist/gateway/static/root/assets/cron-api-N9hvuRrn.js +0 -1
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-DueM3rBz.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-tlNGNxhP.js +0 -1
- package/dist/gateway/static/root/assets/dist-CJwfHYvT.js +0 -1
- package/dist/gateway/static/root/assets/index-CqZzHNEg.css +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +0 -2
- package/dist/gateway/static/root/assets/url-D6jvVYIA.js +0 -7
- package/dist/gateway/static/root/assets/voice-api-key-field-CTyHz7L_.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +0 -27
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { extractProfileAgentId } from "../../config/agent-profile.js";
|
|
2
|
+
import { init_providers, resolveModel } from "../../providers/index.js";
|
|
3
|
+
import { createWorkflowCatalog } from "../../agent/workflow/catalog.js";
|
|
4
|
+
import { DelegateSubagentRunner } from "../../agent/workflow/subagent-runner.js";
|
|
5
|
+
import { buildWorkflowDefinition } from "../domain/definition-utils.js";
|
|
6
|
+
import { isTerminalWorkflowRunStatus } from "../domain/run.js";
|
|
7
|
+
import "../domain/index.js";
|
|
8
|
+
import { resolveModelRef } from "../../config/agent-typed-models.js";
|
|
9
|
+
import { WorkflowEngine } from "../engine/workflow-engine.js";
|
|
10
|
+
import "../engine/index.js";
|
|
11
|
+
import { WorkflowEventStore } from "../store/event-store.js";
|
|
12
|
+
import { WorkflowRunStore } from "../store/run-store.js";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
//#region src/workflows/service/workflow-run-service.ts
|
|
15
|
+
init_providers();
|
|
16
|
+
var WorkflowRunService = class {
|
|
17
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.options = options;
|
|
20
|
+
}
|
|
21
|
+
async startWorkflowRun(params) {
|
|
22
|
+
const definition = this.loadDefinition(params.definitionId);
|
|
23
|
+
if (!definition) return {
|
|
24
|
+
ok: false,
|
|
25
|
+
code: "definition_not_found",
|
|
26
|
+
message: "Workflow definition not found",
|
|
27
|
+
httpStatus: 404
|
|
28
|
+
};
|
|
29
|
+
const runId = randomUUID();
|
|
30
|
+
const goal = params.goal ?? "";
|
|
31
|
+
const { sessionKey } = await this.options.sessionBridge.prepareRunSession({
|
|
32
|
+
runId,
|
|
33
|
+
agentId: params.agentId,
|
|
34
|
+
definitionId: params.definitionId,
|
|
35
|
+
definitionTitle: definition.title,
|
|
36
|
+
goal,
|
|
37
|
+
parentSessionKey: params.parentSessionKey
|
|
38
|
+
});
|
|
39
|
+
const source = normalizeWorkflowRunSourceForSession(params.source, sessionKey, params.parentSessionKey);
|
|
40
|
+
const abortController = new AbortController();
|
|
41
|
+
const eventStore = new WorkflowEventStore(this.options.service.currentConfig, params.agentId);
|
|
42
|
+
const runStore = new WorkflowRunStore(this.options.service.currentConfig, params.agentId, eventStore);
|
|
43
|
+
const engine = this.createWorkflowEngine({
|
|
44
|
+
eventStore,
|
|
45
|
+
runStore,
|
|
46
|
+
sessionKey
|
|
47
|
+
});
|
|
48
|
+
const inputEnvelope = params.inputEnvelope ?? buildWorkflowRunInputEnvelope(params.input, params.goal);
|
|
49
|
+
this.activeRuns.set(runId, abortController);
|
|
50
|
+
engine.startRun(definition, {
|
|
51
|
+
runId,
|
|
52
|
+
input: inputEnvelope.payload,
|
|
53
|
+
goal: inputEnvelope.goal ?? params.goal,
|
|
54
|
+
source,
|
|
55
|
+
metadata: buildWorkflowRunMetadata({
|
|
56
|
+
definition,
|
|
57
|
+
agentId: params.agentId,
|
|
58
|
+
sessionKey,
|
|
59
|
+
source,
|
|
60
|
+
input: inputEnvelope,
|
|
61
|
+
retryOfRunId: params.retryOfRunId,
|
|
62
|
+
idempotencyKey: params.idempotencyKey
|
|
63
|
+
}),
|
|
64
|
+
signal: abortController.signal,
|
|
65
|
+
concurrency: params.concurrency,
|
|
66
|
+
maxSubagents: params.maxSubagents,
|
|
67
|
+
tokenBudget: params.tokenBudget
|
|
68
|
+
}).catch((err) => {
|
|
69
|
+
this.options.service.emit("workflow.run.error", {
|
|
70
|
+
runId,
|
|
71
|
+
error: err instanceof Error ? err.message : String(err)
|
|
72
|
+
});
|
|
73
|
+
}).finally(() => {
|
|
74
|
+
this.activeRuns.delete(runId);
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
runId,
|
|
79
|
+
sessionKey
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async retryWorkflowRun(params) {
|
|
83
|
+
const existing = await this.createRunStore(params.agentId).readRunView(params.runId);
|
|
84
|
+
if (!existing) return {
|
|
85
|
+
ok: false,
|
|
86
|
+
code: "run_not_found",
|
|
87
|
+
message: "Workflow run not found",
|
|
88
|
+
httpStatus: 404
|
|
89
|
+
};
|
|
90
|
+
const parentSessionKey = existing.run.source.kind === "chat" ? existing.run.source.sessionKey : void 0;
|
|
91
|
+
return this.startWorkflowRun({
|
|
92
|
+
agentId: params.agentId,
|
|
93
|
+
definitionId: existing.run.definitionId,
|
|
94
|
+
input: existing.run.input,
|
|
95
|
+
goal: existing.run.goal,
|
|
96
|
+
source: existing.run.source,
|
|
97
|
+
parentSessionKey,
|
|
98
|
+
retryOfRunId: existing.run.id
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async cancelWorkflowRun(params) {
|
|
102
|
+
const controller = this.activeRuns.get(params.runId);
|
|
103
|
+
if (controller) {
|
|
104
|
+
controller.abort();
|
|
105
|
+
this.activeRuns.delete(params.runId);
|
|
106
|
+
return {
|
|
107
|
+
ok: true,
|
|
108
|
+
cancelled: true
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const runStore = this.createRunStore(params.agentId);
|
|
112
|
+
const view = await runStore.readRunView(params.runId);
|
|
113
|
+
if (!view) return {
|
|
114
|
+
ok: false,
|
|
115
|
+
code: "run_not_found",
|
|
116
|
+
message: "Workflow run not found",
|
|
117
|
+
httpStatus: 404
|
|
118
|
+
};
|
|
119
|
+
if (isTerminalWorkflowRunStatus(view.run.status)) return {
|
|
120
|
+
ok: true,
|
|
121
|
+
cancelled: true,
|
|
122
|
+
alreadyFinished: true
|
|
123
|
+
};
|
|
124
|
+
await new WorkflowEventStore(this.options.service.currentConfig, params.agentId).append({
|
|
125
|
+
runId: params.runId,
|
|
126
|
+
type: "run_cancelled",
|
|
127
|
+
payload: { reason: params.reason ?? "Cancelled by user" }
|
|
128
|
+
});
|
|
129
|
+
const updated = await runStore.rebuildRunView(params.runId);
|
|
130
|
+
if (updated) {
|
|
131
|
+
this.options.service.emit("workflow.run.updated", {
|
|
132
|
+
runId: params.runId,
|
|
133
|
+
view: updated
|
|
134
|
+
});
|
|
135
|
+
this.options.sessionBridge.handleRunViewUpdated(updated);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
ok: true,
|
|
139
|
+
cancelled: true
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
createRunStore(agentId) {
|
|
143
|
+
const eventStore = new WorkflowEventStore(this.options.service.currentConfig, agentId);
|
|
144
|
+
return new WorkflowRunStore(this.options.service.currentConfig, agentId, eventStore);
|
|
145
|
+
}
|
|
146
|
+
async readWorkflowRunView(agentId, runId) {
|
|
147
|
+
return this.createRunStore(agentId).readRunView(runId);
|
|
148
|
+
}
|
|
149
|
+
loadDefinition(definitionId) {
|
|
150
|
+
const catalog = createWorkflowCatalog();
|
|
151
|
+
try {
|
|
152
|
+
const loaded = catalog.load(definitionId);
|
|
153
|
+
return buildWorkflowDefinition({
|
|
154
|
+
name: loaded.name,
|
|
155
|
+
source: loaded.source,
|
|
156
|
+
script: loaded.script,
|
|
157
|
+
meta: loaded.meta
|
|
158
|
+
});
|
|
159
|
+
} catch {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
createWorkflowEngine(params) {
|
|
164
|
+
const gatewayService = this.options.service;
|
|
165
|
+
const runner = new DelegateSubagentRunner({
|
|
166
|
+
workspace: gatewayService.currentWorkspacePath,
|
|
167
|
+
bus: gatewayService.messageBusInstance,
|
|
168
|
+
getDefaultModel: () => resolveModel(gatewayService.agentService.getModelForSession(params.sessionKey)),
|
|
169
|
+
getConfig: () => gatewayService.currentConfig,
|
|
170
|
+
buildChildTools: (childOptions) => this.options.buildChildTools(childOptions)
|
|
171
|
+
});
|
|
172
|
+
return new WorkflowEngine({
|
|
173
|
+
cwd: gatewayService.currentWorkspacePath,
|
|
174
|
+
eventStore: params.eventStore,
|
|
175
|
+
runStore: params.runStore,
|
|
176
|
+
runner,
|
|
177
|
+
resolveModelId: (modelId) => {
|
|
178
|
+
const agentId = extractProfileAgentId(params.sessionKey, gatewayService.currentConfig);
|
|
179
|
+
return resolveModel(resolveModelRef(gatewayService.currentConfig, agentId, modelId));
|
|
180
|
+
},
|
|
181
|
+
onEventAppended: (event) => {
|
|
182
|
+
gatewayService.emit("workflow.event.appended", {
|
|
183
|
+
runId: event.runId,
|
|
184
|
+
event
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
onRunViewUpdated: (view) => {
|
|
188
|
+
gatewayService.emit("workflow.run.updated", {
|
|
189
|
+
runId: view.run.id,
|
|
190
|
+
view
|
|
191
|
+
});
|
|
192
|
+
this.options.sessionBridge.handleRunViewUpdated(view);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
function normalizeWorkflowRunSourceForSession(source, workflowSessionKey, parentSessionKey) {
|
|
198
|
+
if (parentSessionKey?.trim()) return {
|
|
199
|
+
kind: "chat",
|
|
200
|
+
sessionKey: parentSessionKey.trim()
|
|
201
|
+
};
|
|
202
|
+
if (source.kind === "webui") return {
|
|
203
|
+
...source,
|
|
204
|
+
sessionKey: workflowSessionKey
|
|
205
|
+
};
|
|
206
|
+
if (source.kind === "chat") return source;
|
|
207
|
+
return source;
|
|
208
|
+
}
|
|
209
|
+
function buildWorkflowRunInputEnvelope(input, goal) {
|
|
210
|
+
if (isWorkflowRunInputEnvelope(input)) return input;
|
|
211
|
+
return {
|
|
212
|
+
payload: input ?? {},
|
|
213
|
+
goal
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
function buildWorkflowRunMetadata(params) {
|
|
217
|
+
return {
|
|
218
|
+
sessionKey: params.sessionKey,
|
|
219
|
+
triggerSource: params.source.kind,
|
|
220
|
+
agentId: params.agentId,
|
|
221
|
+
retryOfRunId: params.retryOfRunId,
|
|
222
|
+
definition: buildWorkflowRunDefinitionSnapshot(params.definition),
|
|
223
|
+
input: params.input,
|
|
224
|
+
correlation: { idempotencyKey: params.idempotencyKey },
|
|
225
|
+
origin: buildWorkflowRunOrigin(params.source),
|
|
226
|
+
schedule: params.source.kind === "cron" ? {
|
|
227
|
+
scheduleId: params.source.scheduleId,
|
|
228
|
+
fireId: params.source.fireId
|
|
229
|
+
} : void 0
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function buildWorkflowRunDefinitionSnapshot(definition) {
|
|
233
|
+
return {
|
|
234
|
+
id: definition.id,
|
|
235
|
+
name: definition.name,
|
|
236
|
+
title: definition.title,
|
|
237
|
+
version: definition.version,
|
|
238
|
+
source: definition.metadata.source,
|
|
239
|
+
tags: [...definition.metadata.tags],
|
|
240
|
+
phaseCount: definition.phases.length,
|
|
241
|
+
estimatedAgents: definition.metadata.estimatedAgents
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function extractWorkflowRunSessionKey(source) {
|
|
245
|
+
if ("sessionKey" in source && typeof source.sessionKey === "string" && source.sessionKey.trim()) return source.sessionKey.trim();
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
function buildWorkflowRunOrigin(source) {
|
|
249
|
+
switch (source.kind) {
|
|
250
|
+
case "chat": return {
|
|
251
|
+
channel: "chat",
|
|
252
|
+
sessionKey: source.sessionKey,
|
|
253
|
+
messageId: source.messageId
|
|
254
|
+
};
|
|
255
|
+
case "webui": return {
|
|
256
|
+
channel: "webui",
|
|
257
|
+
sessionKey: source.sessionKey
|
|
258
|
+
};
|
|
259
|
+
case "cron": return {
|
|
260
|
+
channel: "cron",
|
|
261
|
+
scheduleId: source.scheduleId,
|
|
262
|
+
fireId: source.fireId
|
|
263
|
+
};
|
|
264
|
+
case "api": return {
|
|
265
|
+
channel: "api",
|
|
266
|
+
requestId: source.requestId
|
|
267
|
+
};
|
|
268
|
+
case "im": return {
|
|
269
|
+
channel: source.channel,
|
|
270
|
+
chatId: source.chatId,
|
|
271
|
+
messageId: source.messageId
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function isWorkflowRunInputEnvelope(input) {
|
|
276
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return false;
|
|
277
|
+
return "payload" in input || "variables" in input || "context" in input;
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
export { WorkflowRunService, buildWorkflowRunDefinitionSnapshot, buildWorkflowRunInputEnvelope, buildWorkflowRunMetadata, extractWorkflowRunSessionKey };
|
|
281
|
+
|
|
282
|
+
//# sourceMappingURL=workflow-run-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-run-service.js","names":["resolveModelById"],"sources":["../../../../src/workflows/service/workflow-run-service.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport type { BuildChildToolsOptions } from '../../agent/child-agent-factory.js';\nimport { extractProfileAgentId } from '../../config/agent-profile.js';\nimport { resolveModelRef } from '../../config/agent-typed-models.js';\nimport type { GatewayWorkflowHost } from '../../gateway/gateway-workflow-host.types.js';\nimport { resolveModel as resolveModelById } from '../../providers/index.js';\nimport { createWorkflowCatalog } from '../../agent/workflow/catalog.js';\nimport { DelegateSubagentRunner } from '../../agent/workflow/subagent-runner.js';\nimport type {\n WorkflowDefinition,\n WorkflowRunDefinitionSnapshot,\n WorkflowRunInputEnvelope,\n WorkflowRunMetadata,\n WorkflowRunSource,\n} from '../domain/index.js';\nimport { buildWorkflowDefinition, isTerminalWorkflowRunStatus } from '../domain/index.js';\nimport { WorkflowEngine } from '../engine/index.js';\nimport { WorkflowEventStore } from '../store/event-store.js';\nimport { WorkflowRunStore } from '../store/run-store.js';\nimport type { WorkflowSessionBridge } from './workflow-session-bridge.js';\nexport type {\n CancelWorkflowRunResult,\n CancelWorkflowRunServiceParams,\n CancelWorkflowRunServiceResult,\n RetryWorkflowRunServiceParams,\n StartWorkflowRunServiceParams,\n StartWorkflowRunServiceResult,\n WorkflowRunServiceErrorCode,\n WorkflowRunServiceErrorResult,\n WorkflowRunServiceResult,\n} from './workflow-run-service.types.js';\n\nimport type {\n CancelWorkflowRunResult,\n CancelWorkflowRunServiceParams,\n RetryWorkflowRunServiceParams,\n StartWorkflowRunServiceParams,\n WorkflowRunServiceResult,\n} from './workflow-run-service.types.js';\n\nexport interface WorkflowRunServiceOptions {\n service: GatewayWorkflowHost;\n sessionBridge: WorkflowSessionBridge;\n buildChildTools: (childOptions: BuildChildToolsOptions) => AgentTool<any, any>[];\n}\n\nexport class WorkflowRunService {\n private readonly activeRuns = new Map<string, AbortController>();\n\n constructor(private readonly options: WorkflowRunServiceOptions) {}\n\n async startWorkflowRun(params: StartWorkflowRunServiceParams): Promise<WorkflowRunServiceResult> {\n const definition = this.loadDefinition(params.definitionId);\n if (!definition) {\n return {\n ok: false,\n code: 'definition_not_found',\n message: 'Workflow definition not found',\n httpStatus: 404,\n };\n }\n\n const runId = randomUUID();\n const goal = params.goal ?? '';\n const { sessionKey } = await this.options.sessionBridge.prepareRunSession({\n runId,\n agentId: params.agentId,\n definitionId: params.definitionId,\n definitionTitle: definition.title,\n goal,\n parentSessionKey: params.parentSessionKey,\n });\n const source = normalizeWorkflowRunSourceForSession(params.source, sessionKey, params.parentSessionKey);\n const abortController = new AbortController();\n const eventStore = new WorkflowEventStore(this.options.service.currentConfig, params.agentId);\n const runStore = new WorkflowRunStore(this.options.service.currentConfig, params.agentId, eventStore);\n const engine = this.createWorkflowEngine({\n eventStore,\n runStore,\n sessionKey,\n });\n const inputEnvelope = params.inputEnvelope ?? buildWorkflowRunInputEnvelope(params.input, params.goal);\n\n this.activeRuns.set(runId, abortController);\n void engine.startRun(definition, {\n runId,\n input: inputEnvelope.payload,\n goal: inputEnvelope.goal ?? params.goal,\n source,\n metadata: buildWorkflowRunMetadata({\n definition,\n agentId: params.agentId,\n sessionKey,\n source,\n input: inputEnvelope,\n retryOfRunId: params.retryOfRunId,\n idempotencyKey: params.idempotencyKey,\n }),\n signal: abortController.signal,\n concurrency: params.concurrency,\n maxSubagents: params.maxSubagents,\n tokenBudget: params.tokenBudget,\n }).catch((err) => {\n this.options.service.emit('workflow.run.error', {\n runId,\n error: err instanceof Error ? err.message : String(err),\n });\n }).finally(() => {\n this.activeRuns.delete(runId);\n });\n\n return { ok: true, runId, sessionKey };\n }\n\n async retryWorkflowRun(params: RetryWorkflowRunServiceParams): Promise<WorkflowRunServiceResult> {\n const runStore = this.createRunStore(params.agentId);\n const existing = await runStore.readRunView(params.runId);\n if (!existing) {\n return {\n ok: false,\n code: 'run_not_found',\n message: 'Workflow run not found',\n httpStatus: 404,\n };\n }\n\n const parentSessionKey =\n existing.run.source.kind === 'chat' ? existing.run.source.sessionKey : undefined;\n\n return this.startWorkflowRun({\n agentId: params.agentId,\n definitionId: existing.run.definitionId,\n input: existing.run.input,\n goal: existing.run.goal,\n source: existing.run.source,\n parentSessionKey,\n retryOfRunId: existing.run.id,\n });\n }\n\n async cancelWorkflowRun(params: CancelWorkflowRunServiceParams): Promise<CancelWorkflowRunResult> {\n const controller = this.activeRuns.get(params.runId);\n if (controller) {\n controller.abort();\n this.activeRuns.delete(params.runId);\n return { ok: true, cancelled: true };\n }\n\n const runStore = this.createRunStore(params.agentId);\n const view = await runStore.readRunView(params.runId);\n if (!view) {\n return {\n ok: false,\n code: 'run_not_found',\n message: 'Workflow run not found',\n httpStatus: 404,\n };\n }\n\n if (isTerminalWorkflowRunStatus(view.run.status)) {\n return { ok: true, cancelled: true, alreadyFinished: true };\n }\n\n const eventStore = new WorkflowEventStore(this.options.service.currentConfig, params.agentId);\n await eventStore.append({\n runId: params.runId,\n type: 'run_cancelled',\n payload: { reason: params.reason ?? 'Cancelled by user' },\n });\n const updated = await runStore.rebuildRunView(params.runId);\n if (updated) {\n this.options.service.emit('workflow.run.updated', { runId: params.runId, view: updated });\n void this.options.sessionBridge.handleRunViewUpdated(updated);\n }\n return { ok: true, cancelled: true };\n }\n\n createRunStore(agentId: string): WorkflowRunStore {\n const eventStore = new WorkflowEventStore(this.options.service.currentConfig, agentId);\n return new WorkflowRunStore(this.options.service.currentConfig, agentId, eventStore);\n }\n\n async readWorkflowRunView(agentId: string, runId: string) {\n return this.createRunStore(agentId).readRunView(runId);\n }\n\n private loadDefinition(definitionId: string): WorkflowDefinition | null {\n const catalog = createWorkflowCatalog();\n try {\n const loaded = catalog.load(definitionId);\n return buildWorkflowDefinition({\n name: loaded.name,\n source: loaded.source,\n script: loaded.script,\n meta: loaded.meta,\n });\n } catch {\n return null;\n }\n }\n\n private createWorkflowEngine(params: {\n eventStore: WorkflowEventStore;\n runStore: WorkflowRunStore;\n sessionKey: string;\n }): WorkflowEngine {\n const gatewayService = this.options.service;\n const runner = new DelegateSubagentRunner({\n workspace: gatewayService.currentWorkspacePath,\n bus: gatewayService.messageBusInstance,\n getDefaultModel: () => resolveModelById(gatewayService.agentService.getModelForSession(params.sessionKey)),\n getConfig: () => gatewayService.currentConfig,\n buildChildTools: (childOptions) => this.options.buildChildTools(childOptions),\n });\n\n return new WorkflowEngine({\n cwd: gatewayService.currentWorkspacePath,\n eventStore: params.eventStore,\n runStore: params.runStore,\n runner,\n resolveModelId: (modelId) => {\n const agentId = extractProfileAgentId(params.sessionKey, gatewayService.currentConfig);\n return resolveModelById(resolveModelRef(gatewayService.currentConfig, agentId, modelId));\n },\n onEventAppended: (event) => {\n gatewayService.emit('workflow.event.appended', { runId: event.runId, event });\n },\n onRunViewUpdated: (view) => {\n gatewayService.emit('workflow.run.updated', { runId: view.run.id, view });\n void this.options.sessionBridge.handleRunViewUpdated(view);\n },\n });\n }\n}\n\nfunction normalizeWorkflowRunSourceForSession(\n source: WorkflowRunSource,\n workflowSessionKey: string,\n parentSessionKey?: string,\n): WorkflowRunSource {\n if (parentSessionKey?.trim()) {\n return { kind: 'chat', sessionKey: parentSessionKey.trim() };\n }\n if (source.kind === 'webui') {\n return { ...source, sessionKey: workflowSessionKey };\n }\n if (source.kind === 'chat') {\n return source;\n }\n return source;\n}\n\nexport function buildWorkflowRunInputEnvelope(input: unknown, goal?: string): WorkflowRunInputEnvelope {\n if (isWorkflowRunInputEnvelope(input)) {\n return input;\n }\n return {\n payload: input ?? {},\n goal,\n };\n}\n\nexport function buildWorkflowRunMetadata(params: {\n definition: WorkflowDefinition;\n agentId: string;\n sessionKey: string;\n source: WorkflowRunSource;\n input: WorkflowRunInputEnvelope;\n retryOfRunId?: string;\n idempotencyKey?: string;\n}): WorkflowRunMetadata {\n return {\n sessionKey: params.sessionKey,\n triggerSource: params.source.kind,\n agentId: params.agentId,\n retryOfRunId: params.retryOfRunId,\n definition: buildWorkflowRunDefinitionSnapshot(params.definition),\n input: params.input,\n correlation: {\n idempotencyKey: params.idempotencyKey,\n },\n origin: buildWorkflowRunOrigin(params.source),\n schedule: params.source.kind === 'cron'\n ? { scheduleId: params.source.scheduleId, fireId: params.source.fireId }\n : undefined,\n };\n}\n\nexport function buildWorkflowRunDefinitionSnapshot(definition: WorkflowDefinition): WorkflowRunDefinitionSnapshot {\n return {\n id: definition.id,\n name: definition.name,\n title: definition.title,\n version: definition.version,\n source: definition.metadata.source,\n tags: [...definition.metadata.tags],\n phaseCount: definition.phases.length,\n estimatedAgents: definition.metadata.estimatedAgents,\n };\n}\n\nexport function extractWorkflowRunSessionKey(source: WorkflowRunSource): string | null {\n if ('sessionKey' in source && typeof source.sessionKey === 'string' && source.sessionKey.trim()) {\n return source.sessionKey.trim();\n }\n return null;\n}\n\nfunction buildWorkflowRunOrigin(source: WorkflowRunSource): WorkflowRunMetadata['origin'] {\n switch (source.kind) {\n case 'chat':\n return { channel: 'chat', sessionKey: source.sessionKey, messageId: source.messageId };\n case 'webui':\n return { channel: 'webui', sessionKey: source.sessionKey };\n case 'cron':\n return { channel: 'cron', scheduleId: source.scheduleId, fireId: source.fireId };\n case 'api':\n return { channel: 'api', requestId: source.requestId };\n case 'im':\n return { channel: source.channel, chatId: source.chatId, messageId: source.messageId };\n }\n}\n\nfunction isWorkflowRunInputEnvelope(input: unknown): input is WorkflowRunInputEnvelope {\n if (!input || typeof input !== 'object' || Array.isArray(input)) {\n return false;\n }\n return 'payload' in input || 'variables' in input || 'context' in input;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { WorkflowRunInputEnvelope, WorkflowRunSource } from '../domain/index.js';
|
|
2
|
+
export interface StartWorkflowRunServiceParams {
|
|
3
|
+
agentId: string;
|
|
4
|
+
definitionId: string;
|
|
5
|
+
parentSessionKey?: string;
|
|
6
|
+
input?: unknown;
|
|
7
|
+
inputEnvelope?: WorkflowRunInputEnvelope;
|
|
8
|
+
goal?: string;
|
|
9
|
+
source: WorkflowRunSource;
|
|
10
|
+
concurrency?: number;
|
|
11
|
+
maxSubagents?: number;
|
|
12
|
+
tokenBudget?: number | null;
|
|
13
|
+
retryOfRunId?: string;
|
|
14
|
+
idempotencyKey?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface StartWorkflowRunServiceResult {
|
|
17
|
+
ok: true;
|
|
18
|
+
runId: string;
|
|
19
|
+
sessionKey: string;
|
|
20
|
+
}
|
|
21
|
+
export type WorkflowRunServiceErrorCode = 'definition_not_found' | 'run_not_found' | 'invalid_state';
|
|
22
|
+
export interface WorkflowRunServiceErrorResult {
|
|
23
|
+
ok: false;
|
|
24
|
+
code: WorkflowRunServiceErrorCode;
|
|
25
|
+
message: string;
|
|
26
|
+
httpStatus: 400 | 404 | 409;
|
|
27
|
+
}
|
|
28
|
+
export type WorkflowRunServiceResult = StartWorkflowRunServiceResult | WorkflowRunServiceErrorResult;
|
|
29
|
+
export interface RetryWorkflowRunServiceParams {
|
|
30
|
+
agentId: string;
|
|
31
|
+
runId: string;
|
|
32
|
+
}
|
|
33
|
+
export interface CancelWorkflowRunServiceParams {
|
|
34
|
+
agentId: string;
|
|
35
|
+
runId: string;
|
|
36
|
+
reason?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface CancelWorkflowRunServiceResult {
|
|
39
|
+
ok: true;
|
|
40
|
+
cancelled: boolean;
|
|
41
|
+
alreadyFinished?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export type CancelWorkflowRunResult = CancelWorkflowRunServiceResult | WorkflowRunServiceErrorResult;
|
|
44
|
+
/** Minimal surface for agent/cron callers (avoids importing the service class). */
|
|
45
|
+
export interface WorkflowRunServiceLike {
|
|
46
|
+
startWorkflowRun(params: StartWorkflowRunServiceParams): Promise<WorkflowRunServiceResult>;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { GatewayWorkflowHost } from '../../gateway/gateway-workflow-host.types.js';
|
|
2
|
+
import type { WorkflowRunView } from '../domain/index.js';
|
|
3
|
+
export declare const WORKFLOW_SESSION_TYPE = "workflow";
|
|
4
|
+
export declare const WORKFLOW_RUN_LINK_CONTEXT_KIND = "workflow-run-link";
|
|
5
|
+
export interface PrepareWorkflowRunSessionParams {
|
|
6
|
+
runId: string;
|
|
7
|
+
agentId: string;
|
|
8
|
+
definitionId: string;
|
|
9
|
+
definitionTitle: string;
|
|
10
|
+
goal: string;
|
|
11
|
+
parentSessionKey?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface PrepareWorkflowRunSessionResult {
|
|
14
|
+
sessionKey: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class WorkflowSessionBridge {
|
|
17
|
+
private readonly gateway;
|
|
18
|
+
private readonly terminalPersistedRunIds;
|
|
19
|
+
constructor(gateway: GatewayWorkflowHost);
|
|
20
|
+
prepareRunSession(params: PrepareWorkflowRunSessionParams): Promise<PrepareWorkflowRunSessionResult>;
|
|
21
|
+
handleRunViewUpdated(view: WorkflowRunView): Promise<void>;
|
|
22
|
+
private persistTerminalTranscript;
|
|
23
|
+
private writeParentRunLink;
|
|
24
|
+
}
|
|
25
|
+
export declare function formatParentRunLinkText(params: {
|
|
26
|
+
definitionId: string;
|
|
27
|
+
goal: string;
|
|
28
|
+
status: WorkflowRunView['run']['status'];
|
|
29
|
+
}): string;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { appendPiTranscriptContextEntry, appendPiTranscriptMessage } from "../../session/parity/jsonl-transcript-io.js";
|
|
2
|
+
import { renderWorkflowText } from "../../agent/workflow/snapshot.js";
|
|
3
|
+
import { isTerminalWorkflowRunStatus } from "../domain/run.js";
|
|
4
|
+
import "../domain/index.js";
|
|
5
|
+
import { runViewToSnapshot } from "./run-view-to-snapshot.js";
|
|
6
|
+
import "../../session/types.js";
|
|
7
|
+
import { buildWorkflowRunSessionKey } from "./workflow-session-key.js";
|
|
8
|
+
import { randomUUID } from "node:crypto";
|
|
9
|
+
//#region src/workflows/service/workflow-session-bridge.ts
|
|
10
|
+
const WORKFLOW_SESSION_TYPE = "workflow";
|
|
11
|
+
const WORKFLOW_RUN_LINK_CONTEXT_KIND = "workflow-run-link";
|
|
12
|
+
var WorkflowSessionBridge = class {
|
|
13
|
+
terminalPersistedRunIds = /* @__PURE__ */ new Set();
|
|
14
|
+
constructor(gateway) {
|
|
15
|
+
this.gateway = gateway;
|
|
16
|
+
}
|
|
17
|
+
async prepareRunSession(params) {
|
|
18
|
+
const sessionKey = buildWorkflowRunSessionKey(params.agentId, params.runId);
|
|
19
|
+
const goalText = formatWorkflowGoalUserMessage(params.definitionId, params.goal);
|
|
20
|
+
const sessionName = truncateSessionName(params.goal.trim() || params.definitionTitle || params.definitionId);
|
|
21
|
+
const store = this.gateway.sessionIndexInstance.getStore();
|
|
22
|
+
await store.resolveTranscriptPath(sessionKey);
|
|
23
|
+
await store.updateMetadata(sessionKey, {
|
|
24
|
+
sessionType: WORKFLOW_SESSION_TYPE,
|
|
25
|
+
name: sessionName,
|
|
26
|
+
tags: ["workflow", params.definitionId],
|
|
27
|
+
customData: {
|
|
28
|
+
workflowRunId: params.runId,
|
|
29
|
+
workflowDefinitionId: params.definitionId,
|
|
30
|
+
workflowGoal: params.goal,
|
|
31
|
+
...params.parentSessionKey ? { parentSessionKey: params.parentSessionKey } : {}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const { absPath } = await store.resolveTranscriptPath(sessionKey);
|
|
35
|
+
await appendPiTranscriptMessage({
|
|
36
|
+
absPath,
|
|
37
|
+
cwd: process.cwd(),
|
|
38
|
+
sessionKey,
|
|
39
|
+
message: {
|
|
40
|
+
role: "user",
|
|
41
|
+
content: [{
|
|
42
|
+
type: "text",
|
|
43
|
+
text: goalText
|
|
44
|
+
}],
|
|
45
|
+
timestamp: Date.now()
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (params.parentSessionKey?.trim()) await this.writeParentRunLink({
|
|
49
|
+
parentSessionKey: params.parentSessionKey.trim(),
|
|
50
|
+
runId: params.runId,
|
|
51
|
+
workflowSessionKey: sessionKey,
|
|
52
|
+
definitionId: params.definitionId,
|
|
53
|
+
goal: params.goal,
|
|
54
|
+
status: "running"
|
|
55
|
+
});
|
|
56
|
+
this.gateway.emit("session.updated", {
|
|
57
|
+
key: sessionKey,
|
|
58
|
+
name: sessionName
|
|
59
|
+
});
|
|
60
|
+
return { sessionKey };
|
|
61
|
+
}
|
|
62
|
+
async handleRunViewUpdated(view) {
|
|
63
|
+
const runId = view.run.id;
|
|
64
|
+
const sessionKey = view.run.metadata?.sessionKey?.trim();
|
|
65
|
+
if (!sessionKey || !isTerminalWorkflowRunStatus(view.run.status)) return;
|
|
66
|
+
if (this.terminalPersistedRunIds.has(runId)) return;
|
|
67
|
+
this.terminalPersistedRunIds.add(runId);
|
|
68
|
+
await this.persistTerminalTranscript(sessionKey, view);
|
|
69
|
+
const parentSessionKey = readParentSessionKey(view);
|
|
70
|
+
if (parentSessionKey) await this.writeParentRunLink({
|
|
71
|
+
parentSessionKey,
|
|
72
|
+
runId,
|
|
73
|
+
workflowSessionKey: sessionKey,
|
|
74
|
+
definitionId: view.run.definitionId,
|
|
75
|
+
goal: view.run.goal,
|
|
76
|
+
status: view.run.status
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
async persistTerminalTranscript(sessionKey, view) {
|
|
80
|
+
const store = this.gateway.sessionIndexInstance.getStore();
|
|
81
|
+
const { absPath } = await store.resolveTranscriptPath(sessionKey);
|
|
82
|
+
const snapshot = runViewToSnapshot(view);
|
|
83
|
+
const toolCallId = randomUUID();
|
|
84
|
+
const envelope = {
|
|
85
|
+
content: [{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: renderWorkflowText(snapshot, view.run.status === "succeeded", { showResultPreviews: true })
|
|
88
|
+
}],
|
|
89
|
+
details: snapshot
|
|
90
|
+
};
|
|
91
|
+
const isError = view.run.status === "failed" || view.run.status === "timeout";
|
|
92
|
+
await appendPiTranscriptMessage({
|
|
93
|
+
absPath,
|
|
94
|
+
cwd: process.cwd(),
|
|
95
|
+
sessionKey,
|
|
96
|
+
message: {
|
|
97
|
+
role: "assistant",
|
|
98
|
+
content: [{
|
|
99
|
+
type: "toolCall",
|
|
100
|
+
id: toolCallId,
|
|
101
|
+
name: "workflow",
|
|
102
|
+
arguments: { name: view.run.definitionId }
|
|
103
|
+
}],
|
|
104
|
+
timestamp: Date.now()
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
await appendPiTranscriptMessage({
|
|
108
|
+
absPath,
|
|
109
|
+
cwd: process.cwd(),
|
|
110
|
+
sessionKey,
|
|
111
|
+
message: {
|
|
112
|
+
role: "toolResult",
|
|
113
|
+
toolCallId,
|
|
114
|
+
content: [{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: JSON.stringify(envelope)
|
|
117
|
+
}],
|
|
118
|
+
details: snapshot,
|
|
119
|
+
isError,
|
|
120
|
+
timestamp: Date.now()
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
await store.updateMetadata(sessionKey, { status: "active" });
|
|
124
|
+
}
|
|
125
|
+
async writeParentRunLink(params) {
|
|
126
|
+
const { absPath } = await this.gateway.sessionIndexInstance.getStore().resolveTranscriptPath(params.parentSessionKey);
|
|
127
|
+
const text = formatParentRunLinkText(params);
|
|
128
|
+
await appendPiTranscriptContextEntry({
|
|
129
|
+
absPath,
|
|
130
|
+
cwd: process.cwd(),
|
|
131
|
+
sessionKey: params.parentSessionKey,
|
|
132
|
+
entry: {
|
|
133
|
+
kind: "context",
|
|
134
|
+
id: `workflow-run-link:${params.runId}`,
|
|
135
|
+
text,
|
|
136
|
+
data: {
|
|
137
|
+
kind: WORKFLOW_RUN_LINK_CONTEXT_KIND,
|
|
138
|
+
runId: params.runId,
|
|
139
|
+
workflowSessionKey: params.workflowSessionKey,
|
|
140
|
+
definitionId: params.definitionId,
|
|
141
|
+
goal: params.goal,
|
|
142
|
+
status: params.status
|
|
143
|
+
},
|
|
144
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
function formatWorkflowGoalUserMessage(definitionId, goal) {
|
|
150
|
+
const trimmedGoal = goal.trim();
|
|
151
|
+
if (trimmedGoal) return `Run workflow \`${definitionId}\`:\n\n${trimmedGoal}`;
|
|
152
|
+
return `Run workflow \`${definitionId}\``;
|
|
153
|
+
}
|
|
154
|
+
function truncateSessionName(name) {
|
|
155
|
+
const trimmed = name.trim();
|
|
156
|
+
if (trimmed.length <= 80) return trimmed;
|
|
157
|
+
return `${trimmed.slice(0, 77)}…`;
|
|
158
|
+
}
|
|
159
|
+
function readParentSessionKey(view) {
|
|
160
|
+
if (view.run.source.kind === "chat") {
|
|
161
|
+
const originKey = view.run.source.sessionKey?.trim();
|
|
162
|
+
if (originKey) return originKey;
|
|
163
|
+
}
|
|
164
|
+
const customParent = view.run.metadata?.origin?.sessionKey?.trim();
|
|
165
|
+
if (customParent && view.run.metadata?.triggerSource === "chat") return customParent;
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
function formatParentRunLinkText(params) {
|
|
169
|
+
const label = params.goal.trim() || params.definitionId;
|
|
170
|
+
if (params.status === "running" || params.status === "queued") return `Workflow \`${params.definitionId}\` is running: ${label}`;
|
|
171
|
+
if (params.status === "succeeded") return `Workflow \`${params.definitionId}\` completed: ${label}`;
|
|
172
|
+
return `Workflow \`${params.definitionId}\` finished (${params.status}): ${label}`;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
export { WORKFLOW_RUN_LINK_CONTEXT_KIND, WORKFLOW_SESSION_TYPE, WorkflowSessionBridge, formatParentRunLinkText };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=workflow-session-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-session-bridge.js","names":[],"sources":["../../../../src/workflows/service/workflow-session-bridge.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { GatewayWorkflowHost } from '../../gateway/gateway-workflow-host.types.js';\nimport { renderWorkflowText } from '../../agent/workflow/snapshot.js';\nimport {\n appendPiTranscriptContextEntry,\n appendPiTranscriptMessage,\n} from '../../session/parity/jsonl-transcript-io.js';\nimport { SessionStatus } from '../../session/types.js';\nimport type { WorkflowRunView } from '../domain/index.js';\nimport { isTerminalWorkflowRunStatus } from '../domain/index.js';\n\nimport { runViewToSnapshot } from './run-view-to-snapshot.js';\nimport { buildWorkflowRunSessionKey } from './workflow-session-key.js';\n\nexport const WORKFLOW_SESSION_TYPE = 'workflow';\nexport const WORKFLOW_RUN_LINK_CONTEXT_KIND = 'workflow-run-link';\n\nexport interface PrepareWorkflowRunSessionParams {\n runId: string;\n agentId: string;\n definitionId: string;\n definitionTitle: string;\n goal: string;\n parentSessionKey?: string;\n}\n\nexport interface PrepareWorkflowRunSessionResult {\n sessionKey: string;\n}\n\nexport class WorkflowSessionBridge {\n private readonly terminalPersistedRunIds = new Set<string>();\n\n constructor(private readonly gateway: GatewayWorkflowHost) {}\n\n async prepareRunSession(params: PrepareWorkflowRunSessionParams): Promise<PrepareWorkflowRunSessionResult> {\n const sessionKey = buildWorkflowRunSessionKey(params.agentId, params.runId);\n const goalText = formatWorkflowGoalUserMessage(params.definitionId, params.goal);\n const sessionName = truncateSessionName(params.goal.trim() || params.definitionTitle || params.definitionId);\n\n const store = this.gateway.sessionIndexInstance.getStore();\n await store.resolveTranscriptPath(sessionKey);\n await store.updateMetadata(sessionKey, {\n sessionType: WORKFLOW_SESSION_TYPE,\n name: sessionName,\n tags: ['workflow', params.definitionId],\n customData: {\n workflowRunId: params.runId,\n workflowDefinitionId: params.definitionId,\n workflowGoal: params.goal,\n ...(params.parentSessionKey ? { parentSessionKey: params.parentSessionKey } : {}),\n },\n });\n\n const { absPath } = await store.resolveTranscriptPath(sessionKey);\n await appendPiTranscriptMessage({\n absPath,\n cwd: process.cwd(),\n sessionKey,\n message: {\n role: 'user',\n content: [{ type: 'text', text: goalText }],\n timestamp: Date.now(),\n },\n });\n\n if (params.parentSessionKey?.trim()) {\n await this.writeParentRunLink({\n parentSessionKey: params.parentSessionKey.trim(),\n runId: params.runId,\n workflowSessionKey: sessionKey,\n definitionId: params.definitionId,\n goal: params.goal,\n status: 'running',\n });\n }\n\n this.gateway.emit('session.updated', { key: sessionKey, name: sessionName });\n return { sessionKey };\n }\n\n async handleRunViewUpdated(view: WorkflowRunView): Promise<void> {\n const runId = view.run.id;\n const sessionKey = view.run.metadata?.sessionKey?.trim();\n if (!sessionKey || !isTerminalWorkflowRunStatus(view.run.status)) {\n return;\n }\n if (this.terminalPersistedRunIds.has(runId)) {\n return;\n }\n this.terminalPersistedRunIds.add(runId);\n\n await this.persistTerminalTranscript(sessionKey, view);\n\n const parentSessionKey = readParentSessionKey(view);\n if (parentSessionKey) {\n await this.writeParentRunLink({\n parentSessionKey,\n runId,\n workflowSessionKey: sessionKey,\n definitionId: view.run.definitionId,\n goal: view.run.goal,\n status: view.run.status,\n });\n }\n }\n\n private async persistTerminalTranscript(sessionKey: string, view: WorkflowRunView): Promise<void> {\n const store = this.gateway.sessionIndexInstance.getStore();\n const { absPath } = await store.resolveTranscriptPath(sessionKey);\n const snapshot = runViewToSnapshot(view);\n const toolCallId = randomUUID();\n const completed = view.run.status === 'succeeded';\n const resultText = renderWorkflowText(snapshot, completed, { showResultPreviews: true });\n const envelope = {\n content: [{ type: 'text', text: resultText }],\n details: snapshot,\n };\n const isError = view.run.status === 'failed' || view.run.status === 'timeout';\n\n await appendPiTranscriptMessage({\n absPath,\n cwd: process.cwd(),\n sessionKey,\n message: {\n role: 'assistant',\n content: [\n {\n type: 'toolCall',\n id: toolCallId,\n name: 'workflow',\n arguments: { name: view.run.definitionId },\n },\n ],\n timestamp: Date.now(),\n } as unknown as Parameters<typeof appendPiTranscriptMessage>[0]['message'],\n });\n\n await appendPiTranscriptMessage({\n absPath,\n cwd: process.cwd(),\n sessionKey,\n message: {\n role: 'toolResult',\n toolCallId,\n content: [{ type: 'text', text: JSON.stringify(envelope) }],\n details: snapshot,\n isError,\n timestamp: Date.now(),\n } as Parameters<typeof appendPiTranscriptMessage>[0]['message'],\n });\n\n await store.updateMetadata(sessionKey, {\n status: SessionStatus.ACTIVE,\n });\n }\n\n private async writeParentRunLink(params: {\n parentSessionKey: string;\n runId: string;\n workflowSessionKey: string;\n definitionId: string;\n goal: string;\n status: WorkflowRunView['run']['status'];\n }): Promise<void> {\n const store = this.gateway.sessionIndexInstance.getStore();\n const { absPath } = await store.resolveTranscriptPath(params.parentSessionKey);\n const text = formatParentRunLinkText(params);\n await appendPiTranscriptContextEntry({\n absPath,\n cwd: process.cwd(),\n sessionKey: params.parentSessionKey,\n entry: {\n kind: 'context',\n id: `workflow-run-link:${params.runId}`,\n text,\n data: {\n kind: WORKFLOW_RUN_LINK_CONTEXT_KIND,\n runId: params.runId,\n workflowSessionKey: params.workflowSessionKey,\n definitionId: params.definitionId,\n goal: params.goal,\n status: params.status,\n },\n createdAt: new Date().toISOString(),\n },\n });\n }\n}\n\nfunction formatWorkflowGoalUserMessage(definitionId: string, goal: string): string {\n const trimmedGoal = goal.trim();\n if (trimmedGoal) {\n return `Run workflow \\`${definitionId}\\`:\\n\\n${trimmedGoal}`;\n }\n return `Run workflow \\`${definitionId}\\``;\n}\n\nfunction truncateSessionName(name: string): string {\n const trimmed = name.trim();\n if (trimmed.length <= 80) return trimmed;\n return `${trimmed.slice(0, 77)}…`;\n}\n\nfunction readParentSessionKey(view: WorkflowRunView): string | null {\n if (view.run.source.kind === 'chat') {\n const originKey = view.run.source.sessionKey?.trim();\n if (originKey) return originKey;\n }\n const customParent = view.run.metadata?.origin?.sessionKey?.trim();\n if (customParent && view.run.metadata?.triggerSource === 'chat') {\n return customParent;\n }\n return null;\n}\n\nexport function formatParentRunLinkText(params: {\n definitionId: string;\n goal: string;\n status: WorkflowRunView['run']['status'];\n}): string {\n const label = params.goal.trim() || params.definitionId;\n if (params.status === 'running' || params.status === 'queued') {\n return `Workflow \\`${params.definitionId}\\` is running: ${label}`;\n }\n if (params.status === 'succeeded') {\n return `Workflow \\`${params.definitionId}\\` completed: ${label}`;\n }\n return `Workflow \\`${params.definitionId}\\` finished (${params.status}): ${label}`;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Stable webchat session key for one workflow run (`agent:{id}:webchat:…:direct:wf_{runId}`). */
|
|
2
|
+
export declare function buildWorkflowRunSessionKey(agentId: string, runId: string): string;
|
|
3
|
+
export declare function readWorkflowRunIdFromSessionCustomData(customData: Record<string, unknown> | undefined): string | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { buildSessionKey, init_session_key } from "../../routing/session-key.js";
|
|
2
|
+
//#region src/workflows/service/workflow-session-key.ts
|
|
3
|
+
init_session_key();
|
|
4
|
+
/** Stable webchat session key for one workflow run (`agent:{id}:webchat:…:direct:wf_{runId}`). */
|
|
5
|
+
function buildWorkflowRunSessionKey(agentId, runId) {
|
|
6
|
+
return buildSessionKey({
|
|
7
|
+
agentId,
|
|
8
|
+
source: "webchat",
|
|
9
|
+
accountId: "default",
|
|
10
|
+
peerKind: "direct",
|
|
11
|
+
peerId: `wf_${runId}`
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function readWorkflowRunIdFromSessionCustomData(customData) {
|
|
15
|
+
const raw = customData?.workflowRunId;
|
|
16
|
+
return typeof raw === "string" && raw.trim() ? raw.trim() : null;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { buildWorkflowRunSessionKey, readWorkflowRunIdFromSessionCustomData };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=workflow-session-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-session-key.js","names":[],"sources":["../../../../src/workflows/service/workflow-session-key.ts"],"sourcesContent":["import { buildSessionKey } from '../../routing/session-key.js';\n\n/** Stable webchat session key for one workflow run (`agent:{id}:webchat:…:direct:wf_{runId}`). */\nexport function buildWorkflowRunSessionKey(agentId: string, runId: string): string {\n return buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: `wf_${runId}`,\n });\n}\n\nexport function readWorkflowRunIdFromSessionCustomData(\n customData: Record<string, unknown> | undefined,\n): string | null {\n const raw = customData?.workflowRunId;\n return typeof raw === 'string' && raw.trim() ? raw.trim() : null;\n}\n"],"mappings":";;kBAA+D;;AAG/D,SAAgB,2BAA2B,SAAiB,OAAuB;AACjF,QAAO,gBAAgB;EACrB;EACA,QAAQ;EACR,WAAW;EACX,UAAU;EACV,QAAQ,MAAM;EACf,CAAC;;AAGJ,SAAgB,uCACd,YACe;CACf,MAAM,MAAM,YAAY;AACxB,QAAO,OAAO,QAAQ,YAAY,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG"}
|
|
@@ -49,6 +49,7 @@ var WorkflowRunStore = class {
|
|
|
49
49
|
title: view.run.title,
|
|
50
50
|
status: view.run.status,
|
|
51
51
|
source: view.run.source,
|
|
52
|
+
metadata: view.run.metadata,
|
|
52
53
|
createdAtMs: view.run.createdAtMs,
|
|
53
54
|
startedAtMs: view.run.startedAtMs,
|
|
54
55
|
completedAtMs: view.run.completedAtMs,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-store.js","names":[],"sources":["../../../../src/workflows/store/run-store.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport type { Config } from '../../config/schema.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { projectWorkflowRunView } from '../engine/projector.js';\nimport type { WorkflowRunSummary, WorkflowRunView } from '../domain/run.js';\n\nimport { WorkflowEventStore } from './event-store.js';\nimport { resolveWorkflowRunViewPath } from './paths.js';\n\nconst log = createLogger('WorkflowRunStore');\n\nexport class WorkflowRunStore {\n private readonly eventStore: WorkflowEventStore;\n\n constructor(\n private readonly config: Config,\n private readonly agentId: string,\n eventStore?: WorkflowEventStore,\n ) {\n this.eventStore = eventStore ?? new WorkflowEventStore(config, agentId);\n }\n\n async rebuildRunView(runId: string): Promise<WorkflowRunView | null> {\n const events = await this.eventStore.readRunEvents(runId);\n const view = projectWorkflowRunView(events);\n if (!view) {\n return null;\n }\n\n const viewPath = resolveWorkflowRunViewPath(this.config, this.agentId, runId);\n await writeTextAtomic(viewPath, `${JSON.stringify(view, null, 2)}\\n`);\n return view;\n }\n\n async readRunView(runId: string): Promise<WorkflowRunView | null> {\n const viewPath = resolveWorkflowRunViewPath(this.config, this.agentId, runId);\n try {\n const content = await readFile(viewPath, 'utf8');\n return JSON.parse(content) as WorkflowRunView;\n } catch (err) {\n const code = err && typeof err === 'object' && 'code' in err ? String((err as NodeJS.ErrnoException).code) : '';\n if (code !== 'ENOENT') {\n log.debug({ err, runId, viewPath }, 'Workflow run view read failed; rebuilding from events');\n }\n return this.rebuildRunView(runId);\n }\n }\n\n async listRunSummaries(limit = 50): Promise<WorkflowRunSummary[]> {\n const safeLimit = Math.min(500, Math.max(1, Math.floor(limit)));\n const runIds = await this.eventStore.listRunIds();\n const summaries: WorkflowRunSummary[] = [];\n for (const runId of runIds) {\n const view = await this.readRunView(runId);\n if (!view) {\n continue;\n }\n summaries.push({\n id: view.run.id,\n definitionId: view.run.definitionId,\n title: view.run.title,\n status: view.run.status,\n source: view.run.source,\n createdAtMs: view.run.createdAtMs,\n startedAtMs: view.run.startedAtMs,\n completedAtMs: view.run.completedAtMs,\n metrics: view.run.metrics,\n });\n }\n\n summaries.sort((left, right) => right.createdAtMs - left.createdAtMs);\n return summaries.slice(0, safeLimit);\n }\n}\n\nexport function createWorkflowRunStore(config: Config, agentId: string): WorkflowRunStore {\n return new WorkflowRunStore(config, agentId);\n}\n"],"mappings":";;;;;;;;wBAGmE;aACd;AAOrD,MAAM,MAAM,aAAa,mBAAmB;AAE5C,IAAa,mBAAb,MAA8B;CAC5B;CAEA,YACE,QACA,SACA,YACA;AAHiB,OAAA,SAAA;AACA,OAAA,UAAA;AAGjB,OAAK,aAAa,cAAc,IAAI,mBAAmB,QAAQ,QAAQ;;CAGzE,MAAM,eAAe,OAAgD;EAEnE,MAAM,OAAO,uBAAuB,MADf,KAAK,WAAW,cAAc,MAAM,CACd;AAC3C,MAAI,CAAC,KACH,QAAO;AAIT,QAAM,gBADW,2BAA2B,KAAK,QAAQ,KAAK,SAAS,MACzC,EAAE,GAAG,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC,IAAI;AACrE,SAAO;;CAGT,MAAM,YAAY,OAAgD;EAChE,MAAM,WAAW,2BAA2B,KAAK,QAAQ,KAAK,SAAS,MAAM;AAC7E,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,UAAO,KAAK,MAAM,QAAQ;WACnB,KAAK;AAEZ,QADa,OAAO,OAAO,QAAQ,YAAY,UAAU,MAAM,OAAQ,IAA8B,KAAK,GAAG,QAChG,SACX,KAAI,MAAM;IAAE;IAAK;IAAO;IAAU,EAAE,wDAAwD;AAE9F,UAAO,KAAK,eAAe,MAAM;;;CAIrC,MAAM,iBAAiB,QAAQ,IAAmC;EAChE,MAAM,YAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,CAAC,CAAC;EAC/D,MAAM,SAAS,MAAM,KAAK,WAAW,YAAY;EACjD,MAAM,YAAkC,EAAE;AAC1C,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MAAM,KAAK,YAAY,MAAM;AAC1C,OAAI,CAAC,KACH;AAEF,aAAU,KAAK;IACb,IAAI,KAAK,IAAI;IACb,cAAc,KAAK,IAAI;IACvB,OAAO,KAAK,IAAI;IAChB,QAAQ,KAAK,IAAI;IACjB,QAAQ,KAAK,IAAI;IACjB,aAAa,KAAK,IAAI;IACtB,aAAa,KAAK,IAAI;IACtB,eAAe,KAAK,IAAI;IACxB,SAAS,KAAK,IAAI;IACnB,CAAC;;AAGJ,YAAU,MAAM,MAAM,UAAU,MAAM,cAAc,KAAK,YAAY;AACrE,SAAO,UAAU,MAAM,GAAG,UAAU;;;AAIxC,SAAgB,uBAAuB,QAAgB,SAAmC;AACxF,QAAO,IAAI,iBAAiB,QAAQ,QAAQ"}
|
|
1
|
+
{"version":3,"file":"run-store.js","names":[],"sources":["../../../../src/workflows/store/run-store.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport type { Config } from '../../config/schema.js';\nimport { writeTextAtomic } from '../../infra/write-file-atomic.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { projectWorkflowRunView } from '../engine/projector.js';\nimport type { WorkflowRunSummary, WorkflowRunView } from '../domain/run.js';\n\nimport { WorkflowEventStore } from './event-store.js';\nimport { resolveWorkflowRunViewPath } from './paths.js';\n\nconst log = createLogger('WorkflowRunStore');\n\nexport class WorkflowRunStore {\n private readonly eventStore: WorkflowEventStore;\n\n constructor(\n private readonly config: Config,\n private readonly agentId: string,\n eventStore?: WorkflowEventStore,\n ) {\n this.eventStore = eventStore ?? new WorkflowEventStore(config, agentId);\n }\n\n async rebuildRunView(runId: string): Promise<WorkflowRunView | null> {\n const events = await this.eventStore.readRunEvents(runId);\n const view = projectWorkflowRunView(events);\n if (!view) {\n return null;\n }\n\n const viewPath = resolveWorkflowRunViewPath(this.config, this.agentId, runId);\n await writeTextAtomic(viewPath, `${JSON.stringify(view, null, 2)}\\n`);\n return view;\n }\n\n async readRunView(runId: string): Promise<WorkflowRunView | null> {\n const viewPath = resolveWorkflowRunViewPath(this.config, this.agentId, runId);\n try {\n const content = await readFile(viewPath, 'utf8');\n return JSON.parse(content) as WorkflowRunView;\n } catch (err) {\n const code = err && typeof err === 'object' && 'code' in err ? String((err as NodeJS.ErrnoException).code) : '';\n if (code !== 'ENOENT') {\n log.debug({ err, runId, viewPath }, 'Workflow run view read failed; rebuilding from events');\n }\n return this.rebuildRunView(runId);\n }\n }\n\n async listRunSummaries(limit = 50): Promise<WorkflowRunSummary[]> {\n const safeLimit = Math.min(500, Math.max(1, Math.floor(limit)));\n const runIds = await this.eventStore.listRunIds();\n const summaries: WorkflowRunSummary[] = [];\n for (const runId of runIds) {\n const view = await this.readRunView(runId);\n if (!view) {\n continue;\n }\n summaries.push({\n id: view.run.id,\n definitionId: view.run.definitionId,\n title: view.run.title,\n status: view.run.status,\n source: view.run.source,\n metadata: view.run.metadata,\n createdAtMs: view.run.createdAtMs,\n startedAtMs: view.run.startedAtMs,\n completedAtMs: view.run.completedAtMs,\n metrics: view.run.metrics,\n });\n }\n\n summaries.sort((left, right) => right.createdAtMs - left.createdAtMs);\n return summaries.slice(0, safeLimit);\n }\n}\n\nexport function createWorkflowRunStore(config: Config, agentId: string): WorkflowRunStore {\n return new WorkflowRunStore(config, agentId);\n}\n"],"mappings":";;;;;;;;wBAGmE;aACd;AAOrD,MAAM,MAAM,aAAa,mBAAmB;AAE5C,IAAa,mBAAb,MAA8B;CAC5B;CAEA,YACE,QACA,SACA,YACA;AAHiB,OAAA,SAAA;AACA,OAAA,UAAA;AAGjB,OAAK,aAAa,cAAc,IAAI,mBAAmB,QAAQ,QAAQ;;CAGzE,MAAM,eAAe,OAAgD;EAEnE,MAAM,OAAO,uBAAuB,MADf,KAAK,WAAW,cAAc,MAAM,CACd;AAC3C,MAAI,CAAC,KACH,QAAO;AAIT,QAAM,gBADW,2BAA2B,KAAK,QAAQ,KAAK,SAAS,MACzC,EAAE,GAAG,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC,IAAI;AACrE,SAAO;;CAGT,MAAM,YAAY,OAAgD;EAChE,MAAM,WAAW,2BAA2B,KAAK,QAAQ,KAAK,SAAS,MAAM;AAC7E,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,UAAU,OAAO;AAChD,UAAO,KAAK,MAAM,QAAQ;WACnB,KAAK;AAEZ,QADa,OAAO,OAAO,QAAQ,YAAY,UAAU,MAAM,OAAQ,IAA8B,KAAK,GAAG,QAChG,SACX,KAAI,MAAM;IAAE;IAAK;IAAO;IAAU,EAAE,wDAAwD;AAE9F,UAAO,KAAK,eAAe,MAAM;;;CAIrC,MAAM,iBAAiB,QAAQ,IAAmC;EAChE,MAAM,YAAY,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,CAAC,CAAC;EAC/D,MAAM,SAAS,MAAM,KAAK,WAAW,YAAY;EACjD,MAAM,YAAkC,EAAE;AAC1C,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,OAAO,MAAM,KAAK,YAAY,MAAM;AAC1C,OAAI,CAAC,KACH;AAEF,aAAU,KAAK;IACb,IAAI,KAAK,IAAI;IACb,cAAc,KAAK,IAAI;IACvB,OAAO,KAAK,IAAI;IAChB,QAAQ,KAAK,IAAI;IACjB,QAAQ,KAAK,IAAI;IACjB,UAAU,KAAK,IAAI;IACnB,aAAa,KAAK,IAAI;IACtB,aAAa,KAAK,IAAI;IACtB,eAAe,KAAK,IAAI;IACxB,SAAS,KAAK,IAAI;IACnB,CAAC;;AAGJ,YAAU,MAAM,MAAM,UAAU,MAAM,cAAc,KAAK,YAAY;AACrE,SAAO,UAAU,MAAM,GAAG,UAAU;;;AAIxC,SAAgB,uBAAuB,QAAgB,SAAmC;AACxF,QAAO,IAAI,iBAAiB,QAAQ,QAAQ"}
|