@foldrun/core 0.4.0 → 0.6.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.
Files changed (170) hide show
  1. package/README.md +7 -4
  2. package/dist/index.d.ts +4 -0
  3. package/dist/index.js +4 -0
  4. package/dist/src/account.d.ts +45 -0
  5. package/dist/src/account.js +130 -0
  6. package/dist/src/api-tools.d.ts +8 -0
  7. package/dist/src/api-tools.js +22 -4
  8. package/dist/src/browser-pod.d.ts +148 -0
  9. package/dist/src/browser-pod.js +333 -0
  10. package/dist/src/catalog.js +2 -1
  11. package/dist/src/clock.d.ts +49 -0
  12. package/dist/src/clock.js +121 -0
  13. package/dist/src/completions.js +17 -8
  14. package/dist/src/confine.d.ts +22 -0
  15. package/dist/src/confine.js +218 -3
  16. package/dist/src/container.d.ts +9 -0
  17. package/dist/src/container.js +115 -5
  18. package/dist/src/context-tools.d.ts +1 -1
  19. package/dist/src/deploy.d.ts +33 -0
  20. package/dist/src/deploy.js +145 -6
  21. package/dist/src/egress.d.ts +7 -0
  22. package/dist/src/egress.js +6 -0
  23. package/dist/src/eol.d.ts +2 -0
  24. package/dist/src/eol.js +7 -0
  25. package/dist/src/evals.d.ts +5 -0
  26. package/dist/src/evals.js +9 -2
  27. package/dist/src/flow-lint.d.ts +8 -0
  28. package/dist/src/flow-lint.js +223 -1
  29. package/dist/src/flow-patterns.d.ts +141 -0
  30. package/dist/src/flow-patterns.js +568 -0
  31. package/dist/src/gitrepo.d.ts +18 -0
  32. package/dist/src/gitrepo.js +49 -0
  33. package/dist/src/host-env.js +5 -0
  34. package/dist/src/kinds.js +1 -1
  35. package/dist/src/language.d.ts +17 -0
  36. package/dist/src/language.js +55 -0
  37. package/dist/src/layout.d.ts +69 -0
  38. package/dist/src/layout.js +200 -0
  39. package/dist/src/library.d.ts +9 -0
  40. package/dist/src/library.js +30 -3
  41. package/dist/src/limits.d.ts +84 -0
  42. package/dist/src/limits.js +287 -0
  43. package/dist/src/locale.d.ts +47 -0
  44. package/dist/src/locale.js +177 -0
  45. package/dist/src/mail.d.ts +88 -0
  46. package/dist/src/mail.js +247 -0
  47. package/dist/src/model-credential.d.ts +14 -0
  48. package/dist/src/model-credential.js +58 -0
  49. package/dist/src/model-probe.d.ts +3 -0
  50. package/dist/src/model-probe.js +1 -0
  51. package/dist/src/notify.d.ts +53 -7
  52. package/dist/src/notify.js +194 -126
  53. package/dist/src/openapi.js +5 -3
  54. package/dist/src/operator.d.ts +201 -0
  55. package/dist/src/operator.js +251 -0
  56. package/dist/src/paths.d.ts +28 -0
  57. package/dist/src/paths.js +55 -0
  58. package/dist/src/platform.d.ts +43 -3
  59. package/dist/src/platform.js +9 -1
  60. package/dist/src/provider-health.js +3 -2
  61. package/dist/src/providers.d.ts +481 -0
  62. package/dist/src/providers.js +1105 -6
  63. package/dist/src/refusal.d.ts +83 -0
  64. package/dist/src/refusal.js +281 -0
  65. package/dist/src/run-container.d.ts +149 -13
  66. package/dist/src/run-container.js +424 -43
  67. package/dist/src/runner.d.ts +177 -9
  68. package/dist/src/runner.js +1146 -154
  69. package/dist/src/runtime.d.ts +52 -0
  70. package/dist/src/runtime.js +493 -58
  71. package/dist/src/script-tools.d.ts +17 -2
  72. package/dist/src/script-tools.js +82 -10
  73. package/dist/src/secret-files.d.ts +6 -5
  74. package/dist/src/secret-files.js +24 -11
  75. package/dist/src/secret-health.d.ts +30 -6
  76. package/dist/src/secret-health.js +42 -20
  77. package/dist/src/secrets.d.ts +19 -0
  78. package/dist/src/secrets.js +155 -86
  79. package/dist/src/starter.d.ts +9 -0
  80. package/dist/src/starter.js +92 -11
  81. package/dist/src/step-exec.d.ts +72 -2
  82. package/dist/src/step-exec.js +431 -37
  83. package/dist/src/step-removal.d.ts +15 -0
  84. package/dist/src/step-removal.js +49 -0
  85. package/dist/src/storage.d.ts +23 -4
  86. package/dist/src/storage.js +125 -23
  87. package/dist/src/store.d.ts +222 -37
  88. package/dist/src/store.js +349 -62
  89. package/dist/src/subagents.d.ts +75 -0
  90. package/dist/src/subagents.js +149 -0
  91. package/dist/src/test-mode.d.ts +17 -2
  92. package/dist/src/test-mode.js +53 -13
  93. package/dist/src/tool-names.d.ts +13 -1
  94. package/dist/src/tool-names.js +38 -11
  95. package/dist/src/tool-programs.d.ts +26 -0
  96. package/dist/src/tool-programs.js +172 -0
  97. package/dist/src/tool-test.js +104 -12
  98. package/dist/src/translator.d.ts +8 -2
  99. package/dist/src/translator.js +69 -23
  100. package/dist/src/trigger-log.d.ts +1 -1
  101. package/dist/src/triggers.d.ts +3 -0
  102. package/dist/src/triggers.js +10 -2
  103. package/dist/src/untrusted-fetch.d.ts +11 -0
  104. package/dist/src/untrusted-fetch.js +77 -0
  105. package/dist/src/web-actions.d.ts +91 -0
  106. package/dist/src/web-actions.js +199 -0
  107. package/dist/src/webhook.d.ts +4 -0
  108. package/dist/src/webhook.js +39 -0
  109. package/index.ts +4 -0
  110. package/package.json +3 -3
  111. package/src/account.ts +149 -0
  112. package/src/api-tools.ts +32 -4
  113. package/src/browser-pod.ts +350 -0
  114. package/src/catalog.ts +2 -1
  115. package/src/clock.ts +149 -0
  116. package/src/completions.ts +17 -8
  117. package/src/confine.ts +218 -3
  118. package/src/container.ts +112 -5
  119. package/src/context-tools.ts +1 -1
  120. package/src/deploy.ts +137 -6
  121. package/src/egress.ts +13 -1
  122. package/src/eol.ts +7 -0
  123. package/src/evals.ts +14 -2
  124. package/src/flow-lint.ts +253 -1
  125. package/src/flow-patterns.ts +597 -0
  126. package/src/gitrepo.ts +48 -0
  127. package/src/host-env.ts +5 -0
  128. package/src/kinds.ts +1 -1
  129. package/src/language.ts +62 -0
  130. package/src/layout.ts +228 -0
  131. package/src/library.ts +37 -3
  132. package/src/limits.ts +290 -0
  133. package/src/locale.ts +217 -0
  134. package/src/mail.ts +318 -0
  135. package/src/model-credential.ts +71 -0
  136. package/src/model-probe.ts +4 -0
  137. package/src/notify.ts +189 -103
  138. package/src/openapi.ts +5 -3
  139. package/src/operator.ts +300 -0
  140. package/src/paths.ts +54 -0
  141. package/src/platform.ts +52 -3
  142. package/src/provider-health.ts +3 -2
  143. package/src/providers.ts +1368 -6
  144. package/src/refusal.ts +320 -0
  145. package/src/run-container.ts +460 -44
  146. package/src/runner.ts +1168 -155
  147. package/src/runtime.ts +487 -55
  148. package/src/script-tools.ts +81 -10
  149. package/src/secret-files.ts +22 -10
  150. package/src/secret-health.ts +64 -19
  151. package/src/secrets.ts +149 -87
  152. package/src/starter.ts +93 -11
  153. package/src/step-exec.ts +447 -38
  154. package/src/step-removal.ts +59 -0
  155. package/src/storage.ts +141 -22
  156. package/src/store.ts +506 -70
  157. package/src/subagents.ts +189 -0
  158. package/src/test-mode.ts +51 -11
  159. package/src/tool-names.ts +40 -11
  160. package/src/tool-programs.ts +179 -0
  161. package/src/tool-test.ts +110 -12
  162. package/src/translator.ts +72 -22
  163. package/src/trigger-log.ts +1 -0
  164. package/src/triggers.ts +10 -2
  165. package/src/untrusted-fetch.ts +88 -0
  166. package/src/web-actions.ts +237 -0
  167. package/src/webhook.ts +41 -0
  168. package/templates/blog-desk/agents/writer/agent.md +1 -1
  169. package/templates/hello/agents/curator/agent.md +4 -4
  170. package/templates/hello/agents/notetaker/agent.md +3 -3
