@sapiom/orchestration-core 0.2.0 → 0.3.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @sapiom/orchestration-core
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [5c974b1]
8
+ - @sapiom/tools@0.5.0
9
+ - @sapiom/orchestration@0.1.9
10
+
11
+ ## 0.3.0
12
+
13
+ ### Minor Changes
14
+
15
+ - e17b2d1: `scaffold` now initializes a git repository with an initial commit, so a freshly scaffolded project is immediately deployable (deploy requires a repo with at least one commit). Best-effort: if `git` is unavailable the project is left uninitialized. `ScaffoldResult` gains `gitInitialized`.
16
+
17
+ Adds `waitForExecution` (and `isExecutionTerminal`) to poll an execution until it reaches a terminal state, settles on a pause that needs a signal, or a wait budget elapses — so callers don't hand-roll a poll loop. The `sapiom_dev_orchestrations_inspect` MCP tool gains opt-in `wait` / `maxWaitSeconds` options that use it and return `done` / `waiting` / `hint`; a non-blocking inspect of a still-running execution now also hints to use `wait`.
18
+
19
+ Fixes `sapiom_dev_orchestrations_link`: omitting `name` no longer sends an empty name (which the gateway rejected). It now defaults to the orchestration's name read from `index.ts` (matching `defineOrchestration({ name })`), and returns a clear error if no name is available.
20
+
21
+ ### Patch Changes
22
+
23
+ - e17b2d1: **BREAKING (`@sapiom/tools`):** align the coding-run resume payload with the shape a resumed step actually receives. `CodingResultPayload` now carries `executionEnvironment: { type, id } | null` instead of `sandbox: { name, workspaceRoot }`. Re-attach a resumed run's sandbox with `ctx.sapiom.sandboxes.attach(result.executionEnvironment.id)` (for a `blaxel_sandbox`).
24
+
25
+ Adds `codingResultSchema` (runtime validation of the resume payload), `toResumePayload`, `ExecutionEnvironmentRef`, and `EXECUTION_ENVIRONMENT_BLAXEL_SANDBOX`. The stub client now emits the same payload shape a resumed step receives, so a step written against the local loop runs identically once deployed.
26
+
27
+ The `coding-pause` template and its guidance are updated to the new shape.
28
+
29
+ - Updated dependencies [e17b2d1]
30
+ - @sapiom/tools@0.4.0
31
+ - @sapiom/orchestration@0.1.8
32
+
3
33
  ## 0.2.0
4
34
 
5
35
  ### Minor Changes
