hive-intelligence 1.6.7 → 1.7.2

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 (57) hide show
  1. package/README.md +10 -4
  2. package/agent-skills/.claude-plugin/plugin.json +10 -0
  3. package/agent-skills/README.md +2 -0
  4. package/agent-skills/SKILL.md +18 -6
  5. package/agent-skills/evals/trigger-queries.json +70 -0
  6. package/agent-skills/package.json +3 -1
  7. package/agent-skills/packs/hive/SKILL.md +404 -0
  8. package/agent-skills/packs/hive/evals/evals.json +50 -0
  9. package/agent-skills/packs/hive/evals/triggers.json +39 -0
  10. package/agent-skills/packs/hive-build-onboarding/SKILL.md +1 -1
  11. package/agent-skills/packs/hive-cli/SKILL.md +2 -2
  12. package/agent-skills/packs/hive-mcp/SKILL.md +9 -5
  13. package/agent-skills/packs/hive-prediction-markets/SKILL.md +145 -0
  14. package/agent-skills/packs/hive-prediction-markets/evals/evals.json +29 -0
  15. package/agent-skills/packs/hive-prediction-markets/evals/triggers.json +14 -0
  16. package/agent-skills/packs/hive-query/SKILL.md +4 -2
  17. package/agent-skills/packs/hive-stateful-monitoring/SKILL.md +3 -3
  18. package/agent-skills/references/agents-routing.md +4 -1
  19. package/agent-skills/scripts/validate-agent-skills-package.mjs +2 -0
  20. package/agent-skills/skills.sh.json +9 -1
  21. package/build/{api-client-6AM3HVHQ.js → api-client-POBN6Y5S.js} +12 -3
  22. package/build/{auth-4LPSQJXD.js → auth-6XVL5CE3.js} +1 -1
  23. package/build/call-args-BUB6YNHW.js +27 -0
  24. package/build/{chunk-GADPH72D.js → chunk-4QDGA6GP.js} +52 -1
  25. package/build/{chunk-2SPCKQBJ.js → chunk-5QAXJON7.js} +71 -0
  26. package/build/chunk-APBLB62S.js +474 -0
  27. package/build/chunk-AZFOTKS2.js +394 -0
  28. package/build/{chunk-GYVF75XB.js → chunk-FQNW6SZ6.js} +1 -1
  29. package/build/{chunk-32NRUWXA.js → chunk-KQVPKTEO.js} +3 -3
  30. package/build/{chunk-LW2DHE32.js → chunk-L4KVJDA7.js} +1 -1
  31. package/build/{chunk-J2PXISXW.js → chunk-LP7PDQCO.js} +4289 -626
  32. package/build/{chunk-P7NLFSZQ.js → chunk-RNVZIPNY.js} +100 -9
  33. package/build/chunk-XN3T6YOG.js +32 -0
  34. package/build/{chunk-KUF754NT.js → chunk-YLHNUAFT.js} +52 -12
  35. package/build/{chunk-G23ZAW36.js → chunk-ZBMMJ6LE.js} +3 -2
  36. package/build/{chunk-LP5ECG7A.js → chunk-ZDXMZPC6.js} +26 -2
  37. package/build/{chunk-S4HBVZ7O.js → chunk-ZSPPJW4G.js} +44 -7
  38. package/build/cli.js +120 -48
  39. package/build/{completion-YVSWWF6D.js → completion-ROZAH667.js} +1 -1
  40. package/build/{doctor-AM6QST7Z.js → doctor-KPYW2U7D.js} +42 -5
  41. package/build/{errors-EL6UMXNJ.js → errors-YQAVCXXO.js} +9 -1
  42. package/build/feedback-G2DFCCI6.js +113 -0
  43. package/build/{init-all-54G3CVZA.js → init-all-JXLG7LOX.js} +5 -5
  44. package/build/{mcpServer-NWOKFR7Q.js → mcpServer-SUDGFNIF.js} +2 -2
  45. package/build/monitor-worker.js +62 -10
  46. package/build/{namespace-PA2IDNRT.js → namespace-XMFFW47T.js} +1 -1
  47. package/build/{output-XGTE4EWJ.js → output-BBHBJI32.js} +5 -1
  48. package/build/release.json +4 -4
  49. package/build/routing-4VKAVRYR.js +43 -0
  50. package/build/{serve-XRNMHIJX.js → serve-BYC3LRLN.js} +1 -1
  51. package/build/server.js +317 -41
  52. package/build/stdio.js +2 -2
  53. package/build/{tools-FNPMELSU.js → tools-NJQPIJ53.js} +81 -33
  54. package/build/{uninstall-P3JJZCXT.js → uninstall-4TJ4SZLU.js} +26 -7
  55. package/build/{upgrade-ATIFZANV.js → upgrade-3NR3LAGU.js} +2 -2
  56. package/build/{watch-FG2C5Y2Z.js → watch-BUSEPVDM.js} +5 -3
  57. package/package.json +1 -1
