feat: scaffold TypeScript monorepo with all plugin interfaces
Phase 0 complete. Establishes: - pnpm workspace with 18 packages (core, cli, web, 15 plugins) - Complete type definitions in packages/core/src/types.ts defining all 8 plugin slot interfaces (Runtime, Agent, Workspace, Tracker, SCM, Notifier, Terminal) + core service interfaces - YAML config loader with Zod validation and sensible defaults - Plugin registry with built-in discovery - CLAUDE.md with conventions for spawned agents All agents can now branch from main and implement their assigned packages against the interfaces defined in types.ts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
36b0792eb6
commit
5058c409d5
|
|
@ -0,0 +1,6 @@
|
|||
node_modules/
|
||||
dist/
|
||||
.next/
|
||||
*.tsbuildinfo
|
||||
.env
|
||||
.env.local
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
# CLAUDE.md — Agent Orchestrator
|
||||
|
||||
## What This Project Is
|
||||
|
||||
An open-source, agent-agnostic system for orchestrating parallel AI coding agents. Any coding agent, any repo, any issue tracker, any runtime. The system manages session lifecycle, tracks PR/CI/review state, auto-handles routine issues (CI failures, review comments), and pushes notifications to humans only when their judgment is needed.
|
||||
|
||||
**Core principle: Push, not pull.** The human spawns agents, walks away, and gets notified when needed.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Language**: TypeScript throughout (ESM, Node 20+)
|
||||
- **Monorepo**: pnpm workspaces
|
||||
- **Web**: Next.js 15 (App Router) + Tailwind CSS
|
||||
- **CLI**: Commander.js
|
||||
- **Config**: YAML + Zod validation
|
||||
- **Real-time**: Server-Sent Events
|
||||
- **State**: Flat metadata files + JSONL event log
|
||||
|
||||
## Architecture
|
||||
|
||||
8 plugin slots — every abstraction is swappable:
|
||||
|
||||
| Slot | Interface | Default Plugin |
|
||||
|------|-----------|---------------|
|
||||
| Runtime | `Runtime` | tmux |
|
||||
| Agent | `Agent` | claude-code |
|
||||
| Workspace | `Workspace` | worktree |
|
||||
| Tracker | `Tracker` | github |
|
||||
| SCM | `SCM` | github |
|
||||
| Notifier | `Notifier` | desktop |
|
||||
| Terminal | `Terminal` | iterm2 |
|
||||
| Lifecycle | (core, not pluggable) | — |
|
||||
|
||||
All interfaces are defined in `packages/core/src/types.ts`. **Read this file first** — it is the source of truth for all abstractions.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
packages/
|
||||
core/ — @agent-orchestrator/core (types, config, services)
|
||||
cli/ — @agent-orchestrator/cli (the `ao` command)
|
||||
web/ — @agent-orchestrator/web (Next.js dashboard)
|
||||
plugins/
|
||||
runtime-tmux/ — tmux session runtime
|
||||
runtime-process/ — child process runtime
|
||||
agent-claude-code/ — Claude Code adapter
|
||||
agent-codex/ — Codex CLI adapter
|
||||
agent-aider/ — Aider adapter
|
||||
workspace-worktree/ — git worktree isolation
|
||||
workspace-clone/ — git clone isolation
|
||||
tracker-github/ — GitHub Issues tracker
|
||||
tracker-linear/ — Linear tracker
|
||||
scm-github/ — GitHub PRs, CI, reviews
|
||||
notifier-desktop/ — OS desktop notifications
|
||||
notifier-slack/ — Slack notifications
|
||||
notifier-webhook/ — Generic webhook notifications
|
||||
terminal-iterm2/ — macOS iTerm2 tab management
|
||||
terminal-web/ — xterm.js web terminal
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
### TypeScript
|
||||
- ESM modules (`"type": "module"`)
|
||||
- Use `.js` extensions in imports (TypeScript ESM requirement): `import { foo } from "./bar.js"`
|
||||
- Strict mode enabled
|
||||
- Use `node:` prefix for Node.js builtins: `import { readFileSync } from "node:fs"`
|
||||
|
||||
### Plugin Structure
|
||||
Every plugin exports a `PluginModule`:
|
||||
```typescript
|
||||
import type { PluginModule, Runtime } from "@agent-orchestrator/core";
|
||||
|
||||
export const manifest = {
|
||||
name: "tmux",
|
||||
slot: "runtime" as const,
|
||||
description: "Runtime plugin: tmux sessions",
|
||||
version: "0.1.0",
|
||||
};
|
||||
|
||||
export function create(): Runtime {
|
||||
return {
|
||||
name: "tmux",
|
||||
// ... implement interface
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Shell Commands
|
||||
When a plugin needs to run shell commands (git, tmux, gh, etc.), use `child_process.execFile` or `child_process.spawn` from `node:child_process`. Wrap them in async helpers.
|
||||
|
||||
### Error Handling
|
||||
- Throw typed errors, don't return error codes
|
||||
- Plugin methods should throw if they can't do their job
|
||||
- The core services catch and handle plugin errors
|
||||
|
||||
### Config
|
||||
- Config is loaded from `agent-orchestrator.yaml` (see `.yaml.example`)
|
||||
- All paths support `~` expansion
|
||||
- Per-project overrides for plugins and reactions
|
||||
|
||||
## Reference Implementation
|
||||
|
||||
The `scripts/` directory contains the original bash scripts that this TypeScript codebase replaces. Use them as specifications:
|
||||
|
||||
| Script | What It Specifies |
|
||||
|--------|------------------|
|
||||
| `claude-ao-session` | Session lifecycle (spawn, list, kill, cleanup) |
|
||||
| `claude-dashboard` | Web dashboard, API, activity detection |
|
||||
| `claude-batch-spawn` | Batch spawning with duplicate detection |
|
||||
| `send-to-session` | Smart message delivery (busy detection, wait-for-idle) |
|
||||
| `claude-status` | JSONL introspection, live branch detection |
|
||||
| `claude-review-check` | PR review scanning, fix prompt generation |
|
||||
| `claude-bugbot-fix` | Automated comment detection + fixes |
|
||||
| `claude-session-status` | Activity classification (working/idle/blocked) |
|
||||
| `get-claude-session-info` | Agent introspection (session ID, summary extraction) |
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm build # build all packages
|
||||
pnpm typecheck # typecheck all packages
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
1. **Stateless orchestrator** — no database, just flat metadata files + event log
|
||||
2. **Plugins implement interfaces** — every plugin is a pure implementation of an interface from `types.ts`
|
||||
3. **Push notifications** — the Notifier is the primary human interface, not the dashboard
|
||||
4. **Two-tier event handling** — auto-handle routine issues (CI, reviews), notify human only when judgment is needed
|
||||
5. **Backwards-compatible metadata** — flat key=value files matching the existing bash script format
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
# Agent Orchestrator Configuration
|
||||
# Copy to agent-orchestrator.yaml and customize.
|
||||
|
||||
# Where to store session metadata
|
||||
dataDir: ~/.agent-orchestrator
|
||||
|
||||
# Where to create workspaces (git worktrees, clones)
|
||||
worktreeDir: ~/.worktrees
|
||||
|
||||
# Web dashboard port
|
||||
port: 3000
|
||||
|
||||
# Default plugins (these are the defaults — you can omit this section)
|
||||
defaults:
|
||||
runtime: tmux # tmux | process | docker | kubernetes | ssh | e2b
|
||||
agent: claude-code # claude-code | codex | aider | goose | custom
|
||||
workspace: worktree # worktree | clone | copy
|
||||
notifiers: [desktop] # desktop | slack | discord | webhook | email
|
||||
|
||||
# Projects — at minimum, specify repo and path
|
||||
projects:
|
||||
my-app:
|
||||
name: My App
|
||||
repo: org/my-app
|
||||
path: ~/my-app
|
||||
defaultBranch: main
|
||||
sessionPrefix: app
|
||||
|
||||
# Issue tracker (defaults to github issues)
|
||||
# tracker:
|
||||
# plugin: linear
|
||||
# teamId: "your-team-id"
|
||||
|
||||
# Files to symlink into workspaces
|
||||
# symlinks: [.env, .claude]
|
||||
|
||||
# Commands to run after workspace creation
|
||||
# postCreate:
|
||||
# - "pnpm install"
|
||||
|
||||
# Agent-specific config
|
||||
# agentConfig:
|
||||
# permissions: skip # --dangerously-skip-permissions
|
||||
# model: opus
|
||||
|
||||
# Per-project reaction overrides
|
||||
# reactions:
|
||||
# approved-and-green:
|
||||
# auto: true # enable auto-merge for this project
|
||||
|
||||
# Notification channels
|
||||
# notifiers:
|
||||
# slack:
|
||||
# plugin: slack
|
||||
# webhook: ${SLACK_WEBHOOK_URL}
|
||||
# channel: "#agent-updates"
|
||||
|
||||
# Notification routing by priority
|
||||
# notificationRouting:
|
||||
# urgent: [desktop, slack] # agent stuck, needs input, errored
|
||||
# action: [desktop, slack] # PR ready to merge
|
||||
# warning: [slack] # auto-fix failed
|
||||
# info: [slack] # summary, all done
|
||||
|
||||
# Reactions — auto-responses to events (these are the defaults)
|
||||
# reactions:
|
||||
# ci-failed:
|
||||
# auto: true
|
||||
# action: send-to-agent
|
||||
# retries: 2
|
||||
# escalateAfter: 2
|
||||
#
|
||||
# changes-requested:
|
||||
# auto: true
|
||||
# action: send-to-agent
|
||||
# escalateAfter: 30m
|
||||
#
|
||||
# approved-and-green:
|
||||
# auto: false # set to true for auto-merge
|
||||
# action: notify
|
||||
# priority: action
|
||||
#
|
||||
# agent-stuck:
|
||||
# threshold: 10m
|
||||
# action: notify
|
||||
# priority: urgent
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "agent-orchestrator",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Orchestrate parallel AI coding agents across any runtime, any repo, any issue tracker",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.4",
|
||||
"scripts": {
|
||||
"build": "pnpm -r build",
|
||||
"dev": "pnpm --filter @agent-orchestrator/web dev",
|
||||
"lint": "pnpm -r lint",
|
||||
"typecheck": "pnpm -r typecheck",
|
||||
"clean": "pnpm -r clean"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/cli",
|
||||
"version": "0.1.0",
|
||||
"description": "CLI for agent-orchestrator — the `ao` command",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"ao": "dist/index.js"
|
||||
},
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsx src/index.ts",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*",
|
||||
"chalk": "^5.4.0",
|
||||
"commander": "^13.0.0",
|
||||
"ora": "^8.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env node
|
||||
// CLI entry point — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/core",
|
||||
"version": "0.1.0",
|
||||
"description": "Core library — types, config, session manager, lifecycle manager, event bus",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
},
|
||||
"./types": {
|
||||
"types": "./dist/types.d.ts",
|
||||
"import": "./dist/types.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"yaml": "^2.7.0",
|
||||
"zod": "^3.24.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
/**
|
||||
* Configuration loader — reads agent-orchestrator.yaml and validates with Zod.
|
||||
*
|
||||
* Minimal config that just works:
|
||||
* projects:
|
||||
* my-app:
|
||||
* repo: org/repo
|
||||
* path: ~/my-app
|
||||
*
|
||||
* Everything else has sensible defaults.
|
||||
*/
|
||||
|
||||
import { readFileSync, existsSync } from "node:fs";
|
||||
import { resolve, join } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
import { parse as parseYaml } from "yaml";
|
||||
import { z } from "zod";
|
||||
import type { OrchestratorConfig } from "./types.js";
|
||||
|
||||
// =============================================================================
|
||||
// ZOD SCHEMAS
|
||||
// =============================================================================
|
||||
|
||||
const ReactionConfigSchema = z.object({
|
||||
auto: z.boolean().default(true),
|
||||
action: z.enum(["send-to-agent", "notify", "auto-merge"]).default("notify"),
|
||||
message: z.string().optional(),
|
||||
priority: z.enum(["urgent", "action", "warning", "info"]).optional(),
|
||||
retries: z.number().optional(),
|
||||
escalateAfter: z.union([z.number(), z.string()]).optional(),
|
||||
threshold: z.string().optional(),
|
||||
includeSummary: z.boolean().optional(),
|
||||
});
|
||||
|
||||
const TrackerConfigSchema = z
|
||||
.object({
|
||||
plugin: z.string(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
const SCMConfigSchema = z
|
||||
.object({
|
||||
plugin: z.string(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
const NotifierConfigSchema = z
|
||||
.object({
|
||||
plugin: z.string(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
const AgentSpecificConfigSchema = z
|
||||
.object({
|
||||
permissions: z.enum(["skip", "default"]).optional(),
|
||||
model: z.string().optional(),
|
||||
})
|
||||
.passthrough();
|
||||
|
||||
const ProjectConfigSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
repo: z.string(),
|
||||
path: z.string(),
|
||||
defaultBranch: z.string().default("main"),
|
||||
sessionPrefix: z.string().optional(),
|
||||
runtime: z.string().optional(),
|
||||
agent: z.string().optional(),
|
||||
workspace: z.string().optional(),
|
||||
tracker: TrackerConfigSchema.optional(),
|
||||
scm: SCMConfigSchema.optional(),
|
||||
symlinks: z.array(z.string()).optional(),
|
||||
postCreate: z.array(z.string()).optional(),
|
||||
agentConfig: AgentSpecificConfigSchema.optional(),
|
||||
reactions: z.record(ReactionConfigSchema.partial()).optional(),
|
||||
});
|
||||
|
||||
const DefaultPluginsSchema = z.object({
|
||||
runtime: z.string().default("tmux"),
|
||||
agent: z.string().default("claude-code"),
|
||||
workspace: z.string().default("worktree"),
|
||||
notifiers: z.array(z.string()).default(["desktop"]),
|
||||
});
|
||||
|
||||
const OrchestratorConfigSchema = z.object({
|
||||
dataDir: z.string().default("~/.agent-orchestrator"),
|
||||
worktreeDir: z.string().default("~/.worktrees"),
|
||||
port: z.number().default(3000),
|
||||
defaults: DefaultPluginsSchema.default({}),
|
||||
projects: z.record(ProjectConfigSchema),
|
||||
notifiers: z.record(NotifierConfigSchema).default({}),
|
||||
notificationRouting: z
|
||||
.record(z.array(z.string()))
|
||||
.default({
|
||||
urgent: ["desktop", "slack"],
|
||||
action: ["desktop", "slack"],
|
||||
warning: ["slack"],
|
||||
info: ["slack"],
|
||||
}),
|
||||
reactions: z.record(ReactionConfigSchema).default({}),
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
// CONFIG LOADING
|
||||
// =============================================================================
|
||||
|
||||
/** Expand ~ to home directory */
|
||||
function expandHome(filepath: string): string {
|
||||
if (filepath.startsWith("~/")) {
|
||||
return join(homedir(), filepath.slice(2));
|
||||
}
|
||||
return filepath;
|
||||
}
|
||||
|
||||
/** Expand all path fields in the config */
|
||||
function expandPaths(config: OrchestratorConfig): OrchestratorConfig {
|
||||
config.dataDir = expandHome(config.dataDir);
|
||||
config.worktreeDir = expandHome(config.worktreeDir);
|
||||
|
||||
for (const project of Object.values(config.projects)) {
|
||||
project.path = expandHome(project.path);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/** Apply defaults to project configs */
|
||||
function applyProjectDefaults(
|
||||
config: OrchestratorConfig
|
||||
): OrchestratorConfig {
|
||||
for (const [id, project] of Object.entries(config.projects)) {
|
||||
// Derive name from project ID if not set
|
||||
if (!project.name) {
|
||||
project.name = id;
|
||||
}
|
||||
|
||||
// Derive session prefix from project ID if not set
|
||||
if (!project.sessionPrefix) {
|
||||
project.sessionPrefix = id;
|
||||
}
|
||||
|
||||
// Infer SCM from repo if not set
|
||||
if (!project.scm && project.repo.includes("/")) {
|
||||
project.scm = { plugin: "github" };
|
||||
}
|
||||
|
||||
// Infer tracker from repo if not set (default to github issues)
|
||||
if (!project.tracker) {
|
||||
project.tracker = { plugin: "github" };
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/** Apply default reactions */
|
||||
function applyDefaultReactions(
|
||||
config: OrchestratorConfig
|
||||
): OrchestratorConfig {
|
||||
const defaults: Record<string, typeof config.reactions[string]> = {
|
||||
"ci-failed": {
|
||||
auto: true,
|
||||
action: "send-to-agent",
|
||||
message:
|
||||
"CI is failing on your PR. Run `gh pr checks` to see the failures, fix them, and push.",
|
||||
retries: 2,
|
||||
escalateAfter: 2,
|
||||
},
|
||||
"changes-requested": {
|
||||
auto: true,
|
||||
action: "send-to-agent",
|
||||
message:
|
||||
"There are review comments on your PR. Check with `gh pr view --comments` and `gh api` for inline comments. Address each one, push fixes, and reply.",
|
||||
escalateAfter: "30m",
|
||||
},
|
||||
"bugbot-comments": {
|
||||
auto: true,
|
||||
action: "send-to-agent",
|
||||
message:
|
||||
"Automated review comments found on your PR. Fix the issues flagged by the bot.",
|
||||
escalateAfter: "30m",
|
||||
},
|
||||
"merge-conflicts": {
|
||||
auto: true,
|
||||
action: "send-to-agent",
|
||||
message:
|
||||
"Your branch has merge conflicts. Rebase on the default branch and resolve them.",
|
||||
escalateAfter: "15m",
|
||||
},
|
||||
"approved-and-green": {
|
||||
auto: false,
|
||||
action: "notify",
|
||||
priority: "action",
|
||||
message: "PR is ready to merge",
|
||||
},
|
||||
"agent-stuck": {
|
||||
auto: true,
|
||||
action: "notify",
|
||||
priority: "urgent",
|
||||
threshold: "10m",
|
||||
},
|
||||
"agent-needs-input": {
|
||||
auto: true,
|
||||
action: "notify",
|
||||
priority: "urgent",
|
||||
},
|
||||
"agent-exited": {
|
||||
auto: true,
|
||||
action: "notify",
|
||||
priority: "urgent",
|
||||
},
|
||||
"all-complete": {
|
||||
auto: true,
|
||||
action: "notify",
|
||||
priority: "info",
|
||||
includeSummary: true,
|
||||
},
|
||||
};
|
||||
|
||||
// Merge defaults with user-specified reactions (user wins)
|
||||
config.reactions = { ...defaults, ...config.reactions };
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/** Search for config file in standard locations */
|
||||
function findConfigFile(startDir?: string): string | null {
|
||||
const searchPaths = [
|
||||
startDir ? resolve(startDir, "agent-orchestrator.yaml") : null,
|
||||
startDir ? resolve(startDir, "agent-orchestrator.yml") : null,
|
||||
resolve(process.cwd(), "agent-orchestrator.yaml"),
|
||||
resolve(process.cwd(), "agent-orchestrator.yml"),
|
||||
resolve(homedir(), ".agent-orchestrator.yaml"),
|
||||
resolve(homedir(), ".agent-orchestrator.yml"),
|
||||
resolve(homedir(), ".config", "agent-orchestrator", "config.yaml"),
|
||||
].filter((p): p is string => p !== null);
|
||||
|
||||
for (const path of searchPaths) {
|
||||
if (existsSync(path)) {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// PUBLIC API
|
||||
// =============================================================================
|
||||
|
||||
/** Load and validate config from a YAML file */
|
||||
export function loadConfig(configPath?: string): OrchestratorConfig {
|
||||
const path = configPath ?? findConfigFile();
|
||||
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
"No agent-orchestrator.yaml found. Run `ao init` to create one."
|
||||
);
|
||||
}
|
||||
|
||||
const raw = readFileSync(path, "utf-8");
|
||||
const parsed = parseYaml(raw);
|
||||
|
||||
return validateConfig(parsed);
|
||||
}
|
||||
|
||||
/** Validate a raw config object */
|
||||
export function validateConfig(raw: unknown): OrchestratorConfig {
|
||||
const validated = OrchestratorConfigSchema.parse(raw);
|
||||
|
||||
let config = validated as OrchestratorConfig;
|
||||
config = expandPaths(config);
|
||||
config = applyProjectDefaults(config);
|
||||
config = applyDefaultReactions(config);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/** Get the default config (useful for `ao init`) */
|
||||
export function getDefaultConfig(): OrchestratorConfig {
|
||||
return validateConfig({
|
||||
projects: {},
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* @agent-orchestrator/core
|
||||
*
|
||||
* Core library for the Agent Orchestrator.
|
||||
* Exports all types, config loader, and service implementations.
|
||||
*/
|
||||
|
||||
// Types — everything plugins and consumers need
|
||||
export * from "./types.js";
|
||||
|
||||
// Config — YAML loader + validation
|
||||
export { loadConfig, validateConfig, getDefaultConfig } from "./config.js";
|
||||
|
||||
// Plugin registry
|
||||
export { createPluginRegistry } from "./plugin-registry.js";
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* Plugin Registry — discovers and loads plugins.
|
||||
*
|
||||
* Plugins can be:
|
||||
* 1. Built-in (packages/plugins/*)
|
||||
* 2. npm packages (@agent-orchestrator/plugin-*)
|
||||
* 3. Local file paths specified in config
|
||||
*/
|
||||
|
||||
import type {
|
||||
PluginSlot,
|
||||
PluginManifest,
|
||||
PluginModule,
|
||||
PluginRegistry,
|
||||
OrchestratorConfig,
|
||||
} from "./types.js";
|
||||
|
||||
/** Map from "slot:name" → plugin instance */
|
||||
type PluginMap = Map<string, { manifest: PluginManifest; instance: unknown }>;
|
||||
|
||||
function makeKey(slot: PluginSlot, name: string): string {
|
||||
return `${slot}:${name}`;
|
||||
}
|
||||
|
||||
/** Built-in plugin package names, mapped to their npm package */
|
||||
const BUILTIN_PLUGINS: Array<{ slot: PluginSlot; name: string; pkg: string }> = [
|
||||
// Runtimes
|
||||
{ slot: "runtime", name: "tmux", pkg: "@agent-orchestrator/plugin-runtime-tmux" },
|
||||
{ slot: "runtime", name: "process", pkg: "@agent-orchestrator/plugin-runtime-process" },
|
||||
// Agents
|
||||
{ slot: "agent", name: "claude-code", pkg: "@agent-orchestrator/plugin-agent-claude-code" },
|
||||
{ slot: "agent", name: "codex", pkg: "@agent-orchestrator/plugin-agent-codex" },
|
||||
{ slot: "agent", name: "aider", pkg: "@agent-orchestrator/plugin-agent-aider" },
|
||||
// Workspaces
|
||||
{ slot: "workspace", name: "worktree", pkg: "@agent-orchestrator/plugin-workspace-worktree" },
|
||||
{ slot: "workspace", name: "clone", pkg: "@agent-orchestrator/plugin-workspace-clone" },
|
||||
// Trackers
|
||||
{ slot: "tracker", name: "github", pkg: "@agent-orchestrator/plugin-tracker-github" },
|
||||
{ slot: "tracker", name: "linear", pkg: "@agent-orchestrator/plugin-tracker-linear" },
|
||||
// SCM
|
||||
{ slot: "scm", name: "github", pkg: "@agent-orchestrator/plugin-scm-github" },
|
||||
// Notifiers
|
||||
{ slot: "notifier", name: "desktop", pkg: "@agent-orchestrator/plugin-notifier-desktop" },
|
||||
{ slot: "notifier", name: "slack", pkg: "@agent-orchestrator/plugin-notifier-slack" },
|
||||
{ slot: "notifier", name: "webhook", pkg: "@agent-orchestrator/plugin-notifier-webhook" },
|
||||
// Terminals
|
||||
{ slot: "terminal", name: "iterm2", pkg: "@agent-orchestrator/plugin-terminal-iterm2" },
|
||||
{ slot: "terminal", name: "web", pkg: "@agent-orchestrator/plugin-terminal-web" },
|
||||
];
|
||||
|
||||
export function createPluginRegistry(): PluginRegistry {
|
||||
const plugins: PluginMap = new Map();
|
||||
|
||||
return {
|
||||
register(plugin: PluginModule): void {
|
||||
const { manifest } = plugin;
|
||||
const key = makeKey(manifest.slot, manifest.name);
|
||||
const instance = plugin.create();
|
||||
plugins.set(key, { manifest, instance });
|
||||
},
|
||||
|
||||
get<T>(slot: PluginSlot, name: string): T | null {
|
||||
const entry = plugins.get(makeKey(slot, name));
|
||||
return entry ? (entry.instance as T) : null;
|
||||
},
|
||||
|
||||
list(slot: PluginSlot): PluginManifest[] {
|
||||
const result: PluginManifest[] = [];
|
||||
for (const [key, entry] of plugins) {
|
||||
if (key.startsWith(`${slot}:`)) {
|
||||
result.push(entry.manifest);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
async loadBuiltins(): Promise<void> {
|
||||
for (const builtin of BUILTIN_PLUGINS) {
|
||||
try {
|
||||
const mod = (await import(builtin.pkg)) as PluginModule;
|
||||
if (mod.manifest && typeof mod.create === "function") {
|
||||
this.register(mod);
|
||||
}
|
||||
} catch {
|
||||
// Plugin not installed — that's fine, only load what's available
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async loadFromConfig(config: OrchestratorConfig): Promise<void> {
|
||||
// First, load all built-ins
|
||||
await this.loadBuiltins();
|
||||
|
||||
// Then, load any additional plugins specified in project configs
|
||||
// (future: support npm package names and local file paths)
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,842 @@
|
|||
/**
|
||||
* Agent Orchestrator — Core Type Definitions
|
||||
*
|
||||
* This file defines ALL interfaces and types that the system uses.
|
||||
* Every plugin, CLI command, and web API route builds against these.
|
||||
*
|
||||
* Architecture: 8 plugin slots + core services
|
||||
* 1. Runtime — where sessions execute (tmux, docker, k8s, process)
|
||||
* 2. Agent — AI coding tool (claude-code, codex, aider)
|
||||
* 3. Workspace — code isolation (worktree, clone)
|
||||
* 4. Tracker — issue tracking (github, linear, jira)
|
||||
* 5. SCM — source platform + PR/CI/reviews (github, gitlab)
|
||||
* 6. Notifier — push notifications (desktop, slack, webhook)
|
||||
* 7. Terminal — human interaction UI (iterm2, web, none)
|
||||
* 8. Lifecycle Manager (core, not pluggable)
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// SESSION
|
||||
// =============================================================================
|
||||
|
||||
/** Unique session identifier, e.g. "my-app-1", "backend-12" */
|
||||
export type SessionId = string;
|
||||
|
||||
/** Session lifecycle states */
|
||||
export type SessionStatus =
|
||||
| "spawning"
|
||||
| "working"
|
||||
| "pr_open"
|
||||
| "ci_failed"
|
||||
| "review_pending"
|
||||
| "changes_requested"
|
||||
| "approved"
|
||||
| "mergeable"
|
||||
| "merged"
|
||||
| "cleanup"
|
||||
| "needs_input"
|
||||
| "stuck"
|
||||
| "errored"
|
||||
| "killed";
|
||||
|
||||
/** Activity state as detected by the agent plugin */
|
||||
export type ActivityState =
|
||||
| "active" // agent is processing (thinking, writing code)
|
||||
| "idle" // agent is at prompt, waiting for input
|
||||
| "waiting_input" // agent is asking a question / permission prompt
|
||||
| "blocked" // agent hit an error or is stuck
|
||||
| "exited"; // agent process is no longer running
|
||||
|
||||
/** A running agent session */
|
||||
export interface Session {
|
||||
/** Unique session ID, e.g. "my-app-3" */
|
||||
id: SessionId;
|
||||
|
||||
/** Which project this session belongs to */
|
||||
projectId: string;
|
||||
|
||||
/** Current lifecycle status */
|
||||
status: SessionStatus;
|
||||
|
||||
/** Activity state from agent plugin */
|
||||
activity: ActivityState;
|
||||
|
||||
/** Git branch name */
|
||||
branch: string | null;
|
||||
|
||||
/** Issue identifier (if working on an issue) */
|
||||
issueId: string | null;
|
||||
|
||||
/** PR info (once PR is created) */
|
||||
pr: PRInfo | null;
|
||||
|
||||
/** Workspace path on disk */
|
||||
workspacePath: string | null;
|
||||
|
||||
/** Runtime handle for communicating with the session */
|
||||
runtimeHandle: RuntimeHandle | null;
|
||||
|
||||
/** Agent introspection data (summary, cost, etc.) */
|
||||
agentInfo: AgentIntrospection | null;
|
||||
|
||||
/** When the session was created */
|
||||
createdAt: Date;
|
||||
|
||||
/** Last activity timestamp */
|
||||
lastActivityAt: Date;
|
||||
|
||||
/** Metadata key-value pairs */
|
||||
metadata: Record<string, string>;
|
||||
}
|
||||
|
||||
/** Config for creating a new session */
|
||||
export interface SessionSpawnConfig {
|
||||
projectId: string;
|
||||
issueId?: string;
|
||||
branch?: string;
|
||||
prompt?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// RUNTIME — Plugin Slot 1
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Runtime determines WHERE and HOW agent sessions execute.
|
||||
* tmux, docker, kubernetes, child processes, SSH, cloud sandboxes, etc.
|
||||
*/
|
||||
export interface Runtime {
|
||||
readonly name: string;
|
||||
|
||||
/** Create a new session environment and return a handle */
|
||||
create(config: RuntimeCreateConfig): Promise<RuntimeHandle>;
|
||||
|
||||
/** Destroy a session environment */
|
||||
destroy(handle: RuntimeHandle): Promise<void>;
|
||||
|
||||
/** Send a text message/prompt to the running agent */
|
||||
sendMessage(handle: RuntimeHandle, message: string): Promise<void>;
|
||||
|
||||
/** Capture recent output from the session */
|
||||
getOutput(handle: RuntimeHandle, lines?: number): Promise<string>;
|
||||
|
||||
/** Check if the session environment is still alive */
|
||||
isAlive(handle: RuntimeHandle): Promise<boolean>;
|
||||
|
||||
/** Get resource metrics (uptime, memory, etc.) */
|
||||
getMetrics?(handle: RuntimeHandle): Promise<RuntimeMetrics>;
|
||||
|
||||
/** Get info needed to attach a human to this session (for Terminal plugin) */
|
||||
getAttachInfo?(handle: RuntimeHandle): Promise<AttachInfo>;
|
||||
}
|
||||
|
||||
export interface RuntimeCreateConfig {
|
||||
sessionId: SessionId;
|
||||
workspacePath: string;
|
||||
launchCommand: string;
|
||||
environment: Record<string, string>;
|
||||
}
|
||||
|
||||
/** Opaque handle returned by runtime.create() */
|
||||
export interface RuntimeHandle {
|
||||
/** Runtime-specific identifier (tmux session name, container ID, pod name, etc.) */
|
||||
id: string;
|
||||
/** Which runtime created this handle */
|
||||
runtimeName: string;
|
||||
/** Runtime-specific data */
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface RuntimeMetrics {
|
||||
uptimeMs: number;
|
||||
memoryMb?: number;
|
||||
cpuPercent?: number;
|
||||
}
|
||||
|
||||
export interface AttachInfo {
|
||||
/** How to connect: tmux attach, docker exec, SSH, web URL, etc. */
|
||||
type: "tmux" | "docker" | "ssh" | "web" | "process";
|
||||
/** For tmux: session name. For docker: container ID. For web: URL. */
|
||||
target: string;
|
||||
/** Optional: command to run to attach */
|
||||
command?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// AGENT — Plugin Slot 2
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Agent adapter for a specific AI coding tool.
|
||||
* Knows how to launch, detect activity, and introspect the agent.
|
||||
*/
|
||||
export interface Agent {
|
||||
readonly name: string;
|
||||
|
||||
/** Process name to look for (e.g. "claude", "codex", "aider") */
|
||||
readonly processName: string;
|
||||
|
||||
/** Get the shell command to launch this agent */
|
||||
getLaunchCommand(config: AgentLaunchConfig): string;
|
||||
|
||||
/** Get environment variables for the agent process */
|
||||
getEnvironment(config: AgentLaunchConfig): Record<string, string>;
|
||||
|
||||
/** Detect what the agent is currently doing */
|
||||
detectActivity(session: Session): Promise<ActivityState>;
|
||||
|
||||
/** Check if agent process is running (given runtime handle) */
|
||||
isProcessRunning(handle: RuntimeHandle): Promise<boolean>;
|
||||
|
||||
/** Extract information from agent's internal data (summary, cost, session ID) */
|
||||
introspect(session: Session): Promise<AgentIntrospection | null>;
|
||||
|
||||
/** Optional: run setup after agent is launched (e.g. configure MCP servers) */
|
||||
postLaunchSetup?(session: Session): Promise<void>;
|
||||
}
|
||||
|
||||
export interface AgentLaunchConfig {
|
||||
sessionId: SessionId;
|
||||
projectConfig: ProjectConfig;
|
||||
issueId?: string;
|
||||
prompt?: string;
|
||||
permissions?: "skip" | "default";
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface AgentIntrospection {
|
||||
/** Agent's auto-generated summary of what it's working on */
|
||||
summary: string | null;
|
||||
/** Agent's internal session ID (for resume) */
|
||||
agentSessionId: string | null;
|
||||
/** Estimated cost so far */
|
||||
cost?: CostEstimate;
|
||||
/** Last message type in agent's log */
|
||||
lastMessageType?: string;
|
||||
/** When agent's log was last modified */
|
||||
lastLogModified?: Date;
|
||||
}
|
||||
|
||||
export interface CostEstimate {
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
estimatedCostUsd: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// WORKSPACE — Plugin Slot 3
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Workspace manages code isolation — how each session gets its own copy of the repo.
|
||||
*/
|
||||
export interface Workspace {
|
||||
readonly name: string;
|
||||
|
||||
/** Create an isolated workspace for a session */
|
||||
create(config: WorkspaceCreateConfig): Promise<WorkspaceInfo>;
|
||||
|
||||
/** Destroy a workspace */
|
||||
destroy(workspacePath: string): Promise<void>;
|
||||
|
||||
/** List existing workspaces for a project */
|
||||
list(projectId: string): Promise<WorkspaceInfo[]>;
|
||||
|
||||
/** Optional: run hooks after workspace creation (symlinks, installs, etc.) */
|
||||
postCreate?(info: WorkspaceInfo, project: ProjectConfig): Promise<void>;
|
||||
}
|
||||
|
||||
export interface WorkspaceCreateConfig {
|
||||
projectId: string;
|
||||
project: ProjectConfig;
|
||||
sessionId: SessionId;
|
||||
branch: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceInfo {
|
||||
path: string;
|
||||
branch: string;
|
||||
sessionId: SessionId;
|
||||
projectId: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TRACKER — Plugin Slot 4
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Issue/task tracker integration — GitHub Issues, Linear, Jira, etc.
|
||||
*/
|
||||
export interface Tracker {
|
||||
readonly name: string;
|
||||
|
||||
/** Fetch issue details */
|
||||
getIssue(identifier: string, project: ProjectConfig): Promise<Issue>;
|
||||
|
||||
/** Check if issue is completed/closed */
|
||||
isCompleted(identifier: string, project: ProjectConfig): Promise<boolean>;
|
||||
|
||||
/** Generate a URL for the issue */
|
||||
issueUrl(identifier: string, project: ProjectConfig): string;
|
||||
|
||||
/** Generate a git branch name for the issue */
|
||||
branchName(identifier: string, project: ProjectConfig): string;
|
||||
|
||||
/** Generate a prompt for the agent to work on this issue */
|
||||
generatePrompt(identifier: string, project: ProjectConfig): Promise<string>;
|
||||
|
||||
/** Optional: list issues with filters */
|
||||
listIssues?(filters: IssueFilters, project: ProjectConfig): Promise<Issue[]>;
|
||||
|
||||
/** Optional: update issue state */
|
||||
updateIssue?(identifier: string, update: IssueUpdate, project: ProjectConfig): Promise<void>;
|
||||
|
||||
/** Optional: create a new issue */
|
||||
createIssue?(input: CreateIssueInput, project: ProjectConfig): Promise<Issue>;
|
||||
}
|
||||
|
||||
export interface Issue {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
url: string;
|
||||
state: "open" | "in_progress" | "closed" | "cancelled";
|
||||
labels: string[];
|
||||
assignee?: string;
|
||||
priority?: number;
|
||||
}
|
||||
|
||||
export interface IssueFilters {
|
||||
state?: "open" | "closed" | "all";
|
||||
labels?: string[];
|
||||
assignee?: string;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface IssueUpdate {
|
||||
state?: "open" | "in_progress" | "closed";
|
||||
labels?: string[];
|
||||
assignee?: string;
|
||||
comment?: string;
|
||||
}
|
||||
|
||||
export interface CreateIssueInput {
|
||||
title: string;
|
||||
description: string;
|
||||
labels?: string[];
|
||||
assignee?: string;
|
||||
priority?: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SCM — Plugin Slot 5
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Source code management platform — PR lifecycle, CI checks, code reviews.
|
||||
* This is the richest plugin interface, covering the full PR pipeline.
|
||||
*/
|
||||
export interface SCM {
|
||||
readonly name: string;
|
||||
|
||||
// --- PR Lifecycle ---
|
||||
|
||||
/** Detect if a session has an open PR (by branch name) */
|
||||
detectPR(session: Session, project: ProjectConfig): Promise<PRInfo | null>;
|
||||
|
||||
/** Get current PR state */
|
||||
getPRState(pr: PRInfo): Promise<PRState>;
|
||||
|
||||
/** Merge a PR */
|
||||
mergePR(pr: PRInfo, method?: MergeMethod): Promise<void>;
|
||||
|
||||
/** Close a PR without merging */
|
||||
closePR(pr: PRInfo): Promise<void>;
|
||||
|
||||
// --- CI Tracking ---
|
||||
|
||||
/** Get individual CI check statuses */
|
||||
getCIChecks(pr: PRInfo): Promise<CICheck[]>;
|
||||
|
||||
/** Get overall CI summary */
|
||||
getCISummary(pr: PRInfo): Promise<CIStatus>;
|
||||
|
||||
// --- Review Tracking ---
|
||||
|
||||
/** Get all reviews on a PR */
|
||||
getReviews(pr: PRInfo): Promise<Review[]>;
|
||||
|
||||
/** Get the overall review decision */
|
||||
getReviewDecision(pr: PRInfo): Promise<ReviewDecision>;
|
||||
|
||||
/** Get pending (unresolved) review comments */
|
||||
getPendingComments(pr: PRInfo): Promise<ReviewComment[]>;
|
||||
|
||||
/** Get automated review comments (bots, linters, security scanners) */
|
||||
getAutomatedComments(pr: PRInfo): Promise<AutomatedComment[]>;
|
||||
|
||||
// --- Merge Readiness ---
|
||||
|
||||
/** Check if PR is ready to merge */
|
||||
getMergeability(pr: PRInfo): Promise<MergeReadiness>;
|
||||
}
|
||||
|
||||
// --- PR Types ---
|
||||
|
||||
export interface PRInfo {
|
||||
number: number;
|
||||
url: string;
|
||||
title: string;
|
||||
owner: string;
|
||||
repo: string;
|
||||
branch: string;
|
||||
baseBranch: string;
|
||||
isDraft: boolean;
|
||||
}
|
||||
|
||||
export type PRState = "open" | "merged" | "closed";
|
||||
|
||||
export type MergeMethod = "merge" | "squash" | "rebase";
|
||||
|
||||
// --- CI Types ---
|
||||
|
||||
export interface CICheck {
|
||||
name: string;
|
||||
status: "pending" | "running" | "passed" | "failed" | "skipped";
|
||||
url?: string;
|
||||
conclusion?: string;
|
||||
startedAt?: Date;
|
||||
completedAt?: Date;
|
||||
}
|
||||
|
||||
export type CIStatus = "pending" | "passing" | "failing" | "none";
|
||||
|
||||
// --- Review Types ---
|
||||
|
||||
export interface Review {
|
||||
author: string;
|
||||
state: "approved" | "changes_requested" | "commented" | "dismissed" | "pending";
|
||||
body?: string;
|
||||
submittedAt: Date;
|
||||
}
|
||||
|
||||
export type ReviewDecision = "approved" | "changes_requested" | "pending" | "none";
|
||||
|
||||
export interface ReviewComment {
|
||||
id: string;
|
||||
author: string;
|
||||
body: string;
|
||||
path?: string;
|
||||
line?: number;
|
||||
isResolved: boolean;
|
||||
createdAt: Date;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface AutomatedComment {
|
||||
id: string;
|
||||
botName: string;
|
||||
body: string;
|
||||
path?: string;
|
||||
line?: number;
|
||||
severity: "error" | "warning" | "info";
|
||||
createdAt: Date;
|
||||
url: string;
|
||||
}
|
||||
|
||||
// --- Merge Readiness ---
|
||||
|
||||
export interface MergeReadiness {
|
||||
mergeable: boolean;
|
||||
ciPassing: boolean;
|
||||
approved: boolean;
|
||||
noConflicts: boolean;
|
||||
blockers: string[];
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// NOTIFIER — Plugin Slot 6 (PRIMARY INTERFACE)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Notifier is the PRIMARY interface between the orchestrator and the human.
|
||||
* The human walks away after spawning agents. Notifications bring them back.
|
||||
*
|
||||
* Push, not pull. The human never polls.
|
||||
*/
|
||||
export interface Notifier {
|
||||
readonly name: string;
|
||||
|
||||
/** Push a notification to the human */
|
||||
notify(event: OrchestratorEvent): Promise<void>;
|
||||
|
||||
/** Push a notification with actionable buttons/links */
|
||||
notifyWithActions?(event: OrchestratorEvent, actions: NotifyAction[]): Promise<void>;
|
||||
|
||||
/** Post a message to a channel (for team-visible notifiers like Slack) */
|
||||
post?(message: string, context?: NotifyContext): Promise<string | null>;
|
||||
}
|
||||
|
||||
export interface NotifyAction {
|
||||
label: string;
|
||||
url?: string;
|
||||
callbackEndpoint?: string;
|
||||
}
|
||||
|
||||
export interface NotifyContext {
|
||||
sessionId?: SessionId;
|
||||
projectId?: string;
|
||||
prUrl?: string;
|
||||
channel?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TERMINAL — Plugin Slot 7
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Terminal manages how humans view/interact with running sessions.
|
||||
* Opens IDE tabs, browser windows, or terminal sessions.
|
||||
*/
|
||||
export interface Terminal {
|
||||
readonly name: string;
|
||||
|
||||
/** Open a session for human interaction */
|
||||
openSession(session: Session): Promise<void>;
|
||||
|
||||
/** Open all sessions for a project */
|
||||
openAll(sessions: Session[]): Promise<void>;
|
||||
|
||||
/** Check if a session is already open in a tab/window */
|
||||
isSessionOpen?(session: Session): Promise<boolean>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EVENTS
|
||||
// =============================================================================
|
||||
|
||||
/** Priority levels for events — determines notification routing */
|
||||
export type EventPriority = "urgent" | "action" | "warning" | "info";
|
||||
|
||||
/** All orchestrator event types */
|
||||
export type EventType =
|
||||
// Session lifecycle
|
||||
| "session.spawned"
|
||||
| "session.working"
|
||||
| "session.exited"
|
||||
| "session.killed"
|
||||
| "session.stuck"
|
||||
| "session.needs_input"
|
||||
| "session.errored"
|
||||
// PR lifecycle
|
||||
| "pr.created"
|
||||
| "pr.updated"
|
||||
| "pr.merged"
|
||||
| "pr.closed"
|
||||
// CI
|
||||
| "ci.passing"
|
||||
| "ci.failing"
|
||||
| "ci.fix_sent"
|
||||
| "ci.fix_failed"
|
||||
// Reviews
|
||||
| "review.pending"
|
||||
| "review.approved"
|
||||
| "review.changes_requested"
|
||||
| "review.comments_sent"
|
||||
| "review.comments_unresolved"
|
||||
// Automated reviews
|
||||
| "automated_review.found"
|
||||
| "automated_review.fix_sent"
|
||||
// Merge
|
||||
| "merge.ready"
|
||||
| "merge.conflicts"
|
||||
| "merge.completed"
|
||||
// Reactions
|
||||
| "reaction.triggered"
|
||||
| "reaction.escalated"
|
||||
// Summary
|
||||
| "summary.all_complete";
|
||||
|
||||
/** An event emitted by the orchestrator */
|
||||
export interface OrchestratorEvent {
|
||||
id: string;
|
||||
type: EventType;
|
||||
priority: EventPriority;
|
||||
sessionId: SessionId;
|
||||
projectId: string;
|
||||
timestamp: Date;
|
||||
message: string;
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// REACTIONS
|
||||
// =============================================================================
|
||||
|
||||
/** A configured automatic reaction to an event */
|
||||
export interface ReactionConfig {
|
||||
/** Whether this reaction is enabled */
|
||||
auto: boolean;
|
||||
|
||||
/** What to do: send message to agent, notify human, auto-merge */
|
||||
action: "send-to-agent" | "notify" | "auto-merge";
|
||||
|
||||
/** Message to send (for send-to-agent) */
|
||||
message?: string;
|
||||
|
||||
/** Priority for notifications */
|
||||
priority?: EventPriority;
|
||||
|
||||
/** How many times to retry send-to-agent before escalating */
|
||||
retries?: number;
|
||||
|
||||
/** Escalate to human notification after this many failures or this duration */
|
||||
escalateAfter?: number | string;
|
||||
|
||||
/** Threshold duration for time-based triggers (e.g. "10m" for stuck detection) */
|
||||
threshold?: string;
|
||||
|
||||
/** Whether to include a summary in the notification */
|
||||
includeSummary?: boolean;
|
||||
}
|
||||
|
||||
export interface ReactionResult {
|
||||
reactionType: string;
|
||||
success: boolean;
|
||||
action: string;
|
||||
message?: string;
|
||||
escalated: boolean;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
/** Top-level orchestrator configuration (from agent-orchestrator.yaml) */
|
||||
export interface OrchestratorConfig {
|
||||
/** Where to store session metadata */
|
||||
dataDir: string;
|
||||
|
||||
/** Where to create workspaces (worktrees, clones) */
|
||||
worktreeDir: string;
|
||||
|
||||
/** Web dashboard port */
|
||||
port: number;
|
||||
|
||||
/** Default plugin selections */
|
||||
defaults: DefaultPlugins;
|
||||
|
||||
/** Project configurations */
|
||||
projects: Record<string, ProjectConfig>;
|
||||
|
||||
/** Notification channel configs */
|
||||
notifiers: Record<string, NotifierConfig>;
|
||||
|
||||
/** Notification routing by priority */
|
||||
notificationRouting: Record<EventPriority, string[]>;
|
||||
|
||||
/** Default reaction configs */
|
||||
reactions: Record<string, ReactionConfig>;
|
||||
}
|
||||
|
||||
export interface DefaultPlugins {
|
||||
runtime: string;
|
||||
agent: string;
|
||||
workspace: string;
|
||||
notifiers: string[];
|
||||
}
|
||||
|
||||
export interface ProjectConfig {
|
||||
/** Display name */
|
||||
name: string;
|
||||
|
||||
/** GitHub repo in "owner/repo" format */
|
||||
repo: string;
|
||||
|
||||
/** Local path to the repo */
|
||||
path: string;
|
||||
|
||||
/** Default branch (main, master, next, develop, etc.) */
|
||||
defaultBranch: string;
|
||||
|
||||
/** Session name prefix (e.g. "app" → "app-1", "app-2") */
|
||||
sessionPrefix: string;
|
||||
|
||||
/** Override default runtime */
|
||||
runtime?: string;
|
||||
|
||||
/** Override default agent */
|
||||
agent?: string;
|
||||
|
||||
/** Override default workspace */
|
||||
workspace?: string;
|
||||
|
||||
/** Issue tracker configuration */
|
||||
tracker?: TrackerConfig;
|
||||
|
||||
/** SCM configuration (usually inferred from repo) */
|
||||
scm?: SCMConfig;
|
||||
|
||||
/** Files/dirs to symlink into workspaces */
|
||||
symlinks?: string[];
|
||||
|
||||
/** Commands to run after workspace creation */
|
||||
postCreate?: string[];
|
||||
|
||||
/** Agent-specific configuration */
|
||||
agentConfig?: AgentSpecificConfig;
|
||||
|
||||
/** Per-project reaction overrides */
|
||||
reactions?: Record<string, Partial<ReactionConfig>>;
|
||||
}
|
||||
|
||||
export interface TrackerConfig {
|
||||
plugin: string;
|
||||
/** Plugin-specific config (e.g. teamId for Linear) */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface SCMConfig {
|
||||
plugin: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface NotifierConfig {
|
||||
plugin: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface AgentSpecificConfig {
|
||||
permissions?: "skip" | "default";
|
||||
model?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// PLUGIN SYSTEM
|
||||
// =============================================================================
|
||||
|
||||
/** Plugin slot types */
|
||||
export type PluginSlot =
|
||||
| "runtime"
|
||||
| "agent"
|
||||
| "workspace"
|
||||
| "tracker"
|
||||
| "scm"
|
||||
| "notifier"
|
||||
| "terminal";
|
||||
|
||||
/** Plugin manifest — what every plugin exports */
|
||||
export interface PluginManifest {
|
||||
/** Plugin name (e.g. "tmux", "claude-code", "github") */
|
||||
name: string;
|
||||
|
||||
/** Which slot this plugin fills */
|
||||
slot: PluginSlot;
|
||||
|
||||
/** Human-readable description */
|
||||
description: string;
|
||||
|
||||
/** Version */
|
||||
version: string;
|
||||
}
|
||||
|
||||
/** What a plugin module must export */
|
||||
export interface PluginModule<T = unknown> {
|
||||
manifest: PluginManifest;
|
||||
create(config?: Record<string, unknown>): T;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SESSION METADATA (flat file format)
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Session metadata stored as flat key=value files.
|
||||
* Matches the existing bash script format for backwards compatibility.
|
||||
*/
|
||||
export interface SessionMetadata {
|
||||
worktree: string;
|
||||
branch: string;
|
||||
status: string;
|
||||
issue?: string;
|
||||
pr?: string;
|
||||
summary?: string;
|
||||
project?: string;
|
||||
createdAt?: string;
|
||||
runtimeHandle?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SERVICE INTERFACES (core, not pluggable)
|
||||
// =============================================================================
|
||||
|
||||
/** Session manager — CRUD for sessions */
|
||||
export interface SessionManager {
|
||||
spawn(config: SessionSpawnConfig): Promise<Session>;
|
||||
list(projectId?: string): Promise<Session[]>;
|
||||
get(sessionId: SessionId): Promise<Session | null>;
|
||||
kill(sessionId: SessionId): Promise<void>;
|
||||
cleanup(projectId?: string): Promise<CleanupResult>;
|
||||
send(sessionId: SessionId, message: string): Promise<void>;
|
||||
}
|
||||
|
||||
export interface CleanupResult {
|
||||
killed: string[];
|
||||
skipped: string[];
|
||||
errors: Array<{ sessionId: string; error: string }>;
|
||||
}
|
||||
|
||||
/** Lifecycle manager — state machine + reaction engine */
|
||||
export interface LifecycleManager {
|
||||
/** Start the lifecycle polling loop */
|
||||
start(intervalMs?: number): void;
|
||||
|
||||
/** Stop the lifecycle polling loop */
|
||||
stop(): void;
|
||||
|
||||
/** Get current state for all sessions */
|
||||
getStates(): Map<SessionId, SessionStatus>;
|
||||
|
||||
/** Force-check a specific session now */
|
||||
check(sessionId: SessionId): Promise<void>;
|
||||
|
||||
/** Subscribe to lifecycle events */
|
||||
on(event: EventType | "*", handler: (event: OrchestratorEvent) => void): void;
|
||||
off(event: EventType | "*", handler: (event: OrchestratorEvent) => void): void;
|
||||
}
|
||||
|
||||
/** Event bus — pub/sub + persistence */
|
||||
export interface EventBus {
|
||||
emit(event: OrchestratorEvent): void;
|
||||
on(event: EventType | "*", handler: (event: OrchestratorEvent) => void): void;
|
||||
off(event: EventType | "*", handler: (event: OrchestratorEvent) => void): void;
|
||||
getHistory(filter?: EventFilter): OrchestratorEvent[];
|
||||
}
|
||||
|
||||
export interface EventFilter {
|
||||
sessionId?: SessionId;
|
||||
projectId?: string;
|
||||
type?: EventType;
|
||||
priority?: EventPriority;
|
||||
since?: Date;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
/** Plugin registry — discovery + loading */
|
||||
export interface PluginRegistry {
|
||||
/** Register a plugin */
|
||||
register(plugin: PluginModule): void;
|
||||
|
||||
/** Get a plugin by slot and name */
|
||||
get<T>(slot: PluginSlot, name: string): T | null;
|
||||
|
||||
/** List plugins for a slot */
|
||||
list(slot: PluginSlot): PluginManifest[];
|
||||
|
||||
/** Load built-in plugins */
|
||||
loadBuiltins(): Promise<void>;
|
||||
|
||||
/** Load plugins from config (npm packages, local paths) */
|
||||
loadFromConfig(config: OrchestratorConfig): Promise<void>;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-agent-aider",
|
||||
"version": "0.1.0",
|
||||
"description": "Agent plugin: Aider",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// agent-aider plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-agent-claude-code",
|
||||
"version": "0.1.0",
|
||||
"description": "Agent plugin: Claude Code",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// agent-claude-code plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-agent-codex",
|
||||
"version": "0.1.0",
|
||||
"description": "Agent plugin: OpenAI Codex CLI",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// agent-codex plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-notifier-desktop",
|
||||
"version": "0.1.0",
|
||||
"description": "Notifier plugin: OS desktop notifications",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// notifier-desktop plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-notifier-slack",
|
||||
"version": "0.1.0",
|
||||
"description": "Notifier plugin: Slack",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// notifier-slack plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-notifier-webhook",
|
||||
"version": "0.1.0",
|
||||
"description": "Notifier plugin: generic webhook",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// notifier-webhook plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-runtime-process",
|
||||
"version": "0.1.0",
|
||||
"description": "Runtime plugin: child processes",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// runtime-process plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-runtime-tmux",
|
||||
"version": "0.1.0",
|
||||
"description": "Runtime plugin: tmux sessions",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// runtime-tmux plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-scm-github",
|
||||
"version": "0.1.0",
|
||||
"description": "SCM plugin: GitHub (PRs, CI, reviews)",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// scm-github plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-terminal-iterm2",
|
||||
"version": "0.1.0",
|
||||
"description": "Terminal plugin: macOS iTerm2",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// terminal-iterm2 plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-terminal-web",
|
||||
"version": "0.1.0",
|
||||
"description": "Terminal plugin: xterm.js web terminal",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// terminal-web plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-tracker-github",
|
||||
"version": "0.1.0",
|
||||
"description": "Tracker plugin: GitHub Issues",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// tracker-github plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-tracker-linear",
|
||||
"version": "0.1.0",
|
||||
"description": "Tracker plugin: Linear",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// tracker-linear plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-workspace-clone",
|
||||
"version": "0.1.0",
|
||||
"description": "Workspace plugin: git clone",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// workspace-clone plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/plugin-workspace-worktree",
|
||||
"version": "0.1.0",
|
||||
"description": "Workspace plugin: git worktrees",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^25.2.3",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
// workspace-worktree plugin — to be implemented
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "@agent-orchestrator/web",
|
||||
"version": "0.1.0",
|
||||
"description": "Web dashboard for agent-orchestrator",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"clean": "rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@agent-orchestrator/core": "workspace:*",
|
||||
"next": "^15.1.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Web dashboard layout — to be implemented
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// Dashboard home — to be implemented
|
||||
export default function Home() {
|
||||
return <div>Agent Orchestrator Dashboard</div>;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"jsx": "preserve",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"plugins": [{ "name": "next" }],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "next-env.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,3 @@
|
|||
packages:
|
||||
- "packages/*"
|
||||
- "packages/plugins/*"
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"lib": ["ES2022"],
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue