@agimon-ai/po-workflow 0.0.0-alpha.2 → 0.0.0-alpha.4
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 +1 -1
- package/dist/apiContracts.cjs +2 -2
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.mjs +2 -2
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/extensions/native.mjs +14 -0
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +110 -35
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.mjs +118 -43
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +151 -151
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +1 -2
- package/llms.txt +2 -2
- package/package.json +20 -19
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region generated/server.d.ts
|
|
2
|
-
export declare const facet: import("@agimon-ai/po-core/serverFacet").
|
|
2
|
+
export declare const facet: import("@agimon-ai/po-core/serverFacet").PoServerFacet;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { facet as default };
|
|
5
5
|
//# sourceMappingURL=server.d.mts.map
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { n as resolveWorkflowEntry, r as validateWorkflowLaunch, t as parseWorkflowLaunchCommand } from "../workflowLaunchCommand-GGqimmTC.mjs";
|
|
2
2
|
import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/serverFacet";
|
|
3
3
|
import { composeRootHooks, defineChannel, defineRoot, defineRoutedContribution } from "@agimon-ai/po-core/extensionFile";
|
|
4
|
-
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
6
6
|
import path, { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
|
-
import { BACKGROUND_WORK_HOLDING_PROVIDERS,
|
|
7
|
+
import { BACKGROUND_WORK_HOLDING_PROVIDERS, PO_BACKGROUND_WORK_SERVICE, holdsSettledSession, readPoBackgroundWorkService } from "@agimon-ai/po-core/backgroundWork";
|
|
8
8
|
import { SUBAGENT_PARENT_SESSION_ENV, readChildProcessContext, resolveRootSessionId } from "@agimon-ai/po-core/childProcess";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { PO_NARRATION_SERVICE, createNarrationRequest, requirePoNarrationService } from "@agimon-ai/po-core/narration";
|
|
10
|
+
import { PO_NOTIFICATION_ENTRY_TYPE, createPoNotificationEntryData } from "@agimon-ai/po-core/notification";
|
|
11
|
+
import { createPoReadinessCoordinator, readPoReadinessCoordinator } from "@agimon-ai/po-core/readiness";
|
|
12
12
|
import { defineMinorMode, serverMinorModes } from "@agimon-ai/po-minor-mode";
|
|
13
|
-
import {
|
|
13
|
+
import { createPoTelemetry } from "@agimon-ai/po-telemetry";
|
|
14
14
|
import { NativeTerminalService, WORKFLOW_DECISION_FILE_ENV, WORKFLOW_DECISION_STEERING_ENV, WORKFLOW_DECISION_STEERING_HOST, WorkflowRegistryService, WorkflowTerminalService, connectNativeTerminal, createEmbeddedWorkflowFeature, diagnoseWorkflow, gateStepDecision, readStepDecision, readWorkflowCatalog, readWorkflowProgress, serveNativeTerminal, summarizeWorkflow, summarizeWorkflowProgress, terminalSocketPath } from "@agimon-ai/workflow-mcp";
|
|
15
15
|
import { z } from "zod";
|
|
16
16
|
import fs, { existsSync, statSync } from "node:fs";
|
|
17
|
-
import { WORKFLOW_STEP_SESSION_PROVENANCE } from "@agimon-ai/po-core/hubChannel";
|
|
17
|
+
import { HOME_ENTITY_LIMIT, WORKFLOW_STEP_SESSION_PROVENANCE } from "@agimon-ai/po-core/hubChannel";
|
|
18
18
|
import { execFile } from "node:child_process";
|
|
19
19
|
import { Readable } from "node:stream";
|
|
20
|
-
import {
|
|
20
|
+
import { poApiCallerFrom } from "@agimon-ai/po-core/packageApi";
|
|
21
21
|
import { Hono } from "hono";
|
|
22
22
|
import { streamSSE } from "hono/streaming";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
@@ -178,9 +178,9 @@ function registerRunProvider(ctx) {
|
|
|
178
178
|
let items = [];
|
|
179
179
|
let provider;
|
|
180
180
|
let disposed = false;
|
|
181
|
-
ctx.inject([
|
|
181
|
+
ctx.inject([PO_BACKGROUND_WORK_SERVICE], (serviceContext) => {
|
|
182
182
|
if (disposed) return void 0;
|
|
183
|
-
const service =
|
|
183
|
+
const service = readPoBackgroundWorkService(serviceContext);
|
|
184
184
|
if (!service) return void 0;
|
|
185
185
|
const registration = service.register({
|
|
186
186
|
provider: PROVIDER_NAME,
|
|
@@ -940,14 +940,14 @@ const PENDING_LINE_LIMIT = 500;
|
|
|
940
940
|
const STOP_TIMEOUT_MS = 1e4;
|
|
941
941
|
const SESSION_CLOSED_REASON = "The session that runs this workflow closed.";
|
|
942
942
|
const RUNNING_STAGE$1 = "running";
|
|
943
|
-
const LAUNCH_REQUESTED_EVENT = "
|
|
944
|
-
const RUN_STARTED_EVENT = "
|
|
945
|
-
const RUN_FINISHED_EVENT = "
|
|
946
|
-
const RUN_FAILED_EVENT = "
|
|
947
|
-
const ENGINE_ERROR_EVENT = "
|
|
948
|
-
const ENGINE_WARNING_EVENT = "
|
|
949
|
-
const RUN_LOG_FAILED_EVENT = "
|
|
950
|
-
const RUN_STOP_FAILED_EVENT = "
|
|
943
|
+
const LAUNCH_REQUESTED_EVENT = "po_workflow.launch_requested";
|
|
944
|
+
const RUN_STARTED_EVENT = "po_workflow.run_started";
|
|
945
|
+
const RUN_FINISHED_EVENT = "po_workflow.run_finished";
|
|
946
|
+
const RUN_FAILED_EVENT = "po_workflow.run_failed";
|
|
947
|
+
const ENGINE_ERROR_EVENT = "po_workflow.engine_error";
|
|
948
|
+
const ENGINE_WARNING_EVENT = "po_workflow.engine_warning";
|
|
949
|
+
const RUN_LOG_FAILED_EVENT = "po_workflow.run_log_failed";
|
|
950
|
+
const RUN_STOP_FAILED_EVENT = "po_workflow.run_stop_failed";
|
|
951
951
|
function delay$1(ms) {
|
|
952
952
|
return new Promise((settle) => {
|
|
953
953
|
setTimeout(settle, ms).unref?.();
|
|
@@ -1179,12 +1179,12 @@ const BUSY_RETRY_MS = 2e3;
|
|
|
1179
1179
|
const RELEASE_TIMEOUT_MS = 1e4;
|
|
1180
1180
|
/** What the runtime says when a turn is already running; the reminder then waits for it. */
|
|
1181
1181
|
const BUSY_SESSION_PATTERN = /\bbusy\b|LaneBusy/i;
|
|
1182
|
-
const STEP_SESSION_STARTED_EVENT = "
|
|
1183
|
-
const STEP_SESSION_FAILED_EVENT = "
|
|
1184
|
-
const STEP_REMINDER_EVENT = "
|
|
1185
|
-
const STEP_WAITING_EVENT = "
|
|
1186
|
-
const STEP_SESSION_RELEASE_FAILED_EVENT = "
|
|
1187
|
-
const STEP_PANE_FAILED_EVENT = "
|
|
1182
|
+
const STEP_SESSION_STARTED_EVENT = "po_workflow.step_session_started";
|
|
1183
|
+
const STEP_SESSION_FAILED_EVENT = "po_workflow.step_session_failed";
|
|
1184
|
+
const STEP_REMINDER_EVENT = "po_workflow.step_reminder";
|
|
1185
|
+
const STEP_WAITING_EVENT = "po_workflow.step_waiting";
|
|
1186
|
+
const STEP_SESSION_RELEASE_FAILED_EVENT = "po_workflow.step_session_release_failed";
|
|
1187
|
+
const STEP_PANE_FAILED_EVENT = "po_workflow.step_pane_failed";
|
|
1188
1188
|
const PO_KEYS = new Set(PO_RUN_CONFIG_KEYS);
|
|
1189
1189
|
/**
|
|
1190
1190
|
* A step's `runConfig`, validated against the keys Po understands.
|
|
@@ -2346,7 +2346,7 @@ function createWorkflowHubApi(options = {}) {
|
|
|
2346
2346
|
return context.json({ deleted: true });
|
|
2347
2347
|
});
|
|
2348
2348
|
app.post(routes.openRunDirectory.path, async (context) => {
|
|
2349
|
-
if (
|
|
2349
|
+
if (poApiCallerFrom(context.req.raw.headers)?.locality !== "local") return context.json({ error: "Opening Finder is only available on the host." }, 403);
|
|
2350
2350
|
const workspace = context.req.param("workspace");
|
|
2351
2351
|
const runKey = context.req.param("runKey");
|
|
2352
2352
|
const record = await runOf(workspace, runKey);
|
|
@@ -3045,8 +3045,8 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3045
3045
|
let deliveryRetry;
|
|
3046
3046
|
const catalogDeps = defaultCatalogDeps();
|
|
3047
3047
|
const catalogReader = createWorkflowCatalogReader(catalogDeps);
|
|
3048
|
-
const telemetry =
|
|
3049
|
-
serviceName: "
|
|
3048
|
+
const telemetry = createPoTelemetry({
|
|
3049
|
+
serviceName: "po-workflow",
|
|
3050
3050
|
packageName: SOURCE,
|
|
3051
3051
|
cwd: host.context.cwd,
|
|
3052
3052
|
env: host.context.environment,
|
|
@@ -3060,12 +3060,12 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3060
3060
|
parentSessionId: host.context.sessionContext?.parentSessionId,
|
|
3061
3061
|
publishActivity: (activity) => serverHost.context.publishActivity?.(activity),
|
|
3062
3062
|
postNotice: async (notice) => {
|
|
3063
|
-
const data =
|
|
3063
|
+
const data = createPoNotificationEntryData({
|
|
3064
3064
|
title: notice.title,
|
|
3065
3065
|
body: notice.body,
|
|
3066
3066
|
level: notice.level
|
|
3067
3067
|
});
|
|
3068
|
-
if (data !== void 0) await host.context.session.appendCustomEntry(
|
|
3068
|
+
if (data !== void 0) await host.context.session.appendCustomEntry(PO_NOTIFICATION_ENTRY_TYPE, data);
|
|
3069
3069
|
},
|
|
3070
3070
|
isIdle: async () => {
|
|
3071
3071
|
const activity = await host.context.session.activity();
|
|
@@ -3077,7 +3077,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3077
3077
|
}
|
|
3078
3078
|
}) : void 0;
|
|
3079
3079
|
const reportLifecycleFailure = (error) => {
|
|
3080
|
-
telemetry.recordWarning("
|
|
3080
|
+
telemetry.recordWarning("po_workflow.session_lifecycle_failed", error);
|
|
3081
3081
|
};
|
|
3082
3082
|
/** This session's runs, published to its panel and counted as its background work. */
|
|
3083
3083
|
const publishRuns = (executionContext) => {
|
|
@@ -3109,9 +3109,9 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3109
3109
|
const request = createNarrationRequest(text);
|
|
3110
3110
|
if (request === void 0 || narration === void 0) return;
|
|
3111
3111
|
try {
|
|
3112
|
-
Promise.resolve(narration.request(request)).catch((error) => telemetry.recordWarning("
|
|
3112
|
+
Promise.resolve(narration.request(request)).catch((error) => telemetry.recordWarning("po_workflow.narration_failed", error));
|
|
3113
3113
|
} catch (error) {
|
|
3114
|
-
telemetry.recordWarning("
|
|
3114
|
+
telemetry.recordWarning("po_workflow.narration_failed", error);
|
|
3115
3115
|
}
|
|
3116
3116
|
} }, view, previous, previous === void 0 && (!Number.isFinite(startedAt) || startedAt >= sessionStartedAt));
|
|
3117
3117
|
}
|
|
@@ -3159,7 +3159,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3159
3159
|
} catch (error) {
|
|
3160
3160
|
if (disposed) return;
|
|
3161
3161
|
pending.attempts += 1;
|
|
3162
|
-
await telemetry.recordError("
|
|
3162
|
+
await telemetry.recordError("po_workflow.terminal_delivery_failed", error, { "workflow.pending_terminal_count": pendingCompletions.size });
|
|
3163
3163
|
}
|
|
3164
3164
|
}
|
|
3165
3165
|
for (const quiet of [true, false]) {
|
|
@@ -3207,12 +3207,12 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3207
3207
|
deliveredCompletions.add(identity);
|
|
3208
3208
|
pendingCompletions.delete(identity);
|
|
3209
3209
|
}
|
|
3210
|
-
for (const outcome of batch.outcomes) telemetry.recordEvent("
|
|
3210
|
+
for (const outcome of batch.outcomes) telemetry.recordEvent("po_workflow.run_transition", { outcome });
|
|
3211
3211
|
publishRuns(host.context);
|
|
3212
3212
|
} catch (error) {
|
|
3213
3213
|
if (disposed) return;
|
|
3214
3214
|
batch.attempts += 1;
|
|
3215
|
-
await telemetry.recordError("
|
|
3215
|
+
await telemetry.recordError("po_workflow.terminal_delivery_failed", error, { "workflow.pending_terminal_count": pendingCompletions.size });
|
|
3216
3216
|
}
|
|
3217
3217
|
}
|
|
3218
3218
|
})().finally(() => {
|
|
@@ -3267,7 +3267,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3267
3267
|
publishRuns(executionContext);
|
|
3268
3268
|
deliverCompletions().then(() => done?.(activeRunCount > 0 || pendingCompletions.size > 0));
|
|
3269
3269
|
} catch (error) {
|
|
3270
|
-
telemetry.recordWarning("
|
|
3270
|
+
telemetry.recordWarning("po_workflow.publish_failed", error);
|
|
3271
3271
|
}
|
|
3272
3272
|
}, RUNS_PUBLISH_DEBOUNCE_MS);
|
|
3273
3273
|
runsTimer.unref?.();
|
|
@@ -3470,7 +3470,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3470
3470
|
if (owned.length === 0 || !owned.every(succeeded)) return;
|
|
3471
3471
|
if (!owned.some((run) => runLaunchedBySession(run, host.context.sessionId))) return;
|
|
3472
3472
|
await sessionService.release(source);
|
|
3473
|
-
telemetry.recordEvent("
|
|
3473
|
+
telemetry.recordEvent("po_workflow.session_released", { outcome: "released" });
|
|
3474
3474
|
};
|
|
3475
3475
|
const stopReleaseRequests = communication?.subscribe(WORKFLOW_SESSION_RELEASE_TYPE, (source) => {
|
|
3476
3476
|
releaseWorkflowSession(source).catch(reportLifecycleFailure);
|
|
@@ -3597,7 +3597,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3597
3597
|
return launchFromApi(parameters);
|
|
3598
3598
|
})],
|
|
3599
3599
|
async onStart() {
|
|
3600
|
-
readiness ??= ownedReadiness =
|
|
3600
|
+
readiness ??= ownedReadiness = createPoReadinessCoordinator({ notify: (notice) => {
|
|
3601
3601
|
host.context.client.notify({
|
|
3602
3602
|
body: `${SOURCE} initialization ${notice.state}: ${notice.error?.message ?? notice.diagnostics.join("; ")}`,
|
|
3603
3603
|
level: "warning"
|
|
@@ -3616,9 +3616,9 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3616
3616
|
},
|
|
3617
3617
|
services: [
|
|
3618
3618
|
(context) => {
|
|
3619
|
-
readiness =
|
|
3620
|
-
context.inject([
|
|
3621
|
-
const service =
|
|
3619
|
+
readiness = readPoReadinessCoordinator(context);
|
|
3620
|
+
context.inject([PO_NARRATION_SERVICE], (serviceContext) => {
|
|
3621
|
+
const service = requirePoNarrationService(serviceContext);
|
|
3622
3622
|
narration = service;
|
|
3623
3623
|
return () => {
|
|
3624
3624
|
if (narration === service) narration = void 0;
|
|
@@ -3669,7 +3669,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3669
3669
|
try {
|
|
3670
3670
|
const activity = await execution.session.activity();
|
|
3671
3671
|
if (disposed || !activity.isIdle || activity.hasPendingMessages) return;
|
|
3672
|
-
const snapshot = serviceContext === void 0 ? void 0 :
|
|
3672
|
+
const snapshot = serviceContext === void 0 ? void 0 : readPoBackgroundWorkService(serviceContext)?.snapshot(execution.sessionId);
|
|
3673
3673
|
if (snapshot === void 0 || snapshot.items.some(holdsSettledSession) || snapshot.errors.some((error) => BACKGROUND_WORK_HOLDING_PROVIDERS.includes(error.provider))) return;
|
|
3674
3674
|
const gate = await gateStepDecision(environment);
|
|
3675
3675
|
if (disposed || gate.action !== "block") return;
|
|
@@ -3904,7 +3904,7 @@ function createWorkflowServerRuntime(host, serverHost) {
|
|
|
3904
3904
|
dryRun: input.dryRun,
|
|
3905
3905
|
runner: input.runner
|
|
3906
3906
|
}));
|
|
3907
|
-
telemetry.recordEvent("
|
|
3907
|
+
telemetry.recordEvent("po_workflow.recovery_evidence_requested", { outcome: "requested" });
|
|
3908
3908
|
const sections = [];
|
|
3909
3909
|
for (const name of [
|
|
3910
3910
|
"changelog.md",
|
|
@@ -4146,6 +4146,81 @@ function createWorkflowsChannel(options = {}) {
|
|
|
4146
4146
|
}
|
|
4147
4147
|
};
|
|
4148
4148
|
return {
|
|
4149
|
+
homeFor(scope) {
|
|
4150
|
+
if (!scopes.has(scope.sessionId)) return {
|
|
4151
|
+
coverage: "unavailable",
|
|
4152
|
+
entities: []
|
|
4153
|
+
};
|
|
4154
|
+
const runs = [];
|
|
4155
|
+
const slices = delegated.get(scope.sessionId);
|
|
4156
|
+
if ((slices?.size ?? 0) > HOME_ENTITY_LIMIT) return {
|
|
4157
|
+
coverage: "partial",
|
|
4158
|
+
entities: []
|
|
4159
|
+
};
|
|
4160
|
+
for (const slice of [own.get(scope.sessionId) ?? [], ...slices?.values() ?? []]) {
|
|
4161
|
+
if (runs.length + slice.length > HOME_ENTITY_LIMIT) return {
|
|
4162
|
+
coverage: "partial",
|
|
4163
|
+
entities: []
|
|
4164
|
+
};
|
|
4165
|
+
for (const run of slice) runs.push(run);
|
|
4166
|
+
}
|
|
4167
|
+
const entities = /* @__PURE__ */ new Map();
|
|
4168
|
+
let partial = false;
|
|
4169
|
+
let remaining = HOME_ENTITY_LIMIT;
|
|
4170
|
+
for (const run of runs) {
|
|
4171
|
+
const owner = run.ownerSessionId ?? scope.sessionId;
|
|
4172
|
+
const refs = /* @__PURE__ */ new Set([owner]);
|
|
4173
|
+
if (run.launcherSessionId) refs.add(run.launcherSessionId);
|
|
4174
|
+
if (run.jobs.length > remaining) {
|
|
4175
|
+
partial = true;
|
|
4176
|
+
break;
|
|
4177
|
+
}
|
|
4178
|
+
remaining -= run.jobs.length;
|
|
4179
|
+
let complete = true;
|
|
4180
|
+
for (const job of run.jobs) {
|
|
4181
|
+
if (job.steps.length > remaining) {
|
|
4182
|
+
complete = false;
|
|
4183
|
+
break;
|
|
4184
|
+
}
|
|
4185
|
+
remaining -= job.steps.length;
|
|
4186
|
+
for (const step of job.steps) {
|
|
4187
|
+
if (step.ref?.kind === "session") refs.add(step.ref.id);
|
|
4188
|
+
if (refs.size > 65) {
|
|
4189
|
+
complete = false;
|
|
4190
|
+
break;
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
if (!complete) break;
|
|
4194
|
+
}
|
|
4195
|
+
if (!complete) {
|
|
4196
|
+
partial = true;
|
|
4197
|
+
break;
|
|
4198
|
+
}
|
|
4199
|
+
const id = createHash("sha256").update(JSON.stringify([
|
|
4200
|
+
run.workspace,
|
|
4201
|
+
run.runId ?? run.runKey,
|
|
4202
|
+
run.startedAt
|
|
4203
|
+
])).digest("hex");
|
|
4204
|
+
if (entities.has(id)) continue;
|
|
4205
|
+
if (entities.size >= HOME_ENTITY_LIMIT) {
|
|
4206
|
+
partial = true;
|
|
4207
|
+
continue;
|
|
4208
|
+
}
|
|
4209
|
+
entities.set(id, {
|
|
4210
|
+
id,
|
|
4211
|
+
kind: run.outcome === "interrupted" ? "paused" : run.stage === "error" || run.outcome === "failed" ? "failure" : run.stale === true ? "blocked" : run.stage === "completed" ? "completed" : run.executionState === "paused" || run.executionState === "pause_requested" ? "paused" : "running",
|
|
4212
|
+
title: (run.displayName.trim() || run.runKey).slice(0, 160),
|
|
4213
|
+
...run.errorMessage?.trim() || (run.stale === true ? run.staleReason?.trim() || "Recorded workflow is stale." : void 0) ? { detail: (run.errorMessage?.trim() || run.staleReason?.trim() || "Recorded workflow is stale.").slice(0, 320) } : {},
|
|
4214
|
+
updatedAt: run.finishedAt ?? run.startedAt,
|
|
4215
|
+
sessionId: owner,
|
|
4216
|
+
relatedSessionIds: [...refs].filter((id) => id !== owner)
|
|
4217
|
+
});
|
|
4218
|
+
}
|
|
4219
|
+
return {
|
|
4220
|
+
coverage: partial ? "partial" : "ready",
|
|
4221
|
+
entities: [...entities.values()]
|
|
4222
|
+
};
|
|
4223
|
+
},
|
|
4149
4224
|
payloadFor(scope) {
|
|
4150
4225
|
return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : void 0;
|
|
4151
4226
|
},
|