@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 +18 -1
- package/dist/host.js +2 -0
- package/dist/host.js.map +2 -2
- package/dist/index.js +14 -1
- package/dist/index.js.map +2 -2
- package/dist/kernel/users.js +113 -0
- package/dist/kernel/users.js.map +7 -0
- package/dist/main.js +30 -8
- package/dist/main.js.map +2 -2
- package/dist/owner.js +19 -2
- package/dist/owner.js.map +2 -2
- package/dist/scoops/index.js +28 -8
- package/dist/scoops/index.js.map +2 -2
- package/dist/types/host.d.ts +3 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/kernel/users.d.ts +53 -0
- package/dist/types/main.d.ts +4 -0
- package/dist/types/owner.d.ts +2 -3
- package/dist/types/scoops/index.d.ts +4 -1
- package/dist/types/worker.d.ts +5 -0
- package/dist/worker.js +9 -3
- package/dist/worker.js.map +2 -2
- package/package.json +1 -1
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
|
|
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": "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;
|
|
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": "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",
|
|
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 {
|
|
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
|
|
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,
|
|
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 {
|
|
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,
|
|
63
|
-
const
|
|
64
|
-
const
|
|
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,
|
|
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,
|
|
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
|
|
5
|
-
"mappings": "AAAA,SAA+B,oBAAoB;AACnD,SAAS,gBAAgB;AAGlB,MAAM,aAAa;
|
|
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
|
}
|
package/dist/scoops/index.js
CHANGED
|
@@ -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,
|
|
39
|
-
await env.createDir(
|
|
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 = `${
|
|
42
|
-
await env.writeFile(path, script, context);
|
|
43
|
-
await env.exec(["chmod", "
|
|
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
|
|
123
|
-
await
|
|
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
|
package/dist/scoops/index.js.map
CHANGED
|
@@ -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
|
|
5
|
-
"mappings": "AAGA,SAAsB,YAAY;AAGlC,SAAS,gBAAgB,WAAW,mBAA+B;AACnE,SAA0B,WAAW,eAAe;AACpD,SAAS,gBAAgB,iBAAiB,kBAAkB;AAC5D,SAA4B,
|
|
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
|
}
|
package/dist/types/host.d.ts
CHANGED
|
@@ -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>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/types/main.d.ts
CHANGED
|
@@ -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>;
|
package/dist/types/owner.d.ts
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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';
|
package/dist/types/worker.d.ts
CHANGED
|
@@ -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
|
|
12
|
+
function kernelPorts(scope) {
|
|
13
13
|
return new Promise((resolve) => {
|
|
14
14
|
scope.addEventListener("message", ({ data }) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
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
|
package/dist/worker.js.map
CHANGED
|
@@ -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
|
|
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;
|
|
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