Merge pull request 'chore: enforce folder module discipline in @uncaged/workflow' (#107) from chore/106-workflow-module-discipline into main
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
import type { RoleMeta, WorkflowDefinition } from "../types.js";
|
import type { RoleMeta, WorkflowDefinition } from "../types.js";
|
||||||
import type { WorkflowDescriptor, WorkflowRoleSchema } from "./workflow-descriptor.js";
|
import type { WorkflowDescriptor, WorkflowRoleSchema } from "./types.js";
|
||||||
|
|
||||||
function stripJsonSchemaMeta(json: Record<string, unknown>): WorkflowRoleSchema {
|
function stripJsonSchemaMeta(json: Record<string, unknown>): WorkflowRoleSchema {
|
||||||
const { $schema: _drop, ...rest } = json;
|
const { $schema: _drop, ...rest } = json;
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ import type {
|
|||||||
Program,
|
Program,
|
||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
} from "acorn";
|
} from "acorn";
|
||||||
|
import * as acorn from "acorn";
|
||||||
|
|
||||||
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
|
|
||||||
|
import type { WorkflowBundleValidationInput } from "./types.js";
|
||||||
|
|
||||||
/** Acorn Node with index-access for property traversal. */
|
/** Acorn Node with index-access for property traversal. */
|
||||||
type AcornNode = Node & { [key: string]: unknown };
|
type AcornNode = Node & { [key: string]: unknown };
|
||||||
@@ -22,17 +27,6 @@ function narrowNode<T extends Node>(node: Node): T {
|
|||||||
return node as unknown as T;
|
return node as unknown as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
import * as acorn from "acorn";
|
|
||||||
|
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
|
||||||
|
|
||||||
export type WorkflowBundleValidationInput = {
|
|
||||||
/** Absolute or relative path (used for `.esm.js` suffix checks). */
|
|
||||||
filePath: string;
|
|
||||||
/** UTF-8 source of the bundle. */
|
|
||||||
source: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function endsWithEsmJs(path: string): boolean {
|
function endsWithEsmJs(path: string): boolean {
|
||||||
return path.endsWith(".esm.js");
|
return path.endsWith(".esm.js");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
import type { WorkflowFn } from "../types.js";
|
import type { WorkflowFn } from "../types.js";
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
import { importWorkflowBundleModule } from "./bundle-import-env.js";
|
import { importWorkflowBundleModule } from "./bundle-import-env.js";
|
||||||
import { ensureUncagedWorkflowSymlink } from "./ensure-uncaged-workflow-symlink.js";
|
import { ensureUncagedWorkflowSymlink } from "./ensure-uncaged-workflow-symlink.js";
|
||||||
import type { WorkflowDescriptor } from "./workflow-descriptor.js";
|
import type { ExtractBundleExportsOptions, ExtractedBundleExports } from "./types.js";
|
||||||
import { validateWorkflowDescriptor } from "./workflow-descriptor.js";
|
import { validateWorkflowDescriptor } from "./workflow-descriptor.js";
|
||||||
|
|
||||||
export type ExtractedBundleExports = {
|
|
||||||
run: WorkflowFn;
|
|
||||||
descriptor: WorkflowDescriptor;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExtractBundleExportsOptions = {
|
|
||||||
/** When set, ensures `node_modules/@uncaged/workflow` exists under this root before import. */
|
|
||||||
storageRoot: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Load a workflow `.esm.js` bundle and read its named exports (`run`, `descriptor`). */
|
/** Load a workflow `.esm.js` bundle and read its named exports (`run`, `descriptor`). */
|
||||||
export async function extractBundleExports(
|
export async function extractBundleExports(
|
||||||
bundlePath: string,
|
bundlePath: string,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { stringify } from "yaml";
|
import { stringify } from "yaml";
|
||||||
|
|
||||||
import type { WorkflowDescriptor } from "./workflow-descriptor.js";
|
import type { WorkflowDescriptor } from "./types.js";
|
||||||
|
|
||||||
/** Serialize a validated workflow descriptor to YAML for storage next to the bundle. */
|
/** Serialize a validated workflow descriptor to YAML for storage next to the bundle. */
|
||||||
export function stringifyWorkflowDescriptor(descriptor: WorkflowDescriptor): string {
|
export function stringifyWorkflowDescriptor(descriptor: WorkflowDescriptor): string {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
export { buildDescriptor } from "./build-descriptor.js";
|
||||||
|
export { importWorkflowBundleModule } from "./bundle-import-env.js";
|
||||||
|
export { validateWorkflowBundle } from "./bundle-validator.js";
|
||||||
|
export { ensureUncagedWorkflowSymlink } from "./ensure-uncaged-workflow-symlink.js";
|
||||||
|
export { extractBundleExports } from "./extract-bundle-exports.js";
|
||||||
|
export { stringifyWorkflowDescriptor } from "./generate-descriptor.js";
|
||||||
|
export type {
|
||||||
|
ExtractBundleExportsOptions,
|
||||||
|
ExtractedBundleExports,
|
||||||
|
WorkflowBundleValidationInput,
|
||||||
|
WorkflowDescriptor,
|
||||||
|
WorkflowRoleDescriptor,
|
||||||
|
WorkflowRoleSchema,
|
||||||
|
} from "./types.js";
|
||||||
|
export { validateWorkflowDescriptor } from "./workflow-descriptor.js";
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import type { WorkflowFn } from "../types.js";
|
||||||
|
|
||||||
|
/** JSON Schema fragment describing one role's `meta` shape (subset supported by code generation). */
|
||||||
|
export type WorkflowRoleSchema = Record<string, unknown>;
|
||||||
|
|
||||||
|
export type WorkflowRoleDescriptor = {
|
||||||
|
description: string;
|
||||||
|
schema: WorkflowRoleSchema;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Workflow metadata exported as `export const descriptor` from `.esm.js` bundles. */
|
||||||
|
export type WorkflowDescriptor = {
|
||||||
|
description: string;
|
||||||
|
roles: Record<string, WorkflowRoleDescriptor>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WorkflowBundleValidationInput = {
|
||||||
|
/** Absolute or relative path (used for `.esm.js` suffix checks). */
|
||||||
|
filePath: string;
|
||||||
|
/** UTF-8 source of the bundle. */
|
||||||
|
source: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtractedBundleExports = {
|
||||||
|
run: WorkflowFn;
|
||||||
|
descriptor: WorkflowDescriptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtractBundleExportsOptions = {
|
||||||
|
/** When set, ensures `node_modules/@uncaged/workflow` exists under this root before import. */
|
||||||
|
storageRoot: string | null;
|
||||||
|
};
|
||||||
@@ -1,18 +1,6 @@
|
|||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
|
|
||||||
/** JSON Schema fragment describing one role's `meta` shape (subset supported by code generation). */
|
import type { WorkflowDescriptor, WorkflowRoleDescriptor, WorkflowRoleSchema } from "./types.js";
|
||||||
export type WorkflowRoleSchema = Record<string, unknown>;
|
|
||||||
|
|
||||||
export type WorkflowRoleDescriptor = {
|
|
||||||
description: string;
|
|
||||||
schema: WorkflowRoleSchema;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Workflow metadata exported as `export const descriptor` from `.esm.js` bundles. */
|
|
||||||
export type WorkflowDescriptor = {
|
|
||||||
description: string;
|
|
||||||
roles: Record<string, WorkflowRoleDescriptor>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function validateWorkflowDescriptor(value: unknown): Result<WorkflowDescriptor, string> {
|
export function validateWorkflowDescriptor(value: unknown): Result<WorkflowDescriptor, string> {
|
||||||
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
||||||
|
|||||||
@@ -2,13 +2,7 @@ import { mkdir, readdir, readFile, rename, unlink, writeFile } from "node:fs/pro
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { hashString } from "./hash.js";
|
import { hashString } from "./hash.js";
|
||||||
|
import type { CasStore } from "./types.js";
|
||||||
export type CasStore = {
|
|
||||||
put(content: string): Promise<string>;
|
|
||||||
get(hash: string): Promise<string | null>;
|
|
||||||
delete(hash: string): Promise<void>;
|
|
||||||
list(): Promise<string[]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createCasStore(casDir: string): CasStore {
|
export function createCasStore(casDir: string): CasStore {
|
||||||
async function ensureDir(): Promise<void> {
|
async function ensureDir(): Promise<void> {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Buffer } from "node:buffer";
|
|||||||
|
|
||||||
import XXH from "xxhashjs";
|
import XXH from "xxhashjs";
|
||||||
|
|
||||||
import { encodeUint64AsCrockford } from "../util/base32.js";
|
import { encodeUint64AsCrockford } from "../util/index.js";
|
||||||
|
|
||||||
function digestToUint64(digest: { toString(radix?: number): string }): bigint {
|
function digestToUint64(digest: { toString(radix?: number): string }): bigint {
|
||||||
const hex = digest.toString(16).padStart(16, "0");
|
const hex = digest.toString(16).padStart(16, "0");
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export { createCasStore, createThreadCas } from "./cas.js";
|
||||||
|
export { hashString, hashWorkflowBundleBytes } from "./hash.js";
|
||||||
|
export {
|
||||||
|
createContentMerkleNode,
|
||||||
|
getContentMerklePayload,
|
||||||
|
parseMerkleNode,
|
||||||
|
putContentMerkleNode,
|
||||||
|
putStepMerkleNode,
|
||||||
|
putThreadMerkleNode,
|
||||||
|
serializeMerkleNode,
|
||||||
|
} from "./merkle.js";
|
||||||
|
export type {
|
||||||
|
CasStore,
|
||||||
|
MerkleNode,
|
||||||
|
MerkleNodeType,
|
||||||
|
StepMerklePayload,
|
||||||
|
ThreadMerklePayload,
|
||||||
|
} from "./types.js";
|
||||||
@@ -1,14 +1,6 @@
|
|||||||
import { parse, stringify } from "yaml";
|
import { parse, stringify } from "yaml";
|
||||||
|
|
||||||
import type { CasStore } from "./cas.js";
|
import type { CasStore, MerkleNode, StepMerklePayload, ThreadMerklePayload } from "./types.js";
|
||||||
|
|
||||||
export type MerkleNodeType = "content" | "step" | "thread";
|
|
||||||
|
|
||||||
export type MerkleNode = {
|
|
||||||
type: MerkleNodeType;
|
|
||||||
payload: string | Record<string, unknown>;
|
|
||||||
children: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export function serializeMerkleNode(node: MerkleNode): string {
|
export function serializeMerkleNode(node: MerkleNode): string {
|
||||||
return stringify(
|
return stringify(
|
||||||
@@ -53,20 +45,6 @@ export function createContentMerkleNode(payload: string): MerkleNode {
|
|||||||
return { type: "content", payload, children: [] };
|
return { type: "content", payload, children: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StepMerklePayload = {
|
|
||||||
role: string;
|
|
||||||
meta: Record<string, unknown>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ThreadMerklePayload = {
|
|
||||||
workflow: string;
|
|
||||||
threadId: string;
|
|
||||||
result: {
|
|
||||||
returnCode: number;
|
|
||||||
summary: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Serializes a step Merkle node (role + meta + content child) and stores it in CAS. */
|
/** Serializes a step Merkle node (role + meta + content child) and stores it in CAS. */
|
||||||
export async function putStepMerkleNode(
|
export async function putStepMerkleNode(
|
||||||
store: CasStore,
|
store: CasStore,
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
export type CasStore = {
|
||||||
|
put(content: string): Promise<string>;
|
||||||
|
get(hash: string): Promise<string | null>;
|
||||||
|
delete(hash: string): Promise<void>;
|
||||||
|
list(): Promise<string[]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MerkleNodeType = "content" | "step" | "thread";
|
||||||
|
|
||||||
|
export type MerkleNode = {
|
||||||
|
type: MerkleNodeType;
|
||||||
|
payload: string | Record<string, unknown>;
|
||||||
|
children: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StepMerklePayload = {
|
||||||
|
role: string;
|
||||||
|
meta: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ThreadMerklePayload = {
|
||||||
|
workflow: string;
|
||||||
|
threadId: string;
|
||||||
|
result: {
|
||||||
|
returnCode: number;
|
||||||
|
summary: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { CasStore } from "../cas/cas.js";
|
import type { CasStore } from "../cas/index.js";
|
||||||
import { putContentMerkleNode } from "../cas/merkle.js";
|
import { putContentMerkleNode } from "../cas/index.js";
|
||||||
import { buildExtractUserContent, type ExtractFn } from "../extract/extract-fn.js";
|
import { buildExtractUserContent, type ExtractFn, reactExtract } from "../extract/index.js";
|
||||||
import { reactExtract } from "../extract/react-extract.js";
|
|
||||||
import {
|
import {
|
||||||
type AgentBinding,
|
type AgentBinding,
|
||||||
type AgentContext,
|
type AgentContext,
|
||||||
@@ -20,7 +19,7 @@ import {
|
|||||||
type WorkflowFn,
|
type WorkflowFn,
|
||||||
type WorkflowFnOptions,
|
type WorkflowFnOptions,
|
||||||
} from "../types.js";
|
} from "../types.js";
|
||||||
import { mergeRefsWithContentHash } from "../util/refs-field.js";
|
import { mergeRefsWithContentHash } from "../util/index.js";
|
||||||
|
|
||||||
function isRoleNext<M extends RoleMeta>(
|
function isRoleNext<M extends RoleMeta>(
|
||||||
next: (keyof M & string) | typeof END,
|
next: (keyof M & string) | typeof END,
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { appendFile, mkdir } from "node:fs/promises";
|
import { appendFile, mkdir } from "node:fs/promises";
|
||||||
import { dirname } from "node:path";
|
import { dirname } from "node:path";
|
||||||
|
|
||||||
import type { CasStore } from "../cas/cas.js";
|
import {
|
||||||
import { getContentMerklePayload, putStepMerkleNode, putThreadMerkleNode } from "../cas/merkle.js";
|
type CasStore,
|
||||||
|
getContentMerklePayload,
|
||||||
|
putStepMerkleNode,
|
||||||
|
putThreadMerkleNode,
|
||||||
|
} from "../cas/index.js";
|
||||||
import type {
|
import type {
|
||||||
ThreadInput,
|
ThreadInput,
|
||||||
WorkflowCompletion,
|
WorkflowCompletion,
|
||||||
@@ -10,41 +14,9 @@ import type {
|
|||||||
WorkflowFnOptions,
|
WorkflowFnOptions,
|
||||||
WorkflowResult,
|
WorkflowResult,
|
||||||
} from "../types.js";
|
} from "../types.js";
|
||||||
import type { LogFn } from "../util/logger.js";
|
import { type LogFn, normalizeRefsField } from "../util/index.js";
|
||||||
import { normalizeRefsField } from "../util/refs-field.js";
|
|
||||||
|
|
||||||
export type ExecuteThreadIo = {
|
import type { ExecuteThreadIo, ExecuteThreadOptions } from "./types.js";
|
||||||
threadId: string;
|
|
||||||
hash: string;
|
|
||||||
dataJsonlPath: string;
|
|
||||||
infoJsonlPath: string;
|
|
||||||
cas: CasStore;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** One persisted role line in `.data.jsonl` (engine adds these for fork replay before running the generator). */
|
|
||||||
export type PrefilledDiskStep = {
|
|
||||||
role: string;
|
|
||||||
contentHash: string;
|
|
||||||
meta: Record<string, unknown>;
|
|
||||||
refs: string[];
|
|
||||||
timestamp: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ExecuteThreadOptions = {
|
|
||||||
maxRounds: number;
|
|
||||||
/** Passed to the bundle as `WorkflowFnOptions.depth`. */
|
|
||||||
depth: number;
|
|
||||||
signal: AbortSignal;
|
|
||||||
/** Invoked after each successful yield (and outer-loop checks); used for pause/resume. */
|
|
||||||
awaitAfterEachYield: () => Promise<void>;
|
|
||||||
/** When non-null, written into the start record so tooling can trace lineage. */
|
|
||||||
forkSourceThreadId: string | null;
|
|
||||||
/**
|
|
||||||
* Written to `.data.jsonl` immediately after the start record, before the generator runs.
|
|
||||||
* Must match `input.steps` length and order when present.
|
|
||||||
*/
|
|
||||||
prefilledDiskSteps: PrefilledDiskStep[] | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function appendDataLine(path: string, record: unknown): Promise<void> {
|
async function appendDataLine(path: string, record: unknown): Promise<void> {
|
||||||
const line = `${JSON.stringify(record)}\n`;
|
const line = `${JSON.stringify(record)}\n`;
|
||||||
|
|||||||
@@ -1,18 +1,7 @@
|
|||||||
import type { RoleOutput, WorkflowCompletion } from "../types.js";
|
import type { WorkflowCompletion } from "../types.js";
|
||||||
import { normalizeRefsField } from "../util/refs-field.js";
|
import { err, normalizeRefsField, ok, type Result } from "../util/index.js";
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
|
||||||
|
|
||||||
/** Role steps replayed from `.data.jsonl`, including persisted timestamps. */
|
import type { ForkHistoricalStep, ForkPlan, ParsedThreadStartRecord } from "./types.js";
|
||||||
export type ForkHistoricalStep = RoleOutput & { timestamp: number };
|
|
||||||
|
|
||||||
export type ParsedThreadStartRecord = {
|
|
||||||
workflowName: string;
|
|
||||||
hash: string;
|
|
||||||
threadId: string;
|
|
||||||
prompt: string;
|
|
||||||
maxRounds: number;
|
|
||||||
depth: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Recognizes a persisted workflow completion line (no `role`; has numeric `returnCode` and string `summary`). Omits `rootHash` when absent. */
|
/** Recognizes a persisted workflow completion line (no `role`; has numeric `returnCode` and string `summary`). Omits `rootHash` when absent. */
|
||||||
export function tryParseWorkflowResultRecord(
|
export function tryParseWorkflowResultRecord(
|
||||||
@@ -228,15 +217,6 @@ export function selectForkHistoricalSteps(
|
|||||||
return ok(roleSteps.slice(0, idx + 1));
|
return ok(roleSteps.slice(0, idx + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ForkPlan = {
|
|
||||||
workflowName: string;
|
|
||||||
hash: string;
|
|
||||||
sourceThreadId: string;
|
|
||||||
prompt: string;
|
|
||||||
runOptions: { maxRounds: number; depth: number };
|
|
||||||
historicalSteps: ForkHistoricalStep[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read `.data.jsonl` text and compute fork payload for the worker `run` command.
|
* Read `.data.jsonl` text and compute fork payload for the worker `run` command.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
import { readdir, readFile } from "node:fs/promises";
|
import { readdir, readFile } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { type CasStore, createCasStore } from "../cas/cas.js";
|
import { type CasStore, createCasStore } from "../cas/index.js";
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, getGlobalCasDir, ok, type Result } from "../util/index.js";
|
||||||
import { getGlobalCasDir } from "../util/storage-root.js";
|
|
||||||
import { parseThreadDataJsonl } from "./fork-thread.js";
|
import { parseThreadDataJsonl } from "./fork-thread.js";
|
||||||
|
import type { GcResult } from "./types.js";
|
||||||
export type GcResult = {
|
|
||||||
scannedThreads: number;
|
|
||||||
activeRefs: number;
|
|
||||||
deletedEntries: number;
|
|
||||||
deletedHashes: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
async function listThreadDataJsonlPaths(storageRoot: string): Promise<Result<string[], string>> {
|
async function listThreadDataJsonlPaths(storageRoot: string): Promise<Result<string[], string>> {
|
||||||
const logsRoot = join(storageRoot, "logs");
|
const logsRoot = join(storageRoot, "logs");
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
export { createWorkflow } from "./create-workflow.js";
|
||||||
|
export { executeThread } from "./engine.js";
|
||||||
|
export {
|
||||||
|
buildForkPlan,
|
||||||
|
parseThreadDataJsonl,
|
||||||
|
selectForkHistoricalSteps,
|
||||||
|
tryParseRoleStepRecord,
|
||||||
|
tryParseWorkflowResultRecord,
|
||||||
|
} from "./fork-thread.js";
|
||||||
|
export { garbageCollectCas } from "./gc.js";
|
||||||
|
export { createThreadPauseGate } from "./thread-pause-gate.js";
|
||||||
|
export type {
|
||||||
|
ExecuteThreadIo,
|
||||||
|
ExecuteThreadOptions,
|
||||||
|
ForkHistoricalStep,
|
||||||
|
ForkPlan,
|
||||||
|
GcResult,
|
||||||
|
ParsedThreadStartRecord,
|
||||||
|
PrefilledDiskStep,
|
||||||
|
ThreadPauseGate,
|
||||||
|
} from "./types.js";
|
||||||
|
export { getWorkerHostScriptPath } from "./worker-entry-path.js";
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
|
|
||||||
export type ThreadPauseGate = {
|
import type { ThreadPauseGate } from "./types.js";
|
||||||
awaitAfterYield: () => Promise<void>;
|
|
||||||
pause: () => Result<void, string>;
|
|
||||||
resume: () => Result<void, string>;
|
|
||||||
isPaused: () => boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause/resume gate for workflow threads: after each generator yield the engine awaits
|
* Pause/resume gate for workflow threads: after each generator yield the engine awaits
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import type { CasStore } from "../cas/index.js";
|
||||||
|
import type { RoleOutput } from "../types.js";
|
||||||
|
import type { Result } from "../util/index.js";
|
||||||
|
|
||||||
|
export type ExecuteThreadIo = {
|
||||||
|
threadId: string;
|
||||||
|
hash: string;
|
||||||
|
dataJsonlPath: string;
|
||||||
|
infoJsonlPath: string;
|
||||||
|
cas: CasStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** One persisted role line in `.data.jsonl` (engine adds these for fork replay before running the generator). */
|
||||||
|
export type PrefilledDiskStep = {
|
||||||
|
role: string;
|
||||||
|
contentHash: string;
|
||||||
|
meta: Record<string, unknown>;
|
||||||
|
refs: string[];
|
||||||
|
timestamp: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExecuteThreadOptions = {
|
||||||
|
maxRounds: number;
|
||||||
|
/** Passed to the bundle as `WorkflowFnOptions.depth`. */
|
||||||
|
depth: number;
|
||||||
|
signal: AbortSignal;
|
||||||
|
/** Invoked after each successful yield (and outer-loop checks); used for pause/resume. */
|
||||||
|
awaitAfterEachYield: () => Promise<void>;
|
||||||
|
/** When non-null, written into the start record so tooling can trace lineage. */
|
||||||
|
forkSourceThreadId: string | null;
|
||||||
|
/**
|
||||||
|
* Written to `.data.jsonl` immediately after the start record, before the generator runs.
|
||||||
|
* Must match `input.steps` length and order when present.
|
||||||
|
*/
|
||||||
|
prefilledDiskSteps: PrefilledDiskStep[] | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Role steps replayed from `.data.jsonl`, including persisted timestamps. */
|
||||||
|
export type ForkHistoricalStep = RoleOutput & { timestamp: number };
|
||||||
|
|
||||||
|
export type ParsedThreadStartRecord = {
|
||||||
|
workflowName: string;
|
||||||
|
hash: string;
|
||||||
|
threadId: string;
|
||||||
|
prompt: string;
|
||||||
|
maxRounds: number;
|
||||||
|
depth: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ForkPlan = {
|
||||||
|
workflowName: string;
|
||||||
|
hash: string;
|
||||||
|
sourceThreadId: string;
|
||||||
|
prompt: string;
|
||||||
|
runOptions: { maxRounds: number; depth: number };
|
||||||
|
historicalSteps: ForkHistoricalStep[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type GcResult = {
|
||||||
|
scannedThreads: number;
|
||||||
|
activeRefs: number;
|
||||||
|
deletedEntries: number;
|
||||||
|
deletedHashes: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ThreadPauseGate = {
|
||||||
|
awaitAfterYield: () => Promise<void>;
|
||||||
|
pause: () => Result<void, string>;
|
||||||
|
resume: () => Result<void, string>;
|
||||||
|
isPaused: () => boolean;
|
||||||
|
};
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
import { appendFile, mkdir, unlink, writeFile } from "node:fs/promises";
|
import { appendFile, mkdir, unlink, writeFile } from "node:fs/promises";
|
||||||
import { createServer, type Socket } from "node:net";
|
import { createServer, type Socket } from "node:net";
|
||||||
import { dirname, join } from "node:path";
|
import { dirname, join } from "node:path";
|
||||||
import { importWorkflowBundleModule } from "../bundle/bundle-import-env.js";
|
import { ensureUncagedWorkflowSymlink, importWorkflowBundleModule } from "../bundle/index.js";
|
||||||
import { ensureUncagedWorkflowSymlink } from "../bundle/ensure-uncaged-workflow-symlink.js";
|
import { createCasStore } from "../cas/index.js";
|
||||||
import { createCasStore } from "../cas/cas.js";
|
|
||||||
import type { RoleOutput, WorkflowFn, WorkflowResult } from "../types.js";
|
import type { RoleOutput, WorkflowFn, WorkflowResult } from "../types.js";
|
||||||
import { createLogger } from "../util/logger.js";
|
import {
|
||||||
import { normalizeRefsField } from "../util/refs-field.js";
|
createLogger,
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
err,
|
||||||
import { getGlobalCasDir } from "../util/storage-root.js";
|
getGlobalCasDir,
|
||||||
import type { PrefilledDiskStep } from "./engine.js";
|
normalizeRefsField,
|
||||||
import { type ExecuteThreadIo, executeThread } from "./engine.js";
|
ok,
|
||||||
import { createThreadPauseGate, type ThreadPauseGate } from "./thread-pause-gate.js";
|
type Result,
|
||||||
|
} from "../util/index.js";
|
||||||
|
import { executeThread } from "./engine.js";
|
||||||
|
import { createThreadPauseGate } from "./thread-pause-gate.js";
|
||||||
|
import type { ExecuteThreadIo, PrefilledDiskStep, ThreadPauseGate } from "./types.js";
|
||||||
|
|
||||||
const bootLog = createLogger({ sink: { kind: "stderr" } });
|
const bootLog = createLogger({ sink: { kind: "stderr" } });
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { readWorkflowRegistry } from "./registry/registry.js";
|
import type { WorkflowConfig } from "./registry/index.js";
|
||||||
import type { WorkflowConfig } from "./registry/registry-types.js";
|
import { readWorkflowRegistry } from "./registry/index.js";
|
||||||
import type { LlmProvider } from "./types.js";
|
import type { LlmProvider } from "./types.js";
|
||||||
import { err, ok, type Result } from "./util/result.js";
|
import { err, getDefaultWorkflowStorageRoot, ok, type Result } from "./util/index.js";
|
||||||
import { getDefaultWorkflowStorageRoot } from "./util/storage-root.js";
|
|
||||||
|
|
||||||
const DEFAULT_WORKFLOW_AS_AGENT_MAX_DEPTH = 3;
|
const DEFAULT_WORKFLOW_AS_AGENT_MAX_DEPTH = 3;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import type * as z from "zod/v4";
|
import type * as z from "zod/v4";
|
||||||
import { getContentMerklePayload } from "../cas/merkle.js";
|
|
||||||
|
import { getContentMerklePayload } from "../cas/index.js";
|
||||||
import type { ExtractContext, LlmProvider } from "../types.js";
|
import type { ExtractContext, LlmProvider } from "../types.js";
|
||||||
import { llmExtractWithRetry } from "./llm-extract.js";
|
import { llmExtractWithRetry } from "./llm-extract.js";
|
||||||
|
import type { ExtractFn } from "./types.js";
|
||||||
export type ExtractFn = <T extends Record<string, unknown>>(
|
|
||||||
schema: z.ZodType<T>,
|
|
||||||
prompt: string,
|
|
||||||
ctx: ExtractContext,
|
|
||||||
) => Promise<T>;
|
|
||||||
|
|
||||||
/** Builds the user-side extraction prompt (thread + agent output + instruction). */
|
/** Builds the user-side extraction prompt (thread + agent output + instruction). */
|
||||||
export async function buildExtractUserContent(
|
export async function buildExtractUserContent(
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
export {
|
||||||
|
buildExtractUserContent,
|
||||||
|
createExtract,
|
||||||
|
} from "./extract-fn.js";
|
||||||
|
export {
|
||||||
|
extractFunctionToolFromZodSchema,
|
||||||
|
llmErrorToCause,
|
||||||
|
llmExtract,
|
||||||
|
llmExtractWithRetry,
|
||||||
|
} from "./llm-extract.js";
|
||||||
|
export { reactExtract } from "./react-extract.js";
|
||||||
|
export type {
|
||||||
|
ExtractFn,
|
||||||
|
LlmError,
|
||||||
|
LlmExtractArgs,
|
||||||
|
ReactExtractArgs,
|
||||||
|
} from "./types.js";
|
||||||
@@ -1,20 +1,8 @@
|
|||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
import type { LlmProvider } from "../types.js";
|
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
|
||||||
|
|
||||||
export type LlmExtractArgs<T> = {
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
text: string;
|
|
||||||
schema: z.ZodType<T>;
|
|
||||||
provider: LlmProvider;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LlmError =
|
import type { LlmError, LlmExtractArgs } from "./types.js";
|
||||||
| { kind: "http_error"; status: number; body: string }
|
|
||||||
| { kind: "invalid_response_json"; message: string }
|
|
||||||
| { kind: "no_tool_call"; preview: string }
|
|
||||||
| { kind: "tool_arguments_invalid_json"; message: string }
|
|
||||||
| { kind: "schema_validation_failed"; message: string }
|
|
||||||
| { kind: "network_error"; message: string };
|
|
||||||
|
|
||||||
function chatCompletionsUrl(baseUrl: string): string {
|
function chatCompletionsUrl(baseUrl: string): string {
|
||||||
const trimmed = baseUrl.replace(/\/+$/, "");
|
const trimmed = baseUrl.replace(/\/+$/, "");
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
import type * as z from "zod/v4";
|
import type * as z from "zod/v4";
|
||||||
|
|
||||||
import type { CasStore } from "../cas/cas.js";
|
import type { CasStore } from "../cas/index.js";
|
||||||
import type { LlmProvider } from "../types.js";
|
import type { LlmProvider } from "../types.js";
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
import { extractFunctionToolFromZodSchema } from "./llm-extract.js";
|
|
||||||
|
|
||||||
export type ReactExtractArgs<T extends Record<string, unknown>> = {
|
import { extractFunctionToolFromZodSchema } from "./llm-extract.js";
|
||||||
text: string;
|
import type { ReactExtractArgs } from "./types.js";
|
||||||
schema: z.ZodType<T>;
|
|
||||||
provider: LlmProvider;
|
|
||||||
cas: CasStore;
|
|
||||||
};
|
|
||||||
|
|
||||||
const MAX_REACT_ROUNDS = 10;
|
const MAX_REACT_ROUNDS = 10;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import type * as z from "zod/v4";
|
||||||
|
|
||||||
|
import type { CasStore } from "../cas/index.js";
|
||||||
|
import type { ExtractContext, LlmProvider } from "../types.js";
|
||||||
|
|
||||||
|
export type ExtractFn = <T extends Record<string, unknown>>(
|
||||||
|
schema: z.ZodType<T>,
|
||||||
|
prompt: string,
|
||||||
|
ctx: ExtractContext,
|
||||||
|
) => Promise<T>;
|
||||||
|
|
||||||
|
export type ReactExtractArgs<T extends Record<string, unknown>> = {
|
||||||
|
text: string;
|
||||||
|
schema: z.ZodType<T>;
|
||||||
|
provider: LlmProvider;
|
||||||
|
cas: CasStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LlmExtractArgs<T> = {
|
||||||
|
text: string;
|
||||||
|
schema: z.ZodType<T>;
|
||||||
|
provider: LlmProvider;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LlmError =
|
||||||
|
| { kind: "http_error"; status: number; body: string }
|
||||||
|
| { kind: "invalid_response_json"; message: string }
|
||||||
|
| { kind: "no_tool_call"; preview: string }
|
||||||
|
| { kind: "tool_arguments_invalid_json"; message: string }
|
||||||
|
| { kind: "schema_validation_failed"; message: string }
|
||||||
|
| { kind: "network_error"; message: string };
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
export { buildDescriptor } from "./bundle/build-descriptor.js";
|
|
||||||
export {
|
|
||||||
validateWorkflowBundle,
|
|
||||||
type WorkflowBundleValidationInput,
|
|
||||||
} from "./bundle/bundle-validator.js";
|
|
||||||
export {
|
export {
|
||||||
|
buildDescriptor,
|
||||||
type ExtractedBundleExports,
|
type ExtractedBundleExports,
|
||||||
extractBundleExports,
|
extractBundleExports,
|
||||||
} from "./bundle/extract-bundle-exports.js";
|
stringifyWorkflowDescriptor,
|
||||||
export { stringifyWorkflowDescriptor } from "./bundle/generate-descriptor.js";
|
validateWorkflowBundle,
|
||||||
export {
|
|
||||||
validateWorkflowDescriptor,
|
validateWorkflowDescriptor,
|
||||||
|
type WorkflowBundleValidationInput,
|
||||||
type WorkflowDescriptor,
|
type WorkflowDescriptor,
|
||||||
type WorkflowRoleDescriptor,
|
type WorkflowRoleDescriptor,
|
||||||
type WorkflowRoleSchema,
|
type WorkflowRoleSchema,
|
||||||
} from "./bundle/workflow-descriptor.js";
|
} from "./bundle/index.js";
|
||||||
export { type CasStore, createCasStore, createThreadCas } from "./cas/cas.js";
|
|
||||||
export { hashString, hashWorkflowBundleBytes } from "./cas/hash.js";
|
|
||||||
export {
|
export {
|
||||||
|
type CasStore,
|
||||||
|
createCasStore,
|
||||||
createContentMerkleNode,
|
createContentMerkleNode,
|
||||||
|
createThreadCas,
|
||||||
getContentMerklePayload,
|
getContentMerklePayload,
|
||||||
|
hashString,
|
||||||
|
hashWorkflowBundleBytes,
|
||||||
type MerkleNode,
|
type MerkleNode,
|
||||||
type MerkleNodeType,
|
type MerkleNodeType,
|
||||||
parseMerkleNode,
|
parseMerkleNode,
|
||||||
@@ -28,35 +27,37 @@ export {
|
|||||||
type StepMerklePayload,
|
type StepMerklePayload,
|
||||||
serializeMerkleNode,
|
serializeMerkleNode,
|
||||||
type ThreadMerklePayload,
|
type ThreadMerklePayload,
|
||||||
} from "./cas/merkle.js";
|
} from "./cas/index.js";
|
||||||
export { createWorkflow } from "./engine/create-workflow.js";
|
|
||||||
export {
|
export {
|
||||||
|
buildForkPlan,
|
||||||
|
createThreadPauseGate,
|
||||||
|
createWorkflow,
|
||||||
type ExecuteThreadIo,
|
type ExecuteThreadIo,
|
||||||
type ExecuteThreadOptions,
|
type ExecuteThreadOptions,
|
||||||
executeThread,
|
executeThread,
|
||||||
type PrefilledDiskStep,
|
|
||||||
} from "./engine/engine.js";
|
|
||||||
export {
|
|
||||||
buildForkPlan,
|
|
||||||
type ForkHistoricalStep,
|
type ForkHistoricalStep,
|
||||||
type ForkPlan,
|
type ForkPlan,
|
||||||
|
type GcResult,
|
||||||
|
garbageCollectCas,
|
||||||
|
getWorkerHostScriptPath,
|
||||||
type ParsedThreadStartRecord,
|
type ParsedThreadStartRecord,
|
||||||
|
type PrefilledDiskStep,
|
||||||
parseThreadDataJsonl,
|
parseThreadDataJsonl,
|
||||||
selectForkHistoricalSteps,
|
selectForkHistoricalSteps,
|
||||||
|
type ThreadPauseGate,
|
||||||
tryParseRoleStepRecord,
|
tryParseRoleStepRecord,
|
||||||
tryParseWorkflowResultRecord,
|
tryParseWorkflowResultRecord,
|
||||||
} from "./engine/fork-thread.js";
|
} from "./engine/index.js";
|
||||||
export { type GcResult, garbageCollectCas } from "./engine/gc.js";
|
|
||||||
export { createThreadPauseGate, type ThreadPauseGate } from "./engine/thread-pause-gate.js";
|
|
||||||
export { getWorkerHostScriptPath } from "./engine/worker-entry-path.js";
|
|
||||||
export { createExtract, type ExtractFn } from "./extract/extract-fn.js";
|
|
||||||
export {
|
export {
|
||||||
|
createExtract,
|
||||||
|
type ExtractFn,
|
||||||
type LlmError,
|
type LlmError,
|
||||||
llmErrorToCause,
|
llmErrorToCause,
|
||||||
llmExtract,
|
llmExtract,
|
||||||
llmExtractWithRetry,
|
llmExtractWithRetry,
|
||||||
} from "./extract/llm-extract.js";
|
type ReactExtractArgs,
|
||||||
export { type ReactExtractArgs, reactExtract } from "./extract/react-extract.js";
|
reactExtract,
|
||||||
|
} from "./extract/index.js";
|
||||||
export { getExtractProvider } from "./extract-provider.js";
|
export { getExtractProvider } from "./extract-provider.js";
|
||||||
export {
|
export {
|
||||||
type ExtractProviderConfig,
|
type ExtractProviderConfig,
|
||||||
@@ -74,7 +75,7 @@ export {
|
|||||||
type WorkflowRegistryFile,
|
type WorkflowRegistryFile,
|
||||||
workflowRegistryPath,
|
workflowRegistryPath,
|
||||||
writeWorkflowRegistry,
|
writeWorkflowRegistry,
|
||||||
} from "./registry/registry.js";
|
} from "./registry/index.js";
|
||||||
export {
|
export {
|
||||||
type AgentBinding,
|
type AgentBinding,
|
||||||
type AgentContext,
|
type AgentContext,
|
||||||
@@ -101,18 +102,19 @@ export {
|
|||||||
} from "./types.js";
|
} from "./types.js";
|
||||||
export {
|
export {
|
||||||
CROCKFORD_BASE32_ALPHABET,
|
CROCKFORD_BASE32_ALPHABET,
|
||||||
|
type CreateLoggerOptions,
|
||||||
|
createLogger,
|
||||||
decodeCrockfordBase32Bits,
|
decodeCrockfordBase32Bits,
|
||||||
decodeCrockfordToUint64,
|
decodeCrockfordToUint64,
|
||||||
encodeCrockfordBase32Bits,
|
encodeCrockfordBase32Bits,
|
||||||
encodeUint64AsCrockford,
|
encodeUint64AsCrockford,
|
||||||
} from "./util/base32.js";
|
err,
|
||||||
export {
|
generateUlid,
|
||||||
type CreateLoggerOptions,
|
getDefaultWorkflowStorageRoot,
|
||||||
createLogger,
|
getGlobalCasDir,
|
||||||
type LogFn,
|
type LogFn,
|
||||||
type LoggerSink,
|
type LoggerSink,
|
||||||
} from "./util/logger.js";
|
ok,
|
||||||
export { err, ok, type Result } from "./util/result.js";
|
type Result,
|
||||||
export { getDefaultWorkflowStorageRoot, getGlobalCasDir } from "./util/storage-root.js";
|
} from "./util/index.js";
|
||||||
export { generateUlid } from "./util/ulid.js";
|
|
||||||
export { type WorkflowAsAgentOptions, workflowAsAgent } from "./workflow-as-agent.js";
|
export { type WorkflowAsAgentOptions, workflowAsAgent } from "./workflow-as-agent.js";
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
export {
|
||||||
|
getRegisteredWorkflow,
|
||||||
|
listRegisteredWorkflowNames,
|
||||||
|
parseWorkflowRegistryYaml,
|
||||||
|
readWorkflowRegistry,
|
||||||
|
registerWorkflowVersion,
|
||||||
|
rollbackWorkflowToHistoryHash,
|
||||||
|
stringifyWorkflowRegistryYaml,
|
||||||
|
unregisterWorkflow,
|
||||||
|
workflowRegistryPath,
|
||||||
|
writeWorkflowRegistry,
|
||||||
|
} from "./registry.js";
|
||||||
|
export type {
|
||||||
|
ExtractProviderConfig,
|
||||||
|
WorkflowConfig,
|
||||||
|
WorkflowHistoryEntry,
|
||||||
|
WorkflowRegistryEntry,
|
||||||
|
WorkflowRegistryFile,
|
||||||
|
} from "./types.js";
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
import type {
|
import type {
|
||||||
ExtractProviderConfig,
|
ExtractProviderConfig,
|
||||||
WorkflowConfig,
|
WorkflowConfig,
|
||||||
WorkflowHistoryEntry,
|
WorkflowHistoryEntry,
|
||||||
WorkflowRegistryEntry,
|
WorkflowRegistryEntry,
|
||||||
WorkflowRegistryFile,
|
WorkflowRegistryFile,
|
||||||
} from "./registry-types.js";
|
} from "./types.js";
|
||||||
|
|
||||||
function resolveRegistryApiKey(raw: string): Result<string, Error> {
|
function resolveRegistryApiKey(raw: string): Result<string, Error> {
|
||||||
if (raw.startsWith("env:")) {
|
if (raw.startsWith("env:")) {
|
||||||
|
|||||||
@@ -2,21 +2,9 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|||||||
import { dirname, join } from "node:path";
|
import { dirname, join } from "node:path";
|
||||||
|
|
||||||
import { parseDocument, stringify } from "yaml";
|
import { parseDocument, stringify } from "yaml";
|
||||||
import { err, ok, type Result } from "../util/result.js";
|
import { err, ok, type Result } from "../util/index.js";
|
||||||
import { normalizeWorkflowRegistryRoot } from "./registry-normalize.js";
|
import { normalizeWorkflowRegistryRoot } from "./registry-normalize.js";
|
||||||
import type {
|
import type { WorkflowHistoryEntry, WorkflowRegistryEntry, WorkflowRegistryFile } from "./types.js";
|
||||||
WorkflowHistoryEntry,
|
|
||||||
WorkflowRegistryEntry,
|
|
||||||
WorkflowRegistryFile,
|
|
||||||
} from "./registry-types.js";
|
|
||||||
|
|
||||||
export type {
|
|
||||||
ExtractProviderConfig,
|
|
||||||
WorkflowConfig,
|
|
||||||
WorkflowHistoryEntry,
|
|
||||||
WorkflowRegistryEntry,
|
|
||||||
WorkflowRegistryFile,
|
|
||||||
} from "./registry-types.js";
|
|
||||||
|
|
||||||
export function workflowRegistryPath(storageRoot: string): string {
|
export function workflowRegistryPath(storageRoot: string): string {
|
||||||
return join(storageRoot, "workflow.yaml");
|
return join(storageRoot, "workflow.yaml");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type * as z from "zod/v4";
|
import type * as z from "zod/v4";
|
||||||
|
|
||||||
import type { CasStore } from "./cas/cas.js";
|
import type { CasStore } from "./cas/index.js";
|
||||||
|
|
||||||
/** Sentinel values for automaton control flow. */
|
/** Sentinel values for automaton control flow. */
|
||||||
export const START = "__start__" as const;
|
export const START = "__start__" as const;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { err, ok, type Result } from "./result.js";
|
import { err, ok } from "./result.js";
|
||||||
|
import type { Result } from "./types.js";
|
||||||
|
|
||||||
/** Crockford Base32 alphabet (no I, L, O, U) — exactly 32 symbols. */
|
/** Crockford Base32 alphabet (no I, L, O, U) — exactly 32 symbols. */
|
||||||
export const CROCKFORD_BASE32_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
export const CROCKFORD_BASE32_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
export {
|
||||||
|
CROCKFORD_BASE32_ALPHABET,
|
||||||
|
decodeCrockfordBase32Bits,
|
||||||
|
decodeCrockfordToUint64,
|
||||||
|
encodeCrockfordBase32Bits,
|
||||||
|
encodeUint64AsCrockford,
|
||||||
|
} from "./base32.js";
|
||||||
|
export { createLogger } from "./logger.js";
|
||||||
|
export { mergeRefsWithContentHash, normalizeRefsField } from "./refs-field.js";
|
||||||
|
export { err, ok } from "./result.js";
|
||||||
|
export { getDefaultWorkflowStorageRoot, getGlobalCasDir } from "./storage-root.js";
|
||||||
|
export type { CreateLoggerOptions, LogFn, LoggerSink, Result } from "./types.js";
|
||||||
|
export { generateUlid } from "./ulid.js";
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { appendFileSync } from "node:fs";
|
import { appendFileSync } from "node:fs";
|
||||||
|
|
||||||
import { CROCKFORD_BASE32_ALPHABET } from "./base32.js";
|
import { CROCKFORD_BASE32_ALPHABET } from "./base32.js";
|
||||||
|
import type { CreateLoggerOptions, LogFn } from "./types.js";
|
||||||
|
|
||||||
const TAG_LENGTH = 8;
|
const TAG_LENGTH = 8;
|
||||||
|
|
||||||
@@ -22,14 +23,6 @@ function assertValidLogTag(tag: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LoggerSink = { kind: "stderr" } | { kind: "file"; path: string };
|
|
||||||
|
|
||||||
export type CreateLoggerOptions = {
|
|
||||||
sink: LoggerSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type LogFn = (tag: string, content: string) => void;
|
|
||||||
|
|
||||||
/** Append one JSONL log record: `{ tag, content, timestamp }` per RFC-001. */
|
/** Append one JSONL log record: `{ tag, content, timestamp }` per RFC-001. */
|
||||||
export function createLogger(options: CreateLoggerOptions): LogFn {
|
export function createLogger(options: CreateLoggerOptions): LogFn {
|
||||||
if (options.sink.kind === "stderr") {
|
if (options.sink.kind === "stderr") {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
|
import type { Result } from "./types.js";
|
||||||
|
|
||||||
export function ok<T>(value: T): Result<T, never> {
|
export function ok<T>(value: T): Result<T, never> {
|
||||||
return { ok: true, value };
|
return { ok: true, value };
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
|
||||||
|
|
||||||
|
export type LoggerSink = { kind: "stderr" } | { kind: "file"; path: string };
|
||||||
|
|
||||||
|
export type CreateLoggerOptions = {
|
||||||
|
sink: LoggerSink;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LogFn = (tag: string, content: string) => void;
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
|
||||||
import { extractBundleExports } from "./bundle/extract-bundle-exports.js";
|
import { extractBundleExports } from "./bundle/index.js";
|
||||||
import { createCasStore } from "./cas/cas.js";
|
import { createCasStore } from "./cas/index.js";
|
||||||
import { type ExecuteThreadIo, executeThread } from "./engine/engine.js";
|
import type { ExecuteThreadIo } from "./engine/index.js";
|
||||||
|
import { executeThread } from "./engine/index.js";
|
||||||
import { getWorkflowAsAgentMaxDepth } from "./extract-provider.js";
|
import { getWorkflowAsAgentMaxDepth } from "./extract-provider.js";
|
||||||
import { getRegisteredWorkflow, readWorkflowRegistry } from "./registry/registry.js";
|
import { getRegisteredWorkflow, readWorkflowRegistry } from "./registry/index.js";
|
||||||
import type { AgentContext, AgentFn, ThreadInput } from "./types.js";
|
import type { AgentContext, AgentFn, ThreadInput } from "./types.js";
|
||||||
import { createLogger } from "./util/logger.js";
|
import {
|
||||||
import { getDefaultWorkflowStorageRoot, getGlobalCasDir } from "./util/storage-root.js";
|
createLogger,
|
||||||
import { generateUlid } from "./util/ulid.js";
|
generateUlid,
|
||||||
|
getDefaultWorkflowStorageRoot,
|
||||||
|
getGlobalCasDir,
|
||||||
|
} from "./util/index.js";
|
||||||
|
|
||||||
export type WorkflowAsAgentOptions = {
|
export type WorkflowAsAgentOptions = {
|
||||||
/** When `null`, uses `getDefaultWorkflowStorageRoot()`. */
|
/** When `null`, uses `getDefaultWorkflowStorageRoot()`. */
|
||||||
|
|||||||
Reference in New Issue
Block a user