@haven_ai/signer 0.7.0-alpha.0 → 0.8.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 +26 -12
- package/dist/cli.cjs +21 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +21 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +21 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +21 -11
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,14 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
12
12
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
13
13
|
|
|
14
14
|
var SIGNER_HOSTED_HANDOFF_SHAPES = {
|
|
15
|
-
haven_get_payment_status: { payment_id: z.string().min(1) }
|
|
15
|
+
haven_get_payment_status: { payment_id: z.string().min(1) },
|
|
16
|
+
// #3506: `haven_sign` hands a signed budget row to the hosted `haven_submit`
|
|
17
|
+
// (`signTaskBudget` / `signSubBudget` in tools.ts emit exactly these
|
|
18
|
+
// `next_arguments`). One hosted tool, two argument shapes, so each shape is
|
|
19
|
+
// its own entry keyed `<hosted tool>#<variant>`; the parity test reads the
|
|
20
|
+
// part before `#` as the hosted tool it checks the entry against.
|
|
21
|
+
"haven_submit#task_budget": { task_budget_id: z.string().min(1), signature: z.string().regex(/^0x[0-9a-fA-F]+$/) },
|
|
22
|
+
"haven_submit#sub_budget": { sub_budget_id: z.string().min(1), signature: z.string().regex(/^0x[0-9a-fA-F]+$/) }
|
|
16
23
|
};
|
|
17
24
|
function target(shape) {
|
|
18
25
|
const schema = z.object(shape).strict();
|
|
@@ -159,7 +166,8 @@ function stableStringify(value) {
|
|
|
159
166
|
const object = value;
|
|
160
167
|
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
161
168
|
}
|
|
162
|
-
var DIRECT_RELAY_FALLBACK = "call haven_sign with payload_hash and typed_data_b64 from
|
|
169
|
+
var DIRECT_RELAY_FALLBACK = "re-run whichever of haven_send / haven_pay you called, with the SAME idempotency_key (echoed on its result) plus include_signing_payload: true, then call haven_sign with payload_hash and typed_data_b64 from THAT re-run's result, passed through unchanged";
|
|
170
|
+
var DIRECT_404_FALLBACK = "either the payment_id is not from this agent\u2019s own POST /payments call, or this Haven backend predates #3271 (which also predates #3495, so its result already carries payload_hash and typed_data_b64 unconditionally): pass those fields from the ORIGINAL haven_send / haven_pay result, unchanged, if it already carries them \u2014 or, on a newer server, re-run haven_send / haven_pay with the SAME idempotency_key plus include_signing_payload: true and pass them from THAT result instead";
|
|
163
171
|
var HavenSignContextError = class extends HavenSigningError {
|
|
164
172
|
/**
|
|
165
173
|
* #3001 / #3010 review: the recovery path, when signing OTHER bytes is
|
|
@@ -237,7 +245,7 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
237
245
|
step = signerRefusalStep({
|
|
238
246
|
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
239
247
|
nextTool: null,
|
|
240
|
-
nextToolOmittedReason:
|
|
248
|
+
nextToolOmittedReason: DIRECT_404_FALLBACK
|
|
241
249
|
});
|
|
242
250
|
} else if (flow === "direct" && refusal?.errorCode === "expired") {
|
|
243
251
|
this.next_action = AgentPaymentNextAction.PaymentWindowExpired;
|
|
@@ -392,7 +400,7 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
392
400
|
} catch (err) {
|
|
393
401
|
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
394
402
|
throw new HavenSignContextError(
|
|
395
|
-
timedOut ? `Haven did not answer the direct-payment signing-context fetch for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from
|
|
403
|
+
timedOut ? `Haven did not answer the direct-payment signing-context fetch for ${paymentId} within ${timeoutMs} ms. Retry, or re-run haven_send / haven_pay with the same idempotency_key plus include_signing_payload: true and pass typed_data_b64 from that result instead.` : `Could not reach Haven to fetch the direct-payment signing context for ${paymentId}: ${err instanceof Error ? err.message : String(err)}. Retry, or re-run haven_send / haven_pay with the same idempotency_key plus include_signing_payload: true and pass typed_data_b64 from that result instead.`,
|
|
396
404
|
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE",
|
|
397
405
|
void 0,
|
|
398
406
|
paymentId,
|
|
@@ -405,7 +413,7 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
405
413
|
} catch (err) {
|
|
406
414
|
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
407
415
|
throw new HavenSignContextError(
|
|
408
|
-
`Haven did not finish sending the direct-payment signing context for ${paymentId} within ${timeoutMs} ms. Retry, or pass typed_data_b64 from
|
|
416
|
+
`Haven did not finish sending the direct-payment signing context for ${paymentId} within ${timeoutMs} ms. Retry, or re-run haven_send / haven_pay with the same idempotency_key plus include_signing_payload: true and pass typed_data_b64 from that result instead.`,
|
|
409
417
|
"SIGN_CONTEXT_TIMEOUT",
|
|
410
418
|
void 0,
|
|
411
419
|
paymentId,
|
|
@@ -417,7 +425,7 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
417
425
|
if (!response.ok) {
|
|
418
426
|
const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
|
|
419
427
|
throw new HavenSignContextError(
|
|
420
|
-
`Haven refused the direct-payment signing-context fetch for ${paymentId}: ${detail}` + (response.status === 404 ? " \u2014 either the payment_id is not from this agent\u2019s own POST /payments call, or this Haven backend predates #3271. Pass payload_hash and typed_data_b64 from the
|
|
428
|
+
`Haven refused the direct-payment signing-context fetch for ${paymentId}: ${detail}` + (response.status === 404 ? " \u2014 either the payment_id is not from this agent\u2019s own POST /payments call, or this Haven backend predates #3271 (which also predates #3495, so its haven_send / haven_pay result already carries payload_hash and typed_data_b64 unconditionally). Pass payload_hash and typed_data_b64, unchanged, from the original result \u2014 or, on a newer server, from a same-key re-run with include_signing_payload: true." : body.error_code === "expired" ? " The payment window has expired; call haven_send / haven_pay again with the same idempotency_key." : ""),
|
|
421
429
|
"SIGN_CONTEXT_REFUSED",
|
|
422
430
|
refusalOf(response.status, body),
|
|
423
431
|
paymentId,
|
|
@@ -428,7 +436,7 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
428
436
|
const version = body.direct_sign_context_version;
|
|
429
437
|
if (!signData || typeof signData.hash !== "string" || !signData.typed_data || typeof signData.typed_data !== "object" || signData.signature_scheme !== "eip712_userop" || typeof version !== "number" || !SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS.includes(version)) {
|
|
430
438
|
throw new HavenSignContextError(
|
|
431
|
-
typeof version === "number" && !SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS.includes(version) ? `The Haven direct-payment sign-context response is version ${version}, which this signer does not support (supported: ${SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS.join(", ")}). Update @haven_ai/signer.` : "The Haven direct-payment sign-context response is missing sign_data.typed_data, or its signature_scheme is not 'eip712_userop' \u2014 the backend may predate #3271.
|
|
439
|
+
typeof version === "number" && !SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS.includes(version) ? `The Haven direct-payment sign-context response is version ${version}, which this signer does not support (supported: ${SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS.join(", ")}). Update @haven_ai/signer.` : "The Haven direct-payment sign-context response is missing sign_data.typed_data, or its signature_scheme is not 'eip712_userop' \u2014 the backend may predate #3271. Re-run haven_send / haven_pay with the same idempotency_key plus include_signing_payload: true and pass typed_data_b64 from that result instead.",
|
|
432
440
|
"SIGN_CONTEXT_MALFORMED",
|
|
433
441
|
void 0,
|
|
434
442
|
paymentId,
|
|
@@ -670,7 +678,7 @@ async function fetchTaskBudgetSignContext(identity, taskBudgetId, fetchImpl = fe
|
|
|
670
678
|
|
|
671
679
|
// src/tools.ts
|
|
672
680
|
var SIGNER_NAME = "@haven_ai/signer";
|
|
673
|
-
var SIGNER_VERSION = "0.
|
|
681
|
+
var SIGNER_VERSION = "0.8.1-alpha.0";
|
|
674
682
|
var UNSUPPORTED_ARGUMENT_MARKER = "HavenSignerUnsupportedArgument:";
|
|
675
683
|
var USEROP_BINDING_MISMATCH = "USEROP_BINDING_MISMATCH";
|
|
676
684
|
var HavenUserOpBindingRefusedError = class extends HavenSigningError {
|
|
@@ -684,7 +692,7 @@ var HavenUserOpBindingRefusedError = class extends HavenSigningError {
|
|
|
684
692
|
this.step = signerRefusalStep({
|
|
685
693
|
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
686
694
|
nextTool: null,
|
|
687
|
-
nextToolOmittedReason: "call haven_sign again with payment_id alone (preferred), or with typed_data copied unchanged from the payment result"
|
|
695
|
+
nextToolOmittedReason: "call haven_sign again with payment_id alone (preferred), or with typed_data copied unchanged from the payment result (or, on a compact direct-payment result, from a same-key re-run with include_signing_payload: true)"
|
|
688
696
|
});
|
|
689
697
|
}
|
|
690
698
|
};
|
|
@@ -1490,7 +1498,7 @@ function normalizeError(err) {
|
|
|
1490
1498
|
|
|
1491
1499
|
// src/consent.ts
|
|
1492
1500
|
var toolSummaries = {
|
|
1493
|
-
haven_sign: "signs a Haven-prepared payment, task-budget
|
|
1501
|
+
haven_sign: "signs a Haven-prepared payment, task-budget or sub-budget open or close (a UserOp from your own account redeeming a delegation made to it, directly or via a task-budget child; a sub-budget child narrowing your budget for another agent of yours; or an x402 funding intent against a Haven-signed context)",
|
|
1494
1502
|
haven_x402_sign_header: "builds and signs the EIP-3009 merchant payment header for an x402 payment",
|
|
1495
1503
|
haven_sign_x402: "the two above in one call: funding payload + merchant header",
|
|
1496
1504
|
haven_sign_sweep_delegate: "signs a Haven-prepared gasless sweep of stranded funds back to your own account"
|
|
@@ -2023,7 +2031,8 @@ function signerCompatibility() {
|
|
|
2023
2031
|
x402_expected_context_versions: [...SUPPORTED_X402_EXPECTED_VERSIONS],
|
|
2024
2032
|
sweep_binding_versions: [...SUPPORTED_SWEEP_BINDING_VERSIONS],
|
|
2025
2033
|
direct_sign_context_versions: [...SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS],
|
|
2026
|
-
task_sign_context_versions: [...SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS]
|
|
2034
|
+
task_sign_context_versions: [...SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS],
|
|
2035
|
+
sub_budget_sign_context_versions: [...SUPPORTED_SUB_BUDGET_SIGN_CONTEXT_VERSIONS]
|
|
2027
2036
|
};
|
|
2028
2037
|
}
|
|
2029
2038
|
function signerCapabilityAdvertisement() {
|
|
@@ -2043,6 +2052,7 @@ function signerInstructions() {
|
|
|
2043
2052
|
`- sweep authorization binding versions supported: ${compatibility.sweep_binding_versions.join(", ")}`,
|
|
2044
2053
|
`- direct-payment (haven_send / haven_pay) sign-context versions supported: ${compatibility.direct_sign_context_versions.join(", ")} \u2014 pass payment_id alone to haven_sign; this signer fetches the exact bytes`,
|
|
2045
2054
|
`- task-budget sign-context versions supported: ${compatibility.task_sign_context_versions.join(", ")} \u2014 pass task_budget_id alone to haven_sign; this signer fetches the exact bytes`,
|
|
2055
|
+
`- sub-budget sign-context versions supported: ${compatibility.sub_budget_sign_context_versions.join(", ")} \u2014 pass sub_budget_id alone to haven_sign; this signer fetches the exact bytes (a sub-budget your owner issued narrows your own budget for another agent of your account)`,
|
|
2046
2056
|
"",
|
|
2047
2057
|
"Haven quote and prepare results report the expected-context version they will emit",
|
|
2048
2058
|
"(signer_compatibility.x402_expected_context_version). If that version is not in the list",
|