Skip to content

Latest commit

 

History

History
427 lines (368 loc) · 26.2 KB

pi-rpc-provider.md

File metadata and controls

427 lines (368 loc) · 26.2 KB

Pi daily-task provider

Pi is the default daily-task agent reached through its native stdin/stdout JSONL RPC. It is not an ACP bridge and does not replace the Python Host. The runtime is pinned to @earendil-works/pi-coding-agent@1.2.0.

Install and configure

Use Node 22.19 or newer. The normal desktop installation (npm ci in electron/) installs the pinned Pi runtime automatically alongside Electron. An existing desktop checkout can rerun that command to install Pi or restore the locked version. Pi installation errors fail the desktop installation; they are not silently ignored. Runtime startup does not install packages.

For a headless deployment or a standalone Pi runtime repair, run this from the repository root:

npm ci --ignore-scripts --prefix agent_host/pi_runtime

Pi is enabled by default. The runtime install uses its existing lockfile and --ignore-scripts; if you skip the desktop postinstall with --ignore-scripts, install Pi separately with the command above (and provision Electron separately for desktop use). Model credentials are still required. For the default DeepSeek connection, the same DEEPSEEK_API_KEY configured for Amadeus under Settings -> Models or in .env is passed to the trusted Pi child process; no second agent login is required. Settings → Work Provider connections and .env expose these defaults:

PI_PROVIDER_ENABLED=true
PI_NODE_PATH=node
PI_AGENT_DIR=runtime/pi
PI_MODEL_PROVIDER=deepseek
PI_MODEL=deepseek-v4-flash

At backend startup Amadeus runs Pi's non-refreshing native authentication check for the selected provider/model. A missing credential keeps Pi unregistered and Settings reports the actionable reason instead of allowing the first Work to fail. This check does not make a billed inference request, so account access and remote model availability are still established by the first real Work. For custom API endpoints or local models, configure runtime/pi/models.json using Pi's native model schema. Existing Amadeus Models UI endpoint settings are not automatically translated into Pi configuration. Do not put credentials in command-line args.

The managed Pi extension retains the official legacy DeepSeek wire IDs deepseek-v4-flash and deepseek-v4-flash-vision-exp. At session_start and before each agent turn, only an unregistered current selection of either alias can copy the effective canonical deepseek-flash metadata through public pi.setModel. This happens before Pi converts images. No Provider is replaced, so native catalog caches and later native refreshes remain intact; configured endpoints, authentication and session defaults remain owned by Pi. Registered aliases and explicit native/extension Provider registrations take precedence. At the first eligible selection in a new Work, the extension reads only alias declaration presence from native models.json: an alias in models or modelOverrides disables automatic compatibility. The declaration snapshot is reused for that Work. If declarations cannot be read or parsed reliably, the registry reports an error (including an unrelated Provider), or the repair is unavailable or rejected, compatibility is skipped for that Work and Pi's native model selection is retained. A fixed warning is shown once without configuration contents; this optional repair does not emit a fatal extension error. No file is rewritten. Canonical models, Pro and other unknown IDs are unchanged. See DeepSeek's alias compatibility and image input contract. The initial native unknown-model warning may still appear because CLI selection precedes session_start. Changes to declarations or compatibility code require a new Pi Work/process; hot editing declarations and manual native /reload of an already corrected unregistered alias are not supported by this Host path. The extension does not trigger catalog or authentication refreshes. A successful MCP image tool result alone does not prove the model received or understood it.

中文:维护的 Pi 扩展在 session_start 和每轮开始前,仅为当前选中且未注册的上述 两个精确旧别名,经公开 pi.setModel 复用有效 canonical metadata,保留 wire ID, 并在 Pi 转换图片之前生效。不替换 Provider,原生目录缓存和后续原生 refresh 不变, endpoint、认证、默认型号仍由 Pi 管理;已注册别名、显式 native/extension Provider 优先。新 Work 首次符合条件时,仅读原生 models.json 中别名是否出现在 models 或 modelOverrides,有声明便不自动兼容;本 Work 复用该声明快照。若声明无法可靠 读取或解析、注册表报错(包括无关 Provider),或修补不可用、被拒绝,本 Work 跳过 兼容修补并保留 Pi 原生选择,只提示一次不含配置内容的固定警告;这项可选修补不产生 致命扩展错误。不改写文件。canonical、Pro 和其他未知型号不受影响。 初始 CLI 选择早于 session_start,因此原生未知型号警告仍可能出现。配置声明或兼容 代码变更须新建 Pi Work/进程;不支持热改声明,也不承诺手工 /reload 已修补未注册 别名的语义。扩展不主动刷新目录或认证;工具返回图片成功不等于模型已接收或理解。

