@alavida/agentpack 0.1.5 → 0.1.7
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/bin/intent.js +30 -5
- package/package.json +6 -3
- package/src/application/auth/get-auth-status.js +97 -0
- package/src/application/auth/login.js +110 -0
- package/src/application/auth/logout.js +16 -0
- package/src/application/auth/verify-auth.js +37 -0
- package/src/cli.js +2 -0
- package/src/commands/auth.js +78 -0
- package/src/commands/skills.js +62 -5
- package/src/domain/auth/registry-resolution.js +55 -0
- package/src/domain/skills/skill-catalog.js +116 -0
- package/src/domain/skills/skill-model.js +70 -1
- package/src/domain/skills/skill-target-resolution.js +100 -0
- package/src/infrastructure/fs/user-config-repository.js +40 -0
- package/src/infrastructure/fs/user-credentials-repository.js +30 -0
- package/src/infrastructure/fs/user-npmrc-repository.js +74 -0
- package/src/infrastructure/runtime/inspect-materialized-skills.js +153 -0
- package/src/infrastructure/runtime/materialize-skills.js +78 -31
- package/src/infrastructure/runtime/open-browser.js +6 -0
- package/src/lib/skills.js +359 -192
package/bin/intent.js
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
8
|
+
const intentPackageRoot = join(packageRoot, 'node_modules', '@tanstack', 'intent');
|
|
9
|
+
|
|
6
10
|
try {
|
|
7
|
-
|
|
11
|
+
const packageJsonPath = join(intentPackageRoot, 'package.json');
|
|
12
|
+
if (!existsSync(packageJsonPath)) {
|
|
13
|
+
const error = new Error('@tanstack/intent is not installed');
|
|
14
|
+
error.code = 'MODULE_NOT_FOUND';
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
19
|
+
const cliRelativePath = typeof packageJson.bin === 'string'
|
|
20
|
+
? packageJson.bin
|
|
21
|
+
: packageJson.bin?.intent;
|
|
22
|
+
|
|
23
|
+
if (!cliRelativePath) {
|
|
24
|
+
throw new Error('@tanstack/intent does not expose an intent cli binary');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const result = spawnSync(process.execPath, [join(intentPackageRoot, cliRelativePath), ...process.argv.slice(2)], {
|
|
28
|
+
stdio: 'inherit',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (result.error) throw result.error;
|
|
32
|
+
process.exit(result.status ?? 0);
|
|
8
33
|
} catch (e) {
|
|
9
34
|
if (e?.code === 'ERR_MODULE_NOT_FOUND' || e?.code === 'MODULE_NOT_FOUND') {
|
|
10
35
|
console.error('@tanstack/intent is not installed.')
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alavida/agentpack",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Package-backed skills lifecycle CLI for agent skills and plugins",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"workspaces": [
|
|
7
|
+
"packages/*"
|
|
8
|
+
],
|
|
6
9
|
"bin": {
|
|
7
10
|
"agentpack": "bin/agentpack.js",
|
|
8
11
|
"intent": "bin/intent.js"
|
|
@@ -20,8 +23,8 @@
|
|
|
20
23
|
"smoke:monorepo": "node scripts/smoke-monorepo.mjs",
|
|
21
24
|
"docs:dev": "cd docs && mint dev",
|
|
22
25
|
"changeset": "changeset",
|
|
23
|
-
"version-packages": "
|
|
24
|
-
"release": "
|
|
26
|
+
"version-packages": "node scripts/version-packages.mjs",
|
|
27
|
+
"release": "node scripts/release.mjs",
|
|
25
28
|
"intent:validate": "npx @tanstack/intent validate",
|
|
26
29
|
"build:dashboard": "node scripts/build-dashboard.mjs"
|
|
27
30
|
},
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { readUserConfig } from '../../infrastructure/fs/user-config-repository.js';
|
|
4
|
+
import { readUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
|
|
5
|
+
import { getUserNpmrcPath, parseNpmrc, readUserNpmrc } from '../../infrastructure/fs/user-npmrc-repository.js';
|
|
6
|
+
import { resolveRegistryConfig } from '../../domain/auth/registry-resolution.js';
|
|
7
|
+
import { verifyAuth } from './verify-auth.js';
|
|
8
|
+
|
|
9
|
+
function findRepoNpmrc(cwd) {
|
|
10
|
+
let current = cwd;
|
|
11
|
+
|
|
12
|
+
while (true) {
|
|
13
|
+
const npmrcPath = join(current, '.npmrc');
|
|
14
|
+
if (existsSync(npmrcPath)) {
|
|
15
|
+
return {
|
|
16
|
+
path: npmrcPath,
|
|
17
|
+
config: parseNpmrc(readFileSync(npmrcPath, 'utf-8')),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const gitPath = join(current, '.git');
|
|
22
|
+
if (existsSync(gitPath)) break;
|
|
23
|
+
|
|
24
|
+
const parent = join(current, '..');
|
|
25
|
+
if (parent === current) break;
|
|
26
|
+
current = parent;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
path: null,
|
|
31
|
+
config: {},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function getAuthStatus({
|
|
36
|
+
cwd = process.cwd(),
|
|
37
|
+
env = process.env,
|
|
38
|
+
verify = false,
|
|
39
|
+
} = {}) {
|
|
40
|
+
const config = readUserConfig({ env });
|
|
41
|
+
const credentials = readUserCredentials({ env });
|
|
42
|
+
const userNpmrc = readUserNpmrc({ env });
|
|
43
|
+
const repoNpmrc = findRepoNpmrc(cwd);
|
|
44
|
+
|
|
45
|
+
const resolved = resolveRegistryConfig({
|
|
46
|
+
scope: config.scope,
|
|
47
|
+
defaults: {
|
|
48
|
+
registry: config.registry,
|
|
49
|
+
verificationPackage: config.verificationPackage,
|
|
50
|
+
},
|
|
51
|
+
userNpmrc,
|
|
52
|
+
repoNpmrc: repoNpmrc.config,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const userNpmrcPath = getUserNpmrcPath({ env });
|
|
56
|
+
const requiredRegistryKey = `${config.scope}:registry`;
|
|
57
|
+
const requiredTokenKey = resolved.registry
|
|
58
|
+
? `//${new URL(resolved.registry).host}/:_authToken`
|
|
59
|
+
: null;
|
|
60
|
+
|
|
61
|
+
const npmWired = Boolean(
|
|
62
|
+
userNpmrc[requiredRegistryKey]
|
|
63
|
+
&& requiredTokenKey
|
|
64
|
+
&& userNpmrc[requiredTokenKey]
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
const result = {
|
|
68
|
+
provider: config.provider,
|
|
69
|
+
configured: Boolean(credentials?.token && npmWired),
|
|
70
|
+
scope: config.scope,
|
|
71
|
+
registry: resolved.registry,
|
|
72
|
+
storage: {
|
|
73
|
+
mode: credentials?.token ? 'file' : 'missing',
|
|
74
|
+
},
|
|
75
|
+
npmConfig: {
|
|
76
|
+
path: userNpmrcPath,
|
|
77
|
+
wired: npmWired,
|
|
78
|
+
source: resolved.source,
|
|
79
|
+
repoOverridePath: repoNpmrc.path,
|
|
80
|
+
},
|
|
81
|
+
verification: {
|
|
82
|
+
status: 'not_checked',
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
if (!verify) {
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
result.verification = await verifyAuth({
|
|
91
|
+
registry: resolved.registry,
|
|
92
|
+
authToken: credentials?.token || null,
|
|
93
|
+
verificationPackage: resolved.verificationPackage,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import readline from 'node:readline/promises';
|
|
2
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
3
|
+
import { readUserConfig, writeUserConfig } from '../../infrastructure/fs/user-config-repository.js';
|
|
4
|
+
import { writeUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
|
|
5
|
+
import { writeManagedNpmrcEntries } from '../../infrastructure/fs/user-npmrc-repository.js';
|
|
6
|
+
import { openBrowser } from '../../infrastructure/runtime/open-browser.js';
|
|
7
|
+
import { verifyAuth } from './verify-auth.js';
|
|
8
|
+
import { AgentpackError, EXIT_CODES } from '../../utils/errors.js';
|
|
9
|
+
|
|
10
|
+
const GITHUB_TOKEN_URL = 'https://github.com/settings/tokens';
|
|
11
|
+
|
|
12
|
+
function buildVerificationFailure(verification) {
|
|
13
|
+
if (verification.status === 'invalid') {
|
|
14
|
+
return new AgentpackError('The GitHub personal access token was rejected by GitHub Packages', {
|
|
15
|
+
code: 'auth_verification_failed',
|
|
16
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (verification.status === 'insufficient_permissions') {
|
|
21
|
+
return new AgentpackError('The GitHub personal access token does not have package read access', {
|
|
22
|
+
code: 'auth_verification_failed',
|
|
23
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (verification.status === 'unreachable') {
|
|
28
|
+
return new AgentpackError('GitHub Packages could not be reached during verification', {
|
|
29
|
+
code: 'auth_verification_failed',
|
|
30
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (verification.status === 'not_configured') {
|
|
35
|
+
return new AgentpackError('Authentication verification is not configured for this machine', {
|
|
36
|
+
code: 'auth_verification_not_configured',
|
|
37
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new AgentpackError('The saved credential was rejected by the configured registry', {
|
|
42
|
+
code: 'auth_verification_failed',
|
|
43
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function login({
|
|
48
|
+
env = process.env,
|
|
49
|
+
scope = null,
|
|
50
|
+
registry = null,
|
|
51
|
+
verificationPackage = null,
|
|
52
|
+
} = {}) {
|
|
53
|
+
const current = readUserConfig({ env });
|
|
54
|
+
const nextConfig = {
|
|
55
|
+
...current,
|
|
56
|
+
scope: scope || current.scope,
|
|
57
|
+
registry: registry || current.registry,
|
|
58
|
+
verificationPackage: verificationPackage || current.verificationPackage,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
openBrowser(GITHUB_TOKEN_URL);
|
|
62
|
+
output.write(`Configuring GitHub Packages auth for ${nextConfig.scope}`);
|
|
63
|
+
output.write('Use a GitHub personal access token with package read access.');
|
|
64
|
+
|
|
65
|
+
const rl = readline.createInterface({ input, output });
|
|
66
|
+
try {
|
|
67
|
+
const token = (await rl.question('Token: ')).trim();
|
|
68
|
+
if (!token) {
|
|
69
|
+
throw new AgentpackError('A GitHub credential is required to continue', {
|
|
70
|
+
code: 'auth_token_missing',
|
|
71
|
+
exitCode: EXIT_CODES.GENERAL,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const verification = await verifyAuth({
|
|
76
|
+
registry: nextConfig.registry,
|
|
77
|
+
authToken: token,
|
|
78
|
+
verificationPackage: nextConfig.verificationPackage,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (verification.status !== 'valid') {
|
|
82
|
+
throw buildVerificationFailure(verification);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const managedEntries = {
|
|
86
|
+
[`${nextConfig.scope}:registry`]: nextConfig.registry,
|
|
87
|
+
[`//${new URL(nextConfig.registry).host}/:_authToken`]: token,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
writeManagedNpmrcEntries({ entries: managedEntries, env });
|
|
91
|
+
writeUserCredentials({ token }, { env });
|
|
92
|
+
writeUserConfig({
|
|
93
|
+
...nextConfig,
|
|
94
|
+
managedNpmKeys: Object.keys(managedEntries),
|
|
95
|
+
}, { env });
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
configured: true,
|
|
99
|
+
provider: nextConfig.provider,
|
|
100
|
+
scope: nextConfig.scope,
|
|
101
|
+
registry: nextConfig.registry,
|
|
102
|
+
verificationPackage: nextConfig.verificationPackage,
|
|
103
|
+
storage: {
|
|
104
|
+
mode: 'file',
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
} finally {
|
|
108
|
+
rl.close();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { deleteUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
|
|
2
|
+
import { removeManagedNpmrcEntries } from '../../infrastructure/fs/user-npmrc-repository.js';
|
|
3
|
+
import { readUserConfig } from '../../infrastructure/fs/user-config-repository.js';
|
|
4
|
+
|
|
5
|
+
export function logout({ env = process.env } = {}) {
|
|
6
|
+
const config = readUserConfig({ env });
|
|
7
|
+
const keys = config.managedNpmKeys || [];
|
|
8
|
+
|
|
9
|
+
deleteUserCredentials({ env });
|
|
10
|
+
removeManagedNpmrcEntries({ keys, env });
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
removedCredentials: true,
|
|
14
|
+
removedNpmKeys: keys.length,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export async function verifyAuth({
|
|
2
|
+
registry,
|
|
3
|
+
authToken,
|
|
4
|
+
verificationPackage,
|
|
5
|
+
} = {}) {
|
|
6
|
+
if (!registry || !authToken || !verificationPackage) {
|
|
7
|
+
return { status: 'not_configured' };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const url = `${registry.replace(/\/+$/, '')}/${encodeURIComponent(verificationPackage)}`;
|
|
11
|
+
|
|
12
|
+
let response;
|
|
13
|
+
try {
|
|
14
|
+
response = await fetch(url, {
|
|
15
|
+
headers: {
|
|
16
|
+
accept: 'application/json',
|
|
17
|
+
authorization: `Bearer ${authToken}`,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
} catch {
|
|
21
|
+
return { status: 'unreachable' };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (response.ok) {
|
|
25
|
+
return { status: 'valid' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (response.status === 401) {
|
|
29
|
+
return { status: 'invalid' };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (response.status === 403) {
|
|
33
|
+
return { status: 'insufficient_permissions' };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { status: 'unreachable' };
|
|
37
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { formatError, AgentpackError, EXIT_CODES } from './utils/errors.js';
|
|
4
4
|
import { output } from './utils/output.js';
|
|
5
|
+
import { authCommand } from './commands/auth.js';
|
|
5
6
|
import { skillsCommand } from './commands/skills.js';
|
|
6
7
|
import { pluginCommand } from './commands/plugin.js';
|
|
7
8
|
|
|
@@ -21,6 +22,7 @@ export function createProgram() {
|
|
|
21
22
|
.option('--workbench <path>', 'Override workbench context (name or path)');
|
|
22
23
|
|
|
23
24
|
program.addCommand(skillsCommand());
|
|
25
|
+
program.addCommand(authCommand());
|
|
24
26
|
program.addCommand(pluginCommand());
|
|
25
27
|
|
|
26
28
|
program.addHelpText('after', `
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { login } from '../application/auth/login.js';
|
|
3
|
+
import { logout } from '../application/auth/logout.js';
|
|
4
|
+
import { output } from '../utils/output.js';
|
|
5
|
+
import { getAuthStatus } from '../application/auth/get-auth-status.js';
|
|
6
|
+
|
|
7
|
+
export function authCommand() {
|
|
8
|
+
const cmd = new Command('auth')
|
|
9
|
+
.description('Configure and inspect package registry authentication');
|
|
10
|
+
|
|
11
|
+
cmd.addHelpText('after', `
|
|
12
|
+
Defaults:
|
|
13
|
+
Scope: @alavida-ai
|
|
14
|
+
Registry: https://npm.pkg.github.com
|
|
15
|
+
Token: GitHub personal access token with package read access
|
|
16
|
+
`);
|
|
17
|
+
|
|
18
|
+
cmd
|
|
19
|
+
.command('login')
|
|
20
|
+
.description('Configure GitHub Packages authentication for this machine')
|
|
21
|
+
.option('--scope <scope>', 'Override the package scope to configure')
|
|
22
|
+
.option('--registry <url>', 'Override the package registry URL')
|
|
23
|
+
.option('--verify-package <packageName>', 'Override the package used for live verification')
|
|
24
|
+
.action(async (opts, command) => {
|
|
25
|
+
const globalOpts = command.optsWithGlobals();
|
|
26
|
+
const result = await login({
|
|
27
|
+
scope: opts.scope || null,
|
|
28
|
+
registry: opts.registry || null,
|
|
29
|
+
verificationPackage: opts.verifyPackage || null,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
if (globalOpts.json) {
|
|
33
|
+
output.json(result);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
output.write(`Configured auth for ${result.scope}`);
|
|
38
|
+
output.write(`Registry: ${result.registry}`);
|
|
39
|
+
output.write(`Storage: ${result.storage.mode}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
cmd
|
|
43
|
+
.command('status')
|
|
44
|
+
.description('Show authentication status for the configured package registry')
|
|
45
|
+
.option('--verify', 'Check whether the stored credential works against the configured registry')
|
|
46
|
+
.action(async (opts, command) => {
|
|
47
|
+
const globalOpts = command.optsWithGlobals();
|
|
48
|
+
const result = await getAuthStatus({ verify: opts.verify });
|
|
49
|
+
|
|
50
|
+
if (globalOpts.json) {
|
|
51
|
+
output.json(result);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
output.write(`Provider: ${result.provider}`);
|
|
56
|
+
output.write(`Configured: ${result.configured}`);
|
|
57
|
+
output.write(`Storage: ${result.storage.mode}`);
|
|
58
|
+
output.write(`Verification: ${result.verification.status}`);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
cmd
|
|
62
|
+
.command('logout')
|
|
63
|
+
.description('Remove configured package registry authentication')
|
|
64
|
+
.action((opts, command) => {
|
|
65
|
+
const globalOpts = command.optsWithGlobals();
|
|
66
|
+
const result = logout();
|
|
67
|
+
|
|
68
|
+
if (globalOpts.json) {
|
|
69
|
+
output.json(result);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
output.write(`Removed Credentials: ${result.removedCredentials}`);
|
|
74
|
+
output.write(`Removed npm Keys: ${result.removedNpmKeys}`);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return cmd;
|
|
78
|
+
}
|
package/src/commands/skills.js
CHANGED
|
@@ -136,6 +136,8 @@ export function skillsCommand() {
|
|
|
136
136
|
output.write(`Outdated Skills: ${result.outdatedCount}`);
|
|
137
137
|
output.write(`Deprecated Skills: ${result.deprecatedCount}`);
|
|
138
138
|
output.write(`Incomplete Skills: ${result.incompleteCount}`);
|
|
139
|
+
output.write(`Runtime Drifted Skills: ${result.runtimeDriftCount}`);
|
|
140
|
+
output.write(`Orphaned Materializations: ${result.orphanedMaterializationCount}`);
|
|
139
141
|
output.write(`Registry Configured: ${result.registry.configured}`);
|
|
140
142
|
|
|
141
143
|
if (result.outdated.length > 0) {
|
|
@@ -170,6 +172,28 @@ export function skillsCommand() {
|
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
}
|
|
175
|
+
|
|
176
|
+
if (result.runtimeDrift.length > 0) {
|
|
177
|
+
output.write('');
|
|
178
|
+
output.write('Runtime Drift:');
|
|
179
|
+
for (const install of result.runtimeDrift) {
|
|
180
|
+
output.write(`- ${install.packageName}`);
|
|
181
|
+
for (const issue of install.issues) {
|
|
182
|
+
output.write(` issue: ${issue.code}`);
|
|
183
|
+
output.write(` target: ${issue.target}`);
|
|
184
|
+
if (issue.runtimeName) output.write(` runtime: ${issue.runtimeName}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (result.orphanedMaterializations.length > 0) {
|
|
190
|
+
output.write('');
|
|
191
|
+
output.write('Orphaned Materializations:');
|
|
192
|
+
for (const entry of result.orphanedMaterializations) {
|
|
193
|
+
output.write(`- ${entry.target}`);
|
|
194
|
+
output.write(` issue: ${entry.code}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
173
197
|
});
|
|
174
198
|
|
|
175
199
|
cmd
|
|
@@ -280,6 +304,19 @@ export function skillsCommand() {
|
|
|
280
304
|
return;
|
|
281
305
|
}
|
|
282
306
|
|
|
307
|
+
if (result.kind === 'package') {
|
|
308
|
+
output.write(`Package: ${result.packageName}`);
|
|
309
|
+
if (result.packageVersion) output.write(`Version: ${result.packageVersion}`);
|
|
310
|
+
output.write(`Path: ${result.packagePath}`);
|
|
311
|
+
output.write('');
|
|
312
|
+
output.write('Exports:');
|
|
313
|
+
for (const entry of result.exports) {
|
|
314
|
+
output.write(`- ${entry.name}`);
|
|
315
|
+
output.write(` path: ${entry.skillFile}`);
|
|
316
|
+
}
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
283
320
|
output.write(`Skill: ${result.name}`);
|
|
284
321
|
if (result.description) output.write(`Description: ${result.description}`);
|
|
285
322
|
if (result.packageName) output.write(`Package: ${result.packageName}`);
|
|
@@ -287,6 +324,7 @@ export function skillsCommand() {
|
|
|
287
324
|
if (result.status) output.write(`Status: ${result.status}`);
|
|
288
325
|
if (result.replacement) output.write(`Replacement: ${result.replacement}`);
|
|
289
326
|
if (result.message) output.write(`Message: ${result.message}`);
|
|
327
|
+
if (result.wraps) output.write(`Wraps: ${result.wraps}`);
|
|
290
328
|
output.write(`Path: ${result.skillFile}`);
|
|
291
329
|
|
|
292
330
|
output.write('');
|
|
@@ -304,6 +342,12 @@ export function skillsCommand() {
|
|
|
304
342
|
} else {
|
|
305
343
|
for (const requirement of result.requires) output.write(`- ${requirement}`);
|
|
306
344
|
}
|
|
345
|
+
|
|
346
|
+
if (result.overrides?.length) {
|
|
347
|
+
output.write('');
|
|
348
|
+
output.write('Overrides:');
|
|
349
|
+
for (const override of result.overrides) output.write(`- ${override}`);
|
|
350
|
+
}
|
|
307
351
|
});
|
|
308
352
|
|
|
309
353
|
cmd
|
|
@@ -363,16 +407,26 @@ export function skillsCommand() {
|
|
|
363
407
|
const result = validateSkillsUseCase(target);
|
|
364
408
|
|
|
365
409
|
if (globalOpts.json) {
|
|
366
|
-
output.json(
|
|
367
|
-
target
|
|
368
|
-
? result.skills[0]
|
|
369
|
-
: result
|
|
370
|
-
);
|
|
410
|
+
output.json(target && result.count === 1 ? result.skills[0] : result);
|
|
371
411
|
if (!result.valid) process.exitCode = EXIT_CODES.VALIDATION;
|
|
372
412
|
return;
|
|
373
413
|
}
|
|
374
414
|
|
|
375
415
|
if (target) {
|
|
416
|
+
if (result.count > 1) {
|
|
417
|
+
output.write(`Validated Skills: ${result.count}`);
|
|
418
|
+
output.write(`Valid Skills: ${result.validCount}`);
|
|
419
|
+
output.write(`Invalid Skills: ${result.invalidCount}`);
|
|
420
|
+
for (const skill of result.skills) {
|
|
421
|
+
output.write('');
|
|
422
|
+
output.write(`- ${skill.name || skill.packageName || skill.packagePath}`);
|
|
423
|
+
output.write(` status: ${skill.valid ? 'valid' : 'invalid'}`);
|
|
424
|
+
output.write(` path: ${skill.skillFile}`);
|
|
425
|
+
}
|
|
426
|
+
if (!result.valid) process.exitCode = EXIT_CODES.VALIDATION;
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
|
|
376
430
|
const skill = result.skills[0];
|
|
377
431
|
output.write(`Skill: ${skill.packageName || skill.packagePath}`);
|
|
378
432
|
output.write(`Status: ${skill.valid ? 'valid' : 'invalid'}`);
|
|
@@ -459,6 +513,9 @@ export function skillsCommand() {
|
|
|
459
513
|
output.write(` direct: ${install.direct}`);
|
|
460
514
|
output.write(` version: ${install.packageVersion}`);
|
|
461
515
|
output.write(` source: ${install.sourcePackagePath}`);
|
|
516
|
+
if (install.skills?.length > 0) {
|
|
517
|
+
output.write(` skills: ${install.skills.map((skill) => skill.name).join(', ')}`);
|
|
518
|
+
}
|
|
462
519
|
for (const materialization of install.materializations) {
|
|
463
520
|
output.write(` materialized: ${materialization.target} (${materialization.mode})`);
|
|
464
521
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
function getScopedRegistry(config, scope) {
|
|
2
|
+
return config?.[`${scope}:registry`] || null;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function getRegistryHostKey(registry) {
|
|
6
|
+
if (!registry) return null;
|
|
7
|
+
try {
|
|
8
|
+
const url = new URL(registry);
|
|
9
|
+
return `//${url.host}/:_authToken`;
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getAuthToken(config, registry) {
|
|
16
|
+
const hostKey = getRegistryHostKey(registry);
|
|
17
|
+
return hostKey ? (config?.[hostKey] || null) : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function resolveRegistryConfig({
|
|
21
|
+
scope,
|
|
22
|
+
defaults = {},
|
|
23
|
+
userNpmrc = {},
|
|
24
|
+
repoNpmrc = {},
|
|
25
|
+
} = {}) {
|
|
26
|
+
const repoRegistry = getScopedRegistry(repoNpmrc, scope);
|
|
27
|
+
if (repoRegistry) {
|
|
28
|
+
return {
|
|
29
|
+
scope,
|
|
30
|
+
registry: repoRegistry,
|
|
31
|
+
authToken: getAuthToken(repoNpmrc, repoRegistry),
|
|
32
|
+
verificationPackage: defaults.verificationPackage || null,
|
|
33
|
+
source: 'repo',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const userRegistry = getScopedRegistry(userNpmrc, scope);
|
|
38
|
+
if (userRegistry) {
|
|
39
|
+
return {
|
|
40
|
+
scope,
|
|
41
|
+
registry: userRegistry,
|
|
42
|
+
authToken: getAuthToken(userNpmrc, userRegistry),
|
|
43
|
+
verificationPackage: defaults.verificationPackage || null,
|
|
44
|
+
source: 'user',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
scope,
|
|
50
|
+
registry: defaults.registry || null,
|
|
51
|
+
authToken: null,
|
|
52
|
+
verificationPackage: defaults.verificationPackage || null,
|
|
53
|
+
source: 'default',
|
|
54
|
+
};
|
|
55
|
+
}
|