@ai-ecoverse/slicc-agent 3.43.1 → 3.45.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 (66) hide show
  1. package/README.md +13 -2
  2. package/dist/agent.js +1 -0
  3. package/dist/agent.js.map +2 -2
  4. package/dist/client.js +3 -1
  5. package/dist/client.js.map +2 -2
  6. package/dist/codemode/index.js +2 -1
  7. package/dist/codemode/index.js.map +2 -2
  8. package/dist/control.js +13 -3
  9. package/dist/control.js.map +2 -2
  10. package/dist/freezer/index.js +5 -4
  11. package/dist/freezer/index.js.map +2 -2
  12. package/dist/host.js +13 -2
  13. package/dist/host.js.map +2 -2
  14. package/dist/kernel/env.js +55 -4
  15. package/dist/kernel/env.js.map +2 -2
  16. package/dist/kernel/exec.js +84 -16
  17. package/dist/kernel/exec.js.map +3 -3
  18. package/dist/licks/licks.js +17 -1
  19. package/dist/licks/licks.js.map +2 -2
  20. package/dist/main.js +29 -10
  21. package/dist/main.js.map +2 -2
  22. package/dist/mcp/content.js +3 -1
  23. package/dist/mcp/content.js.map +2 -2
  24. package/dist/mcp/tools.js +2 -1
  25. package/dist/mcp/tools.js.map +2 -2
  26. package/dist/memory/prompt.js +3 -2
  27. package/dist/memory/prompt.js.map +2 -2
  28. package/dist/memory/store.js +5 -3
  29. package/dist/memory/store.js.map +2 -2
  30. package/dist/remote/host.js +21 -1
  31. package/dist/remote/host.js.map +2 -2
  32. package/dist/secrets/extension.js +147 -0
  33. package/dist/secrets/extension.js.map +7 -0
  34. package/dist/secrets/names.js +72 -0
  35. package/dist/secrets/names.js.map +7 -0
  36. package/dist/secrets/scrub.js +36 -0
  37. package/dist/secrets/scrub.js.map +7 -0
  38. package/dist/secrets/vault.js +162 -0
  39. package/dist/secrets/vault.js.map +7 -0
  40. package/dist/secrets/view.js +15 -0
  41. package/dist/secrets/view.js.map +7 -0
  42. package/dist/services.js.map +2 -2
  43. package/dist/skills/index.js +8 -1
  44. package/dist/skills/index.js.map +2 -2
  45. package/dist/spectrum/agent-port.js +67 -6
  46. package/dist/spectrum/agent-port.js.map +2 -2
  47. package/dist/spectrum/messages.js +13 -0
  48. package/dist/spectrum/messages.js.map +2 -2
  49. package/dist/types/agent.d.ts +1 -0
  50. package/dist/types/client.d.ts +2 -0
  51. package/dist/types/control.d.ts +2 -1
  52. package/dist/types/host.d.ts +9 -1
  53. package/dist/types/kernel/env.d.ts +6 -0
  54. package/dist/types/kernel/exec.d.ts +8 -1
  55. package/dist/types/licks/licks.d.ts +1 -0
  56. package/dist/types/mcp/content.d.ts +1 -1
  57. package/dist/types/remote/host.d.ts +5 -1
  58. package/dist/types/secrets/extension.d.ts +31 -0
  59. package/dist/types/secrets/names.d.ts +24 -0
  60. package/dist/types/secrets/scrub.d.ts +21 -0
  61. package/dist/types/secrets/vault.d.ts +30 -0
  62. package/dist/types/secrets/view.d.ts +9 -0
  63. package/dist/types/services.d.ts +3 -1
  64. package/dist/types/skills/index.d.ts +1 -0
  65. package/dist/types/spectrum/agent-port.d.ts +9 -1
  66. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/skills/index.ts"],
