@agents-inc/cli 0.86.0 → 0.87.0

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/chunk-5UJJQFET.js +564 -0
  3. package/dist/chunk-5UJJQFET.js.map +1 -0
  4. package/dist/{chunk-GED2F75H.js → chunk-7FFNNDJQ.js} +176 -120
  5. package/dist/chunk-7FFNNDJQ.js.map +1 -0
  6. package/dist/{chunk-BV2MIQ3O.js → chunk-I5AZKNNL.js} +1 -1
  7. package/dist/chunk-I5AZKNNL.js.map +1 -0
  8. package/dist/chunk-J6PI73YV.js +68 -0
  9. package/dist/chunk-J6PI73YV.js.map +1 -0
  10. package/dist/commands/compile.js +26 -20
  11. package/dist/commands/compile.js.map +1 -1
  12. package/dist/commands/diff.js +681 -82
  13. package/dist/commands/diff.js.map +1 -1
  14. package/dist/commands/doctor.js +30 -58
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/edit.js +164 -32
  17. package/dist/commands/edit.js.map +1 -1
  18. package/dist/commands/eject.js +177 -27
  19. package/dist/commands/eject.js.map +1 -1
  20. package/dist/commands/import/skill.js +197 -33
  21. package/dist/commands/import/skill.js.map +1 -1
  22. package/dist/commands/info.js +41 -34
  23. package/dist/commands/info.js.map +1 -1
  24. package/dist/commands/init.js +3 -6
  25. package/dist/commands/new/agent.js +140 -44
  26. package/dist/commands/new/agent.js.map +1 -1
  27. package/dist/commands/new/marketplace.js +4 -4
  28. package/dist/commands/new/marketplace.js.map +1 -1
  29. package/dist/commands/new/skill.js +194 -30
  30. package/dist/commands/new/skill.js.map +1 -1
  31. package/dist/commands/outdated.js +1 -3
  32. package/dist/commands/outdated.js.map +1 -1
  33. package/dist/commands/search.js +162 -65
  34. package/dist/commands/search.js.map +1 -1
  35. package/dist/commands/uninstall.js +259 -62
  36. package/dist/commands/uninstall.js.map +1 -1
  37. package/dist/commands/update.js +232 -163
  38. package/dist/commands/update.js.map +1 -1
  39. package/dist/components/skill-search/skill-search.js +1 -1
  40. package/dist/hooks/init.js +2 -4
  41. package/dist/hooks/init.js.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/chunk-BV2MIQ3O.js.map +0 -1
  44. package/dist/chunk-DCVCFBQ7.js +0 -1800
  45. package/dist/chunk-DCVCFBQ7.js.map +0 -1
  46. package/dist/chunk-GED2F75H.js.map +0 -1
  47. package/dist/chunk-O5ZWS26C.js +0 -166
  48. package/dist/chunk-O5ZWS26C.js.map +0 -1
  49. package/dist/chunk-XQK4S22C.js +0 -202
  50. package/dist/chunk-XQK4S22C.js.map +0 -1
@@ -12,15 +12,15 @@ import {
12
12
  collectScopedSkillDirs,
13
13
  compareSkillsWithSource,
14
14
  compileAgents,
15
+ discoverInstalledSkills,
15
16
  findSkillMatch,
16
- loadSource,
17
- updateLocalSkills
18
- } from "../chunk-DCVCFBQ7.js";
17
+ loadSource
18
+ } from "../chunk-5UJJQFET.js";
19
19
  import "../chunk-N6A7A4RA.js";
20
- import "../chunk-O5ZWS26C.js";
21
- import "../chunk-XQK4S22C.js";
22
20
  import "../chunk-FBZR46GC.js";
23
- import "../chunk-TMTUTUEV.js";
21
+ import {
22
+ injectForkedFromMetadata
23
+ } from "../chunk-TMTUTUEV.js";
24
24
  import "../chunk-B6MYECV6.js";
25
25
  import "../chunk-ANXHMG32.js";
