@ai-ecoverse/slicc-agent 3.48.1 → 3.50.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 (89) hide show
  1. package/README.md +38 -6
  2. package/bin/agent +1 -0
  3. package/dist/control.js +1 -1
  4. package/dist/control.js.map +2 -2
  5. package/dist/freezer/index.js +29 -8
  6. package/dist/freezer/index.js.map +2 -2
  7. package/dist/freezer/title.js +2 -2
  8. package/dist/freezer/title.js.map +2 -2
  9. package/dist/gelatiere/catalog.js +1 -1
  10. package/dist/gelatiere/catalog.js.map +2 -2
  11. package/dist/gelatiere/index.js +44 -21
  12. package/dist/gelatiere/index.js.map +2 -2
  13. package/dist/gelatiere/store.js +9 -5
  14. package/dist/gelatiere/store.js.map +2 -2
  15. package/dist/index.js.map +2 -2
  16. package/dist/kernel/accounts.js +141 -0
  17. package/dist/kernel/accounts.js.map +7 -0
  18. package/dist/kernel/agent-users.js +180 -0
  19. package/dist/kernel/agent-users.js.map +7 -0
  20. package/dist/kernel/env.js +9 -3
  21. package/dist/kernel/env.js.map +2 -2
  22. package/dist/kernel/users.js +16 -1
  23. package/dist/kernel/users.js.map +2 -2
  24. package/dist/layout.js +62 -0
  25. package/dist/layout.js.map +7 -0
  26. package/dist/licks/index.js.map +2 -2
  27. package/dist/licks/sources.js +69 -20
  28. package/dist/licks/sources.js.map +2 -2
  29. package/dist/main.js +70 -36
  30. package/dist/main.js.map +2 -2
  31. package/dist/mcp/index.js +5 -3
  32. package/dist/mcp/index.js.map +2 -2
  33. package/dist/mcp/paths.js +15 -0
  34. package/dist/mcp/paths.js.map +7 -0
  35. package/dist/mcp/runtime.js +16 -14
  36. package/dist/mcp/runtime.js.map +3 -3
  37. package/dist/memory/extract.js +2 -1
  38. package/dist/memory/extract.js.map +2 -2
  39. package/dist/memory/prompt.js +5 -1
  40. package/dist/memory/prompt.js.map +2 -2
  41. package/dist/memory/runtime.js +9 -1
  42. package/dist/memory/runtime.js.map +2 -2
  43. package/dist/roles/roles.js +54 -15
  44. package/dist/roles/roles.js.map +2 -2
  45. package/dist/scoops/cli.js +40 -19
  46. package/dist/scoops/cli.js.map +2 -2
  47. package/dist/scoops/extension.js +19 -15
  48. package/dist/scoops/extension.js.map +2 -2
  49. package/dist/scoops/index.js +82 -11
  50. package/dist/scoops/index.js.map +2 -2
  51. package/dist/scoops/requests.js +2 -1
  52. package/dist/scoops/requests.js.map +2 -2
  53. package/dist/scoops/service.js +45 -38
  54. package/dist/scoops/service.js.map +2 -2
  55. package/dist/scoops/sync.js +63 -13
  56. package/dist/scoops/sync.js.map +2 -2
  57. package/dist/skills/index.js +76 -34
  58. package/dist/skills/index.js.map +3 -3
  59. package/dist/sprinkles/index.js +114 -25
  60. package/dist/sprinkles/index.js.map +2 -2
  61. package/dist/sprinkles/sprinkles.js +13 -4
  62. package/dist/sprinkles/sprinkles.js.map +2 -2
  63. package/dist/types/freezer/index.d.ts +3 -1
  64. package/dist/types/freezer/title.d.ts +1 -1
  65. package/dist/types/gelatiere/index.d.ts +8 -0
  66. package/dist/types/gelatiere/store.d.ts +3 -2
  67. package/dist/types/index.d.ts +1 -1
  68. package/dist/types/kernel/accounts.d.ts +29 -0
  69. package/dist/types/kernel/agent-users.d.ts +37 -0
  70. package/dist/types/kernel/env.d.ts +6 -0
  71. package/dist/types/kernel/users.d.ts +15 -0
  72. package/dist/types/layout.d.ts +26 -0
  73. package/dist/types/licks/index.d.ts +2 -1
  74. package/dist/types/licks/sources.d.ts +11 -1
  75. package/dist/types/mcp/paths.d.ts +3 -0
  76. package/dist/types/mcp/runtime.d.ts +3 -3
  77. package/dist/types/memory/prompt.d.ts +1 -0
  78. package/dist/types/memory/runtime.d.ts +1 -0
  79. package/dist/types/roles/roles.d.ts +14 -1
  80. package/dist/types/scoops/cli.d.ts +5 -0
  81. package/dist/types/scoops/extension.d.ts +6 -3
  82. package/dist/types/scoops/index.d.ts +9 -0
  83. package/dist/types/scoops/requests.d.ts +2 -0
  84. package/dist/types/scoops/service.d.ts +5 -3
  85. package/dist/types/scoops/sync.d.ts +9 -6
  86. package/dist/types/skills/index.d.ts +10 -2
  87. package/dist/types/sprinkles/index.d.ts +15 -0
  88. package/dist/types/sprinkles/sprinkles.d.ts +7 -1
  89. package/package.json +4 -4
@@ -8,9 +8,10 @@ import {
8
8
  scoopId
9
9
  } from "../agents.js";
10
10
  import { CODEMODE } from "../codemode/index.js";
11
+ import { LEGACY } from "../layout.js";
11
12
  import { McpAllowDoc, mcpEntries } from "../mcp/index.js";
12
13
  import { visible } from "./visible.js";
13
- const SCOOPS_ROOT = "/scoops";
14
+ import { SCOOPS_ROOT } from "../layout.js";
14
15
  const LEDGER_SIZE = 512;
