@ai-ecoverse/slicc-agent 5.6.0 → 5.8.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 (45) hide show
  1. package/README.md +10 -6
  2. package/dist/agent.js +8 -2
  3. package/dist/agent.js.map +2 -2
  4. package/dist/approvals/index.js +62 -29
  5. package/dist/approvals/index.js.map +2 -2
  6. package/dist/approvals/record.js.map +1 -1
  7. package/dist/control.js +2 -1
  8. package/dist/control.js.map +2 -2
  9. package/dist/guests/attribution.js +19 -0
  10. package/dist/guests/attribution.js.map +2 -2
  11. package/dist/guests/client.js +4 -3
  12. package/dist/guests/client.js.map +2 -2
  13. package/dist/guests/guard.js +168 -23
  14. package/dist/guests/guard.js.map +3 -3
  15. package/dist/guests/index.js +129 -67
  16. package/dist/guests/index.js.map +2 -2
  17. package/dist/guests/review.js +262 -0
  18. package/dist/guests/review.js.map +7 -0
  19. package/dist/guests/seats.js.map +2 -2
  20. package/dist/guests/serve.js +13 -13
  21. package/dist/guests/serve.js.map +2 -2
  22. package/dist/host.js +14 -8
  23. package/dist/host.js.map +2 -2
  24. package/dist/services.js +2 -0
  25. package/dist/services.js.map +2 -2
  26. package/dist/spectrum/agent-port.js +1 -1
  27. package/dist/spectrum/agent-port.js.map +2 -2
  28. package/dist/spectrum/messages.js +50 -6
  29. package/dist/spectrum/messages.js.map +2 -2
  30. package/dist/spectrum/proposals.js +7 -3
  31. package/dist/spectrum/proposals.js.map +2 -2
  32. package/dist/types/agent.d.ts +4 -0
  33. package/dist/types/approvals/index.d.ts +5 -2
  34. package/dist/types/approvals/record.d.ts +2 -0
  35. package/dist/types/control.d.ts +1 -1
  36. package/dist/types/guests/attribution.d.ts +16 -0
  37. package/dist/types/guests/guard.d.ts +29 -2
  38. package/dist/types/guests/index.d.ts +10 -4
  39. package/dist/types/guests/review.d.ts +68 -0
  40. package/dist/types/guests/seats.d.ts +21 -1
  41. package/dist/types/guests/serve.d.ts +3 -3
  42. package/dist/types/services.d.ts +5 -2
  43. package/dist/types/spectrum/messages.d.ts +2 -0
  44. package/dist/types/spectrum/proposals.d.ts +2 -1
  45. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/messages.ts"],
