@haven_ai/signer 0.2.0-alpha.0 → 0.2.1-alpha.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 +41 -1
- package/dist/cli.cjs +85 -10
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +85 -10
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +85 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +85 -10
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -629,6 +629,49 @@ function stableStringify(value) {
|
|
|
629
629
|
const object = value;
|
|
630
630
|
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
631
631
|
}
|
|
632
|
+
var HavenSignContextError = class extends sdk.HavenSigningError {
|
|
633
|
+
/**
|
|
634
|
+
* #3001 / #3010 review: the recovery path, when signing OTHER bytes is
|
|
635
|
+
* actually a remedy — a transport failure (timeout, unreachable) or a
|
|
636
|
+
* body this signer could not read. `typed_data_b64` is NOT in the default
|
|
637
|
+
* quote result since #1272: obtain it by re-running the SAME quote tool
|
|
638
|
+
* with the SAME idempotency_key plus `include_signing_payload: true`.
|
|
639
|
+
* Absent on a backend REFUSAL: an expired, executed or unsignable intent
|
|
640
|
+
* cannot be rescued by re-signing its bytes.
|
|
641
|
+
*/
|
|
642
|
+
fallback;
|
|
643
|
+
/**
|
|
644
|
+
* #3001: `AgentPaymentNextAction` values the signer already emits — the
|
|
645
|
+
* version-mismatch refusal's `stop_and_tell_user` for the classes where
|
|
646
|
+
* retrying the same call cannot help, and `payment_window_expired` (with
|
|
647
|
+
* `retry_with_new_quote`) for the backend's 410 `expired`, exactly as the
|
|
648
|
+
* plain `HavenError` branch already does for that code.
|
|
649
|
+
*/
|
|
650
|
+
next_action;
|
|
651
|
+
retry_with_new_quote;
|
|
652
|
+
/** Present only for `SIGN_CONTEXT_REFUSED` (the backend's HTTP status). */
|
|
653
|
+
http_status;
|
|
654
|
+
/** Present only for `SIGN_CONTEXT_REFUSED`: the backend's own `error_code`. */
|
|
655
|
+
backend_error_code;
|
|
656
|
+
constructor(message, code, refusal) {
|
|
657
|
+
super(message);
|
|
658
|
+
this.code = code;
|
|
659
|
+
this.name = "HavenSignContextError";
|
|
660
|
+
if (code === "SIGN_CONTEXT_REFUSED") {
|
|
661
|
+
this.http_status = refusal?.httpStatus;
|
|
662
|
+
this.backend_error_code = refusal?.errorCode;
|
|
663
|
+
if (refusal?.httpStatus === 410 || refusal?.errorCode === "expired") {
|
|
664
|
+
this.next_action = sdk.AgentPaymentNextAction.PaymentWindowExpired;
|
|
665
|
+
this.retry_with_new_quote = true;
|
|
666
|
+
} else {
|
|
667
|
+
this.next_action = sdk.AgentPaymentNextAction.StopAndTellUser;
|
|
668
|
+
}
|
|
669
|
+
} else {
|
|
670
|
+
this.fallback = "typed_data_b64";
|
|
671
|
+
this.next_action = sdk.AgentPaymentNextAction.StopAndTellUser;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
};
|
|
632
675
|
async function loadHavenIdentity(credentialsPath) {
|
|
633
676
|
if (!credentialsPath) return null;
|
|
634
677
|
try {
|
|
@@ -643,30 +686,50 @@ async function loadHavenIdentity(credentialsPath) {
|
|
|
643
686
|
return null;
|
|
644
687
|
}
|
|
645
688
|
}
|
|
646
|
-
|
|
689
|
+
var SIGN_CONTEXT_TIMEOUT_MS = 15e3;
|
|
690
|
+
async function fetchX402SignContext(identity, paymentId, fetchImpl = fetch, timeoutMs = SIGN_CONTEXT_TIMEOUT_MS) {
|
|
647
691
|
let response;
|
|
648
692
|
try {
|
|
649
693
|
response = await fetchImpl(
|
|
650
694
|
`${identity.apiUrl}/x402/${encodeURIComponent(paymentId)}/sign-context`,
|
|
651
|
-
{
|
|
695
|
+
{
|
|
696
|
+
headers: { Authorization: `Bearer ${identity.apiKey}` },
|
|
697
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
698
|
+
}
|
|
652
699
|
);
|
|
653
700
|
} catch (err) {
|
|
654
|
-
|
|
655
|
-
|
|
701
|
+
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
702
|
+
throw new HavenSignContextError(
|
|
703
|
+
timedOut ? `Haven did not answer the signing-context fetch for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from the quote result instead.` : `Could not reach Haven to fetch the signing context for ${paymentId}: ${err instanceof Error ? err.message : String(err)}. Retry, or pass typed_data_b64 from the quote result instead.`,
|
|
704
|
+
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE"
|
|
656
705
|
);
|
|
657
706
|
}
|
|
658
|
-
|
|
707
|
+
let body;
|
|
708
|
+
try {
|
|
709
|
+
body = await response.json();
|
|
710
|
+
} catch (err) {
|
|
711
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
712
|
+
throw new HavenSignContextError(
|
|
713
|
+
`Haven did not finish sending the signing context for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from the quote result instead.`,
|
|
714
|
+
"SIGN_CONTEXT_TIMEOUT"
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
body = {};
|
|
718
|
+
}
|
|
659
719
|
if (!response.ok) {
|
|
660
720
|
const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
|
|
661
|
-
throw new
|
|
662
|
-
`Haven refused the signing-context fetch for ${paymentId}: ${detail}` + (response.status === 404 ? " \u2014 check the payment_id came from this agent\u2019s own quote." : response.status === 410 ? " Re-run the quote with the same idempotency key, then sign the fresh payment_id." : "")
|
|
721
|
+
throw new HavenSignContextError(
|
|
722
|
+
`Haven refused the signing-context fetch for ${paymentId}: ${detail}` + (response.status === 404 ? " \u2014 check the payment_id came from this agent\u2019s own quote." : response.status === 410 ? " Re-run the quote with the same idempotency key, then sign the fresh payment_id." : ""),
|
|
723
|
+
"SIGN_CONTEXT_REFUSED",
|
|
724
|
+
{ httpStatus: response.status, errorCode: typeof body.error_code === "string" ? body.error_code : void 0 }
|
|
663
725
|
);
|
|
664
726
|
}
|
|
665
727
|
const signData = body.sign_data;
|
|
666
728
|
const x402Expected = body.x402_expected;
|
|
667
729
|
if (!signData || typeof signData.hash !== "string" || !signData.typed_data || typeof signData.typed_data !== "object" || !x402Expected) {
|
|
668
|
-
throw new
|
|
669
|
-
"The Haven sign-context response is missing sign_data.typed_data or x402_expected \u2014 the backend may predate #1263. Pass typed_data_b64 from the quote result instead."
|
|
730
|
+
throw new HavenSignContextError(
|
|
731
|
+
"The Haven sign-context response is missing sign_data.typed_data or x402_expected \u2014 the backend may predate #1263. Pass typed_data_b64 from the quote result instead.",
|
|
732
|
+
"SIGN_CONTEXT_MALFORMED"
|
|
670
733
|
);
|
|
671
734
|
}
|
|
672
735
|
const paymentRequired = body.payment_required;
|
|
@@ -1097,6 +1160,18 @@ function normalizeError(err) {
|
|
|
1097
1160
|
next_action: sdk.AgentPaymentNextAction.StopAndTellUser
|
|
1098
1161
|
};
|
|
1099
1162
|
}
|
|
1163
|
+
if (err instanceof HavenSignContextError) {
|
|
1164
|
+
return {
|
|
1165
|
+
success: false,
|
|
1166
|
+
code: err.code,
|
|
1167
|
+
message: err.message,
|
|
1168
|
+
next_action: err.next_action,
|
|
1169
|
+
...err.fallback !== void 0 ? { fallback: err.fallback } : {},
|
|
1170
|
+
...err.retry_with_new_quote ? { retry_with_new_quote: true } : {},
|
|
1171
|
+
...err.http_status !== void 0 ? { http_status: err.http_status } : {},
|
|
1172
|
+
...err.backend_error_code !== void 0 ? { backend_error_code: err.backend_error_code } : {}
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1100
1175
|
if (err instanceof sdk.HavenSigningError) {
|
|
1101
1176
|
return { success: false, code: err.code, message: err.message };
|
|
1102
1177
|
}
|
|
@@ -1243,7 +1318,7 @@ async function writeAckFile(path$1, hash) {
|
|
|
1243
1318
|
);
|
|
1244
1319
|
}
|
|
1245
1320
|
var SIGNER_NAME = "@haven_ai/signer";
|
|
1246
|
-
var SIGNER_VERSION = "0.2.
|
|
1321
|
+
var SIGNER_VERSION = "0.2.1-alpha.0";
|
|
1247
1322
|
async function resolveEdgeSigner(options = {}) {
|
|
1248
1323
|
const { signer } = await resolveSignerRuntime(options);
|
|
1249
1324
|
return signer;
|