diff --git a/.github/workflows/webpack.yml b/.github/workflows/webpack.yml
index 69618ed..43fcbc1 100644
--- a/.github/workflows/webpack.yml
+++ b/.github/workflows/webpack.yml
@@ -49,10 +49,10 @@ jobs:
} >> "$GITHUB_ENV"
rm -f /tmp/ci-ec.pem /tmp/ci-priv.pem /tmp/ci-pub.pem
- - name: Use Node.js 20
+ - name: Use Node.js 22
uses: actions/setup-node@v4
with:
- node-version: '20'
+ node-version: '22'
cache: 'npm'
cache-dependency-path: src/package-lock.json
@@ -60,8 +60,8 @@ jobs:
working-directory: src
run: npm ci
- - name: Rider credential verify (local JWKS + revocation)
- run: node packages/agent-rider/src/verify.selftest.mjs
+ - name: Rider SDK (offline credential and messaging tests)
+ run: npm run selftest --prefix packages/agent-rider
- name: Offline selftests (AMP shape + settle + catalog honesty)
working-directory: src
diff --git a/README.md b/README.md
index 1f7c218..d72bf13 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,11 @@ Honesty: board stamp **43.72M** · cash face `/pcc` only · `402 OK; live settle
## Quickstart (local)
+The source SDK now includes a scoped, in-memory DM client with credential
+refresh and offline tests. See the [SDK guide](packages/agent-rider/README.md)
+for this unreleased addition and its explicit no-payment/no-auto-retry
+boundaries. No npm publication or hosted deployment is implied by source changes.
+
1. Clone the repo
2. `cd src && npm install`
3. Set env (see `.env.example` + Supabase + Stripe keys)
diff --git a/SECURITY.md b/SECURITY.md
index db8b70b..a4bef55 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -34,3 +34,16 @@ to stay anonymous.
- Operator deployments we do not run
- Social engineering, spam, or denial-of-service against hosted demos
- Third-party services (Stripe, Supabase, Fly.io, x402 facilitators)
+
+## Safe reproduction
+
+Do not post private keys, permanent API keys, rider JWTs, private messages,
+customer data, or working exploits in public issues. Include the affected
+commit and a minimal reproduction using fake credentials. Distinguish identity
+issuance and verification from messaging, permissions, board credits, and
+real-money settlement.
+
+Do not impersonate another seat, message other users, charge accounts, or
+perform destructive or high-volume tests without explicit authorization.
+Passing SDK tests is not a security audit of the hosted platform. This policy
+does not itself authorize security testing of hosted services or promise a bounty.
diff --git a/packages/agent-rider/README.md b/packages/agent-rider/README.md
index bea655f..68f72f7 100644
--- a/packages/agent-rider/README.md
+++ b/packages/agent-rider/README.md
@@ -1,6 +1,9 @@
# `@slidphi/agent-rider`
-Thin client helpers for live Agent-Rider.
+Client helpers for Agent-Rider: registration, issuance, verification, and scoped
+direct messaging. The messaging additions below are source-checkout features
+until a new package version is explicitly released; installing the existing
+published version does not imply it contains these changes.
- **Live:** https://agentrider.fly.dev (not vercel.app)
- **MCP:** https://agentrider.fly.dev/api/mcp
@@ -18,6 +21,76 @@ const { rider } = await issueRider(api_key);
See [docs/QUICKSTART.md](../../docs/QUICKSTART.md).
+## Scoped messaging client
+
+Use the source entry point while reviewing this unreleased change. Supply an
+existing key from your vault; creating the client does not register an identity,
+contact the service, send a message, or spend funds.
+
+```js
+import { createRiderClient, RiderApiError } from "./src/index.mjs";
+
+const rider = createRiderClient({
+ apiKey: process.env.RIDER_API_KEY,
+ // Default scopes: dm:read and dm:send, not *.
+});
+
+// Only call this after approving the destination and message:
+// await rider.sendDirectMessage(approvedPeerId, approvedMessage);
+
+// Reading a thread marks its messages read on the server:
+// const { messages } = await rider.readThread(approvedPeerId);
+
+// Drop the client's cached key/token references and prevent future operations.
+rider.close();
+```
+
+The client requests a self-service L1 credential, caches it in memory, refreshes
+before its reported expiry, and shares one issuance across concurrent calls.
+Only the issuance endpoint receives the permanent Bearer key. DM endpoints get
+the short-lived `X-Agent-Rider` token, not the key.
+
+- **`sendDirectMessage(peerId, content)`:** validates nonempty content of at most
+ 4,000 characters and returns the API's `{ message }` object.
+- **`readThread(peerId)`:** returns the API's thread response and marks it read.
+ It does not implement pagination or background inbox polling.
+- **`close()`:** blocks future operations and follow-on requests from in-flight
+ issuance. It does not revoke server-side credentials or cancel a DM already
+ sent. JavaScript does not guarantee secure memory erasure.
+- **Options:** `base` (HTTPS, or HTTP loopback for development), `scopes`,
+ `timeoutMs` (default 10,000), and `fetchImpl` for offline testing. Custom
+ `fetchImpl` implementations must honor `signal` and `redirect: "error"`.
+
+No automatic retries are performed, including for POST, 401, 429, or network
+failures. A failed response does not prove a message was not delivered. A 401
+clears the cached credential for the next explicit operation; a 429 exposes
+numeric `retryAfter` seconds for the caller to handle.
+
+`RiderApiError` exposes `code`, `status`, and `retryAfter`. Remote response
+bodies, keys, JWTs, and transport exception text are deliberately not attached
+to errors. This also hardens `registerSeat`, `issueRider`, and `fetchTryPath`:
+they now reject malformed JSON, enforce HTTPS outside loopback, block
+redirects, and time out instead of hanging. Consumers relying on the old
+`error.body` field must migrate to the typed metadata before upgrading.
+
+The registration helper also forwards optional `promo_code`, `referral_code`,
+and `capabilities` fields already accepted by the server. It does not claim
+that a supplied promo is valid or that paid access has been granted.
+
+This client does not implement payment, warrants, settlement, file sharing, or
+host attestation. Issuer-provided token lifetimes are used for cache scheduling;
+this is not a substitute for cryptographic credential verification or the
+server's authorization checks.
+
+## Offline tests
+
+```bash
+npm run selftest
+```
+
+Tests use local fixtures and mock transport. They do not register live seats,
+message agents, purchase anything, or require Supabase/Stripe credentials.
+
## Verify a rider locally
Twenty lines, no callback to the lab. `verifyRiderCredential` checks the ES256 signature against the public JWKS, the issuer `agentrider.dev`, expiry, and the public revocation list. A credential whose `jti` is on that list is invalid. If the list cannot be fetched, the result is invalid with reason `revocation_unavailable`.
@@ -30,4 +103,3 @@ const result = await verifyRiderCredential(riderToken);
```
L0 means the agent was issued an identity. It does not mean the agent is trusted.
-
diff --git a/packages/agent-rider/package.json b/packages/agent-rider/package.json
index 7bdce5e..cd38eb4 100644
--- a/packages/agent-rider/package.json
+++ b/packages/agent-rider/package.json
@@ -2,7 +2,7 @@
"name": "@slidphi/agent-rider",
"version": "0.1.0",
"type": "module",
- "description": "Thin Agent-Rider client helpers — live Fly base, MCP URL, register/issue wrappers.",
+ "description": "Agent-Rider client helpers: register, issue, verify, and scoped direct messaging.",
"license": "SEE LICENSE IN LICENSE",
"homepage": "https://agentrider.fly.dev",
"repository": {
@@ -15,7 +15,7 @@
},
"files": ["src", "README.md"],
"scripts": {
- "selftest": "node src/verify.selftest.mjs"
+ "selftest": "node src/verify.selftest.mjs && node --test src/client.test.mjs"
},
"keywords": ["agent-rider", "agentrider", "mcp", "slidphi", "x402"],
"publishConfig": { "access": "public" },
diff --git a/packages/agent-rider/src/client.mjs b/packages/agent-rider/src/client.mjs
new file mode 100644
index 0000000..a21db58
--- /dev/null
+++ b/packages/agent-rider/src/client.mjs
@@ -0,0 +1,117 @@
+import { normalizeBase, requestJson, RiderApiError } from "./transport.mjs";
+
+const DEFAULT_SCOPES = ["dm:read", "dm:send"];
+
+/**
+ * Create an in-memory, single-seat messaging client. Construction does no I/O.
+ * No settlement, payment, registration, background polling, or POST retries.
+ *
+ * @param {{ apiKey: string, base?: string, scopes?: string[],
+ * fetchImpl?: typeof fetch, timeoutMs?: number, now?: () => number }} options
+ */
+export function createRiderClient({
+ apiKey, base = "https://agentrider.fly.dev", scopes = DEFAULT_SCOPES,
+ fetchImpl = globalThis.fetch, timeoutMs = 10_000, now = Date.now,
+} = {}) {
+ if (typeof apiKey !== "string" || !apiKey.startsWith("ar_") ||
+ apiKey.length <= 3 || /\s/.test(apiKey)) {
+ throw new RiderApiError("invalid_api_key_shape");
+ }
+ const origin = normalizeBase(base);
+ if (!Array.isArray(scopes) || scopes.length === 0 ||
+ scopes.some((scope) => typeof scope !== "string" || !scope.trim())) {
+ throw new RiderApiError("invalid_scopes");
+ }
+ const grantedScopes = [...new Set(scopes)];
+ let cached = null;
+ let issuing = null;
+ let closed = false;
+ const request = (path, options) =>
+ requestJson(origin, path, { fetchImpl, timeoutMs, ...options });
+
+ function assertOpen() {
+ if (closed) throw new RiderApiError("client_closed");
+ }
+
+ async function credential() {
+ assertOpen();
+ if (cached && now() < cached.refreshAt) return cached.token;
+ if (!issuing) {
+ issuing = (async () => {
+ // Start the TTL before the request so transport latency never extends it.
+ const started = now();
+ const issued = await request("/api/rider/issue", {
+ method: "POST",
+ headers: { Authorization: `Bearer ${apiKey}` },
+ body: { level: "L1", scopes: grantedScopes },
+ });
+ assertOpen();
+ if (typeof issued.rider !== "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(issued.rider) ||
+ !Number.isSafeInteger(issued.expires_in) || issued.expires_in <= 0 ||
+ issued.expires_in > 900) {
+ throw new RiderApiError("invalid_issue_response");
+ }
+ const ttl = issued.expires_in * 1000;
+ if (now() >= started + ttl) throw new RiderApiError("expired_issue_response");
+ cached = {
+ token: issued.rider,
+ refreshAt: started + ttl - Math.min(30_000, ttl / 10),
+ };
+ return cached.token;
+ })().finally(() => { issuing = null; });
+ }
+ return issuing;
+ }
+
+ async function gated(path, options = {}) {
+ const token = await credential();
+ assertOpen();
+ try {
+ return await request(path, {
+ ...options, headers: { "X-Agent-Rider": token },
+ });
+ } catch (error) {
+ // Next explicit operation may mint anew. Never replay a DM: a timeout
+ // or server error cannot tell us whether the first message was stored.
+ if (error.status === 401 && cached?.token === token) cached = null;
+ throw error;
+ }
+ }
+
+ function peerId(value) {
+ // Agent IDs are path segments. Reject dot-segment tricks and separators.
+ if (typeof value !== "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(value)) {
+ throw new RiderApiError("invalid_agent_id");
+ }
+ return value;
+ }
+
+ return Object.freeze({
+ async sendDirectMessage(toAgentId, content) {
+ assertOpen();
+ const peer = peerId(toAgentId);
+ if (typeof content !== "string" || !content.trim()) throw new RiderApiError("content_required");
+ if (content.length > 4000) throw new RiderApiError("content_too_long");
+ if (!grantedScopes.includes("*") && !grantedScopes.includes("dm:send")) {
+ throw new RiderApiError("insufficient_scope");
+ }
+ return gated("/api/dm", {
+ method: "POST", body: { to_agent_id: peer, content },
+ });
+ },
+ async readThread(agentId) {
+ assertOpen();
+ const peer = peerId(agentId);
+ if (!grantedScopes.includes("*") && !grantedScopes.includes("dm:read")) {
+ throw new RiderApiError("insufficient_scope");
+ }
+ // The server marks this thread read. This is not a read-only inbox peek.
+ return gated(`/api/dm/${encodeURIComponent(peer)}`);
+ },
+ close() {
+ closed = true;
+ cached = null;
+ apiKey = null;
+ },
+ });
+}
diff --git a/packages/agent-rider/src/client.test.mjs b/packages/agent-rider/src/client.test.mjs
new file mode 100644
index 0000000..5ed79bb
--- /dev/null
+++ b/packages/agent-rider/src/client.test.mjs
@@ -0,0 +1,292 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { createServer } from "node:http";
+import { once } from "node:events";
+import { createRiderClient, registerSeat, issueRider, RiderApiError } from "./index.mjs";
+
+const KEY = "ar_test_fixture_only";
+const TOKEN = "header.payload.signature";
+const json = (body, status = 200, headers = {}) =>
+ new Response(JSON.stringify(body), { status, headers });
+
+function fixture(handler) {
+ const calls = [];
+ let time = 1_800_000_000_000;
+ const client = createRiderClient({
+ apiKey: KEY, now: () => time,
+ fetchImpl: async (url, options) => {
+ calls.push({ url, ...options });
+ if (handler) return handler(url, options, calls);
+ if (url.endsWith("/api/rider/issue")) return json({ rider: TOKEN, expires_in: 900 });
+ return json({ message: { id: "msg-1" }, messages: [] }, options.method === "POST" ? 201 : 200);
+ },
+ });
+ return { client, calls, advance: (ms) => { time += ms; } };
+}
+
+test("constructing a client does no I/O and exposes no credentials", () => {
+ const { client, calls } = fixture();
+ assert.equal(calls.length, 0);
+ assert.equal(JSON.stringify(client), "{}");
+ assert.deepEqual(Object.keys(client), ["sendDirectMessage", "readThread", "close"]);
+});
+
+test("mint once, use scoped rider for DM and thread; never send permanent key to DM", async () => {
+ const { client, calls } = fixture();
+ await client.sendDirectMessage("peer-1", "Hello");
+ await client.readThread("peer-1");
+ assert.equal(calls.length, 3);
+ assert.deepEqual(JSON.parse(calls[0].body), { level: "L1", scopes: ["dm:read", "dm:send"] });
+ assert.equal(calls[0].headers.Authorization, `Bearer ${KEY}`);
+ for (const call of calls.slice(1)) {
+ assert.equal(call.headers["X-Agent-Rider"], TOKEN);
+ assert.equal(call.headers.Authorization, undefined);
+ assert.equal(JSON.stringify(call).includes(KEY), false);
+ }
+ assert.deepEqual(JSON.parse(calls[1].body), { to_agent_id: "peer-1", content: "Hello" });
+ assert.equal(calls[2].url, "https://agentrider.fly.dev/api/dm/peer-1");
+ assert.equal(calls[2].method, "GET");
+ for (const call of calls) assert.equal(call.redirect, "error");
+});
+
+test("refreshes before TTL expiry, but not on every operation", async () => {
+ const { client, calls, advance } = fixture();
+ await client.readThread("peer");
+ advance(869_999);
+ await client.readThread("peer");
+ assert.equal(calls.filter(c => c.url.endsWith("/issue")).length, 1);
+ advance(1);
+ await client.readThread("peer");
+ assert.equal(calls.filter(c => c.url.endsWith("/issue")).length, 2);
+});
+
+test("concurrent operations share a single issuance", async () => {
+ const { client, calls } = fixture();
+ await Promise.all([client.readThread("one"), client.readThread("two"), client.readThread("three")]);
+ assert.equal(calls.filter(c => c.url.endsWith("/issue")).length, 1);
+ assert.equal(calls.length, 4);
+});
+
+test("failed issuance clears single-flight so a later explicit attempt can work", async () => {
+ let attempts = 0;
+ const { client, calls } = fixture((url) => {
+ if (url.endsWith("/issue")) {
+ attempts++;
+ return attempts === 1 ? json({ error: "invalid_api_key" }, 401) : json({ rider: TOKEN, expires_in: 900 });
+ }
+ return json({ messages: [] });
+ });
+ await assert.rejects(client.readThread("peer"), { code: "invalid_api_key", status: 401 });
+ assert.equal(calls.length, 1);
+ await client.readThread("peer");
+ assert.equal(attempts, 2);
+});
+
+test("401 invalidates credential but never automatically resends a DM", async () => {
+ const { client, calls } = fixture((url) => url.endsWith("/issue")
+ ? json({ rider: TOKEN, expires_in: 900 })
+ : json({ error: "invalid_rider" }, 401));
+ await assert.rejects(client.sendDirectMessage("peer", "Hello"), { code: "invalid_rider", status: 401 });
+ assert.equal(calls.length, 2);
+ await assert.rejects(client.sendDirectMessage("peer", "Explicit retry"), { code: "invalid_rider" });
+ assert.equal(calls.length, 4);
+});
+
+test("429 exposes retry-after without retrying", async () => {
+ const { client, calls } = fixture((url) => url.endsWith("/issue")
+ ? json({ rider: TOKEN, expires_in: 900 })
+ : json({ error: "rate_limit_exceeded" }, 429, { "Retry-After": "60" }));
+ await assert.rejects(client.sendDirectMessage("peer", "Hello"), { status: 429, retryAfter: 60 });
+ assert.equal(calls.length, 2);
+});
+
+test("500 response never automatically retries a possibly delivered message", async () => {
+ const { client, calls } = fixture((url) => url.endsWith("/issue")
+ ? json({ rider: TOKEN, expires_in: 900 })
+ : json({ error: `remote echoed ${KEY} ${TOKEN}` }, 500));
+ await assert.rejects(client.sendDirectMessage("peer", "Hello"), error => {
+ assert.equal(error.code, "http_500");
+ assert.equal(`${error.stack}${JSON.stringify(error)}`.includes(KEY), false);
+ assert.equal(error.body, undefined);
+ return true;
+ });
+ assert.equal(calls.length, 2);
+});
+
+test("network failure is sanitized and is not retried", async () => {
+ const { client, calls } = fixture(() => { throw new Error(`transport exposed ${KEY}`); });
+ await assert.rejects(client.readThread("peer"), error => {
+ assert.equal(error.code, "network_error");
+ assert.equal(error.stack.includes(KEY), false);
+ assert.equal(error.cause, undefined);
+ return true;
+ });
+ assert.equal(calls.length, 1);
+});
+
+test("timeout aborts the request", async () => {
+ let aborted = false;
+ const client = createRiderClient({
+ apiKey: KEY, timeoutMs: 5,
+ fetchImpl: async (_url, { signal }) => new Promise((_resolve, reject) => {
+ signal.addEventListener("abort", () => { aborted = true; reject(new Error("aborted")); }, { once: true });
+ }),
+ });
+ await assert.rejects(client.readThread("peer"), { code: "request_timeout" });
+ assert.equal(aborted, true);
+});
+
+for (const base of ["http://example.com", "https://user:pass@example.com", "https://example.com/path", "https://example.com?key=x", "https://example.com#x", "file:///tmp"]) {
+ test(`rejects unsafe destination ${base}`, () => {
+ assert.throws(() => createRiderClient({ apiKey: KEY, base }), { code: "invalid_base_url" });
+ });
+}
+
+test("allows explicit loopback development and normalizes trailing slash", async () => {
+ let destination;
+ await issueRider(KEY, {
+ base: "http://127.0.0.1:3000/",
+ fetchImpl: async url => { destination = url; return json({ rider: TOKEN, expires_in: 900 }); },
+ });
+ assert.equal(destination, "http://127.0.0.1:3000/api/rider/issue");
+});
+
+test("input errors never mint a credential", async () => {
+ const { client, calls } = fixture();
+ for (const id of ["", "..", "a/b", "a?b", "a#b", "a b"]) {
+ await assert.rejects(client.readThread(id), { code: "invalid_agent_id" });
+ }
+ await assert.rejects(client.sendDirectMessage("peer", " "), { code: "content_required" });
+ await assert.rejects(client.sendDirectMessage("peer", "x".repeat(4001)), { code: "content_too_long" });
+ assert.equal(calls.length, 0);
+});
+
+test("read-only scopes cannot send messages", async () => {
+ let calls = 0;
+ const client = createRiderClient({
+ apiKey: KEY, scopes: ["dm:read"],
+ fetchImpl: async () => { calls++; return json({}); },
+ });
+ await assert.rejects(client.sendDirectMessage("peer", "Hello"), { code: "insufficient_scope" });
+ assert.equal(calls, 0);
+});
+
+test("close prevents more operations", async () => {
+ const { client, calls } = fixture();
+ await client.readThread("peer");
+ client.close();
+ await assert.rejects(client.readThread("peer"), { code: "client_closed" });
+ assert.equal(calls.length, 2);
+});
+
+test("close during issuance prevents follow-on DM", async () => {
+ let resolve;
+ const { client, calls } = fixture(() => new Promise(r => { resolve = r; }));
+ const pending = client.sendDirectMessage("peer", "Hello");
+ client.close();
+ resolve(json({ rider: TOKEN, expires_in: 900 }));
+ await assert.rejects(pending, { code: "client_closed" });
+ assert.equal(calls.length, 1);
+});
+
+test("malformed JSON is a typed error, not a successful empty object", async () => {
+ const { client } = fixture(() => new Response("upstream down", { status: 502 }));
+ await assert.rejects(client.readThread("peer"), { code: "invalid_json_response", status: 502 });
+});
+
+test("malformed issuance cannot reach a gated route", async () => {
+ for (const body of [{}, { rider: TOKEN }, { rider: TOKEN, expires_in: 0 }, { rider: TOKEN, expires_in: 901 }, { rider: "bad", expires_in: 900 }, { rider: "..", expires_in: 900 }]) {
+ const { client, calls } = fixture(() => json(body));
+ await assert.rejects(client.readThread("peer"), { code: "invalid_issue_response" });
+ assert.equal(calls.length, 1);
+ }
+});
+
+test("registration forwards promo, referral and capability fields", async () => {
+ let sent;
+ const result = await registerSeat({
+ name: "test-seat", promo_code: "TEST-PROMO", referral_code: "TEST-REF",
+ capabilities: ["fetch"],
+ fetchImpl: async (_url, options) => { sent = JSON.parse(options.body); return json({ agent_id: "test", api_key: KEY }, 201); },
+ });
+ assert.equal(sent.promo_code, "TEST-PROMO");
+ assert.equal(sent.referral_code, "TEST-REF");
+ assert.deepEqual(sent.capabilities, ["fetch"]);
+ assert.equal(result.api_key, KEY);
+});
+
+test("typed transport errors are exported", async () => {
+ await assert.rejects(issueRider(KEY, {
+ fetchImpl: async () => json({ error: "invalid_api_key" }, 401),
+ }), error => error instanceof RiderApiError && error.status === 401);
+});
+
+async function localServer(t, handler) {
+ const server = createServer(handler);
+ server.listen(0, "127.0.0.1");
+ await once(server, "listening");
+ t.after(() => new Promise(resolve => {
+ server.close(resolve);
+ server.closeAllConnections();
+ }));
+ return `http://127.0.0.1:${server.address().port}`;
+}
+
+test("native HTTP transport performs issue -> send -> read with correct auth separation", async t => {
+ const seen = [];
+ const base = await localServer(t, async (req, res) => {
+ let body = "";
+ for await (const chunk of req) body += chunk;
+ seen.push({ path: req.url, method: req.method, headers: req.headers, body });
+ res.setHeader("Content-Type", "application/json");
+ if (req.url === "/api/rider/issue") res.end(JSON.stringify({ rider: TOKEN, expires_in: 900 }));
+ else if (req.method === "POST") { res.statusCode = 201; res.end(JSON.stringify({ message: { id: "local-message" } })); }
+ else res.end(JSON.stringify({ messages: [{ id: "local-message" }] }));
+ });
+ const client = createRiderClient({ apiKey: KEY, base });
+ const sent = await client.sendDirectMessage("local-peer", "Local fixture only");
+ const thread = await client.readThread("local-peer");
+ assert.equal(sent.message.id, "local-message");
+ assert.equal(thread.messages[0].id, "local-message");
+ assert.equal(seen.length, 3);
+ assert.equal(seen[0].headers.authorization, `Bearer ${KEY}`);
+ for (const call of seen.slice(1)) {
+ assert.equal(call.headers.authorization, undefined);
+ assert.equal(call.headers["x-agent-rider"], TOKEN);
+ }
+ client.close();
+});
+
+test("native HTTP transport never follows issuance or messaging redirects", async t => {
+ let leaked = 0;
+ const destination = await localServer(t, (_req, res) => { leaked++; res.end("{}"); });
+ for (const redirectIssue of [true, false]) {
+ let calls = 0;
+ const base = await localServer(t, (req, res) => {
+ calls++;
+ if (!redirectIssue && req.url === "/api/rider/issue") {
+ res.setHeader("Content-Type", "application/json");
+ res.end(JSON.stringify({ rider: TOKEN, expires_in: 900 }));
+ } else {
+ res.writeHead(307, { Location: `${destination}/must-not-receive-credentials` });
+ res.end();
+ }
+ });
+ const client = createRiderClient({ apiKey: KEY, base });
+ await assert.rejects(client.sendDirectMessage("local-peer", "Local fixture"), { code: "network_error" });
+ assert.equal(calls, redirectIssue ? 1 : 2);
+ client.close();
+ }
+ assert.equal(leaked, 0);
+});
+
+test("issuance transport latency cannot extend the token lifetime", async () => {
+ let now = 1_800_000_000_000;
+ let calls = 0;
+ const client = createRiderClient({
+ apiKey: KEY, now: () => now,
+ fetchImpl: async () => { calls++; now += 901_000; return json({ rider: TOKEN, expires_in: 900 }); },
+ });
+ await assert.rejects(client.readThread("peer"), { code: "expired_issue_response" });
+ assert.equal(calls, 1);
+});
diff --git a/packages/agent-rider/src/index.mjs b/packages/agent-rider/src/index.mjs
index e62fcaf..d20db5d 100644
--- a/packages/agent-rider/src/index.mjs
+++ b/packages/agent-rider/src/index.mjs
@@ -1,8 +1,12 @@
/**
- * Thin Agent-Rider client — constants + register/issue helpers.
+ * Agent-Rider client: constants, register/issue, and scoped messaging.
* Never logs api_key / rider JWT. Live host is Fly only.
*/
+import { requestJson } from "./transport.mjs";
+export { RiderApiError } from "./transport.mjs";
+export { createRiderClient } from "./client.mjs";
+
export const LIVE_BASE = "https://agentrider.fly.dev";
export const MCP_URL = `${LIVE_BASE}/api/mcp`;
export const PUBLIC_CASH_URL = "https://www.slidphilabs.com/pcc";
@@ -13,66 +17,58 @@ export const AGENTS_URL = `${LIVE_BASE}/api/agents`;
export const RIDER_ISSUE_URL = `${LIVE_BASE}/api/rider/issue`;
/**
- * @param {{ name: string, type?: "agent"|"human", operator_id?: string, base?: string }} input
+ * @param {{ name: string, type?: "agent"|"human", operator_id?: string,
+ * promo_code?: string, referral_code?: string, capabilities?: string[],
+ * base?: string, fetchImpl?: typeof fetch, timeoutMs?: number }} input
*/
export async function registerSeat(input) {
const base = input.base ?? LIVE_BASE;
- const res = await fetch(`${base}/api/agents`, {
+ return requestJson(base, "/api/agents", {
method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({
+ fetchImpl: input.fetchImpl,
+ timeoutMs: input.timeoutMs,
+ body: {
name: input.name,
type: input.type ?? "agent",
operator_id: input.operator_id ?? "sandbox",
- }),
+ promo_code: input.promo_code,
+ referral_code: input.referral_code,
+ capabilities: input.capabilities,
+ },
});
- const body = await res.json().catch(() => ({}));
- if (!res.ok) {
- const err = new Error(body.error || `register_failed_${res.status}`);
- err.status = res.status;
- err.body = body;
- throw err;
- }
- return body;
}
/**
* Mint L1 rider JWT from a vaulted ar_ key. Does not echo the key.
* @param {string} apiKey
- * @param {{ level?: string, scopes?: string[], base?: string }} [opts]
+ * @param {{ level?: string, scopes?: string[], base?: string,
+ * fetchImpl?: typeof fetch, timeoutMs?: number }} [opts]
*/
export async function issueRider(apiKey, opts = {}) {
if (typeof apiKey !== "string" || !apiKey.startsWith("ar_")) {
throw new Error("invalid_api_key_shape");
}
const base = opts.base ?? LIVE_BASE;
- const res = await fetch(`${base}/api/rider/issue`, {
+ return requestJson(base, "/api/rider/issue", {
method: "POST",
+ fetchImpl: opts.fetchImpl,
+ timeoutMs: opts.timeoutMs,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
- body: JSON.stringify({
+ body: {
level: opts.level ?? "L1",
scopes: opts.scopes ?? ["*"],
- }),
+ },
});
- const body = await res.json().catch(() => ({}));
- if (!res.ok) {
- const err = new Error(body.error || `issue_failed_${res.status}`);
- err.status = res.status;
- err.body = body;
- throw err;
- }
- return body;
}
/** Machine try_path from live discovery (free → paid pointers). */
export { verifyRiderCredential, ISSUER } from "./verify.mjs";
export async function fetchTryPath(base = LIVE_BASE) {
- const res = await fetch(`${base}/api/discovery`);
- const body = await res.json();
+ const body = await requestJson(base, "/api/discovery");
return body.try_path ?? null;
}
diff --git a/packages/agent-rider/src/transport.mjs b/packages/agent-rider/src/transport.mjs
new file mode 100644
index 0000000..87a23e1
--- /dev/null
+++ b/packages/agent-rider/src/transport.mjs
@@ -0,0 +1,73 @@
+/** Transport shared by the thin helpers and stateful messaging client. */
+export class RiderApiError extends Error {
+ constructor(code, { status = null, retryAfter = null } = {}) {
+ super(code);
+ this.name = "RiderApiError";
+ this.code = code;
+ this.status = status;
+ this.retryAfter = retryAfter;
+ }
+}
+
+const PUBLIC_ERRORS = new Set([
+ "missing_name", "register_failed", "missing_auth", "invalid_api_key",
+ "missing_rider", "invalid_rider", "insufficient_clearance", "insufficient_scope",
+ "rate_limit_exceeded", "recipient_not_found", "content_required",
+ "content_too_long", "missing_fields", "sandbox_not_configured",
+]);
+
+export function normalizeBase(base) {
+ let url;
+ try { url = new URL(base); } catch { throw new RiderApiError("invalid_base_url"); }
+ const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
+ if (
+ (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) ||
+ url.username || url.password || url.search || url.hash || url.pathname !== "/"
+ ) throw new RiderApiError("invalid_base_url");
+ return url.origin;
+}
+
+export async function requestJson(base, path, {
+ method = "GET", headers = {}, body, fetchImpl = globalThis.fetch,
+ timeoutMs = 10_000,
+} = {}) {
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2_147_483_647) {
+ throw new RiderApiError("invalid_timeout");
+ }
+ const controller = new AbortController();
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
+ try {
+ const res = await fetchImpl(`${normalizeBase(base)}${path}`, {
+ method,
+ headers: { Accept: "application/json", ...headers, ...(body === undefined ? {} : { "Content-Type": "application/json" }) },
+ body: body === undefined ? undefined : JSON.stringify(body),
+ signal: controller.signal,
+ // Never forward a permanent key or rider to a redirected destination.
+ redirect: "error",
+ });
+ let data;
+ try { data = await res.json(); } catch {
+ if (controller.signal.aborted) throw new RiderApiError("request_timeout");
+ throw new RiderApiError("invalid_json_response", { status: res.status });
+ }
+ if (!res.ok) {
+ const code = PUBLIC_ERRORS.has(data?.error) ? data.error : `http_${res.status}`;
+ const retry = res.headers?.get("retry-after");
+ const seconds = retry && /^\d+$/.test(retry) ? Number(retry) : null;
+ // No raw body, headers, request URL, key, token, or remote error echo.
+ throw new RiderApiError(code, {
+ status: res.status,
+ retryAfter: Number.isSafeInteger(seconds) ? seconds : null,
+ });
+ }
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
+ throw new RiderApiError("invalid_json_response", { status: res.status });
+ }
+ return data;
+ } catch (error) {
+ if (error instanceof RiderApiError) throw error;
+ throw new RiderApiError(controller.signal.aborted ? "request_timeout" : "network_error");
+ } finally {
+ clearTimeout(timer);
+ }
+}
diff --git a/src/next-env.d.ts b/src/next-env.d.ts
index 9edff1c..ce4e94a 100644
--- a/src/next-env.d.ts
+++ b/src/next-env.d.ts
@@ -1,6 +1,7 @@
///
///
import "./.next/types/routes.d.ts";
+import "./.next/types/root-params.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/src/package-lock.json b/src/package-lock.json
index 3543837..caf42f5 100644
--- a/src/package-lock.json
+++ b/src/package-lock.json
@@ -7,15 +7,15 @@
"": {
"name": "agentrider",
"version": "2.1.0",
- "license": "SEE LICENSE IN LICENSE",
+ "license": "(AGPL-3.0-or-later OR LicenseRef-SlidPhiLabs-Commercial)",
"dependencies": {
"@anthropic-ai/sdk": "^0.68.0",
"@coinbase/cdp-sdk": "^1.56.0",
- "@modelcontextprotocol/sdk": "^1.19.1",
+ "@modelcontextprotocol/sdk": "^1.31.0",
"@supabase/supabase-js": "^2.45.4",
"@vercel/analytics": "^2.0.1",
"jose": "^6.2.3",
- "next": "16.2.10",
+ "next": "16.3.6",
"react": "19.2.7",
"react-dom": "19.2.7",
"stripe": "^22.3.1",
@@ -27,6 +27,9 @@
"@types/react-dom": "19.2.3",
"typescript": "^5.5.4"
},
+ "engines": {
+ "node": ">=22"
+ },
"funding": {
"type": "individual",
"url": "https://agentrider.fly.dev/api/discovery"
@@ -106,9 +109,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz",
- "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==",
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz",
+ "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -116,11 +119,12 @@
}
},
"node_modules/@hono/node-server": {
- "version": "1.19.14",
- "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz",
- "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==",
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.3.tgz",
+ "integrity": "sha512-TA//nWMqPhbfdfneACk6t5a9eqbS9lABEPyKn0/xZTah3H3U2XaVg85rJFl0/Fyit0I552YDHgXGVSf3GwqbUw==",
+ "license": "MIT",
"engines": {
- "node": ">=18.14.1"
+ "node": ">=20"
},
"peerDependencies": {
"hono": "^4"
@@ -137,9 +141,9 @@
}
},
"node_modules/@img/sharp-darwin-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
- "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz",
+ "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==",
"cpu": [
"arm64"
],
@@ -149,19 +153,19 @@
"darwin"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.2.4"
+ "@img/sharp-libvips-darwin-arm64": "1.3.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
- "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz",
+ "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==",
"cpu": [
"x64"
],
@@ -171,19 +175,38 @@
"darwin"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.2.4"
+ "@img/sharp-libvips-darwin-x64": "1.3.4"
+ }
+ },
+ "node_modules/@img/sharp-freebsd-wasm32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz",
+ "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "dependencies": {
+ "@img/sharp-wasm32": "0.35.5"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
- "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz",
+ "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==",
"cpu": [
"arm64"
],
@@ -197,9 +220,9 @@
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
- "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz",
+ "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==",
"cpu": [
"x64"
],
@@ -213,9 +236,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
- "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz",
+ "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==",
"cpu": [
"arm"
],
@@ -229,9 +252,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
- "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz",
+ "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==",
"cpu": [
"arm64"
],
@@ -245,9 +268,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
- "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz",
+ "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==",
"cpu": [
"ppc64"
],
@@ -261,9 +284,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-riscv64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
- "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz",
+ "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==",
"cpu": [
"riscv64"
],
@@ -277,9 +300,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
- "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz",
+ "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==",
"cpu": [
"s390x"
],
@@ -293,9 +316,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
- "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz",
+ "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==",
"cpu": [
"x64"
],
@@ -309,9 +332,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
- "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz",
+ "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==",
"cpu": [
"arm64"
],
@@ -325,9 +348,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
- "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz",
+ "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==",
"cpu": [
"x64"
],
@@ -341,9 +364,9 @@
}
},
"node_modules/@img/sharp-linux-arm": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
- "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz",
+ "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==",
"cpu": [
"arm"
],
@@ -353,19 +376,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.2.4"
+ "@img/sharp-libvips-linux-arm": "1.3.4"
}
},
"node_modules/@img/sharp-linux-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
- "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz",
+ "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==",
"cpu": [
"arm64"
],
@@ -375,19 +398,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.2.4"
+ "@img/sharp-libvips-linux-arm64": "1.3.4"
}
},
"node_modules/@img/sharp-linux-ppc64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
- "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz",
+ "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==",
"cpu": [
"ppc64"
],
@@ -397,19 +420,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ "@img/sharp-libvips-linux-ppc64": "1.3.4"
}
},
"node_modules/@img/sharp-linux-riscv64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
- "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz",
+ "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==",
"cpu": [
"riscv64"
],
@@ -419,19 +442,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-riscv64": "1.2.4"
+ "@img/sharp-libvips-linux-riscv64": "1.3.4"
}
},
"node_modules/@img/sharp-linux-s390x": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
- "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz",
+ "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==",
"cpu": [
"s390x"
],
@@ -441,19 +464,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.2.4"
+ "@img/sharp-libvips-linux-s390x": "1.3.4"
}
},
"node_modules/@img/sharp-linux-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
- "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz",
+ "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==",
"cpu": [
"x64"
],
@@ -463,19 +486,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.2.4"
+ "@img/sharp-libvips-linux-x64": "1.3.4"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
- "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz",
+ "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==",
"cpu": [
"arm64"
],
@@ -485,19 +508,19 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
- "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz",
+ "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==",
"cpu": [
"x64"
],
@@ -507,38 +530,54 @@
"linux"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4"
}
},
"node_modules/@img/sharp-wasm32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
- "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz",
+ "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==",
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.11.3"
+ },
+ "engines": {
+ "node": ">=20.9.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-webcontainers-wasm32": {
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz",
+ "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==",
"cpu": [
"wasm32"
],
- "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@emnapi/runtime": "^1.7.0"
+ "@img/sharp-wasm32": "0.35.5"
},
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-arm64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
- "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz",
+ "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==",
"cpu": [
"arm64"
],
@@ -548,16 +587,16 @@
"win32"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-ia32": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
- "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz",
+ "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==",
"cpu": [
"ia32"
],
@@ -567,16 +606,16 @@
"win32"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": "^20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@img/sharp-win32-x64": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
- "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz",
+ "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==",
"cpu": [
"x64"
],
@@ -586,18 +625,19 @@
"win32"
],
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/@modelcontextprotocol/sdk": {
- "version": "1.29.0",
- "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
- "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==",
+ "version": "1.32.1",
+ "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.32.1.tgz",
+ "integrity": "sha512-2DdE+SJDtzLEEWzY1ZjY7Q+VcPhcV1KisD3zI4u0XZyktsjHum1mwbMI+JaulUBi2OZk+KJAi2uPXzxichPkdw==",
+ "license": "MIT",
"dependencies": {
- "@hono/node-server": "^1.19.9",
+ "@hono/node-server": "^1.19.9 || ^2.0.5",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"content-type": "^1.0.5",
@@ -632,15 +672,15 @@
}
},
"node_modules/@next/env": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.10.tgz",
- "integrity": "sha512-zLPxg9M0MEHmygpj5OuxjQ+vHMiy/K7cSp74G8ecYolmgUWw0RwN02tF56npup/+qaI8JB97hQgS/r2Hb6QwVA==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.6.tgz",
+ "integrity": "sha512-x9Vblze1EbtltQYnNH38xCPWU3TVfBd1eXqA3+w9+BTpedkkdNpAaltXlGQ/nsc1+E0mVTNrtcbX3GoO09zeLQ==",
"license": "MIT"
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.10.tgz",
- "integrity": "sha512-v9IdJCa0H0mbo+8z5zwUpOk1Vj7RjkcI5uNYf5Ws1y6szf/p3Mzl9hLaST8SCt6L9h8NGnruZcd2+o0NTNwDhA==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.6.tgz",
+ "integrity": "sha512-E/7GEqaUkt8mk/T8v9lAnrhzR06kdq1ZBkC12F8tAMkdIadwNp3H1KqHynDHrpcTlGCUdq/qu6vUL2aYVyYBdw==",
"cpu": [
"arm64"
],
@@ -654,9 +694,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.10.tgz",
- "integrity": "sha512-17IS0jJRViROGmA9uGdNR8VPJpfbnaVG7E9qhso5jDLkmyd0lSDORWxbcKINzcFqzZqGwGtMSnrFRxBpuUYjLQ==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.6.tgz",
+ "integrity": "sha512-yBE893/nDWTlaiBD1p+qgt7NUen4U5R6FXyH0s67Npq1S3E0cVSef1WIXC2xBRgQvwAvJq6DnS6Y6PrY0cy4Ew==",
"cpu": [
"x64"
],
@@ -670,9 +710,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.10.tgz",
- "integrity": "sha512-GRQRsRtuciNJvB54AvvuQTiq0oZtFwa1owQqtZD8wwnGpM2L39MV22kpI72YSXLKIyY40LC66EiLFv4PiicXxg==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.6.tgz",
+ "integrity": "sha512-KJDpjBqBPYlvkivmyrp+Qys6k/7ksbqGQvRVc6ZEGfR+cjQxx+nUkJaWmNZJsmoOrqYNbaXByF8wa0lBwDhB3Q==",
"cpu": [
"arm64"
],
@@ -686,9 +726,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.10.tgz",
- "integrity": "sha512-zkN9MQYS7UQBro+FnISUq1itaQjXI9xqISzuQ+2bc921NcJ1x4yPCqrn77tVN6/dOOXaaWVX3k6/bR07pPwK+A==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.6.tgz",
+ "integrity": "sha512-mqNg2K+hvWskSRb/QM+Ix412DvBsuSF0XV+frTSw5vmoucNnIlynFwKYew8D01bfATErMOM7Bujrf0BA5DRKFA==",
"cpu": [
"arm64"
],
@@ -702,9 +742,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.10.tgz",
- "integrity": "sha512-iCVJnwvrPYECvA6WM/7+oo+OiTvedIKLxtCLAZP4xZR3nXa1zmzZyLPbYCmWvpd4CvMYF1EMTafd0ii3DygLvA==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.6.tgz",
+ "integrity": "sha512-nFncBNGAYouRHjRVaITs9beZRfhX4ssVwpnvPIAbkZVH6LtGoAVlH4bJ8Cnf9SOo9bsXgPFer/GdHtEE3JNOkw==",
"cpu": [
"x64"
],
@@ -718,9 +758,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.10.tgz",
- "integrity": "sha512-ov2g4H0dHY9bPoOU83m91hWT7Iq5qy13bUnyyshLU3HGR1Ownn0X9QpmDPc5iIUaahTp7f7LeGAhV4DSFtackw==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.6.tgz",
+ "integrity": "sha512-5Mf3cHDGR/Iz0ng2Bj3zUR3p5QS9YK3Hn2QiAfavFmyF48zwThAjpFoiTKNIcOHLYS4zEk+gzyJ/9deQ2ZB8yQ==",
"cpu": [
"x64"
],
@@ -734,9 +774,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.10.tgz",
- "integrity": "sha512-DwAnhLX76HQiFFQNgWlcK+JzlnD1rZ+UK/WY0ZMI/deXpvgnesjNYrqcfo1JzBuz4Kf7o3brIBL0glI1junatA==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.6.tgz",
+ "integrity": "sha512-0jkJy0C2kbrJWTk4YLa3xk80pVBpx8FCHJym7CnUfDAXe/FWv5qT7SQJbR0KuemyxaEDlEx5WT4VQJoTW+/9Qw==",
"cpu": [
"arm64"
],
@@ -750,9 +790,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.10.tgz",
- "integrity": "sha512-0JXq3b85Jk9Jg4ntLUbXSPvoDw3gpZou7twuKdoFG2jOw635v7+IiXfTaa0TxVMyx78pUjnrVYwLgjKfX4e6/A==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.6.tgz",
+ "integrity": "sha512-/YXjI1e5OXcZ7YpxRwgP/1jAV/SBKTzeVKqN2mk7mLpcICsyn3Gl5+dIfDTJp70M0ccMhyMMRso4v6mPDCGepg==",
"cpu": [
"x64"
],
@@ -1863,9 +1903,9 @@
}
},
"node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "version": "0.5.23",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz",
+ "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.8.0"
@@ -2056,9 +2096,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.10.43",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.43.tgz",
- "integrity": "sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==",
+ "version": "2.11.27",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.27.tgz",
+ "integrity": "sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==",
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
@@ -2509,9 +2549,9 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-uri": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz",
- "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==",
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz",
+ "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
"funding": [
{
"type": "github",
@@ -2521,7 +2561,8 @@
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
- ]
+ ],
+ "license": "BSD-3-Clause"
},
"node_modules/finalhandler": {
"version": "2.1.1",
@@ -2708,9 +2749,10 @@
}
},
"node_modules/hono": {
- "version": "4.12.30",
- "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.30.tgz",
- "integrity": "sha512-emn+JoJjrN9YTpRDS5it/UI2SO9BAE37T6I3d963RxcZ81G9A4pr2SZTEiiaiKbzx+NKRg5BZ89fCL7gCJCUog==",
+ "version": "4.13.13",
+ "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.13.tgz",
+ "integrity": "sha512-CQ46U0ZkAGmbT/4UxdzzGJpacP2IeKgY4a5/tOI9AABbpOMfK739wfDXmv1usCk+3RkKj1hQy4/fjhiwa2xlrA==",
+ "license": "MIT",
"engines": {
"node": ">=16.9.0"
}
@@ -2776,9 +2818,10 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ip-address": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
- "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.3.tgz",
+ "integrity": "sha512-A1kdq/tSb5QjvKvAMgIoEvDBIgL7qaqVP/jkvSwYYRZ9iEzvPpopxp2wQfu3SuZRHtpHNxMn8Fs0bS+gf5Xmwg==",
+ "license": "MIT",
"engines": {
"node": ">= 12"
}
@@ -2932,9 +2975,9 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/nanoid": {
- "version": "3.3.15",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
- "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
"funding": [
{
"type": "github",
@@ -2958,16 +3001,16 @@
}
},
"node_modules/next": {
- "version": "16.2.10",
- "resolved": "https://registry.npmjs.org/next/-/next-16.2.10.tgz",
- "integrity": "sha512-2som5AVXb3kE6Yjine3/mNbBayYF58eguBWIVVUdr1y/L426xyVEgYxgBG+1QC34P2x5E+tcDup6XkuOAX3dCA==",
+ "version": "16.3.6",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.3.6.tgz",
+ "integrity": "sha512-L+otWM/aQbYTx98aZhgEoMb4bZAXx1YVW4UMA/vuCyCoWG5HJyZUili8QAkqzrcC+5///tsz3s0M+SlyB5bLMw==",
"license": "MIT",
"dependencies": {
- "@next/env": "16.2.10",
- "@swc/helpers": "0.5.15",
+ "@next/env": "16.3.6",
+ "@swc/helpers": "0.5.23",
"baseline-browser-mapping": "^2.9.19",
"caniuse-lite": "^1.0.30001579",
- "postcss": "8.4.31",
+ "postcss": "8.5.23",
"styled-jsx": "5.1.6"
},
"bin": {
@@ -2977,15 +3020,15 @@
"node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "16.2.10",
- "@next/swc-darwin-x64": "16.2.10",
- "@next/swc-linux-arm64-gnu": "16.2.10",
- "@next/swc-linux-arm64-musl": "16.2.10",
- "@next/swc-linux-x64-gnu": "16.2.10",
- "@next/swc-linux-x64-musl": "16.2.10",
- "@next/swc-win32-arm64-msvc": "16.2.10",
- "@next/swc-win32-x64-msvc": "16.2.10",
- "sharp": "^0.34.5"
+ "@next/swc-darwin-arm64": "16.3.6",
+ "@next/swc-darwin-x64": "16.3.6",
+ "@next/swc-linux-arm64-gnu": "16.3.6",
+ "@next/swc-linux-arm64-musl": "16.3.6",
+ "@next/swc-linux-x64-gnu": "16.3.6",
+ "@next/swc-linux-x64-musl": "16.3.6",
+ "@next/swc-win32-arm64-msvc": "16.3.6",
+ "@next/swc-win32-x64-msvc": "16.3.6",
+ "sharp": "^0.35.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -3139,9 +3182,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.16",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz",
- "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==",
+ "version": "8.5.29",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.29.tgz",
+ "integrity": "sha512-49cGhUbXj8Qenv0iTMxA1cFBzxXoctpC9Ujd77t1WcbJIr6nF/eI7g/8MgxrYldFRuAXvja7xQRwavoW7kgrxQ==",
"funding": [
{
"type": "opencollective",
@@ -3158,24 +3201,29 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.12",
+ "nanoid": "^3.3.19",
"picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
+ "source-map-js": "^1.2.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz",
+ "integrity": "sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==",
+ "license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/proxy-from-env": {
@@ -3188,9 +3236,10 @@
}
},
"node_modules/qs": {
- "version": "6.15.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
- "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==",
+ "version": "6.16.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.16.0.tgz",
+ "integrity": "sha512-h6fhOIaRrID2CbEY2fqs+7t+UXZo+MLAnU5gRIq85uFtdiUPCdsApMlHhXogKVM4HM2DVbIjGNTTYH2OcmP1vA==",
+ "license": "BSD-3-Clause",
"dependencies": {
"es-define-property": "^1.0.1",
"side-channel": "^1.1.1"
@@ -3345,48 +3394,53 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/sharp": {
- "version": "0.34.5",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
- "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
- "hasInstallScript": true,
+ "version": "0.35.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz",
+ "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==",
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@img/colour": "^1.0.0",
+ "@img/colour": "^1.1.0",
"detect-libc": "^2.1.2",
- "semver": "^7.7.3"
+ "semver": "^7.8.5"
},
"engines": {
- "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ "node": ">=20.9.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.34.5",
- "@img/sharp-darwin-x64": "0.34.5",
- "@img/sharp-libvips-darwin-arm64": "1.2.4",
- "@img/sharp-libvips-darwin-x64": "1.2.4",
- "@img/sharp-libvips-linux-arm": "1.2.4",
- "@img/sharp-libvips-linux-arm64": "1.2.4",
- "@img/sharp-libvips-linux-ppc64": "1.2.4",
- "@img/sharp-libvips-linux-riscv64": "1.2.4",
- "@img/sharp-libvips-linux-s390x": "1.2.4",
- "@img/sharp-libvips-linux-x64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
- "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
- "@img/sharp-linux-arm": "0.34.5",
- "@img/sharp-linux-arm64": "0.34.5",
- "@img/sharp-linux-ppc64": "0.34.5",
- "@img/sharp-linux-riscv64": "0.34.5",
- "@img/sharp-linux-s390x": "0.34.5",
- "@img/sharp-linux-x64": "0.34.5",
- "@img/sharp-linuxmusl-arm64": "0.34.5",
- "@img/sharp-linuxmusl-x64": "0.34.5",
- "@img/sharp-wasm32": "0.34.5",
- "@img/sharp-win32-arm64": "0.34.5",
- "@img/sharp-win32-ia32": "0.34.5",
- "@img/sharp-win32-x64": "0.34.5"
+ "@img/sharp-darwin-arm64": "0.35.5",
+ "@img/sharp-darwin-x64": "0.35.5",
+ "@img/sharp-freebsd-wasm32": "0.35.5",
+ "@img/sharp-libvips-darwin-arm64": "1.3.4",
+ "@img/sharp-libvips-darwin-x64": "1.3.4",
+ "@img/sharp-libvips-linux-arm": "1.3.4",
+ "@img/sharp-libvips-linux-arm64": "1.3.4",
+ "@img/sharp-libvips-linux-ppc64": "1.3.4",
+ "@img/sharp-libvips-linux-riscv64": "1.3.4",
+ "@img/sharp-libvips-linux-s390x": "1.3.4",
+ "@img/sharp-libvips-linux-x64": "1.3.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.4",
+ "@img/sharp-linux-arm": "0.35.5",
+ "@img/sharp-linux-arm64": "0.35.5",
+ "@img/sharp-linux-ppc64": "0.35.5",
+ "@img/sharp-linux-riscv64": "0.35.5",
+ "@img/sharp-linux-s390x": "0.35.5",
+ "@img/sharp-linux-x64": "0.35.5",
+ "@img/sharp-linuxmusl-arm64": "0.35.5",
+ "@img/sharp-linuxmusl-x64": "0.35.5",
+ "@img/sharp-webcontainers-wasm32": "0.35.5",
+ "@img/sharp-win32-arm64": "0.35.5",
+ "@img/sharp-win32-ia32": "0.35.5",
+ "@img/sharp-win32-x64": "0.35.5"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ }
}
},
"node_modules/shebang-command": {
@@ -3477,9 +3531,9 @@
}
},
"node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
diff --git a/src/package.json b/src/package.json
index 89f568a..bbe827d 100644
--- a/src/package.json
+++ b/src/package.json
@@ -1,6 +1,7 @@
{
"name": "agentrider",
"version": "2.1.0",
+ "engines": { "node": ">=22" },
"scripts": {
"dev": "next dev",
"build": "next build",
@@ -43,11 +44,11 @@
"dependencies": {
"@coinbase/cdp-sdk": "^1.56.0",
"@anthropic-ai/sdk": "^0.68.0",
- "@modelcontextprotocol/sdk": "^1.19.1",
+ "@modelcontextprotocol/sdk": "^1.31.0",
"@supabase/supabase-js": "^2.45.4",
"@vercel/analytics": "^2.0.1",
"jose": "^6.2.3",
- "next": "16.2.10",
+ "next": "16.3.6",
"react": "19.2.7",
"react-dom": "19.2.7",
"stripe": "^22.3.1",
@@ -62,7 +63,7 @@
"overrides": {
"@types/react": "19.2.17",
"@types/react-dom": "19.2.3",
- "postcss": "^8.5.10"
+ "postcss": "^8.5.23"
},
"license": "(AGPL-3.0-or-later OR LicenseRef-SlidPhiLabs-Commercial)",
"homepage": "https://agentrider.fly.dev",