@ai-ecoverse/slicc-agent 5.4.2 → 5.5.1

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 (48) hide show
  1. package/README.md +27 -7
  2. package/dist/approvals/index.js +2 -1
  3. package/dist/approvals/index.js.map +2 -2
  4. package/dist/approvals/policy.js +110 -0
  5. package/dist/approvals/policy.js.map +7 -0
  6. package/dist/client.js +1 -0
  7. package/dist/client.js.map +2 -2
  8. package/dist/control.js.map +2 -2
  9. package/dist/guests/client.js +6 -3
  10. package/dist/guests/client.js.map +2 -2
  11. package/dist/guests/index.js +4 -1
  12. package/dist/guests/index.js.map +2 -2
  13. package/dist/guests/policy.js +75 -0
  14. package/dist/guests/policy.js.map +7 -0
  15. package/dist/guests/seats.js +16 -6
  16. package/dist/guests/seats.js.map +2 -2
  17. package/dist/guests/serve.js +8 -2
  18. package/dist/guests/serve.js.map +2 -2
  19. package/dist/host.js +35 -28
  20. package/dist/host.js.map +2 -2
  21. package/dist/index.js +4 -0
  22. package/dist/index.js.map +2 -2
  23. package/dist/memory/prompt.js +4 -1
  24. package/dist/memory/prompt.js.map +2 -2
  25. package/dist/services.js +12 -3
  26. package/dist/services.js.map +2 -2
  27. package/dist/skills/templates.js +12 -5
  28. package/dist/skills/templates.js.map +2 -2
  29. package/dist/spectrum/approvals-port.js +1 -1
  30. package/dist/spectrum/approvals-port.js.map +1 -1
  31. package/dist/spectrum/guest-port.js +14 -4
  32. package/dist/spectrum/guest-port.js.map +2 -2
  33. package/dist/spectrum/index.js +3 -1
  34. package/dist/spectrum/index.js.map +2 -2
  35. package/dist/types/approvals/index.d.ts +2 -1
  36. package/dist/types/approvals/policy.d.ts +38 -0
  37. package/dist/types/client.d.ts +2 -0
  38. package/dist/types/control.d.ts +1 -1
  39. package/dist/types/guests/index.d.ts +4 -0
  40. package/dist/types/guests/policy.d.ts +23 -0
  41. package/dist/types/guests/seats.d.ts +2 -1
  42. package/dist/types/host.d.ts +1 -3
  43. package/dist/types/index.d.ts +2 -0
  44. package/dist/types/memory/prompt.d.ts +4 -12
  45. package/dist/types/services.d.ts +11 -3
  46. package/dist/types/spectrum/guest-port.d.ts +8 -3
  47. package/dist/types/spectrum/index.d.ts +1 -1
  48. package/package.json +7 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/guest-port.ts"],
