@haven_ai/connect 0.1.23-alpha.2 → 0.1.24-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/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { realpathSync } from 'fs';
3
3
  import { fileURLToPath, pathToFileURL } from 'url';
4
- import { HAVEN_MINIMUM_NODE_VERSION, isSupportedNodeVersion, unsupportedNodeVersionMessage, SKILL_FOLDER_NAME, HAVEN_SKILL_MD, resolveTokenFromAddress } from '@haven_ai/sdk';
4
+ import { HAVEN_MINIMUM_NODE_VERSION, isSupportedNodeVersion, unsupportedNodeVersionMessage, SKILL_FOLDER_NAME, resolveTokenFromAddress, HAVEN_SKILL_MD, HAVEN_SKILL_BODY_MD } from '@haven_ai/sdk';
5
5
  import crypto from 'crypto';
6
6
  import { Wallet } from 'ethers';
7
7
  import { mkdir, rm, chmod, access, writeFile, readFile, unlink } from 'fs/promises';
@@ -246,9 +246,9 @@ var MCP_RUNTIME_MANIFEST = {
246
246
  mcpPackage: "@haven_ai/mcp",
247
247
  mcpVersion: MCP_VERSION,
248
248
  sdkPackage: "@haven_ai/sdk",
249
- sdkVersion: "0.1.23-alpha.2",
249
+ sdkVersion: "0.1.24-alpha.0",
250
250
  signerPackage: "@haven_ai/signer",
251
- signerVersion: "0.1.23-alpha.2",
251
+ signerVersion: "0.1.24-alpha.0",
252
252
  // Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
253
253
  // while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
254
254
  // so the guard that was supposed to enforce the floor waved Node v23 through
@@ -1403,6 +1403,109 @@ async function assertFileExists2(path, label) {
1403
1403
  throw new Error(`Missing ${label}: ${path}`);
1404
1404
  }
1405
1405
  }