4
- "sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport {\n defineExtension,\n type Extension,\n type Registry,\n section,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Licks } from '../licks/licks.ts';\nimport { manifestDirs } from '../roles/roles.ts';\nimport type { Command } from '../services.ts';\nimport {\n type Diagnostic,\n expandSkillCommand,\n formatSkillsForPrompt,\n loadSkills,\n type Skill,\n type SkillRoot,\n} from './skills.ts';\nimport { expandPromptTemplate, loadTemplates, type PromptTemplate } from './templates.ts';\n\nexport const BUILTIN_SKILLS = [\n 'agent',\n 'browser',\n 'gelatiere',\n 'licks',\n 'memory',\n 'skill-authoring',\n 'sprinkles',\n 'welcome',\n];\nexport const BUILTIN_PROMPTS = ['parallel-review', 'review-loop'];\nexport const SKILLS_DIR = '/var/lib/slicc/agent/skills';\nexport const PROMPTS_DIR = '/var/lib/slicc/agent/prompts';\nexport const GLOBAL_DIR = '/usr/share/skills';\nexport const RELOAD_MS = 300;\n\nexport interface SkillsRuntime {\n readonly commands: ReplicatedState<Command[]>;\n skills(): readonly Skill[];\n dirs(): string[];\n templates(): readonly PromptTemplate[];\n expand(text: string, context: Context): Promise<string>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface SkillsAttach {\n env: ExecutionEnv;\n home: string;\n assets?: (path: string) => Promise<string>;\n reloadMs: number;\n}\n\nexport interface SkillsSetup {\n extension: Extension;\n attach(options: SkillsAttach, context: Context): Promise<SkillsRuntime>;\n}\n\ntype Manifest = { pi?: { skills?: unknown; prompts?: unknown } };\n\nexport function piResources(dir: string, text: string, kind: 'skills' | 'prompts'): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const listed = manifest.pi?.[kind];\n const paths = Array.isArray(listed) ? listed : typeof listed === 'string' ? [listed] : [];\n return paths\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nasync function packaged(env: ExecutionEnv, kind: 'skills' | 'prompts', context: Context) {\n const out: string[] = [];\n for (const dir of await manifestDirs(env, '/node_modules', context)) {\n const read = await env.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...piResources(dir, read.value, kind));\n }\n return out;\n}\n\nasync function installBuiltins(\n env: ExecutionEnv,\n assets: (path: string) => Promise<string>,\n context: Context\n): Promise<void> {\n await env.remove(SKILLS_DIR, { recursive: true, force: true }, context);\n await env.remove(PROMPTS_DIR, { recursive: true, force: true }, context);\n for (const name of BUILTIN_SKILLS) {\n const text = await assets(`packages/vfs-root/skills/${name}/SKILL.md`).catch(() => undefined);\n if (text === undefined) continue;\n await env.createDir(`${SKILLS_DIR}/${name}`, { recursive: true }, context);\n await env.writeFile(`${SKILLS_DIR}/${name}/SKILL.md`, text, context);\n }\n await env.createDir(PROMPTS_DIR, { recursive: true }, context);\n for (const name of BUILTIN_PROMPTS) {\n const text = await assets(`packages/vfs-root/prompts/${name}.md`).catch(() => undefined);\n if (text !== undefined) await env.writeFile(`${PROMPTS_DIR}/${name}.md`, text, context);\n }\n}\n\nexport function problemLick(problem: Diagnostic, home: string) {\n const path = problem.path.startsWith(`${home}/`)\n ? `~${problem.path.slice(home.length)}`\n : problem.path;\n return {\n channel: 'fswatch' as const,\n source: `skills:${path}`,\n title: `Skill or prompt template problem: ${path}`,\n text: problem.message,\n body: 'The file is used with this problem, or skipped if it has no description.\\nThe rules are in the slicc-agent README.',\n target: 'cone' as const,\n severity: 'warn' as const,\n eventId: `${path}\\n${problem.message}`,\n };\n}\n\nexport function commandsOf(\n skills: readonly Skill[],\n templates: readonly PromptTemplate[]\n): Command[] {\n return [\n ...templates.map((template) => ({\n name: template.name,\n description: template.description,\n kind: 'prompt' as const,\n })),\n ...skills.map((skill) => ({\n name: `skill:${skill.name}`,\n description: skill.description,\n kind: 'skill' as const,\n })),\n ];\n}\n\nexport function setupSkills(registry: Registry, licks: Licks): SkillsSetup {\n let current: Skill[] = [];\n const extension = defineExtension({\n name: 'slicc-skills',\n sections: [section('skills', async () => formatSkillsForPrompt(current) || undefined)],\n });\n registry.install(extension);\n return {\n extension,\n async attach(options, context) {\n const { env, home } = options;\n if (options.assets)\n await installBuiltins(env, options.assets, context).catch(() => undefined);\n await env.exec(`mkdir -p ${GLOBAL_DIR} && chmod 755 ${GLOBAL_DIR}`, undefined, context);\n let templates: PromptTemplate[] = [];\n const commands = replicatedState<Command[]>([]);\n const reported = new Set<string>();\n const reload = async (using: Context) => {\n const roots: SkillRoot[] = [\n { dir: `${home}/.pi/agent/skills`, source: 'user' },\n { dir: `${home}/.agents/skills`, source: 'user' },\n { dir: GLOBAL_DIR, source: 'global' },\n ...(await packaged(env, 'skills', using)).map((dir) => ({\n dir,\n source: 'package' as const,\n })),\n { dir: SKILLS_DIR, source: 'builtin' },\n ];\n const loaded = await loadSkills(env, roots, using);\n const prompts = await loadTemplates(\n env,\n [`${home}/.pi/agent/prompts`, ...(await packaged(env, 'prompts', using)), PROMPTS_DIR],\n using\n );\n current = loaded.skills;\n templates = prompts.templates;\n commands.replace(using, commandsOf(current, templates));\n for (const problem of [...loaded.diagnostics, ...prompts.diagnostics]) {\n const key = `${problem.path}\\n${problem.message}`;\n if (reported.has(key)) continue;\n reported.add(key);\n await licks.deliver(problemLick(problem, home), using).catch(() => undefined);\n }\n };\n await reload(context);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const schedule = () => {\n clearTimeout(timer);\n timer = setTimeout(() => void reload(context).catch(() => undefined), options.reloadMs);\n };\n const watched = await env.watch(\n [\n { path: `${home}/.pi/agent/skills`, recursive: true },\n { path: `${home}/.pi/agent/prompts` },\n { path: `${home}/.agents/skills`, recursive: true },\n { path: GLOBAL_DIR, recursive: true },\n ],\n schedule,\n context\n );\n const watcher: FileWatcher | undefined = watched.ok ? watched.value : undefined;\n return {\n commands,\n skills: () => current,\n dirs: () => current.map((skill) => skill.baseDir),\n templates: () => templates,\n async expand(text, using) {\n const expanded = await expandSkillCommand(text, current, env, using);\n return expanded === text ? expandPromptTemplate(text, templates) : expanded;\n },\n reload,\n async close(using) {\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { type Context, type ReplicatedState, replicatedState } from '@earendil-works/chord';\nimport {\n defineExtension,\n type Extension,\n type Registry,\n section,\n} from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Licks } from '../licks/licks.ts';\nimport { manifestDirs } from '../roles/roles.ts';\nimport type { Command } from '../services.ts';\nimport {\n type Diagnostic,\n expandSkillCommand,\n formatSkillsForPrompt,\n loadSkills,\n type Skill,\n type SkillRoot,\n} from './skills.ts';\nimport { expandPromptTemplate, loadTemplates, type PromptTemplate } from './templates.ts';\n\nexport const BUILTIN_SKILLS = [\n 'agent',\n 'browser',\n 'gelatiere',\n 'licks',\n 'memory',\n 'skill-authoring',\n 'sprinkles',\n 'welcome',\n];\nexport const BUILTIN_PROMPTS = ['parallel-review', 'review-loop'];\nexport const SKILLS_DIR = '/var/lib/slicc/agent/skills';\nexport const PROMPTS_DIR = '/var/lib/slicc/agent/prompts';\nexport const GLOBAL_DIR = '/usr/share/skills';\nexport const RELOAD_MS = 300;\n\nexport interface SkillsRuntime {\n readonly commands: ReplicatedState<Command[]>;\n skills(): readonly Skill[];\n dirs(): string[];\n templates(): readonly PromptTemplate[];\n expand(text: string, context: Context): Promise<string>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface SkillsAttach {\n env: ExecutionEnv;\n home: string;\n assets?: (path: string) => Promise<string>;\n reloadMs: number;\n}\n\nexport interface SkillsSetup {\n extension: Extension;\n attach(options: SkillsAttach, context: Context): Promise<SkillsRuntime>;\n}\n\ntype Manifest = { pi?: { skills?: unknown; prompts?: unknown } };\n\nexport function piResources(dir: string, text: string, kind: 'skills' | 'prompts'): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const listed = manifest.pi?.[kind];\n const paths = Array.isArray(listed) ? listed : typeof listed === 'string' ? [listed] : [];\n return paths\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nasync function packaged(env: ExecutionEnv, kind: 'skills' | 'prompts', context: Context) {\n const out: string[] = [];\n for (const dir of await manifestDirs(env, '/node_modules', context)) {\n const read = await env.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...piResources(dir, read.value, kind));\n }\n return out;\n}\n\nasync function installBuiltins(\n env: ExecutionEnv,\n assets: (path: string) => Promise<string>,\n context: Context\n): Promise<void> {\n await env.remove(SKILLS_DIR, { recursive: true, force: true }, context);\n await env.remove(PROMPTS_DIR, { recursive: true, force: true }, context);\n for (const name of BUILTIN_SKILLS) {\n const text = await assets(`packages/vfs-root/skills/${name}/SKILL.md`).catch(() => undefined);\n if (text === undefined) continue;\n await env.createDir(`${SKILLS_DIR}/${name}`, { recursive: true }, context);\n await env.writeFile(`${SKILLS_DIR}/${name}/SKILL.md`, text, context);\n }\n await env.createDir(PROMPTS_DIR, { recursive: true }, context);\n for (const name of BUILTIN_PROMPTS) {\n const text = await assets(`packages/vfs-root/prompts/${name}.md`).catch(() => undefined);\n if (text !== undefined) await env.writeFile(`${PROMPTS_DIR}/${name}.md`, text, context);\n }\n}\n\nexport function problemLick(problem: Diagnostic, home: string) {\n const path = problem.path.startsWith(`${home}/`)\n ? `~${problem.path.slice(home.length)}`\n : problem.path;\n return {\n channel: 'fswatch' as const,\n source: `skills:${path}`,\n title: `Skill or prompt template problem: ${path}`,\n text: problem.message,\n body: 'The file is used with this problem, or skipped if it has no description.\\nThe rules are in the slicc-agent README.',\n target: 'cone' as const,\n severity: 'warn' as const,\n eventId: `${path}\\n${problem.message}`,\n };\n}\n\nexport const SECRETS_ACTION: Command = {\n name: 'secrets',\n description: 'List the secrets the agent can use, and where each works',\n kind: 'action',\n};\n\nexport function commandsOf(\n skills: readonly Skill[],\n templates: readonly PromptTemplate[]\n): Command[] {\n return [\n ...templates.map((template) => ({\n name: template.name,\n description: template.description,\n kind: 'prompt' as const,\n })),\n ...skills.map((skill) => ({\n name: `skill:${skill.name}`,\n description: skill.description,\n kind: 'skill' as const,\n })),\n SECRETS_ACTION,\n ];\n}\n\nexport function setupSkills(registry: Registry, licks: Licks): SkillsSetup {\n let current: Skill[] = [];\n const extension = defineExtension({\n name: 'slicc-skills',\n sections: [section('skills', async () => formatSkillsForPrompt(current) || undefined)],\n });\n registry.install(extension);\n return {\n extension,\n async attach(options, context) {\n const { env, home } = options;\n if (options.assets)\n await installBuiltins(env, options.assets, context).catch(() => undefined);\n await env.exec(`mkdir -p ${GLOBAL_DIR} && chmod 755 ${GLOBAL_DIR}`, undefined, context);\n let templates: PromptTemplate[] = [];\n const commands = replicatedState<Command[]>([]);\n const reported = new Set<string>();\n const reload = async (using: Context) => {\n const roots: SkillRoot[] = [\n { dir: `${home}/.pi/agent/skills`, source: 'user' },\n { dir: `${home}/.agents/skills`, source: 'user' },\n { dir: GLOBAL_DIR, source: 'global' },\n ...(await packaged(env, 'skills', using)).map((dir) => ({\n dir,\n source: 'package' as const,\n })),\n { dir: SKILLS_DIR, source: 'builtin' },\n ];\n const loaded = await loadSkills(env, roots, using);\n const prompts = await loadTemplates(\n env,\n [`${home}/.pi/agent/prompts`, ...(await packaged(env, 'prompts', using)), PROMPTS_DIR],\n using\n );\n current = loaded.skills;\n templates = prompts.templates;\n commands.replace(using, commandsOf(current, templates));\n for (const problem of [...loaded.diagnostics, ...prompts.diagnostics]) {\n const key = `${problem.path}\\n${problem.message}`;\n if (reported.has(key)) continue;\n reported.add(key);\n await licks.deliver(problemLick(problem, home), using).catch(() => undefined);\n }\n };\n await reload(context);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const schedule = () => {\n clearTimeout(timer);\n timer = setTimeout(() => void reload(context).catch(() => undefined), options.reloadMs);\n };\n const watched = await env.watch(\n [\n { path: `${home}/.pi/agent/skills`, recursive: true },\n { path: `${home}/.pi/agent/prompts` },\n { path: `${home}/.agents/skills`, recursive: true },\n { path: GLOBAL_DIR, recursive: true },\n ],\n schedule,\n context\n );\n const watcher: FileWatcher | undefined = watched.ok ? watched.value : undefined;\n return {\n commands,\n skills: () => current,\n dirs: () => current.map((skill) => skill.baseDir),\n templates: () => templates,\n async expand(text, using) {\n const expanded = await expandSkillCommand(text, current, env, using);\n return expanded === text ? expandPromptTemplate(text, templates) : expanded;\n },\n reload,\n async close(using) {\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
2
2
  import { entryLick } from "../licks/state.js";