4
- "sourcesContent": ["import type {\n AssistantMessage,\n AssistantStatus,\n ErrorAction,\n LickMessage,\n Message,\n MessagePart,\n SystemMessage,\n ToolCall,\n ToolStatus,\n Usage,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { ConversationView, EntryRecord } from '@earendil-works/pi-durable';\nimport { splitUser } from '../attachments.ts';\nimport { GUEST_INPUT_KIND, type GuestInput, guestText } from '../guests/attribution.ts';\nimport { parseLick } from '../licks/lick.ts';\nimport { entryLick, LICK_TOOLS, type LickDecision, lickDecisions } from '../licks/state.ts';\nimport { mcpLabel } from '../mcp/label.ts';\nimport { FROM_KIND, type From } from '../scoops/from.ts';\nimport type { SecretName } from '../secrets/names.ts';\nimport { listedLine, SECRETS_KIND } from '../secrets/view.ts';\nimport type { Delivered } from '../services.ts';\nimport { SPRINKLE_KIND } from '../sprinkles/kind.ts';\n\ntype Json = Record<string, unknown>;\n\ninterface Block {\n type: string;\n text?: string;\n thinking?: string;\n id?: string;\n name?: string;\n arguments?: Json;\n}\n\ninterface ModelMessage {\n role: string;\n content?: string | Block[];\n timestamp?: number;\n stopReason?: string;\n errorMessage?: string;\n provider?: string;\n model?: string;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n cost?: { total?: number };\n };\n toolCallId?: string;\n isError?: boolean;\n details?: { patch?: unknown };\n}\n\ninterface Slot {\n callId: string;\n status: string;\n output?: string;\n}\n\ninterface Live {\n run?: unknown;\n generation?: { message?: ModelMessage; retry?: { at: number; error: string } };\n tools?: Slot[];\n compactions?: { taskId: number; reason: string }[];\n}\n\nexport function textOf(content: ModelMessage['content']): string {\n if (typeof content === 'string') return content;\n return (content ?? []).map((block) => (block.type === 'text' ? (block.text ?? '') : '')).join('');\n}\n\nconst paths = (args: Json | undefined): string[] =>\n typeof args?.path === 'string' ? [args.path] : [];\n\nfunction title(args: Json | undefined): string {\n const subject = args?.command ?? args?.path;\n return typeof subject === 'string' ? subject : '';\n}\n\ninterface Replacement {\n oldText?: string;\n newText?: string;\n}\n\nconst GAP = '\u2026';\n\nfunction seconds(value: unknown): string | undefined {\n return typeof value === 'number' ? `timeout ${value}s` : undefined;\n}\n\nfunction lines(args: Json): string | undefined {\n const { offset, limit } = args as { offset?: number; limit?: number };\n if (typeof offset === 'number' && typeof limit === 'number')\n return `lines ${offset}\u2013${offset + limit - 1}`;\n if (typeof offset === 'number') return `from line ${offset}`;\n return typeof limit === 'number' ? `first ${limit} lines` : undefined;\n}\n\nfunction edits(args: Json): ToolCall['diff'] {\n const list = Array.isArray(args.edits) ? (args.edits as Replacement[]) : [];\n if (list.length === 0) return undefined;\n return {\n before: list.map((edit) => edit.oldText ?? '').join(`\\n${GAP}\\n`),\n after: list.map((edit) => edit.newText ?? '').join(`\\n${GAP}\\n`),\n };\n}\n\nexport function fromPatch(patch: string): ToolCall['diff'] {\n const before: string[] = [];\n const after: string[] = [];\n let hunks = 0;\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) {\n if (hunks++ > 0) {\n before.push(GAP);\n after.push(GAP);\n }\n continue;\n }\n if (hunks === 0 || line === '' || line.startsWith('\\\\')) continue;\n const text = line.slice(1);\n if (line.startsWith('-')) before.push(text);\n else if (line.startsWith('+')) after.push(text);\n else {\n before.push(text);\n after.push(text);\n }\n }\n return hunks ? { before: before.join('\\n'), after: after.join('\\n') } : undefined;\n}\n\nfunction shape(name: string, args: Json): Pick<ToolCall, 'input' | 'meta' | 'diff'> {\n const path = typeof args.path === 'string' ? args.path : '';\n const meta = name === 'bash' ? seconds(args.timeout) : name === 'read' ? lines(args) : undefined;\n const base = meta ? { meta } : {};\n if (name === 'bash' && typeof args.command === 'string') return { input: args.command, ...base };\n if (name === 'read' || name === 'write') return { input: path, ...base };\n if (name === 'edit') {\n const diff = edits(args);\n return { input: path, ...(diff ? { diff } : {}) };\n }\n return { input: JSON.stringify(args, null, 2) };\n}\n\nfunction toolCall(block: Block): ToolCall {\n const args = block.arguments ?? {};\n return {\n id: block.id ?? '',\n name: block.name ?? 'tool',\n title: mcpLabel(block.name ?? '') ?? title(block.arguments),\n ...shape(block.name ?? 'tool', args),\n output: '',\n status: 'running',\n paths: paths(block.arguments),\n };\n}\n\nfunction part(block: Block): MessagePart | undefined {\n if (block.type === 'text') return { type: 'text', text: block.text ?? '' };\n if (block.type === 'thinking') return { type: 'thinking', text: block.thinking ?? '' };\n if (block.type === 'toolCall') return { type: 'tool', tool: toolCall(block) };\n return undefined;\n}\n\nfunction usage(message: ModelMessage): Usage | undefined {\n const used = message.usage;\n if (!used) return undefined;\n return {\n input: used.input ?? 0,\n output: used.output ?? 0,\n cost: used.cost?.total ?? 0,\n cacheRead: used.cacheRead ?? 0,\n cacheWrite: used.cacheWrite ?? 0,\n };\n}\n\nconst statuses: Record<string, AssistantStatus> = { error: 'error', aborted: 'stopped' };\n\nconst credentials =\n /security token|unrecognizedclient|not authori[sz]ed|unauthori[sz]ed|forbidden|\\b40[13]\\b|api key|credential|bearer/i;\nconst models = /model/i;\nconst unavailable =\n /access|invalid|not found|identifier|unsupported|not supported|isn['\u2019]t supported|not available|isn['\u2019]t available/i;\n\nconst providerNames: Record<string, string> = { 'amazon-bedrock': 'Bedrock', adobe: 'Adobe' };\nconst filtered =\n /Provider (?:stopped with|finish_reason): (?:content_filter(?:ed)?|guardrail_intervened|sensitive)|content[_ ]filter(?:ed|ing)?\\b|guardrail[_ ]intervened/i;\nconst refused =\n /refused to complete the request|Provider (?:stopped with|finish_reason): refusal|\\bstop_?reason\\W+refusal\\b/i;\nconst unconnected = /no api key|not configured|no credentials/i;\nconst missing = /missing/i;\nconst adobeAuth =\n /\\b401\\b|authenticat|unauthori[sz]ed|expired|invalid[_ ]?(?:token|credentials?|api[_ ]key)|token verification/i;\n\nfunction proxyRefusal(error: string): { message: string; detail: string } {\n try {\n const body = JSON.parse(error.match(/\\{.*\\}/s)?.[0] ?? '') as {\n error?: { type?: unknown; message?: unknown };\n };\n const { type, message } = body.error ?? {};\n const status = error.match(/^\\s*(\\d{3})\\b/)?.[1];\n return {\n message: typeof message === 'string' ? message : error,\n detail: typeof type === 'string' ? [status, type].filter(Boolean).join(' ') : error,\n };\n } catch {\n return { message: error, detail: error };\n }\n}\n\nexport const CONNECT_IT = 'Connect it in Settings \u203A Accounts.';\n\nexport function providerName(provider: string | undefined, fallback = 'The provider'): string {\n return providerNames[provider ?? ''] ?? fallback;\n}\n\nexport function errorPart(error: string, provider?: string): MessagePart {\n const action = errorAction(error);\n if (action === 'drop-turn') {\n return {\n type: 'error',\n message: filtered.test(error)\n ? \"The model's content filter stopped this reply.\"\n : 'The model refused to answer this turn.',\n detail: error,\n action,\n };\n }\n const name = providerName(provider);\n if (unconnected.test(error))\n return {\n type: 'error',\n message: `${name} isn't connected.`,\n detail: CONNECT_IT,\n action: 'settings',\n };\n if (action === 'settings' && provider === 'adobe') {\n return adobeAuth.test(error)\n ? {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n }\n : { type: 'error', ...proxyRefusal(error), action: 'retry' };\n }\n const lead =\n action === 'settings'\n ? missing.test(error)\n ? `${name} needs an API key.`\n : `${name} rejected the API key.`\n : action === 'change-model'\n ? \"This model isn't available with the current account.\"\n : null;\n return lead\n ? { type: 'error', message: lead, detail: error, action }\n : { type: 'error', message: error, action };\n}\n\nexport function errorAction(message: string): ErrorAction {\n if (filtered.test(message) || refused.test(message)) return 'drop-turn';\n if (credentials.test(message)) return 'settings';\n if (models.test(message) && unavailable.test(message)) return 'change-model';\n return 'retry';\n}\n\nfunction sprinkleMessage(id: string, entry: EntryRecord): AssistantMessage {\n const data = (entry.data ?? {}) as { sprinkle?: unknown; at?: unknown };\n return {\n id,\n role: 'assistant',\n parts: [{ type: 'sprinkle', sprinkle: String(data.sprinkle ?? '') }],\n status: 'done',\n createdAt: typeof data.at === 'number' ? data.at : 0,\n };\n}\n\nexport function assistant(\n id: string,\n message: ModelMessage,\n status?: AssistantStatus\n): AssistantMessage {\n const blocks = Array.isArray(message.content) ? message.content : [];\n const parts = blocks.map(part).filter((item): item is MessagePart => item !== undefined);\n if (message.errorMessage) parts.push(errorPart(message.errorMessage, message.provider));\n const used = usage(message);\n return {\n id,\n role: 'assistant',\n parts,\n status: status ?? statuses[message.stopReason ?? ''] ?? 'done',\n createdAt: message.timestamp ?? 0,\n ...(message.provider && message.model ? { model: `${message.provider}/${message.model}` } : {}),\n ...(used ? { usage: used } : {}),\n };\n}\n\nfunction user(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n from: From | undefined\n): UserMessage {\n return {\n id,\n role: 'user',\n ...shownUser(message.content, `ref:${id.slice(1)}:0`),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n ...(from ? { from: from.from } : {}),\n ...(from?.agent ? { origin: 'agent' as const } : {}),\n };\n}\n\nfunction guestUser(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n data: unknown\n): UserMessage {\n const name = String((data as Partial<GuestInput> | undefined)?.name ?? '');\n const shown = shownUser(message.content, `ref:${id.slice(1)}:0`);\n return {\n id,\n role: 'user',\n ...shown,\n text: guestText(shown.text, name),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n from: name,\n origin: 'guest',\n };\n}\n\nexport function origins(entries: readonly EntryRecord[]): Map<number, From> {\n const out = new Map<number, From>();\n for (const entry of entries)\n if (entry.kind === FROM_KIND) {\n const note = entry.data as From;\n out.set(note.entry, note);\n }\n return out;\n}\n\nfunction lickMessage(\n id: string,\n entry: EntryRecord,\n decisions: ReadonlyMap<string, LickDecision>\n): LickMessage | undefined {\n const lick = entryLick(entry);\n if (!lick) return undefined;\n const state = lick.actions?.length ? (decisions.get(lick.id) ?? 'pending') : undefined;\n return {\n id,\n role: 'lick',\n channel: lick.channel,\n title: lick.title,\n text: lick.text,\n createdAt: lick.at,\n ...(lick.body ? { body: lick.body } : {}),\n ...(lick.count > 1 ? { count: lick.count } : {}),\n ...(state ? { state } : {}),\n ...(lick.severity ? { severity: lick.severity } : {}),\n };\n}\n\nfunction withoutLickTools(message: AssistantMessage): AssistantMessage {\n const parts = message.parts.filter((item) => item.type !== 'tool' || !LICK_TOOLS[item.tool.name]);\n return parts.length === message.parts.length ? message : { ...message, parts };\n}\n\nfunction system(id: string, entry: EntryRecord, text: string): SystemMessage {\n const reason = (entry.data as Json | undefined)?.reason as SystemMessage['trigger'] | undefined;\n return {\n id,\n role: 'system',\n kind: 'compaction',\n text,\n createdAt: 0,\n state: 'summarized',\n ...(reason ? { trigger: reason } : {}),\n };\n}\n\nfunction tools(messages: Message[]): Map<string, ToolCall> {\n const found = new Map<string, ToolCall>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const item of message.parts) if (item.type === 'tool') found.set(item.tool.id, item.tool);\n }\n return found;\n}\n\ninterface Diagnostic {\n severity: string;\n message: string;\n}\n\ninterface Note {\n severity: 'error' | 'warn' | 'info';\n text: string;\n}\n\ntype Card = ToolCall & { notes?: Note[] };\n\nconst RANK: Note['severity'][] = ['error', 'warn', 'info'];\n\nconst LINE = /^\\[(error|warn|info)\\] (.*)$/;\n\nfunction rendered(diagnostics: readonly Diagnostic[]): string {\n return `<harness>\\n${diagnostics.map((item) => `[${item.severity}] ${item.message}`).join('\\n')}\\n</harness>`;\n}\n\nfunction parsed(text: string): Diagnostic[] | undefined {\n const body = /^<harness>\\n([\\s\\S]*)\\n<\\/harness>$/.exec(text)?.[1];\n if (body === undefined) return undefined;\n const found = body.split('\\n').map((line) => LINE.exec(line));\n if (!found.every((match): match is RegExpExecArray => match !== null)) return undefined;\n return found.map(([, severity, message]) => ({ severity, message }) as Diagnostic);\n}\n\nfunction harness(\n content: ModelMessage['content'],\n data: unknown\n): { content: ModelMessage['content']; diagnostics: Diagnostic[] } {\n const last = Array.isArray(content) ? content.at(-1) : undefined;\n const stored = (data as { diagnostics?: unknown } | undefined)?.diagnostics;\n const listed = Array.isArray(stored) ? (stored as Diagnostic[]) : parsed(last?.text ?? '');\n if (!listed?.length || last?.type !== 'text' || last.text !== rendered(listed))\n return { content, diagnostics: [] };\n return { content: (content as Block[]).slice(0, -1), diagnostics: listed };\n}\n\nconst count = (value: string | undefined): string => Number(value).toLocaleString('en');\n\nconst ends: Record<string, string> = { end: ' from the start', beginning: ' from the end' };\n\nconst phrasings: [RegExp, (match: RegExpExecArray) => string][] = [\n [/^Command exited with code (-?\\d+)$/, (match) => `Exited with code ${match[1]}`],\n [/^Command timed out after (.+)$/, (match) => `Timed out after ${match[1]}`],\n [/^Command aborted$/, () => 'Aborted'],\n [/^Full output: (.+)$/, (match) => `Full output in ${match[1]}`],\n [\n /^Output truncated(?: to its (beginning|end))?: (\\d+) lines, (\\d+) bytes dropped$/,\n (match) =>\n `Output truncated: ${count(match[2])} lines and ${count(match[3])} bytes dropped${ends[match[1] ?? ''] ?? ''}`,\n ],\n];\n\nfunction phrased(message: string): string {\n const line = message\n .replace(/\\n[\\s\\S]*$/, '')\n .trim()\n .replace(/\\.$/, '');\n for (const [pattern, phrase] of phrasings) {\n const match = pattern.exec(line);\n if (match) return phrase(match);\n }\n return line;\n}\n\nfunction note(diagnostic: Diagnostic): Note {\n return { severity: diagnostic.severity as Note['severity'], text: phrased(diagnostic.message) };\n}\n\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage, data?: unknown): void {\n const call = calls.get(result.toolCallId ?? '') as Card | undefined;\n if (!call) return;\n const split = harness(result.content, data);\n call.output = textOf(split.content);\n if (split.diagnostics.length)\n call.notes = split.diagnostics\n .map(note)\n .sort((a, b) => RANK.indexOf(a.severity) - RANK.indexOf(b.severity));\n call.status = result.isError ? 'error' : 'done';\n const image = Array.isArray(result.content)\n ? (result.content as { type: string; data?: string; mimeType?: string }[]).find(\n (part) => part.type === 'image' && part.data && part.mimeType\n )\n : undefined;\n if (image) call.image = `data:${image.mimeType};base64,${image.data}`;\n const patch = result.details?.patch;\n const diff = typeof patch === 'string' ? fromPatch(patch) : undefined;\n if (diff) call.diff = diff;\n else if (result.isError) delete call.diff;\n}\n\nfunction rewound(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { stopped?: string[]; restored?: string[]; files?: boolean };\n const notes = [\n 'Its prompt is back in the composer.',\n ...(data.stopped?.length\n ? [`Stopped ${data.stopped.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.restored?.length\n ? [`Restored ${data.restored.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.files ? ['Changed files stay; use Changes or git to revert them.'] : []),\n ];\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Rewound 1 turn',\n text: notes.join(' '),\n createdAt: 0,\n };\n}\n\nfunction thawed(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { name?: string; kind?: string };\n const what = data.kind === 'agent' ? 'agent run' : 'scoop';\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: `Thawed from ${what} ${data.name ?? ''}`.trim(),\n text: textOf(entry.model?.[0]?.content ?? ''),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nfunction secrets(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { names?: SecretName[] };\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Secrets listed',\n text: listedLine(data.names ?? []),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nfunction entryMessage(\n entry: EntryRecord,\n out: Message[],\n calls: Map<string, ToolCall>,\n delivered: Delivered | undefined,\n notes: { decisions: ReadonlyMap<string, LickDecision>; origins: ReadonlyMap<number, From> }\n): void {\n const id = `e${entry.id}`;\n const model = entry.model?.[0] as ModelMessage | undefined;\n if (entry.kind === 'slicc.rewound') out.push(rewound(id, entry));\n if (entry.kind === 'slicc.thawed') out.push(thawed(id, entry));\n else if (entry.kind === SECRETS_KIND) out.push(secrets(id, entry));\n else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));\n else if (entry.kind === 'pi.user' && model)\n out.push(\n lickMessage(id, entry, notes.decisions) ??\n user(id, model, delivered, notes.origins.get(entry.id))\n );\n else if (entry.kind === GUEST_INPUT_KIND && model)\n out.push(guestUser(id, model, delivered, entry.data));\n else if (entry.kind === 'pi.assistant' && model) {\n const message = assistant(id, model);\n out.push(withoutLickTools(message));\n for (const [key, value] of tools([message])) calls.set(key, value);\n } else if (entry.kind === 'pi.tool-result' && model) settle(calls, model, entry.data);\n else if (entry.kind === 'pi.compaction') out.push(system(id, entry, textOf(model?.content)));\n}\n\nconst slotStatus: Record<string, ToolStatus> = {\n pending: 'running',\n running: 'running',\n done: 'done',\n};\n\nfunction live(view: ConversationView, out: Message[], calls: Map<string, ToolCall>): void {\n const state = view.docs['pi.live'] as Live | undefined;\n for (const slot of state?.tools ?? []) {\n const call = calls.get(slot.callId);\n if (call && call.status === 'running') {\n call.status = slotStatus[slot.status] ?? 'running';\n call.output = slot.output ?? call.output;\n }\n }\n const partial = state?.generation?.message;\n if (partial) out.push(assistant('live', partial, 'streaming'));\n for (const compaction of state?.compactions ?? []) {\n out.push({\n id: `compaction-${compaction.taskId}`,\n role: 'system',\n kind: 'compaction',\n text: '',\n createdAt: 0,\n state: 'summarizing',\n trigger: compaction.reason as SystemMessage['trigger'],\n });\n }\n const retry = state?.generation?.retry;\n if (retry)\n out.push({\n id: 'retry',\n role: 'system',\n kind: 'notice',\n text: retry.error,\n createdAt: retry.at,\n });\n}\n\nexport function toMessages(\n view: ConversationView | undefined,\n deliveries: Readonly<Record<string, Delivered>> = {}\n): Message[] {\n const out: Message[] = [];\n if (!view) return out;\n const calls = new Map<string, ToolCall>();\n const notes = { decisions: lickDecisions(view.entries), origins: origins(view.entries) };\n let previous: EntryRecord | undefined;\n for (const entry of view.entries) {\n const steered = previous?.kind === 'pi.tool-result' ? 'steer' : undefined;\n entryMessage(entry, out, calls, deliveries[String(entry.id)] ?? steered, notes);\n previous = entry;\n }\n live(view, out, calls);\n return out;\n}\n\nfunction shownUser(\n content: ModelMessage['content'],\n prefix?: string\n): Pick<UserMessage, 'text' | 'attachments'> {\n const { text, attachments } = splitUser(content, prefix);\n return attachments.length ? { text, attachments } : { text };\n}\n\nexport function isBusy(view: ConversationView | undefined): boolean {\n return Boolean((view?.docs['pi.live'] as Live | undefined)?.run);\n}\n\nexport function queued(\n view: ConversationView | undefined,\n at: (id: string) => number = () => 0\n): UserMessage[] {\n const items = ((view?.docs['pi.inbox'] as { items?: Json[] } | undefined)?.items ?? []) as {\n id: number;\n mode: string;\n content?: ModelMessage['content'];\n entry?: { kind?: string; data?: Partial<GuestInput> };\n }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => {\n const shown = shownUser(item.content);\n const guest =\n item.entry?.kind === GUEST_INPUT_KIND ? String(item.entry.data?.name ?? '') : null;\n return {\n id: `q${item.id}`,\n role: 'user' as const,\n ...shown,\n ...(guest === null\n ? {}\n : { text: guestText(shown.text, guest), from: guest, origin: 'guest' as const }),\n createdAt: at(`q${item.id}`),\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\n };\n });\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n AssistantMessage,\n AssistantStatus,\n ErrorAction,\n LickMessage,\n Message,\n MessagePart,\n SystemMessage,\n ToolCall,\n ToolStatus,\n Usage,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { ConversationView, EntryRecord } from '@earendil-works/pi-durable';\nimport { splitUser } from '../attachments.ts';\nimport {\n ASKED_KIND,\n askedLine,\n GUEST_INPUT_KIND,\n type GuestAsked,\n type GuestInput,\n type GuestOutcome,\n type GuestReviewed,\n guestText,\n REVIEWED_KIND,\n} from '../guests/attribution.ts';\nimport { parseLick } from '../licks/lick.ts';\nimport { entryLick, LICK_TOOLS, type LickDecision, lickDecisions } from '../licks/state.ts';\nimport { mcpLabel } from '../mcp/label.ts';\nimport { FROM_KIND, type From } from '../scoops/from.ts';\nimport type { SecretName } from '../secrets/names.ts';\nimport { listedLine, SECRETS_KIND } from '../secrets/view.ts';\nimport type { Delivered } from '../services.ts';\nimport { SPRINKLE_KIND } from '../sprinkles/kind.ts';\n\ntype Json = Record<string, unknown>;\n\ninterface Block {\n type: string;\n text?: string;\n thinking?: string;\n id?: string;\n name?: string;\n arguments?: Json;\n}\n\ninterface ModelMessage {\n role: string;\n content?: string | Block[];\n timestamp?: number;\n stopReason?: string;\n errorMessage?: string;\n provider?: string;\n model?: string;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n cost?: { total?: number };\n };\n toolCallId?: string;\n isError?: boolean;\n details?: { patch?: unknown };\n}\n\ninterface Slot {\n callId: string;\n status: string;\n output?: string;\n}\n\ninterface Live {\n run?: unknown;\n generation?: { message?: ModelMessage; retry?: { at: number; error: string } };\n tools?: Slot[];\n compactions?: { taskId: number; reason: string }[];\n}\n\nexport function textOf(content: ModelMessage['content']): string {\n if (typeof content === 'string') return content;\n return (content ?? []).map((block) => (block.type === 'text' ? (block.text ?? '') : '')).join('');\n}\n\nconst paths = (args: Json | undefined): string[] =>\n typeof args?.path === 'string' ? [args.path] : [];\n\nfunction title(args: Json | undefined): string {\n const subject = args?.command ?? args?.path;\n return typeof subject === 'string' ? subject : '';\n}\n\ninterface Replacement {\n oldText?: string;\n newText?: string;\n}\n\nconst GAP = '\u2026';\n\nfunction seconds(value: unknown): string | undefined {\n return typeof value === 'number' ? `timeout ${value}s` : undefined;\n}\n\nfunction lines(args: Json): string | undefined {\n const { offset, limit } = args as { offset?: number; limit?: number };\n if (typeof offset === 'number' && typeof limit === 'number')\n return `lines ${offset}\u2013${offset + limit - 1}`;\n if (typeof offset === 'number') return `from line ${offset}`;\n return typeof limit === 'number' ? `first ${limit} lines` : undefined;\n}\n\nfunction edits(args: Json): ToolCall['diff'] {\n const list = Array.isArray(args.edits) ? (args.edits as Replacement[]) : [];\n if (list.length === 0) return undefined;\n return {\n before: list.map((edit) => edit.oldText ?? '').join(`\\n${GAP}\\n`),\n after: list.map((edit) => edit.newText ?? '').join(`\\n${GAP}\\n`),\n };\n}\n\nexport function fromPatch(patch: string): ToolCall['diff'] {\n const before: string[] = [];\n const after: string[] = [];\n let hunks = 0;\n for (const line of patch.split('\\n')) {\n if (line.startsWith('@@')) {\n if (hunks++ > 0) {\n before.push(GAP);\n after.push(GAP);\n }\n continue;\n }\n if (hunks === 0 || line === '' || line.startsWith('\\\\')) continue;\n const text = line.slice(1);\n if (line.startsWith('-')) before.push(text);\n else if (line.startsWith('+')) after.push(text);\n else {\n before.push(text);\n after.push(text);\n }\n }\n return hunks ? { before: before.join('\\n'), after: after.join('\\n') } : undefined;\n}\n\nfunction shape(name: string, args: Json): Pick<ToolCall, 'input' | 'meta' | 'diff'> {\n const path = typeof args.path === 'string' ? args.path : '';\n const meta = name === 'bash' ? seconds(args.timeout) : name === 'read' ? lines(args) : undefined;\n const base = meta ? { meta } : {};\n if (name === 'bash' && typeof args.command === 'string') return { input: args.command, ...base };\n if (name === 'read' || name === 'write') return { input: path, ...base };\n if (name === 'edit') {\n const diff = edits(args);\n return { input: path, ...(diff ? { diff } : {}) };\n }\n return { input: JSON.stringify(args, null, 2) };\n}\n\nfunction toolCall(block: Block): ToolCall {\n const args = block.arguments ?? {};\n return {\n id: block.id ?? '',\n name: block.name ?? 'tool',\n title: mcpLabel(block.name ?? '') ?? title(block.arguments),\n ...shape(block.name ?? 'tool', args),\n output: '',\n status: 'running',\n paths: paths(block.arguments),\n };\n}\n\nfunction part(block: Block): MessagePart | undefined {\n if (block.type === 'text') return { type: 'text', text: block.text ?? '' };\n if (block.type === 'thinking') return { type: 'thinking', text: block.thinking ?? '' };\n if (block.type === 'toolCall') return { type: 'tool', tool: toolCall(block) };\n return undefined;\n}\n\nfunction usage(message: ModelMessage): Usage | undefined {\n const used = message.usage;\n if (!used) return undefined;\n return {\n input: used.input ?? 0,\n output: used.output ?? 0,\n cost: used.cost?.total ?? 0,\n cacheRead: used.cacheRead ?? 0,\n cacheWrite: used.cacheWrite ?? 0,\n };\n}\n\nconst statuses: Record<string, AssistantStatus> = { error: 'error', aborted: 'stopped' };\n\nconst credentials =\n /security token|unrecognizedclient|not authori[sz]ed|unauthori[sz]ed|forbidden|\\b40[13]\\b|api key|credential|bearer/i;\nconst models = /model/i;\nconst unavailable =\n /access|invalid|not found|identifier|unsupported|not supported|isn['\u2019]t supported|not available|isn['\u2019]t available/i;\n\nconst providerNames: Record<string, string> = { 'amazon-bedrock': 'Bedrock', adobe: 'Adobe' };\nconst filtered =\n /Provider (?:stopped with|finish_reason): (?:content_filter(?:ed)?|guardrail_intervened|sensitive)|content[_ ]filter(?:ed|ing)?\\b|guardrail[_ ]intervened/i;\nconst refused =\n /refused to complete the request|Provider (?:stopped with|finish_reason): refusal|\\bstop_?reason\\W+refusal\\b/i;\nconst unconnected = /no api key|not configured|no credentials/i;\nconst missing = /missing/i;\nconst adobeAuth =\n /\\b401\\b|authenticat|unauthori[sz]ed|expired|invalid[_ ]?(?:token|credentials?|api[_ ]key)|token verification/i;\n\nfunction proxyRefusal(error: string): { message: string; detail: string } {\n try {\n const body = JSON.parse(error.match(/\\{.*\\}/s)?.[0] ?? '') as {\n error?: { type?: unknown; message?: unknown };\n };\n const { type, message } = body.error ?? {};\n const status = error.match(/^\\s*(\\d{3})\\b/)?.[1];\n return {\n message: typeof message === 'string' ? message : error,\n detail: typeof type === 'string' ? [status, type].filter(Boolean).join(' ') : error,\n };\n } catch {\n return { message: error, detail: error };\n }\n}\n\nexport const CONNECT_IT = 'Connect it in Settings \u203A Accounts.';\n\nexport function providerName(provider: string | undefined, fallback = 'The provider'): string {\n return providerNames[provider ?? ''] ?? fallback;\n}\n\nexport function errorPart(error: string, provider?: string): MessagePart {\n const action = errorAction(error);\n if (action === 'drop-turn') {\n return {\n type: 'error',\n message: filtered.test(error)\n ? \"The model's content filter stopped this reply.\"\n : 'The model refused to answer this turn.',\n detail: error,\n action,\n };\n }\n const name = providerName(provider);\n if (unconnected.test(error))\n return {\n type: 'error',\n message: `${name} isn't connected.`,\n detail: CONNECT_IT,\n action: 'settings',\n };\n if (action === 'settings' && provider === 'adobe') {\n return adobeAuth.test(error)\n ? {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n }\n : { type: 'error', ...proxyRefusal(error), action: 'retry' };\n }\n const lead =\n action === 'settings'\n ? missing.test(error)\n ? `${name} needs an API key.`\n : `${name} rejected the API key.`\n : action === 'change-model'\n ? \"This model isn't available with the current account.\"\n : null;\n return lead\n ? { type: 'error', message: lead, detail: error, action }\n : { type: 'error', message: error, action };\n}\n\nexport function errorAction(message: string): ErrorAction {\n if (filtered.test(message) || refused.test(message)) return 'drop-turn';\n if (credentials.test(message)) return 'settings';\n if (models.test(message) && unavailable.test(message)) return 'change-model';\n return 'retry';\n}\n\nfunction sprinkleMessage(id: string, entry: EntryRecord): AssistantMessage {\n const data = (entry.data ?? {}) as { sprinkle?: unknown; at?: unknown };\n return {\n id,\n role: 'assistant',\n parts: [{ type: 'sprinkle', sprinkle: String(data.sprinkle ?? '') }],\n status: 'done',\n createdAt: typeof data.at === 'number' ? data.at : 0,\n };\n}\n\nexport function assistant(\n id: string,\n message: ModelMessage,\n status?: AssistantStatus\n): AssistantMessage {\n const blocks = Array.isArray(message.content) ? message.content : [];\n const parts = blocks.map(part).filter((item): item is MessagePart => item !== undefined);\n if (message.errorMessage) parts.push(errorPart(message.errorMessage, message.provider));\n const used = usage(message);\n return {\n id,\n role: 'assistant',\n parts,\n status: status ?? statuses[message.stopReason ?? ''] ?? 'done',\n createdAt: message.timestamp ?? 0,\n ...(message.provider && message.model ? { model: `${message.provider}/${message.model}` } : {}),\n ...(used ? { usage: used } : {}),\n };\n}\n\nfunction user(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n from: From | undefined\n): UserMessage {\n return {\n id,\n role: 'user',\n ...shownUser(message.content, `ref:${id.slice(1)}:0`),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n ...(from ? { from: from.from } : {}),\n ...(from?.agent ? { origin: 'agent' as const } : {}),\n };\n}\n\nfunction guestUser(\n id: string,\n message: ModelMessage,\n delivered: Delivered | undefined,\n data: unknown\n): UserMessage {\n const input = data as Partial<GuestInput> | undefined;\n const name = String(input?.name ?? '');\n const shown = shownUser(message.content, `ref:${id.slice(1)}:0`);\n return {\n id,\n role: 'user',\n ...shown,\n text: guestText(shown.text, name),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n from: name,\n origin: 'guest',\n ...(typeof input?.seat === 'string' ? { seat: input.seat } : {}),\n };\n}\n\nexport function origins(entries: readonly EntryRecord[]): Map<number, From> {\n const out = new Map<number, From>();\n for (const entry of entries)\n if (entry.kind === FROM_KIND) {\n const note = entry.data as From;\n out.set(note.entry, note);\n }\n return out;\n}\n\nfunction lickMessage(\n id: string,\n entry: EntryRecord,\n decisions: ReadonlyMap<string, LickDecision>\n): LickMessage | undefined {\n const lick = entryLick(entry);\n if (!lick) return undefined;\n const state = lick.actions?.length ? (decisions.get(lick.id) ?? 'pending') : undefined;\n return {\n id,\n role: 'lick',\n channel: lick.channel,\n title: lick.title,\n text: lick.text,\n createdAt: lick.at,\n ...(lick.body ? { body: lick.body } : {}),\n ...(lick.count > 1 ? { count: lick.count } : {}),\n ...(state ? { state } : {}),\n ...(lick.severity ? { severity: lick.severity } : {}),\n };\n}\n\nfunction withoutLickTools(message: AssistantMessage): AssistantMessage {\n const parts = message.parts.filter((item) => item.type !== 'tool' || !LICK_TOOLS[item.tool.name]);\n return parts.length === message.parts.length ? message : { ...message, parts };\n}\n\nfunction system(id: string, entry: EntryRecord, text: string): SystemMessage {\n const reason = (entry.data as Json | undefined)?.reason as SystemMessage['trigger'] | undefined;\n return {\n id,\n role: 'system',\n kind: 'compaction',\n text,\n createdAt: 0,\n state: 'summarized',\n ...(reason ? { trigger: reason } : {}),\n };\n}\n\nfunction tools(messages: Message[]): Map<string, ToolCall> {\n const found = new Map<string, ToolCall>();\n for (const message of messages) {\n if (message.role !== 'assistant') continue;\n for (const item of message.parts) if (item.type === 'tool') found.set(item.tool.id, item.tool);\n }\n return found;\n}\n\ninterface Diagnostic {\n severity: string;\n message: string;\n}\n\ninterface Note {\n severity: 'error' | 'warn' | 'info';\n text: string;\n}\n\ntype Card = ToolCall & { notes?: Note[] };\n\nconst RANK: Note['severity'][] = ['error', 'warn', 'info'];\n\nconst LINE = /^\\[(error|warn|info)\\] (.*)$/;\n\nfunction rendered(diagnostics: readonly Diagnostic[]): string {\n return `<harness>\\n${diagnostics.map((item) => `[${item.severity}] ${item.message}`).join('\\n')}\\n</harness>`;\n}\n\nfunction parsed(text: string): Diagnostic[] | undefined {\n const body = /^<harness>\\n([\\s\\S]*)\\n<\\/harness>$/.exec(text)?.[1];\n if (body === undefined) return undefined;\n const found = body.split('\\n').map((line) => LINE.exec(line));\n if (!found.every((match): match is RegExpExecArray => match !== null)) return undefined;\n return found.map(([, severity, message]) => ({ severity, message }) as Diagnostic);\n}\n\nfunction harness(\n content: ModelMessage['content'],\n data: unknown\n): { content: ModelMessage['content']; diagnostics: Diagnostic[] } {\n const last = Array.isArray(content) ? content.at(-1) : undefined;\n const stored = (data as { diagnostics?: unknown } | undefined)?.diagnostics;\n const listed = Array.isArray(stored) ? (stored as Diagnostic[]) : parsed(last?.text ?? '');\n if (!listed?.length || last?.type !== 'text' || last.text !== rendered(listed))\n return { content, diagnostics: [] };\n return { content: (content as Block[]).slice(0, -1), diagnostics: listed };\n}\n\nconst count = (value: string | undefined): string => Number(value).toLocaleString('en');\n\nconst ends: Record<string, string> = { end: ' from the start', beginning: ' from the end' };\n\nconst phrasings: [RegExp, (match: RegExpExecArray) => string][] = [\n [/^Command exited with code (-?\\d+)$/, (match) => `Exited with code ${match[1]}`],\n [/^Command timed out after (.+)$/, (match) => `Timed out after ${match[1]}`],\n [/^Command aborted$/, () => 'Aborted'],\n [/^Full output: (.+)$/, (match) => `Full output in ${match[1]}`],\n [\n /^Output truncated(?: to its (beginning|end))?: (\\d+) lines, (\\d+) bytes dropped$/,\n (match) =>\n `Output truncated: ${count(match[2])} lines and ${count(match[3])} bytes dropped${ends[match[1] ?? ''] ?? ''}`,\n ],\n];\n\nfunction phrased(message: string): string {\n const line = message\n .replace(/\\n[\\s\\S]*$/, '')\n .trim()\n .replace(/\\.$/, '');\n for (const [pattern, phrase] of phrasings) {\n const match = pattern.exec(line);\n if (match) return phrase(match);\n }\n return line;\n}\n\nfunction note(diagnostic: Diagnostic): Note {\n return { severity: diagnostic.severity as Note['severity'], text: phrased(diagnostic.message) };\n}\n\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage, data?: unknown): void {\n const call = calls.get(result.toolCallId ?? '') as Card | undefined;\n if (!call) return;\n const split = harness(result.content, data);\n call.output = textOf(split.content);\n if (split.diagnostics.length)\n call.notes = split.diagnostics\n .map(note)\n .sort((a, b) => RANK.indexOf(a.severity) - RANK.indexOf(b.severity));\n call.status = result.isError ? 'error' : 'done';\n const image = Array.isArray(result.content)\n ? (result.content as { type: string; data?: string; mimeType?: string }[]).find(\n (part) => part.type === 'image' && part.data && part.mimeType\n )\n : undefined;\n if (image) call.image = `data:${image.mimeType};base64,${image.data}`;\n const patch = result.details?.patch;\n const diff = typeof patch === 'string' ? fromPatch(patch) : undefined;\n if (diff) call.diff = diff;\n else if (result.isError) delete call.diff;\n}\n\nfunction rewound(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { stopped?: string[]; restored?: string[]; files?: boolean };\n const notes = [\n 'Its prompt is back in the composer.',\n ...(data.stopped?.length\n ? [`Stopped ${data.stopped.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.restored?.length\n ? [`Restored ${data.restored.map((name) => `scoop ${name}`).join(', ')}.`]\n : []),\n ...(data.files ? ['Changed files stay; use Changes or git to revert them.'] : []),\n ];\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Rewound 1 turn',\n text: notes.join(' '),\n createdAt: 0,\n };\n}\n\nfunction thawed(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { name?: string; kind?: string };\n const what = data.kind === 'agent' ? 'agent run' : 'scoop';\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: `Thawed from ${what} ${data.name ?? ''}`.trim(),\n text: textOf(entry.model?.[0]?.content ?? ''),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nexport function reviewed(entries: readonly EntryRecord[]): Map<string, GuestOutcome> {\n const out = new Map<string, GuestOutcome>();\n for (const entry of entries) {\n if (entry.kind !== REVIEWED_KIND) continue;\n const data = (entry.data ?? {}) as Partial<GuestReviewed>;\n if (typeof data.review === 'string' && data.outcome) out.set(data.review, data.outcome);\n }\n return out;\n}\n\nfunction asked(\n id: string,\n entry: EntryRecord,\n outcomes: ReadonlyMap<string, GuestOutcome>\n): SystemMessage {\n const data = (entry.data ?? {}) as Partial<GuestAsked>;\n return {\n id,\n role: 'system',\n kind: 'notice',\n text: askedLine(\n String(data.name ?? ''),\n String(data.text ?? ''),\n outcomes.get(String(data.review))\n ),\n createdAt: typeof data.at === 'number' ? data.at : 0,\n };\n}\n\nfunction secrets(id: string, entry: EntryRecord): SystemMessage {\n const data = (entry.data ?? {}) as { names?: SecretName[] };\n return {\n id,\n role: 'system',\n kind: 'notice',\n title: 'Secrets listed',\n text: listedLine(data.names ?? []),\n createdAt: entry.model?.[0]?.timestamp ?? 0,\n };\n}\n\nfunction entryMessage(\n entry: EntryRecord,\n out: Message[],\n calls: Map<string, ToolCall>,\n delivered: Delivered | undefined,\n notes: {\n decisions: ReadonlyMap<string, LickDecision>;\n origins: ReadonlyMap<number, From>;\n outcomes: ReadonlyMap<string, GuestOutcome>;\n }\n): void {\n const id = `e${entry.id}`;\n const model = entry.model?.[0] as ModelMessage | undefined;\n if (entry.kind === 'slicc.rewound') out.push(rewound(id, entry));\n if (entry.kind === 'slicc.thawed') out.push(thawed(id, entry));\n else if (entry.kind === SECRETS_KIND) out.push(secrets(id, entry));\n else if (entry.kind === ASKED_KIND) out.push(asked(id, entry, notes.outcomes));\n else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));\n else if (entry.kind === 'pi.user' && model)\n out.push(\n lickMessage(id, entry, notes.decisions) ??\n user(id, model, delivered, notes.origins.get(entry.id))\n );\n else if (entry.kind === GUEST_INPUT_KIND && model)\n out.push(guestUser(id, model, delivered, entry.data));\n else if (entry.kind === 'pi.assistant' && model) {\n const message = assistant(id, model);\n out.push(withoutLickTools(message));\n for (const [key, value] of tools([message])) calls.set(key, value);\n } else if (entry.kind === 'pi.tool-result' && model) settle(calls, model, entry.data);\n else if (entry.kind === 'pi.compaction') out.push(system(id, entry, textOf(model?.content)));\n}\n\nconst slotStatus: Record<string, ToolStatus> = {\n pending: 'running',\n running: 'running',\n done: 'done',\n};\n\nfunction live(view: ConversationView, out: Message[], calls: Map<string, ToolCall>): void {\n const state = view.docs['pi.live'] as Live | undefined;\n for (const slot of state?.tools ?? []) {\n const call = calls.get(slot.callId);\n if (call && call.status === 'running') {\n call.status = slotStatus[slot.status] ?? 'running';\n call.output = slot.output ?? call.output;\n }\n }\n const partial = state?.generation?.message;\n if (partial) out.push(assistant('live', partial, 'streaming'));\n for (const compaction of state?.compactions ?? []) {\n out.push({\n id: `compaction-${compaction.taskId}`,\n role: 'system',\n kind: 'compaction',\n text: '',\n createdAt: 0,\n state: 'summarizing',\n trigger: compaction.reason as SystemMessage['trigger'],\n });\n }\n const retry = state?.generation?.retry;\n if (retry)\n out.push({\n id: 'retry',\n role: 'system',\n kind: 'notice',\n text: retry.error,\n createdAt: retry.at,\n });\n}\n\nexport function toMessages(\n view: ConversationView | undefined,\n deliveries: Readonly<Record<string, Delivered>> = {}\n): Message[] {\n const out: Message[] = [];\n if (!view) return out;\n const calls = new Map<string, ToolCall>();\n const notes = {\n decisions: lickDecisions(view.entries),\n origins: origins(view.entries),\n outcomes: reviewed(view.entries),\n };\n let previous: EntryRecord | undefined;\n for (const entry of view.entries) {\n const steered = previous?.kind === 'pi.tool-result' ? 'steer' : undefined;\n entryMessage(entry, out, calls, deliveries[String(entry.id)] ?? steered, notes);\n previous = entry;\n }\n live(view, out, calls);\n return out;\n}\n\nfunction shownUser(\n content: ModelMessage['content'],\n prefix?: string\n): Pick<UserMessage, 'text' | 'attachments'> {\n const { text, attachments } = splitUser(content, prefix);\n return attachments.length ? { text, attachments } : { text };\n}\n\nexport function isBusy(view: ConversationView | undefined): boolean {\n return Boolean((view?.docs['pi.live'] as Live | undefined)?.run);\n}\n\nexport function queued(\n view: ConversationView | undefined,\n at: (id: string) => number = () => 0\n): UserMessage[] {\n const items = ((view?.docs['pi.inbox'] as { items?: Json[] } | undefined)?.items ?? []) as {\n id: number;\n mode: string;\n content?: ModelMessage['content'];\n entry?: { kind?: string; data?: Partial<GuestInput> };\n }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => {\n const shown = shownUser(item.content);\n const data = item.entry?.data;\n const guest = item.entry?.kind === GUEST_INPUT_KIND ? String(data?.name ?? '') : null;\n const seat = typeof data?.seat === 'string' ? { seat: data.seat } : {};\n return {\n id: `q${item.id}`,\n role: 'user' as const,\n ...shown,\n ...(guest === null\n ? {}\n : {\n text: guestText(shown.text, guest),\n from: guest,\n origin: 'guest' as const,\n ...seat,\n }),\n createdAt: at(`q${item.id}`),\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\n };\n });\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["note", "part"]
7
7
  }
