@skrr-ai/cli 0.1.36 → 0.1.38

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 (266) hide show
  1. package/README.md +17 -4
  2. package/bin/dev-fallback.js +167 -4
  3. package/dist/base-command.js +46 -2
  4. package/dist/commands/agents/actions/create.d.ts +5 -0
  5. package/dist/commands/agents/actions/create.js +42 -5
  6. package/dist/commands/agents/actions/delete.d.ts +1 -0
  7. package/dist/commands/agents/actions/delete.js +7 -0
  8. package/dist/commands/agents/actions/update.d.ts +5 -0
  9. package/dist/commands/agents/actions/update.js +27 -1
  10. package/dist/commands/agents/api-actions/add.d.ts +41 -0
  11. package/dist/commands/agents/api-actions/add.js +205 -0
  12. package/dist/commands/agents/api-actions/index.d.ts +39 -0
  13. package/dist/commands/agents/api-actions/index.js +103 -0
  14. package/dist/commands/agents/api-actions/remove.d.ts +14 -0
  15. package/dist/commands/agents/api-actions/remove.js +36 -0
  16. package/dist/commands/agents/avatar/default/apply.d.ts +25 -0
  17. package/dist/commands/agents/avatar/default/apply.js +56 -0
  18. package/dist/commands/agents/avatar/default/index.d.ts +29 -0
  19. package/dist/commands/agents/avatar/default/index.js +61 -0
  20. package/dist/commands/agents/avatar/default/set.d.ts +24 -0
  21. package/dist/commands/agents/avatar/default/set.js +120 -0
  22. package/dist/commands/agents/avatar/library/delete.d.ts +20 -0
  23. package/dist/commands/agents/avatar/library/delete.js +47 -0
  24. package/dist/commands/agents/avatar/library/index.d.ts +16 -0
  25. package/dist/commands/agents/avatar/library/index.js +56 -0
  26. package/dist/commands/agents/avatar/presets.d.ts +19 -0
  27. package/dist/commands/agents/avatar/presets.js +56 -0
  28. package/dist/commands/agents/avatar/upload.js +7 -1
  29. package/dist/commands/agents/categories/create.d.ts +14 -0
  30. package/dist/commands/agents/categories/create.js +46 -0
  31. package/dist/commands/agents/categories/delete.d.ts +13 -0
  32. package/dist/commands/agents/categories/delete.js +41 -0
  33. package/dist/commands/agents/categories/index.d.ts +36 -0
  34. package/dist/commands/agents/categories/index.js +135 -0
  35. package/dist/commands/agents/categories/update.d.ts +22 -0
  36. package/dist/commands/agents/categories/update.js +59 -0
  37. package/dist/commands/agents/chat.d.ts +21 -0
  38. package/dist/commands/agents/chat.js +94 -7
  39. package/dist/commands/agents/create.d.ts +10 -0
  40. package/dist/commands/agents/create.js +64 -3
  41. package/dist/commands/agents/ensure-default.d.ts +27 -0
  42. package/dist/commands/agents/ensure-default.js +65 -0
  43. package/dist/commands/agents/list.d.ts +15 -0
  44. package/dist/commands/agents/list.js +31 -1
  45. package/dist/commands/agents/mute.d.ts +16 -0
  46. package/dist/commands/agents/mute.js +38 -0
  47. package/dist/commands/agents/pin.d.ts +16 -0
  48. package/dist/commands/agents/pin.js +38 -0
  49. package/dist/commands/agents/scene-background/upload.d.ts +30 -0
  50. package/dist/commands/agents/scene-background/upload.js +97 -0
  51. package/dist/commands/agents/show.js +13 -0
  52. package/dist/commands/agents/tools/auth.d.ts +19 -0
  53. package/dist/commands/agents/tools/auth.js +41 -0
  54. package/dist/commands/agents/tools/calls.d.ts +36 -0
  55. package/dist/commands/agents/tools/calls.js +117 -0
  56. package/dist/commands/agents/tools/index.d.ts +20 -0
  57. package/dist/commands/agents/tools/index.js +77 -0
  58. package/dist/commands/agents/unmute.d.ts +16 -0
  59. package/dist/commands/agents/unmute.js +38 -0
  60. package/dist/commands/agents/unpin.d.ts +16 -0
  61. package/dist/commands/agents/unpin.js +38 -0
  62. package/dist/commands/agents/update.d.ts +12 -0
  63. package/dist/commands/agents/update.js +74 -3
  64. package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
  65. package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
  66. package/dist/commands/convos/messages.d.ts +13 -0
  67. package/dist/commands/convos/messages.js +40 -16
  68. package/dist/commands/daemon/index.js +8 -1
  69. package/dist/commands/daemon/logs.d.ts +26 -0
  70. package/dist/commands/daemon/logs.js +56 -0
  71. package/dist/commands/daemon/uninstall.js +1 -1
  72. package/dist/commands/followups/act.d.ts +22 -0
  73. package/dist/commands/followups/act.js +103 -0
  74. package/dist/commands/followups/cancel.d.ts +20 -0
  75. package/dist/commands/followups/cancel.js +50 -0
  76. package/dist/commands/followups/checkin.d.ts +27 -0
  77. package/dist/commands/followups/checkin.js +107 -0
  78. package/dist/commands/followups/list.d.ts +24 -0
  79. package/dist/commands/followups/list.js +90 -0
  80. package/dist/commands/followups/observability.d.ts +23 -0
  81. package/dist/commands/followups/observability.js +114 -0
  82. package/dist/commands/followups/remind.d.ts +26 -0
  83. package/dist/commands/followups/remind.js +106 -0
  84. package/dist/commands/followups/reschedule.d.ts +15 -0
  85. package/dist/commands/followups/reschedule.js +48 -0
  86. package/dist/commands/followups/resolve.d.ts +23 -0
  87. package/dist/commands/followups/resolve.js +54 -0
  88. package/dist/commands/followups/show.d.ts +12 -0
  89. package/dist/commands/followups/show.js +46 -0
  90. package/dist/commands/followups/watch.d.ts +51 -0
  91. package/dist/commands/followups/watch.js +211 -0
  92. package/dist/commands/goals/labels/add.js +19 -2
  93. package/dist/commands/goals/labels/remove.js +22 -2
  94. package/dist/commands/harnesses/forget.js +28 -0
  95. package/dist/commands/harnesses/install.d.ts +41 -0
  96. package/dist/commands/harnesses/install.js +165 -0
  97. package/dist/commands/harnesses/installers.d.ts +45 -0
  98. package/dist/commands/harnesses/installers.js +155 -0
  99. package/dist/commands/harnesses/list.d.ts +82 -1
  100. package/dist/commands/harnesses/list.js +104 -12
  101. package/dist/commands/harnesses/models.js +10 -1
  102. package/dist/commands/harnesses/show.d.ts +15 -0
  103. package/dist/commands/harnesses/show.js +44 -3
  104. package/dist/commands/harnesses/update.js +1 -1
  105. package/dist/commands/harnesses/usage.d.ts +25 -0
  106. package/dist/commands/harnesses/usage.js +24 -2
  107. package/dist/commands/instructions/status.js +13 -1
  108. package/dist/commands/labels/list.d.ts +24 -1
  109. package/dist/commands/labels/list.js +62 -19
  110. package/dist/commands/machines/dedicated/catalog.js +4 -15
  111. package/dist/commands/machines/dedicated/create.d.ts +8 -0
  112. package/dist/commands/machines/dedicated/create.js +58 -1
  113. package/dist/commands/machines/dedicated/destroy.js +18 -4
  114. package/dist/commands/machines/dedicated/list.js +9 -6
  115. package/dist/commands/machines/hosted/list.js +12 -0
  116. package/dist/commands/machines/list.js +11 -0
  117. package/dist/commands/machines/show.d.ts +1 -0
  118. package/dist/commands/machines/show.js +40 -11
  119. package/dist/commands/memory/governance/index.d.ts +21 -0
  120. package/dist/commands/memory/governance/index.js +64 -0
  121. package/dist/commands/memory/governance/set.d.ts +24 -0
  122. package/dist/commands/memory/governance/set.js +95 -0
  123. package/dist/commands/memory/provenance.d.ts +18 -0
  124. package/dist/commands/memory/provenance.js +66 -0
  125. package/dist/commands/profiles/list.d.ts +23 -0
  126. package/dist/commands/profiles/list.js +96 -0
  127. package/dist/commands/search/skills.d.ts +11 -1
  128. package/dist/commands/search/skills.js +26 -8
  129. package/dist/commands/skills/details.d.ts +2 -0
  130. package/dist/commands/skills/details.js +24 -1
  131. package/dist/commands/skills/import-as-actions.d.ts +32 -0
  132. package/dist/commands/skills/import-as-actions.js +175 -0
  133. package/dist/commands/skills/install.d.ts +2 -0
  134. package/dist/commands/skills/install.js +24 -1
  135. package/dist/commands/skills/invocable.js +6 -2
  136. package/dist/commands/skills/local.d.ts +40 -0
  137. package/dist/commands/skills/local.js +160 -0
  138. package/dist/commands/skills/search.d.ts +11 -1
  139. package/dist/commands/skills/search.js +29 -8
  140. package/dist/commands/spaces/actions/add.js +23 -5
  141. package/dist/commands/spaces/actions/available.js +3 -0
  142. package/dist/commands/spaces/actions/list.d.ts +5 -0
  143. package/dist/commands/spaces/actions/list.js +49 -3
  144. package/dist/commands/spaces/actions/run.d.ts +28 -0
  145. package/dist/commands/spaces/actions/run.js +146 -0
  146. package/dist/commands/spaces/actions/update.js +27 -5
  147. package/dist/commands/spaces/create.d.ts +3 -0
  148. package/dist/commands/spaces/create.js +32 -2
  149. package/dist/commands/spaces/label-summaries.d.ts +27 -0
  150. package/dist/commands/spaces/label-summaries.js +64 -0
  151. package/dist/commands/spaces/labels/add.js +19 -2
  152. package/dist/commands/spaces/labels/remove.js +22 -2
  153. package/dist/commands/spaces/show.js +2 -0
  154. package/dist/commands/spaces/task-rollups.d.ts +5 -0
  155. package/dist/commands/spaces/task-rollups.js +15 -4
  156. package/dist/commands/spaces/update.d.ts +5 -0
  157. package/dist/commands/spaces/update.js +41 -4
  158. package/dist/commands/spaces/workflows/lifecycle-diagnostics.d.ts +11 -0
  159. package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +105 -0
  160. package/dist/commands/tasks/actions/attach.js +32 -7
  161. package/dist/commands/tasks/complete.d.ts +1 -0
  162. package/dist/commands/tasks/complete.js +21 -1
  163. package/dist/commands/tasks/create.d.ts +3 -0
  164. package/dist/commands/tasks/create.js +34 -2
  165. package/dist/commands/tasks/events/append.js +29 -6
  166. package/dist/commands/tasks/expectations/assess.d.ts +12 -0
  167. package/dist/commands/tasks/expectations/assess.js +123 -14
  168. package/dist/commands/tasks/expectations.js +95 -17
  169. package/dist/commands/tasks/follow-up.js +2 -2
  170. package/dist/commands/tasks/labels/attach.js +20 -3
  171. package/dist/commands/tasks/labels/detach.js +21 -3
  172. package/dist/commands/tasks/lifecycle/attach.d.ts +14 -0
  173. package/dist/commands/tasks/lifecycle/attach.js +47 -0
  174. package/dist/commands/tasks/lifecycle/definitions.d.ts +11 -0
  175. package/dist/commands/tasks/lifecycle/definitions.js +59 -0
  176. package/dist/commands/tasks/lifecycle/detach.d.ts +19 -0
  177. package/dist/commands/tasks/lifecycle/detach.js +72 -0
  178. package/dist/commands/tasks/lifecycle/history.d.ts +13 -0
  179. package/dist/commands/tasks/lifecycle/history.js +38 -0
  180. package/dist/commands/tasks/lifecycle/migrate.d.ts +14 -0
  181. package/dist/commands/tasks/lifecycle/migrate.js +68 -0
  182. package/dist/commands/tasks/lifecycle/reconcile.d.ts +11 -0
  183. package/dist/commands/tasks/lifecycle/reconcile.js +27 -0
  184. package/dist/commands/tasks/lifecycle/reopen.d.ts +15 -0
  185. package/dist/commands/tasks/lifecycle/reopen.js +71 -0
  186. package/dist/commands/tasks/lifecycle/show.d.ts +11 -0
  187. package/dist/commands/tasks/lifecycle/show.js +27 -0
  188. package/dist/commands/tasks/lifecycle/start.d.ts +12 -0
  189. package/dist/commands/tasks/lifecycle/start.js +30 -0
  190. package/dist/commands/tasks/lifecycle/transition.d.ts +15 -0
  191. package/dist/commands/tasks/lifecycle/transition.js +109 -0
  192. package/dist/commands/tasks/list.js +16 -9
  193. package/dist/commands/tasks/move.d.ts +1 -0
  194. package/dist/commands/tasks/move.js +29 -0
  195. package/dist/commands/tasks/result/submit.js +11 -1
  196. package/dist/commands/tasks/review-queue.d.ts +44 -0
  197. package/dist/commands/tasks/review-queue.js +314 -0
  198. package/dist/commands/tasks/show.d.ts +11 -0
  199. package/dist/commands/tasks/show.js +139 -4
  200. package/dist/commands/tasks/trust.js +7 -2
  201. package/dist/commands/tasks/update.d.ts +1 -0
  202. package/dist/commands/tasks/update.js +83 -0
  203. package/dist/commands/tasks/updates/add.js +1 -1
  204. package/dist/commands/token/list.d.ts +22 -0
  205. package/dist/commands/token/list.js +68 -0
  206. package/dist/commands/token/revoke.d.ts +23 -0
  207. package/dist/commands/token/revoke.js +53 -0
  208. package/dist/lib/agent-actions.d.ts +92 -11
  209. package/dist/lib/agent-actions.js +171 -25
  210. package/dist/lib/agent-config.d.ts +11 -0
  211. package/dist/lib/agent-config.js +85 -3
  212. package/dist/lib/agent-pin-mute.d.ts +29 -0
  213. package/dist/lib/agent-pin-mute.js +30 -0
  214. package/dist/lib/agent-visual-refs.d.ts +33 -0
  215. package/dist/lib/agent-visual-refs.js +267 -0
  216. package/dist/lib/agentic-stream.d.ts +6 -0
  217. package/dist/lib/agentic-stream.js +34 -3
  218. package/dist/lib/assignee-resolver.d.ts +1 -1
  219. package/dist/lib/assignee-resolver.js +8 -0
  220. package/dist/lib/bulk-task-targets.d.ts +12 -0
  221. package/dist/lib/bulk-task-targets.js +34 -1
  222. package/dist/lib/cli-installers.d.ts +130 -0
  223. package/dist/lib/cli-installers.js +145 -0
  224. package/dist/lib/command-miss.js +55 -7
  225. package/dist/lib/dedicated-lease-command.d.ts +13 -0
  226. package/dist/lib/dedicated-lease-command.js +22 -1
  227. package/dist/lib/dedicated-machines.d.ts +95 -1
  228. package/dist/lib/dedicated-machines.js +236 -2
  229. package/dist/lib/failed-lookup.d.ts +3 -0
  230. package/dist/lib/failed-lookup.js +40 -0
  231. package/dist/lib/first-party-harness-agent.js +16 -2
  232. package/dist/lib/first-party-harness-doctor.d.ts +15 -0
  233. package/dist/lib/first-party-harness-doctor.js +126 -27
  234. package/dist/lib/followups.d.ts +115 -0
  235. package/dist/lib/followups.js +127 -0
  236. package/dist/lib/harnesses.d.ts +8 -0
  237. package/dist/lib/instruction-input.d.ts +19 -1
  238. package/dist/lib/instruction-input.js +52 -1
  239. package/dist/lib/label-ref.d.ts +95 -0
  240. package/dist/lib/label-ref.js +163 -0
  241. package/dist/lib/label-scope.d.ts +17 -2
  242. package/dist/lib/label-scope.js +27 -7
  243. package/dist/lib/local-skills.d.ts +98 -0
  244. package/dist/lib/local-skills.js +195 -0
  245. package/dist/lib/machines.d.ts +10 -10
  246. package/dist/lib/machines.js +23 -1
  247. package/dist/lib/search-query.d.ts +19 -0
  248. package/dist/lib/search-query.js +35 -0
  249. package/dist/lib/space-custom-actions.d.ts +72 -0
  250. package/dist/lib/space-custom-actions.js +117 -0
  251. package/dist/lib/space-resolver.d.ts +1 -21
  252. package/dist/lib/space-resolver.js +19 -10
  253. package/dist/lib/task-closure.d.ts +33 -0
  254. package/dist/lib/task-closure.js +104 -0
  255. package/dist/lib/task-lifecycle-output.d.ts +14 -0
  256. package/dist/lib/task-lifecycle-output.js +209 -0
  257. package/dist/lib/task-ref-resolver.d.ts +1 -17
  258. package/dist/lib/task-ref-resolver.js +18 -8
  259. package/dist/lib/tasks.d.ts +3 -0
  260. package/dist/lib/tasks.js +40 -3
  261. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +4 -0
  262. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +4 -0
  263. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  264. package/dist/node_modules/@skrr-ai/data-provider/index.js +5559 -4897
  265. package/oclif.manifest.json +33890 -28690
  266. package/package.json +24 -6
