@fora-protocol/sdk 1.0.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.
Files changed (115) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +37 -0
  3. package/gen/ts/vocab/functiontokens.js +78 -0
  4. package/gen/ts/vocab/functiontokens.ts +84 -0
  5. package/gen/ts/vocab/geographytokens.js +30 -0
  6. package/gen/ts/vocab/geographytokens.ts +37 -0
  7. package/gen/ts/vocab/pricingunits.js +56 -0
  8. package/gen/ts/vocab/pricingunits.ts +63 -0
  9. package/gen/ts/vocab/quotametrics.js +40 -0
  10. package/gen/ts/vocab/quotametrics.ts +47 -0
  11. package/gen/ts/vocab/usertypes.js +40 -0
  12. package/gen/ts/vocab/usertypes.ts +46 -0
  13. package/gen/ts/wire/base.js +245 -0
  14. package/gen/ts/wire/base.ts +255 -0
  15. package/gen/ts/wire/names.js +41 -0
  16. package/gen/ts/wire/names.ts +42 -0
  17. package/gen/ts/wire/schemas.js +111 -0
  18. package/gen/ts/wire/schemas.ts +216 -0
  19. package/package.json +164 -0
  20. package/sdk/ts/client/content.d.ts +74 -0
  21. package/sdk/ts/client/content.js +466 -0
  22. package/sdk/ts/client/errors.d.ts +79 -0
  23. package/sdk/ts/client/errors.js +148 -0
  24. package/sdk/ts/client/index.d.ts +241 -0
  25. package/sdk/ts/client/index.js +740 -0
  26. package/sdk/ts/client/route.d.ts +41 -0
  27. package/sdk/ts/client/route.js +107 -0
  28. package/sdk/ts/client/send.d.ts +64 -0
  29. package/sdk/ts/client/send.js +142 -0
  30. package/sdk/ts/client/transport.d.ts +187 -0
  31. package/sdk/ts/client/transport.js +381 -0
  32. package/sdk/ts/core/multisig-parse.d.ts +47 -0
  33. package/sdk/ts/core/multisig-parse.js +234 -0
  34. package/sdk/ts/core/sign-request.d.ts +83 -0
  35. package/sdk/ts/core/sign-request.js +146 -0
  36. package/sdk/ts/core/sign.d.ts +31 -0
  37. package/sdk/ts/core/sign.js +82 -0
  38. package/sdk/ts/core/signing-transport.d.ts +75 -0
  39. package/sdk/ts/core/signing-transport.js +172 -0
  40. package/sdk/ts/core/verifier.d.ts +177 -0
  41. package/sdk/ts/core/verifier.js +269 -0
  42. package/sdk/ts/core/verify-multisig-request.d.ts +72 -0
  43. package/sdk/ts/core/verify-multisig-request.js +112 -0
  44. package/sdk/ts/core/verify-request.d.ts +181 -0
  45. package/sdk/ts/core/verify-request.js +284 -0
  46. package/sdk/ts/core/window.d.ts +22 -0
  47. package/sdk/ts/core/window.js +43 -0
  48. package/sdk/ts/core/wire-canon.d.ts +20 -0
  49. package/sdk/ts/core/wire-canon.js +174 -0
  50. package/sdk/ts/hono/middleware.d.ts +38 -0
  51. package/sdk/ts/hono/middleware.js +64 -0
  52. package/sdk/ts/resolvers/errors.d.ts +130 -0
  53. package/sdk/ts/resolvers/errors.js +150 -0
  54. package/sdk/ts/resolvers/http.d.ts +98 -0
  55. package/sdk/ts/resolvers/http.js +274 -0
  56. package/sdk/ts/resolvers/index.d.ts +9 -0
  57. package/sdk/ts/resolvers/index.js +15 -0
  58. package/sdk/ts/resolvers/jwks.d.ts +2 -0
  59. package/sdk/ts/resolvers/jwks.js +43 -0
  60. package/sdk/ts/resolvers/offer-key-cache.d.ts +68 -0
  61. package/sdk/ts/resolvers/offer-key-cache.js +152 -0
  62. package/sdk/ts/resolvers/registration-requirements.d.ts +47 -0
  63. package/sdk/ts/resolvers/registration-requirements.js +220 -0
  64. package/sdk/ts/resolvers/ssrf.d.ts +28 -0
  65. package/sdk/ts/resolvers/ssrf.js +235 -0
  66. package/sdk/ts/resolvers/static.d.ts +7 -0
  67. package/sdk/ts/resolvers/static.js +16 -0
  68. package/sdk/ts/resolvers/wba.d.ts +134 -0
  69. package/sdk/ts/resolvers/wba.js +506 -0
  70. package/sdk/ts/resolvers/wellknown.d.ts +28 -0
  71. package/sdk/ts/resolvers/wellknown.js +169 -0
  72. package/sdk/ts/src/acceptance.d.ts +46 -0
  73. package/sdk/ts/src/acceptance.js +162 -0
  74. package/sdk/ts/src/base64url.d.ts +19 -0
  75. package/sdk/ts/src/base64url.js +55 -0
  76. package/sdk/ts/src/crossfield.d.ts +28 -0
  77. package/sdk/ts/src/crossfield.js +215 -0
  78. package/sdk/ts/src/endpoint-rule.d.ts +30 -0
  79. package/sdk/ts/src/endpoint-rule.js +63 -0
  80. package/sdk/ts/src/errordetail.d.ts +115 -0
  81. package/sdk/ts/src/errordetail.js +256 -0
  82. package/sdk/ts/src/hashurl.d.ts +5 -0
  83. package/sdk/ts/src/hashurl.js +15 -0
  84. package/sdk/ts/src/host-ref.d.ts +70 -0
  85. package/sdk/ts/src/host-ref.js +320 -0
  86. package/sdk/ts/src/hosts.d.ts +138 -0
  87. package/sdk/ts/src/hosts.js +214 -0
  88. package/sdk/ts/src/idempotency.d.ts +11 -0
  89. package/sdk/ts/src/idempotency.js +27 -0
  90. package/sdk/ts/src/jsondepth.d.ts +27 -0
  91. package/sdk/ts/src/jsondepth.js +77 -0
  92. package/sdk/ts/src/licenseterm.d.ts +113 -0
  93. package/sdk/ts/src/licenseterm.js +433 -0
  94. package/sdk/ts/src/money.d.ts +21 -0
  95. package/sdk/ts/src/money.js +60 -0
  96. package/sdk/ts/src/offer-sign.d.ts +11 -0
  97. package/sdk/ts/src/offer-sign.js +31 -0
  98. package/sdk/ts/src/opaque-url.d.ts +3 -0
  99. package/sdk/ts/src/opaque-url.js +20 -0
  100. package/sdk/ts/src/pop.d.ts +51 -0
  101. package/sdk/ts/src/pop.js +166 -0
  102. package/sdk/ts/src/regschema.d.ts +229 -0
  103. package/sdk/ts/src/regschema.js +1315 -0
  104. package/sdk/ts/src/scopes.d.ts +20 -0
  105. package/sdk/ts/src/scopes.js +45 -0
  106. package/sdk/ts/src/signurl.d.ts +23 -0
  107. package/sdk/ts/src/signurl.js +107 -0
  108. package/sdk/ts/src/thumbprint.d.ts +14 -0
  109. package/sdk/ts/src/thumbprint.js +24 -0
  110. package/sdk/ts/src/verify.d.ts +49 -0
  111. package/sdk/ts/src/verify.js +109 -0
  112. package/sdk/ts/src/wire-names.d.ts +1 -0
  113. package/sdk/ts/src/wire-names.js +16 -0
  114. package/sdk/ts/src/wire.d.ts +68 -0
  115. package/sdk/ts/src/wire.js +114 -0
