@skrr-ai/cli 0.1.37 → 0.1.39

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 (177) hide show
  1. package/bin/dev-fallback.js +175 -4
  2. package/dist/base-command.js +46 -2
  3. package/dist/commands/agents/actions/create.js +18 -7
  4. package/dist/commands/agents/actions/delete.d.ts +1 -0
  5. package/dist/commands/agents/actions/delete.js +7 -0
  6. package/dist/commands/agents/actions/update.js +5 -3
  7. package/dist/commands/agents/api-actions/add.js +5 -2
  8. package/dist/commands/agents/api-actions/index.d.ts +11 -0
  9. package/dist/commands/agents/api-actions/index.js +27 -1
  10. package/dist/commands/agents/avatar/default/index.d.ts +11 -0
  11. package/dist/commands/agents/avatar/default/index.js +17 -0
  12. package/dist/commands/agents/avatar/default/set.d.ts +2 -1
  13. package/dist/commands/agents/avatar/default/set.js +32 -7
  14. package/dist/commands/agents/avatar/upload.js +7 -1
  15. package/dist/commands/agents/categories/delete.js +8 -0
  16. package/dist/commands/agents/categories/index.d.ts +21 -5
  17. package/dist/commands/agents/categories/index.js +68 -15
  18. package/dist/commands/agents/chat.d.ts +21 -0
  19. package/dist/commands/agents/chat.js +94 -7
  20. package/dist/commands/agents/create.js +11 -4
  21. package/dist/commands/agents/list.d.ts +15 -0
  22. package/dist/commands/agents/list.js +31 -1
  23. package/dist/commands/agents/scene-background/upload.d.ts +30 -0
  24. package/dist/commands/agents/scene-background/upload.js +97 -0
  25. package/dist/commands/agents/show.js +13 -0
  26. package/dist/commands/agents/tools/calls.d.ts +23 -5
  27. package/dist/commands/agents/tools/calls.js +81 -18
  28. package/dist/commands/agents/update.js +15 -5
  29. package/dist/commands/code/{oversky-agent.d.ts → skrr-agent.d.ts} +3 -3
  30. package/dist/commands/code/{oversky-agent.js → skrr-agent.js} +11 -8
  31. package/dist/commands/convos/messages.d.ts +13 -0
  32. package/dist/commands/convos/messages.js +40 -16
  33. package/dist/commands/daemon/index.js +8 -1
  34. package/dist/commands/daemon/logs.d.ts +26 -0
  35. package/dist/commands/daemon/logs.js +56 -0
  36. package/dist/commands/daemon/uninstall.js +1 -1
  37. package/dist/commands/followups/act.js +3 -2
  38. package/dist/commands/followups/cancel.d.ts +6 -3
  39. package/dist/commands/followups/cancel.js +16 -6
  40. package/dist/commands/followups/observability.d.ts +23 -0
  41. package/dist/commands/followups/observability.js +114 -0
  42. package/dist/commands/followups/reschedule.js +1 -1
  43. package/dist/commands/followups/resolve.js +3 -3
  44. package/dist/commands/followups/show.js +2 -1
  45. package/dist/commands/followups/watch.js +9 -5
  46. package/dist/commands/harnesses/forget.js +28 -0
  47. package/dist/commands/harnesses/install.d.ts +41 -0
  48. package/dist/commands/harnesses/install.js +165 -0
  49. package/dist/commands/harnesses/installers.d.ts +45 -0
  50. package/dist/commands/harnesses/installers.js +155 -0
  51. package/dist/commands/harnesses/list.d.ts +82 -1
  52. package/dist/commands/harnesses/list.js +104 -12
  53. package/dist/commands/harnesses/models.js +10 -1
  54. package/dist/commands/harnesses/show.d.ts +15 -0
  55. package/dist/commands/harnesses/show.js +44 -3
  56. package/dist/commands/harnesses/update.js +1 -1
  57. package/dist/commands/harnesses/usage.d.ts +25 -0
  58. package/dist/commands/harnesses/usage.js +24 -2
  59. package/dist/commands/instructions/status.js +13 -1
  60. package/dist/commands/machines/dedicated/catalog.js +4 -15
  61. package/dist/commands/machines/dedicated/create.d.ts +8 -0
  62. package/dist/commands/machines/dedicated/create.js +63 -2
  63. package/dist/commands/machines/dedicated/destroy.js +19 -5
  64. package/dist/commands/machines/dedicated/exec.js +3 -1
  65. package/dist/commands/machines/dedicated/list.js +9 -6
  66. package/dist/commands/machines/dedicated/price-book.d.ts +17 -0
  67. package/dist/commands/machines/dedicated/price-book.js +35 -0
  68. package/dist/commands/machines/hosted/list.js +12 -0
  69. package/dist/commands/machines/list.js +11 -0
  70. package/dist/commands/machines/show.d.ts +1 -0
  71. package/dist/commands/machines/show.js +40 -11
  72. package/dist/commands/profiles/list.d.ts +23 -0
  73. package/dist/commands/profiles/list.js +96 -0
  74. package/dist/commands/search/skills.d.ts +11 -1
  75. package/dist/commands/search/skills.js +26 -8
  76. package/dist/commands/skills/details.d.ts +2 -0
  77. package/dist/commands/skills/details.js +24 -1
  78. package/dist/commands/skills/import-as-actions.d.ts +32 -0
  79. package/dist/commands/skills/import-as-actions.js +175 -0
  80. package/dist/commands/skills/install.d.ts +2 -0
  81. package/dist/commands/skills/install.js +24 -1
  82. package/dist/commands/skills/invocable.js +6 -2
  83. package/dist/commands/skills/local.d.ts +40 -0
  84. package/dist/commands/skills/local.js +160 -0
  85. package/dist/commands/skills/search.d.ts +11 -1
  86. package/dist/commands/skills/search.js +29 -8
  87. package/dist/commands/spaces/actions/add.js +23 -5
  88. package/dist/commands/spaces/actions/available.js +3 -0
  89. package/dist/commands/spaces/actions/list.d.ts +5 -0
  90. package/dist/commands/spaces/actions/list.js +49 -3
  91. package/dist/commands/spaces/actions/run.d.ts +28 -0
  92. package/dist/commands/spaces/actions/run.js +146 -0
  93. package/dist/commands/spaces/actions/update.js +27 -5
  94. package/dist/commands/spaces/label-summaries.d.ts +27 -0
  95. package/dist/commands/spaces/label-summaries.js +64 -0
  96. package/dist/commands/spaces/task-rollups.d.ts +5 -0
  97. package/dist/commands/spaces/task-rollups.js +15 -4
  98. package/dist/commands/spaces/workflows/lifecycle-diagnostics.js +63 -3
  99. package/dist/commands/tasks/actions/attach.js +32 -7
  100. package/dist/commands/tasks/complete.js +13 -0
  101. package/dist/commands/tasks/create.js +1 -1
  102. package/dist/commands/tasks/events/append.js +29 -6
  103. package/dist/commands/tasks/expectations/assess.d.ts +1 -0
  104. package/dist/commands/tasks/expectations/assess.js +43 -5
  105. package/dist/commands/tasks/expectations.js +77 -16
  106. package/dist/commands/tasks/follow-up.js +2 -2
  107. package/dist/commands/tasks/lifecycle/definitions.js +21 -2
  108. package/dist/commands/tasks/lifecycle/detach.d.ts +7 -0
  109. package/dist/commands/tasks/lifecycle/detach.js +43 -3
  110. package/dist/commands/tasks/lifecycle/migrate.d.ts +2 -0
  111. package/dist/commands/tasks/lifecycle/migrate.js +42 -3
  112. package/dist/commands/tasks/lifecycle/reopen.d.ts +2 -0
  113. package/dist/commands/tasks/lifecycle/reopen.js +40 -3
  114. package/dist/commands/tasks/lifecycle/transition.js +33 -2
  115. package/dist/commands/tasks/list.js +16 -9
  116. package/dist/commands/tasks/move.js +11 -13
  117. package/dist/commands/tasks/review-queue.d.ts +15 -0
  118. package/dist/commands/tasks/review-queue.js +180 -31
  119. package/dist/commands/tasks/show.d.ts +11 -0
  120. package/dist/commands/tasks/show.js +105 -12
  121. package/dist/commands/tasks/trust.js +7 -2
  122. package/dist/commands/tasks/update.js +46 -10
  123. package/dist/commands/tasks/updates/add.js +1 -1
  124. package/dist/commands/token/list.d.ts +22 -0
  125. package/dist/commands/token/list.js +68 -0
  126. package/dist/commands/token/revoke.d.ts +23 -0
  127. package/dist/commands/token/revoke.js +53 -0
  128. package/dist/lib/agent-actions.d.ts +57 -2
  129. package/dist/lib/agent-actions.js +113 -21
  130. package/dist/lib/agent-pin-mute.d.ts +10 -5
  131. package/dist/lib/agent-pin-mute.js +17 -4
  132. package/dist/lib/agent-visual-refs.d.ts +27 -0
  133. package/dist/lib/agent-visual-refs.js +127 -2
  134. package/dist/lib/agentic-stream.d.ts +6 -0
  135. package/dist/lib/agentic-stream.js +34 -3
  136. package/dist/lib/assignee-resolver.d.ts +1 -1
  137. package/dist/lib/assignee-resolver.js +8 -0
  138. package/dist/lib/bulk-task-targets.d.ts +12 -0
  139. package/dist/lib/bulk-task-targets.js +34 -1
  140. package/dist/lib/cli-installers.d.ts +130 -0
  141. package/dist/lib/cli-installers.js +145 -0
  142. package/dist/lib/command-miss.js +55 -7
  143. package/dist/lib/dedicated-lease-command.d.ts +16 -1
  144. package/dist/lib/dedicated-lease-command.js +26 -3
  145. package/dist/lib/dedicated-machines.d.ts +135 -1
  146. package/dist/lib/dedicated-machines.js +307 -3
  147. package/dist/lib/failed-lookup.d.ts +3 -0
  148. package/dist/lib/failed-lookup.js +40 -0
  149. package/dist/lib/first-party-harness-agent.js +9 -2
  150. package/dist/lib/first-party-harness-doctor.d.ts +15 -0
  151. package/dist/lib/first-party-harness-doctor.js +126 -27
  152. package/dist/lib/followups.d.ts +14 -6
  153. package/dist/lib/followups.js +31 -6
  154. package/dist/lib/harnesses.d.ts +8 -0
  155. package/dist/lib/instruction-input.d.ts +19 -1
  156. package/dist/lib/instruction-input.js +52 -1
  157. package/dist/lib/label-scope.d.ts +15 -0
  158. package/dist/lib/label-scope.js +25 -5
  159. package/dist/lib/local-skills.d.ts +98 -0
  160. package/dist/lib/local-skills.js +195 -0
  161. package/dist/lib/machines.d.ts +10 -10
  162. package/dist/lib/machines.js +23 -1
  163. package/dist/lib/search-query.d.ts +19 -0
  164. package/dist/lib/search-query.js +35 -0
  165. package/dist/lib/space-custom-actions.d.ts +72 -0
  166. package/dist/lib/space-custom-actions.js +117 -0
  167. package/dist/lib/space-resolver.d.ts +1 -21
  168. package/dist/lib/space-resolver.js +19 -10
  169. package/dist/lib/task-closure.d.ts +3 -2
  170. package/dist/lib/task-closure.js +18 -20
  171. package/dist/lib/task-lifecycle-output.js +117 -9
  172. package/dist/lib/task-ref-resolver.d.ts +1 -17
  173. package/dist/lib/task-ref-resolver.js +18 -8
  174. package/dist/lib/tasks.js +9 -3
  175. package/dist/node_modules/@skrr-ai/data-provider/index.js +5076 -4947
  176. package/oclif.manifest.json +15505 -14460
  177. package/package.json +9 -3