15
16
  const ScoopWorkDoc = defineDoc({
16
17
  kind: "slicc.scoops.work",
@@ -18,8 +19,8 @@ const ScoopWorkDoc = defineDoc({
18
19
  scope: "session",
19
20
  initial: () => ({ feeds: {}, waits: {}, ledger: {}, turns: {} })
20
21
  });
21
- function workspace(folder) {
22
- return `${SCOOPS_ROOT}/${folder}/workspace`;
22
+ function workspace(folder, layout = LEGACY) {
23
+ return layout.workspace(folder);
23
24
  }
24
25
  async function tail(conversation, context) {
25
26
  const { entries } = await conversation.context(context);
@@ -117,13 +118,14 @@ function claimTurn(work, request, turn) {
117
118
  work.turns[request.cone] = { at: turn, count: count + 1 };
118
119
  return void 0;
119
120
  }
120
- function agentChange(request, folder, tools, mcp) {
121
+ function agentChange(request, folder, host) {
122
+ const { tools, mcp } = host;
121
123
  const model = request.model ?? modelOf(request.role?.model);
122
124
  const thinking = request.thinking ?? request.role?.thinking;
123
125
  const chosen = selection(tools, request.tools ?? request.role?.tools, mcp);
124
126
  const instructions = [request.role?.prompt, request.instructions].filter(Boolean).join("\n\n");
125
127
  return {
126
- cwd: request.cwd ?? workspace(folder),
128
+ cwd: request.cwd ?? workspace(folder, host.layout),
127
129
  ...instructions ? { instructions } : {},
128
130
  ...model ? { model } : {},
129
131
  ...thinking ? { thinkingLevel: thinking } : {},
@@ -137,10 +139,31 @@ async function narrowMcp(tx, state, cone, child, request) {
137
139
  if (listed !== null || inherited !== null)
138
140
  (await tx.doc(McpAllowDoc, child)).allow = listed ?? inherited;
139
141
  }
142
+ function scoopRecord(request, folder, conversation, anchor, created) {
143
+ return {
144
+ name: request.name.trim() || folder,
145
+ folder,
146
+ cone: request.cone,
147
+ conversation,
148
+ anchor,
149
+ role: request.role?.name ?? null,
150
+ ...request.role?.memory ? { memory: request.role.memory } : {},
151
+ ...request.role?.memory && request.origin ? { origin: request.origin } : {},
152
+ ...request.role?.context ? { context: request.role.context } : {},
153
+ kind: request.kind ?? "async",
154
+ parent: request.parent ?? request.cone,
155
+ depth: request.depth ?? 1,
156
+ roots: request.roots ?? null,
157
+ created,
158
+ dropped: null,
159
+ gone: false
160
+ };
161
+ }
140
162
  async function spawn(core, request, context) {
141
163
  const done = await answered(core, request.request, context);
142
164
  if (done) return done;
143
- const { agents, tools, mcp } = await core.host;
165
+ const host = await core.host;
166
+ const { agents } = host;
144
167
  const parent = await coneOfId(core, request.cone, context);
145
168
  const count = liveCount(agents.state(), request.cone);
146
169
  if (count >= request.limits.maxLiveScoops)
@@ -163,26 +186,9 @@ async function spawn(core, request, context) {
163
186
  background: true
164
187
  });
165
188
  const child = await tx.createConversation({ ownership: { kind: "task", taskId: anchor } });
166
- await configure(tx, child.id, agentChange(request, folder, tools, mcp));
189
+ await configure(tx, child.id, agentChange(request, folder, host));
167
190
  await narrowMcp(tx, doc, parent.id, child.id, request);
168
- doc.scoops[id] = {
169
- name: request.name.trim() || folder,
170
- folder,
171
- cone: request.cone,
172
- conversation: child.id,
173
- anchor,
174
- role: request.role?.name ?? null,
175
- ...request.role?.memory ? { memory: request.role.memory } : {},
176
- ...request.role?.memory && request.origin ? { origin: request.origin } : {},
177
- ...request.role?.context ? { context: request.role.context } : {},
178
- kind: request.kind ?? "async",
179
- parent: request.parent ?? request.cone,
180
- depth: request.depth ?? 1,
181
- roots: request.roots ?? null,
182
- created,
183
- dropped: null,
184
- gone: false
185
- };
191
+ doc.scoops[id] = scoopRecord(request, folder, child.id, Number(anchor), created);
186
192
  const target = request.target === void 0 ? request.fromAgent ? `cone:${request.cone}` : null : request.target;
187
193
  const made = [];
188
194
  const asker = request.asker === void 0 ? target : request.asker;
@@ -267,7 +273,7 @@ async function stopFeeds(core, scoop, keep, context) {
267
273
  return dropped.length;
268
274
  }
269
275
  async function stop(core, id, fromAgent, context) {
270
- const { agents, files } = await core.host;
276
+ const { agents, files, layout = LEGACY } = await core.host;
271
277
  const record = agents.state().scoops[id];
272
278
  if (!record || !live(record)) return missing(id);
273
279
  await stopFeeds(core, id, async () => false, context);
@@ -276,15 +282,12 @@ async function stop(core, id, fromAgent, context) {
276
282
  await agents.update((_tx, state) => {
277
283
  state.scoops[id].dropped = mark;
278
284
  }, context);
279
- const removed = await files?.remove(
280
- workspace(record.folder),
281
- { recursive: true, force: true },
282
- context
283
- );
284
- const folder = removed?.ok ? `removed ${workspace(record.folder)}` : `kept ${workspace(record.folder)}`;
285
+ const place = layout.workspace(record.folder);
286
+ const removed = await files?.remove(place, { recursive: true, force: true }, context);
287
+ const folder = removed?.ok ? `removed ${place}` : `kept ${place}`;
285
288
  return {
286
289
  code: 0,
287
- out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${SCOOPS_ROOT}/${record.folder}/reports
290
+ out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${layout.reports(record.folder, record.cone)}
288
291
  `
289
292
  };
290
293
  }
@@ -300,14 +303,18 @@ async function rename(core, id, name, context) {
300
303
  return { code: 0, out: `${record.folder} is now called ${wanted}
301
304
  ` };
302
305
  }
303
- async function resetWorkspace(files, folder, context) {
306
+ async function resetWorkspace(host, folder, context) {
307
+ const { files } = host;
304
308
  if (!files) return true;
305
- const cleared = await files.remove(workspace(folder), { recursive: true, force: true }, context);
309
+ const place = workspace(folder, host.layout);
310
+ const cleared = await files.remove(place, { recursive: true, force: true }, context);
306
311
  if (!cleared.ok) return false;
307
- return (await files.createDir(workspace(folder), { recursive: true }, context)).ok;
312
+ if (host.layout?.users) return true;
313
+ return (await files.createDir(place, { recursive: true }, context)).ok;
308
314
  }
309
315
  async function rewindOne(core, coneId, id, record, seen, result, context) {
310
- const { harness, licks, files } = await core.host;
316
+ const host = await core.host;
317
+ const { harness, licks } = host;
311
318
  if (!await seen(record.created)) {
312
319
  if (live(record)) {
313
320
  await stopFeeds(core, id, async () => false, context);
@@ -318,7 +325,7 @@ async function rewindOne(core, coneId, id, record, seen, result, context) {
318
325
  }
319
326
  if (record.dropped !== null) {
320
327
  if (await seen(record.dropped)) return void 0;
321
- const reset = await resetWorkspace(files, record.folder, context);
328
+ const reset = await resetWorkspace(host, record.folder, context);
322
329
  result.restored.push(
323
330
  reset ? record.name : `${record.name} (its working folder could not be reset)`
324
331
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/scoops/service.ts"],
4
- "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n type AgentChange,\n type AnyTask,\n type Conversation,\n type ConversationId,\n configure,\n defineDoc,\n type Harness,\n type TaskId,\n type ToolRegistration,\n type Tx,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport {\n type Agents,\n type AgentsState,\n freeFolder,\n live,\n type Mark,\n type ScoopRecord,\n scoopId,\n} from '../agents.ts';\nimport { CODEMODE } from '../codemode/index.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { McpAllowDoc, mcpEntries } from '../mcp/index.ts';\nimport type { Role } from '../roles/roles.ts';\nimport { visible } from './visible.ts';\n\nexport const SCOOPS_ROOT = '/scoops';\nexport const LEDGER_SIZE = 512;\n\nexport type Feed = {\n scoop: string;\n created: Mark | null;\n report: boolean;\n target: string | null;\n channel: 'scoop-notify' | 'bash';\n from?: string;\n agent?: boolean;\n};\ntype Wait = { scoops: string[]; done: Record<string, string>; cone: string };\nexport type Answer = { code: number; out: string; err?: string; tasks?: number[] };\ntype WorkState = {\n feeds: Record<string, Feed>;\n waits: Record<string, Wait>;\n ledger: Record<string, Answer>;\n turns: Record<string, { at: number; count: number }>;\n};\n\nexport const ScoopWorkDoc = defineDoc<WorkState>({\n kind: 'slicc.scoops.work',\n version: 1,\n scope: 'session',\n initial: () => ({ feeds: {}, waits: {}, ledger: {}, turns: {} }),\n});\n\nexport interface ScoopTasks {\n anchor: AnyTask;\n reporter: AnyTask;\n wait: AnyTask;\n}\n\nexport interface ScoopsHost {\n harness: Harness;\n agents: Agents;\n licks: Licks;\n groups?: ProcessGroups;\n tools?: readonly ToolRegistration[];\n reads?: () => readonly string[];\n files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;\n mcp?: (names: readonly string[]) => ToolRegistration[];\n}\n\nexport interface Rewound {\n stopped: string[];\n restored: string[];\n}\n\nexport interface ScoopSummary {\n id: string;\n folder: string;\n name: string;\n role: string | null;\n busy: boolean;\n}\n\nexport interface Limits {\n maxLiveScoops: number;\n maxPerTurn: number;\n}\n\nexport interface SpawnRequest {\n cone: string;\n kind?: 'async' | 'sync';\n parent?: string;\n depth?: number;\n roots?: { write: string[]; read: string[] };\n cwd?: string;\n origin?: string;\n instructions?: string;\n target?: string | null;\n asker?: string | null;\n name: string;\n role?: Role;\n model?: { provider: string; modelId: string };\n thinking?: AgentChange['thinkingLevel'];\n tools?: string[];\n prompts: string[];\n fromAgent: boolean;\n request?: string;\n limits: Limits;\n}\n\nexport function workspace(folder: string): string {\n return `${SCOOPS_ROOT}/${folder}/workspace`;\n}\n\nexport async function tail(conversation: Conversation, context: Context): Promise<Mark> {\n const { entries } = await conversation.context(context);\n return { in: conversation.id, at: Number(entries.at(-1)?.id ?? 0) };\n}\n\nexport async function turnStart(conversation: Conversation, context: Context): Promise<number> {\n const { entries } = await conversation.context(context);\n return Number(entries.findLast((entry) => entry.kind === 'pi.user')?.id ?? 0);\n}\n\nexport function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined {\n return Object.entries(state.cones).find(([, cone]) => cone.conversation === conversation)?.[0];\n}\n\nexport function findScoop(\n state: Readonly<AgentsState>,\n handle: string,\n cone: string | null\n): [string, ScoopRecord] | undefined {\n const id = handle.startsWith('scoop:') ? handle : scoopId(handle);\n const reachable = (record: ScoopRecord | undefined): record is ScoopRecord =>\n !!record && live(record) && (cone === null || record.cone === cone);\n const record = state.scoops[id];\n if (reachable(record)) return [id, record];\n return Object.entries(state.scoops).find(\n ([, candidate]) => reachable(candidate) && candidate.name === handle\n );\n}\n\nfunction remember(work: WorkState, request: string | undefined, answer: Answer): void {\n if (!request) return;\n work.ledger[request] = answer;\n const keys = Object.keys(work.ledger);\n for (const key of keys.slice(0, Math.max(0, keys.length - LEDGER_SIZE))) delete work.ledger[key];\n}\n\ntype Core = { host: Promise<ScoopsHost>; tasks: () => ScoopTasks };\n\nasync function coneOfId(core: Core, coneId: string, context: Context): Promise<Conversation> {\n const { agents } = await core.host;\n const found = await agents.conversation(coneId, context);\n if (!found) throw new Error(`There is no cone ${coneId}.`);\n return found;\n}\n\nasync function isBusy(core: Core, conversation: number, context: Context): Promise<boolean> {\n const { harness } = await core.host;\n const handle = await harness.conversation(conversation as ConversationId, context);\n const view = await handle?.viewState(context);\n const run = (view?.value.docs['pi.live'] as { run?: unknown } | undefined)?.run;\n view?.dispose();\n return Boolean(run);\n}\n\nasync function answered(\n core: Core,\n request: string | undefined,\n context: Context\n): Promise<Answer | undefined> {\n if (!request) return undefined;\n const { harness } = await core.host;\n return (await harness.snapshot(ScoopWorkDoc, context))?.ledger[request];\n}\n\ntype NewFeed = Omit<Feed, 'channel' | 'from'> & {\n from: string;\n agent: boolean;\n prompt: string;\n request?: string;\n followUp?: boolean;\n};\n\nasync function addFeed(core: Core, tx: Tx, parent: number, feed: NewFeed): Promise<number> {\n const task = await tx.createTask(\n core.tasks().reporter as never,\n {\n scoop: feed.scoop,\n prompt: feed.prompt,\n ...(feed.followUp ? { followUp: true } : {}),\n ...(feed.request ? { request: feed.request } : {}),\n },\n {\n ownership: { kind: 'conversation' },\n conversationId: parent as ConversationId,\n background: true,\n }\n );\n (await tx.doc(ScoopWorkDoc)).feeds[String(task)] = {\n scoop: feed.scoop,\n created: feed.created,\n report: feed.report,\n target: feed.target,\n channel: 'scoop-notify',\n from: feed.from,\n agent: feed.agent,\n };\n return Number(task);\n}\n\nfunction selection(\n tools: readonly ToolRegistration[] | undefined,\n names: string[] | undefined,\n mcp?: (names: readonly string[]) => ToolRegistration[]\n) {\n if (!names || !tools) return undefined;\n const picked = tools.filter((tool) => names.includes(tool.name));\n const entries = mcpEntries(names) ?? [];\n if (!entries.length) return picked;\n const codemode = tools.find((tool) => tool.name === CODEMODE);\n if (codemode && !picked.includes(codemode)) picked.push(codemode);\n return [...picked, ...(mcp?.(entries) ?? [])];\n}\n\nfunction liveCount(state: Readonly<AgentsState>, cone: string): number {\n return Object.values(state.scoops).filter((scoop) => scoop.cone === cone && live(scoop)).length;\n}\n\nfunction claimTurn(\n work: WorkState,\n request: SpawnRequest,\n turn: number | null\n): Answer | undefined {\n if (turn === null) return undefined;\n const counted = work.turns[request.cone];\n const count = counted && counted.at === turn ? counted.count : 0;\n if (count >= request.limits.maxPerTurn)\n return {\n code: 1,\n out: `subagent: this turn already started ${count} scoops (the limit is ${request.limits.maxPerTurn})\\n`,\n };\n work.turns[request.cone] = { at: turn, count: count + 1 };\n return undefined;\n}\n\nfunction agentChange(\n request: SpawnRequest,\n folder: string,\n tools: readonly ToolRegistration[] | undefined,\n mcp?: (names: readonly string[]) => ToolRegistration[]\n): AgentChange {\n const model = request.model ?? modelOf(request.role?.model);\n const thinking = request.thinking ?? request.role?.thinking;\n const chosen = selection(tools, request.tools ?? request.role?.tools, mcp);\n const instructions = [request.role?.prompt, request.instructions].filter(Boolean).join('\\n\\n');\n return {\n cwd: request.cwd ?? workspace(folder),\n ...(instructions ? { instructions } : {}),\n ...(model ? { model } : {}),\n ...(thinking ? { thinkingLevel: thinking as AgentChange['thinkingLevel'] } : {}),\n ...(chosen ? { tools: chosen } : {}),\n };\n}\n\nasync function narrowMcp(\n tx: Tx,\n state: Readonly<AgentsState>,\n cone: ConversationId,\n child: ConversationId,\n request: SpawnRequest\n): Promise<void> {\n const listed = mcpEntries(request.tools ?? request.role?.tools);\n const caller = state.scoops[request.parent ?? '']?.conversation as ConversationId | undefined;\n const inherited = (await tx.doc(McpAllowDoc, caller ?? cone)).allow;\n if (listed !== null || inherited !== null)\n (await tx.doc(McpAllowDoc, child)).allow = listed ?? inherited;\n}\n\nasync function spawn(core: Core, request: SpawnRequest, context: Context): Promise<Answer> {\n const done = await answered(core, request.request, context);\n if (done) return done;\n const { agents, tools, mcp } = await core.host;\n const parent = await coneOfId(core, request.cone, context);\n const count = liveCount(agents.state(), request.cone);\n if (count >= request.limits.maxLiveScoops)\n return {\n code: 1,\n out: `subagent: this cone already has ${count} live scoops (the limit is ${request.limits.maxLiveScoops}); stop one first\\n`,\n };\n const created = request.fromAgent ? await tail(parent, context) : null;\n const turn = request.fromAgent ? await turnStart(parent, context) : null;\n return agents.update(async (tx, doc) => {\n const work = await tx.doc(ScoopWorkDoc);\n const refused = claimTurn(work as WorkState, request, turn);\n if (refused) return refused;\n const folder = freeFolder(doc, request.name);\n const id = scoopId(folder);\n const anchor = await tx.createTask(core.tasks().anchor as never, null, {\n ownership: { kind: 'conversation' },\n conversationId: parent.id,\n background: true,\n });\n const child = await tx.createConversation({ ownership: { kind: 'task', taskId: anchor } });\n await configure(tx, child.id, agentChange(request, folder, tools, mcp));\n await narrowMcp(tx, doc, parent.id, child.id, request);\n doc.scoops[id] = {\n name: request.name.trim() || folder,\n folder,\n cone: request.cone,\n conversation: child.id,\n anchor,\n role: request.role?.name ?? null,\n ...(request.role?.memory ? { memory: request.role.memory } : {}),\n ...(request.role?.memory && request.origin ? { origin: request.origin } : {}),\n ...(request.role?.context ? { context: request.role.context } : {}),\n kind: request.kind ?? 'async',\n parent: request.parent ?? request.cone,\n depth: request.depth ?? 1,\n roots: request.roots ?? null,\n created,\n dropped: null,\n gone: false,\n };\n const target =\n request.target === undefined\n ? request.fromAgent\n ? `cone:${request.cone}`\n : null\n : request.target;\n const made: number[] = [];\n const asker = request.asker === undefined ? target : request.asker;\n const from = askerName(doc, asker);\n for (const prompt of request.prompts)\n made.push(\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from,\n agent: asker !== null,\n prompt,\n })\n );\n const answer = { code: 0, out: `${folder}\\n`, tasks: made };\n remember(work as WorkState, request.request, answer);\n return answer;\n }, context);\n}\n\nexport function askerName(state: Readonly<AgentsState>, asker: string | null): string {\n if (asker === null) return 'terminal';\n if (asker.startsWith('cone:')) return state.cones[asker.slice('cone:'.length)]?.name ?? asker;\n return state.scoops[asker]?.name ?? asker;\n}\n\nconst missing = (id: string): Answer => ({\n code: 1,\n out: `subagent: there is no scoop ${id.replace('scoop:', '')}\\n`,\n});\n\nasync function feed(\n core: Core,\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n): Promise<Answer> {\n const done = await answered(core, options.request, context);\n if (done) return done;\n const { harness, agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const parent = await coneOfId(core, record.cone, context);\n const created = options.fromAgent ? await tail(parent, context) : null;\n const { target } = options;\n return harness.commit(async (tx) => {\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from: askerName(agents.state(), target),\n agent: target !== null,\n prompt,\n followUp: options.followUp,\n request: options.request,\n });\n const answer = { code: 0, out: `sent to ${record.folder}\\n` };\n remember((await tx.doc(ScoopWorkDoc)) as WorkState, options.request, answer);\n return answer;\n }, context);\n}\n\nasync function signal(core: Core, record: ScoopRecord, context: Context): Promise<void> {\n const { harness, groups } = await core.host;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context, { background: true });\n await groups?.signal(record.conversation);\n}\n\nasync function stopFeeds(\n core: Core,\n scoop: string,\n keep: (feed: Feed) => Promise<boolean>,\n context: Context\n) {\n const { harness } = await core.host;\n const work = (await harness.snapshot(ScoopWorkDoc, context)) ?? { feeds: {} };\n const dropped: string[] = [];\n for (const [task, entry] of Object.entries(work.feeds)) {\n if (entry.scoop !== scoop || (await keep(entry))) continue;\n const record = await harness.getTask(Number(task) as TaskId, context);\n if (record && record.state.status !== 'terminal')\n await harness.abortTask(Number(task) as TaskId, context);\n dropped.push(task);\n }\n if (dropped.length)\n await harness.commit(async (tx) => {\n const doc = await tx.doc(ScoopWorkDoc);\n for (const task of dropped) delete doc.feeds[task];\n }, context);\n return dropped.length;\n}\n\nasync function stop(core: Core, id: string, fromAgent: boolean, context: Context): Promise<Answer> {\n const { agents, files } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n const mark = fromAgent\n ? await tail(await coneOfId(core, record.cone, context), context)\n : { in: 0, at: 0 };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).dropped = mark;\n }, context);\n const removed = await files?.remove(\n workspace(record.folder),\n { recursive: true, force: true },\n context\n );\n const folder = removed?.ok\n ? `removed ${workspace(record.folder)}`\n : `kept ${workspace(record.folder)}`;\n return {\n code: 0,\n out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${SCOOPS_ROOT}/${record.folder}/reports\\n`,\n };\n}\n\nasync function rename(core: Core, id: string, name: string, context: Context): Promise<Answer> {\n const { agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const wanted = name.trim();\n if (!wanted) return { code: 2, out: 'subagent: rename needs a non-empty name\\n' };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).name = wanted;\n }, context);\n return { code: 0, out: `${record.folder} is now called ${wanted}\\n` };\n}\n\nasync function resetWorkspace(\n files: ScoopsHost['files'],\n folder: string,\n context: Context\n): Promise<boolean> {\n if (!files) return true;\n const cleared = await files.remove(workspace(folder), { recursive: true, force: true }, context);\n if (!cleared.ok) return false;\n return (await files.createDir(workspace(folder), { recursive: true }, context)).ok;\n}\n\ntype Seen = (mark: Mark | null) => Promise<boolean>;\n\nasync function rewindOne(\n core: Core,\n coneId: string,\n id: string,\n record: ScoopRecord,\n seen: Seen,\n result: Rewound,\n context: Context\n): Promise<Partial<ScoopRecord> | undefined> {\n const { harness, licks, files } = await core.host;\n if (!(await seen(record.created))) {\n if (live(record)) {\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n result.stopped.push(record.name);\n }\n return { gone: true };\n }\n if (record.dropped !== null) {\n if (await seen(record.dropped)) return undefined;\n const reset = await resetWorkspace(files, record.folder, context);\n result.restored.push(\n reset ? record.name : `${record.name} (its working folder could not be reset)`\n );\n return { dropped: null };\n }\n const withdrawn = await stopFeeds(core, id, (entry) => seen(entry.created), context);\n if (!withdrawn) return undefined;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context);\n await licks.forget(`cone:${coneId}`, 'scoop-notify', id, context);\n return undefined;\n}\n\nasync function rewound(\n core: Core,\n coneId: string,\n fork: Conversation,\n context: Context\n): Promise<Rewound> {\n const { harness, agents } = await core.host;\n const read = (id: number) =>\n harness.commit((tx) => tx.conversation(id as ConversationId), context);\n const seen: Seen = async (mark) =>\n mark === null || mark.in === 0 || (await visible(read, fork.id, mark));\n const result: Rewound = { stopped: [], restored: [] };\n const changes: [string, Partial<ScoopRecord>][] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if (record.cone !== coneId || record.gone) continue;\n const change = await rewindOne(core, coneId, id, record, seen, result, context);\n if (change) changes.push([id, change]);\n }\n if (changes.length)\n await agents.update((_tx, state) => {\n for (const [id, change] of changes) Object.assign(state.scoops[id] as ScoopRecord, change);\n }, context);\n return result;\n}\n\nasync function list(core: Core, coneId: string | null, context: Context): Promise<ScoopSummary[]> {\n const { agents } = await core.host;\n const out: ScoopSummary[] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if ((coneId !== null && record.cone !== coneId) || !live(record)) continue;\n out.push({\n id,\n folder: record.folder,\n name: record.name,\n role: record.role,\n busy: await isBusy(core, record.conversation, context),\n });\n }\n return out;\n}\n\nasync function working(core: Core, ids: readonly string[], context: Context): Promise<string[]> {\n const { harness, agents } = await core.host;\n const feeds = Object.values((await harness.snapshot(ScoopWorkDoc, context))?.feeds ?? {});\n const out: string[] = [];\n for (const id of ids) {\n const record = agents.state().scoops[id];\n if (!record) continue;\n if (\n feeds.some((entry) => entry.scoop === id) ||\n (await isBusy(core, record.conversation, context))\n )\n out.push(id);\n }\n return out;\n}\n\nasync function notifyWhenDone(\n core: Core,\n coneId: string,\n ids: string[],\n deadline: number,\n context: Context\n) {\n const { harness } = await core.host;\n const parent = await coneOfId(core, coneId, context);\n await harness.commit(\n (tx) =>\n tx.createTask(\n core.tasks().wait as never,\n { scoops: ids, cone: coneId, deadline },\n { ownership: { kind: 'conversation' }, conversationId: parent.id, background: true }\n ),\n context\n );\n}\n\nasync function detach(core: Core, tasks: readonly number[], target: string, context: Context) {\n const { harness } = await core.host;\n await harness.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const task of tasks) {\n const entry = work.feeds[String(task)];\n if (!entry) continue;\n entry.report = true;\n entry.target = target;\n entry.channel = 'bash';\n }\n }, context);\n}\n\nasync function note(core: Core, id: string, text: string, context: Context): Promise<Answer> {\n const { agents, licks } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n await licks.deliver(\n {\n channel: 'scoop-notify',\n source: `${id}#note`,\n title: label,\n text: `[scoop ${label} progress]`,\n body: text,\n target: `cone:${record.cone}`,\n },\n context\n );\n return { code: 0, out: 'note sent to the cone\\n' };\n}\n\nexport function createScoops(host: Promise<ScoopsHost>, tasks: () => ScoopTasks) {\n const core: Core = { host, tasks };\n return {\n detach: (made: readonly number[], target: string, context: Context) =>\n detach(core, made, target, context),\n note: (id: string, text: string, context: Context) => note(core, id, text, context),\n spawn: (request: SpawnRequest, context: Context) => spawn(core, request, context),\n feed: (\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n ) => feed(core, id, prompt, options, context),\n stop: (id: string, fromAgent: boolean, context: Context) => stop(core, id, fromAgent, context),\n rename: (id: string, name: string, context: Context) => rename(core, id, name, context),\n rewound: (coneId: string, fork: Conversation, context: Context) =>\n rewound(core, coneId, fork, context),\n list: (coneId: string | null, context: Context) => list(core, coneId, context),\n busy: (conversation: number, context: Context) => isBusy(core, conversation, context),\n working: (ids: readonly string[], context: Context) => working(core, ids, context),\n notifyWhenDone: (coneId: string, ids: string[], deadline: number, context: Context) =>\n notifyWhenDone(core, coneId, ids, deadline, context),\n };\n}\n\nexport function modelOf(\n value: string | undefined\n): { provider: string; modelId: string } | undefined {\n if (!value) return undefined;\n const at = value.indexOf('/');\n if (at <= 0) return undefined;\n return { provider: value.slice(0, at), modelId: value.slice(at + 1) };\n}\n\nexport type Scoops = ReturnType<typeof createScoops>;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n type AgentChange,\n type AnyTask,\n type Conversation,\n type ConversationId,\n configure,\n defineDoc,\n type Harness,\n type TaskId,\n type ToolRegistration,\n type Tx,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport {\n type Agents,\n type AgentsState,\n freeFolder,\n live,\n type Mark,\n type ScoopRecord,\n scoopId,\n} from '../agents.ts';\nimport { CODEMODE } from '../codemode/index.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport { type Layout, LEGACY } from '../layout.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { McpAllowDoc, mcpEntries } from '../mcp/index.ts';\nimport type { Role } from '../roles/roles.ts';\nimport { visible } from './visible.ts';\n\nexport { SCOOPS_ROOT } from '../layout.ts';\nexport const LEDGER_SIZE = 512;\n\nexport type Feed = {\n scoop: string;\n created: Mark | null;\n report: boolean;\n target: string | null;\n channel: 'scoop-notify' | 'bash';\n from?: string;\n agent?: boolean;\n};\ntype Wait = { scoops: string[]; done: Record<string, string>; cone: string };\nexport type Answer = { code: number; out: string; err?: string; tasks?: number[] };\ntype WorkState = {\n feeds: Record<string, Feed>;\n waits: Record<string, Wait>;\n ledger: Record<string, Answer>;\n turns: Record<string, { at: number; count: number }>;\n};\n\nexport const ScoopWorkDoc = defineDoc<WorkState>({\n kind: 'slicc.scoops.work',\n version: 1,\n scope: 'session',\n initial: () => ({ feeds: {}, waits: {}, ledger: {}, turns: {} }),\n});\n\nexport interface ScoopTasks {\n anchor: AnyTask;\n reporter: AnyTask;\n wait: AnyTask;\n}\n\nexport interface ScoopsHost {\n harness: Harness;\n agents: Agents;\n licks: Licks;\n groups?: ProcessGroups;\n tools?: readonly ToolRegistration[];\n reads?: () => readonly string[];\n files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;\n mcp?: (names: readonly string[]) => ToolRegistration[];\n layout?: Layout;\n enforced?: boolean;\n}\n\nexport interface Rewound {\n stopped: string[];\n restored: string[];\n}\n\nexport interface ScoopSummary {\n id: string;\n folder: string;\n name: string;\n role: string | null;\n busy: boolean;\n}\n\nexport interface Limits {\n maxLiveScoops: number;\n maxPerTurn: number;\n}\n\nexport interface SpawnRequest {\n cone: string;\n kind?: 'async' | 'sync';\n parent?: string;\n depth?: number;\n roots?: { write: string[]; read: string[] };\n cwd?: string;\n origin?: string;\n instructions?: string;\n target?: string | null;\n asker?: string | null;\n name: string;\n role?: Role;\n model?: { provider: string; modelId: string };\n thinking?: AgentChange['thinkingLevel'];\n tools?: string[];\n prompts: string[];\n fromAgent: boolean;\n request?: string;\n limits: Limits;\n}\n\nexport function workspace(folder: string, layout: Layout = LEGACY): string {\n return layout.workspace(folder);\n}\n\nexport async function tail(conversation: Conversation, context: Context): Promise<Mark> {\n const { entries } = await conversation.context(context);\n return { in: conversation.id, at: Number(entries.at(-1)?.id ?? 0) };\n}\n\nexport async function turnStart(conversation: Conversation, context: Context): Promise<number> {\n const { entries } = await conversation.context(context);\n return Number(entries.findLast((entry) => entry.kind === 'pi.user')?.id ?? 0);\n}\n\nexport function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined {\n return Object.entries(state.cones).find(([, cone]) => cone.conversation === conversation)?.[0];\n}\n\nexport function findScoop(\n state: Readonly<AgentsState>,\n handle: string,\n cone: string | null\n): [string, ScoopRecord] | undefined {\n const id = handle.startsWith('scoop:') ? handle : scoopId(handle);\n const reachable = (record: ScoopRecord | undefined): record is ScoopRecord =>\n !!record && live(record) && (cone === null || record.cone === cone);\n const record = state.scoops[id];\n if (reachable(record)) return [id, record];\n return Object.entries(state.scoops).find(\n ([, candidate]) => reachable(candidate) && candidate.name === handle\n );\n}\n\nfunction remember(work: WorkState, request: string | undefined, answer: Answer): void {\n if (!request) return;\n work.ledger[request] = answer;\n const keys = Object.keys(work.ledger);\n for (const key of keys.slice(0, Math.max(0, keys.length - LEDGER_SIZE))) delete work.ledger[key];\n}\n\ntype Core = { host: Promise<ScoopsHost>; tasks: () => ScoopTasks };\n\nasync function coneOfId(core: Core, coneId: string, context: Context): Promise<Conversation> {\n const { agents } = await core.host;\n const found = await agents.conversation(coneId, context);\n if (!found) throw new Error(`There is no cone ${coneId}.`);\n return found;\n}\n\nasync function isBusy(core: Core, conversation: number, context: Context): Promise<boolean> {\n const { harness } = await core.host;\n const handle = await harness.conversation(conversation as ConversationId, context);\n const view = await handle?.viewState(context);\n const run = (view?.value.docs['pi.live'] as { run?: unknown } | undefined)?.run;\n view?.dispose();\n return Boolean(run);\n}\n\nasync function answered(\n core: Core,\n request: string | undefined,\n context: Context\n): Promise<Answer | undefined> {\n if (!request) return undefined;\n const { harness } = await core.host;\n return (await harness.snapshot(ScoopWorkDoc, context))?.ledger[request];\n}\n\ntype NewFeed = Omit<Feed, 'channel' | 'from'> & {\n from: string;\n agent: boolean;\n prompt: string;\n request?: string;\n followUp?: boolean;\n};\n\nasync function addFeed(core: Core, tx: Tx, parent: number, feed: NewFeed): Promise<number> {\n const task = await tx.createTask(\n core.tasks().reporter as never,\n {\n scoop: feed.scoop,\n prompt: feed.prompt,\n ...(feed.followUp ? { followUp: true } : {}),\n ...(feed.request ? { request: feed.request } : {}),\n },\n {\n ownership: { kind: 'conversation' },\n conversationId: parent as ConversationId,\n background: true,\n }\n );\n (await tx.doc(ScoopWorkDoc)).feeds[String(task)] = {\n scoop: feed.scoop,\n created: feed.created,\n report: feed.report,\n target: feed.target,\n channel: 'scoop-notify',\n from: feed.from,\n agent: feed.agent,\n };\n return Number(task);\n}\n\nfunction selection(\n tools: readonly ToolRegistration[] | undefined,\n names: string[] | undefined,\n mcp?: (names: readonly string[]) => ToolRegistration[]\n) {\n if (!names || !tools) return undefined;\n const picked = tools.filter((tool) => names.includes(tool.name));\n const entries = mcpEntries(names) ?? [];\n if (!entries.length) return picked;\n const codemode = tools.find((tool) => tool.name === CODEMODE);\n if (codemode && !picked.includes(codemode)) picked.push(codemode);\n return [...picked, ...(mcp?.(entries) ?? [])];\n}\n\nfunction liveCount(state: Readonly<AgentsState>, cone: string): number {\n return Object.values(state.scoops).filter((scoop) => scoop.cone === cone && live(scoop)).length;\n}\n\nfunction claimTurn(\n work: WorkState,\n request: SpawnRequest,\n turn: number | null\n): Answer | undefined {\n if (turn === null) return undefined;\n const counted = work.turns[request.cone];\n const count = counted && counted.at === turn ? counted.count : 0;\n if (count >= request.limits.maxPerTurn)\n return {\n code: 1,\n out: `subagent: this turn already started ${count} scoops (the limit is ${request.limits.maxPerTurn})\\n`,\n };\n work.turns[request.cone] = { at: turn, count: count + 1 };\n return undefined;\n}\n\nfunction agentChange(\n request: SpawnRequest,\n folder: string,\n host: Pick<ScoopsHost, 'tools' | 'mcp' | 'layout'>\n): AgentChange {\n const { tools, mcp } = host;\n const model = request.model ?? modelOf(request.role?.model);\n const thinking = request.thinking ?? request.role?.thinking;\n const chosen = selection(tools, request.tools ?? request.role?.tools, mcp);\n const instructions = [request.role?.prompt, request.instructions].filter(Boolean).join('\\n\\n');\n return {\n cwd: request.cwd ?? workspace(folder, host.layout),\n ...(instructions ? { instructions } : {}),\n ...(model ? { model } : {}),\n ...(thinking ? { thinkingLevel: thinking as AgentChange['thinkingLevel'] } : {}),\n ...(chosen ? { tools: chosen } : {}),\n };\n}\n\nasync function narrowMcp(\n tx: Tx,\n state: Readonly<AgentsState>,\n cone: ConversationId,\n child: ConversationId,\n request: SpawnRequest\n): Promise<void> {\n const listed = mcpEntries(request.tools ?? request.role?.tools);\n const caller = state.scoops[request.parent ?? '']?.conversation as ConversationId | undefined;\n const inherited = (await tx.doc(McpAllowDoc, caller ?? cone)).allow;\n if (listed !== null || inherited !== null)\n (await tx.doc(McpAllowDoc, child)).allow = listed ?? inherited;\n}\n\nfunction scoopRecord(\n request: SpawnRequest,\n folder: string,\n conversation: number,\n anchor: number,\n created: Mark | null\n): ScoopRecord {\n return {\n name: request.name.trim() || folder,\n folder,\n cone: request.cone,\n conversation,\n anchor,\n role: request.role?.name ?? null,\n ...(request.role?.memory ? { memory: request.role.memory } : {}),\n ...(request.role?.memory && request.origin ? { origin: request.origin } : {}),\n ...(request.role?.context ? { context: request.role.context } : {}),\n kind: request.kind ?? 'async',\n parent: request.parent ?? request.cone,\n depth: request.depth ?? 1,\n roots: request.roots ?? null,\n created,\n dropped: null,\n gone: false,\n };\n}\n\nasync function spawn(core: Core, request: SpawnRequest, context: Context): Promise<Answer> {\n const done = await answered(core, request.request, context);\n if (done) return done;\n const host = await core.host;\n const { agents } = host;\n const parent = await coneOfId(core, request.cone, context);\n const count = liveCount(agents.state(), request.cone);\n if (count >= request.limits.maxLiveScoops)\n return {\n code: 1,\n out: `subagent: this cone already has ${count} live scoops (the limit is ${request.limits.maxLiveScoops}); stop one first\\n`,\n };\n const created = request.fromAgent ? await tail(parent, context) : null;\n const turn = request.fromAgent ? await turnStart(parent, context) : null;\n return agents.update(async (tx, doc) => {\n const work = await tx.doc(ScoopWorkDoc);\n const refused = claimTurn(work as WorkState, request, turn);\n if (refused) return refused;\n const folder = freeFolder(doc, request.name);\n const id = scoopId(folder);\n const anchor = await tx.createTask(core.tasks().anchor as never, null, {\n ownership: { kind: 'conversation' },\n conversationId: parent.id,\n background: true,\n });\n const child = await tx.createConversation({ ownership: { kind: 'task', taskId: anchor } });\n await configure(tx, child.id, agentChange(request, folder, host));\n await narrowMcp(tx, doc, parent.id, child.id, request);\n doc.scoops[id] = scoopRecord(request, folder, child.id, Number(anchor), created);\n const target =\n request.target === undefined\n ? request.fromAgent\n ? `cone:${request.cone}`\n : null\n : request.target;\n const made: number[] = [];\n const asker = request.asker === undefined ? target : request.asker;\n const from = askerName(doc, asker);\n for (const prompt of request.prompts)\n made.push(\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from,\n agent: asker !== null,\n prompt,\n })\n );\n const answer = { code: 0, out: `${folder}\\n`, tasks: made };\n remember(work as WorkState, request.request, answer);\n return answer;\n }, context);\n}\n\nexport function askerName(state: Readonly<AgentsState>, asker: string | null): string {\n if (asker === null) return 'terminal';\n if (asker.startsWith('cone:')) return state.cones[asker.slice('cone:'.length)]?.name ?? asker;\n return state.scoops[asker]?.name ?? asker;\n}\n\nconst missing = (id: string): Answer => ({\n code: 1,\n out: `subagent: there is no scoop ${id.replace('scoop:', '')}\\n`,\n});\n\nasync function feed(\n core: Core,\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n): Promise<Answer> {\n const done = await answered(core, options.request, context);\n if (done) return done;\n const { harness, agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const parent = await coneOfId(core, record.cone, context);\n const created = options.fromAgent ? await tail(parent, context) : null;\n const { target } = options;\n return harness.commit(async (tx) => {\n await addFeed(core, tx, parent.id, {\n scoop: id,\n created,\n report: target !== null,\n target,\n from: askerName(agents.state(), target),\n agent: target !== null,\n prompt,\n followUp: options.followUp,\n request: options.request,\n });\n const answer = { code: 0, out: `sent to ${record.folder}\\n` };\n remember((await tx.doc(ScoopWorkDoc)) as WorkState, options.request, answer);\n return answer;\n }, context);\n}\n\nasync function signal(core: Core, record: ScoopRecord, context: Context): Promise<void> {\n const { harness, groups } = await core.host;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context, { background: true });\n await groups?.signal(record.conversation);\n}\n\nasync function stopFeeds(\n core: Core,\n scoop: string,\n keep: (feed: Feed) => Promise<boolean>,\n context: Context\n) {\n const { harness } = await core.host;\n const work = (await harness.snapshot(ScoopWorkDoc, context)) ?? { feeds: {} };\n const dropped: string[] = [];\n for (const [task, entry] of Object.entries(work.feeds)) {\n if (entry.scoop !== scoop || (await keep(entry))) continue;\n const record = await harness.getTask(Number(task) as TaskId, context);\n if (record && record.state.status !== 'terminal')\n await harness.abortTask(Number(task) as TaskId, context);\n dropped.push(task);\n }\n if (dropped.length)\n await harness.commit(async (tx) => {\n const doc = await tx.doc(ScoopWorkDoc);\n for (const task of dropped) delete doc.feeds[task];\n }, context);\n return dropped.length;\n}\n\nasync function stop(core: Core, id: string, fromAgent: boolean, context: Context): Promise<Answer> {\n const { agents, files, layout = LEGACY } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n const mark = fromAgent\n ? await tail(await coneOfId(core, record.cone, context), context)\n : { in: 0, at: 0 };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).dropped = mark;\n }, context);\n const place = layout.workspace(record.folder);\n const removed = await files?.remove(place, { recursive: true, force: true }, context);\n const folder = removed?.ok ? `removed ${place}` : `kept ${place}`;\n return {\n code: 0,\n out: `stopped ${record.folder}; its transcript is kept, ${folder}, and its reports stay in ${layout.reports(record.folder, record.cone)}\\n`,\n };\n}\n\nasync function rename(core: Core, id: string, name: string, context: Context): Promise<Answer> {\n const { agents } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const wanted = name.trim();\n if (!wanted) return { code: 2, out: 'subagent: rename needs a non-empty name\\n' };\n await agents.update((_tx, state) => {\n (state.scoops[id] as ScoopRecord).name = wanted;\n }, context);\n return { code: 0, out: `${record.folder} is now called ${wanted}\\n` };\n}\n\nasync function resetWorkspace(\n host: Pick<ScoopsHost, 'files' | 'layout'>,\n folder: string,\n context: Context\n): Promise<boolean> {\n const { files } = host;\n if (!files) return true;\n const place = workspace(folder, host.layout);\n const cleared = await files.remove(place, { recursive: true, force: true }, context);\n if (!cleared.ok) return false;\n if (host.layout?.users) return true;\n return (await files.createDir(place, { recursive: true }, context)).ok;\n}\n\ntype Seen = (mark: Mark | null) => Promise<boolean>;\n\nasync function rewindOne(\n core: Core,\n coneId: string,\n id: string,\n record: ScoopRecord,\n seen: Seen,\n result: Rewound,\n context: Context\n): Promise<Partial<ScoopRecord> | undefined> {\n const host = await core.host;\n const { harness, licks } = host;\n if (!(await seen(record.created))) {\n if (live(record)) {\n await stopFeeds(core, id, async () => false, context);\n await signal(core, record, context);\n result.stopped.push(record.name);\n }\n return { gone: true };\n }\n if (record.dropped !== null) {\n if (await seen(record.dropped)) return undefined;\n const reset = await resetWorkspace(host, record.folder, context);\n result.restored.push(\n reset ? record.name : `${record.name} (its working folder could not be reset)`\n );\n return { dropped: null };\n }\n const withdrawn = await stopFeeds(core, id, (entry) => seen(entry.created), context);\n if (!withdrawn) return undefined;\n const conversation = await harness.conversation(record.conversation as ConversationId, context);\n await conversation?.abort(context);\n await licks.forget(`cone:${coneId}`, 'scoop-notify', id, context);\n return undefined;\n}\n\nasync function rewound(\n core: Core,\n coneId: string,\n fork: Conversation,\n context: Context\n): Promise<Rewound> {\n const { harness, agents } = await core.host;\n const read = (id: number) =>\n harness.commit((tx) => tx.conversation(id as ConversationId), context);\n const seen: Seen = async (mark) =>\n mark === null || mark.in === 0 || (await visible(read, fork.id, mark));\n const result: Rewound = { stopped: [], restored: [] };\n const changes: [string, Partial<ScoopRecord>][] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if (record.cone !== coneId || record.gone) continue;\n const change = await rewindOne(core, coneId, id, record, seen, result, context);\n if (change) changes.push([id, change]);\n }\n if (changes.length)\n await agents.update((_tx, state) => {\n for (const [id, change] of changes) Object.assign(state.scoops[id] as ScoopRecord, change);\n }, context);\n return result;\n}\n\nasync function list(core: Core, coneId: string | null, context: Context): Promise<ScoopSummary[]> {\n const { agents } = await core.host;\n const out: ScoopSummary[] = [];\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n if ((coneId !== null && record.cone !== coneId) || !live(record)) continue;\n out.push({\n id,\n folder: record.folder,\n name: record.name,\n role: record.role,\n busy: await isBusy(core, record.conversation, context),\n });\n }\n return out;\n}\n\nasync function working(core: Core, ids: readonly string[], context: Context): Promise<string[]> {\n const { harness, agents } = await core.host;\n const feeds = Object.values((await harness.snapshot(ScoopWorkDoc, context))?.feeds ?? {});\n const out: string[] = [];\n for (const id of ids) {\n const record = agents.state().scoops[id];\n if (!record) continue;\n if (\n feeds.some((entry) => entry.scoop === id) ||\n (await isBusy(core, record.conversation, context))\n )\n out.push(id);\n }\n return out;\n}\n\nasync function notifyWhenDone(\n core: Core,\n coneId: string,\n ids: string[],\n deadline: number,\n context: Context\n) {\n const { harness } = await core.host;\n const parent = await coneOfId(core, coneId, context);\n await harness.commit(\n (tx) =>\n tx.createTask(\n core.tasks().wait as never,\n { scoops: ids, cone: coneId, deadline },\n { ownership: { kind: 'conversation' }, conversationId: parent.id, background: true }\n ),\n context\n );\n}\n\nasync function detach(core: Core, tasks: readonly number[], target: string, context: Context) {\n const { harness } = await core.host;\n await harness.commit(async (tx) => {\n const work = await tx.doc(ScoopWorkDoc);\n for (const task of tasks) {\n const entry = work.feeds[String(task)];\n if (!entry) continue;\n entry.report = true;\n entry.target = target;\n entry.channel = 'bash';\n }\n }, context);\n}\n\nasync function note(core: Core, id: string, text: string, context: Context): Promise<Answer> {\n const { agents, licks } = await core.host;\n const record = agents.state().scoops[id];\n if (!record || !live(record)) return missing(id);\n const label = `${record.name} (${record.role ?? 'scoop'})`;\n await licks.deliver(\n {\n channel: 'scoop-notify',\n source: `${id}#note`,\n title: label,\n text: `[scoop ${label} progress]`,\n body: text,\n target: `cone:${record.cone}`,\n },\n context\n );\n return { code: 0, out: 'note sent to the cone\\n' };\n}\n\nexport function createScoops(host: Promise<ScoopsHost>, tasks: () => ScoopTasks) {\n const core: Core = { host, tasks };\n return {\n detach: (made: readonly number[], target: string, context: Context) =>\n detach(core, made, target, context),\n note: (id: string, text: string, context: Context) => note(core, id, text, context),\n spawn: (request: SpawnRequest, context: Context) => spawn(core, request, context),\n feed: (\n id: string,\n prompt: string,\n options: { fromAgent: boolean; request: string; followUp: boolean; target: string | null },\n context: Context\n ) => feed(core, id, prompt, options, context),\n stop: (id: string, fromAgent: boolean, context: Context) => stop(core, id, fromAgent, context),\n rename: (id: string, name: string, context: Context) => rename(core, id, name, context),\n rewound: (coneId: string, fork: Conversation, context: Context) =>\n rewound(core, coneId, fork, context),\n list: (coneId: string | null, context: Context) => list(core, coneId, context),\n busy: (conversation: number, context: Context) => isBusy(core, conversation, context),\n working: (ids: readonly string[], context: Context) => working(core, ids, context),\n notifyWhenDone: (coneId: string, ids: string[], deadline: number, context: Context) =>\n notifyWhenDone(core, coneId, ids, deadline, context),\n };\n}\n\nexport function modelOf(\n value: string | undefined\n): { provider: string; modelId: string } | undefined {\n if (!value) return undefined;\n const at = value.indexOf('/');\n if (at <= 0) return undefined;\n return { provider: value.slice(0, at), modelId: value.slice(at + 1) };\n}\n\nexport type Scoops = ReturnType<typeof createScoops>;\n"],
5
+ "mappings": "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",
6
6
  "names": ["record", "feed"]
