@ai-ecoverse/slicc-agent 3.48.1 → 3.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +38 -6
  2. package/bin/agent +1 -0
  3. package/dist/control.js +1 -1
  4. package/dist/control.js.map +2 -2
  5. package/dist/freezer/index.js +29 -8
  6. package/dist/freezer/index.js.map +2 -2
  7. package/dist/freezer/title.js +2 -2
  8. package/dist/freezer/title.js.map +2 -2
  9. package/dist/gelatiere/catalog.js +1 -1
  10. package/dist/gelatiere/catalog.js.map +2 -2
  11. package/dist/gelatiere/index.js +44 -21
  12. package/dist/gelatiere/index.js.map +2 -2
  13. package/dist/gelatiere/store.js +9 -5
  14. package/dist/gelatiere/store.js.map +2 -2
  15. package/dist/index.js.map +2 -2
  16. package/dist/kernel/accounts.js +141 -0
  17. package/dist/kernel/accounts.js.map +7 -0
  18. package/dist/kernel/agent-users.js +180 -0
  19. package/dist/kernel/agent-users.js.map +7 -0
  20. package/dist/kernel/env.js +9 -3
  21. package/dist/kernel/env.js.map +2 -2
  22. package/dist/kernel/users.js +16 -1
  23. package/dist/kernel/users.js.map +2 -2
  24. package/dist/layout.js +62 -0
  25. package/dist/layout.js.map +7 -0
  26. package/dist/licks/index.js.map +2 -2
  27. package/dist/licks/sources.js +69 -20
  28. package/dist/licks/sources.js.map +2 -2
  29. package/dist/main.js +70 -36
  30. package/dist/main.js.map +2 -2
  31. package/dist/mcp/index.js +5 -3
  32. package/dist/mcp/index.js.map +2 -2
  33. package/dist/mcp/paths.js +15 -0
  34. package/dist/mcp/paths.js.map +7 -0
  35. package/dist/mcp/runtime.js +16 -14
  36. package/dist/mcp/runtime.js.map +3 -3
  37. package/dist/memory/extract.js +2 -1
  38. package/dist/memory/extract.js.map +2 -2
  39. package/dist/memory/prompt.js +5 -1
  40. package/dist/memory/prompt.js.map +2 -2
  41. package/dist/memory/runtime.js +9 -1
  42. package/dist/memory/runtime.js.map +2 -2
  43. package/dist/roles/roles.js +54 -15
  44. package/dist/roles/roles.js.map +2 -2
  45. package/dist/scoops/cli.js +40 -19
  46. package/dist/scoops/cli.js.map +2 -2
  47. package/dist/scoops/extension.js +19 -15
  48. package/dist/scoops/extension.js.map +2 -2
  49. package/dist/scoops/index.js +82 -11
  50. package/dist/scoops/index.js.map +2 -2
  51. package/dist/scoops/requests.js +2 -1
  52. package/dist/scoops/requests.js.map +2 -2
  53. package/dist/scoops/service.js +45 -38
  54. package/dist/scoops/service.js.map +2 -2
  55. package/dist/scoops/sync.js +63 -13
  56. package/dist/scoops/sync.js.map +2 -2
  57. package/dist/skills/index.js +76 -34
  58. package/dist/skills/index.js.map +3 -3
  59. package/dist/sprinkles/index.js +114 -25
  60. package/dist/sprinkles/index.js.map +2 -2
  61. package/dist/sprinkles/sprinkles.js +13 -4
  62. package/dist/sprinkles/sprinkles.js.map +2 -2
  63. package/dist/types/freezer/index.d.ts +3 -1
  64. package/dist/types/freezer/title.d.ts +1 -1
  65. package/dist/types/gelatiere/index.d.ts +8 -0
  66. package/dist/types/gelatiere/store.d.ts +3 -2
  67. package/dist/types/index.d.ts +1 -1
  68. package/dist/types/kernel/accounts.d.ts +29 -0
  69. package/dist/types/kernel/agent-users.d.ts +37 -0
  70. package/dist/types/kernel/env.d.ts +6 -0
  71. package/dist/types/kernel/users.d.ts +15 -0
  72. package/dist/types/layout.d.ts +26 -0
  73. package/dist/types/licks/index.d.ts +2 -1
  74. package/dist/types/licks/sources.d.ts +11 -1
  75. package/dist/types/mcp/paths.d.ts +3 -0
  76. package/dist/types/mcp/runtime.d.ts +3 -3
  77. package/dist/types/memory/prompt.d.ts +1 -0
  78. package/dist/types/memory/runtime.d.ts +1 -0
  79. package/dist/types/roles/roles.d.ts +14 -1
  80. package/dist/types/scoops/cli.d.ts +5 -0
  81. package/dist/types/scoops/extension.d.ts +6 -3
  82. package/dist/types/scoops/index.d.ts +9 -0
  83. package/dist/types/scoops/requests.d.ts +2 -0
  84. package/dist/types/scoops/service.d.ts +5 -3
  85. package/dist/types/scoops/sync.d.ts +9 -6
  86. package/dist/types/skills/index.d.ts +10 -2
  87. package/dist/types/sprinkles/index.d.ts +15 -0
  88. package/dist/types/sprinkles/sprinkles.d.ts +7 -1
  89. package/package.json +4 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sprinkles/sprinkles.ts"],
