hive-intelligence 1.1.4 → 1.3.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 (130) hide show
  1. package/README.md +182 -73
  2. package/agent-skills/.claude-plugin/plugin.json +4 -4
  3. package/agent-skills/.mcp.json +1 -4
  4. package/agent-skills/README.md +16 -10
  5. package/agent-skills/SKILL.md +30 -12
  6. package/agent-skills/package.json +1 -1
  7. package/agent-skills/packs/hive-build/SKILL.md +47 -19
  8. package/agent-skills/packs/hive-build/evals/evals.json +16 -3
  9. package/agent-skills/packs/hive-build/evals/triggers.json +50 -0
  10. package/agent-skills/packs/hive-build-onboarding/SKILL.md +27 -34
  11. package/agent-skills/packs/hive-build-onboarding/evals/evals.json +1 -1
  12. package/agent-skills/packs/hive-build-onboarding/evals/triggers.json +50 -0
  13. package/agent-skills/packs/hive-cli/SKILL.md +33 -35
  14. package/agent-skills/packs/hive-cli/evals/evals.json +1 -1
  15. package/agent-skills/packs/hive-cli/evals/triggers.json +50 -0
  16. package/agent-skills/packs/hive-defi-research/SKILL.md +105 -19
  17. package/agent-skills/packs/hive-defi-research/evals/evals.json +6 -3
  18. package/agent-skills/packs/hive-defi-research/evals/triggers.json +50 -0
  19. package/agent-skills/packs/hive-dex-pool-analysis/SKILL.md +106 -16
  20. package/agent-skills/packs/hive-dex-pool-analysis/evals/evals.json +5 -3
  21. package/agent-skills/packs/hive-dex-pool-analysis/evals/triggers.json +50 -0
  22. package/agent-skills/packs/hive-market-research/SKILL.md +130 -21
  23. package/agent-skills/packs/hive-market-research/evals/evals.json +15 -2
  24. package/agent-skills/packs/hive-market-research/evals/triggers.json +50 -0
  25. package/agent-skills/packs/hive-mcp/SKILL.md +69 -47
  26. package/agent-skills/packs/hive-mcp/evals/evals.json +3 -2
  27. package/agent-skills/packs/hive-mcp/evals/triggers.json +50 -0
  28. package/agent-skills/packs/hive-mcp/references/client-install-matrix.md +62 -35
  29. package/agent-skills/packs/hive-mcp/references/clients.md +81 -68
  30. package/agent-skills/packs/hive-network-infrastructure/SKILL.md +105 -20
  31. package/agent-skills/packs/hive-network-infrastructure/evals/evals.json +4 -2
  32. package/agent-skills/packs/hive-network-infrastructure/evals/triggers.json +50 -0
  33. package/agent-skills/packs/hive-nft-research/SKILL.md +105 -18
  34. package/agent-skills/packs/hive-nft-research/evals/evals.json +4 -2
  35. package/agent-skills/packs/hive-nft-research/evals/triggers.json +50 -0
  36. package/agent-skills/packs/hive-prediction-markets/SKILL.md +108 -21
  37. package/agent-skills/packs/hive-prediction-markets/evals/evals.json +4 -2
  38. package/agent-skills/packs/hive-prediction-markets/evals/triggers.json +50 -0
  39. package/agent-skills/packs/hive-query/SKILL.md +79 -33
  40. package/agent-skills/packs/hive-query/evals/evals.json +7 -5
  41. package/agent-skills/packs/hive-query/evals/triggers.json +50 -0
  42. package/agent-skills/packs/hive-query/references/root-mcp-workflow.md +39 -18
  43. package/agent-skills/packs/hive-security-risk/SKILL.md +110 -19
  44. package/agent-skills/packs/hive-security-risk/evals/evals.json +4 -2
  45. package/agent-skills/packs/hive-security-risk/evals/triggers.json +50 -0
  46. package/agent-skills/packs/hive-solana-analysis/SKILL.md +115 -19
  47. package/agent-skills/packs/hive-solana-analysis/evals/evals.json +4 -2
  48. package/agent-skills/packs/hive-solana-analysis/evals/triggers.json +50 -0
  49. package/agent-skills/packs/hive-stateful-monitoring/SKILL.md +92 -47
  50. package/agent-skills/packs/hive-stateful-monitoring/evals/evals.json +7 -2
  51. package/agent-skills/packs/hive-stateful-monitoring/evals/triggers.json +50 -0
  52. package/agent-skills/packs/hive-stateful-monitoring/references/b2b-subject-context.md +53 -0
  53. package/agent-skills/packs/hive-token-diligence/SKILL.md +119 -21
  54. package/agent-skills/packs/hive-token-diligence/evals/evals.json +6 -4
  55. package/agent-skills/packs/hive-token-diligence/evals/triggers.json +50 -0
  56. package/agent-skills/packs/hive-tool-discovery/SKILL.md +48 -19
  57. package/agent-skills/packs/hive-tool-discovery/evals/evals.json +17 -3
  58. package/agent-skills/packs/hive-tool-discovery/evals/triggers.json +50 -0
  59. package/agent-skills/packs/hive-tool-discovery/references/discovery-surfaces.md +31 -6
  60. package/agent-skills/packs/hive-wallet-investigation/SKILL.md +111 -18
  61. package/agent-skills/packs/hive-wallet-investigation/evals/evals.json +5 -3
  62. package/agent-skills/packs/hive-wallet-investigation/evals/triggers.json +50 -0
  63. package/agent-skills/references/agents-routing.md +17 -7
  64. package/agent-skills/scripts/validate-agent-skills-package.mjs +68 -8
  65. package/bin/hive-mcp.js +5 -5
  66. package/build/{alias-3OPMQF4X.js → alias-BKAVOYQV.js} +2 -2
  67. package/build/{api-client-EPF6FD7A.js → api-client-FTVDFW5V.js} +4 -4
  68. package/build/{auth-Q5Q24IRI.js → auth-EZFJ5RYB.js} +3 -3
  69. package/build/{browser-auth-VPF5LZMZ.js → browser-auth-OJSUNFBI.js} +2 -2
  70. package/build/{cache-T6KC5YEY.js → cache-TBDQ7QBU.js} +2 -2
  71. package/build/{chunk-POT2MBEK.js → chunk-6PC3HUAK.js} +10 -3
  72. package/build/{chunk-NP6NSOG2.js → chunk-725R3KLJ.js} +26 -3
  73. package/build/{chunk-GZPDEXO4.js → chunk-7GD2MFYI.js} +57 -6
  74. package/build/{chunk-ZXB53E7H.js → chunk-AEU43ACS.js} +31 -7
  75. package/build/chunk-EPF36Q3Z.js +71 -0
  76. package/build/chunk-I5Z6FZRL.js +178 -0
  77. package/build/{chunk-3WYWXTNN.js → chunk-ILVPOLA7.js} +12 -3
  78. package/build/{chunk-VBOKVQ74.js → chunk-L326MQZP.js} +6 -5
  79. package/build/{chunk-FRXMGRZQ.js → chunk-M6REON2I.js} +2 -2
  80. package/build/chunk-N32UIHBU.js +125 -0
  81. package/build/{chunk-7JWXBKEJ.js → chunk-Q7VBYLX7.js} +9 -2
  82. package/build/chunk-QDZ7MAVN.js +447 -0
  83. package/build/{chunk-ZTJVOWDQ.js → chunk-R6YZTFQL.js} +2 -0
  84. package/build/{chunk-YZ2PXBJK.js → chunk-RU6QOFHH.js} +6 -9
  85. package/build/{chunk-5XXI25JE.js → chunk-RUHO24SX.js} +16 -9
  86. package/build/{chunk-FH3YGSY5.js → chunk-TNQ7GJ6Q.js} +0 -59
  87. package/build/{chunk-JTUKQWIO.js → chunk-W2QL7LYI.js} +34807 -15070
  88. package/build/{chunk-ZCU7XQKF.js → chunk-ZXKFJQDE.js} +7 -1
  89. package/build/cli.js +3337 -3407
  90. package/build/{completion-46K674EL.js → completion-7KBW243H.js} +4 -4
  91. package/build/{config-XE6Q5P4I.js → config-KAEUX6RM.js} +23 -3
  92. package/build/{config-dir-MAWX5AUF.js → config-dir-5IH7MOOT.js} +2 -2
  93. package/build/{doctor-HGMQE6IN.js → doctor-ORDOCGLM.js} +12 -12
  94. package/build/{errors-J2PH3NLJ.js → errors-HGHUF575.js} +2 -2
  95. package/build/{format-5X2HIVDT.js → format-H7FOQSYY.js} +1 -1
  96. package/build/{init-JMDNM7ZZ.js → init-UCTCUYFA.js} +52 -8
  97. package/build/init-all-BVWW3JVK.js +408 -0
  98. package/build/mcpServer-RUEOTTF7.js +34 -0
  99. package/build/monitor-worker.js +296 -40
  100. package/build/{namespace-FSX2G3NM.js → namespace-L5DGCY7K.js} +2 -2
  101. package/build/{open-5A6ZQMGC.js → open-V2RNA3QT.js} +1 -1
  102. package/build/{output-V3D4YZ6U.js → output-ITGLBKIG.js} +2 -2
  103. package/build/release.json +8 -0
  104. package/build/{serve-AGCOXXFM.js → serve-DKLR2WQH.js} +3 -3
  105. package/build/server.js +4481 -2319
  106. package/build/{setup-RMETGJWK.js → setup-PTYFMTK5.js} +60 -55
  107. package/build/stdio.js +7 -6
  108. package/build/{telemetry-WCME5XEU.js → telemetry-HPLDYR7U.js} +5 -4
  109. package/build/{tools-KAB6QBZC.js → tools-I7GLWTV6.js} +15 -15
  110. package/build/{uninstall-FLJMBBSC.js → uninstall-SAOIPL6K.js} +19 -10
  111. package/build/{update-check-LNZQK3XA.js → update-check-IEXPOYYR.js} +4 -4
  112. package/build/{upgrade-DTUIHVPS.js → upgrade-J4HIGCKE.js} +5 -5
  113. package/build/{version-I6HDAF4L.js → version-Z4HJL4VV.js} +4 -2
  114. package/build/{watch-YNN255QX.js → watch-WVR4CGCD.js} +8 -7
  115. package/package.json +71 -35
  116. package/agent-skills/packs/hive-defi-research/references/workflow.md +0 -41
  117. package/agent-skills/packs/hive-dex-pool-analysis/references/workflow.md +0 -42
  118. package/agent-skills/packs/hive-market-research/references/workflow.md +0 -47
  119. package/agent-skills/packs/hive-network-infrastructure/references/workflow.md +0 -41
  120. package/agent-skills/packs/hive-nft-research/references/workflow.md +0 -42
  121. package/agent-skills/packs/hive-prediction-markets/references/workflow.md +0 -42
  122. package/agent-skills/packs/hive-security-risk/references/workflow.md +0 -46
  123. package/agent-skills/packs/hive-solana-analysis/references/workflow.md +0 -42
  124. package/agent-skills/packs/hive-token-diligence/references/workflow.md +0 -45
  125. package/agent-skills/packs/hive-wallet-investigation/references/workflow.md +0 -45
  126. package/build/chunk-4F5CI6LX.js +0 -340
  127. package/build/chunk-CEWCB5YS.js +0 -71
  128. package/build/chunk-IZPAMRHP.js +0 -43
  129. package/build/init-all-5SKNV75X.js +0 -273
  130. package/build/mcpServer-5TKKSKJM.js +0 -21
