@noopolis/daimon 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,6 +58,8 @@ export type GrokEngineBrokerTurnDependencies = Readonly<{
58
58
  runNative(input: NativeBrokerTurn, signal: AbortSignal): Promise<Readonly<NativeBrokerTurnResult>>;
59
59
  /** The worker the launcher started for this identity (`/proc` by default); only read when the broker ends a turn itself. */
60
60
  observeWorker?(workerUid: number): Promise<GrokWorkerProcess | undefined>;
61
+ /** Whether the worker identity has a live local tool process (default: `grokWorkerToolProcessLive` over `/proc`). */
62
+ observeToolProcess?(workerUid: number): Promise<boolean>;
61
63
  /** Overrides the turn-end grace and idle bounds (tests). */
62
64
  turnEnd?: GrokBrokerTurnEndTiming;
63
65
  /** Whether no live process holds the worker identity (`/proc` by default); polled, bounded, before an aborted turn is sealed. */
@@ -1 +1 @@
1
- {"version":3,"file":"grokEngineBrokerTurn.d.ts","sourceRoot":"","sources":["../../src/runtime/grokEngineBrokerTurn.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grokEngineBrokerTurn.d.ts","sourceRoot":"","sources":["../../src/runtime/grokEngineBrokerTurn.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import { finishBrokerTurnWithUsage } from "./grokEngineBrokerMetering.js";
14
14
  import { GrokBrokerTurnMeter } from "./grokBrokerTurnMeter.js";
15
15
  import { awaitGrokWorkerIdentityEmpty, findGrokWorkerProcess, GROK_WORKER_REAP_WAIT_MS, grokWorkerIdentityEmpty, watchGrokBrokerTurnEnd } from "./grokEngineBrokerTurnEnd.js";
16
16
  import { GrokWorkerAttestationFailure } from "./grokWorkerAttestation.js";
17
+ import { grokWorkerToolProcessLive, grokWorkerToolProcessSampler } from "./grokWorkerToolProcess.js";
17
18
  export class EngineBrokerTurnFailure extends Error {
18
19
  code;
19
20
  diagnostic;
@@ -119,12 +120,14 @@ export async function runGrokEngineBrokerTurn(deps, registration, wakeId, prompt
119
120
  deps.proxy.registerTurn(turnId, { policy: registration.model, meter, clock });
120
121
  const capabilityTtlMs = engineBrokerCapabilityTtlMs(limits.timeoutMs);
121
122
  const providerCapability = deps.proxy.capabilities.issue(agentId, turnId, capabilityTtlMs), mcpCapability = deps.mcp.register(agentId, turnId, mcpEndpoint, capabilityTtlMs);
123
+ // A shell command Grok runs itself is work the proxy and facade never see.
124
+ const toolProcess = grokWorkerToolProcessSampler(() => (deps.observeToolProcess ?? grokWorkerToolProcessLive)(registration.workerUid));
122
125
  watchdog = watchGrokBrokerTurnEnd({
123
- meter, activity: () => deps.mcp.activity?.(turnId), signal: controller.signal, ...(deps.turnEnd === undefined ? {} : { timing: deps.turnEnd }),
126
+ meter, activity: () => deps.mcp.activity?.(turnId), toolProcess: toolProcess.live, signal: controller.signal, ...(deps.turnEnd === undefined ? {} : { timing: deps.turnEnd }),
124
127
  // The worker is read once, as soon as it has made a request — long before
125
128
  // anything can end the turn and reap it — so a final reply is never left
126
129
  // without the worker that gave it.
127
- onPoll: () => { if (worker === undefined && meter.snapshot().requests > 0)
130
+ onPoll: () => { toolProcess.poll(); if (worker === undefined && meter.snapshot().requests > 0)
128
131
  worker = (deps.observeWorker ?? findGrokWorkerProcess)(registration.workerUid).catch(() => undefined); },
129
132
  onFinalReply: () => { worker ??= (deps.observeWorker ?? findGrokWorkerProcess)(registration.workerUid).catch(() => undefined); },
130
133
  // An idle stall is a deadline of its own: it trips the meter as a timeout, so it seals like one.
@@ -30,8 +30,12 @@ import type { GrokBrokerTurnMeter } from "./grokBrokerTurnMeter.js";
30
30
  * so a model that keeps going is never cut off. Independently, a turn with no
31
31
  * model request and no tool call in flight and no activity of either kind for
32
32
  * `idleMs` ends as `onEnd("idle")` — the backstop for a worker that stalls
33
- * without ever answering. Shell tools Grok runs itself are invisible here, so
34
- * the idle bound is minutes, not seconds.
33
+ * without ever answering. Shell tools Grok runs itself never reach the proxy
34
+ * or the facade, and Grok lets the model give one a timeout of up to ten
35
+ * hours, so a worker with a live tool process (`toolProcess`,
36
+ * `grokWorkerToolProcess.ts`) is working too: it is never idle while one runs,
37
+ * and the quiet clock restarts from the last poll that saw one. The idle bound
38
+ * stays minutes, not seconds, because that observation is a poll.
35
39
  */
36
40
  export type GrokBrokerTurnEndTiming = Readonly<{
37
41
  finalGraceMs: number;
@@ -45,6 +49,8 @@ export type GrokBrokerTurnEndReason = "final_reply" | "idle";
45
49
  export declare function watchGrokBrokerTurnEnd(input: Readonly<{
46
50
  meter: Pick<GrokBrokerTurnMeter, "finalReply" | "busy" | "lastActivityAt">;
47
51
  activity: () => EngineBrokerMcpActivity | undefined;
52
+ /** Whether the worker has a local tool process alive, as last observed; absent means never observed. */
53
+ toolProcess?: () => boolean;
48
54
  onFinalReply: () => void;
49
55
  /** Every poll, before any decision: the broker records the worker while it is certainly alive. */
50
56
  onPoll?: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"grokEngineBrokerTurnEnd.d.ts","sourceRoot":"","sources":["../../src/runtime/grokEngineBrokerTurnEnd.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzG,eAAO,MAAM,oBAAoB,EAAE,uBAAqG,CAAC;AACzI,qGAAqG;AACrG,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,MAAM,CAAC;AAE7D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC;IACrD,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,MAAM,GAAG,gBAAgB,CAAC,CAAC;IAC3E,QAAQ,EAAE,MAAM,uBAAuB,GAAG,SAAS,CAAC;IACpD,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC,GAAG,QAAQ,CAAC;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,CAAC,CAyB9B;AAED,oJAAoJ;AACpJ,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAqBnH;AAED,2DAA2D;AAC3D,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAU,EAAE,eAAe,UAAQ,GACvD,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAA2B,EAAE,MAAM,SAAM,EAAE,QAAQ,SAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAarM"}
1
+ {"version":3,"file":"grokEngineBrokerTurnEnd.d.ts","sourceRoot":"","sources":["../../src/runtime/grokEngineBrokerTurnEnd.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzG,eAAO,MAAM,oBAAoB,EAAE,uBAAqG,CAAC;AACzI,qGAAqG;AACrG,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,MAAM,MAAM,uBAAuB,GAAG,aAAa,GAAG,MAAM,CAAC;AAE7D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,QAAQ,CAAC;IACrD,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,MAAM,GAAG,gBAAgB,CAAC,CAAC;IAC3E,QAAQ,EAAE,MAAM,uBAAuB,GAAG,SAAS,CAAC;IACpD,wGAAwG;IACxG,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;IAC5B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,CAAC,MAAM,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACjD,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC,GAAG,QAAQ,CAAC;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,CAAC,CA8B9B;AAED,oJAAoJ;AACpJ,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9E;;;;;;;;;;;GAWG;AACH,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAqBnH;AAED,2DAA2D;AAC3D,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAU,EAAE,eAAe,UAAQ,GACvD,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAED;;;;;;;GAOG;AACH,wBAAsB,4BAA4B,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAA2B,EAAE,MAAM,SAAM,EAAE,QAAQ,SAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAarM"}
@@ -5,7 +5,7 @@ export const GROK_BROKER_TURN_END = Object.freeze({ finalGraceMs: 15_000, idleMs
5
5
  export const GROK_WORKER_REAP_WAIT_MS = 10_000;
6
6
  export function watchGrokBrokerTurnEnd(input) {
7
7
  const timing = input.timing ?? GROK_BROKER_TURN_END, now = input.now ?? Date.now;
8
- let notified, done = false;
8
+ let notified, done = false, toolSeenAt = 0;
9
9
  const check = () => {
10
10
  if (done)
11
11
  return;
@@ -32,11 +32,22 @@ export function watchGrokBrokerTurnEnd(input) {
32
32
  catch {
33
33
  activity = undefined;
34
34
  }
35
+ let tool = false;
36
+ try {
37
+ tool = input.toolProcess?.() === true;
38
+ }
39
+ catch {
40
+ tool = false;
41
+ }
42
+ if (tool)
43
+ toolSeenAt = now();
35
44
  if (input.meter.busy() || (activity?.inFlight ?? 0) > 0)
36
45
  return;
37
46
  const quietSince = Math.max(input.meter.lastActivityAt(), activity?.lastActivityAt ?? 0);
47
+ // A tool process defers only the idle verdict. A final reply called no tool, so a child still
48
+ // alive beside it is not the model's work and must not hold a finished worker open.
38
49
  const reason = final !== undefined && now() - Math.max(final.at, quietSince) >= timing.finalGraceMs ? "final_reply"
39
- : now() - quietSince >= timing.idleMs ? "idle" : undefined;
50
+ : now() - Math.max(quietSince, toolSeenAt) >= timing.idleMs ? "idle" : undefined;
40
51
  if (reason === undefined)
41
52
  return;
42
53
  stop();
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Whether a Grok worker is running one of its own local tools right now,
3
+ * read-only from `/proc`.
4
+ *
5
+ * The broker sees every model request (the proxy) and every MCP tool call (the
6
+ * facade), but not the tools Grok runs in-process: `run_terminal_command`
7
+ * executes as a child of the worker. Grok 1.0.34 advertises that tool with a
8
+ * model-chosen timeout of up to 36 000 000 ms (default 120 000 ms), so a
9
+ * command the model gave a long timeout is real work the broker cannot see,
10
+ * and the idle watchdog (`grokEngineBrokerTurnEnd.ts`) used to end such a turn
11
+ * as stalled ten minutes in.
12
+ *
13
+ * Every engine process carries the argv the launcher compiled — the outer
14
+ * bubblewrap wrapper Grok re-executes into and the Grok process inside it —
15
+ * so `--output-format streaming-messages-json` marks them. A live (non-zombie)
16
+ * process owned by `uid` whose parent is such an engine process, and which is
17
+ * not one itself, is a tool the worker started and is waiting on. Short-lived
18
+ * helpers count too, which only delays an idle verdict by a poll.
19
+ *
20
+ * An unreadable `/proc` (or one mounted `hidepid`) answers `false`: the
21
+ * watchdog then behaves exactly as it did without this signal.
22
+ */
23
+ export declare function grokWorkerToolProcessLive(uid: number, procRoot?: string): Promise<boolean>;
24
+ /**
25
+ * The watchdog's poll is synchronous and `/proc` is not, so the turn keeps the
26
+ * last answer: `poll()` starts one read when none is pending, `live()` returns
27
+ * the latest completed one. A failed read answers `false`, as an unreadable
28
+ * `/proc` does.
29
+ */
30
+ export declare function grokWorkerToolProcessSampler(read: () => Promise<boolean>): Readonly<{
31
+ poll(): void;
32
+ live(): boolean;
33
+ }>;
34
+ //# sourceMappingURL=grokWorkerToolProcess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grokWorkerToolProcess.d.ts","sourceRoot":"","sources":["../../src/runtime/grokWorkerToolProcess.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBjG;AAQD;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC;IAAE,IAAI,IAAI,IAAI,CAAC;IAAC,IAAI,IAAI,OAAO,CAAA;CAAE,CAAC,CAUtH"}
@@ -0,0 +1,78 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ /**
3
+ * Whether a Grok worker is running one of its own local tools right now,
4
+ * read-only from `/proc`.
5
+ *
6
+ * The broker sees every model request (the proxy) and every MCP tool call (the
7
+ * facade), but not the tools Grok runs in-process: `run_terminal_command`
8
+ * executes as a child of the worker. Grok 1.0.34 advertises that tool with a
9
+ * model-chosen timeout of up to 36 000 000 ms (default 120 000 ms), so a
10
+ * command the model gave a long timeout is real work the broker cannot see,
11
+ * and the idle watchdog (`grokEngineBrokerTurnEnd.ts`) used to end such a turn
12
+ * as stalled ten minutes in.
13
+ *
14
+ * Every engine process carries the argv the launcher compiled — the outer
15
+ * bubblewrap wrapper Grok re-executes into and the Grok process inside it —
16
+ * so `--output-format streaming-messages-json` marks them. A live (non-zombie)
17
+ * process owned by `uid` whose parent is such an engine process, and which is
18
+ * not one itself, is a tool the worker started and is waiting on. Short-lived
19
+ * helpers count too, which only delays an idle verdict by a poll.
20
+ *
21
+ * An unreadable `/proc` (or one mounted `hidepid`) answers `false`: the
22
+ * watchdog then behaves exactly as it did without this signal.
23
+ */
24
+ export async function grokWorkerToolProcessLive(uid, procRoot = "/proc") {
25
+ let entries;
26
+ try {
27
+ entries = await readdir(procRoot);
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ const owned = new Map();
33
+ for (const entry of entries) {
34
+ if (!/^\d+$/u.test(entry))
35
+ continue;
36
+ try {
37
+ const status = await readFile(`${procRoot}/${entry}/status`, "utf8");
38
+ if (Number(/^Uid:\s+(\d+)/mu.exec(status)?.[1]) !== uid)
39
+ continue;
40
+ if (/^State:\s+[ZX]/mu.test(status))
41
+ continue;
42
+ const parent = Number(/^PPid:\s+(\d+)/mu.exec(status)?.[1]);
43
+ if (!Number.isSafeInteger(parent))
44
+ continue;
45
+ const argv = (await readFile(`${procRoot}/${entry}/cmdline`, "utf8")).split("\0");
46
+ owned.set(Number(entry), { parent, engine: isGrokEngineArgv(argv) });
47
+ }
48
+ catch { /* a process exiting mid-scan is not part of the answer */ }
49
+ }
50
+ for (const process of owned.values()) {
51
+ if (!process.engine && owned.get(process.parent)?.engine === true)
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ /** The compiled worker argv pair every engine process of a brokered turn carries (`grokBrokerWorkerConfig.ts`). */
57
+ function isGrokEngineArgv(argv) {
58
+ const flag = argv.indexOf("--output-format");
59
+ return flag !== -1 && argv[flag + 1] === "streaming-messages-json";
60
+ }
61
+ /**
62
+ * The watchdog's poll is synchronous and `/proc` is not, so the turn keeps the
63
+ * last answer: `poll()` starts one read when none is pending, `live()` returns
64
+ * the latest completed one. A failed read answers `false`, as an unreadable
65
+ * `/proc` does.
66
+ */
67
+ export function grokWorkerToolProcessSampler(read) {
68
+ let live = false, pending = false;
69
+ return {
70
+ poll: () => {
71
+ if (pending)
72
+ return;
73
+ pending = true;
74
+ void Promise.resolve().then(read).then((value) => { live = value; }, () => { live = false; }).finally(() => { pending = false; });
75
+ },
76
+ live: () => live
77
+ };
78
+ }
@@ -226,7 +226,7 @@ function moltnetTool(agent, wakeContext) {
226
226
  }
227
227
  async function connect(agent, server) {
228
228
  taskClockChildEnvironment(server.env);
229
- const client = new Client({ name: "daimon-production", version: "0.2.3" });
229
+ const client = new Client({ name: "daimon-production", version: "0.2.4" });
230
230
  const headers = server.authSecretEnv === undefined ? {} : { authorization: `Bearer ${requiredSecret(server.authSecretEnv)}` };
231
231
  const transport = server.transport === "stdio"
232
232
  ? new StdioClientTransport({ command: server.command, args: [...server.args], env: stringEnvironment(readyTaskClockEnvironment({ ...server.env, ...cliChildEnvironment([], agent.runtimeHomePath, { executablePath: server.command }) })) })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noopolis/daimon",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "Noopolis native per-agent runtime harness built on Pi.",
5
5
  "license": "MIT",
6
6
  "type": "module",