@wingman-ai/gateway 0.4.1 → 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/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 +49 -11
- package/dist/cli/core/agentInvoker.js +49 -11
- 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/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/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/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/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
|
@@ -62,6 +62,11 @@ const DEFAULT_TOOLS = [
|
|
|
62
62
|
"think"
|
|
63
63
|
];
|
|
64
64
|
const DEFAULT_FS_ROOT = ".";
|
|
65
|
+
const DEFAULT_BROWSER_PROFILE_ID = "default";
|
|
66
|
+
const DEFAULT_BROWSER_PROFILES_DIR = ".wingman/browser-profiles";
|
|
67
|
+
const DEFAULT_BROWSER_EXTENSIONS_DIR = ".wingman/browser-extensions";
|
|
68
|
+
const DEFAULT_BUNDLED_EXTENSION_ID = "wingman";
|
|
69
|
+
const DEFAULT_BROWSER_TRANSPORT = "auto";
|
|
65
70
|
const DEFAULT_MODELS = {
|
|
66
71
|
anthropic: "anthropic:claude-sonnet-4-5",
|
|
67
72
|
openai: "openai:gpt-4o",
|
|
@@ -318,7 +323,10 @@ async function handleConfigSetup(input) {
|
|
|
318
323
|
recursive: true
|
|
319
324
|
});
|
|
320
325
|
(0, external_node_fs_namespaceObject.writeFileSync)(configPath, JSON.stringify(nextConfig, null, 2));
|
|
326
|
+
const browserBootstrap = bootstrapBrowserDefaults(configRoot, nextConfig);
|
|
321
327
|
writeLine(outputManager, `Saved config to ${configPath}`);
|
|
328
|
+
if (browserBootstrap.profileDirectory) writeLine(outputManager, `Prepared default browser profile at ${browserBootstrap.profileDirectory}`);
|
|
329
|
+
if (browserBootstrap.extensionDirectory) writeLine(outputManager, `Installed bundled browser extension at ${browserBootstrap.extensionDirectory}`);
|
|
322
330
|
}
|
|
323
331
|
function mergeConfigFile(configPath, agentId, fsRoot) {
|
|
324
332
|
const raw = (0, external_node_fs_namespaceObject.readFileSync)(configPath, "utf-8");
|
|
@@ -357,6 +365,8 @@ function mergeConfigValues(config, agentId, fsRoot) {
|
|
|
357
365
|
...gateway,
|
|
358
366
|
fsRoots
|
|
359
367
|
};
|
|
368
|
+
const browserMerge = applyRecommendedBrowserConfig(nextConfig);
|
|
369
|
+
if (browserMerge.changed) changed = true;
|
|
360
370
|
return {
|
|
361
371
|
config: nextConfig,
|
|
362
372
|
changed
|
|
@@ -371,7 +381,131 @@ function buildDefaultConfig(agentId, fsRoot) {
|
|
|
371
381
|
fsRoot
|
|
372
382
|
]
|
|
373
383
|
};
|
|
374
|
-
|
|
384
|
+
const nextConfig = config;
|
|
385
|
+
applyRecommendedBrowserConfig(nextConfig);
|
|
386
|
+
return nextConfig;
|
|
387
|
+
}
|
|
388
|
+
function isObjectRecord(value) {
|
|
389
|
+
return Boolean(value) && "object" == typeof value && !Array.isArray(value);
|
|
390
|
+
}
|
|
391
|
+
function readStringRecord(value) {
|
|
392
|
+
if (!isObjectRecord(value)) return {};
|
|
393
|
+
const record = {};
|
|
394
|
+
for (const [key, entry] of Object.entries(value))if ("string" == typeof entry && entry.trim()) record[key] = entry.trim();
|
|
395
|
+
return record;
|
|
396
|
+
}
|
|
397
|
+
function readStringArray(value) {
|
|
398
|
+
if (!Array.isArray(value)) return [];
|
|
399
|
+
return value.filter((entry)=>"string" == typeof entry).map((entry)=>entry.trim()).filter((entry)=>entry.length > 0);
|
|
400
|
+
}
|
|
401
|
+
function normalizePathForConfig(pathValue) {
|
|
402
|
+
return pathValue.replaceAll("\\", "/");
|
|
403
|
+
}
|
|
404
|
+
function applyRecommendedBrowserConfig(config) {
|
|
405
|
+
let changed = false;
|
|
406
|
+
const browserRaw = config.browser;
|
|
407
|
+
const browser = isObjectRecord(browserRaw) ? {
|
|
408
|
+
...browserRaw
|
|
409
|
+
} : {};
|
|
410
|
+
if (!isObjectRecord(browserRaw)) changed = true;
|
|
411
|
+
const profilesDir = "string" == typeof browser.profilesDir && browser.profilesDir.trim() ? browser.profilesDir.trim() : DEFAULT_BROWSER_PROFILES_DIR;
|
|
412
|
+
if (browser.profilesDir !== profilesDir) {
|
|
413
|
+
browser.profilesDir = profilesDir;
|
|
414
|
+
changed = true;
|
|
415
|
+
}
|
|
416
|
+
const defaultProfile = "string" == typeof browser.defaultProfile && browser.defaultProfile.trim() ? browser.defaultProfile.trim() : DEFAULT_BROWSER_PROFILE_ID;
|
|
417
|
+
if (browser.defaultProfile !== defaultProfile) {
|
|
418
|
+
browser.defaultProfile = defaultProfile;
|
|
419
|
+
changed = true;
|
|
420
|
+
}
|
|
421
|
+
const profiles = readStringRecord(browser.profiles);
|
|
422
|
+
const defaultProfilePath = normalizePathForConfig((0, external_node_path_namespaceObject.join)(profilesDir, defaultProfile));
|
|
423
|
+
if (!profiles[defaultProfile]) {
|
|
424
|
+
profiles[defaultProfile] = defaultProfilePath;
|
|
425
|
+
changed = true;
|
|
426
|
+
}
|
|
427
|
+
if (!isObjectRecord(browser.profiles) || Object.keys(profiles).length !== Object.keys(browser.profiles).length) changed = true;
|
|
428
|
+
browser.profiles = profiles;
|
|
429
|
+
const extensionsDir = "string" == typeof browser.extensionsDir && browser.extensionsDir.trim() ? browser.extensionsDir.trim() : DEFAULT_BROWSER_EXTENSIONS_DIR;
|
|
430
|
+
if (browser.extensionsDir !== extensionsDir) {
|
|
431
|
+
browser.extensionsDir = extensionsDir;
|
|
432
|
+
changed = true;
|
|
433
|
+
}
|
|
434
|
+
const extensions = readStringRecord(browser.extensions);
|
|
435
|
+
const defaultExtensionPath = normalizePathForConfig((0, external_node_path_namespaceObject.join)(extensionsDir, DEFAULT_BUNDLED_EXTENSION_ID));
|
|
436
|
+
if (!extensions[DEFAULT_BUNDLED_EXTENSION_ID]) {
|
|
437
|
+
extensions[DEFAULT_BUNDLED_EXTENSION_ID] = defaultExtensionPath;
|
|
438
|
+
changed = true;
|
|
439
|
+
}
|
|
440
|
+
if (!isObjectRecord(browser.extensions) || Object.keys(extensions).length !== Object.keys(browser.extensions).length) changed = true;
|
|
441
|
+
browser.extensions = extensions;
|
|
442
|
+
const defaultExtensions = new Set(readStringArray(browser.defaultExtensions));
|
|
443
|
+
if (!defaultExtensions.has(DEFAULT_BUNDLED_EXTENSION_ID)) {
|
|
444
|
+
defaultExtensions.add(DEFAULT_BUNDLED_EXTENSION_ID);
|
|
445
|
+
changed = true;
|
|
446
|
+
}
|
|
447
|
+
const nextDefaultExtensions = Array.from(defaultExtensions);
|
|
448
|
+
if (!Array.isArray(browser.defaultExtensions) || nextDefaultExtensions.length !== browser.defaultExtensions.length) changed = true;
|
|
449
|
+
browser.defaultExtensions = nextDefaultExtensions;
|
|
450
|
+
const transport = browser.transport;
|
|
451
|
+
if ("auto" !== transport && "playwright" !== transport && "relay" !== transport) {
|
|
452
|
+
browser.transport = DEFAULT_BROWSER_TRANSPORT;
|
|
453
|
+
changed = true;
|
|
454
|
+
}
|
|
455
|
+
config.browser = browser;
|
|
456
|
+
return {
|
|
457
|
+
config,
|
|
458
|
+
changed
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
function resolveBundledBrowserExtensionPath() {
|
|
462
|
+
const candidates = [
|
|
463
|
+
new URL("../../../../extensions/wingman-browser-extension", __rslib_import_meta_url__),
|
|
464
|
+
new URL("../../../extensions/wingman-browser-extension", __rslib_import_meta_url__)
|
|
465
|
+
];
|
|
466
|
+
for (const candidate of candidates){
|
|
467
|
+
const resolved = (0, external_node_url_namespaceObject.fileURLToPath)(candidate);
|
|
468
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(resolved) && (0, external_node_fs_namespaceObject.statSync)(resolved).isDirectory()) return resolved;
|
|
469
|
+
}
|
|
470
|
+
const cwdFallback = (0, external_node_path_namespaceObject.join)(process.cwd(), "extensions", "wingman-browser-extension");
|
|
471
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(cwdFallback) && (0, external_node_fs_namespaceObject.statSync)(cwdFallback).isDirectory()) return cwdFallback;
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
function resolveWorkspacePath(workspace, configuredPath) {
|
|
475
|
+
return (0, external_node_path_namespaceObject.isAbsolute)(configuredPath) ? configuredPath : (0, external_node_path_namespaceObject.join)(workspace, configuredPath);
|
|
476
|
+
}
|
|
477
|
+
function bootstrapBrowserDefaults(configRoot, config) {
|
|
478
|
+
if (!isObjectRecord(config.browser)) return {};
|
|
479
|
+
const browser = config.browser;
|
|
480
|
+
const workspace = (0, external_node_path_namespaceObject.dirname)(configRoot);
|
|
481
|
+
let profileDirectory;
|
|
482
|
+
let extensionDirectory;
|
|
483
|
+
const defaultProfile = "string" == typeof browser.defaultProfile ? browser.defaultProfile.trim() : "";
|
|
484
|
+
if (defaultProfile) {
|
|
485
|
+
const profiles = readStringRecord(browser.profiles);
|
|
486
|
+
const profilesDir = "string" == typeof browser.profilesDir && browser.profilesDir.trim() ? browser.profilesDir.trim() : DEFAULT_BROWSER_PROFILES_DIR;
|
|
487
|
+
const profilePath = profiles[defaultProfile] || normalizePathForConfig((0, external_node_path_namespaceObject.join)(profilesDir, defaultProfile));
|
|
488
|
+
const absoluteProfilePath = resolveWorkspacePath(workspace, profilePath);
|
|
489
|
+
if (!(0, external_node_fs_namespaceObject.existsSync)(absoluteProfilePath)) profileDirectory = absoluteProfilePath;
|
|
490
|
+
(0, external_node_fs_namespaceObject.mkdirSync)(absoluteProfilePath, {
|
|
491
|
+
recursive: true
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
const extensions = readStringRecord(browser.extensions);
|
|
495
|
+
const bundledExtensionPath = extensions[DEFAULT_BUNDLED_EXTENSION_ID];
|
|
496
|
+
if (bundledExtensionPath) {
|
|
497
|
+
const absoluteExtensionPath = resolveWorkspacePath(workspace, bundledExtensionPath);
|
|
498
|
+
const bundledExtensionSource = resolveBundledBrowserExtensionPath();
|
|
499
|
+
const manifestPath = (0, external_node_path_namespaceObject.join)(absoluteExtensionPath, "manifest.json");
|
|
500
|
+
if (bundledExtensionSource && !(0, external_node_fs_namespaceObject.existsSync)(manifestPath)) {
|
|
501
|
+
copyDirectory(bundledExtensionSource, absoluteExtensionPath);
|
|
502
|
+
extensionDirectory = absoluteExtensionPath;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
profileDirectory,
|
|
507
|
+
extensionDirectory
|
|
508
|
+
};
|
|
375
509
|
}
|
|
376
510
|
async function handleAgentSetup(input) {
|
|
377
511
|
const { configRoot, agentId, model, force, nonInteractive, outputManager, bundledAgentsPath, copyAgents, ensureDefaultAgent = true } = input;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { dirname, isAbsolute, join } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { cancel, confirm as prompts_confirm, intro, isCancel, multiselect, note, outro, select as prompts_select, spinner, text as prompts_text } from "@clack/prompts";
|
|
5
5
|
import chalk from "chalk";
|
|
@@ -21,6 +21,11 @@ const DEFAULT_TOOLS = [
|
|
|
21
21
|
"think"
|
|
22
22
|
];
|
|
23
23
|
const DEFAULT_FS_ROOT = ".";
|
|
24
|
+
const DEFAULT_BROWSER_PROFILE_ID = "default";
|
|
25
|
+
const DEFAULT_BROWSER_PROFILES_DIR = ".wingman/browser-profiles";
|
|
26
|
+
const DEFAULT_BROWSER_EXTENSIONS_DIR = ".wingman/browser-extensions";
|
|
27
|
+
const DEFAULT_BUNDLED_EXTENSION_ID = "wingman";
|
|
28
|
+
const DEFAULT_BROWSER_TRANSPORT = "auto";
|
|
24
29
|
const DEFAULT_MODELS = {
|
|
25
30
|
anthropic: "anthropic:claude-sonnet-4-5",
|
|
26
31
|
openai: "openai:gpt-4o",
|
|
@@ -277,7 +282,10 @@ async function handleConfigSetup(input) {
|
|
|
277
282
|
recursive: true
|
|
278
283
|
});
|
|
279
284
|
writeFileSync(configPath, JSON.stringify(nextConfig, null, 2));
|
|
285
|
+
const browserBootstrap = bootstrapBrowserDefaults(configRoot, nextConfig);
|
|
280
286
|
writeLine(outputManager, `Saved config to ${configPath}`);
|
|
287
|
+
if (browserBootstrap.profileDirectory) writeLine(outputManager, `Prepared default browser profile at ${browserBootstrap.profileDirectory}`);
|
|
288
|
+
if (browserBootstrap.extensionDirectory) writeLine(outputManager, `Installed bundled browser extension at ${browserBootstrap.extensionDirectory}`);
|
|
281
289
|
}
|
|
282
290
|
function mergeConfigFile(configPath, agentId, fsRoot) {
|
|
283
291
|
const raw = readFileSync(configPath, "utf-8");
|
|
@@ -316,6 +324,8 @@ function mergeConfigValues(config, agentId, fsRoot) {
|
|
|
316
324
|
...gateway,
|
|
317
325
|
fsRoots
|
|
318
326
|
};
|
|
327
|
+
const browserMerge = applyRecommendedBrowserConfig(nextConfig);
|
|
328
|
+
if (browserMerge.changed) changed = true;
|
|
319
329
|
return {
|
|
320
330
|
config: nextConfig,
|
|
321
331
|
changed
|
|
@@ -330,7 +340,131 @@ function buildDefaultConfig(agentId, fsRoot) {
|
|
|
330
340
|
fsRoot
|
|
331
341
|
]
|
|
332
342
|
};
|
|
333
|
-
|
|
343
|
+
const nextConfig = config;
|
|
344
|
+
applyRecommendedBrowserConfig(nextConfig);
|
|
345
|
+
return nextConfig;
|
|
346
|
+
}
|
|
347
|
+
function isObjectRecord(value) {
|
|
348
|
+
return Boolean(value) && "object" == typeof value && !Array.isArray(value);
|
|
349
|
+
}
|
|
350
|
+
function readStringRecord(value) {
|
|
351
|
+
if (!isObjectRecord(value)) return {};
|
|
352
|
+
const record = {};
|
|
353
|
+
for (const [key, entry] of Object.entries(value))if ("string" == typeof entry && entry.trim()) record[key] = entry.trim();
|
|
354
|
+
return record;
|
|
355
|
+
}
|
|
356
|
+
function readStringArray(value) {
|
|
357
|
+
if (!Array.isArray(value)) return [];
|
|
358
|
+
return value.filter((entry)=>"string" == typeof entry).map((entry)=>entry.trim()).filter((entry)=>entry.length > 0);
|
|
359
|
+
}
|
|
360
|
+
function normalizePathForConfig(pathValue) {
|
|
361
|
+
return pathValue.replaceAll("\\", "/");
|
|
362
|
+
}
|
|
363
|
+
function applyRecommendedBrowserConfig(config) {
|
|
364
|
+
let changed = false;
|
|
365
|
+
const browserRaw = config.browser;
|
|
366
|
+
const browser = isObjectRecord(browserRaw) ? {
|
|
367
|
+
...browserRaw
|
|
368
|
+
} : {};
|
|
369
|
+
if (!isObjectRecord(browserRaw)) changed = true;
|
|
370
|
+
const profilesDir = "string" == typeof browser.profilesDir && browser.profilesDir.trim() ? browser.profilesDir.trim() : DEFAULT_BROWSER_PROFILES_DIR;
|
|
371
|
+
if (browser.profilesDir !== profilesDir) {
|
|
372
|
+
browser.profilesDir = profilesDir;
|
|
373
|
+
changed = true;
|
|
374
|
+
}
|
|
375
|
+
const defaultProfile = "string" == typeof browser.defaultProfile && browser.defaultProfile.trim() ? browser.defaultProfile.trim() : DEFAULT_BROWSER_PROFILE_ID;
|
|
376
|
+
if (browser.defaultProfile !== defaultProfile) {
|
|
377
|
+
browser.defaultProfile = defaultProfile;
|
|
378
|
+
changed = true;
|
|
379
|
+
}
|
|
380
|
+
const profiles = readStringRecord(browser.profiles);
|
|
381
|
+
const defaultProfilePath = normalizePathForConfig(join(profilesDir, defaultProfile));
|
|
382
|
+
if (!profiles[defaultProfile]) {
|
|
383
|
+
profiles[defaultProfile] = defaultProfilePath;
|
|
384
|
+
changed = true;
|
|
385
|
+
}
|
|
386
|
+
if (!isObjectRecord(browser.profiles) || Object.keys(profiles).length !== Object.keys(browser.profiles).length) changed = true;
|
|
387
|
+
browser.profiles = profiles;
|
|
388
|
+
const extensionsDir = "string" == typeof browser.extensionsDir && browser.extensionsDir.trim() ? browser.extensionsDir.trim() : DEFAULT_BROWSER_EXTENSIONS_DIR;
|
|
389
|
+
if (browser.extensionsDir !== extensionsDir) {
|
|
390
|
+
browser.extensionsDir = extensionsDir;
|
|
391
|
+
changed = true;
|
|
392
|
+
}
|
|
393
|
+
const extensions = readStringRecord(browser.extensions);
|
|
394
|
+
const defaultExtensionPath = normalizePathForConfig(join(extensionsDir, DEFAULT_BUNDLED_EXTENSION_ID));
|
|
395
|
+
if (!extensions[DEFAULT_BUNDLED_EXTENSION_ID]) {
|
|
396
|
+
extensions[DEFAULT_BUNDLED_EXTENSION_ID] = defaultExtensionPath;
|
|
397
|
+
changed = true;
|
|
398
|
+
}
|
|
399
|
+
if (!isObjectRecord(browser.extensions) || Object.keys(extensions).length !== Object.keys(browser.extensions).length) changed = true;
|
|
400
|
+
browser.extensions = extensions;
|
|
401
|
+
const defaultExtensions = new Set(readStringArray(browser.defaultExtensions));
|
|
402
|
+
if (!defaultExtensions.has(DEFAULT_BUNDLED_EXTENSION_ID)) {
|
|
403
|
+
defaultExtensions.add(DEFAULT_BUNDLED_EXTENSION_ID);
|
|
404
|
+
changed = true;
|
|
405
|
+
}
|
|
406
|
+
const nextDefaultExtensions = Array.from(defaultExtensions);
|
|
407
|
+
if (!Array.isArray(browser.defaultExtensions) || nextDefaultExtensions.length !== browser.defaultExtensions.length) changed = true;
|
|
408
|
+
browser.defaultExtensions = nextDefaultExtensions;
|
|
409
|
+
const transport = browser.transport;
|
|
410
|
+
if ("auto" !== transport && "playwright" !== transport && "relay" !== transport) {
|
|
411
|
+
browser.transport = DEFAULT_BROWSER_TRANSPORT;
|
|
412
|
+
changed = true;
|
|
413
|
+
}
|
|
414
|
+
config.browser = browser;
|
|
415
|
+
return {
|
|
416
|
+
config,
|
|
417
|
+
changed
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function resolveBundledBrowserExtensionPath() {
|
|
421
|
+
const candidates = [
|
|
422
|
+
new URL("../../../../extensions/wingman-browser-extension", import.meta.url),
|
|
423
|
+
new URL("../../../extensions/wingman-browser-extension", import.meta.url)
|
|
424
|
+
];
|
|
425
|
+
for (const candidate of candidates){
|
|
426
|
+
const resolved = fileURLToPath(candidate);
|
|
427
|
+
if (existsSync(resolved) && statSync(resolved).isDirectory()) return resolved;
|
|
428
|
+
}
|
|
429
|
+
const cwdFallback = join(process.cwd(), "extensions", "wingman-browser-extension");
|
|
430
|
+
if (existsSync(cwdFallback) && statSync(cwdFallback).isDirectory()) return cwdFallback;
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
function resolveWorkspacePath(workspace, configuredPath) {
|
|
434
|
+
return isAbsolute(configuredPath) ? configuredPath : join(workspace, configuredPath);
|
|
435
|
+
}
|
|
436
|
+
function bootstrapBrowserDefaults(configRoot, config) {
|
|
437
|
+
if (!isObjectRecord(config.browser)) return {};
|
|
438
|
+
const browser = config.browser;
|
|
439
|
+
const workspace = dirname(configRoot);
|
|
440
|
+
let profileDirectory;
|
|
441
|
+
let extensionDirectory;
|
|
442
|
+
const defaultProfile = "string" == typeof browser.defaultProfile ? browser.defaultProfile.trim() : "";
|
|
443
|
+
if (defaultProfile) {
|
|
444
|
+
const profiles = readStringRecord(browser.profiles);
|
|
445
|
+
const profilesDir = "string" == typeof browser.profilesDir && browser.profilesDir.trim() ? browser.profilesDir.trim() : DEFAULT_BROWSER_PROFILES_DIR;
|
|
446
|
+
const profilePath = profiles[defaultProfile] || normalizePathForConfig(join(profilesDir, defaultProfile));
|
|
447
|
+
const absoluteProfilePath = resolveWorkspacePath(workspace, profilePath);
|
|
448
|
+
if (!existsSync(absoluteProfilePath)) profileDirectory = absoluteProfilePath;
|
|
449
|
+
mkdirSync(absoluteProfilePath, {
|
|
450
|
+
recursive: true
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
const extensions = readStringRecord(browser.extensions);
|
|
454
|
+
const bundledExtensionPath = extensions[DEFAULT_BUNDLED_EXTENSION_ID];
|
|
455
|
+
if (bundledExtensionPath) {
|
|
456
|
+
const absoluteExtensionPath = resolveWorkspacePath(workspace, bundledExtensionPath);
|
|
457
|
+
const bundledExtensionSource = resolveBundledBrowserExtensionPath();
|
|
458
|
+
const manifestPath = join(absoluteExtensionPath, "manifest.json");
|
|
459
|
+
if (bundledExtensionSource && !existsSync(manifestPath)) {
|
|
460
|
+
copyDirectory(bundledExtensionSource, absoluteExtensionPath);
|
|
461
|
+
extensionDirectory = absoluteExtensionPath;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
profileDirectory,
|
|
466
|
+
extensionDirectory
|
|
467
|
+
};
|
|
334
468
|
}
|
|
335
469
|
async function handleAgentSetup(input) {
|
|
336
470
|
const { configRoot, agentId, model, force, nonInteractive, outputManager, bundledAgentsPath, copyAgents, ensureDefaultAgent = true } = input;
|
|
@@ -42,6 +42,7 @@ async function executeSkillCommand(args, options = {}) {
|
|
|
42
42
|
try {
|
|
43
43
|
const repository = new skillRepository_cjs_namespaceObject.SkillRepository({
|
|
44
44
|
provider: config.skills?.provider,
|
|
45
|
+
repositories: config.skills?.repositories,
|
|
45
46
|
repositoryOwner: config.skills?.repositoryOwner,
|
|
46
47
|
repositoryName: config.skills?.repositoryName,
|
|
47
48
|
githubToken: config.skills?.githubToken,
|
|
@@ -126,9 +127,12 @@ Configuration:
|
|
|
126
127
|
Skills can be configured in .wingman/wingman.config.json:
|
|
127
128
|
{
|
|
128
129
|
"skills": {
|
|
129
|
-
"provider": "
|
|
130
|
-
"
|
|
131
|
-
|
|
130
|
+
"provider": "hybrid",
|
|
131
|
+
"repositories": [
|
|
132
|
+
{ "owner": "your-org", "name": "your-skills-repo" }
|
|
133
|
+
],
|
|
134
|
+
"repositoryOwner": "legacy-owner",
|
|
135
|
+
"repositoryName": "legacy-repo",
|
|
132
136
|
"githubToken": "optional-token",
|
|
133
137
|
"clawhubBaseUrl": "https://clawhub.ai",
|
|
134
138
|
"skillsDirectory": "skills",
|
|
@@ -14,6 +14,7 @@ async function executeSkillCommand(args, options = {}) {
|
|
|
14
14
|
try {
|
|
15
15
|
const repository = new SkillRepository({
|
|
16
16
|
provider: config.skills?.provider,
|
|
17
|
+
repositories: config.skills?.repositories,
|
|
17
18
|
repositoryOwner: config.skills?.repositoryOwner,
|
|
18
19
|
repositoryName: config.skills?.repositoryName,
|
|
19
20
|
githubToken: config.skills?.githubToken,
|
|
@@ -98,9 +99,12 @@ Configuration:
|
|
|
98
99
|
Skills can be configured in .wingman/wingman.config.json:
|
|
99
100
|
{
|
|
100
101
|
"skills": {
|
|
101
|
-
"provider": "
|
|
102
|
-
"
|
|
103
|
-
|
|
102
|
+
"provider": "hybrid",
|
|
103
|
+
"repositories": [
|
|
104
|
+
{ "owner": "your-org", "name": "your-skills-repo" }
|
|
105
|
+
],
|
|
106
|
+
"repositoryOwner": "legacy-owner",
|
|
107
|
+
"repositoryName": "legacy-repo",
|
|
104
108
|
"githubToken": "optional-token",
|
|
105
109
|
"clawhubBaseUrl": "https://clawhub.ai",
|
|
106
110
|
"skillsDirectory": "skills",
|
|
@@ -133,9 +133,13 @@ class WingmanConfigLoader {
|
|
|
133
133
|
outputMode: "auto"
|
|
134
134
|
},
|
|
135
135
|
skills: {
|
|
136
|
-
provider: "
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
provider: "hybrid",
|
|
137
|
+
repositories: [
|
|
138
|
+
{
|
|
139
|
+
owner: "RussellCanfield",
|
|
140
|
+
name: "wingman-ai"
|
|
141
|
+
}
|
|
142
|
+
],
|
|
139
143
|
clawhubBaseUrl: "https://clawhub.ai",
|
|
140
144
|
skillsDirectory: "skills",
|
|
141
145
|
security: {
|
|
@@ -105,9 +105,13 @@ class WingmanConfigLoader {
|
|
|
105
105
|
outputMode: "auto"
|
|
106
106
|
},
|
|
107
107
|
skills: {
|
|
108
|
-
provider: "
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
provider: "hybrid",
|
|
109
|
+
repositories: [
|
|
110
|
+
{
|
|
111
|
+
owner: "RussellCanfield",
|
|
112
|
+
name: "wingman-ai"
|
|
113
|
+
}
|
|
114
|
+
],
|
|
111
115
|
clawhubBaseUrl: "https://clawhub.ai",
|
|
112
116
|
skillsDirectory: "skills",
|
|
113
117
|
security: {
|
|
@@ -27,15 +27,16 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27
27
|
SearchConfigSchema: ()=>SearchConfigSchema,
|
|
28
28
|
HumanInTheLoopConfigSchema: ()=>HumanInTheLoopConfigSchema,
|
|
29
29
|
AgentsConfigSchema: ()=>AgentsConfigSchema,
|
|
30
|
+
validateConfig: ()=>validateConfig,
|
|
30
31
|
GatewayConfigSchema: ()=>GatewayConfigSchema,
|
|
31
32
|
BrowserTransportSchema: ()=>BrowserTransportSchema,
|
|
32
33
|
SkillsConfigSchema: ()=>SkillsConfigSchema,
|
|
33
34
|
SummarizationConfigSchema: ()=>SummarizationConfigSchema,
|
|
34
35
|
BrowserConfigSchema: ()=>BrowserConfigSchema,
|
|
36
|
+
GitHubSkillRepositorySchema: ()=>GitHubSkillRepositorySchema,
|
|
35
37
|
ModelRetryConfigSchema: ()=>ModelRetryConfigSchema,
|
|
36
|
-
WingmanConfigSchema: ()=>WingmanConfigSchema,
|
|
37
38
|
ToolRetryConfigSchema: ()=>ToolRetryConfigSchema,
|
|
38
|
-
|
|
39
|
+
WingmanConfigSchema: ()=>WingmanConfigSchema
|
|
39
40
|
});
|
|
40
41
|
const external_zod_namespaceObject = require("zod");
|
|
41
42
|
const types_cjs_namespaceObject = require("../../agent/middleware/hooks/types.cjs");
|
|
@@ -49,13 +50,24 @@ const SearchConfigSchema = external_zod_namespaceObject.object({
|
|
|
49
50
|
]).default("duckduckgo").describe("Search provider to use"),
|
|
50
51
|
maxResults: external_zod_namespaceObject.number().min(1).max(20).optional().default(5).describe("Maximum number of search results to return")
|
|
51
52
|
});
|
|
53
|
+
const GitHubSkillRepositorySchema = external_zod_namespaceObject.object({
|
|
54
|
+
owner: external_zod_namespaceObject.string().min(1).describe("GitHub repository owner for a skills source"),
|
|
55
|
+
name: external_zod_namespaceObject.string().min(1).describe("GitHub repository name for a skills source")
|
|
56
|
+
});
|
|
52
57
|
const SkillsConfigSchema = external_zod_namespaceObject.object({
|
|
53
58
|
provider: external_zod_namespaceObject["enum"]([
|
|
54
59
|
"github",
|
|
55
|
-
"clawhub"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
"clawhub",
|
|
61
|
+
"hybrid"
|
|
62
|
+
]).default("hybrid").describe("Skill source provider"),
|
|
63
|
+
repositories: external_zod_namespaceObject.array(GitHubSkillRepositorySchema).optional().default([
|
|
64
|
+
{
|
|
65
|
+
owner: "RussellCanfield",
|
|
66
|
+
name: "wingman-ai"
|
|
67
|
+
}
|
|
68
|
+
]).describe("Ordered GitHub skill sources. Later repositories override earlier repositories on name conflicts."),
|
|
69
|
+
repositoryOwner: external_zod_namespaceObject.string().optional().describe("Legacy GitHub repository owner fallback when repositories is empty (requires repositoryName)"),
|
|
70
|
+
repositoryName: external_zod_namespaceObject.string().optional().describe("Legacy GitHub repository name fallback when repositories is empty (requires repositoryOwner)"),
|
|
59
71
|
githubToken: external_zod_namespaceObject.string().optional().describe("GitHub personal access token for higher API rate limits"),
|
|
60
72
|
clawhubBaseUrl: external_zod_namespaceObject.string().default("https://clawhub.ai").describe("Base URL for ClawHub skill API"),
|
|
61
73
|
skillsDirectory: external_zod_namespaceObject.string().default("skills").describe("Directory to install skills in"),
|
|
@@ -386,9 +398,13 @@ const WingmanConfigSchema = external_zod_namespaceObject.object({
|
|
|
386
398
|
outputMode: "auto"
|
|
387
399
|
}),
|
|
388
400
|
skills: SkillsConfigSchema.optional().default({
|
|
389
|
-
provider: "
|
|
390
|
-
|
|
391
|
-
|
|
401
|
+
provider: "hybrid",
|
|
402
|
+
repositories: [
|
|
403
|
+
{
|
|
404
|
+
owner: "RussellCanfield",
|
|
405
|
+
name: "wingman-ai"
|
|
406
|
+
}
|
|
407
|
+
],
|
|
392
408
|
clawhubBaseUrl: "https://clawhub.ai",
|
|
393
409
|
skillsDirectory: "skills",
|
|
394
410
|
security: {
|
|
@@ -482,6 +498,7 @@ exports.AgentsConfigSchema = __webpack_exports__.AgentsConfigSchema;
|
|
|
482
498
|
exports.BrowserConfigSchema = __webpack_exports__.BrowserConfigSchema;
|
|
483
499
|
exports.BrowserTransportSchema = __webpack_exports__.BrowserTransportSchema;
|
|
484
500
|
exports.GatewayConfigSchema = __webpack_exports__.GatewayConfigSchema;
|
|
501
|
+
exports.GitHubSkillRepositorySchema = __webpack_exports__.GitHubSkillRepositorySchema;
|
|
485
502
|
exports.HumanInTheLoopConfigSchema = __webpack_exports__.HumanInTheLoopConfigSchema;
|
|
486
503
|
exports.ModelRetryConfigSchema = __webpack_exports__.ModelRetryConfigSchema;
|
|
487
504
|
exports.SearchConfigSchema = __webpack_exports__.SearchConfigSchema;
|
|
@@ -495,6 +512,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
|
495
512
|
"BrowserConfigSchema",
|
|
496
513
|
"BrowserTransportSchema",
|
|
497
514
|
"GatewayConfigSchema",
|
|
515
|
+
"GitHubSkillRepositorySchema",
|
|
498
516
|
"HumanInTheLoopConfigSchema",
|
|
499
517
|
"ModelRetryConfigSchema",
|
|
500
518
|
"SearchConfigSchema",
|
|
@@ -7,13 +7,22 @@ export declare const SearchConfigSchema: z.ZodObject<{
|
|
|
7
7
|
maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
8
8
|
}, z.core.$strip>;
|
|
9
9
|
export type SearchConfig = z.infer<typeof SearchConfigSchema>;
|
|
10
|
+
export declare const GitHubSkillRepositorySchema: z.ZodObject<{
|
|
11
|
+
owner: z.ZodString;
|
|
12
|
+
name: z.ZodString;
|
|
13
|
+
}, z.core.$strip>;
|
|
10
14
|
export declare const SkillsConfigSchema: z.ZodObject<{
|
|
11
15
|
provider: z.ZodDefault<z.ZodEnum<{
|
|
12
16
|
github: "github";
|
|
13
17
|
clawhub: "clawhub";
|
|
18
|
+
hybrid: "hybrid";
|
|
14
19
|
}>>;
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
repositories: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
21
|
+
owner: z.ZodString;
|
|
22
|
+
name: z.ZodString;
|
|
23
|
+
}, z.core.$strip>>>>;
|
|
24
|
+
repositoryOwner: z.ZodOptional<z.ZodString>;
|
|
25
|
+
repositoryName: z.ZodOptional<z.ZodString>;
|
|
17
26
|
githubToken: z.ZodOptional<z.ZodString>;
|
|
18
27
|
clawhubBaseUrl: z.ZodDefault<z.ZodString>;
|
|
19
28
|
skillsDirectory: z.ZodDefault<z.ZodString>;
|
|
@@ -315,9 +324,14 @@ export declare const WingmanConfigSchema: z.ZodObject<{
|
|
|
315
324
|
provider: z.ZodDefault<z.ZodEnum<{
|
|
316
325
|
github: "github";
|
|
317
326
|
clawhub: "clawhub";
|
|
327
|
+
hybrid: "hybrid";
|
|
318
328
|
}>>;
|
|
319
|
-
|
|
320
|
-
|
|
329
|
+
repositories: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
330
|
+
owner: z.ZodString;
|
|
331
|
+
name: z.ZodString;
|
|
332
|
+
}, z.core.$strip>>>>;
|
|
333
|
+
repositoryOwner: z.ZodOptional<z.ZodString>;
|
|
334
|
+
repositoryName: z.ZodOptional<z.ZodString>;
|
|
321
335
|
githubToken: z.ZodOptional<z.ZodString>;
|
|
322
336
|
clawhubBaseUrl: z.ZodDefault<z.ZodString>;
|
|
323
337
|
skillsDirectory: z.ZodDefault<z.ZodString>;
|
|
@@ -10,13 +10,24 @@ const SearchConfigSchema = object({
|
|
|
10
10
|
]).default("duckduckgo").describe("Search provider to use"),
|
|
11
11
|
maxResults: number().min(1).max(20).optional().default(5).describe("Maximum number of search results to return")
|
|
12
12
|
});
|
|
13
|
+
const GitHubSkillRepositorySchema = object({
|
|
14
|
+
owner: string().min(1).describe("GitHub repository owner for a skills source"),
|
|
15
|
+
name: string().min(1).describe("GitHub repository name for a skills source")
|
|
16
|
+
});
|
|
13
17
|
const SkillsConfigSchema = object({
|
|
14
18
|
provider: external_zod_enum([
|
|
15
19
|
"github",
|
|
16
|
-
"clawhub"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
"clawhub",
|
|
21
|
+
"hybrid"
|
|
22
|
+
]).default("hybrid").describe("Skill source provider"),
|
|
23
|
+
repositories: array(GitHubSkillRepositorySchema).optional().default([
|
|
24
|
+
{
|
|
25
|
+
owner: "RussellCanfield",
|
|
26
|
+
name: "wingman-ai"
|
|
27
|
+
}
|
|
28
|
+
]).describe("Ordered GitHub skill sources. Later repositories override earlier repositories on name conflicts."),
|
|
29
|
+
repositoryOwner: string().optional().describe("Legacy GitHub repository owner fallback when repositories is empty (requires repositoryName)"),
|
|
30
|
+
repositoryName: string().optional().describe("Legacy GitHub repository name fallback when repositories is empty (requires repositoryOwner)"),
|
|
20
31
|
githubToken: string().optional().describe("GitHub personal access token for higher API rate limits"),
|
|
21
32
|
clawhubBaseUrl: string().default("https://clawhub.ai").describe("Base URL for ClawHub skill API"),
|
|
22
33
|
skillsDirectory: string().default("skills").describe("Directory to install skills in"),
|
|
@@ -347,9 +358,13 @@ const WingmanConfigSchema = object({
|
|
|
347
358
|
outputMode: "auto"
|
|
348
359
|
}),
|
|
349
360
|
skills: SkillsConfigSchema.optional().default({
|
|
350
|
-
provider: "
|
|
351
|
-
|
|
352
|
-
|
|
361
|
+
provider: "hybrid",
|
|
362
|
+
repositories: [
|
|
363
|
+
{
|
|
364
|
+
owner: "RussellCanfield",
|
|
365
|
+
name: "wingman-ai"
|
|
366
|
+
}
|
|
367
|
+
],
|
|
353
368
|
clawhubBaseUrl: "https://clawhub.ai",
|
|
354
369
|
skillsDirectory: "skills",
|
|
355
370
|
security: {
|
|
@@ -439,4 +454,4 @@ function validateConfig(data) {
|
|
|
439
454
|
};
|
|
440
455
|
}
|
|
441
456
|
}
|
|
442
|
-
export { AgentsConfigSchema, BrowserConfigSchema, BrowserTransportSchema, GatewayConfigSchema, HumanInTheLoopConfigSchema, ModelRetryConfigSchema, SearchConfigSchema, SkillsConfigSchema, SummarizationConfigSchema, ToolRetryConfigSchema, WingmanConfigSchema, validateConfig };
|
|
457
|
+
export { AgentsConfigSchema, BrowserConfigSchema, BrowserTransportSchema, GatewayConfigSchema, GitHubSkillRepositorySchema, HumanInTheLoopConfigSchema, ModelRetryConfigSchema, SearchConfigSchema, SkillsConfigSchema, SummarizationConfigSchema, ToolRetryConfigSchema, WingmanConfigSchema, validateConfig };
|