coolhand-cli 0.11.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +13 -1
  2. package/dist/api/client-file-client.d.ts +19 -0
  3. package/dist/api/client-file-client.d.ts.map +1 -0
  4. package/dist/api/client-file-client.js +47 -0
  5. package/dist/api/client-file-client.js.map +1 -0
  6. package/dist/api/help-center-client.d.ts +26 -0
  7. package/dist/api/help-center-client.d.ts.map +1 -0
  8. package/dist/api/help-center-client.js +90 -0
  9. package/dist/api/help-center-client.js.map +1 -0
  10. package/dist/api/last-sync.d.ts.map +1 -1
  11. package/dist/api/last-sync.js +2 -1
  12. package/dist/api/last-sync.js.map +1 -1
  13. package/dist/api/workload-client.d.ts +16 -0
  14. package/dist/api/workload-client.d.ts.map +1 -0
  15. package/dist/api/workload-client.js +28 -0
  16. package/dist/api/workload-client.js.map +1 -0
  17. package/dist/auth/callback-server.d.ts.map +1 -1
  18. package/dist/auth/callback-server.js +13 -1
  19. package/dist/auth/callback-server.js.map +1 -1
  20. package/dist/auto-update/index.d.ts +61 -0
  21. package/dist/auto-update/index.d.ts.map +1 -0
  22. package/dist/auto-update/index.js +355 -0
  23. package/dist/auto-update/index.js.map +1 -0
  24. package/dist/auto-update/select.d.ts +28 -0
  25. package/dist/auto-update/select.d.ts.map +1 -0
  26. package/dist/auto-update/select.js +45 -0
  27. package/dist/auto-update/select.js.map +1 -0
  28. package/dist/auto-update/state.d.ts +25 -0
  29. package/dist/auto-update/state.d.ts.map +1 -0
  30. package/dist/auto-update/state.js +81 -0
  31. package/dist/auto-update/state.js.map +1 -0
  32. package/dist/cli.d.ts.map +1 -1
  33. package/dist/cli.js +525 -5
  34. package/dist/cli.js.map +1 -1
  35. package/dist/commands/capture-turn.d.ts +18 -0
  36. package/dist/commands/capture-turn.d.ts.map +1 -0
  37. package/dist/commands/capture-turn.js +152 -0
  38. package/dist/commands/capture-turn.js.map +1 -0
  39. package/dist/commands/download-client-file.d.ts +9 -0
  40. package/dist/commands/download-client-file.d.ts.map +1 -0
  41. package/dist/commands/download-client-file.js +71 -0
  42. package/dist/commands/download-client-file.js.map +1 -0
  43. package/dist/commands/fetch-log.d.ts.map +1 -1
  44. package/dist/commands/fetch-log.js +9 -0
  45. package/dist/commands/fetch-log.js.map +1 -1
  46. package/dist/commands/flush-pending.d.ts.map +1 -1
  47. package/dist/commands/flush-pending.js +1 -30
  48. package/dist/commands/flush-pending.js.map +1 -1
  49. package/dist/commands/get-help-article.d.ts +3 -0
  50. package/dist/commands/get-help-article.d.ts.map +1 -0
  51. package/dist/commands/get-help-article.js +49 -0
  52. package/dist/commands/get-help-article.js.map +1 -0
  53. package/dist/commands/get-template.d.ts.map +1 -1
  54. package/dist/commands/get-template.js +18 -1
  55. package/dist/commands/get-template.js.map +1 -1
  56. package/dist/commands/link-feedback.d.ts +5 -0
  57. package/dist/commands/link-feedback.d.ts.map +1 -0
  58. package/dist/commands/link-feedback.js +89 -0
  59. package/dist/commands/link-feedback.js.map +1 -0
  60. package/dist/commands/list-client-files.d.ts +3 -0
  61. package/dist/commands/list-client-files.d.ts.map +1 -0
  62. package/dist/commands/list-client-files.js +55 -0
  63. package/dist/commands/list-client-files.js.map +1 -0
  64. package/dist/commands/list-help-categories.d.ts +3 -0
  65. package/dist/commands/list-help-categories.d.ts.map +1 -0
  66. package/dist/commands/list-help-categories.js +47 -0
  67. package/dist/commands/list-help-categories.js.map +1 -0
  68. package/dist/commands/search-help-articles.d.ts +3 -0
  69. package/dist/commands/search-help-articles.d.ts.map +1 -0
  70. package/dist/commands/search-help-articles.js +73 -0
  71. package/dist/commands/search-help-articles.js.map +1 -0
  72. package/dist/commands/search-logs.d.ts.map +1 -1
  73. package/dist/commands/search-logs.js +26 -0
  74. package/dist/commands/search-logs.js.map +1 -1
  75. package/dist/commands/search-templates.d.ts.map +1 -1
  76. package/dist/commands/search-templates.js +12 -0
  77. package/dist/commands/search-templates.js.map +1 -1
  78. package/dist/commands/search-workloads.d.ts +3 -0
  79. package/dist/commands/search-workloads.d.ts.map +1 -0
  80. package/dist/commands/search-workloads.js +79 -0
  81. package/dist/commands/search-workloads.js.map +1 -0
  82. package/dist/commands/update-client-file.d.ts +3 -0
  83. package/dist/commands/update-client-file.d.ts.map +1 -0
  84. package/dist/commands/update-client-file.js +39 -0
  85. package/dist/commands/update-client-file.js.map +1 -0
  86. package/dist/commands/update.d.ts +9 -0
  87. package/dist/commands/update.d.ts.map +1 -0
  88. package/dist/commands/update.js +63 -0
  89. package/dist/commands/update.js.map +1 -0
  90. package/dist/config.d.ts +2 -0
  91. package/dist/config.d.ts.map +1 -1
  92. package/dist/config.js +25 -7
  93. package/dist/config.js.map +1 -1
  94. package/dist/errors.d.ts +1 -1
  95. package/dist/errors.d.ts.map +1 -1
  96. package/dist/errors.js.map +1 -1
  97. package/dist/format-cost.d.ts +9 -0
  98. package/dist/format-cost.d.ts.map +1 -0
  99. package/dist/format-cost.js +22 -0
  100. package/dist/format-cost.js.map +1 -0
  101. package/dist/hooks/adapters/claude.d.ts +12 -0
  102. package/dist/hooks/adapters/claude.d.ts.map +1 -0
  103. package/dist/hooks/adapters/claude.js +98 -0
  104. package/dist/hooks/adapters/claude.js.map +1 -0
  105. package/dist/hooks/adapters/copilot.d.ts +15 -0
  106. package/dist/hooks/adapters/copilot.d.ts.map +1 -0
  107. package/dist/hooks/adapters/copilot.js +96 -0
  108. package/dist/hooks/adapters/copilot.js.map +1 -0
  109. package/dist/hooks/adapters/index.d.ts +5 -0
  110. package/dist/hooks/adapters/index.d.ts.map +1 -0
  111. package/dist/hooks/adapters/index.js +8 -0
  112. package/dist/hooks/adapters/index.js.map +1 -0
  113. package/dist/hooks/adapters/shared.d.ts +25 -0
  114. package/dist/hooks/adapters/shared.d.ts.map +1 -0
  115. package/dist/hooks/adapters/shared.js +37 -0
  116. package/dist/hooks/adapters/shared.js.map +1 -0
  117. package/dist/hooks/disabled.d.ts +3 -0
  118. package/dist/hooks/disabled.d.ts.map +1 -0
  119. package/dist/hooks/disabled.js +5 -0
  120. package/dist/hooks/disabled.js.map +1 -0
  121. package/dist/hooks/hook-log.d.ts +7 -0
  122. package/dist/hooks/hook-log.d.ts.map +1 -0
  123. package/dist/hooks/hook-log.js +34 -0
  124. package/dist/hooks/hook-log.js.map +1 -0
  125. package/dist/hooks/identity.d.ts +21 -0
  126. package/dist/hooks/identity.d.ts.map +1 -0
  127. package/dist/hooks/identity.js +121 -0
  128. package/dist/hooks/identity.js.map +1 -0
  129. package/dist/hooks/log-turn.d.ts +23 -0
  130. package/dist/hooks/log-turn.d.ts.map +1 -0
  131. package/dist/hooks/log-turn.js +48 -0
  132. package/dist/hooks/log-turn.js.map +1 -0
  133. package/dist/hooks/send-turn.d.ts +32 -0
  134. package/dist/hooks/send-turn.d.ts.map +1 -0
  135. package/dist/hooks/send-turn.js +305 -0
  136. package/dist/hooks/send-turn.js.map +1 -0
  137. package/dist/hooks/silence.d.ts +7 -0
  138. package/dist/hooks/silence.d.ts.map +1 -0
  139. package/dist/hooks/silence.js +22 -0
  140. package/dist/hooks/silence.js.map +1 -0
  141. package/dist/hooks/stdin.d.ts +11 -0
  142. package/dist/hooks/stdin.d.ts.map +1 -0
  143. package/dist/hooks/stdin.js +51 -0
  144. package/dist/hooks/stdin.js.map +1 -0
  145. package/dist/hooks/turn-state.d.ts +40 -0
  146. package/dist/hooks/turn-state.d.ts.map +1 -0
  147. package/dist/hooks/turn-state.js +97 -0
  148. package/dist/hooks/turn-state.js.map +1 -0
  149. package/dist/hooks/types.d.ts +74 -0
  150. package/dist/hooks/types.d.ts.map +1 -0
  151. package/dist/hooks/types.js +3 -0
  152. package/dist/hooks/types.js.map +1 -0
  153. package/dist/logger.d.ts.map +1 -1
  154. package/dist/logger.js +12 -1
  155. package/dist/logger.js.map +1 -1
  156. package/dist/pending-store.d.ts +22 -2
  157. package/dist/pending-store.d.ts.map +1 -1
  158. package/dist/pending-store.js +25 -3
  159. package/dist/pending-store.js.map +1 -1
  160. package/dist/pending-upload.d.ts +12 -0
  161. package/dist/pending-upload.d.ts.map +1 -0
  162. package/dist/pending-upload.js +51 -0
  163. package/dist/pending-upload.js.map +1 -0
  164. package/dist/sessions/blocks.d.ts +51 -0
  165. package/dist/sessions/blocks.d.ts.map +1 -0
  166. package/dist/sessions/blocks.js +193 -0
  167. package/dist/sessions/blocks.js.map +1 -0
  168. package/dist/sessions/claude-scanner.d.ts +60 -1
  169. package/dist/sessions/claude-scanner.d.ts.map +1 -1
  170. package/dist/sessions/claude-scanner.js +277 -1
  171. package/dist/sessions/claude-scanner.js.map +1 -1
  172. package/dist/sessions/copilot-scanner.d.ts +27 -0
  173. package/dist/sessions/copilot-scanner.d.ts.map +1 -0
  174. package/dist/sessions/copilot-scanner.js +171 -0
  175. package/dist/sessions/copilot-scanner.js.map +1 -0
  176. package/dist/sessions/redact-secrets.d.ts.map +1 -1
  177. package/dist/sessions/redact-secrets.js +49 -10
  178. package/dist/sessions/redact-secrets.js.map +1 -1
  179. package/dist/sessions/turn-envelope.d.ts +62 -0
  180. package/dist/sessions/turn-envelope.d.ts.map +1 -0
  181. package/dist/sessions/turn-envelope.js +182 -0
  182. package/dist/sessions/turn-envelope.js.map +1 -0
  183. package/dist/sessions/usage.d.ts +23 -0
  184. package/dist/sessions/usage.d.ts.map +1 -0
  185. package/dist/sessions/usage.js +56 -0
  186. package/dist/sessions/usage.js.map +1 -0
  187. package/dist/skills/skill-scanner.d.ts.map +1 -1
  188. package/dist/skills/skill-scanner.js +3 -1
  189. package/dist/skills/skill-scanner.js.map +1 -1
  190. package/dist/types.d.ts +107 -0
  191. package/dist/types.d.ts.map +1 -1
  192. package/dist/types.js.map +1 -1
  193. package/dist/version.d.ts +2 -2
  194. package/dist/version.js +1 -1
  195. package/package.json +7 -4
