speexor 0.1.1 → 0.2.0
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/API-REFERENCE.md +96 -1
- package/ARCHITECTURE.md +83 -32
- package/BENCHMARKS.md +52 -0
- package/CHANGELOG.md +35 -4
- package/CODE-OF-CONDUCT.md +83 -83
- package/CONTRIBUTING.md +98 -98
- package/FAQ.md +105 -105
- package/GLOSSARY.md +33 -0
- package/LICENSE.md +21 -21
- package/PUBLISH.md +77 -77
- package/README.md +219 -5
- package/REFACTOR-LOG.md +40 -40
- package/ROADMAP.md +37 -15
- package/SECURITY-DEFAULTS.md +118 -0
- package/SECURITY.md +79 -79
- package/SUMMARY.md +31 -8
- package/TESTING.md +140 -140
- package/dist/{agent-5D3BVWNK.js → agent-D4BRWEOZ.js} +4 -4
- package/dist/agent-D4BRWEOZ.js.map +1 -0
- package/dist/{chunk-2F66BZYJ.js → chunk-2DX54KIM.js} +2 -2
- package/dist/chunk-2DX54KIM.js.map +1 -0
- package/dist/{chunk-B7WLHC4W.js → chunk-7VZHDGRQ.js} +2 -2
- package/dist/chunk-7VZHDGRQ.js.map +1 -0
- package/dist/{chunk-SXALZEOJ.js → chunk-AOFWQZWY.js} +2 -2
- package/dist/chunk-AOFWQZWY.js.map +1 -0
- package/dist/cli/index.js +4 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.js +1 -1
- package/docs/SETUP.md +94 -94
- package/docs/TROUBLESHOOTING.md +113 -113
- package/docs/adr/0001-record-architecture-decisions.md +44 -0
- package/docs/adr/0002-plugin-architecture.md +53 -0
- package/docs/adr/0003-recursive-task-decomposition.md +57 -0
- package/docs/adr/0004-local-first-security.md +58 -0
- package/docs/adr/0005-data-directory-layout.md +69 -0
- package/examples/basic.yaml +61 -61
- package/package.json +103 -102
- package/schema/config.schema.json +119 -119
- package/speexor.config.yaml.example +30 -30
- package/dist/agent-5D3BVWNK.js.map +0 -1
- package/dist/chunk-2F66BZYJ.js.map +0 -1
- package/dist/chunk-B7WLHC4W.js.map +0 -1
- package/dist/chunk-SXALZEOJ.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins/agent/opencode.ts","../src/plugins/agent/claude-code.ts","../src/plugins/agent/aider.ts","../src/plugins/agent/codex.ts","../src/plugins/runtime/tmux.ts","../src/plugins/runtime/process.ts","../src/plugins/workspace/git-worktree.ts","../src/plugins/tracker/github.ts","../src/plugins/scm/github.ts","../src/plugins/notifier/desktop.ts","../src/plugins/index.ts"],"names":["debug","Debug","randomUUID","join","existsSync","mkdirSync","execSync"],"mappings":"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","file":"chunk-7VZHDGRQ.js","sourcesContent":["import type { AgentPlugin, AgentTask, AgentSession, AgentStatus, PluginContext, RuntimeSession } from '../../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:agent:opencode')\r\n\r\nexport class OpenCodeAgent implements AgentPlugin {\r\n name = 'opencode-agent'\r\n version = '0.1.0'\r\n type = 'agent' as const\r\n\r\n private sessions = new Map<string, { task: AgentTask; runtime: RuntimeSession }>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n debug('OpenCode agent initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.sessions.clear()\r\n debug('OpenCode agent destroyed')\r\n }\r\n\r\n async spawn(task: AgentTask, runtime: RuntimeSession): Promise<AgentSession> {\r\n const session: AgentSession = {\r\n id: `oc-${task.id}-${Date.now()}`,\r\n taskId: task.id,\r\n provider: 'opencode',\r\n status: 'running',\r\n startedAt: new Date(),\r\n runtimeSessionId: runtime.id,\r\n }\r\n\r\n this.sessions.set(session.id, { task, runtime })\r\n\r\n await this.context.eventBus.emit('agent:spawned', { sessionId: session.id, task: task.id })\r\n debug(`OpenCode agent spawned: ${session.id}`)\r\n\r\n return session\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) throw new Error(`Session ${sessionId} not found`)\r\n debug(`Input sent to session ${sessionId}: ${input.substring(0, 100)}...`)\r\n }\r\n\r\n async getStatus(sessionId: string): Promise<AgentStatus> {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) return 'error'\r\n return 'running'\r\n }\r\n\r\n async kill(sessionId: string): Promise<void> {\r\n this.sessions.delete(sessionId)\r\n debug(`OpenCode agent killed: ${sessionId}`)\r\n }\r\n}\r\n","import type { AgentPlugin, AgentTask, AgentSession, AgentStatus, PluginContext, RuntimeSession } from '../../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:agent:claude-code')\r\n\r\nexport class ClaudeCodeAgent implements AgentPlugin {\r\n name = 'claude-code-agent'\r\n version = '0.1.0'\r\n type = 'agent' as const\r\n\r\n private sessions = new Map<string, { task: AgentTask; runtime: RuntimeSession }>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n debug('Claude Code agent initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.sessions.clear()\r\n }\r\n\r\n async spawn(task: AgentTask, runtime: RuntimeSession): Promise<AgentSession> {\r\n const session: AgentSession = {\r\n id: `cc-${task.id}-${Date.now()}`,\r\n taskId: task.id,\r\n provider: 'claude-code',\r\n status: 'running',\r\n startedAt: new Date(),\r\n runtimeSessionId: runtime.id,\r\n }\r\n\r\n this.sessions.set(session.id, { task, runtime })\r\n\r\n await this.context.eventBus.emit('agent:spawned', { sessionId: session.id, task: task.id })\r\n debug(`Claude Code agent spawned: ${session.id}`)\r\n\r\n return session\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) throw new Error(`Session ${sessionId} not found`)\r\n }\r\n\r\n async getStatus(sessionId: string): Promise<AgentStatus> {\r\n return this.sessions.has(sessionId) ? 'running' : 'error'\r\n }\r\n\r\n async kill(sessionId: string): Promise<void> {\r\n this.sessions.delete(sessionId)\r\n }\r\n}\r\n","import type { AgentPlugin, AgentTask, AgentSession, AgentStatus, PluginContext, RuntimeSession } from '../../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:agent:aider')\r\n\r\nexport class AiderAgent implements AgentPlugin {\r\n name = 'aider-agent'\r\n version = '0.1.0'\r\n type = 'agent' as const\r\n\r\n private sessions = new Map<string, { task: AgentTask; runtime: RuntimeSession }>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n debug('Aider agent initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.sessions.clear()\r\n }\r\n\r\n async spawn(task: AgentTask, runtime: RuntimeSession): Promise<AgentSession> {\r\n const session: AgentSession = {\r\n id: `ai-${task.id}-${Date.now()}`,\r\n taskId: task.id,\r\n provider: 'aider',\r\n status: 'running',\r\n startedAt: new Date(),\r\n runtimeSessionId: runtime.id,\r\n }\r\n this.sessions.set(session.id, { task, runtime })\r\n debug(`Aider agent spawned: ${session.id}`)\r\n return session\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {}\r\n async getStatus(sessionId: string): Promise<AgentStatus> {\r\n return this.sessions.has(sessionId) ? 'running' : 'error'\r\n }\r\n async kill(sessionId: string): Promise<void> {\r\n this.sessions.delete(sessionId)\r\n }\r\n}\r\n","import type { AgentPlugin, AgentTask, AgentSession, AgentStatus, PluginContext, RuntimeSession } from '../../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:agent:codex')\r\n\r\nexport class CodexAgent implements AgentPlugin {\r\n name = 'codex-agent'\r\n version = '0.1.0'\r\n type = 'agent' as const\r\n\r\n private sessions = new Map<string, { task: AgentTask; runtime: RuntimeSession }>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n debug('Codex agent initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.sessions.clear()\r\n }\r\n\r\n async spawn(task: AgentTask, runtime: RuntimeSession): Promise<AgentSession> {\r\n const session: AgentSession = {\r\n id: `cx-${task.id}-${Date.now()}`,\r\n taskId: task.id,\r\n provider: 'codex',\r\n status: 'running',\r\n startedAt: new Date(),\r\n runtimeSessionId: runtime.id,\r\n }\r\n this.sessions.set(session.id, { task, runtime })\r\n debug(`Codex agent spawned: ${session.id}`)\r\n return session\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {}\r\n async getStatus(sessionId: string): Promise<AgentStatus> {\r\n return this.sessions.has(sessionId) ? 'running' : 'error'\r\n }\r\n async kill(sessionId: string): Promise<void> {\r\n this.sessions.delete(sessionId)\r\n }\r\n}\r\n","import type { RuntimePlugin, RuntimeSession, PluginContext } from '../../core/types.js'\r\nimport { execSync } from 'node:child_process'\r\nimport { randomUUID } from 'node:crypto'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:runtime:tmux')\r\n\r\nexport class TmuxRuntime implements RuntimePlugin {\r\n name = 'tmux-runtime'\r\n version = '0.1.0'\r\n type = 'runtime' as const\r\n\r\n private sessions = new Map<string, RuntimeSession>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n // Verify tmux is available\r\n try {\r\n execSync('tmux -V', { stdio: 'ignore' })\r\n debug('tmux available')\r\n } catch {\r\n console.warn('tmux not found — will fall back to process runtime')\r\n throw new Error('tmux not available on this system')\r\n }\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n for (const [id] of this.sessions) {\r\n await this.destroySession(id).catch(() => {})\r\n }\r\n }\r\n\r\n async createSession(worktreePath: string): Promise<RuntimeSession> {\r\n const id = `tmux-${randomUUID().slice(0, 8)}`\r\n const sessionName = `speexor-${id}`\r\n\r\n try {\r\n execSync(`tmux new-session -d -s ${sessionName} -c ${worktreePath}`, { stdio: 'pipe' })\r\n } catch (error) {\r\n throw new Error(`Failed to create tmux session: ${error}`)\r\n }\r\n\r\n const session: RuntimeSession = {\r\n id,\r\n type: 'tmux',\r\n worktreePath,\r\n createdAt: new Date(),\r\n }\r\n\r\n this.sessions.set(id, session)\r\n debug(`tmux session created: ${id} at ${worktreePath}`)\r\n\r\n return session\r\n }\r\n\r\n async destroySession(sessionId: string): Promise<void> {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) return\r\n\r\n try {\r\n execSync(`tmux kill-session -t speexor-${sessionId}`, { stdio: 'ignore' })\r\n } catch {}\r\n\r\n this.sessions.delete(sessionId)\r\n debug(`tmux session destroyed: ${sessionId}`)\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {\r\n const escaped = input.replace(/'/g, \"'\\\\''\")\r\n execSync(`tmux send-keys -t speexor-${sessionId} '${escaped}' Enter`, { stdio: 'ignore' })\r\n }\r\n\r\n async getOutput(sessionId: string): Promise<string> {\r\n try {\r\n return execSync(`tmux capture-pane -t speexor-${sessionId} -p`, { encoding: 'utf-8' })\r\n } catch {\r\n return ''\r\n }\r\n }\r\n\r\n getLiveStream(sessionId: string): AsyncIterable<string> {\r\n throw new Error('Live stream not implemented for tmux')\r\n }\r\n\r\n async getStatus(sessionId: string): Promise<'running' | 'stopped' | 'error'> {\r\n try {\r\n execSync(`tmux has-session -t speexor-${sessionId}`, { stdio: 'ignore' })\r\n return 'running'\r\n } catch {\r\n return 'stopped'\r\n }\r\n }\r\n}\r\n","import type { RuntimePlugin, RuntimeSession, PluginContext } from '../../core/types.js'\r\nimport { spawn, type ChildProcess } from 'node:child_process'\r\nimport { randomUUID } from 'node:crypto'\r\nimport { createWriteStream, existsSync, mkdirSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:runtime:process')\r\n\r\nexport class ProcessRuntime implements RuntimePlugin {\r\n name = 'process-runtime'\r\n version = '0.1.0'\r\n type = 'runtime' as const\r\n\r\n private sessions = new Map<string, { session: RuntimeSession; process: ChildProcess }>()\r\n private context!: PluginContext\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n debug('Process runtime initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n for (const [id] of this.sessions) {\r\n await this.destroySession(id).catch(() => {})\r\n }\r\n }\r\n\r\n async createSession(worktreePath: string): Promise<RuntimeSession> {\r\n const id = `proc-${randomUUID().slice(0, 8)}`\r\n\r\n // Ensure log directory exists\r\n const logsDir = join(process.cwd(), '.speexor', 'logs')\r\n if (!existsSync(logsDir)) {\r\n mkdirSync(logsDir, { recursive: true })\r\n }\r\n\r\n const logStream = createWriteStream(join(logsDir, `${id}.log`), { flags: 'a' })\r\n\r\n const child = spawn(process.env.SHELL || 'bash', [], {\r\n cwd: worktreePath,\r\n stdio: ['pipe', 'pipe', 'pipe'],\r\n env: { ...process.env, TERM: 'xterm-256color' },\r\n })\r\n\r\n child.stdout?.on('data', (data: Buffer) => {\r\n logStream.write(`[stdout] ${data.toString()}`)\r\n })\r\n\r\n child.stderr?.on('data', (data: Buffer) => {\r\n logStream.write(`[stderr] ${data.toString()}`)\r\n })\r\n\r\n child.on('exit', (code) => {\r\n logStream.write(`[exit] Process exited with code ${code}\\n`)\r\n logStream.end()\r\n })\r\n\r\n const session: RuntimeSession = {\r\n id,\r\n type: 'process',\r\n worktreePath,\r\n pid: child.pid,\r\n createdAt: new Date(),\r\n }\r\n\r\n this.sessions.set(id, { session, process: child })\r\n debug(`Process session created: ${id} (PID: ${child.pid})`)\r\n\r\n return session\r\n }\r\n\r\n async destroySession(sessionId: string): Promise<void> {\r\n const entry = this.sessions.get(sessionId)\r\n if (!entry) return\r\n\r\n entry.process.kill('SIGTERM')\r\n // Force kill after 5s\r\n setTimeout(() => {\r\n try {\r\n entry.process.kill('SIGKILL')\r\n } catch {}\r\n }, 5000)\r\n\r\n this.sessions.delete(sessionId)\r\n debug(`Process session destroyed: ${sessionId}`)\r\n }\r\n\r\n async sendInput(sessionId: string, input: string): Promise<void> {\r\n const entry = this.sessions.get(sessionId)\r\n if (!entry) throw new Error(`Session ${sessionId} not found`)\r\n entry.process.stdin?.write(`${input}\\n`)\r\n }\r\n\r\n async getOutput(sessionId: string): Promise<string> {\r\n const entry = this.sessions.get(sessionId)\r\n if (!entry) return ''\r\n return `Session ${sessionId} (PID: ${entry.process.pid})`\r\n }\r\n\r\n getLiveStream(sessionId: string): AsyncIterable<string> {\r\n throw new Error('Live stream not implemented for process runtime')\r\n }\r\n\r\n async getStatus(sessionId: string): Promise<'running' | 'stopped' | 'error'> {\r\n const entry = this.sessions.get(sessionId)\r\n if (!entry) return 'stopped'\r\n\r\n const exited = entry.process.exitCode !== null\r\n return exited ? 'stopped' : 'running'\r\n }\r\n}\r\n","import type { WorkspacePlugin, WorkspaceSession, AgentTask, PluginContext } from '../../core/types.js'\r\nimport { execSync } from 'node:child_process'\r\nimport { existsSync, mkdirSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\nimport { randomUUID } from 'node:crypto'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:workspace:git-worktree')\r\n\r\nexport class GitWorktreeWorkspace implements WorkspacePlugin {\r\n name = 'git-worktree-workspace'\r\n version = '0.1.0'\r\n type = 'workspace' as const\r\n\r\n private sessions = new Map<string, WorkspaceSession>()\r\n private context!: PluginContext\r\n private worktreesDir = '.speexor/worktrees'\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n\r\n const dir = join(process.cwd(), this.worktreesDir)\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true })\r\n }\r\n\r\n // Verify we're in a git repo\r\n try {\r\n execSync('git rev-parse --git-dir', { stdio: 'ignore' })\r\n } catch {\r\n throw new Error('Not a git repository. Run `speexor start <repo>` first.')\r\n }\r\n\r\n debug('Git worktree workspace initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n const stale = await this.cleanupStale()\r\n if (stale.length > 0) {\r\n debug(`Cleaned up ${stale.length} stale worktree(s)`)\r\n }\r\n }\r\n\r\n async createWorktree(task: AgentTask): Promise<WorkspaceSession> {\r\n const branch = `speexor/${task.id}`\r\n const worktreePath = join(process.cwd(), this.worktreesDir, task.id)\r\n\r\n // Ensure branch exists\r\n try {\r\n execSync(`git show-ref --verify --quiet refs/heads/${branch}`, { stdio: 'ignore' })\r\n } catch {\r\n // Create branch from current HEAD\r\n execSync(`git branch ${branch}`, { stdio: 'pipe' })\r\n }\r\n\r\n // Add worktree\r\n try {\r\n execSync(`git worktree add ${worktreePath} ${branch}`, { stdio: 'pipe' })\r\n } catch (error) {\r\n throw new Error(`Failed to create worktree at ${worktreePath}: ${error}`)\r\n }\r\n\r\n const session: WorkspaceSession = {\r\n id: `wt-${task.id}-${randomUUID().slice(0, 8)}`,\r\n taskId: task.id,\r\n repository: task.repository,\r\n branch,\r\n path: worktreePath,\r\n createdAt: new Date(),\r\n }\r\n\r\n this.sessions.set(session.id, session)\r\n debug(`Worktree created: ${branch} at ${worktreePath}`)\r\n\r\n return session\r\n }\r\n\r\n async removeWorktree(sessionId: string): Promise<void> {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) return\r\n\r\n try {\r\n execSync(`git worktree remove ${session.path}`, { stdio: 'pipe' })\r\n } catch {\r\n // Force remove if clean fails\r\n try {\r\n execSync(`git worktree remove --force ${session.path}`, { stdio: 'pipe' })\r\n } catch {}\r\n }\r\n\r\n this.sessions.delete(sessionId)\r\n debug(`Worktree removed: ${sessionId}`)\r\n }\r\n\r\n getWorktreePath(sessionId: string): string {\r\n const session = this.sessions.get(sessionId)\r\n if (!session) throw new Error(`Session ${sessionId} not found`)\r\n return session.path\r\n }\r\n\r\n async listActive(): Promise<WorkspaceSession[]> {\r\n return Array.from(this.sessions.values())\r\n }\r\n\r\n async cleanupStale(): Promise<string[]> {\r\n const cleaned: string[] = []\r\n\r\n try {\r\n const output = execSync('git worktree list --porcelain', { encoding: 'utf-8' })\r\n const lines = output.split('\\n')\r\n\r\n for (const line of lines) {\r\n if (line.startsWith('worktree ')) {\r\n const path = line.slice(9).trim()\r\n if (path.includes(this.worktreesDir)) {\r\n // Check if session still active\r\n const isActive = Array.from(this.sessions.values()).some((s) => s.path === path)\r\n if (!isActive && existsSync(path)) {\r\n try {\r\n execSync(`git worktree remove --force \"${path}\"`, { stdio: 'pipe' })\r\n cleaned.push(path)\r\n } catch {}\r\n }\r\n }\r\n }\r\n }\r\n } catch {}\r\n\r\n return cleaned\r\n }\r\n}\r\n","import type { TrackerPlugin, TrackerIssue, TrackerFilter, TrackerEvent, PluginContext } from '../../core/types.js'\r\nimport { execSync } from 'node:child_process'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:tracker:github')\r\n\r\nexport class GitHubTracker implements TrackerPlugin {\r\n name = 'github-tracker'\r\n version = '0.1.0'\r\n type = 'tracker' as const\r\n\r\n private context!: PluginContext\r\n private handlers: Array<(event: TrackerEvent) => void> = []\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n // Verify gh CLI\r\n try {\r\n execSync('gh --version', { stdio: 'ignore' })\r\n debug('GitHub CLI available')\r\n } catch {\r\n throw new Error('GitHub CLI (gh) not found. Install from https://cli.github.com/')\r\n }\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.handlers = []\r\n }\r\n\r\n async fetchIssues(filter?: TrackerFilter): Promise<TrackerIssue[]> {\r\n const state = filter?.state ?? 'open'\r\n const labels = filter?.labels?.length ? `--label \"${filter.labels.join(',')}\"` : ''\r\n const limit = filter?.limit ?? 30\r\n\r\n try {\r\n const output = execSync(\r\n `gh issue list --state ${state} ${labels} --limit ${limit} --json number,title,body,state,labels,url,createdAt,updatedAt`,\r\n { encoding: 'utf-8' },\r\n )\r\n\r\n const issues: TrackerIssue[] = JSON.parse(output).map((i: Record<string, unknown>) => ({\r\n id: String((i as { number: number }).number),\r\n title: i.title as string,\r\n description: (i.body as string) ?? '',\r\n state: i.state as 'open' | 'closed',\r\n labels: (i.labels as Array<{ name: string }>)?.map((l: { name: string }) => l.name) ?? [],\r\n url: i.url as string,\r\n createdAt: new Date(i.createdAt as string),\r\n updatedAt: new Date(i.updatedAt as string),\r\n }))\r\n\r\n return issues\r\n } catch (error) {\r\n debug('Failed to fetch issues:', error)\r\n return []\r\n }\r\n }\r\n\r\n async getIssue(id: string): Promise<TrackerIssue | null> {\r\n try {\r\n const output = execSync(`gh issue view ${id} --json number,title,body,state,labels,url,createdAt,updatedAt`, { encoding: 'utf-8' })\r\n\r\n const i = JSON.parse(output)\r\n return {\r\n id: String(i.number),\r\n title: i.title,\r\n description: i.body ?? '',\r\n state: i.state,\r\n labels: i.labels?.map((l: { name: string }) => l.name) ?? [],\r\n url: i.url,\r\n createdAt: new Date(i.createdAt),\r\n updatedAt: new Date(i.updatedAt),\r\n }\r\n } catch {\r\n return null\r\n }\r\n }\r\n\r\n onEvent(handler: (event: TrackerEvent) => void): void {\r\n this.handlers.push(handler)\r\n }\r\n\r\n private emit(event: TrackerEvent): void {\r\n for (const handler of this.handlers) {\r\n handler(event)\r\n }\r\n }\r\n}\r\n","import type { SCMPlugin, PRInfo, PRStatus, PRComment, CIRun, TrackerEvent, PluginContext } from '../../core/types.js'\r\nimport { execSync } from 'node:child_process'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:scm:github')\r\n\r\nexport class GitHubSCM implements SCMPlugin {\r\n name = 'github-scm'\r\n version = '0.1.0'\r\n type = 'scm' as const\r\n\r\n private context!: PluginContext\r\n private handlers: Array<(event: TrackerEvent) => void> = []\r\n\r\n async initialize(context: PluginContext): Promise<void> {\r\n this.context = context\r\n try {\r\n execSync('gh --version', { stdio: 'ignore' })\r\n debug('GitHub CLI available')\r\n } catch {\r\n throw new Error('GitHub CLI (gh) not found')\r\n }\r\n }\r\n\r\n async destroy(): Promise<void> {\r\n this.handlers = []\r\n }\r\n\r\n async createBranch(baseBranch: string, newBranch: string): Promise<void> {\r\n execSync(`git fetch origin ${baseBranch}`, { stdio: 'pipe' })\r\n execSync(`git checkout -b ${newBranch} origin/${baseBranch}`, { stdio: 'pipe' })\r\n }\r\n\r\n async commitAndPush(branch: string, message: string): Promise<string> {\r\n execSync('git add -A', { stdio: 'pipe' })\r\n execSync(`git commit -m \"${message.replace(/\"/g, '\\\\\"')}\"`, { stdio: 'pipe' })\r\n execSync(`git push origin ${branch}`, { stdio: 'pipe' })\r\n\r\n const sha = execSync('git rev-parse HEAD', { encoding: 'utf-8' }).trim()\r\n return sha\r\n }\r\n\r\n async createPullRequest(title: string, description: string, head: string, base: string): Promise<PRInfo> {\r\n const escapedBody = description.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n')\r\n const output = execSync(\r\n `gh pr create --title \"${title}\" --body \"${escapedBody}\" --head ${head} --base ${base} --json number,title,url,state,headRefName,baseRefName,createdAt`,\r\n { encoding: 'utf-8' },\r\n )\r\n\r\n const pr = JSON.parse(output)\r\n return {\r\n id: String(pr.number),\r\n url: pr.url,\r\n title: pr.title,\r\n state: pr.state,\r\n headBranch: pr.headRefName,\r\n baseBranch: pr.baseRefName,\r\n createdAt: new Date(pr.createdAt),\r\n }\r\n }\r\n\r\n async getPRStatus(prId: string): Promise<PRStatus> {\r\n const output = execSync(\r\n `gh pr view ${prId} --json number,state,mergeable,reviews,statusCheckRollup --jq '{state,mergeable,reviews,checks: .statusCheckRollup}'`,\r\n { encoding: 'utf-8' },\r\n )\r\n\r\n const data = JSON.parse(output)\r\n\r\n return {\r\n id: prId,\r\n state: data.state,\r\n mergeable: data.mergeable === 'MERGEABLE',\r\n ciStatus: this.determineCIStatus(data.checks),\r\n reviewStatus: this.determineReviewStatus(data.reviews),\r\n }\r\n }\r\n\r\n async getPRComments(prId: string): Promise<PRComment[]> {\r\n const output = execSync(\r\n `gh pr view ${prId} --json comments --jq '.comments[] | {id: .id, author: .author.name, body: .body, createdAt: .createdAt}'`,\r\n { encoding: 'utf-8' },\r\n )\r\n\r\n // gh returns multiple JSON objects, need to parse as array\r\n const lines = output.trim().split('\\n')\r\n return lines\r\n .filter((l) => l.trim())\r\n .map((line) => {\r\n try {\r\n return JSON.parse(line) as PRComment\r\n } catch {\r\n return null\r\n }\r\n })\r\n .filter((c): c is PRComment => c !== null)\r\n }\r\n\r\n async getCIRuns(prId: string): Promise<CIRun[]> {\r\n const output = execSync(\r\n `gh pr view ${prId} --json statusCheckRollup --jq '.statusCheckRollup[] | {id: .databaseId, name: .name, status: .status, conclusion: .conclusion, url: .detailsUrl}'`,\r\n { encoding: 'utf-8' },\r\n )\r\n\r\n const lines = output.trim().split('\\n')\r\n return lines\r\n .filter((l) => l.trim())\r\n .map((line) => {\r\n try {\r\n return JSON.parse(line) as CIRun\r\n } catch {\r\n return null\r\n }\r\n })\r\n .filter((c): c is CIRun => c !== null)\r\n }\r\n\r\n async mergePR(prId: string, method: 'merge' | 'squash' | 'rebase' = 'squash'): Promise<void> {\r\n execSync(`gh pr merge ${prId} --${method}`, { stdio: 'pipe' })\r\n }\r\n\r\n onEvent(handler: (event: TrackerEvent) => void): void {\r\n this.handlers.push(handler)\r\n }\r\n\r\n private determineCIStatus(checks: Array<{ status: string; conclusion: string | null }>): 'pending' | 'passing' | 'failing' | 'unknown' {\r\n if (!checks || checks.length === 0) return 'unknown'\r\n\r\n const allPassed = checks.every((c) => c.conclusion === 'success')\r\n const anyFailed = checks.some((c) => c.conclusion === 'failure' || c.conclusion === 'cancelled')\r\n const anyPending = checks.some((c) => c.status === 'in_progress' || c.status === 'queued')\r\n\r\n if (anyFailed) return 'failing'\r\n if (anyPending) return 'pending'\r\n if (allPassed) return 'passing'\r\n return 'unknown'\r\n }\r\n\r\n private determineReviewStatus(reviews: Array<{ state: string }>): 'approved' | 'changes-requested' | 'pending' | 'none' {\r\n if (!reviews || reviews.length === 0) return 'none'\r\n\r\n const latestState = reviews[reviews.length - 1]?.state\r\n if (latestState === 'APPROVED') return 'approved'\r\n if (latestState === 'CHANGES_REQUESTED') return 'changes-requested'\r\n if (latestState === 'PENDING') return 'pending'\r\n return 'none'\r\n }\r\n}\r\n","import type { NotifierPlugin, PluginContext } from '../../core/types.js'\r\nimport { execSync } from 'node:child_process'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:notifier:desktop')\r\n\r\nexport class DesktopNotifier implements NotifierPlugin {\r\n name = 'desktop-notifier'\r\n version = '0.1.0'\r\n type = 'notifier' as const\r\n\r\n async initialize(_context: PluginContext): Promise<void> {\r\n debug('Desktop notifier initialized')\r\n }\r\n\r\n async destroy(): Promise<void> {}\r\n\r\n async notify(level: 'info' | 'warn' | 'error' | 'success', title: string, message: string): Promise<void> {\r\n const platform = process.platform\r\n\r\n try {\r\n if (platform === 'darwin') {\r\n const icon = level === 'error' ? '⚠️' : level === 'success' ? '✅' : level === 'warn' ? '⚠️' : 'ℹ️'\r\n execSync(\r\n `osascript -e 'display notification \"${message.replace(/\"/g, '\\\\\"')}\" with title \"${icon} ${title.replace(/\"/g, '\\\\\"')}\"'`,\r\n { stdio: 'ignore' },\r\n )\r\n } else if (platform === 'win32') {\r\n // Windows -- use PowerShell\r\n const icon = level === 'error' ? 'Warning' : 'Information'\r\n execSync(`powershell -c \"New-BurntToastNotification -Text '${title}', '${message}'\"`, { stdio: 'ignore' })\r\n } else if (platform === 'linux') {\r\n execSync(`notify-send \"${title}\" \"${message}\"`, { stdio: 'ignore' })\r\n }\r\n\r\n debug(`Desktop notification: ${title} - ${message}`)\r\n } catch (error) {\r\n // Fail silently -- desktop notifications are non-critical\r\n debug(`Failed to send notification: ${error}`)\r\n }\r\n }\r\n}\r\n","import type { PluginModule } from '../core/types.js'\r\nimport { OpenCodeAgent } from './agent/opencode.js'\r\nimport { ClaudeCodeAgent } from './agent/claude-code.js'\r\nimport { AiderAgent } from './agent/aider.js'\r\nimport { CodexAgent } from './agent/codex.js'\r\nimport { TmuxRuntime } from './runtime/tmux.js'\r\nimport { ProcessRuntime } from './runtime/process.js'\r\nimport { GitWorktreeWorkspace } from './workspace/git-worktree.js'\r\nimport { GitHubTracker } from './tracker/github.js'\r\nimport { GitHubSCM } from './scm/github.js'\r\nimport { DesktopNotifier } from './notifier/desktop.js'\r\n\r\nexport function loadAllPlugins(): PluginModule[] {\r\n const plugins: PluginModule[] = [\r\n // Agent adapters\r\n new OpenCodeAgent(),\r\n new ClaudeCodeAgent(),\r\n new AiderAgent(),\r\n new CodexAgent(),\r\n\r\n // Runtime\r\n new TmuxRuntime(),\r\n new ProcessRuntime(),\r\n\r\n // Workspace\r\n new GitWorktreeWorkspace(),\r\n\r\n // Tracker\r\n new GitHubTracker(),\r\n\r\n // SCM\r\n new GitHubSCM(),\r\n\r\n // Notifier\r\n new DesktopNotifier(),\r\n ]\r\n\r\n return plugins\r\n}\r\n\r\nexport function loadPluginByType(type: string): PluginModule | undefined {\r\n return loadAllPlugins().find((p) => p.type === type)\r\n}\r\n"]}
|
|
@@ -341,5 +341,5 @@ function createDashboardServer(lifecycle, port = 3e3) {
|
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
export { DashboardServer, DashboardState, createDashboardServer };
|
|
344
|
-
//# sourceMappingURL=chunk-
|
|
345
|
-
//# sourceMappingURL=chunk-
|
|
344
|
+
//# sourceMappingURL=chunk-AOFWQZWY.js.map
|
|
345
|
+
//# sourceMappingURL=chunk-AOFWQZWY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dashboard/state.ts","../src/dashboard/server.ts"],"names":[],"mappings":"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","file":"chunk-AOFWQZWY.js","sourcesContent":["import type { SpeexorState, AgentSession, WorktreeSession, RuntimeSession, ProjectConfig } from '../core/types.js'\r\n\r\nexport class DashboardState {\r\n private state: SpeexorState = {\r\n sessions: [],\r\n worktrees: [],\r\n runtimes: [],\r\n projects: [],\r\n }\r\n\r\n private listeners: Array<() => void> = []\r\n\r\n getState(): SpeexorState {\r\n return { ...this.state }\r\n }\r\n\r\n setProjects(projects: ProjectConfig[]): void {\r\n this.state.projects = projects\r\n this.notify()\r\n }\r\n\r\n addSession(session: AgentSession): void {\r\n this.state.sessions.push(session)\r\n this.notify()\r\n }\r\n\r\n updateSession(sessionId: string, updates: Partial<AgentSession>): void {\r\n const idx = this.state.sessions.findIndex((s) => s.id === sessionId)\r\n if (idx !== -1) {\r\n const entry = this.state.sessions[idx]\r\n if (entry) {\r\n if (updates.id !== undefined) entry.id = updates.id\r\n if (updates.taskId !== undefined) entry.taskId = updates.taskId\r\n if (updates.provider !== undefined) entry.provider = updates.provider\r\n if (updates.status !== undefined) entry.status = updates.status\r\n if (updates.startedAt !== undefined) entry.startedAt = updates.startedAt\r\n if (updates.runtimeSessionId !== undefined) entry.runtimeSessionId = updates.runtimeSessionId\r\n this.notify()\r\n }\r\n }\r\n }\r\n\r\n removeSession(sessionId: string): void {\r\n this.state.sessions = this.state.sessions.filter((s) => s.id !== sessionId)\r\n this.notify()\r\n }\r\n\r\n addWorktree(worktree: WorktreeSession): void {\r\n this.state.worktrees.push(worktree)\r\n this.notify()\r\n }\r\n\r\n removeWorktree(sessionId: string): void {\r\n this.state.worktrees = this.state.worktrees.filter((w) => w.id !== sessionId)\r\n this.notify()\r\n }\r\n\r\n addRuntime(runtime: RuntimeSession): void {\r\n this.state.runtimes.push(runtime)\r\n this.notify()\r\n }\r\n\r\n removeRuntime(sessionId: string): void {\r\n this.state.runtimes = this.state.runtimes.filter((r) => r.id !== sessionId)\r\n this.notify()\r\n }\r\n\r\n onUpdate(listener: () => void): () => void {\r\n this.listeners.push(listener)\r\n return () => {\r\n this.listeners = this.listeners.filter((l) => l !== listener)\r\n }\r\n }\r\n\r\n private notify(): void {\r\n for (const listener of this.listeners) {\r\n try {\r\n listener()\r\n } catch {}\r\n }\r\n }\r\n\r\n toJSON(): SpeexorState {\r\n return this.getState()\r\n }\r\n}\r\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\r\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport type { AgentSession } from '../core/types.js'\r\nimport { DashboardState } from './state.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:dashboard')\r\n\r\ninterface Route {\r\n method: string\r\n path: string\r\n handler: (req: IncomingMessage, res: ServerResponse, params: Record<string, string>) => void | Promise<void>\r\n}\r\n\r\nexport class DashboardServer {\r\n private server: ReturnType<typeof createServer>\r\n private lifecycle: SpeexorLifecycle\r\n private state: DashboardState\r\n private port: number\r\n private routes: Route[] = []\r\n\r\n constructor(lifecycle: SpeexorLifecycle, port: number = 3000) {\r\n this.lifecycle = lifecycle\r\n this.state = new DashboardState()\r\n this.port = port\r\n\r\n // Initialize state from lifecycle\r\n this.state.setProjects(lifecycle.getConfig().projects)\r\n\r\n // Listen to lifecycle events\r\n lifecycle.eventBus.on('session:created', (data: unknown) => {\r\n const { session } = data as { session: AgentSession; task: unknown }\r\n this.state.addSession(session)\r\n })\r\n\r\n lifecycle.eventBus.on('session:completed', (data: unknown) => {\r\n const { sessionId } = data as { sessionId: string }\r\n this.state.removeSession(sessionId)\r\n })\r\n\r\n this.setupRoutes()\r\n\r\n this.server = createServer((req, res) => this.handleRequest(req, res))\r\n }\r\n\r\n private setupRoutes(): void {\r\n this.routes = [\r\n { method: 'GET', path: '/api/status', handler: this.handleStatus.bind(this) },\r\n { method: 'GET', path: '/api/projects', handler: this.handleProjects.bind(this) },\r\n { method: 'GET', path: '/api/sessions', handler: this.handleSessions.bind(this) },\r\n { method: 'GET', path: '/api/health', handler: this.handleHealth.bind(this) },\r\n ]\r\n }\r\n\r\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\r\n // CORS headers\r\n res.setHeader('Access-Control-Allow-Origin', '*')\r\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')\r\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type')\r\n\r\n if (req.method === 'OPTIONS') {\r\n res.writeHead(204)\r\n res.end()\r\n return\r\n }\r\n\r\n // Try to match route\r\n const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`)\r\n const pathname = url.pathname\r\n\r\n for (const route of this.routes) {\r\n if (req.method === route.method && this.matchPath(route.path, pathname)) {\r\n try {\r\n await route.handler(req, res, {})\r\n } catch (error) {\r\n this.sendJSON(res, 500, { error: String(error) })\r\n }\r\n return\r\n }\r\n }\r\n\r\n // Serve dashboard HTML for root\r\n if (pathname === '/' || pathname === '/dashboard') {\r\n this.serveDashboardHTML(res)\r\n return\r\n }\r\n\r\n this.sendJSON(res, 404, { error: 'Not found' })\r\n }\r\n\r\n private matchPath(pattern: string, path: string): boolean {\r\n return pattern === path\r\n }\r\n\r\n private sendJSON(res: ServerResponse, status: number, data: unknown): void {\r\n res.writeHead(status, { 'Content-Type': 'application/json' })\r\n res.end(JSON.stringify(data, null, 2))\r\n }\r\n\r\n private handleStatus(_req: IncomingMessage, res: ServerResponse): void {\r\n this.sendJSON(res, 200, {\r\n status: this.lifecycle.getStatus(),\r\n projectCount: this.lifecycle.getConfig().projects.length,\r\n activeSessions: this.lifecycle.listSessions().length,\r\n uptime: process.uptime(),\r\n })\r\n }\r\n\r\n private handleProjects(_req: IncomingMessage, res: ServerResponse): void {\r\n this.sendJSON(res, 200, {\r\n projects: this.lifecycle.getConfig().projects,\r\n })\r\n }\r\n\r\n private handleSessions(_req: IncomingMessage, res: ServerResponse): void {\r\n this.sendJSON(res, 200, {\r\n sessions: this.lifecycle.listSessions(),\r\n worktrees: [], // placeholder\r\n runtimes: [], // placeholder\r\n })\r\n }\r\n\r\n private handleHealth(_req: IncomingMessage, res: ServerResponse): void {\r\n this.sendJSON(res, 200, {\r\n status: 'healthy',\r\n timestamp: new Date().toISOString(),\r\n memory: process.memoryUsage(),\r\n })\r\n }\r\n\r\n private serveDashboardHTML(res: ServerResponse): void {\r\n const html = `<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\" />\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\r\n <title>Speexor Dashboard</title>\r\n <style>\r\n * { margin: 0; padding: 0; box-sizing: border-box; }\r\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #0d1117; color: #c9d1d9; }\r\n .container { max-width: 1200px; margin: 0 auto; padding: 2rem; }\r\n header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; }\r\n h1 { font-size: 1.5rem; color: #58a6ff; }\r\n h1 span { color: #8b949e; font-weight: normal; }\r\n .status-badge { padding: 0.25rem 0.75rem; border-radius: 999px; font-size: 0.8rem; background: #238636; color: #fff; }\r\n .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-bottom: 2rem; }\r\n .stat-card { background: #161b22; border: 1px solid #30363d; border-radius: 6px; padding: 1.25rem; }\r\n .stat-card h3 { font-size: 0.75rem; text-transform: uppercase; color: #8b949e; margin-bottom: 0.5rem; }\r\n .stat-card .value { font-size: 2rem; font-weight: 600; }\r\n .stat-card .value.green { color: #3fb950; }\r\n .stat-card .value.blue { color: #58a6ff; }\r\n .stat-card .value.yellow { color: #d29922; }\r\n .section { margin-bottom: 2rem; }\r\n .section h2 { font-size: 1.1rem; margin-bottom: 1rem; border-bottom: 1px solid #30363d; padding-bottom: 0.5rem; }\r\n table { width: 100%; border-collapse: collapse; }\r\n th, td { text-align: left; padding: 0.75rem; border-bottom: 1px solid #21262d; }\r\n th { color: #8b949e; font-size: 0.8rem; text-transform: uppercase; }\r\n td { font-size: 0.9rem; }\r\n .agent-tag { padding: 0.125rem 0.5rem; border-radius: 999px; font-size: 0.75rem; background: #1f6feb; color: #fff; }\r\n .status-running { color: #3fb950; }\r\n .status-stuck { color: #d29922; }\r\n .status-error { color: #f85149; }\r\n .status-done { color: #8b949e; }\r\n .footer { margin-top: 3rem; text-align: center; color: #484f58; font-size: 0.8rem; }\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"container\">\r\n <header>\r\n <h1>Speexor <span>Dashboard</span></h1>\r\n <span class=\"status-badge\">● Running</span>\r\n </header>\r\n \r\n <div class=\"stats\">\r\n <div class=\"stat-card\">\r\n <h3>Projects</h3>\r\n <div class=\"value blue\" id=\"projectCount\">-</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <h3>Active Agents</h3>\r\n <div class=\"value green\" id=\"agentCount\">-</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <h3>System Status</h3>\r\n <div class=\"value yellow\" id=\"systemStatus\">Healthy</div>\r\n </div>\r\n <div class=\"stat-card\">\r\n <h3>Uptime</h3>\r\n <div class=\"value\" id=\"uptime\">-</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"section\">\r\n <h2>Projects</h2>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th>Name</th>\r\n <th>Repository</th>\r\n <th>Primary Agent</th>\r\n <th>Fallback</th>\r\n </tr>\r\n </thead>\r\n <tbody id=\"projectsBody\">\r\n <tr><td colspan=\"4\">Loading...</td></tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n \r\n <div class=\"section\">\r\n <h2>Active Sessions</h2>\r\n <table>\r\n <thead>\r\n <tr>\r\n <th>ID</th>\r\n <th>Task</th>\r\n <th>Provider</th>\r\n <th>Status</th>\r\n <th>Started</th>\r\n </tr>\r\n </thead>\r\n <tbody id=\"sessionsBody\">\r\n <tr><td colspan=\"5\">Loading...</td></tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n \r\n <div class=\"footer\">\r\n Speexor Agent Orchestrator — part of SpeexJS\r\n </div>\r\n </div>\r\n \r\n <script>\r\n async function fetchJSON(url) {\r\n const res = await fetch(url);\r\n return res.json();\r\n }\r\n \r\n async function refresh() {\r\n try {\r\n const [status, projects, sessions] = await Promise.all([\r\n fetchJSON('/api/status'),\r\n fetchJSON('/api/projects'),\r\n fetchJSON('/api/sessions'),\r\n ]);\r\n \r\n document.getElementById('projectCount').textContent = status.projectCount;\r\n document.getElementById('agentCount').textContent = status.activeSessions;\r\n document.getElementById('systemStatus').textContent = status.status;\r\n document.getElementById('uptime').textContent = Math.floor(status.uptime) + 's';\r\n \r\n const projectsBody = document.getElementById('projectsBody');\r\n if (projects.projects?.length) {\r\n projectsBody.innerHTML = projects.projects.map(p => \\`\r\n <tr>\r\n <td><strong>\\${p.name}</strong></td>\r\n <td>\\${p.repository}</td>\r\n <td><span class=\"agent-tag\">\\${p.provider?.primary || '-'}</span></td>\r\n <td>\\${p.provider?.fallback?.join(', ') || '-'}</td>\r\n </tr>\r\n \\`).join('');\r\n }\r\n \r\n const sessionsBody = document.getElementById('sessionsBody');\r\n if (sessions.sessions?.length) {\r\n sessionsBody.innerHTML = sessions.sessions.map(s => \\`\r\n <tr>\r\n <td>\\${s.id}</td>\r\n <td>\\${s.taskId}</td>\r\n <td><span class=\"agent-tag\">\\${s.provider}</span></td>\r\n <td class=\"status-\\${s.status}\">\\${s.status}</td>\r\n <td>\\${new Date(s.startedAt).toLocaleTimeString()}</td>\r\n </tr>\r\n \\`).join('');\r\n }\r\n } catch (e) {\r\n console.error('Failed to refresh dashboard:', e);\r\n }\r\n }\r\n \r\n refresh();\r\n setInterval(refresh, 5000);\r\n </script>\r\n</body>\r\n</html>`\r\n\r\n res.writeHead(200, { 'Content-Type': 'text/html' })\r\n res.end(html)\r\n }\r\n\r\n start(): void {\r\n this.server.listen(this.port, () => {\r\n debug(`Dashboard server listening on port ${this.port}`)\r\n })\r\n }\r\n\r\n stop(): void {\r\n this.server.close()\r\n debug('Dashboard server stopped')\r\n }\r\n}\r\n\r\nexport function createDashboardServer(lifecycle: SpeexorLifecycle, port: number = 3000): DashboardServer {\r\n return new DashboardServer(lifecycle, port)\r\n}\r\n"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createDashboardServer } from '../chunk-
|
|
3
|
-
import { generateDefaultConfig, loadConfig, SpeexorLifecycle } from '../chunk-
|
|
4
|
-
import { loadAllPlugins } from '../chunk-
|
|
2
|
+
import { createDashboardServer } from '../chunk-AOFWQZWY.js';
|
|
3
|
+
import { generateDefaultConfig, loadConfig, SpeexorLifecycle } from '../chunk-2DX54KIM.js';
|
|
4
|
+
import { loadAllPlugins } from '../chunk-7VZHDGRQ.js';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
7
7
|
import { dirname, join } from 'path';
|
|
@@ -274,7 +274,7 @@ program.name("speexor").description("Agent Orchestrator for multi-AI coding agen
|
|
|
274
274
|
program.command("start [repo]").description("Initialize a project and start the dashboard").option("-p, --port <port>", "Dashboard port", "3000").option("-n, --name <name>", "Project name").option("--no-dashboard", "Skip starting dashboard").action(startCommand);
|
|
275
275
|
program.command("agent").description("Manage agents").addCommand(
|
|
276
276
|
new Command("spawn").description("Spawn a new agent for a task").requiredOption("-t, --task <id>", "Task ID").option("-a, --agent <type>", "Agent type (opencode, claude-code, aider, codex)", "opencode").action(async (opts) => {
|
|
277
|
-
const { agentSpawnCommand } = await import('../agent-
|
|
277
|
+
const { agentSpawnCommand } = await import('../agent-D4BRWEOZ.js');
|
|
278
278
|
await agentSpawnCommand(opts);
|
|
279
279
|
})
|
|
280
280
|
);
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/start.ts","../../src/cli/list.ts","../../src/cli/stop.ts","../../src/cli/logs.ts","../../src/cli/config-help.ts","../../src/cli/index.ts"],"names":["chalk","join","existsSync","__dirname","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport { stringify } from 'yaml'\nimport { loadConfig, generateDefaultConfig, validateConfig } from '../core/config.js'\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\nimport { loadAllPlugins } from '../plugins/index.js'\nimport { createDashboardServer } from '../dashboard/server.js'\nimport Debug from 'debug'\nimport ora from 'ora'\n\nconst debug = Debug('speexor:start')\n\ninterface StartOptions {\n port?: string\n name?: string\n dashboard?: boolean\n}\n\nexport async function startCommand(repo?: string, options: StartOptions = {}) {\n const cwd = process.cwd()\n const port = parseInt(options.port ?? '3000', 10)\n\n // If repo provided, init new project\n if (repo) {\n const spinner = ora('Initializing Speexor project...').start()\n\n const config = generateDefaultConfig(repo, options.name)\n const configPath = join(cwd, 'speexor.config.yaml')\n\n if (existsSync(configPath)) {\n spinner.warn('speexor.config.yaml already exists — using existing config')\n } else {\n const yaml = stringify(config, { indent: 2 })\n writeFileSync(configPath, yaml, 'utf-8')\n spinner.succeed(`Created speexor.config.yaml at ${configPath}`)\n }\n\n // Create worktrees directory\n const worktreesDir = join(cwd, '.speexor', 'worktrees')\n if (!existsSync(worktreesDir)) {\n mkdirSync(worktreesDir, { recursive: true })\n }\n\n const logsDir = join(cwd, '.speexor', 'logs')\n if (!existsSync(logsDir)) {\n mkdirSync(logsDir, { recursive: true })\n }\n\n spinner.succeed('Project initialized')\n }\n\n // Load config\n try {\n const config = loadConfig(cwd)\n debug(`Loaded config with ${config.projects.length} project(s)`)\n\n // Initialize lifecycle\n const lifecycle = new SpeexorLifecycle(config)\n await lifecycle.initialize()\n\n // Load plugins dynamically\n const spinner = ora('Loading plugins...').start()\n const plugins = loadAllPlugins()\n for (const plugin of plugins) {\n lifecycle.registerPlugin(plugin)\n }\n spinner.succeed(`Loaded ${plugins.length} plugin(s)`)\n\n // Start dashboard if enabled\n if (options.dashboard !== false) {\n const server = createDashboardServer(lifecycle, port)\n server.start()\n console.log(`\\n ✨ Speexor Dashboard: http://localhost:${port}`)\n console.log(` 📋 ${config.projects.length} project(s) configured`)\n console.log(` 🤖 Agents: ${plugins.filter((p) => p.type === 'agent').length} adapter(s) loaded`)\n console.log('\\n Press Ctrl+C to stop\\n')\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log('\\nShutting down...')\n await lifecycle.destroy()\n server.stop()\n process.exit(0)\n }\n\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`\\n ✖ Error: ${error.message}\\n`)\n if (!repo) {\n console.log(' Tip: Run `speexor start <repo-url>` first to initialize a project.\\n')\n }\n }\n process.exit(1)\n }\n}\n","import { loadConfig } from '../core/config.js'\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\nimport { loadAllPlugins } from '../plugins/index.js'\nimport chalk from 'chalk'\n\nexport async function listCommand() {\n try {\n const config = loadConfig()\n const lifecycle = new SpeexorLifecycle(config)\n await lifecycle.initialize()\n\n const plugins = loadAllPlugins()\n for (const plugin of plugins) {\n lifecycle.registerPlugin(plugin)\n }\n\n console.log('\\n 📋 Speexor — Active Projects & Agents\\n')\n\n for (const project of config.projects) {\n const statusColor = project.provider.primary === 'opencode' ? chalk.blue : chalk.magenta\n console.log(` ${chalk.bold(project.name)}`)\n console.log(` Repository: ${project.repository}`)\n console.log(` Primary Agent: ${statusColor(project.provider.primary)}`)\n if (project.provider.fallback?.length) {\n console.log(` Fallback: ${project.provider.fallback.join(', ')}`)\n }\n console.log()\n }\n\n const sessions = lifecycle.listSessions()\n if (sessions.length === 0) {\n console.log(` ${chalk.dim('No active agent sessions. Use `speexor agent spawn` to start one.')}\\n`)\n } else {\n for (const session of sessions) {\n console.log(` ${chalk.cyan(session.id)} — ${session.status}`)\n }\n console.log()\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(` ${chalk.red('✖')} ${error.message}\\n`)\n }\n }\n}\n","import { loadConfig } from '../core/config.js'\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\nimport { loadAllPlugins } from '../plugins/index.js'\nimport chalk from 'chalk'\n\nexport async function stopCommand(sessionId: string) {\n try {\n const config = loadConfig()\n const lifecycle = new SpeexorLifecycle(config)\n await lifecycle.initialize()\n\n const plugins = loadAllPlugins()\n for (const plugin of plugins) {\n lifecycle.registerPlugin(plugin)\n }\n\n await lifecycle.stopSession(sessionId)\n console.log(`\\n ${chalk.green('✓')} Session ${chalk.bold(sessionId)} stopped\\n`)\n } catch (error) {\n if (error instanceof Error) {\n console.error(`\\n ${chalk.red('✖')} ${error.message}\\n`)\n }\n }\n}\n","import { loadConfig } from '../core/config.js'\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\nimport { loadAllPlugins } from '../plugins/index.js'\nimport { readFileSync, existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport chalk from 'chalk'\n\ninterface LogsOptions {\n follow?: boolean\n lines?: string\n}\n\nexport async function logsCommand(sessionId: string, options: LogsOptions) {\n const numLines = parseInt(options.lines ?? '50', 10)\n const logPath = join(process.cwd(), '.speexor', 'logs', `${sessionId}.log`)\n\n if (!existsSync(logPath)) {\n console.error(`\\n ${chalk.red('✖')} No logs found for session: ${sessionId}\\n`)\n return\n }\n\n try {\n const content = readFileSync(logPath, 'utf-8')\n const lines = content.split('\\n').filter(Boolean)\n const tail = lines.slice(-numLines)\n\n console.log(`\\n 📋 Logs for session ${chalk.bold(sessionId)} (last ${numLines} lines):\\n`)\n for (const line of tail) {\n console.log(` ${line}`)\n }\n console.log()\n\n if (options.follow) {\n console.log(chalk.dim(' (Follow mode — press Ctrl+C to stop)\\n'))\n // In follow mode, we'd tail the file. For now, just show note.\n }\n } catch (error) {\n if (error instanceof Error) {\n console.error(`\\n ${chalk.red('✖')} ${error.message}\\n`)\n }\n }\n}\n","import chalk from 'chalk'\n\nconst CONFIG_HELP = `\n${chalk.bold('speexor.config.yaml Schema Reference')}\n\n${chalk.cyan('version')}\n ${chalk.dim('string, must be \"1\"')}\n\n${chalk.cyan('projects')}\n ${chalk.dim('array of project configurations')}\n\n ${chalk.cyan('projects[].name')}\n ${chalk.dim('string — Project display name')}\n \n ${chalk.cyan('projects[].repository')}\n ${chalk.dim('string — Git repository URL or local path')}\n \n ${chalk.cyan('projects[].path')}\n ${chalk.dim('string (optional) — Local path override')}\n \n ${chalk.cyan('projects[].branch')}\n ${chalk.dim('string (optional) — Default base branch (default: main)')}\n\n ${chalk.cyan('projects[].provider')}\n ${chalk.dim('Provider routing configuration')}\n \n ${chalk.cyan('projects[].provider.primary')}\n ${chalk.dim('string — Primary agent: opencode, claude-code, aider, codex')}\n \n ${chalk.cyan('projects[].provider.fallback')}\n ${chalk.dim('string[] (optional) — Fallback agents in priority order')}\n \n ${chalk.cyan('projects[].provider.concurrentLimit')}\n ${chalk.dim('number (optional) — Max parallel agents for this project (default: 5)')}\n \n ${chalk.cyan('projects[].provider.costLimit')}\n ${chalk.dim('number (optional) — Cost limit in cents per session')}\n\n ${chalk.cyan('projects[].reactions')}\n ${chalk.dim('Reaction rules for CI/PR events')}\n \n ${chalk.cyan('projects[].reactions.ci-failed')}\n ${chalk.cyan('projects[].reactions.changes-requested')}\n ${chalk.cyan('projects[].reactions.approved-and-green')}\n ${chalk.dim('Each reaction has:')}\n ${chalk.dim(' auto: boolean — Auto-trigger reaction')}\n ${chalk.dim(' action: \"fix\" | \"notify\" | \"escalate\" | \"skip\"')}\n ${chalk.dim(' retries: number — Max retry attempts (0-10)')}\n ${chalk.dim(' escalateAfter: number — Minutes before escalation')}\n\n${chalk.bold('Example:')}\n\n${chalk.green(`\nversion: \"1\"\nprojects:\n - name: brainclash\n repository: https://github.com/user/brainclash\n provider:\n primary: opencode\n fallback: [deepseek, claude-code]\n concurrentLimit: 3\n reactions:\n ci-failed:\n auto: true\n action: fix\n retries: 3\n escalateAfter: 30\n changes-requested:\n auto: true\n action: fix\n retries: 2\n escalateAfter: 60\n approved-and-green:\n auto: false\n action: notify\n retries: 0\n escalateAfter: 0\n`)}\n\n${chalk.bold('Commands:')}\n ${chalk.cyan('speexor start [repo-url|path]')}\n ${chalk.dim('Initialize project + start dashboard')}\n ${chalk.cyan('speexor agent spawn --task <id>')}\n ${chalk.dim('Spawn agent for a task')}\n ${chalk.cyan('speexor list')}\n ${chalk.dim('List all projects and active agents')}\n ${chalk.cyan('speexor stop <session-id>')}\n ${chalk.dim('Stop an agent session')}\n ${chalk.cyan('speexor logs <session-id>')}\n ${chalk.dim('View agent session logs')}\n`\n\nexport function configHelpCommand() {\n console.log(CONFIG_HELP)\n}\n","#!/usr/bin/env node\nimport { Command } from 'commander'\nimport { startCommand } from './start.js'\nimport { listCommand } from './list.js'\nimport { stopCommand } from './stop.js'\nimport { logsCommand } from './logs.js'\nimport { configHelpCommand } from './config-help.js'\nimport { readFileSync, existsSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nfunction getVersion(): string {\n try {\n const pkgPath = join(__dirname, '..', '..', 'package.json')\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\n return pkg.version ?? '0.1.0'\n }\n } catch {}\n return '0.1.0'\n}\n\nconst program = new Command()\n\nprogram.name('speexor').description('Agent Orchestrator for multi-AI coding agent orchestration (Speexor)').version(getVersion())\n\nprogram\n .command('start [repo]')\n .description('Initialize a project and start the dashboard')\n .option('-p, --port <port>', 'Dashboard port', '3000')\n .option('-n, --name <name>', 'Project name')\n .option('--no-dashboard', 'Skip starting dashboard')\n .action(startCommand)\n\nprogram\n .command('agent')\n .description('Manage agents')\n .addCommand(\n new Command('spawn')\n .description('Spawn a new agent for a task')\n .requiredOption('-t, --task <id>', 'Task ID')\n .option('-a, --agent <type>', 'Agent type (opencode, claude-code, aider, codex)', 'opencode')\n .action(async (opts) => {\n const { agentSpawnCommand } = await import('./agent.js')\n await agentSpawnCommand(opts)\n }),\n )\n\nprogram.command('list').description('List all projects and active agent statuses').action(listCommand)\n\nprogram.command('stop <session-id>').description('Stop an agent session safely').action(stopCommand)\n\nprogram\n .command('logs <session-id>')\n .description('Tail logs for an agent session')\n .option('-f, --follow', 'Follow log output')\n .option('-n, --lines <count>', 'Number of lines', '50')\n .action(logsCommand)\n\nprogram.command('config-help').description('Show full config schema reference').action(configHelpCommand)\n\nprogram.parse(process.argv)\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/start.ts","../../src/cli/list.ts","../../src/cli/stop.ts","../../src/cli/logs.ts","../../src/cli/config-help.ts","../../src/cli/index.ts"],"names":["chalk","join","existsSync","__dirname","readFileSync"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\r\nimport { join, resolve } from 'node:path'\r\nimport { stringify } from 'yaml'\r\nimport { loadConfig, generateDefaultConfig, validateConfig } from '../core/config.js'\r\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport { loadAllPlugins } from '../plugins/index.js'\r\nimport { createDashboardServer } from '../dashboard/server.js'\r\nimport Debug from 'debug'\r\nimport ora from 'ora'\r\n\r\nconst debug = Debug('speexor:start')\r\n\r\ninterface StartOptions {\r\n port?: string\r\n name?: string\r\n dashboard?: boolean\r\n}\r\n\r\nexport async function startCommand(repo?: string, options: StartOptions = {}) {\r\n const cwd = process.cwd()\r\n const port = parseInt(options.port ?? '3000', 10)\r\n\r\n // If repo provided, init new project\r\n if (repo) {\r\n const spinner = ora('Initializing Speexor project...').start()\r\n\r\n const config = generateDefaultConfig(repo, options.name)\r\n const configPath = join(cwd, 'speexor.config.yaml')\r\n\r\n if (existsSync(configPath)) {\r\n spinner.warn('speexor.config.yaml already exists — using existing config')\r\n } else {\r\n const yaml = stringify(config, { indent: 2 })\r\n writeFileSync(configPath, yaml, 'utf-8')\r\n spinner.succeed(`Created speexor.config.yaml at ${configPath}`)\r\n }\r\n\r\n // Create worktrees directory\r\n const worktreesDir = join(cwd, '.speexor', 'worktrees')\r\n if (!existsSync(worktreesDir)) {\r\n mkdirSync(worktreesDir, { recursive: true })\r\n }\r\n\r\n const logsDir = join(cwd, '.speexor', 'logs')\r\n if (!existsSync(logsDir)) {\r\n mkdirSync(logsDir, { recursive: true })\r\n }\r\n\r\n spinner.succeed('Project initialized')\r\n }\r\n\r\n // Load config\r\n try {\r\n const config = loadConfig(cwd)\r\n debug(`Loaded config with ${config.projects.length} project(s)`)\r\n\r\n // Initialize lifecycle\r\n const lifecycle = new SpeexorLifecycle(config)\r\n await lifecycle.initialize()\r\n\r\n // Load plugins dynamically\r\n const spinner = ora('Loading plugins...').start()\r\n const plugins = loadAllPlugins()\r\n for (const plugin of plugins) {\r\n lifecycle.registerPlugin(plugin)\r\n }\r\n spinner.succeed(`Loaded ${plugins.length} plugin(s)`)\r\n\r\n // Start dashboard if enabled\r\n if (options.dashboard !== false) {\r\n const server = createDashboardServer(lifecycle, port)\r\n server.start()\r\n console.log(`\\n ✨ Speexor Dashboard: http://localhost:${port}`)\r\n console.log(` 📋 ${config.projects.length} project(s) configured`)\r\n console.log(` 🤖 Agents: ${plugins.filter((p) => p.type === 'agent').length} adapter(s) loaded`)\r\n console.log('\\n Press Ctrl+C to stop\\n')\r\n\r\n // Graceful shutdown\r\n const shutdown = async () => {\r\n console.log('\\nShutting down...')\r\n await lifecycle.destroy()\r\n server.stop()\r\n process.exit(0)\r\n }\r\n\r\n process.on('SIGINT', shutdown)\r\n process.on('SIGTERM', shutdown)\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(`\\n ✖ Error: ${error.message}\\n`)\r\n if (!repo) {\r\n console.log(' Tip: Run `speexor start <repo-url>` first to initialize a project.\\n')\r\n }\r\n }\r\n process.exit(1)\r\n }\r\n}\r\n","import { loadConfig } from '../core/config.js'\r\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport { loadAllPlugins } from '../plugins/index.js'\r\nimport chalk from 'chalk'\r\n\r\nexport async function listCommand() {\r\n try {\r\n const config = loadConfig()\r\n const lifecycle = new SpeexorLifecycle(config)\r\n await lifecycle.initialize()\r\n\r\n const plugins = loadAllPlugins()\r\n for (const plugin of plugins) {\r\n lifecycle.registerPlugin(plugin)\r\n }\r\n\r\n console.log('\\n 📋 Speexor — Active Projects & Agents\\n')\r\n\r\n for (const project of config.projects) {\r\n const statusColor = project.provider.primary === 'opencode' ? chalk.blue : chalk.magenta\r\n console.log(` ${chalk.bold(project.name)}`)\r\n console.log(` Repository: ${project.repository}`)\r\n console.log(` Primary Agent: ${statusColor(project.provider.primary)}`)\r\n if (project.provider.fallback?.length) {\r\n console.log(` Fallback: ${project.provider.fallback.join(', ')}`)\r\n }\r\n console.log()\r\n }\r\n\r\n const sessions = lifecycle.listSessions()\r\n if (sessions.length === 0) {\r\n console.log(` ${chalk.dim('No active agent sessions. Use `speexor agent spawn` to start one.')}\\n`)\r\n } else {\r\n for (const session of sessions) {\r\n console.log(` ${chalk.cyan(session.id)} — ${session.status}`)\r\n }\r\n console.log()\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(` ${chalk.red('✖')} ${error.message}\\n`)\r\n }\r\n }\r\n}\r\n","import { loadConfig } from '../core/config.js'\r\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport { loadAllPlugins } from '../plugins/index.js'\r\nimport chalk from 'chalk'\r\n\r\nexport async function stopCommand(sessionId: string) {\r\n try {\r\n const config = loadConfig()\r\n const lifecycle = new SpeexorLifecycle(config)\r\n await lifecycle.initialize()\r\n\r\n const plugins = loadAllPlugins()\r\n for (const plugin of plugins) {\r\n lifecycle.registerPlugin(plugin)\r\n }\r\n\r\n await lifecycle.stopSession(sessionId)\r\n console.log(`\\n ${chalk.green('✓')} Session ${chalk.bold(sessionId)} stopped\\n`)\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(`\\n ${chalk.red('✖')} ${error.message}\\n`)\r\n }\r\n }\r\n}\r\n","import { loadConfig } from '../core/config.js'\r\nimport { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport { loadAllPlugins } from '../plugins/index.js'\r\nimport { readFileSync, existsSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\nimport chalk from 'chalk'\r\n\r\ninterface LogsOptions {\r\n follow?: boolean\r\n lines?: string\r\n}\r\n\r\nexport async function logsCommand(sessionId: string, options: LogsOptions) {\r\n const numLines = parseInt(options.lines ?? '50', 10)\r\n const logPath = join(process.cwd(), '.speexor', 'logs', `${sessionId}.log`)\r\n\r\n if (!existsSync(logPath)) {\r\n console.error(`\\n ${chalk.red('✖')} No logs found for session: ${sessionId}\\n`)\r\n return\r\n }\r\n\r\n try {\r\n const content = readFileSync(logPath, 'utf-8')\r\n const lines = content.split('\\n').filter(Boolean)\r\n const tail = lines.slice(-numLines)\r\n\r\n console.log(`\\n 📋 Logs for session ${chalk.bold(sessionId)} (last ${numLines} lines):\\n`)\r\n for (const line of tail) {\r\n console.log(` ${line}`)\r\n }\r\n console.log()\r\n\r\n if (options.follow) {\r\n console.log(chalk.dim(' (Follow mode — press Ctrl+C to stop)\\n'))\r\n // In follow mode, we'd tail the file. For now, just show note.\r\n }\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(`\\n ${chalk.red('✖')} ${error.message}\\n`)\r\n }\r\n }\r\n}\r\n","import chalk from 'chalk'\r\n\r\nconst CONFIG_HELP = `\r\n${chalk.bold('speexor.config.yaml Schema Reference')}\r\n\r\n${chalk.cyan('version')}\r\n ${chalk.dim('string, must be \"1\"')}\r\n\r\n${chalk.cyan('projects')}\r\n ${chalk.dim('array of project configurations')}\r\n\r\n ${chalk.cyan('projects[].name')}\r\n ${chalk.dim('string — Project display name')}\r\n \r\n ${chalk.cyan('projects[].repository')}\r\n ${chalk.dim('string — Git repository URL or local path')}\r\n \r\n ${chalk.cyan('projects[].path')}\r\n ${chalk.dim('string (optional) — Local path override')}\r\n \r\n ${chalk.cyan('projects[].branch')}\r\n ${chalk.dim('string (optional) — Default base branch (default: main)')}\r\n\r\n ${chalk.cyan('projects[].provider')}\r\n ${chalk.dim('Provider routing configuration')}\r\n \r\n ${chalk.cyan('projects[].provider.primary')}\r\n ${chalk.dim('string — Primary agent: opencode, claude-code, aider, codex')}\r\n \r\n ${chalk.cyan('projects[].provider.fallback')}\r\n ${chalk.dim('string[] (optional) — Fallback agents in priority order')}\r\n \r\n ${chalk.cyan('projects[].provider.concurrentLimit')}\r\n ${chalk.dim('number (optional) — Max parallel agents for this project (default: 5)')}\r\n \r\n ${chalk.cyan('projects[].provider.costLimit')}\r\n ${chalk.dim('number (optional) — Cost limit in cents per session')}\r\n\r\n ${chalk.cyan('projects[].reactions')}\r\n ${chalk.dim('Reaction rules for CI/PR events')}\r\n \r\n ${chalk.cyan('projects[].reactions.ci-failed')}\r\n ${chalk.cyan('projects[].reactions.changes-requested')}\r\n ${chalk.cyan('projects[].reactions.approved-and-green')}\r\n ${chalk.dim('Each reaction has:')}\r\n ${chalk.dim(' auto: boolean — Auto-trigger reaction')}\r\n ${chalk.dim(' action: \"fix\" | \"notify\" | \"escalate\" | \"skip\"')}\r\n ${chalk.dim(' retries: number — Max retry attempts (0-10)')}\r\n ${chalk.dim(' escalateAfter: number — Minutes before escalation')}\r\n\r\n${chalk.bold('Example:')}\r\n\r\n${chalk.green(`\r\nversion: \"1\"\r\nprojects:\r\n - name: brainclash\r\n repository: https://github.com/user/brainclash\r\n provider:\r\n primary: opencode\r\n fallback: [deepseek, claude-code]\r\n concurrentLimit: 3\r\n reactions:\r\n ci-failed:\r\n auto: true\r\n action: fix\r\n retries: 3\r\n escalateAfter: 30\r\n changes-requested:\r\n auto: true\r\n action: fix\r\n retries: 2\r\n escalateAfter: 60\r\n approved-and-green:\r\n auto: false\r\n action: notify\r\n retries: 0\r\n escalateAfter: 0\r\n`)}\r\n\r\n${chalk.bold('Commands:')}\r\n ${chalk.cyan('speexor start [repo-url|path]')}\r\n ${chalk.dim('Initialize project + start dashboard')}\r\n ${chalk.cyan('speexor agent spawn --task <id>')}\r\n ${chalk.dim('Spawn agent for a task')}\r\n ${chalk.cyan('speexor list')}\r\n ${chalk.dim('List all projects and active agents')}\r\n ${chalk.cyan('speexor stop <session-id>')}\r\n ${chalk.dim('Stop an agent session')}\r\n ${chalk.cyan('speexor logs <session-id>')}\r\n ${chalk.dim('View agent session logs')}\r\n`\r\n\r\nexport function configHelpCommand() {\r\n console.log(CONFIG_HELP)\r\n}\r\n","#!/usr/bin/env node\r\nimport { Command } from 'commander'\r\nimport { startCommand } from './start.js'\r\nimport { listCommand } from './list.js'\r\nimport { stopCommand } from './stop.js'\r\nimport { logsCommand } from './logs.js'\r\nimport { configHelpCommand } from './config-help.js'\r\nimport { readFileSync, existsSync } from 'node:fs'\r\nimport { join, dirname } from 'node:path'\r\nimport { fileURLToPath } from 'node:url'\r\n\r\nconst __dirname = dirname(fileURLToPath(import.meta.url))\r\n\r\nfunction getVersion(): string {\r\n try {\r\n const pkgPath = join(__dirname, '..', '..', 'package.json')\r\n if (existsSync(pkgPath)) {\r\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\r\n return pkg.version ?? '0.1.0'\r\n }\r\n } catch {}\r\n return '0.1.0'\r\n}\r\n\r\nconst program = new Command()\r\n\r\nprogram.name('speexor').description('Agent Orchestrator for multi-AI coding agent orchestration (Speexor)').version(getVersion())\r\n\r\nprogram\r\n .command('start [repo]')\r\n .description('Initialize a project and start the dashboard')\r\n .option('-p, --port <port>', 'Dashboard port', '3000')\r\n .option('-n, --name <name>', 'Project name')\r\n .option('--no-dashboard', 'Skip starting dashboard')\r\n .action(startCommand)\r\n\r\nprogram\r\n .command('agent')\r\n .description('Manage agents')\r\n .addCommand(\r\n new Command('spawn')\r\n .description('Spawn a new agent for a task')\r\n .requiredOption('-t, --task <id>', 'Task ID')\r\n .option('-a, --agent <type>', 'Agent type (opencode, claude-code, aider, codex)', 'opencode')\r\n .action(async (opts) => {\r\n const { agentSpawnCommand } = await import('./agent.js')\r\n await agentSpawnCommand(opts)\r\n }),\r\n )\r\n\r\nprogram.command('list').description('List all projects and active agent statuses').action(listCommand)\r\n\r\nprogram.command('stop <session-id>').description('Stop an agent session safely').action(stopCommand)\r\n\r\nprogram\r\n .command('logs <session-id>')\r\n .description('Tail logs for an agent session')\r\n .option('-f, --follow', 'Follow log output')\r\n .option('-n, --lines <count>', 'Number of lines', '50')\r\n .action(logsCommand)\r\n\r\nprogram.command('config-help').description('Show full config schema reference').action(configHelpCommand)\r\n\r\nprogram.parse(process.argv)\r\n"]}
|
package/dist/core/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import '../chunk-5NA2TFPG.js';
|
|
2
|
-
export { DEFAULT_REACTION_RULES, SpeexorLifecycle, createEventBus, generateDefaultConfig, loadConfig, validateConfig } from '../chunk-
|
|
2
|
+
export { DEFAULT_REACTION_RULES, SpeexorLifecycle, createEventBus, generateDefaultConfig, loadConfig, validateConfig } from '../chunk-2DX54KIM.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import './chunk-5NA2TFPG.js';
|
|
2
|
-
export { DashboardServer, DashboardState, createDashboardServer } from './chunk-
|
|
3
|
-
export { DEFAULT_REACTION_RULES, SpeexorLifecycle, createEventBus, generateDefaultConfig, loadConfig, validateConfig } from './chunk-
|
|
4
|
-
export { loadAllPlugins, loadPluginByType } from './chunk-
|
|
2
|
+
export { DashboardServer, DashboardState, createDashboardServer } from './chunk-AOFWQZWY.js';
|
|
3
|
+
export { DEFAULT_REACTION_RULES, SpeexorLifecycle, createEventBus, generateDefaultConfig, loadConfig, validateConfig } from './chunk-2DX54KIM.js';
|
|
4
|
+
export { loadAllPlugins, loadPluginByType } from './chunk-7VZHDGRQ.js';
|
|
5
5
|
import Debug from 'debug';
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
7
7
|
import { join } from 'path';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/reaction/engine.ts","../src/store/session.ts"],"names":["debug","Debug"],"mappings":"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","file":"index.js","sourcesContent":["import type { SpeexorLifecycle } from '../core/lifecycle.js'\nimport type { ReactionRule, TrackerEvent, ProjectConfig, AgentTask } from '../core/types.js'\nimport Debug from 'debug'\n\nconst debug = Debug('speexor:reaction')\n\ninterface ReactionHandler {\n eventType: string\n rule: ReactionRule\n project: ProjectConfig\n handle(event: TrackerEvent): Promise<void>\n}\n\nexport class ReactionEngine {\n private lifecycle: SpeexorLifecycle\n private handlers: ReactionHandler[] = []\n private retryCounts = new Map<string, number>()\n\n constructor(lifecycle: SpeexorLifecycle) {\n this.lifecycle = lifecycle\n\n // Listen to lifecycle events\n lifecycle.eventBus.on('reaction:triggered', (data: unknown) => {\n const { eventType, taskId } = data as { eventType: string; taskId: string }\n debug(`Reaction triggered: ${eventType} for task ${taskId}`)\n })\n }\n\n configure(projects: ProjectConfig[]): void {\n this.handlers = []\n\n for (const project of projects) {\n if (!project.reactions) continue\n\n for (const [eventType, rule] of Object.entries(project.reactions)) {\n if (!rule) continue\n\n this.handlers.push({\n eventType,\n rule,\n project,\n handle: async (event: TrackerEvent) => {\n await this.executeReaction(event, rule, project)\n },\n })\n }\n }\n\n debug(`Configured ${this.handlers.length} reaction handler(s)`)\n }\n\n async processEvent(event: TrackerEvent): Promise<void> {\n debug(`Processing event: ${event.type} for issue ${event.issueId}`)\n\n const matchingHandlers = this.handlers.filter((h) => h.eventType === event.type)\n\n for (const handler of matchingHandlers) {\n const key = `${event.issueId}:${handler.eventType}`\n const retries = this.retryCounts.get(key) ?? 0\n\n if (retries >= handler.rule.retries) {\n debug(`Max retries reached for ${key} (${retries}/${handler.rule.retries})`)\n if (handler.rule.action === 'escalate') {\n this.escalate(event, handler.project)\n }\n continue\n }\n\n try {\n await handler.handle(event)\n this.retryCounts.set(key, retries + 1)\n } catch (error) {\n debug(`Reaction failed for ${key}: ${error}`)\n }\n }\n }\n\n private async executeReaction(event: TrackerEvent, rule: ReactionRule, project: ProjectConfig): Promise<void> {\n if (!rule.auto) {\n debug(`Rule for ${event.type} is not auto — notifying instead`)\n this.lifecycle.eventBus.emit('reaction:triggered', {\n eventType: event.type,\n taskId: event.issueId,\n action: 'notify',\n })\n return\n }\n\n switch (rule.action) {\n case 'fix':\n await this.autoFix(event, project)\n break\n case 'notify':\n this.lifecycle.eventBus.emit('reaction:triggered', {\n eventType: event.type,\n taskId: event.issueId,\n action: 'notify',\n })\n break\n case 'escalate':\n this.escalate(event, project)\n break\n case 'skip':\n debug(`Skipping reaction for ${event.type}`)\n break\n }\n }\n\n private async autoFix(event: TrackerEvent, project: ProjectConfig): Promise<void> {\n const task: AgentTask = {\n id: `fix-${event.issueId}-${Date.now()}`,\n title: `Auto-fix: ${event.type} for issue ${event.issueId}`,\n description: `Automated fix triggered by event: ${event.type}\\nIssue: ${event.issueId}\\nData: ${JSON.stringify(event.data)}`,\n repository: project.repository,\n branch: `speexor/fix-${event.issueId}`,\n provider: project.provider.primary,\n }\n\n debug(`Auto-fix spawning agent for task ${task.id}`)\n\n try {\n await this.lifecycle.spawnAgent(task)\n } catch (error) {\n debug(`Auto-fix spawn failed: ${error}`)\n }\n }\n\n private escalate(event: TrackerEvent, _project: ProjectConfig): void {\n debug(`Escalating: ${event.type} for issue ${event.issueId}`)\n\n this.lifecycle.eventBus.emit('reaction:triggered', {\n eventType: event.type,\n taskId: event.issueId,\n action: 'escalate',\n message: `Max retries exceeded for ${event.type} on issue ${event.issueId}`,\n })\n }\n\n getRetryCount(key: string): number {\n return this.retryCounts.get(key) ?? 0\n }\n\n resetRetryCount(key: string): void {\n this.retryCounts.delete(key)\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { SpeexorState, AgentSession, WorktreeSession, ProjectConfig } from '../core/types.js'\nimport Debug from 'debug'\n\nconst debug = Debug('speexor:store')\n\nexport class SessionStore {\n private statePath: string\n private state: SpeexorState\n\n constructor(baseDir?: string) {\n const dir = baseDir ?? join(process.cwd(), '.speexor')\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n this.statePath = join(dir, 'state.json')\n this.state = this.load()\n }\n\n private load(): SpeexorState {\n try {\n if (existsSync(this.statePath)) {\n const raw = readFileSync(this.statePath, 'utf-8')\n const data = JSON.parse(raw)\n return {\n sessions: data.sessions ?? [],\n worktrees: data.worktrees ?? [],\n runtimes: data.runtimes ?? [],\n projects: data.projects ?? [],\n }\n }\n } catch (error) {\n debug(`Failed to load state: ${error}`)\n }\n\n return { sessions: [], worktrees: [], runtimes: [], projects: [] }\n }\n\n private save(): void {\n try {\n writeFileSync(this.statePath, JSON.stringify(this.state, null, 2), 'utf-8')\n } catch (error) {\n debug(`Failed to save state: ${error}`)\n }\n }\n\n getState(): SpeexorState {\n return { ...this.state }\n }\n\n addSession(session: AgentSession): void {\n this.state.sessions.push(session)\n this.save()\n }\n\n updateSession(sessionId: string, updates: Partial<AgentSession>): void {\n const idx = this.state.sessions.findIndex((s) => s.id === sessionId)\n if (idx !== -1) {\n const existing = this.state.sessions[idx]\n if (existing) {\n if (updates.id !== undefined) existing.id = updates.id\n if (updates.taskId !== undefined) existing.taskId = updates.taskId\n if (updates.provider !== undefined) existing.provider = updates.provider\n if (updates.status !== undefined) existing.status = updates.status\n if (updates.startedAt !== undefined) existing.startedAt = updates.startedAt\n if (updates.runtimeSessionId !== undefined) existing.runtimeSessionId = updates.runtimeSessionId\n this.save()\n }\n }\n }\n\n removeSession(sessionId: string): void {\n this.state.sessions = this.state.sessions.filter((s) => s.id !== sessionId)\n this.save()\n }\n\n addWorktree(worktree: WorktreeSession): void {\n this.state.worktrees.push(worktree)\n this.save()\n }\n\n removeWorktree(sessionId: string): void {\n this.state.worktrees = this.state.worktrees.filter((w) => w.id !== sessionId)\n this.save()\n }\n\n setProjects(projects: ProjectConfig[]): void {\n this.state.projects = projects\n this.save()\n }\n\n clear(): void {\n this.state = { sessions: [], worktrees: [], runtimes: [], projects: [] }\n this.save()\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/reaction/engine.ts","../src/store/session.ts"],"names":["debug","Debug"],"mappings":"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","file":"index.js","sourcesContent":["import type { SpeexorLifecycle } from '../core/lifecycle.js'\r\nimport type { ReactionRule, TrackerEvent, ProjectConfig, AgentTask } from '../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:reaction')\r\n\r\ninterface ReactionHandler {\r\n eventType: string\r\n rule: ReactionRule\r\n project: ProjectConfig\r\n handle(event: TrackerEvent): Promise<void>\r\n}\r\n\r\nexport class ReactionEngine {\r\n private lifecycle: SpeexorLifecycle\r\n private handlers: ReactionHandler[] = []\r\n private retryCounts = new Map<string, number>()\r\n\r\n constructor(lifecycle: SpeexorLifecycle) {\r\n this.lifecycle = lifecycle\r\n\r\n // Listen to lifecycle events\r\n lifecycle.eventBus.on('reaction:triggered', (data: unknown) => {\r\n const { eventType, taskId } = data as { eventType: string; taskId: string }\r\n debug(`Reaction triggered: ${eventType} for task ${taskId}`)\r\n })\r\n }\r\n\r\n configure(projects: ProjectConfig[]): void {\r\n this.handlers = []\r\n\r\n for (const project of projects) {\r\n if (!project.reactions) continue\r\n\r\n for (const [eventType, rule] of Object.entries(project.reactions)) {\r\n if (!rule) continue\r\n\r\n this.handlers.push({\r\n eventType,\r\n rule,\r\n project,\r\n handle: async (event: TrackerEvent) => {\r\n await this.executeReaction(event, rule, project)\r\n },\r\n })\r\n }\r\n }\r\n\r\n debug(`Configured ${this.handlers.length} reaction handler(s)`)\r\n }\r\n\r\n async processEvent(event: TrackerEvent): Promise<void> {\r\n debug(`Processing event: ${event.type} for issue ${event.issueId}`)\r\n\r\n const matchingHandlers = this.handlers.filter((h) => h.eventType === event.type)\r\n\r\n for (const handler of matchingHandlers) {\r\n const key = `${event.issueId}:${handler.eventType}`\r\n const retries = this.retryCounts.get(key) ?? 0\r\n\r\n if (retries >= handler.rule.retries) {\r\n debug(`Max retries reached for ${key} (${retries}/${handler.rule.retries})`)\r\n if (handler.rule.action === 'escalate') {\r\n this.escalate(event, handler.project)\r\n }\r\n continue\r\n }\r\n\r\n try {\r\n await handler.handle(event)\r\n this.retryCounts.set(key, retries + 1)\r\n } catch (error) {\r\n debug(`Reaction failed for ${key}: ${error}`)\r\n }\r\n }\r\n }\r\n\r\n private async executeReaction(event: TrackerEvent, rule: ReactionRule, project: ProjectConfig): Promise<void> {\r\n if (!rule.auto) {\r\n debug(`Rule for ${event.type} is not auto — notifying instead`)\r\n this.lifecycle.eventBus.emit('reaction:triggered', {\r\n eventType: event.type,\r\n taskId: event.issueId,\r\n action: 'notify',\r\n })\r\n return\r\n }\r\n\r\n switch (rule.action) {\r\n case 'fix':\r\n await this.autoFix(event, project)\r\n break\r\n case 'notify':\r\n this.lifecycle.eventBus.emit('reaction:triggered', {\r\n eventType: event.type,\r\n taskId: event.issueId,\r\n action: 'notify',\r\n })\r\n break\r\n case 'escalate':\r\n this.escalate(event, project)\r\n break\r\n case 'skip':\r\n debug(`Skipping reaction for ${event.type}`)\r\n break\r\n }\r\n }\r\n\r\n private async autoFix(event: TrackerEvent, project: ProjectConfig): Promise<void> {\r\n const task: AgentTask = {\r\n id: `fix-${event.issueId}-${Date.now()}`,\r\n title: `Auto-fix: ${event.type} for issue ${event.issueId}`,\r\n description: `Automated fix triggered by event: ${event.type}\\nIssue: ${event.issueId}\\nData: ${JSON.stringify(event.data)}`,\r\n repository: project.repository,\r\n branch: `speexor/fix-${event.issueId}`,\r\n provider: project.provider.primary,\r\n }\r\n\r\n debug(`Auto-fix spawning agent for task ${task.id}`)\r\n\r\n try {\r\n await this.lifecycle.spawnAgent(task)\r\n } catch (error) {\r\n debug(`Auto-fix spawn failed: ${error}`)\r\n }\r\n }\r\n\r\n private escalate(event: TrackerEvent, _project: ProjectConfig): void {\r\n debug(`Escalating: ${event.type} for issue ${event.issueId}`)\r\n\r\n this.lifecycle.eventBus.emit('reaction:triggered', {\r\n eventType: event.type,\r\n taskId: event.issueId,\r\n action: 'escalate',\r\n message: `Max retries exceeded for ${event.type} on issue ${event.issueId}`,\r\n })\r\n }\r\n\r\n getRetryCount(key: string): number {\r\n return this.retryCounts.get(key) ?? 0\r\n }\r\n\r\n resetRetryCount(key: string): void {\r\n this.retryCounts.delete(key)\r\n }\r\n}\r\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\nimport type { SpeexorState, AgentSession, WorktreeSession, ProjectConfig } from '../core/types.js'\r\nimport Debug from 'debug'\r\n\r\nconst debug = Debug('speexor:store')\r\n\r\nexport class SessionStore {\r\n private statePath: string\r\n private state: SpeexorState\r\n\r\n constructor(baseDir?: string) {\r\n const dir = baseDir ?? join(process.cwd(), '.speexor')\r\n\r\n if (!existsSync(dir)) {\r\n mkdirSync(dir, { recursive: true })\r\n }\r\n\r\n this.statePath = join(dir, 'state.json')\r\n this.state = this.load()\r\n }\r\n\r\n private load(): SpeexorState {\r\n try {\r\n if (existsSync(this.statePath)) {\r\n const raw = readFileSync(this.statePath, 'utf-8')\r\n const data = JSON.parse(raw)\r\n return {\r\n sessions: data.sessions ?? [],\r\n worktrees: data.worktrees ?? [],\r\n runtimes: data.runtimes ?? [],\r\n projects: data.projects ?? [],\r\n }\r\n }\r\n } catch (error) {\r\n debug(`Failed to load state: ${error}`)\r\n }\r\n\r\n return { sessions: [], worktrees: [], runtimes: [], projects: [] }\r\n }\r\n\r\n private save(): void {\r\n try {\r\n writeFileSync(this.statePath, JSON.stringify(this.state, null, 2), 'utf-8')\r\n } catch (error) {\r\n debug(`Failed to save state: ${error}`)\r\n }\r\n }\r\n\r\n getState(): SpeexorState {\r\n return { ...this.state }\r\n }\r\n\r\n addSession(session: AgentSession): void {\r\n this.state.sessions.push(session)\r\n this.save()\r\n }\r\n\r\n updateSession(sessionId: string, updates: Partial<AgentSession>): void {\r\n const idx = this.state.sessions.findIndex((s) => s.id === sessionId)\r\n if (idx !== -1) {\r\n const existing = this.state.sessions[idx]\r\n if (existing) {\r\n if (updates.id !== undefined) existing.id = updates.id\r\n if (updates.taskId !== undefined) existing.taskId = updates.taskId\r\n if (updates.provider !== undefined) existing.provider = updates.provider\r\n if (updates.status !== undefined) existing.status = updates.status\r\n if (updates.startedAt !== undefined) existing.startedAt = updates.startedAt\r\n if (updates.runtimeSessionId !== undefined) existing.runtimeSessionId = updates.runtimeSessionId\r\n this.save()\r\n }\r\n }\r\n }\r\n\r\n removeSession(sessionId: string): void {\r\n this.state.sessions = this.state.sessions.filter((s) => s.id !== sessionId)\r\n this.save()\r\n }\r\n\r\n addWorktree(worktree: WorktreeSession): void {\r\n this.state.worktrees.push(worktree)\r\n this.save()\r\n }\r\n\r\n removeWorktree(sessionId: string): void {\r\n this.state.worktrees = this.state.worktrees.filter((w) => w.id !== sessionId)\r\n this.save()\r\n }\r\n\r\n setProjects(projects: ProjectConfig[]): void {\r\n this.state.projects = projects\r\n this.save()\r\n }\r\n\r\n clear(): void {\r\n this.state = { sessions: [], worktrees: [], runtimes: [], projects: [] }\r\n this.save()\r\n }\r\n}\r\n"]}
|
package/dist/plugins/index.js
CHANGED