@hasna/workflows 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -98
- package/dist/agent-tools.js +130 -1035
- package/dist/cli/index.js +4108 -2473
- package/dist/handlers.js +3287 -55
- package/dist/index.js +1403 -337
- package/dist/mcp/index.js +1725 -1742
- package/dist/sdk.js +1620 -0
- package/dist/serve/admin.js +4248 -0
- package/dist/serve/index.js +3349 -1381
- package/dist/service.js +1168 -250
- package/hasna.contract.json +17 -17
- package/package.json +15 -12
- package/types/agent-tools.d.ts +3 -17
- package/types/client-error.d.ts +4 -0
- package/types/client-tools.d.ts +4 -0
- package/types/client.d.ts +60 -0
- package/types/daemon.d.ts +15 -9
- package/types/db/postgres-store.d.ts +54 -0
- package/types/handlers.d.ts +2 -1
- package/types/identity.d.ts +7 -0
- package/types/lanes/types.d.ts +12 -3
- package/types/openapi.d.ts +7 -0
- package/types/paths.d.ts +10 -1
- package/types/sdk/generated-api.d.ts +159 -0
- package/types/sdk.d.ts +6 -0
- package/types/serve/admin.d.ts +2 -0
- package/types/service.d.ts +75 -4
- package/types/session.d.ts +7 -8
- package/types/setup.d.ts +71 -0
- package/types/store.d.ts +30 -0
- package/types/tool-definitions.d.ts +18 -0
- package/types/types.d.ts +8 -0
- package/types/version.d.ts +1 -0
- package/types/wal.d.ts +9 -1
package/types/service.d.ts
CHANGED
|
@@ -1,16 +1,82 @@
|
|
|
1
|
+
import { type RunToCompletionOptions } from "./daemon.js";
|
|
2
|
+
import { openStore } from "./store.js";
|
|
1
3
|
import type { WorkflowGraph } from "./graph.js";
|
|
2
4
|
import type { HealthReport, ReadinessReport, WorkflowsConfig } from "./types.js";
|
|
3
|
-
export
|
|
5
|
+
export { packageVersion } from "./version.js";
|
|
4
6
|
/** Resolve the service configuration from env + explicit overrides. */
|
|
5
7
|
export declare function resolveWorkflowsConfig(overrides?: Partial<WorkflowsConfig>): WorkflowsConfig;
|
|
6
8
|
export declare class WorkflowsService {
|
|
9
|
+
private readonly execution;
|
|
7
10
|
readonly name = "workflows";
|
|
8
11
|
readonly version: string;
|
|
9
12
|
readonly config: WorkflowsConfig;
|
|
10
13
|
private readonly startedAt;
|
|
11
|
-
|
|
14
|
+
private readonly databaseEnv;
|
|
15
|
+
constructor(config?: Partial<WorkflowsConfig>, execution?: RunToCompletionOptions);
|
|
12
16
|
health(): HealthReport;
|
|
13
|
-
ready(): ReadinessReport
|
|
17
|
+
ready(): Promise<ReadinessReport>;
|
|
18
|
+
private openEngineStore;
|
|
19
|
+
private withStore;
|
|
20
|
+
/** Explicit operator bootstrap; ordinary reads and server startup never create tables. */
|
|
21
|
+
initializeStorage(): Promise<void>;
|
|
22
|
+
listRuns(options?: Parameters<ReturnType<typeof openStore>["listRuns"]>[0]): Promise<import("./store.js").RunRow[]>;
|
|
23
|
+
getRun(id: string): Promise<import("./store.js").RunRow | undefined>;
|
|
24
|
+
listNodes(id: string): Promise<import("./store.js").RunNodeRow[]>;
|
|
25
|
+
events(id: string): import("./wal.js").WalEntry[];
|
|
26
|
+
cancelRun(id: string): Promise<import("./store.js").RunRow | undefined>;
|
|
27
|
+
resumeRun(id: string): Promise<{
|
|
28
|
+
runId: string;
|
|
29
|
+
status: "cancelled" | "pending" | "running" | "completed" | "failed" | "interrupted";
|
|
30
|
+
error: string | null;
|
|
31
|
+
result: any;
|
|
32
|
+
reused: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
sessions(action: "list" | "pull"): {
|
|
35
|
+
seq: number;
|
|
36
|
+
at: string;
|
|
37
|
+
operation: "claim_acquired" | "claim_released" | "graph_registered" | "run_started" | "run_finished" | "node_started" | "node_finished" | "memo_set";
|
|
38
|
+
}[] | {
|
|
39
|
+
entries: number;
|
|
40
|
+
torn: boolean;
|
|
41
|
+
repaired: boolean;
|
|
42
|
+
liveClaims: {
|
|
43
|
+
runId: string;
|
|
44
|
+
worker: string;
|
|
45
|
+
fencing: number;
|
|
46
|
+
expiresAt: string;
|
|
47
|
+
}[];
|
|
48
|
+
};
|
|
49
|
+
machines(action: "list" | "status"): {
|
|
50
|
+
name: string;
|
|
51
|
+
role: string;
|
|
52
|
+
version: string;
|
|
53
|
+
}[] | {
|
|
54
|
+
health: HealthReport;
|
|
55
|
+
sessions: {
|
|
56
|
+
seq: number;
|
|
57
|
+
at: string;
|
|
58
|
+
operation: "claim_acquired" | "claim_released" | "graph_registered" | "run_started" | "run_finished" | "node_started" | "node_finished" | "memo_set";
|
|
59
|
+
}[] | {
|
|
60
|
+
entries: number;
|
|
61
|
+
torn: boolean;
|
|
62
|
+
repaired: boolean;
|
|
63
|
+
liveClaims: {
|
|
64
|
+
runId: string;
|
|
65
|
+
worker: string;
|
|
66
|
+
fencing: number;
|
|
67
|
+
expiresAt: string;
|
|
68
|
+
}[];
|
|
69
|
+
};
|
|
70
|
+
name: string;
|
|
71
|
+
role: string;
|
|
72
|
+
version: string;
|
|
73
|
+
};
|
|
74
|
+
daemonStatus(): {
|
|
75
|
+
activeClaims: number;
|
|
76
|
+
mode: string;
|
|
77
|
+
continuousDaemon: boolean;
|
|
78
|
+
};
|
|
79
|
+
listMemos(): Promise<import("./store.js").MemoRow[]>;
|
|
14
80
|
/**
|
|
15
81
|
* The authenticated trigger: run a graph to a terminal state (bounded
|
|
16
82
|
* cycles) and return its summary. The HTTP layer authenticates; this
|
|
@@ -29,4 +95,9 @@ export declare class WorkflowsService {
|
|
|
29
95
|
reused: boolean;
|
|
30
96
|
}>;
|
|
31
97
|
}
|
|
32
|
-
export declare function createWorkflowsService(config?: Partial<WorkflowsConfig
|
|
98
|
+
export declare function createWorkflowsService(config?: Partial<WorkflowsConfig>, execution?: RunToCompletionOptions): WorkflowsService;
|
|
99
|
+
export declare class WorkflowRequestError extends Error {
|
|
100
|
+
readonly code: string;
|
|
101
|
+
readonly status: number;
|
|
102
|
+
constructor(code: string, message: string, status?: number);
|
|
103
|
+
}
|
package/types/session.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SessionWAL } from "./wal.js";
|
|
2
|
-
import type { RunRow, WorkflowsStore } from "./store.js";
|
|
2
|
+
import type { RunRow, WorkflowsStore, EngineStore } from "./store.js";
|
|
3
3
|
import type { WorkflowGraph } from "./graph.js";
|
|
4
4
|
export interface RepairResult {
|
|
5
5
|
/** runs found running with no live claim */
|
|
@@ -10,18 +10,18 @@ export interface RepairResult {
|
|
|
10
10
|
failed: number;
|
|
11
11
|
}
|
|
12
12
|
export declare const DEFAULT_MAX_ATTEMPTS = 3;
|
|
13
|
-
export declare function repairTornRuns(store:
|
|
13
|
+
export declare function repairTornRuns<S extends EngineStore>(store: S, wal: SessionWAL, opts?: {
|
|
14
14
|
maxAttempts?: number;
|
|
15
15
|
now?: number;
|
|
16
|
-
}): RepairResult
|
|
16
|
+
}): S extends WorkflowsStore ? RepairResult : Promise<RepairResult>;
|
|
17
17
|
/** Stable hash of a JSON-serializable payload. */
|
|
18
18
|
export declare function inputHash(payload: unknown): string;
|
|
19
19
|
/** Memo key: graphName:nodeId:<inputHash>. */
|
|
20
20
|
export declare function memoKey(graphName: string, nodeId: string, input: unknown): string;
|
|
21
21
|
/** Look up a memo by input; a hit increments hitCount and returns the row. */
|
|
22
|
-
export declare function tryMemoHit(store:
|
|
22
|
+
export declare function tryMemoHit<S extends EngineStore>(store: S, graphName: string, nodeId: string, input: unknown): ReturnType<S["memoGet"]>;
|
|
23
23
|
/** Persist a node output for future runs with the same input. */
|
|
24
|
-
export declare function recordMemo(store:
|
|
24
|
+
export declare function recordMemo<S extends EngineStore>(store: S, graphName: string, nodeId: string, input: unknown, output: unknown): ReturnType<S["memoPut"]>;
|
|
25
25
|
/** One watched file's fingerprint entry (mtime + sha256). */
|
|
26
26
|
export interface MemoWatchEntry {
|
|
27
27
|
/** The pattern as declared on the graph. */
|
|
@@ -69,7 +69,6 @@ export declare function restoreInterruptedRun(store: WorkflowsStore, runId: stri
|
|
|
69
69
|
/**
|
|
70
70
|
* Idempotent run lookup: the run whose context carries the given idempotency
|
|
71
71
|
* key, if any. The three-table law forbids an extra column, so the key lives
|
|
72
|
-
* in the reserved __wf namespace of context_json;
|
|
73
|
-
* store's own listRuns cap (1000 rows).
|
|
72
|
+
* in the reserved __wf namespace of context_json; a database lookup covers the entire run history.
|
|
74
73
|
*/
|
|
75
|
-
export declare function findRunByIdempotencyKey(store:
|
|
74
|
+
export declare function findRunByIdempotencyKey<S extends EngineStore>(store: S, key: string): ReturnType<S["getRunByIdempotencyKey"]>;
|
package/types/setup.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type IdentityEnvironment } from "./identity.js";
|
|
2
|
+
type SetupOptions = {
|
|
3
|
+
apiUrl?: string;
|
|
4
|
+
replace?: boolean;
|
|
5
|
+
agent?: string;
|
|
6
|
+
env?: IdentityEnvironment;
|
|
7
|
+
fetchImpl?: typeof fetch;
|
|
8
|
+
};
|
|
9
|
+
export declare function setupWorkflows(options?: SetupOptions): Promise<{
|
|
10
|
+
app: string;
|
|
11
|
+
action: string;
|
|
12
|
+
credentials_path: string;
|
|
13
|
+
mode: string;
|
|
14
|
+
authority: string;
|
|
15
|
+
verified_before_write: boolean;
|
|
16
|
+
verified_after_write: boolean;
|
|
17
|
+
effective_tier: "disk";
|
|
18
|
+
effective_source: string;
|
|
19
|
+
preservation: string | undefined;
|
|
20
|
+
warning: null;
|
|
21
|
+
}>;
|
|
22
|
+
export declare function loginWorkflows(options?: SetupOptions, suppliedKey?: string): Promise<{
|
|
23
|
+
app: string;
|
|
24
|
+
action: string;
|
|
25
|
+
credentials_path: string;
|
|
26
|
+
mode: string;
|
|
27
|
+
authority: string;
|
|
28
|
+
verified_before_write: boolean;
|
|
29
|
+
verified_after_write: boolean;
|
|
30
|
+
effective_tier: "disk";
|
|
31
|
+
effective_source: string;
|
|
32
|
+
preservation: string | undefined;
|
|
33
|
+
warning: null;
|
|
34
|
+
}>;
|
|
35
|
+
/** Sign out only a key written by login; environment and setup credentials stay owned by their source. */
|
|
36
|
+
export declare function logoutWorkflows(options?: {
|
|
37
|
+
revoke?: boolean;
|
|
38
|
+
env?: IdentityEnvironment;
|
|
39
|
+
}): {
|
|
40
|
+
app: string;
|
|
41
|
+
action: string;
|
|
42
|
+
exit_code: number;
|
|
43
|
+
message: string;
|
|
44
|
+
} | {
|
|
45
|
+
app: string;
|
|
46
|
+
action: string;
|
|
47
|
+
credentials_path: string;
|
|
48
|
+
preservation: string;
|
|
49
|
+
exit_code: number;
|
|
50
|
+
message: string;
|
|
51
|
+
};
|
|
52
|
+
export declare function workflowsWhoami(options?: {
|
|
53
|
+
apiUrl?: string;
|
|
54
|
+
agent?: string;
|
|
55
|
+
env?: IdentityEnvironment;
|
|
56
|
+
}): {
|
|
57
|
+
app: string;
|
|
58
|
+
agent: string;
|
|
59
|
+
agent_source: string;
|
|
60
|
+
authority: string;
|
|
61
|
+
credential_tier: import("@hasna/contracts").CredentialTier;
|
|
62
|
+
credential_source: string | null;
|
|
63
|
+
} | {
|
|
64
|
+
app: string;
|
|
65
|
+
agent: string;
|
|
66
|
+
agent_source: string;
|
|
67
|
+
authority: string;
|
|
68
|
+
credential_tier: string;
|
|
69
|
+
credential_source: null;
|
|
70
|
+
};
|
|
71
|
+
export {};
|
package/types/store.d.ts
CHANGED
|
@@ -48,6 +48,27 @@ export interface CreateRunNodeInput {
|
|
|
48
48
|
nodeId: string;
|
|
49
49
|
lane?: string;
|
|
50
50
|
}
|
|
51
|
+
export interface StepCommit {
|
|
52
|
+
runId: string;
|
|
53
|
+
nodeRowId: string;
|
|
54
|
+
status: NodeStatus;
|
|
55
|
+
patch?: Parameters<WorkflowsStore["setRunNodeStatus"]>[2];
|
|
56
|
+
incrementAttempts?: boolean;
|
|
57
|
+
context?: unknown;
|
|
58
|
+
memo?: {
|
|
59
|
+
key: string;
|
|
60
|
+
graphName: string;
|
|
61
|
+
nodeId: string;
|
|
62
|
+
inputHash: string;
|
|
63
|
+
outputJson: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export type DispatchResult<T> = {
|
|
67
|
+
started: false;
|
|
68
|
+
} | {
|
|
69
|
+
started: true;
|
|
70
|
+
result: T;
|
|
71
|
+
};
|
|
51
72
|
export interface WorkflowsStore {
|
|
52
73
|
/** The data dir this store was opened on (resolves relative memoWatch paths). */
|
|
53
74
|
readonly dataDir: string;
|
|
@@ -55,6 +76,7 @@ export interface WorkflowsStore {
|
|
|
55
76
|
listTables(): string[];
|
|
56
77
|
createRun(input: CreateRunInput): RunRow;
|
|
57
78
|
getRun(id: string): RunRow | undefined;
|
|
79
|
+
getRunByIdempotencyKey(key: string): RunRow | undefined;
|
|
58
80
|
listRuns(opts?: {
|
|
59
81
|
status?: RunStatus;
|
|
60
82
|
limit?: number;
|
|
@@ -65,8 +87,14 @@ export interface WorkflowsStore {
|
|
|
65
87
|
startedAt?: string;
|
|
66
88
|
finishedAt?: string;
|
|
67
89
|
}): void;
|
|
90
|
+
compareRunStatus(id: string, expected: RunStatus[], status: RunStatus, patch?: Parameters<WorkflowsStore["setRunStatus"]>[2]): boolean;
|
|
68
91
|
/** Persist the run's durable execution state (the engine's cursor + steps). */
|
|
69
92
|
setRunContext(id: string, context: unknown): void;
|
|
93
|
+
setRunningContext(id: string, context: unknown): boolean;
|
|
94
|
+
blockRunResume(id: string): void;
|
|
95
|
+
finishDispatch(id: string, unconfirmed: boolean): void;
|
|
96
|
+
dispatchIfRunning<T>(id: string, action: () => T): DispatchResult<T>;
|
|
97
|
+
commitStep(input: StepCommit): boolean;
|
|
70
98
|
bumpAttempts(id: string): void;
|
|
71
99
|
createRunNode(input: CreateRunNodeInput): RunNodeRow;
|
|
72
100
|
getRunNode(id: string): RunNodeRow | undefined;
|
|
@@ -89,3 +117,5 @@ export interface WorkflowsStore {
|
|
|
89
117
|
memoClear(): void;
|
|
90
118
|
}
|
|
91
119
|
export declare function openStore(dataDir: string): WorkflowsStore;
|
|
120
|
+
/** One execution engine accepts the synchronous embedded and asynchronous hosted stores. */
|
|
121
|
+
export type EngineStore = WorkflowsStore | import("./db/postgres-store.js").AsyncWorkflowsStore;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface McpTool {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object";
|
|
6
|
+
properties: Record<string, unknown>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface ToolCallResult {
|
|
11
|
+
content: {
|
|
12
|
+
type: "text";
|
|
13
|
+
text: string;
|
|
14
|
+
}[];
|
|
15
|
+
isError: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function textResult(payload: unknown): ToolCallResult;
|
|
18
|
+
export declare function workflowsTools(_service?: unknown): McpTool[];
|
package/types/types.d.ts
CHANGED
|
@@ -20,9 +20,17 @@ export interface WorkflowsConfig {
|
|
|
20
20
|
apiUrl?: string;
|
|
21
21
|
/** Optional client API key (WORKFLOWS_API_KEY) — resolved, never printed. */
|
|
22
22
|
apiKey?: string;
|
|
23
|
+
/** Gateway origin identity. When configured, every /v1 route requires it. */
|
|
24
|
+
originAuth?: string;
|
|
25
|
+
/** Hosted server authority. SQLite requires an explicit embedded selection. */
|
|
26
|
+
storageBackend: "postgresql" | "sqlite";
|
|
27
|
+
databaseUrl?: string;
|
|
28
|
+
databaseSchema?: string;
|
|
23
29
|
}
|
|
24
30
|
export interface HealthReport {
|
|
25
31
|
ok: boolean;
|
|
32
|
+
status: "ok";
|
|
33
|
+
backend: "postgresql" | "sqlite";
|
|
26
34
|
service: string;
|
|
27
35
|
version: string;
|
|
28
36
|
pid: number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function packageVersion(): string;
|
package/types/wal.d.ts
CHANGED
|
@@ -71,14 +71,22 @@ export declare const WAL_FILE_NAME = "session.wal";
|
|
|
71
71
|
export declare const SESSIONS_DIR_NAME = "sessions";
|
|
72
72
|
export declare class SessionWAL {
|
|
73
73
|
readonly filePath: string;
|
|
74
|
+
private journalLocked;
|
|
74
75
|
private constructor();
|
|
75
76
|
static open(dataDir: string): SessionWAL;
|
|
76
77
|
static openAt(filePath: string): SessionWAL;
|
|
77
78
|
/** Append one op and return the persisted entry (seq is 1-based). */
|
|
78
79
|
append(op: WalOp): WalEntry;
|
|
80
|
+
private withJournalLock;
|
|
81
|
+
/** Atomic journal claim/release decisions use the same cross-process mutex. */
|
|
82
|
+
exclusive<T>(operation: () => T): T;
|
|
83
|
+
private appendLocked;
|
|
79
84
|
private nextSeq;
|
|
80
85
|
/** Read and verify the whole WAL; truncate the first torn tail. */
|
|
81
|
-
replay(
|
|
86
|
+
replay(options?: {
|
|
87
|
+
repair?: boolean;
|
|
88
|
+
}): WalReplay;
|
|
89
|
+
private replayLocked;
|
|
82
90
|
close(): void;
|
|
83
91
|
}
|
|
84
92
|
/** Write a fresh (empty) WAL — used by tests and by init. */
|