1406
+ var CODEX_AGENTS_BEGIN_MARKER = "<!-- BEGIN haven-pay (managed by @haven_ai/connect; edits inside this section are overwritten on re-setup) -->";
1407
+ var CODEX_AGENTS_END_MARKER = "<!-- END haven-pay -->";
1408
+ async function installSkillForRuntime(runtime, deps = {}) {
1409
+ switch (runtime) {
1410
+ case "claude-code":
1411
+ return installSkillFile(
1412
+ resolve(deps.homeDir ?? homedir(), ".claude", "skills", SKILL_FOLDER_NAME),
1413
+ "~/.claude/skills/haven-pay"
1414
+ );
1415
+ case "hermes":
1416
+ return installSkillFile(
1417
+ join(hermesHome(deps), "skills", SKILL_FOLDER_NAME),
1418
+ "the Hermes skills folder"
1419
+ );
1420
+ case "codex-cli":
1421
+ case "codex-desktop":
1422
+ return installCodexAgentsSection(deps);
1423
+ default:
1424
+ return void 0;
1425
+ }
1426
+ }
1427
+ async function installSkillFile(skillDir, label) {
1428
+ try {
1429
+ await mkdir(skillDir, { recursive: true });
1430
+ const target = join(skillDir, "SKILL.md");
1431
+ await writeFile(target, HAVEN_SKILL_MD, "utf8");
1432
+ return {
1433
+ installed: true,
1434
+ target,
1435
+ messages: [`Installed the generic Haven payment skill (${label}). It contains no secrets.`]
1436
+ };
1437
+ } catch (err) {
1438
+ return {
1439
+ installed: false,
1440
+ messages: [
1441
+ `Could not install the Haven payment skill: ${err instanceof Error ? err.message : String(err)}. Download it from the Haven dashboard instead.`
1442
+ ]
1443
+ };
1444
+ }
1445
+ }
1446
+ async function installCodexAgentsSection(deps) {
1447
+ try {
1448
+ const codexDir = resolve(deps.homeDir ?? homedir(), ".codex");
1449
+ const target = join(codexDir, "AGENTS.md");
1450
+ await mkdir(codexDir, { recursive: true });
1451
+ const existing = await readFile(target, "utf8").catch(() => null);
1452
+ const next = upsertManagedSection(existing, codexManagedSection());
1453
+ if (next !== existing) {
1454
+ await writeFile(target, next, "utf8");
1455
+ }
1456
+ return {
1457
+ installed: true,
1458
+ target,
1459
+ messages: [
1460
+ "Installed the generic Haven payment guidance as a managed section in ~/.codex/AGENTS.md (Codex reads it as global instructions). It contains no secrets; your own content in that file is untouched."
1461
+ ]
1462
+ };
1463
+ } catch (err) {
1464
+ return {
1465
+ installed: false,
1466
+ messages: [
1467
+ `Could not install the Haven payment guidance into ~/.codex/AGENTS.md: ${err instanceof Error ? err.message : String(err)}. Download the skill from the Haven dashboard instead.`
1468
+ ]
1469
+ };
1470
+ }
1471
+ }
1472
+ function codexManagedSection() {
1473
+ return `${CODEX_AGENTS_BEGIN_MARKER}
1474
+
1475
+ ${HAVEN_SKILL_BODY_MD.trimEnd()}
1476
+
1477
+ ${CODEX_AGENTS_END_MARKER}
1478
+ `;
1479
+ }
1480
+ function upsertManagedSection(existing, section) {
1481
+ if (existing === null || existing.trim() === "") return section;
1482
+ const begins = markerLineIndexes(existing, CODEX_AGENTS_BEGIN_MARKER);
1483
+ const ends = markerLineIndexes(existing, CODEX_AGENTS_END_MARKER);
1484
+ if (begins.length === 1 && ends.length === 1 && ends[0] > begins[0]) {
1485
+ const afterEnd = ends[0] + CODEX_AGENTS_END_MARKER.length;
1486
+ const tail = existing.startsWith("\r\n", afterEnd) ? existing.slice(afterEnd + 2) : existing.startsWith("\n", afterEnd) ? existing.slice(afterEnd + 1) : existing.slice(afterEnd);
1487
+ return existing.slice(0, begins[0]) + section + tail;
1488
+ }
1489
+ if (begins.length > 0 || ends.length > 0) {
1490
+ throw new Error(
1491
+ "found a damaged Haven marker section (orphaned or duplicated markers); remove the leftover marker lines and re-run setup"
1492
+ );
1493
+ }
1494
+ return `${existing.replace(/\n*$/, "\n\n")}${section}`;
1495
+ }
1496
+ function markerLineIndexes(text, marker) {
1497
+ const indexes = [];
1498
+ for (let from = 0; ; ) {
1499
+ const at = text.indexOf(marker, from);
1500
+ if (at === -1) return indexes;
1501
+ if (at === 0 || text[at - 1] === "\n") indexes.push(at);
1502
+ from = at + marker.length;
1503
+ }
1504
+ }
1505
+ function hermesHome(deps) {
1506
+ const env = deps.env ?? process.env;
1507
+ return env.HERMES_HOME ?? join(deps.homeDir ?? homedir(), ".hermes");
1508
+ }
1406
1509
 
1407
1510
  // src/runtime-registry.ts
