@ai-ecoverse/slicc-agent 3.45.2 → 3.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -447,9 +447,9 @@ The process table is the worker's root client's `ps()`. Each process is named af
447
447
 
448
448
  **The feed.** The transcript service adds `monitor`, a `MonitorFeed` with these parts:
449
449
  - `usage`;
450
- - `agents`, each with running, queued, tool, retry, last error, model and context tokens;
450
+ - `agents`, each with running, queued, tool, retry, last error, model, context tokens and, on kernels that report CPU times, the CPU share of its processes;
451
451
  - `tasks`;
452
- - `processes`;
452
+ - `processes`, with each one's CPU times and share of a core on kernels that report them (see CPU);
453
453
  - `problems`, the newest 50 failed tasks, retries and failed turns since the panel opened;
454
454
  - `paused`.
455
455
 
@@ -471,14 +471,17 @@ The process table is the worker's root client's `ps()`. Each process is named af
471
471
  | Processes in one agent's group | over 32 | over 64 |
472
472
  | Processes in the kernel | over 128 | over 256 |
473
473
  | A zombie | after 60 s | |
474
- | A background process of an agent | after 30 min | after an hour |
474
+ | A background process of an agent, on kernels without CPU times | after 30 min | after an hour |
475
+ | An agent's process group at 90% of a core or more, on kernels with CPU times | for 2 min | for 4 min, or at 180% |
475
476
  | Context | 80% | |
476
477
  | A paused scheduler | always | |
477
478
 
478
479
  - **Sections:** cones and scoops, tasks as a tree per cone, processes, recent problems, pending changes and sprinkles. Each row has an `id`, and agents and tasks have a `depth` (at most 6), which spectrum (≥ 1.57.0) draws as indentation.
479
480
  - **More sections:** `createAgentModel(connection, { monitor: { extra } })` adds the page's own sections, such as terminals, browser tabs and tray followers.
480
481
 
481
- **Memory.** From slicc-kernel 1.61.0, `ps()` entries carry `rss`, each process's wasm memory. When they do, the monitor shows a Process memory vital and each process row's size. On older kernels, both are left out. `/proc/meminfo`'s `MemTotal`, CPU times and load are placeholders, so the runaway alerts count processes and their age instead of measuring CPU. The tray chip gets no `spent` or `rate`, so spectrum (≥ 1.57.0) shows only what's known.
482
+ **CPU.** From slicc-kernel 1.67.1, `ps()` entries carry `utime` and `stime`, each process's CPU time in milliseconds. The feed passes them on, and each process's `cpu` is its share of one core between the last two polls: `null` on the first poll, or when a pid is restarted or reused. An agent's `cpu` sums its processes. The adapter remembers since when each agent's process group has been at 90% of a core or more, and raises `runaway-cpu-<pgid>`, "research is using a lot of CPU", once that has lasted 2 min. With CPU times, an idle long-running process raises no alert. On older kernels, none of these fields appear, and the age alert stays.
483
+
484
+ **Memory.** From slicc-kernel 1.61.0, `ps()` entries carry `rss`, each process's wasm memory. When they do, the monitor shows a Process memory vital and each process row's size. On older kernels, both are left out. `/proc/meminfo`'s `MemTotal` is a placeholder. The tray chip gets no `spent` or `rate`, so spectrum (≥ 1.57.0) shows only what's known.
482
485
 
483
486
  ### Sprinkles
484
487
 
@@ -552,7 +555,7 @@ The agent never holds a secret's value. Values live in the vault (`vault.sliccy.
552
555
 
553
556
  ## The kernel
554
557
 
555
- `@ai-ecoverse/slicc-kernel` is a peer dependency (`>=1.47.1 <2`, the first kernel with users and the H1 wasm commands; until 3.31.0 the floor was 1.26.3): the agent only calls `attachKernel`, the client end of the page kernel's port, so it must match the kernel the page runs. Seven chooses that version: slicc-bios pins the certified kernel next to the agent in `src/packages/agent/package.json`, and pnpm fills the peer from that pin. The devDependency is the lowest certified kernel the range allows (1.47.1), and the unit and integration tests run on it with the H1 wasm commands as devDependencies. A second CI job reruns the integration tests on the newest certified kernel (`NEWEST_CERTIFIED_KERNEL` in `.github/workflows/ci.yml`), with the wasm commands certified for it (`NEWEST_CERTIFIED_WASM`). Today the floor is 1.47.1 and the newest certified kernel 1.65.2; the second job moves by hand to each newer certified kernel, so both ends of the range are tested. If the port protocol ever breaks within 1.x, a patch release narrows the upper bound. Renovate opens PRs for the kernel, `wasi-pnpm`, the `wasm-*` packages and `slicc-cdp` but never merges them, because they move only after the homescoop coordinator certifies them.
558
+ `@ai-ecoverse/slicc-kernel` is a peer dependency (`>=1.47.1 <2`, the first kernel with users and the H1 wasm commands; until 3.31.0 the floor was 1.26.3): the agent only calls `attachKernel`, the client end of the page kernel's port, so it must match the kernel the page runs. Seven chooses that version: slicc-bios pins the certified kernel next to the agent in `src/packages/agent/package.json`, and pnpm fills the peer from that pin. The devDependency is the lowest certified kernel the range allows (1.47.1), and the unit and integration tests run on it with the H1 wasm commands as devDependencies. A second CI job reruns the integration tests on the newest certified kernel (`NEWEST_CERTIFIED_KERNEL` in `.github/workflows/ci.yml`), with the wasm commands certified for it (`NEWEST_CERTIFIED_WASM`). Today the floor is 1.47.1 and the newest certified kernel 1.67.1; the second job moves by hand to each newer certified kernel, so both ends of the range are tested. If the port protocol ever breaks within 1.x, a patch release narrows the upper bound. Renovate opens PRs for the kernel, `wasi-pnpm`, the `wasm-*` packages and `slicc-cdp` but never merges them, because they move only after the homescoop coordinator certifies them.
556
559
 
557
560
  ## Patched dependencies
558
561
 
