@revealui/harnesses 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-JG6CAG4A.js +540 -0
- package/dist/chunk-JG6CAG4A.js.map +1 -0
- package/dist/{chunk-HH2PJYQN.js → chunk-XLIKSLM3.js} +15 -68
- package/dist/chunk-XLIKSLM3.js.map +1 -0
- package/dist/{chunk-JDI6B2IB.js → chunk-XXEKWC6F.js} +2 -2
- package/dist/{chunk-JDI6B2IB.js.map → chunk-XXEKWC6F.js.map} +1 -1
- package/dist/cli.js +9 -9
- package/dist/cli.js.map +1 -1
- package/dist/content/index.d.ts +8 -8
- package/dist/content/index.js +1 -1
- package/dist/index.js +3 -3
- package/dist/workboard/index.d.ts +115 -61
- package/dist/workboard/index.js +5 -1
- package/package.json +7 -3
- package/dist/chunk-FJGN6DTH.js +0 -387
- package/dist/chunk-FJGN6DTH.js.map +0 -1
- package/dist/chunk-HH2PJYQN.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
HarnessCoordinator,
|
|
4
4
|
checkHarnessesLicense
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XLIKSLM3.js";
|
|
6
6
|
import {
|
|
7
7
|
buildManifest,
|
|
8
8
|
diffContent,
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
listContent,
|
|
11
11
|
listGenerators,
|
|
12
12
|
validateManifest
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XXEKWC6F.js";
|
|
14
14
|
import {
|
|
15
15
|
WorkboardManager
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JG6CAG4A.js";
|
|
17
17
|
import "./chunk-DGUM43GV.js";
|
|
18
18
|
|
|
19
19
|
// src/cli.ts
|
|
@@ -459,16 +459,16 @@ async function main() {
|
|
|
459
459
|
const workboardPath = join(projectRoot, ".claude", "workboard.md");
|
|
460
460
|
const manager = new WorkboardManager(workboardPath);
|
|
461
461
|
const state = manager.read();
|
|
462
|
-
process.stdout.write(`
|
|
462
|
+
process.stdout.write(`Agents (${state.agents.length}):
|
|
463
463
|
`);
|
|
464
|
-
for (const
|
|
465
|
-
const stale = Date.now() - new Date(
|
|
466
|
-
process.stdout.write(` ${
|
|
464
|
+
for (const a of state.agents) {
|
|
465
|
+
const stale = Date.now() - new Date(a.updated).getTime() > 4 * 60 * 60 * 1e3;
|
|
466
|
+
process.stdout.write(` ${a.id} [${a.env}] \u2014 ${a.task}${stale ? " (STALE)" : ""}
|
|
467
467
|
`);
|
|
468
|
-
if (
|
|
468
|
+
if (a.files) process.stdout.write(` files: ${a.files}
|
|
469
469
|
`);
|
|
470
470
|
}
|
|
471
|
-
if (state.
|
|
471
|
+
if (state.agents.length === 0) process.stdout.write(" (no active agents)\n");
|
|
472
472
|
}
|
|
473
473
|
break;
|
|
474
474
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * revealui-harnesses — CLI daemon and RPC client for AI harness coordination.\n *\n * Commands:\n * start [--project <path>] Detect harnesses, register in workboard, start RPC server\n * status List available harnesses via RPC\n * list List harnesses in TSV format\n * sync <harnessId> <push|pull> Sync harness config to/from SSD\n * coordinate [--print] Print current workboard state\n * coordinate --init <path> Register this session in the workboard and start daemon\n *\n * License: Pro tier required (isFeatureEnabled(\"harnesses\"))\n */\n\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { createConnection } from 'node:net';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport {\n buildManifest,\n diffContent,\n generateContent,\n listContent,\n listGenerators,\n validateManifest,\n} from './content/index.js';\nimport { HarnessCoordinator } from './coordinator.js';\nimport { checkHarnessesLicense } from './index.js';\nimport { WorkboardManager } from './workboard/workboard-manager.js';\n\nconst DEFAULT_SOCKET = join(homedir(), '.local', 'share', 'revealui', 'harness.sock');\nconst DEFAULT_PROJECT = process.cwd();\n\nconst [, , command, ...args] = process.argv;\n\nasync function rpcCall(method: string, params: unknown = {}): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const socket = createConnection(DEFAULT_SOCKET);\n let buffer = '';\n socket.on('connect', () => {\n const req = JSON.stringify({ jsonrpc: '2.0', id: 1, method, params });\n socket.write(`${req}\\n`);\n });\n socket.on('data', (chunk) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const resp = JSON.parse(line) as { result?: unknown; error?: { message: string } };\n socket.destroy();\n if (resp.error) reject(new Error(resp.error.message));\n else resolve(resp.result);\n } catch {\n reject(new Error(`Invalid JSON: ${line}`));\n }\n }\n });\n socket.on('error', reject);\n setTimeout(() => {\n socket.destroy();\n reject(new Error('RPC timeout'));\n }, 5000);\n });\n}\n\nasync function handleContentCommand(subcommand: string | undefined, args: string[]): Promise<void> {\n const manifest = buildManifest();\n const projectRoot = process.cwd();\n const ctx = { projectRoot };\n\n switch (subcommand) {\n case 'list': {\n const summary = listContent(manifest);\n process.stdout.write(`Canonical content:\\n`);\n process.stdout.write(` Rules: ${summary.rules}\\n`);\n process.stdout.write(` Commands: ${summary.commands}\\n`);\n process.stdout.write(` Agents: ${summary.agents}\\n`);\n process.stdout.write(` Skills: ${summary.skills}\\n`);\n process.stdout.write(` Preambles: ${summary.preambles}\\n`);\n process.stdout.write(` Total: ${summary.total}\\n`);\n process.stdout.write(`\\nRules:\\n`);\n for (const rule of manifest.rules) {\n process.stdout.write(` ${rule.id} (tier ${rule.preambleTier}) — ${rule.description}\\n`);\n }\n process.stdout.write(`\\nCommands:\\n`);\n for (const cmd of manifest.commands) {\n process.stdout.write(\n ` ${cmd.id}${cmd.disableModelInvocation ? ' [manual]' : ''} — ${cmd.description.slice(0, 80)}\\n`,\n );\n }\n process.stdout.write(`\\nAgents:\\n`);\n for (const agent of manifest.agents) {\n process.stdout.write(` ${agent.id} [${agent.isolation}] — ${agent.description}\\n`);\n }\n process.stdout.write(`\\nSkills:\\n`);\n for (const skill of manifest.skills) {\n process.stdout.write(\n ` ${skill.id}${skill.disableModelInvocation ? ' [manual]' : ''} — ${skill.description.slice(0, 80)}\\n`,\n );\n }\n process.stdout.write(`\\nGenerators: ${listGenerators().join(', ')}\\n`);\n break;\n }\n\n case 'validate': {\n const result = validateManifest(manifest);\n if (result.valid) {\n process.stdout.write(`✓ All definitions valid\\n`);\n } else {\n process.stderr.write(`✗ Validation errors:\\n`);\n for (const error of result.errors) {\n process.stderr.write(` - ${error}\\n`);\n }\n process.exit(1);\n }\n break;\n }\n\n case 'diff': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const entries = diffContent(generatorId, manifest, ctx, projectRoot);\n const added = entries.filter((e) => e.status === 'added');\n const modified = entries.filter((e) => e.status === 'modified');\n const unchanged = entries.filter((e) => e.status === 'unchanged');\n\n if (added.length === 0 && modified.length === 0) {\n process.stdout.write(`✓ No changes (${unchanged.length} files up to date)\\n`);\n } else {\n if (added.length > 0) {\n process.stdout.write(`Added (${added.length}):\\n`);\n for (const e of added) process.stdout.write(` + ${e.relativePath}\\n`);\n }\n if (modified.length > 0) {\n process.stdout.write(`Modified (${modified.length}):\\n`);\n for (const e of modified) process.stdout.write(` ~ ${e.relativePath}\\n`);\n }\n process.stdout.write(`Unchanged: ${unchanged.length}\\n`);\n }\n break;\n }\n\n case 'sync': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const dryRun = args.includes('--dry-run');\n const files = generateContent(generatorId, manifest, ctx);\n\n if (dryRun) {\n process.stdout.write(`Dry run — would write ${files.length} files:\\n`);\n for (const file of files) {\n process.stdout.write(` ${file.relativePath}\\n`);\n }\n } else {\n let written = 0;\n for (const file of files) {\n const absolutePath = join(projectRoot, file.relativePath);\n mkdirSync(dirname(absolutePath), { recursive: true });\n writeFileSync(absolutePath, file.content, 'utf-8');\n written++;\n }\n process.stdout.write(`✓ Wrote ${written} files via ${generatorId} generator\\n`);\n }\n break;\n }\n\n case 'export': {\n const outIdx = args.indexOf('--output');\n const rawOutput = outIdx >= 0 ? args[outIdx + 1] : undefined;\n if (!rawOutput) {\n process.stderr.write('Usage: content export --output <path>\\n');\n process.exit(1);\n }\n const outputDir: string = rawOutput;\n\n // 1. Write canonical definitions organized by type/tier\n const definitionTypes = [\n { key: 'rules' as const, items: manifest.rules },\n { key: 'commands' as const, items: manifest.commands },\n { key: 'agents' as const, items: manifest.agents },\n { key: 'skills' as const, items: manifest.skills },\n ];\n\n let canonicalCount = 0;\n for (const { key, items } of definitionTypes) {\n for (const item of items) {\n const tier = item.tier ?? 'oss';\n const filePath = join(outputDir, key, tier, `${item.id}.md`);\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, item.content, 'utf-8');\n canonicalCount++;\n }\n }\n\n // 2. Write pre-rendered generator output (compute once, reuse for manifest)\n const generatorIds = listGenerators();\n const generatorOutputs = new Map<string, { relativePath: string; content: string }[]>();\n let generatedCount = 0;\n for (const genId of generatorIds) {\n const files = generateContent(genId, manifest, ctx);\n generatorOutputs.set(genId, files);\n for (const file of files) {\n const filePath = join(outputDir, 'generators', genId, file.relativePath);\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, file.content, 'utf-8');\n generatedCount++;\n }\n }\n\n // 3. Write manifest.json with metadata\n interface ManifestEntry {\n id: string;\n type: string;\n name: string;\n description: string;\n tier: string;\n tags?: string[];\n canonicalPath: string;\n generatorPaths: Record<string, string[]>;\n }\n\n const entries: ManifestEntry[] = [];\n for (const { key, items } of definitionTypes) {\n for (const item of items) {\n const tier = item.tier ?? 'oss';\n const type = key.replace(/s$/, ''); // rules → rule\n const entry: ManifestEntry = {\n id: item.id,\n type,\n name: item.name,\n description: item.description,\n tier,\n canonicalPath: `${key}/${tier}/${item.id}.md`,\n generatorPaths: {},\n };\n if ('tags' in item && Array.isArray(item.tags) && item.tags.length > 0) {\n entry.tags = item.tags;\n }\n // Map each generator's output paths for this definition\n for (const genId of generatorIds) {\n const genFiles = generatorOutputs.get(genId) ?? [];\n const matching = genFiles\n .filter((f) => f.relativePath.includes(item.id))\n .map((f) => f.relativePath);\n if (matching.length > 0) {\n entry.generatorPaths[genId] = matching;\n }\n }\n entries.push(entry);\n }\n }\n\n const exportManifest = {\n version: 1,\n generatedAt: new Date().toISOString(),\n generators: generatorIds,\n definitions: entries,\n };\n\n const manifestPath = join(outputDir, 'manifest.json');\n mkdirSync(dirname(manifestPath), { recursive: true });\n writeFileSync(manifestPath, `${JSON.stringify(exportManifest, null, 2)}\\n`, 'utf-8');\n\n process.stdout.write(`✓ Exported to ${outputDir}\\n`);\n process.stdout.write(` Canonical definitions: ${canonicalCount}\\n`);\n process.stdout.write(\n ` Generator output: ${generatedCount} files (${generatorIds.join(', ')})\\n`,\n );\n process.stdout.write(` Manifest: manifest.json\\n`);\n break;\n }\n\n case 'pull': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const tierIdx = args.indexOf('--tier');\n const tierFilter = tierIdx >= 0 ? (args[tierIdx + 1] ?? 'oss') : 'oss';\n\n if (!['oss', 'pro', 'all'].includes(tierFilter)) {\n process.stderr.write(`Invalid tier: ${tierFilter}. Use: oss, pro, all\\n`);\n process.exit(1);\n }\n\n // Pro tier requires a valid license\n const needsLicense = tierFilter === 'pro' || tierFilter === 'all';\n if (needsLicense) {\n const licensed = await checkHarnessesLicense();\n if (!licensed) {\n process.stderr.write(\n 'Pro rules require a valid license key. Visit https://revealui.com/pricing\\n',\n );\n process.exit(1);\n }\n }\n\n const baseUrl =\n args[args.indexOf('--url') + 1] ??\n process.env.REVEALUI_RULES_URL ??\n 'https://raw.githubusercontent.com/RevealUIStudio/editor-configs/main/harnesses';\n\n // Fetch manifest from remote\n process.stdout.write(`Fetching manifest from ${baseUrl}/manifest.json...\\n`);\n const manifestRes = await fetch(`${baseUrl}/manifest.json`);\n if (!manifestRes.ok) {\n process.stderr.write(\n `Failed to fetch manifest: ${manifestRes.status} ${manifestRes.statusText}\\n`,\n );\n process.exit(1);\n }\n\n const remoteManifest = (await manifestRes.json()) as {\n definitions: Array<{\n id: string;\n type: string;\n name: string;\n tier: string;\n generatorPaths: Record<string, string[]>;\n }>;\n };\n\n // Filter definitions by tier\n const filtered = remoteManifest.definitions.filter((def) => {\n if (tierFilter === 'all') return true;\n return def.tier === tierFilter;\n });\n\n process.stdout.write(`Found ${filtered.length} definitions (tier: ${tierFilter})\\n`);\n\n // Download pre-rendered files for the selected generator\n let written = 0;\n let errors = 0;\n for (const def of filtered) {\n const paths = def.generatorPaths[generatorId] ?? [];\n for (const relPath of paths) {\n const fileUrl = `${baseUrl}/generators/${generatorId}/${relPath}`;\n try {\n const fileRes = await fetch(fileUrl);\n if (!fileRes.ok) {\n process.stderr.write(` ✗ ${relPath} (${fileRes.status})\\n`);\n errors++;\n continue;\n }\n const content = await fileRes.text();\n const absolutePath = join(projectRoot, relPath);\n mkdirSync(dirname(absolutePath), { recursive: true });\n writeFileSync(absolutePath, content, 'utf-8');\n written++;\n } catch (err) {\n process.stderr.write(\n ` ✗ ${relPath} (${err instanceof Error ? err.message : 'fetch error'})\\n`,\n );\n errors++;\n }\n }\n }\n\n process.stdout.write(`✓ Pulled ${written} files via ${generatorId} generator\\n`);\n if (errors > 0) {\n process.stderr.write(` ${errors} file(s) failed to download\\n`);\n }\n break;\n }\n\n default:\n process.stderr.write(`Unknown content subcommand: ${subcommand ?? '(none)'}\\n`);\n process.stderr.write(`Available: list, validate, diff, sync, export, pull\\n`);\n process.exit(1);\n }\n}\n\nasync function main() {\n // Content commands are developer tooling — no license required\n if (command === 'content') {\n const [subcommand] = args;\n const contentArgs = args.slice(1);\n await handleContentCommand(subcommand, contentArgs);\n return;\n }\n\n if (!(await checkHarnessesLicense())) {\n process.stderr.write(\n '⚠ @revealui/harnesses requires a Pro license. Visit https://revealui.com/pricing\\n',\n );\n process.exit(2);\n }\n\n switch (command) {\n case 'start': {\n const projectIdx = args.indexOf('--project');\n const projectRoot =\n projectIdx >= 0 ? (args[projectIdx + 1] ?? DEFAULT_PROJECT) : DEFAULT_PROJECT;\n\n const coordinator = new HarnessCoordinator({\n projectRoot,\n task: 'Harness coordination active',\n });\n\n await coordinator.start();\n const ids = await coordinator.getRegistry().listAvailable();\n process.stdout.write(`✓ Detected harnesses: ${ids.length > 0 ? ids.join(', ') : 'none'}\\n`);\n process.stdout.write(`✓ RPC server listening on ${DEFAULT_SOCKET}\\n`);\n process.stdout.write(`✓ Session registered in workboard\\n`);\n\n const shutdown = async () => {\n await coordinator.stop();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n break;\n }\n\n case 'status': {\n try {\n const infos = (await rpcCall('harness.list')) as Array<{\n id: string;\n name: string;\n version?: string;\n }>;\n if (infos.length === 0) {\n process.stdout.write('No harnesses available\\n');\n } else {\n for (const info of infos) {\n process.stdout.write(\n `${info.id}\\t${info.name}${info.version ? `\\t${info.version}` : ''}\\n`,\n );\n }\n }\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'list': {\n try {\n const infos = (await rpcCall('harness.list')) as Array<{ id: string; name: string }>;\n for (const info of infos) {\n process.stdout.write(`${info.id}\\t${info.name}\\n`);\n }\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'sync': {\n const [harnessId, direction] = args;\n if (!(harnessId && direction && ['push', 'pull'].includes(direction))) {\n process.stderr.write('Usage: revealui-harnesses sync <harnessId> <push|pull>\\n');\n process.exit(1);\n }\n try {\n const result = (await rpcCall('harness.syncConfig', { harnessId, direction })) as {\n success: boolean;\n message?: string;\n };\n process.stdout.write(result.success ? `✓ ${result.message}\\n` : `✗ ${result.message}\\n`);\n if (!result.success) process.exit(1);\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'coordinate': {\n if (args.includes('--init')) {\n const pathIdx = args.indexOf('--init');\n const projectRoot = args[pathIdx + 1] ?? DEFAULT_PROJECT;\n const coordinator = new HarnessCoordinator({ projectRoot, task: 'Coordinate harnesses' });\n await coordinator.start();\n const workboard = coordinator.getWorkboard();\n const conflicts = workboard.checkConflicts('', []);\n process.stdout.write(\n `✓ Session registered. Conflicts: ${conflicts.clean ? 'none' : conflicts.conflicts.length}\\n`,\n );\n await coordinator.stop();\n } else {\n // --print: dump current workboard to stdout\n const projectRoot = args[args.indexOf('--project') + 1] ?? DEFAULT_PROJECT;\n const workboardPath = join(projectRoot, '.claude', 'workboard.md');\n const manager = new WorkboardManager(workboardPath);\n const state = manager.read();\n process.stdout.write(`Sessions (${state.sessions.length}):\\n`);\n for (const s of state.sessions) {\n const stale = Date.now() - new Date(s.updated).getTime() > 4 * 60 * 60 * 1000;\n process.stdout.write(` ${s.id} [${s.env}] — ${s.task}${stale ? ' (STALE)' : ''}\\n`);\n if (s.files) process.stdout.write(` files: ${s.files}\\n`);\n }\n if (state.sessions.length === 0) process.stdout.write(' (no active sessions)\\n');\n }\n break;\n }\n\n case 'health': {\n try {\n const result = (await rpcCall('harness.health')) as {\n healthy: boolean;\n registeredHarnesses: Array<{ harnessId: string; available: boolean }>;\n workboard: { readable: boolean; sessionCount: number; staleSessionIds: string[] };\n diagnostics: string[];\n };\n process.stdout.write(`Health: ${result.healthy ? 'HEALTHY' : 'UNHEALTHY'}\\n`);\n process.stdout.write(`Harnesses:\\n`);\n for (const h of result.registeredHarnesses) {\n process.stdout.write(` ${h.harnessId}: ${h.available ? 'available' : 'unavailable'}\\n`);\n }\n process.stdout.write(\n `Workboard: ${result.workboard.readable ? 'readable' : 'unreadable'}, ${result.workboard.sessionCount} session(s)\\n`,\n );\n if (result.workboard.staleSessionIds.length > 0) {\n process.stdout.write(` Stale: ${result.workboard.staleSessionIds.join(', ')}\\n`);\n }\n if (result.diagnostics.length > 0) {\n process.stdout.write(`Diagnostics:\\n`);\n for (const d of result.diagnostics) {\n process.stdout.write(` ${d}\\n`);\n }\n }\n if (!result.healthy) process.exit(1);\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n default:\n process.stdout.write(`revealui-harnesses — AI harness coordination for RevealUI\n\nCommands:\n start [--project <path>] Start daemon (detects harnesses, registers session)\n status List available harnesses (requires daemon)\n list List harnesses in TSV format (requires daemon)\n sync <id> <push|pull> Sync harness config to/from SSD (requires daemon)\n health Run health check (requires daemon)\n coordinate [--project <path>] Print workboard state\n coordinate --init [<path>] Register + start daemon\n content <subcommand> Manage canonical content definitions\n\nContent Subcommands:\n content list List all canonical content with metadata\n content validate Validate all definitions against schemas\n content diff [--generator <id>] Show what would change vs current files\n content sync [--generator <id>] [--dry-run] Generate and write files\n content export --output <path> Export canonical + generated files to directory\n content pull [--generator <id>] [--tier oss|pro|all] Pull rules from rules repo\n`);\n break;\n }\n}\n\nmain().catch((err) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":["args"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * revealui-harnesses — CLI daemon and RPC client for AI harness coordination.\n *\n * Commands:\n * start [--project <path>] Detect harnesses, register in workboard, start RPC server\n * status List available harnesses via RPC\n * list List harnesses in TSV format\n * sync <harnessId> <push|pull> Sync harness config to/from SSD\n * coordinate [--print] Print current workboard state\n * coordinate --init <path> Register this session in the workboard and start daemon\n *\n * License: Pro tier required (isFeatureEnabled(\"harnesses\"))\n */\n\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { createConnection } from 'node:net';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport {\n buildManifest,\n diffContent,\n generateContent,\n listContent,\n listGenerators,\n validateManifest,\n} from './content/index.js';\nimport { HarnessCoordinator } from './coordinator.js';\nimport { checkHarnessesLicense } from './index.js';\nimport { WorkboardManager } from './workboard/workboard-manager.js';\n\nconst DEFAULT_SOCKET = join(homedir(), '.local', 'share', 'revealui', 'harness.sock');\nconst DEFAULT_PROJECT = process.cwd();\n\nconst [, , command, ...args] = process.argv;\n\nasync function rpcCall(method: string, params: unknown = {}): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const socket = createConnection(DEFAULT_SOCKET);\n let buffer = '';\n socket.on('connect', () => {\n const req = JSON.stringify({ jsonrpc: '2.0', id: 1, method, params });\n socket.write(`${req}\\n`);\n });\n socket.on('data', (chunk) => {\n buffer += chunk.toString();\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const resp = JSON.parse(line) as { result?: unknown; error?: { message: string } };\n socket.destroy();\n if (resp.error) reject(new Error(resp.error.message));\n else resolve(resp.result);\n } catch {\n reject(new Error(`Invalid JSON: ${line}`));\n }\n }\n });\n socket.on('error', reject);\n setTimeout(() => {\n socket.destroy();\n reject(new Error('RPC timeout'));\n }, 5000);\n });\n}\n\nasync function handleContentCommand(subcommand: string | undefined, args: string[]): Promise<void> {\n const manifest = buildManifest();\n const projectRoot = process.cwd();\n const ctx = { projectRoot };\n\n switch (subcommand) {\n case 'list': {\n const summary = listContent(manifest);\n process.stdout.write(`Canonical content:\\n`);\n process.stdout.write(` Rules: ${summary.rules}\\n`);\n process.stdout.write(` Commands: ${summary.commands}\\n`);\n process.stdout.write(` Agents: ${summary.agents}\\n`);\n process.stdout.write(` Skills: ${summary.skills}\\n`);\n process.stdout.write(` Preambles: ${summary.preambles}\\n`);\n process.stdout.write(` Total: ${summary.total}\\n`);\n process.stdout.write(`\\nRules:\\n`);\n for (const rule of manifest.rules) {\n process.stdout.write(` ${rule.id} (tier ${rule.preambleTier}) — ${rule.description}\\n`);\n }\n process.stdout.write(`\\nCommands:\\n`);\n for (const cmd of manifest.commands) {\n process.stdout.write(\n ` ${cmd.id}${cmd.disableModelInvocation ? ' [manual]' : ''} — ${cmd.description.slice(0, 80)}\\n`,\n );\n }\n process.stdout.write(`\\nAgents:\\n`);\n for (const agent of manifest.agents) {\n process.stdout.write(` ${agent.id} [${agent.isolation}] — ${agent.description}\\n`);\n }\n process.stdout.write(`\\nSkills:\\n`);\n for (const skill of manifest.skills) {\n process.stdout.write(\n ` ${skill.id}${skill.disableModelInvocation ? ' [manual]' : ''} — ${skill.description.slice(0, 80)}\\n`,\n );\n }\n process.stdout.write(`\\nGenerators: ${listGenerators().join(', ')}\\n`);\n break;\n }\n\n case 'validate': {\n const result = validateManifest(manifest);\n if (result.valid) {\n process.stdout.write(`✓ All definitions valid\\n`);\n } else {\n process.stderr.write(`✗ Validation errors:\\n`);\n for (const error of result.errors) {\n process.stderr.write(` - ${error}\\n`);\n }\n process.exit(1);\n }\n break;\n }\n\n case 'diff': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const entries = diffContent(generatorId, manifest, ctx, projectRoot);\n const added = entries.filter((e) => e.status === 'added');\n const modified = entries.filter((e) => e.status === 'modified');\n const unchanged = entries.filter((e) => e.status === 'unchanged');\n\n if (added.length === 0 && modified.length === 0) {\n process.stdout.write(`✓ No changes (${unchanged.length} files up to date)\\n`);\n } else {\n if (added.length > 0) {\n process.stdout.write(`Added (${added.length}):\\n`);\n for (const e of added) process.stdout.write(` + ${e.relativePath}\\n`);\n }\n if (modified.length > 0) {\n process.stdout.write(`Modified (${modified.length}):\\n`);\n for (const e of modified) process.stdout.write(` ~ ${e.relativePath}\\n`);\n }\n process.stdout.write(`Unchanged: ${unchanged.length}\\n`);\n }\n break;\n }\n\n case 'sync': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const dryRun = args.includes('--dry-run');\n const files = generateContent(generatorId, manifest, ctx);\n\n if (dryRun) {\n process.stdout.write(`Dry run — would write ${files.length} files:\\n`);\n for (const file of files) {\n process.stdout.write(` ${file.relativePath}\\n`);\n }\n } else {\n let written = 0;\n for (const file of files) {\n const absolutePath = join(projectRoot, file.relativePath);\n mkdirSync(dirname(absolutePath), { recursive: true });\n writeFileSync(absolutePath, file.content, 'utf-8');\n written++;\n }\n process.stdout.write(`✓ Wrote ${written} files via ${generatorId} generator\\n`);\n }\n break;\n }\n\n case 'export': {\n const outIdx = args.indexOf('--output');\n const rawOutput = outIdx >= 0 ? args[outIdx + 1] : undefined;\n if (!rawOutput) {\n process.stderr.write('Usage: content export --output <path>\\n');\n process.exit(1);\n }\n const outputDir: string = rawOutput;\n\n // 1. Write canonical definitions organized by type/tier\n const definitionTypes = [\n { key: 'rules' as const, items: manifest.rules },\n { key: 'commands' as const, items: manifest.commands },\n { key: 'agents' as const, items: manifest.agents },\n { key: 'skills' as const, items: manifest.skills },\n ];\n\n let canonicalCount = 0;\n for (const { key, items } of definitionTypes) {\n for (const item of items) {\n const tier = item.tier ?? 'oss';\n const filePath = join(outputDir, key, tier, `${item.id}.md`);\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, item.content, 'utf-8');\n canonicalCount++;\n }\n }\n\n // 2. Write pre-rendered generator output (compute once, reuse for manifest)\n const generatorIds = listGenerators();\n const generatorOutputs = new Map<string, { relativePath: string; content: string }[]>();\n let generatedCount = 0;\n for (const genId of generatorIds) {\n const files = generateContent(genId, manifest, ctx);\n generatorOutputs.set(genId, files);\n for (const file of files) {\n const filePath = join(outputDir, 'generators', genId, file.relativePath);\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, file.content, 'utf-8');\n generatedCount++;\n }\n }\n\n // 3. Write manifest.json with metadata\n interface ManifestEntry {\n id: string;\n type: string;\n name: string;\n description: string;\n tier: string;\n tags?: string[];\n canonicalPath: string;\n generatorPaths: Record<string, string[]>;\n }\n\n const entries: ManifestEntry[] = [];\n for (const { key, items } of definitionTypes) {\n for (const item of items) {\n const tier = item.tier ?? 'oss';\n const type = key.replace(/s$/, ''); // rules → rule\n const entry: ManifestEntry = {\n id: item.id,\n type,\n name: item.name,\n description: item.description,\n tier,\n canonicalPath: `${key}/${tier}/${item.id}.md`,\n generatorPaths: {},\n };\n if ('tags' in item && Array.isArray(item.tags) && item.tags.length > 0) {\n entry.tags = item.tags;\n }\n // Map each generator's output paths for this definition\n for (const genId of generatorIds) {\n const genFiles = generatorOutputs.get(genId) ?? [];\n const matching = genFiles\n .filter((f) => f.relativePath.includes(item.id))\n .map((f) => f.relativePath);\n if (matching.length > 0) {\n entry.generatorPaths[genId] = matching;\n }\n }\n entries.push(entry);\n }\n }\n\n const exportManifest = {\n version: 1,\n generatedAt: new Date().toISOString(),\n generators: generatorIds,\n definitions: entries,\n };\n\n const manifestPath = join(outputDir, 'manifest.json');\n mkdirSync(dirname(manifestPath), { recursive: true });\n writeFileSync(manifestPath, `${JSON.stringify(exportManifest, null, 2)}\\n`, 'utf-8');\n\n process.stdout.write(`✓ Exported to ${outputDir}\\n`);\n process.stdout.write(` Canonical definitions: ${canonicalCount}\\n`);\n process.stdout.write(\n ` Generator output: ${generatedCount} files (${generatorIds.join(', ')})\\n`,\n );\n process.stdout.write(` Manifest: manifest.json\\n`);\n break;\n }\n\n case 'pull': {\n const genIdx = args.indexOf('--generator');\n const generatorId = genIdx >= 0 ? (args[genIdx + 1] ?? 'claude-code') : 'claude-code';\n const tierIdx = args.indexOf('--tier');\n const tierFilter = tierIdx >= 0 ? (args[tierIdx + 1] ?? 'oss') : 'oss';\n\n if (!['oss', 'pro', 'all'].includes(tierFilter)) {\n process.stderr.write(`Invalid tier: ${tierFilter}. Use: oss, pro, all\\n`);\n process.exit(1);\n }\n\n // Pro tier requires a valid license\n const needsLicense = tierFilter === 'pro' || tierFilter === 'all';\n if (needsLicense) {\n const licensed = await checkHarnessesLicense();\n if (!licensed) {\n process.stderr.write(\n 'Pro rules require a valid license key. Visit https://revealui.com/pricing\\n',\n );\n process.exit(1);\n }\n }\n\n const baseUrl =\n args[args.indexOf('--url') + 1] ??\n process.env.REVEALUI_RULES_URL ??\n 'https://raw.githubusercontent.com/RevealUIStudio/editor-configs/main/harnesses';\n\n // Fetch manifest from remote\n process.stdout.write(`Fetching manifest from ${baseUrl}/manifest.json...\\n`);\n const manifestRes = await fetch(`${baseUrl}/manifest.json`);\n if (!manifestRes.ok) {\n process.stderr.write(\n `Failed to fetch manifest: ${manifestRes.status} ${manifestRes.statusText}\\n`,\n );\n process.exit(1);\n }\n\n const remoteManifest = (await manifestRes.json()) as {\n definitions: Array<{\n id: string;\n type: string;\n name: string;\n tier: string;\n generatorPaths: Record<string, string[]>;\n }>;\n };\n\n // Filter definitions by tier\n const filtered = remoteManifest.definitions.filter((def) => {\n if (tierFilter === 'all') return true;\n return def.tier === tierFilter;\n });\n\n process.stdout.write(`Found ${filtered.length} definitions (tier: ${tierFilter})\\n`);\n\n // Download pre-rendered files for the selected generator\n let written = 0;\n let errors = 0;\n for (const def of filtered) {\n const paths = def.generatorPaths[generatorId] ?? [];\n for (const relPath of paths) {\n const fileUrl = `${baseUrl}/generators/${generatorId}/${relPath}`;\n try {\n const fileRes = await fetch(fileUrl);\n if (!fileRes.ok) {\n process.stderr.write(` ✗ ${relPath} (${fileRes.status})\\n`);\n errors++;\n continue;\n }\n const content = await fileRes.text();\n const absolutePath = join(projectRoot, relPath);\n mkdirSync(dirname(absolutePath), { recursive: true });\n writeFileSync(absolutePath, content, 'utf-8');\n written++;\n } catch (err) {\n process.stderr.write(\n ` ✗ ${relPath} (${err instanceof Error ? err.message : 'fetch error'})\\n`,\n );\n errors++;\n }\n }\n }\n\n process.stdout.write(`✓ Pulled ${written} files via ${generatorId} generator\\n`);\n if (errors > 0) {\n process.stderr.write(` ${errors} file(s) failed to download\\n`);\n }\n break;\n }\n\n default:\n process.stderr.write(`Unknown content subcommand: ${subcommand ?? '(none)'}\\n`);\n process.stderr.write(`Available: list, validate, diff, sync, export, pull\\n`);\n process.exit(1);\n }\n}\n\nasync function main() {\n // Content commands are developer tooling — no license required\n if (command === 'content') {\n const [subcommand] = args;\n const contentArgs = args.slice(1);\n await handleContentCommand(subcommand, contentArgs);\n return;\n }\n\n if (!(await checkHarnessesLicense())) {\n process.stderr.write(\n '⚠ @revealui/harnesses requires a Pro license. Visit https://revealui.com/pricing\\n',\n );\n process.exit(2);\n }\n\n switch (command) {\n case 'start': {\n const projectIdx = args.indexOf('--project');\n const projectRoot =\n projectIdx >= 0 ? (args[projectIdx + 1] ?? DEFAULT_PROJECT) : DEFAULT_PROJECT;\n\n const coordinator = new HarnessCoordinator({\n projectRoot,\n task: 'Harness coordination active',\n });\n\n await coordinator.start();\n const ids = await coordinator.getRegistry().listAvailable();\n process.stdout.write(`✓ Detected harnesses: ${ids.length > 0 ? ids.join(', ') : 'none'}\\n`);\n process.stdout.write(`✓ RPC server listening on ${DEFAULT_SOCKET}\\n`);\n process.stdout.write(`✓ Session registered in workboard\\n`);\n\n const shutdown = async () => {\n await coordinator.stop();\n process.exit(0);\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n break;\n }\n\n case 'status': {\n try {\n const infos = (await rpcCall('harness.list')) as Array<{\n id: string;\n name: string;\n version?: string;\n }>;\n if (infos.length === 0) {\n process.stdout.write('No harnesses available\\n');\n } else {\n for (const info of infos) {\n process.stdout.write(\n `${info.id}\\t${info.name}${info.version ? `\\t${info.version}` : ''}\\n`,\n );\n }\n }\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'list': {\n try {\n const infos = (await rpcCall('harness.list')) as Array<{ id: string; name: string }>;\n for (const info of infos) {\n process.stdout.write(`${info.id}\\t${info.name}\\n`);\n }\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'sync': {\n const [harnessId, direction] = args;\n if (!(harnessId && direction && ['push', 'pull'].includes(direction))) {\n process.stderr.write('Usage: revealui-harnesses sync <harnessId> <push|pull>\\n');\n process.exit(1);\n }\n try {\n const result = (await rpcCall('harness.syncConfig', { harnessId, direction })) as {\n success: boolean;\n message?: string;\n };\n process.stdout.write(result.success ? `✓ ${result.message}\\n` : `✗ ${result.message}\\n`);\n if (!result.success) process.exit(1);\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'coordinate': {\n if (args.includes('--init')) {\n const pathIdx = args.indexOf('--init');\n const projectRoot = args[pathIdx + 1] ?? DEFAULT_PROJECT;\n const coordinator = new HarnessCoordinator({ projectRoot, task: 'Coordinate harnesses' });\n await coordinator.start();\n const workboard = coordinator.getWorkboard();\n const conflicts = workboard.checkConflicts('', []);\n process.stdout.write(\n `✓ Session registered. Conflicts: ${conflicts.clean ? 'none' : conflicts.conflicts.length}\\n`,\n );\n await coordinator.stop();\n } else {\n // --print: dump current workboard to stdout\n const projectRoot = args[args.indexOf('--project') + 1] ?? DEFAULT_PROJECT;\n const workboardPath = join(projectRoot, '.claude', 'workboard.md');\n const manager = new WorkboardManager(workboardPath);\n const state = manager.read();\n process.stdout.write(`Agents (${state.agents.length}):\\n`);\n for (const a of state.agents) {\n const stale = Date.now() - new Date(a.updated).getTime() > 4 * 60 * 60 * 1000;\n process.stdout.write(` ${a.id} [${a.env}] — ${a.task}${stale ? ' (STALE)' : ''}\\n`);\n if (a.files) process.stdout.write(` files: ${a.files}\\n`);\n }\n if (state.agents.length === 0) process.stdout.write(' (no active agents)\\n');\n }\n break;\n }\n\n case 'health': {\n try {\n const result = (await rpcCall('harness.health')) as {\n healthy: boolean;\n registeredHarnesses: Array<{ harnessId: string; available: boolean }>;\n workboard: { readable: boolean; sessionCount: number; staleSessionIds: string[] };\n diagnostics: string[];\n };\n process.stdout.write(`Health: ${result.healthy ? 'HEALTHY' : 'UNHEALTHY'}\\n`);\n process.stdout.write(`Harnesses:\\n`);\n for (const h of result.registeredHarnesses) {\n process.stdout.write(` ${h.harnessId}: ${h.available ? 'available' : 'unavailable'}\\n`);\n }\n process.stdout.write(\n `Workboard: ${result.workboard.readable ? 'readable' : 'unreadable'}, ${result.workboard.sessionCount} session(s)\\n`,\n );\n if (result.workboard.staleSessionIds.length > 0) {\n process.stdout.write(` Stale: ${result.workboard.staleSessionIds.join(', ')}\\n`);\n }\n if (result.diagnostics.length > 0) {\n process.stdout.write(`Diagnostics:\\n`);\n for (const d of result.diagnostics) {\n process.stdout.write(` ${d}\\n`);\n }\n }\n if (!result.healthy) process.exit(1);\n } catch (err) {\n process.stderr.write(`RPC error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n break;\n }\n\n default:\n process.stdout.write(`revealui-harnesses — AI harness coordination for RevealUI\n\nCommands:\n start [--project <path>] Start daemon (detects harnesses, registers session)\n status List available harnesses (requires daemon)\n list List harnesses in TSV format (requires daemon)\n sync <id> <push|pull> Sync harness config to/from SSD (requires daemon)\n health Run health check (requires daemon)\n coordinate [--project <path>] Print workboard state\n coordinate --init [<path>] Register + start daemon\n content <subcommand> Manage canonical content definitions\n\nContent Subcommands:\n content list List all canonical content with metadata\n content validate Validate all definitions against schemas\n content diff [--generator <id>] Show what would change vs current files\n content sync [--generator <id>] [--dry-run] Generate and write files\n content export --output <path> Export canonical + generated files to directory\n content pull [--generator <id>] [--tier oss|pro|all] Pull rules from rules repo\n`);\n break;\n }\n}\n\nmain().catch((err) => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgBA,SAAS,WAAW,qBAAqB;AACzC,SAAS,wBAAwB;AACjC,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAa9B,IAAM,iBAAiB,KAAK,QAAQ,GAAG,UAAU,SAAS,YAAY,cAAc;AACpF,IAAM,kBAAkB,QAAQ,IAAI;AAEpC,IAAM,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,IAAI,QAAQ;AAEvC,eAAe,QAAQ,QAAgB,SAAkB,CAAC,GAAqB;AAC7E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,iBAAiB,cAAc;AAC9C,QAAI,SAAS;AACb,WAAO,GAAG,WAAW,MAAM;AACzB,YAAM,MAAM,KAAK,UAAU,EAAE,SAAS,OAAO,IAAI,GAAG,QAAQ,OAAO,CAAC;AACpE,aAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAAA,IACzB,CAAC;AACD,WAAO,GAAG,QAAQ,CAAC,UAAU;AAC3B,gBAAU,MAAM,SAAS;AACzB,YAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,eAAS,MAAM,IAAI,KAAK;AACxB,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,KAAK,KAAK,EAAG;AAClB,YAAI;AACF,gBAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,iBAAO,QAAQ;AACf,cAAI,KAAK,MAAO,QAAO,IAAI,MAAM,KAAK,MAAM,OAAO,CAAC;AAAA,cAC/C,SAAQ,KAAK,MAAM;AAAA,QAC1B,QAAQ;AACN,iBAAO,IAAI,MAAM,iBAAiB,IAAI,EAAE,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF,CAAC;AACD,WAAO,GAAG,SAAS,MAAM;AACzB,eAAW,MAAM;AACf,aAAO,QAAQ;AACf,aAAO,IAAI,MAAM,aAAa,CAAC;AAAA,IACjC,GAAG,GAAI;AAAA,EACT,CAAC;AACH;AAEA,eAAe,qBAAqB,YAAgCA,OAA+B;AACjG,QAAM,WAAW,cAAc;AAC/B,QAAM,cAAc,QAAQ,IAAI;AAChC,QAAM,MAAM,EAAE,YAAY;AAE1B,UAAQ,YAAY;AAAA,IAClB,KAAK,QAAQ;AACX,YAAM,UAAU,YAAY,QAAQ;AACpC,cAAQ,OAAO,MAAM;AAAA,CAAsB;AAC3C,cAAQ,OAAO,MAAM,eAAe,QAAQ,KAAK;AAAA,CAAI;AACrD,cAAQ,OAAO,MAAM,eAAe,QAAQ,QAAQ;AAAA,CAAI;AACxD,cAAQ,OAAO,MAAM,eAAe,QAAQ,MAAM;AAAA,CAAI;AACtD,cAAQ,OAAO,MAAM,eAAe,QAAQ,MAAM;AAAA,CAAI;AACtD,cAAQ,OAAO,MAAM,gBAAgB,QAAQ,SAAS;AAAA,CAAI;AAC1D,cAAQ,OAAO,MAAM,eAAe,QAAQ,KAAK;AAAA,CAAI;AACrD,cAAQ,OAAO,MAAM;AAAA;AAAA,CAAY;AACjC,iBAAW,QAAQ,SAAS,OAAO;AACjC,gBAAQ,OAAO,MAAM,KAAK,KAAK,EAAE,UAAU,KAAK,YAAY,YAAO,KAAK,WAAW;AAAA,CAAI;AAAA,MACzF;AACA,cAAQ,OAAO,MAAM;AAAA;AAAA,CAAe;AACpC,iBAAW,OAAO,SAAS,UAAU;AACnC,gBAAQ,OAAO;AAAA,UACb,KAAK,IAAI,EAAE,GAAG,IAAI,yBAAyB,cAAc,EAAE,WAAM,IAAI,YAAY,MAAM,GAAG,EAAE,CAAC;AAAA;AAAA,QAC/F;AAAA,MACF;AACA,cAAQ,OAAO,MAAM;AAAA;AAAA,CAAa;AAClC,iBAAW,SAAS,SAAS,QAAQ;AACnC,gBAAQ,OAAO,MAAM,KAAK,MAAM,EAAE,KAAK,MAAM,SAAS,YAAO,MAAM,WAAW;AAAA,CAAI;AAAA,MACpF;AACA,cAAQ,OAAO,MAAM;AAAA;AAAA,CAAa;AAClC,iBAAW,SAAS,SAAS,QAAQ;AACnC,gBAAQ,OAAO;AAAA,UACb,KAAK,MAAM,EAAE,GAAG,MAAM,yBAAyB,cAAc,EAAE,WAAM,MAAM,YAAY,MAAM,GAAG,EAAE,CAAC;AAAA;AAAA,QACrG;AAAA,MACF;AACA,cAAQ,OAAO,MAAM;AAAA,cAAiB,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,CAAI;AACrE;AAAA,IACF;AAAA,IAEA,KAAK,YAAY;AACf,YAAM,SAAS,iBAAiB,QAAQ;AACxC,UAAI,OAAO,OAAO;AAChB,gBAAQ,OAAO,MAAM;AAAA,CAA2B;AAAA,MAClD,OAAO;AACL,gBAAQ,OAAO,MAAM;AAAA,CAAwB;AAC7C,mBAAW,SAAS,OAAO,QAAQ;AACjC,kBAAQ,OAAO,MAAM,OAAO,KAAK;AAAA,CAAI;AAAA,QACvC;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAASA,MAAK,QAAQ,aAAa;AACzC,YAAM,cAAc,UAAU,IAAKA,MAAK,SAAS,CAAC,KAAK,gBAAiB;AACxE,YAAM,UAAU,YAAY,aAAa,UAAU,KAAK,WAAW;AACnE,YAAM,QAAQ,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,OAAO;AACxD,YAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,UAAU;AAC9D,YAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW;AAEhE,UAAI,MAAM,WAAW,KAAK,SAAS,WAAW,GAAG;AAC/C,gBAAQ,OAAO,MAAM,sBAAiB,UAAU,MAAM;AAAA,CAAsB;AAAA,MAC9E,OAAO;AACL,YAAI,MAAM,SAAS,GAAG;AACpB,kBAAQ,OAAO,MAAM,UAAU,MAAM,MAAM;AAAA,CAAM;AACjD,qBAAW,KAAK,MAAO,SAAQ,OAAO,MAAM,OAAO,EAAE,YAAY;AAAA,CAAI;AAAA,QACvE;AACA,YAAI,SAAS,SAAS,GAAG;AACvB,kBAAQ,OAAO,MAAM,aAAa,SAAS,MAAM;AAAA,CAAM;AACvD,qBAAW,KAAK,SAAU,SAAQ,OAAO,MAAM,OAAO,EAAE,YAAY;AAAA,CAAI;AAAA,QAC1E;AACA,gBAAQ,OAAO,MAAM,cAAc,UAAU,MAAM;AAAA,CAAI;AAAA,MACzD;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAASA,MAAK,QAAQ,aAAa;AACzC,YAAM,cAAc,UAAU,IAAKA,MAAK,SAAS,CAAC,KAAK,gBAAiB;AACxE,YAAM,SAASA,MAAK,SAAS,WAAW;AACxC,YAAM,QAAQ,gBAAgB,aAAa,UAAU,GAAG;AAExD,UAAI,QAAQ;AACV,gBAAQ,OAAO,MAAM,8BAAyB,MAAM,MAAM;AAAA,CAAW;AACrE,mBAAW,QAAQ,OAAO;AACxB,kBAAQ,OAAO,MAAM,KAAK,KAAK,YAAY;AAAA,CAAI;AAAA,QACjD;AAAA,MACF,OAAO;AACL,YAAI,UAAU;AACd,mBAAW,QAAQ,OAAO;AACxB,gBAAM,eAAe,KAAK,aAAa,KAAK,YAAY;AACxD,oBAAU,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,wBAAc,cAAc,KAAK,SAAS,OAAO;AACjD;AAAA,QACF;AACA,gBAAQ,OAAO,MAAM,gBAAW,OAAO,cAAc,WAAW;AAAA,CAAc;AAAA,MAChF;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,SAASA,MAAK,QAAQ,UAAU;AACtC,YAAM,YAAY,UAAU,IAAIA,MAAK,SAAS,CAAC,IAAI;AACnD,UAAI,CAAC,WAAW;AACd,gBAAQ,OAAO,MAAM,yCAAyC;AAC9D,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,YAAM,YAAoB;AAG1B,YAAM,kBAAkB;AAAA,QACtB,EAAE,KAAK,SAAkB,OAAO,SAAS,MAAM;AAAA,QAC/C,EAAE,KAAK,YAAqB,OAAO,SAAS,SAAS;AAAA,QACrD,EAAE,KAAK,UAAmB,OAAO,SAAS,OAAO;AAAA,QACjD,EAAE,KAAK,UAAmB,OAAO,SAAS,OAAO;AAAA,MACnD;AAEA,UAAI,iBAAiB;AACrB,iBAAW,EAAE,KAAK,MAAM,KAAK,iBAAiB;AAC5C,mBAAW,QAAQ,OAAO;AACxB,gBAAM,OAAO,KAAK,QAAQ;AAC1B,gBAAM,WAAW,KAAK,WAAW,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AAC3D,oBAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,wBAAc,UAAU,KAAK,SAAS,OAAO;AAC7C;AAAA,QACF;AAAA,MACF;AAGA,YAAM,eAAe,eAAe;AACpC,YAAM,mBAAmB,oBAAI,IAAyD;AACtF,UAAI,iBAAiB;AACrB,iBAAW,SAAS,cAAc;AAChC,cAAM,QAAQ,gBAAgB,OAAO,UAAU,GAAG;AAClD,yBAAiB,IAAI,OAAO,KAAK;AACjC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,WAAW,KAAK,WAAW,cAAc,OAAO,KAAK,YAAY;AACvE,oBAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,wBAAc,UAAU,KAAK,SAAS,OAAO;AAC7C;AAAA,QACF;AAAA,MACF;AAcA,YAAM,UAA2B,CAAC;AAClC,iBAAW,EAAE,KAAK,MAAM,KAAK,iBAAiB;AAC5C,mBAAW,QAAQ,OAAO;AACxB,gBAAM,OAAO,KAAK,QAAQ;AAC1B,gBAAM,OAAO,IAAI,QAAQ,MAAM,EAAE;AACjC,gBAAM,QAAuB;AAAA,YAC3B,IAAI,KAAK;AAAA,YACT;AAAA,YACA,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB;AAAA,YACA,eAAe,GAAG,GAAG,IAAI,IAAI,IAAI,KAAK,EAAE;AAAA,YACxC,gBAAgB,CAAC;AAAA,UACnB;AACA,cAAI,UAAU,QAAQ,MAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,GAAG;AACtE,kBAAM,OAAO,KAAK;AAAA,UACpB;AAEA,qBAAW,SAAS,cAAc;AAChC,kBAAM,WAAW,iBAAiB,IAAI,KAAK,KAAK,CAAC;AACjD,kBAAM,WAAW,SACd,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,KAAK,EAAE,CAAC,EAC9C,IAAI,CAAC,MAAM,EAAE,YAAY;AAC5B,gBAAI,SAAS,SAAS,GAAG;AACvB,oBAAM,eAAe,KAAK,IAAI;AAAA,YAChC;AAAA,UACF;AACA,kBAAQ,KAAK,KAAK;AAAA,QACpB;AAAA,MACF;AAEA,YAAM,iBAAiB;AAAA,QACrB,SAAS;AAAA,QACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,YAAY;AAAA,QACZ,aAAa;AAAA,MACf;AAEA,YAAM,eAAe,KAAK,WAAW,eAAe;AACpD,gBAAU,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,oBAAc,cAAc,GAAG,KAAK,UAAU,gBAAgB,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAEnF,cAAQ,OAAO,MAAM,sBAAiB,SAAS;AAAA,CAAI;AACnD,cAAQ,OAAO,MAAM,4BAA4B,cAAc;AAAA,CAAI;AACnE,cAAQ,OAAO;AAAA,QACb,uBAAuB,cAAc,WAAW,aAAa,KAAK,IAAI,CAAC;AAAA;AAAA,MACzE;AACA,cAAQ,OAAO,MAAM;AAAA,CAA6B;AAClD;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,SAASA,MAAK,QAAQ,aAAa;AACzC,YAAM,cAAc,UAAU,IAAKA,MAAK,SAAS,CAAC,KAAK,gBAAiB;AACxE,YAAM,UAAUA,MAAK,QAAQ,QAAQ;AACrC,YAAM,aAAa,WAAW,IAAKA,MAAK,UAAU,CAAC,KAAK,QAAS;AAEjE,UAAI,CAAC,CAAC,OAAO,OAAO,KAAK,EAAE,SAAS,UAAU,GAAG;AAC/C,gBAAQ,OAAO,MAAM,iBAAiB,UAAU;AAAA,CAAwB;AACxE,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAGA,YAAM,eAAe,eAAe,SAAS,eAAe;AAC5D,UAAI,cAAc;AAChB,cAAM,WAAW,MAAM,sBAAsB;AAC7C,YAAI,CAAC,UAAU;AACb,kBAAQ,OAAO;AAAA,YACb;AAAA,UACF;AACA,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,YAAM,UACJA,MAAKA,MAAK,QAAQ,OAAO,IAAI,CAAC,KAC9B,QAAQ,IAAI,sBACZ;AAGF,cAAQ,OAAO,MAAM,0BAA0B,OAAO;AAAA,CAAqB;AAC3E,YAAM,cAAc,MAAM,MAAM,GAAG,OAAO,gBAAgB;AAC1D,UAAI,CAAC,YAAY,IAAI;AACnB,gBAAQ,OAAO;AAAA,UACb,6BAA6B,YAAY,MAAM,IAAI,YAAY,UAAU;AAAA;AAAA,QAC3E;AACA,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,iBAAkB,MAAM,YAAY,KAAK;AAW/C,YAAM,WAAW,eAAe,YAAY,OAAO,CAAC,QAAQ;AAC1D,YAAI,eAAe,MAAO,QAAO;AACjC,eAAO,IAAI,SAAS;AAAA,MACtB,CAAC;AAED,cAAQ,OAAO,MAAM,SAAS,SAAS,MAAM,uBAAuB,UAAU;AAAA,CAAK;AAGnF,UAAI,UAAU;AACd,UAAI,SAAS;AACb,iBAAW,OAAO,UAAU;AAC1B,cAAM,QAAQ,IAAI,eAAe,WAAW,KAAK,CAAC;AAClD,mBAAW,WAAW,OAAO;AAC3B,gBAAM,UAAU,GAAG,OAAO,eAAe,WAAW,IAAI,OAAO;AAC/D,cAAI;AACF,kBAAM,UAAU,MAAM,MAAM,OAAO;AACnC,gBAAI,CAAC,QAAQ,IAAI;AACf,sBAAQ,OAAO,MAAM,YAAO,OAAO,KAAK,QAAQ,MAAM;AAAA,CAAK;AAC3D;AACA;AAAA,YACF;AACA,kBAAM,UAAU,MAAM,QAAQ,KAAK;AACnC,kBAAM,eAAe,KAAK,aAAa,OAAO;AAC9C,sBAAU,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,0BAAc,cAAc,SAAS,OAAO;AAC5C;AAAA,UACF,SAAS,KAAK;AACZ,oBAAQ,OAAO;AAAA,cACb,YAAO,OAAO,KAAK,eAAe,QAAQ,IAAI,UAAU,aAAa;AAAA;AAAA,YACvE;AACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,cAAQ,OAAO,MAAM,iBAAY,OAAO,cAAc,WAAW;AAAA,CAAc;AAC/E,UAAI,SAAS,GAAG;AACd,gBAAQ,OAAO,MAAM,KAAK,MAAM;AAAA,CAA+B;AAAA,MACjE;AACA;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,OAAO,MAAM,+BAA+B,cAAc,QAAQ;AAAA,CAAI;AAC9E,cAAQ,OAAO,MAAM;AAAA,CAAuD;AAC5E,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,eAAe,OAAO;AAEpB,MAAI,YAAY,WAAW;AACzB,UAAM,CAAC,UAAU,IAAI;AACrB,UAAM,cAAc,KAAK,MAAM,CAAC;AAChC,UAAM,qBAAqB,YAAY,WAAW;AAClD;AAAA,EACF;AAEA,MAAI,CAAE,MAAM,sBAAsB,GAAI;AACpC,YAAQ,OAAO;AAAA,MACb;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,SAAS;AAAA,IACf,KAAK,SAAS;AACZ,YAAM,aAAa,KAAK,QAAQ,WAAW;AAC3C,YAAM,cACJ,cAAc,IAAK,KAAK,aAAa,CAAC,KAAK,kBAAmB;AAEhE,YAAM,cAAc,IAAI,mBAAmB;AAAA,QACzC;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAED,YAAM,YAAY,MAAM;AACxB,YAAM,MAAM,MAAM,YAAY,YAAY,EAAE,cAAc;AAC1D,cAAQ,OAAO,MAAM,8BAAyB,IAAI,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM;AAAA,CAAI;AAC1F,cAAQ,OAAO,MAAM,kCAA6B,cAAc;AAAA,CAAI;AACpE,cAAQ,OAAO,MAAM;AAAA,CAAqC;AAE1D,YAAM,WAAW,YAAY;AAC3B,cAAM,YAAY,KAAK;AACvB,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,GAAG,UAAU,QAAQ;AAC7B,cAAQ,GAAG,WAAW,QAAQ;AAC9B;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,UAAI;AACF,cAAM,QAAS,MAAM,QAAQ,cAAc;AAK3C,YAAI,MAAM,WAAW,GAAG;AACtB,kBAAQ,OAAO,MAAM,0BAA0B;AAAA,QACjD,OAAO;AACL,qBAAW,QAAQ,OAAO;AACxB,oBAAQ,OAAO;AAAA,cACb,GAAG,KAAK,EAAE,IAAK,KAAK,IAAI,GAAG,KAAK,UAAU,IAAK,KAAK,OAAO,KAAK,EAAE;AAAA;AAAA,YACpE;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,OAAO,MAAM,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACvF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,UAAI;AACF,cAAM,QAAS,MAAM,QAAQ,cAAc;AAC3C,mBAAW,QAAQ,OAAO;AACxB,kBAAQ,OAAO,MAAM,GAAG,KAAK,EAAE,IAAK,KAAK,IAAI;AAAA,CAAI;AAAA,QACnD;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,OAAO,MAAM,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACvF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,CAAC,WAAW,SAAS,IAAI;AAC/B,UAAI,EAAE,aAAa,aAAa,CAAC,QAAQ,MAAM,EAAE,SAAS,SAAS,IAAI;AACrE,gBAAQ,OAAO,MAAM,0DAA0D;AAC/E,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,UAAI;AACF,cAAM,SAAU,MAAM,QAAQ,sBAAsB,EAAE,WAAW,UAAU,CAAC;AAI5E,gBAAQ,OAAO,MAAM,OAAO,UAAU,UAAK,OAAO,OAAO;AAAA,IAAO,UAAK,OAAO,OAAO;AAAA,CAAI;AACvF,YAAI,CAAC,OAAO,QAAS,SAAQ,KAAK,CAAC;AAAA,MACrC,SAAS,KAAK;AACZ,gBAAQ,OAAO,MAAM,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACvF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA,KAAK,cAAc;AACjB,UAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,cAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,cAAM,cAAc,KAAK,UAAU,CAAC,KAAK;AACzC,cAAM,cAAc,IAAI,mBAAmB,EAAE,aAAa,MAAM,uBAAuB,CAAC;AACxF,cAAM,YAAY,MAAM;AACxB,cAAM,YAAY,YAAY,aAAa;AAC3C,cAAM,YAAY,UAAU,eAAe,IAAI,CAAC,CAAC;AACjD,gBAAQ,OAAO;AAAA,UACb,yCAAoC,UAAU,QAAQ,SAAS,UAAU,UAAU,MAAM;AAAA;AAAA,QAC3F;AACA,cAAM,YAAY,KAAK;AAAA,MACzB,OAAO;AAEL,cAAM,cAAc,KAAK,KAAK,QAAQ,WAAW,IAAI,CAAC,KAAK;AAC3D,cAAM,gBAAgB,KAAK,aAAa,WAAW,cAAc;AACjE,cAAM,UAAU,IAAI,iBAAiB,aAAa;AAClD,cAAM,QAAQ,QAAQ,KAAK;AAC3B,gBAAQ,OAAO,MAAM,WAAW,MAAM,OAAO,MAAM;AAAA,CAAM;AACzD,mBAAW,KAAK,MAAM,QAAQ;AAC5B,gBAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,KAAK,EAAE,OAAO,EAAE,QAAQ,IAAI,IAAI,KAAK,KAAK;AACzE,kBAAQ,OAAO,MAAM,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,YAAO,EAAE,IAAI,GAAG,QAAQ,aAAa,EAAE;AAAA,CAAI;AACnF,cAAI,EAAE,MAAO,SAAQ,OAAO,MAAM,cAAc,EAAE,KAAK;AAAA,CAAI;AAAA,QAC7D;AACA,YAAI,MAAM,OAAO,WAAW,EAAG,SAAQ,OAAO,MAAM,wBAAwB;AAAA,MAC9E;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,UAAI;AACF,cAAM,SAAU,MAAM,QAAQ,gBAAgB;AAM9C,gBAAQ,OAAO,MAAM,WAAW,OAAO,UAAU,YAAY,WAAW;AAAA,CAAI;AAC5E,gBAAQ,OAAO,MAAM;AAAA,CAAc;AACnC,mBAAW,KAAK,OAAO,qBAAqB;AAC1C,kBAAQ,OAAO,MAAM,KAAK,EAAE,SAAS,KAAK,EAAE,YAAY,cAAc,aAAa;AAAA,CAAI;AAAA,QACzF;AACA,gBAAQ,OAAO;AAAA,UACb,cAAc,OAAO,UAAU,WAAW,aAAa,YAAY,KAAK,OAAO,UAAU,YAAY;AAAA;AAAA,QACvG;AACA,YAAI,OAAO,UAAU,gBAAgB,SAAS,GAAG;AAC/C,kBAAQ,OAAO,MAAM,YAAY,OAAO,UAAU,gBAAgB,KAAK,IAAI,CAAC;AAAA,CAAI;AAAA,QAClF;AACA,YAAI,OAAO,YAAY,SAAS,GAAG;AACjC,kBAAQ,OAAO,MAAM;AAAA,CAAgB;AACrC,qBAAW,KAAK,OAAO,aAAa;AAClC,oBAAQ,OAAO,MAAM,KAAK,CAAC;AAAA,CAAI;AAAA,UACjC;AAAA,QACF;AACA,YAAI,CAAC,OAAO,QAAS,SAAQ,KAAK,CAAC;AAAA,MACrC,SAAS,KAAK;AACZ,gBAAQ,OAAO,MAAM,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACvF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,OAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAmB1B;AACK;AAAA,EACJ;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,OAAO,MAAM,GAAG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AAC5E,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["args"]}
|
package/dist/content/index.d.ts
CHANGED
|
@@ -14,8 +14,8 @@ declare const AgentSchema: z.ZodObject<{
|
|
|
14
14
|
name: z.ZodString;
|
|
15
15
|
description: z.ZodString;
|
|
16
16
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
17
|
-
oss: "oss";
|
|
18
17
|
pro: "pro";
|
|
18
|
+
oss: "oss";
|
|
19
19
|
}>>;
|
|
20
20
|
isolation: z.ZodDefault<z.ZodEnum<{
|
|
21
21
|
worktree: "worktree";
|
|
@@ -31,8 +31,8 @@ declare const CommandSchema: z.ZodObject<{
|
|
|
31
31
|
name: z.ZodString;
|
|
32
32
|
description: z.ZodString;
|
|
33
33
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
34
|
-
oss: "oss";
|
|
35
34
|
pro: "pro";
|
|
35
|
+
oss: "oss";
|
|
36
36
|
}>>;
|
|
37
37
|
disableModelInvocation: z.ZodDefault<z.ZodBoolean>;
|
|
38
38
|
argumentHint: z.ZodOptional<z.ZodString>;
|
|
@@ -53,8 +53,8 @@ declare const ManifestSchema: z.ZodObject<{
|
|
|
53
53
|
}>;
|
|
54
54
|
preambleTier: z.ZodDefault<z.ZodNumber>;
|
|
55
55
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
56
|
-
oss: "oss";
|
|
57
56
|
pro: "pro";
|
|
57
|
+
oss: "oss";
|
|
58
58
|
}>>;
|
|
59
59
|
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
60
60
|
content: z.ZodString;
|
|
@@ -64,8 +64,8 @@ declare const ManifestSchema: z.ZodObject<{
|
|
|
64
64
|
name: z.ZodString;
|
|
65
65
|
description: z.ZodString;
|
|
66
66
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
67
|
-
oss: "oss";
|
|
68
67
|
pro: "pro";
|
|
68
|
+
oss: "oss";
|
|
69
69
|
}>>;
|
|
70
70
|
disableModelInvocation: z.ZodDefault<z.ZodBoolean>;
|
|
71
71
|
argumentHint: z.ZodOptional<z.ZodString>;
|
|
@@ -76,8 +76,8 @@ declare const ManifestSchema: z.ZodObject<{
|
|
|
76
76
|
name: z.ZodString;
|
|
77
77
|
description: z.ZodString;
|
|
78
78
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
79
|
-
oss: "oss";
|
|
80
79
|
pro: "pro";
|
|
80
|
+
oss: "oss";
|
|
81
81
|
}>>;
|
|
82
82
|
isolation: z.ZodDefault<z.ZodEnum<{
|
|
83
83
|
worktree: "worktree";
|
|
@@ -91,8 +91,8 @@ declare const ManifestSchema: z.ZodObject<{
|
|
|
91
91
|
name: z.ZodString;
|
|
92
92
|
description: z.ZodString;
|
|
93
93
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
94
|
-
oss: "oss";
|
|
95
94
|
pro: "pro";
|
|
95
|
+
oss: "oss";
|
|
96
96
|
}>>;
|
|
97
97
|
disableModelInvocation: z.ZodDefault<z.ZodBoolean>;
|
|
98
98
|
skipFrontmatter: z.ZodDefault<z.ZodBoolean>;
|
|
@@ -128,8 +128,8 @@ declare const RuleSchema: z.ZodObject<{
|
|
|
128
128
|
}>;
|
|
129
129
|
preambleTier: z.ZodDefault<z.ZodNumber>;
|
|
130
130
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
131
|
-
oss: "oss";
|
|
132
131
|
pro: "pro";
|
|
132
|
+
oss: "oss";
|
|
133
133
|
}>>;
|
|
134
134
|
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
135
135
|
content: z.ZodString;
|
|
@@ -141,8 +141,8 @@ declare const SkillSchema: z.ZodObject<{
|
|
|
141
141
|
name: z.ZodString;
|
|
142
142
|
description: z.ZodString;
|
|
143
143
|
tier: z.ZodDefault<z.ZodEnum<{
|
|
144
|
-
oss: "oss";
|
|
145
144
|
pro: "pro";
|
|
145
|
+
oss: "oss";
|
|
146
146
|
}>>;
|
|
147
147
|
disableModelInvocation: z.ZodDefault<z.ZodBoolean>;
|
|
148
148
|
skipFrontmatter: z.ZodDefault<z.ZodBoolean>;
|
package/dist/content/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -18,14 +18,14 @@ import {
|
|
|
18
18
|
syncAllConfigs,
|
|
19
19
|
syncConfig,
|
|
20
20
|
validateConfigJson
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-XLIKSLM3.js";
|
|
22
22
|
import {
|
|
23
23
|
buildManifest,
|
|
24
24
|
diffContent,
|
|
25
25
|
generateContent,
|
|
26
26
|
listContent,
|
|
27
27
|
validateManifest
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-XXEKWC6F.js";
|
|
29
29
|
import {
|
|
30
30
|
WorkboardManager,
|
|
31
31
|
acquireLock,
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
releaseLock,
|
|
37
37
|
withLock,
|
|
38
38
|
withLockAsync
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-JG6CAG4A.js";
|
|
40
40
|
import "./chunk-DGUM43GV.js";
|
|
41
41
|
export {
|
|
42
42
|
ClaudeCodeAdapter,
|
|
@@ -1,47 +1,101 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* WorkboardProtocol — types for the multi-agent coordination workboard.
|
|
2
|
+
* WorkboardProtocol — types for the multi-agent coordination workboard (v2).
|
|
3
3
|
*
|
|
4
4
|
* The workboard (.claude/workboard.md) is the shared coordination primitive
|
|
5
|
-
* that lets multiple AI coding agents
|
|
6
|
-
* in parallel on the same codebase without stepping on each other.
|
|
5
|
+
* that lets multiple AI coding agents work safely in parallel.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* v2 adds a task board with claiming protocol:
|
|
8
|
+
* Agents — who's running (hook-managed)
|
|
9
|
+
* Tasks — what needs doing (agent-managed, claimable)
|
|
10
|
+
* Blocked — waiting on external action
|
|
11
|
+
* Done — recently completed
|
|
12
|
+
* Log — audit trail
|
|
13
|
+
*
|
|
14
|
+
* Status values: available | claimed | partial | blocked | done
|
|
15
|
+
* Priority values: P0 | P1 | P2 | P3
|
|
10
16
|
*/
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
/** Valid task statuses. */
|
|
18
|
+
type TaskStatus = 'available' | 'claimed' | 'partial' | 'blocked' | 'done';
|
|
19
|
+
/** Valid task priorities. */
|
|
20
|
+
type TaskPriority = 'P0' | 'P1' | 'P2' | 'P3';
|
|
21
|
+
/** A row in the ## Agents table (managed by hooks). */
|
|
22
|
+
interface WorkboardAgent {
|
|
23
|
+
/** Unique agent identifier, e.g. "agent-edit", "agent-system", "wsl-root" */
|
|
14
24
|
id: string;
|
|
15
|
-
/** Human-readable environment description
|
|
25
|
+
/** Human-readable environment description */
|
|
16
26
|
env: string;
|
|
17
27
|
/** ISO timestamp of when the session registered */
|
|
18
28
|
started: string;
|
|
19
29
|
/** Current task description */
|
|
20
30
|
task: string;
|
|
21
|
-
/** Comma-separated list of file globs this
|
|
31
|
+
/** Comma-separated list of file globs this agent is actively modifying */
|
|
22
32
|
files: string;
|
|
23
33
|
/** ISO timestamp of last workboard update */
|
|
24
34
|
updated: string;
|
|
25
35
|
}
|
|
26
|
-
/** A
|
|
27
|
-
interface
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
|
|
36
|
+
/** A row in the ## Tasks table (managed by agents). */
|
|
37
|
+
interface WorkboardTask {
|
|
38
|
+
/** Task identifier, e.g. "T-001" */
|
|
39
|
+
id: string;
|
|
40
|
+
/** Short task description */
|
|
41
|
+
task: string;
|
|
42
|
+
/** Priority: P0 (drop everything), P1 (must do), P2 (should do), P3 (nice to have) */
|
|
43
|
+
pri: TaskPriority;
|
|
44
|
+
/** Current status */
|
|
45
|
+
status: TaskStatus;
|
|
46
|
+
/** Agent id that owns this task (empty if available) */
|
|
47
|
+
owner: string;
|
|
48
|
+
/** GitHub issue or PR number, e.g. "#88", "PR #110" */
|
|
49
|
+
gh: string;
|
|
50
|
+
/** ISO date of last update */
|
|
51
|
+
updated: string;
|
|
52
|
+
/** Free-form notes about progress or remaining work */
|
|
53
|
+
notes: string;
|
|
54
|
+
}
|
|
55
|
+
/** A row in the ## Blocked table. */
|
|
56
|
+
interface WorkboardBlockedTask {
|
|
57
|
+
/** Task identifier */
|
|
58
|
+
id: string;
|
|
59
|
+
/** Short task description */
|
|
60
|
+
task: string;
|
|
61
|
+
/** What's blocking this task */
|
|
62
|
+
blocker: string;
|
|
63
|
+
/** GitHub issue or PR number */
|
|
64
|
+
gh: string;
|
|
65
|
+
/** Additional notes */
|
|
66
|
+
notes: string;
|
|
34
67
|
}
|
|
35
|
-
/**
|
|
68
|
+
/** A row in the ## Done table. */
|
|
69
|
+
interface WorkboardDoneTask {
|
|
70
|
+
/** Task identifier */
|
|
71
|
+
id: string;
|
|
72
|
+
/** Short task description */
|
|
73
|
+
task: string;
|
|
74
|
+
/** Agent that completed the task */
|
|
75
|
+
owner: string;
|
|
76
|
+
/** ISO date of completion */
|
|
77
|
+
completed: string;
|
|
78
|
+
/** GitHub issue or PR number */
|
|
79
|
+
gh: string;
|
|
80
|
+
/** Additional notes */
|
|
81
|
+
notes: string;
|
|
82
|
+
}
|
|
83
|
+
/** Full parsed workboard state (v2). */
|
|
36
84
|
interface WorkboardState {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
|
|
85
|
+
/** Lines before the first ## section (title, protocol docs) */
|
|
86
|
+
preamble: string[];
|
|
87
|
+
/** Active agent sessions */
|
|
88
|
+
agents: WorkboardAgent[];
|
|
89
|
+
/** Task board — claimable work items */
|
|
90
|
+
tasks: WorkboardTask[];
|
|
91
|
+
/** Blocked tasks — waiting on external action */
|
|
92
|
+
blocked: WorkboardBlockedTask[];
|
|
93
|
+
/** Recently completed tasks */
|
|
94
|
+
done: WorkboardDoneTask[];
|
|
95
|
+
/** Timestamped log entries (raw markdown list items) */
|
|
96
|
+
log: string[];
|
|
97
|
+
/** Unknown sections preserved as raw markdown, keyed by section title */
|
|
98
|
+
_extra: Record<string, string>;
|
|
45
99
|
}
|
|
46
100
|
/** Result of a conflict detection check. */
|
|
47
101
|
interface ConflictResult {
|
|
@@ -54,58 +108,58 @@ interface ConflictResult {
|
|
|
54
108
|
overlappingFiles: string[];
|
|
55
109
|
}>;
|
|
56
110
|
}
|
|
111
|
+
/** @deprecated Use WorkboardAgent instead */
|
|
112
|
+
type WorkboardSession = WorkboardAgent;
|
|
113
|
+
/** @deprecated Use WorkboardState.log entries instead */
|
|
114
|
+
interface WorkboardEntry {
|
|
115
|
+
timestamp: string;
|
|
116
|
+
sessionId: string;
|
|
117
|
+
description: string;
|
|
118
|
+
}
|
|
57
119
|
|
|
58
120
|
/**
|
|
59
|
-
* WorkboardManager — reads, parses, and writes .claude/workboard.md.
|
|
60
|
-
*
|
|
61
|
-
* The workboard is a markdown file with a specific structure:
|
|
62
|
-
* ## Sessions — markdown table
|
|
63
|
-
* ## Plans — freeform markdown
|
|
64
|
-
* ## Recent — bullet list
|
|
65
|
-
* ## Context — freeform markdown
|
|
66
|
-
* ## Plan Reference — freeform markdown
|
|
121
|
+
* WorkboardManager — reads, parses, and writes .claude/workboard.md (v2).
|
|
67
122
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
123
|
+
* Supports both v1 (Sessions/Recent) and v2 (Agents/Tasks/Blocked/Done/Log)
|
|
124
|
+
* formats for backward compatibility. Always serializes to v2.
|
|
70
125
|
*
|
|
71
|
-
* All mutating methods use file locking (O_EXCL) to prevent race conditions
|
|
72
|
-
*
|
|
73
|
-
* (tmp file + rename).
|
|
126
|
+
* All mutating methods use file locking (O_EXCL) to prevent race conditions.
|
|
127
|
+
* Writes are atomic (tmp file + rename).
|
|
74
128
|
*/
|
|
75
129
|
declare class WorkboardManager {
|
|
76
130
|
private readonly workboardPath;
|
|
77
131
|
private readonly lockPath;
|
|
78
132
|
constructor(workboardPath: string);
|
|
79
|
-
/** Read and parse the workboard. */
|
|
80
133
|
read(): WorkboardState;
|
|
81
|
-
/** Write a workboard state back to disk (locked + atomic). */
|
|
82
134
|
write(state: WorkboardState): void;
|
|
83
|
-
/** Read and parse the workboard asynchronously. */
|
|
84
135
|
readAsync(): Promise<WorkboardState>;
|
|
85
|
-
/** Write a workboard state back to disk asynchronously (locked + atomic). */
|
|
86
136
|
writeAsync(state: WorkboardState): Promise<void>;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
137
|
+
registerAgent(agent: WorkboardAgent): void;
|
|
138
|
+
unregisterAgent(id: string): void;
|
|
139
|
+
updateAgent(id: string, updates: Partial<WorkboardAgent>): void;
|
|
140
|
+
/** Claim an available or partial task. Returns true on success. */
|
|
141
|
+
claimTask(taskId: string, agentId: string): boolean;
|
|
142
|
+
/** Move a task from Tasks to Done. Returns true on success. */
|
|
143
|
+
completeTask(taskId: string, agentId: string): boolean;
|
|
144
|
+
/** Mark a claimed task as partial (agent stopped mid-work). */
|
|
145
|
+
markPartial(taskId: string, notes: string): boolean;
|
|
146
|
+
/** Release a claimed/partial task back to available. */
|
|
147
|
+
releaseTask(taskId: string): boolean;
|
|
148
|
+
/** Move a blocked task to Tasks as available. */
|
|
149
|
+
unblockTask(taskId: string, pri?: string): boolean;
|
|
94
150
|
claimFiles(id: string, files: string[]): void;
|
|
95
|
-
/** Clear a session's file reservations. */
|
|
96
151
|
releaseFiles(id: string): void;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/** Returns sessions whose `updated` timestamp is older than 4 hours. */
|
|
100
|
-
detectStale(): WorkboardSession[];
|
|
101
|
-
/**
|
|
102
|
-
* Check whether the given files conflict with any other active session's reservations.
|
|
103
|
-
* Returns a ConflictResult describing any overlaps found.
|
|
104
|
-
*/
|
|
152
|
+
addLogEntry(agentId: string, description: string): void;
|
|
153
|
+
detectStale(): WorkboardAgent[];
|
|
105
154
|
checkConflicts(mySessionId: string, files: string[]): ConflictResult;
|
|
155
|
+
getClaimedTasks(agentId: string): WorkboardTask[];
|
|
106
156
|
private readUnlocked;
|
|
107
157
|
private writeUnlocked;
|
|
108
158
|
}
|
|
159
|
+
/** @deprecated Use registerAgent instead */
|
|
160
|
+
declare const registerSession: (agent: WorkboardAgent) => void;
|
|
161
|
+
/** @deprecated Use unregisterAgent instead */
|
|
162
|
+
declare const unregisterSession: (id: string) => void;
|
|
109
163
|
|
|
110
164
|
/**
|
|
111
165
|
* Acquire an exclusive file lock using O_EXCL (kernel-level atomic create).
|
|
@@ -158,4 +212,4 @@ declare function detectSessionType(): SessionType;
|
|
|
158
212
|
*/
|
|
159
213
|
declare function deriveSessionId(type: SessionType, existingIds: string[]): string;
|
|
160
214
|
|
|
161
|
-
export { type ConflictResult, type SessionType, type WorkboardEntry, WorkboardManager, type WorkboardSession, type WorkboardState, acquireLock, atomicWriteSync, deriveSessionId, detectSessionType, lockPathFor, releaseLock, withLock, withLockAsync };
|
|
215
|
+
export { type ConflictResult, type SessionType, type TaskPriority, type TaskStatus, type WorkboardAgent, type WorkboardBlockedTask, type WorkboardDoneTask, type WorkboardEntry, WorkboardManager, type WorkboardSession, type WorkboardState, type WorkboardTask, acquireLock, atomicWriteSync, deriveSessionId, detectSessionType, lockPathFor, registerSession, releaseLock, unregisterSession, withLock, withLockAsync };
|
package/dist/workboard/index.js
CHANGED
|
@@ -5,10 +5,12 @@ import {
|
|
|
5
5
|
deriveSessionId,
|
|
6
6
|
detectSessionType,
|
|
7
7
|
lockPathFor,
|
|
8
|
+
registerSession,
|
|
8
9
|
releaseLock,
|
|
10
|
+
unregisterSession,
|
|
9
11
|
withLock,
|
|
10
12
|
withLockAsync
|
|
11
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-JG6CAG4A.js";
|
|
12
14
|
import "../chunk-DGUM43GV.js";
|
|
13
15
|
export {
|
|
14
16
|
WorkboardManager,
|
|
@@ -17,7 +19,9 @@ export {
|
|
|
17
19
|
deriveSessionId,
|
|
18
20
|
detectSessionType,
|
|
19
21
|
lockPathFor,
|
|
22
|
+
registerSession,
|
|
20
23
|
releaseLock,
|
|
24
|
+
unregisterSession,
|
|
21
25
|
withLock,
|
|
22
26
|
withLockAsync
|
|
23
27
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/harnesses",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "[Pro] AI harness integration system - adapters, daemon, workboard coordination, and JSON-RPC server",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"zod": "^4.3.6",
|
|
16
|
-
"@revealui/core": "0.5.
|
|
16
|
+
"@revealui/core": "0.5.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/node": "^25.3.0",
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"vitest": "^4.0.18",
|
|
23
23
|
"dev": "0.0.1"
|
|
24
24
|
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=24.13.0"
|
|
27
|
+
},
|
|
25
28
|
"exports": {
|
|
26
29
|
".": {
|
|
27
30
|
"types": "./dist/index.d.ts",
|
|
@@ -49,7 +52,8 @@
|
|
|
49
52
|
},
|
|
50
53
|
"main": "./dist/index.js",
|
|
51
54
|
"publishConfig": {
|
|
52
|
-
"access": "public"
|
|
55
|
+
"access": "public",
|
|
56
|
+
"registry": "https://registry.npmjs.org"
|
|
53
57
|
},
|
|
54
58
|
"type": "module",
|
|
55
59
|
"types": "./dist/index.d.ts",
|