@ai-ecoverse/slicc-agent 3.34.0 → 3.35.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/README.md CHANGED
@@ -65,6 +65,23 @@ const agent = await openAgent({ models, model, storage, registry, env: kernelEnv
65
65
 
66
66
  A conversation without a `cwd` works in `/home`.
67
67
 
68
+ **Kernel users.** A `KernelSource` may also have `users` (`add`, `remove`, `list`, as `kernel.users`), and its `connect` takes `{ user, agentId }` for a client bound to that user. The page builds the kernel's `connect({ user, tag })` from them, and so decides what the tag looks like. With `users`, the worker gets a second port next to the kernel's, for these calls (`kernelPorts(self)` resolves `{ kernel, admin? }`), and the `AgentHost` has `users`, a pool of one bound client per agent (`userClients`), which the agent doesn't use for conversations yet. Without `users` (or with `runAgentWorker(self, { users: false })`), nothing changes:
69
+
70
+ ```js
71
+ const owner = await startAgent({
72
+ worker,
73
+ kernel: {
74
+ connect: (options) =>
75
+ options?.user
76
+ ? kernel.connect({ user: options.user, tag: JSON.stringify({ kind: 'agent', agentId: options.agentId }) })
77
+ : kernel.connect(),
78
+ users: kernel.users,
79
+ },
80
+ });
81
+ ```
82
+
83
+ At boot, the worker sets `/.slicc`, where the session database lives in OPFS, to `0700`, so that only root can read it through the kernel.
84
+
68
85
  ### The worker seven starts
69
86
 
70
87
  `@ai-ecoverse/slicc-agent/agent-worker` is a complete agent worker. It waits for the page kernel's port, then:
@@ -165,7 +182,7 @@ A **cone** is a top-level agent the user talks to; a **scoop** is a helper agent
165
182
 
166
183
  Each scoop is owned by a background durable task, its **anchor**, so Stop in its cone doesn't end it; `agent stop` and Drop do. They keep its transcript in durable storage and its reports in `/scoops/<handle>/reports/`, which report licks point at, and remove its working folder `/scoops/<handle>/workspace`. Each request handed to a scoop gets a **reporter** task that waits for the run, writes the answer to `/scoops/<handle>/reports/<task id>.md` and reports it to whoever asked. Requests from a cone's or a scoop's bash report into that agent's `pi.inbox` as a lick, through the licks outbox, so they steer and coalesce like any lick; requests from a terminal report nowhere, and a user typing in a scoop's chat gets the answer there. In a scoop's chat, a request someone else sent shows who sent it (`UserMessage.from`): the asking cone's or scoop's name, with `origin: 'agent'` so spectrum (≥ 1.26.0) shows it as that agent's request with an "Agent" badge, or `terminal` without an origin. Once the request is placed, the reporter appends a `slicc.from` entry (`{ from, entry }`) without model messages, and the adapter sets `from` on that entry's message. A request withdrawn before it was placed leaves no entry. The report lick's text is `[scoop <name> (<role>) <status>]`, and its body has the report's path and line count and a 1,000-character preview. A scoop's prompt has a `scoop` section with its name, its cone, its folders and its limits. The `agent` command is taught by the built-in `agent` skill (below), whose description says that roles exist and that `agent list --agents` lists them.
167
184
 
168
- **The `agent` command.** One bash script is installed as `agent` and `subagent` in the kernel's `$PNPM_HOME/bin` (the worker asks the kernel for `PNPM_HOME`: `/home/.local/share/pnpm` before kernel users, root's `/usr/local/share/pnpm`, whose commands every user finds, from kernel 1.47.1), so the user, a cone or a scoop runs it in any bash. It writes a request (NUL-separated fields: `slicc-agent/1`, the name it was called by, `$SLICC_AGENT`, the working directory, its pid, argc, the arguments and stdin) to `/var/lib/slicc/agent/requests/in/` and polls `out/` for the answer and exit code; the worker writes `<id>.ack` when it picks a request up, and the script gives up after 20 s without one ("the SLICC agent isn't running", exit 1). The kernel environment exports `SLICC_AGENT`, `PI_PROVIDER`, `PI_MODEL` and `PI_REASONING_LEVEL` into every agent command, so the worker knows the caller. `/var/lib/slicc/agent/scoops/<handle>/metadata.json` mirrors each scoop's state for scripts.
185
+ **The `agent` command.** One bash script is installed as `agent` and `subagent` (and as `sprinkle`, `memory`, `gelatiere` and `freezer`) in `/usr/local/bin`, mode `0755`, which is on every user's `PATH`, so the user, a cone or a scoop runs it in any bash. Root's `$PNPM_HOME/bin` (`/usr/local/share/pnpm/bin`) is on root's `PATH` only: other users find root's installed packages in `/usr/bin`, but not loose scripts. Copies that earlier versions put in the kernel's `$PNPM_HOME/bin` are removed, so they can't shadow the new ones for root. It writes a request (NUL-separated fields: `slicc-agent/1`, the name it was called by, `$SLICC_AGENT`, the working directory, its pid, argc, the arguments and stdin) to `/var/lib/slicc/agent/requests/in/` and polls `out/` for the answer and exit code; the worker writes `<id>.ack` when it picks a request up, and the script gives up after 20 s without one ("the SLICC agent isn't running", exit 1). The kernel environment exports `SLICC_AGENT`, `PI_PROVIDER`, `PI_MODEL` and `PI_REASONING_LEVEL` into every agent command, so the worker knows the caller. `/var/lib/slicc/agent/scoops/<handle>/metadata.json` mirrors each scoop's state for scripts.
169
186
  - `agent [options] --prompt <text>` (or `--file <path>`, or `-` for stdin, or v6's `agent <cwd> <allowed-commands> <prompt>`) is **synchronous**: an ephemeral scoop runs, and the command prints its final answer and exits 0, or prints the reason on stderr and exits 1. Afterwards the scoop is stopped, its folder removed, its conversation marked dropped and its transcript archived as Markdown in `/tmp/agent-sessions/<handle>.md` (`/home/sessions/` with `--persist-session`, nowhere with `--no-persist-session`). The script traps TERM, INT and HUP and cancels the scoop, and the worker checks the script's pid in the kernel's process table every second for a SIGKILL. If the caller's run is still going when the bash call dies (a bash timeout), the scoop continues and its answer arrives as a `bash` lick; `--background-after <seconds>` does the same on purpose. Sync calls nest up to three deep. Allowed commands in v6's form are told to the scoop, not enforced.
170
187
  - `agent --async …` (= `subagent spawn …`) starts a persistent scoop and prints its handle; only cones start them. `list [--agents]`, `status`, `rename`, `send [--follow-up]`, `wait [--timeout <s>] [--notify]` (30 s by default; `--notify` returns at once and brings the answers together in one `scoop-wait` lick) and `stop` manage them. From a scoop, `agent send parent "<note>"` posts a progress note to its cone as a lick, coalesced per scoop.
171
188
  - Options: `--name`, `--agent <role>`, `--model <provider/model>`, `--thinking <level>` or `--effort low|medium|high|max`, `--tools <a,b>` (or `auto`/`full`), `--read-only <paths>`, `--system-prompt[-file]`. `--schema-b64`, `--tools output`, `--session`, `--resume`, `--image`, `--no-escalate`, `--minimal` and `--usage` answer "not supported in SLICC yet".
package/dist/host.js CHANGED
@@ -169,6 +169,7 @@ async function hostAgent(agent, options = {}) {
169
169
  return {
170
170
  serverId,
171
171
  agent,
172
+ ...options.users ? { users: options.users } : {},
172
173
  connect: (endpoint, connectOptions) => (connectOptions?.readOnly ? view : full).listener.connect(endpoint),
173
174
  async close() {
174
175
  await full.server.close();
@@ -189,6 +190,7 @@ async function hostAgent(agent, options = {}) {
189
190
  await options.scoops?.runtime.close(context);
190
191
  await options.licks?.sources.close(context);
191
192
  await agent.close();
193
+ await options.users?.close();
192
194
  }
193
195
  };
194
196
  }
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 createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport {\n type RoutedServerServiceHost,\n type RoutedSessionAttachment,\n type RoutedSessionHandle,\n Server,\n type ServerHost,\n SessionNotFoundError,\n} from '@earendil-works/pi-server';\nimport type { Agent } from './agent.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 { PortListener } from './listener.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { viewControl, viewRemote, viewSettings } from './readonly.ts';\nimport { createRemote } from './remote/host.ts';\nimport {\n AGENT_SESSION,\n AgentControl,\n AgentRemoteService,\n AgentSessions,\n AgentSettings,\n AgentTranscript,\n type Command,\n} from './services.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { agentViews } from './views.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n connect(endpoint: PortEndpoint, options?: { readOnly?: boolean }): void;\n close(): Promise<void>;\n}\n\nfunction endpointFor(provider: RemoteServiceProvider): RoutedSessionAttachment {\n const endpoint = createRemoteServiceEndpoint(provider);\n return {\n invokeService: (call, publish, context) =>\n endpoint.invoke(call, (id, update) => publish(id, update, context), context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction sessionServices(provider: RemoteServiceProvider): RoutedSessionHandle {\n return {\n attachClient: () => endpointFor(provider),\n close: async () => {},\n };\n}\n\nfunction serverServices(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: AgentSessions, mode: 'singleton' }]);\n provider.provide(AgentSessions, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n const attachment = endpointFor(provider);\n return {\n invokeService: attachment.invokeService,\n release(context) {\n attachment.release(context);\n provider.dispose();\n },\n };\n },\n };\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};\n\nasync function follow(agent: Agent, context: Context) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(attached.value);\n const mirror = (value: ConversationView, from: Context) => state.replace(from, 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, next.value);\n off = next.subscribe(mirror);\n });\n return {\n state,\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\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 } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n const transcript = await follow(agent, context);\n const { state } = transcript;\n const mounted = await agentViews(agent, context);\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const provider = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n { service: AgentRemoteService, mode: 'singleton' },\n ]);\n const deliveries = trackDeliveries(agent.harness, state, context);\n const control = 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 );\n provider.provide(AgentControl, control);\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\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 provider.provide(AgentRemoteService, remote);\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 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 };\n provider.provide(AgentTranscript, transcriptService);\n const settings = options.settings ?? noSettings;\n provider.provide(AgentSettings, settings);\n const viewer = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n { service: AgentRemoteService, mode: 'singleton' },\n ]);\n viewer.provide(AgentControl, viewControl(control));\n viewer.provide(AgentTranscript, transcriptService);\n viewer.provide(AgentSettings, viewSettings(settings));\n viewer.provide(AgentRemoteService, viewRemote(remote));\n const serve = async (id: string, services: RemoteServiceProvider) => {\n const host: ServerHost = {\n serverServices: serverServices(),\n async resolveSession(sessionId) {\n if (sessionId !== AGENT_SESSION)\n throw new SessionNotFoundError(`unknown session ${sessionId}`);\n return { id: sessionId };\n },\n openSession: async () => sessionServices(services),\n };\n const listener = new PortListener(id);\n const server = await new Server(host, { serverId: id, listeners: [listener] }).start();\n return { listener, server };\n };\n const full = await serve(serverId, provider);\n const view = await serve(crypto.randomUUID(), viewer);\n return {\n serverId,\n agent,\n connect: (endpoint, connectOptions) =>\n (connectOptions?.readOnly ? view : full).listener.connect(endpoint),\n async close() {\n await full.server.close();\n await view.server.close();\n viewer.dispose();\n await remote.dispose();\n provider.dispose();\n deliveries.dispose();\n transcript.dispose();\n mounted.dispose();\n for (const off of untouch) off();\n options.freezer?.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 },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type Context,\n createRemoteServiceEndpoint,\n RemoteServiceProvider,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport {\n type RoutedServerServiceHost,\n type RoutedSessionAttachment,\n type RoutedSessionHandle,\n Server,\n type ServerHost,\n SessionNotFoundError,\n} from '@earendil-works/pi-server';\nimport type { Agent } from './agent.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 type { UserClients } from './kernel/users.ts';\nimport { PortListener } from './listener.ts';\nimport type { McpRuntime } from './mcp/index.ts';\nimport type { MemoryEntry, MemoryScope } from './memory/format.ts';\nimport type { MemoryRuntime } from './memory/index.ts';\nimport { viewControl, viewRemote, viewSettings } from './readonly.ts';\nimport { createRemote } from './remote/host.ts';\nimport {\n AGENT_SESSION,\n AgentControl,\n AgentRemoteService,\n AgentSessions,\n AgentSettings,\n AgentTranscript,\n type Command,\n} from './services.ts';\nimport type { SkillsRuntime } from './skills/index.ts';\nimport type { SprinklesRuntime } from './sprinkles/index.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\nimport { agentViews } from './views.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface AgentHost {\n readonly serverId: string;\n readonly agent: Agent;\n readonly users?: UserClients;\n connect(endpoint: PortEndpoint, options?: { readOnly?: boolean }): void;\n close(): Promise<void>;\n}\n\nfunction endpointFor(provider: RemoteServiceProvider): RoutedSessionAttachment {\n const endpoint = createRemoteServiceEndpoint(provider);\n return {\n invokeService: (call, publish, context) =>\n endpoint.invoke(call, (id, update) => publish(id, update, context), context),\n release: () => endpoint.dispose(),\n };\n}\n\nfunction sessionServices(provider: RemoteServiceProvider): RoutedSessionHandle {\n return {\n attachClient: () => endpointFor(provider),\n close: async () => {},\n };\n}\n\nfunction serverServices(): RoutedServerServiceHost {\n return {\n attachClient(presentation) {\n const provider = new RemoteServiceProvider([{ service: AgentSessions, mode: 'singleton' }]);\n provider.provide(AgentSessions, {\n attach: (sessionId, context) => presentation.attachSession(sessionId, context),\n detach: (context) => presentation.detachSession(context),\n });\n const attachment = endpointFor(provider);\n return {\n invokeService: attachment.invokeService,\n release(context) {\n attachment.release(context);\n provider.dispose();\n },\n };\n },\n };\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};\n\nasync function follow(agent: Agent, context: Context) {\n let attached = await agent.cone().viewState(context);\n const state = replicatedState<ConversationView>(attached.value);\n const mirror = (value: ConversationView, from: Context) => state.replace(from, 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, next.value);\n off = next.subscribe(mirror);\n });\n return {\n state,\n dispose() {\n stop();\n off();\n attached.dispose();\n },\n };\n}\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 } = {}\n): Promise<AgentHost> {\n const context = options.context ?? BACKGROUND_CONTEXT;\n const serverId = options.serverId ?? crypto.randomUUID();\n const transcript = await follow(agent, context);\n const { state } = transcript;\n const mounted = await agentViews(agent, context);\n const touch = () => options.freezer?.touch();\n const untouch = [state.subscribe(touch), mounted.views.subscribe(touch)];\n const provider = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n { service: AgentRemoteService, mode: 'singleton' },\n ]);\n const deliveries = trackDeliveries(agent.harness, state, context);\n const control = 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 );\n provider.provide(AgentControl, control);\n const remote = createRemote({\n harness: agent.harness,\n send: (request, using) => control.send(request, using),\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 provider.provide(AgentRemoteService, remote);\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 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 };\n provider.provide(AgentTranscript, transcriptService);\n const settings = options.settings ?? noSettings;\n provider.provide(AgentSettings, settings);\n const viewer = new RemoteServiceProvider([\n { service: AgentControl, mode: 'singleton' },\n { service: AgentTranscript, mode: 'singleton' },\n { service: AgentSettings, mode: 'singleton' },\n { service: AgentRemoteService, mode: 'singleton' },\n ]);\n viewer.provide(AgentControl, viewControl(control));\n viewer.provide(AgentTranscript, transcriptService);\n viewer.provide(AgentSettings, viewSettings(settings));\n viewer.provide(AgentRemoteService, viewRemote(remote));\n const serve = async (id: string, services: RemoteServiceProvider) => {\n const host: ServerHost = {\n serverServices: serverServices(),\n async resolveSession(sessionId) {\n if (sessionId !== AGENT_SESSION)\n throw new SessionNotFoundError(`unknown session ${sessionId}`);\n return { id: sessionId };\n },\n openSession: async () => sessionServices(services),\n };\n const listener = new PortListener(id);\n const server = await new Server(host, { serverId: id, listeners: [listener] }).start();\n return { listener, server };\n };\n const full = await serve(serverId, provider);\n const view = await serve(crypto.randomUUID(), viewer);\n return {\n serverId,\n agent,\n ...(options.users ? { users: options.users } : {}),\n connect: (endpoint, connectOptions) =>\n (connectOptions?.readOnly ? view : full).listener.connect(endpoint),\n async close() {\n await full.server.close();\n await view.server.close();\n viewer.dispose();\n await remote.dispose();\n provider.dispose();\n deliveries.dispose();\n transcript.dispose();\n mounted.dispose();\n for (const off of untouch) off();\n options.freezer?.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"],
5
+ "mappings": "AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0BAA0B;AAEnC;AAAA,EAIE;AAAA,EAEA;AAAA,OACK;AAIP,SAAS,0BAA2D;AACpE,SAAS,uBAAuB;AAGhC,SAAS,oBAAoB;AAI7B,SAAS,aAAa,YAAY,oBAAoB;AACtD,SAAS,oBAAoB;AAC7B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAIP,SAAS,kBAAkB;AAW3B,SAAS,YAAY,UAA0D;AAC7E,QAAM,WAAW,4BAA4B,QAAQ;AACrD,SAAO;AAAA,IACL,eAAe,CAAC,MAAM,SAAS,YAC7B,SAAS,OAAO,MAAM,CAAC,IAAI,WAAW,QAAQ,IAAI,QAAQ,OAAO,GAAG,OAAO;AAAA,IAC7E,SAAS,MAAM,SAAS,QAAQ;AAAA,EAClC;AACF;AAEA,SAAS,gBAAgB,UAAsD;AAC7E,SAAO;AAAA,IACL,cAAc,MAAM,YAAY,QAAQ;AAAA,IACxC,OAAO,YAAY;AAAA,IAAC;AAAA,EACtB;AACF;AAEA,SAAS,iBAA0C;AACjD,SAAO;AAAA,IACL,aAAa,cAAc;AACzB,YAAM,WAAW,IAAI,sBAAsB,CAAC,EAAE,SAAS,eAAe,MAAM,YAAY,CAAC,CAAC;AAC1F,eAAS,QAAQ,eAAe;AAAA,QAC9B,QAAQ,CAAC,WAAW,YAAY,aAAa,cAAc,WAAW,OAAO;AAAA,QAC7E,QAAQ,CAAC,YAAY,aAAa,cAAc,OAAO;AAAA,MACzD,CAAC;AACD,YAAM,aAAa,YAAY,QAAQ;AACvC,aAAO;AAAA,QACL,eAAe,WAAW;AAAA,QAC1B,QAAQ,SAAS;AACf,qBAAW,QAAQ,OAAO;AAC1B,mBAAS,QAAQ;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,MAAM,aAA4B;AAAA,EAChC,OAAO,gBAAgB,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,EAAE,CAAC;AAAA,EACnD,SAAS,YAAY;AACnB,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAAA,EACA,YAAY,YAAY;AAAA,EAAC;AAAA,EACzB,QAAQ,YAAY;AACtB;AAEA,eAAe,OAAO,OAAc,SAAkB;AACpD,MAAI,WAAW,MAAM,MAAM,KAAK,EAAE,UAAU,OAAO;AACnD,QAAM,QAAQ,gBAAkC,SAAS,KAAK;AAC9D,QAAM,SAAS,CAAC,OAAyB,SAAkB,MAAM,QAAQ,MAAM,KAAK;AACpF,MAAI,MAAM,SAAS,UAAU,MAAM;AACnC,QAAM,OAAO,MAAM,OAAO,OAAO,iBAAiB;AAChD,UAAM,OAAO,MAAM,aAAa,UAAU,OAAO;AACjD,QAAI;AACJ,aAAS,QAAQ;AACjB,eAAW;AACX,UAAM,QAAQ,SAAS,KAAK,KAAK;AACjC,UAAM,KAAK,UAAU,MAAM;AAAA,EAC7B,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AACR,WAAK;AACL,UAAI;AACJ,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACF;AAEA,eAAsB,UACpB,OACA,UAaI,CAAC,GACe;AACpB,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,WAAW,QAAQ,YAAY,OAAO,WAAW;AACvD,QAAM,aAAa,MAAM,OAAO,OAAO,OAAO;AAC9C,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,UAAU,MAAM,WAAW,OAAO,OAAO;AAC/C,QAAM,QAAQ,MAAM,QAAQ,SAAS,MAAM;AAC3C,QAAM,UAAU,CAAC,MAAM,UAAU,KAAK,GAAG,QAAQ,MAAM,UAAU,KAAK,CAAC;AACvE,QAAM,WAAW,IAAI,sBAAsB;AAAA,IACzC,EAAE,SAAS,cAAc,MAAM,YAAY;AAAA,IAC3C,EAAE,SAAS,iBAAiB,MAAM,YAAY;AAAA,IAC9C,EAAE,SAAS,eAAe,MAAM,YAAY;AAAA,IAC5C,EAAE,SAAS,oBAAoB,MAAM,YAAY;AAAA,EACnD,CAAC;AACD,QAAM,aAAa,gBAAgB,MAAM,SAAS,OAAO,OAAO;AAChE,QAAM,UAAU;AAAA,IACd,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,WAAS,QAAQ,cAAc,OAAO;AACtC,QAAM,SAAS,aAAa;AAAA,IAC1B,SAAS,MAAM;AAAA,IACf,MAAM,CAAC,SAAS,UAAU,QAAQ,KAAK,SAAS,KAAK;AAAA,IACrD,MAAM,aAAa,SAAS,OAAO;AACjC,UAAI,CAAC,QAAS,QAAO,MAAM,KAAK;AAChC,YAAM,QAAQ,MAAM,MAAM,OAAO,aAAa,SAAS,KAAK;AAC5D,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,qBAAqB,OAAO,GAAG;AAC3D,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,WAAS,QAAQ,oBAAoB,MAAM;AAC3C,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA,YAAY,WAAW;AAAA,IACvB,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,UAAU,QAAQ,QAAQ,YAAY,gBAA2B,CAAC,CAAC;AAAA,IACnE,WAAW,QAAQ,WAAW,aAAa,gBAA4B,CAAC,CAAC;AAAA,IACzE,UAAU,QAAQ,QAAQ,YAAY,gBAA+B,CAAC,CAAC;AAAA,IACvE,cAAc,QAAQ,QAAQ,UAAU,gBAA+B,CAAC,CAAC;AAAA,IACzE,QAAQ,QAAQ,SAAS,UAAU,gBAA8B,CAAC,CAAC;AAAA,IACnE,SACE,QAAQ,SAAS,QAAQ,gBAA6B,EAAE,aAAa,MAAM,SAAS,CAAC,EAAE,CAAC;AAAA,EAC5F;AACA,WAAS,QAAQ,iBAAiB,iBAAiB;AACnD,QAAM,WAAW,QAAQ,YAAY;AACrC,WAAS,QAAQ,eAAe,QAAQ;AACxC,QAAM,SAAS,IAAI,sBAAsB;AAAA,IACvC,EAAE,SAAS,cAAc,MAAM,YAAY;AAAA,IAC3C,EAAE,SAAS,iBAAiB,MAAM,YAAY;AAAA,IAC9C,EAAE,SAAS,eAAe,MAAM,YAAY;AAAA,IAC5C,EAAE,SAAS,oBAAoB,MAAM,YAAY;AAAA,EACnD,CAAC;AACD,SAAO,QAAQ,cAAc,YAAY,OAAO,CAAC;AACjD,SAAO,QAAQ,iBAAiB,iBAAiB;AACjD,SAAO,QAAQ,eAAe,aAAa,QAAQ,CAAC;AACpD,SAAO,QAAQ,oBAAoB,WAAW,MAAM,CAAC;AACrD,QAAM,QAAQ,OAAO,IAAY,aAAoC;AACnE,UAAM,OAAmB;AAAA,MACvB,gBAAgB,eAAe;AAAA,MAC/B,MAAM,eAAe,WAAW;AAC9B,YAAI,cAAc;AAChB,gBAAM,IAAI,qBAAqB,mBAAmB,SAAS,EAAE;AAC/D,eAAO,EAAE,IAAI,UAAU;AAAA,MACzB;AAAA,MACA,aAAa,YAAY,gBAAgB,QAAQ;AAAA,IACnD;AACA,UAAM,WAAW,IAAI,aAAa,EAAE;AACpC,UAAM,SAAS,MAAM,IAAI,OAAO,MAAM,EAAE,UAAU,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC,EAAE,MAAM;AACrF,WAAO,EAAE,UAAU,OAAO;AAAA,EAC5B;AACA,QAAM,OAAO,MAAM,MAAM,UAAU,QAAQ;AAC3C,QAAM,OAAO,MAAM,MAAM,OAAO,WAAW,GAAG,MAAM;AACpD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,IAChD,SAAS,CAAC,UAAU,oBACjB,gBAAgB,WAAW,OAAO,MAAM,SAAS,QAAQ,QAAQ;AAAA,IACpE,MAAM,QAAQ;AACZ,YAAM,KAAK,OAAO,MAAM;AACxB,YAAM,KAAK,OAAO,MAAM;AACxB,aAAO,QAAQ;AACf,YAAM,OAAO,QAAQ;AACrB,eAAS,QAAQ;AACjB,iBAAW,QAAQ;AACnB,iBAAW,QAAQ;AACnB,cAAQ,QAAQ;AAChB,iBAAW,OAAO,QAAS,KAAI;AAC/B,cAAQ,SAAS,MAAM;AACvB,YAAM,QAAQ,SAAS,MAAM,OAAO;AACpC,YAAM,QAAQ,QAAQ,MAAM,OAAO;AACnC,YAAM,QAAQ,WAAW,MAAM,OAAO;AACtC,YAAM,QAAQ,QAAQ,MAAM,OAAO;AACnC,YAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,YAAM,QAAQ,QAAQ,QAAQ,MAAM,OAAO;AAC3C,YAAM,QAAQ,OAAO,QAAQ,MAAM,OAAO;AAC1C,YAAM,MAAM,MAAM;AAClB,YAAM,QAAQ,OAAO,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/dist/index.js CHANGED
@@ -12,6 +12,11 @@ import { createAgentControl } from "./control.js";
12
12
  import { CREDENTIALS_DATABASE, EncryptedCredentialStore } from "./credentials.js";
13
13
  import { hostAgent } from "./host.js";
14
14
  import { HOME, kernelEnvironment, SliccKernelEnv } from "./kernel/env.js";
15
+ import {
16
+ adminOver,
17
+ serveAdmin,
18
+ userClients
19
+ } from "./kernel/users.js";
15
20
  import { PortListener } from "./listener.js";
16
21
  import {
17
22
  runAgentWorker
@@ -47,7 +52,11 @@ import {
47
52
  } from "./sqlite.js";
48
53
  import { systemSection } from "./system.js";
49
54
  import { PortChannel, withUnrefTimers } from "./wire.js";
50
- import { kernelPort, serveConnections } from "./worker.js";
55
+ import {
56
+ kernelPort,
57
+ kernelPorts,
58
+ serveConnections
59
+ } from "./worker.js";
51
60
  export {
52
61
  ADOBE,
53
62
  ADOBE_PROXY,
@@ -69,6 +78,7 @@ export {
69
78
  SliccKernelEnv,
70
79
  SliccPrompt,
71
80
  WasmSqliteDatabase,
81
+ adminOver,
72
82
  adobeConfig,
73
83
  adobeModel,
74
84
  adobeProvider,
@@ -82,17 +92,20 @@ export {
82
92
  hostAgent,
83
93
  kernelEnvironment,
84
94
  kernelPort,
95
+ kernelPorts,
85
96
  openAgent,
86
97
  openMemorySqliteStorage,
87
98
  openOpfsSqliteStorage,
88
99
  patchServerAccept,
89
100
  runAgentWorker,
101
+ serveAdmin,
90
102
  serveConnections,
91
103
  sliccPrompt,
92
104
  sliccProviders,
93
105
  startAgent,
94
106
  systemSection,
95
107
  transportFetch,
108
+ userClients,
96
109
  withDefaultRegions,
97
110
  withUnrefTimers
98
111
  };
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["export {\n ADOBE,\n ADOBE_PROXY,\n type AdobeConfig,\n type AdobeModelInfo,\n adobeConfig,\n adobeModel,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nexport { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';\nexport { type AgentConnection, connectAgent } from './client.ts';\nexport { createAgentControl } from './control.ts';\nexport { CREDENTIALS_DATABASE, EncryptedCredentialStore } from './credentials.ts';\nexport { type AgentHost, hostAgent } from './host.ts';\nexport type {\n KernelClient,\n KernelFs,\n KernelProcess,\n KernelStat,\n SpawnOptions,\n} from './kernel/client.ts';\nexport { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nexport { PortListener } from './listener.ts';\nexport {\n type AgentWorkerOptions,\n type AgentWorkerScope,\n type KernelAttach,\n runAgentWorker,\n} from './main.ts';\nexport { type Transport, type TransportResponse, transportFetch } from './net.ts';\nexport {\n AGENT_LOCK,\n type AgentOwner,\n type AgentWorker,\n type OwnerOptions,\n startAgent,\n} from './owner.ts';\nexport { applyPatches, patchServerAccept } from './patches.ts';\nexport { SliccPrompt, sliccPrompt } from './prompt.ts';\nexport {\n type AccountState,\n AGENT_SESSION,\n AgentControl,\n AgentSessions,\n AgentSettings,\n type AgentSettingsChange,\n AgentTranscript,\n type BudgetState,\n type ModelChoice,\n type OperationError,\n type PromptResult,\n type SendMode,\n type SendRequest,\n type SendResponse,\n type SettingsState,\n type SignIn,\n} from './services.ts';\nexport {\n BEDROCK,\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n DEFAULT_REGIONS,\n sliccProviders,\n withDefaultRegions,\n} from './settings.ts';\nexport {\n AGENT_DIRECTORY,\n type OpfsSqliteOptions,\n openMemorySqliteStorage,\n openOpfsSqliteStorage,\n WasmSqliteDatabase,\n} from './sqlite.ts';\nexport { type SystemFacts, systemSection } from './system.ts';\nexport { PortChannel, type PortEndpoint, withUnrefTimers } from './wire.ts';\nexport { kernelPort, serveConnections, type WorkerScope } from './worker.ts';\n"],
5
- "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAwC,YAAY,iBAAiB;AACrE,SAA+B,oBAAoB;AACnD,SAAS,0BAA0B;AACnC,SAAS,sBAAsB,gCAAgC;AAC/D,SAAyB,iBAAiB;AAQ1C,SAAS,MAA6B,mBAAmB,sBAAsB;AAC/E,SAAS,oBAAoB;AAC7B;AAAA,EAIE;AAAA,OACK;AACP,SAAiD,sBAAsB;AACvE;AAAA,EACE;AAAA,EAIA;AAAA,OACK;AACP,SAAS,cAAc,yBAAyB;AAChD,SAAS,aAAa,mBAAmB;AACzC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OAUK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA2B,qBAAqB;AAChD,SAAS,aAAgC,uBAAuB;AAChE,SAAS,YAAY,wBAA0C;",
4
+ "sourcesContent": ["export {\n ADOBE,\n ADOBE_PROXY,\n type AdobeConfig,\n type AdobeModelInfo,\n adobeConfig,\n adobeModel,\n adobeProvider,\n adobeUsage,\n type Budget,\n} from './adobe.ts';\nexport { type Agent, type AgentOptions, answerText, openAgent } from './agent.ts';\nexport { type AgentConnection, connectAgent } from './client.ts';\nexport { createAgentControl } from './control.ts';\nexport { CREDENTIALS_DATABASE, EncryptedCredentialStore } from './credentials.ts';\nexport { type AgentHost, hostAgent } from './host.ts';\nexport type {\n KernelClient,\n KernelFs,\n KernelProcess,\n KernelStat,\n SpawnOptions,\n} from './kernel/client.ts';\nexport { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nexport {\n adminOver,\n type KernelAdmin,\n type KernelUser,\n type KernelUsers,\n serveAdmin,\n type UserClient,\n type UserClients,\n type UserConnect,\n type UserSpec,\n userClients,\n} from './kernel/users.ts';\nexport { PortListener } from './listener.ts';\nexport {\n type AgentWorkerOptions,\n type AgentWorkerScope,\n type KernelAttach,\n runAgentWorker,\n} from './main.ts';\nexport { type Transport, type TransportResponse, transportFetch } from './net.ts';\nexport {\n AGENT_LOCK,\n type AgentOwner,\n type AgentWorker,\n type KernelSource,\n type OwnerOptions,\n startAgent,\n} from './owner.ts';\nexport { applyPatches, patchServerAccept } from './patches.ts';\nexport { SliccPrompt, sliccPrompt } from './prompt.ts';\nexport {\n type AccountState,\n AGENT_SESSION,\n AgentControl,\n AgentSessions,\n AgentSettings,\n type AgentSettingsChange,\n AgentTranscript,\n type BudgetState,\n type ModelChoice,\n type OperationError,\n type PromptResult,\n type SendMode,\n type SendRequest,\n type SendResponse,\n type SettingsState,\n type SignIn,\n} from './services.ts';\nexport {\n BEDROCK,\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n DEFAULT_REGIONS,\n sliccProviders,\n withDefaultRegions,\n} from './settings.ts';\nexport {\n AGENT_DIRECTORY,\n type OpfsSqliteOptions,\n openMemorySqliteStorage,\n openOpfsSqliteStorage,\n WasmSqliteDatabase,\n} from './sqlite.ts';\nexport { type SystemFacts, systemSection } from './system.ts';\nexport { PortChannel, type PortEndpoint, withUnrefTimers } from './wire.ts';\nexport {\n type KernelPorts,\n kernelPort,\n kernelPorts,\n serveConnections,\n type WorkerScope,\n} from './worker.ts';\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAwC,YAAY,iBAAiB;AACrE,SAA+B,oBAAoB;AACnD,SAAS,0BAA0B;AACnC,SAAS,sBAAsB,gCAAgC;AAC/D,SAAyB,iBAAiB;AAQ1C,SAAS,MAA6B,mBAAmB,sBAAsB;AAC/E;AAAA,EACE;AAAA,EAIA;AAAA,EAKA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B;AAAA,EAIE;AAAA,OACK;AACP,SAAiD,sBAAsB;AACvE;AAAA,EACE;AAAA,EAKA;AAAA,OACK;AACP,SAAS,cAAc,yBAAyB;AAChD,SAAS,aAAa,mBAAmB;AACzC;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OAUK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAA2B,qBAAqB;AAChD,SAAS,aAAgC,uBAAuB;AAChE;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,113 @@
1
+ function failure(error) {
2
+ const message = error instanceof Error ? error.message : String(error);
3
+ const code = error?.code;
4
+ return typeof code === "string" ? { message, code } : { message };
5
+ }
6
+ async function perform(source, call) {
7
+ const users = source.users;
8
+ if (call.op === "connect") return source.connect(call.args[0]);
9
+ if (!users) throw Object.assign(new Error("this kernel has no users"), { code: "ENOSYS" });
10
+ if (call.op === "users.add") return users.add(call.args[0]);
11
+ if (call.op === "users.remove")
12
+ return users.remove(call.args[0], call.args[1]);
13
+ return users.list();
14
+ }
15
+ function serveAdmin(port, source) {
16
+ port.addEventListener("message", (event) => {
17
+ const call = event.data;
18
+ perform(source, call).then(
19
+ (value) => {
20
+ const transfer = call.op === "connect" ? [value] : [];
21
+ port.postMessage({ id: call.id, value }, transfer);
22
+ },
23
+ (error) => port.postMessage({ id: call.id, error: failure(error) })
24
+ );
25
+ });
26
+ port.start?.();
27
+ }
28
+ function adminOver(port) {
29
+ const pending = /* @__PURE__ */ new Map();
30
+ let next = 0;
31
+ let shut = false;
32
+ port.addEventListener("message", (event) => {
33
+ const reply = event.data;
34
+ const waiting = pending.get(reply.id);
35
+ if (!waiting) return;
36
+ pending.delete(reply.id);
37
+ if (reply.error) waiting.reject(Object.assign(new Error(reply.error.message), reply.error));
38
+ else waiting.resolve(reply.value);
39
+ });
40
+ port.start?.();
41
+ const call = (op, ...args) => new Promise((resolve, reject) => {
42
+ if (shut) {
43
+ reject(new Error("the kernel admin closed"));
44
+ return;
45
+ }
46
+ const id = ++next;
47
+ pending.set(id, { resolve, reject });
48
+ port.postMessage({ id, op, args });
49
+ });
50
+ return {
51
+ connect: (options) => call("connect", options),
52
+ users: {
53
+ add: (spec) => call("users.add", spec),
54
+ remove: (name, options) => call("users.remove", name, options),
55
+ list: () => call("users.list")
56
+ },
57
+ close() {
58
+ shut = true;
59
+ for (const waiting of pending.values()) waiting.reject(new Error("the kernel admin closed"));
60
+ pending.clear();
61
+ port.close?.();
62
+ }
63
+ };
64
+ }
65
+ function userClients(admin, attach) {
66
+ const held = /* @__PURE__ */ new Map();
67
+ const forget = (agentId, entry) => {
68
+ if (held.get(agentId) === entry) held.delete(agentId);
69
+ };
70
+ const end = async (entry, kill) => {
71
+ const client = await entry.client.catch(() => void 0);
72
+ await client?.close?.({ kill });
73
+ };
74
+ return {
75
+ users: admin.users,
76
+ client(agentId, user) {
77
+ const known = held.get(agentId);
78
+ if (known?.user === user) return known.client;
79
+ if (known) void end(known, true);
80
+ const entry = {
81
+ user,
82
+ client: admin.connect({ user, agentId }).then(attach)
83
+ };
84
+ held.set(agentId, entry);
85
+ entry.client.then(
86
+ (client) => client.closed?.then(
87
+ () => forget(agentId, entry),
88
+ () => forget(agentId, entry)
89
+ ),
90
+ () => forget(agentId, entry)
91
+ );
92
+ return entry.client;
93
+ },
94
+ async drop(agentId) {
95
+ const entry = held.get(agentId);
96
+ if (!entry) return;
97
+ held.delete(agentId);
98
+ await end(entry, true);
99
+ },
100
+ async close() {
101
+ const entries = [...held.values()];
102
+ held.clear();
103
+ await Promise.all(entries.map((entry) => end(entry, false)));
104
+ admin.close();
105
+ }
106
+ };
107
+ }
108
+ export {
109
+ adminOver,
110
+ serveAdmin,
111
+ userClients
112
+ };
113
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/kernel/users.ts"],
4
+ "sourcesContent": ["import type { PortEndpoint } from '../wire.ts';\nimport type { KernelClient } from './client.ts';\n\nexport interface KernelUser {\n name: string;\n uid: number;\n gid: number;\n home: string;\n shell: string;\n groups: number[];\n umask?: number;\n}\n\nexport interface UserSpec {\n name: string;\n home?: string;\n groups?: string[];\n umask?: number;\n homeGroup?: string;\n}\n\nexport interface KernelUsers {\n add(spec: UserSpec): Promise<KernelUser>;\n remove(name: string, options?: { keepHome?: boolean }): Promise<boolean>;\n list(): Promise<KernelUser[]>;\n}\n\nexport interface UserConnect {\n user?: string;\n agentId?: string;\n}\n\nexport interface KernelSource {\n connect(options?: UserConnect): Promise<Transferable>;\n users?: KernelUsers;\n}\n\nexport interface KernelAdmin {\n connect(options: UserConnect): Promise<MessagePort>;\n users: KernelUsers;\n close(): void;\n}\n\ntype Op = 'connect' | 'users.add' | 'users.remove' | 'users.list';\ntype Call = { id: number; op: Op; args: unknown[] };\ntype Reply = { id: number; value?: unknown; error?: { message: string; code?: string } };\n\nfunction failure(error: unknown): { message: string; code?: string } {\n const message = error instanceof Error ? error.message : String(error);\n const code = (error as { code?: unknown } | null)?.code;\n return typeof code === 'string' ? { message, code } : { message };\n}\n\nasync function perform(source: KernelSource, call: Call): Promise<unknown> {\n const users = source.users;\n if (call.op === 'connect') return source.connect(call.args[0] as UserConnect);\n if (!users) throw Object.assign(new Error('this kernel has no users'), { code: 'ENOSYS' });\n if (call.op === 'users.add') return users.add(call.args[0] as UserSpec);\n if (call.op === 'users.remove')\n return users.remove(call.args[0] as string, call.args[1] as { keepHome?: boolean });\n return users.list();\n}\n\nexport function serveAdmin(port: PortEndpoint, source: KernelSource): void {\n port.addEventListener('message', (event: MessageEvent) => {\n const call = event.data as Call;\n perform(source, call).then(\n (value) => {\n const transfer = call.op === 'connect' ? [value as Transferable] : [];\n port.postMessage({ id: call.id, value } satisfies Reply, transfer);\n },\n (error: unknown) => port.postMessage({ id: call.id, error: failure(error) } satisfies Reply)\n );\n });\n port.start?.();\n}\n\nexport function adminOver(port: PortEndpoint): KernelAdmin {\n const pending = new Map<number, { resolve(value: unknown): void; reject(error: Error): void }>();\n let next = 0;\n let shut = false;\n port.addEventListener('message', (event: MessageEvent) => {\n const reply = event.data as Reply;\n const waiting = pending.get(reply.id);\n if (!waiting) return;\n pending.delete(reply.id);\n if (reply.error) waiting.reject(Object.assign(new Error(reply.error.message), reply.error));\n else waiting.resolve(reply.value);\n });\n port.start?.();\n const call = <T>(op: Op, ...args: unknown[]) =>\n new Promise<T>((resolve, reject) => {\n if (shut) {\n reject(new Error('the kernel admin closed'));\n return;\n }\n const id = ++next;\n pending.set(id, { resolve: resolve as (value: unknown) => void, reject });\n port.postMessage({ id, op, args } satisfies Call);\n });\n return {\n connect: (options) => call<MessagePort>('connect', options),\n users: {\n add: (spec) => call<KernelUser>('users.add', spec),\n remove: (name, options) => call<boolean>('users.remove', name, options),\n list: () => call<KernelUser[]>('users.list'),\n },\n close() {\n shut = true;\n for (const waiting of pending.values()) waiting.reject(new Error('the kernel admin closed'));\n pending.clear();\n port.close?.();\n },\n };\n}\n\nexport type UserClient = KernelClient & {\n close?(options?: { kill?: boolean }): unknown;\n closed?: Promise<unknown>;\n};\n\nexport interface UserClients {\n readonly users: KernelUsers;\n client(agentId: string, user: string): Promise<UserClient>;\n drop(agentId: string): Promise<void>;\n close(): Promise<void>;\n}\n\ntype Held = { user: string; client: Promise<UserClient> };\n\nexport function userClients(\n admin: KernelAdmin,\n attach: (port: MessagePort) => Promise<UserClient>\n): UserClients {\n const held = new Map<string, Held>();\n const forget = (agentId: string, entry: Held) => {\n if (held.get(agentId) === entry) held.delete(agentId);\n };\n const end = async (entry: Held, kill: boolean) => {\n const client = await entry.client.catch(() => undefined);\n await client?.close?.({ kill });\n };\n return {\n users: admin.users,\n client(agentId, user) {\n const known = held.get(agentId);\n if (known?.user === user) return known.client;\n if (known) void end(known, true);\n const entry: Held = {\n user,\n client: admin.connect({ user, agentId }).then(attach),\n };\n held.set(agentId, entry);\n entry.client.then(\n (client) =>\n client.closed?.then(\n () => forget(agentId, entry),\n () => forget(agentId, entry)\n ),\n () => forget(agentId, entry)\n );\n return entry.client;\n },\n async drop(agentId) {\n const entry = held.get(agentId);\n if (!entry) return;\n held.delete(agentId);\n await end(entry, true);\n },\n async close() {\n const entries = [...held.values()];\n held.clear();\n await Promise.all(entries.map((entry) => end(entry, false)));\n admin.close();\n },\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/main.js CHANGED
@@ -22,6 +22,7 @@ import { imageReads } from "./images/index.js";
22
22
  import { createActivity } from "./kernel/activity.js";
23
23
  import { HOME, kernelEnvironment, SliccKernelEnv } from "./kernel/env.js";
24
24
  import { processGroups } from "./kernel/groups.js";
25
+ import { adminOver, userClients } from "./kernel/users.js";
25
26
  import { setupLicks } from "./licks/index.js";
26
27
  import { setupMcp } from "./mcp/index.js";
27
28
  import { setupMemory } from "./memory/index.js";
@@ -46,7 +47,25 @@ import {
46
47
  kernelBoot,
47
48
  transportName
48
49
  } from "./system.js";
49
- import { kernelPort, serveConnections } from "./worker.js";
50
+ import { kernelPorts, serveConnections } from "./worker.js";
51
+ function usersOf(admin, wanted, attach) {
52
+ if (!admin) return void 0;
53
+ if (wanted === false) {
54
+ admin.close();
55
+ return void 0;
56
+ }
57
+ return userClients(adminOver(admin), attach);
58
+ }
59
+ const STORE_DIR = "/.slicc";
60
+ async function attached(ports, options) {
61
+ const attach = options.attach ?? attachKernel;
62
+ const { kernel, admin } = await ports;
63
+ const client = await attach(kernel);
64
+ return { client, users: usersOf(admin, options.users, attach) };
65
+ }
66
+ function privateStore(env) {
67
+ return env.exec(`mkdir -p ${STORE_DIR} && chmod 700 ${STORE_DIR}`, void 0, BACKGROUND_CONTEXT);
68
+ }
50
69
  async function codemodeTools(client, options, native, extra) {
51
70
  const settings = await client.fs.readFile(`${HOME}/.pi/agent/settings.json`).catch(() => void 0);
52
71
  if (disabledBySettings(settings === void 0 ? void 0 : new TextDecoder().decode(settings)))
@@ -59,9 +78,10 @@ async function codemodeTools(client, options, native, extra) {
59
78
  codemodeTool({ declared: CodingTools.tools, sandbox, extra })
60
79
  ];
61
80
  }
62
- async function start(scope, port, options) {
63
- const attach = options.attach ?? attachKernel;
64
- const client = await attach(await port);
81
+ async function start(scope, ports, options) {
82
+ const { client, users } = await attached(ports, options);
83
+ const home = new SliccKernelEnv(client, { cwd: HOME });
84
+ await privateStore(home);
65
85
  const native = scope.fetch.bind(scope);
66
86
  scope.fetch = transportFetch(client.transport, scope.location.origin, native);
67
87
  const facts = {
@@ -108,7 +128,6 @@ async function start(scope, port, options) {
108
128
  env: environment
109
129
  });
110
130
  opened = agent;
111
- const home = new SliccKernelEnv(client, { cwd: HOME });
112
131
  const sources = licks.attach(agent, { env: home, home: HOME, activity });
113
132
  await sources.start(BACKGROUND_CONTEXT);
114
133
  await sources.boot(
@@ -210,7 +229,8 @@ async function start(scope, port, options) {
210
229
  memory: memoryRuntime,
211
230
  freezer,
212
231
  changes,
213
- mcp: mcpRuntime
232
+ mcp: mcpRuntime,
233
+ ...users ? { users } : {}
214
234
  });
215
235
  }
216
236
  function alive(client) {
@@ -220,13 +240,15 @@ function alive(client) {
220
240
  };
221
241
  }
222
242
  function runAgentWorker(scope, options = {}) {
223
- const host = start(scope, kernelPort(scope), options);
243
+ const host = start(scope, kernelPorts(scope), options);
224
244
  host.catch(() => void 0);
225
245
  serveConnections(scope, host);
226
246
  return host;
227
247
  }
228
248
  export {
249
+ STORE_DIR,
229
250
  alive,
230
- runAgentWorker
251
+ runAgentWorker,
252
+ usersOf
231
253
  };
232
254
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/main.ts"],
4
- "sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {\n createRegistry,\n type ModelRef,\n type Storage,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport { CodingTools } from '@earendil-works/pi-durable/tools';\nimport { type Agent, openAgent } from './agent.ts';\nimport { attachChanges, CHANGES_MS } from './changes/index.ts';\nimport {\n codemodeExtension,\n codemodeTool,\n disabledBySettings,\n locateWasm,\n sandboxFactory,\n} from './codemode/index.ts';\nimport { EncryptedCredentialStore } from './credentials.ts';\nimport { attachFreezer } from './freezer/index.ts';\nimport { settingsText, titler } from './freezer/title.ts';\nimport { lateGelatiere } from './gelatiere/index.ts';\nimport { type AgentHost, hostAgent } from './host.ts';\nimport { imageReads } from './images/index.ts';\nimport { createActivity } from './kernel/activity.ts';\nimport type { KernelClient } from './kernel/client.ts';\nimport { HOME, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nimport { processGroups } from './kernel/groups.ts';\nimport { setupLicks } from './licks/index.ts';\nimport { setupMcp } from './mcp/index.ts';\nimport { setupMemory } from './memory/index.ts';\nimport { modelsCommand } from './models/index.ts';\nimport { type Transport, transportFetch } from './net.ts';\nimport { sliccPrompt } from './prompt.ts';\nimport { identity } from './scoops/identity.ts';\nimport { type Assets, packageAssets, type ScoopsRuntime, setupScoops } from './scoops/index.ts';\nimport {\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n sliccProviders,\n} from './settings.ts';\nimport { RELOAD_MS, setupSkills } from './skills/index.ts';\nimport { setupSprinkles } from './sprinkles/index.ts';\nimport { openOpfsSqliteStorage } from './sqlite.ts';\nimport {\n agentVersion,\n browserConnected,\n commandsOnPath,\n kernelBoot,\n transportName,\n} from './system.ts';\nimport { kernelPort, serveConnections, type WorkerScope } from './worker.ts';\n\nexport interface AgentWorkerScope extends WorkerScope {\n fetch: typeof fetch;\n location: { origin: string };\n}\n\nexport type KernelAttach = (port: MessagePort) => Promise<KernelClient & { transport: Transport }>;\n\nexport interface AgentWorkerOptions {\n model?: ModelRef;\n providers?: Provider[];\n attach?: KernelAttach;\n credentials?: () => Promise<CredentialStore>;\n storage?: () => Promise<Storage>;\n assets?: Assets;\n codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;\n codemodeWorker?: string | URL;\n catalog?: string;\n}\n\nasync function codemodeTools(\n client: KernelClient,\n options: AgentWorkerOptions,\n native: typeof fetch,\n extra: Parameters<typeof codemodeTool>[0]['extra']\n) {\n const settings = await client.fs\n .readFile(`${HOME}/.pi/agent/settings.json`)\n .catch(() => undefined);\n if (disabledBySettings(settings === undefined ? undefined : new TextDecoder().decode(settings)))\n return [];\n const sandbox = sandboxFactory(\n options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),\n options.codemodeWorker\n );\n return [\n codemodeTool({ declared: CodingTools.tools as readonly ToolRegistration[], sandbox, extra }),\n ];\n}\n\nasync function start(\n scope: AgentWorkerScope,\n port: Promise<MessagePort>,\n options: AgentWorkerOptions\n): Promise<AgentHost> {\n const attach: KernelAttach = options.attach ?? attachKernel;\n const client = await attach(await port);\n const native = scope.fetch.bind(scope);\n scope.fetch = transportFetch(client.transport, scope.location.origin, native);\n const facts = {\n version: await agentVersion((url) => native(url)),\n commands: await commandsOnPath(client),\n transport: transportName(client.transport),\n browser: await browserConnected(client),\n };\n const credentials = await (options.credentials ?? (() => EncryptedCredentialStore.open()))();\n const providers = options.providers ?? sliccProviders();\n const models = createSliccModels(credentials, providers);\n const registry = createRegistry();\n registry.install(CodingTools);\n registry.install(sliccPrompt(facts));\n registry.install(\n imageReads(\n (CodingTools.tools as readonly ToolRegistration[]).find(\n (tool) => tool.name === 'read'\n ) as ToolRegistration\n )\n );\n const memory = setupMemory(registry);\n const coding = CodingTools.tools as readonly ToolRegistration[];\n const mcp = setupMcp(registry);\n const codemode = await codemodeTools(client, options, native, mcp.codemode);\n registry.install(codemodeExtension(codemode));\n const licks = setupLicks(registry);\n const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode, ...memory.tools]);\n const skills = setupSkills(registry, licks.licks);\n const activity = createActivity();\n const groups = processGroups(client);\n const model = options.model ?? DEFAULT_MODEL;\n let opened: Agent | undefined;\n const environment = kernelEnvironment(client, {\n activity,\n groups,\n identify: identity(() => opened?.agents, model),\n });\n const agent = await openAgent({\n models,\n model,\n storage: await (options.storage ?? (() => openOpfsSqliteStorage()))(),\n registry,\n env: environment,\n });\n opened = agent;\n const home = new SliccKernelEnv(client, { cwd: HOME });\n const sources = licks.attach(agent, { env: home, home: HOME, activity });\n await sources.start(BACKGROUND_CONTEXT);\n await sources.boot(\n { version: facts.version, boot: await kernelBoot(client) },\n BACKGROUND_CONTEXT\n );\n const skillsRuntime = await skills.attach(\n { env: home, home: HOME, assets: options.assets ?? packageAssets(), reloadMs: RELOAD_MS },\n BACKGROUND_CONTEXT\n );\n const mcpRuntime = await mcp.attach(\n {\n env: home,\n home: HOME,\n credentials,\n licks: licks.licks,\n fetch: scope.fetch,\n version: facts.version,\n reloadMs: RELOAD_MS,\n codemode: codemode.length > 0,\n cors: client.transport.traits?.crossOrigin === 'cors',\n },\n BACKGROUND_CONTEXT\n );\n const gelatiere = lateGelatiere();\n const sprinkles = await setupSprinkles().attach(\n {\n intercept: gelatiere.intercept,\n harness: agent.harness,\n agents: agent.agents,\n licks: licks.licks,\n env: home,\n assets: options.assets ?? packageAssets(),\n reloadMs: RELOAD_MS,\n },\n BACKGROUND_CONTEXT\n );\n let roles: ScoopsRuntime | undefined;\n const memoryRuntime = await memory.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n env: home,\n home: HOME,\n reloadMs: RELOAD_MS,\n roles: async (using) => roles?.roles(using),\n },\n BACKGROUND_CONTEXT\n );\n const freezer = attachFreezer({\n harness: agent.harness,\n agents: agent.agents,\n env: home,\n extract: memory.extract,\n title: titler(models, settingsText(home, HOME)),\n });\n licks.licks.guard(freezer.frozenTarget);\n const settings = await createAgentSettings(models, credentials, providers, { mcp: mcpRuntime });\n const runtime = await scoops.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n groups,\n env: home,\n home: HOME,\n alive: alive(client),\n reads: skillsRuntime.dirs,\n sprinkle: sprinkles.command,\n memory: memoryRuntime.command,\n gelatiere: gelatiere.command,\n freezer: freezer.command,\n models: modelsCommand({ agents: agent.agents, settings, catalog: models }),\n mcp: mcp.direct,\n ...(options.assets ? { assets: options.assets } : {}),\n },\n BACKGROUND_CONTEXT\n );\n roles = runtime;\n gelatiere.attach({\n agents: agent.agents,\n licks: licks.licks,\n env: home,\n home: HOME,\n scoops: scoops.scoops,\n roles: runtime.roles,\n assets: options.assets ?? packageAssets(),\n fetch: scope.fetch,\n skills: skillsRuntime.skills,\n ...(options.catalog ? { catalog: options.catalog } : {}),\n });\n await memoryRuntime.reload(BACKGROUND_CONTEXT).catch(() => undefined);\n const changes = attachChanges({ agents: agent.agents, env: home, reloadMs: CHANGES_MS });\n return hostAgent(agent, {\n settings,\n licks: { licks: licks.licks, sources },\n scoops: { scoops: scoops.scoops, runtime },\n skills: skillsRuntime,\n sprinkles,\n memory: memoryRuntime,\n freezer,\n changes,\n mcp: mcpRuntime,\n });\n}\n\nexport function alive(client: KernelClient) {\n return async (pid: number): Promise<boolean> => {\n if (!client.ps) return true;\n return (await client.ps()).some((process) => process.pid === pid);\n };\n}\n\nexport function runAgentWorker(\n scope: AgentWorkerScope,\n options: AgentWorkerOptions = {}\n): Promise<AgentHost> {\n const host = start(scope, kernelPort(scope), options);\n host.catch(() => undefined);\n serveConnections(scope, host);\n return host;\n}\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AAEnC;AAAA,EACE;AAAA,OAIK;AACP,SAAS,mBAAmB;AAC5B,SAAqB,iBAAiB;AACtC,SAAS,eAAe,kBAAkB;AAC1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gCAAgC;AACzC,SAAS,qBAAqB;AAC9B,SAAS,cAAc,cAAc;AACrC,SAAS,qBAAqB;AAC9B,SAAyB,iBAAiB;AAC1C,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAE/B,SAAS,MAAM,mBAAmB,sBAAsB;AACxD,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAyB,sBAAsB;AAC/C,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB;AACzB,SAAsB,eAAmC,mBAAmB;AAC5E;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,mBAAmB;AACvC,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY,wBAA0C;AAqB/D,eAAe,cACb,QACA,SACA,QACA,OACA;AACA,QAAM,WAAW,MAAM,OAAO,GAC3B,SAAS,GAAG,IAAI,0BAA0B,EAC1C,MAAM,MAAM,MAAS;AACxB,MAAI,mBAAmB,aAAa,SAAY,SAAY,IAAI,YAAY,EAAE,OAAO,QAAQ,CAAC;AAC5F,WAAO,CAAC;AACV,QAAM,UAAU;AAAA,IACd,QAAQ,iBAAiB,MAAM,WAAW,QAAQ,IAAI,IAAI,YAAY,GAAG,CAAC;AAAA,IAC1E,QAAQ;AAAA,EACV;AACA,SAAO;AAAA,IACL,aAAa,EAAE,UAAU,YAAY,OAAsC,SAAS,MAAM,CAAC;AAAA,EAC7F;AACF;AAEA,eAAe,MACb,OACA,MACA,SACoB;AACpB,QAAM,SAAuB,QAAQ,UAAU;AAC/C,QAAM,SAAS,MAAM,OAAO,MAAM,IAAI;AACtC,QAAM,SAAS,MAAM,MAAM,KAAK,KAAK;AACrC,QAAM,QAAQ,eAAe,OAAO,WAAW,MAAM,SAAS,QAAQ,MAAM;AAC5E,QAAM,QAAQ;AAAA,IACZ,SAAS,MAAM,aAAa,CAAC,QAAQ,OAAO,GAAG,CAAC;AAAA,IAChD,UAAU,MAAM,eAAe,MAAM;AAAA,IACrC,WAAW,cAAc,OAAO,SAAS;AAAA,IACzC,SAAS,MAAM,iBAAiB,MAAM;AAAA,EACxC;AACA,QAAM,cAAc,OAAO,QAAQ,gBAAgB,MAAM,yBAAyB,KAAK,IAAI;AAC3F,QAAM,YAAY,QAAQ,aAAa,eAAe;AACtD,QAAM,SAAS,kBAAkB,aAAa,SAAS;AACvD,QAAM,WAAW,eAAe;AAChC,WAAS,QAAQ,WAAW;AAC5B,WAAS,QAAQ,YAAY,KAAK,CAAC;AACnC,WAAS;AAAA,IACP;AAAA,MACG,YAAY,MAAsC;AAAA,QACjD,CAAC,SAAS,KAAK,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAS,YAAY,QAAQ;AACnC,QAAM,SAAS,YAAY;AAC3B,QAAM,MAAM,SAAS,QAAQ;AAC7B,QAAM,WAAW,MAAM,cAAc,QAAQ,SAAS,QAAQ,IAAI,QAAQ;AAC1E,WAAS,QAAQ,kBAAkB,QAAQ,CAAC;AAC5C,QAAM,QAAQ,WAAW,QAAQ;AACjC,QAAM,SAAS,YAAY,UAAU,MAAM,OAAO,CAAC,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,KAAK,CAAC;AAC3F,QAAM,SAAS,YAAY,UAAU,MAAM,KAAK;AAChD,QAAM,WAAW,eAAe;AAChC,QAAM,SAAS,cAAc,MAAM;AACnC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI;AACJ,QAAM,cAAc,kBAAkB,QAAQ;AAAA,IAC5C;AAAA,IACA;AAAA,IACA,UAAU,SAAS,MAAM,QAAQ,QAAQ,KAAK;AAAA,EAChD,CAAC;AACD,QAAM,QAAQ,MAAM,UAAU;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,SAAS,OAAO,QAAQ,YAAY,MAAM,sBAAsB,IAAI;AAAA,IACpE;AAAA,IACA,KAAK;AAAA,EACP,CAAC;AACD,WAAS;AACT,QAAM,OAAO,IAAI,eAAe,QAAQ,EAAE,KAAK,KAAK,CAAC;AACrD,QAAM,UAAU,MAAM,OAAO,OAAO,EAAE,KAAK,MAAM,MAAM,MAAM,SAAS,CAAC;AACvE,QAAM,QAAQ,MAAM,kBAAkB;AACtC,QAAM,QAAQ;AAAA,IACZ,EAAE,SAAS,MAAM,SAAS,MAAM,MAAM,WAAW,MAAM,EAAE;AAAA,IACzD;AAAA,EACF;AACA,QAAM,gBAAgB,MAAM,OAAO;AAAA,IACjC,EAAE,KAAK,MAAM,MAAM,MAAM,QAAQ,QAAQ,UAAU,cAAc,GAAG,UAAU,UAAU;AAAA,IACxF;AAAA,EACF;AACA,QAAM,aAAa,MAAM,IAAI;AAAA,IAC3B;AAAA,MACE,KAAK;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,OAAO,MAAM;AAAA,MACb,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,UAAU;AAAA,MACV,UAAU,SAAS,SAAS;AAAA,MAC5B,MAAM,OAAO,UAAU,QAAQ,gBAAgB;AAAA,IACjD;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAAY,cAAc;AAChC,QAAM,YAAY,MAAM,eAAe,EAAE;AAAA,IACvC;AAAA,MACE,WAAW,UAAU;AAAA,MACrB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,OAAO,MAAM;AAAA,MACb,KAAK;AAAA,MACL,QAAQ,QAAQ,UAAU,cAAc;AAAA,MACxC,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AACA,MAAI;AACJ,QAAM,gBAAgB,MAAM,OAAO;AAAA,IACjC;AAAA,MACE,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,KAAK;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO,OAAO,UAAU,OAAO,MAAM,KAAK;AAAA,IAC5C;AAAA,IACA;AAAA,EACF;AACA,QAAM,UAAU,cAAc;AAAA,IAC5B,SAAS,MAAM;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,KAAK;AAAA,IACL,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO,QAAQ,aAAa,MAAM,IAAI,CAAC;AAAA,EAChD,CAAC;AACD,QAAM,MAAM,MAAM,QAAQ,YAAY;AACtC,QAAM,WAAW,MAAM,oBAAoB,QAAQ,aAAa,WAAW,EAAE,KAAK,WAAW,CAAC;AAC9F,QAAM,UAAU,MAAM,OAAO;AAAA,IAC3B;AAAA,MACE,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd;AAAA,MACA,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO,MAAM,MAAM;AAAA,MACnB,OAAO,cAAc;AAAA,MACrB,UAAU,UAAU;AAAA,MACpB,QAAQ,cAAc;AAAA,MACtB,WAAW,UAAU;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,QAAQ,cAAc,EAAE,QAAQ,MAAM,QAAQ,UAAU,SAAS,OAAO,CAAC;AAAA,MACzE,KAAK,IAAI;AAAA,MACT,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACrD;AAAA,IACA;AAAA,EACF;AACA,UAAQ;AACR,YAAU,OAAO;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM;AAAA,IACb,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,OAAO;AAAA,IACf,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ,UAAU,cAAc;AAAA,IACxC,OAAO,MAAM;AAAA,IACb,QAAQ,cAAc;AAAA,IACtB,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACxD,CAAC;AACD,QAAM,cAAc,OAAO,kBAAkB,EAAE,MAAM,MAAM,MAAS;AACpE,QAAM,UAAU,cAAc,EAAE,QAAQ,MAAM,QAAQ,KAAK,MAAM,UAAU,WAAW,CAAC;AACvF,SAAO,UAAU,OAAO;AAAA,IACtB;AAAA,IACA,OAAO,EAAE,OAAO,MAAM,OAAO,QAAQ;AAAA,IACrC,QAAQ,EAAE,QAAQ,OAAO,QAAQ,QAAQ;AAAA,IACzC,QAAQ;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA,KAAK;AAAA,EACP,CAAC;AACH;AAEO,SAAS,MAAM,QAAsB;AAC1C,SAAO,OAAO,QAAkC;AAC9C,QAAI,CAAC,OAAO,GAAI,QAAO;AACvB,YAAQ,MAAM,OAAO,GAAG,GAAG,KAAK,CAAC,YAAY,QAAQ,QAAQ,GAAG;AAAA,EAClE;AACF;AAEO,SAAS,eACd,OACA,UAA8B,CAAC,GACX;AACpB,QAAM,OAAO,MAAM,OAAO,WAAW,KAAK,GAAG,OAAO;AACpD,OAAK,MAAM,MAAM,MAAS;AAC1B,mBAAiB,OAAO,IAAI;AAC5B,SAAO;AACT;",
4
+ "sourcesContent": ["import { attachKernel } from '@ai-ecoverse/slicc-kernel';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { CredentialStore, Provider } from '@earendil-works/pi-ai';\nimport {\n createRegistry,\n type ModelRef,\n type Storage,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport { CodingTools } from '@earendil-works/pi-durable/tools';\nimport { type Agent, openAgent } from './agent.ts';\nimport { attachChanges, CHANGES_MS } from './changes/index.ts';\nimport {\n codemodeExtension,\n codemodeTool,\n disabledBySettings,\n locateWasm,\n sandboxFactory,\n} from './codemode/index.ts';\nimport { EncryptedCredentialStore } from './credentials.ts';\nimport { attachFreezer } from './freezer/index.ts';\nimport { settingsText, titler } from './freezer/title.ts';\nimport { lateGelatiere } from './gelatiere/index.ts';\nimport { type AgentHost, hostAgent } from './host.ts';\nimport { imageReads } from './images/index.ts';\nimport { createActivity } from './kernel/activity.ts';\nimport type { KernelClient } from './kernel/client.ts';\nimport { HOME, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';\nimport { processGroups } from './kernel/groups.ts';\nimport { adminOver, type UserClient, type UserClients, userClients } from './kernel/users.ts';\nimport { setupLicks } from './licks/index.ts';\nimport { setupMcp } from './mcp/index.ts';\nimport { setupMemory } from './memory/index.ts';\nimport { modelsCommand } from './models/index.ts';\nimport { type Transport, transportFetch } from './net.ts';\nimport { sliccPrompt } from './prompt.ts';\nimport { identity } from './scoops/identity.ts';\nimport { type Assets, packageAssets, type ScoopsRuntime, setupScoops } from './scoops/index.ts';\nimport {\n createAgentSettings,\n createSliccModels,\n DEFAULT_MODEL,\n sliccProviders,\n} from './settings.ts';\nimport { RELOAD_MS, setupSkills } from './skills/index.ts';\nimport { setupSprinkles } from './sprinkles/index.ts';\nimport { openOpfsSqliteStorage } from './sqlite.ts';\nimport {\n agentVersion,\n browserConnected,\n commandsOnPath,\n kernelBoot,\n transportName,\n} from './system.ts';\nimport { type KernelPorts, kernelPorts, serveConnections, type WorkerScope } from './worker.ts';\n\nexport interface AgentWorkerScope extends WorkerScope {\n fetch: typeof fetch;\n location: { origin: string };\n}\n\nexport type KernelAttach = (port: MessagePort) => Promise<KernelClient & { transport: Transport }>;\n\nexport interface AgentWorkerOptions {\n model?: ModelRef;\n providers?: Provider[];\n attach?: KernelAttach;\n credentials?: () => Promise<CredentialStore>;\n storage?: () => Promise<Storage>;\n assets?: Assets;\n codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;\n codemodeWorker?: string | URL;\n catalog?: string;\n users?: boolean;\n}\n\nexport function usersOf(\n admin: MessagePort | undefined,\n wanted: boolean | undefined,\n attach: KernelAttach\n): UserClients | undefined {\n if (!admin) return undefined;\n if (wanted === false) {\n admin.close();\n return undefined;\n }\n return userClients(adminOver(admin), attach as (port: MessagePort) => Promise<UserClient>);\n}\n\nexport const STORE_DIR = '/.slicc';\n\nasync function attached(ports: Promise<KernelPorts>, options: AgentWorkerOptions) {\n const attach: KernelAttach = options.attach ?? attachKernel;\n const { kernel, admin } = await ports;\n const client = await attach(kernel);\n return { client, users: usersOf(admin, options.users, attach) };\n}\n\nfunction privateStore(env: SliccKernelEnv): Promise<unknown> {\n return env.exec(`mkdir -p ${STORE_DIR} && chmod 700 ${STORE_DIR}`, undefined, BACKGROUND_CONTEXT);\n}\n\nasync function codemodeTools(\n client: KernelClient,\n options: AgentWorkerOptions,\n native: typeof fetch,\n extra: Parameters<typeof codemodeTool>[0]['extra']\n) {\n const settings = await client.fs\n .readFile(`${HOME}/.pi/agent/settings.json`)\n .catch(() => undefined);\n if (disabledBySettings(settings === undefined ? undefined : new TextDecoder().decode(settings)))\n return [];\n const sandbox = sandboxFactory(\n options.codemodeWasm ?? (() => locateWasm(native, new URL(import.meta.url))),\n options.codemodeWorker\n );\n return [\n codemodeTool({ declared: CodingTools.tools as readonly ToolRegistration[], sandbox, extra }),\n ];\n}\n\nasync function start(\n scope: AgentWorkerScope,\n ports: Promise<KernelPorts>,\n options: AgentWorkerOptions\n): Promise<AgentHost> {\n const { client, users } = await attached(ports, options);\n const home = new SliccKernelEnv(client, { cwd: HOME });\n await privateStore(home);\n const native = scope.fetch.bind(scope);\n scope.fetch = transportFetch(client.transport, scope.location.origin, native);\n const facts = {\n version: await agentVersion((url) => native(url)),\n commands: await commandsOnPath(client),\n transport: transportName(client.transport),\n browser: await browserConnected(client),\n };\n const credentials = await (options.credentials ?? (() => EncryptedCredentialStore.open()))();\n const providers = options.providers ?? sliccProviders();\n const models = createSliccModels(credentials, providers);\n const registry = createRegistry();\n registry.install(CodingTools);\n registry.install(sliccPrompt(facts));\n registry.install(\n imageReads(\n (CodingTools.tools as readonly ToolRegistration[]).find(\n (tool) => tool.name === 'read'\n ) as ToolRegistration\n )\n );\n const memory = setupMemory(registry);\n const coding = CodingTools.tools as readonly ToolRegistration[];\n const mcp = setupMcp(registry);\n const codemode = await codemodeTools(client, options, native, mcp.codemode);\n registry.install(codemodeExtension(codemode));\n const licks = setupLicks(registry);\n const scoops = setupScoops(registry, licks.licks, [...coding, ...codemode, ...memory.tools]);\n const skills = setupSkills(registry, licks.licks);\n const activity = createActivity();\n const groups = processGroups(client);\n const model = options.model ?? DEFAULT_MODEL;\n let opened: Agent | undefined;\n const environment = kernelEnvironment(client, {\n activity,\n groups,\n identify: identity(() => opened?.agents, model),\n });\n const agent = await openAgent({\n models,\n model,\n storage: await (options.storage ?? (() => openOpfsSqliteStorage()))(),\n registry,\n env: environment,\n });\n opened = agent;\n const sources = licks.attach(agent, { env: home, home: HOME, activity });\n await sources.start(BACKGROUND_CONTEXT);\n await sources.boot(\n { version: facts.version, boot: await kernelBoot(client) },\n BACKGROUND_CONTEXT\n );\n const skillsRuntime = await skills.attach(\n { env: home, home: HOME, assets: options.assets ?? packageAssets(), reloadMs: RELOAD_MS },\n BACKGROUND_CONTEXT\n );\n const mcpRuntime = await mcp.attach(\n {\n env: home,\n home: HOME,\n credentials,\n licks: licks.licks,\n fetch: scope.fetch,\n version: facts.version,\n reloadMs: RELOAD_MS,\n codemode: codemode.length > 0,\n cors: client.transport.traits?.crossOrigin === 'cors',\n },\n BACKGROUND_CONTEXT\n );\n const gelatiere = lateGelatiere();\n const sprinkles = await setupSprinkles().attach(\n {\n intercept: gelatiere.intercept,\n harness: agent.harness,\n agents: agent.agents,\n licks: licks.licks,\n env: home,\n assets: options.assets ?? packageAssets(),\n reloadMs: RELOAD_MS,\n },\n BACKGROUND_CONTEXT\n );\n let roles: ScoopsRuntime | undefined;\n const memoryRuntime = await memory.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n env: home,\n home: HOME,\n reloadMs: RELOAD_MS,\n roles: async (using) => roles?.roles(using),\n },\n BACKGROUND_CONTEXT\n );\n const freezer = attachFreezer({\n harness: agent.harness,\n agents: agent.agents,\n env: home,\n extract: memory.extract,\n title: titler(models, settingsText(home, HOME)),\n });\n licks.licks.guard(freezer.frozenTarget);\n const settings = await createAgentSettings(models, credentials, providers, { mcp: mcpRuntime });\n const runtime = await scoops.attach(\n {\n harness: agent.harness,\n agents: agent.agents,\n groups,\n env: home,\n home: HOME,\n alive: alive(client),\n reads: skillsRuntime.dirs,\n sprinkle: sprinkles.command,\n memory: memoryRuntime.command,\n gelatiere: gelatiere.command,\n freezer: freezer.command,\n models: modelsCommand({ agents: agent.agents, settings, catalog: models }),\n mcp: mcp.direct,\n ...(options.assets ? { assets: options.assets } : {}),\n },\n BACKGROUND_CONTEXT\n );\n roles = runtime;\n gelatiere.attach({\n agents: agent.agents,\n licks: licks.licks,\n env: home,\n home: HOME,\n scoops: scoops.scoops,\n roles: runtime.roles,\n assets: options.assets ?? packageAssets(),\n fetch: scope.fetch,\n skills: skillsRuntime.skills,\n ...(options.catalog ? { catalog: options.catalog } : {}),\n });\n await memoryRuntime.reload(BACKGROUND_CONTEXT).catch(() => undefined);\n const changes = attachChanges({ agents: agent.agents, env: home, reloadMs: CHANGES_MS });\n return hostAgent(agent, {\n settings,\n licks: { licks: licks.licks, sources },\n scoops: { scoops: scoops.scoops, runtime },\n skills: skillsRuntime,\n sprinkles,\n memory: memoryRuntime,\n freezer,\n changes,\n mcp: mcpRuntime,\n ...(users ? { users } : {}),\n });\n}\n\nexport function alive(client: KernelClient) {\n return async (pid: number): Promise<boolean> => {\n if (!client.ps) return true;\n return (await client.ps()).some((process) => process.pid === pid);\n };\n}\n\nexport function runAgentWorker(\n scope: AgentWorkerScope,\n options: AgentWorkerOptions = {}\n): Promise<AgentHost> {\n const host = start(scope, kernelPorts(scope), options);\n host.catch(() => undefined);\n serveConnections(scope, host);\n return host;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/owner.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { connectAgent } from "./client.js";
2
+ import { serveAdmin } from "./kernel/users.js";
2
3
  import { holdLock } from "./opfs-pool.js";
3
4
  const AGENT_LOCK = "slicc-agent";
4
5
  async function startAgent(options) {
@@ -6,16 +7,32 @@ async function startAgent(options) {
6
7
  const channel = options.channel ?? (() => new MessageChannel());
7
8
  const spawn = async () => {
8
9
  const created = options.worker();
10
+ let admin;
9
11
  try {
10
12
  if (options.kernel) {
11
13
  const port = await options.kernel.connect();
12
- created.postMessage({ kernel: port }, [port]);
14
+ if (!options.kernel.users) created.postMessage({ kernel: port }, [port]);
15
+ else {
16
+ const { port1, port2 } = channel();
17
+ admin = port1;
18
+ serveAdmin(port1, options.kernel);
19
+ created.postMessage({ kernel: port, admin: port2 }, [port, port2]);
20
+ }
13
21
  }
14
22
  } catch (error) {
23
+ admin?.close?.();
15
24
  created.terminate();
16
25
  throw error;
17
26
  }
18
- return created;
27
+ if (!admin) return created;
28
+ const served = admin;
29
+ return {
30
+ postMessage: (message, transfer) => created.postMessage(message, transfer),
31
+ terminate() {
32
+ served.close?.();
33
+ created.terminate();
34
+ }
35
+ };
19
36
  };
20
37
  let worker = Promise.resolve().then(spawn);
21
38
  try {
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 AgentConnection, connectAgent } from './client.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}\n\nexport interface AgentOwner {\n connect(options?: PortOptions): Promise<AgentConnection>;\n port(options?: PortOptions): Promise<PortEndpoint & Transferable>;\n restart(): Promise<void>;\n release(): Promise<void>;\n}\n\nexport interface KernelSource {\n connect(): Promise<Transferable>;\n}\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 try {\n if (options.kernel) {\n const port = await options.kernel.connect();\n created.postMessage({ kernel: port }, [port]);\n }\n } catch (error) {\n created.terminate();\n throw error;\n }\n return created;\n };\n let worker: Promise<AgentWorker | undefined> = Promise.resolve().then(spawn);\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 ready.postMessage({ connect: port2, ...readOnly }, [port2]);\n return port1;\n };\n return {\n async connect(portOptions) {\n return connectAgent(await open(portOptions));\n },\n port: open,\n restart() {\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 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": "AAAA,SAA+B,oBAAoB;AACnD,SAAS,gBAAgB;AAGlB,MAAM,aAAa;AA8B1B,eAAsB,WAAW,SAA4C;AAC3E,QAAM,UAAU,QAAQ,OACpB,MAAM,SACN,MAAM,SAAS,QAAQ,SAAS,UAAU,OAAO,UAAU;AAC/D,QAAM,UAAU,QAAQ,YAAY,MAAM,IAAI,eAAe;AAC7D,QAAM,QAAQ,YAAkC;AAC9C,UAAM,UAAU,QAAQ,OAAO;AAC/B,QAAI;AACF,UAAI,QAAQ,QAAQ;AAClB,cAAM,OAAO,MAAM,QAAQ,OAAO,QAAQ;AAC1C,gBAAQ,YAAY,EAAE,QAAQ,KAAK,GAAG,CAAC,IAAI,CAAC;AAAA,MAC9C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,UAAU;AAClB,YAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT;AACA,MAAI,SAA2C,QAAQ,QAAQ,EAAE,KAAK,KAAK;AAC3E,MAAI;AACF,UAAM;AAAA,EACR,SAAS,OAAO;AACd,YAAQ;AACR,UAAM;AAAA,EACR;AACA,QAAM,OAAO,OAAO,cAA2B,CAAC,MAA4C;AAC1F,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wBAAwB;AACpD,UAAM,EAAE,OAAO,MAAM,IAAI,QAAQ;AACjC,UAAM,WAAW,YAAY,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;AACvE,UAAM,YAAY,EAAE,SAAS,OAAO,GAAG,SAAS,GAAG,CAAC,KAAK,CAAC;AAC1D,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,MAAM,QAAQ,aAAa;AACzB,aAAO,aAAa,MAAM,KAAK,WAAW,CAAC;AAAA,IAC7C;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AACR,eAAS,OACN,MAAM,MAAM,MAAS,EACrB,KAAK,CAAC,QAAQ;AACb,aAAK,UAAU;AACf,eAAO,MAAM;AAAA,MACf,CAAC;AACH,aAAO,OAAO,KAAK,MAAM,MAAS;AAAA,IACpC;AAAA,IACA,MAAM,UAAU;AACd,YAAM,WAAW;AACjB,eAAS,QAAQ,QAAQ,MAAS;AAClC,UAAI;AACF,SAAC,MAAM,SAAS,MAAM,MAAM,MAAS,IAAI,UAAU;AAAA,MACrD,UAAE;AACA,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { 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}\n\nexport interface AgentOwner {\n connect(options?: PortOptions): Promise<AgentConnection>;\n port(options?: PortOptions): Promise<PortEndpoint & Transferable>;\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 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 ready.postMessage({ connect: port2, ...readOnly }, [port2]);\n return port1;\n };\n return {\n async connect(portOptions) {\n return connectAgent(await open(portOptions));\n },\n port: open,\n restart() {\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 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": "AAAA,SAA+B,oBAAoB;AACnD,SAA4B,kBAAkB;AAC9C,SAAS,gBAAgB;AAGlB,MAAM,aAAa;AA4B1B,eAAsB,WAAW,SAA4C;AAC3E,QAAM,UAAU,QAAQ,OACpB,MAAM,SACN,MAAM,SAAS,QAAQ,SAAS,UAAU,OAAO,UAAU;AAC/D,QAAM,UAAU,QAAQ,YAAY,MAAM,IAAI,eAAe;AAC7D,QAAM,QAAQ,YAAkC;AAC9C,UAAM,UAAU,QAAQ,OAAO;AAC/B,QAAI;AACJ,QAAI;AACF,UAAI,QAAQ,QAAQ;AAClB,cAAM,OAAO,MAAM,QAAQ,OAAO,QAAQ;AAC1C,YAAI,CAAC,QAAQ,OAAO,MAAO,SAAQ,YAAY,EAAE,QAAQ,KAAK,GAAG,CAAC,IAAI,CAAC;AAAA,aAClE;AACH,gBAAM,EAAE,OAAO,MAAM,IAAI,QAAQ;AACjC,kBAAQ;AACR,qBAAW,OAAO,QAAQ,MAAM;AAChC,kBAAQ,YAAY,EAAE,QAAQ,MAAM,OAAO,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC;AAAA,QACnE;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,aAAO,QAAQ;AACf,cAAQ,UAAU;AAClB,YAAM;AAAA,IACR;AACA,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,SAAS;AACf,WAAO;AAAA,MACL,aAAa,CAAC,SAAS,aAAa,QAAQ,YAAY,SAAS,QAAQ;AAAA,MACzE,YAAY;AACV,eAAO,QAAQ;AACf,gBAAQ,UAAU;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACA,MAAI,SAA2C,QAAQ,QAAQ,EAAE,KAAK,KAAK;AAC3E,MAAI;AACF,UAAM;AAAA,EACR,SAAS,OAAO;AACd,YAAQ;AACR,UAAM;AAAA,EACR;AACA,QAAM,OAAO,OAAO,cAA2B,CAAC,MAA4C;AAC1F,UAAM,QAAQ,MAAM;AACpB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wBAAwB;AACpD,UAAM,EAAE,OAAO,MAAM,IAAI,QAAQ;AACjC,UAAM,WAAW,YAAY,aAAa,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;AACvE,UAAM,YAAY,EAAE,SAAS,OAAO,GAAG,SAAS,GAAG,CAAC,KAAK,CAAC;AAC1D,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,MAAM,QAAQ,aAAa;AACzB,aAAO,aAAa,MAAM,KAAK,WAAW,CAAC;AAAA,IAC7C;AAAA,IACA,MAAM;AAAA,IACN,UAAU;AACR,eAAS,OACN,MAAM,MAAM,MAAS,EACrB,KAAK,CAAC,QAAQ;AACb,aAAK,UAAU;AACf,eAAO,MAAM;AAAA,MACf,CAAC;AACH,aAAO,OAAO,KAAK,MAAM,MAAS;AAAA,IACpC;AAAA,IACA,MAAM,UAAU;AACd,YAAM,WAAW;AACjB,eAAS,QAAQ,QAAQ,MAAS;AAClC,UAAI;AACF,SAAC,MAAM,SAAS,MAAM,MAAM,MAAS,IAAI,UAAU;AAAA,MACrD,UAAE;AACA,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -2,10 +2,11 @@ import { live } from "../agents.js";
2
2
  import { DEFAULT_LIMITS, loadRoles, packageDirs } from "../roles/roles.js";
3
3
  import { createCli, RUN_DIR } from "./cli.js";
4
4
  import { guardExtension, scoopsExtension, scoopTasks } from "./extension.js";
5
- import { controlPlane } from "./requests.js";
5
+ import { controlPlane, PROTOCOL } from "./requests.js";
6
6
  import { createScoops } from "./service.js";
7
7
  const BUILTIN_ROLES = ["scout", "worker", "reviewer", "oracle", "delegate", "gelatiere"];
8
8
  const PNPM_HOME = "/home/.local/share/pnpm";
9
+ const BIN_DIR = "/usr/local/bin";
9
10
  function packageAssets(base = new URL("../../", import.meta.url)) {
10
11
  return async (path) => {
11
12
  const response = await fetch(new URL(path, base));
@@ -35,12 +36,28 @@ async function pnpmHomeOf(env, context) {
35
36
  ).catch(() => void 0);
36
37
  return ran?.ok && ran.value.exitCode === 0 && /^\/\S*$/.test(out) ? out : PNPM_HOME;
37
38
  }
38
- async function install(env, script, pnpmHome, context) {
39
- await env.createDir(`${pnpmHome}/bin`, { recursive: true }, context);
39
+ async function install(env, script, binDir, context) {
40
+ if (!(await env.createDir(binDir, { recursive: true }, context)).ok) return false;
40
41
  for (const name of COMMANDS) {
41
- const path = `${pnpmHome}/bin/${name}`;
42
- await env.writeFile(path, script, context);
43
- await env.exec(["chmod", "+x", path], void 0, context);
42
+ const path = `${binDir}/${name}`;
43
+ if (!(await env.writeFile(path, script, context)).ok) return false;
44
+ const mode = await env.exec(["chmod", "755", path], void 0, context);
45
+ if (!mode.ok || mode.value.exitCode !== 0) return false;
46
+ }
47
+ return true;
48
+ }
49
+ async function installCommands(env, script, binDir, context) {
50
+ const done = await install(env, script, binDir, context).catch(() => false);
51
+ if (done) await retire(env, binDir, context).catch(() => void 0);
52
+ return done;
53
+ }
54
+ async function retire(env, binDir, context) {
55
+ const old = `${await pnpmHomeOf(env, context)}/bin`;
56
+ if (old === binDir) return;
57
+ for (const name of COMMANDS) {
58
+ const path = `${old}/${name}`;
59
+ const text = await env.readTextFile(path, context);
60
+ if (text.ok && text.value.includes(PROTOCOL)) await env.remove(path, { force: true }, context);
44
61
  }
45
62
  }
46
63
  function mirror(agents, env) {
@@ -119,8 +136,8 @@ function setupScoops(registry, licks, fileTools = []) {
119
136
  await roles(context).catch(() => cached);
120
137
  const script = await assets("bin/agent").catch(() => void 0);
121
138
  if (script) {
122
- const pnpmHome = options.pnpmHome ?? await pnpmHomeOf(env, context);
123
- await install(env, script, pnpmHome, context).catch(() => void 0);
139
+ const binDir = options.binDir ?? BIN_DIR;
140
+ await installCommands(env, script, binDir, context);
124
141
  }
125
142
  const cli = createCli({
126
143
  env,
@@ -146,11 +163,14 @@ function setupScoops(registry, licks, fileTools = []) {
146
163
  };
147
164
  }
148
165
  export {
166
+ BIN_DIR,
149
167
  BUILTIN_ROLES,
150
168
  COMMANDS,
151
169
  PNPM_HOME,
170
+ installCommands,
152
171
  packageAssets,
153
172
  pnpmHomeOf,
173
+ retire,
154
174
  setupScoops
155
175
  };
156
176
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/scoops/index.ts"],
4
- "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Harness, Registry, ToolRegistration } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { type Agents, live } from '../agents.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { DEFAULT_LIMITS, loadRoles, packageDirs, type Roles } from '../roles/roles.ts';\nimport { type CliOptions, createCli, RUN_DIR } from './cli.ts';\nimport { guardExtension, scoopsExtension, scoopTasks } from './extension.ts';\nimport { type ControlPlane, controlPlane } from './requests.ts';\nimport { createScoops, type Scoops, type ScoopsHost } from './service.ts';\n\nexport const BUILTIN_ROLES = ['scout', 'worker', 'reviewer', 'oracle', 'delegate', 'gelatiere'];\nexport const PNPM_HOME = '/home/.local/share/pnpm';\n\nexport type Assets = (path: string) => Promise<string>;\n\nexport function packageAssets(base: URL = new URL('../../', import.meta.url)): Assets {\n return async (path) => {\n const response = await fetch(new URL(path, base));\n if (!response.ok) throw new Error(`${path}: ${response.status}`);\n return response.text();\n };\n}\n\nexport interface AttachOptions {\n harness: Harness;\n agents: Agents;\n groups: ProcessGroups;\n env: ExecutionEnv;\n home: string;\n assets?: Assets;\n pnpmHome?: string;\n controlDir?: string;\n sweepEvery?: number;\n alive?: (pid: number) => Promise<boolean>;\n reads: () => readonly string[];\n sprinkle?: CliOptions['sprinkle'];\n memory?: CliOptions['memory'];\n gelatiere?: CliOptions['gelatiere'];\n freezer?: CliOptions['freezer'];\n models?: CliOptions['models'];\n mcp?: (names: readonly string[]) => ToolRegistration[];\n}\n\nexport interface ScoopsRuntime {\n roles(context: Context): Promise<Roles>;\n plane: ControlPlane;\n close(context: Context): Promise<void>;\n}\n\nexport interface ScoopsSetup {\n scoops: Scoops;\n attach(options: AttachOptions, context: Context): Promise<ScoopsRuntime>;\n}\n\nexport const COMMANDS = [\n 'agent',\n 'subagent',\n 'sprinkle',\n 'memory',\n 'gelatiere',\n 'freezer',\n 'models',\n];\n\nexport async function pnpmHomeOf(env: ExecutionEnv, context: Context): Promise<string> {\n let out = '';\n const ran = await env\n .exec(\n 'printf %s \"$PNPM_HOME\"',\n {\n onOutput: (text) => {\n out += text;\n },\n },\n context\n )\n .catch(() => undefined);\n return ran?.ok && ran.value.exitCode === 0 && /^\\/\\S*$/.test(out) ? out : PNPM_HOME;\n}\n\nasync function install(env: ExecutionEnv, script: string, pnpmHome: string, context: Context) {\n await env.createDir(`${pnpmHome}/bin`, { recursive: true }, context);\n for (const name of COMMANDS) {\n const path = `${pnpmHome}/bin/${name}`;\n await env.writeFile(path, script, context);\n await env.exec(['chmod', '+x', path], undefined, context);\n }\n}\n\nfunction mirror(agents: Agents, env: ExecutionEnv) {\n return async (context: Context) => {\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n const state = record.gone ? 'gone' : live(record) ? 'live' : 'stopped';\n const metadata = {\n handle: record.folder,\n id,\n name: record.name,\n role: record.role,\n cone: record.cone,\n state,\n };\n await env.writeFile(\n `${RUN_DIR}/${record.folder}/metadata.json`,\n `${JSON.stringify(metadata, null, 2)}\\n`,\n context\n );\n }\n };\n}\n\nexport function setupScoops(\n registry: Registry,\n licks: Licks,\n fileTools: readonly ToolRegistration[] = []\n): ScoopsSetup {\n let bind: (host: ScoopsHost) => void = () => undefined;\n const host = new Promise<ScoopsHost>((resolve) => {\n bind = resolve;\n });\n const lookup = () => host;\n const tasks = scoopTasks(lookup);\n const scoops = createScoops(host, () => tasks);\n let cached: Roles = { roles: [], warnings: [], limits: { ...DEFAULT_LIMITS } };\n registry.install(scoopsExtension(tasks));\n registry.install(guardExtension(lookup, fileTools));\n return {\n scoops,\n async attach(options, context) {\n const { harness, agents, groups, env, home } = options;\n const assets = options.assets ?? packageAssets();\n bind({\n harness,\n agents,\n licks,\n tools: fileTools,\n groups,\n reads: options.reads,\n files: env,\n ...(options.mcp ? { mcp: options.mcp } : {}),\n });\n const builtin = async () => {\n const out: { path: string; text: string }[] = [];\n for (const name of BUILTIN_ROLES) {\n const path = `packages/vfs-root/agents/${name}.md`;\n out.push({ path: `builtin:${name}`, text: await assets(path) });\n }\n return out;\n };\n const roles = async (using: Context) => {\n cached = await loadRoles(\n {\n files: env,\n builtin,\n dirs: [\n ...(await packageDirs(env, '/node_modules', using)).map((dir) => ({\n source: 'package' as const,\n dir,\n })),\n { source: 'user', dir: `${home}/.pi/agent/agents` },\n ],\n settingsPath: `${home}/.pi/agent/settings.json`,\n },\n using\n );\n return cached;\n };\n await roles(context).catch(() => cached);\n const script = await assets('bin/agent').catch(() => undefined);\n if (script) {\n const pnpmHome = options.pnpmHome ?? (await pnpmHomeOf(env, context));\n await install(env, script, pnpmHome, context).catch(() => undefined);\n }\n const cli = createCli({\n env,\n harness,\n agents,\n scoops,\n roles: () => roles(context),\n ...(options.alive ? { alive: options.alive } : {}),\n ...(options.sprinkle ? { sprinkle: options.sprinkle } : {}),\n ...(options.memory ? { memory: options.memory } : {}),\n ...(options.gelatiere ? { gelatiere: options.gelatiere } : {}),\n ...(options.freezer ? { freezer: options.freezer } : {}),\n ...(options.models ? { models: options.models } : {}),\n });\n const plane = controlPlane(env, cli, {\n ...(options.controlDir ? { dir: options.controlDir } : {}),\n ...(options.sweepEvery ? { sweepEvery: options.sweepEvery } : {}),\n mirror: mirror(agents, env),\n });\n await plane.start(context);\n return { roles, plane, close: (using) => plane.close(using) };\n },\n };\n}\n\nexport type { Rewound, Scoops } from './service.ts';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { Harness, Registry, ToolRegistration } from '@earendil-works/pi-durable';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { type Agents, live } from '../agents.ts';\nimport type { ProcessGroups } from '../kernel/groups.ts';\nimport type { Licks } from '../licks/licks.ts';\nimport { DEFAULT_LIMITS, loadRoles, packageDirs, type Roles } from '../roles/roles.ts';\nimport { type CliOptions, createCli, RUN_DIR } from './cli.ts';\nimport { guardExtension, scoopsExtension, scoopTasks } from './extension.ts';\nimport { type ControlPlane, controlPlane, PROTOCOL } from './requests.ts';\nimport { createScoops, type Scoops, type ScoopsHost } from './service.ts';\n\nexport const BUILTIN_ROLES = ['scout', 'worker', 'reviewer', 'oracle', 'delegate', 'gelatiere'];\nexport const PNPM_HOME = '/home/.local/share/pnpm';\nexport const BIN_DIR = '/usr/local/bin';\n\nexport type Assets = (path: string) => Promise<string>;\n\nexport function packageAssets(base: URL = new URL('../../', import.meta.url)): Assets {\n return async (path) => {\n const response = await fetch(new URL(path, base));\n if (!response.ok) throw new Error(`${path}: ${response.status}`);\n return response.text();\n };\n}\n\nexport interface AttachOptions {\n harness: Harness;\n agents: Agents;\n groups: ProcessGroups;\n env: ExecutionEnv;\n home: string;\n assets?: Assets;\n binDir?: string;\n controlDir?: string;\n sweepEvery?: number;\n alive?: (pid: number) => Promise<boolean>;\n reads: () => readonly string[];\n sprinkle?: CliOptions['sprinkle'];\n memory?: CliOptions['memory'];\n gelatiere?: CliOptions['gelatiere'];\n freezer?: CliOptions['freezer'];\n models?: CliOptions['models'];\n mcp?: (names: readonly string[]) => ToolRegistration[];\n}\n\nexport interface ScoopsRuntime {\n roles(context: Context): Promise<Roles>;\n plane: ControlPlane;\n close(context: Context): Promise<void>;\n}\n\nexport interface ScoopsSetup {\n scoops: Scoops;\n attach(options: AttachOptions, context: Context): Promise<ScoopsRuntime>;\n}\n\nexport const COMMANDS = [\n 'agent',\n 'subagent',\n 'sprinkle',\n 'memory',\n 'gelatiere',\n 'freezer',\n 'models',\n];\n\nexport async function pnpmHomeOf(env: ExecutionEnv, context: Context): Promise<string> {\n let out = '';\n const ran = await env\n .exec(\n 'printf %s \"$PNPM_HOME\"',\n {\n onOutput: (text) => {\n out += text;\n },\n },\n context\n )\n .catch(() => undefined);\n return ran?.ok && ran.value.exitCode === 0 && /^\\/\\S*$/.test(out) ? out : PNPM_HOME;\n}\n\nasync function install(env: ExecutionEnv, script: string, binDir: string, context: Context) {\n if (!(await env.createDir(binDir, { recursive: true }, context)).ok) return false;\n for (const name of COMMANDS) {\n const path = `${binDir}/${name}`;\n if (!(await env.writeFile(path, script, context)).ok) return false;\n const mode = await env.exec(['chmod', '755', path], undefined, context);\n if (!mode.ok || mode.value.exitCode !== 0) return false;\n }\n return true;\n}\n\nexport async function installCommands(\n env: ExecutionEnv,\n script: string,\n binDir: string,\n context: Context\n): Promise<boolean> {\n const done = await install(env, script, binDir, context).catch(() => false);\n if (done) await retire(env, binDir, context).catch(() => undefined);\n return done;\n}\n\nexport async function retire(env: ExecutionEnv, binDir: string, context: Context) {\n const old = `${await pnpmHomeOf(env, context)}/bin`;\n if (old === binDir) return;\n for (const name of COMMANDS) {\n const path = `${old}/${name}`;\n const text = await env.readTextFile(path, context);\n if (text.ok && text.value.includes(PROTOCOL)) await env.remove(path, { force: true }, context);\n }\n}\n\nfunction mirror(agents: Agents, env: ExecutionEnv) {\n return async (context: Context) => {\n for (const [id, record] of Object.entries(agents.state().scoops)) {\n const state = record.gone ? 'gone' : live(record) ? 'live' : 'stopped';\n const metadata = {\n handle: record.folder,\n id,\n name: record.name,\n role: record.role,\n cone: record.cone,\n state,\n };\n await env.writeFile(\n `${RUN_DIR}/${record.folder}/metadata.json`,\n `${JSON.stringify(metadata, null, 2)}\\n`,\n context\n );\n }\n };\n}\n\nexport function setupScoops(\n registry: Registry,\n licks: Licks,\n fileTools: readonly ToolRegistration[] = []\n): ScoopsSetup {\n let bind: (host: ScoopsHost) => void = () => undefined;\n const host = new Promise<ScoopsHost>((resolve) => {\n bind = resolve;\n });\n const lookup = () => host;\n const tasks = scoopTasks(lookup);\n const scoops = createScoops(host, () => tasks);\n let cached: Roles = { roles: [], warnings: [], limits: { ...DEFAULT_LIMITS } };\n registry.install(scoopsExtension(tasks));\n registry.install(guardExtension(lookup, fileTools));\n return {\n scoops,\n async attach(options, context) {\n const { harness, agents, groups, env, home } = options;\n const assets = options.assets ?? packageAssets();\n bind({\n harness,\n agents,\n licks,\n tools: fileTools,\n groups,\n reads: options.reads,\n files: env,\n ...(options.mcp ? { mcp: options.mcp } : {}),\n });\n const builtin = async () => {\n const out: { path: string; text: string }[] = [];\n for (const name of BUILTIN_ROLES) {\n const path = `packages/vfs-root/agents/${name}.md`;\n out.push({ path: `builtin:${name}`, text: await assets(path) });\n }\n return out;\n };\n const roles = async (using: Context) => {\n cached = await loadRoles(\n {\n files: env,\n builtin,\n dirs: [\n ...(await packageDirs(env, '/node_modules', using)).map((dir) => ({\n source: 'package' as const,\n dir,\n })),\n { source: 'user', dir: `${home}/.pi/agent/agents` },\n ],\n settingsPath: `${home}/.pi/agent/settings.json`,\n },\n using\n );\n return cached;\n };\n await roles(context).catch(() => cached);\n const script = await assets('bin/agent').catch(() => undefined);\n if (script) {\n const binDir = options.binDir ?? BIN_DIR;\n await installCommands(env, script, binDir, context);\n }\n const cli = createCli({\n env,\n harness,\n agents,\n scoops,\n roles: () => roles(context),\n ...(options.alive ? { alive: options.alive } : {}),\n ...(options.sprinkle ? { sprinkle: options.sprinkle } : {}),\n ...(options.memory ? { memory: options.memory } : {}),\n ...(options.gelatiere ? { gelatiere: options.gelatiere } : {}),\n ...(options.freezer ? { freezer: options.freezer } : {}),\n ...(options.models ? { models: options.models } : {}),\n });\n const plane = controlPlane(env, cli, {\n ...(options.controlDir ? { dir: options.controlDir } : {}),\n ...(options.sweepEvery ? { sweepEvery: options.sweepEvery } : {}),\n mirror: mirror(agents, env),\n });\n await plane.start(context);\n return { roles, plane, close: (using) => plane.close(using) };\n },\n };\n}\n\nexport type { Rewound, Scoops } from './service.ts';\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -3,6 +3,7 @@ import type { Agent } from './agent.ts';
3
3
  import type { ChangesRuntime } from './changes/index.ts';
4
4
  import { type HostLicks, type HostScoops } from './control.ts';
5
5
  import type { FreezerRuntime } from './freezer/index.ts';
6
+ import type { UserClients } from './kernel/users.ts';
6
7
  import type { McpRuntime } from './mcp/index.ts';
7
8
  import type { MemoryRuntime } from './memory/index.ts';
8
9
  import { AgentSettings } from './services.ts';
@@ -12,6 +13,7 @@ import type { PortEndpoint } from './wire.ts';
12
13
  export interface AgentHost {
13
14
  readonly serverId: string;
14
15
  readonly agent: Agent;
16
+ readonly users?: UserClients;
15
17
  connect(endpoint: PortEndpoint, options?: {
16
18
  readOnly?: boolean;
17
19
  }): void;
@@ -29,4 +31,5 @@ export declare function hostAgent(agent: Agent, options?: {
29
31
  freezer?: FreezerRuntime;
30
32
  changes?: ChangesRuntime;
31
33
  mcp?: Pick<McpRuntime, 'close'>;
34
+ users?: UserClients;
32
35
  }): Promise<AgentHost>;
@@ -6,10 +6,11 @@ export { CREDENTIALS_DATABASE, EncryptedCredentialStore } from './credentials.ts
6
6
  export { type AgentHost, hostAgent } from './host.ts';
7
7
  export type { KernelClient, KernelFs, KernelProcess, KernelStat, SpawnOptions, } from './kernel/client.ts';
8
8
  export { HOME, type KernelEnvOptions, kernelEnvironment, SliccKernelEnv } from './kernel/env.ts';
9
+ export { adminOver, type KernelAdmin, type KernelUser, type KernelUsers, serveAdmin, type UserClient, type UserClients, type UserConnect, type UserSpec, userClients, } from './kernel/users.ts';
9
10
  export { PortListener } from './listener.ts';
10
11
  export { type AgentWorkerOptions, type AgentWorkerScope, type KernelAttach, runAgentWorker, } from './main.ts';
11
12
  export { type Transport, type TransportResponse, transportFetch } from './net.ts';
12
- export { AGENT_LOCK, type AgentOwner, type AgentWorker, type OwnerOptions, startAgent, } from './owner.ts';
13
+ export { AGENT_LOCK, type AgentOwner, type AgentWorker, type KernelSource, type OwnerOptions, startAgent, } from './owner.ts';
13
14
  export { applyPatches, patchServerAccept } from './patches.ts';
14
15
  export { SliccPrompt, sliccPrompt } from './prompt.ts';
15
16
  export { type AccountState, AGENT_SESSION, AgentControl, AgentSessions, AgentSettings, type AgentSettingsChange, AgentTranscript, type BudgetState, type ModelChoice, type OperationError, type PromptResult, type SendMode, type SendRequest, type SendResponse, type SettingsState, type SignIn, } from './services.ts';
@@ -17,4 +18,4 @@ export { BEDROCK, createAgentSettings, createSliccModels, DEFAULT_MODEL, DEFAULT
17
18
  export { AGENT_DIRECTORY, type OpfsSqliteOptions, openMemorySqliteStorage, openOpfsSqliteStorage, WasmSqliteDatabase, } from './sqlite.ts';
18
19
  export { type SystemFacts, systemSection } from './system.ts';
19
20
  export { PortChannel, type PortEndpoint, withUnrefTimers } from './wire.ts';
20
- export { kernelPort, serveConnections, type WorkerScope } from './worker.ts';
21
+ export { type KernelPorts, kernelPort, kernelPorts, serveConnections, type WorkerScope, } from './worker.ts';
@@ -0,0 +1,53 @@
1
+ import type { PortEndpoint } from '../wire.ts';
2
+ import type { KernelClient } from './client.ts';
3
+ export interface KernelUser {
4
+ name: string;
5
+ uid: number;
6
+ gid: number;
7
+ home: string;
8
+ shell: string;
9
+ groups: number[];
10
+ umask?: number;
11
+ }
12
+ export interface UserSpec {
13
+ name: string;
14
+ home?: string;
15
+ groups?: string[];
16
+ umask?: number;
17
+ homeGroup?: string;
18
+ }
19
+ export interface KernelUsers {
20
+ add(spec: UserSpec): Promise<KernelUser>;
21
+ remove(name: string, options?: {
22
+ keepHome?: boolean;
23
+ }): Promise<boolean>;
24
+ list(): Promise<KernelUser[]>;
25
+ }
26
+ export interface UserConnect {
27
+ user?: string;
28
+ agentId?: string;
29
+ }
30
+ export interface KernelSource {
31
+ connect(options?: UserConnect): Promise<Transferable>;
32
+ users?: KernelUsers;
33
+ }
34
+ export interface KernelAdmin {
35
+ connect(options: UserConnect): Promise<MessagePort>;
36
+ users: KernelUsers;
37
+ close(): void;
38
+ }
39
+ export declare function serveAdmin(port: PortEndpoint, source: KernelSource): void;
40
+ export declare function adminOver(port: PortEndpoint): KernelAdmin;
41
+ export type UserClient = KernelClient & {
42
+ close?(options?: {
43
+ kill?: boolean;
44
+ }): unknown;
45
+ closed?: Promise<unknown>;
46
+ };
47
+ export interface UserClients {
48
+ readonly users: KernelUsers;
49
+ client(agentId: string, user: string): Promise<UserClient>;
50
+ drop(agentId: string): Promise<void>;
51
+ close(): Promise<void>;
52
+ }
53
+ export declare function userClients(admin: KernelAdmin, attach: (port: MessagePort) => Promise<UserClient>): UserClients;
@@ -2,6 +2,7 @@ import type { CredentialStore, Provider } from '@earendil-works/pi-ai';
2
2
  import { type ModelRef, type Storage } from '@earendil-works/pi-durable';
3
3
  import { type AgentHost } from './host.ts';
4
4
  import type { KernelClient } from './kernel/client.ts';
5
+ import { type UserClients } from './kernel/users.ts';
5
6
  import { type Transport } from './net.ts';
6
7
  import { type Assets } from './scoops/index.ts';
7
8
  import { type WorkerScope } from './worker.ts';
@@ -24,6 +25,9 @@ export interface AgentWorkerOptions {
24
25
  codemodeWasm?: () => Promise<WebAssembly.Module | undefined>;
25
26
  codemodeWorker?: string | URL;
26
27
  catalog?: string;
28
+ users?: boolean;
27
29
  }
30
+ export declare function usersOf(admin: MessagePort | undefined, wanted: boolean | undefined, attach: KernelAttach): UserClients | undefined;
31
+ export declare const STORE_DIR = "/.slicc";
28
32
  export declare function alive(client: KernelClient): (pid: number) => Promise<boolean>;
29
33
  export declare function runAgentWorker(scope: AgentWorkerScope, options?: AgentWorkerOptions): Promise<AgentHost>;
@@ -1,4 +1,5 @@
1
1
  import { type AgentConnection } from './client.ts';
2
+ import { type KernelSource } from './kernel/users.ts';
2
3
  import type { PortEndpoint } from './wire.ts';
3
4
  export declare const AGENT_LOCK = "slicc-agent";
4
5
  export interface AgentWorker {
@@ -14,9 +15,7 @@ export interface AgentOwner {
14
15
  restart(): Promise<void>;
15
16
  release(): Promise<void>;
16
17
  }
17
- export interface KernelSource {
18
- connect(): Promise<Transferable>;
19
- }
18
+ export type { KernelSource } from './kernel/users.ts';
20
19
  export interface OwnerOptions {
21
20
  worker: () => AgentWorker;
22
21
  kernel?: KernelSource;
@@ -10,6 +10,7 @@ import { type ControlPlane } from './requests.ts';
10
10
  import { type Scoops } from './service.ts';
11
11
  export declare const BUILTIN_ROLES: string[];
12
12
  export declare const PNPM_HOME = "/home/.local/share/pnpm";
13
+ export declare const BIN_DIR = "/usr/local/bin";
13
14
  export type Assets = (path: string) => Promise<string>;
14
15
  export declare function packageAssets(base?: URL): Assets;
15
16
  export interface AttachOptions {
@@ -19,7 +20,7 @@ export interface AttachOptions {
19
20
  env: ExecutionEnv;
20
21
  home: string;
21
22
  assets?: Assets;
22
- pnpmHome?: string;
23
+ binDir?: string;
23
24
  controlDir?: string;
24
25
  sweepEvery?: number;
25
26
  alive?: (pid: number) => Promise<boolean>;
@@ -42,5 +43,7 @@ export interface ScoopsSetup {
42
43
  }
43
44
  export declare const COMMANDS: string[];
44
45
  export declare function pnpmHomeOf(env: ExecutionEnv, context: Context): Promise<string>;
46
+ export declare function installCommands(env: ExecutionEnv, script: string, binDir: string, context: Context): Promise<boolean>;
47
+ export declare function retire(env: ExecutionEnv, binDir: string, context: Context): Promise<void>;
45
48
  export declare function setupScoops(registry: Registry, licks: Licks, fileTools?: readonly ToolRegistration[]): ScoopsSetup;
46
49
  export type { Rewound, Scoops } from './service.ts';
@@ -3,4 +3,9 @@ export interface WorkerScope {
3
3
  addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;
4
4
  }
5
5
  export declare function serveConnections(scope: WorkerScope, host: Promise<AgentHost>): void;
6
+ export interface KernelPorts {
7
+ kernel: MessagePort;
8
+ admin?: MessagePort;
9
+ }
10
+ export declare function kernelPorts(scope: WorkerScope): Promise<KernelPorts>;
6
11
  export declare function kernelPort(scope: WorkerScope): Promise<MessagePort>;
package/dist/worker.js CHANGED
@@ -9,16 +9,22 @@ function serveConnections(scope, host) {
9
9
  );
10
10
  });
11
11
  }
12
- function kernelPort(scope) {
12
+ function kernelPorts(scope) {
13
13
  return new Promise((resolve) => {
14
14
  scope.addEventListener("message", ({ data }) => {
15
- const port = data?.kernel;
16
- if (port) resolve(port);
15
+ const message = data;
16
+ const kernel = message?.kernel;
17
+ if (!kernel) return;
18
+ resolve(message.admin ? { kernel, admin: message.admin } : { kernel });
17
19
  });
18
20
  });
19
21
  }
22
+ function kernelPort(scope) {
23
+ return kernelPorts(scope).then((ports) => ports.kernel);
24
+ }
20
25
  export {
21
26
  kernelPort,
27
+ kernelPorts,
22
28
  serveConnections
23
29
  };
24
30
  //# sourceMappingURL=worker.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/worker.ts"],
4
- "sourcesContent": ["import type { AgentHost } from './host.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface WorkerScope {\n addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;\n}\n\nexport function serveConnections(scope: WorkerScope, host: Promise<AgentHost>): void {\n scope.addEventListener('message', ({ data }) => {\n const message = data as { connect?: PortEndpoint; readOnly?: boolean } | null;\n const port = message?.connect;\n if (!port) return;\n host.then(\n (ready) => ready.connect(port, { readOnly: message?.readOnly === true }),\n () => port.close?.()\n );\n });\n}\n\nexport function kernelPort(scope: WorkerScope): Promise<MessagePort> {\n return new Promise((resolve) => {\n scope.addEventListener('message', ({ data }) => {\n const port = (data as { kernel?: MessagePort } | null)?.kernel;\n if (port) resolve(port);\n });\n });\n}\n"],
5
- "mappings": "AAOO,SAAS,iBAAiB,OAAoB,MAAgC;AACnF,QAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,UAAM,UAAU;AAChB,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,KAAM;AACX,SAAK;AAAA,MACH,CAAC,UAAU,MAAM,QAAQ,MAAM,EAAE,UAAU,SAAS,aAAa,KAAK,CAAC;AAAA,MACvE,MAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAEO,SAAS,WAAW,OAA0C;AACnE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,YAAM,OAAQ,MAA0C;AACxD,UAAI,KAAM,SAAQ,IAAI;AAAA,IACxB,CAAC;AAAA,EACH,CAAC;AACH;",
4
+ "sourcesContent": ["import type { AgentHost } from './host.ts';\nimport type { PortEndpoint } from './wire.ts';\n\nexport interface WorkerScope {\n addEventListener(type: 'message', listener: (event: MessageEvent) => void): void;\n}\n\nexport function serveConnections(scope: WorkerScope, host: Promise<AgentHost>): void {\n scope.addEventListener('message', ({ data }) => {\n const message = data as { connect?: PortEndpoint; readOnly?: boolean } | null;\n const port = message?.connect;\n if (!port) return;\n host.then(\n (ready) => ready.connect(port, { readOnly: message?.readOnly === true }),\n () => port.close?.()\n );\n });\n}\n\nexport interface KernelPorts {\n kernel: MessagePort;\n admin?: MessagePort;\n}\n\nexport function kernelPorts(scope: WorkerScope): Promise<KernelPorts> {\n return new Promise((resolve) => {\n scope.addEventListener('message', ({ data }) => {\n const message = data as { kernel?: MessagePort; admin?: MessagePort } | null;\n const kernel = message?.kernel;\n if (!kernel) return;\n resolve(message.admin ? { kernel, admin: message.admin } : { kernel });\n });\n });\n}\n\nexport function kernelPort(scope: WorkerScope): Promise<MessagePort> {\n return kernelPorts(scope).then((ports) => ports.kernel);\n}\n"],
5
+ "mappings": "AAOO,SAAS,iBAAiB,OAAoB,MAAgC;AACnF,QAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,UAAM,UAAU;AAChB,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,KAAM;AACX,SAAK;AAAA,MACH,CAAC,UAAU,MAAM,QAAQ,MAAM,EAAE,UAAU,SAAS,aAAa,KAAK,CAAC;AAAA,MACvE,MAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAOO,SAAS,YAAY,OAA0C;AACpE,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,iBAAiB,WAAW,CAAC,EAAE,KAAK,MAAM;AAC9C,YAAM,UAAU;AAChB,YAAM,SAAS,SAAS;AACxB,UAAI,CAAC,OAAQ;AACb,cAAQ,QAAQ,QAAQ,EAAE,QAAQ,OAAO,QAAQ,MAAM,IAAI,EAAE,OAAO,CAAC;AAAA,IACvE,CAAC;AAAA,EACH,CAAC;AACH;AAEO,SAAS,WAAW,OAA0C;AACnE,SAAO,YAAY,KAAK,EAAE,KAAK,CAAC,UAAU,MAAM,MAAM;AACxD;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-agent",
3
- "version": "3.34.0",
3
+ "version": "3.35.0",
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",