@wingman-ai/gateway 0.4.0 → 0.4.2
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/README.md +29 -111
- package/dist/agent/config/agentConfig.cjs +2 -0
- package/dist/agent/config/agentConfig.d.ts +6 -0
- package/dist/agent/config/agentConfig.js +2 -0
- package/dist/agent/config/agentLoader.cjs +21 -18
- package/dist/agent/config/agentLoader.js +22 -19
- package/dist/agent/config/toolRegistry.cjs +19 -0
- package/dist/agent/config/toolRegistry.d.ts +4 -0
- package/dist/agent/config/toolRegistry.js +17 -1
- package/dist/agent/middleware/additional-messages.cjs +115 -11
- package/dist/agent/middleware/additional-messages.d.ts +9 -0
- package/dist/agent/middleware/additional-messages.js +115 -11
- package/dist/agent/tests/agentLoader.test.cjs +45 -0
- package/dist/agent/tests/agentLoader.test.js +45 -0
- package/dist/agent/tests/toolRegistry.test.cjs +2 -0
- package/dist/agent/tests/toolRegistry.test.js +2 -0
- package/dist/agent/tools/node_invoke.cjs +146 -0
- package/dist/agent/tools/node_invoke.d.ts +86 -0
- package/dist/agent/tools/node_invoke.js +109 -0
- package/dist/cli/commands/gateway.cjs +1 -1
- package/dist/cli/commands/gateway.js +1 -1
- package/dist/cli/commands/init.cjs +135 -1
- package/dist/cli/commands/init.js +136 -2
- package/dist/cli/commands/skill.cjs +7 -3
- package/dist/cli/commands/skill.js +7 -3
- package/dist/cli/config/loader.cjs +7 -3
- package/dist/cli/config/loader.js +7 -3
- package/dist/cli/config/schema.cjs +27 -9
- package/dist/cli/config/schema.d.ts +18 -4
- package/dist/cli/config/schema.js +23 -8
- package/dist/cli/core/agentInvoker.cjs +70 -14
- package/dist/cli/core/agentInvoker.d.ts +10 -0
- package/dist/cli/core/agentInvoker.js +70 -14
- package/dist/cli/services/skillRepository.cjs +155 -69
- package/dist/cli/services/skillRepository.d.ts +7 -2
- package/dist/cli/services/skillRepository.js +155 -69
- package/dist/cli/services/skillService.cjs +93 -26
- package/dist/cli/services/skillService.d.ts +7 -0
- package/dist/cli/services/skillService.js +96 -29
- package/dist/cli/types/skill.d.ts +8 -3
- package/dist/gateway/http/nodes.cjs +247 -0
- package/dist/gateway/http/nodes.d.ts +20 -0
- package/dist/gateway/http/nodes.js +210 -0
- package/dist/gateway/node.cjs +10 -1
- package/dist/gateway/node.d.ts +10 -1
- package/dist/gateway/node.js +10 -1
- package/dist/gateway/server.cjs +414 -27
- package/dist/gateway/server.d.ts +34 -0
- package/dist/gateway/server.js +408 -27
- package/dist/gateway/types.d.ts +6 -1
- package/dist/gateway/validation.cjs +2 -0
- package/dist/gateway/validation.d.ts +4 -0
- package/dist/gateway/validation.js +2 -0
- package/dist/skills/activation.cjs +92 -0
- package/dist/skills/activation.d.ts +12 -0
- package/dist/skills/activation.js +58 -0
- package/dist/skills/bin-requirements.cjs +63 -0
- package/dist/skills/bin-requirements.d.ts +3 -0
- package/dist/skills/bin-requirements.js +26 -0
- package/dist/skills/metadata.cjs +141 -0
- package/dist/skills/metadata.d.ts +29 -0
- package/dist/skills/metadata.js +104 -0
- package/dist/skills/overlay.cjs +75 -0
- package/dist/skills/overlay.d.ts +2 -0
- package/dist/skills/overlay.js +38 -0
- package/dist/tests/additionalMessageMiddleware.test.cjs +92 -0
- package/dist/tests/additionalMessageMiddleware.test.js +92 -0
- package/dist/tests/cli-config-loader.test.cjs +7 -3
- package/dist/tests/cli-config-loader.test.js +7 -3
- package/dist/tests/cli-init.test.cjs +54 -0
- package/dist/tests/cli-init.test.js +54 -0
- package/dist/tests/config-json-schema.test.cjs +12 -0
- package/dist/tests/config-json-schema.test.js +12 -0
- package/dist/tests/gateway-http-security.test.cjs +277 -0
- package/dist/tests/gateway-http-security.test.d.ts +1 -0
- package/dist/tests/gateway-http-security.test.js +271 -0
- package/dist/tests/gateway-node-mode.test.cjs +174 -0
- package/dist/tests/gateway-node-mode.test.d.ts +1 -0
- package/dist/tests/gateway-node-mode.test.js +168 -0
- package/dist/tests/gateway-origin-policy.test.cjs +60 -0
- package/dist/tests/gateway-origin-policy.test.d.ts +1 -0
- package/dist/tests/gateway-origin-policy.test.js +54 -0
- package/dist/tests/gateway.test.cjs +1 -0
- package/dist/tests/gateway.test.js +1 -0
- package/dist/tests/node-tools.test.cjs +77 -0
- package/dist/tests/node-tools.test.d.ts +1 -0
- package/dist/tests/node-tools.test.js +71 -0
- package/dist/tests/nodes-api.test.cjs +86 -0
- package/dist/tests/nodes-api.test.d.ts +1 -0
- package/dist/tests/nodes-api.test.js +80 -0
- package/dist/tests/skill-activation.test.cjs +86 -0
- package/dist/tests/skill-activation.test.d.ts +1 -0
- package/dist/tests/skill-activation.test.js +80 -0
- package/dist/tests/skill-metadata.test.cjs +119 -0
- package/dist/tests/skill-metadata.test.d.ts +1 -0
- package/dist/tests/skill-metadata.test.js +113 -0
- package/dist/tests/skill-repository.test.cjs +363 -0
- package/dist/tests/skill-repository.test.js +363 -0
- package/dist/webui/assets/{index-DHbfLOUR.js → index-BMekSELC.js} +106 -106
- package/dist/webui/index.html +1 -1
- package/package.json +4 -4
- package/skills/gog/SKILL.md +1 -1
- package/skills/weather/SKILL.md +1 -1
- package/skills/ui-registry/SKILL.md +0 -35
|
@@ -59,6 +59,8 @@ const hooks_cjs_namespaceObject = require("../../agent/middleware/hooks.cjs");
|
|
|
59
59
|
const media_compat_cjs_namespaceObject = require("../../agent/middleware/media-compat.cjs");
|
|
60
60
|
const terminal_session_manager_cjs_namespaceObject = require("../../agent/tools/terminal_session_manager.cjs");
|
|
61
61
|
const uiRegistry_cjs_namespaceObject = require("../../agent/uiRegistry.cjs");
|
|
62
|
+
const activation_cjs_namespaceObject = require("../../skills/activation.cjs");
|
|
63
|
+
const overlay_cjs_namespaceObject = require("../../skills/overlay.cjs");
|
|
62
64
|
const agentLoader_cjs_namespaceObject = require("../../agent/config/agentLoader.cjs");
|
|
63
65
|
const loader_cjs_namespaceObject = require("../config/loader.cjs");
|
|
64
66
|
function _define_property(obj, key, value) {
|
|
@@ -322,6 +324,7 @@ class AgentInvoker {
|
|
|
322
324
|
let activeToolName = null;
|
|
323
325
|
let lastToolName = null;
|
|
324
326
|
let rootLangGraphRunId;
|
|
327
|
+
const skillOverlayDirectories = [];
|
|
325
328
|
const isCancelled = ()=>options?.signal?.aborted === true;
|
|
326
329
|
try {
|
|
327
330
|
const hookSessionId = sessionId || (0, external_uuid_namespaceObject.v4)();
|
|
@@ -329,7 +332,9 @@ class AgentInvoker {
|
|
|
329
332
|
const effectiveWorkdir = this.workdir ? executionWorkspace : null;
|
|
330
333
|
const loader = new agentLoader_cjs_namespaceObject.AgentLoader(this.configDir, this.workspace, this.wingmanConfig, executionWorkspace, {
|
|
331
334
|
terminalOwnerId: `${agentName}:${hookSessionId}`,
|
|
332
|
-
terminalSessionManager: this.terminalSessionManager
|
|
335
|
+
terminalSessionManager: this.terminalSessionManager,
|
|
336
|
+
nodeInvoker: this.nodeInvoker,
|
|
337
|
+
nodeDefaultTargetClientId: this.nodeDefaultTargetClientId
|
|
333
338
|
});
|
|
334
339
|
const targetAgent = await loader.loadAgent(agentName);
|
|
335
340
|
if (!targetAgent) throw new Error(`Agent "${agentName}" not found`);
|
|
@@ -375,7 +380,10 @@ class AgentInvoker {
|
|
|
375
380
|
defaultOutputDir: this.defaultOutputDir,
|
|
376
381
|
outputVirtualPath: outputMount.virtualPath,
|
|
377
382
|
dynamicUiEnabled: this.wingmanConfig?.gateway?.dynamicUiEnabled !== false,
|
|
378
|
-
skillsDirectory
|
|
383
|
+
skillsDirectory,
|
|
384
|
+
nodeConnectedIdsProvider: this.nodeConnectedIdsProvider,
|
|
385
|
+
nodeConnectedTargetsProvider: this.nodeConnectedTargetsProvider,
|
|
386
|
+
defaultNodeTargetClientId: this.nodeDefaultTargetClientId
|
|
379
387
|
})
|
|
380
388
|
];
|
|
381
389
|
const summarizationSettings = resolveSummarizationMiddlewareSettings(this.wingmanConfig);
|
|
@@ -407,9 +415,8 @@ class AgentInvoker {
|
|
|
407
415
|
}
|
|
408
416
|
const checkpointer = this.sessionManager?.getCheckpointer();
|
|
409
417
|
const bundledSkillsPath = (0, uiRegistry_cjs_namespaceObject.getBundledSkillsPath)();
|
|
418
|
+
const workspaceSkillsPath = (0, external_node_path_namespaceObject.join)(this.workspace, normalizedSkillsDirectory);
|
|
410
419
|
const skillsSources = [];
|
|
411
|
-
if ((0, external_node_fs_namespaceObject.existsSync)(bundledSkillsPath)) skillsSources.push("/skills-bundled/");
|
|
412
|
-
skillsSources.push(skillsVirtualPath);
|
|
413
420
|
const backendOverrides = {
|
|
414
421
|
"/memories/": new external_deepagents_namespaceObject.FilesystemBackend({
|
|
415
422
|
rootDir: (0, external_node_path_namespaceObject.join)(this.workspace, this.configDir, "memories"),
|
|
@@ -425,15 +432,46 @@ class AgentInvoker {
|
|
|
425
432
|
rootDir: executionWorkspace,
|
|
426
433
|
virtualMode: true
|
|
427
434
|
});
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
435
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(workspaceSkillsPath)) {
|
|
436
|
+
const workspaceActivation = await (0, activation_cjs_namespaceObject.resolveSkillActivation)(workspaceSkillsPath);
|
|
437
|
+
if (workspaceActivation.inactiveSkills.length > 0) {
|
|
438
|
+
const summary = workspaceActivation.inactiveSkills.map((entry)=>`${entry.name} (missing: ${entry.missingBins.join(", ")})`).join("; ");
|
|
439
|
+
this.logger.info(`Inactive workspace skills: ${summary}`);
|
|
440
|
+
}
|
|
441
|
+
let workspaceOverlayRoot = workspaceSkillsPath;
|
|
442
|
+
try {
|
|
443
|
+
const workspaceOverlay = await (0, overlay_cjs_namespaceObject.createSkillOverlayDirectory)(workspaceSkillsPath, workspaceActivation.activeSkillNames);
|
|
444
|
+
workspaceOverlayRoot = workspaceOverlay;
|
|
445
|
+
skillOverlayDirectories.push(workspaceOverlay);
|
|
446
|
+
} catch (error) {
|
|
447
|
+
this.logger.debug("Failed to build workspace skill overlay; falling back to unfiltered skills directory", error);
|
|
448
|
+
}
|
|
449
|
+
backendOverrides[skillsVirtualPath] = new external_deepagents_namespaceObject.FilesystemBackend({
|
|
450
|
+
rootDir: workspaceOverlayRoot,
|
|
451
|
+
virtualMode: true
|
|
452
|
+
});
|
|
453
|
+
skillsSources.push(skillsVirtualPath);
|
|
454
|
+
}
|
|
455
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(bundledSkillsPath)) {
|
|
456
|
+
const bundledActivation = await (0, activation_cjs_namespaceObject.resolveSkillActivation)(bundledSkillsPath);
|
|
457
|
+
if (bundledActivation.inactiveSkills.length > 0) {
|
|
458
|
+
const summary = bundledActivation.inactiveSkills.map((entry)=>`${entry.name} (missing: ${entry.missingBins.join(", ")})`).join("; ");
|
|
459
|
+
this.logger.info(`Inactive bundled skills: ${summary}`);
|
|
460
|
+
}
|
|
461
|
+
let bundledOverlayRoot = bundledSkillsPath;
|
|
462
|
+
try {
|
|
463
|
+
const bundledOverlay = await (0, overlay_cjs_namespaceObject.createSkillOverlayDirectory)(bundledSkillsPath, bundledActivation.activeSkillNames);
|
|
464
|
+
bundledOverlayRoot = bundledOverlay;
|
|
465
|
+
skillOverlayDirectories.push(bundledOverlay);
|
|
466
|
+
} catch (error) {
|
|
467
|
+
this.logger.debug("Failed to build bundled skill overlay; falling back to unfiltered skills directory", error);
|
|
468
|
+
}
|
|
469
|
+
backendOverrides["/skills-bundled/"] = new external_deepagents_namespaceObject.FilesystemBackend({
|
|
470
|
+
rootDir: bundledOverlayRoot,
|
|
471
|
+
virtualMode: true
|
|
472
|
+
});
|
|
473
|
+
skillsSources.push("/skills-bundled/");
|
|
474
|
+
}
|
|
437
475
|
if (outputMount.virtualPath && outputMount.absolutePath) backendOverrides[outputMount.virtualPath] = new external_deepagents_namespaceObject.FilesystemBackend({
|
|
438
476
|
rootDir: outputMount.absolutePath,
|
|
439
477
|
virtualMode: true
|
|
@@ -571,6 +609,11 @@ class AgentInvoker {
|
|
|
571
609
|
this.outputManager.emitAgentError(errorWithToolContext);
|
|
572
610
|
throw error;
|
|
573
611
|
} finally{
|
|
612
|
+
for (const overlayDirectory of skillOverlayDirectories)try {
|
|
613
|
+
await (0, overlay_cjs_namespaceObject.removeSkillOverlayDirectory)(overlayDirectory);
|
|
614
|
+
} catch (error) {
|
|
615
|
+
this.logger.debug(`Failed to cleanup skill overlay directory ${overlayDirectory}`, error);
|
|
616
|
+
}
|
|
574
617
|
if (this.mcpManager) {
|
|
575
618
|
this.logger.debug("Cleaning up MCP client");
|
|
576
619
|
await this.mcpManager.cleanup();
|
|
@@ -602,6 +645,10 @@ class AgentInvoker {
|
|
|
602
645
|
_define_property(this, "workdir", null);
|
|
603
646
|
_define_property(this, "defaultOutputDir", null);
|
|
604
647
|
_define_property(this, "mcpProxyConfig", void 0);
|
|
648
|
+
_define_property(this, "nodeInvoker", void 0);
|
|
649
|
+
_define_property(this, "nodeDefaultTargetClientId", void 0);
|
|
650
|
+
_define_property(this, "nodeConnectedIdsProvider", void 0);
|
|
651
|
+
_define_property(this, "nodeConnectedTargetsProvider", void 0);
|
|
605
652
|
this.outputManager = options.outputManager;
|
|
606
653
|
this.logger = options.logger;
|
|
607
654
|
this.workspace = options.workspace || process.cwd();
|
|
@@ -611,9 +658,18 @@ class AgentInvoker {
|
|
|
611
658
|
this.workdir = options.workdir || null;
|
|
612
659
|
this.defaultOutputDir = options.defaultOutputDir || null;
|
|
613
660
|
this.mcpProxyConfig = options.mcpProxyConfig;
|
|
661
|
+
this.nodeInvoker = options.nodeInvoker;
|
|
662
|
+
this.nodeDefaultTargetClientId = options.nodeDefaultTargetClientId;
|
|
663
|
+
this.nodeConnectedIdsProvider = options.nodeConnectedIdsProvider;
|
|
664
|
+
this.nodeConnectedTargetsProvider = options.nodeConnectedTargetsProvider;
|
|
614
665
|
const configLoader = new loader_cjs_namespaceObject.WingmanConfigLoader(this.configDir, this.workspace);
|
|
615
666
|
this.wingmanConfig = configLoader.loadConfig();
|
|
616
|
-
this.loader = new agentLoader_cjs_namespaceObject.AgentLoader(this.configDir, this.workspace, this.wingmanConfig
|
|
667
|
+
this.loader = new agentLoader_cjs_namespaceObject.AgentLoader(this.configDir, this.workspace, this.wingmanConfig, this.workspace, {
|
|
668
|
+
terminalOwnerId: "default",
|
|
669
|
+
terminalSessionManager: this.terminalSessionManager,
|
|
670
|
+
nodeInvoker: this.nodeInvoker,
|
|
671
|
+
nodeDefaultTargetClientId: this.nodeDefaultTargetClientId
|
|
672
|
+
});
|
|
617
673
|
}
|
|
618
674
|
}
|
|
619
675
|
function buildUserContent(prompt, attachments, model) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { WingmanAgentConfig } from "@/agent/config/agentConfig.js";
|
|
2
2
|
import { type MCPProxyConfig } from "@/agent/config/mcpClientManager.js";
|
|
3
|
+
import { type ConnectedNodeTarget } from "@/agent/middleware/additional-messages.js";
|
|
3
4
|
import { type TerminalSessionManager } from "@/agent/tools/terminal_session_manager.js";
|
|
5
|
+
import type { NodeInvokeRequest, NodeInvokeResult } from "@/agent/tools/node_invoke.js";
|
|
4
6
|
import type { WingmanAgent } from "@/types/agents.js";
|
|
5
7
|
import type { Logger } from "../../logger.js";
|
|
6
8
|
import type { WingmanConfigType } from "../config/schema.js";
|
|
@@ -16,6 +18,10 @@ export interface AgentInvokerOptions {
|
|
|
16
18
|
workdir?: string | null;
|
|
17
19
|
defaultOutputDir?: string | null;
|
|
18
20
|
mcpProxyConfig?: MCPProxyConfig;
|
|
21
|
+
nodeInvoker?: (request: NodeInvokeRequest) => Promise<NodeInvokeResult>;
|
|
22
|
+
nodeDefaultTargetClientId?: string;
|
|
23
|
+
nodeConnectedIdsProvider?: () => string[] | Promise<string[]>;
|
|
24
|
+
nodeConnectedTargetsProvider?: () => ConnectedNodeTarget[] | Promise<ConnectedNodeTarget[]>;
|
|
19
25
|
}
|
|
20
26
|
export interface InvokeAgentOptions {
|
|
21
27
|
signal?: AbortSignal;
|
|
@@ -152,6 +158,10 @@ export declare class AgentInvoker {
|
|
|
152
158
|
private workdir;
|
|
153
159
|
private defaultOutputDir;
|
|
154
160
|
private mcpProxyConfig;
|
|
161
|
+
private nodeInvoker;
|
|
162
|
+
private nodeDefaultTargetClientId;
|
|
163
|
+
private nodeConnectedIdsProvider;
|
|
164
|
+
private nodeConnectedTargetsProvider;
|
|
155
165
|
constructor(options: AgentInvokerOptions);
|
|
156
166
|
findAllAgents(): WingmanAgentConfig[];
|
|
157
167
|
/**
|
|
@@ -10,6 +10,8 @@ import { createHooksMiddleware } from "../../agent/middleware/hooks.js";
|
|
|
10
10
|
import { mediaCompatibilityMiddleware } from "../../agent/middleware/media-compat.js";
|
|
11
11
|
import { getSharedTerminalSessionManager } from "../../agent/tools/terminal_session_manager.js";
|
|
12
12
|
import { getBundledSkillsPath } from "../../agent/uiRegistry.js";
|
|
13
|
+
import { resolveSkillActivation } from "../../skills/activation.js";
|
|
14
|
+
import { createSkillOverlayDirectory, removeSkillOverlayDirectory } from "../../skills/overlay.js";
|
|
13
15
|
import { AgentLoader } from "../../agent/config/agentLoader.js";
|
|
14
16
|
import { WingmanConfigLoader } from "../config/loader.js";
|
|
15
17
|
function _define_property(obj, key, value) {
|
|
@@ -273,6 +275,7 @@ class AgentInvoker {
|
|
|
273
275
|
let activeToolName = null;
|
|
274
276
|
let lastToolName = null;
|
|
275
277
|
let rootLangGraphRunId;
|
|
278
|
+
const skillOverlayDirectories = [];
|
|
276
279
|
const isCancelled = ()=>options?.signal?.aborted === true;
|
|
277
280
|
try {
|
|
278
281
|
const hookSessionId = sessionId || v4();
|
|
@@ -280,7 +283,9 @@ class AgentInvoker {
|
|
|
280
283
|
const effectiveWorkdir = this.workdir ? executionWorkspace : null;
|
|
281
284
|
const loader = new AgentLoader(this.configDir, this.workspace, this.wingmanConfig, executionWorkspace, {
|
|
282
285
|
terminalOwnerId: `${agentName}:${hookSessionId}`,
|
|
283
|
-
terminalSessionManager: this.terminalSessionManager
|
|
286
|
+
terminalSessionManager: this.terminalSessionManager,
|
|
287
|
+
nodeInvoker: this.nodeInvoker,
|
|
288
|
+
nodeDefaultTargetClientId: this.nodeDefaultTargetClientId
|
|
284
289
|
});
|
|
285
290
|
const targetAgent = await loader.loadAgent(agentName);
|
|
286
291
|
if (!targetAgent) throw new Error(`Agent "${agentName}" not found`);
|
|
@@ -326,7 +331,10 @@ class AgentInvoker {
|
|
|
326
331
|
defaultOutputDir: this.defaultOutputDir,
|
|
327
332
|
outputVirtualPath: outputMount.virtualPath,
|
|
328
333
|
dynamicUiEnabled: this.wingmanConfig?.gateway?.dynamicUiEnabled !== false,
|
|
329
|
-
skillsDirectory
|
|
334
|
+
skillsDirectory,
|
|
335
|
+
nodeConnectedIdsProvider: this.nodeConnectedIdsProvider,
|
|
336
|
+
nodeConnectedTargetsProvider: this.nodeConnectedTargetsProvider,
|
|
337
|
+
defaultNodeTargetClientId: this.nodeDefaultTargetClientId
|
|
330
338
|
})
|
|
331
339
|
];
|
|
332
340
|
const summarizationSettings = resolveSummarizationMiddlewareSettings(this.wingmanConfig);
|
|
@@ -358,9 +366,8 @@ class AgentInvoker {
|
|
|
358
366
|
}
|
|
359
367
|
const checkpointer = this.sessionManager?.getCheckpointer();
|
|
360
368
|
const bundledSkillsPath = getBundledSkillsPath();
|
|
369
|
+
const workspaceSkillsPath = join(this.workspace, normalizedSkillsDirectory);
|
|
361
370
|
const skillsSources = [];
|
|
362
|
-
if (existsSync(bundledSkillsPath)) skillsSources.push("/skills-bundled/");
|
|
363
|
-
skillsSources.push(skillsVirtualPath);
|
|
364
371
|
const backendOverrides = {
|
|
365
372
|
"/memories/": new FilesystemBackend({
|
|
366
373
|
rootDir: join(this.workspace, this.configDir, "memories"),
|
|
@@ -376,15 +383,46 @@ class AgentInvoker {
|
|
|
376
383
|
rootDir: executionWorkspace,
|
|
377
384
|
virtualMode: true
|
|
378
385
|
});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
386
|
+
if (existsSync(workspaceSkillsPath)) {
|
|
387
|
+
const workspaceActivation = await resolveSkillActivation(workspaceSkillsPath);
|
|
388
|
+
if (workspaceActivation.inactiveSkills.length > 0) {
|
|
389
|
+
const summary = workspaceActivation.inactiveSkills.map((entry)=>`${entry.name} (missing: ${entry.missingBins.join(", ")})`).join("; ");
|
|
390
|
+
this.logger.info(`Inactive workspace skills: ${summary}`);
|
|
391
|
+
}
|
|
392
|
+
let workspaceOverlayRoot = workspaceSkillsPath;
|
|
393
|
+
try {
|
|
394
|
+
const workspaceOverlay = await createSkillOverlayDirectory(workspaceSkillsPath, workspaceActivation.activeSkillNames);
|
|
395
|
+
workspaceOverlayRoot = workspaceOverlay;
|
|
396
|
+
skillOverlayDirectories.push(workspaceOverlay);
|
|
397
|
+
} catch (error) {
|
|
398
|
+
this.logger.debug("Failed to build workspace skill overlay; falling back to unfiltered skills directory", error);
|
|
399
|
+
}
|
|
400
|
+
backendOverrides[skillsVirtualPath] = new FilesystemBackend({
|
|
401
|
+
rootDir: workspaceOverlayRoot,
|
|
402
|
+
virtualMode: true
|
|
403
|
+
});
|
|
404
|
+
skillsSources.push(skillsVirtualPath);
|
|
405
|
+
}
|
|
406
|
+
if (existsSync(bundledSkillsPath)) {
|
|
407
|
+
const bundledActivation = await resolveSkillActivation(bundledSkillsPath);
|
|
408
|
+
if (bundledActivation.inactiveSkills.length > 0) {
|
|
409
|
+
const summary = bundledActivation.inactiveSkills.map((entry)=>`${entry.name} (missing: ${entry.missingBins.join(", ")})`).join("; ");
|
|
410
|
+
this.logger.info(`Inactive bundled skills: ${summary}`);
|
|
411
|
+
}
|
|
412
|
+
let bundledOverlayRoot = bundledSkillsPath;
|
|
413
|
+
try {
|
|
414
|
+
const bundledOverlay = await createSkillOverlayDirectory(bundledSkillsPath, bundledActivation.activeSkillNames);
|
|
415
|
+
bundledOverlayRoot = bundledOverlay;
|
|
416
|
+
skillOverlayDirectories.push(bundledOverlay);
|
|
417
|
+
} catch (error) {
|
|
418
|
+
this.logger.debug("Failed to build bundled skill overlay; falling back to unfiltered skills directory", error);
|
|
419
|
+
}
|
|
420
|
+
backendOverrides["/skills-bundled/"] = new FilesystemBackend({
|
|
421
|
+
rootDir: bundledOverlayRoot,
|
|
422
|
+
virtualMode: true
|
|
423
|
+
});
|
|
424
|
+
skillsSources.push("/skills-bundled/");
|
|
425
|
+
}
|
|
388
426
|
if (outputMount.virtualPath && outputMount.absolutePath) backendOverrides[outputMount.virtualPath] = new FilesystemBackend({
|
|
389
427
|
rootDir: outputMount.absolutePath,
|
|
390
428
|
virtualMode: true
|
|
@@ -522,6 +560,11 @@ class AgentInvoker {
|
|
|
522
560
|
this.outputManager.emitAgentError(errorWithToolContext);
|
|
523
561
|
throw error;
|
|
524
562
|
} finally{
|
|
563
|
+
for (const overlayDirectory of skillOverlayDirectories)try {
|
|
564
|
+
await removeSkillOverlayDirectory(overlayDirectory);
|
|
565
|
+
} catch (error) {
|
|
566
|
+
this.logger.debug(`Failed to cleanup skill overlay directory ${overlayDirectory}`, error);
|
|
567
|
+
}
|
|
525
568
|
if (this.mcpManager) {
|
|
526
569
|
this.logger.debug("Cleaning up MCP client");
|
|
527
570
|
await this.mcpManager.cleanup();
|
|
@@ -553,6 +596,10 @@ class AgentInvoker {
|
|
|
553
596
|
_define_property(this, "workdir", null);
|
|
554
597
|
_define_property(this, "defaultOutputDir", null);
|
|
555
598
|
_define_property(this, "mcpProxyConfig", void 0);
|
|
599
|
+
_define_property(this, "nodeInvoker", void 0);
|
|
600
|
+
_define_property(this, "nodeDefaultTargetClientId", void 0);
|
|
601
|
+
_define_property(this, "nodeConnectedIdsProvider", void 0);
|
|
602
|
+
_define_property(this, "nodeConnectedTargetsProvider", void 0);
|
|
556
603
|
this.outputManager = options.outputManager;
|
|
557
604
|
this.logger = options.logger;
|
|
558
605
|
this.workspace = options.workspace || process.cwd();
|
|
@@ -562,9 +609,18 @@ class AgentInvoker {
|
|
|
562
609
|
this.workdir = options.workdir || null;
|
|
563
610
|
this.defaultOutputDir = options.defaultOutputDir || null;
|
|
564
611
|
this.mcpProxyConfig = options.mcpProxyConfig;
|
|
612
|
+
this.nodeInvoker = options.nodeInvoker;
|
|
613
|
+
this.nodeDefaultTargetClientId = options.nodeDefaultTargetClientId;
|
|
614
|
+
this.nodeConnectedIdsProvider = options.nodeConnectedIdsProvider;
|
|
615
|
+
this.nodeConnectedTargetsProvider = options.nodeConnectedTargetsProvider;
|
|
565
616
|
const configLoader = new WingmanConfigLoader(this.configDir, this.workspace);
|
|
566
617
|
this.wingmanConfig = configLoader.loadConfig();
|
|
567
|
-
this.loader = new AgentLoader(this.configDir, this.workspace, this.wingmanConfig
|
|
618
|
+
this.loader = new AgentLoader(this.configDir, this.workspace, this.wingmanConfig, this.workspace, {
|
|
619
|
+
terminalOwnerId: "default",
|
|
620
|
+
terminalSessionManager: this.terminalSessionManager,
|
|
621
|
+
nodeInvoker: this.nodeInvoker,
|
|
622
|
+
nodeDefaultTargetClientId: this.nodeDefaultTargetClientId
|
|
623
|
+
});
|
|
568
624
|
}
|
|
569
625
|
}
|
|
570
626
|
function buildUserContent(prompt, attachments, model) {
|
|
@@ -27,6 +27,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27
27
|
SkillRepository: ()=>SkillRepository
|
|
28
28
|
});
|
|
29
29
|
const external_logger_cjs_namespaceObject = require("../../logger.cjs");
|
|
30
|
+
const metadata_cjs_namespaceObject = require("../../skills/metadata.cjs");
|
|
30
31
|
function _define_property(obj, key, value) {
|
|
31
32
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
32
33
|
value: value,
|
|
@@ -63,7 +64,8 @@ class SkillRepository {
|
|
|
63
64
|
async listAvailableSkills() {
|
|
64
65
|
try {
|
|
65
66
|
if ("clawhub" === this.provider) return await this.listSkillsFromClawhub();
|
|
66
|
-
return await this.listSkillsFromGitHub();
|
|
67
|
+
if ("github" === this.provider) return await this.listSkillsFromGitHub();
|
|
68
|
+
return await this.listSkillsFromHybrid();
|
|
67
69
|
} catch (error) {
|
|
68
70
|
if (error instanceof Error) throw new Error(`Failed to list skills: ${error.message}`);
|
|
69
71
|
throw error;
|
|
@@ -85,19 +87,39 @@ class SkillRepository {
|
|
|
85
87
|
return Buffer.from(arrayBuffer);
|
|
86
88
|
}
|
|
87
89
|
async getSkillMetadata(skillName) {
|
|
88
|
-
if ("clawhub" === this.provider) return await this.getClawhubSkillMetadata(skillName);
|
|
89
90
|
try {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return
|
|
91
|
+
if ("clawhub" === this.provider) return await this.getClawhubSkillMetadata(skillName);
|
|
92
|
+
if ("github" === this.provider) {
|
|
93
|
+
const repository = await this.resolveGitHubRepositoryForSkill(skillName);
|
|
94
|
+
return await this.getGitHubSkillMetadata(skillName, repository);
|
|
95
|
+
}
|
|
96
|
+
return await this.getHybridSkillMetadata(skillName);
|
|
96
97
|
} catch (error) {
|
|
97
98
|
if (error instanceof Error) throw new Error(`Failed to fetch skill metadata for ${skillName}: ${error.message}`);
|
|
98
99
|
throw error;
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
async getGitHubSkillMetadata(skillName, repository) {
|
|
103
|
+
const skillMdPath = `/repos/${repository.owner}/${repository.name}/contents/skills/${skillName}/SKILL.md`;
|
|
104
|
+
const skillMd = await this.fetchGitHub(skillMdPath);
|
|
105
|
+
if ("file" !== skillMd.type || !skillMd.content) throw new Error(`SKILL.md not found or invalid in ${repository.owner}/${repository.name}`);
|
|
106
|
+
const content = Buffer.from(skillMd.content, "base64").toString("utf-8");
|
|
107
|
+
return this.parseSkillMetadata(content);
|
|
108
|
+
}
|
|
109
|
+
async resolveGitHubRepositoryForSkill(skillName) {
|
|
110
|
+
const repositories = this.getGitHubRepositories();
|
|
111
|
+
for(let index = repositories.length - 1; index >= 0; index -= 1){
|
|
112
|
+
const repository = repositories[index];
|
|
113
|
+
try {
|
|
114
|
+
await this.fetchGitHub(`/repos/${repository.owner}/${repository.name}/contents/skills/${skillName}/SKILL.md`);
|
|
115
|
+
return repository;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (error instanceof Error && error.message.includes("Resource not found")) continue;
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
throw new Error(`Skill '${skillName}' not found in configured GitHub repositories: ${repositories.map((repository)=>`${repository.owner}/${repository.name}`).join(", ")}`);
|
|
122
|
+
}
|
|
101
123
|
async getClawhubSkillMetadata(skillName) {
|
|
102
124
|
try {
|
|
103
125
|
const detail = await this.fetchJson(`${this.clawhubBaseUrl}/api/v1/skills/${encodeURIComponent(skillName)}`, {
|
|
@@ -127,51 +149,50 @@ class SkillRepository {
|
|
|
127
149
|
throw error;
|
|
128
150
|
}
|
|
129
151
|
}
|
|
152
|
+
async getHybridSkillMetadata(skillName) {
|
|
153
|
+
let githubError;
|
|
154
|
+
try {
|
|
155
|
+
const repository = await this.resolveGitHubRepositoryForSkill(skillName);
|
|
156
|
+
return await this.getGitHubSkillMetadata(skillName, repository);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
githubError = error;
|
|
159
|
+
logger.debug(`Falling back to ClawHub metadata lookup for '${skillName}' after GitHub error: ${error instanceof Error ? error.message : String(error)}`);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
return await this.getClawhubSkillMetadata(skillName);
|
|
163
|
+
} catch (clawhubError) {
|
|
164
|
+
throw new Error(`GitHub error: ${githubError instanceof Error ? githubError.message : String(githubError)}; ClawHub error: ${clawhubError instanceof Error ? clawhubError.message : String(clawhubError)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
130
167
|
parseSkillMetadata(content) {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
168
|
+
const parsed = (0, metadata_cjs_namespaceObject.parseSkillFrontmatter)(content);
|
|
169
|
+
return {
|
|
170
|
+
name: parsed.name,
|
|
171
|
+
description: parsed.description,
|
|
172
|
+
...parsed.license ? {
|
|
173
|
+
license: parsed.license
|
|
174
|
+
} : {},
|
|
175
|
+
...parsed.compatibility ? {
|
|
176
|
+
compatibility: parsed.compatibility
|
|
177
|
+
} : {},
|
|
178
|
+
...parsed.allowedTools.length > 0 ? {
|
|
179
|
+
allowedTools: parsed.allowedTools
|
|
180
|
+
} : {},
|
|
181
|
+
...parsed.metadata ? {
|
|
182
|
+
metadata: parsed.metadata
|
|
183
|
+
} : {}
|
|
138
184
|
};
|
|
139
|
-
const lines = frontmatter.split("\n");
|
|
140
|
-
for (const line of lines){
|
|
141
|
-
const colonIndex = line.indexOf(":");
|
|
142
|
-
if (-1 === colonIndex) continue;
|
|
143
|
-
const key = line.substring(0, colonIndex).trim();
|
|
144
|
-
const value = line.substring(colonIndex + 1).trim();
|
|
145
|
-
switch(key){
|
|
146
|
-
case "name":
|
|
147
|
-
metadata.name = value;
|
|
148
|
-
break;
|
|
149
|
-
case "description":
|
|
150
|
-
metadata.description = value;
|
|
151
|
-
break;
|
|
152
|
-
case "license":
|
|
153
|
-
metadata.license = value;
|
|
154
|
-
break;
|
|
155
|
-
case "compatibility":
|
|
156
|
-
metadata.compatibility = value;
|
|
157
|
-
break;
|
|
158
|
-
case "allowed-tools":
|
|
159
|
-
metadata.allowedTools = value;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (!metadata.name) throw new Error("Invalid SKILL.md: missing required field 'name'");
|
|
164
|
-
if (!metadata.description) throw new Error("Invalid SKILL.md: missing required field 'description'");
|
|
165
|
-
const nameRegex = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
166
|
-
if (!nameRegex.test(metadata.name)) throw new Error(`Invalid skill name '${metadata.name}': must be lowercase alphanumeric with hyphens only`);
|
|
167
|
-
return metadata;
|
|
168
185
|
}
|
|
169
186
|
async downloadSkill(skillName) {
|
|
170
|
-
if ("clawhub" === this.provider) return await this.downloadSkillFromClawhub(skillName);
|
|
171
187
|
try {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
188
|
+
if ("clawhub" === this.provider) return await this.downloadSkillFromClawhub(skillName);
|
|
189
|
+
if ("github" === this.provider) {
|
|
190
|
+
const repository = await this.resolveGitHubRepositoryForSkill(skillName);
|
|
191
|
+
const files = new Map();
|
|
192
|
+
await this.downloadDirectory(`skills/${skillName}`, files, skillName, repository);
|
|
193
|
+
return files;
|
|
194
|
+
}
|
|
195
|
+
return await this.downloadHybridSkill(skillName);
|
|
175
196
|
} catch (error) {
|
|
176
197
|
if (error instanceof Error) throw new Error(`Failed to download skill ${skillName}: ${error.message}`);
|
|
177
198
|
throw error;
|
|
@@ -214,8 +235,25 @@ class SkillRepository {
|
|
|
214
235
|
throw error;
|
|
215
236
|
}
|
|
216
237
|
}
|
|
217
|
-
async
|
|
218
|
-
|
|
238
|
+
async downloadHybridSkill(skillName) {
|
|
239
|
+
let githubError;
|
|
240
|
+
try {
|
|
241
|
+
const repository = await this.resolveGitHubRepositoryForSkill(skillName);
|
|
242
|
+
const files = new Map();
|
|
243
|
+
await this.downloadDirectory(`skills/${skillName}`, files, skillName, repository);
|
|
244
|
+
return files;
|
|
245
|
+
} catch (error) {
|
|
246
|
+
githubError = error;
|
|
247
|
+
logger.debug(`Falling back to ClawHub download for '${skillName}' after GitHub error: ${error instanceof Error ? error.message : String(error)}`);
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
return await this.downloadSkillFromClawhub(skillName);
|
|
251
|
+
} catch (clawhubError) {
|
|
252
|
+
throw new Error(`GitHub error: ${githubError instanceof Error ? githubError.message : String(githubError)}; ClawHub error: ${clawhubError instanceof Error ? clawhubError.message : String(clawhubError)}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async downloadDirectory(path, files, skillName, repository) {
|
|
256
|
+
const contents = await this.fetchGitHub(`/repos/${repository.owner}/${repository.name}/contents/${path}`);
|
|
219
257
|
for (const item of contents)if ("file" === item.type) if (item.content) {
|
|
220
258
|
const content = Buffer.from(item.content, "base64");
|
|
221
259
|
const relativePath = item.path.replace(`skills/${skillName}/`, "");
|
|
@@ -228,7 +266,7 @@ class SkillRepository {
|
|
|
228
266
|
files.set(relativePath, content);
|
|
229
267
|
}
|
|
230
268
|
}
|
|
231
|
-
else if ("dir" === item.type) await this.downloadDirectory(item.path, files, skillName);
|
|
269
|
+
else if ("dir" === item.type) await this.downloadDirectory(item.path, files, skillName, repository);
|
|
232
270
|
}
|
|
233
271
|
async listSkillsFromClawhub() {
|
|
234
272
|
const allSkills = [];
|
|
@@ -257,32 +295,80 @@ class SkillRepository {
|
|
|
257
295
|
}while (cursor);
|
|
258
296
|
return allSkills;
|
|
259
297
|
}
|
|
260
|
-
async
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
description: metadata.description || "No description",
|
|
268
|
-
path: item.path,
|
|
269
|
-
metadata
|
|
270
|
-
});
|
|
298
|
+
async listSkillsFromHybrid() {
|
|
299
|
+
let clawhubSkills = [];
|
|
300
|
+
let githubSkills = [];
|
|
301
|
+
let clawhubError;
|
|
302
|
+
let githubError;
|
|
303
|
+
try {
|
|
304
|
+
clawhubSkills = await this.listSkillsFromClawhub();
|
|
271
305
|
} catch (error) {
|
|
272
|
-
|
|
306
|
+
clawhubError = error;
|
|
307
|
+
logger.warn(`Failed to list ClawHub skills in hybrid mode: ${error instanceof Error ? error.message : String(error)}`);
|
|
273
308
|
}
|
|
274
|
-
|
|
309
|
+
try {
|
|
310
|
+
githubSkills = await this.listSkillsFromGitHub();
|
|
311
|
+
} catch (error) {
|
|
312
|
+
githubError = error;
|
|
313
|
+
logger.warn(`Failed to list GitHub skills in hybrid mode: ${error instanceof Error ? error.message : String(error)}`);
|
|
314
|
+
}
|
|
315
|
+
if (0 === clawhubSkills.length && 0 === githubSkills.length) throw new Error(`No skill sources available. ClawHub error: ${clawhubError instanceof Error ? clawhubError.message : "none"}; GitHub error: ${githubError instanceof Error ? githubError.message : "none"}`);
|
|
316
|
+
const mergedSkills = new Map();
|
|
317
|
+
for (const skill of clawhubSkills)mergedSkills.set(skill.name, skill);
|
|
318
|
+
for (const skill of githubSkills){
|
|
319
|
+
if (mergedSkills.has(skill.name)) mergedSkills.delete(skill.name);
|
|
320
|
+
mergedSkills.set(skill.name, skill);
|
|
321
|
+
}
|
|
322
|
+
return [
|
|
323
|
+
...mergedSkills.values()
|
|
324
|
+
];
|
|
325
|
+
}
|
|
326
|
+
async listSkillsFromGitHub() {
|
|
327
|
+
const mergedSkills = new Map();
|
|
328
|
+
for (const repository of this.getGitHubRepositories()){
|
|
329
|
+
const contents = await this.fetchGitHub(`/repos/${repository.owner}/${repository.name}/contents/skills`);
|
|
330
|
+
for (const item of contents)if ("dir" === item.type) try {
|
|
331
|
+
const metadata = await this.getGitHubSkillMetadata(item.name, repository);
|
|
332
|
+
if (mergedSkills.has(item.name)) mergedSkills.delete(item.name);
|
|
333
|
+
mergedSkills.set(item.name, {
|
|
334
|
+
name: item.name,
|
|
335
|
+
description: metadata.description || "No description",
|
|
336
|
+
path: item.path,
|
|
337
|
+
metadata
|
|
338
|
+
});
|
|
339
|
+
} catch (error) {
|
|
340
|
+
logger.warn(`Could not read skill ${item.name} from ${repository.owner}/${repository.name}`, error instanceof Error ? error.message : String(error));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return [
|
|
344
|
+
...mergedSkills.values()
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
getGitHubRepositories() {
|
|
348
|
+
if (this.repositories.length > 0) return this.repositories;
|
|
349
|
+
throw new Error("No GitHub skill repositories configured. Set skills.repositories or the legacy skills.repositoryOwner + skills.repositoryName fields.");
|
|
275
350
|
}
|
|
276
351
|
constructor(options = {}){
|
|
277
352
|
_define_property(this, "githubBaseUrl", "https://api.github.com");
|
|
278
|
-
_define_property(this, "
|
|
279
|
-
_define_property(this, "repo", void 0);
|
|
353
|
+
_define_property(this, "repositories", void 0);
|
|
280
354
|
_define_property(this, "token", void 0);
|
|
281
355
|
_define_property(this, "provider", void 0);
|
|
282
356
|
_define_property(this, "clawhubBaseUrl", void 0);
|
|
283
|
-
this.provider = options.provider || "
|
|
284
|
-
|
|
285
|
-
|
|
357
|
+
this.provider = options.provider || "hybrid";
|
|
358
|
+
const normalizedRepositories = (options.repositories || []).map((repository)=>({
|
|
359
|
+
owner: repository.owner.trim(),
|
|
360
|
+
name: repository.name.trim()
|
|
361
|
+
})).filter((repository)=>repository.owner && repository.name);
|
|
362
|
+
const legacyOwner = options.repositoryOwner?.trim();
|
|
363
|
+
const legacyName = options.repositoryName?.trim();
|
|
364
|
+
if (normalizedRepositories.length > 0) this.repositories = normalizedRepositories;
|
|
365
|
+
else if (legacyOwner && legacyName) this.repositories = [
|
|
366
|
+
{
|
|
367
|
+
owner: legacyOwner,
|
|
368
|
+
name: legacyName
|
|
369
|
+
}
|
|
370
|
+
];
|
|
371
|
+
else this.repositories = [];
|
|
286
372
|
this.token = options.githubToken || process.env.GITHUB_TOKEN || void 0;
|
|
287
373
|
this.clawhubBaseUrl = (options.clawhubBaseUrl || "https://clawhub.ai").replace(/\/+$/, "");
|
|
288
374
|
}
|
|
@@ -4,8 +4,7 @@ import type { SkillInfo, SkillMetadata, SkillRepositoryOptions } from "../types/
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class SkillRepository {
|
|
6
6
|
private readonly githubBaseUrl;
|
|
7
|
-
private readonly
|
|
8
|
-
private readonly repo;
|
|
7
|
+
private readonly repositories;
|
|
9
8
|
private readonly token?;
|
|
10
9
|
private readonly provider;
|
|
11
10
|
private readonly clawhubBaseUrl;
|
|
@@ -24,7 +23,10 @@ export declare class SkillRepository {
|
|
|
24
23
|
* Get skill metadata by fetching and parsing SKILL.md
|
|
25
24
|
*/
|
|
26
25
|
getSkillMetadata(skillName: string): Promise<SkillMetadata>;
|
|
26
|
+
private getGitHubSkillMetadata;
|
|
27
|
+
private resolveGitHubRepositoryForSkill;
|
|
27
28
|
private getClawhubSkillMetadata;
|
|
29
|
+
private getHybridSkillMetadata;
|
|
28
30
|
/**
|
|
29
31
|
* Parse SKILL.md content to extract YAML frontmatter
|
|
30
32
|
*/
|
|
@@ -34,10 +36,13 @@ export declare class SkillRepository {
|
|
|
34
36
|
*/
|
|
35
37
|
downloadSkill(skillName: string): Promise<Map<string, string | Buffer>>;
|
|
36
38
|
private downloadSkillFromClawhub;
|
|
39
|
+
private downloadHybridSkill;
|
|
37
40
|
/**
|
|
38
41
|
* Recursively download all files in a directory
|
|
39
42
|
*/
|
|
40
43
|
private downloadDirectory;
|
|
41
44
|
private listSkillsFromClawhub;
|
|
45
|
+
private listSkillsFromHybrid;
|
|
42
46
|
private listSkillsFromGitHub;
|
|
47
|
+
private getGitHubRepositories;
|
|
43
48
|
}
|