@@ -1,13 +1,15 @@
1
+ const APPROVED = "It was approved.";
1
2
  const UNANSWERED = "Nobody approved this in time.";
2
3
  const DECLINED = "It was declined.";
3
4
  const WITHDRAWN = "It was withdrawn.";
4
5
  const ENDED = {
6
+ approved: APPROVED,
5
7
  unanswered: UNANSWERED,
6
8
  rejected: DECLINED,
7
9
  withdrawn: WITHDRAWN
8
10
  };
9
- function proposalQueue(proposals, label) {
10
- return (proposals ?? []).filter((proposal) => proposal.state === "pending").map((proposal) => ({
11
+ function proposalQueue(proposals, label, seat) {
12
+ return (proposals ?? []).filter((proposal) => proposal.state === "pending" || proposal.state === "queued").map((proposal) => ({
11
13
  id: `g${proposal.id}`,
12
14
  role: "user",
13
15
  text: proposal.text,
@@ -15,7 +17,8 @@ function proposalQueue(proposals, label) {
15
17
  queued: true,
16
18
  mode: "queue",
17
19
  from: label,
18
- origin: "guest"
20
+ origin: "guest",
21
+ seat
19
22
  }));
20
23
  }
21
24
  function proposalNotices(proposals) {
@@ -46,6 +49,7 @@ function merged(messages, notices) {
46
49
  return [...out, ...left];
47
50
  }
48
51
  export {
52
+ APPROVED,
49
53
  DECLINED,
50
54
  UNANSWERED,
51
55
  WITHDRAWN,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/proposals.ts"],
4
- "sourcesContent": ["import type { Message, SystemMessage, UserMessage } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { GuestProposal } from '../services.ts';\n\nexport const UNANSWERED = 'Nobody approved this in time.';\nexport const DECLINED = 'It was declined.';\nexport const WITHDRAWN = 'It was withdrawn.';\n\nconst ENDED: Record<string, string> = {\n unanswered: UNANSWERED,\n rejected: DECLINED,\n withdrawn: WITHDRAWN,\n};\n\nexport function proposalQueue(\n proposals: readonly GuestProposal[] | undefined,\n label: string\n): UserMessage[] {\n return (proposals ?? [])\n .filter((proposal) => proposal.state === 'pending')\n .map((proposal) => ({\n id: `g${proposal.id}`,\n role: 'user',\n text: proposal.text,\n createdAt: proposal.createdAt,\n queued: true,\n mode: 'queue',\n from: label,\n origin: 'guest',\n }));\n}\n\nexport function proposalNotices(proposals: readonly GuestProposal[] | undefined): SystemMessage[] {\n return (proposals ?? []).flatMap((proposal) => {\n const title = ENDED[proposal.state];\n if (!title) return [];\n return [\n {\n id: `g${proposal.id}`,\n role: 'system',\n kind: 'notice',\n title,\n text: proposal.text,\n createdAt: proposal.decidedAt ?? proposal.createdAt,\n },\n ];\n });\n}\n\nexport function merged(messages: readonly Message[], notices: readonly SystemMessage[]): Message[] {\n if (!notices.length) return [...messages];\n const out: Message[] = [];\n const left = [...notices].sort((a, b) => a.createdAt - b.createdAt);\n for (const message of messages) {\n while (left.length && (left[0] as SystemMessage).createdAt < message.createdAt)\n out.push(left.shift() as SystemMessage);\n out.push(message);\n }\n return [...out, ...left];\n}\n"],
5
- "mappings": "AAGO,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,YAAY;AAEzB,MAAM,QAAgC;AAAA,EACpC,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AACb;AAEO,SAAS,cACd,WACA,OACe;AACf,UAAQ,aAAa,CAAC,GACnB,OAAO,CAAC,aAAa,SAAS,UAAU,SAAS,EACjD,IAAI,CAAC,cAAc;AAAA,IAClB,IAAI,IAAI,SAAS,EAAE;AAAA,IACnB,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,WAAW,SAAS;AAAA,IACpB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV,EAAE;AACN;AAEO,SAAS,gBAAgB,WAAkE;AAChG,UAAQ,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa;AAC7C,UAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,WAAO;AAAA,MACL;AAAA,QACE,IAAI,IAAI,SAAS,EAAE;AAAA,QACnB,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,MAAM,SAAS;AAAA,QACf,WAAW,SAAS,aAAa,SAAS;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,OAAO,UAA8B,SAA8C;AACjG,MAAI,CAAC,QAAQ,OAAQ,QAAO,CAAC,GAAG,QAAQ;AACxC,QAAM,MAAiB,CAAC;AACxB,QAAM,OAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAClE,aAAW,WAAW,UAAU;AAC9B,WAAO,KAAK,UAAW,KAAK,CAAC,EAAoB,YAAY,QAAQ;AACnE,UAAI,KAAK,KAAK,MAAM,CAAkB;AACxC,QAAI,KAAK,OAAO;AAAA,EAClB;AACA,SAAO,CAAC,GAAG,KAAK,GAAG,IAAI;AACzB;",
4
+ "sourcesContent": ["import type { Message, SystemMessage, UserMessage } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { GuestProposal } from '../services.ts';\n\nexport const APPROVED = 'It was approved.';\nexport const UNANSWERED = 'Nobody approved this in time.';\nexport const DECLINED = 'It was declined.';\nexport const WITHDRAWN = 'It was withdrawn.';\n\nconst ENDED: Record<string, string> = {\n approved: APPROVED,\n unanswered: UNANSWERED,\n rejected: DECLINED,\n withdrawn: WITHDRAWN,\n};\n\nexport function proposalQueue(\n proposals: readonly GuestProposal[] | undefined,\n label: string,\n seat: string\n): UserMessage[] {\n return (proposals ?? [])\n .filter((proposal) => proposal.state === 'pending' || proposal.state === 'queued')\n .map((proposal) => ({\n id: `g${proposal.id}`,\n role: 'user',\n text: proposal.text,\n createdAt: proposal.createdAt,\n queued: true,\n mode: 'queue',\n from: label,\n origin: 'guest',\n seat,\n }));\n}\n\nexport function proposalNotices(proposals: readonly GuestProposal[] | undefined): SystemMessage[] {\n return (proposals ?? []).flatMap((proposal) => {\n const title = ENDED[proposal.state];\n if (!title) return [];\n return [\n {\n id: `g${proposal.id}`,\n role: 'system',\n kind: 'notice',\n title,\n text: proposal.text,\n createdAt: proposal.decidedAt ?? proposal.createdAt,\n },\n ];\n });\n}\n\nexport function merged(messages: readonly Message[], notices: readonly SystemMessage[]): Message[] {\n if (!notices.length) return [...messages];\n const out: Message[] = [];\n const left = [...notices].sort((a, b) => a.createdAt - b.createdAt);\n for (const message of messages) {\n while (left.length && (left[0] as SystemMessage).createdAt < message.createdAt)\n out.push(left.shift() as SystemMessage);\n out.push(message);\n }\n return [...out, ...left];\n}\n"],
5
+ "mappings": "AAGO,MAAM,WAAW;AACjB,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,YAAY;AAEzB,MAAM,QAAgC;AAAA,EACpC,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AACb;AAEO,SAAS,cACd,WACA,OACA,MACe;AACf,UAAQ,aAAa,CAAC,GACnB,OAAO,CAAC,aAAa,SAAS,UAAU,aAAa,SAAS,UAAU,QAAQ,EAChF,IAAI,CAAC,cAAc;AAAA,IAClB,IAAI,IAAI,SAAS,EAAE;AAAA,IACnB,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,WAAW,SAAS;AAAA,IACpB,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,EACF,EAAE;AACN;AAEO,SAAS,gBAAgB,WAAkE;AAChG,UAAQ,aAAa,CAAC,GAAG,QAAQ,CAAC,aAAa;AAC7C,UAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,CAAC,MAAO,QAAO,CAAC;AACpB,WAAO;AAAA,MACL;AAAA,QACE,IAAI,IAAI,SAAS,EAAE;AAAA,QACnB,MAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,MAAM,SAAS;AAAA,QACf,WAAW,SAAS,aAAa,SAAS;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEO,SAAS,OAAO,UAA8B,SAA8C;AACjG,MAAI,CAAC,QAAQ,OAAQ,QAAO,CAAC,GAAG,QAAQ;AACxC,QAAM,MAAiB,CAAC;AACxB,QAAM,OAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAClE,aAAW,WAAW,UAAU;AAC9B,WAAO,KAAK,UAAW,KAAK,CAAC,EAAoB,YAAY,QAAQ;AACnE,UAAI,KAAK,KAAK,MAAM,CAAkB;AACxC,QAAI,KAAK,OAAO;AAAA,EAClB;AACA,SAAO,CAAC,GAAG,KAAK,GAAG,IAAI;AACzB;",
6
6
  "names": []
7
7
  }
@@ -3,6 +3,8 @@ import type { Models } from '@earendil-works/pi-ai/models';
3
3
  import { type Conversation, Harness, type HarnessOptions, type ModelRef, type Registry, type Storage } from '@earendil-works/pi-durable';
4
4
  import { type Agents } from './agents.ts';
5
5
  import type { Cones } from './cone.ts';
6
+ import { type GuestToolGate } from './guests/guard.ts';
7
+ import { type GuestReviews } from './guests/review.ts';
6
8
  export interface AgentOptions {
7
9
  models: Models;
8
10
  model: ModelRef;
@@ -18,6 +20,8 @@ export interface Agent extends Cones {
18
20
  readonly harness: Harness;
19
21
  readonly root: Conversation;
20
22
  readonly agents: Agents;
23
+ readonly reviews: GuestReviews;
24
+ readonly gate: GuestToolGate;
21
25
  onCone(listener: (conversation: Conversation) => void | Promise<void>): () => void;
22
26
  prompt(text: string): Promise<string>;
23
27
  close(): Promise<void>;
@@ -20,15 +20,18 @@ export type Decider = DecidedBy | {
20
20
  };
21
21
  export interface Approvals {
22
22
  readonly state: ReplicatedState<Approval[]>;
23
- request(draft: ApprovalDraft, context: Context): Promise<Approval>;
23
+ request(draft: ApprovalDraft & {
24
+ id?: string;
25
+ }, context: Context): Promise<Approval>;
24
26
  decide(id: string, answer: unknown, reason: string | null, by: Decider, context: Context): Promise<ApprovalDecided>;
25
27
  settled(id: string, context: Context): Promise<Approval>;
26
28
  withdraw(id: string, reason: string | null, context: Context): Promise<Approval | undefined>;
27
29
  withdrawSeat(seat: string, context: Context): Promise<number>;
30
+ expire(id: string, context: Context): Promise<Approval | undefined>;
28
31
  close(): void;
29
32
  }
30
33
  export interface ApprovalsAttach {
31
- harness: Pick<Harness, 'commit'>;
34
+ harness: Pick<Harness, 'commit' | 'documentState'>;
32
35
  now?: () => number;
33
36
  ttlMs?: number;
34
37
  judge?: ApprovalJudge;
@@ -30,6 +30,8 @@ export type GuestMessageDetail = {
30
30
  export type GuestToolDetail = {
31
31
  tool: string;
32
32
  summary: string;
33
+ arguments?: string;
34
+ task?: number;
33
35
  };
34
36
  export type SudoDetail = {
35
37
  command: string;
@@ -24,4 +24,4 @@ export interface HostScoops {
24
24
  }
25
25
  export declare function readable(out: string): string;
26
26
  export declare function submissionId(value: string): SubmissionId | undefined;
27
- export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads, labels?: Pick<LabelsRuntime, 'label'>, guests?: Pick<Guests, 'open' | 'revoke'>): Omit<AgentControl, 'approvalPolicySet'>;
27
+ export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads, labels?: Pick<LabelsRuntime, 'label'>, guests?: Pick<Guests, 'open' | 'revoke' | 'forgetAlways'>): Omit<AgentControl, 'approvalPolicySet'>;
@@ -1,4 +1,20 @@
1
1
  export declare const GUEST_INPUT_KIND = "slicc.guest-input";
2
+ export declare const ASKED_KIND = "slicc.guest-asked";
3
+ export declare const ASKED_CLIP = 200;
4
+ export declare const REVIEWED_KIND = "slicc.guest-reviewed";
5
+ export type GuestAsked = {
6
+ seat: string;
7
+ name: string;
8
+ review: string;
9
+ text: string;
10
+ at: number;
11
+ };
12
+ export type GuestOutcome = 'approved' | 'rejected' | 'unanswered' | 'withdrawn';
13
+ export type GuestReviewed = {
14
+ review: string;
15
+ outcome: GuestOutcome;
16
+ };
17
+ export declare function askedLine(name: string, text: string, outcome?: GuestOutcome): string;
2
18
  export type GuestInput = {
3
19
  seat: string;
4
20
  name: string;
@@ -1,5 +1,32 @@
1
1
  import { type Extension, type Harness } from '@earendil-works/pi-durable';
2
+ import type { Approval, Approvals } from '../approvals/index.ts';
3
+ import { type GuestPolicy } from './policy.ts';
2
4
  export declare const GUEST_GUARD = "slicc-guest-guard";
3
5
  export declare const GUEST_REQUEST = "guest:";
4
- export declare const GUEST_TOOLS_BLOCKED = "Tool calls in a run a guest started need a review, which this agent can't do yet.";
5
- export declare function guestGuard(harness: () => Pick<Harness, 'submission'> | undefined): Extension;
6
+ export declare const GUEST_TOOL_MEMO = "slicc.guest-tool";
7
+ export declare const SUMMARY_LENGTH = 2000;
8
+ export declare const GATE_REASONS: {
9
+ readonly unknown: 'A guest started this run, and its seat names no review for tool calls that this agent knows.';
10
+ readonly ended: "A guest started this run, and that guest's seat has ended.";
11
+ readonly rejected: 'The owner declined this tool call in a run a guest started.';
12
+ readonly judged: 'The automatic check declined this tool call in a run a guest started';
13
+ readonly unanswered: 'Nobody approved this tool call in a run a guest started in time.';
14
+ readonly unroutable: "The cone can't review a tool call it is itself waiting on.";
15
+ readonly scoop: "No scoop can review a guest's tool call yet, so this one is denied.";
16
+ readonly withdrawn: 'The review of this tool call was withdrawn.';
17
+ };
18
+ export interface GateHost {
19
+ approvals: Pick<Approvals, 'state' | 'request' | 'settled' | 'withdraw'>;
20
+ policy(): GuestPolicy;
21
+ now?: () => number;
22
+ }
23
+ export interface GuestToolGate {
24
+ readonly extension: Extension;
25
+ bind(host: GateHost): void;
26
+ }
27
+ type Held = Pick<Harness, 'submission' | 'commit' | 'waitForTask'>;
28
+ export declare function canonical(value: unknown): string;
29
+ export declare function summaryOf(args: Record<string, unknown>): string;
30
+ export declare function reasonOf(item: Approval): string;
31
+ export declare function guestToolGate(harness: () => Held | undefined): GuestToolGate;
32
+ export {};
@@ -5,6 +5,7 @@ import type { Approvals } from '../approvals/index.ts';
5
5
  import type { ApprovalPolicies } from '../approvals/policy.ts';
6
6
  import type { GuestPrincipal } from '../serving.ts';
7
7
  import { type GuestPolicy } from './policy.ts';
8
+ import { type GuestReviews, type ReviewsState } from './review.ts';
8
9
  import { type GuestDraft, type GuestSeat, type SeatRecord } from './seats.ts';
9
10
  export type GuestOpened = {
10
11
  seat: GuestSeat;
@@ -18,9 +19,9 @@ export type Proposed = {
18
19
  submissionId: string;
19
20
  reason: null;
20
21
  } | {
21
- state: 'pending';
22
+ state: 'queued';
22
23
  submissionId: null;
23
- approval: string;
24
+ review: string;
24
25
  reason: null;
25
26
  } | {
26
27
  state: 'unanswered';
@@ -33,10 +34,14 @@ export interface ProposeRequest {
33
34
  }
34
35
  export interface Guests {
35
36
  readonly seats: ReplicatedState<GuestSeat[]>;
37
+ readonly reviews: ReplicatedState<ReviewsState | null>;
36
38
  open(draft: GuestDraft, context: Context): Promise<GuestOpened>;
37
39
  revoke(id: string, context: Context): Promise<{
38
40
  revoked: boolean;
39
41
  }>;
42
+ forgetAlways(id: string, approval: string, context: Context): Promise<{
43
+ removed: boolean;
44
+ }>;
40
45
  admit(id: string, label: string): GuestPrincipal | null;
41
46
  record(id: string): SeatRecord | undefined;
42
47
  current(guest: GuestPrincipal): SeatRecord | undefined;
@@ -47,10 +52,11 @@ export interface Guests {
47
52
  dispose(): void;
48
53
  }
49
54
  export interface GuestsOptions {
50
- harness: Pick<Harness, 'commit' | 'abortSubmission'>;
55
+ harness: Pick<Harness, 'commit' | 'abortSubmission' | 'documentState'>;
51
56
  agents: Pick<Agents, 'state' | 'conversation'>;
52
- approvals?: Pick<Approvals, 'state' | 'request' | 'withdrawSeat'>;
57
+ approvals?: Pick<Approvals, 'state' | 'request' | 'withdrawSeat' | 'expire' | 'withdraw'>;
53
58
  policy?: Pick<ApprovalPolicies, 'current'>;
59
+ reviews?: Pick<GuestReviews, 'task' | 'bind'>;
54
60
  now?: () => number;
55
61
  context?: Context;
56
62
  }
@@ -0,0 +1,68 @@
1
+ import { type Extension, type Tx } from '@earendil-works/pi-durable';
2
+ import type { Agents } from '../agents.ts';
3
+ import type { Approvals } from '../approvals/index.ts';
4
+ import { type GuestGate } from './seats.ts';
5
+ export type ReviewState = 'queued' | 'pending' | 'approved' | 'rejected' | 'unanswered' | 'withdrawn';
6
+ export type Review = {
7
+ id: string;
8
+ seat: string;
9
+ agentId: string;
10
+ label: string;
11
+ text: string;
12
+ request: string;
13
+ tier: GuestGate;
14
+ tools: GuestGate;
15
+ n: number;
16
+ task: number;
17
+ state: ReviewState;
18
+ reason: string | null;
19
+ createdAt: number;
20
+ decidedAt: number | null;
21
+ submissionId: string | null;
22
+ ended: boolean;
23
+ conversation: number;
24
+ auto?: boolean;
25
+ told?: boolean;
26
+ };
27
+ export type ReviewsState = {
28
+ next: number;
29
+ reviews: Record<string, Review>;
30
+ };
31
+ export declare const GuestReviewsDoc: import("@earendil-works/pi-durable").SessionDocToken<ReviewsState>;
32
+ export declare const GUEST_REVIEWS = "slicc-guest-reviews";
33
+ export declare const REVIEW_TASK = "slicc.guest-review";
34
+ export declare const MAX_QUEUED = 8;
35
+ export declare const KEPT_REVIEWS = 100;
36
+ export declare const KEPT_SUBMISSIONS = 100;
37
+ export interface ReviewHost {
38
+ approvals: Pick<Approvals, 'request' | 'expire' | 'withdraw'>;
39
+ agents: Pick<Agents, 'conversation'>;
40
+ line<T>(seat: string, run: () => Promise<T>): Promise<T>;
41
+ alwaysAllowed(): boolean;
42
+ }
43
+ type Input = {
44
+ review: string;
45
+ };
46
+ type Phase = {
47
+ phase: 'turn';
48
+ after?: number;
49
+ } | {
50
+ phase: 'ask';
51
+ } | {
52
+ phase: 'decide';
53
+ } | {
54
+ phase: 'deliver';
55
+ };
56
+ export declare const liveReviews: (state: ReviewsState | null | undefined, seat: string) => Review[];
57
+ export declare function endReview(review: Review, state: ReviewState, reason: string | null, at: number): void;
58
+ export declare function told(tx: Pick<Tx, 'appendEntry'>, review: Review): Promise<void>;
59
+ export declare function pruneReviews(state: ReviewsState, kept?: number): void;
60
+ export declare const deliveryId: (seat: string, review: string) => string;
61
+ export interface GuestReviews {
62
+ readonly extension: Extension;
63
+ readonly task: ReturnType<typeof reviewTask>;
64
+ bind(host: ReviewHost): void;
65
+ }
66
+ declare function reviewTask(lookup: () => Promise<ReviewHost>): import("@earendil-works/pi-durable").Task<Input, Phase, null, object>;
67
+ export declare function guestReviews(): GuestReviews;
68
+ export {};
@@ -1,4 +1,4 @@
1
- import type { ApprovalTier } from '../approvals/record.ts';
1
+ import type { ApprovalTier, DecidedBy } from '../approvals/record.ts';
2
2
  import { type GuestPolicy } from './policy.ts';
3
3
  export type GuestGate = ApprovalTier | 'off';
4
4
  export type GuestGates = {
@@ -12,11 +12,30 @@ export type GuestDraft = {
12
12
  expiresAt: number | null;
13
13
  gates: GuestGates;
14
14
  };
15
+ export type SeatSubmission = {
16
+ id: string;
17
+ approval: string | null;
18
+ tools: GuestGate;
19
+ };
20
+ export type AlwaysTool = {
21
+ approval: string;
22
+ tool: string;
23
+ arguments: string;
24
+ by: DecidedBy | null;
25
+ at: number;
26
+ };
15
27
  export type SeatRecord = GuestDraft & {
16
28
  createdAt: number;
17
29
  epoch: number;
18
30
  revoked: number | null;
19
31
  delivered?: string[];
32
+ submissions?: SeatSubmission[];
33
+ always?: {
34
+ by: DecidedBy | null;
35
+ approval: string;
36
+ at: number;
37
+ };
38
+ alwaysTools?: AlwaysTool[];
20
39
  };
21
40
  export interface GuestSeat {
22
41
  id: string;
@@ -27,6 +46,7 @@ export interface GuestSeat {
27
46
  gates: GuestGates;
28
47
  connected: boolean;
29
48
  pending: number;
49
+ alwaysTools: AlwaysTool[];
30
50
  }
31
51
  export type GuestsState = {
32
52
  seats: Record<string, SeatRecord>;
@@ -1,13 +1,13 @@
1
1
  import type { Context, Host, ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
3
  import type { Agents } from '../agents.ts';
4
- import type { Approval } from '../approvals/index.ts';
5
4
  import type { AgentGuest, GuestProposal } from '../services.ts';
6
5
  import type { GuestPrincipal } from '../serving.ts';
7
6
  import { type PortEndpoint } from '../wire.ts';
8
7
  import type { Guests } from './index.ts';
9
- export declare function proposalsOf(items: readonly Approval[] | undefined, seat: string): GuestProposal[];
10
- export declare function guestOpener(guests: Guests, agents: Pick<Agents, 'state'>, views: ReplicatedState<Record<string, ConversationView>>, context: Context, approvals?: ReplicatedState<Approval[]>): (principal: GuestPrincipal) => {
8
+ import type { ReviewsState } from './review.ts';
9
+ export declare function proposalsOf(state: ReviewsState | null | undefined, seat: string): GuestProposal[];
10
+ export declare function guestOpener(guests: Guests, agents: Pick<Agents, 'state'>, views: ReplicatedState<Record<string, ConversationView>>, context: Context): (principal: GuestPrincipal) => {
11
11
  value: AgentGuest;
12
12
  dispose(): void;
13
13
  } | undefined;
@@ -95,6 +95,9 @@ export interface AgentControl {
95
95
  guestRevoke(id: string, context: Context): Promise<{
96
96
  revoked: boolean;
97
97
  }>;
98
+ guestAlwaysForget(seat: string, approval: string, context: Context): Promise<{
99
+ removed: boolean;
100
+ }>;
98
101
  approvalPolicySet(change: ApprovalPolicyChange, context: Context): Promise<ApprovalPolicySet>;
99
102
  decide(id: string, decision: ApprovalAnswer, reason: string | null, context: Context): Promise<ApprovalDecided>;
100
103
  }
@@ -241,7 +244,7 @@ export interface AgentSettingsChange {
241
244
  thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;
242
245
  agentId?: string | null;
243
246
  }
244
- export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "approvalPolicySet" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "decide" | "discard" | "drop" | "freeze" | "guestOpen" | "guestRevoke" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
247
+ export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "approvalPolicySet" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "decide" | "discard" | "drop" | "freeze" | "guestAlwaysForget" | "guestOpen" | "guestRevoke" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
245
248
  export declare const OWNER_DEVICE_METHODS: readonly (keyof AgentControl & string)[];
246
249
  export declare const CONTROL_READS: readonly (keyof AgentControl & string)[];
247
250
  export declare const AgentControl: RemoteContract;
@@ -288,7 +291,7 @@ export interface GuestShown {
288
291
  export interface GuestProposal {
289
292
  id: string;
290
293
  text: string;
291
- state: 'pending' | 'approved' | 'rejected' | 'unanswered' | 'withdrawn';
294
+ state: 'queued' | 'pending' | 'approved' | 'rejected' | 'unanswered' | 'withdrawn';
292
295
  reason: string | null;
293
296
  createdAt: number;
294
297
  decidedAt: number | null;
@@ -1,5 +1,6 @@
1
1
  import type { AssistantMessage, AssistantStatus, ErrorAction, Message, MessagePart, ToolCall, UserMessage } from '@ai-ecoverse/slicc-spectrum/ui';
2
2
  import type { ConversationView, EntryRecord } from '@earendil-works/pi-durable';
3
+ import { type GuestOutcome } from '../guests/attribution.ts';
3
4
  import { type From } from '../scoops/from.ts';
4
5
  import type { Delivered } from '../services.ts';
5
6
  type Json = Record<string, unknown>;
@@ -42,6 +43,7 @@ export declare function errorPart(error: string, provider?: string): MessagePart
42
43
  export declare function errorAction(message: string): ErrorAction;
43
44
  export declare function assistant(id: string, message: ModelMessage, status?: AssistantStatus): AssistantMessage;
44
45
  export declare function origins(entries: readonly EntryRecord[]): Map<number, From>;
46
+ export declare function reviewed(entries: readonly EntryRecord[]): Map<string, GuestOutcome>;
45
47
  export declare function toMessages(view: ConversationView | undefined, deliveries?: Readonly<Record<string, Delivered>>): Message[];
46
48
  export declare function isBusy(view: ConversationView | undefined): boolean;
47
49
  export declare function queued(view: ConversationView | undefined, at?: (id: string) => number): UserMessage[];
@@ -1,8 +1,9 @@
1
1
  import type { Message, SystemMessage, UserMessage } from '@ai-ecoverse/slicc-spectrum/ui';
2
2
  import type { GuestProposal } from '../services.ts';
3
+ export declare const APPROVED = "It was approved.";
3
4
  export declare const UNANSWERED = "Nobody approved this in time.";
4
5
  export declare const DECLINED = "It was declined.";
5
6
  export declare const WITHDRAWN = "It was withdrawn.";
6
- export declare function proposalQueue(proposals: readonly GuestProposal[] | undefined, label: string): UserMessage[];
7
+ export declare function proposalQueue(proposals: readonly GuestProposal[] | undefined, label: string, seat: string): UserMessage[];
7
8
  export declare function proposalNotices(proposals: readonly GuestProposal[] | undefined): SystemMessage[];
8
9
  export declare function merged(messages: readonly Message[], notices: readonly SystemMessage[]): Message[];