@@ -78,6 +78,17 @@ class MachinesList extends base_command_1.BaseCommand {
78
78
  { key: 'platform', header: 'PLATFORM' },
79
79
  { key: 'seen', header: 'LAST SEEN' },
80
80
  ], (line) => this.log(line));
81
+ // Why a machine is not `online`, under the table. `degraded` on its own is
82
+ // unactionable — the dogfood note on this output was "I still do not know
83
+ // whether something is wrong with my laptop" — and it is usually one named
84
+ // row, not the machine.
85
+ const explained = shown.filter((m) => m.status !== 'online' && m.statusReason);
86
+ if (explained.length > 0) {
87
+ this.log('');
88
+ for (const m of explained) {
89
+ this.log(` ${m.preferences?.name || m.name}: ${m.statusReason}`);
90
+ }
91
+ }
81
92
  const hidden = all.length - shown.length;
82
93
  if (hidden > 0) {
83
94
  this.log('');
@@ -8,6 +8,7 @@ export default class MachinesShow extends BaseCommand {
8
8
  };
9
9
  static flags: {
10
10
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ all: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
12
  };
12
13
  run(): Promise<void>;
13
14
  }
@@ -9,6 +9,7 @@ class MachinesShow extends base_command_1.BaseCommand {
9
9
  static description = 'Show one machine — its identity, harnesses, and available actions';
10
10
  static examples = [
11
11
  '<%= config.bin %> machines show 03548116',
12
+ '<%= config.bin %> machines show 03548116 --all',
12
13
  '<%= config.bin %> machines show "frankdu@DS-3" --json',
13
14
  ];
14
15
  static args = {
@@ -18,7 +19,13 @@ class MachinesShow extends base_command_1.BaseCommand {
18
19
  required: true,
19
20
  }),
20
21
  };
