@shendu-sdt/sdt-dev-agent 0.1.1 → 0.1.3-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -31
- package/dist/catalog.d.ts +16 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +98 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli/index.js +72 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +267 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +31 -5
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts +4 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +20 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +66 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/core/capability-discovery.d.ts +23 -0
- package/dist/core/capability-discovery.d.ts.map +1 -0
- package/dist/core/capability-discovery.js +49 -0
- package/dist/core/capability-discovery.js.map +1 -0
- package/dist/core/init-options.d.ts +7 -1
- package/dist/core/init-options.d.ts.map +1 -1
- package/dist/core/init-options.js +64 -34
- package/dist/core/init-options.js.map +1 -1
- package/dist/core/init-plan.d.ts +25 -1
- package/dist/core/init-plan.d.ts.map +1 -1
- package/dist/core/init-plan.js +211 -37
- package/dist/core/init-plan.js.map +1 -1
- package/dist/core/init-writer.d.ts +17 -1
- package/dist/core/init-writer.d.ts.map +1 -1
- package/dist/core/init-writer.js +72 -19
- package/dist/core/init-writer.js.map +1 -1
- package/dist/core/manifest.d.ts +8 -0
- package/dist/core/manifest.d.ts.map +1 -0
- package/dist/core/manifest.js +16 -0
- package/dist/core/manifest.js.map +1 -0
- package/dist/core/mcp-config.d.ts +12 -0
- package/dist/core/mcp-config.d.ts.map +1 -0
- package/dist/core/mcp-config.js +60 -0
- package/dist/core/mcp-config.js.map +1 -0
- package/dist/core/project-inspector.d.ts +1 -0
- package/dist/core/project-inspector.d.ts.map +1 -1
- package/dist/core/project-inspector.js +4 -0
- package/dist/core/project-inspector.js.map +1 -1
- package/dist/core/remote-skill-installer.d.ts +16 -0
- package/dist/core/remote-skill-installer.d.ts.map +1 -0
- package/dist/core/remote-skill-installer.js +104 -0
- package/dist/core/remote-skill-installer.js.map +1 -0
- package/dist/core/workflow-installer.d.ts +22 -0
- package/dist/core/workflow-installer.d.ts.map +1 -0
- package/dist/core/workflow-installer.js +103 -0
- package/dist/core/workflow-installer.js.map +1 -0
- package/dist/types.d.ts +103 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -2
- package/dist/types.js.map +1 -1
- package/dist/utils/follow-up-notice.d.ts +7 -0
- package/dist/utils/follow-up-notice.d.ts.map +1 -0
- package/dist/utils/follow-up-notice.js +29 -0
- package/dist/utils/follow-up-notice.js.map +1 -0
- package/dist/utils/init-welcome.d.ts.map +1 -1
- package/dist/utils/init-welcome.js +20 -33
- package/dist/utils/init-welcome.js.map +1 -1
- package/dist/utils/mastergo-notice.d.ts +7 -0
- package/dist/utils/mastergo-notice.d.ts.map +1 -0
- package/dist/utils/mastergo-notice.js +14 -0
- package/dist/utils/mastergo-notice.js.map +1 -0
- package/dist/utils/searchable-multi-select.js +5 -6
- package/dist/utils/searchable-multi-select.js.map +1 -1
- package/dist/utils/styled-select.d.ts.map +1 -1
- package/dist/utils/styled-select.js.map +1 -1
- package/dist/utils/terminal-theme.d.ts +4 -0
- package/dist/utils/terminal-theme.d.ts.map +1 -0
- package/dist/utils/terminal-theme.js +25 -0
- package/dist/utils/terminal-theme.js.map +1 -0
- package/package.json +6 -3
- package/templates/bootstrap/project-entry.md +17 -0
- package/templates/mcp/context7/claude-code/server.json +6 -0
- package/templates/mcp/context7/codex/config.toml +3 -0
- package/templates/mcp/mastergo/claude-code/server.json +6 -0
- package/templates/mcp/mastergo/codex/config.toml +4 -0
- package/templates/skills/builtin/bootstrap-project-docs/SKILL.md +16 -0
- package/templates/skills/builtin/bootstrap-project-docs/references/architecture-first.md +7 -0
- package/templates/skills/builtin/bootstrap-project-docs/references/tool-rules-follow-up.md +8 -0
- package/templates/skills/remote/catalog.json +68 -0
- package/templates/workflows/openspec/README.md +7 -0
- package/templates/workflows/openspec/claude-code/README.md +7 -0
- package/templates/workflows/openspec/codex/README.md +7 -0
- package/templates/AGENTS.md +0 -24
- package/templates/ARCHITECTURE.md +0 -26
- package/templates/capabilities/mcp/README.md +0 -8
- package/templates/capabilities/skills/README.md +0 -8
- package/templates/docs/ai-collaboration/README.md +0 -16
- package/templates/tools/claude-code/README.md +0 -8
- package/templates/tools/codex/README.md +0 -8
package/dist/core/init-writer.js
CHANGED
|
@@ -1,28 +1,81 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return conflicts;
|
|
12
|
-
}
|
|
13
|
-
export async function applyInitPlan(targetPath, plan) {
|
|
14
|
-
const conflicts = await collectConflicts(targetPath, plan);
|
|
15
|
-
if (conflicts.length > 0) {
|
|
16
|
-
throw new Error(`Initialization aborted. Existing files would be overwritten:\n${conflicts
|
|
17
|
-
.map((item) => `- ${item}`)
|
|
18
|
-
.join('\n')}`);
|
|
19
|
-
}
|
|
2
|
+
import { detectSkillAvailability } from './capability-discovery.js';
|
|
3
|
+
import { mergeMcpConfig, parseConfiguredMcpIds } from './mcp-config.js';
|
|
4
|
+
import { installRemoteSkill } from './remote-skill-installer.js';
|
|
5
|
+
import { exists, readText, toPosixPath, writeText } from '../utils/fs.js';
|
|
6
|
+
/**
|
|
7
|
+
* 执行 `createInitPlan` 产出的计划。
|
|
8
|
+
* 这里负责真实写盘、MCP 合并、远端 skill 安装以及 manifest 最终回写。
|
|
9
|
+
*/
|
|
10
|
+
export async function applyInitPlan(targetPath, plan, hooks = {}) {
|
|
20
11
|
const writtenFiles = [];
|
|
12
|
+
const failedRemoteSkills = [];
|
|
21
13
|
for (const file of plan.files) {
|
|
14
|
+
if (file.kind === 'manifest') {
|
|
15
|
+
// manifest 需要在远端安装结果落定后再写一次,避免状态不一致。
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
22
18
|
const absolutePath = path.join(targetPath, file.path);
|
|
19
|
+
if (file.kind === 'mcp' && (await exists(absolutePath))) {
|
|
20
|
+
const tool = file.path === '.mcp.json' ? 'claude-code' : 'codex';
|
|
21
|
+
const existingContent = await readText(absolutePath);
|
|
22
|
+
const selectedMcps = plan.manifest.mcps
|
|
23
|
+
.filter((mcp) => mcp.installs.some((install) => install.tool === tool && install.path === file.path))
|
|
24
|
+
.map((mcp) => mcp.id);
|
|
25
|
+
const existingServers = parseConfiguredMcpIds(tool, existingContent);
|
|
26
|
+
for (const mcp of plan.manifest.mcps) {
|
|
27
|
+
const installRecord = mcp.installs.find((install) => install.tool === tool && install.path === file.path);
|
|
28
|
+
if (installRecord && existingServers.has(mcp.id)) {
|
|
29
|
+
installRecord.status = 'already-present';
|
|
30
|
+
installRecord.reason = 'already-present';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const mergedContent = mergeMcpConfig(tool, existingContent, selectedMcps);
|
|
34
|
+
if (mergedContent !== existingContent) {
|
|
35
|
+
await writeText(absolutePath, mergedContent);
|
|
36
|
+
writtenFiles.push(toPosixPath(file.path));
|
|
37
|
+
}
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
23
40
|
await writeText(absolutePath, file.content);
|
|
24
41
|
writtenFiles.push(toPosixPath(file.path));
|
|
25
42
|
}
|
|
26
|
-
|
|
43
|
+
for (const [index, install] of plan.remoteSkillInstalls.entries()) {
|
|
44
|
+
hooks.onRemoteSkillInstallStart?.(install, index + 1, plan.remoteSkillInstalls.length);
|
|
45
|
+
const availability = await detectSkillAvailability(targetPath, install.tool, install.skillId);
|
|
46
|
+
const skillRecord = plan.manifest.skills.find((skill) => skill.id === install.skillId);
|
|
47
|
+
const installRecord = skillRecord?.installs.find((item) => item.tool === install.tool);
|
|
48
|
+
if (!installRecord) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (availability.status === 'already-present') {
|
|
52
|
+
installRecord.status = availability.status;
|
|
53
|
+
installRecord.reason = availability.reason;
|
|
54
|
+
hooks.onRemoteSkillInstallFinish?.(install, 'already-present');
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const result = await installRemoteSkill(targetPath, install);
|
|
58
|
+
if (!result.success) {
|
|
59
|
+
installRecord.status = 'failed';
|
|
60
|
+
installRecord.reason = 'install-failed';
|
|
61
|
+
hooks.onRemoteSkillInstallFinish?.(install, 'failed');
|
|
62
|
+
failedRemoteSkills.push({
|
|
63
|
+
skillId: install.skillId,
|
|
64
|
+
tool: install.tool,
|
|
65
|
+
installCommand: install.installCommand,
|
|
66
|
+
error: result.error ?? 'Unknown error',
|
|
67
|
+
});
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
writtenFiles.push(...result.targetPaths.map((targetPath) => toPosixPath(targetPath)));
|
|
71
|
+
hooks.onRemoteSkillInstallFinish?.(install, 'installed');
|
|
72
|
+
}
|
|
73
|
+
const manifestPath = path.join(targetPath, '.sdt-devagent', 'manifest.json');
|
|
74
|
+
await writeText(manifestPath, `${JSON.stringify(plan.manifest, null, 2)}\n`);
|
|
75
|
+
writtenFiles.push('.sdt-devagent/manifest.json');
|
|
76
|
+
return {
|
|
77
|
+
writtenFiles,
|
|
78
|
+
failedRemoteSkills,
|
|
79
|
+
};
|
|
27
80
|
}
|
|
28
81
|
//# sourceMappingURL=init-writer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-writer.js","sourceRoot":"","sources":["../../src/core/init-writer.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"init-writer.js","sourceRoot":"","sources":["../../src/core/init-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { InstallManifest } from '../types.js';
|
|
2
|
+
/** `.sdt-devagent/manifest.json` 的固定位置。 */
|
|
3
|
+
export declare function getManifestPath(projectRoot: string): string;
|
|
4
|
+
/** 读取并解析项目内 manifest。 */
|
|
5
|
+
export declare function readInstallManifest(projectRoot: string): Promise<InstallManifest>;
|
|
6
|
+
/** 用格式化 JSON 回写 manifest。 */
|
|
7
|
+
export declare function writeInstallManifest(projectRoot: string, manifest: InstallManifest): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/core/manifest.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,yBAAyB;AACzB,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAGvF;AAED,6BAA6B;AAC7B,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readText, writeText } from '../utils/fs.js';
|
|
3
|
+
/** `.sdt-devagent/manifest.json` 的固定位置。 */
|
|
4
|
+
export function getManifestPath(projectRoot) {
|
|
5
|
+
return path.join(projectRoot, '.sdt-devagent', 'manifest.json');
|
|
6
|
+
}
|
|
7
|
+
/** 读取并解析项目内 manifest。 */
|
|
8
|
+
export async function readInstallManifest(projectRoot) {
|
|
9
|
+
const raw = await readText(getManifestPath(projectRoot));
|
|
10
|
+
return JSON.parse(raw);
|
|
11
|
+
}
|
|
12
|
+
/** 用格式化 JSON 回写 manifest。 */
|
|
13
|
+
export async function writeInstallManifest(projectRoot, manifest) {
|
|
14
|
+
await writeText(getManifestPath(projectRoot), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/core/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAGpD,2CAA2C;AAC3C,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,EAAE,eAAe,CAAC,CAAA;AACjE,CAAC;AAED,yBAAyB;AACzB,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,WAAmB;IAC3D,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAA;IACxD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAA;AAC3C,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,WAAmB,EACnB,QAAyB;IAEzB,MAAM,SAAS,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;AACzF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpId, ToolId } from '../types.js';
|
|
2
|
+
/** 获取某个 MCP 在指定工具下的模板片段。 */
|
|
3
|
+
export declare function getMcpSnippet(tool: ToolId, mcpId: McpId): string;
|
|
4
|
+
/** 组装 Codex 项目的 `config.toml` 片段。 */
|
|
5
|
+
export declare function buildCodexMcpConfig(selectedMcps: McpId[]): string;
|
|
6
|
+
/** 组装 Claude Code 项目的 `.mcp.json` 内容。 */
|
|
7
|
+
export declare function buildClaudeMcpConfig(selectedMcps: McpId[]): string;
|
|
8
|
+
/** 从已有配置中解析出已经声明过的 MCP server ID。 */
|
|
9
|
+
export declare function parseConfiguredMcpIds(tool: ToolId, content: string): Set<string>;
|
|
10
|
+
/** 仅把缺失的 MCP 片段追加进去,已存在的 server 不覆盖。 */
|
|
11
|
+
export declare function mergeMcpConfig(tool: ToolId, existingContent: string, selectedMcps: McpId[]): string;
|
|
12
|
+
//# sourceMappingURL=mcp-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config.d.ts","sourceRoot":"","sources":["../../src/core/mcp-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAUhD,4BAA4B;AAC5B,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAIhE;AAED,qCAAqC;AACrC,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,MAAM,CAQjE;AAED,yCAAyC;AACzC,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,MAAM,CASlE;AAED,qCAAqC;AACrC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAShF;AAED,wCAAwC;AACxC,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,KAAK,EAAE,GACpB,MAAM,CAsBR"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
const projectRoot = path.resolve(currentDir, '..', '..');
|
|
6
|
+
/** 从模板目录读取单个 MCP 片段。 */
|
|
7
|
+
function loadTemplate(relativePath) {
|
|
8
|
+
return readFileSync(path.join(projectRoot, 'templates', relativePath), 'utf8');
|
|
9
|
+
}
|
|
10
|
+
/** 获取某个 MCP 在指定工具下的模板片段。 */
|
|
11
|
+
export function getMcpSnippet(tool, mcpId) {
|
|
12
|
+
return tool === 'codex'
|
|
13
|
+
? loadTemplate(path.join('mcp', mcpId, 'codex', 'config.toml'))
|
|
14
|
+
: loadTemplate(path.join('mcp', mcpId, 'claude-code', 'server.json'));
|
|
15
|
+
}
|
|
16
|
+
/** 组装 Codex 项目的 `config.toml` 片段。 */
|
|
17
|
+
export function buildCodexMcpConfig(selectedMcps) {
|
|
18
|
+
const lines = ['# Managed by SDT DevAgent'];
|
|
19
|
+
for (const mcpId of selectedMcps) {
|
|
20
|
+
lines.push('', getMcpSnippet('codex', mcpId).trimEnd());
|
|
21
|
+
}
|
|
22
|
+
return `${lines.join('\n')}\n`;
|
|
23
|
+
}
|
|
24
|
+
/** 组装 Claude Code 项目的 `.mcp.json` 内容。 */
|
|
25
|
+
export function buildClaudeMcpConfig(selectedMcps) {
|
|
26
|
+
const mcpServers = {};
|
|
27
|
+
for (const mcpId of selectedMcps) {
|
|
28
|
+
const parsed = JSON.parse(getMcpSnippet('claude-code', mcpId));
|
|
29
|
+
Object.assign(mcpServers, parsed);
|
|
30
|
+
}
|
|
31
|
+
return `${JSON.stringify({ mcpServers }, null, 2)}\n`;
|
|
32
|
+
}
|
|
33
|
+
/** 从已有配置中解析出已经声明过的 MCP server ID。 */
|
|
34
|
+
export function parseConfiguredMcpIds(tool, content) {
|
|
35
|
+
if (tool === 'codex') {
|
|
36
|
+
return new Set([...content.matchAll(/^\[mcp_servers\.([A-Za-z0-9_-]+)\]$/gm)].map((match) => match[1]));
|
|
37
|
+
}
|
|
38
|
+
const parsed = JSON.parse(content);
|
|
39
|
+
return new Set(Object.keys(parsed.mcpServers ?? {}));
|
|
40
|
+
}
|
|
41
|
+
/** 仅把缺失的 MCP 片段追加进去,已存在的 server 不覆盖。 */
|
|
42
|
+
export function mergeMcpConfig(tool, existingContent, selectedMcps) {
|
|
43
|
+
const existingServers = parseConfiguredMcpIds(tool, existingContent);
|
|
44
|
+
const missingMcps = selectedMcps.filter((mcpId) => !existingServers.has(mcpId));
|
|
45
|
+
if (missingMcps.length === 0) {
|
|
46
|
+
return existingContent.endsWith('\n') ? existingContent : `${existingContent}\n`;
|
|
47
|
+
}
|
|
48
|
+
if (tool === 'codex') {
|
|
49
|
+
const additions = missingMcps.map((mcpId) => getMcpSnippet(tool, mcpId).trim());
|
|
50
|
+
const base = existingContent.trimEnd();
|
|
51
|
+
return `${base}\n\n${additions.join('\n\n')}\n`;
|
|
52
|
+
}
|
|
53
|
+
const parsed = JSON.parse(existingContent);
|
|
54
|
+
const mergedServers = { ...(parsed.mcpServers ?? {}) };
|
|
55
|
+
for (const mcpId of missingMcps) {
|
|
56
|
+
Object.assign(mergedServers, JSON.parse(getMcpSnippet(tool, mcpId)));
|
|
57
|
+
}
|
|
58
|
+
return `${JSON.stringify({ ...parsed, mcpServers: mergedServers }, null, 2)}\n`;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=mcp-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config.js","sourceRoot":"","sources":["../../src/core/mcp-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-inspector.d.ts","sourceRoot":"","sources":["../../src/core/project-inspector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"project-inspector.d.ts","sourceRoot":"","sources":["../../src/core/project-inspector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAqD/C,uCAAuC;AACvC,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAa9E"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { exists, readText } from '../utils/fs.js';
|
|
3
|
+
/** 通过常见 lockfile 推断项目包管理器。 */
|
|
3
4
|
async function detectPackageManager(targetPath) {
|
|
4
5
|
const checks = [
|
|
5
6
|
['pnpm-lock.yaml', 'pnpm'],
|
|
@@ -14,6 +15,7 @@ async function detectPackageManager(targetPath) {
|
|
|
14
15
|
}
|
|
15
16
|
return 'unknown';
|
|
16
17
|
}
|
|
18
|
+
/** 读取项目名;没有 `package.json` 时回退到目录名。 */
|
|
17
19
|
async function detectProjectName(targetPath) {
|
|
18
20
|
const packageJsonPath = path.join(targetPath, 'package.json');
|
|
19
21
|
if (!(await exists(packageJsonPath))) {
|
|
@@ -29,6 +31,7 @@ async function detectProjectName(targetPath) {
|
|
|
29
31
|
hasPackageJson: true,
|
|
30
32
|
};
|
|
31
33
|
}
|
|
34
|
+
/** 在一组候选目录里找第一个存在的目录作为事实值。 */
|
|
32
35
|
async function detectDirectory(targetPath, candidates) {
|
|
33
36
|
for (const candidate of candidates) {
|
|
34
37
|
if (await exists(path.join(targetPath, candidate))) {
|
|
@@ -37,6 +40,7 @@ async function detectDirectory(targetPath, candidates) {
|
|
|
37
40
|
}
|
|
38
41
|
return 'N/A';
|
|
39
42
|
}
|
|
43
|
+
/** `init` 当前只关注最小项目事实,不做框架和业务层深入探测。 */
|
|
40
44
|
export async function inspectProject(targetPath) {
|
|
41
45
|
const project = await detectProjectName(targetPath);
|
|
42
46
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-inspector.js","sourceRoot":"","sources":["../../src/core/project-inspector.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAGjD,KAAK,UAAU,oBAAoB,CAAC,UAAkB;IACpD,MAAM,MAAM,GAA4B;QACtC,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAC1B,CAAC,mBAAmB,EAAE,KAAK,CAAC;QAC5B,CAAC,WAAW,EAAE,MAAM,CAAC;QACrB,CAAC,WAAW,EAAE,KAAK,CAAC;KACrB,CAAA;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,MAAM,EAAE,CAAC;QAChD,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,cAAc,CAAA;QACvB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IAIjD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IAC7D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YACtC,cAAc,EAAE,KAAK;SACtB,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAA;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAA;IAExD,OAAO;QACL,WAAW,EAAE,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1D,cAAc,EAAE,IAAI;KACrB,CAAA;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,UAAkB,EAAE,UAAoB;IACrE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB;IACrD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAEnD,OAAO;QACL,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,cAAc,EAAE,MAAM,oBAAoB,CAAC,UAAU,CAAC;QACtD,UAAU,EAAE,MAAM,eAAe,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QACzE,QAAQ,EAAE,MAAM,eAAe,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3E,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,SAAS,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC3D,UAAU,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;KACxD,CAAA;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"project-inspector.js","sourceRoot":"","sources":["../../src/core/project-inspector.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAGjD,8BAA8B;AAC9B,KAAK,UAAU,oBAAoB,CAAC,UAAkB;IACpD,MAAM,MAAM,GAA4B;QACtC,CAAC,gBAAgB,EAAE,MAAM,CAAC;QAC1B,CAAC,mBAAmB,EAAE,KAAK,CAAC;QAC5B,CAAC,WAAW,EAAE,MAAM,CAAC;QACrB,CAAC,WAAW,EAAE,KAAK,CAAC;KACrB,CAAA;IAED,KAAK,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,MAAM,EAAE,CAAC;QAChD,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,cAAc,CAAA;QACvB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,uCAAuC;AACvC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IAIjD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAA;IAC7D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YACtC,cAAc,EAAE,KAAK;SACtB,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,CAAA;IAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAsB,CAAA;IAExD,OAAO;QACL,WAAW,EAAE,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC1D,cAAc,EAAE,IAAI;KACrB,CAAA;AACH,CAAC;AAED,8BAA8B;AAC9B,KAAK,UAAU,eAAe,CAAC,UAAkB,EAAE,UAAoB;IACrE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,uCAAuC;AACvC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB;IACrD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAEnD,OAAO;QACL,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,cAAc,EAAE,MAAM,oBAAoB,CAAC,UAAU,CAAC;QACtD,UAAU,EAAE,MAAM,eAAe,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;QACzE,QAAQ,EAAE,MAAM,eAAe,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3E,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,SAAS,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC3D,UAAU,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;KACxD,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PlannedRemoteSkillInstall } from '../types.js';
|
|
2
|
+
/** 单次远端 skill 安装后的结果摘要。 */
|
|
3
|
+
export interface RemoteSkillInstallResult {
|
|
4
|
+
tool: PlannedRemoteSkillInstall['tool'];
|
|
5
|
+
skillId: PlannedRemoteSkillInstall['skillId'];
|
|
6
|
+
targetPaths: string[];
|
|
7
|
+
installCommand: string;
|
|
8
|
+
success: boolean;
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 执行远端 skill 安装。
|
|
13
|
+
* 成功标准不是退出码,而是安装后项目级目标路径已经真实出现。
|
|
14
|
+
*/
|
|
15
|
+
export declare function installRemoteSkill(projectRoot: string, install: PlannedRemoteSkillInstall): Promise<RemoteSkillInstallResult>;
|
|
16
|
+
//# sourceMappingURL=remote-skill-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-skill-installer.d.ts","sourceRoot":"","sources":["../../src/core/remote-skill-installer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAE5D,2BAA2B;AAC3B,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAA;IACvC,OAAO,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAA;IAC7C,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAoDD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAwEnC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { hasProjectSkillInstall } from './capability-discovery.js';
|
|
4
|
+
/** 最小的子进程执行包装;统一收集 stdout/stderr 作为错误上下文。 */
|
|
5
|
+
function runCommand(command, args, env, cwd) {
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
const child = spawn(command, args, {
|
|
8
|
+
cwd,
|
|
9
|
+
env,
|
|
10
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
11
|
+
shell: process.platform === 'win32',
|
|
12
|
+
});
|
|
13
|
+
let stdout = '';
|
|
14
|
+
let stderr = '';
|
|
15
|
+
child.stdout?.setEncoding('utf8');
|
|
16
|
+
child.stderr?.setEncoding('utf8');
|
|
17
|
+
child.stdout?.on('data', (chunk) => {
|
|
18
|
+
stdout += chunk;
|
|
19
|
+
});
|
|
20
|
+
child.stderr?.on('data', (chunk) => {
|
|
21
|
+
stderr += chunk;
|
|
22
|
+
});
|
|
23
|
+
child.on('error', (error) => {
|
|
24
|
+
resolve({
|
|
25
|
+
success: false,
|
|
26
|
+
error: error.message,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
child.on('close', (code, signal) => {
|
|
30
|
+
const output = [stdout.trim(), stderr.trim()].filter(Boolean).join('\n');
|
|
31
|
+
if (code === 0) {
|
|
32
|
+
resolve({ success: true, output });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
resolve({
|
|
36
|
+
success: false,
|
|
37
|
+
error: output || `Command failed with ${signal ? `signal ${signal}` : `exit code ${code}`}`,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 执行远端 skill 安装。
|
|
44
|
+
* 成功标准不是退出码,而是安装后项目级目标路径已经真实出现。
|
|
45
|
+
*/
|
|
46
|
+
export async function installRemoteSkill(projectRoot, install) {
|
|
47
|
+
const stubPath = process.env.SDT_DEV_AGENT_SKILLS_STUB_PATH;
|
|
48
|
+
const targetPaths = install.installTargets.map((target) => target.targetPath);
|
|
49
|
+
let execution;
|
|
50
|
+
if (stubPath) {
|
|
51
|
+
// 测试环境通过 stub 精确控制安装结果,避免真实依赖网络和外部 CLI。
|
|
52
|
+
for (const target of install.installTargets) {
|
|
53
|
+
execution = await runCommand(process.execPath, [stubPath, target.skillName, install.tool, path.join(projectRoot, target.targetPath)], process.env, projectRoot);
|
|
54
|
+
if (!execution.success) {
|
|
55
|
+
return {
|
|
56
|
+
tool: install.tool,
|
|
57
|
+
skillId: install.skillId,
|
|
58
|
+
targetPaths,
|
|
59
|
+
installCommand: install.installCommand,
|
|
60
|
+
success: false,
|
|
61
|
+
error: execution.error,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
execution = { success: true, output: '' };
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// 正常链路复用 skills CLI,把能力直接 copy 到项目级目录。
|
|
69
|
+
const skillNames = install.installTargets.map((target) => target.skillName);
|
|
70
|
+
execution = await runCommand('npx', [
|
|
71
|
+
'-y',
|
|
72
|
+
'skills',
|
|
73
|
+
'add',
|
|
74
|
+
install.source,
|
|
75
|
+
'--yes',
|
|
76
|
+
'--skill',
|
|
77
|
+
...skillNames,
|
|
78
|
+
'--copy',
|
|
79
|
+
'-a',
|
|
80
|
+
install.tool,
|
|
81
|
+
], process.env, projectRoot);
|
|
82
|
+
}
|
|
83
|
+
if (execution.success && !hasProjectSkillInstall(projectRoot, install.tool, install.skillId)) {
|
|
84
|
+
const expectedPaths = targetPaths.join(', ');
|
|
85
|
+
const detail = execution.output ? `\nCommand output:\n${execution.output}` : '';
|
|
86
|
+
return {
|
|
87
|
+
tool: install.tool,
|
|
88
|
+
skillId: install.skillId,
|
|
89
|
+
targetPaths,
|
|
90
|
+
installCommand: install.installCommand,
|
|
91
|
+
success: false,
|
|
92
|
+
error: `Command exited successfully but the expected project skill paths were not written: ${expectedPaths}.${detail}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
tool: install.tool,
|
|
97
|
+
skillId: install.skillId,
|
|
98
|
+
targetPaths,
|
|
99
|
+
installCommand: install.installCommand,
|
|
100
|
+
success: execution.success,
|
|
101
|
+
error: execution.success ? undefined : execution.error,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=remote-skill-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-skill-installer.js","sourceRoot":"","sources":["../../src/core/remote-skill-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ToolId, WorkflowId } from '../types.js';
|
|
2
|
+
/** `add workflow` 传给安装器的最小输入。 */
|
|
3
|
+
export interface PlannedWorkflowInstall {
|
|
4
|
+
tool: ToolId;
|
|
5
|
+
workflowId: WorkflowId;
|
|
6
|
+
installCommand: string;
|
|
7
|
+
}
|
|
8
|
+
/** 单次 workflow 安装后的结果摘要。 */
|
|
9
|
+
export interface WorkflowInstallResult {
|
|
10
|
+
tool: ToolId;
|
|
11
|
+
workflowId: WorkflowId;
|
|
12
|
+
targetPaths: string[];
|
|
13
|
+
installCommand: string;
|
|
14
|
+
success: boolean;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 执行 workflow 安装。
|
|
19
|
+
* 当前策略是优先走本机命令,失败时再回退到官方 `npx` 入口。
|
|
20
|
+
*/
|
|
21
|
+
export declare function installWorkflow(projectRoot: string, install: PlannedWorkflowInstall): Promise<WorkflowInstallResult>;
|
|
22
|
+
//# sourceMappingURL=workflow-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-installer.d.ts","sourceRoot":"","sources":["../../src/core/workflow-installer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAErD,iCAAiC;AACjC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,4BAA4B;AAC5B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAyDD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CAyEhC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { hasProjectWorkflowInstall } from './capability-discovery.js';
|
|
4
|
+
import { getWorkflowTargetPaths } from './init-plan.js';
|
|
5
|
+
/** 最小的子进程执行包装;统一收集 stdout/stderr 作为错误上下文。 */
|
|
6
|
+
function runCommand(command, args, env, cwd) {
|
|
7
|
+
return new Promise((resolve) => {
|
|
8
|
+
const child = spawn(command, args, {
|
|
9
|
+
cwd,
|
|
10
|
+
env,
|
|
11
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
12
|
+
shell: process.platform === 'win32',
|
|
13
|
+
});
|
|
14
|
+
let stdout = '';
|
|
15
|
+
let stderr = '';
|
|
16
|
+
child.stdout?.setEncoding('utf8');
|
|
17
|
+
child.stderr?.setEncoding('utf8');
|
|
18
|
+
child.stdout?.on('data', (chunk) => {
|
|
19
|
+
stdout += chunk;
|
|
20
|
+
});
|
|
21
|
+
child.stderr?.on('data', (chunk) => {
|
|
22
|
+
stderr += chunk;
|
|
23
|
+
});
|
|
24
|
+
child.on('error', (error) => {
|
|
25
|
+
resolve({
|
|
26
|
+
success: false,
|
|
27
|
+
error: error.message,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
child.on('close', (code, signal) => {
|
|
31
|
+
const output = [stdout.trim(), stderr.trim()].filter(Boolean).join('\n');
|
|
32
|
+
if (code === 0) {
|
|
33
|
+
resolve({ success: true, output });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
resolve({
|
|
37
|
+
success: false,
|
|
38
|
+
error: output || `Command failed with ${signal ? `signal ${signal}` : `exit code ${code}`}`,
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** `OpenSpec` CLI 使用的工具名与本仓库内部枚举不同。 */
|
|
44
|
+
function mapOpenSpecToolId(tool) {
|
|
45
|
+
return tool === 'claude-code' ? 'claude' : 'codex';
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 执行 workflow 安装。
|
|
49
|
+
* 当前策略是优先走本机命令,失败时再回退到官方 `npx` 入口。
|
|
50
|
+
*/
|
|
51
|
+
export async function installWorkflow(projectRoot, install) {
|
|
52
|
+
const stubPath = process.env.SDT_DEV_AGENT_WORKFLOWS_STUB_PATH;
|
|
53
|
+
const targetPaths = getWorkflowTargetPaths(install.tool, install.workflowId);
|
|
54
|
+
let execution;
|
|
55
|
+
if (stubPath) {
|
|
56
|
+
// 测试环境直接走 stub,避免依赖真实 OpenSpec CLI。
|
|
57
|
+
execution = await runCommand(process.execPath, [
|
|
58
|
+
stubPath,
|
|
59
|
+
install.workflowId,
|
|
60
|
+
install.tool,
|
|
61
|
+
...targetPaths.map((targetPath) => path.join(projectRoot, targetPath)),
|
|
62
|
+
], process.env, projectRoot);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// 优先复用用户本机已安装的 openspec,失败时再回退到 npx。
|
|
66
|
+
const toolArg = mapOpenSpecToolId(install.tool);
|
|
67
|
+
execution = await runCommand('openspec', ['init', '--tools', toolArg, '--profile', 'core', projectRoot], process.env, projectRoot);
|
|
68
|
+
if (!execution.success) {
|
|
69
|
+
execution = await runCommand('npx', [
|
|
70
|
+
'-y',
|
|
71
|
+
'@fission-ai/openspec@latest',
|
|
72
|
+
'init',
|
|
73
|
+
'--tools',
|
|
74
|
+
toolArg,
|
|
75
|
+
'--profile',
|
|
76
|
+
'core',
|
|
77
|
+
projectRoot,
|
|
78
|
+
], process.env, projectRoot);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (execution.success &&
|
|
82
|
+
!hasProjectWorkflowInstall(projectRoot, install.tool, install.workflowId)) {
|
|
83
|
+
const expectedPaths = targetPaths.join(', ');
|
|
84
|
+
const detail = 'output' in execution && execution.output ? `\nCommand output:\n${execution.output}` : '';
|
|
85
|
+
return {
|
|
86
|
+
tool: install.tool,
|
|
87
|
+
workflowId: install.workflowId,
|
|
88
|
+
targetPaths,
|
|
89
|
+
installCommand: install.installCommand,
|
|
90
|
+
success: false,
|
|
91
|
+
error: `Command exited successfully but the expected project workflow paths were not written: ${expectedPaths}.${detail}`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
tool: install.tool,
|
|
96
|
+
workflowId: install.workflowId,
|
|
97
|
+
targetPaths,
|
|
98
|
+
installCommand: install.installCommand,
|
|
99
|
+
success: execution.success,
|
|
100
|
+
error: execution.success ? undefined : execution.error,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=workflow-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-installer.js","sourceRoot":"","sources":["../../src/core/workflow-installer.ts"],"names":[],"mappings":"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"}
|