@ai-ecoverse/slicc-agent 5.10.1 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/host.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  createHost,
3
3
  forbidden,
4
- replicatedState,
5
- resource
4
+ replicatedState
6
5
  } from "@earendil-works/chord";
7
6
  import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
8
7
  import {
@@ -38,12 +37,10 @@ import {
38
37
  } from "./services.js";
39
38
  import {
40
39
  AGENT_HOST,
41
- deviceOf,
42
- guestOf,
43
40
  principalKey,
44
41
  readable,
45
42
  readablesOf,
46
- seatOf,
43
+ SELF,
47
44
  served
48
45
  } from "./serving.js";
49
46
  import { slimmer, thumbnail } from "./thumbs.js";
@@ -232,7 +229,9 @@ async function hostAgent(agent, options = {}) {
232
229
  decide: (by) => (id, decision, reason, using) => approvals.decide(id, decision, reason, by, using)
233
230
  });
234
231
  const offGuests = guests.onEnd((id) => {
235
- void host.invalidatePrincipal((principal) => guestOf(principal)?.id === id);
232
+ void host.invalidatePrincipal(
233
+ (principal) => principal.seat === "guest" && principal.guest.id === id
234
+ );
236
235
  });
237
236
  let links = 0;
238
237
  return {
@@ -296,7 +295,7 @@ function closedToGuests(host) {
296
295
  const serve = ((type, factory, options) => host.serve(
297
296
  type,
298
297
  opened.has(factory) ? factory : (input, principal, self) => {
299
- if (seatOf(principal) === "guest") throw forbidden(CLOSED_TO_GUESTS);
298
+ if (principal.seat === "guest") throw forbidden(CLOSED_TO_GUESTS);
300
299
  return factory(input, principal, self);
301
300
  },
302
301
  options
@@ -318,81 +317,85 @@ function lazily(state) {
318
317
  events: (listener) => readable(state()).events(listener)
319
318
  };
320
319
  }
321
- const seated = (serving, seat, device) => ({
322
- ...seat === "view" ? serving.viewed : serving.trusted,
320
+ const seated = (serving, principal) => ({
321
+ ...principal.seat === "view" ? serving.viewed : serving.trusted,
323
322
  decide: serving.decide({
324
- by: seat === "owner" ? "owner" : "follower",
325
- ...device ? { device } : {}
323
+ by: principal.seat === "owner" ? "owner" : "follower",
324
+ ..."device" in principal && principal.device ? { device: principal.device } : {}
326
325
  })
327
326
  });
328
327
  const VIEW_METHODS = [...CONTROL_READS, ...OWNER_DEVICE_METHODS];
329
328
  function serveAgent(serving) {
330
- const host = closedToGuests(createHost({ name: AGENT_HOST, principalKey }));
329
+ const host = closedToGuests(
330
+ createHost({ name: AGENT_HOST, self: SELF, principalKey })
331
+ );
331
332
  const viewing = { ...serving.transcript, monitor: serving.viewMonitor };
332
- host.serve(AgentControl, ((_input, principal) => {
333
- const seat = seatOf(principal);
334
- const control = seated(serving, seat, deviceOf(principal));
335
- if (seat === "view") return { kind: "view", ...served(() => control, VIEW_METHODS) };
336
- return { kind: "control", ...served(() => control, CONTROL_METHODS) };
333
+ host.serve(AgentControl, (_input, principal) => {
334
+ const control = seated(serving, principal);
335
+ return principal.seat === "view" ? { variant: "view", ...served(() => control, VIEW_METHODS) } : { variant: "control", ...served(() => control, CONTROL_METHODS) };
336
+ });
337
+ host.serve(AgentTranscript, (_input, principal) => ({
338
+ variant: "transcript",
339
+ ...readablesOf(principal.seat === "view" ? viewing : serving.transcript)
337
340
  }));
338
- host.serve(AgentTranscript, ((_input, principal) => ({
339
- kind: "transcript",
340
- ...readablesOf(seatOf(principal) === "view" ? viewing : serving.transcript)
341
- })));
342
- host.serve(AgentSettings, ((_input, principal) => ({
343
- kind: seatOf(principal) === "view" ? "view" : "settings",
344
- state: readable(serving.settings.state),
345
- ...seatOf(principal) === "view" ? {} : served(() => serving.settings, SETTINGS_METHODS)
346
- })));
347
- host.serve(AgentRemoteService, ((_input, principal) => {
348
- if (seatOf(principal) !== "view")
349
- return { kind: "remote", ...served(() => serving.remote, REMOTE_METHODS) };
341
+ host.serve(
342
+ AgentSettings,
343
+ (_input, principal) => principal.seat === "view" ? { variant: "view", state: readable(serving.settings.state) } : {
344
+ variant: "settings",
345
+ state: readable(serving.settings.state),
346
+ ...served(() => serving.settings, SETTINGS_METHODS)
347
+ }
348
+ );
349
+ host.serve(AgentRemoteService, (_input, principal) => {
350
+ if (principal.seat !== "view")
351
+ return { variant: "remote", ...served(() => serving.remote, REMOTE_METHODS) };
350
352
  const scoped = viewRemote(serving.remote);
351
- return { kind: "watch", ...served(() => scoped, REMOTE_READS) };
352
- }));
353
- host.serve(AgentPagesService, ((_input, principal, self) => {
354
- if (seatOf(principal) !== "owner") return { kind: "none" };
355
- const held = self.resources({
356
- mine: resource({
357
- rev: 1,
358
- open: () => ownedPages(serving.pages),
359
- close: (mine) => mine.release()
360
- })
353
+ return { variant: "watch", ...served(() => scoped, REMOTE_READS) };
354
+ });
355
+ host.serve(AgentPagesService, (_input, principal, self) => {
356
+ if (principal.seat !== "owner") return { variant: "none" };
357
+ const mine = self.resource("mine", {
358
+ version: 1,
359
+ open: () => ownedPages(serving.pages),
360
+ close: (owned) => owned.release()
361
361
  });
362
- return { kind: "pages", ...served(() => held.mine.value, PAGE_METHODS) };
363
- }));
362
+ return { variant: "pages", ...served(() => mine.value, PAGE_METHODS) };
363
+ });
364
364
  host.serve(
365
365
  AgentGuestService,
366
366
  openToGuests((_input, principal, self) => {
367
- const guest = guestOf(principal);
368
- if (!guest) return { kind: "none" };
369
- const opening = serving.guest?.(guest);
367
+ if (principal.seat !== "guest") return { variant: "none" };
368
+ const opening = serving.guest?.(principal.guest);
370
369
  if (!opening) throw forbidden(CLOSED_TO_GUESTS);
371
- const held = self.resources({
372
- seat: resource({ rev: 1, open: () => opening, close: (made) => made.dispose() })
370
+ const seat = self.resource("seat", {
371
+ version: 1,
372
+ open: () => opening,
373
+ close: (made) => made.dispose()
373
374
  });
374
- const later = (name) => lazily(() => held.seat.value.value[name]);
375
+ const later = (name) => lazily(() => seat.value.value[name]);
375
376
  return {
376
- kind: "guest",
377
+ variant: "guest",
377
378
  transcript: later("transcript"),
378
379
  seat: later("seat"),
379
380
  proposals: later("proposals"),
380
- ...served(() => held.seat.value.value, GUEST_METHODS)
381
+ ...served(() => seat.value.value, GUEST_METHODS)
381
382
  };
382
383
  })
383
384
  );
384
- host.serve(AgentSudoService, ((_input, principal, self) => {
385
+ host.serve(AgentSudoService, (_input, principal, self) => {
385
386
  const sudo = serving.sudo;
386
- if (seatOf(principal) !== "owner" || !sudo) return { kind: "none" };
387
- const held = self.resources({
388
- mine: resource({ rev: 1, open: () => ownedSudo(sudo), close: (mine) => mine.release() })
387
+ if (principal.seat !== "owner" || !sudo) return { variant: "none" };
388
+ const mine = self.resource("mine", {
389
+ version: 1,
390
+ open: () => ownedSudo(sudo),
391
+ close: (owned) => owned.release()
389
392
  });
390
393
  return {
391
- kind: "sudo",
394
+ variant: "sudo",
392
395
  approvals: readable(sudo.approvals),
393
- ...served(() => held.mine.value, SUDO_METHODS)
396
+ ...served(() => mine.value, SUDO_METHODS)
394
397
  };
395
- }));
398
+ });
396
399
  return host;
397
400
  }
398
401
  export {
package/dist/host.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/host.ts"],
4
- "sourcesContent": ["import {\n type Context,\n createHost,\n forbidden,\n type Host,\n type Readable,\n type ReplicatedState,\n replicatedState,\n resource,\n type Self,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { Agent } from './agent.ts';\nimport {\n type ApprovalJudge,\n type Approvals,\n attachApprovals,\n type Decider,\n} from './approvals/index.ts';\nimport { type ApprovalPolicies, alwaysFor, attachApprovalPolicy } from './approvals/policy.ts';\nimport { type AgentSudo, createSudo, ownedSudo } from './approvals/sudo.ts';\nimport type { ChangesView } from './changes/git.ts';\nimport type { ChangesRuntime } from './changes/index.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport type { FreezerRuntime, FrozenCone } from './freezer/index.ts';\nimport { createGuests, type Guests } from './guests/index.ts';\nimport type { ScoopReviewHost } from './guests/scoop.ts';\nimport { admitGuest, guestOpener } from './guests/serve.ts';\nimport type { UserClients } from './kernel/users.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { createMonitor, type MonitorOptions } from './monitor/index.ts';\nimport { viewRemote } from './readonly.ts';\nimport { type AgentRemote, createRemote } from './remote/host.ts';\nimport { createPages, ownedPages, type Pages } from './remote/pages.ts';\nimport type { SecretName } from './secrets/names.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport {\n AgentControl,\n type AgentGuest,\n AgentGuestService,\n AgentPagesService,\n AgentRemoteService,\n AgentSettings,\n AgentSudoService,\n AgentTranscript,\n CONTROL_METHODS,\n CONTROL_READS,\n type Command,\n GUEST_METHODS,\n OWNER_DEVICE_METHODS,\n PAGE_METHODS,\n type PrivateRevision,\n REMOTE_METHODS,\n REMOTE_READS,\n SETTINGS_METHODS,\n SUDO_METHODS,\n} from './services.ts';\nimport {\n AGENT_HOST,\n type AgentPrincipal,\n deviceOf,\n type GuestPrincipal,\n guestOf,\n principalKey,\n readable,\n readablesOf,\n type Seat,\n seatOf,\n served,\n} from './serving.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { slimmer, type Thumbnail, thumbnail } from './thumbs.ts';\nimport { type LabelsRuntime, visibleLabels, watchLabel } from './titles/labels.ts';\nimport type { Uploads } from './uploads.ts';\nimport { agentViews } from './views.ts';\nimport { type PortEndpoint, PortLink } from './wire.ts';\n\nexport interface ConnectOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n readonly users?: UserClients;\n readonly pages: Pages;\n readonly guests: Guests;\n readonly approvals: Approvals;\n connect(endpoint: PortEndpoint, options?: ConnectOptions): void;\n close(): Promise<void>;\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n signIn: async () => null,\n dismissMoved: async () => {},\n};\n\nasync function follow(\n agent: Agent,\n context: Context,\n slim: (view: ConversationView) => ConversationView\n) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(slim(attached.value));\n const mirror = (value: ConversationView, from: Context) => state.replace(from, slim(value));\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, slim(next.value));\n off = next.subscribe(mirror);\n });\n return {\n state,\n refresh: () => state.replace(context, slim(attached.value)),\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport interface HostSecrets {\n vault: ReplicatedState<VaultState>;\n list(): readonly SecretName[];\n close?(): void;\n}\n\nconst idleVault = replicatedState<VaultState>({\n port: 'none',\n needed: false,\n version: 0,\n locked: 'no',\n held: 0,\n});\n\nfunction gatedControls(\n control: AgentControl,\n shown: (entry: number) => boolean,\n views: () => readonly ConversationView[],\n labels: ReplicatedState<Record<string, string>>\n) {\n const visible = (entry: number) =>\n views().some((view) => view.entries.some((item) => item.id === entry));\n const gated =\n (allowed: (entry: number) => boolean): AgentControl['image'] =>\n async (ref, using) =>\n allowed(ref.entry) ? control.image(ref, using) : { data: null, mimeType: null };\n const trusted: AgentControl = { ...control, image: gated(shown) };\n const viewed: AgentControl = { ...control, image: gated(visible), toolLabel: watchLabel(labels) };\n return { trusted, viewed };\n}\n\nasync function approving(\n agent: Agent,\n policy: ApprovalPolicies,\n options: { judge?: ApprovalJudge; intent?: ScoopReviewHost['intent']; approvalMs?: number },\n context: Context\n): Promise<Approvals> {\n const approvals = await attachApprovals(\n {\n harness: agent.harness,\n guestAlways: alwaysFor(policy),\n sudoApprover: () => policy.current().sudo.approver,\n scoops: agent.scoopReviews,\n ...(options.judge ? { judge: options.judge } : {}),\n ...(options.approvalMs ? { ttlMs: options.approvalMs } : {}),\n },\n context\n );\n agent.scoopReviews.bind({\n approvals,\n agents: agent.agents,\n harness: agent.harness,\n ...(options.intent ? { intent: options.intent } : {}),\n });\n return approvals;\n}\n\nasync function guestsOf(\n agent: Agent,\n approvals: Approvals,\n policy: ApprovalPolicies,\n context: Context\n): Promise<Guests> {\n const guests = await createGuests({\n harness: agent.harness,\n agents: agent.agents,\n approvals,\n policy,\n reviews: agent.reviews,\n context,\n });\n agent.gate.bind({ approvals, policy: () => guests.policy() });\n return guests;\n}\n\nconst noRevision = () => replicatedState<PrivateRevision>({ revision: 0 });\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n skills?: SkillsRuntime;\n sprinkles?: SprinklesRuntime;\n memory?: MemoryRuntime;\n freezer?: FreezerRuntime;\n changes?: ChangesRuntime;\n mcp?: Pick<McpRuntime, 'close'>;\n users?: UserClients;\n monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'>;\n pages?: Pages;\n secrets?: HostSecrets;\n uploads?: Uploads;\n thumbnail?: Thumbnail;\n labels?: LabelsRuntime;\n approvals?: Approvals;\n judge?: ApprovalJudge;\n intent?: ScoopReviewHost['intent'];\n approvalMs?: number;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n let refresh = () => {};\n const slims = slimmer(options.thumbnail ?? thumbnail, () => refresh());\n const transcript = await follow(agent, context, slims.slim);\n const { state } = transcript;\n const mounted = await agentViews(agent, context, slims.slim);\n refresh = () => {\n transcript.refresh();\n mounted.refresh();\n };\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const pages = options.pages ?? createPages();\n const deliveries = trackDeliveries(agent.harness, state, context);\n const policy = await attachApprovalPolicy(agent.harness, context);\n const approvals = options.approvals ?? (await approving(agent, policy, options, context));\n const monitor = createMonitor({\n ...options.monitor,\n harness: agent.harness,\n agents: agent.agents,\n views: mounted.views,\n context,\n });\n const guests = await guestsOf(agent, approvals, policy, context);\n const control: AgentControl = {\n ...createAgentControl(\n agent.harness,\n agent,\n deliveries,\n options.licks,\n options.scoops,\n options.skills,\n options.sprinkles,\n options.memory,\n options.freezer,\n options.changes,\n monitor,\n options.secrets?.list,\n options.uploads,\n options.labels,\n guests\n ),\n approvalPolicySet: (change, using) => policy.set(change, using),\n };\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\n vault: options.secrets?.vault ?? idleVault,\n async conversation(agentId, using) {\n if (!agentId) return agent.cone();\n const found = await agent.agents.conversation(agentId, using);\n if (!found) throw new Error(`There is no agent ${agentId}.`);\n return found;\n },\n });\n const shownViews = () => [state.value, ...Object.values(mounted.views.value)];\n const kept = options.labels?.labels ?? replicatedState<Record<string, string>>({});\n const labels = visibleLabels(kept, [state, mounted.views], shownViews);\n const transcriptService = {\n state,\n deliveries: deliveries.state,\n agents: mounted.agents,\n views: mounted.views,\n commands: options.skills?.commands ?? replicatedState<Command[]>([]),\n privateRevision: options.skills?.privateRevision ?? noRevision(),\n sprinkles: options.sprinkles?.sprinkles ?? replicatedState<Sprinkle[]>([]),\n memories: options.memory?.memories ?? replicatedState<MemoryEntry[]>([]),\n memoryScopes: options.memory?.scopes ?? replicatedState<MemoryScope[]>([]),\n frozen: options.freezer?.frozen ?? replicatedState<FrozenCone[]>([]),\n changes:\n options.changes?.view ?? replicatedState<ChangesView>({ unavailable: null, changes: [] }),\n monitor: monitor.state,\n vault: options.secrets?.vault ?? idleVault,\n labels: labels.state,\n guests: guests.seats,\n approvals: approvals.state,\n approvalPolicy: policy.state,\n };\n const sudo = createSudo({\n approvals,\n agents: () => agent.agents.state(),\n ...(options.licks ? { licks: options.licks.licks } : {}),\n });\n const settings = options.settings ?? noSettings;\n const gates = gatedControls(control, slims.shown, shownViews, transcriptService.labels);\n const { trusted, viewed } = gates;\n const host = serveAgent({\n trusted,\n viewed,\n transcript: transcriptService,\n viewMonitor: monitor.viewState,\n sudo,\n settings,\n remote,\n pages,\n guest: guestOpener(guests, agent.agents, mounted.views, context),\n decide: (by) => (id, decision, reason, using) =>\n approvals.decide(id, decision, reason, by, using),\n });\n const offGuests = guests.onEnd((id) => {\n void host.invalidatePrincipal((principal) => guestOf(principal)?.id === id);\n });\n let links = 0;\n return {\n serverId,\n agent,\n pages,\n guests,\n approvals,\n ...(options.users ? { users: options.users } : {}),\n connect(endpoint, connectOptions) {\n if (connectOptions?.guest) {\n links += 1;\n admitGuest(guests, endpoint, connectOptions.guest, serverId, links, host);\n return;\n }\n const seat: Seat = connectOptions?.readOnly\n ? 'view'\n : connectOptions?.pages === false\n ? 'control'\n : 'owner';\n links += 1;\n const link = new PortLink(endpoint);\n link.greet(serverId);\n const device = connectOptions?.device ? { device: connectOptions.device } : {};\n host.accept(link, {\n principal: { seat, link: links, ...device } satisfies AgentPrincipal,\n });\n },\n async close() {\n offGuests();\n await host.close();\n guests.dispose();\n await pages.dispose();\n await monitor.dispose();\n await remote.dispose();\n deliveries.dispose();\n sudo.close();\n approvals.close();\n transcript.dispose();\n mounted.dispose();\n labels.dispose();\n slims.dispose();\n for (const off of untouch) off();\n options.freezer?.close();\n options.secrets?.close?.();\n await options.changes?.close(context);\n await options.memory?.close(context);\n await options.sprinkles?.close(context);\n await options.skills?.close(context);\n await options.mcp?.close(context);\n await options.scoops?.runtime.close(context);\n await options.licks?.sources.close(context);\n await agent.close();\n await options.users?.close();\n },\n };\n}\n\ninterface Served {\n trusted: AgentControl;\n viewed: AgentControl;\n transcript: Record<keyof AgentTranscript, ReplicatedState<unknown>>;\n viewMonitor: ReplicatedState<unknown>;\n sudo?: AgentSudo;\n settings: AgentSettings;\n remote: AgentRemote;\n pages: Pages;\n guest?: (principal: GuestPrincipal) => { value: AgentGuest; dispose(): void } | undefined;\n decide: (by: Decider) => AgentControl['decide'];\n}\n\nexport const CLOSED_TO_GUESTS = 'a guest seat has only its transcript and propose';\n\nconst opened = new WeakSet<object>();\n\nexport const openToGuests = <F extends object>(factory: F): F => {\n opened.add(factory);\n return factory;\n};\n\nexport function closedToGuests(host: Host): Host {\n const serve = ((type: never, factory: (...args: unknown[]) => unknown, options?: never) =>\n host.serve(\n type,\n (opened.has(factory)\n ? factory\n : (input: unknown, principal: unknown, self: unknown) => {\n if (seatOf(principal as never) === 'guest') throw forbidden(CLOSED_TO_GUESTS);\n return factory(input, principal, self);\n }) as never,\n options\n )) as Host['serve'];\n return new Proxy(host, {\n get(target, key) {\n if (key === 'serve') return serve;\n const value = Reflect.get(target, key, target) as unknown;\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n\nexport function lazily<T>(state: () => ReplicatedState<T>): Readable<T> {\n return {\n get value() {\n return readable(state()).value;\n },\n subscribe: (listener) => readable(state()).subscribe(listener),\n events: (listener) => readable(state()).events(listener),\n };\n}\n\nconst seated = (serving: Served, seat: Seat, device: string | undefined): AgentControl => ({\n ...(seat === 'view' ? serving.viewed : serving.trusted),\n decide: serving.decide({\n by: seat === 'owner' ? 'owner' : 'follower',\n ...(device ? { device } : {}),\n }),\n});\n\nconst VIEW_METHODS = [...CONTROL_READS, ...OWNER_DEVICE_METHODS];\n\nexport function serveAgent(serving: Served): Host {\n const host = closedToGuests(createHost({ name: AGENT_HOST, principalKey }));\n const viewing = { ...serving.transcript, monitor: serving.viewMonitor };\n host.serve(AgentControl, ((_input: unknown, principal: unknown) => {\n const seat = seatOf(principal);\n const control = seated(serving, seat, deviceOf(principal));\n if (seat === 'view') return { kind: 'view', ...served(() => control, VIEW_METHODS) };\n return { kind: 'control', ...served(() => control, CONTROL_METHODS) };\n }) as never);\n host.serve(AgentTranscript, ((_input: unknown, principal: unknown) => ({\n kind: 'transcript',\n ...readablesOf(seatOf(principal) === 'view' ? viewing : serving.transcript),\n })) as never);\n host.serve(AgentSettings, ((_input: unknown, principal: unknown) => ({\n kind: seatOf(principal) === 'view' ? 'view' : 'settings',\n state: readable(serving.settings.state),\n ...(seatOf(principal) === 'view' ? {} : served(() => serving.settings, SETTINGS_METHODS)),\n })) as never);\n host.serve(AgentRemoteService, ((_input: unknown, principal: unknown) => {\n if (seatOf(principal) !== 'view')\n return { kind: 'remote', ...served(() => serving.remote, REMOTE_METHODS) };\n const scoped = viewRemote(serving.remote);\n return { kind: 'watch', ...served(() => scoped, REMOTE_READS) };\n }) as never);\n host.serve(AgentPagesService, ((_input: unknown, principal: unknown, self: Self) => {\n if (seatOf(principal) !== 'owner') return { kind: 'none' };\n const held = self.resources({\n mine: resource({\n rev: 1,\n open: () => ownedPages(serving.pages),\n close: (mine) => mine.release(),\n }),\n });\n return { kind: 'pages', ...served(() => held.mine.value, PAGE_METHODS) };\n }) as never);\n host.serve(\n AgentGuestService,\n openToGuests((_input: unknown, principal: unknown, self: Self) => {\n const guest = guestOf(principal as never);\n if (!guest) return { kind: 'none' };\n const opening = serving.guest?.(guest);\n if (!opening) throw forbidden(CLOSED_TO_GUESTS);\n const held = self.resources({\n seat: resource({ rev: 1, open: () => opening, close: (made) => made.dispose() }),\n });\n const later = (name: 'transcript' | 'seat' | 'proposals') =>\n lazily(() => held.seat.value.value[name] as ReplicatedState<unknown>);\n return {\n kind: 'guest',\n transcript: later('transcript'),\n seat: later('seat'),\n proposals: later('proposals'),\n ...served(() => held.seat.value.value, GUEST_METHODS),\n };\n }) as never\n );\n host.serve(AgentSudoService, ((_input: unknown, principal: unknown, self: Self) => {\n const sudo = serving.sudo;\n if (seatOf(principal) !== 'owner' || !sudo) return { kind: 'none' };\n const held = self.resources({\n mine: resource({ rev: 1, open: () => ownedSudo(sudo), close: (mine) => mine.release() }),\n });\n return {\n kind: 'sudo',\n approvals: readable(sudo.approvals),\n ...served(() => held.mine.value, SUDO_METHODS),\n };\n }) as never);\n return host;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type Context,\n createHost,\n forbidden,\n type Host,\n type Readable,\n type ReplicatedState,\n replicatedState,\n type Self,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { Agent } from './agent.ts';\nimport {\n type ApprovalJudge,\n type Approvals,\n attachApprovals,\n type Decider,\n} from './approvals/index.ts';\nimport { type ApprovalPolicies, alwaysFor, attachApprovalPolicy } from './approvals/policy.ts';\nimport { type AgentSudo, createSudo, ownedSudo } from './approvals/sudo.ts';\nimport type { ChangesView } from './changes/git.ts';\nimport type { ChangesRuntime } from './changes/index.ts';\nimport { createAgentControl, type HostLicks, type HostScoops } from './control.ts';\nimport { trackDeliveries } from './deliveries.ts';\nimport type { FreezerRuntime, FrozenCone } from './freezer/index.ts';\nimport { createGuests, type Guests } from './guests/index.ts';\nimport type { ScoopReviewHost } from './guests/scoop.ts';\nimport { admitGuest, guestOpener } from './guests/serve.ts';\nimport type { UserClients } from './kernel/users.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { createMonitor, type MonitorOptions } from './monitor/index.ts';\nimport { viewRemote } from './readonly.ts';\nimport { type AgentRemote, createRemote } from './remote/host.ts';\nimport { createPages, ownedPages, type Pages } from './remote/pages.ts';\nimport type { SecretName } from './secrets/names.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport {\n AgentControl,\n type AgentGuest,\n AgentGuestService,\n AgentPagesService,\n AgentRemoteService,\n AgentSettings,\n AgentSudoService,\n AgentTranscript,\n CONTROL_METHODS,\n CONTROL_READS,\n type Command,\n GUEST_METHODS,\n OWNER_DEVICE_METHODS,\n PAGE_METHODS,\n type PrivateRevision,\n REMOTE_METHODS,\n REMOTE_READS,\n SETTINGS_METHODS,\n SUDO_METHODS,\n} from './services.ts';\nimport {\n AGENT_HOST,\n type AgentPrincipal,\n type GuestPrincipal,\n principalKey,\n readable,\n readablesOf,\n SELF,\n type Seat,\n served,\n} from './serving.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { slimmer, type Thumbnail, thumbnail } from './thumbs.ts';\nimport { type LabelsRuntime, visibleLabels, watchLabel } from './titles/labels.ts';\nimport type { Uploads } from './uploads.ts';\nimport { agentViews } from './views.ts';\nimport { type PortEndpoint, PortLink } from './wire.ts';\n\nexport interface ConnectOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n readonly users?: UserClients;\n readonly pages: Pages;\n readonly guests: Guests;\n readonly approvals: Approvals;\n connect(endpoint: PortEndpoint, options?: ConnectOptions): void;\n close(): Promise<void>;\n}\n\nconst noSettings: AgentSettings = {\n state: replicatedState({ models: [], accounts: [] }),\n connect: async () => {\n throw new Error('this agent has no accounts');\n },\n disconnect: async () => {},\n signIn: async () => null,\n dismissMoved: async () => {},\n};\n\nasync function follow(\n agent: Agent,\n context: Context,\n slim: (view: ConversationView) => ConversationView\n) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(slim(attached.value));\n const mirror = (value: ConversationView, from: Context) => state.replace(from, slim(value));\n let off = attached.subscribe(mirror);\n const stop = agent.onCone(async (conversation) => {\n const next = await conversation.viewState(context);\n off();\n attached.dispose();\n attached = next;\n state.replace(context, slim(next.value));\n off = next.subscribe(mirror);\n });\n return {\n state,\n refresh: () => state.replace(context, slim(attached.value)),\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\n\nexport interface HostSecrets {\n vault: ReplicatedState<VaultState>;\n list(): readonly SecretName[];\n close?(): void;\n}\n\nconst idleVault = replicatedState<VaultState>({\n port: 'none',\n needed: false,\n version: 0,\n locked: 'no',\n held: 0,\n});\n\nfunction gatedControls(\n control: AgentControl,\n shown: (entry: number) => boolean,\n views: () => readonly ConversationView[],\n labels: ReplicatedState<Record<string, string>>\n) {\n const visible = (entry: number) =>\n views().some((view) => view.entries.some((item) => item.id === entry));\n const gated =\n (allowed: (entry: number) => boolean): AgentControl['image'] =>\n async (ref, using) =>\n allowed(ref.entry) ? control.image(ref, using) : { data: null, mimeType: null };\n const trusted: AgentControl = { ...control, image: gated(shown) };\n const viewed: AgentControl = { ...control, image: gated(visible), toolLabel: watchLabel(labels) };\n return { trusted, viewed };\n}\n\nasync function approving(\n agent: Agent,\n policy: ApprovalPolicies,\n options: { judge?: ApprovalJudge; intent?: ScoopReviewHost['intent']; approvalMs?: number },\n context: Context\n): Promise<Approvals> {\n const approvals = await attachApprovals(\n {\n harness: agent.harness,\n guestAlways: alwaysFor(policy),\n sudoApprover: () => policy.current().sudo.approver,\n scoops: agent.scoopReviews,\n ...(options.judge ? { judge: options.judge } : {}),\n ...(options.approvalMs ? { ttlMs: options.approvalMs } : {}),\n },\n context\n );\n agent.scoopReviews.bind({\n approvals,\n agents: agent.agents,\n harness: agent.harness,\n ...(options.intent ? { intent: options.intent } : {}),\n });\n return approvals;\n}\n\nasync function guestsOf(\n agent: Agent,\n approvals: Approvals,\n policy: ApprovalPolicies,\n context: Context\n): Promise<Guests> {\n const guests = await createGuests({\n harness: agent.harness,\n agents: agent.agents,\n approvals,\n policy,\n reviews: agent.reviews,\n context,\n });\n agent.gate.bind({ approvals, policy: () => guests.policy() });\n return guests;\n}\n\nconst noRevision = () => replicatedState<PrivateRevision>({ revision: 0 });\n\nexport async function hostAgent(\n agent: Agent,\n options: {\n serverId?: string;\n context?: Context;\n settings?: AgentSettings;\n licks?: HostLicks;\n scoops?: HostScoops;\n skills?: SkillsRuntime;\n sprinkles?: SprinklesRuntime;\n memory?: MemoryRuntime;\n freezer?: FreezerRuntime;\n changes?: ChangesRuntime;\n mcp?: Pick<McpRuntime, 'close'>;\n users?: UserClients;\n monitor?: Pick<MonitorOptions, 'kernel' | 'groups' | 'users'>;\n pages?: Pages;\n secrets?: HostSecrets;\n uploads?: Uploads;\n thumbnail?: Thumbnail;\n labels?: LabelsRuntime;\n approvals?: Approvals;\n judge?: ApprovalJudge;\n intent?: ScoopReviewHost['intent'];\n approvalMs?: number;\n } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n let refresh = () => {};\n const slims = slimmer(options.thumbnail ?? thumbnail, () => refresh());\n const transcript = await follow(agent, context, slims.slim);\n const { state } = transcript;\n const mounted = await agentViews(agent, context, slims.slim);\n refresh = () => {\n transcript.refresh();\n mounted.refresh();\n };\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const pages = options.pages ?? createPages();\n const deliveries = trackDeliveries(agent.harness, state, context);\n const policy = await attachApprovalPolicy(agent.harness, context);\n const approvals = options.approvals ?? (await approving(agent, policy, options, context));\n const monitor = createMonitor({\n ...options.monitor,\n harness: agent.harness,\n agents: agent.agents,\n views: mounted.views,\n context,\n });\n const guests = await guestsOf(agent, approvals, policy, context);\n const control: AgentControl = {\n ...createAgentControl(\n agent.harness,\n agent,\n deliveries,\n options.licks,\n options.scoops,\n options.skills,\n options.sprinkles,\n options.memory,\n options.freezer,\n options.changes,\n monitor,\n options.secrets?.list,\n options.uploads,\n options.labels,\n guests\n ),\n approvalPolicySet: (change, using) => policy.set(change, using),\n };\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\n vault: options.secrets?.vault ?? idleVault,\n async conversation(agentId, using) {\n if (!agentId) return agent.cone();\n const found = await agent.agents.conversation(agentId, using);\n if (!found) throw new Error(`There is no agent ${agentId}.`);\n return found;\n },\n });\n const shownViews = () => [state.value, ...Object.values(mounted.views.value)];\n const kept = options.labels?.labels ?? replicatedState<Record<string, string>>({});\n const labels = visibleLabels(kept, [state, mounted.views], shownViews);\n const transcriptService = {\n state,\n deliveries: deliveries.state,\n agents: mounted.agents,\n views: mounted.views,\n commands: options.skills?.commands ?? replicatedState<Command[]>([]),\n privateRevision: options.skills?.privateRevision ?? noRevision(),\n sprinkles: options.sprinkles?.sprinkles ?? replicatedState<Sprinkle[]>([]),\n memories: options.memory?.memories ?? replicatedState<MemoryEntry[]>([]),\n memoryScopes: options.memory?.scopes ?? replicatedState<MemoryScope[]>([]),\n frozen: options.freezer?.frozen ?? replicatedState<FrozenCone[]>([]),\n changes:\n options.changes?.view ?? replicatedState<ChangesView>({ unavailable: null, changes: [] }),\n monitor: monitor.state,\n vault: options.secrets?.vault ?? idleVault,\n labels: labels.state,\n guests: guests.seats,\n approvals: approvals.state,\n approvalPolicy: policy.state,\n };\n const sudo = createSudo({\n approvals,\n agents: () => agent.agents.state(),\n ...(options.licks ? { licks: options.licks.licks } : {}),\n });\n const settings = options.settings ?? noSettings;\n const gates = gatedControls(control, slims.shown, shownViews, transcriptService.labels);\n const { trusted, viewed } = gates;\n const host = serveAgent({\n trusted,\n viewed,\n transcript: transcriptService,\n viewMonitor: monitor.viewState,\n sudo,\n settings,\n remote,\n pages,\n guest: guestOpener(guests, agent.agents, mounted.views, context),\n decide: (by) => (id, decision, reason, using) =>\n approvals.decide(id, decision, reason, by, using),\n });\n const offGuests = guests.onEnd((id) => {\n void host.invalidatePrincipal(\n (principal) => principal.seat === 'guest' && principal.guest.id === id\n );\n });\n let links = 0;\n return {\n serverId,\n agent,\n pages,\n guests,\n approvals,\n ...(options.users ? { users: options.users } : {}),\n connect(endpoint, connectOptions) {\n if (connectOptions?.guest) {\n links += 1;\n admitGuest(guests, endpoint, connectOptions.guest, serverId, links, host);\n return;\n }\n const seat: Exclude<Seat, 'guest'> = connectOptions?.readOnly\n ? 'view'\n : connectOptions?.pages === false\n ? 'control'\n : 'owner';\n links += 1;\n const link = new PortLink(endpoint);\n link.greet(serverId);\n const device = connectOptions?.device ? { device: connectOptions.device } : {};\n host.accept(link, {\n principal: { seat, link: links, ...device } satisfies AgentPrincipal,\n });\n },\n async close() {\n offGuests();\n await host.close();\n guests.dispose();\n await pages.dispose();\n await monitor.dispose();\n await remote.dispose();\n deliveries.dispose();\n sudo.close();\n approvals.close();\n transcript.dispose();\n mounted.dispose();\n labels.dispose();\n slims.dispose();\n for (const off of untouch) off();\n options.freezer?.close();\n options.secrets?.close?.();\n await options.changes?.close(context);\n await options.memory?.close(context);\n await options.sprinkles?.close(context);\n await options.skills?.close(context);\n await options.mcp?.close(context);\n await options.scoops?.runtime.close(context);\n await options.licks?.sources.close(context);\n await agent.close();\n await options.users?.close();\n },\n };\n}\n\ninterface Served {\n trusted: AgentControl;\n viewed: AgentControl;\n transcript: Record<keyof AgentTranscript, ReplicatedState<unknown>>;\n viewMonitor: ReplicatedState<unknown>;\n sudo?: AgentSudo;\n settings: AgentSettings;\n remote: AgentRemote;\n pages: Pages;\n guest?: (principal: GuestPrincipal) => { value: AgentGuest; dispose(): void } | undefined;\n decide: (by: Decider) => AgentControl['decide'];\n}\n\nexport const CLOSED_TO_GUESTS = 'a guest seat has only its transcript and propose';\n\nconst opened = new WeakSet<object>();\n\nexport const openToGuests = <F extends object>(factory: F): F => {\n opened.add(factory);\n return factory;\n};\n\nexport function closedToGuests(host: Host<AgentPrincipal>): Host<AgentPrincipal> {\n const serve = ((type: never, factory: (...args: unknown[]) => unknown, options?: never) =>\n host.serve(\n type,\n (opened.has(factory)\n ? factory\n : (input: unknown, principal: AgentPrincipal, self: unknown) => {\n if (principal.seat === 'guest') throw forbidden(CLOSED_TO_GUESTS);\n return factory(input, principal, self);\n }) as never,\n options\n )) as Host<AgentPrincipal>['serve'];\n return new Proxy(host, {\n get(target, key) {\n if (key === 'serve') return serve;\n const value = Reflect.get(target, key, target) as unknown;\n return typeof value === 'function' ? value.bind(target) : value;\n },\n });\n}\n\nexport function lazily<T>(state: () => ReplicatedState<T>): Readable<T> {\n return {\n get value() {\n return readable(state()).value;\n },\n subscribe: (listener) => readable(state()).subscribe(listener),\n events: (listener) => readable(state()).events(listener),\n };\n}\n\nconst seated = (serving: Served, principal: AgentPrincipal): AgentControl => ({\n ...(principal.seat === 'view' ? serving.viewed : serving.trusted),\n decide: serving.decide({\n by: principal.seat === 'owner' ? 'owner' : 'follower',\n ...('device' in principal && principal.device ? { device: principal.device } : {}),\n }),\n});\n\nconst VIEW_METHODS = [...CONTROL_READS, ...OWNER_DEVICE_METHODS];\n\nexport function serveAgent(serving: Served): Host<AgentPrincipal> {\n const host = closedToGuests(\n createHost<AgentPrincipal>({ name: AGENT_HOST, self: SELF, principalKey })\n );\n const viewing = { ...serving.transcript, monitor: serving.viewMonitor };\n host.serve(AgentControl, (_input, principal) => {\n const control = seated(serving, principal);\n return principal.seat === 'view'\n ? { variant: 'view', ...served(() => control, VIEW_METHODS) }\n : { variant: 'control', ...served(() => control, CONTROL_METHODS) };\n });\n host.serve(AgentTranscript, (_input, principal) => ({\n variant: 'transcript',\n ...readablesOf(principal.seat === 'view' ? viewing : serving.transcript),\n }));\n host.serve(AgentSettings, (_input, principal) =>\n principal.seat === 'view'\n ? { variant: 'view', state: readable(serving.settings.state) }\n : {\n variant: 'settings',\n state: readable(serving.settings.state),\n ...served(() => serving.settings, SETTINGS_METHODS),\n }\n );\n host.serve(AgentRemoteService, (_input, principal) => {\n if (principal.seat !== 'view')\n return { variant: 'remote', ...served(() => serving.remote, REMOTE_METHODS) };\n const scoped = viewRemote(serving.remote);\n return { variant: 'watch', ...served(() => scoped, REMOTE_READS) };\n });\n host.serve(AgentPagesService, (_input, principal, self) => {\n if (principal.seat !== 'owner') return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedPages(serving.pages),\n close: (owned) => owned.release(),\n });\n return { variant: 'pages', ...served(() => mine.value, PAGE_METHODS) };\n });\n host.serve(\n AgentGuestService,\n openToGuests((_input: unknown, principal: AgentPrincipal, self: Self<AgentPrincipal>) => {\n if (principal.seat !== 'guest') return { variant: 'none' };\n const opening = serving.guest?.(principal.guest);\n if (!opening) throw forbidden(CLOSED_TO_GUESTS);\n const seat = self.resource('seat', {\n version: 1,\n open: () => opening,\n close: (made) => made.dispose(),\n });\n const later = (name: 'transcript' | 'seat' | 'proposals') =>\n lazily(() => seat.value.value[name] as ReplicatedState<unknown>);\n return {\n variant: 'guest',\n transcript: later('transcript'),\n seat: later('seat'),\n proposals: later('proposals'),\n ...served(() => seat.value.value, GUEST_METHODS),\n };\n })\n );\n host.serve(AgentSudoService, (_input, principal, self) => {\n const sudo = serving.sudo;\n if (principal.seat !== 'owner' || !sudo) return { variant: 'none' };\n const mine = self.resource('mine', {\n version: 1,\n open: () => ownedSudo(sudo),\n close: (owned) => owned.release(),\n });\n return {\n variant: 'sudo',\n approvals: readable(sudo.approvals),\n ...served(() => mine.value, SUDO_METHODS),\n };\n });\n return host;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/owner.js CHANGED
@@ -38,8 +38,11 @@ async function startAgent(options) {
38
38
  let worker = Promise.resolve().then(spawn);
39
39
  const asking = /* @__PURE__ */ new Set();
40
40
  const stopAsking = () => {
41
- for (const stop of asking) stop.abort();
41
+ const waiting = [...asking];
42
42
  asking.clear();
43
+ return () => {
44
+ for (const stop of waiting) stop.abort();
45
+ };
43
46
  };
44
47
  try {
45
48
  await worker;
@@ -76,20 +79,22 @@ async function startAgent(options) {
76
79
  }
77
80
  },
78
81
  restart() {
79
- stopAsking();
82
+ const deny = stopAsking();
80
83
  worker = worker.catch(() => void 0).then((old) => {
81
84
  old?.terminate();
85
+ deny();
82
86
  return spawn();
83
87
  });
84
88
  return worker.then(() => void 0);
85
89
  },
86
90
  async release() {
87
- stopAsking();
91
+ const deny = stopAsking();
88
92
  const previous = worker;
89
93
  worker = Promise.resolve(void 0);
90
94
  try {
91
95
  (await previous.catch(() => void 0))?.terminate();
92
96
  } finally {
97
+ deny();
93
98
  release();
94
99
  }
95
100
  }
package/dist/owner.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/owner.ts"],
4
- "sourcesContent": ["import type { SudoAnswer, SudoRequest } from './approvals/sudo.ts';\nimport { type ApproveOptions, askSudo, unavailable } from './approvals/sudo-client.ts';\nimport { type AgentConnection, connectAgent } from './client.ts';\nimport { type KernelSource, serveAdmin } from './kernel/users.ts';\nimport { holdLock } from './opfs-pool.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport const AGENT_LOCK = 'slicc-agent';\n\nexport interface AgentWorker {\n postMessage(message: unknown, transfer: Transferable[]): void;\n terminate(): void;\n}\n\nexport interface PortOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentOwner {\n connect(options?: PortOptions): Promise<AgentConnection>;\n port(options?: PortOptions): Promise<PortEndpoint & Transferable>;\n approve(request: SudoRequest, options?: ApproveOptions): Promise<SudoAnswer>;\n restart(): Promise<void>;\n release(): Promise<void>;\n}\n\nexport type { KernelSource } from './kernel/users.ts';\n\nexport interface OwnerOptions {\n worker: () => AgentWorker;\n kernel?: KernelSource;\n locks?: LockManager;\n held?: boolean;\n channel?: () => { port1: PortEndpoint & Transferable; port2: Transferable };\n}\n\nexport async function startAgent(options: OwnerOptions): Promise<AgentOwner> {\n const release = options.held\n ? () => undefined\n : await holdLock(options.locks ?? navigator.locks, AGENT_LOCK);\n const channel = options.channel ?? (() => new MessageChannel());\n const spawn = async (): Promise<AgentWorker> => {\n const created = options.worker();\n let admin: (PortEndpoint & Transferable) | undefined;\n try {\n if (options.kernel) {\n const port = await options.kernel.connect();\n if (!options.kernel.users) created.postMessage({ kernel: port }, [port]);\n else {\n const { port1, port2 } = channel();\n admin = port1;\n serveAdmin(port1, options.kernel);\n created.postMessage({ kernel: port, admin: port2 }, [port, port2]);\n }\n }\n } catch (error) {\n admin?.close?.();\n created.terminate();\n throw error;\n }\n if (!admin) return created;\n const served = admin;\n return {\n postMessage: (message, transfer) => created.postMessage(message, transfer),\n terminate() {\n served.close?.();\n created.terminate();\n },\n };\n };\n let worker: Promise<AgentWorker | undefined> = Promise.resolve().then(spawn);\n const asking = new Set<AbortController>();\n const stopAsking = () => {\n for (const stop of asking) stop.abort();\n asking.clear();\n };\n try {\n await worker;\n } catch (error) {\n release();\n throw error;\n }\n const open = async (portOptions: PortOptions = {}): Promise<PortEndpoint & Transferable> => {\n const ready = await worker;\n if (!ready) throw new Error('the agent was released');\n const { port1, port2 } = channel();\n const readOnly = portOptions.readOnly === true ? { readOnly: true } : {};\n const pages = portOptions.pages === false ? { pages: false } : {};\n const guest = portOptions.guest\n ? { guest: { id: String(portOptions.guest.id), label: String(portOptions.guest.label) } }\n : {};\n const device = portOptions.device ? { device: portOptions.device } : {};\n ready.postMessage({ connect: port2, ...readOnly, ...pages, ...guest, ...device }, [port2]);\n return port1;\n };\n return {\n async connect(portOptions) {\n return connectAgent(await open(portOptions));\n },\n port: open,\n async approve(request, approveOptions) {\n const stop = new AbortController();\n asking.add(stop);\n try {\n const port = await open().catch((error: unknown) => {\n throw unavailable(error);\n });\n return await askSudo(port, request, approveOptions, stop.signal);\n } finally {\n asking.delete(stop);\n }\n },\n restart() {\n stopAsking();\n worker = worker\n .catch(() => undefined)\n .then((old) => {\n old?.terminate();\n return spawn();\n });\n return worker.then(() => undefined);\n },\n async release() {\n stopAsking();\n const previous = worker;\n worker = Promise.resolve(undefined);\n try {\n (await previous.catch(() => undefined))?.terminate();\n } finally {\n release();\n }\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { SudoAnswer, SudoRequest } from './approvals/sudo.ts';\nimport { type ApproveOptions, askSudo, unavailable } from './approvals/sudo-client.ts';\nimport { type AgentConnection, connectAgent } from './client.ts';\nimport { type KernelSource, serveAdmin } from './kernel/users.ts';\nimport { holdLock } from './opfs-pool.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport const AGENT_LOCK = 'slicc-agent';\n\nexport interface AgentWorker {\n postMessage(message: unknown, transfer: Transferable[]): void;\n terminate(): void;\n}\n\nexport interface PortOptions {\n readOnly?: boolean;\n pages?: boolean;\n guest?: { id: string; label: string };\n device?: string;\n}\n\nexport interface AgentOwner {\n connect(options?: PortOptions): Promise<AgentConnection>;\n port(options?: PortOptions): Promise<PortEndpoint & Transferable>;\n approve(request: SudoRequest, options?: ApproveOptions): Promise<SudoAnswer>;\n restart(): Promise<void>;\n release(): Promise<void>;\n}\n\nexport type { KernelSource } from './kernel/users.ts';\n\nexport interface OwnerOptions {\n worker: () => AgentWorker;\n kernel?: KernelSource;\n locks?: LockManager;\n held?: boolean;\n channel?: () => { port1: PortEndpoint & Transferable; port2: Transferable };\n}\n\nexport async function startAgent(options: OwnerOptions): Promise<AgentOwner> {\n const release = options.held\n ? () => undefined\n : await holdLock(options.locks ?? navigator.locks, AGENT_LOCK);\n const channel = options.channel ?? (() => new MessageChannel());\n const spawn = async (): Promise<AgentWorker> => {\n const created = options.worker();\n let admin: (PortEndpoint & Transferable) | undefined;\n try {\n if (options.kernel) {\n const port = await options.kernel.connect();\n if (!options.kernel.users) created.postMessage({ kernel: port }, [port]);\n else {\n const { port1, port2 } = channel();\n admin = port1;\n serveAdmin(port1, options.kernel);\n created.postMessage({ kernel: port, admin: port2 }, [port, port2]);\n }\n }\n } catch (error) {\n admin?.close?.();\n created.terminate();\n throw error;\n }\n if (!admin) return created;\n const served = admin;\n return {\n postMessage: (message, transfer) => created.postMessage(message, transfer),\n terminate() {\n served.close?.();\n created.terminate();\n },\n };\n };\n let worker: Promise<AgentWorker | undefined> = Promise.resolve().then(spawn);\n const asking = new Set<AbortController>();\n const stopAsking = () => {\n const waiting = [...asking];\n asking.clear();\n return () => {\n for (const stop of waiting) stop.abort();\n };\n };\n try {\n await worker;\n } catch (error) {\n release();\n throw error;\n }\n const open = async (portOptions: PortOptions = {}): Promise<PortEndpoint & Transferable> => {\n const ready = await worker;\n if (!ready) throw new Error('the agent was released');\n const { port1, port2 } = channel();\n const readOnly = portOptions.readOnly === true ? { readOnly: true } : {};\n const pages = portOptions.pages === false ? { pages: false } : {};\n const guest = portOptions.guest\n ? { guest: { id: String(portOptions.guest.id), label: String(portOptions.guest.label) } }\n : {};\n const device = portOptions.device ? { device: portOptions.device } : {};\n ready.postMessage({ connect: port2, ...readOnly, ...pages, ...guest, ...device }, [port2]);\n return port1;\n };\n return {\n async connect(portOptions) {\n return connectAgent(await open(portOptions));\n },\n port: open,\n async approve(request, approveOptions) {\n const stop = new AbortController();\n asking.add(stop);\n try {\n const port = await open().catch((error: unknown) => {\n throw unavailable(error);\n });\n return await askSudo(port, request, approveOptions, stop.signal);\n } finally {\n asking.delete(stop);\n }\n },\n restart() {\n const deny = stopAsking();\n worker = worker\n .catch(() => undefined)\n .then((old) => {\n old?.terminate();\n deny();\n return spawn();\n });\n return worker.then(() => undefined);\n },\n async release() {\n const deny = stopAsking();\n const previous = worker;\n worker = Promise.resolve(undefined);\n try {\n (await previous.catch(() => undefined))?.terminate();\n } finally {\n deny();\n release();\n }\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/serving.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ hostNamed,
2
3
  isChordError,
3
4
  method,
4
5
  remote
@@ -7,17 +8,14 @@ import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/conte
7
8
  import { diffRevisions } from "@earendil-works/chord/delta";
8
9
  import { Type } from "typebox";
9
10
  const AGENT_HOST = "agent";
10
- const seatOf = (principal) => principal.seat;
11
- const guestOf = (principal) => {
12
- const found = principal;
13
- return found?.seat === "guest" ? found.guest : void 0;
14
- };
15
- const deviceOf = (principal) => principal.device;
11
+ const SELF = { seat: "host" };
16
12
  const principalKey = (principal) => {
17
- const { seat, link } = principal ?? {};
18
- const guest = guestOf(principal);
19
- if (guest) return `guest:${guest.id}:e${guest.epoch}:${link}`;
20
- return seat ? `${seat}:${link}` : "host";
13
+ if (principal.seat === "host") return "host";
14
+ if (principal.seat === "guest") {
15
+ const { guest, link } = principal;
16
+ return `guest:${guest.id}:e${guest.epoch}:${link}`;
17
+ }
18
+ return `${principal.seat}:${principal.link}`;
21
19
  };
22
20
  const Args = Type.Array(Type.Unknown());
23
21
  const Value = Type.Unknown();
@@ -25,6 +23,7 @@ function contract(name, variants) {
25
23
  const def = {
26
24
  version: 1,
27
25
  input: Type.Object({}),
26
+ host: hostNamed(AGENT_HOST),
28
27
  variants: Object.fromEntries(
29
28
  Object.entries(variants).map(([kind, members]) => [
30
29
  kind,
@@ -110,7 +109,6 @@ function replicated(member) {
110
109
  subscribe(listener) {
111
110
  let sequence = 0;
112
111
  return member.subscribe((value) => {
113
- if (value === void 0) return;
114
112
  sequence += 1;
115
113
  void listener(value, BACKGROUND_CONTEXT, {
116
114
  kind: sequence === 1 ? "hydrate" : "update",
@@ -120,16 +118,6 @@ function replicated(member) {
120
118
  }
121
119
  };
122
120
  }
123
- function kept(member) {
124
- let resolve;
125
- const ready = new Promise((done) => {
126
- resolve = done;
127
- });
128
- const stop = member.subscribe((value) => {
129
- if (value !== void 0) resolve();
130
- });
131
- return { ready, stop };
132
- }
133
121
  const CLOSED = "the connection to the agent is closed";
134
122
  function plain(error) {
135
123
  if (!isChordError(error)) return error;
@@ -166,18 +154,15 @@ function bound(handle, root, names, absent) {
166
154
  export {
167
155
  AGENT_HOST,
168
156
  CLOSED,
157
+ SELF,
169
158
  bound,
170
159
  contextOf,
171
160
  contract,
172
- deviceOf,
173
- guestOf,
174
- kept,
175
161
  plain,
176
162
  principalKey,
177
163
  readable,
178
164
  readablesOf,
179
165
  replicated,
180
- seatOf,
181
166
  served
182
167
  };
183
168
  //# sourceMappingURL=serving.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/serving.ts"],
4
- "sourcesContent": ["import {\n type Ctx,\n isChordError,\n method,\n type Principal,\n type Readable,\n type RemoteContract,\n type ReplicatedState,\n remote,\n type StateEvent,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT, type Context, withAbortSignal } from '@earendil-works/chord/context';\nimport { diffRevisions } from '@earendil-works/chord/delta';\nimport { Type } from 'typebox';\n\nexport const AGENT_HOST = 'agent';\n\nexport type Seat = 'owner' | 'control' | 'view' | 'guest';\n\nexport interface GuestPrincipal {\n id: string;\n name: string;\n epoch: number;\n}\n\nexport interface AgentPrincipal {\n seat: Seat;\n link: number;\n guest?: GuestPrincipal;\n device?: string;\n}\n\nexport const seatOf = (principal: Principal): Seat => (principal as AgentPrincipal).seat;\n\nexport const guestOf = (principal: Principal): GuestPrincipal | undefined => {\n const found = principal as Partial<AgentPrincipal> | undefined;\n return found?.seat === 'guest' ? found.guest : undefined;\n};\n\nexport const deviceOf = (principal: Principal): string | undefined =>\n (principal as AgentPrincipal).device;\n\nexport const principalKey = (principal: Principal): string => {\n const { seat, link } = (principal ?? {}) as Partial<AgentPrincipal>;\n const guest = guestOf(principal);\n if (guest) return `guest:${guest.id}:e${guest.epoch}:${link}`;\n return seat ? `${seat}:${link}` : 'host';\n};\n\nexport interface Members {\n methods?: readonly string[];\n state?: readonly string[];\n}\n\nconst Args = Type.Array(Type.Unknown());\nconst Value = Type.Unknown();\n\nexport function contract(name: string, variants: Record<string, Members>): RemoteContract {\n const def: Parameters<typeof remote>[1] = {\n version: 1,\n input: Type.Object({}),\n variants: Object.fromEntries(\n Object.entries(variants).map(([kind, members]) => [\n kind,\n {\n state: Object.fromEntries((members.state ?? []).map((member) => [member, Value])),\n methods: Object.fromEntries(\n (members.methods ?? []).map((member) => [member, method(Args, Value)])\n ),\n },\n ])\n ),\n };\n return remote(name, def);\n}\n\nexport type Callable = (...args: unknown[]) => Promise<unknown>;\n\nexport const contextOf = (ctx: Ctx): Context => withAbortSignal(ctx.signal, BACKGROUND_CONTEXT);\n\nexport function served(\n impl: () => object,\n names: readonly string[]\n): Record<string, (args: unknown[], ctx: Ctx) => Promise<unknown>> {\n return Object.fromEntries(\n names.map((name) => [\n name,\n (args: unknown[], ctx: Ctx) =>\n ((impl() as Record<string, Callable>)[name] as Callable)(...args, contextOf(ctx)),\n ])\n );\n}\n\nconst readables = new WeakMap<object, Readable<unknown>>();\n\nexport function readable<T>(state: ReplicatedState<T>): Readable<T> {\n const known = readables.get(state);\n if (known) return known as Readable<T>;\n const values = new Set<(value: T) => void>();\n const events = new Set<(event: StateEvent<T>) => void>();\n let value = state.value as T;\n let off: (() => void) | undefined;\n const start = () => {\n if (off) return;\n value = state.value as T;\n off = state.subscribe((next) => {\n const before = value;\n value = next;\n if (before === next) return;\n const event: StateEvent<T> =\n before === undefined\n ? { type: 'reset', value: next }\n : { type: 'ops', ops: diffRevisions(before as never, next as never), value: next };\n for (const listener of [...events]) listener(event);\n for (const listener of [...values]) listener(next);\n });\n };\n const stop = () => {\n if (values.size + events.size > 0 || !off) return;\n off();\n off = undefined;\n };\n const made: Readable<T> = {\n get value() {\n return off ? value : (state.value as T);\n },\n subscribe(listener) {\n values.add(listener);\n start();\n listener(value);\n return () => {\n values.delete(listener);\n stop();\n };\n },\n events(listener) {\n events.add(listener);\n start();\n listener({ type: 'snap', value });\n return () => {\n events.delete(listener);\n stop();\n };\n },\n };\n readables.set(state, made);\n return made;\n}\n\nexport function readablesOf(\n states: Record<string, ReplicatedState<unknown>>\n): Record<string, Readable<unknown>> {\n return Object.fromEntries(Object.entries(states).map(([name, state]) => [name, readable(state)]));\n}\n\nexport interface Remote {\n readonly kind: string | undefined;\n readonly ready: Promise<void>;\n release(): void;\n [member: string]: unknown;\n}\n\nexport function replicated<T>(member: Readable<T | undefined>): ReplicatedState<T> {\n return {\n get value() {\n return member.value;\n },\n subscribe(listener: (value: T, context: Context, delivery: never) => unknown) {\n let sequence = 0;\n return member.subscribe((value) => {\n if (value === undefined) return;\n sequence += 1;\n void listener(value, BACKGROUND_CONTEXT, {\n kind: sequence === 1 ? 'hydrate' : 'update',\n sequence,\n } as never);\n });\n },\n } as ReplicatedState<T>;\n}\n\nexport function kept(member: Readable<unknown>): { ready: Promise<void>; stop(): void } {\n let resolve!: () => void;\n const ready = new Promise<void>((done) => {\n resolve = done;\n });\n const stop = member.subscribe((value) => {\n if (value !== undefined) resolve();\n });\n return { ready, stop };\n}\n\nexport const CLOSED = 'the connection to the agent is closed';\n\nexport function plain(error: unknown): unknown {\n if (!isChordError(error)) return error;\n if (error.code === 'released') return Object.assign(new Error(CLOSED), { code: 'released' });\n const prefix = error.reason ? `${error.code}/${error.reason}: ` : `${error.code}: `;\n const message = error.message.startsWith(prefix)\n ? error.message.slice(prefix.length)\n : error.message;\n return Object.assign(new Error(message), { code: error.code });\n}\n\nconst isContext = (value: unknown): value is Context =>\n typeof value === 'object' &&\n value !== null &&\n 'abortSignal' in value &&\n typeof (value as Context).value === 'function';\n\nexport type Root = <R>(\n run: (ctx: Ctx) => Promise<R>,\n options: { signal?: AbortSignal }\n) => Promise<R>;\n\nexport function bound<T extends object>(\n handle: Remote,\n root: Root,\n names: readonly string[],\n absent: (name: string) => Callable\n): T {\n const shape = (handle as { shape?: { members: readonly string[] } }).shape;\n const members = new Set(shape?.members ?? []);\n return Object.fromEntries(\n names.map((name) => {\n if (!members.has(name)) return [name, absent(name)];\n const call = handle[name] as (args: unknown[], ctx: Ctx) => Promise<unknown>;\n return [\n name,\n async (...given: unknown[]) => {\n const last = given.at(-1);\n const context = isContext(last) ? last : undefined;\n const args = context ? given.slice(0, -1) : given;\n const signal = context?.abortSignal;\n try {\n return await root((ctx) => call(args, ctx), signal ? { signal } : {});\n } catch (error) {\n throw plain(error);\n }\n },\n ];\n })\n ) as T;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type Ctx,\n hostNamed,\n isChordError,\n method,\n type Readable,\n type RemoteContract,\n type ReplicatedState,\n remote,\n type StateEvent,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT, type Context, withAbortSignal } from '@earendil-works/chord/context';\nimport { diffRevisions } from '@earendil-works/chord/delta';\nimport { Type } from 'typebox';\n\nexport const AGENT_HOST = 'agent';\n\nexport type Seat = 'owner' | 'control' | 'view' | 'guest';\n\nexport interface GuestPrincipal {\n id: string;\n name: string;\n epoch: number;\n}\n\nexport type AgentPrincipal =\n | { seat: 'owner' | 'control' | 'view'; link: number; device?: string }\n | { seat: 'guest'; link: number; guest: GuestPrincipal }\n | { seat: 'host' };\n\nexport const SELF: AgentPrincipal = { seat: 'host' };\n\nexport const principalKey = (principal: AgentPrincipal): string => {\n if (principal.seat === 'host') return 'host';\n if (principal.seat === 'guest') {\n const { guest, link } = principal;\n return `guest:${guest.id}:e${guest.epoch}:${link}`;\n }\n return `${principal.seat}:${principal.link}`;\n};\n\nexport interface Members {\n methods?: readonly string[];\n state?: readonly string[];\n}\n\nconst Args = Type.Array(Type.Unknown());\nconst Value = Type.Unknown();\n\nexport function contract(name: string, variants: Record<string, Members>): RemoteContract {\n const def: Parameters<typeof remote>[1] = {\n version: 1,\n input: Type.Object({}),\n host: hostNamed(AGENT_HOST),\n variants: Object.fromEntries(\n Object.entries(variants).map(([kind, members]) => [\n kind,\n {\n state: Object.fromEntries((members.state ?? []).map((member) => [member, Value])),\n methods: Object.fromEntries(\n (members.methods ?? []).map((member) => [member, method(Args, Value)])\n ),\n },\n ])\n ),\n };\n return remote(name, def);\n}\n\nexport type Callable = (...args: unknown[]) => Promise<unknown>;\n\nexport const contextOf = (ctx: Ctx): Context => withAbortSignal(ctx.signal, BACKGROUND_CONTEXT);\n\nexport function served(\n impl: () => object,\n names: readonly string[]\n): Record<string, (args: unknown[], ctx: Ctx) => Promise<unknown>> {\n return Object.fromEntries(\n names.map((name) => [\n name,\n (args: unknown[], ctx: Ctx) =>\n ((impl() as Record<string, Callable>)[name] as Callable)(...args, contextOf(ctx)),\n ])\n );\n}\n\nconst readables = new WeakMap<object, Readable<unknown>>();\n\nexport function readable<T>(state: ReplicatedState<T>): Readable<T> {\n const known = readables.get(state);\n if (known) return known as Readable<T>;\n const values = new Set<(value: T) => void>();\n const events = new Set<(event: StateEvent<T>) => void>();\n let value = state.value as T;\n let off: (() => void) | undefined;\n const start = () => {\n if (off) return;\n value = state.value as T;\n off = state.subscribe((next) => {\n const before = value;\n value = next;\n if (before === next) return;\n const event: StateEvent<T> =\n before === undefined\n ? { type: 'reset', value: next }\n : { type: 'ops', ops: diffRevisions(before as never, next as never), value: next };\n for (const listener of [...events]) listener(event);\n for (const listener of [...values]) listener(next);\n });\n };\n const stop = () => {\n if (values.size + events.size > 0 || !off) return;\n off();\n off = undefined;\n };\n const made: Readable<T> = {\n get value() {\n return off ? value : (state.value as T);\n },\n subscribe(listener) {\n values.add(listener);\n start();\n listener(value);\n return () => {\n values.delete(listener);\n stop();\n };\n },\n events(listener) {\n events.add(listener);\n start();\n listener({ type: 'snap', value });\n return () => {\n events.delete(listener);\n stop();\n };\n },\n };\n readables.set(state, made);\n return made;\n}\n\nexport function readablesOf(\n states: Record<string, ReplicatedState<unknown>>\n): Record<string, Readable<unknown>> {\n return Object.fromEntries(Object.entries(states).map(([name, state]) => [name, readable(state)]));\n}\n\nexport interface Remote {\n readonly variant: string | undefined;\n readonly ready: Promise<void>;\n release(): void;\n [member: string]: unknown;\n}\n\nexport function replicated<T>(member: Readable<T>): ReplicatedState<T> {\n return {\n get value() {\n return member.value;\n },\n subscribe(listener: (value: T, context: Context, delivery: never) => unknown) {\n let sequence = 0;\n return member.subscribe((value) => {\n sequence += 1;\n void listener(value, BACKGROUND_CONTEXT, {\n kind: sequence === 1 ? 'hydrate' : 'update',\n sequence,\n } as never);\n });\n },\n } as ReplicatedState<T>;\n}\n\nexport const CLOSED = 'the connection to the agent is closed';\n\nexport function plain(error: unknown): unknown {\n if (!isChordError(error)) return error;\n if (error.code === 'released') return Object.assign(new Error(CLOSED), { code: 'released' });\n const prefix = error.reason ? `${error.code}/${error.reason}: ` : `${error.code}: `;\n const message = error.message.startsWith(prefix)\n ? error.message.slice(prefix.length)\n : error.message;\n return Object.assign(new Error(message), { code: error.code });\n}\n\nconst isContext = (value: unknown): value is Context =>\n typeof value === 'object' &&\n value !== null &&\n 'abortSignal' in value &&\n typeof (value as Context).value === 'function';\n\nexport type Root = <R>(\n run: (ctx: Ctx) => Promise<R>,\n options: { signal?: AbortSignal }\n) => Promise<R>;\n\nexport function bound<T extends object>(\n handle: Remote,\n root: Root,\n names: readonly string[],\n absent: (name: string) => Callable\n): T {\n const shape = (handle as { shape?: { members: readonly string[] } }).shape;\n const members = new Set(shape?.members ?? []);\n return Object.fromEntries(\n names.map((name) => {\n if (!members.has(name)) return [name, absent(name)];\n const call = handle[name] as (args: unknown[], ctx: Ctx) => Promise<unknown>;\n return [\n name,\n async (...given: unknown[]) => {\n const last = given.at(-1);\n const context = isContext(last) ? last : undefined;\n const args = context ? given.slice(0, -1) : given;\n const signal = context?.abortSignal;\n try {\n return await root((ctx) => call(args, ctx), signal ? { signal } : {});\n } catch (error) {\n throw plain(error);\n }\n },\n ];\n })\n ) as T;\n}\n"],
5
+ "mappings": "AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,OAEK;AACP,SAAS,oBAAkC,uBAAuB;AAClE,SAAS,qBAAqB;AAC9B,SAAS,YAAY;AAEd,MAAM,aAAa;AAenB,MAAM,OAAuB,EAAE,MAAM,OAAO;AAE5C,MAAM,eAAe,CAAC,cAAsC;AACjE,MAAI,UAAU,SAAS,OAAQ,QAAO;AACtC,MAAI,UAAU,SAAS,SAAS;AAC9B,UAAM,EAAE,OAAO,KAAK,IAAI;AACxB,WAAO,SAAS,MAAM,EAAE,KAAK,MAAM,KAAK,IAAI,IAAI;AAAA,EAClD;AACA,SAAO,GAAG,UAAU,IAAI,IAAI,UAAU,IAAI;AAC5C;AAOA,MAAM,OAAO,KAAK,MAAM,KAAK,QAAQ,CAAC;AACtC,MAAM,QAAQ,KAAK,QAAQ;AAEpB,SAAS,SAAS,MAAc,UAAmD;AACxF,QAAM,MAAoC;AAAA,IACxC,SAAS;AAAA,IACT,OAAO,KAAK,OAAO,CAAC,CAAC;AAAA,IACrB,MAAM,UAAU,UAAU;AAAA,IAC1B,UAAU,OAAO;AAAA,MACf,OAAO,QAAQ,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM;AAAA,QAChD;AAAA,QACA;AAAA,UACE,OAAO,OAAO,aAAa,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,KAAK,CAAC,CAAC;AAAA,UAChF,SAAS,OAAO;AAAA,aACb,QAAQ,WAAW,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,OAAO,MAAM,KAAK,CAAC,CAAC;AAAA,UACvE;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,OAAO,MAAM,GAAG;AACzB;AAIO,MAAM,YAAY,CAAC,QAAsB,gBAAgB,IAAI,QAAQ,kBAAkB;AAEvF,SAAS,OACd,MACA,OACiE;AACjE,SAAO,OAAO;AAAA,IACZ,MAAM,IAAI,CAAC,SAAS;AAAA,MAClB;AAAA,MACA,CAAC,MAAiB,QACd,KAAK,EAA+B,IAAI,EAAe,GAAG,MAAM,UAAU,GAAG,CAAC;AAAA,IACpF,CAAC;AAAA,EACH;AACF;AAEA,MAAM,YAAY,oBAAI,QAAmC;AAElD,SAAS,SAAY,OAAwC;AAClE,QAAM,QAAQ,UAAU,IAAI,KAAK;AACjC,MAAI,MAAO,QAAO;AAClB,QAAM,SAAS,oBAAI,IAAwB;AAC3C,QAAM,SAAS,oBAAI,IAAoC;AACvD,MAAI,QAAQ,MAAM;AAClB,MAAI;AACJ,QAAM,QAAQ,MAAM;AAClB,QAAI,IAAK;AACT,YAAQ,MAAM;AACd,UAAM,MAAM,UAAU,CAAC,SAAS;AAC9B,YAAM,SAAS;AACf,cAAQ;AACR,UAAI,WAAW,KAAM;AACrB,YAAM,QACJ,WAAW,SACP,EAAE,MAAM,SAAS,OAAO,KAAK,IAC7B,EAAE,MAAM,OAAO,KAAK,cAAc,QAAiB,IAAa,GAAG,OAAO,KAAK;AACrF,iBAAW,YAAY,CAAC,GAAG,MAAM,EAAG,UAAS,KAAK;AAClD,iBAAW,YAAY,CAAC,GAAG,MAAM,EAAG,UAAS,IAAI;AAAA,IACnD,CAAC;AAAA,EACH;AACA,QAAM,OAAO,MAAM;AACjB,QAAI,OAAO,OAAO,OAAO,OAAO,KAAK,CAAC,IAAK;AAC3C,QAAI;AACJ,UAAM;AAAA,EACR;AACA,QAAM,OAAoB;AAAA,IACxB,IAAI,QAAQ;AACV,aAAO,MAAM,QAAS,MAAM;AAAA,IAC9B;AAAA,IACA,UAAU,UAAU;AAClB,aAAO,IAAI,QAAQ;AACnB,YAAM;AACN,eAAS,KAAK;AACd,aAAO,MAAM;AACX,eAAO,OAAO,QAAQ;AACtB,aAAK;AAAA,MACP;AAAA,IACF;AAAA,IACA,OAAO,UAAU;AACf,aAAO,IAAI,QAAQ;AACnB,YAAM;AACN,eAAS,EAAE,MAAM,QAAQ,MAAM,CAAC;AAChC,aAAO,MAAM;AACX,eAAO,OAAO,QAAQ;AACtB,aAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACA,YAAU,IAAI,OAAO,IAAI;AACzB,SAAO;AACT;AAEO,SAAS,YACd,QACmC;AACnC,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,CAAC,CAAC;AAClG;AASO,SAAS,WAAc,QAAyC;AACrE,SAAO;AAAA,IACL,IAAI,QAAQ;AACV,aAAO,OAAO;AAAA,IAChB;AAAA,IACA,UAAU,UAAoE;AAC5E,UAAI,WAAW;AACf,aAAO,OAAO,UAAU,CAAC,UAAU;AACjC,oBAAY;AACZ,aAAK,SAAS,OAAO,oBAAoB;AAAA,UACvC,MAAM,aAAa,IAAI,YAAY;AAAA,UACnC;AAAA,QACF,CAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,MAAM,SAAS;AAEf,SAAS,MAAM,OAAyB;AAC7C,MAAI,CAAC,aAAa,KAAK,EAAG,QAAO;AACjC,MAAI,MAAM,SAAS,WAAY,QAAO,OAAO,OAAO,IAAI,MAAM,MAAM,GAAG,EAAE,MAAM,WAAW,CAAC;AAC3F,QAAM,SAAS,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,MAAM,MAAM,OAAO,GAAG,MAAM,IAAI;AAC/E,QAAM,UAAU,MAAM,QAAQ,WAAW,MAAM,IAC3C,MAAM,QAAQ,MAAM,OAAO,MAAM,IACjC,MAAM;AACV,SAAO,OAAO,OAAO,IAAI,MAAM,OAAO,GAAG,EAAE,MAAM,MAAM,KAAK,CAAC;AAC/D;AAEA,MAAM,YAAY,CAAC,UACjB,OAAO,UAAU,YACjB,UAAU,QACV,iBAAiB,SACjB,OAAQ,MAAkB,UAAU;AAO/B,SAAS,MACd,QACA,MACA,OACA,QACG;AACH,QAAM,QAAS,OAAsD;AACrE,QAAM,UAAU,IAAI,IAAI,OAAO,WAAW,CAAC,CAAC;AAC5C,SAAO,OAAO;AAAA,IACZ,MAAM,IAAI,CAAC,SAAS;AAClB,UAAI,CAAC,QAAQ,IAAI,IAAI,EAAG,QAAO,CAAC,MAAM,OAAO,IAAI,CAAC;AAClD,YAAM,OAAO,OAAO,IAAI;AACxB,aAAO;AAAA,QACL;AAAA,QACA,UAAU,UAAqB;AAC7B,gBAAM,OAAO,MAAM,GAAG,EAAE;AACxB,gBAAM,UAAU,UAAU,IAAI,IAAI,OAAO;AACzC,gBAAM,OAAO,UAAU,MAAM,MAAM,GAAG,EAAE,IAAI;AAC5C,gBAAM,SAAS,SAAS;AACxB,cAAI;AACF,mBAAO,MAAM,KAAK,CAAC,QAAQ,KAAK,MAAM,GAAG,GAAG,SAAS,EAAE,OAAO,IAAI,CAAC,CAAC;AAAA,UACtE,SAAS,OAAO;AACd,kBAAM,MAAM,KAAK;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- import { type Context, type ReplicatedState } from '@earendil-works/chord';
1
+ import { type Context, type Host, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
3
  import type { ApprovalPolicy } from './approvals/policy.ts';
4
4
  import type { Approval } from './approvals/record.ts';
@@ -10,8 +10,9 @@ import type { AgentRemote } from './remote/host.ts';
10
10
  import type { AgentPages } from './remote/pages.ts';
11
11
  import type { VaultState } from './secrets/vault.ts';
12
12
  import { AgentControl, AgentSettings, type AgentsSummary, type Command, type Delivered, type GuestProposal, type GuestShown, type MonitorFeed, type PrivateRevision, type SendMode } from './services.ts';
13
+ import { type AgentPrincipal, type Remote } from './serving.ts';
13
14
  import type { Sprinkle } from './sprinkles/kind.ts';
14
- import { type PortEndpoint } from './wire.ts';
15
+ import { type PortEndpoint, PortLink } from './wire.ts';
15
16
  export interface AgentConnection {
16
17
  readonly serverId: string;
17
18
  readonly control: AgentControl;
@@ -56,8 +57,12 @@ export interface Lasting<T> {
56
57
  freeze(): void;
57
58
  }
58
59
  export declare function lasting<T>(state: ReplicatedState<T>): Lasting<T>;
59
- export declare const OTHER_VERSION = "That SLICC runs another version of the agent, so this tab can't follow it. Update both SLICCs, then reload this page.";
60
60
  export declare const final: (error: unknown) => unknown;
61
+ export declare const ended: (link: PortLink) => Promise<never>;
62
+ type Contract = Parameters<Host<AgentPrincipal>['get']>[0];
63
+ export declare function clientHost(link: PortLink, name: string): Host<AgentPrincipal>;
64
+ export declare function holding(host: Host<AgentPrincipal>, link: PortLink, contracts: readonly Contract[]): Promise<Remote[]>;
61
65
  export declare function connectAgent(endpoint: PortEndpoint, options?: {
62
66
  context?: Context;
63
67
  }): Promise<AgentConnection>;
68
+ export {};
@@ -2,10 +2,11 @@ import type { Context, Host, ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView } from '@earendil-works/pi-durable';
3
3
  import type { Agents } from '../agents.ts';
4
4
  import type { AgentGuest, GuestProposal } from '../services.ts';
5
- import type { GuestPrincipal } from '../serving.ts';
5
+ import type { AgentPrincipal, GuestPrincipal } from '../serving.ts';
6
6
  import { type PortEndpoint } from '../wire.ts';
7
7
  import type { Guests } from './index.ts';
8
8
  import type { ReviewsState } from './review.ts';
9
+ export declare const GUEST_CALLS = 4;
9
10
  export declare function proposalsOf(state: ReviewsState | null | undefined, seat: string): GuestProposal[];
10
11
  export declare function guestOpener(guests: Guests, agents: Pick<Agents, 'state'>, views: ReplicatedState<Record<string, ConversationView>>, context: Context): (principal: GuestPrincipal) => {
11
12
  value: AgentGuest;
@@ -14,4 +15,4 @@ export declare function guestOpener(guests: Guests, agents: Pick<Agents, 'state'
14
15
  export declare function admitGuest(guests: Guests, endpoint: PortEndpoint, asked: {
15
16
  id: string;
16
17
  label: string;
17
- }, serverId: string, link: number, host: Pick<Host, 'accept'>): void;
18
+ }, serverId: string, link: number, host: Pick<Host<AgentPrincipal>, 'accept'>): void;