@@ -4,6 +4,30 @@ import {
4
4
  import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
5
5
  import { live } from "../agents.js";
6
6
  import { commandLine, program, redacted } from "./redact.js";
7
+ function timed(entry) {
8
+ return typeof entry.utime === "number" && typeof entry.stime === "number";
9
+ }
10
+ function cpuShares(entries, previous, at) {
11
+ const marks = /* @__PURE__ */ new Map();
12
+ const shares = /* @__PURE__ */ new Map();
13
+ for (const entry of entries) {
14
+ if (!timed(entry)) continue;
15
+ const mark = { started: entry.started ?? 0, total: entry.utime + entry.stime, at };
16
+ const last = previous.get(entry.pid);
17
+ marks.set(entry.pid, mark);
18
+ shares.set(
19
+ entry.pid,
20
+ last && last.started === mark.started && mark.total >= last.total && at > last.at ? Math.round((mark.total - last.total) / (at - last.at) * 1e3) / 1e3 : null
21
+ );
22
+ }
23
+ return { marks, shares };
24
+ }
25
+ function agentCpu(processes, agentId) {
26
+ if (!processes.some((row) => typeof row.cpu === "number")) return null;
27
+ let sum = 0;
28
+ for (const row of processes) if (row.agentId === agentId) sum += row.cpu ?? 0;
29
+ return Math.round(sum * 1e3) / 1e3;
30
+ }
7
31
  const TTL_MS = 3e4;
8
32
  const PS_MS = 2e3;
9
33
  const PS_TIMEOUT_MS = 5e3;
@@ -97,6 +121,7 @@ class Session {
97
121
  #graph = { tasks: {} };
98
122
  #usage = null;
99
123
  #processes = null;
124
+ #cpu = { marks: /* @__PURE__ */ new Map(), shares: /* @__PURE__ */ new Map() };
100
125
  #kernel;
101
126
  #users = /* @__PURE__ */ new Map();
102
127
  #paused = false;
@@ -201,6 +226,7 @@ class Session {
201
226
  this.#settings.timers.clear(timeout);
202
227
  this.#handles.delete(timeout);
203
228
  this.#processes = entries;
229
+ if (entries) this.#cpu = cpuShares(entries, this.#cpu.marks, this.#settings.now());
204
230
  this.#kernel = entries ? "ok" : "unreachable";
205
231
  this.schedule();
206
232
  this.#later(() => this.#poll(), this.#settings.psMs);
@@ -329,7 +355,8 @@ class Session {
329
355
  started: entry.started ?? 0,
330
356
  zombie: zombie ? this.#since(`zombie:${entry.pid}`) : null,
331
357
  tty: Boolean(entry.tty),
332
- rss: typeof entry.rss === "number" ? entry.rss : null
358
+ rss: typeof entry.rss === "number" ? entry.rss : null,
359
+ ...timed(entry) ? { utime: entry.utime, stime: entry.stime, cpu: this.#cpu.shares.get(entry.pid) ?? null } : {}
333
360
  };
334
361
  }
335
362
  #emit() {
@@ -353,7 +380,10 @@ class Session {
353
380
  for (const pgid of this.#options.groups?.owned(agent.conversation) ?? [])
354
381
  groups.set(pgid, agent.id);
355
382
  const programs = /* @__PURE__ */ new Map();
356
- const processes = this.#processes?.map((entry) => this.#process(entry, groups, programs)) ?? null;
383
+ const entries = this.#processes;
384
+ const processes = entries?.map((entry) => this.#process(entry, groups, programs)) ?? null;
385
+ if (entries?.some(timed))
386
+ for (const row of rows) row.cpu = agentCpu(processes, row.id);
357
387
  this.#seen = this.#next;
358
388
  const feed = {
359
389
  open: true,
@@ -449,6 +479,8 @@ export {
449
479
  THROTTLE_MS,
450
480
  TTL_MS,
451
481
  USAGE_MS,
482
+ agentCpu,
483
+ cpuShares,
452
484
  createMonitor,
453
485
  emptyFeed,
454
486
  globalTimers,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/monitor/index.ts"],
4
- "sourcesContent": ["import {\n type Context,\n type JsonValue,\n type ReplicatedState,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type {\n CommitPublication,\n ConversationView,\n Harness,\n TaskGraph,\n TaskGraphNode,\n TaskGraphWatch,\n TaskRecord,\n UsageState,\n} from '@earendil-works/pi-durable';\nimport { type AgentsState, live } from '../agents.ts';\nimport type {\n MonitorAgent,\n MonitorFeed,\n MonitorLease,\n MonitorProblem,\n MonitorProcess,\n MonitorTask,\n} from '../services.ts';\nimport { commandLine, program, redacted } from './redact.ts';\n\nexport interface PsEntry {\n pid: number;\n ppid?: number;\n pgid?: number;\n argv?: readonly string[];\n tty?: unknown;\n started?: number;\n state?: string;\n uid?: number;\n rss?: number;\n}\n\nexport interface Timers {\n set(run: () => void, ms: number): unknown;\n clear(handle: unknown): void;\n}\n\nexport interface MonitorOptions {\n harness: Pick<Harness, 'watchTaskGraph' | 'usage' | 'subscribeCommits' | 'inspect'>;\n agents: { state(): Readonly<AgentsState>; onChange(listener: () => void): () => void };\n views: ReplicatedState<Record<string, ConversationView>>;\n kernel?: { ps?(): Promise<readonly PsEntry[]> };\n groups?: { owned(owner: number): number[] };\n users?: () => Promise<readonly { name: string; uid: number }[]>;\n secrets?: () => readonly string[];\n now?: () => number;\n timers?: Timers;\n ttlMs?: number;\n psMs?: number;\n psTimeoutMs?: number;\n throttleMs?: number;\n usageMs?: number;\n context?: Context;\n}\n\nexport interface Monitor {\n readonly state: ReplicatedState<MonitorFeed>;\n readonly viewState: ReplicatedState<MonitorFeed>;\n open(lease: string | null, resync: boolean, context: Context): Promise<MonitorLease>;\n close(lease: string, context: Context): Promise<void>;\n active(): boolean;\n dispose(): Promise<void>;\n}\n\nexport const TTL_MS = 30000;\nexport const PS_MS = 2000;\nexport const PS_TIMEOUT_MS = 5000;\nexport const THROTTLE_MS = 1000;\nexport const USAGE_MS = 2000;\nexport const PROBLEMS_MAX = 50;\n\nexport const globalTimers: Timers = {\n set: (run, ms) => setTimeout(run, ms),\n clear: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n};\n\nexport function emptyFeed(): MonitorFeed {\n return {\n open: false,\n at: 0,\n usage: null,\n agents: [],\n tasks: [],\n processes: null,\n kernel: 'checking',\n problems: [],\n paused: false,\n };\n}\n\ninterface Live {\n run?: unknown;\n generation?: { attempt: number; retry?: { at: number; error: string } };\n tools?: { name: string; status: string; taskId?: unknown }[];\n}\n\ninterface ModelMessage {\n stopReason?: string;\n errorMessage?: string;\n usage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number };\n}\n\nexport function totals(usage: UsageState): { tokens: number; cost: number; free: boolean } {\n let tokens = 0;\n let cost = 0;\n for (const bucket of [usage.models, usage.tools])\n for (const entry of Object.values(bucket)) {\n tokens += entry.totalTokens ?? 0;\n cost += entry.cost?.total ?? 0;\n }\n return { tokens, cost, free: cost === 0 };\n}\n\nfunction phaseOf(node: TaskGraphNode): string {\n return 'phase' in node.state ? node.state.phase : node.state.outcome;\n}\n\nfunction contextOf(message: ModelMessage): number | null {\n const usage = message.usage;\n if (!usage) return null;\n const parts = [usage.input, usage.output, usage.cacheRead, usage.cacheWrite];\n const total = parts.reduce<number>((sum, part) => sum + (part ?? 0), 0);\n return total > 0 ? total : null;\n}\n\nfunction lastAssistant(view: ConversationView | undefined) {\n const entries = view?.entries ?? [];\n for (let at = entries.length - 1; at >= 0; at--) {\n const entry = entries[at] as (typeof entries)[number];\n if (entry.kind === 'pi.assistant')\n return { id: String(entry.id), message: (entry.model?.[0] ?? {}) as ModelMessage };\n }\n return undefined;\n}\n\nfunction conversations(state: Readonly<AgentsState>): Map<number, string> {\n const out = new Map<number, string>();\n for (const [id, scoop] of Object.entries(state.scoops)) out.set(scoop.conversation, id);\n for (const [id, cone] of Object.entries(state.cones)) out.set(cone.conversation, id);\n return out;\n}\n\nfunction liveAgents(state: Readonly<AgentsState>) {\n const cones = Object.entries(state.cones).map(([id, cone]) => ({\n id,\n name: cone.name,\n kind: 'cone' as const,\n parentId: null,\n conversation: cone.conversation,\n }));\n const scoops = Object.entries(state.scoops)\n .filter(([, scoop]) => live(scoop))\n .map(([id, scoop]) => ({\n id,\n name: scoop.name,\n kind: 'scoop' as const,\n parentId: scoop.parent,\n conversation: scoop.conversation,\n }));\n return [...cones, ...scoops];\n}\n\nexport function narrowed(feed: MonitorFeed, programs: ReadonlyMap<number, string>): MonitorFeed {\n if (!feed.processes) return feed;\n return {\n ...feed,\n processes: feed.processes.map((row) => ({ ...row, command: programs.get(row.pid) ?? '' })),\n };\n}\n\ninterface Settings {\n now: () => number;\n timers: Timers;\n context: Context;\n psMs: number;\n psTimeoutMs: number;\n throttleMs: number;\n usageMs: number;\n secrets: () => readonly string[];\n}\n\ntype Agent = ReturnType<typeof liveAgents>[number];\n\nclass Session {\n stopped = false;\n readonly #options: MonitorOptions;\n readonly #settings: Settings;\n readonly #publish: (feed: MonitorFeed, view: MonitorFeed) => void;\n readonly #off: (() => void)[] = [];\n readonly #handles = new Set<unknown>();\n #watch: TaskGraphWatch | undefined;\n #graph: TaskGraph = { tasks: {} };\n #usage: UsageState | null = null;\n #processes: readonly PsEntry[] | null = null;\n #kernel: MonitorFeed['kernel'];\n #users = new Map<number, string>();\n #paused = false;\n #problems: MonitorProblem[] = [];\n #seen = new Map<string, number>();\n #next = new Map<string, number>();\n #build: unknown;\n #usageTimer: unknown;\n #lastBuild = Number.NEGATIVE_INFINITY;\n #last = '';\n\n constructor(\n options: MonitorOptions,\n settings: Settings,\n publish: (feed: MonitorFeed, view: MonitorFeed) => void\n ) {\n this.#options = options;\n this.#settings = settings;\n this.#publish = publish;\n this.#kernel = options.kernel?.ps ? 'checking' : 'unreachable';\n }\n\n start(): void {\n const options = this.#options;\n this.#off.push(\n options.harness.subscribeCommits((publication) => this.#commit(publication)),\n options.agents.onChange(() => this.schedule()),\n options.views.subscribe(() => this.schedule())\n );\n void options.harness.watchTaskGraph(this.#settings.context).then(\n (watch) => this.#watching(watch),\n () => undefined\n );\n void options.users?.().then(\n (list) => {\n this.#users = new Map(list.map((user) => [user.uid, user.name]));\n this.schedule();\n },\n () => undefined\n );\n this.#poll();\n this.refresh();\n }\n\n stop(): void {\n this.stopped = true;\n for (const off of this.#off) off();\n for (const handle of this.#handles) this.#settings.timers.clear(handle);\n this.#handles.clear();\n void this.#watch?.stop();\n }\n\n refresh(): void {\n void this.#readUsage();\n void this.#options.harness.inspect(this.#settings.context).then(\n (inspection) => {\n this.#paused = inspection.scheduling === 'paused';\n this.schedule();\n },\n () => undefined\n );\n this.schedule();\n }\n\n schedule(): void {\n if (this.stopped || this.#build !== undefined) return;\n const wait = Math.max(0, this.#lastBuild + this.#settings.throttleMs - this.#settings.now());\n this.#build = this.#later(() => {\n this.#build = undefined;\n this.#emit();\n }, wait);\n }\n\n #later(task: () => void, ms: number): unknown {\n if (this.stopped) return undefined;\n const handle = this.#settings.timers.set(() => {\n this.#handles.delete(handle);\n if (!this.stopped) task();\n }, ms);\n this.#handles.add(handle);\n return handle;\n }\n\n #watching(watch: TaskGraphWatch): void {\n if (this.stopped) {\n void watch.stop();\n return;\n }\n this.#watch = watch;\n this.#graph = watch.value;\n this.schedule();\n watch.start(async (graph) => {\n this.#graph = graph;\n this.schedule();\n });\n }\n\n #readUsage(): Promise<void> {\n return this.#options.harness.usage(this.#settings.context).then(\n (usage) => {\n this.#usage = usage;\n this.schedule();\n },\n () => undefined\n );\n }\n\n #poll(): void {\n const kernel = this.#options.kernel;\n if (!kernel?.ps) return;\n let settled = false;\n const settle = (entries: readonly PsEntry[] | null) => {\n if (settled || this.stopped) return;\n settled = true;\n this.#settings.timers.clear(timeout);\n this.#handles.delete(timeout);\n this.#processes = entries;\n this.#kernel = entries ? 'ok' : 'unreachable';\n this.schedule();\n this.#later(() => this.#poll(), this.#settings.psMs);\n };\n const timeout = this.#later(() => settle(null), this.#settings.psTimeoutMs);\n kernel.ps().then(settle, () => settle(null));\n }\n\n #problem(entry: MonitorProblem): void {\n if (this.#problems.some((known) => known.id === entry.id)) return;\n this.#problems.unshift(entry);\n this.#problems.length = Math.min(this.#problems.length, PROBLEMS_MAX);\n }\n\n #commit(publication: CommitPublication): void {\n let changed = false;\n for (const change of publication.changes) {\n if (change.type === 'task') changed = this.#failed(change.value) || changed;\n else if (change.type === 'document' && change.record.kind === 'pi.usage')\n this.#usageChanged();\n }\n if (changed) this.schedule();\n }\n\n #failed(task: TaskRecord<JsonValue, JsonValue, JsonValue>): boolean {\n if (task.state.status !== 'terminal') return false;\n const outcome = task.state.outcome;\n if (outcome.status !== 'faulted' && outcome.status !== 'orphaned') return false;\n this.#problem({\n id: `task:${task.id}`,\n at: this.#settings.now(),\n agentId: conversations(this.#options.agents.state()).get(task.conversationId) ?? null,\n kind: 'task',\n message: redacted(\n outcome.status === 'faulted' ? outcome.error.message : outcome.reason,\n this.#settings.secrets()\n ),\n });\n return true;\n }\n\n #usageChanged(): void {\n if (this.#usageTimer !== undefined) return;\n this.#usageTimer = this.#later(() => {\n this.#usageTimer = undefined;\n void this.#readUsage();\n }, this.#settings.usageMs);\n }\n\n #since(key: string): number {\n const at = this.#seen.get(key) ?? this.#settings.now();\n this.#next.set(key, at);\n return at;\n }\n\n #agent(agent: Agent, view: ConversationView | undefined, tools: Map<string, string>) {\n const secrets = this.#settings.secrets();\n const liveDoc = view?.docs['pi.live'] as Live | undefined;\n for (const slot of liveDoc?.tools ?? [])\n if (slot.taskId !== undefined) tools.set(String(slot.taskId), slot.name);\n const inbox = view?.docs['pi.inbox'] as { items?: unknown[] } | undefined;\n const doc = view?.docs['pi.agent'] as\n | { model?: { provider: string; modelId: string } }\n | undefined;\n const generation = liveDoc?.generation;\n const retry = generation?.retry\n ? {\n attempt: generation.attempt,\n since: this.#since(`retry:${agent.id}`),\n error: redacted(generation.retry.error, secrets),\n }\n : null;\n if (retry)\n this.#problem({\n id: `retry:${agent.id}:${retry.since}`,\n at: retry.since,\n agentId: agent.id,\n kind: 'retry',\n message: retry.error,\n });\n const last = lastAssistant(view);\n const failed =\n last?.message.stopReason === 'error'\n ? redacted(last.message.errorMessage || 'error', secrets)\n : null;\n if (failed && last)\n this.#problem({\n id: `turn:${last.id}`,\n at: this.#settings.now(),\n agentId: agent.id,\n kind: 'turn',\n message: failed,\n });\n return {\n id: agent.id,\n name: agent.name,\n kind: agent.kind,\n parentId: agent.parentId,\n model: doc?.model ? `${doc.model.provider}/${doc.model.modelId}` : null,\n running: Boolean(liveDoc?.run),\n queued: inbox?.items?.length ?? 0,\n tool: liveDoc?.tools?.find((slot) => slot.status === 'running')?.name ?? null,\n retry,\n failed,\n context: last ? contextOf(last.message) : null,\n };\n }\n\n #task(node: TaskGraphNode, owners: Map<number, string>, details: Map<string, string>) {\n const id = String(node.id);\n const status = node.state.status;\n return {\n id,\n kind: node.kind,\n detail: details.get(id) ?? null,\n agentId: owners.get(node.conversationId) ?? null,\n owner: node.owner === undefined ? null : String(node.owner),\n status,\n phase: phaseOf(node),\n background: node.background,\n aborting: node.abortRequested ? this.#since(`abort:${id}`) : null,\n since: this.#since(`task:${id}:${status}`),\n waits: node.state.status === 'waiting' ? node.state.on.length : 0,\n };\n }\n\n #process(entry: PsEntry, groups: Map<number, string>, programs: Map<number, string>) {\n const argv = entry.argv ?? [];\n const pgid = entry.pgid ?? entry.pid;\n const zombie = entry.state === 'Z';\n programs.set(entry.pid, program(argv));\n const uid = entry.uid;\n return {\n pid: entry.pid,\n ppid: entry.ppid ?? 0,\n pgid,\n user:\n uid === undefined ? null : (this.#users.get(uid) ?? (uid === 0 ? 'root' : `uid ${uid}`)),\n agentId: groups.get(pgid) ?? null,\n command: commandLine(argv, this.#settings.secrets()),\n state: zombie ? ('Z' as const) : ('S' as const),\n started: entry.started ?? 0,\n zombie: zombie ? this.#since(`zombie:${entry.pid}`) : null,\n tty: Boolean(entry.tty),\n rss: typeof entry.rss === 'number' ? entry.rss : null,\n };\n }\n\n #emit(): void {\n this.#lastBuild = this.#settings.now();\n this.#next = new Map();\n const registry = this.#options.agents.state();\n const views = this.#options.views.value ?? {};\n const agents = liveAgents(registry);\n const details = new Map<string, string>();\n const rows: MonitorAgent[] = agents.map((agent) =>\n this.#agent(agent, views[agent.id], details)\n );\n for (const scoop of Object.values(registry.scoops))\n details.set(String(scoop.anchor), scoop.name);\n const owners = conversations(registry);\n const tasks: MonitorTask[] = Object.values(this.#graph.tasks).map((node) =>\n this.#task(node, owners, details)\n );\n const groups = new Map<number, string>();\n for (const agent of agents)\n for (const pgid of this.#options.groups?.owned(agent.conversation) ?? [])\n groups.set(pgid, agent.id);\n const programs = new Map<number, string>();\n const processes: MonitorProcess[] | null =\n this.#processes?.map((entry) => this.#process(entry, groups, programs)) ?? null;\n this.#seen = this.#next;\n const feed: MonitorFeed = {\n open: true,\n at: this.#lastBuild,\n usage: this.#usage ? totals(this.#usage) : null,\n agents: rows,\n tasks,\n processes,\n kernel: this.#kernel,\n problems: [...this.#problems],\n paused: this.#paused,\n };\n const key = JSON.stringify({ ...feed, at: 0 });\n if (key === this.#last) return;\n this.#last = key;\n this.#publish(feed, narrowed(feed, programs));\n }\n}\n\nexport function createMonitor(options: MonitorOptions): Monitor {\n const settings: Settings = {\n now: options.now ?? Date.now,\n timers: options.timers ?? globalTimers,\n context: options.context ?? BACKGROUND_CONTEXT,\n psMs: options.psMs ?? PS_MS,\n psTimeoutMs: options.psTimeoutMs ?? PS_TIMEOUT_MS,\n throttleMs: options.throttleMs ?? THROTTLE_MS,\n usageMs: options.usageMs ?? USAGE_MS,\n secrets: () => options.secrets?.() ?? [],\n };\n const { now, timers, context } = settings;\n const ttlMs = options.ttlMs ?? TTL_MS;\n const state = replicatedState<MonitorFeed>(emptyFeed());\n const viewState = replicatedState<MonitorFeed>(emptyFeed());\n const leases = new Map<string, number>();\n let session: Session | undefined;\n let sweep: unknown;\n const publish = (feed: MonitorFeed, view: MonitorFeed) => {\n state.replace(context, feed);\n viewState.replace(context, view);\n };\n const stop = () => {\n if (sweep !== undefined) timers.clear(sweep);\n sweep = undefined;\n const current = session;\n if (!current) return;\n session = undefined;\n current.stop();\n publish(\n { ...(state.value as MonitorFeed), open: false },\n { ...(viewState.value as MonitorFeed), open: false }\n );\n };\n const arm = () => {\n if (sweep !== undefined) timers.clear(sweep);\n sweep = timers.set(expire, Math.max(0, Math.min(...leases.values()) - now()));\n };\n const expire = () => {\n sweep = undefined;\n const at = now();\n for (const [lease, until] of [...leases]) if (until <= at) leases.delete(lease);\n if (leases.size) arm();\n else stop();\n };\n return {\n state,\n viewState,\n async open(lease, resync) {\n const id = lease ?? crypto.randomUUID();\n leases.set(id, now() + ttlMs);\n arm();\n if (!session) {\n session = new Session(options, settings, publish);\n session.start();\n } else if (resync) session.refresh();\n return { lease: id, ttlMs };\n },\n async close(lease) {\n if (!leases.delete(lease)) return;\n if (leases.size) arm();\n else stop();\n },\n active: () => session !== undefined,\n async dispose() {\n leases.clear();\n stop();\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n type Context,\n type JsonValue,\n type ReplicatedState,\n replicatedState,\n} from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type {\n CommitPublication,\n ConversationView,\n Harness,\n TaskGraph,\n TaskGraphNode,\n TaskGraphWatch,\n TaskRecord,\n UsageState,\n} from '@earendil-works/pi-durable';\nimport { type AgentsState, live } from '../agents.ts';\nimport type {\n MonitorAgent,\n MonitorFeed,\n MonitorLease,\n MonitorProblem,\n MonitorProcess,\n MonitorTask,\n} from '../services.ts';\nimport { commandLine, program, redacted } from './redact.ts';\n\nexport interface PsEntry {\n pid: number;\n ppid?: number;\n pgid?: number;\n argv?: readonly string[];\n tty?: unknown;\n started?: number;\n state?: string;\n uid?: number;\n rss?: number;\n utime?: number;\n stime?: number;\n}\n\nexport interface CpuMark {\n started: number;\n total: number;\n at: number;\n}\n\nexport interface CpuReading {\n marks: Map<number, CpuMark>;\n shares: Map<number, number | null>;\n}\n\nfunction timed(entry: PsEntry): entry is PsEntry & { utime: number; stime: number } {\n return typeof entry.utime === 'number' && typeof entry.stime === 'number';\n}\n\nexport function cpuShares(\n entries: readonly PsEntry[],\n previous: ReadonlyMap<number, CpuMark>,\n at: number\n): CpuReading {\n const marks = new Map<number, CpuMark>();\n const shares = new Map<number, number | null>();\n for (const entry of entries) {\n if (!timed(entry)) continue;\n const mark = { started: entry.started ?? 0, total: entry.utime + entry.stime, at };\n const last = previous.get(entry.pid);\n marks.set(entry.pid, mark);\n shares.set(\n entry.pid,\n last && last.started === mark.started && mark.total >= last.total && at > last.at\n ? Math.round(((mark.total - last.total) / (at - last.at)) * 1000) / 1000\n : null\n );\n }\n return { marks, shares };\n}\n\nexport function agentCpu(processes: readonly MonitorProcess[], agentId: string): number | null {\n if (!processes.some((row) => typeof row.cpu === 'number')) return null;\n let sum = 0;\n for (const row of processes) if (row.agentId === agentId) sum += row.cpu ?? 0;\n return Math.round(sum * 1000) / 1000;\n}\n\nexport interface Timers {\n set(run: () => void, ms: number): unknown;\n clear(handle: unknown): void;\n}\n\nexport interface MonitorOptions {\n harness: Pick<Harness, 'watchTaskGraph' | 'usage' | 'subscribeCommits' | 'inspect'>;\n agents: { state(): Readonly<AgentsState>; onChange(listener: () => void): () => void };\n views: ReplicatedState<Record<string, ConversationView>>;\n kernel?: { ps?(): Promise<readonly PsEntry[]> };\n groups?: { owned(owner: number): number[] };\n users?: () => Promise<readonly { name: string; uid: number }[]>;\n secrets?: () => readonly string[];\n now?: () => number;\n timers?: Timers;\n ttlMs?: number;\n psMs?: number;\n psTimeoutMs?: number;\n throttleMs?: number;\n usageMs?: number;\n context?: Context;\n}\n\nexport interface Monitor {\n readonly state: ReplicatedState<MonitorFeed>;\n readonly viewState: ReplicatedState<MonitorFeed>;\n open(lease: string | null, resync: boolean, context: Context): Promise<MonitorLease>;\n close(lease: string, context: Context): Promise<void>;\n active(): boolean;\n dispose(): Promise<void>;\n}\n\nexport const TTL_MS = 30000;\nexport const PS_MS = 2000;\nexport const PS_TIMEOUT_MS = 5000;\nexport const THROTTLE_MS = 1000;\nexport const USAGE_MS = 2000;\nexport const PROBLEMS_MAX = 50;\n\nexport const globalTimers: Timers = {\n set: (run, ms) => setTimeout(run, ms),\n clear: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n};\n\nexport function emptyFeed(): MonitorFeed {\n return {\n open: false,\n at: 0,\n usage: null,\n agents: [],\n tasks: [],\n processes: null,\n kernel: 'checking',\n problems: [],\n paused: false,\n };\n}\n\ninterface Live {\n run?: unknown;\n generation?: { attempt: number; retry?: { at: number; error: string } };\n tools?: { name: string; status: string; taskId?: unknown }[];\n}\n\ninterface ModelMessage {\n stopReason?: string;\n errorMessage?: string;\n usage?: { input?: number; output?: number; cacheRead?: number; cacheWrite?: number };\n}\n\nexport function totals(usage: UsageState): { tokens: number; cost: number; free: boolean } {\n let tokens = 0;\n let cost = 0;\n for (const bucket of [usage.models, usage.tools])\n for (const entry of Object.values(bucket)) {\n tokens += entry.totalTokens ?? 0;\n cost += entry.cost?.total ?? 0;\n }\n return { tokens, cost, free: cost === 0 };\n}\n\nfunction phaseOf(node: TaskGraphNode): string {\n return 'phase' in node.state ? node.state.phase : node.state.outcome;\n}\n\nfunction contextOf(message: ModelMessage): number | null {\n const usage = message.usage;\n if (!usage) return null;\n const parts = [usage.input, usage.output, usage.cacheRead, usage.cacheWrite];\n const total = parts.reduce<number>((sum, part) => sum + (part ?? 0), 0);\n return total > 0 ? total : null;\n}\n\nfunction lastAssistant(view: ConversationView | undefined) {\n const entries = view?.entries ?? [];\n for (let at = entries.length - 1; at >= 0; at--) {\n const entry = entries[at] as (typeof entries)[number];\n if (entry.kind === 'pi.assistant')\n return { id: String(entry.id), message: (entry.model?.[0] ?? {}) as ModelMessage };\n }\n return undefined;\n}\n\nfunction conversations(state: Readonly<AgentsState>): Map<number, string> {\n const out = new Map<number, string>();\n for (const [id, scoop] of Object.entries(state.scoops)) out.set(scoop.conversation, id);\n for (const [id, cone] of Object.entries(state.cones)) out.set(cone.conversation, id);\n return out;\n}\n\nfunction liveAgents(state: Readonly<AgentsState>) {\n const cones = Object.entries(state.cones).map(([id, cone]) => ({\n id,\n name: cone.name,\n kind: 'cone' as const,\n parentId: null,\n conversation: cone.conversation,\n }));\n const scoops = Object.entries(state.scoops)\n .filter(([, scoop]) => live(scoop))\n .map(([id, scoop]) => ({\n id,\n name: scoop.name,\n kind: 'scoop' as const,\n parentId: scoop.parent,\n conversation: scoop.conversation,\n }));\n return [...cones, ...scoops];\n}\n\nexport function narrowed(feed: MonitorFeed, programs: ReadonlyMap<number, string>): MonitorFeed {\n if (!feed.processes) return feed;\n return {\n ...feed,\n processes: feed.processes.map((row) => ({ ...row, command: programs.get(row.pid) ?? '' })),\n };\n}\n\ninterface Settings {\n now: () => number;\n timers: Timers;\n context: Context;\n psMs: number;\n psTimeoutMs: number;\n throttleMs: number;\n usageMs: number;\n secrets: () => readonly string[];\n}\n\ntype Agent = ReturnType<typeof liveAgents>[number];\n\nclass Session {\n stopped = false;\n readonly #options: MonitorOptions;\n readonly #settings: Settings;\n readonly #publish: (feed: MonitorFeed, view: MonitorFeed) => void;\n readonly #off: (() => void)[] = [];\n readonly #handles = new Set<unknown>();\n #watch: TaskGraphWatch | undefined;\n #graph: TaskGraph = { tasks: {} };\n #usage: UsageState | null = null;\n #processes: readonly PsEntry[] | null = null;\n #cpu: CpuReading = { marks: new Map(), shares: new Map() };\n #kernel: MonitorFeed['kernel'];\n #users = new Map<number, string>();\n #paused = false;\n #problems: MonitorProblem[] = [];\n #seen = new Map<string, number>();\n #next = new Map<string, number>();\n #build: unknown;\n #usageTimer: unknown;\n #lastBuild = Number.NEGATIVE_INFINITY;\n #last = '';\n\n constructor(\n options: MonitorOptions,\n settings: Settings,\n publish: (feed: MonitorFeed, view: MonitorFeed) => void\n ) {\n this.#options = options;\n this.#settings = settings;\n this.#publish = publish;\n this.#kernel = options.kernel?.ps ? 'checking' : 'unreachable';\n }\n\n start(): void {\n const options = this.#options;\n this.#off.push(\n options.harness.subscribeCommits((publication) => this.#commit(publication)),\n options.agents.onChange(() => this.schedule()),\n options.views.subscribe(() => this.schedule())\n );\n void options.harness.watchTaskGraph(this.#settings.context).then(\n (watch) => this.#watching(watch),\n () => undefined\n );\n void options.users?.().then(\n (list) => {\n this.#users = new Map(list.map((user) => [user.uid, user.name]));\n this.schedule();\n },\n () => undefined\n );\n this.#poll();\n this.refresh();\n }\n\n stop(): void {\n this.stopped = true;\n for (const off of this.#off) off();\n for (const handle of this.#handles) this.#settings.timers.clear(handle);\n this.#handles.clear();\n void this.#watch?.stop();\n }\n\n refresh(): void {\n void this.#readUsage();\n void this.#options.harness.inspect(this.#settings.context).then(\n (inspection) => {\n this.#paused = inspection.scheduling === 'paused';\n this.schedule();\n },\n () => undefined\n );\n this.schedule();\n }\n\n schedule(): void {\n if (this.stopped || this.#build !== undefined) return;\n const wait = Math.max(0, this.#lastBuild + this.#settings.throttleMs - this.#settings.now());\n this.#build = this.#later(() => {\n this.#build = undefined;\n this.#emit();\n }, wait);\n }\n\n #later(task: () => void, ms: number): unknown {\n if (this.stopped) return undefined;\n const handle = this.#settings.timers.set(() => {\n this.#handles.delete(handle);\n if (!this.stopped) task();\n }, ms);\n this.#handles.add(handle);\n return handle;\n }\n\n #watching(watch: TaskGraphWatch): void {\n if (this.stopped) {\n void watch.stop();\n return;\n }\n this.#watch = watch;\n this.#graph = watch.value;\n this.schedule();\n watch.start(async (graph) => {\n this.#graph = graph;\n this.schedule();\n });\n }\n\n #readUsage(): Promise<void> {\n return this.#options.harness.usage(this.#settings.context).then(\n (usage) => {\n this.#usage = usage;\n this.schedule();\n },\n () => undefined\n );\n }\n\n #poll(): void {\n const kernel = this.#options.kernel;\n if (!kernel?.ps) return;\n let settled = false;\n const settle = (entries: readonly PsEntry[] | null) => {\n if (settled || this.stopped) return;\n settled = true;\n this.#settings.timers.clear(timeout);\n this.#handles.delete(timeout);\n this.#processes = entries;\n if (entries) this.#cpu = cpuShares(entries, this.#cpu.marks, this.#settings.now());\n this.#kernel = entries ? 'ok' : 'unreachable';\n this.schedule();\n this.#later(() => this.#poll(), this.#settings.psMs);\n };\n const timeout = this.#later(() => settle(null), this.#settings.psTimeoutMs);\n kernel.ps().then(settle, () => settle(null));\n }\n\n #problem(entry: MonitorProblem): void {\n if (this.#problems.some((known) => known.id === entry.id)) return;\n this.#problems.unshift(entry);\n this.#problems.length = Math.min(this.#problems.length, PROBLEMS_MAX);\n }\n\n #commit(publication: CommitPublication): void {\n let changed = false;\n for (const change of publication.changes) {\n if (change.type === 'task') changed = this.#failed(change.value) || changed;\n else if (change.type === 'document' && change.record.kind === 'pi.usage')\n this.#usageChanged();\n }\n if (changed) this.schedule();\n }\n\n #failed(task: TaskRecord<JsonValue, JsonValue, JsonValue>): boolean {\n if (task.state.status !== 'terminal') return false;\n const outcome = task.state.outcome;\n if (outcome.status !== 'faulted' && outcome.status !== 'orphaned') return false;\n this.#problem({\n id: `task:${task.id}`,\n at: this.#settings.now(),\n agentId: conversations(this.#options.agents.state()).get(task.conversationId) ?? null,\n kind: 'task',\n message: redacted(\n outcome.status === 'faulted' ? outcome.error.message : outcome.reason,\n this.#settings.secrets()\n ),\n });\n return true;\n }\n\n #usageChanged(): void {\n if (this.#usageTimer !== undefined) return;\n this.#usageTimer = this.#later(() => {\n this.#usageTimer = undefined;\n void this.#readUsage();\n }, this.#settings.usageMs);\n }\n\n #since(key: string): number {\n const at = this.#seen.get(key) ?? this.#settings.now();\n this.#next.set(key, at);\n return at;\n }\n\n #agent(agent: Agent, view: ConversationView | undefined, tools: Map<string, string>) {\n const secrets = this.#settings.secrets();\n const liveDoc = view?.docs['pi.live'] as Live | undefined;\n for (const slot of liveDoc?.tools ?? [])\n if (slot.taskId !== undefined) tools.set(String(slot.taskId), slot.name);\n const inbox = view?.docs['pi.inbox'] as { items?: unknown[] } | undefined;\n const doc = view?.docs['pi.agent'] as\n | { model?: { provider: string; modelId: string } }\n | undefined;\n const generation = liveDoc?.generation;\n const retry = generation?.retry\n ? {\n attempt: generation.attempt,\n since: this.#since(`retry:${agent.id}`),\n error: redacted(generation.retry.error, secrets),\n }\n : null;\n if (retry)\n this.#problem({\n id: `retry:${agent.id}:${retry.since}`,\n at: retry.since,\n agentId: agent.id,\n kind: 'retry',\n message: retry.error,\n });\n const last = lastAssistant(view);\n const failed =\n last?.message.stopReason === 'error'\n ? redacted(last.message.errorMessage || 'error', secrets)\n : null;\n if (failed && last)\n this.#problem({\n id: `turn:${last.id}`,\n at: this.#settings.now(),\n agentId: agent.id,\n kind: 'turn',\n message: failed,\n });\n return {\n id: agent.id,\n name: agent.name,\n kind: agent.kind,\n parentId: agent.parentId,\n model: doc?.model ? `${doc.model.provider}/${doc.model.modelId}` : null,\n running: Boolean(liveDoc?.run),\n queued: inbox?.items?.length ?? 0,\n tool: liveDoc?.tools?.find((slot) => slot.status === 'running')?.name ?? null,\n retry,\n failed,\n context: last ? contextOf(last.message) : null,\n };\n }\n\n #task(node: TaskGraphNode, owners: Map<number, string>, details: Map<string, string>) {\n const id = String(node.id);\n const status = node.state.status;\n return {\n id,\n kind: node.kind,\n detail: details.get(id) ?? null,\n agentId: owners.get(node.conversationId) ?? null,\n owner: node.owner === undefined ? null : String(node.owner),\n status,\n phase: phaseOf(node),\n background: node.background,\n aborting: node.abortRequested ? this.#since(`abort:${id}`) : null,\n since: this.#since(`task:${id}:${status}`),\n waits: node.state.status === 'waiting' ? node.state.on.length : 0,\n };\n }\n\n #process(entry: PsEntry, groups: Map<number, string>, programs: Map<number, string>) {\n const argv = entry.argv ?? [];\n const pgid = entry.pgid ?? entry.pid;\n const zombie = entry.state === 'Z';\n programs.set(entry.pid, program(argv));\n const uid = entry.uid;\n return {\n pid: entry.pid,\n ppid: entry.ppid ?? 0,\n pgid,\n user:\n uid === undefined ? null : (this.#users.get(uid) ?? (uid === 0 ? 'root' : `uid ${uid}`)),\n agentId: groups.get(pgid) ?? null,\n command: commandLine(argv, this.#settings.secrets()),\n state: zombie ? ('Z' as const) : ('S' as const),\n started: entry.started ?? 0,\n zombie: zombie ? this.#since(`zombie:${entry.pid}`) : null,\n tty: Boolean(entry.tty),\n rss: typeof entry.rss === 'number' ? entry.rss : null,\n ...(timed(entry)\n ? { utime: entry.utime, stime: entry.stime, cpu: this.#cpu.shares.get(entry.pid) ?? null }\n : {}),\n };\n }\n\n #emit(): void {\n this.#lastBuild = this.#settings.now();\n this.#next = new Map();\n const registry = this.#options.agents.state();\n const views = this.#options.views.value ?? {};\n const agents = liveAgents(registry);\n const details = new Map<string, string>();\n const rows: MonitorAgent[] = agents.map((agent) =>\n this.#agent(agent, views[agent.id], details)\n );\n for (const scoop of Object.values(registry.scoops))\n details.set(String(scoop.anchor), scoop.name);\n const owners = conversations(registry);\n const tasks: MonitorTask[] = Object.values(this.#graph.tasks).map((node) =>\n this.#task(node, owners, details)\n );\n const groups = new Map<number, string>();\n for (const agent of agents)\n for (const pgid of this.#options.groups?.owned(agent.conversation) ?? [])\n groups.set(pgid, agent.id);\n const programs = new Map<number, string>();\n const entries = this.#processes;\n const processes: MonitorProcess[] | null =\n entries?.map((entry) => this.#process(entry, groups, programs)) ?? null;\n if (entries?.some(timed))\n for (const row of rows) row.cpu = agentCpu(processes as MonitorProcess[], row.id);\n this.#seen = this.#next;\n const feed: MonitorFeed = {\n open: true,\n at: this.#lastBuild,\n usage: this.#usage ? totals(this.#usage) : null,\n agents: rows,\n tasks,\n processes,\n kernel: this.#kernel,\n problems: [...this.#problems],\n paused: this.#paused,\n };\n const key = JSON.stringify({ ...feed, at: 0 });\n if (key === this.#last) return;\n this.#last = key;\n this.#publish(feed, narrowed(feed, programs));\n }\n}\n\nexport function createMonitor(options: MonitorOptions): Monitor {\n const settings: Settings = {\n now: options.now ?? Date.now,\n timers: options.timers ?? globalTimers,\n context: options.context ?? BACKGROUND_CONTEXT,\n psMs: options.psMs ?? PS_MS,\n psTimeoutMs: options.psTimeoutMs ?? PS_TIMEOUT_MS,\n throttleMs: options.throttleMs ?? THROTTLE_MS,\n usageMs: options.usageMs ?? USAGE_MS,\n secrets: () => options.secrets?.() ?? [],\n };\n const { now, timers, context } = settings;\n const ttlMs = options.ttlMs ?? TTL_MS;\n const state = replicatedState<MonitorFeed>(emptyFeed());\n const viewState = replicatedState<MonitorFeed>(emptyFeed());\n const leases = new Map<string, number>();\n let session: Session | undefined;\n let sweep: unknown;\n const publish = (feed: MonitorFeed, view: MonitorFeed) => {\n state.replace(context, feed);\n viewState.replace(context, view);\n };\n const stop = () => {\n if (sweep !== undefined) timers.clear(sweep);\n sweep = undefined;\n const current = session;\n if (!current) return;\n session = undefined;\n current.stop();\n publish(\n { ...(state.value as MonitorFeed), open: false },\n { ...(viewState.value as MonitorFeed), open: false }\n );\n };\n const arm = () => {\n if (sweep !== undefined) timers.clear(sweep);\n sweep = timers.set(expire, Math.max(0, Math.min(...leases.values()) - now()));\n };\n const expire = () => {\n sweep = undefined;\n const at = now();\n for (const [lease, until] of [...leases]) if (until <= at) leases.delete(lease);\n if (leases.size) arm();\n else stop();\n };\n return {\n state,\n viewState,\n async open(lease, resync) {\n const id = lease ?? crypto.randomUUID();\n leases.set(id, now() + ttlMs);\n arm();\n if (!session) {\n session = new Session(options, settings, publish);\n session.start();\n } else if (resync) session.refresh();\n return { lease: id, ttlMs };\n },\n async close(lease) {\n if (!leases.delete(lease)) return;\n if (leases.size) arm();\n else stop();\n },\n active: () => session !== undefined,\n async dispose() {\n leases.clear();\n stop();\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/services.ts"],
4
- "sourcesContent": ["import {\n type Context,\n defineService,\n type JsonValue,\n type ReplicatedState,\n} from '@earendil-works/chord';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { ChangesView } from './changes/git.ts';\nimport type { FrozenCone } from './freezer/index.ts';\nimport type { MemoryEntry, MemoryScope, MemoryTag } from './memory/format.ts';\nimport type { AgentRemote } from './remote/host.ts';\nimport type { AgentPages } from './remote/pages.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\n\nexport type SendMode = 'steer' | 'followUp' | 'reject';\n\nexport interface SendRequest {\n text: string;\n whenBusy: SendMode;\n requestId: string | null;\n agentId?: string | null;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n}\n\nexport type SendResponse =\n | { accepted: true; submissionId: string; error: null }\n | { accepted: false; submissionId: null; error: OperationError };\n\nexport type PromptResult =\n | { status: 'done'; text: string; reason: null }\n | { status: 'unanswered'; text: null; reason: string };\n\nexport interface AgentControl {\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n wait(submissionId: string, context: Context): Promise<PromptResult>;\n withdraw(\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n abort(context: Context): Promise<void>;\n compact(instructions: string | null, context: Context): Promise<SendResponse>;\n compactAgent(\n agentId: string,\n instructions: string | null,\n context: Context\n ): Promise<SendResponse>;\n reset(handoff: string | null, context: Context): Promise<void>;\n configure(change: AgentSettingsChange, context: Context): Promise<void>;\n rewind(messageId: string | null, context: Context): Promise<Rewound>;\n rewindAgent(agentId: string, messageId: string | null, context: Context): Promise<Rewound>;\n resolveLick(\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n resolveAgentLick(\n agentId: string,\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n webhook(\n name: string,\n delivery: WebhookRequest,\n context: Context\n ): Promise<{ delivered: boolean }>;\n stopAgent(agentId: string, context: Context): Promise<void>;\n selectCone(agentId: string, context: Context): Promise<void>;\n createCone(name: string, context: Context): Promise<Created>;\n createScoop(parentId: string, name: string, context: Context): Promise<Created>;\n drop(agentId: string, context: Context): Promise<Created>;\n unqueue(\n agentId: string | null,\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n sprinkleSend(\n sprinkleId: string,\n payload: { action: string; data: JsonValue | null; target: string | null },\n context: Context\n ): Promise<{ delivered: boolean }>;\n sprinkleCall(\n sprinkleId: string,\n method: string,\n args: JsonValue[],\n context: Context\n ): Promise<JsonValue>;\n memorySave(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n memoryRemove(id: string, context: Context): Promise<{ removed: boolean }>;\n freeze(agentId: string, context: Context): Promise<Created>;\n newChat(agentId: string, context: Context): Promise<Created>;\n thaw(frozenId: string, context: Context): Promise<Created>;\n discard(frozenId: string, context: Context): Promise<Created>;\n changesOpen(context: Context): Promise<void>;\n changeAccept(path: string, context: Context): Promise<Created>;\n changeRevert(path: string, context: Context): Promise<Created>;\n monitorOpen(lease: string | null, resync: boolean, context: Context): Promise<MonitorLease>;\n monitorClose(lease: string, context: Context): Promise<void>;\n}\n\nexport interface MonitorLease {\n lease: string;\n ttlMs: number;\n}\n\nexport interface MonitorAgent {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n model: string | null;\n running: boolean;\n queued: number;\n tool: string | null;\n retry: { attempt: number; since: number; error: string } | null;\n failed: string | null;\n context: number | null;\n}\n\nexport interface MonitorTask {\n id: string;\n kind: string;\n detail: string | null;\n agentId: string | null;\n owner: string | null;\n status: 'pending' | 'running' | 'waiting' | 'completing';\n phase: string;\n background: boolean;\n aborting: number | null;\n since: number;\n waits: number;\n}\n\nexport interface MonitorProcess {\n pid: number;\n ppid: number;\n pgid: number;\n user: string | null;\n agentId: string | null;\n command: string;\n state: 'S' | 'Z';\n started: number;\n zombie: number | null;\n tty: boolean;\n rss: number | null;\n}\n\nexport interface MonitorProblem {\n id: string;\n at: number;\n agentId: string | null;\n kind: 'task' | 'retry' | 'turn';\n message: string;\n}\n\nexport interface MonitorFeed {\n open: boolean;\n at: number;\n usage: { tokens: number; cost: number; free: boolean } | null;\n agents: MonitorAgent[];\n tasks: MonitorTask[];\n processes: MonitorProcess[] | null;\n kernel: 'checking' | 'ok' | 'unreachable';\n problems: MonitorProblem[];\n paused: boolean;\n}\n\nexport interface MemoryDraft {\n id: string | null;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport type Created = { id: string; error: null } | { id: null; error: string };\n\nexport interface AgentSummary {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n role: string | null;\n}\n\nexport interface AgentsSummary {\n active: string;\n agents: AgentSummary[];\n}\n\nexport type LickResolved =\n | { done: true; text: string; error: null }\n | { done: false; text: null; error: string };\n\nexport interface WebhookRequest {\n id: string | null;\n headers: Record<string, string>;\n body: string;\n}\n\nexport type Rewound =\n | { done: true; text: string; reason: null }\n | { done: false; text: null; reason: 'busy' | 'no-turn' };\n\nexport interface AgentSettingsChange {\n model: { provider: string; modelId: string } | null;\n thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;\n agentId?: string | null;\n}\n\nexport const AgentControl = defineService<AgentControl>('slicc.agent.control');\n\nexport type Delivered = 'run' | 'steer' | 'follow-up';\n\nexport interface AgentTranscript {\n readonly state: ReplicatedState<ConversationView>;\n readonly deliveries: ReplicatedState<Record<string, Delivered>>;\n readonly agents: ReplicatedState<AgentsSummary>;\n readonly views: ReplicatedState<Record<string, ConversationView>>;\n readonly commands: ReplicatedState<Command[]>;\n readonly sprinkles: ReplicatedState<Sprinkle[]>;\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly memoryScopes: ReplicatedState<MemoryScope[]>;\n readonly frozen: ReplicatedState<FrozenCone[]>;\n readonly changes: ReplicatedState<ChangesView>;\n readonly monitor: ReplicatedState<MonitorFeed>;\n readonly vault: ReplicatedState<VaultState>;\n}\n\nexport interface Command {\n name: string;\n description: string;\n kind: 'prompt' | 'skill' | 'action';\n}\n\nexport const AgentTranscript = defineService<AgentTranscript>('slicc.agent.transcript');\n\nexport interface AgentSessions {\n attach(sessionId: string, context: Context): Promise<void>;\n detach(context: Context): Promise<void>;\n}\n\nexport const AgentSessions = defineService<AgentSessions>('slicc.agent.sessions');\n\nexport const AgentRemoteService = defineService<AgentRemote>('slicc.agent.remote');\n\nexport const AgentPagesService = defineService<AgentPages>('slicc.agent.pages');\n\nexport const AGENT_SESSION = 'agent';\n\nexport interface ModelChoice {\n id: string;\n label: string;\n provider: string;\n kind: 'chat' | 'classifier';\n reasoning: boolean;\n images?: boolean;\n contextWindow: number;\n}\n\nexport interface AccountState {\n id: string;\n provider: string;\n identity: string;\n status: 'connected' | 'disconnected' | 'expired';\n auth: 'api-key' | 'oauth';\n needs: 'cors-free-transport' | null;\n group?: 'providers' | 'mcp';\n secret?: 'api-key' | 'token';\n}\n\nexport interface BudgetState {\n provider: string;\n percent: number;\n window: 'weekly';\n resets: string;\n}\n\nexport interface SignIn {\n clientId: string;\n scopes: string;\n imsEnvironment: string;\n}\n\nexport interface McpSignIn {\n url: string;\n state: string;\n}\n\nexport interface SettingsState {\n models: ModelChoice[];\n accounts: AccountState[];\n budget?: BudgetState | null;\n}\n\nexport interface AgentSettings {\n readonly state: ReplicatedState<SettingsState>;\n connect(\n providerId: string,\n secret: string,\n region: string | null,\n context: Context\n ): Promise<void>;\n disconnect(providerId: string, context: Context): Promise<void>;\n signIn(providerId: string, context: Context): Promise<SignIn | McpSignIn | null>;\n}\n\nexport const AgentSettings = defineService<AgentSettings>('slicc.agent.settings');\n"],
5
- "mappings": "AAAA;AAAA,EAEE;AAAA,OAGK;AAmNA,MAAM,eAAe,cAA4B,qBAAqB;AAyBtE,MAAM,kBAAkB,cAA+B,wBAAwB;AAO/E,MAAM,gBAAgB,cAA6B,sBAAsB;AAEzE,MAAM,qBAAqB,cAA2B,oBAAoB;AAE1E,MAAM,oBAAoB,cAA0B,mBAAmB;AAEvE,MAAM,gBAAgB;AA2DtB,MAAM,gBAAgB,cAA6B,sBAAsB;",
4
+ "sourcesContent": ["import {\n type Context,\n defineService,\n type JsonValue,\n type ReplicatedState,\n} from '@earendil-works/chord';\nimport type { ConversationView } from '@earendil-works/pi-durable';\nimport type { ChangesView } from './changes/git.ts';\nimport type { FrozenCone } from './freezer/index.ts';\nimport type { MemoryEntry, MemoryScope, MemoryTag } from './memory/format.ts';\nimport type { AgentRemote } from './remote/host.ts';\nimport type { AgentPages } from './remote/pages.ts';\nimport type { VaultState } from './secrets/vault.ts';\nimport type { Sprinkle } from './sprinkles/kind.ts';\n\nexport type SendMode = 'steer' | 'followUp' | 'reject';\n\nexport interface SendRequest {\n text: string;\n whenBusy: SendMode;\n requestId: string | null;\n agentId?: string | null;\n}\n\nexport interface OperationError {\n code: string;\n message: string;\n}\n\nexport type SendResponse =\n | { accepted: true; submissionId: string; error: null }\n | { accepted: false; submissionId: null; error: OperationError };\n\nexport type PromptResult =\n | { status: 'done'; text: string; reason: null }\n | { status: 'unanswered'; text: null; reason: string };\n\nexport interface AgentControl {\n send(request: SendRequest, context: Context): Promise<SendResponse>;\n wait(submissionId: string, context: Context): Promise<PromptResult>;\n withdraw(\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n abort(context: Context): Promise<void>;\n compact(instructions: string | null, context: Context): Promise<SendResponse>;\n compactAgent(\n agentId: string,\n instructions: string | null,\n context: Context\n ): Promise<SendResponse>;\n reset(handoff: string | null, context: Context): Promise<void>;\n configure(change: AgentSettingsChange, context: Context): Promise<void>;\n rewind(messageId: string | null, context: Context): Promise<Rewound>;\n rewindAgent(agentId: string, messageId: string | null, context: Context): Promise<Rewound>;\n resolveLick(\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n resolveAgentLick(\n agentId: string,\n lickId: string,\n state: 'confirmed' | 'dismissed',\n context: Context\n ): Promise<LickResolved>;\n webhook(\n name: string,\n delivery: WebhookRequest,\n context: Context\n ): Promise<{ delivered: boolean }>;\n stopAgent(agentId: string, context: Context): Promise<void>;\n selectCone(agentId: string, context: Context): Promise<void>;\n createCone(name: string, context: Context): Promise<Created>;\n createScoop(parentId: string, name: string, context: Context): Promise<Created>;\n drop(agentId: string, context: Context): Promise<Created>;\n unqueue(\n agentId: string | null,\n submissionId: string,\n context: Context\n ): Promise<{ outcome: 'withdrawn' | 'already_placed' | 'not_found' }>;\n sprinkleSend(\n sprinkleId: string,\n payload: { action: string; data: JsonValue | null; target: string | null },\n context: Context\n ): Promise<{ delivered: boolean }>;\n sprinkleCall(\n sprinkleId: string,\n method: string,\n args: JsonValue[],\n context: Context\n ): Promise<JsonValue>;\n memorySave(draft: MemoryDraft, context: Context): Promise<MemoryEntry>;\n memoryRemove(id: string, context: Context): Promise<{ removed: boolean }>;\n freeze(agentId: string, context: Context): Promise<Created>;\n newChat(agentId: string, context: Context): Promise<Created>;\n thaw(frozenId: string, context: Context): Promise<Created>;\n discard(frozenId: string, context: Context): Promise<Created>;\n changesOpen(context: Context): Promise<void>;\n changeAccept(path: string, context: Context): Promise<Created>;\n changeRevert(path: string, context: Context): Promise<Created>;\n monitorOpen(lease: string | null, resync: boolean, context: Context): Promise<MonitorLease>;\n monitorClose(lease: string, context: Context): Promise<void>;\n}\n\nexport interface MonitorLease {\n lease: string;\n ttlMs: number;\n}\n\nexport interface MonitorAgent {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n model: string | null;\n running: boolean;\n queued: number;\n tool: string | null;\n retry: { attempt: number; since: number; error: string } | null;\n failed: string | null;\n context: number | null;\n cpu?: number | null;\n}\n\nexport interface MonitorTask {\n id: string;\n kind: string;\n detail: string | null;\n agentId: string | null;\n owner: string | null;\n status: 'pending' | 'running' | 'waiting' | 'completing';\n phase: string;\n background: boolean;\n aborting: number | null;\n since: number;\n waits: number;\n}\n\nexport interface MonitorProcess {\n pid: number;\n ppid: number;\n pgid: number;\n user: string | null;\n agentId: string | null;\n command: string;\n state: 'S' | 'Z';\n started: number;\n zombie: number | null;\n tty: boolean;\n rss: number | null;\n utime?: number;\n stime?: number;\n cpu?: number | null;\n}\n\nexport interface MonitorProblem {\n id: string;\n at: number;\n agentId: string | null;\n kind: 'task' | 'retry' | 'turn';\n message: string;\n}\n\nexport interface MonitorFeed {\n open: boolean;\n at: number;\n usage: { tokens: number; cost: number; free: boolean } | null;\n agents: MonitorAgent[];\n tasks: MonitorTask[];\n processes: MonitorProcess[] | null;\n kernel: 'checking' | 'ok' | 'unreachable';\n problems: MonitorProblem[];\n paused: boolean;\n}\n\nexport interface MemoryDraft {\n id: string | null;\n scope: string;\n section: string;\n title: string;\n body: string;\n tag: MemoryTag | null;\n}\n\nexport type Created = { id: string; error: null } | { id: null; error: string };\n\nexport interface AgentSummary {\n id: string;\n name: string;\n kind: 'cone' | 'scoop';\n parentId: string | null;\n role: string | null;\n}\n\nexport interface AgentsSummary {\n active: string;\n agents: AgentSummary[];\n}\n\nexport type LickResolved =\n | { done: true; text: string; error: null }\n | { done: false; text: null; error: string };\n\nexport interface WebhookRequest {\n id: string | null;\n headers: Record<string, string>;\n body: string;\n}\n\nexport type Rewound =\n | { done: true; text: string; reason: null }\n | { done: false; text: null; reason: 'busy' | 'no-turn' };\n\nexport interface AgentSettingsChange {\n model: { provider: string; modelId: string } | null;\n thinkingLevel: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | null;\n agentId?: string | null;\n}\n\nexport const AgentControl = defineService<AgentControl>('slicc.agent.control');\n\nexport type Delivered = 'run' | 'steer' | 'follow-up';\n\nexport interface AgentTranscript {\n readonly state: ReplicatedState<ConversationView>;\n readonly deliveries: ReplicatedState<Record<string, Delivered>>;\n readonly agents: ReplicatedState<AgentsSummary>;\n readonly views: ReplicatedState<Record<string, ConversationView>>;\n readonly commands: ReplicatedState<Command[]>;\n readonly sprinkles: ReplicatedState<Sprinkle[]>;\n readonly memories: ReplicatedState<MemoryEntry[]>;\n readonly memoryScopes: ReplicatedState<MemoryScope[]>;\n readonly frozen: ReplicatedState<FrozenCone[]>;\n readonly changes: ReplicatedState<ChangesView>;\n readonly monitor: ReplicatedState<MonitorFeed>;\n readonly vault: ReplicatedState<VaultState>;\n}\n\nexport interface Command {\n name: string;\n description: string;\n kind: 'prompt' | 'skill' | 'action';\n}\n\nexport const AgentTranscript = defineService<AgentTranscript>('slicc.agent.transcript');\n\nexport interface AgentSessions {\n attach(sessionId: string, context: Context): Promise<void>;\n detach(context: Context): Promise<void>;\n}\n\nexport const AgentSessions = defineService<AgentSessions>('slicc.agent.sessions');\n\nexport const AgentRemoteService = defineService<AgentRemote>('slicc.agent.remote');\n\nexport const AgentPagesService = defineService<AgentPages>('slicc.agent.pages');\n\nexport const AGENT_SESSION = 'agent';\n\nexport interface ModelChoice {\n id: string;\n label: string;\n provider: string;\n kind: 'chat' | 'classifier';\n reasoning: boolean;\n images?: boolean;\n contextWindow: number;\n}\n\nexport interface AccountState {\n id: string;\n provider: string;\n identity: string;\n status: 'connected' | 'disconnected' | 'expired';\n auth: 'api-key' | 'oauth';\n needs: 'cors-free-transport' | null;\n group?: 'providers' | 'mcp';\n secret?: 'api-key' | 'token';\n}\n\nexport interface BudgetState {\n provider: string;\n percent: number;\n window: 'weekly';\n resets: string;\n}\n\nexport interface SignIn {\n clientId: string;\n scopes: string;\n imsEnvironment: string;\n}\n\nexport interface McpSignIn {\n url: string;\n state: string;\n}\n\nexport interface SettingsState {\n models: ModelChoice[];\n accounts: AccountState[];\n budget?: BudgetState | null;\n}\n\nexport interface AgentSettings {\n readonly state: ReplicatedState<SettingsState>;\n connect(\n providerId: string,\n secret: string,\n region: string | null,\n context: Context\n ): Promise<void>;\n disconnect(providerId: string, context: Context): Promise<void>;\n signIn(providerId: string, context: Context): Promise<SignIn | McpSignIn | null>;\n}\n\nexport const AgentSettings = defineService<AgentSettings>('slicc.agent.settings');\n"],
5
+ "mappings": "AAAA;AAAA,EAEE;AAAA,OAGK;AAuNA,MAAM,eAAe,cAA4B,qBAAqB;AAyBtE,MAAM,kBAAkB,cAA+B,wBAAwB;AAO/E,MAAM,gBAAgB,cAA6B,sBAAsB;AAEzE,MAAM,qBAAqB,cAA2B,oBAAoB;AAE1E,MAAM,oBAAoB,cAA0B,mBAAmB;AAEvE,MAAM,gBAAgB;AA2DtB,MAAM,gBAAgB,cAA6B,sBAAsB;",
6
6
  "names": []
7
7
  }
@@ -15,6 +15,8 @@ const GROUP_MAX = 32;
15
15
  const TOTAL_MAX = 128;
16
16
  const ZOMBIE_MS = 6e4;
17
17
  const STALE_MS = 18e5;
18
+ const CPU_SHARE = 0.9;
19
+ const CPU_SUSTAIN_MS = 12e4;
18
20
  const CONTEXT_WARN = 0.8;
19
21
  const DEPTH_MAX = 6;
20
22
  const MINUTE = 6e4;
@@ -208,6 +210,7 @@ function vitals(input, feed) {
208
210
  }
209
211
  function stale(process, agents, now) {
210
212
  if (!process.agentId || process.state === "Z" || !process.started) return false;
213
+ if (typeof process.utime === "number") return false;
211
214
  if (agents.get(process.agentId)?.tool === "bash") return false;
212
215
  return now - process.started > STALE_MS;
213
216
  }
@@ -221,6 +224,43 @@ function groups(processes) {
221
224
  }
222
225
  return out;
223
226
  }
227
+ function groupCpu(processes) {
228
+ const out = /* @__PURE__ */ new Map();
229
+ for (const [pgid, members] of groups(processes)) {
230
+ const measured = members.filter((row) => typeof row.cpu === "number");
231
+ if (!measured.length) continue;
232
+ const share = measured.reduce((sum, row) => sum + row.cpu, 0);
233
+ out.set(pgid, { agentId: members[0].agentId, share });
234
+ }
235
+ return out;
236
+ }
237
+ function hotGroups(processes, at, previous) {
238
+ const out = /* @__PURE__ */ new Map();
239
+ for (const [pgid, { share }] of groupCpu(processes))
240
+ if (share >= CPU_SHARE) out.set(pgid, previous.get(pgid) ?? at);
241
+ return out;
242
+ }
243
+ function busy(input, processes) {
244
+ const shares = groupCpu(processes);
245
+ const out = [];
246
+ for (const [pgid, since] of input.hot ?? []) {
247
+ const group = shares.get(pgid);
248
+ const held = input.now - since;
249
+ if (group && group.share >= CPU_SHARE && held >= CPU_SUSTAIN_MS)
250
+ out.push({ pgid, ...group, held });
251
+ }
252
+ return out;
253
+ }
254
+ function cpuAlerts(input, processes, nameOf) {
255
+ return busy(input, processes).map(
256
+ (group) => ({
257
+ id: `runaway-cpu-${group.pgid}`,
258
+ title: `${nameOf(group.agentId)} is using a lot of CPU`,
259
+ detail: `${Math.round(group.share * 100)}% of one core for ${Math.floor(group.held / MINUTE)} minutes. Kill them with kill -- -${group.pgid}.`,
260
+ severity: group.share >= CPU_SHARE * 2 || group.held >= CPU_SUSTAIN_MS * 2 ? "error" : "warn"
261
+ })
262
+ );
263
+ }
224
264
  function resetLine(budget) {
225
265
  const resets = new Date(budget.resets);
226
266
  return Number.isNaN(resets.getTime()) ? `The ${budget.window} budget is nearly used up.` : `Resets ${resets.toISOString().slice(0, 16).replace("T", " ")} UTC.`;
@@ -299,7 +339,7 @@ function crowdAlerts(processes, nameOf) {
299
339
  function processAlerts(input, feed, nameOf) {
300
340
  const processes = feed.processes ?? [];
301
341
  const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));
302
- const out = crowdAlerts(processes, nameOf);
342
+ const out = [...crowdAlerts(processes, nameOf), ...cpuAlerts(input, processes, nameOf)];
303
343
  for (const process of processes) {
304
344
  if (process.zombie !== null && input.now - process.zombie > ZOMBIE_MS)
305
345
  out.push({
@@ -392,6 +432,7 @@ function processRows(input, feed) {
392
432
  const crowded = /* @__PURE__ */ new Set();
393
433
  for (const [pgid, members] of groups(feed.processes ?? []))
394
434
  if (members.length > GROUP_MAX) crowded.add(pgid);
435
+ for (const group of busy(input, feed.processes ?? [])) crowded.add(group.pgid);
395
436
  return (feed.processes ?? []).map((process) => {
396
437
  const runaway = stale(process, agents, input.now) || crowded.has(process.pgid);
397
438
  const badges = [
@@ -512,6 +553,8 @@ class MonitorAdapter {
512
553
  #listeners = 0;
513
554
  #open;
514
555
  #history = [];
556
+ #hot = /* @__PURE__ */ new Map();
557
+ #hotAt = -1;
515
558
  constructor(connection, options = {}) {
516
559
  this.#connection = connection;
517
560
  this.#extra = options.extra ?? (() => []);
@@ -546,7 +589,8 @@ class MonitorAdapter {
546
589
  sprinkles: this.#connection.sprinkles?.value ?? [],
547
590
  extra: this.#extra(),
548
591
  history: this.#history,
549
- now: this.#now()
592
+ now: this.#now(),
593
+ hot: this.#hot
550
594
  });
551
595
  }
552
596
  resync() {
@@ -559,6 +603,8 @@ class MonitorAdapter {
559
603
  #start() {
560
604
  const control = this.#connection.control;
561
605
  this.#history = [];
606
+ this.#hot = /* @__PURE__ */ new Map();
607
+ this.#hotAt = -1;
562
608
  void control.changesOpen(BACKGROUND_CONTEXT).catch(() => void 0);
563
609
  const lease = control.monitorOpen(null, true, BACKGROUND_CONTEXT).then(
564
610
  (opened) => opened.lease || null,
@@ -586,9 +632,16 @@ class MonitorAdapter {
586
632
  });
587
633
  if (this.#history.length > HISTORY) this.#history.shift();
588
634
  }
635
+ #track() {
636
+ const feed = this.#connection.monitor?.value;
637
+ if (!feed?.open || feed.at === this.#hotAt) return;
638
+ this.#hotAt = feed.at;
639
+ this.#hot = hotGroups(feed.processes ?? [], feed.at, this.#hot);
640
+ }
589
641
  #update() {
590
642
  if (!this.#listeners) return;
591
643
  this.#sample();
644
+ this.#track();
592
645
  this.#emitter.emit("snapshot", this.snapshot());
593
646
  }
594
647
  }
@@ -598,6 +651,8 @@ export {
598
651
  BUDGET_ERROR,
599
652
  BUDGET_WARN,
600
653
  CONTEXT_WARN,
654
+ CPU_SHARE,
655
+ CPU_SUSTAIN_MS,
601
656
  DEPTH_MAX,
602
657
  FAILED_MS,
603
658
  GROUP_MAX,
@@ -615,6 +670,8 @@ export {
615
670
  bytes,
616
671
  count,
617
672
  globalIntervals,
673
+ groupCpu,
674
+ hotGroups,
618
675
  money,
619
676
  monitorSnapshot,
620
677
  taskLabel,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/spectrum/monitor-port.ts"],
4
- "sourcesContent": ["import type {\n MonitorAlert,\n MonitorEvents,\n MonitorPort,\n MonitorRow,\n MonitorSection,\n MonitorSnapshot,\n MonitorStatus,\n MonitorVital,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentConnection } from '../client.ts';\nimport type {\n BudgetState,\n ModelChoice,\n MonitorAgent,\n MonitorFeed,\n MonitorProcess,\n MonitorTask,\n} from '../services.ts';\nimport { Emitter } from './emitter.ts';\n\nexport const RENEW_MS = 10000;\nexport const ROWS_MAX = 200;\nexport const HISTORY = 24;\nexport const BUDGET_WARN = 80;\nexport const BUDGET_ERROR = 95;\nexport const RETRY_WARN = 3;\nexport const RETRY_ERROR = 6;\nexport const RETRY_SLOW_MS = 120000;\nexport const FAILED_MS = 600000;\nexport const ABORT_MS = 30000;\nexport const ABORT_ROW_MS = 10000;\nexport const GROUP_MAX = 32;\nexport const TOTAL_MAX = 128;\nexport const ZOMBIE_MS = 60000;\nexport const STALE_MS = 1800000;\nexport const CONTEXT_WARN = 0.8;\nexport const DEPTH_MAX = 6;\nconst MINUTE = 60000;\nconst HOUR = 3600000;\n\nexport interface Sample {\n at: number;\n cost: number;\n tokens: number;\n active: number;\n}\n\nexport interface MonitorInput {\n feed: MonitorFeed | undefined;\n budget: BudgetState | null | undefined;\n models: readonly ModelChoice[];\n changes: readonly { path: string; status: string }[];\n sprinkles: readonly { name: string; title: string }[];\n extra: readonly MonitorSection[];\n history: readonly Sample[];\n now: number;\n}\n\nconst KINDS: Record<string, string> = {\n 'pi.generation': 'generating',\n 'pi.compaction': 'compacting',\n 'slicc.cron': 'cron',\n 'slicc.scoop-wait': 'agent wait',\n 'slicc.scoop-reporter': 'report',\n 'slicc.memory-extract': 'memory extraction',\n};\n\nexport function age(ms: number): string {\n const seconds = Math.max(0, Math.round(ms / 1000));\n if (seconds < 60) return `${seconds}s`;\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;\n return `${Math.floor(seconds / 3600)}h`;\n}\n\nexport function money(value: number): string {\n if (value > 0 && value < 0.01) return '<$0.01';\n return `$${value.toFixed(2)}`;\n}\n\nexport function count(value: number): string {\n if (value < 1000) return String(value);\n if (value < 1000000) return `${(value / 1000).toFixed(1)}k`;\n return `${(value / 1000000).toFixed(1)}M`;\n}\n\nexport function bytes(value: number): string {\n if (value < 1024) return `${value} B`;\n const units = ['KiB', 'MiB', 'GiB', 'TiB'];\n let size = value / 1024;\n let unit = 0;\n while (size >= 1024 && unit < units.length - 1) {\n size /= 1024;\n unit++;\n }\n return `${size.toFixed(size < 10 ? 1 : 0)} ${units[unit]}`;\n}\n\nfunction memoryVital(processes: readonly MonitorProcess[]): MonitorVital[] {\n const measured = processes.filter((row) => typeof row.rss === 'number');\n if (!measured.length) return [];\n const total = measured.reduce((sum, row) => sum + (row.rss as number), 0);\n const agents = measured\n .filter((row) => row.agentId)\n .reduce((sum, row) => sum + (row.rss as number), 0);\n return [\n {\n id: 'memory',\n label: 'Process memory',\n value: bytes(total),\n unit: `${bytes(agents)} by agents`,\n },\n ];\n}\n\nexport function taskLabel(task: MonitorTask): string {\n if (task.kind === 'pi.tool') return task.detail ? `tool ${task.detail}` : 'tool';\n if (task.kind === 'slicc.scoop-anchor') return task.detail ? `scoop ${task.detail}` : 'scoop';\n return KINDS[task.kind] ?? task.kind;\n}\n\nfunction coneOf(agents: ReadonlyMap<string, MonitorAgent>, id: string | null): string | null {\n const visited = new Set<string>();\n let current = id === null ? undefined : agents.get(id);\n while (current?.parentId && !visited.has(current.id)) {\n visited.add(current.id);\n const parent = agents.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n return current ? current.id : null;\n}\n\nfunction ordered(feed: MonitorFeed): MonitorAgent[] {\n const byId = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const out: MonitorAgent[] = [];\n for (const cone of feed.agents.filter((agent) => agent.kind === 'cone')) {\n out.push(cone);\n for (const agent of feed.agents)\n if (agent.kind === 'scoop' && coneOf(byId, agent.id) === cone.id) out.push(agent);\n }\n for (const agent of feed.agents) if (!out.includes(agent)) out.push(agent);\n return out;\n}\n\nexport function taskTree(feed: MonitorFeed): { task: MonitorTask; depth: number }[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const order = ordered(feed).map((agent) => agent.id);\n const rank = (task: MonitorTask) => {\n const at = task.agentId === null ? -1 : order.indexOf(task.agentId);\n return at < 0 ? order.length : at;\n };\n const groupOf = (task: MonitorTask) => coneOf(agents, task.agentId) ?? '';\n const byId = new Map(feed.tasks.map((task) => [task.id, task]));\n const children = new Map<string, MonitorTask[]>();\n const roots: MonitorTask[] = [];\n for (const task of feed.tasks) {\n const owner = task.owner === null ? undefined : byId.get(task.owner);\n if (owner && groupOf(owner) === groupOf(task)) {\n const list = children.get(owner.id) ?? [];\n list.push(task);\n children.set(owner.id, list);\n } else roots.push(task);\n }\n const sort = (list: MonitorTask[]) =>\n list.sort((a, b) => rank(a) - rank(b) || Number(a.id) - Number(b.id));\n const out: { task: MonitorTask; depth: number }[] = [];\n const visit = (task: MonitorTask, depth: number) => {\n out.push({ task, depth });\n for (const child of sort(children.get(task.id) ?? [])) visit(child, depth + 1);\n };\n for (const root of sort(roots)) visit(root, 0);\n return out;\n}\n\nfunction capped(rows: MonitorRow[]): MonitorRow[] {\n if (rows.length <= ROWS_MAX) return rows;\n const shown = rows.slice(0, ROWS_MAX - 1);\n return [\n ...shown,\n { id: 'more', name: `+${rows.length - shown.length} more`, meta: '', status: 'idle' },\n ];\n}\n\nfunction contextRatio(agent: MonitorAgent, models: readonly ModelChoice[]): number | null {\n const window = models.find((model) => model.id === agent.model)?.contextWindow;\n if (!agent.context || !window) return null;\n return Math.min(1, agent.context / window);\n}\n\nfunction rate(history: readonly Sample[], pick: (sample: Sample) => number): number | null {\n const first = history[0];\n const last = history.at(-1);\n if (!first || !last || last.at - first.at < MINUTE) return null;\n return ((pick(last) - pick(first)) / (last.at - first.at)) * HOUR;\n}\n\nfunction budgetVital(budget: BudgetState): MonitorVital {\n const resets = new Date(budget.resets);\n return {\n id: 'budget',\n label: `Budget (${budget.window})`,\n value: `${budget.percent}%`,\n ...(Number.isNaN(resets.getTime())\n ? {}\n : { unit: `resets ${resets.toISOString().slice(0, 16).replace('T', ' ')} UTC` }),\n ratio: Math.min(1, Math.max(0, budget.percent / 100)),\n };\n}\n\nfunction vitals(input: MonitorInput, feed: MonitorFeed): MonitorVital[] {\n const out: MonitorVital[] = [];\n if (feed.usage) {\n const free = feed.usage.free;\n const pick = (sample: Sample) => (free ? sample.tokens : sample.cost);\n const perHour = rate(input.history, pick);\n const series = input.history.map(pick);\n out.push({\n id: 'spend',\n label: free ? 'Tokens' : 'Spend',\n value: free ? count(feed.usage.tokens) : money(feed.usage.cost),\n unit: free ? 'tokens' : `${count(feed.usage.tokens)} tokens`,\n ...(perHour === null ? {} : { delta: `${free ? count(perHour) : money(perHour)}/h` }),\n ...(series.length > 1 ? { series } : {}),\n });\n }\n const active = feed.agents.filter((agent) => agent.running).length;\n const actives = input.history.map((sample) => sample.active);\n out.push({\n id: 'agents',\n label: 'Active agents',\n value: String(active),\n unit: `of ${feed.agents.length}`,\n ...(actives.length > 1 ? { series: actives } : {}),\n });\n const tools = feed.tasks.filter(\n (task) => task.kind === 'pi.tool' && task.status === 'running'\n ).length;\n out.push({\n id: 'tasks',\n label: 'Running',\n value: String(tools),\n unit: `${tools === 1 ? 'tool' : 'tools'} \u00B7 ${feed.tasks.length} ${feed.tasks.length === 1 ? 'task' : 'tasks'}`,\n });\n out.push(\n feed.processes\n ? {\n id: 'processes',\n label: 'Processes',\n value: String(feed.processes.length),\n unit: `${feed.processes.filter((row) => row.agentId).length} by agents`,\n }\n : feed.kernel === 'checking'\n ? { id: 'processes', label: 'Processes', value: '\u2026', unit: 'checking' }\n : { id: 'processes', label: 'Processes', value: '\u2014', unit: 'kernel not reachable' }\n );\n out.push(...memoryVital(feed.processes ?? []));\n const ratios = feed.agents\n .map((agent) => contextRatio(agent, input.models))\n .filter((ratio): ratio is number => ratio !== null);\n if (ratios.length) {\n const fullest = Math.max(...ratios);\n out.push({\n id: 'context',\n label: 'Fullest context',\n value: `${Math.round(fullest * 100)}%`,\n ratio: fullest,\n });\n }\n return out;\n}\n\nfunction stale(process: MonitorProcess, agents: ReadonlyMap<string, MonitorAgent>, now: number) {\n if (!process.agentId || process.state === 'Z' || !process.started) return false;\n if (agents.get(process.agentId)?.tool === 'bash') return false;\n return now - process.started > STALE_MS;\n}\n\nfunction groups(processes: readonly MonitorProcess[]): Map<number, MonitorProcess[]> {\n const out = new Map<number, MonitorProcess[]>();\n for (const process of processes) {\n if (!process.agentId) continue;\n const list = out.get(process.pgid) ?? [];\n list.push(process);\n out.set(process.pgid, list);\n }\n return out;\n}\n\ntype Names = (id: string | null) => string;\n\nfunction resetLine(budget: BudgetState): string {\n const resets = new Date(budget.resets);\n return Number.isNaN(resets.getTime())\n ? `The ${budget.window} budget is nearly used up.`\n : `Resets ${resets.toISOString().slice(0, 16).replace('T', ' ')} UTC.`;\n}\n\nfunction budgetAlerts(budget: BudgetState | null | undefined): MonitorAlert[] {\n if (!budget || budget.percent < BUDGET_WARN) return [];\n return [\n {\n id: 'budget',\n title: `Budget ${budget.percent}% used`,\n detail: resetLine(budget),\n severity: budget.percent >= BUDGET_ERROR ? 'error' : 'warn',\n },\n ];\n}\n\nfunction agentAlerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const agent of feed.agents) {\n const retry = agent.retry;\n if (retry && (retry.attempt >= RETRY_WARN || input.now - retry.since > RETRY_SLOW_MS))\n out.push({\n id: `retry-${agent.id}`,\n title: `${agent.name} is retrying (attempt ${retry.attempt})`,\n detail: retry.error,\n severity: retry.attempt >= RETRY_ERROR ? 'error' : 'warn',\n });\n if (agent.failed && !agent.running)\n out.push({\n id: `turn-${agent.id}`,\n title: `${agent.name}'s last turn failed`,\n detail: agent.failed,\n severity: 'error',\n });\n }\n return out;\n}\n\nfunction taskAlerts(input: MonitorInput, feed: MonitorFeed, nameOf: Names): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const problem of feed.problems)\n if (problem.kind === 'task' && input.now - problem.at < FAILED_MS)\n out.push({\n id: `failed-${problem.id}`,\n title: `A task of ${nameOf(problem.agentId)} failed`,\n detail: problem.message,\n severity: 'error',\n });\n for (const task of feed.tasks)\n if (task.aborting !== null && input.now - task.aborting > ABORT_MS)\n out.push({\n id: `abort-${task.id}`,\n title: `Stop is still waiting for ${taskLabel(task)}`,\n detail: `${nameOf(task.agentId)} asked it to stop ${age(input.now - task.aborting)} ago.`,\n severity: 'warn',\n });\n return out;\n}\n\nfunction crowdAlerts(processes: readonly MonitorProcess[], nameOf: Names): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const [pgid, members] of groups(processes))\n if (members.length > GROUP_MAX)\n out.push({\n id: `runaway-${pgid}`,\n title: `${nameOf((members[0] as MonitorProcess).agentId)} has ${members.length} processes`,\n detail: `Kill them with kill -- -${pgid}.`,\n severity: members.length > GROUP_MAX * 2 ? 'error' : 'warn',\n });\n if (processes.length > TOTAL_MAX)\n out.push({\n id: 'runaway-total',\n title: `The kernel has ${processes.length} processes`,\n detail: 'Something may be starting processes in a loop.',\n severity: processes.length > TOTAL_MAX * 2 ? 'error' : 'warn',\n });\n return out;\n}\n\nfunction processAlerts(input: MonitorInput, feed: MonitorFeed, nameOf: Names): MonitorAlert[] {\n const processes = feed.processes ?? [];\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const out = crowdAlerts(processes, nameOf);\n for (const process of processes) {\n if (process.zombie !== null && input.now - process.zombie > ZOMBIE_MS)\n out.push({\n id: `zombie-${process.pid}`,\n title: `Process ${process.pid} is a zombie`,\n detail: `Its parent ${process.ppid} hasn't reaped it.`,\n severity: 'warn',\n });\n if (stale(process, agents, input.now))\n out.push({\n id: `stale-${process.pid}`,\n title: `${process.command || `Process ${process.pid}`} has run for ${age(input.now - process.started)}`,\n detail: `${nameOf(process.agentId)} started it in the background. Kill it with kill ${process.pid}.`,\n severity: input.now - process.started > STALE_MS * 2 ? 'error' : 'warn',\n });\n }\n return out;\n}\n\nfunction contextAlerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const agent of feed.agents) {\n const ratio = contextRatio(agent, input.models);\n if (ratio !== null && ratio >= CONTEXT_WARN)\n out.push({\n id: `context-${agent.id}`,\n title: `${agent.name} is ${Math.round(ratio * 100)}% full`,\n detail: 'Compact it soon to keep replies fast.',\n severity: 'warn',\n });\n }\n if (feed.paused)\n out.push({\n id: 'scheduler',\n title: \"The agent isn't scheduling work\",\n detail: 'Its scheduler is paused.',\n severity: 'warn',\n });\n return out;\n}\n\nfunction alerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const nameOf: Names = (id) => (id ? (agents.get(id)?.name ?? id) : 'the session');\n return [\n ...budgetAlerts(input.budget),\n ...agentAlerts(input, feed),\n ...taskAlerts(input, feed, nameOf),\n ...processAlerts(input, feed, nameOf),\n ...contextAlerts(input, feed),\n ];\n}\n\nfunction agentRow(agent: MonitorAgent, depth: number, models: readonly ModelChoice[]): MonitorRow {\n const ratio = contextRatio(agent, models);\n const word = agent.retry\n ? 'retrying'\n : agent.running\n ? 'running'\n : agent.failed\n ? 'failed'\n : 'idle';\n const status: MonitorStatus = agent.retry\n ? 'warn'\n : agent.running\n ? 'active'\n : agent.failed\n ? 'error'\n : 'idle';\n const model = models.find((choice) => choice.id === agent.model)?.label ?? agent.model;\n const meta = [word, model, ratio === null ? null : `${Math.round(ratio * 100)}% context`]\n .filter(Boolean)\n .join(' \u00B7 ');\n const badges = [\n ...(agent.queued ? [`${agent.queued} queued`] : []),\n ...(agent.tool ? [agent.tool] : []),\n ...(agent.retry ? [`retry ${agent.retry.attempt}`] : []),\n ];\n return {\n id: agent.id,\n name: agent.name,\n meta,\n status,\n depth,\n ...(badges.length ? { badges } : {}),\n };\n}\n\nfunction taskRow(\n task: MonitorTask,\n depth: number,\n nameOf: (id: string | null) => string,\n now: number\n): MonitorRow {\n const aborting = task.aborting !== null && now - task.aborting > ABORT_ROW_MS;\n const status: MonitorStatus = aborting\n ? 'warn'\n : task.status === 'running' || task.status === 'completing'\n ? 'active'\n : 'idle';\n const badges = [\n ...(task.background ? ['background'] : []),\n ...(task.aborting !== null ? ['aborting'] : []),\n ...(task.waits ? [`waits on ${task.waits}`] : []),\n ];\n return {\n id: task.id,\n name: taskLabel(task),\n depth: Math.min(depth, DEPTH_MAX),\n meta: [nameOf(task.agentId), task.phase, age(now - task.since)].filter(Boolean).join(' \u00B7 '),\n status,\n ...(badges.length ? { badges } : {}),\n };\n}\n\nfunction processRows(input: MonitorInput, feed: MonitorFeed): MonitorRow[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const crowded = new Set<number>();\n for (const [pgid, members] of groups(feed.processes ?? []))\n if (members.length > GROUP_MAX) crowded.add(pgid);\n return (feed.processes ?? []).map((process) => {\n const runaway = stale(process, agents, input.now) || crowded.has(process.pgid);\n const badges = [\n ...(process.agentId ? [agents.get(process.agentId)?.name ?? process.agentId] : []),\n ...(process.tty ? ['terminal'] : []),\n ];\n return {\n id: String(process.pid),\n name: process.command || `[${process.pid}]`,\n meta: [\n `pid ${process.pid}`,\n process.user,\n typeof process.rss === 'number' ? bytes(process.rss) : null,\n process.started ? age(input.now - process.started) : null,\n ]\n .filter(Boolean)\n .join(' \u00B7 '),\n status: runaway ? 'error' : process.state === 'Z' ? 'warn' : 'idle',\n ...(badges.length ? { badges } : {}),\n };\n });\n}\n\nconst PROBLEM_KINDS = { task: 'task failed', retry: 'retry', turn: 'turn failed' } as const;\n\nfunction depthOf(agents: ReadonlyMap<string, MonitorAgent>, agent: MonitorAgent): number {\n const visited = new Set<string>();\n let depth = 0;\n let current = agent;\n while (current.parentId && !visited.has(current.id)) {\n visited.add(current.id);\n const parent = agents.get(current.parentId);\n if (!parent) break;\n depth++;\n current = parent;\n }\n return depth;\n}\n\nfunction sections(input: MonitorInput, feed: MonitorFeed): MonitorSection[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const nameOf = (id: string | null) => (id ? (agents.get(id)?.name ?? id) : 'session');\n return [\n {\n id: 'agents',\n label: 'Cones and scoops',\n rows: ordered(feed).map((agent) =>\n agentRow(agent, Math.min(depthOf(agents, agent), DEPTH_MAX), input.models)\n ),\n },\n {\n id: 'tasks',\n label: 'Tasks',\n rows: capped(\n taskTree(feed).map(({ task, depth }) => taskRow(task, depth, nameOf, input.now))\n ),\n },\n { id: 'processes', label: 'Processes', rows: capped(processRows(input, feed)) },\n {\n id: 'problems',\n label: 'Recent problems',\n rows: feed.problems.map((problem) => ({\n id: problem.id,\n name: `${nameOf(problem.agentId)} \u00B7 ${PROBLEM_KINDS[problem.kind]}`,\n meta: problem.message,\n status: problem.kind === 'retry' ? 'warn' : 'error',\n })),\n },\n ];\n}\n\nfunction pageSections(input: MonitorInput): MonitorSection[] {\n return [\n {\n id: 'changes',\n label: 'Pending changes',\n rows: input.changes.map((change) => ({\n id: change.path,\n name: change.path,\n meta: change.status,\n status: 'warn',\n })),\n },\n {\n id: 'sprinkles',\n label: 'Sprinkles',\n rows: input.sprinkles.map((sprinkle) => ({\n name: sprinkle.title,\n meta: sprinkle.name,\n status: 'idle',\n })),\n },\n ...input.extra,\n ];\n}\n\nexport function monitorSnapshot(input: MonitorInput): MonitorSnapshot {\n const budget = input.budget ? [budgetVital(input.budget)] : [];\n const feed = input.feed;\n if (!feed?.at)\n return {\n vitals: budget,\n alerts: [],\n sections: pageSections(input),\n updatedAt: input.now,\n };\n return {\n vitals: [...budget, ...vitals(input, feed)],\n alerts: alerts(input, feed),\n sections: [...sections(input, feed), ...pageSections(input)],\n updatedAt: feed.at,\n };\n}\n\nexport interface Intervals {\n every(run: () => void, ms: number): unknown;\n stop(handle: unknown): void;\n}\n\nexport const globalIntervals: Intervals = {\n every: (run, ms) => setInterval(run, ms),\n stop: (handle) => clearInterval(handle as ReturnType<typeof setInterval>),\n};\n\nexport interface MonitorAdapterOptions {\n extra?: () => readonly MonitorSection[];\n renewMs?: number;\n intervals?: Intervals;\n now?: () => number;\n}\n\ninterface Open {\n lease: Promise<string | null>;\n timer: unknown;\n}\n\nexport class MonitorAdapter implements MonitorPort {\n readonly #connection: AgentConnection;\n readonly #emitter = new Emitter<MonitorEvents>();\n readonly #extra: () => readonly MonitorSection[];\n readonly #renewMs: number;\n readonly #intervals: Intervals;\n readonly #now: () => number;\n #listeners = 0;\n #open: Open | undefined;\n #history: Sample[] = [];\n\n constructor(connection: AgentConnection, options: MonitorAdapterOptions = {}) {\n this.#connection = connection;\n this.#extra = options.extra ?? (() => []);\n this.#renewMs = options.renewMs ?? RENEW_MS;\n this.#intervals = options.intervals ?? globalIntervals;\n this.#now = options.now ?? Date.now;\n connection.monitor?.subscribe(() => this.#update());\n connection.settings.state.subscribe(() => this.#update());\n connection.changes?.subscribe(() => this.#update());\n connection.sprinkles?.subscribe(() => this.#update());\n }\n\n on<K extends keyof MonitorEvents>(\n type: K,\n listener: (detail: MonitorEvents[K]) => void\n ): () => void {\n const off = this.#emitter.on(type, listener);\n this.#listeners++;\n if (this.#listeners === 1) this.#start();\n let done = false;\n return () => {\n if (done) return;\n done = true;\n off();\n this.#listeners--;\n if (!this.#listeners) this.#stop();\n };\n }\n\n snapshot(): MonitorSnapshot {\n const settings = this.#connection.settings.state.value;\n return monitorSnapshot({\n feed: this.#connection.monitor?.value,\n budget: settings?.budget,\n models: settings?.models ?? [],\n changes: this.#connection.changes?.value?.changes ?? [],\n sprinkles: this.#connection.sprinkles?.value ?? [],\n extra: this.#extra(),\n history: this.#history,\n now: this.#now(),\n });\n }\n\n resync(): void {\n const open = this.#open;\n const control = this.#connection.control;\n if (open)\n void open.lease\n .then((lease) => (lease ? control.monitorOpen(lease, true, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n this.#emitter.emit('snapshot', this.snapshot());\n }\n\n #start(): void {\n const control = this.#connection.control;\n this.#history = [];\n void control.changesOpen(BACKGROUND_CONTEXT).catch(() => undefined);\n const lease = control.monitorOpen(null, true, BACKGROUND_CONTEXT).then(\n (opened) => opened.lease || null,\n () => null\n );\n const renew = () =>\n void lease\n .then((held) => (held ? control.monitorOpen(held, false, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n this.#open = { lease, timer: this.#intervals.every(renew, this.#renewMs) };\n }\n\n #stop(): void {\n const open = this.#open;\n if (!open) return;\n this.#open = undefined;\n this.#intervals.stop(open.timer);\n const control = this.#connection.control;\n void open.lease\n .then((held) => (held ? control.monitorClose(held, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n }\n\n #sample(): void {\n const feed = this.#connection.monitor?.value;\n if (!feed?.open || !feed.usage || this.#history.at(-1)?.at === feed.at) return;\n this.#history.push({\n at: feed.at,\n cost: feed.usage.cost,\n tokens: feed.usage.tokens,\n active: feed.agents.filter((agent) => agent.running).length,\n });\n if (this.#history.length > HISTORY) this.#history.shift();\n }\n\n #update(): void {\n if (!this.#listeners) return;\n this.#sample();\n this.#emitter.emit('snapshot', this.snapshot());\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type {\n MonitorAlert,\n MonitorEvents,\n MonitorPort,\n MonitorRow,\n MonitorSection,\n MonitorSnapshot,\n MonitorStatus,\n MonitorVital,\n} from '@ai-ecoverse/slicc-spectrum/ui';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { AgentConnection } from '../client.ts';\nimport type {\n BudgetState,\n ModelChoice,\n MonitorAgent,\n MonitorFeed,\n MonitorProcess,\n MonitorTask,\n} from '../services.ts';\nimport { Emitter } from './emitter.ts';\n\nexport const RENEW_MS = 10000;\nexport const ROWS_MAX = 200;\nexport const HISTORY = 24;\nexport const BUDGET_WARN = 80;\nexport const BUDGET_ERROR = 95;\nexport const RETRY_WARN = 3;\nexport const RETRY_ERROR = 6;\nexport const RETRY_SLOW_MS = 120000;\nexport const FAILED_MS = 600000;\nexport const ABORT_MS = 30000;\nexport const ABORT_ROW_MS = 10000;\nexport const GROUP_MAX = 32;\nexport const TOTAL_MAX = 128;\nexport const ZOMBIE_MS = 60000;\nexport const STALE_MS = 1800000;\nexport const CPU_SHARE = 0.9;\nexport const CPU_SUSTAIN_MS = 120000;\nexport const CONTEXT_WARN = 0.8;\nexport const DEPTH_MAX = 6;\nconst MINUTE = 60000;\nconst HOUR = 3600000;\n\nexport interface Sample {\n at: number;\n cost: number;\n tokens: number;\n active: number;\n}\n\nexport interface MonitorInput {\n feed: MonitorFeed | undefined;\n budget: BudgetState | null | undefined;\n models: readonly ModelChoice[];\n changes: readonly { path: string; status: string }[];\n sprinkles: readonly { name: string; title: string }[];\n extra: readonly MonitorSection[];\n history: readonly Sample[];\n now: number;\n hot?: ReadonlyMap<number, number>;\n}\n\nconst KINDS: Record<string, string> = {\n 'pi.generation': 'generating',\n 'pi.compaction': 'compacting',\n 'slicc.cron': 'cron',\n 'slicc.scoop-wait': 'agent wait',\n 'slicc.scoop-reporter': 'report',\n 'slicc.memory-extract': 'memory extraction',\n};\n\nexport function age(ms: number): string {\n const seconds = Math.max(0, Math.round(ms / 1000));\n if (seconds < 60) return `${seconds}s`;\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;\n return `${Math.floor(seconds / 3600)}h`;\n}\n\nexport function money(value: number): string {\n if (value > 0 && value < 0.01) return '<$0.01';\n return `$${value.toFixed(2)}`;\n}\n\nexport function count(value: number): string {\n if (value < 1000) return String(value);\n if (value < 1000000) return `${(value / 1000).toFixed(1)}k`;\n return `${(value / 1000000).toFixed(1)}M`;\n}\n\nexport function bytes(value: number): string {\n if (value < 1024) return `${value} B`;\n const units = ['KiB', 'MiB', 'GiB', 'TiB'];\n let size = value / 1024;\n let unit = 0;\n while (size >= 1024 && unit < units.length - 1) {\n size /= 1024;\n unit++;\n }\n return `${size.toFixed(size < 10 ? 1 : 0)} ${units[unit]}`;\n}\n\nfunction memoryVital(processes: readonly MonitorProcess[]): MonitorVital[] {\n const measured = processes.filter((row) => typeof row.rss === 'number');\n if (!measured.length) return [];\n const total = measured.reduce((sum, row) => sum + (row.rss as number), 0);\n const agents = measured\n .filter((row) => row.agentId)\n .reduce((sum, row) => sum + (row.rss as number), 0);\n return [\n {\n id: 'memory',\n label: 'Process memory',\n value: bytes(total),\n unit: `${bytes(agents)} by agents`,\n },\n ];\n}\n\nexport function taskLabel(task: MonitorTask): string {\n if (task.kind === 'pi.tool') return task.detail ? `tool ${task.detail}` : 'tool';\n if (task.kind === 'slicc.scoop-anchor') return task.detail ? `scoop ${task.detail}` : 'scoop';\n return KINDS[task.kind] ?? task.kind;\n}\n\nfunction coneOf(agents: ReadonlyMap<string, MonitorAgent>, id: string | null): string | null {\n const visited = new Set<string>();\n let current = id === null ? undefined : agents.get(id);\n while (current?.parentId && !visited.has(current.id)) {\n visited.add(current.id);\n const parent = agents.get(current.parentId);\n if (!parent) break;\n current = parent;\n }\n return current ? current.id : null;\n}\n\nfunction ordered(feed: MonitorFeed): MonitorAgent[] {\n const byId = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const out: MonitorAgent[] = [];\n for (const cone of feed.agents.filter((agent) => agent.kind === 'cone')) {\n out.push(cone);\n for (const agent of feed.agents)\n if (agent.kind === 'scoop' && coneOf(byId, agent.id) === cone.id) out.push(agent);\n }\n for (const agent of feed.agents) if (!out.includes(agent)) out.push(agent);\n return out;\n}\n\nexport function taskTree(feed: MonitorFeed): { task: MonitorTask; depth: number }[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const order = ordered(feed).map((agent) => agent.id);\n const rank = (task: MonitorTask) => {\n const at = task.agentId === null ? -1 : order.indexOf(task.agentId);\n return at < 0 ? order.length : at;\n };\n const groupOf = (task: MonitorTask) => coneOf(agents, task.agentId) ?? '';\n const byId = new Map(feed.tasks.map((task) => [task.id, task]));\n const children = new Map<string, MonitorTask[]>();\n const roots: MonitorTask[] = [];\n for (const task of feed.tasks) {\n const owner = task.owner === null ? undefined : byId.get(task.owner);\n if (owner && groupOf(owner) === groupOf(task)) {\n const list = children.get(owner.id) ?? [];\n list.push(task);\n children.set(owner.id, list);\n } else roots.push(task);\n }\n const sort = (list: MonitorTask[]) =>\n list.sort((a, b) => rank(a) - rank(b) || Number(a.id) - Number(b.id));\n const out: { task: MonitorTask; depth: number }[] = [];\n const visit = (task: MonitorTask, depth: number) => {\n out.push({ task, depth });\n for (const child of sort(children.get(task.id) ?? [])) visit(child, depth + 1);\n };\n for (const root of sort(roots)) visit(root, 0);\n return out;\n}\n\nfunction capped(rows: MonitorRow[]): MonitorRow[] {\n if (rows.length <= ROWS_MAX) return rows;\n const shown = rows.slice(0, ROWS_MAX - 1);\n return [\n ...shown,\n { id: 'more', name: `+${rows.length - shown.length} more`, meta: '', status: 'idle' },\n ];\n}\n\nfunction contextRatio(agent: MonitorAgent, models: readonly ModelChoice[]): number | null {\n const window = models.find((model) => model.id === agent.model)?.contextWindow;\n if (!agent.context || !window) return null;\n return Math.min(1, agent.context / window);\n}\n\nfunction rate(history: readonly Sample[], pick: (sample: Sample) => number): number | null {\n const first = history[0];\n const last = history.at(-1);\n if (!first || !last || last.at - first.at < MINUTE) return null;\n return ((pick(last) - pick(first)) / (last.at - first.at)) * HOUR;\n}\n\nfunction budgetVital(budget: BudgetState): MonitorVital {\n const resets = new Date(budget.resets);\n return {\n id: 'budget',\n label: `Budget (${budget.window})`,\n value: `${budget.percent}%`,\n ...(Number.isNaN(resets.getTime())\n ? {}\n : { unit: `resets ${resets.toISOString().slice(0, 16).replace('T', ' ')} UTC` }),\n ratio: Math.min(1, Math.max(0, budget.percent / 100)),\n };\n}\n\nfunction vitals(input: MonitorInput, feed: MonitorFeed): MonitorVital[] {\n const out: MonitorVital[] = [];\n if (feed.usage) {\n const free = feed.usage.free;\n const pick = (sample: Sample) => (free ? sample.tokens : sample.cost);\n const perHour = rate(input.history, pick);\n const series = input.history.map(pick);\n out.push({\n id: 'spend',\n label: free ? 'Tokens' : 'Spend',\n value: free ? count(feed.usage.tokens) : money(feed.usage.cost),\n unit: free ? 'tokens' : `${count(feed.usage.tokens)} tokens`,\n ...(perHour === null ? {} : { delta: `${free ? count(perHour) : money(perHour)}/h` }),\n ...(series.length > 1 ? { series } : {}),\n });\n }\n const active = feed.agents.filter((agent) => agent.running).length;\n const actives = input.history.map((sample) => sample.active);\n out.push({\n id: 'agents',\n label: 'Active agents',\n value: String(active),\n unit: `of ${feed.agents.length}`,\n ...(actives.length > 1 ? { series: actives } : {}),\n });\n const tools = feed.tasks.filter(\n (task) => task.kind === 'pi.tool' && task.status === 'running'\n ).length;\n out.push({\n id: 'tasks',\n label: 'Running',\n value: String(tools),\n unit: `${tools === 1 ? 'tool' : 'tools'} \u00B7 ${feed.tasks.length} ${feed.tasks.length === 1 ? 'task' : 'tasks'}`,\n });\n out.push(\n feed.processes\n ? {\n id: 'processes',\n label: 'Processes',\n value: String(feed.processes.length),\n unit: `${feed.processes.filter((row) => row.agentId).length} by agents`,\n }\n : feed.kernel === 'checking'\n ? { id: 'processes', label: 'Processes', value: '\u2026', unit: 'checking' }\n : { id: 'processes', label: 'Processes', value: '\u2014', unit: 'kernel not reachable' }\n );\n out.push(...memoryVital(feed.processes ?? []));\n const ratios = feed.agents\n .map((agent) => contextRatio(agent, input.models))\n .filter((ratio): ratio is number => ratio !== null);\n if (ratios.length) {\n const fullest = Math.max(...ratios);\n out.push({\n id: 'context',\n label: 'Fullest context',\n value: `${Math.round(fullest * 100)}%`,\n ratio: fullest,\n });\n }\n return out;\n}\n\nfunction stale(process: MonitorProcess, agents: ReadonlyMap<string, MonitorAgent>, now: number) {\n if (!process.agentId || process.state === 'Z' || !process.started) return false;\n if (typeof process.utime === 'number') return false;\n if (agents.get(process.agentId)?.tool === 'bash') return false;\n return now - process.started > STALE_MS;\n}\n\nfunction groups(processes: readonly MonitorProcess[]): Map<number, MonitorProcess[]> {\n const out = new Map<number, MonitorProcess[]>();\n for (const process of processes) {\n if (!process.agentId) continue;\n const list = out.get(process.pgid) ?? [];\n list.push(process);\n out.set(process.pgid, list);\n }\n return out;\n}\n\ntype Names = (id: string | null) => string;\n\nexport function groupCpu(\n processes: readonly MonitorProcess[]\n): Map<number, { agentId: string; share: number }> {\n const out = new Map<number, { agentId: string; share: number }>();\n for (const [pgid, members] of groups(processes)) {\n const measured = members.filter((row) => typeof row.cpu === 'number');\n if (!measured.length) continue;\n const share = measured.reduce((sum, row) => sum + (row.cpu as number), 0);\n out.set(pgid, { agentId: (members[0] as MonitorProcess).agentId as string, share });\n }\n return out;\n}\n\nexport function hotGroups(\n processes: readonly MonitorProcess[],\n at: number,\n previous: ReadonlyMap<number, number>\n): Map<number, number> {\n const out = new Map<number, number>();\n for (const [pgid, { share }] of groupCpu(processes))\n if (share >= CPU_SHARE) out.set(pgid, previous.get(pgid) ?? at);\n return out;\n}\n\nfunction busy(input: MonitorInput, processes: readonly MonitorProcess[]) {\n const shares = groupCpu(processes);\n const out: { pgid: number; agentId: string; share: number; held: number }[] = [];\n for (const [pgid, since] of input.hot ?? []) {\n const group = shares.get(pgid);\n const held = input.now - since;\n if (group && group.share >= CPU_SHARE && held >= CPU_SUSTAIN_MS)\n out.push({ pgid, ...group, held });\n }\n return out;\n}\n\nfunction cpuAlerts(input: MonitorInput, processes: readonly MonitorProcess[], nameOf: Names) {\n return busy(input, processes).map(\n (group): MonitorAlert => ({\n id: `runaway-cpu-${group.pgid}`,\n title: `${nameOf(group.agentId)} is using a lot of CPU`,\n detail: `${Math.round(group.share * 100)}% of one core for ${Math.floor(group.held / MINUTE)} minutes. Kill them with kill -- -${group.pgid}.`,\n severity: group.share >= CPU_SHARE * 2 || group.held >= CPU_SUSTAIN_MS * 2 ? 'error' : 'warn',\n })\n );\n}\n\nfunction resetLine(budget: BudgetState): string {\n const resets = new Date(budget.resets);\n return Number.isNaN(resets.getTime())\n ? `The ${budget.window} budget is nearly used up.`\n : `Resets ${resets.toISOString().slice(0, 16).replace('T', ' ')} UTC.`;\n}\n\nfunction budgetAlerts(budget: BudgetState | null | undefined): MonitorAlert[] {\n if (!budget || budget.percent < BUDGET_WARN) return [];\n return [\n {\n id: 'budget',\n title: `Budget ${budget.percent}% used`,\n detail: resetLine(budget),\n severity: budget.percent >= BUDGET_ERROR ? 'error' : 'warn',\n },\n ];\n}\n\nfunction agentAlerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const agent of feed.agents) {\n const retry = agent.retry;\n if (retry && (retry.attempt >= RETRY_WARN || input.now - retry.since > RETRY_SLOW_MS))\n out.push({\n id: `retry-${agent.id}`,\n title: `${agent.name} is retrying (attempt ${retry.attempt})`,\n detail: retry.error,\n severity: retry.attempt >= RETRY_ERROR ? 'error' : 'warn',\n });\n if (agent.failed && !agent.running)\n out.push({\n id: `turn-${agent.id}`,\n title: `${agent.name}'s last turn failed`,\n detail: agent.failed,\n severity: 'error',\n });\n }\n return out;\n}\n\nfunction taskAlerts(input: MonitorInput, feed: MonitorFeed, nameOf: Names): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const problem of feed.problems)\n if (problem.kind === 'task' && input.now - problem.at < FAILED_MS)\n out.push({\n id: `failed-${problem.id}`,\n title: `A task of ${nameOf(problem.agentId)} failed`,\n detail: problem.message,\n severity: 'error',\n });\n for (const task of feed.tasks)\n if (task.aborting !== null && input.now - task.aborting > ABORT_MS)\n out.push({\n id: `abort-${task.id}`,\n title: `Stop is still waiting for ${taskLabel(task)}`,\n detail: `${nameOf(task.agentId)} asked it to stop ${age(input.now - task.aborting)} ago.`,\n severity: 'warn',\n });\n return out;\n}\n\nfunction crowdAlerts(processes: readonly MonitorProcess[], nameOf: Names): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const [pgid, members] of groups(processes))\n if (members.length > GROUP_MAX)\n out.push({\n id: `runaway-${pgid}`,\n title: `${nameOf((members[0] as MonitorProcess).agentId)} has ${members.length} processes`,\n detail: `Kill them with kill -- -${pgid}.`,\n severity: members.length > GROUP_MAX * 2 ? 'error' : 'warn',\n });\n if (processes.length > TOTAL_MAX)\n out.push({\n id: 'runaway-total',\n title: `The kernel has ${processes.length} processes`,\n detail: 'Something may be starting processes in a loop.',\n severity: processes.length > TOTAL_MAX * 2 ? 'error' : 'warn',\n });\n return out;\n}\n\nfunction processAlerts(input: MonitorInput, feed: MonitorFeed, nameOf: Names): MonitorAlert[] {\n const processes = feed.processes ?? [];\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const out = [...crowdAlerts(processes, nameOf), ...cpuAlerts(input, processes, nameOf)];\n for (const process of processes) {\n if (process.zombie !== null && input.now - process.zombie > ZOMBIE_MS)\n out.push({\n id: `zombie-${process.pid}`,\n title: `Process ${process.pid} is a zombie`,\n detail: `Its parent ${process.ppid} hasn't reaped it.`,\n severity: 'warn',\n });\n if (stale(process, agents, input.now))\n out.push({\n id: `stale-${process.pid}`,\n title: `${process.command || `Process ${process.pid}`} has run for ${age(input.now - process.started)}`,\n detail: `${nameOf(process.agentId)} started it in the background. Kill it with kill ${process.pid}.`,\n severity: input.now - process.started > STALE_MS * 2 ? 'error' : 'warn',\n });\n }\n return out;\n}\n\nfunction contextAlerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const out: MonitorAlert[] = [];\n for (const agent of feed.agents) {\n const ratio = contextRatio(agent, input.models);\n if (ratio !== null && ratio >= CONTEXT_WARN)\n out.push({\n id: `context-${agent.id}`,\n title: `${agent.name} is ${Math.round(ratio * 100)}% full`,\n detail: 'Compact it soon to keep replies fast.',\n severity: 'warn',\n });\n }\n if (feed.paused)\n out.push({\n id: 'scheduler',\n title: \"The agent isn't scheduling work\",\n detail: 'Its scheduler is paused.',\n severity: 'warn',\n });\n return out;\n}\n\nfunction alerts(input: MonitorInput, feed: MonitorFeed): MonitorAlert[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const nameOf: Names = (id) => (id ? (agents.get(id)?.name ?? id) : 'the session');\n return [\n ...budgetAlerts(input.budget),\n ...agentAlerts(input, feed),\n ...taskAlerts(input, feed, nameOf),\n ...processAlerts(input, feed, nameOf),\n ...contextAlerts(input, feed),\n ];\n}\n\nfunction agentRow(agent: MonitorAgent, depth: number, models: readonly ModelChoice[]): MonitorRow {\n const ratio = contextRatio(agent, models);\n const word = agent.retry\n ? 'retrying'\n : agent.running\n ? 'running'\n : agent.failed\n ? 'failed'\n : 'idle';\n const status: MonitorStatus = agent.retry\n ? 'warn'\n : agent.running\n ? 'active'\n : agent.failed\n ? 'error'\n : 'idle';\n const model = models.find((choice) => choice.id === agent.model)?.label ?? agent.model;\n const meta = [word, model, ratio === null ? null : `${Math.round(ratio * 100)}% context`]\n .filter(Boolean)\n .join(' \u00B7 ');\n const badges = [\n ...(agent.queued ? [`${agent.queued} queued`] : []),\n ...(agent.tool ? [agent.tool] : []),\n ...(agent.retry ? [`retry ${agent.retry.attempt}`] : []),\n ];\n return {\n id: agent.id,\n name: agent.name,\n meta,\n status,\n depth,\n ...(badges.length ? { badges } : {}),\n };\n}\n\nfunction taskRow(\n task: MonitorTask,\n depth: number,\n nameOf: (id: string | null) => string,\n now: number\n): MonitorRow {\n const aborting = task.aborting !== null && now - task.aborting > ABORT_ROW_MS;\n const status: MonitorStatus = aborting\n ? 'warn'\n : task.status === 'running' || task.status === 'completing'\n ? 'active'\n : 'idle';\n const badges = [\n ...(task.background ? ['background'] : []),\n ...(task.aborting !== null ? ['aborting'] : []),\n ...(task.waits ? [`waits on ${task.waits}`] : []),\n ];\n return {\n id: task.id,\n name: taskLabel(task),\n depth: Math.min(depth, DEPTH_MAX),\n meta: [nameOf(task.agentId), task.phase, age(now - task.since)].filter(Boolean).join(' \u00B7 '),\n status,\n ...(badges.length ? { badges } : {}),\n };\n}\n\nfunction processRows(input: MonitorInput, feed: MonitorFeed): MonitorRow[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const crowded = new Set<number>();\n for (const [pgid, members] of groups(feed.processes ?? []))\n if (members.length > GROUP_MAX) crowded.add(pgid);\n for (const group of busy(input, feed.processes ?? [])) crowded.add(group.pgid);\n return (feed.processes ?? []).map((process) => {\n const runaway = stale(process, agents, input.now) || crowded.has(process.pgid);\n const badges = [\n ...(process.agentId ? [agents.get(process.agentId)?.name ?? process.agentId] : []),\n ...(process.tty ? ['terminal'] : []),\n ];\n return {\n id: String(process.pid),\n name: process.command || `[${process.pid}]`,\n meta: [\n `pid ${process.pid}`,\n process.user,\n typeof process.rss === 'number' ? bytes(process.rss) : null,\n process.started ? age(input.now - process.started) : null,\n ]\n .filter(Boolean)\n .join(' \u00B7 '),\n status: runaway ? 'error' : process.state === 'Z' ? 'warn' : 'idle',\n ...(badges.length ? { badges } : {}),\n };\n });\n}\n\nconst PROBLEM_KINDS = { task: 'task failed', retry: 'retry', turn: 'turn failed' } as const;\n\nfunction depthOf(agents: ReadonlyMap<string, MonitorAgent>, agent: MonitorAgent): number {\n const visited = new Set<string>();\n let depth = 0;\n let current = agent;\n while (current.parentId && !visited.has(current.id)) {\n visited.add(current.id);\n const parent = agents.get(current.parentId);\n if (!parent) break;\n depth++;\n current = parent;\n }\n return depth;\n}\n\nfunction sections(input: MonitorInput, feed: MonitorFeed): MonitorSection[] {\n const agents = new Map(feed.agents.map((agent) => [agent.id, agent]));\n const nameOf = (id: string | null) => (id ? (agents.get(id)?.name ?? id) : 'session');\n return [\n {\n id: 'agents',\n label: 'Cones and scoops',\n rows: ordered(feed).map((agent) =>\n agentRow(agent, Math.min(depthOf(agents, agent), DEPTH_MAX), input.models)\n ),\n },\n {\n id: 'tasks',\n label: 'Tasks',\n rows: capped(\n taskTree(feed).map(({ task, depth }) => taskRow(task, depth, nameOf, input.now))\n ),\n },\n { id: 'processes', label: 'Processes', rows: capped(processRows(input, feed)) },\n {\n id: 'problems',\n label: 'Recent problems',\n rows: feed.problems.map((problem) => ({\n id: problem.id,\n name: `${nameOf(problem.agentId)} \u00B7 ${PROBLEM_KINDS[problem.kind]}`,\n meta: problem.message,\n status: problem.kind === 'retry' ? 'warn' : 'error',\n })),\n },\n ];\n}\n\nfunction pageSections(input: MonitorInput): MonitorSection[] {\n return [\n {\n id: 'changes',\n label: 'Pending changes',\n rows: input.changes.map((change) => ({\n id: change.path,\n name: change.path,\n meta: change.status,\n status: 'warn',\n })),\n },\n {\n id: 'sprinkles',\n label: 'Sprinkles',\n rows: input.sprinkles.map((sprinkle) => ({\n name: sprinkle.title,\n meta: sprinkle.name,\n status: 'idle',\n })),\n },\n ...input.extra,\n ];\n}\n\nexport function monitorSnapshot(input: MonitorInput): MonitorSnapshot {\n const budget = input.budget ? [budgetVital(input.budget)] : [];\n const feed = input.feed;\n if (!feed?.at)\n return {\n vitals: budget,\n alerts: [],\n sections: pageSections(input),\n updatedAt: input.now,\n };\n return {\n vitals: [...budget, ...vitals(input, feed)],\n alerts: alerts(input, feed),\n sections: [...sections(input, feed), ...pageSections(input)],\n updatedAt: feed.at,\n };\n}\n\nexport interface Intervals {\n every(run: () => void, ms: number): unknown;\n stop(handle: unknown): void;\n}\n\nexport const globalIntervals: Intervals = {\n every: (run, ms) => setInterval(run, ms),\n stop: (handle) => clearInterval(handle as ReturnType<typeof setInterval>),\n};\n\nexport interface MonitorAdapterOptions {\n extra?: () => readonly MonitorSection[];\n renewMs?: number;\n intervals?: Intervals;\n now?: () => number;\n}\n\ninterface Open {\n lease: Promise<string | null>;\n timer: unknown;\n}\n\nexport class MonitorAdapter implements MonitorPort {\n readonly #connection: AgentConnection;\n readonly #emitter = new Emitter<MonitorEvents>();\n readonly #extra: () => readonly MonitorSection[];\n readonly #renewMs: number;\n readonly #intervals: Intervals;\n readonly #now: () => number;\n #listeners = 0;\n #open: Open | undefined;\n #history: Sample[] = [];\n #hot = new Map<number, number>();\n #hotAt = -1;\n\n constructor(connection: AgentConnection, options: MonitorAdapterOptions = {}) {\n this.#connection = connection;\n this.#extra = options.extra ?? (() => []);\n this.#renewMs = options.renewMs ?? RENEW_MS;\n this.#intervals = options.intervals ?? globalIntervals;\n this.#now = options.now ?? Date.now;\n connection.monitor?.subscribe(() => this.#update());\n connection.settings.state.subscribe(() => this.#update());\n connection.changes?.subscribe(() => this.#update());\n connection.sprinkles?.subscribe(() => this.#update());\n }\n\n on<K extends keyof MonitorEvents>(\n type: K,\n listener: (detail: MonitorEvents[K]) => void\n ): () => void {\n const off = this.#emitter.on(type, listener);\n this.#listeners++;\n if (this.#listeners === 1) this.#start();\n let done = false;\n return () => {\n if (done) return;\n done = true;\n off();\n this.#listeners--;\n if (!this.#listeners) this.#stop();\n };\n }\n\n snapshot(): MonitorSnapshot {\n const settings = this.#connection.settings.state.value;\n return monitorSnapshot({\n feed: this.#connection.monitor?.value,\n budget: settings?.budget,\n models: settings?.models ?? [],\n changes: this.#connection.changes?.value?.changes ?? [],\n sprinkles: this.#connection.sprinkles?.value ?? [],\n extra: this.#extra(),\n history: this.#history,\n now: this.#now(),\n hot: this.#hot,\n });\n }\n\n resync(): void {\n const open = this.#open;\n const control = this.#connection.control;\n if (open)\n void open.lease\n .then((lease) => (lease ? control.monitorOpen(lease, true, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n this.#emitter.emit('snapshot', this.snapshot());\n }\n\n #start(): void {\n const control = this.#connection.control;\n this.#history = [];\n this.#hot = new Map();\n this.#hotAt = -1;\n void control.changesOpen(BACKGROUND_CONTEXT).catch(() => undefined);\n const lease = control.monitorOpen(null, true, BACKGROUND_CONTEXT).then(\n (opened) => opened.lease || null,\n () => null\n );\n const renew = () =>\n void lease\n .then((held) => (held ? control.monitorOpen(held, false, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n this.#open = { lease, timer: this.#intervals.every(renew, this.#renewMs) };\n }\n\n #stop(): void {\n const open = this.#open;\n if (!open) return;\n this.#open = undefined;\n this.#intervals.stop(open.timer);\n const control = this.#connection.control;\n void open.lease\n .then((held) => (held ? control.monitorClose(held, BACKGROUND_CONTEXT) : undefined))\n .catch(() => undefined);\n }\n\n #sample(): void {\n const feed = this.#connection.monitor?.value;\n if (!feed?.open || !feed.usage || this.#history.at(-1)?.at === feed.at) return;\n this.#history.push({\n at: feed.at,\n cost: feed.usage.cost,\n tokens: feed.usage.tokens,\n active: feed.agents.filter((agent) => agent.running).length,\n });\n if (this.#history.length > HISTORY) this.#history.shift();\n }\n\n #track(): void {\n const feed = this.#connection.monitor?.value;\n if (!feed?.open || feed.at === this.#hotAt) return;\n this.#hotAt = feed.at;\n this.#hot = hotGroups(feed.processes ?? [], feed.at, this.#hot);\n }\n\n #update(): void {\n if (!this.#listeners) return;\n this.#sample();\n this.#track();\n this.#emitter.emit('snapshot', this.snapshot());\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { type Context, type ReplicatedState } from '@earendil-works/chord';
2
2
  import type { ConversationView, Harness, UsageState } from '@earendil-works/pi-durable';
3
3
  import { type AgentsState } from '../agents.ts';
4
- import type { MonitorFeed, MonitorLease } from '../services.ts';
4
+ import type { MonitorFeed, MonitorLease, MonitorProcess } from '../services.ts';
5
5
  export interface PsEntry {
6
6
  pid: number;
7
7
  ppid?: number;
@@ -12,7 +12,20 @@ export interface PsEntry {
12
12
  state?: string;
13
13
  uid?: number;
14
14
  rss?: number;
15
+ utime?: number;
16
+ stime?: number;
15
17
  }
18
+ export interface CpuMark {
19
+ started: number;
20
+ total: number;
21
+ at: number;
22
+ }
23
+ export interface CpuReading {
24
+ marks: Map<number, CpuMark>;
25
+ shares: Map<number, number | null>;
26
+ }
27
+ export declare function cpuShares(entries: readonly PsEntry[], previous: ReadonlyMap<number, CpuMark>, at: number): CpuReading;
28
+ export declare function agentCpu(processes: readonly MonitorProcess[], agentId: string): number | null;
16
29
  export interface Timers {
17
30
  set(run: () => void, ms: number): unknown;
18
31
  clear(handle: unknown): void;
@@ -104,6 +104,7 @@ export interface MonitorAgent {
104
104
  } | null;
105
105
  failed: string | null;
106
106
  context: number | null;
107
+ cpu?: number | null;
107
108
  }
108
109
  export interface MonitorTask {
109
110
  id: string;
@@ -130,6 +131,9 @@ export interface MonitorProcess {
130
131
  zombie: number | null;
131
132
  tty: boolean;
132
133
  rss: number | null;
134
+ utime?: number;
135
+ stime?: number;
136
+ cpu?: number | null;
133
137
  }
134
138
  export interface MonitorProblem {
135
139
  id: string;
@@ -1,6 +1,6 @@
1
1
  import type { MonitorEvents, MonitorPort, MonitorSection, MonitorSnapshot } from '@ai-ecoverse/slicc-spectrum/ui';
2
2
  import type { AgentConnection } from '../client.ts';
3
- import type { BudgetState, ModelChoice, MonitorFeed, MonitorTask } from '../services.ts';
3
+ import type { BudgetState, ModelChoice, MonitorFeed, MonitorProcess, MonitorTask } from '../services.ts';
4
4
  export declare const RENEW_MS = 10000;
5
5
  export declare const ROWS_MAX = 200;
6
6
  export declare const HISTORY = 24;
@@ -16,6 +16,8 @@ export declare const GROUP_MAX = 32;
16
16
  export declare const TOTAL_MAX = 128;
17
17
  export declare const ZOMBIE_MS = 60000;
18
18
  export declare const STALE_MS = 1800000;
19
+ export declare const CPU_SHARE = 0.9;
20
+ export declare const CPU_SUSTAIN_MS = 120000;
19
21
  export declare const CONTEXT_WARN = 0.8;
20
22
  export declare const DEPTH_MAX = 6;
21
23
  export interface Sample {
@@ -39,6 +41,7 @@ export interface MonitorInput {
39
41
  extra: readonly MonitorSection[];
40
42
  history: readonly Sample[];
41
43
  now: number;
44
+ hot?: ReadonlyMap<number, number>;
42
45
  }
43
46
  export declare function age(ms: number): string;
44
47
  export declare function money(value: number): string;
@@ -49,6 +52,11 @@ export declare function taskTree(feed: MonitorFeed): {
49
52
  task: MonitorTask;
50
53
  depth: number;
51
54
  }[];
55
+ export declare function groupCpu(processes: readonly MonitorProcess[]): Map<number, {
56
+ agentId: string;
57
+ share: number;
58
+ }>;
59
+ export declare function hotGroups(processes: readonly MonitorProcess[], at: number, previous: ReadonlyMap<number, number>): Map<number, number>;
52
60
  export declare function monitorSnapshot(input: MonitorInput): MonitorSnapshot;
53
61
  export interface Intervals {
54
62
  every(run: () => void, ms: number): unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-ecoverse/slicc-agent",
3
- "version": "3.45.2",
3
+ "version": "3.46.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.13.1",
66
- "@ai-ecoverse/slicc-spectrum": "1.62.0",
66
+ "@ai-ecoverse/slicc-spectrum": "1.62.1",
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",