@ai-ecoverse/slicc-agent 3.10.0 → 3.12.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 (58) hide show
  1. package/README.md +31 -2
  2. package/bin/agent +1 -1
  3. package/dist/client.js +9 -1
  4. package/dist/client.js.map +2 -2
  5. package/dist/control.js +11 -1
  6. package/dist/control.js.map +2 -2
  7. package/dist/host.js +5 -2
  8. package/dist/host.js.map +2 -2
  9. package/dist/main.js +15 -1
  10. package/dist/main.js.map +2 -2
  11. package/dist/scoops/cli.js +2 -0
  12. package/dist/scoops/cli.js.map +2 -2
  13. package/dist/scoops/extension.js +6 -3
  14. package/dist/scoops/extension.js.map +2 -2
  15. package/dist/scoops/from.js.map +1 -1
  16. package/dist/scoops/index.js +3 -2
  17. package/dist/scoops/index.js.map +2 -2
  18. package/dist/scoops/requests.js +1 -1
  19. package/dist/scoops/requests.js.map +2 -2
  20. package/dist/scoops/service.js +6 -2
  21. package/dist/scoops/service.js.map +2 -2
  22. package/dist/services.js +3 -1
  23. package/dist/services.js.map +2 -2
  24. package/dist/skills/index.js +1 -1
  25. package/dist/skills/index.js.map +2 -2
  26. package/dist/spectrum/index.js +5 -1
  27. package/dist/spectrum/index.js.map +3 -3
  28. package/dist/spectrum/messages.js +15 -2
  29. package/dist/spectrum/messages.js.map +2 -2
  30. package/dist/spectrum/sprinkle-port.js +37 -0
  31. package/dist/spectrum/sprinkle-port.js.map +7 -0
  32. package/dist/sprinkles/index.js +216 -0
  33. package/dist/sprinkles/index.js.map +7 -0
  34. package/dist/sprinkles/kind.js +5 -0
  35. package/dist/sprinkles/kind.js.map +7 -0
  36. package/dist/sprinkles/sprinkles.js +65 -0
  37. package/dist/sprinkles/sprinkles.js.map +7 -0
  38. package/dist/types/client.d.ts +2 -0
  39. package/dist/types/control.d.ts +2 -1
  40. package/dist/types/host.d.ts +2 -0
  41. package/dist/types/scoops/cli.d.ts +1 -0
  42. package/dist/types/scoops/extension.d.ts +1 -0
  43. package/dist/types/scoops/from.d.ts +1 -0
  44. package/dist/types/scoops/index.d.ts +2 -0
  45. package/dist/types/scoops/requests.d.ts +1 -1
  46. package/dist/types/scoops/service.d.ts +1 -0
  47. package/dist/types/services.d.ts +11 -1
  48. package/dist/types/spectrum/index.d.ts +3 -0
  49. package/dist/types/spectrum/messages.d.ts +2 -1
  50. package/dist/types/spectrum/sprinkle-port.d.ts +10 -0
  51. package/dist/types/sprinkles/index.d.ts +38 -0
  52. package/dist/types/sprinkles/kind.d.ts +10 -0
  53. package/dist/types/sprinkles/sprinkles.d.ts +24 -0
  54. package/package.json +5 -5
  55. package/packages/vfs-root/skills/sprinkles/SKILL.md +58 -0
  56. package/packages/vfs-root/skills/welcome/SKILL.md +31 -0
  57. package/packages/vfs-root/sprinkles/suggestions.shtml +391 -0
  58. package/packages/vfs-root/sprinkles/welcome.shtml +552 -0
@@ -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 = ['agent', 'licks', 'skill-authoring'];\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 COMPAT_DIR = '/workspace/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 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: COMPAT_DIR, source: 'compat' },\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: COMPAT_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 = ['agent', 'licks', 'skill-authoring', 'sprinkles', 'welcome'];\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 COMPAT_DIR = '/workspace/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 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: COMPAT_DIR, source: 'compat' },\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: COMPAT_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 { AgentAdapter } from "./agent-port.js";
2
2
  import { SettingsAdapter } from "./settings-port.js";
3
+ import { SprinkleAdapter } from "./sprinkle-port.js";
3
4
  import { TrayAdapter } from "./tray-port.js";
4
5
  import { AgentAdapter as AgentAdapter2, CONE } from "./agent-port.js";
5
6
  import {
@@ -12,6 +13,7 @@ import {
12
13
  toMessages
13
14
  } from "./messages.js";
14
15
  import { SETTINGS_KEY, SettingsAdapter as SettingsAdapter2 } from "./settings-port.js";
16
+ import { SprinkleAdapter as SprinkleAdapter2 } from "./sprinkle-port.js";
15
17
  import { TrayAdapter as TrayAdapter2 } from "./tray-port.js";
16
18
  function createAgentModel(connection, options = {}) {
17
19
  const agent = new AgentAdapter(connection);
@@ -23,7 +25,8 @@ function createAgentModel(connection, options = {}) {
23
25
  options.storage ?? null,
24
26
  options.login ?? null
25
27
  ),
26
- tray: new TrayAdapter(connection.settings)
28
+ tray: new TrayAdapter(connection.settings),
29
+ sprinkles: new SprinkleAdapter(connection)
27
30
  };
28
31
  }
