@straion/cli 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +0 -4
- package/dist/cli.d.ts +0 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -7
- package/dist/cli.js.map +1 -1
- package/dist/commands/default.d.ts +1 -2
- package/dist/commands/default.d.ts.map +1 -1
- package/dist/commands/default.js +7 -42
- package/dist/commands/default.js.map +1 -1
- package/dist/commands/find-requirements.d.ts.map +1 -1
- package/dist/commands/find-requirements.integration.test.js +17 -56
- package/dist/commands/find-requirements.integration.test.js.map +1 -1
- package/dist/commands/find-requirements.js +20 -32
- package/dist/commands/find-requirements.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.integration.test.js +21 -142
- package/dist/commands/login.integration.test.js.map +1 -1
- package/dist/commands/login.js +10 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/logout.d.ts.map +1 -1
- package/dist/commands/logout.js +7 -22
- package/dist/commands/logout.js.map +1 -1
- package/dist/commands/session-start.d.ts.map +1 -1
- package/dist/commands/session-start.js +1 -8
- package/dist/commands/session-start.js.map +1 -1
- package/dist/commands/setup.d.ts +3 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +23 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/components/banner.d.ts +3 -0
- package/dist/components/banner.d.ts.map +1 -0
- package/dist/components/banner.js +13 -0
- package/dist/components/banner.js.map +1 -0
- package/dist/components/default-flow.d.ts +11 -0
- package/dist/components/default-flow.d.ts.map +1 -0
- package/dist/components/default-flow.js +64 -0
- package/dist/components/default-flow.js.map +1 -0
- package/dist/components/hero.d.ts.map +1 -1
- package/dist/components/hero.js +22 -28
- package/dist/components/hero.js.map +1 -1
- package/dist/components/login/login-error.d.ts.map +1 -1
- package/dist/components/login/login-error.js +2 -4
- package/dist/components/login/login-error.js.map +1 -1
- package/dist/components/login/login-flow.d.ts +3 -3
- package/dist/components/login/login-flow.d.ts.map +1 -1
- package/dist/components/login/login-flow.js +19 -49
- package/dist/components/login/login-flow.js.map +1 -1
- package/dist/components/login/login-flow.test.js +8 -8
- package/dist/components/login/login-flow.test.js.map +1 -1
- package/dist/components/login/user-settings-link.d.ts +3 -0
- package/dist/components/login/user-settings-link.d.ts.map +1 -0
- package/dist/components/login/user-settings-link.js +8 -0
- package/dist/components/login/user-settings-link.js.map +1 -0
- package/dist/components/multi-select.d.ts +16 -0
- package/dist/components/multi-select.d.ts.map +1 -0
- package/dist/components/multi-select.js +105 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/org-selector.d.ts.map +1 -1
- package/dist/components/org-selector.js +3 -1
- package/dist/components/org-selector.js.map +1 -1
- package/dist/components/pat-input.js +1 -1
- package/dist/components/pat-input.js.map +1 -1
- package/dist/components/setup/agent-setup.d.ts +9 -0
- package/dist/components/setup/agent-setup.d.ts.map +1 -0
- package/dist/components/setup/agent-setup.js +65 -0
- package/dist/components/setup/agent-setup.js.map +1 -0
- package/dist/components/setup/agents/agent-registry.d.ts +44 -0
- package/dist/components/setup/agents/agent-registry.d.ts.map +1 -0
- package/dist/components/setup/agents/agent-registry.js +64 -0
- package/dist/components/setup/agents/agent-registry.js.map +1 -0
- package/dist/components/setup/agents/command-helpers.d.ts +5 -0
- package/dist/components/setup/agents/command-helpers.d.ts.map +1 -0
- package/dist/components/setup/agents/command-helpers.js +28 -0
- package/dist/components/setup/agents/command-helpers.js.map +1 -0
- package/dist/components/setup/checking-agents.d.ts +16 -0
- package/dist/components/setup/checking-agents.d.ts.map +1 -0
- package/dist/components/setup/checking-agents.js +30 -0
- package/dist/components/setup/checking-agents.js.map +1 -0
- package/dist/components/setup/download-skills-and-plugins.d.ts +9 -0
- package/dist/components/setup/download-skills-and-plugins.d.ts.map +1 -0
- package/dist/components/setup/download-skills-and-plugins.js +29 -0
- package/dist/components/setup/download-skills-and-plugins.js.map +1 -0
- package/dist/components/setup/perform-setup.d.ts +23 -0
- package/dist/components/setup/perform-setup.d.ts.map +1 -0
- package/dist/components/setup/perform-setup.js +45 -0
- package/dist/components/setup/perform-setup.js.map +1 -0
- package/dist/components/spinner.d.ts +6 -2
- package/dist/components/spinner.d.ts.map +1 -1
- package/dist/components/spinner.js +12 -3
- package/dist/components/spinner.js.map +1 -1
- package/dist/hooks/use-credentials.d.ts +13 -0
- package/dist/hooks/use-credentials.d.ts.map +1 -0
- package/dist/hooks/use-credentials.js +33 -0
- package/dist/hooks/use-credentials.js.map +1 -0
- package/dist/lib/graphql.d.ts +57 -41
- package/dist/lib/graphql.d.ts.map +1 -1
- package/dist/lib/graphql.js +7 -0
- package/dist/lib/graphql.js.map +1 -1
- package/dist/lib/logger.d.ts +13 -8
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/logger.js +6 -29
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/login.d.ts.map +1 -1
- package/dist/lib/middleware.d.ts +4 -8
- package/dist/lib/middleware.d.ts.map +1 -1
- package/dist/lib/middleware.js +5 -9
- package/dist/lib/middleware.js.map +1 -1
- package/dist/lib/skills-manager.d.ts +33 -0
- package/dist/lib/skills-manager.d.ts.map +1 -0
- package/dist/lib/skills-manager.js +233 -0
- package/dist/lib/skills-manager.js.map +1 -0
- package/dist/lib/skills-manager.test.d.ts +7 -0
- package/dist/lib/skills-manager.test.d.ts.map +1 -0
- package/dist/lib/skills-manager.test.js +248 -0
- package/dist/lib/skills-manager.test.js.map +1 -0
- package/dist/state/global-config.d.ts +23 -9
- package/dist/state/global-config.d.ts.map +1 -1
- package/dist/state/global-config.js +42 -36
- package/dist/state/global-config.js.map +1 -1
- package/dist/state/session-manager.js +2 -2
- package/dist/state/session-manager.js.map +1 -1
- package/dist/test/integration-helpers.d.ts +0 -5
- package/dist/test/integration-helpers.d.ts.map +1 -1
- package/dist/test/integration-helpers.js +0 -16
- package/dist/test/integration-helpers.js.map +1 -1
- package/package.json +15 -4
- package/dist/lib/output.d.ts +0 -16
- package/dist/lib/output.d.ts.map +0 -1
- package/dist/lib/output.js +0 -14
- package/dist/lib/output.js.map +0 -1
- package/dist/state/directory-config.d.ts +0 -21
- package/dist/state/directory-config.d.ts.map +0 -1
- package/dist/state/directory-config.js +0 -59
- package/dist/state/directory-config.js.map +0 -1
- /package/{LICENSE.txt → LICENSE} +0 -0
package/dist/lib/middleware.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import { createCredentialManager } from '../auth/credentials.js';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveOrgForDirectory } from '../state/global-config.js';
|
|
3
3
|
import { createCommandLogger } from './logger.js';
|
|
4
4
|
/**
|
|
5
5
|
* Wrapper for command actions that provides logging only (no auth).
|
|
6
6
|
* Requires `--session <id>` option on the command
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
|
-
* .action(withLogging(async (options, { logger
|
|
9
|
+
* .action(withLogging(async (options, { logger }) => {
|
|
10
10
|
* logger.info('Command started');
|
|
11
11
|
* // With data: logger.info({ userId: '123' }, 'User action');
|
|
12
12
|
* }))
|
|
13
13
|
*/
|
|
14
14
|
export function withLogging(action) {
|
|
15
15
|
return async function (options) {
|
|
16
|
-
const globalOpts = this.optsWithGlobals();
|
|
17
16
|
const logger = createCommandLogger(this, {
|
|
18
17
|
sessionId: options.session,
|
|
19
18
|
context: { cwd: process.cwd() },
|
|
20
19
|
});
|
|
21
20
|
try {
|
|
22
|
-
return await action(options, { logger
|
|
21
|
+
return await action(options, { logger }, this);
|
|
23
22
|
}
|
|
24
23
|
catch (error) {
|
|
25
24
|
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
@@ -33,20 +32,18 @@ export function withLogging(action) {
|
|
|
33
32
|
* Requires `--session <id>` option on the command.
|
|
34
33
|
*
|
|
35
34
|
* @example
|
|
36
|
-
* .action(withAuthAndLogging(async (options, { logger, accessToken, organization
|
|
35
|
+
* .action(withAuthAndLogging(async (options, { logger, accessToken, organization }) => {
|
|
37
36
|
* logger.info('Command started');
|
|
38
37
|
* // With data: logger.info({ orgId: organization.id }, 'Processing org');
|
|
39
38
|
* }))
|
|
40
39
|
*/
|
|
41
40
|
export function withAuthAndLogging(action) {
|
|
42
41
|
return async function (options) {
|
|
43
|
-
const globalOpts = this.optsWithGlobals();
|
|
44
42
|
const logger = createCommandLogger(this, {
|
|
45
43
|
sessionId: options.session,
|
|
46
44
|
context: { cwd: process.cwd() },
|
|
47
45
|
});
|
|
48
46
|
try {
|
|
49
|
-
// Support STRAION_API_KEY env var as alternative to stored credentials
|
|
50
47
|
const envToken = process.env.STRAION_API_KEY;
|
|
51
48
|
let accessToken = null;
|
|
52
49
|
if (envToken) {
|
|
@@ -61,14 +58,13 @@ export function withAuthAndLogging(action) {
|
|
|
61
58
|
logger.debug('Using token from stored credentials');
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
|
-
const resolvedOrg =
|
|
61
|
+
const resolvedOrg = resolveOrgForDirectory(process.cwd());
|
|
65
62
|
if (!accessToken || !resolvedOrg) {
|
|
66
63
|
console.log('No credentials for the straion cli found. Please log in first using "straion login".');
|
|
67
64
|
process.exit(1);
|
|
68
65
|
}
|
|
69
66
|
const ctx = {
|
|
70
67
|
logger,
|
|
71
|
-
outputFormat: globalOpts.outputFormat,
|
|
72
68
|
accessToken,
|
|
73
69
|
organization: resolvedOrg,
|
|
74
70
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/lib/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/lib/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAGnE,OAAO,EAAE,mBAAmB,EAAuB,MAAM,aAAa,CAAC;AAWvE;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,MAAiF;IAEjF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAgF;IAEhF,OAAO,KAAK,WAA0B,OAAiB;QACrD,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,EAAE;YACvC,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YAC7C,IAAI,WAAW,GAAkB,IAAI,CAAC;YAEtC,IAAI,QAAQ,EAAE,CAAC;gBACb,WAAW,GAAG,QAAQ,CAAC;gBACvB,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,MAAM,iBAAiB,GAAG,MAAM,uBAAuB,EAAE,CAAC;gBAC1D,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,cAAc,EAAE,CAAC;gBAC7D,WAAW,GAAG,WAAW,EAAE,WAAW,IAAI,IAAI,CAAC;gBAC/C,IAAI,WAAW,EAAE,CAAC;oBAChB,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;YAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAE1D,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CACT,sFAAsF,CACvF,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAED,MAAM,GAAG,GAAgB;gBACvB,MAAM;gBACN,WAAW;gBACX,YAAY,EAAE,WAAW;aAC1B,CAAC;YAEF,OAAO,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;YAC/C,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type AgentId } from '../components/setup/agents/agent-registry.js';
|
|
2
|
+
export declare const SKILLS_GITHUB_URL = "https://github.com/straion-dev/straion-claude-marketplace";
|
|
3
|
+
export type LinkType = 'symlink' | 'copy' | 'none';
|
|
4
|
+
export interface LinkResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
path: string;
|
|
7
|
+
mode: 'symlink' | 'copy' | 'plugin';
|
|
8
|
+
type: 'plugin' | 'skill';
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
declare const centralMarketplaceDir: string;
|
|
12
|
+
export { centralMarketplaceDir };
|
|
13
|
+
/**
|
|
14
|
+
* Check if central marketplace is downloaded
|
|
15
|
+
*/
|
|
16
|
+
export declare function isDownloaded(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Download and extract marketplace tarball from GitHub.
|
|
19
|
+
* The tarball root is the marketplace root containing .claude-plugin/marketplace.json
|
|
20
|
+
*/
|
|
21
|
+
export declare function download(onProgress?: (msg: string) => void): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Check how skill is linked for an agent
|
|
24
|
+
*/
|
|
25
|
+
export declare function getLinkType(agentSkillsDir: string): LinkType;
|
|
26
|
+
/**
|
|
27
|
+
* Link skill to agent (symlink preferred, copy as fallback)
|
|
28
|
+
* @returns LinkResult with success status, path, and mode
|
|
29
|
+
*/
|
|
30
|
+
export declare function linkSkill(agentSkillsDir: string, skillName: string): Promise<LinkResult>;
|
|
31
|
+
export declare function linkPlugin(installPlugin: (marketplacePath: string) => Promise<boolean>): Promise<LinkResult>;
|
|
32
|
+
export declare function link(agent: AgentId): Promise<LinkResult[]>;
|
|
33
|
+
//# sourceMappingURL=skills-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manager.d.ts","sourceRoot":"","sources":["../../src/lib/skills-manager.ts"],"names":[],"mappings":"AAeA,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,8CAA8C,CAAC;AASpF,eAAO,MAAM,iBAAiB,8DAA8D,CAAC;AAI7F,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD,QAAA,MAAM,qBAAqB,QAAiC,CAAC;AAG7D,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAEjC;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDhF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,QAAQ,CAuB5D;AAeD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmE9F;AAED,wBAAsB,UAAU,CAC9B,aAAa,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC3D,OAAO,CAAC,UAAU,CAAC,CAqBrB;AAED,wBAAsB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA2BhE"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { exec as execCallback } from 'node:child_process';
|
|
2
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, readlinkSync, rmSync, symlinkSync, } from 'node:fs';
|
|
3
|
+
import { cp, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join, resolve } from 'node:path';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
import { agents } from '../components/setup/agents/agent-registry.js';
|
|
8
|
+
import { ensureGlobalDir, globalDir } from '../state/global-config.js';
|
|
9
|
+
import { createLogger } from './logger.js';
|
|
10
|
+
const exec = promisify(execCallback);
|
|
11
|
+
const logger = createLogger();
|
|
12
|
+
export const SKILLS_GITHUB_URL = 'https://github.com/straion-dev/straion-claude-marketplace';
|
|
13
|
+
// Placeholder URL - replace with actual GitHub tarball URL
|
|
14
|
+
const SKILLS_GITHUB_TAR_URL = `${SKILLS_GITHUB_URL}/archive/refs/heads/main.tar.gz`;
|
|
15
|
+
// Central marketplace directory - the tarball root is the marketplace root
|
|
16
|
+
// Structure:
|
|
17
|
+
// ~/.straion/marketplace/
|
|
18
|
+
// ├── .claude-plugin/marketplace.json
|
|
19
|
+
// └── straion-plugin/
|
|
20
|
+
// ├── .claude-plugin/plugin.json
|
|
21
|
+
// ├── skills/straion/
|
|
22
|
+
// └── hooks/
|
|
23
|
+
const centralMarketplaceDir = join(globalDir, 'marketplace');
|
|
24
|
+
const centralSkillsDir = join(centralMarketplaceDir, 'straion-plugin', 'skills');
|
|
25
|
+
export { centralMarketplaceDir };
|
|
26
|
+
/**
|
|
27
|
+
* Check if central marketplace is downloaded
|
|
28
|
+
*/
|
|
29
|
+
export function isDownloaded() {
|
|
30
|
+
return existsSync(centralMarketplaceDir);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Download and extract marketplace tarball from GitHub.
|
|
34
|
+
* The tarball root is the marketplace root containing .claude-plugin/marketplace.json
|
|
35
|
+
*/
|
|
36
|
+
export async function download(onProgress) {
|
|
37
|
+
const progress = onProgress ?? (() => undefined);
|
|
38
|
+
progress('Fetching marketplace from GitHub...');
|
|
39
|
+
// Create temp directory for download
|
|
40
|
+
const tempDir = join(tmpdir(), `straion-marketplace-${Date.now()}`);
|
|
41
|
+
mkdirSync(tempDir, { recursive: true });
|
|
42
|
+
try {
|
|
43
|
+
// Fetch the tarball
|
|
44
|
+
const response = await fetch(SKILLS_GITHUB_TAR_URL);
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(`Failed to download: ${response.status} ${response.statusText}`);
|
|
47
|
+
}
|
|
48
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
49
|
+
const tarballPath = join(tempDir, 'marketplace.tar.gz');
|
|
50
|
+
await writeFile(tarballPath, Buffer.from(arrayBuffer));
|
|
51
|
+
progress('Extracting skills and plugins...');
|
|
52
|
+
const extractDir = join(tempDir, 'extracted');
|
|
53
|
+
mkdirSync(extractDir, { recursive: true });
|
|
54
|
+
await exec(`tar -xzf "${tarballPath}" -C "${extractDir}"`);
|
|
55
|
+
// Find the extracted directory (GitHub tarballs extract to repo-branch/)
|
|
56
|
+
const extractedContents = readdirSync(extractDir);
|
|
57
|
+
if (extractedContents.length === 0) {
|
|
58
|
+
throw new Error('Extracted tarball is empty');
|
|
59
|
+
}
|
|
60
|
+
const extractedDir = join(extractDir, extractedContents[0]);
|
|
61
|
+
// Ensure global directory exists
|
|
62
|
+
ensureGlobalDir();
|
|
63
|
+
// Remove existing marketplace if present
|
|
64
|
+
if (existsSync(centralMarketplaceDir)) {
|
|
65
|
+
rmSync(centralMarketplaceDir, { recursive: true, force: true });
|
|
66
|
+
}
|
|
67
|
+
// Copy the entire extracted repo as the marketplace
|
|
68
|
+
// The tarball root is the marketplace root with structure:
|
|
69
|
+
// ├── .claude-plugin/marketplace.json
|
|
70
|
+
// └── straion-plugin/
|
|
71
|
+
// ├── .claude-plugin/plugin.json
|
|
72
|
+
// ├── skills/straion/
|
|
73
|
+
// └── hooks/
|
|
74
|
+
await cp(extractedDir, centralMarketplaceDir, { recursive: true });
|
|
75
|
+
progress('Skills and plugins downloaded successfully');
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
// Clean up temp directory
|
|
79
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check how skill is linked for an agent
|
|
84
|
+
*/
|
|
85
|
+
export function getLinkType(agentSkillsDir) {
|
|
86
|
+
const skillPath = join(agentSkillsDir);
|
|
87
|
+
if (!existsSync(skillPath)) {
|
|
88
|
+
return 'none';
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const stats = lstatSync(skillPath);
|
|
92
|
+
if (stats.isSymbolicLink()) {
|
|
93
|
+
// Verify it points to our central skill
|
|
94
|
+
const target = readlinkSync(skillPath);
|
|
95
|
+
if (target === centralSkillsDir) {
|
|
96
|
+
return 'symlink';
|
|
97
|
+
}
|
|
98
|
+
// Symlink exists but points elsewhere
|
|
99
|
+
return 'none';
|
|
100
|
+
}
|
|
101
|
+
// It's a regular directory (copy)
|
|
102
|
+
return 'copy';
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return 'none';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Cleans and recreates a directory.
|
|
110
|
+
* Handles edge cases like broken symlinks and ELOOP errors.
|
|
111
|
+
*/
|
|
112
|
+
function cleanAndCreate(path) {
|
|
113
|
+
try {
|
|
114
|
+
rmSync(path, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Ignore cleanup errors - mkdir will fail if there's a real problem
|
|
118
|
+
}
|
|
119
|
+
mkdirSync(path, { recursive: true });
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Link skill to agent (symlink preferred, copy as fallback)
|
|
123
|
+
* @returns LinkResult with success status, path, and mode
|
|
124
|
+
*/
|
|
125
|
+
export async function linkSkill(agentSkillsDir, skillName) {
|
|
126
|
+
if (!existsSync(centralSkillsDir)) {
|
|
127
|
+
return {
|
|
128
|
+
success: false,
|
|
129
|
+
path: '',
|
|
130
|
+
type: 'skill',
|
|
131
|
+
mode: 'symlink',
|
|
132
|
+
error: 'Central skills not downloaded. Call download() first.',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Ensure agent skills directory exists
|
|
136
|
+
mkdirSync(agentSkillsDir, { recursive: true });
|
|
137
|
+
const targetPath = join(agentSkillsDir, skillName);
|
|
138
|
+
const centralSkillPath = join(centralSkillsDir, skillName);
|
|
139
|
+
logger.debug(`Linking skill ${skillName} to agent skills dir at ${targetPath}`);
|
|
140
|
+
// Self-loop detection: if paths resolve to same location, no symlink needed
|
|
141
|
+
const resolvedSource = resolve(centralSkillPath);
|
|
142
|
+
const resolvedTarget = resolve(targetPath);
|
|
143
|
+
logger.debug({ source: resolvedSource, target: resolvedTarget }, 'Resolved paths for self-loop check');
|
|
144
|
+
if (resolvedSource === resolvedTarget) {
|
|
145
|
+
return { success: true, path: targetPath, mode: 'symlink', type: 'skill' };
|
|
146
|
+
}
|
|
147
|
+
// Clean up existing path, handling ELOOP (circular symlink) errors
|
|
148
|
+
try {
|
|
149
|
+
const stats = lstatSync(targetPath);
|
|
150
|
+
if (stats) {
|
|
151
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
// Handle ELOOP (too many symbolic links) - indicates corrupted symlink
|
|
156
|
+
if (err && typeof err === 'object' && 'code' in err && err.code === 'ELOOP') {
|
|
157
|
+
try {
|
|
158
|
+
rmSync(targetPath, { force: true });
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// If we can't remove it, symlink creation will fail and trigger copy fallback
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// ENOENT is fine - path doesn't exist
|
|
165
|
+
}
|
|
166
|
+
// Try symlink first
|
|
167
|
+
try {
|
|
168
|
+
symlinkSync(centralSkillPath, targetPath, 'dir');
|
|
169
|
+
return { success: true, path: targetPath, mode: 'symlink', type: 'skill' };
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// Symlink failed (likely Windows without dev mode), fall back to copy
|
|
173
|
+
try {
|
|
174
|
+
cleanAndCreate(targetPath);
|
|
175
|
+
await cp(centralSkillPath, targetPath, { recursive: true });
|
|
176
|
+
return { success: true, path: targetPath, mode: 'copy', type: 'skill' };
|
|
177
|
+
}
|
|
178
|
+
catch (copyErr) {
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
path: targetPath,
|
|
182
|
+
mode: 'copy',
|
|
183
|
+
error: copyErr instanceof Error ? copyErr.message : 'Failed to copy skills',
|
|
184
|
+
type: 'skill',
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export async function linkPlugin(installPlugin) {
|
|
190
|
+
if (!existsSync(centralMarketplaceDir)) {
|
|
191
|
+
logger.error('Central marketplace directory does not exist.');
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
path: '',
|
|
195
|
+
mode: 'plugin',
|
|
196
|
+
type: 'plugin',
|
|
197
|
+
error: 'Plugin not downloaded. Call download() first.',
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
// If agent has a native plugin install method, use it
|
|
201
|
+
const success = await installPlugin(centralMarketplaceDir);
|
|
202
|
+
return {
|
|
203
|
+
success,
|
|
204
|
+
path: centralMarketplaceDir,
|
|
205
|
+
mode: 'plugin',
|
|
206
|
+
type: 'plugin',
|
|
207
|
+
error: success ? undefined : 'Failed to install plugin via agent CLI',
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
export async function link(agent) {
|
|
211
|
+
const agentInfo = agents[agent];
|
|
212
|
+
if ('installPlugin' in agentInfo) {
|
|
213
|
+
const res = await linkPlugin(agentInfo.installPlugin);
|
|
214
|
+
return [res];
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// we need to create one link per skill in the central skill directory.
|
|
218
|
+
const skillDirs = readdirSync(centralSkillsDir, { withFileTypes: true })
|
|
219
|
+
.filter((dirent) => dirent.isDirectory())
|
|
220
|
+
.map((dirent) => dirent.name);
|
|
221
|
+
const results = await Promise.allSettled(skillDirs.map((skillName) => linkSkill(agentInfo.globalSkillsDir, skillName)));
|
|
222
|
+
return results.map((res) => res.status === 'fulfilled'
|
|
223
|
+
? res.value
|
|
224
|
+
: {
|
|
225
|
+
success: false,
|
|
226
|
+
path: '',
|
|
227
|
+
mode: 'symlink',
|
|
228
|
+
type: 'skill',
|
|
229
|
+
error: res.reason instanceof Error ? res.reason.message : String(res.reason),
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=skills-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manager.js","sourceRoot":"","sources":["../../src/lib/skills-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manager.test.d.ts","sourceRoot":"","sources":["../../src/lib/skills-manager.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the skills-manager module.
|
|
3
|
+
*
|
|
4
|
+
* Tests cover skill download, linking (symlink/copy), and detection.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, lstatSync, mkdirSync, readlinkSync, rmSync, symlinkSync, writeFileSync, } from 'node:fs';
|
|
7
|
+
import os from 'node:os';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
10
|
+
// Use vi.hoisted to create the mock path before vi.mock runs
|
|
11
|
+
const { mockGlobalDir } = vi.hoisted(() => {
|
|
12
|
+
const nodePath = require('node:path');
|
|
13
|
+
const nodeOs = require('node:os');
|
|
14
|
+
const nodeFs = require('node:fs');
|
|
15
|
+
const testId = `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
16
|
+
const dir = nodePath.join(nodeOs.tmpdir(), `straion-test-global-${testId}`);
|
|
17
|
+
return {
|
|
18
|
+
mockGlobalDir: dir,
|
|
19
|
+
existsSync: nodeFs.existsSync,
|
|
20
|
+
mkdirSync: nodeFs.mkdirSync,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
vi.mock('../state/global-config.js', () => {
|
|
24
|
+
const nodeFs = require('node:fs');
|
|
25
|
+
return {
|
|
26
|
+
globalDir: mockGlobalDir,
|
|
27
|
+
ensureGlobalDir: () => {
|
|
28
|
+
if (!nodeFs.existsSync(mockGlobalDir)) {
|
|
29
|
+
nodeFs.mkdirSync(mockGlobalDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
return mockGlobalDir;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
// Import after mocking
|
|
36
|
+
import { download, getLinkType, isDownloaded, linkSkill } from './skills-manager.js';
|
|
37
|
+
describe('skills-manager', () => {
|
|
38
|
+
let tempAgentDir;
|
|
39
|
+
// New marketplace structure
|
|
40
|
+
const centralMarketplaceDir = path.join(mockGlobalDir, 'marketplace');
|
|
41
|
+
const centralPluginPath = path.join(centralMarketplaceDir, 'straion-plugin');
|
|
42
|
+
const centralSkillsDir = path.join(centralPluginPath, 'skills');
|
|
43
|
+
const centralSkillPath = path.join(centralSkillsDir, 'straion');
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
// Create fresh temp directories for each test
|
|
46
|
+
tempAgentDir = path.join(os.tmpdir(), `straion-agent-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
47
|
+
mkdirSync(tempAgentDir, { recursive: true });
|
|
48
|
+
// Ensure clean state for global dir
|
|
49
|
+
mkdirSync(mockGlobalDir, { recursive: true });
|
|
50
|
+
if (existsSync(centralMarketplaceDir)) {
|
|
51
|
+
rmSync(centralMarketplaceDir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
afterEach(() => {
|
|
55
|
+
// Clean up temp directories
|
|
56
|
+
if (existsSync(tempAgentDir)) {
|
|
57
|
+
rmSync(tempAgentDir, { recursive: true, force: true });
|
|
58
|
+
}
|
|
59
|
+
if (existsSync(centralMarketplaceDir)) {
|
|
60
|
+
rmSync(centralMarketplaceDir, { recursive: true, force: true });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
afterAll(() => {
|
|
64
|
+
// Clean up mock global dir
|
|
65
|
+
if (existsSync(mockGlobalDir)) {
|
|
66
|
+
rmSync(mockGlobalDir, { recursive: true, force: true });
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
describe('isDownloaded', () => {
|
|
70
|
+
it('returns false when marketplace directory does not exist', () => {
|
|
71
|
+
expect(isDownloaded()).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it('returns true when marketplace directory exists', () => {
|
|
74
|
+
mkdirSync(centralMarketplaceDir, { recursive: true });
|
|
75
|
+
expect(isDownloaded()).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
it('returns true when marketplace and plugin directories exist', () => {
|
|
78
|
+
mkdirSync(centralPluginPath, { recursive: true });
|
|
79
|
+
expect(isDownloaded()).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe('getLinkType', () => {
|
|
83
|
+
it('returns "none" when skill path does not exist', () => {
|
|
84
|
+
const skillPath = path.join(tempAgentDir, 'straion');
|
|
85
|
+
const result = getLinkType(skillPath);
|
|
86
|
+
expect(result).toBe('none');
|
|
87
|
+
});
|
|
88
|
+
it('returns "copy" when skill path is a regular directory', () => {
|
|
89
|
+
const skillPath = path.join(tempAgentDir, 'straion');
|
|
90
|
+
mkdirSync(skillPath, { recursive: true });
|
|
91
|
+
writeFileSync(path.join(skillPath, 'SKILL.md'), '# Test Skill');
|
|
92
|
+
const result = getLinkType(skillPath);
|
|
93
|
+
expect(result).toBe('copy');
|
|
94
|
+
});
|
|
95
|
+
it('returns "symlink" when skill path is a symlink to central path', () => {
|
|
96
|
+
// Create central skills directory
|
|
97
|
+
mkdirSync(centralSkillsDir, { recursive: true });
|
|
98
|
+
writeFileSync(path.join(centralSkillsDir, 'SKILL.md'), '# Central Skill');
|
|
99
|
+
// Create symlink in agent dir pointing to centralSkillsDir
|
|
100
|
+
const skillPath = path.join(tempAgentDir, 'straion');
|
|
101
|
+
symlinkSync(centralSkillsDir, skillPath, 'dir');
|
|
102
|
+
const result = getLinkType(skillPath);
|
|
103
|
+
expect(result).toBe('symlink');
|
|
104
|
+
});
|
|
105
|
+
it('returns "none" when symlink points to different location', () => {
|
|
106
|
+
// Create a different target directory
|
|
107
|
+
const otherDir = path.join(os.tmpdir(), `other-skill-${Date.now()}`);
|
|
108
|
+
mkdirSync(otherDir, { recursive: true });
|
|
109
|
+
try {
|
|
110
|
+
// Create symlink pointing elsewhere
|
|
111
|
+
const skillPath = path.join(tempAgentDir, 'straion');
|
|
112
|
+
symlinkSync(otherDir, skillPath, 'dir');
|
|
113
|
+
const result = getLinkType(skillPath);
|
|
114
|
+
expect(result).toBe('none');
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
// Cleanup
|
|
118
|
+
rmSync(otherDir, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
describe('linkSkill', () => {
|
|
123
|
+
const skillName = 'straion';
|
|
124
|
+
beforeEach(() => {
|
|
125
|
+
// Create central skill directory with content (marketplace structure)
|
|
126
|
+
mkdirSync(centralSkillPath, { recursive: true });
|
|
127
|
+
writeFileSync(path.join(centralSkillPath, 'SKILL.md'), '# Central Skill\nTest content');
|
|
128
|
+
writeFileSync(path.join(centralSkillPath, 'index.ts'), 'export const skill = {};');
|
|
129
|
+
});
|
|
130
|
+
it('returns error when central skills not downloaded', async () => {
|
|
131
|
+
// Remove central skills
|
|
132
|
+
rmSync(centralMarketplaceDir, { recursive: true, force: true });
|
|
133
|
+
const result = await linkSkill(tempAgentDir, skillName);
|
|
134
|
+
expect(result.success).toBe(false);
|
|
135
|
+
expect(result.error).toContain('Central skills not downloaded');
|
|
136
|
+
});
|
|
137
|
+
it('creates agent skills directory if it does not exist', async () => {
|
|
138
|
+
const newAgentDir = path.join(os.tmpdir(), `new-agent-${Date.now()}`);
|
|
139
|
+
try {
|
|
140
|
+
await linkSkill(newAgentDir, skillName);
|
|
141
|
+
expect(existsSync(newAgentDir)).toBe(true);
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
rmSync(newAgentDir, { recursive: true, force: true });
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
it('creates symlink to central skill', async () => {
|
|
148
|
+
const result = await linkSkill(tempAgentDir, skillName);
|
|
149
|
+
expect(result.success).toBe(true);
|
|
150
|
+
const skillPath = path.join(tempAgentDir, skillName);
|
|
151
|
+
expect(existsSync(skillPath)).toBe(true);
|
|
152
|
+
expect(result.path).toBe(skillPath);
|
|
153
|
+
// Check if it's a symlink
|
|
154
|
+
const stats = lstatSync(skillPath);
|
|
155
|
+
if (stats.isSymbolicLink()) {
|
|
156
|
+
expect(result.mode).toBe('symlink');
|
|
157
|
+
expect(readlinkSync(skillPath)).toBe(centralSkillPath);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
// On systems where symlink fails, it should be a copy
|
|
161
|
+
expect(result.mode).toBe('copy');
|
|
162
|
+
expect(existsSync(path.join(skillPath, 'SKILL.md'))).toBe(true);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
it('removes existing skill before linking', async () => {
|
|
166
|
+
// Create existing skill directory
|
|
167
|
+
const existingSkillPath = path.join(tempAgentDir, skillName);
|
|
168
|
+
mkdirSync(existingSkillPath, { recursive: true });
|
|
169
|
+
writeFileSync(path.join(existingSkillPath, 'old-file.txt'), 'old content');
|
|
170
|
+
await linkSkill(tempAgentDir, skillName);
|
|
171
|
+
// Old file should be gone
|
|
172
|
+
expect(existsSync(path.join(existingSkillPath, 'old-file.txt'))).toBe(false);
|
|
173
|
+
// New content should exist
|
|
174
|
+
expect(existsSync(path.join(existingSkillPath, 'SKILL.md'))).toBe(true);
|
|
175
|
+
});
|
|
176
|
+
it('removes existing symlink before linking', async () => {
|
|
177
|
+
// Create existing symlink to somewhere else
|
|
178
|
+
const otherDir = path.join(os.tmpdir(), `other-${Date.now()}`);
|
|
179
|
+
mkdirSync(otherDir, { recursive: true });
|
|
180
|
+
try {
|
|
181
|
+
const existingSkillPath = path.join(tempAgentDir, skillName);
|
|
182
|
+
symlinkSync(otherDir, existingSkillPath, 'dir');
|
|
183
|
+
const result = await linkSkill(tempAgentDir, skillName);
|
|
184
|
+
expect(result.success).toBe(true);
|
|
185
|
+
// Should now point to central or be a copy
|
|
186
|
+
const stats = lstatSync(existingSkillPath);
|
|
187
|
+
if (stats.isSymbolicLink()) {
|
|
188
|
+
expect(readlinkSync(existingSkillPath)).toBe(centralSkillPath);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
expect(existsSync(path.join(existingSkillPath, 'SKILL.md'))).toBe(true);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
// Cleanup
|
|
196
|
+
rmSync(otherDir, { recursive: true, force: true });
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
it('handles self-loop when source and target resolve to same path', async () => {
|
|
200
|
+
// Link to the skills directory containing central skill (simulating self-loop scenario)
|
|
201
|
+
const result = await linkSkill(centralSkillsDir, skillName);
|
|
202
|
+
// Should succeed without creating a self-referential symlink
|
|
203
|
+
expect(result.success).toBe(true);
|
|
204
|
+
expect(result.mode).toBe('symlink');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
describe('download', () => {
|
|
208
|
+
beforeEach(() => {
|
|
209
|
+
vi.stubGlobal('fetch', vi.fn());
|
|
210
|
+
});
|
|
211
|
+
afterEach(() => {
|
|
212
|
+
vi.unstubAllGlobals();
|
|
213
|
+
});
|
|
214
|
+
it('throws error on failed fetch', async () => {
|
|
215
|
+
vi.mocked(fetch).mockResolvedValue({
|
|
216
|
+
ok: false,
|
|
217
|
+
status: 404,
|
|
218
|
+
statusText: 'Not Found',
|
|
219
|
+
});
|
|
220
|
+
await expect(download()).rejects.toThrow('Failed to download: 404 Not Found');
|
|
221
|
+
});
|
|
222
|
+
it('calls progress callback during download', async () => {
|
|
223
|
+
vi.mocked(fetch).mockResolvedValue({
|
|
224
|
+
ok: true,
|
|
225
|
+
arrayBuffer: () => Promise.resolve(new ArrayBuffer(0)),
|
|
226
|
+
});
|
|
227
|
+
const progressMessages = [];
|
|
228
|
+
const onProgress = (msg) => progressMessages.push(msg);
|
|
229
|
+
try {
|
|
230
|
+
await download(onProgress);
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// May fail on tar extraction, but progress should still be called
|
|
234
|
+
}
|
|
235
|
+
expect(progressMessages).toContain('Fetching marketplace from GitHub...');
|
|
236
|
+
});
|
|
237
|
+
it('works without progress callback', async () => {
|
|
238
|
+
vi.mocked(fetch).mockResolvedValue({
|
|
239
|
+
ok: false,
|
|
240
|
+
status: 500,
|
|
241
|
+
statusText: 'Server Error',
|
|
242
|
+
});
|
|
243
|
+
// Should not throw on missing callback, only on fetch error
|
|
244
|
+
await expect(download()).rejects.toThrow('Failed to download: 500 Server Error');
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
//# sourceMappingURL=skills-manager.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-manager.test.js","sourceRoot":"","sources":["../../src/lib/skills-manager.test.ts"],"names":[],"mappings":"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"}
|