@@ -1,42 +1,135 @@
1
1
  ---
2
2
  name: hive-wallet-investigation
3
- description: Use this skill for wallet, portfolio, holder, whale, transfer, PnL, NFT exposure, DeFi position, or notable on-chain activity investigations. Require wallet address and chain before executing Hive wallet tools.
3
+ description: Use this skill whenever the user wants to look inside a wallet or address — portfolio, holdings, balances, transfers, PnL, NFT exposure, DeFi positions, whale moves, "what does this address hold", "trace this wallet's activity" — even if they just paste an address. Requires wallet address and chain before executing Hive wallet tools. For Solana wallets use hive-solana-analysis; for "is this address malicious" risk checks use hive-security-risk.
4
4
  license: MIT
5
5
  metadata:
6
6
  package: "@hiveintelligence/agent-skills"
7
7
  category: "wallet"
8
8
  requires_network: "true"
9
- version: 1.0.0
9
+ version: 1.3.0
10
10
  ---
11
11
 
12
12
  # hive-wallet-investigation — Wallet Investigation
13
13
 
14
- Use this skill when the user asks to investigate a wallet, portfolio, holdings,
15
- transfers, PnL, NFT exposure, or DeFi positions.
14
+ Investigate a wallet's balances, transfers, PnL, NFT exposure, DeFi positions,
15
+ and notable activity with live Hive data, scoped to exactly what the user
16
+ asked.
16
17
 
