@pooder/core 1.2.0 → 2.1.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/CHANGELOG.md +12 -0
- package/dist/index.d.mts +109 -3
- package/dist/index.d.ts +109 -3
- package/dist/index.js +309 -2
- package/dist/index.mjs +304 -1
- package/package.json +1 -1
- package/src/contribution/points.ts +27 -3
- package/src/extension.ts +7 -0
- package/src/index.ts +22 -1
- package/src/services/ToolRegistryService.ts +41 -0
- package/src/services/ToolSessionService.ts +176 -0
- package/src/services/WorkbenchService.ts +159 -0
- package/src/services/index.ts +10 -1
- package/src/test-extension-full.ts +3 -3
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -37,12 +37,33 @@ interface CommandContribution {
|
|
|
37
37
|
/**
|
|
38
38
|
* Tool Contribution Data Definition
|
|
39
39
|
*/
|
|
40
|
+
type ToolInteraction = "instant" | "session" | "hybrid";
|
|
41
|
+
type ToolSessionLeavePolicy = "block" | "commit" | "rollback";
|
|
42
|
+
interface ToolCommandBindings {
|
|
43
|
+
execute?: string;
|
|
44
|
+
begin?: string;
|
|
45
|
+
validate?: string;
|
|
46
|
+
commit?: string;
|
|
47
|
+
rollback?: string;
|
|
48
|
+
reset?: string;
|
|
49
|
+
}
|
|
40
50
|
interface ToolContribution {
|
|
41
51
|
id: string;
|
|
42
52
|
name: string;
|
|
43
|
-
description
|
|
53
|
+
description?: string;
|
|
54
|
+
icon?: string;
|
|
55
|
+
interaction: ToolInteraction;
|
|
44
56
|
parameters?: Record<string, any>;
|
|
45
|
-
|
|
57
|
+
commands?: ToolCommandBindings;
|
|
58
|
+
view?: {
|
|
59
|
+
id?: string;
|
|
60
|
+
type?: "sidebar" | "panel" | "editor" | "dialog";
|
|
61
|
+
location?: string;
|
|
62
|
+
};
|
|
63
|
+
session?: {
|
|
64
|
+
autoBegin?: boolean;
|
|
65
|
+
leavePolicy?: ToolSessionLeavePolicy;
|
|
66
|
+
};
|
|
46
67
|
}
|
|
47
68
|
/**
|
|
48
69
|
* View Contribution Data Definition
|
|
@@ -249,6 +270,91 @@ declare class ConfigurationService implements Service {
|
|
|
249
270
|
dispose(): void;
|
|
250
271
|
}
|
|
251
272
|
|
|
273
|
+
declare class ToolRegistryService implements Service {
|
|
274
|
+
private tools;
|
|
275
|
+
registerTool(tool: ToolContribution): Disposable;
|
|
276
|
+
unregisterTool(toolId: string): void;
|
|
277
|
+
getTool(toolId: string): ToolContribution | undefined;
|
|
278
|
+
listTools(): ToolContribution[];
|
|
279
|
+
hasTool(toolId: string): boolean;
|
|
280
|
+
dispose(): void;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
type ToolSessionStatus = "idle" | "active";
|
|
284
|
+
interface ToolSessionState {
|
|
285
|
+
toolId: string;
|
|
286
|
+
status: ToolSessionStatus;
|
|
287
|
+
dirty: boolean;
|
|
288
|
+
startedAt?: number;
|
|
289
|
+
lastUpdatedAt?: number;
|
|
290
|
+
}
|
|
291
|
+
type LeaveDecision = "allow" | "blocked";
|
|
292
|
+
interface LeaveResult {
|
|
293
|
+
decision: LeaveDecision;
|
|
294
|
+
reason?: string;
|
|
295
|
+
}
|
|
296
|
+
declare class ToolSessionService implements Service {
|
|
297
|
+
private readonly sessions;
|
|
298
|
+
private commandService?;
|
|
299
|
+
private toolRegistry?;
|
|
300
|
+
setCommandService(commandService: CommandService): void;
|
|
301
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
302
|
+
registerDirtyTracker(toolId: string, callback: () => boolean): Disposable;
|
|
303
|
+
private readonly dirtyTrackers;
|
|
304
|
+
private ensureSession;
|
|
305
|
+
getState(toolId: string): ToolSessionState;
|
|
306
|
+
isDirty(toolId: string): boolean;
|
|
307
|
+
markDirty(toolId: string, dirty?: boolean): void;
|
|
308
|
+
private resolveTool;
|
|
309
|
+
private runCommand;
|
|
310
|
+
begin(toolId: string): Promise<void>;
|
|
311
|
+
validate(toolId: string): Promise<{
|
|
312
|
+
ok: boolean;
|
|
313
|
+
result?: any;
|
|
314
|
+
}>;
|
|
315
|
+
commit(toolId: string): Promise<{
|
|
316
|
+
ok: boolean;
|
|
317
|
+
result?: any;
|
|
318
|
+
}>;
|
|
319
|
+
rollback(toolId: string): Promise<void>;
|
|
320
|
+
deactivateSession(toolId: string): void;
|
|
321
|
+
handleBeforeLeave(toolId: string): Promise<LeaveResult>;
|
|
322
|
+
dispose(): void;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface ToolSwitchContext {
|
|
326
|
+
from: string | null;
|
|
327
|
+
to: string | null;
|
|
328
|
+
reason?: string;
|
|
329
|
+
}
|
|
330
|
+
interface ToolSwitchResult {
|
|
331
|
+
ok: boolean;
|
|
332
|
+
from: string | null;
|
|
333
|
+
to: string | null;
|
|
334
|
+
reason?: string;
|
|
335
|
+
}
|
|
336
|
+
type ToolSwitchGuard = (context: ToolSwitchContext) => boolean | Promise<boolean>;
|
|
337
|
+
declare class WorkbenchService implements Service {
|
|
338
|
+
private _activeToolId;
|
|
339
|
+
private eventBus?;
|
|
340
|
+
private toolRegistry?;
|
|
341
|
+
private sessionService?;
|
|
342
|
+
private guards;
|
|
343
|
+
init(): void;
|
|
344
|
+
dispose(): void;
|
|
345
|
+
setEventBus(bus: EventBus): void;
|
|
346
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
347
|
+
setToolSessionService(sessionService: ToolSessionService): void;
|
|
348
|
+
get activeToolId(): string | null;
|
|
349
|
+
registerSwitchGuard(guard: ToolSwitchGuard, priority?: number): Disposable;
|
|
350
|
+
private runGuards;
|
|
351
|
+
switchTool(id: string | null, options?: {
|
|
352
|
+
reason?: string;
|
|
353
|
+
}): Promise<ToolSwitchResult>;
|
|
354
|
+
activate(id: string | null): Promise<ToolSwitchResult>;
|
|
355
|
+
deactivate(): Promise<ToolSwitchResult>;
|
|
356
|
+
}
|
|
357
|
+
|
|
252
358
|
declare class Pooder {
|
|
253
359
|
readonly eventBus: EventBus;
|
|
254
360
|
private readonly services;
|
|
@@ -264,4 +370,4 @@ declare class Pooder {
|
|
|
264
370
|
getContributions<T>(pointId: string): Contribution<T>[];
|
|
265
371
|
}
|
|
266
372
|
|
|
267
|
-
export { type CommandContribution, CommandService, type ConfigurationContribution, ConfigurationService, type Contribution, type ContributionMetadata, type ContributionPoint, ContributionPointIds, ContributionRegistry, type Extension, type ExtensionContext, ExtensionManager, type ExtensionMetadata, ExtensionRegistry, Pooder, type Service, ServiceRegistry, type ToolContribution, type ViewContribution };
|
|
373
|
+
export { type CommandContribution, CommandService, type ConfigurationContribution, ConfigurationService, type Contribution, type ContributionMetadata, type ContributionPoint, ContributionPointIds, ContributionRegistry, EventBus, type Extension, type ExtensionContext, ExtensionManager, type ExtensionMetadata, ExtensionRegistry, Pooder, type Service, ServiceRegistry, type ToolCommandBindings, type ToolContribution, type ToolInteraction, ToolRegistryService, type ToolSessionLeavePolicy, ToolSessionService, type ViewContribution, WorkbenchService };
|
package/dist/index.d.ts
CHANGED
|
@@ -37,12 +37,33 @@ interface CommandContribution {
|
|
|
37
37
|
/**
|
|
38
38
|
* Tool Contribution Data Definition
|
|
39
39
|
*/
|
|
40
|
+
type ToolInteraction = "instant" | "session" | "hybrid";
|
|
41
|
+
type ToolSessionLeavePolicy = "block" | "commit" | "rollback";
|
|
42
|
+
interface ToolCommandBindings {
|
|
43
|
+
execute?: string;
|
|
44
|
+
begin?: string;
|
|
45
|
+
validate?: string;
|
|
46
|
+
commit?: string;
|
|
47
|
+
rollback?: string;
|
|
48
|
+
reset?: string;
|
|
49
|
+
}
|
|
40
50
|
interface ToolContribution {
|
|
41
51
|
id: string;
|
|
42
52
|
name: string;
|
|
43
|
-
description
|
|
53
|
+
description?: string;
|
|
54
|
+
icon?: string;
|
|
55
|
+
interaction: ToolInteraction;
|
|
44
56
|
parameters?: Record<string, any>;
|
|
45
|
-
|
|
57
|
+
commands?: ToolCommandBindings;
|
|
58
|
+
view?: {
|
|
59
|
+
id?: string;
|
|
60
|
+
type?: "sidebar" | "panel" | "editor" | "dialog";
|
|
61
|
+
location?: string;
|
|
62
|
+
};
|
|
63
|
+
session?: {
|
|
64
|
+
autoBegin?: boolean;
|
|
65
|
+
leavePolicy?: ToolSessionLeavePolicy;
|
|
66
|
+
};
|
|
46
67
|
}
|
|
47
68
|
/**
|
|
48
69
|
* View Contribution Data Definition
|
|
@@ -249,6 +270,91 @@ declare class ConfigurationService implements Service {
|
|
|
249
270
|
dispose(): void;
|
|
250
271
|
}
|
|
251
272
|
|
|
273
|
+
declare class ToolRegistryService implements Service {
|
|
274
|
+
private tools;
|
|
275
|
+
registerTool(tool: ToolContribution): Disposable;
|
|
276
|
+
unregisterTool(toolId: string): void;
|
|
277
|
+
getTool(toolId: string): ToolContribution | undefined;
|
|
278
|
+
listTools(): ToolContribution[];
|
|
279
|
+
hasTool(toolId: string): boolean;
|
|
280
|
+
dispose(): void;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
type ToolSessionStatus = "idle" | "active";
|
|
284
|
+
interface ToolSessionState {
|
|
285
|
+
toolId: string;
|
|
286
|
+
status: ToolSessionStatus;
|
|
287
|
+
dirty: boolean;
|
|
288
|
+
startedAt?: number;
|
|
289
|
+
lastUpdatedAt?: number;
|
|
290
|
+
}
|
|
291
|
+
type LeaveDecision = "allow" | "blocked";
|
|
292
|
+
interface LeaveResult {
|
|
293
|
+
decision: LeaveDecision;
|
|
294
|
+
reason?: string;
|
|
295
|
+
}
|
|
296
|
+
declare class ToolSessionService implements Service {
|
|
297
|
+
private readonly sessions;
|
|
298
|
+
private commandService?;
|
|
299
|
+
private toolRegistry?;
|
|
300
|
+
setCommandService(commandService: CommandService): void;
|
|
301
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
302
|
+
registerDirtyTracker(toolId: string, callback: () => boolean): Disposable;
|
|
303
|
+
private readonly dirtyTrackers;
|
|
304
|
+
private ensureSession;
|
|
305
|
+
getState(toolId: string): ToolSessionState;
|
|
306
|
+
isDirty(toolId: string): boolean;
|
|
307
|
+
markDirty(toolId: string, dirty?: boolean): void;
|
|
308
|
+
private resolveTool;
|
|
309
|
+
private runCommand;
|
|
310
|
+
begin(toolId: string): Promise<void>;
|
|
311
|
+
validate(toolId: string): Promise<{
|
|
312
|
+
ok: boolean;
|
|
313
|
+
result?: any;
|
|
314
|
+
}>;
|
|
315
|
+
commit(toolId: string): Promise<{
|
|
316
|
+
ok: boolean;
|
|
317
|
+
result?: any;
|
|
318
|
+
}>;
|
|
319
|
+
rollback(toolId: string): Promise<void>;
|
|
320
|
+
deactivateSession(toolId: string): void;
|
|
321
|
+
handleBeforeLeave(toolId: string): Promise<LeaveResult>;
|
|
322
|
+
dispose(): void;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
interface ToolSwitchContext {
|
|
326
|
+
from: string | null;
|
|
327
|
+
to: string | null;
|
|
328
|
+
reason?: string;
|
|
329
|
+
}
|
|
330
|
+
interface ToolSwitchResult {
|
|
331
|
+
ok: boolean;
|
|
332
|
+
from: string | null;
|
|
333
|
+
to: string | null;
|
|
334
|
+
reason?: string;
|
|
335
|
+
}
|
|
336
|
+
type ToolSwitchGuard = (context: ToolSwitchContext) => boolean | Promise<boolean>;
|
|
337
|
+
declare class WorkbenchService implements Service {
|
|
338
|
+
private _activeToolId;
|
|
339
|
+
private eventBus?;
|
|
340
|
+
private toolRegistry?;
|
|
341
|
+
private sessionService?;
|
|
342
|
+
private guards;
|
|
343
|
+
init(): void;
|
|
344
|
+
dispose(): void;
|
|
345
|
+
setEventBus(bus: EventBus): void;
|
|
346
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
347
|
+
setToolSessionService(sessionService: ToolSessionService): void;
|
|
348
|
+
get activeToolId(): string | null;
|
|
349
|
+
registerSwitchGuard(guard: ToolSwitchGuard, priority?: number): Disposable;
|
|
350
|
+
private runGuards;
|
|
351
|
+
switchTool(id: string | null, options?: {
|
|
352
|
+
reason?: string;
|
|
353
|
+
}): Promise<ToolSwitchResult>;
|
|
354
|
+
activate(id: string | null): Promise<ToolSwitchResult>;
|
|
355
|
+
deactivate(): Promise<ToolSwitchResult>;
|
|
356
|
+
}
|
|
357
|
+
|
|
252
358
|
declare class Pooder {
|
|
253
359
|
readonly eventBus: EventBus;
|
|
254
360
|
private readonly services;
|
|
@@ -264,4 +370,4 @@ declare class Pooder {
|
|
|
264
370
|
getContributions<T>(pointId: string): Contribution<T>[];
|
|
265
371
|
}
|
|
266
372
|
|
|
267
|
-
export { type CommandContribution, CommandService, type ConfigurationContribution, ConfigurationService, type Contribution, type ContributionMetadata, type ContributionPoint, ContributionPointIds, ContributionRegistry, type Extension, type ExtensionContext, ExtensionManager, type ExtensionMetadata, ExtensionRegistry, Pooder, type Service, ServiceRegistry, type ToolContribution, type ViewContribution };
|
|
373
|
+
export { type CommandContribution, CommandService, type ConfigurationContribution, ConfigurationService, type Contribution, type ContributionMetadata, type ContributionPoint, ContributionPointIds, ContributionRegistry, EventBus, type Extension, type ExtensionContext, ExtensionManager, type ExtensionMetadata, ExtensionRegistry, Pooder, type Service, ServiceRegistry, type ToolCommandBindings, type ToolContribution, type ToolInteraction, ToolRegistryService, type ToolSessionLeavePolicy, ToolSessionService, type ViewContribution, WorkbenchService };
|
package/dist/index.js
CHANGED
|
@@ -24,10 +24,14 @@ __export(index_exports, {
|
|
|
24
24
|
ConfigurationService: () => ConfigurationService,
|
|
25
25
|
ContributionPointIds: () => ContributionPointIds,
|
|
26
26
|
ContributionRegistry: () => ContributionRegistry,
|
|
27
|
+
EventBus: () => event_default,
|
|
27
28
|
ExtensionManager: () => ExtensionManager,
|
|
28
29
|
ExtensionRegistry: () => ExtensionRegistry,
|
|
29
30
|
Pooder: () => Pooder,
|
|
30
|
-
ServiceRegistry: () => ServiceRegistry
|
|
31
|
+
ServiceRegistry: () => ServiceRegistry,
|
|
32
|
+
ToolRegistryService: () => ToolRegistryService,
|
|
33
|
+
ToolSessionService: () => ToolSessionService,
|
|
34
|
+
WorkbenchService: () => WorkbenchService
|
|
31
35
|
});
|
|
32
36
|
module.exports = __toCommonJS(index_exports);
|
|
33
37
|
|
|
@@ -278,6 +282,11 @@ var ExtensionManager = class {
|
|
|
278
282
|
const commandService = this.context.services.get("CommandService");
|
|
279
283
|
return commandService.registerCommand(item.id, item.data.handler);
|
|
280
284
|
}
|
|
285
|
+
if (pointId === ContributionPointIds.TOOLS) {
|
|
286
|
+
const toolRegistry = this.context.services.get("ToolRegistryService");
|
|
287
|
+
if (!toolRegistry) return;
|
|
288
|
+
return toolRegistry.registerTool(item.data);
|
|
289
|
+
}
|
|
281
290
|
}
|
|
282
291
|
unregister(name) {
|
|
283
292
|
const extension = this.extensionRegistry.get(name);
|
|
@@ -480,6 +489,289 @@ var ConfigurationService = class {
|
|
|
480
489
|
}
|
|
481
490
|
};
|
|
482
491
|
|
|
492
|
+
// src/services/ToolRegistryService.ts
|
|
493
|
+
var ToolRegistryService = class {
|
|
494
|
+
constructor() {
|
|
495
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
496
|
+
}
|
|
497
|
+
registerTool(tool) {
|
|
498
|
+
if (!(tool == null ? void 0 : tool.id)) {
|
|
499
|
+
throw new Error("ToolContribution.id is required.");
|
|
500
|
+
}
|
|
501
|
+
this.tools.set(tool.id, tool);
|
|
502
|
+
return {
|
|
503
|
+
dispose: () => {
|
|
504
|
+
if (this.tools.get(tool.id) === tool) {
|
|
505
|
+
this.tools.delete(tool.id);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
unregisterTool(toolId) {
|
|
511
|
+
this.tools.delete(toolId);
|
|
512
|
+
}
|
|
513
|
+
getTool(toolId) {
|
|
514
|
+
return this.tools.get(toolId);
|
|
515
|
+
}
|
|
516
|
+
listTools() {
|
|
517
|
+
return Array.from(this.tools.values());
|
|
518
|
+
}
|
|
519
|
+
hasTool(toolId) {
|
|
520
|
+
return this.tools.has(toolId);
|
|
521
|
+
}
|
|
522
|
+
dispose() {
|
|
523
|
+
this.tools.clear();
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/services/ToolSessionService.ts
|
|
528
|
+
var ToolSessionService = class {
|
|
529
|
+
constructor() {
|
|
530
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
531
|
+
this.dirtyTrackers = /* @__PURE__ */ new Map();
|
|
532
|
+
}
|
|
533
|
+
setCommandService(commandService) {
|
|
534
|
+
this.commandService = commandService;
|
|
535
|
+
}
|
|
536
|
+
setToolRegistry(toolRegistry) {
|
|
537
|
+
this.toolRegistry = toolRegistry;
|
|
538
|
+
}
|
|
539
|
+
registerDirtyTracker(toolId, callback) {
|
|
540
|
+
const wrapped = () => {
|
|
541
|
+
try {
|
|
542
|
+
return callback();
|
|
543
|
+
} catch (e) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
this.dirtyTrackers.set(toolId, wrapped);
|
|
548
|
+
return {
|
|
549
|
+
dispose: () => {
|
|
550
|
+
if (this.dirtyTrackers.get(toolId) === wrapped) {
|
|
551
|
+
this.dirtyTrackers.delete(toolId);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
ensureSession(toolId) {
|
|
557
|
+
const existing = this.sessions.get(toolId);
|
|
558
|
+
if (existing) return existing;
|
|
559
|
+
const created = {
|
|
560
|
+
toolId,
|
|
561
|
+
status: "idle",
|
|
562
|
+
dirty: false
|
|
563
|
+
};
|
|
564
|
+
this.sessions.set(toolId, created);
|
|
565
|
+
return created;
|
|
566
|
+
}
|
|
567
|
+
getState(toolId) {
|
|
568
|
+
return { ...this.ensureSession(toolId) };
|
|
569
|
+
}
|
|
570
|
+
isDirty(toolId) {
|
|
571
|
+
const tracker = this.dirtyTrackers.get(toolId);
|
|
572
|
+
if (tracker) return tracker();
|
|
573
|
+
return this.ensureSession(toolId).dirty;
|
|
574
|
+
}
|
|
575
|
+
markDirty(toolId, dirty = true) {
|
|
576
|
+
const session = this.ensureSession(toolId);
|
|
577
|
+
session.dirty = dirty;
|
|
578
|
+
session.lastUpdatedAt = Date.now();
|
|
579
|
+
}
|
|
580
|
+
resolveTool(toolId) {
|
|
581
|
+
var _a;
|
|
582
|
+
return (_a = this.toolRegistry) == null ? void 0 : _a.getTool(toolId);
|
|
583
|
+
}
|
|
584
|
+
async runCommand(commandId, ...args) {
|
|
585
|
+
if (!commandId || !this.commandService) return void 0;
|
|
586
|
+
return await this.commandService.executeCommand(commandId, ...args);
|
|
587
|
+
}
|
|
588
|
+
async begin(toolId) {
|
|
589
|
+
var _a;
|
|
590
|
+
const tool = this.resolveTool(toolId);
|
|
591
|
+
const session = this.ensureSession(toolId);
|
|
592
|
+
if (session.status === "active") return;
|
|
593
|
+
await this.runCommand((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.begin);
|
|
594
|
+
session.status = "active";
|
|
595
|
+
session.startedAt = Date.now();
|
|
596
|
+
session.lastUpdatedAt = session.startedAt;
|
|
597
|
+
}
|
|
598
|
+
async validate(toolId) {
|
|
599
|
+
var _a;
|
|
600
|
+
const tool = this.resolveTool(toolId);
|
|
601
|
+
if (!((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.validate)) {
|
|
602
|
+
return { ok: true };
|
|
603
|
+
}
|
|
604
|
+
const result = await this.runCommand(tool.commands.validate);
|
|
605
|
+
if (result === false) return { ok: false, result };
|
|
606
|
+
if (result && typeof result === "object" && "ok" in result) {
|
|
607
|
+
return { ok: Boolean(result.ok), result };
|
|
608
|
+
}
|
|
609
|
+
return { ok: true, result };
|
|
610
|
+
}
|
|
611
|
+
async commit(toolId) {
|
|
612
|
+
var _a;
|
|
613
|
+
const tool = this.resolveTool(toolId);
|
|
614
|
+
const validateResult = await this.validate(toolId);
|
|
615
|
+
if (!validateResult.ok) return validateResult;
|
|
616
|
+
const result = await this.runCommand((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.commit);
|
|
617
|
+
const session = this.ensureSession(toolId);
|
|
618
|
+
session.dirty = false;
|
|
619
|
+
session.status = "idle";
|
|
620
|
+
session.lastUpdatedAt = Date.now();
|
|
621
|
+
return { ok: true, result };
|
|
622
|
+
}
|
|
623
|
+
async rollback(toolId) {
|
|
624
|
+
var _a, _b;
|
|
625
|
+
const tool = this.resolveTool(toolId);
|
|
626
|
+
await this.runCommand(((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.rollback) || ((_b = tool == null ? void 0 : tool.commands) == null ? void 0 : _b.reset));
|
|
627
|
+
const session = this.ensureSession(toolId);
|
|
628
|
+
session.dirty = false;
|
|
629
|
+
session.status = "idle";
|
|
630
|
+
session.lastUpdatedAt = Date.now();
|
|
631
|
+
}
|
|
632
|
+
deactivateSession(toolId) {
|
|
633
|
+
const session = this.ensureSession(toolId);
|
|
634
|
+
session.status = "idle";
|
|
635
|
+
session.lastUpdatedAt = Date.now();
|
|
636
|
+
}
|
|
637
|
+
async handleBeforeLeave(toolId) {
|
|
638
|
+
var _a, _b;
|
|
639
|
+
const tool = this.resolveTool(toolId);
|
|
640
|
+
if (!tool) return { decision: "allow" };
|
|
641
|
+
if (tool.interaction !== "session") return { decision: "allow" };
|
|
642
|
+
const dirty = this.isDirty(toolId);
|
|
643
|
+
if (!dirty) return { decision: "allow" };
|
|
644
|
+
const leavePolicy = (_b = (_a = tool.session) == null ? void 0 : _a.leavePolicy) != null ? _b : "block";
|
|
645
|
+
if (leavePolicy === "commit") {
|
|
646
|
+
const committed = await this.commit(toolId);
|
|
647
|
+
if (!committed.ok) {
|
|
648
|
+
return { decision: "blocked", reason: "session-validation-failed" };
|
|
649
|
+
}
|
|
650
|
+
return { decision: "allow" };
|
|
651
|
+
}
|
|
652
|
+
if (leavePolicy === "rollback") {
|
|
653
|
+
await this.rollback(toolId);
|
|
654
|
+
return { decision: "allow" };
|
|
655
|
+
}
|
|
656
|
+
return { decision: "blocked", reason: "session-dirty" };
|
|
657
|
+
}
|
|
658
|
+
dispose() {
|
|
659
|
+
this.sessions.clear();
|
|
660
|
+
this.dirtyTrackers.clear();
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
// src/services/WorkbenchService.ts
|
|
665
|
+
var WorkbenchService = class {
|
|
666
|
+
constructor() {
|
|
667
|
+
this._activeToolId = null;
|
|
668
|
+
this.guards = [];
|
|
669
|
+
}
|
|
670
|
+
init() {
|
|
671
|
+
}
|
|
672
|
+
dispose() {
|
|
673
|
+
this.guards = [];
|
|
674
|
+
}
|
|
675
|
+
setEventBus(bus) {
|
|
676
|
+
this.eventBus = bus;
|
|
677
|
+
}
|
|
678
|
+
setToolRegistry(toolRegistry) {
|
|
679
|
+
this.toolRegistry = toolRegistry;
|
|
680
|
+
}
|
|
681
|
+
setToolSessionService(sessionService) {
|
|
682
|
+
this.sessionService = sessionService;
|
|
683
|
+
}
|
|
684
|
+
get activeToolId() {
|
|
685
|
+
return this._activeToolId;
|
|
686
|
+
}
|
|
687
|
+
registerSwitchGuard(guard, priority = 0) {
|
|
688
|
+
const item = { guard, priority };
|
|
689
|
+
this.guards.push(item);
|
|
690
|
+
this.guards.sort((a, b) => b.priority - a.priority);
|
|
691
|
+
return {
|
|
692
|
+
dispose: () => {
|
|
693
|
+
const index = this.guards.indexOf(item);
|
|
694
|
+
if (index >= 0) this.guards.splice(index, 1);
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
async runGuards(context) {
|
|
699
|
+
for (const { guard } of this.guards) {
|
|
700
|
+
const allowed = await Promise.resolve(guard(context));
|
|
701
|
+
if (!allowed) return false;
|
|
702
|
+
}
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
705
|
+
async switchTool(id, options) {
|
|
706
|
+
var _a, _b, _c, _d, _e;
|
|
707
|
+
if (this._activeToolId === id) {
|
|
708
|
+
return { ok: true, from: this._activeToolId, to: id };
|
|
709
|
+
}
|
|
710
|
+
if (id && this.toolRegistry && !this.toolRegistry.hasTool(id)) {
|
|
711
|
+
return {
|
|
712
|
+
ok: false,
|
|
713
|
+
from: this._activeToolId,
|
|
714
|
+
to: id,
|
|
715
|
+
reason: `tool-not-registered:${id}`
|
|
716
|
+
};
|
|
717
|
+
}
|
|
718
|
+
const context = {
|
|
719
|
+
from: this._activeToolId,
|
|
720
|
+
to: id,
|
|
721
|
+
reason: options == null ? void 0 : options.reason
|
|
722
|
+
};
|
|
723
|
+
const guardAllowed = await this.runGuards(context);
|
|
724
|
+
if (!guardAllowed) {
|
|
725
|
+
(_a = this.eventBus) == null ? void 0 : _a.emit("tool:switch:blocked", {
|
|
726
|
+
...context,
|
|
727
|
+
reason: "blocked-by-guard"
|
|
728
|
+
});
|
|
729
|
+
return {
|
|
730
|
+
ok: false,
|
|
731
|
+
from: this._activeToolId,
|
|
732
|
+
to: id,
|
|
733
|
+
reason: "blocked-by-guard"
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
if (context.from && this.sessionService) {
|
|
737
|
+
const leaveResult = await this.sessionService.handleBeforeLeave(
|
|
738
|
+
context.from
|
|
739
|
+
);
|
|
740
|
+
if (leaveResult.decision === "blocked") {
|
|
741
|
+
(_b = this.eventBus) == null ? void 0 : _b.emit("tool:switch:blocked", {
|
|
742
|
+
...context,
|
|
743
|
+
reason: leaveResult.reason || "session-blocked"
|
|
744
|
+
});
|
|
745
|
+
return {
|
|
746
|
+
ok: false,
|
|
747
|
+
from: this._activeToolId,
|
|
748
|
+
to: id,
|
|
749
|
+
reason: leaveResult.reason || "session-blocked"
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
this.sessionService.deactivateSession(context.from);
|
|
753
|
+
}
|
|
754
|
+
if (id && this.sessionService && this.toolRegistry) {
|
|
755
|
+
const tool = this.toolRegistry.getTool(id);
|
|
756
|
+
if ((tool == null ? void 0 : tool.interaction) === "session" && ((_c = tool.session) == null ? void 0 : _c.autoBegin) !== false) {
|
|
757
|
+
await this.sessionService.begin(id);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
const previous = this._activeToolId;
|
|
761
|
+
this._activeToolId = id;
|
|
762
|
+
const reason = options == null ? void 0 : options.reason;
|
|
763
|
+
(_d = this.eventBus) == null ? void 0 : _d.emit("tool:activated", { id, previous, reason });
|
|
764
|
+
(_e = this.eventBus) == null ? void 0 : _e.emit("tool:switch", { from: previous, to: id, reason });
|
|
765
|
+
return { ok: true, from: previous, to: id };
|
|
766
|
+
}
|
|
767
|
+
async activate(id) {
|
|
768
|
+
return await this.switchTool(id, { reason: "activate" });
|
|
769
|
+
}
|
|
770
|
+
async deactivate() {
|
|
771
|
+
return await this.switchTool(null, { reason: "deactivate" });
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
|
|
483
775
|
// src/index.ts
|
|
484
776
|
var Pooder = class {
|
|
485
777
|
constructor() {
|
|
@@ -491,6 +783,17 @@ var Pooder = class {
|
|
|
491
783
|
this.registerService(commandService, "CommandService");
|
|
492
784
|
const configurationService = new ConfigurationService();
|
|
493
785
|
this.registerService(configurationService, "ConfigurationService");
|
|
786
|
+
const toolRegistryService = new ToolRegistryService();
|
|
787
|
+
this.registerService(toolRegistryService, "ToolRegistryService");
|
|
788
|
+
const toolSessionService = new ToolSessionService();
|
|
789
|
+
toolSessionService.setCommandService(commandService);
|
|
790
|
+
toolSessionService.setToolRegistry(toolRegistryService);
|
|
791
|
+
this.registerService(toolSessionService, "ToolSessionService");
|
|
792
|
+
const workbenchService = new WorkbenchService();
|
|
793
|
+
workbenchService.setEventBus(this.eventBus);
|
|
794
|
+
workbenchService.setToolRegistry(toolRegistryService);
|
|
795
|
+
workbenchService.setToolSessionService(toolSessionService);
|
|
796
|
+
this.registerService(workbenchService, "WorkbenchService");
|
|
494
797
|
const context = {
|
|
495
798
|
eventBus: this.eventBus,
|
|
496
799
|
services: {
|
|
@@ -579,8 +882,12 @@ var Pooder = class {
|
|
|
579
882
|
ConfigurationService,
|
|
580
883
|
ContributionPointIds,
|
|
581
884
|
ContributionRegistry,
|
|
885
|
+
EventBus,
|
|
582
886
|
ExtensionManager,
|
|
583
887
|
ExtensionRegistry,
|
|
584
888
|
Pooder,
|
|
585
|
-
ServiceRegistry
|
|
889
|
+
ServiceRegistry,
|
|
890
|
+
ToolRegistryService,
|
|
891
|
+
ToolSessionService,
|
|
892
|
+
WorkbenchService
|
|
586
893
|
});
|