@haven_ai/connect 0.1.23-alpha.0 → 0.1.23-alpha.1
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 +93 -10
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.d.cts +8 -1
- package/dist/cli.d.ts +8 -1
- package/dist/cli.js +94 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +92 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -4
- package/dist/index.d.ts +43 -4
- package/dist/index.js +93 -11
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/cli.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
var fs = require('fs');
|
|
4
5
|
var url = require('url');
|
|
6
|
+
var sdk = require('@haven_ai/sdk');
|
|
5
7
|
var crypto = require('crypto');
|
|
6
8
|
var ethers = require('ethers');
|
|
7
9
|
var promises = require('fs/promises');
|
|
@@ -11,7 +13,6 @@ var child_process = require('child_process');
|
|
|
11
13
|
var util = require('util');
|
|
12
14
|
var yaml = require('yaml');
|
|
13
15
|
var mcp = require('@haven_ai/mcp');
|
|
14
|
-
var sdk = require('@haven_ai/sdk');
|
|
15
16
|
var signer = require('@haven_ai/signer');
|
|
16
17
|
|
|
17
18
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
@@ -49,6 +50,10 @@ function createConnectApiClient(baseUrl, fetchImpl = fetch) {
|
|
|
49
50
|
}
|
|
50
51
|
})
|
|
51
52
|
}),
|
|
53
|
+
getConnectorStatus: (setupId, apiKey) => request(fetchImpl, `${root}/agent-connection-setups/${encodeURIComponent(setupId)}/connector-status`, {
|
|
54
|
+
method: "GET",
|
|
55
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
56
|
+
}),
|
|
52
57
|
updateInstallStatus: async (setupId, apiKey, input) => {
|
|
53
58
|
await request(fetchImpl, `${root}/agent-connection-setups/${encodeURIComponent(setupId)}/install-status`, {
|
|
54
59
|
method: "POST",
|
|
@@ -75,6 +80,14 @@ function createConnectApiClient(baseUrl, fetchImpl = fetch) {
|
|
|
75
80
|
}
|
|
76
81
|
};
|
|
77
82
|
}
|
|
83
|
+
var ConnectRequestError = class extends Error {
|
|
84
|
+
constructor(message, status) {
|
|
85
|
+
super(message);
|
|
86
|
+
this.status = status;
|
|
87
|
+
this.name = "ConnectRequestError";
|
|
88
|
+
}
|
|
89
|
+
status;
|
|
90
|
+
};
|
|
78
91
|
async function request(fetchImpl, url, init) {
|
|
79
92
|
const response = await fetchImpl(url, {
|
|
80
93
|
...init,
|
|
@@ -87,7 +100,7 @@ async function request(fetchImpl, url, init) {
|
|
|
87
100
|
const body = text ? JSON.parse(text) : null;
|
|
88
101
|
if (!response.ok) {
|
|
89
102
|
const message = body?.error ?? body?.message ?? `${response.status} ${response.statusText}`;
|
|
90
|
-
throw new
|
|
103
|
+
throw new ConnectRequestError(`Haven setup request failed: ${message}`, response.status);
|
|
91
104
|
}
|
|
92
105
|
return body;
|
|
93
106
|
}
|
|
@@ -240,9 +253,9 @@ var MCP_RUNTIME_MANIFEST = {
|
|
|
240
253
|
mcpPackage: "@haven_ai/mcp",
|
|
241
254
|
mcpVersion: mcp.MCP_VERSION,
|
|
242
255
|
sdkPackage: "@haven_ai/sdk",
|
|
243
|
-
sdkVersion: "0.1.23-alpha.
|
|
256
|
+
sdkVersion: "0.1.23-alpha.1",
|
|
244
257
|
signerPackage: "@haven_ai/signer",
|
|
245
|
-
signerVersion: "0.1.23-alpha.
|
|
258
|
+
signerVersion: "0.1.23-alpha.1",
|
|
246
259
|
// Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
|
|
247
260
|
// while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
|
|
248
261
|
// so the guard that was supposed to enforce the floor waved Node v23 through
|
|
@@ -1941,7 +1954,7 @@ function localRuntimePrepareErrorCode(err) {
|
|
|
1941
1954
|
}
|
|
1942
1955
|
|
|
1943
1956
|
// src/runtime.ts
|
|
1944
|
-
var CONNECTOR_VERSION = "0.1.23-alpha.
|
|
1957
|
+
var CONNECTOR_VERSION = "0.1.23-alpha.1";
|
|
1945
1958
|
var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
|
|
1946
1959
|
async function runConnect(options, deps = {}) {
|
|
1947
1960
|
assertSupportedNodeVersion(deps.nodeVersion, MCP_RUNTIME_MANIFEST.minimumNodeVersion);
|
|
@@ -2055,6 +2068,9 @@ async function runConnect(options, deps = {}) {
|
|
|
2055
2068
|
} else {
|
|
2056
2069
|
log("Haven setup on this machine is complete.");
|
|
2057
2070
|
}
|
|
2071
|
+
if (options.waitForApproval !== false && !runtimeInstall.errorCode) {
|
|
2072
|
+
await waitForBudgetApproval(api, registration.setup_id, localApiKey, log, options.approvalWait);
|
|
2073
|
+
}
|
|
2058
2074
|
printNextSteps(runtimeInstall, log);
|
|
2059
2075
|
try {
|
|
2060
2076
|
await api.updateInstallStatus(registration.setup_id, localApiKey, {
|
|
@@ -2193,6 +2209,61 @@ function printRuntimeInstall(result, log) {
|
|
|
2193
2209
|
log("Local Haven signer still needs runtime setup.");
|
|
2194
2210
|
}
|
|
2195
2211
|
}
|
|
2212
|
+
function formatAtomicAmount(atomic, decimals) {
|
|
2213
|
+
const s = atomic.toString().padStart(decimals + 1, "0");
|
|
2214
|
+
const intPart = s.slice(0, s.length - decimals) || "0";
|
|
2215
|
+
const fracPart = s.slice(s.length - decimals).replace(/0+$/, "");
|
|
2216
|
+
return fracPart ? `${intPart}.${fracPart}` : intPart;
|
|
2217
|
+
}
|
|
2218
|
+
function describeResetPeriod(resetPeriodMin) {
|
|
2219
|
+
if (resetPeriodMin === 1440) return "per day";
|
|
2220
|
+
if (resetPeriodMin === 60) return "per hour";
|
|
2221
|
+
if (resetPeriodMin === 0) return "with no automatic reset";
|
|
2222
|
+
return `per ${resetPeriodMin} minutes`;
|
|
2223
|
+
}
|
|
2224
|
+
function describeApprovedBudget(budget) {
|
|
2225
|
+
const token = sdk.resolveTokenFromAddress(budget.token_address);
|
|
2226
|
+
const amount = token ? `${formatAtomicAmount(BigInt(budget.amount), token.decimals)} ${budget.token_symbol}` : `${budget.amount} ${budget.token_symbol} (atomic units)`;
|
|
2227
|
+
return `${amount} ${describeResetPeriod(budget.reset_period_min)}`;
|
|
2228
|
+
}
|
|
2229
|
+
async function waitForBudgetApproval(api, setupId, apiKey, log, options = {}) {
|
|
2230
|
+
const intervalMs = options.intervalMs ?? 5e3;
|
|
2231
|
+
const timeoutMs = options.timeoutMs ?? 18e4;
|
|
2232
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
2233
|
+
const maxPolls = Math.max(1, Math.floor(timeoutMs / intervalMs));
|
|
2234
|
+
const remindEvery = Math.max(1, Math.floor(3e4 / intervalMs));
|
|
2235
|
+
log("Registered with Haven \u2014 waiting for you to approve the budget in the dashboard\u2026");
|
|
2236
|
+
for (let i = 0; i < maxPolls; i++) {
|
|
2237
|
+
await sleep(intervalMs);
|
|
2238
|
+
let status;
|
|
2239
|
+
try {
|
|
2240
|
+
status = await api.getConnectorStatus(setupId, apiKey);
|
|
2241
|
+
} catch (err) {
|
|
2242
|
+
if (err instanceof ConnectRequestError && (err.status === 401 || err.status === 404)) {
|
|
2243
|
+
log("This setup ended in Haven \u2014 start a fresh connection from the dashboard when ready.");
|
|
2244
|
+
return "ended";
|
|
2245
|
+
}
|
|
2246
|
+
continue;
|
|
2247
|
+
}
|
|
2248
|
+
if (status.status === "active") {
|
|
2249
|
+
log(
|
|
2250
|
+
status.approved_budget ? `Budget approved \u{1F389} \u2014 I can now spend up to ${describeApprovedBudget(status.approved_budget)} from your Haven wallet.` : "Budget approved \u{1F389} \u2014 the agent can now spend within its Haven rules."
|
|
2251
|
+
);
|
|
2252
|
+
return "approved";
|
|
2253
|
+
}
|
|
2254
|
+
if (status.status === "cancelled" || status.status === "expired" || status.status === "failed") {
|
|
2255
|
+
log(`This setup ended in Haven (${status.status}) \u2014 start a fresh connection from the dashboard when ready.`);
|
|
2256
|
+
return "ended";
|
|
2257
|
+
}
|
|
2258
|
+
if ((i + 1) % remindEvery === 0) {
|
|
2259
|
+
log("Still waiting for budget approval in Haven\u2026");
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
log(
|
|
2263
|
+
"Budget approval is still pending in Haven. Approve it in the dashboard whenever you are ready \u2014 the agent tools unlock the moment you do. Verify later with the read-only haven_get_agent tool."
|
|
2264
|
+
);
|
|
2265
|
+
return "pending";
|
|
2266
|
+
}
|
|
2196
2267
|
function completionHandoffLines(result) {
|
|
2197
2268
|
if (result.errorCode === "manual_runtime_setup_required") {
|
|
2198
2269
|
return [
|
|
@@ -2329,11 +2400,14 @@ async function runCli(argv, io = {
|
|
|
2329
2400
|
return 0;
|
|
2330
2401
|
}
|
|
2331
2402
|
try {
|
|
2332
|
-
const result = await runConnect(
|
|
2333
|
-
|
|
2403
|
+
const result = await runConnect(
|
|
2404
|
+
{ ...parsed.options, waitForApproval: !parsed.json },
|
|
2405
|
+
{
|
|
2406
|
+
log: (message) => (parsed.json ? io.stderr : io.stdout)(`${message}
|
|
2334
2407
|
`),
|
|
2335
|
-
|
|
2336
|
-
|
|
2408
|
+
redactPaths: parsed.json
|
|
2409
|
+
}
|
|
2410
|
+
);
|
|
2337
2411
|
if (parsed.json) io.stdout(`${JSON.stringify(result.outcome)}
|
|
2338
2412
|
`);
|
|
2339
2413
|
return 0;
|
|
@@ -2352,8 +2426,17 @@ async function main() {
|
|
|
2352
2426
|
const exitCode = await runCli(process.argv.slice(2));
|
|
2353
2427
|
if (exitCode !== 0) process.exitCode = exitCode;
|
|
2354
2428
|
}
|
|
2355
|
-
|
|
2429
|
+
function isCliEntrypoint(argvPath = process.argv[1], moduleUrl = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href))) {
|
|
2430
|
+
if (!argvPath) return false;
|
|
2431
|
+
try {
|
|
2432
|
+
return fs.realpathSync(argvPath) === fs.realpathSync(url.fileURLToPath(moduleUrl));
|
|
2433
|
+
} catch {
|
|
2434
|
+
return url.pathToFileURL(argvPath).href === moduleUrl;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
if (isCliEntrypoint()) void main();
|
|
2356
2438
|
|
|
2439
|
+
exports.isCliEntrypoint = isCliEntrypoint;
|
|
2357
2440
|
exports.runCli = runCli;
|
|
2358
2441
|
//# sourceMappingURL=cli.cjs.map
|
|
2359
2442
|
//# sourceMappingURL=cli.cjs.map
|