# Weft

**Weaving your AI agents into one.**

Weft is an SDK-first, provider-agnostic AI Agent Chat Runtime SDK. It takes heterogeneous event streams from multiple AI agent providers — Claude Agent SDK, Codex app-server, CLI fallbacks, and third-party ACP — and weaves them into a single **canonical timeline**, powering an embeddable, production-grade streaming Chat UI.

```
Claude Agent SDK ─────┐
                      │
Codex app-server ─────┼──▶  Canonical Timeline  ──▶  Embeddable Chat Panel
                      │      (seq · epoch · cursor)
CLI fallback ─────────┘
```

---

## Why Weft

In weaving, the **weft** is the crosswise strand that passes through all the lengthwise yarns, binding them into a single piece of cloth. That is exactly what this project does — it cuts across Claude, Codex, and any future provider, weaving their raw event streams into one unified runtime experience.

### Design Principles

- **SDK-First** — Provider-native SDKs and app-servers are the default runtime path; CLI streaming (`claude -p` / `codex exec`) is an explicit fallback, never silent.
- **Provider-Owned Auth** — Weft detects and delegates provider authentication. It never stores, injects, or transfers credentials across providers.
- **Canonical Timeline** — Every provider event maps to a unified `TimelineEnvelope` with `seq`, `epoch`, `cursor`, and `gap` semantics — enabling live streaming, reconnect, replay, and catch-up.
- **Streaming-First UI** — Polished TurnCard with buffered rendering, throttled updates, block-level memoization, and tool activity details.
- **Extension Plane** — Policy, Sources, Skills, and Automations plug in through runtime hooks and timeline events — never inside provider adapters.
- **Node.js Core** — All runtime packages use standard Node.js APIs (`child_process`, `node:http`, `ws`). No platform-specific runtime dependencies.
- **License Clean** — MIT. Inspired by Craft, Paseo, CloudCLI, and AionUi architectures; clean-room reimplemented without copying AGPL source.

---

## Consumer Usage (npm install)

Weft is published as a single npm package with sub-path exports:

```bash
npm install @percena/weft
```

```typescript
// Core types — browser-safe
import type { AgentEvent, Message, Session } from '@percena/weft'

// React chat UI
import { SessionViewer, AgentChatPanel } from '@percena/weft/chat'
import { useAgentChatSession } from '@percena/weft/chat'

// Provider runtimes (Node.js)
import * as providers from '@percena/weft/providers'
import { createHostAgentRuntime } from '@percena/weft/factory'

// Auth detection
import { readClaudeAuth, readCodexAuth } from '@percena/weft/auth'

// Skills, Sources, Automations
import { defineSkill } from '@percena/weft/skills'
import { registerSource } from '@percena/weft/sources'
```

### Sub-path Exports

| Import Path | Description | Browser-safe |
|-------------|-------------|:---:|
| `@percena/weft` | Core types + timeline + runtime-core + policy | ✅ |
| `@percena/weft/chat` | React UI components + chat panel glue | ✅ |
| `@percena/weft/providers` | Claude/Codex/Flitro provider factories | ❌ |
| `@percena/weft/auth` | Provider auth detection utilities | ❌ |
| `@percena/weft/server` | HTTP + WebSocket server | ❌ |
| `@percena/weft/skills` | Skill definitions and storage | ❌ |
| `@percena/weft/skills/browser` | Browser-safe skill activation helpers | ✅ |
| `@percena/weft/sources` | MCP source management | ❌ |
| `@percena/weft/automations` | Cron, webhooks, event bus | ❌ |
| `@percena/weft/factory` | Host-side runtime composition | ❌ |
| `@percena/weft/styles` | CSS theme (custom properties) | ✅ |

---

## Architecture

