@rowan-agent/agent 0.22.0 → 0.23.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/dist/index.d.ts +30 -4
- package/dist/index.js +146 -26
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -368,10 +368,12 @@ declare class ExtensionRunner {
|
|
|
368
368
|
private readonly hostUnsubscribers;
|
|
369
369
|
private readonly phases;
|
|
370
370
|
private _phaseCache;
|
|
371
|
+
private readonly skills;
|
|
371
372
|
private readonly pendingProviders;
|
|
372
373
|
private bound;
|
|
373
374
|
private readonly errorListeners;
|
|
374
375
|
private readonly capabilityListeners;
|
|
376
|
+
private readonly resourceChangeListeners;
|
|
375
377
|
/** Current agent context — set by the agent before each phase */
|
|
376
378
|
currentContext?: AgentContext;
|
|
377
379
|
constructor(options?: ExtensionRunnerOptions);
|
|
@@ -419,7 +421,7 @@ declare class ExtensionRunner {
|
|
|
419
421
|
/** Dispose all active Extensions in reverse activation order. */
|
|
420
422
|
close(): Promise<void>;
|
|
421
423
|
get extensionHost(): ExtensionHost;
|
|
422
|
-
notifyConfigChanged(extensionId: string, scope: ScopeRef): void
|
|
424
|
+
notifyConfigChanged(extensionId: string, scope: ScopeRef): Promise<void>;
|
|
423
425
|
getRunState(runId: string, extensionId: string, key: string): JsonValue | undefined;
|
|
424
426
|
setRunState(runId: string, extensionId: string, key: string, value: JsonValue): void;
|
|
425
427
|
deleteRunState(runId: string, extensionId: string, key: string): void;
|
|
@@ -437,6 +439,12 @@ declare class ExtensionRunner {
|
|
|
437
439
|
* Returns an unsubscribe function.
|
|
438
440
|
*/
|
|
439
441
|
onCapabilitiesChanged(listener: (capabilities: readonly ExtensionCapability[]) => void): () => void;
|
|
442
|
+
/**
|
|
443
|
+
* Subscribe to resource changes (tools, phases, skills registered, unregistered, or disposed).
|
|
444
|
+
* Used by RuntimeBootstrapRegistry to re-commit implicit sources after activation.
|
|
445
|
+
*/
|
|
446
|
+
onResourceChange(listener: (kind: "tool" | "phase" | "skill") => Promise<void> | void): () => void;
|
|
447
|
+
private notifyResourceChange;
|
|
440
448
|
triggerUiAction(event: {
|
|
441
449
|
contributionId: string;
|
|
442
450
|
actionId: string;
|
|
@@ -449,6 +457,7 @@ declare class ExtensionRunner {
|
|
|
449
457
|
}): PhaseRegistry;
|
|
450
458
|
/** Adapt an extension RegisteredPhase to the core Phase type. */
|
|
451
459
|
private adaptToPhase;
|
|
460
|
+
getSkills(): Skill[];
|
|
452
461
|
/**
|
|
453
462
|
* Bind the runner — flushes pending provider registrations and
|
|
454
463
|
* replaces runtime stubs with real implementations.
|
|
@@ -515,6 +524,10 @@ declare class ExtensionRunner {
|
|
|
515
524
|
private registerPhaseDefinition;
|
|
516
525
|
private unregisterPhase;
|
|
517
526
|
private loadRegisteredPhase;
|
|
527
|
+
private registerSkill;
|
|
528
|
+
private registerSkillDefinition;
|
|
529
|
+
private unregisterSkill;
|
|
530
|
+
private loadRegisteredSkill;
|
|
518
531
|
private registerProvider;
|
|
519
532
|
private unregisterProvider;
|
|
520
533
|
private flushPendingProviders;
|
|
@@ -588,8 +601,10 @@ declare class RuntimeExtensionLifetime {
|
|
|
588
601
|
activate(extensions: readonly LoadedExtension[]): Promise<ExtensionActivationResult>;
|
|
589
602
|
tools(): readonly RegisteredTool[];
|
|
590
603
|
phases(): readonly Phase[];
|
|
604
|
+
skills(): readonly Skill[];
|
|
591
605
|
get extensionRunner(): ExtensionRunner;
|
|
592
606
|
get extensionHost(): ExtensionHost;
|
|
607
|
+
onResourceChange(listener: (kind: "tool" | "phase" | "skill") => Promise<void> | void): () => void;
|
|
593
608
|
dropRunState(runId: string): void;
|
|
594
609
|
close(): Promise<void>;
|
|
595
610
|
}
|
|
@@ -597,7 +612,9 @@ declare class RuntimeExtensionLifetime {
|
|
|
597
612
|
declare class RuntimeBootstrapRegistry extends ResourceRegistry {
|
|
598
613
|
private readonly extensions;
|
|
599
614
|
private readonly extensionSourceId;
|
|
615
|
+
private commitQueue;
|
|
600
616
|
constructor(extensions?: RuntimeExtensionLifetime);
|
|
617
|
+
private recommit;
|
|
601
618
|
get extensionHost(): ExtensionHost;
|
|
602
619
|
/** Install Rowan-owned implicit resources before any host source is read. */
|
|
603
620
|
ensureCoreResources(): Promise<void>;
|
|
@@ -1324,6 +1341,8 @@ interface SourceInfo {
|
|
|
1324
1341
|
}
|
|
1325
1342
|
/** Register a Phase by directory path or Phase object; PHASE.md and direct child Skills are loaded atomically when a path is supplied. */
|
|
1326
1343
|
type PhaseRegistration = string | Phase;
|
|
1344
|
+
/** Register a Skill directory (containing SKILL.md) or a Skill object. Registering an existing name replaces it. */
|
|
1345
|
+
type SkillRegistration = string | Skill;
|
|
1327
1346
|
/**
|
|
1328
1347
|
* Tool definition for registering LLM-callable tools via `api.tools.register()`.
|
|
1329
1348
|
*
|
|
@@ -1495,9 +1514,9 @@ interface ExtensionAPI {
|
|
|
1495
1514
|
/** Tool capabilities — register and unregister custom tools. */
|
|
1496
1515
|
tools: {
|
|
1497
1516
|
/** Register a custom LLM-callable tool. */
|
|
1498
|
-
register(tool: ToolDefinition): void
|
|
1517
|
+
register(tool: ToolDefinition): Promise<void>;
|
|
1499
1518
|
/** Unregister a previously registered tool by name. */
|
|
1500
|
-
unregister(toolName: string): void
|
|
1519
|
+
unregister(toolName: string): Promise<void>;
|
|
1501
1520
|
};
|
|
1502
1521
|
/** Capability contributions — advertise tools or features to the host. */
|
|
1503
1522
|
capabilities: {
|
|
@@ -1532,6 +1551,13 @@ interface ExtensionAPI {
|
|
|
1532
1551
|
/** Get the message set by setMessage */
|
|
1533
1552
|
getMessage(): string | undefined;
|
|
1534
1553
|
};
|
|
1554
|
+
/** Skill capabilities — register and unregister standalone skills. */
|
|
1555
|
+
skills: {
|
|
1556
|
+
/** Register a Skill directory (containing SKILL.md) or a Skill object. Registering an existing name replaces it. */
|
|
1557
|
+
register(skill: SkillRegistration): Promise<void>;
|
|
1558
|
+
/** Unregister a previously registered Skill by name. */
|
|
1559
|
+
unregister(skillName: string): void;
|
|
1560
|
+
};
|
|
1535
1561
|
/** Extension manifest from package.json `rowan` field. */
|
|
1536
1562
|
manifest?: ExtensionManifest;
|
|
1537
1563
|
/** Utility functions. */
|
|
@@ -3331,4 +3357,4 @@ declare function parseFrontmatter<T = Record<string, unknown>>(raw: string): Fro
|
|
|
3331
3357
|
|
|
3332
3358
|
declare function createCoreTools(input?: CoreToolContext): Tool$1[];
|
|
3333
3359
|
|
|
3334
|
-
export { type AfterToolCall, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, COMPACT_PHASE_ID, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type ContextCompactionRecord, type ContextStatus, type CoreToolContext, DEFAULT_PHASE_ID, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EntryPhaseSpec, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionCapability, type ExtensionCapabilityContribution, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionHost, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type ExtensionStateStore, type ExtensionToolContribution, type FrontmatterResult, type HistorySeed, type HookEvent, type HookEventType, type HookHandler, type HostApiExtension, InMemoryConfigProvider, InMemoryExtensionHost, InMemoryStore, type InteractionRecord, type InvocationCatalogEntry, type InvocationSource, type JsonObject, type JsonPrimitive, type JsonValue, type LiveInteractionEvent, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type MessageRevised, type MessageRevisionResult, type Metadata, type ModelRetry, type OpaqueId, type Outcome$1 as Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecution, type PhaseExecutionIdentity, type PhaseInput, type PhaseInvocation, type PhaseMessageManager, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type PhaseStatus, type PhaseStatusState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RetentionResult, type RunBoundary, type RunClaim, type RunEndEvent, type RunEvent, type RunFailure, type RunId, type RunInteraction, RunInteractionBoundary, RunInteractionCancelledError, type RunInteractionDriver, type RunInteractionKind, type RunInteractionRequest, type RunInteractionState, type RunInteractionStatus, type RunListCursor, type RunRecord, type RunSnapshot, type RunStartEvent, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, STOP_PHASE_ID, type SettingsBadge, type SettingsControl, type SettingsDefinition, type SettingsItem, type SettingsOption, type SettingsSection, type Skill, SqliteStore, type TextContent, type ThinkingContent, type ThinkingDelta, type Tool$1 as Tool, type ToolCallContext, type ToolCallDelta, type ToolCallId, type ToolCallPresentationInput, type ToolCallPresentationOutput, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, type WithdrawnUserInput, brandConfigToken, createCompactPhase, createCorePhases, createCoreTools, createDefaultPhase, createStopPhase, isConfigurationSnapshot, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, mergeToolCall, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
|
|
3360
|
+
export { type AfterToolCall, type AgentConfiguration, type AgentDefinition, type AgentId, type AgentListCursor, type AgentRecord, type AgentRun, AgentRuntime, type AgentRuntimeOptions, type AgentSummary, type AnyRuntimeError, type AssistantContent, type AssistantMessage, type BeforeToolCall, COMPACT_PHASE_ID, type ConfigProvider, type ConfigPutResult, type ConfigResolution, type ConfigToken, type ConfigurationSnapshot, type ContextCandidate, type ContextCompactionRecord, type ContextStatus, type CoreToolContext, DEFAULT_PHASE_ID, type DefinitionLayer, type DurableConsumer, type DurableRunEvent, type DurableStore, type DurableToolResult, type EntryPhaseSpec, type EventCursor, type EventId, type ExecutionCheckpoint, type ExecutionId, type ExecutionToken, type ExtensionAPI, type ExtensionActivationError, type ExtensionActivationResult, type ExtensionCapability, type ExtensionCapabilityContribution, type ExtensionContribution, type ExtensionDisposer, type ExtensionFactory, type ExtensionFactoryResult, type ExtensionHost, ExtensionLifetimeError, type ExtensionLifetimeErrorCode, type ExtensionLoadInput, type ExtensionStateStore, type ExtensionToolContribution, type FrontmatterResult, type HistorySeed, type HookEvent, type HookEventType, type HookHandler, type HostApiExtension, InMemoryConfigProvider, InMemoryExtensionHost, InMemoryStore, type InteractionRecord, type InvocationCatalogEntry, type InvocationSource, type JsonObject, type JsonPrimitive, type JsonValue, type LiveInteractionEvent, type LoadExtensionsResult, type LoadInput, type LoadResult, type LoadedExtension, type Message, type MessageBase, type MessageCommitted, type MessageContent, type MessageDelta, type MessageId, type MessageRevised, type MessageRevisionResult, type Metadata, type ModelRetry, type OpaqueId, type Outcome$1 as Outcome, type OwnerLease, type OwnerToken, type Page, type Phase, type PhaseContext, type PhaseContribution, type PhaseExecution, type PhaseExecutionIdentity, type PhaseInput, type PhaseInvocation, type PhaseMessageManager, type PhaseOutput, type PhaseRegistry, type PhaseRegistrySelection, type PhaseState, type PhaseStatus, type PhaseStatusState, type ResolvedResourceView, type ResourceDiagnostic, type ResourceKind, type ResourceRef, ResourceRegistry, ResourceRegistryError, type ResourceRegistryErrorCode, type ResourceSourceId, type ResourceView, type RetentionResult, type RunBoundary, type RunClaim, type RunEndEvent, type RunEvent, type RunFailure, type RunId, type RunInteraction, RunInteractionBoundary, RunInteractionCancelledError, type RunInteractionDriver, type RunInteractionKind, type RunInteractionRequest, type RunInteractionState, type RunInteractionStatus, type RunListCursor, type RunRecord, type RunSnapshot, type RunStartEvent, type RunState, type RunStateChanged, type RunSummary, RuntimeBootstrapRegistry, RuntimeError, type RuntimeErrorCode, type RuntimeErrorDetails, RuntimeExtensionLifetime, STOP_PHASE_ID, type SettingsBadge, type SettingsControl, type SettingsDefinition, type SettingsItem, type SettingsOption, type SettingsSection, type Skill, type SkillRegistration, SqliteStore, type TextContent, type ThinkingContent, type ThinkingDelta, type Tool$1 as Tool, type ToolCallContext, type ToolCallDelta, type ToolCallId, type ToolCallPresentationInput, type ToolCallPresentationOutput, type ToolCallSnapshot, type ToolCallState, type ToolContribution, type ToolDefinition, type ToolExecutionResult, type ToolInvocationContext, type ToolMessage, type ToolMessageContent, type ToolResultContent, type ToolStateChanged, type ToolUseContent, type UserContent, type UserInput, type UserMessage, type WithdrawnUserInput, brandConfigToken, createCompactPhase, createCorePhases, createCoreTools, createDefaultPhase, createStopPhase, isConfigurationSnapshot, isRuntimeError, loadExtensionsFromPath as loadExtensions, loadPhase, loadPhases, loadSkill, loadSkills, mergeToolCall, parseAgentDefinition, parseFrontmatter, resolveConfigurationSnapshot };
|
package/dist/index.js
CHANGED
|
@@ -1704,11 +1704,11 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
|
|
|
1704
1704
|
tools: {
|
|
1705
1705
|
register: (tool) => {
|
|
1706
1706
|
assertActive();
|
|
1707
|
-
options?.registerTool?.(tool);
|
|
1707
|
+
return Promise.resolve(options?.registerTool?.(tool));
|
|
1708
1708
|
},
|
|
1709
1709
|
unregister: (toolName) => {
|
|
1710
1710
|
assertActive();
|
|
1711
|
-
options?.unregisterTool?.(toolName);
|
|
1711
|
+
return Promise.resolve(options?.unregisterTool?.(toolName));
|
|
1712
1712
|
}
|
|
1713
1713
|
},
|
|
1714
1714
|
capabilities: {
|
|
@@ -1768,7 +1768,7 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
|
|
|
1768
1768
|
},
|
|
1769
1769
|
unregister: (phaseName) => {
|
|
1770
1770
|
assertActive();
|
|
1771
|
-
options?.unregisterPhase?.(phaseName);
|
|
1771
|
+
return options?.unregisterPhase?.(phaseName);
|
|
1772
1772
|
},
|
|
1773
1773
|
getPayload: () => outputPayload,
|
|
1774
1774
|
setPayload: (p) => {
|
|
@@ -1783,6 +1783,16 @@ function createExtensionAPI(hooks, options, runtime, eventBus) {
|
|
|
1783
1783
|
},
|
|
1784
1784
|
getNextPhase: () => nextPhase,
|
|
1785
1785
|
getMessage: () => outputMessage
|
|
1786
|
+
},
|
|
1787
|
+
skills: {
|
|
1788
|
+
register: async (skill) => {
|
|
1789
|
+
assertActive();
|
|
1790
|
+
await options?.registerSkill?.(skill);
|
|
1791
|
+
},
|
|
1792
|
+
unregister: (skillName) => {
|
|
1793
|
+
assertActive();
|
|
1794
|
+
return options?.unregisterSkill?.(skillName);
|
|
1795
|
+
}
|
|
1786
1796
|
}
|
|
1787
1797
|
};
|
|
1788
1798
|
if (options?.namespaces) {
|
|
@@ -3502,12 +3512,10 @@ var DEFAULT_RETRY_DELAY_MS = 5e3;
|
|
|
3502
3512
|
function isRetryableError(error) {
|
|
3503
3513
|
if (!(error instanceof Error)) return false;
|
|
3504
3514
|
const message = error.message.toLowerCase();
|
|
3505
|
-
if (
|
|
3506
|
-
if (message.includes("
|
|
3507
|
-
if (message.includes("server error") || message.includes("
|
|
3508
|
-
if (message.includes("
|
|
3509
|
-
if (message.includes("service unavailable") || message.includes("503")) return true;
|
|
3510
|
-
if (message.includes("gateway timeout") || message.includes("504")) return true;
|
|
3515
|
+
if (/(?<![\d:])(429|500|502|503|504|529)(?!\d)/.test(message)) return true;
|
|
3516
|
+
if (message.includes("rate limit") || message.includes("overloaded")) return true;
|
|
3517
|
+
if (message.includes("server error") || message.includes("bad gateway")) return true;
|
|
3518
|
+
if (message.includes("service unavailable") || message.includes("gateway timeout")) return true;
|
|
3511
3519
|
if (message.includes("econnreset") || message.includes("econnrefused")) return true;
|
|
3512
3520
|
if (message.includes("socket connection was closed") || message.includes("socket hang up")) return true;
|
|
3513
3521
|
if (message.includes("fetch failed") || message.includes("etimedout")) return true;
|
|
@@ -3575,6 +3583,12 @@ async function executePhase(ctx) {
|
|
|
3575
3583
|
const api = createExtensionAPI(void 0, {
|
|
3576
3584
|
registerPhase: async () => {
|
|
3577
3585
|
},
|
|
3586
|
+
unregisterPhase: () => {
|
|
3587
|
+
},
|
|
3588
|
+
registerSkill: async () => {
|
|
3589
|
+
},
|
|
3590
|
+
unregisterSkill: () => {
|
|
3591
|
+
},
|
|
3578
3592
|
registerProvider: () => {
|
|
3579
3593
|
},
|
|
3580
3594
|
unregisterProvider: () => {
|
|
@@ -6107,6 +6121,8 @@ var ExtensionRunner = class {
|
|
|
6107
6121
|
// Phase management
|
|
6108
6122
|
phases = /* @__PURE__ */ new Map();
|
|
6109
6123
|
_phaseCache = null;
|
|
6124
|
+
// Skill management
|
|
6125
|
+
skills = /* @__PURE__ */ new Map();
|
|
6110
6126
|
// Provider management
|
|
6111
6127
|
pendingProviders = [];
|
|
6112
6128
|
bound = false;
|
|
@@ -6114,6 +6130,8 @@ var ExtensionRunner = class {
|
|
|
6114
6130
|
errorListeners = /* @__PURE__ */ new Set();
|
|
6115
6131
|
// Capability change listeners
|
|
6116
6132
|
capabilityListeners = /* @__PURE__ */ new Set();
|
|
6133
|
+
// Resource change listeners (for Registry live sync)
|
|
6134
|
+
resourceChangeListeners = /* @__PURE__ */ new Set();
|
|
6117
6135
|
/** Current agent context — set by the agent before each phase */
|
|
6118
6136
|
currentContext;
|
|
6119
6137
|
constructor(options) {
|
|
@@ -6124,7 +6142,7 @@ var ExtensionRunner = class {
|
|
|
6124
6142
|
this.host = options?.host ?? new InMemoryExtensionHost();
|
|
6125
6143
|
if (this.host.onConfigChanged) {
|
|
6126
6144
|
const unsub = this.host.onConfigChanged((extensionId, scope) => {
|
|
6127
|
-
this.notifyConfigChanged(extensionId, scope);
|
|
6145
|
+
void this.notifyConfigChanged(extensionId, scope);
|
|
6128
6146
|
});
|
|
6129
6147
|
if (typeof unsub === "function") {
|
|
6130
6148
|
this.hostUnsubscribers.push(unsub);
|
|
@@ -6217,6 +6235,7 @@ var ExtensionRunner = class {
|
|
|
6217
6235
|
path: ext.path,
|
|
6218
6236
|
tools: /* @__PURE__ */ new Map(),
|
|
6219
6237
|
phases: /* @__PURE__ */ new Set(),
|
|
6238
|
+
skills: /* @__PURE__ */ new Set(),
|
|
6220
6239
|
capabilities: /* @__PURE__ */ new Map(),
|
|
6221
6240
|
cleanup: [],
|
|
6222
6241
|
runtime: createExtensionRuntime(),
|
|
@@ -6261,19 +6280,22 @@ var ExtensionRunner = class {
|
|
|
6261
6280
|
}
|
|
6262
6281
|
this.extensions.length = 0;
|
|
6263
6282
|
this.capabilityListeners.clear();
|
|
6283
|
+
this.resourceChangeListeners.clear();
|
|
6264
6284
|
this.phases.clear();
|
|
6265
6285
|
this._phaseCache = null;
|
|
6286
|
+
this.skills.clear();
|
|
6287
|
+
this.bound = false;
|
|
6266
6288
|
this.runtime.invalidate("This Extension Runtime has been closed.");
|
|
6267
6289
|
}
|
|
6268
6290
|
get extensionHost() {
|
|
6269
6291
|
return this.host;
|
|
6270
6292
|
}
|
|
6271
|
-
notifyConfigChanged(extensionId, scope) {
|
|
6293
|
+
async notifyConfigChanged(extensionId, scope) {
|
|
6272
6294
|
const listeners = this.configChangeListeners.get(extensionId);
|
|
6273
6295
|
if (!listeners) return;
|
|
6274
6296
|
for (const listener of listeners) {
|
|
6275
6297
|
try {
|
|
6276
|
-
listener(scope);
|
|
6298
|
+
await listener(scope);
|
|
6277
6299
|
} catch (error) {
|
|
6278
6300
|
this.emitError({
|
|
6279
6301
|
extensionPath: "<runtime>",
|
|
@@ -6359,6 +6381,20 @@ var ExtensionRunner = class {
|
|
|
6359
6381
|
this.capabilityListeners.add(listener);
|
|
6360
6382
|
return () => this.capabilityListeners.delete(listener);
|
|
6361
6383
|
}
|
|
6384
|
+
/**
|
|
6385
|
+
* Subscribe to resource changes (tools, phases, skills registered, unregistered, or disposed).
|
|
6386
|
+
* Used by RuntimeBootstrapRegistry to re-commit implicit sources after activation.
|
|
6387
|
+
*/
|
|
6388
|
+
onResourceChange(listener) {
|
|
6389
|
+
this.resourceChangeListeners.add(listener);
|
|
6390
|
+
return () => this.resourceChangeListeners.delete(listener);
|
|
6391
|
+
}
|
|
6392
|
+
async notifyResourceChange(kind) {
|
|
6393
|
+
if (!this.bound) return;
|
|
6394
|
+
for (const listener of this.resourceChangeListeners) {
|
|
6395
|
+
await listener(kind);
|
|
6396
|
+
}
|
|
6397
|
+
}
|
|
6362
6398
|
triggerUiAction(event) {
|
|
6363
6399
|
this.events.emit("ui.action", event);
|
|
6364
6400
|
}
|
|
@@ -6395,6 +6431,12 @@ var ExtensionRunner = class {
|
|
|
6395
6431
|
};
|
|
6396
6432
|
}
|
|
6397
6433
|
// ---------------------------------------------------------------------------
|
|
6434
|
+
// Skill management
|
|
6435
|
+
// ---------------------------------------------------------------------------
|
|
6436
|
+
getSkills() {
|
|
6437
|
+
return [...this.skills.values()].map((s) => s.definition);
|
|
6438
|
+
}
|
|
6439
|
+
// ---------------------------------------------------------------------------
|
|
6398
6440
|
// Lifecycle
|
|
6399
6441
|
// ---------------------------------------------------------------------------
|
|
6400
6442
|
/**
|
|
@@ -6571,6 +6613,8 @@ var ExtensionRunner = class {
|
|
|
6571
6613
|
return createExtensionAPI(this.hooks, {
|
|
6572
6614
|
registerPhase: (registration) => this.registerPhase(extension, registration),
|
|
6573
6615
|
unregisterPhase: (phaseName) => this.unregisterPhase(extension, phaseName),
|
|
6616
|
+
registerSkill: (registration) => this.registerSkill(extension, registration),
|
|
6617
|
+
unregisterSkill: (skillName) => this.unregisterSkill(extension, skillName),
|
|
6574
6618
|
registerProvider: (config) => this.registerProvider(config),
|
|
6575
6619
|
unregisterProvider: (name) => this.unregisterProvider(name),
|
|
6576
6620
|
registerTool: (tool) => this.registerTool(extension, tool),
|
|
@@ -6620,6 +6664,8 @@ var ExtensionRunner = class {
|
|
|
6620
6664
|
}
|
|
6621
6665
|
}, extension.runtime, this.events);
|
|
6622
6666
|
}
|
|
6667
|
+
// Validation stays synchronous so a duplicate throws at the call site even
|
|
6668
|
+
// when the caller does not await the Registry re-commit.
|
|
6623
6669
|
registerTool(extension, tool) {
|
|
6624
6670
|
if (extension.tools.has(tool.name)) {
|
|
6625
6671
|
throw new Error(`Duplicate Tool name "${tool.name}" in extension ${extension.path}.`);
|
|
@@ -6640,11 +6686,11 @@ var ExtensionRunner = class {
|
|
|
6640
6686
|
definition: tool,
|
|
6641
6687
|
sourceInfo
|
|
6642
6688
|
});
|
|
6689
|
+
return this.notifyResourceChange("tool");
|
|
6643
6690
|
}
|
|
6644
6691
|
unregisterTool(extension, toolName) {
|
|
6645
|
-
if (extension.tools.
|
|
6646
|
-
|
|
6647
|
-
}
|
|
6692
|
+
if (!extension.tools.delete(toolName)) return Promise.resolve();
|
|
6693
|
+
return this.notifyResourceChange("tool");
|
|
6648
6694
|
}
|
|
6649
6695
|
contributeCapability(extension, contribution) {
|
|
6650
6696
|
const key = `${contribution.kind}:${contribution.name}`;
|
|
@@ -6698,7 +6744,7 @@ var ExtensionRunner = class {
|
|
|
6698
6744
|
}
|
|
6699
6745
|
throw new Error(`Phase registration requires a directory path or Phase object.`);
|
|
6700
6746
|
}
|
|
6701
|
-
registerPhaseDefinition(extension, phase) {
|
|
6747
|
+
async registerPhaseDefinition(extension, phase) {
|
|
6702
6748
|
const name = phase.name;
|
|
6703
6749
|
if (this.phases.has(name)) {
|
|
6704
6750
|
throw new Error(`Duplicate phase name: ${name}`);
|
|
@@ -6710,29 +6756,65 @@ var ExtensionRunner = class {
|
|
|
6710
6756
|
this.phases.set(name, registered);
|
|
6711
6757
|
extension.phases.add(name);
|
|
6712
6758
|
this._phaseCache = null;
|
|
6759
|
+
await this.notifyResourceChange("phase");
|
|
6713
6760
|
}
|
|
6714
|
-
unregisterPhase(extension, phaseName) {
|
|
6761
|
+
async unregisterPhase(extension, phaseName) {
|
|
6715
6762
|
const registered = this.phases.get(phaseName);
|
|
6716
6763
|
if (registered && registered.source.extensionPath === extension.path) {
|
|
6717
6764
|
this.phases.delete(phaseName);
|
|
6718
6765
|
extension.phases.delete(phaseName);
|
|
6719
6766
|
this._phaseCache = null;
|
|
6767
|
+
await this.notifyResourceChange("phase");
|
|
6720
6768
|
}
|
|
6721
6769
|
}
|
|
6722
6770
|
async loadRegisteredPhase(extension, registration) {
|
|
6723
6771
|
const extensionBase = extension.path.startsWith("<") ? this.cwd : dirname6(extension.path);
|
|
6724
6772
|
const phase = await loadPhase(resolve5(extensionBase, registration));
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6773
|
+
await this.registerPhaseDefinition(extension, phase);
|
|
6774
|
+
}
|
|
6775
|
+
async registerSkill(extension, registration) {
|
|
6776
|
+
if (typeof registration === "string") {
|
|
6777
|
+
if (registration.length === 0) {
|
|
6778
|
+
throw new Error(`Skill registration requires a directory path.`);
|
|
6779
|
+
}
|
|
6780
|
+
return this.loadRegisteredSkill(extension, registration);
|
|
6781
|
+
}
|
|
6782
|
+
if (typeof registration === "object" && registration !== null && "name" in registration) {
|
|
6783
|
+
return this.registerSkillDefinition(extension, registration);
|
|
6784
|
+
}
|
|
6785
|
+
throw new Error(`Skill registration requires a directory path or Skill object.`);
|
|
6786
|
+
}
|
|
6787
|
+
async registerSkillDefinition(extension, skill) {
|
|
6788
|
+
const name = skill.name;
|
|
6789
|
+
const existing = this.skills.get(name);
|
|
6790
|
+
if (existing && existing.source.extensionPath !== extension.path) {
|
|
6791
|
+
for (const ext of this.extensions) {
|
|
6792
|
+
if (ext.path === existing.source.extensionPath) {
|
|
6793
|
+
ext.skills.delete(name);
|
|
6794
|
+
break;
|
|
6795
|
+
}
|
|
6796
|
+
}
|
|
6728
6797
|
}
|
|
6729
6798
|
const registered = {
|
|
6730
|
-
definition:
|
|
6799
|
+
definition: skill,
|
|
6731
6800
|
source: { extensionPath: extension.path }
|
|
6732
6801
|
};
|
|
6733
|
-
this.
|
|
6734
|
-
extension.
|
|
6735
|
-
this.
|
|
6802
|
+
this.skills.set(name, registered);
|
|
6803
|
+
extension.skills.add(name);
|
|
6804
|
+
await this.notifyResourceChange("skill");
|
|
6805
|
+
}
|
|
6806
|
+
async unregisterSkill(extension, skillName) {
|
|
6807
|
+
const registered = this.skills.get(skillName);
|
|
6808
|
+
if (registered && registered.source.extensionPath === extension.path) {
|
|
6809
|
+
this.skills.delete(skillName);
|
|
6810
|
+
extension.skills.delete(skillName);
|
|
6811
|
+
await this.notifyResourceChange("skill");
|
|
6812
|
+
}
|
|
6813
|
+
}
|
|
6814
|
+
async loadRegisteredSkill(extension, registration) {
|
|
6815
|
+
const extensionBase = extension.path.startsWith("<") ? this.cwd : dirname6(extension.path);
|
|
6816
|
+
const skill = await loadSkill(resolve5(extensionBase, registration));
|
|
6817
|
+
await this.registerSkillDefinition(extension, skill);
|
|
6736
6818
|
}
|
|
6737
6819
|
registerProvider(config) {
|
|
6738
6820
|
if (this.bound) {
|
|
@@ -6771,7 +6853,18 @@ var ExtensionRunner = class {
|
|
|
6771
6853
|
}
|
|
6772
6854
|
async disposeExtension(extension, message) {
|
|
6773
6855
|
extension.runtime.invalidate(message);
|
|
6856
|
+
const hadTools = extension.tools.size > 0;
|
|
6857
|
+
const hadPhases = extension.phases.size > 0;
|
|
6858
|
+
const hadSkills = extension.skills.size > 0;
|
|
6859
|
+
extension.tools.clear();
|
|
6774
6860
|
for (const name of extension.phases) this.phases.delete(name);
|
|
6861
|
+
extension.phases.clear();
|
|
6862
|
+
for (const name of extension.skills) {
|
|
6863
|
+
if (this.skills.get(name)?.source.extensionPath === extension.path) {
|
|
6864
|
+
this.skills.delete(name);
|
|
6865
|
+
}
|
|
6866
|
+
}
|
|
6867
|
+
extension.skills.clear();
|
|
6775
6868
|
const hadCapabilities = extension.capabilities.size > 0;
|
|
6776
6869
|
extension.capabilities.clear();
|
|
6777
6870
|
for (const cleanup of [...extension.cleanup].reverse()) {
|
|
@@ -6789,6 +6882,11 @@ var ExtensionRunner = class {
|
|
|
6789
6882
|
if (hadCapabilities) {
|
|
6790
6883
|
this.notifyCapabilitiesChanged();
|
|
6791
6884
|
}
|
|
6885
|
+
if (this.bound) {
|
|
6886
|
+
if (hadTools) await this.notifyResourceChange("tool");
|
|
6887
|
+
if (hadPhases) await this.notifyResourceChange("phase");
|
|
6888
|
+
if (hadSkills) await this.notifyResourceChange("skill");
|
|
6889
|
+
}
|
|
6792
6890
|
}
|
|
6793
6891
|
};
|
|
6794
6892
|
function createExtensionRunner(options) {
|
|
@@ -7409,12 +7507,18 @@ var RuntimeExtensionLifetime = class {
|
|
|
7409
7507
|
phases() {
|
|
7410
7508
|
return this.runner.getPhases();
|
|
7411
7509
|
}
|
|
7510
|
+
skills() {
|
|
7511
|
+
return this.runner.getSkills();
|
|
7512
|
+
}
|
|
7412
7513
|
get extensionRunner() {
|
|
7413
7514
|
return this.runner;
|
|
7414
7515
|
}
|
|
7415
7516
|
get extensionHost() {
|
|
7416
7517
|
return this.runner.extensionHost;
|
|
7417
7518
|
}
|
|
7519
|
+
onResourceChange(listener) {
|
|
7520
|
+
return this.runner.onResourceChange(listener);
|
|
7521
|
+
}
|
|
7418
7522
|
dropRunState(runId) {
|
|
7419
7523
|
this.runner.dropRunState(runId);
|
|
7420
7524
|
}
|
|
@@ -7428,9 +7532,24 @@ var RuntimeBootstrapRegistry = class extends ResourceRegistry {
|
|
|
7428
7532
|
constructor(extensions = new RuntimeExtensionLifetime()) {
|
|
7429
7533
|
super();
|
|
7430
7534
|
this.extensions = extensions;
|
|
7535
|
+
this.extensions.onResourceChange((kind) => this.recommit(kind));
|
|
7431
7536
|
}
|
|
7432
7537
|
extensions;
|
|
7433
7538
|
extensionSourceId = "rowan.extensions";
|
|
7539
|
+
commitQueue = Promise.resolve();
|
|
7540
|
+
recommit(kind) {
|
|
7541
|
+
const next = this.commitQueue.then(async () => {
|
|
7542
|
+
if (kind === "tool") {
|
|
7543
|
+
await this.replaceImplicit("tool", this.extensionSourceId, this.extensions.tools().map(adaptExtensionTool));
|
|
7544
|
+
} else if (kind === "phase") {
|
|
7545
|
+
await this.replaceImplicit("phase", this.extensionSourceId, [...this.extensions.phases()]);
|
|
7546
|
+
} else if (kind === "skill") {
|
|
7547
|
+
await this.replaceImplicit("skill", this.extensionSourceId, [...this.extensions.skills()]);
|
|
7548
|
+
}
|
|
7549
|
+
});
|
|
7550
|
+
this.commitQueue = next.catch(() => void 0);
|
|
7551
|
+
return next;
|
|
7552
|
+
}
|
|
7434
7553
|
get extensionHost() {
|
|
7435
7554
|
return this.extensions.extensionHost;
|
|
7436
7555
|
}
|
|
@@ -7446,8 +7565,9 @@ var RuntimeBootstrapRegistry = class extends ResourceRegistry {
|
|
|
7446
7565
|
})();
|
|
7447
7566
|
const normalized = await loaded;
|
|
7448
7567
|
const result = await this.extensions.activate(normalized.extensions);
|
|
7449
|
-
await this.
|
|
7450
|
-
await this.
|
|
7568
|
+
await this.recommit("tool");
|
|
7569
|
+
await this.recommit("phase");
|
|
7570
|
+
await this.recommit("skill");
|
|
7451
7571
|
return {
|
|
7452
7572
|
...result,
|
|
7453
7573
|
revision: `extensions:${Date.now()}`,
|