devworkspace 0.3.0 → 0.3.1
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 +24 -0
- package/README.md +5 -4
- package/dist/agents/claude/adapter.d.ts +3 -14
- package/dist/agents/claude/adapter.js +46 -49
- package/dist/agents/claude/adapter.js.map +1 -1
- package/dist/agents/codex/adapter.d.ts +2 -0
- package/dist/agents/codex/adapter.js +61 -0
- package/dist/agents/codex/adapter.js.map +1 -0
- package/dist/agents/copilot/adapter.d.ts +2 -0
- package/dist/agents/copilot/adapter.js +62 -0
- package/dist/agents/copilot/adapter.js.map +1 -0
- package/dist/agents/cursor/adapter.d.ts +2 -0
- package/dist/agents/cursor/adapter.js +127 -0
- package/dist/agents/cursor/adapter.js.map +1 -0
- package/dist/agents/index.d.ts +15 -0
- package/dist/agents/index.js +54 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/shared.d.ts +20 -0
- package/dist/agents/shared.js +76 -0
- package/dist/agents/shared.js.map +1 -0
- package/dist/agents/types.d.ts +16 -1
- package/dist/agents/types.js.map +1 -1
- package/dist/cli/help.js +12 -5
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/render.d.ts +2 -1
- package/dist/cli/render.js +21 -0
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/run.js +17 -6
- package/dist/cli/run.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/adapters/claudePlugin.d.ts +12 -0
- package/dist/integrations/adapters/claudePlugin.js +37 -8
- package/dist/integrations/adapters/claudePlugin.js.map +1 -1
- package/dist/integrations/adapters/pluginSkill.js +5 -0
- package/dist/integrations/adapters/pluginSkill.js.map +1 -1
- package/dist/security/files.js +10 -2
- package/dist/security/files.js.map +1 -1
- package/dist/security/redact.js +1 -1
- package/dist/security/redact.js.map +1 -1
- package/dist/services/agent.d.ts +12 -2
- package/dist/services/agent.js +96 -14
- package/dist/services/agent.js.map +1 -1
- package/dist/services/analysis.js +3 -3
- package/dist/services/analysis.js.map +1 -1
- package/dist/services/doctor.js +31 -14
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/reset.js +45 -5
- package/dist/services/reset.js.map +1 -1
- package/dist/services/status.d.ts +2 -0
- package/dist/services/status.js +62 -10
- package/dist/services/status.js.map +1 -1
- package/dist/services/tasks.js +6 -1
- package/dist/services/tasks.js.map +1 -1
- package/dist/tasks/routing.js +14 -10
- package/dist/tasks/routing.js.map +1 -1
- package/dist/tasks/task.js +6 -2
- package/dist/tasks/task.js.map +1 -1
- package/dist/verification/scope.js +1 -1
- package/dist/verification/scope.js.map +1 -1
- package/docs/agents.md +60 -0
- package/docs/architecture.md +2 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { getTaskContext } from './services/taskContext.js';
|
|
|
9
9
|
export { getContext, addFact, verifyFactByKey, removeFactByKey } from './services/knowledge.js';
|
|
10
10
|
export { createTask, listTasksService, showTask, setTaskStatus, updateTask, recordVerification, recordTests, attestTask } from './services/tasks.js';
|
|
11
11
|
export { recordDecision, getDecisions, recordSession, getSessions } from './services/records.js';
|
|
12
|
-
export { installAgent } from './services/agent.js';
|
|
12
|
+
export { installAgent, listAgents, AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles } from './services/agent.js';
|
|
13
13
|
export { exportWorkspace, importWorkspace } from './services/portability.js';
|
|
14
14
|
export { migrateWorkspace } from './services/migrate.js';
|
|
15
15
|
export { resetWorkspace } from './services/reset.js';
|
|
@@ -26,4 +26,5 @@ export type { DoctorResult, DoctorCheck } from './services/doctor.js';
|
|
|
26
26
|
export type { Task, TaskStatus, TaskType } from './tasks/task.js';
|
|
27
27
|
export type { Fact, ProjectConfig, CommandEntry } from './config/schemas.js';
|
|
28
28
|
export type { IntegrationReport, StatusCode as IntegrationStatusCode } from './integrations/types.js';
|
|
29
|
-
export type { AgentAdapter, PlannedChange } from './agents/types.js';
|
|
29
|
+
export type { AgentAdapter, AgentCapabilities, PlannedChange } from './agents/types.js';
|
|
30
|
+
export type { AgentInfo, AgentInstallResult } from './services/agent.js';
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { getTaskContext } from './services/taskContext.js';
|
|
|
10
10
|
export { getContext, addFact, verifyFactByKey, removeFactByKey } from './services/knowledge.js';
|
|
11
11
|
export { createTask, listTasksService, showTask, setTaskStatus, updateTask, recordVerification, recordTests, attestTask } from './services/tasks.js';
|
|
12
12
|
export { recordDecision, getDecisions, recordSession, getSessions } from './services/records.js';
|
|
13
|
-
export { installAgent } from './services/agent.js';
|
|
13
|
+
export { installAgent, listAgents, AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles } from './services/agent.js';
|
|
14
14
|
export { exportWorkspace, importWorkspace } from './services/portability.js';
|
|
15
15
|
export { migrateWorkspace } from './services/migrate.js';
|
|
16
16
|
export { resetWorkspace } from './services/reset.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACrJ,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACrJ,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAChI,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["// Programmatic API: the same engine that powers the CLI, for a future VS Code extension, dashboards and automation.\nexport { packageVersion } from './core/version.js';\nexport { DevWorkspaceError, EXIT } from './errors/index.js';\nexport { initWorkspace } from './services/init.js';\nexport { analyzeWorkspace } from './services/analysis.js';\nexport { getStatus } from './services/status.js';\nexport { runDoctor } from './services/doctor.js';\nexport { refreshWorkspace } from './services/refresh.js';\nexport { getTaskContext } from './services/taskContext.js';\nexport { getContext, addFact, verifyFactByKey, removeFactByKey } from './services/knowledge.js';\nexport { createTask, listTasksService, showTask, setTaskStatus, updateTask, recordVerification, recordTests, attestTask } from './services/tasks.js';\nexport { recordDecision, getDecisions, recordSession, getSessions } from './services/records.js';\nexport { installAgent, listAgents, AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles } from './services/agent.js';\nexport { exportWorkspace, importWorkspace } from './services/portability.js';\nexport { migrateWorkspace } from './services/migrate.js';\nexport { resetWorkspace } from './services/reset.js';\nexport { setupIntegrations, integrationsStatus } from './services/integrations.js';\nexport { classifyRequest, detectConstraints, WORKFLOWS } from './tasks/routing.js';\nexport { evaluateGate } from './tasks/task.js';\nexport { redact, findSecrets, containsSecret } from './security/redact.js';\nexport { isSensitiveFile } from './security/files.js';\nexport { buildOnboardingPrompt } from './prompts/onboarding.js';\nexport { ONBOARDING_REQUIREMENTS, REFRESH_REQUIREMENTS, validatePrompt } from './prompts/requirements.js';\nexport type { ServiceOptions } from './services/common.js';\nexport type { StatusResult } from './services/status.js';\nexport type { DoctorResult, DoctorCheck } from './services/doctor.js';\nexport type { Task, TaskStatus, TaskType } from './tasks/task.js';\nexport type { Fact, ProjectConfig, CommandEntry } from './config/schemas.js';\nexport type { IntegrationReport, StatusCode as IntegrationStatusCode } from './integrations/types.js';\nexport type { AgentAdapter, AgentCapabilities, PlannedChange } from './agents/types.js';\nexport type { AgentInfo, AgentInstallResult } from './services/agent.js';\n"]}
|
|
@@ -18,6 +18,18 @@ export interface NativeSpec {
|
|
|
18
18
|
pluginName: string;
|
|
19
19
|
}
|
|
20
20
|
export declare const pluginId: (s: NativeSpec) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Parse `claude plugin list --json` output: a JSON array, single-line or pretty-printed. The whole output is parsed first;
|
|
23
|
+
* if a banner or warning precedes it, the text from the first line that starts the array is tried instead.
|
|
24
|
+
* Anything else is an error: "could not read" must never be mistaken for "no plugins installed".
|
|
25
|
+
*/
|
|
26
|
+
export declare function parsePluginList(stdout: string): {
|
|
27
|
+
ok: true;
|
|
28
|
+
plugins: InstalledPlugin[];
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
error: string;
|
|
32
|
+
};
|
|
21
33
|
export declare function listPlugins(ctx: AdapterContext, claude: Tool): Promise<{
|
|
22
34
|
ok: boolean;
|
|
23
35
|
plugins: InstalledPlugin[];
|
|
@@ -6,17 +6,44 @@ import { isInside } from '../../utils/paths.js';
|
|
|
6
6
|
export const MIN_PLUGIN_JSON = '2.1.268';
|
|
7
7
|
export const MIN_MARKETPLACE_JSON = '2.1.287';
|
|
8
8
|
export const pluginId = (s) => `${s.pluginName}@${s.marketplaceName}`;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Parse `claude plugin list --json` output: a JSON array, single-line or pretty-printed. The whole output is parsed first;
|
|
11
|
+
* if a banner or warning precedes it, the text from the first line that starts the array is tried instead.
|
|
12
|
+
* Anything else is an error: "could not read" must never be mistaken for "no plugins installed".
|
|
13
|
+
*/
|
|
14
|
+
export function parsePluginList(stdout) {
|
|
15
|
+
const text = stdout.replace(/^\uFEFF/, '').trim();
|
|
16
|
+
if (!text)
|
|
17
|
+
return { ok: false, error: '`claude plugin list --json` printed nothing' };
|
|
18
|
+
let parsed;
|
|
13
19
|
try {
|
|
14
|
-
|
|
15
|
-
return { ok: true, plugins: Array.isArray(parsed) ? parsed : [] };
|
|
20
|
+
parsed = JSON.parse(text);
|
|
16
21
|
}
|
|
17
22
|
catch {
|
|
18
|
-
|
|
23
|
+
const at = text.search(/^\[/m);
|
|
24
|
+
try {
|
|
25
|
+
if (at < 0)
|
|
26
|
+
throw new Error('no array');
|
|
27
|
+
parsed = JSON.parse(text.slice(at));
|
|
28
|
+
// Output that merely contains a stray "[]" after noise is not evidence that nothing is installed.
|
|
29
|
+
if (Array.isArray(parsed) && parsed.length === 0)
|
|
30
|
+
throw new Error('empty array found only after other output');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return { ok: false, error: 'could not parse `claude plugin list --json` output' };
|
|
34
|
+
}
|
|
19
35
|
}
|
|
36
|
+
const valid = (x) => typeof x === 'object' && x !== null && typeof x.id === 'string' && typeof x.scope === 'string' && typeof x.enabled === 'boolean';
|
|
37
|
+
if (!Array.isArray(parsed) || !parsed.every(valid))
|
|
38
|
+
return { ok: false, error: 'unexpected `claude plugin list --json` structure (expected an array of plugins with id, scope and enabled)' };
|
|
39
|
+
return { ok: true, plugins: parsed };
|
|
40
|
+
}
|
|
41
|
+
export async function listPlugins(ctx, claude) {
|
|
42
|
+
const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'list', '--json'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });
|
|
43
|
+
if (!r.ok)
|
|
44
|
+
return { ok: false, plugins: [], error: (r.stderr || r.error || r.stdout).trim().slice(0, 300) || `exit ${r.code}` };
|
|
45
|
+
const p = parsePluginList(r.stdout);
|
|
46
|
+
return p.ok ? { ok: true, plugins: p.plugins } : { ok: false, plugins: [], error: p.error };
|
|
20
47
|
}
|
|
21
48
|
export async function marketplaceRegistered(ctx, claude, name) {
|
|
22
49
|
const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'marketplace', 'list'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });
|
|
@@ -43,7 +70,9 @@ export function samePath(a, b) {
|
|
|
43
70
|
}
|
|
44
71
|
/** Match the plugin for this project: user-scope installs apply everywhere; project/local installs must belong to this root. */
|
|
45
72
|
export function findPlugin(plugins, id, root) {
|
|
46
|
-
|
|
73
|
+
// The same plugin can be listed at several scopes; an enabled applicable entry wins over a disabled one.
|
|
74
|
+
const mine = plugins.filter((p) => p.id === id && (p.scope === 'user' || p.scope === 'managed' || samePath(p.projectPath, root) || (p.projectPath && isInside(canonical(root), canonical(p.projectPath)))));
|
|
75
|
+
return mine.find((p) => p.enabled) ?? mine[0];
|
|
47
76
|
}
|
|
48
77
|
/** Cheap check of settings files (no process spawn): which plugins/marketplaces are declared. */
|
|
49
78
|
export async function readDeclared(ctx, spec) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claudePlugin.js","sourceRoot":"","sources":["../../../src/integrations/adapters/claudePlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { promises as fs, realpathSync } from 'node:fs';\nimport { compareVersions, parseLastJsonLine, type Tool } from '../exec.js';\nimport { isInside } from '../../utils/paths.js';\nimport type { AdapterContext, InstallScope, PlanStep, StepOutcome } from '../types.js';\n\n/** Minimum Claude Code versions for the flags we rely on (from the plugin CLI reference). */\nexport const MIN_PLUGIN_JSON = '2.1.268';\nexport const MIN_MARKETPLACE_JSON = '2.1.287';\n\nexport interface InstalledPlugin {\n id: string;\n version?: string;\n scope: string;\n enabled: boolean;\n projectPath?: string;\n errors?: string[];\n}\n\nexport interface NativeSpec {\n marketplaceName: string;\n /** Always an https git URL: `owner/repo` shorthand makes Claude Code try SSH, which fails without GitHub keys. */\n marketplaceUrl: string;\n pluginName: string;\n}\n\nexport const pluginId = (s: NativeSpec): string => `${s.pluginName}@${s.marketplaceName}`;\n\nexport async function listPlugins(ctx: AdapterContext, claude: Tool): Promise<{ ok: boolean; plugins: InstalledPlugin[]; error?: string }> {\n const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'list', '--json'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });\n if (!r.ok) return { ok: false, plugins: [], error: (r.stderr || r.error || r.stdout).trim().slice(0, 300) || `exit ${r.code}` };\n try {\n const parsed = JSON.parse(r.stdout.trim().split(/\\r?\\n/).filter((l) => l.trim().startsWith('[')).pop() ?? r.stdout) as unknown;\n return { ok: true, plugins: Array.isArray(parsed) ? (parsed as InstalledPlugin[]) : [] };\n } catch {\n return { ok: false, plugins: [], error: 'could not parse `claude plugin list --json` output' };\n }\n}\n\nexport async function marketplaceRegistered(ctx: AdapterContext, claude: Tool, name: string): Promise<boolean | null> {\n const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'marketplace', 'list'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });\n if (!r.ok) return null;\n return new RegExp(`(^|[^A-Za-z0-9._-])${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}($|[^A-Za-z0-9._-])`, 'm').test(r.stdout);\n}\n\n/** Resolve symlinks when the path exists (macOS temp dirs live under /var, a link to /private/var), else just normalise. */\nfunction canonical(p: string): string {\n try {\n return realpathSync(path.resolve(p));\n } catch {\n return path.resolve(p);\n }\n}\n\nexport function samePath(a: string | undefined, b: string): boolean {\n if (!a) return false;\n const norm = (p: string): string => canonical(p).replace(/[\\\\/]+$/, '');\n const x = norm(a);\n const y = norm(b);\n return process.platform === 'win32' ? x.toLowerCase() === y.toLowerCase() : x === y;\n}\n\n/** Match the plugin for this project: user-scope installs apply everywhere; project/local installs must belong to this root. */\nexport function findPlugin(plugins: InstalledPlugin[], id: string, root: string): InstalledPlugin | undefined {\n return plugins.find((p) => p.id === id && (p.scope === 'user' || p.scope === 'managed' || samePath(p.projectPath, root) || (p.projectPath && isInside(canonical(root), canonical(p.projectPath)))));\n}\n\n/** Cheap check of settings files (no process spawn): which plugins/marketplaces are declared. */\nexport async function readDeclared(ctx: AdapterContext, spec: NativeSpec): Promise<{ marketplace: boolean; enabled: InstallScope | null }> {\n const files: [string, InstallScope][] = [\n [path.join(ctx.root, '.claude', 'settings.json'), 'project'],\n [path.join(ctx.root, '.claude', 'settings.local.json'), 'project'],\n [path.join(ctx.home, '.claude', 'settings.json'), 'user'],\n ];\n let marketplace = false;\n let enabled: InstallScope | null = null;\n for (const [file, scope] of files) {\n try {\n const j = JSON.parse(await fs.readFile(file, 'utf8')) as { extraKnownMarketplaces?: Record<string, unknown>; enabledPlugins?: Record<string, unknown> };\n if (j.extraKnownMarketplaces && spec.marketplaceName in j.extraKnownMarketplaces) marketplace = true;\n if (j.enabledPlugins && j.enabledPlugins[pluginId(spec)] === true && enabled === null) enabled = scope;\n } catch {\n /* missing or unreadable */\n }\n }\n return { marketplace, enabled };\n}\n\nexport const SSH_FIX = 'git config --global url.\"https://github.com/\".insteadOf git@github.com:';\n\n/** Claude Code clones plugin sources over SSH by default; without a GitHub SSH key that fails with these messages. */\nexport function sshHint(text: string): string | undefined {\n return /host key verification failed|permission denied \\(publickey\\)|could not read from remote repository/i.test(text)\n ? `Claude Code cloned over SSH and you have no usable GitHub SSH key. The fix documented by Agent Skills changes your global Git config, so run it yourself, then re-run setup: ${SSH_FIX}`\n : undefined;\n}\n\nfunction describeFailure(json: Record<string, unknown> | null, stderr: string, stdout: string): string {\n const msg = typeof json?.message === 'string' ? json.message : (stderr || stdout).trim().split(/\\r?\\n/).filter(Boolean).slice(-2).join(' ');\n return msg.slice(0, 400) || 'the command failed without output';\n}\n\n/** Steps that register the marketplace (if needed) and install the plugin at the given scope. */\nexport function nativeSteps(ctx: AdapterContext, claude: Tool, spec: NativeSpec, scope: InstallScope, opts: { registered: boolean }): PlanStep[] {\n const steps: PlanStep[] = [];\n const level = scope === 'user' ? 'user-config' : 'project';\n const useMpJson = compareVersions(claude.version, MIN_MARKETPLACE_JSON) >= 0;\n const useJson = compareVersions(claude.version, MIN_PLUGIN_JSON) >= 0;\n const exe = path.basename(claude.command, path.extname(claude.command));\n\n if (!opts.registered) {\n const args = ['plugin', 'marketplace', 'add', spec.marketplaceUrl, '--scope', scope, ...(useMpJson ? ['--json'] : [])];\n steps.push({\n id: `${spec.marketplaceName}:marketplace`,\n description: `Register the ${spec.marketplaceName} marketplace (${scope} scope)`,\n command: `${exe} ${args.join(' ')}`,\n level,\n async run(): Promise<StepOutcome> {\n const r = await ctx.runner.run({ command: claude.command, args, cwd: ctx.root, timeoutMs: 180_000, signal: ctx.signal });\n const json = parseLastJsonLine(r.stdout);\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 180 s (network?)' };\n if (r.ok && json?.outcome !== 'failed') return { ok: true, detail: typeof json?.message === 'string' ? json.message : 'registered' };\n if (/already (on disk|added|exists)/i.test(r.stdout + r.stderr)) return { ok: true, detail: 'already registered' };\n return { ok: false, detail: describeFailure(json, r.stderr, r.stdout), hint: sshHint(`${r.stdout}\\n${r.stderr}`) };\n },\n });\n }\n\n const installArgs = ['plugin', 'install', pluginId(spec), '--scope', scope, ...(useJson ? ['--json'] : [])];\n steps.push({\n id: `${pluginId(spec)}:install`,\n description: `Install the ${spec.pluginName} plugin (${scope} scope)`,\n command: `${exe} ${installArgs.join(' ')}`,\n level,\n async run(): Promise<StepOutcome> {\n // Never pass -y: that would accept a marketplace-declared command without the user seeing it.\n const r = await ctx.runner.run({ command: claude.command, args: installArgs, cwd: ctx.root, timeoutMs: 180_000, signal: ctx.signal });\n const json = parseLastJsonLine(r.stdout);\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 180 s (network?)' };\n const text = `${r.stdout}\\n${r.stderr}`;\n if (json && (json.shownCommand || json.failureCode === 'command_not_accepted') || /only displayed|Run this command now/i.test(text)) {\n return { ok: false, requiresApproval: true, detail: 'Claude Code needs you to approve a command shown by the marketplace; run the command above yourself in a terminal.' };\n }\n if (/already installed/i.test(text) && r.ok) return { ok: true, detail: 'already installed' };\n if (r.ok && json?.outcome !== 'failed') return { ok: true, detail: 'installed', restartRequired: true };\n return { ok: false, detail: describeFailure(json, r.stderr, r.stdout), hint: sshHint(`${r.stdout}\\n${r.stderr}`) };\n },\n });\n return steps;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"claudePlugin.js","sourceRoot":"","sources":["../../../src/integrations/adapters/claudePlugin.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { promises as fs, realpathSync } from 'node:fs';\nimport { compareVersions, parseLastJsonLine, type Tool } from '../exec.js';\nimport { isInside } from '../../utils/paths.js';\nimport type { AdapterContext, InstallScope, PlanStep, StepOutcome } from '../types.js';\n\n/** Minimum Claude Code versions for the flags we rely on (from the plugin CLI reference). */\nexport const MIN_PLUGIN_JSON = '2.1.268';\nexport const MIN_MARKETPLACE_JSON = '2.1.287';\n\nexport interface InstalledPlugin {\n id: string;\n version?: string;\n scope: string;\n enabled: boolean;\n projectPath?: string;\n errors?: string[];\n}\n\nexport interface NativeSpec {\n marketplaceName: string;\n /** Always an https git URL: `owner/repo` shorthand makes Claude Code try SSH, which fails without GitHub keys. */\n marketplaceUrl: string;\n pluginName: string;\n}\n\nexport const pluginId = (s: NativeSpec): string => `${s.pluginName}@${s.marketplaceName}`;\n\n/**\n * Parse `claude plugin list --json` output: a JSON array, single-line or pretty-printed. The whole output is parsed first;\n * if a banner or warning precedes it, the text from the first line that starts the array is tried instead.\n * Anything else is an error: \"could not read\" must never be mistaken for \"no plugins installed\".\n */\nexport function parsePluginList(stdout: string): { ok: true; plugins: InstalledPlugin[] } | { ok: false; error: string } {\n const text = stdout.replace(/^\\uFEFF/, '').trim();\n if (!text) return { ok: false, error: '`claude plugin list --json` printed nothing' };\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n const at = text.search(/^\\[/m);\n try {\n if (at < 0) throw new Error('no array');\n parsed = JSON.parse(text.slice(at));\n // Output that merely contains a stray \"[]\" after noise is not evidence that nothing is installed.\n if (Array.isArray(parsed) && parsed.length === 0) throw new Error('empty array found only after other output');\n } catch {\n return { ok: false, error: 'could not parse `claude plugin list --json` output' };\n }\n }\n const valid = (x: unknown): x is InstalledPlugin => typeof x === 'object' && x !== null && typeof (x as InstalledPlugin).id === 'string' && typeof (x as InstalledPlugin).scope === 'string' && typeof (x as InstalledPlugin).enabled === 'boolean';\n if (!Array.isArray(parsed) || !parsed.every(valid)) return { ok: false, error: 'unexpected `claude plugin list --json` structure (expected an array of plugins with id, scope and enabled)' };\n return { ok: true, plugins: parsed };\n}\n\nexport async function listPlugins(ctx: AdapterContext, claude: Tool): Promise<{ ok: boolean; plugins: InstalledPlugin[]; error?: string }> {\n const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'list', '--json'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });\n if (!r.ok) return { ok: false, plugins: [], error: (r.stderr || r.error || r.stdout).trim().slice(0, 300) || `exit ${r.code}` };\n const p = parsePluginList(r.stdout);\n return p.ok ? { ok: true, plugins: p.plugins } : { ok: false, plugins: [], error: p.error };\n}\n\nexport async function marketplaceRegistered(ctx: AdapterContext, claude: Tool, name: string): Promise<boolean | null> {\n const r = await ctx.runner.run({ command: claude.command, args: ['plugin', 'marketplace', 'list'], cwd: ctx.root, timeoutMs: 30_000, signal: ctx.signal });\n if (!r.ok) return null;\n return new RegExp(`(^|[^A-Za-z0-9._-])${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}($|[^A-Za-z0-9._-])`, 'm').test(r.stdout);\n}\n\n/** Resolve symlinks when the path exists (macOS temp dirs live under /var, a link to /private/var), else just normalise. */\nfunction canonical(p: string): string {\n try {\n return realpathSync(path.resolve(p));\n } catch {\n return path.resolve(p);\n }\n}\n\nexport function samePath(a: string | undefined, b: string): boolean {\n if (!a) return false;\n const norm = (p: string): string => canonical(p).replace(/[\\\\/]+$/, '');\n const x = norm(a);\n const y = norm(b);\n return process.platform === 'win32' ? x.toLowerCase() === y.toLowerCase() : x === y;\n}\n\n/** Match the plugin for this project: user-scope installs apply everywhere; project/local installs must belong to this root. */\nexport function findPlugin(plugins: InstalledPlugin[], id: string, root: string): InstalledPlugin | undefined {\n // The same plugin can be listed at several scopes; an enabled applicable entry wins over a disabled one.\n const mine = plugins.filter((p) => p.id === id && (p.scope === 'user' || p.scope === 'managed' || samePath(p.projectPath, root) || (p.projectPath && isInside(canonical(root), canonical(p.projectPath)))));\n return mine.find((p) => p.enabled) ?? mine[0];\n}\n\n/** Cheap check of settings files (no process spawn): which plugins/marketplaces are declared. */\nexport async function readDeclared(ctx: AdapterContext, spec: NativeSpec): Promise<{ marketplace: boolean; enabled: InstallScope | null }> {\n const files: [string, InstallScope][] = [\n [path.join(ctx.root, '.claude', 'settings.json'), 'project'],\n [path.join(ctx.root, '.claude', 'settings.local.json'), 'project'],\n [path.join(ctx.home, '.claude', 'settings.json'), 'user'],\n ];\n let marketplace = false;\n let enabled: InstallScope | null = null;\n for (const [file, scope] of files) {\n try {\n const j = JSON.parse(await fs.readFile(file, 'utf8')) as { extraKnownMarketplaces?: Record<string, unknown>; enabledPlugins?: Record<string, unknown> };\n if (j.extraKnownMarketplaces && spec.marketplaceName in j.extraKnownMarketplaces) marketplace = true;\n if (j.enabledPlugins && j.enabledPlugins[pluginId(spec)] === true && enabled === null) enabled = scope;\n } catch {\n /* missing or unreadable */\n }\n }\n return { marketplace, enabled };\n}\n\nexport const SSH_FIX = 'git config --global url.\"https://github.com/\".insteadOf git@github.com:';\n\n/** Claude Code clones plugin sources over SSH by default; without a GitHub SSH key that fails with these messages. */\nexport function sshHint(text: string): string | undefined {\n return /host key verification failed|permission denied \\(publickey\\)|could not read from remote repository/i.test(text)\n ? `Claude Code cloned over SSH and you have no usable GitHub SSH key. The fix documented by Agent Skills changes your global Git config, so run it yourself, then re-run setup: ${SSH_FIX}`\n : undefined;\n}\n\nfunction describeFailure(json: Record<string, unknown> | null, stderr: string, stdout: string): string {\n const msg = typeof json?.message === 'string' ? json.message : (stderr || stdout).trim().split(/\\r?\\n/).filter(Boolean).slice(-2).join(' ');\n return msg.slice(0, 400) || 'the command failed without output';\n}\n\n/** Steps that register the marketplace (if needed) and install the plugin at the given scope. */\nexport function nativeSteps(ctx: AdapterContext, claude: Tool, spec: NativeSpec, scope: InstallScope, opts: { registered: boolean }): PlanStep[] {\n const steps: PlanStep[] = [];\n const level = scope === 'user' ? 'user-config' : 'project';\n const useMpJson = compareVersions(claude.version, MIN_MARKETPLACE_JSON) >= 0;\n const useJson = compareVersions(claude.version, MIN_PLUGIN_JSON) >= 0;\n const exe = path.basename(claude.command, path.extname(claude.command));\n\n if (!opts.registered) {\n const args = ['plugin', 'marketplace', 'add', spec.marketplaceUrl, '--scope', scope, ...(useMpJson ? ['--json'] : [])];\n steps.push({\n id: `${spec.marketplaceName}:marketplace`,\n description: `Register the ${spec.marketplaceName} marketplace (${scope} scope)`,\n command: `${exe} ${args.join(' ')}`,\n level,\n async run(): Promise<StepOutcome> {\n const r = await ctx.runner.run({ command: claude.command, args, cwd: ctx.root, timeoutMs: 180_000, signal: ctx.signal });\n const json = parseLastJsonLine(r.stdout);\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 180 s (network?)' };\n if (r.ok && json?.outcome !== 'failed') return { ok: true, detail: typeof json?.message === 'string' ? json.message : 'registered' };\n if (/already (on disk|added|exists)/i.test(r.stdout + r.stderr)) return { ok: true, detail: 'already registered' };\n return { ok: false, detail: describeFailure(json, r.stderr, r.stdout), hint: sshHint(`${r.stdout}\\n${r.stderr}`) };\n },\n });\n }\n\n const installArgs = ['plugin', 'install', pluginId(spec), '--scope', scope, ...(useJson ? ['--json'] : [])];\n steps.push({\n id: `${pluginId(spec)}:install`,\n description: `Install the ${spec.pluginName} plugin (${scope} scope)`,\n command: `${exe} ${installArgs.join(' ')}`,\n level,\n async run(): Promise<StepOutcome> {\n // Never pass -y: that would accept a marketplace-declared command without the user seeing it.\n const r = await ctx.runner.run({ command: claude.command, args: installArgs, cwd: ctx.root, timeoutMs: 180_000, signal: ctx.signal });\n const json = parseLastJsonLine(r.stdout);\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 180 s (network?)' };\n const text = `${r.stdout}\\n${r.stderr}`;\n if (json && (json.shownCommand || json.failureCode === 'command_not_accepted') || /only displayed|Run this command now/i.test(text)) {\n return { ok: false, requiresApproval: true, detail: 'Claude Code needs you to approve a command shown by the marketplace; run the command above yourself in a terminal.' };\n }\n if (/already installed/i.test(text) && r.ok) return { ok: true, detail: 'already installed' };\n if (r.ok && json?.outcome !== 'failed') return { ok: true, detail: 'installed', restartRequired: true };\n return { ok: false, detail: describeFailure(json, r.stderr, r.stdout), hint: sshHint(`${r.stdout}\\n${r.stderr}`) };\n },\n });\n return steps;\n}\n"]}
|
|
@@ -131,6 +131,11 @@ export function createPluginSkillAdapter(cfg) {
|
|
|
131
131
|
return { steps, blockers, protectPaths, notes: ['already verified'] };
|
|
132
132
|
if (o.nativeInstalled && !o.nativeError)
|
|
133
133
|
return { steps, blockers, protectPaths, notes: ['native plugin already installed'] };
|
|
134
|
+
// If the plugin list cannot be read we do not know what is installed: installing anything now could duplicate or overwrite it.
|
|
135
|
+
if (o.claude && compareVersions(o.claude.version, MIN_PLUGIN_JSON) >= 0 && o.listError) {
|
|
136
|
+
blockers.push(`Could not read the installed plugin list (${o.listError}), so nothing was installed. Run "claude plugin list --json" yourself to see what is installed, then re-run setup.`);
|
|
137
|
+
return { steps, blockers, protectPaths, notes };
|
|
138
|
+
}
|
|
134
139
|
if (o.claude && compareVersions(o.claude.version, MIN_PLUGIN_JSON) >= 0 && !o.listError) {
|
|
135
140
|
// marketplace registered but plugin missing -> only the install step
|
|
136
141
|
steps.push(...nativeSteps(ctx, o.claude, cfg.native, scope, { registered: o.registered }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pluginSkill.js","sourceRoot":"","sources":["../../../src/integrations/adapters/pluginSkill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,aAAa,EAAa,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,qBAAqB,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAmB,MAAM,mBAAmB,CAAC;AAC1J,OAAO,EAAE,qBAAqB,EAAqB,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAuB/C,MAAM,UAAU,GAAG,QAAQ,CAAC;AAE5B,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7I,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,CAAS;IACjC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,GAAsB;IAC7D,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEhC,KAAK,UAAU,OAAO,CAAC,GAAmB,EAAE,IAAa;QAYvD,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,MAAM,GAAgB,IAAI,CAAC;QAC/B,IAAI,eAAe,GAAG,QAAQ,CAAC,OAAO,KAAK,IAAI,CAAC;QAChD,IAAI,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC;QACnC,IAAI,WAAW,GAAkB,IAAI,CAAC;QACtC,IAAI,UAAU,GAAG,QAAQ,CAAC,WAAW,CAAC;QACtC,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YAC/D,IAAI,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpE,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBACzC,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;oBACT,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;oBAC9C,eAAe,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;oBACnC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACnE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC;oBAC7B,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;wBAAE,WAAW,GAAG,CAAC,CAAC,MAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBACvF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;wBAAE,WAAW,GAAG,sCAAsC,CAAC;oBAC1E,IAAI,CAAC,CAAC,EAAE,CAAC;wBACP,MAAM,GAAG,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;wBACjF,UAAU,GAAG,GAAG,IAAI,UAAU,CAAC;oBACjC,CAAC;;wBAAM,UAAU,GAAG,IAAI,CAAC;gBAC3B,CAAC;;oBAAM,SAAS,GAAG,CAAC,CAAC,KAAK,IAAI,wBAAwB,CAAC;YACzD,CAAC;QACH,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC/E,MAAM,aAAa,GAAG,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACnH,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,IAAI,GAAG,CAAC,aAAa,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,GAAG,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;YAC5D,IAAI,GAAG,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QACpN,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;IACrI,CAAC;IAED,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,OAAO,EAAE,GAAG,CAAC,OAAO;QAEpB,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI;YACrB,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,MAAM,GAAY,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,MAAM,IAAI,GAA4B,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACvF,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAW,CAAC;YAC3E,IAAI,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,uCAAuC,EAAE,CAAC,CAAC;YACxJ,IAAI,CAAC,CAAC,SAAS;gBAAE,QAAQ,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAEjF,IAAI,CAAC,CAAC,eAAe,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,WAAW,IAAI,GAAG,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;gBAChJ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;gBAC/B,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;oBAClB,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;oBAC9D,SAAS,CAAC,IAAI,CAAC,qEAAqE,EAAE,EAAE,CAAC,CAAC;gBAC5F,CAAC;gBACD,MAAM,KAAK,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;gBACvH,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACjC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;gBAChD,QAAQ,GAAG,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;gBACtC,IAAI,CAAC,IAAI;oBAAE,QAAQ,CAAC,IAAI,CAAC,iHAAiH,CAAC,CAAC;gBAC5I,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;YAC3M,CAAC;YAED,IAAI,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,MAAM,QAAQ,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC;gBACpE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,uBAAuB,CAAC,CAAC,aAAa,SAAS,EAAE,CAAC,CAAC;gBACpK,IAAI,GAAG,CAAC,aAAa;oBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,aAAa,iBAAiB,EAAE,CAAC,CAAC;gBACvJ,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC7E,QAAQ,CAAC,IAAI,CAAC,wCAAwC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC7E,SAAS,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;gBAC3D,CAAC;gBACD,IAAI,CAAC,CAAC,CAAC,IAAI;oBAAE,QAAQ,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,aAAa,2HAA2H,CAAC,CAAC;gBACvL,QAAQ,CAAC,IAAI,CAAC,yBAAyB,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;gBAC9G,SAAS,CAAC,IAAI,CAAC,sDAAsD,GAAG,CAAC,MAAM,CAAC,cAAc,gDAAgD,EAAE,kBAAkB,CAAC,CAAC;gBACpK,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;YAC7J,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,eAAe,gDAAgD,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;YAChL,SAAS,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YAC1D,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;QAC1I,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM;YACpB,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAG,CAAC,uBAAuB,EAAE,6BAA6B,EAAE,WAAW,EAAE,mBAAmB,EAAE,WAAW,CAAC,CAAC;YAC7H,MAAM,KAAK,GAAe,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;YAE9B,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;gBAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC7H,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,WAAW;gBAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,iCAAiC,CAAC,EAAE,CAAC;YAE9H,IAAI,CAAC,CAAC,MAAM,IAAI,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;gBACxF,qEAAqE;gBACrE,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC3F,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;oBACnC,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,WAAW,kCAAkC,CAAC,CAAC;gBACtG,CAAC;gBACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;YAClD,CAAC;YACD,IAAI,CAAC,CAAC,MAAM;gBAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,eAAe,0EAA0E,CAAC,CAAC;;gBAChK,KAAK,CAAC,IAAI,CAAC,4HAA4H,CAAC,CAAC;YAC9I,IAAI,CAAC,CAAC,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,SAAS,2BAA2B,CAAC,CAAC;YAEtG,0DAA0D;YAC1D,IAAI,CAAC,CAAC,eAAe,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI;gBAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,mCAAmC,CAAC,EAAE,CAAC;YACnK,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;YACvD,MAAM,OAAO,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;YACvD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5G,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;gBAC7E,QAAQ,CAAC,IAAI,CACX,mBAAmB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iMAAiM,CACzO,CAAC;gBACF,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;YAClD,CAAC;YACD,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACnK,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,aAAa;gBAC1B,WAAW,EAAE,WAAW,GAAG,CAAC,IAAI,gBAAgB,GAAG,CAAC,UAAU,yBAAyB,KAAK,2CAA2C;gBACvI,OAAO,EAAE,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;gBAChC,KAAK,EAAE,kBAAkB;gBACzB,KAAK,CAAC,GAAG;oBACP,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;oBACjD,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;oBACvJ,IAAI,CAAC,CAAC,OAAO;wBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;oBACzD,IAAI,CAAC,CAAC,QAAQ;wBAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;oBACjF,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;wBACV,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBAChH,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;oBACpF,CAAC;oBACD,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpD,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,wBAAwB,EAAE,CAAC,CAAC;oBAC3H,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,wBAAwB,EAAE,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC;gBAClI,CAAC;aACF,CAAC,CAAC;YACH,KAAK,CAAC,IAAI,CAAC;gBACT,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,SAAS;gBACtB,WAAW,EAAE,gFAAgF;gBAC7F,KAAK,EAAE,SAAS;gBAChB,KAAK,CAAC,GAAG;oBACP,MAAM,qBAAqB,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;oBAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;gBACtB,CAAC;aACF,CAAC,CAAC;YACH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAClD,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { compareVersions, findClaudeCli, type Tool } from '../exec.js';\nimport { findPlugin, listPlugins, marketplaceRegistered, MIN_PLUGIN_JSON, nativeSteps, pluginId, readDeclared, type NativeSpec } from './claudePlugin.js';\nimport { writeThirdPartyNotice, type NoticeSource } from '../notices.js';\nimport type { AdapterContext, Check, IntegrationAdapter, IntegrationId, IntegrationReport, PlanResult, PlanStep, StepOutcome } from '../types.js';\nimport { pathExists } from '../../utils/fs.js';\n\nexport interface PluginSkillConfig {\n id: IntegrationId;\n name: string;\n usage: string;\n docsUrl: string;\n native: NativeSpec;\n /** `owner/repo` for the portable `npx skills add` path. */\n skillsRepo: string;\n /** Skill directories whose presence means the portable skills are installed. */\n coreSkills: string[];\n notice: NoticeSource;\n /** Capabilities the native plugin provides that portable skills cannot. */\n nativeOnly: string[];\n /** True only when the plugin's own manifest registers lifecycle hooks (verified from its plugin.json). */\n nativeHooks: boolean;\n /** Extra check for the native plugin (e.g. hooks need node). */\n extraNativeChecks?(ctx: AdapterContext): Promise<{ checks: Check[]; warnings: string[]; degraded: boolean }>;\n /** Shared supplementary directory expected beside skills (agent-skills ships references/). */\n referencesDir?: string;\n}\n\nconst SKILLS_CLI = 'skills';\n\nasync function skillDirs(base: string): Promise<string[]> {\n try {\n return (await fs.readdir(path.join(base, '.claude', 'skills'), { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n return pathExists(p);\n}\n\nexport function createPluginSkillAdapter(cfg: PluginSkillConfig): IntegrationAdapter {\n const id = pluginId(cfg.native);\n\n async function observe(ctx: AdapterContext, deep: boolean): Promise<{\n claude: Tool | null;\n nativeInstalled: boolean;\n nativeScope: 'project' | 'user' | null;\n nativeError: string | null;\n registered: boolean;\n version: string | null;\n listError: string | null;\n portablePresent: string[];\n portableScope: 'project' | 'user' | null;\n refs: boolean;\n }> {\n const declared = await readDeclared(ctx, cfg.native);\n let claude: Tool | null = null;\n let nativeInstalled = declared.enabled !== null;\n let nativeScope = declared.enabled;\n let nativeError: string | null = null;\n let registered = declared.marketplace;\n let version: string | null = null;\n let listError: string | null = null;\n if (deep) {\n claude = await findClaudeCli(ctx.runner, ctx.home, ctx.signal);\n if (claude && compareVersions(claude.version, MIN_PLUGIN_JSON) >= 0) {\n const l = await listPlugins(ctx, claude);\n if (l.ok) {\n const p = findPlugin(l.plugins, id, ctx.root);\n nativeInstalled = !!p && p.enabled;\n nativeScope = p ? (p.scope === 'user' ? 'user' : 'project') : null;\n version = p?.version ?? null;\n if (p && (p.errors?.length ?? 0) > 0) nativeError = p.errors!.join('; ').slice(0, 300);\n if (p && !p.enabled) nativeError = 'the plugin is installed but disabled';\n if (!p) {\n const reg = await marketplaceRegistered(ctx, claude, cfg.native.marketplaceName);\n registered = reg ?? registered;\n } else registered = true;\n } else listError = l.error ?? 'could not list plugins';\n }\n }\n const projectSkills = await skillDirs(ctx.root);\n const userSkills = await skillDirs(ctx.home);\n const inProject = cfg.coreSkills.filter((s) => projectSkills.includes(s));\n const inUser = cfg.coreSkills.filter((s) => userSkills.includes(s));\n const portablePresent = inProject.length >= inUser.length ? inProject : inUser;\n const portableScope = portablePresent.length === 0 ? null : inProject.length >= inUser.length ? 'project' : 'user';\n let refs = true;\n if (cfg.referencesDir && portablePresent.length > 0) {\n const base = portableScope === 'user' ? ctx.home : ctx.root;\n refs = (await fileExists(path.join(base, '.claude', 'skills', cfg.referencesDir))) || (await fileExists(path.join(base, '.claude', cfg.referencesDir))) || (await fileExists(path.join(base, cfg.referencesDir)));\n }\n return { claude, nativeInstalled, nativeScope, nativeError, registered, version, listError, portablePresent, portableScope, refs };\n }\n\n return {\n id: cfg.id,\n name: cfg.name,\n required: true,\n usage: cfg.usage,\n docsUrl: cfg.docsUrl,\n\n async inspect(ctx, deep): Promise<IntegrationReport> {\n const o = await observe(ctx, deep);\n const checks: Check[] = [];\n const warnings: string[] = [];\n const nextSteps: string[] = [];\n const caps: Record<string, boolean> = { skills: false, commands: false, hooks: false };\n const base = { id: cfg.id, name: cfg.name, required: true, deep } as const;\n if (deep) checks.push({ name: 'Claude Code CLI', ok: !!o.claude, detail: o.claude ? `v${o.claude.version}` : 'not found (PATH or VS Code extension)' });\n if (o.listError) warnings.push(`Could not read the plugin list: ${o.listError}`);\n\n if (o.nativeInstalled) {\n checks.push({ name: 'native plugin', ok: !o.nativeError, detail: o.nativeError ?? `${id}${o.nativeScope ? ` (${o.nativeScope} scope)` : ''}` });\n caps.skills = true;\n caps.commands = true;\n let degraded = !!o.nativeError;\n if (o.nativeError) {\n warnings.push(`${cfg.name} plugin problem: ${o.nativeError}`);\n nextSteps.push(`claude plugin list (inspect errors), then: claude plugin enable ${id}`);\n }\n const extra = cfg.extraNativeChecks ? await cfg.extraNativeChecks(ctx) : { checks: [], warnings: [], degraded: false };\n checks.push(...extra.checks);\n warnings.push(...extra.warnings);\n caps.hooks = cfg.nativeHooks && !extra.degraded;\n degraded = degraded || extra.degraded;\n if (!deep) warnings.push('Not yet verified against `claude plugin list`; run `devworkspace doctor` or `devworkspace integrations status`.');\n return { ...base, status: degraded ? 'DEGRADED' : deep ? 'VERIFIED' : 'INSTALLED', variant: 'native plugin', scope: o.nativeScope, version: o.version, checks, capabilities: caps, warnings, nextSteps };\n }\n\n if (o.portablePresent.length > 0) {\n const complete = o.portablePresent.length === cfg.coreSkills.length;\n caps.skills = complete;\n checks.push({ name: 'portable skills', ok: complete, detail: `${o.portablePresent.length}/${cfg.coreSkills.length} core skills found (${o.portableScope} scope)` });\n if (cfg.referencesDir) checks.push({ name: 'supplementary references', ok: o.refs, detail: o.refs ? 'found' : `${cfg.referencesDir}/ not installed` });\n if (!complete) {\n const missing = cfg.coreSkills.filter((s) => !o.portablePresent.includes(s));\n warnings.push(`Partial installation: missing skills ${missing.join(', ')}.`);\n nextSteps.push('devworkspace integrations repair --yes');\n }\n if (!o.refs) warnings.push(`The shared ${cfg.referencesDir}/ checklists are not installed (known limitation of the skills CLI), so skills that point to them have broken references.`);\n warnings.push(`Portable skills only: ${cfg.nativeOnly.join(', ')} from the native plugin are not available.`);\n nextSteps.push(`For the full plugin: claude plugin marketplace add ${cfg.native.marketplaceUrl} --scope project, then claude plugin install ${id} --scope project`);\n return { ...base, status: 'DEGRADED', variant: 'portable skills', scope: o.portableScope, version: null, checks, capabilities: caps, warnings, nextSteps };\n }\n\n checks.push({ name: 'marketplace', ok: o.registered, detail: o.registered ? `${cfg.native.marketplaceName} is registered but the plugin is not installed` : 'not registered' });\n nextSteps.push('devworkspace setup --integrations --yes');\n return { ...base, status: 'NOT_INSTALLED', variant: null, scope: null, version: null, checks, capabilities: caps, warnings, nextSteps };\n },\n\n async plan(ctx, report): Promise<PlanResult> {\n const o = await observe(ctx, true);\n const blockers: string[] = [];\n const notes: string[] = [];\n const protectPaths = ['.claude/settings.json', '.claude/settings.local.json', 'CLAUDE.md', '.claude/CLAUDE.md', 'AGENTS.md'];\n const steps: PlanStep[] = [];\n const scope = ctx.setup.scope;\n\n if (report.status === 'VERIFIED' && !ctx.setup.repair) return { steps, blockers, protectPaths, notes: ['already verified'] };\n if (o.nativeInstalled && !o.nativeError) return { steps, blockers, protectPaths, notes: ['native plugin already installed'] };\n\n if (o.claude && compareVersions(o.claude.version, MIN_PLUGIN_JSON) >= 0 && !o.listError) {\n // marketplace registered but plugin missing -> only the install step\n steps.push(...nativeSteps(ctx, o.claude, cfg.native, scope, { registered: o.registered }));\n if (o.nativeError && o.nativeScope) {\n notes.push(`The plugin is present but unhealthy (${o.nativeError}); re-running install to repair.`);\n }\n return { steps, blockers, protectPaths, notes };\n }\n if (o.claude) notes.push(`Claude Code ${o.claude.version} is older than ${MIN_PLUGIN_JSON}, which the plugin commands' --json output needs; using portable skills.`);\n else notes.push('The Claude Code CLI was not found on PATH or in the VS Code extension; using portable skills instead of the native plugin.');\n if (o.listError) notes.push(`\\`claude plugin list\\` failed (${o.listError}); using portable skills.`);\n\n // ---- portable skills via the documented Skills CLI ----\n if (o.portablePresent.length === cfg.coreSkills.length && o.refs) return { steps, blockers, protectPaths, notes: [...notes, 'portable skills already installed'] };\n const managed = new Set(ctx.prior?.managedPaths ?? []);\n const baseDir = scope === 'user' ? ctx.home : ctx.root;\n const existing = await skillDirs(baseDir);\n const conflicts = cfg.coreSkills.filter((s) => existing.includes(s) && !managed.has(`.claude/skills/${s}`));\n if (conflicts.length > 0 && o.portablePresent.length < cfg.coreSkills.length) {\n blockers.push(\n `Skill folder(s) ${conflicts.join(', ')} already exist in .claude/skills and were not installed by DevWorkspace, so they are treated as yours and will not be overwritten. Rename or remove them, or install the native plugin instead.`,\n );\n return { steps, blockers, protectPaths, notes };\n }\n const args = ['--yes', SKILLS_CLI, 'add', cfg.skillsRepo, '--agent', 'claude-code', '--skill', '*', '--copy', '-y', '--json', ...(scope === 'user' ? ['-g'] : [])];\n steps.push({\n id: `${cfg.id}:skills-cli`,\n description: `Install ${cfg.name} skills from ${cfg.skillsRepo} with the Skills CLI (${scope} scope, copied files, telemetry disabled)`,\n command: `npx ${args.join(' ')}`,\n level: 'third-party-code',\n async run(): Promise<StepOutcome> {\n const before = new Set(await skillDirs(baseDir));\n const r = await ctx.runner.runNpx(args, { cwd: ctx.root, timeoutMs: 300_000, signal: ctx.signal, env: { DISABLE_TELEMETRY: '1', DO_NOT_TRACK: '1' } });\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 300 s (network?)' };\n if (!r.ok) {\n const tail = `${r.stderr}\\n${r.stdout}`.split(/\\r?\\n/).map((l) => l.trim()).filter(Boolean).slice(-3).join(' ');\n return { ok: false, detail: (tail || r.error || `exit ${r.code}`).slice(0, 400) };\n }\n const after = await skillDirs(baseDir);\n const created = after.filter((s) => !before.has(s));\n ctx.report({ id: cfg.id, step: `${cfg.id}:skills-cli`, state: 'info', detail: `${created.length} skill folder(s) added` });\n return { ok: true, detail: `${created.length} skill folder(s) added`, managedPaths: created.map((s) => `.claude/skills/${s}`) };\n },\n });\n steps.push({\n id: `${cfg.id}:notice`,\n description: 'Record third-party license/attribution in .devworkspace/THIRD_PARTY_NOTICES.md',\n level: 'project',\n async run(): Promise<StepOutcome> {\n await writeThirdPartyNotice(ctx.root, cfg.notice);\n return { ok: true };\n },\n });\n return { steps, blockers, protectPaths, notes };\n },\n };\n}\n\n"]}
|
|
1
|
+
{"version":3,"file":"pluginSkill.js","sourceRoot":"","sources":["../../../src/integrations/adapters/pluginSkill.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { compareVersions, findClaudeCli, type Tool } from '../exec.js';\nimport { findPlugin, listPlugins, marketplaceRegistered, MIN_PLUGIN_JSON, nativeSteps, pluginId, readDeclared, type NativeSpec } from './claudePlugin.js';\nimport { writeThirdPartyNotice, type NoticeSource } from '../notices.js';\nimport type { AdapterContext, Check, IntegrationAdapter, IntegrationId, IntegrationReport, PlanResult, PlanStep, StepOutcome } from '../types.js';\nimport { pathExists } from '../../utils/fs.js';\n\nexport interface PluginSkillConfig {\n id: IntegrationId;\n name: string;\n usage: string;\n docsUrl: string;\n native: NativeSpec;\n /** `owner/repo` for the portable `npx skills add` path. */\n skillsRepo: string;\n /** Skill directories whose presence means the portable skills are installed. */\n coreSkills: string[];\n notice: NoticeSource;\n /** Capabilities the native plugin provides that portable skills cannot. */\n nativeOnly: string[];\n /** True only when the plugin's own manifest registers lifecycle hooks (verified from its plugin.json). */\n nativeHooks: boolean;\n /** Extra check for the native plugin (e.g. hooks need node). */\n extraNativeChecks?(ctx: AdapterContext): Promise<{ checks: Check[]; warnings: string[]; degraded: boolean }>;\n /** Shared supplementary directory expected beside skills (agent-skills ships references/). */\n referencesDir?: string;\n}\n\nconst SKILLS_CLI = 'skills';\n\nasync function skillDirs(base: string): Promise<string[]> {\n try {\n return (await fs.readdir(path.join(base, '.claude', 'skills'), { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);\n } catch {\n return [];\n }\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n return pathExists(p);\n}\n\nexport function createPluginSkillAdapter(cfg: PluginSkillConfig): IntegrationAdapter {\n const id = pluginId(cfg.native);\n\n async function observe(ctx: AdapterContext, deep: boolean): Promise<{\n claude: Tool | null;\n nativeInstalled: boolean;\n nativeScope: 'project' | 'user' | null;\n nativeError: string | null;\n registered: boolean;\n version: string | null;\n listError: string | null;\n portablePresent: string[];\n portableScope: 'project' | 'user' | null;\n refs: boolean;\n }> {\n const declared = await readDeclared(ctx, cfg.native);\n let claude: Tool | null = null;\n let nativeInstalled = declared.enabled !== null;\n let nativeScope = declared.enabled;\n let nativeError: string | null = null;\n let registered = declared.marketplace;\n let version: string | null = null;\n let listError: string | null = null;\n if (deep) {\n claude = await findClaudeCli(ctx.runner, ctx.home, ctx.signal);\n if (claude && compareVersions(claude.version, MIN_PLUGIN_JSON) >= 0) {\n const l = await listPlugins(ctx, claude);\n if (l.ok) {\n const p = findPlugin(l.plugins, id, ctx.root);\n nativeInstalled = !!p && p.enabled;\n nativeScope = p ? (p.scope === 'user' ? 'user' : 'project') : null;\n version = p?.version ?? null;\n if (p && (p.errors?.length ?? 0) > 0) nativeError = p.errors!.join('; ').slice(0, 300);\n if (p && !p.enabled) nativeError = 'the plugin is installed but disabled';\n if (!p) {\n const reg = await marketplaceRegistered(ctx, claude, cfg.native.marketplaceName);\n registered = reg ?? registered;\n } else registered = true;\n } else listError = l.error ?? 'could not list plugins';\n }\n }\n const projectSkills = await skillDirs(ctx.root);\n const userSkills = await skillDirs(ctx.home);\n const inProject = cfg.coreSkills.filter((s) => projectSkills.includes(s));\n const inUser = cfg.coreSkills.filter((s) => userSkills.includes(s));\n const portablePresent = inProject.length >= inUser.length ? inProject : inUser;\n const portableScope = portablePresent.length === 0 ? null : inProject.length >= inUser.length ? 'project' : 'user';\n let refs = true;\n if (cfg.referencesDir && portablePresent.length > 0) {\n const base = portableScope === 'user' ? ctx.home : ctx.root;\n refs = (await fileExists(path.join(base, '.claude', 'skills', cfg.referencesDir))) || (await fileExists(path.join(base, '.claude', cfg.referencesDir))) || (await fileExists(path.join(base, cfg.referencesDir)));\n }\n return { claude, nativeInstalled, nativeScope, nativeError, registered, version, listError, portablePresent, portableScope, refs };\n }\n\n return {\n id: cfg.id,\n name: cfg.name,\n required: true,\n usage: cfg.usage,\n docsUrl: cfg.docsUrl,\n\n async inspect(ctx, deep): Promise<IntegrationReport> {\n const o = await observe(ctx, deep);\n const checks: Check[] = [];\n const warnings: string[] = [];\n const nextSteps: string[] = [];\n const caps: Record<string, boolean> = { skills: false, commands: false, hooks: false };\n const base = { id: cfg.id, name: cfg.name, required: true, deep } as const;\n if (deep) checks.push({ name: 'Claude Code CLI', ok: !!o.claude, detail: o.claude ? `v${o.claude.version}` : 'not found (PATH or VS Code extension)' });\n if (o.listError) warnings.push(`Could not read the plugin list: ${o.listError}`);\n\n if (o.nativeInstalled) {\n checks.push({ name: 'native plugin', ok: !o.nativeError, detail: o.nativeError ?? `${id}${o.nativeScope ? ` (${o.nativeScope} scope)` : ''}` });\n caps.skills = true;\n caps.commands = true;\n let degraded = !!o.nativeError;\n if (o.nativeError) {\n warnings.push(`${cfg.name} plugin problem: ${o.nativeError}`);\n nextSteps.push(`claude plugin list (inspect errors), then: claude plugin enable ${id}`);\n }\n const extra = cfg.extraNativeChecks ? await cfg.extraNativeChecks(ctx) : { checks: [], warnings: [], degraded: false };\n checks.push(...extra.checks);\n warnings.push(...extra.warnings);\n caps.hooks = cfg.nativeHooks && !extra.degraded;\n degraded = degraded || extra.degraded;\n if (!deep) warnings.push('Not yet verified against `claude plugin list`; run `devworkspace doctor` or `devworkspace integrations status`.');\n return { ...base, status: degraded ? 'DEGRADED' : deep ? 'VERIFIED' : 'INSTALLED', variant: 'native plugin', scope: o.nativeScope, version: o.version, checks, capabilities: caps, warnings, nextSteps };\n }\n\n if (o.portablePresent.length > 0) {\n const complete = o.portablePresent.length === cfg.coreSkills.length;\n caps.skills = complete;\n checks.push({ name: 'portable skills', ok: complete, detail: `${o.portablePresent.length}/${cfg.coreSkills.length} core skills found (${o.portableScope} scope)` });\n if (cfg.referencesDir) checks.push({ name: 'supplementary references', ok: o.refs, detail: o.refs ? 'found' : `${cfg.referencesDir}/ not installed` });\n if (!complete) {\n const missing = cfg.coreSkills.filter((s) => !o.portablePresent.includes(s));\n warnings.push(`Partial installation: missing skills ${missing.join(', ')}.`);\n nextSteps.push('devworkspace integrations repair --yes');\n }\n if (!o.refs) warnings.push(`The shared ${cfg.referencesDir}/ checklists are not installed (known limitation of the skills CLI), so skills that point to them have broken references.`);\n warnings.push(`Portable skills only: ${cfg.nativeOnly.join(', ')} from the native plugin are not available.`);\n nextSteps.push(`For the full plugin: claude plugin marketplace add ${cfg.native.marketplaceUrl} --scope project, then claude plugin install ${id} --scope project`);\n return { ...base, status: 'DEGRADED', variant: 'portable skills', scope: o.portableScope, version: null, checks, capabilities: caps, warnings, nextSteps };\n }\n\n checks.push({ name: 'marketplace', ok: o.registered, detail: o.registered ? `${cfg.native.marketplaceName} is registered but the plugin is not installed` : 'not registered' });\n nextSteps.push('devworkspace setup --integrations --yes');\n return { ...base, status: 'NOT_INSTALLED', variant: null, scope: null, version: null, checks, capabilities: caps, warnings, nextSteps };\n },\n\n async plan(ctx, report): Promise<PlanResult> {\n const o = await observe(ctx, true);\n const blockers: string[] = [];\n const notes: string[] = [];\n const protectPaths = ['.claude/settings.json', '.claude/settings.local.json', 'CLAUDE.md', '.claude/CLAUDE.md', 'AGENTS.md'];\n const steps: PlanStep[] = [];\n const scope = ctx.setup.scope;\n\n if (report.status === 'VERIFIED' && !ctx.setup.repair) return { steps, blockers, protectPaths, notes: ['already verified'] };\n if (o.nativeInstalled && !o.nativeError) return { steps, blockers, protectPaths, notes: ['native plugin already installed'] };\n\n // If the plugin list cannot be read we do not know what is installed: installing anything now could duplicate or overwrite it.\n if (o.claude && compareVersions(o.claude.version, MIN_PLUGIN_JSON) >= 0 && o.listError) {\n blockers.push(`Could not read the installed plugin list (${o.listError}), so nothing was installed. Run \"claude plugin list --json\" yourself to see what is installed, then re-run setup.`);\n return { steps, blockers, protectPaths, notes };\n }\n if (o.claude && compareVersions(o.claude.version, MIN_PLUGIN_JSON) >= 0 && !o.listError) {\n // marketplace registered but plugin missing -> only the install step\n steps.push(...nativeSteps(ctx, o.claude, cfg.native, scope, { registered: o.registered }));\n if (o.nativeError && o.nativeScope) {\n notes.push(`The plugin is present but unhealthy (${o.nativeError}); re-running install to repair.`);\n }\n return { steps, blockers, protectPaths, notes };\n }\n if (o.claude) notes.push(`Claude Code ${o.claude.version} is older than ${MIN_PLUGIN_JSON}, which the plugin commands' --json output needs; using portable skills.`);\n else notes.push('The Claude Code CLI was not found on PATH or in the VS Code extension; using portable skills instead of the native plugin.');\n if (o.listError) notes.push(`\\`claude plugin list\\` failed (${o.listError}); using portable skills.`);\n\n // ---- portable skills via the documented Skills CLI ----\n if (o.portablePresent.length === cfg.coreSkills.length && o.refs) return { steps, blockers, protectPaths, notes: [...notes, 'portable skills already installed'] };\n const managed = new Set(ctx.prior?.managedPaths ?? []);\n const baseDir = scope === 'user' ? ctx.home : ctx.root;\n const existing = await skillDirs(baseDir);\n const conflicts = cfg.coreSkills.filter((s) => existing.includes(s) && !managed.has(`.claude/skills/${s}`));\n if (conflicts.length > 0 && o.portablePresent.length < cfg.coreSkills.length) {\n blockers.push(\n `Skill folder(s) ${conflicts.join(', ')} already exist in .claude/skills and were not installed by DevWorkspace, so they are treated as yours and will not be overwritten. Rename or remove them, or install the native plugin instead.`,\n );\n return { steps, blockers, protectPaths, notes };\n }\n const args = ['--yes', SKILLS_CLI, 'add', cfg.skillsRepo, '--agent', 'claude-code', '--skill', '*', '--copy', '-y', '--json', ...(scope === 'user' ? ['-g'] : [])];\n steps.push({\n id: `${cfg.id}:skills-cli`,\n description: `Install ${cfg.name} skills from ${cfg.skillsRepo} with the Skills CLI (${scope} scope, copied files, telemetry disabled)`,\n command: `npx ${args.join(' ')}`,\n level: 'third-party-code',\n async run(): Promise<StepOutcome> {\n const before = new Set(await skillDirs(baseDir));\n const r = await ctx.runner.runNpx(args, { cwd: ctx.root, timeoutMs: 300_000, signal: ctx.signal, env: { DISABLE_TELEMETRY: '1', DO_NOT_TRACK: '1' } });\n if (r.aborted) return { ok: false, detail: 'cancelled' };\n if (r.timedOut) return { ok: false, detail: 'timed out after 300 s (network?)' };\n if (!r.ok) {\n const tail = `${r.stderr}\\n${r.stdout}`.split(/\\r?\\n/).map((l) => l.trim()).filter(Boolean).slice(-3).join(' ');\n return { ok: false, detail: (tail || r.error || `exit ${r.code}`).slice(0, 400) };\n }\n const after = await skillDirs(baseDir);\n const created = after.filter((s) => !before.has(s));\n ctx.report({ id: cfg.id, step: `${cfg.id}:skills-cli`, state: 'info', detail: `${created.length} skill folder(s) added` });\n return { ok: true, detail: `${created.length} skill folder(s) added`, managedPaths: created.map((s) => `.claude/skills/${s}`) };\n },\n });\n steps.push({\n id: `${cfg.id}:notice`,\n description: 'Record third-party license/attribution in .devworkspace/THIRD_PARTY_NOTICES.md',\n level: 'project',\n async run(): Promise<StepOutcome> {\n await writeThirdPartyNotice(ctx.root, cfg.notice);\n return { ok: true };\n },\n });\n return { steps, blockers, protectPaths, notes };\n },\n };\n}\n\n"]}
|
package/dist/security/files.js
CHANGED
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { promises as fs } from 'node:fs';
|
|
3
3
|
import { DevWorkspaceError } from '../errors/index.js';
|
|
4
4
|
import { readTextBounded } from '../utils/fs.js';
|
|
5
|
+
import { assertNoSymlinkEscape, isInside } from '../utils/paths.js';
|
|
5
6
|
const TEMPLATE_ENV = /^\.env\.(?:example|sample|template|dist|defaults?)$/i;
|
|
6
7
|
const SENSITIVE_BASENAME = [
|
|
7
8
|
/^\.env$/i,
|
|
@@ -30,15 +31,22 @@ export function isSensitiveFile(relPath) {
|
|
|
30
31
|
}
|
|
31
32
|
/** The only sanctioned way for analysis code to read repository text. */
|
|
32
33
|
export async function safeReadText(root, rel, maxBytes) {
|
|
33
|
-
|
|
34
|
+
const absRoot = path.resolve(root);
|
|
35
|
+
const full = path.isAbsolute(rel) ? path.resolve(rel) : path.resolve(absRoot, rel);
|
|
36
|
+
if (!isInside(absRoot, full)) {
|
|
37
|
+
throw new DevWorkspaceError('SECURITY', `Refusing to read path outside repository root: ${rel}.`, {
|
|
38
|
+
hint: 'All repository text reads must remain within the workspace root.',
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (isSensitiveFile(rel) || isSensitiveFile(full)) {
|
|
34
42
|
throw new DevWorkspaceError('SECURITY', `Refusing to read sensitive file ${rel}.`, {
|
|
35
43
|
hint: 'DevWorkspace never reads credential files. Only their presence is recorded.',
|
|
36
44
|
});
|
|
37
45
|
}
|
|
38
|
-
const full = path.join(root, ...rel.split('/'));
|
|
39
46
|
const st = await fs.lstat(full);
|
|
40
47
|
if (st.isSymbolicLink())
|
|
41
48
|
return null;
|
|
49
|
+
await assertNoSymlinkEscape(absRoot, full);
|
|
42
50
|
return readTextBounded(full, maxBytes);
|
|
43
51
|
}
|
|
44
52
|
//# sourceMappingURL=files.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/security/files.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/security/files.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAEpE,MAAM,YAAY,GAAG,sDAAsD,CAAC;AAE5E,MAAM,kBAAkB,GAAa;IACnC,UAAU;IACV,cAAc;IACd,kDAAkD;IAClD,0CAA0C;IAC1C,0BAA0B;IAC1B,sBAAsB;IACtB,gCAAgC;IAChC,sDAAsD;IACtD,gCAAgC;IAChC,YAAY;CACb,CAAC;AAEF,SAAS,IAAI,CAAC,OAAe;IAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IACxB,IAAI,aAAa,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,EAAE,GAAW,EAAE,QAAiB;IAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACnF,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,iBAAiB,CAAC,UAAU,EAAE,kDAAkD,GAAG,GAAG,EAAE;YAChG,IAAI,EAAE,kEAAkE;SACzE,CAAC,CAAC;IACL,CAAC;IACD,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,iBAAiB,CAAC,UAAU,EAAE,mCAAmC,GAAG,GAAG,EAAE;YACjF,IAAI,EAAE,6EAA6E;SACpF,CAAC,CAAC;IACL,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,cAAc,EAAE;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3C,OAAO,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC","sourcesContent":["import path from 'node:path';\nimport { promises as fs } from 'node:fs';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { readTextBounded } from '../utils/fs.js';\nimport { assertNoSymlinkEscape, isInside } from '../utils/paths.js';\n\nconst TEMPLATE_ENV = /^\\.env\\.(?:example|sample|template|dist|defaults?)$/i;\n\nconst SENSITIVE_BASENAME: RegExp[] = [\n /^\\.env$/i,\n /^\\.env\\..+$/i,\n /\\.(?:pem|key|p12|pfx|jks|keystore|ppk|asc|gpg)$/i,\n /^id_(?:rsa|dsa|ecdsa|ed25519)(?:\\..*)?$/i,\n /^credentials?(?:\\..*)?$/i,\n /^secrets?(?:\\..*)?$/i,\n /^service[-_]?account.*\\.json$/i,\n /^\\.(?:npmrc|pypirc|netrc|htpasswd|git-credentials)$/i,\n /^terraform\\.tfstate(?:\\..*)?$/i,\n /\\.tfvars$/i,\n];\n\nfunction base(relPath: string): string {\n return path.posix.basename(relPath.replace(/\\\\/g, '/'));\n}\n\n/** Environment-file templates (.env.example) carry no secrets by convention. */\nexport function isEnvTemplate(relPath: string): boolean {\n return TEMPLATE_ENV.test(base(relPath));\n}\n\nexport function isSensitiveFile(relPath: string): boolean {\n const b = base(relPath);\n if (isEnvTemplate(b)) return false;\n return SENSITIVE_BASENAME.some((re) => re.test(b));\n}\n\n/** The only sanctioned way for analysis code to read repository text. */\nexport async function safeReadText(root: string, rel: string, maxBytes?: number): Promise<string | null> {\n const absRoot = path.resolve(root);\n const full = path.isAbsolute(rel) ? path.resolve(rel) : path.resolve(absRoot, rel);\n if (!isInside(absRoot, full)) {\n throw new DevWorkspaceError('SECURITY', `Refusing to read path outside repository root: ${rel}.`, {\n hint: 'All repository text reads must remain within the workspace root.',\n });\n }\n if (isSensitiveFile(rel) || isSensitiveFile(full)) {\n throw new DevWorkspaceError('SECURITY', `Refusing to read sensitive file ${rel}.`, {\n hint: 'DevWorkspace never reads credential files. Only their presence is recorded.',\n });\n }\n const st = await fs.lstat(full);\n if (st.isSymbolicLink()) return null;\n await assertNoSymlinkEscape(absRoot, full);\n return readTextBounded(full, maxBytes);\n}\n"]}
|
package/dist/security/redact.js
CHANGED
|
@@ -8,7 +8,7 @@ export const SECRET_PATTERNS = [
|
|
|
8
8
|
{ type: 'github-token', re: /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{30,}\b|\bgithub_pat_[A-Za-z0-9_]{40,}\b/g },
|
|
9
9
|
{ type: 'slack-token', re: /\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g },
|
|
10
10
|
{ type: 'api-key', re: /\bsk-[A-Za-z0-9_-]{20,}\b/g },
|
|
11
|
-
{ type: 'google-api-key', re: /\bAIza[0-9A-Za-z_-]{
|
|
11
|
+
{ type: 'google-api-key', re: /\bAIza[0-9A-Za-z_-]{34,36}\b/g },
|
|
12
12
|
{ type: 'npm-token', re: /\bnpm_[A-Za-z0-9]{36}\b/g },
|
|
13
13
|
{ type: 'jwt', re: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g },
|
|
14
14
|
{ type: 'url-credentials', re: /\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@]+:[^\s/@]{3,}@/gi },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/security/redact.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,6IAA6I;KAClJ;IACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,gCAAgC,EAAE;IAChE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,gFAAgF,EAAE;IAC9G,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,mCAAmC,EAAE;IAChE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,4BAA4B,EAAE;IACrD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/security/redact.ts"],"names":[],"mappings":"AAKA,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAoB;IAC9C;QACE,IAAI,EAAE,aAAa;QACnB,EAAE,EAAE,6IAA6I;KAClJ;IACD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,gCAAgC,EAAE;IAChE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,gFAAgF,EAAE;IAC9G,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,mCAAmC,EAAE;IAChE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,4BAA4B,EAAE;IACrD,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,+BAA+B,EAAE;IAC/D,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,0BAA0B,EAAE;IACrD,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,oEAAoE,EAAE;IACzF,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,kDAAkD,EAAE;IACnF;QACE,IAAI,EAAE,gBAAgB;QACtB,EAAE,EAAE,sJAAsJ;KAC3J;CACF,CAAC;AAOF,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,WAA4B,eAAe;IACnF,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,QAAQ,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAyB,CAAC;QAC9B,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;YACnC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;gBAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,yDAAyD;QACjG,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,eAAe,EAAE,CAAC;QAC3C,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,aAAa,IAAI,GAAG,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["export interface SecretPattern {\n type: string;\n re: RegExp;\n}\n\n/** Patterns for common credential formats. Values are never stored or printed. */\nexport const SECRET_PATTERNS: SecretPattern[] = [\n {\n type: 'private-key',\n re: /-----BEGIN (?:RSA |EC |DSA |OPENSSH |PGP |ENCRYPTED )?PRIVATE KEY(?: BLOCK)?-----[\\s\\S]*?(?:-----END [A-Z ]*PRIVATE KEY(?: BLOCK)?-----|$)/g,\n },\n { type: 'aws-access-key', re: /\\b(?:AKIA|ASIA)[0-9A-Z]{16}\\b/g },\n { type: 'github-token', re: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{30,}\\b|\\bgithub_pat_[A-Za-z0-9_]{40,}\\b/g },\n { type: 'slack-token', re: /\\bxox[abprs]-[A-Za-z0-9-]{10,}\\b/g },\n { type: 'api-key', re: /\\bsk-[A-Za-z0-9_-]{20,}\\b/g },\n { type: 'google-api-key', re: /\\bAIza[0-9A-Za-z_-]{34,36}\\b/g },\n { type: 'npm-token', re: /\\bnpm_[A-Za-z0-9]{36}\\b/g },\n { type: 'jwt', re: /\\beyJ[A-Za-z0-9_-]{8,}\\.eyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\b/g },\n { type: 'url-credentials', re: /\\b[a-z][a-z0-9+.-]*:\\/\\/[^\\s/:@]+:[^\\s/@]{3,}@/gi },\n {\n type: 'generic-secret',\n re: /\\b(?:api[_-]?key|secret|token|passwd|password|auth[_-]?key|private[_-]?key)[\"']?\\s*[:=]\\s*[\"']?(?=[A-Za-z0-9_\\-+/=]*\\d)[A-Za-z0-9_\\-+/=]{16,}[\"']?/gi,\n },\n];\n\nexport interface SecretFinding {\n type: string;\n index: number;\n}\n\nexport function findSecrets(text: string, patterns: SecretPattern[] = SECRET_PATTERNS): SecretFinding[] {\n const out: SecretFinding[] = [];\n for (const { type, re } of patterns) {\n const r = new RegExp(re.source, re.flags);\n let m: RegExpExecArray | null;\n while ((m = r.exec(text)) !== null) {\n out.push({ type, index: m.index });\n if (m[0].length === 0) r.lastIndex++; // a pattern that can match nothing must not loop forever\n }\n }\n return out;\n}\n\nexport function containsSecret(text: string): boolean {\n return findSecrets(text).length > 0;\n}\n\nexport function redact(text: string): string {\n let out = text;\n for (const { type, re } of SECRET_PATTERNS) {\n out = out.replace(new RegExp(re.source, re.flags), `[REDACTED:${type}]`);\n }\n return out;\n}\n"]}
|
package/dist/services/agent.d.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles } from '../agents/index.js';
|
|
2
|
+
import type { AgentCapabilities, PlannedChange } from '../agents/types.js';
|
|
3
|
+
export type { AgentAdapter, AgentCapabilities, PlannedChange } from '../agents/types.js';
|
|
2
4
|
import { type ServiceOptions } from './common.js';
|
|
3
|
-
export
|
|
5
|
+
export { AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles };
|
|
4
6
|
export interface AgentInstallResult {
|
|
5
7
|
agent: string;
|
|
6
8
|
dryRun: boolean;
|
|
7
9
|
changes: Omit<PlannedChange, 'content'>[];
|
|
8
10
|
conflicts: number;
|
|
9
11
|
}
|
|
12
|
+
export interface AgentInfo {
|
|
13
|
+
id: string;
|
|
14
|
+
displayName: string;
|
|
15
|
+
capabilities: AgentCapabilities;
|
|
16
|
+
detectedFiles: string[];
|
|
17
|
+
installed: boolean;
|
|
18
|
+
}
|
|
10
19
|
export declare function installAgent(o: ServiceOptions, agentId?: string): Promise<AgentInstallResult>;
|
|
20
|
+
export declare function listAgents(o: ServiceOptions): Promise<AgentInfo[]>;
|
|
11
21
|
export declare function relPath(root: string, p: string): string;
|