stageflow 0.19.0 → 0.25.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/README.md +16 -3
- package/dist/a2a/configDiscovery.d.ts +9 -0
- package/dist/a2a/configDiscovery.js +18 -0
- package/dist/a2a/contracts.d.ts +93 -0
- package/dist/a2a/contracts.js +163 -0
- package/dist/a2a/limits.d.ts +14 -0
- package/dist/a2a/limits.js +29 -0
- package/dist/a2a/registry.d.ts +44 -0
- package/dist/a2a/registry.js +159 -0
- package/dist/a2a/server.d.ts +29 -0
- package/dist/a2a/server.js +341 -0
- package/dist/a2a/service.d.ts +97 -0
- package/dist/a2a/service.js +496 -0
- package/dist/a2a/store.d.ts +106 -0
- package/dist/a2a/store.js +245 -0
- package/dist/agent/activity.d.ts +5 -0
- package/dist/agent/activityObserver.d.ts +3 -0
- package/dist/agent/activityObserver.js +6 -1
- package/dist/agent/piAdapter.js +7 -3
- package/dist/agent/port.d.ts +2 -0
- package/dist/agent/providerInspect.d.ts +19 -0
- package/dist/agent/providerInspect.js +35 -0
- package/dist/agent/streamLogRedact.d.ts +2 -0
- package/dist/agent/streamLogRedact.js +13 -0
- package/dist/cli/a2aCommand.d.ts +8 -0
- package/dist/cli/a2aCommand.js +131 -0
- package/dist/cli/artifactCommand.js +2 -2
- package/dist/cli/envelopeCommand.js +2 -2
- package/dist/cli/exportRunCommand.js +2 -2
- package/dist/cli/hostClient.d.ts +43 -0
- package/dist/cli/hostClient.js +182 -0
- package/dist/cli/providersCommand.js +5 -3
- package/dist/cli/runCommand.d.ts +6 -5
- package/dist/cli/runCommand.js +23 -31
- package/dist/cli/runOutput.d.ts +1 -1
- package/dist/cli/runStageCommand.d.ts +33 -0
- package/dist/cli/runStageCommand.js +407 -0
- package/dist/cli/runsCommand.d.ts +3 -7
- package/dist/cli/runsCommand.js +33 -94
- package/dist/cli.js +20 -5
- package/dist/config/describePipeline.d.ts +26 -0
- package/dist/config/describePipeline.js +37 -0
- package/dist/config/loadPipeline.d.ts +13 -1
- package/dist/config/loadPipeline.js +34 -4
- package/dist/config/mergePipelineIncludes.d.ts +11 -0
- package/dist/config/mergePipelineIncludes.js +75 -0
- package/dist/config/validateCatalog.d.ts +2 -2
- package/dist/config/validateCatalog.js +24 -17
- package/dist/mcp/catalogTools.js +285 -52
- package/dist/mcp/controlTools.js +77 -19
- package/dist/mcp/deps.d.ts +3 -0
- package/dist/mcp/projectMcpTools.d.ts +3 -0
- package/dist/mcp/projectMcpTools.js +25 -0
- package/dist/mcp/providerTools.d.ts +3 -0
- package/dist/mcp/providerTools.js +17 -0
- package/dist/mcp/readArtifact.d.ts +9 -0
- package/dist/mcp/readArtifact.js +11 -0
- package/dist/mcp/server.js +9 -1
- package/dist/mcp/tailStreamLog.d.ts +8 -0
- package/dist/mcp/tailStreamLog.js +28 -0
- package/dist/mcp/toolResults.d.ts +17 -0
- package/dist/mcp/toolResults.js +15 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/mcp/waitRun.js +4 -4
- package/dist/mcp/waitingGates.d.ts +1 -0
- package/dist/mcp/waitingGates.js +3 -2
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/projection/projectRun.d.ts +3 -0
- package/dist/projection/projectRun.js +7 -0
- package/dist/runstore/createStore.d.ts +10 -0
- package/dist/runstore/createStore.js +13 -4
- package/dist/runstore/port.d.ts +17 -2
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +11 -1
- package/dist/runstore/sqlite/SqliteRunStore.js +81 -26
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +6 -0
- package/dist/runstore/submission.d.ts +11 -0
- package/dist/runstore/submission.js +7 -0
- package/dist/runstore/workspaceLayout.d.ts +1 -0
- package/dist/runstore/workspaceLayout.js +3 -0
- package/dist/runtime/feedbackLoopCoordinator.d.ts +9 -1
- package/dist/runtime/feedbackLoopCoordinator.js +50 -20
- package/dist/runtime/feedbackLoopDecision.js +33 -1
- package/dist/runtime/pipelineRunner.d.ts +5 -3
- package/dist/runtime/pipelineRunner.js +6 -1
- package/dist/runtime/pipelineScheduler.js +32 -15
- package/dist/runtime/reloadRunCatalog.js +7 -1
- package/dist/runtime/resolveEnvelopeRef.d.ts +30 -0
- package/dist/runtime/resolveEnvelopeRef.js +79 -0
- package/dist/runtime/resumeReconstruct.js +2 -2
- package/dist/runtime/runManager.d.ts +24 -2
- package/dist/runtime/runManager.js +83 -19
- package/dist/runtime/settingsFile.d.ts +2 -0
- package/dist/runtime/settingsFile.js +19 -0
- package/dist/runtime/stageAttemptBootstrap.d.ts +3 -0
- package/dist/runtime/stageAttemptBootstrap.js +8 -2
- package/dist/runtime/stageStreamLog.d.ts +17 -0
- package/dist/runtime/stageStreamLog.js +89 -0
- package/dist/runtime/stageWorker.js +2 -1
- package/dist/server/bootstrap.d.ts +2 -0
- package/dist/server/bootstrap.js +22 -4
- package/dist/server/createHttpHost.js +6 -0
- package/dist/server/ensureGlobalService.d.ts +35 -0
- package/dist/server/ensureGlobalService.js +138 -0
- package/dist/server/http.d.ts +20 -1
- package/dist/server/http.js +450 -402
- package/dist/server/mcpHost.js +7 -8
- package/dist/server/operatorResults.d.ts +10 -0
- package/dist/server/operatorResults.js +24 -0
- package/dist/server/providerRoutes.d.ts +0 -6
- package/dist/server/providerRoutes.js +10 -18
- package/dist/types/pipeline.d.ts +8 -0
- package/dist/ui/assets/{index-DMVdl1qB.js → index-Da5EHU6M.js} +5 -5
- package/dist/ui/index.html +1 -1
- package/package.json +2 -1
- package/skills/stageflow/references/control-surface.md +2 -2
- package/skills/stageflow-run/SKILL.md +27 -9
- package/skills/stageflow-run/references/mcp-call.md +1 -1
- package/skills/stageflow-run/scripts/mcp-call.mjs +9 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { spawn as spawnDefault } from "node:child_process";
|
|
2
|
+
import { openSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { ensureGlobalHome } from "../project/globalHome.js";
|
|
6
|
+
import { DEFAULT_PORT } from "./createHttpHost.js";
|
|
7
|
+
/**
|
|
8
|
+
* The well-known port the global service listens on. Overridable via
|
|
9
|
+
* STAGEFLOW_SERVICE_PORT — real usage never sets this (there's exactly one
|
|
10
|
+
* global service by design), but tests use it to point a spawned `sf run`
|
|
11
|
+
* subprocess at an isolated, already-running test server instead of the
|
|
12
|
+
* real machine's global service.
|
|
13
|
+
*/
|
|
14
|
+
function resolveServicePort() {
|
|
15
|
+
const raw = process.env.STAGEFLOW_SERVICE_PORT;
|
|
16
|
+
if (raw === undefined)
|
|
17
|
+
return DEFAULT_PORT;
|
|
18
|
+
const parsed = Number(raw);
|
|
19
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_PORT;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The published `sf` binary is compiled JS (`dist/cli.js`), directly
|
|
23
|
+
* runnable as `node <entry> mcp`. In dev/test, `cliEntry` is instead raw
|
|
24
|
+
* TypeScript source (`src/cli.ts`), which plain node can't execute — route
|
|
25
|
+
* through the same tsx loader `npm run dev` already uses for that case.
|
|
26
|
+
*/
|
|
27
|
+
function resolveSpawnArgs(cliEntry) {
|
|
28
|
+
const portArgs = ["--port", String(resolveServicePort())];
|
|
29
|
+
if (!/\.(?:m|c)?ts$/.test(cliEntry)) {
|
|
30
|
+
return [cliEntry, "mcp", ...portArgs];
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const tsxCliUrl = import.meta.resolve("tsx/cli");
|
|
34
|
+
return [fileURLToPath(tsxCliUrl), cliEntry, "mcp", ...portArgs];
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return [cliEntry, "mcp", ...portArgs];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function hostBaseUrl() {
|
|
41
|
+
return `http://127.0.0.1:${resolveServicePort()}`;
|
|
42
|
+
}
|
|
43
|
+
export async function probeGlobalServiceDetailed() {
|
|
44
|
+
const ac = new AbortController();
|
|
45
|
+
const timer = setTimeout(() => ac.abort(), 1500);
|
|
46
|
+
try {
|
|
47
|
+
let res;
|
|
48
|
+
try {
|
|
49
|
+
res = await fetch(`${hostBaseUrl()}/api/health`, { signal: ac.signal });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return "unreachable";
|
|
53
|
+
}
|
|
54
|
+
if (res.status !== 200)
|
|
55
|
+
return "unhealthy";
|
|
56
|
+
try {
|
|
57
|
+
JSON.parse(await res.text());
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return "unhealthy";
|
|
61
|
+
}
|
|
62
|
+
return "up";
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function defaultProbeHost() {
|
|
69
|
+
return (await probeGlobalServiceDetailed()) === "up" ? "up" : "down";
|
|
70
|
+
}
|
|
71
|
+
const DEFAULT_POLL_INTERVAL_MS = 200;
|
|
72
|
+
const DEFAULT_TIMEOUT_MS = Number(process.env.STAGEFLOW_AUTOSTART_TIMEOUT_MS) || 10_000;
|
|
73
|
+
function sleep(ms) {
|
|
74
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Health-probe-then-spawn: makes sure a global Stageflow service is
|
|
78
|
+
* reachable at the well-known port, starting one headlessly (`<cliEntry>
|
|
79
|
+
* mcp`, detached) if nothing answers yet. No-ops if one is already up.
|
|
80
|
+
*/
|
|
81
|
+
export async function ensureGlobalService(options = {}) {
|
|
82
|
+
const probeHost = options.probeHost ?? probeGlobalServiceDetailed;
|
|
83
|
+
const spawnFn = options.spawnFn ?? spawnDefault;
|
|
84
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
85
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
86
|
+
const initial = await probeHost();
|
|
87
|
+
if (initial === "up") {
|
|
88
|
+
return { ok: true, alreadyRunning: true };
|
|
89
|
+
}
|
|
90
|
+
if (initial === "unhealthy") {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
reason: "port_occupied",
|
|
94
|
+
message: `Port ${resolveServicePort()} is already in use by a process that isn't the Stageflow service (its health check didn't return valid health JSON). Free the port and try again.`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const cliEntry = options.cliEntry ?? process.argv[1] ?? "";
|
|
98
|
+
const globalHome = ensureGlobalHome();
|
|
99
|
+
const logPath = path.join(globalHome, "service.log");
|
|
100
|
+
let logFd;
|
|
101
|
+
try {
|
|
102
|
+
logFd = openSync(logPath, "a");
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
return {
|
|
106
|
+
ok: false,
|
|
107
|
+
reason: "spawn_failed",
|
|
108
|
+
message: `Failed to open service log at ${logPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const spawnArgs = resolveSpawnArgs(cliEntry);
|
|
113
|
+
const child = spawnFn(process.execPath, spawnArgs, {
|
|
114
|
+
detached: true,
|
|
115
|
+
stdio: ["ignore", logFd, logFd],
|
|
116
|
+
});
|
|
117
|
+
child.unref();
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
reason: "spawn_failed",
|
|
123
|
+
message: `Failed to spawn the global Stageflow service: ${err instanceof Error ? err.message : String(err)}`,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
const deadline = Date.now() + timeoutMs;
|
|
127
|
+
while (Date.now() < deadline) {
|
|
128
|
+
await sleep(pollIntervalMs);
|
|
129
|
+
if ((await probeHost()) === "up") {
|
|
130
|
+
return { ok: true, alreadyRunning: false };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
reason: "timed_out",
|
|
136
|
+
message: `Timed out after ${timeoutMs}ms waiting for the global Stageflow service to become healthy. Check the log at ${logPath}.`,
|
|
137
|
+
};
|
|
138
|
+
}
|
package/dist/server/http.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import type { AgentPort } from "../agent/port.js";
|
|
|
2
2
|
import { type ProviderAuthContext } from "../agent/providerAuth.js";
|
|
3
3
|
import type { RunStoreKind } from "../runstore/createStore.js";
|
|
4
4
|
import type { RunStore } from "../runstore/port.js";
|
|
5
|
+
import type { RunManager } from "../runtime/runManager.js";
|
|
5
6
|
import type { RunChangeBus } from "../runtime/runChangeBus.js";
|
|
6
|
-
import { DEFAULT_PORT, type HttpHostEnvelope } from "./createHttpHost.js";
|
|
7
|
+
import { DEFAULT_PORT, type HttpHostEnvelope, type HttpHostRouteContext } from "./createHttpHost.js";
|
|
7
8
|
export type UiServerOptions = {
|
|
8
9
|
agent: AgentPort;
|
|
9
10
|
cwd?: string;
|
|
@@ -20,5 +21,23 @@ export type UiServerOptions = {
|
|
|
20
21
|
runChangeBus?: RunChangeBus;
|
|
21
22
|
};
|
|
22
23
|
export declare function defaultUiDistDir(): string;
|
|
24
|
+
export type OperatorRouteDeps = {
|
|
25
|
+
manager: RunManager;
|
|
26
|
+
store: RunStore;
|
|
27
|
+
cwd: string;
|
|
28
|
+
agentDir: string;
|
|
29
|
+
rootDir: string;
|
|
30
|
+
providerAuthContext: ProviderAuthContext | undefined;
|
|
31
|
+
/** Omit for a headless service (e.g. `sf mcp`) — GETs outside the API surface just 404. */
|
|
32
|
+
uiDistDir?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* The full operator-console route surface: REST API (runs, stages,
|
|
36
|
+
* catalog, settings, providers) plus, when `uiDistDir` is given, static
|
|
37
|
+
* console UI file serving. Shared by `startUiServer` (browser-facing) and
|
|
38
|
+
* `startMcpServer` (headless global-service daemon) — both need the REST
|
|
39
|
+
* API; only the former needs the UI files.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createOperatorRoutes(deps: OperatorRouteDeps): (ctx: HttpHostRouteContext) => Promise<boolean | void>;
|
|
23
42
|
export declare function startUiServer(options: UiServerOptions): Promise<HttpHostEnvelope>;
|
|
24
43
|
export { DEFAULT_PORT };
|