@sentropic/h2a-runtime 0.94.3 → 0.96.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/central-mcp.d.ts +28 -0
- package/dist/central-mcp.d.ts.map +1 -0
- package/dist/central-mcp.js +204 -0
- package/dist/central-mcp.js.map +1 -0
- package/dist/cli-help-groups.d.ts.map +1 -1
- package/dist/cli-help-groups.js +1 -0
- package/dist/cli-help-groups.js.map +1 -1
- package/dist/config.d.ts +12 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +195 -1
- package/dist/index.js.map +1 -1
- package/dist/native-host.d.ts +16 -0
- package/dist/native-host.d.ts.map +1 -1
- package/dist/native-host.js +41 -0
- package/dist/native-host.js.map +1 -1
- package/dist/native-restart.d.ts +74 -0
- package/dist/native-restart.d.ts.map +1 -0
- package/dist/native-restart.js +182 -0
- package/dist/native-restart.js.map +1 -0
- package/dist/native-terminal/client.d.ts +4 -2
- package/dist/native-terminal/client.d.ts.map +1 -1
- package/dist/native-terminal/client.js +10 -2
- package/dist/native-terminal/client.js.map +1 -1
- package/dist/native-terminal/host.d.ts +41 -19
- package/dist/native-terminal/host.d.ts.map +1 -1
- package/dist/native-terminal/host.js +102 -6
- package/dist/native-terminal/host.js.map +1 -1
- package/dist/native-terminal/op.d.ts.map +1 -1
- package/dist/native-terminal/op.js +128 -1
- package/dist/native-terminal/op.js.map +1 -1
- package/dist/native-terminal/protocol.d.ts +1 -1
- package/dist/native-terminal/protocol.d.ts.map +1 -1
- package/dist/native-terminal/protocol.js +2 -0
- package/dist/native-terminal/protocol.js.map +1 -1
- package/dist/native-terminal/server.d.ts.map +1 -1
- package/dist/native-terminal/server.js +30 -1
- package/dist/native-terminal/server.js.map +1 -1
- package/dist/native-terminal/socket-path.d.ts +6 -0
- package/dist/native-terminal/socket-path.d.ts.map +1 -1
- package/dist/native-terminal/socket-path.js +5 -1
- package/dist/native-terminal/socket-path.js.map +1 -1
- package/dist/native-terminal/supervisor.d.ts.map +1 -1
- package/dist/native-terminal/supervisor.js +71 -7
- package/dist/native-terminal/supervisor.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { Command, Help } from "commander";
|
|
|
9
9
|
import { applyRuntimeHelpGroups, groupRuntimeHelpItems, } from "./cli-help-groups.js";
|
|
10
10
|
import { attach, createRemoteSession, getRemoteSession, listRemoteSessions, refreshRemoteSession, renameRemoteSession, sessionTerminalHealth, stopRemoteSession, } from "./attach.js";
|
|
11
11
|
import { authHeaders, clearDefaultRemote, getDefaultRemote, getDefaultTarget, getDefaultTools, getH2aConfig, getJobMaxAgeHours, getMaxConcurrent, getLlmMeshRuntimeConfig, getTmuxProfileConfig, getTunnel, resolveConfigPath, setDefaultRemote, setDefaultTarget, migrateConfigHomeIfNeeded, setDefaultTools, setLlmMeshRuntimeConfig, setTmuxProfileConfig, setToken, setTunnel, } from "./config.js";
|
|
12
|
+
import { prepareCentralMcpForLaunch, prepareCentralMcpForRestore, } from "./central-mcp.js";
|
|
12
13
|
import { ensureConnected, stopTunnel } from "./tunnel.js";
|
|
13
14
|
import { detectToolAuth, KNOWN_TOOLS, partitionTools } from "./auth-tools.js";
|
|
14
15
|
import { transmittedSecrets, secretsSummary } from "./secrets.js";
|
|
@@ -18,7 +19,8 @@ import { syncConversation } from "./sync.js";
|
|
|
18
19
|
import { attachLocalSession, attachPodTmux, capturePane, capturePaneVisible, clearPaneComposer, conductorRunning, currentTmuxSessionName, currentTmuxSessionIs, ensureManagedTmuxProfile, ensureHeadlessTerminal, existingLocalSessionSlugs, fanoutLabels, findLocalSession, killLocalSession, localSessionGatewayEnvStatus, listLocalSessions, listH2aStatusSurfaces, listLocalSessionsWithDiagnostics, localSessionIdle, localSessionPanePid, localSessionName, paneProcessObservation, paneTreeCpuMs, paneWorkerAttribution, paneWorkerAttributionFromView, paneWorkerPid, pasteLiteralBlock, submitPane, installH2aStatusSurface, managedSessionCandidates, parseManagedSessionName, openH2aStatusWindow, persistLaunchContext, readLaunchContext, readFleetProcView, relaunchInSession, resolveAgentPane, resolveAgentPaneForInstance, resolveLocalSession, sessionRelaunchSafety, runLocalCliForeground, sendKeysLiteral, sessionAttached, sessionAttachedCount, setLocalSessionDisplayName, slugify, cleanupHeadlessPromptFile, startH2aWindow, startH2aWindowVerified, startHeadlessSession, startLocalSession, tmuxAvailable, uninstallH2aStatusSurface, } from "./tmux.js";
|
|
19
20
|
import { deliverInitialPrompt, sleepSync, } from "./prompt-delivery.js";
|
|
20
21
|
import { buildLaunchContext } from "./launch-context.js";
|
|
21
|
-
import { attachNativeSession, killNativeSessionTree, nativeHostAvailable, nativePromptDeliveryDeps, nativeSessionLiveness, nativeSessionPid, nativeTreeCpuMs, nativeWorkerPid, resolveSessionHostKind, startNativeH2aSidecar, startNativeHeadlessSession, startNativeSession, } from "./native-host.js";
|
|
22
|
+
import { attachNativeSession, driveNativeInstruction, killNativeSessionIfIncarnation, killNativeSessionTree, nativeHostAvailable, nativePromptDeliveryDeps, nativeSessionLiveness, nativeSessionPid, nativeSessionState, nativeTreeCpuMs, nativeWorkerPid, resolveSessionHostKind, startNativeH2aSidecar, startNativeHeadlessSession, startNativeSession, } from "./native-host.js";
|
|
23
|
+
import { executeNativeRestart, NativeRestartError, } from "./native-restart.js";
|
|
22
24
|
import { migrateTmuxNames } from "./tmux-name-migration.js";
|
|
23
25
|
import { projectStatusForH2a } from "./status-projection.js";
|
|
24
26
|
import { buildAgentLaunchArgs, isAgentLaunchEffort, isAgentLaunchProfile, } from "./agent-launch-args.js";
|
|
@@ -74,6 +76,7 @@ const KNOWN_PROFILE_HELP = `${CLI_PROFILES.join(", ")} (aliases: claude-code, an
|
|
|
74
76
|
export const packageName = "@sentropic/h2a-runtime";
|
|
75
77
|
export const H2A_RUNTIME_CLI_API_VERSION = 1;
|
|
76
78
|
export { run } from "./run.js";
|
|
79
|
+
export { executeNativeRestart, nativeMcpRelaunchInstruction, NativeRestartError, } from "./native-restart.js";
|
|
77
80
|
export { AGENT_LAUNCH_EFFORTS, AGENT_LAUNCH_PROFILES, AGENT_LAUNCH_PROMPT_MAX_BYTES, assertAgentLaunchModel, assertAgentLaunchPrompt, buildAgentLaunchArgs, isAgentLaunchEffort, isAgentLaunchProfile, } from "./agent-launch-args.js";
|
|
78
81
|
export { attach, createRemoteSession, getRemoteSession, listRemoteSessions, refreshRemoteSession, renameRemoteSession, stopRemoteSession, } from "./attach.js";
|
|
79
82
|
export { inspectProfileAuth } from "./auth-diagnostics.js";
|
|
@@ -1401,6 +1404,64 @@ async function injectLlmMeshGatewayEnv(mode = "auto", allowDirectFallback = true
|
|
|
1401
1404
|
}
|
|
1402
1405
|
return meshEnv.ANTHROPIC_BASE_URL;
|
|
1403
1406
|
}
|
|
1407
|
+
function captureAnthropicGatewayEnvironment() {
|
|
1408
|
+
return {
|
|
1409
|
+
...(process.env.ANTHROPIC_BASE_URL !== undefined
|
|
1410
|
+
? { ANTHROPIC_BASE_URL: process.env.ANTHROPIC_BASE_URL }
|
|
1411
|
+
: {}),
|
|
1412
|
+
...(process.env.ANTHROPIC_AUTH_TOKEN !== undefined
|
|
1413
|
+
? { ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN }
|
|
1414
|
+
: {}),
|
|
1415
|
+
...(process.env.ANTHROPIC_API_KEY !== undefined
|
|
1416
|
+
? { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY }
|
|
1417
|
+
: {}),
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
async function prepareNativeRestart(session, mode) {
|
|
1421
|
+
if (mode === "gateway" && !profileUsesLlmMeshGateway(session.profile)) {
|
|
1422
|
+
throw new Error("gateway is unsupported for this profile");
|
|
1423
|
+
}
|
|
1424
|
+
const original = captureAnthropicGatewayEnvironment();
|
|
1425
|
+
const restore = replaceAnthropicGatewayEnvironment(process.env, original);
|
|
1426
|
+
try {
|
|
1427
|
+
const effectiveMode = gatewayModeForProfile(session.profile, mode);
|
|
1428
|
+
await injectLlmMeshGatewayEnv(effectiveMode, effectiveMode !== "gateway", session.name);
|
|
1429
|
+
const useBare = shouldUseClaudeBare(session.profile);
|
|
1430
|
+
return {
|
|
1431
|
+
command: localCliCommand(session.profile),
|
|
1432
|
+
args: session.convId
|
|
1433
|
+
? localResumeArgs(session.profile, session.convId, { bare: useBare })
|
|
1434
|
+
: localStartArgs(session.profile, { bare: useBare }),
|
|
1435
|
+
gatewayEnvironment: captureAnthropicGatewayEnvironment(),
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
finally {
|
|
1439
|
+
restore();
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
function renderNativeRestartResult(result, json) {
|
|
1443
|
+
if (json) {
|
|
1444
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
for (const row of result.sessions) {
|
|
1448
|
+
if (row.state === "completed") {
|
|
1449
|
+
if (row.restarted) {
|
|
1450
|
+
process.stderr.write(`[h2a] restarted native CLI ${row.id} (gateway=${row.gatewayMode})\n`);
|
|
1451
|
+
}
|
|
1452
|
+
if (row.instructionSubmitted) {
|
|
1453
|
+
process.stderr.write(`[h2a] submitted MCP relaunch/attach instruction to ${row.id}; MCP health is not yet proven\n`);
|
|
1454
|
+
}
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (row.state === "failed") {
|
|
1458
|
+
process.stderr.write(`[h2a] restart failed for ${row.id} (${row.failure ?? "unknown"})\n`);
|
|
1459
|
+
}
|
|
1460
|
+
else {
|
|
1461
|
+
process.stderr.write(`[h2a] restart did not touch ${row.id} because an earlier session failed\n`);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1404
1465
|
export async function prepareStructuredGateway(mode, inject = (selectedMode) => injectLlmMeshGatewayEnv(selectedMode, selectedMode !== "gateway")) {
|
|
1405
1466
|
const gateway = await inject(mode);
|
|
1406
1467
|
if (mode === "gateway" && !gateway) {
|
|
@@ -4062,6 +4123,14 @@ export async function main(argv) {
|
|
|
4062
4123
|
process.exitCode = 2;
|
|
4063
4124
|
return;
|
|
4064
4125
|
}
|
|
4126
|
+
try {
|
|
4127
|
+
await prepareCentralMcpForLaunch({ root: cwd, profile, cwd });
|
|
4128
|
+
}
|
|
4129
|
+
catch (error) {
|
|
4130
|
+
process.stderr.write(`[h2a] ${error.message}\n`);
|
|
4131
|
+
process.exitCode = 1;
|
|
4132
|
+
return;
|
|
4133
|
+
}
|
|
4065
4134
|
const started = [];
|
|
4066
4135
|
for (const label of labels) {
|
|
4067
4136
|
const clientSessionId = localSessionName(slugify(label ?? cwd));
|
|
@@ -5773,6 +5842,121 @@ export async function main(argv) {
|
|
|
5773
5842
|
process.stderr.write("[h2a] wake-request watch stopped\n");
|
|
5774
5843
|
});
|
|
5775
5844
|
// ---------------------------------------------------------------------------
|
|
5845
|
+
// restart — explicit native CLI recreation or guarded live MCP instruction
|
|
5846
|
+
// ---------------------------------------------------------------------------
|
|
5847
|
+
program
|
|
5848
|
+
.command("restart [session]")
|
|
5849
|
+
.description("Restart one live managed native-PTY CLI, or every live managed native CLI with --all. --gw requires the explicit value on|off. With --relaunch-mcp alone, keep the CLI alive and submit one guarded MCP relaunch/attach instruction through the native drive backchannel.")
|
|
5850
|
+
.option("--all", "target every live managed native CLI session")
|
|
5851
|
+
.option("--gw <on|off>", "restart with llm-mesh gateway explicitly on or off")
|
|
5852
|
+
.option("--relaunch-mcp <name>", "submit a bounded instruction to relaunch or attach this MCP server; submission does not prove MCP health")
|
|
5853
|
+
.option("--json", "emit a versioned, credential-free result")
|
|
5854
|
+
.action(async (session, opts) => {
|
|
5855
|
+
try {
|
|
5856
|
+
const registry = loadRegistry();
|
|
5857
|
+
if (registry.state === "unknown") {
|
|
5858
|
+
throw new NativeRestartError("registry-unreadable", `local registry is unreadable (${registry.reason})`);
|
|
5859
|
+
}
|
|
5860
|
+
const candidates = registry.entries.map((entry) => ({
|
|
5861
|
+
id: entry.id,
|
|
5862
|
+
...(entry.label !== undefined ? { label: entry.label } : {}),
|
|
5863
|
+
name: entry.tmuxSession ?? localSessionName(entry.id),
|
|
5864
|
+
kind: entry.kind,
|
|
5865
|
+
...(entry.role !== undefined ? { role: entry.role } : {}),
|
|
5866
|
+
...(entry.endedAt !== undefined ? { endedAt: entry.endedAt } : {}),
|
|
5867
|
+
profile: entry.tool,
|
|
5868
|
+
cwd: entry.cwd,
|
|
5869
|
+
...(entry.convId !== undefined ? { convId: entry.convId } : {}),
|
|
5870
|
+
...(entry.sessionClass !== undefined
|
|
5871
|
+
? { sessionClass: entry.sessionClass }
|
|
5872
|
+
: {}),
|
|
5873
|
+
...(entry.gatewayMode !== undefined
|
|
5874
|
+
? { gatewayMode: entry.gatewayMode }
|
|
5875
|
+
: {}),
|
|
5876
|
+
}));
|
|
5877
|
+
const result = await executeNativeRestart({
|
|
5878
|
+
...(session !== undefined ? { target: session } : {}),
|
|
5879
|
+
...(opts.all === true ? { all: true } : {}),
|
|
5880
|
+
...(opts.gw !== undefined
|
|
5881
|
+
? { gateway: opts.gw }
|
|
5882
|
+
: {}),
|
|
5883
|
+
...(opts.relaunchMcp !== undefined
|
|
5884
|
+
? { relaunchMcp: opts.relaunchMcp }
|
|
5885
|
+
: {}),
|
|
5886
|
+
}, {
|
|
5887
|
+
listSessions: () => candidates,
|
|
5888
|
+
snapshot: (candidate) => {
|
|
5889
|
+
const probe = nativeSessionState(candidate.name);
|
|
5890
|
+
if (probe.state === "unknown")
|
|
5891
|
+
return { state: "unknown" };
|
|
5892
|
+
if (probe.state === "absent" ||
|
|
5893
|
+
probe.session.status !== "running") {
|
|
5894
|
+
return { state: "dead" };
|
|
5895
|
+
}
|
|
5896
|
+
return {
|
|
5897
|
+
state: "live",
|
|
5898
|
+
generation: probe.session.generation,
|
|
5899
|
+
incarnation: probe.session.incarnation,
|
|
5900
|
+
controlled: probe.session.controlled ?? true,
|
|
5901
|
+
};
|
|
5902
|
+
},
|
|
5903
|
+
prepare: (candidate, _snapshot, mode) => prepareNativeRestart(candidate, mode),
|
|
5904
|
+
restart: (candidate, snapshot, mode, prepared) => {
|
|
5905
|
+
if (!killNativeSessionIfIncarnation(candidate.name, snapshot.generation, snapshot.incarnation)) {
|
|
5906
|
+
throw new Error("fenced native stop failed");
|
|
5907
|
+
}
|
|
5908
|
+
const restore = replaceAnthropicGatewayEnvironment(process.env, prepared.gatewayEnvironment);
|
|
5909
|
+
try {
|
|
5910
|
+
const relaunched = startNativeSession(candidate.profile, prepared.command, candidate.cwd, prepared.args, candidate.id, {
|
|
5911
|
+
...(candidate.convId !== undefined
|
|
5912
|
+
? { resumeId: candidate.convId }
|
|
5913
|
+
: {}),
|
|
5914
|
+
sessionClass: candidate.sessionClass ?? "human",
|
|
5915
|
+
refuseExisting: true,
|
|
5916
|
+
});
|
|
5917
|
+
enrollFromRun({
|
|
5918
|
+
profile: candidate.profile,
|
|
5919
|
+
slug: candidate.id,
|
|
5920
|
+
tmuxSession: relaunched.name,
|
|
5921
|
+
hostKind: "local-native",
|
|
5922
|
+
pid: relaunched.pid,
|
|
5923
|
+
cwd: candidate.cwd,
|
|
5924
|
+
sessionClass: candidate.sessionClass ?? "human",
|
|
5925
|
+
...(candidate.convId !== undefined
|
|
5926
|
+
? { convId: candidate.convId }
|
|
5927
|
+
: {}),
|
|
5928
|
+
...(mode !== "auto" ? { gatewayMode: mode } : {}),
|
|
5929
|
+
});
|
|
5930
|
+
}
|
|
5931
|
+
finally {
|
|
5932
|
+
restore();
|
|
5933
|
+
}
|
|
5934
|
+
},
|
|
5935
|
+
drive: (candidate, instruction) => driveNativeInstruction(candidate.id, instruction),
|
|
5936
|
+
});
|
|
5937
|
+
renderNativeRestartResult(result, opts.json === true);
|
|
5938
|
+
if (!result.ok)
|
|
5939
|
+
process.exitCode = 1;
|
|
5940
|
+
}
|
|
5941
|
+
catch (error) {
|
|
5942
|
+
const known = error instanceof NativeRestartError;
|
|
5943
|
+
const code = known ? error.code : "restart-internal";
|
|
5944
|
+
const message = known ? error.message : "restart failed unexpectedly";
|
|
5945
|
+
if (opts.json === true) {
|
|
5946
|
+
process.stdout.write(`${JSON.stringify({
|
|
5947
|
+
kind: "h2a.restart.result",
|
|
5948
|
+
version: 1,
|
|
5949
|
+
ok: false,
|
|
5950
|
+
error: { code, message },
|
|
5951
|
+
})}\n`);
|
|
5952
|
+
}
|
|
5953
|
+
else {
|
|
5954
|
+
process.stderr.write(`[h2a] restart: ${message}\n`);
|
|
5955
|
+
}
|
|
5956
|
+
process.exitCode = 1;
|
|
5957
|
+
}
|
|
5958
|
+
});
|
|
5959
|
+
// ---------------------------------------------------------------------------
|
|
5776
5960
|
// relaunch — recover idle sessions, or explicitly force-recreate one/all
|
|
5777
5961
|
// ---------------------------------------------------------------------------
|
|
5778
5962
|
program
|
|
@@ -6511,6 +6695,14 @@ export async function main(argv) {
|
|
|
6511
6695
|
}
|
|
6512
6696
|
if (forceGateway)
|
|
6513
6697
|
restoreOpts.forceGateway = forceGateway;
|
|
6698
|
+
try {
|
|
6699
|
+
await prepareCentralMcpForRestore({ root: process.cwd() });
|
|
6700
|
+
}
|
|
6701
|
+
catch (error) {
|
|
6702
|
+
process.stderr.write(`[h2a] ${error.message}\n`);
|
|
6703
|
+
process.exitCode = 1;
|
|
6704
|
+
return;
|
|
6705
|
+
}
|
|
6514
6706
|
if (needRemote) {
|
|
6515
6707
|
const url = getConfiguredRemote();
|
|
6516
6708
|
await ensureConnected(url);
|
|
@@ -7368,6 +7560,7 @@ if (isEntryPoint()) {
|
|
|
7368
7560
|
export { main as dispatchH2a };
|
|
7369
7561
|
/** @deprecated Compatibility for older h2a cores; new cores require dispatchH2a. */
|
|
7370
7562
|
export { main as dispatch };
|
|
7563
|
+
export { ensureCentralMcp } from "./central-mcp.js";
|
|
7371
7564
|
/**
|
|
7372
7565
|
* h2a-facing surface: the read-only remote-agents projection consumed by the
|
|
7373
7566
|
* objective-loop tick's *agents adapter* in `@sentropic/h2a` (via lazy
|
|
@@ -7382,6 +7575,7 @@ export { projectStatusForH2a };
|
|
|
7382
7575
|
export { NativeTerminalClient } from "./native-terminal/client.js";
|
|
7383
7576
|
export { NativeTerminalHost } from "./native-terminal/host.js";
|
|
7384
7577
|
export { NativeTerminalHostSupervisor } from "./native-terminal/supervisor.js";
|
|
7578
|
+
export { assertOwnedByCurrentUser, sameNativeTerminalSocket } from "./native-terminal/socket-path.js";
|
|
7385
7579
|
/**
|
|
7386
7580
|
* Status-bar writer surface, consumed by `@sentropic/h2a`'s
|
|
7387
7581
|
* `status --write-bars` loop via lazy `import()`: enumerate the sessions whose
|