@ai-ecoverse/slicc-agent 6.19.4 → 6.19.6
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 +3 -3
- package/dist/guests/guard.js +27 -2
- package/dist/guests/guard.js.map +2 -2
- package/dist/kernel/groups.js +5 -1
- package/dist/kernel/groups.js.map +2 -2
- package/dist/kernel/lineage.js +54 -0
- package/dist/kernel/lineage.js.map +7 -0
- package/dist/licks/licks.js +19 -3
- package/dist/licks/licks.js.map +2 -2
- package/dist/licks/sources.js +2 -1
- package/dist/licks/sources.js.map +2 -2
- package/dist/scoops/cli.js +66 -19
- package/dist/scoops/cli.js.map +2 -2
- package/dist/scoops/extension.js +44 -16
- package/dist/scoops/extension.js.map +2 -2
- package/dist/scoops/service.js +8 -6
- package/dist/scoops/service.js.map +2 -2
- package/dist/scoops/taints.js +2 -6
- package/dist/scoops/taints.js.map +2 -2
- package/dist/types/guests/guard.d.ts +5 -0
- package/dist/types/kernel/client.d.ts +2 -0
- package/dist/types/kernel/groups.d.ts +3 -1
- package/dist/types/kernel/lineage.d.ts +12 -0
- package/dist/types/licks/licks.d.ts +3 -0
- package/dist/types/licks/sources.d.ts +2 -0
- package/dist/types/scoops/cli.d.ts +2 -1
- package/dist/types/scoops/extension.d.ts +5 -1
- package/dist/types/scoops/service.d.ts +3 -2
- package/dist/types/scoops/taints.d.ts +1 -1
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/licks/sources.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Conversation, Harness, TaskId } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Activity } from '../kernel/activity.ts';\nimport type { Jobs } from '../kernel/jobs.ts';\nimport { ROOT_USER } from '../layout.ts';\nimport { type Attachment, attachmentPart } from './attachment.ts';\nimport { type BootFacts, booting, LicksHostDoc } from './boot.ts';\nimport { type ConfigError, parseWebhook, type WebhookEntry } from './config.ts';\nimport {\n type CronJob,\n installJobs,\n type LegacyJob,\n legacyJobs,\n relickJobs,\n sendCommand,\n} from './crontab.ts';\nimport { type ConfigFiles, configFiles, Watches } from './fswatch.ts';\nimport type { LickChannel, LickTarget } from './lick.ts';\nimport type { LickEvent, Licks } from './licks.ts';\n\nexport const SLICC_DIR = '.slicc';\n\nexport interface LickSourcesOptions {\n harness: Harness;\n root: Conversation;\n cone: () => Conversation;\n env: ExecutionEnv;\n home: string;\n licks: Licks;\n flushEvery?: number;\n activity?: Activity;\n jobs?: Jobs;\n dirs?: () => readonly LickDir[] | Promise<readonly LickDir[]>;\n cronUser?: (target: LickTarget, place: LickDir) => string | undefined;\n fetch?: typeof fetch;\n}\n\nexport interface LickDir {\n dir: string;\n home: string;\n cone: string | null;\n env?: ExecutionEnv;\n}\n\nexport function scopedTarget(target: LickTarget, cone: string | null): LickTarget {\n return cone && target === 'cone' ? (`cone:${cone}` as LickTarget) : target;\n}\n\nexport function scopedName(name: string, cone: string | null): string {\n return cone ? `${cone}:${name}` : name;\n}\n\nfunction scoped<T extends { name: string; target: LickTarget }>(entry: T, cone: string | null): T {\n return { ...entry, name: scopedName(entry.name, cone), target: scopedTarget(entry.target, cone) };\n}\n\nexport interface WebhookDelivery {\n id?: string;\n headers?: Record<string, string>;\n body: unknown;\n verified?: boolean;\n attachment?: Attachment;\n}\n\nexport async function withAttachment(\n delivery: WebhookDelivery,\n fetcher: typeof fetch | undefined\n): Promise<WebhookDelivery> {\n const { attachment, ...rest } = delivery;\n if (!attachment) return delivery;\n const part = await attachmentPart(attachment, fetcher);\n return { ...rest, body: [rest.body, part].filter(Boolean).join('\\n\\n') };\n}\n\nexport interface LickSources {\n start(context: Context): Promise<void>;\n reconcile(context: Context): Promise<void>;\n boot(facts: BootFacts, context: Context): Promise<void>;\n webhook(name: string, delivery: WebhookDelivery, context: Context): Promise<boolean>;\n close(context: Context): Promise<void>;\n}\n\nexport function hash(text: string): string {\n let value = 2166136261;\n for (let at = 0; at < text.length; at++) value = Math.imul(value ^ text.charCodeAt(at), 16777619);\n return (value >>> 0).toString(36);\n}\n\nexport function shortPath(path: string, home: string): string {\n return path === home || path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;\n}\n\nexport function configLick(\n error: ConfigError,\n home: string,\n cone: string | null = null\n): LickEvent {\n const file = shortPath(error.file, home);\n const channel: LickChannel = error.file.includes('/watches/')\n ? 'fswatch'\n : error.file.includes('/webhooks/')\n ? 'webhook'\n : 'cron';\n const text = `${error.line ? `line ${error.line}: ` : ''}${error.error}`;\n return {\n channel,\n source: `config:${file}`,\n title: `Invalid ${file}`,\n text,\n body: error.file.endsWith('/crontab.migrated')\n ? \"Its jobs in the kernel crontab still lack --lick=cron, so they don't fire as cron licks; add it with crontab -.\"\n : channel === 'cron'\n ? 'Not moved into the kernel crontab until the file is fixed; the installed crontab is unchanged.\\nThe format is in the slicc-agent README.'\n : 'Ignored until the file is fixed.\\nThe formats are in the slicc-agent README.',\n target: scopedTarget('cone', cone),\n severity: 'error',\n eventId: hash(`${file}\\n${text}`),\n };\n}\n\nexport const UNVERIFIED = \"verified: false (the gateway couldn't check this request's signature)\";\n\nexport function webhookLick(\n name: string,\n entry: WebhookEntry,\n delivery: WebhookDelivery\n): LickEvent {\n const payload =\n typeof delivery.body === 'string' ? delivery.body : JSON.stringify(delivery.body, null, 2);\n const headers = Object.entries(delivery.headers ?? {})\n .map(([key, value]) => `${key}: ${value}`)\n .join('\\n');\n return {\n channel: 'webhook',\n source: name,\n title: name,\n text: entry.message || `Webhook ${name} received a request`,\n body: [delivery.verified === false ? UNVERIFIED : '', headers, payload]\n .filter(Boolean)\n .join('\\n\\n'),\n target: entry.target,\n coalesce: false,\n ...(delivery.id ? { eventId: delivery.id } : {}),\n ...(entry.triage ? { triage: entry.triage } : {}),\n };\n}\n\nasync function webhooksIn(\n files: ConfigFiles,\n dir: string,\n context: Context\n): Promise<{ entries: Map<string, WebhookEntry>; errors: ConfigError[] }> {\n const errors: ConfigError[] = [];\n const into = new Map<string, WebhookEntry>();\n for (const name of await files.list(dir, context)) {\n if (name.endsWith('.v6')) continue;\n const file = `${dir}/${name}`;\n const json = await files.read(file, context);\n if (json === undefined) continue;\n try {\n const entry = parseWebhook(file, json);\n into.set(entry.name, entry);\n } catch (error) {\n errors.push({ file, error: (error as Error).message });\n }\n }\n return { entries: into, errors };\n}\n\nexport function createLickSources(options: LickSourcesOptions): LickSources {\n const { harness, env, licks, home } = options;\n const files = configFiles(env);\n const deliver = (event: LickEvent, context: Context) => licks.deliver(event, context);\n const boots = booting(harness, options.cone, deliver, options.jobs);\n const dirsOf = options.dirs ?? (() => [{ dir: `${home}/${SLICC_DIR}`, home, cone: null }]);\n const watching = new Map<string, Watches>();\n const watchesOf = (place: LickDir) => {\n let found = watching.get(place.dir);\n if (!found) {\n const retarget = (event: LickEvent, context: Context) =>\n deliver({ ...event, target: scopedTarget(event.target, place.cone) }, context);\n found = new Watches(place.env ?? env, retarget, place.home, options.activity);\n watching.set(place.dir, found);\n }\n return found;\n };\n let webhooks = new Map<string, WebhookEntry>();\n const relicked = new Set<string>();\n let control: FileWatcher | undefined;\n let controlled = '';\n let reconcileTimer: ReturnType<typeof setTimeout> | undefined;\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n let lock: Promise<unknown> = Promise.resolve();\n const serial = <T>(operation: () => Promise<T>): Promise<T> => {\n const run = lock.then(operation, operation);\n lock = run.catch(() => undefined);\n return run;\n };\n\n async function reconcileNow(context: Context): Promise<void> {\n if (closed) return;\n const places = await dirsOf();\n const errors: { error: ConfigError; place: LickDir }[] = [];\n const hooks = new Map<string, WebhookEntry>();\n for (const place of places) {\n const crontab = [...(await relick(place, context)), ...(await migrate(place, context))];\n const watchErrors = await watchesOf(place).reconcile(`${place.dir}/watches`, context);\n const found = await webhooksIn(files, `${place.dir}/webhooks`, context);\n for (const entry of found.entries.values()) {\n const named = scoped(entry, place.cone);\n hooks.set(named.name, named);\n }\n for (const error of [...crontab, ...watchErrors, ...found.errors])\n errors.push({ error, place });\n }\n for (const [dir, watches] of [...watching])\n if (!places.some((place) => place.dir === dir)) {\n watching.delete(dir);\n await watches.close(context);\n }\n webhooks = hooks;\n for (const { error, place } of errors)\n await deliver(configLick(error, place.home, place.cone), context);\n await watchControl(places, context);\n }\n\n function byUser(place: LickDir, jobs: readonly LegacyJob[]): Map<string, LegacyJob[]> {\n const users = new Map<string, LegacyJob[]>();\n for (const job of jobs) {\n const user = options.cronUser?.(job.target, place) ?? place.cone ?? ROOT_USER;\n users.set(user, [...(users.get(user) ?? []), job]);\n }\n return users;\n }\n\n async function relick(place: LickDir, context: Context): Promise<ConfigError[]> {\n if (relicked.has(place.dir)) return [];\n relicked.add(place.dir);\n const file = `${place.dir}/crontab.migrated`;\n const text = await files.read(file, context);\n if (text === undefined) return [];\n const errors: ConfigError[] = [];\n for (const [user, list] of byUser(place, legacyJobs(text).jobs))\n for (const problem of await relickJobs(env, user, list, context))\n errors.push({ file, ...problem });\n return errors;\n }\n\n async function migrate(place: LickDir, context: Context): Promise<ConfigError[]> {\n const file = `${place.dir}/crontab`;\n const text = await files.read(file, context);\n if (!text?.trim()) return [];\n const { jobs, problems } = legacyJobs(text);\n if (problems.length) return problems.map((problem) => ({ file, ...problem }));\n const users = new Map<string, CronJob[]>();\n for (const [user, list] of byUser(place, jobs))\n users.set(\n user,\n list.map((job) => ({\n name: job.name,\n schedule: job.schedule,\n command: sendCommand(job.target, job.message),\n line: job.line,\n }))\n );\n const errors: ConfigError[] = [];\n for (const [user, list] of users)\n for (const problem of await installJobs(env, user, list, context))\n errors.push({ file, ...problem });\n if (errors.length) return errors;\n await env.writeFile(`${file}.migrated`, text, context);\n await env.remove(file, { force: true }, context);\n return [];\n }\n\n async function retire(context: Context): Promise<void> {\n const stored = (await harness.snapshot(LicksHostDoc, context))?.cron ?? {};\n const records = Object.values(stored);\n if (!records.length) return;\n for (const record of records)\n await harness.abortTask(record.task as TaskId, context).catch(() => undefined);\n await harness.commit(async (tx) => {\n (await tx.doc(LicksHostDoc)).cron = {};\n }, context);\n }\n\n async function watchControl(places: readonly LickDir[], context: Context): Promise<void> {\n const key = places.map((place) => place.dir).join('\\n');\n if (key === controlled || closed) return;\n controlled = key;\n await control?.close(context);\n const result = await env.watch(\n places.map((place) => ({ path: place.dir, recursive: true })),\n () => scheduleReconcile(context),\n context\n );\n control = result.ok ? result.value : undefined;\n }\n\n const reconcile = (context: Context) => serial(() => reconcileNow(context));\n\n function scheduleReconcile(context: Context): void {\n clearTimeout(reconcileTimer);\n reconcileTimer = setTimeout(() => {\n void reconcile(context).catch(() => undefined);\n }, 300);\n }\n\n async function flushIfWaiting(context: Context): Promise<void> {\n if (await licks.pending(context)) await licks.flush(context);\n }\n\n return {\n async start(context) {\n await licks.flush(context);\n await retire(context);\n await reconcile(context);\n flushTimer = setInterval(() => {\n void flushIfWaiting(context).catch(() => undefined);\n }, options.flushEvery ?? 2000);\n },\n reconcile,\n boot: boots.boot,\n async webhook(name, delivery, context) {\n const entry = webhooks.get(name);\n if (!entry) return false;\n await deliver(\n webhookLick(name, entry, await withAttachment(delivery, options.fetch)),\n context\n );\n return true;\n },\n async close(context) {\n closed = true;\n boots.stop();\n clearTimeout(reconcileTimer);\n clearInterval(flushTimer);\n await control?.close(context);\n for (const watches of watching.values()) await watches.close(context);\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Conversation, Harness, TaskId } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { InheritedTaint } from '../guests/guard.ts';\nimport type { Activity } from '../kernel/activity.ts';\nimport type { Jobs } from '../kernel/jobs.ts';\nimport { ROOT_USER } from '../layout.ts';\nimport { type Attachment, attachmentPart } from './attachment.ts';\nimport { type BootFacts, booting, LicksHostDoc } from './boot.ts';\nimport { type ConfigError, parseWebhook, type WebhookEntry } from './config.ts';\nimport {\n type CronJob,\n installJobs,\n type LegacyJob,\n legacyJobs,\n relickJobs,\n sendCommand,\n} from './crontab.ts';\nimport { type ConfigFiles, configFiles, Watches } from './fswatch.ts';\nimport type { LickChannel, LickTarget } from './lick.ts';\nimport type { LickEvent, Licks } from './licks.ts';\n\nexport const SLICC_DIR = '.slicc';\n\nexport interface LickSourcesOptions {\n harness: Harness;\n root: Conversation;\n cone: () => Conversation;\n env: ExecutionEnv;\n home: string;\n licks: Licks;\n flushEvery?: number;\n activity?: Activity;\n jobs?: Jobs;\n dirs?: () => readonly LickDir[] | Promise<readonly LickDir[]>;\n cronUser?: (target: LickTarget, place: LickDir) => string | undefined;\n fetch?: typeof fetch;\n}\n\nexport interface LickDir {\n dir: string;\n home: string;\n cone: string | null;\n env?: ExecutionEnv;\n}\n\nexport function scopedTarget(target: LickTarget, cone: string | null): LickTarget {\n return cone && target === 'cone' ? (`cone:${cone}` as LickTarget) : target;\n}\n\nexport function scopedName(name: string, cone: string | null): string {\n return cone ? `${cone}:${name}` : name;\n}\n\nfunction scoped<T extends { name: string; target: LickTarget }>(entry: T, cone: string | null): T {\n return { ...entry, name: scopedName(entry.name, cone), target: scopedTarget(entry.target, cone) };\n}\n\nexport interface WebhookDelivery {\n id?: string;\n headers?: Record<string, string>;\n body: unknown;\n verified?: boolean;\n attachment?: Attachment;\n taints?: readonly InheritedTaint[];\n}\n\nexport async function withAttachment(\n delivery: WebhookDelivery,\n fetcher: typeof fetch | undefined\n): Promise<WebhookDelivery> {\n const { attachment, ...rest } = delivery;\n if (!attachment) return delivery;\n const part = await attachmentPart(attachment, fetcher);\n return { ...rest, body: [rest.body, part].filter(Boolean).join('\\n\\n') };\n}\n\nexport interface LickSources {\n start(context: Context): Promise<void>;\n reconcile(context: Context): Promise<void>;\n boot(facts: BootFacts, context: Context): Promise<void>;\n webhook(name: string, delivery: WebhookDelivery, context: Context): Promise<boolean>;\n close(context: Context): Promise<void>;\n}\n\nexport function hash(text: string): string {\n let value = 2166136261;\n for (let at = 0; at < text.length; at++) value = Math.imul(value ^ text.charCodeAt(at), 16777619);\n return (value >>> 0).toString(36);\n}\n\nexport function shortPath(path: string, home: string): string {\n return path === home || path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;\n}\n\nexport function configLick(\n error: ConfigError,\n home: string,\n cone: string | null = null\n): LickEvent {\n const file = shortPath(error.file, home);\n const channel: LickChannel = error.file.includes('/watches/')\n ? 'fswatch'\n : error.file.includes('/webhooks/')\n ? 'webhook'\n : 'cron';\n const text = `${error.line ? `line ${error.line}: ` : ''}${error.error}`;\n return {\n channel,\n source: `config:${file}`,\n title: `Invalid ${file}`,\n text,\n body: error.file.endsWith('/crontab.migrated')\n ? \"Its jobs in the kernel crontab still lack --lick=cron, so they don't fire as cron licks; add it with crontab -.\"\n : channel === 'cron'\n ? 'Not moved into the kernel crontab until the file is fixed; the installed crontab is unchanged.\\nThe format is in the slicc-agent README.'\n : 'Ignored until the file is fixed.\\nThe formats are in the slicc-agent README.',\n target: scopedTarget('cone', cone),\n severity: 'error',\n eventId: hash(`${file}\\n${text}`),\n };\n}\n\nexport const UNVERIFIED = \"verified: false (the gateway couldn't check this request's signature)\";\n\nexport function webhookLick(\n name: string,\n entry: WebhookEntry,\n delivery: WebhookDelivery\n): LickEvent {\n const payload =\n typeof delivery.body === 'string' ? delivery.body : JSON.stringify(delivery.body, null, 2);\n const headers = Object.entries(delivery.headers ?? {})\n .map(([key, value]) => `${key}: ${value}`)\n .join('\\n');\n return {\n channel: 'webhook',\n source: name,\n title: name,\n text: entry.message || `Webhook ${name} received a request`,\n body: [delivery.verified === false ? UNVERIFIED : '', headers, payload]\n .filter(Boolean)\n .join('\\n\\n'),\n target: entry.target,\n coalesce: false,\n ...(delivery.id ? { eventId: delivery.id } : {}),\n ...(entry.triage ? { triage: entry.triage } : {}),\n ...(delivery.taints?.length ? { taints: delivery.taints } : {}),\n };\n}\n\nasync function webhooksIn(\n files: ConfigFiles,\n dir: string,\n context: Context\n): Promise<{ entries: Map<string, WebhookEntry>; errors: ConfigError[] }> {\n const errors: ConfigError[] = [];\n const into = new Map<string, WebhookEntry>();\n for (const name of await files.list(dir, context)) {\n if (name.endsWith('.v6')) continue;\n const file = `${dir}/${name}`;\n const json = await files.read(file, context);\n if (json === undefined) continue;\n try {\n const entry = parseWebhook(file, json);\n into.set(entry.name, entry);\n } catch (error) {\n errors.push({ file, error: (error as Error).message });\n }\n }\n return { entries: into, errors };\n}\n\nexport function createLickSources(options: LickSourcesOptions): LickSources {\n const { harness, env, licks, home } = options;\n const files = configFiles(env);\n const deliver = (event: LickEvent, context: Context) => licks.deliver(event, context);\n const boots = booting(harness, options.cone, deliver, options.jobs);\n const dirsOf = options.dirs ?? (() => [{ dir: `${home}/${SLICC_DIR}`, home, cone: null }]);\n const watching = new Map<string, Watches>();\n const watchesOf = (place: LickDir) => {\n let found = watching.get(place.dir);\n if (!found) {\n const retarget = (event: LickEvent, context: Context) =>\n deliver({ ...event, target: scopedTarget(event.target, place.cone) }, context);\n found = new Watches(place.env ?? env, retarget, place.home, options.activity);\n watching.set(place.dir, found);\n }\n return found;\n };\n let webhooks = new Map<string, WebhookEntry>();\n const relicked = new Set<string>();\n let control: FileWatcher | undefined;\n let controlled = '';\n let reconcileTimer: ReturnType<typeof setTimeout> | undefined;\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n let closed = false;\n let lock: Promise<unknown> = Promise.resolve();\n const serial = <T>(operation: () => Promise<T>): Promise<T> => {\n const run = lock.then(operation, operation);\n lock = run.catch(() => undefined);\n return run;\n };\n\n async function reconcileNow(context: Context): Promise<void> {\n if (closed) return;\n const places = await dirsOf();\n const errors: { error: ConfigError; place: LickDir }[] = [];\n const hooks = new Map<string, WebhookEntry>();\n for (const place of places) {\n const crontab = [...(await relick(place, context)), ...(await migrate(place, context))];\n const watchErrors = await watchesOf(place).reconcile(`${place.dir}/watches`, context);\n const found = await webhooksIn(files, `${place.dir}/webhooks`, context);\n for (const entry of found.entries.values()) {\n const named = scoped(entry, place.cone);\n hooks.set(named.name, named);\n }\n for (const error of [...crontab, ...watchErrors, ...found.errors])\n errors.push({ error, place });\n }\n for (const [dir, watches] of [...watching])\n if (!places.some((place) => place.dir === dir)) {\n watching.delete(dir);\n await watches.close(context);\n }\n webhooks = hooks;\n for (const { error, place } of errors)\n await deliver(configLick(error, place.home, place.cone), context);\n await watchControl(places, context);\n }\n\n function byUser(place: LickDir, jobs: readonly LegacyJob[]): Map<string, LegacyJob[]> {\n const users = new Map<string, LegacyJob[]>();\n for (const job of jobs) {\n const user = options.cronUser?.(job.target, place) ?? place.cone ?? ROOT_USER;\n users.set(user, [...(users.get(user) ?? []), job]);\n }\n return users;\n }\n\n async function relick(place: LickDir, context: Context): Promise<ConfigError[]> {\n if (relicked.has(place.dir)) return [];\n relicked.add(place.dir);\n const file = `${place.dir}/crontab.migrated`;\n const text = await files.read(file, context);\n if (text === undefined) return [];\n const errors: ConfigError[] = [];\n for (const [user, list] of byUser(place, legacyJobs(text).jobs))\n for (const problem of await relickJobs(env, user, list, context))\n errors.push({ file, ...problem });\n return errors;\n }\n\n async function migrate(place: LickDir, context: Context): Promise<ConfigError[]> {\n const file = `${place.dir}/crontab`;\n const text = await files.read(file, context);\n if (!text?.trim()) return [];\n const { jobs, problems } = legacyJobs(text);\n if (problems.length) return problems.map((problem) => ({ file, ...problem }));\n const users = new Map<string, CronJob[]>();\n for (const [user, list] of byUser(place, jobs))\n users.set(\n user,\n list.map((job) => ({\n name: job.name,\n schedule: job.schedule,\n command: sendCommand(job.target, job.message),\n line: job.line,\n }))\n );\n const errors: ConfigError[] = [];\n for (const [user, list] of users)\n for (const problem of await installJobs(env, user, list, context))\n errors.push({ file, ...problem });\n if (errors.length) return errors;\n await env.writeFile(`${file}.migrated`, text, context);\n await env.remove(file, { force: true }, context);\n return [];\n }\n\n async function retire(context: Context): Promise<void> {\n const stored = (await harness.snapshot(LicksHostDoc, context))?.cron ?? {};\n const records = Object.values(stored);\n if (!records.length) return;\n for (const record of records)\n await harness.abortTask(record.task as TaskId, context).catch(() => undefined);\n await harness.commit(async (tx) => {\n (await tx.doc(LicksHostDoc)).cron = {};\n }, context);\n }\n\n async function watchControl(places: readonly LickDir[], context: Context): Promise<void> {\n const key = places.map((place) => place.dir).join('\\n');\n if (key === controlled || closed) return;\n controlled = key;\n await control?.close(context);\n const result = await env.watch(\n places.map((place) => ({ path: place.dir, recursive: true })),\n () => scheduleReconcile(context),\n context\n );\n control = result.ok ? result.value : undefined;\n }\n\n const reconcile = (context: Context) => serial(() => reconcileNow(context));\n\n function scheduleReconcile(context: Context): void {\n clearTimeout(reconcileTimer);\n reconcileTimer = setTimeout(() => {\n void reconcile(context).catch(() => undefined);\n }, 300);\n }\n\n async function flushIfWaiting(context: Context): Promise<void> {\n if (await licks.pending(context)) await licks.flush(context);\n }\n\n return {\n async start(context) {\n await licks.flush(context);\n await retire(context);\n await reconcile(context);\n flushTimer = setInterval(() => {\n void flushIfWaiting(context).catch(() => undefined);\n }, options.flushEvery ?? 2000);\n },\n reconcile,\n boot: boots.boot,\n async webhook(name, delivery, context) {\n const entry = webhooks.get(name);\n if (!entry) return false;\n await deliver(\n webhookLick(name, entry, await withAttachment(delivery, options.fetch)),\n context\n );\n return true;\n },\n async close(context) {\n closed = true;\n boots.stop();\n clearTimeout(reconcileTimer);\n clearInterval(flushTimer);\n await control?.close(context);\n for (const watches of watching.values()) await watches.close(context);\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/scoops/cli.js
CHANGED
|
@@ -7,6 +7,7 @@ import { webhookDelivery } from "../licks/events.js";
|
|
|
7
7
|
import { LICK_CHANNELS } from "../licks/lick.js";
|
|
8
8
|
import { scopedName } from "../licks/sources.js";
|
|
9
9
|
import { findRole } from "../roles/roles.js";
|
|
10
|
+
import { callerOf as agentOf } from "./identity.js";
|
|
10
11
|
import { findScoop, modelOf } from "./service.js";
|
|
11
12
|
import { cancelSync, detachSync, runSync } from "./sync.js";
|
|
12
13
|
import { callerTaints } from "./taints.js";
|
|
@@ -77,23 +78,56 @@ class CallerError extends Error {
|
|
|
77
78
|
function taintsOf(deps, request, who, context) {
|
|
78
79
|
return callerTaints(deps.harness, deps.agents.state(), who, request.caller, context);
|
|
79
80
|
}
|
|
80
|
-
function
|
|
81
|
+
function anonymous(agents) {
|
|
82
|
+
return { id: null, cone: agents.activeCone(), fromAgent: false, scoop: null, depth: 0 };
|
|
83
|
+
}
|
|
84
|
+
function callerOf(agents, request, lineage) {
|
|
85
|
+
if (!lineage) throw new CallerError("can't tell which process is asking from the process table");
|
|
86
|
+
const walked = lineage.agent === null ? void 0 : agentOf(agents, lineage.agent);
|
|
81
87
|
const user = request.user;
|
|
82
|
-
if (!user || user === ROOT_USER)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
88
|
+
if (!user || user === ROOT_USER) {
|
|
89
|
+
if (request.caller && request.caller !== walked)
|
|
90
|
+
throw new CallerError(
|
|
91
|
+
`SLICC_AGENT says ${request.caller}, but this process belongs to ${walked ?? "no agent"}`
|
|
92
|
+
);
|
|
93
|
+
return (walked ? claimed(agents, walked) : void 0) ?? anonymous(agents);
|
|
94
|
+
}
|
|
90
95
|
const own = agentOfUser(agents.state(), user);
|
|
91
96
|
if (request.caller && request.caller !== own)
|
|
92
97
|
throw new CallerError(`SLICC_AGENT says ${request.caller}, but you are ${user}`);
|
|
98
|
+
if (walked && walked !== own)
|
|
99
|
+
throw new CallerError(`you are ${user}, but this process belongs to ${walked}`);
|
|
93
100
|
const found = own ? claimed(agents, own) : void 0;
|
|
94
101
|
if (!found) throw new CallerError(`${user} is no cone or live scoop`);
|
|
95
102
|
return found;
|
|
96
103
|
}
|
|
104
|
+
const UNCHECKED = /* @__PURE__ */ new Set(["__cancel", "__detach"]);
|
|
105
|
+
function unchecked(request) {
|
|
106
|
+
return request.as === "agent" && UNCHECKED.has(request.argv[0] ?? "");
|
|
107
|
+
}
|
|
108
|
+
function sameArgs(a, b) {
|
|
109
|
+
return a.length === b.length && a.every((arg, at) => arg === b[at]);
|
|
110
|
+
}
|
|
111
|
+
function runsCommand(argv, request) {
|
|
112
|
+
return argv.some(
|
|
113
|
+
(arg, at) => at > 0 && arg.split("/").at(-1) === request.as && sameArgs(argv.slice(at + 1), request.argv)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
async function uidOf(deps, user, context) {
|
|
117
|
+
const read = await deps.env.readTextFile("/etc/passwd", context);
|
|
118
|
+
const line = read.ok ? read.value.split("\n").find((entry) => entry.startsWith(`${user}:`)) : "";
|
|
119
|
+
const uid = Number(line?.split(":")[2] ?? Number.NaN);
|
|
120
|
+
return Number.isInteger(uid) ? uid : void 0;
|
|
121
|
+
}
|
|
122
|
+
async function attested(deps, request, context) {
|
|
123
|
+
const lineage = await deps.scoops.lineage(request.pid);
|
|
124
|
+
if (!lineage) return void 0;
|
|
125
|
+
if (!runsCommand(lineage.argv, request))
|
|
126
|
+
throw new CallerError(`process ${request.pid} is not this ${request.as} call`);
|
|
127
|
+
if (request.user && lineage.uid !== await uidOf(deps, request.user, context))
|
|
128
|
+
throw new CallerError(`process ${request.pid} does not run as ${request.user}`);
|
|
129
|
+
return lineage;
|
|
130
|
+
}
|
|
97
131
|
async function readText(deps, value, request, context) {
|
|
98
132
|
const env = await deps.layout.envFor(request.user ?? null, context) ?? deps.env;
|
|
99
133
|
const read = await env.readTextFile(resolve(request.cwd, value), context);
|
|
@@ -272,7 +306,7 @@ async function send(deps, request, who, context) {
|
|
|
272
306
|
if (!text.trim()) return fail("send needs a message, --file or -", 2);
|
|
273
307
|
if (request.argv[1] === "parent") {
|
|
274
308
|
if (!who.scoop) return fail("only a scoop has a parent to send to");
|
|
275
|
-
return deps.scoops.note(who.scoop, text, context);
|
|
309
|
+
return deps.scoops.note(who.scoop, text, await taintsOf(deps, request, who, context), context);
|
|
276
310
|
}
|
|
277
311
|
if (who.scoop) return fail("a scoop can only send to its parent");
|
|
278
312
|
const found = handle(deps, who, request.argv[1]);
|
|
@@ -320,15 +354,19 @@ function refusedChannel(channel) {
|
|
|
320
354
|
2
|
|
321
355
|
);
|
|
322
356
|
}
|
|
323
|
-
async function cronSend(deps, licks, request, parsed, context) {
|
|
357
|
+
async function cronSend(deps, licks, request, parsed, sender, context) {
|
|
324
358
|
if (!request.cron)
|
|
325
359
|
return fail("--lick=cron only works inside a cron job, which sets SLICC_CRON_JOB");
|
|
360
|
+
if (sender.spawned)
|
|
361
|
+
return fail("--lick=cron only works inside a cron job, and an agent's bash started this one");
|
|
326
362
|
if (last(parsed, "--source") !== void 0)
|
|
327
363
|
return fail("--source is for --lick=webhook; a cron lick is named by its job's # name:", 2);
|
|
328
364
|
const target = cronTarget(deps, request, parsed.rest[0] ?? "");
|
|
329
365
|
if (isAnswer(target)) return target;
|
|
330
366
|
const text = (await message(deps, unnamed(parsed), request, context)).trim();
|
|
331
|
-
await
|
|
367
|
+
const taints = await taintsOf(deps, request, sender.who, context);
|
|
368
|
+
const lick = cronLick(request.cron, target, text);
|
|
369
|
+
await licks.deliver(taints.length ? { ...lick, taints } : lick, context);
|
|
332
370
|
return ok("");
|
|
333
371
|
}
|
|
334
372
|
function webhookScope(deps, request) {
|
|
@@ -339,7 +377,7 @@ function webhookScope(deps, request) {
|
|
|
339
377
|
if (own.startsWith("scoop:")) return fail("a scoop can't send webhook licks; its cone can");
|
|
340
378
|
return own.slice(CONE_PREFIX.length);
|
|
341
379
|
}
|
|
342
|
-
async function webhookSend(deps, request, parsed, context) {
|
|
380
|
+
async function webhookSend(deps, request, parsed, sender, context) {
|
|
343
381
|
if (!deps.webhook) return fail("webhooks are not available in this agent");
|
|
344
382
|
const source = last(parsed, "--source");
|
|
345
383
|
if (!source)
|
|
@@ -350,9 +388,10 @@ async function webhookSend(deps, request, parsed, context) {
|
|
|
350
388
|
if (isAnswer(scope)) return scope;
|
|
351
389
|
const text = await message(deps, unnamed(parsed), request, context);
|
|
352
390
|
if (!text.trim()) return fail("send needs a message, --file or -", 2);
|
|
391
|
+
const taints = await taintsOf(deps, request, sender.who, context);
|
|
353
392
|
const delivered = await deps.webhook(
|
|
354
393
|
scopedName(source, scope),
|
|
355
|
-
webhookDelivery(text.trimEnd()),
|
|
394
|
+
{ ...webhookDelivery(text.trimEnd()), taints },
|
|
356
395
|
context
|
|
357
396
|
);
|
|
358
397
|
return delivered ? ok("") : fail(`there is no webhook ${source}; add ~/.slicc/webhooks/${source}.json`);
|
|
@@ -360,14 +399,18 @@ async function webhookSend(deps, request, parsed, context) {
|
|
|
360
399
|
function unnamed(parsed) {
|
|
361
400
|
return { ...parsed, rest: parsed.rest.slice(1) };
|
|
362
401
|
}
|
|
363
|
-
async function lickSend(deps, request, context) {
|
|
402
|
+
async function lickSend(deps, request, lineage, context) {
|
|
364
403
|
const parsed = flags(request.argv.slice(1), ["--file", "--lick", "--source"]);
|
|
365
404
|
const unknown = [...parsed.switches][0];
|
|
366
405
|
if (unknown) return fail(`unknown option ${unknown}`, 2);
|
|
367
406
|
const channel = last(parsed, "--lick") ?? "";
|
|
368
407
|
if (!PROCESS_LICKS.includes(channel)) return refusedChannel(channel);
|
|
369
408
|
if (!deps.licks) return fail("licks are not available in this agent");
|
|
370
|
-
|
|
409
|
+
const sender = {
|
|
410
|
+
who: callerOf(deps.agents, request, lineage),
|
|
411
|
+
spawned: lineage.spawned
|
|
412
|
+
};
|
|
413
|
+
return channel === "cron" ? cronSend(deps, deps.licks, request, parsed, sender, context) : webhookSend(deps, request, parsed, sender, context);
|
|
371
414
|
}
|
|
372
415
|
async function latest(deps, record, context) {
|
|
373
416
|
const dir = deps.layout.reports(record.folder, record.cone);
|
|
@@ -422,7 +465,8 @@ async function wait(deps, request, who, context) {
|
|
|
422
465
|
if (!parsed.switches.has("--notify")) return block(deps, ids, seconds, context);
|
|
423
466
|
if (!who.fromAgent || who.scoop)
|
|
424
467
|
return fail("wait --notify is for a cone; a terminal waits with agent wait");
|
|
425
|
-
await deps
|
|
468
|
+
const taints = await taintsOf(deps, request, who, context);
|
|
469
|
+
await deps.scoops.notifyWhenDone(who.cone, ids, deps.now() + seconds * 1e3, taints, context);
|
|
426
470
|
return ok(`you'll get one scoop-wait lick when ${ids.length > 1 ? "they are" : "it is"} done
|
|
427
471
|
`);
|
|
428
472
|
}
|
|
@@ -528,10 +572,13 @@ function createCli(options) {
|
|
|
528
572
|
},
|
|
529
573
|
async run(request, context) {
|
|
530
574
|
try {
|
|
575
|
+
if (unchecked(request))
|
|
576
|
+
return await dispatch(deps, request, anonymous(deps.agents), context);
|
|
577
|
+
const lineage = await attested(deps, request, context);
|
|
531
578
|
const argv = expanded(request.argv);
|
|
532
579
|
if (request.as === "agent" && argv[0] === "send" && argv.includes("--lick"))
|
|
533
|
-
return await lickSend(deps, { ...request, argv }, context);
|
|
534
|
-
return await dispatch(deps, request, callerOf(
|
|
580
|
+
return await lickSend(deps, { ...request, argv }, lineage, context);
|
|
581
|
+
return await dispatch(deps, request, callerOf(deps.agents, request, lineage), context);
|
|
535
582
|
} catch (error) {
|
|
536
583
|
return fail(error.message);
|
|
537
584
|
}
|
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 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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",
|
|
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 type { Lineage } from '../kernel/lineage.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 { callerOf as agentOf } from './identity.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\nfunction anonymous(agents: Agents): Caller {\n return { id: null, cone: agents.activeCone(), fromAgent: false, scoop: null, depth: 0 };\n}\n\nexport function callerOf(agents: Agents, request: Request, lineage: Lineage | undefined): Caller {\n if (!lineage) throw new CallerError(\"can't tell which process is asking from the process table\");\n const walked = lineage.agent === null ? undefined : agentOf(agents, lineage.agent);\n const user = request.user;\n if (!user || user === ROOT_USER) {\n if (request.caller && request.caller !== walked)\n throw new CallerError(\n `SLICC_AGENT says ${request.caller}, but this process belongs to ${walked ?? 'no agent'}`\n );\n return (walked ? claimed(agents, walked) : undefined) ?? anonymous(agents);\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 if (walked && walked !== own)\n throw new CallerError(`you are ${user}, but this process belongs to ${walked}`);\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\nconst UNCHECKED = new Set(['__cancel', '__detach']);\n\nfunction unchecked(request: Request): boolean {\n return request.as === 'agent' && UNCHECKED.has(request.argv[0] ?? '');\n}\n\nfunction sameArgs(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((arg, at) => arg === b[at]);\n}\n\nfunction runsCommand(argv: readonly string[], request: Request): boolean {\n return argv.some(\n (arg, at) =>\n at > 0 && arg.split('/').at(-1) === request.as && sameArgs(argv.slice(at + 1), request.argv)\n );\n}\n\nasync function uidOf(deps: Deps, user: string, context: Context): Promise<number | undefined> {\n const read = await deps.env.readTextFile('/etc/passwd', context);\n const line = read.ok ? read.value.split('\\n').find((entry) => entry.startsWith(`${user}:`)) : '';\n const uid = Number(line?.split(':')[2] ?? Number.NaN);\n return Number.isInteger(uid) ? uid : undefined;\n}\n\nasync function attested(\n deps: Deps,\n request: Request,\n context: Context\n): Promise<Lineage | undefined> {\n const lineage = await deps.scoops.lineage(request.pid);\n if (!lineage) return undefined;\n if (!runsCommand(lineage.argv, request))\n throw new CallerError(`process ${request.pid} is not this ${request.as} call`);\n if (request.user && lineage.uid !== (await uidOf(deps, request.user, context)))\n throw new CallerError(`process ${request.pid} does not run as ${request.user}`);\n return lineage;\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, await taintsOf(deps, request, who, context), 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\ntype Sender = { who: Caller; spawned: boolean };\n\nasync function cronSend(\n deps: Deps,\n licks: Pick<Licks, 'deliver'>,\n request: Request,\n parsed: Flags,\n sender: Sender,\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 (sender.spawned)\n return fail(\"--lick=cron only works inside a cron job, and an agent's bash started this one\");\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 const taints = await taintsOf(deps, request, sender.who, context);\n const lick = cronLick(request.cron, target, text);\n await licks.deliver(taints.length ? { ...lick, taints } : lick, 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 sender: Sender,\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 taints = await taintsOf(deps, request, sender.who, context);\n const delivered = await deps.webhook(\n scopedName(source, scope),\n { ...webhookDelivery(text.trimEnd()), taints },\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(\n deps: Deps,\n request: Request,\n lineage: Lineage | undefined,\n context: Context\n): 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 const sender = {\n who: callerOf(deps.agents, request, lineage),\n spawned: (lineage as Lineage).spawned,\n };\n return channel === 'cron'\n ? cronSend(deps, deps.licks, request, parsed, sender, context)\n : webhookSend(deps, request, parsed, sender, 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 const taints = await taintsOf(deps, request, who, context);\n await deps.scoops.notifyWhenDone(who.cone, ids, deps.now() + seconds * 1000, taints, 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 if (unchecked(request))\n return await dispatch(deps, request, anonymous(deps.agents), context);\n const lineage = await attested(deps, request, context);\n const argv = expanded(request.argv);\n if (request.as === 'agent' && argv[0] === 'send' && argv.includes('--lick'))\n return await lickSend(deps, { ...request, argv }, lineage, context);\n return await dispatch(deps, request, callerOf(deps.agents, request, lineage), 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
|
}
|