@foldrun/core 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -10
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/src/account.d.ts +45 -0
- package/dist/src/account.js +130 -0
- package/dist/src/api-tools.d.ts +8 -0
- package/dist/src/api-tools.js +22 -4
- package/dist/src/approvals.d.ts +104 -1
- package/dist/src/approvals.js +192 -2
- package/dist/src/browser-pod.d.ts +129 -0
- package/dist/src/browser-pod.js +284 -0
- package/dist/src/budget.d.ts +32 -0
- package/dist/src/budget.js +177 -0
- package/dist/src/catalog.js +3 -1
- package/dist/src/clock.d.ts +49 -0
- package/dist/src/clock.js +121 -0
- package/dist/src/completions.js +17 -8
- package/dist/src/confine.d.ts +22 -0
- package/dist/src/confine.js +224 -4
- package/dist/src/deploy.d.ts +33 -0
- package/dist/src/deploy.js +145 -6
- package/dist/src/egress.d.ts +26 -2
- package/dist/src/egress.js +8 -1
- package/dist/src/eol.d.ts +2 -0
- package/dist/src/eol.js +7 -0
- package/dist/src/evals.d.ts +9 -0
- package/dist/src/evals.js +26 -13
- package/dist/src/flow-lint.d.ts +12 -0
- package/dist/src/flow-lint.js +331 -1
- package/dist/src/flow-patterns.d.ts +141 -0
- package/dist/src/flow-patterns.js +568 -0
- package/dist/src/gitrepo.d.ts +18 -0
- package/dist/src/gitrepo.js +49 -0
- package/dist/src/host-env.d.ts +8 -0
- package/dist/src/host-env.js +48 -0
- package/dist/src/json-schema.d.ts +12 -0
- package/dist/src/json-schema.js +202 -0
- package/dist/src/kinds.js +1 -1
- package/dist/src/language.d.ts +17 -0
- package/dist/src/language.js +55 -0
- package/dist/src/layout.d.ts +69 -0
- package/dist/src/layout.js +200 -0
- package/dist/src/library.d.ts +9 -0
- package/dist/src/library.js +43 -4
- package/dist/src/limits.d.ts +84 -0
- package/dist/src/limits.js +287 -0
- package/dist/src/locale.d.ts +47 -0
- package/dist/src/locale.js +177 -0
- package/dist/src/mail.d.ts +88 -0
- package/dist/src/mail.js +245 -0
- package/dist/src/model-probe.d.ts +3 -0
- package/dist/src/model-probe.js +1 -0
- package/dist/src/notify.d.ts +132 -8
- package/dist/src/notify.js +360 -58
- package/dist/src/openapi.js +5 -3
- package/dist/src/operator.d.ts +201 -0
- package/dist/src/operator.js +251 -0
- package/dist/src/paths.d.ts +33 -0
- package/dist/src/paths.js +87 -0
- package/dist/src/platform.d.ts +144 -4
- package/dist/src/platform.js +27 -3
- package/dist/src/provider-health.d.ts +55 -0
- package/dist/src/provider-health.js +233 -0
- package/dist/src/providers.d.ts +481 -0
- package/dist/src/providers.js +1105 -6
- package/dist/src/refusal.d.ts +83 -0
- package/dist/src/refusal.js +281 -0
- package/dist/src/run-container.d.ts +206 -17
- package/dist/src/run-container.js +547 -80
- package/dist/src/runner.d.ts +179 -10
- package/dist/src/runner.js +1423 -169
- package/dist/src/runtime.d.ts +52 -0
- package/dist/src/runtime.js +493 -58
- package/dist/src/script-tools.d.ts +15 -2
- package/dist/src/script-tools.js +44 -4
- package/dist/src/secret-files.d.ts +6 -5
- package/dist/src/secret-files.js +24 -11
- package/dist/src/secret-health.d.ts +83 -0
- package/dist/src/secret-health.js +177 -0
- package/dist/src/secrets.d.ts +38 -1
- package/dist/src/secrets.js +197 -96
- package/dist/src/starter.d.ts +9 -0
- package/dist/src/starter.js +95 -11
- package/dist/src/step-exec.d.ts +106 -1
- package/dist/src/step-exec.js +558 -85
- package/dist/src/step-removal.d.ts +15 -0
- package/dist/src/step-removal.js +49 -0
- package/dist/src/storage.d.ts +23 -4
- package/dist/src/storage.js +125 -23
- package/dist/src/store.d.ts +492 -38
- package/dist/src/store.js +882 -69
- package/dist/src/subagents.d.ts +75 -0
- package/dist/src/subagents.js +149 -0
- package/dist/src/tar.js +2 -1
- package/dist/src/test-mode.d.ts +111 -0
- package/dist/src/test-mode.js +285 -0
- package/dist/src/tool-names.d.ts +13 -1
- package/dist/src/tool-names.js +38 -11
- package/dist/src/tool-programs.d.ts +26 -0
- package/dist/src/tool-programs.js +172 -0
- package/dist/src/tool-test.js +152 -33
- package/dist/src/translator.d.ts +8 -2
- package/dist/src/translator.js +71 -24
- package/dist/src/trigger-log.d.ts +43 -0
- package/dist/src/trigger-log.js +122 -0
- package/dist/src/triggers.d.ts +23 -0
- package/dist/src/triggers.js +101 -12
- package/dist/src/untrusted-fetch.d.ts +11 -0
- package/dist/src/untrusted-fetch.js +77 -0
- package/dist/src/web-actions.d.ts +91 -0
- package/dist/src/web-actions.js +199 -0
- package/dist/src/webhook.d.ts +19 -3
- package/dist/src/webhook.js +50 -11
- package/index.ts +3 -0
- package/package.json +5 -5
- package/src/account.ts +149 -0
- package/src/api-tools.ts +32 -4
- package/src/approvals.ts +253 -2
- package/src/browser-pod.ts +313 -0
- package/src/budget.ts +178 -0
- package/src/catalog.ts +3 -1
- package/src/clock.ts +149 -0
- package/src/completions.ts +17 -8
- package/src/confine.ts +224 -4
- package/src/deploy.ts +137 -6
- package/src/egress.ts +32 -4
- package/src/eol.ts +7 -0
- package/src/evals.ts +36 -11
- package/src/flow-lint.ts +371 -1
- package/src/flow-patterns.ts +597 -0
- package/src/gitrepo.ts +48 -0
- package/src/host-env.ts +51 -0
- package/src/json-schema.ts +184 -0
- package/src/kinds.ts +1 -1
- package/src/language.ts +62 -0
- package/src/layout.ts +228 -0
- package/src/library.ts +50 -4
- package/src/limits.ts +290 -0
- package/src/locale.ts +217 -0
- package/src/mail.ts +316 -0
- package/src/model-probe.ts +4 -0
- package/src/notify.ts +391 -44
- package/src/openapi.ts +5 -3
- package/src/operator.ts +300 -0
- package/src/paths.ts +83 -0
- package/src/platform.ts +158 -5
- package/src/provider-health.ts +275 -0
- package/src/providers.ts +1368 -6
- package/src/refusal.ts +320 -0
- package/src/run-container.ts +611 -76
- package/src/runner.ts +1463 -165
- package/src/runtime.ts +487 -55
- package/src/script-tools.ts +55 -6
- package/src/secret-files.ts +22 -10
- package/src/secret-health.ts +230 -0
- package/src/secrets.ts +191 -95
- package/src/starter.ts +96 -11
- package/src/step-exec.ts +548 -41
- package/src/step-removal.ts +59 -0
- package/src/storage.ts +149 -24
- package/src/store.ts +1227 -74
- package/src/subagents.ts +189 -0
- package/src/tar.ts +2 -1
- package/src/test-mode.ts +311 -0
- package/src/tool-names.ts +40 -11
- package/src/tool-programs.ts +179 -0
- package/src/tool-test.ts +159 -32
- package/src/translator.ts +74 -23
- package/src/trigger-log.ts +160 -0
- package/src/triggers.ts +102 -12
- package/src/untrusted-fetch.ts +88 -0
- package/src/web-actions.ts +237 -0
- package/src/webhook.ts +58 -11
- package/templates/hello/agents/curator/agent.md +1 -1
- package/templates/hello/agents/notetaker/agent.md +1 -1
package/dist/src/store.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { BrowserPodOutcome } from "./browser-pod.ts";
|
|
1
2
|
import { singleWorkspace } from "./paths.ts";
|
|
3
|
+
import type { TestEffect } from "./test-mode.ts";
|
|
4
|
+
import type { OperatorEvent } from "./operator.ts";
|
|
2
5
|
/**
|
|
3
6
|
* The frontmatter of one markdown file, as the runtime reads it. Exported
|
|
4
7
|
* for the CLI: `foldrun probe` used to import gray-matter itself, which is
|
|
@@ -53,9 +56,10 @@ export declare function workspaceDir(tenant: string, workspace: string): string;
|
|
|
53
56
|
* The account root — where `library/`, account secrets and the account-wide
|
|
54
57
|
* AGENTS.md live.
|
|
55
58
|
*
|
|
56
|
-
* On a laptop
|
|
57
|
-
*
|
|
58
|
-
* rule libraryDir uses, so the two never
|
|
59
|
+
* On a laptop it is wherever `singleAccountRoot` says: the workspace's parent
|
|
60
|
+
* for a flat `my-desk/`, and the account root two levels up for a workspace
|
|
61
|
+
* inside `my-account/workspaces/`. Same rule libraryDir uses, so the two never
|
|
62
|
+
* disagree about where "up" is.
|
|
59
63
|
*/
|
|
60
64
|
export declare function accountDir(tenant: string): string;
|
|
61
65
|
/**
|
|
@@ -110,6 +114,10 @@ export declare function assertCanonicalCase(rel: string): void;
|
|
|
110
114
|
export declare const PLATFORM_FILES: string[];
|
|
111
115
|
/** True for anything the platform, not the author or the agent, writes. */
|
|
112
116
|
export declare function isPlatformPath(rel: string): boolean;
|
|
117
|
+
/** What a deploy keeps whatever it ships — the rule above saveWorkspace's
|
|
118
|
+
* body. planDeploy reports removals through the same test, so a plan never
|
|
119
|
+
* lists a file the save would keep. */
|
|
120
|
+
export declare function keptOnDeploy(rel: string, shipped: ReadonlySet<string>): boolean;
|
|
113
121
|
export declare function saveWorkspace(tenant: string, workspace: string, files: DeployFile[],
|
|
114
122
|
/** Attribution for the revision this save records. A deploy passes the
|
|
115
123
|
* commit, which becomes the revision's id. */
|
|
@@ -131,19 +139,25 @@ export interface McpSpec {
|
|
|
131
139
|
url?: string;
|
|
132
140
|
headers: Record<string, string>;
|
|
133
141
|
}
|
|
134
|
-
|
|
142
|
+
/** `outward: true` in a tool's frontmatter: this one sends, posts, buys,
|
|
143
|
+
* publishes or uploads. It changes nothing at run time — `check` uses it to
|
|
144
|
+
* insist the step that grants it has a verify or a gate. */
|
|
145
|
+
export type OutwardMark = {
|
|
146
|
+
outward?: boolean;
|
|
147
|
+
};
|
|
148
|
+
export type ToolDef = ({
|
|
135
149
|
kind: "http";
|
|
136
150
|
name: string;
|
|
137
151
|
spec: ApiSpec;
|
|
138
|
-
} | {
|
|
152
|
+
} & OutwardMark) | ({
|
|
139
153
|
kind: "script";
|
|
140
154
|
name: string;
|
|
141
155
|
spec: Record<string, unknown>;
|
|
142
|
-
} | {
|
|
156
|
+
} & OutwardMark) | ({
|
|
143
157
|
kind: "mcp";
|
|
144
158
|
name: string;
|
|
145
159
|
spec: McpSpec;
|
|
146
|
-
};
|
|
160
|
+
} & OutwardMark);
|
|
147
161
|
/**
|
|
148
162
|
* The program inside a single-file script tool: the first fenced block whose
|
|
149
163
|
* language tag names a runnable language. By tag, not by position — a body
|
|
@@ -167,6 +181,13 @@ export declare function fencedCodeBlock(body: string): {
|
|
|
167
181
|
start: number;
|
|
168
182
|
end: number;
|
|
169
183
|
} | null;
|
|
184
|
+
/**
|
|
185
|
+
* `outward: true` — this tool changes something that is not ours: it sends,
|
|
186
|
+
* posts, buys, publishes, uploads. The runtime does not treat it differently;
|
|
187
|
+
* `check` does, because the step that uses one is the step where a silent
|
|
188
|
+
* failure costs something that cannot be taken back. See `lintFlow`.
|
|
189
|
+
*/
|
|
190
|
+
export declare function toolIsOutward(data: Record<string, unknown>): boolean;
|
|
170
191
|
export declare function parseToolDef(data: Record<string, unknown>, fallbackName: string, body?: string): ToolDef | null;
|
|
171
192
|
/**
|
|
172
193
|
* Tools in a directory, in both shapes.
|
|
@@ -189,6 +210,19 @@ export declare function parseToolDef(data: Record<string, unknown>, fallbackName
|
|
|
189
210
|
*
|
|
190
211
|
* Flat files keep working unchanged — the shape is a migration, not a break.
|
|
191
212
|
*/
|
|
213
|
+
/**
|
|
214
|
+
* A folder tool's `requirements.txt` and `package.json`, as a `runtime:`
|
|
215
|
+
* block. Requirement lines only: comments and blanks are left out, and so
|
|
216
|
+
* are options — whole option lines (`-r`, `--index-url`, `-e`) and the ones
|
|
217
|
+
* a requirement carries (`--hash=…`). Options never reach the installer,
|
|
218
|
+
* which takes them from the same argv as its operands; their NAMES are kept
|
|
219
|
+
* in `ignored`, never their values (an index URL can carry a password), so
|
|
220
|
+
* the build log can say what was not applied. Anything else that is not a
|
|
221
|
+
* requirement is refused later by parseRuntime with a log line, the same as
|
|
222
|
+
* it would be in tool.md. `dependencies` only — a tool's dev dependencies
|
|
223
|
+
* are its author's, not its runtime's.
|
|
224
|
+
*/
|
|
225
|
+
export declare function folderRuntime(folder: string): Record<string, unknown> | null;
|
|
192
226
|
declare function readToolDir(dir: string, scope?: "workspace" | "account"): Record<string, ToolDef>;
|
|
193
227
|
/** Definitions that exist on disk but could not be read, for the scopes an
|
|
194
228
|
* agent draws on. Empty when everything parsed. */
|
|
@@ -211,7 +245,9 @@ export interface ApiSpec {
|
|
|
211
245
|
openapi?: string;
|
|
212
246
|
/** Which of the document's operations to expose — operationIds or
|
|
213
247
|
* `"METHOD /path"` strings. Absent: every operation, capped at 60.
|
|
214
|
-
* Present: only these, and the generic `call_<api>` tool is withheld
|
|
248
|
+
* Present: only these, and the generic `call_<api>` tool is withheld —
|
|
249
|
+
* always. If none of them resolve (document missing, moved, or an
|
|
250
|
+
* operation renamed) the API gets no tools that run: it fails closed. */
|
|
215
251
|
operations?: string[];
|
|
216
252
|
/** Calls per second this API may see from one step: `count` is the burst
|
|
217
253
|
* the bucket holds, `perSec` the refill rate. `"5/s"` → {5, 5};
|
|
@@ -241,14 +277,52 @@ export interface AgentInfo {
|
|
|
241
277
|
/** Names still written under the removed `use:` key. Nothing is granted
|
|
242
278
|
* for them; `foldrun check` and the run log say what to write instead. */
|
|
243
279
|
legacyUse: string[];
|
|
280
|
+
/** Retired built-in names still in `tools:` (files, bash) — granted, but
|
|
281
|
+
* `check` says what to write instead. */
|
|
282
|
+
retiredTools: string[];
|
|
244
283
|
/** Colleagues this agent may consult mid-run (`agents:`) — each becomes a
|
|
245
284
|
* consult_<name> tool. The team's edges, as the author drew them. */
|
|
246
285
|
consults: string[];
|
|
286
|
+
/** Colleagues this agent may DELEGATE to (`subagents:`) — each runs with
|
|
287
|
+
* its own context and its own tools, no wider than this agent's. */
|
|
288
|
+
subagents: string[];
|
|
247
289
|
/** The `skills:` allowlist, or null when the field is absent — which is
|
|
248
290
|
* not the same thing: absent inherits every skill in scope, an empty
|
|
249
291
|
* list withholds all of them. */
|
|
250
292
|
skills: string[] | null;
|
|
251
293
|
secrets: string[];
|
|
294
|
+
/** `budget:` — the most this agent may spend in ONE run, in USD, across
|
|
295
|
+
* every step it takes in it; null is no cap. Per run and nothing else:
|
|
296
|
+
* an agent has no calendar, the workspace and the account do. */
|
|
297
|
+
budget: number | null;
|
|
298
|
+
/** What is wrong with the `budget:` line, or null. */
|
|
299
|
+
budgetProblem: string | null;
|
|
300
|
+
/** `timezone:` — the calendar this agent works to, nearest-wins over its
|
|
301
|
+
* flow's, its workspace's and the account's. Null inherits. */
|
|
302
|
+
timezone: string | null;
|
|
303
|
+
/** What is wrong with the `timezone:` line, or null. */
|
|
304
|
+
timezoneProblem: string | null;
|
|
305
|
+
languageProblem: string | null;
|
|
306
|
+
/** region:/currency:/units:/calendar: values that cannot be read. */
|
|
307
|
+
localeProblems: string[];
|
|
308
|
+
/** `web:` values that cannot work. The run says
|
|
309
|
+
* so in its trail and carries on; check and deploy say so first. */
|
|
310
|
+
webProblems: string[];
|
|
311
|
+
/** `web:` that works but should change — the old `session:` key, a pinned
|
|
312
|
+
* user agent behind the runner image's Chrome (when this process knows
|
|
313
|
+
* that Chrome: FOLDRUN_RUNNER_ENGINES). Warnings, never refusals. */
|
|
314
|
+
webWarnings: string[];
|
|
315
|
+
/** `schedule:` written on an agent, which nothing runs — only a flow has
|
|
316
|
+
* a clock. The message, or null when there is no such line. */
|
|
317
|
+
scheduleProblem: string | null;
|
|
318
|
+
/** `limits:` — the agent's own per-step call limits, as readable. */
|
|
319
|
+
limits: Record<string, number>;
|
|
320
|
+
/** What is wrong with the `limits:` block's shape; key-vs-grant problems
|
|
321
|
+
* need the tool lists, and `check` adds them (limits.ts limitKeyProblems). */
|
|
322
|
+
limitProblems: string[];
|
|
323
|
+
/** Tools this agent declares inline rather than in `tools:` — `apis:`,
|
|
324
|
+
* `scripts:` and `mcpServers:` names — which a limit may also name. */
|
|
325
|
+
inlineTools: string[];
|
|
252
326
|
}
|
|
253
327
|
export declare const MODEL_TIERS: Record<string, string>;
|
|
254
328
|
export type Tier = keyof typeof MODEL_TIERS;
|
|
@@ -280,6 +354,11 @@ export declare function parseApis(raw: unknown): ApiSpec[];
|
|
|
280
354
|
export interface FlowStep {
|
|
281
355
|
agent: string;
|
|
282
356
|
instruction: string;
|
|
357
|
+
/** The instruction was written over more than one line and the parser
|
|
358
|
+
* joined them. It runs, but `foldrun check` says so: a wrapped
|
|
359
|
+
* instruction is one editor keystroke away from being a paragraph of
|
|
360
|
+
* prose the parser has to guess about. */
|
|
361
|
+
wrapped?: boolean;
|
|
283
362
|
group: number;
|
|
284
363
|
optional: boolean;
|
|
285
364
|
/** Set when the step targets another flow (`[[flow:name]]`) instead of an agent. */
|
|
@@ -291,11 +370,14 @@ export interface FlowStep {
|
|
|
291
370
|
effort?: string;
|
|
292
371
|
/** Pause for a human before running this step. */
|
|
293
372
|
approve?: boolean;
|
|
294
|
-
/** Run only if the previous
|
|
295
|
-
*
|
|
373
|
+
/** Run only if the previous group's result has a line beginning with
|
|
374
|
+
* this marker (case-insensitive). The previous group is the nearest
|
|
375
|
+
* earlier one that produced a result. Independent: every matching
|
|
376
|
+
* `when:` step in a group runs. */
|
|
296
377
|
when?: string;
|
|
297
378
|
/** Exclusive routing: of a group's `case:` steps, only the FIRST whose
|
|
298
|
-
*
|
|
379
|
+
* marker leads a line of the previous group's result runs; the rest are
|
|
380
|
+
* routed past. */
|
|
299
381
|
case?: string;
|
|
300
382
|
/** The route of last resort: runs only when none of its group's `case:`
|
|
301
383
|
* steps matched. */
|
|
@@ -357,9 +439,32 @@ export interface FlowStep {
|
|
|
357
439
|
* cannot, and hands the value to the next group losslessly — the narrow
|
|
358
440
|
* move the grammar ADR allowed instead of variables. */
|
|
359
441
|
output?: "json";
|
|
442
|
+
/** `schema:` — the JSON Schema an `output: json` value must satisfy,
|
|
443
|
+
* written inline (one-line JSON, or a YAML block under the key) and
|
|
444
|
+
* checked where the reply is; a value that does not fit fails the step
|
|
445
|
+
* with the field named. */
|
|
446
|
+
schema?: Record<string, unknown> | boolean;
|
|
447
|
+
/** `schema: <path>` — the same, in a file under the workspace, read when
|
|
448
|
+
* the step runs. */
|
|
449
|
+
schemaPath?: string;
|
|
450
|
+
/** `parallel:` — how many of an `each:` step's instances run at once.
|
|
451
|
+
* Unset is all of them, which is what fan-out always did. */
|
|
452
|
+
parallel?: number;
|
|
453
|
+
/** `max_turns:` — the most model turns this step may take before it is
|
|
454
|
+
* stopped, beside `budget:` (money) and `timeout:` (time). */
|
|
455
|
+
maxTurns?: number;
|
|
456
|
+
/** `limits: {web.search: 10}` — this step's call limits, over the agent's
|
|
457
|
+
* (nearest wins per key). See limits.ts. */
|
|
458
|
+
limits?: Record<string, number>;
|
|
360
459
|
/** 1-indexed line in the flow file. Diagnostics without a line make you
|
|
361
460
|
* search; every real linter emits file:line. */
|
|
362
461
|
line?: number;
|
|
462
|
+
/** What is wrong with an option's VALUE, in the author's words — `timeout:
|
|
463
|
+
* abc`, `retry: 9`, `each: columns`. The parser keeps the step (a run
|
|
464
|
+
* still has a shape) and the lint reports each of these as an error, so
|
|
465
|
+
* `foldrun check` fails on a value that would otherwise be read as
|
|
466
|
+
* something the author never wrote: `timeout: 15m` used to be one second. */
|
|
467
|
+
problems?: string[];
|
|
363
468
|
}
|
|
364
469
|
export interface FlowInfo {
|
|
365
470
|
name: string;
|
|
@@ -390,11 +495,16 @@ export interface FlowInfo {
|
|
|
390
495
|
* that crosses it is the last one that runs. Null: no cap of its own
|
|
391
496
|
* (the workspace's monthly `budget:` still applies). */
|
|
392
497
|
budget: number | null;
|
|
498
|
+
/** What is wrong with the `budget:` line, or null. */
|
|
499
|
+
budgetProblem: string | null;
|
|
393
500
|
/** `trigger: flow` — start when this other flow of the workspace finishes,
|
|
394
501
|
* with `on:` saying which endings count. The finished run's summary and
|
|
395
502
|
* result become this run's task. */
|
|
396
503
|
after: string | null;
|
|
397
|
-
|
|
504
|
+
/** `blocked` is a completed run whose verdict is BLOCKED — the work
|
|
505
|
+
* refused itself. `completed` no longer includes those: a follow-up to a
|
|
506
|
+
* publish that did not happen should not run as if it had. */
|
|
507
|
+
on: "completed" | "failed" | "blocked" | "any";
|
|
398
508
|
/** `trigger: once` — an ISO 8601 instant; fires the first tick at or after
|
|
399
509
|
* it, once, then never again. */
|
|
400
510
|
at: string | null;
|
|
@@ -412,6 +522,66 @@ export interface FlowInfo {
|
|
|
412
522
|
/** `trigger: storage` — a path prefix under storage/; a file landing
|
|
413
523
|
* there starts the flow with the path as its task. */
|
|
414
524
|
path: string | null;
|
|
525
|
+
/** `idempotency:` — the name of the field that identifies a delivery, so
|
|
526
|
+
* the same one twice starts one run. A header on the request
|
|
527
|
+
* ("x-github-delivery"), or "body:<key>" for a top-level field of a JSON
|
|
528
|
+
* body. A name, never an expression: the value is read from the delivery,
|
|
529
|
+
* not computed from it. Null: every delivery is its own event. */
|
|
530
|
+
idempotency: string | null;
|
|
531
|
+
/** `debounce:` — seconds of quiet before a fired trigger becomes a run.
|
|
532
|
+
* A burst of deliveries, storage writes or watched changes collapses into
|
|
533
|
+
* one run once they stop. The task is the LAST event's, since that is the
|
|
534
|
+
* state the flow is reacting to. Null: every event starts a run. */
|
|
535
|
+
debounce: number | null;
|
|
536
|
+
/** `throttle:` — the least time between two runs of this flow. A trigger
|
|
537
|
+
* arriving inside the window is dropped, and the trace of the run that
|
|
538
|
+
* held the window says how many. Null: no floor. */
|
|
539
|
+
throttle: number | null;
|
|
540
|
+
/** `catchup:` — what a scheduled flow does about a fire it missed while
|
|
541
|
+
* the platform was not running. "last" is the behaviour that always
|
|
542
|
+
* applied: one make-up run for however many were missed. "none" skips
|
|
543
|
+
* them, for a flow whose moment has passed by the time anyone notices.
|
|
544
|
+
* Null reads as "last". */
|
|
545
|
+
catchup: "last" | "none" | null;
|
|
546
|
+
/** `disable_after:` — consecutive failed runs after which the platform
|
|
547
|
+
* stops firing this flow's schedule and says so. A nightly desk that has
|
|
548
|
+
* failed all week is not going to fix itself, and every one of those runs
|
|
549
|
+
* costs money and sends mail. Null: never quarantined. */
|
|
550
|
+
disableAfter: number | null;
|
|
551
|
+
/** `pause_when:` — a marker (DONE, NOTHING LEFT) that, leading a line of
|
|
552
|
+
* any step's reply in the flow's latest run, pauses its schedule: the
|
|
553
|
+
* work is finished, so firing again would only spend money saying so.
|
|
554
|
+
* Derived from that run, like disable_after, so a run that finds work
|
|
555
|
+
* again (a person clicking Run after adding some) lifts it by itself.
|
|
556
|
+
* Null: never paused. */
|
|
557
|
+
pauseWhen: string | null;
|
|
558
|
+
/** `sla:` — seconds a run of this flow is expected to take. A run still
|
|
559
|
+
* going well past it is reported once, as a notification, and keeps
|
|
560
|
+
* running: this is a smoke alarm, not a timeout. Null: no expectation. */
|
|
561
|
+
sla: number | null;
|
|
562
|
+
/** `approvers:` — the email addresses that may decide this flow's gates,
|
|
563
|
+
* or the single word "admins" for anyone at admin or above. Empty means
|
|
564
|
+
* the account's existing rule: any member who can run the workspace.
|
|
565
|
+
* Nobody may approve their own run's gate whatever this says. */
|
|
566
|
+
approvers: string[] | null;
|
|
567
|
+
/** `approve_within:` — how long a gate waits for a person before the run
|
|
568
|
+
* is rejected and fails. A gate with no expiry holds its run, and its
|
|
569
|
+
* place in the account's concurrency, for as long as nobody looks.
|
|
570
|
+
* Null: it waits indefinitely, which stays the default. */
|
|
571
|
+
approveWithin: number | null;
|
|
572
|
+
/** `live: true` — this flow's runs are real even where the platform would
|
|
573
|
+
* default them to test: in a preview workspace, and as an eval's subject.
|
|
574
|
+
* Only ever an opt-out of the safe default, never the other way round. */
|
|
575
|
+
live: boolean;
|
|
576
|
+
/** `description:` — one line on what this flow is for, shown in listings
|
|
577
|
+
* and the trace. Read here so a documented, scaffolded field means
|
|
578
|
+
* something rather than sitting in every file unread. */
|
|
579
|
+
description: string | null;
|
|
580
|
+
/** Flow-level frontmatter values the parser could not read — a bad
|
|
581
|
+
* `overlap:`/`priority:`/`catchup:`/`on:`/`signature:`, or a step line
|
|
582
|
+
* whose `[[target]]` is malformed. Errors, the way a bad step option is,
|
|
583
|
+
* rather than a silent default. */
|
|
584
|
+
frontProblems: string[];
|
|
415
585
|
steps: FlowStep[];
|
|
416
586
|
}
|
|
417
587
|
export declare const FLOW_TRIGGERS: readonly ["manual", "schedule", "webhook", "email", "flow", "once", "watch", "storage"];
|
|
@@ -422,9 +592,25 @@ export interface AgentAssets {
|
|
|
422
592
|
}
|
|
423
593
|
export declare function agentAssets(tenant: string, workspace: string, agent: string): AgentAssets;
|
|
424
594
|
export declare function listAgents(tenant: string, workspace: string): AgentInfo[];
|
|
595
|
+
/** The most fan-out instances `parallel:` may run at once — the fan-out's
|
|
596
|
+
* own hard cap, since more slots than items is no cap. */
|
|
597
|
+
export declare const PARALLEL_CAP = 20;
|
|
598
|
+
/** The most turns `max_turns:` may allow. A turn is one model reply, tool
|
|
599
|
+
* calls included; a step that needs more than this is not one step. */
|
|
600
|
+
export declare const MAX_TURNS_CAP = 500;
|
|
425
601
|
/** "90s", "30m", "4h", "3d" — or a bare number of seconds. Clamped to 30
|
|
426
602
|
* days: a wait is a pause in a flow, not a second scheduler. */
|
|
427
603
|
export declare function parseWait(value: string): number | undefined;
|
|
604
|
+
/** The one duration grammar every key shares — `wait:`, `timeout:`, the
|
|
605
|
+
* flow's `throttle:`/`debounce:`/`sla:` — as whole seconds, at least 1.
|
|
606
|
+
* Undefined for anything that is not one: the caller says what the key
|
|
607
|
+
* was, because "not a duration" is only useful with the line it names. */
|
|
608
|
+
export declare function parseDuration(value: string): number | undefined;
|
|
609
|
+
/** `timeout:` — the same units `wait:` takes, and no ceiling: the platform
|
|
610
|
+
* sets no clock of its own, so the author's number stands as written.
|
|
611
|
+
* `timeout: 15m` was `Math.max(1, Number("15m") || 0)` — one second — and
|
|
612
|
+
* every step wearing it was cut off before its first tool call returned. */
|
|
613
|
+
export declare function parseTimeout(value: string): number | undefined;
|
|
428
614
|
/** An ISO 8601 instant (YAML may already have parsed it into a Date), or
|
|
429
615
|
* null for anything that is not one — a `once` flow with an unreadable
|
|
430
616
|
* `at:` never fires, and `foldrun check` says so. */
|
|
@@ -437,7 +623,7 @@ export declare function parseInstant(raw: unknown): string | null;
|
|
|
437
623
|
* removed a leading OR a trailing quote independently, so a value that
|
|
438
624
|
* merely *ended* with one lost it — and
|
|
439
625
|
*
|
|
440
|
-
* verify: test "$(cat
|
|
626
|
+
* verify: test "$(cat workspace/storage/draft/published.run)" = "$FOLDRUN_RUN_ID"
|
|
441
627
|
*
|
|
442
628
|
* reached bash unbalanced, which exited 2 with "unexpected EOF" on every
|
|
443
629
|
* run. The step could never pass, whatever the agent did, and nothing said
|
|
@@ -449,7 +635,55 @@ export declare function parseInstant(raw: unknown): string | null;
|
|
|
449
635
|
* they are two pairs, not one wrapper.
|
|
450
636
|
*/
|
|
451
637
|
export declare function unquote(raw: string): string;
|
|
638
|
+
/**
|
|
639
|
+
* Does this text carry the marker a `when:` is looking for?
|
|
640
|
+
*
|
|
641
|
+
* At the START OF A LINE, not anywhere in the prose. A plain substring
|
|
642
|
+
* search is the obvious implementation and it is wrong in a way that is
|
|
643
|
+
* very hard to see: an agent writing
|
|
644
|
+
*
|
|
645
|
+
* There are no BLOCKED items this week.
|
|
646
|
+
*
|
|
647
|
+
* opened a `when: BLOCKED` gate, because the word is right there. Saying a
|
|
648
|
+
* marker is absent necessarily names it, so the more carefully an agent
|
|
649
|
+
* explains itself the more likely it is to trip its own condition. It bit
|
|
650
|
+
* one desk on its first run and sat latent in another.
|
|
651
|
+
*
|
|
652
|
+
* A verdict is written as a headline — the line leads with it — so leading
|
|
653
|
+
* position is what distinguishes "this is my verdict" from "here is a word
|
|
654
|
+
* I am using in a sentence". Markdown decoration in front of it is fine: a
|
|
655
|
+
* heading, a bullet or bold is still a line that leads with the marker.
|
|
656
|
+
*
|
|
657
|
+
* The marker must also END at a boundary, so BLOCKED does not match
|
|
658
|
+
* BLOCKEDBY.
|
|
659
|
+
*/
|
|
660
|
+
/**
|
|
661
|
+
* The path of a `when: rows of <path>` condition, or null when the condition
|
|
662
|
+
* is a marker. `rows of` is the phrase `each:` uses for the same file, so a
|
|
663
|
+
* flow reads a CSV one way in both. The whole phrase is required: a bare
|
|
664
|
+
* `when: ROWS` stays the marker it always was.
|
|
665
|
+
*/
|
|
666
|
+
export declare function whenRowsPath(when: string): string | null;
|
|
667
|
+
export declare function markerPresent(text: string | null | undefined, marker: string): boolean;
|
|
452
668
|
export declare function parseFlow(file: string, raw: string): FlowInfo;
|
|
669
|
+
/** A schema written out: JSON, or YAML (parsed as frontmatter is, by the
|
|
670
|
+
* same engine). The result must be an object — a schema is a document,
|
|
671
|
+
* and `schema: 3` or `schema: [a, b]` describes nothing. */
|
|
672
|
+
export declare function parseSchemaText(text: string): {
|
|
673
|
+
schema: Record<string, unknown> | boolean;
|
|
674
|
+
} | {
|
|
675
|
+
problem: string;
|
|
676
|
+
};
|
|
677
|
+
/** May this person decide a gate of this flow? `approvers:` is an allowlist
|
|
678
|
+
* of addresses plus the word "admins"; an empty list defers to whatever
|
|
679
|
+
* permission the caller already needed to reach the route.
|
|
680
|
+
*
|
|
681
|
+
* Self-approval is refused separately (see approvals.ts): who STARTED a run
|
|
682
|
+
* is a property of the run, not of the flow file. */
|
|
683
|
+
export declare function mayApprove(flow: Pick<FlowInfo, "approvers"> | null | undefined, who: {
|
|
684
|
+
email?: string | null;
|
|
685
|
+
role?: string | null;
|
|
686
|
+
}): boolean;
|
|
453
687
|
/** A live run of this flow — the fact overlap: decisions are made on. */
|
|
454
688
|
export declare function flowHasLiveRun(tenant: string, workspace: string, flowName: string): boolean;
|
|
455
689
|
/**
|
|
@@ -460,41 +694,29 @@ export declare function flowHasLiveRun(tenant: string, workspace: string, flowNa
|
|
|
460
694
|
* and the diff is exactly the lines that changed. A flow with no
|
|
461
695
|
* frontmatter gains the smallest one that can carry the trigger.
|
|
462
696
|
*/
|
|
463
|
-
|
|
697
|
+
declare function setFlowTriggerLF(raw: string, opts: {
|
|
464
698
|
trigger: FlowTrigger;
|
|
465
699
|
schedule?: string;
|
|
466
700
|
timezone?: string;
|
|
467
701
|
}): string;
|
|
468
|
-
|
|
469
|
-
* Rewrite one step's option lines — the board's step editor. Surgical, like
|
|
470
|
-
* every flow rewrite: only the managed option lines of block `index` change;
|
|
471
|
-
* the step line, its unmanaged options (approve stays the `!` marker's
|
|
472
|
-
* business), other steps, comments and frontmatter survive verbatim.
|
|
473
|
-
* `null` clears an option; values are clamped exactly as parseFlow reads
|
|
474
|
-
* them, so what the editor writes is what the runner will do.
|
|
475
|
-
*/
|
|
476
|
-
/**
|
|
477
|
-
* Rewrite one step's instruction, and nothing else.
|
|
478
|
-
*
|
|
479
|
-
* The step line carries four things — the group number, the optional/approve
|
|
480
|
-
* marker, the wikilink, and the instruction — and only the last is being
|
|
481
|
-
* edited. Rebuilding the line from the parsed step would silently normalise
|
|
482
|
-
* the other three (a "2?" becoming "2.", an en dash becoming an em dash), so
|
|
483
|
-
* the prefix is taken verbatim from the file and only the tail replaced. A
|
|
484
|
-
* flow's markdown stays the author's.
|
|
485
|
-
*/
|
|
486
|
-
export declare function updateFlowStepInstruction(raw: string, index: number, instruction: string): string;
|
|
487
|
-
export declare function updateFlowStep(raw: string, index: number, options: Partial<Record<"model" | "effort" | "retry" | "timeout" | "verify" | "when" | "case" | "else" | "loop" | "until" | "each" | "max", string | number | null>>): string;
|
|
488
|
-
export declare function reorderFlowSteps(raw: string, groups: number[][]): string;
|
|
702
|
+
declare function updateFlowStepLF(raw: string, index: number, options: Partial<Record<"model" | "effort" | "retry" | "timeout" | "verify" | "when" | "case" | "else" | "loop" | "until" | "each" | "max" | "limits", string | number | null>>): string;
|
|
489
703
|
/** Append a step as its own group at the end of the flow. */
|
|
490
|
-
|
|
704
|
+
declare function addFlowStepLF(raw: string, step: {
|
|
491
705
|
target: string;
|
|
492
706
|
subflow?: boolean;
|
|
493
707
|
instruction?: string;
|
|
494
708
|
}): string;
|
|
495
|
-
|
|
496
|
-
export declare
|
|
709
|
+
export declare const setFlowTrigger: (raw: string, opts: Parameters<typeof setFlowTriggerLF>[1]) => string;
|
|
710
|
+
export declare const updateFlowStepInstruction: (raw: string, index: number, instruction: string) => string;
|
|
711
|
+
export declare const updateFlowStep: (raw: string, index: number, options: Parameters<typeof updateFlowStepLF>[2]) => string;
|
|
712
|
+
export declare const reorderFlowSteps: (raw: string, groups: number[][]) => string;
|
|
713
|
+
export declare const addFlowStep: (raw: string, step: Parameters<typeof addFlowStepLF>[1]) => string;
|
|
714
|
+
export declare const removeFlowStep: (raw: string, index: number) => string;
|
|
497
715
|
export declare function listFlows(tenant: string, workspace: string): FlowInfo[];
|
|
716
|
+
/** One flow of a workspace by name, or null. The same read listFlows makes,
|
|
717
|
+
* named so callers that want a single flow — the approval rules, the
|
|
718
|
+
* runner's budget stamp — do not each re-implement the directory walk. */
|
|
719
|
+
export declare function readFlow(tenant: string, workspace: string, flowName: string): FlowInfo | null;
|
|
498
720
|
export interface WorkspaceSummary {
|
|
499
721
|
name: string;
|
|
500
722
|
description: string;
|
|
@@ -642,10 +864,83 @@ export interface RunEvent {
|
|
|
642
864
|
call?: string;
|
|
643
865
|
ms?: number;
|
|
644
866
|
err?: boolean;
|
|
867
|
+
/** Set on a test run's event that reports what the platform did instead
|
|
868
|
+
* of the real thing — a refused send, a redirected email, a diverted
|
|
869
|
+
* state write, a withheld secret. The run page lists these; the text is
|
|
870
|
+
* still the trace's line. See test-mode.ts. */
|
|
871
|
+
effect?: TestEffect;
|
|
872
|
+
/** Set when a person was involved mid-step: a question the agent asked
|
|
873
|
+
* (ask_person), its answer, or a message a person sent in (operator.ts). */
|
|
874
|
+
operator?: OperatorEvent;
|
|
875
|
+
/** Set on a tool event a SUB-AGENT made (`subagents:`): its name. The
|
|
876
|
+
* trace labels the call with it; cost stays the step's. */
|
|
877
|
+
subagent?: string;
|
|
878
|
+
/** Set on an error a failed check wrote — `verify:` (its headline and its
|
|
879
|
+
* detail), `output: json`, a schema. What the runner reads to decline a
|
|
880
|
+
* retry of an outward step whose tools already ran. */
|
|
881
|
+
check?: boolean;
|
|
645
882
|
}
|
|
883
|
+
/** A question an agent asked a person while its step ran (tools: [ask]). */
|
|
884
|
+
export interface StepQuestion {
|
|
885
|
+
id: string;
|
|
886
|
+
question: string;
|
|
887
|
+
options?: string[];
|
|
888
|
+
askedAt: string;
|
|
889
|
+
answer?: string;
|
|
890
|
+
answeredAt?: string;
|
|
891
|
+
by?: string | null;
|
|
892
|
+
/** true when the wait ran out with no answer. */
|
|
893
|
+
unanswered?: boolean;
|
|
894
|
+
}
|
|
895
|
+
/** A message a person sent into a running step, and when the agent got it. */
|
|
896
|
+
export interface StepMessage {
|
|
897
|
+
text: string;
|
|
898
|
+
by?: string | null;
|
|
899
|
+
at: string;
|
|
900
|
+
deliveredAt: string;
|
|
901
|
+
}
|
|
902
|
+
/** One attempt of a step — see StepRecord.tries. */
|
|
903
|
+
export interface StepAttempt {
|
|
904
|
+
/** Which try, 1-based, in the order they ran: a retry is the next try,
|
|
905
|
+
* and so is the full re-run after a slim go the browser pod was lost
|
|
906
|
+
* under. Equal to the step's attempt (`attempts` at the time) unless
|
|
907
|
+
* `attempt` says otherwise. */
|
|
908
|
+
n: number;
|
|
909
|
+
/** The step's attempt this try belongs to, written only when it is not
|
|
910
|
+
* `n` — after a lost slim go, its full re-run is try 2 of attempt 1. */
|
|
911
|
+
attempt?: number;
|
|
912
|
+
/** `lost`: a slim go the account's browser pod went away under, which
|
|
913
|
+
* the step ran again on the full image within the same attempt — a row
|
|
914
|
+
* of its own (image slim), before the full go's. */
|
|
915
|
+
status: "completed" | "failed" | "lost";
|
|
916
|
+
costUsd: number | null;
|
|
917
|
+
tokens: {
|
|
918
|
+
input: number;
|
|
919
|
+
output: number;
|
|
920
|
+
} | null;
|
|
921
|
+
computeSecs: number | null;
|
|
922
|
+
startedAt: string;
|
|
923
|
+
finishedAt: string;
|
|
924
|
+
/** The last error event this attempt wrote, when it failed. */
|
|
925
|
+
error?: string;
|
|
926
|
+
/** The runner image this attempt ended on, and — when it browsed through
|
|
927
|
+
* the account's pod from slim — what happened to the pod: reconnects,
|
|
928
|
+
* the re-run on full, or why it was not re-run. */
|
|
929
|
+
image?: "full" | "slim";
|
|
930
|
+
browserPod?: string;
|
|
931
|
+
}
|
|
932
|
+
/** The step's totals across its attempts, from the rows. Null where no
|
|
933
|
+
* attempt reported the figure — an in-process step rents no sandbox, and
|
|
934
|
+
* billing reads null as zero, not as "unknown, charge something". */
|
|
935
|
+
export declare function sumAttempts(tries: StepAttempt[]): Pick<StepAttempt, "costUsd" | "tokens" | "computeSecs">;
|
|
646
936
|
export interface StepRecord {
|
|
647
937
|
agent: string;
|
|
648
938
|
instruction: string;
|
|
939
|
+
/** Questions the agent asked a person mid-step (tools: [ask]), newest
|
|
940
|
+
* last. One without an answer (and not `unanswered`) is still open. */
|
|
941
|
+
questions?: StepQuestion[];
|
|
942
|
+
/** Messages a person sent into the running step, as delivered. */
|
|
943
|
+
messages?: StepMessage[];
|
|
649
944
|
group: number;
|
|
650
945
|
optional: boolean;
|
|
651
946
|
/** Carried from the flow — see FlowStep. Both are resolved at run
|
|
@@ -662,6 +957,17 @@ export interface StepRecord {
|
|
|
662
957
|
verify?: string;
|
|
663
958
|
/** Attempts made so far, for the run trace. */
|
|
664
959
|
attempts?: number;
|
|
960
|
+
/**
|
|
961
|
+
* One row per attempt, oldest first: what each cost and how it ended.
|
|
962
|
+
* `costUsd`, `tokens` and `computeSecs` on the step are the SUM of these
|
|
963
|
+
* rows — a retried step spent every attempt's money, and the run's spend,
|
|
964
|
+
* the flow's `budget:` and the platform's bill all read the step's
|
|
965
|
+
* figure, so the figure is the total. Before this the step carried only
|
|
966
|
+
* the last attempt's cost and a `retry: 2` step could spend three shares
|
|
967
|
+
* of the budget while reporting one. A loop cycle that re-runs the step
|
|
968
|
+
* appends here too, so its earlier cycles are not lost from the bill.
|
|
969
|
+
*/
|
|
970
|
+
tries?: StepAttempt[];
|
|
665
971
|
/** The sandbox this step is executing in, while it is: which executor,
|
|
666
972
|
* its handle (a pod name), and how many of its output lines the driver
|
|
667
973
|
* has already applied to this record. What a driver that inherits the
|
|
@@ -677,6 +983,27 @@ export interface StepRecord {
|
|
|
677
983
|
/** A size class a retry moved the step up to (an evicted or OOM-killed
|
|
678
984
|
* attempt), overriding the agent's own `size:` for the attempts after. */
|
|
679
985
|
sizeUp?: "large" | "heavy";
|
|
986
|
+
/** Which runner image the step's sandbox ran: `full` (browsers in it) or
|
|
987
|
+
* `slim`, why, and `pod` when a browsing step ran slim and browsed
|
|
988
|
+
* through the account's browser pod. The last attempt's; absent where
|
|
989
|
+
* the executor has one image (docker, in-process). */
|
|
990
|
+
image?: {
|
|
991
|
+
variant: "full" | "slim";
|
|
992
|
+
why?: string;
|
|
993
|
+
pod?: boolean;
|
|
994
|
+
} | null;
|
|
995
|
+
/** Slim browsing through the account's pod (browser-pod.ts): reconnect
|
|
996
|
+
* tries and how many got through; when the pod was lost, why and what
|
|
997
|
+
* the step had written by then; and what happened — `fallback` (the
|
|
998
|
+
* step had only read and ran again on the full image) or `failure` (it
|
|
999
|
+
* had written, so it was not re-run). */
|
|
1000
|
+
browserPod?: (BrowserPodOutcome & {
|
|
1001
|
+
fallback?: string;
|
|
1002
|
+
failure?: string;
|
|
1003
|
+
}) | null;
|
|
1004
|
+
/** The slim go a lost browser pod ended, set aside while the step re-runs
|
|
1005
|
+
* on full; recordAttempt makes it a `lost` row of `tries` and clears it. */
|
|
1006
|
+
podLostTry?: Omit<StepAttempt, "n" | "attempt" | "startedAt"> | null;
|
|
680
1007
|
/** When the step actually started and finished executing — not when the
|
|
681
1008
|
* run reached it. A step's events approximate this (first and last), but
|
|
682
1009
|
* a model can think for minutes before its first tool call, and a step
|
|
@@ -699,6 +1026,11 @@ export interface StepRecord {
|
|
|
699
1026
|
max?: number;
|
|
700
1027
|
/** Carried from the flow — see FlowStep. */
|
|
701
1028
|
output?: "json";
|
|
1029
|
+
schema?: Record<string, unknown> | boolean;
|
|
1030
|
+
schemaPath?: string;
|
|
1031
|
+
parallel?: number;
|
|
1032
|
+
maxTurns?: number;
|
|
1033
|
+
limits?: Record<string, number>;
|
|
702
1034
|
/** The parsed JSON an `output: json` step returned. Kept beside the prose
|
|
703
1035
|
* result rather than instead of it: the reply is still what a person
|
|
704
1036
|
* reads on the run page, and the data is what the next step computes on. */
|
|
@@ -824,6 +1156,20 @@ export interface RunRecord {
|
|
|
824
1156
|
* simply gets its first line — which is still better than a status.
|
|
825
1157
|
*/
|
|
826
1158
|
summary?: string | null;
|
|
1159
|
+
/**
|
|
1160
|
+
* What the run's work concluded, when its summary leads with one of the
|
|
1161
|
+
* four verdict words every desk ends on: GOOD, BAD, QUIET, BLOCKED.
|
|
1162
|
+
*
|
|
1163
|
+
* `status` says whether the machine ran — a step crashed, a budget ran
|
|
1164
|
+
* out. The verdict says what the agents found when it did. They are
|
|
1165
|
+
* different facts: a publisher that checks, sees the wrong change in
|
|
1166
|
+
* front of it and refuses to push has run perfectly, and its run is
|
|
1167
|
+
* `completed`. Until this field, that run was a green tick beside a line
|
|
1168
|
+
* reading BLOCKED (run-mu4sdg8z-1otr, 2026-09-17) — the one outcome a
|
|
1169
|
+
* person most needed to see, drawn as success. Null: the summary does
|
|
1170
|
+
* not lead with a verdict, and the run reads exactly as it always did.
|
|
1171
|
+
*/
|
|
1172
|
+
verdict?: Verdict | null;
|
|
827
1173
|
/** The flow's per-run `budget:` at the time this run started, so the cap
|
|
828
1174
|
* a run was held to is on its record rather than read from a file that
|
|
829
1175
|
* may since have changed. Null: none. */
|
|
@@ -832,6 +1178,26 @@ export interface RunRecord {
|
|
|
832
1178
|
* the agents decided was worth remembering, listed so a person can review
|
|
833
1179
|
* the lesson without diffing the folder. */
|
|
834
1180
|
memoryWrites?: string[];
|
|
1181
|
+
/** Who asked for this run, when a person did: their email address. A
|
|
1182
|
+
* schedule, a webhook and a chained flow have no one, and leave it unset.
|
|
1183
|
+
* Kept so a gate can refuse the one approval nobody should be able to
|
|
1184
|
+
* give — your own. */
|
|
1185
|
+
startedBy?: string | null;
|
|
1186
|
+
/** When this run's gate stops waiting, stamped the moment it parks from
|
|
1187
|
+
* the flow's `approve_within:`. A gate nobody answers by then is rejected
|
|
1188
|
+
* and the run fails, rather than holding a concurrency slot forever. */
|
|
1189
|
+
approveBy?: string | null;
|
|
1190
|
+
/** A test run: every step runs for real, against the real files and the
|
|
1191
|
+
* real read APIs, but nothing outward happens — sends are refused or
|
|
1192
|
+
* sunk at the egress proxy, send-capable secrets never enter the
|
|
1193
|
+
* sandbox, and state/ and storage/ writes land under this run's own
|
|
1194
|
+
* directory. On the record, not in an env var, so a script cannot turn
|
|
1195
|
+
* it off; carried onto every rerun of this run. See test-mode.ts. */
|
|
1196
|
+
test?: boolean;
|
|
1197
|
+
/** Digests of the emailed approval links that have already decided a
|
|
1198
|
+
* step of this run — never the tokens. A link is good once; the second
|
|
1199
|
+
* click is a 409, not a second approval. Written by approvals.ts. */
|
|
1200
|
+
approvalLinksUsed?: string[];
|
|
835
1201
|
steps: StepRecord[];
|
|
836
1202
|
}
|
|
837
1203
|
export declare function runFilePath(tenant: string, workspace: string, runId: string): string;
|
|
@@ -878,7 +1244,81 @@ export declare function writeRun(tenant: string, workspace: string, run: RunReco
|
|
|
878
1244
|
export interface RunWithWorkspace extends RunRecord {
|
|
879
1245
|
workspace: string;
|
|
880
1246
|
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Every run in the account, newest first, off the per-workspace index.
|
|
1249
|
+
*
|
|
1250
|
+
* A finished run comes back as the index knows it: id, flow, status,
|
|
1251
|
+
* summary, times, and each step's agent, group, status, cost, tokens,
|
|
1252
|
+
* seconds, skip reason and last error — with `instruction` empty, `events`
|
|
1253
|
+
* holding only that error, and `result` null. That is what every list and
|
|
1254
|
+
* every rollup reads (runCost, runFailure, runDurationSecs, the usage
|
|
1255
|
+
* window, the graph's stats). A run that is still live — queued, running,
|
|
1256
|
+
* or parked at a gate — is read whole, because the gate's question and its
|
|
1257
|
+
* events are what the approvals list shows. Anything wanting a finished
|
|
1258
|
+
* run's reply or trace opens it with readRun.
|
|
1259
|
+
*
|
|
1260
|
+
* This used to parse every run file of every workspace on every call, and
|
|
1261
|
+
* the dashboard calls it every twenty seconds per open tab.
|
|
1262
|
+
*/
|
|
881
1263
|
export declare function listAllRuns(tenant: string): RunWithWorkspace[];
|
|
1264
|
+
/** What a list knows about one step. */
|
|
1265
|
+
export interface RunSummaryStep {
|
|
1266
|
+
agent: string;
|
|
1267
|
+
group: number;
|
|
1268
|
+
status: StepRecord["status"];
|
|
1269
|
+
costUsd: number | null;
|
|
1270
|
+
tokens?: {
|
|
1271
|
+
input: number;
|
|
1272
|
+
output: number;
|
|
1273
|
+
} | null;
|
|
1274
|
+
computeSecs?: number | null;
|
|
1275
|
+
skipReason?: string;
|
|
1276
|
+
/** The last error event, for a failed step — what runFailure reads. */
|
|
1277
|
+
error?: string;
|
|
1278
|
+
item?: string;
|
|
1279
|
+
waitFor?: "event";
|
|
1280
|
+
ask?: string;
|
|
1281
|
+
/** The step's instruction, kept for a parked step so the approvals banner can show the question without the record. */
|
|
1282
|
+
instruction?: string;
|
|
1283
|
+
/** When a parked step last spoke — the moment the banner sorts by. */
|
|
1284
|
+
waitingSince?: string;
|
|
1285
|
+
startedAt?: string;
|
|
1286
|
+
finishedAt?: string;
|
|
1287
|
+
}
|
|
1288
|
+
/** What a list knows about one run. */
|
|
1289
|
+
export interface RunSummary {
|
|
1290
|
+
id: string;
|
|
1291
|
+
flow: string;
|
|
1292
|
+
status: RunRecord["status"];
|
|
1293
|
+
summary: string | null;
|
|
1294
|
+
startedAt: string;
|
|
1295
|
+
finishedAt: string | null;
|
|
1296
|
+
stopRequested?: boolean;
|
|
1297
|
+
test?: boolean;
|
|
1298
|
+
budgetUsd?: number | null;
|
|
1299
|
+
tags?: string[];
|
|
1300
|
+
startedBy?: string | null;
|
|
1301
|
+
parkedAt?: string | null;
|
|
1302
|
+
/** A step is parked for a person — what the approvals banner counts. */
|
|
1303
|
+
awaitingApproval: boolean;
|
|
1304
|
+
steps: RunSummaryStep[];
|
|
1305
|
+
}
|
|
1306
|
+
/** One run's row. */
|
|
1307
|
+
export declare function summarizeRun(run: RunRecord): RunSummary;
|
|
1308
|
+
/** A RunRecord with the shape a list reads and nothing else — see listAllRuns. */
|
|
1309
|
+
export declare function runFromSummary(s: RunSummary): RunRecord;
|
|
1310
|
+
/**
|
|
1311
|
+
* The workspace's runs as the index knows them, newest first — the call a
|
|
1312
|
+
* list makes. Reconciled against the directory on every read: rows for
|
|
1313
|
+
* records that are gone are dropped, records with no row or a moved mtime
|
|
1314
|
+
* are re-read, and the index is rewritten if anything changed. A missing
|
|
1315
|
+
* or unreadable index is a full scan that leaves one behind.
|
|
1316
|
+
*/
|
|
1317
|
+
export declare function listRunSummaries(tenant: string, workspace: string): RunSummary[];
|
|
1318
|
+
/** Every workspace's runs as summaries, tagged with the workspace. */
|
|
1319
|
+
export declare function listAllRunSummaries(tenant: string): (RunSummary & {
|
|
1320
|
+
workspace: string;
|
|
1321
|
+
})[];
|
|
882
1322
|
/**
|
|
883
1323
|
* The status a person should see. "failed" and "someone stopped it" are
|
|
884
1324
|
* different facts — the record keeps them apart (stopRequested), and the
|
|
@@ -943,6 +1383,18 @@ export declare function runFailure(run: RunRecord): {
|
|
|
943
1383
|
* runFailure, which puts the reason for a failure on the list for the same
|
|
944
1384
|
* reason — the sentence was in the record all along.
|
|
945
1385
|
*/
|
|
1386
|
+
export declare const VERDICTS: readonly ["GOOD", "BAD", "QUIET", "BLOCKED"];
|
|
1387
|
+
export type Verdict = (typeof VERDICTS)[number];
|
|
1388
|
+
/**
|
|
1389
|
+
* The verdict a headline leads with, or null. Leading, whole-word and
|
|
1390
|
+
* upper-case only — "GOOD — 6 links applied", "**BLOCKED**: nothing
|
|
1391
|
+
* pushed", "BAD: 3 pages dropped". A summary that merely contains the word
|
|
1392
|
+
* ("no BLOCKED items") has no verdict, for the reason markerPresent gives.
|
|
1393
|
+
*/
|
|
1394
|
+
export declare function verdictOf(summary: string | null | undefined): Verdict | null;
|
|
1395
|
+
/** A run's verdict: recorded when it finished, else read from its summary,
|
|
1396
|
+
* so runs from before the field existed show one too. */
|
|
1397
|
+
export declare function runVerdict(run: Pick<RunRecord, "verdict" | "summary">): Verdict | null;
|
|
946
1398
|
export declare function runSummary(run: RunRecord): string | null;
|
|
947
1399
|
/**
|
|
948
1400
|
* What one step concluded, in a line.
|
|
@@ -997,6 +1449,8 @@ export interface AgentStep {
|
|
|
997
1449
|
* step-io-model, which is the pure copy the client can import. */
|
|
998
1450
|
export declare function deniedPaths(step: Pick<StepRecord, "events">): number;
|
|
999
1451
|
export declare function listAgentSteps(tenant: string, workspace: string, agent: string): AgentStep[];
|
|
1452
|
+
/** Every run of the workspace, whole, newest first. Parses every record;
|
|
1453
|
+
* a list that needs only what a list needs reads listRunSummaries. */
|
|
1000
1454
|
export declare function listRuns(tenant: string, workspace: string): RunRecord[];
|
|
1001
1455
|
/**
|
|
1002
1456
|
* `provider:` — which endpoint the model calls run against, and the two
|