@foldrun/core 2.6.0 → 2.8.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/dist/src/capture.js +39 -1
- package/dist/src/delegate-tools.d.ts +45 -0
- package/dist/src/delegate-tools.js +153 -0
- package/dist/src/egress.d.ts +43 -2
- package/dist/src/frontmatter-fields.js +2 -1
- package/dist/src/oauth-presets.d.ts +7 -0
- package/dist/src/oauth-presets.js +7 -0
- package/dist/src/operator.d.ts +19 -0
- package/dist/src/operator.js +29 -0
- package/dist/src/platform.d.ts +8 -0
- package/dist/src/run-container.d.ts +9 -2
- package/dist/src/run-container.js +38 -2
- package/dist/src/runner.d.ts +21 -1
- package/dist/src/runner.js +362 -14
- package/dist/src/scan.js +17 -1
- package/dist/src/secret-files.js +23 -2
- package/dist/src/secrets.d.ts +62 -2
- package/dist/src/secrets.js +206 -20
- package/dist/src/starter.js +1 -0
- package/dist/src/store.d.ts +34 -0
- package/dist/src/store.js +12 -0
- package/dist/src/subagents.d.ts +14 -0
- package/dist/src/subagents.js +8 -0
- package/package.json +1 -1
- package/src/capture.ts +33 -1
- package/src/delegate-tools.ts +175 -0
- package/src/egress.ts +38 -3
- package/src/frontmatter-fields.ts +2 -1
- package/src/oauth-presets.ts +7 -0
- package/src/operator.ts +52 -0
- package/src/platform.ts +5 -0
- package/src/run-container.ts +46 -3
- package/src/runner.ts +362 -12
- package/src/scan.ts +19 -1
- package/src/secret-files.ts +22 -2
- package/src/secrets.ts +237 -23
- package/src/starter.ts +1 -0
- package/src/store.ts +38 -0
- package/src/subagents.ts +19 -0
|
@@ -477,6 +477,7 @@ try {
|
|
|
477
477
|
const { buildConsultTools } = await import("@foldrun/core/agent-tools");
|
|
478
478
|
const { buildSearchTools, buildHistoryTools, buildDeskTools } = await import("@foldrun/core/context-tools");
|
|
479
479
|
const { httpChannel, buildAskTool, buildPeerTools, inboxReader } = await import("@foldrun/core/operator");
|
|
480
|
+
const { buildDelegateTools } = await import("@foldrun/core/delegate-tools");
|
|
480
481
|
const { startTranslator } = await import("@foldrun/core/translator");
|
|
481
482
|
const { prepareRuntime } = await import("@foldrun/core/runtime");
|
|
482
483
|
const { materializeFileSecrets } = await import("@foldrun/core/secret-files");
|
|
@@ -576,6 +577,39 @@ try {
|
|
|
576
577
|
const ask = input.ask ? buildAskTool({ channel, timeoutSec: input.ask.timeoutSec, emit }) : { server: null };
|
|
577
578
|
const peers = input.peers ? buildPeerTools({ channel, self: input.peers.self, siblings: input.peers.siblings, emit }) : { server: null };
|
|
578
579
|
const inbox = channel ? inboxReader(channel, emit) : undefined;
|
|
580
|
+
// sandbox: own sub-agents: a tool each, whose job runs in its own sandbox
|
|
581
|
+
// on the worker, reached over the same proxy door.
|
|
582
|
+
const delegate = input.delegates?.length ? buildDelegateTools({ specs: input.delegates, channel, emit, timeoutSec: input.timeoutSec }) : { server: null };
|
|
583
|
+
|
|
584
|
+
// Keyless cloud identities (FOLDRUN_IDENTITIES): each token file kept
|
|
585
|
+
// fresh through the proxy's /identity door, which mints only what this
|
|
586
|
+
// step's lease was granted. Fetched before the step starts, renewed five
|
|
587
|
+
// minutes before it expires (with jitter); a failure is said and retried.
|
|
588
|
+
// Plain JS: this text is the driver, not TypeScript.
|
|
589
|
+
const identityNames = (env.FOLDRUN_IDENTITIES || "").split(",").filter(Boolean);
|
|
590
|
+
if (identityNames.length) {
|
|
591
|
+
// No backslashes: this sits inside a template literal, which eats them.
|
|
592
|
+
const ep = new RegExp("^(https?://[^/]+)/e/([A-Za-z0-9_-]{16,})/?$").exec(env.FOLDRUN_EGRESS || "");
|
|
593
|
+
const dir = env.FOLDRUN_IDENTITY_DIR || "/tmp/foldrun-identity";
|
|
594
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
595
|
+
const keepFresh = async (name) => {
|
|
596
|
+
let wait = 30000;
|
|
597
|
+
try {
|
|
598
|
+
if (!ep) throw new Error("no egress proxy to ask");
|
|
599
|
+
const res = await fetch(ep[1] + "/identity/" + ep[2] + "/" + name, { signal: AbortSignal.timeout(15000) });
|
|
600
|
+
const body = await res.json().catch(() => ({}));
|
|
601
|
+
if (!res.ok || !body.token) throw new Error((body.error && body.error.message) || ("proxy answered " + res.status));
|
|
602
|
+
const file = dir + "/" + name.toLowerCase() + ".jwt";
|
|
603
|
+
fs.writeFileSync(file + ".tmp", body.token, { mode: 0o600 });
|
|
604
|
+
fs.renameSync(file + ".tmp", file);
|
|
605
|
+
wait = Math.max(30000, body.expiresAt - Date.now() - 300000 + Math.floor(Math.random() * 60000) - 30000);
|
|
606
|
+
} catch (err) {
|
|
607
|
+
emit("error", "identity " + name + ": " + (err && err.message ? err.message : String(err)) + " — trying again in 30s");
|
|
608
|
+
}
|
|
609
|
+
setTimeout(() => { void keepFresh(name); }, wait).unref();
|
|
610
|
+
};
|
|
611
|
+
await Promise.all(identityNames.map(keepFresh));
|
|
612
|
+
}
|
|
579
613
|
|
|
580
614
|
mark("tools");
|
|
581
615
|
const outcome = await executeStep({
|
|
@@ -597,6 +631,7 @@ try {
|
|
|
597
631
|
...(desks.server ? { foldrun_desks: desks.server } : {}),
|
|
598
632
|
...(ask.server ? { foldrun_ask: ask.server } : {}),
|
|
599
633
|
...(peers.server ? { foldrun_peers: peers.server } : {}),
|
|
634
|
+
...(delegate.server ? { foldrun_delegate: delegate.server } : {}),
|
|
600
635
|
...(install.server ? { foldrun_install: install.server } : {}),
|
|
601
636
|
...input.mcpServers,
|
|
602
637
|
},
|
|
@@ -1457,8 +1492,9 @@ export async function runStepInContainer(args) {
|
|
|
1457
1492
|
const wsOut = path.join(staging, "out");
|
|
1458
1493
|
fs.mkdirSync(wsOut);
|
|
1459
1494
|
const back = spawnSync(cli(), ["cp", `${containerId}:/workspace/.`, wsOut], { encoding: "utf8" });
|
|
1495
|
+
let applied = [];
|
|
1460
1496
|
if (back.status === 0) {
|
|
1461
|
-
applyContainerChanges(args.workspaceRoot, wsOut, wsIn, (m) => args.emit("error", m), args.divert);
|
|
1497
|
+
applied = applyContainerChanges(args.workspaceRoot, wsOut, wsIn, (m) => args.emit("error", m), args.divert);
|
|
1462
1498
|
}
|
|
1463
1499
|
else {
|
|
1464
1500
|
args.emit("error", `copy-out failed — the step's file changes were lost:\n${back.stderr.slice(0, 500)}`);
|
|
@@ -1472,7 +1508,7 @@ export async function runStepInContainer(args) {
|
|
|
1472
1508
|
phases,
|
|
1473
1509
|
};
|
|
1474
1510
|
args.emit("info", timingLine(timing));
|
|
1475
|
-
return { ...outcome, timing };
|
|
1511
|
+
return { ...outcome, timing, applied };
|
|
1476
1512
|
}
|
|
1477
1513
|
finally {
|
|
1478
1514
|
if (containerId)
|
package/dist/src/runner.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SubagentSpec } from "./subagents.ts";
|
|
1
|
+
import { type DelegateSpec, type SubagentSpec } from "./subagents.ts";
|
|
2
2
|
import { type FlowStep, type RunRecord, type StepRecord } from "./store.ts";
|
|
3
3
|
import { type Catalog } from "./catalog.ts";
|
|
4
4
|
import { type SearchRoot, type RunDigest } from "./context-tools.ts";
|
|
@@ -189,6 +189,26 @@ export declare function buildSubagentSpecs(o: {
|
|
|
189
189
|
parentAllowed: string[];
|
|
190
190
|
push: (type: "info" | "error", text: string) => void;
|
|
191
191
|
}): SubagentSpec[];
|
|
192
|
+
/**
|
|
193
|
+
* The `sandbox: own` sub-agents a step may hand jobs to: a name and a
|
|
194
|
+
* description each, all the parent's sandbox needs. What they may hold is
|
|
195
|
+
* read from their own file when a job arrives — never cut to the parent's,
|
|
196
|
+
* and never seen by it. `canRun` is false where nothing can start their
|
|
197
|
+
* sandbox (a sub-agent's own step: depth one; a step outside a run).
|
|
198
|
+
*/
|
|
199
|
+
export declare function buildDelegateSpecs(o: {
|
|
200
|
+
names: unknown;
|
|
201
|
+
self: string;
|
|
202
|
+
workspaceRoot: string;
|
|
203
|
+
canRun: boolean;
|
|
204
|
+
push: (type: "info" | "error", text: string) => void;
|
|
205
|
+
/** Told, per offered sub-agent, whether a tool it holds acts outside the
|
|
206
|
+
* workspace — a delegating step whose job may have sent something must
|
|
207
|
+
* not be re-run as if it had only read (launchStep's retry policy). */
|
|
208
|
+
outward?: (name: string, outward: boolean) => void;
|
|
209
|
+
tenant?: string;
|
|
210
|
+
tags?: string[];
|
|
211
|
+
}): DelegateSpec[];
|
|
192
212
|
export declare function sharedInstructions(agentDir: string, tenant: string): string | null;
|
|
193
213
|
/**
|
|
194
214
|
* Which of an agent's in-scope skills load for this run.
|