For interactive Pi login against the same isolated configuration directory:

$env:PI_CODING_AGENT_DIR = (Join-Path (Get-Location) 'runtime/pi')
node agent_host/pi_runtime/node_modules/@earendil-works/pi-coding-agent/dist/cli.js

Settings → Models → Roles → Work role assignments has two independent dropdowns: Coding defaults to Codex, everyday execution defaults to Pi. Candidates come from registered compatible manifests, including custom ACP agents. Equivalent startup settings are:

WORK_CODING_PROVIDER=codex
WORK_EXECUTION_PROVIDER=pi

Restart the backend after startup configuration changes. Work Page also exposes Pi through the existing dynamic provider list. Missing optional runtimes are reported as unavailable and do not prevent role-only Chat startup. This branch adds no complexity classifier or automatic failover. Provider selection and explicit task addressing use the existing planner.

OpenClaw remains registerable through its existing Gateway adapter and keeps its native session support. It no longer owns the default everyday execution role by default. It can be assigned the execution role in the GUI, explicitly selected for an individual task, or used to continue its existing Work.

Role changes update the existing planner's routing instructions and new-task examples; they do not alter registration, manifests, or existing Work ownership. Registered general agents remain addressable regardless of role assignment. No extra requirements JSON is needed to enable an assigned agent: the Host derives its baseline context requirements from registered capabilities. COOPERATIVE_CHAT_REQUIREMENTS_JSON and COOPERATIVE_CHAT_ADDITIONAL_REQUIREMENTS_JSON remain optional Host policy overrides, defaulting to {}. Remove stale overrides if switching providers with different workspace capabilities. Legacy COOPERATIVE_CHAT_PROVIDER and PROVIDER_DELEGATE_DEFAULT_PROVIDER are read as execution-role migration aliases only when WORK_EXECUTION_PROVIDER is absent.

Responsibilities and reuse

Registration and GUI settings

Builtin adapters are composed by provider_bootstrap.py; their capability manifests are code-owned in provider_catalog.py. Settings choose connections, enablement and defaults, not whether an implementation can actually restore, cancel, access a workspace or accept an MCP projection. The GUI displays runtime availability; it does not let users grant an adapter unsupported capabilities.

Role dropdowns live under Models → Roles; connection/registration cards live under Providers, with a link back to the role settings. Changes persist in Desktop settings and apply at backend restart. Coding and daily execution route independently; there is no universal Pi role. The Work page is an explicit per-task provider selector. It initially selects the execution-role provider and preserves manual choices. An unavailable default requires a selection rather than silently choosing by manifest priority.

The existing ACP editor adds installed external agents without Python code changes. Registered compatible ACP agents appear in the role dropdowns too. Advanced cooperative policy overrides and trusted Pi extension paths remain startup configuration, with no dedicated GUI editor. MCP connections are configurable in the GUI only for adapters advertising the mcp_connection projection (Codex, Pi and compatible ACP agents). Enable a connection, bind it to Pi, then save and restart the backend. Pi projects the same Host registry, including bound extension-package MCP contributions. OpenClaw does not advertise this projection. Pi's bundled anonymous web search continues to use its existing Host MCP bridge independently of these bindings.

  • ProviderRuntime, Work Ledger, control admission and task/session identities remain unchanged. Bootstrap registers one ordinary pi provider.
  • The adapter reuses ProviderSessionHandle, ProviderInputDelivery, activity evidence, parent-context/progress helpers and the Host permission flow.
  • pi_rpc.py implements only Pi's distinct type-based JSONL transport. Codex and ACP SDKs own incompatible transports; OpenClaw uses WebSocket RPC. There is no second task store or new Host-level agent framework.
  • Each run owns one subprocess; the saved native session file is its opaque continuation handle. Reattachment requires that exact file and identity. Sessions are not reused by guessing the latest transcript.
  • Startup update/telemetry requests are disabled for the managed runtime; model inference and explicitly invoked network tools still use the network.
  • The adapter waits for agent_settled, not intermediate agent_end events which can precede retries, compaction or queued inputs.
  • Additional input uses native steer acknowledgement at a tool boundary. This is append delivery, not the Host's latest-revision-wins plan replacement; the manifest deliberately does not advertise immediate replacement steering.
  • Cancellation clears queued input and awaits native abort acknowledgement. Process loss or a missing prompt acknowledgement yields an unknown/orphaned execution, never an automatic retry or a claimed successful cancellation.

