@skillsmith/cli 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/commands/index.d.ts +1 -0
  4. package/dist/src/commands/index.d.ts.map +1 -1
  5. package/dist/src/commands/index.js +2 -0
  6. package/dist/src/commands/index.js.map +1 -1
  7. package/dist/src/commands/inventory.action.d.ts +55 -0
  8. package/dist/src/commands/inventory.action.d.ts.map +1 -0
  9. package/dist/src/commands/inventory.action.js +179 -0
  10. package/dist/src/commands/inventory.action.js.map +1 -0
  11. package/dist/src/commands/inventory.action.test.d.ts +19 -0
  12. package/dist/src/commands/inventory.action.test.d.ts.map +1 -0
  13. package/dist/src/commands/inventory.action.test.js +371 -0
  14. package/dist/src/commands/inventory.action.test.js.map +1 -0
  15. package/dist/src/commands/inventory.d.ts +21 -0
  16. package/dist/src/commands/inventory.d.ts.map +1 -0
  17. package/dist/src/commands/inventory.js +42 -0
  18. package/dist/src/commands/inventory.js.map +1 -0
  19. package/dist/src/commands/login.d.ts.map +1 -1
  20. package/dist/src/commands/login.js +8 -40
  21. package/dist/src/commands/login.js.map +1 -1
  22. package/dist/src/commands/login.test.js +12 -32
  23. package/dist/src/commands/login.test.js.map +1 -1
  24. package/dist/src/index.js +9 -5
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/utils/skills-directory.d.ts +42 -0
  27. package/dist/src/utils/skills-directory.d.ts.map +1 -1
  28. package/dist/src/utils/skills-directory.js +76 -0
  29. package/dist/src/utils/skills-directory.js.map +1 -1
  30. package/dist/src/utils/startup-header-gate.d.ts +29 -0
  31. package/dist/src/utils/startup-header-gate.d.ts.map +1 -0
  32. package/dist/src/utils/startup-header-gate.js +44 -0
  33. package/dist/src/utils/startup-header-gate.js.map +1 -0
  34. package/dist/src/utils/startup-header-gate.test.d.ts +2 -0
  35. package/dist/src/utils/startup-header-gate.test.d.ts.map +1 -0
  36. package/dist/src/utils/startup-header-gate.test.js +46 -0
  37. package/dist/src/utils/startup-header-gate.test.js.map +1 -0
  38. package/dist/tests/skills-directory-per-harness.test.d.ts +2 -0
  39. package/dist/tests/skills-directory-per-harness.test.d.ts.map +1 -0
  40. package/dist/tests/skills-directory-per-harness.test.js +116 -0
  41. package/dist/tests/skills-directory-per-harness.test.js.map +1 -0
  42. package/package.json +3 -3
  43. package/dist/src/commands/login.post-login-sync.test.d.ts +0 -2
  44. package/dist/src/commands/login.post-login-sync.test.d.ts.map +0 -1
  45. package/dist/src/commands/login.post-login-sync.test.js +0 -120
  46. package/dist/src/commands/login.post-login-sync.test.js.map +0 -1
@@ -24,4 +24,5 @@ export { createImportCommand, importSkills } from './import.js';
24
24
  export { createImportLocalCommand, runImportLocal } from './import-local.js';
25
25
  export { createConfigCommand } from './config.js';
26
26
  export { createTelemetryCommand } from './telemetry.js';
27
+ export { createInventoryCommand } from './inventory.js';
27
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAMzF,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/D,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAG5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAMzF,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAGnD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAG9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAG/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAG/C,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAG/D,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAG5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -45,4 +45,6 @@ export { createImportLocalCommand, runImportLocal } from './import-local.js';
45
45
  export { createConfigCommand } from './config.js';
46
46
  // SMI-5021 Wave 3: telemetry management subcommands
47
47
  export { createTelemetryCommand } from './telemetry.js';
