@sentropic/h2a-runtime 0.81.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/account-pool.d.ts +168 -0
- package/dist/account-pool.d.ts.map +1 -0
- package/dist/account-pool.js +385 -0
- package/dist/account-pool.js.map +1 -0
- package/dist/agents-projection.d.ts +56 -0
- package/dist/agents-projection.d.ts.map +1 -0
- package/dist/agents-projection.js +82 -0
- package/dist/agents-projection.js.map +1 -0
- package/dist/attach.d.ts +75 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +432 -0
- package/dist/attach.js.map +1 -0
- package/dist/auth-bundle.d.ts +21 -0
- package/dist/auth-bundle.d.ts.map +1 -0
- package/dist/auth-bundle.js +112 -0
- package/dist/auth-bundle.js.map +1 -0
- package/dist/auth-diagnostics.d.ts +18 -0
- package/dist/auth-diagnostics.d.ts.map +1 -0
- package/dist/auth-diagnostics.js +23 -0
- package/dist/auth-diagnostics.js.map +1 -0
- package/dist/auth-login.d.ts +9 -0
- package/dist/auth-login.d.ts.map +1 -0
- package/dist/auth-login.js +21 -0
- package/dist/auth-login.js.map +1 -0
- package/dist/auth-refresh.d.ts +32 -0
- package/dist/auth-refresh.d.ts.map +1 -0
- package/dist/auth-refresh.js +83 -0
- package/dist/auth-refresh.js.map +1 -0
- package/dist/auth-tools.d.ts +55 -0
- package/dist/auth-tools.d.ts.map +1 -0
- package/dist/auth-tools.js +163 -0
- package/dist/auth-tools.js.map +1 -0
- package/dist/browser-bridge-local.d.ts +27 -0
- package/dist/browser-bridge-local.d.ts.map +1 -0
- package/dist/browser-bridge-local.js +51 -0
- package/dist/browser-bridge-local.js.map +1 -0
- package/dist/browser.d.ts +53 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +61 -0
- package/dist/browser.js.map +1 -0
- package/dist/conductor-launch.d.ts +179 -0
- package/dist/conductor-launch.d.ts.map +1 -0
- package/dist/conductor-launch.js +414 -0
- package/dist/conductor-launch.js.map +1 -0
- package/dist/config.d.ts +182 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +334 -0
- package/dist/config.js.map +1 -0
- package/dist/conv-guard.d.ts +76 -0
- package/dist/conv-guard.d.ts.map +1 -0
- package/dist/conv-guard.js +131 -0
- package/dist/conv-guard.js.map +1 -0
- package/dist/convsync.d.ts +24 -0
- package/dist/convsync.d.ts.map +1 -0
- package/dist/convsync.js +108 -0
- package/dist/convsync.js.map +1 -0
- package/dist/cred-health.d.ts +96 -0
- package/dist/cred-health.d.ts.map +1 -0
- package/dist/cred-health.js +170 -0
- package/dist/cred-health.js.map +1 -0
- package/dist/delegate.d.ts +406 -0
- package/dist/delegate.d.ts.map +1 -0
- package/dist/delegate.js +739 -0
- package/dist/delegate.js.map +1 -0
- package/dist/enroll.d.ts +91 -0
- package/dist/enroll.d.ts.map +1 -0
- package/dist/enroll.js +248 -0
- package/dist/enroll.js.map +1 -0
- package/dist/fanout.d.ts +63 -0
- package/dist/fanout.d.ts.map +1 -0
- package/dist/fanout.js +115 -0
- package/dist/fanout.js.map +1 -0
- package/dist/forward.d.ts +66 -0
- package/dist/forward.d.ts.map +1 -0
- package/dist/forward.js +141 -0
- package/dist/forward.js.map +1 -0
- package/dist/gitdiff.d.ts +31 -0
- package/dist/gitdiff.d.ts.map +1 -0
- package/dist/gitdiff.js +133 -0
- package/dist/gitdiff.js.map +1 -0
- package/dist/h2a-bridge.d.ts +102 -0
- package/dist/h2a-bridge.d.ts.map +1 -0
- package/dist/h2a-bridge.js +333 -0
- package/dist/h2a-bridge.js.map +1 -0
- package/dist/h2a-jobs.d.ts +235 -0
- package/dist/h2a-jobs.d.ts.map +1 -0
- package/dist/h2a-jobs.js +388 -0
- package/dist/h2a-jobs.js.map +1 -0
- package/dist/h2a-ping.d.ts +38 -0
- package/dist/h2a-ping.d.ts.map +1 -0
- package/dist/h2a-ping.js +58 -0
- package/dist/h2a-ping.js.map +1 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5887 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive-throttle.d.ts +164 -0
- package/dist/interactive-throttle.d.ts.map +1 -0
- package/dist/interactive-throttle.js +194 -0
- package/dist/interactive-throttle.js.map +1 -0
- package/dist/lineage-client.d.ts +77 -0
- package/dist/lineage-client.d.ts.map +1 -0
- package/dist/lineage-client.js +117 -0
- package/dist/lineage-client.js.map +1 -0
- package/dist/lineage-lease.d.ts +152 -0
- package/dist/lineage-lease.d.ts.map +1 -0
- package/dist/lineage-lease.js +303 -0
- package/dist/lineage-lease.js.map +1 -0
- package/dist/llm-gateway-runtime/accounts.d.ts +48 -0
- package/dist/llm-gateway-runtime/accounts.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/accounts.js +226 -0
- package/dist/llm-gateway-runtime/accounts.js.map +1 -0
- package/dist/llm-gateway-runtime/index.d.ts +4 -0
- package/dist/llm-gateway-runtime/index.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/index.js +58 -0
- package/dist/llm-gateway-runtime/index.js.map +1 -0
- package/dist/llm-gateway-runtime/model-catalog.d.ts +36 -0
- package/dist/llm-gateway-runtime/model-catalog.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/model-catalog.js +146 -0
- package/dist/llm-gateway-runtime/model-catalog.js.map +1 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.d.ts +3 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.js +139 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.js.map +1 -0
- package/dist/llm-gateway-runtime/proxy-openai.d.ts +117 -0
- package/dist/llm-gateway-runtime/proxy-openai.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/proxy-openai.js +1132 -0
- package/dist/llm-gateway-runtime/proxy-openai.js.map +1 -0
- package/dist/llm-gateway-runtime/session-ledger.d.ts +32 -0
- package/dist/llm-gateway-runtime/session-ledger.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/session-ledger.js +62 -0
- package/dist/llm-gateway-runtime/session-ledger.js.map +1 -0
- package/dist/llm-gateway-runtime/sticky.d.ts +40 -0
- package/dist/llm-gateway-runtime/sticky.d.ts.map +1 -0
- package/dist/llm-gateway-runtime/sticky.js +254 -0
- package/dist/llm-gateway-runtime/sticky.js.map +1 -0
- package/dist/llm-mesh.d.ts +102 -0
- package/dist/llm-mesh.d.ts.map +1 -0
- package/dist/llm-mesh.js +433 -0
- package/dist/llm-mesh.js.map +1 -0
- package/dist/migrate-candidates.d.ts +35 -0
- package/dist/migrate-candidates.d.ts.map +1 -0
- package/dist/migrate-candidates.js +128 -0
- package/dist/migrate-candidates.js.map +1 -0
- package/dist/migrate.d.ts +125 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +561 -0
- package/dist/migrate.js.map +1 -0
- package/dist/plugin-manifest.d.ts +143 -0
- package/dist/plugin-manifest.d.ts.map +1 -0
- package/dist/plugin-manifest.js +233 -0
- package/dist/plugin-manifest.js.map +1 -0
- package/dist/plugin.d.ts +274 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +919 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pod-liveness.d.ts +51 -0
- package/dist/pod-liveness.d.ts.map +1 -0
- package/dist/pod-liveness.js +80 -0
- package/dist/pod-liveness.js.map +1 -0
- package/dist/profile-menu.d.ts +7 -0
- package/dist/profile-menu.d.ts.map +1 -0
- package/dist/profile-menu.js +52 -0
- package/dist/profile-menu.js.map +1 -0
- package/dist/profiles.d.ts +23 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +66 -0
- package/dist/profiles.js.map +1 -0
- package/dist/protocol-local.d.ts +27 -0
- package/dist/protocol-local.d.ts.map +1 -0
- package/dist/protocol-local.js +12 -0
- package/dist/protocol-local.js.map +1 -0
- package/dist/pty.d.ts +26 -0
- package/dist/pty.d.ts.map +1 -0
- package/dist/pty.js +45 -0
- package/dist/pty.js.map +1 -0
- package/dist/readiness.d.ts +38 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +169 -0
- package/dist/readiness.js.map +1 -0
- package/dist/registry.d.ts +258 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +570 -0
- package/dist/registry.js.map +1 -0
- package/dist/relaunch.d.ts +52 -0
- package/dist/relaunch.d.ts.map +1 -0
- package/dist/relaunch.js +76 -0
- package/dist/relaunch.js.map +1 -0
- package/dist/restore.d.ts +165 -0
- package/dist/restore.d.ts.map +1 -0
- package/dist/restore.js +530 -0
- package/dist/restore.js.map +1 -0
- package/dist/run.d.ts +29 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +206 -0
- package/dist/run.js.map +1 -0
- package/dist/secrets.d.ts +25 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +98 -0
- package/dist/secrets.js.map +1 -0
- package/dist/session-restore.d.ts +26 -0
- package/dist/session-restore.d.ts.map +1 -0
- package/dist/session-restore.js +122 -0
- package/dist/session-restore.js.map +1 -0
- package/dist/skills-sync.d.ts +126 -0
- package/dist/skills-sync.d.ts.map +1 -0
- package/dist/skills-sync.js +255 -0
- package/dist/skills-sync.js.map +1 -0
- package/dist/smoke.d.ts +23 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +138 -0
- package/dist/smoke.js.map +1 -0
- package/dist/soft-refresh.d.ts +107 -0
- package/dist/soft-refresh.d.ts.map +1 -0
- package/dist/soft-refresh.js +426 -0
- package/dist/soft-refresh.js.map +1 -0
- package/dist/sync-status.d.ts +22 -0
- package/dist/sync-status.d.ts.map +1 -0
- package/dist/sync-status.js +41 -0
- package/dist/sync-status.js.map +1 -0
- package/dist/sync.d.ts +77 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +302 -0
- package/dist/sync.js.map +1 -0
- package/dist/throttle-signatures.d.ts +43 -0
- package/dist/throttle-signatures.d.ts.map +1 -0
- package/dist/throttle-signatures.js +116 -0
- package/dist/throttle-signatures.js.map +1 -0
- package/dist/tmux.d.ts +286 -0
- package/dist/tmux.d.ts.map +1 -0
- package/dist/tmux.js +970 -0
- package/dist/tmux.js.map +1 -0
- package/dist/tunnel.d.ts +25 -0
- package/dist/tunnel.d.ts.map +1 -0
- package/dist/tunnel.js +127 -0
- package/dist/tunnel.js.map +1 -0
- package/dist/workspace-merge.d.ts +17 -0
- package/dist/workspace-merge.d.ts.map +1 -0
- package/dist/workspace-merge.js +153 -0
- package/dist/workspace-merge.js.map +1 -0
- package/dist/workspace-sync-incremental.d.ts +64 -0
- package/dist/workspace-sync-incremental.d.ts.map +1 -0
- package/dist/workspace-sync-incremental.js +199 -0
- package/dist/workspace-sync-incremental.js.map +1 -0
- package/dist/workspace-sync.d.ts +3 -0
- package/dist/workspace-sync.d.ts.map +1 -0
- package/dist/workspace-sync.js +187 -0
- package/dist/workspace-sync.js.map +1 -0
- package/dist/workspace.d.ts +70 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +173 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +44 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
export const DEFAULT_LAYOUT = {
|
|
5
|
+
maxAgeHours: 48,
|
|
6
|
+
maxPerWindow: 12,
|
|
7
|
+
sharedWindows: 2,
|
|
8
|
+
multiSession: {},
|
|
9
|
+
multiSessionDefault: 1,
|
|
10
|
+
groups: [],
|
|
11
|
+
};
|
|
12
|
+
/** Default h2a side-window command (a2a-cli launcher contract). */
|
|
13
|
+
export const DEFAULT_H2A_COMMAND = "h2a mcp-serve --auto-open --auto-upgrade --wake local-tmux";
|
|
14
|
+
/** Default session target when none is configured/passed. */
|
|
15
|
+
export const DEFAULT_SESSION_TARGET = "scaleway-kapsule";
|
|
16
|
+
function parseTunnel(raw) {
|
|
17
|
+
if (!raw || typeof raw !== "object")
|
|
18
|
+
return undefined;
|
|
19
|
+
const t = raw;
|
|
20
|
+
if (typeof t.namespace !== "string" ||
|
|
21
|
+
typeof t.service !== "string" ||
|
|
22
|
+
typeof t.localPort !== "number" ||
|
|
23
|
+
typeof t.remotePort !== "number") {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const tunnel = {
|
|
27
|
+
namespace: t.namespace,
|
|
28
|
+
service: t.service,
|
|
29
|
+
localPort: t.localPort,
|
|
30
|
+
remotePort: t.remotePort,
|
|
31
|
+
};
|
|
32
|
+
if (typeof t.kubeconfig === "string")
|
|
33
|
+
tunnel.kubeconfig = t.kubeconfig;
|
|
34
|
+
return tunnel;
|
|
35
|
+
}
|
|
36
|
+
function parseH2a(raw) {
|
|
37
|
+
if (!raw || typeof raw !== "object")
|
|
38
|
+
return undefined;
|
|
39
|
+
const h = raw;
|
|
40
|
+
const h2a = {};
|
|
41
|
+
if (typeof h.enabled === "boolean")
|
|
42
|
+
h2a.enabled = h.enabled;
|
|
43
|
+
if (typeof h.command === "string")
|
|
44
|
+
h2a.command = h.command;
|
|
45
|
+
return Object.keys(h2a).length > 0 ? h2a : undefined;
|
|
46
|
+
}
|
|
47
|
+
function parseLlmMeshRuntime(raw) {
|
|
48
|
+
if (!raw || typeof raw !== "object")
|
|
49
|
+
return undefined;
|
|
50
|
+
const r = raw;
|
|
51
|
+
const llmMesh = {};
|
|
52
|
+
if (typeof r.enabled === "boolean")
|
|
53
|
+
llmMesh.enabled = r.enabled;
|
|
54
|
+
return Object.keys(llmMesh).length > 0 ? llmMesh : undefined;
|
|
55
|
+
}
|
|
56
|
+
function parseTmuxProfile(raw) {
|
|
57
|
+
if (!raw || typeof raw !== "object")
|
|
58
|
+
return undefined;
|
|
59
|
+
const r = raw;
|
|
60
|
+
const tmux = {};
|
|
61
|
+
if (typeof r.profile === "string" && r.profile.trim()) {
|
|
62
|
+
tmux.profile = r.profile.trim();
|
|
63
|
+
}
|
|
64
|
+
return Object.keys(tmux).length > 0 ? tmux : undefined;
|
|
65
|
+
}
|
|
66
|
+
function parsePluginMcp(raw) {
|
|
67
|
+
if (!raw || typeof raw !== "object")
|
|
68
|
+
return undefined;
|
|
69
|
+
const m = raw;
|
|
70
|
+
if (typeof m.name !== "string" ||
|
|
71
|
+
typeof m.command !== "string" ||
|
|
72
|
+
!Array.isArray(m.args) ||
|
|
73
|
+
!m.args.every((a) => typeof a === "string")) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const mcp = {
|
|
77
|
+
name: m.name,
|
|
78
|
+
command: m.command,
|
|
79
|
+
args: m.args,
|
|
80
|
+
};
|
|
81
|
+
if (typeof m.scriptRel === "string")
|
|
82
|
+
mcp.scriptRel = m.scriptRel;
|
|
83
|
+
return mcp;
|
|
84
|
+
}
|
|
85
|
+
function parsePlugins(raw) {
|
|
86
|
+
if (!Array.isArray(raw))
|
|
87
|
+
return undefined;
|
|
88
|
+
const plugins = [];
|
|
89
|
+
for (const item of raw) {
|
|
90
|
+
if (!item || typeof item !== "object")
|
|
91
|
+
continue;
|
|
92
|
+
const p = item;
|
|
93
|
+
if (typeof p.pkg !== "string" ||
|
|
94
|
+
typeof p.version !== "string" ||
|
|
95
|
+
!Array.isArray(p.mcp)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const mcp = p.mcp
|
|
99
|
+
.map(parsePluginMcp)
|
|
100
|
+
.filter((m) => m !== undefined);
|
|
101
|
+
const entry = { pkg: p.pkg, version: p.version, mcp };
|
|
102
|
+
const install = parsePluginInstall(p.install);
|
|
103
|
+
if (install)
|
|
104
|
+
entry.install = install;
|
|
105
|
+
plugins.push(entry);
|
|
106
|
+
}
|
|
107
|
+
return plugins;
|
|
108
|
+
}
|
|
109
|
+
function parsePluginInstall(raw) {
|
|
110
|
+
if (!raw || typeof raw !== "object")
|
|
111
|
+
return undefined;
|
|
112
|
+
const i = raw;
|
|
113
|
+
if (i.method !== "npm" && i.method !== "curl" && i.method !== "script") {
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
const install = { method: i.method };
|
|
117
|
+
if (typeof i.spec === "string")
|
|
118
|
+
install.spec = i.spec;
|
|
119
|
+
return install;
|
|
120
|
+
}
|
|
121
|
+
// Resolved lazily so tests can redirect the config home via
|
|
122
|
+
// REMOTE_CLI_CONFIG_HOME without clobbering the real ~/.config.
|
|
123
|
+
function configHome() {
|
|
124
|
+
return process.env.REMOTE_CLI_CONFIG_HOME ?? homedir();
|
|
125
|
+
}
|
|
126
|
+
export function resolveConfigPath() {
|
|
127
|
+
return join(configHome(), ".config", "sentropic", "remote-cli", "config.json");
|
|
128
|
+
}
|
|
129
|
+
export function normalizeRemoteUrl(rawUrl) {
|
|
130
|
+
const trimmed = rawUrl.trim();
|
|
131
|
+
if (!trimmed) {
|
|
132
|
+
throw new Error("Remote URL cannot be empty.");
|
|
133
|
+
}
|
|
134
|
+
const parsed = new URL(trimmed);
|
|
135
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
136
|
+
throw new Error(`Unsupported remote URL protocol "${parsed.protocol}". Use http:// or https://.`);
|
|
137
|
+
}
|
|
138
|
+
return trimmed.replace(/\/+$/, "");
|
|
139
|
+
}
|
|
140
|
+
export function readRemoteConfig() {
|
|
141
|
+
try {
|
|
142
|
+
const raw = readFileSync(resolveConfigPath(), "utf8");
|
|
143
|
+
const parsed = JSON.parse(raw);
|
|
144
|
+
if (parsed && typeof parsed === "object") {
|
|
145
|
+
const config = {};
|
|
146
|
+
if (typeof parsed.defaultRemote === "string")
|
|
147
|
+
config.defaultRemote = parsed.defaultRemote;
|
|
148
|
+
if (typeof parsed.token === "string")
|
|
149
|
+
config.token = parsed.token;
|
|
150
|
+
if (typeof parsed.defaultTarget === "string")
|
|
151
|
+
config.defaultTarget = parsed.defaultTarget;
|
|
152
|
+
if (Array.isArray(parsed.defaultTools) &&
|
|
153
|
+
parsed.defaultTools.every((t) => typeof t === "string")) {
|
|
154
|
+
config.defaultTools = parsed.defaultTools;
|
|
155
|
+
}
|
|
156
|
+
const tunnel = parseTunnel(parsed.tunnel);
|
|
157
|
+
if (tunnel)
|
|
158
|
+
config.tunnel = tunnel;
|
|
159
|
+
if (parsed.layout && typeof parsed.layout === "object")
|
|
160
|
+
config.layout = parsed.layout;
|
|
161
|
+
const plugins = parsePlugins(parsed.plugins);
|
|
162
|
+
if (plugins)
|
|
163
|
+
config.plugins = plugins;
|
|
164
|
+
const h2a = parseH2a(parsed.h2a);
|
|
165
|
+
if (h2a)
|
|
166
|
+
config.h2a = h2a;
|
|
167
|
+
const llmMesh = parseLlmMeshRuntime(parsed.llmMesh);
|
|
168
|
+
if (llmMesh)
|
|
169
|
+
config.llmMesh = llmMesh;
|
|
170
|
+
const tmux = parseTmuxProfile(parsed.tmux);
|
|
171
|
+
if (tmux)
|
|
172
|
+
config.tmux = tmux;
|
|
173
|
+
if (typeof parsed.maxConcurrent === "number" &&
|
|
174
|
+
Number.isFinite(parsed.maxConcurrent) &&
|
|
175
|
+
parsed.maxConcurrent > 0) {
|
|
176
|
+
config.maxConcurrent = Math.trunc(parsed.maxConcurrent);
|
|
177
|
+
}
|
|
178
|
+
return config;
|
|
179
|
+
}
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
if (error.code === "ENOENT")
|
|
184
|
+
return {};
|
|
185
|
+
throw new Error(`failed to read remote config: ${error.message}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export function writeRemoteConfig(config) {
|
|
189
|
+
const path = resolveConfigPath();
|
|
190
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
191
|
+
writeFileSync(path, JSON.stringify(config, null, 2), "utf8");
|
|
192
|
+
}
|
|
193
|
+
export function getDefaultRemote() {
|
|
194
|
+
const config = readRemoteConfig();
|
|
195
|
+
return config.defaultRemote;
|
|
196
|
+
}
|
|
197
|
+
export function setDefaultRemote(rawUrl) {
|
|
198
|
+
const defaultRemote = normalizeRemoteUrl(rawUrl);
|
|
199
|
+
writeRemoteConfig({ ...readRemoteConfig(), defaultRemote });
|
|
200
|
+
return defaultRemote;
|
|
201
|
+
}
|
|
202
|
+
export function clearDefaultRemote() {
|
|
203
|
+
const { defaultRemote: _drop, ...rest } = readRemoteConfig();
|
|
204
|
+
writeRemoteConfig(rest);
|
|
205
|
+
}
|
|
206
|
+
export function getDefaultTarget() {
|
|
207
|
+
const configured = readRemoteConfig().defaultTarget;
|
|
208
|
+
return configured ?? DEFAULT_SESSION_TARGET;
|
|
209
|
+
}
|
|
210
|
+
export function setDefaultTarget(value) {
|
|
211
|
+
writeRemoteConfig({ ...readRemoteConfig(), defaultTarget: value });
|
|
212
|
+
}
|
|
213
|
+
export function getDefaultTools() {
|
|
214
|
+
return readRemoteConfig().defaultTools ?? [];
|
|
215
|
+
}
|
|
216
|
+
export function setDefaultTools(tools) {
|
|
217
|
+
writeRemoteConfig({ ...readRemoteConfig(), defaultTools: tools });
|
|
218
|
+
}
|
|
219
|
+
/** Plugins installed via `remote plugin add` (mirrors getDefaultTools). */
|
|
220
|
+
export function getPlugins() {
|
|
221
|
+
return readRemoteConfig().plugins ?? [];
|
|
222
|
+
}
|
|
223
|
+
export function setPlugins(plugins) {
|
|
224
|
+
writeRemoteConfig({ ...readRemoteConfig(), plugins });
|
|
225
|
+
}
|
|
226
|
+
/** h2a config merged with defaults (enabled=false, default mcp-serve command). */
|
|
227
|
+
export function getH2aConfig() {
|
|
228
|
+
const raw = readRemoteConfig().h2a ?? {};
|
|
229
|
+
return {
|
|
230
|
+
enabled: raw.enabled ?? false,
|
|
231
|
+
command: raw.command ?? DEFAULT_H2A_COMMAND,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
export function setH2aConfig(h2a) {
|
|
235
|
+
writeRemoteConfig({ ...readRemoteConfig(), h2a });
|
|
236
|
+
}
|
|
237
|
+
export function getLlmMeshRuntimeConfig() {
|
|
238
|
+
const raw = readRemoteConfig().llmMesh ?? {};
|
|
239
|
+
return {
|
|
240
|
+
enabled: raw.enabled ?? false,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
export function setLlmMeshRuntimeConfig(llmMesh) {
|
|
244
|
+
writeRemoteConfig({ ...readRemoteConfig(), llmMesh });
|
|
245
|
+
}
|
|
246
|
+
export function getTmuxProfileConfig() {
|
|
247
|
+
const raw = readRemoteConfig().tmux ?? {};
|
|
248
|
+
return { profile: raw.profile ?? "remote" };
|
|
249
|
+
}
|
|
250
|
+
export function setTmuxProfileConfig(tmux) {
|
|
251
|
+
writeRemoteConfig({ ...readRemoteConfig(), tmux });
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* P4 — the configured default concurrency cap for delegated jobs, or undefined
|
|
255
|
+
* when unset (the caller falls back to DEFAULT_MAX_CONCURRENT). The env override
|
|
256
|
+
* `REMOTE_MAX_CONCURRENT` wins so a conductor window can be tuned without writing
|
|
257
|
+
* config.
|
|
258
|
+
*/
|
|
259
|
+
export function getMaxConcurrent() {
|
|
260
|
+
const env = process.env.REMOTE_MAX_CONCURRENT;
|
|
261
|
+
if (env !== undefined) {
|
|
262
|
+
const n = Number.parseInt(env, 10);
|
|
263
|
+
if (Number.isFinite(n) && n > 0)
|
|
264
|
+
return n;
|
|
265
|
+
}
|
|
266
|
+
return readRemoteConfig().maxConcurrent;
|
|
267
|
+
}
|
|
268
|
+
export function setMaxConcurrent(value) {
|
|
269
|
+
writeRemoteConfig({ ...readRemoteConfig(), maxConcurrent: value });
|
|
270
|
+
}
|
|
271
|
+
/** Generous default age (hours) after which a stuck `running` job is swept → failed. */
|
|
272
|
+
export const DEFAULT_JOB_MAX_AGE_HOURS = 24;
|
|
273
|
+
/**
|
|
274
|
+
* Max age (hours) a delegated job may stay `running`/`awaiting-decision` before
|
|
275
|
+
* the reconciler sweeps it to `failed` (M2 — convergence: a job whose hook +
|
|
276
|
+
* liveness signal were both lost would otherwise occupy a slot forever).
|
|
277
|
+
* `REMOTE_JOB_MAX_AGE_HOURS` overrides; default is generous (24h) so a genuinely
|
|
278
|
+
* long-running interactive job is never killed prematurely.
|
|
279
|
+
*/
|
|
280
|
+
export function getJobMaxAgeHours() {
|
|
281
|
+
const env = process.env.REMOTE_JOB_MAX_AGE_HOURS;
|
|
282
|
+
if (env !== undefined) {
|
|
283
|
+
const n = Number.parseFloat(env);
|
|
284
|
+
if (Number.isFinite(n) && n > 0)
|
|
285
|
+
return n;
|
|
286
|
+
}
|
|
287
|
+
return DEFAULT_JOB_MAX_AGE_HOURS;
|
|
288
|
+
}
|
|
289
|
+
export function getTunnel() {
|
|
290
|
+
return readRemoteConfig().tunnel;
|
|
291
|
+
}
|
|
292
|
+
export function setTunnel(tunnel) {
|
|
293
|
+
writeRemoteConfig({ ...readRemoteConfig(), tunnel });
|
|
294
|
+
}
|
|
295
|
+
export function clearTunnel() {
|
|
296
|
+
const { tunnel: _drop, ...rest } = readRemoteConfig();
|
|
297
|
+
writeRemoteConfig(rest);
|
|
298
|
+
}
|
|
299
|
+
/** Layout config merged with defaults (used by `remote restore`). */
|
|
300
|
+
export function getLayoutConfig() {
|
|
301
|
+
const raw = readRemoteConfig().layout ?? {};
|
|
302
|
+
return {
|
|
303
|
+
maxAgeHours: typeof raw.maxAgeHours === "number"
|
|
304
|
+
? raw.maxAgeHours
|
|
305
|
+
: DEFAULT_LAYOUT.maxAgeHours,
|
|
306
|
+
maxPerWindow: typeof raw.maxPerWindow === "number"
|
|
307
|
+
? raw.maxPerWindow
|
|
308
|
+
: DEFAULT_LAYOUT.maxPerWindow,
|
|
309
|
+
sharedWindows: typeof raw.sharedWindows === "number"
|
|
310
|
+
? raw.sharedWindows
|
|
311
|
+
: DEFAULT_LAYOUT.sharedWindows,
|
|
312
|
+
multiSession: raw.multiSession && typeof raw.multiSession === "object"
|
|
313
|
+
? raw.multiSession
|
|
314
|
+
: DEFAULT_LAYOUT.multiSession,
|
|
315
|
+
multiSessionDefault: typeof raw.multiSessionDefault === "number"
|
|
316
|
+
? raw.multiSessionDefault
|
|
317
|
+
: DEFAULT_LAYOUT.multiSessionDefault,
|
|
318
|
+
groups: Array.isArray(raw.groups) ? raw.groups : DEFAULT_LAYOUT.groups,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
export function setLayoutConfig(layout) {
|
|
322
|
+
writeRemoteConfig({ ...readRemoteConfig(), layout });
|
|
323
|
+
}
|
|
324
|
+
export function getToken() {
|
|
325
|
+
return process.env.REMOTE_TOKEN ?? readRemoteConfig().token;
|
|
326
|
+
}
|
|
327
|
+
export function setToken(value) {
|
|
328
|
+
writeRemoteConfig({ ...readRemoteConfig(), token: value });
|
|
329
|
+
}
|
|
330
|
+
export function authHeaders() {
|
|
331
|
+
const token = getToken();
|
|
332
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
333
|
+
}
|
|
334
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-writer guard per conversation (WP5).
|
|
3
|
+
*
|
|
4
|
+
* A claude/codex conversation is one append-only .jsonl — TWO CLIs resuming
|
|
5
|
+
* the same convId at once interleave their appends and corrupt it (the user's
|
|
6
|
+
* critical asset). Before `remote run -r <conv>` / `remote migrate forward
|
|
7
|
+
* -r <conv>` start a new writer, convOwners() lists every LIVE writer already
|
|
8
|
+
* holding that conversation:
|
|
9
|
+
*
|
|
10
|
+
* (a) live local registry entries (registry.ts) with the same convId —
|
|
11
|
+
* another tmux session or a hook-enrolled plain-terminal CLI,
|
|
12
|
+
* (b) live remote sessions whose cliSessionId (reported by the session-agent)
|
|
13
|
+
* matches; a remote session WITHOUT a cliSessionId but running on the
|
|
14
|
+
* same workspacePath is flagged as a SUSPECT (warning, not refusal).
|
|
15
|
+
*
|
|
16
|
+
* guardConvWriters() is the shared wiring: prints the warnings/refusal and
|
|
17
|
+
* tells the caller whether to proceed (--force overrides, loudly).
|
|
18
|
+
*/
|
|
19
|
+
import { type LivenessOpts } from "./registry.js";
|
|
20
|
+
export type ConvOwnerWhere = "local-tmux" | "local" | "remote";
|
|
21
|
+
export type ConvOwner = {
|
|
22
|
+
where: ConvOwnerWhere;
|
|
23
|
+
/** Short handle: tmux slug, registry label, or remote session id/name. */
|
|
24
|
+
label: string;
|
|
25
|
+
/** Human sentence: what holds the conversation and how to release it. */
|
|
26
|
+
detail: string;
|
|
27
|
+
/** true = cwd-only heuristic (no cliSessionId) — warn, do not refuse. */
|
|
28
|
+
suspect?: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** The subset of listRemoteSessions() rows the guard needs. */
|
|
31
|
+
export type RemoteSessionLite = {
|
|
32
|
+
id: string;
|
|
33
|
+
displayName?: string;
|
|
34
|
+
cliSessionId?: string;
|
|
35
|
+
workspacePath?: string;
|
|
36
|
+
};
|
|
37
|
+
export type ConvOwnersOpts = LivenessOpts & {
|
|
38
|
+
/** Registry file override (tests). */
|
|
39
|
+
registryPath?: string;
|
|
40
|
+
/** Registry entry id to ignore (the entry the caller is creating/reviving). */
|
|
41
|
+
excludeId?: string;
|
|
42
|
+
/** Live remote sessions, already fetched by the caller (omit = no remote check). */
|
|
43
|
+
remoteSessions?: ReadonlyArray<RemoteSessionLite>;
|
|
44
|
+
/** Local project path — enables the workspacePath "suspect" heuristic. */
|
|
45
|
+
cwd?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Every live writer currently holding convId. Entries with suspect=true are
|
|
49
|
+
* heuristic matches (same workspacePath, no cliSessionId) — warning-grade only.
|
|
50
|
+
*/
|
|
51
|
+
export declare function convOwners(convId: string, opts?: ConvOwnersOpts): ConvOwner[];
|
|
52
|
+
/** Multi-line refusal message for hard (non-suspect) conflicts. */
|
|
53
|
+
export declare function formatConvConflict(convId: string, owners: ReadonlyArray<ConvOwner>): string;
|
|
54
|
+
export type GuardConvWritersArgs = LivenessOpts & {
|
|
55
|
+
convId: string;
|
|
56
|
+
/** Local project path (suspect heuristic for remote sessions). */
|
|
57
|
+
cwd: string;
|
|
58
|
+
/** Registry entry id to ignore (the entry the caller is creating/reviving). */
|
|
59
|
+
excludeId?: string;
|
|
60
|
+
/** Override the refusal (still warns). */
|
|
61
|
+
force?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Best-effort fetch of live remote sessions; a throw (no remote configured,
|
|
64
|
+
* tunnel down) silently degrades the guard to local-registry-only.
|
|
65
|
+
*/
|
|
66
|
+
fetchRemoteSessions?: () => Promise<ReadonlyArray<RemoteSessionLite>>;
|
|
67
|
+
/** Registry file override (tests). */
|
|
68
|
+
registryPath?: string;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Shared wiring for `remote run -r` / `remote migrate forward -r`. Prints
|
|
72
|
+
* warnings (suspects, --force override) and the refusal itself; returns
|
|
73
|
+
* true when the caller may start the new writer.
|
|
74
|
+
*/
|
|
75
|
+
export declare function guardConvWriters(args: GuardConvWritersArgs): Promise<boolean>;
|
|
76
|
+
//# sourceMappingURL=conv-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conv-guard.d.ts","sourceRoot":"","sources":["../src/conv-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAY,KAAK,YAAY,EAAsB,MAAM,eAAe,CAAC;AAEhF,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,+DAA+D;AAC/D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG;IAC1C,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,cAAc,CAAC,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAClD,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAuBF;;;GAGG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,cAAmB,GACxB,SAAS,EAAE,CAsCb;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,GAC/B,MAAM,CAQR;AAED,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,GAAG,EAAE,MAAM,CAAC;IACZ,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,OAAO,CAAC,CAkClB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-writer guard per conversation (WP5).
|
|
3
|
+
*
|
|
4
|
+
* A claude/codex conversation is one append-only .jsonl — TWO CLIs resuming
|
|
5
|
+
* the same convId at once interleave their appends and corrupt it (the user's
|
|
6
|
+
* critical asset). Before `remote run -r <conv>` / `remote migrate forward
|
|
7
|
+
* -r <conv>` start a new writer, convOwners() lists every LIVE writer already
|
|
8
|
+
* holding that conversation:
|
|
9
|
+
*
|
|
10
|
+
* (a) live local registry entries (registry.ts) with the same convId —
|
|
11
|
+
* another tmux session or a hook-enrolled plain-terminal CLI,
|
|
12
|
+
* (b) live remote sessions whose cliSessionId (reported by the session-agent)
|
|
13
|
+
* matches; a remote session WITHOUT a cliSessionId but running on the
|
|
14
|
+
* same workspacePath is flagged as a SUSPECT (warning, not refusal).
|
|
15
|
+
*
|
|
16
|
+
* guardConvWriters() is the shared wiring: prints the warnings/refusal and
|
|
17
|
+
* tells the caller whether to proceed (--force overrides, loudly).
|
|
18
|
+
*/
|
|
19
|
+
import { listLive } from "./registry.js";
|
|
20
|
+
function ownerFromEntry(e) {
|
|
21
|
+
if (e.kind === "local-tmux") {
|
|
22
|
+
const slug = e.label ?? e.id;
|
|
23
|
+
return {
|
|
24
|
+
where: "local-tmux",
|
|
25
|
+
label: slug,
|
|
26
|
+
detail: `local tmux session ${e.tmuxSession ?? `remote-${e.id}`} (${e.tool}, cwd ${e.cwd}) — stop it first: remote stop ${slug}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
where: "local",
|
|
31
|
+
label: e.label ?? e.id.slice(0, 12),
|
|
32
|
+
detail: `local ${e.tool} process${e.pid !== undefined ? ` (pid ${e.pid})` : ""} in ${e.cwd} — exit that CLI first`,
|
|
33
|
+
// A no-pid hook entry is UNVERIFIABLE (no process to probe): a crash leaves
|
|
34
|
+
// it "live" forever. Demote it to a SUSPECT (warn) so it never hard-blocks
|
|
35
|
+
// a relaunch; only verifiable writers (live tmux / pid+cmdline / remote)
|
|
36
|
+
// refuse. A pid'd entry that reached here passed the liveness check → hard.
|
|
37
|
+
...(e.pid === undefined ? { suspect: true } : {}),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Every live writer currently holding convId. Entries with suspect=true are
|
|
42
|
+
* heuristic matches (same workspacePath, no cliSessionId) — warning-grade only.
|
|
43
|
+
*/
|
|
44
|
+
export function convOwners(convId, opts = {}) {
|
|
45
|
+
const owners = [];
|
|
46
|
+
const live = listLive({
|
|
47
|
+
...(opts.tmuxHasSession ? { tmuxHasSession: opts.tmuxHasSession } : {}),
|
|
48
|
+
...(opts.pidAlive ? { pidAlive: opts.pidAlive } : {}),
|
|
49
|
+
...(opts.bootTimeMs !== undefined ? { bootTimeMs: opts.bootTimeMs } : {}),
|
|
50
|
+
...(opts.processCmdline ? { processCmdline: opts.processCmdline } : {}),
|
|
51
|
+
...(opts.registryPath ? { path: opts.registryPath } : {}),
|
|
52
|
+
});
|
|
53
|
+
for (const e of live) {
|
|
54
|
+
if (e.convId !== convId)
|
|
55
|
+
continue;
|
|
56
|
+
if (opts.excludeId !== undefined && e.id === opts.excludeId)
|
|
57
|
+
continue;
|
|
58
|
+
// kind "remote" registry entries can be stale (the registry cannot probe
|
|
59
|
+
// the cluster) — opts.remoteSessions, fetched live, is authoritative.
|
|
60
|
+
if (e.kind === "remote")
|
|
61
|
+
continue;
|
|
62
|
+
owners.push(ownerFromEntry(e));
|
|
63
|
+
}
|
|
64
|
+
for (const s of opts.remoteSessions ?? []) {
|
|
65
|
+
if (s.cliSessionId === convId) {
|
|
66
|
+
owners.push({
|
|
67
|
+
where: "remote",
|
|
68
|
+
label: s.displayName ?? s.id,
|
|
69
|
+
detail: `remote session ${s.id}${s.workspacePath ? ` (${s.workspacePath})` : ""} is on this conversation — stop it first: remote stop ${s.id}`,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
else if (s.cliSessionId === undefined &&
|
|
73
|
+
opts.cwd !== undefined &&
|
|
74
|
+
s.workspacePath === opts.cwd) {
|
|
75
|
+
owners.push({
|
|
76
|
+
where: "remote",
|
|
77
|
+
label: s.displayName ?? s.id,
|
|
78
|
+
detail: `remote session ${s.id} runs on the same path (${s.workspacePath}) and MAY hold this conversation (no cliSessionId reported yet)`,
|
|
79
|
+
suspect: true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return owners;
|
|
84
|
+
}
|
|
85
|
+
/** Multi-line refusal message for hard (non-suspect) conflicts. */
|
|
86
|
+
export function formatConvConflict(convId, owners) {
|
|
87
|
+
const lines = owners.map((o) => ` - [${o.where}] ${o.label}: ${o.detail}`);
|
|
88
|
+
return (`[remote] conversation ${convId} already has a live writer:\n` +
|
|
89
|
+
`${lines.join("\n")}\n` +
|
|
90
|
+
`[remote] two CLIs appending to the same conversation .jsonl corrupt it — ` +
|
|
91
|
+
`stop the other writer first, or pass --force to take over anyway.\n`);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Shared wiring for `remote run -r` / `remote migrate forward -r`. Prints
|
|
95
|
+
* warnings (suspects, --force override) and the refusal itself; returns
|
|
96
|
+
* true when the caller may start the new writer.
|
|
97
|
+
*/
|
|
98
|
+
export async function guardConvWriters(args) {
|
|
99
|
+
let remoteSessions;
|
|
100
|
+
if (args.fetchRemoteSessions) {
|
|
101
|
+
try {
|
|
102
|
+
remoteSessions = await args.fetchRemoteSessions();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// remote unreachable — degrade to the local registry (best-effort)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const owners = convOwners(args.convId, {
|
|
109
|
+
cwd: args.cwd,
|
|
110
|
+
...(args.excludeId !== undefined ? { excludeId: args.excludeId } : {}),
|
|
111
|
+
...(remoteSessions !== undefined ? { remoteSessions } : {}),
|
|
112
|
+
...(args.registryPath ? { registryPath: args.registryPath } : {}),
|
|
113
|
+
...(args.tmuxHasSession ? { tmuxHasSession: args.tmuxHasSession } : {}),
|
|
114
|
+
...(args.pidAlive ? { pidAlive: args.pidAlive } : {}),
|
|
115
|
+
...(args.bootTimeMs !== undefined ? { bootTimeMs: args.bootTimeMs } : {}),
|
|
116
|
+
...(args.processCmdline ? { processCmdline: args.processCmdline } : {}),
|
|
117
|
+
});
|
|
118
|
+
const hard = owners.filter((o) => !o.suspect);
|
|
119
|
+
for (const s of owners.filter((o) => o.suspect)) {
|
|
120
|
+
process.stderr.write(`[remote] warning: ${s.detail} — make sure it is not resuming conversation ${args.convId}.\n`);
|
|
121
|
+
}
|
|
122
|
+
if (hard.length === 0)
|
|
123
|
+
return true;
|
|
124
|
+
if (args.force) {
|
|
125
|
+
process.stderr.write(`[remote] warning: --force — taking over conversation ${args.convId} despite ${hard.length} live writer(s); concurrent writes WILL corrupt the .jsonl.\n`);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
process.stderr.write(formatConvConflict(args.convId, hard));
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=conv-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conv-guard.js","sourceRoot":"","sources":["../src/conv-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation alignment check: is a remote session's conversation log in sync
|
|
3
|
+
* with the latest LOCAL conversation for the same project? Compares metrics only
|
|
4
|
+
* (id, bytes, lines, sha256) — local read directly, remote computed in-Pod via
|
|
5
|
+
* kubectl (only the numbers cross the wire, never the conversation content).
|
|
6
|
+
*/
|
|
7
|
+
export type ConvStat = {
|
|
8
|
+
convId: string;
|
|
9
|
+
bytes: number;
|
|
10
|
+
lines: number;
|
|
11
|
+
sha: string;
|
|
12
|
+
};
|
|
13
|
+
/** claude's cwd→project-dir encoding (slashes → dashes). */
|
|
14
|
+
export declare function encodeCwd(cwd: string): string;
|
|
15
|
+
/** Newest local conversation for a project path (or undefined). */
|
|
16
|
+
export declare function localConvStat(workspacePath: string, home?: string): ConvStat | undefined;
|
|
17
|
+
/** Newest remote conversation for a session (computed in-Pod, metrics only). */
|
|
18
|
+
export declare function remoteConvStat(sessionId: string, workspacePath: string): ConvStat | undefined;
|
|
19
|
+
export type AlignVerdict = {
|
|
20
|
+
state: "in-sync" | "local-ahead" | "remote-ahead" | "diverged" | "missing";
|
|
21
|
+
detail: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function alignment(local: ConvStat | undefined, remote: ConvStat | undefined): AlignVerdict;
|
|
24
|
+
//# sourceMappingURL=convsync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convsync.d.ts","sourceRoot":"","sources":["../src/convsync.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAMD,mEAAmE;AACnE,wBAAgB,aAAa,CAC3B,aAAa,EAAE,MAAM,EACrB,IAAI,GAAE,MAAkB,GACvB,QAAQ,GAAG,SAAS,CAmBtB;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,GACpB,QAAQ,GAAG,SAAS,CAgCtB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,SAAS,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,CAAC;IAC3E,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,SAAS,CACvB,KAAK,EAAE,QAAQ,GAAG,SAAS,EAC3B,MAAM,EAAE,QAAQ,GAAG,SAAS,GAC3B,YAAY,CA0Bd"}
|