@@ -1,6 +1,30 @@
1
1
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
 
3
3
  // src/cli/namespace.ts
4
+ var ARCHIVE_HISTORY_ARGS = {
5
+ base_coin: {
6
+ flag: "--base-coin <ticker>",
7
+ description: "Base asset ticker (BTC, ETH, SOL)",
8
+ required: true
9
+ },
10
+ exchange: {
11
+ flag: "--exchange <name>",
12
+ description: "Venue filter (Binance, Hyperliquid); omit for all venues"
13
+ },
14
+ from: {
15
+ flag: "--from <iso>",
16
+ description: "Inclusive ISO 8601 lower time bound"
17
+ },
18
+ to: {
19
+ flag: "--to <iso>",
20
+ description: "Inclusive ISO 8601 upper time bound"
21
+ },
22
+ limit: {
23
+ flag: "--limit <n>",
24
+ description: "Max rows, newest first",
25
+ type: "number"
26
+ }
27
+ };
4
28
  var NAMESPACE = [
5
29
  {
6
30
  name: "market",
@@ -610,6 +634,53 @@ var NAMESPACE = [
610
634
  }
611
635
  }
612
636
  ]
637
+ },
638
+ {
639
+ name: "archive",
640
+ description: "Hive Archive: cross-venue derivatives history (funding, OI, basis, positioning, liquidations)",
641
+ commands: [
642
+ {
643
+ name: "coverage",
644
+ description: "Archive venues and per-dataset time coverage",
645
+ tool: "archive_get_coverage",
646
+ args: {
647
+ base_coin: {
648
+ flag: "--base-coin <ticker>",
649
+ description: "Probe coin for futures datasets (default BTC)"
650
+ }
651
+ }
652
+ },
653
+ {
654
+ name: "funding",
655
+ description: "Historical funding-rate settlements",
656
+ tool: "archive_get_funding_history",
657
+ args: { ...ARCHIVE_HISTORY_ARGS }
658
+ },
659
+ {
660
+ name: "oi",
661
+ description: "Historical open-interest snapshots",
662
+ tool: "archive_get_open_interest_history",
663
+ args: { ...ARCHIVE_HISTORY_ARGS }
664
+ },
665
+ {
666
+ name: "basis",
667
+ description: "Historical spot-vs-futures basis snapshots",
668
+ tool: "archive_get_basis_history",
669
+ args: { ...ARCHIVE_HISTORY_ARGS }
670
+ },
671
+ {
672
+ name: "long-short",
673
+ description: "Historical long/short-ratio snapshots",
674
+ tool: "archive_get_long_short_history",
675
+ args: { ...ARCHIVE_HISTORY_ARGS }
676
+ },
677
+ {
678
+ name: "liquidations",
679
+ description: "Historical liquidation events",
680
+ tool: "archive_get_liquidations_history",
681
+ args: { ...ARCHIVE_HISTORY_ARGS }
682
+ }
683
+ ]
613
684
  }
614
685
  ];