26
26
  import {
@@ -28,11 +28,13 @@ import {
28
28
  EXIT_CODES
29
29
  } from "../chunk-MMTMXLI4.js";
30
30
  import {
31
+ copy,
31
32
  getErrorMessage
32
33
  } from "../chunk-NUU3U43A.js";
33
34
  import "../chunk-6XWHJHNZ.js";
34
35
  import {
35
- CLI_BIN_NAME
36
+ CLI_BIN_NAME,
37
+ LOCAL_SKILLS_PATH
36
38
  } from "../chunk-6PGL2XMY.js";
37
39
  import "../chunk-NPMMU4GY.js";
38
40
  import {
@@ -45,6 +47,7 @@ import { Flags, Args } from "@oclif/core";
45
47
  import { printTable } from "@oclif/table";
46
48
  import { render } from "ink";
47
49
  import os from "os";
50
+ import path from "path";
48
51
  import { jsx } from "react/jsx-runtime";
49
52
  var UpdateConfirm = ({ onConfirm, onCancel }) => {
50
53
  return /* @__PURE__ */ jsx(
@@ -88,182 +91,248 @@ var Update = class _Update extends BaseCommand {
88
91
  async run() {
89
92
  const { args, flags } = await this.parse(_Update);
90
93
  const projectDir = process.cwd();
91
- const shouldRecompile = !flags["no-recompile"];
92
94
  try {
93
- const homeDir = os.homedir();
94
- const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);
95
- if (!hasProject && !hasGlobal) {
96
- this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);
97
- return;
98
- }
99
- this.log(STATUS_MESSAGES.LOADING_SKILLS);
100
- const { sourceResult } = await loadSource({
101
- sourceFlag: flags.source,
102
- projectDir
103
- });
104
- this.log(
105
- `Loaded from ${sourceResult.isLocal ? "local" : "remote"}: ${sourceResult.sourcePath}`
106
- );
107
- const comparison = await compareSkillsWithSource(
108
- projectDir,
109
- sourceResult.sourcePath,
110
- sourceResult.matrix
111
- );
112
- const allResults = comparison.merged;
113
- const skillBaseDir = /* @__PURE__ */ new Map();
114
- for (const r of comparison.projectResults) skillBaseDir.set(r.id, projectDir);
115
- for (const r of comparison.globalResults) {
116
- if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);
117
- }
118
- let outdatedSkills = allResults.filter((r) => r.status === "outdated");
119
- if (args.skill) {
120
- const { match: foundSkill, similar } = findSkillMatch(args.skill, allResults);
121
- if (!foundSkill) {
122
- this.log("");
123
- this.log(`Error: Skill "${args.skill}" not found.`);
124
- this.log("");
125
- if (similar.length > 0) {
126
- this.log("Did you mean one of these?");
127
- for (const name of similar) {
128
- this.log(` - ${name}`);
129
- }
130
- this.log("");
95
+ const context = await this.loadContext(flags, projectDir);
96
+ if (!context) return;
97
+ const outdatedSkills = this.resolveTargetSkills(args.skill, context);
98
+ if (!outdatedSkills) return;
99
+ this.printUpdateTable(outdatedSkills);
100
+ const confirmed = flags.yes || await this.confirmUpdate();
101
+ if (!confirmed) return;
102
+ this.log("");
103
+ const updateResult = await this.executeUpdates(outdatedSkills, context);
104
+ this.printUpdateResults(updateResult);
105
+ const recompiledAgents = flags["no-recompile"] ? [] : await this.recompileAfterUpdate(updateResult, context);
106
+ this.printCompletionSummary(updateResult, recompiledAgents);
107
+ } catch (error) {
108
+ const message = getErrorMessage(error);
109
+ this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });
110
+ }
111
+ }
112
+ async loadContext(flags, projectDir) {
113
+ const homeDir = os.homedir();
114
+ const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);
115
+ if (!hasProject && !hasGlobal) {
116
+ this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);
117
+ return null;
118
+ }
119
+ this.log(STATUS_MESSAGES.LOADING_SKILLS);
120
+ const { sourceResult } = await loadSource({
121
+ sourceFlag: flags.source,
122
+ projectDir
123
+ });
124
+ this.log(
125
+ `Loaded from ${sourceResult.isLocal ? "local" : "remote"}: ${sourceResult.sourcePath}`
126
+ );
127
+ const comparison = await compareSkillsWithSource(
128
+ projectDir,
129
+ sourceResult.sourcePath,
130
+ sourceResult.matrix
131
+ );
132
+ const skillBaseDir = /* @__PURE__ */ new Map();
133
+ for (const r of comparison.projectResults) skillBaseDir.set(r.id, projectDir);
134
+ for (const r of comparison.globalResults) {
135
+ if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);
136
+ }
137
+ return {
138
+ projectDir,
139
+ homeDir,
140
+ sourceResult,
141
+ allResults: comparison.merged,
142
+ skillBaseDir
143
+ };
144
+ }
145
+ resolveTargetSkills(skillArg, context) {
146
+ let outdatedSkills = context.allResults.filter((r) => r.status === "outdated");
147
+ if (skillArg) {
148
+ const { match: foundSkill, similar } = findSkillMatch(skillArg, context.allResults);
149
+ if (!foundSkill) {
150
+ this.log("");
151
+ this.log(`Error: Skill "${skillArg}" not found.`);
152
+ this.log("");
153
+ if (similar.length > 0) {
154
+ this.log("Did you mean one of these?");
155
+ for (const name of similar) {
156
+ this.log(` - ${name}`);
131
157
  }
132
- this.log(`Run \`${CLI_BIN_NAME} search ${args.skill}\` to search available skills.`);
133
- this.log("");
134
- this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });
135
- }
136
- if (foundSkill.status === "current") {
137
- this.log("");
138
- this.log(`Skill "${foundSkill.id}" is already up to date.`);
139
- this.log("");
140
- this.log(` Local hash: ${foundSkill.localHash}`);
141
- this.log(` Source hash: ${foundSkill.sourceHash}`);
142
158
  this.log("");
143
- return;
144
159
  }
145
- if (foundSkill.status === "local-only") {
146
- this.log("");
147
- this.log(`Skill "${foundSkill.id}" is a local-only skill (not forked from source).`);
148
- this.log("Cannot update local-only skills.");
149
- this.log("");
150
- return;
151
- }
152
- outdatedSkills = [foundSkill];
160
+ this.log(`Run \`${CLI_BIN_NAME} search ${skillArg}\` to search available skills.`);
161
+ this.log("");
162
+ this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });
153
163
  }
154
- if (outdatedSkills.length === 0) {
164
+ if (foundSkill.status === "current") {
155
165
  this.log("");
156
- this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);
166
+ this.log(`Skill "${foundSkill.id}" is already up to date.`);
157
167
  this.log("");
158
- return;
168
+ this.log(` Local hash: ${foundSkill.localHash}`);
169
+ this.log(` Source hash: ${foundSkill.sourceHash}`);
170
+ this.log("");
171
+ return null;
159
172
  }
173
+ if (foundSkill.status === "local-only") {
174
+ this.log("");
175
+ this.log(`Skill "${foundSkill.id}" is a local-only skill (not forked from source).`);
176
+ this.log("Cannot update local-only skills.");
177
+ this.log("");
178
+ return null;
179
+ }
180
+ outdatedSkills = [foundSkill];
181
+ }
182
+ if (outdatedSkills.length === 0) {
160
183
  this.log("");
161
- this.log("The following skills will be updated:");
162
- this.log("");
163
- printTable({
164
- data: outdatedSkills.map((skill) => ({
165
- skill: skill.id,
166
- localHash: skill.localHash ?? "-",
167
- sourceHash: skill.sourceHash ?? "-"
168
- })),
169
- columns: [
170
- { key: "skill", name: "Skill" },
171
- { key: "localHash", name: "Local Hash" },
172
- { key: "sourceHash", name: "Source Hash" }
173
- ],
174
- headerOptions: { bold: true }
175
- });
176
- this.log("");
177
- this.log(`${outdatedSkills.length} skill(s) will be updated.`);
184
+ this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);
178
185
  this.log("");