17
- ## Task toolset
18
+ ## Task toolset and identifiers
18
19
 
19
- Use `wallet_investigation`.
20
+ Toolset: `wallet_investigation`. Read
21
+ `hive://toolsets/wallet_investigation` before execution; it is authoritative
22
+ for the current output schema, material-call budget, phases, fallback
23
+ condition, and stop conditions.
20
24
 
21
- Required identifiers: wallet address and chain.
25
+ - Required: wallet address and chain/network — unless the user explicitly asks
26
+ for multi-chain.
27
+ - Optional: time window, asset filter, counterparty, protocol, NFT collection.
22
28
 
23
- ## Procedure
29
+ Ask for the chain when an EVM address appears without context: the same
30
+ address exists on every EVM chain with different state, so guessing the chain
31
+ silently changes the answer. For Solana wallets, hand off to
32
+ `hive-solana-analysis`.
33
+
34
+ Before choosing endpoints, select exactly one matching entry from the exact
35
+ workflow's routes[]. Follow its ordered steps, use a fallback only under that
36
+ step's published condition, stop at four material calls, and preserve the
37
+ selected route_id in the typed result. The broad coverageCatalog is discovery
38
+ coverage, not an execution plan.
24
39
 
25
- Read `references/workflow.md` when the request needs multi-chain handling,
26
- activity triage, risk caveats, or a structured wallet investigation report.
40
+ ## Procedure
27
41
 
28
42
  1. Validate the address format for the requested chain.
