@forgeintel/sdk 0.5.0-alpha.oldfeedback.1 → 0.5.0-alpha.oldfeedback.1.b13
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 +17 -18
- package/dist/context.js +1 -1
- package/dist/core.d.ts +5 -4
- package/dist/core.js +9 -7
- package/dist/express.js +13 -3
- package/dist/fetch.js +8 -7
- package/dist/hono.js +0 -2
- package/dist/openapi.d.ts +2 -2
- package/dist/openapi.js +6 -2
- package/package.json +3 -7
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **Beta.** Install with `npm install @forgeintel/sdk`. The API may change before 1.0.
|
|
4
4
|
|
|
5
|
-
The Forge SDK for x402 paid APIs. Paid responses carry a `feedback_id`, the 402 challenge asks agents to rate the call, a rating is
|
|
5
|
+
The Forge SDK for x402 paid APIs. Paid responses carry a `feedback_id`, the 402 challenge asks agents to rate the call, a rating is a free GET with no payment, and every call is reported to your Forge dashboard in the background. Never on your critical path: no network calls while your API serves a request, and it fails open. Aware of x402 v1 and v2, and of OpenAPI 2.0 through 3.2. Every change is additive, and anything it doesn't understand passes through untouched.
|
|
6
6
|
|
|
7
7
|
## Express
|
|
8
8
|
|
|
@@ -11,22 +11,20 @@ import { createForge } from "@forgeintel/sdk";
|
|
|
11
11
|
|
|
12
12
|
const forge = createForge({
|
|
13
13
|
apiKey: process.env.FORGE_API_KEY,
|
|
14
|
-
agentContext: true,
|
|
15
|
-
feedback: true,
|
|
16
14
|
});
|
|
17
15
|
|
|
18
16
|
app.use(forge.middleware()); // 1. first: before payments and your /openapi.json route
|
|
19
17
|
app.use(paymentMiddleware(routes, resourceServer)); // 2. your existing x402 setup, unchanged
|
|
20
18
|
```
|
|
21
19
|
|
|
22
|
-
Works with `@x402/express` (v2) and `x402-express` (v1), on Express 4.21+ or 5. The root export is the Express adapter (also at `@forgeintel/sdk/express`).
|
|
20
|
+
Works with `@x402/express` (v2) and `x402-express` (v1), on Express 4.21+ or 5. Complete example: [forge-examples/node-express](https://github.com/tryforgeintel/forge-examples/tree/main/node-express). The root export is the Express adapter (also at `@forgeintel/sdk/express`).
|
|
23
21
|
|
|
24
22
|
## Hono (Node, Bun, Deno, Cloudflare Workers)
|
|
25
23
|
|
|
26
24
|
```ts
|
|
27
25
|
import { createForge } from "@forgeintel/sdk/hono";
|
|
28
26
|
|
|
29
|
-
const forge = createForge({ apiKey
|
|
27
|
+
const forge = createForge({ apiKey });
|
|
30
28
|
app.use(forge.middleware()); // before paymentMiddleware from @x402/hono
|
|
31
29
|
app.use(paymentMiddleware(routes, resourceServer));
|
|
32
30
|
```
|
|
@@ -36,7 +34,7 @@ app.use(paymentMiddleware(routes, resourceServer));
|
|
|
36
34
|
```ts
|
|
37
35
|
import { createForge } from "@forgeintel/sdk/next";
|
|
38
36
|
|
|
39
|
-
export const forge = createForge({ apiKey
|
|
37
|
+
export const forge = createForge({ apiKey });
|
|
40
38
|
// app/api/…/route.ts: Forge outermost, around @x402/next's withX402
|
|
41
39
|
export const POST = forge.withForge(withX402(handler, route, resourceServer));
|
|
42
40
|
// app/feedback/[[...path]]/route.ts: Forge's own routes
|
|
@@ -49,7 +47,7 @@ export const { GET, POST, HEAD } = forge.routes;
|
|
|
49
47
|
|
|
50
48
|
## Any other framework
|
|
51
49
|
|
|
52
|
-
`@forgeintel/sdk/core` is the same logic without a framework. Call `forge.route()` first, then `forge.call()` per paid request, and `call.headers()` / `call.json()` / `call.finish()` where you build the 402 and the paid response. See the [core
|
|
50
|
+
`@forgeintel/sdk/core` is the same logic without a framework. Call `forge.route()` first, then `forge.call()` per paid request, and `call.headers()` / `call.json()` / `call.finish()` where you build the 402 and the paid response. See the [core API reference](https://docs.forgeintel.co/reference/core-api).
|
|
53
51
|
|
|
54
52
|
Zero runtime dependencies. Node ≥ 20.19. Works from both `import` and `require()`.
|
|
55
53
|
|
|
@@ -57,8 +55,8 @@ Zero runtime dependencies. Node ≥ 20.19. Works from both `import` and `require
|
|
|
57
55
|
|
|
58
56
|
| When | What happens |
|
|
59
57
|
| --- | --- |
|
|
60
|
-
| 402 challenge | Appends one line to the description: *
|
|
61
|
-
| Paid 2xx response | Adds the `Forge-Feedback-Id` header. JSON object bodies also get one `forge_feedback` object: `feedback_id`, `
|
|
58
|
+
| 402 challenge | Appends one line to the description: *After your call, please rate this service for other agents: GET https://…/feedback/rate?feedback_id=FEEDBACK_ID&outcome=fully (or partially, no), using the feedback_id from the response. Free, no payment: any HTTP client works, including your x402 one. …* On x402 v2 it also adds an `extensions["forge-feedback"]` block with the `ask`, the rating link, and the outcome and issue values. The description never exceeds 500 characters (the CDP facilitator rejects longer ones): a shorter line is used when the full one doesn't fit, and none when neither does. Payment terms are never touched. |
|
|
59
|
+
| Paid 2xx response | Adds the `Forge-Feedback-Id` header. JSON object bodies also get one `forge_feedback` object: `feedback_id`, `feedback_url` (with `outcome=` left blank) and `rate_this_call`, unless your body already has a `forge_feedback` key or your OpenAPI schema for that response couldn't safely take it. Rating links are absolute: your origin registered in Forge, fetched in the background, or the request's own x402 resource origin. |
|
|
62
60
|
| `GET /openapi.json` | Your document is served enriched: feedback routes documented, feedback fields added to paid response schemas, one sentence in `x-guidance`. |
|
|
63
61
|
| `GET /feedback/rate` | Quick rating: `feedback_id`, `outcome`, optional `issue`. |
|
|
64
62
|
| `POST /feedback` | Same fields, plus an optional `note` (≤ 280 chars). |
|
|
@@ -93,7 +91,7 @@ OpenAPI: Swagger 2.0 and OpenAPI 3.0, 3.1 and 3.2. Additive only; shared compone
|
|
|
93
91
|
| `challengeSentence` | built-in | Override for wording experiments. `{rate_url}` and `{summary_url}` are substituted. Wording that presents the rating as required, makes anything depend on it, or asks for user data is refused (with a warning). |
|
|
94
92
|
| `challengeExtension` | `true` | Add the `forge-feedback` extension to x402 v2 challenges. |
|
|
95
93
|
| `receiptExtension` | `true` | Add it, with the real `feedback_id`, to the x402 v2 payment receipt (`PAYMENT-RESPONSE`). |
|
|
96
|
-
| `agentContext` |
|
|
94
|
+
| `agentContext` | optional | Ask for self-reported `agent_context` (agent name, search query) on paid requests; record and strip it before your code runs. Unset, it is optional and never rejects a request. `true` (or `{ required: true }`) requires it before payment processing. `{ searchQuery: false }` stops asking for the search query; `false` disables collection. |
|
|
97
95
|
| `injectBody` | `true` | Add the `forge_feedback` object to paid JSON bodies. |
|
|
98
96
|
| `rateHint` | built-in | The `forge_feedback.rate_this_call` field. A string overrides it (`{feedback_url}` is substituted); `false` removes it. |
|
|
99
97
|
| `injectText` | `false` | Append a two-line trailer to paid `text/plain` bodies. |
|
|
@@ -105,23 +103,24 @@ OpenAPI: Swagger 2.0 and OpenAPI 3.0, 3.1 and 3.2. Additive only; shared compone
|
|
|
105
103
|
|
|
106
104
|
`forge.diagnostics()` returns counters and the last OpenAPI report. `forge.enrichOpenApi(doc)` is available for build-time use. Call `await forge.shutdown()` in your shutdown handler to flush pending events.
|
|
107
105
|
|
|
108
|
-
|
|
106
|
+
Runnable examples (Express and FastAPI): [github.com/tryforgeintel/forge-examples](https://github.com/tryforgeintel/forge-examples). Docs: [docs.forgeintel.co](https://docs.forgeintel.co).
|
|
109
107
|
|
|
110
108
|
Client headers are captured automatically at discovery, challenge, payment, and rating stages, including unknown clients. Forge identifies awal, AgentCash, pay.sh and x402scan-mcp from known headers; other clients remain unknown. There is no client-signals switch. Legacy `agent_context.client` inputs remain accepted but are no longer requested.
|
|
111
109
|
|
|
112
110
|
### Agent context on paid requests
|
|
113
111
|
|
|
114
112
|
```ts
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
113
|
+
createForge({ apiKey }); // default: asked for, optional
|
|
114
|
+
createForge({ apiKey, agentContext: true }); // required before payment
|
|
115
|
+
createForge({ apiKey, agentContext: { searchQuery: false } }); // required, agent name only
|
|
116
|
+
createForge({ apiKey, agentContext: { required: false, searchQuery: false } }); // optional, agent name only
|
|
117
|
+
createForge({ apiKey, agentContext: false }); // off
|
|
119
118
|
```
|
|
120
119
|
|
|
121
|
-
|
|
120
|
+
By default Forge asks for context and records it whenever an agent sends it, but a paid request without it is never rejected, so existing paying clients keep working. Forge documents `agent_context` and its `agent_type` and `search_query` fields as optional. Any agent name is accepted; known spellings are normalized (`Claude` and `claude-code` become `Claude Code`). Send the search query, or `"direct"`. When the merchant declares a `bazaar` extension, Forge adds the same field there (schema and example), so agents that discover the service through Bazaar see it too. Context is self-reported, not authenticated identity.
|
|
122
121
|
|
|
123
|
-
|
|
122
|
+
`agentContext: true`, or an object without `required: false`, makes context required: Forge documents the fields as required, and a request carrying `PAYMENT-SIGNATURE` or `X-PAYMENT` gets HTTP 400 with field errors when context is missing or invalid, before the downstream payment handler runs. Mount Forge **before payment middleware**. Initial unpaid requests can still receive a 402, and inspection and feedback routes stay accessible. Feedback has its own `feedback` switch.
|
|
124
123
|
|
|
125
124
|
Required mode reads JSON bodies up to 1 MiB, including chunked bodies, before payment processing. It rejects malformed or oversized JSON. Express parses these bodies even if your JSON parser is mounted later; mount a custom parser before Forge if you need one. For non-JSON bodies and bodyless requests, supply `agent_type` and `agent_search_query` query parameters. Forge strips context before forwarding to merchant validators. Next.js integrations that use a payment proxy should wrap both the proxy with `forge.proxy(...)` and the route with `forge.withForge(...)`.
|
|
126
125
|
|
|
127
|
-
If using the framework-free core directly, call `requestUrl` and `requestBody`, then check `call.contextError()` **before** invoking your payment logic; send its response when non-null
|
|
126
|
+
If using the framework-free core directly, call `requestUrl` and `requestBody`, then check `call.contextError()` **before** invoking your payment logic; send its response when non-null (it is always null when context is optional).
|
package/dist/context.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Self-reported facts about the calling agent, removed before merchant validation.
|
|
2
|
-
//
|
|
2
|
+
// Optional by default; merchants can require context on payment-bearing requests.
|
|
3
3
|
/** Suggested agent names; anything else is kept as given. */
|
|
4
4
|
export const AGENT_TYPES = ["Claude Code", "Codex", "Cursor", "Grok Bot", "Muse", "Hermes", "Instinct", "OpenClaw", "Others"];
|
|
5
5
|
/** Spellings agents use for the suggested names, compared lowercase with only letters and digits kept. */
|
package/dist/core.d.ts
CHANGED
|
@@ -50,13 +50,14 @@ export interface ForgeOptions {
|
|
|
50
50
|
*/
|
|
51
51
|
receiptExtension?: boolean;
|
|
52
52
|
/**
|
|
53
|
-
* Agent context:
|
|
53
|
+
* Agent context: self-reported `agent_context` {agent_type, search_query} on the paid request
|
|
54
54
|
* (JSON body, or agent_type / agent_search_query query parameters). Forge documents it in the
|
|
55
55
|
* extension and OpenAPI, reads it, reports it with the call, and removes it before your validators and handlers
|
|
56
|
-
* run.
|
|
56
|
+
* run. By default it is asked for but optional: a paid request without it is never rejected.
|
|
57
|
+
* `true` or `{ required: true }` requires it: payment-bearing requests with missing/invalid context get a 400
|
|
58
|
+
* before payment middleware (an object is required unless it sets `required: false`).
|
|
59
|
+
* `{ searchQuery: false }` stops asking for (and recording) the search query; `false` stops
|
|
57
60
|
* asking and recording altogether (the fields are still removed if an agent sends them).
|
|
58
|
-
* Enabled context rejects payment-bearing requests with missing/invalid context before payment middleware.
|
|
59
|
-
* `required` is retained for compatibility; `false` is ignored. Use `false` for agentContext to disable it.
|
|
60
61
|
*/
|
|
61
62
|
agentContext?: boolean | {
|
|
62
63
|
searchQuery?: boolean;
|
package/dist/core.js
CHANGED
|
@@ -67,8 +67,6 @@ export function checkOptions(input) {
|
|
|
67
67
|
fallback("agentContext", boolean(raw.agentContext) || (!!raw.agentContext && typeof raw.agentContext === "object" && !Array.isArray(raw.agentContext)), "must be true, false or { searchQuery, required }");
|
|
68
68
|
if (raw.agentContext && typeof raw.agentContext === "object" && !Array.isArray(raw.agentContext)) {
|
|
69
69
|
const context = raw.agentContext;
|
|
70
|
-
if (context.required === false)
|
|
71
|
-
warnings.push("agentContext.required: false is no longer supported; enabled context is required on paid requests. Set agentContext: false to disable context");
|
|
72
70
|
for (const key of ["required", "searchQuery"]) {
|
|
73
71
|
if (context[key] !== undefined && typeof context[key] !== "boolean") {
|
|
74
72
|
errors.push(`agentContext.${key} must be a boolean`);
|
|
@@ -106,7 +104,10 @@ export function checkOptions(input) {
|
|
|
106
104
|
}
|
|
107
105
|
return { errors, warnings, options };
|
|
108
106
|
}
|
|
109
|
-
/**
|
|
107
|
+
/**
|
|
108
|
+
* Used when invalid options turned Forge off: nothing is recorded or added, but agent context is still removed from
|
|
109
|
+
* requests, so agents that learned about it (an earlier deploy, a cached listing) can't trip strict validators.
|
|
110
|
+
*/
|
|
110
111
|
function disabledCore(errors, warnings) {
|
|
111
112
|
const passThrough = {
|
|
112
113
|
feedbackId: undefined,
|
|
@@ -115,8 +116,8 @@ function disabledCore(errors, warnings) {
|
|
|
115
116
|
json: (_status, body) => body,
|
|
116
117
|
text: (_status, _type, body) => body,
|
|
117
118
|
headers: () => ({}),
|
|
118
|
-
requestBody: (body) => body,
|
|
119
|
-
requestUrl: (url) => url,
|
|
119
|
+
requestBody: (body) => takeFromBody(body).body,
|
|
120
|
+
requestUrl: (url) => takeFromUrl(url).url,
|
|
120
121
|
finish: () => { },
|
|
121
122
|
};
|
|
122
123
|
return {
|
|
@@ -184,10 +185,11 @@ function enabledCore(options, configWarnings) {
|
|
|
184
185
|
const injectBody = options.injectBody ?? true;
|
|
185
186
|
const injectText = options.injectText ?? false;
|
|
186
187
|
const tone = options.tone ?? "soft";
|
|
187
|
-
const contextOption = options.agentContext
|
|
188
|
+
const contextOption = options.agentContext;
|
|
188
189
|
const collectContext = contextOption !== false;
|
|
189
190
|
const searchQuery = collectContext && (typeof contextOption !== "object" || contextOption.searchQuery !== false);
|
|
190
|
-
|
|
191
|
+
// Optional unless configured: true, or an object without required: false, keeps the strict (400) behavior.
|
|
192
|
+
const requiredContext = contextOption === true || (typeof contextOption === "object" && contextOption.required !== false);
|
|
191
193
|
const receipts = options.receiptExtension ?? true;
|
|
192
194
|
const rateHint = options.rateHint === false
|
|
193
195
|
? null
|
package/dist/express.js
CHANGED
|
@@ -135,7 +135,7 @@ export function createForge(options) {
|
|
|
135
135
|
core.onError(error);
|
|
136
136
|
}
|
|
137
137
|
if (call.contextRequired) {
|
|
138
|
-
//
|
|
138
|
+
// Required context: parse before payment middleware even when the merchant mounts express.json later.
|
|
139
139
|
// The body setter above captures context and leaves only merchant fields in req.body.
|
|
140
140
|
const parseError = await new Promise((resolve) => {
|
|
141
141
|
express.json({ limit: "1mb", type: ["application/json", "application/*+json"] })(req, res, resolve);
|
|
@@ -202,8 +202,18 @@ export function createForge(options) {
|
|
|
202
202
|
diagnostics: core.diagnostics,
|
|
203
203
|
shutdown: core.shutdown,
|
|
204
204
|
middleware() {
|
|
205
|
-
if (!core.enabled)
|
|
206
|
-
|
|
205
|
+
if (!core.enabled) {
|
|
206
|
+
// Disabled by invalid options: only remove agent context, so strict validators never see it.
|
|
207
|
+
return (req, _res, next) => {
|
|
208
|
+
try {
|
|
209
|
+
takeAgentContext(req, core.call({ method: req.method, path: req.path, header: () => undefined }));
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// never break the business request
|
|
213
|
+
}
|
|
214
|
+
next();
|
|
215
|
+
};
|
|
216
|
+
}
|
|
207
217
|
return (req, res, next) => {
|
|
208
218
|
core
|
|
209
219
|
.route({
|
package/dist/fetch.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Web-standard adapter: Request in, Response out. Works wherever handlers are (request) => Response:
|
|
2
2
|
// Hono, Next.js route handlers, Cloudflare Workers, Bun, Deno. The Hono and Next adapters build on this.
|
|
3
3
|
import { BODY_LIMIT, SPEC_LIMIT, createForgeCore } from "./core.js";
|
|
4
|
-
/** Buffer limit;
|
|
4
|
+
/** Buffer limit; required context rejects oversized paid JSON before payment processing. */
|
|
5
5
|
const JSON_LIMIT = 1024 * 1024;
|
|
6
6
|
const isJson = (type) => /^application\/(?:[\w.+-]+\+)?json\b/i.test(type ?? "");
|
|
7
7
|
export function toResponse(response) {
|
|
@@ -113,8 +113,6 @@ export function createForge(options) {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
async function handle(request, next) {
|
|
116
|
-
if (!core.enabled)
|
|
117
|
-
return next(request);
|
|
118
116
|
// Before the handler: our own routes, the spec, and agent context. Required-context errors stop paid attempts.
|
|
119
117
|
let call;
|
|
120
118
|
let forwarded = request;
|
|
@@ -135,10 +133,10 @@ export function createForge(options) {
|
|
|
135
133
|
if (without !== parsed)
|
|
136
134
|
body = JSON.stringify(without);
|
|
137
135
|
}
|
|
138
|
-
else if (request.body && isJson(request.headers.get("content-type")) && smallEnough(request.headers, JSON_LIMIT)) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
else if (request.body && isJson(request.headers.get("content-type")) && (smallEnough(request.headers, JSON_LIMIT) || !request.headers.has("content-length"))) {
|
|
137
|
+
// Optional context, best effort: a body that is too large or not JSON goes to the handler untouched.
|
|
138
|
+
const parsed = await boundedJson(request).catch(() => undefined);
|
|
139
|
+
if (parsed !== undefined) {
|
|
142
140
|
const without = call.requestBody(parsed);
|
|
143
141
|
if (without !== parsed)
|
|
144
142
|
body = JSON.stringify(without);
|
|
@@ -168,6 +166,9 @@ export function createForge(options) {
|
|
|
168
166
|
}
|
|
169
167
|
return next(request);
|
|
170
168
|
}
|
|
169
|
+
// Disabled by invalid options: agent context is removed (above), nothing else.
|
|
170
|
+
if (!core.enabled)
|
|
171
|
+
return next(forwarded);
|
|
171
172
|
const response = await next(forwarded);
|
|
172
173
|
// After the handler: decorate the 402 or the paid response. Any failure before the body is read: the original
|
|
173
174
|
// response goes out. Once read, the body is always sent from what was read (decorated or not).
|
package/dist/hono.js
CHANGED
|
@@ -10,8 +10,6 @@ export function createForge(options) {
|
|
|
10
10
|
shutdown: forge.shutdown,
|
|
11
11
|
validate: forge.validate,
|
|
12
12
|
middleware() {
|
|
13
|
-
if (!forge.enabled)
|
|
14
|
-
return async (_c, next) => next();
|
|
15
13
|
return async (c, next) => {
|
|
16
14
|
let ranNext = false;
|
|
17
15
|
const response = await forge.handle(c.req.raw, async (request) => {
|
package/dist/openapi.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ type Json = Record<string, any>;
|
|
|
2
2
|
export type SpecVersion = "2.0" | "3.0" | "3.1" | "3.2";
|
|
3
3
|
export type ResponseSupport = "extended" | "incompatible" | "undocumented";
|
|
4
4
|
export interface EnrichOptions {
|
|
5
|
-
/** Disable all feedback additions while retaining
|
|
5
|
+
/** Disable all feedback additions while retaining agent context. */
|
|
6
6
|
feedback?: boolean;
|
|
7
7
|
/** Optional merchant public origin. Without it, feedback links use same-origin paths. */
|
|
8
8
|
publicUrl?: string;
|
|
@@ -30,7 +30,7 @@ export interface OperationReport {
|
|
|
30
30
|
path: string;
|
|
31
31
|
/** Per 2xx status code: whether feedback_id was added to its JSON schema. */
|
|
32
32
|
responses: Record<string, ResponseSupport>;
|
|
33
|
-
/** Where
|
|
33
|
+
/** Where agent context was documented, if asked to. */
|
|
34
34
|
agentContext?: "body" | "query" | "not_added";
|
|
35
35
|
reasons: string[];
|
|
36
36
|
}
|
package/dist/openapi.js
CHANGED
|
@@ -61,6 +61,8 @@ function feedbackProperties(rateUrl, hintField = false) {
|
|
|
61
61
|
}
|
|
62
62
|
/** Returns an extended copy of an object schema, or a reason it can't be extended safely. */
|
|
63
63
|
function extendSchema(doc, schema, props) {
|
|
64
|
+
if (schema === true)
|
|
65
|
+
schema = {}; // `true` accepts any value, like {}
|
|
64
66
|
if (!isObj(schema))
|
|
65
67
|
return { reason: "no_schema" };
|
|
66
68
|
let target = schema;
|
|
@@ -83,7 +85,10 @@ function extendSchema(doc, schema, props) {
|
|
|
83
85
|
if (COMPOSITION.some((k) => k in copy))
|
|
84
86
|
return { reason: "composition" };
|
|
85
87
|
const types = Array.isArray(copy.type) ? copy.type : [copy.type];
|
|
86
|
-
|
|
88
|
+
// {} (annotations only) accepts any value, e.g. FastAPI's default response schema. `properties` only constrains
|
|
89
|
+
// objects, so documenting the field there narrows nothing.
|
|
90
|
+
const anyValue = Object.keys(copy).every((k) => ANNOTATIONS.has(k));
|
|
91
|
+
const objectish = anyValue || types.includes("object") || (copy.type === undefined && (isObj(copy.properties) || Array.isArray(copy.allOf)));
|
|
87
92
|
if (!objectish)
|
|
88
93
|
return { reason: "not_object" };
|
|
89
94
|
if ("propertyNames" in copy || "maxProperties" in copy)
|
|
@@ -110,7 +115,6 @@ function extendSchema(doc, schema, props) {
|
|
|
110
115
|
const BODYLESS = new Set(["get", "head", "delete", "options", "trace"]);
|
|
111
116
|
/** Document agent context on a paid operation; skip schemas that cannot be extended safely. */
|
|
112
117
|
function addAgentContext(doc, version, item, method, op, opts, report) {
|
|
113
|
-
opts = { ...opts, required: true }; // Enabled context cannot be made optional by a legacy option.
|
|
114
118
|
const resolve = (v) => (isObj(v) && typeof v.$ref === "string" ? resolveRef(doc, v.$ref) : v);
|
|
115
119
|
const listed = [...(Array.isArray(item.parameters) ? item.parameters : []), ...(Array.isArray(op.parameters) ? op.parameters : [])].map(resolve).filter(isObj);
|
|
116
120
|
const props = { [CONTEXT_FIELD]: agentContextSchema(opts) };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeintel/sdk",
|
|
3
|
-
"version": "0.5.0-alpha.oldfeedback.1",
|
|
4
|
-
"description": "The Forge SDK for x402 paid APIs: agent feedback,
|
|
3
|
+
"version": "0.5.0-alpha.oldfeedback.1.b13",
|
|
4
|
+
"description": "The Forge SDK for x402 paid APIs: agent feedback, agent context, OpenAPI and challenge enrichment, and passive call signals. Express, Hono, Next.js and fetch handlers. No Forge network request on the merchant response path.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
@@ -61,11 +61,7 @@
|
|
|
61
61
|
"cloudflare-workers",
|
|
62
62
|
"bun"
|
|
63
63
|
],
|
|
64
|
-
"
|
|
65
|
-
"type": "git",
|
|
66
|
-
"url": "git+https://github.com/ClawCash/forge-feedback.git",
|
|
67
|
-
"directory": "packages/sdk"
|
|
68
|
-
},
|
|
64
|
+
"homepage": "https://docs.forgeintel.co",
|
|
69
65
|
"scripts": {
|
|
70
66
|
"build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
71
67
|
"test": "node -e \"require('fs').rmSync('dist-test',{recursive:true,force:true})\" && tsc -p tsconfig.test.json && node --test --test-reporter=spec \"dist-test/test/**/*.test.js\"",
|