@ai-ecoverse/slicc-agent 3.47.3 → 3.47.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -186,7 +186,7 @@ A **cone** is a top-level agent the user talks to; a **scoop** is a helper agent
186
186
 
187
187
  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.
188
188
 
189
- **The `agent` command.** One bash script is installed under seven names, `agent`, `subagent`, `memory`, `gelatiere`, `freezer`, `models` and `panel`, 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. A file at one of those paths that isn't slicc-agent's (it lacks the `slicc-agent/1` request marker), such as a root global package's `memory`, is left alone, with one warning per boot in the worker's console. 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`, or `tab:$SLICC_TAB` from a terminal that has only that, 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 (with an optional `<id>.err`, the answer's stdout is `<id>.out` and its stderr `<id>.err`); 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.
189
+ **The `agent` command.** One bash script is installed under seven names, `agent`, `subagent`, `memory`, `gelatiere`, `freezer`, `models` and `panel`, 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. A file at one of those paths that isn't slicc-agent's (it lacks the `slicc-agent/1` request marker), such as a root global package's `memory`, is left alone, with one warning per boot in the worker's console. 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`, or `tab:$SLICC_TAB` from a terminal that has only that, 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 (with an optional `<id>.err`, the answer's stdout is `<id>.out` and its stderr `<id>.err`); 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, and `PLAYWRIGHT_CLI_SESSION` with the same agent id, so each agent's `playwright-cli` keeps its own current tab (slicc-cdp #129). The user's terminals get none of these. `/var/lib/slicc/agent/scoops/<handle>/metadata.json` mirrors each scoop's state for scripts.
190
190
  - `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.
191
191
  - `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.
192
192
  - 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".
@@ -16,7 +16,10 @@ function identity(agents, fallback) {
16
16
  return async (target, context) => {
17
17
  const out = {};
18
18
  const caller = callerOf(agents(), target.conversationId);
19
- if (caller) out.SLICC_AGENT = caller;
19
+ if (caller) {
20
+ out.SLICC_AGENT = caller;
21
+ out.PLAYWRIGHT_CLI_SESSION = caller;
22
+ }
20
23
  const read = target.read;
21
24
  const stored = read && target.conversationId !== void 0 ? await read.snapshot(AgentDoc, target.conversationId, context) : void 0;
22
25
  const model = stored?.model ?? fallback;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/scoops/identity.ts"],
4
- "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n AgentDoc,\n type ConversationId,\n type DocumentReader,\n type ModelRef,\n} from '@earendil-works/pi-durable';\nimport type { Agents } from '../agents.ts';\nimport type { EnvTargetLike } from '../kernel/env.ts';\n\nexport function callerOf(\n agents: Agents | undefined,\n conversation: number | undefined\n): string | undefined {\n if (!agents || conversation === undefined) return undefined;\n const state = agents.state();\n const cone = Object.entries(state.cones).find(\n ([, record]) => record.conversation === conversation\n )?.[0];\n if (cone) return `cone:${cone}`;\n return Object.entries(state.scoops).find(\n ([, record]) => record.conversation === conversation\n )?.[0];\n}\n\nexport function identity(agents: () => Agents | undefined, fallback: ModelRef) {\n return async (target: EnvTargetLike, context: Context): Promise<Record<string, string>> => {\n const out: Record<string, string> = {};\n const caller = callerOf(agents(), target.conversationId);\n if (caller) out.SLICC_AGENT = caller;\n const read = target.read as DocumentReader | undefined;\n const stored =\n read && target.conversationId !== undefined\n ? await read.snapshot(AgentDoc, target.conversationId as ConversationId, context)\n : undefined;\n const model = stored?.model ?? fallback;\n out.PI_PROVIDER = model.provider;\n out.PI_MODEL = model.modelId;\n out.PI_REASONING_LEVEL = stored?.thinkingLevel ?? 'off';\n return out;\n };\n}\n"],
5
- "mappings": "AACA;AAAA,EACE;AAAA,OAIK;AAIA,SAAS,SACd,QACA,cACoB;AACpB,MAAI,CAAC,UAAU,iBAAiB,OAAW,QAAO;AAClD,QAAM,QAAQ,OAAO,MAAM;AAC3B,QAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,EAAE;AAAA,IACvC,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,iBAAiB;AAAA,EAC1C,IAAI,CAAC;AACL,MAAI,KAAM,QAAO,QAAQ,IAAI;AAC7B,SAAO,OAAO,QAAQ,MAAM,MAAM,EAAE;AAAA,IAClC,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,iBAAiB;AAAA,EAC1C,IAAI,CAAC;AACP;AAEO,SAAS,SAAS,QAAkC,UAAoB;AAC7E,SAAO,OAAO,QAAuB,YAAsD;AACzF,UAAM,MAA8B,CAAC;AACrC,UAAM,SAAS,SAAS,OAAO,GAAG,OAAO,cAAc;AACvD,QAAI,OAAQ,KAAI,cAAc;AAC9B,UAAM,OAAO,OAAO;AACpB,UAAM,SACJ,QAAQ,OAAO,mBAAmB,SAC9B,MAAM,KAAK,SAAS,UAAU,OAAO,gBAAkC,OAAO,IAC9E;AACN,UAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAI,cAAc,MAAM;AACxB,QAAI,WAAW,MAAM;AACrB,QAAI,qBAAqB,QAAQ,iBAAiB;AAClD,WAAO;AAAA,EACT;AACF;",
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport {\n AgentDoc,\n type ConversationId,\n type DocumentReader,\n type ModelRef,\n} from '@earendil-works/pi-durable';\nimport type { Agents } from '../agents.ts';\nimport type { EnvTargetLike } from '../kernel/env.ts';\n\nexport function callerOf(\n agents: Agents | undefined,\n conversation: number | undefined\n): string | undefined {\n if (!agents || conversation === undefined) return undefined;\n const state = agents.state();\n const cone = Object.entries(state.cones).find(\n ([, record]) => record.conversation === conversation\n )?.[0];\n if (cone) return `cone:${cone}`;\n return Object.entries(state.scoops).find(\n ([, record]) => record.conversation === conversation\n )?.[0];\n}\n\nexport function identity(agents: () => Agents | undefined, fallback: ModelRef) {\n return async (target: EnvTargetLike, context: Context): Promise<Record<string, string>> => {\n const out: Record<string, string> = {};\n const caller = callerOf(agents(), target.conversationId);\n if (caller) {\n out.SLICC_AGENT = caller;\n out.PLAYWRIGHT_CLI_SESSION = caller;\n }\n const read = target.read as DocumentReader | undefined;\n const stored =\n read && target.conversationId !== undefined\n ? await read.snapshot(AgentDoc, target.conversationId as ConversationId, context)\n : undefined;\n const model = stored?.model ?? fallback;\n out.PI_PROVIDER = model.provider;\n out.PI_MODEL = model.modelId;\n out.PI_REASONING_LEVEL = stored?.thinkingLevel ?? 'off';\n return out;\n };\n}\n"],
5
+ "mappings": "AACA;AAAA,EACE;AAAA,OAIK;AAIA,SAAS,SACd,QACA,cACoB;AACpB,MAAI,CAAC,UAAU,iBAAiB,OAAW,QAAO;AAClD,QAAM,QAAQ,OAAO,MAAM;AAC3B,QAAM,OAAO,OAAO,QAAQ,MAAM,KAAK,EAAE;AAAA,IACvC,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,iBAAiB;AAAA,EAC1C,IAAI,CAAC;AACL,MAAI,KAAM,QAAO,QAAQ,IAAI;AAC7B,SAAO,OAAO,QAAQ,MAAM,MAAM,EAAE;AAAA,IAClC,CAAC,CAAC,EAAE,MAAM,MAAM,OAAO,iBAAiB;AAAA,EAC1C,IAAI,CAAC;AACP;AAEO,SAAS,SAAS,QAAkC,UAAoB;AAC7E,SAAO,OAAO,QAAuB,YAAsD;AACzF,UAAM,MAA8B,CAAC;AACrC,UAAM,SAAS,SAAS,OAAO,GAAG,OAAO,cAAc;AACvD,QAAI,QAAQ;AACV,UAAI,cAAc;AAClB,UAAI,yBAAyB;AAAA,IAC/B;AACA,UAAM,OAAO,OAAO;AACpB,UAAM,SACJ,QAAQ,OAAO,mBAAmB,SAC9B,MAAM,KAAK,SAAS,UAAU,OAAO,gBAAkC,OAAO,IAC9E;AACN,UAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAI,cAAc,MAAM;AACxB,QAAI,WAAW,MAAM;AACrB,QAAI,qBAAqB,QAAQ,iBAAiB;AAClD,WAAO;AAAA,EACT;AACF;",
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.47.3",
3
+ "version": "3.47.4",
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.13.1",
66
- "@ai-ecoverse/slicc-spectrum": "1.65.2",
66
+ "@ai-ecoverse/slicc-spectrum": "1.66.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",