@hasna/loops 0.4.13 → 0.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +99 -3
- package/README.md +171 -39
- package/dist/api/index.d.ts +36 -0
- package/dist/api/index.js +1518 -15
- package/dist/cli/index.js +7280 -3213
- package/dist/cli/ui.d.ts +44 -0
- package/dist/daemon/index.js +1433 -303
- package/dist/generated/storage-kit/health.d.ts +19 -0
- package/dist/generated/storage-kit/index.d.ts +7 -0
- package/dist/generated/storage-kit/migrations.d.ts +47 -0
- package/dist/generated/storage-kit/mode.d.ts +47 -0
- package/dist/generated/storage-kit/pool.d.ts +33 -0
- package/dist/generated/storage-kit/query.d.ts +35 -0
- package/dist/generated/storage-kit/tls.d.ts +25 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8689 -4837
- package/dist/lib/cloud/mode.d.ts +17 -0
- package/dist/lib/cloud/resolve.d.ts +16 -0
- package/dist/lib/cloud/storage.d.ts +82 -0
- package/dist/lib/cloud/transport.d.ts +148 -0
- package/dist/lib/format.d.ts +2 -1
- package/dist/lib/health.d.ts +83 -3
- package/dist/lib/migration.d.ts +40 -0
- package/dist/lib/mode.js +15 -3
- package/dist/lib/route/index.d.ts +2 -0
- package/dist/lib/route/policies.d.ts +51 -0
- package/dist/lib/route/provider-admission.d.ts +37 -0
- package/dist/lib/route/throttle.d.ts +4 -0
- package/dist/lib/route/types.d.ts +8 -0
- package/dist/lib/run-receipts.d.ts +14 -0
- package/dist/lib/scheduler.d.ts +5 -2
- package/dist/lib/storage/contract.d.ts +7 -1
- package/dist/lib/storage/index.d.ts +1 -0
- package/dist/lib/storage/index.js +2028 -231
- package/dist/lib/storage/pg-executor.d.ts +27 -0
- package/dist/lib/storage/pg-runner-claim.d.ts +40 -0
- package/dist/lib/storage/postgres-loop-storage.d.ts +120 -0
- package/dist/lib/storage/postgres-schema.js +29 -0
- package/dist/lib/storage/postgres.js +29 -0
- package/dist/lib/storage/sqlite.d.ts +6 -0
- package/dist/lib/storage/sqlite.js +748 -26
- package/dist/lib/store/index.d.ts +268 -0
- package/dist/lib/store.d.ts +282 -1
- package/dist/lib/store.js +746 -26
- package/dist/lib/template-kit.d.ts +25 -0
- package/dist/lib/templates.d.ts +16 -1
- package/dist/mcp/http.d.ts +16 -0
- package/dist/mcp/index.js +2885 -634
- package/dist/runner/index.js +198 -32
- package/dist/sdk/http.d.ts +182 -0
- package/dist/sdk/http.js +166 -0
- package/dist/sdk/index.d.ts +55 -18
- package/dist/sdk/index.js +2734 -617
- package/dist/serve/index.d.ts +4 -0
- package/dist/serve/index.js +9095 -0
- package/dist/types.d.ts +52 -0
- package/docs/AUTOMATION_RUNTIME_DESIGN.md +442 -1
- package/docs/CUTOVER-RUNBOOK.md +78 -0
- package/docs/DEPLOYMENT_MODES.md +35 -18
- package/docs/RUNTIME_BOUNDARY.md +203 -0
- package/docs/USAGE.md +195 -38
- package/package.json +15 -3
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import type { CreateLoopInput, CreateWorkflowInput, Loop, LoopRun, LoopStatus, RunReceipt, RunStatus, WorkflowEvent, WorkflowInvocation, WorkflowRun, WorkflowSpec, WorkflowStepRun, WorkflowWorkItem, WorkflowWorkItemStatus, WriteRunReceiptInput } from "../../types.js";
|
|
2
|
+
import type { Goal, GoalPlanNode, GoalRun, GoalStatus } from "../goal/types.js";
|
|
3
|
+
import type { HasnaStorageClient } from "../cloud/storage.js";
|
|
4
|
+
import type { Env } from "../cloud/mode.js";
|
|
5
|
+
import { Store } from "../store.js";
|
|
6
|
+
import type { PruneHistoryOptions, PruneHistorySummary } from "../store.js";
|
|
7
|
+
/** Which transport backs a resolved store (for banners/diagnostics only). */
|
|
8
|
+
export type StoreTransport = "local" | "cloud-http";
|
|
9
|
+
/**
|
|
10
|
+
* Thrown when a command routed through the cloud ApiStore hits an operation that
|
|
11
|
+
* the hosted `/v1` API does not yet expose. Failing loudly here is deliberate:
|
|
12
|
+
* the alternative (silently reading/writing the on-box sqlite island while the
|
|
13
|
+
* machine is flipped to cloud) is exactly the split-brain bug we are removing.
|
|
14
|
+
*/
|
|
15
|
+
export declare class CloudUnsupportedError extends Error {
|
|
16
|
+
constructor(operation: string);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The single data interface for the OpenLoops client. Both {@link LocalStore}
|
|
20
|
+
* and {@link ApiStore} implement it; callers hold a `LoopStore` and never know
|
|
21
|
+
* (or branch on) which one. Every method is async so the two transports share
|
|
22
|
+
* one surface.
|
|
23
|
+
*/
|
|
24
|
+
export interface LoopStore {
|
|
25
|
+
readonly transport: StoreTransport;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
createLoop(input: CreateLoopInput, from?: Date): Promise<Loop>;
|
|
28
|
+
getLoop(id: string): Promise<Loop | undefined>;
|
|
29
|
+
findLoopByName(name: string): Promise<Loop | undefined>;
|
|
30
|
+
requireLoop(idOrName: string): Promise<Loop>;
|
|
31
|
+
requireUniqueLoop(idOrName: string): Promise<Loop>;
|
|
32
|
+
listLoops(opts?: {
|
|
33
|
+
status?: LoopStatus;
|
|
34
|
+
limit?: number;
|
|
35
|
+
offset?: number;
|
|
36
|
+
archived?: boolean;
|
|
37
|
+
includeArchived?: boolean;
|
|
38
|
+
name?: string;
|
|
39
|
+
}): Promise<Loop[]>;
|
|
40
|
+
countLoops(status?: LoopStatus, opts?: {
|
|
41
|
+
archived?: boolean;
|
|
42
|
+
includeArchived?: boolean;
|
|
43
|
+
}): Promise<number>;
|
|
44
|
+
updateLoop(id: string, patch: Partial<Pick<Loop, "status" | "nextRunAt" | "retryScheduledFor" | "expiresAt">>): Promise<Loop>;
|
|
45
|
+
renameLoop(id: string, name: string): Promise<Loop>;
|
|
46
|
+
archiveLoop(idOrName: string): Promise<Loop>;
|
|
47
|
+
unarchiveLoop(idOrName: string): Promise<Loop>;
|
|
48
|
+
deleteLoop(idOrName: string): Promise<boolean>;
|
|
49
|
+
createWorkflow(input: CreateWorkflowInput): Promise<WorkflowSpec>;
|
|
50
|
+
getWorkflow(id: string): Promise<WorkflowSpec | undefined>;
|
|
51
|
+
findWorkflowByName(name: string): Promise<WorkflowSpec | undefined>;
|
|
52
|
+
requireWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
53
|
+
listWorkflows(opts?: {
|
|
54
|
+
status?: WorkflowSpec["status"];
|
|
55
|
+
limit?: number;
|
|
56
|
+
offset?: number;
|
|
57
|
+
}): Promise<WorkflowSpec[]>;
|
|
58
|
+
countWorkflows(opts?: {
|
|
59
|
+
status?: WorkflowSpec["status"];
|
|
60
|
+
}): Promise<number>;
|
|
61
|
+
archiveWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
62
|
+
getWorkflowRun(id: string): Promise<WorkflowRun | undefined>;
|
|
63
|
+
requireWorkflowRun(id: string): Promise<WorkflowRun>;
|
|
64
|
+
listWorkflowRuns(opts?: {
|
|
65
|
+
workflowId?: string;
|
|
66
|
+
loopRunId?: string;
|
|
67
|
+
limit?: number;
|
|
68
|
+
}): Promise<WorkflowRun[]>;
|
|
69
|
+
listWorkflowStepRuns(workflowRunId: string): Promise<WorkflowStepRun[]>;
|
|
70
|
+
listWorkflowEvents(workflowRunId: string, limit?: number): Promise<WorkflowEvent[]>;
|
|
71
|
+
recoverWorkflowRun(workflowRunId: string, reason?: string): Promise<{
|
|
72
|
+
run: WorkflowRun;
|
|
73
|
+
recoveredSteps: WorkflowStepRun[];
|
|
74
|
+
}>;
|
|
75
|
+
cancelWorkflowRun(workflowRunId: string, reason?: string): Promise<WorkflowRun>;
|
|
76
|
+
listWorkflowWorkItems(opts?: {
|
|
77
|
+
status?: WorkflowWorkItemStatus;
|
|
78
|
+
routeKey?: string;
|
|
79
|
+
limit?: number;
|
|
80
|
+
}): Promise<WorkflowWorkItem[]>;
|
|
81
|
+
getWorkflowWorkItem(id: string): Promise<WorkflowWorkItem | undefined>;
|
|
82
|
+
requeueWorkflowWorkItem(id: string, patch?: {
|
|
83
|
+
reason?: string;
|
|
84
|
+
}): Promise<WorkflowWorkItem>;
|
|
85
|
+
listWorkflowInvocations(opts?: {
|
|
86
|
+
limit?: number;
|
|
87
|
+
}): Promise<WorkflowInvocation[]>;
|
|
88
|
+
getWorkflowInvocation(id: string): Promise<WorkflowInvocation | undefined>;
|
|
89
|
+
getGoal(id: string): Promise<Goal | undefined>;
|
|
90
|
+
findGoalByLoop(idOrName: string): Promise<Goal | undefined>;
|
|
91
|
+
findGoalByRunId(id: string): Promise<Goal | undefined>;
|
|
92
|
+
listGoals(opts?: {
|
|
93
|
+
status?: GoalStatus;
|
|
94
|
+
limit?: number;
|
|
95
|
+
}): Promise<Goal[]>;
|
|
96
|
+
listGoalPlanNodes(goalIdOrPlanId: string): Promise<GoalPlanNode[]>;
|
|
97
|
+
listGoalRuns(opts?: {
|
|
98
|
+
goalId?: string;
|
|
99
|
+
runId?: string;
|
|
100
|
+
limit?: number;
|
|
101
|
+
}): Promise<GoalRun[]>;
|
|
102
|
+
listRuns(opts?: {
|
|
103
|
+
loopId?: string;
|
|
104
|
+
status?: RunStatus;
|
|
105
|
+
limit?: number;
|
|
106
|
+
offset?: number;
|
|
107
|
+
}): Promise<LoopRun[]>;
|
|
108
|
+
getRun(id: string): Promise<LoopRun | undefined>;
|
|
109
|
+
writeRunReceipt(input: WriteRunReceiptInput): Promise<RunReceipt>;
|
|
110
|
+
getRunReceipt(runId: string): Promise<RunReceipt | undefined>;
|
|
111
|
+
listRunReceipts(opts?: {
|
|
112
|
+
loopId?: string;
|
|
113
|
+
repo?: string;
|
|
114
|
+
taskId?: string;
|
|
115
|
+
knowledgeId?: string;
|
|
116
|
+
status?: string;
|
|
117
|
+
limit?: number;
|
|
118
|
+
}): Promise<RunReceipt[]>;
|
|
119
|
+
pruneHistory(opts: PruneHistoryOptions): Promise<PruneHistorySummary>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* On-box SQLite transport. Wraps a single {@link Store} and awaits its
|
|
123
|
+
* synchronous methods so callers see the async {@link LoopStore} surface.
|
|
124
|
+
*/
|
|
125
|
+
export declare class LocalStore implements LoopStore {
|
|
126
|
+
readonly transport: "local";
|
|
127
|
+
private readonly store;
|
|
128
|
+
constructor(store?: Store);
|
|
129
|
+
/**
|
|
130
|
+
* The underlying on-box sqlite {@link Store}. Exposed ONLY for genuinely
|
|
131
|
+
* local-runtime operations that cannot route over HTTP — the scheduler
|
|
132
|
+
* (tick/run-now inline execution), migration import/export, and local
|
|
133
|
+
* diagnostics (doctor/health/daemon status). Callers must gate on
|
|
134
|
+
* `transport === "local"` first; the hosted ApiStore has no `raw` store, so
|
|
135
|
+
* these operations fail loudly in cloud mode instead of touching an island.
|
|
136
|
+
*/
|
|
137
|
+
get raw(): Store;
|
|
138
|
+
close(): Promise<void>;
|
|
139
|
+
createLoop(input: CreateLoopInput, from?: Date): Promise<Loop>;
|
|
140
|
+
getLoop(id: string): Promise<Loop | undefined>;
|
|
141
|
+
findLoopByName(name: string): Promise<Loop | undefined>;
|
|
142
|
+
requireLoop(idOrName: string): Promise<Loop>;
|
|
143
|
+
requireUniqueLoop(idOrName: string): Promise<Loop>;
|
|
144
|
+
listLoops(opts?: Parameters<Store["listLoops"]>[0]): Promise<Loop[]>;
|
|
145
|
+
countLoops(status?: LoopStatus, opts?: {
|
|
146
|
+
archived?: boolean;
|
|
147
|
+
includeArchived?: boolean;
|
|
148
|
+
}): Promise<number>;
|
|
149
|
+
updateLoop(id: string, patch: Partial<Pick<Loop, "status" | "nextRunAt" | "retryScheduledFor" | "expiresAt">>): Promise<Loop>;
|
|
150
|
+
renameLoop(id: string, name: string): Promise<Loop>;
|
|
151
|
+
archiveLoop(idOrName: string): Promise<Loop>;
|
|
152
|
+
unarchiveLoop(idOrName: string): Promise<Loop>;
|
|
153
|
+
deleteLoop(idOrName: string): Promise<boolean>;
|
|
154
|
+
createWorkflow(input: CreateWorkflowInput): Promise<WorkflowSpec>;
|
|
155
|
+
getWorkflow(id: string): Promise<WorkflowSpec | undefined>;
|
|
156
|
+
findWorkflowByName(name: string): Promise<WorkflowSpec | undefined>;
|
|
157
|
+
requireWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
158
|
+
listWorkflows(opts?: Parameters<Store["listWorkflows"]>[0]): Promise<WorkflowSpec[]>;
|
|
159
|
+
countWorkflows(opts?: {
|
|
160
|
+
status?: WorkflowSpec["status"];
|
|
161
|
+
}): Promise<number>;
|
|
162
|
+
archiveWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
163
|
+
getWorkflowRun(id: string): Promise<WorkflowRun | undefined>;
|
|
164
|
+
requireWorkflowRun(id: string): Promise<WorkflowRun>;
|
|
165
|
+
listWorkflowRuns(opts?: Parameters<Store["listWorkflowRuns"]>[0]): Promise<WorkflowRun[]>;
|
|
166
|
+
listWorkflowStepRuns(workflowRunId: string): Promise<WorkflowStepRun[]>;
|
|
167
|
+
listWorkflowEvents(workflowRunId: string, limit?: number): Promise<WorkflowEvent[]>;
|
|
168
|
+
recoverWorkflowRun(workflowRunId: string, reason?: string): Promise<{
|
|
169
|
+
run: WorkflowRun;
|
|
170
|
+
recoveredSteps: WorkflowStepRun[];
|
|
171
|
+
}>;
|
|
172
|
+
cancelWorkflowRun(workflowRunId: string, reason?: string): Promise<WorkflowRun>;
|
|
173
|
+
listWorkflowWorkItems(opts?: Parameters<Store["listWorkflowWorkItems"]>[0]): Promise<WorkflowWorkItem[]>;
|
|
174
|
+
getWorkflowWorkItem(id: string): Promise<WorkflowWorkItem | undefined>;
|
|
175
|
+
requeueWorkflowWorkItem(id: string, patch?: {
|
|
176
|
+
reason?: string;
|
|
177
|
+
}): Promise<WorkflowWorkItem>;
|
|
178
|
+
listWorkflowInvocations(opts?: Parameters<Store["listWorkflowInvocations"]>[0]): Promise<WorkflowInvocation[]>;
|
|
179
|
+
getWorkflowInvocation(id: string): Promise<WorkflowInvocation | undefined>;
|
|
180
|
+
getGoal(id: string): Promise<Goal | undefined>;
|
|
181
|
+
findGoalByLoop(idOrName: string): Promise<Goal | undefined>;
|
|
182
|
+
findGoalByRunId(id: string): Promise<Goal | undefined>;
|
|
183
|
+
listGoals(opts?: Parameters<Store["listGoals"]>[0]): Promise<Goal[]>;
|
|
184
|
+
listGoalPlanNodes(goalIdOrPlanId: string): Promise<GoalPlanNode[]>;
|
|
185
|
+
listGoalRuns(opts?: Parameters<Store["listGoalRuns"]>[0]): Promise<GoalRun[]>;
|
|
186
|
+
listRuns(opts?: Parameters<Store["listRuns"]>[0]): Promise<LoopRun[]>;
|
|
187
|
+
getRun(id: string): Promise<LoopRun | undefined>;
|
|
188
|
+
writeRunReceipt(input: WriteRunReceiptInput): Promise<RunReceipt>;
|
|
189
|
+
getRunReceipt(runId: string): Promise<RunReceipt | undefined>;
|
|
190
|
+
listRunReceipts(opts?: Parameters<Store["listRunReceipts"]>[0]): Promise<RunReceipt[]>;
|
|
191
|
+
pruneHistory(opts: PruneHistoryOptions): Promise<PruneHistorySummary>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Self_hosted / cloud transport: routes every read+write through the hosted
|
|
195
|
+
* `/v1` API. Loop/name resolution (requireLoop/requireUniqueLoop/find*) is done
|
|
196
|
+
* client-side by listing and matching, mirroring the local Store behaviour, so a
|
|
197
|
+
* server that ignores a name filter can never return the wrong row.
|
|
198
|
+
*/
|
|
199
|
+
export declare class ApiStore implements LoopStore {
|
|
200
|
+
private readonly client;
|
|
201
|
+
readonly baseUrl: string;
|
|
202
|
+
readonly transport: "cloud-http";
|
|
203
|
+
constructor(client: HasnaStorageClient, baseUrl: string);
|
|
204
|
+
private get t();
|
|
205
|
+
close(): Promise<void>;
|
|
206
|
+
createLoop(input: CreateLoopInput): Promise<Loop>;
|
|
207
|
+
getLoop(id: string): Promise<Loop | undefined>;
|
|
208
|
+
findLoopByName(name: string): Promise<Loop | undefined>;
|
|
209
|
+
requireLoop(idOrName: string): Promise<Loop>;
|
|
210
|
+
requireUniqueLoop(idOrName: string): Promise<Loop>;
|
|
211
|
+
private resolveLoop;
|
|
212
|
+
listLoops(opts?: Parameters<LoopStore["listLoops"]>[0]): Promise<Loop[]>;
|
|
213
|
+
countLoops(status?: LoopStatus, opts?: {
|
|
214
|
+
archived?: boolean;
|
|
215
|
+
includeArchived?: boolean;
|
|
216
|
+
}): Promise<number>;
|
|
217
|
+
updateLoop(id: string, patch: Partial<Pick<Loop, "status" | "nextRunAt" | "retryScheduledFor" | "expiresAt">>): Promise<Loop>;
|
|
218
|
+
renameLoop(id: string, name: string): Promise<Loop>;
|
|
219
|
+
archiveLoop(idOrName: string): Promise<Loop>;
|
|
220
|
+
unarchiveLoop(idOrName: string): Promise<Loop>;
|
|
221
|
+
deleteLoop(idOrName: string): Promise<boolean>;
|
|
222
|
+
createWorkflow(input: CreateWorkflowInput): Promise<WorkflowSpec>;
|
|
223
|
+
getWorkflow(id: string): Promise<WorkflowSpec | undefined>;
|
|
224
|
+
findWorkflowByName(name: string): Promise<WorkflowSpec | undefined>;
|
|
225
|
+
requireWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
226
|
+
listWorkflows(opts?: Parameters<LoopStore["listWorkflows"]>[0]): Promise<WorkflowSpec[]>;
|
|
227
|
+
countWorkflows(opts?: {
|
|
228
|
+
status?: WorkflowSpec["status"];
|
|
229
|
+
}): Promise<number>;
|
|
230
|
+
archiveWorkflow(idOrName: string): Promise<WorkflowSpec>;
|
|
231
|
+
getWorkflowRun(id: string): Promise<WorkflowRun | undefined>;
|
|
232
|
+
requireWorkflowRun(id: string): Promise<WorkflowRun>;
|
|
233
|
+
listWorkflowRuns(opts?: Parameters<LoopStore["listWorkflowRuns"]>[0]): Promise<WorkflowRun[]>;
|
|
234
|
+
listWorkflowStepRuns(workflowRunId: string): Promise<WorkflowStepRun[]>;
|
|
235
|
+
listWorkflowEvents(workflowRunId: string, limit?: number): Promise<WorkflowEvent[]>;
|
|
236
|
+
recoverWorkflowRun(workflowRunId: string, reason?: string): Promise<{
|
|
237
|
+
run: WorkflowRun;
|
|
238
|
+
recoveredSteps: WorkflowStepRun[];
|
|
239
|
+
}>;
|
|
240
|
+
cancelWorkflowRun(_workflowRunId: string, _reason?: string): Promise<WorkflowRun>;
|
|
241
|
+
listWorkflowWorkItems(opts?: Parameters<LoopStore["listWorkflowWorkItems"]>[0]): Promise<WorkflowWorkItem[]>;
|
|
242
|
+
getWorkflowWorkItem(id: string): Promise<WorkflowWorkItem | undefined>;
|
|
243
|
+
requeueWorkflowWorkItem(_id: string, _patch?: {
|
|
244
|
+
reason?: string;
|
|
245
|
+
}): Promise<WorkflowWorkItem>;
|
|
246
|
+
listWorkflowInvocations(opts?: Parameters<LoopStore["listWorkflowInvocations"]>[0]): Promise<WorkflowInvocation[]>;
|
|
247
|
+
getWorkflowInvocation(id: string): Promise<WorkflowInvocation | undefined>;
|
|
248
|
+
getGoal(id: string): Promise<Goal | undefined>;
|
|
249
|
+
findGoalByLoop(idOrName: string): Promise<Goal | undefined>;
|
|
250
|
+
findGoalByRunId(id: string): Promise<Goal | undefined>;
|
|
251
|
+
listGoals(opts?: Parameters<LoopStore["listGoals"]>[0]): Promise<Goal[]>;
|
|
252
|
+
listGoalPlanNodes(goalIdOrPlanId: string): Promise<GoalPlanNode[]>;
|
|
253
|
+
listGoalRuns(opts?: Parameters<LoopStore["listGoalRuns"]>[0]): Promise<GoalRun[]>;
|
|
254
|
+
listRuns(opts?: Parameters<LoopStore["listRuns"]>[0]): Promise<LoopRun[]>;
|
|
255
|
+
getRun(id: string): Promise<LoopRun | undefined>;
|
|
256
|
+
writeRunReceipt(input: WriteRunReceiptInput): Promise<RunReceipt>;
|
|
257
|
+
getRunReceipt(runId: string): Promise<RunReceipt | undefined>;
|
|
258
|
+
listRunReceipts(opts?: Parameters<LoopStore["listRunReceipts"]>[0]): Promise<RunReceipt[]>;
|
|
259
|
+
pruneHistory(opts: PruneHistoryOptions): Promise<PruneHistorySummary>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Resolve the client store for the current environment: an {@link ApiStore} when
|
|
263
|
+
* the client-flip contract resolves to cloud-http (self_hosted/cloud), else a
|
|
264
|
+
* {@link LocalStore}. Callers hold a {@link LoopStore} and never branch on mode.
|
|
265
|
+
*/
|
|
266
|
+
export declare function getStore(env?: Env): LoopStore;
|
|
267
|
+
/** True when the resolved store is the hosted HTTP transport (cloud/self_hosted). */
|
|
268
|
+
export declare function isCloudStore(env?: Env): boolean;
|
package/dist/lib/store.d.ts
CHANGED
|
@@ -1,9 +1,232 @@
|
|
|
1
|
-
import type { CreateLoopInput, CreateWorkflowInvocationInput, CreateWorkflowInput, Goal, GoalAutoExecute, GoalPlanNode, GoalRun, GoalStatus, Loop, LoopRun, LoopStatus, RunStatus, TimeoutMs, WorkflowEvent, WorkflowInvocation, WorkflowRun, WorkflowRunStatus, WorkflowSpec, WorkflowStepRun, WorkflowWorkItem, WorkflowWorkItemStatus, UpsertWorkflowWorkItemInput } from "../types.js";
|
|
1
|
+
import type { CreateLoopInput, CreateWorkflowInvocationInput, CreateWorkflowInput, Goal, GoalAutoExecute, GoalPlanNode, GoalRun, GoalStatus, Loop, LoopRun, LoopStatus, RunReceipt, RunStatus, TimeoutMs, WriteRunReceiptInput, WorkflowEvent, WorkflowInvocation, WorkflowRun, WorkflowRunStatus, WorkflowSpec, WorkflowStepRun, WorkflowWorkItem, WorkflowWorkItemStatus, UpsertWorkflowWorkItemInput } from "../types.js";
|
|
2
2
|
interface DaemonLeaseFence {
|
|
3
3
|
daemonLeaseId?: string;
|
|
4
4
|
now?: Date;
|
|
5
5
|
claimToken?: string;
|
|
6
6
|
}
|
|
7
|
+
export interface LoopRow {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description: string | null;
|
|
11
|
+
status: string;
|
|
12
|
+
archived_at: string | null;
|
|
13
|
+
archived_from_status: string | null;
|
|
14
|
+
schedule_json: string;
|
|
15
|
+
target_json: string;
|
|
16
|
+
goal_json: string | null;
|
|
17
|
+
machine_json: string | null;
|
|
18
|
+
next_run_at: string | null;
|
|
19
|
+
retry_scheduled_for: string | null;
|
|
20
|
+
catch_up: string;
|
|
21
|
+
catch_up_limit: number;
|
|
22
|
+
overlap: string;
|
|
23
|
+
max_attempts: number;
|
|
24
|
+
retry_delay_ms: number;
|
|
25
|
+
lease_ms: number;
|
|
26
|
+
expires_at: string | null;
|
|
27
|
+
created_at: string;
|
|
28
|
+
updated_at: string;
|
|
29
|
+
}
|
|
30
|
+
export interface RunRow {
|
|
31
|
+
id: string;
|
|
32
|
+
loop_id: string;
|
|
33
|
+
loop_name: string;
|
|
34
|
+
scheduled_for: string;
|
|
35
|
+
attempt: number;
|
|
36
|
+
status: string;
|
|
37
|
+
started_at: string | null;
|
|
38
|
+
finished_at: string | null;
|
|
39
|
+
claimed_by: string | null;
|
|
40
|
+
claim_token: string | null;
|
|
41
|
+
lease_expires_at: string | null;
|
|
42
|
+
pid: number | null;
|
|
43
|
+
pgid: number | null;
|
|
44
|
+
process_started_at: string | null;
|
|
45
|
+
exit_code: number | null;
|
|
46
|
+
duration_ms: number | null;
|
|
47
|
+
stdout: string | null;
|
|
48
|
+
stderr: string | null;
|
|
49
|
+
error: string | null;
|
|
50
|
+
goal_run_id: string | null;
|
|
51
|
+
created_at: string;
|
|
52
|
+
updated_at: string;
|
|
53
|
+
}
|
|
54
|
+
export interface RunReceiptRow {
|
|
55
|
+
loop_id: string;
|
|
56
|
+
run_id: string;
|
|
57
|
+
machine_json: string;
|
|
58
|
+
repo: string;
|
|
59
|
+
task_ids_json: string;
|
|
60
|
+
knowledge_ids_json: string;
|
|
61
|
+
digest_id: string;
|
|
62
|
+
started_at: string | null;
|
|
63
|
+
finished_at: string | null;
|
|
64
|
+
status: string;
|
|
65
|
+
exit_code: number | null;
|
|
66
|
+
summary_json: string;
|
|
67
|
+
evidence_paths_json: string;
|
|
68
|
+
created_at: string;
|
|
69
|
+
updated_at: string;
|
|
70
|
+
}
|
|
71
|
+
export interface WorkflowRow {
|
|
72
|
+
id: string;
|
|
73
|
+
name: string;
|
|
74
|
+
description: string | null;
|
|
75
|
+
version: number;
|
|
76
|
+
status: string;
|
|
77
|
+
goal_json: string | null;
|
|
78
|
+
steps_json: string;
|
|
79
|
+
created_at: string;
|
|
80
|
+
updated_at: string;
|
|
81
|
+
}
|
|
82
|
+
export interface WorkflowRunRow {
|
|
83
|
+
id: string;
|
|
84
|
+
workflow_id: string;
|
|
85
|
+
workflow_name: string;
|
|
86
|
+
loop_id: string | null;
|
|
87
|
+
loop_run_id: string | null;
|
|
88
|
+
invocation_id: string | null;
|
|
89
|
+
work_item_id: string | null;
|
|
90
|
+
scheduled_for: string | null;
|
|
91
|
+
idempotency_key: string | null;
|
|
92
|
+
manifest_path: string | null;
|
|
93
|
+
status: string;
|
|
94
|
+
started_at: string | null;
|
|
95
|
+
finished_at: string | null;
|
|
96
|
+
duration_ms: number | null;
|
|
97
|
+
error: string | null;
|
|
98
|
+
goal_run_id: string | null;
|
|
99
|
+
created_at: string;
|
|
100
|
+
updated_at: string;
|
|
101
|
+
}
|
|
102
|
+
export interface WorkflowInvocationRow {
|
|
103
|
+
id: string;
|
|
104
|
+
workflow_id: string | null;
|
|
105
|
+
template_id: string | null;
|
|
106
|
+
source_kind: string;
|
|
107
|
+
source_id: string | null;
|
|
108
|
+
source_dedupe_key: string | null;
|
|
109
|
+
source_json: string;
|
|
110
|
+
subject_kind: string;
|
|
111
|
+
subject_id: string | null;
|
|
112
|
+
subject_path: string | null;
|
|
113
|
+
subject_url: string | null;
|
|
114
|
+
subject_json: string;
|
|
115
|
+
intent: string;
|
|
116
|
+
scope_json: string | null;
|
|
117
|
+
output_policy_json: string | null;
|
|
118
|
+
created_at: string;
|
|
119
|
+
updated_at: string;
|
|
120
|
+
}
|
|
121
|
+
export interface WorkflowWorkItemRow {
|
|
122
|
+
id: string;
|
|
123
|
+
route_key: string;
|
|
124
|
+
idempotency_key: string;
|
|
125
|
+
invocation_id: string;
|
|
126
|
+
source_type: string;
|
|
127
|
+
source_ref: string;
|
|
128
|
+
subject_ref: string;
|
|
129
|
+
project_key: string | null;
|
|
130
|
+
project_group: string | null;
|
|
131
|
+
machine_id: string | null;
|
|
132
|
+
route_scope: string | null;
|
|
133
|
+
priority: number;
|
|
134
|
+
status: string;
|
|
135
|
+
attempts: number;
|
|
136
|
+
next_attempt_at: string | null;
|
|
137
|
+
lease_expires_at: string | null;
|
|
138
|
+
workflow_id: string | null;
|
|
139
|
+
loop_id: string | null;
|
|
140
|
+
workflow_run_id: string | null;
|
|
141
|
+
last_reason: string | null;
|
|
142
|
+
created_at: string;
|
|
143
|
+
updated_at: string;
|
|
144
|
+
}
|
|
145
|
+
export interface WorkflowStepRunRow {
|
|
146
|
+
id: string;
|
|
147
|
+
workflow_run_id: string;
|
|
148
|
+
step_id: string;
|
|
149
|
+
sequence: number;
|
|
150
|
+
status: string;
|
|
151
|
+
started_at: string | null;
|
|
152
|
+
finished_at: string | null;
|
|
153
|
+
exit_code: number | null;
|
|
154
|
+
pid: number | null;
|
|
155
|
+
duration_ms: number | null;
|
|
156
|
+
stdout: string | null;
|
|
157
|
+
stderr: string | null;
|
|
158
|
+
error: string | null;
|
|
159
|
+
account_profile: string | null;
|
|
160
|
+
account_tool: string | null;
|
|
161
|
+
goal_run_id: string | null;
|
|
162
|
+
created_at: string;
|
|
163
|
+
updated_at: string;
|
|
164
|
+
}
|
|
165
|
+
export interface WorkflowEventRow {
|
|
166
|
+
id: string;
|
|
167
|
+
workflow_run_id: string;
|
|
168
|
+
sequence: number;
|
|
169
|
+
event_type: string;
|
|
170
|
+
step_id: string | null;
|
|
171
|
+
payload_json: string | null;
|
|
172
|
+
created_at: string;
|
|
173
|
+
}
|
|
174
|
+
export interface GoalRow {
|
|
175
|
+
id: string;
|
|
176
|
+
plan_id: string;
|
|
177
|
+
objective: string;
|
|
178
|
+
status: string;
|
|
179
|
+
token_budget: number | null;
|
|
180
|
+
tokens_used: number;
|
|
181
|
+
time_used_seconds: number;
|
|
182
|
+
auto_execute: string;
|
|
183
|
+
max_tokens: number | null;
|
|
184
|
+
source_type: string | null;
|
|
185
|
+
source_id: string | null;
|
|
186
|
+
loop_id: string | null;
|
|
187
|
+
loop_run_id: string | null;
|
|
188
|
+
workflow_id: string | null;
|
|
189
|
+
workflow_run_id: string | null;
|
|
190
|
+
workflow_step_id: string | null;
|
|
191
|
+
created_at: string;
|
|
192
|
+
updated_at: string;
|
|
193
|
+
}
|
|
194
|
+
export interface GoalPlanNodeRow {
|
|
195
|
+
id: string;
|
|
196
|
+
goal_id: string;
|
|
197
|
+
plan_id: string;
|
|
198
|
+
key: string;
|
|
199
|
+
sequence: number;
|
|
200
|
+
priority: number;
|
|
201
|
+
objective: string;
|
|
202
|
+
status: string;
|
|
203
|
+
ready: number;
|
|
204
|
+
token_budget: number | null;
|
|
205
|
+
tokens_used: number;
|
|
206
|
+
time_used_seconds: number;
|
|
207
|
+
depends_on_json: string;
|
|
208
|
+
created_at: string;
|
|
209
|
+
updated_at: string;
|
|
210
|
+
}
|
|
211
|
+
export interface GoalRunRow {
|
|
212
|
+
id: string;
|
|
213
|
+
goal_id: string;
|
|
214
|
+
plan_id: string;
|
|
215
|
+
loop_id: string | null;
|
|
216
|
+
loop_run_id: string | null;
|
|
217
|
+
workflow_id: string | null;
|
|
218
|
+
workflow_run_id: string | null;
|
|
219
|
+
workflow_step_id: string | null;
|
|
220
|
+
turn: number;
|
|
221
|
+
phase: string;
|
|
222
|
+
status: string;
|
|
223
|
+
node_key: string | null;
|
|
224
|
+
tokens_used: number;
|
|
225
|
+
evidence_json: string | null;
|
|
226
|
+
raw_response_json: string | null;
|
|
227
|
+
created_at: string;
|
|
228
|
+
updated_at: string;
|
|
229
|
+
}
|
|
7
230
|
export interface DaemonLease {
|
|
8
231
|
id: string;
|
|
9
232
|
pid: number;
|
|
@@ -13,6 +236,28 @@ export interface DaemonLease {
|
|
|
13
236
|
createdAt: string;
|
|
14
237
|
updatedAt: string;
|
|
15
238
|
}
|
|
239
|
+
export interface LeaseRow {
|
|
240
|
+
id: string;
|
|
241
|
+
pid: number;
|
|
242
|
+
hostname: string;
|
|
243
|
+
heartbeat_at: string;
|
|
244
|
+
expires_at: string;
|
|
245
|
+
created_at: string;
|
|
246
|
+
updated_at: string;
|
|
247
|
+
}
|
|
248
|
+
export declare function rowToLoop(row: LoopRow): Loop;
|
|
249
|
+
export declare function rowToRun(row: RunRow): LoopRun;
|
|
250
|
+
export declare function rowToRunReceipt(row: RunReceiptRow): RunReceipt;
|
|
251
|
+
export declare function rowToWorkflow(row: WorkflowRow): WorkflowSpec;
|
|
252
|
+
export declare function rowToWorkflowRun(row: WorkflowRunRow): WorkflowRun;
|
|
253
|
+
export declare function rowToWorkflowInvocation(row: WorkflowInvocationRow): WorkflowInvocation;
|
|
254
|
+
export declare function rowToWorkflowWorkItem(row: WorkflowWorkItemRow): WorkflowWorkItem;
|
|
255
|
+
export declare function rowToWorkflowStepRun(row: WorkflowStepRunRow): WorkflowStepRun;
|
|
256
|
+
export declare function rowToGoal(row: GoalRow): Goal;
|
|
257
|
+
export declare function rowToGoalPlanNode(row: GoalPlanNodeRow): GoalPlanNode;
|
|
258
|
+
export declare function rowToGoalRun(row: GoalRunRow): GoalRun;
|
|
259
|
+
export declare function rowToWorkflowEvent(row: WorkflowEventRow): WorkflowEvent;
|
|
260
|
+
export declare function rowToLease(row: LeaseRow): DaemonLease;
|
|
16
261
|
export interface ClaimRunResult {
|
|
17
262
|
run: LoopRun;
|
|
18
263
|
loop: Loop;
|
|
@@ -122,6 +367,10 @@ export interface RecordGoalEventInput {
|
|
|
122
367
|
evidence?: Record<string, unknown>;
|
|
123
368
|
rawResponse?: unknown;
|
|
124
369
|
}
|
|
370
|
+
export declare function workItemStatusForLoopRun(status: RunStatus, attempt: number, maxAttempts: number | undefined): WorkflowWorkItemStatus | undefined;
|
|
371
|
+
export declare function scrubbedOrNull(value: string | undefined | null): string | null;
|
|
372
|
+
/** Scrub secrets then bound size before persisting run stdout/stderr. */
|
|
373
|
+
export declare function persistedRunOutput(value: string | undefined | null): string | null;
|
|
125
374
|
export declare class Store {
|
|
126
375
|
private db;
|
|
127
376
|
private rootDir;
|
|
@@ -131,6 +380,7 @@ export declare class Store {
|
|
|
131
380
|
private migrate;
|
|
132
381
|
private migrations;
|
|
133
382
|
private createBaseSchema;
|
|
383
|
+
private createRunReceiptsSchema;
|
|
134
384
|
/**
|
|
135
385
|
* Add a column only if it does not already exist. Idempotent — avoids the
|
|
136
386
|
* "duplicate column name" error that SQLite logs (via libsqlite3, before any
|
|
@@ -152,9 +402,12 @@ export declare class Store {
|
|
|
152
402
|
listLoops(opts?: {
|
|
153
403
|
status?: LoopStatus;
|
|
154
404
|
limit?: number;
|
|
405
|
+
offset?: number;
|
|
155
406
|
archived?: boolean;
|
|
156
407
|
includeArchived?: boolean;
|
|
408
|
+
name?: string;
|
|
157
409
|
}): Loop[];
|
|
410
|
+
private withLatestRunSummaries;
|
|
158
411
|
dueLoops(now: Date, limit?: number): Loop[];
|
|
159
412
|
updateLoop(id: string, patch: Partial<Pick<Loop, "status" | "nextRunAt" | "retryScheduledFor" | "expiresAt">>, opts?: DaemonLeaseFence): Loop;
|
|
160
413
|
private activeLoopReferenceCount;
|
|
@@ -162,6 +415,7 @@ export declare class Store {
|
|
|
162
415
|
retargetWorkflowLoop(idOrName: string, workflowId: string, opts?: DaemonLeaseFence & {
|
|
163
416
|
workflowTimeoutMs?: TimeoutMs;
|
|
164
417
|
}): Loop;
|
|
418
|
+
updateAgentLoopTimeout(idOrName: string, timeoutMs: TimeoutMs, opts?: DaemonLeaseFence): Loop;
|
|
165
419
|
createAndRetargetWorkflowLoop(idOrName: string, workflowInput: CreateWorkflowInput, opts?: DaemonLeaseFence & {
|
|
166
420
|
workflowTimeoutMs?: TimeoutMs;
|
|
167
421
|
archiveOld?: boolean;
|
|
@@ -201,6 +455,8 @@ export declare class Store {
|
|
|
201
455
|
private generatedRouteArchiveContext;
|
|
202
456
|
private maybeArchiveGeneratedRouteWorkflow;
|
|
203
457
|
private maybeArchiveTerminalGeneratedRouteWorkflow;
|
|
458
|
+
private taskLifecycleTodosPointerContext;
|
|
459
|
+
private syncSuccessfulTaskLifecycleTodosPointers;
|
|
204
460
|
createWorkflowInvocation(input: CreateWorkflowInvocationInput): WorkflowInvocation;
|
|
205
461
|
refreshWorkflowInvocationForWorkItem(workItemId: string, input: CreateWorkflowInvocationInput): WorkflowInvocation;
|
|
206
462
|
getWorkflowInvocation(id: string): WorkflowInvocation | undefined;
|
|
@@ -309,6 +565,7 @@ export declare class Store {
|
|
|
309
565
|
listWorkflowEvents(workflowRunId: string, limit?: number): WorkflowEvent[];
|
|
310
566
|
hasRunningRun(loopId: string): boolean;
|
|
311
567
|
hasRunningRunForSlot(loopId: string, scheduledFor: string): boolean;
|
|
568
|
+
private hasBlockingRunningRunForOtherSlot;
|
|
312
569
|
markRunPid(id: string, pid: number, claimedBy?: string, opts?: DaemonLeaseFence): LoopRun | undefined;
|
|
313
570
|
/**
|
|
314
571
|
* Record the spawned child's process identity (pid, process group id, start
|
|
@@ -332,7 +589,20 @@ export declare class Store {
|
|
|
332
589
|
loopId?: string;
|
|
333
590
|
status?: RunStatus;
|
|
334
591
|
limit?: number;
|
|
592
|
+
offset?: number;
|
|
335
593
|
}): LoopRun[];
|
|
594
|
+
writeRunReceipt(input: WriteRunReceiptInput, opts?: {
|
|
595
|
+
now?: Date;
|
|
596
|
+
}): RunReceipt;
|
|
597
|
+
getRunReceipt(runId: string): RunReceipt | undefined;
|
|
598
|
+
listRunReceipts(opts?: {
|
|
599
|
+
loopId?: string;
|
|
600
|
+
repo?: string;
|
|
601
|
+
taskId?: string;
|
|
602
|
+
knowledgeId?: string;
|
|
603
|
+
status?: string;
|
|
604
|
+
limit?: number;
|
|
605
|
+
}): RunReceipt[];
|
|
336
606
|
private deferLiveExpiredRun;
|
|
337
607
|
recoverExpiredRunLeases(now?: Date, opts?: DaemonLeaseFence & {
|
|
338
608
|
limit?: number;
|
|
@@ -355,6 +625,17 @@ export declare class Store {
|
|
|
355
625
|
}): number;
|
|
356
626
|
countRuns(status?: RunStatus): number;
|
|
357
627
|
exportMigrationRows(opts?: StoreMigrationRowsOptions): StoreMigrationRows;
|
|
628
|
+
/**
|
|
629
|
+
* Page through loop_runs for a streaming export. A full `exportMigrationRows`
|
|
630
|
+
* loads every run's stdout/stderr into memory at once (hundreds of MB on a
|
|
631
|
+
* busy host); a self-hosted backfill instead pulls stable ordered pages so
|
|
632
|
+
* peak memory stays bounded. Order is deterministic (created_at, id) so
|
|
633
|
+
* offset paging over an immutable snapshot never skips or repeats a row.
|
|
634
|
+
*/
|
|
635
|
+
exportMigrationRunPage(opts: {
|
|
636
|
+
limit: number;
|
|
637
|
+
offset: number;
|
|
638
|
+
}): LoopRun[];
|
|
358
639
|
private countTable;
|
|
359
640
|
private migrationChecks;
|
|
360
641
|
upsertMigrationWorkflow(workflow: WorkflowSpec, opts?: StoreMigrationUpsertOptions): WorkflowSpec;
|