@ai-ecoverse/slicc-agent 3.47.3 → 3.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -7
- package/dist/attachments.js +168 -0
- package/dist/attachments.js.map +7 -0
- package/dist/changes/git.js +2 -2
- package/dist/changes/git.js.map +1 -1
- package/dist/control.js +30 -10
- package/dist/control.js.map +2 -2
- package/dist/host.js +26 -9
- package/dist/host.js.map +3 -3
- package/dist/images/fit.js +50 -0
- package/dist/images/fit.js.map +7 -0
- package/dist/images/index.js +7 -47
- package/dist/images/index.js.map +3 -3
- package/dist/index.js +15 -0
- package/dist/index.js.map +2 -2
- package/dist/main.js +11 -2
- package/dist/main.js.map +2 -2
- package/dist/mcp/runtime.js +1 -1
- package/dist/mcp/runtime.js.map +2 -2
- package/dist/net.js +10 -1
- package/dist/net.js.map +2 -2
- package/dist/readonly.js +7 -1
- package/dist/readonly.js.map +2 -2
- package/dist/remote/client.js +9 -4
- package/dist/remote/client.js.map +2 -2
- package/dist/remote/host.js +1 -0
- package/dist/remote/host.js.map +2 -2
- package/dist/scoops/identity.js +4 -1
- package/dist/scoops/identity.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/spectrum/agent-port.js +17 -2
- package/dist/spectrum/agent-port.js.map +2 -2
- package/dist/spectrum/messages.js +7 -2
- package/dist/spectrum/messages.js.map +2 -2
- package/dist/spectrum/outgoing.js +73 -0
- package/dist/spectrum/outgoing.js.map +7 -0
- package/dist/system.js +11 -6
- package/dist/system.js.map +2 -2
- package/dist/thumbs.js +105 -0
- package/dist/thumbs.js.map +7 -0
- package/dist/types/attachments.d.ts +58 -0
- package/dist/types/changes/git.d.ts +2 -2
- package/dist/types/control.d.ts +2 -1
- package/dist/types/host.d.ts +4 -0
- package/dist/types/images/fit.d.ts +10 -0
- package/dist/types/images/index.d.ts +2 -10
- package/dist/types/index.d.ts +2 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/net.d.ts +8 -0
- package/dist/types/remote/client.d.ts +2 -0
- package/dist/types/remote/host.d.ts +2 -0
- package/dist/types/services.d.ts +16 -0
- package/dist/types/spectrum/outgoing.d.ts +8 -0
- package/dist/types/system.d.ts +1 -1
- package/dist/types/thumbs.d.ts +19 -0
- package/dist/types/uploads.d.ts +14 -0
- package/dist/types/views.d.ts +2 -1
- package/dist/uploads.js +43 -0
- package/dist/uploads.js.map +7 -0
- package/dist/views.js +6 -2
- package/dist/views.js.map +2 -2
- package/package.json +3 -3
- package/packages/vfs-root/skills/browser/SKILL.md +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/spectrum/agent-port.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n Agent,\n AgentEvents,\n AgentPort,\n AgentStatus,\n FrozenCone,\n Message,\n Outgoing,\n SlashCommand,\n SystemMessage,\n Thinking,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { AgentConnection } from '../client.ts';\nimport { entryLick } from '../licks/state.ts';\nimport { type VaultHold, vaultHold } from '../secrets/view.ts';\nimport type { AgentSettingsChange, AgentSummary, Command } from '../services.ts';\nimport { attempt } from './attempt.ts';\nimport { Emitter } from './emitter.ts';\nimport { isBusy, queued, toMessages } from './messages.ts';\n\nexport const CONE = 'cone';\n\nconst thinking: Record<string, Thinking> = {\n off: 'off',\n minimal: 'low',\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'high',\n max: 'high',\n};\n\ninterface AgentDoc {\n model?: { provider: string; modelId: string };\n thinkingLevel?: string;\n}\n\nfunction status(view: ConversationView | undefined, messages: readonly Message[]): AgentStatus {\n if (isBusy(view)) {\n const live = view?.docs['pi.live'] as { tools?: { status: string }[] } | undefined;\n return live?.tools?.some((slot) => slot.status === 'running') ? 'working' : 'thinking';\n }\n const last = messages.at(-1);\n return last?.role === 'assistant' && last.status === 'error' ? 'error' : 'idle';\n}\n\nexport function slashCommand({ kind, ...command }: Command): SlashCommand {\n return kind === 'action' ? command : { ...command, kind };\n}\n\nexport type AgentHold = VaultHold;\n\nexport type AgentAdapterEvents = AgentEvents & { hold: AgentHold | null };\n\nfunction sameHold(a: AgentHold | null, b: AgentHold | null): boolean {\n return a === b || (a !== null && b !== null && a.reason === b.reason && a.held === b.held);\n}\n\ninterface Pending {\n agentId: string;\n message: UserMessage;\n dropped: boolean;\n release(): void;\n released: Promise<void>;\n}\n\nexport class AgentAdapter extends Emitter<AgentAdapterEvents> implements AgentPort {\n readonly #connection: AgentConnection;\n readonly #ready: Promise<void>;\n readonly #messages = new Map<string, Message[]>();\n #active: string | null = null;\n #creating = new Map<string, Promise<string | null>>();\n #hold: AgentHold | null = null;\n readonly #outbox = new Map<string, Pending>();\n readonly #notices = new Map<string, { at: number; message: SystemMessage }[]>();\n\n constructor(connection: AgentConnection) {\n super();\n this.#connection = connection;\n this.#hold = this.hold();\n connection.vault?.subscribe(() => {\n const next = this.hold();\n if (sameHold(next, this.#hold)) return;\n this.#hold = next;\n if (!next) for (const pending of this.#outbox.values()) pending.release();\n this.emit('hold', next);\n this.emit('agents', this.list());\n });\n connection.frozen?.subscribe(() => {\n this.emit('frozen', this.frozen());\n this.emit('agents', this.list());\n });\n this.#ready = new Promise((resolve) => {\n connection.transcript.subscribe(() => {\n this.#refresh();\n resolve();\n });\n connection.deliveries.subscribe(() => this.#refresh());\n connection.views?.subscribe(() => this.#refresh());\n connection.agents?.subscribe(() => this.#refresh());\n });\n }\n\n #summary(): readonly AgentSummary[] {\n const agents = this.#connection.agents?.value?.agents;\n return agents?.length\n ? agents\n : [{ id: CONE, name: 'sliccy', kind: 'cone', parentId: null, role: null }];\n }\n\n #view(agentId: string = this.active()): ConversationView | undefined {\n const views = this.#connection.views?.value;\n const view = views?.[agentId];\n if (view) return view;\n const cone = this.#connection.agents?.value?.active ?? CONE;\n return agentId === cone ? this.#connection.transcript.value : undefined;\n }\n\n #refresh(): void {\n this.#active ??= this.#connection.agents?.value?.active ?? null;\n this.emit('agents', this.list());\n for (const summary of this.#summary()) this.#update(summary.id);\n for (const id of [...this.#messages.keys(), ...this.#notices.keys()])\n if (!this.#summary().some((summary) => summary.id === id)) {\n this.#messages.delete(id);\n this.#notices.delete(id);\n }\n }\n\n notify(text: string, agentId: string = this.active()): void {\n const notes = this.#notices.get(agentId) ?? [];\n notes.push({\n at: this.#messages.get(agentId)?.length ?? 0,\n message: {\n id: `n${crypto.randomUUID()}`,\n role: 'system',\n kind: 'notice',\n text,\n createdAt: Date.now(),\n },\n });\n this.#notices.set(agentId, notes);\n this.emit('messages', agentId);\n }\n\n #report(agentId: string): (text: string) => void {\n return (text) => this.notify(text, agentId);\n }\n\n #update(agentId: string): void {\n const view = this.#view(agentId);\n if (!view) return;\n const before = this.#messages.get(agentId) ?? [];\n const after = toMessages(view, this.#connection.deliveries.value);\n this.#messages.set(agentId, after);\n if (before.length !== after.length) {\n this.emit('messages', agentId);\n return;\n }\n const changed = after.filter(\n (message, index) => JSON.stringify(message) !== JSON.stringify(before[index])\n );\n if (changed.length === 1) this.emit('message', { agentId, message: changed[0] as Message });\n else if (changed.length > 1) this.emit('messages', agentId);\n }\n\n ready(): Promise<void> {\n return this.#ready;\n }\n\n hold(): AgentHold | null {\n return vaultHold(this.#connection.vault?.value);\n }\n\n list(): readonly Agent[] {\n const rows = this.#connection.frozen?.value ?? [];\n return this.#summary().map((summary) => {\n const view = this.#view(summary.id);\n const doc = view?.docs['pi.agent'] as AgentDoc | undefined;\n const title =\n summary.kind === 'cone' ? rows.find((row) => row.id === summary.id)?.title : undefined;\n return {\n id: summary.id,\n name: summary.role ? `${summary.name} \u00B7 ${summary.role}` : summary.name,\n kind: summary.kind,\n parentId: summary.parentId,\n status: this.#status(summary.id, status(view, this.#messages.get(summary.id) ?? [])),\n model: doc?.model ? `${doc.model.provider}/${doc.model.modelId}` : '',\n contextFill: 0,\n unread: 0,\n thinking: thinking[doc?.thinkingLevel ?? 'off'] ?? 'off',\n ...(title ? { title } : {}),\n };\n });\n }\n\n active(): string {\n const known = this.#summary();\n if (this.#active && this.#creating.has(this.#active)) return this.#active;\n if (this.#active && known.some((summary) => summary.id === this.#active)) return this.#active;\n return this.#connection.agents?.value?.active ?? CONE;\n }\n\n select(id: string): void {\n if (this.#creating.has(id)) {\n this.#active = id;\n this.emit('active', id);\n return;\n }\n const found = this.#summary().find((summary) => summary.id === id);\n if (!found) return;\n this.#active = id;\n if (found.kind === 'cone')\n attempt(\n this.#connection.control.selectCone(id, BACKGROUND_CONTEXT),\n 'switch cones',\n this.#report(id)\n );\n this.emit('active', id);\n this.emit('messages', id);\n }\n\n messages(agentId: string = this.active()): readonly Message[] {\n const shown = this.#messages.get(agentId) ?? [];\n const notes = this.#notices.get(agentId);\n if (!notes) return shown;\n const at = (index: number) => notes.filter((note) => note.at === index).map((n) => n.message);\n const late = notes.filter((note) => note.at >= shown.length).map((note) => note.message);\n return [...shown.flatMap((message, index) => [...at(index), message]), ...late];\n }\n\n async send(agentId: string, input: string | Outgoing): Promise<void> {\n const outgoing = typeof input === 'string' ? { text: input } : input;\n const target = this.#creating.has(agentId) ? await this.#creating.get(agentId) : agentId;\n if (target === null) throw new Error('The scoop could not be created.');\n const pending = target && this.#held(target) ? this.#pending(target, outgoing) : undefined;\n if (pending) await pending.released;\n if (pending?.dropped) return this.#settle(pending);\n const sent = await this.#connection.control\n .send(\n {\n text: outgoing.text,\n whenBusy: outgoing.mode === 'queue' ? 'followUp' : 'steer',\n requestId: crypto.randomUUID(),\n agentId: target || null,\n },\n BACKGROUND_CONTEXT\n )\n .finally(() => pending && this.#settle(pending));\n if (!sent.accepted) throw new Error(sent.error.message);\n if (pending?.dropped)\n attempt(\n this.#connection.control.unqueue(pending.agentId, sent.submissionId, BACKGROUND_CONTEXT),\n 'remove queued messages',\n this.#report(pending.agentId)\n );\n }\n\n #pending(agentId: string, outgoing: Outgoing): Pending {\n const id = `p${crypto.randomUUID()}`;\n const message: UserMessage = {\n id,\n role: 'user',\n text: outgoing.text,\n createdAt: Date.now(),\n queued: true,\n mode: outgoing.mode === 'queue' ? 'queue' : 'steer',\n };\n const { promise: released, resolve: release } = Promise.withResolvers<void>();\n const pending = { agentId, message, dropped: false, release, released };\n this.#outbox.set(id, pending);\n this.emit('messages', agentId);\n return pending;\n }\n\n #settle(pending: Pending): void {\n this.#outbox.delete(pending.message.id);\n this.emit('messages', pending.agentId);\n }\n\n async rewind(agentId: string, messageId: string): Promise<Outgoing | null> {\n const rewound = await this.#connection.control.rewindAgent(\n agentId,\n messageId,\n BACKGROUND_CONTEXT\n );\n return rewound.done ? { text: rewound.text } : null;\n }\n\n stop(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.stopAgent(agentId, BACKGROUND_CONTEXT),\n 'stop agents',\n this.#report(agentId)\n );\n }\n\n busy(agentId: string = this.active()): boolean {\n return isBusy(this.#view(agentId)) || this.#held(agentId);\n }\n\n #status(agentId: string, shown: AgentStatus): AgentStatus {\n return shown === 'idle' && this.#held(agentId) ? 'working' : shown;\n }\n\n #held(agentId: string): boolean {\n return this.#hold !== null && agentId === (this.#connection.agents?.value?.active ?? CONE);\n }\n\n queue(agentId: string = this.active()): readonly UserMessage[] {\n const pending = [...this.#outbox.values()]\n .filter((item) => item.agentId === agentId && !item.dropped)\n .map((item) => item.message);\n return [...queued(this.#view(agentId)), ...pending];\n }\n\n unqueue(agentId: string, messageId: string): void {\n const pending = this.#outbox.get(messageId);\n if (pending) {\n pending.dropped = true;\n pending.release();\n this.emit('messages', pending.agentId);\n return;\n }\n attempt(\n this.#connection.control.unqueue(agentId, messageId.replace(/^q/, ''), BACKGROUND_CONTEXT),\n 'remove queued messages',\n this.#report(agentId)\n );\n }\n\n suggestion(): string | null {\n return null;\n }\n\n answer(): void {}\n\n resolveLick(agentId: string, messageId: string, state: 'confirmed' | 'dismissed'): void {\n const message = this.messages(agentId).find((candidate) => candidate.id === messageId);\n const entry = this.#view(agentId)?.entries.find(\n (candidate) => `e${candidate.id}` === messageId\n );\n const lick = message?.role === 'lick' && entry ? entryLick(entry) : undefined;\n if (lick)\n attempt(\n this.#connection.control.resolveAgentLick(agentId, lick.id, state, BACKGROUND_CONTEXT),\n 'answer licks',\n this.#report(agentId)\n );\n }\n\n compact(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.compactAgent(agentId, null, BACKGROUND_CONTEXT),\n 'compact conversations',\n this.#report(agentId)\n );\n }\n\n clear(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.newChat(agentId, BACKGROUND_CONTEXT),\n 'start new chats',\n this.#report(agentId)\n );\n }\n\n freeze(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.freeze(agentId, BACKGROUND_CONTEXT),\n 'freeze cones',\n this.#report(agentId)\n );\n }\n\n #configure(agentId: string, change: Partial<AgentSettingsChange>): void {\n attempt(\n this.#connection.control.configure(\n {\n model: change.model ?? null,\n thinkingLevel: change.thinkingLevel ?? null,\n agentId,\n },\n BACKGROUND_CONTEXT\n ),\n 'change agent settings',\n this.#report(agentId)\n );\n }\n\n setModel(agentId: string, model: string): void {\n const at = model.indexOf('/');\n if (at <= 0) return;\n this.#configure(agentId, {\n model: { provider: model.slice(0, at), modelId: model.slice(at + 1) },\n });\n }\n\n setThinking(agentId: string, level: Thinking): void {\n this.#configure(agentId, { thinkingLevel: level });\n }\n\n async older(): Promise<readonly Message[]> {\n return [];\n }\n\n commands(): readonly SlashCommand[] {\n return (this.#connection.commands?.value ?? []).map(slashCommand);\n }\n\n createScoop(parentId: string, name: string): Agent {\n const provisional = `scoop:creating-${crypto.randomUUID()}`;\n const created = this.#connection.control.createScoop(parentId, name, BACKGROUND_CONTEXT).then(\n (result) => result.id,\n () => null\n );\n this.#creating.set(provisional, created);\n void created.then((id) => {\n if (this.#active !== provisional) return;\n this.#active = id ?? parentId;\n this.emit('active', this.#active);\n this.emit('messages', this.#active);\n });\n return {\n id: provisional,\n name,\n kind: 'scoop',\n parentId,\n status: 'idle',\n model: '',\n contextFill: 0,\n unread: 0,\n };\n }\n\n async drop(agentId: string): Promise<void> {\n const parent = this.#summary().find((summary) => summary.id === agentId)?.parentId ?? CONE;\n const dropped = await this.#connection.control.drop(agentId, BACKGROUND_CONTEXT);\n if (dropped.error !== null) throw new Error(dropped.error);\n if (this.#active === agentId) this.select(parent);\n }\n\n async createCone(name: string): Promise<Agent> {\n const created = await this.#connection.control.createCone(name, BACKGROUND_CONTEXT);\n if (created.error !== null) throw new Error(created.error);\n return {\n id: created.id,\n name: name.trim(),\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: '',\n contextFill: 0,\n unread: 0,\n };\n }\n\n frozen(): readonly FrozenCone[] {\n return (this.#connection.frozen?.value ?? []).map(\n ({ id, name, title, model, messages, frozenAt, kind, live, thawedAs }) => ({\n id,\n name,\n title,\n model,\n messages,\n frozenAt,\n kind,\n live,\n ...(thawedAs ? { thawedAs } : {}),\n })\n );\n }\n\n thaw(id: string): Agent | null {\n const record = this.frozen().find((item) => item.id === id);\n if (!record) return null;\n if (record.live) {\n const running = this.list().find((agent) => agent.id === id) ?? null;\n if (running) this.select(id);\n return running;\n }\n const provisional = `thawing-${crypto.randomUUID()}`;\n const thawed = this.#connection.control.thaw(id, BACKGROUND_CONTEXT).then(\n (result) => result.id,\n () => null\n );\n this.#creating.set(provisional, thawed);\n void thawed.then((cone) => {\n if (this.#active !== provisional) return;\n this.#active = cone ?? CONE;\n this.emit('active', this.#active);\n this.emit('messages', this.#active);\n });\n return {\n id: provisional,\n name: record.name,\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: record.model,\n contextFill: 0,\n unread: 0,\n };\n }\n\n discard(id: string): void {\n attempt(\n this.#connection.control.discard(id, BACKGROUND_CONTEXT),\n 'discard frozen cones',\n this.#report(this.active())\n );\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type {\n Agent,\n AgentEvents,\n AgentPort,\n AgentStatus,\n FrozenCone,\n Message,\n Outgoing,\n SlashCommand,\n SystemMessage,\n Thinking,\n UserMessage,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { AgentConnection } from '../client.ts';\nimport { shrink } from '../images/fit.ts';\nimport { entryLick } from '../licks/state.ts';\nimport { type VaultHold, vaultHold } from '../secrets/view.ts';\nimport type { AgentSettingsChange, AgentSummary, Command } from '../services.ts';\nimport { attempt } from './attempt.ts';\nimport { Emitter } from './emitter.ts';\nimport { isBusy, queued, toMessages } from './messages.ts';\nimport { readUrl, sendAttachments } from './outgoing.ts';\n\nexport const CONE = 'cone';\n\nconst thinking: Record<string, Thinking> = {\n off: 'off',\n minimal: 'low',\n low: 'low',\n medium: 'medium',\n high: 'high',\n xhigh: 'high',\n max: 'high',\n};\n\ninterface AgentDoc {\n model?: { provider: string; modelId: string };\n thinkingLevel?: string;\n}\n\nfunction status(view: ConversationView | undefined, messages: readonly Message[]): AgentStatus {\n if (isBusy(view)) {\n const live = view?.docs['pi.live'] as { tools?: { status: string }[] } | undefined;\n return live?.tools?.some((slot) => slot.status === 'running') ? 'working' : 'thinking';\n }\n const last = messages.at(-1);\n return last?.role === 'assistant' && last.status === 'error' ? 'error' : 'idle';\n}\n\nexport function slashCommand({ kind, ...command }: Command): SlashCommand {\n return kind === 'action' ? command : { ...command, kind };\n}\n\nexport type AgentHold = VaultHold;\n\nexport type AgentAdapterEvents = AgentEvents & { hold: AgentHold | null };\n\nfunction sameHold(a: AgentHold | null, b: AgentHold | null): boolean {\n return a === b || (a !== null && b !== null && a.reason === b.reason && a.held === b.held);\n}\n\ninterface Pending {\n agentId: string;\n message: UserMessage;\n dropped: boolean;\n release(): void;\n released: Promise<void>;\n}\n\nexport class AgentAdapter extends Emitter<AgentAdapterEvents> implements AgentPort {\n readonly #connection: AgentConnection;\n readonly #ready: Promise<void>;\n readonly #messages = new Map<string, Message[]>();\n #active: string | null = null;\n #creating = new Map<string, Promise<string | null>>();\n #hold: AgentHold | null = null;\n readonly #outbox = new Map<string, Pending>();\n readonly #notices = new Map<string, { at: number; message: SystemMessage }[]>();\n\n constructor(connection: AgentConnection) {\n super();\n this.#connection = connection;\n this.#hold = this.hold();\n connection.vault?.subscribe(() => {\n const next = this.hold();\n if (sameHold(next, this.#hold)) return;\n this.#hold = next;\n if (!next) for (const pending of this.#outbox.values()) pending.release();\n this.emit('hold', next);\n this.emit('agents', this.list());\n });\n connection.frozen?.subscribe(() => {\n this.emit('frozen', this.frozen());\n this.emit('agents', this.list());\n });\n this.#ready = new Promise((resolve) => {\n connection.transcript.subscribe(() => {\n this.#refresh();\n resolve();\n });\n connection.deliveries.subscribe(() => this.#refresh());\n connection.views?.subscribe(() => this.#refresh());\n connection.agents?.subscribe(() => this.#refresh());\n });\n }\n\n #summary(): readonly AgentSummary[] {\n const agents = this.#connection.agents?.value?.agents;\n return agents?.length\n ? agents\n : [{ id: CONE, name: 'sliccy', kind: 'cone', parentId: null, role: null }];\n }\n\n #view(agentId: string = this.active()): ConversationView | undefined {\n const views = this.#connection.views?.value;\n const view = views?.[agentId];\n if (view) return view;\n const cone = this.#connection.agents?.value?.active ?? CONE;\n return agentId === cone ? this.#connection.transcript.value : undefined;\n }\n\n #refresh(): void {\n this.#active ??= this.#connection.agents?.value?.active ?? null;\n this.emit('agents', this.list());\n for (const summary of this.#summary()) this.#update(summary.id);\n for (const id of [...this.#messages.keys(), ...this.#notices.keys()])\n if (!this.#summary().some((summary) => summary.id === id)) {\n this.#messages.delete(id);\n this.#notices.delete(id);\n }\n }\n\n notify(text: string, agentId: string = this.active()): void {\n const notes = this.#notices.get(agentId) ?? [];\n notes.push({\n at: this.#messages.get(agentId)?.length ?? 0,\n message: {\n id: `n${crypto.randomUUID()}`,\n role: 'system',\n kind: 'notice',\n text,\n createdAt: Date.now(),\n },\n });\n this.#notices.set(agentId, notes);\n this.emit('messages', agentId);\n }\n\n #report(agentId: string): (text: string) => void {\n return (text) => this.notify(text, agentId);\n }\n\n #update(agentId: string): void {\n const view = this.#view(agentId);\n if (!view) return;\n const before = this.#messages.get(agentId) ?? [];\n const after = toMessages(view, this.#connection.deliveries.value);\n this.#messages.set(agentId, after);\n if (before.length !== after.length) {\n this.emit('messages', agentId);\n return;\n }\n const changed = after.filter(\n (message, index) => JSON.stringify(message) !== JSON.stringify(before[index])\n );\n if (changed.length === 1) this.emit('message', { agentId, message: changed[0] as Message });\n else if (changed.length > 1) this.emit('messages', agentId);\n }\n\n ready(): Promise<void> {\n return this.#ready;\n }\n\n hold(): AgentHold | null {\n return vaultHold(this.#connection.vault?.value);\n }\n\n list(): readonly Agent[] {\n const rows = this.#connection.frozen?.value ?? [];\n return this.#summary().map((summary) => {\n const view = this.#view(summary.id);\n const doc = view?.docs['pi.agent'] as AgentDoc | undefined;\n const title =\n summary.kind === 'cone' ? rows.find((row) => row.id === summary.id)?.title : undefined;\n return {\n id: summary.id,\n name: summary.role ? `${summary.name} \u00B7 ${summary.role}` : summary.name,\n kind: summary.kind,\n parentId: summary.parentId,\n status: this.#status(summary.id, status(view, this.#messages.get(summary.id) ?? [])),\n model: doc?.model ? `${doc.model.provider}/${doc.model.modelId}` : '',\n contextFill: 0,\n unread: 0,\n thinking: thinking[doc?.thinkingLevel ?? 'off'] ?? 'off',\n ...(title ? { title } : {}),\n };\n });\n }\n\n active(): string {\n const known = this.#summary();\n if (this.#active && this.#creating.has(this.#active)) return this.#active;\n if (this.#active && known.some((summary) => summary.id === this.#active)) return this.#active;\n return this.#connection.agents?.value?.active ?? CONE;\n }\n\n select(id: string): void {\n if (this.#creating.has(id)) {\n this.#active = id;\n this.emit('active', id);\n return;\n }\n const found = this.#summary().find((summary) => summary.id === id);\n if (!found) return;\n this.#active = id;\n if (found.kind === 'cone')\n attempt(\n this.#connection.control.selectCone(id, BACKGROUND_CONTEXT),\n 'switch cones',\n this.#report(id)\n );\n this.emit('active', id);\n this.emit('messages', id);\n }\n\n messages(agentId: string = this.active()): readonly Message[] {\n const shown = this.#messages.get(agentId) ?? [];\n const notes = this.#notices.get(agentId);\n if (!notes) return shown;\n const at = (index: number) => notes.filter((note) => note.at === index).map((n) => n.message);\n const late = notes.filter((note) => note.at >= shown.length).map((note) => note.message);\n return [...shown.flatMap((message, index) => [...at(index), message]), ...late];\n }\n\n async send(agentId: string, input: string | Outgoing): Promise<void> {\n const outgoing = typeof input === 'string' ? { text: input } : input;\n const attachments = outgoing.attachments?.length\n ? await sendAttachments(outgoing.attachments, readUrl, shrink, (ref) =>\n this.#connection.control.image(ref, BACKGROUND_CONTEXT)\n ).catch((error: Error) => {\n this.notify(error.message, agentId);\n return null;\n })\n : [];\n if (!attachments) return;\n const target = this.#creating.has(agentId) ? await this.#creating.get(agentId) : agentId;\n if (target === null) throw new Error('The scoop could not be created.');\n const pending = target && this.#held(target) ? this.#pending(target, outgoing) : undefined;\n if (pending) await pending.released;\n if (pending?.dropped) return this.#settle(pending);\n const sent = await this.#connection.control\n .send(\n {\n text: outgoing.text,\n whenBusy: outgoing.mode === 'queue' ? 'followUp' : 'steer',\n requestId: crypto.randomUUID(),\n agentId: target || null,\n ...(attachments.length ? { attachments } : {}),\n },\n BACKGROUND_CONTEXT\n )\n .finally(() => pending && this.#settle(pending));\n if (!sent.accepted) throw new Error(sent.error.message);\n if (pending?.dropped)\n attempt(\n this.#connection.control.unqueue(pending.agentId, sent.submissionId, BACKGROUND_CONTEXT),\n 'remove queued messages',\n this.#report(pending.agentId)\n );\n }\n\n #pending(agentId: string, outgoing: Outgoing): Pending {\n const id = `p${crypto.randomUUID()}`;\n const message: UserMessage = {\n id,\n role: 'user',\n text: outgoing.text,\n createdAt: Date.now(),\n ...(outgoing.attachments?.length ? { attachments: [...outgoing.attachments] } : {}),\n queued: true,\n mode: outgoing.mode === 'queue' ? 'queue' : 'steer',\n };\n const { promise: released, resolve: release } = Promise.withResolvers<void>();\n const pending = { agentId, message, dropped: false, release, released };\n this.#outbox.set(id, pending);\n this.emit('messages', agentId);\n return pending;\n }\n\n #settle(pending: Pending): void {\n this.#outbox.delete(pending.message.id);\n this.emit('messages', pending.agentId);\n }\n\n async rewind(agentId: string, messageId: string): Promise<Outgoing | null> {\n const rewound = await this.#connection.control.rewindAgent(\n agentId,\n messageId,\n BACKGROUND_CONTEXT\n );\n if (!rewound.done) return null;\n return rewound.attachments?.length\n ? { text: rewound.text, attachments: rewound.attachments }\n : { text: rewound.text };\n }\n\n stop(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.stopAgent(agentId, BACKGROUND_CONTEXT),\n 'stop agents',\n this.#report(agentId)\n );\n }\n\n busy(agentId: string = this.active()): boolean {\n return isBusy(this.#view(agentId)) || this.#held(agentId);\n }\n\n #status(agentId: string, shown: AgentStatus): AgentStatus {\n return shown === 'idle' && this.#held(agentId) ? 'working' : shown;\n }\n\n #held(agentId: string): boolean {\n return this.#hold !== null && agentId === (this.#connection.agents?.value?.active ?? CONE);\n }\n\n queue(agentId: string = this.active()): readonly UserMessage[] {\n const pending = [...this.#outbox.values()]\n .filter((item) => item.agentId === agentId && !item.dropped)\n .map((item) => item.message);\n return [...queued(this.#view(agentId)), ...pending];\n }\n\n unqueue(agentId: string, messageId: string): void {\n const pending = this.#outbox.get(messageId);\n if (pending) {\n pending.dropped = true;\n pending.release();\n this.emit('messages', pending.agentId);\n return;\n }\n attempt(\n this.#connection.control.unqueue(agentId, messageId.replace(/^q/, ''), BACKGROUND_CONTEXT),\n 'remove queued messages',\n this.#report(agentId)\n );\n }\n\n suggestion(): string | null {\n return null;\n }\n\n answer(): void {}\n\n resolveLick(agentId: string, messageId: string, state: 'confirmed' | 'dismissed'): void {\n const message = this.messages(agentId).find((candidate) => candidate.id === messageId);\n const entry = this.#view(agentId)?.entries.find(\n (candidate) => `e${candidate.id}` === messageId\n );\n const lick = message?.role === 'lick' && entry ? entryLick(entry) : undefined;\n if (lick)\n attempt(\n this.#connection.control.resolveAgentLick(agentId, lick.id, state, BACKGROUND_CONTEXT),\n 'answer licks',\n this.#report(agentId)\n );\n }\n\n compact(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.compactAgent(agentId, null, BACKGROUND_CONTEXT),\n 'compact conversations',\n this.#report(agentId)\n );\n }\n\n clear(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.newChat(agentId, BACKGROUND_CONTEXT),\n 'start new chats',\n this.#report(agentId)\n );\n }\n\n freeze(agentId: string = this.active()): void {\n attempt(\n this.#connection.control.freeze(agentId, BACKGROUND_CONTEXT),\n 'freeze cones',\n this.#report(agentId)\n );\n }\n\n #configure(agentId: string, change: Partial<AgentSettingsChange>): void {\n attempt(\n this.#connection.control.configure(\n {\n model: change.model ?? null,\n thinkingLevel: change.thinkingLevel ?? null,\n agentId,\n },\n BACKGROUND_CONTEXT\n ),\n 'change agent settings',\n this.#report(agentId)\n );\n }\n\n setModel(agentId: string, model: string): void {\n const at = model.indexOf('/');\n if (at <= 0) return;\n this.#configure(agentId, {\n model: { provider: model.slice(0, at), modelId: model.slice(at + 1) },\n });\n }\n\n setThinking(agentId: string, level: Thinking): void {\n this.#configure(agentId, { thinkingLevel: level });\n }\n\n async older(): Promise<readonly Message[]> {\n return [];\n }\n\n commands(): readonly SlashCommand[] {\n return (this.#connection.commands?.value ?? []).map(slashCommand);\n }\n\n createScoop(parentId: string, name: string): Agent {\n const provisional = `scoop:creating-${crypto.randomUUID()}`;\n const created = this.#connection.control.createScoop(parentId, name, BACKGROUND_CONTEXT).then(\n (result) => result.id,\n () => null\n );\n this.#creating.set(provisional, created);\n void created.then((id) => {\n if (this.#active !== provisional) return;\n this.#active = id ?? parentId;\n this.emit('active', this.#active);\n this.emit('messages', this.#active);\n });\n return {\n id: provisional,\n name,\n kind: 'scoop',\n parentId,\n status: 'idle',\n model: '',\n contextFill: 0,\n unread: 0,\n };\n }\n\n async drop(agentId: string): Promise<void> {\n const parent = this.#summary().find((summary) => summary.id === agentId)?.parentId ?? CONE;\n const dropped = await this.#connection.control.drop(agentId, BACKGROUND_CONTEXT);\n if (dropped.error !== null) throw new Error(dropped.error);\n if (this.#active === agentId) this.select(parent);\n }\n\n async createCone(name: string): Promise<Agent> {\n const created = await this.#connection.control.createCone(name, BACKGROUND_CONTEXT);\n if (created.error !== null) throw new Error(created.error);\n return {\n id: created.id,\n name: name.trim(),\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: '',\n contextFill: 0,\n unread: 0,\n };\n }\n\n frozen(): readonly FrozenCone[] {\n return (this.#connection.frozen?.value ?? []).map(\n ({ id, name, title, model, messages, frozenAt, kind, live, thawedAs }) => ({\n id,\n name,\n title,\n model,\n messages,\n frozenAt,\n kind,\n live,\n ...(thawedAs ? { thawedAs } : {}),\n })\n );\n }\n\n thaw(id: string): Agent | null {\n const record = this.frozen().find((item) => item.id === id);\n if (!record) return null;\n if (record.live) {\n const running = this.list().find((agent) => agent.id === id) ?? null;\n if (running) this.select(id);\n return running;\n }\n const provisional = `thawing-${crypto.randomUUID()}`;\n const thawed = this.#connection.control.thaw(id, BACKGROUND_CONTEXT).then(\n (result) => result.id,\n () => null\n );\n this.#creating.set(provisional, thawed);\n void thawed.then((cone) => {\n if (this.#active !== provisional) return;\n this.#active = cone ?? CONE;\n this.emit('active', this.#active);\n this.emit('messages', this.#active);\n });\n return {\n id: provisional,\n name: record.name,\n kind: 'cone',\n parentId: null,\n status: 'idle',\n model: record.model,\n contextFill: 0,\n unread: 0,\n };\n }\n\n discard(id: string): void {\n attempt(\n this.#connection.control.discard(id, BACKGROUND_CONTEXT),\n 'discard frozen cones',\n this.#report(this.active())\n );\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { splitUser } from "../attachments.js";
|
|
1
2
|
import { parseLick } from "../licks/lick.js";
|
|
2
3
|
import { entryLick, LICK_TOOLS, lickDecisions } from "../licks/state.js";
|
|
3
4
|
import { mcpLabel } from "../mcp/label.js";
|
|
@@ -165,7 +166,7 @@ function user(id, message, delivered, from) {
|
|
|
165
166
|
return {
|
|
166
167
|
id,
|
|
167
168
|
role: "user",
|
|
168
|
-
|
|
169
|
+
...shownUser(message.content, `ref:${id.slice(1)}:0`),
|
|
169
170
|
createdAt: message.timestamp ?? 0,
|
|
170
171
|
...delivered ? { delivered } : {},
|
|
171
172
|
...from ? { from: from.from } : {},
|
|
@@ -393,6 +394,10 @@ function toMessages(view, deliveries = {}) {
|
|
|
393
394
|
live(view, out, calls);
|
|
394
395
|
return out;
|
|
395
396
|
}
|
|
397
|
+
function shownUser(content, prefix) {
|
|
398
|
+
const { text, attachments } = splitUser(content, prefix);
|
|
399
|
+
return attachments.length ? { text, attachments } : { text };
|
|
400
|
+
}
|
|
396
401
|
function isBusy(view) {
|
|
397
402
|
return Boolean(view?.docs["pi.live"]?.run);
|
|
398
403
|
}
|
|
@@ -401,7 +406,7 @@ function queued(view) {
|
|
|
401
406
|
return items.filter((item) => item.mode !== "write" && !parseLick(textOf(item.content))).map((item) => ({
|
|
402
407
|
id: `q${item.id}`,
|
|
403
408
|
role: "user",
|
|
404
|
-
|
|
409
|
+
...shownUser(item.content),
|
|
405
410
|
createdAt: 0,
|
|
406
411
|
queued: true,
|
|
407
412
|
mode: item.mode === "steer" ? "steer" : "queue"
|
|
@@ -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 { 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' };\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 missing = /no api key|missing|not configured|no credentials/i;\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 if (action === 'settings' && provider === 'adobe') {\n return {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n };\n }\n const name = providerNames[provider ?? ''] ?? 'The provider';\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 text: textOf(message.content),\n createdAt: message.timestamp ?? 0,\n ...(delivered ? { delivered } : {}),\n ...(from ? { from: from.from } : {}),\n ...(from?.agent ? { origin: 'agent' as const } : {}),\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 === '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\nexport function isBusy(view: ConversationView | undefined): boolean {\n return Boolean((view?.docs['pi.live'] as Live | undefined)?.run);\n}\n\nexport function queued(view: ConversationView | undefined): 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 }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => ({\n id: `q${item.id}`,\n role: 'user',\n text: textOf(item.content),\n createdAt: 0,\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\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 { 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' };\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 missing = /no api key|missing|not configured|no credentials/i;\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 if (action === 'settings' && provider === 'adobe') {\n return {\n type: 'error',\n message: 'Your Adobe session has expired.',\n detail: error,\n action: 'login',\n };\n }\n const name = providerNames[provider ?? ''] ?? 'The provider';\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\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 === '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(view: ConversationView | undefined): 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 }[];\n return items\n .filter((item) => item.mode !== 'write' && !parseLick(textOf(item.content)))\n .map((item) => ({\n id: `q${item.id}`,\n role: 'user' as const,\n ...shownUser(item.content),\n createdAt: 0,\n queued: true,\n mode: item.mode === 'steer' ? 'steer' : 'queue',\n }));\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["note", "part"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FILE_LIMIT,
|
|
3
|
+
limitOf,
|
|
4
|
+
REF,
|
|
5
|
+
TOGETHER,
|
|
6
|
+
TOTAL_LIMIT,
|
|
7
|
+
textBytes,
|
|
8
|
+
tooLarge
|
|
9
|
+
} from "../attachments.js";
|
|
10
|
+
import { base64, shrink } from "../images/fit.js";
|
|
11
|
+
const readUrl = async (url) => {
|
|
12
|
+
const response = await fetch(url);
|
|
13
|
+
if (!response.ok) throw new Error(`status ${response.status}`);
|
|
14
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
15
|
+
};
|
|
16
|
+
const KINDS = /* @__PURE__ */ new Set(["image", "text", "file"]);
|
|
17
|
+
async function bytesOf(attachment, read, fit) {
|
|
18
|
+
const bytes = await read(attachment.url).catch((error) => {
|
|
19
|
+
throw new Error(`Couldn't read ${attachment.name}: ${error.message}.`);
|
|
20
|
+
});
|
|
21
|
+
const kind = attachment.kind;
|
|
22
|
+
const image = { bytes, mimeType: attachment.mimeType };
|
|
23
|
+
const fitted = kind === "image" && bytes.length > limitOf(kind) ? await fit(image).catch(() => image) : image;
|
|
24
|
+
if (fitted.bytes.length > limitOf(kind)) throw new Error(tooLarge(attachment.name, kind));
|
|
25
|
+
return fitted;
|
|
26
|
+
}
|
|
27
|
+
async function kept(attachment, stored) {
|
|
28
|
+
const match = REF.exec(attachment.id);
|
|
29
|
+
if (!match) return void 0;
|
|
30
|
+
const [, entry, message, part] = match.map(Number);
|
|
31
|
+
const found = await stored({ entry, message, part });
|
|
32
|
+
if (found.data === null)
|
|
33
|
+
throw new Error(`Couldn't find ${attachment.name} again; attach it again.`);
|
|
34
|
+
return found;
|
|
35
|
+
}
|
|
36
|
+
async function resolved(attachment, read, fit, stored) {
|
|
37
|
+
const kind = attachment.kind;
|
|
38
|
+
const base = {
|
|
39
|
+
name: attachment.name,
|
|
40
|
+
kind,
|
|
41
|
+
mimeType: attachment.mimeType,
|
|
42
|
+
...attachment.path === void 0 ? {} : { path: attachment.path }
|
|
43
|
+
};
|
|
44
|
+
const found = await kept(attachment, stored);
|
|
45
|
+
if (found?.data) return { ...base, mimeType: found.mimeType, data: found.data };
|
|
46
|
+
if (kind === "text" && attachment.text !== void 0) {
|
|
47
|
+
if (textBytes(attachment.text) > FILE_LIMIT) throw new Error(tooLarge(attachment.name, kind));
|
|
48
|
+
return { ...base, text: attachment.text };
|
|
49
|
+
}
|
|
50
|
+
if (attachment.url) {
|
|
51
|
+
const { bytes, mimeType } = await bytesOf(attachment, read, fit);
|
|
52
|
+
return { ...base, mimeType, data: base64(bytes) };
|
|
53
|
+
}
|
|
54
|
+
if (attachment.path !== void 0) return base;
|
|
55
|
+
throw new Error(`Couldn't read ${attachment.name}; attach it again.`);
|
|
56
|
+
}
|
|
57
|
+
async function sendAttachments(attachments = [], read = readUrl, fit = shrink, stored = async () => ({ data: null, mimeType: null })) {
|
|
58
|
+
const out = [];
|
|
59
|
+
let total = 0;
|
|
60
|
+
for (const attachment of attachments) {
|
|
61
|
+
if (attachment.error || !KINDS.has(attachment.kind)) continue;
|
|
62
|
+
const item = await resolved(attachment, read, fit, stored);
|
|
63
|
+
total += textBytes(item.text ?? "") + (item.data?.length ?? 0) * 3 / 4;
|
|
64
|
+
if (total > TOTAL_LIMIT) throw new Error(TOGETHER);
|
|
65
|
+
out.push(item);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
readUrl,
|
|
71
|
+
sendAttachments
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=outgoing.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/spectrum/outgoing.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Attachment } from '@ai-ecoverse/slicc-spectrum/ui';\nimport {\n type AttachmentKind,\n FILE_LIMIT,\n limitOf,\n REF,\n type SendAttachment,\n TOGETHER,\n TOTAL_LIMIT,\n textBytes,\n tooLarge,\n} from '../attachments.ts';\nimport { base64, type Shrink, shrink } from '../images/fit.ts';\nimport type { ImageRef, StoredImage } from '../services.ts';\n\nexport type Read = (url: string) => Promise<Uint8Array>;\n\nexport type Stored = (ref: ImageRef) => Promise<StoredImage>;\n\nexport const readUrl: Read = async (url) => {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`status ${response.status}`);\n return new Uint8Array(await response.arrayBuffer());\n};\n\nconst KINDS = new Set<string>(['image', 'text', 'file']);\n\nasync function bytesOf(\n attachment: Attachment,\n read: Read,\n fit: Shrink\n): Promise<{ bytes: Uint8Array; mimeType: string }> {\n const bytes = await read(attachment.url as string).catch((error: Error) => {\n throw new Error(`Couldn't read ${attachment.name}: ${error.message}.`);\n });\n const kind = attachment.kind as AttachmentKind;\n const image = { bytes, mimeType: attachment.mimeType };\n const fitted =\n kind === 'image' && bytes.length > limitOf(kind) ? await fit(image).catch(() => image) : image;\n if (fitted.bytes.length > limitOf(kind)) throw new Error(tooLarge(attachment.name, kind));\n return fitted;\n}\n\nasync function kept(attachment: Attachment, stored: Stored): Promise<StoredImage | undefined> {\n const match = REF.exec(attachment.id);\n if (!match) return undefined;\n const [, entry, message, part] = match.map(Number) as number[];\n const found = await stored({ entry, message, part } as ImageRef);\n if (found.data === null)\n throw new Error(`Couldn't find ${attachment.name} again; attach it again.`);\n return found;\n}\n\nasync function resolved(\n attachment: Attachment,\n read: Read,\n fit: Shrink,\n stored: Stored\n): Promise<SendAttachment> {\n const kind = attachment.kind as AttachmentKind;\n const base = {\n name: attachment.name,\n kind,\n mimeType: attachment.mimeType,\n ...(attachment.path === undefined ? {} : { path: attachment.path }),\n };\n const found = await kept(attachment, stored);\n if (found?.data) return { ...base, mimeType: found.mimeType, data: found.data };\n if (kind === 'text' && attachment.text !== undefined) {\n if (textBytes(attachment.text) > FILE_LIMIT) throw new Error(tooLarge(attachment.name, kind));\n return { ...base, text: attachment.text };\n }\n if (attachment.url) {\n const { bytes, mimeType } = await bytesOf(attachment, read, fit);\n return { ...base, mimeType, data: base64(bytes) };\n }\n if (attachment.path !== undefined) return base;\n throw new Error(`Couldn't read ${attachment.name}; attach it again.`);\n}\n\nexport async function sendAttachments(\n attachments: readonly Attachment[] = [],\n read: Read = readUrl,\n fit: Shrink = shrink,\n stored: Stored = async () => ({ data: null, mimeType: null })\n): Promise<SendAttachment[]> {\n const out: SendAttachment[] = [];\n let total = 0;\n for (const attachment of attachments) {\n if (attachment.error || !KINDS.has(attachment.kind)) continue;\n const item = await resolved(attachment, read, fit, stored);\n total += textBytes(item.text ?? '') + ((item.data?.length ?? 0) * 3) / 4;\n if (total > TOTAL_LIMIT) throw new Error(TOGETHER);\n out.push(item);\n }\n return out;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/system.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { linkedExit, pageOnly } from "./net.js";
|
|
1
2
|
const LIST_PATH = 'IFS=:; for d in $PATH; do [ -d "$d" ] && ls -1 "$d"; done';
|
|
2
3
|
const RUNTIMES = ["node", "python3"];
|
|
3
4
|
async function commandsOnPath(client) {
|
|
@@ -25,12 +26,16 @@ async function browserConnected(client) {
|
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
29
|
+
const EXITS = {
|
|
30
|
+
local: "a linked slicc exit that fetches without CORS",
|
|
31
|
+
remote: "a linked slicc exit on another device that fetches without CORS",
|
|
32
|
+
tailnet: "your tailnet's exit node, which fetches without CORS"
|
|
33
|
+
};
|
|
28
34
|
function transportName(transport) {
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (traits?.manualRedirects) return "a local proxy (slicc-node) that fetches without CORS";
|
|
35
|
+
const exit = linkedExit(transport);
|
|
36
|
+
if (exit) return EXITS[exit.kind] ?? "a linked exit that fetches without CORS";
|
|
37
|
+
if (pageOnly(transport)) return "the page's own fetch, so only servers that allow CORS answer";
|
|
38
|
+
if (transport?.traits?.manualRedirects) return "a local proxy that fetches without CORS";
|
|
34
39
|
return "a relay that fetches without CORS";
|
|
35
40
|
}
|
|
36
41
|
async function agentVersion(fetcher, url = new URL("../package.json", import.meta.url)) {
|
|
@@ -53,7 +58,7 @@ function systemSection(facts) {
|
|
|
53
58
|
...facts.browser ? [
|
|
54
59
|
`Browser: one may be available (SLICC_CDP_URL is set), but nothing has checked that one is attached, so don't tell the user it's connected. ${facts.commands.includes("curlwright") ? "playwright-cli and curlwright drive" : "playwright-cli drives"} the user's own browser through the SLICC extension, with their logins. Read the browser skill and run its check before you use it.`
|
|
55
60
|
] : [],
|
|
56
|
-
facts.commands.includes("git") ? "Git: local repositories work (init, add, commit, status, diff, restore, branch, checkout, log). Clone, fetch and push over HTTPS need slicc
|
|
61
|
+
facts.commands.includes("git") ? "Git: local repositories work (init, add, commit, status, diff, restore, branch, checkout, log). Clone, fetch and push over HTTPS need slicc linked or the SLICC extension connected; through the page alone they fail with a CORS or 502 error." : "Git: not installed. When you need it, install it with `pnpm add -g @ai-ecoverse/wasm-git`.",
|
|
57
62
|
`Not here yet: ${[...missing, ...facts.browser ? [] : ["a browser or CDP tool"], "GitHub credentials"].join(", ")}.`
|
|
58
63
|
].join("\n");
|
|
59
64
|
}
|
package/dist/system.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/system.ts"],
|
|
4
|
-
"sourcesContent": ["import type { KernelClient } from './kernel/client.ts';\nimport type
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { KernelClient } from './kernel/client.ts';\nimport { linkedExit, pageOnly, type Transport } from './net.ts';\n\nexport interface SystemFacts {\n version: string;\n commands: string[];\n transport: string;\n browser?: boolean;\n}\n\nconst LIST_PATH = 'IFS=:; for d in $PATH; do [ -d \"$d\" ] && ls -1 \"$d\"; done';\nconst RUNTIMES = ['node', 'python3'];\n\nexport async function commandsOnPath(client: KernelClient): Promise<string[]> {\n const decoder = new TextDecoder();\n let out = '';\n try {\n const process = await client.spawn(['bash', '-c', LIST_PATH], {\n onStdout: (bytes) => {\n out += decoder.decode(bytes, { stream: true });\n },\n });\n await process.exited;\n } catch {\n return [];\n }\n const names = out.split('\\n').map((name) => name.trim());\n return [...new Set(names.filter(Boolean))].sort();\n}\n\nconst BROWSER = '[ -n \"$SLICC_CDP_URL\" ] && command -v playwright-cli >/dev/null';\n\nexport async function browserConnected(client: KernelClient): Promise<boolean> {\n try {\n const process = await client.spawn(['bash', '-c', BROWSER], {});\n return (await process.exited) === 0;\n } catch {\n return false;\n }\n}\n\nconst EXITS: Record<string, string> = {\n local: 'a linked slicc exit that fetches without CORS',\n remote: 'a linked slicc exit on another device that fetches without CORS',\n tailnet: \"your tailnet's exit node, which fetches without CORS\",\n};\n\nexport function transportName(transport: Transport | undefined): string {\n const exit = linkedExit(transport);\n if (exit) return EXITS[exit.kind] ?? 'a linked exit that fetches without CORS';\n if (pageOnly(transport)) return \"the page's own fetch, so only servers that allow CORS answer\";\n if (transport?.traits?.manualRedirects) return 'a local proxy that fetches without CORS';\n return 'a relay that fetches without CORS';\n}\n\nexport async function agentVersion(\n fetcher: (url: URL) => Promise<Response>,\n url = new URL('../package.json', import.meta.url)\n): Promise<string> {\n try {\n const response = await fetcher(url);\n const manifest = response.ok ? ((await response.json()) as { version?: string }) : {};\n return manifest.version ?? 'unknown';\n } catch {\n return 'unknown';\n }\n}\n\nexport function systemSection(facts: SystemFacts): string {\n const missing = RUNTIMES.filter((name) => !facts.commands.includes(name));\n return [\n `You are SLICC's agent in seven: slicc-agent ${facts.version}, installed in /opt/agent. Your bash runs on the page's shared slicc-kernel, a WebAssembly sandbox in the user's browser, not on a server or the user's machine.`,\n \"Files: / is the browser's private file system (OPFS). Work in /home and /tmp. /os and /opt are the system; change them only when asked.\",\n `Commands on PATH: ${facts.commands.join(' ') || 'none found'}.`,\n \"Install command-line tools with `pnpm add -g <package>`. There is no ipk. Tested packages that aren't preinstalled: `@ai-ecoverse/wasm-git` (git), `@ai-ecoverse/wasi-esbuild` (esbuild), `@ai-ecoverse/wasi-typescript` (tsc, TypeScript 7) and `@ai-ecoverse/wasi-biome` (biome: check, format, lint). PDFs: `@ai-ecoverse/wasm-poppler` (pdftotext, pdfinfo, pdftoppm, pdfimages, pdfunite, pdfseparate) and `@ai-ecoverse/wasm-qpdf` (qpdf: merge, split, rotate, encrypt). Python: `@ai-ecoverse/wasix-python` (python3, pip); `@ai-ecoverse/wasix-uv-shim@0.1.0-1` adds `uv` (a shim over pip and venv, not Astral's uv: venv, pip, run, init, add, remove, sync), and only `uv run` uses the venv for now.\",\n `Network: requests go through ${facts.transport}. localhost and 127.0.0.1 are this sandbox's own loopback, not the user's computer.`,\n ...(facts.browser\n ? [\n `Browser: one may be available (SLICC_CDP_URL is set), but nothing has checked that one is attached, so don't tell the user it's connected. ${facts.commands.includes('curlwright') ? 'playwright-cli and curlwright drive' : 'playwright-cli drives'} the user's own browser through the SLICC extension, with their logins. Read the browser skill and run its check before you use it.`,\n ]\n : []),\n facts.commands.includes('git')\n ? 'Git: local repositories work (init, add, commit, status, diff, restore, branch, checkout, log). Clone, fetch and push over HTTPS need slicc linked or the SLICC extension connected; through the page alone they fail with a CORS or 502 error.'\n : 'Git: not installed. When you need it, install it with `pnpm add -g @ai-ecoverse/wasm-git`.',\n `Not here yet: ${[...missing, ...(facts.browser ? [] : ['a browser or CDP tool']), 'GitHub credentials'].join(', ')}.`,\n ].join('\\n');\n}\n\nexport async function kernelBoot(client: KernelClient): Promise<string | null> {\n const decoder = new TextDecoder();\n let out = '';\n try {\n const process = await client.spawn(['cat', '/proc/stat'], {\n onStdout: (bytes) => {\n out += decoder.decode(bytes, { stream: true });\n },\n });\n await process.exited;\n } catch {\n return null;\n }\n return /^btime (\\d+)$/m.exec(out)?.[1] ?? null;\n}\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,YAAY,gBAAgC;AASrD,MAAM,YAAY;AAClB,MAAM,WAAW,CAAC,QAAQ,SAAS;AAEnC,eAAsB,eAAe,QAAyC;AAC5E,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,MAAM;AACV,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,MAAM,CAAC,QAAQ,MAAM,SAAS,GAAG;AAAA,MAC5D,UAAU,CAAC,UAAU;AACnB,eAAO,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,MAC/C;AAAA,IACF,CAAC;AACD,UAAM,QAAQ;AAAA,EAChB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,IAAI,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AACvD,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,OAAO,OAAO,CAAC,CAAC,EAAE,KAAK;AAClD;AAEA,MAAM,UAAU;AAEhB,eAAsB,iBAAiB,QAAwC;AAC7E,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,MAAM,CAAC,QAAQ,MAAM,OAAO,GAAG,CAAC,CAAC;AAC9D,WAAQ,MAAM,QAAQ,WAAY;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,MAAM,QAAgC;AAAA,EACpC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,SAAS;AACX;AAEO,SAAS,cAAc,WAA0C;AACtE,QAAM,OAAO,WAAW,SAAS;AACjC,MAAI,KAAM,QAAO,MAAM,KAAK,IAAI,KAAK;AACrC,MAAI,SAAS,SAAS,EAAG,QAAO;AAChC,MAAI,WAAW,QAAQ,gBAAiB,QAAO;AAC/C,SAAO;AACT;AAEA,eAAsB,aACpB,SACA,MAAM,IAAI,IAAI,mBAAmB,YAAY,GAAG,GAC/B;AACjB,MAAI;AACF,UAAM,WAAW,MAAM,QAAQ,GAAG;AAClC,UAAM,WAAW,SAAS,KAAO,MAAM,SAAS,KAAK,IAA8B,CAAC;AACpF,WAAO,SAAS,WAAW;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,cAAc,OAA4B;AACxD,QAAM,UAAU,SAAS,OAAO,CAAC,SAAS,CAAC,MAAM,SAAS,SAAS,IAAI,CAAC;AACxE,SAAO;AAAA,IACL,+CAA+C,MAAM,OAAO;AAAA,IAC5D;AAAA,IACA,qBAAqB,MAAM,SAAS,KAAK,GAAG,KAAK,YAAY;AAAA,IAC7D;AAAA,IACA,gCAAgC,MAAM,SAAS;AAAA,IAC/C,GAAI,MAAM,UACN;AAAA,MACE,8IAA8I,MAAM,SAAS,SAAS,YAAY,IAAI,wCAAwC,uBAAuB;AAAA,IACvP,IACA,CAAC;AAAA,IACL,MAAM,SAAS,SAAS,KAAK,IACzB,oPACA;AAAA,IACJ,iBAAiB,CAAC,GAAG,SAAS,GAAI,MAAM,UAAU,CAAC,IAAI,CAAC,uBAAuB,GAAI,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,EACrH,EAAE,KAAK,IAAI;AACb;AAEA,eAAsB,WAAW,QAA8C;AAC7E,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,MAAM;AACV,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,MAAM,CAAC,OAAO,YAAY,GAAG;AAAA,MACxD,UAAU,CAAC,UAAU;AACnB,eAAO,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,MAC/C;AAAA,IACF,CAAC;AACD,UAAM,QAAQ;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO,iBAAiB,KAAK,GAAG,IAAI,CAAC,KAAK;AAC5C;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|