botanary-mcp 0.3.0 → 0.4.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/README.md +140 -15
- package/dist/src/api-client.js +38 -5
- package/dist/src/api-client.js.map +1 -1
- package/dist/src/diagnose.js.map +1 -1
- package/dist/src/identity/backends/libsecret.js +4 -4
- package/dist/src/identity/backends/libsecret.js.map +1 -1
- package/dist/src/identity/backends/macos-keychain.js +5 -5
- package/dist/src/identity/backends/macos-keychain.js.map +1 -1
- package/dist/src/identity/backends/select.js +16 -5
- package/dist/src/identity/backends/select.js.map +1 -1
- package/dist/src/identity/backends/types.js +3 -1
- package/dist/src/identity/backends/types.js.map +1 -1
- package/dist/src/identity/backends/windows-dpapi.js +2 -2
- package/dist/src/identity/backends/windows-dpapi.js.map +1 -1
- package/dist/src/package-version.js +50 -0
- package/dist/src/package-version.js.map +1 -0
- package/dist/src/runtime.js +81 -1
- package/dist/src/runtime.js.map +1 -1
- package/dist/src/server.js +49 -6
- package/dist/src/server.js.map +1 -1
- package/dist/src/tools.js +1014 -24
- package/dist/src/tools.js.map +1 -1
- package/dist/src/wallet/api-get.js +68 -0
- package/dist/src/wallet/api-get.js.map +1 -0
- package/dist/src/wallet/browser.js +75 -0
- package/dist/src/wallet/browser.js.map +1 -0
- package/dist/src/wallet/composites.js +52 -0
- package/dist/src/wallet/composites.js.map +1 -0
- package/dist/src/wallet/login.js +138 -0
- package/dist/src/wallet/login.js.map +1 -0
- package/dist/src/wallet/payloads.js +53 -0
- package/dist/src/wallet/payloads.js.map +1 -0
- package/dist/src/wallet/routes.manifest.js +120 -0
- package/dist/src/wallet/routes.manifest.js.map +1 -0
- package/dist/src/wallet/send.js +116 -0
- package/dist/src/wallet/send.js.map +1 -0
- package/dist/src/wallet/session-store.js +109 -0
- package/dist/src/wallet/session-store.js.map +1 -0
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
# botanary-mcp
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
A local MCP server that lets an outside coding agent - Claude Code, Codex, Cursor, or something you
|
|
4
|
+
wrote yourself - act on a Botanary account. It has **two lanes**, backed by two independent credentials:
|
|
5
|
+
|
|
6
|
+
- **The agent lane.** This machine holds its own secp256k1 signing key, proves who it is, pairs with a
|
|
7
|
+
Botanary account, reads its balance, and spends *unattended* under whatever grant its owner gave it -
|
|
8
|
+
all without Botanary ever holding, seeing, or backing up that key.
|
|
9
|
+
- **The wallet lane.** The human owner logs in through their own browser (`wallet_login`) - the same
|
|
10
|
+
provider consent they already use - and this machine holds an opaque, revocable session that can read
|
|
11
|
+
and *build* on the owner's behalf, but **can never sign as the owner**. Every owner-authorized money
|
|
12
|
+
movement ends in a signature the owner makes themselves, in their own browser, against their own
|
|
13
|
+
embedded wallet.
|
|
14
|
+
|
|
15
|
+
**These are independent credentials that can point at different Botanary accounts.** The agent key is
|
|
16
|
+
paired to whatever account its owner paired it to; the wallet session operates on whatever account was
|
|
17
|
+
picked at login. Nothing forces them to agree - `wallet_status` prints both bindings side by side and
|
|
18
|
+
flags a mismatch as a first-class finding, and `wallet_send`'s own lane arbitration (below) refuses to
|
|
19
|
+
let a mandate on one account authorize a spend on the other, no matter how "helpful" that would be.
|
|
20
|
+
|
|
21
|
+
## Tools
|
|
22
|
+
|
|
23
|
+
`botanary-mcp` advertises a **subset** of its tools at any moment - a small starter set when nothing is
|
|
24
|
+
logged in yet, the wallet tools once `wallet_login` succeeds, the agent tools once this machine has a
|
|
25
|
+
local identity - and pushes `notifications/tools/list_changed` when that set changes. This is a listing
|
|
26
|
+
optimization, not a security boundary: every tool below is always *reachable* by name, and a hidden one
|
|
27
|
+
called anyway answers honestly ("log in first") rather than pretending not to exist. See "Why the
|
|
28
|
+
advertised tool list changes" further down.
|
|
29
|
+
|
|
30
|
+
### Agent lane (this machine acting as a connected agent, under a grant)
|
|
9
31
|
|
|
10
32
|
| Tool | What it does |
|
|
11
33
|
|---|---|
|
|
@@ -25,6 +47,81 @@ The tools this server exposes:
|
|
|
25
47
|
| `what_may_i_do` | Renders the grant in plain terms, or an honest "nothing yet" - a convenience read, never the check. |
|
|
26
48
|
| `forget` | STEP 1 of 2: preview what would be destroyed and get a single-use confirmation token. Deletes nothing on its own. |
|
|
27
49
|
| `confirm_forget` | STEP 2 of 2: actually delete the agent key from this machine. Requires the token from `forget`. |
|
|
50
|
+
| `list_apis` | Calls `GET /apis/list` - the paid (x402) third-party API endpoints this agent may call on a chain, each with its live price and this agent's remaining budget. Reads only; calls nothing and spends nothing. |
|
|
51
|
+
| `call_api` | Calls `POST /apis/calls` - call one of those endpoints and pay for it, inside the budget the OWNER committed on-chain (`X402PaymentValidator`). Signs the EIP-3009 authorization with this agent's own key; the owner never signs, and the on-chain budget - not this tool - is what bounds it. A response marked `simulated` is synthetic test data, and says so. |
|
|
52
|
+
| `get_api_budget` | Calls `GET /apis/budget` - remaining authorizations, per-call maximum, expiry and epoch for this agent on a chain. Does NOT say which endpoints are enabled (`list_apis` does). |
|
|
53
|
+
|
|
54
|
+
### Wallet lane (the human owner's own session, after `wallet_login`)
|
|
55
|
+
|
|
56
|
+
| Tool | What it does |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `wallet_login` | Device-style browser login: opens the owner's browser, waits for them to authorize, stores the resulting session in the OS keychain. No browser available (SSH, a container)? Prints the URL and code instead - same flow, no second code path. |
|
|
59
|
+
| `wallet_logout` | Revokes the session (`DELETE /auth/session`) and clears it locally - even if the network call fails, so a dead network can never strand a live credential on disk. |
|
|
60
|
+
| `wallet_status` | Prints the wallet session's account AND the agent's bound account side by side, and flags a mismatch explicitly. Safe to call regardless of which lane(s), if any, are set up. |
|
|
61
|
+
| `wallet_use_account` | Switch which of the owner's accounts every subsequent `wallet_*` call uses - including which account `wallet_send`'s lane arbitration compares a paired agent's mandate against. Validates the id against `GET /accounts` first; persists to the same keychain item `wallet_login` writes. |
|
|
62
|
+
| `wallet_send` | Sends tokens from the **owner's own account**. See "Lane arbitration" below - this is the tool the safety property in this README is really about. |
|
|
63
|
+
| `wallet_portfolio` | Reads `GET /balance` + `GET /chains`: balances across all chains and each chain's tier (watch/basic/botanary). Raw balance and tier data - it does not itself evaluate whether a send would succeed. |
|
|
64
|
+
| `wallet_activity` | Reads `GET /history`: the owner's recent sends, swaps, and yield transactions with timestamps, amounts, and final status. |
|
|
65
|
+
| `wallet_markets` | Reads `GET /markets/tokens`: public market data (prices, symbols) - not account-scoped. |
|
|
66
|
+
| `wallet_yield` | Reads `GET /yield/pools` + `GET /yield/shortlist` + `GET /farm/positions`: available pools, a recommended shortlist, and this account's farming positions. `shortlist` is ranked off the caller's own holdings server-side and is NOT scoped to the account `wallet_use_account` most recently switched to - the result's own `scopeCaveats` field says so explicitly. |
|
|
67
|
+
| `wallet_mandates` | Reads `GET /delegations` + `GET /mandates`: what the agent lane may spend unattended - active delegations with budget info, and any outstanding mandates. |
|
|
68
|
+
| `wallet_agents` | Reads `GET /agents` + `GET /agents/requests`: connected agents and any pending approval requests they've filed. |
|
|
69
|
+
| `wallet_api_get` | Read ANY `GET` endpoint in Botanary's frozen OpenAPI contract, authenticated as the owner. **GET-only, deliberately** - see below. |
|
|
70
|
+
|
|
71
|
+
## Lane arbitration: how `wallet_send` decides who signs
|
|
72
|
+
|
|
73
|
+
`wallet_send` resolves one of exactly two lanes, in this order, every time it's called:
|
|
74
|
+
|
|
75
|
+
1. **This machine holds a paired agent identity with a live mandate that covers the action, ON THE SAME
|
|
76
|
+
ACCOUNT the wallet session is presently using.** Then it signs locally with the agent's session key
|
|
77
|
+
and relays - no browser, no human click.
|
|
78
|
+
2. **Otherwise** - no paired agent, no live grant, the mandate is out of bounds for this exact request
|
|
79
|
+
(wrong chain, over budget, over the per-action cap), or **the mandate is on a DIFFERENT account** -
|
|
80
|
+
it parks a typed intent (`POST /sign-requests`), opens the owner's browser to review and sign it
|
|
81
|
+
there, and polls to a terminal result.
|
|
82
|
+
|
|
83
|
+
**The same-account condition is not incidental - it is the whole safety argument.** The two credentials
|
|
84
|
+
are independent (see the top of this README): an agent paired to one account and a browser session open
|
|
85
|
+
on another is not a bug to route around, it's the scenario this check exists to catch. Without it, "it
|
|
86
|
+
signed without asking me" could mean money moved out of an account the owner was not even looking at -
|
|
87
|
+
which is exactly what happened once (an agent paired to an empty account while the owner's real funds
|
|
88
|
+
sat elsewhere, surfacing as a cryptic `AA21 didn't pay prefund` three Postgres queries later). Every
|
|
89
|
+
`wallet_send` result names the lane it took (`lane: "agent" | "browser"`), and when a mandate existed but
|
|
90
|
+
was refused for the agent lane, the result says exactly why.
|
|
91
|
+
|
|
92
|
+
A local balance/chain-tier check runs before opening a browser, purely as a courtesy so a doomed request
|
|
93
|
+
doesn't cost the owner a browser trip - **it is never the authorization.** The real check is the build
|
|
94
|
+
the browser page itself does against the live backend, and beneath that, on-chain enforcement. A green
|
|
95
|
+
result from this preflight proves nothing by itself, the same discipline `propose_payment`'s own
|
|
96
|
+
client-side bounds check documents on the agent lane.
|
|
97
|
+
|
|
98
|
+
## `wallet_api_get` is GET-only, deliberately - and there is no `api_post`
|
|
99
|
+
|
|
100
|
+
Every path is validated against a manifest generated from the frozen OpenAPI contract
|
|
101
|
+
(`openapi/botanary-v1.yaml`, via `pnpm generate:routes` - see "Development" below) before anything
|
|
102
|
+
reaches the network. An undocumented path, or any method other than `GET`, is refused.
|
|
103
|
+
|
|
104
|
+
**There is no write counterpart, and there must not be one.** A generic `api_post` would let a model
|
|
105
|
+
reach *any* mutation - freeze the account, remove a signer, drain a grant - with no typed intent, no
|
|
106
|
+
review panel, and no lane arbitration. Every write instead goes through `wallet_send` (or a future
|
|
107
|
+
`wallet_swap`): a typed intent the owner reviews and signs in their own browser, or the agent lane's own
|
|
108
|
+
on-chain-bound mandate. `wallet_api_get` is deliberately incapable of being that shortcut.
|
|
109
|
+
|
|
110
|
+
## Why the advertised tool list changes
|
|
111
|
+
|
|
112
|
+
This package ships close to twenty tools. Advertising all of them at once - most of which are unusable
|
|
113
|
+
in the caller's *current* state (no wallet session yet, no paired agent yet) - is exactly the kind of
|
|
114
|
+
overlapping-description clutter that degrades tool selection in a client with many MCP servers attached.
|
|
115
|
+
So the advertised list is gated by state: a small starter set (`wallet_login`, `get_pairing_code`,
|
|
116
|
+
`diagnose`, `wallet_status`, ...) is always visible; the wallet tools appear once `wallet_login`
|
|
117
|
+
succeeds; the agent tools appear once this machine has a local identity. `wallet_login`/`wallet_logout`
|
|
118
|
+
push `notifications/tools/list_changed` so a client that implements it can re-fetch immediately.
|
|
119
|
+
|
|
120
|
+
**Not every client implements that notification, and a hidden tool must still work when called.** If
|
|
121
|
+
your client cached the list from before you logged in and you (or the model) call `wallet_send` anyway,
|
|
122
|
+
it does not 404 or pretend the tool doesn't exist - it answers honestly ("not logged in - run
|
|
123
|
+
wallet_login first"). The gating is a UX optimization on top of a surface that is always fully reachable,
|
|
124
|
+
never a second, hidden permission system.
|
|
28
125
|
|
|
29
126
|
## Add it to your agent
|
|
30
127
|
|
|
@@ -79,10 +176,14 @@ Claude Desktop is likewise config-file only - add this block to
|
|
|
79
176
|
}
|
|
80
177
|
```
|
|
81
178
|
|
|
82
|
-
Restart the client so it picks up the new server.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
179
|
+
Restart the client so it picks up the new server. From here, two independent things you can ask for:
|
|
180
|
+
|
|
181
|
+
- **"What's your Botanary identity / pairing code?"** - the AGENT lane. It calls `get_identity` /
|
|
182
|
+
`get_pairing_code` and reads the key straight out of wherever this machine's OS keeps secrets. The
|
|
183
|
+
first call generates the key; nothing before that point touches disk or asks any question.
|
|
184
|
+
- **"Log me into Botanary"** - the WALLET lane. It calls `wallet_login`, opens your own browser to the
|
|
185
|
+
provider login you already use, and waits for you to authorize. Nothing is generated on this machine;
|
|
186
|
+
the session it stores is revocable from Botanary's Settings → Connected apps at any time.
|
|
86
187
|
|
|
87
188
|
## What a freshly-connected agent can and cannot do
|
|
88
189
|
|
|
@@ -175,6 +276,23 @@ Two more things worth knowing:
|
|
|
175
276
|
metadata file (address / public key / fingerprint / when it was created / which backend holds the key)
|
|
176
277
|
that's written once alongside the real key and never contains it.
|
|
177
278
|
|
|
279
|
+
### The links this server opens are never handed to a shell
|
|
280
|
+
|
|
281
|
+
Two flows end with this process opening a URL in the owner's own browser: `wallet_login`'s
|
|
282
|
+
`verificationUrl` and `wallet_send`'s browser handoff. **Both URLs are chosen by the backend**, which
|
|
283
|
+
makes the launcher a place where "a compromised backend fails to availability, never to authority"
|
|
284
|
+
could quietly stop being true - a URL interpolated into a shell command string is arbitrary code
|
|
285
|
+
execution on the owner's laptop, and `"..."` quoting does not prevent it (`$(...)` and backticks still
|
|
286
|
+
expand inside double quotes).
|
|
287
|
+
|
|
288
|
+
So `src/wallet/browser.ts` uses `execFile`, never `exec`: the opener is spawned directly with an argv
|
|
289
|
+
array, so a URL is one opaque argument no matter what characters are in it, and no shell exists to
|
|
290
|
+
interpret them. On Windows that means `rundll32 url.dll,FileProtocolHandler` rather than `start`, which
|
|
291
|
+
is a `cmd.exe` builtin and would have needed one. On top of that, the URL must parse as an absolute
|
|
292
|
+
`http`/`https` URL before anything is launched at all - which also refuses a bare `-flag` that
|
|
293
|
+
`open`/`xdg-open` would otherwise read as its own argument. `test/wallet-browser.spec.ts` pins both
|
|
294
|
+
halves: the argv shape, and that the real spawn primitive leaves a substitution payload literal.
|
|
295
|
+
|
|
178
296
|
### Deleting the key on its own machine
|
|
179
297
|
|
|
180
298
|
```bash
|
|
@@ -231,6 +349,10 @@ pnpm dev # run bin/botanary-mcp.ts directly, watching for changes (no
|
|
|
231
349
|
pnpm typecheck # tsc --noEmit, strict (matches the backend repo's compiler settings)
|
|
232
350
|
pnpm test # vitest - no network, no real keychain (every OS call is mocked; see
|
|
233
351
|
# test/fixtures/fake-exec.ts and test/fixtures/fake-backend.ts)
|
|
352
|
+
pnpm generate:routes # regenerate src/wallet/routes.manifest.ts from the sibling botanary-be
|
|
353
|
+
# checkout's openapi/botanary-v1.yaml - run this and commit the result whenever
|
|
354
|
+
# the contract changes; it never runs automatically (a published install has no
|
|
355
|
+
# sibling openapi/ directory to read it from)
|
|
234
356
|
```
|
|
235
357
|
|
|
236
358
|
`BOTANARY_MCP_HOME` overrides where the non-secret metadata file (and the file-fallback secret, if it's
|
|
@@ -247,15 +369,18 @@ What stays out on purpose:
|
|
|
247
369
|
|
|
248
370
|
- **An agent-initiated disconnect** - `DELETE /agents/{id}` is owner-only and stays that way. `forget`
|
|
249
371
|
deletes a local key; it never closes the owner-side connection, and the two must not be confused.
|
|
250
|
-
- **
|
|
251
|
-
policy, grant another agent access, or unfreeze the account - not because those endpoints
|
|
252
|
-
call, but because an agent's grant is authority to spend inside a fence, never authority to
|
|
253
|
-
fence. There is no tool here that could be talked into trying.
|
|
372
|
+
- **AGENT-LANE authority beyond a grant.** Nothing the agent lane does can add or remove a signer, write
|
|
373
|
+
or change a policy, grant another agent access, or unfreeze the account - not because those endpoints
|
|
374
|
+
are hard to call, but because an agent's grant is authority to spend inside a fence, never authority to
|
|
375
|
+
move the fence. There is no agent-lane tool here that could be talked into trying.
|
|
254
376
|
- **A cached or session-spanning bounds check as the real gate.** `propose_payment`'s pre-check (and
|
|
255
377
|
`what_may_i_do`'s rendering) reads `GET /agents/me` fresh via `AgentRuntime.me()` and refuses using
|
|
256
378
|
whatever the backend reports at that moment - it never assumes a bound it read earlier still holds.
|
|
257
379
|
The chain is still the only real enforcement either way (see "The bound it reads is a convenience, not
|
|
258
|
-
the check" above).
|
|
380
|
+
the check" above). The wallet lane's own `wallet_send` makes the SAME promise for the mandate lane it
|
|
381
|
+
can take (see "Lane arbitration" above), and its browser-lane fallback is likewise never a shortcut:
|
|
382
|
+
`wallet_api_get` is GET-only with no write counterpart, so every wallet-lane write terminates in the
|
|
383
|
+
owner's own browser signature, not in anything this package executes on its own.
|
|
259
384
|
|
|
260
385
|
`src/runtime.ts`'s `AgentRuntime` is the seam every tool in `src/tools.ts` is built on: it owns identity,
|
|
261
386
|
signing (`store.sign()`/`store.signHash()`), a cached-with-retry agent session, and one method per
|
package/dist/src/api-client.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export class BotanaryApiError extends Error {
|
|
6
6
|
status;
|
|
7
7
|
details;
|
|
8
|
+
retryAfterSeconds;
|
|
8
9
|
constructor(message, status,
|
|
9
10
|
/**
|
|
10
11
|
* The backend's own `error.details` blob, carried through rather than flattened into the message.
|
|
@@ -13,10 +14,20 @@ export class BotanaryApiError extends Error {
|
|
|
13
14
|
* Keeping the object means a handler keys off a field the backend guarantees instead of a sentence it
|
|
14
15
|
* is free to reword. Null whenever the response carried none.
|
|
15
16
|
*/
|
|
16
|
-
details = null
|
|
17
|
+
details = null,
|
|
18
|
+
/**
|
|
19
|
+
* The `Retry-After` header's value in SECONDS, when the server sent one (429/503 carry it). Null
|
|
20
|
+
* otherwise. Kept as a first-class field because a caller that wants to survive a rate limit -
|
|
21
|
+
* `wallet/login.ts`'s poll loop is the one that must - cannot see response headers otherwise, and
|
|
22
|
+
* guessing a backoff when the server told you the exact number is how a retry storm starts.
|
|
23
|
+
* Only the numeric (delta-seconds) form is parsed; the HTTP-date form yields null, and the caller
|
|
24
|
+
* falls back to its own backoff rather than mis-parsing a date as a duration.
|
|
25
|
+
*/
|
|
26
|
+
retryAfterSeconds = null) {
|
|
17
27
|
super(message);
|
|
18
28
|
this.status = status;
|
|
19
29
|
this.details = details;
|
|
30
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
20
31
|
this.name = 'BotanaryApiError';
|
|
21
32
|
}
|
|
22
33
|
}
|
|
@@ -37,16 +48,38 @@ export class BotanaryApiClient {
|
|
|
37
48
|
async get(path, token) {
|
|
38
49
|
return this.#request('GET', path, undefined, token);
|
|
39
50
|
}
|
|
51
|
+
/** DELETE request for logout and cleanup operations. No body, authenticated with optional token. */
|
|
52
|
+
async delete(path, token) {
|
|
53
|
+
return this.#request('DELETE', path, undefined, token);
|
|
54
|
+
}
|
|
40
55
|
async #request(method, path, body, token) {
|
|
41
56
|
const res = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
42
57
|
method,
|
|
43
58
|
headers: { 'content-type': 'application/json', ...(token ? { authorization: `Bearer ${token}` } : {}) },
|
|
44
59
|
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
45
60
|
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
// Skip body parsing for 204 No Content and other empty responses. DELETE /auth/session returns
|
|
62
|
+
// 204 with no body; parsing would throw SyntaxError. Check status first, then try to parse only
|
|
63
|
+
// if there might be content.
|
|
64
|
+
let json;
|
|
65
|
+
if (res.status !== 204 && res.headers.get('content-length') !== '0') {
|
|
66
|
+
try {
|
|
67
|
+
json = (await res.json());
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// If parsing fails on a non-empty response, treat as a parsing error but continue to
|
|
71
|
+
// check res.ok so we surface the right error
|
|
72
|
+
json = undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
// Numeric delta-seconds only - `Number.parseInt` on an HTTP-date ("Wed, 21 Oct 2015 07:28:00 GMT")
|
|
77
|
+
// yields NaN, which normalizes to null rather than a nonsense wait.
|
|
78
|
+
const rawRetryAfter = res.headers.get('retry-after');
|
|
79
|
+
const retryAfterSeconds = rawRetryAfter != null ? Number.parseInt(rawRetryAfter, 10) : Number.NaN;
|
|
80
|
+
throw new BotanaryApiError(json?.error?.message ?? `${path} failed with ${res.status}`, res.status, json?.error?.details ?? null, Number.isFinite(retryAfterSeconds) && retryAfterSeconds >= 0 ? retryAfterSeconds : null);
|
|
81
|
+
}
|
|
82
|
+
return (json ?? {});
|
|
50
83
|
}
|
|
51
84
|
}
|
|
52
85
|
//# sourceMappingURL=api-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"AAAA;;;+DAG+D;AAC/D,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAG9B;IAQA;
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/src/diagnose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../src/diagnose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../src/diagnose.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@ import { redactSecret } from '../redact.js';
|
|
|
9
9
|
// bare containers and plenty of real dev machines don't have one - isAvailable() below treats that as
|
|
10
10
|
// "unavailable" so store.ts falls through to the file fallback, rather than failing outright.
|
|
11
11
|
const NOT_FOUND_CODES = new Set([1]); // secret-tool lookup exits 1 (empty stdout) when there's no match.
|
|
12
|
-
export function createLibsecretBackend(exec = nodeExec) {
|
|
12
|
+
export function createLibsecretBackend(exec = nodeExec, accountName = ACCOUNT_NAME, serviceName = SERVICE_NAME) {
|
|
13
13
|
return {
|
|
14
14
|
id: 'libsecret',
|
|
15
15
|
label: 'Linux Secret Service (libsecret)',
|
|
@@ -28,7 +28,7 @@ export function createLibsecretBackend(exec = nodeExec) {
|
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
30
|
async save(secret) {
|
|
31
|
-
const r = await exec('secret-tool', ['store', '--label=Botanary agent identity', 'service',
|
|
31
|
+
const r = await exec('secret-tool', ['store', '--label=Botanary agent identity', 'service', serviceName, 'account', accountName], { input: secret });
|
|
32
32
|
if (r.code !== 0) {
|
|
33
33
|
// secret-tool doesn't echo stdin back on error, but redact defensively anyway - this backend
|
|
34
34
|
// should never be the one place that skips it.
|
|
@@ -36,7 +36,7 @@ export function createLibsecretBackend(exec = nodeExec) {
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
async load() {
|
|
39
|
-
const r = await exec('secret-tool', ['lookup', 'service',
|
|
39
|
+
const r = await exec('secret-tool', ['lookup', 'service', serviceName, 'account', accountName]);
|
|
40
40
|
if (r.code !== 0) {
|
|
41
41
|
if (NOT_FOUND_CODES.has(r.code) && !r.stderr.trim())
|
|
42
42
|
return null;
|
|
@@ -46,7 +46,7 @@ export function createLibsecretBackend(exec = nodeExec) {
|
|
|
46
46
|
return value.length > 0 ? value : null;
|
|
47
47
|
},
|
|
48
48
|
async delete() {
|
|
49
|
-
const r = await exec('secret-tool', ['clear', 'service',
|
|
49
|
+
const r = await exec('secret-tool', ['clear', 'service', serviceName, 'account', accountName]);
|
|
50
50
|
// secret-tool clear exits 0 whether or not anything was there - nothing to tolerate specially.
|
|
51
51
|
if (r.code !== 0) {
|
|
52
52
|
throw new KeyBackendError('libsecret', 'delete', r.stderr || `exit ${r.code}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libsecret.js","sourceRoot":"","sources":["../../../../src/identity/backends/libsecret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,YAAY,EAAmB,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,gGAAgG;AAChG,4FAA4F;AAC5F,4FAA4F;AAC5F,EAAE;AACF,wGAAwG;AACxG,sGAAsG;AACtG,8FAA8F;AAC9F,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mEAAmE;AAEzG,MAAM,UAAU,sBAAsB,CAAC,OAAa,QAAQ;
|
|
1
|
+
{"version":3,"file":"libsecret.js","sourceRoot":"","sources":["../../../../src/identity/backends/libsecret.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ import { redactSecret } from '../redact.js';
|
|
|
13
13
|
// binding, which we deliberately don't ship. `find-generic-password`/`delete-generic-password` take no
|
|
14
14
|
// secret argument, so they don't have this issue.
|
|
15
15
|
const NOT_FOUND_RE = /could not be found|item.*could not be found|specified item could not be found/i;
|
|
16
|
-
export function createMacosKeychainBackend(exec = nodeExec) {
|
|
16
|
+
export function createMacosKeychainBackend(exec = nodeExec, accountName = ACCOUNT_NAME, serviceName = SERVICE_NAME) {
|
|
17
17
|
return {
|
|
18
18
|
id: 'macos-keychain',
|
|
19
19
|
label: 'macOS Keychain',
|
|
@@ -34,8 +34,8 @@ export function createMacosKeychainBackend(exec = nodeExec) {
|
|
|
34
34
|
// -U: update in place if an entry already exists, instead of erroring "already exists".
|
|
35
35
|
const r = await exec('security', [
|
|
36
36
|
'add-generic-password',
|
|
37
|
-
'-a',
|
|
38
|
-
'-s',
|
|
37
|
+
'-a', accountName,
|
|
38
|
+
'-s', serviceName,
|
|
39
39
|
'-w', secret,
|
|
40
40
|
'-U',
|
|
41
41
|
]);
|
|
@@ -44,7 +44,7 @@ export function createMacosKeychainBackend(exec = nodeExec) {
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
async load() {
|
|
47
|
-
const r = await exec('security', ['find-generic-password', '-a',
|
|
47
|
+
const r = await exec('security', ['find-generic-password', '-a', accountName, '-s', serviceName, '-w']);
|
|
48
48
|
if (r.code !== 0) {
|
|
49
49
|
if (NOT_FOUND_RE.test(r.stderr))
|
|
50
50
|
return null;
|
|
@@ -53,7 +53,7 @@ export function createMacosKeychainBackend(exec = nodeExec) {
|
|
|
53
53
|
return r.stdout.trim();
|
|
54
54
|
},
|
|
55
55
|
async delete() {
|
|
56
|
-
const r = await exec('security', ['delete-generic-password', '-a',
|
|
56
|
+
const r = await exec('security', ['delete-generic-password', '-a', accountName, '-s', serviceName]);
|
|
57
57
|
if (r.code !== 0 && !NOT_FOUND_RE.test(r.stderr)) {
|
|
58
58
|
throw new KeyBackendError('macos-keychain', 'delete', r.stderr || `exit ${r.code}`);
|
|
59
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"macos-keychain.js","sourceRoot":"","sources":["../../../../src/identity/backends/macos-keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,YAAY,EAAmB,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,oGAAoG;AACpG,kGAAkG;AAClG,oFAAoF;AACpF,EAAE;AACF,oGAAoG;AACpG,iGAAiG;AACjG,sGAAsG;AACtG,qGAAqG;AACrG,kGAAkG;AAClG,uGAAuG;AACvG,kDAAkD;AAClD,MAAM,YAAY,GAAG,gFAAgF,CAAC;AAEtG,MAAM,UAAU,0BAA0B,CAAC,OAAa,QAAQ;
|
|
1
|
+
{"version":3,"file":"macos-keychain.js","sourceRoot":"","sources":["../../../../src/identity/backends/macos-keychain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,YAAY,EAAmB,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1F,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,oGAAoG;AACpG,kGAAkG;AAClG,oFAAoF;AACpF,EAAE;AACF,oGAAoG;AACpG,iGAAiG;AACjG,sGAAsG;AACtG,qGAAqG;AACrG,kGAAkG;AAClG,uGAAuG;AACvG,kDAAkD;AAClD,MAAM,YAAY,GAAG,gFAAgF,CAAC;AAEtG,MAAM,UAAU,0BAA0B,CAAC,OAAa,QAAQ,EAAE,cAAsB,YAAY,EAAE,cAAsB,YAAY;IACtI,OAAO;QACL,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,gBAAgB;QAEvB,KAAK,CAAC,WAAW;YACf,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;gBAAE,OAAO,KAAK,CAAC;YAChD,IAAI,CAAC;gBACH,0FAA0F;gBAC1F,4EAA4E;gBAC5E,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;gBACjC,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAc;YACvB,wFAAwF;YACxF,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE;gBAC/B,sBAAsB;gBACtB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,MAAM;gBACZ,IAAI;aACL,CAAC,CAAC;YACH,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1G,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI;YACR,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,uBAAuB,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;YACxG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACjB,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;oBAAE,OAAO,IAAI,CAAC;gBAC7C,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACpF,CAAC;YACD,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,MAAM;YACV,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,yBAAyB,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;YACpG,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gBACjD,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,23 +1,34 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
1
2
|
import { createFileFallbackBackend } from './file-fallback.js';
|
|
2
3
|
import { createLibsecretBackend } from './libsecret.js';
|
|
3
4
|
import { createMacosKeychainBackend } from './macos-keychain.js';
|
|
5
|
+
import { ACCOUNT_NAME, WALLET_ACCOUNT_NAME } from './types.js';
|
|
4
6
|
import { createWindowsDpapiBackend } from './windows-dpapi.js';
|
|
7
|
+
import { fileFallbackSecretPath, botanaryMcpHome } from '../../paths.js';
|
|
5
8
|
/**
|
|
6
9
|
* Fixed, platform-derived priority order. The SAME list is used for reads and writes (store.ts): a new
|
|
7
10
|
* key is written to the first available candidate, and every candidate is swept in this order when
|
|
8
11
|
* looking for an existing one. `file-fallback` is always last and always available, so this list can
|
|
9
12
|
* never be empty and a caller can never end up with nowhere to store a key.
|
|
13
|
+
*
|
|
14
|
+
* CRITICAL: the agent's names (SERVICE_NAME / ACCOUNT_NAME) are FROZEN for backward compatibility.
|
|
15
|
+
* Existing installs already have keys stored under these names. Wallet uses a distinct ACCOUNT_NAME
|
|
16
|
+
* to prevent collision.
|
|
10
17
|
*/
|
|
11
|
-
export function defaultCandidates(platform = process.platform) {
|
|
18
|
+
export function defaultCandidates(platform = process.platform, isWallet = false) {
|
|
19
|
+
const accountName = isWallet ? WALLET_ACCOUNT_NAME : ACCOUNT_NAME;
|
|
20
|
+
// Wallet uses distinct file paths so multiple identities never collide
|
|
21
|
+
const walletFileFallbackPath = isWallet ? join(botanaryMcpHome(), 'wallet.key') : fileFallbackSecretPath();
|
|
22
|
+
const walletWindowsDpapiPath = isWallet ? join(botanaryMcpHome(), 'wallet.dpapi') : join(botanaryMcpHome(), 'identity.dpapi');
|
|
12
23
|
switch (platform) {
|
|
13
24
|
case 'darwin':
|
|
14
|
-
return [createMacosKeychainBackend(), createFileFallbackBackend()];
|
|
25
|
+
return [createMacosKeychainBackend(undefined, accountName), createFileFallbackBackend(walletFileFallbackPath)];
|
|
15
26
|
case 'linux':
|
|
16
|
-
return [createLibsecretBackend(), createFileFallbackBackend()];
|
|
27
|
+
return [createLibsecretBackend(undefined, accountName), createFileFallbackBackend(walletFileFallbackPath)];
|
|
17
28
|
case 'win32':
|
|
18
|
-
return [createWindowsDpapiBackend(), createFileFallbackBackend()];
|
|
29
|
+
return [createWindowsDpapiBackend(undefined, walletWindowsDpapiPath), createFileFallbackBackend(walletFileFallbackPath)];
|
|
19
30
|
default:
|
|
20
|
-
return [createFileFallbackBackend()];
|
|
31
|
+
return [createFileFallbackBackend(walletFileFallbackPath)];
|
|
21
32
|
}
|
|
22
33
|
}
|
|
23
34
|
/** Pick the first available backend from `candidates`, in order. Used only to decide where a NEW key
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../src/identity/backends/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../src/identity/backends/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEzE;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAA4B,OAAO,CAAC,QAAQ,EAAE,WAAoB,KAAK;IACvG,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,YAAY,CAAC;IAElE,uEAAuE;IACvE,MAAM,sBAAsB,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,sBAAsB,EAAE,CAAC;IAC3G,MAAM,sBAAsB,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAE9H,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,CAAC,0BAA0B,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,yBAAyB,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjH,KAAK,OAAO;YACV,OAAO,CAAC,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,yBAAyB,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC7G,KAAK,OAAO;YACV,OAAO,CAAC,yBAAyB,CAAC,SAAS,EAAE,sBAAsB,CAAC,EAAE,yBAAyB,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC3H;YACE,OAAO,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;oFACoF;AACpF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,UAAwB;IAC5D,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE,CAAC;QACjC,IAAI,MAAM,OAAO,CAAC,WAAW,EAAE;YAAE,OAAO,OAAO,CAAC;IAClD,CAAC;IACD,8FAA8F;IAC9F,qGAAqG;IACrG,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;AAC/F,CAAC"}
|
|
@@ -10,7 +10,9 @@ export class KeyBackendError extends Error {
|
|
|
10
10
|
}
|
|
11
11
|
/** Fixed, non-secret names every real backend stores the identity under. There is exactly one agent
|
|
12
12
|
* identity per machine by design (see README) - a multi-identity store is a bigger feature than this
|
|
13
|
-
* package builds.
|
|
13
|
+
* package builds. These defaults are FROZEN: existing installs already have agent keys stored here.
|
|
14
|
+
* The wallet lane uses a different ACCOUNT_NAME to prevent collision. */
|
|
14
15
|
export const SERVICE_NAME = 'botanary-mcp';
|
|
15
16
|
export const ACCOUNT_NAME = 'agent-identity';
|
|
17
|
+
export const WALLET_ACCOUNT_NAME = 'wallet-session';
|
|
16
18
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/identity/backends/types.ts"],"names":[],"mappings":"AA6BA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB;IACA;IAFlB,YACkB,OAAe,EACf,SAA+C,EAC/D,OAAe;QAEf,KAAK,CAAC,IAAI,OAAO,KAAK,SAAS,YAAY,OAAO,EAAE,CAAC,CAAC;QAJtC,YAAO,GAAP,OAAO,CAAQ;QACf,cAAS,GAAT,SAAS,CAAsC;QAI/D,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/identity/backends/types.ts"],"names":[],"mappings":"AA6BA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB;IACA;IAFlB,YACkB,OAAe,EACf,SAA+C,EAC/D,OAAe;QAEf,KAAK,CAAC,IAAI,OAAO,KAAK,SAAS,YAAY,OAAO,EAAE,CAAC,CAAC;QAJtC,YAAO,GAAP,OAAO,CAAQ;QACf,cAAS,GAAT,SAAS,CAAsC;QAI/D,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;;0EAG0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAC3C,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC"}
|
|
@@ -34,8 +34,8 @@ const UNPROTECT_SCRIPT = [
|
|
|
34
34
|
'[Console]::Out.Write([System.Text.Encoding]::UTF8.GetString($unprotected))',
|
|
35
35
|
].join('\n');
|
|
36
36
|
const PS_ARGS = ['-NoProfile', '-NonInteractive', '-Command'];
|
|
37
|
-
function defaultFilePath() {
|
|
38
|
-
return join(botanaryMcpHome(),
|
|
37
|
+
function defaultFilePath(filename = 'identity.dpapi') {
|
|
38
|
+
return join(botanaryMcpHome(), filename);
|
|
39
39
|
}
|
|
40
40
|
export function createWindowsDpapiBackend(exec = nodeExec, filePath = defaultFilePath()) {
|
|
41
41
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"windows-dpapi.js","sourceRoot":"","sources":["../../../../src/identity/backends/windows-dpapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAa,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAmB,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,sGAAsG;AACtG,uGAAuG;AACvG,+FAA+F;AAC/F,8FAA8F;AAC9F,EAAE;AACF,mFAAmF;AACnF,sGAAsG;AACtG,qGAAqG;AACrG,qGAAqG;AACrG,sGAAsG;AACtG,qGAAqG;AACrG,+FAA+F;AAC/F,qGAAqG;AACrG,sGAAsG;AACtG,uGAAuG;AACvG,MAAM,cAAc,GAAG;IACrB,wCAAwC;IACxC,mCAAmC;IACnC,uDAAuD;IACvD,oJAAoJ;IACpJ,6DAA6D;CAC9D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,gBAAgB,GAAG;IACvB,wCAAwC;IACxC,kCAAkC;IAClC,4CAA4C;IAC5C,wJAAwJ;IACxJ,4EAA4E;CAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAE9D,SAAS,eAAe;
|
|
1
|
+
{"version":3,"file":"windows-dpapi.js","sourceRoot":"","sources":["../../../../src/identity/backends/windows-dpapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAa,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAmB,eAAe,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,sGAAsG;AACtG,uGAAuG;AACvG,+FAA+F;AAC/F,8FAA8F;AAC9F,EAAE;AACF,mFAAmF;AACnF,sGAAsG;AACtG,qGAAqG;AACrG,qGAAqG;AACrG,sGAAsG;AACtG,qGAAqG;AACrG,+FAA+F;AAC/F,qGAAqG;AACrG,sGAAsG;AACtG,uGAAuG;AACvG,MAAM,cAAc,GAAG;IACrB,wCAAwC;IACxC,mCAAmC;IACnC,uDAAuD;IACvD,oJAAoJ;IACpJ,6DAA6D;CAC9D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,gBAAgB,GAAG;IACvB,wCAAwC;IACxC,kCAAkC;IAClC,4CAA4C;IAC5C,wJAAwJ;IACxJ,4EAA4E;CAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;AAE9D,SAAS,eAAe,CAAC,WAAmB,gBAAgB;IAC1D,OAAO,IAAI,CAAC,eAAe,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,OAAa,QAAQ,EAAE,WAAmB,eAAe,EAAE;IACnG,OAAO;QACL,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,kDAAkD;QAEzD,KAAK,CAAC,WAAW;YACf,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;gBAAE,OAAO,KAAK,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;gBACpE,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC;YAClD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAc;YACvB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,OAAO,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBACrC,iGAAiG;gBACjG,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;YACzG,CAAC;YACD,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACjE,gGAAgG;YAChG,2FAA2F;YAC3F,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,UAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,UAAU,GAAG,CAAC,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACzD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAChE,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;YAC3E,CAAC;YACD,IAAI,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAC;YAC7B,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,OAAO,EAAE,gBAAgB,CAAC,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;YAC1F,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACnF,CAAC;YACD,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,MAAM;YACV,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This package's own version, read from its real `package.json` at runtime.
|
|
3
|
+
*
|
|
4
|
+
* WHY NOT a hand-maintained constant: `server.ts` used to carry `const PACKAGE_VERSION = '0.3.0'`, a
|
|
5
|
+
* literal that nothing forces to track `package.json`. Once a SECOND consumer appeared - the CLI-login
|
|
6
|
+
* handshake reports `clientVersion` to the backend, which surfaces it on the owner's consent screen -
|
|
7
|
+
* a stale literal stops being cosmetic: the owner is being shown a version claim about the very client
|
|
8
|
+
* asking for authority over their account, and it has to be the version actually running.
|
|
9
|
+
*
|
|
10
|
+
* WHY NOT `import pkg from '../package.json'`: `tsc` would then EMIT that JSON into `outDir`, producing
|
|
11
|
+
* a `dist/package.json` with no `"type": "module"` field - which Node reads as a package boundary and
|
|
12
|
+
* uses to decide that every `.js` under `dist/` is CommonJS. The published `bin` entrypoint would fail
|
|
13
|
+
* to load. Reading it with `fs` at runtime keeps `dist/` free of any nested manifest.
|
|
14
|
+
*
|
|
15
|
+
* The walk handles BOTH layouts this file runs under with one code path: `src/package-version.ts` under
|
|
16
|
+
* vitest/@swc-node (package root is one level up) and `dist/src/package-version.js` when installed from
|
|
17
|
+
* npm (two levels up).
|
|
18
|
+
*/
|
|
19
|
+
import { readFileSync } from 'node:fs';
|
|
20
|
+
import { dirname, join } from 'node:path';
|
|
21
|
+
import { fileURLToPath } from 'node:url';
|
|
22
|
+
/** Last resort only - see `readPackageVersion`. Never the normal path. */
|
|
23
|
+
const UNKNOWN_VERSION = '0.0.0-unknown';
|
|
24
|
+
function readPackageVersion() {
|
|
25
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
// Bounded: five levels is far more than either real layout needs, and a bound means a malformed
|
|
27
|
+
// install can never turn this into an unbounded filesystem walk on every login.
|
|
28
|
+
for (let i = 0; i < 5; i++) {
|
|
29
|
+
try {
|
|
30
|
+
const parsed = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
|
|
31
|
+
// Name-checked so a nested manifest (a bundler artifact, a stray fixture) can never be mistaken
|
|
32
|
+
// for ours and report someone else's version to the consent screen.
|
|
33
|
+
if (parsed.name === 'botanary-mcp' && typeof parsed.version === 'string')
|
|
34
|
+
return parsed.version;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// No package.json at this level, or it is unreadable - keep walking up.
|
|
38
|
+
}
|
|
39
|
+
const parent = dirname(dir);
|
|
40
|
+
if (parent === dir)
|
|
41
|
+
break; // filesystem root
|
|
42
|
+
dir = parent;
|
|
43
|
+
}
|
|
44
|
+
// Never throw: a version string is metadata on a login handshake, and failing to read it must not be
|
|
45
|
+
// able to stop an owner logging in to their own wallet.
|
|
46
|
+
return UNKNOWN_VERSION;
|
|
47
|
+
}
|
|
48
|
+
/** Resolved once at module load - the file cannot change under a running process. */
|
|
49
|
+
export const PACKAGE_VERSION = readPackageVersion();
|
|
50
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../../src/package-version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,0EAA0E;AAC1E,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC,SAAS,kBAAkB;IACzB,IAAI,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAClD,gGAAgG;IAChG,gFAAgF;IAChF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAGxE,CAAC;YACF,gGAAgG;YAChG,oEAAoE;YACpE,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ;gBAAE,OAAO,MAAM,CAAC,OAAO,CAAC;QAClG,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM,CAAC,kBAAkB;QAC7C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,qGAAqG;IACrG,wDAAwD;IACxD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,MAAM,eAAe,GAAW,kBAAkB,EAAE,CAAC"}
|