615
686
  function resolveCommand(domain, subcommand) {
@@ -0,0 +1,474 @@
1
+ import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
+ import {
3
+ CliError,
4
+ ExitCode
5
+ } from "./chunk-ZSPPJW4G.js";
6
+ import {
7
+ errorEnvelope,
8
+ info,
9
+ shouldOutputJson,
10
+ successEnvelope,
11
+ writeOutput,
12
+ yellow
13
+ } from "./chunk-ZDXMZPC6.js";
14
+ import {
15
+ ensureConfigDir,
16
+ getConfigDir,
17
+ readJsonFile,
18
+ writeJsonFile
19
+ } from "./chunk-6PC3HUAK.js";
20
+
21
+ // src/cli/routing.ts
22
+ import { createHash } from "crypto";
23
+ import {
24
+ existsSync,
25
+ mkdirSync,
26
+ readFileSync,
27
+ unlinkSync,
28
+ writeFileSync
29
+ } from "fs";
30
+ import { homedir } from "os";
31
+ import { dirname, join, resolve } from "path";
32
+
33
+ // src/cli/routing-block.ts
34
+ var ROUTING_BLOCK = [
35
+ "## Hive MCP Routing",
36
+ "",
37
+ "For live crypto intelligence, prefer Hive retrieval over model memory.",
38
+ "",
39
+ "- User asks about live crypto data, prices, wallets, tokens, DeFi, NFTs,",
40
+ " Solana, security, DEX pools, network state, or prediction markets:",
41
+ " use `hive` (it loads `hive-query` for the full toolset walk).",
42
+ "- Exact Hive endpoint, provider, schema, or argument shape is unknown:",
43
+ " use `hive-tool-discovery`.",
44
+ "- Clear domain request:",
45
+ " - prices, liquidity, exchanges, OHLC, order books: `hive-market-research`",
46
+ " - token metadata, holders, liquidity, enrichment, risk:",
47
+ " `hive-token-diligence`",
48
+ " - wallet balances, transfers, PnL, NFTs, DeFi positions:",
49
+ " `hive-wallet-investigation`",
50
+ " - token, approval, contract, dApp, phishing, simulation risk:",
51
+ " `hive-security-risk`",
52
+ " - DEX pools, pairs, trades, liquidity, OHLCV: `hive-dex-pool-analysis`",
53
+ " - protocol TVL, fees, yields, stablecoins, bridges:",
54
+ " `hive-defi-research`",
55
+ " - NFT ownership, metadata, floors, sales, rarity: `hive-nft-research`",
56
+ " - Solana wallets, SPL accounts, DAS assets, priority fees:",
57
+ " `hive-solana-analysis`",
58
+ " - blocks, gas, receipts, logs, RPC diagnostics:",
59
+ " `hive-network-infrastructure`",
60
+ " - Polymarket odds, events, order books, odds history, wallet positions:",
61
+ " `hive-prediction-markets`",
62
+ "- User asks Hive to remember, monitor, schedule, alert, or report crypto",
63
+ " intelligence across sessions: use `hive-stateful-monitoring`.",
64
+ "- Setup, API key, CLI, or app integration:",
65
+ " use `hive-mcp`, `hive-build-onboarding`, `hive-cli`, or `hive-build`.",
66
+ "",
67
+ "Default execution loop:",
68
+ "1. Read the compact `hive://toolsets` index or call `search_tools`.",
69
+ "2. Select one task toolset and its best matching compact `routes[]` entry.",
70
+ " Preserve `route_id`; follow the ordered calls, conditional per-call",
71
+ " fallbacks, four-call cap, and stop condition. Use `coverageCatalog` only",
72
+ " for long-tail discovery.",
73
+ "3. Call `get_api_endpoint_schema` and inspect `operation`/`callPattern`.",
74
+ "4. Execute reads through `invoke_api_endpoint` with bounded args. Explain any",
75
+ " Hive state change, obtain explicit approval, then use",
76
+ " `invoke_stateful_endpoint`; never auto-approve it.",
77
+ "5. Copy exact server-returned `_hive` blocks into the task receipt, cite exact",
78
+ " receipt IDs from `claims[]`, account for every canonical `coverage[]`",
79
+ " phase, include `route_id`, and call `validate_task_result` before presenting a structured",
80
+ " result.",
81
+ "6. Report provider, source recency, fallback/cache/degraded state, and runtime",
82
+ " status (`ok`, `invalid_input`, `missing_key`, `plan_required`,",
83
+ " `rate_limited`, `degraded`, or `failing`). `observed_at` is Hive",
84
+ " first-observation/original cache time, not necessarily upstream event time."
85
+ ].join("\n");
86
+
87
+ // src/cli/routing.ts
88
+ var ROUTING_START = "<!-- hive-routing:start -->";
89
+ var ROUTING_END = "<!-- hive-routing:end -->";
90
+ var ROUTING_FILES = ["AGENTS.md", "CLAUDE.md"];
91
+ function detectEol(content) {
92
+ return content.includes("\r\n") ? "\r\n" : "\n";
93
+ }
94
+ function renderRoutingBlock(eol = "\n") {
95
+ return [ROUTING_START, ...ROUTING_BLOCK.split("\n"), ROUTING_END].join(eol) + eol;
96
+ }
97
+ function findRoutingBlock(content) {
98
+ const start = content.indexOf(ROUTING_START);
99
+ if (start < 0) return null;
100
+ if (start > 0 && content[start - 1] !== "\n") return null;
101
+ const endMarker = content.indexOf(ROUTING_END, start + ROUTING_START.length);
102
+ if (endMarker < 0) return null;
103
+ let end = endMarker + ROUTING_END.length;
104
+ if (content.startsWith("\r\n", end)) end += 2;
105
+ else if (content.startsWith("\n", end)) end += 1;
106
+ const inner = content.slice(start + ROUTING_START.length, endMarker).replace(/\r\n/g, "\n");
107
+ const body = inner.replace(/^\n/, "").replace(/\n$/, "");
108
+ return { start, end, body };
109
+ }
110
+ function appendRoutingBlock(content) {
111
+ const eol = detectEol(content);
112
+ const block = renderRoutingBlock(eol);
113
+ if (content === "") return block;
114
+ return content + (content.endsWith("\n") ? eol : eol + eol) + block;
115
+ }
116
+ function stripRoutingBlock(content) {
117
+ const span = findRoutingBlock(content);
118
+ if (!span) return null;
119
+ let before = content.slice(0, span.start);
120
+ if (before.endsWith("\r\n\r\n")) before = before.slice(0, -2);
121
+ else if (before.endsWith("\n\n")) before = before.slice(0, -1);
122
+ return before + content.slice(span.end);
123
+ }
124
+ function diffLines(expected, actual) {
125
+ const a = expected.split("\n");
126
+ const b = actual.split("\n");
127
+ const out = [];
128
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
129
+ if (a[i] === b[i]) continue;
130
+ if (a[i] !== void 0) out.push(`- ${a[i]}`);
131
+ if (b[i] !== void 0) out.push(`+ ${b[i]}`);
132
+ }
133
+ return out;
134
+ }
135
+ function recordsPath() {
136
+ return join(getConfigDir(), "routing.json");
137
+ }
138
+ function readRoutingRecords() {
139
+ return readJsonFile(recordsPath()) ?? {};
140
+ }
141
+ function writeRoutingRecords(records) {
142
+ ensureConfigDir();
143
+ writeJsonFile(recordsPath(), records);
144
+ }
145
+ function projectHash(projectPath) {
146
+ return createHash("sha256").update(projectPath).digest("hex").slice(0, 16);
147
+ }
148
+ function backupPath(projectPath) {
149
+ return join(getConfigDir(), "routing", `${projectHash(projectPath)}.orig`);
150
+ }
151
+ function resolveProject(opts) {
152
+ return resolve(opts.cwd ?? process.cwd());
153
+ }
154
+ function outcome(action, project, file, status, message, exitCode, extra = {}) {
155
+ return { action, project, file, status, message, exitCode, ...extra };
156
+ }
157
+ function refuseHome(action, project) {
158
+ if (project !== resolve(homedir())) return null;
159
+ return outcome(
160
+ action,
161
+ project,
162
+ null,
163
+ "refused",
164
+ "Refusing to touch your home directory; run `hive routing` inside a project.",
165
+ ExitCode.INVALID_ARGS
166
+ );
167
+ }
168
+ function skippedByEnv(action, project) {
169
+ return outcome(
170
+ action,
171
+ project,
172
+ null,
173
+ "skipped",
174
+ `Routing ${action} skipped: HIVE_ROUTING=never is set, so the CLI never writes routing blocks on this machine.`,
175
+ ExitCode.SUCCESS
176
+ );
177
+ }
178
+ function isRoutingFile(name) {
179
+ return ROUTING_FILES.includes(name);
180
+ }
181
+ function pickFile(project, requested) {
182
+ if (requested !== void 0) {
183
+ if (!isRoutingFile(requested)) {
184
+ return {
185
+ error: `--file must be one of ${ROUTING_FILES.join(", ")} (got '${requested}')`
186
+ };
187
+ }
188
+ return { file: requested };
189
+ }
190
+ for (const candidate of ROUTING_FILES) {
191
+ if (existsSync(join(project, candidate))) return { file: candidate };
192
+ }
193
+ return { file: ROUTING_FILES[0] };
194
+ }
195
+ function installRouting(opts = {}) {
196
+ const project = resolveProject(opts);
197
+ if (process.env.HIVE_ROUTING === "never")
198
+ return skippedByEnv("install", project);
199
+ const home = refuseHome("install", project);
200
+ if (home) return home;
201
+ const pick = pickFile(project, opts.file);
202
+ if ("error" in pick) {
203
+ return outcome(
204
+ "install",
205
+ project,
206
+ null,
207
+ "refused",
208
+ pick.error,
209
+ ExitCode.INVALID_ARGS
210
+ );
211
+ }
212
+ const filePath = join(project, pick.file);
213
+ const exists = existsSync(filePath);
214
+ if (!exists && !opts.create) {
215
+ return outcome(
216
+ "install",
217
+ project,
218
+ pick.file,
219
+ "refused",
220
+ `${pick.file} not found in ${project}; pass --create to create it${opts.file ? "" : ", or --file CLAUDE.md to target that file"}.`,
221
+ ExitCode.INVALID_ARGS
222
+ );
223
+ }
224
+ const originalBytes = exists ? readFileSync(filePath) : Buffer.alloc(0);
225
+ const original = originalBytes.toString("utf-8");
226
+ const span = findRoutingBlock(original);
227
+ const records = readRoutingRecords();
228
+ if (span) {
229
+ if (span.body !== ROUTING_BLOCK) {
230
+ return outcome(
231
+ "install",
232
+ project,
233
+ pick.file,
234
+ "refused",
235
+ `${pick.file} already has a Hive routing block that was edited by hand; leaving it alone. Remove it manually to reinstall the stock block.`,
236
+ ExitCode.GENERAL_ERROR,
237
+ { diff: diffLines(ROUTING_BLOCK, span.body) }
238
+ );
239
+ }
240
+ if (!opts.dryRun && records[project]?.status !== "installed") {
241
+ records[project] = {
242
+ status: "installed",
243
+ file: pick.file,
244
+ at: (/* @__PURE__ */ new Date()).toISOString()
245
+ };
246
+ writeRoutingRecords(records);
247
+ }
248
+ return outcome(
249
+ "install",
250
+ project,
251
+ pick.file,
252
+ "already-installed",
253
+ `${pick.file} already contains the Hive routing block; nothing to do.`,
254
+ ExitCode.SUCCESS
255
+ );
256
+ }
257
+ const next = appendRoutingBlock(original);
258
+ if (opts.dryRun) {
259
+ return outcome(
260
+ "install",
261
+ project,
262
+ pick.file,
263
+ "dry-run",
264
+ `Would ${exists ? "append the Hive routing block to" : "create"} ${pick.file} (dry-run: nothing written).`,
265
+ ExitCode.SUCCESS,
266
+ { content: next }
267
+ );
268
+ }
269
+ const backup = backupPath(project);
270
+ mkdirSync(dirname(backup), { recursive: true, mode: 448 });
271
+ writeFileSync(backup, originalBytes);
272
+ writeFileSync(filePath, next, "utf-8");
273
+ records[project] = {
274
+ status: "installed",
275
+ file: pick.file,
276
+ at: (/* @__PURE__ */ new Date()).toISOString(),
277
+ ...exists ? {} : { created: true }
278
+ };
279
+ writeRoutingRecords(records);
280
+ return outcome(
281
+ "install",
282
+ project,
283
+ pick.file,
284
+ "installed",
285
+ `${exists ? "Appended" : "Created"} ${pick.file} with the Hive routing block. Undo with: hive routing remove`,
286
+ ExitCode.SUCCESS
287
+ );
288
+ }
289
+ function declineRouting(opts = {}) {
290
+ const project = resolveProject(opts);
291
+ if (process.env.HIVE_ROUTING === "never")
292
+ return skippedByEnv("decline", project);
293
+ const home = refuseHome("decline", project);
294
+ if (home) return home;
295
+ if (opts.dryRun) {
296
+ return outcome(
297
+ "decline",
298
+ project,
299
+ null,
300
+ "dry-run",
301
+ `Would record ${project} as declined (dry-run: nothing written).`,
302
+ ExitCode.SUCCESS
303
+ );
304
+ }
305
+ const records = readRoutingRecords();
306
+ records[project] = {
307
+ status: "declined",
308
+ file: null,
309
+ at: (/* @__PURE__ */ new Date()).toISOString()
310
+ };
311
+ writeRoutingRecords(records);
312
+ return outcome(
313
+ "decline",
314
+ project,
315
+ null,
316
+ "declined",
317
+ `Recorded: no Hive routing block for ${project}. Change your mind with: hive routing install`,
318
+ ExitCode.SUCCESS
319
+ );
320
+ }
321
+ function forgetProject(project, records) {
322
+ const backup = backupPath(project);
323
+ if (existsSync(backup)) unlinkSync(backup);
324
+ if (project in records) {
325
+ delete records[project];
326
+ writeRoutingRecords(records);
327
+ }
328
+ }
329
+ function removeRouting(opts = {}) {
330
+ const project = resolveProject(opts);
331
+ const home = refuseHome("remove", project);
332
+ if (home) return home;
333
+ const records = readRoutingRecords();
334
+ const record = records[project];
335
+ let file = opts.file ?? record?.file ?? void 0;
336
+ if (file !== void 0 && !isRoutingFile(file)) {
337
+ return outcome(
338
+ "remove",
339
+ project,
340
+ null,
341
+ "refused",
342
+ `--file must be one of ${ROUTING_FILES.join(", ")} (got '${file}')`,
343
+ ExitCode.INVALID_ARGS
344
+ );
345
+ }
346
+ if (file === void 0) {
347
+ file = ROUTING_FILES.find((candidate) => {
348
+ const path = join(project, candidate);
349
+ return existsSync(path) && findRoutingBlock(readFileSync(path, "utf-8")) !== null;
350
+ });
351
+ }
352
+ const filePath = file ? join(project, file) : null;
353
+ const current = filePath && existsSync(filePath) ? readFileSync(filePath, "utf-8") : null;
354
+ const span = current === null ? null : findRoutingBlock(current);
355
+ if (current === null || !span) {
356
+ if (!opts.dryRun) forgetProject(project, records);
357
+ return outcome(
358
+ "remove",
359
+ project,
360
+ file ?? null,
361
+ "not-installed",
362
+ `No Hive routing block found in ${project}; nothing to remove.`,
363
+ ExitCode.SUCCESS
364
+ );
365
+ }
366
+ if (span.body !== ROUTING_BLOCK) {
367
+ return outcome(
368
+ "remove",
369
+ project,
370
+ file,
371
+ "refused",
372
+ `The Hive routing block in ${file} was edited by hand; refusing to remove it. Delete it manually if you want it gone.`,
373
+ ExitCode.GENERAL_ERROR,
374
+ { diff: diffLines(ROUTING_BLOCK, span.body) }
375
+ );
376
+ }
377
+ const stripped = stripRoutingBlock(current);
378
+ const backup = backupPath(project);
379
+ let final = stripped;
380
+ let note = "";
381
+ if (existsSync(backup)) {
382
+ const originalBytes = readFileSync(backup);
383
+ const original = originalBytes.toString("utf-8");
384
+ if (stripped === original || stripped === original + detectEol(current)) {
385
+ final = originalBytes;
386
+ } else {
387
+ note = " The file changed since install, so only the block was removed and your other edits were kept.";
388
+ }
389
+ }
390
+ if (opts.dryRun) {
391
+ return outcome(
392
+ "remove",
393
+ project,
394
+ file,
395
+ "dry-run",
396
+ `Would remove the Hive routing block from ${file} (dry-run: nothing written).${note}`,
397
+ ExitCode.SUCCESS,
398
+ { content: final.toString() }
399
+ );
400
+ }
401
+ if (record?.created && final.length === 0) {
402
+ unlinkSync(filePath);
403
+ } else {
404
+ writeFileSync(filePath, final);
405
+ }
406
+ forgetProject(project, records);
407
+ return outcome(
408
+ "remove",
409
+ project,
410
+ file,
411
+ "removed",
412
+ `${record?.created && final.length === 0 ? `Deleted ${file}, which install had created` : `Removed the Hive routing block from ${file}`}.${note}`,
413
+ ExitCode.SUCCESS
414
+ );
415
+ }
416
+ function removeRecordedRoutingBlocks(opts = {}) {
417
+ const records = readRoutingRecords();
418
+ const outcomes = [];
419
+ for (const [project, record] of Object.entries(records)) {
420
+ if (record.status !== "installed") continue;
421
+ outcomes.push(
422
+ removeRouting({
423
+ cwd: project,
424
+ file: record.file ?? void 0,
425
+ dryRun: opts.dryRun
426
+ })
427
+ );
428
+ }
429
+ return outcomes;
430
+ }
431
+ async function runRouting(action, opts = {}) {
432
+ const result = action === "install" ? installRouting(opts) : action === "decline" ? declineRouting(opts) : removeRouting(opts);
433
+ const { exitCode, ...data } = result;
434
+ if (opts.json || shouldOutputJson()) {
435
+ if (exitCode === ExitCode.SUCCESS) {
436
+ await writeOutput(successEnvelope(data, {}));
437
+ } else {
438
+ const err = new CliError(
439
+ exitCode === ExitCode.INVALID_ARGS ? "INVALID_ARGS" : "GENERAL_ERROR",
440
+ result.message
441
+ );
442
+ await writeOutput({ ...errorEnvelope(err, {}), data });
443
+ }
444
+ return exitCode;
445
+ }
446
+ if (result.status === "dry-run" && result.content !== void 0) {
447
+ process.stdout.write(result.content);
448
+ }
449
+ info(result.message);
450
+ for (const line of result.diff ?? []) {
451
+ process.stderr.write(yellow(` ${line}`) + "\n");
452
+ }
453
+ return exitCode;
454
+ }
455
+
456
+ export {
457
+ ROUTING_START,
458
+ ROUTING_END,
459
+ ROUTING_FILES,
460
+ detectEol,
461
+ renderRoutingBlock,
462
+ findRoutingBlock,
463
+ appendRoutingBlock,
464
+ stripRoutingBlock,
465
+ diffLines,
466
+ readRoutingRecords,
467
+ projectHash,
468
+ backupPath,
469
+ installRouting,
470
+ declineRouting,
471
+ removeRouting,
472
+ removeRecordedRoutingBlocks,
473
+ runRouting
474
+ };