@ai-ecoverse/slicc-agent 3.5.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +21 -4
  2. package/bin/agent +76 -0
  3. package/dist/agent.js +7 -14
  4. package/dist/agent.js.map +2 -2
  5. package/dist/agents.js +133 -0
  6. package/dist/agents.js.map +7 -0
  7. package/dist/client.js +3 -1
  8. package/dist/client.js.map +2 -2
  9. package/dist/cone.js +2 -16
  10. package/dist/cone.js.map +2 -2
  11. package/dist/control.js +68 -10
  12. package/dist/control.js.map +2 -2
  13. package/dist/host.js +11 -2
  14. package/dist/host.js.map +2 -2
  15. package/dist/kernel/env.js +49 -5
  16. package/dist/kernel/env.js.map +2 -2
  17. package/dist/kernel/exec.js +2 -1
  18. package/dist/kernel/exec.js.map +2 -2
  19. package/dist/kernel/groups.js +31 -0
  20. package/dist/kernel/groups.js.map +7 -0
  21. package/dist/kernel/watch.js +86 -0
  22. package/dist/kernel/watch.js.map +2 -2
  23. package/dist/licks/index.js +16 -1
  24. package/dist/licks/index.js.map +2 -2
  25. package/dist/licks/lick.js.map +1 -1
  26. package/dist/licks/licks.js +12 -1
  27. package/dist/licks/licks.js.map +2 -2
  28. package/dist/main.js +38 -9
  29. package/dist/main.js.map +2 -2
  30. package/dist/roles/frontmatter.js +59 -0
  31. package/dist/roles/frontmatter.js.map +7 -0
  32. package/dist/roles/roles.js +204 -0
  33. package/dist/roles/roles.js.map +7 -0
  34. package/dist/scoops/cli.js +391 -0
  35. package/dist/scoops/cli.js.map +7 -0
  36. package/dist/scoops/extension.js +301 -0
  37. package/dist/scoops/extension.js.map +7 -0
  38. package/dist/scoops/identity.js +33 -0
  39. package/dist/scoops/identity.js.map +7 -0
  40. package/dist/scoops/index.js +120 -0
  41. package/dist/scoops/index.js.map +7 -0
  42. package/dist/scoops/requests.js +136 -0
  43. package/dist/scoops/requests.js.map +7 -0
  44. package/dist/scoops/service.js +409 -0
  45. package/dist/scoops/service.js.map +7 -0
  46. package/dist/scoops/sync.js +252 -0
  47. package/dist/scoops/sync.js.map +7 -0
  48. package/dist/scoops/visible.js +15 -0
  49. package/dist/scoops/visible.js.map +7 -0
  50. package/dist/services.js.map +2 -2
  51. package/dist/spectrum/agent-port.js +137 -54
  52. package/dist/spectrum/agent-port.js.map +2 -2
  53. package/dist/spectrum/messages.js +19 -10
  54. package/dist/spectrum/messages.js.map +2 -2
  55. package/dist/types/agent.d.ts +3 -1
  56. package/dist/types/agents.d.ts +54 -0
  57. package/dist/types/client.d.ts +3 -1
  58. package/dist/types/cone.d.ts +1 -3
  59. package/dist/types/control.d.ts +7 -1
  60. package/dist/types/host.d.ts +2 -1
  61. package/dist/types/kernel/client.d.ts +13 -0
  62. package/dist/types/kernel/env.d.ts +13 -2
  63. package/dist/types/kernel/exec.d.ts +2 -2
  64. package/dist/types/kernel/groups.d.ts +7 -0
  65. package/dist/types/kernel/watch.d.ts +12 -1
  66. package/dist/types/licks/index.d.ts +5 -0
  67. package/dist/types/licks/lick.d.ts +1 -1
  68. package/dist/types/licks/licks.d.ts +2 -1
  69. package/dist/types/main.d.ts +3 -0
  70. package/dist/types/roles/frontmatter.d.ts +7 -0
  71. package/dist/types/roles/roles.d.ts +48 -0
  72. package/dist/types/scoops/cli.d.ts +66 -0
  73. package/dist/types/scoops/extension.d.ts +63 -0
  74. package/dist/types/scoops/identity.d.ts +6 -0
  75. package/dist/types/scoops/index.d.ts +37 -0
  76. package/dist/types/scoops/requests.d.ts +32 -0
  77. package/dist/types/scoops/service.d.ts +116 -0
  78. package/dist/types/scoops/sync.d.ts +22 -0
  79. package/dist/types/scoops/visible.d.ts +4 -0
  80. package/dist/types/services.d.ts +30 -0
  81. package/dist/types/spectrum/agent-port.d.ts +13 -11
  82. package/dist/types/views.d.ts +12 -0
  83. package/dist/views.js +89 -0
  84. package/dist/views.js.map +7 -0
  85. package/package.json +6 -4
  86. package/packages/vfs-root/agents/delegate.md +8 -0
  87. package/packages/vfs-root/agents/oracle.md +25 -0
  88. package/packages/vfs-root/agents/reviewer.md +23 -0
  89. package/packages/vfs-root/agents/scout.md +30 -0
  90. package/packages/vfs-root/agents/worker.md +23 -0
  91. package/packages/vfs-root/skills/agent/SKILL.md +72 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/roles/roles.ts"],
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { type FrontmatterValue, parseFrontmatter } from './frontmatter.ts';\n\nexport type RoleSource = 'builtin' | 'package' | 'user' | 'project';\nexport type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\nexport interface Role {\n name: string;\n description: string;\n prompt: string;\n mode: 'replace' | 'append';\n tools?: string[];\n model?: string;\n thinking?: Thinking;\n aliases: string[];\n output?: string;\n source: RoleSource;\n path: string;\n}\n\nexport interface Roles {\n roles: Role[];\n warnings: string[];\n limits: { maxLiveScoops: number; maxPerTurn: number };\n}\n\nexport const DEFAULT_LIMITS = { maxLiveScoops: 16, maxPerTurn: 64 };\n\nconst TOOLS: Record<string, string> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'bash',\n find: 'bash',\n ls: 'bash',\n};\n\nconst THINKING = new Set<string>(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\n\nconst APPLIED = new Set([\n 'name',\n 'description',\n 'tools',\n 'model',\n 'thinking',\n 'systemPromptMode',\n 'aliases',\n 'output',\n 'package',\n 'advertise',\n 'inheritProjectContext',\n 'inheritSkills',\n 'skills',\n 'defaultReads',\n]);\n\nconst LATER: Record<string, string> = {\n memory: 'per-agent memory comes with SLICC\u2019s memory panel',\n};\n\nexport type RoleFiles = Pick<ExecutionEnv, 'readTextFile' | 'listDir'>;\n\nexport interface RoleSourceDir {\n source: RoleSource;\n dir: string;\n}\n\nfunction list(value: FrontmatterValue | undefined): string[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string')\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction tools(names: string[], where: string, warnings: string[]): string[] {\n const mapped: string[] = [];\n for (const name of names) {\n const tool = TOOLS[name];\n if (tool) {\n if (!mapped.includes(tool)) mapped.push(tool);\n } else warnings.push(`${where}: tool \"${name}\" isn't available in SLICC; it's left out`);\n }\n return mapped;\n}\n\nexport function parseRole(\n text: string,\n source: RoleSource,\n path: string,\n warnings: string[]\n): Role | undefined {\n const { fields, body, problems } = parseFrontmatter(text);\n for (const problem of problems) warnings.push(`${path}: ${problem}`);\n const name = fields.name;\n const description = fields.description;\n if (typeof name !== 'string' || typeof description !== 'string') {\n warnings.push(`${path}: an agent file needs a name and a description; skipped`);\n return undefined;\n }\n for (const key of Object.keys(fields))\n if (!APPLIED.has(key))\n warnings.push(\n `${path}: \"${key}\" ${LATER[key] ? `is not read yet (${LATER[key]})` : \"isn't supported in SLICC; it's ignored\"}`\n );\n const thinking =\n typeof fields.thinking === 'string' && THINKING.has(fields.thinking)\n ? (fields.thinking as Thinking)\n : undefined;\n if (fields.thinking !== undefined && !thinking)\n warnings.push(`${path}: thinking \"${String(fields.thinking)}\" is unknown; ignored`);\n const pkg = typeof fields.package === 'string' && fields.package ? `${fields.package}.` : '';\n return {\n name: `${pkg}${name}`,\n description,\n prompt: body,\n mode: fields.systemPromptMode === 'append' ? 'append' : 'replace',\n ...(fields.tools !== undefined ? { tools: tools(list(fields.tools), path, warnings) } : {}),\n ...(typeof fields.model === 'string' ? { model: fields.model } : {}),\n ...(thinking ? { thinking } : {}),\n aliases: list(fields.aliases),\n ...(typeof fields.output === 'string' ? { output: fields.output } : {}),\n source,\n path,\n };\n}\n\nasync function markdown(\n files: RoleFiles,\n dir: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n if (dir.endsWith('.md')) return [dir];\n const listed = await files.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n const path = `${dir}/${info.name}`;\n if (info.kind === 'directory') out.push(...(await markdown(files, path, context, depth + 1)));\n else if (info.name.endsWith('.md') && !info.name.endsWith('.chain.md')) out.push(path);\n }\n return out.sort();\n}\n\ntype Override = {\n model?: unknown;\n thinking?: unknown;\n tools?: unknown;\n systemPrompt?: unknown;\n description?: unknown;\n disabled?: unknown;\n};\n\ninterface Settings {\n overrides: Record<string, Override>;\n limits: Roles['limits'];\n}\n\nfunction positive(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;\n}\n\nasync function settings(\n files: RoleFiles,\n path: string,\n context: Context,\n warnings: string[]\n): Promise<Settings> {\n const read = await files.readTextFile(path, context);\n const empty = { overrides: {}, limits: { ...DEFAULT_LIMITS } };\n if (!read.ok) return empty;\n let parsed: {\n subagents?: {\n agentOverrides?: Record<string, Override>;\n maxLiveScoops?: unknown;\n maxPerTurn?: unknown;\n };\n };\n try {\n parsed = JSON.parse(read.value);\n } catch (error) {\n warnings.push(`${path}: not valid JSON (${(error as Error).message}); overrides ignored`);\n return empty;\n }\n const subagents = parsed.subagents ?? {};\n return {\n overrides: subagents.agentOverrides ?? {},\n limits: {\n maxLiveScoops: positive(subagents.maxLiveScoops, DEFAULT_LIMITS.maxLiveScoops),\n maxPerTurn: positive(subagents.maxPerTurn, DEFAULT_LIMITS.maxPerTurn),\n },\n };\n}\n\nfunction apply(role: Role, override: Override | undefined, warnings: string[]): Role | undefined {\n if (!override) return role;\n if (override.disabled === true) return undefined;\n const next: Role = { ...role };\n if (typeof override.model === 'string') next.model = override.model;\n if (typeof override.thinking === 'string' && THINKING.has(override.thinking))\n next.thinking = override.thinking as Thinking;\n if (typeof override.description === 'string') next.description = override.description;\n if (typeof override.systemPrompt === 'string') next.prompt = override.systemPrompt;\n if (Array.isArray(override.tools))\n next.tools = tools(override.tools.map(String), `override for ${role.name}`, warnings);\n return next;\n}\n\nexport interface LoadOptions {\n files: RoleFiles;\n builtin: () => Promise<{ path: string; text: string }[]>;\n dirs: RoleSourceDir[];\n settingsPath: string;\n}\n\nconst ORDER: RoleSource[] = ['builtin', 'package', 'user', 'project'];\n\nexport async function loadRoles(options: LoadOptions, context: Context): Promise<Roles> {\n const warnings: string[] = [];\n const byName = new Map<string, Role>();\n const add = (role: Role | undefined) => {\n if (role) byName.set(role.name, role);\n };\n for (const { path, text } of await options.builtin())\n add(parseRole(text, 'builtin', path, warnings));\n const dirs = [...options.dirs].sort((a, b) => ORDER.indexOf(a.source) - ORDER.indexOf(b.source));\n for (const { source, dir } of dirs)\n for (const path of await markdown(options.files, dir, context)) {\n const read = await options.files.readTextFile(path, context);\n if (read.ok) add(parseRole(read.value, source, path, warnings));\n }\n const { overrides, limits } = await settings(\n options.files,\n options.settingsPath,\n context,\n warnings\n );\n const roles: Role[] = [];\n for (const role of byName.values()) {\n const applied = apply(role, overrides[role.name], warnings);\n if (applied) roles.push(applied);\n }\n return { roles, warnings, limits };\n}\n\nexport function findRole(roles: readonly Role[], name: string): Role | undefined {\n return (\n roles.find((role) => role.name === name) ?? roles.find((role) => role.aliases.includes(name))\n );\n}\n\nasync function manifestDirs(files: RoleFiles, root: string, context: Context): Promise<string[]> {\n const top = await files.listDir(root, context);\n if (!top.ok) return [];\n const out: string[] = [];\n for (const entry of top.value) {\n if (entry.kind !== 'directory' || entry.name.startsWith('.')) continue;\n if (!entry.name.startsWith('@')) {\n out.push(`${root}/${entry.name}`);\n continue;\n }\n const scoped = await files.listDir(`${root}/${entry.name}`, context);\n if (scoped.ok)\n for (const inner of scoped.value)\n if (inner.kind === 'directory') out.push(`${root}/${entry.name}/${inner.name}`);\n }\n return out;\n}\n\ntype Manifest = {\n 'pi-subagents'?: { agents?: unknown };\n pi?: { subagents?: { agents?: unknown } };\n};\n\nexport function agentPaths(dir: string, text: string): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const agents = manifest['pi-subagents']?.agents ?? manifest.pi?.subagents?.agents;\n const listed = Array.isArray(agents) ? agents : typeof agents === 'string' ? [agents] : [];\n return listed\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nexport async function packageDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const out: string[] = [];\n for (const dir of await manifestDirs(files, root, context)) {\n const read = await files.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...agentPaths(dir, read.value));\n }\n return out;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,391 @@
1
+ import { resolve } from "../kernel/paths.js";
2
+ import { findRole } from "../roles/roles.js";
3
+ import { findScoop, modelOf, SCOOPS_ROOT } from "./service.js";
4
+ import { cancelSync, detachSync, runSync } from "./sync.js";
5
+ const DEFAULT_WAIT_S = 30;
6
+ const MAX_DEPTH = 3;
7
+ const RUN_DIR = "/var/lib/slicc/agent/scoops";
8
+ const THINKING = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh"]);
9
+ const EFFORT = { low: "low", medium: "medium", high: "high", max: "xhigh" };
10
+ const USAGE = `usage:
11
+ agent [options] (--prompt <text> | --file <path> | -)... run a scoop, wait, print its answer
12
+ agent --async [options] (--prompt <text> | --file <path> | -)... start a scoop, print its handle
13
+ agent <cwd> <allowed-commands> <prompt> the same as a synchronous run, in v6's form
14
+ agent list [--agents] | status <handle> | rename <handle> <name>
15
+ agent send <handle> [--follow-up] (<message> | --file <path> | -)
16
+ agent send parent <note> from a scoop: a progress note to its cone
17
+ agent wait <handle>... [--timeout <seconds>] [--notify]
18
+ agent stop <handle>
19
+
20
+ options:
21
+ --name <name> --agent <role> --model <provider/model> --thinking <level> | --effort <low|medium|high|max>
22
+ --tools <a,b> --read-only <path,path> --system-prompt <text> | --system-prompt-file <path>
23
+ --background-after <seconds> --persist-session | --no-persist-session
24
+
25
+ A synchronous run removes the scoop's folder afterwards. Its transcript is archived in
26
+ /tmp/agent-sessions/<handle>.md, in /home/sessions/<handle>.md with --persist-session, or nowhere
27
+ with --no-persist-session. subagent is the same command: subagent spawn = agent --async.
28
+ `;
29
+ const ok = (out) => ({ code: 0, out });
30
+ const fail = (out, code = 1) => ({ code, out: `agent: ${out}
31
+ ` });
32
+ function isAnswer(value) {
33
+ return typeof value === "object" && value !== null && "code" in value && "out" in value;
34
+ }
35
+ function flags(argv, withValue) {
36
+ const values = /* @__PURE__ */ new Map();
37
+ const switches = /* @__PURE__ */ new Set();
38
+ const rest = [];
39
+ for (let at = 0; at < argv.length; at++) {
40
+ const arg = argv[at];
41
+ if (withValue.includes(arg)) {
42
+ const value = argv[at + 1];
43
+ if (value === void 0) throw new Error(`${arg} needs a value`);
44
+ values.set(arg, [...values.get(arg) ?? [], value]);
45
+ at++;
46
+ } else if (arg.startsWith("--")) switches.add(arg);
47
+ else rest.push(arg);
48
+ }
49
+ return { values, switches, rest };
50
+ }
51
+ function last(parsed, flag) {
52
+ return parsed.values.get(flag)?.at(-1);
53
+ }
54
+ function callerOf(agents, request) {
55
+ const state = agents.state();
56
+ if (request.caller.startsWith("cone:") && state.cones[request.caller.slice(5)]) {
57
+ const cone = request.caller.slice(5);
58
+ return { id: `cone:${cone}`, cone, fromAgent: true, scoop: null, depth: 0 };
59
+ }
60
+ const record = request.caller.startsWith("scoop:") ? state.scoops[request.caller] : void 0;
61
+ if (record)
62
+ return {
63
+ id: request.caller,
64
+ cone: record.cone,
65
+ fromAgent: true,
66
+ scoop: request.caller,
67
+ depth: record.depth
68
+ };
69
+ return { id: null, cone: agents.activeCone(), fromAgent: false, scoop: null, depth: 0 };
70
+ }
71
+ async function readText(deps, value, request, context) {
72
+ const read = await deps.env.readTextFile(resolve(request.cwd, value), context);
73
+ if (!read.ok) throw new Error(`can't read ${value}: ${read.error.message}`);
74
+ return read.value;
75
+ }
76
+ async function prompts(deps, argv, request, context) {
77
+ const out = [];
78
+ for (let at = 0; at < argv.length; at++) {
79
+ const arg = argv[at];
80
+ if (arg === "--prompt") out.push(argv[++at] ?? "");
81
+ else if (arg === "--file") out.push(await readText(deps, argv[++at] ?? "", request, context));
82
+ else if (arg === "-") out.push(request.stdin);
83
+ }
84
+ return out.filter((prompt) => prompt.trim());
85
+ }
86
+ function toolList(listed) {
87
+ if (listed === void 0 || listed === "auto" || listed === "full") return void 0;
88
+ return listed.split(",").map((tool) => tool.trim()).filter(Boolean);
89
+ }
90
+ function choices(parsed) {
91
+ const provider = last(parsed, "--provider");
92
+ const modelText = last(parsed, "--model");
93
+ const model = modelText ? provider ? { provider, modelId: modelText } : modelOf(modelText) : void 0;
94
+ if (modelText && !model)
95
+ return fail("--model needs provider/model, or --provider with --model", 2);
96
+ const effort = last(parsed, "--effort");
97
+ if (effort && !EFFORT[effort]) return fail("--effort must be low, medium, high or max", 2);
98
+ const thinking = last(parsed, "--thinking") ?? (effort ? EFFORT[effort] : void 0);
99
+ if (thinking && !THINKING.has(thinking))
100
+ return fail(`--thinking must be one of ${[...THINKING].join(", ")}`, 2);
101
+ if (last(parsed, "--tools") === "output")
102
+ return fail("--tools output needs --schema-b64, which is not supported in SLICC yet", 2);
103
+ const tools = toolList(last(parsed, "--tools"));
104
+ return {
105
+ ...model ? { model } : {},
106
+ ...thinking ? { thinking } : {},
107
+ ...tools ? { tools } : {}
108
+ };
109
+ }
110
+ async function role(deps, parsed) {
111
+ const roles = await deps.roles();
112
+ const name = last(parsed, "--agent");
113
+ const found = name ? findRole(roles.roles, name) : void 0;
114
+ if (name && !found)
115
+ return {
116
+ roles,
117
+ error: fail(`there is no agent role ${name}; \`agent list --agents\` shows them`)
118
+ };
119
+ return { roles, role: found };
120
+ }
121
+ function handle(deps, who, name) {
122
+ return name ? findScoop(deps.agents.state(), name, who.fromAgent ? who.cone : null) : void 0;
123
+ }
124
+ const ASYNC_VALUES = [
125
+ "--name",
126
+ "--agent",
127
+ "--provider",
128
+ "--model",
129
+ "--thinking",
130
+ "--effort",
131
+ "--tools",
132
+ "--prompt",
133
+ "--file"
134
+ ];
135
+ const ASYNC_SWITCHES = /* @__PURE__ */ new Set(["--async", "--no-extensions", "--no-skills", "--no-context-files"]);
136
+ const UNSUPPORTED = /* @__PURE__ */ new Set([
137
+ "--no-prompt-templates",
138
+ "--session",
139
+ "--resume",
140
+ "--image",
141
+ "--no-escalate",
142
+ "--minimal",
143
+ "--usage",
144
+ "--schema-b64",
145
+ "--cwd"
146
+ ]);
147
+ function unsupported(argv) {
148
+ const found = argv.find((arg) => UNSUPPORTED.has(arg) || arg.startsWith("--image="));
149
+ return found ? fail(`${found} is not supported in SLICC yet`, 2) : void 0;
150
+ }
151
+ async function spawnAsync(deps, request, who, argv, context) {
152
+ if (who.scoop) return fail("a scoop cannot start async scoops; run agent without --async");
153
+ const refused = unsupported(argv);
154
+ if (refused) return refused;
155
+ const parsed = flags(argv, ASYNC_VALUES);
156
+ const unknown = [...parsed.switches].find((flag) => !ASYNC_SWITCHES.has(flag));
157
+ if (unknown) return fail(`unknown option ${unknown}`, 2);
158
+ const given = await prompts(deps, argv, request, context);
159
+ if (!given.length) return fail("--async needs at least one --prompt, --file or -", 2);
160
+ const chosen = choices(parsed);
161
+ if (isAnswer(chosen)) return chosen;
162
+ const found = await role(deps, parsed);
163
+ if (found.error) return found.error;
164
+ return deps.scoops.spawn(
165
+ {
166
+ cone: who.cone,
167
+ kind: "async",
168
+ name: last(parsed, "--name") ?? found.role?.name ?? "scoop",
169
+ ...found.role ? { role: found.role } : {},
170
+ ...chosen.model ? { model: chosen.model } : {},
171
+ ...chosen.thinking ? { thinking: chosen.thinking } : {},
172
+ ...chosen.tools ? { tools: chosen.tools } : {},
173
+ prompts: given,
174
+ fromAgent: who.fromAgent,
175
+ request: request.id,
176
+ limits: found.roles.limits
177
+ },
178
+ context
179
+ );
180
+ }
181
+ async function listAgents(deps) {
182
+ const roles = await deps.roles();
183
+ const lines = roles.roles.map(
184
+ (entry) => `${entry.name} ${entry.source} ${entry.description}${entry.aliases.length ? ` (also ${entry.aliases.join(", ")})` : ""}`
185
+ );
186
+ return ok(
187
+ `${[
188
+ ...lines,
189
+ "",
190
+ "Agent files are read from the built-in roles, installed packages (pi-subagents.agents) and ~/.pi/agent/agents.",
191
+ "A project's .pi/agents folder is read only once the folder is trusted, which SLICC doesn't support yet.",
192
+ ...roles.warnings.map((warning) => `warning: ${warning}`)
193
+ ].join("\n")}
194
+ `
195
+ );
196
+ }
197
+ async function list(deps, request, who, context) {
198
+ if (request.argv.includes("--agents")) return listAgents(deps);
199
+ const rows = await deps.scoops.list(who.cone, context);
200
+ if (!rows.length) return ok("no scoops\n");
201
+ return ok(
202
+ `${rows.map((row) => `${row.folder} ${row.name} ${row.role ?? "-"} ${row.busy ? "working" : "idle"}`).join("\n")}
203
+ `
204
+ );
205
+ }
206
+ async function status(deps, request, who, context) {
207
+ const found = handle(deps, who, request.argv[1]);
208
+ if (!found) return fail(`there is no scoop ${request.argv[1] ?? ""}`.trim());
209
+ const [, record] = found;
210
+ const busy = await deps.scoops.busy(record.conversation, context);
211
+ return ok(
212
+ `${[
213
+ `handle: ${record.folder}`,
214
+ `name: ${record.name}`,
215
+ `role: ${record.role ?? "-"}`,
216
+ `kind: ${record.kind}`,
217
+ `state: ${busy ? "working" : "idle"}`,
218
+ `folder: ${SCOOPS_ROOT}/${record.folder}`,
219
+ `reports: ${SCOOPS_ROOT}/${record.folder}/reports`
220
+ ].join("\n")}
221
+ `
222
+ );
223
+ }
224
+ async function message(deps, parsed, request, context) {
225
+ const file = last(parsed, "--file");
226
+ if (file) return readText(deps, file, request, context);
227
+ return parsed.rest.includes("-") ? request.stdin : parsed.rest.join(" ");
228
+ }
229
+ async function send(deps, request, who, context) {
230
+ const parsed = flags(request.argv.slice(2), ["--file"]);
231
+ const unknown = [...parsed.switches].find((flag) => flag !== "--follow-up");
232
+ if (unknown) return fail(`unknown option ${unknown}`, 2);
233
+ const text = await message(deps, parsed, request, context);
234
+ if (!text.trim()) return fail("send needs a message, --file or -", 2);
235
+ if (request.argv[1] === "parent") {
236
+ if (!who.scoop) return fail("only a scoop has a parent to send to");
237
+ return deps.scoops.note(who.scoop, text, context);
238
+ }
239
+ if (who.scoop) return fail("a scoop can only send to its parent");
240
+ const found = handle(deps, who, request.argv[1]);
241
+ if (!found) return fail(`there is no scoop ${request.argv[1] ?? ""}`.trim());
242
+ const followUp = parsed.switches.has("--follow-up");
243
+ return deps.scoops.feed(
244
+ found[0],
245
+ text,
246
+ { fromAgent: who.fromAgent, request: request.id, followUp, target: who.id },
247
+ context
248
+ );
249
+ }
250
+ async function latest(deps, folder, context) {
251
+ const dir = `${SCOOPS_ROOT}/${folder}/reports`;
252
+ const listed = await deps.env.listDir(dir, context);
253
+ if (!listed.ok || !listed.value.length) return "(no answer yet)";
254
+ const newest = [...listed.value].sort(
255
+ (a, b) => Number.parseInt(b.name, 10) - Number.parseInt(a.name, 10)
256
+ )[0];
257
+ const read = await deps.env.readTextFile(`${dir}/${newest?.name}`, context);
258
+ return read.ok ? read.value.trimEnd() : "(no answer yet)";
259
+ }
260
+ function waitTargets(deps, who, rest) {
261
+ if (!rest.length) return fail("wait needs at least one handle", 2);
262
+ const missing = rest.filter((name) => !handle(deps, who, name));
263
+ if (missing.length) return fail(`there is no scoop ${missing.join(", ")}`);
264
+ return rest.map((name) => handle(deps, who, name)[0]);
265
+ }
266
+ async function block(deps, ids, seconds, context) {
267
+ const deadline = deps.now() + seconds * 1e3;
268
+ let open = await deps.scoops.working(ids, context);
269
+ while (open.length && deps.now() < deadline) {
270
+ await new Promise((done) => setTimeout(done, 200));
271
+ open = await deps.scoops.working(ids, context);
272
+ }
273
+ const state = deps.agents.state();
274
+ const sections = [];
275
+ for (const id of ids) {
276
+ const record = state.scoops[id];
277
+ if (record)
278
+ sections.push(
279
+ `## ${record.folder}${open.includes(id) ? " (still working)" : ""}
280
+ ${await latest(deps, record.folder, context)}`
281
+ );
282
+ }
283
+ const body = `${sections.join("\n\n")}
284
+ `;
285
+ if (!open.length) return ok(body);
286
+ const still = open.map((id) => state.scoops[id]?.folder).join(", ");
287
+ return { code: 1, out: `${body}agent: timed out after ${seconds}s; still working: ${still}
288
+ ` };
289
+ }
290
+ async function wait(deps, request, who, context) {
291
+ const parsed = flags(request.argv.slice(1), ["--timeout"]);
292
+ const unknown = [...parsed.switches].find((flag) => flag !== "--notify");
293
+ if (unknown) return fail(`unknown option ${unknown}`, 2);
294
+ const seconds = Number(last(parsed, "--timeout") ?? DEFAULT_WAIT_S);
295
+ if (!Number.isInteger(seconds) || seconds <= 0)
296
+ return fail("--timeout must be a positive whole number of seconds", 2);
297
+ const ids = waitTargets(deps, who, parsed.rest);
298
+ if (isAnswer(ids)) return ids;
299
+ if (!parsed.switches.has("--notify")) return block(deps, ids, seconds, context);
300
+ if (!who.fromAgent || who.scoop)
301
+ return fail("wait --notify is for a cone; a terminal waits with agent wait");
302
+ await deps.scoops.notifyWhenDone(who.cone, ids, deps.now() + seconds * 1e3, context);
303
+ return ok(`you'll get one scoop-wait lick when ${ids.length > 1 ? "they are" : "it is"} done
304
+ `);
305
+ }
306
+ async function stop(deps, request, who, context) {
307
+ if (who.scoop) return fail("a scoop cannot stop scoops");
308
+ const found = handle(deps, who, request.argv[1]);
309
+ if (!found) return fail(`there is no scoop ${request.argv[1] ?? ""}`.trim());
310
+ return deps.scoops.stop(found[0], who.fromAgent, context);
311
+ }
312
+ async function rename(deps, request, who, context) {
313
+ if (who.scoop) return fail("a scoop cannot rename scoops");
314
+ const found = handle(deps, who, request.argv[1]);
315
+ if (!found) return fail(`there is no scoop ${request.argv[1] ?? ""}`.trim());
316
+ return deps.scoops.rename(found[0], request.argv.slice(2).join(" "), context);
317
+ }
318
+ const help = async () => ok(USAGE);
319
+ const VERBS = {
320
+ list,
321
+ status,
322
+ send,
323
+ wait,
324
+ stop,
325
+ rename,
326
+ help,
327
+ "--help": help,
328
+ "-h": help,
329
+ __cancel: (deps, request, _who, context) => cancelSync(deps, request.argv[1] ?? "", context),
330
+ __detach: (deps, request, _who, context) => detachSync(deps, request.argv[1] ?? "", context)
331
+ };
332
+ async function dispatch(deps, request, who, context) {
333
+ const first = request.argv[0] ?? "";
334
+ const verb = VERBS[first];
335
+ if (verb) return verb(deps, request, who, context);
336
+ if (request.as === "subagent") {
337
+ if (first === "spawn") return spawnAsync(deps, request, who, request.argv.slice(1), context);
338
+ return { code: 2, out: USAGE };
339
+ }
340
+ if (!request.argv.length) return { code: 2, out: USAGE };
341
+ if (request.argv.includes("--async"))
342
+ return spawnAsync(deps, request, who, request.argv, context);
343
+ return runSync(deps, request, who, context);
344
+ }
345
+ const BLOCKING = /* @__PURE__ */ new Set([
346
+ "wait",
347
+ "list",
348
+ "status",
349
+ "help",
350
+ "--help",
351
+ "-h",
352
+ "__cancel",
353
+ "__detach"
354
+ ]);
355
+ function createCli(options) {
356
+ const deps = { ...options, now: options.now ?? Date.now, sync: { pending: /* @__PURE__ */ new Map() } };
357
+ return {
358
+ blocking(request) {
359
+ const first = request.argv[0] ?? "";
360
+ if (BLOCKING.has(first)) return true;
361
+ return request.as === "agent" && !VERBS[first] && !request.argv.includes("--async");
362
+ },
363
+ async run(request, context) {
364
+ try {
365
+ return await dispatch(deps, request, callerOf(options.agents, request), context);
366
+ } catch (error) {
367
+ return fail(error.message);
368
+ }
369
+ }
370
+ };
371
+ }
372
+ export {
373
+ DEFAULT_WAIT_S,
374
+ MAX_DEPTH,
375
+ RUN_DIR,
376
+ THINKING,
377
+ USAGE,
378
+ callerOf,
379
+ choices,
380
+ createCli,
381
+ fail,
382
+ flags,
383
+ isAnswer,
384
+ last,
385
+ ok,
386
+ prompts,
387
+ readText,
388
+ role,
389
+ unsupported
390
+ };
391
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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 } 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}\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 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(`there is no scoop ${request.argv[1] ?? ''}`.trim());\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(`there is no scoop ${request.argv[1] ?? ''}`.trim());\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) return fail(`there is no scoop ${missing.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(`there is no scoop ${request.argv[1] ?? ''}`.trim());\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(`there is no scoop ${request.argv[1] ?? ''}`.trim());\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\nasync function dispatch(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\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 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
+ "names": []
7
+ }