@orchagent/cli 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -21,11 +21,12 @@ function mapModelToAlias(model) {
|
|
|
21
21
|
}
|
|
22
22
|
// Convert agent name to valid Claude Code name (lowercase + hyphens)
|
|
23
23
|
function normalizeAgentName(name) {
|
|
24
|
-
|
|
24
|
+
const normalized = name
|
|
25
25
|
.toLowerCase()
|
|
26
26
|
.replace(/[^a-z0-9-]/g, '-')
|
|
27
27
|
.replace(/-+/g, '-')
|
|
28
28
|
.replace(/^-|-$/g, '');
|
|
29
|
+
return normalized || 'agent'; // Fallback if empty
|
|
29
30
|
}
|
|
30
31
|
exports.claudeCodeAdapter = {
|
|
31
32
|
id: 'claude-code',
|
package/dist/adapters/cursor.js
CHANGED
|
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.cursorAdapter = void 0;
|
|
4
4
|
// Convert agent name to valid filename (lowercase + hyphens)
|
|
5
5
|
function normalizeAgentName(name) {
|
|
6
|
-
|
|
6
|
+
const normalized = name
|
|
7
7
|
.toLowerCase()
|
|
8
8
|
.replace(/[^a-z0-9-]/g, '-')
|
|
9
9
|
.replace(/-+/g, '-')
|
|
10
10
|
.replace(/^-|-$/g, '');
|
|
11
|
+
return normalized || 'agent'; // Fallback if empty
|
|
11
12
|
}
|
|
12
13
|
exports.cursorAdapter = {
|
|
13
14
|
id: 'cursor',
|
package/dist/commands/config.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.registerConfigCommand = registerConfigCommand;
|
|
4
4
|
const config_1 = require("../lib/config");
|
|
5
5
|
const errors_1 = require("../lib/errors");
|
|
6
|
+
const adapters_1 = require("../adapters");
|
|
6
7
|
const SUPPORTED_KEYS = ['default-format'];
|
|
7
8
|
function isValidKey(key) {
|
|
8
9
|
return SUPPORTED_KEYS.includes(key);
|
|
@@ -13,10 +14,11 @@ async function setConfigValue(key, value) {
|
|
|
13
14
|
}
|
|
14
15
|
if (key === 'default-format') {
|
|
15
16
|
const formats = value.split(',').map((f) => f.trim()).filter(Boolean);
|
|
16
|
-
// Validate all format IDs
|
|
17
|
-
const
|
|
17
|
+
// Validate all format IDs against adapter registry
|
|
18
|
+
const validFormatIds = adapters_1.adapterRegistry.getIds();
|
|
19
|
+
const invalidFormats = formats.filter((f) => !validFormatIds.includes(f));
|
|
18
20
|
if (invalidFormats.length > 0) {
|
|
19
|
-
throw new errors_1.CliError(`Invalid format ID(s): ${invalidFormats.join(', ')}. Valid formats: ${
|
|
21
|
+
throw new errors_1.CliError(`Invalid format ID(s): ${invalidFormats.join(', ')}. Valid formats: ${validFormatIds.join(', ')}`);
|
|
20
22
|
}
|
|
21
23
|
await (0, config_1.setDefaultFormats)(formats);
|
|
22
24
|
process.stdout.write(`Set default-format to: ${formats.join(',')}\n`);
|
package/dist/commands/install.js
CHANGED
|
@@ -14,6 +14,9 @@ const analytics_1 = require("../lib/analytics");
|
|
|
14
14
|
const adapters_1 = require("../adapters");
|
|
15
15
|
const installed_1 = require("../lib/installed");
|
|
16
16
|
const DEFAULT_VERSION = 'v1';
|
|
17
|
+
function escapeRegex(str) {
|
|
18
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
19
|
+
}
|
|
17
20
|
function parseAgentRef(value) {
|
|
18
21
|
const [ref, versionPart] = value.split('@');
|
|
19
22
|
const version = versionPart?.trim() || DEFAULT_VERSION;
|
|
@@ -96,7 +99,7 @@ function registerInstallCommand(program) {
|
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
// Validate scope
|
|
99
|
-
|
|
102
|
+
let scope = options.scope;
|
|
100
103
|
if (scope !== 'user' && scope !== 'project') {
|
|
101
104
|
throw new errors_1.CliError('Scope must be "user" or "project"');
|
|
102
105
|
}
|
|
@@ -104,6 +107,7 @@ function registerInstallCommand(program) {
|
|
|
104
107
|
process.stdout.write(`Fetching ${org}/${parsed.name}@${parsed.version}...\n`);
|
|
105
108
|
const agent = await downloadAgentWithFallback(resolved, org, parsed.name, parsed.version);
|
|
106
109
|
// Install for each format
|
|
110
|
+
let filesWritten = 0;
|
|
107
111
|
for (const formatId of targetFormats) {
|
|
108
112
|
const adapter = adapters_1.adapterRegistry.get(formatId);
|
|
109
113
|
if (!adapter) {
|
|
@@ -123,6 +127,14 @@ function registerInstallCommand(program) {
|
|
|
123
127
|
for (const warn of checkResult.warnings) {
|
|
124
128
|
process.stdout.write(`Warning (${formatId}): ${warn}\n`);
|
|
125
129
|
}
|
|
130
|
+
// Check if adapter supports requested scope
|
|
131
|
+
const supportedScopes = adapter.installPaths.map(p => p.scope);
|
|
132
|
+
if (!supportedScopes.includes(scope)) {
|
|
133
|
+
process.stderr.write(`Warning: ${adapter.name} doesn't support '${scope}' scope. ` +
|
|
134
|
+
`Supported: ${supportedScopes.join(', ')}. Using '${supportedScopes[0]}' instead.\n`);
|
|
135
|
+
// Use the first supported scope
|
|
136
|
+
scope = supportedScopes[0];
|
|
137
|
+
}
|
|
126
138
|
// Convert
|
|
127
139
|
const files = adapter.convert(agent);
|
|
128
140
|
// Determine base directory
|
|
@@ -138,7 +150,31 @@ function registerInstallCommand(program) {
|
|
|
138
150
|
}
|
|
139
151
|
// Create directory and write file
|
|
140
152
|
await promises_1.default.mkdir(fullDir, { recursive: true });
|
|
153
|
+
// Special handling for AGENTS.md - append/replace instead of overwrite
|
|
154
|
+
if (file.filename === 'AGENTS.md') {
|
|
155
|
+
let existingContent = '';
|
|
156
|
+
try {
|
|
157
|
+
existingContent = await promises_1.default.readFile(fullPath, 'utf-8');
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// File doesn't exist, will create new
|
|
161
|
+
}
|
|
162
|
+
const agentRef = `${org}/${parsed.name}`;
|
|
163
|
+
const markerStart = `<!-- orchagent:${agentRef} -->`;
|
|
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
|
|
175
|
+
}
|
|
141
176
|
await promises_1.default.writeFile(fullPath, file.content);
|
|
177
|
+
filesWritten++;
|
|
142
178
|
// Track installation
|
|
143
179
|
const installedAgent = {
|
|
144
180
|
agent: `${org}/${parsed.name}`,
|
|
@@ -155,17 +191,23 @@ function registerInstallCommand(program) {
|
|
|
155
191
|
}
|
|
156
192
|
}
|
|
157
193
|
if (!options.dryRun) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
194
|
+
if (filesWritten > 0) {
|
|
195
|
+
await (0, analytics_1.track)('cli_agent_install', {
|
|
196
|
+
agent: `${org}/${parsed.name}`,
|
|
197
|
+
formats: targetFormats,
|
|
198
|
+
scope,
|
|
199
|
+
});
|
|
200
|
+
process.stdout.write(`\nAgent installed successfully!\n`);
|
|
201
|
+
if (scope === 'user') {
|
|
202
|
+
process.stdout.write(`Available in all your projects.\n`);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
process.stdout.write(`Available in this project only.\n`);
|
|
206
|
+
}
|
|
166
207
|
}
|
|
167
208
|
else {
|
|
168
|
-
process.
|
|
209
|
+
process.stderr.write(`\nNo files were installed. Check warnings above.\n`);
|
|
210
|
+
process.exit(1);
|
|
169
211
|
}
|
|
170
212
|
}
|
|
171
213
|
});
|
package/dist/commands/skill.js
CHANGED
|
@@ -178,7 +178,12 @@ Instructions and guidance for AI agents...
|
|
|
178
178
|
else {
|
|
179
179
|
const defaults = await (0, config_1.getDefaultFormats)();
|
|
180
180
|
if (defaults.length > 0) {
|
|
181
|
-
|
|
181
|
+
// Filter to formats that have skill directories
|
|
182
|
+
targetFormats = defaults.filter(f => config_1.VALID_FORMAT_IDS.includes(f));
|
|
183
|
+
const skipped = defaults.filter(f => !config_1.VALID_FORMAT_IDS.includes(f));
|
|
184
|
+
if (skipped.length > 0) {
|
|
185
|
+
process.stderr.write(`Note: Skipping ${skipped.join(', ')} (no skill directory)\n`);
|
|
186
|
+
}
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
// Determine target directories
|
package/dist/commands/update.js
CHANGED
|
@@ -12,6 +12,9 @@ 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
|
+
function escapeRegex(str) {
|
|
16
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
+
}
|
|
15
18
|
async function fetchLatestAgent(config, agentRef) {
|
|
16
19
|
const [org, name] = agentRef.split('/');
|
|
17
20
|
if (!org || !name)
|
|
@@ -97,12 +100,39 @@ function registerUpdateCommand(program) {
|
|
|
97
100
|
continue;
|
|
98
101
|
}
|
|
99
102
|
const files = adapter.convert(latest.agent);
|
|
103
|
+
if (files.length > 1) {
|
|
104
|
+
process.stderr.write(` Skipped: Multi-file adapters not supported for update. Reinstall instead.\n`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
100
107
|
for (const file of files) {
|
|
101
108
|
// Use the original path from tracking
|
|
102
109
|
const fullPath = item.path;
|
|
103
110
|
try {
|
|
104
111
|
const dir = path_1.default.dirname(fullPath);
|
|
105
112
|
await promises_1.default.mkdir(dir, { recursive: true });
|
|
113
|
+
// Special handling for AGENTS.md - append/replace instead of overwrite
|
|
114
|
+
if (file.filename === 'AGENTS.md') {
|
|
115
|
+
let existingContent = '';
|
|
116
|
+
try {
|
|
117
|
+
existingContent = await promises_1.default.readFile(fullPath, 'utf-8');
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// File doesn't exist, will create new
|
|
121
|
+
}
|
|
122
|
+
const agentRef = item.agent;
|
|
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
|
|
135
|
+
}
|
|
106
136
|
await promises_1.default.writeFile(fullPath, file.content);
|
|
107
137
|
// Update tracking
|
|
108
138
|
const updatedItem = {
|