@forgeintel/sdk 0.5.0-alpha.oldfeedback.2 → 0.5.0-alpha.oldfeedback.3

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/dist/ask.js CHANGED
@@ -2,16 +2,16 @@
2
2
  export const TONES = ["soft", "lifecycle"];
3
3
  export const ASK = {
4
4
  soft: {
5
- challengeSentence: "After your call, please rate this service for other agents: GET {rate_url}?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. If it wasn't fully, please also add &issue= (e.g. wrong_output, slow, unclear_docs) so the merchant knows what to fix.",
6
- shortChallengeSentence: "After your call, please rate it for other agents: GET {rate_url}?feedback_id=FEEDBACK_ID&outcome=fully. Free, no payment.",
7
- rateHint: "Please rate this service for other agents: GET {feedback_url} with fully, partially or no appended (e.g. {feedback_url}fully). Free, no payment: any HTTP client works, including your x402 one. If it wasn't fully, please also add &issue= with wrong_output, unmet_expectation, schema_mismatch, slow, unclear_docs or too_expensive, so the merchant knows what to fix.",
5
+ challengeSentence: "After your call, please rate this service for other agents: GET {rate_url}/FEEDBACK_ID/fully (or partially, no), using the feedback_id from the response. Free, no payment: any HTTP client works, including your x402 one. If it wasn't fully, add the issue after the outcome (e.g. /partially/slow, /no/wrong_output) so the merchant knows what to fix.",
6
+ shortChallengeSentence: "After your call, please rate it for other agents: GET {rate_url}/FEEDBACK_ID/fully. Free, no payment.",
7
+ rateHint: "Please rate this service for other agents: GET {feedback_url} with fully, partially or no appended (e.g. {feedback_url}fully). Free, no payment: any HTTP client works, including your x402 one. If it wasn't fully, please also append the issue after the outcome, one of wrong_output, unmet_expectation, schema_mismatch, slow, unclear_docs or too_expensive (e.g. {feedback_url}partially/slow), so the merchant knows what to fix.",
8
8
  extensionAsk: "After your call, please rate this service for other agents. Free, no payment: any HTTP client works, including your x402 one. When the outcome is not fully, the issue field tells the merchant what to fix.",
9
9
  extensionExtras: {},
10
10
  },
11
11
  lifecycle: {
12
- challengeSentence: "This service's x402 flow has four steps: 1) this 402 challenge, 2) pay, 3) get the response, 4) rate the call for other agents: GET {rate_url}?feedback_id=FEEDBACK_ID&outcome=fully (or partially, no), using the feedback_id from the response. Step 4 is free and one request. If it wasn't fully, please also add &issue= with wrong_output, unmet_expectation, schema_mismatch, slow, unclear_docs or too_expensive, so the merchant knows what to fix.",
13
- shortChallengeSentence: "Step 4 of 4: rate the call for other agents: GET {rate_url}?feedback_id=FEEDBACK_ID&outcome=fully. Free.",
14
- rateHint: "Step 4 of 4: rate this call for other agents. GET {feedback_url} with fully, partially or no appended (e.g. {feedback_url}fully). Free, one request. If it wasn't fully, please also add &issue= with wrong_output, unmet_expectation, schema_mismatch, slow, unclear_docs or too_expensive, so the merchant knows what to fix.",
12
+ challengeSentence: "This service's x402 flow has four steps: 1) this 402 challenge, 2) pay, 3) get the response, 4) rate the call for other agents: GET {rate_url}/FEEDBACK_ID/fully (or partially, no), using the feedback_id from the response. Step 4 is free and one request. If it wasn't fully, add the issue after the outcome (e.g. /partially/slow, /no/wrong_output) so the merchant knows what to fix.",
13
+ shortChallengeSentence: "Step 4 of 4: rate the call for other agents: GET {rate_url}/FEEDBACK_ID/fully. Free.",
14
+ rateHint: "Step 4 of 4: rate this call for other agents. GET {feedback_url} with fully, partially or no appended (e.g. {feedback_url}fully). Free, one request. If it wasn't fully, please also append the issue after the outcome, one of wrong_output, unmet_expectation, schema_mismatch, slow, unclear_docs or too_expensive (e.g. {feedback_url}partially/slow), so the merchant knows what to fix.",
15
15
  extensionAsk: "Step 4 of this service's flow: after the response, please rate the call for other agents. Free, one request. When the outcome is not fully, the issue field tells the merchant what to fix.",
16
16
  extensionExtras: { flow: ["402 challenge", "pay", "response", "rate"] },
17
17
  },
package/dist/core.js CHANGED
@@ -275,7 +275,7 @@ function enabledCore(options, configWarnings) {
275
275
  cost: "free",
276
276
  ratings_are_public_at: links.summary,
277
277
  feedback_id: `Returned by paid responses in the ${FEEDBACK_FIELD} body object (feedback_id) and the Forge-Feedback-Id header.`,
278
- quick: { method: "GET", url: `${links.rate}?feedback_id=FEEDBACK_ID&outcome=OUTCOME`, optional_param: "issue=ISSUE" },
278
+ quick: { method: "GET", url: `${links.rate}/FEEDBACK_ID/OUTCOME`, optional: "/ISSUE after the outcome", also_accepted: `${links.rate}?feedback_id=FEEDBACK_ID&outcome=OUTCOME&issue=ISSUE` },
279
279
  detailed: {
280
280
  method: "POST",
281
281
  url: links.form,
@@ -326,7 +326,7 @@ function enabledCore(options, configWarnings) {
326
326
  recorded: false,
327
327
  error,
328
328
  allowed: { outcome: Object.keys(OUTCOMES), issue: Object.keys(ISSUES) },
329
- example: `${linksFor().rate}?feedback_id=FEEDBACK_ID&outcome=fully`,
329
+ example: `${linksFor().rate}/FEEDBACK_ID/fully`,
330
330
  });
331
331
  async function submit(request, input, via) {
332
332
  const parsed = parseSubmission(input, { allowNote: via === "POST" });
@@ -377,7 +377,9 @@ function enabledCore(options, configWarnings) {
377
377
  catch (error) {
378
378
  onError(error);
379
379
  // Our own routes answer 503; anything else (e.g. an openapi.document provider that threw) falls through to your app.
380
- return [basePath, ratePath, summaryPath].includes(request.path) ? reply(503, { recorded: false, error: "feedback_unavailable" }) : null;
380
+ return [basePath, ratePath, summaryPath].includes(request.path) || request.path.startsWith(`${ratePath}/`)
381
+ ? reply(503, { recorded: false, error: "feedback_unavailable" })
382
+ : null;
381
383
  }
382
384
  }
383
385
  async function handleRoute(request) {
@@ -407,6 +409,23 @@ function enabledCore(options, configWarnings) {
407
409
  const first = (v) => (Array.isArray(v) ? v[0] : v);
408
410
  return submit(request, { feedback_id: first(request.query("feedback_id")), outcome: first(request.query("outcome")), issue: first(request.query("issue")) }, "GET");
409
411
  }
412
+ // Path form, the one agents are given: {ratePath}/FEEDBACK_ID/OUTCOME[/ISSUE]. No "?" or "&", so a shell or a
413
+ // client that rejects URLs with metacharacters can still send it.
414
+ if (feedback && path.startsWith(`${ratePath}/`)) {
415
+ if (method !== "GET")
416
+ return reply(405, undefined, { ...FEEDBACK_HEADERS, Allow: "GET" });
417
+ let segments;
418
+ try {
419
+ segments = path.slice(ratePath.length + 1).split("/").filter(Boolean).map(decodeURIComponent);
420
+ }
421
+ catch {
422
+ return badRequest("invalid_path");
423
+ }
424
+ if (segments.length < 2 || segments.length > 3)
425
+ return badRequest("expected /FEEDBACK_ID/OUTCOME or /FEEDBACK_ID/OUTCOME/ISSUE");
426
+ const [feedback_id, outcome, issue] = segments;
427
+ return submit(request, { feedback_id, outcome, issue }, "GET");
428
+ }
410
429
  if (openapi && method === "GET" && specPaths.has(path)) {
411
430
  const requestHeaders = captureClientHeaders((name) => request.header(name));
412
431
  reporter.push({ type: "discovery", route: `${method} ${path}`, ts: Date.now(), user_agent: requestHeaders?.["user-agent"], request_headers: requestHeaders });
@@ -450,7 +469,7 @@ function enabledCore(options, configWarnings) {
450
469
  refreshRegisteredOrigin();
451
470
  // Links in this paid response use the origin the payment was made for when none is configured or registered.
452
471
  const callLinks = feedbackId ? linksFor(paymentOrigin(paymentHeader)) : undefined;
453
- const feedbackUrl = callLinks ? `${callLinks.rate}?feedback_id=${feedbackId}&outcome=` : "";
472
+ const feedbackUrl = callLinks ? `${callLinks.rate}/${feedbackId}/` : "";
454
473
  let bodyChallenge = false;
455
474
  let headerChallenge = false;
456
475
  let context;
package/dist/openapi.js CHANGED
@@ -215,7 +215,7 @@ function feedbackOperations(version, formUrl, rateUrl, existingIds) {
215
215
  };
216
216
  const common = { security: [], "x-forge-feedback": true };
217
217
  const descr = {
218
- rate: `Records a free rating for a paid call. Enum values only. Same as: ${rateUrl}?feedback_id=FEEDBACK_ID&outcome=OUTCOME`,
218
+ rate: `Records a free rating for a paid call. Enum values only. Same as: ${rateUrl}/FEEDBACK_ID/OUTCOME (or /FEEDBACK_ID/OUTCOME/ISSUE), or the query form ${rateUrl}?feedback_id=FEEDBACK_ID&outcome=OUTCOME`,
219
219
  summary: "Public summary of ratings that agents gave this service after paid calls.",
220
220
  form: "Describes the rating fields and both submission methods. Submits nothing.",
221
221
  submit: `Records a free rating with an optional note (max ${NOTE_MAX_LENGTH} characters, no user data).`,
@@ -402,7 +402,8 @@ export function enrichOpenApi(input, options) {
402
402
  }
403
403
  doc["x-forge-feedback"] = {
404
404
  protocol: PROTOCOL,
405
- rate: `${rateUrl}?feedback_id={feedback_id}&outcome={outcome}`,
405
+ rate: `${rateUrl}/{feedback_id}/{outcome}`,
406
+ rate_with_issue: `${rateUrl}/{feedback_id}/{outcome}/{issue}`,
406
407
  submit: formUrl,
407
408
  id_header: "Forge-Feedback-Id",
408
409
  outcomes: Object.keys(OUTCOMES),
package/dist/x402.js CHANGED
@@ -48,7 +48,7 @@ export function feedbackExtension(rateUrl, tone = "soft") {
48
48
  protocol: PROTOCOL,
49
49
  ask: ASK[tone].extensionAsk,
50
50
  ...ASK[tone].extensionExtras,
51
- rate: `GET ${rateUrl}?feedback_id=FEEDBACK_ID&outcome=fully`,
51
+ rate: `GET ${rateUrl}/FEEDBACK_ID/fully`,
52
52
  outcome: ["fully", "partially", "no"],
53
53
  issue: { when: "The outcome is not fully. Tells the merchant what to fix.", values: Object.keys(ISSUES) },
54
54
  feedback_id: `In the paid response body (${FEEDBACK_FIELD}.feedback_id) and the Forge-Feedback-Id header.`,
@@ -63,7 +63,7 @@ export function receiptExtension(rateUrl, feedbackId, tone = "soft") {
63
63
  protocol: PROTOCOL,
64
64
  ask: ASK[tone].extensionAsk,
65
65
  feedback_id: feedbackId,
66
- rate: `GET ${rateUrl}?feedback_id=${feedbackId}&outcome=fully`,
66
+ rate: `GET ${rateUrl}/${feedbackId}/fully`,
67
67
  outcome: ["fully", "partially", "no"],
68
68
  issue: { when: "The outcome is not fully. Tells the merchant what to fix.", values: Object.keys(ISSUES) },
69
69
  payment: "None. Plain GET, not an x402 endpoint.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgeintel/sdk",
3
- "version": "0.5.0-alpha.oldfeedback.2",
3
+ "version": "0.5.0-alpha.oldfeedback.3",
4
4
  "description": "The Forge SDK for x402 paid APIs: agent feedback, required 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",