4
- "sourcesContent": ["import type { GuestDraft, GuestEvents, GuestPort, GuestSeat } from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentConnection } from '../client.ts';\nimport { Emitter } from './emitter.ts';\n\nexport interface GuestHub {\n mint(request: GuestDraft & { agentId: string }): Promise<{ id: string; url: string }>;\n revoke(id: string): Promise<void>;\n}\n\nexport const NO_HUB = 'Inviting guests needs the tray hub.';\nexport const NO_CONTROL = 'Only a tab with Control can invite guests.';\nexport const NO_OWNER = \"Only the owner's tab can invite guests.\";\n\nexport class GuestAdapter extends Emitter<GuestEvents> implements GuestPort {\n readonly #connection: AgentConnection;\n readonly #hub: GuestHub | null;\n\n constructor(connection: AgentConnection, hub: GuestHub | null) {\n super();\n this.#connection = connection;\n this.#hub = hub;\n connection.guests?.subscribe(() => this.emit('seats', this.list()));\n }\n\n list(): readonly GuestSeat[] {\n return this.#connection.guests?.value ?? [];\n }\n\n unavailable(): string | null {\n const connection = this.#connection;\n if (connection.viewOnly || connection.guest || !connection.guests) return NO_CONTROL;\n if (connection.owner === false) return NO_OWNER;\n return this.#hub ? null : NO_HUB;\n }\n\n async mint(agentId: string, draft: GuestDraft): Promise<{ seat: GuestSeat; url: string }> {\n const problem = this.unavailable();\n if (problem) throw new Error(problem);\n const hub = this.#hub as GuestHub;\n const gates = { messages: draft.gates.messages, tools: draft.gates.tools };\n const minted = await hub.mint({\n label: draft.label,\n expiresAt: draft.expiresAt,\n gates,\n agentId,\n });\n const opened = await this.#connection.control\n .guestOpen(\n { id: minted.id, label: draft.label, agentId, expiresAt: draft.expiresAt, gates },\n BACKGROUND_CONTEXT\n )\n .catch((error: Error) => ({ seat: null, error: error.message }));\n if (!opened.seat) {\n await hub.revoke(minted.id).catch(() => undefined);\n throw new Error(opened.error);\n }\n return { seat: opened.seat, url: minted.url };\n }\n\n async revoke(id: string): Promise<void> {\n await this.#connection.control.guestRevoke(id, BACKGROUND_CONTEXT);\n await this.#hub?.revoke(id);\n }\n}\n"],
5
- "mappings": "AACA,SAAS,0BAA0B;AAEnC,SAAS,eAAe;AAOjB,MAAM,SAAS;AACf,MAAM,aAAa;AACnB,MAAM,WAAW;AAEjB,MAAM,qBAAqB,QAA0C;AAAA,EACjE;AAAA,EACA;AAAA,EAET,YAAY,YAA6B,KAAsB;AAC7D,UAAM;AACN,SAAK,cAAc;AACnB,SAAK,OAAO;AACZ,eAAW,QAAQ,UAAU,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,OAA6B;AAC3B,WAAO,KAAK,YAAY,QAAQ,SAAS,CAAC;AAAA,EAC5C;AAAA,EAEA,cAA6B;AAC3B,UAAM,aAAa,KAAK;AACxB,QAAI,WAAW,YAAY,WAAW,SAAS,CAAC,WAAW,OAAQ,QAAO;AAC1E,QAAI,WAAW,UAAU,MAAO,QAAO;AACvC,WAAO,KAAK,OAAO,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,KAAK,SAAiB,OAA8D;AACxF,UAAM,UAAU,KAAK,YAAY;AACjC,QAAI,QAAS,OAAM,IAAI,MAAM,OAAO;AACpC,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,EAAE,UAAU,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,MAAM;AACzE,UAAM,SAAS,MAAM,IAAI,KAAK;AAAA,MAC5B,OAAO,MAAM;AAAA,MACb,WAAW,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,SAAS,MAAM,KAAK,YAAY,QACnC;AAAA,MACC,EAAE,IAAI,OAAO,IAAI,OAAO,MAAM,OAAO,SAAS,WAAW,MAAM,WAAW,MAAM;AAAA,MAChF;AAAA,IACF,EACC,MAAM,CAAC,WAAkB,EAAE,MAAM,MAAM,OAAO,MAAM,QAAQ,EAAE;AACjE,QAAI,CAAC,OAAO,MAAM;AAChB,YAAM,IAAI,OAAO,OAAO,EAAE,EAAE,MAAM,MAAM,MAAS;AACjD,YAAM,IAAI,MAAM,OAAO,KAAK;AAAA,IAC9B;AACA,WAAO,EAAE,MAAM,OAAO,MAAM,KAAK,OAAO,IAAI;AAAA,EAC9C;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,YAAY,QAAQ,YAAY,IAAI,kBAAkB;AACjE,UAAM,KAAK,MAAM,OAAO,EAAE;AAAA,EAC5B;AACF;",
4
+ "sourcesContent": ["import type {\n GuestDraft,\n GuestEvents,\n GuestGate,\n GuestPort,\n GuestSeat,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentConnection } from '../client.ts';\nimport { DEFAULT_GUEST_POLICY, type GateKind } from '../guests/policy.ts';\nimport { Emitter } from './emitter.ts';\n\nexport interface GuestHub {\n mint(request: GuestDraft & { agentId: string }): Promise<{ id: string; url: string }>;\n revoke(id: string): Promise<void>;\n}\n\nexport const NO_HUB = 'Inviting guests needs the tray hub.';\nexport const NOT_OWNER_DEVICE = \"Only the owner's devices can invite guests.\";\nexport const NO_CONTROL = NOT_OWNER_DEVICE;\nexport const NO_OWNER = NOT_OWNER_DEVICE;\n\nconst offered = (kinds: readonly GateKind[]): GuestGate[] =>\n kinds.map((kind) => (kind === 'scoop' ? 'scoop:*' : kind));\n\nexport class GuestAdapter extends Emitter<GuestEvents> implements GuestPort {\n readonly #connection: AgentConnection;\n readonly #hub: GuestHub | null;\n\n constructor(connection: AgentConnection, hub: GuestHub | null) {\n super();\n this.#connection = connection;\n this.#hub = hub;\n connection.guests?.subscribe(() => this.emit('seats', this.list()));\n }\n\n list(): readonly GuestSeat[] {\n return this.#connection.guests?.value ?? [];\n }\n\n gates(): { messages: GuestGate[]; tools: GuestGate[] } {\n const policy = this.#connection.approvalPolicy?.value?.guests ?? DEFAULT_GUEST_POLICY;\n return {\n messages: offered(policy.allowedMessageGates),\n tools: offered(policy.allowedToolGates),\n };\n }\n\n unavailable(): string | null {\n const connection = this.#connection;\n if (connection.guest || !connection.guests) return NOT_OWNER_DEVICE;\n return this.#hub ? null : NO_HUB;\n }\n\n async mint(agentId: string, draft: GuestDraft): Promise<{ seat: GuestSeat; url: string }> {\n const problem = this.unavailable();\n if (problem) throw new Error(problem);\n const hub = this.#hub as GuestHub;\n const gates = { messages: draft.gates.messages, tools: draft.gates.tools };\n const minted = await hub.mint({\n label: draft.label,\n expiresAt: draft.expiresAt,\n gates,\n agentId,\n });\n const opened = await this.#connection.control\n .guestOpen(\n { id: minted.id, label: draft.label, agentId, expiresAt: draft.expiresAt, gates },\n BACKGROUND_CONTEXT\n )\n .catch((error: Error) => ({ seat: null, error: error.message }));\n if (!opened.seat) {\n await hub.revoke(minted.id).catch(() => undefined);\n throw new Error(opened.error);\n }\n return { seat: opened.seat, url: minted.url };\n }\n\n async revoke(id: string): Promise<void> {\n await this.#connection.control.guestRevoke(id, BACKGROUND_CONTEXT);\n await this.#hub?.revoke(id);\n }\n}\n"],
5
+ "mappings": "AAOA,SAAS,0BAA0B;AAEnC,SAAS,4BAA2C;AACpD,SAAS,eAAe;AAOjB,MAAM,SAAS;AACf,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,WAAW;AAExB,MAAM,UAAU,CAAC,UACf,MAAM,IAAI,CAAC,SAAU,SAAS,UAAU,YAAY,IAAK;AAEpD,MAAM,qBAAqB,QAA0C;AAAA,EACjE;AAAA,EACA;AAAA,EAET,YAAY,YAA6B,KAAsB;AAC7D,UAAM;AACN,SAAK,cAAc;AACnB,SAAK,OAAO;AACZ,eAAW,QAAQ,UAAU,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,OAA6B;AAC3B,WAAO,KAAK,YAAY,QAAQ,SAAS,CAAC;AAAA,EAC5C;AAAA,EAEA,QAAuD;AACrD,UAAM,SAAS,KAAK,YAAY,gBAAgB,OAAO,UAAU;AACjE,WAAO;AAAA,MACL,UAAU,QAAQ,OAAO,mBAAmB;AAAA,MAC5C,OAAO,QAAQ,OAAO,gBAAgB;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,cAA6B;AAC3B,UAAM,aAAa,KAAK;AACxB,QAAI,WAAW,SAAS,CAAC,WAAW,OAAQ,QAAO;AACnD,WAAO,KAAK,OAAO,OAAO;AAAA,EAC5B;AAAA,EAEA,MAAM,KAAK,SAAiB,OAA8D;AACxF,UAAM,UAAU,KAAK,YAAY;AACjC,QAAI,QAAS,OAAM,IAAI,MAAM,OAAO;AACpC,UAAM,MAAM,KAAK;AACjB,UAAM,QAAQ,EAAE,UAAU,MAAM,MAAM,UAAU,OAAO,MAAM,MAAM,MAAM;AACzE,UAAM,SAAS,MAAM,IAAI,KAAK;AAAA,MAC5B,OAAO,MAAM;AAAA,MACb,WAAW,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,SAAS,MAAM,KAAK,YAAY,QACnC;AAAA,MACC,EAAE,IAAI,OAAO,IAAI,OAAO,MAAM,OAAO,SAAS,WAAW,MAAM,WAAW,MAAM;AAAA,MAChF;AAAA,IACF,EACC,MAAM,CAAC,WAAkB,EAAE,MAAM,MAAM,OAAO,MAAM,QAAQ,EAAE;AACjE,QAAI,CAAC,OAAO,MAAM;AAChB,YAAM,IAAI,OAAO,OAAO,EAAE,EAAE,MAAM,MAAM,MAAS;AACjD,YAAM,IAAI,MAAM,OAAO,KAAK;AAAA,IAC9B;AACA,WAAO,EAAE,MAAM,OAAO,MAAM,KAAK,OAAO,IAAI;AAAA,EAC9C;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,YAAY,QAAQ,YAAY,IAAI,kBAAkB;AACjE,UAAM,KAAK,MAAM,OAAO,EAAE;AAAA,EAC5B;AACF;",
6
6
  "names": []