Daily tools and native extensions

The bundled amadeus.ts extension uses anonymous Exa MCP for search through Amadeus's existing MCP client, and pi-simple-web-tools@0.1.0 inside the Pi process for article extraction only. Its keyed search module is not used. There is no dependency on Amadeus's Browser provider, planner, browser sessions or Playwright installation. The extraction package is pinned because the adapter uses its module API; upgrade it with the integration tests.

User goal Tools / existing owner
Find an article by title, author or topic web_search uses anonymous Exa MCP; no API key or registration
Read and summarize an article web_read extracts markdown/HTML/PDF with HTTP and Readability; web_fetch reads simple text/feeds
Open a supplied or discovered URL visibly open_url reuses the system-browser opener also used by Canvas URL actions
Find, read and open a particular article Pi can compose search → select source → read → open in one Work and continue the same native session
Read current news news_search reads Google News RSS; source articles should be read before making detailed claims

Search connects to https://mcp.exa.ai/mcp?tools=web_search_exa only when called. It requires no API key, browser, local MCP server, or new npm dependency. The short-lived Python bridge uses the existing open_mcp_connection implementation; it never creates a nested Provider or Work and never reads/sends an Exa key. There is no paid fallback. The public service has rate limits and may become unavailable; these produce ordinary tool failures for Pi to handle without failing the RPC conversation. Queries are sent to Exa as an external search service. Search relevance and publication dates still need model evaluation.

Live anonymous smoke checks found the original Transformer paper, Chinese weekly article sources and dated New Zealand news results. Three search calls took about 0.9–1.1 seconds each, excluding initial connection/process startup. This is a small sample, not a service guarantee or proof of same-day coverage.

web_read returns bounded slices with next_offset, so long articles remain readable without writing outside the Host workspace or granting access to a global temporary directory. The source URL is the requested URL, not a verified redirect destination. Content extraction does not prove completeness or bypass paywalls. Neither search snippets nor news feeds prove the full article was read.

JavaScript rendering is optional. If needed, install Playwright in agent_host/pi_runtime and its Chromium binary; the component loads it lazily. The default install does not include a browser. This experiment does not provide general click/type control or access to a user's logged-in tabs.

pi_web_tools.py also bridges the shared OS URL opener. A visible open reports OS acceptance, not verified page load. Opening the system browser does not create another Provider or Work.

Pi retains its native file/command tools. File tools are confined to the Host-assigned workspace and access level; command execution and unknown extension tools require write access and a Host approval. Launching an app uses an executable plus argv without a shell, always requires approval and reports process-start evidence only. It does not claim control over an existing app or reuse Browser login state; those remain with Amadeus's existing domain owners.

Set PI_EXTENSIONS_JSON to an array of explicit trusted extension paths to use the native plugin API. Ambient extension discovery and project trust approval are disabled; Pi's native skills are retained. Confirmation requests are mapped to existing Host allow/deny requests. Native select/input/editor dialogs are cancelled because this provider contract has no general form response; TUI-only extensions are not supported by RPC.

The extension gate is not an operating-system sandbox: native extensions are arbitrary code, and approved shell commands have process-user access. Do not load untrusted extensions or treat the path checks as isolation from hostile code. No Pi process runs in the Electron UI process.

Pi 1.2.0 and Host-managed MCP

The managed runtime retains the existing file/web tools and adds direct tools and resources only from enabled MCP connections bound to Pi. The Host supplies the configuration in the trusted child environment, never command-line arguments or a second persisted registry. Pi's public createMcpExtension and MCP client own discovery, schema/result handling and connection shutdown.

