@ai-ecoverse/slicc-agent 6.19.1 → 6.19.3
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 +1 -1
- package/dist/guests/guard.js +9 -2
- package/dist/guests/guard.js.map +2 -2
- package/dist/scoops/cli.js +16 -3
- package/dist/scoops/cli.js.map +2 -2
- package/dist/scoops/service.js +5 -1
- package/dist/scoops/service.js.map +2 -2
- package/dist/scoops/sync.js +4 -1
- package/dist/scoops/sync.js.map +2 -2
- package/dist/scoops/taints.js +28 -0
- package/dist/scoops/taints.js.map +7 -0
- package/dist/types/guests/guard.d.ts +1 -0
- package/dist/types/scoops/cli.d.ts +5 -1
- package/dist/types/scoops/service.d.ts +8 -6
- package/dist/types/scoops/taints.d.ts +12 -0
- package/dist/types/workflow/index.d.ts +4 -0
- package/dist/workflow/index.js +3 -2
- package/dist/workflow/index.js.map +2 -2
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -358,7 +358,7 @@ A **workflow** is a Claude Code dynamic workflow script, a `.workflow.js`, run a
|
|
|
358
358
|
- **Stop.** `agent workflow stop` aborts the task, which stops every scoop the run has running (each is listed with its creation) and removes their folders.
|
|
359
359
|
- **State.** The session document `slicc.workflows` holds every run: its name, source, status (`running`, `completed`, `failed`, `stopped`), phase, agent counts, output tokens, the last 200 log lines and the result or error. The newest 50 finished runs are kept.
|
|
360
360
|
- **Steps are scoops.** Each agent is a synchronous scoop with the scoop guard, removed when it answers. Scoops don't get the `workflow` tool, and a scoop can't start, stop or save workflows.
|
|
361
|
-
- **Guests.** A run started from a run a guest started (through the `workflow` tool or `agent workflow run` in its bash) records the guest's seats and tiers. Each step's scoop gets them in its `slicc.guest-taint` document, and the guest tool gate reviews every tool call in that scoop as it would the guest's own; a seat that is gone denies them.
|
|
361
|
+
- **Guests.** A run started from a run a guest started (through the `workflow` tool or `agent workflow run` in its bash) records the guest's seats and tiers. Each step's scoop gets them in its `slicc.guest-taint` document, and the guest tool gate reviews every tool call in that scoop as it would the guest's own; a seat that is gone denies them. A scoop that `agent` or `agent --async` starts, or `agent send` feeds, from such a run gets them the same way; a caller that names no agent carries the seats of every running agent.
|
|
362
362
|
- **The `workflow` tool.** A cone's model calls it with `action: run` (`file`, a path or a saved name, or `script`, the source, with `args`, `budget`, `concurrency` and `wait`), `list`, `status`, `stop` or `save` (`run`, `name`, `force`). Guest runs go through the guest tool gate as any tool call does.
|
|
363
363
|
- **The CLI.** `agent workflow run <file.js | name> [--args <json>] [--budget <tokens>] [--concurrency <n>] [--wait]`, or `--script '<js>'`, prints the run id, or with `--wait` the result as JSON (exit 1 if it failed or was stopped). `list`, `status <run>`, `wait <run>`, `stop <run>` and `save <run> <name> [--force]` manage runs. `save` writes the run's source to `~/.slicc/workflows/<name>.workflow.js`, and `agent workflow run <name>` runs it; v6's bare `<name>` command is gone.
|
|
364
364
|
- **Differences from awsl-workflow@1.** No nested `workflow()`, `isolation`, timers or model tiers; a direct `agent()` failure always rejects, with no Claude-compatible `null`; a resumed run continues the same attempt instead of starting a new one with a fresh budget.
|
package/dist/guests/guard.js
CHANGED
|
@@ -115,10 +115,16 @@ async function runTaints(harness, conversationId, context) {
|
|
|
115
115
|
const inherited = (await harness.snapshot(GuestTaintDoc, conversationId, context))?.taints ?? [];
|
|
116
116
|
const seats = (await harness.snapshot(GuestsDoc, context))?.seats ?? {};
|
|
117
117
|
const found = inputs.length ? await taintsOf(inputs, seats, harness, context) : [];
|
|
118
|
-
return [
|
|
118
|
+
return distinctTaints([
|
|
119
119
|
...found.map((taint) => ({ seat: taint.seat?.id ?? null, tier: taint.tier })),
|
|
120
120
|
...inherited
|
|
121
|
-
];
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
function distinctTaints(taints) {
|
|
124
|
+
const kept = /* @__PURE__ */ new Map();
|
|
125
|
+
for (const taint of taints) kept.set(`${taint.seat}
|
|
126
|
+
${taint.tier}`, taint);
|
|
127
|
+
return [...kept.values()];
|
|
122
128
|
}
|
|
123
129
|
function inheritedTaints(inherited, seats) {
|
|
124
130
|
return inherited.map((taint) => ({
|
|
@@ -269,6 +275,7 @@ export {
|
|
|
269
275
|
SUMMARY_LENGTH,
|
|
270
276
|
argumentsHash,
|
|
271
277
|
canonical,
|
|
278
|
+
distinctTaints,
|
|
272
279
|
guestToolGate,
|
|
273
280
|
reasonOf,
|
|
274
281
|
runTaints,
|
package/dist/guests/guard.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/guests/guard.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { awaitWithContext, BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport {\n type ConversationId,\n defineDoc,\n defineExtension,\n type Extension,\n type Harness,\n type HookApi,\n hook,\n LiveDoc,\n type SubmissionId,\n type TaskId,\n type ToolHookCall,\n ToolTask,\n} from '@earendil-works/pi-durable';\nimport type { Approval, Approvals } from '../approvals/index.ts';\nimport { REASONS, scoopTier } from '../approvals/record.ts';\nimport { scrubText, scrubTexts } from '../secrets/scrub.ts';\nimport { type GuestPolicy, gateKind, gateRefusal } from './policy.ts';\nimport { type AlwaysTool, GuestsDoc, isGate, liveSeat, type SeatRecord } from './seats.ts';\n\nexport const GUEST_GUARD = 'slicc-guest-guard';\nexport const GUEST_REQUEST = 'guest:';\nexport const GUEST_TOOL_MEMO = 'slicc.guest-tool';\nexport const SUMMARY_LENGTH = 2000;\n\nexport const GATE_REASONS = {\n unknown:\n 'A guest started this run, and its seat names no review for tool calls that this agent knows.',\n ended: \"A guest started this run, and that guest's seat has ended.\",\n rejected: 'The owner declined this tool call in a run a guest started.',\n judged: 'The automatic check declined this tool call in a run a guest started',\n unanswered: 'Nobody approved this tool call in a run a guest started in time.',\n unroutable: \"The cone can't review a tool call it is itself waiting on.\",\n withdrawn: 'The review of this tool call was withdrawn.',\n} as const;\n\nexport interface GateHost {\n approvals: Pick<Approvals, 'state' | 'request' | 'settled' | 'withdraw'>;\n policy(): GuestPolicy;\n now?: () => number;\n}\n\nexport interface GuestToolGate {\n readonly extension: Extension;\n bind(host: GateHost): void;\n}\n\ntype Held = Pick<Harness, 'submission' | 'commit' | 'waitForTask'>;\n\ntype Taint = { seat: SeatRecord | null; tier: string };\n\nexport function canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (value && typeof value === 'object')\n return `{${Object.keys(value)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${canonical((value as Record<string, unknown>)[key])}`)\n .join(',')}}`;\n return JSON.stringify(value ?? null);\n}\n\nfunction leaves(value: unknown, found: string[]): void {\n if (typeof value === 'string') found.push(value);\n else if (value && typeof value === 'object')\n for (const item of Object.values(value)) leaves(item, found);\n}\n\nfunction replaced(value: unknown, texts: string[]): unknown {\n if (typeof value === 'string') return texts.shift();\n if (Array.isArray(value)) return value.map((item) => replaced(item, texts));\n if (value && typeof value === 'object')\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, replaced(item, texts)])\n );\n return value;\n}\n\nexport async function scrubbedArguments(\n args: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n const found: string[] = [];\n leaves(args, found);\n return replaced(args, await scrubTexts(found)) as Record<string, unknown>;\n}\n\nexport async function argumentsHash(args: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(args));\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nasync function shownArguments(text: string): Promise<string> {\n try {\n return canonical(await scrubbedArguments(JSON.parse(text)));\n } catch {\n return scrubText(text);\n }\n}\n\nexport async function sealedRules(rules: readonly AlwaysTool[]): Promise<AlwaysTool[] | null> {\n if (rules.every((rule) => rule.argumentsHash)) return null;\n return Promise.all(\n rules.map(async (rule) =>\n rule.argumentsHash\n ? rule\n : {\n ...rule,\n argumentsHash: await argumentsHash(rule.arguments),\n arguments: await shownArguments(rule.arguments),\n }\n )\n );\n}\n\nexport function summaryOf(args: Record<string, unknown>): string {\n const values = Object.values(args);\n const text = values.length === 1 && typeof values[0] === 'string' ? values[0] : canonical(args);\n return text.length > SUMMARY_LENGTH ? `${text.slice(0, SUMMARY_LENGTH - 1)}\u2026` : text;\n}\n\nconst SCOOP_SAID: Record<string, (name: string) => string> = {\n [REASONS.noScoop]: (name) => `there is no scoop ${name} in this cone to review it.`,\n [REASONS.scoopStopped]: (name) => `the scoop ${name} is stopped, so it can't review it.`,\n [REASONS.scoopAsked]: (name) =>\n `the scoop ${name} can't review a call that asks something of it.`,\n [REASONS.scoopUndecided]: (name) => `the scoop ${name} ended its review without deciding.`,\n};\n\nfunction scoopReason(item: Approval): string | null {\n const name = item.tier.slice('scoop:'.length);\n if (item.decidedBy?.startsWith('scoop:'))\n return `The scoop ${name} declined this tool call in a run a guest started${item.reason ? `: ${item.reason}` : '.'}`;\n const said = SCOOP_SAID[item.reason ?? ''];\n return said ? `A guest started this run, and ${said(name)}` : null;\n}\n\nexport function reasonOf(item: Approval): string {\n const scooped = item.state === 'rejected' && scoopTier(item.tier) ? scoopReason(item) : null;\n if (scooped) return scooped;\n if (item.state === 'rejected' && item.decidedBy === 'judge')\n return item.verdict\n ? `${GATE_REASONS.judged}: ${item.verdict.reason}`\n : `${GATE_REASONS.judged}.`;\n if (item.state === 'rejected')\n return item.reason && item.reason !== REASONS.unknownAnswer\n ? `${GATE_REASONS.rejected} ${item.reason}`\n : GATE_REASONS.rejected;\n if (item.state === 'withdrawn') return GATE_REASONS.withdrawn;\n if (item.reason === REASONS.unknownTier) return GATE_REASONS.unknown;\n if (item.reason === REASONS.unroutable) return GATE_REASONS.unroutable;\n return GATE_REASONS.unanswered;\n}\n\nexport type InheritedTaint = { seat: string | null; tier: string };\n\nexport const GuestTaintDoc = defineDoc<{ taints: InheritedTaint[] }>({\n kind: 'slicc.guest-taint',\n version: 1,\n scope: 'conversation',\n history: 'rewindable',\n fork: 'asOf',\n initial: () => ({ taints: [] }),\n});\n\ntype TaintReader = Pick<Harness, 'submission' | 'snapshot'>;\n\nexport async function runTaints(\n harness: TaintReader,\n conversationId: ConversationId,\n context: Context\n): Promise<InheritedTaint[]> {\n const live = await harness.snapshot(LiveDoc, conversationId, context);\n const inputs = live?.run?.inputs ?? [];\n const inherited = (await harness.snapshot(GuestTaintDoc, conversationId, context))?.taints ?? [];\n const seats = (await harness.snapshot(GuestsDoc, context))?.seats ?? {};\n const found = inputs.length ? await taintsOf(inputs, seats, harness, context) : [];\n return [\n ...found.map((taint) => ({ seat: taint.seat?.id ?? null, tier: taint.tier })),\n ...inherited,\n ];\n}\n\nfunction inheritedTaints(\n inherited: readonly InheritedTaint[],\n seats: Readonly<Record<string, SeatRecord>>\n): Taint[] {\n return inherited.map((taint) => ({\n seat: taint.seat === null ? null : (seats[taint.seat] ?? null),\n tier: taint.tier,\n }));\n}\n\nexport async function taintsOf(\n inputs: readonly SubmissionId[],\n seats: Readonly<Record<string, SeatRecord>>,\n harness: Pick<Harness, 'submission'>,\n context: Context\n): Promise<Taint[]> {\n const found = new Map<string, Taint>();\n for (const id of inputs) {\n const seat = Object.values(seats).find((record) =>\n record.submissions?.some((entry) => entry.id === String(id))\n );\n const tier = seat?.submissions?.find((entry) => entry.id === String(id))?.tools;\n if (seat) {\n found.set(`${seat.id}\\n${tier}`, { seat, tier: String(tier) });\n continue;\n }\n const submission = await harness.submission(id, context);\n const record = submission ? await submission.status(context) : undefined;\n if (record?.requestId?.startsWith(GUEST_REQUEST)) return [{ seat: null, tier: '' }];\n }\n return [...found.values()];\n}\n\nfunction settledEarly(\n seat: SeatRecord,\n tier: string,\n policy: GuestPolicy,\n at: number,\n tool: string,\n hash: string\n): string | null {\n if (!policy.allowedToolGates.includes(gateKind(tier)))\n return gateRefusal(\"a guest's tool calls\", policy.allowedToolGates);\n if (!liveSeat(seat, at)) return GATE_REASONS.ended;\n if (tier === 'off') return '';\n const kept = seat.alwaysTools?.some((rule) => rule.tool === tool && rule.argumentsHash === hash);\n return policy.always.tools && kept ? '' : null;\n}\n\nconst ended = (status: string) => status === 'terminal' || status === 'completing';\n\nexport function guestToolGate(harness: () => Held | undefined): GuestToolGate {\n let resolveHost: (host: GateHost) => void = () => {};\n const bound = new Promise<GateHost>((resolve) => {\n resolveHost = resolve;\n });\n const watched = new Set<string>();\n const watch = (host: GateHost, id: string, task: number) => {\n const held = harness();\n if (!held || watched.has(id)) return;\n watched.add(id);\n void held\n .waitForTask(task as unknown as TaskId, BACKGROUND_CONTEXT)\n .then((record) =>\n ended(record.state.status)\n ? host.approvals.withdraw(id, REASONS.aborted, BACKGROUND_CONTEXT)\n : undefined\n )\n .catch(() => undefined)\n .finally(() => watched.delete(id));\n };\n const remember = (seat: string, rule: AlwaysTool) =>\n (harness() as Held).commit(async (tx) => {\n const record = (await tx.doc(GuestsDoc)).seats[seat];\n if (!record || record.revoked !== null) return;\n const kept = (record.alwaysTools ?? []).filter(\n (entry) => entry.tool !== rule.tool || entry.argumentsHash !== rule.argumentsHash\n );\n record.alwaysTools = [...kept, rule];\n }, BACKGROUND_CONTEXT);\n const review = async (\n taint: Taint,\n call: ToolHookCall,\n api: HookApi,\n context: Context\n ): Promise<string | undefined> => {\n const { seat } = taint;\n if (seat === null || !isGate(taint.tier)) return GATE_REASONS.unknown;\n const host = await awaitWithContext(bound, context);\n const policy = host.policy();\n const now = host.now ?? Date.now;\n const hash = await argumentsHash(canonical(call.arguments));\n const always = policy.always.tools;\n const early = settledEarly(seat, taint.tier, policy, now(), call.name, hash);\n if (early !== null) return early || undefined;\n const id = await api.memo<string>(\n `${GUEST_TOOL_MEMO}:${seat.id}:${taint.tier}`,\n `apr-${crypto.randomUUID()}`,\n context\n );\n const task = Number(api.taskId);\n const shown = await scrubbedArguments(call.arguments);\n const asked = await host.approvals.request(\n {\n id,\n kind: 'guest-tool',\n seat: seat.id,\n agentId: seat.agentId,\n requester: { kind: 'guest', name: seat.label, seat: seat.id },\n tier: taint.tier,\n detail: {\n tool: call.name,\n summary: summaryOf(shown),\n arguments: canonical(shown),\n task,\n },\n },\n BACKGROUND_CONTEXT\n );\n watch(host, id, task);\n const live = async () =>\n liveSeat((await api.snapshot(GuestsDoc, context))?.seats[seat.id], now());\n if (!(await live())) {\n await host.approvals.withdraw(id, REASONS.revoked, BACKGROUND_CONTEXT);\n return GATE_REASONS.ended;\n }\n const item = asked.state === 'pending' ? await host.approvals.settled(id, context) : asked;\n if (item.state !== 'approved') return reasonOf(item);\n if (!(await live())) return GATE_REASONS.ended;\n if (item.answer === 'always' && always)\n await remember(seat.id, {\n approval: item.id,\n tool: call.name,\n argumentsHash: hash,\n arguments: canonical(shown),\n by: item.decidedBy,\n at: item.decidedAt ?? now(),\n });\n return undefined;\n };\n return {\n extension: defineExtension({\n name: GUEST_GUARD,\n hooks: [\n hook(ToolTask, {\n async beforeTool(call, api, context) {\n const live = await api.snapshot(LiveDoc, api.conversationId, context);\n const inputs = live?.run?.inputs ?? [];\n const inherited =\n (await api.snapshot(GuestTaintDoc, api.conversationId, context))?.taints ?? [];\n if (!inputs.length && !inherited.length) return undefined;\n const seats = (await api.snapshot(GuestsDoc, context))?.seats ?? {};\n const held = harness() as Held;\n const found = inputs.length ? await taintsOf(inputs, seats, held, context) : [];\n for (const taint of [...found, ...inheritedTaints(inherited, seats)]) {\n const block = await review(taint, call, api, context);\n if (block) return { block };\n }\n return undefined;\n },\n }),\n ],\n }),\n bind(host) {\n resolveHost(host);\n for (const item of host.approvals.state.value ?? [])\n if (item.kind === 'guest-tool' && item.state === 'pending' && item.detail.task)\n watch(host, item.id, item.detail.task);\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { awaitWithContext, BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport {\n type ConversationId,\n defineDoc,\n defineExtension,\n type Extension,\n type Harness,\n type HookApi,\n hook,\n LiveDoc,\n type SubmissionId,\n type TaskId,\n type ToolHookCall,\n ToolTask,\n} from '@earendil-works/pi-durable';\nimport type { Approval, Approvals } from '../approvals/index.ts';\nimport { REASONS, scoopTier } from '../approvals/record.ts';\nimport { scrubText, scrubTexts } from '../secrets/scrub.ts';\nimport { type GuestPolicy, gateKind, gateRefusal } from './policy.ts';\nimport { type AlwaysTool, GuestsDoc, isGate, liveSeat, type SeatRecord } from './seats.ts';\n\nexport const GUEST_GUARD = 'slicc-guest-guard';\nexport const GUEST_REQUEST = 'guest:';\nexport const GUEST_TOOL_MEMO = 'slicc.guest-tool';\nexport const SUMMARY_LENGTH = 2000;\n\nexport const GATE_REASONS = {\n unknown:\n 'A guest started this run, and its seat names no review for tool calls that this agent knows.',\n ended: \"A guest started this run, and that guest's seat has ended.\",\n rejected: 'The owner declined this tool call in a run a guest started.',\n judged: 'The automatic check declined this tool call in a run a guest started',\n unanswered: 'Nobody approved this tool call in a run a guest started in time.',\n unroutable: \"The cone can't review a tool call it is itself waiting on.\",\n withdrawn: 'The review of this tool call was withdrawn.',\n} as const;\n\nexport interface GateHost {\n approvals: Pick<Approvals, 'state' | 'request' | 'settled' | 'withdraw'>;\n policy(): GuestPolicy;\n now?: () => number;\n}\n\nexport interface GuestToolGate {\n readonly extension: Extension;\n bind(host: GateHost): void;\n}\n\ntype Held = Pick<Harness, 'submission' | 'commit' | 'waitForTask'>;\n\ntype Taint = { seat: SeatRecord | null; tier: string };\n\nexport function canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`;\n if (value && typeof value === 'object')\n return `{${Object.keys(value)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${canonical((value as Record<string, unknown>)[key])}`)\n .join(',')}}`;\n return JSON.stringify(value ?? null);\n}\n\nfunction leaves(value: unknown, found: string[]): void {\n if (typeof value === 'string') found.push(value);\n else if (value && typeof value === 'object')\n for (const item of Object.values(value)) leaves(item, found);\n}\n\nfunction replaced(value: unknown, texts: string[]): unknown {\n if (typeof value === 'string') return texts.shift();\n if (Array.isArray(value)) return value.map((item) => replaced(item, texts));\n if (value && typeof value === 'object')\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, replaced(item, texts)])\n );\n return value;\n}\n\nexport async function scrubbedArguments(\n args: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n const found: string[] = [];\n leaves(args, found);\n return replaced(args, await scrubTexts(found)) as Record<string, unknown>;\n}\n\nexport async function argumentsHash(args: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(args));\n return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nasync function shownArguments(text: string): Promise<string> {\n try {\n return canonical(await scrubbedArguments(JSON.parse(text)));\n } catch {\n return scrubText(text);\n }\n}\n\nexport async function sealedRules(rules: readonly AlwaysTool[]): Promise<AlwaysTool[] | null> {\n if (rules.every((rule) => rule.argumentsHash)) return null;\n return Promise.all(\n rules.map(async (rule) =>\n rule.argumentsHash\n ? rule\n : {\n ...rule,\n argumentsHash: await argumentsHash(rule.arguments),\n arguments: await shownArguments(rule.arguments),\n }\n )\n );\n}\n\nexport function summaryOf(args: Record<string, unknown>): string {\n const values = Object.values(args);\n const text = values.length === 1 && typeof values[0] === 'string' ? values[0] : canonical(args);\n return text.length > SUMMARY_LENGTH ? `${text.slice(0, SUMMARY_LENGTH - 1)}\u2026` : text;\n}\n\nconst SCOOP_SAID: Record<string, (name: string) => string> = {\n [REASONS.noScoop]: (name) => `there is no scoop ${name} in this cone to review it.`,\n [REASONS.scoopStopped]: (name) => `the scoop ${name} is stopped, so it can't review it.`,\n [REASONS.scoopAsked]: (name) =>\n `the scoop ${name} can't review a call that asks something of it.`,\n [REASONS.scoopUndecided]: (name) => `the scoop ${name} ended its review without deciding.`,\n};\n\nfunction scoopReason(item: Approval): string | null {\n const name = item.tier.slice('scoop:'.length);\n if (item.decidedBy?.startsWith('scoop:'))\n return `The scoop ${name} declined this tool call in a run a guest started${item.reason ? `: ${item.reason}` : '.'}`;\n const said = SCOOP_SAID[item.reason ?? ''];\n return said ? `A guest started this run, and ${said(name)}` : null;\n}\n\nexport function reasonOf(item: Approval): string {\n const scooped = item.state === 'rejected' && scoopTier(item.tier) ? scoopReason(item) : null;\n if (scooped) return scooped;\n if (item.state === 'rejected' && item.decidedBy === 'judge')\n return item.verdict\n ? `${GATE_REASONS.judged}: ${item.verdict.reason}`\n : `${GATE_REASONS.judged}.`;\n if (item.state === 'rejected')\n return item.reason && item.reason !== REASONS.unknownAnswer\n ? `${GATE_REASONS.rejected} ${item.reason}`\n : GATE_REASONS.rejected;\n if (item.state === 'withdrawn') return GATE_REASONS.withdrawn;\n if (item.reason === REASONS.unknownTier) return GATE_REASONS.unknown;\n if (item.reason === REASONS.unroutable) return GATE_REASONS.unroutable;\n return GATE_REASONS.unanswered;\n}\n\nexport type InheritedTaint = { seat: string | null; tier: string };\n\nexport const GuestTaintDoc = defineDoc<{ taints: InheritedTaint[] }>({\n kind: 'slicc.guest-taint',\n version: 1,\n scope: 'conversation',\n history: 'rewindable',\n fork: 'asOf',\n initial: () => ({ taints: [] }),\n});\n\ntype TaintReader = Pick<Harness, 'submission' | 'snapshot'>;\n\nexport async function runTaints(\n harness: TaintReader,\n conversationId: ConversationId,\n context: Context\n): Promise<InheritedTaint[]> {\n const live = await harness.snapshot(LiveDoc, conversationId, context);\n const inputs = live?.run?.inputs ?? [];\n const inherited = (await harness.snapshot(GuestTaintDoc, conversationId, context))?.taints ?? [];\n const seats = (await harness.snapshot(GuestsDoc, context))?.seats ?? {};\n const found = inputs.length ? await taintsOf(inputs, seats, harness, context) : [];\n return distinctTaints([\n ...found.map((taint) => ({ seat: taint.seat?.id ?? null, tier: taint.tier })),\n ...inherited,\n ]);\n}\n\nexport function distinctTaints(taints: readonly InheritedTaint[]): InheritedTaint[] {\n const kept = new Map<string, InheritedTaint>();\n for (const taint of taints) kept.set(`${taint.seat}\\n${taint.tier}`, taint);\n return [...kept.values()];\n}\n\nfunction inheritedTaints(\n inherited: readonly InheritedTaint[],\n seats: Readonly<Record<string, SeatRecord>>\n): Taint[] {\n return inherited.map((taint) => ({\n seat: taint.seat === null ? null : (seats[taint.seat] ?? null),\n tier: taint.tier,\n }));\n}\n\nexport async function taintsOf(\n inputs: readonly SubmissionId[],\n seats: Readonly<Record<string, SeatRecord>>,\n harness: Pick<Harness, 'submission'>,\n context: Context\n): Promise<Taint[]> {\n const found = new Map<string, Taint>();\n for (const id of inputs) {\n const seat = Object.values(seats).find((record) =>\n record.submissions?.some((entry) => entry.id === String(id))\n );\n const tier = seat?.submissions?.find((entry) => entry.id === String(id))?.tools;\n if (seat) {\n found.set(`${seat.id}\\n${tier}`, { seat, tier: String(tier) });\n continue;\n }\n const submission = await harness.submission(id, context);\n const record = submission ? await submission.status(context) : undefined;\n if (record?.requestId?.startsWith(GUEST_REQUEST)) return [{ seat: null, tier: '' }];\n }\n return [...found.values()];\n}\n\nfunction settledEarly(\n seat: SeatRecord,\n tier: string,\n policy: GuestPolicy,\n at: number,\n tool: string,\n hash: string\n): string | null {\n if (!policy.allowedToolGates.includes(gateKind(tier)))\n return gateRefusal(\"a guest's tool calls\", policy.allowedToolGates);\n if (!liveSeat(seat, at)) return GATE_REASONS.ended;\n if (tier === 'off') return '';\n const kept = seat.alwaysTools?.some((rule) => rule.tool === tool && rule.argumentsHash === hash);\n return policy.always.tools && kept ? '' : null;\n}\n\nconst ended = (status: string) => status === 'terminal' || status === 'completing';\n\nexport function guestToolGate(harness: () => Held | undefined): GuestToolGate {\n let resolveHost: (host: GateHost) => void = () => {};\n const bound = new Promise<GateHost>((resolve) => {\n resolveHost = resolve;\n });\n const watched = new Set<string>();\n const watch = (host: GateHost, id: string, task: number) => {\n const held = harness();\n if (!held || watched.has(id)) return;\n watched.add(id);\n void held\n .waitForTask(task as unknown as TaskId, BACKGROUND_CONTEXT)\n .then((record) =>\n ended(record.state.status)\n ? host.approvals.withdraw(id, REASONS.aborted, BACKGROUND_CONTEXT)\n : undefined\n )\n .catch(() => undefined)\n .finally(() => watched.delete(id));\n };\n const remember = (seat: string, rule: AlwaysTool) =>\n (harness() as Held).commit(async (tx) => {\n const record = (await tx.doc(GuestsDoc)).seats[seat];\n if (!record || record.revoked !== null) return;\n const kept = (record.alwaysTools ?? []).filter(\n (entry) => entry.tool !== rule.tool || entry.argumentsHash !== rule.argumentsHash\n );\n record.alwaysTools = [...kept, rule];\n }, BACKGROUND_CONTEXT);\n const review = async (\n taint: Taint,\n call: ToolHookCall,\n api: HookApi,\n context: Context\n ): Promise<string | undefined> => {\n const { seat } = taint;\n if (seat === null || !isGate(taint.tier)) return GATE_REASONS.unknown;\n const host = await awaitWithContext(bound, context);\n const policy = host.policy();\n const now = host.now ?? Date.now;\n const hash = await argumentsHash(canonical(call.arguments));\n const always = policy.always.tools;\n const early = settledEarly(seat, taint.tier, policy, now(), call.name, hash);\n if (early !== null) return early || undefined;\n const id = await api.memo<string>(\n `${GUEST_TOOL_MEMO}:${seat.id}:${taint.tier}`,\n `apr-${crypto.randomUUID()}`,\n context\n );\n const task = Number(api.taskId);\n const shown = await scrubbedArguments(call.arguments);\n const asked = await host.approvals.request(\n {\n id,\n kind: 'guest-tool',\n seat: seat.id,\n agentId: seat.agentId,\n requester: { kind: 'guest', name: seat.label, seat: seat.id },\n tier: taint.tier,\n detail: {\n tool: call.name,\n summary: summaryOf(shown),\n arguments: canonical(shown),\n task,\n },\n },\n BACKGROUND_CONTEXT\n );\n watch(host, id, task);\n const live = async () =>\n liveSeat((await api.snapshot(GuestsDoc, context))?.seats[seat.id], now());\n if (!(await live())) {\n await host.approvals.withdraw(id, REASONS.revoked, BACKGROUND_CONTEXT);\n return GATE_REASONS.ended;\n }\n const item = asked.state === 'pending' ? await host.approvals.settled(id, context) : asked;\n if (item.state !== 'approved') return reasonOf(item);\n if (!(await live())) return GATE_REASONS.ended;\n if (item.answer === 'always' && always)\n await remember(seat.id, {\n approval: item.id,\n tool: call.name,\n argumentsHash: hash,\n arguments: canonical(shown),\n by: item.decidedBy,\n at: item.decidedAt ?? now(),\n });\n return undefined;\n };\n return {\n extension: defineExtension({\n name: GUEST_GUARD,\n hooks: [\n hook(ToolTask, {\n async beforeTool(call, api, context) {\n const live = await api.snapshot(LiveDoc, api.conversationId, context);\n const inputs = live?.run?.inputs ?? [];\n const inherited =\n (await api.snapshot(GuestTaintDoc, api.conversationId, context))?.taints ?? [];\n if (!inputs.length && !inherited.length) return undefined;\n const seats = (await api.snapshot(GuestsDoc, context))?.seats ?? {};\n const held = harness() as Held;\n const found = inputs.length ? await taintsOf(inputs, seats, held, context) : [];\n for (const taint of [...found, ...inheritedTaints(inherited, seats)]) {\n const block = await review(taint, call, api, context);\n if (block) return { block };\n }\n return undefined;\n },\n }),\n ],\n }),\n bind(host) {\n resolveHost(host);\n for (const item of host.approvals.state.value ?? [])\n if (item.kind === 'guest-tool' && item.state === 'pending' && item.detail.task)\n watch(host, item.id, item.detail.task);\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["record"]
|
|
7
7
|
}
|
package/dist/scoops/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ import { scopedName } from "../licks/sources.js";
|
|
|
9
9
|
import { findRole } from "../roles/roles.js";
|
|
10
10
|
import { findScoop, modelOf } from "./service.js";
|
|
11
11
|
import { cancelSync, detachSync, runSync } from "./sync.js";
|
|
12
|
+
import { callerTaints } from "./taints.js";
|
|
12
13
|
const DEFAULT_WAIT_S = 30;
|
|
13
14
|
const MAX_DEPTH = 3;
|
|
14
15
|
const RUN_DIR = "/var/lib/slicc/agent/scoops";
|
|
@@ -73,6 +74,9 @@ function claimed(agents, caller) {
|
|
|
73
74
|
}
|
|
74
75
|
class CallerError extends Error {
|
|
75
76
|
}
|
|
77
|
+
function taintsOf(deps, request, who, context) {
|
|
78
|
+
return callerTaints(deps.harness, deps.agents.state(), who, request.caller, context);
|
|
79
|
+
}
|
|
76
80
|
function callerOf(agents, request) {
|
|
77
81
|
const user = request.user;
|
|
78
82
|
if (!user || user === ROOT_USER)
|
|
@@ -192,6 +196,7 @@ async function spawnAsync(deps, request, who, argv, context) {
|
|
|
192
196
|
if (isAnswer(chosen)) return chosen;
|
|
193
197
|
const found = await role(deps, parsed);
|
|
194
198
|
if (found.error) return found.error;
|
|
199
|
+
const taints = await taintsOf(deps, request, who, context);
|
|
195
200
|
return deps.scoops.spawn(
|
|
196
201
|
{
|
|
197
202
|
cone: who.cone,
|
|
@@ -205,7 +210,8 @@ async function spawnAsync(deps, request, who, argv, context) {
|
|
|
205
210
|
origin: request.cwd,
|
|
206
211
|
fromAgent: who.fromAgent,
|
|
207
212
|
request: request.id,
|
|
208
|
-
limits: found.roles.limits
|
|
213
|
+
limits: found.roles.limits,
|
|
214
|
+
taints
|
|
209
215
|
},
|
|
210
216
|
context
|
|
211
217
|
);
|
|
@@ -274,10 +280,11 @@ async function send(deps, request, who, context) {
|
|
|
274
280
|
const refused = await reviewing(deps, who, found, context);
|
|
275
281
|
if (refused) return refused;
|
|
276
282
|
const followUp = parsed.switches.has("--follow-up");
|
|
283
|
+
const taints = await taintsOf(deps, request, who, context);
|
|
277
284
|
return deps.scoops.feed(
|
|
278
285
|
found[0],
|
|
279
286
|
text,
|
|
280
|
-
{ fromAgent: who.fromAgent, request: request.id, followUp, target: who.id },
|
|
287
|
+
{ fromAgent: who.fromAgent, request: request.id, followUp, target: who.id, taints },
|
|
281
288
|
context
|
|
282
289
|
);
|
|
283
290
|
}
|
|
@@ -443,7 +450,12 @@ const VERBS = {
|
|
|
443
450
|
wait,
|
|
444
451
|
stop,
|
|
445
452
|
rename,
|
|
446
|
-
workflow: (deps, request, who, context) => deps.workflow ? deps.workflow(
|
|
453
|
+
workflow: async (deps, request, who, context) => deps.workflow ? deps.workflow(
|
|
454
|
+
request.argv.slice(1),
|
|
455
|
+
{ ...who, taints: await taintsOf(deps, request, who, context) },
|
|
456
|
+
request,
|
|
457
|
+
context
|
|
458
|
+
) : fail("workflows are not available in this agent"),
|
|
447
459
|
help,
|
|
448
460
|
"--help": help,
|
|
449
461
|
"-h": help,
|
|
@@ -546,6 +558,7 @@ export {
|
|
|
546
558
|
prompts,
|
|
547
559
|
readText,
|
|
548
560
|
role,
|
|
561
|
+
taintsOf,
|
|
549
562
|
unsupported
|
|
550
563
|
};
|
|
551
564
|
//# sourceMappingURL=cli.js.map
|
package/dist/scoops/cli.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/scoops/cli.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Harness } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { Agents, AgentsState } from '../agents.ts';\nimport { reviewersOf } from '../guests/scoop.ts';\nimport { CONE_PREFIX } from '../kernel/accounts.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport { agentOfUser, type Layout, LEGACY, ROOT_USER } from '../layout.ts';\nimport { cronLick } from '../licks/crontab.ts';\nimport { webhookDelivery } from '../licks/events.ts';\nimport { LICK_CHANNELS, type LickTarget } from '../licks/lick.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { scopedName, type WebhookDelivery } from '../licks/sources.ts';\nimport { findRole, type Roles } from '../roles/roles.ts';\nimport type { Request, Runner } from './requests.ts';\nimport { type Answer, findScoop, modelOf, type Scoops } from './service.ts';\nimport { cancelSync, detachSync, runSync, type SyncState } from './sync.ts';\n\nexport const DEFAULT_WAIT_S = 30;\nexport const MAX_DEPTH = 3;\nexport const RUN_DIR = '/var/lib/slicc/agent/scoops';\n\nexport const THINKING = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\nconst EFFORT: Record<string, string> = { low: 'low', medium: 'medium', high: 'high', max: 'xhigh' };\n\nexport const USAGE = `usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send <target> --lick=<cron|webhook> [--source <name>] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\n agent workflow run|list|status|stop|save ... Claude Code workflows; agent workflow help\n\noptions:\n --name <name> --agent <role> --model <provider/model> --thinking <level> | --effort <low|medium|high|max>\n --tools <a,b> --read-only <path,path> --system-prompt <text> | --system-prompt-file <path>\n --background-after <seconds> --persist-session | --no-persist-session\n\nA synchronous run removes the scoop's folder afterwards. Its transcript is archived in\n/tmp/agent-sessions/<handle>.md, in /home/sessions/<handle>.md with --persist-session, or nowhere\nwith --no-persist-session. subagent is the same command: subagent spawn = agent --async.\n`;\n\nexport interface CliOptions {\n env: ExecutionEnv;\n harness: Harness;\n agents: Agents;\n scoops: Scoops;\n roles: () => Promise<Roles>;\n alive?: (pid: number) => Promise<boolean>;\n now?: () => number;\n memory?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n gelatiere?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n freezer?: (\n argv: readonly string[],\n caller: string | null,\n context: Context,\n asker?: { user: string | null; cwd: string }\n ) => Promise<Answer>;\n models?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n layout?: Layout;\n panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => Promise<Answer>;\n licks?: Pick<Licks, 'deliver'>;\n webhook?: (name: string, delivery: WebhookDelivery, context: Context) => Promise<boolean>;\n workflow?: (\n argv: readonly string[],\n who: Caller,\n request: Request,\n context: Context\n ) => Promise<Answer>;\n}\n\nexport interface PanelCaller {\n agentId: string | null;\n cone: string;\n tab: string | null;\n}\n\nexport type Deps = CliOptions & { now: () => number; sync: SyncState; layout: Layout };\n\nexport interface Caller {\n id: string | null;\n cone: string;\n fromAgent: boolean;\n scoop: string | null;\n depth: number;\n}\n\nexport type Flags = { values: Map<string, string[]>; switches: Set<string>; rest: string[] };\n\nexport const ok = (out: string): Answer => ({ code: 0, out });\nexport const fail = (out: string, code = 1): Answer => ({ code, out: `agent: ${out}\\n` });\n\nexport function isAnswer(value: unknown): value is Answer {\n return typeof value === 'object' && value !== null && 'code' in value && 'out' in value;\n}\n\nexport function flags(argv: readonly string[], withValue: readonly string[]): Flags {\n const values = new Map<string, string[]>();\n const switches = new Set<string>();\n const rest: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at] as string;\n if (withValue.includes(arg)) {\n const value = argv[at + 1];\n if (value === undefined) throw new Error(`${arg} needs a value`);\n values.set(arg, [...(values.get(arg) ?? []), value]);\n at++;\n } else if (arg.startsWith('--')) switches.add(arg);\n else rest.push(arg);\n }\n return { values, switches, rest };\n}\n\nexport function last(parsed: Flags, flag: string): string | undefined {\n return parsed.values.get(flag)?.at(-1);\n}\n\nfunction claimed(agents: Agents, caller: string): Caller | undefined {\n const state = agents.state();\n if (caller.startsWith('cone:') && state.cones[caller.slice(5)]) {\n const cone = caller.slice(5);\n return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };\n }\n const record = caller.startsWith('scoop:') ? state.scoops[caller] : undefined;\n if (record)\n return { id: caller, cone: record.cone, fromAgent: true, scoop: caller, depth: record.depth };\n return undefined;\n}\n\nexport class CallerError extends Error {}\n\nexport function callerOf(agents: Agents, request: Request): Caller {\n const user = request.user;\n if (!user || user === ROOT_USER)\n return (\n claimed(agents, request.caller) ?? {\n id: null,\n cone: agents.activeCone(),\n fromAgent: false,\n scoop: null,\n depth: 0,\n }\n );\n const own = agentOfUser(agents.state(), user);\n if (request.caller && request.caller !== own)\n throw new CallerError(`SLICC_AGENT says ${request.caller}, but you are ${user}`);\n const found = own ? claimed(agents, own) : undefined;\n if (!found) throw new CallerError(`${user} is no cone or live scoop`);\n return found;\n}\n\nexport async function readText(\n deps: Deps,\n value: string,\n request: Request,\n context: Context\n): Promise<string> {\n const env = (await deps.layout.envFor(request.user ?? null, context)) ?? deps.env;\n const read = await env.readTextFile(resolve(request.cwd, value), context);\n if (!read.ok) throw new Error(`can't read ${value}: ${read.error.message}`);\n return read.value;\n}\n\nexport async function prompts(\n deps: Deps,\n argv: readonly string[],\n request: Request,\n context: Context\n) {\n const out: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at];\n if (arg === '--prompt') out.push(argv[++at] ?? '');\n else if (arg === '--file') out.push(await readText(deps, argv[++at] ?? '', request, context));\n else if (arg === '-') out.push(request.stdin);\n }\n return out.filter((prompt) => prompt.trim());\n}\n\nexport type Choice = {\n model?: { provider: string; modelId: string };\n thinking?: string;\n tools?: string[];\n};\n\nfunction toolList(listed: string | undefined): string[] | undefined {\n if (listed === undefined || listed === 'auto' || listed === 'full') return undefined;\n return listed\n .split(',')\n .map((tool) => tool.trim())\n .filter(Boolean);\n}\n\nexport function choices(parsed: Flags): Choice | Answer {\n const provider = last(parsed, '--provider');\n const modelText = last(parsed, '--model');\n const model = modelText\n ? provider\n ? { provider, modelId: modelText }\n : modelOf(modelText)\n : undefined;\n if (modelText && !model)\n return fail('--model needs provider/model, or --provider with --model', 2);\n const effort = last(parsed, '--effort');\n if (effort && !EFFORT[effort]) return fail('--effort must be low, medium, high or max', 2);\n const thinking = last(parsed, '--thinking') ?? (effort ? EFFORT[effort] : undefined);\n if (thinking && !THINKING.has(thinking))\n return fail(`--thinking must be one of ${[...THINKING].join(', ')}`, 2);\n if (last(parsed, '--tools') === 'output')\n return fail('--tools output needs --schema-b64, which is not supported in SLICC yet', 2);\n const tools = toolList(last(parsed, '--tools'));\n return {\n ...(model ? { model } : {}),\n ...(thinking ? { thinking } : {}),\n ...(tools ? { tools } : {}),\n };\n}\n\nexport async function role(deps: Deps, parsed: Flags) {\n const roles = await deps.roles();\n const name = last(parsed, '--agent');\n const found = name ? findRole(roles.roles, name) : undefined;\n if (name && !found)\n return {\n roles,\n error: fail(`there is no agent role ${name}; \\`agent list --agents\\` shows them`),\n };\n return { roles, role: found };\n}\n\nfunction handle(deps: Deps, who: Caller, name: string | undefined) {\n return name ? findScoop(deps.agents.state(), name, who.fromAgent ? who.cone : null) : undefined;\n}\n\nasync function reviewing(\n deps: Deps,\n who: Caller,\n [id, record]: [string, { name: string }],\n context: Context\n) {\n if (!who.fromAgent || who.scoop) return undefined;\n const reviewers = await reviewersOf(deps.harness, deps.agents.state(), who.cone, context);\n if (!reviewers.includes(id)) return undefined;\n return fail(\n `the scoop ${record.name} reviews this guest run's requests, so this run can't ask anything of it`\n );\n}\n\nconst ASYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n];\nconst ASYNC_SWITCHES = new Set(['--async', '--no-extensions', '--no-skills', '--no-context-files']);\nconst UNSUPPORTED = new Set([\n '--no-prompt-templates',\n '--session',\n '--resume',\n '--image',\n '--no-escalate',\n '--minimal',\n '--usage',\n '--schema-b64',\n '--cwd',\n]);\n\nexport function unsupported(argv: readonly string[]): Answer | undefined {\n const found = argv.find((arg) => UNSUPPORTED.has(arg) || arg.startsWith('--image='));\n return found ? fail(`${found} is not supported in SLICC yet`, 2) : undefined;\n}\n\nasync function spawnAsync(\n deps: Deps,\n request: Request,\n who: Caller,\n argv: readonly string[],\n context: Context\n) {\n if (who.scoop) return fail('a scoop cannot start async scoops; run agent without --async');\n const refused = unsupported(argv);\n if (refused) return refused;\n const parsed = flags(argv, ASYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !ASYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const given = await prompts(deps, argv, request, context);\n if (!given.length) return fail('--async needs at least one --prompt, --file or -', 2);\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n return deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'async',\n name: last(parsed, '--name') ?? found.role?.name ?? 'scoop',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n}\n\nasync function listAgents(deps: Deps): Promise<Answer> {\n const roles = await deps.roles();\n const lines = roles.roles.map(\n (entry) =>\n `${entry.name}\\t${entry.source}\\t${entry.description}${entry.aliases.length ? ` (also ${entry.aliases.join(', ')})` : ''}`\n );\n return ok(\n `${[\n ...lines,\n '',\n 'Agent files are read from the built-in roles, installed packages (pi-subagents.agents) and ~/.pi/agent/agents.',\n \"A project's .pi/agents folder is read only once the folder is trusted, which SLICC doesn't support yet.\",\n ...roles.warnings.map((warning) => `warning: ${warning}`),\n ].join('\\n')}\\n`\n );\n}\n\nasync function list(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (request.argv.includes('--agents')) return listAgents(deps);\n const rows = await deps.scoops.list(who.cone, context);\n if (!rows.length) return ok('no scoops\\n');\n return ok(\n `${rows.map((row) => `${row.folder}\\t${row.name}\\t${row.role ?? '-'}\\t${row.busy ? 'working' : 'idle'}`).join('\\n')}\\n`\n );\n}\n\nasync function status(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const [, record] = found;\n const busy = await deps.scoops.busy(record.conversation, context);\n return ok(\n `${[\n `handle: ${record.folder}`,\n `name: ${record.name}`,\n `role: ${record.role ?? '-'}`,\n `kind: ${record.kind}`,\n `state: ${busy ? 'working' : 'idle'}`,\n `folder: ${deps.layout.scoopRoot(record.folder)}`,\n `reports: ${deps.layout.reports(record.folder, record.cone)}`,\n ].join('\\n')}\\n`\n );\n}\n\nasync function message(\n deps: Deps,\n parsed: Flags,\n request: Request,\n context: Context\n): Promise<string> {\n const file = last(parsed, '--file');\n if (file) return readText(deps, file, request, context);\n return parsed.rest.includes('-') ? request.stdin : parsed.rest.join(' ');\n}\n\nasync function send(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(2), ['--file']);\n const unknown = [...parsed.switches].find((flag) => flag !== '--follow-up');\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const text = await message(deps, parsed, request, context);\n if (!text.trim()) return fail('send needs a message, --file or -', 2);\n if (request.argv[1] === 'parent') {\n if (!who.scoop) return fail('only a scoop has a parent to send to');\n return deps.scoops.note(who.scoop, text, context);\n }\n if (who.scoop) return fail('a scoop can only send to its parent');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n const followUp = parsed.switches.has('--follow-up');\n return deps.scoops.feed(\n found[0],\n text,\n { fromAgent: who.fromAgent, request: request.id, followUp, target: who.id },\n context\n );\n}\n\nfunction cronTarget(deps: Deps, request: Request, name: string): LickTarget | Answer {\n const state = deps.agents.state();\n if (!name) return fail('send needs cone or a scoop handle', 2);\n const user = request.user && request.user !== ROOT_USER ? request.user : undefined;\n const own = user ? agentOfUser(state, user) : undefined;\n if (user && !own) return fail(`${user} is no cone or scoop`);\n if (own?.startsWith('scoop:')) {\n const record = state.scoops[own] as { name: string };\n const mine = [own, own.slice('scoop:'.length), record.name].includes(name);\n return mine\n ? (own as LickTarget)\n : fail(\"a scoop's cron job can only send to the scoop itself\");\n }\n const cone = own ? own.slice(CONE_PREFIX.length) : null;\n const home: LickTarget = cone ? `cone:${cone}` : 'cone';\n if (name === 'cone') return home;\n return (findScoop(state, name, cone)?.[0] as LickTarget | undefined) ?? home;\n}\n\nconst PROCESS_LICKS = ['cron', 'webhook'];\n\nfunction expanded(argv: readonly string[]): string[] {\n return argv.flatMap((arg) => {\n const at = arg.indexOf('=');\n const name = arg.slice(0, at);\n return at > 0 && (name === '--lick' || name === '--source') ? [name, arg.slice(at + 1)] : [arg];\n });\n}\n\nfunction refusedChannel(channel: string): Answer {\n const own = (LICK_CHANNELS as readonly string[]).includes(channel);\n const what = own\n ? `--lick=${channel} is the agent's own channel`\n : `there is no lick channel \"${channel}\"`;\n return fail(\n `${what}; a process may send ${PROCESS_LICKS.map((name) => `--lick=${name}`).join(' or ')}`,\n 2\n );\n}\n\nasync function cronSend(\n deps: Deps,\n licks: Pick<Licks, 'deliver'>,\n request: Request,\n parsed: Flags,\n context: Context\n): Promise<Answer> {\n if (!request.cron)\n return fail('--lick=cron only works inside a cron job, which sets SLICC_CRON_JOB');\n if (last(parsed, '--source') !== undefined)\n return fail(\"--source is for --lick=webhook; a cron lick is named by its job's # name:\", 2);\n const target = cronTarget(deps, request, parsed.rest[0] ?? '');\n if (isAnswer(target)) return target;\n const text = (await message(deps, unnamed(parsed), request, context)).trim();\n await licks.deliver(cronLick(request.cron, target, text), context);\n return ok('');\n}\n\nfunction webhookScope(deps: Deps, request: Request): string | null | Answer {\n const user = request.user && request.user !== ROOT_USER ? request.user : undefined;\n if (!user) return null;\n const own = agentOfUser(deps.agents.state(), user);\n if (!own) return fail(`${user} is no cone or scoop`);\n if (own.startsWith('scoop:')) return fail(\"a scoop can't send webhook licks; its cone can\");\n return own.slice(CONE_PREFIX.length);\n}\n\nasync function webhookSend(\n deps: Deps,\n request: Request,\n parsed: Flags,\n context: Context\n): Promise<Answer> {\n if (!deps.webhook) return fail('webhooks are not available in this agent');\n const source = last(parsed, '--source');\n if (!source)\n return fail('--lick=webhook needs --source <name>, for ~/.slicc/webhooks/<name>.json', 2);\n if (parsed.rest[0] !== 'cone')\n return fail('a webhook lick goes to the cone: agent send cone --lick=webhook \u2026', 2);\n const scope = webhookScope(deps, request);\n if (isAnswer(scope)) return scope;\n const text = await message(deps, unnamed(parsed), request, context);\n if (!text.trim()) return fail('send needs a message, --file or -', 2);\n const delivered = await deps.webhook(\n scopedName(source, scope),\n webhookDelivery(text.trimEnd()),\n context\n );\n return delivered\n ? ok('')\n : fail(`there is no webhook ${source}; add ~/.slicc/webhooks/${source}.json`);\n}\n\nfunction unnamed(parsed: Flags): Flags {\n return { ...parsed, rest: parsed.rest.slice(1) };\n}\n\nasync function lickSend(deps: Deps, request: Request, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(1), ['--file', '--lick', '--source']);\n const unknown = [...parsed.switches][0];\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const channel = last(parsed, '--lick') ?? '';\n if (!PROCESS_LICKS.includes(channel)) return refusedChannel(channel);\n if (!deps.licks) return fail('licks are not available in this agent');\n return channel === 'cron'\n ? cronSend(deps, deps.licks, request, parsed, context)\n : webhookSend(deps, request, parsed, context);\n}\n\nasync function latest(\n deps: Deps,\n record: { folder: string; cone: string },\n context: Context\n): Promise<string> {\n const dir = deps.layout.reports(record.folder, record.cone);\n const listed = await deps.env.listDir(dir, context);\n if (!listed.ok || !listed.value.length) return '(no answer yet)';\n const newest = [...listed.value].sort(\n (a, b) => Number.parseInt(b.name, 10) - Number.parseInt(a.name, 10)\n )[0];\n const read = await deps.env.readTextFile(`${dir}/${newest?.name}`, context);\n return read.ok ? read.value.trimEnd() : '(no answer yet)';\n}\n\nfunction waitTargets(deps: Deps, who: Caller, rest: readonly string[]): string[] | Answer {\n if (!rest.length) return fail('wait needs at least one handle', 2);\n const missing = rest.filter((name) => !handle(deps, who, name));\n if (missing.length)\n return fail(missing.map((name) => noScoop(deps.agents.state(), name)).join('; '));\n return rest.map((name) => (handle(deps, who, name) as [string, unknown])[0]);\n}\n\nasync function block(\n deps: Deps,\n ids: string[],\n seconds: number,\n context: Context\n): Promise<Answer> {\n const deadline = deps.now() + seconds * 1000;\n let open = await deps.scoops.working(ids, context);\n while (open.length && deps.now() < deadline) {\n await new Promise((done) => setTimeout(done, 200));\n open = await deps.scoops.working(ids, context);\n }\n const state = deps.agents.state();\n const sections: string[] = [];\n for (const id of ids) {\n const record = state.scoops[id];\n if (record)\n sections.push(\n `## ${record.folder}${open.includes(id) ? ' (still working)' : ''}\\n${await latest(deps, record, context)}`\n );\n }\n const body = `${sections.join('\\n\\n')}\\n`;\n if (!open.length) return ok(body);\n const still = open.map((id) => state.scoops[id]?.folder).join(', ');\n return { code: 1, out: `${body}agent: timed out after ${seconds}s; still working: ${still}\\n` };\n}\n\nasync function wait(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(1), ['--timeout']);\n const unknown = [...parsed.switches].find((flag) => flag !== '--notify');\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const seconds = Number(last(parsed, '--timeout') ?? DEFAULT_WAIT_S);\n if (!Number.isInteger(seconds) || seconds <= 0)\n return fail('--timeout must be a positive whole number of seconds', 2);\n const ids = waitTargets(deps, who, parsed.rest);\n if (isAnswer(ids)) return ids;\n if (!parsed.switches.has('--notify')) return block(deps, ids, seconds, context);\n if (!who.fromAgent || who.scoop)\n return fail('wait --notify is for a cone; a terminal waits with agent wait');\n await deps.scoops.notifyWhenDone(who.cone, ids, deps.now() + seconds * 1000, context);\n return ok(`you'll get one scoop-wait lick when ${ids.length > 1 ? 'they are' : 'it is'} done\\n`);\n}\n\nasync function stop(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot stop scoops');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n return deps.scoops.stop(found[0], who.fromAgent, context);\n}\n\nasync function rename(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot rename scoops');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n return deps.scoops.rename(found[0], request.argv.slice(2).join(' '), context);\n}\n\ntype Verb = (deps: Deps, request: Request, who: Caller, context: Context) => Promise<Answer>;\n\nconst help: Verb = async () => ok(USAGE);\n\nconst VERBS: Record<string, Verb> = {\n list,\n status,\n send,\n wait,\n stop,\n rename,\n workflow: (deps, request, who, context) =>\n deps.workflow\n ? deps.workflow(request.argv.slice(1), who, request, context)\n : Promise.resolve(fail('workflows are not available in this agent')),\n help,\n '--help': help,\n '-h': help,\n __cancel: (deps, request, _who, context) => cancelSync(deps, request.argv[1] ?? '', context),\n __detach: (deps, request, _who, context) => detachSync(deps, request.argv[1] ?? '', context),\n};\n\nexport function noScoop(state: Readonly<AgentsState>, name: string): string {\n const id = name.startsWith('scoop:') ? name : `scoop:${name}`;\n const record =\n state.scoops[id]?.frozen !== undefined\n ? state.scoops[id]\n : Object.values(state.scoops).find(\n (candidate) => candidate.frozen && candidate.name === name\n );\n const frozen = record?.frozen ? state.frozen?.[record.frozen] : undefined;\n if (frozen) return `scoop ${name} is frozen with cone ${frozen.name}; thaw the cone first`;\n return `there is no scoop ${name}`.trim();\n}\n\nexport function panelCaller(request: Request, who: Caller): PanelCaller {\n const agentId = who.scoop ?? (who.fromAgent ? who.cone : null);\n return { agentId, cone: who.cone, tab: agentId === null ? (request.tab ?? null) : null };\n}\n\nasync function dispatch(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n if (request.as === 'panel')\n return deps.panel\n ? deps.panel(request.argv, panelCaller(request, who), context)\n : { code: 1, out: 'panel: panels are not available in this agent\\n' };\n if (request.as === 'memory')\n return deps.memory\n ? deps.memory(request.argv, who.id, context)\n : fail('memory is not available in this agent');\n if (request.as === 'gelatiere')\n return deps.gelatiere\n ? deps.gelatiere(request.argv, who.id, context)\n : fail('the gelatiere is not available in this agent');\n if (request.as === 'freezer')\n return deps.freezer\n ? deps.freezer(request.argv, who.id, context, {\n user: request.user ?? null,\n cwd: request.cwd,\n })\n : fail('the freezer is not available in this agent');\n if (request.as === 'models')\n return deps.models\n ? deps.models(request.argv, who.id, context)\n : fail('models is not available in this agent');\n const first = request.argv[0] ?? '';\n const verb = VERBS[first];\n if (verb) return verb(deps, request, who, context);\n if (request.as === 'subagent') {\n if (first === 'spawn') return spawnAsync(deps, request, who, request.argv.slice(1), context);\n return { code: 2, out: USAGE };\n }\n if (!request.argv.length) return { code: 2, out: USAGE };\n if (request.argv.includes('--async'))\n return spawnAsync(deps, request, who, request.argv, context);\n return runSync(deps, request, who, context);\n}\n\nconst BLOCKING = new Set([\n 'wait',\n 'workflow',\n 'list',\n 'status',\n 'help',\n '--help',\n '-h',\n '__cancel',\n '__detach',\n]);\n\nexport function createCli(options: CliOptions): Runner {\n const deps: Deps = {\n ...options,\n now: options.now ?? Date.now,\n sync: { pending: new Map() },\n layout: options.layout ?? LEGACY,\n };\n return {\n blocking(request) {\n if (request.as === 'panel') return true;\n const first = request.argv[0] ?? '';\n if (BLOCKING.has(first)) return true;\n return request.as === 'agent' && !VERBS[first] && !request.argv.includes('--async');\n },\n async run(request, context) {\n try {\n const argv = expanded(request.argv);\n if (request.as === 'agent' && argv[0] === 'send' && argv.includes('--lick'))\n return await lickSend(deps, { ...request, argv }, context);\n return await dispatch(deps, request, callerOf(options.agents, request), context);\n } catch (error) {\n return fail((error as Error).message);\n }\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Harness } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { Agents, AgentsState } from '../agents.ts';\nimport type { InheritedTaint } from '../guests/guard.ts';\nimport { reviewersOf } from '../guests/scoop.ts';\nimport { CONE_PREFIX } from '../kernel/accounts.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport { agentOfUser, type Layout, LEGACY, ROOT_USER } from '../layout.ts';\nimport { cronLick } from '../licks/crontab.ts';\nimport { webhookDelivery } from '../licks/events.ts';\nimport { LICK_CHANNELS, type LickTarget } from '../licks/lick.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { scopedName, type WebhookDelivery } from '../licks/sources.ts';\nimport { findRole, type Roles } from '../roles/roles.ts';\nimport type { Request, Runner } from './requests.ts';\nimport { type Answer, findScoop, modelOf, type Scoops } from './service.ts';\nimport { cancelSync, detachSync, runSync, type SyncState } from './sync.ts';\nimport { callerTaints } from './taints.ts';\n\nexport const DEFAULT_WAIT_S = 30;\nexport const MAX_DEPTH = 3;\nexport const RUN_DIR = '/var/lib/slicc/agent/scoops';\n\nexport const THINKING = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\nconst EFFORT: Record<string, string> = { low: 'low', medium: 'medium', high: 'high', max: 'xhigh' };\n\nexport const USAGE = `usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send <target> --lick=<cron|webhook> [--source <name>] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\n agent workflow run|list|status|stop|save ... Claude Code workflows; agent workflow help\n\noptions:\n --name <name> --agent <role> --model <provider/model> --thinking <level> | --effort <low|medium|high|max>\n --tools <a,b> --read-only <path,path> --system-prompt <text> | --system-prompt-file <path>\n --background-after <seconds> --persist-session | --no-persist-session\n\nA synchronous run removes the scoop's folder afterwards. Its transcript is archived in\n/tmp/agent-sessions/<handle>.md, in /home/sessions/<handle>.md with --persist-session, or nowhere\nwith --no-persist-session. subagent is the same command: subagent spawn = agent --async.\n`;\n\nexport interface CliOptions {\n env: ExecutionEnv;\n harness: Harness;\n agents: Agents;\n scoops: Scoops;\n roles: () => Promise<Roles>;\n alive?: (pid: number) => Promise<boolean>;\n now?: () => number;\n memory?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n gelatiere?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n freezer?: (\n argv: readonly string[],\n caller: string | null,\n context: Context,\n asker?: { user: string | null; cwd: string }\n ) => Promise<Answer>;\n models?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n layout?: Layout;\n panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => Promise<Answer>;\n licks?: Pick<Licks, 'deliver'>;\n webhook?: (name: string, delivery: WebhookDelivery, context: Context) => Promise<boolean>;\n workflow?: (\n argv: readonly string[],\n who: Caller & { taints: InheritedTaint[] },\n request: Request,\n context: Context\n ) => Promise<Answer>;\n}\n\nexport interface PanelCaller {\n agentId: string | null;\n cone: string;\n tab: string | null;\n}\n\nexport type Deps = CliOptions & { now: () => number; sync: SyncState; layout: Layout };\n\nexport interface Caller {\n id: string | null;\n cone: string;\n fromAgent: boolean;\n scoop: string | null;\n depth: number;\n}\n\nexport type Flags = { values: Map<string, string[]>; switches: Set<string>; rest: string[] };\n\nexport const ok = (out: string): Answer => ({ code: 0, out });\nexport const fail = (out: string, code = 1): Answer => ({ code, out: `agent: ${out}\\n` });\n\nexport function isAnswer(value: unknown): value is Answer {\n return typeof value === 'object' && value !== null && 'code' in value && 'out' in value;\n}\n\nexport function flags(argv: readonly string[], withValue: readonly string[]): Flags {\n const values = new Map<string, string[]>();\n const switches = new Set<string>();\n const rest: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at] as string;\n if (withValue.includes(arg)) {\n const value = argv[at + 1];\n if (value === undefined) throw new Error(`${arg} needs a value`);\n values.set(arg, [...(values.get(arg) ?? []), value]);\n at++;\n } else if (arg.startsWith('--')) switches.add(arg);\n else rest.push(arg);\n }\n return { values, switches, rest };\n}\n\nexport function last(parsed: Flags, flag: string): string | undefined {\n return parsed.values.get(flag)?.at(-1);\n}\n\nfunction claimed(agents: Agents, caller: string): Caller | undefined {\n const state = agents.state();\n if (caller.startsWith('cone:') && state.cones[caller.slice(5)]) {\n const cone = caller.slice(5);\n return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };\n }\n const record = caller.startsWith('scoop:') ? state.scoops[caller] : undefined;\n if (record)\n return { id: caller, cone: record.cone, fromAgent: true, scoop: caller, depth: record.depth };\n return undefined;\n}\n\nexport class CallerError extends Error {}\n\nexport function taintsOf(deps: Deps, request: Request, who: Caller, context: Context) {\n return callerTaints(deps.harness, deps.agents.state(), who, request.caller, context);\n}\n\nexport function callerOf(agents: Agents, request: Request): Caller {\n const user = request.user;\n if (!user || user === ROOT_USER)\n return (\n claimed(agents, request.caller) ?? {\n id: null,\n cone: agents.activeCone(),\n fromAgent: false,\n scoop: null,\n depth: 0,\n }\n );\n const own = agentOfUser(agents.state(), user);\n if (request.caller && request.caller !== own)\n throw new CallerError(`SLICC_AGENT says ${request.caller}, but you are ${user}`);\n const found = own ? claimed(agents, own) : undefined;\n if (!found) throw new CallerError(`${user} is no cone or live scoop`);\n return found;\n}\n\nexport async function readText(\n deps: Deps,\n value: string,\n request: Request,\n context: Context\n): Promise<string> {\n const env = (await deps.layout.envFor(request.user ?? null, context)) ?? deps.env;\n const read = await env.readTextFile(resolve(request.cwd, value), context);\n if (!read.ok) throw new Error(`can't read ${value}: ${read.error.message}`);\n return read.value;\n}\n\nexport async function prompts(\n deps: Deps,\n argv: readonly string[],\n request: Request,\n context: Context\n) {\n const out: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at];\n if (arg === '--prompt') out.push(argv[++at] ?? '');\n else if (arg === '--file') out.push(await readText(deps, argv[++at] ?? '', request, context));\n else if (arg === '-') out.push(request.stdin);\n }\n return out.filter((prompt) => prompt.trim());\n}\n\nexport type Choice = {\n model?: { provider: string; modelId: string };\n thinking?: string;\n tools?: string[];\n};\n\nfunction toolList(listed: string | undefined): string[] | undefined {\n if (listed === undefined || listed === 'auto' || listed === 'full') return undefined;\n return listed\n .split(',')\n .map((tool) => tool.trim())\n .filter(Boolean);\n}\n\nexport function choices(parsed: Flags): Choice | Answer {\n const provider = last(parsed, '--provider');\n const modelText = last(parsed, '--model');\n const model = modelText\n ? provider\n ? { provider, modelId: modelText }\n : modelOf(modelText)\n : undefined;\n if (modelText && !model)\n return fail('--model needs provider/model, or --provider with --model', 2);\n const effort = last(parsed, '--effort');\n if (effort && !EFFORT[effort]) return fail('--effort must be low, medium, high or max', 2);\n const thinking = last(parsed, '--thinking') ?? (effort ? EFFORT[effort] : undefined);\n if (thinking && !THINKING.has(thinking))\n return fail(`--thinking must be one of ${[...THINKING].join(', ')}`, 2);\n if (last(parsed, '--tools') === 'output')\n return fail('--tools output needs --schema-b64, which is not supported in SLICC yet', 2);\n const tools = toolList(last(parsed, '--tools'));\n return {\n ...(model ? { model } : {}),\n ...(thinking ? { thinking } : {}),\n ...(tools ? { tools } : {}),\n };\n}\n\nexport async function role(deps: Deps, parsed: Flags) {\n const roles = await deps.roles();\n const name = last(parsed, '--agent');\n const found = name ? findRole(roles.roles, name) : undefined;\n if (name && !found)\n return {\n roles,\n error: fail(`there is no agent role ${name}; \\`agent list --agents\\` shows them`),\n };\n return { roles, role: found };\n}\n\nfunction handle(deps: Deps, who: Caller, name: string | undefined) {\n return name ? findScoop(deps.agents.state(), name, who.fromAgent ? who.cone : null) : undefined;\n}\n\nasync function reviewing(\n deps: Deps,\n who: Caller,\n [id, record]: [string, { name: string }],\n context: Context\n) {\n if (!who.fromAgent || who.scoop) return undefined;\n const reviewers = await reviewersOf(deps.harness, deps.agents.state(), who.cone, context);\n if (!reviewers.includes(id)) return undefined;\n return fail(\n `the scoop ${record.name} reviews this guest run's requests, so this run can't ask anything of it`\n );\n}\n\nconst ASYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n];\nconst ASYNC_SWITCHES = new Set(['--async', '--no-extensions', '--no-skills', '--no-context-files']);\nconst UNSUPPORTED = new Set([\n '--no-prompt-templates',\n '--session',\n '--resume',\n '--image',\n '--no-escalate',\n '--minimal',\n '--usage',\n '--schema-b64',\n '--cwd',\n]);\n\nexport function unsupported(argv: readonly string[]): Answer | undefined {\n const found = argv.find((arg) => UNSUPPORTED.has(arg) || arg.startsWith('--image='));\n return found ? fail(`${found} is not supported in SLICC yet`, 2) : undefined;\n}\n\nasync function spawnAsync(\n deps: Deps,\n request: Request,\n who: Caller,\n argv: readonly string[],\n context: Context\n) {\n if (who.scoop) return fail('a scoop cannot start async scoops; run agent without --async');\n const refused = unsupported(argv);\n if (refused) return refused;\n const parsed = flags(argv, ASYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !ASYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const given = await prompts(deps, argv, request, context);\n if (!given.length) return fail('--async needs at least one --prompt, --file or -', 2);\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n const taints = await taintsOf(deps, request, who, context);\n return deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'async',\n name: last(parsed, '--name') ?? found.role?.name ?? 'scoop',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n taints,\n },\n context\n );\n}\n\nasync function listAgents(deps: Deps): Promise<Answer> {\n const roles = await deps.roles();\n const lines = roles.roles.map(\n (entry) =>\n `${entry.name}\\t${entry.source}\\t${entry.description}${entry.aliases.length ? ` (also ${entry.aliases.join(', ')})` : ''}`\n );\n return ok(\n `${[\n ...lines,\n '',\n 'Agent files are read from the built-in roles, installed packages (pi-subagents.agents) and ~/.pi/agent/agents.',\n \"A project's .pi/agents folder is read only once the folder is trusted, which SLICC doesn't support yet.\",\n ...roles.warnings.map((warning) => `warning: ${warning}`),\n ].join('\\n')}\\n`\n );\n}\n\nasync function list(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (request.argv.includes('--agents')) return listAgents(deps);\n const rows = await deps.scoops.list(who.cone, context);\n if (!rows.length) return ok('no scoops\\n');\n return ok(\n `${rows.map((row) => `${row.folder}\\t${row.name}\\t${row.role ?? '-'}\\t${row.busy ? 'working' : 'idle'}`).join('\\n')}\\n`\n );\n}\n\nasync function status(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const [, record] = found;\n const busy = await deps.scoops.busy(record.conversation, context);\n return ok(\n `${[\n `handle: ${record.folder}`,\n `name: ${record.name}`,\n `role: ${record.role ?? '-'}`,\n `kind: ${record.kind}`,\n `state: ${busy ? 'working' : 'idle'}`,\n `folder: ${deps.layout.scoopRoot(record.folder)}`,\n `reports: ${deps.layout.reports(record.folder, record.cone)}`,\n ].join('\\n')}\\n`\n );\n}\n\nasync function message(\n deps: Deps,\n parsed: Flags,\n request: Request,\n context: Context\n): Promise<string> {\n const file = last(parsed, '--file');\n if (file) return readText(deps, file, request, context);\n return parsed.rest.includes('-') ? request.stdin : parsed.rest.join(' ');\n}\n\nasync function send(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(2), ['--file']);\n const unknown = [...parsed.switches].find((flag) => flag !== '--follow-up');\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const text = await message(deps, parsed, request, context);\n if (!text.trim()) return fail('send needs a message, --file or -', 2);\n if (request.argv[1] === 'parent') {\n if (!who.scoop) return fail('only a scoop has a parent to send to');\n return deps.scoops.note(who.scoop, text, context);\n }\n if (who.scoop) return fail('a scoop can only send to its parent');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n const followUp = parsed.switches.has('--follow-up');\n const taints = await taintsOf(deps, request, who, context);\n return deps.scoops.feed(\n found[0],\n text,\n { fromAgent: who.fromAgent, request: request.id, followUp, target: who.id, taints },\n context\n );\n}\n\nfunction cronTarget(deps: Deps, request: Request, name: string): LickTarget | Answer {\n const state = deps.agents.state();\n if (!name) return fail('send needs cone or a scoop handle', 2);\n const user = request.user && request.user !== ROOT_USER ? request.user : undefined;\n const own = user ? agentOfUser(state, user) : undefined;\n if (user && !own) return fail(`${user} is no cone or scoop`);\n if (own?.startsWith('scoop:')) {\n const record = state.scoops[own] as { name: string };\n const mine = [own, own.slice('scoop:'.length), record.name].includes(name);\n return mine\n ? (own as LickTarget)\n : fail(\"a scoop's cron job can only send to the scoop itself\");\n }\n const cone = own ? own.slice(CONE_PREFIX.length) : null;\n const home: LickTarget = cone ? `cone:${cone}` : 'cone';\n if (name === 'cone') return home;\n return (findScoop(state, name, cone)?.[0] as LickTarget | undefined) ?? home;\n}\n\nconst PROCESS_LICKS = ['cron', 'webhook'];\n\nfunction expanded(argv: readonly string[]): string[] {\n return argv.flatMap((arg) => {\n const at = arg.indexOf('=');\n const name = arg.slice(0, at);\n return at > 0 && (name === '--lick' || name === '--source') ? [name, arg.slice(at + 1)] : [arg];\n });\n}\n\nfunction refusedChannel(channel: string): Answer {\n const own = (LICK_CHANNELS as readonly string[]).includes(channel);\n const what = own\n ? `--lick=${channel} is the agent's own channel`\n : `there is no lick channel \"${channel}\"`;\n return fail(\n `${what}; a process may send ${PROCESS_LICKS.map((name) => `--lick=${name}`).join(' or ')}`,\n 2\n );\n}\n\nasync function cronSend(\n deps: Deps,\n licks: Pick<Licks, 'deliver'>,\n request: Request,\n parsed: Flags,\n context: Context\n): Promise<Answer> {\n if (!request.cron)\n return fail('--lick=cron only works inside a cron job, which sets SLICC_CRON_JOB');\n if (last(parsed, '--source') !== undefined)\n return fail(\"--source is for --lick=webhook; a cron lick is named by its job's # name:\", 2);\n const target = cronTarget(deps, request, parsed.rest[0] ?? '');\n if (isAnswer(target)) return target;\n const text = (await message(deps, unnamed(parsed), request, context)).trim();\n await licks.deliver(cronLick(request.cron, target, text), context);\n return ok('');\n}\n\nfunction webhookScope(deps: Deps, request: Request): string | null | Answer {\n const user = request.user && request.user !== ROOT_USER ? request.user : undefined;\n if (!user) return null;\n const own = agentOfUser(deps.agents.state(), user);\n if (!own) return fail(`${user} is no cone or scoop`);\n if (own.startsWith('scoop:')) return fail(\"a scoop can't send webhook licks; its cone can\");\n return own.slice(CONE_PREFIX.length);\n}\n\nasync function webhookSend(\n deps: Deps,\n request: Request,\n parsed: Flags,\n context: Context\n): Promise<Answer> {\n if (!deps.webhook) return fail('webhooks are not available in this agent');\n const source = last(parsed, '--source');\n if (!source)\n return fail('--lick=webhook needs --source <name>, for ~/.slicc/webhooks/<name>.json', 2);\n if (parsed.rest[0] !== 'cone')\n return fail('a webhook lick goes to the cone: agent send cone --lick=webhook \u2026', 2);\n const scope = webhookScope(deps, request);\n if (isAnswer(scope)) return scope;\n const text = await message(deps, unnamed(parsed), request, context);\n if (!text.trim()) return fail('send needs a message, --file or -', 2);\n const delivered = await deps.webhook(\n scopedName(source, scope),\n webhookDelivery(text.trimEnd()),\n context\n );\n return delivered\n ? ok('')\n : fail(`there is no webhook ${source}; add ~/.slicc/webhooks/${source}.json`);\n}\n\nfunction unnamed(parsed: Flags): Flags {\n return { ...parsed, rest: parsed.rest.slice(1) };\n}\n\nasync function lickSend(deps: Deps, request: Request, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(1), ['--file', '--lick', '--source']);\n const unknown = [...parsed.switches][0];\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const channel = last(parsed, '--lick') ?? '';\n if (!PROCESS_LICKS.includes(channel)) return refusedChannel(channel);\n if (!deps.licks) return fail('licks are not available in this agent');\n return channel === 'cron'\n ? cronSend(deps, deps.licks, request, parsed, context)\n : webhookSend(deps, request, parsed, context);\n}\n\nasync function latest(\n deps: Deps,\n record: { folder: string; cone: string },\n context: Context\n): Promise<string> {\n const dir = deps.layout.reports(record.folder, record.cone);\n const listed = await deps.env.listDir(dir, context);\n if (!listed.ok || !listed.value.length) return '(no answer yet)';\n const newest = [...listed.value].sort(\n (a, b) => Number.parseInt(b.name, 10) - Number.parseInt(a.name, 10)\n )[0];\n const read = await deps.env.readTextFile(`${dir}/${newest?.name}`, context);\n return read.ok ? read.value.trimEnd() : '(no answer yet)';\n}\n\nfunction waitTargets(deps: Deps, who: Caller, rest: readonly string[]): string[] | Answer {\n if (!rest.length) return fail('wait needs at least one handle', 2);\n const missing = rest.filter((name) => !handle(deps, who, name));\n if (missing.length)\n return fail(missing.map((name) => noScoop(deps.agents.state(), name)).join('; '));\n return rest.map((name) => (handle(deps, who, name) as [string, unknown])[0]);\n}\n\nasync function block(\n deps: Deps,\n ids: string[],\n seconds: number,\n context: Context\n): Promise<Answer> {\n const deadline = deps.now() + seconds * 1000;\n let open = await deps.scoops.working(ids, context);\n while (open.length && deps.now() < deadline) {\n await new Promise((done) => setTimeout(done, 200));\n open = await deps.scoops.working(ids, context);\n }\n const state = deps.agents.state();\n const sections: string[] = [];\n for (const id of ids) {\n const record = state.scoops[id];\n if (record)\n sections.push(\n `## ${record.folder}${open.includes(id) ? ' (still working)' : ''}\\n${await latest(deps, record, context)}`\n );\n }\n const body = `${sections.join('\\n\\n')}\\n`;\n if (!open.length) return ok(body);\n const still = open.map((id) => state.scoops[id]?.folder).join(', ');\n return { code: 1, out: `${body}agent: timed out after ${seconds}s; still working: ${still}\\n` };\n}\n\nasync function wait(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(1), ['--timeout']);\n const unknown = [...parsed.switches].find((flag) => flag !== '--notify');\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const seconds = Number(last(parsed, '--timeout') ?? DEFAULT_WAIT_S);\n if (!Number.isInteger(seconds) || seconds <= 0)\n return fail('--timeout must be a positive whole number of seconds', 2);\n const ids = waitTargets(deps, who, parsed.rest);\n if (isAnswer(ids)) return ids;\n if (!parsed.switches.has('--notify')) return block(deps, ids, seconds, context);\n if (!who.fromAgent || who.scoop)\n return fail('wait --notify is for a cone; a terminal waits with agent wait');\n await deps.scoops.notifyWhenDone(who.cone, ids, deps.now() + seconds * 1000, context);\n return ok(`you'll get one scoop-wait lick when ${ids.length > 1 ? 'they are' : 'it is'} done\\n`);\n}\n\nasync function stop(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot stop scoops');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n return deps.scoops.stop(found[0], who.fromAgent, context);\n}\n\nasync function rename(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot rename scoops');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const refused = await reviewing(deps, who, found, context);\n if (refused) return refused;\n return deps.scoops.rename(found[0], request.argv.slice(2).join(' '), context);\n}\n\ntype Verb = (deps: Deps, request: Request, who: Caller, context: Context) => Promise<Answer>;\n\nconst help: Verb = async () => ok(USAGE);\n\nconst VERBS: Record<string, Verb> = {\n list,\n status,\n send,\n wait,\n stop,\n rename,\n workflow: async (deps, request, who, context) =>\n deps.workflow\n ? deps.workflow(\n request.argv.slice(1),\n { ...who, taints: await taintsOf(deps, request, who, context) },\n request,\n context\n )\n : fail('workflows are not available in this agent'),\n help,\n '--help': help,\n '-h': help,\n __cancel: (deps, request, _who, context) => cancelSync(deps, request.argv[1] ?? '', context),\n __detach: (deps, request, _who, context) => detachSync(deps, request.argv[1] ?? '', context),\n};\n\nexport function noScoop(state: Readonly<AgentsState>, name: string): string {\n const id = name.startsWith('scoop:') ? name : `scoop:${name}`;\n const record =\n state.scoops[id]?.frozen !== undefined\n ? state.scoops[id]\n : Object.values(state.scoops).find(\n (candidate) => candidate.frozen && candidate.name === name\n );\n const frozen = record?.frozen ? state.frozen?.[record.frozen] : undefined;\n if (frozen) return `scoop ${name} is frozen with cone ${frozen.name}; thaw the cone first`;\n return `there is no scoop ${name}`.trim();\n}\n\nexport function panelCaller(request: Request, who: Caller): PanelCaller {\n const agentId = who.scoop ?? (who.fromAgent ? who.cone : null);\n return { agentId, cone: who.cone, tab: agentId === null ? (request.tab ?? null) : null };\n}\n\nasync function dispatch(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n if (request.as === 'panel')\n return deps.panel\n ? deps.panel(request.argv, panelCaller(request, who), context)\n : { code: 1, out: 'panel: panels are not available in this agent\\n' };\n if (request.as === 'memory')\n return deps.memory\n ? deps.memory(request.argv, who.id, context)\n : fail('memory is not available in this agent');\n if (request.as === 'gelatiere')\n return deps.gelatiere\n ? deps.gelatiere(request.argv, who.id, context)\n : fail('the gelatiere is not available in this agent');\n if (request.as === 'freezer')\n return deps.freezer\n ? deps.freezer(request.argv, who.id, context, {\n user: request.user ?? null,\n cwd: request.cwd,\n })\n : fail('the freezer is not available in this agent');\n if (request.as === 'models')\n return deps.models\n ? deps.models(request.argv, who.id, context)\n : fail('models is not available in this agent');\n const first = request.argv[0] ?? '';\n const verb = VERBS[first];\n if (verb) return verb(deps, request, who, context);\n if (request.as === 'subagent') {\n if (first === 'spawn') return spawnAsync(deps, request, who, request.argv.slice(1), context);\n return { code: 2, out: USAGE };\n }\n if (!request.argv.length) return { code: 2, out: USAGE };\n if (request.argv.includes('--async'))\n return spawnAsync(deps, request, who, request.argv, context);\n return runSync(deps, request, who, context);\n}\n\nconst BLOCKING = new Set([\n 'wait',\n 'workflow',\n 'list',\n 'status',\n 'help',\n '--help',\n '-h',\n '__cancel',\n '__detach',\n]);\n\nexport function createCli(options: CliOptions): Runner {\n const deps: Deps = {\n ...options,\n now: options.now ?? Date.now,\n sync: { pending: new Map() },\n layout: options.layout ?? LEGACY,\n };\n return {\n blocking(request) {\n if (request.as === 'panel') return true;\n const first = request.argv[0] ?? '';\n if (BLOCKING.has(first)) return true;\n return request.as === 'agent' && !VERBS[first] && !request.argv.includes('--async');\n },\n async run(request, context) {\n try {\n const argv = expanded(request.argv);\n if (request.as === 'agent' && argv[0] === 'send' && argv.includes('--lick'))\n return await lickSend(deps, { ...request, argv }, context);\n return await dispatch(deps, request, callerOf(options.agents, request), context);\n } catch (error) {\n return fail((error as Error).message);\n }\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/scoops/service.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
scoopId
|
|
9
9
|
} from "../agents.js";
|
|
10
10
|
import { CODEMODE } from "../codemode/index.js";
|
|
11
|
-
import { GuestTaintDoc } from "../guests/guard.js";
|
|
11
|
+
import { distinctTaints, GuestTaintDoc } from "../guests/guard.js";
|
|
12
12
|
import { LEGACY } from "../layout.js";
|
|
13
13
|
import { McpAllowDoc, mcpEntries } from "../mcp/index.js";
|
|
14
14
|
import { visible } from "./visible.js";
|
|
@@ -239,6 +239,10 @@ async function feed(core, id, prompt, options, context) {
|
|
|
239
239
|
const created = options.fromAgent ? await tail(parent, context) : null;
|
|
240
240
|
const { target } = options;
|
|
241
241
|
return harness.commit(async (tx) => {
|
|
242
|
+
if (options.taints?.length) {
|
|
243
|
+
const doc = await tx.doc(GuestTaintDoc, record.conversation);
|
|
244
|
+
doc.taints = distinctTaints([...doc.taints, ...options.taints]);
|
|
245
|
+
}
|
|
242
246
|
await addFeed(core, tx, parent.id, {
|
|
243
247
|
scoop: id,
|
|
244
248
|
created,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/scoops/service.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n type AgentChange,\n type AnyTask,\n type Conversation,\n type ConversationId,\n configure,\n defineDoc,\n type Extension,\n type Harness,\n type TaskId,\n type ToolRegistration,\n type Tx,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport {\n type Agents,\n type AgentsState,\n freeFolder,\n live,\n type Mark,\n type ScoopRecord,\n scoopId,\n} from '../agents.ts';\nimport { CODEMODE } from '../codemode/index.ts';\nimport { GuestTaintDoc, type InheritedTaint } from '../guests/guard.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport { type Layout, LEGACY } from '../layout.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { McpAllowDoc, mcpEntries } from '../mcp/index.ts';\nimport type { Role } from '../roles/roles.ts';\nimport type { Choosable } from '../selection.ts';\nimport { visible } from './visible.ts';\n\nexport { SCOOPS_ROOT } from '../layout.ts';\nexport const LEDGER_SIZE = 512;\n\nexport type Feed = {\n scoop: string;\n created: Mark | null;\n report: boolean;\n target: string | null;\n channel: 'scoop-notify' | 'bash';\n from?: string;\n agent?: boolean;\n};\ntype Wait = { scoops: string[]; done: Record<string, string>; cone: string };\nexport type Answer = { code: number; out: string; err?: string; tasks?: number[] };\ntype WorkState = {\n feeds: Record<string, Feed>;\n waits: Record<string, Wait>;\n ledger: Record<string, Answer>;\n turns: Record<string, { at: number; count: number }>;\n};\n\nexport const ScoopWorkDoc = defineDoc<WorkState>({\n kind: 'slicc.scoops.work',\n version: 1,\n scope: 'session',\n initial: () => ({ feeds: {}, waits: {}, ledger: {}, turns: {} }),\n});\n\nexport interface ScoopTasks {\n anchor: AnyTask;\n reporter: AnyTask;\n wait: AnyTask;\n}\n\nexport type EnvOf = (\n conversationId: ConversationId,\n context: Context\n) => Promise<Pick<ExecutionEnv, 'canonicalPath'> | undefined>;\n\nexport interface ScoopsHost {\n harness: Harness;\n agents: Agents;\n licks: Licks;\n groups?: ProcessGroups;\n tools?: readonly ToolRegistration[];\n reads?: () => readonly string[];\n files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;\n envOf?: EnvOf;\n mcp?: (names: readonly string[]) => ToolRegistration[];\n layout?: Layout;\n enforced?: boolean;\n exclude?: readonly Extension[];\n}\n\nexport interface Rewound {\n stopped: string[];\n restored: string[];\n}\n\nexport interface ScoopSummary {\n id: string;\n folder: string;\n name: string;\n role: string | null;\n busy: boolean;\n}\n\nexport interface Limits {\n maxLiveScoops: number;\n maxPerTurn: number;\n}\n\nexport interface SpawnRequest {\n cone: string;\n kind?: 'async' | 'sync';\n parent?: string;\n depth?: number;\n roots?: { write: string[]; read: string[] };\n cwd?: string;\n origin?: string;\n instructions?: string;\n target?: string | null;\n asker?: string | null;\n name: string;\n role?: Role;\n model?: { provider: string; modelId: string };\n thinking?: AgentChange['thinkingLevel'];\n tools?: string[];\n prompts: string[];\n fromAgent: boolean;\n request?: string;\n limits: Limits;\n taints?: InheritedTaint[];\n created?: (tx: Tx, made: Spawned) => Promise<void>;\n}\n\nexport interface Spawned {\n folder: string;\n conversation: number;\n tasks: number[];\n}\n\nexport function workspace(folder: string, layout: Layout = LEGACY): string {\n return layout.workspace(folder);\n}\n\nexport async function tail(conversation: Conversation, context: Context): Promise<Mark> {\n const { entries } = await conversation.context(context);\n return { in: conversation.id, at: Number(entries.at(-1)?.id ?? 0) };\n}\n\nexport async function turnStart(conversation: Conversation, context: Context): Promise<number> {\n const { entries } = await conversation.context(context);\n return Number(entries.findLast((entry) => entry.kind === 'pi.user')?.id ?? 0);\n}\n\nexport function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined {\n return Object.entries(state.cones).find(([, cone]) => cone.conversation === conversation)?.[0];\n}\n\nexport function findScoop(\n state: Readonly<AgentsState>,\n handle: string,\n cone: string | null\n): [string, ScoopRecord] | undefined {\n const id = handle.startsWith('scoop:') ? handle : scoopId(handle);\n const reachable = (record: ScoopRecord | undefined): record is ScoopRecord =>\n !!record && live(record) && (cone === null || record.cone === cone);\n const record = state.scoops[id];\n if (reachable(record)) return [id, record];\n return Object.entries(state.scoops).find(\n ([, candidate]) => reachable(candidate) && candidate.name === handle\n );\n}\n\nfunction remember(work: WorkState, request: string | undefined, answer: Answer): void {\n if (!request) return;\n work.ledger[request] = answer;\n const keys = Object.keys(work.ledger);\n for (const key of keys.slice(0, Math.max(0, keys.length - LEDGER_SIZE))) delete work.ledger[key];\n}\n\ntype Core = { host: Promise<ScoopsHost>; tasks: () => ScoopTasks };\n\nasync function coneOfId(core: Core, coneId: string, context: Context): Promise<Conversation> {\n const { agents } = await core.host;\n const found = await agents.conversation(coneId, context);\n if (!found) throw new Error(`There is no cone ${coneId}.`);\n return found;\n}\n\nasync function isBusy(core: Core, conversation: number, context: Context): Promise<boolean> {\n const { harness } = await core.host;\n const handle = await harness.conversation(conversation as ConversationId, context);\n const view = await handle?.viewState(context);\n const run = (view?.value.docs['pi.live'] as { run?: unknown } | undefined)?.run;\n view?.dispose();\n return Boolean(run);\n}\n\nasync function answered(\n core: Core,\n request: string | undefined,\n context: Context\n): Promise<Answer | undefined> {\n if (!request) return undefined;\n const { harness } = await core.host;\n return (await harness.snapshot(ScoopWorkDoc, context))?.ledger[request];\n}\n\ntype NewFeed = Omit<Feed, 'channel' | 'from'> & {\n from: string;\n agent: boolean;\n prompt: string;\n request?: string;\n followUp?: boolean;\n};\n\nasync function addFeed(core: Core, tx: Tx, parent: number, feed: NewFeed): Promise<number> {\n const task = await tx.createTask(\n core.tasks().reporter as never,\n {\n scoop: feed.scoop,\n prompt: feed.prompt,\n ...(feed.followUp ? { followUp: true } : {}),\n ...(feed.request ? { request: feed.request } : {}),\n },\n {\n ownership: { kind: 'conversation' },\n conversationId: parent as ConversationId,\n background: true,\n }\n );\n (await tx.doc(ScoopWorkDoc)).feeds[String(task)] = {\n scoop: feed.scoop,\n created: feed.created,\n report: feed.report,\n target: feed.target,\n channel: 'scoop-notify',\n from: feed.from,\n agent: feed.agent,\n };\n return Number(task);\n}\n\nexport function choosable(tools: readonly ToolRegistration[]): Choosable {\n const names = new Set(tools.map((tool) => tool.name));\n return (name) => names.has(name) || (mcpEntries([name]) ?? []).length > 0;\n}\n\nfunction selection(\n tools: readonly ToolRegistration[] | undefined,\n names: string[] | undefined,\n mcp?: (names: readonly string[]) => ToolRegistration[]\n) {\n if (!names || !tools) return undefined;\n const picked = tools.filter((tool) => names.includes(tool.name));\n const entries = mcpEntries(names) ?? [];\n if (!entries.length) return picked;\n const codemode = tools.find((tool) => tool.name === CODEMODE);\n if (codemode && !picked.includes(codemode)) picked.push(codemode);\n return [...picked, ...(mcp?.(entries) ?? [])];\n}\n\nfunction liveCount(state: Readonly<AgentsState>, cone: string): number {\n return Object.values(state.scoops).filter((scoop) => scoop.cone === cone && live(scoop)).length;\n}\n\nfunction claimTurn(\n work: WorkState,\n request: SpawnRequest,\n turn: number | null\n): Answer | undefined {\n if (turn === null) return undefined;\n const counted = work.turns[request.cone];\n const count = counted && counted.at === turn ? counted.count : 0;\n if (count >= request.limits.maxPerTurn)\n return {\n code: 1,\n out: `subagent: this turn already started ${count} scoops (the limit is ${request.limits.maxPerTurn})\\n`,\n };\n work.turns[request.cone] = { at: turn, count: count + 1 };\n return undefined;\n}\n\nexport function agentChange(\n request: SpawnRequest,\n folder: string,\n host: Pick<ScoopsHost, 'tools' | 'mcp' | 'layout' | 'exclude'>\n): AgentChange {\n const { tools, mcp } = host;\n const model = request.model ?? modelOf(request.role?.model);\n const thinking = request.thinking ?? request.role?.thinking;\n const chosen = selection(tools, request.tools ?? request.role?.tools, mcp);\n const instructions = [request.role?.prompt, request.instructions].filter(Boolean).join('\\n\\n');\n return {\n cwd: request.cwd ?? workspace(folder, host.layout),\n ...(instructions ? { instructions } : {}),\n ...(model ? { model } : {}),\n ...(thinking ? { thinkingLevel: thinking as AgentChange['thinkingLevel'] } : {}),\n ...(chosen ? { tools: chosen } : {}),\n ...(host.exclude?.length ? { extensions: { remove: host.exclude } } : {}),\n };\n}\n\nasync function narrowMcp(\n tx: Tx,\n state: Readonly<AgentsState>,\n cone: ConversationId,\n child: ConversationId,\n request: SpawnRequest\n): Promise<void> {\n const listed = mcpEntries(request.tools ?? request.role?.tools);\n const caller = state.scoops[request.parent ?? '']?.conversation as ConversationId | undefined;\n const inherited = (await tx.doc(McpAllowDoc, caller ?? cone)).allow;\n if (listed !== null || inherited !== null)\n (await tx.doc(McpAllowDoc, child)).allow = listed ?? inherited;\n}\n\nfunction scoopRecord(\n request: SpawnRequest,\n folder: string,\n conversation: number,\n anchor: number,\n created: Mark | null\n): ScoopRecord {\n return {\n name: request.name.trim() || folder,\n folder,\n cone: request.cone,\n conversation,\n anchor,\n role: request.role?.name ?? null,\n ...(request.role?.memory ? { memory: request.role.memory } : {}),\n ...(request.role?.memory && request.origin ? { origin: request.origin } : {}),\n ...(request.role?.context ? { context: request.role.context } : {}),\n kind: request.kind ?? 'async',\n parent: request.parent ?? request.cone,\n depth: request.depth ?? 1,\n roots: request.roots ?? null,\n created,\n dropped: null,\n gone: false,\n };\n}\n\nasync function spawn(core: Core, request: SpawnRequest, context: Context): Promise<Answer> {\n const done = await answered(core, request.request, context);\n if (done) return done;\n const host = await core.host;\n const { agents } = host;\n const parent = await coneOfId(core, request.cone, context);\n const count = liveCount(agents.state(), request.cone);\n if (count >= request.limits.maxLiveScoops)\n return {\n code: 1,\n out: `subagent: this cone already has ${count} live scoops (the limit is ${request.limits.maxLiveScoops}); stop one first\\n`,\n };\n const created = request.fromAgent ? await tail(parent, context) : null;\n const turn = request.fromAgent ? await turnStart(parent, context) : null;\n return agents.update(async (tx, doc) => {\n const work = await tx.doc(ScoopWorkDoc);\n const refused = claimTurn(work as WorkState, request, turn);\n if (refused) return refused;\n const folder = freeFolder(doc, request.name);\n const id = scoopId(folder);\n const anchor = await tx.createTask(core.tasks().anchor as never, null, {\n ownership: { kind: 'conversation' },\n conversationId: parent.id,\n background: true,\n });\n const child = await tx.createConversation({ ownership: { kind: 'task', taskId: anchor } });\n await configure(tx, child.id, agentChange(request, folder, host));\n await narrowMcp(tx, doc, parent.id, child.id, request);\n if (request.taints?.length) (await tx.doc(GuestTaintDoc, child.id)).taints = request.taints;\n doc.scoops[id] = scoopRecord(request, folder, child.id, Number(anchor), created);\n const target =\n request.target === undefined\n ? request.fromAgent\n ? `cone:${request.cone}`\n : null\n : request.target;\n const made: number[] = [];\n const asker = request.asker === undefined ? target : request.asker;\n const from = askerName(doc, asker);\n for (const prompt of request.prompts)\n made.push(\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from,\n agent: asker !== null,\n prompt,\n })\n );\n const answer = { code: 0, out: `${folder}\\n`, tasks: made };\n await request.created?.(tx, { folder, conversation: Number(child.id), tasks: made });\n remember(work as WorkState, request.request, answer);\n return answer;\n }, context);\n}\n\nexport function askerName(state: Readonly<AgentsState>, asker: string | null): string {\n if (asker === null) return 'terminal';\n if (asker.startsWith('cone:')) return state.cones[asker.slice('cone:'.length)]?.name ?? asker;\n return state.scoops[asker]?.name ?? asker;\n}\n\nconst missing = (id: string): Answer => ({\n code: 1,\n out: `subagent: there is no scoop ${id.replace('scoop:', '')}\\n`,\n});\n\nasync function feed(\n core: Core,\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n): Promise<Answer> {\n const done = await answered(core, options.request, context);\n if (done) return done;\n const { harness, agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const parent = await coneOfId(core, record.cone, context);\n const created = options.fromAgent ? await tail(parent, context) : null;\n const { target } = options;\n return harness.commit(async (tx) => {\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from: askerName(agents.state(), target),\n agent: target !== null,\n prompt,\n followUp: options.followUp,\n request: options.request,\n });\n const answer = { code: 0, out: `sent to ${record.folder}\\n` };\n remember((await tx.doc(ScoopWorkDoc)) as WorkState, options.request, answer);\n return answer;\n }, context);\n}\n\nasync function signal(core: Core, record: ScoopRecord, context: Context): Promise<void> {\n const { harness, groups } = await core.host;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context, { background: true });\n await groups?.signal(record.conversation);\n}\n\nasync function stopFeeds(\n core: Core,\n scoop: string,\n keep: (feed: Feed) => Promise<boolean>,\n context: Context\n) {\n const { harness } = await core.host;\n const work = (await harness.snapshot(ScoopWorkDoc, context)) ?? { feeds: {} };\n const dropped: string[] = [];\n for (const [task, entry] of Object.entries(work.feeds)) {\n if (entry.scoop !== scoop || (await keep(entry))) continue;\n const record = await harness.getTask(Number(task) as TaskId, context);\n if (record && record.state.status !== 'terminal')\n await harness.abortTask(Number(task) as TaskId, context);\n dropped.push(task);\n }\n if (dropped.length)\n await harness.commit(async (tx) => {\n const doc = await tx.doc(ScoopWorkDoc);\n for (const task of dropped) delete doc.feeds[task];\n }, context);\n return dropped.length;\n}\n\nasync function stop(core: Core, id: string, fromAgent: boolean, context: Context): Promise<Answer> {\n const { agents, files, layout = LEGACY } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n const mark = fromAgent\n ? await tail(await coneOfId(core, record.cone, context), context)\n : { in: 0, at: 0 };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).dropped = mark;\n }, context);\n const place = layout.workspace(record.folder);\n const removed = await files?.remove(place, { recursive: true, force: true }, context);\n const folder = removed?.ok ? `removed ${place}` : `kept ${place}`;\n return {\n code: 0,\n out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${layout.reports(record.folder, record.cone)}\\n`,\n };\n}\n\nasync function rename(core: Core, id: string, name: string, context: Context): Promise<Answer> {\n const { agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const wanted = name.trim();\n if (!wanted) return { code: 2, out: 'subagent: rename needs a non-empty name\\n' };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).name = wanted;\n }, context);\n return { code: 0, out: `${record.folder} is now called ${wanted}\\n` };\n}\n\nasync function resetWorkspace(\n host: Pick<ScoopsHost, 'files' | 'layout'>,\n folder: string,\n context: Context\n): Promise<boolean> {\n const { files } = host;\n if (!files) return true;\n const place = workspace(folder, host.layout);\n const cleared = await files.remove(place, { recursive: true, force: true }, context);\n if (!cleared.ok) return false;\n if (host.layout?.users) return true;\n return (await files.createDir(place, { recursive: true }, context)).ok;\n}\n\ntype Seen = (mark: Mark | null) => Promise<boolean>;\n\nasync function rewindOne(\n core: Core,\n coneId: string,\n id: string,\n record: ScoopRecord,\n seen: Seen,\n result: Rewound,\n context: Context\n): Promise<Partial<ScoopRecord> | undefined> {\n const host = await core.host;\n const { harness, licks } = host;\n if (!(await seen(record.created))) {\n if (live(record)) {\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n result.stopped.push(record.name);\n }\n return { gone: true };\n }\n if (record.dropped !== null) {\n if (await seen(record.dropped)) return undefined;\n const reset = await resetWorkspace(host, record.folder, context);\n result.restored.push(\n reset ? record.name : `${record.name} (its working folder could not be reset)`\n );\n return { dropped: null };\n }\n const withdrawn = await stopFeeds(core, id, (entry) => seen(entry.created), context);\n if (!withdrawn) return undefined;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context);\n await licks.forget(`cone:${coneId}`, 'scoop-notify', id, context);\n return undefined;\n}\n\nasync function rewound(\n core: Core,\n coneId: string,\n fork: Conversation,\n context: Context\n): Promise<Rewound> {\n const { harness, agents } = await core.host;\n const read = (id: number) =>\n harness.commit((tx) => tx.conversation(id as ConversationId), context);\n const seen: Seen = async (mark) =>\n mark === null || mark.in === 0 || (await visible(read, fork.id, mark));\n const result: Rewound = { stopped: [], restored: [] };\n const changes: [string, Partial<ScoopRecord>][] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if (record.cone !== coneId || record.gone) continue;\n const change = await rewindOne(core, coneId, id, record, seen, result, context);\n if (change) changes.push([id, change]);\n }\n if (changes.length)\n await agents.update((_tx, state) => {\n for (const [id, change] of changes) Object.assign(state.scoops[id] as ScoopRecord, change);\n }, context);\n return result;\n}\n\nasync function list(core: Core, coneId: string | null, context: Context): Promise<ScoopSummary[]> {\n const { agents } = await core.host;\n const out: ScoopSummary[] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if ((coneId !== null && record.cone !== coneId) || !live(record)) continue;\n out.push({\n id,\n folder: record.folder,\n name: record.name,\n role: record.role,\n busy: await isBusy(core, record.conversation, context),\n });\n }\n return out;\n}\n\nasync function working(core: Core, ids: readonly string[], context: Context): Promise<string[]> {\n const { harness, agents } = await core.host;\n const feeds = Object.values((await harness.snapshot(ScoopWorkDoc, context))?.feeds ?? {});\n const out: string[] = [];\n for (const id of ids) {\n const record = agents.state().scoops[id];\n if (!record) continue;\n if (\n feeds.some((entry) => entry.scoop === id) ||\n (await isBusy(core, record.conversation, context))\n )\n out.push(id);\n }\n return out;\n}\n\nasync function notifyWhenDone(\n core: Core,\n coneId: string,\n ids: string[],\n deadline: number,\n context: Context\n) {\n const { harness } = await core.host;\n const parent = await coneOfId(core, coneId, context);\n await harness.commit(\n (tx) =>\n tx.createTask(\n core.tasks().wait as never,\n { scoops: ids, cone: coneId, deadline },\n { ownership: { kind: 'conversation' }, conversationId: parent.id, background: true }\n ),\n context\n );\n}\n\nasync function detach(core: Core, tasks: readonly number[], target: string, context: Context) {\n const { harness } = await core.host;\n await harness.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const task of tasks) {\n const entry = work.feeds[String(task)];\n if (!entry) continue;\n entry.report = true;\n entry.target = target;\n entry.channel = 'bash';\n }\n }, context);\n}\n\nasync function note(core: Core, id: string, text: string, context: Context): Promise<Answer> {\n const { agents, licks } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n await licks.deliver(\n {\n channel: 'scoop-notify',\n source: `${id}#note`,\n title: label,\n text: `[scoop ${label} progress]`,\n body: text,\n target: `cone:${record.cone}`,\n },\n context\n );\n return { code: 0, out: 'note sent to the cone\\n' };\n}\n\nexport function createScoops(host: Promise<ScoopsHost>, tasks: () => ScoopTasks) {\n const core: Core = { host, tasks };\n return {\n detach: (made: readonly number[], target: string, context: Context) =>\n detach(core, made, target, context),\n note: (id: string, text: string, context: Context) => note(core, id, text, context),\n spawn: (request: SpawnRequest, context: Context) => spawn(core, request, context),\n feed: (\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n ) => feed(core, id, prompt, options, context),\n stop: (id: string, fromAgent: boolean, context: Context) => stop(core, id, fromAgent, context),\n rename: (id: string, name: string, context: Context) => rename(core, id, name, context),\n rewound: (coneId: string, fork: Conversation, context: Context) =>\n rewound(core, coneId, fork, context),\n list: (coneId: string | null, context: Context) => list(core, coneId, context),\n busy: (conversation: number, context: Context) => isBusy(core, conversation, context),\n working: (ids: readonly string[], context: Context) => working(core, ids, context),\n notifyWhenDone: (coneId: string, ids: string[], deadline: number, context: Context) =>\n notifyWhenDone(core, coneId, ids, deadline, context),\n };\n}\n\nexport function modelOf(\n value: string | undefined\n): { provider: string; modelId: string } | undefined {\n if (!value) return undefined;\n const at = value.indexOf('/');\n if (at <= 0) return undefined;\n return { provider: value.slice(0, at), modelId: value.slice(at + 1) };\n}\n\nexport type Scoops = ReturnType<typeof createScoops>;\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n type AgentChange,\n type AnyTask,\n type Conversation,\n type ConversationId,\n configure,\n defineDoc,\n type Extension,\n type Harness,\n type TaskId,\n type ToolRegistration,\n type Tx,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport {\n type Agents,\n type AgentsState,\n freeFolder,\n live,\n type Mark,\n type ScoopRecord,\n scoopId,\n} from '../agents.ts';\nimport { CODEMODE } from '../codemode/index.ts';\nimport { distinctTaints, GuestTaintDoc, type InheritedTaint } from '../guests/guard.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport { type Layout, LEGACY } from '../layout.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { McpAllowDoc, mcpEntries } from '../mcp/index.ts';\nimport type { Role } from '../roles/roles.ts';\nimport type { Choosable } from '../selection.ts';\nimport { visible } from './visible.ts';\n\nexport { SCOOPS_ROOT } from '../layout.ts';\nexport const LEDGER_SIZE = 512;\n\nexport type Feed = {\n scoop: string;\n created: Mark | null;\n report: boolean;\n target: string | null;\n channel: 'scoop-notify' | 'bash';\n from?: string;\n agent?: boolean;\n};\ntype Wait = { scoops: string[]; done: Record<string, string>; cone: string };\nexport type Answer = { code: number; out: string; err?: string; tasks?: number[] };\ntype WorkState = {\n feeds: Record<string, Feed>;\n waits: Record<string, Wait>;\n ledger: Record<string, Answer>;\n turns: Record<string, { at: number; count: number }>;\n};\n\nexport const ScoopWorkDoc = defineDoc<WorkState>({\n kind: 'slicc.scoops.work',\n version: 1,\n scope: 'session',\n initial: () => ({ feeds: {}, waits: {}, ledger: {}, turns: {} }),\n});\n\nexport interface ScoopTasks {\n anchor: AnyTask;\n reporter: AnyTask;\n wait: AnyTask;\n}\n\nexport type EnvOf = (\n conversationId: ConversationId,\n context: Context\n) => Promise<Pick<ExecutionEnv, 'canonicalPath'> | undefined>;\n\nexport interface ScoopsHost {\n harness: Harness;\n agents: Agents;\n licks: Licks;\n groups?: ProcessGroups;\n tools?: readonly ToolRegistration[];\n reads?: () => readonly string[];\n files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;\n envOf?: EnvOf;\n mcp?: (names: readonly string[]) => ToolRegistration[];\n layout?: Layout;\n enforced?: boolean;\n exclude?: readonly Extension[];\n}\n\nexport interface Rewound {\n stopped: string[];\n restored: string[];\n}\n\nexport interface ScoopSummary {\n id: string;\n folder: string;\n name: string;\n role: string | null;\n busy: boolean;\n}\n\nexport interface Limits {\n maxLiveScoops: number;\n maxPerTurn: number;\n}\n\nexport interface SpawnRequest {\n cone: string;\n kind?: 'async' | 'sync';\n parent?: string;\n depth?: number;\n roots?: { write: string[]; read: string[] };\n cwd?: string;\n origin?: string;\n instructions?: string;\n target?: string | null;\n asker?: string | null;\n name: string;\n role?: Role;\n model?: { provider: string; modelId: string };\n thinking?: AgentChange['thinkingLevel'];\n tools?: string[];\n prompts: string[];\n fromAgent: boolean;\n request?: string;\n limits: Limits;\n taints?: InheritedTaint[];\n created?: (tx: Tx, made: Spawned) => Promise<void>;\n}\n\nexport interface FeedOptions {\n fromAgent: boolean;\n request: string;\n followUp: boolean;\n target: string | null;\n taints?: InheritedTaint[];\n}\n\nexport interface Spawned {\n folder: string;\n conversation: number;\n tasks: number[];\n}\n\nexport function workspace(folder: string, layout: Layout = LEGACY): string {\n return layout.workspace(folder);\n}\n\nexport async function tail(conversation: Conversation, context: Context): Promise<Mark> {\n const { entries } = await conversation.context(context);\n return { in: conversation.id, at: Number(entries.at(-1)?.id ?? 0) };\n}\n\nexport async function turnStart(conversation: Conversation, context: Context): Promise<number> {\n const { entries } = await conversation.context(context);\n return Number(entries.findLast((entry) => entry.kind === 'pi.user')?.id ?? 0);\n}\n\nexport function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined {\n return Object.entries(state.cones).find(([, cone]) => cone.conversation === conversation)?.[0];\n}\n\nexport function findScoop(\n state: Readonly<AgentsState>,\n handle: string,\n cone: string | null\n): [string, ScoopRecord] | undefined {\n const id = handle.startsWith('scoop:') ? handle : scoopId(handle);\n const reachable = (record: ScoopRecord | undefined): record is ScoopRecord =>\n !!record && live(record) && (cone === null || record.cone === cone);\n const record = state.scoops[id];\n if (reachable(record)) return [id, record];\n return Object.entries(state.scoops).find(\n ([, candidate]) => reachable(candidate) && candidate.name === handle\n );\n}\n\nfunction remember(work: WorkState, request: string | undefined, answer: Answer): void {\n if (!request) return;\n work.ledger[request] = answer;\n const keys = Object.keys(work.ledger);\n for (const key of keys.slice(0, Math.max(0, keys.length - LEDGER_SIZE))) delete work.ledger[key];\n}\n\ntype Core = { host: Promise<ScoopsHost>; tasks: () => ScoopTasks };\n\nasync function coneOfId(core: Core, coneId: string, context: Context): Promise<Conversation> {\n const { agents } = await core.host;\n const found = await agents.conversation(coneId, context);\n if (!found) throw new Error(`There is no cone ${coneId}.`);\n return found;\n}\n\nasync function isBusy(core: Core, conversation: number, context: Context): Promise<boolean> {\n const { harness } = await core.host;\n const handle = await harness.conversation(conversation as ConversationId, context);\n const view = await handle?.viewState(context);\n const run = (view?.value.docs['pi.live'] as { run?: unknown } | undefined)?.run;\n view?.dispose();\n return Boolean(run);\n}\n\nasync function answered(\n core: Core,\n request: string | undefined,\n context: Context\n): Promise<Answer | undefined> {\n if (!request) return undefined;\n const { harness } = await core.host;\n return (await harness.snapshot(ScoopWorkDoc, context))?.ledger[request];\n}\n\ntype NewFeed = Omit<Feed, 'channel' | 'from'> & {\n from: string;\n agent: boolean;\n prompt: string;\n request?: string;\n followUp?: boolean;\n};\n\nasync function addFeed(core: Core, tx: Tx, parent: number, feed: NewFeed): Promise<number> {\n const task = await tx.createTask(\n core.tasks().reporter as never,\n {\n scoop: feed.scoop,\n prompt: feed.prompt,\n ...(feed.followUp ? { followUp: true } : {}),\n ...(feed.request ? { request: feed.request } : {}),\n },\n {\n ownership: { kind: 'conversation' },\n conversationId: parent as ConversationId,\n background: true,\n }\n );\n (await tx.doc(ScoopWorkDoc)).feeds[String(task)] = {\n scoop: feed.scoop,\n created: feed.created,\n report: feed.report,\n target: feed.target,\n channel: 'scoop-notify',\n from: feed.from,\n agent: feed.agent,\n };\n return Number(task);\n}\n\nexport function choosable(tools: readonly ToolRegistration[]): Choosable {\n const names = new Set(tools.map((tool) => tool.name));\n return (name) => names.has(name) || (mcpEntries([name]) ?? []).length > 0;\n}\n\nfunction selection(\n tools: readonly ToolRegistration[] | undefined,\n names: string[] | undefined,\n mcp?: (names: readonly string[]) => ToolRegistration[]\n) {\n if (!names || !tools) return undefined;\n const picked = tools.filter((tool) => names.includes(tool.name));\n const entries = mcpEntries(names) ?? [];\n if (!entries.length) return picked;\n const codemode = tools.find((tool) => tool.name === CODEMODE);\n if (codemode && !picked.includes(codemode)) picked.push(codemode);\n return [...picked, ...(mcp?.(entries) ?? [])];\n}\n\nfunction liveCount(state: Readonly<AgentsState>, cone: string): number {\n return Object.values(state.scoops).filter((scoop) => scoop.cone === cone && live(scoop)).length;\n}\n\nfunction claimTurn(\n work: WorkState,\n request: SpawnRequest,\n turn: number | null\n): Answer | undefined {\n if (turn === null) return undefined;\n const counted = work.turns[request.cone];\n const count = counted && counted.at === turn ? counted.count : 0;\n if (count >= request.limits.maxPerTurn)\n return {\n code: 1,\n out: `subagent: this turn already started ${count} scoops (the limit is ${request.limits.maxPerTurn})\\n`,\n };\n work.turns[request.cone] = { at: turn, count: count + 1 };\n return undefined;\n}\n\nexport function agentChange(\n request: SpawnRequest,\n folder: string,\n host: Pick<ScoopsHost, 'tools' | 'mcp' | 'layout' | 'exclude'>\n): AgentChange {\n const { tools, mcp } = host;\n const model = request.model ?? modelOf(request.role?.model);\n const thinking = request.thinking ?? request.role?.thinking;\n const chosen = selection(tools, request.tools ?? request.role?.tools, mcp);\n const instructions = [request.role?.prompt, request.instructions].filter(Boolean).join('\\n\\n');\n return {\n cwd: request.cwd ?? workspace(folder, host.layout),\n ...(instructions ? { instructions } : {}),\n ...(model ? { model } : {}),\n ...(thinking ? { thinkingLevel: thinking as AgentChange['thinkingLevel'] } : {}),\n ...(chosen ? { tools: chosen } : {}),\n ...(host.exclude?.length ? { extensions: { remove: host.exclude } } : {}),\n };\n}\n\nasync function narrowMcp(\n tx: Tx,\n state: Readonly<AgentsState>,\n cone: ConversationId,\n child: ConversationId,\n request: SpawnRequest\n): Promise<void> {\n const listed = mcpEntries(request.tools ?? request.role?.tools);\n const caller = state.scoops[request.parent ?? '']?.conversation as ConversationId | undefined;\n const inherited = (await tx.doc(McpAllowDoc, caller ?? cone)).allow;\n if (listed !== null || inherited !== null)\n (await tx.doc(McpAllowDoc, child)).allow = listed ?? inherited;\n}\n\nfunction scoopRecord(\n request: SpawnRequest,\n folder: string,\n conversation: number,\n anchor: number,\n created: Mark | null\n): ScoopRecord {\n return {\n name: request.name.trim() || folder,\n folder,\n cone: request.cone,\n conversation,\n anchor,\n role: request.role?.name ?? null,\n ...(request.role?.memory ? { memory: request.role.memory } : {}),\n ...(request.role?.memory && request.origin ? { origin: request.origin } : {}),\n ...(request.role?.context ? { context: request.role.context } : {}),\n kind: request.kind ?? 'async',\n parent: request.parent ?? request.cone,\n depth: request.depth ?? 1,\n roots: request.roots ?? null,\n created,\n dropped: null,\n gone: false,\n };\n}\n\nasync function spawn(core: Core, request: SpawnRequest, context: Context): Promise<Answer> {\n const done = await answered(core, request.request, context);\n if (done) return done;\n const host = await core.host;\n const { agents } = host;\n const parent = await coneOfId(core, request.cone, context);\n const count = liveCount(agents.state(), request.cone);\n if (count >= request.limits.maxLiveScoops)\n return {\n code: 1,\n out: `subagent: this cone already has ${count} live scoops (the limit is ${request.limits.maxLiveScoops}); stop one first\\n`,\n };\n const created = request.fromAgent ? await tail(parent, context) : null;\n const turn = request.fromAgent ? await turnStart(parent, context) : null;\n return agents.update(async (tx, doc) => {\n const work = await tx.doc(ScoopWorkDoc);\n const refused = claimTurn(work as WorkState, request, turn);\n if (refused) return refused;\n const folder = freeFolder(doc, request.name);\n const id = scoopId(folder);\n const anchor = await tx.createTask(core.tasks().anchor as never, null, {\n ownership: { kind: 'conversation' },\n conversationId: parent.id,\n background: true,\n });\n const child = await tx.createConversation({ ownership: { kind: 'task', taskId: anchor } });\n await configure(tx, child.id, agentChange(request, folder, host));\n await narrowMcp(tx, doc, parent.id, child.id, request);\n if (request.taints?.length) (await tx.doc(GuestTaintDoc, child.id)).taints = request.taints;\n doc.scoops[id] = scoopRecord(request, folder, child.id, Number(anchor), created);\n const target =\n request.target === undefined\n ? request.fromAgent\n ? `cone:${request.cone}`\n : null\n : request.target;\n const made: number[] = [];\n const asker = request.asker === undefined ? target : request.asker;\n const from = askerName(doc, asker);\n for (const prompt of request.prompts)\n made.push(\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from,\n agent: asker !== null,\n prompt,\n })\n );\n const answer = { code: 0, out: `${folder}\\n`, tasks: made };\n await request.created?.(tx, { folder, conversation: Number(child.id), tasks: made });\n remember(work as WorkState, request.request, answer);\n return answer;\n }, context);\n}\n\nexport function askerName(state: Readonly<AgentsState>, asker: string | null): string {\n if (asker === null) return 'terminal';\n if (asker.startsWith('cone:')) return state.cones[asker.slice('cone:'.length)]?.name ?? asker;\n return state.scoops[asker]?.name ?? asker;\n}\n\nconst missing = (id: string): Answer => ({\n code: 1,\n out: `subagent: there is no scoop ${id.replace('scoop:', '')}\\n`,\n});\n\nasync function feed(\n core: Core,\n id: string,\n prompt: string,\n options: FeedOptions,\n context: Context\n): Promise<Answer> {\n const done = await answered(core, options.request, context);\n if (done) return done;\n const { harness, agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const parent = await coneOfId(core, record.cone, context);\n const created = options.fromAgent ? await tail(parent, context) : null;\n const { target } = options;\n return harness.commit(async (tx) => {\n if (options.taints?.length) {\n const doc = await tx.doc(GuestTaintDoc, record.conversation as ConversationId);\n doc.taints = distinctTaints([...doc.taints, ...options.taints]);\n }\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from: askerName(agents.state(), target),\n agent: target !== null,\n prompt,\n followUp: options.followUp,\n request: options.request,\n });\n const answer = { code: 0, out: `sent to ${record.folder}\\n` };\n remember((await tx.doc(ScoopWorkDoc)) as WorkState, options.request, answer);\n return answer;\n }, context);\n}\n\nasync function signal(core: Core, record: ScoopRecord, context: Context): Promise<void> {\n const { harness, groups } = await core.host;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context, { background: true });\n await groups?.signal(record.conversation);\n}\n\nasync function stopFeeds(\n core: Core,\n scoop: string,\n keep: (feed: Feed) => Promise<boolean>,\n context: Context\n) {\n const { harness } = await core.host;\n const work = (await harness.snapshot(ScoopWorkDoc, context)) ?? { feeds: {} };\n const dropped: string[] = [];\n for (const [task, entry] of Object.entries(work.feeds)) {\n if (entry.scoop !== scoop || (await keep(entry))) continue;\n const record = await harness.getTask(Number(task) as TaskId, context);\n if (record && record.state.status !== 'terminal')\n await harness.abortTask(Number(task) as TaskId, context);\n dropped.push(task);\n }\n if (dropped.length)\n await harness.commit(async (tx) => {\n const doc = await tx.doc(ScoopWorkDoc);\n for (const task of dropped) delete doc.feeds[task];\n }, context);\n return dropped.length;\n}\n\nasync function stop(core: Core, id: string, fromAgent: boolean, context: Context): Promise<Answer> {\n const { agents, files, layout = LEGACY } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n const mark = fromAgent\n ? await tail(await coneOfId(core, record.cone, context), context)\n : { in: 0, at: 0 };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).dropped = mark;\n }, context);\n const place = layout.workspace(record.folder);\n const removed = await files?.remove(place, { recursive: true, force: true }, context);\n const folder = removed?.ok ? `removed ${place}` : `kept ${place}`;\n return {\n code: 0,\n out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${layout.reports(record.folder, record.cone)}\\n`,\n };\n}\n\nasync function rename(core: Core, id: string, name: string, context: Context): Promise<Answer> {\n const { agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const wanted = name.trim();\n if (!wanted) return { code: 2, out: 'subagent: rename needs a non-empty name\\n' };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).name = wanted;\n }, context);\n return { code: 0, out: `${record.folder} is now called ${wanted}\\n` };\n}\n\nasync function resetWorkspace(\n host: Pick<ScoopsHost, 'files' | 'layout'>,\n folder: string,\n context: Context\n): Promise<boolean> {\n const { files } = host;\n if (!files) return true;\n const place = workspace(folder, host.layout);\n const cleared = await files.remove(place, { recursive: true, force: true }, context);\n if (!cleared.ok) return false;\n if (host.layout?.users) return true;\n return (await files.createDir(place, { recursive: true }, context)).ok;\n}\n\ntype Seen = (mark: Mark | null) => Promise<boolean>;\n\nasync function rewindOne(\n core: Core,\n coneId: string,\n id: string,\n record: ScoopRecord,\n seen: Seen,\n result: Rewound,\n context: Context\n): Promise<Partial<ScoopRecord> | undefined> {\n const host = await core.host;\n const { harness, licks } = host;\n if (!(await seen(record.created))) {\n if (live(record)) {\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n result.stopped.push(record.name);\n }\n return { gone: true };\n }\n if (record.dropped !== null) {\n if (await seen(record.dropped)) return undefined;\n const reset = await resetWorkspace(host, record.folder, context);\n result.restored.push(\n reset ? record.name : `${record.name} (its working folder could not be reset)`\n );\n return { dropped: null };\n }\n const withdrawn = await stopFeeds(core, id, (entry) => seen(entry.created), context);\n if (!withdrawn) return undefined;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context);\n await licks.forget(`cone:${coneId}`, 'scoop-notify', id, context);\n return undefined;\n}\n\nasync function rewound(\n core: Core,\n coneId: string,\n fork: Conversation,\n context: Context\n): Promise<Rewound> {\n const { harness, agents } = await core.host;\n const read = (id: number) =>\n harness.commit((tx) => tx.conversation(id as ConversationId), context);\n const seen: Seen = async (mark) =>\n mark === null || mark.in === 0 || (await visible(read, fork.id, mark));\n const result: Rewound = { stopped: [], restored: [] };\n const changes: [string, Partial<ScoopRecord>][] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if (record.cone !== coneId || record.gone) continue;\n const change = await rewindOne(core, coneId, id, record, seen, result, context);\n if (change) changes.push([id, change]);\n }\n if (changes.length)\n await agents.update((_tx, state) => {\n for (const [id, change] of changes) Object.assign(state.scoops[id] as ScoopRecord, change);\n }, context);\n return result;\n}\n\nasync function list(core: Core, coneId: string | null, context: Context): Promise<ScoopSummary[]> {\n const { agents } = await core.host;\n const out: ScoopSummary[] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if ((coneId !== null && record.cone !== coneId) || !live(record)) continue;\n out.push({\n id,\n folder: record.folder,\n name: record.name,\n role: record.role,\n busy: await isBusy(core, record.conversation, context),\n });\n }\n return out;\n}\n\nasync function working(core: Core, ids: readonly string[], context: Context): Promise<string[]> {\n const { harness, agents } = await core.host;\n const feeds = Object.values((await harness.snapshot(ScoopWorkDoc, context))?.feeds ?? {});\n const out: string[] = [];\n for (const id of ids) {\n const record = agents.state().scoops[id];\n if (!record) continue;\n if (\n feeds.some((entry) => entry.scoop === id) ||\n (await isBusy(core, record.conversation, context))\n )\n out.push(id);\n }\n return out;\n}\n\nasync function notifyWhenDone(\n core: Core,\n coneId: string,\n ids: string[],\n deadline: number,\n context: Context\n) {\n const { harness } = await core.host;\n const parent = await coneOfId(core, coneId, context);\n await harness.commit(\n (tx) =>\n tx.createTask(\n core.tasks().wait as never,\n { scoops: ids, cone: coneId, deadline },\n { ownership: { kind: 'conversation' }, conversationId: parent.id, background: true }\n ),\n context\n );\n}\n\nasync function detach(core: Core, tasks: readonly number[], target: string, context: Context) {\n const { harness } = await core.host;\n await harness.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const task of tasks) {\n const entry = work.feeds[String(task)];\n if (!entry) continue;\n entry.report = true;\n entry.target = target;\n entry.channel = 'bash';\n }\n }, context);\n}\n\nasync function note(core: Core, id: string, text: string, context: Context): Promise<Answer> {\n const { agents, licks } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n await licks.deliver(\n {\n channel: 'scoop-notify',\n source: `${id}#note`,\n title: label,\n text: `[scoop ${label} progress]`,\n body: text,\n target: `cone:${record.cone}`,\n },\n context\n );\n return { code: 0, out: 'note sent to the cone\\n' };\n}\n\nexport function createScoops(host: Promise<ScoopsHost>, tasks: () => ScoopTasks) {\n const core: Core = { host, tasks };\n return {\n detach: (made: readonly number[], target: string, context: Context) =>\n detach(core, made, target, context),\n note: (id: string, text: string, context: Context) => note(core, id, text, context),\n spawn: (request: SpawnRequest, context: Context) => spawn(core, request, context),\n feed: (id: string, prompt: string, options: FeedOptions, context: Context) =>\n feed(core, id, prompt, options, context),\n stop: (id: string, fromAgent: boolean, context: Context) => stop(core, id, fromAgent, context),\n rename: (id: string, name: string, context: Context) => rename(core, id, name, context),\n rewound: (coneId: string, fork: Conversation, context: Context) =>\n rewound(core, coneId, fork, context),\n list: (coneId: string | null, context: Context) => list(core, coneId, context),\n busy: (conversation: number, context: Context) => isBusy(core, conversation, context),\n working: (ids: readonly string[], context: Context) => working(core, ids, context),\n notifyWhenDone: (coneId: string, ids: string[], deadline: number, context: Context) =>\n notifyWhenDone(core, coneId, ids, deadline, context),\n };\n}\n\nexport function modelOf(\n value: string | undefined\n): { provider: string; modelId: string } | undefined {\n if (!value) return undefined;\n const at = value.indexOf('/');\n if (at <= 0) return undefined;\n return { provider: value.slice(0, at), modelId: value.slice(at + 1) };\n}\n\nexport type Scoops = ReturnType<typeof createScoops>;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["record", "feed"]
|
|
7
7
|
}
|
package/dist/scoops/sync.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
prompts,
|
|
12
12
|
readText,
|
|
13
13
|
role,
|
|
14
|
+
taintsOf,
|
|
14
15
|
unsupported
|
|
15
16
|
} from "./cli.js";
|
|
16
17
|
import { SESSIONS } from "../layout.js";
|
|
@@ -234,6 +235,7 @@ async function runSync(deps, request, who, context) {
|
|
|
234
235
|
if (isAnswer(chosen)) return chosen;
|
|
235
236
|
const found = await role(deps, parsed);
|
|
236
237
|
if (found.error) return found.error;
|
|
238
|
+
const taints = await taintsOf(deps, request, who, context);
|
|
237
239
|
await share(deps, request, planned.shares, context);
|
|
238
240
|
const spawned = await deps.scoops.spawn(
|
|
239
241
|
{
|
|
@@ -255,7 +257,8 @@ async function runSync(deps, request, who, context) {
|
|
|
255
257
|
origin: request.cwd,
|
|
256
258
|
fromAgent: who.fromAgent,
|
|
257
259
|
request: request.id,
|
|
258
|
-
limits: found.roles.limits
|
|
260
|
+
limits: found.roles.limits,
|
|
261
|
+
taints
|
|
259
262
|
},
|
|
260
263
|
context
|
|
261
264
|
);
|
package/dist/scoops/sync.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/scoops/sync.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ConversationId, EntryRecord, TaskId } from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport type { ScoopRecord } from '../agents.ts';\nimport { quote } from '../kernel/env.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport {\n type Caller,\n choices,\n type Deps,\n fail,\n flags,\n isAnswer,\n last,\n MAX_DEPTH,\n prompts,\n readText,\n role,\n unsupported,\n} from './cli.ts';\nimport type { ReportResult } from './extension.ts';\nimport type { Request } from './requests.ts';\nimport type { Answer } from './service.ts';\n\nexport { SESSIONS } from '../layout.ts';\n\ntype Ending = 'cancel' | 'detach';\n\ninterface Pending {\n end: (ending: Ending) => void;\n}\n\nexport interface SyncState {\n pending: Map<string, Pending>;\n}\n\nconst SYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n '--read-only',\n '--system-prompt',\n '--system-prompt-file',\n '--background-after',\n];\nconst SYNC_SWITCHES = new Set([\n '--persist-session',\n '--no-persist-session',\n '--no-extensions',\n '--no-skills',\n '--no-context-files',\n]);\n\ntype Persist = 'tmp' | 'durable' | 'none';\ntype Kept = Exclude<Persist, 'none'>;\n\nfunction persistOf(switches: Set<string>): Persist {\n if (switches.has('--no-persist-session')) return 'none';\n return switches.has('--persist-session') ? 'durable' : 'tmp';\n}\n\nfunction block(text: unknown): string {\n return typeof text === 'string' ? text : JSON.stringify(text, null, 2);\n}\n\nfunction entryMarkdown(entry: EntryRecord): string | undefined {\n const message = entry.model?.[0] as { content?: unknown; toolCallId?: string } | undefined;\n if (entry.kind === 'pi.user') return `## Request\\n\\n${answerText(message?.content)}`;\n if (entry.kind === 'pi.tool-result')\n return `### Result\\n\\n\\`\\`\\`\\n${answerText(message?.content)}\\n\\`\\`\\``;\n if (entry.kind !== 'pi.assistant') return undefined;\n const parts = Array.isArray(message?.content)\n ? (message.content as { type: string; name?: string; arguments?: unknown }[])\n : [];\n const calls = parts\n .filter((part) => part.type === 'toolCall')\n .map((part) => `\\`${part.name}\\` ${block(part.arguments)}`);\n return [`## Answer\\n\\n${answerText(message?.content)}`, ...calls].join('\\n\\n');\n}\n\nexport function transcript(record: ScoopRecord, entries: readonly EntryRecord[]): string {\n const body = entries.map(entryMarkdown).filter(Boolean);\n return `# ${record.name}${record.role ? ` (${record.role})` : ''}\\n\\n${body.join('\\n\\n')}\\n`;\n}\n\nasync function archive(\n deps: Deps,\n record: ScoopRecord,\n persist: Persist,\n user: string | null,\n context: Context\n): Promise<string | null> {\n if (persist === 'none') return null;\n const kept: Kept = persist;\n const conversation = await deps.harness.conversation(\n record.conversation as ConversationId,\n context\n );\n if (!conversation) return null;\n const { entries } = await conversation.context(context);\n const dir = deps.layout.sessions(kept, user);\n const path = `${dir}/${record.folder}.md`;\n if (kept === 'tmp') await deps.layout.ownDir(dir, user, context);\n const env = (await deps.layout.envFor(user, context)) ?? deps.env;\n const written = await env.writeFile(path, transcript(record, entries), context);\n return written.ok ? path : null;\n}\n\nasync function finish(\n deps: Deps,\n id: string,\n persist: Persist,\n user: string | null,\n shares: readonly Shared[],\n context: Context\n): Promise<void> {\n const record = deps.agents.state().scoops[id];\n if (!record) return;\n const written = shares.filter((shared) => shared.write).map((shared) => quote(shared.path));\n if (written.length)\n await deps.env.exec(`chmod -R g+rwX ${written.join(' ')}`, undefined, context);\n await archive(deps, record, persist, user, context).catch(() => null);\n await deps.scoops.stop(id, false, context);\n await deps.env.remove(\n deps.layout.scoopRoot(record.folder),\n { recursive: true, force: true },\n context\n );\n}\n\nasync function callerRunning(deps: Deps, who: Caller, context: Context): Promise<boolean> {\n if (!who.fromAgent) return false;\n const state = deps.agents.state();\n const conversation = who.scoop\n ? state.scoops[who.scoop]?.conversation\n : state.cones[who.cone]?.conversation;\n return conversation !== undefined && deps.scoops.busy(conversation, context);\n}\n\nasync function keep(\n deps: Deps,\n id: string,\n tasks: readonly number[],\n target: string | null,\n context: Context\n) {\n if (target) await deps.scoops.detach(tasks, target, context);\n await deps.agents.update((_tx, state) => {\n const record = state.scoops[id];\n if (record) record.kind = 'async';\n }, context);\n}\n\nfunction watchPid(deps: Deps, pid: number | null, end: (ending: Ending) => void): () => void {\n const alive = deps.alive;\n if (pid === null || !alive) return () => undefined;\n const timer = setInterval(() => {\n void alive(pid).then(\n (yes) => yes || end('cancel'),\n () => undefined\n );\n }, 1000);\n return () => clearInterval(timer);\n}\n\nexport type Shared = { path: string; write: boolean };\n\nexport function sharesOf(\n home: string,\n cwd: string,\n workdir: string | undefined,\n readOnly: readonly string[]\n): Shared[] {\n const inside = (path: string) => path.startsWith(`${home}/`);\n const out: Shared[] = [];\n if (workdir && inside(workdir)) out.push({ path: workdir, write: true });\n for (const path of [...readOnly, ...(workdir ? [] : [cwd])])\n if (inside(path) && !out.some((shared) => shared.path === path))\n out.push({ path, write: false });\n return out;\n}\n\nexport function shareScript(home: string, shares: readonly Shared[]): string {\n const lines: string[] = [];\n for (const { path, write } of shares) {\n const at = quote(path);\n lines.push(`chmod -R ${write ? 'g+rwX' : 'g+rX'} ${at}`);\n if (write)\n lines.push(\n `shopt -s globstar dotglob nullglob; for dir in ${at} ${at}/**/; do chmod g+s \"$dir\"; done`\n );\n const parts = path\n .slice(home.length + 1)\n .split('/')\n .slice(0, -1);\n for (let depth = 1; depth <= parts.length; depth++)\n lines.push(`chmod g+x ${quote(`${home}/${parts.slice(0, depth).join('/')}`)}`);\n }\n return lines.join('\\n');\n}\n\nexport function shareNote(shares: readonly Shared[]): string {\n const listed = shares\n .map(({ path, write }) => `${path}${write ? ' (you may change files there)' : ' (read only)'}`)\n .join(', ');\n return `Your caller shared these with you through its group: ${listed}.`;\n}\n\nasync function share(deps: Deps, request: Request, shares: readonly Shared[], context: Context) {\n const env = await deps.layout.envFor(request.user ?? null, context);\n if (!env || !shares.length) return;\n const home = deps.layout.homeOf(request.user ?? null);\n await env.exec(shareScript(home, shares), undefined, context);\n}\n\ninterface Plan {\n given: string[];\n shares: Shared[];\n workdir?: string;\n instructions: string;\n readOnly: string[];\n persist: Persist;\n}\n\nasync function plan(\n deps: Deps,\n request: Request,\n parsed: ReturnType<typeof flags>,\n context: Context\n) {\n const given = await prompts(deps, request.argv, request, context);\n let workdir: string | undefined;\n const notes: string[] = [];\n if (!given.length && parsed.rest.length === 3) {\n const [cwd, allowed, prompt] = parsed.rest as [string, string, string];\n workdir = resolve(request.cwd, cwd);\n if (allowed && allowed !== '*')\n notes.push(\n `Use only these commands in bash: ${allowed}. This is not enforced; keep to it anyway.`\n );\n given.push(prompt);\n } else if (parsed.rest.length) return fail(`unexpected argument ${parsed.rest[0]}`, 2);\n if (!given.length)\n return fail('agent needs --prompt, --file, - or <cwd> <allowed-commands> <prompt>', 2);\n const systemFile = last(parsed, '--system-prompt-file');\n const system =\n last(parsed, '--system-prompt') ??\n (systemFile ? await readText(deps, systemFile, request, context) : undefined);\n if (system) notes.push(system);\n const readOnly = (last(parsed, '--read-only') ?? '')\n .split(',')\n .map((path) => path.trim())\n .filter(Boolean)\n .map((path) => resolve(request.cwd, path));\n const home = deps.layout.homeOf(request.user ?? null);\n const shares = deps.layout.users ? sharesOf(home, request.cwd, workdir, readOnly) : [];\n if (shares.length) notes.push(shareNote(shares));\n if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);\n const result: Plan = {\n given,\n instructions: notes.join('\\n\\n'),\n readOnly,\n persist: persistOf(parsed.switches),\n shares,\n };\n if (workdir) result.workdir = workdir;\n return result;\n}\n\nasync function outcome(\n deps: Deps,\n tasks: readonly number[],\n context: Context\n): Promise<ReportResult> {\n let result: ReportResult = { text: '', failed: 'no request', path: null };\n for (const task of tasks) {\n const settled = await deps.harness.waitForTask(task as TaskId<ReportResult>, context);\n const outcome = settled.state.outcome;\n result =\n outcome.status === 'completed'\n ? outcome.result\n : { text: '', failed: outcome.status, path: null };\n }\n return result;\n}\n\nfunction answerOf(result: ReportResult): Answer {\n if (result.failed) return fail(`the scoop's request ended without an answer: ${result.failed}`);\n return { code: 0, out: result.text.endsWith('\\n') ? result.text : `${result.text}\\n` };\n}\n\nasync function settle(\n deps: Deps,\n who: Caller,\n id: string,\n tasks: readonly number[],\n ending: Ending,\n context: Context\n): Promise<Answer> {\n const handle = id.slice('scoop:'.length);\n if (ending === 'detach') {\n await keep(deps, id, tasks, who.id, context);\n const how = who.id ? 'its answer arrives as a lick' : `follow it with agent wait ${handle}`;\n return { code: 0, out: `${handle} continues in the background; ${how}\\n` };\n }\n if (await callerRunning(deps, who, context)) {\n await keep(deps, id, tasks, who.id, context);\n return {\n code: 143,\n out: `agent: the call was interrupted; ${handle} continues and its answer arrives as a lick\\n`,\n };\n }\n return { code: 130, out: 'agent: stopped\\n' };\n}\n\nexport async function runSync(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const refused = unsupported(request.argv);\n if (refused) return refused;\n if (who.depth >= MAX_DEPTH) return fail(`agents nest at most ${MAX_DEPTH} deep`);\n const parsed = flags(request.argv, SYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !SYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const planned = await plan(deps, request, parsed, context);\n if (isAnswer(planned)) return planned;\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n await share(deps, request, planned.shares, context);\n const spawned = await deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'sync',\n parent: who.scoop ?? who.cone,\n depth: who.depth + 1,\n roots: { write: planned.workdir ? [planned.workdir] : [], read: planned.readOnly },\n ...(planned.workdir ? { cwd: planned.workdir } : {}),\n ...(planned.instructions ? { instructions: planned.instructions } : {}),\n target: null,\n asker: who.id,\n name: last(parsed, '--name') ?? found.role?.name ?? 'agent',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: planned.given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n if (spawned.code !== 0) return spawned;\n const id = `scoop:${spawned.out.trim()}`;\n const tasks = spawned.tasks ?? [];\n let end: (ending: Ending) => void = () => undefined;\n const ended = new Promise<Ending>((done) => {\n end = done;\n });\n deps.sync.pending.set(request.id, { end });\n const unwatch = watchPid(deps, request.pid, end);\n try {\n const raced = await Promise.race([outcome(deps, tasks, context), ended]);\n if (typeof raced === 'string') {\n const answer = await settle(deps, who, id, tasks, raced, context);\n if (answer.code === 130)\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answer;\n }\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answerOf(raced);\n } finally {\n unwatch();\n deps.sync.pending.delete(request.id);\n }\n}\n\nexport async function cancelSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('cancel');\n return { code: 0, out: '' };\n}\n\nexport async function detachSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('detach');\n return { code: 0, out: '' };\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ConversationId, EntryRecord, TaskId } from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport type { ScoopRecord } from '../agents.ts';\nimport { quote } from '../kernel/env.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport {\n type Caller,\n choices,\n type Deps,\n fail,\n flags,\n isAnswer,\n last,\n MAX_DEPTH,\n prompts,\n readText,\n role,\n taintsOf,\n unsupported,\n} from './cli.ts';\nimport type { ReportResult } from './extension.ts';\nimport type { Request } from './requests.ts';\nimport type { Answer } from './service.ts';\n\nexport { SESSIONS } from '../layout.ts';\n\ntype Ending = 'cancel' | 'detach';\n\ninterface Pending {\n end: (ending: Ending) => void;\n}\n\nexport interface SyncState {\n pending: Map<string, Pending>;\n}\n\nconst SYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n '--read-only',\n '--system-prompt',\n '--system-prompt-file',\n '--background-after',\n];\nconst SYNC_SWITCHES = new Set([\n '--persist-session',\n '--no-persist-session',\n '--no-extensions',\n '--no-skills',\n '--no-context-files',\n]);\n\ntype Persist = 'tmp' | 'durable' | 'none';\ntype Kept = Exclude<Persist, 'none'>;\n\nfunction persistOf(switches: Set<string>): Persist {\n if (switches.has('--no-persist-session')) return 'none';\n return switches.has('--persist-session') ? 'durable' : 'tmp';\n}\n\nfunction block(text: unknown): string {\n return typeof text === 'string' ? text : JSON.stringify(text, null, 2);\n}\n\nfunction entryMarkdown(entry: EntryRecord): string | undefined {\n const message = entry.model?.[0] as { content?: unknown; toolCallId?: string } | undefined;\n if (entry.kind === 'pi.user') return `## Request\\n\\n${answerText(message?.content)}`;\n if (entry.kind === 'pi.tool-result')\n return `### Result\\n\\n\\`\\`\\`\\n${answerText(message?.content)}\\n\\`\\`\\``;\n if (entry.kind !== 'pi.assistant') return undefined;\n const parts = Array.isArray(message?.content)\n ? (message.content as { type: string; name?: string; arguments?: unknown }[])\n : [];\n const calls = parts\n .filter((part) => part.type === 'toolCall')\n .map((part) => `\\`${part.name}\\` ${block(part.arguments)}`);\n return [`## Answer\\n\\n${answerText(message?.content)}`, ...calls].join('\\n\\n');\n}\n\nexport function transcript(record: ScoopRecord, entries: readonly EntryRecord[]): string {\n const body = entries.map(entryMarkdown).filter(Boolean);\n return `# ${record.name}${record.role ? ` (${record.role})` : ''}\\n\\n${body.join('\\n\\n')}\\n`;\n}\n\nasync function archive(\n deps: Deps,\n record: ScoopRecord,\n persist: Persist,\n user: string | null,\n context: Context\n): Promise<string | null> {\n if (persist === 'none') return null;\n const kept: Kept = persist;\n const conversation = await deps.harness.conversation(\n record.conversation as ConversationId,\n context\n );\n if (!conversation) return null;\n const { entries } = await conversation.context(context);\n const dir = deps.layout.sessions(kept, user);\n const path = `${dir}/${record.folder}.md`;\n if (kept === 'tmp') await deps.layout.ownDir(dir, user, context);\n const env = (await deps.layout.envFor(user, context)) ?? deps.env;\n const written = await env.writeFile(path, transcript(record, entries), context);\n return written.ok ? path : null;\n}\n\nasync function finish(\n deps: Deps,\n id: string,\n persist: Persist,\n user: string | null,\n shares: readonly Shared[],\n context: Context\n): Promise<void> {\n const record = deps.agents.state().scoops[id];\n if (!record) return;\n const written = shares.filter((shared) => shared.write).map((shared) => quote(shared.path));\n if (written.length)\n await deps.env.exec(`chmod -R g+rwX ${written.join(' ')}`, undefined, context);\n await archive(deps, record, persist, user, context).catch(() => null);\n await deps.scoops.stop(id, false, context);\n await deps.env.remove(\n deps.layout.scoopRoot(record.folder),\n { recursive: true, force: true },\n context\n );\n}\n\nasync function callerRunning(deps: Deps, who: Caller, context: Context): Promise<boolean> {\n if (!who.fromAgent) return false;\n const state = deps.agents.state();\n const conversation = who.scoop\n ? state.scoops[who.scoop]?.conversation\n : state.cones[who.cone]?.conversation;\n return conversation !== undefined && deps.scoops.busy(conversation, context);\n}\n\nasync function keep(\n deps: Deps,\n id: string,\n tasks: readonly number[],\n target: string | null,\n context: Context\n) {\n if (target) await deps.scoops.detach(tasks, target, context);\n await deps.agents.update((_tx, state) => {\n const record = state.scoops[id];\n if (record) record.kind = 'async';\n }, context);\n}\n\nfunction watchPid(deps: Deps, pid: number | null, end: (ending: Ending) => void): () => void {\n const alive = deps.alive;\n if (pid === null || !alive) return () => undefined;\n const timer = setInterval(() => {\n void alive(pid).then(\n (yes) => yes || end('cancel'),\n () => undefined\n );\n }, 1000);\n return () => clearInterval(timer);\n}\n\nexport type Shared = { path: string; write: boolean };\n\nexport function sharesOf(\n home: string,\n cwd: string,\n workdir: string | undefined,\n readOnly: readonly string[]\n): Shared[] {\n const inside = (path: string) => path.startsWith(`${home}/`);\n const out: Shared[] = [];\n if (workdir && inside(workdir)) out.push({ path: workdir, write: true });\n for (const path of [...readOnly, ...(workdir ? [] : [cwd])])\n if (inside(path) && !out.some((shared) => shared.path === path))\n out.push({ path, write: false });\n return out;\n}\n\nexport function shareScript(home: string, shares: readonly Shared[]): string {\n const lines: string[] = [];\n for (const { path, write } of shares) {\n const at = quote(path);\n lines.push(`chmod -R ${write ? 'g+rwX' : 'g+rX'} ${at}`);\n if (write)\n lines.push(\n `shopt -s globstar dotglob nullglob; for dir in ${at} ${at}/**/; do chmod g+s \"$dir\"; done`\n );\n const parts = path\n .slice(home.length + 1)\n .split('/')\n .slice(0, -1);\n for (let depth = 1; depth <= parts.length; depth++)\n lines.push(`chmod g+x ${quote(`${home}/${parts.slice(0, depth).join('/')}`)}`);\n }\n return lines.join('\\n');\n}\n\nexport function shareNote(shares: readonly Shared[]): string {\n const listed = shares\n .map(({ path, write }) => `${path}${write ? ' (you may change files there)' : ' (read only)'}`)\n .join(', ');\n return `Your caller shared these with you through its group: ${listed}.`;\n}\n\nasync function share(deps: Deps, request: Request, shares: readonly Shared[], context: Context) {\n const env = await deps.layout.envFor(request.user ?? null, context);\n if (!env || !shares.length) return;\n const home = deps.layout.homeOf(request.user ?? null);\n await env.exec(shareScript(home, shares), undefined, context);\n}\n\ninterface Plan {\n given: string[];\n shares: Shared[];\n workdir?: string;\n instructions: string;\n readOnly: string[];\n persist: Persist;\n}\n\nasync function plan(\n deps: Deps,\n request: Request,\n parsed: ReturnType<typeof flags>,\n context: Context\n) {\n const given = await prompts(deps, request.argv, request, context);\n let workdir: string | undefined;\n const notes: string[] = [];\n if (!given.length && parsed.rest.length === 3) {\n const [cwd, allowed, prompt] = parsed.rest as [string, string, string];\n workdir = resolve(request.cwd, cwd);\n if (allowed && allowed !== '*')\n notes.push(\n `Use only these commands in bash: ${allowed}. This is not enforced; keep to it anyway.`\n );\n given.push(prompt);\n } else if (parsed.rest.length) return fail(`unexpected argument ${parsed.rest[0]}`, 2);\n if (!given.length)\n return fail('agent needs --prompt, --file, - or <cwd> <allowed-commands> <prompt>', 2);\n const systemFile = last(parsed, '--system-prompt-file');\n const system =\n last(parsed, '--system-prompt') ??\n (systemFile ? await readText(deps, systemFile, request, context) : undefined);\n if (system) notes.push(system);\n const readOnly = (last(parsed, '--read-only') ?? '')\n .split(',')\n .map((path) => path.trim())\n .filter(Boolean)\n .map((path) => resolve(request.cwd, path));\n const home = deps.layout.homeOf(request.user ?? null);\n const shares = deps.layout.users ? sharesOf(home, request.cwd, workdir, readOnly) : [];\n if (shares.length) notes.push(shareNote(shares));\n if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);\n const result: Plan = {\n given,\n instructions: notes.join('\\n\\n'),\n readOnly,\n persist: persistOf(parsed.switches),\n shares,\n };\n if (workdir) result.workdir = workdir;\n return result;\n}\n\nasync function outcome(\n deps: Deps,\n tasks: readonly number[],\n context: Context\n): Promise<ReportResult> {\n let result: ReportResult = { text: '', failed: 'no request', path: null };\n for (const task of tasks) {\n const settled = await deps.harness.waitForTask(task as TaskId<ReportResult>, context);\n const outcome = settled.state.outcome;\n result =\n outcome.status === 'completed'\n ? outcome.result\n : { text: '', failed: outcome.status, path: null };\n }\n return result;\n}\n\nfunction answerOf(result: ReportResult): Answer {\n if (result.failed) return fail(`the scoop's request ended without an answer: ${result.failed}`);\n return { code: 0, out: result.text.endsWith('\\n') ? result.text : `${result.text}\\n` };\n}\n\nasync function settle(\n deps: Deps,\n who: Caller,\n id: string,\n tasks: readonly number[],\n ending: Ending,\n context: Context\n): Promise<Answer> {\n const handle = id.slice('scoop:'.length);\n if (ending === 'detach') {\n await keep(deps, id, tasks, who.id, context);\n const how = who.id ? 'its answer arrives as a lick' : `follow it with agent wait ${handle}`;\n return { code: 0, out: `${handle} continues in the background; ${how}\\n` };\n }\n if (await callerRunning(deps, who, context)) {\n await keep(deps, id, tasks, who.id, context);\n return {\n code: 143,\n out: `agent: the call was interrupted; ${handle} continues and its answer arrives as a lick\\n`,\n };\n }\n return { code: 130, out: 'agent: stopped\\n' };\n}\n\nexport async function runSync(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const refused = unsupported(request.argv);\n if (refused) return refused;\n if (who.depth >= MAX_DEPTH) return fail(`agents nest at most ${MAX_DEPTH} deep`);\n const parsed = flags(request.argv, SYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !SYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const planned = await plan(deps, request, parsed, context);\n if (isAnswer(planned)) return planned;\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n const taints = await taintsOf(deps, request, who, context);\n await share(deps, request, planned.shares, context);\n const spawned = await deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'sync',\n parent: who.scoop ?? who.cone,\n depth: who.depth + 1,\n roots: { write: planned.workdir ? [planned.workdir] : [], read: planned.readOnly },\n ...(planned.workdir ? { cwd: planned.workdir } : {}),\n ...(planned.instructions ? { instructions: planned.instructions } : {}),\n target: null,\n asker: who.id,\n name: last(parsed, '--name') ?? found.role?.name ?? 'agent',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: planned.given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n taints,\n },\n context\n );\n if (spawned.code !== 0) return spawned;\n const id = `scoop:${spawned.out.trim()}`;\n const tasks = spawned.tasks ?? [];\n let end: (ending: Ending) => void = () => undefined;\n const ended = new Promise<Ending>((done) => {\n end = done;\n });\n deps.sync.pending.set(request.id, { end });\n const unwatch = watchPid(deps, request.pid, end);\n try {\n const raced = await Promise.race([outcome(deps, tasks, context), ended]);\n if (typeof raced === 'string') {\n const answer = await settle(deps, who, id, tasks, raced, context);\n if (answer.code === 130)\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answer;\n }\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answerOf(raced);\n } finally {\n unwatch();\n deps.sync.pending.delete(request.id);\n }\n}\n\nexport async function cancelSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('cancel');\n return { code: 0, out: '' };\n}\n\nexport async function detachSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('detach');\n return { code: 0, out: '' };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["outcome"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { LiveDoc } from "@earendil-works/pi-durable";
|
|
2
|
+
import { live } from "../agents.js";
|
|
3
|
+
import { distinctTaints, runTaints } from "../guests/guard.js";
|
|
4
|
+
function conversations(state) {
|
|
5
|
+
return [
|
|
6
|
+
...Object.values(state.cones).map((cone) => cone.conversation),
|
|
7
|
+
...Object.values(state.scoops).filter(live).map((scoop) => scoop.conversation)
|
|
8
|
+
];
|
|
9
|
+
}
|
|
10
|
+
async function callerTaints(harness, state, who, claim, context) {
|
|
11
|
+
if (who.fromAgent) {
|
|
12
|
+
const own = who.scoop ? state.scoops[who.scoop]?.conversation : state.cones[who.cone]?.conversation;
|
|
13
|
+
if (own === void 0) throw new Error("can't tell which agent run is asking");
|
|
14
|
+
return runTaints(harness, own, context);
|
|
15
|
+
}
|
|
16
|
+
if (claim) throw new Error(`there is no agent ${claim} to ask for`);
|
|
17
|
+
const found = [];
|
|
18
|
+
for (const conversation of conversations(state)) {
|
|
19
|
+
const id = conversation;
|
|
20
|
+
if ((await harness.snapshot(LiveDoc, id, context))?.run)
|
|
21
|
+
found.push(...await runTaints(harness, id, context));
|
|
22
|
+
}
|
|
23
|
+
return distinctTaints(found);
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
callerTaints
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=taints.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/scoops/taints.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { type ConversationId, type Harness, LiveDoc } from '@earendil-works/pi-durable';\nimport { type AgentsState, live } from '../agents.ts';\nimport { distinctTaints, type InheritedTaint, runTaints } from '../guests/guard.ts';\n\ntype Reader = Pick<Harness, 'submission' | 'snapshot'>;\n\nexport interface TaintedCaller {\n fromAgent: boolean;\n cone: string;\n scoop: string | null;\n}\n\nfunction conversations(state: Readonly<AgentsState>): number[] {\n return [\n ...Object.values(state.cones).map((cone) => cone.conversation),\n ...Object.values(state.scoops)\n .filter(live)\n .map((scoop) => scoop.conversation),\n ];\n}\n\nexport async function callerTaints(\n harness: Reader,\n state: Readonly<AgentsState>,\n who: TaintedCaller,\n claim: string,\n context: Context\n): Promise<InheritedTaint[]> {\n if (who.fromAgent) {\n const own = who.scoop\n ? state.scoops[who.scoop]?.conversation\n : state.cones[who.cone]?.conversation;\n if (own === undefined) throw new Error(\"can't tell which agent run is asking\");\n return runTaints(harness, own as ConversationId, context);\n }\n if (claim) throw new Error(`there is no agent ${claim} to ask for`);\n const found: InheritedTaint[] = [];\n for (const conversation of conversations(state)) {\n const id = conversation as ConversationId;\n if ((await harness.snapshot(LiveDoc, id, context))?.run)\n found.push(...(await runTaints(harness, id, context)));\n }\n return distinctTaints(found);\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAA4C,eAAe;AAC3D,SAA2B,YAAY;AACvC,SAAS,gBAAqC,iBAAiB;AAU/D,SAAS,cAAc,OAAwC;AAC7D,SAAO;AAAA,IACL,GAAG,OAAO,OAAO,MAAM,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,YAAY;AAAA,IAC7D,GAAG,OAAO,OAAO,MAAM,MAAM,EAC1B,OAAO,IAAI,EACX,IAAI,CAAC,UAAU,MAAM,YAAY;AAAA,EACtC;AACF;AAEA,eAAsB,aACpB,SACA,OACA,KACA,OACA,SAC2B;AAC3B,MAAI,IAAI,WAAW;AACjB,UAAM,MAAM,IAAI,QACZ,MAAM,OAAO,IAAI,KAAK,GAAG,eACzB,MAAM,MAAM,IAAI,IAAI,GAAG;AAC3B,QAAI,QAAQ,OAAW,OAAM,IAAI,MAAM,sCAAsC;AAC7E,WAAO,UAAU,SAAS,KAAuB,OAAO;AAAA,EAC1D;AACA,MAAI,MAAO,OAAM,IAAI,MAAM,qBAAqB,KAAK,aAAa;AAClE,QAAM,QAA0B,CAAC;AACjC,aAAW,gBAAgB,cAAc,KAAK,GAAG;AAC/C,UAAM,KAAK;AACX,SAAK,MAAM,QAAQ,SAAS,SAAS,IAAI,OAAO,IAAI;AAClD,YAAM,KAAK,GAAI,MAAM,UAAU,SAAS,IAAI,OAAO,CAAE;AAAA,EACzD;AACA,SAAO,eAAe,KAAK;AAC7B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -45,6 +45,7 @@ export declare const GuestTaintDoc: import("@earendil-works/pi-durable").Rewinda
|
|
|
45
45
|
}>;
|
|
46
46
|
type TaintReader = Pick<Harness, 'submission' | 'snapshot'>;
|
|
47
47
|
export declare function runTaints(harness: TaintReader, conversationId: ConversationId, context: Context): Promise<InheritedTaint[]>;
|
|
48
|
+
export declare function distinctTaints(taints: readonly InheritedTaint[]): InheritedTaint[];
|
|
48
49
|
export declare function taintsOf(inputs: readonly SubmissionId[], seats: Readonly<Record<string, SeatRecord>>, harness: Pick<Harness, 'submission'>, context: Context): Promise<Taint[]>;
|
|
49
50
|
export declare function guestToolGate(harness: () => Held | undefined): GuestToolGate;
|
|
50
51
|
export {};
|
|
@@ -2,6 +2,7 @@ import type { Context } from '@earendil-works/chord';
|
|
|
2
2
|
import type { Harness } from '@earendil-works/pi-durable';
|
|
3
3
|
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
4
4
|
import type { Agents, AgentsState } from '../agents.ts';
|
|
5
|
+
import type { InheritedTaint } from '../guests/guard.ts';
|
|
5
6
|
import { type Layout } from '../layout.ts';
|
|
6
7
|
import type { Licks } from '../licks/licks.ts';
|
|
7
8
|
import { type WebhookDelivery } from '../licks/sources.ts';
|
|
@@ -33,7 +34,9 @@ export interface CliOptions {
|
|
|
33
34
|
panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => Promise<Answer>;
|
|
34
35
|
licks?: Pick<Licks, 'deliver'>;
|
|
35
36
|
webhook?: (name: string, delivery: WebhookDelivery, context: Context) => Promise<boolean>;
|
|
36
|
-
workflow?: (argv: readonly string[], who: Caller
|
|
37
|
+
workflow?: (argv: readonly string[], who: Caller & {
|
|
38
|
+
taints: InheritedTaint[];
|
|
39
|
+
}, request: Request, context: Context) => Promise<Answer>;
|
|
37
40
|
}
|
|
38
41
|
export interface PanelCaller {
|
|
39
42
|
agentId: string | null;
|
|
@@ -64,6 +67,7 @@ export declare function flags(argv: readonly string[], withValue: readonly strin
|
|
|
64
67
|
export declare function last(parsed: Flags, flag: string): string | undefined;
|
|
65
68
|
export declare class CallerError extends Error {
|
|
66
69
|
}
|
|
70
|
+
export declare function taintsOf(deps: Deps, request: Request, who: Caller, context: Context): Promise<InheritedTaint[]>;
|
|
67
71
|
export declare function callerOf(agents: Agents, request: Request): Caller;
|
|
68
72
|
export declare function readText(deps: Deps, value: string, request: Request, context: Context): Promise<string>;
|
|
69
73
|
export declare function prompts(deps: Deps, argv: readonly string[], request: Request, context: Context): Promise<string[]>;
|
|
@@ -104,6 +104,13 @@ export interface SpawnRequest {
|
|
|
104
104
|
taints?: InheritedTaint[];
|
|
105
105
|
created?: (tx: Tx, made: Spawned) => Promise<void>;
|
|
106
106
|
}
|
|
107
|
+
export interface FeedOptions {
|
|
108
|
+
fromAgent: boolean;
|
|
109
|
+
request: string;
|
|
110
|
+
followUp: boolean;
|
|
111
|
+
target: string | null;
|
|
112
|
+
taints?: InheritedTaint[];
|
|
113
|
+
}
|
|
107
114
|
export interface Spawned {
|
|
108
115
|
folder: string;
|
|
109
116
|
conversation: number;
|
|
@@ -121,12 +128,7 @@ export declare function createScoops(host: Promise<ScoopsHost>, tasks: () => Sco
|
|
|
121
128
|
detach: (made: readonly number[], target: string, context: Context) => Promise<void>;
|
|
122
129
|
note: (id: string, text: string, context: Context) => Promise<Answer>;
|
|
123
130
|
spawn: (request: SpawnRequest, context: Context) => Promise<Answer>;
|
|
124
|
-
feed: (id: string, prompt: string, options:
|
|
125
|
-
fromAgent: boolean;
|
|
126
|
-
request: string;
|
|
127
|
-
followUp: boolean;
|
|
128
|
-
target: string | null;
|
|
129
|
-
}, context: Context) => Promise<Answer>;
|
|
131
|
+
feed: (id: string, prompt: string, options: FeedOptions, context: Context) => Promise<Answer>;
|
|
130
132
|
stop: (id: string, fromAgent: boolean, context: Context) => Promise<Answer>;
|
|
131
133
|
rename: (id: string, name: string, context: Context) => Promise<Answer>;
|
|
132
134
|
rewound: (coneId: string, fork: Conversation, context: Context) => Promise<Rewound>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context } from '@earendil-works/chord';
|
|
2
|
+
import { type Harness } from '@earendil-works/pi-durable';
|
|
3
|
+
import { type AgentsState } from '../agents.ts';
|
|
4
|
+
import { type InheritedTaint } from '../guests/guard.ts';
|
|
5
|
+
type Reader = Pick<Harness, 'submission' | 'snapshot'>;
|
|
6
|
+
export interface TaintedCaller {
|
|
7
|
+
fromAgent: boolean;
|
|
8
|
+
cone: string;
|
|
9
|
+
scoop: string | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function callerTaints(harness: Reader, state: Readonly<AgentsState>, who: TaintedCaller, claim: string, context: Context): Promise<InheritedTaint[]>;
|
|
12
|
+
export {};
|
|
@@ -3,6 +3,7 @@ import { type AnyTask, type Extension, type Registry, type ToolRegistration } fr
|
|
|
3
3
|
import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
|
|
4
4
|
import type { Agents } from '../agents.ts';
|
|
5
5
|
import { sharedSandbox } from '../codemode/index.ts';
|
|
6
|
+
import { type InheritedTaint } from '../guests/guard.ts';
|
|
6
7
|
import type { Layout } from '../layout.ts';
|
|
7
8
|
import { type Engine, type RunHost, type RunRecord } from './run.ts';
|
|
8
9
|
export { WorkflowsDoc } from './run.ts';
|
|
@@ -20,6 +21,7 @@ export interface Files {
|
|
|
20
21
|
export interface RunRequest {
|
|
21
22
|
cone: string;
|
|
22
23
|
from?: number | null;
|
|
24
|
+
taints?: InheritedTaint[];
|
|
23
25
|
files: Files;
|
|
24
26
|
target: string;
|
|
25
27
|
script?: boolean;
|
|
@@ -53,6 +55,7 @@ export interface Invocation {
|
|
|
53
55
|
cone: string;
|
|
54
56
|
scoop: boolean;
|
|
55
57
|
from: number | null;
|
|
58
|
+
taints?: InheritedTaint[];
|
|
56
59
|
files: Files;
|
|
57
60
|
}
|
|
58
61
|
export declare const USAGE = "usage:\n agent workflow run <file.js | name> [--args <json>] [--budget <tokens>] [--concurrency <n>] [--wait]\n agent workflow run --script '<js>' [same options]\n agent workflow list | status <run> | wait <run> | stop <run> | save <run> <name> [--force]\n\nGlobals: agent(prompt, { label, phase, schema, model, effort, agentType }), parallel(thunks),\npipeline(items, ...stages), phase(title), log(message), console, args, budget (output tokens).\n\nRuns a Claude Code .workflow.js as a durable task; it survives a reload. Without --wait it prints\nthe run id. --budget caps output tokens, --concurrency caps agents running at once. save keeps a\nrun's source as ~/.slicc/workflows/<name>.workflow.js, which agent workflow run <name> runs.\n";
|
|
@@ -97,6 +100,7 @@ export declare function cliCommand(workflows: Workflows, layout: Layout, env: Fi
|
|
|
97
100
|
cone: string;
|
|
98
101
|
scoop: string | null;
|
|
99
102
|
fromAgent: boolean;
|
|
103
|
+
taints: InheritedTaint[];
|
|
100
104
|
}, request: {
|
|
101
105
|
user?: string | null;
|
|
102
106
|
cwd: string;
|
package/dist/workflow/index.js
CHANGED
|
@@ -91,7 +91,7 @@ function createWorkflows(host) {
|
|
|
91
91
|
const cone = await agents.conversation(request.cone, context);
|
|
92
92
|
if (!cone) throw new Error(`there is no cone ${request.cone}`);
|
|
93
93
|
const from = request.from ?? null;
|
|
94
|
-
const taints = from === null ? [] : await runTaints(harness, from, context);
|
|
94
|
+
const taints = request.taints ?? (from === null ? [] : await runTaints(harness, from, context));
|
|
95
95
|
return harness.commit(async (tx) => {
|
|
96
96
|
const task = await tx.createTask(
|
|
97
97
|
(await host).tasks.run,
|
|
@@ -221,6 +221,7 @@ async function runWorkflow(workflows, who, options, context) {
|
|
|
221
221
|
{
|
|
222
222
|
cone: who.cone,
|
|
223
223
|
from: who.from,
|
|
224
|
+
...who.taints ? { taints: who.taints } : {},
|
|
224
225
|
files: who.files,
|
|
225
226
|
target,
|
|
226
227
|
...options.script !== void 0 ? { script: true } : {},
|
|
@@ -404,7 +405,7 @@ function cliCommand(workflows, layout, env, agents) {
|
|
|
404
405
|
const from = who.fromAgent ? agents.state().cones[who.cone]?.conversation ?? null : null;
|
|
405
406
|
return command(
|
|
406
407
|
workflows,
|
|
407
|
-
{ cone: who.cone, scoop: who.scoop !== null, from, files },
|
|
408
|
+
{ cone: who.cone, scoop: who.scoop !== null, from, taints: who.taints, files },
|
|
408
409
|
argv,
|
|
409
410
|
context
|
|
410
411
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/workflow/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport { Type } from '@earendil-works/pi-ai';\nimport {\n type AnyTask,\n type ConversationId,\n defineExtension,\n defineTool,\n type Extension,\n type Registry,\n type TaskId,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { Agents } from '../agents.ts';\nimport { MEMORY_LIMIT_BYTES, sharedSandbox } from '../codemode/index.ts';\nimport { runTaints } from '../guests/guard.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport type { Layout } from '../layout.ts';\nimport { coneOf } from '../scoops/service.ts';\nimport {\n type Engine,\n KEPT_RUNS,\n type RunHost,\n type RunRecord,\n runTask,\n WorkflowsDoc,\n} from './run.ts';\nimport { buildCode, DEFAULT_CONCURRENCY, maxConcurrency, parseMeta } from './script.ts';\n\nexport { WorkflowsDoc } from './run.ts';\n\nexport const WORKFLOW = 'workflow';\nexport const SAVE_NAME = /^[a-z0-9][a-z0-9-]*$/;\n\nexport type Answer = { code: number; out: string };\n\nexport interface Files {\n dir: string;\n env: Pick<ExecutionEnv, 'readTextFile' | 'writeFile' | 'createDir' | 'fileInfo'>;\n cwd: string;\n}\n\nexport interface RunRequest {\n cone: string;\n from?: number | null;\n files: Files;\n target: string;\n script?: boolean;\n args?: JsonValue;\n budget?: number;\n concurrency?: number;\n}\n\nexport interface WorkflowHost extends RunHost {\n envFor(user: string | null, context: Context): Promise<Files['env']>;\n tasks: { run: AnyTask };\n}\n\nconst ok = (out: string): Answer => ({ code: 0, out });\nconst fail = (out: string, code = 1): Answer => ({ code, out: `workflow: ${out}\\n` });\n\nexport function workflowsDir(home: string): string {\n return `${home}/.slicc/workflows`;\n}\n\nexport function pathOf(files: Files, target: string): string {\n if (SAVE_NAME.test(target) && !target.endsWith('.js'))\n return `${files.dir}/${target}.workflow.js`;\n return resolve(files.cwd, target);\n}\n\nexport function concurrencyOf(value: number | undefined): number {\n const most = maxConcurrency();\n if (value === undefined) return Math.min(DEFAULT_CONCURRENCY, most);\n if (!Number.isFinite(value)) throw new Error('concurrency must be a number');\n return Math.min(most, Math.max(1, Math.trunc(value)));\n}\n\nexport function budgetOf(value: number | undefined): number | null {\n if (value === undefined) return null;\n if (!Number.isFinite(value) || value <= 0) throw new Error('budget must be a positive number');\n return value;\n}\n\nasync function sourceOf(request: RunRequest, context: Context) {\n if (request.script) return { source: request.target, file: null };\n const path = pathOf(request.files, request.target);\n const read = await request.files.env.readTextFile(path, context);\n if (!read.ok) throw new Error(`can't read ${path}: ${read.error.message}`);\n return { source: read.value, file: path };\n}\n\nfunction prune(runs: Record<string, RunRecord>): void {\n const ended = Object.values(runs)\n .filter((run) => run.status !== 'running')\n .sort((a, b) => Number(a.id) - Number(b.id));\n for (const run of ended.slice(0, Math.max(0, ended.length - KEPT_RUNS))) delete runs[run.id];\n}\n\nexport function summary(run: RunRecord): string {\n const budget = run.budget === null ? '' : ` of ${run.budget}`;\n const lines = [\n `run ${run.id}: ${run.name} (${run.status})`,\n `phase: ${run.phase ?? '-'}`,\n `agents: ${run.agents.done} done, ${run.agents.failed} failed, ${run.agents.running.length} running, ${run.agents.started} started`,\n `output tokens: ${run.spent}${budget}`,\n `concurrency: ${run.concurrency}`,\n ];\n if (run.logs.length) lines.push('log:', ...run.logs.slice(-20).map((line) => ` ${line}`));\n if (run.error) lines.push(`error: ${run.error}`);\n if (run.status === 'completed')\n lines.push(`result: ${JSON.stringify(run.result ?? null, null, 2)}`);\n return `${lines.join('\\n')}\\n`;\n}\n\nexport function outcome(run: RunRecord): Answer {\n if (run.status === 'completed') return ok(`${JSON.stringify(run.result ?? null, null, 2)}\\n`);\n if (run.status === 'stopped') return fail(`run ${run.id} was stopped`);\n return fail(`run ${run.id} failed: ${run.error ?? 'unknown error'}`);\n}\n\nexport function createWorkflows(host: Promise<WorkflowHost>) {\n const runs = async (context: Context) => {\n const { harness } = await host;\n return (await harness.snapshot(WorkflowsDoc, context))?.runs ?? {};\n };\n const find = async (id: string, context: Context) => (await runs(context))[id];\n\n async function start(request: RunRequest, context: Context): Promise<string> {\n const { harness, agents } = await host;\n const { source, file } = await sourceOf(request, context);\n const meta = parseMeta(source);\n const budget = budgetOf(request.budget);\n const concurrency = concurrencyOf(request.concurrency);\n const code = buildCode(source, {\n ...(request.args !== undefined ? { args: request.args } : {}),\n budget,\n concurrency,\n });\n const cone = await agents.conversation(request.cone, context);\n if (!cone) throw new Error(`there is no cone ${request.cone}`);\n const from = request.from ?? null;\n const taints = from === null ? [] : await runTaints(harness, from as ConversationId, context);\n return harness.commit(async (tx) => {\n const task = await tx.createTask(\n (await host).tasks.run as never,\n { code },\n {\n ownership: { kind: 'conversation' },\n conversationId: cone.id as ConversationId,\n background: true,\n }\n );\n const doc = await tx.doc(WorkflowsDoc);\n prune(doc.runs as Record<string, RunRecord>);\n const id = String(task);\n doc.runs[id] = {\n id,\n name: meta.name,\n description: meta.description,\n cone: request.cone,\n home: request.files.dir,\n file,\n source,\n budget,\n concurrency,\n status: 'running',\n phase: null,\n started: Date.now(),\n ended: null,\n agents: { started: 0, done: 0, failed: 0, running: [] },\n spent: 0,\n logs: [],\n fromAgent: from !== null,\n taints,\n };\n return id;\n }, context);\n }\n\n async function wait(id: string, context: Context): Promise<RunRecord | undefined> {\n const { harness } = await host;\n if (!(await find(id, context))) return undefined;\n await harness.waitForTask(Number(id) as TaskId, context);\n return find(id, context);\n }\n\n async function stop(id: string, context: Context): Promise<RunRecord | undefined> {\n const { harness } = await host;\n const run = await find(id, context);\n if (run?.status !== 'running') return run;\n await harness.abortTask(Number(id) as TaskId, context);\n return wait(id, context);\n }\n\n async function save(\n id: string,\n name: string,\n force: boolean,\n files: Files,\n context: Context\n ): Promise<Answer> {\n if (!SAVE_NAME.test(name)) return fail(`invalid name ${name} (use [a-z0-9][a-z0-9-]*)`, 2);\n const run = await find(id, context);\n if (!run) return fail(`there is no run ${id}`);\n const path = `${files.dir}/${name}.workflow.js`;\n const exists = await files.env.fileInfo(path, context);\n if (exists.ok && !force) return fail(`${path} already exists (pass --force to overwrite)`);\n const made = await files.env.createDir(files.dir, { recursive: true }, context);\n if (!made.ok) return fail(`can't create ${files.dir}: ${made.error.message}`);\n const written = await files.env.writeFile(path, run.source, context);\n if (!written.ok) return fail(`can't write ${path}: ${written.error.message}`);\n return ok(`saved workflow ${name} to ${path}; run it with agent workflow run ${name}\\n`);\n }\n\n return {\n runs,\n find,\n start,\n wait,\n stop,\n save,\n async list(cone: string | null, context: Context): Promise<RunRecord[]> {\n return Object.values(await runs(context))\n .filter((run) => cone === null || run.cone === cone)\n .sort((a, b) => Number(a.id) - Number(b.id));\n },\n };\n}\n\nexport type Workflows = ReturnType<typeof createWorkflows>;\n\nexport interface Invocation {\n cone: string;\n scoop: boolean;\n from: number | null;\n files: Files;\n}\n\nexport const USAGE = `usage:\n agent workflow run <file.js | name> [--args <json>] [--budget <tokens>] [--concurrency <n>] [--wait]\n agent workflow run --script '<js>' [same options]\n agent workflow list | status <run> | wait <run> | stop <run> | save <run> <name> [--force]\n\nGlobals: agent(prompt, { label, phase, schema, model, effort, agentType }), parallel(thunks),\npipeline(items, ...stages), phase(title), log(message), console, args, budget (output tokens).\n\nRuns a Claude Code .workflow.js as a durable task; it survives a reload. Without --wait it prints\nthe run id. --budget caps output tokens, --concurrency caps agents running at once. save keeps a\nrun's source as ~/.slicc/workflows/<name>.workflow.js, which agent workflow run <name> runs.\n`;\n\nconst VALUES = new Set(['--args', '--budget', '--concurrency', '--script']);\nconst SWITCHES = new Set(['--wait', '--force']);\n\ntype Parsed = { values: Map<string, string>; switches: Set<string>; rest: string[] };\n\nexport function parseArgv(argv: readonly string[]): Parsed {\n const values = new Map<string, string>();\n const switches = new Set<string>();\n const rest: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at] as string;\n if (VALUES.has(arg)) {\n const value = argv[++at];\n if (value === undefined) throw new Error(`${arg} needs a value`);\n values.set(arg, value);\n } else if (SWITCHES.has(arg)) switches.add(arg);\n else if (arg.startsWith('--')) throw new Error(`unknown option ${arg}`);\n else rest.push(arg);\n }\n return { values, switches, rest };\n}\n\nfunction number(parsed: Parsed, flag: string): number | undefined {\n const value = parsed.values.get(flag);\n if (value === undefined) return undefined;\n const found = Number(value);\n if (!Number.isFinite(found)) throw new Error(`${flag} must be a number`);\n return found;\n}\n\nfunction argsOf(parsed: Parsed): JsonValue | undefined {\n const text = parsed.values.get('--args');\n if (text === undefined) return undefined;\n try {\n return JSON.parse(text) as JsonValue;\n } catch {\n throw new Error('--args must be valid JSON');\n }\n}\n\nexport interface RunOptions {\n target?: string;\n script?: string;\n args?: JsonValue;\n budget?: number;\n concurrency?: number;\n wait?: boolean;\n}\n\nexport async function runWorkflow(\n workflows: Workflows,\n who: Invocation,\n options: RunOptions,\n context: Context\n): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot start workflows');\n const target = options.script ?? options.target;\n if (target === undefined) return fail('run needs a <file.js>, a saved name or --script', 2);\n const id = await workflows.start(\n {\n cone: who.cone,\n from: who.from,\n files: who.files,\n target,\n ...(options.script !== undefined ? { script: true } : {}),\n ...(options.args !== undefined ? { args: options.args } : {}),\n ...(options.budget !== undefined ? { budget: options.budget } : {}),\n ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}),\n },\n context\n );\n if (!options.wait)\n return ok(`${id}\\nworkflow run ${id} started; follow it with agent workflow status ${id}\\n`);\n const run = await workflows.wait(id, context);\n return run ? outcome(run) : fail(`run ${id} is gone`);\n}\n\nasync function listed(workflows: Workflows, who: Invocation, context: Context) {\n const rows = await workflows.list(who.cone, context);\n if (!rows.length) return ok('no workflow runs\\n');\n return ok(\n `${rows.map((run) => `${run.id}\\t${run.status}\\t${run.agents.done}/${run.agents.started}\\t${run.name}`).join('\\n')}\\n`\n );\n}\n\nfunction runOptions(parsed: Parsed): RunOptions {\n const args = argsOf(parsed);\n const budget = number(parsed, '--budget');\n const concurrency = number(parsed, '--concurrency');\n const script = parsed.values.get('--script');\n const target = parsed.rest[0];\n return {\n ...(target !== undefined ? { target } : {}),\n ...(script !== undefined ? { script } : {}),\n ...(args !== undefined ? { args } : {}),\n ...(budget !== undefined ? { budget } : {}),\n ...(concurrency !== undefined ? { concurrency } : {}),\n wait: parsed.switches.has('--wait'),\n };\n}\n\ntype Verb = (\n workflows: Workflows,\n who: Invocation,\n parsed: Parsed,\n context: Context\n) => Promise<Answer>;\n\nasync function owned(workflows: Workflows, who: Invocation, id: string, context: Context) {\n const run = await workflows.find(id, context);\n return run && run.cone === who.cone ? run : undefined;\n}\n\nconst VERBS: Record<string, Verb> = {\n run: (workflows, who, parsed, context) =>\n runWorkflow(workflows, who, runOptions(parsed), context),\n list: (workflows, who, _parsed, context) => listed(workflows, who, context),\n async status(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n const run = await owned(workflows, who, id, context);\n return run ? ok(summary(run)) : fail(`there is no run ${id}`);\n },\n async wait(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const run = await workflows.wait(id, context);\n return run ? outcome(run) : fail(`run ${id} is gone`);\n },\n async stop(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (who.scoop) return fail('a scoop cannot stop workflows');\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const run = await workflows.stop(id, context);\n return ok(`run ${id} is ${run?.status ?? 'gone'}\\n`);\n },\n async save(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (who.scoop) return fail('a scoop cannot save workflows');\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const name = parsed.rest[1] ?? '';\n return workflows.save(id, name, parsed.switches.has('--force'), who.files, context);\n },\n};\n\nexport async function command(\n workflows: Workflows,\n who: Invocation,\n argv: readonly string[],\n context: Context\n): Promise<Answer> {\n const [verb, ...rest] = argv;\n const handler = verb === undefined ? undefined : VERBS[verb];\n if (!handler) return { code: verb === 'help' || verb === undefined ? 0 : 2, out: USAGE };\n return handler(workflows, who, parseArgv(rest), context);\n}\n\nexport const TOOL_DESCRIPTION = `Run a Claude Code dynamic workflow (.workflow.js) as a durable background task that survives a reload, or manage runs.\naction run: give file (a path, or the name of a saved workflow) or script (the source). The source starts with \\`export const meta = { name, description }\\`; the body may use top-level await and return a JSON result. Globals: \\`agent(prompt, { label, phase, schema, model: 'provider/model', effort, agentType })\\` runs one scoop and resolves to its answer (JSON matching schema, when given), and rejects when it fails; \\`parallel(thunks)\\` and \\`pipeline(items, ...stages)\\` turn a failed branch into null; \\`phase(title)\\`, \\`log(message)\\`, \\`console.*\\`, \\`args\\`, \\`budget\\` ({ total, spent(), remaining() } in output tokens). No Date.now(), Math.random(), timers, require, fs or nested workflow().\nbudget caps output tokens, concurrency caps agents running at once (default 8). wait: true blocks until the run ends and returns its result; otherwise the run id comes back at once.\naction list | status (run) | stop (run) | save (run, name, force): manage runs; save keeps the source as ~/.slicc/workflows/<name>.workflow.js.`;\n\nconst parameters = Type.Object({\n action: Type.Union([\n Type.Literal('run'),\n Type.Literal('list'),\n Type.Literal('status'),\n Type.Literal('stop'),\n Type.Literal('save'),\n ]),\n file: Type.Optional(Type.String()),\n script: Type.Optional(Type.String()),\n args: Type.Optional(Type.Unknown()),\n budget: Type.Optional(Type.Number()),\n concurrency: Type.Optional(Type.Number()),\n wait: Type.Optional(Type.Boolean()),\n run: Type.Optional(Type.String()),\n name: Type.Optional(Type.String()),\n force: Type.Optional(Type.Boolean()),\n});\n\ntype ToolArgs = {\n action: 'run' | 'list' | 'status' | 'stop' | 'save';\n file?: string;\n script?: string;\n args?: unknown;\n budget?: number;\n concurrency?: number;\n wait?: boolean;\n run?: string;\n name?: string;\n force?: boolean;\n};\n\nexport function toolArgv(args: ToolArgs): string[] {\n const argv: string[] = [args.action];\n if (args.action !== 'run') {\n if (args.run !== undefined) argv.push(args.run);\n if (args.name !== undefined) argv.push(args.name);\n if (args.force) argv.push('--force');\n }\n return argv;\n}\n\nexport function workflowTool(\n workflows: Workflows,\n who: (conversation: number, context: Context) => Promise<Invocation | undefined>\n): ToolRegistration {\n return defineTool({\n name: WORKFLOW,\n description: TOOL_DESCRIPTION,\n parameters,\n async execute(args, api, context) {\n const caller = await who(Number(api.conversationId), context);\n if (!caller) throw new Error('only a cone can use workflows');\n const given = args as ToolArgs;\n const answer =\n given.action === 'run'\n ? await runWorkflow(\n workflows,\n caller,\n {\n ...(given.file !== undefined ? { target: given.file } : {}),\n ...(given.script !== undefined ? { script: given.script } : {}),\n ...(given.args !== undefined ? { args: given.args as JsonValue } : {}),\n ...(given.budget !== undefined ? { budget: given.budget } : {}),\n ...(given.concurrency !== undefined ? { concurrency: given.concurrency } : {}),\n wait: given.wait === true,\n },\n context\n )\n : await command(workflows, caller, toolArgv(given), context);\n return {\n output: [{ type: 'text', text: answer.out }],\n ...(answer.code === 0 ? {} : { isError: true }),\n };\n },\n }) as ToolRegistration;\n}\n\nexport interface WorkflowsSetup {\n workflows: Workflows;\n extension: Extension;\n attach(host: Omit<WorkflowHost, 'tasks'>): void;\n}\n\nexport function setupWorkflows(registry: Registry): WorkflowsSetup {\n let bind: (host: WorkflowHost) => void = () => undefined;\n const host = new Promise<WorkflowHost>((resolve) => {\n bind = resolve;\n });\n const run = runTask(() => host);\n const workflows = createWorkflows(host);\n const who = async (conversation: number, context: Context): Promise<Invocation | undefined> => {\n const bound = await host;\n const cone = coneOf(bound.agents.state(), conversation);\n if (!cone) return undefined;\n const home = bound.layout.homeOf(cone);\n return {\n cone,\n scoop: false,\n from: conversation,\n files: { dir: workflowsDir(home), env: await bound.envFor(cone, context), cwd: home },\n };\n };\n const extension = defineExtension({\n name: 'slicc-workflows',\n tasks: [run],\n tools: [workflowTool(workflows, who)],\n });\n registry.install(extension);\n return {\n workflows,\n extension,\n attach(given) {\n bind({ ...given, tasks: { run: run as AnyTask } });\n },\n };\n}\n\nexport function cliCommand(\n workflows: Workflows,\n layout: Layout,\n env: Files['env'],\n agents: Pick<Agents, 'state'>\n): (\n argv: readonly string[],\n who: { cone: string; scoop: string | null; fromAgent: boolean },\n request: { user?: string | null; cwd: string },\n context: Context\n) => Promise<Answer> {\n return async (argv, who, request, context) => {\n const user = request.user ?? null;\n const files = {\n dir: workflowsDir(layout.homeOf(user)),\n env: (await layout.envFor(user, context)) ?? env,\n cwd: request.cwd,\n };\n const from = who.fromAgent ? (agents.state().cones[who.cone]?.conversation ?? null) : null;\n return command(\n workflows,\n { cone: who.cone, scoop: who.scoop !== null, from, files },\n argv,\n context\n );\n };\n}\n\nexport function workflowEngine(factory = sharedSandbox): () => Engine {\n let engine: Engine | undefined;\n return () => {\n const make = factory();\n if (!make) throw new Error('workflows need the codemode sandbox, which settings turned off');\n engine ??= make({ memoryLimitBytes: MEMORY_LIMIT_BYTES });\n return engine;\n };\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport { Type } from '@earendil-works/pi-ai';\nimport {\n type AnyTask,\n type ConversationId,\n defineExtension,\n defineTool,\n type Extension,\n type Registry,\n type TaskId,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { Agents } from '../agents.ts';\nimport { MEMORY_LIMIT_BYTES, sharedSandbox } from '../codemode/index.ts';\nimport { type InheritedTaint, runTaints } from '../guests/guard.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport type { Layout } from '../layout.ts';\nimport { coneOf } from '../scoops/service.ts';\nimport {\n type Engine,\n KEPT_RUNS,\n type RunHost,\n type RunRecord,\n runTask,\n WorkflowsDoc,\n} from './run.ts';\nimport { buildCode, DEFAULT_CONCURRENCY, maxConcurrency, parseMeta } from './script.ts';\n\nexport { WorkflowsDoc } from './run.ts';\n\nexport const WORKFLOW = 'workflow';\nexport const SAVE_NAME = /^[a-z0-9][a-z0-9-]*$/;\n\nexport type Answer = { code: number; out: string };\n\nexport interface Files {\n dir: string;\n env: Pick<ExecutionEnv, 'readTextFile' | 'writeFile' | 'createDir' | 'fileInfo'>;\n cwd: string;\n}\n\nexport interface RunRequest {\n cone: string;\n from?: number | null;\n taints?: InheritedTaint[];\n files: Files;\n target: string;\n script?: boolean;\n args?: JsonValue;\n budget?: number;\n concurrency?: number;\n}\n\nexport interface WorkflowHost extends RunHost {\n envFor(user: string | null, context: Context): Promise<Files['env']>;\n tasks: { run: AnyTask };\n}\n\nconst ok = (out: string): Answer => ({ code: 0, out });\nconst fail = (out: string, code = 1): Answer => ({ code, out: `workflow: ${out}\\n` });\n\nexport function workflowsDir(home: string): string {\n return `${home}/.slicc/workflows`;\n}\n\nexport function pathOf(files: Files, target: string): string {\n if (SAVE_NAME.test(target) && !target.endsWith('.js'))\n return `${files.dir}/${target}.workflow.js`;\n return resolve(files.cwd, target);\n}\n\nexport function concurrencyOf(value: number | undefined): number {\n const most = maxConcurrency();\n if (value === undefined) return Math.min(DEFAULT_CONCURRENCY, most);\n if (!Number.isFinite(value)) throw new Error('concurrency must be a number');\n return Math.min(most, Math.max(1, Math.trunc(value)));\n}\n\nexport function budgetOf(value: number | undefined): number | null {\n if (value === undefined) return null;\n if (!Number.isFinite(value) || value <= 0) throw new Error('budget must be a positive number');\n return value;\n}\n\nasync function sourceOf(request: RunRequest, context: Context) {\n if (request.script) return { source: request.target, file: null };\n const path = pathOf(request.files, request.target);\n const read = await request.files.env.readTextFile(path, context);\n if (!read.ok) throw new Error(`can't read ${path}: ${read.error.message}`);\n return { source: read.value, file: path };\n}\n\nfunction prune(runs: Record<string, RunRecord>): void {\n const ended = Object.values(runs)\n .filter((run) => run.status !== 'running')\n .sort((a, b) => Number(a.id) - Number(b.id));\n for (const run of ended.slice(0, Math.max(0, ended.length - KEPT_RUNS))) delete runs[run.id];\n}\n\nexport function summary(run: RunRecord): string {\n const budget = run.budget === null ? '' : ` of ${run.budget}`;\n const lines = [\n `run ${run.id}: ${run.name} (${run.status})`,\n `phase: ${run.phase ?? '-'}`,\n `agents: ${run.agents.done} done, ${run.agents.failed} failed, ${run.agents.running.length} running, ${run.agents.started} started`,\n `output tokens: ${run.spent}${budget}`,\n `concurrency: ${run.concurrency}`,\n ];\n if (run.logs.length) lines.push('log:', ...run.logs.slice(-20).map((line) => ` ${line}`));\n if (run.error) lines.push(`error: ${run.error}`);\n if (run.status === 'completed')\n lines.push(`result: ${JSON.stringify(run.result ?? null, null, 2)}`);\n return `${lines.join('\\n')}\\n`;\n}\n\nexport function outcome(run: RunRecord): Answer {\n if (run.status === 'completed') return ok(`${JSON.stringify(run.result ?? null, null, 2)}\\n`);\n if (run.status === 'stopped') return fail(`run ${run.id} was stopped`);\n return fail(`run ${run.id} failed: ${run.error ?? 'unknown error'}`);\n}\n\nexport function createWorkflows(host: Promise<WorkflowHost>) {\n const runs = async (context: Context) => {\n const { harness } = await host;\n return (await harness.snapshot(WorkflowsDoc, context))?.runs ?? {};\n };\n const find = async (id: string, context: Context) => (await runs(context))[id];\n\n async function start(request: RunRequest, context: Context): Promise<string> {\n const { harness, agents } = await host;\n const { source, file } = await sourceOf(request, context);\n const meta = parseMeta(source);\n const budget = budgetOf(request.budget);\n const concurrency = concurrencyOf(request.concurrency);\n const code = buildCode(source, {\n ...(request.args !== undefined ? { args: request.args } : {}),\n budget,\n concurrency,\n });\n const cone = await agents.conversation(request.cone, context);\n if (!cone) throw new Error(`there is no cone ${request.cone}`);\n const from = request.from ?? null;\n const taints =\n request.taints ??\n (from === null ? [] : await runTaints(harness, from as ConversationId, context));\n return harness.commit(async (tx) => {\n const task = await tx.createTask(\n (await host).tasks.run as never,\n { code },\n {\n ownership: { kind: 'conversation' },\n conversationId: cone.id as ConversationId,\n background: true,\n }\n );\n const doc = await tx.doc(WorkflowsDoc);\n prune(doc.runs as Record<string, RunRecord>);\n const id = String(task);\n doc.runs[id] = {\n id,\n name: meta.name,\n description: meta.description,\n cone: request.cone,\n home: request.files.dir,\n file,\n source,\n budget,\n concurrency,\n status: 'running',\n phase: null,\n started: Date.now(),\n ended: null,\n agents: { started: 0, done: 0, failed: 0, running: [] },\n spent: 0,\n logs: [],\n fromAgent: from !== null,\n taints,\n };\n return id;\n }, context);\n }\n\n async function wait(id: string, context: Context): Promise<RunRecord | undefined> {\n const { harness } = await host;\n if (!(await find(id, context))) return undefined;\n await harness.waitForTask(Number(id) as TaskId, context);\n return find(id, context);\n }\n\n async function stop(id: string, context: Context): Promise<RunRecord | undefined> {\n const { harness } = await host;\n const run = await find(id, context);\n if (run?.status !== 'running') return run;\n await harness.abortTask(Number(id) as TaskId, context);\n return wait(id, context);\n }\n\n async function save(\n id: string,\n name: string,\n force: boolean,\n files: Files,\n context: Context\n ): Promise<Answer> {\n if (!SAVE_NAME.test(name)) return fail(`invalid name ${name} (use [a-z0-9][a-z0-9-]*)`, 2);\n const run = await find(id, context);\n if (!run) return fail(`there is no run ${id}`);\n const path = `${files.dir}/${name}.workflow.js`;\n const exists = await files.env.fileInfo(path, context);\n if (exists.ok && !force) return fail(`${path} already exists (pass --force to overwrite)`);\n const made = await files.env.createDir(files.dir, { recursive: true }, context);\n if (!made.ok) return fail(`can't create ${files.dir}: ${made.error.message}`);\n const written = await files.env.writeFile(path, run.source, context);\n if (!written.ok) return fail(`can't write ${path}: ${written.error.message}`);\n return ok(`saved workflow ${name} to ${path}; run it with agent workflow run ${name}\\n`);\n }\n\n return {\n runs,\n find,\n start,\n wait,\n stop,\n save,\n async list(cone: string | null, context: Context): Promise<RunRecord[]> {\n return Object.values(await runs(context))\n .filter((run) => cone === null || run.cone === cone)\n .sort((a, b) => Number(a.id) - Number(b.id));\n },\n };\n}\n\nexport type Workflows = ReturnType<typeof createWorkflows>;\n\nexport interface Invocation {\n cone: string;\n scoop: boolean;\n from: number | null;\n taints?: InheritedTaint[];\n files: Files;\n}\n\nexport const USAGE = `usage:\n agent workflow run <file.js | name> [--args <json>] [--budget <tokens>] [--concurrency <n>] [--wait]\n agent workflow run --script '<js>' [same options]\n agent workflow list | status <run> | wait <run> | stop <run> | save <run> <name> [--force]\n\nGlobals: agent(prompt, { label, phase, schema, model, effort, agentType }), parallel(thunks),\npipeline(items, ...stages), phase(title), log(message), console, args, budget (output tokens).\n\nRuns a Claude Code .workflow.js as a durable task; it survives a reload. Without --wait it prints\nthe run id. --budget caps output tokens, --concurrency caps agents running at once. save keeps a\nrun's source as ~/.slicc/workflows/<name>.workflow.js, which agent workflow run <name> runs.\n`;\n\nconst VALUES = new Set(['--args', '--budget', '--concurrency', '--script']);\nconst SWITCHES = new Set(['--wait', '--force']);\n\ntype Parsed = { values: Map<string, string>; switches: Set<string>; rest: string[] };\n\nexport function parseArgv(argv: readonly string[]): Parsed {\n const values = new Map<string, string>();\n const switches = new Set<string>();\n const rest: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at] as string;\n if (VALUES.has(arg)) {\n const value = argv[++at];\n if (value === undefined) throw new Error(`${arg} needs a value`);\n values.set(arg, value);\n } else if (SWITCHES.has(arg)) switches.add(arg);\n else if (arg.startsWith('--')) throw new Error(`unknown option ${arg}`);\n else rest.push(arg);\n }\n return { values, switches, rest };\n}\n\nfunction number(parsed: Parsed, flag: string): number | undefined {\n const value = parsed.values.get(flag);\n if (value === undefined) return undefined;\n const found = Number(value);\n if (!Number.isFinite(found)) throw new Error(`${flag} must be a number`);\n return found;\n}\n\nfunction argsOf(parsed: Parsed): JsonValue | undefined {\n const text = parsed.values.get('--args');\n if (text === undefined) return undefined;\n try {\n return JSON.parse(text) as JsonValue;\n } catch {\n throw new Error('--args must be valid JSON');\n }\n}\n\nexport interface RunOptions {\n target?: string;\n script?: string;\n args?: JsonValue;\n budget?: number;\n concurrency?: number;\n wait?: boolean;\n}\n\nexport async function runWorkflow(\n workflows: Workflows,\n who: Invocation,\n options: RunOptions,\n context: Context\n): Promise<Answer> {\n if (who.scoop) return fail('a scoop cannot start workflows');\n const target = options.script ?? options.target;\n if (target === undefined) return fail('run needs a <file.js>, a saved name or --script', 2);\n const id = await workflows.start(\n {\n cone: who.cone,\n from: who.from,\n ...(who.taints ? { taints: who.taints } : {}),\n files: who.files,\n target,\n ...(options.script !== undefined ? { script: true } : {}),\n ...(options.args !== undefined ? { args: options.args } : {}),\n ...(options.budget !== undefined ? { budget: options.budget } : {}),\n ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}),\n },\n context\n );\n if (!options.wait)\n return ok(`${id}\\nworkflow run ${id} started; follow it with agent workflow status ${id}\\n`);\n const run = await workflows.wait(id, context);\n return run ? outcome(run) : fail(`run ${id} is gone`);\n}\n\nasync function listed(workflows: Workflows, who: Invocation, context: Context) {\n const rows = await workflows.list(who.cone, context);\n if (!rows.length) return ok('no workflow runs\\n');\n return ok(\n `${rows.map((run) => `${run.id}\\t${run.status}\\t${run.agents.done}/${run.agents.started}\\t${run.name}`).join('\\n')}\\n`\n );\n}\n\nfunction runOptions(parsed: Parsed): RunOptions {\n const args = argsOf(parsed);\n const budget = number(parsed, '--budget');\n const concurrency = number(parsed, '--concurrency');\n const script = parsed.values.get('--script');\n const target = parsed.rest[0];\n return {\n ...(target !== undefined ? { target } : {}),\n ...(script !== undefined ? { script } : {}),\n ...(args !== undefined ? { args } : {}),\n ...(budget !== undefined ? { budget } : {}),\n ...(concurrency !== undefined ? { concurrency } : {}),\n wait: parsed.switches.has('--wait'),\n };\n}\n\ntype Verb = (\n workflows: Workflows,\n who: Invocation,\n parsed: Parsed,\n context: Context\n) => Promise<Answer>;\n\nasync function owned(workflows: Workflows, who: Invocation, id: string, context: Context) {\n const run = await workflows.find(id, context);\n return run && run.cone === who.cone ? run : undefined;\n}\n\nconst VERBS: Record<string, Verb> = {\n run: (workflows, who, parsed, context) =>\n runWorkflow(workflows, who, runOptions(parsed), context),\n list: (workflows, who, _parsed, context) => listed(workflows, who, context),\n async status(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n const run = await owned(workflows, who, id, context);\n return run ? ok(summary(run)) : fail(`there is no run ${id}`);\n },\n async wait(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const run = await workflows.wait(id, context);\n return run ? outcome(run) : fail(`run ${id} is gone`);\n },\n async stop(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (who.scoop) return fail('a scoop cannot stop workflows');\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const run = await workflows.stop(id, context);\n return ok(`run ${id} is ${run?.status ?? 'gone'}\\n`);\n },\n async save(workflows, who, parsed, context) {\n const id = parsed.rest[0] ?? '';\n if (who.scoop) return fail('a scoop cannot save workflows');\n if (!(await owned(workflows, who, id, context))) return fail(`there is no run ${id}`);\n const name = parsed.rest[1] ?? '';\n return workflows.save(id, name, parsed.switches.has('--force'), who.files, context);\n },\n};\n\nexport async function command(\n workflows: Workflows,\n who: Invocation,\n argv: readonly string[],\n context: Context\n): Promise<Answer> {\n const [verb, ...rest] = argv;\n const handler = verb === undefined ? undefined : VERBS[verb];\n if (!handler) return { code: verb === 'help' || verb === undefined ? 0 : 2, out: USAGE };\n return handler(workflows, who, parseArgv(rest), context);\n}\n\nexport const TOOL_DESCRIPTION = `Run a Claude Code dynamic workflow (.workflow.js) as a durable background task that survives a reload, or manage runs.\naction run: give file (a path, or the name of a saved workflow) or script (the source). The source starts with \\`export const meta = { name, description }\\`; the body may use top-level await and return a JSON result. Globals: \\`agent(prompt, { label, phase, schema, model: 'provider/model', effort, agentType })\\` runs one scoop and resolves to its answer (JSON matching schema, when given), and rejects when it fails; \\`parallel(thunks)\\` and \\`pipeline(items, ...stages)\\` turn a failed branch into null; \\`phase(title)\\`, \\`log(message)\\`, \\`console.*\\`, \\`args\\`, \\`budget\\` ({ total, spent(), remaining() } in output tokens). No Date.now(), Math.random(), timers, require, fs or nested workflow().\nbudget caps output tokens, concurrency caps agents running at once (default 8). wait: true blocks until the run ends and returns its result; otherwise the run id comes back at once.\naction list | status (run) | stop (run) | save (run, name, force): manage runs; save keeps the source as ~/.slicc/workflows/<name>.workflow.js.`;\n\nconst parameters = Type.Object({\n action: Type.Union([\n Type.Literal('run'),\n Type.Literal('list'),\n Type.Literal('status'),\n Type.Literal('stop'),\n Type.Literal('save'),\n ]),\n file: Type.Optional(Type.String()),\n script: Type.Optional(Type.String()),\n args: Type.Optional(Type.Unknown()),\n budget: Type.Optional(Type.Number()),\n concurrency: Type.Optional(Type.Number()),\n wait: Type.Optional(Type.Boolean()),\n run: Type.Optional(Type.String()),\n name: Type.Optional(Type.String()),\n force: Type.Optional(Type.Boolean()),\n});\n\ntype ToolArgs = {\n action: 'run' | 'list' | 'status' | 'stop' | 'save';\n file?: string;\n script?: string;\n args?: unknown;\n budget?: number;\n concurrency?: number;\n wait?: boolean;\n run?: string;\n name?: string;\n force?: boolean;\n};\n\nexport function toolArgv(args: ToolArgs): string[] {\n const argv: string[] = [args.action];\n if (args.action !== 'run') {\n if (args.run !== undefined) argv.push(args.run);\n if (args.name !== undefined) argv.push(args.name);\n if (args.force) argv.push('--force');\n }\n return argv;\n}\n\nexport function workflowTool(\n workflows: Workflows,\n who: (conversation: number, context: Context) => Promise<Invocation | undefined>\n): ToolRegistration {\n return defineTool({\n name: WORKFLOW,\n description: TOOL_DESCRIPTION,\n parameters,\n async execute(args, api, context) {\n const caller = await who(Number(api.conversationId), context);\n if (!caller) throw new Error('only a cone can use workflows');\n const given = args as ToolArgs;\n const answer =\n given.action === 'run'\n ? await runWorkflow(\n workflows,\n caller,\n {\n ...(given.file !== undefined ? { target: given.file } : {}),\n ...(given.script !== undefined ? { script: given.script } : {}),\n ...(given.args !== undefined ? { args: given.args as JsonValue } : {}),\n ...(given.budget !== undefined ? { budget: given.budget } : {}),\n ...(given.concurrency !== undefined ? { concurrency: given.concurrency } : {}),\n wait: given.wait === true,\n },\n context\n )\n : await command(workflows, caller, toolArgv(given), context);\n return {\n output: [{ type: 'text', text: answer.out }],\n ...(answer.code === 0 ? {} : { isError: true }),\n };\n },\n }) as ToolRegistration;\n}\n\nexport interface WorkflowsSetup {\n workflows: Workflows;\n extension: Extension;\n attach(host: Omit<WorkflowHost, 'tasks'>): void;\n}\n\nexport function setupWorkflows(registry: Registry): WorkflowsSetup {\n let bind: (host: WorkflowHost) => void = () => undefined;\n const host = new Promise<WorkflowHost>((resolve) => {\n bind = resolve;\n });\n const run = runTask(() => host);\n const workflows = createWorkflows(host);\n const who = async (conversation: number, context: Context): Promise<Invocation | undefined> => {\n const bound = await host;\n const cone = coneOf(bound.agents.state(), conversation);\n if (!cone) return undefined;\n const home = bound.layout.homeOf(cone);\n return {\n cone,\n scoop: false,\n from: conversation,\n files: { dir: workflowsDir(home), env: await bound.envFor(cone, context), cwd: home },\n };\n };\n const extension = defineExtension({\n name: 'slicc-workflows',\n tasks: [run],\n tools: [workflowTool(workflows, who)],\n });\n registry.install(extension);\n return {\n workflows,\n extension,\n attach(given) {\n bind({ ...given, tasks: { run: run as AnyTask } });\n },\n };\n}\n\nexport function cliCommand(\n workflows: Workflows,\n layout: Layout,\n env: Files['env'],\n agents: Pick<Agents, 'state'>\n): (\n argv: readonly string[],\n who: { cone: string; scoop: string | null; fromAgent: boolean; taints: InheritedTaint[] },\n request: { user?: string | null; cwd: string },\n context: Context\n) => Promise<Answer> {\n return async (argv, who, request, context) => {\n const user = request.user ?? null;\n const files = {\n dir: workflowsDir(layout.homeOf(user)),\n env: (await layout.envFor(user, context)) ?? env,\n cwd: request.cwd,\n };\n const from = who.fromAgent ? (agents.state().cones[who.cone]?.conversation ?? null) : null;\n return command(\n workflows,\n { cone: who.cone, scoop: who.scoop !== null, from, taints: who.taints, files },\n argv,\n context\n );\n };\n}\n\nexport function workflowEngine(factory = sharedSandbox): () => Engine {\n let engine: Engine | undefined;\n return () => {\n const make = factory();\n if (!make) throw new Error('workflows need the codemode sandbox, which settings turned off');\n engine ??= make({ memoryLimitBytes: MEMORY_LIMIT_BYTES });\n return engine;\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["WorkflowsDoc", "resolve"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-agent",
|
|
3
|
-
"version": "6.19.
|
|
3
|
+
"version": "6.19.3",
|
|
4
4
|
"description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"release": "semantic-release"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@ai-ecoverse/slicc-kernel": "1.143.
|
|
68
|
+
"@ai-ecoverse/slicc-kernel": "1.143.4",
|
|
69
69
|
"@ai-ecoverse/slicc-scrub": "1.0.0",
|
|
70
|
-
"@ai-ecoverse/slicc-shared-web": "1.30.
|
|
70
|
+
"@ai-ecoverse/slicc-shared-web": "1.30.2",
|
|
71
71
|
"@ai-ecoverse/slicc-spectrum": "1.104.3",
|
|
72
72
|
"@ai-ecoverse/wasi-fnox": "1.39.0-6",
|
|
73
73
|
"@ai-ecoverse/wasm-bash": "5.3.0-22",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"typescript": "7.0.2"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@ai-ecoverse/slicc-browsers": "1.16.
|
|
88
|
+
"@ai-ecoverse/slicc-browsers": "1.16.1",
|
|
89
89
|
"@ai-ecoverse/slicc-vault": "1.15.2",
|
|
90
90
|
"@aws-sdk/middleware-websocket": "^3.972.54",
|
|
91
91
|
"@earendil-works/chord": "1.3.0",
|