21
- static flags = { json: core_1.Flags.boolean({ description: 'Output as JSON' }) };
22
+ static flags = {
23
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
24
+ all: core_1.Flags.boolean({
25
+ description: 'Include harness registrations superseded by newer ones',
26
+ default: false,
27
+ }),
28
+ };
22
29
  async run() {
23
30
  this.requireAuth();
24
31
  const { args, flags } = await this.parse(MachinesShow);
@@ -43,6 +50,10 @@ class MachinesShow extends base_command_1.BaseCommand {
43
50
  this.log(` id ${machine.id}`);
44
51
  this.log(` identity ${machine.identityKind}`);
45
52
  this.log(` status ${machine.status}`);
53
+ // The status alone does not say what to do. Naming the rows that decided it
54
+ // is the actionable half — bring that provider back, or forget the row.
55
+ if (machine.statusReason)
56
+ this.log(` why ${machine.statusReason}`);
46
57
  if (machine.machineUuid)
47
58
  this.log(` machineUuid ${machine.machineUuid}`);
48
59
  if (machine.daemonId)
@@ -60,20 +71,34 @@ class MachinesShow extends base_command_1.BaseCommand {
60
71
  const harnesses = machine.harnesses ?? [];
61
72
  const live = (0, machines_1.liveHarnessCount)(machine);
62
73
  const superseded = harnesses.length - live;
74
+ // Superseded registrations are history, not capabilities, and they are not
75
+ // counted as missing ones next to a status of `online`. They are hidden by
76
+ // default, the convention `machines list` already set for dead machines:
77
+ // printed, they were 35 of a machine's 42 rows, back two months, under a
78
+ // header whose count read like a summary of rows it then printed anyway
79
+ // (OSK-9389). `--all` shows them, and `--json` always carries every row.
80
+ const shown = flags.all ? harnesses : harnesses.filter((h) => !h.superseded);
63
81
  this.log('');
64
- // The superseded rows are still listed — labelled, not dropped, so they can
65
- // be seen and reaped — but they are not missing capabilities and must not
66
- // be counted as such next to a status of `online`.
67
82
  this.log(`Harnesses (${machine.onlineHarnessCount}/${live} online` +
68
- (superseded > 0 ? `, ${superseded} superseded by newer registrations` : '') +
83
+ (flags.all && superseded > 0 ? `, ${superseded} superseded by newer registrations` : '') +
69
84
  ')');
70
- if (harnesses.length > 0) {
71
- (0, format_1.renderTable)(harnesses.map((h) => ({
85
+ if (shown.length > 0) {
86
+ (0, format_1.renderTable)(shown.map((h) => ({
72
87
  id: (0, format_1.formatCell)(h.id),
73
88
  provider: (0, format_1.formatCell)(h.provider),
74
- // A superseded row that merely says `offline` reads as a harness
75
- // that went down. Naming it is what explains the count above.
76
- status: h.superseded ? 'superseded' : (0, format_1.formatCell)(h.status),
89
+ // Liveness only. Whether a newer registration replaced the row is a
90
+ // different fact — a superseded row can have been online — so it
91
+ // gets its own column rather than overwriting this one.
92
+ status: (0, format_1.formatCell)(h.status),
93
+ registration: h.superseded ? 'superseded' : 'current',
94
+ // `authStatus` is the DAEMON's standing with skrr, not this
95
+ // provider's standing with its vendor. It is written across every row
96
+ // of a daemon at once (`HarnessService.markAuthOkAfterRegister` does
97
+ // one `updateMany({owner, daemonId})`), so it is structurally the
98
+ // same value for all of them and can never answer "is this harness
99
+ // signed in". Under a bare `AUTH` header it read as the second
100
+ // question and answered `ok` for a Devin whose own CLI said
101
+ // "Not logged in." The header now names what the value is.
77
102
  auth: (0, format_1.formatCell)(h.authStatus),
78
103
  seen: h.lastSeenAt
79
104
  ? new Date(h.lastSeenAt).toISOString().slice(0, 16).replace('T', ' ')
@@ -82,10 +107,14 @@ class MachinesShow extends base_command_1.BaseCommand {
82
107
  { key: 'id', header: 'HARNESS ID' },
83
108
  { key: 'provider', header: 'PROVIDER' },
84
109
  { key: 'status', header: 'STATUS' },
85
- { key: 'auth', header: 'AUTH' },
110
+ ...(flags.all ? [{ key: 'registration', header: 'REGISTRATION' }] : []),
111
+ { key: 'auth', header: 'DAEMON AUTH' },
86
112
  { key: 'seen', header: 'LAST SEEN' },
87
113
  ], (line) => this.log(` ${line}`));
88
114
  }
115
+ if (!flags.all && superseded > 0) {
116
+ this.log(` ${superseded} superseded registration(s) hidden — pass --all to include them.`);
117
+ }
89
118
  // Print what is PERMITTED, not the whole control map: a list of six
90
119
  // booleans mostly reading false is noise, and the useful question is
91
120
  // "what can I do to this machine right now".
@@ -0,0 +1,21 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * An agent's memory POLICY: which pools its runtime may read and write, how long
4
+ * retained facts are governed, and what deletion means.
5
+ *
6
+ * Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
7
+ * uses the same door the web does. The distinction the route draws — and this
8
+ * command surfaces — is between a policy an owner has DELIBERATELY saved and the
9
+ * defaults an unconfigured agent reads as. Mongoose materializes the leaf
10
+ * defaults on every new agent row, so "has a policy" cannot be answered by the
11
+ * field being present; only `updatedAt` says a human decided something.
12
+ */
13
+ export default class MemoryGovernanceShow extends BaseCommand {
14
+ static description: string;
15
+ static examples: string[];
16
+ static flags: {
17
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
19
+ };
20
+ run(): Promise<void>;
21
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const agent_resolver_1 = require("../../../lib/agent-resolver");
7
+ /**
8
+ * An agent's memory POLICY: which pools its runtime may read and write, how long
9
+ * retained facts are governed, and what deletion means.
10
+ *
11
+ * Its own route rather than a corner of `PATCH /api/agents/:id`, and the CLI
12
+ * uses the same door the web does. The distinction the route draws — and this
13
+ * command surfaces — is between a policy an owner has DELIBERATELY saved and the
14
+ * defaults an unconfigured agent reads as. Mongoose materializes the leaf
15
+ * defaults on every new agent row, so "has a policy" cannot be answered by the
16
+ * field being present; only `updatedAt` says a human decided something.
17
+ */
18
+ class MemoryGovernanceShow extends base_command_1.BaseCommand {
19
+ static description = "Show an agent's memory governance policy";
20
+ static examples = [
21
+ '<%= config.bin %> memory governance --agent <agent-id>',
22
+ '<%= config.bin %> memory governance --agent <agent-id> --json',
23
+ ];
24
+ static flags = {
25
+ agent: core_1.Flags.string({
26
+ description: 'Agent ID (falls back to OVERSKY_AGENT_ID, then your primary agent)',
27
+ }),
28
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
29
+ };
30
+ async run() {
31
+ this.requireAuth();
32
+ const { flags } = await this.parse(MemoryGovernanceShow);
33
+ let agentId;
34
+ try {
35
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
36
+ }
37
+ catch (err) {
38
+ this.error(err.message, { exit: 1 });
39
+ }
40
+ let policy;
41
+ try {
42
+ policy = await data_provider_1.dataService.getAgentMemoryGovernance(agentId);
43
+ }
44
+ catch (err) {
45
+ this.handleApiError(err);
46
+ }
47
+ if (flags.json) {
48
+ this.log(this.agentJson(agentId, policy));
49
+ return;
50
+ }
51
+ const p = policy;
52
+ this.log(`Memory governance for agent ${agentId}`);
53
+ this.log(` Read scopes: ${(p.allowedReadScopes ?? []).join(', ') || '-'}`);
54
+ this.log(` Write scopes: ${(p.allowedWriteScopes ?? []).join(', ') || '-'}`);
55
+ this.log(` Retention: ${p.retentionDays ?? '-'} days`);
56
+ this.log(` On deletion: ${p.deletionMode ?? '-'}`);
57
+ this.log(` Shared memory: ${p.requireEvidenceForSharedMemory ? 'requires evidence' : 'no evidence required'}`);
58
+ this.log('');
59
+ this.log(p.updatedAt
60
+ ? `Configured ${String(p.updatedAt).slice(0, 10)}.`
61
+ : 'Never configured — these are the defaults a run reads, not a saved policy.');
62
+ }
63
+ }
64
+ exports.default = MemoryGovernanceShow;
@@ -0,0 +1,24 @@
1
+ import { BaseCommand } from '../../../base-command';
2
+ /**
3
+ * Change an agent's memory policy. Requires EDIT on the agent.
4
+ *
5
+ * PARTIAL by design and worth being explicit about: the route merges over the
6
+ * leaves an owner has actually set, so omitting a flag leaves that leaf unset
7
+ * rather than freezing today's default into the row. That is why `--read-scope`
8
+ * REPLACES the list instead of adding to it — a list flag that appended would
9
+ * make "only agent memory" unreachable once anything wider had been granted.
10
+ */
11
+ export default class MemoryGovernanceSet extends BaseCommand {
12
+ static description: string;
13
+ static examples: string[];
14
+ static flags: {
15
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
16
+ 'read-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ 'write-scope': import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
18
+ 'retention-days': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
19
+ 'deletion-mode': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
20
+ 'require-evidence': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
22
+ };
23
+ run(): Promise<void>;
24
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../../base-command");
6
+ const agent_resolver_1 = require("../../../lib/agent-resolver");
7
+ const MEMORY_SCOPES = ['agent', 'user', 'workspace'];
8
+ /**
9
+ * Change an agent's memory policy. Requires EDIT on the agent.
10
+ *
11
+ * PARTIAL by design and worth being explicit about: the route merges over the
12
+ * leaves an owner has actually set, so omitting a flag leaves that leaf unset
13
+ * rather than freezing today's default into the row. That is why `--read-scope`
14
+ * REPLACES the list instead of adding to it — a list flag that appended would
15
+ * make "only agent memory" unreachable once anything wider had been granted.
16
+ */
17
+ class MemoryGovernanceSet extends base_command_1.BaseCommand {
18
+ static description = "Change an agent's memory governance policy (requires EDIT)";
19
+ static examples = [
20
+ '<%= config.bin %> memory governance set --agent <agent-id> --retention-days 90',
21
+ '<%= config.bin %> memory governance set --agent <agent-id> --read-scope agent --read-scope workspace',
22
+ '<%= config.bin %> memory governance set --agent <agent-id> --deletion-mode delete --no-require-evidence',
23
+ ];
24
+ static flags = {
25
+ agent: core_1.Flags.string({ description: 'Agent ID' }),
26
+ 'read-scope': core_1.Flags.string({
27
+ description: 'Memory pool the runtime may READ (repeatable; replaces the list)',
28
+ options: [...MEMORY_SCOPES],
29
+ multiple: true,
30
+ }),
31
+ 'write-scope': core_1.Flags.string({
32
+ description: 'Memory pool the runtime may WRITE (repeatable; replaces the list)',
33
+ options: [...MEMORY_SCOPES],
34
+ multiple: true,
35
+ }),
36
+ 'retention-days': core_1.Flags.integer({
37
+ description: 'How long retained facts are governed (1-3650)',
38
+ }),
39
+ 'deletion-mode': core_1.Flags.string({
40
+ description: 'What deletion means for this agent',
41
+ options: ['archive', 'delete'],
42
+ }),
43
+ 'require-evidence': core_1.Flags.boolean({
44
+ description: 'Require evidence before a fact enters shared memory',
45
+ allowNo: true,
46
+ }),
47
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
48
+ };
49
+ async run() {
50
+ this.requireAuth();
51
+ const { flags } = await this.parse(MemoryGovernanceSet);
52
+ const patch = {
53
+ ...(flags['read-scope'] === undefined
54
+ ? {}
55
+ : { allowedReadScopes: flags['read-scope'] }),
56
+ ...(flags['write-scope'] === undefined
57
+ ? {}
58
+ : { allowedWriteScopes: flags['write-scope'] }),
59
+ ...(flags['retention-days'] === undefined ? {} : { retentionDays: flags['retention-days'] }),
60
+ ...(flags['deletion-mode'] === undefined
61
+ ? {}
62
+ : { deletionMode: flags['deletion-mode'] }),
63
+ ...(flags['require-evidence'] === undefined
64
+ ? {}
65
+ : { requireEvidenceForSharedMemory: flags['require-evidence'] }),
66
+ };
67
+ if (Object.keys(patch).length === 0) {
68
+ this.error('Nothing to change. Pass at least one of --read-scope, --write-scope, ' +
69
+ '--retention-days, --deletion-mode, --require-evidence.', { exit: 1 });
70
+ }
71
+ let agentId;
72
+ try {
73
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
74
+ }
75
+ catch (err) {
76
+ this.error(err.message, { exit: 1 });
77
+ }
78
+ let policy;
79
+ try {
80
+ policy = await data_provider_1.dataService.updateAgentMemoryGovernance(agentId, patch);
81
+ }
82
+ catch (err) {
83
+ this.handleApiError(err);
84
+ }
85
+ if (flags.json) {
86
+ this.log(this.agentJson(agentId, policy));
87
+ return;
88
+ }
89
+ this.log(`Updated memory governance for agent ${agentId}.`);
90
+ this.log(` Read scopes: ${(policy.allowedReadScopes ?? []).join(', ') || '-'}`);
91
+ this.log(` Write scopes: ${(policy.allowedWriteScopes ?? []).join(', ') || '-'}`);
92
+ this.log(` Retention: ${policy.retentionDays ?? '-'} days`);
93
+ }
94
+ }
95
+ exports.default = MemoryGovernanceSet;
@@ -0,0 +1,18 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * Where an agent's stored memories came from.
4
+ *
5
+ * The other half of governance: a policy says what a runtime MAY remember, and
6
+ * this says what it actually did and on whose evidence. Read-only, VIEW on the
7
+ * agent.
8
+ */
9
+ export default class MemoryProvenance extends BaseCommand {
10
+ static description: string;
11
+ static examples: string[];
12
+ static flags: {
13
+ agent: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
14
+ limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
15
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const data_provider_1 = require("@skrr-ai/data-provider");
5
+ const base_command_1 = require("../../base-command");
6
+ const agent_resolver_1 = require("../../lib/agent-resolver");
7
+ const format_1 = require("../../lib/format");
8
+ /**
9
+ * Where an agent's stored memories came from.
10
+ *
11
+ * The other half of governance: a policy says what a runtime MAY remember, and
12
+ * this says what it actually did and on whose evidence. Read-only, VIEW on the
13
+ * agent.
14
+ */
15
+ class MemoryProvenance extends base_command_1.BaseCommand {
16
+ static description = "Show where an agent's stored memories came from";
17
+ static examples = [
18
+ '<%= config.bin %> memory provenance --agent <agent-id>',
19
+ '<%= config.bin %> memory provenance --agent <agent-id> --limit 50 --json',
20
+ ];
21
+ static flags = {
22
+ agent: core_1.Flags.string({ description: 'Agent ID' }),
23
+ limit: core_1.Flags.integer({ description: 'How many entries to return' }),
24
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
25
+ };
26
+ async run() {
27
+ this.requireAuth();
28
+ const { flags } = await this.parse(MemoryProvenance);
29
+ let agentId;
30
+ try {
31
+ agentId = await (0, agent_resolver_1.resolveAgentId)(flags.agent);
32
+ }
33
+ catch (err) {
34
+ this.error(err.message, { exit: 1 });
35
+ }
36
+ let response;
37
+ try {
38
+ response = await data_provider_1.dataService.getAgentMemoryProvenance(agentId, flags.limit === undefined ? undefined : { limit: flags.limit });
39
+ }
40
+ catch (err) {
41
+ this.handleApiError(err);
42
+ }
43
+ if (flags.json) {
44
+ this.log(this.agentJson(agentId, response));
45
+ return;
46
+ }
47
+ const payload = response;
48
+ const entries = Array.isArray(response)
49
+ ? response
50
+ : (payload?.entries ?? []);
51
+ if (entries.length === 0) {
52
+ this.log(`No memory provenance recorded for agent ${agentId}.`);
53
+ return;
54
+ }
55
+ (0, format_1.renderTable)(entries.map((entry) => ({
56
+ key: String(entry.key ?? '-'),
57
+ source: String(entry.source ?? entry.origin ?? '-'),
58
+ at: entry.updated_at ? String(entry.updated_at).slice(0, 10) : '-',
59
+ })), [
60
+ { key: 'key', header: 'KEY', verbatim: true },
61
+ { key: 'source', header: 'SOURCE', maxWidth: 30 },
62
+ { key: 'at', header: 'UPDATED' },
63
+ ], (line) => this.log(line));
64
+ }
65
+ }
66
+ exports.default = MemoryProvenance;
@@ -0,0 +1,23 @@
1
+ import { BaseCommand } from '../../base-command';
2
+ /**
3
+ * Which stored sessions exist on this machine.
4
+ *
5
+ * Every command advertises `--profile` and nothing could tell you what to pass
6
+ * it. Profiles are additive and stored on disk — the default at
7
+ * `<root>/cli-config.json`, named ones at `<root>/profiles/<name>/cli-config.json`
8
+ * — so the list was always knowable; there was simply no way to ask.
9
+ *
10
+ * That is not only a discoverability nit. A second profile is how one machine
11
+ * holds a second identity, which is what any test of a NON-OWNER path needs. A
12
+ * dogfood run of the `force`-past-a-required-Review flow stalled on exactly
13
+ * this: the flag was there, the second identity was reachable, and nothing named
14
+ * it.
15
+ */
16
+ export default class ProfilesList extends BaseCommand {
17
+ static description: string;
18
+ static examples: string[];
19
+ static flags: {
20
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
21
+ };
22
+ run(): Promise<void>;
23
+ }
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_fs_1 = __importDefault(require("node:fs"));
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const core_1 = require("@oclif/core");
9
+ const base_command_1 = require("../../base-command");
10
+ const config_1 = require("../../lib/config");
11
+ const keychain_1 = require("../../lib/keychain");
12
+ /**
13
+ * Which stored sessions exist on this machine.
14
+ *
15
+ * Every command advertises `--profile` and nothing could tell you what to pass
16
+ * it. Profiles are additive and stored on disk — the default at
17
+ * `<root>/cli-config.json`, named ones at `<root>/profiles/<name>/cli-config.json`
18
+ * — so the list was always knowable; there was simply no way to ask.
19
+ *
20
+ * That is not only a discoverability nit. A second profile is how one machine
21
+ * holds a second identity, which is what any test of a NON-OWNER path needs. A
22
+ * dogfood run of the `force`-past-a-required-Review flow stalled on exactly
23
+ * this: the flag was there, the second identity was reachable, and nothing named
24
+ * it.
25
+ */
26
+ class ProfilesList extends base_command_1.BaseCommand {
27
+ static description = 'List the stored sessions (profiles) on this machine';
28
+ static examples = [
29
+ '<%= config.bin %> profiles list',
30
+ '<%= config.bin %> profiles list --json',
31
+ '<%= config.bin %> login --profile reviewer',
32
+ ];
33
+ static flags = {
34
+ json: core_1.Flags.boolean({ description: 'Output as JSON' }),
35
+ };
36
+ async run() {
37
+ const { flags } = await this.parse(ProfilesList);
38
+ const root = (0, config_1.configRoot)();
39
+ const active = (0, keychain_1.getActiveProfile)() || keychain_1.DEFAULT_PROFILE;
40
+ const rows = [];
41
+ const seen = new Set();
42
+ const describe = (name, configFile) => {
43
+ /*
44
+ * Deliberately NOT a "signed in" column.
45
+ *
46
+ * The credential does not live in `cli-config.json` — it is in the
47
+ * keychain — so this file can only report the deployment. A first draft
48
+ * inferred sign-in from a `token` key that is never there and printed
49
+ * `no` for the profile the caller was actively authenticated as: a
50
+ * confident wrong answer, which is worse than an absent one and exactly
51
+ * the failure this whole surface keeps making. Read the server, say the
52
+ * server.
53
+ */
54
+ if (seen.has(name))
55
+ return;
56
+ seen.add(name);
57
+ let server;
58
+ try {
59
+ const raw = JSON.parse(node_fs_1.default.readFileSync(configFile, 'utf8'));
60
+ server = typeof raw.baseURL === 'string' ? raw.baseURL : undefined;
61
+ }
62
+ catch {
63
+ // A profile directory with no readable config is still a profile; say
64
+ // so rather than hiding it, because a half-written one is exactly what
65
+ // someone would be trying to diagnose.
66
+ }
67
+ rows.push({ name, active: name === active, server });
68
+ };
69
+ describe(keychain_1.DEFAULT_PROFILE, node_path_1.default.join(root, 'cli-config.json'));
70
+ try {
71
+ for (const entry of node_fs_1.default.readdirSync(node_path_1.default.join(root, 'profiles'), { withFileTypes: true })) {
72
+ if (!entry.isDirectory())
73
+ continue;
74
+ describe(entry.name, node_path_1.default.join(root, 'profiles', entry.name, 'cli-config.json'));
75
+ }
76
+ }
77
+ catch {
78
+ // No `profiles/` directory means no named profiles — not an error.
79
+ }
80
+ if (flags.json) {
81
+ this.log(JSON.stringify({ root, active, profiles: rows }, null, 2));
82
+ return;
83
+ }
84
+ // Width from the DATA, so a long profile name cannot run into the next
85
+ // column — `df-memory-verify-isolated` did exactly that at a fixed 24.
86
+ const width = Math.max(4, ...rows.map((row) => row.name.length)) + 2;
87
+ this.log('NAME'.padEnd(width) + 'ACTIVE'.padEnd(9) + 'SERVER');
88
+ for (const row of rows) {
89
+ this.log(row.name.padEnd(width) + (row.active ? 'yes' : '-').padEnd(9) + (row.server || '-'));
90
+ }
91
+ this.log('');
92
+ this.log(`Add one: ${this.config.bin} login --profile <name>`);
93
+ this.log(`Use one: ${this.config.bin} <command> --profile <name> (or OVERSKY_PROFILE)`);
94
+ }
95
+ }
96
+ exports.default = ProfilesList;
@@ -2,9 +2,19 @@ import { BaseCommand } from '../../base-command';
2
2
  export default class SearchSkills extends BaseCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
+ /**
6
+ * `skills search` and `search skills` are the SAME search, and both spellings
7
+ * stay. Neither said so, their one-liners differed, and only one carried short
8
+ * flags — so a reader picked one at random with no way to tell whether they had
9
+ * picked a deprecated spelling. Duplication that is deliberate should say so;
10
+ * duplication that is silent reads as a mistake either way.
11
+ */
12
+ static args: {
13
+ query: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
14
+ };
5
15
  static flags: {
6
16
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
- query: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
17
+ query: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
8
18
  category: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
9
19
  limit: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
10
20
  };
@@ -4,19 +4,36 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
6
  const format_1 = require("../../lib/format");
7
+ const search_query_1 = require("../../lib/search-query");
7
8
  class SearchSkills extends base_command_1.BaseCommand {
8
- static description = 'Search skills in the skrr store';
9
+ static description = 'Search skills in the skrr store by keyword (same as `skills search`)';
9
10
  static examples = [
10
- '<%= config.bin %> search skills --query "web scraping"',
11
- '<%= config.bin %> search skills --query summarize --category productivity',
12
- '<%= config.bin %> search skills --query translate --limit 10 --json',
11
+ '<%= config.bin %> search skills "web scraping"',
12
+ '<%= config.bin %> search skills summarize --category productivity',
13
+ '<%= config.bin %> search skills translate --limit 10 --json',
14
+ '<%= config.bin %> search skills -q translate',
13
15
  ];
16
+ /**
17
+ * `skills search` and `search skills` are the SAME search, and both spellings
18
+ * stay. Neither said so, their one-liners differed, and only one carried short
19
+ * flags — so a reader picked one at random with no way to tell whether they had
20
+ * picked a deprecated spelling. Duplication that is deliberate should say so;
21
+ * duplication that is silent reads as a mistake either way.
22
+ */
23
+ static args = {
24
+ query: core_1.Args.string({
25
+ description: 'Search term (same value as --query; pass either, not both)',
26
+ required: false,
27
+ ignoreStdin: true,
28
+ }),
29
+ };
14
30
  static flags = {
15
31
  json: core_1.Flags.boolean({ description: 'Output as JSON' }),
32
+ // See `skills search` — the positional satisfies it and the flag stays so
33
+ // existing scripts keep working.
16
34
  query: core_1.Flags.string({
17
35
  char: 'q',
18
36
  description: 'Search query',
19
- required: true,
20
37
  }),
21
38
  category: core_1.Flags.string({
22
39
  char: 'c',
@@ -29,11 +46,12 @@ class SearchSkills extends base_command_1.BaseCommand {
29
46
  };
30
47
  async run() {
31
48
  this.requireAuth();
32
- const { flags } = await this.parse(SearchSkills);
49
+ const { args, flags } = await this.parse(SearchSkills);
50
+ const query = (0, search_query_1.resolveSearchQuery)(this, args.query, flags.query, 'search skills');
33
51
  let response;
34
52
  try {
35
53
  response = await data_provider_1.dataService.getStoreSkills({
36
- q: flags.query,
54
+ q: query,
37
55
  category: flags.category,
38
56
  limit: flags.limit,
39
57
  });
@@ -48,7 +66,7 @@ class SearchSkills extends base_command_1.BaseCommand {
48
66
  const r = response;
49
67
  const items = Array.isArray(r) ? r : (r?.data ?? []);
50
68
  if (items.length === 0) {
51
- this.log('No skills found.');
69
+ this.log(`No skills found matching '${query}'.`);
52
70
  return;
53
71
  }
54
72
  const rows = items.map((s) => ({
@@ -8,5 +8,7 @@ export default class SkillsDetails extends BaseCommand {
8
8
  static flags: {
9
9
  json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
10
  };
11
+ /** A store 404 for a name that may be a skill on the caller's machine. */
12
+ private failOnStoreMiss;
11
13
  run(): Promise<void>;
12
14
  }