Ambient extensions and Pi's built-in discovery remain disabled by --no-extensions; project-local files remain disabled by --no-approve. Neither global/project mcp.json nor native extension server registrations can override or add to the Host snapshot. Explicit trusted native extension code still loads under PI_EXTENSIONS_JSON, with the same arbitrary-code trust boundary as before. Codemode and tool search are not part of the managed default tool set. No connection binding means the original tool set.

Every projected MCP tool or resource call uses the existing Host allow-once/deny card, including tools annotated read-only. A server's annotation does not grant permission. This approval is independent of local workspace write access: a workspace-less or read-only Work or cooperative chat can use an approved connector without acquiring file or shell rights. File/path checks and the write-access-plus-approval gate for shell and other extension tools are unchanged. Denial and cancellation do not authorize a later call. The trusted MCP gate uses the existing mcp.tool.call capability and call_tool action, shared with the standard MCP Provider. The Host applies the same workspace-independent approval policy to that capability; generic tool permissions remain denied in read-only cooperative contexts. Codex's mcp.elicitation remains a distinct server input/confirmation request and does not receive this tool-call exception. The earlier pre-release mcp.tool.execute spelling is superseded, without an alias; restart the backend when updating this integration so active permission owners use the same contract.

Direct-tool approval cards show the Host connection display name and original MCP tool name, even when Pi hashes its model-facing identifier. The three resource operations resolve their server argument against the same Host snapshot and show its display name and ID. An unfiltered list identifies all bound connections as its scope with a bounded name preview; an unknown ID is not attributed to a known connection. Approval labels replace control/format characters and line breaks with spaces, and are capped at 320 Unicode code points (plus the fixed title prefix), with an ellipsis when shortened. Execution names and arguments are never rewritten by this display formatting. Enabling and binding a stdio connection authorizes starting its configured executable when the Work connects. Per-call approval does not sandbox that server's startup code; only bind trusted services.

Stdio servers receive the platform allowlist from isolated_child_environment plus only their own explicit environment bindings. Values remain literal; ${...} and !command are not expanded by Pi. HTTP connections use anonymous access or the configured bearer token (the explicit connection value takes precedence over its named Host environment variable). Pi model credentials, other connections' values and native Pi OAuth accounts are not implicitly forwarded. Interactive MCP OAuth and native /mcp configuration are not exposed through this adapter; configure authentication through Host connection settings.

Missing bearer tokens skip the affected connection; native namespace collisions skip all ambiguous connections. Other connections and Pi remain available. These errors and connection failures appear as redacted runtime.notice status entries in provider activity, with Host Settings guidance. They neither count as task progress nor claim tool execution or a diagnosed task failure. Notices are retained in the bounded Provider activity journal so session reloads and backend restarts can restore the same activity entries.

Each run (including each cooperative turn) starts a fresh Pi process and the bound services. This incurs service startup/discovery cost on every run; connections are not pooled across turns. The first prompt waits at most 3 seconds for direct tools, down from Pi's 10-second default. Connected services contribute tools to the first model request; slower services can become available on later model turns within the same run, and a runtime notice reports that they are still connecting. A short run may finish before a slow service becomes usable. This budget does not change the native timeout for an actual MCP request.

Connections reload from the current Host snapshot on a new run, including when restoring an existing native session. Disabling or unbinding a connection takes effect after the backend restart required by Host settings.

Normal completion/cancellation closes Pi's stdin and waits for native session disposal before force termination is considered. Tests verify direct server exit and sequential-session cleanup. This is not an OS sandbox or a guarantee that arbitrary descendants survive neither an abrupt Host/Pi crash nor forced termination; the native transport owns its process handling.

Cancellation and transport disposal / 取消与连接收尾

An acknowledged native abort is the business cancellation result, not proof that the Pi/MCP transport has closed. PiAdapter completes and awaits its owned transport teardown even if permission-expiration publication fails or the Host cancels the producer task again. The original publication error or cancellation still propagates; successful disposal also releases the active-run/session registrations and signals the run's completion. EOF and the existing close deadline remain unchanged; this does not authorize replay or automatic approval.

原生 abort 回执只证明业务取消,不等于 Pi/MCP 连接已经关闭。权限过期事件发布失败, 或 Host 再次取消 producer 时,PiAdapter 仍等待本轮原连接完成收尾,再释放运行及会话 登记并标记完成;原发布错误或取消继续向上传播。EOF 和原有关闭时限不变,不重派任务, 不自动批准权限。真实进程与连接清理应与业务终态分别核验。

