@pooder/core 2.0.0 → 2.2.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 +196 -21
- package/dist/index.d.ts +196 -21
- package/dist/index.js +718 -157
- package/dist/index.mjs +707 -156
- package/package.json +1 -1
- package/src/command.ts +10 -10
- package/src/context.ts +22 -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 +177 -164
- package/src/index.ts +338 -145
- package/src/run-test-full.ts +98 -98
- package/src/service.ts +191 -11
- 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 +213 -0
- package/src/services/WorkbenchService.ts +187 -8
- package/src/services/index.ts +23 -1
- package/src/services/tokens.ts +27 -0
- package/src/test-extension-full.ts +79 -79
package/dist/index.mjs
CHANGED
|
@@ -1,20 +1,108 @@
|
|
|
1
1
|
// src/service.ts
|
|
2
|
+
function createServiceToken(name) {
|
|
3
|
+
if (!name) {
|
|
4
|
+
throw new Error("Service token name is required.");
|
|
5
|
+
}
|
|
6
|
+
return Object.freeze({
|
|
7
|
+
kind: "service-token",
|
|
8
|
+
key: Symbol(name),
|
|
9
|
+
name
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function isServiceToken(identifier) {
|
|
13
|
+
return typeof identifier === "object" && identifier !== null && "kind" in identifier && identifier.kind === "service-token";
|
|
14
|
+
}
|
|
2
15
|
var ServiceRegistry = class {
|
|
3
16
|
constructor() {
|
|
4
|
-
this.
|
|
17
|
+
this.servicesByName = /* @__PURE__ */ new Map();
|
|
18
|
+
this.servicesByToken = /* @__PURE__ */ new Map();
|
|
19
|
+
this.registrationOrder = [];
|
|
5
20
|
}
|
|
6
|
-
register(
|
|
7
|
-
this.
|
|
21
|
+
register(identifier, service, options = {}) {
|
|
22
|
+
const normalized = this.normalizeIdentifier(identifier);
|
|
23
|
+
const existing = this.findEntry(normalized);
|
|
24
|
+
if (existing && !options.allowOverride) {
|
|
25
|
+
throw new Error(`Service "${normalized.name}" is already registered.`);
|
|
26
|
+
}
|
|
27
|
+
if (existing) {
|
|
28
|
+
this.removeEntry(existing);
|
|
29
|
+
}
|
|
30
|
+
const entry = {
|
|
31
|
+
token: normalized.token,
|
|
32
|
+
name: normalized.name,
|
|
33
|
+
service
|
|
34
|
+
};
|
|
35
|
+
this.servicesByName.set(entry.name, entry);
|
|
36
|
+
if (entry.token) {
|
|
37
|
+
this.servicesByToken.set(entry.token.key, entry);
|
|
38
|
+
}
|
|
39
|
+
this.registrationOrder.push(entry);
|
|
8
40
|
return service;
|
|
9
41
|
}
|
|
10
|
-
get(
|
|
11
|
-
|
|
42
|
+
get(identifier) {
|
|
43
|
+
const normalized = this.normalizeIdentifier(identifier);
|
|
44
|
+
const entry = this.findEntry(normalized);
|
|
45
|
+
return entry == null ? void 0 : entry.service;
|
|
46
|
+
}
|
|
47
|
+
getOrThrow(identifier, errorMessage) {
|
|
48
|
+
const service = this.get(identifier);
|
|
49
|
+
if (service) {
|
|
50
|
+
return service;
|
|
51
|
+
}
|
|
52
|
+
const normalized = this.normalizeIdentifier(identifier);
|
|
53
|
+
throw new Error(errorMessage != null ? errorMessage : `Service "${normalized.name}" not found.`);
|
|
12
54
|
}
|
|
13
|
-
has(
|
|
14
|
-
|
|
55
|
+
has(identifier) {
|
|
56
|
+
const normalized = this.normalizeIdentifier(identifier);
|
|
57
|
+
return Boolean(this.findEntry(normalized));
|
|
15
58
|
}
|
|
16
|
-
delete(
|
|
17
|
-
this.
|
|
59
|
+
delete(identifier) {
|
|
60
|
+
const normalized = this.normalizeIdentifier(identifier);
|
|
61
|
+
const entry = this.findEntry(normalized);
|
|
62
|
+
if (!entry) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
this.removeEntry(entry);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
list() {
|
|
69
|
+
return this.registrationOrder.map((entry) => ({
|
|
70
|
+
id: entry.name,
|
|
71
|
+
token: entry.token,
|
|
72
|
+
service: entry.service
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
clear() {
|
|
76
|
+
this.servicesByName.clear();
|
|
77
|
+
this.servicesByToken.clear();
|
|
78
|
+
this.registrationOrder.length = 0;
|
|
79
|
+
}
|
|
80
|
+
findEntry(identifier) {
|
|
81
|
+
var _a;
|
|
82
|
+
if (identifier.token) {
|
|
83
|
+
return (_a = this.servicesByToken.get(identifier.token.key)) != null ? _a : this.servicesByName.get(identifier.name);
|
|
84
|
+
}
|
|
85
|
+
return this.servicesByName.get(identifier.name);
|
|
86
|
+
}
|
|
87
|
+
normalizeIdentifier(identifier) {
|
|
88
|
+
if (isServiceToken(identifier)) {
|
|
89
|
+
return { token: identifier, name: identifier.name };
|
|
90
|
+
}
|
|
91
|
+
const name = identifier.trim();
|
|
92
|
+
if (!name) {
|
|
93
|
+
throw new Error("Service identifier must be a non-empty string.");
|
|
94
|
+
}
|
|
95
|
+
return { name };
|
|
96
|
+
}
|
|
97
|
+
removeEntry(entry) {
|
|
98
|
+
this.servicesByName.delete(entry.name);
|
|
99
|
+
if (entry.token) {
|
|
100
|
+
this.servicesByToken.delete(entry.token.key);
|
|
101
|
+
}
|
|
102
|
+
const index = this.registrationOrder.lastIndexOf(entry);
|
|
103
|
+
if (index >= 0) {
|
|
104
|
+
this.registrationOrder.splice(index, 1);
|
|
105
|
+
}
|
|
18
106
|
}
|
|
19
107
|
};
|
|
20
108
|
|
|
@@ -172,122 +260,6 @@ var ContributionRegistry = class {
|
|
|
172
260
|
}
|
|
173
261
|
};
|
|
174
262
|
|
|
175
|
-
// src/extension.ts
|
|
176
|
-
var ExtensionRegistry = class extends Map {
|
|
177
|
-
};
|
|
178
|
-
var ExtensionManager = class {
|
|
179
|
-
constructor(context) {
|
|
180
|
-
this.extensionRegistry = new ExtensionRegistry();
|
|
181
|
-
this.extensionDisposables = /* @__PURE__ */ new Map();
|
|
182
|
-
this.context = context;
|
|
183
|
-
}
|
|
184
|
-
register(extension) {
|
|
185
|
-
if (this.extensionRegistry.has(extension.id)) {
|
|
186
|
-
console.warn(
|
|
187
|
-
`Plugin "${extension.id}" already registered. It will be overwritten.`
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
this.extensionDisposables.set(extension.id, []);
|
|
191
|
-
const disposables = this.extensionDisposables.get(extension.id);
|
|
192
|
-
if (extension.contribute) {
|
|
193
|
-
for (const [pointId, items] of Object.entries(extension.contribute())) {
|
|
194
|
-
if (Array.isArray(items)) {
|
|
195
|
-
items.forEach((item, index) => {
|
|
196
|
-
const contributionId = item.id || (item.command ? item.command : `${extension.id}.${pointId}.${index}`);
|
|
197
|
-
const contribution = {
|
|
198
|
-
id: contributionId,
|
|
199
|
-
metadata: {
|
|
200
|
-
extensionId: extension.id,
|
|
201
|
-
...item == null ? void 0 : item.metadata
|
|
202
|
-
},
|
|
203
|
-
data: item
|
|
204
|
-
};
|
|
205
|
-
const disposable = this.context.contributions.register(
|
|
206
|
-
pointId,
|
|
207
|
-
contribution
|
|
208
|
-
);
|
|
209
|
-
disposables.push(disposable);
|
|
210
|
-
const dispose = this.collectContribution(pointId, contribution);
|
|
211
|
-
if (dispose) {
|
|
212
|
-
disposables.push(dispose);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
try {
|
|
219
|
-
this.extensionRegistry.set(extension.id, extension);
|
|
220
|
-
this.context.eventBus.emit("extension:register", extension);
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.error(
|
|
223
|
-
`Error in onCreate hook for plugin "${extension.id}":`,
|
|
224
|
-
error
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
try {
|
|
228
|
-
extension.activate(this.context);
|
|
229
|
-
} catch (error) {
|
|
230
|
-
console.error(
|
|
231
|
-
`Error in onActivate hook for plugin "${extension.id}":`,
|
|
232
|
-
error
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
console.log(`Plugin "${extension.id}" registered successfully`);
|
|
236
|
-
}
|
|
237
|
-
collectContribution(pointId, item) {
|
|
238
|
-
if (pointId === ContributionPointIds.CONFIGURATIONS) {
|
|
239
|
-
const configService = this.context.services.get(
|
|
240
|
-
"ConfigurationService"
|
|
241
|
-
);
|
|
242
|
-
configService == null ? void 0 : configService.initializeDefaults([item.data]);
|
|
243
|
-
}
|
|
244
|
-
if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
|
|
245
|
-
const commandService = this.context.services.get("CommandService");
|
|
246
|
-
return commandService.registerCommand(item.id, item.data.handler);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
unregister(name) {
|
|
250
|
-
const extension = this.extensionRegistry.get(name);
|
|
251
|
-
if (!extension) {
|
|
252
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
try {
|
|
256
|
-
extension.deactivate(this.context);
|
|
257
|
-
} catch (error) {
|
|
258
|
-
console.error(`Error in deactivate for plugin "${name}":`, error);
|
|
259
|
-
}
|
|
260
|
-
const disposables = this.extensionDisposables.get(name);
|
|
261
|
-
if (disposables) {
|
|
262
|
-
disposables.forEach((d) => d.dispose());
|
|
263
|
-
this.extensionDisposables.delete(name);
|
|
264
|
-
}
|
|
265
|
-
this.extensionRegistry.delete(name);
|
|
266
|
-
console.log(`Plugin "${name}" unregistered`);
|
|
267
|
-
return true;
|
|
268
|
-
}
|
|
269
|
-
enable(name) {
|
|
270
|
-
const extension = this.extensionRegistry.get(name);
|
|
271
|
-
if (!extension) {
|
|
272
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
disable(name) {
|
|
277
|
-
const extension = this.extensionRegistry.get(name);
|
|
278
|
-
if (!extension) {
|
|
279
|
-
console.warn(`Plugin "${name}" not found.`);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
update() {
|
|
284
|
-
}
|
|
285
|
-
destroy() {
|
|
286
|
-
const extensionNames = Array.from(this.extensionRegistry.keys());
|
|
287
|
-
extensionNames.forEach((name) => this.unregister(name));
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
|
|
291
263
|
// src/services/CommandService.ts
|
|
292
264
|
var CommandService = class {
|
|
293
265
|
constructor() {
|
|
@@ -447,27 +419,486 @@ var ConfigurationService = class {
|
|
|
447
419
|
}
|
|
448
420
|
};
|
|
449
421
|
|
|
422
|
+
// src/services/ToolRegistryService.ts
|
|
423
|
+
var ToolRegistryService = class {
|
|
424
|
+
constructor() {
|
|
425
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
426
|
+
}
|
|
427
|
+
registerTool(tool) {
|
|
428
|
+
if (!(tool == null ? void 0 : tool.id)) {
|
|
429
|
+
throw new Error("ToolContribution.id is required.");
|
|
430
|
+
}
|
|
431
|
+
this.tools.set(tool.id, tool);
|
|
432
|
+
return {
|
|
433
|
+
dispose: () => {
|
|
434
|
+
if (this.tools.get(tool.id) === tool) {
|
|
435
|
+
this.tools.delete(tool.id);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
unregisterTool(toolId) {
|
|
441
|
+
this.tools.delete(toolId);
|
|
442
|
+
}
|
|
443
|
+
getTool(toolId) {
|
|
444
|
+
return this.tools.get(toolId);
|
|
445
|
+
}
|
|
446
|
+
listTools() {
|
|
447
|
+
return Array.from(this.tools.values());
|
|
448
|
+
}
|
|
449
|
+
hasTool(toolId) {
|
|
450
|
+
return this.tools.has(toolId);
|
|
451
|
+
}
|
|
452
|
+
dispose() {
|
|
453
|
+
this.tools.clear();
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
// src/services/tokens.ts
|
|
458
|
+
var COMMAND_SERVICE = createServiceToken(
|
|
459
|
+
"CommandService"
|
|
460
|
+
);
|
|
461
|
+
var CONFIGURATION_SERVICE = createServiceToken(
|
|
462
|
+
"ConfigurationService"
|
|
463
|
+
);
|
|
464
|
+
var TOOL_REGISTRY_SERVICE = createServiceToken("ToolRegistryService");
|
|
465
|
+
var TOOL_SESSION_SERVICE = createServiceToken("ToolSessionService");
|
|
466
|
+
var WORKBENCH_SERVICE = createServiceToken("WorkbenchService");
|
|
467
|
+
var CORE_SERVICE_TOKENS = {
|
|
468
|
+
COMMAND: COMMAND_SERVICE,
|
|
469
|
+
CONFIGURATION: CONFIGURATION_SERVICE,
|
|
470
|
+
TOOL_REGISTRY: TOOL_REGISTRY_SERVICE,
|
|
471
|
+
TOOL_SESSION: TOOL_SESSION_SERVICE,
|
|
472
|
+
WORKBENCH: WORKBENCH_SERVICE
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// src/services/ToolSessionService.ts
|
|
476
|
+
var ToolSessionService = class {
|
|
477
|
+
constructor(dependencies = {}) {
|
|
478
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
479
|
+
this.dirtyTrackers = /* @__PURE__ */ new Map();
|
|
480
|
+
this.commandService = dependencies.commandService;
|
|
481
|
+
this.toolRegistry = dependencies.toolRegistry;
|
|
482
|
+
}
|
|
483
|
+
init(context) {
|
|
484
|
+
var _a, _b;
|
|
485
|
+
(_a = this.commandService) != null ? _a : this.commandService = context.get(COMMAND_SERVICE);
|
|
486
|
+
(_b = this.toolRegistry) != null ? _b : this.toolRegistry = context.get(TOOL_REGISTRY_SERVICE);
|
|
487
|
+
if (!this.commandService) {
|
|
488
|
+
throw new Error("ToolSessionService requires CommandService.");
|
|
489
|
+
}
|
|
490
|
+
if (!this.toolRegistry) {
|
|
491
|
+
throw new Error("ToolSessionService requires ToolRegistryService.");
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
setCommandService(commandService) {
|
|
495
|
+
this.commandService = commandService;
|
|
496
|
+
}
|
|
497
|
+
setToolRegistry(toolRegistry) {
|
|
498
|
+
this.toolRegistry = toolRegistry;
|
|
499
|
+
}
|
|
500
|
+
registerDirtyTracker(toolId, callback) {
|
|
501
|
+
const wrapped = () => {
|
|
502
|
+
try {
|
|
503
|
+
return callback();
|
|
504
|
+
} catch (e) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
this.dirtyTrackers.set(toolId, wrapped);
|
|
509
|
+
return {
|
|
510
|
+
dispose: () => {
|
|
511
|
+
if (this.dirtyTrackers.get(toolId) === wrapped) {
|
|
512
|
+
this.dirtyTrackers.delete(toolId);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
ensureSession(toolId) {
|
|
518
|
+
const existing = this.sessions.get(toolId);
|
|
519
|
+
if (existing) return existing;
|
|
520
|
+
const created = {
|
|
521
|
+
toolId,
|
|
522
|
+
status: "idle",
|
|
523
|
+
dirty: false
|
|
524
|
+
};
|
|
525
|
+
this.sessions.set(toolId, created);
|
|
526
|
+
return created;
|
|
527
|
+
}
|
|
528
|
+
getState(toolId) {
|
|
529
|
+
return { ...this.ensureSession(toolId) };
|
|
530
|
+
}
|
|
531
|
+
isDirty(toolId) {
|
|
532
|
+
const tracker = this.dirtyTrackers.get(toolId);
|
|
533
|
+
if (tracker) return tracker();
|
|
534
|
+
return this.ensureSession(toolId).dirty;
|
|
535
|
+
}
|
|
536
|
+
markDirty(toolId, dirty = true) {
|
|
537
|
+
const session = this.ensureSession(toolId);
|
|
538
|
+
session.dirty = dirty;
|
|
539
|
+
session.lastUpdatedAt = Date.now();
|
|
540
|
+
}
|
|
541
|
+
resolveTool(toolId) {
|
|
542
|
+
return this.getToolRegistry().getTool(toolId);
|
|
543
|
+
}
|
|
544
|
+
async runCommand(commandId, ...args) {
|
|
545
|
+
if (!commandId) return void 0;
|
|
546
|
+
return await this.getCommandService().executeCommand(commandId, ...args);
|
|
547
|
+
}
|
|
548
|
+
getCommandService() {
|
|
549
|
+
if (!this.commandService) {
|
|
550
|
+
throw new Error("ToolSessionService is not initialized.");
|
|
551
|
+
}
|
|
552
|
+
return this.commandService;
|
|
553
|
+
}
|
|
554
|
+
getToolRegistry() {
|
|
555
|
+
if (!this.toolRegistry) {
|
|
556
|
+
throw new Error("ToolSessionService is not initialized.");
|
|
557
|
+
}
|
|
558
|
+
return this.toolRegistry;
|
|
559
|
+
}
|
|
560
|
+
async begin(toolId) {
|
|
561
|
+
var _a;
|
|
562
|
+
const tool = this.resolveTool(toolId);
|
|
563
|
+
const session = this.ensureSession(toolId);
|
|
564
|
+
if (session.status === "active") return;
|
|
565
|
+
await this.runCommand((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.begin);
|
|
566
|
+
session.status = "active";
|
|
567
|
+
session.startedAt = Date.now();
|
|
568
|
+
session.lastUpdatedAt = session.startedAt;
|
|
569
|
+
}
|
|
570
|
+
async validate(toolId) {
|
|
571
|
+
var _a;
|
|
572
|
+
const tool = this.resolveTool(toolId);
|
|
573
|
+
if (!((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.validate)) {
|
|
574
|
+
return { ok: true };
|
|
575
|
+
}
|
|
576
|
+
const result = await this.runCommand(tool.commands.validate);
|
|
577
|
+
if (result === false) return { ok: false, result };
|
|
578
|
+
if (result && typeof result === "object" && "ok" in result) {
|
|
579
|
+
return { ok: Boolean(result.ok), result };
|
|
580
|
+
}
|
|
581
|
+
return { ok: true, result };
|
|
582
|
+
}
|
|
583
|
+
async commit(toolId) {
|
|
584
|
+
var _a;
|
|
585
|
+
const tool = this.resolveTool(toolId);
|
|
586
|
+
const validateResult = await this.validate(toolId);
|
|
587
|
+
if (!validateResult.ok) return validateResult;
|
|
588
|
+
const result = await this.runCommand((_a = tool == null ? void 0 : tool.commands) == null ? void 0 : _a.commit);
|
|
589
|
+
const session = this.ensureSession(toolId);
|
|
590
|
+
session.dirty = false;
|
|
591
|
+
session.status = "idle";
|
|
592
|
+
session.lastUpdatedAt = Date.now();
|
|
593
|
+
return { ok: true, result };
|
|
594
|
+
}
|
|
595
|
+
async rollback(toolId) {
|
|
596
|
+
var _a, _b;
|
|
597
|
+
const tool = this.resolveTool(toolId);
|
|
598
|
+
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));
|
|
599
|
+
const session = this.ensureSession(toolId);
|
|
600
|
+
session.dirty = false;
|
|
601
|
+
session.status = "idle";
|
|
602
|
+
session.lastUpdatedAt = Date.now();
|
|
603
|
+
}
|
|
604
|
+
deactivateSession(toolId) {
|
|
605
|
+
const session = this.ensureSession(toolId);
|
|
606
|
+
session.status = "idle";
|
|
607
|
+
session.lastUpdatedAt = Date.now();
|
|
608
|
+
}
|
|
609
|
+
async handleBeforeLeave(toolId) {
|
|
610
|
+
var _a, _b;
|
|
611
|
+
const tool = this.resolveTool(toolId);
|
|
612
|
+
if (!tool) return { decision: "allow" };
|
|
613
|
+
if (tool.interaction !== "session") return { decision: "allow" };
|
|
614
|
+
const dirty = this.isDirty(toolId);
|
|
615
|
+
if (!dirty) return { decision: "allow" };
|
|
616
|
+
const leavePolicy = (_b = (_a = tool.session) == null ? void 0 : _a.leavePolicy) != null ? _b : "block";
|
|
617
|
+
if (leavePolicy === "commit") {
|
|
618
|
+
const committed = await this.commit(toolId);
|
|
619
|
+
if (!committed.ok) {
|
|
620
|
+
return { decision: "blocked", reason: "session-validation-failed" };
|
|
621
|
+
}
|
|
622
|
+
return { decision: "allow" };
|
|
623
|
+
}
|
|
624
|
+
if (leavePolicy === "rollback") {
|
|
625
|
+
await this.rollback(toolId);
|
|
626
|
+
return { decision: "allow" };
|
|
627
|
+
}
|
|
628
|
+
return { decision: "blocked", reason: "session-dirty" };
|
|
629
|
+
}
|
|
630
|
+
dispose() {
|
|
631
|
+
this.sessions.clear();
|
|
632
|
+
this.dirtyTrackers.clear();
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
450
636
|
// src/services/WorkbenchService.ts
|
|
451
637
|
var WorkbenchService = class {
|
|
452
|
-
constructor() {
|
|
638
|
+
constructor(dependencies = {}) {
|
|
453
639
|
this._activeToolId = null;
|
|
640
|
+
this.guards = [];
|
|
641
|
+
this.eventBus = dependencies.eventBus;
|
|
642
|
+
this.toolRegistry = dependencies.toolRegistry;
|
|
643
|
+
this.sessionService = dependencies.sessionService;
|
|
454
644
|
}
|
|
455
|
-
init() {
|
|
645
|
+
init(context) {
|
|
646
|
+
var _a, _b, _c;
|
|
647
|
+
(_a = this.eventBus) != null ? _a : this.eventBus = context.eventBus;
|
|
648
|
+
(_b = this.toolRegistry) != null ? _b : this.toolRegistry = context.get(TOOL_REGISTRY_SERVICE);
|
|
649
|
+
(_c = this.sessionService) != null ? _c : this.sessionService = context.get(TOOL_SESSION_SERVICE);
|
|
650
|
+
if (!this.eventBus) {
|
|
651
|
+
throw new Error("WorkbenchService requires EventBus.");
|
|
652
|
+
}
|
|
653
|
+
if (!this.toolRegistry) {
|
|
654
|
+
throw new Error("WorkbenchService requires ToolRegistryService.");
|
|
655
|
+
}
|
|
656
|
+
if (!this.sessionService) {
|
|
657
|
+
throw new Error("WorkbenchService requires ToolSessionService.");
|
|
658
|
+
}
|
|
456
659
|
}
|
|
457
660
|
dispose() {
|
|
661
|
+
this.guards = [];
|
|
458
662
|
}
|
|
459
663
|
setEventBus(bus) {
|
|
460
664
|
this.eventBus = bus;
|
|
461
665
|
}
|
|
666
|
+
setToolRegistry(toolRegistry) {
|
|
667
|
+
this.toolRegistry = toolRegistry;
|
|
668
|
+
}
|
|
669
|
+
setToolSessionService(sessionService) {
|
|
670
|
+
this.sessionService = sessionService;
|
|
671
|
+
}
|
|
462
672
|
get activeToolId() {
|
|
463
673
|
return this._activeToolId;
|
|
464
674
|
}
|
|
465
|
-
|
|
675
|
+
registerSwitchGuard(guard, priority = 0) {
|
|
676
|
+
const item = { guard, priority };
|
|
677
|
+
this.guards.push(item);
|
|
678
|
+
this.guards.sort((a, b) => b.priority - a.priority);
|
|
679
|
+
return {
|
|
680
|
+
dispose: () => {
|
|
681
|
+
const index = this.guards.indexOf(item);
|
|
682
|
+
if (index >= 0) this.guards.splice(index, 1);
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
async runGuards(context) {
|
|
687
|
+
for (const { guard } of this.guards) {
|
|
688
|
+
const allowed = await Promise.resolve(guard(context));
|
|
689
|
+
if (!allowed) return false;
|
|
690
|
+
}
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
async switchTool(id, options) {
|
|
466
694
|
var _a;
|
|
467
|
-
|
|
695
|
+
const eventBus = this.getEventBus();
|
|
696
|
+
const toolRegistry = this.getToolRegistry();
|
|
697
|
+
const sessionService = this.getSessionService();
|
|
698
|
+
if (this._activeToolId === id) {
|
|
699
|
+
return { ok: true, from: this._activeToolId, to: id };
|
|
700
|
+
}
|
|
701
|
+
if (id && !toolRegistry.hasTool(id)) {
|
|
702
|
+
return {
|
|
703
|
+
ok: false,
|
|
704
|
+
from: this._activeToolId,
|
|
705
|
+
to: id,
|
|
706
|
+
reason: `tool-not-registered:${id}`
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
const context = {
|
|
710
|
+
from: this._activeToolId,
|
|
711
|
+
to: id,
|
|
712
|
+
reason: options == null ? void 0 : options.reason
|
|
713
|
+
};
|
|
714
|
+
const guardAllowed = await this.runGuards(context);
|
|
715
|
+
if (!guardAllowed) {
|
|
716
|
+
eventBus.emit("tool:switch:blocked", {
|
|
717
|
+
...context,
|
|
718
|
+
reason: "blocked-by-guard"
|
|
719
|
+
});
|
|
720
|
+
return {
|
|
721
|
+
ok: false,
|
|
722
|
+
from: this._activeToolId,
|
|
723
|
+
to: id,
|
|
724
|
+
reason: "blocked-by-guard"
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
if (context.from) {
|
|
728
|
+
const leaveResult = await sessionService.handleBeforeLeave(context.from);
|
|
729
|
+
if (leaveResult.decision === "blocked") {
|
|
730
|
+
eventBus.emit("tool:switch:blocked", {
|
|
731
|
+
...context,
|
|
732
|
+
reason: leaveResult.reason || "session-blocked"
|
|
733
|
+
});
|
|
734
|
+
return {
|
|
735
|
+
ok: false,
|
|
736
|
+
from: this._activeToolId,
|
|
737
|
+
to: id,
|
|
738
|
+
reason: leaveResult.reason || "session-blocked"
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
sessionService.deactivateSession(context.from);
|
|
742
|
+
}
|
|
743
|
+
if (id) {
|
|
744
|
+
const tool = toolRegistry.getTool(id);
|
|
745
|
+
if ((tool == null ? void 0 : tool.interaction) === "session" && ((_a = tool.session) == null ? void 0 : _a.autoBegin) !== false) {
|
|
746
|
+
await sessionService.begin(id);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
468
749
|
const previous = this._activeToolId;
|
|
469
750
|
this._activeToolId = id;
|
|
470
|
-
|
|
751
|
+
const reason = options == null ? void 0 : options.reason;
|
|
752
|
+
eventBus.emit("tool:activated", { id, previous, reason });
|
|
753
|
+
eventBus.emit("tool:switch", { from: previous, to: id, reason });
|
|
754
|
+
return { ok: true, from: previous, to: id };
|
|
755
|
+
}
|
|
756
|
+
async activate(id) {
|
|
757
|
+
return await this.switchTool(id, { reason: "activate" });
|
|
758
|
+
}
|
|
759
|
+
async deactivate() {
|
|
760
|
+
return await this.switchTool(null, { reason: "deactivate" });
|
|
761
|
+
}
|
|
762
|
+
getEventBus() {
|
|
763
|
+
if (!this.eventBus) {
|
|
764
|
+
throw new Error("WorkbenchService is not initialized.");
|
|
765
|
+
}
|
|
766
|
+
return this.eventBus;
|
|
767
|
+
}
|
|
768
|
+
getToolRegistry() {
|
|
769
|
+
if (!this.toolRegistry) {
|
|
770
|
+
throw new Error("WorkbenchService is not initialized.");
|
|
771
|
+
}
|
|
772
|
+
return this.toolRegistry;
|
|
773
|
+
}
|
|
774
|
+
getSessionService() {
|
|
775
|
+
if (!this.sessionService) {
|
|
776
|
+
throw new Error("WorkbenchService is not initialized.");
|
|
777
|
+
}
|
|
778
|
+
return this.sessionService;
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/extension.ts
|
|
783
|
+
var ExtensionRegistry = class extends Map {
|
|
784
|
+
};
|
|
785
|
+
var ExtensionManager = class {
|
|
786
|
+
constructor(context) {
|
|
787
|
+
this.extensionRegistry = new ExtensionRegistry();
|
|
788
|
+
this.extensionDisposables = /* @__PURE__ */ new Map();
|
|
789
|
+
this.context = context;
|
|
790
|
+
}
|
|
791
|
+
register(extension) {
|
|
792
|
+
if (this.extensionRegistry.has(extension.id)) {
|
|
793
|
+
console.warn(
|
|
794
|
+
`Plugin "${extension.id}" already registered. It will be overwritten.`
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
this.extensionDisposables.set(extension.id, []);
|
|
798
|
+
const disposables = this.extensionDisposables.get(extension.id);
|
|
799
|
+
if (extension.contribute) {
|
|
800
|
+
for (const [pointId, items] of Object.entries(extension.contribute())) {
|
|
801
|
+
if (Array.isArray(items)) {
|
|
802
|
+
items.forEach((item, index) => {
|
|
803
|
+
const contributionId = item.id || (item.command ? item.command : `${extension.id}.${pointId}.${index}`);
|
|
804
|
+
const contribution = {
|
|
805
|
+
id: contributionId,
|
|
806
|
+
metadata: {
|
|
807
|
+
extensionId: extension.id,
|
|
808
|
+
...item == null ? void 0 : item.metadata
|
|
809
|
+
},
|
|
810
|
+
data: item
|
|
811
|
+
};
|
|
812
|
+
const disposable = this.context.contributions.register(
|
|
813
|
+
pointId,
|
|
814
|
+
contribution
|
|
815
|
+
);
|
|
816
|
+
disposables.push(disposable);
|
|
817
|
+
const dispose = this.collectContribution(pointId, contribution);
|
|
818
|
+
if (dispose) {
|
|
819
|
+
disposables.push(dispose);
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
try {
|
|
826
|
+
this.extensionRegistry.set(extension.id, extension);
|
|
827
|
+
this.context.eventBus.emit("extension:register", extension);
|
|
828
|
+
} catch (error) {
|
|
829
|
+
console.error(
|
|
830
|
+
`Error in onCreate hook for plugin "${extension.id}":`,
|
|
831
|
+
error
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
try {
|
|
835
|
+
extension.activate(this.context);
|
|
836
|
+
} catch (error) {
|
|
837
|
+
console.error(
|
|
838
|
+
`Error in onActivate hook for plugin "${extension.id}":`,
|
|
839
|
+
error
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
console.log(`Plugin "${extension.id}" registered successfully`);
|
|
843
|
+
}
|
|
844
|
+
collectContribution(pointId, item) {
|
|
845
|
+
if (pointId === ContributionPointIds.CONFIGURATIONS) {
|
|
846
|
+
const configService = this.context.services.get(
|
|
847
|
+
CONFIGURATION_SERVICE
|
|
848
|
+
);
|
|
849
|
+
configService == null ? void 0 : configService.initializeDefaults([item.data]);
|
|
850
|
+
}
|
|
851
|
+
if (pointId === ContributionPointIds.COMMANDS && item.data.handler) {
|
|
852
|
+
const commandService = this.context.services.get(COMMAND_SERVICE);
|
|
853
|
+
return commandService.registerCommand(item.id, item.data.handler);
|
|
854
|
+
}
|
|
855
|
+
if (pointId === ContributionPointIds.TOOLS) {
|
|
856
|
+
const toolRegistry = this.context.services.get(
|
|
857
|
+
TOOL_REGISTRY_SERVICE
|
|
858
|
+
);
|
|
859
|
+
if (!toolRegistry) return;
|
|
860
|
+
return toolRegistry.registerTool(item.data);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
unregister(name) {
|
|
864
|
+
const extension = this.extensionRegistry.get(name);
|
|
865
|
+
if (!extension) {
|
|
866
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
try {
|
|
870
|
+
extension.deactivate(this.context);
|
|
871
|
+
} catch (error) {
|
|
872
|
+
console.error(`Error in deactivate for plugin "${name}":`, error);
|
|
873
|
+
}
|
|
874
|
+
const disposables = this.extensionDisposables.get(name);
|
|
875
|
+
if (disposables) {
|
|
876
|
+
disposables.forEach((d) => d.dispose());
|
|
877
|
+
this.extensionDisposables.delete(name);
|
|
878
|
+
}
|
|
879
|
+
this.extensionRegistry.delete(name);
|
|
880
|
+
console.log(`Plugin "${name}" unregistered`);
|
|
881
|
+
return true;
|
|
882
|
+
}
|
|
883
|
+
enable(name) {
|
|
884
|
+
const extension = this.extensionRegistry.get(name);
|
|
885
|
+
if (!extension) {
|
|
886
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
disable(name) {
|
|
891
|
+
const extension = this.extensionRegistry.get(name);
|
|
892
|
+
if (!extension) {
|
|
893
|
+
console.warn(`Plugin "${name}" not found.`);
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
update() {
|
|
898
|
+
}
|
|
899
|
+
destroy() {
|
|
900
|
+
const extensionNames = Array.from(this.extensionRegistry.keys());
|
|
901
|
+
extensionNames.forEach((name) => this.unregister(name));
|
|
471
902
|
}
|
|
472
903
|
};
|
|
473
904
|
|
|
@@ -476,19 +907,37 @@ var Pooder = class {
|
|
|
476
907
|
constructor() {
|
|
477
908
|
this.eventBus = new event_default();
|
|
478
909
|
this.services = new ServiceRegistry();
|
|
910
|
+
this.serviceContext = {
|
|
911
|
+
eventBus: this.eventBus,
|
|
912
|
+
get: (identifier) => this.services.get(identifier),
|
|
913
|
+
getOrThrow: (identifier, errorMessage) => this.services.getOrThrow(identifier, errorMessage),
|
|
914
|
+
has: (identifier) => this.services.has(identifier)
|
|
915
|
+
};
|
|
479
916
|
this.contributions = new ContributionRegistry();
|
|
480
917
|
this.initDefaultContributionPoints();
|
|
481
918
|
const commandService = new CommandService();
|
|
482
|
-
this.registerService(commandService,
|
|
919
|
+
this.registerService(commandService, CORE_SERVICE_TOKENS.COMMAND);
|
|
483
920
|
const configurationService = new ConfigurationService();
|
|
484
|
-
this.registerService(configurationService,
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
921
|
+
this.registerService(configurationService, CORE_SERVICE_TOKENS.CONFIGURATION);
|
|
922
|
+
const toolRegistryService = new ToolRegistryService();
|
|
923
|
+
this.registerService(toolRegistryService, CORE_SERVICE_TOKENS.TOOL_REGISTRY);
|
|
924
|
+
const toolSessionService = new ToolSessionService({
|
|
925
|
+
commandService,
|
|
926
|
+
toolRegistry: toolRegistryService
|
|
927
|
+
});
|
|
928
|
+
this.registerService(toolSessionService, CORE_SERVICE_TOKENS.TOOL_SESSION);
|
|
929
|
+
const workbenchService = new WorkbenchService({
|
|
930
|
+
eventBus: this.eventBus,
|
|
931
|
+
toolRegistry: toolRegistryService,
|
|
932
|
+
sessionService: toolSessionService
|
|
933
|
+
});
|
|
934
|
+
this.registerService(workbenchService, CORE_SERVICE_TOKENS.WORKBENCH);
|
|
488
935
|
const context = {
|
|
489
936
|
eventBus: this.eventBus,
|
|
490
937
|
services: {
|
|
491
|
-
get: (
|
|
938
|
+
get: (identifier) => this.services.get(identifier),
|
|
939
|
+
getOrThrow: (identifier, errorMessage) => this.services.getOrThrow(identifier, errorMessage),
|
|
940
|
+
has: (identifier) => this.services.has(identifier)
|
|
492
941
|
},
|
|
493
942
|
contributions: {
|
|
494
943
|
get: (pointId) => this.getContributions(pointId),
|
|
@@ -520,38 +969,102 @@ var Pooder = class {
|
|
|
520
969
|
});
|
|
521
970
|
}
|
|
522
971
|
// --- Service Management ---
|
|
523
|
-
registerService(service,
|
|
524
|
-
|
|
525
|
-
const serviceId =
|
|
972
|
+
registerService(service, identifier, options = {}) {
|
|
973
|
+
const serviceIdentifier = this.resolveServiceIdentifier(service, identifier);
|
|
974
|
+
const serviceId = this.getServiceLabel(serviceIdentifier);
|
|
526
975
|
try {
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
976
|
+
const initResult = this.invokeServiceHook(service, "init");
|
|
977
|
+
if (this.isPromiseLike(initResult)) {
|
|
978
|
+
throw new Error(
|
|
979
|
+
`Service "${serviceId}" init() is async. Use registerServiceAsync() instead.`
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
this.services.register(serviceIdentifier, service, options);
|
|
983
|
+
this.eventBus.emit("service:register", service, { id: serviceId });
|
|
984
|
+
return true;
|
|
985
|
+
} catch (error) {
|
|
986
|
+
console.error(`Error initializing service ${serviceId}:`, error);
|
|
987
|
+
return false;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
async registerServiceAsync(service, identifier, options = {}) {
|
|
991
|
+
const serviceIdentifier = this.resolveServiceIdentifier(service, identifier);
|
|
992
|
+
const serviceId = this.getServiceLabel(serviceIdentifier);
|
|
993
|
+
try {
|
|
994
|
+
await this.invokeServiceHookAsync(service, "init");
|
|
995
|
+
this.services.register(serviceIdentifier, service, options);
|
|
996
|
+
this.eventBus.emit("service:register", service, { id: serviceId });
|
|
997
|
+
return true;
|
|
998
|
+
} catch (error) {
|
|
999
|
+
console.error(`Error initializing service ${serviceId}:`, error);
|
|
530
1000
|
return false;
|
|
531
1001
|
}
|
|
532
|
-
|
|
533
|
-
|
|
1002
|
+
}
|
|
1003
|
+
unregisterService(serviceOrIdentifier, id) {
|
|
1004
|
+
const resolvedIdentifier = this.resolveUnregisterIdentifier(
|
|
1005
|
+
serviceOrIdentifier,
|
|
1006
|
+
id
|
|
1007
|
+
);
|
|
1008
|
+
const serviceId = this.getServiceLabel(resolvedIdentifier);
|
|
1009
|
+
const registeredService = this.services.get(resolvedIdentifier);
|
|
1010
|
+
if (!registeredService) {
|
|
1011
|
+
console.warn(`Service ${serviceId} is not registered.`);
|
|
1012
|
+
return true;
|
|
1013
|
+
}
|
|
1014
|
+
try {
|
|
1015
|
+
const disposeResult = this.invokeServiceHook(registeredService, "dispose");
|
|
1016
|
+
if (this.isPromiseLike(disposeResult)) {
|
|
1017
|
+
throw new Error(
|
|
1018
|
+
`Service "${serviceId}" dispose() is async. Use unregisterServiceAsync() instead.`
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
} catch (error) {
|
|
1022
|
+
console.error(`Error disposing service ${serviceId}:`, error);
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
this.services.delete(resolvedIdentifier);
|
|
1026
|
+
this.eventBus.emit("service:unregister", registeredService, { id: serviceId });
|
|
534
1027
|
return true;
|
|
535
1028
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
1029
|
+
async unregisterServiceAsync(serviceOrIdentifier, id) {
|
|
1030
|
+
const resolvedIdentifier = this.resolveUnregisterIdentifier(
|
|
1031
|
+
serviceOrIdentifier,
|
|
1032
|
+
id
|
|
1033
|
+
);
|
|
1034
|
+
const serviceId = this.getServiceLabel(resolvedIdentifier);
|
|
1035
|
+
const registeredService = this.services.get(resolvedIdentifier);
|
|
1036
|
+
if (!registeredService) {
|
|
540
1037
|
console.warn(`Service ${serviceId} is not registered.`);
|
|
541
1038
|
return true;
|
|
542
1039
|
}
|
|
543
1040
|
try {
|
|
544
|
-
(
|
|
545
|
-
} catch (
|
|
546
|
-
console.error(`Error disposing service ${serviceId}:`,
|
|
1041
|
+
await this.invokeServiceHookAsync(registeredService, "dispose");
|
|
1042
|
+
} catch (error) {
|
|
1043
|
+
console.error(`Error disposing service ${serviceId}:`, error);
|
|
547
1044
|
return false;
|
|
548
1045
|
}
|
|
549
|
-
this.services.delete(
|
|
550
|
-
this.eventBus.emit("service:unregister",
|
|
1046
|
+
this.services.delete(resolvedIdentifier);
|
|
1047
|
+
this.eventBus.emit("service:unregister", registeredService, { id: serviceId });
|
|
551
1048
|
return true;
|
|
552
1049
|
}
|
|
553
|
-
getService(
|
|
554
|
-
return this.services.get(
|
|
1050
|
+
getService(identifier) {
|
|
1051
|
+
return this.services.get(identifier);
|
|
1052
|
+
}
|
|
1053
|
+
getServiceOrThrow(identifier, errorMessage) {
|
|
1054
|
+
return this.services.getOrThrow(identifier, errorMessage);
|
|
1055
|
+
}
|
|
1056
|
+
hasService(identifier) {
|
|
1057
|
+
return this.services.has(identifier);
|
|
1058
|
+
}
|
|
1059
|
+
async dispose() {
|
|
1060
|
+
var _a;
|
|
1061
|
+
this.extensionManager.destroy();
|
|
1062
|
+
const registrations = this.services.list().slice().reverse();
|
|
1063
|
+
for (const item of registrations) {
|
|
1064
|
+
const identifier = (_a = item.token) != null ? _a : item.id;
|
|
1065
|
+
await this.unregisterServiceAsync(identifier);
|
|
1066
|
+
}
|
|
1067
|
+
this.services.clear();
|
|
555
1068
|
}
|
|
556
1069
|
// --- Contribution Management ---
|
|
557
1070
|
registerContributionPoint(point) {
|
|
@@ -566,8 +1079,39 @@ var Pooder = class {
|
|
|
566
1079
|
getContributions(pointId) {
|
|
567
1080
|
return this.contributions.get(pointId);
|
|
568
1081
|
}
|
|
1082
|
+
resolveServiceIdentifier(service, identifier) {
|
|
1083
|
+
return identifier != null ? identifier : service.constructor.name;
|
|
1084
|
+
}
|
|
1085
|
+
resolveUnregisterIdentifier(serviceOrIdentifier, id) {
|
|
1086
|
+
if (typeof serviceOrIdentifier === "string" || isServiceToken(serviceOrIdentifier)) {
|
|
1087
|
+
return serviceOrIdentifier;
|
|
1088
|
+
}
|
|
1089
|
+
return id != null ? id : serviceOrIdentifier.constructor.name;
|
|
1090
|
+
}
|
|
1091
|
+
getServiceLabel(identifier) {
|
|
1092
|
+
if (typeof identifier === "string") {
|
|
1093
|
+
return identifier;
|
|
1094
|
+
}
|
|
1095
|
+
return identifier.name;
|
|
1096
|
+
}
|
|
1097
|
+
invokeServiceHook(service, hook) {
|
|
1098
|
+
const handler = service[hook];
|
|
1099
|
+
if (!handler) {
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
return handler.call(service, this.serviceContext);
|
|
1103
|
+
}
|
|
1104
|
+
async invokeServiceHookAsync(service, hook) {
|
|
1105
|
+
await this.invokeServiceHook(service, hook);
|
|
1106
|
+
}
|
|
1107
|
+
isPromiseLike(value) {
|
|
1108
|
+
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
1109
|
+
}
|
|
569
1110
|
};
|
|
570
1111
|
export {
|
|
1112
|
+
COMMAND_SERVICE,
|
|
1113
|
+
CONFIGURATION_SERVICE,
|
|
1114
|
+
CORE_SERVICE_TOKENS,
|
|
571
1115
|
CommandService,
|
|
572
1116
|
ConfigurationService,
|
|
573
1117
|
ContributionPointIds,
|
|
@@ -577,5 +1121,12 @@ export {
|
|
|
577
1121
|
ExtensionRegistry,
|
|
578
1122
|
Pooder,
|
|
579
1123
|
ServiceRegistry,
|
|
580
|
-
|
|
1124
|
+
TOOL_REGISTRY_SERVICE,
|
|
1125
|
+
TOOL_SESSION_SERVICE,
|
|
1126
|
+
ToolRegistryService,
|
|
1127
|
+
ToolSessionService,
|
|
1128
|
+
WORKBENCH_SERVICE,
|
|
1129
|
+
WorkbenchService,
|
|
1130
|
+
createServiceToken,
|
|
1131
|
+
isServiceToken
|
|
581
1132
|
};
|