From 459f93b7516064152766000820ca0d36a07bc7f8 Mon Sep 17 00:00:00 2001
From: Gabriel Gordon-Hall
Date: Tue, 15 Jul 2025 12:59:28 +0100
Subject: [PATCH] refactor: explicit Opencode `Executor` (#188)
* use display and fromStr implementations in ExecutorConfig
(cherry picked from commit 115a6a447d9195d28b9c29004fa6301fb60b1b89)
(cherry picked from commit 25d589d54a3fc89f8868f5c409f25bdb162f1326)
* rename opencode to charm/opencode
(cherry picked from commit 41fe88a46cc6c7a1cbf5ecbc3599639351c415c8)
* rename opencode on the frontend
* resuse executor types on the frontend
* put back missing types
---
backend/src/bin/generate_types.rs | 4 +-
backend/src/executor.rs | 18 +-
.../{opencode.rs => charm_opencode.rs} | 16 +-
backend/src/executors/mod.rs | 4 +-
backend/src/routes/task_attempts.rs | 11 +-
backend/src/services/process_service.rs | 66 +---
frontend/src/components/OnboardingDialog.tsx | 6 +-
.../components/tasks/TaskDetailsToolbar.tsx | 12 +-
shared/types.ts | 368 ++++--------------
9 files changed, 135 insertions(+), 370 deletions(-)
rename backend/src/executors/{opencode.rs => charm_opencode.rs} (89%)
diff --git a/backend/src/bin/generate_types.rs b/backend/src/bin/generate_types.rs
index 0a5f2ddd..e980ff84 100644
--- a/backend/src/bin/generate_types.rs
+++ b/backend/src/bin/generate_types.rs
@@ -9,7 +9,7 @@ export const EXECUTOR_TYPES: string[] = [
"claude",
"amp",
"gemini",
- "opencode"
+ "charmopencode"
];
export const EDITOR_TYPES: EditorType[] = [
@@ -26,7 +26,7 @@ export const EXECUTOR_LABELS: Record = {
"claude": "Claude",
"amp": "Amp",
"gemini": "Gemini",
- "opencode": "OpenCode"
+ "charmopencode": "Charm Opencode"
};
export const EDITOR_LABELS: Record = {
diff --git a/backend/src/executor.rs b/backend/src/executor.rs
index 39c052ea..87ad3373 100644
--- a/backend/src/executor.rs
+++ b/backend/src/executor.rs
@@ -7,7 +7,7 @@ use ts_rs::TS;
use uuid::Uuid;
use crate::executors::{
- AmpExecutor, ClaudeExecutor, EchoExecutor, GeminiExecutor, OpencodeExecutor,
+ AmpExecutor, CharmOpencodeExecutor, ClaudeExecutor, EchoExecutor, GeminiExecutor,
SetupScriptExecutor,
};
@@ -345,8 +345,8 @@ pub enum ExecutorConfig {
Claude,
Amp,
Gemini,
- Opencode,
SetupScript { script: String },
+ CharmOpencode,
// Future executors can be added here
// Shell { command: String },
// Docker { image: String, command: String },
@@ -369,7 +369,7 @@ impl FromStr for ExecutorConfig {
"claude" => Ok(ExecutorConfig::Claude),
"amp" => Ok(ExecutorConfig::Amp),
"gemini" => Ok(ExecutorConfig::Gemini),
- "opencode" => Ok(ExecutorConfig::Opencode),
+ "charmopencode" => Ok(ExecutorConfig::CharmOpencode),
"setup_script" => Ok(ExecutorConfig::SetupScript {
script: "setup script".to_string(),
}),
@@ -385,7 +385,7 @@ impl ExecutorConfig {
ExecutorConfig::Claude => Box::new(ClaudeExecutor),
ExecutorConfig::Amp => Box::new(AmpExecutor),
ExecutorConfig::Gemini => Box::new(GeminiExecutor),
- ExecutorConfig::Opencode => Box::new(OpencodeExecutor),
+ ExecutorConfig::CharmOpencode => Box::new(CharmOpencodeExecutor),
ExecutorConfig::SetupScript { script } => {
Box::new(SetupScriptExecutor::new(script.clone()))
}
@@ -395,7 +395,9 @@ impl ExecutorConfig {
pub fn config_path(&self) -> Option {
match self {
ExecutorConfig::Echo => None,
- ExecutorConfig::Opencode => dirs::home_dir().map(|home| home.join(".opencode.json")),
+ ExecutorConfig::CharmOpencode => {
+ dirs::home_dir().map(|home| home.join(".opencode.json"))
+ }
ExecutorConfig::Claude => dirs::home_dir().map(|home| home.join(".claude.json")),
ExecutorConfig::Amp => {
dirs::config_dir().map(|config| config.join("amp").join("settings.json"))
@@ -411,7 +413,7 @@ impl ExecutorConfig {
pub fn mcp_attribute_path(&self) -> Option> {
match self {
ExecutorConfig::Echo => None, // Echo doesn't support MCP
- ExecutorConfig::Opencode => Some(vec!["mcpServers"]),
+ ExecutorConfig::CharmOpencode => Some(vec!["mcpServers"]),
ExecutorConfig::Claude => Some(vec!["mcpServers"]),
ExecutorConfig::Amp => Some(vec!["amp", "mcpServers"]), // Nested path for Amp
ExecutorConfig::Gemini => Some(vec!["mcpServers"]),
@@ -431,7 +433,7 @@ impl ExecutorConfig {
pub fn display_name(&self) -> &'static str {
match self {
ExecutorConfig::Echo => "Echo (Test Mode)",
- ExecutorConfig::Opencode => "Opencode",
+ ExecutorConfig::CharmOpencode => "Charm Opencode",
ExecutorConfig::Claude => "Claude",
ExecutorConfig::Amp => "Amp",
ExecutorConfig::Gemini => "Gemini",
@@ -447,7 +449,7 @@ impl std::fmt::Display for ExecutorConfig {
ExecutorConfig::Claude => "claude",
ExecutorConfig::Amp => "amp",
ExecutorConfig::Gemini => "gemini",
- ExecutorConfig::Opencode => "opencode",
+ ExecutorConfig::CharmOpencode => "charmopencode",
ExecutorConfig::SetupScript { .. } => "setup_script",
};
write!(f, "{}", s)
diff --git a/backend/src/executors/opencode.rs b/backend/src/executors/charm_opencode.rs
similarity index 89%
rename from backend/src/executors/opencode.rs
rename to backend/src/executors/charm_opencode.rs
index 4e4c31b9..21a22d3f 100644
--- a/backend/src/executors/opencode.rs
+++ b/backend/src/executors/charm_opencode.rs
@@ -9,16 +9,16 @@ use crate::{
};
/// An executor that uses OpenCode to process tasks
-pub struct OpencodeExecutor;
+pub struct CharmOpencodeExecutor;
/// An executor that continues an OpenCode thread
-pub struct OpencodeFollowupExecutor {
+pub struct CharmOpencodeFollowupExecutor {
pub session_id: String,
pub prompt: String,
}
#[async_trait]
-impl Executor for OpencodeExecutor {
+impl Executor for CharmOpencodeExecutor {
async fn spawn(
&self,
pool: &sqlx::SqlitePool,
@@ -70,9 +70,9 @@ Task title: {}"#,
let child = command
.group_spawn() // Create new process group so we can kill entire tree
.map_err(|e| {
- crate::executor::SpawnContext::from_command(&command, "OpenCode")
+ crate::executor::SpawnContext::from_command(&command, "CharmOpenCode")
.with_task(task_id, Some(task.title.clone()))
- .with_context("OpenCode CLI execution for new task")
+ .with_context("CharmOpenCode CLI execution for new task")
.spawn_error(e)
})?;
@@ -81,7 +81,7 @@ Task title: {}"#,
}
#[async_trait]
-impl Executor for OpencodeFollowupExecutor {
+impl Executor for CharmOpencodeFollowupExecutor {
async fn spawn(
&self,
_pool: &sqlx::SqlitePool,
@@ -111,9 +111,9 @@ impl Executor for OpencodeFollowupExecutor {
let child = command
.group_spawn() // Create new process group so we can kill entire tree
.map_err(|e| {
- crate::executor::SpawnContext::from_command(&command, "OpenCode")
+ crate::executor::SpawnContext::from_command(&command, "CharmOpenCode")
.with_context(format!(
- "OpenCode CLI followup execution for session {}",
+ "CharmOpenCode CLI followup execution for session {}",
self.session_id
))
.spawn_error(e)
diff --git a/backend/src/executors/mod.rs b/backend/src/executors/mod.rs
index 602a9c96..8c57e2b3 100644
--- a/backend/src/executors/mod.rs
+++ b/backend/src/executors/mod.rs
@@ -1,15 +1,15 @@
pub mod amp;
+pub mod charm_opencode;
pub mod claude;
pub mod dev_server;
pub mod echo;
pub mod gemini;
-pub mod opencode;
pub mod setup_script;
pub use amp::{AmpExecutor, AmpFollowupExecutor};
+pub use charm_opencode::{CharmOpencodeExecutor, CharmOpencodeFollowupExecutor};
pub use claude::{ClaudeExecutor, ClaudeFollowupExecutor};
pub use dev_server::DevServerExecutor;
pub use echo::EchoExecutor;
pub use gemini::{GeminiExecutor, GeminiFollowupExecutor};
-pub use opencode::{OpencodeExecutor, OpencodeFollowupExecutor};
pub use setup_script::SetupScriptExecutor;
diff --git a/backend/src/routes/task_attempts.rs b/backend/src/routes/task_attempts.rs
index 6227556a..c5aae7b0 100644
--- a/backend/src/routes/task_attempts.rs
+++ b/backend/src/routes/task_attempts.rs
@@ -1217,7 +1217,6 @@ pub async fn get_execution_process_normalized_logs(
if !stdout.trim().is_empty() {
// Determine executor type and create appropriate executor for normalization
let executor_type = process.executor_type.as_deref().unwrap_or("unknown");
-
let executor_config = if process.process_type == ExecutionProcessType::SetupScript {
// For setup scripts, use the setup script executor
ExecutorConfig::SetupScript {
@@ -1227,13 +1226,9 @@ pub async fn get_execution_process_normalized_logs(
.unwrap_or_else(|| "setup script".to_string()),
}
} else {
- match executor_type {
- "amp" => ExecutorConfig::Amp,
- "claude" => ExecutorConfig::Claude,
- "echo" => ExecutorConfig::Echo,
- "gemini" => ExecutorConfig::Gemini,
- "opencode" => ExecutorConfig::Opencode,
- _ => {
+ match executor_type.to_string().parse() {
+ Ok(config) => config,
+ Err(_) => {
tracing::warn!(
"Unsupported executor type: {}, cannot normalize logs properly",
executor_type
diff --git a/backend/src/services/process_service.rs b/backend/src/services/process_service.rs
index 39387c04..568e398b 100644
--- a/backend/src/services/process_service.rs
+++ b/backend/src/services/process_service.rs
@@ -415,20 +415,18 @@ impl ProcessService {
)
})?;
- // Determine the executor config from the stored executor_type
- let executor_config = match most_recent_coding_agent.executor_type.as_deref() {
- Some("claude") => crate::executor::ExecutorConfig::Claude,
- Some("amp") => crate::executor::ExecutorConfig::Amp,
- Some("gemini") => crate::executor::ExecutorConfig::Gemini,
- Some("echo") => crate::executor::ExecutorConfig::Echo,
- Some("opencode") => crate::executor::ExecutorConfig::Opencode,
+ let executor_config: crate::executor::ExecutorConfig = match most_recent_coding_agent
+ .executor_type
+ .as_deref()
+ {
+ Some(executor_str) => executor_str.parse().unwrap(),
_ => {
tracing::error!(
- "Invalid or missing executor type '{}' for execution process {} (task attempt {})",
- most_recent_coding_agent.executor_type.as_deref().unwrap_or("None"),
- most_recent_coding_agent.id,
- attempt_id
- );
+ "Invalid or missing executor type '{}' for execution process {} (task attempt {})",
+ most_recent_coding_agent.executor_type.as_deref().unwrap_or("None"),
+ most_recent_coding_agent.id,
+ attempt_id
+ );
return Err(TaskAttemptError::ValidationError(format!(
"Invalid executor type for follow-up: {}",
most_recent_coding_agent
@@ -640,7 +638,7 @@ impl ProcessService {
Some("claude") => crate::executor::ExecutorConfig::Claude,
Some("amp") => crate::executor::ExecutorConfig::Amp,
Some("gemini") => crate::executor::ExecutorConfig::Gemini,
- Some("opencode") => crate::executor::ExecutorConfig::Opencode,
+ Some("charmopencode") => crate::executor::ExecutorConfig::CharmOpencode,
_ => crate::executor::ExecutorConfig::Echo, // Default for "echo" or None
}
}
@@ -667,35 +665,13 @@ impl ProcessService {
None, // Dev servers don't have an executor type
),
crate::executor::ExecutorType::CodingAgent(config) => {
- let executor_type_str = match config {
- crate::executor::ExecutorConfig::Echo => "echo",
- crate::executor::ExecutorConfig::Claude => "claude",
- crate::executor::ExecutorConfig::Amp => "amp",
- crate::executor::ExecutorConfig::Gemini => "gemini",
- crate::executor::ExecutorConfig::Opencode => "opencode",
- crate::executor::ExecutorConfig::SetupScript { .. } => "setup_script",
- };
- (
- "executor".to_string(),
- None,
- Some(executor_type_str.to_string()),
- )
- }
- crate::executor::ExecutorType::FollowUpCodingAgent { config, .. } => {
- let executor_type_str = match config {
- crate::executor::ExecutorConfig::Echo => "echo",
- crate::executor::ExecutorConfig::Claude => "claude",
- crate::executor::ExecutorConfig::Amp => "amp",
- crate::executor::ExecutorConfig::Gemini => "gemini",
- crate::executor::ExecutorConfig::Opencode => "opencode",
- crate::executor::ExecutorConfig::SetupScript { .. } => "setup_script",
- };
- (
- "followup_executor".to_string(),
- None,
- Some(executor_type_str.to_string()),
- )
+ ("executor".to_string(), None, Some(format!("{}", config)))
}
+ crate::executor::ExecutorType::FollowUpCodingAgent { config, .. } => (
+ "followup_executor".to_string(),
+ None,
+ Some(format!("{}", config)),
+ ),
};
let create_process = CreateExecutionProcess {
@@ -803,8 +779,8 @@ impl ProcessService {
prompt,
} => {
use crate::executors::{
- AmpFollowupExecutor, ClaudeFollowupExecutor, GeminiFollowupExecutor,
- OpencodeFollowupExecutor,
+ AmpFollowupExecutor, CharmOpencodeFollowupExecutor, ClaudeFollowupExecutor,
+ GeminiFollowupExecutor,
};
let executor: Box = match config {
@@ -839,9 +815,9 @@ impl ProcessService {
// Echo doesn't support followup, use regular echo
config.create_executor()
}
- crate::executor::ExecutorConfig::Opencode => {
+ crate::executor::ExecutorConfig::CharmOpencode => {
if let Some(sid) = session_id {
- Box::new(OpencodeFollowupExecutor {
+ Box::new(CharmOpencodeFollowupExecutor {
session_id: sid.clone(),
prompt: prompt.clone(),
})
diff --git a/frontend/src/components/OnboardingDialog.tsx b/frontend/src/components/OnboardingDialog.tsx
index 3151366c..52ee06ad 100644
--- a/frontend/src/components/OnboardingDialog.tsx
+++ b/frontend/src/components/OnboardingDialog.tsx
@@ -81,9 +81,7 @@ export function OnboardingDialog({ open, onComplete }: OnboardingDialogProps) {
diff --git a/frontend/src/components/tasks/TaskDetailsToolbar.tsx b/frontend/src/components/tasks/TaskDetailsToolbar.tsx
index 7bd43400..1c0bea4f 100644
--- a/frontend/src/components/tasks/TaskDetailsToolbar.tsx
+++ b/frontend/src/components/tasks/TaskDetailsToolbar.tsx
@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button';
import { useConfig } from '@/components/config-provider';
import { attemptsApi, projectsApi } from '@/lib/api';
import type { GitBranch, TaskAttempt } from 'shared/types';
+import { EXECUTOR_TYPES, EXECUTOR_LABELS } from 'shared/types';
import {
TaskAttemptDataContext,
TaskAttemptLoadingContext,
@@ -16,13 +17,10 @@ import CreatePRDialog from '@/components/tasks/Toolbar/CreatePRDialog.tsx';
import CreateAttempt from '@/components/tasks/Toolbar/CreateAttempt.tsx';
import CurrentAttempt from '@/components/tasks/Toolbar/CurrentAttempt.tsx';
-const availableExecutors = [
- { id: 'echo', name: 'Echo' },
- { id: 'claude', name: 'Claude' },
- { id: 'amp', name: 'Amp' },
- { id: 'gemini', name: 'Gemini' },
- { id: 'opencode', name: 'OpenCode' },
-];
+const availableExecutors = EXECUTOR_TYPES.map((id) => ({
+ id,
+ name: EXECUTOR_LABELS[id] || id,
+}));
function TaskDetailsToolbar() {
const { task, projectId } = useContext(TaskDetailsContext);
diff --git a/shared/types.ts b/shared/types.ts
index 856f8040..0801b0c7 100644
--- a/shared/types.ts
+++ b/shared/types.ts
@@ -4,90 +4,35 @@
export type ApiResponse = { success: boolean, data: T | null, message: string | null, };
-export type Config = {
- theme: ThemeMode,
- executor: ExecutorConfig,
- disclaimer_acknowledged: boolean,
- onboarding_acknowledged: boolean,
- telemetry_acknowledged: boolean,
- sound_alerts: boolean,
- sound_file: SoundFile,
- push_notifications: boolean,
- editor: EditorConfig,
- github: GitHubConfig,
- analytics_enabled: boolean | null,
-};
+export type Config = { theme: ThemeMode, executor: ExecutorConfig, disclaimer_acknowledged: boolean, onboarding_acknowledged: boolean, telemetry_acknowledged: boolean, sound_alerts: boolean, sound_file: SoundFile, push_notifications: boolean, editor: EditorConfig, github: GitHubConfig, analytics_enabled: boolean | null, };
export type ThemeMode = "light" | "dark" | "system" | "purple" | "green" | "blue" | "orange" | "red";
export type EditorConfig = { editor_type: EditorType, custom_command: string | null, };
-export type GitHubConfig = {
- pat: string | null,
- token: string | null,
- username: string | null,
- primary_email: string | null,
- default_pr_base: string | null,
-};
+export type GitHubConfig = { pat: string | null, token: string | null, username: string | null, primary_email: string | null, default_pr_base: string | null, };
export type EditorType = "vscode" | "cursor" | "windsurf" | "intellij" | "zed" | "custom";
export type EditorConstants = { editor_types: Array, editor_labels: Array, };
-export type SoundFile =
- "abstract-sound1"
- | "abstract-sound2"
- | "abstract-sound3"
- | "abstract-sound4"
- | "cow-mooing"
- | "phone-vibration"
- | "rooster";
+export type SoundFile = "abstract-sound1" | "abstract-sound2" | "abstract-sound3" | "abstract-sound4" | "cow-mooing" | "phone-vibration" | "rooster";
export type SoundConstants = { sound_files: Array, sound_labels: Array, };
export type ConfigConstants = { editor: EditorConstants, sound: SoundConstants, };
-export type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" } | { "type": "gemini" } | {
- "type": "opencode"
-};
+export type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" } | { "type": "gemini" } | { "type": "setupscript", script: string, } | { "type": "charmopencode" };
export type ExecutorConstants = { executor_types: Array, executor_labels: Array, };
-export type CreateProject = {
- name: string,
- git_repo_path: string,
- use_existing_repo: boolean,
- setup_script: string | null,
- dev_script: string | null,
-};
+export type CreateProject = { name: string, git_repo_path: string, use_existing_repo: boolean, setup_script: string | null, dev_script: string | null, };
-export type Project = {
- id: string,
- name: string,
- git_repo_path: string,
- setup_script: string | null,
- dev_script: string | null,
- created_at: Date,
- updated_at: Date,
-};
+export type Project = { id: string, name: string, git_repo_path: string, setup_script: string | null, dev_script: string | null, created_at: Date, updated_at: Date, };
-export type ProjectWithBranch = {
- id: string,
- name: string,
- git_repo_path: string,
- setup_script: string | null,
- dev_script: string | null,
- current_branch: string | null,
- created_at: Date,
- updated_at: Date,
-};
+export type ProjectWithBranch = { id: string, name: string, git_repo_path: string, setup_script: string | null, dev_script: string | null, current_branch: string | null, created_at: Date, updated_at: Date, };
-export type UpdateProject = {
- name: string | null,
- git_repo_path: string | null,
- setup_script: string | null,
- dev_script: string | null,
-};
+export type UpdateProject = { name: string | null, git_repo_path: string | null, setup_script: string | null, dev_script: string | null, };
export type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType, };
@@ -99,65 +44,19 @@ export type CreateBranch = { name: string, base_branch: string | null, };
export type CreateTask = { project_id: string, title: string, description: string | null, };
-export type CreateTaskAndStart = {
- project_id: string,
- title: string,
- description: string | null,
- executor: ExecutorConfig | null,
-};
+export type CreateTaskAndStart = { project_id: string, title: string, description: string | null, executor: ExecutorConfig | null, };
export type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
-export type Task = {
- id: string,
- project_id: string,
- title: string,
- description: string | null,
- status: TaskStatus,
- created_at: string,
- updated_at: string,
-};
+export type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, };
-export type TaskWithAttemptStatus = {
- id: string,
- project_id: string,
- title: string,
- description: string | null,
- status: TaskStatus,
- created_at: string,
- updated_at: string,
- has_in_progress_attempt: boolean,
- has_merged_attempt: boolean,
- has_failed_attempt: boolean,
-};
+export type TaskWithAttemptStatus = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, has_in_progress_attempt: boolean, has_merged_attempt: boolean, has_failed_attempt: boolean, };
export type UpdateTask = { title: string | null, description: string | null, status: TaskStatus | null, };
-export type TaskAttemptStatus =
- "setuprunning"
- | "setupcomplete"
- | "setupfailed"
- | "executorrunning"
- | "executorcomplete"
- | "executorfailed";
+export type TaskAttemptStatus = "setuprunning" | "setupcomplete" | "setupfailed" | "executorrunning" | "executorcomplete" | "executorfailed";
-export type TaskAttempt = {
- id: string,
- task_id: string,
- worktree_path: string,
- branch: string,
- base_branch: string,
- merge_commit: string | null,
- executor: string | null,
- pr_url: string | null,
- pr_number: bigint | null,
- pr_status: string | null,
- pr_merged_at: string | null,
- worktree_deleted: boolean,
- setup_completed_at: string | null,
- created_at: string,
- updated_at: string,
-};
+export type TaskAttempt = { id: string, task_id: string, worktree_path: string, branch: string, base_branch: string, merge_commit: string | null, executor: string | null, pr_url: string | null, pr_number: bigint | null, pr_status: string | null, pr_merged_at: string | null, worktree_deleted: boolean, setup_completed_at: string | null, created_at: string, updated_at: string, };
export type CreateTaskAttempt = { executor: string | null, base_branch: string | null, };
@@ -165,48 +64,31 @@ export type UpdateTaskAttempt = Record;
export type CreateFollowUpAttempt = { prompt: string, };
-export type TaskAttemptActivity = {
- id: string,
- execution_process_id: string,
- status: TaskAttemptStatus,
- note: string | null,
- created_at: string,
-};
+export type TaskAttemptActivity = { id: string, execution_process_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, };
-export type TaskAttemptActivityWithPrompt = {
- id: string,
- execution_process_id: string,
- status: TaskAttemptStatus,
- note: string | null,
- created_at: string,
- prompt: string | null,
-};
+export type TaskAttemptActivityWithPrompt = { id: string, execution_process_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, prompt: string | null, };
-export type CreateTaskAttemptActivity = {
- execution_process_id: string,
- status: TaskAttemptStatus | null,
- note: string | null,
-};
+export type CreateTaskAttemptActivity = { execution_process_id: string, status: TaskAttemptStatus | null, note: string | null, };
export type AttemptData = {
- activities: TaskAttemptActivityWithPrompt[];
- processes: ExecutionProcessSummary[];
- runningProcessDetails: Record;
+ activities: TaskAttemptActivityWithPrompt[];
+ processes: ExecutionProcessSummary[];
+ runningProcessDetails: Record;
}
export interface ProcessedLine {
- content: string;
- chunkType: DiffChunkType;
- oldLineNumber?: number;
- newLineNumber?: number;
+ content: string;
+ chunkType: DiffChunkType;
+ oldLineNumber?: number;
+ newLineNumber?: number;
}
export interface ProcessedSection {
- type: 'context' | 'change' | 'expanded';
- lines: ProcessedLine[];
- expandKey?: string;
- expandedAbove?: boolean;
- expandedBelow?: boolean;
+ type: 'context' | 'change' | 'expanded';
+ lines: ProcessedLine[];
+ expandKey?: string;
+ expandedAbove?: boolean;
+ expandedBelow?: boolean;
}
export type DirectoryEntry = { name: string, path: string, is_directory: boolean, is_git_repo: boolean, };
@@ -219,185 +101,97 @@ export type FileDiff = { path: string, chunks: Array, };
export type WorktreeDiff = { files: Array, };
-export type BranchStatus = {
- is_behind: boolean,
- commits_behind: number,
- commits_ahead: number,
- up_to_date: boolean,
- merged: boolean,
- has_uncommitted_changes: boolean,
- base_branch_name: string,
-};
+export type BranchStatus = { is_behind: boolean, commits_behind: number, commits_ahead: number, up_to_date: boolean, merged: boolean, has_uncommitted_changes: boolean, base_branch_name: string, };
-export type ExecutionState =
- "NotStarted"
- | "SetupRunning"
- | "SetupComplete"
- | "SetupFailed"
- | "CodingAgentRunning"
- | "CodingAgentComplete"
- | "CodingAgentFailed"
- | "Complete";
+export type ExecutionState = "NotStarted" | "SetupRunning" | "SetupComplete" | "SetupFailed" | "CodingAgentRunning" | "CodingAgentComplete" | "CodingAgentFailed" | "Complete";
-export type TaskAttemptState = {
- execution_state: ExecutionState,
- has_changes: boolean,
- has_setup_script: boolean,
- setup_process_id: string | null,
- coding_agent_process_id: string | null,
-};
+export type TaskAttemptState = { execution_state: ExecutionState, has_changes: boolean, has_setup_script: boolean, setup_process_id: string | null, coding_agent_process_id: string | null, };
-export type ExecutionProcess = {
- id: string,
- task_attempt_id: string,
- process_type: ExecutionProcessType,
- executor_type: string | null,
- status: ExecutionProcessStatus,
- command: string,
- args: string | null,
- working_directory: string,
- stdout: string | null,
- stderr: string | null,
- exit_code: bigint | null,
- started_at: string,
- completed_at: string | null,
- created_at: string,
- updated_at: string,
-};
+export type ExecutionProcess = { id: string, task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, status: ExecutionProcessStatus, command: string, args: string | null, working_directory: string, stdout: string | null, stderr: string | null, exit_code: bigint | null, started_at: string, completed_at: string | null, created_at: string, updated_at: string, };
-export type ExecutionProcessSummary = {
- id: string,
- task_attempt_id: string,
- process_type: ExecutionProcessType,
- executor_type: string | null,
- status: ExecutionProcessStatus,
- command: string,
- args: string | null,
- working_directory: string,
- exit_code: bigint | null,
- started_at: string,
- completed_at: string | null,
- created_at: string,
- updated_at: string,
-};
+export type ExecutionProcessSummary = { id: string, task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, status: ExecutionProcessStatus, command: string, args: string | null, working_directory: string, exit_code: bigint | null, started_at: string, completed_at: string | null, created_at: string, updated_at: string, };
export type ExecutionProcessStatus = "running" | "completed" | "failed" | "killed";
export type ExecutionProcessType = "setupscript" | "codingagent" | "devserver";
-export type CreateExecutionProcess = {
- task_attempt_id: string,
- process_type: ExecutionProcessType,
- executor_type: string | null,
- command: string,
- args: string | null,
- working_directory: string,
-};
+export type CreateExecutionProcess = { task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, command: string, args: string | null, working_directory: string, };
-export type UpdateExecutionProcess = {
- status: ExecutionProcessStatus | null,
- exit_code: bigint | null,
- completed_at: string | null,
-};
+export type UpdateExecutionProcess = { status: ExecutionProcessStatus | null, exit_code: bigint | null, completed_at: string | null, };
-export type ExecutorSession = {
- id: string,
- task_attempt_id: string,
- execution_process_id: string,
- session_id: string | null,
- prompt: string | null,
- summary: string | null,
- created_at: string,
- updated_at: string,
-};
+export type ExecutorSession = { id: string, task_attempt_id: string, execution_process_id: string, session_id: string | null, prompt: string | null, summary: string | null, created_at: string, updated_at: string, };
export type CreateExecutorSession = { task_attempt_id: string, execution_process_id: string, prompt: string | null, };
export type UpdateExecutorSession = { session_id: string | null, prompt: string | null, summary: string | null, };
-export type NormalizedConversation = {
- entries: Array,
- session_id: string | null,
- executor_type: string,
- prompt: string | null,
- summary: string | null,
-};
+export type NormalizedConversation = { entries: Array, session_id: string | null, executor_type: string, prompt: string | null, summary: string | null, };
export type NormalizedEntry = { timestamp: string | null, entry_type: NormalizedEntryType, content: string, };
-export type NormalizedEntryType = { "type": "user_message" } | { "type": "assistant_message" } | {
- "type": "tool_use",
- tool_name: string,
- action_type: ActionType,
-} | { "type": "system_message" } | { "type": "error_message" } | { "type": "thinking" };
+export type NormalizedEntryType = { "type": "user_message" } | { "type": "assistant_message" } | { "type": "tool_use", tool_name: string, action_type: ActionType, } | { "type": "system_message" } | { "type": "error_message" } | { "type": "thinking" };
-export type ActionType = { "action": "file_read", path: string, } | { "action": "file_write", path: string, } | {
- "action": "command_run",
- command: string,
-} | { "action": "search", query: string, } | { "action": "web_fetch", url: string, } | {
- "action": "task_create",
- description: string,
-} | { "action": "other", description: string, };
+export type ActionType = { "action": "file_read", path: string, } | { "action": "file_write", path: string, } | { "action": "command_run", command: string, } | { "action": "search", query: string, } | { "action": "web_fetch", url: string, } | { "action": "task_create", description: string, } | { "action": "other", description: string, };
export type StartGitHubDeviceFlowType = {
- device_code: string;
- user_code: string;
- verification_uri: string;
- expires_in: number;
- interval: number;
+ device_code: string;
+ user_code: string;
+ verification_uri: string;
+ expires_in: number;
+ interval: number;
};
// Generated constants
export const EXECUTOR_TYPES: string[] = [
- "echo",
- "claude",
- "amp",
- "gemini",
- "opencode"
+ "echo",
+ "claude",
+ "amp",
+ "gemini",
+ "charmopencode"
];
export const EDITOR_TYPES: EditorType[] = [
- "vscode",
- "cursor",
- "windsurf",
- "intellij",
- "zed",
- "custom"
+ "vscode",
+ "cursor",
+ "windsurf",
+ "intellij",
+ "zed",
+ "custom"
];
export const EXECUTOR_LABELS: Record = {
- "echo": "Echo (Test Mode)",
- "claude": "Claude",
- "amp": "Amp",
- "gemini": "Gemini",
- "opencode": "OpenCode"
+ "echo": "Echo (Test Mode)",
+ "claude": "Claude",
+ "amp": "Amp",
+ "gemini": "Gemini",
+ "charmopencode": "Charm Opencode"
};
export const EDITOR_LABELS: Record = {
- "vscode": "VS Code",
- "cursor": "Cursor",
- "windsurf": "Windsurf",
- "intellij": "IntelliJ IDEA",
- "zed": "Zed",
- "custom": "Custom"
+ "vscode": "VS Code",
+ "cursor": "Cursor",
+ "windsurf": "Windsurf",
+ "intellij": "IntelliJ IDEA",
+ "zed": "Zed",
+ "custom": "Custom"
};
export const SOUND_FILES: SoundFile[] = [
- "abstract-sound1",
- "abstract-sound2",
- "abstract-sound3",
- "abstract-sound4",
- "cow-mooing",
- "phone-vibration",
- "rooster"
+ "abstract-sound1",
+ "abstract-sound2",
+ "abstract-sound3",
+ "abstract-sound4",
+ "cow-mooing",
+ "phone-vibration",
+ "rooster"
];
export const SOUND_LABELS: Record = {
- "abstract-sound1": "Gentle Chime",
- "abstract-sound2": "Soft Bell",
- "abstract-sound3": "Digital Tone",
- "abstract-sound4": "Subtle Alert",
- "cow-mooing": "Cow Mooing",
- "phone-vibration": "Phone Vibration",
- "rooster": "Rooster Call"
-};
\ No newline at end of file
+ "abstract-sound1": "Gentle Chime",
+ "abstract-sound2": "Soft Bell",
+ "abstract-sound3": "Digital Tone",
+ "abstract-sound4": "Subtle Alert",
+ "cow-mooing": "Cow Mooing",
+ "phone-vibration": "Phone Vibration",
+ "rooster": "Rooster Call"
+};