iii / worker
$worker

harness

v0.5.0

Meta-worker that composes the modular Node workers backing the iii chat surface.

agent-ready brief for v0.5.0
install + config + dependencies + readme + api reference, all in one place. fetch as agent-context.md for an llm to consume.
the same content rendered as discrete blocks below is exposed as a single markdown document at /workers/harness.md?version=0.5.0. paste it into an llm prompt or pipe it through curl from a worker.

install

install
$iii worker add harness@0.5.0

dependencies

readme

README.md

harness

Node/TypeScript port of the iii harness stack. One package, one folder per worker, one feature per file. Each worker is independently runnable as pnpm dev: (development) or iii- (production binary).

The Rust workers shell, iii-directory, and the engine's state::*/ stream::*/iii::durable::* primitives are NOT ported — they run alongside harness over the iii bus.

Workers

Folder Bus surface Role
src/harness/ ui::subscribe/unsubscribe, harness::fs::read_inline, policy::check_permissions, harness::provider::{register,resolve,list} Meta-worker; loads iii-permissions.yaml; spins up ui::* fanout pumps; owns the provider registry + the harness entry in the configuration worker (api keys, per-provider settings, permissions).
src/approval-gate/ approval::resolve Persists operator decisions to scope approvals (turn-orchestrator reacts via turn::on_approval); default mode seeded from harness config permissions.default_mode.
src/turn-orchestrator/ run::start, turn::{state}, turn::get_state Durable FSM driving each agent turn; dispatchWithHook approval chokepoint.
src/session/ session-tree::* (11 fns), session-inbox::* (3 fns) Branching session storage + per-session inbox queues.
src/llm-budget/ budget::* (14 fns) Workspace + agent LLM spend caps.
src/hook-fanout/ hook-fanout::publish_collect Generic publish-and-collect over a stream topic.
src/models-catalog/ models::list, models::get, models::supports, models::register Model catalog populated exclusively by provider discovery (provider::::refresh_models -> models::register); no embedded seed.
src/provider-anthropic/ provider::anthropic::{stream,complete,refresh_models} Anthropic SSE → channel writer; self-declares to the harness registry; pulls /v1/models into the catalog.
src/provider-openai/ provider::openai::{stream,complete,refresh_models} OpenAI SSE → channel writer; self-declares + pulls /v1/models.
src/provider-kimi/ provider::kimi::{stream,complete,refresh_models} Kimi (Moonshot) SSE → channel writer; self-declares + pulls /v1/models.
src/provider-lmstudio/ provider::lmstudio::{stream,complete,refresh_models,load_model,unload_model} LM Studio (localhost); self-declares + discovers loaded models.
src/provider-llamacpp/ provider::llamacpp::{stream,complete,refresh_models} llama-server (localhost); self-declares + discovers the loaded model.
src/context-compaction/ (none — pure side-car on agent::events) Optional out-of-band session-history compactor.

Quickstart

pnpm install
pnpm build              # compile to dist/
# In separate terminals (or via your process manager):
node dist/harness/main.js               --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/turn-orchestrator/main.js     --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/approval-gate/main.js         --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/session/main.js               --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/hook-fanout/main.js           --url ws://127.0.0.1:49134
node dist/models-catalog/main.js        --url ws://127.0.0.1:49134
node dist/provider-anthropic/main.js    --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/provider-openai/main.js       --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/provider-kimi/main.js         --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/provider-lmstudio/main.js     --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/provider-llamacpp/main.js     --url ws://127.0.0.1:49134 --config ./config.yaml
node dist/llm-budget/main.js            --url ws://127.0.0.1:49134
# Optional side-car:
node dist/context-compaction/main.js    --url ws://127.0.0.1:49134

For development, replace node dist//main.js with pnpm dev:.

Configuration

All workers honour --url / III_URL for the engine WebSocket and --config for the YAML config file (default ./config.yaml).

The harness worker watches iii-permissions.yaml (default ./iii-permissions.yaml) and reloads it on change. The shipped default file at the workspace root is symlinked into this folder.

Layout

  • docs/ — architecture documentation: docs/architecture.md is the system overview; one file per worker lives under docs/workers/.
  • src/types/ — wire types (mirrors harness/crates/harness-types).
  • src/runtime/ — cross-worker SDK helpers (worker bootstrap, state/stream wrappers, OTel stub).
  • src// — one folder per worker. Each register.ts composes the worker's bus surface from per-feature files; each main.ts is the binary entry-point.
  • tests/ — vitest suites per worker.

api reference (json)

agent-api-reference.json
{
  "functions": [
    {
      "description": "Resolve a provider credential + settings (api_url, max_tokens) from the harness configuration. Server-side only.",
      "metadata": {},
      "name": "harness::provider::resolve",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Read a host file via shell::fs::read, drain its channel, and return a {content:[{text}], details:{size, truncated, bytes_read}} envelope (max 256 KiB inline by default).",
      "metadata": {},
      "name": "harness::fs::read_inline",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Internal: agent::events fanout handler.",
      "metadata": {},
      "name": "harness::fanout::agent_event_handler",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "List providers declared to the harness.",
      "metadata": {},
      "name": "harness::provider::list",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Browser kickoff: forward payload to run::start. Used by console/web over the iii-browser-sdk.",
      "metadata": {},
      "name": "harness::trigger",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Register a browser's interest in a session (or all sessions if session_id is null).",
      "metadata": {},
      "name": "ui::subscribe",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Check a function call against iii-permissions.yaml; returns allow, deny, or needs_approval.",
      "metadata": {},
      "name": "policy::check_permissions",
      "request_schema": {
        "$ref": "#/definitions/CheckPermissionsPayload",
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "CheckPermissionsPayload": {
            "additionalProperties": false,
            "properties": {
              "args": {
                "additionalProperties": {},
                "type": "object"
              },
              "function_id": {
                "minLength": 1,
                "type": "string"
              }
            },
            "required": [
              "function_id"
            ],
            "type": "object"
          }
        }
      },
      "response_schema": {}
    },
    {
      "description": "Self-declare an LLM provider (id, config schema, defaults) into the dynamic harness configuration schema.",
      "metadata": {},
      "name": "harness::provider::register",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Internal: fans out a newly-created session id to ui::sessions::changed::<browser_id>.",
      "metadata": {},
      "name": "harness::fanout::session_created",
      "request_schema": {},
      "response_schema": {}
    },
    {
      "description": "Remove a browser's subscription to a session (or its all-sessions sub if session_id is null).",
      "metadata": {},
      "name": "ui::unsubscribe",
      "request_schema": {},
      "response_schema": {}
    }
  ],
  "triggers": []
}