@ai-ecoverse/slicc-agent 3.33.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 +24 -2
- package/bin/agent +1 -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 +46 -21
- package/dist/main.js.map +2 -2
- package/dist/models/index.js +182 -0
- package/dist/models/index.js.map +7 -0
- package/dist/owner.js +19 -2
- package/dist/owner.js.map +2 -2
- package/dist/scoops/cli.js +2 -0
- package/dist/scoops/cli.js.map +2 -2
- package/dist/scoops/index.js +39 -10
- package/dist/scoops/index.js.map +2 -2
- package/dist/scoops/requests.js +1 -1
- package/dist/scoops/requests.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/models/index.d.ts +16 -0
- package/dist/types/owner.d.ts +2 -3
- package/dist/types/scoops/cli.d.ts +1 -0
- package/dist/types/scoops/index.d.ts +5 -1
- package/dist/types/scoops/requests.d.ts +1 -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 +2 -2
- package/packages/vfs-root/skills/agent/SKILL.md +2 -0
package/dist/scoops/requests.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const CONTROL_DIR = "/var/lib/slicc/agent/requests";
|
|
2
2
|
const PROTOCOL = "slicc-agent/1";
|
|
3
3
|
const STALE_MS = 10 * 6e4;
|
|
4
|
-
const COMMAND_NAMES = /* @__PURE__ */ new Set(["subagent", "sprinkle", "memory", "gelatiere", "freezer"]);
|
|
4
|
+
const COMMAND_NAMES = /* @__PURE__ */ new Set(["subagent", "sprinkle", "memory", "gelatiere", "freezer", "models"]);
|
|
5
5
|
const HEADER = 6;
|
|
6
6
|
function parseRequest(id, bytes) {
|
|
7
7
|
const decoder = new TextDecoder();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/scoops/requests.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Answer } from './service.ts';\n\nexport const CONTROL_DIR = '/var/lib/slicc/agent/requests';\nexport const PROTOCOL = 'slicc-agent/1';\nexport const STALE_MS = 10 * 60_000;\nconst COMMAND_NAMES = new Set(['subagent', 'sprinkle', 'memory', 'gelatiere', 'freezer']);\n\nexport interface Request {\n id: string;\n as: 'agent' | 'subagent' | 'sprinkle' | 'memory' | 'gelatiere' | 'freezer';\n caller: string;\n cwd: string;\n pid: number | null;\n argv: string[];\n stdin: string;\n}\n\nconst HEADER = 6;\n\nexport function parseRequest(id: string, bytes: Uint8Array): Request | undefined {\n const decoder = new TextDecoder();\n const fields: string[] = [];\n let at = 0;\n while (fields.length < HEADER) {\n const end = bytes.indexOf(0, at);\n if (end < 0) return undefined;\n fields.push(decoder.decode(bytes.subarray(at, end)));\n at = end + 1;\n }\n const [version, as, caller, cwd, pid, count] = fields;\n const argc = Number(count);\n if (version !== PROTOCOL || !Number.isInteger(argc) || argc < 0) return undefined;\n const argv: string[] = [];\n while (argv.length < argc) {\n const end = bytes.indexOf(0, at);\n if (end < 0) return undefined;\n argv.push(decoder.decode(bytes.subarray(at, end)));\n at = end + 1;\n }\n const process = Number(pid);\n return {\n id,\n as: COMMAND_NAMES.has(as as string) ? (as as Request['as']) : 'agent',\n caller: caller as string,\n cwd: cwd || '/',\n pid: Number.isInteger(process) && process > 0 ? process : null,\n argv,\n stdin: decoder.decode(bytes.subarray(at)),\n };\n}\n\nexport interface Runner {\n run(request: Request, context: Context): Promise<Answer>;\n blocking(request: Request): boolean;\n}\n\nexport interface ControlPlane {\n start(context: Context): Promise<void>;\n sweep(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface PlaneOptions {\n dir?: string;\n now?: () => number;\n sweepEvery?: number;\n mirror?: (context: Context) => Promise<void>;\n}\n\nexport function controlPlane(\n env: ExecutionEnv,\n runner: Runner,\n options: PlaneOptions = {}\n): ControlPlane {\n const dir = options.dir ?? CONTROL_DIR;\n const requests = `${dir}/in`;\n const responses = `${dir}/out`;\n const now = options.now ?? Date.now;\n const handled = new Set<string>();\n let watcher: FileWatcher | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n let lock: Promise<unknown> = Promise.resolve();\n const serial = <T>(operation: () => Promise<T>): Promise<T> => {\n const next = lock.then(operation, operation);\n lock = next.catch(() => undefined);\n return next;\n };\n\n async function answer(id: string, result: Answer, context: Context) {\n await env.writeFile(`${responses}/${id}.out`, result.out, context);\n await env.writeFile(`${responses}/${id}.code`, String(result.code), context);\n await env.remove(`${requests}/${id}`, { force: true }, context);\n await env.remove(`${responses}/${id}.ack`, { force: true }, context);\n await options.mirror?.(context).catch(() => undefined);\n }\n\n async function handle(id: string, context: Context) {\n if (handled.has(id)) return;\n handled.add(id);\n try {\n const bytes = await env.readBinaryFile(`${requests}/${id}`, context);\n if (!bytes.ok) return;\n await env.writeFile(`${responses}/${id}.ack`, '', context);\n const request = parseRequest(id, bytes.value);\n if (!request) {\n await answer(\n id,\n { code: 2, out: 'agent: this request is not understood; update the agent command\\n' },\n context\n );\n return;\n }\n const result = runner.blocking(request)\n ? await runner.run(request, context)\n : await serial(() => runner.run(request, context));\n await answer(id, result, context);\n } finally {\n handled.delete(id);\n }\n }\n\n async function scan(context: Context) {\n const listed = await env.listDir(requests, context);\n if (!listed.ok) return;\n for (const entry of listed.value.sort((a, b) => a.name.localeCompare(b.name)))\n if (entry.kind === 'file' && !entry.name.startsWith('.'))\n void handle(entry.name, context).catch(() => undefined);\n }\n\n async function sweep(context: Context) {\n for (const folder of [requests, responses]) {\n const listed = await env.listDir(folder, context);\n if (!listed.ok) continue;\n for (const entry of listed.value) {\n const stale = now() - entry.mtimeMs > STALE_MS;\n const removable = folder === responses || entry.name.startsWith('.tmp-');\n if (stale && removable)\n await env.remove(`${folder}/${entry.name}`, { force: true }, context);\n }\n }\n }\n\n return {\n async start(context) {\n await env.createDir(requests, { recursive: true }, context);\n await env.createDir(responses, { recursive: true }, context);\n const leftovers = await env.listDir(requests, context);\n if (leftovers.ok)\n for (const entry of leftovers.value)\n if (entry.name.startsWith('.tmp-'))\n await env.remove(`${requests}/${entry.name}`, { force: true }, context);\n await sweep(context);\n const watched = await env.watch(\n [{ path: requests }],\n () => void scan(context).catch(() => undefined),\n context\n );\n if (watched.ok) watcher = watched.value;\n await scan(context);\n timer = setInterval(\n () => void sweep(context).catch(() => undefined),\n options.sweepEvery ?? 60_000\n );\n },\n sweep,\n async close(context) {\n clearInterval(timer);\n await watcher?.close(context);\n await lock;\n },\n };\n}\n"],
|
|
5
|
-
"mappings": "AAIO,MAAM,cAAc;AACpB,MAAM,WAAW;AACjB,MAAM,WAAW,KAAK;AAC7B,MAAM,gBAAgB,oBAAI,IAAI,CAAC,YAAY,YAAY,UAAU,aAAa,
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv, FileWatcher } from '@earendil-works/pi-durable/env';\nimport type { Answer } from './service.ts';\n\nexport const CONTROL_DIR = '/var/lib/slicc/agent/requests';\nexport const PROTOCOL = 'slicc-agent/1';\nexport const STALE_MS = 10 * 60_000;\nconst COMMAND_NAMES = new Set(['subagent', 'sprinkle', 'memory', 'gelatiere', 'freezer', 'models']);\n\nexport interface Request {\n id: string;\n as: 'agent' | 'subagent' | 'sprinkle' | 'memory' | 'gelatiere' | 'freezer' | 'models';\n caller: string;\n cwd: string;\n pid: number | null;\n argv: string[];\n stdin: string;\n}\n\nconst HEADER = 6;\n\nexport function parseRequest(id: string, bytes: Uint8Array): Request | undefined {\n const decoder = new TextDecoder();\n const fields: string[] = [];\n let at = 0;\n while (fields.length < HEADER) {\n const end = bytes.indexOf(0, at);\n if (end < 0) return undefined;\n fields.push(decoder.decode(bytes.subarray(at, end)));\n at = end + 1;\n }\n const [version, as, caller, cwd, pid, count] = fields;\n const argc = Number(count);\n if (version !== PROTOCOL || !Number.isInteger(argc) || argc < 0) return undefined;\n const argv: string[] = [];\n while (argv.length < argc) {\n const end = bytes.indexOf(0, at);\n if (end < 0) return undefined;\n argv.push(decoder.decode(bytes.subarray(at, end)));\n at = end + 1;\n }\n const process = Number(pid);\n return {\n id,\n as: COMMAND_NAMES.has(as as string) ? (as as Request['as']) : 'agent',\n caller: caller as string,\n cwd: cwd || '/',\n pid: Number.isInteger(process) && process > 0 ? process : null,\n argv,\n stdin: decoder.decode(bytes.subarray(at)),\n };\n}\n\nexport interface Runner {\n run(request: Request, context: Context): Promise<Answer>;\n blocking(request: Request): boolean;\n}\n\nexport interface ControlPlane {\n start(context: Context): Promise<void>;\n sweep(context: Context): Promise<void>;\n close(context: Context): Promise<void>;\n}\n\nexport interface PlaneOptions {\n dir?: string;\n now?: () => number;\n sweepEvery?: number;\n mirror?: (context: Context) => Promise<void>;\n}\n\nexport function controlPlane(\n env: ExecutionEnv,\n runner: Runner,\n options: PlaneOptions = {}\n): ControlPlane {\n const dir = options.dir ?? CONTROL_DIR;\n const requests = `${dir}/in`;\n const responses = `${dir}/out`;\n const now = options.now ?? Date.now;\n const handled = new Set<string>();\n let watcher: FileWatcher | undefined;\n let timer: ReturnType<typeof setInterval> | undefined;\n let lock: Promise<unknown> = Promise.resolve();\n const serial = <T>(operation: () => Promise<T>): Promise<T> => {\n const next = lock.then(operation, operation);\n lock = next.catch(() => undefined);\n return next;\n };\n\n async function answer(id: string, result: Answer, context: Context) {\n await env.writeFile(`${responses}/${id}.out`, result.out, context);\n await env.writeFile(`${responses}/${id}.code`, String(result.code), context);\n await env.remove(`${requests}/${id}`, { force: true }, context);\n await env.remove(`${responses}/${id}.ack`, { force: true }, context);\n await options.mirror?.(context).catch(() => undefined);\n }\n\n async function handle(id: string, context: Context) {\n if (handled.has(id)) return;\n handled.add(id);\n try {\n const bytes = await env.readBinaryFile(`${requests}/${id}`, context);\n if (!bytes.ok) return;\n await env.writeFile(`${responses}/${id}.ack`, '', context);\n const request = parseRequest(id, bytes.value);\n if (!request) {\n await answer(\n id,\n { code: 2, out: 'agent: this request is not understood; update the agent command\\n' },\n context\n );\n return;\n }\n const result = runner.blocking(request)\n ? await runner.run(request, context)\n : await serial(() => runner.run(request, context));\n await answer(id, result, context);\n } finally {\n handled.delete(id);\n }\n }\n\n async function scan(context: Context) {\n const listed = await env.listDir(requests, context);\n if (!listed.ok) return;\n for (const entry of listed.value.sort((a, b) => a.name.localeCompare(b.name)))\n if (entry.kind === 'file' && !entry.name.startsWith('.'))\n void handle(entry.name, context).catch(() => undefined);\n }\n\n async function sweep(context: Context) {\n for (const folder of [requests, responses]) {\n const listed = await env.listDir(folder, context);\n if (!listed.ok) continue;\n for (const entry of listed.value) {\n const stale = now() - entry.mtimeMs > STALE_MS;\n const removable = folder === responses || entry.name.startsWith('.tmp-');\n if (stale && removable)\n await env.remove(`${folder}/${entry.name}`, { force: true }, context);\n }\n }\n }\n\n return {\n async start(context) {\n await env.createDir(requests, { recursive: true }, context);\n await env.createDir(responses, { recursive: true }, context);\n const leftovers = await env.listDir(requests, context);\n if (leftovers.ok)\n for (const entry of leftovers.value)\n if (entry.name.startsWith('.tmp-'))\n await env.remove(`${requests}/${entry.name}`, { force: true }, context);\n await sweep(context);\n const watched = await env.watch(\n [{ path: requests }],\n () => void scan(context).catch(() => undefined),\n context\n );\n if (watched.ok) watcher = watched.value;\n await scan(context);\n timer = setInterval(\n () => void sweep(context).catch(() => undefined),\n options.sweepEvery ?? 60_000\n );\n },\n sweep,\n async close(context) {\n clearInterval(timer);\n await watcher?.close(context);\n await lock;\n },\n };\n}\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>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context } from '@earendil-works/chord';
|
|
2
|
+
import type { Models } from '@earendil-works/pi-ai/models';
|
|
3
|
+
import type { Agents } from '../agents.ts';
|
|
4
|
+
import type { AgentSettings } from '../services.ts';
|
|
5
|
+
export type Answer = {
|
|
6
|
+
code: number;
|
|
7
|
+
out: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const USAGE: string;
|
|
10
|
+
export interface ModelsOptions {
|
|
11
|
+
agents: Agents;
|
|
12
|
+
settings: Pick<AgentSettings, 'state'>;
|
|
13
|
+
catalog: Pick<Models, 'getProviders' | 'getModels'>;
|
|
14
|
+
}
|
|
15
|
+
export declare function closest(wanted: string, ids: readonly string[], count?: number): string[];
|
|
16
|
+
export declare function modelsCommand(options: ModelsOptions): (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
|
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;
|
|
@@ -23,6 +23,7 @@ export interface CliOptions {
|
|
|
23
23
|
memory?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
|
|
24
24
|
gelatiere?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
|
|
25
25
|
freezer?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
|
|
26
|
+
models?: (argv: readonly string[], caller: string | null, context: Context) => Promise<Answer>;
|
|
26
27
|
}
|
|
27
28
|
export type Deps = CliOptions & {
|
|
28
29
|
now: () => number;
|
|
@@ -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>;
|
|
@@ -28,6 +29,7 @@ export interface AttachOptions {
|
|
|
28
29
|
memory?: CliOptions['memory'];
|
|
29
30
|
gelatiere?: CliOptions['gelatiere'];
|
|
30
31
|
freezer?: CliOptions['freezer'];
|
|
32
|
+
models?: CliOptions['models'];
|
|
31
33
|
mcp?: (names: readonly string[]) => ToolRegistration[];
|
|
32
34
|
}
|
|
33
35
|
export interface ScoopsRuntime {
|
|
@@ -41,5 +43,7 @@ export interface ScoopsSetup {
|
|
|
41
43
|
}
|
|
42
44
|
export declare const COMMANDS: string[];
|
|
43
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>;
|
|
44
48
|
export declare function setupScoops(registry: Registry, licks: Licks, fileTools?: readonly ToolRegistration[]): ScoopsSetup;
|
|
45
49
|
export type { Rewound, Scoops } from './service.ts';
|
|
@@ -6,7 +6,7 @@ export declare const PROTOCOL = "slicc-agent/1";
|
|
|
6
6
|
export declare const STALE_MS: number;
|
|
7
7
|
export interface Request {
|
|
8
8
|
id: string;
|
|
9
|
-
as: 'agent' | 'subagent' | 'sprinkle' | 'memory' | 'gelatiere' | 'freezer';
|
|
9
|
+
as: 'agent' | 'subagent' | 'sprinkle' | 'memory' | 'gelatiere' | 'freezer' | 'models';
|
|
10
10
|
caller: string;
|
|
11
11
|
cwd: string;
|
|
12
12
|
pid: number | null;
|
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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-agent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.35.0",
|
|
4
4
|
"description": "SLICC's agent core on pi durable: an agent worker, session storage, remoting and pi extensions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@ai-ecoverse/slicc-kernel": "1.47.1",
|
|
65
65
|
"@ai-ecoverse/slicc-shared-web": "1.12.1",
|
|
66
|
-
"@ai-ecoverse/slicc-spectrum": "1.
|
|
66
|
+
"@ai-ecoverse/slicc-spectrum": "1.53.0",
|
|
67
67
|
"@ai-ecoverse/wasm-bash": "5.3.0-17",
|
|
68
68
|
"@ai-ecoverse/wasm-coreutils": "9.12.0-5",
|
|
69
69
|
"@ai-ecoverse/wasm-git": "2.55.0-15",
|
|
@@ -44,6 +44,8 @@ It returns at once, and one `scoop-wait` lick brings all their answers together.
|
|
|
44
44
|
|
|
45
45
|
A scoop starts with your provider, model and thinking level. Use `--model provider/model`, `--thinking` or `--effort` only when you mean to choose differently. Never pass `$PI_PROVIDER`, `$PI_MODEL` or `$PI_REASONING_LEVEL` back explicitly.
|
|
46
46
|
|
|
47
|
+
`models` lists the models you can use, `models current` prints yours, and `models use <provider/model> [--thinking <level>]` switches your own model, as the Settings picker does.
|
|
48
|
+
|
|
47
49
|
Without `--tools`, a scoop gets read, write, edit and bash; `--tools read,bash` is an allowlist. grep, find and ls map to bash, and bash can change files, so no tool list is truly read-only. A scoop's read, write and edit tools reach only its folder, /tmp and its working folder, and read /home; its bash is not confined, and the scoop is told so.
|
|
48
50
|
|
|
49
51
|
## Inspect, talk, stop
|