29
- 2. Start with balances and native balance.
30
- 3. Add transfers, NFT holdings, DeFi positions, or PnL only when relevant.
31
- 4. Summarize exposure, concentration, notable activity, and missing data.
43
+ 2. Call `search_tools` for wallet balance, native balance, transfer, NFT,
44
+ DeFi-position, and PnL capabilities as the question requires.
45
+ 3. Call `get_api_endpoint_schema` for each endpoint before calling it.
46
+ 4. Call `invoke_api_endpoint` with schema-valid, bounded arguments.
47
+ 5. Start with balances and native balance. Add transfers for activity
48
+ questions; add NFTs, DeFi positions, or PnL only when relevant.
49
+ 6. Summarize exposure, concentration, notable activity, and missing data.
50
+
51
+ ## Bounded calls
52
+
53
+ - Use explicit `limit`, `page`, `per_page`, or time filters for transfers.
54
+ - Do not fetch full history for a quick portfolio read.
55
+ - Avoid mixing chains unless the user requested multi-chain analysis.
56
+
57
+ ## Worked example
58
+
59
+ User: "What does 0x28C6c06298d514Db089934071355E5743bf21d60 hold on Ethereum,
60
+ and did anything big move this week?"
61
+
62
+ 1. `search_tools` → `{"query": "wallet token balances native balance transfers ethereum", "limit": 5}`
63
+ 2. `get_api_endpoint_schema` for the balance and transfer endpoints returned.
64
+ 3. `invoke_api_endpoint` for balances first, then transfers with a 7-day
65
+ window and an explicit limit — argument names come from the schema, not
66
+ from memory.
67
+ 4. Answer with the report template, flagging spam tokens and truncated
68
+ history.
69
+
70
+ ## Report template
71
+
72
+ ```markdown
73
+ ## Summary
74
+ [Wallet posture and the most notable finding.]
32
75
 
33
- ## Example
76
+ ## Calls made
77
+ - Toolset: wallet_investigation
78
+ - Endpoint(s): [exact endpoint names]
79
+ - Identifiers: [chain, wallet, filters]
34
80
 
35
- If the user provides an EVM wallet but no chain, ask whether they want Ethereum,
36
- Base, Arbitrum, Polygon, or a multi-chain investigation.
81
+ ## Evidence
82
+ - Balances: [native + top token holdings]
83
+ - Activity: [transfers in window, counterparties]
84
+ - Exposure: [NFTs, DeFi positions, PnL if requested]
85
+ - Provenance: [provider, fetched_at, observed_at/cache_age_ms, runtime status per call]
86
+
87
+ ## Caveats
88
+ [Missing chains, truncated history, unavailable enrichment, degraded providers.]
89
+
90
+ ## Next action
91
+ [Chain expansion, transfer drilldown, risk check, or PnL detail — only if needed.]
92
+ ```
93
+
94
+ ## Gotchas
95
+
96
+ - Wallet labels and owner identity are not guaranteed.
97
+ - Token balances can include spam or illiquid assets — say so rather than
98
+ inflating portfolio value.
99
+ - Absence of DeFi/NFT data may reflect provider coverage, not true absence.
100
+
101
+ ## Evidence receipt (required)
102
+
103
+ End every Hive-backed answer with a compact receipt built from the `_hive`
104
+ object on each material tool response:
105
+
106
+ - `provider`, `tool`, `fetched_at`, `observed_at`, `cache_age_ms`, and `runtime_status`
107
+ - `receipt_id`, `receipt_version`, server/build version, and SHA-256 input/result
108
+ digests when present (self-checks, not signatures)
109
+ - `source`, `cache_status`, `truncated`, and any warnings
110
+ - canonical chain/entity identifiers plus block, slot, transaction, or query ids
111
+ present in provider data
112
+ - material provider disagreements and how they were handled
113
+ - checks that were unavailable, gated, stale, truncated, or intentionally not run
114
+ - a `claims[]` citation from each material statement to exact receipt IDs
115
+ - one `coverage[]` entry for every canonical evidence phase, with each gap explained
116
+
117
+ Never turn missing evidence into a clean result, silently merge conflicting
118
+ provider values, or omit a degraded/fallback call from the receipt.
119
+ `observed_at` is Hive's first-observation/original cache-population time, and
120
+ `cache_age_ms: 0` only means newly retrieved by Hive. Use provider time, block,
121
+ slot, transaction, or candle close for source recency; if absent, mark it
122
+ unknown. Run `validate_task_result` before presenting the typed workflow result;
123
+ it checks structure but cannot authenticate an invented receipt.
37
124
 
38
125
  ## Runtime status handling
39
126
 
40
- Classify provider failures as `missing_key`, `plan_required`, `rate_limited`,
41
- `degraded`, or `failing`. A single blocked enrichment tool should not suppress
127
+ Classify provider failures as `invalid_input`, `missing_key`, `plan_required`,
128
+ `rate_limited`, `degraded`, or `failing`. A single blocked enrichment tool should not suppress
42
129
  balances or transfers that did succeed.