@@ -1,29 +1,29 @@
1
- export { OrchestrationError } from './errors.js';
2
- export type { StructuredError } from './errors.js';
3
- export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST } from './client.js';
4
- export type { ClientOptions, GatewayErrorBody } from './client.js';
5
- export { readConfig, requireConfig, writeConfig, CONFIG_FILE } from './config.js';
6
- export type { SapiomConfig } from './config.js';
7
- export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE } from './scaffold.js';
8
- export type { ScaffoldOptions, ScaffoldResult, ResolvedVersions } from './scaffold.js';
9
- export { check } from './check.js';
10
- export type { CheckOptions, CheckResult } from './check.js';
11
- export { link } from './link.js';
12
- export type { LinkOptions, LinkResult, DefinitionSummary } from './link.js';
13
- export { deploy } from './deploy.js';
14
- export type { DeployOptions, DeployResult } from './deploy.js';
15
- export { run, parseJsonInput } from './run.js';
16
- export type { RunOptions, RunResult } from './run.js';
17
- export { inspect, listExecutions, inspectBuild } from './inspect.js';
18
- export type { InspectOptions, InspectResult, ListExecutionsResult, InspectBuildOptions, InspectBuildResult, ExecutionDetail, StepRecord, BuildDetail, } from './inspect.js';
19
- export { signal, parseSignalPayload } from './signal.js';
20
- export type { SignalOptions, SignalResult } from './signal.js';
21
- export { assertDeployable, pushHead } from './git.js';
22
- export { parseStubFile, STUB_FILE_VERSION } from './local/stubs.js';
23
- export type { StubFile, StepStubs, StubResponse } from './local/stubs.js';
24
- export { runLocal, runLocalFromDir, STUBS_FILE } from './local/run-local.js';
25
- export type { RunLocalOptions, LocalRunResult, LocalRunOutcome } from './local/run-local.js';
26
- export { loadDefinition } from './local/load.js';
27
- export type { LoadedDefinition } from './local/load.js';
28
- export { LocalStubDispatcher } from './local/dispatcher.js';
29
- export type { LocalStepTrace, LogEntry } from './local/dispatcher.js';
1
+ export { OrchestrationError } from "./errors.js";
2
+ export type { StructuredError } from "./errors.js";
3
+ export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST, } from "./client.js";
4
+ export type { ClientOptions, GatewayErrorBody } from "./client.js";
5
+ export { readConfig, requireConfig, writeConfig, CONFIG_FILE, } from "./config.js";
6
+ export type { SapiomConfig } from "./config.js";
7
+ export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE, } from "./scaffold.js";
8
+ export type { ScaffoldOptions, ScaffoldResult, ResolvedVersions, } from "./scaffold.js";
9
+ export { check } from "./check.js";
10
+ export type { CheckOptions, CheckResult } from "./check.js";
11
+ export { link } from "./link.js";
12
+ export type { LinkOptions, LinkResult, DefinitionSummary } from "./link.js";
13
+ export { deploy } from "./deploy.js";
14
+ export type { DeployOptions, DeployResult } from "./deploy.js";
15
+ export { run, parseJsonInput } from "./run.js";
16
+ export type { RunOptions, RunResult } from "./run.js";
17
+ export { inspect, listExecutions, inspectBuild, waitForExecution, isExecutionTerminal, } from "./inspect.js";
18
+ export type { InspectOptions, InspectResult, ListExecutionsResult, InspectBuildOptions, InspectBuildResult, ExecutionDetail, StepRecord, BuildDetail, WaitForExecutionOptions, WaitForExecutionResult, WaitStopReason, } from "./inspect.js";
19
+ export { signal, parseSignalPayload } from "./signal.js";
20
+ export type { SignalOptions, SignalResult } from "./signal.js";
21
+ export { assertDeployable, pushHead } from "./git.js";
22
+ export { parseStubFile, STUB_FILE_VERSION } from "./local/stubs.js";
23
+ export type { StubFile, StepStubs, StubResponse } from "./local/stubs.js";
24
+ export { runLocal, runLocalFromDir, STUBS_FILE } from "./local/run-local.js";
25
+ export type { RunLocalOptions, LocalRunResult, LocalRunOutcome, } from "./local/run-local.js";
26
+ export { loadDefinition } from "./local/load.js";
27
+ export type { LoadedDefinition } from "./local/load.js";
28
+ export { LocalStubDispatcher } from "./local/dispatcher.js";
29
+ export type { LocalStepTrace, LogEntry } from "./local/dispatcher.js";
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LocalStubDispatcher = exports.loadDefinition = exports.STUBS_FILE = exports.runLocalFromDir = exports.runLocal = exports.STUB_FILE_VERSION = exports.parseStubFile = exports.pushHead = exports.assertDeployable = exports.parseSignalPayload = exports.signal = exports.inspectBuild = exports.listExecutions = exports.inspect = exports.parseJsonInput = exports.run = exports.deploy = exports.link = exports.check = exports.DEFAULT_TEMPLATE = exports.listTemplates = exports.resolveTemplate = exports.resolveVersions = exports.scaffold = exports.CONFIG_FILE = exports.writeConfig = exports.requireConfig = exports.readConfig = exports.DEFAULT_WORKFLOWS_HOST = exports.createClient = exports.GatewayClient = exports.OrchestrationError = void 0;
3
+ exports.LocalStubDispatcher = exports.loadDefinition = exports.STUBS_FILE = exports.runLocalFromDir = exports.runLocal = exports.STUB_FILE_VERSION = exports.parseStubFile = exports.pushHead = exports.assertDeployable = exports.parseSignalPayload = exports.signal = exports.isExecutionTerminal = exports.waitForExecution = exports.inspectBuild = exports.listExecutions = exports.inspect = exports.parseJsonInput = exports.run = exports.deploy = exports.link = exports.check = exports.DEFAULT_TEMPLATE = exports.listTemplates = exports.resolveTemplate = exports.resolveVersions = exports.scaffold = exports.CONFIG_FILE = exports.writeConfig = exports.requireConfig = exports.readConfig = exports.DEFAULT_WORKFLOWS_HOST = exports.createClient = exports.GatewayClient = exports.OrchestrationError = void 0;
4
4
  var errors_js_1 = require("./errors.js");