3
+ import { vaultHold } from "../secrets/view.js";
3
4
  import { Emitter } from "./emitter.js";
4
5
  import { isBusy, queued, toMessages } from "./messages.js";
5
6
  const CONE = "cone";
@@ -20,15 +21,32 @@ function status(view, messages) {
20
21
  const last = messages.at(-1);
21
22
  return last?.role === "assistant" && last.status === "error" ? "error" : "idle";
22
23
  }
24
+ function slashCommand({ kind, ...command }) {
25
+ return kind === "action" ? command : { ...command, kind };
26
+ }
27
+ function sameHold(a, b) {
28
+ return a === b || a !== null && b !== null && a.reason === b.reason && a.held === b.held;
29
+ }
23
30
  class AgentAdapter extends Emitter {
24
31
  #connection;
25
32
  #ready;
26
33
  #messages = /* @__PURE__ */ new Map();
27
34
  #active = null;
28
35
  #creating = /* @__PURE__ */ new Map();
36
+ #hold = null;
37
+ #outbox = /* @__PURE__ */ new Map();
29
38
  constructor(connection) {
30
39
  super();
31
40
  this.#connection = connection;
41
+ this.#hold = this.hold();
42
+ connection.vault?.subscribe(() => {
43
+ const next = this.hold();
44
+ if (sameHold(next, this.#hold)) return;
45
+ this.#hold = next;
46
+ if (!next) for (const pending of this.#outbox.values()) pending.release();
47
+ this.emit("hold", next);
48
+ this.emit("agents", this.list());
49
+ });
32
50
  connection.frozen?.subscribe(() => {
33
51
  this.emit("frozen", this.frozen());
34
52
  this.emit("agents", this.list());
@@ -80,6 +98,9 @@ class AgentAdapter extends Emitter {
80
98
  ready() {
81
99
  return this.#ready;
82
100
  }
101
+ hold() {
102
+ return vaultHold(this.#connection.vault?.value);
103
+ }
83
104
  list() {
84
105
  const rows = this.#connection.frozen?.value ?? [];
85
106
  return this.#summary().map((summary) => {
@@ -91,7 +112,7 @@ class AgentAdapter extends Emitter {
91
112
  name: summary.role ? `${summary.name} \xB7 ${summary.role}` : summary.name,
92
113
  kind: summary.kind,
93
114
  parentId: summary.parentId,
94
- status: status(view, this.#messages.get(summary.id) ?? []),
115
+ status: this.#status(summary.id, status(view, this.#messages.get(summary.id) ?? [])),
95
116
  model: doc?.model ? `${doc.model.provider}/${doc.model.modelId}` : "",
96
117
  contextFill: 0,
97
118
  unread: 0,
@@ -126,6 +147,9 @@ class AgentAdapter extends Emitter {
126
147
  const outgoing = typeof input === "string" ? { text: input } : input;
127
148
  const target = this.#creating.has(agentId) ? await this.#creating.get(agentId) : agentId;
128
149
  if (target === null) throw new Error("The scoop could not be created.");
150
+ const pending = target && this.#held(target) ? this.#pending(target, outgoing) : void 0;
151
+ if (pending) await pending.released;
152
+ if (pending?.dropped) return this.#settle(pending);
129
153
  const sent = await this.#connection.control.send(
130
154
  {
131
155
  text: outgoing.text,
@@ -134,8 +158,30 @@ class AgentAdapter extends Emitter {
134
158
  agentId: target || null
135
159
  },
136
160
  BACKGROUND_CONTEXT
137
- );
161
+ ).finally(() => pending && this.#settle(pending));
138
162
  if (!sent.accepted) throw new Error(sent.error.message);
163
+ if (pending?.dropped)
164
+ void this.#connection.control.unqueue(pending.agentId, sent.submissionId, BACKGROUND_CONTEXT);
165
+ }
166
+ #pending(agentId, outgoing) {
167
+ const id = `p${crypto.randomUUID()}`;
168
+ const message = {
169
+ id,
170
+ role: "user",
171
+ text: outgoing.text,
172
+ createdAt: Date.now(),
173
+ queued: true,
174
+ mode: outgoing.mode === "queue" ? "queue" : "steer"
175
+ };
176
+ const { promise: released, resolve: release } = Promise.withResolvers();
177
+ const pending = { agentId, message, dropped: false, release, released };
178
+ this.#outbox.set(id, pending);
179
+ this.emit("messages", agentId);
180
+ return pending;
181
+ }
182
+ #settle(pending) {
183
+ this.#outbox.delete(pending.message.id);
184
+ this.emit("messages", pending.agentId);
139
185
  }
140
186
  async rewind(agentId, messageId) {
141
187
  const rewound = await this.#connection.control.rewindAgent(
@@ -149,12 +195,26 @@ class AgentAdapter extends Emitter {
149
195
  void this.#connection.control.stopAgent(agentId, BACKGROUND_CONTEXT);
150
196
  }
151
197
  busy(agentId = this.active()) {
152
- return isBusy(this.#view(agentId));
198
+ return isBusy(this.#view(agentId)) || this.#held(agentId);
199
+ }
200
+ #status(agentId, shown) {
201
+ return shown === "idle" && this.#held(agentId) ? "working" : shown;
202
+ }
203
+ #held(agentId) {
204
+ return this.#hold !== null && agentId === (this.#connection.agents?.value?.active ?? CONE);
153
205
  }
154
206
  queue(agentId = this.active()) {
155
- return queued(this.#view(agentId));
207
+ const pending = [...this.#outbox.values()].filter((item) => item.agentId === agentId && !item.dropped).map((item) => item.message);
208
+ return [...queued(this.#view(agentId)), ...pending];
156
209
  }
157
210
  unqueue(agentId, messageId) {
211
+ const pending = this.#outbox.get(messageId);
212
+ if (pending) {
213
+ pending.dropped = true;
214
+ pending.release();
215
+ this.emit("messages", pending.agentId);
216
+ return;
217
+ }
158
218
  void this.#connection.control.unqueue(agentId, messageId.replace(/^q/, ""), BACKGROUND_CONTEXT);
159
219
  }
160
220
  suggestion() {
@@ -204,7 +264,7 @@ class AgentAdapter extends Emitter {
204
264
  return [];
205
265
  }
206
266
  commands() {
207
- return (this.#connection.commands?.value ?? []).map((command) => ({ ...command }));
267
+ return (this.#connection.commands?.value ?? []).map(slashCommand);
208
268
  }
209
269
  createScoop(parentId, name) {
210
270
  const provisional = `scoop:creating-${crypto.randomUUID()}`;
@@ -302,6 +362,7 @@ class AgentAdapter extends Emitter {
302
362
  }
303
363
  export {
304
364
  AgentAdapter,
305
- CONE
365
+ CONE,
366
+ slashCommand
306
367
  };
307
368
  //# sourceMappingURL=agent-port.js.map
@@ -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 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 { AgentSettingsChange, AgentSummary } from '../services.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 class AgentAdapter extends Emitter<AgentEvents> 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\n constructor(connection: AgentConnection) {\n super();\n this.#connection = connection;\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()])\n if (!this.#summary().some((summary) => summary.id === id)) this.#messages.delete(id);\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 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: 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') void this.#connection.control.selectCone(id, BACKGROUND_CONTEXT);\n this.emit('active', id);\n this.emit('messages', id);\n }\n\n messages(agentId: string = this.active()): readonly Message[] {\n return this.#messages.get(agentId) ?? [];\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 sent = await this.#connection.control.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 if (!sent.accepted) throw new Error(sent.error.message);\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 void this.#connection.control.stopAgent(agentId, BACKGROUND_CONTEXT);\n }\n\n busy(agentId: string = this.active()): boolean {\n return isBusy(this.#view(agentId));\n }\n\n queue(agentId: string = this.active()): readonly UserMessage[] {\n return queued(this.#view(agentId));\n }\n\n unqueue(agentId: string, messageId: string): void {\n void this.#connection.control.unqueue(agentId, messageId.replace(/^q/, ''), BACKGROUND_CONTEXT);\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 void this.#connection.control.resolveAgentLick(agentId, lick.id, state, BACKGROUND_CONTEXT);\n }\n\n compact(agentId: string = this.active()): void {\n void this.#connection.control.compactAgent(agentId, null, BACKGROUND_CONTEXT);\n }\n\n clear(agentId: string = this.active()): void {\n void this.#connection.control.newChat(agentId, BACKGROUND_CONTEXT);\n }\n\n freeze(agentId: string = this.active()): void {\n void this.#connection.control.freeze(agentId, BACKGROUND_CONTEXT);\n }\n\n #configure(agentId: string, change: Partial<AgentSettingsChange>): void {\n void this.#connection.control.configure(\n {\n model: change.model ?? null,\n thinkingLevel: change.thinkingLevel ?? null,\n agentId,\n },\n BACKGROUND_CONTEXT\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((command) => ({ ...command }));\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 void this.#connection.control.discard(id, BACKGROUND_CONTEXT);\n }\n}\n"],
5
- "mappings": "AAYA,SAAS,0BAA0B;AAGnC,SAAS,iBAAiB;AAE1B,SAAS,eAAe;AACxB,SAAS,QAAQ,QAAQ,kBAAkB;AAEpC,MAAM,OAAO;AAEpB,MAAM,WAAqC;AAAA,EACzC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AACP;AAOA,SAAS,OAAO,MAAoC,UAA2C;AAC7F,MAAI,OAAO,IAAI,GAAG;AAChB,UAAM,OAAO,MAAM,KAAK,SAAS;AACjC,WAAO,MAAM,OAAO,KAAK,CAAC,SAAS,KAAK,WAAW,SAAS,IAAI,YAAY;AAAA,EAC9E;AACA,QAAM,OAAO,SAAS,GAAG,EAAE;AAC3B,SAAO,MAAM,SAAS,eAAe,KAAK,WAAW,UAAU,UAAU;AAC3E;AAEO,MAAM,qBAAqB,QAA0C;AAAA,EACjE;AAAA,EACA;AAAA,EACA,YAAY,oBAAI,IAAuB;AAAA,EAChD,UAAyB;AAAA,EACzB,YAAY,oBAAI,IAAoC;AAAA,EAEpD,YAAY,YAA6B;AACvC,UAAM;AACN,SAAK,cAAc;AACnB,eAAW,QAAQ,UAAU,MAAM;AACjC,WAAK,KAAK,UAAU,KAAK,OAAO,CAAC;AACjC,WAAK,KAAK,UAAU,KAAK,KAAK,CAAC;AAAA,IACjC,CAAC;AACD,SAAK,SAAS,IAAI,QAAQ,CAAC,YAAY;AACrC,iBAAW,WAAW,UAAU,MAAM;AACpC,aAAK,SAAS;AACd,gBAAQ;AAAA,MACV,CAAC;AACD,iBAAW,WAAW,UAAU,MAAM,KAAK,SAAS,CAAC;AACrD,iBAAW,OAAO,UAAU,MAAM,KAAK,SAAS,CAAC;AACjD,iBAAW,QAAQ,UAAU,MAAM,KAAK,SAAS,CAAC;AAAA,IACpD,CAAC;AAAA,EACH;AAAA,EAEA,WAAoC;AAClC,UAAM,SAAS,KAAK,YAAY,QAAQ,OAAO;AAC/C,WAAO,QAAQ,SACX,SACA,CAAC,EAAE,IAAI,MAAM,MAAM,UAAU,MAAM,QAAQ,UAAU,MAAM,MAAM,KAAK,CAAC;AAAA,EAC7E;AAAA,EAEA,MAAM,UAAkB,KAAK,OAAO,GAAiC;AACnE,UAAM,QAAQ,KAAK,YAAY,OAAO;AACtC,UAAM,OAAO,QAAQ,OAAO;AAC5B,QAAI,KAAM,QAAO;AACjB,UAAM,OAAO,KAAK,YAAY,QAAQ,OAAO,UAAU;AACvD,WAAO,YAAY,OAAO,KAAK,YAAY,WAAW,QAAQ;AAAA,EAChE;AAAA,EAEA,WAAiB;AACf,SAAK,YAAY,KAAK,YAAY,QAAQ,OAAO,UAAU;AAC3D,SAAK,KAAK,UAAU,KAAK,KAAK,CAAC;AAC/B,eAAW,WAAW,KAAK,SAAS,EAAG,MAAK,QAAQ,QAAQ,EAAE;AAC9D,eAAW,MAAM,CAAC,GAAG,KAAK,UAAU,KAAK,CAAC;AACxC,UAAI,CAAC,KAAK,SAAS,EAAE,KAAK,CAAC,YAAY,QAAQ,OAAO,EAAE,EAAG,MAAK,UAAU,OAAO,EAAE;AAAA,EACvF;AAAA,EAEA,QAAQ,SAAuB;AAC7B,UAAM,OAAO,KAAK,MAAM,OAAO;AAC/B,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC;AAC/C,UAAM,QAAQ,WAAW,MAAM,KAAK,YAAY,WAAW,KAAK;AAChE,SAAK,UAAU,IAAI,SAAS,KAAK;AACjC,QAAI,OAAO,WAAW,MAAM,QAAQ;AAClC,WAAK,KAAK,YAAY,OAAO;AAC7B;AAAA,IACF;AACA,UAAM,UAAU,MAAM;AAAA,MACpB,CAAC,SAAS,UAAU,KAAK,UAAU,OAAO,MAAM,KAAK,UAAU,OAAO,KAAK,CAAC;AAAA,IAC9E;AACA,QAAI,QAAQ,WAAW,EAAG,MAAK,KAAK,WAAW,EAAE,SAAS,SAAS,QAAQ,CAAC,EAAa,CAAC;AAAA,aACjF,QAAQ,SAAS,EAAG,MAAK,KAAK,YAAY,OAAO;AAAA,EAC5D;AAAA,EAEA,QAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAyB;AACvB,UAAM,OAAO,KAAK,YAAY,QAAQ,SAAS,CAAC;AAChD,WAAO,KAAK,SAAS,EAAE,IAAI,CAAC,YAAY;AACtC,YAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,YAAM,MAAM,MAAM,KAAK,UAAU;AACjC,YAAM,QACJ,QAAQ,SAAS,SAAS,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,QAAQ,EAAE,GAAG,QAAQ;AAC/E,aAAO;AAAA,QACL,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ,OAAO,GAAG,QAAQ,IAAI,SAAM,QAAQ,IAAI,KAAK,QAAQ;AAAA,QACnE,MAAM,QAAQ;AAAA,QACd,UAAU,QAAQ;AAAA,QAClB,QAAQ,OAAO,MAAM,KAAK,UAAU,IAAI,QAAQ,EAAE,KAAK,CAAC,CAAC;AAAA,QACzD,OAAO,KAAK,QAAQ,GAAG,IAAI,MAAM,QAAQ,IAAI,IAAI,MAAM,OAAO,KAAK;AAAA,QACnE,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,UAAU,SAAS,KAAK,iBAAiB,KAAK,KAAK;AAAA,QACnD,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,SAAiB;AACf,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,KAAK,WAAW,KAAK,UAAU,IAAI,KAAK,OAAO,EAAG,QAAO,KAAK;AAClE,QAAI,KAAK,WAAW,MAAM,KAAK,CAAC,YAAY,QAAQ,OAAO,KAAK,OAAO,EAAG,QAAO,KAAK;AACtF,WAAO,KAAK,YAAY,QAAQ,OAAO,UAAU;AAAA,EACnD;AAAA,EAEA,OAAO,IAAkB;AACvB,QAAI,KAAK,UAAU,IAAI,EAAE,GAAG;AAC1B,WAAK,UAAU;AACf,WAAK,KAAK,UAAU,EAAE;AACtB;AAAA,IACF;AACA,UAAM,QAAQ,KAAK,SAAS,EAAE,KAAK,CAAC,YAAY,QAAQ,OAAO,EAAE;AACjE,QAAI,CAAC,MAAO;AACZ,SAAK,UAAU;AACf,QAAI,MAAM,SAAS,OAAQ,MAAK,KAAK,YAAY,QAAQ,WAAW,IAAI,kBAAkB;AAC1F,SAAK,KAAK,UAAU,EAAE;AACtB,SAAK,KAAK,YAAY,EAAE;AAAA,EAC1B;AAAA,EAEA,SAAS,UAAkB,KAAK,OAAO,GAAuB;AAC5D,WAAO,KAAK,UAAU,IAAI,OAAO,KAAK,CAAC;AAAA,EACzC;AAAA,EAEA,MAAM,KAAK,SAAiB,OAAyC;AACnE,UAAM,WAAW,OAAO,UAAU,WAAW,EAAE,MAAM,MAAM,IAAI;AAC/D,UAAM,SAAS,KAAK,UAAU,IAAI,OAAO,IAAI,MAAM,KAAK,UAAU,IAAI,OAAO,IAAI;AACjF,QAAI,WAAW,KAAM,OAAM,IAAI,MAAM,iCAAiC;AACtE,UAAM,OAAO,MAAM,KAAK,YAAY,QAAQ;AAAA,MAC1C;AAAA,QACE,MAAM,SAAS;AAAA,QACf,UAAU,SAAS,SAAS,UAAU,aAAa;AAAA,QACnD,WAAW,OAAO,WAAW;AAAA,QAC7B,SAAS,UAAU;AAAA,MACrB;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,KAAK,MAAM,OAAO;AAAA,EACxD;AAAA,EAEA,MAAM,OAAO,SAAiB,WAA6C;AACzE,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ;AAAA,MAC7C;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI;AAAA,EACjD;AAAA,EAEA,KAAK,UAAkB,KAAK,OAAO,GAAS;AAC1C,SAAK,KAAK,YAAY,QAAQ,UAAU,SAAS,kBAAkB;AAAA,EACrE;AAAA,EAEA,KAAK,UAAkB,KAAK,OAAO,GAAY;AAC7C,WAAO,OAAO,KAAK,MAAM,OAAO,CAAC;AAAA,EACnC;AAAA,EAEA,MAAM,UAAkB,KAAK,OAAO,GAA2B;AAC7D,WAAO,OAAO,KAAK,MAAM,OAAO,CAAC;AAAA,EACnC;AAAA,EAEA,QAAQ,SAAiB,WAAyB;AAChD,SAAK,KAAK,YAAY,QAAQ,QAAQ,SAAS,UAAU,QAAQ,MAAM,EAAE,GAAG,kBAAkB;AAAA,EAChG;AAAA,EAEA,aAA4B;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,SAAe;AAAA,EAAC;AAAA,EAEhB,YAAY,SAAiB,WAAmB,OAAwC;AACtF,UAAM,UAAU,KAAK,SAAS,OAAO,EAAE,KAAK,CAAC,cAAc,UAAU,OAAO,SAAS;AACrF,UAAM,QAAQ,KAAK,MAAM,OAAO,GAAG,QAAQ;AAAA,MACzC,CAAC,cAAc,IAAI,UAAU,EAAE,OAAO;AAAA,IACxC;AACA,UAAM,OAAO,SAAS,SAAS,UAAU,QAAQ,UAAU,KAAK,IAAI;AACpE,QAAI;AACF,WAAK,KAAK,YAAY,QAAQ,iBAAiB,SAAS,KAAK,IAAI,OAAO,kBAAkB;AAAA,EAC9F;AAAA,EAEA,QAAQ,UAAkB,KAAK,OAAO,GAAS;AAC7C,SAAK,KAAK,YAAY,QAAQ,aAAa,SAAS,MAAM,kBAAkB;AAAA,EAC9E;AAAA,EAEA,MAAM,UAAkB,KAAK,OAAO,GAAS;AAC3C,SAAK,KAAK,YAAY,QAAQ,QAAQ,SAAS,kBAAkB;AAAA,EACnE;AAAA,EAEA,OAAO,UAAkB,KAAK,OAAO,GAAS;AAC5C,SAAK,KAAK,YAAY,QAAQ,OAAO,SAAS,kBAAkB;AAAA,EAClE;AAAA,EAEA,WAAW,SAAiB,QAA4C;AACtE,SAAK,KAAK,YAAY,QAAQ;AAAA,MAC5B;AAAA,QACE,OAAO,OAAO,SAAS;AAAA,QACvB,eAAe,OAAO,iBAAiB;AAAA,QACvC;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS,SAAiB,OAAqB;AAC7C,UAAM,KAAK,MAAM,QAAQ,GAAG;AAC5B,QAAI,MAAM,EAAG;AACb,SAAK,WAAW,SAAS;AAAA,MACvB,OAAO,EAAE,UAAU,MAAM,MAAM,GAAG,EAAE,GAAG,SAAS,MAAM,MAAM,KAAK,CAAC,EAAE;AAAA,IACtE,CAAC;AAAA,EACH;AAAA,EAEA,YAAY,SAAiB,OAAuB;AAClD,SAAK,WAAW,SAAS,EAAE,eAAe,MAAM,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,QAAqC;AACzC,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,WAAoC;AAClC,YAAQ,KAAK,YAAY,UAAU,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,EAAE;AAAA,EACnF;AAAA,EAEA,YAAY,UAAkB,MAAqB;AACjD,UAAM,cAAc,kBAAkB,OAAO,WAAW,CAAC;AACzD,UAAM,UAAU,KAAK,YAAY,QAAQ,YAAY,UAAU,MAAM,kBAAkB,EAAE;AAAA,MACvF,CAAC,WAAW,OAAO;AAAA,MACnB,MAAM;AAAA,IACR;AACA,SAAK,UAAU,IAAI,aAAa,OAAO;AACvC,SAAK,QAAQ,KAAK,CAAC,OAAO;AACxB,UAAI,KAAK,YAAY,YAAa;AAClC,WAAK,UAAU,MAAM;AACrB,WAAK,KAAK,UAAU,KAAK,OAAO;AAChC,WAAK,KAAK,YAAY,KAAK,OAAO;AAAA,IACpC,CAAC;AACD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,SAAgC;AACzC,UAAM,SAAS,KAAK,SAAS,EAAE,KAAK,CAAC,YAAY,QAAQ,OAAO,OAAO,GAAG,YAAY;AACtF,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,KAAK,SAAS,kBAAkB;AAC/E,QAAI,QAAQ,UAAU,KAAM,OAAM,IAAI,MAAM,QAAQ,KAAK;AACzD,QAAI,KAAK,YAAY,QAAS,MAAK,OAAO,MAAM;AAAA,EAClD;AAAA,EAEA,MAAM,WAAW,MAA8B;AAC7C,UAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,WAAW,MAAM,kBAAkB;AAClF,QAAI,QAAQ,UAAU,KAAM,OAAM,IAAI,MAAM,QAAQ,KAAK;AACzD,WAAO;AAAA,MACL,IAAI,QAAQ;AAAA,MACZ,MAAM,KAAK,KAAK;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,SAAgC;AAC9B,YAAQ,KAAK,YAAY,QAAQ,SAAS,CAAC,GAAG;AAAA,MAC5C,CAAC,EAAE,IAAI,MAAM,OAAO,OAAO,UAAU,UAAU,MAAM,MAAM,SAAS,OAAO;AAAA,QACzE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,IAA0B;AAC7B,UAAM,SAAS,KAAK,OAAO,EAAE,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE;AAC1D,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI,OAAO,MAAM;AACf,YAAM,UAAU,KAAK,KAAK,EAAE,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK;AAChE,UAAI,QAAS,MAAK,OAAO,EAAE;AAC3B,aAAO;AAAA,IACT;AACA,UAAM,cAAc,WAAW,OAAO,WAAW,CAAC;AAClD,UAAM,SAAS,KAAK,YAAY,QAAQ,KAAK,IAAI,kBAAkB,EAAE;AAAA,MACnE,CAAC,WAAW,OAAO;AAAA,MACnB,MAAM;AAAA,IACR;AACA,SAAK,UAAU,IAAI,aAAa,MAAM;AACtC,SAAK,OAAO,KAAK,CAAC,SAAS;AACzB,UAAI,KAAK,YAAY,YAAa;AAClC,WAAK,UAAU,QAAQ;AACvB,WAAK,KAAK,UAAU,KAAK,OAAO;AAChC,WAAK,KAAK,YAAY,KAAK,OAAO;AAAA,IACpC,CAAC;AACD,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,OAAO;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,OAAO,OAAO;AAAA,MACd,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,QAAQ,IAAkB;AACxB,SAAK,KAAK,YAAY,QAAQ,QAAQ,IAAI,kBAAkB;AAAA,EAC9D;AACF;",
4
+ "sourcesContent": ["import type {\n Agent,\n AgentEvents,\n AgentPort,\n AgentStatus,\n FrozenCone,\n Message,\n Outgoing,\n SlashCommand,\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 { 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\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()])\n if (!this.#summary().some((summary) => summary.id === id)) this.#messages.delete(id);\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') void this.#connection.control.selectCone(id, BACKGROUND_CONTEXT);\n this.emit('active', id);\n this.emit('messages', id);\n }\n\n messages(agentId: string = this.active()): readonly Message[] {\n return this.#messages.get(agentId) ?? [];\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 void this.#connection.control.unqueue(pending.agentId, sent.submissionId, BACKGROUND_CONTEXT);\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 void this.#connection.control.stopAgent(agentId, BACKGROUND_CONTEXT);\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 void this.#connection.control.unqueue(agentId, messageId.replace(/^q/, ''), BACKGROUND_CONTEXT);\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 void this.#connection.control.resolveAgentLick(agentId, lick.id, state, BACKGROUND_CONTEXT);\n }\n\n compact(agentId: string = this.active()): void {\n void this.#connection.control.compactAgent(agentId, null, BACKGROUND_CONTEXT);\n }\n\n clear(agentId: string = this.active()): void {\n void this.#connection.control.newChat(agentId, BACKGROUND_CONTEXT);\n }\n\n freeze(agentId: string = this.active()): void {\n void this.#connection.control.freeze(agentId, BACKGROUND_CONTEXT);\n }\n\n #configure(agentId: string, change: Partial<AgentSettingsChange>): void {\n void this.#connection.control.configure(\n {\n model: change.model ?? null,\n thinkingLevel: change.thinkingLevel ?? null,\n agentId,\n },\n BACKGROUND_CONTEXT\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 void this.#connection.control.discard(id, BACKGROUND_CONTEXT);\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2,6 +2,7 @@ import { parseLick } from "../licks/lick.js";
2
2
  import { entryLick, LICK_TOOLS, lickDecisions } from "../licks/state.js";
3
3
  import { mcpLabel } from "../mcp/label.js";
4
4
  import { FROM_KIND } from "../scoops/from.js";
5
+ import { listedLine, SECRETS_KIND } from "../secrets/view.js";
5
6
  import { SPRINKLE_KIND } from "../sprinkles/kind.js";
6
7
  function textOf(content) {
7
8
  if (typeof content === "string") return content;
@@ -264,11 +265,23 @@ function thawed(id, entry) {
264
265
  createdAt: entry.model?.[0]?.timestamp ?? 0
265
266
  };
266
267
  }
268
+ function secrets(id, entry) {
269
+ const data = entry.data ?? {};
270
+ return {
271
+ id,
272
+ role: "system",
273
+ kind: "notice",
274
+ title: "Secrets listed",
275
+ text: listedLine(data.names ?? []),
276
+ createdAt: entry.model?.[0]?.timestamp ?? 0
277
+ };
278
+ }
267
279
  function entryMessage(entry, out, calls, delivered, notes) {
268
280
  const id = `e${entry.id}`;
269
281
  const model = entry.model?.[0];
270
282
  if (entry.kind === "slicc.rewound") out.push(rewound(id, entry));
271
283
  if (entry.kind === "slicc.thawed") out.push(thawed(id, entry));
284
+ else if (entry.kind === SECRETS_KIND) out.push(secrets(id, entry));
272
285
  else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));
273
286
  else if (entry.kind === "pi.user" && model)
274
287
  out.push(
@@ -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 { 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\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage): void {\n const call = calls.get(result.toolCallId ?? '');\n if (!call) return;\n call.output = textOf(result.content);\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 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 === 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);\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 { 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\nfunction settle(calls: Map<string, ToolCall>, result: ModelMessage): void {\n const call = calls.get(result.toolCallId ?? '');\n if (!call) return;\n call.output = textOf(result.content);\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);\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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",
6
6
  "names": ["part"]
7
7
  }
@@ -11,6 +11,7 @@ export interface AgentOptions {
11
11
  settings?: HarnessOptions['settings'];
12
12
  env?: HarnessOptions['env'];
13
13
  context?: Context;
14
+ beforeResume?: (harness: Harness, context: Context) => Promise<unknown>;
14
15
  }
15
16
  export interface Agent extends Cones {
16
17
  readonly harness: Harness;
@@ -5,6 +5,7 @@ import type { FrozenCone } from './freezer/index.ts';
5
5
  import type { MemoryEntry, MemoryScope } from './memory/format.ts';
6
6
  import type { AgentRemote } from './remote/host.ts';
7
7
  import type { AgentPages } from './remote/pages.ts';
8
+ import type { VaultState } from './secrets/vault.ts';
8
9
  import { AgentControl, AgentSettings, type AgentsSummary, type Command, type Delivered, type MonitorFeed, type SendMode } from './services.ts';
9
10
  import type { Sprinkle } from './sprinkles/kind.ts';
10
11
  import { type PortEndpoint } from './wire.ts';
@@ -22,6 +23,7 @@ export interface AgentConnection {
22
23
  readonly frozen?: ReplicatedState<FrozenCone[]>;
23
24
  readonly changes?: ReplicatedState<ChangesView>;
24
25
  readonly monitor?: ReplicatedState<MonitorFeed>;
26
+ readonly vault?: ReplicatedState<VaultState>;
25
27
  readonly settings: AgentSettings;
26
28
  readonly remote?: AgentRemote;
27
29
  readonly pages?: AgentPages;
@@ -7,6 +7,7 @@ import type { LickSources, Licks } from './licks/index.ts';
7
7
  import type { MemoryRuntime } from './memory/index.ts';
8
8
  import type { Monitor } from './monitor/index.ts';
9
9
  import type { Scoops, ScoopsRuntime } from './scoops/index.ts';
10
+ import type { SecretName } from './secrets/names.ts';
10
11
  import type { AgentControl } from './services.ts';
11
12
  import type { SkillsRuntime } from './skills/index.ts';
12
13
  import type { SprinklesRuntime } from './sprinkles/index.ts';
@@ -20,4 +21,4 @@ export interface HostScoops {
20
21
  }
21
22
  export declare function readable(out: string): string;
22
23
  export declare function submissionId(value: string): SubmissionId | undefined;
23
- export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand'>, 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'>): AgentControl;
24
+ export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand'>, 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[]): AgentControl;
@@ -1,4 +1,4 @@
1
- import { type Context } from '@earendil-works/chord';
1
+ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { Agent } from './agent.ts';
3
3
  import type { ChangesRuntime } from './changes/index.ts';
4
4
  import { type HostLicks, type HostScoops } from './control.ts';
@@ -8,6 +8,8 @@ import type { McpRuntime } from './mcp/index.ts';
8
8
  import type { MemoryRuntime } from './memory/index.ts';
9
9
  import { type MonitorOptions } from './monitor/index.ts';
10
10
  import { type Pages } from './remote/pages.ts';
11
+ import type { SecretName } from './secrets/names.ts';
12
+ import type { VaultState } from './secrets/vault.ts';
11
13
  import { AgentSettings } from './services.ts';
12
14
  import type { SkillsRuntime } from './skills/index.ts';
13
15
  import type { SprinklesRuntime } from './sprinkles/index.ts';
@@ -24,6 +26,11 @@ export interface AgentHost {
24
26
  connect(endpoint: PortEndpoint, options?: ConnectOptions): void;
25
27
  close(): Promise<void>;
26
28
  }
29
+ export interface HostSecrets {
30
+ vault: ReplicatedState<VaultState>;
31
+ list(): readonly SecretName[];
32
+ close?(): void;
33
+ }
27
34
  export declare function hostAgent(agent: Agent, options?: {
28
35
  serverId?: string;
29
36
  context?: Context;
@@ -39,4 +46,5 @@ export declare function hostAgent(agent: Agent, options?: {
39
46
  users?: UserClients;
40
47
  monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users' | 'secrets'>;
41
48
  pages?: Pages;
49
+ secrets?: HostSecrets;
42
50
  }): Promise<AgentHost>;
@@ -1,5 +1,6 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
2
  import { type BinaryReader, type DirReader, type ExecutionEnv, type ExecutionError, FileError, type FileInfo, type FileWatcher, type Result, type ShellExecOptions, type ShellExecResult, type TextLineReader, type WatchChange, type WatchTarget } from '@earendil-works/pi-durable/env';
3
+ import type { Scrub } from '../secrets/scrub.ts';
3
4
  import type { Activity } from './activity.ts';
4
5
  import type { KernelClient } from './client.ts';
5
6
  import type { ProcessGroups } from './groups.ts';
@@ -12,7 +13,12 @@ export interface KernelEnvOptions {
12
13
  groups?: ProcessGroups;
13
14
  owner?: number;
14
15
  exports?: Readonly<Record<string, string>>;
16
+ scrub?: Scrub;
17
+ spawn?: (argv: readonly string[]) => readonly string[];
15
18
  }
19
+ export declare const STREAMED_READ: number;
20
+ export declare const READ_CHUNK: number;
21
+ export declare function scrubbedFile(scrub: Scrub, bytes: Uint8Array): Promise<Uint8Array>;
16
22
  export declare function quote(value: string): string;
17
23
  export declare function prefixed(command: string, exports: Readonly<Record<string, string>> | undefined): string;
18
24
  type FileResult<T> = Promise<Result<T, FileError>>;
@@ -1,10 +1,17 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
2
  import { ExecutionError, type Result, type ShellExecOptions, type ShellExecResult } from '@earendil-works/pi-durable/env';
3
+ import type { ScrubStream } from '../secrets/scrub.ts';
3
4
  import type { KernelClient, KernelProcess } from './client.ts';
4
5
  export declare const SHELL: readonly ['bash', '-c'];
6
+ export declare const HELD_LIMIT: number;
7
+ export declare const HELD = "output held: waiting for the vault";
8
+ export interface ExecHooks {
9
+ scrub?: () => ScrubStream;
10
+ spawn?: (argv: readonly string[]) => readonly string[];
11
+ }
5
12
  export declare function sweep(client: Pick<KernelClient, 'kill' | 'ps'>, process: KernelProcess): Promise<void>;
6
13
  export interface Join {
7
14
  pgid?: number;
8
15
  refused(code: string): void;
9
16
  }
10
- export declare function execute(client: KernelClient, cwd: string, command: string | readonly string[], options: ShellExecOptions | undefined, context: Context, spawned?: (process: KernelProcess) => void, join?: Join): Promise<Result<ShellExecResult, ExecutionError>>;
17
+ export declare function execute(client: KernelClient, cwd: string, command: string | readonly string[], options: ShellExecOptions | undefined, context: Context, spawned?: (process: KernelProcess) => void, join?: Join, hooks?: ExecHooks): Promise<Result<ShellExecResult, ExecutionError>>;