package/src/starter.ts CHANGED
@@ -72,6 +72,37 @@ dropped further down.
72
72
  ];
73
73
  }
74
74
 
75
+ /**
76
+ * What an account folder ignores, at its own root.
77
+ *
78
+ * The workspace scaffold has always shipped one of these; an account folder is
79
+ * the thing that gets committed now, and the key that decrypts its secrets
80
+ * lives at ITS root — `<account>/.foldrun/` — so the guard has to be here too
81
+ * or the first `git add .` commits the vault key.
82
+ */
83
+ export function accountGitignore(): StarterFile {
84
+ return {
85
+ path: ".gitignore",
86
+ content: `# The key that decrypts every secret in this account, plus the local run
87
+ # store. Never commit these.
88
+ .foldrun/
89
+
90
+ # Written by runs, not by you.
91
+ workspaces/*/runs/
92
+ workspaces/*/outputs/
93
+ state/
94
+ storage/
95
+ # The link a running step keeps in its agent folder (workspace/ for the
96
+ # shell); removed when the step ends, ignored in case one is left behind.
97
+ workspaces/*/agents/*/workspace
98
+
99
+ .env
100
+ .env.local
101
+ .DS_Store
102
+ `,
103
+ };
104
+ }
105
+
75
106
  export function starterFiles(workspace: string): StarterFile[] {
76
107
  return [
77
108
  {
@@ -107,6 +138,9 @@ Context every agent here shares. Prices, rules, anything they should all know.
107
138
  # Written by runs, not by you.
108
139
  runs/
109
140
  outputs/
141
+ # The link a running step keeps in its agent folder (workspace/ for the
142
+ # shell); removed when the step ends, ignored in case one is left behind.
143
+ agents/*/workspace
110
144
 
111
145
  .env
112
146
  .env.local
@@ -124,6 +158,8 @@ effort: high
124
158
  tools:
125
159
  - web
126
160
  - read
161
+ web:
162
+ actions: [search, fetch]
127
163
  ---
128
164
 
129
165
  Pick exactly one topic, in a short paragraph, and say who it helps and why now.
@@ -137,7 +173,7 @@ Do not write the article.
137
173
  name: writer
138
174
  description: Turns a brief into a short draft.
139
175
  tools:
140
- - files
176
+ - write
141
177
  ---
142
178
 
143
179
  Write a short draft from the brief you were given. Save it to outputs/draft.md.
@@ -224,6 +260,10 @@ foldrun deploy --url <server> --token $FOLDRUN_TOKEN
224
260
  \`check\` is cheap and catches a broken flow before a schedule fires it at 3am.
225
261
  Run it after edits, the way you would run a typecheck.
226
262
 
263
+ A deploy that would delete files this folder no longer has lists them and
264
+ stops: with no terminal it is refused. Tell the person what it would delete; add \`--yes\`
265
+ only when they asked for exactly that deletion.
266
+
227
267
  ## Where things go
228
268
 
229
269
  | Path | What |
@@ -246,10 +286,23 @@ Regenerated every run means a file; accumulated across runs means \`state/\`.
246
286
  That last row is worth knowing: a subagent you write in Claude Code is imported
247
287
  as \`agents/<name>/agent.md\` at deploy, no conversion. Write it either way.
248
288
 
289
+ ## Paths inside a workspace
290
+
291
+ An agent's working directory is \`agents/<name>/\`. Write every path to the
292
+ workspace's own folders as \`workspace/…\` — \`workspace/storage/report.csv\`,
293
+ \`workspace/state/cursor.json\` — in an agent's prose, in flow options
294
+ (\`each: rows of\`, \`when: rows of\`, \`verify:\`, \`preview:\`, \`schema:\`) and in
295
+ script arguments. It resolves the same in the file tools, the shell, scripts
296
+ and checks. The older \`../../storage/…\` reaches the same place and still
297
+ works; \`foldrun check\` suggests the new spelling where it sees it.
298
+ A Node script started as \`node workspace/tools/x/run.mjs\` is its own main
299
+ module there, so its \`import.meta.url\` entry check runs (it did not before
300
+ 2 Oct 2026 and exited 0 doing nothing).
301
+
249
302
  ## What a deploy does NOT touch
250
303
 
251
- \`runs/\`, \`state/\`, \`secrets.json\`, and any memory an agent wrote that your
252
- push does not mention. Those belong to the platform, not to git — a deploy that
304
+ \`runs/\`, \`state/\`, \`storage/\`, \`secrets.json\`, the trigger log, and any
305
+ memory an agent wrote that your push does not mention. Those belong to the platform, not to git — a deploy that
253
306
  reverted what an agent learned would make every run a little dumber.
254
307
 
255
308
  Secrets never go in these files. \`foldrun secrets\` puts them in the vault, and
@@ -285,19 +338,32 @@ All of it, \`/api/workspaces/<workspace>\` unless noted:
285
338
  | \`/runs/<id>/stop\` | POST | kill it — destroys the sandbox too |
286
339
  | \`/runs/<id>/rerun\` | POST | again, or from a chosen step |
287
340
  | \`/runs/<id>/approve\` | POST | release a run waiting on a human |
341
+ | \`/runs/<id>/answer\` | POST | answer a question an agent is asking mid-step (\`tools: [ask]\`) |
342
+ | \`/runs/<id>/message\` | POST | tell a running step something; \`step\` picks one of a parallel group |
288
343
  | \`/flows\` · \`/flows/<f>\` | GET POST · POST DELETE PATCH | list, create, edit |
289
344
  | \`/flows/<f>/run\` | POST | start a flow |
290
345
  | \`/agents\` · \`/agents/<a>/run\` | GET POST · POST | list agents, run one |
291
346
  | \`/evals\` · \`/evals/<e>/run\` | GET POST · POST | list evals, run one |
292
347
  | \`/tools/<t>/test\` | POST | exercise one tool alone |
293
- | \`/storage\` · \`/storage/download\` · \`/storage/upload-url\` | GET POST PUT DELETE · GET · POST | workspace files |
348
+ | \`/storage\` · \`/storage/download\` · \`/storage/upload-url\` · \`/storage/preview\` | GET POST PUT DELETE · GET · POST · GET | workspace files, any type; \`preview\` returns one parsed for reading |
294
349
  | \`/assets\` | POST | upload an asset |
295
350
  | \`/hooks/<f>/rotate\` | POST | new webhook token for a flow |
351
+ | \`/notify/deliveries\` · \`/notify/deliveries/<id>/redeliver\` | GET · POST | every notify: webhook sent and each attempt; send one again |
352
+ | \`/restore\` | POST | the workspace's source back to a point in its history — \`dryRun\` first, then \`confirm\` |
296
353
  | \`/vocabulary\` | GET | what this workspace's documents may say |
297
354
 
298
355
  Account-level, outside \`/workspaces\`: \`/api/secrets\`, \`/api/keys\`, \`/api/schedule\`,
299
356
  \`/api/approvals\`, \`/api/usage\`, \`/api/library/<kind>\`, \`/api/team\`, \`/api/billing\`,
300
- \`/api/healthz\` (open) and \`/api/metrics\` (Prometheus).
357
+ \`/api/me/notifications\` (what mail you get; a key acts for whoever minted it),
358
+ \`/api/account/backups\` (snapshots, restore requests), \`/api/me/onboarding\` (getting started),
359
+ \`/api/healthz\` and \`/api/version\` (open), \`/api/changelog\` (release notes)
360
+ and \`/api/metrics\` (Prometheus).
361
+
362
+ Every call answers — and the CLI sends — \`Foldrun-Version: YYYY-MM-DD\` (dated API
363
+ versions; an account pin in Settings → API), \`X-RateLimit-*\` headers (a \`429\`
364
+ carries \`Retry-After\`), and writes that start work take an \`Idempotency-Key\`
365
+ (a retry with the same key replays the first answer). The whole surface as
366
+ OpenAPI 3.1: \`/api/openapi.json\` (open), or \`foldrun api spec --out openapi.json\`.
301
367
 
302
368
  Debugging a failed run is usually: \`runs\` to find it, \`runs/<id>\` to read which
303
369
  step failed and what it cost, fix the markdown, \`deploy\`, then \`rerun\`.
@@ -310,6 +376,11 @@ git push endpoint.
310
376
 
311
377
  A numbered list of steps. The number is the GROUP: same number means those
312
378
  steps run in parallel, and the flow waits for all of them before the next.
379
+ The dashboard's canvas and the CLI edit the same file: \`foldrun flow show
380
+ <flow>\` draws it, \`foldrun flow add <flow> <pattern>\` inserts a pattern
381
+ (chain, parallel, router, fan-out, loop, approval, ask, wait, rescue,
382
+ subflow), \`foldrun flow rm-step\` removes a step, and \`foldrun agent link
383
+ <agent> --subagent|--consult|--can-ask\` wires agents together.
313
384
 
314
385
  \`\`\`markdown
315
386
  ---
@@ -325,7 +396,7 @@ priority: normal # high | normal | low — where its runs stand in the q
325
396
  1. [[researcher]] — Find three sources on {{topic}}.
326
397
  2. [[writer]] — Draft from what the researcher found.
327
398
  model: max
328
- verify: the draft cites every source
399
+ verify: judge: the draft cites every source
329
400
  3?. [[editor]] — Tighten it.
330
401
  4!. [[publisher]] — Publish it.
331
402
  \`\`\`
@@ -338,11 +409,14 @@ Indented under a step, any of:
338
409
  | | |
339
410
  |---|---|
340
411
  | \`approve: true\` | stop for a human (\`!\` is shorthand for this) |
341
- | \`when: <condition>\` | run only if it holds |
412
+ | \`when: <MARKER>\` | run only if a line of the previous result begins with it |
413
+ | \`when: rows of <path>\` | run only if that CSV has a data row — for the steps after an \`each:\` |
342
414
  | \`case: <value>\` / \`else: true\` | branch on the previous step's result |
343
415
  | \`retry: 2\` | re-run on failure, up to 5 |
344
416
  | \`timeout: 900\` | seconds before the step is cut off |
345
- | \`verify: <claim>\` | the step fails unless this is true of its output |
417
+ | \`verify: <shell>\` | the step fails unless the command exits 0; the reply is in \`$FOLDRUN_REPLY_FILE\` |
418
+ | \`verify: judge: <claim>\` | a model grades the claim against the output |
419
+ | \`verify: contains:\` / \`not-contains:\` / \`matches:\` / \`file:\` | the cheap checks, no shell |
346
420
  | \`model:\` / \`effort:\` | override the flow's default for this step |
347
421
  | \`loop: 3\` / \`until: <condition>\` | repeat until it holds, at most 5 |
348
422
  | \`each: lines\` | run once per line of the previous result |
@@ -359,6 +433,7 @@ Indented under a step, any of:
359
433
  | \`each: items\` | run once per element of the previous step's JSON array |
360
434
  | \`parallel: 3\` | how many \`each:\` instances run at once — default all |
361
435
  | \`max_turns: 20\` | the most model turns before the step is stopped, beside \`budget:\` and \`timeout:\` |
436
+ | \`limits: {web.search: 10}\` | this step's call limits, over the agent's key by key |
362
437
 
363
438
  ## Writing an agent
364
439
 
@@ -372,14 +447,17 @@ description: Finds and summarises sources.
372
447
  model: default # fast | default | max
373
448
  effort: low # how hard to think about it
374
449
  size: large # small | large | heavy — the sandbox it rents
375
- tools: [WebSearch, Read, my-folder-tool] # built-ins and your own tools/, one list
450
+ tools: [web, read, ask, my-folder-tool] # built-ins and your own tools/, one list; \`ask\` lets it ask you mid-step
376
451
  disallowedTools: [Bash] # subtract from what it would otherwise have
377
452
  skills: [house-style] # from skills/
378
453
  scripts: [summarise.py] # from scripts/, each becomes a callable tool
379
454
  apis: [{ name: crm }] # an HTTP API, as a tool
380
455
  mcpServers: {} # an MCP server, as a tool
381
- agents: [writer] # colleagues this one may consult
382
- secrets: [CRM_TOKEN] # from the vault — never written in these files
456
+ agents: [writer] # colleagues this one may consult (an answer, no tools)
457
+ subagents: [researcher] # colleagues it may delegate a job to (own context, own tools ≤ its own)
458
+ secrets: [CRM_TOKEN] # keys the agent uses itself; a tool's own come with the tool
459
+ limits: {web.search: 40, crm: 20, calls: 300} # per step; a call past a limit is refused, never run
460
+ timezone: Australia/Sydney # the calendar it works to — IANA name or UTC+10
383
461
  provider: {} # BYOK: your own model credential
384
462
  permissionMode: plan # plan first, act once approved
385
463
  runtime: # only if scripts need packages
@@ -392,6 +470,10 @@ You research a topic and report what you found...
392
470
  Only \`name\` and the prose are required. Every other field widens or narrows
393
471
  what the agent can reach, and the default is narrow.
394
472
 
473
+ \`timezone:\` is nearest-wins all the way down: the agent's own, else its
474
+ flow's, else the workspace's AGENTS.md, else the account's, else UTC. It sets
475
+ \`TZ\` and the date the agent is told, so a Sydney desk stamps the Sydney date.
476
+
395
477
  \`runtime:\` installs pip/npm packages in the sandbox each agent runs in. Pin
396
478
  versions the normal way (\`pandas>=2\`, \`lodash@^4\`). Python and Node are
397
479
  supported; anything else should ship as a committed binary.