4
- "sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport { defineDoc } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { normalize } from '../kernel/paths.ts';\n\nexport { SPRINKLE_KIND, type Sprinkle } from './kind.ts';\n\nexport const SPRINKLES_DIR = '/home/sprinkles';\nexport const WELCOME = 'welcome';\nexport const SUGGESTIONS = 'suggestions';\nexport const SUGGESTIONS_DIR = '/home/.gelatiere';\nexport const SUGGESTIONS_STORE = `${SUGGESTIONS_DIR}/suggestions.json`;\nexport const WELCOMED = '/home/.welcomed';\nexport const WELCOME_PROFILE = '/home/.welcome.json';\nexport const DEFAULT_ICON = 'sparkles';\n\nexport type SprinkleMethod = 'readFile' | 'exists' | 'getState' | 'setState';\n\nexport const SprinklesDoc = defineDoc<{\n owners: Record<string, string>;\n state: Record<string, JsonValue>;\n welcomed: boolean;\n}>({\n kind: 'slicc.sprinkles',\n version: 1,\n scope: 'session',\n initial: () => ({ owners: {}, state: {}, welcomed: false }),\n});\n\nfunction decode(text: string): string {\n return text\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&amp;/g, '&');\n}\n\nexport function describe(name: string, html: string): { title: string; icon: string } {\n const title = /<title>([\\s\\S]*?)<\\/title>/i.exec(html)?.[1]?.trim();\n const icon =\n /<link\\b[^>]*\\brel=[\"']icon[\"'][^>]*\\bhref=[\"']([^\"']+)[\"']/i.exec(html)?.[1] ??\n /<link\\b[^>]*\\bhref=[\"']([^\"']+)[\"'][^>]*\\brel=[\"']icon[\"']/i.exec(html)?.[1];\n return { title: title ? decode(title) : name, icon: icon ?? DEFAULT_ICON };\n}\n\nexport const NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;\n\nexport async function sprinkleFiles(\n env: Pick<ExecutionEnv, 'listDir'>,\n dir: string,\n context: Context\n): Promise<{ name: string; path: string }[]> {\n const listed = await env.listDir(dir, context);\n if (!listed.ok) return [];\n const out = new Map<string, string>();\n for (const entry of [...listed.value].sort((a, b) => a.name.localeCompare(b.name))) {\n if (entry.kind !== 'directory' && entry.name.endsWith('.shtml')) {\n const name = entry.name.slice(0, -'.shtml'.length);\n if (NAME.test(name)) out.set(name, `${dir}/${entry.name}`);\n }\n if (entry.kind === 'directory' && NAME.test(entry.name) && !out.has(entry.name)) {\n const inner = await env.listDir(`${dir}/${entry.name}`, context);\n if (inner.ok && inner.value.some((item) => item.name === `${entry.name}.shtml`))\n out.set(entry.name, `${dir}/${entry.name}/${entry.name}.shtml`);\n }\n }\n return [...out].map(([name, path]) => ({ name, path }));\n}\n\nexport function homePath(path: unknown): string {\n if (typeof path !== 'string' || !path) throw new Error('a sprinkle reads files by absolute path');\n const mapped = path.startsWith('/shared/') ? `/home/${path.slice('/shared/'.length)}` : path;\n const segments = mapped.split('/');\n if (segments.includes('.') || segments.includes('..'))\n throw new Error(`a sprinkle reads paths without . or .. segments, not ${path}`);\n const resolved = normalize(mapped);\n if (resolved !== '/home' && !resolved.startsWith('/home/'))\n throw new Error(`a sprinkle can only read files in /home, not ${path}`);\n return resolved;\n}\n\nexport const NO_EXEC =\n \"sprinkles can't run commands in SLICC; send the agent a message with slicc.lick() and let it run them\";\n"],
5
- "mappings": "AACA,SAAS,iBAAiB;AAE1B,SAAS,iBAAiB;AAE1B,SAAS,qBAAoC;AAEtC,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAChB,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,oBAAoB,GAAG,eAAe;AAC5C,MAAM,WAAW;AACjB,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAIrB,MAAM,eAAe,UAIzB;AAAA,EACD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS,OAAO,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,GAAG,UAAU,MAAM;AAC3D,CAAC;AAED,SAAS,OAAO,MAAsB;AACpC,SAAO,KACJ,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,UAAU,GAAG;AAC1B;AAEO,SAAS,SAAS,MAAc,MAA+C;AACpF,QAAM,QAAQ,8BAA8B,KAAK,IAAI,IAAI,CAAC,GAAG,KAAK;AAClE,QAAM,OACJ,8DAA8D,KAAK,IAAI,IAAI,CAAC,KAC5E,8DAA8D,KAAK,IAAI,IAAI,CAAC;AAC9E,SAAO,EAAE,OAAO,QAAQ,OAAO,KAAK,IAAI,MAAM,MAAM,QAAQ,aAAa;AAC3E;AAEO,MAAM,OAAO;AAEpB,eAAsB,cACpB,KACA,KACA,SAC2C;AAC3C,QAAM,SAAS,MAAM,IAAI,QAAQ,KAAK,OAAO;AAC7C,MAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,SAAS,CAAC,GAAG,OAAO,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,GAAG;AAClF,QAAI,MAAM,SAAS,eAAe,MAAM,KAAK,SAAS,QAAQ,GAAG;AAC/D,YAAM,OAAO,MAAM,KAAK,MAAM,GAAG,CAAC,SAAS,MAAM;AACjD,UAAI,KAAK,KAAK,IAAI,EAAG,KAAI,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,EAAE;AAAA,IAC3D;AACA,QAAI,MAAM,SAAS,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,MAAM,IAAI,GAAG;AAC/E,YAAM,QAAQ,MAAM,IAAI,QAAQ,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,OAAO;AAC/D,UAAI,MAAM,MAAM,MAAM,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,GAAG,MAAM,IAAI,QAAQ;AAC5E,YAAI,IAAI,MAAM,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ;AAAA,IAClE;AAAA,EACF;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,KAAK,EAAE;AACxD;AAEO,SAAS,SAAS,MAAuB;AAC9C,MAAI,OAAO,SAAS,YAAY,CAAC,KAAM,OAAM,IAAI,MAAM,yCAAyC;AAChG,QAAM,SAAS,KAAK,WAAW,UAAU,IAAI,SAAS,KAAK,MAAM,WAAW,MAAM,CAAC,KAAK;AACxF,QAAM,WAAW,OAAO,MAAM,GAAG;AACjC,MAAI,SAAS,SAAS,GAAG,KAAK,SAAS,SAAS,IAAI;AAClD,UAAM,IAAI,MAAM,wDAAwD,IAAI,EAAE;AAChF,QAAM,WAAW,UAAU,MAAM;AACjC,MAAI,aAAa,WAAW,CAAC,SAAS,WAAW,QAAQ;AACvD,UAAM,IAAI,MAAM,gDAAgD,IAAI,EAAE;AACxE,SAAO;AACT;AAEO,MAAM,UACX;",
4
+ "sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport { defineDoc } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { normalize } from '../kernel/paths.ts';\n\nexport { SPRINKLE_KIND, type Sprinkle } from './kind.ts';\n\nexport const SPRINKLES_DIR = '/home/sprinkles';\nexport const WELCOME = 'welcome';\nexport const SUGGESTIONS = 'suggestions';\nexport const SUGGESTIONS_DIR = '/home/.gelatiere';\nexport const SUGGESTIONS_STORE = `${SUGGESTIONS_DIR}/suggestions.json`;\nexport const WELCOMED = '/home/.welcomed';\nexport const WELCOME_PROFILE = '/home/.welcome.json';\nexport const DEFAULT_ICON = 'sparkles';\n\nexport type SprinkleMethod = 'readFile' | 'exists' | 'getState' | 'setState';\n\nexport const SprinklesDoc = defineDoc<{\n owners: Record<string, string>;\n state: Record<string, JsonValue>;\n welcomed: boolean;\n}>({\n kind: 'slicc.sprinkles',\n version: 1,\n scope: 'session',\n initial: () => ({ owners: {}, state: {}, welcomed: false }),\n});\n\nfunction decode(text: string): string {\n return text\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&amp;/g, '&');\n}\n\nexport function describe(name: string, html: string): { title: string; icon: string } {\n const title = /<title>([\\s\\S]*?)<\\/title>/i.exec(html)?.[1]?.trim();\n const icon =\n /<link\\b[^>]*\\brel=[\"']icon[\"'][^>]*\\bhref=[\"']([^\"']+)[\"']/i.exec(html)?.[1] ??\n /<link\\b[^>]*\\bhref=[\"']([^\"']+)[\"'][^>]*\\brel=[\"']icon[\"']/i.exec(html)?.[1];\n return { title: title ? decode(title) : name, icon: icon ?? DEFAULT_ICON };\n}\n\nexport const NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;\n\nexport async function sprinkleFiles(\n env: Pick<ExecutionEnv, 'listDir'>,\n dir: string,\n context: Context\n): Promise<{ name: string; path: string }[]> {\n const listed = await env.listDir(dir, context);\n if (!listed.ok) return [];\n const out = new Map<string, string>();\n for (const entry of [...listed.value].sort((a, b) => a.name.localeCompare(b.name))) {\n if (entry.kind !== 'directory' && entry.name.endsWith('.shtml')) {\n const name = entry.name.slice(0, -'.shtml'.length);\n if (NAME.test(name)) out.set(name, `${dir}/${entry.name}`);\n }\n if (entry.kind === 'directory' && NAME.test(entry.name) && !out.has(entry.name)) {\n const inner = await env.listDir(`${dir}/${entry.name}`, context);\n if (inner.ok && inner.value.some((item) => item.name === `${entry.name}.shtml`))\n out.set(entry.name, `${dir}/${entry.name}/${entry.name}.shtml`);\n }\n }\n return [...out].map(([name, path]) => ({ name, path }));\n}\n\nexport function homePath(path: unknown, shared = '/home', root = '/home'): string {\n if (typeof path !== 'string' || !path) throw new Error('a sprinkle reads files by absolute path');\n const mapped = path.startsWith('/shared/') ? `${shared}/${path.slice('/shared/'.length)}` : path;\n const segments = mapped.split('/');\n if (segments.includes('.') || segments.includes('..'))\n throw new Error(`a sprinkle reads paths without . or .. segments, not ${path}`);\n const resolved = normalize(mapped);\n if (resolved !== root && !resolved.startsWith(`${root}/`))\n throw new Error(`a sprinkle can only read files in ${root}, not ${path}`);\n return resolved;\n}\n\nexport function sharedPaths(shared: string) {\n return {\n suggestionsDir: `${shared}/.gelatiere`,\n suggestions: `${shared}/.gelatiere/suggestions.json`,\n welcomed: `${shared}/.welcomed`,\n profile: `${shared}/.welcome.json`,\n };\n}\n\nexport const NO_EXEC =\n \"sprinkles can't run commands in SLICC; send the agent a message with slicc.lick() and let it run them\";\n"],
5
+ "mappings": "AACA,SAAS,iBAAiB;AAE1B,SAAS,iBAAiB;AAE1B,SAAS,qBAAoC;AAEtC,MAAM,gBAAgB;AACtB,MAAM,UAAU;AAChB,MAAM,cAAc;AACpB,MAAM,kBAAkB;AACxB,MAAM,oBAAoB,GAAG,eAAe;AAC5C,MAAM,WAAW;AACjB,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAIrB,MAAM,eAAe,UAIzB;AAAA,EACD,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS,OAAO,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,GAAG,UAAU,MAAM;AAC3D,CAAC;AAED,SAAS,OAAO,MAAsB;AACpC,SAAO,KACJ,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,WAAW,GAAG,EACtB,QAAQ,UAAU,GAAG,EACrB,QAAQ,UAAU,GAAG;AAC1B;AAEO,SAAS,SAAS,MAAc,MAA+C;AACpF,QAAM,QAAQ,8BAA8B,KAAK,IAAI,IAAI,CAAC,GAAG,KAAK;AAClE,QAAM,OACJ,8DAA8D,KAAK,IAAI,IAAI,CAAC,KAC5E,8DAA8D,KAAK,IAAI,IAAI,CAAC;AAC9E,SAAO,EAAE,OAAO,QAAQ,OAAO,KAAK,IAAI,MAAM,MAAM,QAAQ,aAAa;AAC3E;AAEO,MAAM,OAAO;AAEpB,eAAsB,cACpB,KACA,KACA,SAC2C;AAC3C,QAAM,SAAS,MAAM,IAAI,QAAQ,KAAK,OAAO;AAC7C,MAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,SAAS,CAAC,GAAG,OAAO,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,GAAG;AAClF,QAAI,MAAM,SAAS,eAAe,MAAM,KAAK,SAAS,QAAQ,GAAG;AAC/D,YAAM,OAAO,MAAM,KAAK,MAAM,GAAG,CAAC,SAAS,MAAM;AACjD,UAAI,KAAK,KAAK,IAAI,EAAG,KAAI,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,EAAE;AAAA,IAC3D;AACA,QAAI,MAAM,SAAS,eAAe,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,IAAI,MAAM,IAAI,GAAG;AAC/E,YAAM,QAAQ,MAAM,IAAI,QAAQ,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,OAAO;AAC/D,UAAI,MAAM,MAAM,MAAM,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,GAAG,MAAM,IAAI,QAAQ;AAC5E,YAAI,IAAI,MAAM,MAAM,GAAG,GAAG,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,QAAQ;AAAA,IAClE;AAAA,EACF;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,KAAK,EAAE;AACxD;AAEO,SAAS,SAAS,MAAe,SAAS,SAAS,OAAO,SAAiB;AAChF,MAAI,OAAO,SAAS,YAAY,CAAC,KAAM,OAAM,IAAI,MAAM,yCAAyC;AAChG,QAAM,SAAS,KAAK,WAAW,UAAU,IAAI,GAAG,MAAM,IAAI,KAAK,MAAM,WAAW,MAAM,CAAC,KAAK;AAC5F,QAAM,WAAW,OAAO,MAAM,GAAG;AACjC,MAAI,SAAS,SAAS,GAAG,KAAK,SAAS,SAAS,IAAI;AAClD,UAAM,IAAI,MAAM,wDAAwD,IAAI,EAAE;AAChF,QAAM,WAAW,UAAU,MAAM;AACjC,MAAI,aAAa,QAAQ,CAAC,SAAS,WAAW,GAAG,IAAI,GAAG;AACtD,UAAM,IAAI,MAAM,qCAAqC,IAAI,SAAS,IAAI,EAAE;AAC1E,SAAO;AACT;AAEO,SAAS,YAAY,QAAgB;AAC1C,SAAO;AAAA,IACL,gBAAgB,GAAG,MAAM;AAAA,IACzB,aAAa,GAAG,MAAM;AAAA,IACtB,UAAU,GAAG,MAAM;AAAA,IACnB,SAAS,GAAG,MAAM;AAAA,EACpB;AACF;AAEO,MAAM,UACX;",
6
6
  "names": []
