@@ -16,37 +16,60 @@ import { forceSelectModel } from "./semantic/summariser";
1616import { syncTagsFromConfig } from "./tags/tagSync" ;
1717import { setupFileWatchers } from "./watchers" ;
1818import { PrivateTaskDecorationProvider } from "./tree/PrivateTaskDecorationProvider" ;
19+ import { appState } from "./state" ;
1920
2021const MAKE_EXECUTABLE_COMMAND = "commandtree.makeExecutable" ;
2122const EXECUTE_PERMISSION_BITS = 0o111 ;
2223const WINDOWS_PLATFORM = "win32" ;
2324
24- let treeProvider : CommandTreeProvider ;
25- let quickTasksProvider : QuickTasksProvider ;
26- let taskRunner : TaskRunner ;
27-
2825export interface ExtensionExports {
2926 commandTreeProvider : CommandTreeProvider ;
3027 quickTasksProvider : QuickTasksProvider ;
3128}
3229
30+ function getTreeProvider ( ) : CommandTreeProvider {
31+ if ( appState . treeProvider === undefined ) {
32+ throw new Error ( "CommandTree extension not activated" ) ;
33+ }
34+ return appState . treeProvider ;
35+ }
36+
37+ function getQuickTasksProvider ( ) : QuickTasksProvider {
38+ if ( appState . quickTasksProvider === undefined ) {
39+ throw new Error ( "CommandTree extension not activated" ) ;
40+ }
41+ return appState . quickTasksProvider ;
42+ }
43+
44+ function getTaskRunner ( ) : TaskRunner {
45+ if ( appState . taskRunner === undefined ) {
46+ throw new Error ( "CommandTree extension not activated" ) ;
47+ }
48+ return appState . taskRunner ;
49+ }
50+
3351export async function activate ( context : vscode . ExtensionContext ) : Promise < ExtensionExports | undefined > {
3452 const workspaceRoot = vscode . workspace . workspaceFolders ?. [ 0 ] ?. uri . fsPath ;
3553 logger . info ( "Extension activating" , { workspaceRoot } ) ;
3654 if ( workspaceRoot === undefined ) {
3755 logger . warn ( "No workspace root found, extension not activating" ) ;
3856 return undefined ;
3957 }
40- await initDatabaseSafe ( workspaceRoot ) ;
41- treeProvider = new CommandTreeProvider ( workspaceRoot ) ;
42- quickTasksProvider = new QuickTasksProvider ( ) ;
43- taskRunner = new TaskRunner ( ) ;
58+ if ( appState . activated && appState . treeProvider !== undefined && appState . quickTasksProvider !== undefined ) {
59+ logger . info ( "Extension already activated; reusing existing state" ) ;
60+ return { commandTreeProvider : appState . treeProvider , quickTasksProvider : appState . quickTasksProvider } ;
61+ }
62+ appState . treeProvider = new CommandTreeProvider ( workspaceRoot ) ;
63+ appState . quickTasksProvider = new QuickTasksProvider ( ) ;
64+ appState . taskRunner = new TaskRunner ( ) ;
65+ appState . activated = true ;
4466 registerTreeViews ( context ) ;
4567 registerCommands ( context ) ;
4668 setupWatchers ( context , workspaceRoot ) ;
69+ await initDatabaseSafe ( workspaceRoot ) ;
4770 runBackgroundStartup ( workspaceRoot ) ;
4871 logger . info ( "Extension activation complete" ) ;
49- return { commandTreeProvider : treeProvider , quickTasksProvider } ;
72+ return { commandTreeProvider : appState . treeProvider , quickTasksProvider : appState . quickTasksProvider } ;
5073}
5174
5275function runBackgroundStartup ( workspaceRoot : string ) : void {
@@ -90,22 +113,24 @@ function setupWatchers(context: vscode.ExtensionContext, workspaceRoot: string):
90113
91114async function initialDiscovery ( workspaceRoot : string ) : Promise < void > {
92115 await syncQuickTasks ( ) ;
93- logger . info ( "syncQuickTasks complete" , { taskCount : treeProvider . getAllTasks ( ) . length } ) ;
116+ logger . info ( "syncQuickTasks complete" , { taskCount : getTreeProvider ( ) . getAllTasks ( ) . length } ) ;
94117 await registerDiscoveredCommands ( workspaceRoot ) ;
95118 await syncTagsFromJson ( workspaceRoot ) ;
96119}
97120
98121function registerTreeViews ( context : vscode . ExtensionContext ) : void {
122+ const tp = getTreeProvider ( ) ;
123+ const qp = getQuickTasksProvider ( ) ;
99124 context . subscriptions . push (
100125 vscode . window . createTreeView ( "commandtree" , {
101- treeDataProvider : treeProvider ,
126+ treeDataProvider : tp ,
102127 showCollapseAll : true ,
103- dragAndDropController : treeProvider ,
128+ dragAndDropController : tp ,
104129 } ) ,
105130 vscode . window . createTreeView ( "commandtree-quick" , {
106- treeDataProvider : quickTasksProvider ,
131+ treeDataProvider : qp ,
107132 showCollapseAll : true ,
108- dragAndDropController : quickTasksProvider ,
133+ dragAndDropController : qp ,
109134 } ) ,
110135 vscode . window . registerFileDecorationProvider ( new PrivateTaskDecorationProvider ( ) )
111136 ) ;
@@ -123,18 +148,18 @@ function registerCommands(context: vscode.ExtensionContext): void {
123148function registerCoreCommands ( context : vscode . ExtensionContext ) : void {
124149 context . subscriptions . push (
125150 vscode . commands . registerCommand ( "commandtree.refresh" , async ( ) => {
126- await treeProvider . refresh ( ) ;
127- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
151+ await getTreeProvider ( ) . refresh ( ) ;
152+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
128153 vscode . window . showInformationMessage ( "CommandTree refreshed" ) ;
129154 } ) ,
130155 vscode . commands . registerCommand ( "commandtree.run" , async ( item : CommandTreeItem | undefined ) => {
131156 if ( item !== undefined && isCommandItem ( item . data ) ) {
132- await taskRunner . run ( item . data , "newTerminal" ) ;
157+ await getTaskRunner ( ) . run ( item . data , "newTerminal" ) ;
133158 }
134159 } ) ,
135160 vscode . commands . registerCommand ( "commandtree.runInCurrentTerminal" , async ( item : CommandTreeItem | undefined ) => {
136161 if ( item !== undefined && isCommandItem ( item . data ) ) {
137- await taskRunner . run ( item . data , "currentTerminal" ) ;
162+ await getTaskRunner ( ) . run ( item . data , "currentTerminal" ) ;
138163 }
139164 } ) ,
140165 vscode . commands . registerCommand ( "commandtree.openPreview" , async ( item : CommandTreeItem | undefined ) => {
@@ -160,7 +185,7 @@ function registerFilterCommands(context: vscode.ExtensionContext): void {
160185 context . subscriptions . push (
161186 vscode . commands . registerCommand ( "commandtree.filterByTag" , handleFilterByTag ) ,
162187 vscode . commands . registerCommand ( "commandtree.clearFilter" , ( ) => {
163- treeProvider . clearFilters ( ) ;
188+ getTreeProvider ( ) . clearFilters ( ) ;
164189 updateFilterContext ( ) ;
165190 } ) ,
166191 vscode . commands . registerCommand ( "commandtree.generateSummaries" , async ( ) => {
@@ -198,9 +223,9 @@ function registerQuickCommands(context: vscode.ExtensionContext): void {
198223 async ( item : CommandTreeItem | CommandItem | undefined ) => {
199224 const task = extractTask ( item ) ;
200225 if ( task !== undefined ) {
201- quickTasksProvider . addToQuick ( task ) ;
202- await treeProvider . refresh ( ) ;
203- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
226+ getQuickTasksProvider ( ) . addToQuick ( task ) ;
227+ await getTreeProvider ( ) . refresh ( ) ;
228+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
204229 }
205230 }
206231 ) ,
@@ -209,20 +234,20 @@ function registerQuickCommands(context: vscode.ExtensionContext): void {
209234 async ( item : CommandTreeItem | CommandItem | undefined ) => {
210235 const task = extractTask ( item ) ;
211236 if ( task !== undefined ) {
212- quickTasksProvider . removeFromQuick ( task ) ;
213- await treeProvider . refresh ( ) ;
214- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
237+ getQuickTasksProvider ( ) . removeFromQuick ( task ) ;
238+ await getTreeProvider ( ) . refresh ( ) ;
239+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
215240 }
216241 }
217242 ) ,
218243 vscode . commands . registerCommand ( "commandtree.refreshQuick" , ( ) => {
219- quickTasksProvider . refresh ( ) ;
244+ getQuickTasksProvider ( ) . refresh ( ) ;
220245 } )
221246 ) ;
222247}
223248
224249async function handleFilterByTag ( ) : Promise < void > {
225- const tags = treeProvider . getAllTags ( ) ;
250+ const tags = getTreeProvider ( ) . getAllTags ( ) ;
226251 if ( tags . length === 0 ) {
227252 await vscode . window . showInformationMessage ( "No tags defined. Right-click commands to add tags." ) ;
228253 return ;
@@ -235,7 +260,7 @@ async function handleFilterByTag(): Promise<void> {
235260 placeHolder : "Select tag to filter by" ,
236261 } ) ;
237262 if ( selected ) {
238- treeProvider . setTagFilter ( selected . tag ) ;
263+ getTreeProvider ( ) . setTagFilter ( selected . tag ) ;
239264 updateFilterContext ( ) ;
240265 }
241266}
@@ -296,12 +321,12 @@ async function handleAddTag(item: CommandTreeItem | CommandItem | undefined, tag
296321 if ( task === undefined ) {
297322 return ;
298323 }
299- const tagName = tagNameArg ?? ( await pickOrCreateTag ( treeProvider . getAllTags ( ) , task . label ) ) ;
324+ const tagName = tagNameArg ?? ( await pickOrCreateTag ( getTreeProvider ( ) . getAllTags ( ) , task . label ) ) ;
300325 if ( tagName === undefined || tagName === "" ) {
301326 return ;
302327 }
303- await treeProvider . addTaskToTag ( task , tagName ) ;
304- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
328+ await getTreeProvider ( ) . addTaskToTag ( task , tagName ) ;
329+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
305330}
306331
307332async function handleRemoveTag ( item : CommandTreeItem | CommandItem | undefined , tagNameArg ?: string ) : Promise < void > {
@@ -324,22 +349,22 @@ async function handleRemoveTag(item: CommandTreeItem | CommandItem | undefined,
324349 }
325350 tagToRemove = selected . tag ;
326351 }
327- await treeProvider . removeTaskFromTag ( task , tagToRemove ) ;
328- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
352+ await getTreeProvider ( ) . removeTaskFromTag ( task , tagToRemove ) ;
353+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
329354}
330355
331356async function syncQuickTasks ( ) : Promise < void > {
332- await treeProvider . refresh ( ) ;
333- const allTasks = treeProvider . getAllTasks ( ) ;
334- quickTasksProvider . updateTasks ( allTasks ) ;
357+ await getTreeProvider ( ) . refresh ( ) ;
358+ const allTasks = getTreeProvider ( ) . getAllTasks ( ) ;
359+ getQuickTasksProvider ( ) . updateTasks ( allTasks ) ;
335360}
336361
337362async function syncTagsFromJson ( workspaceRoot : string ) : Promise < void > {
338- const allTasks = treeProvider . getAllTasks ( ) ;
363+ const allTasks = getTreeProvider ( ) . getAllTasks ( ) ;
339364 const synced = syncTagsFromConfig ( { allTasks, workspaceRoot } ) ;
340365 if ( synced ) {
341- await treeProvider . refresh ( ) ;
342- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
366+ await getTreeProvider ( ) . refresh ( ) ;
367+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
343368 }
344369}
345370
@@ -370,7 +395,7 @@ async function pickOrCreateTag(existingTags: string[], taskLabel: string): Promi
370395}
371396
372397async function registerDiscoveredCommands ( workspaceRoot : string ) : Promise < void > {
373- const tasks = treeProvider . getAllTasks ( ) ;
398+ const tasks = getTreeProvider ( ) . getAllTasks ( ) ;
374399 if ( tasks . length === 0 ) {
375400 return ;
376401 }
@@ -400,7 +425,7 @@ function initAiSummaries(workspaceRoot: string): void {
400425}
401426
402427async function runSummarisation ( workspaceRoot : string ) : Promise < void > {
403- const tasks = treeProvider . getAllTasks ( ) ;
428+ const tasks = getTreeProvider ( ) . getAllTasks ( ) ;
404429 logger . info ( "[SUMMARY] Starting" , { taskCount : tasks . length } ) ;
405430 if ( tasks . length === 0 ) {
406431 logger . warn ( "[SUMMARY] No tasks to summarise" ) ;
@@ -420,8 +445,8 @@ async function runSummarisation(workspaceRoot: string): Promise<void> {
420445 return ;
421446 }
422447 if ( summaryResult . value > 0 ) {
423- await treeProvider . refresh ( ) ;
424- quickTasksProvider . updateTasks ( treeProvider . getAllTasks ( ) ) ;
448+ await getTreeProvider ( ) . refresh ( ) ;
449+ getQuickTasksProvider ( ) . updateTasks ( getTreeProvider ( ) . getAllTasks ( ) ) ;
425450 }
426451 vscode . window . showInformationMessage ( `CommandTree: Summarised ${ summaryResult . value } commands` ) ;
427452}
@@ -436,7 +461,7 @@ async function syncAndSummarise(workspaceRoot: string): Promise<void> {
436461}
437462
438463function updateFilterContext ( ) : void {
439- vscode . commands . executeCommand ( "setContext" , "commandtree.hasFilter" , treeProvider . hasFilter ( ) ) ;
464+ vscode . commands . executeCommand ( "setContext" , "commandtree.hasFilter" , getTreeProvider ( ) . hasFilter ( ) ) ;
440465}
441466
442467export function deactivate ( ) : void {
0 commit comments