@forgeintel/sdk 0.2.0-beta.0 → 0.4.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -5
- package/dist/ask.d.ts +25 -0
- package/dist/ask.js +36 -0
- package/dist/context.d.ts +74 -0
- package/dist/context.js +117 -0
- package/dist/core.d.ts +42 -4
- package/dist/core.js +96 -19
- package/dist/express.js +43 -5
- package/dist/fetch.d.ts +17 -0
- package/dist/fetch.js +171 -0
- package/dist/hono.d.ts +10 -0
- package/dist/hono.js +35 -0
- package/dist/id.d.ts +5 -0
- package/dist/id.js +7 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.js +4 -2
- package/dist/next.d.ts +25 -0
- package/dist/next.js +30 -0
- package/dist/openapi.d.ts +6 -0
- package/dist/openapi.js +55 -0
- package/dist/reporter.d.ts +7 -0
- package/dist/x402.d.ts +30 -4
- package/dist/x402.js +61 -4
- package/package.json +29 -11
package/dist/next.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createForge as createForgeFetch } from "./fetch.js";
|
|
2
|
+
/**
|
|
3
|
+
* Rebuild a forwarded Request as the original's class (NextRequest), so handlers and withX402 still get
|
|
4
|
+
* `nextUrl` and friends. Next isn't imported: the constructor comes from the request itself.
|
|
5
|
+
*/
|
|
6
|
+
function sameKind(original, forwarded) {
|
|
7
|
+
const Kind = original.constructor;
|
|
8
|
+
return Kind === Request ? forwarded : new Kind(forwarded);
|
|
9
|
+
}
|
|
10
|
+
export function createForge(options) {
|
|
11
|
+
const forge = createForgeFetch(options);
|
|
12
|
+
const own = async (request) => (await forge.route(request)) ?? new Response(JSON.stringify({ error: "not_found" }), { status: 404, headers: { "Content-Type": "application/json" } });
|
|
13
|
+
return {
|
|
14
|
+
enabled: forge.enabled,
|
|
15
|
+
challengeSentence: forge.challengeSentence,
|
|
16
|
+
enrichOpenApi: forge.enrichOpenApi,
|
|
17
|
+
diagnostics: forge.diagnostics,
|
|
18
|
+
shutdown: forge.shutdown,
|
|
19
|
+
handle: forge.handle,
|
|
20
|
+
withForge: (handler) => (request, context) => forge.handle(request, (forwarded) => handler(forwarded === request ? request : sameKind(request, forwarded), context)),
|
|
21
|
+
routes: { GET: own, POST: own, HEAD: own },
|
|
22
|
+
proxy: (proxy) => async (request) => {
|
|
23
|
+
const response = await proxy(request);
|
|
24
|
+
// Only the 402: the proxy passes paid requests on to the route, where withForge mints the feedback ID.
|
|
25
|
+
if (response.status !== 402 || !forge.enabled)
|
|
26
|
+
return response;
|
|
27
|
+
return forge.handle(request, () => response);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
package/dist/openapi.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export interface EnrichOptions {
|
|
|
16
16
|
describeOperations?: boolean;
|
|
17
17
|
/** Also document the optional rate_this_call body field (when the SDK's rateHint is on). */
|
|
18
18
|
hintField?: boolean;
|
|
19
|
+
/** Document optional agent context on paid operations: `agent_context` in JSON request bodies, agent_* query parameters otherwise. */
|
|
20
|
+
agentContext?: {
|
|
21
|
+
searchQuery: boolean;
|
|
22
|
+
};
|
|
19
23
|
}
|
|
20
24
|
export interface OperationReport {
|
|
21
25
|
method: string;
|
|
@@ -23,6 +27,8 @@ export interface OperationReport {
|
|
|
23
27
|
path: string;
|
|
24
28
|
/** Per 2xx status code: whether feedback_id was added to its JSON schema. */
|
|
25
29
|
responses: Record<string, ResponseSupport>;
|
|
30
|
+
/** Where optional agent context was documented, if asked to. */
|
|
31
|
+
agentContext?: "body" | "query" | "not_added";
|
|
26
32
|
reasons: string[];
|
|
27
33
|
}
|
|
28
34
|
export interface EnrichReport {
|
package/dist/openapi.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Additive, idempotent OpenAPI enrichment for Swagger 2.0 and OpenAPI 3.0 / 3.1 / 3.2.
|
|
2
2
|
// Rules: never mutate the input, never modify a shared $ref target, never override merchant paths,
|
|
3
3
|
// and on any unexpected input return the original document unchanged.
|
|
4
|
+
import { CONTEXT_FIELD, agentContextParameters, agentContextSchema } from "./context.js";
|
|
4
5
|
import { FEEDBACK_ID_PATTERN } from "./id.js";
|
|
5
6
|
import { ISSUES, NOTE_MAX_LENGTH, OUTCOMES, PROTOCOL } from "./values.js";
|
|
6
7
|
const METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
@@ -98,6 +99,58 @@ function extendSchema(doc, schema, props) {
|
|
|
98
99
|
copy.properties = { ...(isObj(copy.properties) ? copy.properties : {}), ...clone(props) };
|
|
99
100
|
return { schema: copy };
|
|
100
101
|
}
|
|
102
|
+
const BODYLESS = new Set(["get", "head", "delete", "options", "trace"]);
|
|
103
|
+
/** Document optional agent context on one paid operation. Never required; skipped when a schema can't take it safely. */
|
|
104
|
+
function addAgentContext(doc, version, item, method, op, opts, report) {
|
|
105
|
+
const resolve = (v) => (isObj(v) && typeof v.$ref === "string" ? resolveRef(doc, v.$ref) : v);
|
|
106
|
+
const listed = [...(Array.isArray(item.parameters) ? item.parameters : []), ...(Array.isArray(op.parameters) ? op.parameters : [])].map(resolve).filter(isObj);
|
|
107
|
+
const props = { [CONTEXT_FIELD]: agentContextSchema(opts) };
|
|
108
|
+
const notAdded = (reason) => {
|
|
109
|
+
report.agentContext = "not_added";
|
|
110
|
+
report.reasons.push(`request: ${reason}`);
|
|
111
|
+
};
|
|
112
|
+
if (BODYLESS.has(method)) {
|
|
113
|
+
const taken = new Set(listed.filter((p) => p.in === "query").map((p) => p.name));
|
|
114
|
+
const params = agentContextParameters(opts).filter((p) => !taken.has(p.name));
|
|
115
|
+
if (!params.length)
|
|
116
|
+
return notAdded("parameter_collision");
|
|
117
|
+
const documented = params.map((p) => version === "2.0"
|
|
118
|
+
? { name: p.name, in: "query", required: false, description: p.description, ...p.schema }
|
|
119
|
+
: { name: p.name, in: "query", required: false, description: p.description, schema: p.schema });
|
|
120
|
+
op.parameters = [...(Array.isArray(op.parameters) ? op.parameters : []), ...documented];
|
|
121
|
+
report.agentContext = "query";
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (version === "2.0") {
|
|
125
|
+
const params = Array.isArray(op.parameters) ? op.parameters : [];
|
|
126
|
+
const index = params.findIndex((p) => resolve(p)?.in === "body");
|
|
127
|
+
if (index < 0)
|
|
128
|
+
return notAdded("no_request_body");
|
|
129
|
+
const param = clone(resolve(params[index]));
|
|
130
|
+
const result = extendSchema(doc, param.schema, props);
|
|
131
|
+
if ("reason" in result)
|
|
132
|
+
return notAdded(result.reason);
|
|
133
|
+
param.schema = result.schema;
|
|
134
|
+
op.parameters = params.map((p, i) => (i === index ? param : p)); // inline copy if it was a shared $ref
|
|
135
|
+
report.agentContext = "body";
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const body = resolve(op.requestBody);
|
|
139
|
+
if (!isObj(body) || !isObj(body.content))
|
|
140
|
+
return notAdded("no_request_body");
|
|
141
|
+
const copy = clone(body);
|
|
142
|
+
const media = Object.entries(copy.content).filter(([type, entry]) => isJsonMedia(type) && isObj(entry) && "schema" in entry);
|
|
143
|
+
if (!media.length)
|
|
144
|
+
return notAdded("no_json_request_body");
|
|
145
|
+
for (const [, entry] of media) {
|
|
146
|
+
const result = extendSchema(doc, entry.schema, props);
|
|
147
|
+
if ("reason" in result)
|
|
148
|
+
return notAdded(result.reason);
|
|
149
|
+
entry.schema = result.schema;
|
|
150
|
+
}
|
|
151
|
+
op.requestBody = copy; // inline copy if it was a shared $ref
|
|
152
|
+
report.agentContext = "body";
|
|
153
|
+
}
|
|
101
154
|
const isJsonMedia = (type) => /^application\/(?:[\w.+-]+\+)?json\b/i.test(type);
|
|
102
155
|
const is2xx = (code) => /^2(\d\d|XX)$/i.test(code);
|
|
103
156
|
function appendSentence(text, sentence, marker) {
|
|
@@ -280,6 +333,8 @@ export function enrichOpenApi(input, options) {
|
|
|
280
333
|
op.responses[code] = response; // inline copy if it was a shared $ref
|
|
281
334
|
opReport.responses[code] = "extended";
|
|
282
335
|
}
|
|
336
|
+
if (options.agentContext)
|
|
337
|
+
addAgentContext(doc, version, item, method, op, options.agentContext, opReport);
|
|
283
338
|
// agentcash-style payment metadata carries its own output schema.
|
|
284
339
|
const info = op["x-payment-info"];
|
|
285
340
|
if (isObj(info) && isObj(info.outputSchema)) {
|
package/dist/reporter.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { AgentContext } from "./context.js";
|
|
1
2
|
export type ForgeEvent = {
|
|
2
3
|
type: "challenge";
|
|
3
4
|
route: string;
|
|
4
5
|
ts: number;
|
|
5
6
|
user_agent?: string;
|
|
7
|
+
agent_context?: AgentContext;
|
|
6
8
|
} | {
|
|
7
9
|
type: "interaction";
|
|
8
10
|
feedback_id: string;
|
|
@@ -12,7 +14,12 @@ export type ForgeEvent = {
|
|
|
12
14
|
payer?: string;
|
|
13
15
|
network?: string;
|
|
14
16
|
amount?: string;
|
|
17
|
+
scheme?: string;
|
|
18
|
+
asset?: string;
|
|
19
|
+
/** Settlement transaction reference from the receipt. */
|
|
20
|
+
transaction?: string;
|
|
15
21
|
user_agent?: string;
|
|
22
|
+
agent_context?: AgentContext;
|
|
16
23
|
ts: number;
|
|
17
24
|
};
|
|
18
25
|
/** Batches events to the backend in the background. Drops the oldest events if the backend stays down. */
|
package/dist/x402.d.ts
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
import { type Tone } from "./ask.js";
|
|
2
|
+
/** Key of the Forge extension in x402 v2 `extensions`: in the 402 challenge (next to e.g. `bazaar`) and in the payment receipt. */
|
|
2
3
|
export declare const FEEDBACK_EXTENSION = "forge-feedback";
|
|
3
4
|
/**
|
|
4
5
|
* The `forge-feedback` challenge extension: how to rate the call, as structured data. Clients that inspect
|
|
5
6
|
* the 402 (e.g. `awal x402 details`) print every extension, so this reaches agents before they pay.
|
|
7
|
+
* With `agentContext`, it also says how to report agent context with the paid request.
|
|
6
8
|
*/
|
|
7
|
-
export declare function feedbackExtension(rateUrl: string): {
|
|
9
|
+
export declare function feedbackExtension(rateUrl: string, tone?: Tone, agentContext?: string): {
|
|
8
10
|
info: {
|
|
11
|
+
agent_context?: string | undefined;
|
|
12
|
+
rate: string;
|
|
13
|
+
outcome: string[];
|
|
14
|
+
feedback_id: string;
|
|
15
|
+
payment: string;
|
|
9
16
|
protocol: string;
|
|
10
17
|
ask: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
/** The receipt extension: the same ask, with the real feedback ID, in the settlement response after payment. */
|
|
21
|
+
export declare function receiptExtension(rateUrl: string, feedbackId: string, tone?: Tone): {
|
|
22
|
+
info: {
|
|
23
|
+
protocol: string;
|
|
24
|
+
ask: string;
|
|
25
|
+
feedback_id: string;
|
|
11
26
|
rate: string;
|
|
12
27
|
outcome: string[];
|
|
13
|
-
feedback_id: string;
|
|
14
28
|
payment: string;
|
|
15
29
|
};
|
|
16
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Add the receipt extension to a base64 PAYMENT-RESPONSE header (x402 v2 settlement response), only when
|
|
33
|
+
* settlement succeeded. The receipt is informational for the client: facilitator fields are untouched.
|
|
34
|
+
* Returns undefined when the header can't be parsed, settlement failed, or the extension is already there.
|
|
35
|
+
*/
|
|
36
|
+
export declare function describeReceipt(headerValue: string, extension: unknown): string | undefined;
|
|
17
37
|
/** What the SDK adds to a challenge. Each part is skipped when already present. */
|
|
18
38
|
export interface ChallengeAdditions {
|
|
19
39
|
/** Appended to the description (v2 resource.description, v1 accepts[].description). */
|
|
@@ -40,6 +60,12 @@ export interface PaymentFacts {
|
|
|
40
60
|
payer?: string;
|
|
41
61
|
network?: string;
|
|
42
62
|
amount?: string;
|
|
63
|
+
scheme?: string;
|
|
64
|
+
asset?: string;
|
|
65
|
+
/** Settlement transaction reference, from the receipt (see readReceipt). */
|
|
66
|
+
transaction?: string;
|
|
43
67
|
}
|
|
44
|
-
/** Best-effort read of the payer, network and
|
|
68
|
+
/** Best-effort read of the payer, network, amount, scheme and asset from an x402 v1/v2 payment header. Never throws. */
|
|
45
69
|
export declare function readPaymentHeader(headerValue: string): PaymentFacts;
|
|
70
|
+
/** Best-effort read of a successful settlement receipt (base64 PAYMENT-RESPONSE): transaction, payer, network. Never throws. */
|
|
71
|
+
export declare function readReceipt(headerValue: string): Pick<PaymentFacts, "transaction" | "payer" | "network">;
|
package/dist/x402.js
CHANGED
|
@@ -1,22 +1,60 @@
|
|
|
1
|
+
import { ASK } from "./ask.js";
|
|
1
2
|
import { PROTOCOL } from "./values.js";
|
|
2
|
-
/** Key of the Forge extension in
|
|
3
|
+
/** Key of the Forge extension in x402 v2 `extensions`: in the 402 challenge (next to e.g. `bazaar`) and in the payment receipt. */
|
|
3
4
|
export const FEEDBACK_EXTENSION = "forge-feedback";
|
|
4
5
|
/**
|
|
5
6
|
* The `forge-feedback` challenge extension: how to rate the call, as structured data. Clients that inspect
|
|
6
7
|
* the 402 (e.g. `awal x402 details`) print every extension, so this reaches agents before they pay.
|
|
8
|
+
* With `agentContext`, it also says how to report agent context with the paid request.
|
|
7
9
|
*/
|
|
8
|
-
export function feedbackExtension(rateUrl) {
|
|
10
|
+
export function feedbackExtension(rateUrl, tone = "soft", agentContext) {
|
|
9
11
|
return {
|
|
10
12
|
info: {
|
|
11
13
|
protocol: PROTOCOL,
|
|
12
|
-
ask:
|
|
14
|
+
ask: ASK[tone].extensionAsk,
|
|
15
|
+
...ASK[tone].extensionExtras,
|
|
13
16
|
rate: `GET ${rateUrl}?feedback_id=FEEDBACK_ID&outcome=fully`,
|
|
14
17
|
outcome: ["fully", "partially", "no"],
|
|
15
18
|
feedback_id: "In the paid response body (feedback_id) and the Forge-Feedback-Id header.",
|
|
16
19
|
payment: "None. Plain GET, not an x402 endpoint.",
|
|
20
|
+
...(agentContext ? { agent_context: agentContext } : {}),
|
|
17
21
|
},
|
|
18
22
|
};
|
|
19
23
|
}
|
|
24
|
+
/** The receipt extension: the same ask, with the real feedback ID, in the settlement response after payment. */
|
|
25
|
+
export function receiptExtension(rateUrl, feedbackId, tone = "soft") {
|
|
26
|
+
return {
|
|
27
|
+
info: {
|
|
28
|
+
protocol: PROTOCOL,
|
|
29
|
+
ask: ASK[tone].extensionAsk,
|
|
30
|
+
feedback_id: feedbackId,
|
|
31
|
+
rate: `GET ${rateUrl}?feedback_id=${feedbackId}&outcome=fully`,
|
|
32
|
+
outcome: ["fully", "partially", "no"],
|
|
33
|
+
payment: "None. Plain GET, not an x402 endpoint.",
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Add the receipt extension to a base64 PAYMENT-RESPONSE header (x402 v2 settlement response), only when
|
|
39
|
+
* settlement succeeded. The receipt is informational for the client: facilitator fields are untouched.
|
|
40
|
+
* Returns undefined when the header can't be parsed, settlement failed, or the extension is already there.
|
|
41
|
+
*/
|
|
42
|
+
export function describeReceipt(headerValue, extension) {
|
|
43
|
+
let receipt;
|
|
44
|
+
try {
|
|
45
|
+
receipt = JSON.parse(Buffer.from(headerValue, "base64").toString("utf8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
if (!receipt || typeof receipt !== "object" || receipt.success !== true)
|
|
51
|
+
return undefined;
|
|
52
|
+
const extensions = receipt.extensions;
|
|
53
|
+
if (extensions !== undefined && extensions !== null && (typeof extensions !== "object" || Array.isArray(extensions) || FEEDBACK_EXTENSION in extensions))
|
|
54
|
+
return undefined;
|
|
55
|
+
receipt.extensions = { ...extensions, [FEEDBACK_EXTENSION]: extension };
|
|
56
|
+
return Buffer.from(JSON.stringify(receipt), "utf8").toString("base64");
|
|
57
|
+
}
|
|
20
58
|
function appendSentence(description, sentence, marker) {
|
|
21
59
|
const current = typeof description === "string" ? description.trim() : "";
|
|
22
60
|
return current.includes(marker) ? current : current ? `${current} ${sentence}` : sentence;
|
|
@@ -91,7 +129,7 @@ export function describeChallengeBody(body, additions) {
|
|
|
91
129
|
}
|
|
92
130
|
return undefined;
|
|
93
131
|
}
|
|
94
|
-
/** Best-effort read of the payer, network and
|
|
132
|
+
/** Best-effort read of the payer, network, amount, scheme and asset from an x402 v1/v2 payment header. Never throws. */
|
|
95
133
|
export function readPaymentHeader(headerValue) {
|
|
96
134
|
try {
|
|
97
135
|
const p = JSON.parse(Buffer.from(headerValue, "base64").toString("utf8"));
|
|
@@ -100,6 +138,8 @@ export function readPaymentHeader(headerValue) {
|
|
|
100
138
|
payer: authorization?.from,
|
|
101
139
|
network: p?.accepted?.network ?? p?.network,
|
|
102
140
|
amount: p?.accepted?.amount ?? authorization?.value,
|
|
141
|
+
scheme: p?.accepted?.scheme ?? p?.scheme,
|
|
142
|
+
asset: p?.accepted?.asset,
|
|
103
143
|
};
|
|
104
144
|
for (const key of Object.keys(facts)) {
|
|
105
145
|
if (typeof facts[key] !== "string")
|
|
@@ -111,3 +151,20 @@ export function readPaymentHeader(headerValue) {
|
|
|
111
151
|
return {};
|
|
112
152
|
}
|
|
113
153
|
}
|
|
154
|
+
/** Best-effort read of a successful settlement receipt (base64 PAYMENT-RESPONSE): transaction, payer, network. Never throws. */
|
|
155
|
+
export function readReceipt(headerValue) {
|
|
156
|
+
try {
|
|
157
|
+
const r = JSON.parse(Buffer.from(headerValue, "base64").toString("utf8"));
|
|
158
|
+
if (r?.success !== true)
|
|
159
|
+
return {};
|
|
160
|
+
const facts = { transaction: r.transaction, payer: r.payer, network: r.network };
|
|
161
|
+
for (const key of Object.keys(facts)) {
|
|
162
|
+
if (typeof facts[key] !== "string" || !facts[key])
|
|
163
|
+
delete facts[key];
|
|
164
|
+
}
|
|
165
|
+
return facts;
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeintel/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The Forge SDK for x402 paid APIs: agent feedback (feedback IDs, one-request GET ratings), OpenAPI and challenge enrichment, and passive call signals. Express
|
|
3
|
+
"version": "0.4.0-beta.0",
|
|
4
|
+
"description": "The Forge SDK for x402 paid APIs: agent feedback (feedback IDs, one-request GET ratings), agent context, OpenAPI and challenge enrichment, and passive call signals. Express, Hono, Next.js and any fetch handler. Never on your critical path.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -23,6 +23,21 @@
|
|
|
23
23
|
"import": "./dist/core.js",
|
|
24
24
|
"default": "./dist/core.js"
|
|
25
25
|
},
|
|
26
|
+
"./fetch": {
|
|
27
|
+
"types": "./dist/fetch.d.ts",
|
|
28
|
+
"import": "./dist/fetch.js",
|
|
29
|
+
"default": "./dist/fetch.js"
|
|
30
|
+
},
|
|
31
|
+
"./hono": {
|
|
32
|
+
"types": "./dist/hono.d.ts",
|
|
33
|
+
"import": "./dist/hono.js",
|
|
34
|
+
"default": "./dist/hono.js"
|
|
35
|
+
},
|
|
36
|
+
"./next": {
|
|
37
|
+
"types": "./dist/next.d.ts",
|
|
38
|
+
"import": "./dist/next.js",
|
|
39
|
+
"default": "./dist/next.js"
|
|
40
|
+
},
|
|
26
41
|
"./package.json": "./package.json"
|
|
27
42
|
},
|
|
28
43
|
"types": "./dist/index.d.ts",
|
|
@@ -40,7 +55,11 @@
|
|
|
40
55
|
"openapi",
|
|
41
56
|
"express",
|
|
42
57
|
"payments",
|
|
43
|
-
"forge"
|
|
58
|
+
"forge",
|
|
59
|
+
"hono",
|
|
60
|
+
"nextjs",
|
|
61
|
+
"cloudflare-workers",
|
|
62
|
+
"bun"
|
|
44
63
|
],
|
|
45
64
|
"repository": {
|
|
46
65
|
"type": "git",
|
|
@@ -57,25 +76,24 @@
|
|
|
57
76
|
"tag": "beta"
|
|
58
77
|
},
|
|
59
78
|
"peerDependencies": {
|
|
60
|
-
"express": ">=4.21 <6"
|
|
79
|
+
"express": ">=4.21 <6",
|
|
80
|
+
"hono": ">=4"
|
|
61
81
|
},
|
|
62
82
|
"peerDependenciesMeta": {
|
|
63
83
|
"express": {
|
|
64
84
|
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"hono": {
|
|
87
|
+
"optional": true
|
|
65
88
|
}
|
|
66
89
|
},
|
|
67
90
|
"devDependencies": {
|
|
68
91
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
69
92
|
"@types/express": "^5.0.3",
|
|
70
93
|
"@types/node": "^22.18.0",
|
|
71
|
-
"@x402/core": "~2.25.0",
|
|
72
|
-
"@x402/evm": "~2.25.0",
|
|
73
|
-
"@x402/express": "~2.25.0",
|
|
74
94
|
"ajv": "^8.20.0",
|
|
75
95
|
"ajv-formats": "^3.0.1",
|
|
76
|
-
"
|
|
77
|
-
"typescript": "^5.9.2"
|
|
78
|
-
"viem": "^2.56.3",
|
|
79
|
-
"x402-express": "^1.2.0"
|
|
96
|
+
"hono": "^4.13.7",
|
|
97
|
+
"typescript": "^5.9.2"
|
|
80
98
|
}
|
|
81
99
|
}
|