```
Host App  (Electron / Tauri / VPS daemon / Browser)
  │
  ▼
@weft/runtime-core ─────── AgentRuntime contract · state machine · command sink
  │
  ├─▶ @weft/provider-claude   Native SDK runtime  +  claude -p fallback
  ├─▶ @weft/provider-codex    App-server runtime   +  codex exec fallback
  └─▶ @weft/provider-flitro   HTTP-first Go Agent Server provider
  │
  ▼
@weft/policy ────────────── Permission modes · tool policy · scoped approvals
@weft/sources ───────────── MCP / API / local source registry · credential boundary
@weft/skills ────────────── Skill metadata · activation plan · required sources
@weft/automations ───────── Event bus · scheduler · prompt / webhook actions
  │
  ▼
@weft/timeline ──────────── Canonical event schema · seq / cursor / replay / merge
  │
  ▼
@weft/processor ─────────── Pure reducer:  TimelineEnvelope → SessionState → Message[]
  │
  ▼
@weft/ui ────────────────── TurnCard · StreamingMarkdown · PermissionRequestCard
  │
  ▼
@weft/local-chat ────────── useAgentChatSession · AgentChatPanel
                             Browser-safe, embeddable chat module
```

---

## Packages

### Core Runtime

| Package | Description |
|---------|-------------|
| `@weft/core` | Zero-dependency type foundation: `AgentEvent`, `Message`, `Session`, errors |
| `@weft/api-types` | Transport DTOs: `SessionEvent`, `RPC_CHANNELS`, `PermissionMode` |
| `@weft/timeline` | Canonical timeline: `TimelineEnvelope`, seq/epoch/cursor, replay, merge, gap detection |
| `@weft/runtime-core` | `AgentRuntime` contract, capability report, state machine, extension context |
| `@weft/runtime-factory` | Desktop/VPS host composition entrypoint |

### Provider Runtimes

| Package | Description |
|---------|-------------|
| `@weft/provider-claude` | Claude Agent SDK driver + `claude -p` fallback + permission/source bridge |
| `@weft/provider-codex` | Codex app-server driver + JSON-RPC client + `codex exec` fallback |
| `@weft/provider-flitro` | HTTP-first Go Agent Server provider |
| `@weft/adaptor` | Backend abstraction layer for migration support |

### Extension Plane

| Package | Description |
|---------|-------------|
| `@weft/policy` | Permission modes (`safe`/`ask`/`allow-all`), tool policy engine, layered rules, scoped approvals |
| `@weft/sources` | MCP / API / local source registry, credential boundary, provider-neutral tool assembly |
| `@weft/skills` | Skill metadata, activation plan, required sources, scoped `alwaysAllow` |
| `@weft/automations` | Event bus, cron/condition matcher, prompt/webhook actions, history store, loop guard |

### UI & Chat

| Package | Description |
|---------|-------------|
| `@weft/ui` | React components: `TurnCard`, `SessionViewer`, `StreamingMarkdown`, `PermissionRequestCard` |
| `@weft/local-chat` | Embeddable chat panel: `AgentChatPanel`, `useAgentChatSession`, reconnect/catchup |

### Host Infrastructure

| Package | Description |
|---------|-------------|
| `@weft/server` | Local HTTP/WebSocket server + client, session management, timeline streaming, admin APIs |
| `@weft/host-services` | Host-only contracts: audit, artifacts, notifications, privileged execution, utility tools |
| `@weft/local-runtime` | CLI fallback baseline for local provider execution |

### Testing

| Package | Description |
|---------|-------------|
| `@weft/e2e-tests` | End-to-end tests covering runtime, providers, timeline, policy, server, and demo integration |

---

## Getting Started (Development)

### Prerequisites

- **Node.js** ≥ 18
- **pnpm** ≥ 10
- **TypeScript** ≥ 5.0

### Install

```bash
git clone <repo-url> weft && cd weft
pnpm install
```

### Verify

```bash
# Run all tests
pnpm run test

# Type-check entire monorepo
pnpm run check

# Build all packages (topological order L0→L6)
pnpm run build
```

### Web — Live Mode