package/README.md CHANGED
@@ -77,20 +77,26 @@ coolhand close-optimization opt-123 "Added the suggested index; verified query l
77
77
  | `coolhand logout` | Remove a stored client |
78
78
  | `coolhand status` | Check whether a token is configured |
79
79
  | `coolhand whoami` | Show the currently configured client |
80
+ | `coolhand update` | Upgrade to the newest stable release that is at least 48 hours old |
80
81
  | `coolhand clients` | List or switch the default client |
81
82
  | `coolhand claude` | Run Claude CLI through the Coolhand proxy |
82
83
  | `coolhand monitor` | Run an arbitrary CLI through the Coolhand proxy |
83
84
  | `coolhand list-workloads` | List workloads with optional search and pagination |
84
85
  | `coolhand get-workload` | Fetch a single workload by ID |
85
86
  | `coolhand update-workload` | Update a workload's name and/or description |
87
+ | `coolhand search-workloads` | List and search workloads, optionally with cost and performance metrics |
86
88
  | `coolhand search-templates` | List and search LLM request templates |
87
89
  | `coolhand get-template` | Fetch a single template by ID, with its prompt patterns |
90
+ | `coolhand search-help-articles` | Search or list Coolhand help center articles (no login needed) |
91
+ | `coolhand get-help-article` | Read one help center article by slug, with its markdown body |
92
+ | `coolhand list-help-categories` | List help center sections and their allowed tags |
88
93
  | `coolhand search-optimizations` | List and filter optimization records |
