@xopcai/xopc 0.0.20 → 0.0.21
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/extensions/feishu/src/adapters/cli-login.d.ts +8 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js +225 -0
- package/dist/extensions/feishu/src/adapters/cli-login.js.map +1 -0
- package/dist/extensions/feishu/src/adapters/onboard-cli.js +1 -105
- package/dist/extensions/feishu/src/adapters/onboard-cli.js.map +1 -1
- package/dist/extensions/feishu/src/auth/app-registration.d.ts +47 -0
- package/dist/extensions/feishu/src/auth/app-registration.js +122 -0
- package/dist/extensions/feishu/src/auth/app-registration.js.map +1 -0
- package/dist/extensions/feishu/src/plugin.d.ts +2 -0
- package/dist/extensions/feishu/src/plugin.js +2 -0
- package/dist/extensions/feishu/src/plugin.js.map +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.d.ts +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/gateway/static/root/assets/{agents-DbLV2ldC.js → agents-MbH57-L9.js} +2 -2
- package/dist/gateway/static/root/assets/{agents-DbLV2ldC.js.map → agents-MbH57-L9.js.map} +1 -1
- package/dist/gateway/static/root/assets/{apps-page-CDRSbv3l.js → apps-page-3i3DvI7i.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-CDRSbv3l.js.map → apps-page-3i3DvI7i.js.map} +1 -1
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js +9 -0
- package/dist/gateway/static/root/assets/channels-settings-CcuSzoB6.js.map +1 -0
- package/dist/gateway/static/root/assets/{cron-page-D-fhl446.js → cron-page-Be1h9Yub.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-D-fhl446.js.map → cron-page-Be1h9Yub.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-DqyPqEDr.js → cron-utils-CR97EvZS.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-DqyPqEDr.js.map → cron-utils-CR97EvZS.js.map} +1 -1
- package/dist/gateway/static/root/assets/{dist-BTNDXpKu.js → dist-r_Gy-XJv.js} +2 -2
- package/dist/gateway/static/root/assets/{dist-BTNDXpKu.js.map → dist-r_Gy-XJv.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-CiOtMG3X.js → extension-debug-page-QfYEYruq.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-CiOtMG3X.js.map → extension-debug-page-QfYEYruq.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-a59AFw7Q.js → extension-page-4FW-BmKG.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-a59AFw7Q.js.map → extension-page-4FW-BmKG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BQyLvxBY.js → extension-settings-page-E_Wq9LL8.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-BQyLvxBY.js.map → extension-settings-page-E_Wq9LL8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{index-fGYWcYhm.js → index-CcQtNJKo.js} +60 -54
- package/dist/gateway/static/root/assets/{index-fGYWcYhm.js.map → index-CcQtNJKo.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-D9Wmfh2f.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-DMSWW0-k.js → logs-page-DFhTU-kG.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-DMSWW0-k.js.map → logs-page-DFhTU-kG.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-CL2E3nPk.js → sessions-page-wmnnIj6Z.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-CL2E3nPk.js.map → sessions-page-wmnnIj6Z.js.map} +1 -1
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js +2 -0
- package/dist/gateway/static/root/assets/settings-page-BTmUXY4s.js.map +1 -0
- package/dist/gateway/static/root/assets/{skills-page-0rmNu4AL.js → skills-page-D-fRbJG0.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-0rmNu4AL.js.map → skills-page-D-fRbJG0.js.map} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +6 -6
- package/dist/src/agent/context/workspace-seed.js +1 -1
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.d.ts +2 -1
- package/dist/src/agent/memory/builtin-memory-store.js +7 -6
- package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/memory/index.d.ts +4 -2
- package/dist/src/agent/prompt/memory/index.js +22 -10
- package/dist/src/agent/prompt/memory/index.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +1 -1
- package/dist/src/agent/service.js +5 -5
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/factory.js +10 -3
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/index.d.ts +1 -1
- package/dist/src/agent/tools/memory-tool.d.ts +7 -2
- package/dist/src/agent/tools/memory-tool.js +11 -5
- package/dist/src/agent/tools/memory-tool.js.map +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/registry.d.ts +1 -1
- package/dist/src/channels/registry.js +25 -1
- package/dist/src/channels/registry.js.map +1 -1
- package/dist/src/chat-commands/builtins/config.js +3 -3
- package/dist/src/chat-commands/builtins/session.js +1 -1
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/chat-commands/index.js +1 -1
- package/dist/src/chat-commands/processor.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/channels.js +20 -2
- package/dist/src/cli/commands/channels.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/gateway/call.d.ts +2 -0
- package/dist/src/cli/commands/gateway/call.js +90 -0
- package/dist/src/cli/commands/gateway/call.js.map +1 -0
- package/dist/src/cli/commands/gateway/health.d.ts +2 -0
- package/dist/src/cli/commands/gateway/health.js +77 -0
- package/dist/src/cli/commands/gateway/health.js.map +1 -0
- package/dist/src/cli/commands/gateway/index.d.ts +3 -0
- package/dist/src/cli/commands/gateway/index.js +4 -1
- package/dist/src/cli/commands/gateway/probe.d.ts +2 -0
- package/dist/src/cli/commands/gateway/probe.js +102 -0
- package/dist/src/cli/commands/gateway/probe.js.map +1 -0
- package/dist/src/cli/commands/gateway/status.d.ts +0 -3
- package/dist/src/cli/commands/gateway/status.js +107 -24
- package/dist/src/cli/commands/gateway/status.js.map +1 -1
- package/dist/src/cli/commands/gateway.js +7 -1
- package/dist/src/cli/commands/gateway.js.map +1 -1
- package/dist/src/cli/commands/init.js +3 -3
- package/dist/src/cli/commands/update.js +19 -1
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/cli/utils/gateway-client.d.ts +28 -0
- package/dist/src/cli/utils/gateway-client.js +115 -0
- package/dist/src/cli/utils/gateway-client.js.map +1 -0
- package/dist/src/config/index.js +2 -2
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/paths-state.d.ts +4 -0
- package/dist/src/config/paths-state.js +9 -1
- package/dist/src/config/paths-state.js.map +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/reload.d.ts +2 -0
- package/dist/src/config/reload.js +9 -1
- package/dist/src/config/reload.js.map +1 -1
- package/dist/src/config/rules.js +12 -2
- package/dist/src/config/rules.js.map +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/extensions/api.d.ts +6 -1
- package/dist/src/extensions/api.js +52 -1
- package/dist/src/extensions/api.js.map +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.d.ts +6 -1
- package/dist/src/extensions/loader.js +21 -2
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/extensions/normalize-manifest.js +33 -0
- package/dist/src/extensions/normalize-manifest.js.map +1 -1
- package/dist/src/extensions/sdk/index.d.ts +1 -1
- package/dist/src/extensions/sdk/index.js.map +1 -1
- package/dist/src/extensions/types/core.d.ts +35 -1
- package/dist/src/extensions/types/manifest.d.ts +14 -0
- package/dist/src/gateway/agents-admin.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -0
- package/dist/src/gateway/hono/lib/config-payload.js +1 -0
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/channels.js +111 -0
- package/dist/src/gateway/hono/routes/channels.js.map +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +13 -2
- package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
- package/dist/src/gateway/hono/routes/config.js +82 -1
- package/dist/src/gateway/hono/routes/config.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +17 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/sessions.js +16 -0
- package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
- package/dist/src/gateway/hono/routes/status.js +31 -7
- package/dist/src/gateway/hono/routes/status.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.js +118 -15
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/index.js +1 -1
- package/dist/src/gateway/server.js +3 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +23 -0
- package/dist/src/gateway/service.js +111 -4
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
- package/dist/src/infra/update-check.js +54 -21
- package/dist/src/infra/update-check.js.map +1 -1
- package/dist/src/infra/update-lock.d.ts +13 -0
- package/dist/src/infra/update-lock.js +67 -0
- package/dist/src/infra/update-lock.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +6 -5
- package/dist/src/infra/update-runner.js +93 -13
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.js +37 -11
- package/dist/src/infra/update-startup.js.map +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/config-store.js +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.js +3 -3
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/channels-settings-DyNnMN1-.js +0 -9
- package/dist/gateway/static/root/assets/channels-settings-DyNnMN1-.js.map +0 -1
- package/dist/gateway/static/root/assets/index-BQNdJlkw.css +0 -1
- package/dist/gateway/static/root/assets/settings-page-CSIVMAJE.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-CSIVMAJE.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { init_paths, resolveExtensionsDir } from "../config/paths.js";
|
|
2
2
|
import { getExtensionLockfileManager } from "./lockfile.js";
|
|
3
|
-
import { readFile, readdir } from "fs/promises";
|
|
4
3
|
import { join } from "path";
|
|
5
4
|
import { existsSync } from "fs";
|
|
5
|
+
import { readFile, readdir } from "fs/promises";
|
|
6
6
|
//#region src/extensions/health.ts
|
|
7
7
|
init_paths();
|
|
8
8
|
var ExtensionHealthChecker = class {
|
|
@@ -10,7 +10,7 @@ import type { Config } from '../config/config-surface.js';
|
|
|
10
10
|
import type { MessageBus } from '../infra/bus/index.js';
|
|
11
11
|
import type { SessionManager } from '../session/manager.js';
|
|
12
12
|
import type { AgentTool } from '@mariozechner/pi-agent-core';
|
|
13
|
-
import type { ExtensionApi, ExtensionRegistry, ExtensionCliRegistration, GatewayMethodHandler, HttpRequestHandler, ExtensionCommand, ExtensionService, ExtensionHookEvent, ExtensionHookHandler, ExtensionManifest, ExtensionRecord, ResolvedExtensionConfig, DiscoveredExtension } from './types/index.js';
|
|
13
|
+
import type { ExtensionApi, ExtensionRegistry, ExtensionCliRegistration, GatewayMethodHandler, HttpRequestHandler, ExtensionCommand, ExtensionReloadRegistration, ExtensionService, ExtensionHookEvent, ExtensionHookHandler, ExtensionManifest, ExtensionRecord, ResolvedExtensionConfig, DiscoveredExtension } from './types/index.js';
|
|
14
14
|
import type { ActivationContext } from './activation-planner.js';
|
|
15
15
|
import { ActivationPlanner } from './activation-planner.js';
|
|
16
16
|
import { ManifestRegistry } from './manifest-registry.js';
|
|
@@ -30,6 +30,7 @@ export declare class ExtensionRegistryImpl implements ExtensionRegistry {
|
|
|
30
30
|
tools: Map<string, AgentTool<any, any>>;
|
|
31
31
|
channelPlugins: ChannelPlugin[];
|
|
32
32
|
private cliRegistrations;
|
|
33
|
+
private reloadRegistrations;
|
|
33
34
|
addExtension(record: ExtensionRecord): void;
|
|
34
35
|
getExtension(id: string): ExtensionRecord | undefined;
|
|
35
36
|
getEnabledExtensions(): ExtensionRecord[];
|
|
@@ -51,6 +52,10 @@ export declare class ExtensionRegistryImpl implements ExtensionRegistry {
|
|
|
51
52
|
getAllTools(): any[];
|
|
52
53
|
addCliRegistration(reg: ExtensionCliRegistration): void;
|
|
53
54
|
getCliRegistrations(): readonly ExtensionCliRegistration[];
|
|
55
|
+
addReloadRegistration(reg: ExtensionReloadRegistration): void;
|
|
56
|
+
removeReloadRegistration(extensionId: string): void;
|
|
57
|
+
getReloadRegistrations(): readonly ExtensionReloadRegistration[];
|
|
58
|
+
getMatchingReloadRegistrations(changedPaths: string[]): ExtensionReloadRegistration[];
|
|
54
59
|
}
|
|
55
60
|
export interface ExtensionLoaderOptions {
|
|
56
61
|
workspaceDir?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { init_agent_scope, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
|
|
1
2
|
import { createLogger, createServiceLogger } from "../utils/logger/index.js";
|
|
2
3
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import { init_agent_scope, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
|
|
4
4
|
import { init_paths, resolveBundledExtensionsDir, resolveExtensionSdkPath, resolveExtensionsDir, resolveWorkspaceExtensionsDir } from "../config/paths.js";
|
|
5
5
|
import { init_loader, loadConfig } from "../config/loader.js";
|
|
6
6
|
import { getProviderRegistry, init_plugin_registry } from "../providers/plugin-registry.js";
|
|
@@ -45,6 +45,7 @@ var ExtensionRegistryImpl = class {
|
|
|
45
45
|
tools = /* @__PURE__ */ new Map();
|
|
46
46
|
channelPlugins = [];
|
|
47
47
|
cliRegistrations = [];
|
|
48
|
+
reloadRegistrations = [];
|
|
48
49
|
addExtension(record) {
|
|
49
50
|
this.extensions.set(record.id, record);
|
|
50
51
|
}
|
|
@@ -115,6 +116,22 @@ var ExtensionRegistryImpl = class {
|
|
|
115
116
|
getCliRegistrations() {
|
|
116
117
|
return this.cliRegistrations;
|
|
117
118
|
}
|
|
119
|
+
addReloadRegistration(reg) {
|
|
120
|
+
this.reloadRegistrations = this.reloadRegistrations.filter((r) => r.extensionId !== reg.extensionId);
|
|
121
|
+
this.reloadRegistrations.push(reg);
|
|
122
|
+
}
|
|
123
|
+
removeReloadRegistration(extensionId) {
|
|
124
|
+
this.reloadRegistrations = this.reloadRegistrations.filter((r) => r.extensionId !== extensionId);
|
|
125
|
+
}
|
|
126
|
+
getReloadRegistrations() {
|
|
127
|
+
return this.reloadRegistrations;
|
|
128
|
+
}
|
|
129
|
+
getMatchingReloadRegistrations(changedPaths) {
|
|
130
|
+
return this.reloadRegistrations.filter((reg) => {
|
|
131
|
+
if (reg.configPrefixes.length === 0) return true;
|
|
132
|
+
return reg.configPrefixes.some((prefix) => changedPaths.some((path) => path === prefix || path.startsWith(`${prefix}.`)));
|
|
133
|
+
});
|
|
134
|
+
}
|
|
118
135
|
};
|
|
119
136
|
var ExtensionLoader = class {
|
|
120
137
|
registry;
|
|
@@ -614,7 +631,9 @@ var ExtensionLoader = class {
|
|
|
614
631
|
config: this._appConfig,
|
|
615
632
|
log: logger
|
|
616
633
|
} : void 0;
|
|
617
|
-
|
|
634
|
+
const api = new ExtensionApiImpl(manifest.id, manifest.name, manifest.version, extensionDir, appConfig, extensionOnly, logger, resolvePath, this.registry, runtime);
|
|
635
|
+
if (manifest.reload?.configPrefixes?.length) api._setReloadConfigPrefixes(manifest.reload.configPrefixes);
|
|
636
|
+
return api;
|
|
618
637
|
}
|
|
619
638
|
async initializeExtension(module, api, _manifest) {
|
|
620
639
|
if (typeof module === "function") await module(api);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","names":["apiImpl"],"sources":["../../../src/extensions/loader.ts"],"sourcesContent":["/**\n * Extension Loader and Registry\n * \n * Supports three-tier extension storage:\n * 1. Workspace level (workspace/.extensions/) - highest priority\n * 2. Global level (~/.xopc/extensions/) - shared across workspaces\n * 3. Bundled level (xopc/extensions/) - shipped with xopc\n */\n\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname, isAbsolute } from 'path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { createJiti } from 'jiti';\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { loadConfig } from '../config/loader.js';\nimport {\n resolveAgentWorkspaceDir,\n resolveExtensionsDir,\n resolveWorkspaceExtensionsDir,\n resolveBundledExtensionsDir,\n resolveExtensionSdkPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/config-surface.js';\nimport type { MessageBus } from '../infra/bus/index.js';\nimport type { SessionManager } from '../session/manager.js';\nimport type { AgentTool } from '@mariozechner/pi-agent-core';\nimport type {\n ExtensionApi,\n ExtensionModule,\n ExtensionRegistry,\n ExtensionCliRegistration,\n GatewayMethodHandler,\n HttpRequestHandler,\n ExtensionCommand,\n ExtensionService,\n ExtensionHookEvent,\n ExtensionHookHandler,\n ExtensionManifest,\n ExtensionRecord,\n ResolvedExtensionConfig,\n DiscoveredExtension,\n} from './types/index.js';\nimport type { ActivationContext } from './activation-planner.js';\nimport { ActivationPlanner } from './activation-planner.js';\nimport { mergeActivationContext } from './activation-context.js';\nimport { ManifestRegistry } from './manifest-registry.js';\nimport { normalizeExtensionManifest } from './normalize-manifest.js';\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport { bundledChannelPlugins } from '../channels/plugins/bundled.js';\nimport { ExtensionApiImpl, createExtensionLogger, createPathResolver } from './api.js';\nimport { createLogger, createServiceLogger } from '../utils/logger.js';\n\n// Security imports\nimport {\n checkExtensionPathSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n type SecurityConfig,\n // Note: ExtensionSourceOrigin is defined locally in this file\n} from './security.js';\n\n// Provider imports\nimport { getProviderRegistry, type ProviderPluginRegistry } from '../providers/plugin-registry.js';\n\n// Slot imports\nimport {\n getSlotRegistry,\n type SlotRegistry,\n type SlotKey,\n} from './slots.js';\n\n// Diagnostics imports\nimport {\n getExtensionCache,\n getExtensionDiagnostics,\n type ExtensionLoaderCache,\n type ExtensionDiagnostics,\n} from './diagnostics.js';\n\nconst EXTENSION_MANIFEST_FILE = 'xopc.extension.json';\n\nconst log = createLogger('ExtensionLoader');\n\n// Extension source origin for debugging\nexport type ExtensionSourceOrigin = 'workspace' | 'global' | 'bundled' | 'config';\n\n// ============================================================================\n// Extension Registry\n// ============================================================================\n\nexport class ExtensionRegistryImpl implements ExtensionRegistry {\n extensions = new Map<string, ExtensionRecord>();\n hooks = new Map<ExtensionHookEvent, ExtensionHookHandler[]>();\n httpRoutes = new Map<string, HttpRequestHandler>();\n commands = new Map<string, ExtensionCommand>();\n services = new Map<string, ExtensionService>();\n gatewayMethods = new Map<string, GatewayMethodHandler>();\n tools: Map<string, AgentTool<any, any>> = new Map();\n channelPlugins: ChannelPlugin[] = [];\n private cliRegistrations: ExtensionCliRegistration[] = [];\n\n addExtension(record: ExtensionRecord): void {\n this.extensions.set(record.id, record);\n }\n\n getExtension(id: string): ExtensionRecord | undefined {\n return this.extensions.get(id);\n }\n\n getEnabledExtensions(): ExtensionRecord[] {\n return Array.from(this.extensions.values()).filter((p) => p.enabled);\n }\n\n addHook(\n event: ExtensionHookEvent,\n handler: ExtensionHookHandler,\n extensionId: string,\n _priority = 0,\n ): void {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n this.hooks.get(event)!.push(handler);\n }\n\n getHooks(event: ExtensionHookEvent): ExtensionHookHandler[] {\n return this.hooks.get(event) || [];\n }\n\n addChannelPlugin(plugin: ChannelPlugin): void {\n this.channelPlugins = this.channelPlugins.filter((p) => p.id !== plugin.id);\n this.channelPlugins.push(plugin);\n }\n\n addHttpRoute(path: string, handler: HttpRequestHandler): void {\n if (this.httpRoutes.has(path)) {\n log.warn({ path }, `HTTP route already registered, overwriting`);\n }\n this.httpRoutes.set(path, handler);\n }\n\n getHttpRoute(path: string): HttpRequestHandler | undefined {\n return this.httpRoutes.get(path);\n }\n\n addCommand(command: ExtensionCommand): void {\n if (this.commands.has(command.name)) {\n log.warn({ command: command.name }, `Command already registered, overwriting`);\n }\n this.commands.set(command.name, command);\n }\n\n getCommand(name: string): ExtensionCommand | undefined {\n return this.commands.get(name);\n }\n\n addService(service: ExtensionService): void {\n if (this.services.has(service.id)) {\n log.warn({ service: service.id }, `Service already registered, overwriting`);\n }\n this.services.set(service.id, service);\n }\n\n getService(id: string): ExtensionService | undefined {\n return this.services.get(id);\n }\n\n addGatewayMethod(method: string, handler: GatewayMethodHandler): void {\n if (this.gatewayMethods.has(method)) {\n log.warn({ method }, `Gateway method already registered, overwriting`);\n }\n this.gatewayMethods.set(method, handler);\n }\n\n getGatewayMethod(method: string): GatewayMethodHandler | undefined {\n return this.gatewayMethods.get(method);\n }\n\n // Tools\n addTool(tool: any): void {\n if (this.tools.has(tool.name)) {\n log.warn({ tool: tool.name }, `Tool already registered, overwriting`);\n }\n this.tools.set(tool.name, tool);\n }\n\n removeTool(name: string): void {\n this.tools.delete(name);\n }\n\n getTools(): Map<string, any> {\n return this.tools;\n }\n\n getTool(name: string): any | undefined {\n return this.tools.get(name);\n }\n\n getAllTools(): any[] {\n return Array.from(this.tools.values());\n }\n\n addCliRegistration(reg: ExtensionCliRegistration): void {\n this.cliRegistrations.push(reg);\n }\n\n getCliRegistrations(): readonly ExtensionCliRegistration[] {\n return this.cliRegistrations;\n }\n}\n\n// ============================================================================\n// Extension Loader\n// ============================================================================\n\nexport interface ExtensionLoaderOptions {\n workspaceDir?: string;\n extensionsDir?: string;\n bundledExtensions?: string[];\n}\n\nexport class ExtensionLoader {\n private registry: ExtensionRegistryImpl;\n private options: ExtensionLoaderOptions;\n private extensionInstances: Map<string, ExtensionApi> = new Map();\n private jiti: ReturnType<typeof createJiti>;\n private _appConfig?: Config;\n private _runtimeContext?: { bus: MessageBus; sessionManager?: SessionManager };\n \n // Security\n private securityConfig: SecurityConfig;\n \n // Provider Registry\n private providerRegistry: ProviderPluginRegistry;\n \n // Slot Registry & Config\n private slotRegistry: SlotRegistry;\n private slotsConfig: Partial<Record<SlotKey, string>> = {};\n \n // Cache and Diagnostics\n private cache: ExtensionLoaderCache;\n private diagnostics: ExtensionDiagnostics;\n\n /** Manifest-only registry cache (no runtime module load). */\n private manifestRegistry: ManifestRegistry | null = null;\n\n constructor(options?: ExtensionLoaderOptions) {\n this.registry = new ExtensionRegistryImpl();\n for (const p of bundledChannelPlugins) {\n this.registry.addChannelPlugin(p);\n }\n this.options = options || (() => {\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n return {\n workspaceDir: resolveAgentWorkspaceDir(c, aid),\n extensionsDir: resolveWorkspaceExtensionsDir(c, aid),\n };\n })();\n\n // Initialize security config\n this.securityConfig = DEFAULT_SECURITY_CONFIG;\n \n // Initialize provider registry\n this.providerRegistry = getProviderRegistry();\n \n // Initialize slot registry\n this.slotRegistry = getSlotRegistry();\n \n // Initialize cache and diagnostics \n this.cache = getExtensionCache();\n this.diagnostics = getExtensionDiagnostics();\n\n // Build jiti alias for extension-sdk (+ subpath entry points)\n const alias: Record<string, string> = {};\n const sdkPath = resolveExtensionSdkPath();\n if (sdkPath) {\n alias['xopc/extension-sdk'] = sdkPath;\n const sdkDir = dirname(sdkPath);\n alias['xopc/extension-sdk/core'] = join(sdkDir, 'core.ts');\n alias['xopc/extension-sdk/lazy'] = join(sdkDir, 'lazy.ts');\n alias['xopc/extension-sdk/provider'] = join(sdkDir, 'provider.ts');\n alias['xopc/extension-sdk/channel'] = join(sdkDir, 'channel.ts');\n alias['xopc/extension-sdk/hooks'] = join(sdkDir, 'hooks.ts');\n alias['xopc/extension-sdk/tools'] = join(sdkDir, 'tools.ts');\n alias['xopc/extension-sdk/testing'] = join(sdkDir, 'testing.ts');\n }\n\n // Initialize jiti with TypeScript support and SDK alias\n this.jiti = createJiti(fileURLToPath(import.meta.url), {\n interopDefault: true,\n extensions: ['.ts', '.tsx', '.mts', '.cts', '.js', '.mjs', '.cjs', '.json'],\n alias,\n });\n }\n\n /**\n * Set security configuration \n */\n setSecurityConfig(config: Partial<SecurityConfig>): void {\n this.securityConfig = { ...this.securityConfig, ...config };\n }\n\n /**\n * Get security configuration \n */\n getSecurityConfig(): SecurityConfig {\n return this.securityConfig;\n }\n\n /**\n * Get provider registry \n */\n getProviderRegistry(): ProviderPluginRegistry {\n return this.providerRegistry;\n }\n\n /**\n * Get slot registry \n */\n getSlotRegistry(): SlotRegistry {\n return this.slotRegistry;\n }\n\n /**\n * Get diagnostics \n */\n getDiagnostics(): ExtensionDiagnostics {\n return this.diagnostics;\n }\n\n /**\n * Set configuration from main Config object \n */\n setConfig(config: Config): void {\n this._appConfig = config;\n // Wire slot config\n const slots = (config.extensions as any)?.slots || {};\n this.slotsConfig = {\n memory: slots.memory,\n tts: slots.tts,\n imageGeneration: slots.imageGeneration,\n webSearch: slots.webSearch,\n };\n\n // Wire security config\n const security = (config.extensions as any)?.security;\n if (security) {\n this.securityConfig = {\n checkPermissions: security.checkPermissions ?? true,\n allowUntrusted: security.allowUntrusted ?? false,\n allow: security.allow ?? [],\n trackProvenance: security.trackProvenance ?? true,\n allowPromptInjection: security.allowPromptInjection ?? false,\n };\n }\n }\n\n /**\n * Inject MessageBus and optional SessionManager for ExtensionApi.runtime (Gateway).\n */\n setRuntimeContext(ctx: { bus: MessageBus; sessionManager?: SessionManager }): void {\n this._runtimeContext = ctx;\n }\n\n getRegistry(): ExtensionRegistryImpl {\n return this.registry;\n }\n\n /**\n * Phase 1: build manifest registry (filesystem manifests only, no extension code load).\n */\n buildManifestRegistry(): ManifestRegistry {\n if (this.manifestRegistry) {\n return this.manifestRegistry;\n }\n const discovered = this.discoverExtensions();\n this.manifestRegistry = ManifestRegistry.fromDiscovered(discovered);\n return this.manifestRegistry;\n }\n\n /**\n * Phase 2: activation planner over the manifest registry (pure logic).\n */\n planActivation(_context?: Partial<ActivationContext>): ActivationPlanner {\n return new ActivationPlanner(this.buildManifestRegistry());\n }\n\n /**\n * Phase 3: load only extensions selected by the activation plan.\n */\n async loadByActivationPlan(context?: Partial<ActivationContext>): Promise<void> {\n const registry = this.buildManifestRegistry();\n const planner = new ActivationPlanner(registry);\n const fullContext = mergeActivationContext(this._appConfig, context);\n const activatedIds = planner.getActivatedIds(fullContext).sort((a, b) => a.localeCompare(b));\n\n for (const extensionId of activatedIds) {\n if (this.extensionInstances.has(extensionId)) continue;\n const entry = registry.getEntry(extensionId);\n if (!entry) {\n log.debug(\n { extensionId },\n 'Activation plan references extension id that was not discovered on disk',\n );\n continue;\n }\n\n const config: ResolvedExtensionConfig = {\n id: extensionId,\n name: entry.manifest.name || extensionId,\n source: entry.source,\n path: entry.path,\n enabled: true,\n config: this.resolveExtensionConfig(extensionId),\n };\n\n await this.loadExtension(config);\n }\n }\n\n getManifestRegistry(): ManifestRegistry {\n return this.buildManifestRegistry();\n }\n\n invalidateManifestCache(): void {\n this.manifestRegistry = null;\n }\n\n private resolveExtensionConfig(extensionId: string): Record<string, unknown> {\n if (!this._appConfig) return {};\n const extensionsConfig = (this._appConfig as Record<string, unknown>).extensions as\n | Record<string, unknown>\n | undefined;\n if (!extensionsConfig || typeof extensionsConfig !== 'object') return {};\n const raw = extensionsConfig[extensionId];\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n return {};\n }\n\n /**\n * Discover extensions from all three tiers:\n * 1. Workspace (.extensions/) - highest priority\n * 2. Global (~/.xopc/extensions/) - shared\n * 3. Bundled (xopc/extensions/) - lowest priority\n */\n discoverExtensions(): DiscoveredExtension[] {\n const discovered = new Map<string, DiscoveredExtension>();\n\n // Priority 3: Bundled extensions (lowest)\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir) {\n this.discoverInDirectory(bundledDir, 'bundled', discovered);\n }\n\n // Priority 2: Global extensions\n const globalDir = resolveExtensionsDir();\n this.discoverInDirectory(globalDir, 'global', discovered);\n\n // Priority 1: Workspace extensions (highest, can override)\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n const workspaceExtensionsDir = resolveWorkspaceExtensionsDir(c, aid);\n this.discoverInDirectory(workspaceExtensionsDir, 'workspace', discovered);\n\n return Array.from(discovered.values());\n }\n\n private discoverInDirectory(\n dir: string,\n source: ExtensionSourceOrigin,\n discovered: Map<string, DiscoveredExtension>,\n ): void {\n if (!existsSync(dir)) {\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const extensionPath = join(dir, entry);\n\n // Check if it's a directory\n try {\n const stat = existsSync(extensionPath);\n if (!stat) continue;\n } catch {\n continue;\n }\n\n // Try to load manifest\n const manifest = this.loadManifest(extensionPath);\n if (!manifest) continue;\n\n const extensionId = manifest.id || entry;\n\n // Higher priority origins can override lower ones\n const existing = discovered.get(extensionId);\n if (existing) {\n const priority = { workspace: 3, global: 2, bundled: 1, config: 0 };\n if (priority[source] <= priority[existing.source]) {\n log.debug(\n { extensionId, from: source, existing: existing.source },\n 'Skipping lower priority extension',\n );\n continue;\n }\n log.info(\n { extensionId, from: source, overriding: existing.source },\n 'Extension override by higher priority source',\n );\n }\n\n discovered.set(extensionId, {\n id: extensionId,\n path: extensionPath,\n source,\n manifest,\n });\n }\n }\n\n /**\n * Load all discovered extensions\n */\n async loadAllExtensions(enabledIds?: string[]): Promise<void> {\n const extensions = this.discoverExtensions();\n\n for (const extension of extensions) {\n // If enabledIds specified, only load those\n if (enabledIds && !enabledIds.includes(extension.id)) {\n continue;\n }\n\n const config: ResolvedExtensionConfig = {\n id: extension.id,\n name: extension.manifest.name || extension.id,\n source: extension.source,\n path: extension.path,\n enabled: true,\n config: {},\n };\n\n await this.loadExtension(config);\n }\n }\n\n async loadExtensions(configs: ResolvedExtensionConfig[]): Promise<void> {\n for (const extensionConfig of configs) {\n if (extensionConfig.enabled) {\n await this.loadExtension(extensionConfig);\n }\n }\n }\n\n async loadExtension(config: ResolvedExtensionConfig): Promise<ExtensionApi | null> {\n try {\n // Check cache first\n const cacheKey = this.cache.buildKey(this.options, [config.id]);\n const cached = this.cache.get<ExtensionApi>(cacheKey);\n if (cached) {\n log.debug({ extensionId: config.id }, 'Extension loaded from cache');\n return cached;\n }\n\n // Check if already loaded\n if (this.extensionInstances.has(config.id)) {\n return this.extensionInstances.get(config.id)!;\n }\n\n // Resolve extension path using resolveExtensionPath\n let extensionPath: string | null;\n if (isAbsolute(config.path)) {\n extensionPath = config.path;\n } else {\n // Try to resolve extension ID to actual path\n extensionPath = resolveExtensionPath(config.path, this.options) ||\n resolveExtensionPath(config.id, this.options);\n }\n \n if (!extensionPath) {\n log.error({ extensionId: config.id, path: config.path }, `Could not resolve extension path`);\n this.diagnostics.error(config.id, `Could not resolve extension path: ${config.path}`);\n return null;\n }\n\n log.debug({ extensionId: config.id, extensionPath }, 'Resolved extension path');\n\n // Security check\n const source = config.source || 'bundled';\n const safetyResult = checkExtensionPathSafety(extensionPath, extensionPath, source);\n \n if (!safetyResult.safe) {\n logSecurityIssue(config.id, safetyResult);\n \n if (this.securityConfig.checkPermissions && source !== 'bundled') {\n // Check allowlist\n if (!isExtensionAllowed(config.id, this.securityConfig)) {\n this.diagnostics.error(config.id, `Extension not allowed: ${safetyResult.detail}`);\n log.error({ extensionId: config.id, reason: safetyResult.reason }, 'Extension blocked by security policy');\n return null;\n }\n }\n }\n\n // Track provenance \n provenanceTracker.track(config.id, source);\n\n const manifest = this.loadManifest(extensionPath);\n if (!manifest) {\n log.error({ extensionId: config.id, extensionPath }, `Failed to load manifest for extension`);\n this.diagnostics.error(config.id, `Failed to load manifest`);\n return null;\n }\n\n // Validate extension config against schema (basic validation)\n if (manifest.configSchema) {\n try {\n const schema = manifest.configSchema as Record<string, unknown>;\n const extensionConfig = config.config as Record<string, unknown>;\n \n // Basic validation: check required fields and types\n if (schema.type === 'object' && schema.properties) {\n const props = schema.properties as Record<string, Record<string, unknown>>;\n const required = (schema.required as string[]) || [];\n \n for (const field of required) {\n if (extensionConfig[field] === undefined) {\n log.error({ \n extensionId: config.id, \n field \n }, 'Extension config validation failed: missing required field');\n return null;\n }\n }\n \n for (const [key, value] of Object.entries(extensionConfig)) {\n const propSchema = props[key];\n if (propSchema) {\n if (propSchema.type && !this.validateType(value, propSchema.type as string)) {\n log.error({ \n extensionId: config.id, \n field: key,\n expected: propSchema.type,\n actual: typeof value\n }, 'Extension config validation failed: type mismatch');\n return null;\n }\n }\n }\n }\n \n log.debug({ extensionId: config.id }, 'Extension config validated');\n } catch (err) {\n log.warn({ err, extensionId: config.id }, 'Config schema validation skipped');\n }\n }\n\n // Create extension API\n const extensionDir = dirname(extensionPath);\n const api = this.createExtensionApi(manifest, config, extensionDir);\n\n // Load extension module\n const module = await this.loadModule(extensionPath, manifest);\n if (!module) {\n log.error({ extensionId: config.id }, `Failed to load module for extension`);\n this.diagnostics.error(config.id, `Failed to load module`);\n return null;\n }\n\n // Check and claim slots\n const slotClaimed = this.claimExtensionSlots(config.id, manifest);\n if (!slotClaimed) {\n log.warn({ extensionId: config.id }, 'Failed to claim required slots');\n }\n\n // Initialize extension\n await this.initializeExtension(module, api, manifest);\n\n // Register to registry\n this.registry.addExtension({\n id: config.id,\n name: manifest.name,\n version: manifest.version,\n path: extensionPath,\n module,\n config: config.config,\n enabled: true,\n source: config.source,\n });\n\n // Register extension tools to registry (so AgentManager can access them)\n // Note: api is actually ExtensionApiImpl at runtime\n const apiImpl = api as unknown as { _getTools: () => Map<string, AgentTool> };\n const extensionTools = apiImpl._getTools();\n for (const tool of extensionTools.values()) {\n this.registry.addTool(tool);\n }\n\n this.extensionInstances.set(config.id, api);\n \n // Cache the loaded extension\n this.cache.set(cacheKey, api);\n\n this.diagnostics.info(config.id, `Loaded extension: ${manifest.name}`);\n log.info({ name: manifest.name, id: manifest.id, source: config.source }, `Loaded extension`);\n\n return api;\n } catch (error) {\n log.error({ err: error, extensionId: config.id }, `Error loading extension`);\n this.diagnostics.error(config.id, `Error loading extension: ${error}`);\n return null;\n }\n }\n\n /**\n * Claim extension slots based on manifest kind\n * Respects configured preferred plugin from config.extensions.slots\n */\n private claimExtensionSlots(extensionId: string, manifest: ExtensionManifest): boolean {\n const kind = manifest.kind as string;\n \n // Map extension kind to slot\n const slotMap: Record<string, SlotKey> = {\n 'memory': 'memory',\n 'tts': 'tts',\n 'image-generation': 'imageGeneration',\n 'imageGeneration': 'imageGeneration',\n 'web-search': 'webSearch',\n 'webSearch': 'webSearch',\n };\n \n const slotKey = slotMap[kind];\n if (!slotKey) {\n return true; // No slot required\n }\n \n // Check if slot is reserved for a different plugin in config\n const preferredPlugin = this.slotsConfig[slotKey];\n if (preferredPlugin && preferredPlugin !== extensionId) {\n log.info(\n { extensionId, slotKey, preferredPlugin },\n `Skipping slot claim: slot \"${slotKey}\" is reserved for \"${preferredPlugin}\"`\n );\n this.diagnostics.info(\n extensionId,\n `Slot \"${slotKey}\" is reserved for \"${preferredPlugin}\", skipping claim`\n );\n return false;\n }\n \n const claimed = this.slotRegistry.claim(slotKey, extensionId, null);\n if (!claimed) {\n this.diagnostics.warn(extensionId, `Slot \"${slotKey}\" already claimed by another extension`);\n }\n return claimed;\n }\n\n loadManifest(extensionPath: string): ExtensionManifest | null {\n const manifestPath = join(extensionPath, EXTENSION_MANIFEST_FILE);\n\n // First try to load xopc.extension.json\n if (existsSync(manifestPath)) {\n try {\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n log.error({ manifestPath }, 'Manifest root must be a JSON object');\n return null;\n }\n return normalizeExtensionManifest(raw as Record<string, unknown>);\n } catch (error) {\n log.error({ err: error, manifestPath }, `Failed to parse manifest`);\n return null;\n }\n }\n\n // Fallback to package.json\n const packagePath = join(extensionPath, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));\n \n // Check for xopc.extension marker\n if (packageJson.xopc?.extension) {\n const xopcConfig = packageJson.xopc;\n return normalizeExtensionManifest({\n id: xopcConfig.id || packageJson.name,\n name: xopcConfig.name || packageJson.name,\n description: xopcConfig.description || packageJson.description,\n version: xopcConfig.version || packageJson.version || '1.0.0',\n kind: xopcConfig.kind || 'utility',\n main: xopcConfig.main || packageJson.main || 'index.js',\n configSchema: xopcConfig.configSchema,\n });\n }\n\n // Also support xopc-extension-* naming convention\n if (packageJson.name?.startsWith('xopc-extension-')) {\n const id = packageJson.name.replace('xopc-extension-', '');\n return normalizeExtensionManifest({\n id,\n name: packageJson.name,\n description: packageJson.description,\n version: packageJson.version || '1.0.0',\n kind: 'utility',\n main: packageJson.main || 'index.js',\n });\n }\n } catch (error) {\n log.error({ err: error, packagePath }, `Failed to parse package.json`);\n }\n }\n\n return null;\n }\n\n private async loadModule(\n extensionPath: string,\n manifest: ExtensionManifest,\n ): Promise<ExtensionModule | null> {\n // Determine entry point - .ts files prioritized for development\n const entryPoints = [\n manifest.main,\n 'index.ts',\n 'index.js',\n 'extension.ts',\n 'extension.js',\n ].filter(Boolean) as string[];\n\n for (const entry of entryPoints) {\n const fullPath = isAbsolute(entry) ? entry : join(extensionPath, entry);\n\n if (existsSync(fullPath)) {\n try {\n // Use jiti to load both .ts and .js files\n const mod = this.jiti(fullPath);\n return mod.default || mod;\n } catch (error) {\n log.warn({ err: error, path: fullPath }, `Failed to load module`);\n }\n }\n }\n\n return null;\n }\n\n private createExtensionApi(\n manifest: ExtensionManifest,\n resolved: ResolvedExtensionConfig,\n extensionDir: string,\n ): ExtensionApi {\n const logger = createExtensionLogger(`[${manifest.id}]`);\n const resolvePath = createPathResolver(extensionDir, this.options.workspaceDir || '');\n\n const appConfig = this._appConfig ?? ({} as Config);\n const extensionOnly = (resolved.config ?? {}) as Record<string, unknown>;\n\n const runtime =\n this._appConfig && this._runtimeContext\n ? {\n config: this._appConfig,\n bus: this._runtimeContext.bus,\n log: logger,\n sessionManager: this._runtimeContext.sessionManager,\n }\n : this._appConfig\n ? {\n config: this._appConfig,\n log: logger,\n }\n : undefined;\n\n return new ExtensionApiImpl(\n manifest.id,\n manifest.name,\n manifest.version,\n extensionDir,\n appConfig,\n extensionOnly,\n logger,\n resolvePath,\n this.registry,\n runtime,\n );\n }\n\n private async initializeExtension(\n module: ExtensionModule,\n api: ExtensionApi,\n _manifest: ExtensionManifest,\n ): Promise<void> {\n if (typeof module === 'function') {\n // Module is a function that receives the API\n await module(api);\n } else if (typeof module === 'object' && module.register) {\n // Module is a ExtensionDefinition with register method\n await module.register(api);\n }\n }\n\n async startServices(): Promise<void> {\n const services = Array.from(this.registry.services.values());\n\n for (const service of services) {\n const serviceLog = createServiceLogger(service.id);\n try {\n await service.start?.();\n serviceLog.info(`Started service`);\n } catch (error) {\n serviceLog.error({ err: error }, `Failed to start service`);\n }\n }\n }\n\n async stopServices(): Promise<void> {\n const services = Array.from(this.registry.services.values()).reverse();\n\n for (const service of services) {\n if (service.stop) {\n const serviceLog = createServiceLogger(service.id);\n try {\n await service.stop();\n serviceLog.info(`Stopped service`);\n } catch (error) {\n serviceLog.error({ err: error }, `Failed to stop service`);\n }\n }\n }\n }\n\n /**\n * Basic type validation for config values\n */\n private validateType(value: unknown, expectedType: string): boolean {\n if (expectedType === 'string') return typeof value === 'string';\n if (expectedType === 'number' || expectedType === 'integer') return typeof value === 'number';\n if (expectedType === 'boolean') return typeof value === 'boolean';\n if (expectedType === 'array') return Array.isArray(value);\n if (expectedType === 'object') return typeof value === 'object' && value !== null && !Array.isArray(value);\n return true;\n }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport function resolveExtensionPath(id: string, _options: ExtensionLoaderOptions): string | null {\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n // Priority 1: Workspace\n const workspacePath = join(resolveWorkspaceExtensionsDir(c, aid), id);\n if (existsSync(workspacePath)) return workspacePath;\n\n // Priority 2: Global\n const globalPath = join(resolveExtensionsDir(), id);\n if (existsSync(globalPath)) return globalPath;\n\n // Priority 3: Bundled\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir) {\n const bundledPath = join(bundledDir, id);\n if (existsSync(bundledPath)) return bundledPath;\n }\n\n // Check if it's an npm package\n try {\n const require = createRequire(import.meta.url);\n const resolved = require.resolve(id);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function normalizeExtensionConfig(\n rawConfig: Record<string, unknown>,\n): ResolvedExtensionConfig[] {\n const extensions: ResolvedExtensionConfig[] = [];\n\n const enabled = (rawConfig.enabled as string[]) || [];\n const disabled = (rawConfig.disabled as string[]) || [];\n\n // Parse enabled extensions\n for (const id of enabled) {\n const config = (rawConfig[id] as Record<string, unknown>) || {};\n extensions.push({\n id,\n name: id,\n source: 'config',\n path: id,\n enabled: true,\n config,\n });\n }\n\n // Parse disabled extensions\n for (const id of disabled) {\n if (!extensions.find((p) => p.id === id)) {\n const config = (rawConfig[id] as Record<string, unknown>) || {};\n extensions.push({\n id,\n name: id,\n source: 'config',\n path: id,\n enabled: false,\n config,\n });\n }\n }\n\n return extensions;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"loader.js","names":["apiImpl"],"sources":["../../../src/extensions/loader.ts"],"sourcesContent":["/**\n * Extension Loader and Registry\n * \n * Supports three-tier extension storage:\n * 1. Workspace level (workspace/.extensions/) - highest priority\n * 2. Global level (~/.xopc/extensions/) - shared across workspaces\n * 3. Bundled level (xopc/extensions/) - shipped with xopc\n */\n\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname, isAbsolute } from 'path';\nimport { fileURLToPath } from 'node:url';\nimport { createRequire } from 'node:module';\nimport { createJiti } from 'jiti';\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { loadConfig } from '../config/loader.js';\nimport {\n resolveAgentWorkspaceDir,\n resolveExtensionsDir,\n resolveWorkspaceExtensionsDir,\n resolveBundledExtensionsDir,\n resolveExtensionSdkPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/config-surface.js';\nimport type { MessageBus } from '../infra/bus/index.js';\nimport type { SessionManager } from '../session/manager.js';\nimport type { AgentTool } from '@mariozechner/pi-agent-core';\nimport type {\n ExtensionApi,\n ExtensionModule,\n ExtensionRegistry,\n ExtensionCliRegistration,\n GatewayMethodHandler,\n HttpRequestHandler,\n ExtensionCommand,\n ExtensionReloadRegistration,\n ExtensionService,\n ExtensionHookEvent,\n ExtensionHookHandler,\n ExtensionManifest,\n ExtensionRecord,\n ResolvedExtensionConfig,\n DiscoveredExtension,\n} from './types/index.js';\nimport type { ActivationContext } from './activation-planner.js';\nimport { ActivationPlanner } from './activation-planner.js';\nimport { mergeActivationContext } from './activation-context.js';\nimport { ManifestRegistry } from './manifest-registry.js';\nimport { normalizeExtensionManifest } from './normalize-manifest.js';\nimport type { ChannelPlugin } from '../channels/plugin-types.js';\nimport { bundledChannelPlugins } from '../channels/plugins/bundled.js';\nimport { ExtensionApiImpl, createExtensionLogger, createPathResolver } from './api.js';\nimport { createLogger, createServiceLogger } from '../utils/logger.js';\n\n// Security imports\nimport {\n checkExtensionPathSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n type SecurityConfig,\n // Note: ExtensionSourceOrigin is defined locally in this file\n} from './security.js';\n\n// Provider imports\nimport { getProviderRegistry, type ProviderPluginRegistry } from '../providers/plugin-registry.js';\n\n// Slot imports\nimport {\n getSlotRegistry,\n type SlotRegistry,\n type SlotKey,\n} from './slots.js';\n\n// Diagnostics imports\nimport {\n getExtensionCache,\n getExtensionDiagnostics,\n type ExtensionLoaderCache,\n type ExtensionDiagnostics,\n} from './diagnostics.js';\n\nconst EXTENSION_MANIFEST_FILE = 'xopc.extension.json';\n\nconst log = createLogger('ExtensionLoader');\n\n// Extension source origin for debugging\nexport type ExtensionSourceOrigin = 'workspace' | 'global' | 'bundled' | 'config';\n\n// ============================================================================\n// Extension Registry\n// ============================================================================\n\nexport class ExtensionRegistryImpl implements ExtensionRegistry {\n extensions = new Map<string, ExtensionRecord>();\n hooks = new Map<ExtensionHookEvent, ExtensionHookHandler[]>();\n httpRoutes = new Map<string, HttpRequestHandler>();\n commands = new Map<string, ExtensionCommand>();\n services = new Map<string, ExtensionService>();\n gatewayMethods = new Map<string, GatewayMethodHandler>();\n tools: Map<string, AgentTool<any, any>> = new Map();\n channelPlugins: ChannelPlugin[] = [];\n private cliRegistrations: ExtensionCliRegistration[] = [];\n private reloadRegistrations: ExtensionReloadRegistration[] = [];\n\n addExtension(record: ExtensionRecord): void {\n this.extensions.set(record.id, record);\n }\n\n getExtension(id: string): ExtensionRecord | undefined {\n return this.extensions.get(id);\n }\n\n getEnabledExtensions(): ExtensionRecord[] {\n return Array.from(this.extensions.values()).filter((p) => p.enabled);\n }\n\n addHook(\n event: ExtensionHookEvent,\n handler: ExtensionHookHandler,\n extensionId: string,\n _priority = 0,\n ): void {\n if (!this.hooks.has(event)) {\n this.hooks.set(event, []);\n }\n this.hooks.get(event)!.push(handler);\n }\n\n getHooks(event: ExtensionHookEvent): ExtensionHookHandler[] {\n return this.hooks.get(event) || [];\n }\n\n addChannelPlugin(plugin: ChannelPlugin): void {\n this.channelPlugins = this.channelPlugins.filter((p) => p.id !== plugin.id);\n this.channelPlugins.push(plugin);\n }\n\n addHttpRoute(path: string, handler: HttpRequestHandler): void {\n if (this.httpRoutes.has(path)) {\n log.warn({ path }, `HTTP route already registered, overwriting`);\n }\n this.httpRoutes.set(path, handler);\n }\n\n getHttpRoute(path: string): HttpRequestHandler | undefined {\n return this.httpRoutes.get(path);\n }\n\n addCommand(command: ExtensionCommand): void {\n if (this.commands.has(command.name)) {\n log.warn({ command: command.name }, `Command already registered, overwriting`);\n }\n this.commands.set(command.name, command);\n }\n\n getCommand(name: string): ExtensionCommand | undefined {\n return this.commands.get(name);\n }\n\n addService(service: ExtensionService): void {\n if (this.services.has(service.id)) {\n log.warn({ service: service.id }, `Service already registered, overwriting`);\n }\n this.services.set(service.id, service);\n }\n\n getService(id: string): ExtensionService | undefined {\n return this.services.get(id);\n }\n\n addGatewayMethod(method: string, handler: GatewayMethodHandler): void {\n if (this.gatewayMethods.has(method)) {\n log.warn({ method }, `Gateway method already registered, overwriting`);\n }\n this.gatewayMethods.set(method, handler);\n }\n\n getGatewayMethod(method: string): GatewayMethodHandler | undefined {\n return this.gatewayMethods.get(method);\n }\n\n // Tools\n addTool(tool: any): void {\n if (this.tools.has(tool.name)) {\n log.warn({ tool: tool.name }, `Tool already registered, overwriting`);\n }\n this.tools.set(tool.name, tool);\n }\n\n removeTool(name: string): void {\n this.tools.delete(name);\n }\n\n getTools(): Map<string, any> {\n return this.tools;\n }\n\n getTool(name: string): any | undefined {\n return this.tools.get(name);\n }\n\n getAllTools(): any[] {\n return Array.from(this.tools.values());\n }\n\n addCliRegistration(reg: ExtensionCliRegistration): void {\n this.cliRegistrations.push(reg);\n }\n\n getCliRegistrations(): readonly ExtensionCliRegistration[] {\n return this.cliRegistrations;\n }\n\n addReloadRegistration(reg: ExtensionReloadRegistration): void {\n this.reloadRegistrations = this.reloadRegistrations.filter(\n (r) => r.extensionId !== reg.extensionId,\n );\n this.reloadRegistrations.push(reg);\n }\n\n removeReloadRegistration(extensionId: string): void {\n this.reloadRegistrations = this.reloadRegistrations.filter(\n (r) => r.extensionId !== extensionId,\n );\n }\n\n getReloadRegistrations(): readonly ExtensionReloadRegistration[] {\n return this.reloadRegistrations;\n }\n\n getMatchingReloadRegistrations(changedPaths: string[]): ExtensionReloadRegistration[] {\n return this.reloadRegistrations.filter((reg) => {\n if (reg.configPrefixes.length === 0) {\n return true;\n }\n return reg.configPrefixes.some((prefix) =>\n changedPaths.some((path) => path === prefix || path.startsWith(`${prefix}.`)),\n );\n });\n }\n}\n\n// ============================================================================\n// Extension Loader\n// ============================================================================\n\nexport interface ExtensionLoaderOptions {\n workspaceDir?: string;\n extensionsDir?: string;\n bundledExtensions?: string[];\n}\n\nexport class ExtensionLoader {\n private registry: ExtensionRegistryImpl;\n private options: ExtensionLoaderOptions;\n private extensionInstances: Map<string, ExtensionApi> = new Map();\n private jiti: ReturnType<typeof createJiti>;\n private _appConfig?: Config;\n private _runtimeContext?: { bus: MessageBus; sessionManager?: SessionManager };\n \n // Security\n private securityConfig: SecurityConfig;\n \n // Provider Registry\n private providerRegistry: ProviderPluginRegistry;\n \n // Slot Registry & Config\n private slotRegistry: SlotRegistry;\n private slotsConfig: Partial<Record<SlotKey, string>> = {};\n \n // Cache and Diagnostics\n private cache: ExtensionLoaderCache;\n private diagnostics: ExtensionDiagnostics;\n\n /** Manifest-only registry cache (no runtime module load). */\n private manifestRegistry: ManifestRegistry | null = null;\n\n constructor(options?: ExtensionLoaderOptions) {\n this.registry = new ExtensionRegistryImpl();\n for (const p of bundledChannelPlugins) {\n this.registry.addChannelPlugin(p);\n }\n this.options = options || (() => {\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n return {\n workspaceDir: resolveAgentWorkspaceDir(c, aid),\n extensionsDir: resolveWorkspaceExtensionsDir(c, aid),\n };\n })();\n\n // Initialize security config\n this.securityConfig = DEFAULT_SECURITY_CONFIG;\n \n // Initialize provider registry\n this.providerRegistry = getProviderRegistry();\n \n // Initialize slot registry\n this.slotRegistry = getSlotRegistry();\n \n // Initialize cache and diagnostics \n this.cache = getExtensionCache();\n this.diagnostics = getExtensionDiagnostics();\n\n // Build jiti alias for extension-sdk (+ subpath entry points)\n const alias: Record<string, string> = {};\n const sdkPath = resolveExtensionSdkPath();\n if (sdkPath) {\n alias['xopc/extension-sdk'] = sdkPath;\n const sdkDir = dirname(sdkPath);\n alias['xopc/extension-sdk/core'] = join(sdkDir, 'core.ts');\n alias['xopc/extension-sdk/lazy'] = join(sdkDir, 'lazy.ts');\n alias['xopc/extension-sdk/provider'] = join(sdkDir, 'provider.ts');\n alias['xopc/extension-sdk/channel'] = join(sdkDir, 'channel.ts');\n alias['xopc/extension-sdk/hooks'] = join(sdkDir, 'hooks.ts');\n alias['xopc/extension-sdk/tools'] = join(sdkDir, 'tools.ts');\n alias['xopc/extension-sdk/testing'] = join(sdkDir, 'testing.ts');\n }\n\n // Initialize jiti with TypeScript support and SDK alias\n this.jiti = createJiti(fileURLToPath(import.meta.url), {\n interopDefault: true,\n extensions: ['.ts', '.tsx', '.mts', '.cts', '.js', '.mjs', '.cjs', '.json'],\n alias,\n });\n }\n\n /**\n * Set security configuration \n */\n setSecurityConfig(config: Partial<SecurityConfig>): void {\n this.securityConfig = { ...this.securityConfig, ...config };\n }\n\n /**\n * Get security configuration \n */\n getSecurityConfig(): SecurityConfig {\n return this.securityConfig;\n }\n\n /**\n * Get provider registry \n */\n getProviderRegistry(): ProviderPluginRegistry {\n return this.providerRegistry;\n }\n\n /**\n * Get slot registry \n */\n getSlotRegistry(): SlotRegistry {\n return this.slotRegistry;\n }\n\n /**\n * Get diagnostics \n */\n getDiagnostics(): ExtensionDiagnostics {\n return this.diagnostics;\n }\n\n /**\n * Set configuration from main Config object \n */\n setConfig(config: Config): void {\n this._appConfig = config;\n // Wire slot config\n const slots = (config.extensions as any)?.slots || {};\n this.slotsConfig = {\n memory: slots.memory,\n tts: slots.tts,\n imageGeneration: slots.imageGeneration,\n webSearch: slots.webSearch,\n };\n\n // Wire security config\n const security = (config.extensions as any)?.security;\n if (security) {\n this.securityConfig = {\n checkPermissions: security.checkPermissions ?? true,\n allowUntrusted: security.allowUntrusted ?? false,\n allow: security.allow ?? [],\n trackProvenance: security.trackProvenance ?? true,\n allowPromptInjection: security.allowPromptInjection ?? false,\n };\n }\n }\n\n /**\n * Inject MessageBus and optional SessionManager for ExtensionApi.runtime (Gateway).\n */\n setRuntimeContext(ctx: { bus: MessageBus; sessionManager?: SessionManager }): void {\n this._runtimeContext = ctx;\n }\n\n getRegistry(): ExtensionRegistryImpl {\n return this.registry;\n }\n\n /**\n * Phase 1: build manifest registry (filesystem manifests only, no extension code load).\n */\n buildManifestRegistry(): ManifestRegistry {\n if (this.manifestRegistry) {\n return this.manifestRegistry;\n }\n const discovered = this.discoverExtensions();\n this.manifestRegistry = ManifestRegistry.fromDiscovered(discovered);\n return this.manifestRegistry;\n }\n\n /**\n * Phase 2: activation planner over the manifest registry (pure logic).\n */\n planActivation(_context?: Partial<ActivationContext>): ActivationPlanner {\n return new ActivationPlanner(this.buildManifestRegistry());\n }\n\n /**\n * Phase 3: load only extensions selected by the activation plan.\n */\n async loadByActivationPlan(context?: Partial<ActivationContext>): Promise<void> {\n const registry = this.buildManifestRegistry();\n const planner = new ActivationPlanner(registry);\n const fullContext = mergeActivationContext(this._appConfig, context);\n const activatedIds = planner.getActivatedIds(fullContext).sort((a, b) => a.localeCompare(b));\n\n for (const extensionId of activatedIds) {\n if (this.extensionInstances.has(extensionId)) continue;\n const entry = registry.getEntry(extensionId);\n if (!entry) {\n log.debug(\n { extensionId },\n 'Activation plan references extension id that was not discovered on disk',\n );\n continue;\n }\n\n const config: ResolvedExtensionConfig = {\n id: extensionId,\n name: entry.manifest.name || extensionId,\n source: entry.source,\n path: entry.path,\n enabled: true,\n config: this.resolveExtensionConfig(extensionId),\n };\n\n await this.loadExtension(config);\n }\n }\n\n getManifestRegistry(): ManifestRegistry {\n return this.buildManifestRegistry();\n }\n\n invalidateManifestCache(): void {\n this.manifestRegistry = null;\n }\n\n private resolveExtensionConfig(extensionId: string): Record<string, unknown> {\n if (!this._appConfig) return {};\n const extensionsConfig = (this._appConfig as Record<string, unknown>).extensions as\n | Record<string, unknown>\n | undefined;\n if (!extensionsConfig || typeof extensionsConfig !== 'object') return {};\n const raw = extensionsConfig[extensionId];\n if (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n return raw as Record<string, unknown>;\n }\n return {};\n }\n\n /**\n * Discover extensions from all three tiers:\n * 1. Workspace (.extensions/) - highest priority\n * 2. Global (~/.xopc/extensions/) - shared\n * 3. Bundled (xopc/extensions/) - lowest priority\n */\n discoverExtensions(): DiscoveredExtension[] {\n const discovered = new Map<string, DiscoveredExtension>();\n\n // Priority 3: Bundled extensions (lowest)\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir) {\n this.discoverInDirectory(bundledDir, 'bundled', discovered);\n }\n\n // Priority 2: Global extensions\n const globalDir = resolveExtensionsDir();\n this.discoverInDirectory(globalDir, 'global', discovered);\n\n // Priority 1: Workspace extensions (highest, can override)\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n const workspaceExtensionsDir = resolveWorkspaceExtensionsDir(c, aid);\n this.discoverInDirectory(workspaceExtensionsDir, 'workspace', discovered);\n\n return Array.from(discovered.values());\n }\n\n private discoverInDirectory(\n dir: string,\n source: ExtensionSourceOrigin,\n discovered: Map<string, DiscoveredExtension>,\n ): void {\n if (!existsSync(dir)) {\n return;\n }\n\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const extensionPath = join(dir, entry);\n\n // Check if it's a directory\n try {\n const stat = existsSync(extensionPath);\n if (!stat) continue;\n } catch {\n continue;\n }\n\n // Try to load manifest\n const manifest = this.loadManifest(extensionPath);\n if (!manifest) continue;\n\n const extensionId = manifest.id || entry;\n\n // Higher priority origins can override lower ones\n const existing = discovered.get(extensionId);\n if (existing) {\n const priority = { workspace: 3, global: 2, bundled: 1, config: 0 };\n if (priority[source] <= priority[existing.source]) {\n log.debug(\n { extensionId, from: source, existing: existing.source },\n 'Skipping lower priority extension',\n );\n continue;\n }\n log.info(\n { extensionId, from: source, overriding: existing.source },\n 'Extension override by higher priority source',\n );\n }\n\n discovered.set(extensionId, {\n id: extensionId,\n path: extensionPath,\n source,\n manifest,\n });\n }\n }\n\n /**\n * Load all discovered extensions\n */\n async loadAllExtensions(enabledIds?: string[]): Promise<void> {\n const extensions = this.discoverExtensions();\n\n for (const extension of extensions) {\n // If enabledIds specified, only load those\n if (enabledIds && !enabledIds.includes(extension.id)) {\n continue;\n }\n\n const config: ResolvedExtensionConfig = {\n id: extension.id,\n name: extension.manifest.name || extension.id,\n source: extension.source,\n path: extension.path,\n enabled: true,\n config: {},\n };\n\n await this.loadExtension(config);\n }\n }\n\n async loadExtensions(configs: ResolvedExtensionConfig[]): Promise<void> {\n for (const extensionConfig of configs) {\n if (extensionConfig.enabled) {\n await this.loadExtension(extensionConfig);\n }\n }\n }\n\n async loadExtension(config: ResolvedExtensionConfig): Promise<ExtensionApi | null> {\n try {\n // Check cache first\n const cacheKey = this.cache.buildKey(this.options, [config.id]);\n const cached = this.cache.get<ExtensionApi>(cacheKey);\n if (cached) {\n log.debug({ extensionId: config.id }, 'Extension loaded from cache');\n return cached;\n }\n\n // Check if already loaded\n if (this.extensionInstances.has(config.id)) {\n return this.extensionInstances.get(config.id)!;\n }\n\n // Resolve extension path using resolveExtensionPath\n let extensionPath: string | null;\n if (isAbsolute(config.path)) {\n extensionPath = config.path;\n } else {\n // Try to resolve extension ID to actual path\n extensionPath = resolveExtensionPath(config.path, this.options) ||\n resolveExtensionPath(config.id, this.options);\n }\n \n if (!extensionPath) {\n log.error({ extensionId: config.id, path: config.path }, `Could not resolve extension path`);\n this.diagnostics.error(config.id, `Could not resolve extension path: ${config.path}`);\n return null;\n }\n\n log.debug({ extensionId: config.id, extensionPath }, 'Resolved extension path');\n\n // Security check\n const source = config.source || 'bundled';\n const safetyResult = checkExtensionPathSafety(extensionPath, extensionPath, source);\n \n if (!safetyResult.safe) {\n logSecurityIssue(config.id, safetyResult);\n \n if (this.securityConfig.checkPermissions && source !== 'bundled') {\n // Check allowlist\n if (!isExtensionAllowed(config.id, this.securityConfig)) {\n this.diagnostics.error(config.id, `Extension not allowed: ${safetyResult.detail}`);\n log.error({ extensionId: config.id, reason: safetyResult.reason }, 'Extension blocked by security policy');\n return null;\n }\n }\n }\n\n // Track provenance \n provenanceTracker.track(config.id, source);\n\n const manifest = this.loadManifest(extensionPath);\n if (!manifest) {\n log.error({ extensionId: config.id, extensionPath }, `Failed to load manifest for extension`);\n this.diagnostics.error(config.id, `Failed to load manifest`);\n return null;\n }\n\n // Validate extension config against schema (basic validation)\n if (manifest.configSchema) {\n try {\n const schema = manifest.configSchema as Record<string, unknown>;\n const extensionConfig = config.config as Record<string, unknown>;\n \n // Basic validation: check required fields and types\n if (schema.type === 'object' && schema.properties) {\n const props = schema.properties as Record<string, Record<string, unknown>>;\n const required = (schema.required as string[]) || [];\n \n for (const field of required) {\n if (extensionConfig[field] === undefined) {\n log.error({ \n extensionId: config.id, \n field \n }, 'Extension config validation failed: missing required field');\n return null;\n }\n }\n \n for (const [key, value] of Object.entries(extensionConfig)) {\n const propSchema = props[key];\n if (propSchema) {\n if (propSchema.type && !this.validateType(value, propSchema.type as string)) {\n log.error({ \n extensionId: config.id, \n field: key,\n expected: propSchema.type,\n actual: typeof value\n }, 'Extension config validation failed: type mismatch');\n return null;\n }\n }\n }\n }\n \n log.debug({ extensionId: config.id }, 'Extension config validated');\n } catch (err) {\n log.warn({ err, extensionId: config.id }, 'Config schema validation skipped');\n }\n }\n\n // Create extension API\n const extensionDir = dirname(extensionPath);\n const api = this.createExtensionApi(manifest, config, extensionDir);\n\n // Load extension module\n const module = await this.loadModule(extensionPath, manifest);\n if (!module) {\n log.error({ extensionId: config.id }, `Failed to load module for extension`);\n this.diagnostics.error(config.id, `Failed to load module`);\n return null;\n }\n\n // Check and claim slots\n const slotClaimed = this.claimExtensionSlots(config.id, manifest);\n if (!slotClaimed) {\n log.warn({ extensionId: config.id }, 'Failed to claim required slots');\n }\n\n // Initialize extension\n await this.initializeExtension(module, api, manifest);\n\n // Register to registry\n this.registry.addExtension({\n id: config.id,\n name: manifest.name,\n version: manifest.version,\n path: extensionPath,\n module,\n config: config.config,\n enabled: true,\n source: config.source,\n });\n\n // Register extension tools to registry (so AgentManager can access them)\n // Note: api is actually ExtensionApiImpl at runtime\n const apiImpl = api as unknown as { _getTools: () => Map<string, AgentTool> };\n const extensionTools = apiImpl._getTools();\n for (const tool of extensionTools.values()) {\n this.registry.addTool(tool);\n }\n\n this.extensionInstances.set(config.id, api);\n \n // Cache the loaded extension\n this.cache.set(cacheKey, api);\n\n this.diagnostics.info(config.id, `Loaded extension: ${manifest.name}`);\n log.info({ name: manifest.name, id: manifest.id, source: config.source }, `Loaded extension`);\n\n return api;\n } catch (error) {\n log.error({ err: error, extensionId: config.id }, `Error loading extension`);\n this.diagnostics.error(config.id, `Error loading extension: ${error}`);\n return null;\n }\n }\n\n /**\n * Claim extension slots based on manifest kind\n * Respects configured preferred plugin from config.extensions.slots\n */\n private claimExtensionSlots(extensionId: string, manifest: ExtensionManifest): boolean {\n const kind = manifest.kind as string;\n \n // Map extension kind to slot\n const slotMap: Record<string, SlotKey> = {\n 'memory': 'memory',\n 'tts': 'tts',\n 'image-generation': 'imageGeneration',\n 'imageGeneration': 'imageGeneration',\n 'web-search': 'webSearch',\n 'webSearch': 'webSearch',\n };\n \n const slotKey = slotMap[kind];\n if (!slotKey) {\n return true; // No slot required\n }\n \n // Check if slot is reserved for a different plugin in config\n const preferredPlugin = this.slotsConfig[slotKey];\n if (preferredPlugin && preferredPlugin !== extensionId) {\n log.info(\n { extensionId, slotKey, preferredPlugin },\n `Skipping slot claim: slot \"${slotKey}\" is reserved for \"${preferredPlugin}\"`\n );\n this.diagnostics.info(\n extensionId,\n `Slot \"${slotKey}\" is reserved for \"${preferredPlugin}\", skipping claim`\n );\n return false;\n }\n \n const claimed = this.slotRegistry.claim(slotKey, extensionId, null);\n if (!claimed) {\n this.diagnostics.warn(extensionId, `Slot \"${slotKey}\" already claimed by another extension`);\n }\n return claimed;\n }\n\n loadManifest(extensionPath: string): ExtensionManifest | null {\n const manifestPath = join(extensionPath, EXTENSION_MANIFEST_FILE);\n\n // First try to load xopc.extension.json\n if (existsSync(manifestPath)) {\n try {\n const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n log.error({ manifestPath }, 'Manifest root must be a JSON object');\n return null;\n }\n return normalizeExtensionManifest(raw as Record<string, unknown>);\n } catch (error) {\n log.error({ err: error, manifestPath }, `Failed to parse manifest`);\n return null;\n }\n }\n\n // Fallback to package.json\n const packagePath = join(extensionPath, 'package.json');\n if (existsSync(packagePath)) {\n try {\n const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));\n \n // Check for xopc.extension marker\n if (packageJson.xopc?.extension) {\n const xopcConfig = packageJson.xopc;\n return normalizeExtensionManifest({\n id: xopcConfig.id || packageJson.name,\n name: xopcConfig.name || packageJson.name,\n description: xopcConfig.description || packageJson.description,\n version: xopcConfig.version || packageJson.version || '1.0.0',\n kind: xopcConfig.kind || 'utility',\n main: xopcConfig.main || packageJson.main || 'index.js',\n configSchema: xopcConfig.configSchema,\n });\n }\n\n // Also support xopc-extension-* naming convention\n if (packageJson.name?.startsWith('xopc-extension-')) {\n const id = packageJson.name.replace('xopc-extension-', '');\n return normalizeExtensionManifest({\n id,\n name: packageJson.name,\n description: packageJson.description,\n version: packageJson.version || '1.0.0',\n kind: 'utility',\n main: packageJson.main || 'index.js',\n });\n }\n } catch (error) {\n log.error({ err: error, packagePath }, `Failed to parse package.json`);\n }\n }\n\n return null;\n }\n\n private async loadModule(\n extensionPath: string,\n manifest: ExtensionManifest,\n ): Promise<ExtensionModule | null> {\n // Determine entry point - .ts files prioritized for development\n const entryPoints = [\n manifest.main,\n 'index.ts',\n 'index.js',\n 'extension.ts',\n 'extension.js',\n ].filter(Boolean) as string[];\n\n for (const entry of entryPoints) {\n const fullPath = isAbsolute(entry) ? entry : join(extensionPath, entry);\n\n if (existsSync(fullPath)) {\n try {\n // Use jiti to load both .ts and .js files\n const mod = this.jiti(fullPath);\n return mod.default || mod;\n } catch (error) {\n log.warn({ err: error, path: fullPath }, `Failed to load module`);\n }\n }\n }\n\n return null;\n }\n\n private createExtensionApi(\n manifest: ExtensionManifest,\n resolved: ResolvedExtensionConfig,\n extensionDir: string,\n ): ExtensionApi {\n const logger = createExtensionLogger(`[${manifest.id}]`);\n const resolvePath = createPathResolver(extensionDir, this.options.workspaceDir || '');\n\n const appConfig = this._appConfig ?? ({} as Config);\n const extensionOnly = (resolved.config ?? {}) as Record<string, unknown>;\n\n const runtime =\n this._appConfig && this._runtimeContext\n ? {\n config: this._appConfig,\n bus: this._runtimeContext.bus,\n log: logger,\n sessionManager: this._runtimeContext.sessionManager,\n }\n : this._appConfig\n ? {\n config: this._appConfig,\n log: logger,\n }\n : undefined;\n\n const api = new ExtensionApiImpl(\n manifest.id,\n manifest.name,\n manifest.version,\n extensionDir,\n appConfig,\n extensionOnly,\n logger,\n resolvePath,\n this.registry,\n runtime,\n );\n if (manifest.reload?.configPrefixes?.length) {\n api._setReloadConfigPrefixes(manifest.reload.configPrefixes);\n }\n return api;\n }\n\n private async initializeExtension(\n module: ExtensionModule,\n api: ExtensionApi,\n _manifest: ExtensionManifest,\n ): Promise<void> {\n if (typeof module === 'function') {\n // Module is a function that receives the API\n await module(api);\n } else if (typeof module === 'object' && module.register) {\n // Module is a ExtensionDefinition with register method\n await module.register(api);\n }\n }\n\n async startServices(): Promise<void> {\n const services = Array.from(this.registry.services.values());\n\n for (const service of services) {\n const serviceLog = createServiceLogger(service.id);\n try {\n await service.start?.();\n serviceLog.info(`Started service`);\n } catch (error) {\n serviceLog.error({ err: error }, `Failed to start service`);\n }\n }\n }\n\n async stopServices(): Promise<void> {\n const services = Array.from(this.registry.services.values()).reverse();\n\n for (const service of services) {\n if (service.stop) {\n const serviceLog = createServiceLogger(service.id);\n try {\n await service.stop();\n serviceLog.info(`Stopped service`);\n } catch (error) {\n serviceLog.error({ err: error }, `Failed to stop service`);\n }\n }\n }\n }\n\n /**\n * Basic type validation for config values\n */\n private validateType(value: unknown, expectedType: string): boolean {\n if (expectedType === 'string') return typeof value === 'string';\n if (expectedType === 'number' || expectedType === 'integer') return typeof value === 'number';\n if (expectedType === 'boolean') return typeof value === 'boolean';\n if (expectedType === 'array') return Array.isArray(value);\n if (expectedType === 'object') return typeof value === 'object' && value !== null && !Array.isArray(value);\n return true;\n }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nexport function resolveExtensionPath(id: string, _options: ExtensionLoaderOptions): string | null {\n const c = loadConfig();\n const aid = resolveDefaultAgentId(c);\n // Priority 1: Workspace\n const workspacePath = join(resolveWorkspaceExtensionsDir(c, aid), id);\n if (existsSync(workspacePath)) return workspacePath;\n\n // Priority 2: Global\n const globalPath = join(resolveExtensionsDir(), id);\n if (existsSync(globalPath)) return globalPath;\n\n // Priority 3: Bundled\n const bundledDir = resolveBundledExtensionsDir();\n if (bundledDir) {\n const bundledPath = join(bundledDir, id);\n if (existsSync(bundledPath)) return bundledPath;\n }\n\n // Check if it's an npm package\n try {\n const require = createRequire(import.meta.url);\n const resolved = require.resolve(id);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function normalizeExtensionConfig(\n rawConfig: Record<string, unknown>,\n): ResolvedExtensionConfig[] {\n const extensions: ResolvedExtensionConfig[] = [];\n\n const enabled = (rawConfig.enabled as string[]) || [];\n const disabled = (rawConfig.disabled as string[]) || [];\n\n // Parse enabled extensions\n for (const id of enabled) {\n const config = (rawConfig[id] as Record<string, unknown>) || {};\n extensions.push({\n id,\n name: id,\n source: 'config',\n path: id,\n enabled: true,\n config,\n });\n }\n\n // Parse disabled extensions\n for (const id of disabled) {\n if (!extensions.find((p) => p.id === id)) {\n const config = (rawConfig[id] as Record<string, unknown>) || {};\n extensions.push({\n id,\n name: id,\n source: 'config',\n path: id,\n enabled: false,\n config,\n });\n }\n }\n\n return extensions;\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
3
|
import { init_paths, resolveExtensionsDir, resolveExtensionsLockPath } from "../config/paths.js";
|
|
4
|
-
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
5
4
|
import { dirname, join } from "path";
|
|
6
5
|
import { existsSync } from "fs";
|
|
6
|
+
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
7
7
|
import { createHash } from "crypto";
|
|
8
8
|
//#region src/extensions/lockfile.ts
|
|
9
9
|
init_logger();
|
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
function isRecord(x) {
|
|
3
3
|
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
4
4
|
}
|
|
5
|
+
function normalizeReload(raw) {
|
|
6
|
+
if (!isRecord(raw)) return void 0;
|
|
7
|
+
const configPrefixes = Array.isArray(raw.configPrefixes) ? raw.configPrefixes.filter((x) => typeof x === "string") : void 0;
|
|
8
|
+
const supportsHotReload = typeof raw.supportsHotReload === "boolean" ? raw.supportsHotReload : void 0;
|
|
9
|
+
if (!configPrefixes?.length && supportsHotReload === void 0) return void 0;
|
|
10
|
+
return {
|
|
11
|
+
...configPrefixes?.length ? { configPrefixes } : {},
|
|
12
|
+
...supportsHotReload !== void 0 ? { supportsHotReload } : {}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function normalizeManifestCommands(raw) {
|
|
16
|
+
if (!Array.isArray(raw)) return void 0;
|
|
17
|
+
const out = [];
|
|
18
|
+
for (const item of raw) {
|
|
19
|
+
if (!isRecord(item)) continue;
|
|
20
|
+
const name = typeof item.name === "string" ? item.name.trim() : "";
|
|
21
|
+
const description = typeof item.description === "string" ? item.description : "";
|
|
22
|
+
if (!name || !description) continue;
|
|
23
|
+
const aliases = Array.isArray(item.aliases) ? item.aliases.filter((x) => typeof x === "string") : void 0;
|
|
24
|
+
const scope = Array.isArray(item.scope) ? item.scope.filter((x) => x === "global" || x === "private" || x === "group") : void 0;
|
|
25
|
+
const examples = Array.isArray(item.examples) ? item.examples.filter((x) => typeof x === "string") : void 0;
|
|
26
|
+
out.push({
|
|
27
|
+
name,
|
|
28
|
+
description,
|
|
29
|
+
...aliases?.length ? { aliases } : {},
|
|
30
|
+
...scope?.length ? { scope } : {},
|
|
31
|
+
...examples?.length ? { examples } : {}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return out.length > 0 ? out : void 0;
|
|
35
|
+
}
|
|
5
36
|
/**
|
|
6
37
|
* Normalize raw JSON manifest into ExtensionManifest with stable optional fields.
|
|
7
38
|
*/
|
|
@@ -28,6 +59,8 @@ function normalizeExtensionManifest(raw) {
|
|
|
28
59
|
activation: normalizeActivation(raw.activation),
|
|
29
60
|
contracts: normalizeContracts(raw.contracts),
|
|
30
61
|
setup: normalizeSetup(raw.setup),
|
|
62
|
+
reload: normalizeReload(raw.reload),
|
|
63
|
+
commands: normalizeManifestCommands(raw.commands),
|
|
31
64
|
ui: normalizeUiManifest(raw.ui)
|
|
32
65
|
};
|
|
33
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize-manifest.js","names":[],"sources":["../../../src/extensions/normalize-manifest.ts"],"sourcesContent":["import type {\n ActivationDeclaration,\n ChatWidgetContribution,\n ChatWidgetMatch,\n CommandContribution,\n ContractDeclaration,\n ExtensionManifest,\n ExtensionUiContributions,\n ExtensionUiManifest,\n ExtensionUiPermission,\n ModelSupportDeclaration,\n PageContribution,\n ProviderAuthChoice,\n SettingsPanelContribution,\n SetupDeclaration,\n SidebarPanelContribution,\n StatusBarItemContribution,\n} from './types/manifest.js';\nimport type { ExtensionKind } from './types/core.js';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\n/**\n * Normalize raw JSON manifest into ExtensionManifest with stable optional fields.\n */\nexport function normalizeExtensionManifest(raw: Record<string, unknown>): ExtensionManifest {\n const id = String(raw.id ?? '');\n return {\n id,\n name: typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : id,\n description: typeof raw.description === 'string' ? raw.description : undefined,\n version: typeof raw.version === 'string' ? raw.version : undefined,\n kind: raw.kind as ExtensionKind | undefined,\n main: typeof raw.main === 'string' ? raw.main : undefined,\n configSchema: isRecord(raw.configSchema) ? (raw.configSchema as Record<string, unknown>) : undefined,\n dependencies: isRecord(raw.dependencies) ? (raw.dependencies as Record<string, string>) : undefined,\n\n enabledByDefault: typeof raw.enabledByDefault === 'boolean' ? raw.enabledByDefault : undefined,\n legacyExtensionIds: Array.isArray(raw.legacyExtensionIds)\n ? raw.legacyExtensionIds.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n providers: Array.isArray(raw.providers)\n ? raw.providers.filter((x): x is string => typeof x === 'string')\n : undefined,\n providerAuthEnvVars: normalizeStringArrayMap(raw.providerAuthEnvVars),\n providerAuthChoices: normalizeProviderAuthChoices(raw.providerAuthChoices),\n modelSupport: normalizeModelSupport(raw.modelSupport),\n autoEnableWhenConfiguredProviders: Array.isArray(raw.autoEnableWhenConfiguredProviders)\n ? raw.autoEnableWhenConfiguredProviders.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n channels: Array.isArray(raw.channels)\n ? raw.channels.filter((x): x is string => typeof x === 'string')\n : undefined,\n channelEnvVars: normalizeStringArrayMap(raw.channelEnvVars),\n\n activation: normalizeActivation(raw.activation),\n contracts: normalizeContracts(raw.contracts),\n setup: normalizeSetup(raw.setup),\n ui: normalizeUiManifest(raw.ui),\n };\n}\n\nconst VALID_UI_PERMISSIONS = new Set<ExtensionUiPermission>([\n 'agent.send',\n 'agent.subscribe',\n 'session.read',\n 'session.write',\n 'config.read',\n 'config.write',\n 'storage',\n 'notification',\n 'clipboard',\n 'theme',\n 'workspace.read',\n 'workspace.write',\n]);\n\nexport function normalizeUiManifest(raw: unknown): ExtensionUiManifest | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!isRecord(raw)) return undefined;\n const main = typeof raw.main === 'string' && raw.main.length > 0 ? raw.main : undefined;\n const icon = typeof raw.icon === 'string' && raw.icon.length > 0 ? raw.icon : undefined;\n let permissions: ExtensionUiPermission[] | undefined;\n if (Array.isArray(raw.permissions)) {\n const p = raw.permissions.filter(\n (x): x is ExtensionUiPermission =>\n typeof x === 'string' && VALID_UI_PERMISSIONS.has(x as ExtensionUiPermission),\n );\n permissions = p.length ? p : undefined;\n }\n const contributions = normalizeUiContributions(raw.contributions);\n if (!main && !icon && !permissions && !contributions) return undefined;\n return {\n ...(main !== undefined ? { main } : {}),\n ...(icon !== undefined ? { icon } : {}),\n ...(permissions !== undefined ? { permissions } : {}),\n ...(contributions !== undefined ? { contributions } : {}),\n };\n}\n\nfunction normalizeUiContributions(raw: unknown): ExtensionUiContributions | undefined {\n if (!isRecord(raw)) return undefined;\n const sidebarPanels = normalizeSidebarPanels(raw.sidebarPanels);\n const settingsPanels = normalizeSettingsPanels(raw.settingsPanels);\n const chatWidgets = normalizeChatWidgets(raw.chatWidgets);\n const pages = normalizePages(raw.pages);\n const commands = normalizeCommands(raw.commands);\n const statusBarItems = normalizeStatusBarItems(raw.statusBarItems);\n const out: ExtensionUiContributions = {\n ...(sidebarPanels ? { sidebarPanels } : {}),\n ...(settingsPanels ? { settingsPanels } : {}),\n ...(chatWidgets ? { chatWidgets } : {}),\n ...(pages ? { pages } : {}),\n ...(commands ? { commands } : {}),\n ...(statusBarItems ? { statusBarItems } : {}),\n };\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeSidebarPanels(raw: unknown): SidebarPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SidebarPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n icon: typeof item.icon === 'string' ? item.icon : undefined,\n defaultVisible: typeof item.defaultVisible === 'boolean' ? item.defaultVisible : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeSettingsPanels(raw: unknown): SettingsPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SettingsPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n order: typeof item.order === 'number' ? item.order : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeChatWidgetMatch(raw: unknown): ChatWidgetMatch | undefined {\n if (!isRecord(raw)) return undefined;\n const toolName = typeof raw.toolName === 'string' ? raw.toolName : undefined;\n const contentType = typeof raw.contentType === 'string' ? raw.contentType : undefined;\n let metadata: Record<string, unknown> | undefined;\n if (isRecord(raw.metadata)) {\n metadata = { ...raw.metadata };\n }\n if (!toolName && !contentType && !metadata) return undefined;\n return { toolName, contentType, metadata };\n}\n\nfunction normalizeChatWidgets(raw: unknown): ChatWidgetContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ChatWidgetContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n const match = normalizeChatWidgetMatch(item.match);\n if (!match) continue;\n out.push({\n id,\n title,\n entrypoint,\n match,\n maxHeight: typeof item.maxHeight === 'number' ? item.maxHeight : undefined,\n interactive: typeof item.interactive === 'boolean' ? item.interactive : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizePages(raw: unknown): PageContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: PageContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const path = item.path;\n const entrypoint = item.entrypoint;\n if (\n typeof id !== 'string' ||\n typeof title !== 'string' ||\n typeof path !== 'string' ||\n typeof entrypoint !== 'string'\n ) {\n continue;\n }\n out.push({\n id,\n title,\n path,\n entrypoint,\n showInNav: typeof item.showInNav === 'boolean' ? item.showInNav : undefined,\n navIcon: typeof item.navIcon === 'string' ? item.navIcon : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeCommands(raw: unknown): CommandContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: CommandContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n if (typeof id !== 'string' || typeof title !== 'string') continue;\n out.push({\n id,\n title,\n shortcut: typeof item.shortcut === 'string' ? item.shortcut : undefined,\n opensPanel: typeof item.opensPanel === 'string' ? item.opensPanel : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStatusBarItems(raw: unknown): StatusBarItemContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: StatusBarItemContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof entrypoint !== 'string') continue;\n const position = item.position;\n out.push({\n id,\n entrypoint,\n position: position === 'left' || position === 'right' ? position : undefined,\n width: typeof item.width === 'number' ? item.width : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStringArrayMap(\n raw: unknown,\n): Record<string, string[]> | undefined {\n if (!isRecord(raw)) return undefined;\n const out: Record<string, string[]> = {};\n for (const [k, v] of Object.entries(raw)) {\n if (Array.isArray(v)) {\n const arr = v.filter((x): x is string => typeof x === 'string');\n if (arr.length) out[k] = arr;\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeProviderAuthChoices(raw: unknown): ProviderAuthChoice[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ProviderAuthChoice[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const provider = item.provider;\n const method = item.method;\n const choiceId = item.choiceId;\n const choiceLabel = item.choiceLabel;\n if (\n typeof provider !== 'string' ||\n typeof choiceId !== 'string' ||\n typeof choiceLabel !== 'string' ||\n (method !== 'api-key' && method !== 'oauth' && method !== 'cli' && method !== 'env')\n ) {\n continue;\n }\n out.push({\n provider,\n method,\n choiceId,\n choiceLabel,\n choiceHint: typeof item.choiceHint === 'string' ? item.choiceHint : undefined,\n groupId: typeof item.groupId === 'string' ? item.groupId : undefined,\n groupLabel: typeof item.groupLabel === 'string' ? item.groupLabel : undefined,\n groupHint: typeof item.groupHint === 'string' ? item.groupHint : undefined,\n cliFlag: typeof item.cliFlag === 'string' ? item.cliFlag : undefined,\n cliOption: typeof item.cliOption === 'string' ? item.cliOption : undefined,\n cliDescription: typeof item.cliDescription === 'string' ? item.cliDescription : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeModelSupport(raw: unknown): ModelSupportDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const modelPrefixes = Array.isArray(raw.modelPrefixes)\n ? raw.modelPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const modelPatterns = Array.isArray(raw.modelPatterns)\n ? raw.modelPatterns.filter((x): x is string => typeof x === 'string')\n : undefined;\n if (!modelPrefixes?.length && !modelPatterns?.length) return undefined;\n return { modelPrefixes, modelPatterns };\n}\n\nfunction normalizeActivation(raw: unknown): ActivationDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const onProviders = Array.isArray(raw.onProviders)\n ? raw.onProviders.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onCommands = Array.isArray(raw.onCommands)\n ? raw.onCommands.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onChannels = Array.isArray(raw.onChannels)\n ? raw.onChannels.filter((x): x is string => typeof x === 'string')\n : undefined;\n const capRaw = raw.onCapabilities;\n const onCapabilities = Array.isArray(capRaw)\n ? capRaw.filter(\n (x): x is 'provider' | 'channel' | 'tool' | 'hook' =>\n x === 'provider' || x === 'channel' || x === 'tool' || x === 'hook',\n )\n : undefined;\n if (!onProviders?.length && !onCommands?.length && !onChannels?.length && !onCapabilities?.length) {\n return undefined;\n }\n return { onProviders, onCommands, onChannels, onCapabilities };\n}\n\nfunction normalizeContracts(raw: unknown): ContractDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const pick = (k: string) =>\n Array.isArray(raw[k]) ? raw[k].filter((x: unknown): x is string => typeof x === 'string') : undefined;\n const c: ContractDeclaration = {\n mediaUnderstandingProviders: pick('mediaUnderstandingProviders'),\n speechProviders: pick('speechProviders'),\n imageGenerationProviders: pick('imageGenerationProviders'),\n webSearchProviders: pick('webSearchProviders'),\n memoryProviders: pick('memoryProviders'),\n };\n if (\n !c.mediaUnderstandingProviders?.length &&\n !c.speechProviders?.length &&\n !c.imageGenerationProviders?.length &&\n !c.webSearchProviders?.length &&\n !c.memoryProviders?.length\n ) {\n return undefined;\n }\n return c;\n}\n\nfunction normalizeSetup(raw: unknown): SetupDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const requiresRuntime = typeof raw.requiresRuntime === 'boolean' ? raw.requiresRuntime : undefined;\n let providers: SetupDeclaration['providers'];\n if (Array.isArray(raw.providers)) {\n providers = [];\n for (const p of raw.providers) {\n if (!isRecord(p) || typeof p.id !== 'string') continue;\n providers.push({\n id: p.id,\n authMethods: Array.isArray(p.authMethods)\n ? p.authMethods.filter((x): x is string => typeof x === 'string')\n : undefined,\n envVars: Array.isArray(p.envVars)\n ? p.envVars.filter((x): x is string => typeof x === 'string')\n : undefined,\n });\n }\n if (providers.length === 0) providers = undefined;\n }\n if (!providers && requiresRuntime === undefined) return undefined;\n return { providers, requiresRuntime };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"normalize-manifest.js","names":[],"sources":["../../../src/extensions/normalize-manifest.ts"],"sourcesContent":["import type {\n ActivationDeclaration,\n ChatWidgetContribution,\n ChatWidgetMatch,\n CommandContribution,\n ContractDeclaration,\n ExtensionManifest,\n ExtensionManifestCommand,\n ExtensionUiContributions,\n ExtensionUiManifest,\n ExtensionUiPermission,\n ModelSupportDeclaration,\n PageContribution,\n ProviderAuthChoice,\n SettingsPanelContribution,\n SetupDeclaration,\n SidebarPanelContribution,\n StatusBarItemContribution,\n} from './types/manifest.js';\nimport type { ExtensionKind } from './types/core.js';\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n return typeof x === 'object' && x !== null && !Array.isArray(x);\n}\n\nfunction normalizeReload(raw: unknown): ExtensionManifest['reload'] {\n if (!isRecord(raw)) return undefined;\n const configPrefixes = Array.isArray(raw.configPrefixes)\n ? raw.configPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const supportsHotReload =\n typeof raw.supportsHotReload === 'boolean' ? raw.supportsHotReload : undefined;\n if (!configPrefixes?.length && supportsHotReload === undefined) return undefined;\n return {\n ...(configPrefixes?.length ? { configPrefixes } : {}),\n ...(supportsHotReload !== undefined ? { supportsHotReload } : {}),\n };\n}\n\nfunction normalizeManifestCommands(raw: unknown): ExtensionManifestCommand[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ExtensionManifestCommand[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const name = typeof item.name === 'string' ? item.name.trim() : '';\n const description = typeof item.description === 'string' ? item.description : '';\n if (!name || !description) continue;\n const aliases = Array.isArray(item.aliases)\n ? item.aliases.filter((x): x is string => typeof x === 'string')\n : undefined;\n const scope = Array.isArray(item.scope)\n ? item.scope.filter(\n (x): x is 'global' | 'private' | 'group' =>\n x === 'global' || x === 'private' || x === 'group',\n )\n : undefined;\n const examples = Array.isArray(item.examples)\n ? item.examples.filter((x): x is string => typeof x === 'string')\n : undefined;\n out.push({\n name,\n description,\n ...(aliases?.length ? { aliases } : {}),\n ...(scope?.length ? { scope } : {}),\n ...(examples?.length ? { examples } : {}),\n });\n }\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * Normalize raw JSON manifest into ExtensionManifest with stable optional fields.\n */\nexport function normalizeExtensionManifest(raw: Record<string, unknown>): ExtensionManifest {\n const id = String(raw.id ?? '');\n return {\n id,\n name: typeof raw.name === 'string' && raw.name.length > 0 ? raw.name : id,\n description: typeof raw.description === 'string' ? raw.description : undefined,\n version: typeof raw.version === 'string' ? raw.version : undefined,\n kind: raw.kind as ExtensionKind | undefined,\n main: typeof raw.main === 'string' ? raw.main : undefined,\n configSchema: isRecord(raw.configSchema) ? (raw.configSchema as Record<string, unknown>) : undefined,\n dependencies: isRecord(raw.dependencies) ? (raw.dependencies as Record<string, string>) : undefined,\n\n enabledByDefault: typeof raw.enabledByDefault === 'boolean' ? raw.enabledByDefault : undefined,\n legacyExtensionIds: Array.isArray(raw.legacyExtensionIds)\n ? raw.legacyExtensionIds.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n providers: Array.isArray(raw.providers)\n ? raw.providers.filter((x): x is string => typeof x === 'string')\n : undefined,\n providerAuthEnvVars: normalizeStringArrayMap(raw.providerAuthEnvVars),\n providerAuthChoices: normalizeProviderAuthChoices(raw.providerAuthChoices),\n modelSupport: normalizeModelSupport(raw.modelSupport),\n autoEnableWhenConfiguredProviders: Array.isArray(raw.autoEnableWhenConfiguredProviders)\n ? raw.autoEnableWhenConfiguredProviders.filter((x): x is string => typeof x === 'string')\n : undefined,\n\n channels: Array.isArray(raw.channels)\n ? raw.channels.filter((x): x is string => typeof x === 'string')\n : undefined,\n channelEnvVars: normalizeStringArrayMap(raw.channelEnvVars),\n\n activation: normalizeActivation(raw.activation),\n contracts: normalizeContracts(raw.contracts),\n setup: normalizeSetup(raw.setup),\n reload: normalizeReload(raw.reload),\n commands: normalizeManifestCommands(raw.commands),\n ui: normalizeUiManifest(raw.ui),\n };\n}\n\nconst VALID_UI_PERMISSIONS = new Set<ExtensionUiPermission>([\n 'agent.send',\n 'agent.subscribe',\n 'session.read',\n 'session.write',\n 'config.read',\n 'config.write',\n 'storage',\n 'notification',\n 'clipboard',\n 'theme',\n 'workspace.read',\n 'workspace.write',\n]);\n\nexport function normalizeUiManifest(raw: unknown): ExtensionUiManifest | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!isRecord(raw)) return undefined;\n const main = typeof raw.main === 'string' && raw.main.length > 0 ? raw.main : undefined;\n const icon = typeof raw.icon === 'string' && raw.icon.length > 0 ? raw.icon : undefined;\n let permissions: ExtensionUiPermission[] | undefined;\n if (Array.isArray(raw.permissions)) {\n const p = raw.permissions.filter(\n (x): x is ExtensionUiPermission =>\n typeof x === 'string' && VALID_UI_PERMISSIONS.has(x as ExtensionUiPermission),\n );\n permissions = p.length ? p : undefined;\n }\n const contributions = normalizeUiContributions(raw.contributions);\n if (!main && !icon && !permissions && !contributions) return undefined;\n return {\n ...(main !== undefined ? { main } : {}),\n ...(icon !== undefined ? { icon } : {}),\n ...(permissions !== undefined ? { permissions } : {}),\n ...(contributions !== undefined ? { contributions } : {}),\n };\n}\n\nfunction normalizeUiContributions(raw: unknown): ExtensionUiContributions | undefined {\n if (!isRecord(raw)) return undefined;\n const sidebarPanels = normalizeSidebarPanels(raw.sidebarPanels);\n const settingsPanels = normalizeSettingsPanels(raw.settingsPanels);\n const chatWidgets = normalizeChatWidgets(raw.chatWidgets);\n const pages = normalizePages(raw.pages);\n const commands = normalizeCommands(raw.commands);\n const statusBarItems = normalizeStatusBarItems(raw.statusBarItems);\n const out: ExtensionUiContributions = {\n ...(sidebarPanels ? { sidebarPanels } : {}),\n ...(settingsPanels ? { settingsPanels } : {}),\n ...(chatWidgets ? { chatWidgets } : {}),\n ...(pages ? { pages } : {}),\n ...(commands ? { commands } : {}),\n ...(statusBarItems ? { statusBarItems } : {}),\n };\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeSidebarPanels(raw: unknown): SidebarPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SidebarPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n icon: typeof item.icon === 'string' ? item.icon : undefined,\n defaultVisible: typeof item.defaultVisible === 'boolean' ? item.defaultVisible : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeSettingsPanels(raw: unknown): SettingsPanelContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: SettingsPanelContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n out.push({\n id,\n title,\n entrypoint,\n order: typeof item.order === 'number' ? item.order : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeChatWidgetMatch(raw: unknown): ChatWidgetMatch | undefined {\n if (!isRecord(raw)) return undefined;\n const toolName = typeof raw.toolName === 'string' ? raw.toolName : undefined;\n const contentType = typeof raw.contentType === 'string' ? raw.contentType : undefined;\n let metadata: Record<string, unknown> | undefined;\n if (isRecord(raw.metadata)) {\n metadata = { ...raw.metadata };\n }\n if (!toolName && !contentType && !metadata) return undefined;\n return { toolName, contentType, metadata };\n}\n\nfunction normalizeChatWidgets(raw: unknown): ChatWidgetContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ChatWidgetContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof title !== 'string' || typeof entrypoint !== 'string') {\n continue;\n }\n const match = normalizeChatWidgetMatch(item.match);\n if (!match) continue;\n out.push({\n id,\n title,\n entrypoint,\n match,\n maxHeight: typeof item.maxHeight === 'number' ? item.maxHeight : undefined,\n interactive: typeof item.interactive === 'boolean' ? item.interactive : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizePages(raw: unknown): PageContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: PageContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n const path = item.path;\n const entrypoint = item.entrypoint;\n if (\n typeof id !== 'string' ||\n typeof title !== 'string' ||\n typeof path !== 'string' ||\n typeof entrypoint !== 'string'\n ) {\n continue;\n }\n out.push({\n id,\n title,\n path,\n entrypoint,\n showInNav: typeof item.showInNav === 'boolean' ? item.showInNav : undefined,\n navIcon: typeof item.navIcon === 'string' ? item.navIcon : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeCommands(raw: unknown): CommandContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: CommandContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const title = item.title;\n if (typeof id !== 'string' || typeof title !== 'string') continue;\n out.push({\n id,\n title,\n shortcut: typeof item.shortcut === 'string' ? item.shortcut : undefined,\n opensPanel: typeof item.opensPanel === 'string' ? item.opensPanel : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStatusBarItems(raw: unknown): StatusBarItemContribution[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: StatusBarItemContribution[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const id = item.id;\n const entrypoint = item.entrypoint;\n if (typeof id !== 'string' || typeof entrypoint !== 'string') continue;\n const position = item.position;\n out.push({\n id,\n entrypoint,\n position: position === 'left' || position === 'right' ? position : undefined,\n width: typeof item.width === 'number' ? item.width : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeStringArrayMap(\n raw: unknown,\n): Record<string, string[]> | undefined {\n if (!isRecord(raw)) return undefined;\n const out: Record<string, string[]> = {};\n for (const [k, v] of Object.entries(raw)) {\n if (Array.isArray(v)) {\n const arr = v.filter((x): x is string => typeof x === 'string');\n if (arr.length) out[k] = arr;\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nfunction normalizeProviderAuthChoices(raw: unknown): ProviderAuthChoice[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: ProviderAuthChoice[] = [];\n for (const item of raw) {\n if (!isRecord(item)) continue;\n const provider = item.provider;\n const method = item.method;\n const choiceId = item.choiceId;\n const choiceLabel = item.choiceLabel;\n if (\n typeof provider !== 'string' ||\n typeof choiceId !== 'string' ||\n typeof choiceLabel !== 'string' ||\n (method !== 'api-key' && method !== 'oauth' && method !== 'cli' && method !== 'env')\n ) {\n continue;\n }\n out.push({\n provider,\n method,\n choiceId,\n choiceLabel,\n choiceHint: typeof item.choiceHint === 'string' ? item.choiceHint : undefined,\n groupId: typeof item.groupId === 'string' ? item.groupId : undefined,\n groupLabel: typeof item.groupLabel === 'string' ? item.groupLabel : undefined,\n groupHint: typeof item.groupHint === 'string' ? item.groupHint : undefined,\n cliFlag: typeof item.cliFlag === 'string' ? item.cliFlag : undefined,\n cliOption: typeof item.cliOption === 'string' ? item.cliOption : undefined,\n cliDescription: typeof item.cliDescription === 'string' ? item.cliDescription : undefined,\n });\n }\n return out.length ? out : undefined;\n}\n\nfunction normalizeModelSupport(raw: unknown): ModelSupportDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const modelPrefixes = Array.isArray(raw.modelPrefixes)\n ? raw.modelPrefixes.filter((x): x is string => typeof x === 'string')\n : undefined;\n const modelPatterns = Array.isArray(raw.modelPatterns)\n ? raw.modelPatterns.filter((x): x is string => typeof x === 'string')\n : undefined;\n if (!modelPrefixes?.length && !modelPatterns?.length) return undefined;\n return { modelPrefixes, modelPatterns };\n}\n\nfunction normalizeActivation(raw: unknown): ActivationDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const onProviders = Array.isArray(raw.onProviders)\n ? raw.onProviders.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onCommands = Array.isArray(raw.onCommands)\n ? raw.onCommands.filter((x): x is string => typeof x === 'string')\n : undefined;\n const onChannels = Array.isArray(raw.onChannels)\n ? raw.onChannels.filter((x): x is string => typeof x === 'string')\n : undefined;\n const capRaw = raw.onCapabilities;\n const onCapabilities = Array.isArray(capRaw)\n ? capRaw.filter(\n (x): x is 'provider' | 'channel' | 'tool' | 'hook' =>\n x === 'provider' || x === 'channel' || x === 'tool' || x === 'hook',\n )\n : undefined;\n if (!onProviders?.length && !onCommands?.length && !onChannels?.length && !onCapabilities?.length) {\n return undefined;\n }\n return { onProviders, onCommands, onChannels, onCapabilities };\n}\n\nfunction normalizeContracts(raw: unknown): ContractDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const pick = (k: string) =>\n Array.isArray(raw[k]) ? raw[k].filter((x: unknown): x is string => typeof x === 'string') : undefined;\n const c: ContractDeclaration = {\n mediaUnderstandingProviders: pick('mediaUnderstandingProviders'),\n speechProviders: pick('speechProviders'),\n imageGenerationProviders: pick('imageGenerationProviders'),\n webSearchProviders: pick('webSearchProviders'),\n memoryProviders: pick('memoryProviders'),\n };\n if (\n !c.mediaUnderstandingProviders?.length &&\n !c.speechProviders?.length &&\n !c.imageGenerationProviders?.length &&\n !c.webSearchProviders?.length &&\n !c.memoryProviders?.length\n ) {\n return undefined;\n }\n return c;\n}\n\nfunction normalizeSetup(raw: unknown): SetupDeclaration | undefined {\n if (!isRecord(raw)) return undefined;\n const requiresRuntime = typeof raw.requiresRuntime === 'boolean' ? raw.requiresRuntime : undefined;\n let providers: SetupDeclaration['providers'];\n if (Array.isArray(raw.providers)) {\n providers = [];\n for (const p of raw.providers) {\n if (!isRecord(p) || typeof p.id !== 'string') continue;\n providers.push({\n id: p.id,\n authMethods: Array.isArray(p.authMethods)\n ? p.authMethods.filter((x): x is string => typeof x === 'string')\n : undefined,\n envVars: Array.isArray(p.envVars)\n ? p.envVars.filter((x): x is string => typeof x === 'string')\n : undefined,\n });\n }\n if (providers.length === 0) providers = undefined;\n }\n if (!providers && requiresRuntime === undefined) return undefined;\n return { providers, requiresRuntime };\n}\n"],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ export type { SlotKey, SlotClaim, SlotConfig, } from '../slots.js';
|
|
|
18
18
|
export type { DiagnosticLevel, ExtensionDiagnostic, ExtensionLoaderCache, } from '../diagnostics.js';
|
|
19
19
|
export type { ChannelPlugin, ChannelPluginInitOptions, ChannelPluginStartOptions, } from '../../channels/plugin-types.js';
|
|
20
20
|
export type { HttpRequestHandler, HttpRequest, HttpResponse, } from '../types/index.js';
|
|
21
|
-
export type { ExtensionCommand, } from '../types/index.js';
|
|
21
|
+
export type { ExtensionCommand, ExtensionCommandHandler, ExtensionCommandContext, ExtensionCommandResult, ExtensionReloadHandler, ExtensionReloadResult, ExtensionReloadRegistration, } from '../types/index.js';
|
|
22
22
|
export type { ExtensionService, } from '../types/index.js';
|
|
23
23
|
export type { GatewayMethodHandler, } from '../types/index.js';
|
|
24
24
|
export { TypedEventBus } from '../typed-event-bus.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/extensions/sdk/index.ts"],"sourcesContent":["/**\n * xopc Extension SDK\n * \n * Official SDK for developing xopc extensions.\n * Import types and utilities from this module:\n * \n * @example\n * import type { ExtensionApi, ExtensionDefinition } from 'xopc/extension-sdk';\n */\n\n// ============================================================================\n// Core extension types\n// ============================================================================\n\nexport type {\n ExtensionDefinition,\n ExtensionModule,\n ExtensionKind,\n ExtensionApi,\n ExtensionLogger,\n ExtensionManifest,\n ExtensionRecord,\n ExtensionRegistry,\n ResolvedExtensionConfig,\n ExtensionRuntime,\n ExtensionCliRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Tools (re-exported from @mariozechner/pi-agent-core)\n// ============================================================================\n\nexport type {\n AgentTool,\n AgentToolResult,\n AgentToolUpdateCallback,\n ToolExecutionStartEvent,\n ToolExecutionUpdateEvent,\n ToolExecutionEndEvent,\n} from '../types/index.js';\n\n// ============================================================================\n// Hooks ( Strongly Typed)\n// ============================================================================\n\nexport type {\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookOptions,\n HookAgentContext,\n AgentMessage,\n ContextEvent,\n ContextResult,\n InputEvent,\n InputResult,\n TurnEvent,\n TurnResult,\n // New hook types\n HookHandlerMap,\n HookExecutionMode,\n // Note: HOOK_EXECUTION_MODES is exported as value below\n // LLM observation hooks\n HookBeforeModelResolveEvent,\n HookBeforeModelResolveResult,\n HookBeforePromptBuildEvent,\n HookBeforePromptBuildResult,\n HookLlmInputEvent,\n HookLlmOutputEvent,\n // Inbound claim\n HookInboundClaimEvent,\n HookInboundClaimResult,\n // Reset hook\n HookBeforeResetEvent,\n HookBeforeResetResult,\n // Message write hook\n HookBeforeMessageWriteEvent,\n HookBeforeMessageWriteResult,\n // Turn hooks\n HookTurnStartEvent,\n HookTurnEndEvent,\n // Tool execution hooks\n HookToolExecutionStartEvent,\n HookToolExecutionUpdateEvent,\n HookToolExecutionEndEvent,\n // Existing context types\n HookContext,\n BeforeAgentStartContext,\n BeforeAgentStartResult,\n AgentEndContext,\n BeforeCompactionContext,\n AfterCompactionContext,\n MessageReceivedContext,\n MessageSendingContext,\n MessageSendingResult,\n MessageSentContext,\n BeforeToolCallContext,\n BeforeToolCallResult,\n AfterToolCallContext,\n SessionStartContext,\n SessionEndContext,\n GatewayStartContext,\n GatewayStopContext,\n} from '../types/index.js';\n\n// ============================================================================\n// Typed Event Bus\n// ============================================================================\n\nexport type {\n EventMap,\n RequestMap,\n EventHandler,\n EventHandlerMeta,\n RequestHandler,\n RequestHandlerMeta,\n WildcardEventHandler,\n WildcardHandlerMeta,\n TypedEventBusOptions,\n RequestOptions,\n} from '../types/index.js';\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type {\n ProviderPlugin,\n ProviderModelDefinition,\n ProviderCapabilities,\n ProviderStreamParams,\n ProviderStreamChunk,\n ProviderCompleteParams,\n ProviderResponse,\n ProviderRegistry,\n BUILTIN_PROVIDERS,\n BuiltinProviderId,\n} from '../types/index.js';\n\n// ============================================================================\n// Advanced Features\n// ============================================================================\n\nexport type {\n ProviderConfig,\n ModelConfig,\n OAuthConfig,\n OAuthCallbacks,\n OAuthCredentials,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n ShortcutHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Security Types\n// ============================================================================\n\nexport type {\n SafetyCheckResult,\n SecurityConfig,\n ExtensionSourceOrigin,\n ProvenanceInfo,\n} from '../security.js';\n\n// ============================================================================\n// Slot Types\n// ============================================================================\n\nexport type {\n SlotKey,\n SlotClaim,\n SlotConfig,\n} from '../slots.js';\n\n// ============================================================================\n// Diagnostics Types\n// ============================================================================\n\nexport type {\n DiagnosticLevel,\n ExtensionDiagnostic,\n ExtensionLoaderCache,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Channels (ChannelPlugin registry)\n// ============================================================================\n\nexport type {\n ChannelPlugin,\n ChannelPluginInitOptions,\n ChannelPluginStartOptions,\n} from '../../channels/plugin-types.js';\n\n// ============================================================================\n// HTTP\n// ============================================================================\n\nexport type {\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n} from '../types/index.js';\n\n// ============================================================================\n// Commands\n// ============================================================================\n\nexport type {\n ExtensionCommand,\n} from '../types/index.js';\n\n// ============================================================================\n// Services\n// ============================================================================\n\nexport type {\n ExtensionService,\n} from '../types/index.js';\n\n// ============================================================================\n// Gateway\n// ============================================================================\n\nexport type {\n GatewayMethodHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Export Classes\n// ============================================================================\n\nexport { TypedEventBus } from '../typed-event-bus.js';\nexport { ExtensionRegistryImpl } from '../loader.js';\nexport { ProviderPluginRegistry, getProviderRegistry } from '../../providers/plugin-registry.js';\nexport { SlotRegistry, getSlotRegistry, registerSlotType } from '../slots.js';\nexport { HOOK_EXECUTION_MODES } from '../types/hooks.js';\n\nexport { defineChannelPluginEntry } from './channel-entry.js';\nexport { registerExtensionCliProgram } from './channel-helpers.js';\n\n// ============================================================================\n// Export Hook Runner and Utilities\n// ============================================================================\n\nexport { \n ExtensionHookRunner, \n createHookContext, \n isHookEvent \n} from '../hooks.js';\n\n// ============================================================================\n// Security Utilities\n// ============================================================================\n\nexport {\n checkExtensionPathSafety,\n checkExtensionDirSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n} from '../security.js';\n\n// ============================================================================\n// Diagnostics Utilities\n// ============================================================================\n\nexport {\n getExtensionCache,\n getExtensionDiagnostics,\n ExtensionLoaderCacheImpl,\n ExtensionDiagnostics,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Config\n// ============================================================================\n\nexport type { Config } from '../../config/config-surface.js';\n\n// Subpath barrels (also available as `xopc/extension-sdk/<name>`)\nexport { lazyModule, lazyFunction } from './lazy.js';\n"],"mappings":";;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/extensions/sdk/index.ts"],"sourcesContent":["/**\n * xopc Extension SDK\n * \n * Official SDK for developing xopc extensions.\n * Import types and utilities from this module:\n * \n * @example\n * import type { ExtensionApi, ExtensionDefinition } from 'xopc/extension-sdk';\n */\n\n// ============================================================================\n// Core extension types\n// ============================================================================\n\nexport type {\n ExtensionDefinition,\n ExtensionModule,\n ExtensionKind,\n ExtensionApi,\n ExtensionLogger,\n ExtensionManifest,\n ExtensionRecord,\n ExtensionRegistry,\n ResolvedExtensionConfig,\n ExtensionRuntime,\n ExtensionCliRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Tools (re-exported from @mariozechner/pi-agent-core)\n// ============================================================================\n\nexport type {\n AgentTool,\n AgentToolResult,\n AgentToolUpdateCallback,\n ToolExecutionStartEvent,\n ToolExecutionUpdateEvent,\n ToolExecutionEndEvent,\n} from '../types/index.js';\n\n// ============================================================================\n// Hooks ( Strongly Typed)\n// ============================================================================\n\nexport type {\n ExtensionHookEvent,\n ExtensionHookHandler,\n HookOptions,\n HookAgentContext,\n AgentMessage,\n ContextEvent,\n ContextResult,\n InputEvent,\n InputResult,\n TurnEvent,\n TurnResult,\n // New hook types\n HookHandlerMap,\n HookExecutionMode,\n // Note: HOOK_EXECUTION_MODES is exported as value below\n // LLM observation hooks\n HookBeforeModelResolveEvent,\n HookBeforeModelResolveResult,\n HookBeforePromptBuildEvent,\n HookBeforePromptBuildResult,\n HookLlmInputEvent,\n HookLlmOutputEvent,\n // Inbound claim\n HookInboundClaimEvent,\n HookInboundClaimResult,\n // Reset hook\n HookBeforeResetEvent,\n HookBeforeResetResult,\n // Message write hook\n HookBeforeMessageWriteEvent,\n HookBeforeMessageWriteResult,\n // Turn hooks\n HookTurnStartEvent,\n HookTurnEndEvent,\n // Tool execution hooks\n HookToolExecutionStartEvent,\n HookToolExecutionUpdateEvent,\n HookToolExecutionEndEvent,\n // Existing context types\n HookContext,\n BeforeAgentStartContext,\n BeforeAgentStartResult,\n AgentEndContext,\n BeforeCompactionContext,\n AfterCompactionContext,\n MessageReceivedContext,\n MessageSendingContext,\n MessageSendingResult,\n MessageSentContext,\n BeforeToolCallContext,\n BeforeToolCallResult,\n AfterToolCallContext,\n SessionStartContext,\n SessionEndContext,\n GatewayStartContext,\n GatewayStopContext,\n} from '../types/index.js';\n\n// ============================================================================\n// Typed Event Bus\n// ============================================================================\n\nexport type {\n EventMap,\n RequestMap,\n EventHandler,\n EventHandlerMeta,\n RequestHandler,\n RequestHandlerMeta,\n WildcardEventHandler,\n WildcardHandlerMeta,\n TypedEventBusOptions,\n RequestOptions,\n} from '../types/index.js';\n\n// ============================================================================\n// Provider Types\n// ============================================================================\n\nexport type {\n ProviderPlugin,\n ProviderModelDefinition,\n ProviderCapabilities,\n ProviderStreamParams,\n ProviderStreamChunk,\n ProviderCompleteParams,\n ProviderResponse,\n ProviderRegistry,\n BUILTIN_PROVIDERS,\n BuiltinProviderId,\n} from '../types/index.js';\n\n// ============================================================================\n// Advanced Features\n// ============================================================================\n\nexport type {\n ProviderConfig,\n ModelConfig,\n OAuthConfig,\n OAuthCallbacks,\n OAuthCredentials,\n FlagConfig,\n FlagValue,\n ShortcutConfig,\n ShortcutHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Security Types\n// ============================================================================\n\nexport type {\n SafetyCheckResult,\n SecurityConfig,\n ExtensionSourceOrigin,\n ProvenanceInfo,\n} from '../security.js';\n\n// ============================================================================\n// Slot Types\n// ============================================================================\n\nexport type {\n SlotKey,\n SlotClaim,\n SlotConfig,\n} from '../slots.js';\n\n// ============================================================================\n// Diagnostics Types\n// ============================================================================\n\nexport type {\n DiagnosticLevel,\n ExtensionDiagnostic,\n ExtensionLoaderCache,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Channels (ChannelPlugin registry)\n// ============================================================================\n\nexport type {\n ChannelPlugin,\n ChannelPluginInitOptions,\n ChannelPluginStartOptions,\n} from '../../channels/plugin-types.js';\n\n// ============================================================================\n// HTTP\n// ============================================================================\n\nexport type {\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n} from '../types/index.js';\n\n// ============================================================================\n// Commands\n// ============================================================================\n\nexport type {\n ExtensionCommand,\n ExtensionCommandHandler,\n ExtensionCommandContext,\n ExtensionCommandResult,\n ExtensionReloadHandler,\n ExtensionReloadResult,\n ExtensionReloadRegistration,\n} from '../types/index.js';\n\n// ============================================================================\n// Services\n// ============================================================================\n\nexport type {\n ExtensionService,\n} from '../types/index.js';\n\n// ============================================================================\n// Gateway\n// ============================================================================\n\nexport type {\n GatewayMethodHandler,\n} from '../types/index.js';\n\n// ============================================================================\n// Export Classes\n// ============================================================================\n\nexport { TypedEventBus } from '../typed-event-bus.js';\nexport { ExtensionRegistryImpl } from '../loader.js';\nexport { ProviderPluginRegistry, getProviderRegistry } from '../../providers/plugin-registry.js';\nexport { SlotRegistry, getSlotRegistry, registerSlotType } from '../slots.js';\nexport { HOOK_EXECUTION_MODES } from '../types/hooks.js';\n\nexport { defineChannelPluginEntry } from './channel-entry.js';\nexport { registerExtensionCliProgram } from './channel-helpers.js';\n\n// ============================================================================\n// Export Hook Runner and Utilities\n// ============================================================================\n\nexport { \n ExtensionHookRunner, \n createHookContext, \n isHookEvent \n} from '../hooks.js';\n\n// ============================================================================\n// Security Utilities\n// ============================================================================\n\nexport {\n checkExtensionPathSafety,\n checkExtensionDirSafety,\n isExtensionAllowed,\n provenanceTracker,\n logSecurityIssue,\n DEFAULT_SECURITY_CONFIG,\n} from '../security.js';\n\n// ============================================================================\n// Diagnostics Utilities\n// ============================================================================\n\nexport {\n getExtensionCache,\n getExtensionDiagnostics,\n ExtensionLoaderCacheImpl,\n ExtensionDiagnostics,\n} from '../diagnostics.js';\n\n// ============================================================================\n// Config\n// ============================================================================\n\nexport type { Config } from '../../config/config-surface.js';\n\n// Subpath barrels (also available as `xopc/extension-sdk/<name>`)\nexport { lazyModule, lazyFunction } from './lazy.js';\n"],"mappings":";;;;;;;;;;;;sBAiPiG"}
|