11import * as fs from "fs" ;
22import * as os from "os" ;
33import * as path from "path" ;
4- import { z } from "zod" ;
54import { normalizeCwd } from "../paths" ;
65import {
76 sanitizeDashboardConfig ,
@@ -12,6 +11,27 @@ import {
1211 parseStatusMessageFrequencyMs ,
1312 type StatusMessageFrequencyMs ,
1413} from "../status-message-frequency" ;
14+ import {
15+ odeConfigSchema ,
16+ type ChannelDetail ,
17+ type WorkspaceConfig ,
18+ type AgentProvider ,
19+ type AgentsConfig ,
20+ type UpdateConfig ,
21+ type OdeConfig ,
22+ type UserConfig ,
23+ } from "./ode-schema" ;
24+ import { isAgentProviderId } from "@/shared/agent-provider" ;
25+
26+ export type {
27+ ChannelDetail ,
28+ WorkspaceConfig ,
29+ AgentProvider ,
30+ AgentsConfig ,
31+ UpdateConfig ,
32+ OdeConfig ,
33+ UserConfig ,
34+ } from "./ode-schema" ;
1535
1636const existsSync = fs . existsSync ;
1737const mkdirSync = fs . mkdirSync ;
@@ -24,147 +44,12 @@ const XDG_CONFIG_HOME = join(homedir(), ".config");
2444const ODE_CONFIG_DIR = join ( XDG_CONFIG_HOME , "ode" ) ;
2545export const ODE_CONFIG_FILE = join ( ODE_CONFIG_DIR , "ode.json" ) ;
2646
27- const userSchema = z . object ( {
28- name : z . string ( ) . optional ( ) . default ( "" ) ,
29- email : z . string ( ) . optional ( ) . default ( "" ) ,
30- initials : z . string ( ) . optional ( ) . default ( "" ) ,
31- avatar : z . string ( ) . optional ( ) . default ( "" ) ,
32- gitStrategy : z . enum ( [ "default" , "worktree" ] ) . optional ( ) . default ( "worktree" ) ,
33- defaultStatusMessageFormat : z . enum ( [
34- "minimum" ,
35- "medium" ,
36- "aggressive" ,
37- "low" ,
38- "high" ,
39- ] ) . optional ( ) . default ( "medium" ) ,
40- defaultMessageFrequency : z . enum ( [
41- "minimum" ,
42- "medium" ,
43- "aggressive" ,
44- "low" ,
45- "high" ,
46- ] ) . optional ( ) ,
47- messageUpdateIntervalMs : z . number ( ) . optional ( ) ,
48- IM_MESSAGE_UPDATE_INTERVAL_MS : z . number ( ) . optional ( ) . default ( DEFAULT_STATUS_MESSAGE_FREQUENCY_MS ) ,
49- } ) ;
50-
51- const agentProviderSchema = z . enum ( [ "opencode" , "claudecode" , "codex" , "kimi" , "kiro" , "kilo" , "qwen" , "goose" , "gemini" ] ) ;
52-
53- const agentsSchema = z . object ( {
54- opencode : z . object ( {
55- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
56- models : z . array ( z . string ( ) ) . optional ( ) . default ( [ ] ) ,
57- } ) . optional ( ) . default ( { enabled : true , models : [ ] } ) ,
58- claudecode : z . object ( {
59- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
60- } ) . optional ( ) . default ( { enabled : true } ) ,
61- codex : z . object ( {
62- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
63- models : z . array ( z . string ( ) ) . optional ( ) . default ( [ ] ) ,
64- } ) . optional ( ) . default ( { enabled : true , models : [ ] } ) ,
65- kimi : z . object ( {
66- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
67- } ) . optional ( ) . default ( { enabled : true } ) ,
68- kiro : z . object ( {
69- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
70- } ) . optional ( ) . default ( { enabled : true } ) ,
71- kilo : z . object ( {
72- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
73- models : z . array ( z . string ( ) ) . optional ( ) . default ( [ ] ) ,
74- } ) . optional ( ) . default ( { enabled : true , models : [ ] } ) ,
75- qwen : z . object ( {
76- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
77- } ) . optional ( ) . default ( { enabled : true } ) ,
78- goose : z . object ( {
79- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
80- } ) . optional ( ) . default ( { enabled : true } ) ,
81- gemini : z . object ( {
82- enabled : z . boolean ( ) . optional ( ) . default ( true ) ,
83- } ) . optional ( ) . default ( { enabled : true } ) ,
84- } ) . optional ( ) . default ( {
85- opencode : { enabled : true , models : [ ] } ,
86- claudecode : { enabled : true } ,
87- codex : { enabled : true , models : [ ] } ,
88- kimi : { enabled : true } ,
89- kiro : { enabled : true } ,
90- kilo : { enabled : true , models : [ ] } ,
91- qwen : { enabled : true } ,
92- goose : { enabled : true } ,
93- gemini : { enabled : true } ,
94- } ) ;
95-
96- const channelDetailSchema = z . object ( {
97- id : z . string ( ) ,
98- name : z . string ( ) ,
99- agentProvider : z . preprocess (
100- ( value ) => ( value === "claude" ? "claudecode" : value ) ,
101- agentProviderSchema . optional ( ) . default ( "opencode" )
102- ) ,
103- model : z . string ( ) . optional ( ) . default ( "" ) ,
104- workingDirectory : z . string ( ) . optional ( ) . default ( "" ) ,
105- baseBranch : z . string ( ) . optional ( ) . default ( "main" ) ,
106- channelSystemMessage : z . string ( ) . optional ( ) . default ( "" ) ,
107- } ) ;
108-
10947const DEFAULT_UPDATE_INTERVAL_MS = 60 * 60 * 1000 ;
11048const MIN_UPDATE_INTERVAL_MS = 5 * 60 * 1000 ;
11149const DEFAULT_MESSAGE_UPDATE_INTERVAL_MS = DEFAULT_STATUS_MESSAGE_FREQUENCY_MS ;
11250const MIN_MESSAGE_UPDATE_INTERVAL_MS = 250 ;
11351export const DEFAULT_CODEX_MODEL = "gpt-5.3-codex" ;
11452
115- const updateSchema = z . object ( {
116- autoUpgrade : z . boolean ( ) . optional ( ) . default ( true ) ,
117- checkIntervalMs : z . number ( ) . optional ( ) . default ( DEFAULT_UPDATE_INTERVAL_MS ) ,
118- } ) ;
119-
120- const workspaceSchema = z . object ( {
121- id : z . string ( ) ,
122- type : z . enum ( [ "slack" , "discord" , "lark" ] ) . optional ( ) . default ( "slack" ) ,
123- name : z . string ( ) . optional ( ) . default ( "" ) ,
124- domain : z . string ( ) . optional ( ) . default ( "" ) ,
125- status : z . enum ( [ "active" , "paused" ] ) . optional ( ) . default ( "active" ) ,
126- channels : z . number ( ) . optional ( ) . default ( 0 ) ,
127- members : z . number ( ) . optional ( ) . default ( 0 ) ,
128- lastSync : z . string ( ) . optional ( ) . default ( "" ) ,
129- slackAppToken : z . string ( ) . optional ( ) . default ( "" ) ,
130- slackBotToken : z . string ( ) . optional ( ) . default ( "" ) ,
131- discordBotToken : z . string ( ) . optional ( ) . default ( "" ) ,
132- larkAppKey : z . string ( ) . optional ( ) . default ( "" ) ,
133- larkAppId : z . string ( ) . optional ( ) . default ( "" ) ,
134- larkAppSecret : z . string ( ) . optional ( ) . default ( "" ) ,
135- channelDetails : z . array ( channelDetailSchema ) . optional ( ) . default ( [ ] ) ,
136- } ) ;
137-
138- const odeConfigSchema = z . object ( {
139- user : userSchema ,
140- githubInfos : z
141- . record (
142- z . string ( ) ,
143- z . object ( {
144- token : z . string ( ) . optional ( ) . default ( "" ) ,
145- gitName : z . string ( ) . optional ( ) . default ( "" ) ,
146- gitEmail : z . string ( ) . optional ( ) . default ( "" ) ,
147- } )
148- )
149- . optional ( )
150- . default ( { } ) ,
151- agents : agentsSchema ,
152- completeOnboarding : z . boolean ( ) . optional ( ) . default ( false ) ,
153- workspaces : z . array ( workspaceSchema ) ,
154- updates : updateSchema . optional ( ) . default ( {
155- autoUpgrade : true ,
156- checkIntervalMs : DEFAULT_UPDATE_INTERVAL_MS ,
157- } ) ,
158- } ) ;
159-
160- export type ChannelDetail = z . infer < typeof channelDetailSchema > ;
161- export type WorkspaceConfig = z . infer < typeof workspaceSchema > ;
162- export type AgentProvider = z . infer < typeof agentProviderSchema > ;
163- export type AgentsConfig = z . infer < typeof agentsSchema > ;
164- export type UpdateConfig = z . infer < typeof updateSchema > ;
165- export type OdeConfig = z . infer < typeof odeConfigSchema > ;
166- export type UserConfig = z . infer < typeof userSchema > ;
167-
16853let cachedConfig : OdeConfig | null = null ;
16954
17055const EMPTY_TEMPLATE : OdeConfig = {
@@ -771,8 +656,7 @@ export function getChannelModel(channelId: string): string | null {
771656
772657export function getChannelAgentProvider ( channelId : string ) : AgentProvider {
773658 const provider = getChannelDetails ( channelId ) ?. agentProvider ;
774- if ( provider === "claudecode" || provider === "codex" || provider === "kimi" || provider === "kiro" || provider === "kilo" || provider === "qwen" || provider === "goose" || provider === "gemini" ) return provider ;
775- return "opencode" ;
659+ return isAgentProviderId ( provider ) ? provider : "opencode" ;
776660}
777661
778662export function setChannelModel ( channelId : string , model : string ) : void {
0 commit comments