@hey-research-lab/virtuals-plugin 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/LICENSE +21 -0
- package/README.md +247 -2
- package/dist/acp.d.ts +259 -0
- package/dist/acp.js +814 -0
- package/dist/index.cjs +879 -0
- package/dist/index.d.cts +163 -0
- package/dist/index.d.ts +163 -0
- package/dist/index.js +833 -0
- package/package.json +100 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## 0.1.1 — unreleased (not yet on npm)
|
|
8
|
+
|
|
9
|
+
- Security: `HEY_API_KEY` from the environment is sent to `https://heyresearch.xyz` only. With a custom
|
|
10
|
+
`baseUrl` (a mock, a proxy, a local server) no key is sent unless the caller passes `apiKey`
|
|
11
|
+
explicitly, as the AgentKit, GOAT and CLI integrations already do.
|
|
12
|
+
- Development: vitest 4.1.12.
|
|
13
|
+
|
|
14
|
+
## 0.1.0 — 2026-10-13
|
|
15
|
+
|
|
16
|
+
Initial release.
|
|
17
|
+
|
|
18
|
+
- GAME worker for `@virtuals-protocol/game` 0.1.14: `heyResearchWorker({ apiKey?, baseUrl? })` and
|
|
19
|
+
`heyResearchFunctions()` with five functions — `hey_research_project`, `hey_find_projects`,
|
|
20
|
+
`hey_recent_changes`, `hey_project_timeline`, `hey_chain_overview` — each returning
|
|
21
|
+
`ExecutableGameFunctionResponse` (Done for an answer, including "HEY holds no such project";
|
|
22
|
+
Failed for a refused or failed read) with text that keeps HEY's semantics, its as-of time, the
|
|
23
|
+
HEY link and the attribution line.
|
|
24
|
+
- Research by HEY slug, `$TICKER`, name or 0x contract: a contract resolves through HEY's token
|
|
25
|
+
lookup, a ticker or name through HEY's search, and is researched only on one exact match; several
|
|
26
|
+
matches are listed, never guessed.
|
|
27
|
+
- `@hey-research-lab/virtuals-plugin/acp`: an Agent Commerce Protocol provider scaffold for
|
|
28
|
+
`@virtuals-protocol/acp-node-v2` 0.1.15 offering "HEY builder research on a Robinhood Chain
|
|
29
|
+
project/contract". Off by default: it needs every `HEY_ACP_*` variable and `HEY_ACP_ENABLE=1`.
|
|
30
|
+
Price defaults to 0 USDC (pricing is the founder's decision); settlement chain (Base or Robinhood
|
|
31
|
+
Chain) has no default.
|
|
32
|
+
- Robinhood Chain (4663) only; any other chain is refused with `unsupported_chain`.
|
|
33
|
+
- Tests over saved fixtures with the network blocked and the ACP client fully stubbed; a
|
|
34
|
+
forbidden-word scan over every output.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 HEY Research Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,248 @@
|
|
|
1
|
-
#
|
|
1
|
+
# hey-virtuals-plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Virtuals Protocol GAME worker, plus an Agent Commerce Protocol provider scaffold, that lets an
|
|
4
|
+
agent ask HEY Research Lab which Robinhood Chain projects are still building, what they shipped and
|
|
5
|
+
what HEY does not know.
|
|
6
|
+
|
|
7
|
+
[](https://github.com/hey-research-lab/hey-virtuals-plugin/actions/workflows/ci.yml)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](package.json)
|
|
10
|
+
[](https://heyresearch.xyz)
|
|
11
|
+
|
|
12
|
+
## Why it exists
|
|
13
|
+
|
|
14
|
+
Many agents on Robinhood Chain run on Virtuals: in HEY's own catalogue, 668 of the 971 "AI Agents"
|
|
15
|
+
projects were launched through Virtuals. Those agents are asked about projects, tickers and
|
|
16
|
+
contracts every day. This package gives them HEY's answer — activity status, the last meaningful
|
|
17
|
+
ship, the change ledger and the gaps, each with its evidence and source — without having to find
|
|
18
|
+
HEY first. It reads only HEY's public API, through the published
|
|
19
|
+
[`@hey-research-lab/sdk`](https://www.npmjs.com/package/@hey-research-lab/sdk).
|
|
20
|
+
|
|
21
|
+
## Why Robinhood Chain only
|
|
22
|
+
|
|
23
|
+
HEY researches one chain: Robinhood Chain, chain id `4663` (`eip155:4663`). Every function takes
|
|
24
|
+
an optional `chain_id` that accepts `4663` or `eip155:4663` only; anything else is refused with
|
|
25
|
+
`unsupported_chain` ("HEY supports Robinhood Chain (4663) only; chain X is not supported.") before
|
|
26
|
+
any request. The ACP provider applies the same rule to a buyer's requirement. (Which chain an ACP
|
|
27
|
+
job _settles_ on is a separate choice; see below.)
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install @hey-research-lab/virtuals-plugin @virtuals-protocol/game
|
|
33
|
+
# only for the ACP provider:
|
|
34
|
+
npm install @virtuals-protocol/acp-node-v2
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Node.js 22 or later. No HEY API key is needed; `HEY_API_KEY` (from heyresearch.xyz/account) only
|
|
38
|
+
lifts the anonymous rate limit.
|
|
39
|
+
|
|
40
|
+
## Smallest working example
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { GameAgent } from '@virtuals-protocol/game';
|
|
44
|
+
import { heyResearchWorker } from '@hey-research-lab/virtuals-plugin';
|
|
45
|
+
|
|
46
|
+
const agent = new GameAgent(process.env.GAME_API_KEY!, {
|
|
47
|
+
name: 'Robinhood Chain builder scout',
|
|
48
|
+
goal: 'Report which Robinhood Chain projects are still building, citing HEY.',
|
|
49
|
+
description: 'Reports building evidence with its source and as-of time; unknown stays unknown.',
|
|
50
|
+
workers: [heyResearchWorker()], // or heyResearchWorker({ apiKey, baseUrl })
|
|
51
|
+
});
|
|
52
|
+
await agent.init();
|
|
53
|
+
await agent.run(60, { verbose: true });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
To call one function without an agent (offline-friendly for your own tests, with an injected
|
|
57
|
+
`fetchImpl`):
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { heyResearchFunctions } from '@hey-research-lab/virtuals-plugin';
|
|
61
|
+
const [research] = heyResearchFunctions();
|
|
62
|
+
const res = await research.executable({ query: '$AGENTOS' }, console.log);
|
|
63
|
+
console.log(res.status, res.feedback); // "done", HEY's answer as text
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
A runnable script is in [`examples/game-agent.ts`](examples/game-agent.ts).
|
|
67
|
+
|
|
68
|
+
## Functions
|
|
69
|
+
|
|
70
|
+
| Name | What it answers | SDK read |
|
|
71
|
+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
72
|
+
| `hey_research_project` | One project by HEY slug, `$TICKER`, name or 0x contract: activity status, last meaningful ship, meaningful events in 30 days, Build Momentum, Still Building, token contract and its verification, market context, unknowns, evidence ids | `agent.answer('research_project')`, after `token.lookup` (contract) or `search.suggest` (ticker, name) |
|
|
73
|
+
| `hey_find_projects` | Projects in HEY's index by name, ticker or contract, each labelled: published project (slug, status, link), launch record (not researched), issuer stock token (never a project) | `search.suggest` |
|
|
74
|
+
| `hey_recent_changes` | What changed on the chain or for one project in 1–30 days: the true total, how many count as building, each event with its date, precision and evidence id | `agent.answer('what_changed')` |
|
|
75
|
+
| `hey_project_timeline` | One project's ships and timeline: date and precision, verification state, whether it counts as building, source | `projects.timeline` |
|
|
76
|
+
| `hey_chain_overview` | Robinhood Chain day by day: ships, builders shipping, projects published, then transactions, launches and DEX figures (market context) | `chain` |
|
|
77
|
+
|
|
78
|
+
Each returns an `ExecutableGameFunctionResponse`:
|
|
79
|
+
|
|
80
|
+
- **Done** with HEY's answer as text — including "HEY holds no published project for …" and a
|
|
81
|
+
list of candidates for an ambiguous name, which are answers, not failures.
|
|
82
|
+
- **Failed** for an unsupported chain, a malformed argument, or a read HEY refused or could not
|
|
83
|
+
serve, with HEY's own error code and sentence, the retry delay and the request id
|
|
84
|
+
(`HEY could not answer: rate_limited (HTTP 429) — … Retry after 12 seconds. Request id: …`).
|
|
85
|
+
|
|
86
|
+
Every answer keeps HEY's semantics: an unknown value reads "unknown", "not measured — reason",
|
|
87
|
+
"withheld — reason" or "not read", never 0 or "none"; market figures are labelled context and
|
|
88
|
+
never a builder signal; a ticker is not identity (a ticker that several records share is called
|
|
89
|
+
out, and a name that matches several projects is listed, not guessed). Every answer ends with:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Source: HEY Research Lab — heyresearch.xyz · https://heyresearch.xyz/project/<slug>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`heyResearchWorker(options)` takes `apiKey`, `baseUrl` (tests and local mocks only: `https:` or
|
|
96
|
+
`http://localhost`; the environment's `HEY_API_KEY` goes to heyresearch.xyz only, so a custom `baseUrl`
|
|
97
|
+
needs an explicit `apiKey`), `fetchImpl`, `timeoutMs`, `client`, and `id` / `name` / `description` /
|
|
98
|
+
`getEnvironment` overrides. `heyResearchFunctions(options)` returns the five `GameFunction`s for
|
|
99
|
+
your own worker. The framework-neutral reads (`researchProject`, `findProjects`, `recentChanges`,
|
|
100
|
+
`projectTimeline`, `chainOverview`) are exported too.
|
|
101
|
+
|
|
102
|
+
## ACP provider (seller) scaffold
|
|
103
|
+
|
|
104
|
+
`@hey-research-lab/virtuals-plugin/acp` lets HEY act as an
|
|
105
|
+
[Agent Commerce Protocol](https://app.virtuals.io/research/agent-commerce-protocol) provider with
|
|
106
|
+
one offering: **"HEY builder research on a Robinhood Chain project/contract"**. A buyer sends
|
|
107
|
+
`{"query": "<slug | $TICKER | name | 0x contract>", "chainId": 4663}`; the seller checks HEY holds
|
|
108
|
+
an answer, proposes the budget, and when the job is funded reads HEY again and submits the
|
|
109
|
+
deliverable: JSON (`hey.virtuals-acp-deliverable/v1`) with the same report text the GAME function
|
|
110
|
+
returns, the project link, HEY's citation and as-of time, and the attribution line. If HEY holds no
|
|
111
|
+
such project, or several match, the job is rejected _before_ any budget, with HEY's answer in the
|
|
112
|
+
message. If HEY cannot be read at delivery, the job is rejected so the funds return.
|
|
113
|
+
|
|
114
|
+
It is built on `@virtuals-protocol/acp-node-v2`. The package named in older guides,
|
|
115
|
+
`@virtuals-protocol/acp-node`, is deprecated on npm in favour of v2, so this scaffold compiles
|
|
116
|
+
against v2 (0.1.15).
|
|
117
|
+
|
|
118
|
+
**It does nothing by default.** Importing it connects to nothing. `startHeyAcpSeller()` throws a
|
|
119
|
+
clear `AcpConfigError` naming every missing variable (never a value) and does not load the ACP SDK
|
|
120
|
+
until all of these are set and `HEY_ACP_ENABLE=1`:
|
|
121
|
+
|
|
122
|
+
| Variable | What | Where it comes from |
|
|
123
|
+
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
124
|
+
| `HEY_ACP_WALLET_ADDRESS` | The agent wallet address | Agent page on app.virtuals.io |
|
|
125
|
+
| `HEY_ACP_WALLET_ID` | The agent wallet id (v2's replacement for v1's "session entity key id") | Agent page on app.virtuals.io |
|
|
126
|
+
| `HEY_ACP_SIGNER_PRIVATE_KEY` | The signer key: a Privy authorization key (base64, not an EOA private key) | Agent page → **Signers** → **+ Add Signer** → **Copy Key** |
|
|
127
|
+
| `HEY_ACP_CHAIN_ID` | Settlement chain: `8453` (Base) or `4663` (Robinhood Chain). No default | The founder's decision |
|
|
128
|
+
| `HEY_ACP_PRICE_USDC` | USDC per job; **default `0`**, the lowest value the SDK and registry accept (the SDK's own seller example runs a 0 USDC offering) | **The founder's decision**; set it equal to the offering's price on the registry |
|
|
129
|
+
| `HEY_ACP_OFFERING_NAME` | Defaults to `hey_builder_research`; must equal the offering name on the registry | — |
|
|
130
|
+
| `HEY_ACP_BUILDER_CODE` | Optional Base builder code | Agent page → **Settings** |
|
|
131
|
+
| `HEY_ACP_ENABLE` | `1` to start. Anything else: nothing starts | The founder |
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
pnpm dlx tsx examples/acp-seller.ts # explains what is missing, or checks the config and exits unless HEY_ACP_ENABLE=1
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { startHeyAcpSeller } from '@hey-research-lab/virtuals-plugin/acp';
|
|
139
|
+
const seller = await startHeyAcpSeller(); // reads HEY_ACP_* from the environment
|
|
140
|
+
// … later: await seller.stop();
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The building blocks are exported for review and for your own wiring: `loadHeyAcpConfig`,
|
|
144
|
+
`createHeyAcpEntryHandler`, `parseRequirement`, `buildDeliverable`, `HEY_ACP_OFFERING` (name,
|
|
145
|
+
description, requirement JSON Schema, deliverable description, SLA) and the `AcpRuntime` seam.
|
|
146
|
+
|
|
147
|
+
### Which wallet and chain ACP settles on
|
|
148
|
+
|
|
149
|
+
Facts as the ACP v2 SDK (0.1.15) states them in its own constants; HEY has not independently
|
|
150
|
+
verified any of these contracts:
|
|
151
|
+
|
|
152
|
+
- **Wallet.** Each registered agent has an agent wallet: a Privy server-managed smart account (on
|
|
153
|
+
Alchemy's account infrastructure) created on app.virtuals.io. HEY's process never holds that
|
|
154
|
+
wallet's key; it holds a _signer_ authorization key the founder generates under the agent's
|
|
155
|
+
Signers tab, which lets the SDK ask Privy to sign for the agent wallet. The buyer's payment, in
|
|
156
|
+
USDC, is escrowed by the ACP contract and released to the agent wallet when the job completes.
|
|
157
|
+
- **Chains.** The SDK's mainnets are Base (`8453`), Robinhood Chain (`4663`) and Arc (`5042`), plus
|
|
158
|
+
Solana. On Base and Robinhood Chain the ACP contract is
|
|
159
|
+
`0x238E541BfefD82238730D00a2208E5497F1832E0`; USDC is
|
|
160
|
+
`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` on Base and
|
|
161
|
+
`0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` on Robinhood Chain. Both chains are in the SDK's
|
|
162
|
+
ERC-20 gas-sponsored list. This scaffold allows Base or Robinhood Chain and picks neither.
|
|
163
|
+
- **To decide:** the settlement chain (Base is where most ACP buyers already hold USDC; Robinhood
|
|
164
|
+
Chain keeps HEY on the chain it researches), the price, and whether to register at all. Any
|
|
165
|
+
protocol fee is Virtuals' and is not modelled here; check their current terms.
|
|
166
|
+
|
|
167
|
+
A paid job buys delivery of the same public answer anyone can read free on heyresearch.xyz; it
|
|
168
|
+
changes no status, score or order on HEY.
|
|
169
|
+
|
|
170
|
+
## Listing
|
|
171
|
+
|
|
172
|
+
**GAME (game-node plugins).**
|
|
173
|
+
|
|
174
|
+
1. Done: the package is on npm as
|
|
175
|
+
[`@hey-research-lab/virtuals-plugin`](https://www.npmjs.com/package/@hey-research-lab/virtuals-plugin)
|
|
176
|
+
and this repository is public.
|
|
177
|
+
2. Fork [game-by-virtuals/game-node](https://github.com/game-by-virtuals/game-node), add
|
|
178
|
+
`plugins/heyResearchPlugin/` with a `README.md` (install, usage, functions, troubleshooting) and
|
|
179
|
+
the [`plugin_metadata.yml`](plugin_metadata.yml) in this repository (filled from their
|
|
180
|
+
template). Plugins there keep their own package names (`tokenmetrics-virtuals-plugin` is one).
|
|
181
|
+
3. Open a pull request with their plugin PR template and the `plugin` label, with a log of a run.
|
|
182
|
+
|
|
183
|
+
**ACP (Service Registry on app.virtuals.io).**
|
|
184
|
+
|
|
185
|
+
1. Sign in at [app.virtuals.io](https://app.virtuals.io/acp/new) and register a new agent as a
|
|
186
|
+
provider (seller). Give it HEY's name and description; never imply Robinhood affiliation.
|
|
187
|
+
2. On the agent's page, note the wallet address and wallet id; under **Signers**, add a signer and
|
|
188
|
+
copy its key; under **Settings**, copy the builder code (optional).
|
|
189
|
+
3. Add one offering: name `hey_builder_research`; description, requirement schema and deliverable
|
|
190
|
+
from `HEY_ACP_OFFERING`; SLA at least 5 minutes; price as decided; on the settlement chain chosen.
|
|
191
|
+
4. Set the `HEY_ACP_*` variables on the host that will run the seller (never in the repository), run
|
|
192
|
+
`examples/acp-seller.ts` once without `HEY_ACP_ENABLE` to check them, then with
|
|
193
|
+
`HEY_ACP_ENABLE=1`.
|
|
194
|
+
5. Test with a separate buyer agent (the SDK requires different wallets) at a 0 or minimal price
|
|
195
|
+
before announcing the offering.
|
|
196
|
+
|
|
197
|
+
## How it relates to HEY Research Lab
|
|
198
|
+
|
|
199
|
+
It reads HEY's public API through `@hey-research-lab/sdk` and nothing else — no page scraping, no
|
|
200
|
+
provider calls, no key embedded. The `x-hey-integration` header (`hey-virtuals-plugin/<version>`)
|
|
201
|
+
lets HEY count this plugin's calls. HEY's private quality gate stays authoritative: the plugin
|
|
202
|
+
relays what HEY publishes and computes no status, score or verdict of its own.
|
|
203
|
+
|
|
204
|
+
## What it does NOT prove
|
|
205
|
+
|
|
206
|
+
The plugin relays HEY's public research to an agent. A HEY answer is evidence with provenance:
|
|
207
|
+
activity status is a record of development, not a view on a token, and nothing it returns is
|
|
208
|
+
investment advice, a safety verdict or a recommendation. An unknown value means HEY does not know —
|
|
209
|
+
not zero. A paid ACP job buys delivery of the same public answer anyone can read free; it does not
|
|
210
|
+
make the answer true, current or advice, and it changes nothing on HEY.
|
|
211
|
+
|
|
212
|
+
HEY Research Lab is an independent research project and is not affiliated with, endorsed by or
|
|
213
|
+
partnered with Robinhood Markets, Inc. or Robinhood Chain. It is not affiliated with or endorsed by
|
|
214
|
+
Virtuals Protocol either.
|
|
215
|
+
|
|
216
|
+
## What it never does
|
|
217
|
+
|
|
218
|
+
- Never says a token is safe, never tells anyone to buy or sell, never predicts a price.
|
|
219
|
+
- Never profiles addresses, never calls them people, never follows one.
|
|
220
|
+
- Never fills an unknown with 0, false or "none".
|
|
221
|
+
- Never claims Robinhood affiliation.
|
|
222
|
+
- Never calls a provider, a write route or `POST /api/scan`; never embeds a key.
|
|
223
|
+
- ACP: never connects, registers or signs without the founder's configuration and
|
|
224
|
+
`HEY_ACP_ENABLE=1`; never logs or stores the signer key.
|
|
225
|
+
|
|
226
|
+
## Security
|
|
227
|
+
|
|
228
|
+
See [SECURITY.md](SECURITY.md). Network: HTTPS GETs to `https://heyresearch.xyz` only (and, for an
|
|
229
|
+
enabled ACP seller, the ACP SDK's own connections). No files are read or written. Peer dependencies
|
|
230
|
+
beyond the allowed set, with why: `@virtuals-protocol/game` (the framework this plugs into) and,
|
|
231
|
+
optional, `@virtuals-protocol/acp-node-v2` (the ACP client, loaded only when the seller starts).
|
|
232
|
+
|
|
233
|
+
## Contributing
|
|
234
|
+
|
|
235
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Tests run offline over saved fixtures with the network
|
|
236
|
+
blocked and the ACP client stubbed; `pnpm scan` checks for leaked secrets and attribution.
|
|
237
|
+
|
|
238
|
+
## Links
|
|
239
|
+
|
|
240
|
+
[Site](https://heyresearch.xyz) · [Developers](https://heyresearch.xyz/developers) ·
|
|
241
|
+
[Public API](https://heyresearch.xyz/docs/public-api) · [Agents guide](https://heyresearch.xyz/developers/agents) ·
|
|
242
|
+
[MCP](https://heyresearch.xyz/docs/mcp) · [SDK](https://www.npmjs.com/package/@hey-research-lab/sdk) ·
|
|
243
|
+
[Organisation](https://github.com/hey-research-lab) · [GAME SDK](https://github.com/game-by-virtuals/game-node) ·
|
|
244
|
+
[ACP SDK v2](https://www.npmjs.com/package/@virtuals-protocol/acp-node-v2) · Contact: hi@heyresearch.xyz
|
|
245
|
+
|
|
246
|
+
## Licence
|
|
247
|
+
|
|
248
|
+
MIT © 2026 HEY Research Lab
|
package/dist/acp.d.ts
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { FetchLike, HeyClient, HeyAgentResponse } from '@hey-research-lab/sdk';
|
|
2
|
+
import { inspect } from 'node:util';
|
|
3
|
+
import { JobRoomEntry, AssetToken } from '@virtuals-protocol/acp-node-v2';
|
|
4
|
+
|
|
5
|
+
/** How the plugin reaches HEY. Everything is optional: with nothing set it reads the public API anonymously. */
|
|
6
|
+
type HeyPluginOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* A HEY API key from heyresearch.xyz/account. Optional: it lifts the anonymous rate limit and
|
|
9
|
+
* nothing else. Defaults to `HEY_API_KEY` from the environment, which is sent to heyresearch.xyz
|
|
10
|
+
* only: with a custom `baseUrl`, pass the key here explicitly or none is sent. Sent as a bearer
|
|
11
|
+
* token, never logged.
|
|
12
|
+
*/
|
|
13
|
+
apiKey?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Defaults to https://heyresearch.xyz. Only for tests and local mocks: `https:` or
|
|
16
|
+
* `http://localhost` / `http://127.0.0.1`. It is not a network switch.
|
|
17
|
+
*/
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
/** For tests and exotic runtimes; the global `fetch` by default. */
|
|
20
|
+
fetchImpl?: FetchLike;
|
|
21
|
+
/** Milliseconds before a HEY read is abandoned; the SDK's default is 15 000. */
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
/** A ready client, when the host already has one. Overrides the four fields above. */
|
|
24
|
+
client?: HeyClient;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Settlement chains this scaffold allows. Both are mainnets the ACP v2 SDK
|
|
29
|
+
* (`@virtuals-protocol/acp-node-v2` 0.1.15) lists in `EVM_MAINNET_CHAINS`, with a USDC address
|
|
30
|
+
* and the ACP contract registered. Which one HEY settles on is the founder's decision; there is
|
|
31
|
+
* deliberately no default.
|
|
32
|
+
*/
|
|
33
|
+
declare const ACP_SETTLEMENT_CHAINS: {
|
|
34
|
+
readonly 8453: "Base";
|
|
35
|
+
readonly 4663: "Robinhood Chain";
|
|
36
|
+
};
|
|
37
|
+
type AcpSettlementChainId = keyof typeof ACP_SETTLEMENT_CHAINS;
|
|
38
|
+
/**
|
|
39
|
+
* The default price, in USDC per job: 0, the lowest value the ACP v2 SDK and the registry accept
|
|
40
|
+
* (the SDK's own seller example runs a 0 USDC offering). Pricing is the founder's decision: set
|
|
41
|
+
* `HEY_ACP_PRICE_USDC` to the same value as the offering on app.virtuals.io.
|
|
42
|
+
*/
|
|
43
|
+
declare const DEFAULT_PRICE_USDC = 0;
|
|
44
|
+
/** A typo guard, not a policy: a price above this is refused as a likely mistake. */
|
|
45
|
+
declare const MAX_PRICE_USDC = 1000;
|
|
46
|
+
declare const DEFAULT_OFFERING_NAME = "hey_builder_research";
|
|
47
|
+
/** Holds a secret so that logging, `JSON.stringify` and `util.inspect` never print it. */
|
|
48
|
+
declare class Secret {
|
|
49
|
+
#private;
|
|
50
|
+
constructor(value: string);
|
|
51
|
+
/** The only way to read the value; called once, when the wallet adapter is built. */
|
|
52
|
+
reveal(): string;
|
|
53
|
+
toString(): string;
|
|
54
|
+
toJSON(): string;
|
|
55
|
+
[inspect.custom](): string;
|
|
56
|
+
}
|
|
57
|
+
type HeyAcpConfig = {
|
|
58
|
+
/** `HEY_ACP_ENABLE=1`. Without it nothing connects, registers or signs. */
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
/** The agent wallet address shown on the agent's page on app.virtuals.io. */
|
|
61
|
+
walletAddress: `0x${string}`;
|
|
62
|
+
/** The agent wallet id shown on the same page. */
|
|
63
|
+
walletId: string;
|
|
64
|
+
/** The signer key from the agent's Signers tab (a Privy authorization key, not an EOA key). */
|
|
65
|
+
signer: Secret;
|
|
66
|
+
settlementChainId: AcpSettlementChainId;
|
|
67
|
+
priceUsdc: number;
|
|
68
|
+
offeringName: string;
|
|
69
|
+
/** Optional Base builder code from the agent's Settings tab. */
|
|
70
|
+
builderCode?: string;
|
|
71
|
+
};
|
|
72
|
+
declare class AcpConfigError extends Error {
|
|
73
|
+
readonly missing: string[];
|
|
74
|
+
readonly invalid: string[];
|
|
75
|
+
readonly code = "acp_not_configured";
|
|
76
|
+
constructor(missing: string[], invalid: string[]);
|
|
77
|
+
}
|
|
78
|
+
type AcpEnv = Record<string, string | undefined>;
|
|
79
|
+
/**
|
|
80
|
+
* Reads and checks the seller's configuration from the environment. Throws one `AcpConfigError`
|
|
81
|
+
* naming every missing or invalid variable, never their values.
|
|
82
|
+
*/
|
|
83
|
+
declare function loadHeyAcpConfig(env?: AcpEnv): HeyAcpConfig;
|
|
84
|
+
/** A one-line, secret-free description of the configuration for logs. */
|
|
85
|
+
declare function describeAcpConfig(config: HeyAcpConfig): string;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* What one HEY read produced, before a framework wraps it.
|
|
89
|
+
*
|
|
90
|
+
* - `answer`: HEY answered about a project or the chain.
|
|
91
|
+
* - `not_found` / `ambiguous`: HEY answered that it holds no such project, or several match. These
|
|
92
|
+
* are answers too (a reading of HEY's index), so `ok` is true.
|
|
93
|
+
* - `invalid` / `error`: the request was malformed, refused, or HEY could not be read.
|
|
94
|
+
*/
|
|
95
|
+
type HeyOutcome = 'answer' | 'not_found' | 'ambiguous' | 'invalid' | 'error';
|
|
96
|
+
type HeyResult = {
|
|
97
|
+
ok: boolean;
|
|
98
|
+
outcome: HeyOutcome;
|
|
99
|
+
/** The text an agent reads: HEY's semantics kept, ending with the attribution line. */
|
|
100
|
+
text: string;
|
|
101
|
+
projectUrl?: string;
|
|
102
|
+
asOf?: string;
|
|
103
|
+
citation?: HeyAgentResponse['citation'];
|
|
104
|
+
error?: {
|
|
105
|
+
code: string;
|
|
106
|
+
message: string;
|
|
107
|
+
retryable: boolean;
|
|
108
|
+
status?: number;
|
|
109
|
+
retryAfterSeconds?: number;
|
|
110
|
+
requestId?: string;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/** What to enter on app.virtuals.io when adding the offering. The price is not here: it is the founder's. */
|
|
115
|
+
declare const HEY_ACP_OFFERING: {
|
|
116
|
+
readonly name: "hey_builder_research";
|
|
117
|
+
readonly description: string;
|
|
118
|
+
readonly requirement: {
|
|
119
|
+
readonly type: "object";
|
|
120
|
+
readonly additionalProperties: false;
|
|
121
|
+
readonly required: readonly ["query"];
|
|
122
|
+
readonly properties: {
|
|
123
|
+
readonly query: {
|
|
124
|
+
readonly type: "string";
|
|
125
|
+
readonly minLength: 2;
|
|
126
|
+
readonly maxLength: 200;
|
|
127
|
+
readonly description: "A HEY project slug, a $TICKER, a project name, or a 0x token/contract address on Robinhood Chain.";
|
|
128
|
+
};
|
|
129
|
+
readonly chainId: {
|
|
130
|
+
readonly type: "integer";
|
|
131
|
+
readonly const: 4663;
|
|
132
|
+
readonly description: "Optional; only 4663 (Robinhood Chain) is supported.";
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
readonly deliverable: string;
|
|
137
|
+
/** The registry's floor is 5 minutes (`MIN_SLA_MINS`); a HEY read takes seconds. */
|
|
138
|
+
readonly slaMinutes: 5;
|
|
139
|
+
};
|
|
140
|
+
declare const DELIVERABLE_SCHEMA = "hey.virtuals-acp-deliverable/v1";
|
|
141
|
+
type ParsedRequirement = {
|
|
142
|
+
ok: true;
|
|
143
|
+
query: string;
|
|
144
|
+
} | {
|
|
145
|
+
ok: false;
|
|
146
|
+
code: 'invalid_requirement' | 'unsupported_chain';
|
|
147
|
+
message: string;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* A buyer's requirement: `{"query": "...", "chainId": 4663}` as the offering's schema asks, or a
|
|
151
|
+
* bare string. Only `query` and `chainId` are read; anything else is ignored, never merged.
|
|
152
|
+
*/
|
|
153
|
+
declare function parseRequirement(content: string): ParsedRequirement;
|
|
154
|
+
/** The deliverable the buyer receives: HEY's report, its link, citation and as-of time, and the attribution. */
|
|
155
|
+
declare function buildDeliverable(query: string, result: HeyResult, deliveredAt: Date): string;
|
|
156
|
+
/**
|
|
157
|
+
* The part of an ACP v2 `JobSession` the seller uses. `JobSession` satisfies it (a type test holds
|
|
158
|
+
* that), and tests pass a stub, so no test ever builds a real session, wallet or connection.
|
|
159
|
+
*/
|
|
160
|
+
type AcpSessionLike = {
|
|
161
|
+
readonly jobId: string;
|
|
162
|
+
readonly chainId: number;
|
|
163
|
+
readonly status: string;
|
|
164
|
+
readonly job: {
|
|
165
|
+
readonly description: string;
|
|
166
|
+
} | null;
|
|
167
|
+
readonly entries: readonly JobRoomEntry[];
|
|
168
|
+
setBudget(amount: AssetToken): Promise<void>;
|
|
169
|
+
submit(deliverable: string): Promise<void>;
|
|
170
|
+
reject(reason: string): Promise<void>;
|
|
171
|
+
sendMessage(content: string): Promise<void>;
|
|
172
|
+
};
|
|
173
|
+
type HeyAcpHandlerDeps = {
|
|
174
|
+
offeringName: string;
|
|
175
|
+
priceUsdc: number;
|
|
176
|
+
/** `AssetToken.usdc` from the ACP SDK; injected so tests never load it. */
|
|
177
|
+
usdc: (amount: number, chainId: number) => AssetToken;
|
|
178
|
+
/** The HEY read that answers a job (the same `researchProject` the GAME worker uses). */
|
|
179
|
+
research: (query: string) => Promise<HeyResult>;
|
|
180
|
+
log?: (message: string) => void;
|
|
181
|
+
now?: () => Date;
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* The seller's state machine, after the ACP v2 seller example:
|
|
185
|
+
*
|
|
186
|
+
* requirement message (status open) → check offering, chain and that HEY holds an answer,
|
|
187
|
+
* then `setBudget` (or `reject` before anything is paid)
|
|
188
|
+
* job.funded → read HEY again and `submit` the deliverable
|
|
189
|
+
* (or `reject`, which returns the funds, if HEY is unreachable)
|
|
190
|
+
* job.completed / rejected / expired → log only
|
|
191
|
+
*
|
|
192
|
+
* The requirement is read back from the session's own history at `job.funded`, so a restarted
|
|
193
|
+
* seller resumes a funded job without any state of its own.
|
|
194
|
+
*/
|
|
195
|
+
declare function createHeyAcpEntryHandler(deps: HeyAcpHandlerDeps): (session: AcpSessionLike, entry: JobRoomEntry) => Promise<void>;
|
|
196
|
+
|
|
197
|
+
/** The part of an ACP v2 `AcpAgent` the seller uses; `AcpAgent` satisfies it (a type test holds that). */
|
|
198
|
+
type AcpAgentLike = {
|
|
199
|
+
on(event: 'entry', handler: (session: AcpSessionLike, entry: JobRoomEntry) => void | Promise<void>): unknown;
|
|
200
|
+
start(onConnected?: () => void): Promise<void>;
|
|
201
|
+
stop(): Promise<void>;
|
|
202
|
+
getAddress(): Promise<string>;
|
|
203
|
+
};
|
|
204
|
+
type CreateAcpAgentInput = {
|
|
205
|
+
walletAddress: `0x${string}`;
|
|
206
|
+
walletId: string;
|
|
207
|
+
signer: Secret;
|
|
208
|
+
chainId: AcpSettlementChainId;
|
|
209
|
+
builderCode?: string;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Everything the seller needs from the ACP SDK, behind one seam: building the agent (the only step
|
|
213
|
+
* that touches the wallet) and making a USDC amount. Tests replace it entirely.
|
|
214
|
+
*/
|
|
215
|
+
type AcpRuntime = {
|
|
216
|
+
createAgent(input: CreateAcpAgentInput): Promise<AcpAgentLike>;
|
|
217
|
+
usdc(amount: number, chainId: number): AssetToken;
|
|
218
|
+
};
|
|
219
|
+
declare class AcpSdkMissingError extends Error {
|
|
220
|
+
readonly code = "acp_sdk_missing";
|
|
221
|
+
constructor();
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Loads `@virtuals-protocol/acp-node-v2` on first use (never at import time) and adapts it to
|
|
225
|
+
* `AcpRuntime`: a Privy-managed agent wallet through `PrivyAlchemyEvmProviderAdapter`, on the one
|
|
226
|
+
* settlement chain configured, and `AcpAgent.create({ evmProvider })`.
|
|
227
|
+
*/
|
|
228
|
+
declare function loadAcpRuntime(): Promise<AcpRuntime>;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* `@hey-research-lab/virtuals-plugin/acp`: HEY as an Agent Commerce Protocol provider (seller)
|
|
232
|
+
* offering one service, "HEY builder research on a Robinhood Chain project/contract".
|
|
233
|
+
*
|
|
234
|
+
* A scaffold the founder switches on: nothing here connects, registers or signs until
|
|
235
|
+
* `startHeyAcpSeller` runs with a complete configuration and `HEY_ACP_ENABLE=1`.
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
type StartHeyAcpSellerOptions = HeyPluginOptions & {
|
|
239
|
+
/** A checked configuration; read from `env` (default `process.env`) when absent. */
|
|
240
|
+
config?: HeyAcpConfig;
|
|
241
|
+
env?: AcpEnv;
|
|
242
|
+
/** The ACP SDK seam; `loadAcpRuntime()` by default. Tests pass a stub. */
|
|
243
|
+
runtime?: AcpRuntime;
|
|
244
|
+
/** Where progress lines go; never receives a secret. `console.log` by default. */
|
|
245
|
+
log?: (message: string) => void;
|
|
246
|
+
now?: () => Date;
|
|
247
|
+
};
|
|
248
|
+
type HeyAcpSeller = {
|
|
249
|
+
agent: AcpAgentLike;
|
|
250
|
+
config: HeyAcpConfig;
|
|
251
|
+
stop(): Promise<void>;
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* Builds the agent wallet adapter, registers the HEY entry handler and starts listening for jobs.
|
|
255
|
+
* Refuses, before loading the ACP SDK, when the configuration is incomplete or not enabled.
|
|
256
|
+
*/
|
|
257
|
+
declare function startHeyAcpSeller(options?: StartHeyAcpSellerOptions): Promise<HeyAcpSeller>;
|
|
258
|
+
|
|
259
|
+
export { ACP_SETTLEMENT_CHAINS, type AcpAgentLike, AcpConfigError, type AcpEnv, type AcpRuntime, AcpSdkMissingError, type AcpSessionLike, type AcpSettlementChainId, type CreateAcpAgentInput, DEFAULT_OFFERING_NAME, DEFAULT_PRICE_USDC, DELIVERABLE_SCHEMA, HEY_ACP_OFFERING, type HeyAcpConfig, type HeyAcpHandlerDeps, type HeyAcpSeller, MAX_PRICE_USDC, type ParsedRequirement, Secret, type StartHeyAcpSellerOptions, buildDeliverable, createHeyAcpEntryHandler, describeAcpConfig, loadAcpRuntime, loadHeyAcpConfig, parseRequirement, startHeyAcpSeller };
|