```bash
pnpm run web
```

Start the backend server and web frontend with a single command. Open `http://127.0.0.1:5174/chat` to create a session.

### Demo — Fixture Mode

```bash
cd apps/demo
pnpm run dev
```

Open the local URL and click **Start** to replay canonical timeline fixtures. Add `?autoplay=1` for auto-play.

> **Security**: Fixture mode never starts a local CLI. Live mode never holds subprocess handles or provider secrets in the browser — all host capabilities are accessed through `@weft/server`.

---

## Runtime Selection

Weft selects the best available runtime for each provider, with explicit fallback reporting:

```
┌─────────────────────────────────────────────────────┐
│  Claude                    Codex                    │
│                                                     │
│  1. Claude Agent SDK       1. Codex app-server      │
│     (native-sdk)              (app-server)          │
│           │                       │                 │
│           ▼                       ▼                 │
│  2. claude -p              2. codex exec --json     │
│     (cli-fallback)            (cli-fallback)        │
└─────────────────────────────────────────────────────┘
```

```typescript
import { createHostAgentRuntime } from '@percena/weft/factory'

const { runtime } = await createHostAgentRuntime({
  provider: 'codex',
  cwd: '/path/to/project',
})

const report = await runtime.preflight()
// report.auth: { mode, configured, source }
```

Fallback is **never silent** — it produces a `runtime_fallback` timeline event and is clearly visible in `RuntimeCapabilityReport`.

---

## Extension Plane

Weft's extension plane keeps policy, sources, skills, and automations decoupled from provider runtimes. All extensions plug in through `RuntimeExtensionContext`:

```typescript
import { createHostAgentRuntime } from '@percena/weft/factory'

const { runtime } = await createHostAgentRuntime({
  provider: 'claude',
  cwd,
  extensions: {
    policy: policyHook,           // ToolIntent → allow / ask / deny
    sources: sourceContext,        // Active MCP/API sources
    skills: skillContext,          // Activated skill metadata
    commandOrigin: 'user',         // user | automation | scheduler
    hostServices: hostCallbacks,   // SessionToolBridge + host capabilities
  },
})
```

### Permission Policy

```typescript
import { evaluatePolicy } from '@percena/weft'

// Unified tool intent across all providers
const intent: ToolIntent = {
  kind: 'bash',
  command: 'rm -rf /tmp/cache',
  cwd: '/project',
}

const decision = evaluatePolicy(intent, layers)
// decision.result: 'allow' | 'ask' | 'deny'
// decision.explain: human-readable reason
```

### Source Activation

Sources provide MCP/API/local tools to the runtime without leaking credentials:

```typescript
import { registerSource } from '@percena/weft/sources'

registerSource({
  name: 'my-mcp-server',
  type: 'mcp',
  config: { command: 'npx', args: ['-y', 'my-mcp-server'] },
})
```

---

## Provider Smoke Tests

Real provider integration tests are opt-in to avoid CI dependency on personal auth:

```bash
# Codex app-server auth probe
WEFT_RUN_REAL_AGENT_E2E=1 npx vitest run packages/e2e-tests/src/real-provider-smoke.test.ts

# Real Codex turn
WEFT_RUN_REAL_CODEX_TURN_E2E=1 npx vitest run packages/e2e-tests/src/real-provider-smoke.test.ts

# Real Claude Agent SDK turn
WEFT_RUN_REAL_CLAUDE_E2E=1 npx vitest run packages/e2e-tests/src/real-provider-smoke.test.ts
```

---

## Project Structure