1408
1511
  var RUNTIME_PROFILES = {
@@ -1714,7 +1817,7 @@ async function installRuntime(input, deps = {}) {
1714
1817
  const errorCode = configResult.errorCode ?? (configResult.runtimeMcpMode === "local_stdio" ? localMcpErrorCode(signerCredentialReady, localMcpConsent, localMcpProbe?.status) : hostedMcpErrorCode(configResult.hostedConfigured, hostedProbe.status) ?? signerConsentErrorCode(signerCredentialReady, signerConsent));
1715
1818
  const hostedProbeMessages = configResult.hostedConfigured && hostedProbe.status !== "ok" ? [`Hosted Haven MCP probe failed: ${hostedProbe.status}.`] : configResult.hostedConfigured ? ["Verified hosted Haven MCP tools with a read-only handshake."] : [];
1716
1819
  const localProbeMessages = localMcpProbe && localMcpProbe.status !== "ok" ? [`Local Haven MCP handshake failed: ${localMcpProbe.status}.`] : localMcpProbe?.status === "ok" ? ["Verified local Haven MCP tools with a stdio handshake."] : [];
1717
- const skillInstall = runtime === "claude-code" && !configResult.errorCode ? await installClaudeSkill(deps.homeDir) : void 0;
1820
+ const skillInstall = !configResult.errorCode ? await installSkillForRuntime(runtime, { homeDir: deps.homeDir, env: deps.env }) : void 0;
1718
1821
  return {
1719
1822
  runtime,
1720
1823
  runtimeMcpMode: configResult.runtimeMcpMode,
@@ -1838,22 +1941,6 @@ async function configureClaudeCodeHosted(deps, input, signerCommand) {
1838
1941
  async function defaultRunCommand(command, args) {
1839
1942
  await execFileAsync3(command, args, { timeout: 1e4 });
1840
1943
  }
1841
- async function installClaudeSkill(homeDir) {
1842
- try {
1843
- const skillDir = resolve(homeDir ?? homedir(), ".claude", "skills", SKILL_FOLDER_NAME);
1844
- await mkdir(skillDir, { recursive: true });
1845
- await writeFile(join(skillDir, "SKILL.md"), HAVEN_SKILL_MD, "utf8");
1846
- return {
1847
- installed: true,
1848
- messages: ["Installed the generic Haven payment skill (~/.claude/skills/haven-pay). It contains no secrets."]
1849
- };
1850
- } catch (err) {
1851
- return {
1852
- installed: false,
1853
- messages: [`Could not install the Haven payment skill: ${err instanceof Error ? err.message : String(err)}. Download it from the Haven dashboard instead.`]
1854
- };
1855
- }
1856
- }
1857
1944
  function buildProbeResult(mode, hostedConfigured, hostedStatus, signerReady, localMcpReady, localMcpProbeStatus) {
1858
1945
  if (mode === "local_stdio") {
1859
1946
  if (localMcpReady) return "local_stdio_mcp_ready";
@@ -1947,7 +2034,7 @@ function localRuntimePrepareErrorCode(err) {
1947
2034
  }
1948
2035
 
1949
2036
  // src/runtime.ts
1950
- var CONNECTOR_VERSION = "0.1.23-alpha.2";
2037
+ var CONNECTOR_VERSION = "0.1.24-alpha.0";
1951
2038
  var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
1952
2039
  async function runConnect(options, deps = {}) {
1953
2040
  assertSupportedNodeVersion(deps.nodeVersion, MCP_RUNTIME_MANIFEST.minimumNodeVersion);
@@ -2210,9 +2297,11 @@ function formatAtomicAmount(atomic, decimals) {
2210
2297
  }
2211
2298
  function describeResetPeriod(resetPeriodMin) {
2212
2299
  if (resetPeriodMin === 1440) return "per day";
2300
+ if (resetPeriodMin === 10080) return "per week";
2301
+ if (resetPeriodMin === 43200) return "per month";
2213
2302
  if (resetPeriodMin === 60) return "per hour";
2214
- if (resetPeriodMin === 0) return "with no automatic reset";
2215
- return `per ${resetPeriodMin} minutes`;
2303
+ if (resetPeriodMin === 0) return "in total";
2304
+ return `every ${resetPeriodMin} minutes`;
2216
2305
  }
2217
2306
  function describeApprovedBudget(budget) {
2218
2307
  const token = resolveTokenFromAddress(budget.token_address);