@orchagent/cli 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/agents-md.js +3 -2
- package/dist/adapters/claude-code.js +4 -26
- package/dist/adapters/cursor.js +3 -11
- package/dist/adapters/index.js +5 -1
- package/dist/adapters/utils.js +35 -0
- package/dist/commands/config.js +10 -3
- package/dist/commands/formats.js +4 -6
- package/dist/commands/install.js +9 -22
- package/dist/commands/skill.js +21 -16
- package/dist/commands/update.js +2 -16
- package/dist/lib/agents-md-utils.js +34 -0
- package/dist/lib/api.js +8 -0
- package/dist/lib/config.js +59 -8
- package/dist/lib/string-utils.js +12 -0
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ exports.agentsMdAdapter = {
|
|
|
6
6
|
name: 'AGENTS.md (Universal)',
|
|
7
7
|
version: '1.0.0',
|
|
8
8
|
formatVersion: '1.0',
|
|
9
|
-
|
|
9
|
+
supportedTypes: ['prompt', 'skill'],
|
|
10
10
|
installPaths: [
|
|
11
11
|
{
|
|
12
12
|
scope: 'project',
|
|
@@ -29,7 +29,8 @@ exports.agentsMdAdapter = {
|
|
|
29
29
|
return { canConvert: true, warnings, errors };
|
|
30
30
|
},
|
|
31
31
|
convert(agent) {
|
|
32
|
-
const
|
|
32
|
+
const orgSlug = agent.org_slug || 'unknown';
|
|
33
|
+
const agentRef = `${orgSlug}/${agent.name}`;
|
|
33
34
|
const description = agent.description || '';
|
|
34
35
|
// Use orchagent markers for managed section
|
|
35
36
|
const content = `<!-- orchagent:${agentRef} -->
|
|
@@ -4,36 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.claudeCodeAdapter = void 0;
|
|
7
|
+
const utils_1 = require("./utils");
|
|
7
8
|
const yaml_1 = __importDefault(require("yaml"));
|
|
8
|
-
// Map Anthropic model names to Claude Code aliases
|
|
9
|
-
function mapModelToAlias(model) {
|
|
10
|
-
if (!model)
|
|
11
|
-
return 'inherit';
|
|
12
|
-
const lower = model.toLowerCase();
|
|
13
|
-
if (lower.includes('opus'))
|
|
14
|
-
return 'opus';
|
|
15
|
-
if (lower.includes('haiku'))
|
|
16
|
-
return 'haiku';
|
|
17
|
-
// Default to sonnet for any Claude model
|
|
18
|
-
if (lower.includes('claude') || lower.includes('sonnet'))
|
|
19
|
-
return 'sonnet';
|
|
20
|
-
return 'inherit';
|
|
21
|
-
}
|
|
22
|
-
// Convert agent name to valid Claude Code name (lowercase + hyphens)
|
|
23
|
-
function normalizeAgentName(name) {
|
|
24
|
-
const normalized = name
|
|
25
|
-
.toLowerCase()
|
|
26
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
27
|
-
.replace(/-+/g, '-')
|
|
28
|
-
.replace(/^-|-$/g, '');
|
|
29
|
-
return normalized || 'agent'; // Fallback if empty
|
|
30
|
-
}
|
|
31
9
|
exports.claudeCodeAdapter = {
|
|
32
10
|
id: 'claude-code',
|
|
33
11
|
name: 'Claude Code Sub-Agent',
|
|
34
12
|
version: '1.0.0',
|
|
35
13
|
formatVersion: '2026-01',
|
|
36
|
-
|
|
14
|
+
supportedTypes: ['prompt', 'skill'],
|
|
37
15
|
installPaths: [
|
|
38
16
|
{
|
|
39
17
|
scope: 'user',
|
|
@@ -69,7 +47,7 @@ exports.claudeCodeAdapter = {
|
|
|
69
47
|
return { canConvert: true, warnings, errors };
|
|
70
48
|
},
|
|
71
49
|
convert(agent) {
|
|
72
|
-
const normalizedName = normalizeAgentName(agent.name);
|
|
50
|
+
const normalizedName = (0, utils_1.normalizeAgentName)(agent.name);
|
|
73
51
|
// Build frontmatter
|
|
74
52
|
const frontmatter = {
|
|
75
53
|
name: normalizedName,
|
|
@@ -78,7 +56,7 @@ exports.claudeCodeAdapter = {
|
|
|
78
56
|
};
|
|
79
57
|
// Map model if specified
|
|
80
58
|
if (agent.default_models?.anthropic) {
|
|
81
|
-
const modelAlias = mapModelToAlias(agent.default_models.anthropic);
|
|
59
|
+
const modelAlias = (0, utils_1.mapModelToAlias)(agent.default_models.anthropic);
|
|
82
60
|
if (modelAlias !== 'inherit') {
|
|
83
61
|
frontmatter.model = modelAlias;
|
|
84
62
|
}
|
package/dist/adapters/cursor.js
CHANGED
|
@@ -1,21 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cursorAdapter = void 0;
|
|
4
|
-
|
|
5
|
-
function normalizeAgentName(name) {
|
|
6
|
-
const normalized = name
|
|
7
|
-
.toLowerCase()
|
|
8
|
-
.replace(/[^a-z0-9-]/g, '-')
|
|
9
|
-
.replace(/-+/g, '-')
|
|
10
|
-
.replace(/^-|-$/g, '');
|
|
11
|
-
return normalized || 'agent'; // Fallback if empty
|
|
12
|
-
}
|
|
4
|
+
const utils_1 = require("./utils");
|
|
13
5
|
exports.cursorAdapter = {
|
|
14
6
|
id: 'cursor',
|
|
15
7
|
name: 'Cursor Rules',
|
|
16
8
|
version: '1.0.0',
|
|
17
9
|
formatVersion: '2026-01',
|
|
18
|
-
|
|
10
|
+
supportedTypes: ['prompt', 'skill'],
|
|
19
11
|
installPaths: [
|
|
20
12
|
{
|
|
21
13
|
scope: 'project',
|
|
@@ -44,7 +36,7 @@ exports.cursorAdapter = {
|
|
|
44
36
|
return { canConvert: true, warnings, errors };
|
|
45
37
|
},
|
|
46
38
|
convert(agent) {
|
|
47
|
-
const normalizedName = normalizeAgentName(agent.name);
|
|
39
|
+
const normalizedName = (0, utils_1.normalizeAgentName)(agent.name);
|
|
48
40
|
const description = agent.description || `Rules from ${agent.name}`;
|
|
49
41
|
// Cursor .mdc format
|
|
50
42
|
const content = `---
|
package/dist/adapters/index.js
CHANGED
|
@@ -14,9 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.agentsMdAdapter = exports.cursorAdapter = exports.claudeCodeAdapter = exports.adapterRegistry = exports.AdapterRegistry = void 0;
|
|
17
|
+
exports.agentsMdAdapter = exports.cursorAdapter = exports.claudeCodeAdapter = exports.adapterRegistry = exports.AdapterRegistry = exports.mapModelToAlias = exports.normalizeAgentName = void 0;
|
|
18
18
|
// Export types
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
|
+
// Export utilities
|
|
21
|
+
var utils_1 = require("./utils");
|
|
22
|
+
Object.defineProperty(exports, "normalizeAgentName", { enumerable: true, get: function () { return utils_1.normalizeAgentName; } });
|
|
23
|
+
Object.defineProperty(exports, "mapModelToAlias", { enumerable: true, get: function () { return utils_1.mapModelToAlias; } });
|
|
20
24
|
// Export registry
|
|
21
25
|
const registry_1 = require("./registry");
|
|
22
26
|
var registry_2 = require("./registry");
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared utilities for format adapters
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeAgentName = normalizeAgentName;
|
|
7
|
+
exports.mapModelToAlias = mapModelToAlias;
|
|
8
|
+
/**
|
|
9
|
+
* Convert agent name to valid format (lowercase + hyphens only).
|
|
10
|
+
* Used for filenames and identifiers across all adapters.
|
|
11
|
+
*/
|
|
12
|
+
function normalizeAgentName(name) {
|
|
13
|
+
const normalized = name
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
16
|
+
.replace(/-+/g, '-')
|
|
17
|
+
.replace(/^-|-$/g, '');
|
|
18
|
+
return normalized || 'agent'; // Fallback if empty
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Map Anthropic model names to Claude Code aliases.
|
|
22
|
+
*/
|
|
23
|
+
function mapModelToAlias(model) {
|
|
24
|
+
if (!model)
|
|
25
|
+
return 'inherit';
|
|
26
|
+
const lower = model.toLowerCase();
|
|
27
|
+
if (lower.includes('opus'))
|
|
28
|
+
return 'opus';
|
|
29
|
+
if (lower.includes('haiku'))
|
|
30
|
+
return 'haiku';
|
|
31
|
+
// Default to sonnet for any Claude model
|
|
32
|
+
if (lower.includes('claude') || lower.includes('sonnet'))
|
|
33
|
+
return 'sonnet';
|
|
34
|
+
return 'inherit';
|
|
35
|
+
}
|
package/dist/commands/config.js
CHANGED
|
@@ -4,6 +4,12 @@ exports.registerConfigCommand = registerConfigCommand;
|
|
|
4
4
|
const config_1 = require("../lib/config");
|
|
5
5
|
const errors_1 = require("../lib/errors");
|
|
6
6
|
const adapters_1 = require("../adapters");
|
|
7
|
+
// Valid formats: union of skill directory formats and agent export adapters
|
|
8
|
+
function getAllValidFormatIds() {
|
|
9
|
+
const adapterIds = adapters_1.adapterRegistry.getIds();
|
|
10
|
+
const skillFormatIds = [...config_1.VALID_FORMAT_IDS];
|
|
11
|
+
return [...new Set([...adapterIds, ...skillFormatIds])];
|
|
12
|
+
}
|
|
7
13
|
const SUPPORTED_KEYS = ['default-format'];
|
|
8
14
|
function isValidKey(key) {
|
|
9
15
|
return SUPPORTED_KEYS.includes(key);
|
|
@@ -14,8 +20,8 @@ async function setConfigValue(key, value) {
|
|
|
14
20
|
}
|
|
15
21
|
if (key === 'default-format') {
|
|
16
22
|
const formats = value.split(',').map((f) => f.trim()).filter(Boolean);
|
|
17
|
-
// Validate
|
|
18
|
-
const validFormatIds =
|
|
23
|
+
// Validate format IDs against union of skill formats and agent adapters
|
|
24
|
+
const validFormatIds = getAllValidFormatIds();
|
|
19
25
|
const invalidFormats = formats.filter((f) => !validFormatIds.includes(f));
|
|
20
26
|
if (invalidFormats.length > 0) {
|
|
21
27
|
throw new errors_1.CliError(`Invalid format ID(s): ${invalidFormats.join(', ')}. Valid formats: ${validFormatIds.join(', ')}`);
|
|
@@ -29,7 +35,8 @@ async function getConfigValue(key) {
|
|
|
29
35
|
throw new errors_1.CliError(`Unknown config key: ${key}. Supported keys: ${SUPPORTED_KEYS.join(', ')}`);
|
|
30
36
|
}
|
|
31
37
|
if (key === 'default-format') {
|
|
32
|
-
const
|
|
38
|
+
const resolved = await (0, config_1.getResolvedConfig)();
|
|
39
|
+
const formats = await (0, config_1.getDefaultFormats)(resolved);
|
|
33
40
|
if (formats.length === 0) {
|
|
34
41
|
process.stdout.write('(not set)\n');
|
|
35
42
|
}
|
package/dist/commands/formats.js
CHANGED
|
@@ -19,7 +19,7 @@ function registerFormatsCommand(program) {
|
|
|
19
19
|
name: a.name,
|
|
20
20
|
version: a.version,
|
|
21
21
|
formatVersion: a.formatVersion,
|
|
22
|
-
|
|
22
|
+
supportedTypes: a.supportedTypes,
|
|
23
23
|
installPaths: a.installPaths,
|
|
24
24
|
}));
|
|
25
25
|
process.stdout.write(JSON.stringify(data, null, 2) + '\n');
|
|
@@ -28,13 +28,11 @@ function registerFormatsCommand(program) {
|
|
|
28
28
|
process.stdout.write('\nAvailable export formats:\n\n');
|
|
29
29
|
for (const adapter of adapters) {
|
|
30
30
|
process.stdout.write(` ${chalk_1.default.cyan(adapter.id)} ${adapter.name}\n`);
|
|
31
|
-
|
|
31
|
+
const typeLabels = adapter.supportedTypes.map(t => t === 'skill' ? 'skills' : `${t} agents`);
|
|
32
|
+
process.stdout.write(` Supports: ${typeLabels.join(', ')}\n`);
|
|
32
33
|
process.stdout.write(` Format version: ${adapter.formatVersion}\n`);
|
|
33
34
|
for (const installPath of adapter.installPaths) {
|
|
34
|
-
|
|
35
|
-
? installPath.path
|
|
36
|
-
: installPath.path;
|
|
37
|
-
process.stdout.write(` ${installPath.scope}: ${pathDisplay}\n`);
|
|
35
|
+
process.stdout.write(` ${installPath.scope}: ${installPath.path}\n`);
|
|
38
36
|
}
|
|
39
37
|
process.stdout.write('\n');
|
|
40
38
|
}
|
package/dist/commands/install.js
CHANGED
|
@@ -13,10 +13,8 @@ const errors_1 = require("../lib/errors");
|
|
|
13
13
|
const analytics_1 = require("../lib/analytics");
|
|
14
14
|
const adapters_1 = require("../adapters");
|
|
15
15
|
const installed_1 = require("../lib/installed");
|
|
16
|
+
const agents_md_utils_1 = require("../lib/agents-md-utils");
|
|
16
17
|
const DEFAULT_VERSION = 'v1';
|
|
17
|
-
function escapeRegex(str) {
|
|
18
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
19
|
-
}
|
|
20
18
|
function parseAgentRef(value) {
|
|
21
19
|
const [ref, versionPart] = value.split('@');
|
|
22
20
|
const version = versionPart?.trim() || DEFAULT_VERSION;
|
|
@@ -89,7 +87,7 @@ function registerInstallCommand(program) {
|
|
|
89
87
|
}
|
|
90
88
|
}
|
|
91
89
|
else {
|
|
92
|
-
const defaults = await (0, config_1.getDefaultFormats)();
|
|
90
|
+
const defaults = await (0, config_1.getDefaultFormats)(resolved);
|
|
93
91
|
if (defaults.length > 0) {
|
|
94
92
|
targetFormats = defaults;
|
|
95
93
|
}
|
|
@@ -127,18 +125,18 @@ function registerInstallCommand(program) {
|
|
|
127
125
|
for (const warn of checkResult.warnings) {
|
|
128
126
|
process.stdout.write(`Warning (${formatId}): ${warn}\n`);
|
|
129
127
|
}
|
|
130
|
-
//
|
|
128
|
+
// Determine scope for this adapter (use local variable to not affect other formats)
|
|
129
|
+
let effectiveScope = scope;
|
|
131
130
|
const supportedScopes = adapter.installPaths.map(p => p.scope);
|
|
132
|
-
if (!supportedScopes.includes(
|
|
131
|
+
if (!supportedScopes.includes(effectiveScope)) {
|
|
133
132
|
process.stderr.write(`Warning: ${adapter.name} doesn't support '${scope}' scope. ` +
|
|
134
133
|
`Supported: ${supportedScopes.join(', ')}. Using '${supportedScopes[0]}' instead.\n`);
|
|
135
|
-
|
|
136
|
-
scope = supportedScopes[0];
|
|
134
|
+
effectiveScope = supportedScopes[0];
|
|
137
135
|
}
|
|
138
136
|
// Convert
|
|
139
137
|
const files = adapter.convert(agent);
|
|
140
138
|
// Determine base directory
|
|
141
|
-
const baseDir =
|
|
139
|
+
const baseDir = effectiveScope === 'user' ? os_1.default.homedir() : process.cwd();
|
|
142
140
|
// Install each file
|
|
143
141
|
for (const file of files) {
|
|
144
142
|
const fullDir = path_1.default.join(baseDir, file.installPath);
|
|
@@ -160,18 +158,7 @@ function registerInstallCommand(program) {
|
|
|
160
158
|
// File doesn't exist, will create new
|
|
161
159
|
}
|
|
162
160
|
const agentRef = `${org}/${parsed.name}`;
|
|
163
|
-
|
|
164
|
-
const markerEnd = `<!-- /orchagent:${agentRef} -->`;
|
|
165
|
-
if (existingContent.includes(markerStart)) {
|
|
166
|
-
// Replace existing section
|
|
167
|
-
const regex = new RegExp(`${escapeRegex(markerStart)}[\\s\\S]*?${escapeRegex(markerEnd)}`, 'g');
|
|
168
|
-
file.content = existingContent.replace(regex, file.content.trim());
|
|
169
|
-
}
|
|
170
|
-
else if (existingContent) {
|
|
171
|
-
// Append to existing file
|
|
172
|
-
file.content = existingContent.trimEnd() + '\n\n' + file.content;
|
|
173
|
-
}
|
|
174
|
-
// else: new file, use content as-is
|
|
161
|
+
file.content = (0, agents_md_utils_1.mergeAgentsMdContent)(existingContent, file.content, agentRef);
|
|
175
162
|
}
|
|
176
163
|
await promises_1.default.writeFile(fullPath, file.content);
|
|
177
164
|
filesWritten++;
|
|
@@ -180,7 +167,7 @@ function registerInstallCommand(program) {
|
|
|
180
167
|
agent: `${org}/${parsed.name}`,
|
|
181
168
|
version: parsed.version,
|
|
182
169
|
format: formatId,
|
|
183
|
-
scope,
|
|
170
|
+
scope: effectiveScope,
|
|
184
171
|
path: fullPath,
|
|
185
172
|
installedAt: new Date().toISOString(),
|
|
186
173
|
adapterVersion: adapter.version,
|
package/dist/commands/skill.js
CHANGED
|
@@ -29,14 +29,14 @@ const DEFAULT_VERSION = 'v1';
|
|
|
29
29
|
* - https://github.com/skillcreatorai/Ai-Agent-Skills
|
|
30
30
|
*/
|
|
31
31
|
const AI_TOOL_SKILL_DIRS = [
|
|
32
|
-
{ name: 'Claude Code',
|
|
33
|
-
{ name: 'Cursor',
|
|
34
|
-
{ name: 'Codex',
|
|
35
|
-
{ name: 'Amp',
|
|
36
|
-
{ name: 'OpenCode',
|
|
37
|
-
{ name: 'Antigravity',
|
|
32
|
+
{ name: 'Claude Code', projectPath: '.claude/skills', userPath: '.claude/skills' },
|
|
33
|
+
{ name: 'Cursor', projectPath: '.cursor/skills', userPath: '.cursor/skills' },
|
|
34
|
+
{ name: 'Codex', projectPath: '.codex/skills', userPath: '.codex/skills' },
|
|
35
|
+
{ name: 'Amp', projectPath: '.agents/skills', userPath: '.agents/skills' },
|
|
36
|
+
{ name: 'OpenCode', projectPath: '.opencode/skill', userPath: '.opencode/skill' },
|
|
37
|
+
{ name: 'Antigravity', projectPath: '.agent/skills', userPath: '.agent/skills' },
|
|
38
38
|
// TODO: Add more as we research them:
|
|
39
|
-
// { name: 'Windsurf',
|
|
39
|
+
// { name: 'Windsurf', projectPath: '.windsurf/skills', userPath: '.windsurf/skills' },
|
|
40
40
|
];
|
|
41
41
|
function parseSkillRef(value) {
|
|
42
42
|
const [ref, versionPart] = value.split('@');
|
|
@@ -161,6 +161,7 @@ Instructions and guidance for AI agents...
|
|
|
161
161
|
.command('install <skill>')
|
|
162
162
|
.description('Install skill to local AI tool directories (Claude Code, Cursor, etc.)')
|
|
163
163
|
.option('--global', 'Install to home directory (default: current directory)')
|
|
164
|
+
.option('--scope <scope>', 'Install scope: user or project', 'project')
|
|
164
165
|
.option('--dry-run', 'Show what would be installed without making changes')
|
|
165
166
|
.option('--format <formats>', 'Comma-separated format IDs (e.g., claude-code,cursor)')
|
|
166
167
|
.action(async (skillRef, options) => {
|
|
@@ -176,7 +177,7 @@ Instructions and guidance for AI agents...
|
|
|
176
177
|
}
|
|
177
178
|
}
|
|
178
179
|
else {
|
|
179
|
-
const defaults = await (0, config_1.getDefaultFormats)();
|
|
180
|
+
const defaults = await (0, config_1.getDefaultFormats)(resolved);
|
|
180
181
|
if (defaults.length > 0) {
|
|
181
182
|
// Filter to formats that have skill directories
|
|
182
183
|
targetFormats = defaults.filter(f => config_1.VALID_FORMAT_IDS.includes(f));
|
|
@@ -202,8 +203,8 @@ Instructions and guidance for AI agents...
|
|
|
202
203
|
'The skill exists but has an empty prompt. This may be a publishing issue.\n' +
|
|
203
204
|
'Try re-publishing the skill or contact the skill author.');
|
|
204
205
|
}
|
|
205
|
-
// Determine
|
|
206
|
-
const
|
|
206
|
+
// Determine scope (--global is legacy alias for --scope user)
|
|
207
|
+
const scope = options.global ? 'user' : (options.scope || 'project');
|
|
207
208
|
// Build skill content with header
|
|
208
209
|
const skillContent = `# ${skillData.name}
|
|
209
210
|
|
|
@@ -216,9 +217,11 @@ ${skillData.prompt}
|
|
|
216
217
|
// Dry run - show what would be installed
|
|
217
218
|
if (options.dryRun) {
|
|
218
219
|
process.stdout.write(`Would install ${org}/${parsed.skill}@${parsed.version}\n\n`);
|
|
219
|
-
process.stdout.write(`Target directories:\n`);
|
|
220
|
+
process.stdout.write(`Target directories (scope: ${scope}):\n`);
|
|
220
221
|
for (const tool of toolDirs) {
|
|
221
|
-
const
|
|
222
|
+
const baseDir = scope === 'user' ? os_1.default.homedir() : process.cwd();
|
|
223
|
+
const toolPath = scope === 'user' ? tool.userPath : tool.projectPath;
|
|
224
|
+
const skillDir = path_1.default.join(baseDir, toolPath);
|
|
222
225
|
const skillFile = path_1.default.join(skillDir, `${parsed.skill}.md`);
|
|
223
226
|
process.stdout.write(` - ${tool.name}: ${skillFile}\n`);
|
|
224
227
|
}
|
|
@@ -228,7 +231,9 @@ ${skillData.prompt}
|
|
|
228
231
|
// Install to target AI tool directories
|
|
229
232
|
const installed = [];
|
|
230
233
|
for (const tool of toolDirs) {
|
|
231
|
-
const
|
|
234
|
+
const baseDir = scope === 'user' ? os_1.default.homedir() : process.cwd();
|
|
235
|
+
const toolPath = scope === 'user' ? tool.userPath : tool.projectPath;
|
|
236
|
+
const skillDir = path_1.default.join(baseDir, toolPath);
|
|
232
237
|
const skillFile = path_1.default.join(skillDir, `${parsed.skill}.md`);
|
|
233
238
|
try {
|
|
234
239
|
await promises_1.default.mkdir(skillDir, { recursive: true });
|
|
@@ -237,7 +242,7 @@ ${skillData.prompt}
|
|
|
237
242
|
}
|
|
238
243
|
catch (err) {
|
|
239
244
|
// Skip if we can't write (e.g., permission issues)
|
|
240
|
-
process.stderr.write(`Warning: Could not install to ${
|
|
245
|
+
process.stderr.write(`Warning: Could not install to ${toolPath}: ${err.message}\n`);
|
|
241
246
|
}
|
|
242
247
|
}
|
|
243
248
|
if (installed.length === 0) {
|
|
@@ -245,7 +250,7 @@ ${skillData.prompt}
|
|
|
245
250
|
}
|
|
246
251
|
await (0, analytics_1.track)('cli_skill_install', {
|
|
247
252
|
skill: `${org}/${parsed.skill}`,
|
|
248
|
-
|
|
253
|
+
scope,
|
|
249
254
|
});
|
|
250
255
|
// Report authenticated install to backend (fire-and-forget)
|
|
251
256
|
// This tracks unique installers for manipulation-resistant metrics
|
|
@@ -257,6 +262,6 @@ ${skillData.prompt}
|
|
|
257
262
|
for (const tool of installed) {
|
|
258
263
|
process.stdout.write(` - ${tool}\n`);
|
|
259
264
|
}
|
|
260
|
-
process.stdout.write(`\nLocation: ${
|
|
265
|
+
process.stdout.write(`\nLocation: ${scope === 'user' ? '~/' : './'}\n`);
|
|
261
266
|
});
|
|
262
267
|
}
|
package/dist/commands/update.js
CHANGED
|
@@ -12,9 +12,7 @@ const api_1 = require("../lib/api");
|
|
|
12
12
|
const analytics_1 = require("../lib/analytics");
|
|
13
13
|
const adapters_1 = require("../adapters");
|
|
14
14
|
const installed_1 = require("../lib/installed");
|
|
15
|
-
|
|
16
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
-
}
|
|
15
|
+
const agents_md_utils_1 = require("../lib/agents-md-utils");
|
|
18
16
|
async function fetchLatestAgent(config, agentRef) {
|
|
19
17
|
const [org, name] = agentRef.split('/');
|
|
20
18
|
if (!org || !name)
|
|
@@ -119,19 +117,7 @@ function registerUpdateCommand(program) {
|
|
|
119
117
|
catch {
|
|
120
118
|
// File doesn't exist, will create new
|
|
121
119
|
}
|
|
122
|
-
|
|
123
|
-
const markerStart = `<!-- orchagent:${agentRef} -->`;
|
|
124
|
-
const markerEnd = `<!-- /orchagent:${agentRef} -->`;
|
|
125
|
-
if (existingContent.includes(markerStart)) {
|
|
126
|
-
// Replace existing section
|
|
127
|
-
const regex = new RegExp(`${escapeRegex(markerStart)}[\\s\\S]*?${escapeRegex(markerEnd)}`, 'g');
|
|
128
|
-
file.content = existingContent.replace(regex, file.content.trim());
|
|
129
|
-
}
|
|
130
|
-
else if (existingContent) {
|
|
131
|
-
// Append to existing file
|
|
132
|
-
file.content = existingContent.trimEnd() + '\n\n' + file.content;
|
|
133
|
-
}
|
|
134
|
-
// else: new file, use content as-is
|
|
120
|
+
file.content = (0, agents_md_utils_1.mergeAgentsMdContent)(existingContent, file.content, item.agent);
|
|
135
121
|
}
|
|
136
122
|
await promises_1.default.writeFile(fullPath, file.content);
|
|
137
123
|
// Update tracking
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Utilities for handling AGENTS.md file updates
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mergeAgentsMdContent = mergeAgentsMdContent;
|
|
7
|
+
const string_utils_1 = require("./string-utils");
|
|
8
|
+
/**
|
|
9
|
+
* Merge new content into an existing AGENTS.md file.
|
|
10
|
+
*
|
|
11
|
+
* - If the agent's section already exists (identified by markers), replace it
|
|
12
|
+
* - If the file has content but no section for this agent, append
|
|
13
|
+
* - If the file is empty/new, use the new content as-is
|
|
14
|
+
*
|
|
15
|
+
* @param existingContent - Current content of AGENTS.md (empty string if file doesn't exist)
|
|
16
|
+
* @param newContent - New content to merge (should include orchagent markers)
|
|
17
|
+
* @param agentRef - Agent reference like "org/agent-name" used in markers
|
|
18
|
+
* @returns Merged content
|
|
19
|
+
*/
|
|
20
|
+
function mergeAgentsMdContent(existingContent, newContent, agentRef) {
|
|
21
|
+
const markerStart = `<!-- orchagent:${agentRef} -->`;
|
|
22
|
+
const markerEnd = `<!-- /orchagent:${agentRef} -->`;
|
|
23
|
+
if (existingContent.includes(markerStart)) {
|
|
24
|
+
// Replace existing section
|
|
25
|
+
const regex = new RegExp(`${(0, string_utils_1.escapeRegex)(markerStart)}[\\s\\S]*?${(0, string_utils_1.escapeRegex)(markerEnd)}`, 'g');
|
|
26
|
+
return existingContent.replace(regex, newContent.trim());
|
|
27
|
+
}
|
|
28
|
+
else if (existingContent.trim()) {
|
|
29
|
+
// Append to existing file
|
|
30
|
+
return existingContent.trimEnd() + '\n\n' + newContent;
|
|
31
|
+
}
|
|
32
|
+
// New file, use content as-is
|
|
33
|
+
return newContent;
|
|
34
|
+
}
|
package/dist/lib/api.js
CHANGED
|
@@ -57,6 +57,7 @@ exports.checkAgentDelete = checkAgentDelete;
|
|
|
57
57
|
exports.deleteAgent = deleteAgent;
|
|
58
58
|
exports.previewAgentVersion = previewAgentVersion;
|
|
59
59
|
exports.reportInstall = reportInstall;
|
|
60
|
+
exports.fetchUserProfile = fetchUserProfile;
|
|
60
61
|
const errors_1 = require("./errors");
|
|
61
62
|
const DEFAULT_TIMEOUT_MS = 15000;
|
|
62
63
|
const MAX_RETRIES = 3;
|
|
@@ -349,3 +350,10 @@ async function reportInstall(config, org, skill, version, cliVersion) {
|
|
|
349
350
|
headers: { 'X-CLI-Version': cliVersion },
|
|
350
351
|
});
|
|
351
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
* Fetch the current user's profile from the server.
|
|
355
|
+
*/
|
|
356
|
+
async function fetchUserProfile(config) {
|
|
357
|
+
const result = await request(config, 'GET', '/users/me');
|
|
358
|
+
return result.user;
|
|
359
|
+
}
|
package/dist/lib/config.js
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -20,12 +53,12 @@ const DEFAULT_API_URL = 'https://api.orchagent.io';
|
|
|
20
53
|
exports.VALID_FORMAT_IDS = ['claude-code', 'cursor', 'codex', 'amp', 'opencode', 'antigravity'];
|
|
21
54
|
// Map format IDs to skill directories (used by skill install and agent install)
|
|
22
55
|
exports.FORMAT_SKILL_DIRS = {
|
|
23
|
-
'claude-code': { name: 'Claude Code',
|
|
24
|
-
'cursor': { name: 'Cursor',
|
|
25
|
-
'codex': { name: 'Codex',
|
|
26
|
-
'amp': { name: 'Amp',
|
|
27
|
-
'opencode': { name: 'OpenCode',
|
|
28
|
-
'antigravity': { name: 'Antigravity',
|
|
56
|
+
'claude-code': { name: 'Claude Code', projectPath: '.claude/skills', userPath: '.claude/skills' },
|
|
57
|
+
'cursor': { name: 'Cursor', projectPath: '.cursor/skills', userPath: '.cursor/skills' },
|
|
58
|
+
'codex': { name: 'Codex', projectPath: '.codex/skills', userPath: '.codex/skills' },
|
|
59
|
+
'amp': { name: 'Amp', projectPath: '.agents/skills', userPath: '.agents/skills' },
|
|
60
|
+
'opencode': { name: 'OpenCode', projectPath: '.opencode/skill', userPath: '.opencode/skill' },
|
|
61
|
+
'antigravity': { name: 'Antigravity', projectPath: '.agent/skills', userPath: '.agent/skills' },
|
|
29
62
|
};
|
|
30
63
|
async function loadConfig() {
|
|
31
64
|
try {
|
|
@@ -70,9 +103,27 @@ async function getResolvedConfig(overrides = {}, profile) {
|
|
|
70
103
|
function getConfigPath() {
|
|
71
104
|
return CONFIG_PATH;
|
|
72
105
|
}
|
|
73
|
-
async function getDefaultFormats() {
|
|
106
|
+
async function getDefaultFormats(resolvedConfig) {
|
|
107
|
+
// 1. Check local config first (explicit override)
|
|
74
108
|
const config = await loadConfig();
|
|
75
|
-
|
|
109
|
+
if (config.default_formats?.length) {
|
|
110
|
+
return config.default_formats;
|
|
111
|
+
}
|
|
112
|
+
// 2. Try server preferences (if logged in)
|
|
113
|
+
if (resolvedConfig?.apiKey) {
|
|
114
|
+
try {
|
|
115
|
+
const { fetchUserProfile } = await Promise.resolve().then(() => __importStar(require('./api')));
|
|
116
|
+
const user = await fetchUserProfile(resolvedConfig);
|
|
117
|
+
if (user.preferences?.default_formats?.length) {
|
|
118
|
+
return user.preferences.default_formats;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Offline or not logged in - use defaults
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 3. Return empty (no default = install to all)
|
|
126
|
+
return [];
|
|
76
127
|
}
|
|
77
128
|
async function setDefaultFormats(formats) {
|
|
78
129
|
const config = await loadConfig();
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared string utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.escapeRegex = escapeRegex;
|
|
7
|
+
/**
|
|
8
|
+
* Escape special regex characters in a string
|
|
9
|
+
*/
|
|
10
|
+
function escapeRegex(str) {
|
|
11
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
12
|
+
}
|