7
7
  }
@@ -2,6 +2,7 @@ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { EntryRecord, Harness } from '@earendil-works/pi-durable';
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  import { type Agents, type AgentsState, type FrozenRecord } from '../agents.ts';
5
+ import { type Layout } from '../layout.ts';
5
6
  import type { LickTarget } from '../licks/lick.ts';
6
7
  export type Answer = {
7
8
  code: number;
@@ -32,6 +33,7 @@ export interface FreezerAttach {
32
33
  title?: (transcript: string, model: string, context: Context) => Promise<string | undefined>;
33
34
  extract?: (conversation: number, tail: number, context: Context, cone: string) => Promise<unknown>;
34
35
  now?: () => number;
36
+ layout?: Layout;
35
37
  }
36
38
  export interface FreezerRuntime {
37
39
  readonly frozen: ReplicatedState<FrozenCone[]>;
@@ -53,6 +55,6 @@ export declare function modelName(model: {
53
55
  } | undefined): string;
54
56
  export declare function firstLine(entries: readonly EntryRecord[]): string;
55
57
  export declare function markdown(record: Pick<FrozenRecord, 'title' | 'name' | 'model' | 'frozenAt'>, entries: readonly EntryRecord[]): string;
56
- export declare function thawedNote(kind: ConversationKind, name: string, folder: string, kept: boolean): string;
58
+ export declare function thawedNote(kind: ConversationKind, name: string, folder: string, kept: boolean, home?: string): string;
57
59
  export declare function frozenTarget(state: Readonly<AgentsState>, target: LickTarget): Frozen | undefined;
58
60
  export declare function attachFreezer(options: FreezerAttach): FreezerRuntime;
@@ -2,5 +2,5 @@ import type { Context } from '@earendil-works/chord';
2
2
  import type { Models } from '@earendil-works/pi-ai/models';
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  export declare const TITLE_PROMPT = "Give this chat a title of three to six words that says what it was about. Answer with the title only, without quotes.";
5
- export declare function settingsText(env: Pick<ExecutionEnv, 'readTextFile'>, home: string): (context: Context) => Promise<string | undefined>;
5
+ export declare function settingsText(env: Pick<ExecutionEnv, 'readTextFile'>, home: string, dir?: string): (context: Context) => Promise<string | undefined>;
6
6
  export declare function titler(models: Models, settings: (context: Context) => Promise<string | undefined>): (transcript: string, model: string, context: Context) => Promise<string | undefined>;
@@ -27,6 +27,14 @@ export interface GelatiereAttach {
27
27
  skills?: () => readonly {
28
28
  name: string;
29
29
  }[];
30
+ files?: ExecutionEnv;
31
+ profile?: string;
32
+ shared?: string;
33
+ as?: (caller: string | null, context: Context) => Promise<Caller | undefined>;
34
+ }
35
+ export interface Caller {
36
+ env: ExecutionEnv;
37
+ home: string;
30
38
  }
31
39
  export interface GelatiereRuntime {
32
40
  command(argv: readonly string[], caller: string | null, context: Context): Promise<Answer>;
@@ -33,5 +33,6 @@ export declare function fold(store: readonly Suggestion[], candidates: unknown,
33
33
  rejected: string[];
34
34
  };
35
35
  export declare function open(store: readonly Suggestion[]): Suggestion[];
36
- export declare function readStore(env: Pick<ExecutionEnv, 'readTextFile'>, context: Context): Promise<Suggestion[] | null>;
37
- export declare function writeStore(env: Pick<ExecutionEnv, 'writeFile' | 'createDir'>, store: readonly Suggestion[], context: Context): Promise<void>;
36
+ export declare function storeOf(shared: string): string;
37
+ export declare function readStore(env: Pick<ExecutionEnv, 'readTextFile'>, context: Context, file?: string): Promise<Suggestion[] | null>;
38
+ export declare function writeStore(env: Pick<ExecutionEnv, 'writeFile' | 'createDir'>, store: readonly Suggestion[], context: Context, file?: string): Promise<void>;
@@ -7,7 +7,7 @@ export { CREDENTIALS_DATABASE, EncryptedCredentialStore } from './credentials.ts
7
7
  export { type AgentHost, type ConnectOptions, hostAgent } from './host.ts';
8
8
  export type { KernelClient, KernelFs, KernelProcess, KernelStat, SpawnOptions, } from './kernel/client.ts';
9
9
  export { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';
10
- export { adminOver, type KernelAdmin, type KernelUser, type KernelUsers, serveAdmin, type UserClient, type UserClients, type UserConnect, type UserSpec, userClients, } from './kernel/users.ts';
10
+ export { adminOver, type KernelAdmin, type KernelGroup, type KernelGroups, type KernelUser, type KernelUsers, serveAdmin, type UserClient, type UserClients, type UserConnect, type UserSpec, userClients, } from './kernel/users.ts';
11
11
  export { PortListener } from './listener.ts';
12
12
  export { type AgentWorkerOptions, type AgentWorkerScope, type KernelAttach, runAgentWorker, } from './main.ts';
13
13
  export { type Loopback, type Transport, type TransportResponse, transportFetch, } from './net.ts';
@@ -0,0 +1,29 @@
1
+ import type { Agents, AgentsState } from '../agents.ts';
2
+ import type { KernelClient } from './client.ts';
3
+ import type { KernelGroups, UserClients, UserSpec } from './users.ts';
4
+ export type UsersMode = 'off' | 'report' | 'enforce';
5
+ export declare const SCOOP_UMASK = 23;
6
+ export declare const CONE_UMASK = 63;
7
+ export declare const CONE_HOME_MODE = 456;
8
+ export declare const SCOOP_HOME_MODE = 1512;
9
+ export declare const SUDO_GROUP = "sudo";
10
+ export declare const CONE_PREFIX = "cone:";
11
+ export declare const SCOOP_USER = "scoop-";
12
+ export declare function scoopUser(folder: string): string;
13
+ export declare function homeOf(user: string): string;
14
+ export declare function userOf(state: Readonly<AgentsState>, agentId: string): string | undefined;
15
+ export type Wanted = {
16
+ agentId: string;
17
+ cone: string | null;
18
+ spec: UserSpec;
19
+ };
20
+ export declare function wanted(state: Readonly<AgentsState>): Wanted[];
21
+ export interface Accounts {
22
+ readonly mode: UsersMode;
23
+ agentOf(conversation: number | undefined): string | undefined;
24
+ home(agentId: string): string | undefined;
25
+ client(agentId: string): Promise<KernelClient>;
26
+ reconcile(): Promise<void>;
27
+ boot(): Promise<void>;
28
+ }
29
+ export declare function createAccounts(pool: UserClients, agents: () => Agents | undefined, mode?: UsersMode, groups?: KernelGroups, warn?: (message: string) => void): Accounts;
@@ -0,0 +1,37 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import type { Agents, AgentsState } from '../agents.ts';
3
+ import type { GelatiereAttach } from '../gelatiere/index.ts';
4
+ import { type Layout } from '../layout.ts';
5
+ import type { LickDir } from '../licks/sources.ts';
6
+ import type { Spools } from '../scoops/index.ts';
7
+ import type { SkillPeople } from '../skills/index.ts';
8
+ import type { SprinklePlace, SprinklesAttach } from '../sprinkles/index.ts';
9
+ import { type Accounts, type UsersMode } from './accounts.ts';
10
+ import type { KernelClient } from './client.ts';
11
+ import { type EnvRoute, type EnvTargetLike, SliccKernelEnv } from './env.ts';
12
+ import type { UserClients } from './users.ts';
13
+ export interface AgentUsers {
14
+ readonly accounts: Accounts;
15
+ readonly layout: Layout;
16
+ readonly spools: Spools;
17
+ readonly enforced: boolean;
18
+ readonly people: SkillPeople;
19
+ follow(runtimes: readonly {
20
+ reload?(context: Context): Promise<void>;
21
+ reconcile?(context: Context): Promise<void>;
22
+ }[]): void;
23
+ lickDirs(): Promise<LickDir[]>;
24
+ sprinklePlaces(): SprinklePlace[];
25
+ sprinkles(): Partial<SprinklesAttach>;
26
+ envOfAgent(agentId: string): Promise<SliccKernelEnv | undefined>;
27
+ gelatiere(root: SliccKernelEnv): Promise<Partial<GelatiereAttach>>;
28
+ route(target: EnvTargetLike): Promise<EnvRoute | undefined>;
29
+ start(agents: Agents): Promise<void>;
30
+ close(): void;
31
+ }
32
+ export declare function modeOf(client: KernelClient): UsersMode;
33
+ export declare function missingSupport(pool: UserClients | undefined, client: KernelClient, requested: boolean | undefined): Promise<string[]>;
34
+ export declare function warnSupport(pool: UserClients | undefined, client: KernelClient, requested: boolean | undefined, report?: (message: string) => void): Promise<void>;
35
+ export declare function legacyCwd(state: Readonly<AgentsState>, agentId: string, cwd: string): boolean;
36
+ export declare function spoolScript(user: string, dir: string): string;
37
+ export declare function agentUsers(pool: UserClients, client: KernelClient, root: SliccKernelEnv, agents: () => Agents | undefined): AgentUsers;
@@ -70,7 +70,13 @@ export type EnvTargetLike = {
70
70
  conversationId?: number;
71
71
  read?: unknown;
72
72
  };
73
+ export type EnvRoute = {
74
+ client: KernelClient;
75
+ home: string;
76
+ cwd?: string;
77
+ };
73
78
  export declare function kernelEnvironment(client: KernelClient, options?: Omit<KernelEnvOptions, 'cwd'> & {
74
79
  identify?: (target: EnvTargetLike, context: Context) => Promise<Record<string, string>>;
80
+ route?: (target: EnvTargetLike) => Promise<EnvRoute | undefined>;
75
81
  }): (target: EnvTargetLike, context?: Context) => SliccKernelEnv | Promise<SliccKernelEnv>;
76
82
  export {};
@@ -15,6 +15,7 @@ export interface UserSpec {
15
15
  groups?: string[];
16
16
  umask?: number;
17
17
  homeGroup?: string;
18
+ homeMode?: number;
18
19
  }
19
20
  export interface KernelUsers {
20
21
  add(spec: UserSpec): Promise<KernelUser>;
@@ -22,6 +23,17 @@ export interface KernelUsers {
22
23
  keepHome?: boolean;
23
24
  }): Promise<boolean>;
24
25
  list(): Promise<KernelUser[]>;
26
+ mode?: string;
27
+ }
28
+ export interface KernelGroup {
29
+ name: string;
30
+ gid: number;
31
+ members: string[];
32
+ }
33
+ export interface KernelGroups {
34
+ list(): Promise<KernelGroup[]>;
35
+ addMember(group: string, user: string): Promise<unknown>;
36
+ removeMember(group: string, user: string): Promise<unknown>;
25
37
  }
26
38
  export interface UserConnect {
27
39
  user?: string;
@@ -30,10 +42,12 @@ export interface UserConnect {
30
42
  export interface KernelSource {
31
43
  connect(options?: UserConnect): Promise<Transferable>;
32
44
  users?: KernelUsers;
45
+ groups?: KernelGroups;
33
46
  }
34
47
  export interface KernelAdmin {
35
48
  connect(options: UserConnect): Promise<MessagePort>;
36
49
  users: KernelUsers;
50
+ groups: KernelGroups;
37
51
  close(): void;
38
52
  }
39
53
  export declare function serveAdmin(port: PortEndpoint, source: KernelSource): void;
@@ -46,6 +60,7 @@ export type UserClient = KernelClient & {
46
60
  };
47
61
  export interface UserClients {
48
62
  readonly users: KernelUsers;
63
+ readonly groups: KernelGroups;
49
64
  client(agentId: string, user: string): Promise<UserClient>;
50
65
  drop(agentId: string): Promise<void>;
51
66
  close(): Promise<void>;
@@ -0,0 +1,26 @@
1
+ import type { Context } from '@earendil-works/chord';
2
+ import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
3
+ import type { AgentsState } from './agents.ts';
4
+ export declare const SCOOPS_ROOT = "/scoops";
5
+ export declare const SESSIONS: {
6
+ tmp: string;
7
+ durable: string;
8
+ };
9
+ export declare const ROOT_USER = "root";
10
+ export declare const AGENT_DIR = "/etc/slicc/agent";
11
+ export declare const ROOT_HOME = "/root";
12
+ export declare const SHARED_DIR = "/var/lib/slicc/agent/shared";
13
+ export type Persist = 'tmp' | 'durable';
14
+ export interface Layout {
15
+ readonly users: boolean;
16
+ scoopRoot(folder: string): string;
17
+ workspace(folder: string): string;
18
+ reports(folder: string, cone: string): string;
19
+ sessions(persist: Persist, user: string | null): string;
20
+ homeOf(user: string | null): string;
21
+ envFor(user: string | null, context: Context): Promise<ExecutionEnv | undefined>;
22
+ ownDir(path: string, user: string | null, context: Context): Promise<void>;
23
+ }
24
+ export declare const LEGACY: Layout;
25
+ export declare function agentOfUser(state: Readonly<AgentsState>, user: string): string | undefined;
26
+ export declare function usersLayout(state: () => Readonly<AgentsState>, envOf: (agentId: string, home: string) => Promise<ExecutionEnv>, root: Pick<ExecutionEnv, 'exec'>): Layout;
@@ -5,7 +5,7 @@ import { type Agents } from '../agents.ts';
5
5
  import type { Activity } from '../kernel/activity.ts';
6
6
  import type { LickChannel, LickTarget } from './lick.ts';
7
7
  import { type Licks } from './licks.ts';
8
- import { type LickSources } from './sources.ts';
8
+ import { type LickDir, type LickSources } from './sources.ts';
9
9
  export interface LicksAgent {
10
10
  harness: Harness;
11
11
  root: Conversation;
@@ -21,6 +21,7 @@ export interface LicksSetup {
21
21
  now?: () => number;
22
22
  flushEvery?: number;
23
23
  activity?: Activity;
24
+ dirs?: () => Promise<readonly LickDir[]>;
24
25
  }): LickSources;
25
26
  }
26
27
  export declare function setupLicks(registry: Registry): LicksSetup;
@@ -5,6 +5,7 @@ import type { Activity } from '../kernel/activity.ts';
5
5
  import { type BootFacts } from './boot.ts';
6
6
  import { type ConfigError, type WebhookEntry } from './config.ts';
7
7
  import type { cronTask } from './extension.ts';
8
+ import type { LickTarget } from './lick.ts';
8
9
  import type { LickEvent, Licks } from './licks.ts';
9
10
  export declare const SLICC_DIR = ".slicc";
10
11
  export interface LickSourcesOptions {
@@ -18,7 +19,16 @@ export interface LickSourcesOptions {
18
19
  now?: () => number;
19
20
  flushEvery?: number;
20
21
  activity?: Activity;
22
+ dirs?: () => readonly LickDir[] | Promise<readonly LickDir[]>;
21
23
  }
24
+ export interface LickDir {
25
+ dir: string;
26
+ home: string;
27
+ cone: string | null;
28
+ env?: ExecutionEnv;
29
+ }
30
+ export declare function scopedTarget(target: LickTarget, cone: string | null): LickTarget;
31
+ export declare function scopedName(name: string, cone: string | null): string;
22
32
  export interface WebhookDelivery {
23
33
  id?: string;
24
34
  headers?: Record<string, string>;
@@ -33,6 +43,6 @@ export interface LickSources {
33
43
  }
34
44
  export declare function hash(text: string): string;
35
45
  export declare function shortPath(path: string, home: string): string;
36
- export declare function configLick(error: ConfigError, home: string): LickEvent;
46
+ export declare function configLick(error: ConfigError, home: string, cone?: string | null): LickEvent;
37
47
  export declare function webhookLick(name: string, entry: WebhookEntry, delivery: WebhookDelivery): LickEvent;
38
48
  export declare function createLickSources(options: LickSourcesOptions): LickSources;
@@ -0,0 +1,3 @@
1
+ export declare function configPath(home: string, dir?: string): string;
2
+ export declare function logPath(home: string, dir?: string): string;
3
+ export declare function shown(path: string, home: string): string;
@@ -8,12 +8,12 @@ import { McpCatalog } from './catalog.ts';
8
8
  import { type McpConfigProblem } from './config.ts';
9
9
  import { McpServerConnection } from './connection.ts';
10
10
  export declare const MCP_LOG_MAX_BYTES: number;
11
- export declare function configPath(home: string): string;
12
- export declare function logPath(home: string): string;
11
+ export { configPath, logPath, shown } from './paths.ts';
13
12
  export interface McpAttach {
14
13
  licks: Licks;
15
14
  env: ExecutionEnv;
16
15
  home: string;
16
+ agentDir?: string;
17
17
  credentials: CredentialStore;
18
18
  fetch: typeof fetch;
19
19
  version: string;
@@ -35,7 +35,7 @@ export interface McpRuntime extends McpAccounts {
35
35
  reload(context: Context): Promise<void>;
36
36
  close(context: Context): Promise<void>;
37
37
  }
38
- export declare function problemLick(problem: McpConfigProblem, home: string): LickEvent;
38
+ export declare function problemLick(problem: McpConfigProblem, home: string, dir?: string): LickEvent;
39
39
  export declare function stateLick(connection: McpServerConnection, cors: boolean): LickEvent | undefined;
40
40
  export declare function connectedLick(connection: McpServerConnection): LickEvent;
41
41
  export declare function logLine(server: string, params: unknown, secrets: readonly string[], at: Date): string;
@@ -10,6 +10,7 @@ export type Host = {
10
10
  agents: Agents;
11
11
  env: ExecutionEnv;
12
12
  home: string;
13
+ agentDir?: string;
13
14
  files: MemoryFiles;
14
15
  changed: (context: Context) => Promise<void>;
15
16
  };
@@ -32,6 +32,7 @@ export interface MemoryAttach {
32
32
  agents: Agents;
33
33
  env: ExecutionEnv;
34
34
  home: string;
35
+ agentDir?: string;
35
36
  reloadMs: number;
36
37
  idleCheckMs?: number;
37
38
  roles?: (context: Context) => Promise<{
@@ -54,4 +54,17 @@ export declare function loadRoles(options: LoadOptions, context: Context): Promi
54
54
  export declare function findRole(roles: readonly Role[], name: string): Role | undefined;
55
55
  export declare function manifestDirs(files: RoleFiles, root: string, context: Context): Promise<string[]>;
56
56
  export declare function agentPaths(dir: string, text: string): string[];
57
- export declare function packageDirs(files: RoleFiles, root: string, context: Context): Promise<string[]>;
57
+ export declare const PACKAGE_ROOTS: string[];
58
+ export interface PiPackage {
59
+ dir: string;
60
+ manifest: string;
61
+ }
62
+ export interface PiPackages {
63
+ packages: PiPackage[];
64
+ skipped: {
65
+ path: string;
66
+ message: string;
67
+ }[];
68
+ }
69
+ export declare function piPackages(files: RoleFiles, roots: readonly string[], context: Context): Promise<PiPackages>;
70
+ export declare function packageDirs(files: RoleFiles, roots: readonly string[], context: Context): Promise<string[]>;
@@ -2,6 +2,7 @@ import type { Context } from '@earendil-works/chord';
2
2
  import type { Harness } from '@earendil-works/pi-durable';
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  import type { Agents, AgentsState } from '../agents.ts';
5
+ import { type Layout } from '../layout.ts';
5
6
  import { type Roles } from '../roles/roles.ts';
6
7
  import type { Request, Runner } from './requests.ts';
7
8
  import { type Answer, type Scoops } from './service.ts';
@@ -23,6 +24,7 @@ export interface CliOptions {
23
24
  gelatiere?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
24
25
  freezer?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
25
26
  models?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
27
+ layout?: Layout;
26
28
  panel?: (argv: readonly string[], caller: PanelCaller, context: Context) => Promise<Answer>;
27
29
  }
28
30
  export interface PanelCaller {
@@ -33,6 +35,7 @@ export interface PanelCaller {
33
35
  export type Deps = CliOptions & {
34
36
  now: () => number;
35
37
  sync: SyncState;
38
+ layout: Layout;
36
39
  };
37
40
  export interface Caller {
38
41
  id: string | null;
@@ -51,6 +54,8 @@ export declare const fail: (out: string, code?: number) => Answer;
51
54
  export declare function isAnswer(value: unknown): value is Answer;
52
55
  export declare function flags(argv: readonly string[], withValue: readonly string[]): Flags;
53
56
  export declare function last(parsed: Flags, flag: string): string | undefined;
57
+ export declare class CallerError extends Error {
58
+ }
54
59
  export declare function callerOf(agents: Agents, request: Request): Caller;
55
60
  export declare function readText(deps: Deps, value: string, request: Request, context: Context): Promise<string>;
56
61
  export declare function prompts(deps: Deps, argv: readonly string[], request: Request, context: Context): Promise<string[]>;
@@ -1,11 +1,14 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
2
  import { type ConversationId, type Extension, type Submission, type ToolRegistration, type Tx } from '@earendil-works/pi-durable';
3
3
  import { type ScoopRecord } from '../agents.ts';
4
+ import { type Layout } from '../layout.ts';
4
5
  import type { LickEvent } from '../licks/licks.ts';
5
6
  import { type ScoopsHost } from './service.ts';
6
7
  export declare const PREVIEW = 1000;
7
8
  type Lookup = () => Promise<ScoopsHost>;
8
- export declare function scoopFacts(record: Pick<ScoopRecord, 'name' | 'folder' | 'role'>): string;
9
+ export declare function scoopFacts(record: Pick<ScoopRecord, 'name' | 'folder' | 'role'> & {
10
+ cone?: string;
11
+ }, layout?: Layout): string;
9
12
  export type ReportResult = {
10
13
  text: string;
11
14
  failed: string | null;
@@ -66,9 +69,9 @@ export declare function scoopTasks(lookup: Lookup): {
66
69
  phase: 'watch';
67
70
  }, null, object>;
68
71
  };
69
- export declare function scoopsExtension(tasks: ReturnType<typeof scoopTasks>): Extension;
72
+ export declare function scoopsExtension(tasks: ReturnType<typeof scoopTasks>, layout?: () => Layout): Extension;
70
73
  export declare function allowed(record: Pick<ScoopRecord, 'folder'> & {
71
74
  roots?: ScoopRecord['roots'];
72
- }, coneCwd: string, path: string, writing: boolean, reads?: readonly string[]): boolean;
75
+ }, coneCwd: string, path: string, writing: boolean, reads?: readonly string[], own?: string): boolean;
73
76
  export declare function guardExtension(lookup: Lookup, tools: readonly ToolRegistration[]): Extension;
74
77
  export {};
@@ -3,6 +3,7 @@ import type { Harness, Registry, ToolRegistration } from '@earendil-works/pi-dur
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  import { type Agents } from '../agents.ts';
5
5
  import type { ProcessGroups } from '../kernel/groups.ts';
6
+ import { type Layout } from '../layout.ts';
6
7
  import type { Licks } from '../licks/licks.ts';
7
8
  import { type Roles } from '../roles/roles.ts';
8
9
  import { type CliOptions } from './cli.ts';
@@ -31,6 +32,14 @@ export interface AttachOptions {
31
32
  models?: CliOptions['models'];
32
33
  panel?: CliOptions['panel'];
33
34
  mcp?: (names: readonly string[]) => ToolRegistration[];
35
+ layout?: Layout;
36
+ enforced?: boolean;
37
+ spools?: Spools;
38
+ agentDir?: string;
39
+ }
40
+ export interface Spools {
41
+ users(): readonly string[];
42
+ prepare(user: string, dir: string, context: Context): Promise<void>;
34
43
  }
35
44
  export interface ScoopsRuntime {
36
45
  roles(context: Context): Promise<Roles>;
@@ -13,6 +13,7 @@ export interface Request {
13
13
  pid: number | null;
14
14
  argv: string[];
15
15
  stdin: string;
16
+ user?: string;
16
17
  }
17
18
  export declare function parseRequest(id: string, bytes: Uint8Array): Request | undefined;
18
19
  export interface Runner {
@@ -29,5 +30,6 @@ export interface PlaneOptions {
29
30
  now?: () => number;
30
31
  sweepEvery?: number;
31
32
  mirror?: (context: Context) => Promise<void>;
33
+ user?: string;
32
34
  }
33
35
  export declare function controlPlane(env: ExecutionEnv, runner: Runner, options?: PlaneOptions): ControlPlane;
@@ -3,9 +3,10 @@ import { type AgentChange, type AnyTask, type Conversation, type Harness, type T
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  import { type Agents, type AgentsState, type Mark, type ScoopRecord } from '../agents.ts';
5
5
  import type { ProcessGroups } from '../kernel/groups.ts';
6
+ import { type Layout } from '../layout.ts';
6
7
  import type { Licks } from '../licks/licks.ts';
7
8
  import type { Role } from '../roles/roles.ts';
8
- export declare const SCOOPS_ROOT = "/scoops";
9
+ export { SCOOPS_ROOT } from '../layout.ts';
9
10
  export declare const LEDGER_SIZE = 512;
10
11
  export type Feed = {
11
12
  scoop: string;
@@ -51,6 +52,8 @@ export interface ScoopsHost {
51
52
  reads?: () => readonly string[];
52
53
  files?: Pick<ExecutionEnv, 'remove' | 'createDir'>;
53
54
  mcp?: (names: readonly string[]) => ToolRegistration[];
55
+ layout?: Layout;
56
+ enforced?: boolean;
54
57
  }
55
58
  export interface Rewound {
56
59
  stopped: string[];
@@ -94,7 +97,7 @@ export interface SpawnRequest {
94
97
  request?: string;
95
98
  limits: Limits;
96
99
  }
97
- export declare function workspace(folder: string): string;
100
+ export declare function workspace(folder: string, layout?: Layout): string;
98
101
  export declare function tail(conversation: Conversation, context: Context): Promise<Mark>;
99
102
  export declare function turnStart(conversation: Conversation, context: Context): Promise<number>;
100
103
  export declare function coneOf(state: Readonly<AgentsState>, conversation: number): string | undefined;
@@ -123,4 +126,3 @@ export declare function modelOf(value: string | undefined): {
123
126
  modelId: string;
124
127
  } | undefined;
125
128
  export type Scoops = ReturnType<typeof createScoops>;
126
- export {};
@@ -3,11 +3,8 @@ import type { EntryRecord } from '@earendil-works/pi-durable';
3
3
  import type { ScoopRecord } from '../agents.ts';
4
4
  import { type Caller, type Deps } from './cli.ts';
5
5
  import type { Request } from './requests.ts';
6
- import { type Answer } from './service.ts';
7
- export declare const SESSIONS: {
8
- tmp: string;
9
- durable: string;
10
- };
6
+ import type { Answer } from './service.ts';
7
+ export { SESSIONS } from '../layout.ts';
11
8
  type Ending = 'cancel' | 'detach';
12
9
  interface Pending {
13
10
  end: (ending: Ending) => void;
@@ -16,7 +13,13 @@ export interface SyncState {
16
13
  pending: Map<string, Pending>;
17
14
  }
18
15
  export declare function transcript(record: ScoopRecord, entries: readonly EntryRecord[]): string;
16
+ export type Shared = {
17
+ path: string;
18
+ write: boolean;
19
+ };
20
+ export declare function sharesOf(home: string, cwd: string, workdir: string | undefined, readOnly: readonly string[]): Shared[];
21
+ export declare function shareScript(home: string, shares: readonly Shared[]): string;
22
+ export declare function shareNote(shares: readonly Shared[]): string;
19
23
  export declare function runSync(deps: Deps, request: Request, who: Caller, context: Context): Promise<Answer>;
20
24
  export declare function cancelSync(deps: Deps, requestId: string, _context: Context): Promise<Answer>;
21
25
  export declare function detachSync(deps: Deps, requestId: string, _context: Context): Promise<Answer>;
22
- export {};
@@ -3,7 +3,7 @@ import { type Extension, type Registry } from '@earendil-works/pi-durable';
3
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
4
4
  import type { Licks } from '../licks/licks.ts';
5
5
  import type { Command } from '../services.ts';
6
- import { type Diagnostic, type Skill } from './skills.ts';
6
+ import { type Diagnostic, type Skill, type SkillRoot } from './skills.ts';
7
7
  import { type PromptTemplate } from './templates.ts';
8
8
  export declare const BUILTIN_SKILLS: string[];
9
9
  export declare const BUILTIN_PROMPTS: string[];
@@ -16,16 +16,24 @@ export interface SkillsRuntime {
16
16
  skills(): readonly Skill[];
17
17
  dirs(): string[];
18
18
  templates(): readonly PromptTemplate[];
19
- expand(text: string, context: Context): Promise<string>;
19
+ expand(text: string, context: Context, conversationId?: number): Promise<string>;
20
20
  reload(context: Context): Promise<void>;
21
21
  close(context: Context): Promise<void>;
22
22
  }
23
23
  export interface SkillsAttach {
24
24
  env: ExecutionEnv;
25
25
  home: string;
26
+ agentDir?: string;
26
27
  assets?: (path: string) => Promise<string>;
27
28
  reloadMs: number;
29
+ people?: SkillPeople;
28
30
  }
31
+ export interface SkillPeople {
32
+ homes(): readonly string[];
33
+ homeOf(conversationId: number | undefined): string | undefined;
34
+ envOf(home: string): Promise<ExecutionEnv | undefined>;
35
+ }
36
+ export declare function userRoots(homes: readonly string[]): SkillRoot[];
29
37
  export interface SkillsSetup {
30
38
  extension: Extension;
31
39
  attach(options: SkillsAttach, context: Context): Promise<SkillsRuntime>;
@@ -28,8 +28,23 @@ export interface SprinklesAttach {
28
28
  reloadMs: number;
29
29
  dir?: string;
30
30
  intercept?: (id: string, payload: SprinklePayload, context: Context) => Promise<boolean>;
31
+ places?: () => readonly SprinklePlace[];
32
+ envOf?: (agentId: string, context: Context) => Promise<ExecutionEnv | undefined>;
33
+ homeOf?: (agentId: string) => string | undefined;
34
+ shared?: string;
31
35
  }
36
+ export interface SprinklePlace {
37
+ dir: string;
38
+ cone: string;
39
+ }
40
+ export declare function liveOwner(agents: Agents, owner: string | undefined): string | undefined;
32
41
  export declare function ownerOf(agents: Agents, owner: string | undefined): string;
42
+ export declare const NO_OWNER = "this sprinkle has no owner, so it can only be shown";
43
+ export declare function ownedRead(files: ExecutionEnv, asked: string, home: string, using: Context): Promise<{
44
+ files: ExecutionEnv;
45
+ path: string;
46
+ check: () => Promise<void>;
47
+ }>;
33
48
  export declare function setupSprinkles(): {
34
49
  attach(options: SprinklesAttach, context: Context): Promise<SprinklesRuntime>;
35
50
  };
@@ -24,5 +24,11 @@ export declare function sprinkleFiles(env: Pick<ExecutionEnv, 'listDir'>, dir: s
24
24
  name: string;
25
25
  path: string;
26
26
  }[]>;
27
- export declare function homePath(path: unknown): string;
27
+ export declare function homePath(path: unknown, shared?: string, root?: string): string;
28
+ export declare function sharedPaths(shared: string): {
29
+ suggestionsDir: string;
30
+ suggestions: string;
31
+ welcomed: string;
32
+ profile: string;
33
+ };
28
34
  export declare const NO_EXEC = "sprinkles can't run commands in SLICC; send the agent a message with slicc.lick() and let it run them";