@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/notify.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { type RunRecord } from "./store.ts";
|
|
2
2
|
/**
|
|
3
|
-
* The platform's own mail: an invite, a low balance.
|
|
3
|
+
* The platform's own mail: an invite, a password reset, a low balance.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* An account that configured its own mail — RESEND_API_KEY and EMAIL_FROM
|
|
6
|
+
* on the account — gets ALL of its mail from that sender, these included:
|
|
7
|
+
* a business that sends from its own domain does not want a second, foreign
|
|
8
|
+
* address turning up in its people's inboxes (2026-09-17, an owner found
|
|
9
|
+
* foldrun.io mail beside their own and asked for none of it). Only an
|
|
10
|
+
* account with no sender of its own falls to the platform's key and sender
|
|
11
|
+
* (FOLDRUN_RESEND_API_KEY, FOLDRUN_EMAIL_FROM), so invites still work
|
|
12
|
+
* before anyone has set mail up.
|
|
11
13
|
*/
|
|
12
14
|
export declare function platformMail(tenant: string): {
|
|
13
15
|
key: string;
|
|
@@ -36,20 +38,102 @@ export interface NotifyConfig {
|
|
|
36
38
|
url?: string;
|
|
37
39
|
email?: string;
|
|
38
40
|
events: string[];
|
|
41
|
+
/** `signing_secret:` — the NAME of a vault secret, never its value. With
|
|
42
|
+
* one, every webhook carries an HMAC of the body it delivers, so the
|
|
43
|
+
* receiver can tell a real notification from anyone who learned the URL.
|
|
44
|
+
* Inbound hooks have verified a signature since they existed; a delivery
|
|
45
|
+
* going the other way is the same problem in the same shape. */
|
|
46
|
+
signingSecret?: string;
|
|
39
47
|
}
|
|
40
48
|
export declare function notifyConfig(tenant: string, workspace: string): NotifyConfig | null;
|
|
49
|
+
/**
|
|
50
|
+
* The headers that prove a delivery came from this install.
|
|
51
|
+
*
|
|
52
|
+
* `x-foldrun-signature` is a hex SHA-256 HMAC over "<timestamp>.<body>",
|
|
53
|
+
* keyed by the named vault secret — the timestamp is inside the signed
|
|
54
|
+
* string so a captured delivery cannot be replayed later with a fresh one.
|
|
55
|
+
* `x-signature` is the plain HMAC of the body beside it, the scheme the
|
|
56
|
+
* inbound `signature: hmac` verifies.
|
|
57
|
+
*
|
|
58
|
+
* No secret named, no headers: signing is opt-in, and a receiver that does
|
|
59
|
+
* not check one is no worse off than before.
|
|
60
|
+
*/
|
|
61
|
+
export declare function signatureHeaders(tenant: string, workspace: string, config: NotifyConfig, body: string): Record<string, string>;
|
|
62
|
+
/** When each attempt is made, counted from the one before: at once, then
|
|
63
|
+
* 1m, 5m, 30m, 2h and 6h. Six attempts over about eight and a half hours,
|
|
64
|
+
* then the delivery is given up and stays in the log to be redelivered. */
|
|
65
|
+
export declare const WEBHOOK_BACKOFF_MS: readonly [0, 60000, number, number, number, number];
|
|
66
|
+
/** When attempt `n + 1` is due after attempt `n` (1-based) failed at
|
|
67
|
+
* `at`, or null when `n` was the last. */
|
|
68
|
+
export declare function nextAttemptAt(n: number, at: number): number | null;
|
|
69
|
+
/** The delivery id: sent as X-Foldrun-Delivery on every attempt of one
|
|
70
|
+
* delivery, redeliveries included, so a receiver dedupes on it. */
|
|
71
|
+
export declare function newDeliveryId(): string;
|
|
72
|
+
/** The URL with ${SECRET}s resolved, and how it may be shown: a Slack hook
|
|
73
|
+
* URL is itself a credential, so it is never echoed resolved. */
|
|
74
|
+
export declare function webhookTarget(tenant: string, workspace: string, config?: NotifyConfig | null): {
|
|
75
|
+
url: string | null;
|
|
76
|
+
shown: string;
|
|
77
|
+
};
|
|
78
|
+
export interface WebhookAttempt {
|
|
79
|
+
/** 1-based. */
|
|
80
|
+
n: number;
|
|
81
|
+
at: string;
|
|
82
|
+
/** The receiver's status, or null when none came back (a timeout, DNS). */
|
|
83
|
+
statusCode: number | null;
|
|
84
|
+
durationMs: number;
|
|
85
|
+
/** The first 500 characters of what the receiver answered. */
|
|
86
|
+
response: string | null;
|
|
87
|
+
error: string | null;
|
|
88
|
+
/** A person pressed redeliver or test; not part of the backoff. */
|
|
89
|
+
manual?: boolean;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* One attempt at one delivery, against the workspace's notify: as it reads
|
|
93
|
+
* NOW — a URL fixed between attempts is the one the retry goes to. Signed
|
|
94
|
+
* afresh each time (the timestamp is inside the signature, so a stale
|
|
95
|
+
* signature is one a receiver should refuse). Never throws.
|
|
96
|
+
*/
|
|
97
|
+
export declare function attemptWebhook(tenant: string, workspace: string, d: {
|
|
98
|
+
id: string;
|
|
99
|
+
event: string;
|
|
100
|
+
body: string;
|
|
101
|
+
attempt: number;
|
|
102
|
+
manual?: boolean;
|
|
103
|
+
}): Promise<WebhookAttempt & {
|
|
104
|
+
ok: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
/** One waiting step's pair of links. */
|
|
107
|
+
export interface StepLinks {
|
|
108
|
+
/** Index into run.steps. */
|
|
109
|
+
step: number;
|
|
110
|
+
agent: string;
|
|
111
|
+
approveUrl: string;
|
|
112
|
+
rejectUrl: string;
|
|
113
|
+
}
|
|
41
114
|
/**
|
|
42
115
|
* The approve/reject links for a run waiting on a person, or null when the
|
|
43
116
|
* install cannot say where it lives. A notification that only says "waiting
|
|
44
117
|
* for you" sends the reader to find a laptop; one that carries the decision
|
|
45
118
|
* lets them make it where they read it.
|
|
46
119
|
*
|
|
120
|
+
* One pair per waiting step, each bound to that step and to a moment (the
|
|
121
|
+
* flow's `approve_within:`, else a week) — see approvals.ts. A link bound
|
|
122
|
+
* to the run alone approved every later gate of the run for as long as it
|
|
123
|
+
* ran. When the notification goes to a named approver — an address in the
|
|
124
|
+
* flow's `approvers:` — the links are bound to that person too, so a
|
|
125
|
+
* forwarded mail decides as nobody. `approveUrl`/`rejectUrl` on the result
|
|
126
|
+
* are the first waiting step's pair, for receivers written against that.
|
|
127
|
+
*
|
|
47
128
|
* The reject link goes to the same page with the choice pre-selected — a
|
|
48
129
|
* GET must not decide anything, because inbox link-checkers follow links.
|
|
49
130
|
*/
|
|
50
|
-
export declare function approvalLinks(tenant: string, workspace: string,
|
|
131
|
+
export declare function approvalLinks(tenant: string, workspace: string, run: RunRecord,
|
|
132
|
+
/** Who the notification is going to, when it is going to one address. */
|
|
133
|
+
recipient?: string | null): {
|
|
51
134
|
approveUrl: string;
|
|
52
135
|
rejectUrl: string;
|
|
136
|
+
links: StepLinks[];
|
|
53
137
|
} | null;
|
|
54
138
|
/**
|
|
55
139
|
* Fire the webhook for a run's state, if the workspace asked to hear about
|
|
@@ -58,4 +142,44 @@ export declare function approvalLinks(tenant: string, workspace: string, runId:
|
|
|
58
142
|
*/
|
|
59
143
|
/** Flows whose completion is nobody's news: eval cases and adhoc runs. */
|
|
60
144
|
export declare function isQuietFlow(flow: string): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* A notification that is not about one run finishing.
|
|
147
|
+
*
|
|
148
|
+
* Three things need to say something to the same destination a run
|
|
149
|
+
* notification goes to, and none of them has a RunRecord to hand: a flow
|
|
150
|
+
* that has been quarantined, a run that has outlived its `sla:`, and a
|
|
151
|
+
* budget that is nearly spent. They are the messages a person most needs
|
|
152
|
+
* and least expects, because each one is about something NOT happening —
|
|
153
|
+
* the failure mode that never sends mail is the one that costs a week.
|
|
154
|
+
*
|
|
155
|
+
* The event name is matched against `events:` exactly like a run status,
|
|
156
|
+
* so a workspace that wants none of this writes its own list and gets none
|
|
157
|
+
* of it. They are on by default: an alert nobody opted into is the point.
|
|
158
|
+
*/
|
|
159
|
+
export declare function sendPlainNotification(tenant: string, workspace: string, msg: {
|
|
160
|
+
event: string;
|
|
161
|
+
headline: string;
|
|
162
|
+
detail: string;
|
|
163
|
+
flow?: string;
|
|
164
|
+
runId?: string;
|
|
165
|
+
}): Promise<boolean>;
|
|
166
|
+
/**
|
|
167
|
+
* Prove the notification path works, now, while someone is looking.
|
|
168
|
+
*
|
|
169
|
+
* Every run notification is sent when nobody is watching, to a destination
|
|
170
|
+
* nobody has tested, through a mail domain nobody has verified. On
|
|
171
|
+
* 2026-09-06 every one of them had been going to a bin for weeks and the
|
|
172
|
+
* only symptom was silence — which is indistinguishable from nothing having
|
|
173
|
+
* gone wrong. An alert that has never been proven to arrive is not an alert.
|
|
174
|
+
*
|
|
175
|
+
* Unlike every other send here, this one reports its failure in full: the
|
|
176
|
+
* provider's own words, which are what actually name the problem ("domain
|
|
177
|
+
* not verified", "you can only send to your own address"). Swallowing them
|
|
178
|
+
* is right for a run notification and useless for a test.
|
|
179
|
+
*/
|
|
180
|
+
export declare function sendTestNotification(tenant: string, workspace: string): Promise<{
|
|
181
|
+
ok: boolean;
|
|
182
|
+
destination: string;
|
|
183
|
+
detail: string;
|
|
184
|
+
}>;
|
|
61
185
|
export declare function sendRunNotification(tenant: string, workspace: string, run: RunRecord): Promise<boolean>;
|