130
+
131
+ ## Hand-offs
132
+
133
+ - Solana wallet (base58 address) → `hive-solana-analysis`.
134
+ - "Is this address dangerous / phishing / sanctioned" → `hive-security-risk`.
135
+ - Token-specific deep dive on one holding → `hive-token-diligence`.
@@ -3,13 +3,15 @@
3
3
  "evals": [
4
4
  {
5
5
  "id": 1,
6
- "prompt": "Investigate this Ethereum wallet's balances and recent transfers: 0x0000000000000000000000000000000000000000",
7
- "expected_output": "Uses wallet_investigation, validates chain/address, starts with balances, adds bounded recent transfers, and reports source/freshness/runtime status.",
6
+ "prompt": "What does 0x28C6c06298d514Db089934071355E5743bf21d60 hold on Ethereum, and did anything big move in the last week?",
7
+ "expected_output": "Uses wallet_investigation, validates chain/address, starts with balances, adds bounded recent transfers, and ends with a source/freshness/runtime receipt.",
8
8
  "files": [],
9
9
  "assertions": [
10
10
  "Chooses wallet_investigation.",
11
+ "Selects the matching portfolio_snapshot or recent_activity route and follows its ordered calls.",
11
12
  "Starts with balances/native balance.",
12
- "Bounds transfer history."
13
+ "Bounds transfer history.",
14
+ "Includes receipt ids and missing evidence."
13
15
  ]
14
16
  },
15
17
  {
@@ -0,0 +1,50 @@
1
+ [
2
+ {
3
+ "query": "what does 0x28C6c06298d514Db089934071355E5743bf21d60 hold on ethereum",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "trace where this wallet's funds came from, it just sent me 2 eth",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "did this whale wallet dump any LINK this week? 0x… on mainnet",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "show me this address's defi positions and nft exposure",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "whats the realized pnl of this trader address",
20
+ "should_trigger": true
21
+ },
22
+ {
23
+ "query": "this EVM address might be active on several chains, can you inspect it",
24
+ "should_trigger": true
25
+ },
26
+ {
27
+ "query": "is this address that dm'd me flagged as a scammer or phishing",
28
+ "should_trigger": false
29
+ },
30
+ {
31
+ "query": "analyze this solana wallet 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
32
+ "should_trigger": false
33
+ },
34
+ {
35
+ "query": "alert me whenever this wallet moves more than $50k",
36
+ "should_trigger": false
37
+ },
38
+ {
39
+ "query": "how do hd wallets derive addresses from a seed phrase",
40
+ "should_trigger": false
41
+ },
42
+ {
43
+ "query": "whats gas on mainnet right now",
44
+ "should_trigger": false
45
+ },
46
+ {
47
+ "query": "what tokens should i buy this week",
48
+ "should_trigger": false
49
+ }
50
+ ]
@@ -38,13 +38,23 @@ For live crypto intelligence, prefer Hive retrieval over model memory.
38
38
  use `hive-mcp`, `hive-build-onboarding`, `hive-cli`, or `hive-build`.
39
39
 
40
40
  Default execution loop:
41
- 1. Read `hive://toolsets` or call `search_tools`.
42
- 2. Select one task toolset or exact endpoint.
43
- 3. Call `get_api_endpoint_schema`.
44
- 4. Execute through `invoke_api_endpoint` with bounded args.
45
- 5. Report provider, source/freshness, fallback/cache/degraded state, and
46
- runtime status (`ok`, `missing_key`, `plan_required`, `rate_limited`,
47
- `degraded`, or `failing`).
41
+ 1. Read the compact `hive://toolsets` index or call `search_tools`.
42
+ 2. Select one task toolset and its best matching compact `routes[]` entry.
43
+ Preserve `route_id`; follow the ordered calls, conditional per-call
44
+ fallbacks, four-call cap, and stop condition. Use `coverageCatalog` only
45
+ for long-tail discovery.
46
+ 3. Call `get_api_endpoint_schema` and inspect `operation`/`callPattern`.
47
+ 4. Execute reads through `invoke_api_endpoint` with bounded args. Explain any
48
+ Hive state change, obtain explicit approval, then use
49
+ `invoke_stateful_endpoint`; never auto-approve it.
50
+ 5. Copy exact server-returned `_hive` blocks into the task receipt, cite exact
51
+ receipt IDs from `claims[]`, account for every canonical `coverage[]`
52
+ phase, include `route_id`, and call `validate_task_result` before presenting a structured
53
+ result.
54
+ 6. Report provider, source recency, fallback/cache/degraded state, and runtime
55
+ status (`ok`, `invalid_input`, `missing_key`, `plan_required`,
56
+ `rate_limited`, `degraded`, or `failing`). `observed_at` is Hive
57
+ first-observation/original cache time, not necessarily upstream event time.
48
58
  ```
49
59
 
50
60
  Keep this snippet short. The skill files carry the detailed workflow and should
@@ -6,8 +6,8 @@ import { fileURLToPath } from "node:url";
6
6
  const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
7
7
  const packsRoot = join(root, "packs");
8
8
  const failures = [];
9
-
10
- const workflowReferenceSkills = new Set([
9
+ const receiptSkills = new Set([
10
+ "hive-query",
11
11
  "hive-market-research",
12
12
  "hive-token-diligence",
13
13
  "hive-wallet-investigation",
@@ -18,6 +18,7 @@ const workflowReferenceSkills = new Set([
18
18
  "hive-solana-analysis",
19
19
  "hive-network-infrastructure",
20
20
  "hive-prediction-markets",
21
+ "hive-stateful-monitoring",
21
22
  ]);
22
23
 
23
24
  function fail(message) {
@@ -80,8 +81,11 @@ for (const skillName of skillDirs) {
80
81
  const description = field(fm, "description");
81
82
 
82
83
  if (name !== skillName) fail(`${skillName} frontmatter name must match directory.`);
83
- if (!description.startsWith("Use this skill")) {
84
- fail(`${skillName} description must start with trigger language: "Use this skill".`);
84
+ const hasTriggerLanguage =
85
+ description.startsWith("Use this skill") ||
86
+ (skillName === "hive-query" && description.startsWith("Default entry point"));
87
+ if (!hasTriggerLanguage) {
88
+ fail(`${skillName} description must start with explicit trigger language.`);
85
89
  }
86
90
  if (description.includes(": ")) {
87
91
  fail(`${skillName} description contains ': ', which breaks some YAML parsers unless quoted.`);
@@ -95,6 +99,13 @@ for (const skillName of skillDirs) {
95
99
  if (!body.includes("## Runtime status handling")) {
96
100
  fail(`${skillName} must document runtime status handling.`);
97
101
  }
102
+ if (
103
+ receiptSkills.has(skillName) &&
104
+ (!body.includes("## Evidence receipt (required)") ||
105
+ !body.includes("`receipt_id`"))
106
+ ) {
107
+ fail(`${skillName} must require Hive evidence receipts.`);
108
+ }
98
109
 
99
110
  const evalFile = join(skillDir, "evals", "evals.json");
100
111
  if (!existsSync(evalFile)) {
@@ -113,11 +124,42 @@ for (const skillName of skillDirs) {
113
124
  fail(`${skillName} eval ${entry.id ?? "unknown"} needs assertions.`);
114
125
  }
115
126
  }
127
+ if (
128
+ receiptSkills.has(skillName) &&
129
+ !(evals?.evals ?? []).some((entry) =>
130
+ `${entry.expected_output ?? ""} ${(entry.assertions ?? []).join(" ")}`
131
+ .toLowerCase()
132
+ .includes("receipt"),
133
+ )
134
+ ) {
135
+ fail(`${skillName} evals must cover the evidence receipt contract.`);
136
+ }
116
137
  }
117
138
 
118
- if (workflowReferenceSkills.has(skillName)) {
119
- const workflow = join(skillDir, "references", "workflow.md");
120
- if (!existsSync(workflow)) fail(`${skillName} is missing references/workflow.md.`);
139
+ const triggerFile = join(skillDir, "evals", "triggers.json");
140
+ if (!existsSync(triggerFile)) {
141
+ fail(`${skillName} is missing evals/triggers.json.`);
142
+ } else {
143
+ const triggers = readJson(triggerFile);
144
+ if (!Array.isArray(triggers) || triggers.length < 4) {
145
+ fail(`${skillName} must define at least four trigger evals.`);
146
+ } else {
147
+ if (!triggers.some((entry) => entry?.should_trigger === true)) {
148
+ fail(`${skillName} trigger evals need a positive example.`);
149
+ }
150
+ if (!triggers.some((entry) => entry?.should_trigger === false)) {
151
+ fail(`${skillName} trigger evals need a negative example.`);
152
+ }
153
+ for (const entry of triggers) {
154
+ if (
155
+ typeof entry?.query !== "string" ||
156
+ !entry.query.trim() ||
157
+ typeof entry?.should_trigger !== "boolean"
158
+ ) {
159
+ fail(`${skillName} has an invalid trigger eval entry.`);
160
+ }
161
+ }
162
+ }
121
163
  }
122
164
 
123
165
  const referenceMatches = [...body.matchAll(/`(references\/[^`]+)`/g)];
@@ -143,11 +185,17 @@ if (directoryManifest) {
143
185
  // the drift mode where a pack ships with evals but is invisible to install and
144
186
  // routing (e.g. a skill missing from plugin.json never loads via plugin install).
145
187
  const pluginManifestPath = join(root, ".claude-plugin", "plugin.json");
188
+ const packageManifest = readJson(join(root, "package.json"));
146
189
  if (!existsSync(pluginManifestPath)) {
147
190
  fail("agent-skills/.claude-plugin/plugin.json is missing.");
148
191
  } else {
149
192
  const pluginManifest = readJson(pluginManifestPath);
150
193
  if (pluginManifest) {
194
+ if (packageManifest && pluginManifest.version !== packageManifest.version) {
195
+ fail(
196
+ `.claude-plugin/plugin.json version ${pluginManifest.version} must match package.json ${packageManifest.version}.`,
197
+ );
198
+ }
151
199
  const pluginSkills = new Set((pluginManifest.skills ?? []).map((skill) => skill.name));
152
200
  for (const skillName of skillDirs) {
153
201
  if (!pluginSkills.has(skillName)) {
@@ -169,9 +217,21 @@ if (!existsSync(pluginManifestPath)) {
169
217
  } else {
170
218
  const mcp = readJson(mcpPath);
171
219
  const hive = mcp?.mcpServers?.hive;
172
- if (!hive?.url || !hive.url.includes("mcp.hiveintelligence.xyz")) {
220
+ if (hive?.url !== "https://mcp.hiveintelligence.xyz/mcp") {
173
221
  fail(`${pluginManifest.mcpServers} must define mcpServers.hive.url for the hosted Hive endpoint.`);
174
222
  }
223
+ if (
224
+ JSON.stringify(hive) !==
225
+ JSON.stringify({
226
+ type: "http",
227
+ url: "https://mcp.hiveintelligence.xyz/mcp",
228
+ })
229
+ ) {
230
+ fail(`${pluginManifest.mcpServers} must be an exact URL-only interactive OAuth config.`);
231
+ }
232
+ if (/authorization|bearer|api.?key|token|secret|\$\{/i.test(JSON.stringify(hive))) {
233
+ fail(`${pluginManifest.mcpServers} must not contain credentials or placeholders.`);
234
+ }
175
235
  }
176
236
  }
177
237
  }
package/bin/hive-mcp.js CHANGED
@@ -4,14 +4,14 @@
4
4
  // In an ESM file (type:module), static imports are parsed before execution,
5
5
  // so a version check using `if (major < 20)` would never execute on old Node.
6
6
  // However, since this file IS ESM and uses import statements, the check below
7
- // is a best-effort guard for Node 20+ (which already supports ESM + TLA).
7
+ // is a best-effort guard for Node 22.12+ (which supports the package runtime).
8
8
  // For Node <16, this file fails at parse time with a SyntaxError — engines
9
9
  // field in package.json is the primary enforcement mechanism.
10
10
 
11
- const major = parseInt(process.versions.node.split(".")[0], 10);
12
- if (major < 20) {
11
+ const [major, minor] = process.versions.node.split(".").map(Number);
12
+ if (major < 22 || (major === 22 && minor < 12)) {
13
13
  process.stderr.write(
14
- `Error: hive requires Node.js 20 or later (found ${process.versions.node}).\n`,
14
+ `Error: hive requires Node.js 22.12 or later (found ${process.versions.node}).\n`,
15
15
  );
16
16
  process.exit(1);
17
17
  }
@@ -25,7 +25,7 @@ const cliPath = join(__dirname, "..", "build", "cli.js");
25
25
 
26
26
  if (!existsSync(cliPath)) {
27
27
  process.stderr.write(
28
- "Error: build/cli.js not found. Run `npm run build` or `bun run build` first.\n",
28
+ "Error: build/cli.js not found. Run `npm run build` first.\n",
29
29
  );
30
30
  process.exit(1);
31
31
  }
@@ -3,8 +3,8 @@ import {
3
3
  ensureConfigDir,
4
4
  getConfig,
5
5
  saveConfig
6
- } from "./chunk-POT2MBEK.js";
7
- import "./chunk-3WYWXTNN.js";
6
+ } from "./chunk-6PC3HUAK.js";
7
+ import "./chunk-ILVPOLA7.js";
8
8
 
9
9
  // src/cli/alias.ts
10
10
  function getAliases() {
@@ -10,10 +10,10 @@ import {
10
10
  getUsage,
11
11
  listKeysApi,
12
12
  revokeKeyApi
13
- } from "./chunk-7JWXBKEJ.js";
14
- import "./chunk-ZCU7XQKF.js";
15
- import "./chunk-POT2MBEK.js";
16
- import "./chunk-3WYWXTNN.js";
13
+ } from "./chunk-Q7VBYLX7.js";
14
+ import "./chunk-ZXKFJQDE.js";
15
+ import "./chunk-6PC3HUAK.js";
16
+ import "./chunk-ILVPOLA7.js";
17
17
  export {
18
18
  authLogin,
19
19
  authMe,
@@ -16,9 +16,9 @@ import {
16
16
  runWhoami,
17
17
  saveProfile,
18
18
  switchProfile
19
- } from "./chunk-5XXI25JE.js";
20
- import "./chunk-POT2MBEK.js";
21
- import "./chunk-3WYWXTNN.js";
19
+ } from "./chunk-RUHO24SX.js";
20
+ import "./chunk-6PC3HUAK.js";
21
+ import "./chunk-ILVPOLA7.js";
22
22
  export {
23
23
  getActiveProfile,
24
24
  listProfiles,
@@ -1,8 +1,8 @@
1
1
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
  import {
3
3
  browserLogin
4
- } from "./chunk-GZPDEXO4.js";
5
- import "./chunk-3WYWXTNN.js";
4
+ } from "./chunk-7GD2MFYI.js";
5
+ import "./chunk-ILVPOLA7.js";
6
6
  export {
7
7
  browserLogin
8
8
  };
@@ -4,8 +4,8 @@ import {
4
4
  getConfigDir,
5
5
  readJsonFile,
6
6
  writeJsonFile
7
- } from "./chunk-POT2MBEK.js";
8
- import "./chunk-3WYWXTNN.js";
7
+ } from "./chunk-6PC3HUAK.js";
8
+ import "./chunk-ILVPOLA7.js";
9
9
 
10
10
  // src/cli/cache.ts
11
11
  import { existsSync, unlinkSync } from "fs";
@@ -1,7 +1,13 @@
1
1
  import { createRequire } from 'node:module'; const require = createRequire(import.meta.url);
2
2
 
3
3
  // src/cli/config-dir.ts
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
4
+ import {
5
+ chmodSync,
6
+ existsSync,
7
+ mkdirSync,
8
+ readFileSync,
9
+ writeFileSync
10
+ } from "fs";
5
11
  import { join } from "path";
6
12
  import { homedir } from "os";
7
13
  var DEFAULT_CONFIG = {
@@ -24,9 +30,9 @@ function getConfigDir() {
24
30
  }
25
31
  function ensureConfigDir() {
26
32
  const dir = getConfigDir();
27
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
33
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true, mode: 448 });
28
34
  const cacheDir = join(dir, "cache");
29
- if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true });
35
+ if (!existsSync(cacheDir)) mkdirSync(cacheDir, { recursive: true, mode: 448 });
30
36
  }
31
37
  function readJsonFile(filePath) {
32
38
  try {
@@ -41,6 +47,7 @@ function writeJsonFile(filePath, data) {
41
47
  encoding: "utf-8",
42
48
  mode: 384
43
49
  });
50
+ chmodSync(filePath, 384);
44
51
  }
45
52
  function getConfig() {
46
53
  const filePath = join(getConfigDir(), "config.json");
@@ -149,7 +149,8 @@ function errorEnvelope(err, meta) {
149
149
  error: {
150
150
  code: err.code,
151
151
  message: err.message,
152
- ...err.suggestion && { suggestion: err.suggestion }
152
+ ...err.suggestion && { suggestion: err.suggestion },
153
+ ...err.docUrl && { doc_url: err.docUrl }
153
154
  },
154
155
  meta
155
156
  };
@@ -201,12 +202,34 @@ async function writeOutput(envelope) {
201
202
  const provider = envelope.meta.provider ? dim(` (${envelope.meta.provider})`) : "";
202
203
  const timing = envelope.meta.duration_ms != null ? dim(` ${envelope.meta.duration_ms}ms`) : "";
203
204
  process.stderr.write(`${status}${provider}${timing}
204
-
205
205
  `);
206
+ const receipt = [
207
+ envelope.meta.provider ? `provider=${envelope.meta.provider}` : void 0,
208
+ envelope.meta.source ? `source=${envelope.meta.source}` : void 0,
209
+ envelope.meta.origin_source ? `origin=${envelope.meta.origin_source}` : void 0,
210
+ envelope.meta.runtime_status ? `runtime=${envelope.meta.runtime_status}` : void 0,
211
+ envelope.meta.fetched_at ? `fetched=${envelope.meta.fetched_at}` : void 0,
212
+ envelope.meta.observed_at ? `observed=${envelope.meta.observed_at}` : void 0,
213
+ envelope.meta.cache_age_ms != null ? `cache_age_ms=${envelope.meta.cache_age_ms}` : void 0,
214
+ envelope.meta.cache_status ? `cache=${envelope.meta.cache_status}` : void 0,
215
+ envelope.meta.receipt_id ? `receipt=${envelope.meta.receipt_id}` : void 0
216
+ ].filter((value) => Boolean(value));
217
+ if (receipt.length > 0) {
218
+ process.stderr.write(dim(`Evidence: ${receipt.join(" \xB7 ")}
219
+ `));
220
+ }
221
+ if (envelope.meta.truncated) {
222
+ process.stderr.write(yellow("Evidence warning: response was truncated.\n"));
223
+ }
224
+ for (const warning of envelope.meta.warnings ?? []) {
225
+ process.stderr.write(yellow(`Evidence warning: ${warning}
226
+ `));
227
+ }
228
+ process.stderr.write("\n");
206
229
  }
207
230
  if (envelope.ok && envelope.data != null) {
208
231
  if (Array.isArray(envelope.data) && envelope.data.length > 0 && typeof envelope.data[0] === "object" && envelope.data[0] !== null) {
209
- const { formatTable } = await import("./format-5X2HIVDT.js");
232
+ const { formatTable } = await import("./format-H7FOQSYY.js");
210
233
  process.stdout.write(
211
234
  formatTable(envelope.data) + "\n"
212
235
  );
@@ -5,6 +5,31 @@ import { createServer } from "http";
5
5
  import { randomBytes } from "crypto";
6
6
  import { execFile } from "child_process";
7
7
  import { platform } from "os";
8
+ async function exchangeCliCode(args) {
9
+ const exchangeUrl = new URL("/auth/cli/exchange", args.baseUrl);
10
+ const controller = new AbortController();
11
+ const timer = setTimeout(() => controller.abort(), 1e4);
12
+ try {
13
+ const response = await fetch(exchangeUrl, {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: JSON.stringify({ code: args.code, state: args.state }),
17
+ signal: controller.signal
18
+ });
19
+ if (!response.ok) {
20
+ throw new Error(`CLI auth exchange failed with HTTP ${response.status}`);
21
+ }
22
+ const payload = await response.json();
23
+ const key = typeof payload.key === "string" ? payload.key : typeof payload.api_key?.key === "string" ? payload.api_key.key : "";
24
+ if (!key) throw new Error("CLI auth exchange returned no API key.");
25
+ return {
26
+ key,
27
+ email: typeof payload.email === "string" ? payload.email : ""
28
+ };
29
+ } finally {
30
+ clearTimeout(timer);
31
+ }
32
+ }
8
33
  function openBrowser(url) {
9
34
  const plat = platform();
10
35
  let cmd;
@@ -33,7 +58,7 @@ async function browserLogin(opts) {
33
58
  const state = randomBytes(16).toString("hex");
34
59
  return new Promise((resolve, reject) => {
35
60
  let settled = false;
36
- const server = createServer((req, res) => {
61
+ const server = createServer(async (req, res) => {
37
62
  const url = new URL(req.url || "/", `http://localhost`);
38
63
  if (url.pathname !== "/callback") {
39
64
  res.writeHead(404);
@@ -45,20 +70,42 @@ async function browserLogin(opts) {
45
70
  res.end();
46
71
  return;
47
72
  }
48
- const key = url.searchParams.get("key");
49
- const email = url.searchParams.get("email");
73
+ const legacyKey = url.searchParams.get("key");
74
+ const code = url.searchParams.get("code");
50
75
  const returnedState = url.searchParams.get("state");
51
76
  if (returnedState !== state) {
52
77
  res.writeHead(403);
53
78
  res.end("State mismatch \u2014 possible CSRF attack. Please try again.");
54
79
  return;
55
80
  }
56
- if (!key) {
81
+ if (legacyKey) {
82
+ res.writeHead(400);
83
+ res.end(
84
+ "Insecure legacy callback rejected. Please update Hive auth and try again."
85
+ );
86
+ return;
87
+ }
88
+ if (!code) {
57
89
  res.writeHead(400);
58
- res.end("Missing API key in callback");
90
+ res.end("Missing one-time code in callback");
59
91
  return;
60
92
  }
61
93
  settled = true;
94
+ let exchanged;
95
+ try {
96
+ exchanged = await exchangeCliCode({
97
+ baseUrl,
98
+ code,
99
+ state: returnedState
100
+ });
101
+ } catch (error) {
102
+ clearTimeout(timer);
103
+ server.close();
104
+ res.writeHead(502);
105
+ res.end("Could not complete CLI auth exchange. Return to the terminal.");
106
+ reject(error);
107
+ return;
108
+ }
62
109
  res.writeHead(200, { "Content-Type": "text/html" });
63
110
  res.end(`<!DOCTYPE html>
64
111
  <html>
@@ -79,7 +126,11 @@ async function browserLogin(opts) {
79
126
  </html>`);
80
127
  clearTimeout(timer);
81
128
  server.close();
82
- resolve({ key, email: email || "", state: returnedState });
129
+ resolve({
130
+ key: exchanged.key,
131
+ email: exchanged.email,
132
+ state: returnedState
133
+ });
83
134
  });
84
135
  server.listen(0, "127.0.0.1", () => {
85
136
  const addr = server.address();