48
+ // SMI-5392 Wave 3: cross-harness inventory push/status/forget-device
49
+ export { createInventoryCommand } from './inventory.js';
48
50
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,4BAA4B;AAC5B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEzF,2BAA2B;AAC3B,0CAA0C;AAC1C,mCAAmC;AACnC,8CAA8C;AAC9C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAE1B,8BAA8B;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,4BAA4B;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAEvD,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAE7C,mCAAmC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,+CAA+C;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,iEAAiE;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAE9D,kCAAkC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE/D,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEjF,6CAA6C;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAE7C,iFAAiF;AACjF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/D,iDAAiD;AACjD,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAE5E,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,oDAAoD;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,4BAA4B;AAC5B,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEzF,2BAA2B;AAC3B,0CAA0C;AAC1C,mCAAmC;AACnC,8CAA8C;AAC9C,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAE1B,8BAA8B;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,4BAA4B;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAEvD,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAE7C,mCAAmC;AACnC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,+CAA+C;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAEnD,iEAAiE;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAE9D,kCAAkC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,sDAAsD;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE/D,6DAA6D;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C,uCAAuC;AACvC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEjF,6CAA6C;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAE7C,iFAAiF;AACjF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/D,iDAAiD;AACjD,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAE5E,2DAA2D;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEjD,oDAAoD;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAEvD,qEAAqE;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @fileoverview `skillsmith inventory` action implementations + telemetry wrappers.
3
+ * @module @skillsmith/cli/commands/inventory.action
4
+ * @see SMI-5392 Wave 3 — CLI `inventory push/status/forget-device` subcommands
5
+ * (umbrella SMI-5382). Follows the SMI-5128 sibling-split convention: the run*
6
+ * business logic + typed-error handling + withTelemetry-wrapped exports live here;
7
+ * the commander factory stays in inventory.ts.
8
+ *
9
+ * Error-mapping contract for `push`:
10
+ * InventoryAuthError → "Not logged in. Run `skillsmith login` and try again."
11
+ * InventoryConflictError → device already owned; instruct forget-device
12
+ * InventoryValidationError → err.message (server-supplied reason)
13
+ * InventoryUploadError → "Inventory upload failed. " + err.message
14
+ */
15
+ /**
16
+ * Build and upload this device's cross-harness skill inventory snapshot.
17
+ *
18
+ * The local opt-out (`SKILLSMITH_INVENTORY_DISABLE`) and the server-side
19
+ * consent-disabled path are both rendered as informational messages rather
20
+ * than errors.
21
+ *
22
+ * @see SMI-5392
23
+ */
24
+ export declare function runPush(): Promise<void>;
25
+ /** @internal Exported for unit tests. */
26
+ export declare function inventoryPushActionImpl(): Promise<void>;
27
+ export declare const inventoryPushAction: () => Promise<void>;
28
+ /**
29
+ * Print a local inventory snapshot: device ID, last-push timestamp, local
30
+ * opt-out flag, harness presence, and per-harness skill counts.
31
+ *
32
+ * @param opts.verbose - When true, list individual skill IDs under each harness.
33
+ * @see SMI-5392
34
+ */
35
+ export declare function runStatus(opts?: {
36
+ verbose?: boolean;
37
+ }): Promise<void>;
38
+ /** @internal Exported for unit tests. */
39
+ export declare function inventoryStatusActionImpl(options: {
40
+ verbose?: boolean;
41
+ }): Promise<void>;
42
+ export declare const inventoryStatusAction: (options: {
43
+ verbose?: boolean;
44
+ }) => Promise<void>;
45
+ /**
46
+ * Clear the locally-persisted device registration so that the next push
47
+ * registers a fresh device UUID.
48
+ *
49
+ * @see SMI-5392
50
+ */
51
+ export declare function runForgetDevice(): Promise<void>;
52
+ /** @internal Exported for unit tests. */
53
+ export declare function inventoryForgetDeviceActionImpl(): Promise<void>;
54
+ export declare const inventoryForgetDeviceAction: () => Promise<void>;
55
+ //# sourceMappingURL=inventory.action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.action.d.ts","sourceRoot":"","sources":["../../../src/commands/inventory.action.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAyBH;;;;;;;;GAQG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CA+B7C;AAED,yCAAyC;AACzC,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,IAAI,CAAC,CAsB7D;AAED,eAAO,MAAM,mBAAmB,qBAI9B,CAAA;AAMF;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD3E;AAED,yCAAyC;AACzC,wBAAsB,yBAAyB,CAAC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAO7F;AAED,eAAO,MAAM,qBAAqB;cATmC,OAAO;mBAa1E,CAAA;AAMF;;;;;GAKG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAMrD;AAED,yCAAyC;AACzC,wBAAsB,+BAA+B,IAAI,OAAO,CAAC,IAAI,CAAC,CAOrE;AAED,eAAO,MAAM,2BAA2B,qBAItC,CAAA"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * @fileoverview `skillsmith inventory` action implementations + telemetry wrappers.
3
+ * @module @skillsmith/cli/commands/inventory.action
4
+ * @see SMI-5392 Wave 3 — CLI `inventory push/status/forget-device` subcommands
5
+ * (umbrella SMI-5382). Follows the SMI-5128 sibling-split convention: the run*
6
+ * business logic + typed-error handling + withTelemetry-wrapped exports live here;
7
+ * the commander factory stays in inventory.ts.
8
+ *
9
+ * Error-mapping contract for `push`:
10
+ * InventoryAuthError → "Not logged in. Run `skillsmith login` and try again."
11
+ * InventoryConflictError → device already owned; instruct forget-device
12
+ * InventoryValidationError → err.message (server-supplied reason)
13
+ * InventoryUploadError → "Inventory upload failed. " + err.message
14
+ */
15
+ import chalk from 'chalk';
16
+ import { pushInventory, getDeviceId, forgetDevice, getLastInventoryPushAt, isInventorySyncDisabledLocally, InventoryAuthError, InventoryConflictError, InventoryValidationError, InventoryUploadError, } from '@skillsmith/core';
17
+ import { enumerateHarnessPresence } from '@skillsmith/core/install';
18
+ import { withTelemetry } from '@skillsmith/core/telemetry';
19
+ import { sanitizeError } from '../utils/sanitize.js';
20
+ import { getInstalledSkillsPerHarness } from '../utils/skills-directory.js';
21
+ import { VERSION } from '../version.js';
22
+ // ---------------------------------------------------------------------------
23
+ // push
24
+ // ---------------------------------------------------------------------------
25
+ /**
26
+ * Build and upload this device's cross-harness skill inventory snapshot.
27
+ *
28
+ * The local opt-out (`SKILLSMITH_INVENTORY_DISABLE`) and the server-side
29
+ * consent-disabled path are both rendered as informational messages rather
30
+ * than errors.
31
+ *
32
+ * @see SMI-5392
33
+ */
34
+ export async function runPush() {
35
+ const r = await pushInventory({ cliVersion: VERSION });
36
+ if (r.reason === 'disabled_locally') {
37
+ console.log(chalk.dim('Inventory sync disabled locally via SKILLSMITH_INVENTORY_DISABLE; nothing sent.'));
38
+ return;
39
+ }
40
+ if (!r.applied && r.reason === 'consent_disabled') {
41
+ console.log(chalk.yellow('Inventory sync is OFF for your account. Enable it in account settings; nothing stored.'));
42
+ return;
43
+ }
44
+ if (r.applied) {
45
+ console.log(chalk.green(`Pushed for device ${r.device_id ?? '(unknown)'}: ` +
46
+ `${r.skills_present ?? 0} present, ${r.skills_absent ?? 0} marked absent.`));
47
+ return;
48
+ }
49
+ // Defensive: unexpected ok/reason combo — relay raw fields.
50
+ console.log(`Inventory push result: ok=${String(r.ok)} reason=${r.reason ?? '(none)'}`);
51
+ }
52
+ /** @internal Exported for unit tests. */
53
+ export async function inventoryPushActionImpl() {
54
+ try {
55
+ await runPush();
56
+ }
57
+ catch (err) {
58
+ if (err instanceof InventoryAuthError) {
59
+ console.error(chalk.red('Not logged in. Run `skillsmith login` and try again.'));
60
+ }
61
+ else if (err instanceof InventoryConflictError) {
62
+ console.error(chalk.red('This device is registered to another account. ' +
63
+ 'Run `skillsmith inventory forget-device` and push again.'));
64
+ }
65
+ else if (err instanceof InventoryValidationError) {
66
+ console.error(chalk.red(err.message));
67
+ }
68
+ else if (err instanceof InventoryUploadError) {
69
+ console.error(chalk.red('Inventory upload failed. ' + err.message));
70
+ }
71
+ else {
72
+ console.error(chalk.red('Error:'), sanitizeError(err));
73
+ }
74
+ process.exit(1);
75
+ }
76
+ }
77
+ export const inventoryPushAction = withTelemetry(inventoryPushActionImpl, {
78
+ source: 'cli',
79
+ extractSkillId: () => 'inventory push',
80
+ extractFramework: () => 'cli',
81
+ });
82
+ // ---------------------------------------------------------------------------
83
+ // status (read-only, no network)
84
+ // ---------------------------------------------------------------------------
85
+ /**
86
+ * Print a local inventory snapshot: device ID, last-push timestamp, local
87
+ * opt-out flag, harness presence, and per-harness skill counts.
88
+ *
89
+ * @param opts.verbose - When true, list individual skill IDs under each harness.
90
+ * @see SMI-5392
91
+ */
92
+ export async function runStatus(opts) {
93
+ const deviceId = getDeviceId();
94
+ const lastPush = getLastInventoryPushAt();
95
+ const syncDisabled = isInventorySyncDisabledLocally();
96
+ const harnessPresence = enumerateHarnessPresence();
97
+ const allSkills = await getInstalledSkillsPerHarness();
98
+ // Group skill counts by harness key.
99
+ const countByHarness = new Map();
100
+ for (const entry of allSkills) {
101
+ const key = String(entry.harness);
102
+ countByHarness.set(key, (countByHarness.get(key) ?? 0) + 1);
103
+ }
104
+ console.log(chalk.bold('Skillsmith Inventory Status'));
105
+ console.log();
106
+ console.log(` Device ID: ${deviceId ? chalk.cyan(deviceId) : chalk.dim('(not yet registered — a push will create one)')}`);
107
+ console.log(` Last push: ${lastPush ? chalk.dim(lastPush) : chalk.dim('never')}`);
108
+ console.log(` Local opt-out: ${syncDisabled ? chalk.yellow('yes (SKILLSMITH_INVENTORY_DISABLE set)') : chalk.dim('no')}`);
109
+ // Local (./.claude/skills) skills count.
110
+ const localCount = countByHarness.get('local') ?? 0;
111
+ if (localCount > 0) {
112
+ console.log(` Local skills: ${chalk.dim(`${localCount} skill${localCount === 1 ? '' : 's'} in ./.claude/skills (repo-local — not synced to your account)`)}`);
113
+ if (opts?.verbose) {
114
+ for (const s of allSkills.filter((e) => e.harness === 'local')) {
115
+ console.log(` - ${s.skillId}`);
116
+ }
117
+ }
118
+ }
119
+ console.log();
120
+ console.log(' Harness presence:');
121
+ for (const { harness, present } of harnessPresence) {
122
+ const count = countByHarness.get(harness) ?? 0;
123
+ const badge = present ? chalk.green('yes') : chalk.dim('no ');
124
+ const skillStr = present ? chalk.dim(`${count} skill${count === 1 ? '' : 's'}`) : '';
125
+ console.log(` ${String(harness).padEnd(14)} ${badge} ${skillStr}`);
126
+ if (opts?.verbose && present) {
127
+ for (const s of allSkills.filter((e) => e.harness === harness)) {
128
+ console.log(` - ${s.skillId}`);
129
+ }
130
+ }
131
+ }
132
+ }
133
+ /** @internal Exported for unit tests. */
134
+ export async function inventoryStatusActionImpl(options) {
135
+ try {
136
+ await runStatus(options);
137
+ }
138
+ catch (err) {
139
+ console.error(chalk.red('Error:'), sanitizeError(err));
140
+ process.exit(1);
141
+ }
142
+ }
143
+ export const inventoryStatusAction = withTelemetry(inventoryStatusActionImpl, {
144
+ source: 'cli',
145
+ extractSkillId: () => 'inventory status',
146
+ extractFramework: () => 'cli',
147
+ });
148
+ // ---------------------------------------------------------------------------
149
+ // forget-device
150
+ // ---------------------------------------------------------------------------
151
+ /**
152
+ * Clear the locally-persisted device registration so that the next push
153
+ * registers a fresh device UUID.
154
+ *
155
+ * @see SMI-5392
156
+ */
157
+ export async function runForgetDevice() {
158
+ const had = getDeviceId();
159
+ forgetDevice();
160
+ console.log(chalk.green('Device registration cleared.'));
161
+ console.log(chalk.dim(` Was: ${had ?? '(none)'}`));
162
+ console.log(chalk.dim(' The next push will register a fresh device.'));
163
+ }
164
+ /** @internal Exported for unit tests. */
165
+ export async function inventoryForgetDeviceActionImpl() {
166
+ try {
167
+ await runForgetDevice();
168
+ }
169
+ catch (err) {
170
+ console.error(chalk.red('Error:'), sanitizeError(err));
171
+ process.exit(1);
172
+ }
173
+ }
174
+ export const inventoryForgetDeviceAction = withTelemetry(inventoryForgetDeviceActionImpl, {
175
+ source: 'cli',
176
+ extractSkillId: () => 'inventory forget-device',
177
+ extractFramework: () => 'cli',
178
+ });
179
+ //# sourceMappingURL=inventory.action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.action.js","sourceRoot":"","sources":["../../../src/commands/inventory.action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview Tests for `skillsmith inventory` subcommands.
3
+ * @module @skillsmith/cli/commands/inventory.action.test
4
+ * @see SMI-5392 Wave 3 — CLI inventory push/status/forget-device (umbrella SMI-5382)
5
+ *
6
+ * Covers:
7
+ * push: renders applied / consent-off / disabled-locally output correctly
8
+ * push: maps each of the 4 typed errors to console.error + process.exit(1)
9
+ * status: prints device ID, last-push, opt-out flag, and harness presence
10
+ * forget-device: calls core forgetDevice and prints confirmation with prior ID
11
+ *
12
+ * instanceof strategy:
13
+ * @skillsmith/core is mocked with inline class definitions for the four error
14
+ * types. Because vi.mock factories are hoisted, both the source module and the
15
+ * test file receive the SAME class reference — so `err instanceof InventoryAuthError`
16
+ * inside inventoryPushActionImpl matches the errors thrown in tests.
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=inventory.action.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.action.test.d.ts","sourceRoot":"","sources":["../../../src/commands/inventory.action.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG"}