179
- if (!flags.yes) {
180
- let confirmed = false;
181
- let cancelled = false;
182
- const { waitUntilExit } = render(
183
- /* @__PURE__ */ jsx(
184
- UpdateConfirm,
185
- {
186
- onConfirm: () => {
187
- confirmed = true;
188
- },
189
- onCancel: () => {
190
- cancelled = true;
191
- }
192
- }
193
- )
194
- );
195
- await waitUntilExit();
196
- if (cancelled) {
197
- this.log("Update cancelled");
198
- this.exit(EXIT_CODES.CANCELLED);
199
- }
200
- if (!confirmed) {
201
- this.log(INFO_MESSAGES.NO_CHANGES_MADE);
202
- return;
186
+ return null;
187
+ }
188
+ return outdatedSkills;
189
+ }
190
+ printUpdateTable(outdatedSkills) {
191
+ this.log("");
192
+ this.log("The following skills will be updated:");
193
+ this.log("");
194
+ printTable({
195
+ data: outdatedSkills.map((skill) => ({
196
+ skill: skill.id,
197
+ localHash: skill.localHash ?? "-",
198
+ sourceHash: skill.sourceHash ?? "-"
199
+ })),
200
+ columns: [
201
+ { key: "skill", name: "Skill" },
202
+ { key: "localHash", name: "Local Hash" },
203
+ { key: "sourceHash", name: "Source Hash" }
204
+ ],
205
+ headerOptions: { bold: true }
206
+ });
207
+ this.log("");
208
+ this.log(`${outdatedSkills.length} skill(s) will be updated.`);
209
+ this.log("");
210
+ }
211
+ async confirmUpdate() {
212
+ let confirmed = false;
213
+ let cancelled = false;
214
+ const { waitUntilExit } = render(
215
+ /* @__PURE__ */ jsx(
216
+ UpdateConfirm,
217
+ {
218
+ onConfirm: () => {
219
+ confirmed = true;
220
+ },
221
+ onCancel: () => {
222
+ cancelled = true;
223
+ }
203
224
  }
204
- }
205
- this.log("");
206
- const updateResult = await updateLocalSkills({
207
- skills: outdatedSkills,
208
- sourceResult,
209
- skillBaseDir,
210
- onProgress: (skillId) => this.log(`Updating ${skillId}...`)
225
+ )
226
+ );
227
+ await waitUntilExit();
228
+ if (cancelled) {
229
+ this.log("Update cancelled");
230
+ this.exit(EXIT_CODES.CANCELLED);
231
+ }
232
+ if (!confirmed) {
233
+ this.log(INFO_MESSAGES.NO_CHANGES_MADE);
234
+ return false;
235
+ }
236
+ return true;
237
+ }
238
+ async executeUpdates(outdatedSkills, context) {
239
+ return updateLocalSkills({
240
+ skills: outdatedSkills,
241
+ sourceResult: context.sourceResult,
242
+ skillBaseDir: context.skillBaseDir,
243
+ onProgress: (skillId) => this.log(`Updating ${skillId}...`)
244
+ });
245
+ }
246
+ printUpdateResults(updateResult) {
247
+ for (const item of updateResult.updated) {
248
+ this.log(` Updated ${item.id}`);
249
+ }
250
+ for (const item of updateResult.failed) {
251
+ this.log(` Failed to update ${item.id}: ${item.error}`);
252
+ }
253
+ }
254
+ async recompileAfterUpdate(updateResult, context) {
255
+ if (updateResult.totalUpdated === 0) return [];
256
+ this.log("");
257
+ this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);
258
+ try {
259
+ const { allSkills } = await discoverInstalledSkills(context.projectDir);
260
+ const recompileResult = await compileAgents({
261
+ projectDir: context.projectDir,
262
+ sourcePath: context.sourceResult.sourcePath,
263
+ skills: allSkills
211
264
  });
212
- for (const item of updateResult.updated) {
213
- this.log(` Updated ${item.id}`);
214
- }
215
- for (const item of updateResult.failed) {
216
- this.log(` Failed to update ${item.id}: ${item.error}`);
217
- }
218
- let recompiledAgents = [];
219
- if (shouldRecompile && updateResult.totalUpdated > 0) {
220
- this.log("");
221
- this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);
222
- try {
223
- const recompileResult = await compileAgents({
224
- projectDir,
225
- sourcePath: sourceResult.sourcePath
226
- });
227
- recompiledAgents = recompileResult.compiled;
228
- if (recompiledAgents.length > 0) {
229
- this.log("Agents recompiled");
230
- for (const agent of recompiledAgents) {
231
- this.log(` Recompiled: ${agent}`);
232
- }
233
- } else {
234
- this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);
235
- }
236
- if (recompileResult.warnings.length > 0) {
237
- for (const warning of recompileResult.warnings) {
238
- this.warn(warning);
239
- }
240
- }
241
- } catch (error) {
242
- this.warn("Agent recompilation failed");
243
- this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);
265
+ const recompiledAgents = recompileResult.compiled;
266
+ if (recompiledAgents.length > 0) {
267
+ this.log("Agents recompiled");
268
+ for (const agent of recompiledAgents) {
269
+ this.log(` Recompiled: ${agent}`);
244
270
  }
245
- }
246
- this.log("");
247
- if (updateResult.totalFailed === 0) {
248
- const agentMsg = recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : "";
249
- this.logSuccess(
250
- `Update complete! ${updateResult.totalUpdated} skill(s) updated${agentMsg}.`
251
- );
252
271
  } else {
253
- this.warn(
254
- `Update finished with errors: ${updateResult.totalUpdated} updated, ${updateResult.totalFailed} failed.`
255
- );
272
+ this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);
256
273
  }
257
- this.log("");
258
- if (updateResult.totalFailed > 0) {
259
- this.error("Some updates failed", { exit: EXIT_CODES.ERROR });
274
+ if (recompileResult.warnings.length > 0) {
275
+ for (const warning of recompileResult.warnings) {
276
+ this.warn(warning);
277
+ }
260
278
  }
279
+ return recompiledAgents;
261
280
  } catch (error) {
262
- const message = getErrorMessage(error);
263
- this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });
281
+ this.warn("Agent recompilation failed");
282
+ this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);
283
+ return [];
284
+ }
285
+ }
286
+ printCompletionSummary(updateResult, recompiledAgents) {
287
+ this.log("");
288
+ if (updateResult.totalFailed === 0) {
289
+ const agentMsg = recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : "";
290
+ this.logSuccess(`Update complete! ${updateResult.totalUpdated} skill(s) updated${agentMsg}.`);
291
+ } else {
292
+ this.warn(
293
+ `Update finished with errors: ${updateResult.totalUpdated} updated, ${updateResult.totalFailed} failed.`
294
+ );
295
+ }
296
+ this.log("");
297
+ if (updateResult.totalFailed > 0) {
298
+ this.error("Some updates failed", { exit: EXIT_CODES.ERROR });
264
299
  }
265
300
  }
266
301
  };