7
7
  }
@@ -20,7 +20,8 @@ import {
20
20
  GuestAdapter as GuestAdapter2,
21
21
  NO_CONTROL,
22
22
  NO_HUB,
23
- NO_OWNER
23
+ NO_OWNER,
24
+ NOT_OWNER_DEVICE
24
25
  } from "./guest-port.js";
25
26
  import { MemoryAdapter as MemoryAdapter2 } from "./memory-port.js";
26
27
  import {
@@ -91,6 +92,7 @@ export {
91
92
  MemoryAdapter2 as MemoryAdapter,
92
93
  MonitorAdapter2 as MonitorAdapter,
93
94
  NOT_HERE,
95
+ NOT_OWNER_DEVICE,
94
96
  NO_CONTROL,
95
97
  NO_HUB,
96
98
  NO_OWNER,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/index.ts"],
4
- "sourcesContent": ["import type { MonitorSection } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { AgentConnection } from '../client.ts';\nimport type { GuestGates } from '../guests/seats.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { ApprovalsAdapter, type HostApprovals } from './approvals-port.ts';\nimport { ChangesAdapter } from './changes-port.ts';\nimport { GuestAdapter, type GuestHub } from './guest-port.ts';\nimport { MemoryAdapter } from './memory-port.ts';\nimport { MonitorAdapter } from './monitor-port.ts';\nimport { type HostNotices, NoticesAdapter } from './notices-port.ts';\nimport { PageAdapter, type PageOptions } from './page-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 ApprovalsAdapter,\n type HostApprovals,\n NOT_HERE,\n shown as shownApproval,\n} from './approvals-port.ts';\nexport { ChangesAdapter, type ChangesEvents } from './changes-port.ts';\nexport {\n GuestAdapter,\n type GuestHub,\n NO_CONTROL,\n NO_HUB,\n NO_OWNER,\n} from './guest-port.ts';\nexport { MemoryAdapter } from './memory-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport {\n MonitorAdapter,\n type MonitorAdapterOptions,\n type MonitorInput,\n monitorSnapshot,\n} from './monitor-port.ts';\nexport {\n type HostNotices,\n KEYS_MOVED,\n movedList,\n movedNotice,\n NoticesAdapter,\n} from './notices-port.ts';\nexport {\n PageAdapter,\n type PageDocument,\n type PageOptions,\n type PageRun,\n type PageTarget,\n} from './page-port.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 interface GuestSeatShown {\n id: string;\n label: string;\n agentId: string;\n expiresAt: number | null;\n gates: GuestGates;\n}\n\nfunction seatOf(connection: AgentConnection): { seat?: GuestSeatShown } {\n const guest = connection.guest;\n if (!guest) return {};\n const { id, label, agentId, expiresAt, gates } = guest;\n return { seat: { id, label, agentId, expiresAt, gates: { ...gates } } };\n}\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: {\n storage?: Pick<Storage, 'getItem' | 'setItem'> | null;\n login?: Login;\n monitor?: { extra?: () => readonly MonitorSection[] };\n page?: PageOptions;\n guests?: GuestHub;\n approvals?: HostApprovals;\n notices?: HostNotices;\n } = {}\n): {\n agent: AgentAdapter;\n approvals: ApprovalsAdapter;\n settings: SettingsAdapter;\n tray: TrayAdapter;\n sprinkles: SprinkleAdapter;\n memory: MemoryAdapter;\n changes: ChangesAdapter;\n monitor: MonitorAdapter;\n notices: NoticesAdapter;\n page: PageAdapter | null;\n guests: GuestAdapter;\n seat?: GuestSeatShown;\n} {\n const agent = new AgentAdapter(connection);\n const report = (text: string) => agent.notify(text);\n const run = options.page?.run;\n return {\n agent,\n guests: new GuestAdapter(connection, options.guests ?? null),\n ...seatOf(connection),\n approvals: new ApprovalsAdapter(connection, options.approvals),\n page: options.page && run ? new PageAdapter(connection, agent, { ...options.page, run }) : null,\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, report),\n memory: new MemoryAdapter(connection, report),\n changes: new ChangesAdapter(connection, report),\n notices: new NoticesAdapter(connection.settings, report, options.notices),\n monitor: new MonitorAdapter(\n connection,\n options.monitor?.extra ? { extra: options.monitor.extra } : {}\n ),\n };\n}\n"],
5
- "mappings": "AAGA,SAAS,oBAAoB;AAC7B,SAAS,wBAA4C;AACrD,SAAS,sBAAsB;AAC/B,SAAS,oBAAmC;AAC5C,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAA2B,sBAAsB;AACjD,SAAS,mBAAqC;AAC9C,SAAqB,uBAAuB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC;AAAA,EACE,oBAAAC;AAAA,EAEA;AAAA,EACS;AAAA,OACJ;AACP,SAAS,kBAAAC,uBAA0C;AACnD;AAAA,EACE,gBAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAAC,sBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,kBAAAC;AAAA,EAGA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;AACP;AAAA,EACE,eAAAC;AAAA,OAKK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAAC,oBAAmB;AAU5B,SAAS,OAAO,YAAwD;AACtE,QAAM,QAAQ,WAAW;AACzB,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,QAAM,EAAE,IAAI,OAAO,SAAS,WAAW,MAAM,IAAI;AACjD,SAAO,EAAE,MAAM,EAAE,IAAI,OAAO,SAAS,WAAW,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE;AACxE;AAEO,SAAS,iBACd,YACA,UAQI,CAAC,GAcL;AACA,QAAM,QAAQ,IAAI,aAAa,UAAU;AACzC,QAAM,SAAS,CAAC,SAAiB,MAAM,OAAO,IAAI;AAClD,QAAM,MAAM,QAAQ,MAAM;AAC1B,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,IAAI,aAAa,YAAY,QAAQ,UAAU,IAAI;AAAA,IAC3D,GAAG,OAAO,UAAU;AAAA,IACpB,WAAW,IAAI,iBAAiB,YAAY,QAAQ,SAAS;AAAA,IAC7D,MAAM,QAAQ,QAAQ,MAAM,IAAI,YAAY,YAAY,OAAO,EAAE,GAAG,QAAQ,MAAM,IAAI,CAAC,IAAI;AAAA,IAC3F,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,YAAY,MAAM;AAAA,IACjD,QAAQ,IAAI,cAAc,YAAY,MAAM;AAAA,IAC5C,SAAS,IAAI,eAAe,YAAY,MAAM;AAAA,IAC9C,SAAS,IAAI,eAAe,WAAW,UAAU,QAAQ,QAAQ,OAAO;AAAA,IACxE,SAAS,IAAI;AAAA,MACX;AAAA,MACA,QAAQ,SAAS,QAAQ,EAAE,OAAO,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import type { MonitorSection } from '@ai-ecoverse/slicc-spectrum/ui';\nimport type { AgentConnection } from '../client.ts';\nimport type { GuestGates } from '../guests/seats.ts';\nimport { AgentAdapter } from './agent-port.ts';\nimport { ApprovalsAdapter, type HostApprovals } from './approvals-port.ts';\nimport { ChangesAdapter } from './changes-port.ts';\nimport { GuestAdapter, type GuestHub } from './guest-port.ts';\nimport { MemoryAdapter } from './memory-port.ts';\nimport { MonitorAdapter } from './monitor-port.ts';\nimport { type HostNotices, NoticesAdapter } from './notices-port.ts';\nimport { PageAdapter, type PageOptions } from './page-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 ApprovalsAdapter,\n type HostApprovals,\n NOT_HERE,\n shown as shownApproval,\n} from './approvals-port.ts';\nexport { ChangesAdapter, type ChangesEvents } from './changes-port.ts';\nexport {\n GuestAdapter,\n type GuestHub,\n NO_CONTROL,\n NO_HUB,\n NO_OWNER,\n NOT_OWNER_DEVICE,\n} from './guest-port.ts';\nexport { MemoryAdapter } from './memory-port.ts';\nexport {\n assistant,\n errorAction,\n errorPart,\n isBusy,\n queued,\n textOf,\n toMessages,\n} from './messages.ts';\nexport {\n MonitorAdapter,\n type MonitorAdapterOptions,\n type MonitorInput,\n monitorSnapshot,\n} from './monitor-port.ts';\nexport {\n type HostNotices,\n KEYS_MOVED,\n movedList,\n movedNotice,\n NoticesAdapter,\n} from './notices-port.ts';\nexport {\n PageAdapter,\n type PageDocument,\n type PageOptions,\n type PageRun,\n type PageTarget,\n} from './page-port.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 interface GuestSeatShown {\n id: string;\n label: string;\n agentId: string;\n expiresAt: number | null;\n gates: GuestGates;\n}\n\nfunction seatOf(connection: AgentConnection): { seat?: GuestSeatShown } {\n const guest = connection.guest;\n if (!guest) return {};\n const { id, label, agentId, expiresAt, gates } = guest;\n return { seat: { id, label, agentId, expiresAt, gates: { ...gates } } };\n}\n\nexport function createAgentModel(\n connection: AgentConnection,\n options: {\n storage?: Pick<Storage, 'getItem' | 'setItem'> | null;\n login?: Login;\n monitor?: { extra?: () => readonly MonitorSection[] };\n page?: PageOptions;\n guests?: GuestHub;\n approvals?: HostApprovals;\n notices?: HostNotices;\n } = {}\n): {\n agent: AgentAdapter;\n approvals: ApprovalsAdapter;\n settings: SettingsAdapter;\n tray: TrayAdapter;\n sprinkles: SprinkleAdapter;\n memory: MemoryAdapter;\n changes: ChangesAdapter;\n monitor: MonitorAdapter;\n notices: NoticesAdapter;\n page: PageAdapter | null;\n guests: GuestAdapter;\n seat?: GuestSeatShown;\n} {\n const agent = new AgentAdapter(connection);\n const report = (text: string) => agent.notify(text);\n const run = options.page?.run;\n return {\n agent,\n guests: new GuestAdapter(connection, options.guests ?? null),\n ...seatOf(connection),\n approvals: new ApprovalsAdapter(connection, options.approvals),\n page: options.page && run ? new PageAdapter(connection, agent, { ...options.page, run }) : null,\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, report),\n memory: new MemoryAdapter(connection, report),\n changes: new ChangesAdapter(connection, report),\n notices: new NoticesAdapter(connection.settings, report, options.notices),\n monitor: new MonitorAdapter(\n connection,\n options.monitor?.extra ? { extra: options.monitor.extra } : {}\n ),\n };\n}\n"],
5
+ "mappings": "AAGA,SAAS,oBAAoB;AAC7B,SAAS,wBAA4C;AACrD,SAAS,sBAAsB;AAC/B,SAAS,oBAAmC;AAC5C,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAA2B,sBAAsB;AACjD,SAAS,mBAAqC;AAC9C,SAAqB,uBAAuB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAE5B,SAAS,gBAAAA,eAAc,YAAY;AACnC;AAAA,EACE,oBAAAC;AAAA,EAEA;AAAA,EACS;AAAA,OACJ;AACP,SAAS,kBAAAC,uBAA0C;AACnD;AAAA,EACE,gBAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,iBAAAC,sBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,kBAAAC;AAAA,EAGA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAAC;AAAA,OACK;AACP;AAAA,EACE,eAAAC;AAAA,OAKK;AACP,SAAqB,cAAc,mBAAAC,wBAAuB;AAC1D,SAAS,mBAAAC,wBAAuB;AAChC,SAAS,eAAAC,oBAAmB;AAU5B,SAAS,OAAO,YAAwD;AACtE,QAAM,QAAQ,WAAW;AACzB,MAAI,CAAC,MAAO,QAAO,CAAC;AACpB,QAAM,EAAE,IAAI,OAAO,SAAS,WAAW,MAAM,IAAI;AACjD,SAAO,EAAE,MAAM,EAAE,IAAI,OAAO,SAAS,WAAW,OAAO,EAAE,GAAG,MAAM,EAAE,EAAE;AACxE;AAEO,SAAS,iBACd,YACA,UAQI,CAAC,GAcL;AACA,QAAM,QAAQ,IAAI,aAAa,UAAU;AACzC,QAAM,SAAS,CAAC,SAAiB,MAAM,OAAO,IAAI;AAClD,QAAM,MAAM,QAAQ,MAAM;AAC1B,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,IAAI,aAAa,YAAY,QAAQ,UAAU,IAAI;AAAA,IAC3D,GAAG,OAAO,UAAU;AAAA,IACpB,WAAW,IAAI,iBAAiB,YAAY,QAAQ,SAAS;AAAA,IAC7D,MAAM,QAAQ,QAAQ,MAAM,IAAI,YAAY,YAAY,OAAO,EAAE,GAAG,QAAQ,MAAM,IAAI,CAAC,IAAI;AAAA,IAC3F,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,YAAY,MAAM;AAAA,IACjD,QAAQ,IAAI,cAAc,YAAY,MAAM;AAAA,IAC5C,SAAS,IAAI,eAAe,YAAY,MAAM;AAAA,IAC9C,SAAS,IAAI,eAAe,WAAW,UAAU,QAAQ,QAAQ,OAAO;AAAA,IACxE,SAAS,IAAI;AAAA,MACX;AAAA,MACA,QAAQ,SAAS,QAAQ,EAAE,OAAO,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,IAC/D;AAAA,EACF;AACF;",
6
6
  "names": ["AgentAdapter", "ApprovalsAdapter", "ChangesAdapter", "GuestAdapter", "MemoryAdapter", "MonitorAdapter", "NoticesAdapter", "PageAdapter", "SettingsAdapter", "SprinkleAdapter", "TrayAdapter"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { Harness } from '@earendil-works/pi-durable';
3
3
  import type { ApprovalJudge } from './judge.ts';
4
- import { type Approval, type ApprovalDraft, type ApprovalState, type DecidedBy } from './record.ts';
4
+ import { type Approval, type ApprovalDraft, type ApprovalKind, type ApprovalState, type DecidedBy } from './record.ts';
5
5
  export * from './intent.ts';
6
6
  export * from './judge.ts';
7
7
  export * from './record.ts';
@@ -28,5 +28,6 @@ export interface ApprovalsAttach {
28
28
  now?: () => number;
29
29
  ttlMs?: number;
30
30
  judge?: ApprovalJudge;
31
+ guestAlways?: (kind: ApprovalKind) => boolean;
31
32
  }
32
33
  export declare function attachApprovals(options: ApprovalsAttach, context?: Context): Promise<Approvals>;
@@ -0,0 +1,38 @@
1
+ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
+ import { type Harness, type JsonObject } from '@earendil-works/pi-durable';
3
+ import { type GuestPolicy, type GuestPolicyChange } from '../guests/policy.ts';
4
+ import type { ApprovalKind } from './record.ts';
5
+ export type SudoPolicy = {
6
+ approver: 'user' | 'agent';
7
+ };
8
+ export type ApprovalPolicy = {
9
+ guests: GuestPolicy;
10
+ sudo: SudoPolicy;
11
+ };
12
+ export type ApprovalPolicyChange = {
13
+ guests?: GuestPolicyChange;
14
+ sudo?: Partial<SudoPolicy>;
15
+ };
16
+ export type ApprovalPolicySet = {
17
+ policy: ApprovalPolicy;
18
+ error: null;
19
+ } | {
20
+ policy: null;
21
+ error: string;
22
+ };
23
+ export declare const DEFAULT_APPROVAL_POLICY: ApprovalPolicy;
24
+ type Overrides = Partial<Record<keyof ApprovalPolicy, JsonObject>>;
25
+ export declare const ApprovalPolicyDoc: import("@earendil-works/pi-durable").SessionDocToken<{
26
+ overrides: Overrides;
27
+ }>;
28
+ export declare function changedPolicy(base: ApprovalPolicy, change: unknown): ApprovalPolicySet;
29
+ export declare function resolvedPolicy(overrides: Overrides): ApprovalPolicy;
30
+ export declare function overridden(overrides: Overrides, change: Record<string, Record<string, unknown>>, policy: ApprovalPolicy): Overrides;
31
+ export interface ApprovalPolicies {
32
+ readonly state: ReplicatedState<ApprovalPolicy>;
33
+ current(): ApprovalPolicy;
34
+ set(change: unknown, context: Context): Promise<ApprovalPolicySet>;
35
+ }
36
+ export declare const alwaysFor: (policy: Pick<ApprovalPolicies, 'current'>) => (kind: ApprovalKind) => boolean;
37
+ export declare function attachApprovalPolicy(harness: Pick<Harness, 'commit'>, context?: Context): Promise<ApprovalPolicies>;
38
+ export {};
@@ -1,5 +1,6 @@
1
1
  import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
+ import type { ApprovalPolicy } from './approvals/policy.ts';
3
4
  import type { Approval } from './approvals/record.ts';
4
5
  import type { ChangesView } from './changes/git.ts';
5
6
  import type { FrozenCone } from './freezer/index.ts';
@@ -34,6 +35,7 @@ export interface AgentConnection {
34
35
  readonly proposals?: ReplicatedState<GuestProposal[]>;
35
36
  readonly owner?: boolean;
36
37
  readonly approvals?: ReplicatedState<Approval[]>;
38
+ readonly approvalPolicy?: ReplicatedState<ApprovalPolicy>;
37
39
  readonly settings: AgentSettings;
38
40
  readonly remote?: AgentRemote;
39
41
  readonly pages?: AgentPages;
@@ -24,4 +24,4 @@ export interface HostScoops {
24
24
  }
25
25
  export declare function readable(out: string): string;
26
26
  export declare function submissionId(value: string): SubmissionId | undefined;
27
- export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads, labels?: Pick<LabelsRuntime, 'label'>, guests?: Pick<Guests, 'open' | 'revoke'>): AgentControl;
27
+ export declare function createAgentControl(harness: Harness, target: Conversation | Cones, deliveries?: Deliveries, licks?: HostLicks, scoops?: HostScoops, skills?: Pick<SkillsRuntime, 'expand' | 'commandsFor'>, sprinkles?: Pick<SprinklesRuntime, 'send' | 'call'>, memory?: Pick<MemoryRuntime, 'save' | 'remove'>, freezer?: Pick<FreezerRuntime, 'freeze' | 'newChat' | 'thaw' | 'discard'>, changes?: Pick<ChangesRuntime, 'open' | 'accept' | 'revert'>, monitor?: Pick<Monitor, 'open' | 'close'>, secrets?: () => readonly SecretName[], uploads?: Uploads, labels?: Pick<LabelsRuntime, 'label'>, guests?: Pick<Guests, 'open' | 'revoke'>): Omit<AgentControl, 'approvalPolicySet'>;
@@ -2,7 +2,9 @@ import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import { type Harness } from '@earendil-works/pi-durable';
3
3
  import type { Agents } from '../agents.ts';
4
4
  import type { Approvals } from '../approvals/index.ts';
5
+ import type { ApprovalPolicies } from '../approvals/policy.ts';
5
6
  import type { GuestPrincipal } from '../serving.ts';
7
+ import { type GuestPolicy } from './policy.ts';
6
8
  import { type GuestDraft, type GuestSeat, type SeatRecord } from './seats.ts';
7
9
  export type GuestOpened = {
8
10
  seat: GuestSeat;
@@ -41,12 +43,14 @@ export interface Guests {
41
43
  joined(id: string): () => void;
42
44
  onEnd(listener: (id: string) => void): () => void;
43
45
  propose(guest: GuestPrincipal, request: ProposeRequest, context: Context): Promise<Proposed>;
46
+ policy(): GuestPolicy;
44
47
  dispose(): void;
45
48
  }
46
49
  export interface GuestsOptions {
47
50
  harness: Pick<Harness, 'commit' | 'abortSubmission'>;
48
51
  agents: Pick<Agents, 'state' | 'conversation'>;
49
52
  approvals?: Pick<Approvals, 'state' | 'request' | 'withdrawSeat'>;
53
+ policy?: Pick<ApprovalPolicies, 'current'>;
50
54
  now?: () => number;
51
55
  context?: Context;
52
56
  }
@@ -0,0 +1,23 @@
1
+ import type { ApprovalTier } from '../approvals/record.ts';
2
+ export type GateKind = 'user' | 'agent' | 'scoop' | 'cone' | 'off';
3
+ export type GuestPolicy = {
4
+ manageGuests: 'deny' | ApprovalTier;
5
+ allowedToolGates: GateKind[];
6
+ allowedMessageGates: GateKind[];
7
+ maxSeatDays: number;
8
+ always: {
9
+ messages: boolean;
10
+ tools: boolean;
11
+ };
12
+ };
13
+ export type GuestPolicyChange = Partial<GuestPolicy>;
14
+ export declare const GATE_KINDS: readonly GateKind[];
15
+ export declare const DEFAULT_GUEST_POLICY: GuestPolicy;
16
+ export declare const MAX_SEAT_DAYS = 365;
17
+ export declare const DAY_MS: number;
18
+ export declare const GUESTS_MANAGE_DENIED = "The owner's guest policy doesn't let guests manage guests.";
19
+ export declare const GUESTS_MANAGE_LATER = "Guests can't manage guests yet, whatever the policy says.";
20
+ export declare const POLICY_MANAGE_DENY_ONLY = "manageGuests can only be deny: guests can't manage guests yet.";
21
+ export declare const gateKind: (gate: string) => GateKind;
22
+ export declare function gateRefusal(what: string, allowed: readonly GateKind[]): string;
23
+ export declare function changedGuests(next: GuestPolicy, change: unknown): string | null;
@@ -1,4 +1,5 @@
1
1
  import type { ApprovalTier } from '../approvals/record.ts';
2
+ import { type GuestPolicy } from './policy.ts';
2
3
  export type GuestGate = ApprovalTier | 'off';
3
4
  export type GuestGates = {
4
5
  messages: GuestGate;
@@ -35,5 +36,5 @@ export declare const MAX_SEAT_MS: number;
35
36
  export declare const MAX_LABEL = 64;
36
37
  export declare function cleanLabel(raw: unknown): string;
37
38
  export declare function isGate(value: unknown): value is GuestGate;
38
- export declare function checkDraft(draft: GuestDraft, now: number): string | null;
39
+ export declare function checkDraft(draft: GuestDraft, now: number, policy?: GuestPolicy): string | null;
39
40
  export declare function liveSeat(seat: SeatRecord | undefined, now: number): boolean;
@@ -14,7 +14,7 @@ import { type Pages } from './remote/pages.ts';
14
14
  import type { SecretName } from './secrets/names.ts';
15
15
  import type { VaultState } from './secrets/vault.ts';
16
16
  import { AgentControl, type AgentGuest, AgentSettings, AgentTranscript } from './services.ts';
17
- import { type GuestPrincipal, type Seat } from './serving.ts';
17
+ import { type GuestPrincipal } from './serving.ts';
18
18
  import type { SkillsRuntime } from './skills/index.ts';
19
19
  import type { SprinklesRuntime } from './sprinkles/index.ts';
20
20
  import { type Thumbnail } from './thumbs.ts';
@@ -84,7 +84,5 @@ export declare const CLOSED_TO_GUESTS = "a guest seat has only its transcript an
84
84
  export declare const openToGuests: <F extends object>(factory: F) => F;
85
85
  export declare function closedToGuests(host: Host): Host;
86
86
  export declare function lazily<T>(state: () => ReplicatedState<T>): Readable<T>;
87
- export declare const GUEST_MANAGERS: ReadonlySet<Seat>;
88
- export declare const OWNER_GUESTS = "only the owner can invite or revoke guests";
89
87
  export declare function serveAgent(serving: Served): Host;
90
88
  export {};
@@ -1,11 +1,13 @@
1
1
  export { ADOBE, ADOBE_PROXY, type AdobeConfig, type AdobeModelInfo, adobeClassifiers, adobeConfig, adobeIdentity, adobeModel, adobeProvider, adobeUsage, type Budget, SESSION_HEADER, VERSION_HEADER, withAdobeIdentity, } from './adobe.ts';
2
2
  export { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';
3
3
  export { APPROVAL_MS, type Approval, type ApprovalAnswer, type ApprovalDecided, type ApprovalDraft, type ApprovalJudge, type ApprovalKind, type ApprovalRequester, type ApprovalState, type Approvals, ApprovalsDoc, type ApprovalTier, type ApprovalVerdict, approvalJudge, attachApprovals, DEFAULT_POLICY, type DecidedBy, JUDGE_ALLOW, JUDGE_DENY, JUDGE_KIND, JUDGE_MODEL, JUDGE_QUESTIONS, type Judgement, judgeModelOf, judgeSpender, judgeState, type OwnerIntent, ownerIntent, POLICY_FILE, REASONS, seedPolicy, VERDICT_REASONS, verdictOf, verdictRecorder, } from './approvals/index.ts';
4
+ export { type ApprovalPolicy, type ApprovalPolicyChange, type ApprovalPolicySet, DEFAULT_APPROVAL_POLICY, type SudoPolicy, } from './approvals/policy.ts';
4
5
  export { FILE_LIMIT, IMAGE_LIMIT, type SendAttachment, type ShownAttachment, splitUser, TOTAL_LIMIT, userParts, } from './attachments.ts';
5
6
  export { type AgentConnection, connectAgent } from './client.ts';
6
7
  export { createAgentControl } from './control.ts';
7
8
  export { connectGuest, GUEST_ONLY, type GuestConnection, SEAT_REFUSED, } from './guests/client.ts';
8
9
  export type { GuestOpened, Proposed, ProposeRequest } from './guests/index.ts';
10
+ export type { GateKind, GuestPolicy } from './guests/policy.ts';
9
11
  export type { GuestDraft, GuestGate, GuestGates, GuestSeat } from './guests/seats.ts';
10
12
  export { type AgentHost, type ConnectOptions, hostAgent } from './host.ts';
11
13
  export type { KernelClient, KernelFs, KernelProcess, KernelStat, SpawnOptions, } from './kernel/client.ts';
@@ -1,6 +1,5 @@
1
1
  import type { Context } from '@earendil-works/chord';
2
- import { Type } from '@earendil-works/pi-ai';
3
- import { type Harness } from '@earendil-works/pi-durable';
2
+ import { type Harness, type ToolRegistration } from '@earendil-works/pi-durable';
4
3
  import type { ExecutionEnv } from '@earendil-works/pi-durable/env';
5
4
  import type { Agents, AgentsState, ScoopRecord } from '../agents.ts';
6
5
  import { type MemoryFiles, type Place, type Written } from './store.ts';
@@ -29,8 +28,8 @@ type Problem = {
29
28
  };
30
29
  export declare function whoIs(state: Readonly<AgentsState>, conversation: number): Who;
31
30
  export declare function ownPlace(host: Host, who: Who, cwd: string, context: Context): Promise<Place | Problem>;
32
- export declare function contextSection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<import("@earendil-works/pi-durable").ToolRegistration>;
33
- export declare function memorySection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<import("@earendil-works/pi-durable").ToolRegistration>;
31
+ export declare function contextSection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<ToolRegistration>;
32
+ export declare function memorySection(ready: Promise<Host>): import("@earendil-works/pi-durable").PromptSection<ToolRegistration>;
34
33
  type Args = {
35
34
  section: string;
36
35
  title: string;
@@ -40,12 +39,5 @@ type Args = {
40
39
  scope?: 'own' | 'global';
41
40
  };
42
41
  export declare function writeAnswer(args: Args, place: Place, written: Written): string;
43
- export declare function memoryWriteTool(ready: Promise<Host>): import("@earendil-works/pi-durable").ToolRegistration<Type.TObject<{
44
- section: Type.TString;
45
- title: Type.TString;
46
- body: Type.TOptional<Type.TString>;
47
- tag: Type.TOptional<Type.TUnion<[Type.TLiteral<"user">, Type.TLiteral<"feedback">, Type.TLiteral<"project">]>>;
48
- remove: Type.TOptional<Type.TBoolean>;
49
- scope: Type.TOptional<Type.TUnion<[Type.TLiteral<"own">, Type.TLiteral<"global">]>>;
50
- }>, import("@earendil-works/chord").JsonValue>;
42
+ export declare function memoryWriteTool(ready: Promise<Host>): ToolRegistration;
51
43
  export {};
@@ -1,6 +1,7 @@
1
1
  import type { Context, JsonValue, RemoteContract, ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
3
  import type { Approval, ApprovalAnswer, ApprovalDecided } from './approvals/index.ts';
4
+ import type { ApprovalPolicy, ApprovalPolicyChange, ApprovalPolicySet } from './approvals/policy.ts';
4
5
  import type { SendAttachment, ShownAttachment } from './attachments.ts';
5
6
  import type { ChangesView } from './changes/git.ts';
6
7
  import type { FrozenCone } from './freezer/index.ts';
@@ -94,6 +95,7 @@ export interface AgentControl {
94
95
  guestRevoke(id: string, context: Context): Promise<{
95
96
  revoked: boolean;
96
97
  }>;
98
+ approvalPolicySet(change: ApprovalPolicyChange, context: Context): Promise<ApprovalPolicySet>;
97
99
  decide(id: string, decision: ApprovalAnswer, reason: string | null, context: Context): Promise<ApprovalDecided>;
98
100
  }
99
101
  export interface ImageRef {
@@ -239,7 +241,8 @@ export interface AgentSettingsChange {
239
241
  thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;
240
242
  agentId?: string | null;
241
243
  }
242
- export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "decide" | "discard" | "drop" | "freeze" | "guestOpen" | "guestRevoke" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
244
+ export declare const CONTROL_METHODS: ("abort" | "agentCommands" | "approvalPolicySet" | "changeAccept" | "changeRevert" | "changesOpen" | "compact" | "compactAgent" | "configure" | "createCone" | "createScoop" | "decide" | "discard" | "drop" | "freeze" | "guestOpen" | "guestRevoke" | "image" | "memoryRemove" | "memorySave" | "monitorClose" | "monitorOpen" | "newChat" | "reset" | "resolveAgentLick" | "resolveLick" | "rewind" | "rewindAgent" | "selectCone" | "send" | "sprinkleCall" | "sprinkleSend" | "stopAgent" | "thaw" | "toolLabel" | "unqueue" | "wait" | "webhook" | "withdraw")[];
245
+ export declare const OWNER_DEVICE_METHODS: readonly (keyof AgentControl & string)[];
243
246
  export declare const CONTROL_READS: readonly (keyof AgentControl & string)[];
244
247
  export declare const AgentControl: RemoteContract;
245
248
  export type Delivered = 'run' | 'steer' | 'follow-up';
@@ -260,6 +263,7 @@ export interface AgentTranscript {
260
263
  readonly labels: ReplicatedState<Record<string, string>>;
261
264
  readonly guests: ReplicatedState<GuestSeat[]>;
262
265
  readonly approvals: ReplicatedState<Approval[]>;
266
+ readonly approvalPolicy: ReplicatedState<ApprovalPolicy>;
263
267
  }
264
268
  export interface PrivateRevision {
265
269
  revision: number;
@@ -269,7 +273,7 @@ export interface Command {
269
273
  description: string;
270
274
  kind: 'prompt' | 'skill' | 'action';
271
275
  }
272
- export declare const TRANSCRIPT_STATES: ("agents" | "approvals" | "changes" | "commands" | "deliveries" | "frozen" | "guests" | "labels" | "memories" | "memoryScopes" | "monitor" | "privateRevision" | "sprinkles" | "state" | "vault" | "views")[];
276
+ export declare const TRANSCRIPT_STATES: ("agents" | "approvalPolicy" | "approvals" | "changes" | "commands" | "deliveries" | "frozen" | "guests" | "labels" | "memories" | "memoryScopes" | "monitor" | "privateRevision" | "sprinkles" | "state" | "vault" | "views")[];
273
277
  export declare const AgentTranscript: RemoteContract;
274
278
  export declare const REMOTE_METHODS: ("abort" | "close" | "next" | "prompt" | "watch")[];
275
279
  export declare const REMOTE_READS: readonly (keyof AgentRemote & string)[];
@@ -294,9 +298,13 @@ export interface AgentGuest {
294
298
  readonly seat: ReplicatedState<GuestShown>;
295
299
  readonly proposals: ReplicatedState<GuestProposal[]>;
296
300
  propose(request: ProposeRequest, context: Context): Promise<Proposed>;
301
+ guestOpen(draft: GuestDraft, context: Context): Promise<GuestOpened>;
302
+ guestRevoke(id: string, context: Context): Promise<{
303
+ revoked: boolean;
304
+ }>;
297
305
  }
298
306
  export declare const GUEST_STATES: readonly ['transcript', 'seat', 'proposals'];
299
- export declare const GUEST_METHODS: readonly ['propose'];
307
+ export declare const GUEST_METHODS: readonly ['propose', 'guestOpen', 'guestRevoke'];
300
308
  export declare const AgentGuestService: RemoteContract;
301
309
  export declare const AgentRemoteService: RemoteContract;
302
310
  export declare const PAGE_METHODS: ("answer" | "close" | "next" | "open" | "report")[];
@@ -1,4 +1,4 @@
1
- import type { GuestDraft, GuestEvents, GuestPort, GuestSeat } from '@ai-ecoverse/slicc-spectrum/ui';
1
+ import type { GuestDraft, GuestEvents, GuestGate, GuestPort, GuestSeat } from '@ai-ecoverse/slicc-spectrum/ui';
2
2
  import type { AgentConnection } from '../client.ts';
3
3
  import { Emitter } from './emitter.ts';
4
4
  export interface GuestHub {
@@ -11,12 +11,17 @@ export interface GuestHub {
11
11
  revoke(id: string): Promise<void>;
12
12
  }
13
13
  export declare const NO_HUB = "Inviting guests needs the tray hub.";
14
- export declare const NO_CONTROL = "Only a tab with Control can invite guests.";
15
- export declare const NO_OWNER = "Only the owner's tab can invite guests.";
14
+ export declare const NOT_OWNER_DEVICE = "Only the owner's devices can invite guests.";
15
+ export declare const NO_CONTROL = "Only the owner's devices can invite guests.";
16
+ export declare const NO_OWNER = "Only the owner's devices can invite guests.";
16
17
  export declare class GuestAdapter extends Emitter<GuestEvents> implements GuestPort {
17
18
  #private;
18
19
  constructor(connection: AgentConnection, hub: GuestHub | null);
19
20
  list(): readonly GuestSeat[];
21
+ gates(): {
22
+ messages: GuestGate[];
23
+ tools: GuestGate[];
24
+ };
20
25
  unavailable(): string | null;
21
26
  mint(agentId: string, draft: GuestDraft): Promise<{
22
27
  seat: GuestSeat;
@@ -15,7 +15,7 @@ import { TrayAdapter } from './tray-port.ts';
15
15
  export { AgentAdapter, CONE } from './agent-port.ts';
16
16
  export { ApprovalsAdapter, type HostApprovals, NOT_HERE, shown as shownApproval, } from './approvals-port.ts';
17
17
  export { ChangesAdapter, type ChangesEvents } from './changes-port.ts';
18
- export { GuestAdapter, type GuestHub, NO_CONTROL, NO_HUB, NO_OWNER, } from './guest-port.ts';
18
+ export { GuestAdapter, type GuestHub, NO_CONTROL, NO_HUB, NO_OWNER, NOT_OWNER_DEVICE, } from './guest-port.ts';
19
19
  export { MemoryAdapter } from './memory-port.ts';
20
20
  export { assistant, errorAction, errorPart, isBusy, queued, textOf, toMessages, } from './messages.ts';
21
21
  export { MonitorAdapter, type MonitorAdapterOptions, type MonitorInput, monitorSnapshot, } from './monitor-port.ts';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-agent",
3
- "version": "5.4.2",
3
+ "version": "5.5.1",
4
4
  "description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -54,7 +54,8 @@
54
54
  "test:unit": "NODE_NO_WARNINGS=1 mcr -c node_modules/@ai-ecoverse/slicc-shared-web/mcr.config.mjs node --test 'test/unit/**/*.test.mjs'",
55
55
  "typecheck": "tsc",
56
56
  "eval:judge": "node evals/judge.mjs",
57
- "lint": "slicc-lint && npm run lint:patches",
57
+ "lint": "slicc-lint && npm run lint:patches && npm run lint:chord",
58
+ "lint:chord": "node scripts/check-chord.mjs",
58
59
  "lint:patches": "node scripts/check-patches.mjs",
59
60
  "format": "biome check --write .",
60
61
  "trust": "npx fledgling sync -y --skip-publish",
@@ -83,10 +84,10 @@
83
84
  "@ai-ecoverse/slicc-browsers": "1.7.3",
84
85
  "@ai-ecoverse/slicc-vault": "1.9.1",
85
86
  "@earendil-works/chord": "1.2.0",
86
- "@earendil-works/pi-ai": "1.2.0",
87
- "@earendil-works/pi-codemode": "1.2.0",
88
- "@earendil-works/pi-durable": "1.2.0",
89
- "@earendil-works/pi-mcp": "1.2.0",
87
+ "@earendil-works/pi-ai": "1.3.0",
88
+ "@earendil-works/pi-codemode": "1.3.0",
89
+ "@earendil-works/pi-durable": "1.3.0",
90
+ "@earendil-works/pi-mcp": "1.3.0",
90
91
  "@sqlite.org/sqlite-wasm": "3.53.4-build2",
91
92
  "typebox": "1.3.36"
92
93
  },