@codemieai/code 0.0.32 → 0.0.34
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 +73 -7
- package/bin/codemie-opencode.js +11 -0
- package/dist/agents/codemie-code/agent.d.ts +17 -1
- package/dist/agents/codemie-code/agent.d.ts.map +1 -1
- package/dist/agents/codemie-code/agent.js +62 -3
- package/dist/agents/codemie-code/agent.js.map +1 -1
- package/dist/agents/codemie-code/index.d.ts +1 -0
- package/dist/agents/codemie-code/index.d.ts.map +1 -1
- package/dist/agents/codemie-code/index.js +28 -2
- package/dist/agents/codemie-code/index.js.map +1 -1
- package/dist/agents/codemie-code/prompts.d.ts +12 -3
- package/dist/agents/codemie-code/prompts.d.ts.map +1 -1
- package/dist/agents/codemie-code/prompts.js +25 -5
- package/dist/agents/codemie-code/prompts.js.map +1 -1
- package/dist/agents/codemie-code/types.d.ts +3 -0
- package/dist/agents/codemie-code/types.d.ts.map +1 -1
- package/dist/agents/codemie-code/types.js.map +1 -1
- package/dist/agents/codemie-code/ui/todoPanel.d.ts.map +1 -1
- package/dist/agents/codemie-code/ui/todoPanel.js +4 -0
- package/dist/agents/codemie-code/ui/todoPanel.js.map +1 -1
- package/dist/agents/core/AgentCLI.d.ts.map +1 -1
- package/dist/agents/core/AgentCLI.js +3 -1
- package/dist/agents/core/AgentCLI.js.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.js +46 -2
- package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
- package/dist/agents/core/session/BaseSessionAdapter.d.ts +25 -0
- package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
- package/dist/agents/core/session/SessionStore.d.ts +15 -0
- package/dist/agents/core/session/SessionStore.d.ts.map +1 -1
- package/dist/agents/core/session/SessionStore.js +46 -0
- package/dist/agents/core/session/SessionStore.js.map +1 -1
- package/dist/agents/core/session/discovery-types.d.ts +53 -0
- package/dist/agents/core/session/discovery-types.d.ts.map +1 -0
- package/dist/agents/core/session/discovery-types.js +8 -0
- package/dist/agents/core/session/discovery-types.js.map +1 -0
- package/dist/agents/core/session/types.d.ts +2 -0
- package/dist/agents/core/session/types.d.ts.map +1 -1
- package/dist/agents/core/types.d.ts +45 -0
- package/dist/agents/core/types.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.d.ts +44 -1
- package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +214 -0
- package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
- package/dist/agents/plugins/claude/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/agents/plugins/claude/plugin/README.md +40 -2
- package/dist/agents/plugins/claude/plugin/claude-templates/README.md +5 -5
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/CLAUDE.md.template +177 -436
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/agents/code-review-agent-template.md.template +49 -82
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/agents/refactor-cleaner-agent.md.template +337 -0
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/agents/solution-architect-agent.md.template +129 -419
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/agents/unit-tester-agent.md.template +146 -693
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/api/api-patterns.md.template +110 -138
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/architecture/architecture.md.template +197 -0
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/data/database-patterns.md.template +171 -91
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/development/development-practices.md.template +219 -131
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/security/security-practices.md.template +223 -98
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/standards/code-quality.md.template +131 -95
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/testing/testing-patterns.md.template +247 -75
- package/dist/agents/plugins/claude/plugin/commands/README.md +133 -0
- package/dist/agents/plugins/claude/plugin/commands/codemie-init.md +336 -544
- package/dist/agents/plugins/claude/plugin/commands/codemie-subagents.md +232 -503
- package/dist/agents/plugins/claude/plugin/commands/memory-add.md +311 -30
- package/dist/agents/plugins/claude/plugin/commands/memory-refresh.md +218 -39
- package/dist/agents/plugins/claude/plugin/hooks/hooks.json +11 -0
- package/dist/agents/plugins/gemini/extension/gemini-extension.json +1 -1
- package/dist/agents/plugins/gemini/extension/hooks/hooks.json +12 -0
- package/dist/agents/plugins/gemini/gemini.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/gemini/gemini.plugin.js +2 -4
- package/dist/agents/plugins/gemini/gemini.plugin.js.map +1 -1
- package/dist/agents/plugins/opencode/index.d.ts +8 -0
- package/dist/agents/plugins/opencode/index.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/index.js +12 -0
- package/dist/agents/plugins/opencode/index.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode-message-types.d.ts +207 -0
- package/dist/agents/plugins/opencode/opencode-message-types.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode-message-types.js +59 -0
- package/dist/agents/plugins/opencode/opencode-message-types.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode-model-configs.d.ts +65 -0
- package/dist/agents/plugins/opencode/opencode-model-configs.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode-model-configs.js +184 -0
- package/dist/agents/plugins/opencode/opencode-model-configs.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode.paths.d.ts +62 -0
- package/dist/agents/plugins/opencode/opencode.paths.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode.paths.js +148 -0
- package/dist/agents/plugins/opencode/opencode.paths.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode.plugin.d.ts +35 -0
- package/dist/agents/plugins/opencode/opencode.plugin.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode.plugin.js +338 -0
- package/dist/agents/plugins/opencode/opencode.plugin.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode.session.d.ts +77 -0
- package/dist/agents/plugins/opencode/opencode.session.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode.session.js +424 -0
- package/dist/agents/plugins/opencode/opencode.session.js.map +1 -0
- package/dist/agents/plugins/opencode/opencode.storage-utils.d.ts +25 -0
- package/dist/agents/plugins/opencode/opencode.storage-utils.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode.storage-utils.js +96 -0
- package/dist/agents/plugins/opencode/opencode.storage-utils.js.map +1 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.conversations-processor.d.ts +30 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.conversations-processor.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.conversations-processor.js +116 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.conversations-processor.js.map +1 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts +102 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js +584 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js.map +1 -0
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +2 -0
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/doctor/checks/AgentsCheck.d.ts +5 -0
- package/dist/cli/commands/doctor/checks/AgentsCheck.d.ts.map +1 -1
- package/dist/cli/commands/doctor/checks/AgentsCheck.js +29 -0
- package/dist/cli/commands/doctor/checks/AgentsCheck.js.map +1 -1
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +63 -6
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +86 -7
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/opencode-metrics.d.ts +13 -0
- package/dist/cli/commands/opencode-metrics.d.ts.map +1 -0
- package/dist/cli/commands/opencode-metrics.js +200 -0
- package/dist/cli/commands/opencode-metrics.js.map +1 -0
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +113 -0
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/skill.d.ts +6 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +196 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +34 -6
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/migrations/003-remove-hooks-node.migration.d.ts +22 -0
- package/dist/migrations/003-remove-hooks-node.migration.d.ts.map +1 -0
- package/dist/migrations/003-remove-hooks-node.migration.js +103 -0
- package/dist/migrations/003-remove-hooks-node.migration.js.map +1 -0
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +1 -1
- package/dist/migrations/index.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.d.ts +3 -2
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.d.ts.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.js +6 -2
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-api-client.js.map +1 -1
- package/dist/providers/plugins/sso/sso.http-client.js +2 -2
- package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.js +14 -10
- package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
- package/dist/skills/core/SkillDiscovery.d.ts +83 -0
- package/dist/skills/core/SkillDiscovery.d.ts.map +1 -0
- package/dist/skills/core/SkillDiscovery.js +237 -0
- package/dist/skills/core/SkillDiscovery.js.map +1 -0
- package/dist/skills/core/SkillManager.d.ts +86 -0
- package/dist/skills/core/SkillManager.d.ts.map +1 -0
- package/dist/skills/core/SkillManager.js +155 -0
- package/dist/skills/core/SkillManager.js.map +1 -0
- package/dist/skills/core/types.d.ts +120 -0
- package/dist/skills/core/types.d.ts.map +1 -0
- package/dist/skills/core/types.js +20 -0
- package/dist/skills/core/types.js.map +1 -0
- package/dist/skills/index.d.ts +12 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +12 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/utils/content-loader.d.ts +25 -0
- package/dist/skills/utils/content-loader.d.ts.map +1 -0
- package/dist/skills/utils/content-loader.js +161 -0
- package/dist/skills/utils/content-loader.js.map +1 -0
- package/dist/skills/utils/frontmatter.d.ts +60 -0
- package/dist/skills/utils/frontmatter.d.ts.map +1 -0
- package/dist/skills/utils/frontmatter.js +114 -0
- package/dist/skills/utils/frontmatter.js.map +1 -0
- package/dist/skills/utils/pattern-matcher.d.ts +60 -0
- package/dist/skills/utils/pattern-matcher.d.ts.map +1 -0
- package/dist/skills/utils/pattern-matcher.js +97 -0
- package/dist/skills/utils/pattern-matcher.js.map +1 -0
- package/dist/utils/exec.d.ts.map +1 -1
- package/dist/utils/exec.js +11 -1
- package/dist/utils/exec.js.map +1 -1
- package/dist/utils/installation-detector.d.ts +22 -0
- package/dist/utils/installation-detector.d.ts.map +1 -0
- package/dist/utils/installation-detector.js +49 -0
- package/dist/utils/installation-detector.js.map +1 -0
- package/dist/utils/native-installer.d.ts +49 -0
- package/dist/utils/native-installer.d.ts.map +1 -0
- package/dist/utils/native-installer.js +194 -0
- package/dist/utils/native-installer.js.map +1 -0
- package/dist/utils/version-utils.d.ts +50 -0
- package/dist/utils/version-utils.d.ts.map +1 -0
- package/dist/utils/version-utils.js +92 -0
- package/dist/utils/version-utils.js.map +1 -0
- package/package.json +5 -2
- package/scripts/copy-mr-skill-to-global.ts +252 -0
- package/scripts/demo-hooks.sh +125 -0
- package/scripts/test-hooks.sh +196 -0
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/INDEX.md +0 -205
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/TEMPLATE_SIZES.md +0 -74
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/architecture/layered-architecture.md.template +0 -143
- package/dist/agents/plugins/claude/plugin/claude-templates/templates/guides/architecture/project-structure.md.template +0 -127
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pattern matcher for skill invocation detection
|
|
3
|
+
*
|
|
4
|
+
* Detects /skill-name patterns in user messages and extracts skill names.
|
|
5
|
+
* Excludes URLs and built-in CLI commands.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Built-in CLI commands that should NOT be treated as skills
|
|
9
|
+
*/
|
|
10
|
+
const BUILT_IN_COMMANDS = new Set([
|
|
11
|
+
'help',
|
|
12
|
+
'clear',
|
|
13
|
+
'exit',
|
|
14
|
+
'quit',
|
|
15
|
+
'stats',
|
|
16
|
+
'todos',
|
|
17
|
+
'config',
|
|
18
|
+
'health',
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Regex pattern for skill invocation
|
|
22
|
+
*
|
|
23
|
+
* Matches: /skill-name with optional arguments
|
|
24
|
+
* Excludes: URLs (negative lookbehind for : or alphanumeric before /)
|
|
25
|
+
* Format: /[a-z][a-z0-9-]{0,49} (lowercase, alphanumeric + hyphens, 1-50 chars)
|
|
26
|
+
*/
|
|
27
|
+
const SKILL_PATTERN = /(?<![:\w])\/([a-z][a-z0-9-]{0,49})(?:\s+([^\n/]+))?/g;
|
|
28
|
+
/**
|
|
29
|
+
* Extract skill patterns from a user message
|
|
30
|
+
*
|
|
31
|
+
* @param message - User message to scan
|
|
32
|
+
* @returns Pattern match result with detected skills
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const result = extractSkillPatterns('/mr');
|
|
37
|
+
* // result.patterns = [{ name: 'mr', position: 0, raw: '/mr' }]
|
|
38
|
+
*
|
|
39
|
+
* const result2 = extractSkillPatterns('ensure you can /commit this');
|
|
40
|
+
* // result2.patterns = [{ name: 'commit', position: 15, args: 'this', raw: '/commit this' }]
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export function extractSkillPatterns(message) {
|
|
44
|
+
const patterns = [];
|
|
45
|
+
const seenNames = new Set();
|
|
46
|
+
// Reset regex state
|
|
47
|
+
SKILL_PATTERN.lastIndex = 0;
|
|
48
|
+
let match;
|
|
49
|
+
while ((match = SKILL_PATTERN.exec(message)) !== null) {
|
|
50
|
+
const [fullMatch, skillName, args] = match;
|
|
51
|
+
const position = match.index;
|
|
52
|
+
// Skip if this is part of a URL
|
|
53
|
+
// Check if there's http:// or https:// within the last 100 chars before this position
|
|
54
|
+
const lookback = Math.min(100, position);
|
|
55
|
+
const beforeMatch = message.slice(position - lookback, position);
|
|
56
|
+
// If we find a protocol and no whitespace between it and this slash, it's part of a URL
|
|
57
|
+
if (/https?:\/\/[^\s]*$/.test(beforeMatch)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// Skip built-in commands
|
|
61
|
+
if (BUILT_IN_COMMANDS.has(skillName)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// Deduplicate by skill name (keep first occurrence)
|
|
65
|
+
if (seenNames.has(skillName)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
seenNames.add(skillName);
|
|
69
|
+
patterns.push({
|
|
70
|
+
name: skillName,
|
|
71
|
+
position,
|
|
72
|
+
args: args?.trim(),
|
|
73
|
+
raw: fullMatch,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
patterns,
|
|
78
|
+
originalMessage: message,
|
|
79
|
+
hasPatterns: patterns.length > 0,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate a skill name
|
|
84
|
+
*
|
|
85
|
+
* @param name - Skill name to validate
|
|
86
|
+
* @returns True if valid, false otherwise
|
|
87
|
+
*
|
|
88
|
+
* Rules:
|
|
89
|
+
* - Lowercase letters only
|
|
90
|
+
* - Can include digits and hyphens
|
|
91
|
+
* - Must start with a letter
|
|
92
|
+
* - 1-50 characters
|
|
93
|
+
*/
|
|
94
|
+
export function isValidSkillName(name) {
|
|
95
|
+
return /^[a-z][a-z0-9-]{0,49}$/.test(name);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=pattern-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-matcher.js","sourceRoot":"","sources":["../../../src/skills/utils/pattern-matcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH;;GAEG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,QAAQ;CACT,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,sDAAsD,CAAC;AAE7E;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IAClD,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,oBAAoB;IACpB,aAAa,CAAC,SAAS,GAAG,CAAC,CAAC;IAE5B,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;QAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;QAE7B,gCAAgC;QAChC,sFAAsF;QACtF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACzC,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEjE,wFAAwF;QACxF,IAAI,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3C,SAAS;QACX,CAAC;QAED,yBAAyB;QACzB,IAAI,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACrC,SAAS;QACX,CAAC;QAED,oDAAoD;QACpD,IAAI,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,SAAS;QACX,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEzB,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI,EAAE,SAAS;YACf,QAAQ;YACR,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;YAClB,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,QAAQ;QACR,eAAe,EAAE,OAAO;QACxB,WAAW,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC;KACjC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC"}
|
package/dist/utils/exec.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA2FrB"}
|
package/dist/utils/exec.js
CHANGED
|
@@ -28,7 +28,17 @@ export async function exec(command, args = [], options = {}) {
|
|
|
28
28
|
}
|
|
29
29
|
// Interactive mode: inherit stdio for user prompts
|
|
30
30
|
const stdio = options.interactive ? 'inherit' : 'pipe';
|
|
31
|
-
|
|
31
|
+
// When using shell: true, merge args into command string to avoid DEP0190
|
|
32
|
+
// Node.js deprecation warning: shell mode doesn't escape array arguments, only concatenates them
|
|
33
|
+
let finalCommand = command;
|
|
34
|
+
let finalArgs = args;
|
|
35
|
+
if (useShell && args.length > 0) {
|
|
36
|
+
// Quote arguments that contain spaces or special characters
|
|
37
|
+
const quotedArgs = args.map(arg => arg.includes(' ') || arg.includes('"') ? `"${arg.replace(/"/g, '\\"')}"` : arg);
|
|
38
|
+
finalCommand = `${command} ${quotedArgs.join(' ')}`;
|
|
39
|
+
finalArgs = [];
|
|
40
|
+
}
|
|
41
|
+
const child = spawn(finalCommand, finalArgs, {
|
|
32
42
|
cwd: options.cwd || process.cwd(),
|
|
33
43
|
env: { ...process.env, ...options.env },
|
|
34
44
|
shell: useShell,
|
package/dist/utils/exec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,IAAI,CAAC;AAgBpB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAe,EACf,OAAiB,EAAE,EACnB,UAAuB,EAAE;IAEzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC;QAE5C,mCAAmC;QACnC,6CAA6C;QAC7C,0EAA0E;QAC1E,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,CAAC;QAED,mDAAmD;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAEvD,MAAM,
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,MAAM,IAAI,CAAC;AAgBpB;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAe,EACf,OAAiB,EAAE,EACnB,UAAuB,EAAE;IAEzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,SAAS,GAAG,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,CAAC;QAE5C,mCAAmC;QACnC,6CAA6C;QAC7C,0EAA0E;QAC1E,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,CAAC;QAED,mDAAmD;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAEvD,0EAA0E;QAC1E,iGAAiG;QACjG,IAAI,YAAY,GAAG,OAAO,CAAC;QAC3B,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,IAAI,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,4DAA4D;YAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAChC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAC/E,CAAC;YACF,YAAY,GAAG,GAAG,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,SAAS,GAAG,EAAE,CAAC;QACjB,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,SAAS,EAAE;YAC3C,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;YACjC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;YACvC,KAAK,EAAE,QAAQ;YACf,WAAW,EAAE,SAAS,EAAE,iCAAiC;YACzD,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,SAAS,GAA0B,IAAI,CAAC;QAE5C,6DAA6D;QAC7D,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,IAAI,SAAS,EAAE,CAAC;gBACd,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;QACH,CAAC,CAAC;QAEF,iDAAiD;QACjD,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC,CAAC,CAAC;YAEH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBAChC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,OAAO,EAAE,CAAC;YAEV,MAAM,MAAM,GAAG;gBACb,IAAI,EAAE,IAAI,IAAI,CAAC;gBACf,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;gBACrB,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;aACtB,CAAC;YAEF,qDAAqD;YACrD,oEAAoE;YACpE,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACtC,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,IAAI,EAAE,CAAC,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,iBAAiB;QACjB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,KAAK,CAAC,IAAI,EAAE,CAAC;gBACb,MAAM,CAAC,IAAI,KAAK,CAAC,2BAA2B,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;YACpE,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple installation method detector for external agents
|
|
3
|
+
* Detects whether agents were installed via npm or native installers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Installation method type
|
|
7
|
+
*/
|
|
8
|
+
export type InstallationMethod = 'npm' | 'native' | 'unknown';
|
|
9
|
+
/**
|
|
10
|
+
* Detect if a command was installed via npm by checking its path
|
|
11
|
+
*
|
|
12
|
+
* @param commandName - Command to check (e.g., 'claude')
|
|
13
|
+
* @returns Installation method: 'npm', 'native', or 'unknown'
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const method = await detectInstallationMethod('claude');
|
|
17
|
+
* if (method === 'npm') {
|
|
18
|
+
* console.log('Installed via npm (deprecated)');
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectInstallationMethod(commandName: string): Promise<InstallationMethod>;
|
|
22
|
+
//# sourceMappingURL=installation-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installation-detector.d.ts","sourceRoot":"","sources":["../../src/utils/installation-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiC/F"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple installation method detector for external agents
|
|
3
|
+
* Detects whether agents were installed via npm or native installers
|
|
4
|
+
*/
|
|
5
|
+
import { getCommandPath } from './processes.js';
|
|
6
|
+
/**
|
|
7
|
+
* Detect if a command was installed via npm by checking its path
|
|
8
|
+
*
|
|
9
|
+
* @param commandName - Command to check (e.g., 'claude')
|
|
10
|
+
* @returns Installation method: 'npm', 'native', or 'unknown'
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const method = await detectInstallationMethod('claude');
|
|
14
|
+
* if (method === 'npm') {
|
|
15
|
+
* console.log('Installed via npm (deprecated)');
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
export async function detectInstallationMethod(commandName) {
|
|
19
|
+
try {
|
|
20
|
+
// Get the full path to the command
|
|
21
|
+
const commandPath = await getCommandPath(commandName);
|
|
22
|
+
if (!commandPath) {
|
|
23
|
+
return 'unknown';
|
|
24
|
+
}
|
|
25
|
+
// npm-specific path patterns (cross-platform)
|
|
26
|
+
const npmPatterns = [
|
|
27
|
+
'/node_modules/', // Unix: npm global/local
|
|
28
|
+
'/.nvm/', // Unix: nvm installations
|
|
29
|
+
'/.npm-global/', // Unix: npm custom prefix
|
|
30
|
+
'\\node_modules\\', // Windows: npm global/local
|
|
31
|
+
'\\npm\\', // Windows: npm directories
|
|
32
|
+
'AppData\\npm', // Windows: user npm directory
|
|
33
|
+
'Program Files\\nodejs\\node_modules', // Windows: system npm
|
|
34
|
+
];
|
|
35
|
+
// Check if path contains any npm-specific pattern
|
|
36
|
+
for (const pattern of npmPatterns) {
|
|
37
|
+
if (commandPath.includes(pattern)) {
|
|
38
|
+
return 'npm';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// If not in npm directory, assume native installation
|
|
42
|
+
return 'native';
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// If detection fails, return unknown
|
|
46
|
+
return 'unknown';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=installation-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installation-detector.js","sourceRoot":"","sources":["../../src/utils/installation-detector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAOhD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,WAAmB;IACjE,IAAI,CAAC;QACJ,mCAAmC;QACnC,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;QAEtD,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,8CAA8C;QAC9C,MAAM,WAAW,GAAG;YACnB,gBAAgB,EAAM,yBAAyB;YAC/C,QAAQ,EAAc,0BAA0B;YAChD,eAAe,EAAO,0BAA0B;YAChD,kBAAkB,EAAI,4BAA4B;YAClD,SAAS,EAAa,2BAA2B;YACjD,cAAc,EAAQ,8BAA8B;YACpD,qCAAqC,EAAE,sBAAsB;SAC7D,CAAC;QAEF,kDAAkD;QAClD,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;YACnC,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACnC,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;QAED,sDAAsD;QACtD,OAAO,QAAQ,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACR,qCAAqC;QACrC,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native installer utilities for platform-specific agent installation
|
|
3
|
+
* Used for Claude Code native installation management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Platform-specific installer URLs
|
|
7
|
+
*/
|
|
8
|
+
export interface PlatformInstallerUrls {
|
|
9
|
+
macOS: string;
|
|
10
|
+
windows: string;
|
|
11
|
+
linux: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Native installation options
|
|
15
|
+
*/
|
|
16
|
+
export interface NativeInstallOptions {
|
|
17
|
+
timeout?: number;
|
|
18
|
+
env?: Record<string, string>;
|
|
19
|
+
verifyCommand?: string;
|
|
20
|
+
installFlags?: string[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Native installation result
|
|
24
|
+
*/
|
|
25
|
+
export interface NativeInstallResult {
|
|
26
|
+
success: boolean;
|
|
27
|
+
installedVersion: string | null;
|
|
28
|
+
output: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Install agent using native platform installer
|
|
32
|
+
* Detects platform and executes appropriate installation script
|
|
33
|
+
*
|
|
34
|
+
* @param agentName - Agent name for logging (e.g., 'claude')
|
|
35
|
+
* @param installerUrls - Platform-specific installer URLs
|
|
36
|
+
* @param version - Version to install (e.g., '2.0.30', 'latest', 'stable', or undefined)
|
|
37
|
+
* @param options - Installation options (timeout, env, etc.)
|
|
38
|
+
* @returns Installation result with success status and installed version
|
|
39
|
+
* @throws {AgentInstallationError} If installation fails
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* await installNativeAgent('claude', {
|
|
43
|
+
* macOS: 'https://claude.ai/install.sh',
|
|
44
|
+
* windows: 'https://claude.ai/install.ps1',
|
|
45
|
+
* linux: 'https://claude.ai/install.sh'
|
|
46
|
+
* }, '2.0.30');
|
|
47
|
+
*/
|
|
48
|
+
export declare function installNativeAgent(agentName: string, installerUrls: PlatformInstallerUrls, version?: string, options?: NativeInstallOptions): Promise<NativeInstallResult>;
|
|
49
|
+
//# sourceMappingURL=native-installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-installer.d.ts","sourceRoot":"","sources":["../../src/utils/native-installer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;CACf;AA0HD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,CACvC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,qBAAqB,EACpC,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAuF9B"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native installer utilities for platform-specific agent installation
|
|
3
|
+
* Used for Claude Code native installation management
|
|
4
|
+
*/
|
|
5
|
+
import { exec } from './processes.js';
|
|
6
|
+
import { AgentInstallationError } from './errors.js';
|
|
7
|
+
import { logger } from './logger.js';
|
|
8
|
+
import { sanitizeLogArgs, sanitizeValue } from './security.js';
|
|
9
|
+
import { isValidSemanticVersion } from './version-utils.js';
|
|
10
|
+
/**
|
|
11
|
+
* Detect current platform
|
|
12
|
+
* @returns Platform identifier: 'macOS' | 'windows' | 'linux'
|
|
13
|
+
*/
|
|
14
|
+
function detectPlatform() {
|
|
15
|
+
const platform = process.platform;
|
|
16
|
+
if (platform === 'darwin') {
|
|
17
|
+
return 'macOS';
|
|
18
|
+
}
|
|
19
|
+
else if (platform === 'win32') {
|
|
20
|
+
return 'windows';
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
// Assume Linux for all other platforms (linux, freebsd, etc.)
|
|
24
|
+
return 'linux';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build installer command for the detected platform
|
|
29
|
+
*
|
|
30
|
+
* @param agentName - Agent name for error messages
|
|
31
|
+
* @param installerUrls - Platform-specific installer URLs
|
|
32
|
+
* @param version - Optional version to install
|
|
33
|
+
* @param platform - Detected platform
|
|
34
|
+
* @param installFlags - Additional flags to pass to installer (e.g., ['--force'])
|
|
35
|
+
* @returns Command string to execute
|
|
36
|
+
*/
|
|
37
|
+
function buildInstallerCommand(agentName, installerUrls, version, platform, installFlags) {
|
|
38
|
+
// Validate installer URLs are HTTPS (security requirement)
|
|
39
|
+
const url = installerUrls[platform];
|
|
40
|
+
if (!url.startsWith('https://')) {
|
|
41
|
+
throw new AgentInstallationError(agentName, `Installer URL must use HTTPS: ${url}`);
|
|
42
|
+
}
|
|
43
|
+
// SECURITY: Validate version string to prevent command injection
|
|
44
|
+
// Only allow semantic versions or special channels (latest, stable)
|
|
45
|
+
if (version) {
|
|
46
|
+
const allowedChannels = ['latest', 'stable'];
|
|
47
|
+
const isValidChannel = allowedChannels.includes(version.toLowerCase());
|
|
48
|
+
const isValidVersion = isValidSemanticVersion(version);
|
|
49
|
+
if (!isValidChannel && !isValidVersion) {
|
|
50
|
+
throw new AgentInstallationError(agentName, `Invalid version format: "${version}". Expected semantic version (e.g., "2.0.30"), "latest", or "stable".`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// SECURITY: Validate install flags against whitelist
|
|
54
|
+
// Only allow known safe flags to prevent command injection
|
|
55
|
+
const allowedFlags = ['--force', '--silent', '--yes', '-y', '-f', '--no-progress'];
|
|
56
|
+
if (installFlags && installFlags.length > 0) {
|
|
57
|
+
for (const flag of installFlags) {
|
|
58
|
+
if (!allowedFlags.includes(flag)) {
|
|
59
|
+
throw new AgentInstallationError(agentName, `Invalid install flag: "${flag}". Allowed flags: ${allowedFlags.join(', ')}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Build platform-specific command
|
|
64
|
+
if (platform === 'windows') {
|
|
65
|
+
// Windows CMD command (simpler and more universal than PowerShell)
|
|
66
|
+
// Download install.cmd, execute with args, then delete
|
|
67
|
+
const versionArg = version ? ` ${version}` : '';
|
|
68
|
+
const flagsArg = installFlags && installFlags.length > 0 ? ` ${installFlags.join(' ')}` : '';
|
|
69
|
+
return `curl -fsSL ${url} -o install.cmd && install.cmd${versionArg}${flagsArg} && del install.cmd`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// macOS/Linux shell script command
|
|
73
|
+
const versionArg = version ? ` -s -- ${version}` : '';
|
|
74
|
+
const scriptFlags = installFlags && installFlags.length > 0 ? ` ${installFlags.join(' ')}` : '';
|
|
75
|
+
return `curl -fsSL ${url} | bash${versionArg}${scriptFlags}`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verify installation by running the verify command
|
|
80
|
+
*
|
|
81
|
+
* @param verifyCommand - Command to verify (e.g., 'claude')
|
|
82
|
+
* @returns Installed version string or null if verification failed
|
|
83
|
+
*/
|
|
84
|
+
async function verifyInstallation(verifyCommand) {
|
|
85
|
+
try {
|
|
86
|
+
// Run version check command (e.g., 'claude --version')
|
|
87
|
+
const result = await exec(verifyCommand, ['--version'], {
|
|
88
|
+
timeout: 5000, // 5 second timeout for version check
|
|
89
|
+
});
|
|
90
|
+
if (result.code === 0 && result.stdout) {
|
|
91
|
+
// Parse version from output (usually first line, may have 'v' prefix)
|
|
92
|
+
const versionMatch = result.stdout.trim().match(/v?(\d+\.\d+\.\d+)/);
|
|
93
|
+
if (versionMatch) {
|
|
94
|
+
return versionMatch[1];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger.debug('Installation verification failed', ...sanitizeLogArgs({ error }));
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Install agent using native platform installer
|
|
106
|
+
* Detects platform and executes appropriate installation script
|
|
107
|
+
*
|
|
108
|
+
* @param agentName - Agent name for logging (e.g., 'claude')
|
|
109
|
+
* @param installerUrls - Platform-specific installer URLs
|
|
110
|
+
* @param version - Version to install (e.g., '2.0.30', 'latest', 'stable', or undefined)
|
|
111
|
+
* @param options - Installation options (timeout, env, etc.)
|
|
112
|
+
* @returns Installation result with success status and installed version
|
|
113
|
+
* @throws {AgentInstallationError} If installation fails
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* await installNativeAgent('claude', {
|
|
117
|
+
* macOS: 'https://claude.ai/install.sh',
|
|
118
|
+
* windows: 'https://claude.ai/install.ps1',
|
|
119
|
+
* linux: 'https://claude.ai/install.sh'
|
|
120
|
+
* }, '2.0.30');
|
|
121
|
+
*/
|
|
122
|
+
export async function installNativeAgent(agentName, installerUrls, version, options) {
|
|
123
|
+
const platform = detectPlatform();
|
|
124
|
+
const timeout = options?.timeout || 120000; // 2 minute default timeout
|
|
125
|
+
logger.debug('Starting native agent installation', {
|
|
126
|
+
agentName,
|
|
127
|
+
platform,
|
|
128
|
+
version: version || 'latest',
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
// Build installer command
|
|
132
|
+
const command = buildInstallerCommand(agentName, installerUrls, version, platform, options?.installFlags);
|
|
133
|
+
logger.debug('Executing installer command', {
|
|
134
|
+
agentName,
|
|
135
|
+
platform,
|
|
136
|
+
// Don't log full command (may contain sensitive URLs)
|
|
137
|
+
});
|
|
138
|
+
// Execute installer
|
|
139
|
+
const result = await exec(command, [], {
|
|
140
|
+
timeout,
|
|
141
|
+
env: options?.env,
|
|
142
|
+
shell: true, // Required for piped commands (curl | bash)
|
|
143
|
+
});
|
|
144
|
+
// Check if installation succeeded
|
|
145
|
+
if (result.code !== 0) {
|
|
146
|
+
// SECURITY: Sanitize output before including in error message
|
|
147
|
+
// Installer scripts might echo sensitive environment variables
|
|
148
|
+
const sanitizedOutput = sanitizeValue(result.stderr || result.stdout);
|
|
149
|
+
throw new AgentInstallationError(agentName, `Installer exited with code ${result.code}. Output: ${sanitizedOutput}`);
|
|
150
|
+
}
|
|
151
|
+
logger.debug('Installer completed successfully', {
|
|
152
|
+
agentName,
|
|
153
|
+
platform,
|
|
154
|
+
});
|
|
155
|
+
// Verify installation if verify command provided
|
|
156
|
+
let installedVersion = null;
|
|
157
|
+
if (options?.verifyCommand) {
|
|
158
|
+
logger.debug('Verifying installation', {
|
|
159
|
+
agentName,
|
|
160
|
+
verifyCommand: options.verifyCommand,
|
|
161
|
+
});
|
|
162
|
+
installedVersion = await verifyInstallation(options.verifyCommand);
|
|
163
|
+
if (!installedVersion) {
|
|
164
|
+
logger.warn('Installation verification failed', {
|
|
165
|
+
agentName,
|
|
166
|
+
verifyCommand: options.verifyCommand,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
logger.debug('Installation verified', {
|
|
171
|
+
agentName,
|
|
172
|
+
installedVersion,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// SECURITY: Sanitize output before returning
|
|
177
|
+
// Prevents exposure of sensitive data in logs or UI
|
|
178
|
+
const sanitizedOutput = sanitizeValue(result.stdout || result.stderr || '');
|
|
179
|
+
return {
|
|
180
|
+
success: true,
|
|
181
|
+
installedVersion,
|
|
182
|
+
output: sanitizedOutput,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
// If it's already an AgentInstallationError, rethrow
|
|
187
|
+
if (error instanceof AgentInstallationError) {
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
// Wrap other errors
|
|
191
|
+
throw new AgentInstallationError(agentName, `Failed to install: ${error instanceof Error ? error.message : String(error)}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=native-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-installer.js","sourceRoot":"","sources":["../../src/utils/native-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version comparison utilities for semantic versioning
|
|
3
|
+
* Used for Claude Code version management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Semantic version components
|
|
7
|
+
*/
|
|
8
|
+
export interface SemanticVersion {
|
|
9
|
+
major: number;
|
|
10
|
+
minor: number;
|
|
11
|
+
patch: number;
|
|
12
|
+
raw: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse semantic version string into comparable components
|
|
16
|
+
*
|
|
17
|
+
* @param version - Version string (e.g., '2.0.30')
|
|
18
|
+
* @returns Version components { major, minor, patch, raw }
|
|
19
|
+
* @throws {Error} If version string is invalid
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* parseSemanticVersion('2.0.30') // Returns { major: 2, minor: 0, patch: 30, raw: '2.0.30' }
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseSemanticVersion(version: string): SemanticVersion;
|
|
25
|
+
/**
|
|
26
|
+
* Check if version string is valid semantic version
|
|
27
|
+
*
|
|
28
|
+
* @param version - Version string to validate
|
|
29
|
+
* @returns true if valid semantic version
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* isValidSemanticVersion('2.0.30') // true
|
|
33
|
+
* isValidSemanticVersion('v2.0.30') // true
|
|
34
|
+
* isValidSemanticVersion('invalid') // false
|
|
35
|
+
*/
|
|
36
|
+
export declare function isValidSemanticVersion(version: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Compare two semantic versions
|
|
39
|
+
*
|
|
40
|
+
* @param version1 - First version string (e.g., '2.0.30')
|
|
41
|
+
* @param version2 - Second version string (e.g., '2.0.45')
|
|
42
|
+
* @returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* compareVersions('2.0.30', '2.0.45') // Returns -1
|
|
46
|
+
* compareVersions('2.0.45', '2.0.30') // Returns 1
|
|
47
|
+
* compareVersions('2.0.30', '2.0.30') // Returns 0
|
|
48
|
+
*/
|
|
49
|
+
export declare function compareVersions(version1: string, version2: string): number;
|
|
50
|
+
//# sourceMappingURL=version-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-utils.d.ts","sourceRoot":"","sources":["../../src/utils/version-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAmBrE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAO/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoC1E"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version comparison utilities for semantic versioning
|
|
3
|
+
* Used for Claude Code version management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Parse semantic version string into comparable components
|
|
7
|
+
*
|
|
8
|
+
* @param version - Version string (e.g., '2.0.30')
|
|
9
|
+
* @returns Version components { major, minor, patch, raw }
|
|
10
|
+
* @throws {Error} If version string is invalid
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* parseSemanticVersion('2.0.30') // Returns { major: 2, minor: 0, patch: 30, raw: '2.0.30' }
|
|
14
|
+
*/
|
|
15
|
+
export function parseSemanticVersion(version) {
|
|
16
|
+
// Remove 'v' prefix if present
|
|
17
|
+
const cleanVersion = version.trim().replace(/^v/, '');
|
|
18
|
+
// Match semantic version pattern: major.minor.patch
|
|
19
|
+
const match = cleanVersion.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
20
|
+
if (!match) {
|
|
21
|
+
throw new Error(`Invalid semantic version format: "${version}". Expected format: major.minor.patch (e.g., "2.0.30")`);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
major: parseInt(match[1], 10),
|
|
25
|
+
minor: parseInt(match[2], 10),
|
|
26
|
+
patch: parseInt(match[3], 10),
|
|
27
|
+
raw: version,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if version string is valid semantic version
|
|
32
|
+
*
|
|
33
|
+
* @param version - Version string to validate
|
|
34
|
+
* @returns true if valid semantic version
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* isValidSemanticVersion('2.0.30') // true
|
|
38
|
+
* isValidSemanticVersion('v2.0.30') // true
|
|
39
|
+
* isValidSemanticVersion('invalid') // false
|
|
40
|
+
*/
|
|
41
|
+
export function isValidSemanticVersion(version) {
|
|
42
|
+
try {
|
|
43
|
+
parseSemanticVersion(version);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Compare two semantic versions
|
|
52
|
+
*
|
|
53
|
+
* @param version1 - First version string (e.g., '2.0.30')
|
|
54
|
+
* @param version2 - Second version string (e.g., '2.0.45')
|
|
55
|
+
* @returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* compareVersions('2.0.30', '2.0.45') // Returns -1
|
|
59
|
+
* compareVersions('2.0.45', '2.0.30') // Returns 1
|
|
60
|
+
* compareVersions('2.0.30', '2.0.30') // Returns 0
|
|
61
|
+
*/
|
|
62
|
+
export function compareVersions(version1, version2) {
|
|
63
|
+
// Handle special channel names (treat as highest version)
|
|
64
|
+
const isSpecialChannel = (v) => ['latest', 'stable'].includes(v.toLowerCase());
|
|
65
|
+
if (isSpecialChannel(version1) && isSpecialChannel(version2)) {
|
|
66
|
+
return 0; // Both special channels, consider equal
|
|
67
|
+
}
|
|
68
|
+
if (isSpecialChannel(version1)) {
|
|
69
|
+
return 1; // v1 is latest/stable, higher than any specific version
|
|
70
|
+
}
|
|
71
|
+
if (isSpecialChannel(version2)) {
|
|
72
|
+
return -1; // v2 is latest/stable, higher than v1
|
|
73
|
+
}
|
|
74
|
+
// Parse both versions
|
|
75
|
+
const v1 = parseSemanticVersion(version1);
|
|
76
|
+
const v2 = parseSemanticVersion(version2);
|
|
77
|
+
// Compare major version
|
|
78
|
+
if (v1.major !== v2.major) {
|
|
79
|
+
return v1.major < v2.major ? -1 : 1;
|
|
80
|
+
}
|
|
81
|
+
// Compare minor version
|
|
82
|
+
if (v1.minor !== v2.minor) {
|
|
83
|
+
return v1.minor < v2.minor ? -1 : 1;
|
|
84
|
+
}
|
|
85
|
+
// Compare patch version
|
|
86
|
+
if (v1.patch !== v2.patch) {
|
|
87
|
+
return v1.patch < v2.patch ? -1 : 1;
|
|
88
|
+
}
|
|
89
|
+
// Versions are equal
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=version-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version-utils.js","sourceRoot":"","sources":["../../src/utils/version-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAe;IACnD,+BAA+B;IAC/B,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAEtD,oDAAoD;IACpD,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAE1D,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACd,qCAAqC,OAAO,wDAAwD,CACpG,CAAC;IACH,CAAC;IAED,OAAO;QACN,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7B,GAAG,EAAE,OAAO;KACZ,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACrD,IAAI,CAAC;QACJ,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,QAAgB;IACjE,0DAA0D;IAC1D,MAAM,gBAAgB,GAAG,CAAC,CAAS,EAAW,EAAE,CAC/C,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAEhD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,OAAO,CAAC,CAAC,CAAC,wCAAwC;IACnD,CAAC;IACD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,CAAC,CAAC,wDAAwD;IACnE,CAAC;IACD,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,CAAC,CAAC,CAAC,sCAAsC;IAClD,CAAC;IAED,sBAAsB;IACtB,MAAM,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAE1C,wBAAwB;IACxB,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,wBAAwB;IACxB,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,wBAAwB;IACxB,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC;IAED,qBAAqB;IACrB,OAAO,CAAC,CAAC;AACV,CAAC"}
|