This repository has been archived on 2026-06-01. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
xiaoju 06b1e3d785 refactor(cli,workflow-meta): scaffold AGENT.md on init; align develop prompts
Generate AGENT.md at ~/.uncaged-nerve root during nerve init (layout, verb-first workflows, createRole four-tuple, root build, coding style). Role prompts instruct agents to use cat AGENT.md instead of node_modules nerve-skills paths.

E2E init test asserts AGENT.md. Retain .knowledge workflow/adapter updates and flat single-file roles guidance from the branch.

Fixes #287

Made-with: Cursor
2026-04-30 13:41:24 +00:00

3.5 KiB

Agent Adapters (RFC-003)

Adapter = capability. Role = scenario. Workflows declare adapters directly via import.

AgentFn Protocol

type AgentFn = (ctx: ThreadContext, systemPrompt: string) => Promise<string>
  • Input: thread context ({ threadId, start, steps }) + system prompt (role identity)
  • Output: single-shot Promise<string> — no streaming support
  • Adapter handles tool-specific details internally

Streaming Limitations

The AgentFn protocol does not support streaming responses (AsyncIterable<string> or ReadableStream). It's strictly limited to single-shot Promise<string> returns.

For long-running or incremental agent outputs:

  • CLI tools buffer full output until completion
  • Timeout enforcement via timeoutMs (default 300s)
  • No intermediate results exposed to workflow logic
  • Progress indication happens at the CLI tool level only

Available Adapters

Package Adapter Tool
@uncaged/nerve-adapter-cursor cursorAdapter / createCursorAdapter() cursor-agent CLI
@uncaged/nerve-adapter-hermes hermesAdapter / createHermesAdapter() hermes chat CLI
@uncaged/nerve-workflow-utils createLlmAdapter(provider) OpenAI-compatible HTTP chat (single-turn)

The Cursor and Hermes adapter packages each export a default instance (sensible defaults) and a factory for custom config. createLlmAdapter is a factory on @uncaged/nerve-workflow-utils only.

createLlmAdapter

createLlmAdapter builds an AgentFn from an LlmProvider (baseUrl, apiKey, model). One chat completion per role step: system = the string passed by createRole (your prompt); user = ctx.start.content (the thread’s start frame). On failure it throws with a formatted LLM error.

import { createLlmAdapter, createRole } from "@uncaged/nerve-workflow-utils";
import { z } from "zod";

const metaSchema = z.object({ ok: z.boolean() });

const planner = createRole(
  createLlmAdapter({ baseUrl: "https://api.example.com/v1", apiKey: "…", model: "gpt-4o-mini" }),
  "You are a planner…",
  metaSchema,
  extractConfig,
);

Use this when you want a role backed by an HTTP LLM instead of a subprocess CLI adapter.

Usage in Workflows

Adapters are passed directly to createRole:

import { createRole } from "@uncaged/nerve-workflow-utils";
import { cursorAdapter } from "@uncaged/nerve-adapter-cursor";

const coder = createRole(cursorAdapter, prompt, schema, extractConfig);

No registry, no config indirection. TypeScript catches missing adapters at compile time.

Extract Layer

Parses agent raw string → typed meta. Configured in nerve.yaml:

extract:
  provider: dashscope
  model: qwen-plus

Two-level merge: global → role override. Retry once on parse failure (feeds error back to LLM), then throw ExtractError.

Error Handling

When adapters' underlying CLI tools (e.g., cursor-agent or hermes) fail, errors are surfaced synchronously via rejection with no fallback/retry logic:

  • Missing/unavailable tool: spawn_failed error when CLI binary not found in $PATH
  • Non-zero exit code: non_zero_exit error with captured stdout/stderr
  • Timeout: timeout error when execution exceeds configured timeoutMs
  • Abort signal: aborted error when AbortSignal triggers cancellation

All errors are immediately thrown as Error instances with descriptive messages (e.g., "cursor-agent: exitCode=7 stdout=... stderr=..."). No automatic retries or fallback adapters.