omp packages

@sage-protocol/pi-adapter0.5.1

Sage Protocol MCP integration for pi coding agent

hack4kites Published 1 month ago MIT ~332 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

@sage-protocol/pi-adapter

Sage integration for the Pi coding agent runtime.

  • Pi agent: earendil-works/pi — extensible terminal coding harness
  • Compatibility: declared peer range >=0.64.0 <0.87.0; local typecheck, tests, and synthetic SDK tool execution verified with Pi 0.86.1. Targeted Pi 1.3.0 native codemode checks pass; packaged-extension compatibility with 1.x is not yet declared.
  • Sage Protocol: sage-protocol/sage — decentralized capability/library layer for AI agents

What It Does

  • Exposes Sage MCP tools (hub_list_servers, hub_status, hub_session_list, hub_start_server, hub_stop_server, sage_search, sage_execute, sage_status, and sage_behavior)
  • Lets Pi own skill discovery and loading through native <available_skills>, /skill:<name>, and full SKILL.md reads
  • Injects SessionStart Sage context and shows the loaded library/skill inventory
  • Captures prompts and responses for RLM feedback
  • Observes truthful full native skill loads and writes source- and session-qualified load receipts
  • Exposes sage_mark_guided_use in the packaged Pi extension so an agent can bind actually loaded, actually applied skills to the exact prompt capture through Sage's native-use daemon path
  • Optionally exposes one status-only sage_wallet_status tool when Glove supplies either a strict inherited connected descriptor declaration or the complete legacy endpoint/root/owner tuple
  • Preserves optional security hooks and explicit subagent skill resolution
  • Keeps Sage-owned skills under packages/sage/skills/ and the curated Pi export surface rather than bundling copies in this adapter

The adapter does not call sage suggest hook skill for each prompt, inject sage-suggested-skills, or render a suggestion-quality widget. It has no suggestion auto-skip or auto-reject lifecycle. Manual sage suggest skill "<task>" remains available when a person or agent explicitly wants CLI ranking, but it is not automatic Pi injection.

Tool and CLI routing

Prefer Sage tools. When an operation is unavailable through them, use the installed Sage CLI with the same approval and credential safeguards. A security or approval denial is not tool unavailability: switching surfaces must not bypass it. Keep the same profile, required approvals, dry runs, and credential protections. Explicit CLI restrictions such as SAGE_ALLOW_BASH_CLI=0 remain in effect.

The local extension imports dist/index.js. After changing its source, run npm run build and start a fresh Pi session to load the revised guidance.

Install

# Pi CLI extension (no source changes)
pi install npm:@sage-protocol/pi-adapter

# SDK embedding
npm install @sage-protocol/pi-adapter

Quick Start

import {
  createAgentSession,
  createCodingTools,
  type ToolDefinition as PiToolDefinition,
} from '@earendil-works/pi-coding-agent';
import {
  createSageSessionConfig,
  type ToolDefinition as SageToolDefinition,
} from '@sage-protocol/pi-adapter';

function asPiCustomTools(tools: SageToolDefinition[]): PiToolDefinition[] {
  // Type-shape compatibility across supported Pi minors; no runtime conversion.
  return tools as unknown as PiToolDefinition[];
}

const sage = await createSageSessionConfig({ source: 'pi-agent-core' });
const cwd = process.cwd();
const securedTools = sage.wrapToolsWithSecurity(createCodingTools(cwd));
const { session } = await createAgentSession({
  cwd,
  noTools: 'builtin',
  customTools: asPiCustomTools([...securedTools, ...sage.customTools]),
});
const disposeSageHooks = sage.setupHooks(session);

In current Pi, tools is a string allowlist. Tool definitions belong in customTools; noTools: 'builtin' prevents duplicate unwrapped built-ins. The single helper cast is only the TypeScript peer-version boundary between the adapter's cross-minor tool shape and Pi's generic ToolDefinition—it does not convert anything at runtime.

Pi presents its native skill catalog separately. When a skill applies, load it with /skill:<name> or read its complete SKILL.md, follow the procedure, then call sage_mark_guided_use only if the loaded procedure actually guided the current turn. Loading alone is not use.

API

createSageSessionConfig(config) returns:

