@mono-agent/agent-runtime 0.15.2 → 0.15.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.
Files changed (39) hide show
  1. package/README.md +55 -7
  2. package/package.json +5 -1
  3. package/src/agent/tools/agent-tool.js +859 -0
  4. package/src/agent/tools/bash.js +241 -123
  5. package/src/agent/tools/exec.js +238 -0
  6. package/src/agent/tools/index.js +10 -3
  7. package/src/agent/tools/node-repl.js +231 -95
  8. package/src/agent/tools/pi-bridge.js +115 -24
  9. package/src/agent/tools/shared/process-runner.js +162 -0
  10. package/src/agent/tools/shared/semaphore.js +73 -0
  11. package/src/agent/tools/web-browser-render.js +221 -0
  12. package/src/agent/tools/web-controller.js +160 -0
  13. package/src/agent/tools/web-fetch.js +653 -68
  14. package/src/agent/tools/web-search.js +568 -16
  15. package/src/ai/providers/codex-app.js +18 -0
  16. package/src/ai/providers/pi-native/stream-subscriber.js +37 -0
  17. package/src/ai/providers/pi-native/turn-runner.js +60 -5
  18. package/src/ai/providers/pi-native.js +49 -5
  19. package/src/ai/runtime/router.js +302 -166
  20. package/src/ai/types.js +52 -1
  21. package/src/runtime.js +51 -1
  22. package/types/agent/tools/agent-tool.d.ts +60 -0
  23. package/types/agent/tools/bash.d.ts +55 -7
  24. package/types/agent/tools/exec.d.ts +53 -0
  25. package/types/agent/tools/index.d.ts +5 -3
  26. package/types/agent/tools/node-repl.d.ts +28 -3
  27. package/types/agent/tools/pi-bridge.d.ts +6 -2
  28. package/types/agent/tools/shared/process-runner.d.ts +33 -0
  29. package/types/agent/tools/shared/semaphore.d.ts +29 -0
  30. package/types/agent/tools/web-browser-render.d.ts +16 -0
  31. package/types/agent/tools/web-controller.d.ts +20 -0
  32. package/types/agent/tools/web-fetch.d.ts +74 -5
  33. package/types/agent/tools/web-search.d.ts +81 -5
  34. package/types/ai/backend.d.ts +57 -0
  35. package/types/ai/providers/pi-native/turn-runner.d.ts +34 -2
  36. package/types/ai/providers/pi-native.d.ts +12 -0
  37. package/types/ai/registry.d.ts +1 -0
  38. package/types/ai/runtime/router.d.ts +23 -3
  39. package/types/ai/types.d.ts +163 -1
package/README.md CHANGED
@@ -246,12 +246,19 @@ inferSkillsRoot
246
246
 
