@pooder/core 2.0.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 +6 -0
- package/dist/index.d.mts +100 -4
- package/dist/index.d.ts +100 -4
- package/dist/index.js +280 -4
- package/dist/index.mjs +278 -4
- package/package.json +1 -1
- package/src/command.ts +10 -10
- package/src/context.ts +17 -17
- package/src/contribution/index.ts +12 -12
- package/src/contribution/points.ts +27 -3
- package/src/contribution/registry.ts +118 -118
- package/src/disposable.ts +3 -3
- package/src/extension.ts +171 -164
- package/src/index.ts +161 -145
- package/src/run-test-full.ts +98 -98
- package/src/services/CommandService.ts +79 -79
- package/src/services/ConfigurationService.ts +107 -107
- package/src/services/ToolRegistryService.ts +41 -0
- package/src/services/ToolSessionService.ts +176 -0
- package/src/services/WorkbenchService.ts +138 -9
- package/src/services/index.ts +9 -1
- package/src/test-extension-full.ts +79 -79
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,14 +270,89 @@ 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>;
|
|
252
337
|
declare class WorkbenchService implements Service {
|
|
253
338
|
private _activeToolId;
|
|
254
339
|
private eventBus?;
|
|
340
|
+
private toolRegistry?;
|
|
341
|
+
private sessionService?;
|
|
342
|
+
private guards;
|
|
255
343
|
init(): void;
|
|
256
344
|
dispose(): void;
|
|
257
345
|
setEventBus(bus: EventBus): void;
|
|
346
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
347
|
+
setToolSessionService(sessionService: ToolSessionService): void;
|
|
258
348
|
get activeToolId(): string | null;
|
|
259
|
-
|
|
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>;
|
|
260
356
|
}
|
|
261
357
|
|
|
262
358
|
declare class Pooder {
|
|
@@ -274,4 +370,4 @@ declare class Pooder {
|
|
|
274
370
|
getContributions<T>(pointId: string): Contribution<T>[];
|
|
275
371
|
}
|
|
276
372
|
|
|
277
|
-
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 ToolContribution, type ViewContribution, WorkbenchService };
|
|
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,14 +270,89 @@ 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>;
|
|
252
337
|
declare class WorkbenchService implements Service {
|
|
253
338
|
private _activeToolId;
|
|
254
339
|
private eventBus?;
|
|
340
|
+
private toolRegistry?;
|
|
341
|
+
private sessionService?;
|
|
342
|
+
private guards;
|
|
255
343
|
init(): void;
|
|
256
344
|
dispose(): void;
|
|
257
345
|
setEventBus(bus: EventBus): void;
|
|
346
|
+
setToolRegistry(toolRegistry: ToolRegistryService): void;
|
|
347
|
+
setToolSessionService(sessionService: ToolSessionService): void;
|
|
258
348
|
get activeToolId(): string | null;
|
|
259
|
-
|
|
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>;
|
|
260
356
|
}
|
|
261
357
|
|
|
262
358
|
declare class Pooder {
|
|
@@ -274,4 +370,4 @@ declare class Pooder {
|
|
|
274
370
|
getContributions<T>(pointId: string): Contribution<T>[];
|
|
275
371
|
}
|
|
276
372
|
|
|
277
|
-
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 ToolContribution, type ViewContribution, WorkbenchService };
|
|
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
|
@@ -29,6 +29,8 @@ __export(index_exports, {
|
|
|
29
29
|
ExtensionRegistry: () => ExtensionRegistry,
|
|
30
30
|
Pooder: () => Pooder,
|
|
31
31
|
ServiceRegistry: () => ServiceRegistry,
|
|
32
|
+
ToolRegistryService: () => ToolRegistryService,
|
|
33
|
+
ToolSessionService: () => ToolSessionService,
|
|
32
34
|
WorkbenchService: () => WorkbenchService
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -280,6 +282,11 @@ var ExtensionManager = class {
|
|
|
280
282
|
const commandService = this.context.services.get("CommandService");
|
|
281
283
|
return commandService.registerCommand(item.id, item.data.handler);
|
|
282
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
|
+
}
|
|
283
290
|
}
|
|
284
291
|
unregister(name) {
|
|
285
292
|
const extension = this.extensionRegistry.get(name);
|
|
@@ -482,27 +489,286 @@ var ConfigurationService = class {
|
|
|
482
489
|
}
|
|
483
490
|
};
|
|
484
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
|
+
|
|
485
664
|
// src/services/WorkbenchService.ts
|
|
486
665
|
var WorkbenchService = class {
|
|
487
666
|
constructor() {
|
|
488
667
|
this._activeToolId = null;
|
|
668
|
+
this.guards = [];
|
|
489
669
|
}
|
|
490
670
|
init() {
|
|
491
671
|
}
|
|
492
672
|
dispose() {
|
|
673
|
+
this.guards = [];
|
|
493
674
|
}
|
|
494
675
|
setEventBus(bus) {
|
|
495
676
|
this.eventBus = bus;
|
|
496
677
|
}
|
|
678
|
+
setToolRegistry(toolRegistry) {
|
|
679
|
+
this.toolRegistry = toolRegistry;
|
|
680
|
+
}
|
|
681
|
+
setToolSessionService(sessionService) {
|
|
682
|
+
this.sessionService = sessionService;
|
|
683
|
+
}
|
|
497
684
|
get activeToolId() {
|
|
498
685
|
return this._activeToolId;
|
|
499
686
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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
|
+
}
|
|
503
760
|
const previous = this._activeToolId;
|
|
504
761
|
this._activeToolId = id;
|
|
505
|
-
|
|
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" });
|
|
506
772
|
}
|
|
507
773
|
};
|
|
508
774
|
|
|
@@ -517,8 +783,16 @@ var Pooder = class {
|
|
|
517
783
|
this.registerService(commandService, "CommandService");
|
|
518
784
|
const configurationService = new ConfigurationService();
|
|
519
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");
|
|
520
792
|
const workbenchService = new WorkbenchService();
|
|
521
793
|
workbenchService.setEventBus(this.eventBus);
|
|
794
|
+
workbenchService.setToolRegistry(toolRegistryService);
|
|
795
|
+
workbenchService.setToolSessionService(toolSessionService);
|
|
522
796
|
this.registerService(workbenchService, "WorkbenchService");
|
|
523
797
|
const context = {
|
|
524
798
|
eventBus: this.eventBus,
|
|
@@ -613,5 +887,7 @@ var Pooder = class {
|
|
|
613
887
|
ExtensionRegistry,
|
|
614
888
|
Pooder,
|
|
615
889
|
ServiceRegistry,
|
|
890
|
+
ToolRegistryService,
|
|
891
|
+
ToolSessionService,
|
|
616
892
|
WorkbenchService
|
|
617
893
|
});
|