33 getChannelAgentProvider ,
44 getChannelModel ,
55 resolveChannelCwd ,
6+ getWorkspaces ,
67 getEnabledAgentProviders ,
78 getOpenCodeModels ,
89 getCodexModels ,
@@ -18,14 +19,17 @@ import {
1819 setGitHubInfoForUser ,
1920 getUserGeneralSettings ,
2021 setUserGeneralSettings ,
22+ invalidateOdeConfigCache ,
2123} from "@/config" ;
2224import { startServer as startOpenCodeServer } from "@/agents/opencode" ;
2325import { startServer as startCodexServer } from "@/agents/codex" ;
26+ import { syncSlackWorkspace } from "@/core/web/local-settings" ;
2427
2528const SETTINGS_LAUNCH_ACTION = "open_settings_modal" ;
2629const SETTINGS_MODAL_ID = "settings_modal" ;
2730const GENERAL_SETTINGS_LAUNCH_ACTION = "open_general_settings_modal" ;
2831const GENERAL_SETTINGS_MODAL_ID = "general_settings_modal" ;
32+ const GENERAL_SYNC_WORKSPACE_ACTION = "general_sync_workspace" ;
2933const GITHUB_LAUNCH_ACTION = "open_github_token_modal" ;
3034const GITHUB_MODAL_ID = "github_token_modal" ;
3135const GITHUB_TOKEN_BLOCK = "github_token" ;
@@ -361,6 +365,18 @@ function buildGeneralSettingsModal(params: {
361365 ?? gitStrategyOptions [ 0 ] ,
362366 } ,
363367 } ,
368+ {
369+ type : "actions" as const ,
370+ elements : [
371+ {
372+ type : "button" as const ,
373+ action_id : GENERAL_SYNC_WORKSPACE_ACTION ,
374+ text : { type : "plain_text" as const , text : "Sync Workspace" } ,
375+ style : "primary" as const ,
376+ value : channelId ,
377+ } ,
378+ ] ,
379+ } ,
364380 ] ,
365381 } ;
366382}
@@ -447,6 +463,40 @@ export function setupInteractiveHandlers(): void {
447463 } ) ;
448464 } ) ;
449465
466+ slackApp . action ( GENERAL_SYNC_WORKSPACE_ACTION , async ( { ack, body, client } ) => {
467+ await ack ( ) ;
468+
469+ const channelId = ( body as any ) . actions ?. [ 0 ] ?. value
470+ ?? ( body as any ) . view ?. private_metadata
471+ ?? ( body as any ) . channel ?. id ;
472+ const userId = ( body as any ) . user ?. id ;
473+ if ( ! channelId || ! userId ) return ;
474+
475+ const workspaces = getWorkspaces ( ) ;
476+ const syncResults = await Promise . allSettled (
477+ workspaces . map ( async ( workspace ) => syncSlackWorkspace ( workspace . id ) )
478+ ) ;
479+
480+ const successful = syncResults
481+ . filter ( ( result ) : result is PromiseFulfilledResult < Awaited < ReturnType < typeof syncSlackWorkspace > > > => result . status === "fulfilled" )
482+ . map ( ( result ) => result . value ) ;
483+ const syncedWorkspaces = successful . length ;
484+ const syncedChannels = successful . reduce ( ( sum , workspace ) => sum + ( workspace . channels ?? workspace . channelDetails . length ) , 0 ) ;
485+ const failedWorkspaces = syncResults . length - syncedWorkspaces ;
486+
487+ invalidateOdeConfigCache ( ) ;
488+
489+ const message = failedWorkspaces > 0
490+ ? `Synced ${ syncedWorkspaces } workspaces with ${ syncedChannels } channels in total. Failed to sync ${ failedWorkspaces } workspaces.`
491+ : `Synced ${ syncedWorkspaces } workspaces with ${ syncedChannels } channels in total.` ;
492+
493+ await client . chat . postEphemeral ( {
494+ channel : channelId ,
495+ user : userId ,
496+ text : message ,
497+ } ) ;
498+ } ) ;
499+
450500 slackApp . action ( PROVIDER_ACTION , async ( { ack, body, client } ) => {
451501 await ack ( ) ;
452502
0 commit comments