{
  customTools: ToolDefinition[];           // Sage hub and code-mode bridge tools
  mcpBridge: SageMcpBridge;                 // MCP process lifecycle
  setupHooks: (session: AgentSession) => () => void;  // SessionStart + capture hooks
  wrapToolsWithSecurity: (tools: ToolDefinition[]) => ToolDefinition[];
}

Recommended configuration:

interface SageP2Config {
  sageBin?: string;           // default: "sage"
  sageProfile?: string;       // Sage config profile
  timeoutMs?: number;         // default: 20_000
  enableRlmFeedback?: boolean;
  enableSecurityHooks?: boolean;
  securityFailurePolicy?: "warn" | "block"; // default: "warn"; what to do when a scan cannot decide
  source?: string;            // default: "pi"
  // Inherited mode: both exact Glove values are required, with no legacy fields.
  gloveLocalServiceFdsV1?: string;          // exact JSON alias-to-FD map
  gloveGuestChannelServiceAlias?: string;  // exact wallet service alias
  // Legacy mode: all three are required, with no inherited fields.
  gloveGuestChannelEndpoint?: string; // canonical absolute Unix socket path
  gloveGuestChannelRoot?: string;     // canonical absolute trusted root
  gloveGuestChannelOwnerUid?: number; // isolated socket-owner UID (not Pi's UID)
  env?: Record<string, string>;

  /** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
  suggestLimit?: number;
  /** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
  suggestDebounceMs?: number;
  /** @deprecated Low-level legacy suggestion compatibility; ignored by the default Pi path. */
  enableProvision?: boolean;
}

Migrating to 0.4

Version 0.4 moves Pi skill discovery and loading to Pi's native skill surface. The legacy sageInjectSuggestion(...) method is retained as a no-op for compatibility, and default setup no longer performs automatic suggestions. Do not call sageInjectSuggestion; use Pi's native skill load flow and call sage_mark_guided_use after an actually loaded skill guides the current prompt.

The guided-use write requires both the Sage CLI command sage suggest feedback native-use and daemon capability native_skill_use_v1. Version 0.4.2 reports which runtime half is stale instead of collapsing either case into a generic write failure. It never falls back to weaker suggestion feedback. Update the CLI when it lacks the command; update and restart saged when the daemon lacks the capability. Then retry the same declaration.

Docs

Validate

npm test
npm run typecheck
npm run build
git diff --check

License

MIT

Session inbox discovery

sage_inbox({ action: "list" }) returns at most 20 live peers and 8 KiB of JSON text. Each row keeps its canonical session UUID. Labels remain untrusted; compact project labels show the last two path segments.

List-only options:

  • includeOffline: true: include historical peers.
  • limit: 1..200: change the row ceiling; the byte ceiling still applies.
  • detail: "full": include bounded full project labels, generation, and lease.
  • project, harness: exact label filters, applied before the row ceiling.

All options apply only to the received broker page, currently at most 200 peers. hasMore retains the broker's meaning. view reports source, matched, returned, and omitted counts, label truncation, and source incompleteness. An empty filtered view does not prove no matching peer exists. There is no server cursor or stable pagination; reaching peers beyond the first broker page still requires Sage transport/broker changes (#18).

/inbox selects a live peer; /inbox all includes offline peers. Use /inbox ask [all] for a correlated request. Explicit sends to canonical UUIDs still support offline delivery. ACK, fencing, and ask timeout rules are unchanged.

Inbox discovery, search/execute, hub tools, and sage_status retain legacy text for older Pi hosts and also provide outputSchema / structuredContent for native codemode. Status keeps its CLI reference in text and in cliReference; its version and MCP client version come from package metadata. A security block withholds text, structured data, and details; a warning removes structured data so codemode callers must see the warning text.

Session inbox liveness (shared with hook-driven harnesses)

The adapter currently renews the daemon lease from its own 2 s poll in src/intercom.ts. The Sage CLI now ships a harness-agnostic keepalive, sage inbox keepalive --auth-file <capability> --watch-pid <pid>, which is what hook-driven harnesses (Claude Code, Codex) use. A follow-up can have the adapter spawn it detached after saveAuth with process.pid as the watched host, send heartbeat only on idle/busy transitions, and replace the receive poll with sage inbox receive --auth-file <capability> --wait <secs>, so both harness families share one liveness mechanism. Fencing (session_inbox_fenced) stops both the adapter timer and the keepalive.