302
+ async function updateLocalSkills(options) {
303
+ const { skills, sourceResult, skillBaseDir, onProgress } = options;
304
+ const updated = [];
305
+ const failed = [];
306
+ for (const skill of skills) {
307
+ onProgress?.(skill.id);
308
+ if (!skill.sourcePath || !skill.sourceHash) {
309
+ failed.push({
310
+ id: skill.id,
311
+ success: false,
312
+ newHash: null,
313
+ error: "No source path available"
314
+ });
315
+ continue;
316
+ }
317
+ const baseDir = skillBaseDir.get(skill.id) ?? process.cwd();
318
+ const localSkillsPath = path.join(baseDir, LOCAL_SKILLS_PATH);
319
+ const destPath = path.join(localSkillsPath, skill.dirName);
320
+ const srcPath = path.join(sourceResult.sourcePath, "src", skill.sourcePath);
321
+ try {
322
+ await copy(srcPath, destPath);
323
+ await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);
324
+ updated.push({ id: skill.id, success: true, newHash: skill.sourceHash });
325
+ } catch (error) {
326
+ failed.push({ id: skill.id, success: false, newHash: null, error: getErrorMessage(error) });
327
+ }
328
+ }
329
+ return {
330
+ updated,
331
+ failed,
332
+ totalUpdated: updated.length,
333
+ totalFailed: failed.length
334
+ };
335
+ }
267
336
  export {
268
337
  Update as default
269
338
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport os from \"os\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n loadSource,\n compareSkillsWithSource,\n compileAgents,\n updateLocalSkills,\n collectScopedSkillDirs,\n findSkillMatch,\n} from \"../lib/operations/index.js\";\nimport { CLI_BIN_NAME } from \"../consts.js\";\nimport {\n ERROR_MESSAGES,\n SUCCESS_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n} from \"../utils/messages.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\ntype UpdateConfirmProps = {\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n const homeDir = os.homedir();\n const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);\n\n if (!hasProject && !hasGlobal) {\n this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);\n return;\n }\n\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n const comparison = await compareSkillsWithSource(\n projectDir,\n sourceResult.sourcePath,\n sourceResult.matrix,\n );\n const allResults = comparison.merged;\n // Build skillBaseDir from separate results for updateLocalSkills dest path\n const skillBaseDir = new Map<string, string>();\n for (const r of comparison.projectResults) skillBaseDir.set(r.id, projectDir);\n for (const r of comparison.globalResults) {\n if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);\n }\n\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n if (args.skill) {\n const { match: foundSkill, similar } = findSkillMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`${CLI_BIN_NAME} search ${args.skill}\\` to search available skills.`);\n this.log(\"\");\n this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n outdatedSkills = [foundSkill];\n }\n\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);\n this.log(\"\");\n return;\n }\n\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n }\n\n this.log(\"\");\n\n const updateResult = await updateLocalSkills({\n skills: outdatedSkills,\n sourceResult,\n skillBaseDir,\n onProgress: (skillId) => this.log(`Updating ${skillId}...`),\n });\n\n for (const item of updateResult.updated) {\n this.log(` Updated ${item.id}`);\n }\n for (const item of updateResult.failed) {\n this.log(` Failed to update ${item.id}: ${item.error}`);\n }\n\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updateResult.totalUpdated > 0) {\n this.log(\"\");\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n\n try {\n const recompileResult = await compileAgents({\n projectDir,\n sourcePath: sourceResult.sourcePath,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);\n }\n }\n\n this.log(\"\");\n if (updateResult.totalFailed === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(\n `Update complete! ${updateResult.totalUpdated} skill(s) updated${agentMsg}.`,\n );\n } else {\n this.warn(\n `Update finished with errors: ${updateResult.totalUpdated} updated, ${updateResult.totalFailed} failed.`,\n );\n }\n this.log(\"\");\n\n if (updateResult.totalFailed > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { copy } from \"../utils/fs.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n loadSource,\n compareSkillsWithSource,\n compileAgents,\n collectScopedSkillDirs,\n findSkillMatch,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport {\n ERROR_MESSAGES,\n SUCCESS_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n} from \"../utils/messages.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\nimport { injectForkedFromMetadata, type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport type { SourceLoadResult } from \"../lib/loading/source-loader.js\";\n\ntype UpdateConfirmProps = {\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\ntype UpdateContext = {\n projectDir: string;\n homeDir: string;\n sourceResult: SourceLoadResult;\n allResults: SkillComparisonResult[];\n skillBaseDir: Map<string, string>;\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n\n try {\n const context = await this.loadContext(flags, projectDir);\n if (!context) return;\n\n const outdatedSkills = this.resolveTargetSkills(args.skill, context);\n if (!outdatedSkills) return;\n\n this.printUpdateTable(outdatedSkills);\n\n const confirmed = flags.yes || (await this.confirmUpdate());\n if (!confirmed) return;\n\n this.log(\"\");\n\n const updateResult = await this.executeUpdates(outdatedSkills, context);\n this.printUpdateResults(updateResult);\n\n const recompiledAgents = flags[\"no-recompile\"]\n ? []\n : await this.recompileAfterUpdate(updateResult, context);\n\n this.printCompletionSummary(updateResult, recompiledAgents);\n } catch (error) {\n const message = getErrorMessage(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n\n private async loadContext(\n flags: { source?: string },\n projectDir: string,\n ): Promise<UpdateContext | null> {\n const homeDir = os.homedir();\n const { hasProject, hasGlobal } = await collectScopedSkillDirs(projectDir);\n\n if (!hasProject && !hasGlobal) {\n this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);\n return null;\n }\n\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n const comparison = await compareSkillsWithSource(\n projectDir,\n sourceResult.sourcePath,\n sourceResult.matrix,\n );\n\n const skillBaseDir = new Map<string, string>();\n for (const r of comparison.projectResults) skillBaseDir.set(r.id, projectDir);\n for (const r of comparison.globalResults) {\n if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);\n }\n\n return {\n projectDir,\n homeDir,\n sourceResult,\n allResults: comparison.merged,\n skillBaseDir,\n };\n }\n\n private resolveTargetSkills(\n skillArg: string | undefined,\n context: UpdateContext,\n ): SkillComparisonResult[] | null {\n let outdatedSkills = context.allResults.filter((r) => r.status === \"outdated\");\n\n if (skillArg) {\n const { match: foundSkill, similar } = findSkillMatch(skillArg, context.allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${skillArg}\" not found.`);\n this.log(\"\");\n\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`${CLI_BIN_NAME} search ${skillArg}\\` to search available skills.`);\n this.log(\"\");\n this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return null;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return null;\n }\n\n outdatedSkills = [foundSkill];\n }\n\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);\n this.log(\"\");\n return null;\n }\n\n return outdatedSkills;\n }\n\n private printUpdateTable(outdatedSkills: SkillComparisonResult[]): void {\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n }\n\n private async confirmUpdate(): Promise<boolean> {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return false;\n }\n\n return true;\n }\n\n private async executeUpdates(\n outdatedSkills: SkillComparisonResult[],\n context: UpdateContext,\n ): Promise<UpdateLocalSkillsResult> {\n return updateLocalSkills({\n skills: outdatedSkills,\n sourceResult: context.sourceResult,\n skillBaseDir: context.skillBaseDir,\n onProgress: (skillId) => this.log(`Updating ${skillId}...`),\n });\n }\n\n private printUpdateResults(updateResult: UpdateLocalSkillsResult): void {\n for (const item of updateResult.updated) {\n this.log(` Updated ${item.id}`);\n }\n for (const item of updateResult.failed) {\n this.log(` Failed to update ${item.id}: ${item.error}`);\n }\n }\n\n private async recompileAfterUpdate(\n updateResult: UpdateLocalSkillsResult,\n context: UpdateContext,\n ): Promise<string[]> {\n if (updateResult.totalUpdated === 0) return [];\n\n this.log(\"\");\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n\n try {\n const { allSkills } = await discoverInstalledSkills(context.projectDir);\n const recompileResult = await compileAgents({\n projectDir: context.projectDir,\n sourcePath: context.sourceResult.sourcePath,\n skills: allSkills,\n });\n\n const recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n\n return recompiledAgents;\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);\n return [];\n }\n }\n\n private printCompletionSummary(\n updateResult: UpdateLocalSkillsResult,\n recompiledAgents: string[],\n ): void {\n this.log(\"\");\n if (updateResult.totalFailed === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(`Update complete! ${updateResult.totalUpdated} skill(s) updated${agentMsg}.`);\n } else {\n this.warn(\n `Update finished with errors: ${updateResult.totalUpdated} updated, ${updateResult.totalFailed} failed.`,\n );\n }\n this.log(\"\");\n\n if (updateResult.totalFailed > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n }\n}\n\ntype SkillUpdateResult = {\n id: string;\n success: boolean;\n newHash: string | null;\n error?: string;\n};\n\ntype UpdateLocalSkillsResult = {\n updated: SkillUpdateResult[];\n failed: SkillUpdateResult[];\n totalUpdated: number;\n totalFailed: number;\n};\n\ntype UpdateLocalSkillsOptions = {\n skills: SkillComparisonResult[];\n sourceResult: SourceLoadResult;\n skillBaseDir: Map<string, string>;\n /** Called before each skill update starts. Use for progress logging. */\n onProgress?: (skillId: string) => void;\n};\n\n/**\n * Updates local skills by copying from source and injecting metadata.\n *\n * For each outdated skill, copies the source version to the local skills\n * directory and injects forked-from metadata for change tracking.\n */\nasync function updateLocalSkills(\n options: UpdateLocalSkillsOptions,\n): Promise<UpdateLocalSkillsResult> {\n const { skills, sourceResult, skillBaseDir, onProgress } = options;\n const updated: SkillUpdateResult[] = [];\n const failed: SkillUpdateResult[] = [];\n\n for (const skill of skills) {\n onProgress?.(skill.id);\n if (!skill.sourcePath || !skill.sourceHash) {\n failed.push({\n id: skill.id,\n success: false,\n newHash: null,\n error: \"No source path available\",\n });\n continue;\n }\n\n const baseDir = skillBaseDir.get(skill.id) ?? process.cwd();\n const localSkillsPath = path.join(baseDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n await copy(srcPath, destPath);\n await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n updated.push({ id: skill.id, success: true, newHash: skill.sourceHash });\n } catch (error) {\n failed.push({ id: skill.id, success: false, newHash: null, error: getErrorMessage(error) });\n }\n }\n\n return {\n updated,\n failed,\n totalUpdated: updated.length,\n totalFailed: failed.length,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SkillSearch
4
- } from "../../chunk-BV2MIQ3O.js";
4
+ } from "../../chunk-I5AZKNNL.js";
5
5
  import "../../chunk-HEQVUIHQ.js";
