@ai-ecoverse/slicc-agent 3.48.1 → 3.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -1
- package/bin/agent +1 -0
- package/dist/control.js +1 -1
- package/dist/control.js.map +2 -2
- package/dist/freezer/index.js +29 -8
- package/dist/freezer/index.js.map +2 -2
- package/dist/freezer/title.js +2 -2
- package/dist/freezer/title.js.map +2 -2
- package/dist/gelatiere/catalog.js +1 -1
- package/dist/gelatiere/catalog.js.map +2 -2
- package/dist/gelatiere/index.js +44 -21
- package/dist/gelatiere/index.js.map +2 -2
- package/dist/gelatiere/store.js +9 -5
- package/dist/gelatiere/store.js.map +2 -2
- package/dist/index.js.map +2 -2
- package/dist/kernel/accounts.js +141 -0
- package/dist/kernel/accounts.js.map +7 -0
- package/dist/kernel/agent-users.js +180 -0
- package/dist/kernel/agent-users.js.map +7 -0
- package/dist/kernel/env.js +9 -3
- package/dist/kernel/env.js.map +2 -2
- package/dist/kernel/users.js +16 -1
- package/dist/kernel/users.js.map +2 -2
- package/dist/layout.js +62 -0
- package/dist/layout.js.map +7 -0
- package/dist/licks/index.js.map +2 -2
- package/dist/licks/sources.js +69 -20
- package/dist/licks/sources.js.map +2 -2
- package/dist/main.js +70 -36
- package/dist/main.js.map +2 -2
- package/dist/mcp/index.js +5 -3
- package/dist/mcp/index.js.map +2 -2
- package/dist/mcp/paths.js +15 -0
- package/dist/mcp/paths.js.map +7 -0
- package/dist/mcp/runtime.js +16 -14
- package/dist/mcp/runtime.js.map +3 -3
- package/dist/memory/extract.js +2 -1
- package/dist/memory/extract.js.map +2 -2
- package/dist/memory/prompt.js +5 -1
- package/dist/memory/prompt.js.map +2 -2
- package/dist/memory/runtime.js +9 -1
- package/dist/memory/runtime.js.map +2 -2
- package/dist/scoops/cli.js +40 -19
- package/dist/scoops/cli.js.map +2 -2
- package/dist/scoops/extension.js +19 -15
- package/dist/scoops/extension.js.map +2 -2
- package/dist/scoops/index.js +75 -9
- package/dist/scoops/index.js.map +2 -2
- package/dist/scoops/requests.js +2 -1
- package/dist/scoops/requests.js.map +2 -2
- package/dist/scoops/service.js +45 -38
- package/dist/scoops/service.js.map +2 -2
- package/dist/scoops/sync.js +63 -13
- package/dist/scoops/sync.js.map +2 -2
- package/dist/skills/index.js +67 -22
- package/dist/skills/index.js.map +3 -3
- package/dist/sprinkles/index.js +114 -25
- package/dist/sprinkles/index.js.map +2 -2
- package/dist/sprinkles/sprinkles.js +13 -4
- package/dist/sprinkles/sprinkles.js.map +2 -2
- package/dist/types/freezer/index.d.ts +3 -1
- package/dist/types/freezer/title.d.ts +1 -1
- package/dist/types/gelatiere/index.d.ts +8 -0
- package/dist/types/gelatiere/store.d.ts +3 -2
- package/dist/types/index.d.ts +1 -1
- package/dist/types/kernel/accounts.d.ts +29 -0
- package/dist/types/kernel/agent-users.d.ts +37 -0
- package/dist/types/kernel/env.d.ts +6 -0
- package/dist/types/kernel/users.d.ts +15 -0
- package/dist/types/layout.d.ts +26 -0
- package/dist/types/licks/index.d.ts +2 -1
- package/dist/types/licks/sources.d.ts +11 -1
- package/dist/types/mcp/paths.d.ts +3 -0
- package/dist/types/mcp/runtime.d.ts +3 -3
- package/dist/types/memory/prompt.d.ts +1 -0
- package/dist/types/memory/runtime.d.ts +1 -0
- package/dist/types/scoops/cli.d.ts +5 -0
- package/dist/types/scoops/extension.d.ts +6 -3
- package/dist/types/scoops/index.d.ts +9 -0
- package/dist/types/scoops/requests.d.ts +2 -0
- package/dist/types/scoops/service.d.ts +5 -3
- package/dist/types/scoops/sync.d.ts +9 -6
- package/dist/types/skills/index.d.ts +10 -2
- package/dist/types/sprinkles/index.d.ts +15 -0
- package/dist/types/sprinkles/sprinkles.d.ts +7 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/memory/runtime.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type Context,\n type MutableReplicatedState,\n type ReplicatedState,\n replicatedState,\n} from '@earendil-works/chord';\nimport type { Harness } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Agents } from '../agents.ts';\nimport type { Role } from '../roles/roles.ts';\nimport { workspace } from '../scoops/service.ts';\nimport { MEMORY_FILE, type MemoryEntry, type MemoryScope, type MemoryTag } from './format.ts';\nimport type { Host } from './prompt.ts';\nimport { MEMORY_WRITE } from './prompt.ts';\nimport {\n GLOBAL,\n MemoryFiles,\n memoryRoot,\n type Place,\n placeOf,\n ROLE_PREFIX,\n rolePlace,\n roleRoot,\n} from './store.ts';\n\nexport type Answer = { code: number; out: string };\n\nexport interface MemoryDraft {\n id?: string;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport interface MemoryRuntime {\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly scopes: ReplicatedState<MemoryScope[]>;\n save(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n remove(id: string, context: Context): Promise<boolean>;\n command(argv: readonly string[], caller: string | null, context: Context): Promise<Answer>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface MemoryAttach {\n harness: Harness;\n agents: Agents;\n env: ExecutionEnv;\n home: string;\n reloadMs: number;\n idleCheckMs?: number;\n roles?: (context: Context) => Promise<{ roles: readonly Role[] } | undefined>;\n}\n\nexport const USAGE = `usage:\n memory show [<scope>] print a memory file (yours by default)\n memory scopes every memory scope, its entries and its file\n\nScopes: global (everyone), a cone's id, or role:<path> for a role's memory.\nAgents write memory with the ${MEMORY_WRITE} tool; the files are plain markdown you can edit.\n`;\n\ntype Listed = Place & { group?: 'cones' | 'roles'; name: string };\n\nasync function roleDirs(\n env: ExecutionEnv,\n dir: string,\n prefix: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n const listed = await env.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n if (info.kind !== 'directory') continue;\n const path = prefix ? `${prefix}/${info.name}` : info.name;\n const found = await env.exists(`${dir}/${info.name}/${MEMORY_FILE}`, context);\n if (found.ok && found.value) out.push(path);\n out.push(...(await roleDirs(env, `${dir}/${info.name}`, path, context, depth + 1)));\n }\n return out;\n}\n\nexport async function listPlaces(options: MemoryAttach, context: Context): Promise<Listed[]> {\n const { agents, env, home } = options;\n const state = agents.state();\n const out: Listed[] = [{ ...(placeOf(home, GLOBAL) as Place), name: 'Everyone' }];\n const cones = new Set(Object.keys(state.cones));\n const stored = await env.listDir(memoryRoot(home), context);\n if (stored.ok)\n for (const info of stored.value) if (info.kind === 'directory') cones.add(info.name);\n for (const id of cones) {\n const place = placeOf(home, id);\n if (place) out.push({ ...place, group: 'cones', name: state.cones[id]?.name ?? id });\n }\n const roles = new Set(await roleDirs(env, roleRoot(home), '', context));\n const known = await options.roles?.(context).catch(() => undefined);\n for (const role of known?.roles ?? [])\n if (role.memory?.scope === 'user') roles.add(role.memory.path);\n for (const path of [...roles].sort()) {\n const place = placeOf(home, `${ROLE_PREFIX}${path}`);\n if (place) out.push({ ...place, group: 'roles', name: path.split('/').at(-1) ?? path });\n }\n return out;\n}\n\nasync function callerPlace(\n options: MemoryAttach,\n caller: string | null,\n context: Context\n): Promise<Place | { problem: string }> {\n const { agents, env, home } = options;\n const record = caller ? agents.state().scoops[caller] : undefined;\n if (record?.memory)\n return rolePlace(env, home, record.memory, record.origin ?? workspace(record.folder), context);\n const cone = caller?.startsWith('cone:') ? caller.slice('cone:'.length) : agents.activeCone();\n return placeOf(home, cone) ?? { problem: `there is no memory scope ${cone}` };\n}\n\ntype Parts = {\n options: MemoryAttach;\n files: MemoryFiles;\n memories: MutableReplicatedState<MemoryEntry[]>;\n scopes: MutableReplicatedState<MemoryScope[]>;\n reload: (context: Context) => Promise<void>;\n};\n\nfunction placeFor(home: string, scope: string): Place {\n const place = placeOf(home, scope);\n if (!place) throw new Error(`there is no memory scope ${scope}`);\n return place;\n}\n\nasync function save(parts: Parts, draft: MemoryDraft, context: Context): Promise<MemoryEntry> {\n const { files, memories, options } = parts;\n const place = placeFor(options.home, draft.scope);\n const previous = draft.id ? memories.value.find((item) => item.id === draft.id) : undefined;\n const moved = previous && previous.scope !== draft.scope;\n try {\n const written = await files.change(\n place,\n {\n kind: 'save',\n ...(previous && !moved ? { id: previous.id } : {}),\n section: draft.section,\n title: draft.title,\n body: draft.body,\n tag: draft.tag,\n },\n context\n );\n if (previous && moved)\n await files.change(\n placeFor(options.home, previous.scope),\n { kind: 'remove', id: previous.id },\n context\n );\n return written.entry as MemoryEntry;\n } finally {\n await parts.reload(context).catch(() => undefined);\n }\n}\n\nasync function command(\n parts: Parts,\n argv: readonly string[],\n caller: string | null,\n context: Context\n): Promise<Answer> {\n const { files, memories, scopes, options } = parts;\n const verb = argv[0] ?? 'help';\n if (verb === 'scopes') {\n await parts.reload(context);\n const rows = scopes.value.map((scope) => {\n const count = memories.value.filter((item) => item.scope === scope.id).length;\n const file = placeFor(options.home, scope.id).file;\n return `${scope.id}\\t${scope.label}\\t${count} entr${count === 1 ? 'y' : 'ies'}\\t${file}`;\n });\n return { code: 0, out: `${rows.join('\\n')}\\n` };\n }\n if (verb !== 'show') return { code: verb === 'help' || verb === '--help' ? 0 : 2, out: USAGE };\n const place = argv[1]\n ? (placeOf(options.home, argv[1]) ?? { problem: `there is no memory scope ${argv[1]}` })\n : await callerPlace(options, caller, context);\n if ('problem' in place) return { code: 1, out: `memory: ${place.problem}\\n` };\n const read = await files.read(place.file, context);\n return {\n code: 0,\n out: read?.text.trim()\n ? `# ${place.file}\\n\\n${read.text.trimEnd()}\\n`\n : `${place.file} is empty\\n`,\n };\n}\n\nexport async function attachMemory(\n options: MemoryAttach,\n connect: (host: Host) => void,\n context: Context\n): Promise<MemoryRuntime> {\n const { agents, env, home } = options;\n const files = new MemoryFiles(env);\n const memories = replicatedState<MemoryEntry[]>([]);\n const scopes = replicatedState<MemoryScope[]>([]);\n const reload = async (using: Context) => {\n const found = await listPlaces(options, using);\n const entries: MemoryEntry[] = [];\n for (const place of found) entries.push(...(await files.entries(place, using)));\n scopes.replace(\n using,\n found.map((place) => ({\n id: place.scope,\n label: place.name,\n ...(place.group ? { group: place.group } : {}),\n }))\n );\n memories.replace(using, entries);\n };\n const parts: Parts = { options, files, memories, scopes, reload };\n connect({
|
|
5
|
-
"mappings": "AAAA;AAAA,EAIE;AAAA,OACK;AAKP,SAAS,iBAAiB;AAC1B,SAAS,mBAAuE;AAEhF,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;
|
|
4
|
+
"sourcesContent": ["import {\n type Context,\n type MutableReplicatedState,\n type ReplicatedState,\n replicatedState,\n} from '@earendil-works/chord';\nimport type { Harness } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Agents } from '../agents.ts';\nimport type { Role } from '../roles/roles.ts';\nimport { workspace } from '../scoops/service.ts';\nimport { MEMORY_FILE, type MemoryEntry, type MemoryScope, type MemoryTag } from './format.ts';\nimport type { Host } from './prompt.ts';\nimport { MEMORY_WRITE } from './prompt.ts';\nimport {\n GLOBAL,\n MemoryFiles,\n memoryRoot,\n type Place,\n placeOf,\n ROLE_PREFIX,\n rolePlace,\n roleRoot,\n} from './store.ts';\n\nexport type Answer = { code: number; out: string };\n\nexport interface MemoryDraft {\n id?: string;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport interface MemoryRuntime {\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly scopes: ReplicatedState<MemoryScope[]>;\n save(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n remove(id: string, context: Context): Promise<boolean>;\n command(argv: readonly string[], caller: string | null, context: Context): Promise<Answer>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface MemoryAttach {\n harness: Harness;\n agents: Agents;\n env: ExecutionEnv;\n home: string;\n agentDir?: string;\n reloadMs: number;\n idleCheckMs?: number;\n roles?: (context: Context) => Promise<{ roles: readonly Role[] } | undefined>;\n}\n\nexport const USAGE = `usage:\n memory show [<scope>] print a memory file (yours by default)\n memory scopes every memory scope, its entries and its file\n\nScopes: global (everyone), a cone's id, or role:<path> for a role's memory.\nAgents write memory with the ${MEMORY_WRITE} tool; the files are plain markdown you can edit.\n`;\n\ntype Listed = Place & { group?: 'cones' | 'roles'; name: string };\n\nasync function roleDirs(\n env: ExecutionEnv,\n dir: string,\n prefix: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n const listed = await env.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n if (info.kind !== 'directory') continue;\n const path = prefix ? `${prefix}/${info.name}` : info.name;\n const found = await env.exists(`${dir}/${info.name}/${MEMORY_FILE}`, context);\n if (found.ok && found.value) out.push(path);\n out.push(...(await roleDirs(env, `${dir}/${info.name}`, path, context, depth + 1)));\n }\n return out;\n}\n\nexport async function listPlaces(options: MemoryAttach, context: Context): Promise<Listed[]> {\n const { agents, env, home } = options;\n const state = agents.state();\n const out: Listed[] = [{ ...(placeOf(home, GLOBAL) as Place), name: 'Everyone' }];\n const cones = new Set(Object.keys(state.cones));\n const stored = await env.listDir(memoryRoot(home), context);\n if (stored.ok)\n for (const info of stored.value) if (info.kind === 'directory') cones.add(info.name);\n for (const id of cones) {\n const place = placeOf(home, id);\n if (place) out.push({ ...place, group: 'cones', name: state.cones[id]?.name ?? id });\n }\n const roles = new Set(await roleDirs(env, roleRoot(home), '', context));\n const known = await options.roles?.(context).catch(() => undefined);\n for (const role of known?.roles ?? [])\n if (role.memory?.scope === 'user') roles.add(role.memory.path);\n for (const path of [...roles].sort()) {\n const place = placeOf(home, `${ROLE_PREFIX}${path}`);\n if (place) out.push({ ...place, group: 'roles', name: path.split('/').at(-1) ?? path });\n }\n return out;\n}\n\nasync function callerPlace(\n options: MemoryAttach,\n caller: string | null,\n context: Context\n): Promise<Place | { problem: string }> {\n const { agents, env, home } = options;\n const record = caller ? agents.state().scoops[caller] : undefined;\n if (record?.memory)\n return rolePlace(env, home, record.memory, record.origin ?? workspace(record.folder), context);\n const cone = caller?.startsWith('cone:') ? caller.slice('cone:'.length) : agents.activeCone();\n return placeOf(home, cone) ?? { problem: `there is no memory scope ${cone}` };\n}\n\ntype Parts = {\n options: MemoryAttach;\n files: MemoryFiles;\n memories: MutableReplicatedState<MemoryEntry[]>;\n scopes: MutableReplicatedState<MemoryScope[]>;\n reload: (context: Context) => Promise<void>;\n};\n\nfunction placeFor(home: string, scope: string): Place {\n const place = placeOf(home, scope);\n if (!place) throw new Error(`there is no memory scope ${scope}`);\n return place;\n}\n\nasync function save(parts: Parts, draft: MemoryDraft, context: Context): Promise<MemoryEntry> {\n const { files, memories, options } = parts;\n const place = placeFor(options.home, draft.scope);\n const previous = draft.id ? memories.value.find((item) => item.id === draft.id) : undefined;\n const moved = previous && previous.scope !== draft.scope;\n try {\n const written = await files.change(\n place,\n {\n kind: 'save',\n ...(previous && !moved ? { id: previous.id } : {}),\n section: draft.section,\n title: draft.title,\n body: draft.body,\n tag: draft.tag,\n },\n context\n );\n if (previous && moved)\n await files.change(\n placeFor(options.home, previous.scope),\n { kind: 'remove', id: previous.id },\n context\n );\n return written.entry as MemoryEntry;\n } finally {\n await parts.reload(context).catch(() => undefined);\n }\n}\n\nasync function command(\n parts: Parts,\n argv: readonly string[],\n caller: string | null,\n context: Context\n): Promise<Answer> {\n const { files, memories, scopes, options } = parts;\n const verb = argv[0] ?? 'help';\n if (verb === 'scopes') {\n await parts.reload(context);\n const rows = scopes.value.map((scope) => {\n const count = memories.value.filter((item) => item.scope === scope.id).length;\n const file = placeFor(options.home, scope.id).file;\n return `${scope.id}\\t${scope.label}\\t${count} entr${count === 1 ? 'y' : 'ies'}\\t${file}`;\n });\n return { code: 0, out: `${rows.join('\\n')}\\n` };\n }\n if (verb !== 'show') return { code: verb === 'help' || verb === '--help' ? 0 : 2, out: USAGE };\n const place = argv[1]\n ? (placeOf(options.home, argv[1]) ?? { problem: `there is no memory scope ${argv[1]}` })\n : await callerPlace(options, caller, context);\n if ('problem' in place) return { code: 1, out: `memory: ${place.problem}\\n` };\n const read = await files.read(place.file, context);\n return {\n code: 0,\n out: read?.text.trim()\n ? `# ${place.file}\\n\\n${read.text.trimEnd()}\\n`\n : `${place.file} is empty\\n`,\n };\n}\n\nexport async function attachMemory(\n options: MemoryAttach,\n connect: (host: Host) => void,\n context: Context\n): Promise<MemoryRuntime> {\n const { agents, env, home } = options;\n const files = new MemoryFiles(env);\n const memories = replicatedState<MemoryEntry[]>([]);\n const scopes = replicatedState<MemoryScope[]>([]);\n const reload = async (using: Context) => {\n const found = await listPlaces(options, using);\n const entries: MemoryEntry[] = [];\n for (const place of found) entries.push(...(await files.entries(place, using)));\n scopes.replace(\n using,\n found.map((place) => ({\n id: place.scope,\n label: place.name,\n ...(place.group ? { group: place.group } : {}),\n }))\n );\n memories.replace(using, entries);\n };\n const parts: Parts = { options, files, memories, scopes, reload };\n connect({\n harness: options.harness,\n agents,\n env,\n home,\n ...(options.agentDir ? { agentDir: options.agentDir } : {}),\n files,\n changed: reload,\n });\n await reload(context).catch(() => undefined);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const schedule = () => {\n clearTimeout(timer);\n timer = setTimeout(() => void reload(context).catch(() => undefined), options.reloadMs);\n };\n const offCone = agents.onCone(schedule);\n const watched = await env.watch(\n [\n { path: memoryRoot(home), recursive: true },\n { path: roleRoot(home), recursive: true },\n ],\n schedule,\n context\n );\n const watcher: FileWatcher | undefined = watched.ok ? watched.value : undefined;\n return {\n memories,\n scopes,\n save: (draft, using) => save(parts, draft, using),\n async remove(id, using) {\n const entry = memories.value.find((item) => item.id === id);\n if (!entry) return false;\n const written = await files.change(\n placeFor(home, entry.scope),\n { kind: 'remove', id },\n using\n );\n await reload(using);\n return written.found;\n },\n command: (argv, caller, using) => command(parts, argv, caller, using),\n reload,\n async close(using) {\n offCone();\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/scoops/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolve } from "../kernel/paths.js";
|
|
2
|
+
import { agentOfUser, LEGACY, ROOT_USER } from "../layout.js";
|
|
2
3
|
import { findRole } from "../roles/roles.js";
|
|
3
|
-
import { findScoop, modelOf
|
|
4
|
+
import { findScoop, modelOf } from "./service.js";
|
|
4
5
|
import { cancelSync, detachSync, runSync } from "./sync.js";
|
|
5
6
|
const DEFAULT_WAIT_S = 30;
|
|
6
7
|
const MAX_DEPTH = 3;
|
|
@@ -51,25 +52,39 @@ function flags(argv, withValue) {
|
|
|
51
52
|
function last(parsed, flag) {
|
|
52
53
|
return parsed.values.get(flag)?.at(-1);
|
|
53
54
|
}
|
|
54
|
-
function
|
|
55
|
+
function claimed(agents, caller) {
|
|
55
56
|
const state = agents.state();
|
|
56
|
-
if (
|
|
57
|
-
const cone =
|
|
57
|
+
if (caller.startsWith("cone:") && state.cones[caller.slice(5)]) {
|
|
58
|
+
const cone = caller.slice(5);
|
|
58
59
|
return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };
|
|
59
60
|
}
|
|
60
|
-
const record =
|
|
61
|
+
const record = caller.startsWith("scoop:") ? state.scoops[caller] : void 0;
|
|
61
62
|
if (record)
|
|
62
|
-
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
return { id: caller, cone: record.cone, fromAgent: true, scoop: caller, depth: record.depth };
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
class CallerError extends Error {
|
|
67
|
+
}
|
|
68
|
+
function callerOf(agents, request) {
|
|
69
|
+
const user = request.user;
|
|
70
|
+
if (!user || user === ROOT_USER)
|
|
71
|
+
return claimed(agents, request.caller) ?? {
|
|
72
|
+
id: null,
|
|
73
|
+
cone: agents.activeCone(),
|
|
74
|
+
fromAgent: false,
|
|
75
|
+
scoop: null,
|
|
76
|
+
depth: 0
|
|
68
77
|
};
|
|
69
|
-
|
|
78
|
+
const own = agentOfUser(agents.state(), user);
|
|
79
|
+
if (request.caller && request.caller !== own)
|
|
80
|
+
throw new CallerError(`SLICC_AGENT says ${request.caller}, but you are ${user}`);
|
|
81
|
+
const found = own ? claimed(agents, own) : void 0;
|
|
82
|
+
if (!found) throw new CallerError(`${user} is no cone or live scoop`);
|
|
83
|
+
return found;
|
|
70
84
|
}
|
|
71
85
|
async function readText(deps, value, request, context) {
|
|
72
|
-
const
|
|
86
|
+
const env = await deps.layout.envFor(request.user ?? null, context) ?? deps.env;
|
|
87
|
+
const read = await env.readTextFile(resolve(request.cwd, value), context);
|
|
73
88
|
if (!read.ok) throw new Error(`can't read ${value}: ${read.error.message}`);
|
|
74
89
|
return read.value;
|
|
75
90
|
}
|
|
@@ -216,8 +231,8 @@ async function status(deps, request, who, context) {
|
|
|
216
231
|
`role: ${record.role ?? "-"}`,
|
|
217
232
|
`kind: ${record.kind}`,
|
|
218
233
|
`state: ${busy ? "working" : "idle"}`,
|
|
219
|
-
`folder: ${
|
|
220
|
-
`reports: ${
|
|
234
|
+
`folder: ${deps.layout.scoopRoot(record.folder)}`,
|
|
235
|
+
`reports: ${deps.layout.reports(record.folder, record.cone)}`
|
|
221
236
|
].join("\n")}
|
|
222
237
|
`
|
|
223
238
|
);
|
|
@@ -248,8 +263,8 @@ async function send(deps, request, who, context) {
|
|
|
248
263
|
context
|
|
249
264
|
);
|
|
250
265
|
}
|
|
251
|
-
async function latest(deps,
|
|
252
|
-
const dir =
|
|
266
|
+
async function latest(deps, record, context) {
|
|
267
|
+
const dir = deps.layout.reports(record.folder, record.cone);
|
|
253
268
|
const listed = await deps.env.listDir(dir, context);
|
|
254
269
|
if (!listed.ok || !listed.value.length) return "(no answer yet)";
|
|
255
270
|
const newest = [...listed.value].sort(
|
|
@@ -279,7 +294,7 @@ async function block(deps, ids, seconds, context) {
|
|
|
279
294
|
if (record)
|
|
280
295
|
sections.push(
|
|
281
296
|
`## ${record.folder}${open.includes(id) ? " (still working)" : ""}
|
|
282
|
-
${await latest(deps, record
|
|
297
|
+
${await latest(deps, record, context)}`
|
|
283
298
|
);
|
|
284
299
|
}
|
|
285
300
|
const body = `${sections.join("\n\n")}
|
|
@@ -378,7 +393,12 @@ const BLOCKING = /* @__PURE__ */ new Set([
|
|
|
378
393
|
"__detach"
|
|
379
394
|
]);
|
|
380
395
|
function createCli(options) {
|
|
381
|
-
const deps = {
|
|
396
|
+
const deps = {
|
|
397
|
+
...options,
|
|
398
|
+
now: options.now ?? Date.now,
|
|
399
|
+
sync: { pending: /* @__PURE__ */ new Map() },
|
|
400
|
+
layout: options.layout ?? LEGACY
|
|
401
|
+
};
|
|
382
402
|
return {
|
|
383
403
|
blocking(request) {
|
|
384
404
|
if (request.as === "panel") return true;
|
|
@@ -396,6 +416,7 @@ function createCli(options) {
|
|
|
396
416
|
};
|
|
397
417
|
}
|
|
398
418
|
export {
|
|
419
|
+
CallerError,
|
|
399
420
|
DEFAULT_WAIT_S,
|
|
400
421
|
MAX_DEPTH,
|
|
401
422
|
RUN_DIR,
|
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 { resolve } from '../kernel/paths.ts';\nimport { findRole, type Roles } from '../roles/roles.ts';\nimport type { Request, Runner } from './requests.ts';\nimport { type Answer, findScoop, modelOf, SCOOPS_ROOT, type Scoops } from './service.ts';\nimport { cancelSync, detachSync, runSync, type SyncState } from './sync.ts';\n\nexport const DEFAULT_WAIT_S = 30;\nexport const MAX_DEPTH = 3;\nexport const RUN_DIR = '/var/lib/slicc/agent/scoops';\n\nexport const THINKING = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\nconst EFFORT: Record<string, string> = { low: 'low', medium: 'medium', high: 'high', max: 'xhigh' };\n\nexport const USAGE = `usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\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?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n models?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;\n panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => 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 };\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\nexport function callerOf(agents: Agents, request: Request): Caller {\n const state = agents.state();\n if (request.caller.startsWith('cone:') && state.cones[request.caller.slice(5)]) {\n const cone = request.caller.slice(5);\n return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };\n }\n const record = request.caller.startsWith('scoop:') ? state.scoops[request.caller] : undefined;\n if (record)\n return {\n id: request.caller,\n cone: record.cone,\n fromAgent: true,\n scoop: request.caller,\n depth: record.depth,\n };\n return { id: null, cone: agents.activeCone(), fromAgent: false, scoop: null, depth: 0 };\n}\n\nexport async function readText(\n deps: Deps,\n value: string,\n request: Request,\n context: Context\n): Promise<string> {\n const read = await deps.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\nconst ASYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n];\nconst ASYNC_SWITCHES = new Set(['--async', '--no-extensions', '--no-skills', '--no-context-files']);\nconst UNSUPPORTED = new Set([\n '--no-prompt-templates',\n '--session',\n '--resume',\n '--image',\n '--no-escalate',\n '--minimal',\n '--usage',\n '--schema-b64',\n '--cwd',\n]);\n\nexport function unsupported(argv: readonly string[]): Answer | undefined {\n const found = argv.find((arg) => UNSUPPORTED.has(arg) || arg.startsWith('--image='));\n return found ? fail(`${found} is not supported in SLICC yet`, 2) : undefined;\n}\n\nasync function spawnAsync(\n deps: Deps,\n request: Request,\n who: Caller,\n argv: readonly string[],\n context: Context\n) {\n if (who.scoop) return fail('a scoop cannot start async scoops; run agent without --async');\n const refused = unsupported(argv);\n if (refused) return refused;\n const parsed = flags(argv, ASYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !ASYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const given = await prompts(deps, argv, request, context);\n if (!given.length) return fail('--async needs at least one --prompt, --file or -', 2);\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n return deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'async',\n name: last(parsed, '--name') ?? found.role?.name ?? 'scoop',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n}\n\nasync function listAgents(deps: Deps): Promise<Answer> {\n const roles = await deps.roles();\n const lines = roles.roles.map(\n (entry) =>\n `${entry.name}\\t${entry.source}\\t${entry.description}${entry.aliases.length ? ` (also ${entry.aliases.join(', ')})` : ''}`\n );\n return ok(\n `${[\n ...lines,\n '',\n 'Agent files are read from the built-in roles, installed packages (pi-subagents.agents) and ~/.pi/agent/agents.',\n \"A project's .pi/agents folder is read only once the folder is trusted, which SLICC doesn't support yet.\",\n ...roles.warnings.map((warning) => `warning: ${warning}`),\n ].join('\\n')}\\n`\n );\n}\n\nasync function list(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (request.argv.includes('--agents')) return listAgents(deps);\n const rows = await deps.scoops.list(who.cone, context);\n if (!rows.length) return ok('no scoops\\n');\n return ok(\n `${rows.map((row) => `${row.folder}\\t${row.name}\\t${row.role ?? '-'}\\t${row.busy ? 'working' : 'idle'}`).join('\\n')}\\n`\n );\n}\n\nasync function status(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const [, record] = found;\n const busy = await deps.scoops.busy(record.conversation, context);\n return ok(\n `${[\n `handle: ${record.folder}`,\n `name: ${record.name}`,\n `role: ${record.role ?? '-'}`,\n `kind: ${record.kind}`,\n `state: ${busy ? 'working' : 'idle'}`,\n `folder: ${SCOOPS_ROOT}/${record.folder}`,\n `reports: ${SCOOPS_ROOT}/${record.folder}/reports`,\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 followUp = parsed.switches.has('--follow-up');\n return deps.scoops.feed(\n found[0],\n text,\n { fromAgent: who.fromAgent, request: request.id, followUp, target: who.id },\n context\n );\n}\n\nasync function latest(deps: Deps, folder: string, context: Context): Promise<string> {\n const dir = `${SCOOPS_ROOT}/${folder}/reports`;\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.folder, 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 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 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 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 : 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 '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 = { ...options, now: options.now ?? Date.now, sync: { pending: new Map() } };\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 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 { resolve } from '../kernel/paths.ts';\nimport { agentOfUser, type Layout, LEGACY, ROOT_USER } from '../layout.ts';\nimport { findRole, type Roles } from '../roles/roles.ts';\nimport type { Request, Runner } from './requests.ts';\nimport { type Answer, findScoop, modelOf, type Scoops } from './service.ts';\nimport { cancelSync, detachSync, runSync, type SyncState } from './sync.ts';\n\nexport const DEFAULT_WAIT_S = 30;\nexport const MAX_DEPTH = 3;\nexport const RUN_DIR = '/var/lib/slicc/agent/scoops';\n\nexport const THINKING = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\nconst EFFORT: Record<string, string> = { low: 'low', medium: 'medium', high: 'high', max: 'xhigh' };\n\nexport const USAGE = `usage:\n agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer\n agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle\n agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form\n agent list [--agents] | status <handle> | rename <handle> <name>\n agent send <handle> [--follow-up] (<message> | --file <path> | -)\n agent send parent <note> from a scoop: a progress note to its cone\n agent wait <handle>... [--timeout <seconds>] [--notify]\n agent stop <handle>\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?: (argv: readonly string[], caller: string | null, context: Context) => 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}\n\nexport interface PanelCaller {\n agentId: string | null;\n cone: string;\n tab: string | null;\n}\n\nexport type Deps = CliOptions & { now: () => number; sync: SyncState; layout: Layout };\n\nexport interface Caller {\n id: string | null;\n cone: string;\n fromAgent: boolean;\n scoop: string | null;\n depth: number;\n}\n\nexport type Flags = { values: Map<string, string[]>; switches: Set<string>; rest: string[] };\n\nexport const ok = (out: string): Answer => ({ code: 0, out });\nexport const fail = (out: string, code = 1): Answer => ({ code, out: `agent: ${out}\\n` });\n\nexport function isAnswer(value: unknown): value is Answer {\n return typeof value === 'object' && value !== null && 'code' in value && 'out' in value;\n}\n\nexport function flags(argv: readonly string[], withValue: readonly string[]): Flags {\n const values = new Map<string, string[]>();\n const switches = new Set<string>();\n const rest: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at] as string;\n if (withValue.includes(arg)) {\n const value = argv[at + 1];\n if (value === undefined) throw new Error(`${arg} needs a value`);\n values.set(arg, [...(values.get(arg) ?? []), value]);\n at++;\n } else if (arg.startsWith('--')) switches.add(arg);\n else rest.push(arg);\n }\n return { values, switches, rest };\n}\n\nexport function last(parsed: Flags, flag: string): string | undefined {\n return parsed.values.get(flag)?.at(-1);\n}\n\nfunction claimed(agents: Agents, caller: string): Caller | undefined {\n const state = agents.state();\n if (caller.startsWith('cone:') && state.cones[caller.slice(5)]) {\n const cone = caller.slice(5);\n return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };\n }\n const record = caller.startsWith('scoop:') ? state.scoops[caller] : undefined;\n if (record)\n return { id: caller, cone: record.cone, fromAgent: true, scoop: caller, depth: record.depth };\n return undefined;\n}\n\nexport class CallerError extends Error {}\n\nexport function callerOf(agents: Agents, request: Request): Caller {\n const user = request.user;\n if (!user || user === ROOT_USER)\n return (\n claimed(agents, request.caller) ?? {\n id: null,\n cone: agents.activeCone(),\n fromAgent: false,\n scoop: null,\n depth: 0,\n }\n );\n const own = agentOfUser(agents.state(), user);\n if (request.caller && request.caller !== own)\n throw new CallerError(`SLICC_AGENT says ${request.caller}, but you are ${user}`);\n const found = own ? claimed(agents, own) : undefined;\n if (!found) throw new CallerError(`${user} is no cone or live scoop`);\n return found;\n}\n\nexport async function readText(\n deps: Deps,\n value: string,\n request: Request,\n context: Context\n): Promise<string> {\n const env = (await deps.layout.envFor(request.user ?? null, context)) ?? deps.env;\n const read = await env.readTextFile(resolve(request.cwd, value), context);\n if (!read.ok) throw new Error(`can't read ${value}: ${read.error.message}`);\n return read.value;\n}\n\nexport async function prompts(\n deps: Deps,\n argv: readonly string[],\n request: Request,\n context: Context\n) {\n const out: string[] = [];\n for (let at = 0; at < argv.length; at++) {\n const arg = argv[at];\n if (arg === '--prompt') out.push(argv[++at] ?? '');\n else if (arg === '--file') out.push(await readText(deps, argv[++at] ?? '', request, context));\n else if (arg === '-') out.push(request.stdin);\n }\n return out.filter((prompt) => prompt.trim());\n}\n\nexport type Choice = {\n model?: { provider: string; modelId: string };\n thinking?: string;\n tools?: string[];\n};\n\nfunction toolList(listed: string | undefined): string[] | undefined {\n if (listed === undefined || listed === 'auto' || listed === 'full') return undefined;\n return listed\n .split(',')\n .map((tool) => tool.trim())\n .filter(Boolean);\n}\n\nexport function choices(parsed: Flags): Choice | Answer {\n const provider = last(parsed, '--provider');\n const modelText = last(parsed, '--model');\n const model = modelText\n ? provider\n ? { provider, modelId: modelText }\n : modelOf(modelText)\n : undefined;\n if (modelText && !model)\n return fail('--model needs provider/model, or --provider with --model', 2);\n const effort = last(parsed, '--effort');\n if (effort && !EFFORT[effort]) return fail('--effort must be low, medium, high or max', 2);\n const thinking = last(parsed, '--thinking') ?? (effort ? EFFORT[effort] : undefined);\n if (thinking && !THINKING.has(thinking))\n return fail(`--thinking must be one of ${[...THINKING].join(', ')}`, 2);\n if (last(parsed, '--tools') === 'output')\n return fail('--tools output needs --schema-b64, which is not supported in SLICC yet', 2);\n const tools = toolList(last(parsed, '--tools'));\n return {\n ...(model ? { model } : {}),\n ...(thinking ? { thinking } : {}),\n ...(tools ? { tools } : {}),\n };\n}\n\nexport async function role(deps: Deps, parsed: Flags) {\n const roles = await deps.roles();\n const name = last(parsed, '--agent');\n const found = name ? findRole(roles.roles, name) : undefined;\n if (name && !found)\n return {\n roles,\n error: fail(`there is no agent role ${name}; \\`agent list --agents\\` shows them`),\n };\n return { roles, role: found };\n}\n\nfunction handle(deps: Deps, who: Caller, name: string | undefined) {\n return name ? findScoop(deps.agents.state(), name, who.fromAgent ? who.cone : null) : undefined;\n}\n\nconst ASYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n];\nconst ASYNC_SWITCHES = new Set(['--async', '--no-extensions', '--no-skills', '--no-context-files']);\nconst UNSUPPORTED = new Set([\n '--no-prompt-templates',\n '--session',\n '--resume',\n '--image',\n '--no-escalate',\n '--minimal',\n '--usage',\n '--schema-b64',\n '--cwd',\n]);\n\nexport function unsupported(argv: readonly string[]): Answer | undefined {\n const found = argv.find((arg) => UNSUPPORTED.has(arg) || arg.startsWith('--image='));\n return found ? fail(`${found} is not supported in SLICC yet`, 2) : undefined;\n}\n\nasync function spawnAsync(\n deps: Deps,\n request: Request,\n who: Caller,\n argv: readonly string[],\n context: Context\n) {\n if (who.scoop) return fail('a scoop cannot start async scoops; run agent without --async');\n const refused = unsupported(argv);\n if (refused) return refused;\n const parsed = flags(argv, ASYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !ASYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const given = await prompts(deps, argv, request, context);\n if (!given.length) return fail('--async needs at least one --prompt, --file or -', 2);\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n return deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'async',\n name: last(parsed, '--name') ?? found.role?.name ?? 'scoop',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n}\n\nasync function listAgents(deps: Deps): Promise<Answer> {\n const roles = await deps.roles();\n const lines = roles.roles.map(\n (entry) =>\n `${entry.name}\\t${entry.source}\\t${entry.description}${entry.aliases.length ? ` (also ${entry.aliases.join(', ')})` : ''}`\n );\n return ok(\n `${[\n ...lines,\n '',\n 'Agent files are read from the built-in roles, installed packages (pi-subagents.agents) and ~/.pi/agent/agents.',\n \"A project's .pi/agents folder is read only once the folder is trusted, which SLICC doesn't support yet.\",\n ...roles.warnings.map((warning) => `warning: ${warning}`),\n ].join('\\n')}\\n`\n );\n}\n\nasync function list(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n if (request.argv.includes('--agents')) return listAgents(deps);\n const rows = await deps.scoops.list(who.cone, context);\n if (!rows.length) return ok('no scoops\\n');\n return ok(\n `${rows.map((row) => `${row.folder}\\t${row.name}\\t${row.role ?? '-'}\\t${row.busy ? 'working' : 'idle'}`).join('\\n')}\\n`\n );\n}\n\nasync function status(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const [, record] = found;\n const busy = await deps.scoops.busy(record.conversation, context);\n return ok(\n `${[\n `handle: ${record.folder}`,\n `name: ${record.name}`,\n `role: ${record.role ?? '-'}`,\n `kind: ${record.kind}`,\n `state: ${busy ? 'working' : 'idle'}`,\n `folder: ${deps.layout.scoopRoot(record.folder)}`,\n `reports: ${deps.layout.reports(record.folder, record.cone)}`,\n ].join('\\n')}\\n`\n );\n}\n\nasync function message(\n deps: Deps,\n parsed: Flags,\n request: Request,\n context: Context\n): Promise<string> {\n const file = last(parsed, '--file');\n if (file) return readText(deps, file, request, context);\n return parsed.rest.includes('-') ? request.stdin : parsed.rest.join(' ');\n}\n\nasync function send(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer> {\n const parsed = flags(request.argv.slice(2), ['--file']);\n const unknown = [...parsed.switches].find((flag) => flag !== '--follow-up');\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const text = await message(deps, parsed, request, context);\n if (!text.trim()) return fail('send needs a message, --file or -', 2);\n if (request.argv[1] === 'parent') {\n if (!who.scoop) return fail('only a scoop has a parent to send to');\n return deps.scoops.note(who.scoop, text, context);\n }\n if (who.scoop) return fail('a scoop can only send to its parent');\n const found = handle(deps, who, request.argv[1]);\n if (!found) return fail(noScoop(deps.agents.state(), request.argv[1] ?? ''));\n const followUp = parsed.switches.has('--follow-up');\n return deps.scoops.feed(\n found[0],\n text,\n { fromAgent: who.fromAgent, request: request.id, followUp, target: who.id },\n context\n );\n}\n\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 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 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 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 : 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 '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 return await dispatch(deps, request, callerOf(options.agents, request), context);\n } catch (error) {\n return fail((error as Error).message);\n }\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/scoops/extension.js
CHANGED
|
@@ -9,14 +9,16 @@ import { answerText } from "../agent.js";
|
|
|
9
9
|
import { AgentsDoc, live } from "../agents.js";
|
|
10
10
|
import { HOME } from "../kernel/env.js";
|
|
11
11
|
import { normalize, resolve } from "../kernel/paths.js";
|
|
12
|
+
import { LEGACY } from "../layout.js";
|
|
12
13
|
import { FROM_KIND } from "./from.js";
|
|
13
|
-
import {
|
|
14
|
+
import { ScoopWorkDoc } from "./service.js";
|
|
14
15
|
const PREVIEW = 1e3;
|
|
15
|
-
function scoopFacts(record) {
|
|
16
|
+
function scoopFacts(record, layout = LEGACY) {
|
|
17
|
+
const place = layout.workspace(record.folder);
|
|
16
18
|
return [
|
|
17
19
|
`You are the scoop "${record.name}"${record.role ? ` (role: ${record.role})` : ""}, a helper agent working for a cone. Messages come from the cone or from the user at a terminal; your final answer goes back to whoever asked, so end every task with a complete answer.`,
|
|
18
|
-
`
|
|
19
|
-
"Your bash is not confined: it sees the whole file system and every process. Stay in your folder anyway, and change nothing outside it unless the request says so.",
|
|
20
|
+
layout.users ? `You run as the user ${layout.scoopRoot(record.folder).slice("/home/".length)}, and your home is ${place}: work there. Your cone can read your home; you can't read your cone's home or another scoop's. /tmp is shared scratch.` : `Work in ${place}. Your read, write and edit tools only reach ${layout.scoopRoot(record.folder)} and /tmp, and read ${HOME}.`,
|
|
21
|
+
layout.users ? "Your bash runs as your user too, so the kernel decides what it may read and change. Stay in your home, and change nothing outside it unless the request says so." : "Your bash is not confined: it sees the whole file system and every process. Stay in your folder anyway, and change nothing outside it unless the request says so.",
|
|
20
22
|
"You may run `agent` synchronously for a bounded side task (calls nest at most three deep), but you cannot start asynchronous scoops (`agent --async`, `subagent spawn`)."
|
|
21
23
|
].join("\n");
|
|
22
24
|
}
|
|
@@ -199,11 +201,11 @@ function scoopTasks(lookup) {
|
|
|
199
201
|
}, context);
|
|
200
202
|
},
|
|
201
203
|
async report(task, runtime, context) {
|
|
202
|
-
const { agents, licks } = await lookup();
|
|
204
|
+
const { agents, licks, layout = LEGACY } = await lookup();
|
|
203
205
|
const id = task.input.scoop;
|
|
204
206
|
const record = agents.state().scoops[id];
|
|
205
207
|
const { text, failed } = task.state.checkpoint;
|
|
206
|
-
const path = record && text ? `${
|
|
208
|
+
const path = record && text ? `${layout.reports(record.folder, record.cone)}/${task.id}.md` : null;
|
|
207
209
|
if (path)
|
|
208
210
|
await (await runtime.env(context))?.writeFile(
|
|
209
211
|
path,
|
|
@@ -252,21 +254,20 @@ async function whose(input, context) {
|
|
|
252
254
|
);
|
|
253
255
|
return { scoop };
|
|
254
256
|
}
|
|
255
|
-
function scoopsExtension(tasks) {
|
|
257
|
+
function scoopsExtension(tasks, layout = () => LEGACY) {
|
|
256
258
|
return defineExtension({
|
|
257
259
|
name: "slicc-scoops",
|
|
258
260
|
tasks: [tasks.anchor, tasks.reporter, tasks.wait],
|
|
259
261
|
sections: [
|
|
260
262
|
section("scoop", async (input, context) => {
|
|
261
263
|
const { scoop } = await whose(input, context);
|
|
262
|
-
return scoop ? scoopFacts(scoop) : void 0;
|
|
264
|
+
return scoop ? scoopFacts(scoop, layout()) : void 0;
|
|
263
265
|
})
|
|
264
266
|
]
|
|
265
267
|
});
|
|
266
268
|
}
|
|
267
269
|
const WRITES = /* @__PURE__ */ new Set(["write", "edit"]);
|
|
268
|
-
function allowed(record, coneCwd, path, writing, reads = []) {
|
|
269
|
-
const own = `${SCOOPS_ROOT}/${record.folder}`;
|
|
270
|
+
function allowed(record, coneCwd, path, writing, reads = [], own = LEGACY.scoopRoot(record.folder)) {
|
|
270
271
|
const write = [own, "/tmp", ...record.roots?.write ?? []];
|
|
271
272
|
const roots = writing ? write : [...write, coneCwd, ...record.roots?.read ?? [], ...reads];
|
|
272
273
|
return roots.some((root) => path === root || path.startsWith(`${root === "/" ? "" : root}/`));
|
|
@@ -279,21 +280,24 @@ function guardExtension(lookup, tools) {
|
|
|
279
280
|
(tool) => wrapTool(tool, (inner) => ({
|
|
280
281
|
...inner,
|
|
281
282
|
async execute(args, api, context) {
|
|
282
|
-
const { agents, reads } = await lookup();
|
|
283
|
+
const { agents, reads, layout = LEGACY, enforced } = await lookup();
|
|
283
284
|
const record = Object.values(agents.state().scoops).find(
|
|
284
285
|
(scoop) => scoop.conversation === api.conversationId
|
|
285
286
|
);
|
|
286
|
-
if (!record) return inner.execute(args, api, context);
|
|
287
|
+
if (!record || enforced) return inner.execute(args, api, context);
|
|
288
|
+
const own = layout.scoopRoot(record.folder);
|
|
289
|
+
const cone = layout.users ? own : HOME;
|
|
287
290
|
const path = String(args.path);
|
|
288
|
-
const asked = normalize(resolve(workspace(record.folder), path));
|
|
291
|
+
const asked = normalize(resolve(layout.workspace(record.folder), path));
|
|
289
292
|
const canonical = await api.env?.canonicalPath(asked, context);
|
|
290
293
|
const target = canonical?.ok ? canonical.value : asked;
|
|
291
294
|
const writing = WRITES.has(inner.name);
|
|
292
295
|
const skills = reads?.() ?? [];
|
|
293
|
-
if (allowed(record,
|
|
296
|
+
if (allowed(record, cone, target, writing, skills, own) || allowed(record, cone, asked, writing, skills, own))
|
|
294
297
|
return inner.execute(args, api, context);
|
|
298
|
+
const reach = layout.users || WRITES.has(inner.name) ? "" : `, and reads ${HOME}`;
|
|
295
299
|
return refusal(
|
|
296
|
-
`${target} is outside this scoop's folders. ${inner.name} reaches ${
|
|
300
|
+
`${target} is outside this scoop's folders. ${inner.name} reaches ${own} and /tmp${reach}.`
|
|
297
301
|
);
|
|
298
302
|
}
|
|
299
303
|
}))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/scoops/extension.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n AssistantEntry,\n type ConversationId,\n defineExtension,\n defineTask,\n type Extension,\n type PromptInput,\n type Submission,\n section,\n type ToolRegistration,\n type Tx,\n wrapTool,\n} from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport { AgentsDoc, live, type ScoopRecord } from '../agents.ts';\nimport { HOME } from '../kernel/env.ts';\nimport { normalize, resolve } from '../kernel/paths.ts';\nimport type { LickEvent } from '../licks/licks.ts';\nimport { FROM_KIND } from './from.ts';\nimport { type Feed, SCOOPS_ROOT, type ScoopsHost, ScoopWorkDoc, workspace } from './service.ts';\n\nexport const PREVIEW = 1000;\n\ntype Lookup = () => Promise<ScoopsHost>;\n\nexport function scoopFacts(record: Pick<ScoopRecord, 'name' | 'folder' | 'role'>): string {\n return [\n `You are the scoop \"${record.name}\"${record.role ? ` (role: ${record.role})` : ''}, a helper agent working for a cone. Messages come from the cone or from the user at a terminal; your final answer goes back to whoever asked, so end every task with a complete answer.`,\n `Work in ${workspace(record.folder)}. Your read, write and edit tools only reach ${SCOOPS_ROOT}/${record.folder} and /tmp, and read ${HOME}.`,\n 'Your bash is not confined: it sees the whole file system and every process. Stay in your folder anyway, and change nothing outside it unless the request says so.',\n 'You may run `agent` synchronously for a bounded side task (calls nest at most three deep), but you cannot start asynchronous scoops (`agent --async`, `subagent spawn`).',\n ].join('\\n');\n}\n\nfunction lines(text: string): number {\n return text ? text.split('\\n').length : 0;\n}\n\nexport type ReportResult = { text: string; failed: string | null; path: string | null };\n\nexport function reportLick(\n record: ScoopRecord,\n id: string,\n report: ReportResult,\n route: { target?: string | null; channel?: 'scoop-notify' | 'bash' } = {}\n): LickEvent {\n const status = report.failed ? (report.failed === 'aborted' ? 'stopped' : 'failed') : 'completed';\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n const preview = report.text.length > PREVIEW ? `${report.text.slice(0, PREVIEW)}\u2026` : report.text;\n const where = report.path ? `Output: ${report.path} (${lines(report.text)} lines)` : null;\n const reason = report.failed && report.failed !== 'aborted' ? `Reason: ${report.failed}` : null;\n return {\n channel: route.channel ?? 'scoop-notify',\n source: id,\n title: label,\n text: `[scoop ${record.name} (${record.role ?? 'scoop'}) ${status}]`,\n body: [where, reason, preview].filter(Boolean).join('\\n\\n'),\n target: (route.target ?? `cone:${record.cone}`) as LickEvent['target'],\n ...(report.failed && report.failed !== 'aborted' ? { severity: 'warn' as const } : {}),\n };\n}\n\ntype Noting = {\n commit: (\n write: (\n tx: Tx\n ) => Promise<{ status: 'running'; checkpoint: { phase: 'deliver'; noted: true } }>,\n context: Context\n ) => Promise<unknown>;\n};\n\nexport async function noteWhenPlaced(\n runtime: Noting,\n submission: Pick<Submission, 'status'>,\n conversation: ConversationId,\n note: { from: string | undefined; agent?: boolean; noted: boolean | undefined },\n context: Context\n): Promise<void> {\n const { from } = note;\n while (from && !note.noted && !context.abortSignal?.aborted) {\n const record = await submission.status(context);\n if (record.status !== 'queued') {\n if (!('entry' in record) || record.entry === undefined) return;\n const entry = record.entry;\n await runtime\n .commit(async (tx) => {\n await tx.appendEntry(conversation, {\n kind: FROM_KIND,\n data: { from, entry, ...(note.agent ? { agent: true } : {}) },\n });\n return { status: 'running', checkpoint: { phase: 'deliver', noted: true } };\n }, context)\n .catch(() => undefined);\n return;\n }\n await new Promise((done) => setTimeout(done, NOTE_POLL_MS));\n }\n}\n\nexport const NOTE_POLL_MS = 100;\n\nexport function waitTask(lookup: Lookup) {\n type WaitInput = { scoops: string[]; cone: string; deadline: number };\n\n return defineTask<WaitInput, { phase: 'start' } | { phase: 'watch' }, null>({\n name: 'slicc.scoop-wait',\n version: 1,\n initial: () => ({ phase: 'start' }),\n phases: {\n async start(task, runtime, context) {\n await runtime.commit(async (tx) => {\n (await tx.doc(ScoopWorkDoc)).waits[String(task.id)] = {\n scoops: task.input.scoops,\n done: {},\n cone: task.input.cone,\n };\n return { status: 'running', checkpoint: { phase: 'watch' } };\n }, context);\n },\n async watch(task, runtime, context) {\n const { agents, licks } = await lookup();\n const key = String(task.id);\n for (;;) {\n const work = await runtime.snapshot(ScoopWorkDoc, context);\n const state = work?.waits[key];\n if (!state) break;\n const feeding = new Set(Object.values(work?.feeds ?? {}).map((feed) => feed.scoop));\n const open = state.scoops.filter((id) => !(id in state.done) && feeding.has(id));\n const expired = runtime.now() >= task.input.deadline;\n if (open.length && !expired) {\n await runtime.sleep(Math.min(runtime.now() + 300, task.input.deadline), context);\n continue;\n }\n const names = (id: string) => agents.state().scoops[id]?.name ?? id;\n const body = state.scoops.map((id) =>\n open.includes(id)\n ? `## ${names(id)}\\n(still working when the wait timed out)`\n : `## ${names(id)}\\n${state.done[id] ?? '(nothing was running)'}`\n );\n await licks.deliver(\n {\n channel: 'scoop-wait',\n source: key,\n title: `Waited for ${state.scoops.map(names).join(', ')}`,\n text: open.length\n ? `${state.scoops.length - open.length} of ${state.scoops.length} done; timed out waiting for ${open.map(names).join(', ')}`\n : `All ${state.scoops.length} done`,\n body: body.join('\\n\\n'),\n target: `cone:${state.cone}`,\n coalesce: false,\n eventId: `wait:${key}`,\n },\n context\n );\n break;\n }\n await runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).waits[key];\n return { status: 'terminal', outcome: { status: 'completed', result: null } };\n }, context);\n },\n },\n abort: (task, runtime, context) =>\n runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).waits[String(task.id)];\n return { status: 'terminal', outcome: { status: 'aborted' } };\n }, context),\n });\n}\n\nexport function scoopTasks(lookup: Lookup) {\n const anchor = defineTask<null, { phase: 'done' }, null>({\n name: 'slicc.scoop-anchor',\n version: 1,\n initial: () => ({ phase: 'done' }),\n phases: {\n done: (_task, runtime, context) =>\n runtime.commit(\n () => ({ status: 'terminal', outcome: { status: 'completed', result: null } }),\n context\n ),\n },\n abort: (_task, runtime, context) =>\n runtime.commit(() => ({ status: 'terminal', outcome: { status: 'aborted' } }), context),\n });\n\n type ReporterInput = {\n scoop: string;\n prompt: string;\n followUp?: boolean;\n request?: string;\n };\n type ReporterState =\n | { phase: 'deliver'; noted?: boolean }\n | { phase: 'report'; text: string; failed: string | null };\n\n const reporter = defineTask<ReporterInput, ReporterState, ReportResult>({\n name: 'slicc.scoop-reporter',\n version: 1,\n initial: () => ({ phase: 'deliver' }),\n phases: {\n async deliver(task, runtime, context) {\n const { agents } = await lookup();\n const record = agents.state().scoops[task.input.scoop];\n const handle =\n record && live(record)\n ? await runtime.conversation(record.conversation as ConversationId, context)\n : undefined;\n if (!handle) {\n await runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).feeds[String(task.id)];\n return {\n status: 'terminal',\n outcome: {\n status: 'completed',\n result: { text: '', failed: 'the scoop is gone', path: null },\n },\n };\n }, context);\n return;\n }\n const requestId = task.input.request ? `subagent:${task.input.request}` : `feed:${task.id}`;\n const feed = (await runtime.snapshot(ScoopWorkDoc, context))?.feeds[String(task.id)];\n const submission = await handle.submit(\n {\n type: 'input',\n content: task.input.prompt,\n whenBusy: task.input.followUp ? 'followUp' : 'steer',\n requestId,\n },\n context\n );\n const noting = noteWhenPlaced(\n runtime,\n submission,\n record?.conversation as ConversationId,\n { from: feed?.from, agent: feed?.agent === true, noted: task.state.checkpoint.noted },\n context\n );\n const settled = await submission.wait(context);\n await noting;\n await runtime.commit(async (tx) => {\n if (settled.status !== 'done' || settled.type !== 'input')\n return {\n status: 'running',\n checkpoint: {\n phase: 'report',\n text: '',\n failed: String(settled.reason),\n },\n };\n const answer = await tx.entry(AssistantEntry, settled.answer);\n return {\n status: 'running',\n checkpoint: {\n phase: 'report',\n text: answerText(answer?.model?.[0]?.content),\n failed: null,\n },\n };\n }, context);\n },\n async report(task, runtime, context) {\n const { agents, licks } = await lookup();\n const id = task.input.scoop;\n const record = agents.state().scoops[id];\n const { text, failed } = task.state.checkpoint;\n const path =\n record && text ? `${SCOOPS_ROOT}/${record.folder}/reports/${task.id}.md` : null;\n if (path)\n await (await runtime.env(context))?.writeFile(\n path,\n text.endsWith('\\n') ? text : `${text}\\n`,\n context\n );\n const work = await runtime.snapshot(ScoopWorkDoc, context);\n const entry = work?.feeds[String(task.id)] as Feed;\n const waiting = (wait: { scoops: string[]; done: Record<string, string> }) =>\n wait.scoops.includes(id) && !(id in wait.done);\n const folded = Object.values(work?.waits ?? {}).some(waiting);\n const route = { target: entry.target, channel: entry.channel };\n if (!folded && record && entry.report && failed !== 'aborted')\n await licks.deliver(\n {\n ...reportLick(record, id, { text, failed, path }, route),\n eventId: `report:${task.id}`,\n },\n context\n );\n await runtime.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const wait of Object.values(work.waits))\n if (waiting(wait))\n wait.done[id] = failed\n ? `stopped: ${failed}`\n : `${path ? `Output: ${path}\\n` : ''}${text || '(no text)'}`;\n delete work.feeds[String(task.id)];\n return {\n status: 'terminal',\n outcome: { status: 'completed', result: { text, failed, path } },\n };\n }, context);\n },\n },\n abort: (task, runtime, context) =>\n runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).feeds[String(task.id)];\n return { status: 'terminal', outcome: { status: 'aborted' } };\n }, context),\n });\n\n return { anchor, reporter, wait: waitTask(lookup) };\n}\n\nasync function whose(input: PromptInput, context: Context) {\n const state = await input.read.snapshot(AgentsDoc, context);\n const scoop = Object.values(state?.scoops ?? {}).find(\n (record) => record.conversation === input.conversationId\n );\n return { scoop };\n}\n\nexport function scoopsExtension(tasks: ReturnType<typeof scoopTasks>): Extension {\n return defineExtension({\n name: 'slicc-scoops',\n tasks: [tasks.anchor, tasks.reporter, tasks.wait],\n sections: [\n section('scoop', async (input, context) => {\n const { scoop } = await whose(input, context);\n return scoop ? scoopFacts(scoop) : undefined;\n }),\n ],\n });\n}\n\nconst WRITES = new Set(['write', 'edit']);\n\nexport function allowed(\n record: Pick<ScoopRecord, 'folder'> & { roots?: ScoopRecord['roots'] },\n coneCwd: string,\n path: string,\n writing: boolean,\n reads: readonly string[] = []\n): boolean {\n const own = `${SCOOPS_ROOT}/${record.folder}`;\n const write = [own, '/tmp', ...(record.roots?.write ?? [])];\n const roots = writing ? write : [...write, coneCwd, ...(record.roots?.read ?? []), ...reads];\n return roots.some((root) => path === root || path.startsWith(`${root === '/' ? '' : root}/`));\n}\n\nfunction refusal(value: string) {\n return { content: [{ type: 'text' as const, text: value }], isError: true };\n}\n\nexport function guardExtension(lookup: Lookup, tools: readonly ToolRegistration[]): Extension {\n const wraps = tools\n .filter((tool) => tool.name === 'read' || WRITES.has(tool.name))\n .map((tool) =>\n wrapTool(tool, (inner) => ({\n ...inner,\n async execute(args, api, context) {\n const { agents, reads } = await lookup();\n const record = Object.values(agents.state().scoops).find(\n (scoop) => scoop.conversation === api.conversationId\n );\n if (!record) return inner.execute(args, api, context);\n const path = String((args as { path: unknown }).path);\n const asked = normalize(resolve(workspace(record.folder), path));\n const canonical = await api.env?.canonicalPath(asked, context);\n const target = canonical?.ok ? canonical.value : asked;\n const writing = WRITES.has(inner.name);\n const skills = reads?.() ?? [];\n if (\n allowed(record, HOME, target, writing, skills) ||\n allowed(record, HOME, asked, writing, skills)\n )\n return inner.execute(args, api, context);\n return refusal(\n `${target} is outside this scoop's folders. ${inner.name} reaches ${SCOOPS_ROOT}/${record.folder} and /tmp${WRITES.has(inner.name) ? '' : `, and reads ${HOME}`}.`\n );\n },\n }))\n );\n return defineExtension({ name: 'slicc-scoop-guard', wraps });\n}\n"],
|
|
5
|
-
"mappings": "AACA;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EAIA;AAAA,EAGA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,WAAW,YAA8B;AAClD,SAAS,YAAY;AACrB,SAAS,WAAW,eAAe;
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n AssistantEntry,\n type ConversationId,\n defineExtension,\n defineTask,\n type Extension,\n type PromptInput,\n type Submission,\n section,\n type ToolRegistration,\n type Tx,\n wrapTool,\n} from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport { AgentsDoc, live, type ScoopRecord } from '../agents.ts';\nimport { HOME } from '../kernel/env.ts';\nimport { normalize, resolve } from '../kernel/paths.ts';\nimport { type Layout, LEGACY } from '../layout.ts';\nimport type { LickEvent } from '../licks/licks.ts';\nimport { FROM_KIND } from './from.ts';\nimport { type Feed, type ScoopsHost, ScoopWorkDoc } from './service.ts';\n\nexport const PREVIEW = 1000;\n\ntype Lookup = () => Promise<ScoopsHost>;\n\nexport function scoopFacts(\n record: Pick<ScoopRecord, 'name' | 'folder' | 'role'> & { cone?: string },\n layout: Layout = LEGACY\n): string {\n const place = layout.workspace(record.folder);\n return [\n `You are the scoop \"${record.name}\"${record.role ? ` (role: ${record.role})` : ''}, a helper agent working for a cone. Messages come from the cone or from the user at a terminal; your final answer goes back to whoever asked, so end every task with a complete answer.`,\n layout.users\n ? `You run as the user ${layout.scoopRoot(record.folder).slice('/home/'.length)}, and your home is ${place}: work there. Your cone can read your home; you can't read your cone's home or another scoop's. /tmp is shared scratch.`\n : `Work in ${place}. Your read, write and edit tools only reach ${layout.scoopRoot(record.folder)} and /tmp, and read ${HOME}.`,\n layout.users\n ? 'Your bash runs as your user too, so the kernel decides what it may read and change. Stay in your home, and change nothing outside it unless the request says so.'\n : 'Your bash is not confined: it sees the whole file system and every process. Stay in your folder anyway, and change nothing outside it unless the request says so.',\n 'You may run `agent` synchronously for a bounded side task (calls nest at most three deep), but you cannot start asynchronous scoops (`agent --async`, `subagent spawn`).',\n ].join('\\n');\n}\n\nfunction lines(text: string): number {\n return text ? text.split('\\n').length : 0;\n}\n\nexport type ReportResult = { text: string; failed: string | null; path: string | null };\n\nexport function reportLick(\n record: ScoopRecord,\n id: string,\n report: ReportResult,\n route: { target?: string | null; channel?: 'scoop-notify' | 'bash' } = {}\n): LickEvent {\n const status = report.failed ? (report.failed === 'aborted' ? 'stopped' : 'failed') : 'completed';\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n const preview = report.text.length > PREVIEW ? `${report.text.slice(0, PREVIEW)}\u2026` : report.text;\n const where = report.path ? `Output: ${report.path} (${lines(report.text)} lines)` : null;\n const reason = report.failed && report.failed !== 'aborted' ? `Reason: ${report.failed}` : null;\n return {\n channel: route.channel ?? 'scoop-notify',\n source: id,\n title: label,\n text: `[scoop ${record.name} (${record.role ?? 'scoop'}) ${status}]`,\n body: [where, reason, preview].filter(Boolean).join('\\n\\n'),\n target: (route.target ?? `cone:${record.cone}`) as LickEvent['target'],\n ...(report.failed && report.failed !== 'aborted' ? { severity: 'warn' as const } : {}),\n };\n}\n\ntype Noting = {\n commit: (\n write: (\n tx: Tx\n ) => Promise<{ status: 'running'; checkpoint: { phase: 'deliver'; noted: true } }>,\n context: Context\n ) => Promise<unknown>;\n};\n\nexport async function noteWhenPlaced(\n runtime: Noting,\n submission: Pick<Submission, 'status'>,\n conversation: ConversationId,\n note: { from: string | undefined; agent?: boolean; noted: boolean | undefined },\n context: Context\n): Promise<void> {\n const { from } = note;\n while (from && !note.noted && !context.abortSignal?.aborted) {\n const record = await submission.status(context);\n if (record.status !== 'queued') {\n if (!('entry' in record) || record.entry === undefined) return;\n const entry = record.entry;\n await runtime\n .commit(async (tx) => {\n await tx.appendEntry(conversation, {\n kind: FROM_KIND,\n data: { from, entry, ...(note.agent ? { agent: true } : {}) },\n });\n return { status: 'running', checkpoint: { phase: 'deliver', noted: true } };\n }, context)\n .catch(() => undefined);\n return;\n }\n await new Promise((done) => setTimeout(done, NOTE_POLL_MS));\n }\n}\n\nexport const NOTE_POLL_MS = 100;\n\nexport function waitTask(lookup: Lookup) {\n type WaitInput = { scoops: string[]; cone: string; deadline: number };\n\n return defineTask<WaitInput, { phase: 'start' } | { phase: 'watch' }, null>({\n name: 'slicc.scoop-wait',\n version: 1,\n initial: () => ({ phase: 'start' }),\n phases: {\n async start(task, runtime, context) {\n await runtime.commit(async (tx) => {\n (await tx.doc(ScoopWorkDoc)).waits[String(task.id)] = {\n scoops: task.input.scoops,\n done: {},\n cone: task.input.cone,\n };\n return { status: 'running', checkpoint: { phase: 'watch' } };\n }, context);\n },\n async watch(task, runtime, context) {\n const { agents, licks } = await lookup();\n const key = String(task.id);\n for (;;) {\n const work = await runtime.snapshot(ScoopWorkDoc, context);\n const state = work?.waits[key];\n if (!state) break;\n const feeding = new Set(Object.values(work?.feeds ?? {}).map((feed) => feed.scoop));\n const open = state.scoops.filter((id) => !(id in state.done) && feeding.has(id));\n const expired = runtime.now() >= task.input.deadline;\n if (open.length && !expired) {\n await runtime.sleep(Math.min(runtime.now() + 300, task.input.deadline), context);\n continue;\n }\n const names = (id: string) => agents.state().scoops[id]?.name ?? id;\n const body = state.scoops.map((id) =>\n open.includes(id)\n ? `## ${names(id)}\\n(still working when the wait timed out)`\n : `## ${names(id)}\\n${state.done[id] ?? '(nothing was running)'}`\n );\n await licks.deliver(\n {\n channel: 'scoop-wait',\n source: key,\n title: `Waited for ${state.scoops.map(names).join(', ')}`,\n text: open.length\n ? `${state.scoops.length - open.length} of ${state.scoops.length} done; timed out waiting for ${open.map(names).join(', ')}`\n : `All ${state.scoops.length} done`,\n body: body.join('\\n\\n'),\n target: `cone:${state.cone}`,\n coalesce: false,\n eventId: `wait:${key}`,\n },\n context\n );\n break;\n }\n await runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).waits[key];\n return { status: 'terminal', outcome: { status: 'completed', result: null } };\n }, context);\n },\n },\n abort: (task, runtime, context) =>\n runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).waits[String(task.id)];\n return { status: 'terminal', outcome: { status: 'aborted' } };\n }, context),\n });\n}\n\nexport function scoopTasks(lookup: Lookup) {\n const anchor = defineTask<null, { phase: 'done' }, null>({\n name: 'slicc.scoop-anchor',\n version: 1,\n initial: () => ({ phase: 'done' }),\n phases: {\n done: (_task, runtime, context) =>\n runtime.commit(\n () => ({ status: 'terminal', outcome: { status: 'completed', result: null } }),\n context\n ),\n },\n abort: (_task, runtime, context) =>\n runtime.commit(() => ({ status: 'terminal', outcome: { status: 'aborted' } }), context),\n });\n\n type ReporterInput = {\n scoop: string;\n prompt: string;\n followUp?: boolean;\n request?: string;\n };\n type ReporterState =\n | { phase: 'deliver'; noted?: boolean }\n | { phase: 'report'; text: string; failed: string | null };\n\n const reporter = defineTask<ReporterInput, ReporterState, ReportResult>({\n name: 'slicc.scoop-reporter',\n version: 1,\n initial: () => ({ phase: 'deliver' }),\n phases: {\n async deliver(task, runtime, context) {\n const { agents } = await lookup();\n const record = agents.state().scoops[task.input.scoop];\n const handle =\n record && live(record)\n ? await runtime.conversation(record.conversation as ConversationId, context)\n : undefined;\n if (!handle) {\n await runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).feeds[String(task.id)];\n return {\n status: 'terminal',\n outcome: {\n status: 'completed',\n result: { text: '', failed: 'the scoop is gone', path: null },\n },\n };\n }, context);\n return;\n }\n const requestId = task.input.request ? `subagent:${task.input.request}` : `feed:${task.id}`;\n const feed = (await runtime.snapshot(ScoopWorkDoc, context))?.feeds[String(task.id)];\n const submission = await handle.submit(\n {\n type: 'input',\n content: task.input.prompt,\n whenBusy: task.input.followUp ? 'followUp' : 'steer',\n requestId,\n },\n context\n );\n const noting = noteWhenPlaced(\n runtime,\n submission,\n record?.conversation as ConversationId,\n { from: feed?.from, agent: feed?.agent === true, noted: task.state.checkpoint.noted },\n context\n );\n const settled = await submission.wait(context);\n await noting;\n await runtime.commit(async (tx) => {\n if (settled.status !== 'done' || settled.type !== 'input')\n return {\n status: 'running',\n checkpoint: {\n phase: 'report',\n text: '',\n failed: String(settled.reason),\n },\n };\n const answer = await tx.entry(AssistantEntry, settled.answer);\n return {\n status: 'running',\n checkpoint: {\n phase: 'report',\n text: answerText(answer?.model?.[0]?.content),\n failed: null,\n },\n };\n }, context);\n },\n async report(task, runtime, context) {\n const { agents, licks, layout = LEGACY } = await lookup();\n const id = task.input.scoop;\n const record = agents.state().scoops[id];\n const { text, failed } = task.state.checkpoint;\n const path =\n record && text ? `${layout.reports(record.folder, record.cone)}/${task.id}.md` : null;\n if (path)\n await (await runtime.env(context))?.writeFile(\n path,\n text.endsWith('\\n') ? text : `${text}\\n`,\n context\n );\n const work = await runtime.snapshot(ScoopWorkDoc, context);\n const entry = work?.feeds[String(task.id)] as Feed;\n const waiting = (wait: { scoops: string[]; done: Record<string, string> }) =>\n wait.scoops.includes(id) && !(id in wait.done);\n const folded = Object.values(work?.waits ?? {}).some(waiting);\n const route = { target: entry.target, channel: entry.channel };\n if (!folded && record && entry.report && failed !== 'aborted')\n await licks.deliver(\n {\n ...reportLick(record, id, { text, failed, path }, route),\n eventId: `report:${task.id}`,\n },\n context\n );\n await runtime.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const wait of Object.values(work.waits))\n if (waiting(wait))\n wait.done[id] = failed\n ? `stopped: ${failed}`\n : `${path ? `Output: ${path}\\n` : ''}${text || '(no text)'}`;\n delete work.feeds[String(task.id)];\n return {\n status: 'terminal',\n outcome: { status: 'completed', result: { text, failed, path } },\n };\n }, context);\n },\n },\n abort: (task, runtime, context) =>\n runtime.commit(async (tx) => {\n delete (await tx.doc(ScoopWorkDoc)).feeds[String(task.id)];\n return { status: 'terminal', outcome: { status: 'aborted' } };\n }, context),\n });\n\n return { anchor, reporter, wait: waitTask(lookup) };\n}\n\nasync function whose(input: PromptInput, context: Context) {\n const state = await input.read.snapshot(AgentsDoc, context);\n const scoop = Object.values(state?.scoops ?? {}).find(\n (record) => record.conversation === input.conversationId\n );\n return { scoop };\n}\n\nexport function scoopsExtension(\n tasks: ReturnType<typeof scoopTasks>,\n layout: () => Layout = () => LEGACY\n): Extension {\n return defineExtension({\n name: 'slicc-scoops',\n tasks: [tasks.anchor, tasks.reporter, tasks.wait],\n sections: [\n section('scoop', async (input, context) => {\n const { scoop } = await whose(input, context);\n return scoop ? scoopFacts(scoop, layout()) : undefined;\n }),\n ],\n });\n}\n\nconst WRITES = new Set(['write', 'edit']);\n\nexport function allowed(\n record: Pick<ScoopRecord, 'folder'> & { roots?: ScoopRecord['roots'] },\n coneCwd: string,\n path: string,\n writing: boolean,\n reads: readonly string[] = [],\n own = LEGACY.scoopRoot(record.folder)\n): boolean {\n const write = [own, '/tmp', ...(record.roots?.write ?? [])];\n const roots = writing ? write : [...write, coneCwd, ...(record.roots?.read ?? []), ...reads];\n return roots.some((root) => path === root || path.startsWith(`${root === '/' ? '' : root}/`));\n}\n\nfunction refusal(value: string) {\n return { content: [{ type: 'text' as const, text: value }], isError: true };\n}\n\nexport function guardExtension(lookup: Lookup, tools: readonly ToolRegistration[]): Extension {\n const wraps = tools\n .filter((tool) => tool.name === 'read' || WRITES.has(tool.name))\n .map((tool) =>\n wrapTool(tool, (inner) => ({\n ...inner,\n async execute(args, api, context) {\n const { agents, reads, layout = LEGACY, enforced } = await lookup();\n const record = Object.values(agents.state().scoops).find(\n (scoop) => scoop.conversation === api.conversationId\n );\n if (!record || enforced) return inner.execute(args, api, context);\n const own = layout.scoopRoot(record.folder);\n const cone = layout.users ? own : HOME;\n const path = String((args as { path: unknown }).path);\n const asked = normalize(resolve(layout.workspace(record.folder), path));\n const canonical = await api.env?.canonicalPath(asked, context);\n const target = canonical?.ok ? canonical.value : asked;\n const writing = WRITES.has(inner.name);\n const skills = reads?.() ?? [];\n if (\n allowed(record, cone, target, writing, skills, own) ||\n allowed(record, cone, asked, writing, skills, own)\n )\n return inner.execute(args, api, context);\n const reach = layout.users || WRITES.has(inner.name) ? '' : `, and reads ${HOME}`;\n return refusal(\n `${target} is outside this scoop's folders. ${inner.name} reaches ${own} and /tmp${reach}.`\n );\n },\n }))\n );\n return defineExtension({ name: 'slicc-scoop-guard', wraps });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["work"]
|
|
7
7
|
}
|