@@ -0,0 +1,148 @@
1
+ // The client's typed failure — TS port of sdk/go/connect/callerror.go.
2
+ //
3
+ // A refusal and a failure are different things, and a caller handles the situations
4
+ // differently. It cannot tell them apart from a message, so the class is carried as a
5
+ // value.
6
+ //
7
+ // The one worth naming is: WE refused to send. The routing checks that precede a call to
8
+ // an offer-derived address can decline before anything leaves the process, and folding
9
+ // that into "unreachable" — as a network timeout — hides the difference between "the
10
+ // network is bad" and "the address failed a security check". They call for opposite
11
+ // responses.
12
+ /**
13
+ * ForaCallError is the client's typed failure. Every verb throws this and nothing else,
14
+ * so `instanceof ForaCallError` is not a coin flip on the very type callers are told to
15
+ * branch on — which is what happens when a method yields a typed error where it declines
16
+ * to send and a bare transport error where the peer refuses.
17
+ */
18
+ export class ForaCallError extends Error {
19
+ kind;
20
+ op;
21
+ status;
22
+ reason;
23
+ detail;
24
+ /** The peer's own developer message, taken from its typed reason. Empty when the
25
+ * answer carried none.
26
+ *
27
+ * A field rather than something to recover from `message`'s rendering, because a
28
+ * reason rendered into prose cannot be read back out without parsing it. It sits
29
+ * BESIDE `reason` rather than in it: `reason` is the peer's machine token.
30
+ *
31
+ * NON-AUTHORITATIVE and UNBOUNDED — the contract says both of the field it comes
32
+ * from. Branch on `kind` or on the typed reason, never on this text, and bound it
33
+ * before rendering it to a log line or an agent. */
34
+ peerMessage;
35
+ constructor(init) {
36
+ super(renderCallError(init), init.cause !== undefined ? { cause: init.cause } : undefined);
37
+ this.name = "ForaCallError";
38
+ this.kind = init.kind;
39
+ this.op = init.op;
40
+ this.status = init.status;
41
+ this.reason = init.reason;
42
+ this.detail = init.detail;
43
+ // Taken ONLY from what the decode site passed, never derived from `detail`
44
+ // here. A detail is not always the peer's: the content leg SYNTHESIZES one
45
+ // from the edge's refusal token, and its message is this SDK's own sentence
46
+ // with the token quoted into it. Deriving from the field would put the SDK's
47
+ // words in the field that claims to hold a remote party's, which is the one
48
+ // thing this field exists not to do.
49
+ this.peerMessage = init.peerMessage ?? "";
50
+ }
51
+ /**
52
+ * The most specific machine-readable reason available: the peer's own token when it
53
+ * sent one, otherwise the failure class.
54
+ */
55
+ reasonOf() {
56
+ return this.reason !== undefined && this.reason !== ""
57
+ ? this.reason
58
+ : this.kind;
59
+ }
60
+ }
61
+ // renderCallError mirrors the Go failure renderer's shape (package, op, class, status,
62
+ // reason, cause) so a log line reads the same whichever SDK produced it.
63
+ function renderCallError(init) {
64
+ const parts = [`fora/client: ${init.op}: ${init.kind}`];
65
+ if (init.status !== undefined && init.status !== 0) {
66
+ parts.push(`status ${init.status}`);
67
+ }
68
+ if (init.reason !== undefined && init.reason !== "") {
69
+ parts.push(`reason ${init.reason}`);
70
+ }
71
+ if (init.cause !== undefined) {
72
+ parts.push(String(init.cause instanceof Error ? init.cause.message : init.cause));
73
+ }
74
+ return parts.join(": ");
75
+ }
76
+ /** The refusal for an address that failed a routing check. Its own constructor because
77
+ * every such refusal must state which check declined and must never carry a status:
78
+ * nothing was sent, so there is nothing to report a status for. */
79
+ export function notSent(op, cause) {
80
+ return new ForaCallError({ kind: "not_sent", op, cause });
81
+ }
82
+ /** The refusal for a request that could not be assembled, or an answer that could not be
83
+ * read as the protocol defines it. */
84
+ export function malformed(op, cause) {
85
+ return new ForaCallError({ kind: "malformed", op, cause });
86
+ }
87
+ /**
88
+ * The Connect code a peer answered with, mapped onto the failure class.
89
+ *
90
+ * A peer that answered is a refusal, whatever it said: the distinction a caller needs is
91
+ * "it said no" versus "it never answered", and only the first is worth surfacing a reason
92
+ * for. Three codes land on the second side. `unavailable` is the transport failure
93
+ * proper; `deadline_exceeded` and `canceled` are LOCAL outcomes wearing a Connect code,
94
+ * so neither means the peer reached a verdict — classifying a caller's own cancellation
95
+ * as a refusal would tell it the Exchange declined a call the Exchange may never have
96
+ * seen. `resource_exhausted` is the read cap seen from this side: the peer's answer was
97
+ * larger than the client agreed to read.
98
+ */
99
+ /**
100
+ * The Connect code a status implies when the body is not an envelope that names one.
101
+ *
102
+ * connect-go derives the code from the HTTP STATUS in exactly two cases: a body it cannot
103
+ * read as an envelope, and an envelope carrying no code. Both are what a deployment's own
104
+ * infrastructure produces — a gateway draining, a proxy answering with its own HTML page —
105
+ * and the difference between "the Exchange declined this" and "nothing answered" is the
106
+ * whole reason the failure classes exist. Anything not listed is `unknown`, which reads as
107
+ * a refusal.
108
+ *
109
+ * Not a rule invented here: it is connect-go's own table (protocol.go, httpToCode), and
110
+ * the transport-failure corpus is captured from a real client so a future change to it is
111
+ * reported rather than mirrored by hand.
112
+ */
113
+ const STATUS_CODES = {
114
+ // A 3xx reached this client only because the send refused to follow it, and every leg
115
+ // refuses. That is a server that did not answer the call, not one that declined it —
116
+ // which is what all three failure taxonomies say a redirect is. connect-go maps these
117
+ // to CodeUnknown, but it never sees one: its transport follows redirects, so the row is
118
+ // unreachable there rather than decided.
119
+ 301: "unavailable",
120
+ 302: "unavailable",
121
+ 303: "unavailable",
122
+ 307: "unavailable",
123
+ 308: "unavailable",
124
+ 400: "internal",
125
+ 401: "unauthenticated",
126
+ 403: "permission_denied",
127
+ 404: "unimplemented",
128
+ 429: "unavailable",
129
+ 502: "unavailable",
130
+ 503: "unavailable",
131
+ 504: "unavailable",
132
+ };
133
+ /** The Connect code a non-envelope answer carries, derived from its status. */
134
+ export function connectCodeFromStatus(status) {
135
+ return STATUS_CODES[status] ?? "unknown";
136
+ }
137
+ export function kindOfConnectCode(code) {
138
+ switch (code) {
139
+ case "unavailable":
140
+ case "deadline_exceeded":
141
+ case "canceled":
142
+ return "unreachable";
143
+ case "resource_exhausted":
144
+ return "too_large";
145
+ default:
146
+ return "refused";
147
+ }
148
+ }
@@ -0,0 +1,241 @@
1
+ import { type DiscoveryResult, type Mode, type VerifiedOffer } from "../core/verifier.ts";
2
+ import type { z } from "zod";
3
+ import { type Window } from "../core/window.ts";
4
+ import { DisputeResponseSchema, GetAccountStatusResponseSchema, PushResourcesResponseSchema, RefreshCatalogResponseSchema, RegisterResponseSchema, RemoveResourcesResponseSchema, TransactionResponseSchema, UsageReportResponseSchema } from "../../../gen/ts/wire/schemas.ts";
5
+ import { type Content } from "./content.ts";
6
+ import { type RegistrationRequirements } from "../resolvers/index.ts";
7
+ import type { EndpointResolver } from "./route.ts";
8
+ import { type UnarySend, type Validation } from "./transport.ts";
9
+ /** How long a delivery-fetch proof stays valid, in seconds.
10
+ *
11
+ * Short on purpose, and deliberately NOT the signed URL's own expiry, which can be hours:
12
+ * the proof covers only the method and the URL, so for as long as the window is open
13
+ * anyone who observes the request can repeat it. */
14
+ export declare const DEFAULT_PROOF_WINDOW_SEC = 30;
15
+ /** Reports what one Exchange asks of a registration.
16
+ *
17
+ * An interface for the same two reasons the endpoint seam is one: a test can drive a
18
+ * registration without standing up a manifest server, and this module has no way to
19
+ * accept a terms digest or a schema from configuration — the only way to skip the read
20
+ * is to set `terms_digest` on the request, where the signature covers it.
21
+ *
22
+ * An implementation MUST NOT serve the answer from a cache. The contract requires a
23
+ * registering client to read the digest from a freshly fetched manifest, so a cached one
24
+ * breaks the rule the field exists to record.
25
+ *
26
+ * An implementation's FAILURE decides how a caller is told to react, so it is part of the
27
+ * contract rather than an implementation detail. A failure that is a VERDICT — the domain
28
+ * is unusable, the deployment excludes it, the document served is not an Exchange's, or it
29
+ * is one this reader cannot use — MUST throw the resolver tier's ExchangeNotPermitted,
30
+ * ManifestNotExchange or ManifestUnusable, or the invalid-host error raised for a
31
+ * value that is not a bare domain;
32
+ * those surface as `not_sent`, which tells the caller not to retry. Anything else is read
33
+ * as a transport failure and reported as `unreachable`, i.e. worth retrying. An
34
+ * implementation that throws a bare error for a refusal therefore has its final answer
35
+ * retried indefinitely.
36
+ *
37
+ * ManifestUnusable is the seam's word for "the document arrived and cannot be read for
38
+ * what a registration owes". The SDK's own reader reaches it for a document version it
39
+ * cannot classify, and treats its other two disappointments as absence or as a transport
40
+ * failure. An implementation STRICTER than that one — validating the whole document, or
41
+ * applying a narrower version rule — reaches for the same word, and would otherwise hold
42
+ * a final answer this seam reported as transient.
43
+ *
44
+ * Note which class that is NOT. ManifestVersionRefused belongs to the endpoint seam and
45
+ * is absent from the list above on purpose: the two vocabularies are disjoint, one
46
+ * answering whether an endpoint may be dialled and this one whether a document can be
47
+ * read. An implementation that throws the endpoint class for a version refusal here has
48
+ * its verdict read as a transport failure. */
49
+ export interface RegistrationRequirementsReader {
50
+ resolveRegistrationRequirements(exchange: string): Promise<RegistrationRequirements>;
51
+ }
52
+ /** Everything a client is built from. Every field is injected; the client owns none of it. */
53
+ export interface ClientOptions {
54
+ /** The RFC 9421 request signer. Custody stays with the application — the SDK receives
55
+ * a non-extractable CryptoKey and the keyid it signs under, never key bytes. */
56
+ signer?: {
57
+ privKey: CryptoKey;
58
+ keyid: string;
59
+ };
60
+ /** The PUBLIC half of the key `signer` signs with. A bound delivery fetch presents it
61
+ * in a header and derives the agent identity from it, and a non-extractable CryptoKey
62
+ * cannot yield it — custody keeps the private half, so the public half is supplied
63
+ * alongside. Without it the client can buy but cannot fetch what it bought.
64
+ *
65
+ * There is deliberately no option for a separate agent PRIVATE key. The protocol
66
+ * carries one agent identity: agent_identity_hash is the thumbprint of the agent's
67
+ * request-signing key, an Exchange verifies the detached acceptance against the key
68
+ * registered for the caller its request signature identified, and the delivery URL is
69
+ * bound to that same thumbprint. A second key would be refused at execute, and any URL
70
+ * it did produce could never be fetched. */
71
+ agentPublicKey?: CryptoKey;
72
+ /** The agent's own identity, forwarded on discovery and required on a purchase: both
73
+ * reference services resolve the calling agent from it and refuse a request naming
74
+ * none. */
75
+ requester?: Record<string, unknown>;
76
+ /** Offer-verification strictness. Defaults to "strict" — fail-closed. */
77
+ verification?: Mode;
78
+ /** Whether an outbound request is checked against its generated schema first.
79
+ * Defaults to "strict", which is deliberately stricter than Go — see the Validation
80
+ * type for why. Orthogonal to `verification`: this one is about the message going
81
+ * out, that one about the offers coming back. */
82
+ validation?: Validation;
83
+ /** Resolves an exchange identity to its raw 32-byte Ed25519 offer-signing key.
84
+ * Injected: the client owns no key state. */
85
+ resolveOfferKey?: (exchange: string) => Promise<Uint8Array<ArrayBuffer> | undefined>;
86
+ /** Turns an offer's exchange domain into that Exchange's own advertised origin. Never
87
+ * configuration — a usage report and a dispute go where the signed offer says. */
88
+ endpointResolver?: EndpointResolver;
89
+ /** Reports what one Exchange asks of a registration — the terms revision submitting
90
+ * one accepts, and the schema its registration_data must match. Defaults to the
91
+ * well-known reader over the SSRF-guarded transport, built once with this client:
92
+ * the domain comes off the request rather than from configuration, so it is the
93
+ * request-derived provenance that takes the guarded default.
94
+ *
95
+ * The reader it takes holds no document cache, and that is the point rather than an
96
+ * implementation detail: the contract requires a registering client to read the terms
97
+ * digest from a FRESHLY fetched manifest, so an implementation serving it from a
98
+ * cache breaks the rule the field exists to record. There is deliberately no option
99
+ * to supply a digest or a schema directly — a caller managing its own requirements
100
+ * sets `terms_digest` on the request, which suppresses the read and says so on the
101
+ * message the signature covers. */
102
+ registrationRequirements?: RegistrationRequirementsReader;
103
+ /** The WBA directory origin this client signs as. */
104
+ signatureAgent?: string;
105
+ /** The RFC 9421 freshness window stamped on every outbound call. */
106
+ signWindow?: Window;
107
+ /** The freshness window stamped on a delivery-fetch proof. */
108
+ proofWindow?: Window;
109
+ /** Mints the X-Request-ID correlation value. Absent sends no header. */
110
+ requestId?: () => string;
111
+ /** The dialing seam for the configured (home Exchange / Broker) leg. */
112
+ send?: UnarySend;
113
+ /** The dialing seam for the OFFER-DERIVED leg. Defaults to the SSRF-guarded send,
114
+ * because the caller names a domain, the manifest it serves names an endpoint, and a
115
+ * signed call then goes there. */
116
+ guardedSend?: UnarySend;
117
+ maxRPCReadBytes?: number;
118
+ callTimeoutMs?: number;
119
+ contentTimeoutMs?: number;
120
+ maxContentBytes?: number;
121
+ /** The clock the offer Verifier reads, in epoch milliseconds. */
122
+ now?: () => number;
123
+ }
124
+ /** Tunes a single state-mutating call. */
125
+ export interface CallOptions {
126
+ /**
127
+ * Pins the idempotency key for this call. Reusing a key makes the call a deliberate
128
+ * replay: the server dedupes on it (a fresh key is minted per call by default). The
129
+ * SDK never tracks keys — the server owns dedup.
130
+ *
131
+ * Hold the key and pass the same one back when retrying, on every verb that takes
132
+ * this option. The key identifies the ACTION, not the attempt: a fresh key on a retry
133
+ * reads to the server as a second purchase, a second report, a second dispute.
134
+ */
135
+ idempotencyKey?: string;
136
+ }
137
+ /**
138
+ * The response types, inferred from the generated schemas rather than restated.
139
+ *
140
+ * A verb returning `Record<string, unknown>` hands a caller no help exactly where it is
141
+ * needed: `transaction_id`, `report_id` and the retrieval endpoint are the links of the
142
+ * dispute chain, and every read of one was an unchecked index. Python's verbs return the
143
+ * generated models, so the two faces were the same verb names over materially different
144
+ * ergonomics.
145
+ */
146
+ export type TransactionResponse = z.infer<typeof TransactionResponseSchema>;
147
+ /** The answer to a usage report; carries the `report_id` a dispute is filed against. */
148
+ export type UsageReportResponse = z.infer<typeof UsageReportResponseSchema>;
149
+ /** The answer to a dispute. */
150
+ export type DisputeResponse = z.infer<typeof DisputeResponseSchema>;
151
+ /** The agent-facing Exchange client. */
152
+ export interface Client {
153
+ discover(query: Record<string, unknown>): Promise<DiscoveryResult>;
154
+ execute(offer: VerifiedOffer, opts?: CallOptions): Promise<TransactionResponse>;
155
+ reportUsage(report: Record<string, unknown>, opts?: CallOptions): Promise<UsageReportResponse>;
156
+ dispute(request: Record<string, unknown>, opts?: CallOptions): Promise<DisputeResponse>;
157
+ /** Create this agent's account at the Exchange the request names. Takes no
158
+ * CallOptions: the message carries no idempotency key, because registering again
159
+ * returns the same account handle. */
160
+ register(request: Record<string, unknown>): Promise<RegisterResponse>;
161
+ /** Read whether this agent's account at the named Exchange is active. An empty
162
+ * `billing_ref` is a NORMAL answer — no account there yet. */
163
+ getAccountStatus(request: Record<string, unknown>): Promise<GetAccountStatusResponse>;
164
+ fetch(signedURL: string): Promise<Content>;
165
+ }
166
+ /** The Broker client. */
167
+ export interface BrokerClient {
168
+ resolve(request: Record<string, unknown>): Promise<DiscoveryResult>;
169
+ }
170
+ /**
171
+ * createClient builds a client against baseURL — the agent's HOME Exchange, the one its
172
+ * account lives on.
173
+ *
174
+ * Discovery and purchase go to baseURL. A usage report or a dispute does NOT: those reach
175
+ * the Exchange that ISSUED the offer, resolved per call from that Exchange's own
176
+ * manifest, over a separately guarded transport.
177
+ */
178
+ export declare function createClient(baseURL: string, options?: ClientOptions): Client;
179
+ /**
180
+ * createBrokerClient builds a client against a Broker's base URL.
181
+ *
182
+ * A SEPARATE constructor rather than a second surface on the exchange client because the
183
+ * two speak to different parties. A Broker is not an Exchange: it fans a query out across
184
+ * Exchanges it knows and relays back what they offered, so its address is the Broker's,
185
+ * not any Exchange's. Hanging both off one base URL would mean one of the two was always
186
+ * pointed at the wrong party.
187
+ *
188
+ * It takes the same options, but only the ones a discovery call has any use for do
189
+ * anything, and two need care. A single pinned offer key is the wrong shape here: Broker
190
+ * fan-out returns offers minted by different Exchanges, so inject a resolver that
191
+ * resolves each issuing Exchange's own key. And `requester` is REQUIRED, not optional: a
192
+ * Broker resolves the calling agent from it and declines a request naming none, so
193
+ * resolve refuses locally rather than spending a round trip to be told.
194
+ */
195
+ export declare function createBrokerClient(baseURL: string, options?: ClientOptions): BrokerClient;
196
+ /** The answer to a registration: the account handle this Exchange minted, and the terms
197
+ * revision it recorded against it. */
198
+ export type RegisterResponse = z.infer<typeof RegisterResponseSchema>;
199
+ /** The answer to an account-status read. An empty account handle is a NORMAL answer: it
200
+ * means this agent holds no account at that Exchange yet. */
201
+ export type GetAccountStatusResponse = z.infer<typeof GetAccountStatusResponseSchema>;
202
+ /** The answer to a catalog push: accepted/rejected counts and the warnings the accepted terms carry. */
203
+ export type PushResourcesResponse = z.infer<typeof PushResourcesResponseSchema>;
204
+ /** The answer to a catalog removal. */
205
+ export type RemoveResourcesResponse = z.infer<typeof RemoveResourcesResponseSchema>;
206
+ /** The answer to a catalog refresh request. */
207
+ export type RefreshCatalogResponse = z.infer<typeof RefreshCatalogResponseSchema>;
208
+ /** The publisher-facing Catalog client. */
209
+ export interface CatalogClient {
210
+ pushResources(request: Record<string, unknown>): Promise<PushResourcesResponse>;
211
+ removeResources(request: Record<string, unknown>): Promise<RemoveResourcesResponse>;
212
+ refreshCatalog(request: Record<string, unknown>): Promise<RefreshCatalogResponse>;
213
+ }
214
+ /**
215
+ * createCatalogClient builds a client against an Exchange's CATALOG endpoint — the
216
+ * publisher role's face: push, remove and refresh the catalog entries a publisher, or a
217
+ * contributor it authorised, supplies.
218
+ *
219
+ * A SEPARATE constructor, as the Broker's is, and for a related reason: the address is a
220
+ * different one. An Exchange advertises CatalogService at its manifest's
221
+ * `catalog_endpoint`, distinct from the ExchangeService endpoint the agent client dials,
222
+ * and the caller is a different party holding a different key — a contributor's, named
223
+ * by `caller_id`, never an agent's. Hanging the catalog verbs on the agent client would
224
+ * carry every agent-only holder into a client that uses none of them, and point one of
225
+ * the two roles at the wrong address.
226
+ *
227
+ * The publisher chose the Exchange, so the origin is configuration and the leg runs on
228
+ * the plain send — the posture of the agent client's home Exchange, not of its
229
+ * offer-derived leg. It takes the same options; `signer` is what a real push needs (an
230
+ * Exchange refuses an unsigned catalog call), and the agent-only ones — the requester,
231
+ * the agent key, the offer-key resolver, the endpoint resolver, the guarded send — are
232
+ * inert here rather than errors, so one option set can build every face.
233
+ */
234
+ export declare function createCatalogClient(baseURL: string, options?: ClientOptions): CatalogClient;
235
+ export { ForaCallError } from "./errors.ts";
236
+ export type { CallErrorKind } from "./errors.ts";
237
+ export type { Content } from "./content.ts";
238
+ export type { EndpointResolver } from "./route.ts";
239
+ export type { UnaryRequest, UnaryResponse, UnarySend, Validation } from "./transport.ts";
240
+ export { DEFAULT_CALL_TIMEOUT_MS, DEFAULT_MAX_RPC_READ_BYTES, NOT_CANONICAL_WIRE_NAMING, } from "./transport.ts";
241
+ export { DEFAULT_CONTENT_TIMEOUT_MS, DEFAULT_MAX_CONTENT_BYTES, } from "./content.ts";