singularity-forge/packages/rpc-client
Mikael Hugo a055b3adf2 feat: structured notification event model with metadata-first classification
Replace brittle string-matching in headless-events.ts with structured
source/kind/blocking/dedupe_key metadata on notify() events. String
matching is preserved as a fallback for the ~940 untagged call sites.

- Add NotificationMetadata type to headless-types.ts (canonical definition)
- Extend rpc-types.ts notify event with optional metadata field
- Extend ExtensionUIContext.notify() signature with optional 3rd arg
- Pass metadata through RPC notify implementation in rpc-mode.ts
- Update headless-events.ts: isTerminalNotification, isBlockedNotification,
  isMilestoneReadyNotification, isPauseNotification all check metadata first
- Update notification-store.ts: store metadata on NotificationEntry; use
  metadata.dedupe_key as dedup key when provided (falls back to message hash)
- Update notify-interceptor.ts to thread metadata through to store + original
- Tag critical emit sites with structured metadata:
  stopAuto → { kind: "terminal" } (+ blocking: true when reason includes "block")
  pauseAuto → { kind: "terminal", blocking: true }
  guided-flow milestone ready → { kind: "approval_request", blocking: true }
- Update notification-overlay.ts to prefer metadata.source for [label] display
- Add 17-test regression suite (notification-event-model.test.ts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 23:07:57 +02:00
..
examples chore: checkpoint workspace changes 2026-04-15 13:38:15 +02:00
src feat: structured notification event model with metadata-first classification 2026-05-01 23:07:57 +02:00
.npmignore feat: Headless Integration Hardening & Release (M002) (#2811) 2026-03-26 23:33:22 -06:00
package.json release: v2.75.0 2026-04-17 17:26:59 +00:00
README.md refactor(native): rename gsd_parser.rs to forge_parser.rs 2026-04-15 14:58:21 +02:00
tsconfig.examples.json chore: checkpoint workspace changes 2026-04-15 13:38:15 +02:00
tsconfig.json ci: optimize build workflows and caching 2026-04-14 11:16:47 -05:00

@sf-build/rpc-client

Standalone RPC client SDK for SF. Spawn the agent process, perform a v2 protocol handshake, send commands, and consume typed events via an async generator — all in a few lines of TypeScript.

Zero internal dependencies. Ships its own inlined types.

Installation

npm install @sf-build/rpc-client

Quick Start

import { RpcClient } from '@sf-build/rpc-client';

const client = new RpcClient({ cwd: process.cwd() });
await client.start();
const { sessionId } = await client.init({ clientId: 'my-app' });
console.log(`Session: ${sessionId}`);

await client.prompt('Create a hello world script');
for await (const event of client.events()) {
  if (event.type === 'execution_complete') break;
  console.log(event.type);
}
await client.shutdown();

API

Constructor

const client = new RpcClient(options?: RpcClientOptions);
Option Type Description
cliPath string Path to the CLI entry point
cwd string Working directory for the agent
env Record<string, string> Environment variables
provider string AI provider (e.g. "anthropic")
model string Model ID (e.g. "claude-sonnet")
args string[] Additional CLI arguments

Lifecycle

Method Description
start() Spawn the agent process
init(opts?) v2 handshake — returns sessionId, capabilities
shutdown() Graceful shutdown
stop() Force-kill the process

Commands

Method Description
prompt(message, images?) Send a prompt
steer(message, images?) Interrupt with a steering message
followUp(message, images?) Queue a follow-up message
abort() Abort current operation
subscribe(events) Subscribe to event types (["*"] for all)

Events

// Async generator — recommended
for await (const event of client.events()) {
  console.log(event.type);
}

// Callback-based
const unsubscribe = client.onEvent((event) => {
  console.log(event.type);
});

Helpers

Method Description
waitForIdle(timeout?) Wait for agent_end event
collectEvents(timeout?) Collect events until idle
promptAndWait(message, images?, t?) Send prompt and collect events

Session & Model

Method Description
getState() Get session state
setModel(provider, modelId) Set model
cycleModel() Cycle to next model
getAvailableModels() List available models
setThinkingLevel(level) Set thinking level
cycleThinkingLevel() Cycle thinking level
compact(instructions?) Compact session context
getSessionStats() Get session statistics
bash(command) Execute a bash command
newSession(parent?) Start a new session
sendUIResponse(id, response) Respond to extension UI requests

Type Exports

All protocol types are exported from the package root:

import type {
  RpcCommand,
  RpcResponse,
  RpcInitResult,
  RpcExecutionCompleteEvent,
  RpcCostUpdateEvent,
  RpcV2Event,
  SessionStats,
  SdkAgentEvent,
  RpcClientOptions,
} from '@sf-build/rpc-client';

License

MIT