89
94
  | `coolhand get-optimization` | Fetch a single optimization by ID |
90
95
  | `coolhand update-optimization` | Update an optimization's fields |
91
96
  | `coolhand close-optimization` | Close an optimization with a reason |
92
97
  | `coolhand search-feedback` | Search and filter feedback records |
93
98
  | `coolhand get-feedback` | Fetch a single feedback record by ID |
99
+ | `coolhand link-feedback` | Link feedback records to an optimization in bulk |
94
100
  | `coolhand fetch-log` | Fetch the input/output content of a single LLM request log |
95
101
  | `coolhand search-logs` | Search LLM request logs with flexible filters |
96
102
  | `coolhand search-referenced-files` | List a client's referenced files, aggregated and ranked by reference count |
@@ -98,8 +104,12 @@ coolhand close-optimization opt-123 "Added the suggested index; verified query l
98
104
  | `coolhand analyze-claude-sessions` | Submit Claude sessions for pattern and cost analysis |
99
105
  | `coolhand map-claude-projects` | Upload a file-tree map (names + metadata only) of every folder named "claude" |
100
106
  | `coolhand upload-client-file` | Upload a local file to Coolhand as a client file |
107
+ | `coolhand list-client-files` | List the client's uploaded files, with status and type filters |
108
+ | `coolhand download-client-file` | Download a client file's contents to disk |
109
+ | `coolhand update-client-file` | Change a client file's status to draft, published, or archived |
101
110
  | `coolhand sync-skills` | Upload locally-built Claude skills (SKILL.md files) to Coolhand as client files |
102
111
  | `coolhand wildcard` | Record an agent blocker and exit cleanly |
112
+ | `coolhand capture-turn` | Agent hook: send each finished user and assistant turn to Coolhand with a public API key (see [docs/hook-capture.md](./docs/hook-capture.md)) |
103
113
 
104
114
  See [docs/commands.md](./docs/commands.md) for full flag reference and usage notes.
105
115
 
@@ -142,7 +152,7 @@ coolhand login --write-env .env
142
152
  # sets COOLHAND_API_KEY=<token> in .env, idempotent on re-run
