@sapiom/agent 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/LICENSE +21 -0
  3. package/README.md +130 -0
  4. package/dist/cjs/agent.d.ts +10 -0
  5. package/dist/cjs/agent.js +38 -0
  6. package/dist/cjs/build-manifest.d.ts +15 -0
  7. package/dist/cjs/build-manifest.js +170 -0
  8. package/dist/cjs/context.d.ts +47 -0
  9. package/dist/cjs/context.js +21 -0
  10. package/dist/cjs/directives.d.ts +95 -0
  11. package/dist/cjs/directives.js +74 -0
  12. package/dist/cjs/errors.d.ts +19 -0
  13. package/dist/cjs/errors.js +49 -0
  14. package/dist/cjs/index.d.ts +17 -0
  15. package/dist/cjs/index.js +41 -0
  16. package/dist/cjs/introspection.d.ts +11 -0
  17. package/dist/cjs/introspection.js +62 -0
  18. package/dist/cjs/manifest.d.ts +56 -0
  19. package/dist/cjs/manifest.js +27 -0
  20. package/dist/cjs/step.d.ts +42 -0
  21. package/dist/cjs/step.js +15 -0
  22. package/dist/esm/agent.d.ts +10 -0
  23. package/dist/esm/agent.js +33 -0
  24. package/dist/esm/build-manifest.d.ts +15 -0
  25. package/dist/esm/build-manifest.js +165 -0
  26. package/dist/esm/context.d.ts +47 -0
  27. package/dist/esm/context.js +17 -0
  28. package/dist/esm/directives.d.ts +95 -0
  29. package/dist/esm/directives.js +61 -0
  30. package/dist/esm/errors.d.ts +19 -0
  31. package/dist/esm/errors.js +42 -0
  32. package/dist/esm/index.d.ts +17 -0
  33. package/dist/esm/index.js +9 -0
  34. package/dist/esm/introspection.d.ts +11 -0
  35. package/dist/esm/introspection.js +56 -0
  36. package/dist/esm/manifest.d.ts +56 -0
  37. package/dist/esm/manifest.js +24 -0
  38. package/dist/esm/package.json +1 -0
  39. package/dist/esm/step.d.ts +42 -0
  40. package/dist/esm/step.js +12 -0
  41. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  42. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  43. package/package.json +74 -0