247
247
  ```text
248
248
  bashToolImpl
249
+ bashToolRun
250
+ createWebToolController
249
251
  editToolImpl
252
+ execToolImpl
253
+ execToolRun
250
254
  globToolImpl
251
255
  grepToolImpl
252
256
  isPathAllowed
253
257
  isWorkdirAllowed
254
258
  normalizeBashTimeoutMs
259
+ normalizeProcessTimeoutMs
260
+ performWebFetch
261
+ performWebSearch
255
262
  readToolImpl
256
263
  resolveRgPath
257
264
  webFetchToolImpl
@@ -650,8 +657,11 @@ Per-call options (a non-exhaustive selection):
650
657
  | `cwd` | `string` | Working directory for the agent's tools. |
651
658
  | `allowedTools` | `string[]` | Built-in tool allowlist. Default: all. |
652
659
  | `disallowedTools` | `string[]` | Block list. |
653
- | `mcpServers` | `Record<string, McpServerConfig>` | Configured MCP servers (stdio / sse / http). |
660
+ | `mcpServers` | `Record<string, McpServerConfig>` | Configured MCP servers (stdio / sse / http); on direct Codex, each forwarded server authorizes its own tool calls. |
654
661
  | `sandboxPolicy` | `SandboxPolicy` | Optional fail-closed sandbox policy for built-in tools and stdio MCP process startup. |
662
+ | `webSearchConfig` | `{ backend?, endpoint? }` | Run-scoped local SearXNG/keyless WebSearch backend selection. |
663
+ | `webFetchConfig` | `{ render?, browserCommand? }` | Run-scoped static extraction and optional isolated browser-render policy. |
664
+ | `piToolExecutionMode` | `"safe-parallel" \| "sequential"` | Pi built-in scheduling. Safe parallelism is the default; stateful/mutating and MCP tools stay sequential. |
655
665
  | `maxTurns` | `number` | Hard cap on agent turns. |
656
666
  | `outputSchema` | `JSONSchema` | Requests structured JSON on capable bridges; see “Structured output” below for bridge-specific return behavior. |
657
667
  | `abortSignal` | `AbortSignal` | Cancel the run. |
@@ -744,13 +754,29 @@ Successful provider requests may also emit exact context telemetry through
744
754
 
745
755
  ### Built-in tools
746
756
 
747
- The agent kernel's managed tools are `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`, `NodeRepl`, `WebFetch`, and `WebSearch`. `NodeRepl({ code })` is backed by one lazily started Node.js REPL child per run. You select them via `allowedTools`. Tool implementations honor:
757
+ The agent kernel's managed tools are `Read`, `Write`, `Edit`, `Glob`, `Grep`,
758
+ `Exec`, `Bash`, `NodeRepl`, `WebFetch`, and `WebSearch`.
759
+ `Exec({ executable, args })` invokes one executable directly; `Bash` is the
760
+ clean non-interactive shell surface for pipelines, redirection, and other shell
761
+ syntax. Both preserve bounded partial stdout/stderr and structured exit,
762
+ timeout, abort, signal, and truncation metadata. `NodeRepl({ code })` is backed
763
+ by one lazily started Node.js REPL child per run. You select them via
764
+ `allowedTools`. Tool implementations honor:
748
765
 
749
766
  - `cwd` (required for path-based tools)
750
767
  - The runtime context's `workspace` / `repoRoot` allow-list (paths outside both, plus `/tmp` and `process.cwd()`, are rejected)
751
768
  - Output truncation with optional artifact persistence (`{toolArtifactDir}/tool-output/{runId}/...` when `toolArtifactDir` is configured)
752
769
 
753
- `NodeRepl` uses Node's default `node:repl` evaluator, so variables, `_`, `_error`, and loaded modules persist across calls in the same run. It supports multiline input and top-level `await`, resolves workspace-installed packages, and is closed with the run. Its child is prepared through the same sandbox seam as `Bash`; abort, the fixed 120-second timeout, child exit, or hard output overflow resets the session. It deliberately has no session ids, persistent history, terminal commands, or package-install surface.
770
+ `NodeRepl` uses Node's default `node:repl` evaluator, so variables, `_`, `_error`, and loaded modules persist across calls in the same run. It supports multiline input and top-level `await`, resolves workspace-installed packages, and is closed with the run. Its child is prepared through the same sandbox seam as `Exec`/`Bash` and communicates through token-authenticated, length-prefixed JSON frames on ordinary stdin/stdout; abort, the fixed 120-second timeout, child exit, or hard output overflow resets the session. It deliberately has no session ids, persistent history, terminal commands, or package-install surface.
771
+
772
+ `WebSearch` uses a configured loopback SearXNG endpoint and/or deterministic
773
+ public fallbacks that require no credentials. It canonicalizes and deduplicates
774
+ results, then fuses multiple query rankings. `WebFetch` extracts HTML, JSON,
775
+ feeds, PDFs, and text locally with
776
+ bounded redirects, bodies, headers, and retries. Config can opt into isolated
777
+ `agent-browser` rendering for sparse client-rendered HTML. One ephemeral
778
+ controller per run deduplicates identical calls and closes every browser
779
+ namespace at run end.
754
780
 
755
781
  Pi runs with selected skills also expose `ReadSkill`. It returns the complete
756
782
  skill instructions by default, including content beyond the former
@@ -760,6 +786,17 @@ truncation is explicitly desired; omitting it is not a separate hidden limit.
760
786
  The standard 256 KiB tool-payload guard still applies to oversized tool results.
761
787
 
762
788
  Override or extend the tool surface by passing `mcpServers` for MCP-backed tools.
789
+ On direct Codex normal runs, each valid server that survives translation into
790
+ the app-server config is the authorization boundary for the tools it exposes.
791
+ The bridge accepts Codex's synthesized `mcp_tool_call` elicitation for that exact
792
+ server without persisting an approval. Inherited or otherwise unconfigured
793
+ server names, genuine downstream MCP elicitations, and other app-server requests
794
+ remain fail-closed.
795
+
796
+ This also applies under direct Codex `permissionMode: "plan"`: the read-only
797
+ sandbox constrains Codex-owned filesystem and command execution, but a declared
798
+ MCP tool can still change state managed by its server. Do not declare a server
799
+ whose complete tool surface is not authorized for the run.
763
800
 
764
801
  ### Structured output
765
802
 
@@ -783,8 +820,10 @@ import { createRouterRuntime } from "@mono-agent/agent-runtime";
783
820
  const router = createRouterRuntime({
784
821
  host: { /* same shape as createRuntime */ },
785
822
  routeSafety: "per-route-native",
823
+ // Backoff shape for same-model retries; per-route counts live on `attempts`.
824
+ retry: { backoffMs: 1000, maxBackoffMs: 15000 },
786
825
  chain: [
787
- { model: { sdk: "claude", model: "claude-sonnet-5" }, effort: "high" },
826
+ { model: { sdk: "claude", model: "claude-sonnet-5" }, effort: "high", attempts: 2 },
788
827
  { model: { sdk: "codex", model: "gpt-5.6-sol" }, effort: "xhigh" },
789
828
  { model: { sdk: "pi", provider: "ollama", model: "gemma4:31b" }, effort: null },
790
829
  ],
@@ -797,8 +836,11 @@ console.log(result.failoverHistory, result.routeSafetyHistory);
797
836
  Behaviour:
798
837
 
799
838
  - Successful run on entry N → returns the result with `failoverHistory` set to attempts 0..N-1.
800
- - Retryable provider failure → emits `provider_failover_started`, builds a transcript snapshot, and retries on the next entry.
801
- - Context-window failure after bridge compaction recovery preserves `failureKind: "context_limit"` in `failoverHistory` and tries the next entry; quota/output/max-turn `usage_limit` remains terminal.
839
+ - Retryable provider failure → retries the SAME entry while it has `attempts` left (emitting `provider_retry_started` after a doubling backoff), then emits `provider_failover_started`, builds a transcript snapshot, and advances to the next entry. `attempts` defaults to `1` per entry, so the kernel is single-shot unless a host opts in — `@mono-agent/config` supplies the product default of 2 on the primary.
840
+ - Same-model retries fire only for transient subkinds (`overloaded`, `rate_limited`, `timeout`, `network`, `server_error`, `retryable_request`, terminated streams). A retry drops the route's provider session, since the failed attempt already appended to it, and appends its own `failoverHistory` entry carrying `retryIndex`.
841
+ - A retry is *not* a failover: `provider_route_safety` and `provider_failover_started` are emitted once per entry, and `provider_failover_completed` only fires when a genuinely different model answered.
842
+ - This is a whole-logical-turn retry sitting strictly outside the provider bridges' own transport retries. On a `pi` route, `attempts: 2` combined with pi's default `maxRetries: 2` means up to six provider stream starts.
843
+ - Context-window failure after bridge compaction recovery → never retries the same entry (a second identical request against the same window is a guaranteed second failure); preserves `failureKind: "context_limit"` in `failoverHistory` and tries the next entry; quota/output/max-turn `usage_limit` remains terminal.
802
844
  - Provider auth failure → retries the next chain entry and preserves `failureKind: "provider_auth"` in `failoverHistory` for the failed attempt.
803
845
  - Malformed request/config/billing-type non-retryable failure → returns immediately with `failoverHistory` containing the one attempt.
804
846
  - Cancellation → returns immediately.
@@ -814,7 +856,11 @@ Behaviour:
814
856
  inputs, while request-scoped overrides remain on that exact run. A runtime
815
857
  that cannot accept this projection fails closed as `safety_unavailable`.
816
858
  - Attempt-resolver failures are sanitized to `safety_unavailable`; resolver
817
- credentials/options never enter result telemetry.
859
+ credentials/options never enter result telemetry, and they advance to the next
860
+ entry rather than consuming the route's remaining `attempts`.
861
+ - `resolveAttempt` runs once per attempt — including every same-model retry — and
862
+ receives `{ attemptIndex, retryIndex }`, where `attemptIndex` stays the chain
863
+ index. Its `cleanup` runs after each attempt.
818
864
 
819
865
  Chain entries can require backend capabilities via `requires: { structured_output: true, supports_mcp: true, ... }`; entries that don't satisfy the requirements are skipped (logged in `failoverHistory` as `failureKind: "skipped_capability_mismatch"`).
820
866
 
@@ -1004,6 +1050,8 @@ runtime fails closed.
1004
1050
  documents all five bridges and their execution modes.
1005
1051
  - [Programmatic approvals and structured output](https://mono-agent-docs.vercel.app/programmatic/approval-and-structured-output/)
1006
1052
  shows the code-only host hooks.
1053
+ - [Local-first web research](https://mono-agent-docs.vercel.app/tools/web-research/)
1054
+ documents SearXNG, extraction, retry, browser isolation, and sandbox policy.
1007
1055
  - [Architecture](https://github.com/robertsreberski/mono-agent/blob/main/packages/agent-runtime/ARCHITECTURE.md)
1008
1056
  and [migration guide](https://github.com/robertsreberski/mono-agent/blob/main/packages/agent-runtime/MIGRATION.md)
1009
1057
  cover internal flow and upgrades from `0.3.x`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mono-agent/agent-runtime",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "description": "Agent runtime supporting Claude SDK/CLI, Codex, OpenCode, and Pi SDK bridges out of the box",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-only",
@@ -136,9 +136,13 @@
136
136
  "@earendil-works/pi-agent-core": "0.80.6",
137
137
  "@earendil-works/pi-ai": "0.80.6",
138
138
  "@modelcontextprotocol/sdk": "^1.29.0",
139
+ "@mozilla/readability": "0.6.0",
139
140
  "@opencode-ai/sdk": "^1.15.13",
140
141
  "@vscode/ripgrep": "1.18.0",
141
142
  "cross-spawn": "^7.0.6",
143
+ "defuddle": "0.19.2",
144
+ "linkedom": "0.18.13",
145
+ "unpdf": "1.8.0",
142
146
  "zod": "^4.3.6"
143
147
  },
144
148
  "scripts": {