@sentropic/h2a-runtime 0.92.0 → 0.93.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/conv-guard.d.ts +6 -1
- package/dist/conv-guard.d.ts.map +1 -1
- package/dist/conv-guard.js +33 -8
- package/dist/conv-guard.js.map +1 -1
- package/dist/enroll.d.ts.map +1 -1
- package/dist/enroll.js +12 -2
- package/dist/enroll.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +743 -97
- package/dist/index.js.map +1 -1
- package/dist/launch-layout.d.ts +74 -0
- package/dist/launch-layout.d.ts.map +1 -0
- package/dist/launch-layout.js +324 -0
- package/dist/launch-layout.js.map +1 -0
- package/dist/native-host.d.ts +146 -0
- package/dist/native-host.d.ts.map +1 -0
- package/dist/native-host.js +456 -0
- package/dist/native-host.js.map +1 -0
- package/dist/native-terminal/host.d.ts +317 -1
- package/dist/native-terminal/host.d.ts.map +1 -1
- package/dist/native-terminal/host.js +696 -3
- package/dist/native-terminal/host.js.map +1 -1
- package/dist/native-terminal/op.d.ts +5 -0
- package/dist/native-terminal/op.d.ts.map +1 -0
- package/dist/native-terminal/op.js +408 -0
- package/dist/native-terminal/op.js.map +1 -0
- package/dist/native-terminal/process.d.ts +2 -0
- package/dist/native-terminal/process.d.ts.map +1 -1
- package/dist/native-terminal/process.js +16 -2
- package/dist/native-terminal/process.js.map +1 -1
- package/dist/native-terminal/server.d.ts.map +1 -1
- package/dist/native-terminal/server.js +6 -2
- package/dist/native-terminal/server.js.map +1 -1
- package/dist/native-terminal/socket-path.d.ts +8 -0
- package/dist/native-terminal/socket-path.d.ts.map +1 -1
- package/dist/native-terminal/socket-path.js +31 -1
- package/dist/native-terminal/socket-path.js.map +1 -1
- package/dist/native-terminal/supervisor.d.ts +13 -0
- package/dist/native-terminal/supervisor.d.ts.map +1 -1
- package/dist/native-terminal/supervisor.js +45 -0
- package/dist/native-terminal/supervisor.js.map +1 -1
- package/dist/pty.d.ts +23 -0
- package/dist/pty.d.ts.map +1 -1
- package/dist/pty.js +35 -0
- package/dist/pty.js.map +1 -1
- package/dist/readiness.d.ts +7 -0
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +12 -9
- package/dist/readiness.js.map +1 -1
- package/dist/registry.d.ts +317 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +622 -19
- package/dist/registry.js.map +1 -1
- package/dist/restore.d.ts +91 -32
- package/dist/restore.d.ts.map +1 -1
- package/dist/restore.js +226 -186
- package/dist/restore.js.map +1 -1
- package/dist/tmux.d.ts +2 -1
- package/dist/tmux.d.ts.map +1 -1
- package/dist/tmux.js +1 -1
- package/dist/tmux.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal-layout rendering for `remote restore` — split out of restore.ts so
|
|
3
|
+
* the F3 invariant is a MODULE-BOUNDARY property, not a review rule:
|
|
4
|
+
*
|
|
5
|
+
* launchLayout decides every view/launch from the ONE `HostViewSnapshot`
|
|
6
|
+
* it receives AS A PARAMETER. This module must NOT import any live host
|
|
7
|
+
* reader (listNativeSessions, listLocalSessions*, nativeSession*, probe*):
|
|
8
|
+
* you can't call what you don't have, so a divergence between plan time
|
|
9
|
+
* and launch time can never be re-read here — and an error or divergence
|
|
10
|
+
* NEVER becomes permission to launch (`live -> empty` yields attach or
|
|
11
|
+
* refuse, never `h2a run` fabricating a second writer on a live
|
|
12
|
+
* conversation). Only PURE name helpers may be imported from tmux.js.
|
|
13
|
+
*/
|
|
14
|
+
import { type LocalSession } from "./tmux.js";
|
|
15
|
+
import type { LayoutTab, LayoutWindow } from "./restore.js";
|
|
16
|
+
/**
|
|
17
|
+
* The ONE host inventory snapshot a restore plan runs on: BOTH inventories
|
|
18
|
+
* read once by the caller (restore.ts owns the readers), so the plan gate and
|
|
19
|
+
* the layout render see the SAME state. A failed inventory read is carried as
|
|
20
|
+
* `known: false` — an UNKNOWN view, never an empty one.
|
|
21
|
+
*/
|
|
22
|
+
export type HostViewSnapshot = {
|
|
23
|
+
readonly tmux: {
|
|
24
|
+
readonly known: true;
|
|
25
|
+
readonly sessions: ReadonlyArray<LocalSession>;
|
|
26
|
+
} | {
|
|
27
|
+
readonly known: false;
|
|
28
|
+
readonly reason?: string;
|
|
29
|
+
};
|
|
30
|
+
readonly native: {
|
|
31
|
+
readonly known: true;
|
|
32
|
+
/** RUNNING native sessions only, with the controller-visibility bit. */
|
|
33
|
+
readonly sessions: ReadonlyArray<{
|
|
34
|
+
readonly name: string;
|
|
35
|
+
readonly controlled: boolean | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
} | {
|
|
38
|
+
readonly known: false;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Per-tab command for an ABSENT local session: create it via `remote run …
|
|
43
|
+
* --resume …` (which attaches by default). Live sessions are deliberately
|
|
44
|
+
* handled by `launchLayout`, which knows their exact tmux names and whether they
|
|
45
|
+
* have a client attached; it emits `tmux attach -t <exact-name>` and never
|
|
46
|
+
* relaunches them.
|
|
47
|
+
*/
|
|
48
|
+
export declare function tabCommand(tab: LayoutTab, liveSlugs?: ReadonlySet<string>, opts?: {
|
|
49
|
+
forceGateway?: "gateway" | "direct";
|
|
50
|
+
/** Exact existing tmux name — attach directly, never replace/relaunch it. */
|
|
51
|
+
attachSession?: string;
|
|
52
|
+
}): string;
|
|
53
|
+
/** Group collision candidates before restore emits bare-slug attach/resume commands. */
|
|
54
|
+
export declare function ambiguousLiveSessionNames(sessions: readonly Pick<LocalSession, "name" | "slug">[]): Map<string, string[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Launch the layout in gnome-terminal: one window per group, one tab per session.
|
|
57
|
+
*
|
|
58
|
+
* Default behaviour: a live session with a tmux client is already visible and is
|
|
59
|
+
* skipped; a live session with zero clients is orphaned, so a terminal tab is
|
|
60
|
+
* opened directly onto that exact tmux session. An absent session is launched as
|
|
61
|
+
* before. `--reattach` explicitly opens another tab even for an already-visible
|
|
62
|
+
* session. This is deliberately a view decision, not a liveness decision.
|
|
63
|
+
*
|
|
64
|
+
* Every decision reads the `hostView` PARAMETER — the plan's one snapshot —
|
|
65
|
+
* never a live host (F3: this module has no reader to call).
|
|
66
|
+
*/
|
|
67
|
+
export declare function launchLayout(windows: LayoutWindow[], hostView: HostViewSnapshot, stderr?: NodeJS.WriteStream, opts?: {
|
|
68
|
+
reattach?: boolean;
|
|
69
|
+
forceGateway?: "gateway" | "direct";
|
|
70
|
+
}): {
|
|
71
|
+
opened: number;
|
|
72
|
+
skippedLive: string[];
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=launch-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-layout.d.ts","sourceRoot":"","sources":["../src/launch-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,OAAO,EAA6B,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EACT;QAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;KAAE,GACxE;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,QAAQ,CAAC,MAAM,EACX;QACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;QACrB,wEAAwE;QACxE,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;YAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;SAC1C,CAAC,CAAC;KACJ,GACD;QAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,SAAS,EACd,SAAS,GAAE,WAAW,CAAC,MAAM,CAAa,EAC1C,IAAI,GAAE;IACJ,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACpC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;CACnB,GACL,MAAM,CAgDR;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,GACvD,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAUvB;AA4BD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EAAE,EACvB,QAAQ,EAAE,gBAAgB,EAC1B,MAAM,GAAE,MAAM,CAAC,WAA4B,EAC3C,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAO,GACrE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAgQ3C"}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal-layout rendering for `remote restore` — split out of restore.ts so
|
|
3
|
+
* the F3 invariant is a MODULE-BOUNDARY property, not a review rule:
|
|
4
|
+
*
|
|
5
|
+
* launchLayout decides every view/launch from the ONE `HostViewSnapshot`
|
|
6
|
+
* it receives AS A PARAMETER. This module must NOT import any live host
|
|
7
|
+
* reader (listNativeSessions, listLocalSessions*, nativeSession*, probe*):
|
|
8
|
+
* you can't call what you don't have, so a divergence between plan time
|
|
9
|
+
* and launch time can never be re-read here — and an error or divergence
|
|
10
|
+
* NEVER becomes permission to launch (`live -> empty` yields attach or
|
|
11
|
+
* refuse, never `h2a run` fabricating a second writer on a live
|
|
12
|
+
* conversation). Only PURE name helpers may be imported from tmux.js.
|
|
13
|
+
*/
|
|
14
|
+
import { spawn } from "node:child_process";
|
|
15
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { homedir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { localSessionName, slugify } from "./tmux.js";
|
|
19
|
+
/**
|
|
20
|
+
* Per-tab command for an ABSENT local session: create it via `remote run …
|
|
21
|
+
* --resume …` (which attaches by default). Live sessions are deliberately
|
|
22
|
+
* handled by `launchLayout`, which knows their exact tmux names and whether they
|
|
23
|
+
* have a client attached; it emits `tmux attach -t <exact-name>` and never
|
|
24
|
+
* relaunches them.
|
|
25
|
+
*/
|
|
26
|
+
export function tabCommand(tab, liveSlugs = new Set(), opts = {}) {
|
|
27
|
+
const q = (s) => `'${s.replace(/'/g, "'\\''")}'`;
|
|
28
|
+
if (tab.remoteId) {
|
|
29
|
+
// SCW: attach straight into the Pod's tmux (live, copy-friendly).
|
|
30
|
+
return `h2a attach ${q(tab.remoteId)} --exec`;
|
|
31
|
+
}
|
|
32
|
+
const slug = slugify(tab.label);
|
|
33
|
+
if (tab.attachLive) {
|
|
34
|
+
// §4.1 attach-live: a live managed row whose conversation id is
|
|
35
|
+
// unresolved re-enters by EXACT managed name only. No resume id exists,
|
|
36
|
+
// so no run/replace command may ever be rendered for it.
|
|
37
|
+
return `h2a attach ${q(tab.managedName ?? localSessionName(slug))}`;
|
|
38
|
+
}
|
|
39
|
+
// Effective gateway posture: an explicit `restore --gw/--no-gw` OVERRIDES the
|
|
40
|
+
// per-instance pin; otherwise honour the pinned gatewayMode (absent = default).
|
|
41
|
+
const posture = opts.forceGateway ?? tab.gatewayMode;
|
|
42
|
+
const gwFlag = posture === "gateway" ? " --gw" : posture === "direct" ? " --no-gw" : "";
|
|
43
|
+
// Persisted-host pin — the gatewayMode pattern applied to the terminal
|
|
44
|
+
// host: a NON-LIVE session is re-created on the host its registry record
|
|
45
|
+
// names, never on the current default. A recorded native session survives
|
|
46
|
+
// the fleet-wide H2A_SESSION_HOST=tmux valve via the env pin (any other
|
|
47
|
+
// value selects native — resolveSessionHostKind), where it fails closed if
|
|
48
|
+
// the native host is unavailable rather than silently re-routing; a
|
|
49
|
+
// recorded tmux session survives the native default via --tmux. Tabs
|
|
50
|
+
// without a recorded host (scan fallback) keep following the default.
|
|
51
|
+
const nativePin = tab.hostKind === "local-native" ? "H2A_SESSION_HOST=native " : "";
|
|
52
|
+
const tmuxPin = tab.hostKind === "local-tmux" ? " --tmux" : "";
|
|
53
|
+
const runCmd = (extra) => `${nativePin}h2a run ${q(tab.tool ?? "shell")} ${q(tab.cwd)} ` +
|
|
54
|
+
(tab.sid ? `--resume ${q(tab.sid)} ` : "") +
|
|
55
|
+
`--name ${q(tab.label)}${gwFlag}${tmuxPin}${extra}`;
|
|
56
|
+
if (opts.attachSession) {
|
|
57
|
+
// `h2a attach` resolves the exact managed name and honors the session's
|
|
58
|
+
// RECORDED host (tmux attach for tmux sessions, the native bridge for
|
|
59
|
+
// native-PTY sessions) — a raw `tmux attach -t` here would strand every
|
|
60
|
+
// native session behind a "no such session" error.
|
|
61
|
+
return `h2a attach ${q(opts.attachSession)}`;
|
|
62
|
+
}
|
|
63
|
+
if (liveSlugs.has(slug)) {
|
|
64
|
+
// Compatibility for direct callers that only know a unique slug. Restore
|
|
65
|
+
// itself always supplies the exact name above, avoiding prefix collisions.
|
|
66
|
+
// Crucially, a gateway override never turns a live session into --replace:
|
|
67
|
+
// restore must preserve its process and conversation.
|
|
68
|
+
return `h2a attach ${q(slug)}`;
|
|
69
|
+
}
|
|
70
|
+
return runCmd("");
|
|
71
|
+
}
|
|
72
|
+
/** Group collision candidates before restore emits bare-slug attach/resume commands. */
|
|
73
|
+
export function ambiguousLiveSessionNames(sessions) {
|
|
74
|
+
const namesBySlug = new Map();
|
|
75
|
+
for (const session of sessions) {
|
|
76
|
+
const names = namesBySlug.get(session.slug) ?? [];
|
|
77
|
+
names.push(session.name);
|
|
78
|
+
namesBySlug.set(session.slug, names);
|
|
79
|
+
}
|
|
80
|
+
return new Map([...namesBySlug].filter(([, names]) => names.length > 1));
|
|
81
|
+
}
|
|
82
|
+
// gnome-terminal applies ONE trailing `-- command` to EVERY tab of an
|
|
83
|
+
// invocation (you cannot give each tab its own `--`). So all tabs run the same
|
|
84
|
+
// dispatcher; each claims (under flock) the first map line matching its $PWD
|
|
85
|
+
// and runs that tab's command — exactly how ~/bin/resume-dev-sessions worked.
|
|
86
|
+
const DISPATCHER = `map="$1"
|
|
87
|
+
lock="$map.lock"
|
|
88
|
+
exec 9>"$lock"; flock 9
|
|
89
|
+
line=$(awk -F'\\t' -v c="$PWD" '$1==c{print;exit}' "$map")
|
|
90
|
+
if [ -n "$line" ]; then
|
|
91
|
+
awk -F'\\t' -v c="$PWD" 'BEGIN{d=0} d==0 && $1==c {d=1; next} {print}' "$map" > "$map.tmp" && mv "$map.tmp" "$map"
|
|
92
|
+
fi
|
|
93
|
+
flock -u 9
|
|
94
|
+
cmd=$(printf '%s' "$line" | cut -f2-)
|
|
95
|
+
if [ -n "$cmd" ]; then eval "$cmd"; else echo "[h2a] rien a reprendre pour $PWD" >&2; fi
|
|
96
|
+
exec bash -l`;
|
|
97
|
+
let mapCounter = 0;
|
|
98
|
+
function runDir() {
|
|
99
|
+
const base = process.env.XDG_RUNTIME_DIR
|
|
100
|
+
? join(process.env.XDG_RUNTIME_DIR, "sentropic-remote")
|
|
101
|
+
: join(homedir(), ".config", "sentropic", "remote-cli", "run");
|
|
102
|
+
mkdirSync(base, { recursive: true });
|
|
103
|
+
return base;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Launch the layout in gnome-terminal: one window per group, one tab per session.
|
|
107
|
+
*
|
|
108
|
+
* Default behaviour: a live session with a tmux client is already visible and is
|
|
109
|
+
* skipped; a live session with zero clients is orphaned, so a terminal tab is
|
|
110
|
+
* opened directly onto that exact tmux session. An absent session is launched as
|
|
111
|
+
* before. `--reattach` explicitly opens another tab even for an already-visible
|
|
112
|
+
* session. This is deliberately a view decision, not a liveness decision.
|
|
113
|
+
*
|
|
114
|
+
* Every decision reads the `hostView` PARAMETER — the plan's one snapshot —
|
|
115
|
+
* never a live host (F3: this module has no reader to call).
|
|
116
|
+
*/
|
|
117
|
+
export function launchLayout(windows, hostView, stderr = process.stderr, opts = {}) {
|
|
118
|
+
const tmuxKnown = hostView.tmux.known;
|
|
119
|
+
const tmuxReason = hostView.tmux.known ? undefined : hostView.tmux.reason;
|
|
120
|
+
const tmuxSessions = hostView.tmux.known
|
|
121
|
+
? hostView.tmux.sessions
|
|
122
|
+
: [];
|
|
123
|
+
// Native view by EXACT session name, carrying the controller-visibility
|
|
124
|
+
// bit. A failed inventory read is an UNKNOWN view (undefined map) — never
|
|
125
|
+
// "no sessions": launching a replacement onto an unprovable host state
|
|
126
|
+
// could create a second writer, so unknown fails closed below.
|
|
127
|
+
const nativeSessionsByName = hostView.native.known
|
|
128
|
+
? new Map(hostView.native.sessions.map((session) => [
|
|
129
|
+
session.name,
|
|
130
|
+
{ controlled: session.controlled },
|
|
131
|
+
]))
|
|
132
|
+
: undefined;
|
|
133
|
+
// Slug-union view for LEGACY tabs without a recorded host (scan fallback)
|
|
134
|
+
// ONLY — a tab that carries its persisted hostKind + exact managed name is
|
|
135
|
+
// rendered from that identity and never chooses a host from a merged slug
|
|
136
|
+
// list. A CONTROLLED native session counts as attached (already visible).
|
|
137
|
+
const nativeLive = nativeSessionsByName !== undefined
|
|
138
|
+
? [...nativeSessionsByName.entries()]
|
|
139
|
+
.filter(([name]) => name.startsWith("h2a-") && !name.endsWith(".h2a"))
|
|
140
|
+
.map(([name, view]) => ({
|
|
141
|
+
name,
|
|
142
|
+
slug: name.slice("h2a-".length),
|
|
143
|
+
attached: view.controlled === true,
|
|
144
|
+
}))
|
|
145
|
+
: [];
|
|
146
|
+
const liveSessions = [
|
|
147
|
+
...tmuxSessions,
|
|
148
|
+
...nativeLive.filter((native) => !tmuxSessions.some((s) => s.name === native.name)),
|
|
149
|
+
];
|
|
150
|
+
const ambiguousLiveNames = ambiguousLiveSessionNames(liveSessions);
|
|
151
|
+
const skippedLive = [];
|
|
152
|
+
let opened = 0;
|
|
153
|
+
// A gateway override can configure a NEW process but must never replace a live
|
|
154
|
+
// one. `--reattach` is the sole opt-in that duplicates an already-visible tab.
|
|
155
|
+
const includeAttached = opts.reattach === true;
|
|
156
|
+
const tabOpts = opts.forceGateway ? { forceGateway: opts.forceGateway } : {};
|
|
157
|
+
if (!tmuxKnown) {
|
|
158
|
+
// We cannot reliably tell "attached" from "orphaned". Prefer a harmless
|
|
159
|
+
// duplicate/failing attach over `h2a run` possibly racing a live tmux
|
|
160
|
+
// session; a restore command must never reclaim a view by killing its work.
|
|
161
|
+
stderr.write(`[h2a] tmux view state unavailable${tmuxReason ? ` (${tmuxReason})` : ""}; ` +
|
|
162
|
+
"opening attach tabs rather than relaunching local sessions\n");
|
|
163
|
+
}
|
|
164
|
+
for (const win of windows) {
|
|
165
|
+
// Remote (k8s) tabs are always included — we can't probe pod health here.
|
|
166
|
+
// Local tabs carry their finalized command because a live orphan must attach
|
|
167
|
+
// to its exact tmux name, while an absent session must be launched.
|
|
168
|
+
const activeTabs = [];
|
|
169
|
+
for (const t of win.tabs) {
|
|
170
|
+
if (t.remoteId) {
|
|
171
|
+
activeTabs.push({ tab: t, command: tabCommand(t) });
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const slug = slugify(t.label);
|
|
175
|
+
// --- Tabs WITH a recorded host: exact-identity, single-host render. ---
|
|
176
|
+
// The host decision was made by the plan (persisted kind + exact
|
|
177
|
+
// managed name); this block only renders the view for THAT host.
|
|
178
|
+
if (t.hostKind === "local-native") {
|
|
179
|
+
const exact = t.managedName ?? `h2a-${slug}`;
|
|
180
|
+
if (nativeSessionsByName === undefined) {
|
|
181
|
+
stderr.write(`[h2a] restore: native host state UNKNOWN — "${t.label}" neither relaunched nor attached (fail closed)\n`);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const view = nativeSessionsByName.get(exact);
|
|
185
|
+
if (view !== undefined) {
|
|
186
|
+
if (view.controlled === true) {
|
|
187
|
+
// running && controlled → already visible. Even --reattach must
|
|
188
|
+
// not open a competing controller (single-controller model).
|
|
189
|
+
skippedLive.push(t.label);
|
|
190
|
+
if (includeAttached) {
|
|
191
|
+
stderr.write(`[h2a] restore: "${t.label}" is already controlled in a terminal; not opening a second controller\n`);
|
|
192
|
+
}
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (view.controlled === undefined) {
|
|
196
|
+
// running && view unknown (host predates the visibility bit):
|
|
197
|
+
// preserve the process, report, never relaunch.
|
|
198
|
+
stderr.write(`[h2a] restore: controller visibility UNKNOWN for running native session "${t.label}"; attach manually: h2a attach ${exact}\n`);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
// running && !controlled → exactly one exact-name attach.
|
|
202
|
+
activeTabs.push({
|
|
203
|
+
tab: t,
|
|
204
|
+
command: tabCommand(t, new Set([slug]), { attachSession: exact }),
|
|
205
|
+
});
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
// Dead/absent on a KNOWN native view.
|
|
209
|
+
if (t.attachLive) {
|
|
210
|
+
stderr.write(`[h2a] restore: "${t.label}" was live at plan time but is gone; no resolved conversation exists to relaunch it\n`);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
activeTabs.push({ tab: t, command: tabCommand(t, new Set(), tabOpts) });
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (t.hostKind === "local-tmux") {
|
|
217
|
+
const exact = t.managedName ?? `h2a-${slug}`;
|
|
218
|
+
if (!tmuxKnown) {
|
|
219
|
+
// Conservative: a harmless exact attach, never a relaunch race.
|
|
220
|
+
activeTabs.push({
|
|
221
|
+
tab: t,
|
|
222
|
+
command: tabCommand(t, new Set([slug]), { attachSession: exact }),
|
|
223
|
+
});
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const liveTmux = tmuxSessions.find((session) => session.name === exact);
|
|
227
|
+
if (liveTmux) {
|
|
228
|
+
// DRAIN view: the live legacy process is attach-only — dispatched
|
|
229
|
+
// to its persisted host via `h2a attach`; never replaced, and no
|
|
230
|
+
// tmux session is ever created here.
|
|
231
|
+
if (!includeAttached && liveTmux.attached) {
|
|
232
|
+
skippedLive.push(t.label);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
activeTabs.push({
|
|
236
|
+
tab: t,
|
|
237
|
+
command: tabCommand(t, new Set([slug]), { attachSession: exact }),
|
|
238
|
+
});
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (t.attachLive) {
|
|
242
|
+
stderr.write(`[h2a] restore: "${t.label}" was live at plan time but is gone; no resolved conversation exists to relaunch it\n`);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
// Dead recorded tmux row: re-created on its recorded host via the
|
|
246
|
+
// --tmux pin (tabCommand). Which host a dead tmux session should be
|
|
247
|
+
// relaunched on is a REOPENED policy question — this keeps the #199
|
|
248
|
+
// behavior as-is.
|
|
249
|
+
activeTabs.push({ tab: t, command: tabCommand(t, new Set(), tabOpts) });
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
// --- Legacy tabs without a recorded host: slug-union view (scan). ---
|
|
253
|
+
if (!tmuxKnown) {
|
|
254
|
+
activeTabs.push({
|
|
255
|
+
tab: t,
|
|
256
|
+
command: tabCommand(t, new Set([slug]), { attachSession: `h2a-${slug}` }),
|
|
257
|
+
});
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
const names = ambiguousLiveNames.get(slug);
|
|
261
|
+
if (names) {
|
|
262
|
+
skippedLive.push(t.label);
|
|
263
|
+
stderr.write(`[h2a] restore skipped "${t.label}": local tmux slug is ambiguous (${names.sort().join(", ")}); ` +
|
|
264
|
+
`attach explicitly with h2a attach ${names.sort()[0]} or h2a attach ${names.sort()[1]}\n`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const liveSession = liveSessions.find((session) => session.slug === slug);
|
|
268
|
+
if (liveSession && !includeAttached && liveSession.attached) {
|
|
269
|
+
skippedLive.push(t.label);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (!liveSession && nativeSessionsByName === undefined) {
|
|
273
|
+
// The tab would LAUNCH — but the native host state is unknown, so a
|
|
274
|
+
// homonymous live native session cannot be ruled out. Fail closed.
|
|
275
|
+
stderr.write(`[h2a] restore: native host state UNKNOWN — "${t.label}" not launched (fail closed)\n`);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
activeTabs.push({
|
|
279
|
+
tab: t,
|
|
280
|
+
command: liveSession
|
|
281
|
+
? tabCommand(t, new Set([slug]), { attachSession: liveSession.name })
|
|
282
|
+
: tabCommand(t, new Set(), tabOpts),
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
if (activeTabs.length === 0) {
|
|
286
|
+
// All sessions in this window are already active — no tab needed.
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
// Map keyed by per-tab working directory -> the tab's command. Tabs sharing
|
|
290
|
+
// a cwd (several sessions of one project) each claim a distinct line FIFO.
|
|
291
|
+
const slug = win.title.replace(/[^a-zA-Z0-9]+/g, "-");
|
|
292
|
+
const mapPath = join(runDir(), `restore-${process.pid}-${slug}-${mapCounter++}.map`);
|
|
293
|
+
const body = activeTabs
|
|
294
|
+
.map(({ tab, command }) => `${tab.cwd}\t${command}`)
|
|
295
|
+
.join("\n") + "\n";
|
|
296
|
+
writeFileSync(mapPath, body, "utf8");
|
|
297
|
+
const args = [];
|
|
298
|
+
activeTabs.forEach(({ tab }, i) => {
|
|
299
|
+
args.push(i === 0 ? "--window" : "--tab", `--working-directory=${tab.cwd}`, `--title=${tab.label}`);
|
|
300
|
+
});
|
|
301
|
+
// ONE shared dispatcher command for all tabs of this window.
|
|
302
|
+
args.push("--", "bash", "-lc", DISPATCHER, "remote-restore", mapPath);
|
|
303
|
+
stderr.write(`[h2a] fenêtre "${win.title}" (${activeTabs.length} onglet(s))\n`);
|
|
304
|
+
// Surface gnome-terminal errors (e.g. "Failed to get screen…") instead of
|
|
305
|
+
// silently claiming the window opened.
|
|
306
|
+
const { GNOME_TERMINAL_SCREEN: _drop, ...childEnv } = process.env;
|
|
307
|
+
const child = spawn("gnome-terminal", args, {
|
|
308
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
309
|
+
detached: true,
|
|
310
|
+
env: childEnv,
|
|
311
|
+
});
|
|
312
|
+
child.stderr?.on("data", (chunk) => {
|
|
313
|
+
stderr.write(`[h2a] gnome-terminal: ${chunk.toString().trim()}\n`);
|
|
314
|
+
});
|
|
315
|
+
child.unref();
|
|
316
|
+
opened += activeTabs.length;
|
|
317
|
+
}
|
|
318
|
+
if (skippedLive.length > 0) {
|
|
319
|
+
stderr.write(`[h2a] ${skippedLive.length} session(s) déjà visibles ignorées` +
|
|
320
|
+
` (--reattach pour les rouvrir quand même): ${skippedLive.join(", ")}\n`);
|
|
321
|
+
}
|
|
322
|
+
return { opened, skippedLive };
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=launch-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch-layout.js","sourceRoot":"","sources":["../src/launch-layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { type PromptDeliveryDeps } from "./prompt-delivery.js";
|
|
2
|
+
import { type SessionClass } from "./session-class.js";
|
|
3
|
+
export type SessionHostKind = "native" | "local-tmux";
|
|
4
|
+
/**
|
|
5
|
+
* Which host runs a NEW session's terminal. The native PTY host is the
|
|
6
|
+
* default; `--tmux` (per command) or H2A_SESSION_HOST=tmux (fleet-wide safety
|
|
7
|
+
* valve) selects tmux. Existing sessions are NEVER re-routed here — verbs that
|
|
8
|
+
* act on a recorded session honor its registry kind instead.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveSessionHostKind(opts: {
|
|
11
|
+
readonly tmux?: boolean;
|
|
12
|
+
}, env?: Readonly<Record<string, string | undefined>>): SessionHostKind;
|
|
13
|
+
/** Companion native session that hosts the h2a MCP sidecar for `name`. */
|
|
14
|
+
export declare function nativeSidecarName(name: string): string;
|
|
15
|
+
export type NativeSessionState = {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly pid: number;
|
|
18
|
+
readonly status: "running" | "stopping" | "exited";
|
|
19
|
+
readonly exit: {
|
|
20
|
+
readonly exitCode: number;
|
|
21
|
+
readonly signal?: number;
|
|
22
|
+
} | null;
|
|
23
|
+
/**
|
|
24
|
+
* Controller-visibility bit (never the controller's identity): true when an
|
|
25
|
+
* exclusive input controller is attached. OPTIONAL because an older running
|
|
26
|
+
* host does not report it — consumers must treat absence as an UNKNOWN view
|
|
27
|
+
* and fail closed (report, don't relaunch), never as "uncontrolled".
|
|
28
|
+
*/
|
|
29
|
+
readonly controlled?: boolean;
|
|
30
|
+
};
|
|
31
|
+
export type NativeStartResult = {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly slug: string;
|
|
34
|
+
readonly pid: number;
|
|
35
|
+
};
|
|
36
|
+
/** node-pty loadable + containment binaries present. Pure preflight. */
|
|
37
|
+
export declare function nativeHostAvailable(): {
|
|
38
|
+
readonly ok: true;
|
|
39
|
+
} | {
|
|
40
|
+
readonly ok: false;
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
};
|
|
43
|
+
/** Spawn-or-adopt the per-user host; returns its identity. */
|
|
44
|
+
export declare function ensureNativeHost(): {
|
|
45
|
+
hostPid: number;
|
|
46
|
+
socketPath: string;
|
|
47
|
+
};
|
|
48
|
+
export declare function listNativeSessions(): ReadonlyArray<NativeSessionState>;
|
|
49
|
+
/**
|
|
50
|
+
* 3-state session probe (F2). The lie this type removes: a failed `state` op
|
|
51
|
+
* used to flatten into `undefined`/`alive=false` — indistinguishable from a
|
|
52
|
+
* PROVEN dead/absent session, which let destructive acts read an op failure
|
|
53
|
+
* as a death certificate. The states:
|
|
54
|
+
* - "found": a reachable host answered with the session's state;
|
|
55
|
+
* - "absent": POSITIVE proof of absence — a reachable host does not know
|
|
56
|
+
* the session, or no host is listening at all (a PTY cannot outlive its
|
|
57
|
+
* host process, the same provable-death rule as a missing tmux server);
|
|
58
|
+
* - "unknown": the op failed (spawn error, timeout, protocol failure) —
|
|
59
|
+
* NEVER proof of death; destructive callers must fail closed on it.
|
|
60
|
+
* The classification happens IN-BAND in the `probe` op (op.ts), where the
|
|
61
|
+
* error codes live — never by parsing a generic failure on this side.
|
|
62
|
+
*/
|
|
63
|
+
export type NativeStateProbe = {
|
|
64
|
+
readonly state: "found";
|
|
65
|
+
readonly session: NativeSessionState;
|
|
66
|
+
} | {
|
|
67
|
+
readonly state: "absent";
|
|
68
|
+
} | {
|
|
69
|
+
readonly state: "unknown";
|
|
70
|
+
readonly reason: string;
|
|
71
|
+
};
|
|
72
|
+
export declare function nativeSessionState(name: string): NativeStateProbe;
|
|
73
|
+
/**
|
|
74
|
+
* 3-state liveness (F2): `true` / `false` are POSITIVE verdicts; "unknown"
|
|
75
|
+
* is a probe failure that destructive paths must refuse on. Never throws.
|
|
76
|
+
*/
|
|
77
|
+
export declare function nativeSessionLiveness(name: string): true | false | "unknown";
|
|
78
|
+
export declare function nativeSessionPid(name: string): number | undefined;
|
|
79
|
+
export type NativeLaunchMetadata = {
|
|
80
|
+
readonly label?: string;
|
|
81
|
+
readonly resumeId?: string;
|
|
82
|
+
readonly sessionClass?: SessionClass;
|
|
83
|
+
readonly terminateOnAgentExit?: boolean;
|
|
84
|
+
readonly refuseExisting?: boolean;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* startLocalSession twin. Runs the SAME bash wrapper contract as the tmux
|
|
88
|
+
* path (LOCAL_WRAPPER drop-to-shell / STRUCTURED_LOCAL_WRAPPER exec-only), so
|
|
89
|
+
* agent exit semantics are identical across hosts.
|
|
90
|
+
*/
|
|
91
|
+
export declare function startNativeSession(profile: string, command: string, cwd: string, args?: ReadonlyArray<string>, label?: string, metadata?: NativeLaunchMetadata): NativeStartResult;
|
|
92
|
+
/** sendKeysLiteral twin: raw keystrokes, no interpretation. */
|
|
93
|
+
export declare function nativeSendKeysLiteral(name: string, text: string): boolean;
|
|
94
|
+
/** paste-buffer -p twin: the text lands as ONE bracketed block. */
|
|
95
|
+
export declare function nativePasteBlock(name: string, text: string): boolean;
|
|
96
|
+
/** The Enter that submits a composed block. */
|
|
97
|
+
export declare function nativeSendEnter(name: string): boolean;
|
|
98
|
+
/**
|
|
99
|
+
* capturePane twin. IMPORTANT semantic difference: tmux returns the RENDERED
|
|
100
|
+
* screen; this returns the ANSI-stripped tail of the output stream. For probe
|
|
101
|
+
* matching (prompt echo, modal text) the stream tail carries the same visible
|
|
102
|
+
* text — full-screen-repaint TUIs re-emit their frame into the tail.
|
|
103
|
+
*/
|
|
104
|
+
export declare function nativeCapture(name: string, bytes?: number): string | undefined;
|
|
105
|
+
/** kill-session twin: SIGTERM with SIGKILL escalation inside the op. */
|
|
106
|
+
export declare function killNativeSession(name: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Kill a session AND its h2a sidecar companion (the tmux twin gets this for
|
|
109
|
+
* free because the sidecar is a window inside the killed session).
|
|
110
|
+
*/
|
|
111
|
+
export declare function killNativeSessionTree(name: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* startHeadlessSession twin: run-once agent under HEADLESS_WRAPPER, writing
|
|
114
|
+
* result.json + output.log, session ends when the wrapper finishes. The
|
|
115
|
+
* prompt rides a 0600 file consumed and unlinked by the wrapper — identical
|
|
116
|
+
* contract to the tmux path.
|
|
117
|
+
*/
|
|
118
|
+
export declare function startNativeHeadlessSession(profile: string, command: string, cwd: string, args: ReadonlyArray<string>, resultJson: string, outputLog: string, label: string, promptInput?: string, refuseExisting?: boolean, sessionClass?: SessionClass): NativeStartResult & {
|
|
119
|
+
promptFile?: string;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* startH2aWindow twin: the h2a MCP sidecar runs in a COMPANION native session
|
|
123
|
+
* (`<name>.h2a`) instead of a tmux window. Lifecycle: killNativeSessionTree
|
|
124
|
+
* stops it with its main session.
|
|
125
|
+
*/
|
|
126
|
+
export declare function startNativeH2aSidecar(name: string, cwd: string, h2aCommand: string, options?: {
|
|
127
|
+
verified?: boolean;
|
|
128
|
+
}): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Foreground interactive attach on the CURRENT terminal (tmux attach twin).
|
|
131
|
+
* Blocks until the session exits or the user detaches with Ctrl-\.
|
|
132
|
+
*/
|
|
133
|
+
export declare function attachNativeSession(name: string): number;
|
|
134
|
+
/** clearPaneComposer twin: C-u wipes the composer line (best-effort). */
|
|
135
|
+
export declare function nativeClearComposer(name: string): boolean;
|
|
136
|
+
/** paneTreeCpuMs twin, keyed by session name instead of tmux pane. */
|
|
137
|
+
export declare function nativeTreeCpuMs(name: string): number | undefined;
|
|
138
|
+
/** paneWorkerPid twin: the pid actually doing the work under the wrapper. */
|
|
139
|
+
export declare function nativeWorkerPid(name: string): number | undefined;
|
|
140
|
+
/**
|
|
141
|
+
* PromptDeliveryDeps for a native session — deliverInitialPrompt() runs the
|
|
142
|
+
* SAME measured protocol as on tmux; only the transport differs. The "pane"
|
|
143
|
+
* key given to deliverInitialPrompt must be the session NAME.
|
|
144
|
+
*/
|
|
145
|
+
export declare function nativePromptDeliveryDeps(sleep: (ms: number) => void): PromptDeliveryDeps;
|
|
146
|
+
//# sourceMappingURL=native-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-host.d.ts","sourceRoot":"","sources":["../src/native-host.ts"],"names":[],"mappings":"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"}
|