@@ -0,0 +1,165 @@
1
+ import { zodToJsonSchema } from "./introspection.js";
2
+ import { MANIFEST_PROTOCOL, } from "./manifest.js";
3
+ export function buildManifest(def, opts) {
4
+ const steps = {};
5
+ for (const [stepName, step] of Object.entries(def.steps)) {
6
+ let inputSchema = null;
7
+ if (step.inputSchema) {
8
+ const raw = zodToJsonSchema(step.inputSchema);
9
+ inputSchema = relaxAdditionalProperties(dropDefaultedFromRequired(raw));
10
+ }
11
+ steps[stepName] = {
12
+ timeoutMs: step.timeoutMs ?? null,
13
+ inputSchema,
14
+ transitions: transitionsFor(step),
15
+ };
16
+ }
17
+ return {
18
+ protocol: MANIFEST_PROTOCOL,
19
+ name: def.name,
20
+ entry: def.entry,
21
+ sdkVersion: opts.sdkVersion,
22
+ artifact: opts.artifact,
23
+ steps,
24
+ };
25
+ }
26
+ function transitionsFor(step) {
27
+ const transitions = [];
28
+ for (const target of step.next ?? []) {
29
+ transitions.push({ kind: "continue", target });
30
+ }
31
+ if (step.pause) {
32
+ transitions.push({
33
+ kind: "pause",
34
+ signal: step.pause.signal,
35
+ resumeStep: step.pause.resumeStep,
36
+ });
37
+ }
38
+ if (step.terminal)
39
+ transitions.push({ kind: "terminate" });
40
+ if (step.canFail)
41
+ transitions.push({ kind: "fail" });
42
+ return transitions;
43
+ }
44
+ export function validateGraph(manifest) {
45
+ const errors = [];
46
+ const names = new Set(Object.keys(manifest.steps));
47
+ if (!names.has(manifest.entry)) {
48
+ errors.push(`entry step '${manifest.entry}' is not in the steps map`);
49
+ }
50
+ const forward = buildForwardEdges(manifest, names, errors);
51
+ const warnings = [];
52
+ if (names.has(manifest.entry)) {
53
+ const reachable = bfs([manifest.entry], forward);
54
+ for (const name of names) {
55
+ if (!reachable.has(name))
56
+ warnings.push(`step '${name}' is unreachable from entry '${manifest.entry}'`);
57
+ }
58
+ }
59
+ warnings.push(...terminalReachabilityWarnings(manifest, names, forward));
60
+ return { errors, warnings };
61
+ }
62
+ export function assertValidGraph(manifest) {
63
+ const { errors, warnings } = validateGraph(manifest);
64
+ if (errors.length > 0) {
65
+ throw new Error(`Invalid workflow graph for '${manifest.name}':\n - ${errors.join("\n - ")}`);
66
+ }
67
+ return warnings;
68
+ }
69
+ function buildForwardEdges(manifest, names, errors) {
70
+ const forward = new Map();
71
+ for (const [name, step] of Object.entries(manifest.steps)) {
72
+ const targets = new Set();
73
+ for (const t of step.transitions) {
74
+ if (t.kind === "continue") {
75
+ if (names.has(t.target))
76
+ targets.add(t.target);
77
+ else
78
+ errors.push(`step '${name}' has a continue target '${t.target}' that is not in the steps map`);
79
+ }
80
+ else if (t.kind === "pause" && names.has(t.resumeStep)) {
81
+ targets.add(t.resumeStep);
82
+ }
83
+ }
84
+ if (step.transitions.length === 0) {
85
+ errors.push(`step '${name}' is a dead-end: it declares no transitions (next/terminal/canFail/pause)`);
86
+ }
87
+ forward.set(name, targets);
88
+ }
89
+ return forward;
90
+ }
91
+ function terminalReachabilityWarnings(manifest, names, forward) {
92
+ const sinks = Object.entries(manifest.steps)
93
+ .filter(([, s]) => s.transitions.some((t) => t.kind === "terminate" || t.kind === "fail"))
94
+ .map(([name]) => name);
95
+ if (sinks.length === 0) {
96
+ return [
97
+ "no step can terminate or fail — the workflow has no terminal state",
98
+ ];
99
+ }
100
+ const reverse = new Map();
101
+ for (const name of names)
102
+ reverse.set(name, new Set());
103
+ for (const [name, targets] of forward) {
104
+ for (const t of targets)
105
+ reverse.get(t)?.add(name);
106
+ }
107
+ const canReach = bfs(sinks, reverse);
108
+ const warnings = [];
109
+ for (const name of names) {
110
+ if (!canReach.has(name)) {
111
+ warnings.push(`step '${name}' cannot reach any terminate/fail (possible unbounded loop or missing terminal)`);
112
+ }
113
+ }
114
+ return warnings;
115
+ }
116
+ function bfs(starts, edges) {
117
+ const seen = new Set();
118
+ const queue = [...starts];
119
+ while (queue.length > 0) {
120
+ const cur = queue.shift();
121
+ if (seen.has(cur))
122
+ continue;
123
+ seen.add(cur);
124
+ for (const next of edges.get(cur) ?? [])
125
+ if (!seen.has(next))
126
+ queue.push(next);
127
+ }
128
+ return seen;
129
+ }
130
+ function relaxAdditionalProperties(value) {
131
+ if (Array.isArray(value)) {
132
+ return value.map(relaxAdditionalProperties);
133
+ }
134
+ if (value && typeof value === "object") {
135
+ const out = {};
136
+ for (const [key, v] of Object.entries(value)) {
137
+ if (key === "additionalProperties" && v === false) {
138
+ continue;
139
+ }
140
+ out[key] = relaxAdditionalProperties(v);
141
+ }
142
+ return out;
143
+ }
144
+ return value;
145
+ }
146
+ function dropDefaultedFromRequired(schema) {
147
+ const required = schema.required;
148
+ const properties = schema.properties;
149
+ if (!Array.isArray(required) ||
150
+ !properties ||
151
+ typeof properties !== "object") {
152
+ return schema;
153
+ }
154
+ const props = properties;
155
+ const filtered = required.filter((key) => {
156
+ if (typeof key !== "string")
157
+ return true;
158
+ const prop = props[key];
159
+ return !(prop && typeof prop === "object" && "default" in prop);
160
+ });
161
+ if (filtered.length === required.length) {
162
+ return schema;
163
+ }
164
+ return { ...schema, required: filtered };
165
+ }
@@ -0,0 +1,47 @@
1
+ import type { Sapiom } from '@sapiom/tools';
2
+ import type { NextStepDirective } from './directives.js';
3
+ export interface StepLogger {
4
+ info(message: string, meta?: Record<string, unknown>): void;
5
+ warn(message: string, meta?: Record<string, unknown>): void;
6
+ error(message: string, meta?: Record<string, unknown>): void;
7
+ debug(message: string, meta?: Record<string, unknown>): void;
8
+ }
9
+ export type FinishedStepStatus = 'dispatched' | 'succeeded' | 'failed';
10
+ export interface AgentExecutionContext<TShared extends Record<string, unknown> = Record<string, unknown>> {
11
+ readonly executionId: string;
12
+ readonly workflowName: string;
13
+ readonly organizationId: string | null;
14
+ readonly tenantId: string | null;
15
+ readonly input: unknown;
16
+ readonly shared: TypedContextStore<TShared>;
17
+ readonly history: readonly StepExecutionRecord[];
18
+ readonly attempts: number;
19
+ readonly logger: StepLogger;
20
+ readonly sapiom: Sapiom;
21
+ }
22
+ export interface TypedContextStore<TShared extends Record<string, unknown>> {
23
+ get<K extends keyof TShared>(key: K): TShared[K] | undefined;
24
+ set<K extends keyof TShared>(key: K, value: TShared[K]): void;
25
+ has<K extends keyof TShared>(key: K): boolean;
26
+ snapshot(): Partial<TShared>;
27
+ }
28
+ export interface StepExecutionRecord {
29
+ readonly stepName: string;
30
+ readonly attempt: number;
31
+ readonly status: FinishedStepStatus;
32
+ readonly input: unknown;
33
+ readonly output: unknown;
34
+ readonly error: unknown;
35
+ readonly nextDirective: NextStepDirective | null;
36
+ readonly sharedStateAfter: Record<string, unknown> | null;
37
+ readonly startedAt: Date;
38
+ readonly finishedAt: Date;
39
+ }
40
+ export declare class InMemoryContextStore<TShared extends Record<string, unknown>> implements TypedContextStore<TShared> {
41
+ private state;
42
+ constructor(initial?: Partial<TShared>);
43
+ get<K extends keyof TShared>(key: K): TShared[K] | undefined;
44
+ set<K extends keyof TShared>(key: K, value: TShared[K]): void;
45
+ has<K extends keyof TShared>(key: K): boolean;
46
+ snapshot(): Partial<TShared>;
47
+ }
@@ -0,0 +1,17 @@
1
+ export class InMemoryContextStore {
2
+ constructor(initial = {}) {
3
+ this.state = { ...initial };
4
+ }
5
+ get(key) {
6
+ return this.state[key];
7
+ }
8
+ set(key, value) {
9
+ this.state[key] = value;
10
+ }
11
+ has(key) {
12
+ return key in this.state;
13
+ }
14
+ snapshot() {
15
+ return { ...this.state };
16
+ }
17
+ }
@@ -0,0 +1,95 @@
1
+ import type { DispatchHandle } from '@sapiom/tools';
2
+ export declare const DIRECTIVE_KIND: {
3
+ readonly CONTINUE: "continue";
4
+ readonly RETRY: "retry";
5
+ readonly PAUSE_UNTIL_SIGNAL: "pause_until_signal";
6
+ readonly TERMINATE: "terminate";
7
+ readonly FAIL: "fail";
8
+ };
9
+ export type DirectiveKind = (typeof DIRECTIVE_KIND)[keyof typeof DIRECTIVE_KIND];
10
+ export type NextStepDirective = ContinueDirective | RetryDirective | PauseUntilSignalDirective | TerminateDirective | FailDirective;
11
+ export interface ContinueDirective {
12
+ readonly kind: typeof DIRECTIVE_KIND.CONTINUE;
13
+ readonly stepName: string;
14
+ readonly input?: unknown;
15
+ }
16
+ export interface RetryDirective {
17
+ readonly kind: typeof DIRECTIVE_KIND.RETRY;
18
+ readonly delayMs?: number;
19
+ readonly reason?: string;
20
+ }
21
+ export interface PauseUntilSignalDirective {
22
+ readonly kind: typeof DIRECTIVE_KIND.PAUSE_UNTIL_SIGNAL;
23
+ readonly signal: {
24
+ readonly name: string;
25
+ readonly correlationId?: string;
26
+ };
27
+ readonly timeoutMs?: number;
28
+ readonly resumeStep?: string;
29
+ }
30
+ export interface TerminateDirective {
31
+ readonly kind: typeof DIRECTIVE_KIND.TERMINATE;
32
+ readonly reason?: string;
33
+ }
34
+ export interface FailDirective {
35
+ readonly kind: typeof DIRECTIVE_KIND.FAIL;
36
+ readonly reason?: string;
37
+ }
38
+ export declare function isContinue(d: NextStepDirective): d is ContinueDirective;
39
+ export declare function isRetry(d: NextStepDirective): d is RetryDirective;
40
+ export declare function isPause(d: NextStepDirective): d is PauseUntilSignalDirective;
41
+ export declare function isTerminate(d: NextStepDirective): d is TerminateDirective;
42
+ export declare function isFail(d: NextStepDirective): d is FailDirective;
43
+ export interface Goto<Target extends string> {
44
+ readonly kind: typeof DIRECTIVE_KIND.CONTINUE;
45
+ readonly stepName: Target;
46
+ readonly input?: unknown;
47
+ }
48
+ export interface Terminate {
49
+ readonly kind: typeof DIRECTIVE_KIND.TERMINATE;
50
+ readonly output?: unknown;
51
+ readonly reason?: string;
52
+ }
53
+ export interface Fail {
54
+ readonly kind: typeof DIRECTIVE_KIND.FAIL;
55
+ readonly reason?: string;
56
+ readonly output?: unknown;
57
+ }
58
+ export interface Pause<Resume extends string> {
59
+ readonly kind: typeof DIRECTIVE_KIND.PAUSE_UNTIL_SIGNAL;
60
+ readonly signal: {
61
+ readonly name: string;
62
+ readonly correlationId?: string;
63
+ };
64
+ readonly resumeStep?: Resume;
65
+ readonly timeoutMs?: number;
66
+ readonly output?: unknown;
67
+ }
68
+ export interface Retry {
69
+ readonly kind: typeof DIRECTIVE_KIND.RETRY;
70
+ readonly delayMs?: number;
71
+ readonly reason?: string;
72
+ }
73
+ export declare function goto<const Target extends string>(target: Target, output?: unknown): Goto<Target>;
74
+ export declare function terminate(output?: unknown, opts?: {
75
+ reason?: string;
76
+ }): Terminate;
77
+ export declare function fail(reason?: string, opts?: {
78
+ output?: unknown;
79
+ }): Fail;
80
+ export declare function pauseUntilSignal<const Resume extends string>(args: {
81
+ signal: string;
82
+ resumeStep?: Resume;
83
+ correlationId?: string;
84
+ timeoutMs?: number;
85
+ output?: unknown;
86
+ }): Pause<Resume>;
87
+ export declare function pauseUntilSignal<const Resume extends string>(handle: DispatchHandle | Promise<DispatchHandle>, opts?: {
88
+ resumeStep?: Resume;
89
+ timeoutMs?: number;
90
+ output?: unknown;
91
+ }): Promise<Pause<Resume>>;
92
+ export declare function retry(opts?: {
93
+ delayMs?: number;
94
+ reason?: string;
95
+ }): Retry;
@@ -0,0 +1,61 @@
1
+ export const DIRECTIVE_KIND = {
2
+ CONTINUE: 'continue',
3
+ RETRY: 'retry',
4
+ PAUSE_UNTIL_SIGNAL: 'pause_until_signal',
5
+ TERMINATE: 'terminate',
6
+ FAIL: 'fail',
7
+ };
8
+ export function isContinue(d) {
9
+ return d.kind === DIRECTIVE_KIND.CONTINUE;
10
+ }
11
+ export function isRetry(d) {
12
+ return d.kind === DIRECTIVE_KIND.RETRY;
13
+ }
14
+ export function isPause(d) {
15
+ return d.kind === DIRECTIVE_KIND.PAUSE_UNTIL_SIGNAL;
16
+ }
17
+ export function isTerminate(d) {
18
+ return d.kind === DIRECTIVE_KIND.TERMINATE;
19
+ }
20
+ export function isFail(d) {
21
+ return d.kind === DIRECTIVE_KIND.FAIL;
22
+ }
23
+ export function goto(target, output) {
24
+ return { kind: DIRECTIVE_KIND.CONTINUE, stepName: target, input: output };
25
+ }
26
+ export function terminate(output, opts) {
27
+ return { kind: DIRECTIVE_KIND.TERMINATE, output, reason: opts?.reason };
28
+ }
29
+ export function fail(reason, opts) {
30
+ return { kind: DIRECTIVE_KIND.FAIL, reason, output: opts?.output };
31
+ }
32
+ export function pauseUntilSignal(argOrHandle, opts) {
33
+ if (isThenable(argOrHandle)) {
34
+ return Promise.resolve(argOrHandle).then((handle) => pauseFromHandle(handle, opts));
35
+ }
36
+ if ('dispatch' in argOrHandle) {
37
+ return Promise.resolve(pauseFromHandle(argOrHandle, opts));
38
+ }
39
+ return {
40
+ kind: DIRECTIVE_KIND.PAUSE_UNTIL_SIGNAL,
41
+ signal: { name: argOrHandle.signal, correlationId: argOrHandle.correlationId },
42
+ resumeStep: argOrHandle.resumeStep,
43
+ timeoutMs: argOrHandle.timeoutMs,
44
+ output: argOrHandle.output,
45
+ };
46
+ }
47
+ function isThenable(x) {
48
+ return x != null && typeof x.then === 'function';
49
+ }
50
+ function pauseFromHandle(handle, opts) {
51
+ return {
52
+ kind: DIRECTIVE_KIND.PAUSE_UNTIL_SIGNAL,
53
+ signal: { name: handle.dispatch.resultSignal, correlationId: handle.dispatch.correlationId },
54
+ resumeStep: opts?.resumeStep,
55
+ timeoutMs: opts?.timeoutMs,
56
+ output: opts?.output,
57
+ };
58
+ }
59
+ export function retry(opts) {
60
+ return { kind: DIRECTIVE_KIND.RETRY, delayMs: opts?.delayMs, reason: opts?.reason };
61
+ }
@@ -0,0 +1,19 @@
1
+ import type { $ZodIssue } from 'zod/v4/core';
2
+ export declare class AgentError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare class StepInputValidationError extends AgentError {
6
+ readonly stepName: string;
7
+ readonly issues: readonly $ZodIssue[];
8
+ constructor(stepName: string, issues: readonly $ZodIssue[]);
9
+ }
10
+ export declare class UnknownStepError extends AgentError {
11
+ readonly stepName: string;
12
+ constructor(stepName: string);
13
+ }
14
+ export declare class DisallowedTransitionError extends AgentError {
15
+ readonly stepName: string;
16
+ readonly directiveKind: string;
17
+ readonly target?: string;
18
+ constructor(stepName: string, directiveKind: string, target?: string);
19
+ }
@@ -0,0 +1,42 @@
1
+ export class AgentError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = 'AgentError';
5
+ }
6
+ }
7
+ export class StepInputValidationError extends AgentError {
8
+ constructor(stepName, issues) {
9
+ super(`Input for step '${stepName}' failed validation: ${formatIssues(issues)}`);
10
+ this.name = 'StepInputValidationError';
11
+ this.stepName = stepName;
12
+ this.issues = issues;
13
+ }
14
+ }
15
+ function formatIssues(issues) {
16
+ if (issues.length === 0)
17
+ return 'unknown validation error';
18
+ return issues
19
+ .map((issue) => {
20
+ const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
21
+ return `${path}: ${issue.message}`;
22
+ })
23
+ .join('; ');
24
+ }
25
+ export class UnknownStepError extends AgentError {
26
+ constructor(stepName) {
27
+ super(`Unknown step: ${stepName}`);
28
+ this.name = 'UnknownStepError';
29
+ this.stepName = stepName;
30
+ }
31
+ }
32
+ export class DisallowedTransitionError extends AgentError {
33
+ constructor(stepName, directiveKind, target) {
34
+ super(`Step '${stepName}' returned a '${directiveKind}' directive` +
35
+ (target ? ` to '${target}'` : '') +
36
+ ` that is not in its declared transitions`);
37
+ this.name = 'DisallowedTransitionError';
38
+ this.stepName = stepName;
39
+ this.directiveKind = directiveKind;
40
+ this.target = target;
41
+ }
42
+ }
@@ -0,0 +1,17 @@
1
+ export { DIRECTIVE_KIND, isContinue, isRetry, isPause, isTerminate, isFail } from './directives.js';
2
+ export type { DirectiveKind, NextStepDirective, ContinueDirective, RetryDirective, PauseUntilSignalDirective, TerminateDirective, FailDirective, } from './directives.js';
3
+ export { goto, terminate, fail, pauseUntilSignal, retry } from './directives.js';
4
+ export type { Goto, Terminate, Fail, Pause, Retry } from './directives.js';
5
+ export { defineStep } from './step.js';
6
+ export type { Step, StepResult, StepDefinition, Allowed } from './step.js';
7
+ export type { AgentExecutionContext, TypedContextStore, StepExecutionRecord, StepLogger, FinishedStepStatus, } from './context.js';
8
+ export { InMemoryContextStore } from './context.js';
9
+ export type { AgentDefinition } from './agent.js';
10
+ export { defineAgent, isAgentDefinition, AGENT_DEFINITION_BRAND } from './agent.js';
11
+ export { AgentError, UnknownStepError, StepInputValidationError, DisallowedTransitionError } from './errors.js';
12
+ export { zodToJsonSchema, exampleFromJsonSchema, stepInputContract, workflowInputContract } from './introspection.js';
13
+ export type { StepInputContract, AgentInputContract } from './introspection.js';
14
+ export { MANIFEST_PROTOCOL, agentManifestSchema } from './manifest.js';
15
+ export type { AgentManifest, AgentStepManifest, ManifestTransition } from './manifest.js';
16
+ export { buildManifest, validateGraph, assertValidGraph } from './build-manifest.js';
17
+ export type { GraphValidation } from './build-manifest.js';
@@ -0,0 +1,9 @@
1
+ export { DIRECTIVE_KIND, isContinue, isRetry, isPause, isTerminate, isFail } from './directives.js';
2
+ export { goto, terminate, fail, pauseUntilSignal, retry } from './directives.js';
3
+ export { defineStep } from './step.js';
4
+ export { InMemoryContextStore } from './context.js';
5
+ export { defineAgent, isAgentDefinition, AGENT_DEFINITION_BRAND } from './agent.js';
6
+ export { AgentError, UnknownStepError, StepInputValidationError, DisallowedTransitionError } from './errors.js';
7
+ export { zodToJsonSchema, exampleFromJsonSchema, stepInputContract, workflowInputContract } from './introspection.js';
8
+ export { MANIFEST_PROTOCOL, agentManifestSchema } from './manifest.js';
9
+ export { buildManifest, validateGraph, assertValidGraph } from './build-manifest.js';
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod/v4';
2
+ import type { AgentDefinition } from './agent.js';
3
+ export interface StepInputContract {
4
+ readonly jsonSchema: Record<string, unknown>;
5
+ readonly example: unknown;
6
+ }
7
+ export type AgentInputContract = StepInputContract;
8
+ export declare function zodToJsonSchema(schema: z.ZodType): Record<string, unknown>;
9
+ export declare function stepInputContract(def: AgentDefinition<unknown, Record<string, unknown>>, stepName: string): StepInputContract | null;
10
+ export declare function workflowInputContract(def: AgentDefinition<unknown, Record<string, unknown>>): StepInputContract | null;
11
+ export declare function exampleFromJsonSchema(jsonSchema: Record<string, unknown>): unknown;
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod/v4';
2
+ export function zodToJsonSchema(schema) {
3
+ return z.toJSONSchema(schema);
4
+ }
5
+ export function stepInputContract(def, stepName) {
6
+ const schema = def.steps[stepName]?.inputSchema;
7
+ if (!schema)
8
+ return null;
9
+ const jsonSchema = zodToJsonSchema(schema);
10
+ return { jsonSchema, example: exampleFromJsonSchema(jsonSchema) };
11
+ }
12
+ export function workflowInputContract(def) {
13
+ return stepInputContract(def, def.entry);
14
+ }
15
+ export function exampleFromJsonSchema(jsonSchema) {
16
+ const examples = jsonSchema.examples;
17
+ if (Array.isArray(examples) && examples.length > 0) {
18
+ return examples[0];
19
+ }
20
+ if ('example' in jsonSchema && jsonSchema.example !== undefined) {
21
+ return jsonSchema.example;
22
+ }
23
+ return skeletonFromJsonSchema(jsonSchema);
24
+ }
25
+ function skeletonFromJsonSchema(schema) {
26
+ if (Array.isArray(schema.enum) && schema.enum.length > 0) {
27
+ return schema.enum[0];
28
+ }
29
+ const branches = (schema.anyOf ?? schema.oneOf);
30
+ if (Array.isArray(branches) && branches.length > 0) {
31
+ return skeletonFromJsonSchema(branches[0]);
32
+ }
33
+ switch (schema.type) {
34
+ case 'object': {
35
+ const props = (schema.properties ?? {});
36
+ const out = {};
37
+ for (const [key, value] of Object.entries(props)) {
38
+ out[key] = skeletonFromJsonSchema(value);
39
+ }
40
+ return out;
41
+ }
42
+ case 'array':
43
+ return [];
44
+ case 'string':
45
+ return '';
46
+ case 'number':
47
+ case 'integer':
48
+ return 0;
49
+ case 'boolean':
50
+ return false;
51
+ case 'null':
52
+ return null;
53
+ default:
54
+ return null;
55
+ }
56
+ }
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod/v4';
2
+ export declare const MANIFEST_PROTOCOL: 1;
3
+ export type ManifestTransition = {
4
+ readonly kind: 'continue';
5
+ readonly target: string;
6
+ } | {
7
+ readonly kind: 'terminate';
8
+ } | {
9
+ readonly kind: 'fail';
10
+ } | {
11
+ readonly kind: 'pause';
12
+ readonly signal: string;
13
+ readonly resumeStep: string;
14
+ };
15
+ export interface AgentStepManifest {
16
+ readonly timeoutMs: number | null;
17
+ readonly inputSchema: Record<string, unknown> | null;
18
+ readonly transitions: readonly ManifestTransition[];
19
+ }
20
+ export interface AgentManifest {
21
+ readonly protocol: typeof MANIFEST_PROTOCOL;
22
+ readonly name: string;
23
+ readonly entry: string;
24
+ readonly sdkVersion: string;
25
+ readonly artifact: {
26
+ readonly sha256: string;
27
+ readonly entryFile: string;
28
+ };
29
+ readonly steps: Readonly<Record<string, AgentStepManifest>>;
30
+ }
31
+ export declare const agentManifestSchema: z.ZodObject<{
32
+ protocol: z.ZodLiteral<1>;
33
+ name: z.ZodString;
34
+ entry: z.ZodString;
35
+ sdkVersion: z.ZodString;
36
+ artifact: z.ZodObject<{
37
+ sha256: z.ZodString;
38
+ entryFile: z.ZodString;
39
+ }, z.core.$strip>;
40
+ steps: z.ZodRecord<z.ZodString, z.ZodObject<{
41
+ timeoutMs: z.ZodUnion<readonly [z.ZodNumber, z.ZodNull]>;
42
+ inputSchema: z.ZodUnion<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodNull]>;
43
+ transitions: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
44
+ kind: z.ZodLiteral<"continue">;
45
+ target: z.ZodString;
46
+ }, z.core.$strip>, z.ZodObject<{
47
+ kind: z.ZodLiteral<"terminate">;
48
+ }, z.core.$strip>, z.ZodObject<{
49
+ kind: z.ZodLiteral<"fail">;
50
+ }, z.core.$strip>, z.ZodObject<{
51
+ kind: z.ZodLiteral<"pause">;
52
+ signal: z.ZodString;
53
+ resumeStep: z.ZodString;
54
+ }, z.core.$strip>]>>;
55
+ }, z.core.$strip>>;
56
+ }, z.core.$strip>;
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod/v4';
2
+ export const MANIFEST_PROTOCOL = 1;
3
+ const manifestTransitionSchema = z.discriminatedUnion('kind', [
4
+ z.object({ kind: z.literal('continue'), target: z.string().min(1) }),
5
+ z.object({ kind: z.literal('terminate') }),
6
+ z.object({ kind: z.literal('fail') }),
7
+ z.object({ kind: z.literal('pause'), signal: z.string().min(1), resumeStep: z.string().min(1) }),
8
+ ]);
9
+ const workflowStepManifestSchema = z.object({
10
+ timeoutMs: z.union([z.number().int().positive(), z.null()]),
11
+ inputSchema: z.union([z.record(z.string(), z.unknown()), z.null()]),
12
+ transitions: z.array(manifestTransitionSchema),
13
+ });
14
+ export const agentManifestSchema = z.object({
15
+ protocol: z.literal(MANIFEST_PROTOCOL),
16
+ name: z.string().min(1),
17
+ entry: z.string().min(1),
18
+ sdkVersion: z.string().min(1),
19
+ artifact: z.object({
20
+ sha256: z.string().min(1),
21
+ entryFile: z.string().min(1),
22
+ }),
23
+ steps: z.record(z.string(), workflowStepManifestSchema),
24
+ });
@@ -0,0 +1 @@
1
+ {"type": "module"}
@@ -0,0 +1,42 @@
1
+ import type { ZodType } from 'zod/v4';
2
+ import type { AgentExecutionContext } from './context.js';
3
+ import type { Fail, Goto, NextStepDirective, Pause, Retry, Terminate } from './directives.js';
4
+ export interface Step<TIn = unknown, TOut = unknown, TShared extends Record<string, unknown> = Record<string, unknown>> {
5
+ readonly name: string;
6
+ readonly inputSchema?: ZodType<TIn>;
7
+ readonly timeoutMs?: number;
8
+ run(input: TIn, ctx: AgentExecutionContext<TShared>): Promise<StepResult<TOut>>;
9
+ }
10
+ export interface StepResult<TOut = unknown> {
11
+ readonly output: TOut;
12
+ readonly next: NextStepDirective;
13
+ }
14
+ export type Allowed<Next extends readonly string[], Term extends boolean, CanFail extends boolean, PauseTo extends string> = Goto<Next[number]> | (Term extends true ? Terminate : never) | (CanFail extends true ? Fail : never) | ([PauseTo] extends [never] ? never : Pause<PauseTo>) | Retry;
15
+ export interface StepDefinition<TShared extends Record<string, unknown> = Record<string, unknown>> {
16
+ readonly name: string;
17
+ readonly next: readonly string[];
18
+ readonly terminal: boolean;
19
+ readonly canFail: boolean;
20
+ readonly pause?: {
21
+ readonly signal: string;
22
+ readonly resumeStep: string;
23
+ };
24
+ readonly inputSchema?: ZodType<unknown>;
25
+ readonly timeoutMs?: number;
26
+ run(input: unknown, ctx: AgentExecutionContext<TShared>): Promise<NextStepDirective>;
27
+ }
28
+ export declare function defineStep<TIn = unknown, TShared extends Record<string, unknown> = Record<string, unknown>, const Next extends readonly string[] = readonly [], const Term extends boolean = false, const CanFail extends boolean = false, const PauseDecl extends {
29
+ signal: string;
30
+ resumeStep: string;
31
+ } | undefined = undefined>(def: {
32
+ name: string;
33
+ next?: Next;
34
+ terminal?: Term;
35
+ canFail?: CanFail;
36
+ pause?: PauseDecl;
37
+ inputSchema?: ZodType<TIn>;
38
+ timeoutMs?: number;
39
+ run: (input: TIn, ctx: AgentExecutionContext<TShared>) => Promise<Allowed<Next, Term, CanFail, PauseDecl extends {
40
+ resumeStep: infer R extends string;
41
+ } ? R : never>>;
42
+ }): StepDefinition<TShared>;