```
weft/
├── packages/              # Internal monorepo packages (18 packages)
│   ├── core/              # Type foundation
│   ├── api-types/         # Transport DTOs
│   ├── timeline/          # Canonical timeline
│   ├── runtime-core/      # AgentRuntime contract
│   ├── runtime-factory/   # Host composition
│   ├── provider-claude/   # Claude SDK + fallback
│   ├── provider-codex/    # Codex app-server + fallback
│   ├── provider-flitro/   # Flitro HTTP provider
│   ├── adaptor/           # Backend abstraction
│   ├── policy/            # Permission engine
│   ├── sources/           # Source registry
│   ├── skills/            # Skill metadata
│   ├── automations/       # Automation engine
│   ├── ui/                # React components
│   ├── local-chat/        # Embeddable chat panel
│   ├── local-runtime/     # CLI fallback baseline
│   ├── server/            # HTTP/WS host server
│   ├── host-services/     # Host-only contracts
│   └── e2e-tests/         # End-to-end tests
├── publish/               # npm publish entry point (single "@percena/weft" package)
│   ├── src/               # Barrel re-exports per sub-path
│   ├── tsup.config.ts     # Multi-entry build configuration
│   └── package.json       # name: "@percena/weft", 9 sub-path exports
├── apps/
│   ├── demo/              # Vite demo app (Fixture + Live)
│   └── web/               # Vite web frontend
├── docs/                  # Architecture & design docs
├── pnpm-workspace.yaml    # pnpm workspace configuration
└── package.json           # pnpm monorepo root
```

---

## Documentation

| Document | Description |
|----------|-------------|
| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | Architecture: design principles, runtime tiers, timeline contract, streaming pipeline |
| [GETTING-STARTED.md](docs/GETTING-STARTED.md) | Setup, project structure, testing, and demo usage |
| [SDK-PUBLISH.md](docs/SDK-PUBLISH.md) | SDK publishing: tsup build, exports mapping, CSS distribution, CI/CD |
| [LOCAL-SERVER.md](docs/LOCAL-SERVER.md) | Local HTTP/WebSocket server usage and API reference |
| [CODEX-COMPATIBILITY.md](docs/CODEX-COMPATIBILITY.md) | Codex provider: app-server, CLI fallback, event adapter |
| [FLITRO-PROVIDER.md](docs/FLITRO-PROVIDER.md) | Flitro provider: HTTP/WS integration, timeline mapping |
| [REFACTOR.md](docs/REFACTOR.md) | Frontend/backend separation refactoring plan |

---

## Current Status

**All packages building** · Claude Agent SDK + Codex app-server verified · Host server operational · npm publish ready

### What's Built

- ✅ SDK-first runtime with `native-sdk` / `app-server` / `cli-fallback` selection
- ✅ Canonical timeline with seq/epoch/cursor, reconnect, replay, gap detection
- ✅ Claude Agent SDK driver with permission bridge and MCP source mapping
- ✅ Codex app-server driver with JSON-RPC client and approval bridge
- ✅ Flitro HTTP-first provider for Go Agent Server
- ✅ Provider-neutral permission policy with layered rules and scoped approvals
- ✅ Source/skill activation plans with credential boundary
- ✅ Automation runtime bridge with loop guard, history store, and scheduler
- ✅ Embeddable `AgentChatPanel` with reconnect/catchup and inline permissions
- ✅ Local host server with HTTP/WebSocket transport, metadata, admin APIs, and persistence
- ✅ Host services: audit, artifacts, notifications, utility tools, privileged execution
- ✅ Single npm package (`@percena/weft`) with 9 sub-path exports
- ✅ Node.js runtime (Bun fully removed — `child_process`, `node:http`, `ws`)
- ✅ pnpm workspace + vitest test suite + tsup build pipeline

### What's Next

- 🔲 Desktop/VPS host shell UI
- 🔲 Long-running scheduler ownership
- 🔲 Real browser/script sandbox executor
- 🔲 Platform notification adapters
- 🔲 Secondary LLM provider executor
- 🔲 VPS real-provider E2E coverage

---

## Acknowledgments

Weft is inspired by and draws design ideas from the following projects:

- [craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss) — Permission policy, source/skill activation, timeline schema, host-services contracts, and automation taxonomy

---

## License

[MIT](LICENSE) © Percena