Keep package.json, package-lock.json and the adapter's startup version check in sync. Install with npm ci --ignore-scripts in agent_host/pi_runtime (or the normal desktop installation), then restart the backend. Pi 1.2.0 no longer ships an npm shrinkwrap; the repository lockfile pins the complete tested tree. The Node requirement remains 22.19 or newer. Preserve a copy of the isolated Pi session/configuration directory before upgrading a deployment; restoring a 1.2.0-written session with 0.86.1 is not a supported rollback guarantee.

The scope and acceptance boundary are recorded in issue #222. Codemode/tool search and interactive OAuth require separate integration and acceptance work; MCP schemas remain on the bound Work Provider and are not published to Main Chat. Pi may truncate large direct results or return temporary paths for binary resources. Those paths do not grant extra filesystem access; this integration does not open a global temporary directory to the file tools.

Validation

npm ci --ignore-scripts --prefix agent_host/pi_runtime
npm --prefix agent_host/pi_runtime run typecheck
.venv/Scripts/python.exe -m pytest tests/test_pi_provider.py tests/test_pi_runtime.py tests/test_pi_mcp.py tests/test_pi_web_tools.py tests/test_skill_pi_runtime.py

The native extension has its own pinned TypeScript compiler and strict, no-emit configuration (tsconfig.typecheck.json). It checks every first-party .ts entry and imported TypeScript source, including the web component. As in the Electron configuration, third-party declaration files use skipLibCheck; no source checks are suppressed. Electron's normal npm run build invokes this check through check:pi, so Windows and Linux build CI cover the native extension.

The web component's optional playwright import needs declarations even when the runtime package is absent. Only the type-check configuration maps that name to the pinned development dependency playwright-core, whose declarations are re-exported by Playwright itself. This does not change runtime module resolution, install playwright, download browser binaries, or enable browser rendering. @types/turndown supplies the web parser's missing declarations and @types/node matches the supported Node 22 line. The real Pi regression includes a client-rendered page that must still report the missing optional browser fallback, while ordinary HTTP article reads remain supported. Production runtime installs can omit development dependencies; type checking and source builds require them.

The first suite checks acknowledgement uncertainty, correlation, permissions, cancellation and session identity using deterministic protocol peers. The second starts the real pinned Pi CLI against a local mock model endpoint to test file tools, explicit versus ambient extensions, disabled ambient MCP discovery, Host approval/denial, workspace boundaries and on-disk session restoration. The Skill suite covers native instruction/resource reads, continuation and stale bindings. It skips when the optional npm runtime is absent; it uses no paid model calls. The MCP suite uses synthetic stdio and loopback HTTP services to check connection binding, literal credentials, independent approvals, denial/cancellation, resources, connection errors and restored-session cleanup. Windows Python CI installs the pinned runtime before running these suites. Cooperative ingress tests cover exact approval ownership, read-only MCP approval, local shell denial and unchanged workspace access. The MCP suite also checks per-connection configuration failures, original tool labels after native hashing, single-server and unfiltered resource approval scopes, label normalization without rewriting execution identifiers, and a hanging server's bounded first-prompt delay. Standard MCP Provider and Pi tests assert the shared permission capability/action; cooperative tests reject shell, generic, obsolete and elicitation capabilities under the read-only tool-call policy.

Synthetic captures using the real Electron activity-card component show the notice and approval text before and after the audit fixes. They use fixture events and no real credentials or sessions. Resource cards have separate before and after captures showing selected connections and unfiltered list scope.

For an opt-in real-model run that creates files and opens real browser/Notepad windows on Windows:

.venv/Scripts/python.exe scripts/pi_daily_acceptance.py --provider pi --label trial-1
.venv/Scripts/python.exe scripts/pi_daily_acceptance.py --provider openclaw --label trial-1

The harness approves only Notepad opening the exact generated summary file; it denies additional shell commands. Reports and native sessions stay under ignored runtime/pi-acceptance/. See live comparison for the observed results and verification limits.

References: anonymous search, web extraction component, native RPC, native extensions. The installed version's bundled documentation is the protocol baseline.