@keeperhub/wallet 0.1.2 → 0.1.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/cli.cjs +48 -141
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +48 -141
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +128 -141
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -52
- package/dist/index.d.ts +45 -52
- package/dist/index.js +128 -141
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/keeperhub-wallet.skill.md +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -37,49 +37,6 @@ declare class WalletConfigMissingError extends Error {
|
|
|
37
37
|
constructor();
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
type ClientOptions = {
|
|
41
|
-
/** Defaults to process.env.KEEPERHUB_API_URL ?? "https://app.keeperhub.com" */
|
|
42
|
-
baseUrl?: string;
|
|
43
|
-
/** Injected for tests; defaults to global fetch */
|
|
44
|
-
fetch?: typeof fetch;
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* 202 ask-tier envelope returned by /sign and /approval-request when the
|
|
48
|
-
* risk classifier routes a request to the ask queue. Callers poll
|
|
49
|
-
* `/api/agentic-wallet/approval-request/:id` until status !== "pending".
|
|
50
|
-
*/
|
|
51
|
-
type AskTierResponse = {
|
|
52
|
-
_status: 202;
|
|
53
|
-
approvalRequestId: string;
|
|
54
|
-
};
|
|
55
|
-
/**
|
|
56
|
-
* HMAC-signed HTTP client for the KeeperHub agentic-wallet API surface.
|
|
57
|
-
* Every request to /api/agentic-wallet/* (except /provision, which uses
|
|
58
|
-
* the session cookie) flows through this class.
|
|
59
|
-
*
|
|
60
|
-
* @security No logging of headers, body, or response bodies. Any stdout
|
|
61
|
-
* emitter (the global console object or util.inspect) added to this
|
|
62
|
-
* file is a T-34-08 violation (grep-enforced in CI).
|
|
63
|
-
*/
|
|
64
|
-
declare class KeeperHubClient {
|
|
65
|
-
private readonly baseUrl;
|
|
66
|
-
private readonly fetchImpl;
|
|
67
|
-
private readonly wallet;
|
|
68
|
-
constructor(wallet: WalletConfig, opts?: ClientOptions);
|
|
69
|
-
/**
|
|
70
|
-
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
71
|
-
* /provision. Path MUST start with a leading slash. Body is
|
|
72
|
-
* JSON.stringify'd (or the empty string for GET).
|
|
73
|
-
*
|
|
74
|
-
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
75
|
-
* message)` where `code` is the server-supplied field or the default
|
|
76
|
-
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
77
|
-
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
78
|
-
* AskTierResponse envelope.
|
|
79
|
-
*/
|
|
80
|
-
request<T>(method: "GET" | "POST", path: string, body?: unknown): Promise<T | AskTierResponse>;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
40
|
type BalanceSnapshot = {
|
|
84
41
|
base: {
|
|
85
42
|
chain: "base";
|
|
@@ -93,23 +50,16 @@ type BalanceSnapshot = {
|
|
|
93
50
|
amount: string;
|
|
94
51
|
address: `0x${string}`;
|
|
95
52
|
};
|
|
96
|
-
offChainCredit: {
|
|
97
|
-
amount: string;
|
|
98
|
-
currency: "USD";
|
|
99
|
-
};
|
|
100
53
|
};
|
|
101
54
|
type CheckBalanceOptions = {
|
|
102
55
|
/** Injectable viem client for Base (tests mock readContract). */
|
|
103
56
|
baseClient?: PublicClient;
|
|
104
57
|
/** Injectable viem client for Tempo (tests mock readContract). */
|
|
105
58
|
tempoClient?: PublicClient;
|
|
106
|
-
/** Injectable KeeperHubClient (tests inject a mocked fetch). */
|
|
107
|
-
khClient?: KeeperHubClient;
|
|
108
59
|
};
|
|
109
60
|
/**
|
|
110
|
-
* Read the wallet's balance across Base + Tempo
|
|
111
|
-
*
|
|
112
|
-
* Promise.
|
|
61
|
+
* Read the wallet's on-chain balance across Base + Tempo in parallel. Both
|
|
62
|
+
* legs must resolve; any single failure rejects the Promise.
|
|
113
63
|
*
|
|
114
64
|
* Amounts are formatted as decimal strings (6-decimal USDC precision) so the
|
|
115
65
|
* caller can render them without BigInt math.
|
|
@@ -168,6 +118,49 @@ declare const BASE_USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
|
168
118
|
/** Bridged USDC (USDC.e) on Tempo mainnet. NOT the same contract as BASE_USDC. */
|
|
169
119
|
declare const TEMPO_USDC_E: "0x20c000000000000000000000b9537d11c60e8b50";
|
|
170
120
|
|
|
121
|
+
type ClientOptions = {
|
|
122
|
+
/** Defaults to process.env.KEEPERHUB_API_URL ?? "https://app.keeperhub.com" */
|
|
123
|
+
baseUrl?: string;
|
|
124
|
+
/** Injected for tests; defaults to global fetch */
|
|
125
|
+
fetch?: typeof fetch;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* 202 ask-tier envelope returned by /sign and /approval-request when the
|
|
129
|
+
* risk classifier routes a request to the ask queue. Callers poll
|
|
130
|
+
* `/api/agentic-wallet/approval-request/:id` until status !== "pending".
|
|
131
|
+
*/
|
|
132
|
+
type AskTierResponse = {
|
|
133
|
+
_status: 202;
|
|
134
|
+
approvalRequestId: string;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* HMAC-signed HTTP client for the KeeperHub agentic-wallet API surface.
|
|
138
|
+
* Every request to /api/agentic-wallet/* (except /provision, which uses
|
|
139
|
+
* the session cookie) flows through this class.
|
|
140
|
+
*
|
|
141
|
+
* @security No logging of headers, body, or response bodies. Any stdout
|
|
142
|
+
* emitter (the global console object or util.inspect) added to this
|
|
143
|
+
* file is a T-34-08 violation (grep-enforced in CI).
|
|
144
|
+
*/
|
|
145
|
+
declare class KeeperHubClient {
|
|
146
|
+
private readonly baseUrl;
|
|
147
|
+
private readonly fetchImpl;
|
|
148
|
+
private readonly wallet;
|
|
149
|
+
constructor(wallet: WalletConfig, opts?: ClientOptions);
|
|
150
|
+
/**
|
|
151
|
+
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
152
|
+
* /provision. Path MUST start with a leading slash. Body is
|
|
153
|
+
* JSON.stringify'd (or the empty string for GET).
|
|
154
|
+
*
|
|
155
|
+
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
156
|
+
* message)` where `code` is the server-supplied field or the default
|
|
157
|
+
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
158
|
+
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
159
|
+
* AskTierResponse envelope.
|
|
160
|
+
*/
|
|
161
|
+
request<T>(method: "GET" | "POST", path: string, body?: unknown): Promise<T | AskTierResponse>;
|
|
162
|
+
}
|
|
163
|
+
|
|
171
164
|
type FundInstructions = {
|
|
172
165
|
/** Coinbase Onramp deeplink (legacy query-param form). */
|
|
173
166
|
coinbaseOnrampUrl: string;
|
package/dist/index.js
CHANGED
|
@@ -79,124 +79,6 @@ var tempo = defineChain({
|
|
|
79
79
|
var BASE_USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
80
80
|
var TEMPO_USDC_E = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
81
81
|
|
|
82
|
-
// src/hmac.ts
|
|
83
|
-
import { createHash, createHmac } from "crypto";
|
|
84
|
-
function computeSignature(secret, method, path, subOrgId, body, timestamp) {
|
|
85
|
-
const bodyDigest = createHash("sha256").update(body).digest("hex");
|
|
86
|
-
const signingString = `${method}
|
|
87
|
-
${path}
|
|
88
|
-
${subOrgId}
|
|
89
|
-
${bodyDigest}
|
|
90
|
-
${timestamp}`;
|
|
91
|
-
return createHmac("sha256", secret).update(signingString).digest("hex");
|
|
92
|
-
}
|
|
93
|
-
function buildHmacHeaders(secret, method, path, subOrgId, body) {
|
|
94
|
-
const timestamp = String(Math.floor(Date.now() / 1e3));
|
|
95
|
-
const signature = computeSignature(
|
|
96
|
-
secret,
|
|
97
|
-
method,
|
|
98
|
-
path,
|
|
99
|
-
subOrgId,
|
|
100
|
-
body,
|
|
101
|
-
timestamp
|
|
102
|
-
);
|
|
103
|
-
return {
|
|
104
|
-
"X-KH-Sub-Org": subOrgId,
|
|
105
|
-
"X-KH-Timestamp": timestamp,
|
|
106
|
-
"X-KH-Signature": signature
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/types.ts
|
|
111
|
-
var KeeperHubError = class extends Error {
|
|
112
|
-
code;
|
|
113
|
-
constructor(code, message) {
|
|
114
|
-
super(message);
|
|
115
|
-
this.name = "KeeperHubError";
|
|
116
|
-
this.code = code;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
var WalletConfigMissingError = class extends Error {
|
|
120
|
-
constructor() {
|
|
121
|
-
super(
|
|
122
|
-
"Wallet config not found at ~/.keeperhub/wallet.json. Run `npx @keeperhub/wallet add` to provision."
|
|
123
|
-
);
|
|
124
|
-
this.name = "WalletConfigMissingError";
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// src/client.ts
|
|
129
|
-
var TRAILING_SLASH = /\/$/;
|
|
130
|
-
function defaultCodeForStatus(status) {
|
|
131
|
-
if (status === 401) {
|
|
132
|
-
return "HMAC_INVALID";
|
|
133
|
-
}
|
|
134
|
-
if (status === 403) {
|
|
135
|
-
return "POLICY_BLOCKED";
|
|
136
|
-
}
|
|
137
|
-
if (status === 404) {
|
|
138
|
-
return "NOT_FOUND";
|
|
139
|
-
}
|
|
140
|
-
if (status === 502) {
|
|
141
|
-
return "TURNKEY_UPSTREAM";
|
|
142
|
-
}
|
|
143
|
-
return `HTTP_${status}`;
|
|
144
|
-
}
|
|
145
|
-
var KeeperHubClient = class {
|
|
146
|
-
baseUrl;
|
|
147
|
-
fetchImpl;
|
|
148
|
-
wallet;
|
|
149
|
-
constructor(wallet, opts = {}) {
|
|
150
|
-
this.wallet = wallet;
|
|
151
|
-
const envBase = process.env.KEEPERHUB_API_URL;
|
|
152
|
-
this.baseUrl = (opts.baseUrl ?? envBase ?? "https://app.keeperhub.com").replace(TRAILING_SLASH, "");
|
|
153
|
-
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
157
|
-
* /provision. Path MUST start with a leading slash. Body is
|
|
158
|
-
* JSON.stringify'd (or the empty string for GET).
|
|
159
|
-
*
|
|
160
|
-
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
161
|
-
* message)` where `code` is the server-supplied field or the default
|
|
162
|
-
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
163
|
-
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
164
|
-
* AskTierResponse envelope.
|
|
165
|
-
*/
|
|
166
|
-
async request(method, path, body) {
|
|
167
|
-
const bodyStr = body === void 0 ? "" : JSON.stringify(body);
|
|
168
|
-
const hmacHeaders = buildHmacHeaders(
|
|
169
|
-
this.wallet.hmacSecret,
|
|
170
|
-
method,
|
|
171
|
-
path,
|
|
172
|
-
this.wallet.subOrgId,
|
|
173
|
-
bodyStr
|
|
174
|
-
);
|
|
175
|
-
const headers = method === "POST" ? { ...hmacHeaders, "content-type": "application/json" } : { ...hmacHeaders };
|
|
176
|
-
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
177
|
-
method,
|
|
178
|
-
headers,
|
|
179
|
-
body: method === "POST" ? bodyStr : void 0
|
|
180
|
-
});
|
|
181
|
-
if (response.status === 202) {
|
|
182
|
-
const data = await response.json();
|
|
183
|
-
return { _status: 202, approvalRequestId: data.approvalRequestId };
|
|
184
|
-
}
|
|
185
|
-
if (!response.ok) {
|
|
186
|
-
let code = "UNKNOWN";
|
|
187
|
-
let message = `HTTP ${response.status}`;
|
|
188
|
-
try {
|
|
189
|
-
const data = await response.json();
|
|
190
|
-
code = data.code ?? defaultCodeForStatus(response.status);
|
|
191
|
-
message = data.error ?? message;
|
|
192
|
-
} catch {
|
|
193
|
-
}
|
|
194
|
-
throw new KeeperHubError(code, message);
|
|
195
|
-
}
|
|
196
|
-
return await response.json();
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
82
|
// src/balance.ts
|
|
201
83
|
var USDC_DECIMALS = 6;
|
|
202
84
|
async function checkBalance(wallet, opts = {}) {
|
|
@@ -208,8 +90,7 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
208
90
|
chain: tempo,
|
|
209
91
|
transport: http()
|
|
210
92
|
});
|
|
211
|
-
const
|
|
212
|
-
const [baseRaw, tempoRaw, credit] = await Promise.all([
|
|
93
|
+
const [baseRaw, tempoRaw] = await Promise.all([
|
|
213
94
|
baseClient.readContract({
|
|
214
95
|
address: BASE_USDC,
|
|
215
96
|
abi: erc20Abi,
|
|
@@ -221,12 +102,8 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
221
102
|
abi: erc20Abi,
|
|
222
103
|
functionName: "balanceOf",
|
|
223
104
|
args: [wallet.walletAddress]
|
|
224
|
-
})
|
|
225
|
-
khClient.request("GET", "/api/agentic-wallet/credit")
|
|
105
|
+
})
|
|
226
106
|
]);
|
|
227
|
-
if ("_status" in credit) {
|
|
228
|
-
throw new Error("Unexpected 202 response from /api/agentic-wallet/credit");
|
|
229
|
-
}
|
|
230
107
|
return {
|
|
231
108
|
base: {
|
|
232
109
|
chain: "base",
|
|
@@ -239,10 +116,6 @@ async function checkBalance(wallet, opts = {}) {
|
|
|
239
116
|
token: "USDC.e",
|
|
240
117
|
amount: formatUnits(tempoRaw, USDC_DECIMALS),
|
|
241
118
|
address: wallet.walletAddress
|
|
242
|
-
},
|
|
243
|
-
offChainCredit: {
|
|
244
|
-
amount: credit.amount,
|
|
245
|
-
currency: "USD"
|
|
246
119
|
}
|
|
247
120
|
};
|
|
248
121
|
}
|
|
@@ -273,6 +146,34 @@ function fund(walletAddress) {
|
|
|
273
146
|
};
|
|
274
147
|
}
|
|
275
148
|
|
|
149
|
+
// src/hmac.ts
|
|
150
|
+
import { createHash, createHmac } from "crypto";
|
|
151
|
+
function computeSignature(secret, method, path, subOrgId, body, timestamp) {
|
|
152
|
+
const bodyDigest = createHash("sha256").update(body).digest("hex");
|
|
153
|
+
const signingString = `${method}
|
|
154
|
+
${path}
|
|
155
|
+
${subOrgId}
|
|
156
|
+
${bodyDigest}
|
|
157
|
+
${timestamp}`;
|
|
158
|
+
return createHmac("sha256", secret).update(signingString).digest("hex");
|
|
159
|
+
}
|
|
160
|
+
function buildHmacHeaders(secret, method, path, subOrgId, body) {
|
|
161
|
+
const timestamp = String(Math.floor(Date.now() / 1e3));
|
|
162
|
+
const signature = computeSignature(
|
|
163
|
+
secret,
|
|
164
|
+
method,
|
|
165
|
+
path,
|
|
166
|
+
subOrgId,
|
|
167
|
+
body,
|
|
168
|
+
timestamp
|
|
169
|
+
);
|
|
170
|
+
return {
|
|
171
|
+
"X-KH-Sub-Org": subOrgId,
|
|
172
|
+
"X-KH-Timestamp": timestamp,
|
|
173
|
+
"X-KH-Signature": signature
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
276
177
|
// src/skill-install.ts
|
|
277
178
|
import { chmod, copyFile, mkdir, readFile, writeFile } from "fs/promises";
|
|
278
179
|
import { dirname as dirname2, join as join2 } from "path";
|
|
@@ -372,6 +273,26 @@ async function installSkill(options = {}) {
|
|
|
372
273
|
import { chmod as chmod2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
373
274
|
import { homedir as homedir2 } from "os";
|
|
374
275
|
import { dirname as dirname3, join as join3 } from "path";
|
|
276
|
+
|
|
277
|
+
// src/types.ts
|
|
278
|
+
var KeeperHubError = class extends Error {
|
|
279
|
+
code;
|
|
280
|
+
constructor(code, message) {
|
|
281
|
+
super(message);
|
|
282
|
+
this.name = "KeeperHubError";
|
|
283
|
+
this.code = code;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
var WalletConfigMissingError = class extends Error {
|
|
287
|
+
constructor() {
|
|
288
|
+
super(
|
|
289
|
+
"Wallet config not found at ~/.keeperhub/wallet.json. Run `npx @keeperhub/wallet add` to provision."
|
|
290
|
+
);
|
|
291
|
+
this.name = "WalletConfigMissingError";
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// src/storage.ts
|
|
375
296
|
async function readWalletConfig() {
|
|
376
297
|
const walletPath = join3(homedir2(), ".keeperhub", "wallet.json");
|
|
377
298
|
let raw;
|
|
@@ -400,11 +321,11 @@ function getWalletConfigPath() {
|
|
|
400
321
|
}
|
|
401
322
|
|
|
402
323
|
// src/cli.ts
|
|
403
|
-
var
|
|
324
|
+
var TRAILING_SLASH = /\/$/;
|
|
404
325
|
var WALLET_ADDRESS_PATTERN = /^0x[a-fA-F0-9]{40}$/;
|
|
405
326
|
function resolveBaseUrl(override) {
|
|
406
327
|
const candidate = override ?? process.env.KEEPERHUB_API_URL ?? "https://app.keeperhub.com";
|
|
407
|
-
return candidate.replace(
|
|
328
|
+
return candidate.replace(TRAILING_SLASH, "");
|
|
408
329
|
}
|
|
409
330
|
function isNonEmptyString(value) {
|
|
410
331
|
return typeof value === "string" && value.length > 0;
|
|
@@ -518,14 +439,10 @@ async function cmdFund() {
|
|
|
518
439
|
async function cmdBalance() {
|
|
519
440
|
const wallet = await readWalletConfig();
|
|
520
441
|
const snap = await checkBalance(wallet);
|
|
521
|
-
process.stdout.write(`Base USDC:
|
|
442
|
+
process.stdout.write(`Base USDC: ${snap.base.amount}
|
|
522
443
|
`);
|
|
523
|
-
process.stdout.write(`Tempo USDC.e:
|
|
444
|
+
process.stdout.write(`Tempo USDC.e: ${snap.tempo.amount}
|
|
524
445
|
`);
|
|
525
|
-
process.stdout.write(
|
|
526
|
-
`KeeperHub credit: ${snap.offChainCredit.amount} ${snap.offChainCredit.currency}
|
|
527
|
-
`
|
|
528
|
-
);
|
|
529
446
|
}
|
|
530
447
|
async function cmdInfo() {
|
|
531
448
|
const wallet = await readWalletConfig();
|
|
@@ -538,7 +455,7 @@ async function runCli(argv = process.argv) {
|
|
|
538
455
|
const program = new Command();
|
|
539
456
|
program.name("keeperhub-wallet").description(
|
|
540
457
|
"KeeperHub agentic wallet CLI (auto-pay x402 + MPP 402 responses)"
|
|
541
|
-
).version("0.1.
|
|
458
|
+
).version("0.1.3");
|
|
542
459
|
program.command("add").description("Provision a new agentic wallet (no account required)").option("--base-url <url>", "KeeperHub API base URL").action(async (opts) => {
|
|
543
460
|
await cmdAdd(opts);
|
|
544
461
|
});
|
|
@@ -552,9 +469,7 @@ async function runCli(argv = process.argv) {
|
|
|
552
469
|
).action(async () => {
|
|
553
470
|
await cmdFund();
|
|
554
471
|
});
|
|
555
|
-
program.command("balance").description(
|
|
556
|
-
"Print unified balance: Base USDC + Tempo USDC.e + off-chain KeeperHub credit"
|
|
557
|
-
).action(async () => {
|
|
472
|
+
program.command("balance").description("Print on-chain balance: Base USDC + Tempo USDC.e").action(async () => {
|
|
558
473
|
await cmdBalance();
|
|
559
474
|
});
|
|
560
475
|
program.command("info").description("Print subOrgId and walletAddress from local config").action(async () => {
|
|
@@ -609,6 +524,78 @@ async function runCli(argv = process.argv) {
|
|
|
609
524
|
}
|
|
610
525
|
}
|
|
611
526
|
|
|
527
|
+
// src/client.ts
|
|
528
|
+
var TRAILING_SLASH2 = /\/$/;
|
|
529
|
+
function defaultCodeForStatus(status) {
|
|
530
|
+
if (status === 401) {
|
|
531
|
+
return "HMAC_INVALID";
|
|
532
|
+
}
|
|
533
|
+
if (status === 403) {
|
|
534
|
+
return "POLICY_BLOCKED";
|
|
535
|
+
}
|
|
536
|
+
if (status === 404) {
|
|
537
|
+
return "NOT_FOUND";
|
|
538
|
+
}
|
|
539
|
+
if (status === 502) {
|
|
540
|
+
return "TURNKEY_UPSTREAM";
|
|
541
|
+
}
|
|
542
|
+
return `HTTP_${status}`;
|
|
543
|
+
}
|
|
544
|
+
var KeeperHubClient = class {
|
|
545
|
+
baseUrl;
|
|
546
|
+
fetchImpl;
|
|
547
|
+
wallet;
|
|
548
|
+
constructor(wallet, opts = {}) {
|
|
549
|
+
this.wallet = wallet;
|
|
550
|
+
const envBase = process.env.KEEPERHUB_API_URL;
|
|
551
|
+
this.baseUrl = (opts.baseUrl ?? envBase ?? "https://app.keeperhub.com").replace(TRAILING_SLASH2, "");
|
|
552
|
+
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* HMAC-signed POST/GET to any /api/agentic-wallet/* route except
|
|
556
|
+
* /provision. Path MUST start with a leading slash. Body is
|
|
557
|
+
* JSON.stringify'd (or the empty string for GET).
|
|
558
|
+
*
|
|
559
|
+
* Error mapping: non-2xx/non-202 surface as `KeeperHubError(code,
|
|
560
|
+
* message)` where `code` is the server-supplied field or the default
|
|
561
|
+
* taxonomy (`HMAC_INVALID`, `POLICY_BLOCKED`, `NOT_FOUND`,
|
|
562
|
+
* `TURNKEY_UPSTREAM`, `HTTP_<status>`). 202 ask-tier surfaces as an
|
|
563
|
+
* AskTierResponse envelope.
|
|
564
|
+
*/
|
|
565
|
+
async request(method, path, body) {
|
|
566
|
+
const bodyStr = body === void 0 ? "" : JSON.stringify(body);
|
|
567
|
+
const hmacHeaders = buildHmacHeaders(
|
|
568
|
+
this.wallet.hmacSecret,
|
|
569
|
+
method,
|
|
570
|
+
path,
|
|
571
|
+
this.wallet.subOrgId,
|
|
572
|
+
bodyStr
|
|
573
|
+
);
|
|
574
|
+
const headers = method === "POST" ? { ...hmacHeaders, "content-type": "application/json" } : { ...hmacHeaders };
|
|
575
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
576
|
+
method,
|
|
577
|
+
headers,
|
|
578
|
+
body: method === "POST" ? bodyStr : void 0
|
|
579
|
+
});
|
|
580
|
+
if (response.status === 202) {
|
|
581
|
+
const data = await response.json();
|
|
582
|
+
return { _status: 202, approvalRequestId: data.approvalRequestId };
|
|
583
|
+
}
|
|
584
|
+
if (!response.ok) {
|
|
585
|
+
let code = "UNKNOWN";
|
|
586
|
+
let message = `HTTP ${response.status}`;
|
|
587
|
+
try {
|
|
588
|
+
const data = await response.json();
|
|
589
|
+
code = data.code ?? defaultCodeForStatus(response.status);
|
|
590
|
+
message = data.error ?? message;
|
|
591
|
+
} catch {
|
|
592
|
+
}
|
|
593
|
+
throw new KeeperHubError(code, message);
|
|
594
|
+
}
|
|
595
|
+
return await response.json();
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
612
599
|
// src/safety-config.ts
|
|
613
600
|
import { chmod as chmod3, mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
614
601
|
import { homedir as homedir3 } from "os";
|