29
32
  export {
@@ -31,6 +34,7 @@ export {
31
34
  CONE,
32
35
  SETTINGS_KEY,
33
36
  SettingsAdapter2 as SettingsAdapter,
37
+ SprinkleAdapter2 as SprinkleAdapter,
34
38
  TrayAdapter2 as TrayAdapter,
35
39
  assistant,
36
40
  createAgentModel,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/index.ts"],
4
- "sourcesContent": ["import type { AgentConnection } from '../client.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { type Login, SettingsAdapter } from './settings-port.ts';\nimport { TrayAdapter } from './tray-port.ts';\n\nexport { AgentAdapter, CONE } from './agent-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport { type Login, SETTINGS_KEY, SettingsAdapter } from './settings-port.ts';\nexport { TrayAdapter } from './tray-port.ts';\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: { storage?: Pick<Storage, 'getItem' | 'setItem'> | null; login?: Login } = {}\n): { agent: AgentAdapter; settings: SettingsAdapter; tray: TrayAdapter } {\n const agent = new AgentAdapter(connection);\n return {\n agent,\n settings: new SettingsAdapter(\n connection.settings,\n agent,\n options.storage ?? null,\n options.login ?? null\n ),\n tray: new TrayAdapter(connection.settings),\n };\n}\n"],
5
- "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAqB,uBAAuB;AAC5C,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,eAAAC,oBAAmB;AAErB,SAAS,iBACd,YACA,UAAoF,CAAC,GACd;AACvE,QAAM,QAAQ,IAAI,aAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA,UAAU,IAAI;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,QAAQ,SAAS;AAAA,IACnB;AAAA,IACA,MAAM,IAAI,YAAY,WAAW,QAAQ;AAAA,EAC3C;AACF;",
6
- "names": ["AgentAdapter", "SettingsAdapter", "TrayAdapter"]
4
+ "sourcesContent": ["import type { AgentConnection } from '../client.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { type Login, SettingsAdapter } from './settings-port.ts';\nimport { SprinkleAdapter } from './sprinkle-port.ts';\nimport { TrayAdapter } from './tray-port.ts';\n\nexport { AgentAdapter, CONE } from './agent-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport { type Login, SETTINGS_KEY, SettingsAdapter } from './settings-port.ts';\nexport { SprinkleAdapter } from './sprinkle-port.ts';\nexport { TrayAdapter } from './tray-port.ts';\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: { storage?: Pick<Storage, 'getItem' | 'setItem'> | null; login?: Login } = {}\n): {\n agent: AgentAdapter;\n settings: SettingsAdapter;\n tray: TrayAdapter;\n sprinkles: SprinkleAdapter;\n} {\n const agent = new AgentAdapter(connection);\n return {\n agent,\n settings: new SettingsAdapter(\n connection.settings,\n agent,\n options.storage ?? null,\n options.login ?? null\n ),\n tray: new TrayAdapter(connection.settings),\n sprinkles: new SprinkleAdapter(connection),\n };\n}\n"],
5
+ "mappings": "AACA,SAAS,oBAAoB;AAC7B,SAAqB,uBAAuB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAAC,oBAAmB;AAErB,SAAS,iBACd,YACA,UAAoF,CAAC,GAMrF;AACA,QAAM,QAAQ,IAAI,aAAa,UAAU;AACzC,SAAO;AAAA,IACL;AAAA,IACA,UAAU,IAAI;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,QAAQ,SAAS;AAAA,IACnB;AAAA,IACA,MAAM,IAAI,YAAY,WAAW,QAAQ;AAAA,IACzC,WAAW,IAAI,gBAAgB,UAAU;AAAA,EAC3C;AACF;",
6
+ "names": ["AgentAdapter", "SettingsAdapter", "SprinkleAdapter", "TrayAdapter"]
7
7
  }
@@ -1,6 +1,7 @@
1
1
  import { parseLick } from "../licks/lick.js";
2
2
  import { entryLick, LICK_TOOLS, lickDecisions } from "../licks/state.js";
3
3
  import { FROM_KIND } from "../scoops/from.js";
4
+ import { SPRINKLE_KIND } from "../sprinkles/kind.js";
4
5
  function textOf(content) {
5
6
  if (typeof content === "string") return content;
6
7
  return (content ?? []).map((block) => block.type === "text" ? block.text ?? "" : "").join("");
@@ -132,6 +133,16 @@ function errorAction(message) {
132
133
  if (models.test(message) && unavailable.test(message)) return "change-model";
133
134
  return "retry";
134
135
  }
136
+ function sprinkleMessage(id, entry) {
137
+ const data = entry.data ?? {};
138
+ return {
139
+ id,
140
+ role: "assistant",
141
+ parts: [{ type: "sprinkle", sprinkle: String(data.sprinkle ?? "") }],
142
+ status: "done",
143
+ createdAt: typeof data.at === "number" ? data.at : 0
144
+ };
145
+ }
135
146
  function assistant(id, message, status) {
136
147
  const blocks = Array.isArray(message.content) ? message.content : [];
137
148
  const parts = blocks.map(part).filter((item) => item !== void 0);
@@ -154,7 +165,8 @@ function user(id, message, delivered, from) {
154
165
  text: textOf(message.content),
155
166
  createdAt: message.timestamp ?? 0,
156
167
  ...delivered ? { delivered } : {},
157
- ...from ? { from } : {}
168
+ ...from ? { from: from.from } : {},
169
+ ...from?.agent ? { origin: "agent" } : {}
158
170
  };
159
171
  }
160
172
  function origins(entries) {
@@ -162,7 +174,7 @@ function origins(entries) {
162
174
  for (const entry of entries)
163
175
  if (entry.kind === FROM_KIND) {
164
176
  const note = entry.data;
165
- out.set(note.entry, note.from);
177
+ out.set(note.entry, note);
166
178
  }
167
179
  return out;
168
180
  }
@@ -237,6 +249,7 @@ function entryMessage(entry, out, calls, delivered, notes) {
237
249
  const id = `e${entry.id}`;
238
250
  const model = entry.model?.[0];
239
251
  if (entry.kind === "slicc.rewound") out.push(rewound(id, entry));
252
+ else if (entry.kind === SPRINKLE_KIND) out.push(sprinkleMessage(id, entry));
240
253
  else if (entry.kind === "pi.user" && model)
241
254
  out.push(
242
255
  lickMessage(id, entry, notes.decisions) ?? user(id, model, delivered, notes.origins.get(entry.id))
@@ -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 { FROM_KIND, type From } from '../scoops/from.ts';\nimport type { Delivered } from '../services.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: 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)|refused to complete the request/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: \"The model's content filter stopped this reply.\",\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)) 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\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: string | 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 } : {}),\n };\n}\n\nexport function origins(entries: readonly EntryRecord[]): Map<number, string> {\n const out = new Map<number, string>();\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.from);\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 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[] };\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 ];\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 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, string> }\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 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 { 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: 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)|refused to complete the request/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: \"The model's content filter stopped this reply.\",\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)) 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 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[] };\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 ];\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 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 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": "AAcA,SAAS,iBAAiB;AAC1B,SAAS,WAAW,YAA+B,qBAAqB;AACxE,SAAS,iBAA4B;AAErC,SAAS,qBAAqB;AA8CvB,SAAS,OAAO,SAA0C;AAC/D,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,UAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,UAAW,MAAM,SAAS,SAAU,MAAM,QAAQ,KAAM,EAAG,EAAE,KAAK,EAAE;AAClG;AAEA,MAAM,QAAQ,CAAC,SACb,OAAO,MAAM,SAAS,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC;AAElD,SAAS,MAAM,MAAgC;AAC7C,QAAM,UAAU,MAAM,WAAW,MAAM;AACvC,SAAO,OAAO,YAAY,WAAW,UAAU;AACjD;AAOA,MAAM,MAAM;AAEZ,SAAS,QAAQ,OAAoC;AACnD,SAAO,OAAO,UAAU,WAAW,WAAW,KAAK,MAAM;AAC3D;AAEA,SAAS,MAAM,MAAgC;AAC7C,QAAM,EAAE,QAAQ,MAAM,IAAI;AAC1B,MAAI,OAAO,WAAW,YAAY,OAAO,UAAU;AACjD,WAAO,SAAS,MAAM,SAAI,SAAS,QAAQ,CAAC;AAC9C,MAAI,OAAO,WAAW,SAAU,QAAO,aAAa,MAAM;AAC1D,SAAO,OAAO,UAAU,WAAW,SAAS,KAAK,WAAW;AAC9D;AAEA,SAAS,MAAM,MAA8B;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,KAAK,IAAK,KAAK,QAA0B,CAAC;AAC1E,MAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,SAAO;AAAA,IACL,QAAQ,KAAK,IAAI,CAAC,SAAS,KAAK,WAAW,EAAE,EAAE,KAAK;AAAA,EAAK,GAAG;AAAA,CAAI;AAAA,IAChE,OAAO,KAAK,IAAI,CAAC,SAAS,KAAK,WAAW,EAAE,EAAE,KAAK;AAAA,EAAK,GAAG;AAAA,CAAI;AAAA,EACjE;AACF;AAEO,SAAS,UAAU,OAAiC;AACzD,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ;AACZ,aAAW,QAAQ,MAAM,MAAM,IAAI,GAAG;AACpC,QAAI,KAAK,WAAW,IAAI,GAAG;AACzB,UAAI,UAAU,GAAG;AACf,eAAO,KAAK,GAAG;AACf,cAAM,KAAK,GAAG;AAAA,MAChB;AACA;AAAA,IACF;AACA,QAAI,UAAU,KAAK,SAAS,MAAM,KAAK,WAAW,IAAI,EAAG;AACzD,UAAM,OAAO,KAAK,MAAM,CAAC;AACzB,QAAI,KAAK,WAAW,GAAG,EAAG,QAAO,KAAK,IAAI;AAAA,aACjC,KAAK,WAAW,GAAG,EAAG,OAAM,KAAK,IAAI;AAAA,SACzC;AACH,aAAO,KAAK,IAAI;AAChB,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO,QAAQ,EAAE,QAAQ,OAAO,KAAK,IAAI,GAAG,OAAO,MAAM,KAAK,IAAI,EAAE,IAAI;AAC1E;AAEA,SAAS,MAAM,MAAc,MAAuD;AAClF,QAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,QAAM,OAAO,SAAS,SAAS,QAAQ,KAAK,OAAO,IAAI,SAAS,SAAS,MAAM,IAAI,IAAI;AACvF,QAAM,OAAO,OAAO,EAAE,KAAK,IAAI,CAAC;AAChC,MAAI,SAAS,UAAU,OAAO,KAAK,YAAY,SAAU,QAAO,EAAE,OAAO,KAAK,SAAS,GAAG,KAAK;AAC/F,MAAI,SAAS,UAAU,SAAS,QAAS,QAAO,EAAE,OAAO,MAAM,GAAG,KAAK;AACvE,MAAI,SAAS,QAAQ;AACnB,UAAM,OAAO,MAAM,IAAI;AACvB,WAAO,EAAE,OAAO,MAAM,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AAAA,EAClD;AACA,SAAO,EAAE,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE;AAChD;AAEA,SAAS,SAAS,OAAwB;AACxC,QAAM,OAAO,MAAM,aAAa,CAAC;AACjC,SAAO;AAAA,IACL,IAAI,MAAM,MAAM;AAAA,IAChB,MAAM,MAAM,QAAQ;AAAA,IACpB,OAAO,MAAM,MAAM,SAAS;AAAA,IAC5B,GAAG,MAAM,MAAM,QAAQ,QAAQ,IAAI;AAAA,IACnC,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO,MAAM,MAAM,SAAS;AAAA,EAC9B;AACF;AAEA,SAAS,KAAK,OAAuC;AACnD,MAAI,MAAM,SAAS,OAAQ,QAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,QAAQ,GAAG;AACzE,MAAI,MAAM,SAAS,WAAY,QAAO,EAAE,MAAM,YAAY,MAAM,MAAM,YAAY,GAAG;AACrF,MAAI,MAAM,SAAS,WAAY,QAAO,EAAE,MAAM,QAAQ,MAAM,SAAS,KAAK,EAAE;AAC5E,SAAO;AACT;AAEA,SAAS,MAAM,SAA0C;AACvD,QAAM,OAAO,QAAQ;AACrB,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO;AAAA,IACL,OAAO,KAAK,SAAS;AAAA,IACrB,QAAQ,KAAK,UAAU;AAAA,IACvB,MAAM,KAAK,MAAM,SAAS;AAAA,IAC1B,WAAW,KAAK,aAAa;AAAA,IAC7B,YAAY,KAAK,cAAc;AAAA,EACjC;AACF;AAEA,MAAM,WAA4C,EAAE,OAAO,SAAS,SAAS,UAAU;AAEvF,MAAM,cACJ;AACF,MAAM,SAAS;AACf,MAAM,cACJ;AAEF,MAAM,gBAAwC,EAAE,kBAAkB,UAAU;AAC5E,MAAM,WACJ;AACF,MAAM,UAAU;AAET,SAAS,UAAU,OAAe,UAAgC;AACvE,QAAM,SAAS,YAAY,KAAK;AAChC,MAAI,WAAW,aAAa;AAC1B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,cAAc,aAAa,SAAS;AACjD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AACA,QAAM,OAAO,cAAc,YAAY,EAAE,KAAK;AAC9C,QAAM,OACJ,WAAW,aACP,QAAQ,KAAK,KAAK,IAChB,GAAG,IAAI,uBACP,GAAG,IAAI,2BACT,WAAW,iBACT,yDACA;AACR,SAAO,OACH,EAAE,MAAM,SAAS,SAAS,MAAM,QAAQ,OAAO,OAAO,IACtD,EAAE,MAAM,SAAS,SAAS,OAAO,OAAO;AAC9C;AAEO,SAAS,YAAY,SAA8B;AACxD,MAAI,SAAS,KAAK,OAAO,EAAG,QAAO;AACnC,MAAI,YAAY,KAAK,OAAO,EAAG,QAAO;AACtC,MAAI,OAAO,KAAK,OAAO,KAAK,YAAY,KAAK,OAAO,EAAG,QAAO;AAC9D,SAAO;AACT;AAEA,SAAS,gBAAgB,IAAY,OAAsC;AACzE,QAAM,OAAQ,MAAM,QAAQ,CAAC;AAC7B,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,OAAO,CAAC,EAAE,MAAM,YAAY,UAAU,OAAO,KAAK,YAAY,EAAE,EAAE,CAAC;AAAA,IACnE,QAAQ;AAAA,IACR,WAAW,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AAAA,EACrD;AACF;AAEO,SAAS,UACd,IACA,SACA,QACkB;AAClB,QAAM,SAAS,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,UAAU,CAAC;AACnE,QAAM,QAAQ,OAAO,IAAI,IAAI,EAAE,OAAO,CAAC,SAA8B,SAAS,MAAS;AACvF,MAAI,QAAQ,aAAc,OAAM,KAAK,UAAU,QAAQ,cAAc,QAAQ,QAAQ,CAAC;AACtF,QAAM,OAAO,MAAM,OAAO;AAC1B,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,UAAU,SAAS,QAAQ,cAAc,EAAE,KAAK;AAAA,IACxD,WAAW,QAAQ,aAAa;AAAA,IAChC,GAAI,QAAQ,YAAY,QAAQ,QAAQ,EAAE,OAAO,GAAG,QAAQ,QAAQ,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC;AAAA,IAC7F,GAAI,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAAA,EAChC;AACF;AAEA,SAAS,KACP,IACA,SACA,WACA,MACa;AACb,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,MAAM,OAAO,QAAQ,OAAO;AAAA,IAC5B,WAAW,QAAQ,aAAa;AAAA,IAChC,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IAClC,GAAI,MAAM,QAAQ,EAAE,QAAQ,QAAiB,IAAI,CAAC;AAAA,EACpD;AACF;AAEO,SAAS,QAAQ,SAAoD;AAC1E,QAAM,MAAM,oBAAI,IAAkB;AAClC,aAAW,SAAS;AAClB,QAAI,MAAM,SAAS,WAAW;AAC5B,YAAM,OAAO,MAAM;AACnB,UAAI,IAAI,KAAK,OAAO,IAAI;AAAA,IAC1B;AACF,SAAO;AACT;AAEA,SAAS,YACP,IACA,OACA,WACyB;AACzB,QAAM,OAAO,UAAU,KAAK;AAC5B,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,KAAK,SAAS,SAAU,UAAU,IAAI,KAAK,EAAE,KAAK,YAAa;AAC7E,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,SAAS,KAAK;AAAA,IACd,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,IACX,WAAW,KAAK;AAAA,IAChB,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACvC,GAAI,KAAK,QAAQ,IAAI,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IAC9C,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,KAAK,WAAW,EAAE,UAAU,KAAK,SAAS,IAAI,CAAC;AAAA,EACrD;AACF;AAEA,SAAS,iBAAiB,SAA6C;AACrE,QAAM,QAAQ,QAAQ,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,UAAU,CAAC,WAAW,KAAK,KAAK,IAAI,CAAC;AAChG,SAAO,MAAM,WAAW,QAAQ,MAAM,SAAS,UAAU,EAAE,GAAG,SAAS,MAAM;AAC/E;AAEA,SAAS,OAAO,IAAY,OAAoB,MAA6B;AAC3E,QAAM,SAAU,MAAM,MAA2B;AACjD,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,WAAW;AAAA,IACX,OAAO;AAAA,IACP,GAAI,SAAS,EAAE,SAAS,OAAO,IAAI,CAAC;AAAA,EACtC;AACF;AAEA,SAAS,MAAM,UAA4C;AACzD,QAAM,QAAQ,oBAAI,IAAsB;AACxC,aAAW,WAAW,UAAU;AAC9B,QAAI,QAAQ,SAAS,YAAa;AAClC,eAAW,QAAQ,QAAQ,MAAO,KAAI,KAAK,SAAS,OAAQ,OAAM,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI;AAAA,EAC/F;AACA,SAAO;AACT;AAEA,SAAS,OAAO,OAA8B,QAA4B;AACxE,QAAM,OAAO,MAAM,IAAI,OAAO,cAAc,EAAE;AAC9C,MAAI,CAAC,KAAM;AACX,OAAK,SAAS,OAAO,OAAO,OAAO;AACnC,OAAK,SAAS,OAAO,UAAU,UAAU;AACzC,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,OAAO,OAAO,UAAU,WAAW,UAAU,KAAK,IAAI;AAC5D,MAAI,KAAM,MAAK,OAAO;AAAA,WACb,OAAO,QAAS,QAAO,KAAK;AACvC;AAEA,SAAS,QAAQ,IAAY,OAAmC;AAC9D,QAAM,OAAQ,MAAM,QAAQ,CAAC;AAC7B,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,GAAI,KAAK,SAAS,SACd,CAAC,WAAW,KAAK,QAAQ,IAAI,CAAC,SAAS,SAAS,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,GAAG,IACrE,CAAC;AAAA,IACL,GAAI,KAAK,UAAU,SACf,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,SAAS,SAAS,IAAI,EAAE,EAAE,KAAK,IAAI,CAAC,GAAG,IACvE,CAAC;AAAA,EACP;AACA,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM,MAAM,KAAK,GAAG;AAAA,IACpB,WAAW;AAAA,EACb;AACF;AAEA,SAAS,aACP,OACA,KACA,OACA,WACA,OACM;AACN,QAAM,KAAK,IAAI,MAAM,EAAE;AACvB,QAAM,QAAQ,MAAM,QAAQ,CAAC;AAC7B,MAAI,MAAM,SAAS,gBAAiB,KAAI,KAAK,QAAQ,IAAI,KAAK,CAAC;AAAA,WACtD,MAAM,SAAS,cAAe,KAAI,KAAK,gBAAgB,IAAI,KAAK,CAAC;AAAA,WACjE,MAAM,SAAS,aAAa;AACnC,QAAI;AAAA,MACF,YAAY,IAAI,OAAO,MAAM,SAAS,KACpC,KAAK,IAAI,OAAO,WAAW,MAAM,QAAQ,IAAI,MAAM,EAAE,CAAC;AAAA,IAC1D;AAAA,WACO,MAAM,SAAS,kBAAkB,OAAO;AAC/C,UAAM,UAAU,UAAU,IAAI,KAAK;AACnC,QAAI,KAAK,iBAAiB,OAAO,CAAC;AAClC,eAAW,CAAC,KAAK,KAAK,KAAK,MAAM,CAAC,OAAO,CAAC,EAAG,OAAM,IAAI,KAAK,KAAK;AAAA,EACnE,WAAW,MAAM,SAAS,oBAAoB,MAAO,QAAO,OAAO,KAAK;AAAA,WAC/D,MAAM,SAAS,gBAAiB,KAAI,KAAK,OAAO,IAAI,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC;AAC7F;AAEA,MAAM,aAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AACR;AAEA,SAAS,KAAK,MAAwB,KAAgB,OAAoC;AACxF,QAAM,QAAQ,KAAK,KAAK,SAAS;AACjC,aAAW,QAAQ,OAAO,SAAS,CAAC,GAAG;AACrC,UAAM,OAAO,MAAM,IAAI,KAAK,MAAM;AAClC,QAAI,QAAQ,KAAK,WAAW,WAAW;AACrC,WAAK,SAAS,WAAW,KAAK,MAAM,KAAK;AACzC,WAAK,SAAS,KAAK,UAAU,KAAK;AAAA,IACpC;AAAA,EACF;AACA,QAAM,UAAU,OAAO,YAAY;AACnC,MAAI,QAAS,KAAI,KAAK,UAAU,QAAQ,SAAS,WAAW,CAAC;AAC7D,aAAW,cAAc,OAAO,eAAe,CAAC,GAAG;AACjD,QAAI,KAAK;AAAA,MACP,IAAI,cAAc,WAAW,MAAM;AAAA,MACnC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS,WAAW;AAAA,IACtB,CAAC;AAAA,EACH;AACA,QAAM,QAAQ,OAAO,YAAY;AACjC,MAAI;AACF,QAAI,KAAK;AAAA,MACP,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM,MAAM;AAAA,MACZ,WAAW,MAAM;AAAA,IACnB,CAAC;AACL;AAEO,SAAS,WACd,MACA,aAAkD,CAAC,GACxC;AACX,QAAM,MAAiB,CAAC;AACxB,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,oBAAI,IAAsB;AACxC,QAAM,QAAQ,EAAE,WAAW,cAAc,KAAK,OAAO,GAAG,SAAS,QAAQ,KAAK,OAAO,EAAE;AACvF,MAAI;AACJ,aAAW,SAAS,KAAK,SAAS;AAChC,UAAM,UAAU,UAAU,SAAS,mBAAmB,UAAU;AAChE,iBAAa,OAAO,KAAK,OAAO,WAAW,OAAO,MAAM,EAAE,CAAC,KAAK,SAAS,KAAK;AAC9E,eAAW;AAAA,EACb;AACA,OAAK,MAAM,KAAK,KAAK;AACrB,SAAO;AACT;AAEO,SAAS,OAAO,MAA6C;AAClE,SAAO,QAAS,MAAM,KAAK,SAAS,GAAwB,GAAG;AACjE;AAEO,SAAS,OAAO,MAAmD;AACxE,QAAM,QAAU,MAAM,KAAK,UAAU,GAAsC,SAAS,CAAC;AAKrF,SAAO,MACJ,OAAO,CAAC,SAAS,KAAK,SAAS,WAAW,CAAC,UAAU,OAAO,KAAK,OAAO,CAAC,CAAC,EAC1E,IAAI,CAAC,UAAU;AAAA,IACd,IAAI,IAAI,KAAK,EAAE;AAAA,IACf,MAAM;AAAA,IACN,MAAM,OAAO,KAAK,OAAO;AAAA,IACzB,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,MAAM,KAAK,SAAS,UAAU,UAAU;AAAA,EAC1C,EAAE;AACN;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,37 @@
1
+ import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
2
+ import { Emitter } from "./emitter.js";
3
+ class SprinkleAdapter extends Emitter {
4
+ #connection;
5
+ constructor(connection) {
6
+ super();
7
+ this.#connection = connection;
8
+ connection.sprinkles?.subscribe(() => this.emit("sprinkles", this.list()));
9
+ }
10
+ list() {
11
+ return this.#connection.sprinkles?.value ?? [];
12
+ }
13
+ send(id, payload) {
14
+ const value = payload ?? null;
15
+ void this.#connection.control.sprinkleSend(
16
+ id,
17
+ {
18
+ action: String(value?.action ?? ""),
19
+ data: value?.data ?? null,
20
+ target: typeof value?.target === "string" ? value.target : null
21
+ },
22
+ BACKGROUND_CONTEXT
23
+ );
24
+ }
25
+ call(id, method, args) {
26
+ return this.#connection.control.sprinkleCall(
27
+ id,
28
+ method,
29
+ args,
30
+ BACKGROUND_CONTEXT
31
+ );
32
+ }
33
+ }
34
+ export {
35
+ SprinkleAdapter
36
+ };
37
+ //# sourceMappingURL=sprinkle-port.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/spectrum/sprinkle-port.ts"],
4
+ "sourcesContent": ["import type { Sprinkle, SprinkleEvents, SprinklePort } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { JsonValue } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentConnection } from '../client.ts';\nimport { Emitter } from './emitter.ts';\n\ntype Payload = { action?: unknown; data?: unknown; target?: unknown } | null;\n\nexport class SprinkleAdapter extends Emitter<SprinkleEvents> implements SprinklePort {\n readonly #connection: AgentConnection;\n\n constructor(connection: AgentConnection) {\n super();\n this.#connection = connection;\n connection.sprinkles?.subscribe(() => this.emit('sprinkles', this.list()));\n }\n\n list(): readonly Sprinkle[] {\n return this.#connection.sprinkles?.value ?? [];\n }\n\n send(id: string, payload: unknown): void {\n const value = (payload ?? null) as Payload;\n void this.#connection.control.sprinkleSend(\n id,\n {\n action: String(value?.action ?? ''),\n data: (value?.data ?? null) as JsonValue | null,\n target: typeof value?.target === 'string' ? value.target : null,\n },\n BACKGROUND_CONTEXT\n );\n }\n\n call(id: string, method: string, args: readonly unknown[]): Promise<unknown> {\n return this.#connection.control.sprinkleCall(\n id,\n method,\n args as JsonValue[],\n BACKGROUND_CONTEXT\n );\n }\n}\n"],
5
+ "mappings": "AAEA,SAAS,0BAA0B;AAEnC,SAAS,eAAe;AAIjB,MAAM,wBAAwB,QAAgD;AAAA,EAC1E;AAAA,EAET,YAAY,YAA6B;AACvC,UAAM;AACN,SAAK,cAAc;AACnB,eAAW,WAAW,UAAU,MAAM,KAAK,KAAK,aAAa,KAAK,KAAK,CAAC,CAAC;AAAA,EAC3E;AAAA,EAEA,OAA4B;AAC1B,WAAO,KAAK,YAAY,WAAW,SAAS,CAAC;AAAA,EAC/C;AAAA,EAEA,KAAK,IAAY,SAAwB;AACvC,UAAM,QAAS,WAAW;AAC1B,SAAK,KAAK,YAAY,QAAQ;AAAA,MAC5B;AAAA,MACA;AAAA,QACE,QAAQ,OAAO,OAAO,UAAU,EAAE;AAAA,QAClC,MAAO,OAAO,QAAQ;AAAA,QACtB,QAAQ,OAAO,OAAO,WAAW,WAAW,MAAM,SAAS;AAAA,MAC7D;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,IAAY,QAAgB,MAA4C;AAC3E,WAAO,KAAK,YAAY,QAAQ;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,216 @@
1
+ import {
2
+ replicatedState
3
+ } from "@earendil-works/chord";
4
+ import {
5
+ describe,
6
+ homePath,
7
+ NO_EXEC,
8
+ SPRINKLE_KIND,
9
+ SPRINKLES_DIR,
10
+ SprinklesDoc,
11
+ sprinkleFiles,
12
+ WELCOME,
13
+ WELCOMED
14
+ } from "./sprinkles.js";
15
+ const USAGE = `usage:
16
+ sprinkle list every sprinkle in /home/sprinkles, with its owner
17
+ sprinkle show <name> show a sprinkle in your chat
18
+ sprinkle own <name> [<agent>] send its messages to <agent> (cone, cone-<n> or a scoop's handle)
19
+
20
+ A sprinkle is an .shtml file in /home/sprinkles, as <name>.shtml or <name>/<name>.shtml.
21
+ Every one of them has a button in the rail; edit the file and the open panel reloads.
22
+ `;
23
+ const RETIRED = {
24
+ open: "every sprinkle in /home/sprinkles already has a button in the rail; sprinkle show <name> shows one in the chat",
25
+ reload: "editing the .shtml file reloads the sprinkle",
26
+ close: "delete the .shtml file to retire a sprinkle; the user closes panels",
27
+ send: "a sprinkle reads data with slicc.readFile() or keeps it with slicc.setState(); write the file it reads",
28
+ chat: "show the sprinkle with sprinkle show <name> and wait for its lick"
29
+ };
30
+ function targetOf(agentId) {
31
+ return agentId.startsWith("scoop:") ? agentId : `cone:${agentId}`;
32
+ }
33
+ function agentOf(caller, agents) {
34
+ if (caller?.startsWith("cone:")) return caller.slice("cone:".length);
35
+ return caller ?? agents.activeCone();
36
+ }
37
+ function named(agents, value) {
38
+ const state = agents.state();
39
+ if (value in state.cones) return value;
40
+ const id = value.startsWith("scoop:") ? value : `scoop:${value}`;
41
+ return id in state.scoops ? id : void 0;
42
+ }
43
+ function setupSprinkles() {
44
+ return {
45
+ async attach(options, context) {
46
+ const { harness, agents, licks, env } = options;
47
+ const dir = options.dir ?? SPRINKLES_DIR;
48
+ const sprinkles = replicatedState([]);
49
+ const welcome = options.assets ? await options.assets("packages/vfs-root/sprinkles/welcome.shtml").catch(() => void 0) : void 0;
50
+ const owners = async (using) => (await harness.snapshot(SprinklesDoc, using))?.owners ?? {};
51
+ const reload = async (using) => {
52
+ const owned = await owners(using);
53
+ const out = [];
54
+ for (const { name, path } of await sprinkleFiles(env, dir, using)) {
55
+ if (name === WELCOME) continue;
56
+ const read = await env.readTextFile(path, using);
57
+ if (!read.ok) continue;
58
+ out.push({
59
+ id: name,
60
+ name,
61
+ ...describe(name, read.value),
62
+ agentId: owned[name] ?? agents.activeCone(),
63
+ html: read.value
64
+ });
65
+ }
66
+ if (welcome !== void 0)
67
+ out.push({
68
+ id: WELCOME,
69
+ name: WELCOME,
70
+ ...describe(WELCOME, welcome),
71
+ agentId: owned[WELCOME] ?? "cone",
72
+ html: welcome,
73
+ inline: true
74
+ });
75
+ sprinkles.replace(using, out);
76
+ };
77
+ const inside = async (path, using) => {
78
+ const asked = homePath(path);
79
+ const real = await env.canonicalPath(asked, using);
80
+ return real.ok ? homePath(real.value) : asked;
81
+ };
82
+ const offCone = agents.onCone(() => reload(context).catch(() => void 0));
83
+ const find = (id) => sprinkles.value.find((item) => item.id === id);
84
+ const post = async (id, agentId, using) => {
85
+ const conversation = await agents.conversation(agentId, using);
86
+ if (!conversation) throw new Error(`there is no agent ${agentId}`);
87
+ await conversation.submit(
88
+ { type: "write", entry: { kind: SPRINKLE_KIND, data: { sprinkle: id, at: Date.now() } } },
89
+ using
90
+ );
91
+ };
92
+ const setOwner = async (name, agentId, using) => {
93
+ await harness.commit(async (tx) => {
94
+ (await tx.doc(SprinklesDoc)).owners[name] = agentId;
95
+ }, using);
96
+ await reload(using);
97
+ };
98
+ await reload(context);
99
+ const state = await harness.snapshot(SprinklesDoc, context);
100
+ if (welcome !== void 0 && !state?.welcomed) {
101
+ await post(WELCOME, "cone", context);
102
+ await harness.commit(async (tx) => {
103
+ (await tx.doc(SprinklesDoc)).welcomed = true;
104
+ }, context);
105
+ }
106
+ let timer;
107
+ const watched = await env.watch(
108
+ [{ path: dir, recursive: true }],
109
+ () => {
110
+ clearTimeout(timer);
111
+ timer = setTimeout(() => void reload(context).catch(() => void 0), options.reloadMs);
112
+ },
113
+ context
114
+ );
115
+ const watcher = watched.ok ? watched.value : void 0;
116
+ const commands = {
117
+ async list(_argv, _caller, using) {
118
+ await reload(using);
119
+ const rows = sprinkles.value.filter((item) => !item.inline).map((item) => `${item.name} ${item.title} ${item.agentId}`);
120
+ return { code: 0, out: rows.length ? `${rows.join("\n")}
121
+ ` : "no sprinkles\n" };
122
+ },
123
+ async show(argv, caller, using) {
124
+ await reload(using);
125
+ const name = argv[1] ?? "";
126
+ if (!find(name)) return { code: 1, out: `sprinkle: there is no sprinkle ${name}
127
+ ` };
128
+ const agentId = agentOf(caller, agents);
129
+ await post(name, agentId, using);
130
+ if (!(await owners(using))[name]) await setOwner(name, agentId, using);
131
+ return { code: 0, out: `showed ${name} in the chat of ${agentId}
132
+ ` };
133
+ },
134
+ async own(argv, caller, using) {
135
+ const name = argv[1] ?? "";
136
+ if (!find(name)) return { code: 1, out: `sprinkle: there is no sprinkle ${name}
137
+ ` };
138
+ const agentId = argv[2] ? named(agents, argv[2]) : agentOf(caller, agents);
139
+ if (!agentId) return { code: 1, out: `sprinkle: there is no agent ${argv[2]}
140
+ ` };
141
+ await setOwner(name, agentId, using);
142
+ return { code: 0, out: `${name} now talks to ${agentId}
143
+ ` };
144
+ }
145
+ };
146
+ return {
147
+ sprinkles,
148
+ async send(id, payload, using) {
149
+ const sprinkle = find(id);
150
+ if (!sprinkle) return { delivered: false };
151
+ if (id === WELCOME && payload.action === "onboarding-complete")
152
+ await env.writeFile(WELCOMED, `${(/* @__PURE__ */ new Date()).toISOString()}
153
+ `, using);
154
+ await licks.deliver(
155
+ {
156
+ channel: "sprinkle",
157
+ source: `sprinkle:${id}`,
158
+ title: sprinkle.title,
159
+ text: payload.action || "(no action)",
160
+ ...payload.data === null ? {} : { body: JSON.stringify(payload.data, null, 2) },
161
+ target: targetOf((await owners(using))[id] ?? agents.activeCone())
162
+ },
163
+ using
164
+ );
165
+ return { delivered: true };
166
+ },
167
+ async call(id, method, args, using) {
168
+ if (!find(id)) throw new Error(`there is no sprinkle ${id}`);
169
+ const handlers = {
170
+ async readFile() {
171
+ const read = await env.readTextFile(await inside(args[0], using), using);
172
+ if (!read.ok) throw new Error(read.error.message);
173
+ return read.value;
174
+ },
175
+ async exists() {
176
+ const found = await env.exists(await inside(args[0], using), using);
177
+ return found.ok && found.value;
178
+ },
179
+ async getState() {
180
+ return (await harness.snapshot(SprinklesDoc, using))?.state[id] ?? null;
181
+ },
182
+ async setState() {
183
+ await harness.commit(async (tx) => {
184
+ (await tx.doc(SprinklesDoc)).state[id] = args[0] ?? null;
185
+ }, using);
186
+ return null;
187
+ }
188
+ };
189
+ const handler = handlers[method];
190
+ if (!handler) throw new Error(NO_EXEC);
191
+ return handler();
192
+ },
193
+ async command(argv, caller, using) {
194
+ const verb = argv[0] ?? "help";
195
+ const run = commands[verb];
196
+ if (run) return run(argv, caller, using);
197
+ if (verb in RETIRED)
198
+ return { code: 2, out: `sprinkle ${verb} isn't in SLICC: ${RETIRED[verb]}
199
+ ` };
200
+ return { code: verb === "help" || verb === "--help" ? 0 : 2, out: USAGE };
201
+ },
202
+ reload,
203
+ async close(using) {
204
+ offCone();
205
+ clearTimeout(timer);
206
+ await watcher?.close(using);
207
+ }
208
+ };
209
+ }
210
+ };
211
+ }
212
+ export {
213
+ USAGE,
214
+ setupSprinkles
215
+ };
216
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sprinkles/index.ts"],
4
+ "sourcesContent": ["import {\n type Context,\n type JsonValue,\n type ReplicatedState,\n replicatedState,\n} from '@earendil-works/chord';\nimport type { Harness } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Agents } from '../agents.ts';\nimport type { LickTarget } from '../licks/lick.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport {\n describe,\n homePath,\n NO_EXEC,\n SPRINKLE_KIND,\n SPRINKLES_DIR,\n type Sprinkle,\n type SprinkleMethod,\n SprinklesDoc,\n sprinkleFiles,\n WELCOME,\n WELCOMED,\n} from './sprinkles.ts';\n\nexport type Answer = { code: number; out: string };\n\nexport interface SprinklePayload {\n action: string;\n data: JsonValue | null;\n target: string | null;\n}\n\nexport interface SprinklesRuntime {\n readonly sprinkles: ReplicatedState<Sprinkle[]>;\n send(id: string, payload: SprinklePayload, context: Context): Promise<{ delivered: boolean }>;\n call(id: string, method: string, args: readonly unknown[], context: Context): Promise<JsonValue>;\n command(argv: readonly string[], caller: string | null, context: Context): Promise<Answer>;\n reload(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface SprinklesAttach {\n harness: Harness;\n agents: Agents;\n licks: Licks;\n env: ExecutionEnv;\n assets?: (path: string) => Promise<string>;\n reloadMs: number;\n dir?: string;\n}\n\nexport const USAGE = `usage:\n sprinkle list every sprinkle in /home/sprinkles, with its owner\n sprinkle show <name> show a sprinkle in your chat\n sprinkle own <name> [<agent>] send its messages to <agent> (cone, cone-<n> or a scoop's handle)\n\nA sprinkle is an .shtml file in /home/sprinkles, as <name>.shtml or <name>/<name>.shtml.\nEvery one of them has a button in the rail; edit the file and the open panel reloads.\n`;\n\nconst RETIRED: Record<string, string> = {\n open: 'every sprinkle in /home/sprinkles already has a button in the rail; sprinkle show <name> shows one in the chat',\n reload: 'editing the .shtml file reloads the sprinkle',\n close: 'delete the .shtml file to retire a sprinkle; the user closes panels',\n send: 'a sprinkle reads data with slicc.readFile() or keeps it with slicc.setState(); write the file it reads',\n chat: 'show the sprinkle with sprinkle show <name> and wait for its lick',\n};\n\nfunction targetOf(agentId: string): LickTarget {\n return agentId.startsWith('scoop:') ? (agentId as LickTarget) : `cone:${agentId}`;\n}\n\nfunction agentOf(caller: string | null, agents: Agents): string {\n if (caller?.startsWith('cone:')) return caller.slice('cone:'.length);\n return caller ?? agents.activeCone();\n}\n\nfunction named(agents: Agents, value: string): string | undefined {\n const state = agents.state();\n if (value in state.cones) return value;\n const id = value.startsWith('scoop:') ? value : `scoop:${value}`;\n return id in state.scoops ? id : undefined;\n}\n\nexport function setupSprinkles() {\n return {\n async attach(options: SprinklesAttach, context: Context): Promise<SprinklesRuntime> {\n const { harness, agents, licks, env } = options;\n const dir = options.dir ?? SPRINKLES_DIR;\n const sprinkles = replicatedState<Sprinkle[]>([]);\n const welcome = options.assets\n ? await options.assets('packages/vfs-root/sprinkles/welcome.shtml').catch(() => undefined)\n : undefined;\n const owners = async (using: Context) =>\n (await harness.snapshot(SprinklesDoc, using))?.owners ?? {};\n const reload = async (using: Context) => {\n const owned = await owners(using);\n const out: Sprinkle[] = [];\n for (const { name, path } of await sprinkleFiles(env, dir, using)) {\n if (name === WELCOME) continue;\n const read = await env.readTextFile(path, using);\n if (!read.ok) continue;\n out.push({\n id: name,\n name,\n ...describe(name, read.value),\n agentId: owned[name] ?? agents.activeCone(),\n html: read.value,\n });\n }\n if (welcome !== undefined)\n out.push({\n id: WELCOME,\n name: WELCOME,\n ...describe(WELCOME, welcome),\n agentId: owned[WELCOME] ?? 'cone',\n html: welcome,\n inline: true,\n });\n sprinkles.replace(using, out);\n };\n const inside = async (path: unknown, using: Context) => {\n const asked = homePath(path);\n const real = await env.canonicalPath(asked, using);\n return real.ok ? homePath(real.value) : asked;\n };\n const offCone = agents.onCone(() => reload(context).catch(() => undefined));\n const find = (id: string) => sprinkles.value.find((item) => item.id === id);\n const post = async (id: string, agentId: string, using: Context) => {\n const conversation = await agents.conversation(agentId, using);\n if (!conversation) throw new Error(`there is no agent ${agentId}`);\n await conversation.submit(\n { type: 'write', entry: { kind: SPRINKLE_KIND, data: { sprinkle: id, at: Date.now() } } },\n using\n );\n };\n const setOwner = async (name: string, agentId: string, using: Context) => {\n await harness.commit(async (tx) => {\n (await tx.doc(SprinklesDoc)).owners[name] = agentId;\n }, using);\n await reload(using);\n };\n await reload(context);\n const state = await harness.snapshot(SprinklesDoc, context);\n if (welcome !== undefined && !state?.welcomed) {\n await post(WELCOME, 'cone', context);\n await harness.commit(async (tx) => {\n (await tx.doc(SprinklesDoc)).welcomed = true;\n }, context);\n }\n let timer: ReturnType<typeof setTimeout> | undefined;\n const watched = await env.watch(\n [{ path: dir, recursive: true }],\n () => {\n clearTimeout(timer);\n timer = setTimeout(() => void reload(context).catch(() => undefined), options.reloadMs);\n },\n context\n );\n const watcher: FileWatcher | undefined = watched.ok ? watched.value : undefined;\n const commands: Record<\n string,\n (argv: readonly string[], caller: string | null, using: Context) => Promise<Answer>\n > = {\n async list(_argv, _caller, using) {\n await reload(using);\n const rows = sprinkles.value\n .filter((item) => !item.inline)\n .map((item) => `${item.name}\\t${item.title}\\t${item.agentId}`);\n return { code: 0, out: rows.length ? `${rows.join('\\n')}\\n` : 'no sprinkles\\n' };\n },\n async show(argv, caller, using) {\n await reload(using);\n const name = argv[1] ?? '';\n if (!find(name)) return { code: 1, out: `sprinkle: there is no sprinkle ${name}\\n` };\n const agentId = agentOf(caller, agents);\n await post(name, agentId, using);\n if (!(await owners(using))[name]) await setOwner(name, agentId, using);\n return { code: 0, out: `showed ${name} in the chat of ${agentId}\\n` };\n },\n async own(argv, caller, using) {\n const name = argv[1] ?? '';\n if (!find(name)) return { code: 1, out: `sprinkle: there is no sprinkle ${name}\\n` };\n const agentId = argv[2] ? named(agents, argv[2]) : agentOf(caller, agents);\n if (!agentId) return { code: 1, out: `sprinkle: there is no agent ${argv[2]}\\n` };\n await setOwner(name, agentId, using);\n return { code: 0, out: `${name} now talks to ${agentId}\\n` };\n },\n };\n return {\n sprinkles,\n async send(id, payload, using) {\n const sprinkle = find(id);\n if (!sprinkle) return { delivered: false };\n if (id === WELCOME && payload.action === 'onboarding-complete')\n await env.writeFile(WELCOMED, `${new Date().toISOString()}\\n`, using);\n await licks.deliver(\n {\n channel: 'sprinkle',\n source: `sprinkle:${id}`,\n title: sprinkle.title,\n text: payload.action || '(no action)',\n ...(payload.data === null ? {} : { body: JSON.stringify(payload.data, null, 2) }),\n target: targetOf((await owners(using))[id] ?? agents.activeCone()),\n },\n using\n );\n return { delivered: true };\n },\n async call(id, method, args, using) {\n if (!find(id)) throw new Error(`there is no sprinkle ${id}`);\n const handlers: Record<SprinkleMethod, () => Promise<JsonValue>> = {\n async readFile() {\n const read = await env.readTextFile(await inside(args[0], using), using);\n if (!read.ok) throw new Error(read.error.message);\n return read.value;\n },\n async exists() {\n const found = await env.exists(await inside(args[0], using), using);\n return found.ok && found.value;\n },\n async getState() {\n return (await harness.snapshot(SprinklesDoc, using))?.state[id] ?? null;\n },\n async setState() {\n await harness.commit(async (tx) => {\n (await tx.doc(SprinklesDoc)).state[id] = (args[0] ?? null) as JsonValue;\n }, using);\n return null;\n },\n };\n const handler = handlers[method as SprinkleMethod];\n if (!handler) throw new Error(NO_EXEC);\n return handler();\n },\n async command(argv, caller, using) {\n const verb = argv[0] ?? 'help';\n const run = commands[verb];\n if (run) return run(argv, caller, using);\n if (verb in RETIRED)\n return { code: 2, out: `sprinkle ${verb} isn't in SLICC: ${RETIRED[verb]}\\n` };\n return { code: verb === 'help' || verb === '--help' ? 0 : 2, out: USAGE };\n },\n reload,\n async close(using) {\n offCone();\n clearTimeout(timer);\n await watcher?.close(using);\n },\n };\n },\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,5 @@
1
+ const SPRINKLE_KIND = "slicc.sprinkle";
2
+ export {
3
+ SPRINKLE_KIND
4
+ };
5
+ //# sourceMappingURL=kind.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/sprinkles/kind.ts"],
4
+ "sourcesContent": ["export const SPRINKLE_KIND = 'slicc.sprinkle';\n\nexport interface Sprinkle {\n id: string;\n name: string;\n title: string;\n icon: string;\n agentId: string;\n html: string;\n inline?: boolean;\n}\n"],
5
+ "mappings": "AAAO,MAAM,gBAAgB;",
6
+ "names": []
7
+ }