7
7
  }
@@ -1,4 +1,5 @@
1
1
  import { answerText } from "../agent.js";
2
+ import { quote } from "../kernel/env.js";
2
3
  import { resolve } from "../kernel/paths.js";
3
4
  import {
4
5
  choices,
@@ -12,8 +13,7 @@ import {
12
13
  role,
13
14
  unsupported
14
15
  } from "./cli.js";
15
- import { SCOOPS_ROOT } from "./service.js";
16
- const SESSIONS = { tmp: "/tmp/agent-sessions", durable: "/home/sessions" };
16
+ import { SESSIONS } from "../layout.js";
17
17
  const SYNC_VALUES = [
18
18
  "--name",
19
19
  "--agent",
@@ -68,25 +68,32 @@ function transcript(record, entries) {
68
68
  ${body.join("\n\n")}
69
69
  `;
70
70
  }
71
- async function archive(deps, record, persist, context) {
71
+ async function archive(deps, record, persist, user, context) {
72
72
  if (persist === "none") return null;
73
+ const kept = persist;
73
74
  const conversation = await deps.harness.conversation(
74
75
  record.conversation,
75
76
  context
76
77
  );
77
78
  if (!conversation) return null;
78
79
  const { entries } = await conversation.context(context);
79
- const path = `${SESSIONS[persist]}/${record.folder}.md`;
80
- await deps.env.writeFile(path, transcript(record, entries), context);
81
- return path;
80
+ const dir = deps.layout.sessions(kept, user);
81
+ const path = `${dir}/${record.folder}.md`;
82
+ if (kept === "tmp") await deps.layout.ownDir(dir, user, context);
83
+ const env = await deps.layout.envFor(user, context) ?? deps.env;
84
+ const written = await env.writeFile(path, transcript(record, entries), context);
85
+ return written.ok ? path : null;
82
86
  }
83
- async function finish(deps, id, persist, context) {
87
+ async function finish(deps, id, persist, user, shares, context) {
84
88
  const record = deps.agents.state().scoops[id];
85
89
  if (!record) return;
86
- await archive(deps, record, persist, context).catch(() => null);
90
+ const written = shares.filter((shared) => shared.write).map((shared) => quote(shared.path));
91
+ if (written.length)
92
+ await deps.env.exec(`chmod -R g+rwX ${written.join(" ")}`, void 0, context);
93
+ await archive(deps, record, persist, user, context).catch(() => null);
87
94
  await deps.scoops.stop(id, false, context);
88
95
  await deps.env.remove(
89
- `${SCOOPS_ROOT}/${record.folder}`,
96
+ deps.layout.scoopRoot(record.folder),
90
97
  { recursive: true, force: true },
91
98
  context
92
99
  );
@@ -115,6 +122,40 @@ function watchPid(deps, pid, end) {
115
122
  }, 1e3);
116
123
  return () => clearInterval(timer);
117
124
  }
125
+ function sharesOf(home, cwd, workdir, readOnly) {
126
+ const inside = (path) => path.startsWith(`${home}/`);
127
+ const out = [];
128
+ if (workdir && inside(workdir)) out.push({ path: workdir, write: true });
129
+ for (const path of [...readOnly, ...workdir ? [] : [cwd]])
130
+ if (inside(path) && !out.some((shared) => shared.path === path))
131
+ out.push({ path, write: false });
132
+ return out;
133
+ }
134
+ function shareScript(home, shares) {
135
+ const lines = [];
136
+ for (const { path, write } of shares) {
137
+ const at = quote(path);
138
+ lines.push(`chmod -R ${write ? "g+rwX" : "g+rX"} ${at}`);
139
+ if (write)
140
+ lines.push(
141
+ `shopt -s globstar dotglob nullglob; for dir in ${at} ${at}/**/; do chmod g+s "$dir"; done`
142
+ );
143
+ const parts = path.slice(home.length + 1).split("/").slice(0, -1);
144
+ for (let depth = 1; depth <= parts.length; depth++)
145
+ lines.push(`chmod g+x ${quote(`${home}/${parts.slice(0, depth).join("/")}`)}`);
146
+ }
147
+ return lines.join("\n");
148
+ }
149
+ function shareNote(shares) {
150
+ const listed = shares.map(({ path, write }) => `${path}${write ? " (you may change files there)" : " (read only)"}`).join(", ");
151
+ return `Your caller shared these with you through its group: ${listed}.`;
152
+ }
153
+ async function share(deps, request, shares, context) {
154
+ const env = await deps.layout.envFor(request.user ?? null, context);
155
+ if (!env || !shares.length) return;
156
+ const home = deps.layout.homeOf(request.user ?? null);
157
+ await env.exec(shareScript(home, shares), void 0, context);
158
+ }
118
159
  async function plan(deps, request, parsed, context) {
119
160
  const given = await prompts(deps, request.argv, request, context);
120
161
  let workdir;
@@ -133,13 +174,17 @@ async function plan(deps, request, parsed, context) {
133
174
  const systemFile = last(parsed, "--system-prompt-file");
134
175
  const system = last(parsed, "--system-prompt") ?? (systemFile ? await readText(deps, systemFile, request, context) : void 0);
135
176
  if (system) notes.push(system);
136
- if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);
137
177
  const readOnly = (last(parsed, "--read-only") ?? "").split(",").map((path) => path.trim()).filter(Boolean).map((path) => resolve(request.cwd, path));
178
+ const home = deps.layout.homeOf(request.user ?? null);
179
+ const shares = deps.layout.users ? sharesOf(home, request.cwd, workdir, readOnly) : [];
180
+ if (shares.length) notes.push(shareNote(shares));
181
+ if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);
138
182
  const result = {
139
183
  given,
140
184
  instructions: notes.join("\n\n"),
141
185
  readOnly,
142
- persist: persistOf(parsed.switches)
186
+ persist: persistOf(parsed.switches),
187
+ shares
143
188
  };
144
189
  if (workdir) result.workdir = workdir;
145
190
  return result;
@@ -189,6 +234,7 @@ async function runSync(deps, request, who, context) {
189
234
  if (isAnswer(chosen)) return chosen;
190
235
  const found = await role(deps, parsed);
191
236
  if (found.error) return found.error;
237
+ await share(deps, request, planned.shares, context);
192
238
  const spawned = await deps.scoops.spawn(
193
239
  {
194
240
  cone: who.cone,
@@ -226,10 +272,11 @@ async function runSync(deps, request, who, context) {
226
272
  const raced = await Promise.race([outcome(deps, tasks, context), ended]);
227
273
  if (typeof raced === "string") {
228
274
  const answer = await settle(deps, who, id, tasks, raced, context);
229
- if (answer.code === 130) await finish(deps, id, planned.persist, context);
275
+ if (answer.code === 130)
276
+ await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);
230
277
  return answer;
231
278
  }
232
- await finish(deps, id, planned.persist, context);
279
+ await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);
233
280
  return answerOf(raced);
234
281
  } finally {
235
282
  unwatch();
@@ -249,6 +296,9 @@ export {
249
296
  cancelSync,
250
297
  detachSync,
251
298
  runSync,
299
+ shareNote,
300
+ shareScript,
301
+ sharesOf,
252
302
  transcript
253
303
  };
254
304
  //# sourceMappingURL=sync.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/scoops/sync.ts"],
4
- "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ConversationId, EntryRecord, TaskId } from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport type { ScoopRecord } from '../agents.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport {\n type Caller,\n choices,\n type Deps,\n fail,\n flags,\n isAnswer,\n last,\n MAX_DEPTH,\n prompts,\n readText,\n role,\n unsupported,\n} from './cli.ts';\nimport type { ReportResult } from './extension.ts';\nimport type { Request } from './requests.ts';\nimport { type Answer, SCOOPS_ROOT } from './service.ts';\n\nexport const SESSIONS = { tmp: '/tmp/agent-sessions', durable: '/home/sessions' };\n\ntype Ending = 'cancel' | 'detach';\n\ninterface Pending {\n end: (ending: Ending) => void;\n}\n\nexport interface SyncState {\n pending: Map<string, Pending>;\n}\n\nconst SYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n '--read-only',\n '--system-prompt',\n '--system-prompt-file',\n '--background-after',\n];\nconst SYNC_SWITCHES = new Set([\n '--persist-session',\n '--no-persist-session',\n '--no-extensions',\n '--no-skills',\n '--no-context-files',\n]);\n\ntype Persist = 'tmp' | 'durable' | 'none';\n\nfunction persistOf(switches: Set<string>): Persist {\n if (switches.has('--no-persist-session')) return 'none';\n return switches.has('--persist-session') ? 'durable' : 'tmp';\n}\n\nfunction block(text: unknown): string {\n return typeof text === 'string' ? text : JSON.stringify(text, null, 2);\n}\n\nfunction entryMarkdown(entry: EntryRecord): string | undefined {\n const message = entry.model?.[0] as { content?: unknown; toolCallId?: string } | undefined;\n if (entry.kind === 'pi.user') return `## Request\\n\\n${answerText(message?.content)}`;\n if (entry.kind === 'pi.tool-result')\n return `### Result\\n\\n\\`\\`\\`\\n${answerText(message?.content)}\\n\\`\\`\\``;\n if (entry.kind !== 'pi.assistant') return undefined;\n const parts = Array.isArray(message?.content)\n ? (message.content as { type: string; name?: string; arguments?: unknown }[])\n : [];\n const calls = parts\n .filter((part) => part.type === 'toolCall')\n .map((part) => `\\`${part.name}\\` ${block(part.arguments)}`);\n return [`## Answer\\n\\n${answerText(message?.content)}`, ...calls].join('\\n\\n');\n}\n\nexport function transcript(record: ScoopRecord, entries: readonly EntryRecord[]): string {\n const body = entries.map(entryMarkdown).filter(Boolean);\n return `# ${record.name}${record.role ? ` (${record.role})` : ''}\\n\\n${body.join('\\n\\n')}\\n`;\n}\n\nasync function archive(\n deps: Deps,\n record: ScoopRecord,\n persist: Persist,\n context: Context\n): Promise<string | null> {\n if (persist === 'none') return null;\n const conversation = await deps.harness.conversation(\n record.conversation as ConversationId,\n context\n );\n if (!conversation) return null;\n const { entries } = await conversation.context(context);\n const path = `${SESSIONS[persist]}/${record.folder}.md`;\n await deps.env.writeFile(path, transcript(record, entries), context);\n return path;\n}\n\nasync function finish(deps: Deps, id: string, persist: Persist, context: Context): Promise<void> {\n const record = deps.agents.state().scoops[id];\n if (!record) return;\n await archive(deps, record, persist, context).catch(() => null);\n await deps.scoops.stop(id, false, context);\n await deps.env.remove(\n `${SCOOPS_ROOT}/${record.folder}`,\n { recursive: true, force: true },\n context\n );\n}\n\nasync function callerRunning(deps: Deps, who: Caller, context: Context): Promise<boolean> {\n if (!who.fromAgent) return false;\n const state = deps.agents.state();\n const conversation = who.scoop\n ? state.scoops[who.scoop]?.conversation\n : state.cones[who.cone]?.conversation;\n return conversation !== undefined && deps.scoops.busy(conversation, context);\n}\n\nasync function keep(\n deps: Deps,\n id: string,\n tasks: readonly number[],\n target: string | null,\n context: Context\n) {\n if (target) await deps.scoops.detach(tasks, target, context);\n await deps.agents.update((_tx, state) => {\n const record = state.scoops[id];\n if (record) record.kind = 'async';\n }, context);\n}\n\nfunction watchPid(deps: Deps, pid: number | null, end: (ending: Ending) => void): () => void {\n const alive = deps.alive;\n if (pid === null || !alive) return () => undefined;\n const timer = setInterval(() => {\n void alive(pid).then(\n (yes) => yes || end('cancel'),\n () => undefined\n );\n }, 1000);\n return () => clearInterval(timer);\n}\n\ninterface Plan {\n given: string[];\n workdir?: string;\n instructions: string;\n readOnly: string[];\n persist: Persist;\n}\n\nasync function plan(\n deps: Deps,\n request: Request,\n parsed: ReturnType<typeof flags>,\n context: Context\n) {\n const given = await prompts(deps, request.argv, request, context);\n let workdir: string | undefined;\n const notes: string[] = [];\n if (!given.length && parsed.rest.length === 3) {\n const [cwd, allowed, prompt] = parsed.rest as [string, string, string];\n workdir = resolve(request.cwd, cwd);\n if (allowed && allowed !== '*')\n notes.push(\n `Use only these commands in bash: ${allowed}. This is not enforced; keep to it anyway.`\n );\n given.push(prompt);\n } else if (parsed.rest.length) return fail(`unexpected argument ${parsed.rest[0]}`, 2);\n if (!given.length)\n return fail('agent needs --prompt, --file, - or <cwd> <allowed-commands> <prompt>', 2);\n const systemFile = last(parsed, '--system-prompt-file');\n const system =\n last(parsed, '--system-prompt') ??\n (systemFile ? await readText(deps, systemFile, request, context) : undefined);\n if (system) notes.push(system);\n if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);\n const readOnly = (last(parsed, '--read-only') ?? '')\n .split(',')\n .map((path) => path.trim())\n .filter(Boolean)\n .map((path) => resolve(request.cwd, path));\n const result: Plan = {\n given,\n instructions: notes.join('\\n\\n'),\n readOnly,\n persist: persistOf(parsed.switches),\n };\n if (workdir) result.workdir = workdir;\n return result;\n}\n\nasync function outcome(\n deps: Deps,\n tasks: readonly number[],\n context: Context\n): Promise<ReportResult> {\n let result: ReportResult = { text: '', failed: 'no request', path: null };\n for (const task of tasks) {\n const settled = await deps.harness.waitForTask(task as TaskId<ReportResult>, context);\n const outcome = settled.state.outcome;\n result =\n outcome.status === 'completed'\n ? outcome.result\n : { text: '', failed: outcome.status, path: null };\n }\n return result;\n}\n\nfunction answerOf(result: ReportResult): Answer {\n if (result.failed) return fail(`the scoop's request ended without an answer: ${result.failed}`);\n return { code: 0, out: result.text.endsWith('\\n') ? result.text : `${result.text}\\n` };\n}\n\nasync function settle(\n deps: Deps,\n who: Caller,\n id: string,\n tasks: readonly number[],\n ending: Ending,\n context: Context\n): Promise<Answer> {\n const handle = id.slice('scoop:'.length);\n if (ending === 'detach') {\n await keep(deps, id, tasks, who.id, context);\n const how = who.id ? 'its answer arrives as a lick' : `follow it with agent wait ${handle}`;\n return { code: 0, out: `${handle} continues in the background; ${how}\\n` };\n }\n if (await callerRunning(deps, who, context)) {\n await keep(deps, id, tasks, who.id, context);\n return {\n code: 143,\n out: `agent: the call was interrupted; ${handle} continues and its answer arrives as a lick\\n`,\n };\n }\n return { code: 130, out: 'agent: stopped\\n' };\n}\n\nexport async function runSync(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const refused = unsupported(request.argv);\n if (refused) return refused;\n if (who.depth >= MAX_DEPTH) return fail(`agents nest at most ${MAX_DEPTH} deep`);\n const parsed = flags(request.argv, SYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !SYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const planned = await plan(deps, request, parsed, context);\n if (isAnswer(planned)) return planned;\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n const spawned = await deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'sync',\n parent: who.scoop ?? who.cone,\n depth: who.depth + 1,\n roots: { write: planned.workdir ? [planned.workdir] : [], read: planned.readOnly },\n ...(planned.workdir ? { cwd: planned.workdir } : {}),\n ...(planned.instructions ? { instructions: planned.instructions } : {}),\n target: null,\n asker: who.id,\n name: last(parsed, '--name') ?? found.role?.name ?? 'agent',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: planned.given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n if (spawned.code !== 0) return spawned;\n const id = `scoop:${spawned.out.trim()}`;\n const tasks = spawned.tasks ?? [];\n let end: (ending: Ending) => void = () => undefined;\n const ended = new Promise<Ending>((done) => {\n end = done;\n });\n deps.sync.pending.set(request.id, { end });\n const unwatch = watchPid(deps, request.pid, end);\n try {\n const raced = await Promise.race([outcome(deps, tasks, context), ended]);\n if (typeof raced === 'string') {\n const answer = await settle(deps, who, id, tasks, raced, context);\n if (answer.code === 130) await finish(deps, id, planned.persist, context);\n return answer;\n }\n await finish(deps, id, planned.persist, context);\n return answerOf(raced);\n } finally {\n unwatch();\n deps.sync.pending.delete(request.id);\n }\n}\n\nexport async function cancelSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('cancel');\n return { code: 0, out: '' };\n}\n\nexport async function detachSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('detach');\n return { code: 0, out: '' };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ConversationId, EntryRecord, TaskId } from '@earendil-works/pi-durable';\nimport { answerText } from '../agent.ts';\nimport type { ScoopRecord } from '../agents.ts';\nimport { quote } from '../kernel/env.ts';\nimport { resolve } from '../kernel/paths.ts';\nimport {\n type Caller,\n choices,\n type Deps,\n fail,\n flags,\n isAnswer,\n last,\n MAX_DEPTH,\n prompts,\n readText,\n role,\n unsupported,\n} from './cli.ts';\nimport type { ReportResult } from './extension.ts';\nimport type { Request } from './requests.ts';\nimport type { Answer } from './service.ts';\n\nexport { SESSIONS } from '../layout.ts';\n\ntype Ending = 'cancel' | 'detach';\n\ninterface Pending {\n end: (ending: Ending) => void;\n}\n\nexport interface SyncState {\n pending: Map<string, Pending>;\n}\n\nconst SYNC_VALUES = [\n '--name',\n '--agent',\n '--provider',\n '--model',\n '--thinking',\n '--effort',\n '--tools',\n '--prompt',\n '--file',\n '--read-only',\n '--system-prompt',\n '--system-prompt-file',\n '--background-after',\n];\nconst SYNC_SWITCHES = new Set([\n '--persist-session',\n '--no-persist-session',\n '--no-extensions',\n '--no-skills',\n '--no-context-files',\n]);\n\ntype Persist = 'tmp' | 'durable' | 'none';\ntype Kept = Exclude<Persist, 'none'>;\n\nfunction persistOf(switches: Set<string>): Persist {\n if (switches.has('--no-persist-session')) return 'none';\n return switches.has('--persist-session') ? 'durable' : 'tmp';\n}\n\nfunction block(text: unknown): string {\n return typeof text === 'string' ? text : JSON.stringify(text, null, 2);\n}\n\nfunction entryMarkdown(entry: EntryRecord): string | undefined {\n const message = entry.model?.[0] as { content?: unknown; toolCallId?: string } | undefined;\n if (entry.kind === 'pi.user') return `## Request\\n\\n${answerText(message?.content)}`;\n if (entry.kind === 'pi.tool-result')\n return `### Result\\n\\n\\`\\`\\`\\n${answerText(message?.content)}\\n\\`\\`\\``;\n if (entry.kind !== 'pi.assistant') return undefined;\n const parts = Array.isArray(message?.content)\n ? (message.content as { type: string; name?: string; arguments?: unknown }[])\n : [];\n const calls = parts\n .filter((part) => part.type === 'toolCall')\n .map((part) => `\\`${part.name}\\` ${block(part.arguments)}`);\n return [`## Answer\\n\\n${answerText(message?.content)}`, ...calls].join('\\n\\n');\n}\n\nexport function transcript(record: ScoopRecord, entries: readonly EntryRecord[]): string {\n const body = entries.map(entryMarkdown).filter(Boolean);\n return `# ${record.name}${record.role ? ` (${record.role})` : ''}\\n\\n${body.join('\\n\\n')}\\n`;\n}\n\nasync function archive(\n deps: Deps,\n record: ScoopRecord,\n persist: Persist,\n user: string | null,\n context: Context\n): Promise<string | null> {\n if (persist === 'none') return null;\n const kept: Kept = persist;\n const conversation = await deps.harness.conversation(\n record.conversation as ConversationId,\n context\n );\n if (!conversation) return null;\n const { entries } = await conversation.context(context);\n const dir = deps.layout.sessions(kept, user);\n const path = `${dir}/${record.folder}.md`;\n if (kept === 'tmp') await deps.layout.ownDir(dir, user, context);\n const env = (await deps.layout.envFor(user, context)) ?? deps.env;\n const written = await env.writeFile(path, transcript(record, entries), context);\n return written.ok ? path : null;\n}\n\nasync function finish(\n deps: Deps,\n id: string,\n persist: Persist,\n user: string | null,\n shares: readonly Shared[],\n context: Context\n): Promise<void> {\n const record = deps.agents.state().scoops[id];\n if (!record) return;\n const written = shares.filter((shared) => shared.write).map((shared) => quote(shared.path));\n if (written.length)\n await deps.env.exec(`chmod -R g+rwX ${written.join(' ')}`, undefined, context);\n await archive(deps, record, persist, user, context).catch(() => null);\n await deps.scoops.stop(id, false, context);\n await deps.env.remove(\n deps.layout.scoopRoot(record.folder),\n { recursive: true, force: true },\n context\n );\n}\n\nasync function callerRunning(deps: Deps, who: Caller, context: Context): Promise<boolean> {\n if (!who.fromAgent) return false;\n const state = deps.agents.state();\n const conversation = who.scoop\n ? state.scoops[who.scoop]?.conversation\n : state.cones[who.cone]?.conversation;\n return conversation !== undefined && deps.scoops.busy(conversation, context);\n}\n\nasync function keep(\n deps: Deps,\n id: string,\n tasks: readonly number[],\n target: string | null,\n context: Context\n) {\n if (target) await deps.scoops.detach(tasks, target, context);\n await deps.agents.update((_tx, state) => {\n const record = state.scoops[id];\n if (record) record.kind = 'async';\n }, context);\n}\n\nfunction watchPid(deps: Deps, pid: number | null, end: (ending: Ending) => void): () => void {\n const alive = deps.alive;\n if (pid === null || !alive) return () => undefined;\n const timer = setInterval(() => {\n void alive(pid).then(\n (yes) => yes || end('cancel'),\n () => undefined\n );\n }, 1000);\n return () => clearInterval(timer);\n}\n\nexport type Shared = { path: string; write: boolean };\n\nexport function sharesOf(\n home: string,\n cwd: string,\n workdir: string | undefined,\n readOnly: readonly string[]\n): Shared[] {\n const inside = (path: string) => path.startsWith(`${home}/`);\n const out: Shared[] = [];\n if (workdir && inside(workdir)) out.push({ path: workdir, write: true });\n for (const path of [...readOnly, ...(workdir ? [] : [cwd])])\n if (inside(path) && !out.some((shared) => shared.path === path))\n out.push({ path, write: false });\n return out;\n}\n\nexport function shareScript(home: string, shares: readonly Shared[]): string {\n const lines: string[] = [];\n for (const { path, write } of shares) {\n const at = quote(path);\n lines.push(`chmod -R ${write ? 'g+rwX' : 'g+rX'} ${at}`);\n if (write)\n lines.push(\n `shopt -s globstar dotglob nullglob; for dir in ${at} ${at}/**/; do chmod g+s \"$dir\"; done`\n );\n const parts = path\n .slice(home.length + 1)\n .split('/')\n .slice(0, -1);\n for (let depth = 1; depth <= parts.length; depth++)\n lines.push(`chmod g+x ${quote(`${home}/${parts.slice(0, depth).join('/')}`)}`);\n }\n return lines.join('\\n');\n}\n\nexport function shareNote(shares: readonly Shared[]): string {\n const listed = shares\n .map(({ path, write }) => `${path}${write ? ' (you may change files there)' : ' (read only)'}`)\n .join(', ');\n return `Your caller shared these with you through its group: ${listed}.`;\n}\n\nasync function share(deps: Deps, request: Request, shares: readonly Shared[], context: Context) {\n const env = await deps.layout.envFor(request.user ?? null, context);\n if (!env || !shares.length) return;\n const home = deps.layout.homeOf(request.user ?? null);\n await env.exec(shareScript(home, shares), undefined, context);\n}\n\ninterface Plan {\n given: string[];\n shares: Shared[];\n workdir?: string;\n instructions: string;\n readOnly: string[];\n persist: Persist;\n}\n\nasync function plan(\n deps: Deps,\n request: Request,\n parsed: ReturnType<typeof flags>,\n context: Context\n) {\n const given = await prompts(deps, request.argv, request, context);\n let workdir: string | undefined;\n const notes: string[] = [];\n if (!given.length && parsed.rest.length === 3) {\n const [cwd, allowed, prompt] = parsed.rest as [string, string, string];\n workdir = resolve(request.cwd, cwd);\n if (allowed && allowed !== '*')\n notes.push(\n `Use only these commands in bash: ${allowed}. This is not enforced; keep to it anyway.`\n );\n given.push(prompt);\n } else if (parsed.rest.length) return fail(`unexpected argument ${parsed.rest[0]}`, 2);\n if (!given.length)\n return fail('agent needs --prompt, --file, - or <cwd> <allowed-commands> <prompt>', 2);\n const systemFile = last(parsed, '--system-prompt-file');\n const system =\n last(parsed, '--system-prompt') ??\n (systemFile ? await readText(deps, systemFile, request, context) : undefined);\n if (system) notes.push(system);\n const readOnly = (last(parsed, '--read-only') ?? '')\n .split(',')\n .map((path) => path.trim())\n .filter(Boolean)\n .map((path) => resolve(request.cwd, path));\n const home = deps.layout.homeOf(request.user ?? null);\n const shares = deps.layout.users ? sharesOf(home, request.cwd, workdir, readOnly) : [];\n if (shares.length) notes.push(shareNote(shares));\n if (workdir) notes.push(`Your working folder is ${workdir}; you may change files there.`);\n const result: Plan = {\n given,\n instructions: notes.join('\\n\\n'),\n readOnly,\n persist: persistOf(parsed.switches),\n shares,\n };\n if (workdir) result.workdir = workdir;\n return result;\n}\n\nasync function outcome(\n deps: Deps,\n tasks: readonly number[],\n context: Context\n): Promise<ReportResult> {\n let result: ReportResult = { text: '', failed: 'no request', path: null };\n for (const task of tasks) {\n const settled = await deps.harness.waitForTask(task as TaskId<ReportResult>, context);\n const outcome = settled.state.outcome;\n result =\n outcome.status === 'completed'\n ? outcome.result\n : { text: '', failed: outcome.status, path: null };\n }\n return result;\n}\n\nfunction answerOf(result: ReportResult): Answer {\n if (result.failed) return fail(`the scoop's request ended without an answer: ${result.failed}`);\n return { code: 0, out: result.text.endsWith('\\n') ? result.text : `${result.text}\\n` };\n}\n\nasync function settle(\n deps: Deps,\n who: Caller,\n id: string,\n tasks: readonly number[],\n ending: Ending,\n context: Context\n): Promise<Answer> {\n const handle = id.slice('scoop:'.length);\n if (ending === 'detach') {\n await keep(deps, id, tasks, who.id, context);\n const how = who.id ? 'its answer arrives as a lick' : `follow it with agent wait ${handle}`;\n return { code: 0, out: `${handle} continues in the background; ${how}\\n` };\n }\n if (await callerRunning(deps, who, context)) {\n await keep(deps, id, tasks, who.id, context);\n return {\n code: 143,\n out: `agent: the call was interrupted; ${handle} continues and its answer arrives as a lick\\n`,\n };\n }\n return { code: 130, out: 'agent: stopped\\n' };\n}\n\nexport async function runSync(\n deps: Deps,\n request: Request,\n who: Caller,\n context: Context\n): Promise<Answer> {\n const refused = unsupported(request.argv);\n if (refused) return refused;\n if (who.depth >= MAX_DEPTH) return fail(`agents nest at most ${MAX_DEPTH} deep`);\n const parsed = flags(request.argv, SYNC_VALUES);\n const unknown = [...parsed.switches].find((flag) => !SYNC_SWITCHES.has(flag));\n if (unknown) return fail(`unknown option ${unknown}`, 2);\n const planned = await plan(deps, request, parsed, context);\n if (isAnswer(planned)) return planned;\n const chosen = choices(parsed);\n if (isAnswer(chosen)) return chosen;\n const found = await role(deps, parsed);\n if (found.error) return found.error;\n await share(deps, request, planned.shares, context);\n const spawned = await deps.scoops.spawn(\n {\n cone: who.cone,\n kind: 'sync',\n parent: who.scoop ?? who.cone,\n depth: who.depth + 1,\n roots: { write: planned.workdir ? [planned.workdir] : [], read: planned.readOnly },\n ...(planned.workdir ? { cwd: planned.workdir } : {}),\n ...(planned.instructions ? { instructions: planned.instructions } : {}),\n target: null,\n asker: who.id,\n name: last(parsed, '--name') ?? found.role?.name ?? 'agent',\n ...(found.role ? { role: found.role } : {}),\n ...(chosen.model ? { model: chosen.model } : {}),\n ...(chosen.thinking ? { thinking: chosen.thinking as never } : {}),\n ...(chosen.tools ? { tools: chosen.tools } : {}),\n prompts: planned.given,\n origin: request.cwd,\n fromAgent: who.fromAgent,\n request: request.id,\n limits: found.roles.limits,\n },\n context\n );\n if (spawned.code !== 0) return spawned;\n const id = `scoop:${spawned.out.trim()}`;\n const tasks = spawned.tasks ?? [];\n let end: (ending: Ending) => void = () => undefined;\n const ended = new Promise<Ending>((done) => {\n end = done;\n });\n deps.sync.pending.set(request.id, { end });\n const unwatch = watchPid(deps, request.pid, end);\n try {\n const raced = await Promise.race([outcome(deps, tasks, context), ended]);\n if (typeof raced === 'string') {\n const answer = await settle(deps, who, id, tasks, raced, context);\n if (answer.code === 130)\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answer;\n }\n await finish(deps, id, planned.persist, request.user ?? null, planned.shares, context);\n return answerOf(raced);\n } finally {\n unwatch();\n deps.sync.pending.delete(request.id);\n }\n}\n\nexport async function cancelSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('cancel');\n return { code: 0, out: '' };\n}\n\nexport async function detachSync(\n deps: Deps,\n requestId: string,\n _context: Context\n): Promise<Answer> {\n deps.sync.pending.get(requestId)?.end('detach');\n return { code: 0, out: '' };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["outcome"]
7
7
  }