@@ -36,6 +36,7 @@ exports.projectStateDir = projectStateDir;
36
36
  exports.runDoctor = runDoctor;
37
37
  exports.formatReport = formatReport;
38
38
  const node_fs_1 = require("node:fs");
39
+ const node_os_1 = require("node:os");
39
40
  const node_path_1 = __importDefault(require("node:path"));
40
41
  const first_party_harness_1 = require("./first-party-harness");
41
42
  const auth_core_1 = require("@skrr-ai/auth-core");
@@ -285,40 +286,138 @@ function stateDirCheck(cwd, env) {
285
286
  ];
286
287
  return { name: 'state-paths', status: 'ok', detail: parts.join('; ') };
287
288
  }
288
- function compatCheck(cwd, env) {
289
- // Report both the engine's own writable instruction surfaces and read-only
290
- // compatibility sources so "where did this instruction come from?" has an
291
- // answer — a WL-2 acceptance criterion.
292
- const root = node_path_1.default.resolve(cwd);
293
- const own = [];
294
- for (const file of [
295
- node_path_1.default.join(projectStateDir(root), 'AGENTS.md'),
296
- node_path_1.default.join((0, first_party_harness_1.engineInstructionHome)(env), 'AGENTS.md'),
297
- ]) {
298
- if ((0, node_fs_1.existsSync)(file))
299
- own.push(file);
289
+ /**
290
+ * Skill directories directly under `root` that hold a SKILL.md.
291
+ *
292
+ * A symlinked skill directory counts: installers and dotfile managers link
293
+ * skills in, and a count that skipped them reported 11 of a root's 31.
294
+ */
295
+ function countSkills(root) {
296
+ try {
297
+ return (0, node_fs_1.readdirSync)(root).filter((name) => {
298
+ try {
299
+ return ((0, node_fs_1.statSync)(node_path_1.default.join(root, name)).isDirectory() &&
300
+ (0, node_fs_1.existsSync)(node_path_1.default.join(root, name, 'SKILL.md')));
301
+ }
302
+ catch {
303
+ return false;
304
+ }
305
+ }).length;
300
306
  }
301
- const compatibility = [];
302
- for (const rel of ['AGENTS.md', 'CLAUDE.md', '.agents/skills', '.claude/skills']) {
303
- if ((0, node_fs_1.existsSync)(node_path_1.default.join(root, rel)))
304
- compatibility.push(rel);
307
+ catch {
308
+ return 0;
305
309
  }
306
- if (own.length === 0 && compatibility.length === 0) {
310
+ }
311
+ function compatCheck(cwd, env) {
312
+ // Report every instruction and skill source the engine reads, owned and
313
+ // compatibility alike, so "where did this come from?" has an answer — a WL-2
314
+ // acceptance criterion.
315
+ //
316
+ // It named two skill roots, project-level only, as bare directory names: the
317
+ // user-level `~/.agents/skills` and `~/.claude/skills` the engine also reads
318
+ // were missing, an empty root and a full one looked the same, and nothing said
319
+ // why a machine's other roots (.devin, .windsurf, .codex, …) were absent — so
320
+ // a reader could not tell "not read" from "not reported" (OSK-9357). The set
321
+ // below is the engine's documented compatibility contract
322
+ // (opencode-white-label-implementation-plan §7.2); roots beyond it reach a
323
+ // session only when the daemon links them in, which `skrr skills local` shows.
324
+ const root = node_path_1.default.resolve(cwd);
325
+ const home = env.HOME || (0, node_os_1.homedir)();
326
+ const projectDir = auth_core_1.FIRST_PARTY_HARNESS_ENGINE.projectDirectory;
327
+ const noCompatPrompts = Boolean(env[auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts]);
328
+ const engineHomeDir = (0, first_party_harness_1.engineInstructionHome)(env);
329
+ const shown = (abs) => abs.startsWith(root + node_path_1.default.sep)
330
+ ? node_path_1.default.relative(root, abs)
331
+ : abs.startsWith(home + node_path_1.default.sep)
332
+ ? `~/${node_path_1.default.relative(home, abs)}`
333
+ : abs;
334
+ const declared = [
335
+ {
336
+ abs: node_path_1.default.join(root, projectDir, 'AGENTS.md'),
337
+ kind: 'instructions',
338
+ owner: 'engine',
339
+ scope: 'project',
340
+ },
341
+ {
342
+ abs: node_path_1.default.join(engineHomeDir, 'AGENTS.md'),
343
+ kind: 'instructions',
344
+ owner: 'engine',
345
+ scope: 'user',
346
+ },
347
+ {
348
+ abs: node_path_1.default.join(root, 'AGENTS.md'),
349
+ kind: 'instructions',
350
+ owner: 'compatibility',
351
+ scope: 'project',
352
+ },
353
+ {
354
+ abs: node_path_1.default.join(root, 'CLAUDE.md'),
355
+ kind: 'instructions',
356
+ owner: 'compatibility',
357
+ scope: 'project',
358
+ ...(noCompatPrompts ? { disabled: auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts } : {}),
359
+ },
360
+ {
361
+ abs: node_path_1.default.join(home, '.claude', 'CLAUDE.md'),
362
+ kind: 'instructions',
363
+ owner: 'compatibility',
364
+ scope: 'user',
365
+ ...(noCompatPrompts ? { disabled: auth_core_1.FIRST_PARTY_HARNESS_ENGINE.env.noCompatPrompts } : {}),
366
+ },
367
+ {
368
+ abs: node_path_1.default.join(root, '.agents', 'skills'),
369
+ kind: 'skills',
370
+ owner: 'compatibility',
371
+ scope: 'project',
372
+ },
373
+ {
374
+ abs: node_path_1.default.join(root, '.claude', 'skills'),
375
+ kind: 'skills',
376
+ owner: 'compatibility',
377
+ scope: 'project',
378
+ },
379
+ {
380
+ abs: node_path_1.default.join(home, '.agents', 'skills'),
381
+ kind: 'skills',
382
+ owner: 'compatibility',
383
+ scope: 'user',
384
+ },
385
+ {
386
+ abs: node_path_1.default.join(home, '.claude', 'skills'),
387
+ kind: 'skills',
388
+ owner: 'compatibility',
389
+ scope: 'user',
390
+ },
391
+ ];
392
+ const sources = declared.map(({ abs, ...source }) => {
393
+ const present = (0, node_fs_1.existsSync)(abs);
307
394
  return {
308
- name: 'compat-sources',
309
- status: 'ok',
310
- detail: `no ${auth_core_1.FIRST_PARTY_HARNESS.displayName}-owned or compatibility instruction files in this project`,
395
+ path: shown(abs),
396
+ ...source,
397
+ present,
398
+ ...(source.kind === 'skills' && present ? { skills: countSkills(abs) } : {}),
311
399
  };
312
- }
313
- const details = [];
314
- if (own.length > 0)
315
- details.push(`${auth_core_1.FIRST_PARTY_HARNESS.displayName}-owned: ${own.join(', ')}`);
316
- if (compatibility.length > 0)
317
- details.push(`compatibility (read-only): ${compatibility.join(', ')}`);
400
+ });
401
+ const describe = (source) => {
402
+ if (!source.present)
403
+ return `${source.path} (absent)`;
404
+ if (source.disabled)
405
+ return `${source.path} (off: ${source.disabled})`;
406
+ if (source.kind === 'skills') {
407
+ return `${source.path} (${source.skills} skill${source.skills === 1 ? '' : 's'})`;
408
+ }
409
+ return source.path;
410
+ };
411
+ const owned = sources.filter((source) => source.owner === 'engine');
412
+ const compatibility = sources.filter((source) => source.owner === 'compatibility');
318
413
  return {
319
414
  name: 'compat-sources',
320
415
  status: 'ok',
321
- detail: details.join('; '),
416
+ detail: `${auth_core_1.FIRST_PARTY_HARNESS.displayName}-owned: ${owned.map(describe).join(', ')}; ` +
417
+ `compatibility (read-only): ${compatibility.map(describe).join(', ')}. ` +
418
+ 'A daemon-hosted session also gets the skills its daemon discovers under other roots ' +
419
+ '(.devin, .windsurf, .codex, …) — `skrr skills local` lists them.',
420
+ sources,
322
421
  };
323
422
  }
324
423
  function opencodeCheck(cwd) {
@@ -1,11 +1,18 @@
1
1
  import { withQuery } from './triggers';
2
2
  type Query = Parameters<typeof withQuery>[1];
3
3
  type Json = Record<string, unknown>;
4
- export declare const FOLLOWUP_KINDS: readonly ["reminder", "watch", "checkin", "act"];
5
- export type FollowUpKind = (typeof FOLLOWUP_KINDS)[number];
6
- export declare const FOLLOWUP_STATES: readonly ["armed", "proposed", "settled", "paused"];
7
- /** Terminals a caller may name on `resolve` — the rest are the runtime's. */
8
- export declare const FOLLOWUP_RESOLVE_OUTCOMES: readonly ["resolved", "abandoned"];
4
+ /**
5
+ * The `id` argument every follow-up command that addresses one takes.
6
+ *
7
+ * oclif treats an empty string as a PRESENT required argument, so a scripted
8
+ * `skrr followups show "$ID"` with an empty variable built `/api/followups/` —
9
+ * the LIST route — and answered with the list's requirement, "agentId is
10
+ * required unless allAgents is set", naming two flags `show` does not have
11
+ * (OSK-9676). Refused at parse time instead, so it renders where a missing
12
+ * argument does, with usage, before any request is sent.
13
+ */
14
+ export declare const followUpIdArg: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
15
+ export { FOLLOWUP_KINDS, FOLLOWUP_STATES, FOLLOWUP_RESOLVE_OUTCOMES, type FollowUpKind, } from '@skrr-ai/data-provider';
9
16
  export declare const WATCH_WAIT_KINDS: readonly ["clock", "event", "poll_until"];
10
17
  export interface FollowUpRow {
11
18
  id: string;
@@ -13,6 +20,8 @@ export interface FollowUpRow {
13
20
  form?: string | null;
14
21
  producer?: string;
15
22
  why?: string;
23
+ /** A reminder's own words. */
24
+ content?: string | null;
16
25
  intentKey?: string;
17
26
  subject?: {
18
27
  type?: string;
@@ -104,4 +113,3 @@ export declare const followupsApi: {
104
113
  reschedule: (id: string, body: Json) => Promise<Json>;
105
114
  };
106
115
  export declare function followupSummaryLine(row: FollowUpRow): string;
107
- export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.followupsApi = exports.WATCH_WAIT_KINDS = exports.FOLLOWUP_RESOLVE_OUTCOMES = exports.FOLLOWUP_STATES = exports.FOLLOWUP_KINDS = void 0;
3
+ exports.followupsApi = exports.WATCH_WAIT_KINDS = exports.FOLLOWUP_RESOLVE_OUTCOMES = exports.FOLLOWUP_STATES = exports.FOLLOWUP_KINDS = exports.followUpIdArg = void 0;
4
4
  exports.resolveFollowUpAgent = resolveFollowUpAgent;
5
5
  exports.parseSubjectRef = parseSubjectRef;
6
6
  exports.followupSummaryLine = followupSummaryLine;
@@ -19,19 +19,44 @@ exports.followupSummaryLine = followupSummaryLine;
19
19
  * `why` and the server derives the rest; a second derivation here would be
20
20
  * exactly the drift the service exists to kill.
21
21
  */
22
+ const core_1 = require("@oclif/core");
22
23
  const data_provider_1 = require("@skrr-ai/data-provider");
23
24
  const runtime_context_1 = require("./runtime-context");
24
25
  const triggers_1 = require("./triggers");
25
26
  const agent_resolver_1 = require("./agent-resolver");
26
27
  const MOUNT = '/api/followups';
27
28
  const base = (id) => `${MOUNT}/${encodeURIComponent(id)}`;
29
+ /**
30
+ * The `id` argument every follow-up command that addresses one takes.
31
+ *
32
+ * oclif treats an empty string as a PRESENT required argument, so a scripted
33
+ * `skrr followups show "$ID"` with an empty variable built `/api/followups/` —
34
+ * the LIST route — and answered with the list's requirement, "agentId is
35
+ * required unless allAgents is set", naming two flags `show` does not have
36
+ * (OSK-9676). Refused at parse time instead, so it renders where a missing
37
+ * argument does, with usage, before any request is sent.
38
+ */
39
+ exports.followUpIdArg = core_1.Args.string({
40
+ description: 'Follow-up (trigger) id',
41
+ required: true,
42
+ ignoreStdin: true,
43
+ parse: async (input) => {
44
+ const id = input.trim();
45
+ if (!id)
46
+ throw new Error('id is empty — pass the follow-up id (see `skrr followups list`)');
47
+ return id;
48
+ },
49
+ });
28
50
  /* ------------------------------------------------------------------ *
29
51
  * Vocabulary (client-side validation only — the server is the authority) *
30
52
  * ------------------------------------------------------------------ */
31
- exports.FOLLOWUP_KINDS = ['reminder', 'watch', 'checkin', 'act'];
32
- exports.FOLLOWUP_STATES = ['armed', 'proposed', 'settled', 'paused'];
33
- /** Terminals a caller may name on `resolve` — the rest are the runtime's. */
34
- exports.FOLLOWUP_RESOLVE_OUTCOMES = ['resolved', 'abandoned'];
53
+ // Owned by `@skrr-ai/data-provider`, which the server validates against. These
54
+ // were declared a second time here, and the state list is where the two copies
55
+ // disagreed.
56
+ var data_provider_2 = require("@skrr-ai/data-provider");
57
+ Object.defineProperty(exports, "FOLLOWUP_KINDS", { enumerable: true, get: function () { return data_provider_2.FOLLOWUP_KINDS; } });
58
+ Object.defineProperty(exports, "FOLLOWUP_STATES", { enumerable: true, get: function () { return data_provider_2.FOLLOWUP_STATES; } });
59
+ Object.defineProperty(exports, "FOLLOWUP_RESOLVE_OUTCOMES", { enumerable: true, get: function () { return data_provider_2.FOLLOWUP_RESOLVE_OUTCOMES; } });
35
60
  exports.WATCH_WAIT_KINDS = ['clock', 'event', 'poll_until'];
36
61
  /**
37
62
  * Which agent a follow-up belongs to.
@@ -65,7 +90,7 @@ function resolveFollowUpAgent(explicitAgentId, env = process.env) {
65
90
  return { id: explicitAgentId, boundToSession: false };
66
91
  throw new agent_resolver_1.AgentResolutionError({
67
92
  code: 'AGENT_CONTEXT_AMBIGUOUS',
68
- message: 'No agent context: a follow-up needs an explicit agent and this session supplies none.',
93
+ message: 'No agent: this session is not bound to one, so name the agent these follow-ups are for.',
69
94
  suggestion: 'Pass `--agent <agent-id>`, run inside a daemon session that sets OVERSKY_SESSION_AGENT_ID, or use `--all-agents` where listing is the intent.',
70
95
  details: { runtimeKind: runtime.kind },
71
96
  });
@@ -42,6 +42,14 @@ export interface Harness {
42
42
  _id: string;
43
43
  provider: string;
44
44
  name?: string;
45
+ /**
46
+ * The name everyone else sees, when YOUR alias is covering it. `name` is the
47
+ * effective one. Present only while an alias is actually shadowing a
48
+ * different value, so a reader can tell "no alias" from "alias equals the
49
+ * shared name".
50
+ */
51
+ sharedName?: string;
52
+ aliased?: boolean;
45
53
  status?: string;
46
54
  harnessLocation?: 'local' | 'cloud';
47
55
  daemonId?: string;
@@ -50,11 +50,29 @@ export declare function resolveBundleLabel(bundleId: string | undefined, names:
50
50
  * the daemon is genuinely gone. A remedy that 409s is worse than no remedy — it
51
51
  * spends the reader's attention and returns them to where they started.
52
52
  */
53
+ /**
54
+ * A daemon id is `daemon_<hash>_<source>[_<profile>]`, where the hash covers
55
+ * the MACHINE and the cwd and `<source>` is the supervision mode
56
+ * (`cli`, `launchd`, `electron`, …). So two ids that differ only in that
57
+ * segment describe the SAME machine and directory, started a different way.
58
+ *
59
+ * That matters because switching how the daemon is started — the desktop app
60
+ * installs a launchd agent, `skrr daemon start` runs a cli one — mints a new
61
+ * id and orphans every managed-instruction target pinned to the old one.
62
+ */
63
+ export declare function parseDaemonId(daemonId: string): {
64
+ place: string;
65
+ source: string;
66
+ profile: string;
67
+ } | null;
68
+ /** The live daemon that is this target's machine and directory, started differently. */
69
+ export declare function sameMachineDaemon(targetDaemonId: string, liveDaemonIds: string[]): string | null;
53
70
  export declare function describeTargetSync(target: {
54
71
  status: string;
72
+ daemonId?: string;
55
73
  lastError?: string;
56
74
  lastSyncedAt?: string;
57
75
  lastAttemptedAt?: string;
58
76
  updatedAt?: string;
59
77
  driftCount?: number;
60
- }, now?: number): string;
78
+ }, now?: number, liveDaemonIds?: string[]): string;
@@ -4,6 +4,8 @@ exports.readInstructionBody = readInstructionBody;
4
4
  exports.formatSyncStatus = formatSyncStatus;
5
5
  exports.buildBundleNameIndex = buildBundleNameIndex;
6
6
  exports.resolveBundleLabel = resolveBundleLabel;
7
+ exports.parseDaemonId = parseDaemonId;
8
+ exports.sameMachineDaemon = sameMachineDaemon;
7
9
  exports.describeTargetSync = describeTargetSync;
8
10
  const promises_1 = require("node:fs/promises");
9
11
  async function readStdin() {
@@ -93,7 +95,39 @@ const PENDING_IS_SUSPECT_AFTER_MS = 24 * 60 * 60 * 1000;
93
95
  * the daemon is genuinely gone. A remedy that 409s is worse than no remedy — it
94
96
  * spends the reader's attention and returns them to where they started.
95
97
  */
96
- function describeTargetSync(target, now = Date.now()) {
98
+ /**
99
+ * A daemon id is `daemon_<hash>_<source>[_<profile>]`, where the hash covers
100
+ * the MACHINE and the cwd and `<source>` is the supervision mode
101
+ * (`cli`, `launchd`, `electron`, …). So two ids that differ only in that
102
+ * segment describe the SAME machine and directory, started a different way.
103
+ *
104
+ * That matters because switching how the daemon is started — the desktop app
105
+ * installs a launchd agent, `skrr daemon start` runs a cli one — mints a new
106
+ * id and orphans every managed-instruction target pinned to the old one.
107
+ */
108
+ function parseDaemonId(daemonId) {
109
+ const parts = String(daemonId || '').split('_');
110
+ if (parts.length < 3 || parts[0] !== 'daemon')
111
+ return null;
112
+ return { place: parts[1], source: parts[2], profile: parts.slice(3).join('_') };
113
+ }
114
+ /** The live daemon that is this target's machine and directory, started differently. */
115
+ function sameMachineDaemon(targetDaemonId, liveDaemonIds) {
116
+ const target = parseDaemonId(targetDaemonId);
117
+ if (!target)
118
+ return null;
119
+ for (const live of liveDaemonIds) {
120
+ if (live === targetDaemonId)
121
+ continue;
122
+ const other = parseDaemonId(live);
123
+ if (!other)
124
+ continue;
125
+ if (other.place === target.place && other.profile === target.profile)
126
+ return live;
127
+ }
128
+ return null;
129
+ }
130
+ function describeTargetSync(target, now = Date.now(), liveDaemonIds = []) {
97
131
  const base = formatSyncStatus(target.status, target.lastError);
98
132
  // Say when skrr has overwritten something you typed.
99
133
  //
@@ -131,5 +165,22 @@ function describeTargetSync(target, now = Date.now()) {
131
165
  // remedy off the end — the same truncation e51abf3362 exists to prevent. A
132
166
  // stalled target is not reconciling, so its drift is historical and the
133
167
  // remedy is the actionable half; the count reappears once it is unstuck.
168
+ // CHECK BEFORE ASSERTING, and never ship `--force` with a guess.
169
+ //
170
+ // "daemon may be gone" was stated unconditionally. On this machine it was
171
+ // false — the daemon had answered a heartbeat 112 ms earlier — because the
172
+ // target is pinned to `daemon_<hash>_launchd_default` while the live daemon
173
+ // is `daemon_<hash>_cli_default`: same machine, same directory, started a
174
+ // different way. So the CLI confidently recommended
175
+ // `remove, then purge-target --force` against live, correctly-installed
176
+ // managed blocks. An error that is confidently wrong AND carries its own
177
+ // `--force` is worse than one that says it does not know.
178
+ const elsewhere = sameMachineDaemon(target.daemonId || '', liveDaemonIds);
179
+ if (elsewhere) {
180
+ const live = parseDaemonId(elsewhere);
181
+ const pinned = parseDaemonId(target.daemonId || '');
182
+ // Kept under the STATUS column's `maxWidth: 78`, same constraint as below.
183
+ return `${base} — stalled ${days}d; daemon here now runs as ${live?.source}, not ${pinned?.source}: re-install`;
184
+ }
134
185
  return `${base} — stalled ${days}d; daemon may be gone: remove, then purge-target --force`;
135
186
  }
@@ -11,6 +11,21 @@
11
11
  */
12
12
  export declare const LABEL_SCOPES: readonly ["user", "workspace"];
13
13
  export type LabelScope = (typeof LABEL_SCOPES)[number];
14
+ /**
15
+ * Scopes whose id the server cannot infer, so `--scope-id` must name it.
16
+ *
17
+ * `resolveLabelScope` below and the `--scope-id` help text are BOTH derived
18
+ * from this, rather than each restating the list. They drifted once already:
19
+ * `0298b7e4fd` collapsed the vocabulary from three scopes to two, and the help
20
+ * kept advertising `--scope space` for months after the validator had stopped
21
+ * accepting it — so following `--help` produced `Expected --scope=space to be
22
+ * one of: user, workspace`, whose last line points back at the help that was
23
+ * wrong. Static prose describing a value set is how that happens; deriving it
24
+ * is what stops the next collapse doing the same.
25
+ */
26
+ export declare const LABEL_SCOPES_REQUIRING_ID: readonly ["workspace"];
27
+ /** Scopes the server resolves from the caller — passing an id is an error. */
28
+ export declare const LABEL_SCOPES_INFERRED: "user"[];
14
29
  export declare const LABEL_APPLICABLE: readonly ["task", "space", "goal", "routine"];
15
30
  export type LabelApplicable = (typeof LABEL_APPLICABLE)[number];
16
31
  /**
@@ -11,12 +11,31 @@
11
11
  * id the server can infer (it falls back to the caller).
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.labelScopeFlags = exports.HEX_COLOR_RE = exports.LABEL_APPLICABLE = exports.LABEL_SCOPES = void 0;
14
+ exports.labelScopeFlags = exports.HEX_COLOR_RE = exports.LABEL_APPLICABLE = exports.LABEL_SCOPES_INFERRED = exports.LABEL_SCOPES_REQUIRING_ID = exports.LABEL_SCOPES = void 0;
15
15
  exports.normalizeLabelColor = normalizeLabelColor;
16
16
  exports.resolveLabelScope = resolveLabelScope;
17
17
  exports.resolveApplicableTo = resolveApplicableTo;
18
18
  const core_1 = require("@oclif/core");
19
19
  exports.LABEL_SCOPES = ['user', 'workspace'];
20
+ /**
21
+ * Scopes whose id the server cannot infer, so `--scope-id` must name it.
22
+ *
23
+ * `resolveLabelScope` below and the `--scope-id` help text are BOTH derived
24
+ * from this, rather than each restating the list. They drifted once already:
25
+ * `0298b7e4fd` collapsed the vocabulary from three scopes to two, and the help
26
+ * kept advertising `--scope space` for months after the validator had stopped
27
+ * accepting it — so following `--help` produced `Expected --scope=space to be
28
+ * one of: user, workspace`, whose last line points back at the help that was
29
+ * wrong. Static prose describing a value set is how that happens; deriving it
30
+ * is what stops the next collapse doing the same.
31
+ */
32
+ exports.LABEL_SCOPES_REQUIRING_ID = ['workspace'];
33
+ const scopesRequiringId = () => exports.LABEL_SCOPES_REQUIRING_ID;
34
+ /** Scopes the server resolves from the caller — passing an id is an error. */
35
+ exports.LABEL_SCOPES_INFERRED = exports.LABEL_SCOPES.filter((scope) => !exports.LABEL_SCOPES_REQUIRING_ID.includes(scope));
36
+ function joinScopes(scopes) {
37
+ return scopes.map((scope) => `--scope ${scope}`).join(' / ');
38
+ }
20
39
  exports.LABEL_APPLICABLE = ['task', 'space', 'goal', 'routine'];
21
40
  /**
22
41
  * The server stores colors as bare 6-hex (`api/server/routes/labels.js` Zod is
@@ -34,7 +53,7 @@ exports.labelScopeFlags = {
34
53
  default: 'user',
35
54
  }),
36
55
  'scope-id': core_1.Flags.string({
37
- description: 'Space or workspace ID — required for --scope space|workspace. Omit for --scope user (defaults to you).',
56
+ description: `Scope owner ID — required for ${joinScopes(scopesRequiringId())}. Omit for ${joinScopes(exports.LABEL_SCOPES_INFERRED)} (defaults to you).`,
38
57
  }),
39
58
  };
40
59
  /**
@@ -44,11 +63,12 @@ exports.labelScopeFlags = {
44
63
  function resolveLabelScope(flags) {
45
64
  const scope = (flags.scope ?? 'user');
46
65
  const scopeId = flags['scope-id'];
47
- if (scope === 'workspace' && !scopeId) {
66
+ const requiresId = exports.LABEL_SCOPES_REQUIRING_ID.includes(scope);
67
+ if (requiresId && !scopeId) {
48
68
  throw new Error(`--scope-id is required for --scope ${scope}.`);
49
69
  }
50
- if (scope === 'user' && scopeId) {
51
- throw new Error('--scope-id is not accepted for --scope user; user-scope labels are always your own.');
70
+ if (!requiresId && scopeId) {
71
+ throw new Error(`--scope-id is not accepted for --scope ${scope}; ${scope}-scope labels are always your own.`);
52
72
  }
53
73
  return { scope, ...(scopeId ? { scopeId } : {}) };
54
74
  }
@@ -0,0 +1,98 @@
1
+ import type { DaemonLocalSkill } from '@skrr-ai/data-provider';
2
+ /**
3
+ * Skills on a machine, as its daemon lists them — the CLI half of the `/` menu.
4
+ *
5
+ * `skrr` had two things called "skill" and commands for only one: store and
6
+ * workspace skills (`skills *`, `--skill <skill-id>`) had a full surface, while
7
+ * the skills in a machine's `.claude/skills` and sibling roots — the ones the
8
+ * web `/` menu offers — could be neither listed nor invoked, so a headless
9
+ * operator or a locally-running coding agent could not use them at all
10
+ * (OSK-9478). `skills local` lists them; `agents chat --local-skill` invokes
11
+ * one. Both resolve through here, so a name means the same skill in each.
12
+ */
13
+ export type ConnectedDaemon = {
14
+ daemonId: string;
15
+ deviceName?: string | null;
16
+ };
17
+ /**
18
+ * Which machine to ask, or why there is no single answer.
19
+ *
20
+ * Resolves rather than guesses: picking one of several machines and reporting
21
+ * its skills as "the" answer is the same silent narrowing the listing exists
22
+ * to remove.
23
+ */
24
+ export declare function chooseDaemon(active: ReadonlyArray<ConnectedDaemon>): {
25
+ daemonId: string;
26
+ } | {
27
+ problem: string;
28
+ candidates: ConnectedDaemon[];
29
+ };
30
+ /** A skill with no declared triggers is invocable both ways — the walker's default. */
31
+ export declare function isUserInvocable(skill: Pick<DaemonLocalSkill, 'triggers'>): boolean;
32
+ /**
33
+ * Turn requested names into the references the server resolves.
34
+ *
35
+ * A request is `name`, or `<root>/<name>` when the same name exists under more
36
+ * than one root (`.claude/skills/review` vs `.agents/skills/review`). Each
37
+ * problem is reported in words that say what to type instead; nothing is
38
+ * dropped, because the server's own rule is that a skill the user picked and
39
+ * the turn did not load must fail the turn rather than run without it.
40
+ */
41
+ export declare function resolveLocalSkillRefs(inventory: ReadonlyArray<DaemonLocalSkill>, requested: ReadonlyArray<string>): {
42
+ refs: Array<{
43
+ name: string;
44
+ pathHash: string;
45
+ }>;
46
+ problems: string[];
47
+ };
48
+ /**
49
+ * The prompt with a `/name` for every invoked skill it does not already name.
50
+ *
51
+ * The web composer sends the `/name` in the text beside the reference, and
52
+ * drops a reference whose `/name` is gone; a CLI turn carries the same pair so
53
+ * the agent reads the same invocation either way.
54
+ */
55
+ export declare function withSkillInvocations(prompt: string, refs: ReadonlyArray<{
56
+ name: string;
57
+ }>): string;
58
+ /** Whether a skill argument names a place on disk rather than a store id. */
59
+ export declare function looksLikeSkillPath(arg: string): boolean;
60
+ export type LocalSkillSighting = {
61
+ daemonId: string;
62
+ deviceName?: string | null;
63
+ source?: string;
64
+ };
65
+ /**
66
+ * Where a skill with this name exists on the caller's connected machines.
67
+ *
68
+ * Best-effort by design: it runs only to word an error that is already going
69
+ * to be reported, so a machine that cannot be asked contributes nothing rather
70
+ * than replacing the real error with a second one.
71
+ */
72
+ export declare function findLocalSkillsNamed(name: string): Promise<LocalSkillSighting[]>;
73
+ /**
74
+ * The error for a skill argument a STORE command could not use.
75
+ *
76
+ * `skills install <name>` and `skills details <name>` answered a local skill's
77
+ * name or path with "Skill not found / NOT_FOUND": true of the store, and no
78
+ * help to someone the product had just told it reads their `.claude/skills`
79
+ * (OSK-9412). The answer depends on what the argument was, so it says which:
80
+ * a path (never a store id), a name found on a connected machine (needs no
81
+ * install), or neither (look the id up in the store).
82
+ */
83
+ export declare function describeStoreSkillMiss(arg: string, sightings: ReadonlyArray<LocalSkillSighting>, command: 'install' | 'details'): string;
84
+ /**
85
+ * The first daemon release whose walker scans the skill conventions — the
86
+ * project's `.claude/skills`, `.agents/skills`, `.devin/skills`,
87
+ * `.windsurf/skills` and the global `~/.claude/skills`. It arrived in
88
+ * `e9dfa732cd` and first shipped in 0.8.44; an older daemon scans only
89
+ * `claudeSession.skillsDir`, which is empty unless someone set it by hand.
90
+ */
91
+ export declare const SKILL_CONVENTION_DISCOVERY_SINCE = "0.8.44";
92
+ /**
93
+ * Whether a daemon's reported version is older than `floor`.
94
+ *
95
+ * Unknown or unparseable versions answer false: this decides only whether to
96
+ * add an explanation, and claiming an unknown daemon is old would be a guess.
97
+ */
98
+ export declare function daemonPredates(version: string | null | undefined, floor: string): boolean;