143
153
  ```
144
154
 
145
- The CLI works especially well with the [Coolhand feedback collection skill](https://github.com/Coolhand-Labs/feedback-collection-skill) for Claude Code. The skill scans your project for LLM inference calls and implements best-practice human feedback collection — it reads `COOLHAND_API_KEY` from the environment, which `coolhand login --write-env .env` puts in place.
155
+ The CLI works especially well with the [Coolhand feedback collection skill](https://github.com/Coolhand-Labs/skills) for Claude Code. The skill scans your project for LLM inference calls and implements best-practice human feedback collection — it reads `COOLHAND_API_KEY` from the environment, which `coolhand login --write-env .env` puts in place.
146
156
 
147
157
  ## Configuration file
148
158
 
@@ -171,7 +181,9 @@ Located at `$HOME/.coolhand/config.json` (override with `COOLHAND_CONFIG_DIR` fo
171
181
  - [Auth Flow](./docs/auth-flow.md) — browser-callback sequence, state machine, timeout and error paths
172
182
  - [Configuration File](./docs/config-file.md) — full config schema, multi-client model, `COOLHAND_CONFIG_DIR` override
173
183
  - [Session Capture](./docs/session-capture.md) — session scanning, envelope format, deduplication, scope and limitations
184
+ - [Auto-update](./docs/auto-update.md) — background upgrades with a 48-hour bake period, opt-out, and install-method rules
174
185
  - [Skill Capture](./docs/skill-capture.md) — skill discovery, dedup, and incremental upload logic for `sync-skills`
186
+ - [Hook Capture](./docs/hook-capture.md) — `capture-turn` hook wiring for skills, recorded fields, spool and reliability
175
187
 
176
188
  ## About Coolhand Labs
177
189
 
@@ -0,0 +1,19 @@
1
+ import { Coolhand } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ /**
4
+ * Resolves the CLI's stored client and returns a `Coolhand` instance authenticated with its
5
+ * stored *private* key. `listClientFiles`/`downloadClientFile`/`updateClientFileStatus` need more
6
+ * than a private key: it must be the per-user key of a client admin of the client, which is what
7
+ * `coolhand login --scope private` stores. The client-level key, the public key and OAuth tokens
8
+ * are refused.
9
+ */
10
+ export declare function getClientFileClient(opts?: {
11
+ clientId?: string;
12
+ }): Promise<Coolhand>;
13
+ /**
14
+ * Maps an error thrown by the client-file SDK methods to a `CliError`. A 401 means the stored key
15
+ * was missing or rejected; a 403 means it authenticated but is not a client admin's per-user key;
16
+ * a 404 uses the caller-supplied message (an unknown id and another client's id look the same).
17
+ */
18
+ export declare function mapClientFileHttpError(err: unknown, notFoundMessage: string): CliError;
19
+ //# sourceMappingURL=client-file-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-file-client.d.ts","sourceRoot":"","sources":["../../src/api/client-file-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoB7F;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,QAAQ,CAsBtF"}
@@ -0,0 +1,47 @@
1
+ import { Coolhand, HttpError } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ import { loadConfig, resolveClient } from '../config.js';
4
+ /**
5
+ * Resolves the CLI's stored client and returns a `Coolhand` instance authenticated with its
6
+ * stored *private* key. `listClientFiles`/`downloadClientFile`/`updateClientFileStatus` need more
7
+ * than a private key: it must be the per-user key of a client admin of the client, which is what
8
+ * `coolhand login --scope private` stores. The client-level key, the public key and OAuth tokens
9
+ * are refused.
10
+ */
11
+ export async function getClientFileClient(opts = {}) {
12
+ const cfg = await loadConfig();
13
+ const client = await resolveClient(cfg, opts.clientId);
14
+ if (!client.private_key) {
15
+ throw new CliError('NO_PRIVATE_KEY', "No private key configured. Run 'coolhand login --scope private' first.");
16
+ }
17
+ try {
18
+ // Coolhand validates baseUrl in its constructor (https required; http only for localhost).
19
+ return new Coolhand({ apiKey: client.private_key, baseUrl: client.base_url, silent: true });
20
+ }
21
+ catch (err) {
22
+ throw new CliError('INVALID_BASE_URL', `Invalid base_url for client: ${client.base_url} (${err.message})`);
23
+ }
24
+ }
25
+ /**
26
+ * Maps an error thrown by the client-file SDK methods to a `CliError`. A 401 means the stored key
27
+ * was missing or rejected; a 403 means it authenticated but is not a client admin's per-user key;
28
+ * a 404 uses the caller-supplied message (an unknown id and another client's id look the same).
29
+ */
30
+ export function mapClientFileHttpError(err, notFoundMessage) {
31
+ if (err instanceof HttpError) {
32
+ if (err.status === 401) {
33
+ return new CliError('CLIENT_FILE_ERROR', "The stored private key was rejected. Run 'coolhand login --scope private' to re-authenticate.");
34
+ }
35
+ if (err.status === 403) {
36
+ return new CliError('CLIENT_FILE_ERROR', "Client files can only be managed with a client admin's per-user private key, and the stored key " +
37
+ "was refused. Run 'coolhand login --scope private' as a client admin of this client.");
38
+ }
39
+ if (err.status === 404) {
40
+ return new CliError('CLIENT_FILE_ERROR', notFoundMessage);
41
+ }
42
+ // coolhand-node already formats this as `Client file request failed (<status>): <body>`.
43
+ return new CliError('CLIENT_FILE_ERROR', err.message);
44
+ }
45
+ return new CliError('CLIENT_FILE_ERROR', `Client file request failed: ${err.message}`);
46
+ }
47
+ //# sourceMappingURL=client-file-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-file-client.js","sourceRoot":"","sources":["../../src/api/client-file-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAA8B,EAAE;IACxE,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,MAAM,IAAI,QAAQ,CAChB,gBAAgB,EAChB,wEAAwE,CACzE,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,2FAA2F;QAC3F,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,QAAQ,CAChB,kBAAkB,EAClB,gCAAgC,MAAM,CAAC,QAAQ,KAAM,GAAa,CAAC,OAAO,GAAG,CAC9E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAY,EAAE,eAAuB;IAC1E,IAAI,GAAG,YAAY,SAAS,EAAE,CAAC;QAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,IAAI,QAAQ,CACjB,mBAAmB,EACnB,+FAA+F,CAChG,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,IAAI,QAAQ,CACjB,mBAAmB,EACnB,kGAAkG;gBAChG,qFAAqF,CACxF,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;QAC5D,CAAC;QACD,yFAAyF;QACzF,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,QAAQ,CAAC,mBAAmB,EAAE,+BAAgC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;AACpG,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { HelpCenterDocsService } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ export interface HelpCenterClient {
4
+ service: HelpCenterDocsService;
5
+ /** True when a stored client's key is sent; false when the call has no stored key (node may still
6
+ * add `COOLHAND_API_KEY` from the environment, except for a `--base-url` the key was not issued for). */
7
+ usesStoredKey: boolean;
8
+ }
9
+ /**
10
+ * Builds the help center reader. Reads are public, so no stored client is not an error: the
11
+ * service is constructed without a key and the call is anonymous. When a client is selected its key
12
+ * is sent (it lifts the anonymous rate limit), unless `--base-url` points at a different server —
13
+ * a stored key must never be sent to a host the user did not log in to, so in that case the call is
14
+ * anonymous: the key is withheld and `COOLHAND_API_KEY` is not consulted either.
15
+ */
16
+ export declare function getHelpCenterClient(opts?: {
17
+ clientId?: string;
18
+ baseUrl?: string;
19
+ }): Promise<HelpCenterClient>;
20
+ /**
21
+ * Maps an error thrown by a `HelpCenterDocsService` call to a `CliError`. A `401` means the key was
22
+ * rejected and is reported, never retried anonymously. A `429` is the anonymous rate limit, so it
23
+ * is retryable.
24
+ */
25
+ export declare function mapHelpCenterHttpError(err: unknown, client: HelpCenterClient, notFoundMessage: string): CliError;
26
+ //# sourceMappingURL=help-center-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-center-client.d.ts","sourceRoot":"","sources":["../../src/api/help-center-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAKxC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,qBAAqB,CAAC;IAC/B;8GAC0G;IAC1G,aAAa,EAAE,OAAO,CAAC;CACxB;AAgCD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,gBAAgB,CAAC,CA2B3B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,gBAAgB,EACxB,eAAe,EAAE,MAAM,GACtB,QAAQ,CAqBV"}
@@ -0,0 +1,90 @@
1
+ import { HttpError, HelpCenterDocsService } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ import { findClient, loadConfig } from '../config.js';
4
+ import { logger, stripAnsiEscapes } from '../logger.js';
5
+ import { DEFAULT_BASE_URL } from '../types.js';
6
+ function sameServer(a, b) {
7
+ return a.replace(/\/+$/, '') === b.replace(/\/+$/, '');
8
+ }
9
+ /**
10
+ * Picks the stored client whose key to send, without ever prompting or failing for lack of one:
11
+ * `--client-id` (unknown id is an error, the user named it), then `COOLHAND_CLIENT_ID` and the
12
+ * configured default (a stale value is ignored, the read is public), then the sole stored client.
13
+ * Several clients with no usable default means anonymous rather than the interactive picker that
14
+ * `resolveClient` would open.
15
+ */
16
+ function selectStoredClient(cfg, clientId) {
17
+ if (clientId !== undefined) {
18
+ const entry = findClient(cfg, clientId);
19
+ if (!entry) {
20
+ throw new CliError('CLIENT_NOT_FOUND', `No client "${clientId}" is configured.`);
21
+ }
22
+ return entry;
23
+ }
24
+ const preferred = [process.env.COOLHAND_CLIENT_ID, cfg.default_client_id];
25
+ for (const id of preferred) {
26
+ const entry = id ? findClient(cfg, id) : undefined;
27
+ if (entry) {
28
+ return entry;
29
+ }
30
+ }
31
+ const clients = Object.values(cfg.clients);
32
+ return clients.length === 1 ? clients[0] : undefined;
33
+ }
34
+ /**
35
+ * Builds the help center reader. Reads are public, so no stored client is not an error: the
36
+ * service is constructed without a key and the call is anonymous. When a client is selected its key
37
+ * is sent (it lifts the anonymous rate limit), unless `--base-url` points at a different server —
38
+ * a stored key must never be sent to a host the user did not log in to, so in that case the call is
39
+ * anonymous: the key is withheld and `COOLHAND_API_KEY` is not consulted either.
40
+ */
41
+ export async function getHelpCenterClient(opts = {}) {
42
+ if (opts.clientId === '') {
43
+ throw new CliError('INVALID_ARGS', 'clientId must not be empty');
44
+ }
45
+ const cfg = await loadConfig();
46
+ const client = selectStoredClient(cfg, opts.clientId);
47
+ const baseUrl = opts.baseUrl ?? client?.base_url ?? DEFAULT_BASE_URL;
48
+ const storedKey = client ? (client.api_key ?? client.private_key) : undefined;
49
+ const keyAllowed = client !== undefined && sameServer(baseUrl, client.base_url);
50
+ if (client && storedKey && !keyAllowed) {
51
+ logger.warn(`Reading ${baseUrl} anonymously: client "${stripAnsiEscapes(client.client_name)}" is stored for ${client.base_url}, so its key is not sent.`);
52
+ }
53
+ const key = keyAllowed ? storedKey : undefined;
54
+ if (client && key) {
55
+ process.stderr.write(`Client: ${stripAnsiEscapes(client.client_name)} (${client.client_id})\n`);
56
+ }
57
+ try {
58
+ // '' (not undefined) tells node not to fall back to COOLHAND_API_KEY for a host no key was issued for.
59
+ const service = new HelpCenterDocsService({ apiKey: opts.baseUrl !== undefined && !keyAllowed ? '' : key, baseUrl, silent: true });
60
+ return { service, usesStoredKey: key !== undefined };
61
+ }
62
+ catch (err) {
63
+ throw new CliError('INVALID_BASE_URL', `Invalid base URL: ${baseUrl} (${err.message})`);
64
+ }
65
+ }
66
+ /**
67
+ * Maps an error thrown by a `HelpCenterDocsService` call to a `CliError`. A `401` means the key was
68
+ * rejected and is reported, never retried anonymously. A `429` is the anonymous rate limit, so it
69
+ * is retryable.
70
+ */
71
+ export function mapHelpCenterHttpError(err, client, notFoundMessage) {
72
+ if (err instanceof HttpError) {
73
+ if (err.status === 401) {
74
+ const hint = client.usesStoredKey
75
+ ? "The stored API key was rejected. Run 'coolhand login' to re-authenticate."
76
+ : 'The API key was rejected. Check COOLHAND_API_KEY, or unset it to read anonymously.';
77
+ return new CliError('HELP_CENTER_ERROR', hint);
78
+ }
79
+ if (err.status === 404) {
80
+ return new CliError('HELP_CENTER_ERROR', notFoundMessage);
81
+ }
82
+ if (err.status === 429) {
83
+ return new CliError('HELP_CENTER_ERROR', "Rate limit reached (anonymous callers get 30 requests per minute). Wait a minute and retry, or run 'coolhand login' to lift the limit.");
84
+ }
85
+ // coolhand-node already formats this as `Help center request failed (<status>): <body>`.
86
+ return new CliError('HELP_CENTER_ERROR', err.message);
87
+ }
88
+ return new CliError('HELP_CENTER_ERROR', `Help center request failed: ${err.message}`);
89
+ }
90
+ //# sourceMappingURL=help-center-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-center-client.js","sourceRoot":"","sources":["../../src/api/help-center-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"last-sync.d.ts","sourceRoot":"","sources":["../../src/api/last-sync.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,aAAa,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAqE1F"}
1
+ {"version":3,"file":"last-sync.d.ts","sourceRoot":"","sources":["../../src/api/last-sync.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,aAAa,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAsE1F"}
@@ -57,10 +57,11 @@ export async function fetchLastSync(opts = {}) {
57
57
  headers: { Accept: 'application/json', 'X-API-Key': apiKey },
58
58
  // Never follow redirects: fetch would forward X-API-Key to the redirect target.
59
59
  redirect: 'error',
60
+ signal: AbortSignal.timeout(10000),
60
61
  });
61
62
  }
62
63
  catch {
63
- // Network failure — degrade to local state.
64
+ // Network failure or timeout — degrade to local state.
64
65
  return null;
65
66
  }
66
67
  if (!res.ok) {
@@ -1 +1 @@
1
- {"version":3,"file":"last-sync.js","sourceRoot":"","sources":["../../src/api/last-sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"last-sync.js","sourceRoot":"","sources":["../../src/api/last-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type Coolhand } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ /**
4
+ * `searchWorkloads` needs the same private-key `Coolhand` instance as the template endpoints, so
5
+ * this delegates rather than duplicating the key/base-URL handling.
6
+ */
7
+ export declare function getWorkloadClient(opts?: {
8
+ clientId?: string;
9
+ }): Promise<Coolhand>;
10
+ /**
11
+ * Maps an error thrown by `Coolhand#searchWorkloads` to a `CliError`. A `422` (bad `--since`/
12
+ * `--until`/`--days-back` with `--include-metrics`) falls through to `err.message`, which
13
+ * coolhand-node already formats with the server's `errors` body.
14
+ */
15
+ export declare function mapWorkloadHttpError(err: unknown): CliError;
16
+ //# sourceMappingURL=workload-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload-client.d.ts","sourceRoot":"","sources":["../../src/api/workload-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAErF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAiB3D"}
@@ -0,0 +1,28 @@
1
+ import { HttpError } from 'coolhand-node';
2
+ import { CliError } from '../errors.js';
3
+ import { getTemplateClient } from './template-client.js';
4
+ /**
5
+ * `searchWorkloads` needs the same private-key `Coolhand` instance as the template endpoints, so
6
+ * this delegates rather than duplicating the key/base-URL handling.
7
+ */
8
+ export function getWorkloadClient(opts = {}) {
9
+ return getTemplateClient(opts);
10
+ }
11
+ /**
12
+ * Maps an error thrown by `Coolhand#searchWorkloads` to a `CliError`. A `422` (bad `--since`/
13
+ * `--until`/`--days-back` with `--include-metrics`) falls through to `err.message`, which
14
+ * coolhand-node already formats with the server's `errors` body.
15
+ */
16
+ export function mapWorkloadHttpError(err) {
17
+ if (err instanceof HttpError) {
18
+ if (err.status === 401) {
19
+ return new CliError('WORKLOAD_ERROR', "A private API key is required, and the stored one was rejected. Run 'coolhand login --scope private' to re-authenticate.");
20
+ }
21
+ if (err.status === 504) {
22
+ return new CliError('WORKLOAD_ERROR', 'The server timed out computing this request. It is retryable — narrow it with --search or a smaller --per-page, then retry.');
23
+ }
24
+ return new CliError('WORKLOAD_ERROR', err.message);
25
+ }
26
+ return new CliError('WORKLOAD_ERROR', `Workload request failed: ${err.message}`);
27
+ }
28
+ //# sourceMappingURL=workload-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workload-client.js","sourceRoot":"","sources":["../../src/api/workload-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiB,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA8B,EAAE;IAChE,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY;IAC/C,IAAI,GAAG,YAAY,SAAS,EAAE,CAAC;QAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,IAAI,QAAQ,CACjB,gBAAgB,EAChB,0HAA0H,CAC3H,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,OAAO,IAAI,QAAQ,CACjB,gBAAgB,EAChB,6HAA6H,CAC9H,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,QAAQ,CAAC,gBAAgB,EAAE,4BAA6B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9F,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../../src/auth/callback-server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAyJzG"}
1
+ {"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../../src/auth/callback-server.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAoKzG"}
@@ -21,7 +21,16 @@ export async function startCallbackServer(opts) {
21
21
  });
