@haven_ai/signer 0.5.0-alpha.1 → 0.7.0-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 +12 -6
- package/dist/cli.cjs +481 -22
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +482 -23
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +482 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -4
- package/dist/index.d.ts +39 -4
- package/dist/index.js +483 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID, createHash } from 'crypto';
|
|
2
2
|
import { recoverTypedDataAddress, hashTypedData, hashMessage } from 'viem';
|
|
3
3
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
4
|
-
import { createNextStepBuilder, addressFromKey, HavenSigningError, buildSweepTypedData, selectStandardPaymentOption, HavenApiError, toStandardPaymentRequirements, decodeBase64Json, encodeBase64Json, x402V2PaymentEnvelope, isSettlementChildTypedData, chainIdForNetwork, assertOwnSettlementChild, isPackedUserOperationTypedData, assertUserOpTypedDataBinding, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, HavenTypedDataRefusedError, buildSweepAuthorizationMessage, verifySignature, x402AuthorizationAmount, SignerRefusalCode,
|
|
4
|
+
import { createNextStepBuilder, addressFromKey, HavenSigningError, buildSweepTypedData, selectStandardPaymentOption, HavenApiError, toStandardPaymentRequirements, decodeBase64Json, encodeBase64Json, x402V2PaymentEnvelope, isSettlementChildTypedData, chainIdForNetwork, assertOwnSettlementChild, isPackedUserOperationTypedData, assertUserOpTypedDataBinding, assertBoundDirectPaymentUserOp, assertFundingLegPaysDelegate, HavenTypedDataRefusedError, buildSweepAuthorizationMessage, verifySignature, x402AuthorizationAmount, SignerRefusalCode, connectorUpgradeCommand, SIGNER_UPDATE_FALLBACK, HavenUnsupportedSignerVersionError, buildX402ExpectedMessage, TASK_SIGN_CONTEXT_VERSION, DIRECT_SIGN_CONTEXT_VERSION, AgentPaymentNextAction, HavenError, AgentPaymentFailureCode, havenClientIdentity, isSupportedNodeVersion, unsupportedNodeVersionMessage, HavenUserOpBindingError, connectorRerunCommand, assertOwnTaskChild, assertOwnTaskBudgetCloseUserOp, assertOwnSubBudgetChild, assertOwnSubBudgetCloseUserOp, readClientUpdate, HAVEN_CLIENT_HEADER } from '@haven_ai/sdk/edge';
|
|
5
5
|
export { deriveDelegateAccountAddress } from '@haven_ai/sdk/edge';
|
|
6
6
|
import { stat, lstat, chmod, readFile, mkdir, rename, appendFile, writeFile } from 'fs/promises';
|
|
7
7
|
import { resolve, dirname, join } from 'path';
|
|
@@ -254,7 +254,7 @@ function assertSupportedBindingVersion(received, supported, context) {
|
|
|
254
254
|
const highest = Math.max(...supported);
|
|
255
255
|
const outOfDate = received > highest;
|
|
256
256
|
const code = context === "x402 expected context" ? SignerRefusalCode.UnsupportedExpectedContextVersion : SignerRefusalCode.UnsupportedSweepBindingVersion;
|
|
257
|
-
const ceiling = outOfDate ? `This signer is out of date: it supports ${context} versions up to ${highest}, and Haven sent version ${received}. Update @haven_ai/signer \u2014
|
|
257
|
+
const ceiling = outOfDate ? `This signer is out of date: it supports ${context} versions up to ${highest}, and Haven sent version ${received}. Update @haven_ai/signer \u2014 run \`${connectorUpgradeCommand()}\`, then the repair line it prints, which reinstalls the pinned MCP runtime.` : `Unsupported ${context} version ${received}: this signer supports ${supported.join(", ")}.`;
|
|
258
258
|
const fallback = outOfDate ? SIGNER_UPDATE_FALLBACK : `This ${context} version (${received}) is older than what this signer enforces (${supported.join(", ")}) \u2014 updating @haven_ai/signer will not restore it. Nothing was signed or spent; stop and tell the user rather than retrying.`;
|
|
259
259
|
throw new HavenUnsupportedSignerVersionError(
|
|
260
260
|
`${ceiling} Nothing was signed. Do not rewrite the version field to a supported value: it is part of the Haven-signed binding message, so changing it invalidates the signature and would misrepresent what Haven declared.`,
|
|
@@ -433,7 +433,7 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
433
433
|
/**
|
|
434
434
|
* #3303: on a 426 `client_outdated` refusal, the backend's update hint —
|
|
435
435
|
* this signer is below the minimum the deployment set, and
|
|
436
|
-
* `client_update.upgrade_command`
|
|
436
|
+
* `client_update.upgrade_command` starts the update (#3412: for the signer, the doctor, then its repair line).
|
|
437
437
|
*/
|
|
438
438
|
client_update;
|
|
439
439
|
constructor(message, code, refusal, paymentId, flow = "x402") {
|
|
@@ -450,7 +450,7 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
450
450
|
step = signerRefusalStep({
|
|
451
451
|
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
452
452
|
nextTool: null,
|
|
453
|
-
nextToolOmittedReason: `this signer is below the minimum version Haven accepts \u2014 tell the user to run ${refusal.clientUpdate?.upgrade_command ??
|
|
453
|
+
nextToolOmittedReason: `this signer is below the minimum version Haven accepts \u2014 tell the user to run ${refusal.clientUpdate?.upgrade_command ?? connectorUpgradeCommand()} and the repair line it prints, restart the agent runtime, then retry the same haven_sign / haven_sign_x402 call`
|
|
454
454
|
});
|
|
455
455
|
} else if (flow === "direct" && refusal?.httpStatus === 404) {
|
|
456
456
|
this.fallback = "typed_data_b64";
|
|
@@ -475,6 +475,13 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
475
475
|
nextTool: null,
|
|
476
476
|
nextToolOmittedReason: "re-run the hosted quote tool you called with the same idempotency_key; which one depends on the flow"
|
|
477
477
|
});
|
|
478
|
+
} else if (flow === "task") {
|
|
479
|
+
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
480
|
+
step = signerRefusalStep({
|
|
481
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
482
|
+
nextTool: null,
|
|
483
|
+
nextToolOmittedReason: `re-check this task budget's status (id ${paymentId}) with the hosted Haven server before retrying`
|
|
484
|
+
});
|
|
478
485
|
} else {
|
|
479
486
|
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
480
487
|
step = signerRefusalStep({
|
|
@@ -483,6 +490,13 @@ var HavenSignContextError = class extends HavenSigningError {
|
|
|
483
490
|
nextArguments: { payment_id: paymentId }
|
|
484
491
|
});
|
|
485
492
|
}
|
|
493
|
+
} else if (flow === "task") {
|
|
494
|
+
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
495
|
+
step = signerRefusalStep({
|
|
496
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
497
|
+
nextTool: null,
|
|
498
|
+
nextToolOmittedReason: "retry the same haven_sign call with the same task_budget_id"
|
|
499
|
+
});
|
|
486
500
|
} else {
|
|
487
501
|
this.fallback = "typed_data_b64";
|
|
488
502
|
this.next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
@@ -651,6 +665,229 @@ async function fetchDirectSignContext(identity, paymentId, fetchImpl = fetch, ti
|
|
|
651
665
|
clientUpdate: readClientUpdate(body.client_update)
|
|
652
666
|
};
|
|
653
667
|
}
|
|
668
|
+
var SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS = [TASK_SIGN_CONTEXT_VERSION];
|
|
669
|
+
var SUPPORTED_SUB_BUDGET_SIGN_CONTEXT_VERSIONS = [1];
|
|
670
|
+
async function fetchSubBudgetSignContext(identity, subBudgetId, fetchImpl = fetch, timeoutMs = SIGN_CONTEXT_TIMEOUT_MS, clientIdentity) {
|
|
671
|
+
let response;
|
|
672
|
+
try {
|
|
673
|
+
response = await fetchImpl(
|
|
674
|
+
`${identity.apiUrl}/sub-budgets/${encodeURIComponent(subBudgetId)}/sign-context`,
|
|
675
|
+
{
|
|
676
|
+
headers: signContextHeaders(identity, clientIdentity),
|
|
677
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
} catch (err) {
|
|
681
|
+
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
682
|
+
throw new HavenSignContextError(
|
|
683
|
+
timedOut ? `Haven did not answer the sub-budget signing-context fetch for ${subBudgetId} within ${timeoutMs} ms. Retry.` : `Could not reach Haven to fetch the sub-budget signing context for ${subBudgetId}: ${err instanceof Error ? err.message : String(err)}.`,
|
|
684
|
+
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE",
|
|
685
|
+
void 0,
|
|
686
|
+
subBudgetId,
|
|
687
|
+
"task"
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
let body;
|
|
691
|
+
try {
|
|
692
|
+
body = await response.json();
|
|
693
|
+
} catch (err) {
|
|
694
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
695
|
+
throw new HavenSignContextError(
|
|
696
|
+
`Haven did not finish sending the sub-budget signing context for ${subBudgetId} within ${timeoutMs} ms. Retry.`,
|
|
697
|
+
"SIGN_CONTEXT_TIMEOUT",
|
|
698
|
+
void 0,
|
|
699
|
+
subBudgetId,
|
|
700
|
+
"task"
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
body = {};
|
|
704
|
+
}
|
|
705
|
+
if (!response.ok) {
|
|
706
|
+
const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
|
|
707
|
+
throw new HavenSignContextError(
|
|
708
|
+
`Haven refused the sub-budget signing-context fetch for ${subBudgetId}: ${detail}`,
|
|
709
|
+
"SIGN_CONTEXT_REFUSED",
|
|
710
|
+
refusalOf(response.status, body),
|
|
711
|
+
subBudgetId,
|
|
712
|
+
"task"
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
const purpose = body.purpose;
|
|
716
|
+
const typedData = body.typed_data;
|
|
717
|
+
const version = body.sub_budget_sign_context_version;
|
|
718
|
+
const expected = body.expected;
|
|
719
|
+
const malformed = (detail) => {
|
|
720
|
+
throw new HavenSignContextError(
|
|
721
|
+
`The Haven sub-budget sign-context response for ${subBudgetId} is malformed: ${detail}.`,
|
|
722
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
723
|
+
void 0,
|
|
724
|
+
subBudgetId,
|
|
725
|
+
"task"
|
|
726
|
+
);
|
|
727
|
+
};
|
|
728
|
+
if (typeof version !== "number" || !SUPPORTED_SUB_BUDGET_SIGN_CONTEXT_VERSIONS.includes(version)) {
|
|
729
|
+
throw new HavenSignContextError(
|
|
730
|
+
`The Haven sub-budget sign-context response is version ${String(version)}, which this signer does not support (supported: ${SUPPORTED_SUB_BUDGET_SIGN_CONTEXT_VERSIONS.join(", ")}). Update @haven_ai/signer.`,
|
|
731
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
732
|
+
void 0,
|
|
733
|
+
subBudgetId,
|
|
734
|
+
"task"
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
if (!typedData || typeof typedData !== "object") return malformed("missing typed_data");
|
|
738
|
+
if (!expected || typeof expected !== "object") return malformed("missing expected");
|
|
739
|
+
const e = expected;
|
|
740
|
+
if (purpose === "open") {
|
|
741
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.token_address !== "string" || typeof e.period_amount_atomic !== "string" || typeof e.period_duration_seconds !== "number" || typeof e.start_date !== "number" || e.recipient_address !== null && typeof e.recipient_address !== "string" || typeof e.expires_at !== "number" || typeof e.parent_delegation_hash !== "string" || typeof e.child_delegate_account !== "string") {
|
|
742
|
+
return malformed("expected is missing a required field for purpose open");
|
|
743
|
+
}
|
|
744
|
+
return {
|
|
745
|
+
purpose: "open",
|
|
746
|
+
subBudgetId: String(body.sub_budget_id ?? subBudgetId),
|
|
747
|
+
typedData,
|
|
748
|
+
expected: {
|
|
749
|
+
delegateAccount: e.delegate_account,
|
|
750
|
+
chainId: e.chain_id,
|
|
751
|
+
tokenAddress: e.token_address,
|
|
752
|
+
periodAmountAtomic: e.period_amount_atomic,
|
|
753
|
+
periodDurationSeconds: e.period_duration_seconds,
|
|
754
|
+
startDate: e.start_date,
|
|
755
|
+
recipientAddress: e.recipient_address ?? null,
|
|
756
|
+
expiresAt: e.expires_at,
|
|
757
|
+
parentDelegationHash: e.parent_delegation_hash,
|
|
758
|
+
childDelegateAccount: e.child_delegate_account
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
if (purpose === "close") {
|
|
763
|
+
const userOpHash = body.user_op_hash;
|
|
764
|
+
if (typeof userOpHash !== "string") return malformed("missing user_op_hash for purpose close");
|
|
765
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.delegation_hash !== "string") {
|
|
766
|
+
return malformed("expected is missing a required field for purpose close");
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
purpose: "close",
|
|
770
|
+
subBudgetId: String(body.sub_budget_id ?? subBudgetId),
|
|
771
|
+
typedData,
|
|
772
|
+
userOpHash,
|
|
773
|
+
expected: {
|
|
774
|
+
delegateAccount: e.delegate_account,
|
|
775
|
+
chainId: e.chain_id,
|
|
776
|
+
delegationHash: e.delegation_hash
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
return malformed(`unknown purpose '${String(purpose)}'`);
|
|
781
|
+
}
|
|
782
|
+
async function fetchTaskBudgetSignContext(identity, taskBudgetId, fetchImpl = fetch, timeoutMs = SIGN_CONTEXT_TIMEOUT_MS, clientIdentity) {
|
|
783
|
+
let response;
|
|
784
|
+
try {
|
|
785
|
+
response = await fetchImpl(
|
|
786
|
+
`${identity.apiUrl}/task-budgets/${encodeURIComponent(taskBudgetId)}/sign-context`,
|
|
787
|
+
{
|
|
788
|
+
headers: signContextHeaders(identity, clientIdentity),
|
|
789
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
790
|
+
}
|
|
791
|
+
);
|
|
792
|
+
} catch (err) {
|
|
793
|
+
const timedOut = err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError");
|
|
794
|
+
throw new HavenSignContextError(
|
|
795
|
+
timedOut ? `Haven did not answer the task-budget signing-context fetch for ${taskBudgetId} within ${timeoutMs} ms. Retry.` : `Could not reach Haven to fetch the task-budget signing context for ${taskBudgetId}: ${err instanceof Error ? err.message : String(err)}.`,
|
|
796
|
+
timedOut ? "SIGN_CONTEXT_TIMEOUT" : "SIGN_CONTEXT_UNREACHABLE",
|
|
797
|
+
void 0,
|
|
798
|
+
taskBudgetId,
|
|
799
|
+
"task"
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
let body;
|
|
803
|
+
try {
|
|
804
|
+
body = await response.json();
|
|
805
|
+
} catch (err) {
|
|
806
|
+
if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError")) {
|
|
807
|
+
throw new HavenSignContextError(
|
|
808
|
+
`Haven did not finish sending the task-budget signing context for ${taskBudgetId} within ${timeoutMs} ms. Retry.`,
|
|
809
|
+
"SIGN_CONTEXT_TIMEOUT",
|
|
810
|
+
void 0,
|
|
811
|
+
taskBudgetId,
|
|
812
|
+
"task"
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
body = {};
|
|
816
|
+
}
|
|
817
|
+
if (!response.ok) {
|
|
818
|
+
const detail = typeof body.error === "string" ? body.error : `HTTP ${response.status}`;
|
|
819
|
+
throw new HavenSignContextError(
|
|
820
|
+
`Haven refused the task-budget signing-context fetch for ${taskBudgetId}: ${detail}`,
|
|
821
|
+
"SIGN_CONTEXT_REFUSED",
|
|
822
|
+
refusalOf(response.status, body),
|
|
823
|
+
taskBudgetId,
|
|
824
|
+
"task"
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
const purpose = body.purpose;
|
|
828
|
+
const typedData = body.typed_data;
|
|
829
|
+
const version = body.task_sign_context_version;
|
|
830
|
+
const expected = body.expected;
|
|
831
|
+
const malformed = (detail) => {
|
|
832
|
+
throw new HavenSignContextError(
|
|
833
|
+
`The Haven task-budget sign-context response for ${taskBudgetId} is malformed: ${detail}.`,
|
|
834
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
835
|
+
void 0,
|
|
836
|
+
taskBudgetId,
|
|
837
|
+
"task"
|
|
838
|
+
);
|
|
839
|
+
};
|
|
840
|
+
if (typeof version !== "number" || !SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS.includes(version)) {
|
|
841
|
+
throw new HavenSignContextError(
|
|
842
|
+
`The Haven task-budget sign-context response is version ${String(version)}, which this signer does not support (supported: ${SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS.join(", ")}). Update @haven_ai/signer.`,
|
|
843
|
+
"SIGN_CONTEXT_MALFORMED",
|
|
844
|
+
void 0,
|
|
845
|
+
taskBudgetId,
|
|
846
|
+
"task"
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
if (!typedData || typeof typedData !== "object") return malformed("missing typed_data");
|
|
850
|
+
if (!expected || typeof expected !== "object") return malformed("missing expected");
|
|
851
|
+
const e = expected;
|
|
852
|
+
if (purpose === "open") {
|
|
853
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.token_address !== "string" || typeof e.max_amount_atomic !== "string" || e.recipient_address !== null && typeof e.recipient_address !== "string" || typeof e.expires_at !== "number" || typeof e.parent_delegation_hash !== "string") {
|
|
854
|
+
return malformed("expected is missing a required field for purpose open");
|
|
855
|
+
}
|
|
856
|
+
return {
|
|
857
|
+
purpose: "open",
|
|
858
|
+
taskBudgetId: String(body.task_budget_id ?? taskBudgetId),
|
|
859
|
+
typedData,
|
|
860
|
+
expected: {
|
|
861
|
+
delegateAccount: e.delegate_account,
|
|
862
|
+
chainId: e.chain_id,
|
|
863
|
+
tokenAddress: e.token_address,
|
|
864
|
+
maxAmountAtomic: e.max_amount_atomic,
|
|
865
|
+
recipientAddress: e.recipient_address ?? null,
|
|
866
|
+
expiresAt: e.expires_at,
|
|
867
|
+
parentDelegationHash: e.parent_delegation_hash
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
if (purpose === "close") {
|
|
872
|
+
const userOpHash = body.user_op_hash;
|
|
873
|
+
if (typeof userOpHash !== "string") return malformed("missing user_op_hash for purpose close");
|
|
874
|
+
if (typeof e.delegate_account !== "string" || typeof e.chain_id !== "number" || typeof e.delegation_hash !== "string") {
|
|
875
|
+
return malformed("expected is missing a required field for purpose close");
|
|
876
|
+
}
|
|
877
|
+
return {
|
|
878
|
+
purpose: "close",
|
|
879
|
+
taskBudgetId: String(body.task_budget_id ?? taskBudgetId),
|
|
880
|
+
typedData,
|
|
881
|
+
userOpHash,
|
|
882
|
+
expected: {
|
|
883
|
+
delegateAccount: e.delegate_account,
|
|
884
|
+
chainId: e.chain_id,
|
|
885
|
+
delegationHash: e.delegation_hash
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
return malformed(`unknown purpose '${String(purpose)}'`);
|
|
890
|
+
}
|
|
654
891
|
|
|
655
892
|
// src/capabilities.ts
|
|
656
893
|
var SIGNER_CAPABILITY_KEY = "haven/signer-compatibility";
|
|
@@ -658,7 +895,8 @@ function signerCompatibility() {
|
|
|
658
895
|
return {
|
|
659
896
|
x402_expected_context_versions: [...SUPPORTED_X402_EXPECTED_VERSIONS],
|
|
660
897
|
sweep_binding_versions: [...SUPPORTED_SWEEP_BINDING_VERSIONS],
|
|
661
|
-
direct_sign_context_versions: [...SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS]
|
|
898
|
+
direct_sign_context_versions: [...SUPPORTED_DIRECT_SIGN_CONTEXT_VERSIONS],
|
|
899
|
+
task_sign_context_versions: [...SUPPORTED_TASK_SIGN_CONTEXT_VERSIONS]
|
|
662
900
|
};
|
|
663
901
|
}
|
|
664
902
|
function signerCapabilityAdvertisement() {
|
|
@@ -677,12 +915,13 @@ function signerInstructions() {
|
|
|
677
915
|
`- x402 expected-context versions supported: ${compatibility.x402_expected_context_versions.join(", ")}`,
|
|
678
916
|
`- sweep authorization binding versions supported: ${compatibility.sweep_binding_versions.join(", ")}`,
|
|
679
917
|
`- 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`,
|
|
918
|
+
`- 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`,
|
|
680
919
|
"",
|
|
681
920
|
"Haven quote and prepare results report the expected-context version they will emit",
|
|
682
921
|
"(signer_compatibility.x402_expected_context_version). If that version is not in the list",
|
|
683
922
|
"above, this signer is out of date: STOP before signing, and tell the user to update",
|
|
684
|
-
`@haven_ai/signer
|
|
685
|
-
"MCP runtime. Do not edit the version field to a supported value \u2014 it is part of the",
|
|
923
|
+
`@haven_ai/signer: run \`${connectorUpgradeCommand()}\`, then the repair line it prints,`,
|
|
924
|
+
"which reinstalls the pinned MCP runtime. Do not edit the version field to a supported value \u2014 it is part of the",
|
|
686
925
|
"Haven-signed binding message, so changing it invalidates the signature.",
|
|
687
926
|
"",
|
|
688
927
|
"A version-mismatch refusal from haven_sign / haven_sign_x402 / haven_sign_sweep_delegate is",
|
|
@@ -690,7 +929,13 @@ function signerInstructions() {
|
|
|
690
929
|
"fallback fields alongside the message, so you can branch on it directly. Every signer",
|
|
691
930
|
"refusal also carries the next-step family: next_tool_name + next_tool_server_role when a",
|
|
692
931
|
"hosted tool follows (resolve the role against your own server names), else",
|
|
693
|
-
"next_tool_omitted_reason saying why not."
|
|
932
|
+
"next_tool_omitted_reason saying why not.",
|
|
933
|
+
"",
|
|
934
|
+
"An undeclared top-level argument is refused, not stripped: haven_sign answers",
|
|
935
|
+
"UNSUPPORTED_ARGUMENT with unknown_arguments, signer_version and fallback (the update",
|
|
936
|
+
"command) instead of dropping the key and answering the generic signing error \u2014 if you see",
|
|
937
|
+
"that refusal, this signer predates the argument form you sent. Update the signer; nothing",
|
|
938
|
+
"was signed, fetched or audited."
|
|
694
939
|
].join("\n");
|
|
695
940
|
}
|
|
696
941
|
var OWNER_ONLY_MODE = 384;
|
|
@@ -909,6 +1154,9 @@ var HavenBareHashRefusedError = class extends HavenSigningError {
|
|
|
909
1154
|
};
|
|
910
1155
|
|
|
911
1156
|
// src/tools.ts
|
|
1157
|
+
var SIGNER_NAME = "@haven_ai/signer";
|
|
1158
|
+
var SIGNER_VERSION = "0.7.0-alpha.0";
|
|
1159
|
+
var UNSUPPORTED_ARGUMENT_MARKER = "HavenSignerUnsupportedArgument:";
|
|
912
1160
|
var USEROP_BINDING_MISMATCH = "USEROP_BINDING_MISMATCH";
|
|
913
1161
|
var HavenUserOpBindingRefusedError = class extends HavenSigningError {
|
|
914
1162
|
next_action = AgentPaymentNextAction.StopAndTellUser;
|
|
@@ -1029,7 +1277,20 @@ var toolSchemas = {
|
|
|
1029
1277
|
// Bounded: a realistic redemption payload is ~10KB encoded; 256KB is
|
|
1030
1278
|
// generous headroom while keeping the offline signer from materializing
|
|
1031
1279
|
// arbitrarily large caller input.
|
|
1032
|
-
typed_data_b64: z$1.string().min(1).max(262144).optional()
|
|
1280
|
+
typed_data_b64: z$1.string().min(1).max(262144).optional(),
|
|
1281
|
+
// #3329: sign a task budget's own child delegation (purpose `open`) or
|
|
1282
|
+
// its early-close UserOp (purpose `close`) — the signer fetches the
|
|
1283
|
+
// exact typed data and expectation itself, exactly like payment_id.
|
|
1284
|
+
// Mutually exclusive with payment_id / payload_hash (checked in the
|
|
1285
|
+
// handler, since Zod's object-level refine on a raw shape used by
|
|
1286
|
+
// several call sites is not the shape this schema is composed as).
|
|
1287
|
+
task_budget_id: z$1.string().min(1).optional(),
|
|
1288
|
+
// #3330: sign a sub-budget's own child delegation or its early-close
|
|
1289
|
+
// UserOp — same fetch-verify-sign channel as task_budget_id, against
|
|
1290
|
+
// `GET /sub-budgets/:id/sign-context`. Mutually exclusive with
|
|
1291
|
+
// payment_id / payload_hash AND with task_budget_id (checked in the
|
|
1292
|
+
// handler).
|
|
1293
|
+
sub_budget_id: z$1.string().min(1).optional()
|
|
1033
1294
|
},
|
|
1034
1295
|
haven_x402_sign_header: {
|
|
1035
1296
|
// The parsed HTTP 402 PaymentRequired from the merchant. Typed as an object
|
|
@@ -1079,7 +1340,11 @@ var SIGN_DESCRIPTION = [
|
|
|
1079
1340
|
"intent against a Haven-signed context \u2014 never an arbitrary typed_data payload, however it is shaped.",
|
|
1080
1341
|
"Next: call mcp__haven__haven_submit with signature, then pass x402_binding",
|
|
1081
1342
|
"to mcp__haven-signer__haven_x402_sign_header. A bare payload_hash with no payment_id, typed_data",
|
|
1082
|
-
"or x402_expected is REFUSED (BARE_HASH_REFUSED): a hash carries nothing this signer can verify."
|
|
1343
|
+
"or x402_expected is REFUSED (BARE_HASH_REFUSED): a hash carries nothing this signer can verify.",
|
|
1344
|
+
"TASK BUDGETS (#3329): pass task_budget_id ALONE \u2014 mutually exclusive with payment_id and",
|
|
1345
|
+
"payload_hash \u2014 to sign a task budget\u2019s own child delegation (opening it) or its early-close",
|
|
1346
|
+
"UserOp; this signer fetches the exact typed data itself. Result then carries next_tool_name",
|
|
1347
|
+
"(haven_submit) and next_arguments { task_budget_id, signature } instead of x402_binding."
|
|
1083
1348
|
].join(" ");
|
|
1084
1349
|
var X402_SIGN_HEADER_DESCRIPTION = [
|
|
1085
1350
|
"Build and sign the EIP-3009 merchant payment header for the merchant leg of an x402 payment.",
|
|
@@ -1243,9 +1508,172 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1243
1508
|
throw err;
|
|
1244
1509
|
}
|
|
1245
1510
|
}
|
|
1511
|
+
async function signTaskBudget(taskBudgetId) {
|
|
1512
|
+
const identity = await options.signContext?.loadIdentity() ?? null;
|
|
1513
|
+
if (!identity) {
|
|
1514
|
+
throw new HavenSigningError(
|
|
1515
|
+
`task_budget_id signing needs the agent identity (identity.json next to the signer credentials), which this signer could not load. Re-run \`${connectorRerunCommand()}\` to restore it.`
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1518
|
+
const ctx = await fetchTaskBudgetSignContext(
|
|
1519
|
+
identity,
|
|
1520
|
+
taskBudgetId,
|
|
1521
|
+
options.signContext?.fetchImpl,
|
|
1522
|
+
void 0,
|
|
1523
|
+
options.signContext?.clientIdentity
|
|
1524
|
+
);
|
|
1525
|
+
let signature;
|
|
1526
|
+
if (ctx.purpose === "open") {
|
|
1527
|
+
try {
|
|
1528
|
+
assertOwnTaskChild(
|
|
1529
|
+
ctx.typedData,
|
|
1530
|
+
{
|
|
1531
|
+
chainId: ctx.expected.chainId,
|
|
1532
|
+
tokenAddress: ctx.expected.tokenAddress,
|
|
1533
|
+
maxAmountAtomic: ctx.expected.maxAmountAtomic,
|
|
1534
|
+
recipientAddress: ctx.expected.recipientAddress,
|
|
1535
|
+
expiresAt: ctx.expected.expiresAt,
|
|
1536
|
+
parentDelegationHash: ctx.expected.parentDelegationHash
|
|
1537
|
+
},
|
|
1538
|
+
signer.delegateAddress
|
|
1539
|
+
);
|
|
1540
|
+
} catch (err) {
|
|
1541
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1542
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1543
|
+
}
|
|
1544
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1545
|
+
} else {
|
|
1546
|
+
try {
|
|
1547
|
+
assertUserOpTypedDataBinding(ctx.typedData, ctx.userOpHash);
|
|
1548
|
+
} catch (err) {
|
|
1549
|
+
if (err instanceof HavenUserOpBindingError) throw new HavenUserOpBindingRefusedError(err.message);
|
|
1550
|
+
throw err;
|
|
1551
|
+
}
|
|
1552
|
+
try {
|
|
1553
|
+
assertOwnTaskBudgetCloseUserOp(
|
|
1554
|
+
ctx.typedData,
|
|
1555
|
+
{ delegationHash: ctx.expected.delegationHash },
|
|
1556
|
+
signer.delegateAddress
|
|
1557
|
+
);
|
|
1558
|
+
} catch (err) {
|
|
1559
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1560
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1561
|
+
}
|
|
1562
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1563
|
+
}
|
|
1564
|
+
await auditSigning("haven_sign", hashTypedData(ctx.typedData));
|
|
1565
|
+
return {
|
|
1566
|
+
signature,
|
|
1567
|
+
task_budget_id: ctx.taskBudgetId,
|
|
1568
|
+
purpose: ctx.purpose,
|
|
1569
|
+
next_tool_name: "haven_submit",
|
|
1570
|
+
next_tool_server_role: "hosted",
|
|
1571
|
+
next_arguments: { task_budget_id: ctx.taskBudgetId, signature }
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
async function signSubBudget(subBudgetId) {
|
|
1575
|
+
const identity = await options.signContext?.loadIdentity() ?? null;
|
|
1576
|
+
if (!identity) {
|
|
1577
|
+
throw new HavenSigningError(
|
|
1578
|
+
`sub_budget_id signing needs the agent identity (identity.json next to the signer credentials), which this signer could not load. Re-run \`${connectorRerunCommand()}\` to restore it.`
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
const ctx = await fetchSubBudgetSignContext(
|
|
1582
|
+
identity,
|
|
1583
|
+
subBudgetId,
|
|
1584
|
+
options.signContext?.fetchImpl,
|
|
1585
|
+
void 0,
|
|
1586
|
+
options.signContext?.clientIdentity
|
|
1587
|
+
);
|
|
1588
|
+
let signature;
|
|
1589
|
+
if (ctx.purpose === "open") {
|
|
1590
|
+
try {
|
|
1591
|
+
assertOwnSubBudgetChild(
|
|
1592
|
+
ctx.typedData,
|
|
1593
|
+
{
|
|
1594
|
+
chainId: ctx.expected.chainId,
|
|
1595
|
+
tokenAddress: ctx.expected.tokenAddress,
|
|
1596
|
+
periodAmountAtomic: ctx.expected.periodAmountAtomic,
|
|
1597
|
+
periodDurationSeconds: ctx.expected.periodDurationSeconds,
|
|
1598
|
+
startDate: ctx.expected.startDate,
|
|
1599
|
+
recipientAddress: ctx.expected.recipientAddress,
|
|
1600
|
+
expiresAt: ctx.expected.expiresAt,
|
|
1601
|
+
parentDelegationHash: ctx.expected.parentDelegationHash,
|
|
1602
|
+
delegateAccount: ctx.expected.delegateAccount,
|
|
1603
|
+
childDelegateAccount: ctx.expected.childDelegateAccount
|
|
1604
|
+
},
|
|
1605
|
+
signer.delegateAddress
|
|
1606
|
+
);
|
|
1607
|
+
} catch (err) {
|
|
1608
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1609
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1610
|
+
}
|
|
1611
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1612
|
+
} else {
|
|
1613
|
+
try {
|
|
1614
|
+
assertUserOpTypedDataBinding(ctx.typedData, ctx.userOpHash);
|
|
1615
|
+
} catch (err) {
|
|
1616
|
+
if (err instanceof HavenUserOpBindingError) throw new HavenUserOpBindingRefusedError(err.message);
|
|
1617
|
+
throw err;
|
|
1618
|
+
}
|
|
1619
|
+
try {
|
|
1620
|
+
assertOwnSubBudgetCloseUserOp(
|
|
1621
|
+
ctx.typedData,
|
|
1622
|
+
{ delegationHash: ctx.expected.delegationHash },
|
|
1623
|
+
signer.delegateAddress
|
|
1624
|
+
);
|
|
1625
|
+
} catch (err) {
|
|
1626
|
+
if (err instanceof HavenTypedDataRefusedError) throw err;
|
|
1627
|
+
throw new HavenTypedDataRefusedError(err instanceof Error ? err.message : String(err));
|
|
1628
|
+
}
|
|
1629
|
+
signature = await signer.signDelegationTypedData(ctx.typedData);
|
|
1630
|
+
}
|
|
1631
|
+
await auditSigning("haven_sign", hashTypedData(ctx.typedData));
|
|
1632
|
+
return {
|
|
1633
|
+
signature,
|
|
1634
|
+
sub_budget_id: ctx.subBudgetId,
|
|
1635
|
+
purpose: ctx.purpose,
|
|
1636
|
+
next_tool_name: "haven_submit",
|
|
1637
|
+
next_tool_server_role: "hosted",
|
|
1638
|
+
next_arguments: { sub_budget_id: ctx.subBudgetId, signature }
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1246
1641
|
return {
|
|
1247
1642
|
haven_sign: async (input) => runTool(async () => {
|
|
1248
|
-
const args =
|
|
1643
|
+
const args = parseStrictFor("haven_sign", coerceX402Expected(input));
|
|
1644
|
+
if (args.task_budget_id) {
|
|
1645
|
+
if (args.payment_id || args.payload_hash) {
|
|
1646
|
+
throw new z$1.ZodError([
|
|
1647
|
+
{
|
|
1648
|
+
code: z$1.ZodIssueCode.custom,
|
|
1649
|
+
path: ["task_budget_id"],
|
|
1650
|
+
message: "task_budget_id is mutually exclusive with payment_id / payload_hash \u2014 pass exactly one."
|
|
1651
|
+
}
|
|
1652
|
+
]);
|
|
1653
|
+
}
|
|
1654
|
+
if (args.sub_budget_id) {
|
|
1655
|
+
throw new z$1.ZodError([
|
|
1656
|
+
{
|
|
1657
|
+
code: z$1.ZodIssueCode.custom,
|
|
1658
|
+
path: ["sub_budget_id"],
|
|
1659
|
+
message: "task_budget_id is mutually exclusive with sub_budget_id \u2014 pass exactly one."
|
|
1660
|
+
}
|
|
1661
|
+
]);
|
|
1662
|
+
}
|
|
1663
|
+
return signTaskBudget(args.task_budget_id);
|
|
1664
|
+
}
|
|
1665
|
+
if (args.sub_budget_id) {
|
|
1666
|
+
if (args.payment_id || args.payload_hash) {
|
|
1667
|
+
throw new z$1.ZodError([
|
|
1668
|
+
{
|
|
1669
|
+
code: z$1.ZodIssueCode.custom,
|
|
1670
|
+
path: ["sub_budget_id"],
|
|
1671
|
+
message: "sub_budget_id is mutually exclusive with payment_id / payload_hash \u2014 pass exactly one."
|
|
1672
|
+
}
|
|
1673
|
+
]);
|
|
1674
|
+
}
|
|
1675
|
+
return signSubBudget(args.sub_budget_id);
|
|
1676
|
+
}
|
|
1249
1677
|
const resolved = await resolveSignContext(args, { allowDirectFallback: true });
|
|
1250
1678
|
const typedData = resolved?.ctx.typedData ?? resolveTypedData(args);
|
|
1251
1679
|
const payloadHash = resolved?.ctx.payloadHash ?? args.payload_hash;
|
|
@@ -1288,7 +1716,7 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1288
1716
|
return { signature: result.signature, x402_binding: result.x402Binding, ...clientUpdateField(resolved) };
|
|
1289
1717
|
}),
|
|
1290
1718
|
haven_x402_sign_header: async (input) => runTool(async () => {
|
|
1291
|
-
const args =
|
|
1719
|
+
const args = parseStrictFor("haven_x402_sign_header", coercePaymentRequired(input));
|
|
1292
1720
|
const result = await signer.buildX402PaymentHeader(
|
|
1293
1721
|
args.payment_required,
|
|
1294
1722
|
args.x402_binding
|
|
@@ -1300,7 +1728,7 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1300
1728
|
return { payment_header: result.paymentHeader, accepted: result.accepted };
|
|
1301
1729
|
}),
|
|
1302
1730
|
haven_sign_x402: async (input) => runTool(async () => {
|
|
1303
|
-
const args =
|
|
1731
|
+
const args = parseStrictFor("haven_sign_x402", coerceX402Expected(coercePaymentRequired(input)));
|
|
1304
1732
|
const resolved = await resolveSignContext(args, { allowDirectFallback: false });
|
|
1305
1733
|
const fetched = resolved?.kind === "x402" ? resolved.ctx : void 0;
|
|
1306
1734
|
const payloadHash = fetched?.payloadHash ?? args.payload_hash;
|
|
@@ -1336,7 +1764,7 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1336
1764
|
};
|
|
1337
1765
|
}),
|
|
1338
1766
|
haven_sign_sweep_delegate: async (input) => runTool(async () => {
|
|
1339
|
-
const args =
|
|
1767
|
+
const args = parseStrictFor("haven_sign_sweep_delegate", input);
|
|
1340
1768
|
const result = await signer.signSweepAuthorization({
|
|
1341
1769
|
authorization: args.authorization,
|
|
1342
1770
|
expectedAuth: args.expected_auth,
|
|
@@ -1369,8 +1797,18 @@ function createToolHandlers(signer, options = {}) {
|
|
|
1369
1797
|
}
|
|
1370
1798
|
}
|
|
1371
1799
|
}
|
|
1372
|
-
function
|
|
1373
|
-
|
|
1800
|
+
function parseStrictFor(name, input) {
|
|
1801
|
+
const result = z$1.object(toolSchemas[name]).strict().safeParse(input ?? {});
|
|
1802
|
+
if (result.success) return result.data;
|
|
1803
|
+
const topLevelUnknown = result.error.issues.flatMap(
|
|
1804
|
+
(issue) => issue.code === "unrecognized_keys" && issue.path.length === 0 ? issue.keys : []
|
|
1805
|
+
);
|
|
1806
|
+
if (topLevelUnknown.length === 0) throw result.error;
|
|
1807
|
+
const unknown = [...new Set(topLevelUnknown)];
|
|
1808
|
+
const err = new Error(
|
|
1809
|
+
`${UNSUPPORTED_ARGUMENT_MARKER} ${name} does not accept ${unknown.map((k) => `"${k}"`).join(", ")} \u2014 this signer predates that argument form. Nothing was signed or fetched.`
|
|
1810
|
+
);
|
|
1811
|
+
throw err;
|
|
1374
1812
|
}
|
|
1375
1813
|
function coerceX402Expected(input) {
|
|
1376
1814
|
if (!input || typeof input !== "object") return input;
|
|
@@ -1409,6 +1847,25 @@ async function runTool(fn) {
|
|
|
1409
1847
|
}
|
|
1410
1848
|
}
|
|
1411
1849
|
function normalizeError(err) {
|
|
1850
|
+
if (err instanceof Error && err.message.startsWith(UNSUPPORTED_ARGUMENT_MARKER)) {
|
|
1851
|
+
const unknown = [...err.message.matchAll(/"([^"]+)"/g)].map((m) => m[1]);
|
|
1852
|
+
return {
|
|
1853
|
+
success: false,
|
|
1854
|
+
code: "UNSUPPORTED_ARGUMENT",
|
|
1855
|
+
message: err.message.replace(`${UNSUPPORTED_ARGUMENT_MARKER} `, ""),
|
|
1856
|
+
unknown_arguments: unknown,
|
|
1857
|
+
signer_version: SIGNER_VERSION,
|
|
1858
|
+
fallback: connectorUpgradeCommand(),
|
|
1859
|
+
next_action: AgentPaymentNextAction.StopAndTellUser,
|
|
1860
|
+
...nextStepWireFields(
|
|
1861
|
+
signerRefusalStep({
|
|
1862
|
+
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
1863
|
+
nextTool: null,
|
|
1864
|
+
nextToolOmittedReason: `update @haven_ai/signer: run ${connectorUpgradeCommand()} and the repair line it prints, then repeat the same call`
|
|
1865
|
+
})
|
|
1866
|
+
)
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1412
1869
|
if (err instanceof z$1.ZodError) {
|
|
1413
1870
|
return {
|
|
1414
1871
|
success: false,
|
|
@@ -1430,7 +1887,9 @@ function normalizeError(err) {
|
|
|
1430
1887
|
...nextStepWireFields(signerRefusalStep({
|
|
1431
1888
|
nextAction: AgentPaymentNextAction.StopAndTellUser,
|
|
1432
1889
|
nextTool: null,
|
|
1433
|
-
|
|
1890
|
+
// #3412: the upgrade command, not "re-run the connector" — a bare re-run
|
|
1891
|
+
// stops at "Missing --setup" on an existing install.
|
|
1892
|
+
nextToolOmittedReason: `update @haven_ai/signer: run ${connectorUpgradeCommand()} and the repair line it prints, then repeat the same call`
|
|
1434
1893
|
}))
|
|
1435
1894
|
};
|
|
1436
1895
|
}
|
|
@@ -1516,7 +1975,7 @@ function normalizeError(err) {
|
|
|
1516
1975
|
|
|
1517
1976
|
// src/consent.ts
|
|
1518
1977
|
var toolSummaries = {
|
|
1519
|
-
haven_sign: "signs
|
|
1978
|
+
haven_sign: "signs a Haven-prepared payment, task-budget open, or task-budget close (a UserOp from your own account whose only call redeems a delegation made to it, directly or through a self-delegated task-budget child, or an x402 funding intent against a Haven-signed context)",
|
|
1520
1979
|
haven_x402_sign_header: "builds and signs the EIP-3009 merchant payment header for an x402 payment",
|
|
1521
1980
|
haven_sign_x402: "the two above in one call: funding payload + merchant header",
|
|
1522
1981
|
haven_sign_sweep_delegate: "signs a Haven-prepared gasless sweep of stranded funds back to your own account"
|
|
@@ -1645,8 +2104,6 @@ async function writeAckFile(path, hash) {
|
|
|
1645
2104
|
"utf8"
|
|
1646
2105
|
);
|
|
1647
2106
|
}
|
|
1648
|
-
var SIGNER_NAME = "@haven_ai/signer";
|
|
1649
|
-
var SIGNER_VERSION = "0.5.0-alpha.1";
|
|
1650
2107
|
async function resolveEdgeSigner(options = {}) {
|
|
1651
2108
|
const { signer } = await resolveSignerRuntime(options);
|
|
1652
2109
|
return signer;
|
|
@@ -1701,12 +2158,14 @@ function buildSignerMcpServer(signer, options = {}) {
|
|
|
1701
2158
|
clientIdentity: havenClientIdentity(SIGNER_NAME, SIGNER_VERSION)
|
|
1702
2159
|
}
|
|
1703
2160
|
});
|
|
1704
|
-
const registerTool = server.
|
|
2161
|
+
const registerTool = server.registerTool.bind(server);
|
|
1705
2162
|
for (const name of Object.keys(toolSchemas)) {
|
|
1706
2163
|
registerTool(
|
|
1707
2164
|
name,
|
|
1708
|
-
|
|
1709
|
-
|
|
2165
|
+
{
|
|
2166
|
+
description: toolDescriptions[name],
|
|
2167
|
+
inputSchema: z.object(toolSchemas[name]).passthrough()
|
|
2168
|
+
},
|
|
1710
2169
|
async (args) => toMcpResult(await handlers[name](args))
|
|
1711
2170
|
);
|
|
1712
2171
|
}
|
|
@@ -1760,6 +2219,6 @@ function toMcpResult(payload) {
|
|
|
1760
2219
|
};
|
|
1761
2220
|
}
|
|
1762
2221
|
|
|
1763
|
-
export { AUDIT_ROTATE_BYTES, OWNER_ONLY_MODE, SIGNER_ACK_ENV, SIGNER_CAPABILITY_KEY, SIGNER_HOSTED_HANDOFF_SHAPES, SIGNER_NAME, SIGNER_VERSION, SUPPORTED_SWEEP_BINDING_VERSIONS, SUPPORTED_X402_EXPECTED_VERSIONS, appendSigningAuditEntry, assertSupportedBindingVersion, assertSupportedNodeVersion, assertX402MatchesExpected, buildSignerMcpServer, computeSignerConsentHash, createEdgeSigner, createSigningAuditEntry, createToolHandlers, defaultSigningAuditPath, ensureSignerConsent, hashPayloadForAudit, loadSignerCredentials, permissiveMode, readAccountAddressEnv, readAccountAddressField, renderSignerConsentBlock, resolveEdgeSigner, resolveSignerRuntime, runSignerConsentGate, runSignerStdioServer, signerCapabilityAdvertisement, signerCompatibility, signerInstructions, tightenIfFilePermissive, toolDescriptions, toolSchemas, warnIfCredentialFilePermissive, warnIfFilePermissive };
|
|
2222
|
+
export { AUDIT_ROTATE_BYTES, OWNER_ONLY_MODE, SIGNER_ACK_ENV, SIGNER_CAPABILITY_KEY, SIGNER_HOSTED_HANDOFF_SHAPES, SIGNER_NAME, SIGNER_VERSION, SUPPORTED_SWEEP_BINDING_VERSIONS, SUPPORTED_X402_EXPECTED_VERSIONS, UNSUPPORTED_ARGUMENT_MARKER, appendSigningAuditEntry, assertSupportedBindingVersion, assertSupportedNodeVersion, assertX402MatchesExpected, buildSignerMcpServer, computeSignerConsentHash, createEdgeSigner, createSigningAuditEntry, createToolHandlers, defaultSigningAuditPath, ensureSignerConsent, hashPayloadForAudit, loadSignerCredentials, permissiveMode, readAccountAddressEnv, readAccountAddressField, renderSignerConsentBlock, resolveEdgeSigner, resolveSignerRuntime, runSignerConsentGate, runSignerStdioServer, signerCapabilityAdvertisement, signerCompatibility, signerInstructions, tightenIfFilePermissive, toolDescriptions, toolSchemas, warnIfCredentialFilePermissive, warnIfFilePermissive };
|
|
1764
2223
|
//# sourceMappingURL=index.js.map
|
|
1765
2224
|
//# sourceMappingURL=index.js.map
|