6
6
  import "../../chunk-U3IGFMCY.js";
7
7
  import "../../chunk-HK53FRMU.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  showDashboard
4
- } from "../chunk-GED2F75H.js";
4
+ } from "../chunk-7FFNNDJQ.js";
5
5
  import "../chunk-HZQOFFKA.js";
6
6
  import "../chunk-UNEJKTLP.js";
7
7
  import "../chunk-YVFGISUO.js";
@@ -34,10 +34,8 @@ import "../chunk-HEQVUIHQ.js";
34
34
  import "../chunk-U3IGFMCY.js";
35
35
  import "../chunk-HK53FRMU.js";
36
36
  import "../chunk-B7KZLXHV.js";
37
- import "../chunk-DCVCFBQ7.js";
37
+ import "../chunk-5UJJQFET.js";
38
38
  import "../chunk-N6A7A4RA.js";
39
- import "../chunk-O5ZWS26C.js";
40
- import "../chunk-XQK4S22C.js";
41
39
  import "../chunk-FBZR46GC.js";
42
40
  import {
43
41
  detectInstallation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/hooks/init.ts"],"sourcesContent":["import { Hook } from \"@oclif/core\";\nimport { resolveSource } from \"../lib/configuration/index.js\";\nimport { detectInstallation } from \"../lib/installation/installation.js\";\nimport { showDashboard } from \"../commands/init.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport type { ConfigWithSource } from \"../base-command.js\";\n\nconst hook: Hook<\"init\"> = async function (options) {\n const projectDir = process.cwd();\n\n // When no command is given and project is already initialized, show dashboard\n if (options.id === undefined) {\n const installation = await detectInstallation(projectDir);\n\n if (installation) {\n const selectedCommand = await showDashboard(projectDir);\n if (selectedCommand) {\n await options.config.runCommand(selectedCommand);\n }\n this.exit(EXIT_CODES.SUCCESS);\n }\n }\n\n // Extract --source flag from argv (not yet parsed by oclif at this point)\n let sourceFlag: string | undefined;\n const sourceArgIndex = options.argv.indexOf(\"--source\");\n if (sourceArgIndex !== -1 && sourceArgIndex + 1 < options.argv.length) {\n sourceFlag = options.argv[sourceArgIndex + 1];\n } else {\n const sourceFlagWithEquals = options.argv.find((arg) => arg.startsWith(\"--source=\"));\n if (sourceFlagWithEquals) {\n sourceFlag = sourceFlagWithEquals.split(\"=\")[1];\n }\n }\n\n // Short form -s\n const sArgIndex = options.argv.indexOf(\"-s\");\n if (sArgIndex !== -1 && sArgIndex + 1 < options.argv.length) {\n sourceFlag = options.argv[sArgIndex + 1];\n }\n\n try {\n const resolvedConfig = await resolveSource(sourceFlag, projectDir);\n // Boundary cast: oclif Config is a class (not augmentable); read in BaseCommand.sourceConfig\n (options.config as unknown as ConfigWithSource).sourceConfig = resolvedConfig;\n } catch (error) {\n // Let the command handle config failures - commands can check if sourceConfig is undefined\n }\n};\n\nexport default hook;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAOA,IAAM,OAAqB,eAAgB,SAAS;AAClD,QAAM,aAAa,QAAQ,IAAI;AAG/B,MAAI,QAAQ,OAAO,QAAW;AAC5B,UAAM,eAAe,MAAM,mBAAmB,UAAU;AAExD,QAAI,cAAc;AAChB,YAAM,kBAAkB,MAAM,cAAc,UAAU;AACtD,UAAI,iBAAiB;AACnB,cAAM,QAAQ,OAAO,WAAW,eAAe;AAAA,MACjD;AACA,WAAK,KAAK,WAAW,OAAO;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI;AACJ,QAAM,iBAAiB,QAAQ,KAAK,QAAQ,UAAU;AACtD,MAAI,mBAAmB,MAAM,iBAAiB,IAAI,QAAQ,KAAK,QAAQ;AACrE,iBAAa,QAAQ,KAAK,iBAAiB,CAAC;AAAA,EAC9C,OAAO;AACL,UAAM,uBAAuB,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,WAAW,CAAC;AACnF,QAAI,sBAAsB;AACxB,mBAAa,qBAAqB,MAAM,GAAG,EAAE,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,KAAK,QAAQ,IAAI;AAC3C,MAAI,cAAc,MAAM,YAAY,IAAI,QAAQ,KAAK,QAAQ;AAC3D,iBAAa,QAAQ,KAAK,YAAY,CAAC;AAAA,EACzC;AAEA,MAAI;AACF,UAAM,iBAAiB,MAAM,cAAc,YAAY,UAAU;AAEjE,IAAC,QAAQ,OAAuC,eAAe;AAAA,EACjE,SAAS,OAAO;AAAA,EAEhB;AACF;AAEA,IAAO,eAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/cli/hooks/init.ts"],"sourcesContent":["import { Hook } from \"@oclif/core\";\nimport { resolveSource } from \"../lib/configuration/index.js\";\nimport { detectInstallation } from \"../lib/installation/installation.js\";\nimport { showDashboard } from \"../commands/init.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport type { ConfigWithSource } from \"../base-command.js\";\n\nconst hook: Hook<\"init\"> = async function (options) {\n const projectDir = process.cwd();\n\n // When no command is given and project is already initialized, show dashboard\n if (options.id === undefined) {\n const installation = await detectInstallation(projectDir);\n\n if (installation) {\n const selectedCommand = await showDashboard(projectDir);\n if (selectedCommand) {\n await options.config.runCommand(selectedCommand);\n }\n this.exit(EXIT_CODES.SUCCESS);\n }\n }\n\n // Extract --source flag from argv (not yet parsed by oclif at this point)\n let sourceFlag: string | undefined;\n const sourceArgIndex = options.argv.indexOf(\"--source\");\n if (sourceArgIndex !== -1 && sourceArgIndex + 1 < options.argv.length) {\n sourceFlag = options.argv[sourceArgIndex + 1];\n } else {\n const sourceFlagWithEquals = options.argv.find((arg) => arg.startsWith(\"--source=\"));\n if (sourceFlagWithEquals) {\n sourceFlag = sourceFlagWithEquals.split(\"=\")[1];\n }\n }\n\n // Short form -s\n const sArgIndex = options.argv.indexOf(\"-s\");\n if (sArgIndex !== -1 && sArgIndex + 1 < options.argv.length) {\n sourceFlag = options.argv[sArgIndex + 1];\n }\n\n try {\n const resolvedConfig = await resolveSource(sourceFlag, projectDir);\n // Boundary cast: oclif Config is a class (not augmentable); read in BaseCommand.sourceConfig\n (options.config as unknown as ConfigWithSource).sourceConfig = resolvedConfig;\n } catch (error) {\n // Let the command handle config failures - commands can check if sourceConfig is undefined\n }\n};\n\nexport default hook;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAOA,IAAM,OAAqB,eAAgB,SAAS;AAClD,QAAM,aAAa,QAAQ,IAAI;AAG/B,MAAI,QAAQ,OAAO,QAAW;AAC5B,UAAM,eAAe,MAAM,mBAAmB,UAAU;AAExD,QAAI,cAAc;AAChB,YAAM,kBAAkB,MAAM,cAAc,UAAU;AACtD,UAAI,iBAAiB;AACnB,cAAM,QAAQ,OAAO,WAAW,eAAe;AAAA,MACjD;AACA,WAAK,KAAK,WAAW,OAAO;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI;AACJ,QAAM,iBAAiB,QAAQ,KAAK,QAAQ,UAAU;AACtD,MAAI,mBAAmB,MAAM,iBAAiB,IAAI,QAAQ,KAAK,QAAQ;AACrE,iBAAa,QAAQ,KAAK,iBAAiB,CAAC;AAAA,EAC9C,OAAO;AACL,UAAM,uBAAuB,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,WAAW,CAAC;AACnF,QAAI,sBAAsB;AACxB,mBAAa,qBAAqB,MAAM,GAAG,EAAE,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,KAAK,QAAQ,IAAI;AAC3C,MAAI,cAAc,MAAM,YAAY,IAAI,QAAQ,KAAK,QAAQ;AAC3D,iBAAa,QAAQ,KAAK,YAAY,CAAC;AAAA,EACzC;AAEA,MAAI;AACF,UAAM,iBAAiB,MAAM,cAAc,YAAY,UAAU;AAEjE,IAAC,QAAQ,OAAuC,eAAe;AAAA,EACjE,SAAS,OAAO;AAAA,EAEhB;AACF;AAEA,IAAO,eAAQ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-inc/cli",
3
- "version": "0.86.0",
3
+ "version": "0.87.0",
4
4
  "description": "CLI for managing Agents Inc. skills, stacks, and agents for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/components/skill-search/skill-search.tsx","../src/cli/components/hooks/use-filtered-results.ts"],"sourcesContent":["import React, { useState, useCallback } from \"react\";\nimport { Box, Text, useApp, useInput } from \"ink\";\nimport { ThemeProvider } from \"@inkjs/ui\";\nimport { cliTheme } from \"../themes/default.js\";\nimport type { SkillId } from \"../../types/index.js\";\nimport type { SourcedSkill } from \"../../lib/operations/search-skills.js\";\nimport { CLI_COLORS, UI_SYMBOLS, UI_LAYOUT } from \"../../consts.js\";\nimport {\n HOTKEY_COPY_LINK,\n KEY_LABEL_ENTER,\n KEY_LABEL_ESC,\n KEY_LABEL_SPACE,\n KEY_LABEL_VIM_VERT,\n isHotkey,\n} from \"../wizard/hotkeys.js\";\nimport { useTextInput } from \"../hooks/use-text-input.js\";\nimport { useFilteredResults } from \"../hooks/use-filtered-results.js\";\nimport { truncateText } from \"../../utils/string.js\";\n\nexport type { SourcedSkill };\n\nexport type SkillSearchResult = {\n selectedSkills: SourcedSkill[];\n cancelled: boolean;\n};\n\nexport type SkillSearchProps = {\n skills: SourcedSkill[];\n sourceCount: number;\n initialQuery?: string;\n onComplete: (result: SkillSearchResult) => void;\n onCancel: () => void;\n};\n\nconst {\n MAX_VISIBLE_RESULTS,\n DESCRIPTION_WIDTH,\n COPIED_MESSAGE_TIMEOUT_MS,\n FALLBACK_MESSAGE_TIMEOUT_MS,\n} = UI_LAYOUT;\nconst { CHECKBOX_CHECKED, CHECKBOX_UNCHECKED } = UI_SYMBOLS;\n\nfunction matchesQuery(skill: SourcedSkill, query: string): boolean {\n if (!query.trim()) return true;\n\n const lowerQuery = query.toLowerCase();\n\n if (skill.id.toLowerCase().includes(lowerQuery)) return true;\n if (skill.displayName.toLowerCase().includes(lowerQuery)) return true;\n if (skill.slug.toLowerCase().includes(lowerQuery)) return true;\n if (skill.description.toLowerCase().includes(lowerQuery)) return true;\n if (skill.category.toLowerCase().includes(lowerQuery)) return true;\n return skill.sourceName.toLowerCase().includes(lowerQuery);\n}\n\ntype HeaderProps = {\n sourceCount: number;\n};\n\nconst Header: React.FC<HeaderProps> = ({ sourceCount }) => {\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n borderStyle=\"single\"\n borderBottom={false}\n borderLeft={false}\n borderRight={false}\n paddingX={1}\n >\n <Text bold color={CLI_COLORS.PRIMARY}>\n Search Skills\n </Text>\n <Text dimColor>\n {sourceCount} source{sourceCount !== 1 ? \"s\" : \"\"}\n </Text>\n </Box>\n );\n};\n\ntype SearchInputProps = {\n value: string;\n};\n\nconst SearchInput: React.FC<SearchInputProps> = ({ value }) => {\n return (\n <Box paddingX={1} paddingY={1}>\n <Text color={CLI_COLORS.FOCUS}>{\">\"} </Text>\n <Text>{value}</Text>\n <Text color={CLI_COLORS.FOCUS}>_</Text>\n </Box>\n );\n};\n\ntype ResultItemProps = {\n skill: SourcedSkill;\n isSelected: boolean;\n isFocused: boolean;\n};\n\nconst ResultItem: React.FC<ResultItemProps> = ({ skill, isSelected, isFocused }) => {\n const checkbox = isSelected ? CHECKBOX_CHECKED : CHECKBOX_UNCHECKED;\n const displayName = skill.displayName;\n return (\n <Box flexDirection=\"row\" gap={1}>\n <Text\n color={isFocused ? CLI_COLORS.FOCUS : isSelected ? CLI_COLORS.SUCCESS : undefined}\n bold={isFocused}\n backgroundColor={isFocused ? \"#333333\" : undefined}\n >\n {\" \"}\n {checkbox}{\" \"}\n </Text>\n <Box width={14}>\n <Text dimColor>{truncateText(skill.sourceName, 12)}</Text>\n </Box>\n <Box width={24}>\n <Text color={isFocused ? CLI_COLORS.FOCUS : undefined} bold={isFocused || isSelected}>\n {truncateText(displayName, 22)}\n </Text>\n </Box>\n <Text dimColor>{truncateText(skill.description, DESCRIPTION_WIDTH)}</Text>\n </Box>\n );\n};\n\ntype ResultsListProps = {\n results: SourcedSkill[];\n selectedIds: Set<SkillId>;\n focusedIndex: number;\n scrollOffset: number;\n};\n\nconst ResultsList: React.FC<ResultsListProps> = ({\n results,\n selectedIds,\n focusedIndex,\n scrollOffset,\n}) => {\n const visibleResults = results.slice(scrollOffset, scrollOffset + MAX_VISIBLE_RESULTS);\n\n if (results.length === 0) {\n return (\n <Box paddingX={1} paddingY={1}>\n <Text dimColor>No skills found matching your search.</Text>\n </Box>\n );\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderTop={false}\n borderBottom={false}\n paddingX={1}\n >\n {visibleResults.map((skill, index) => {\n const actualIndex = scrollOffset + index;\n return (\n <ResultItem\n key={skill.id}\n skill={skill}\n isSelected={selectedIds.has(skill.id)}\n isFocused={actualIndex === focusedIndex}\n />\n );\n })}\n </Box>\n );\n};\n\ntype StatusBarProps = {\n resultCount: number;\n selectedCount: number;\n};\n\nconst StatusBar: React.FC<StatusBarProps> = ({ resultCount, selectedCount }) => {\n return (\n <Box paddingX={1}>\n <Text dimColor>\n {resultCount} result{resultCount !== 1 ? \"s\" : \"\"}\n {selectedCount > 0 && <Text color={CLI_COLORS.SUCCESS}> | {selectedCount} selected</Text>}\n </Text>\n </Box>\n );\n};\n\ntype FooterProps = {\n hasSelection: boolean;\n};\n\nconst Footer: React.FC<FooterProps> = ({ hasSelection }) => {\n return (\n <Box\n flexDirection=\"row\"\n justifyContent=\"center\"\n gap={2}\n borderStyle=\"single\"\n borderTop={false}\n borderLeft={false}\n borderRight={false}\n paddingX={1}\n marginTop={1}\n >\n <Text dimColor>\n <Text color={CLI_COLORS.UNFOCUSED}>{KEY_LABEL_VIM_VERT}</Text> navigate\n </Text>\n <Text dimColor>\n <Text color={CLI_COLORS.UNFOCUSED}>{KEY_LABEL_SPACE}</Text> select\n </Text>\n {hasSelection && (\n <Text dimColor>\n <Text color={CLI_COLORS.SUCCESS}>{KEY_LABEL_ENTER}</Text> import\n </Text>\n )}\n <Text dimColor>\n <Text color={CLI_COLORS.UNFOCUSED}>{HOTKEY_COPY_LINK.label}</Text> copy link\n </Text>\n <Text dimColor>\n <Text color={CLI_COLORS.WARNING}>{KEY_LABEL_ESC}</Text> cancel\n </Text>\n </Box>\n );\n};\n\nexport const SkillSearch: React.FC<SkillSearchProps> = ({\n skills,\n sourceCount,\n initialQuery = \"\",\n onComplete,\n onCancel,\n}) => {\n const { exit } = useApp();\n\n const { value: query, handleInput: handleTextInput } = useTextInput(initialQuery);\n const [selectedIds, setSelectedIds] = useState<Set<SkillId>>(new Set());\n const [copiedMessage, setCopiedMessage] = useState<string | null>(null);\n\n const {\n filteredResults,\n safeFocusedIndex,\n focusedItem: focusedSkill,\n scrollOffset,\n moveUp,\n moveDown,\n } = useFilteredResults({\n items: skills,\n query,\n filterFn: matchesQuery,\n maxVisible: MAX_VISIBLE_RESULTS,\n });\n\n const toggleSelection = useCallback((skillId: SkillId) => {\n setSelectedIds((prev) => {\n const next = new Set(prev);\n if (next.has(skillId)) {\n next.delete(skillId);\n } else {\n next.add(skillId);\n }\n return next;\n });\n }, []);\n\n const copySkillLink = useCallback(async (skill: SourcedSkill) => {\n const link = skill.sourceUrl ? `${skill.sourceUrl}/${skill.id}` : skill.id;\n\n try {\n // OSC 52 terminal clipboard escape sequence\n const encoded = Buffer.from(link).toString(\"base64\");\n process.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n setCopiedMessage(`Copied: ${link}`);\n setTimeout(() => setCopiedMessage(null), COPIED_MESSAGE_TIMEOUT_MS);\n } catch {\n setCopiedMessage(`Link: ${link}`);\n setTimeout(() => setCopiedMessage(null), FALLBACK_MESSAGE_TIMEOUT_MS);\n }\n }, []);\n\n useInput((input, key) => {\n if (key.escape) {\n onCancel();\n exit();\n return;\n }\n\n if (key.return) {\n if (selectedIds.size > 0) {\n const selectedSkills = filteredResults.filter((s) => selectedIds.has(s.id));\n onComplete({\n selectedSkills,\n cancelled: false,\n });\n exit();\n }\n return;\n }\n\n if (input === \" \" && focusedSkill) {\n toggleSelection(focusedSkill.id);\n return;\n }\n\n if (isHotkey(input, HOTKEY_COPY_LINK) && focusedSkill) {\n void copySkillLink(focusedSkill);\n return;\n }\n\n const isUp = key.upArrow || input === \"k\";\n const isDown = key.downArrow || input === \"j\";\n\n if (isUp) {\n moveUp();\n }\n\n if (isDown) {\n moveDown();\n }\n\n handleTextInput(input, key);\n });\n\n return (\n <ThemeProvider theme={cliTheme}>\n <Box flexDirection=\"column\">\n <Header sourceCount={sourceCount} />\n <SearchInput value={query} />\n <ResultsList\n results={filteredResults}\n selectedIds={selectedIds}\n focusedIndex={safeFocusedIndex}\n scrollOffset={scrollOffset}\n />\n <StatusBar resultCount={filteredResults.length} selectedCount={selectedIds.size} />\n {copiedMessage && (\n <Box paddingX={1}>\n <Text color={CLI_COLORS.SUCCESS}>{copiedMessage}</Text>\n </Box>\n )}\n <Footer hasSelection={selectedIds.size > 0} />\n </Box>\n </ThemeProvider>\n );\n};\n","import { useState, useMemo, useEffect, useCallback, useRef } from \"react\";\n\ntype UseFilteredResultsOptions<T> = {\n /** Items to filter */\n items: T[];\n /** Current search query */\n query: string;\n /** Filter predicate — returns true if item matches the query */\n filterFn: (item: T, query: string) => boolean;\n /** Number of visible rows in the scrollable viewport */\n maxVisible: number;\n};\n\ntype UseFilteredResultsResult<T> = {\n /** Items that pass the filter */\n filteredResults: T[];\n /** Index clamped to valid range */\n safeFocusedIndex: number;\n /** The item at safeFocusedIndex, or undefined when empty */\n focusedItem: T | undefined;\n /** First visible row offset for windowed rendering */\n scrollOffset: number;\n /** Move focus up one row (clamped, adjusts scroll) */\n moveUp: () => void;\n /** Move focus down one row (clamped, adjusts scroll) */\n moveDown: () => void;\n};\n\n/**\n * Manages filtered list state: query-based filtering, focus tracking,\n * and scroll-offset synchronisation for windowed rendering.\n * Focus and scroll reset automatically when the query changes.\n */\nexport function useFilteredResults<T>({\n items,\n query,\n filterFn,\n maxVisible,\n}: UseFilteredResultsOptions<T>): UseFilteredResultsResult<T> {\n const [focusedIndex, setFocusedIndex] = useState(0);\n const [scrollOffset, setScrollOffset] = useState(0);\n\n useEffect(() => {\n setFocusedIndex(0);\n setScrollOffset(0);\n }, [query]);\n\n const filteredResults = useMemo(() => {\n return items.filter((item) => filterFn(item, query));\n }, [items, query, filterFn]);\n\n const safeFocusedIndex = Math.min(focusedIndex, Math.max(0, filteredResults.length - 1));\n const focusedItem = filteredResults[safeFocusedIndex] as T | undefined;\n\n // Refs for stable callback access (matches use-keyboard-navigation pattern)\n const safeFocusedIndexRef = useRef(safeFocusedIndex);\n const scrollOffsetRef = useRef(scrollOffset);\n const resultCountRef = useRef(filteredResults.length);\n\n useEffect(() => {\n safeFocusedIndexRef.current = safeFocusedIndex;\n }, [safeFocusedIndex]);\n\n useEffect(() => {\n scrollOffsetRef.current = scrollOffset;\n }, [scrollOffset]);\n\n useEffect(() => {\n resultCountRef.current = filteredResults.length;\n }, [filteredResults.length]);\n\n const moveUp = useCallback(() => {\n const current = safeFocusedIndexRef.current;\n if (current <= 0) return;\n const newIndex = current - 1;\n setFocusedIndex(newIndex);\n if (newIndex < scrollOffsetRef.current) {\n setScrollOffset(newIndex);\n }\n }, []);\n\n const moveDown = useCallback(() => {\n const current = safeFocusedIndexRef.current;\n if (current >= resultCountRef.current - 1) return;\n const newIndex = current + 1;\n setFocusedIndex(newIndex);\n if (newIndex >= scrollOffsetRef.current + maxVisible) {\n setScrollOffset(newIndex - maxVisible + 1);\n }\n }, [maxVisible]);\n\n return {\n filteredResults,\n safeFocusedIndex,\n focusedItem,\n scrollOffset,\n moveUp,\n moveDown,\n };\n}\n"],"mappings":"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","names":["useState","useCallback","useState","useCallback"]}