chore: reorganize repo — legacy packages to legacy-packages/, templates to examples/
- Move 15 old workflow-* packages to legacy-packages/ (inactive, preserved for reference)
- Rename templates/ → examples/ for clarity
- Rewrite docs/architecture.md to reflect current uwf architecture
- Active packages remain in packages/: cli-uwf, uwf-agent-hermes, uwf-agent-kit, uwf-moderator, uwf-protocol, workflow-util
小橘 🍊(NEKO Team)
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# @uncaged/workflow-protocol
|
||||
|
||||
## 0.5.0-alpha.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- f74b482: fix: correct internal dependency versions for prerelease
|
||||
- f74b482: fix: use npm publish with pinned deps instead of bun publish (workspace:^ resolution bug)
|
||||
|
||||
## 0.5.0-alpha.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: use npm publish with pinned deps instead of bun publish (workspace:^ resolution bug)
|
||||
|
||||
## 0.5.0-alpha.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: correct internal dependency versions for prerelease
|
||||
|
||||
## 0.5.0-alpha.1
|
||||
|
||||
## 0.5.0-alpha.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- feat: AgentFn<Opt> type boundary and createAgentAdapter bridging function (RFC #252)
|
||||
|
||||
## 0.4.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Add publishConfig to all packages for Gitea registry compatibility with changeset publish.
|
||||
|
||||
## 0.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Test changeset publish with Gitea registry.
|
||||
|
||||
## 0.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Include src/ in published packages so bun runtime can resolve the 'bun' exports condition.
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Fix workspace dependency resolution: use workspace:^ so published packages resolve to compatible versions instead of exact (non-existent) versions.
|
||||
|
||||
## 0.4.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- Fix package exports for published packages and adopt changesets for version management.
|
||||
@@ -0,0 +1,29 @@
|
||||
# @uncaged/workflow-protocol
|
||||
|
||||
Shared workflow types, sentinel constants, and `Result` helpers.
|
||||
|
||||
## What This Package Does
|
||||
|
||||
It defines the cross-package contract for bundles and the engine: thread/step shapes, `WorkflowFn`, agent/extract contexts, descriptor types, and `CasStore` as an interface. Implementations (CAS store, CLI, extract) depend on these types so bundles stay decoupled from Node APIs.
|
||||
|
||||
## Key Exports
|
||||
|
||||
From `src/index.ts`:
|
||||
|
||||
- **Types:** `Result`, `CasStore`, `WorkflowRoleSchema`, `WorkflowRoleDescriptor`, `WorkflowDescriptor`, `RoleMeta`, `RoleOutput`, `StartStep`, `RoleStep`, `ThreadContext`, `ModeratorContext`, `AgentContext`, `ExtractContext`, `WorkflowCompletion`, `WorkflowResult`, `LlmProvider`, `ProviderConfig`, `ResolvedModel`, `WorkflowConfig`, `ExtractFn`, `AgentFn`, `AgentBinding`, `WorkflowRuntime`, `WorkflowFn`, `RoleDefinition`, `Moderator`, `WorkflowDefinition`, `AdvanceOutcome`
|
||||
- **Constants:** `START`, `END`
|
||||
- **Functions:** `ok`, `err`
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Peer:** `zod` ^4 — used in type positions for schemas (`ExtractFn`, `RoleDefinition`, etc.)
|
||||
|
||||
No workspace packages; this is the bottom layer.
|
||||
|
||||
## Usage
|
||||
|
||||
```typescript
|
||||
import { END, START, type WorkflowFn, type ThreadContext } from "@uncaged/workflow-protocol";
|
||||
```
|
||||
|
||||
Concrete `WorkflowFn` implementations are built with `@uncaged/workflow-runtime` (`createWorkflow`).
|
||||
@@ -0,0 +1,154 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
import { tableToModerator } from "../src/moderator-table.js";
|
||||
import type { ModeratorContext, ModeratorTable, StartStep } from "../src/types.js";
|
||||
import { END, START } from "../src/types.js";
|
||||
|
||||
type TestMeta = {
|
||||
planner: { plan: string };
|
||||
coder: { code: string };
|
||||
reviewer: { approved: boolean };
|
||||
};
|
||||
|
||||
function makeCtx(roles: (keyof TestMeta & string)[]): ModeratorContext<TestMeta> {
|
||||
const steps = roles.map((role, i) => ({
|
||||
role,
|
||||
meta: {} as TestMeta[typeof role],
|
||||
contentHash: `hash-${i}`,
|
||||
refs: [],
|
||||
timestamp: Date.now() + i,
|
||||
}));
|
||||
return {
|
||||
threadId: "test-thread",
|
||||
depth: 0,
|
||||
bundleHash: "TESTHASH00001",
|
||||
start: {
|
||||
role: START,
|
||||
content: "test",
|
||||
meta: {},
|
||||
timestamp: Date.now(),
|
||||
parentState: null,
|
||||
} as StartStep,
|
||||
steps,
|
||||
};
|
||||
}
|
||||
|
||||
describe("tableToModerator", () => {
|
||||
test("START -> role A (FALLBACK) returns A on first call", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [{ condition: "FALLBACK", role: "planner" }],
|
||||
planner: [],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
expect(mod(makeCtx([]))).toBe("planner");
|
||||
});
|
||||
|
||||
test("condition true wins over FALLBACK", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [
|
||||
{
|
||||
condition: {
|
||||
name: "always",
|
||||
description: "always true",
|
||||
check: () => true,
|
||||
},
|
||||
role: "planner",
|
||||
},
|
||||
{ condition: "FALLBACK", role: "coder" },
|
||||
],
|
||||
planner: [],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
expect(mod(makeCtx([]))).toBe("planner");
|
||||
});
|
||||
|
||||
test("condition false falls through to FALLBACK", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [
|
||||
{
|
||||
condition: {
|
||||
name: "never",
|
||||
description: "always false",
|
||||
check: () => false,
|
||||
},
|
||||
role: "planner",
|
||||
},
|
||||
{ condition: "FALLBACK", role: "coder" },
|
||||
],
|
||||
planner: [],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
expect(mod(makeCtx([]))).toBe("coder");
|
||||
});
|
||||
|
||||
test("no matching transitions returns END", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [
|
||||
{
|
||||
condition: {
|
||||
name: "never",
|
||||
description: "always false",
|
||||
check: () => false,
|
||||
},
|
||||
role: "planner",
|
||||
},
|
||||
],
|
||||
planner: [],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
expect(mod(makeCtx([]))).toBe(END);
|
||||
});
|
||||
|
||||
test("multi-step: A -> FALLBACK END returns END after A", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [{ condition: "FALLBACK", role: "planner" }],
|
||||
planner: [{ condition: "FALLBACK", role: END }],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
expect(mod(makeCtx(["planner"]))).toBe(END);
|
||||
});
|
||||
|
||||
test("role not in table returns END", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [{ condition: "FALLBACK", role: "planner" }],
|
||||
planner: [{ condition: "FALLBACK", role: "coder" }],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
// coder has empty transitions array
|
||||
expect(mod(makeCtx(["planner", "coder"]))).toBe(END);
|
||||
});
|
||||
|
||||
test("condition receives ctx", () => {
|
||||
const table: ModeratorTable<TestMeta> = {
|
||||
[START]: [
|
||||
{
|
||||
condition: {
|
||||
name: "has-steps",
|
||||
description: "checks ctx.steps",
|
||||
check: (ctx) => ctx.steps.length > 0,
|
||||
},
|
||||
role: "coder",
|
||||
},
|
||||
{ condition: "FALLBACK", role: "planner" },
|
||||
],
|
||||
planner: [],
|
||||
coder: [],
|
||||
reviewer: [],
|
||||
};
|
||||
const mod = tableToModerator(table);
|
||||
// No steps -> condition false -> FALLBACK -> planner
|
||||
expect(mod(makeCtx([]))).toBe("planner");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@uncaged/workflow-protocol",
|
||||
"version": "0.5.0-alpha.4",
|
||||
"files": [
|
||||
"src",
|
||||
"dist",
|
||||
"package.json"
|
||||
],
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"bun": "./src/index.ts",
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
},
|
||||
"./moderator-table.js": {
|
||||
"bun": "./src/moderator-table.ts",
|
||||
"types": "./dist/moderator-table.d.ts",
|
||||
"import": "./dist/moderator-table.js"
|
||||
}
|
||||
},
|
||||
"peerDependencies": {
|
||||
"zod": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"zod": "^4.0.0",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
typescript:
|
||||
specifier: ^5.8.3
|
||||
version: 5.9.3
|
||||
zod:
|
||||
specifier: ^4.0.0
|
||||
version: 4.4.3
|
||||
|
||||
packages:
|
||||
|
||||
typescript@5.9.3:
|
||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
zod@4.4.3:
|
||||
resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
|
||||
|
||||
snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
zod@4.4.3: {}
|
||||
@@ -0,0 +1,39 @@
|
||||
// ── CAS thread chain nodes (RFC: CAS-based thread storage) ──────────
|
||||
|
||||
export type StartNodePayload = {
|
||||
name: string;
|
||||
hash: string;
|
||||
depth: number;
|
||||
/** Parent thread's head state hash at spawn time. `null` for top-level workflows. */
|
||||
parentState: string | null;
|
||||
};
|
||||
|
||||
export type StartNode = {
|
||||
type: "start";
|
||||
payload: StartNodePayload;
|
||||
refs: string[];
|
||||
};
|
||||
|
||||
export type StateNodePayload = {
|
||||
role: string;
|
||||
meta: Record<string, unknown>;
|
||||
start: string;
|
||||
content: string;
|
||||
ancestors: string[];
|
||||
compact: string | null;
|
||||
timestamp: number;
|
||||
/** Child thread's final state hash (workflow-as-agent). `null` when no child spawned. */
|
||||
childThread: string | null;
|
||||
};
|
||||
|
||||
export type StateNode = {
|
||||
type: "state";
|
||||
payload: StateNodePayload;
|
||||
refs: string[];
|
||||
};
|
||||
|
||||
export type ContentMerkleNode = {
|
||||
type: "content";
|
||||
payload: string;
|
||||
refs: string[];
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
// ── Types ──────────────────────────────────────────────────────────
|
||||
|
||||
export type {
|
||||
ContentMerkleNode,
|
||||
StartNode,
|
||||
StartNodePayload,
|
||||
StateNode,
|
||||
StateNodePayload,
|
||||
} from "./cas-types.js";
|
||||
|
||||
export type {
|
||||
AdapterBinding,
|
||||
AdapterFn,
|
||||
AdvanceOutcome,
|
||||
AgentContext,
|
||||
AgentFn,
|
||||
CasStore,
|
||||
ExtractFn,
|
||||
ExtractResult,
|
||||
FALLBACK,
|
||||
LlmProvider,
|
||||
ModeratorCondition,
|
||||
ModeratorContext,
|
||||
ModeratorTable,
|
||||
ModeratorTransition,
|
||||
ProviderConfig,
|
||||
ResolvedModel,
|
||||
Result,
|
||||
RoleDefinition,
|
||||
RoleFn,
|
||||
RoleMeta,
|
||||
RoleOutput,
|
||||
RoleResult,
|
||||
RoleStep,
|
||||
StartStep,
|
||||
ThreadContext,
|
||||
WorkflowCompletion,
|
||||
WorkflowConfig,
|
||||
WorkflowDefinition,
|
||||
WorkflowDescriptor,
|
||||
WorkflowFn,
|
||||
WorkflowGraph,
|
||||
WorkflowGraphEdge,
|
||||
WorkflowResult,
|
||||
WorkflowRoleDescriptor,
|
||||
WorkflowRoleSchema,
|
||||
WorkflowRuntime,
|
||||
} from "./types.js";
|
||||
|
||||
// ── Constants ──────────────────────────────────────────────────────
|
||||
|
||||
export { END, START } from "./types.js";
|
||||
|
||||
// ── Constructor functions ──────────────────────────────────────────
|
||||
|
||||
export { err, ok } from "./result.js";
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { Moderator, ModeratorTable, RoleMeta } from "./types.js";
|
||||
import { END, START } from "./types.js";
|
||||
|
||||
export function tableToModerator<M extends RoleMeta>(table: ModeratorTable<M>): Moderator<M> {
|
||||
return (ctx) => {
|
||||
const lastStep = ctx.steps.length > 0 ? ctx.steps[ctx.steps.length - 1] : null;
|
||||
const currentRole: string = lastStep ? lastStep.role : START;
|
||||
|
||||
const transitions = (table as Record<string, (typeof table)[string]>)[currentRole];
|
||||
if (!transitions) {
|
||||
return END;
|
||||
}
|
||||
|
||||
for (const transition of transitions) {
|
||||
if (transition.condition === "FALLBACK" || transition.condition.check(ctx)) {
|
||||
return transition.role;
|
||||
}
|
||||
}
|
||||
|
||||
return END;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { Result } from "./types.js";
|
||||
|
||||
export function ok<T>(value: T): Result<T, never> {
|
||||
return { ok: true, value };
|
||||
}
|
||||
|
||||
export function err<E>(error: E): Result<never, E> {
|
||||
return { ok: false, error };
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
import type * as z from "zod/v4";
|
||||
|
||||
// ── Constants ──────────────────────────────────────────────────────
|
||||
|
||||
export const START = "__start__" as const;
|
||||
export const END = "__end__" as const;
|
||||
|
||||
// ── Result ─────────────────────────────────────────────────────────
|
||||
|
||||
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
|
||||
|
||||
// ── CAS ────────────────────────────────────────────────────────────
|
||||
|
||||
export type CasStore = {
|
||||
put(content: string): Promise<string>;
|
||||
get(hash: string): Promise<string | null>;
|
||||
delete(hash: string): Promise<void>;
|
||||
list(): Promise<string[]>;
|
||||
};
|
||||
|
||||
// ── Workflow Descriptor ────────────────────────────────────────────
|
||||
|
||||
export type WorkflowRoleSchema = Record<string, unknown>;
|
||||
|
||||
export type WorkflowRoleDescriptor = {
|
||||
description: string;
|
||||
systemPrompt: string;
|
||||
schema: WorkflowRoleSchema;
|
||||
};
|
||||
|
||||
/** Serializable routing edges derived from a moderator transition table. */
|
||||
export type WorkflowGraphEdge = {
|
||||
from: string;
|
||||
to: string;
|
||||
condition: string;
|
||||
conditionDescription: string | null;
|
||||
};
|
||||
|
||||
export type WorkflowGraph = {
|
||||
edges: readonly WorkflowGraphEdge[];
|
||||
};
|
||||
|
||||
export type WorkflowDescriptor = {
|
||||
description: string;
|
||||
roles: Record<string, WorkflowRoleDescriptor>;
|
||||
graph: WorkflowGraph;
|
||||
};
|
||||
|
||||
// ── Role & Thread ──────────────────────────────────────────────────
|
||||
|
||||
export type RoleMeta = Record<string, Record<string, unknown>>;
|
||||
|
||||
export type RoleOutput = {
|
||||
role: string;
|
||||
contentHash: string;
|
||||
meta: Record<string, unknown>;
|
||||
refs: string[];
|
||||
childThread: string | null;
|
||||
};
|
||||
|
||||
export type StartStep = {
|
||||
role: typeof START;
|
||||
content: string;
|
||||
meta: Record<string, never>;
|
||||
timestamp: number;
|
||||
parentState: string | null;
|
||||
};
|
||||
|
||||
export type RoleStep<M extends RoleMeta> = {
|
||||
[K in keyof M & string]: {
|
||||
role: K;
|
||||
meta: M[K];
|
||||
contentHash: string;
|
||||
refs: string[];
|
||||
timestamp: number;
|
||||
};
|
||||
}[keyof M & string];
|
||||
|
||||
export type ThreadContext<M extends RoleMeta = RoleMeta> = {
|
||||
threadId: string;
|
||||
depth: number;
|
||||
bundleHash: string;
|
||||
start: StartStep;
|
||||
steps: RoleStep<M>[];
|
||||
};
|
||||
|
||||
export type ModeratorContext<M extends RoleMeta = RoleMeta> = ThreadContext<M>;
|
||||
|
||||
export type AgentContext<M extends RoleMeta = RoleMeta> = ModeratorContext<M> & {
|
||||
currentRole: {
|
||||
name: string;
|
||||
systemPrompt: string;
|
||||
};
|
||||
};
|
||||
|
||||
// ── Workflow Completion ────────────────────────────────────────────
|
||||
|
||||
export type WorkflowCompletion = {
|
||||
returnCode: number;
|
||||
summary: string;
|
||||
};
|
||||
|
||||
export type WorkflowResult = WorkflowCompletion & {
|
||||
rootHash: string;
|
||||
};
|
||||
|
||||
// ── LLM Provider ───────────────────────────────────────────────────
|
||||
|
||||
export type LlmProvider = {
|
||||
baseUrl: string;
|
||||
apiKey: string;
|
||||
model: string;
|
||||
};
|
||||
|
||||
export type ProviderConfig = {
|
||||
baseUrl: string;
|
||||
apiKey: string;
|
||||
};
|
||||
|
||||
export type ResolvedModel = {
|
||||
baseUrl: string;
|
||||
apiKey: string;
|
||||
model: string;
|
||||
};
|
||||
|
||||
export type WorkflowConfig = {
|
||||
maxDepth: number;
|
||||
supervisorInterval: number;
|
||||
providers: Record<string, ProviderConfig>;
|
||||
models: Record<string, string>;
|
||||
};
|
||||
|
||||
// ── Functions ──────────────────────────────────────────────────────
|
||||
|
||||
/** Structured output of the extract phase (RFC v3 content Merkle + artifact refs). */
|
||||
export type ExtractResult<T extends Record<string, unknown>> = {
|
||||
meta: T;
|
||||
contentPayload: string;
|
||||
refs: string[];
|
||||
};
|
||||
|
||||
export type ExtractFn = <T extends Record<string, unknown>>(
|
||||
schema: z.ZodType<T>,
|
||||
contentHash: string,
|
||||
) => Promise<ExtractResult<T>>;
|
||||
|
||||
// ── Adapter (replaces Agent) ────────────────────────────────────────
|
||||
|
||||
export type RoleResult<T> = { meta: T; childThread: string | null };
|
||||
|
||||
export type RoleFn<T> = (ctx: ThreadContext, runtime: WorkflowRuntime) => Promise<RoleResult<T>>;
|
||||
|
||||
export type AdapterFn = <T>(prompt: string, schema: z.ZodType<T>) => RoleFn<T>;
|
||||
|
||||
/**
|
||||
* Core agent function. Input is always {@link ThreadContext}, output is always string.
|
||||
* `Opt` captures agent-specific structured options (required second argument).
|
||||
*/
|
||||
export type AgentFn<Opt> = (ctx: ThreadContext, options: Opt) => Promise<string>;
|
||||
|
||||
export type AdapterBinding = {
|
||||
adapter: AdapterFn;
|
||||
overrides: Partial<Record<string, AdapterFn>> | null;
|
||||
};
|
||||
|
||||
// ── Workflow Runtime & Definition ──────────────────────────────────
|
||||
|
||||
export type WorkflowRuntime = {
|
||||
cas: CasStore;
|
||||
extract: ExtractFn;
|
||||
};
|
||||
|
||||
export type WorkflowFn = (
|
||||
thread: ThreadContext,
|
||||
runtime: WorkflowRuntime,
|
||||
) => AsyncGenerator<RoleOutput, WorkflowCompletion>;
|
||||
|
||||
export type RoleDefinition<Meta extends Record<string, unknown>> = {
|
||||
description: string;
|
||||
systemPrompt: string;
|
||||
schema: z.ZodType<Meta>;
|
||||
};
|
||||
|
||||
export type Moderator<M extends RoleMeta> = (
|
||||
ctx: ModeratorContext<M>,
|
||||
) => (keyof M & string) | typeof END;
|
||||
|
||||
export type WorkflowDefinition<M extends RoleMeta> = {
|
||||
description: string;
|
||||
roles: { [K in keyof M & string]: RoleDefinition<M[K]> };
|
||||
table: ModeratorTable<M>;
|
||||
};
|
||||
|
||||
// ── Declarative Moderator Table ────────────────────────────────────
|
||||
|
||||
export type ModeratorCondition<M extends RoleMeta> = {
|
||||
name: string;
|
||||
description: string;
|
||||
check: (ctx: ModeratorContext<M>) => boolean;
|
||||
};
|
||||
|
||||
export type FALLBACK = "FALLBACK";
|
||||
|
||||
export type ModeratorTransition<M extends RoleMeta> = {
|
||||
condition: ModeratorCondition<M> | FALLBACK;
|
||||
role: (keyof M & string) | typeof END;
|
||||
};
|
||||
|
||||
export type ModeratorTable<M extends RoleMeta> = Record<
|
||||
(keyof M & string) | typeof START,
|
||||
ModeratorTransition<M>[]
|
||||
>;
|
||||
|
||||
// ── Advance Outcome ────────────────────────────────────────────────
|
||||
|
||||
export type AdvanceOutcome<M extends RoleMeta> =
|
||||
| { kind: "complete"; completion: WorkflowCompletion }
|
||||
| { kind: "yield"; output: RoleOutput; step: RoleStep<M> };
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Reference in New Issue
Block a user