@haven_ai/connect 0.0.0-dev.202609211447.213b411 → 0.0.0-dev.202609231741.b88d644
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 +3 -1
- package/dist/cli.cjs +42 -12
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +42 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +42 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +42 -12
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -159,7 +159,9 @@ minutes. Two rules follow:
|
|
|
159
159
|
This replaces the directory's signer wrapper with a diagnostic that logs the
|
|
160
160
|
retirement (agent id, date, reason, restart guidance) to the host's MCP
|
|
161
161
|
stderr log on every probe, and records it in `TOMBSTONE.json` for
|
|
162
|
-
`--doctor
|
|
162
|
+
`--doctor` — with a copy in `~/.haven/tombstones/` (or `.tombstones/` inside
|
|
163
|
+
a custom credentials root), so the retirement stays visible after the
|
|
164
|
+
directory is deleted. It touches no key material and revokes nothing — revoke the
|
|
163
165
|
agent on the Haven agent page yourself. Delete the tombstone only once every
|
|
164
166
|
long-lived host has been restarted.
|
|
165
167
|
|
package/dist/cli.cjs
CHANGED
|
@@ -619,9 +619,9 @@ var init_runtime_manifest = __esm({
|
|
|
619
619
|
mcpPackage: "@haven_ai/mcp",
|
|
620
620
|
mcpVersion: mcp.MCP_VERSION,
|
|
621
621
|
sdkPackage: "@haven_ai/sdk",
|
|
622
|
-
sdkVersion: "0.0.0-dev.
|
|
622
|
+
sdkVersion: "0.0.0-dev.202609231741.b88d644",
|
|
623
623
|
signerPackage: "@haven_ai/signer",
|
|
624
|
-
signerVersion: "0.0.0-dev.
|
|
624
|
+
signerVersion: "0.0.0-dev.202609231741.b88d644",
|
|
625
625
|
// Sourced from the SDK, never a literal (#1161). This field read '20.0.0'
|
|
626
626
|
// while every package's `engines` said `>=24` and the docs said `>=24.0.0`,
|
|
627
627
|
// so the guard that was supposed to enforce the floor waved Node v23 through
|
|
@@ -1590,7 +1590,7 @@ async function probeLocalSignerCredential(signerPath) {
|
|
|
1590
1590
|
}
|
|
1591
1591
|
}
|
|
1592
1592
|
async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4) {
|
|
1593
|
-
return new Promise((
|
|
1593
|
+
return new Promise((resolve11) => {
|
|
1594
1594
|
const child = child_process.spawn(command, args, { stdio: ["pipe", "pipe", "ignore"] });
|
|
1595
1595
|
let stdout = "";
|
|
1596
1596
|
let settled = false;
|
|
@@ -1602,7 +1602,7 @@ async function probeLocalMcpTools(command, args, requiredTools, timeoutMs = 1e4)
|
|
|
1602
1602
|
settled = true;
|
|
1603
1603
|
clearTimeout(timeout);
|
|
1604
1604
|
child.kill();
|
|
1605
|
-
|
|
1605
|
+
resolve11(result);
|
|
1606
1606
|
};
|
|
1607
1607
|
const timeout = setTimeout(() => finish({ status: "timeout" }), timeoutMs);
|
|
1608
1608
|
child.on("error", () => finish({ status: "process_error" }));
|
|
@@ -3000,16 +3000,28 @@ var init_runtime_install = __esm({
|
|
|
3000
3000
|
// src/tombstone.ts
|
|
3001
3001
|
var tombstone_exports = {};
|
|
3002
3002
|
__export(tombstone_exports, {
|
|
3003
|
+
ROOT_TOMBSTONES_DIRNAME: () => ROOT_TOMBSTONES_DIRNAME,
|
|
3003
3004
|
TOMBSTONE_FILENAME: () => TOMBSTONE_FILENAME,
|
|
3004
3005
|
TOMBSTONE_MARKER: () => TOMBSTONE_MARKER,
|
|
3005
3006
|
defaultTombstonesDir: () => defaultTombstonesDir,
|
|
3006
3007
|
readAgentTombstone: () => readAgentTombstone,
|
|
3007
3008
|
readTombstoneRecords: () => readTombstoneRecords,
|
|
3009
|
+
tombstonesDirForAgentDirectory: () => tombstonesDirForAgentDirectory,
|
|
3010
|
+
tombstonesDirForCredentialRoot: () => tombstonesDirForCredentialRoot,
|
|
3008
3011
|
writeAgentTombstone: () => writeAgentTombstone
|
|
3009
3012
|
});
|
|
3010
3013
|
function defaultTombstonesDir(baseDir) {
|
|
3011
3014
|
return path.join(baseDir ?? path.join(os.homedir(), ".haven"), "tombstones");
|
|
3012
3015
|
}
|
|
3016
|
+
function tombstonesDirForCredentialRoot(credentialRoot, homeDir = os.homedir()) {
|
|
3017
|
+
if (!credentialRoot) return defaultTombstonesDir(path.join(homeDir, ".haven"));
|
|
3018
|
+
const root = path.resolve(credentialRoot);
|
|
3019
|
+
if (root === path.resolve(homeDir, ".haven", "agents")) return defaultTombstonesDir(path.join(homeDir, ".haven"));
|
|
3020
|
+
return path.join(root, ROOT_TOMBSTONES_DIRNAME);
|
|
3021
|
+
}
|
|
3022
|
+
function tombstonesDirForAgentDirectory(directory, homeDir = os.homedir()) {
|
|
3023
|
+
return tombstonesDirForCredentialRoot(path.dirname(path.resolve(directory)), homeDir);
|
|
3024
|
+
}
|
|
3013
3025
|
async function readTombstoneRecords(tombstonesDir) {
|
|
3014
3026
|
const root = tombstonesDir ?? defaultTombstonesDir();
|
|
3015
3027
|
let entries = [];
|
|
@@ -3100,12 +3112,13 @@ async function readAgentTombstone(directory) {
|
|
|
3100
3112
|
return null;
|
|
3101
3113
|
}
|
|
3102
3114
|
}
|
|
3103
|
-
var TOMBSTONE_FILENAME, MIRROR_MODE, TOMBSTONE_MARKER;
|
|
3115
|
+
var TOMBSTONE_FILENAME, ROOT_TOMBSTONES_DIRNAME, MIRROR_MODE, TOMBSTONE_MARKER;
|
|
3104
3116
|
var init_tombstone = __esm({
|
|
3105
3117
|
"src/tombstone.ts"() {
|
|
3106
3118
|
init_redact();
|
|
3107
3119
|
init_connect_error();
|
|
3108
3120
|
TOMBSTONE_FILENAME = "TOMBSTONE.json";
|
|
3121
|
+
ROOT_TOMBSTONES_DIRNAME = ".tombstones";
|
|
3109
3122
|
MIRROR_MODE = 384;
|
|
3110
3123
|
TOMBSTONE_MARKER = "HAVEN-TOMBSTONE";
|
|
3111
3124
|
}
|
|
@@ -4330,7 +4343,8 @@ async function runDoctor(input, deps = {}) {
|
|
|
4330
4343
|
if (retired.length > 0) parts.push(`tombstoned (keys removed): ${retired.join(", ")}`);
|
|
4331
4344
|
if (unverifiable.length > 0) parts.push(`could not verify: ${unverifiable.join(", ")}`);
|
|
4332
4345
|
const knownIds = new Set([...inventory].map((e) => e.agentId ?? path.basename(e.directory)));
|
|
4333
|
-
const
|
|
4346
|
+
const ledgerDir = input.credentialsDir ? tombstonesDirForAgentDirectory(input.credentialsDir, homeDir) : path.join(homeDir, ".haven", "tombstones");
|
|
4347
|
+
const ghostRecords = (await readTombstoneRecords(ledgerDir)).filter(
|
|
4334
4348
|
(rec) => !knownIds.has(rec.agent_id)
|
|
4335
4349
|
);
|
|
4336
4350
|
if (ghostRecords.length > 0) {
|
|
@@ -4828,9 +4842,10 @@ async function pathExists2(path) {
|
|
|
4828
4842
|
|
|
4829
4843
|
// src/runtime.ts
|
|
4830
4844
|
init_unwire();
|
|
4845
|
+
init_tombstone();
|
|
4831
4846
|
init_local_mcp_runtime();
|
|
4832
4847
|
init_runtime_manifest();
|
|
4833
|
-
var CONNECTOR_VERSION = "0.0.0-dev.
|
|
4848
|
+
var CONNECTOR_VERSION = "0.0.0-dev.202609231741.b88d644";
|
|
4834
4849
|
var CONNECT_OUTCOME_SCHEMA_VERSION = 1;
|
|
4835
4850
|
var failureOutcomesByError = /* @__PURE__ */ new WeakMap();
|
|
4836
4851
|
function failureOutcomeFor(runtimeHint, error) {
|
|
@@ -5132,7 +5147,10 @@ async function executeConnect(options, deps, trace) {
|
|
|
5132
5147
|
directory: entry.directory,
|
|
5133
5148
|
agentId: entry.agentId,
|
|
5134
5149
|
reason: "replaced by a new setup (--replace)",
|
|
5135
|
-
replacedBy: registration.agent_id
|
|
5150
|
+
replacedBy: registration.agent_id,
|
|
5151
|
+
// #3251: the ledger follows this run's credential root (default
|
|
5152
|
+
// root → ~/.haven/tombstones, as before; any other → <root>/.tombstones).
|
|
5153
|
+
tombstonesDir: tombstonesDirForCredentialRoot(options.credentialsDir)
|
|
5136
5154
|
});
|
|
5137
5155
|
await teardownLocalKeyMaterial(entry.directory, await readIdentityFile(entry.directory));
|
|
5138
5156
|
await clearMcpServerBinding(entry.directory);
|
|
@@ -5459,7 +5477,7 @@ function describeWaitBound(timeoutMs) {
|
|
|
5459
5477
|
async function waitForBudgetApproval(api, setupId, apiKey, log, options = {}) {
|
|
5460
5478
|
const intervalMs = options.intervalMs ?? 5e3;
|
|
5461
5479
|
const timeoutMs = options.timeoutMs ?? 18e4;
|
|
5462
|
-
const sleep = options.sleep ?? ((ms) => new Promise((
|
|
5480
|
+
const sleep = options.sleep ?? ((ms) => new Promise((resolve11) => setTimeout(resolve11, ms)));
|
|
5463
5481
|
const maxPolls = Math.max(1, Math.floor(timeoutMs / intervalMs));
|
|
5464
5482
|
const remindEvery = Math.max(1, Math.floor(3e4 / intervalMs));
|
|
5465
5483
|
let waitingAnnounced = false;
|
|
@@ -5932,7 +5950,7 @@ async function runCli(argv, io = {
|
|
|
5932
5950
|
return 0;
|
|
5933
5951
|
}
|
|
5934
5952
|
if (parsed.tombstone) {
|
|
5935
|
-
const { writeAgentTombstone: writeAgentTombstone2 } = await Promise.resolve().then(() => (init_tombstone(), tombstone_exports));
|
|
5953
|
+
const { writeAgentTombstone: writeAgentTombstone2, tombstonesDirForAgentDirectory: tombstonesDirForAgentDirectory2 } = await Promise.resolve().then(() => (init_tombstone(), tombstone_exports));
|
|
5936
5954
|
const { readFile: readFile15 } = await import('fs/promises');
|
|
5937
5955
|
const { join: join13 } = await import('path');
|
|
5938
5956
|
try {
|
|
@@ -5948,7 +5966,11 @@ async function runCli(argv, io = {
|
|
|
5948
5966
|
directory: parsed.tombstone.directory,
|
|
5949
5967
|
agentId,
|
|
5950
5968
|
reason: parsed.tombstone.reason ?? "retired by operator via --tombstone",
|
|
5951
|
-
replacedBy: parsed.tombstone.replacedBy
|
|
5969
|
+
replacedBy: parsed.tombstone.replacedBy,
|
|
5970
|
+
// #3251: the ledger of the root that holds the retired directory —
|
|
5971
|
+
// ~/.haven/agents/<x> → ~/.haven/tombstones, exactly as before; a
|
|
5972
|
+
// directory under any other root → <root>/.tombstones.
|
|
5973
|
+
tombstonesDir: tombstonesDirForAgentDirectory2(parsed.tombstone.directory)
|
|
5952
5974
|
});
|
|
5953
5975
|
if (parsed.json) {
|
|
5954
5976
|
io.stdout(`${redactSecrets(JSON.stringify({ tombstoned: true, ...info }))}
|
|
@@ -5977,6 +5999,7 @@ async function runCli(argv, io = {
|
|
|
5977
5999
|
}
|
|
5978
6000
|
if (parsed.unwire) {
|
|
5979
6001
|
const { unwireAgent: unwireAgent2 } = await Promise.resolve().then(() => (init_unwire(), unwire_exports));
|
|
6002
|
+
const { tombstonesDirForAgentDirectory: tombstonesDirForAgentDirectory2 } = await Promise.resolve().then(() => (init_tombstone(), tombstone_exports));
|
|
5980
6003
|
const { homedir: homedir11 } = await import('os');
|
|
5981
6004
|
const { join: join13 } = await import('path');
|
|
5982
6005
|
const homeDir = homedir11();
|
|
@@ -5989,7 +6012,14 @@ async function runCli(argv, io = {
|
|
|
5989
6012
|
reason: parsed.unwire.reason,
|
|
5990
6013
|
replacedBy: parsed.unwire.replacedBy,
|
|
5991
6014
|
destroyKeyMaterial: parsed.unwire.destroyKeyMaterial,
|
|
5992
|
-
homeDir
|
|
6015
|
+
homeDir,
|
|
6016
|
+
// #3251: the ledger of the root that holds the directory being
|
|
6017
|
+
// retired. Derived from the RESOLVED directory, not from
|
|
6018
|
+
// --credentials-dir: `--unwire --credentials-dir <path>` names the agent
|
|
6019
|
+
// directory itself, not a root. ~/.haven/agents/<slug> →
|
|
6020
|
+
// ~/.haven/tombstones, exactly as before; any other root →
|
|
6021
|
+
// <root>/.tombstones.
|
|
6022
|
+
tombstonesDir: tombstonesDirForAgentDirectory2(directory, homeDir)
|
|
5993
6023
|
});
|
|
5994
6024
|
const failures = result.runtimes.filter((r) => r.status === "refused" || r.status === "unreadable");
|
|
5995
6025
|
const retained = result.teardown.status === "retained";
|