5
5
  Object.defineProperty(exports, "OrchestrationError", { enumerable: true, get: function () { return errors_js_1.OrchestrationError; } });
6
6
  var client_js_1 = require("./client.js");
@@ -31,6 +31,8 @@ var inspect_js_1 = require("./inspect.js");
31
31
  Object.defineProperty(exports, "inspect", { enumerable: true, get: function () { return inspect_js_1.inspect; } });
32
32
  Object.defineProperty(exports, "listExecutions", { enumerable: true, get: function () { return inspect_js_1.listExecutions; } });
33
33
  Object.defineProperty(exports, "inspectBuild", { enumerable: true, get: function () { return inspect_js_1.inspectBuild; } });
34
+ Object.defineProperty(exports, "waitForExecution", { enumerable: true, get: function () { return inspect_js_1.waitForExecution; } });
35
+ Object.defineProperty(exports, "isExecutionTerminal", { enumerable: true, get: function () { return inspect_js_1.isExecutionTerminal; } });
34
36
  var signal_js_1 = require("./signal.js");
35
37
  Object.defineProperty(exports, "signal", { enumerable: true, get: function () { return signal_js_1.signal; } });
36
38
  Object.defineProperty(exports, "parseSignalPayload", { enumerable: true, get: function () { return signal_js_1.parseSignalPayload; } });