22
22
  }
23
23
  function handleRequest(req, res) {
24
- const url = new URL(req.url ?? '/', `http://${LOOPBACK}`);
24
+ let url;
25
+ try {
26
+ url = new URL(req.url ?? '/', `http://${LOOPBACK}`);
27
+ }
28
+ catch {
29
+ // A malformed request target (`GET //[`) must not throw out of the handler and kill the login.
30
+ res.statusCode = 400;
31
+ res.end();
32
+ return;
33
+ }
25
34
  if (req.method !== 'GET') {
26
35
  res.statusCode = 405;
27
36
  res.setHeader('Allow', 'GET');
@@ -65,6 +74,9 @@ export async function startCallbackServer(opts) {
65
74
  consumed = true;
66
75
  res.statusCode = 200;
67
76
  res.setHeader('Content-Type', 'text/html; charset=utf-8');
77
+ // The callback URL carries the tokens: keep it out of Referer headers and caches.
78
+ res.setHeader('Referrer-Policy', 'no-referrer');
79
+ res.setHeader('Cache-Control', 'no-store');
68
80
  res.end(SUCCESS_HTML);
69
81
  resolveResult({ token: token ?? undefined, clientName, clientId, private_token: privateToken });
70
82
  closeServerSoon();
@@ -1 +1 @@
1
- {"version":3,"file":"callback-server.js","sourceRoot":"","sources":["../../src/auth/callback-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"callback-server.js","sourceRoot":"","sources":["../../src/auth/callback-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA2C,MAAM,MAAM,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,QAAQ,GAAG,WAAW,CAAC;AAc7B,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAgC;IACxE,IAAI,aAA+C,CAAC;IACpD,IAAI,YAAmC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC7D,aAAa,GAAG,OAAO,CAAC;QACxB,YAAY,GAAG,MAAM,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAiC,CAAC;IAEtC,MAAM,MAAM,GAAW,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;QAChF,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,eAAe;QACtB,YAAY,CAAC,GAAG,EAAE;YAChB,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,aAAa,CAAC,GAAoB,EAAE,GAAmB;QAC9D,IAAI,GAAQ,CAAC;QACb,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,QAAQ,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,+FAA+F;YAC/F,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YACzB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9B,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YACjC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,mEAAmE,CAAC,CAAC,CAAC;YACxF,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,SAAS,CAAC;QAExE,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YACpD,QAAQ,GAAG,IAAI,CAAC;YAChB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,kEAAkE,CAAC,CAAC,CAAC;YACvF,YAAY,CAAC,IAAI,QAAQ,CAAC,gBAAgB,EAAE,kDAAkD,CAAC,CAAC,CAAC;YACjG,eAAe,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,QAAQ,GAAG,IAAI,CAAC;YAChB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;YAC1D,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,2CAA2C,CAAC,CAAC,CAAC;YAChE,YAAY,CACV,IAAI,QAAQ,CACV,kBAAkB,EAClB,0GAA0G,CAC3G,CACF,CAAC;YACF,eAAe,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QAED,QAAQ,GAAG,IAAI,CAAC;QAChB,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;QACrB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;QAC1D,kFAAkF;QAClF,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;QAChD,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC3C,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACtB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC;QAChG,eAAe,EAAE,CAAC;IACpB,CAAC;IAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE;YAC9B,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvC,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAwB,CAAC;IACvD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,0CAA0C,CAAC,CAAC;IACzF,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1B,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,IAAI,CAAC;YAChB,YAAY,CAAC,IAAI,QAAQ,CAAC,SAAS,EAAE,+BAA+B,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC;YAC1F,eAAe,EAAE,CAAC;QACpB,CAAC;IACH,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACnB,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAEhB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAC;gBAChB,YAAY,CAAC,IAAI,QAAQ,CAAC,SAAS,EAAE,6CAA6C,CAAC,CAAC,CAAC;gBACrF,eAAe,EAAE,CAAC;YACpB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAC1B,OAAO,EACP,GAAG,EAAE;gBACH,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,QAAQ,GAAG,IAAI,CAAC;oBAChB,YAAY,CAAC,IAAI,QAAQ,CAAC,SAAS,EAAE,6CAA6C,CAAC,CAAC,CAAC;oBACrF,eAAe,EAAE,CAAC;gBACpB,CAAC;YACH,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,KAAK,GAAG,SAAS,CAAC;QACpB,CAAC;IACH,CAAC,CAAC;IACF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAE/C,KAAK,UAAU,KAAK;QAClB,OAAO,EAAE,CAAC;QACV,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,IAAI,CAAC;YAChB,YAAY,CAAC,IAAI,QAAQ,CAAC,SAAS,EAAE,oDAAoD,CAAC,CAAC,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { spawn, type StdioOptions } from 'child_process';
2
+ import { type Packument } from './select.js';
3
+ /**
4
+ * True when `scriptPath` looks like a global `npm install -g` of this package:
5
+ * `<prefix>/lib/node_modules/<pkg>/…` (macOS/Linux, nvm, Homebrew) or `<prefix>/node_modules/<pkg>/…`
6
+ * under an `npm` directory (Windows). A project-local install (`<project>/node_modules`), `npx` cache,
7
+ * `npm link` checkout, or another package manager's global dir does not match, so we never touch it.
8
+ */
9
+ export declare function isGlobalNpmInstall(scriptPath: string): boolean;
10
+ export declare function canSelfInstall(): boolean;
11
+ export declare function fetchPackument(fetchFn?: typeof fetch): Promise<Packument>;
12
+ /** Newest version that has cleared the bake period and is newer than the running one, or null. */
13
+ export declare function findEligibleUpdate(now?: number, fetchFn?: typeof fetch): Promise<string | null>;
14
+ export interface InstallDeps {
15
+ spawnFn?: typeof spawn;
16
+ /** Whether the user's npm config already sets its own release-age/`before` bake. */
17
+ userHasBake?: () => Promise<boolean>;
18
+ }
19
+ /**
20
+ * `npm install -g <pkg>@<exact version>`; resolves true on a zero exit. Pinned so the bake check is what
21
+ * gets installed, and `--before` holds every transitive dependency to the same 48-hour bake. If the user's
22
+ * npm config already sets `min-release-age` or `before`, ours is left off: npm rejects combining them, and
23
+ * their own bake then covers the dependencies.
24
+ */
25
+ export declare function installVersion(version: string, stdio?: StdioOptions, deps?: InstallDeps): Promise<boolean>;
26
+ export declare function manualInstallHint(version: string): string;
27
+ /** How to update by hand; softened when this copy isn't a global npm install, where that command would add a second copy. */
28
+ export declare function updateHint(version: string): string;
29
+ /** Version in the package.json of the install the running script belongs to, or undefined if it can't be read. */
30
+ export declare function installedVersionOnDisk(): string | undefined;
31
+ export interface BackgroundDeps {
32
+ selfInstall?: boolean;
33
+ install?: (version: string) => Promise<boolean>;
34
+ versionOnDisk?: () => string | undefined;
35
+ fetchFn?: typeof fetch;
36
+ }
37
+ /**
38
+ * Hidden `__auto-update` command, run detached by `maybeAutoUpdate`. Checks the registry and, for a
39
+ * global npm install, installs the eligible version; otherwise records it so the next launch can
40
+ * mention it. Network and install failures are swallowed. A version whose install failed is not
41
+ * retried (a newer one is, and so is that version after a week), so a root-owned prefix doesn't re-run `npm install -g` every day.
42
+ */
43
+ export declare function run(deps?: BackgroundDeps): Promise<number>;
44
+ interface SpawnDeps {
45
+ spawnFn?: typeof spawn;
46
+ }
47
+ /**
48
+ * Called at the start of every command. Costs one small file read: it announces a finished or
49
+ * pending update (once, on stderr) and, at most daily, launches the detached background check.
50
+ * Quiet under `--json`, in CI, and when opted out (`COOLHAND_NO_AUTO_UPDATE=1` or `auto_update: false`
51
+ * in config.json). Best-effort — never throws.
52
+ */
53
+ export declare function maybeAutoUpdate(opts: {
54
+ command: string | undefined;
55
+ json: boolean;
56
+ }, deps?: SpawnDeps & {
57
+ now?: number;
58
+ ownScript?: boolean;
59
+ }): Promise<void>;
60
+ export {};
61
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auto-update/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAUzD,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAyBvG;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAW9D;AAcD,wBAAgB,cAAc,IAAI,OAAO,CAGxC;AAuCD,wBAAsB,cAAc,CAAC,OAAO,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAStF;AAED,kGAAkG;AAClG,wBAAsB,kBAAkB,CAAC,GAAG,SAAa,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEzG;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;IACvB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACtC;AAkCD;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,YAAuB,EAC9B,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,OAAO,CAAC,CA6BlB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,6HAA6H;AAC7H,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,kHAAkH;AAClH,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAgB3D;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAsB,GAAG,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAYpE;AA2CD,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AA0BD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,EACpD,IAAI,GAAE,SAAS,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3D,OAAO,CAAC,IAAI,CAAC,CA0Df"}