@@ -1,4 +1,4 @@
1
- import { GatewayClient } from './client.js';
1
+ import { GatewayClient } from "./client.js";
2
2
  export interface StepRecord {
3
3
  stepName: string;
4
4
  attempt: number;
@@ -12,6 +12,7 @@ export interface ExecutionDetail {
12
12
  id: string;
13
13
  status: string;
14
14
  currentStep?: string | null;
15
+ pausedSignalName?: string | null;
15
16
  error?: unknown;
16
17
  steps?: StepRecord[];
17
18
  }
@@ -27,6 +28,22 @@ export interface InspectResult {
27
28
  execution: ExecutionDetail;
28
29
  }
29
30
  export declare function inspect(opts: InspectOptions, client: GatewayClient): Promise<InspectResult>;
31
+ export declare function isExecutionTerminal(status: string): boolean;
32
+ export type WaitStopReason = "terminal" | "needs-signal" | "timeout";
33
+ export interface WaitForExecutionOptions {
34
+ executionId: string;
35
+ maxWaitMs?: number;
36
+ pollMs?: number;
37
+ autoResumeSignals?: string[];
38
+ sleep?: (ms: number) => Promise<void>;
39
+ now?: () => number;
40
+ }
41
+ export interface WaitForExecutionResult {
42
+ execution: ExecutionDetail;
43
+ reason: WaitStopReason;
44
+ done: boolean;
45
+ }
46
+ export declare function waitForExecution(opts: WaitForExecutionOptions, client: GatewayClient): Promise<WaitForExecutionResult>;
30
47
  export interface ListExecutionsResult {
31
48
  executions: ExecutionDetail[];
32
49
  }
@@ -1,14 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.inspect = inspect;
4
+ exports.isExecutionTerminal = isExecutionTerminal;
5
+ exports.waitForExecution = waitForExecution;
4
6
  exports.listExecutions = listExecutions;
5
7
  exports.inspectBuild = inspectBuild;
6
8
  async function inspect(opts, client) {
7
9
  const execution = await client.get(`/executions/${opts.executionId}`);
8
10
  return { execution };
9
11
  }
12
+ const TERMINAL_STATUSES = new Set([
13
+ "completed",
14
+ "failed",
15
+ "cancelled",
16
+ "canceled",
17
+ ]);
18
+ function isExecutionTerminal(status) {
19
+ return TERMINAL_STATUSES.has(status);
20
+ }
21
+ const AUTO_RESUME_PAUSE_SIGNALS = ["agent.coding.result"];
22
+ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
23
+ async function waitForExecution(opts, client) {
24
+ const maxWaitMs = opts.maxWaitMs ?? 45000;
25
+ const autoResume = opts.autoResumeSignals ?? AUTO_RESUME_PAUSE_SIGNALS;
26
+ const sleep = opts.sleep ?? defaultSleep;
27
+ const now = opts.now ?? Date.now;
28
+ const deadline = now() + maxWaitMs;
29
+ let interval = opts.pollMs ?? 1000;
30
+ for (;;) {
31
+ const { execution } = await inspect({ executionId: opts.executionId }, client);
32
+ if (isExecutionTerminal(execution.status)) {
33
+ return { execution, reason: "terminal", done: true };
34
+ }
35
+ if (execution.status === "paused") {
36
+ const signal = execution.pausedSignalName ?? null;
37
+ if (!signal || !autoResume.includes(signal)) {
38
+ return { execution, reason: "needs-signal", done: false };
39
+ }
40
+ }
41
+ const remaining = deadline - now();
42
+ if (remaining <= 0)
43
+ return { execution, reason: "timeout", done: false };
44
+ await sleep(Math.min(interval, remaining));
45
+ interval = Math.min(interval * 1.5, 5000);
46
+ }
47
+ }
10
48
  async function listExecutions(client) {
11
- const executions = await client.get('/executions');
49
+ const executions = await client.get("/executions");
12
50
  return { executions };
13
51
  }
14
52
  async function inspectBuild(opts, client) {
@@ -18,5 +18,6 @@ export interface ScaffoldResult {
18
18
  targetDir: string;
19
19
  template: string;
20
20
  projectName: string;
21
+ gitInitialized: boolean;
21
22
  }
22
23
  export declare function scaffold(opts: ScaffoldOptions): Promise<ScaffoldResult>;
@@ -8,34 +8,37 @@ exports.resolveVersions = resolveVersions;
8
8
  exports.listTemplates = listTemplates;
9
9
  exports.resolveTemplate = resolveTemplate;
10
10
  exports.scaffold = scaffold;
11
+ const node_child_process_1 = require("node:child_process");
11
12
  const node_fs_1 = require("node:fs");
12
13
  const node_path_1 = __importDefault(require("node:path"));
13
14
  const node_url_1 = require("node:url");
14
15
  const errors_js_1 = require("./errors.js");
15
16
  function resolveModuleDir() {
16
- if (typeof __dirname !== 'undefined')
17
+ if (typeof __dirname !== "undefined")
17
18
  return __dirname;
18
19
  try {
19
- const metaUrl = eval('import.meta.url');
20
- if (typeof metaUrl === 'string')
20
+ const metaUrl = eval("import.meta.url");
21
+ if (typeof metaUrl === "string")
21
22
  return node_path_1.default.dirname((0, node_url_1.fileURLToPath)(metaUrl));
22
23
  }
23
24
  catch {
24
25
  }
25
- return '';
26
+ return "";
26
27
  }
27
28
  const moduleDir = resolveModuleDir();
28
29
  function getTemplatesDir(override) {
29
- return override ?? process.env.SAPIOM_TEMPLATES_DIR ?? node_path_1.default.resolve(moduleDir, '..', '..', 'templates');
30
+ return (override ??
31
+ process.env.SAPIOM_TEMPLATES_DIR ??
32
+ node_path_1.default.resolve(moduleDir, "..", "..", "templates"));
30
33
  }
31
- exports.DEFAULT_TEMPLATE = 'default';
32
- const DOTFILE_NAMES = new Set(['_gitignore', '_npmrc']);
33
- const REGISTRY = 'https://registry.npmjs.org';
34
+ exports.DEFAULT_TEMPLATE = "default";
35
+ const DOTFILE_NAMES = new Set(["_gitignore", "_npmrc"]);
36
+ const REGISTRY = "https://registry.npmjs.org";
34
37
  const VERSION_FALLBACK = {
35
- orchestration: '0.1.1',
36
- tools: '0.1.1',
38
+ orchestration: "0.1.1",
39
+ tools: "0.1.1",
37
40
  };
38
- const ZOD_VERSION = '3.25.76';
41
+ const ZOD_VERSION = "3.25.76";
39
42
  async function latestNpmVersion(pkg) {
40
43
  try {
41
44
  const res = await fetch(`${REGISTRY}/${encodeURIComponent(pkg)}/latest`, {
@@ -44,7 +47,7 @@ async function latestNpmVersion(pkg) {
44
47
  if (!res.ok)
45
48
  return null;
46
49
  const json = (await res.json());
47
- return typeof json.version === 'string' ? json.version : null;
50
+ return typeof json.version === "string" ? json.version : null;
48
51
  }
49
52
  catch {
50
53
  return null;
@@ -52,8 +55,8 @@ async function latestNpmVersion(pkg) {
52
55
  }
53
56
  async function resolveVersions() {
54
57
  const [orchestration, tools] = await Promise.all([
55
- latestNpmVersion('@sapiom/orchestration'),
56
- latestNpmVersion('@sapiom/tools'),
58
+ latestNpmVersion("@sapiom/orchestration"),
59
+ latestNpmVersion("@sapiom/tools"),
57
60
  ]);
58
61
  return {
59
62
  orchestration: orchestration ?? VERSION_FALLBACK.orchestration,
@@ -72,9 +75,11 @@ function resolveTemplate(name, templatesDir) {
72
75
  if (!(0, node_fs_1.existsSync)(dir) || !(0, node_fs_1.statSync)(dir).isDirectory()) {
73
76
  const available = listTemplates(templatesDir);
74
77
  throw new errors_js_1.OrchestrationError({
75
- code: 'UNKNOWN_TEMPLATE',
78
+ code: "UNKNOWN_TEMPLATE",
76
79
  message: `Unknown template '${name}'.` +
77
- (available.length ? ` Available: ${available.join(', ')}.` : ' No templates are bundled.'),
80
+ (available.length
81
+ ? ` Available: ${available.join(", ")}.`
82
+ : " No templates are bundled."),
78
83
  });
79
84
  }
80
85
  return dir;
@@ -82,7 +87,7 @@ function resolveTemplate(name, templatesDir) {
82
87
  function applyReplacements(file, replacements) {
83
88
  let content;
84
89
  try {
85
- content = (0, node_fs_1.readFileSync)(file, 'utf8');
90
+ content = (0, node_fs_1.readFileSync)(file, "utf8");
86
91
  }
87
92
  catch {
88
93
  return;
@@ -111,7 +116,7 @@ function copyTemplate(templateDir, targetDir, replacements) {
111
116
  walk(targetDir, (file) => {
112
117
  const base = node_path_1.default.basename(file);
113
118
  if (DOTFILE_NAMES.has(base)) {
114
- const dotted = node_path_1.default.join(node_path_1.default.dirname(file), '.' + base.slice(1));
119
+ const dotted = node_path_1.default.join(node_path_1.default.dirname(file), "." + base.slice(1));
115
120
  (0, node_fs_1.renameSync)(file, dotted);
116
121
  applyReplacements(dotted, replacements);
117
122
  return;
@@ -119,13 +124,37 @@ function copyTemplate(templateDir, targetDir, replacements) {
119
124
  applyReplacements(file, replacements);
120
125
  });
121
126
  }
127
+ function initGitRepo(dir) {
128
+ const tryGit = (args) => {
129
+ try {
130
+ (0, node_child_process_1.execFileSync)("git", args, { cwd: dir, stdio: "ignore" });
131
+ return true;
132
+ }
133
+ catch {
134
+ return false;
135
+ }
136
+ };
137
+ if (!tryGit(["init"]))
138
+ return false;
139
+ tryGit(["add", "-A"]);
140
+ return (tryGit(["commit", "-m", "Initial commit"]) ||
141
+ tryGit([
142
+ "-c",
143
+ "user.name=Sapiom",
144
+ "-c",
145
+ "user.email=noreply@sapiom.ai",
146
+ "commit",
147
+ "-m",
148
+ "Initial commit",
149
+ ]));
150
+ }
122
151
  async function scaffold(opts) {
123
152
  const { targetDir } = opts;
124
153
  const template = opts.template ?? exports.DEFAULT_TEMPLATE;
125
154
  const projectName = opts.projectName ?? node_path_1.default.basename(targetDir);
126
155
  if ((0, node_fs_1.existsSync)(targetDir) && (0, node_fs_1.readdirSync)(targetDir).length > 0) {
127
156
  throw new errors_js_1.OrchestrationError({
128
- code: 'DIR_NOT_EMPTY',
157
+ code: "DIR_NOT_EMPTY",
129
158
  message: `Target directory '${targetDir}' already exists and is not empty.`,
130
159
  });
131
160
  }
@@ -138,8 +167,9 @@ async function scaffold(opts) {
138
167
  __TOOLS_VERSION__: versions.tools,
139
168
  __ZOD_VERSION__: versions.zod,
140
169
  });
141
- const devDir = node_path_1.default.join(targetDir, '.sapiom-dev');
170
+ const devDir = node_path_1.default.join(targetDir, ".sapiom-dev");
142
171
  (0, node_fs_1.mkdirSync)(devDir, { recursive: true });
143
- (0, node_fs_1.writeFileSync)(node_path_1.default.join(devDir, 'stubs.json'), JSON.stringify({ version: 1, steps: {} }, null, 2) + '\n');
144
- return { targetDir, template, projectName };
172
+ (0, node_fs_1.writeFileSync)(node_path_1.default.join(devDir, "stubs.json"), JSON.stringify({ version: 1, steps: {} }, null, 2) + "\n");
173
+ const gitInitialized = initGitRepo(targetDir);
174
+ return { targetDir, template, projectName, gitInitialized };
145
175
  }
@@ -1,29 +1,29 @@
1
- export { OrchestrationError } from './errors.js';
2
- export type { StructuredError } from './errors.js';
3
- export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST } from './client.js';
4
- export type { ClientOptions, GatewayErrorBody } from './client.js';
5
- export { readConfig, requireConfig, writeConfig, CONFIG_FILE } from './config.js';
6
- export type { SapiomConfig } from './config.js';
7
- export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE } from './scaffold.js';
8
- export type { ScaffoldOptions, ScaffoldResult, ResolvedVersions } from './scaffold.js';
9
- export { check } from './check.js';
10
- export type { CheckOptions, CheckResult } from './check.js';
11
- export { link } from './link.js';
12
- export type { LinkOptions, LinkResult, DefinitionSummary } from './link.js';
13
- export { deploy } from './deploy.js';
14
- export type { DeployOptions, DeployResult } from './deploy.js';
15
- export { run, parseJsonInput } from './run.js';
16
- export type { RunOptions, RunResult } from './run.js';
17
- export { inspect, listExecutions, inspectBuild } from './inspect.js';
18
- export type { InspectOptions, InspectResult, ListExecutionsResult, InspectBuildOptions, InspectBuildResult, ExecutionDetail, StepRecord, BuildDetail, } from './inspect.js';
19
- export { signal, parseSignalPayload } from './signal.js';
20
- export type { SignalOptions, SignalResult } from './signal.js';
21
- export { assertDeployable, pushHead } from './git.js';
22
- export { parseStubFile, STUB_FILE_VERSION } from './local/stubs.js';
23
- export type { StubFile, StepStubs, StubResponse } from './local/stubs.js';
24
- export { runLocal, runLocalFromDir, STUBS_FILE } from './local/run-local.js';
25
- export type { RunLocalOptions, LocalRunResult, LocalRunOutcome } from './local/run-local.js';
26
- export { loadDefinition } from './local/load.js';
27
- export type { LoadedDefinition } from './local/load.js';
28
- export { LocalStubDispatcher } from './local/dispatcher.js';
29
- export type { LocalStepTrace, LogEntry } from './local/dispatcher.js';
1
+ export { OrchestrationError } from "./errors.js";
2
+ export type { StructuredError } from "./errors.js";
3
+ export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST, } from "./client.js";
4
+ export type { ClientOptions, GatewayErrorBody } from "./client.js";
5
+ export { readConfig, requireConfig, writeConfig, CONFIG_FILE, } from "./config.js";
6
+ export type { SapiomConfig } from "./config.js";
7
+ export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE, } from "./scaffold.js";
8
+ export type { ScaffoldOptions, ScaffoldResult, ResolvedVersions, } from "./scaffold.js";
9
+ export { check } from "./check.js";
10
+ export type { CheckOptions, CheckResult } from "./check.js";
11
+ export { link } from "./link.js";
12
+ export type { LinkOptions, LinkResult, DefinitionSummary } from "./link.js";
13
+ export { deploy } from "./deploy.js";
14
+ export type { DeployOptions, DeployResult } from "./deploy.js";
15
+ export { run, parseJsonInput } from "./run.js";
16
+ export type { RunOptions, RunResult } from "./run.js";
17
+ export { inspect, listExecutions, inspectBuild, waitForExecution, isExecutionTerminal, } from "./inspect.js";
18
+ export type { InspectOptions, InspectResult, ListExecutionsResult, InspectBuildOptions, InspectBuildResult, ExecutionDetail, StepRecord, BuildDetail, WaitForExecutionOptions, WaitForExecutionResult, WaitStopReason, } from "./inspect.js";
19
+ export { signal, parseSignalPayload } from "./signal.js";
20
+ export type { SignalOptions, SignalResult } from "./signal.js";
21
+ export { assertDeployable, pushHead } from "./git.js";
22
+ export { parseStubFile, STUB_FILE_VERSION } from "./local/stubs.js";
23
+ export type { StubFile, StepStubs, StubResponse } from "./local/stubs.js";
24
+ export { runLocal, runLocalFromDir, STUBS_FILE } from "./local/run-local.js";
25
+ export type { RunLocalOptions, LocalRunResult, LocalRunOutcome, } from "./local/run-local.js";
26
+ export { loadDefinition } from "./local/load.js";
27
+ export type { LoadedDefinition } from "./local/load.js";
28
+ export { LocalStubDispatcher } from "./local/dispatcher.js";
29
+ export type { LocalStepTrace, LogEntry } from "./local/dispatcher.js";
package/dist/esm/index.js CHANGED
@@ -1,15 +1,15 @@
1
- export { OrchestrationError } from './errors.js';
2
- export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST } from './client.js';
3
- export { readConfig, requireConfig, writeConfig, CONFIG_FILE } from './config.js';
4
- export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE } from './scaffold.js';
5
- export { check } from './check.js';
6
- export { link } from './link.js';
7
- export { deploy } from './deploy.js';
8
- export { run, parseJsonInput } from './run.js';
9
- export { inspect, listExecutions, inspectBuild } from './inspect.js';
10
- export { signal, parseSignalPayload } from './signal.js';
11
- export { assertDeployable, pushHead } from './git.js';
12
- export { parseStubFile, STUB_FILE_VERSION } from './local/stubs.js';
13
- export { runLocal, runLocalFromDir, STUBS_FILE } from './local/run-local.js';
14
- export { loadDefinition } from './local/load.js';
15
- export { LocalStubDispatcher } from './local/dispatcher.js';
1
+ export { OrchestrationError } from "./errors.js";
2
+ export { GatewayClient, createClient, DEFAULT_WORKFLOWS_HOST, } from "./client.js";
3
+ export { readConfig, requireConfig, writeConfig, CONFIG_FILE, } from "./config.js";
4
+ export { scaffold, resolveVersions, resolveTemplate, listTemplates, DEFAULT_TEMPLATE, } from "./scaffold.js";
5
+ export { check } from "./check.js";
6
+ export { link } from "./link.js";
7
+ export { deploy } from "./deploy.js";
8
+ export { run, parseJsonInput } from "./run.js";
9
+ export { inspect, listExecutions, inspectBuild, waitForExecution, isExecutionTerminal, } from "./inspect.js";
10
+ export { signal, parseSignalPayload } from "./signal.js";
11
+ export { assertDeployable, pushHead } from "./git.js";
12
+ export { parseStubFile, STUB_FILE_VERSION } from "./local/stubs.js";
13
+ export { runLocal, runLocalFromDir, STUBS_FILE } from "./local/run-local.js";
14
+ export { loadDefinition } from "./local/load.js";
15
+ export { LocalStubDispatcher } from "./local/dispatcher.js";
@@ -1,4 +1,4 @@
1
- import { GatewayClient } from './client.js';
1
+ import { GatewayClient } from "./client.js";
2
2
  export interface StepRecord {
3
3
  stepName: string;
4
4
  attempt: number;
@@ -12,6 +12,7 @@ export interface ExecutionDetail {
12
12
  id: string;
13
13
  status: string;
14
14
  currentStep?: string | null;
15
+ pausedSignalName?: string | null;
15
16
  error?: unknown;
16
17
  steps?: StepRecord[];
17
18
  }
@@ -27,6 +28,22 @@ export interface InspectResult {
27
28
  execution: ExecutionDetail;
28
29
  }
29
30
  export declare function inspect(opts: InspectOptions, client: GatewayClient): Promise<InspectResult>;
31
+ export declare function isExecutionTerminal(status: string): boolean;
32
+ export type WaitStopReason = "terminal" | "needs-signal" | "timeout";
33
+ export interface WaitForExecutionOptions {
34
+ executionId: string;
35
+ maxWaitMs?: number;
36
+ pollMs?: number;
37
+ autoResumeSignals?: string[];
38
+ sleep?: (ms: number) => Promise<void>;
39
+ now?: () => number;
40
+ }
41
+ export interface WaitForExecutionResult {
42
+ execution: ExecutionDetail;
43
+ reason: WaitStopReason;
44
+ done: boolean;
45
+ }
46
+ export declare function waitForExecution(opts: WaitForExecutionOptions, client: GatewayClient): Promise<WaitForExecutionResult>;
30
47
  export interface ListExecutionsResult {
31
48
  executions: ExecutionDetail[];
32
49
  }
@@ -2,8 +2,44 @@ export async function inspect(opts, client) {
2
2
  const execution = await client.get(`/executions/${opts.executionId}`);
3
3
  return { execution };
4
4
  }
5
+ const TERMINAL_STATUSES = new Set([
6
+ "completed",
7
+ "failed",
8
+ "cancelled",
9
+ "canceled",
10
+ ]);
11
+ export function isExecutionTerminal(status) {
12
+ return TERMINAL_STATUSES.has(status);
13
+ }
14
+ const AUTO_RESUME_PAUSE_SIGNALS = ["agent.coding.result"];
15
+ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
16
+ export async function waitForExecution(opts, client) {
17
+ const maxWaitMs = opts.maxWaitMs ?? 45000;
18
+ const autoResume = opts.autoResumeSignals ?? AUTO_RESUME_PAUSE_SIGNALS;
19
+ const sleep = opts.sleep ?? defaultSleep;
20
+ const now = opts.now ?? Date.now;
21
+ const deadline = now() + maxWaitMs;
22
+ let interval = opts.pollMs ?? 1000;
23
+ for (;;) {
24
+ const { execution } = await inspect({ executionId: opts.executionId }, client);
25
+ if (isExecutionTerminal(execution.status)) {
26
+ return { execution, reason: "terminal", done: true };
27
+ }
28
+ if (execution.status === "paused") {
29
+ const signal = execution.pausedSignalName ?? null;
30
+ if (!signal || !autoResume.includes(signal)) {
31
+ return { execution, reason: "needs-signal", done: false };
32
+ }
33
+ }
34
+ const remaining = deadline - now();
35
+ if (remaining <= 0)
36
+ return { execution, reason: "timeout", done: false };
37
+ await sleep(Math.min(interval, remaining));
38
+ interval = Math.min(interval * 1.5, 5000);
39
+ }
40
+ }
5
41
  export async function listExecutions(client) {
6
- const executions = await client.get('/executions');
42
+ const executions = await client.get("/executions");
7
43
  return { executions };
8
44
  }
9
45
  export async function inspectBuild(opts, client) {
@@ -18,5 +18,6 @@ export interface ScaffoldResult {
18
18
  targetDir: string;
19
19
  template: string;
20
20
  projectName: string;
21
+ gitInitialized: boolean;
21
22
  }
22
23
  export declare function scaffold(opts: ScaffoldOptions): Promise<ScaffoldResult>;