@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/run.js
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { serve } from "@hono/node-server";
|
|
2
|
+
import { createNodeWebSocket } from "@hono/node-ws";
|
|
3
|
+
import { REMOTE_PROTOCOL_VERSION, REMOTE_SCHEMA_VERSION, } from "./protocol-local.js";
|
|
4
|
+
import { Hono } from "hono";
|
|
5
|
+
import { streamSSE } from "hono/streaming";
|
|
6
|
+
import { resolveProfile, withResume } from "./profiles.js";
|
|
7
|
+
import { nodePtySpawner } from "./pty.js";
|
|
8
|
+
function defaultRandomId(prefix) {
|
|
9
|
+
const random = Math.floor(Math.random() * 1e12)
|
|
10
|
+
.toString(36)
|
|
11
|
+
.padStart(8, "0");
|
|
12
|
+
return `${prefix}-${random}`;
|
|
13
|
+
}
|
|
14
|
+
const CONTROL_PLANE_ACTOR = {
|
|
15
|
+
id: "remote-cli",
|
|
16
|
+
kind: "control-plane",
|
|
17
|
+
displayName: "Remote CLI",
|
|
18
|
+
};
|
|
19
|
+
const AGENT_ACTOR = {
|
|
20
|
+
id: "remote-cli-agent",
|
|
21
|
+
kind: "session-agent",
|
|
22
|
+
displayName: "Remote CLI Agent",
|
|
23
|
+
};
|
|
24
|
+
function buildEnvelope(runtime, type, payload, randomId, clock, actor = AGENT_ACTOR) {
|
|
25
|
+
return {
|
|
26
|
+
protocolVersion: REMOTE_PROTOCOL_VERSION,
|
|
27
|
+
schemaVersion: REMOTE_SCHEMA_VERSION,
|
|
28
|
+
eventId: randomId("evt"),
|
|
29
|
+
sessionId: runtime.sessionId,
|
|
30
|
+
sequence: runtime.sequence++,
|
|
31
|
+
type,
|
|
32
|
+
occurredAt: clock().toISOString(),
|
|
33
|
+
correlationId: `cli-${runtime.sessionId}`,
|
|
34
|
+
actor,
|
|
35
|
+
payload,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export async function run(options) {
|
|
39
|
+
const profile = withResume(resolveProfile(options.profile), options.resume);
|
|
40
|
+
const randomId = options.randomId ?? defaultRandomId;
|
|
41
|
+
const clock = options.clock ?? (() => new Date());
|
|
42
|
+
const spawner = options.spawner ?? nodePtySpawner;
|
|
43
|
+
const stdin = options.stdin ?? process.stdin;
|
|
44
|
+
const stdout = options.stdout ?? process.stdout;
|
|
45
|
+
const cwd = options.cwd ?? process.cwd();
|
|
46
|
+
const initialCols = options.initialSize?.cols ?? stdout.columns ?? 80;
|
|
47
|
+
const initialRows = options.initialSize?.rows ?? stdout.rows ?? 24;
|
|
48
|
+
const startupArgs = options.startupArgs ?? [];
|
|
49
|
+
const handle = spawner({
|
|
50
|
+
command: profile.command,
|
|
51
|
+
args: [...profile.args, ...startupArgs],
|
|
52
|
+
cwd,
|
|
53
|
+
env: { ...(options.env ?? process.env) },
|
|
54
|
+
cols: initialCols,
|
|
55
|
+
rows: initialRows,
|
|
56
|
+
});
|
|
57
|
+
const sessionId = randomId("sess");
|
|
58
|
+
const terminalId = randomId("term");
|
|
59
|
+
const subscribers = new Set();
|
|
60
|
+
const runtime = {
|
|
61
|
+
sessionId,
|
|
62
|
+
profile,
|
|
63
|
+
handle,
|
|
64
|
+
sequence: 0,
|
|
65
|
+
exited: false,
|
|
66
|
+
};
|
|
67
|
+
const broadcast = (envelope) => {
|
|
68
|
+
for (const subscriber of subscribers)
|
|
69
|
+
subscriber(envelope);
|
|
70
|
+
};
|
|
71
|
+
// Forward PTY output to host stdout AND broadcast as terminal.output.
|
|
72
|
+
handle.onData((chunk) => {
|
|
73
|
+
stdout.write(chunk);
|
|
74
|
+
broadcast(buildEnvelope(runtime, "terminal.output", {
|
|
75
|
+
terminalId,
|
|
76
|
+
stream: "stdout",
|
|
77
|
+
data: chunk,
|
|
78
|
+
encoding: "utf8",
|
|
79
|
+
}, randomId, clock));
|
|
80
|
+
});
|
|
81
|
+
// Forward host stdin to the PTY.
|
|
82
|
+
if (stdin.isTTY) {
|
|
83
|
+
stdin.setRawMode?.(true);
|
|
84
|
+
}
|
|
85
|
+
stdin.resume();
|
|
86
|
+
stdin.on("data", (data) => {
|
|
87
|
+
const text = typeof data === "string" ? data : data.toString("utf8");
|
|
88
|
+
handle.write(text);
|
|
89
|
+
});
|
|
90
|
+
// Resize PTY when the host terminal resizes.
|
|
91
|
+
const onResize = () => {
|
|
92
|
+
handle.resize(stdout.columns ?? initialCols, stdout.rows ?? initialRows);
|
|
93
|
+
};
|
|
94
|
+
stdout.on?.("resize", onResize);
|
|
95
|
+
// Open control-plane in-process for remote attach.
|
|
96
|
+
const app = new Hono();
|
|
97
|
+
const nodeWs = createNodeWebSocket({ app });
|
|
98
|
+
app.get("/healthz", (c) => c.json({ ok: true, sessionId, profile: profile.profile }));
|
|
99
|
+
app.get(`/sessions/${sessionId}`, (c) => c.json({
|
|
100
|
+
session: {
|
|
101
|
+
id: sessionId,
|
|
102
|
+
profile: profile.profile,
|
|
103
|
+
target: "k3s",
|
|
104
|
+
workspacePath: cwd,
|
|
105
|
+
createdAt: clock().toISOString(),
|
|
106
|
+
createdBy: CONTROL_PLANE_ACTOR,
|
|
107
|
+
},
|
|
108
|
+
}));
|
|
109
|
+
app.get(`/sessions/${sessionId}/events`, (c) => {
|
|
110
|
+
return streamSSE(c, async (stream) => {
|
|
111
|
+
const queue = [];
|
|
112
|
+
let notify = null;
|
|
113
|
+
const subscriber = (envelope) => {
|
|
114
|
+
queue.push(envelope);
|
|
115
|
+
const wake = notify;
|
|
116
|
+
notify = null;
|
|
117
|
+
wake?.();
|
|
118
|
+
};
|
|
119
|
+
subscribers.add(subscriber);
|
|
120
|
+
stream.onAbort(() => {
|
|
121
|
+
subscribers.delete(subscriber);
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
while (!stream.aborted) {
|
|
125
|
+
while (queue.length > 0 && !stream.aborted) {
|
|
126
|
+
const envelope = queue.shift();
|
|
127
|
+
if (!envelope)
|
|
128
|
+
break;
|
|
129
|
+
await stream.writeSSE({
|
|
130
|
+
event: envelope.type,
|
|
131
|
+
data: JSON.stringify(envelope),
|
|
132
|
+
id: envelope.eventId,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (stream.aborted)
|
|
136
|
+
break;
|
|
137
|
+
await new Promise((resolve) => {
|
|
138
|
+
notify = resolve;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
subscribers.delete(subscriber);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
app.post(`/sessions/${sessionId}/terminal/input`, async (c) => {
|
|
148
|
+
const body = (await c.req.json());
|
|
149
|
+
if (typeof body.data === "string")
|
|
150
|
+
handle.write(body.data);
|
|
151
|
+
return c.json({ accepted: true }, 202);
|
|
152
|
+
});
|
|
153
|
+
const port = options.port ?? 0;
|
|
154
|
+
const server = serve({ fetch: app.fetch, port, hostname: "127.0.0.1" });
|
|
155
|
+
nodeWs.injectWebSocket(server);
|
|
156
|
+
let actualPort = port;
|
|
157
|
+
const address = server.address();
|
|
158
|
+
if (address && typeof address === "object") {
|
|
159
|
+
actualPort = address.port;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
await new Promise((resolve, reject) => {
|
|
163
|
+
server.once("listening", () => {
|
|
164
|
+
const addr = server.address();
|
|
165
|
+
if (addr && typeof addr === "object")
|
|
166
|
+
actualPort = addr.port;
|
|
167
|
+
resolve();
|
|
168
|
+
});
|
|
169
|
+
server.once("error", reject);
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// Emit terminal.opened announcement.
|
|
173
|
+
broadcast(buildEnvelope(runtime, "terminal.opened", { terminalId, shell: profile.command }, randomId, clock));
|
|
174
|
+
// Wire exit.
|
|
175
|
+
let resolveExit;
|
|
176
|
+
const exit = new Promise((resolve) => {
|
|
177
|
+
resolveExit = resolve;
|
|
178
|
+
});
|
|
179
|
+
handle.onExit((event) => {
|
|
180
|
+
if (runtime.exited)
|
|
181
|
+
return;
|
|
182
|
+
runtime.exited = true;
|
|
183
|
+
broadcast(buildEnvelope(runtime, "terminal.exited", {
|
|
184
|
+
terminalId,
|
|
185
|
+
exitCode: event.exitCode,
|
|
186
|
+
...(event.signal !== undefined
|
|
187
|
+
? { signal: String(event.signal) }
|
|
188
|
+
: {}),
|
|
189
|
+
}, randomId, clock));
|
|
190
|
+
if (stdin.isTTY) {
|
|
191
|
+
stdin.setRawMode?.(false);
|
|
192
|
+
}
|
|
193
|
+
server.close();
|
|
194
|
+
resolveExit(event);
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
sessionId,
|
|
198
|
+
port: actualPort,
|
|
199
|
+
exit,
|
|
200
|
+
async stop() {
|
|
201
|
+
handle.kill();
|
|
202
|
+
await exit;
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret audit — what auth/credentials were actually transmitted to a session.
|
|
3
|
+
*
|
|
4
|
+
* Source of truth is the LIVE per-session Kubernetes Secret (`session-<id>-auth`)
|
|
5
|
+
* read via kubectl over the configured tunnel — NEVER a local "what I sent"
|
|
6
|
+
* record (which drifts on refresh / a second machine / a control-plane restart).
|
|
7
|
+
* Only KEY NAMES are read (go-template emits keys, never values); values are
|
|
8
|
+
* never decoded or printed. Sanitized Secret keys are mapped back to their
|
|
9
|
+
* original home-relative paths via the known auth registries, and classified by
|
|
10
|
+
* tool with a "broad" flag for account-wide cloud creds.
|
|
11
|
+
*/
|
|
12
|
+
export type SecretEntry = {
|
|
13
|
+
/** Original home-relative path (or the raw Secret key if unrecognized). */
|
|
14
|
+
readonly path: string;
|
|
15
|
+
readonly tool: string;
|
|
16
|
+
readonly broad: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Read the auth-Secret KEY NAMES transmitted to a session (values never read).
|
|
20
|
+
* Returns undefined if there is no configured tunnel / the secret can't be read.
|
|
21
|
+
*/
|
|
22
|
+
export declare function transmittedSecrets(sessionId: string): SecretEntry[] | undefined;
|
|
23
|
+
/** One-line summary for `remote status` (e.g. "claude +scw +aws⚠", or "—"). */
|
|
24
|
+
export declare function secretsSummary(sessionId: string): string;
|
|
25
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+BH,MAAM,MAAM,WAAW,GAAG;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,CAAC;AAcF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,SAAS,CA+B/E;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYxD"}
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret audit — what auth/credentials were actually transmitted to a session.
|
|
3
|
+
*
|
|
4
|
+
* Source of truth is the LIVE per-session Kubernetes Secret (`session-<id>-auth`)
|
|
5
|
+
* read via kubectl over the configured tunnel — NEVER a local "what I sent"
|
|
6
|
+
* record (which drifts on refresh / a second machine / a control-plane restart).
|
|
7
|
+
* Only KEY NAMES are read (go-template emits keys, never values); values are
|
|
8
|
+
* never decoded or printed. Sanitized Secret keys are mapped back to their
|
|
9
|
+
* original home-relative paths via the known auth registries, and classified by
|
|
10
|
+
* tool with a "broad" flag for account-wide cloud creds.
|
|
11
|
+
*/
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
import { homedir } from "node:os";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { getTunnel } from "./config.js";
|
|
16
|
+
import { PROFILE_AUTH_FILES } from "./auth-bundle.js";
|
|
17
|
+
import { TOOL_AUTH_INFO } from "./auth-tools.js";
|
|
18
|
+
/** Same sanitization the orchestrator applies to Secret keys (spec.ts). */
|
|
19
|
+
function credentialSecretKey(relativePath) {
|
|
20
|
+
return relativePath.replace(/^\.+/, "").replace(/\//g, "_");
|
|
21
|
+
}
|
|
22
|
+
/** sanitizedSecretKey → {relpath, tool, broad} for every auth file we ever bundle. */
|
|
23
|
+
function knownKeyMap() {
|
|
24
|
+
const m = new Map();
|
|
25
|
+
for (const [profile, files] of Object.entries(PROFILE_AUTH_FILES)) {
|
|
26
|
+
for (const rel of files) {
|
|
27
|
+
m.set(credentialSecretKey(rel), { relpath: rel, tool: profile, broad: false });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
for (const info of TOOL_AUTH_INFO) {
|
|
31
|
+
m.set(credentialSecretKey(info.relpath), { ...info });
|
|
32
|
+
}
|
|
33
|
+
return m;
|
|
34
|
+
}
|
|
35
|
+
function kubeEnv() {
|
|
36
|
+
const tunnel = getTunnel();
|
|
37
|
+
if (!tunnel)
|
|
38
|
+
return undefined;
|
|
39
|
+
const env = { ...process.env };
|
|
40
|
+
if (tunnel.kubeconfig) {
|
|
41
|
+
env.KUBECONFIG = tunnel.kubeconfig.startsWith("~")
|
|
42
|
+
? join(homedir(), tunnel.kubeconfig.slice(1))
|
|
43
|
+
: tunnel.kubeconfig;
|
|
44
|
+
}
|
|
45
|
+
return env;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read the auth-Secret KEY NAMES transmitted to a session (values never read).
|
|
49
|
+
* Returns undefined if there is no configured tunnel / the secret can't be read.
|
|
50
|
+
*/
|
|
51
|
+
export function transmittedSecrets(sessionId) {
|
|
52
|
+
const tunnel = getTunnel();
|
|
53
|
+
const env = kubeEnv();
|
|
54
|
+
if (!tunnel || !env)
|
|
55
|
+
return undefined;
|
|
56
|
+
const r = spawnSync("kubectl", [
|
|
57
|
+
"-n",
|
|
58
|
+
tunnel.namespace,
|
|
59
|
+
"get",
|
|
60
|
+
"secret",
|
|
61
|
+
`session-${sessionId}-auth`,
|
|
62
|
+
// emit ONLY the keys — the value ($v) is never referenced/printed
|
|
63
|
+
"-o",
|
|
64
|
+
'go-template={{range $k, $v := .data}}{{$k}}{{"\\n"}}{{end}}',
|
|
65
|
+
], { encoding: "utf8", env });
|
|
66
|
+
if (r.status !== 0)
|
|
67
|
+
return undefined;
|
|
68
|
+
const map = knownKeyMap();
|
|
69
|
+
return r.stdout
|
|
70
|
+
.split("\n")
|
|
71
|
+
.map((s) => s.trim())
|
|
72
|
+
.filter(Boolean)
|
|
73
|
+
.map((raw) => {
|
|
74
|
+
const info = map.get(raw);
|
|
75
|
+
return info
|
|
76
|
+
? { path: info.relpath, tool: info.tool, broad: info.broad }
|
|
77
|
+
: { path: raw, tool: "?", broad: false };
|
|
78
|
+
})
|
|
79
|
+
.sort((a, b) => a.path.localeCompare(b.path));
|
|
80
|
+
}
|
|
81
|
+
/** One-line summary for `remote status` (e.g. "claude +scw +aws⚠", or "—"). */
|
|
82
|
+
export function secretsSummary(sessionId) {
|
|
83
|
+
const entries = transmittedSecrets(sessionId);
|
|
84
|
+
if (entries === undefined)
|
|
85
|
+
return "?";
|
|
86
|
+
if (entries.length === 0)
|
|
87
|
+
return "—";
|
|
88
|
+
const seen = new Set();
|
|
89
|
+
const parts = [];
|
|
90
|
+
for (const e of entries) {
|
|
91
|
+
if (seen.has(e.tool))
|
|
92
|
+
continue;
|
|
93
|
+
seen.add(e.tool);
|
|
94
|
+
parts.push(`${e.tool}${e.broad ? "⚠" : ""}`);
|
|
95
|
+
}
|
|
96
|
+
return parts.join(" ");
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type OnConflict = "backup" | "keep-local" | "block";
|
|
2
|
+
export type RestoreResult = {
|
|
3
|
+
readonly restored: string[];
|
|
4
|
+
readonly keptLocal: string[];
|
|
5
|
+
readonly backedUp: string[];
|
|
6
|
+
readonly conflicts: string[];
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Restore persisted conversation state from a workspace export archive into the
|
|
10
|
+
* local HOME. Per file:
|
|
11
|
+
* - local absent → write remote (new conversation).
|
|
12
|
+
* - local == remote → skip.
|
|
13
|
+
* - local is a prefix of remote (remote is a continuation) → overwrite.
|
|
14
|
+
* - remote is a prefix of local (local is ahead) → keep local.
|
|
15
|
+
* - diverged → conflict, resolved by `onConflict`:
|
|
16
|
+
* backup → duplicate local under a fresh id, then write remote.
|
|
17
|
+
* keep-local→ skip remote.
|
|
18
|
+
* block → leave untouched, report.
|
|
19
|
+
*/
|
|
20
|
+
export declare function restoreSessionsToLocal(args: {
|
|
21
|
+
home: string;
|
|
22
|
+
profile: string;
|
|
23
|
+
remoteArchive: Buffer;
|
|
24
|
+
onConflict: OnConflict;
|
|
25
|
+
}): RestoreResult;
|
|
26
|
+
//# sourceMappingURL=session-restore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-restore.d.ts","sourceRoot":"","sources":["../src/session-restore.ts"],"names":[],"mappings":"AAgBA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;CAC9B,CAAC;AA+CF;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;CACxB,GAAG,aAAa,CAqDhB"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { dirname, extname, join, relative } from "node:path";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
const STATE_SUBDIR = ".remote/sessions";
|
|
6
|
+
function extractInto(archive, dest) {
|
|
7
|
+
mkdirSync(dest, { recursive: true });
|
|
8
|
+
const res = spawnSync("tar", ["-xzf", "-", "-C", dest], { input: archive });
|
|
9
|
+
if (res.status !== 0) {
|
|
10
|
+
throw new Error(`tar extract failed: ${res.stderr?.toString() ?? res.status}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function walk(root) {
|
|
14
|
+
const out = [];
|
|
15
|
+
if (!existsSync(root))
|
|
16
|
+
return out;
|
|
17
|
+
const stack = [root];
|
|
18
|
+
while (stack.length > 0) {
|
|
19
|
+
const dir = stack.pop();
|
|
20
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
21
|
+
const abs = join(dir, e.name);
|
|
22
|
+
if (e.isDirectory())
|
|
23
|
+
stack.push(abs);
|
|
24
|
+
else if (e.isFile())
|
|
25
|
+
out.push(relative(root, abs));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function isPrefix(short, long) {
|
|
31
|
+
return short.length <= long.length && long.subarray(0, short.length).equals(short);
|
|
32
|
+
}
|
|
33
|
+
function backupWithNewId(home, rel, local) {
|
|
34
|
+
// Heuristic: the conversation id is the filename stem (uuid-like). Duplicate
|
|
35
|
+
// the local conversation under a fresh id so the CLI lists it separately.
|
|
36
|
+
const ext = extname(rel);
|
|
37
|
+
const dir = dirname(rel);
|
|
38
|
+
const stem = rel.slice(dir === "." ? 0 : dir.length + 1, rel.length - ext.length);
|
|
39
|
+
const newId = randomUUID();
|
|
40
|
+
const newRel = join(dir === "." ? "" : dir, `${newId}${ext}`);
|
|
41
|
+
const replaced = stem.length >= 8
|
|
42
|
+
? Buffer.from(local.toString("utf8").split(stem).join(newId), "utf8")
|
|
43
|
+
: local;
|
|
44
|
+
const dst = join(home, newRel);
|
|
45
|
+
mkdirSync(dirname(dst), { recursive: true });
|
|
46
|
+
writeFileSync(dst, replaced);
|
|
47
|
+
return newRel;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Restore persisted conversation state from a workspace export archive into the
|
|
51
|
+
* local HOME. Per file:
|
|
52
|
+
* - local absent → write remote (new conversation).
|
|
53
|
+
* - local == remote → skip.
|
|
54
|
+
* - local is a prefix of remote (remote is a continuation) → overwrite.
|
|
55
|
+
* - remote is a prefix of local (local is ahead) → keep local.
|
|
56
|
+
* - diverged → conflict, resolved by `onConflict`:
|
|
57
|
+
* backup → duplicate local under a fresh id, then write remote.
|
|
58
|
+
* keep-local→ skip remote.
|
|
59
|
+
* block → leave untouched, report.
|
|
60
|
+
*/
|
|
61
|
+
export function restoreSessionsToLocal(args) {
|
|
62
|
+
// Use HOME/.remote/tmp/ as staging area — project policy forbids /tmp.
|
|
63
|
+
const stagingBase = join(args.home, ".remote", "tmp");
|
|
64
|
+
mkdirSync(stagingBase, { recursive: true });
|
|
65
|
+
const tmp = mkdtempSync(join(stagingBase, "restore-"));
|
|
66
|
+
const result = {
|
|
67
|
+
restored: [],
|
|
68
|
+
keptLocal: [],
|
|
69
|
+
backedUp: [],
|
|
70
|
+
conflicts: [],
|
|
71
|
+
};
|
|
72
|
+
try {
|
|
73
|
+
extractInto(args.remoteArchive, tmp);
|
|
74
|
+
const stateRoot = join(tmp, STATE_SUBDIR, args.profile);
|
|
75
|
+
for (const rel of walk(stateRoot)) {
|
|
76
|
+
const remote = readFileSync(join(stateRoot, rel));
|
|
77
|
+
const localPath = join(args.home, rel);
|
|
78
|
+
let local = null;
|
|
79
|
+
try {
|
|
80
|
+
if (statSync(localPath).isFile())
|
|
81
|
+
local = readFileSync(localPath);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
local = null;
|
|
85
|
+
}
|
|
86
|
+
const write = () => {
|
|
87
|
+
mkdirSync(dirname(localPath), { recursive: true });
|
|
88
|
+
writeFileSync(localPath, remote);
|
|
89
|
+
};
|
|
90
|
+
if (local === null) {
|
|
91
|
+
write();
|
|
92
|
+
result.restored.push(rel);
|
|
93
|
+
}
|
|
94
|
+
else if (local.equals(remote)) {
|
|
95
|
+
// identical, nothing to do
|
|
96
|
+
}
|
|
97
|
+
else if (isPrefix(local, remote)) {
|
|
98
|
+
write();
|
|
99
|
+
result.restored.push(rel);
|
|
100
|
+
}
|
|
101
|
+
else if (isPrefix(remote, local)) {
|
|
102
|
+
result.keptLocal.push(rel);
|
|
103
|
+
}
|
|
104
|
+
else if (args.onConflict === "backup") {
|
|
105
|
+
const bak = backupWithNewId(args.home, rel, local);
|
|
106
|
+
write();
|
|
107
|
+
result.backedUp.push(`${rel} -> ${bak}`);
|
|
108
|
+
}
|
|
109
|
+
else if (args.onConflict === "keep-local") {
|
|
110
|
+
result.keptLocal.push(rel);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
result.conflicts.push(rel);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=session-restore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-restore.js","sourceRoot":"","sources":["../src/session-restore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `remote plugin sync-skills` — propagate the LOCAL user's Claude Code skills
|
|
3
|
+
* and plugin state into each live session Pod's `$HOME/.claude/`, so delegated /
|
|
4
|
+
* remote claude sessions get the same capabilities (superpowers, track, h2a,
|
|
5
|
+
* graphify, sent-tech-design, …) the operator has locally.
|
|
6
|
+
*
|
|
7
|
+
* APPROACH — "copy the resolved cache" (the chosen DEFAULT). We tar a short,
|
|
8
|
+
* explicit WHITELIST of skill+plugin paths and untar it into the Pod. This is
|
|
9
|
+
* deterministic: the Pod gets byte-for-byte the same resolved plugin cache the
|
|
10
|
+
* operator already vetted locally, with no network/marketplace fetch in-Pod.
|
|
11
|
+
* Reversible fork (NOT implemented — documented for the conductor): instead of
|
|
12
|
+
* shipping the cache, re-install marketplaces in-Pod (`claude plugin
|
|
13
|
+
* marketplace add … && claude plugin install …`). That re-resolves remotely
|
|
14
|
+
* (non-deterministic, needs network + auth in the Pod) and is therefore the
|
|
15
|
+
* non-default. If we ever want it, it slots in as an alternate plan builder
|
|
16
|
+
* here; the CLI surface stays the same.
|
|
17
|
+
*
|
|
18
|
+
* CRITICAL SAFETY — we NEVER tar the whole `~/.claude` (it holds settings.json,
|
|
19
|
+
* .credentials.json, OAuth tokens, project transcripts under projects/, and
|
|
20
|
+
* ~/.claude.json). Only the four paths in SKILLS_SYNC_WHITELIST are archived,
|
|
21
|
+
* each a leaf path so no broader directory can sweep a secret in with it. The
|
|
22
|
+
* SAFETY tests assert no credential/transcript path is ever a tar member.
|
|
23
|
+
*
|
|
24
|
+
* Payloads are argv ARRAYS (tar argv, kubectl argv) — never a `bash -lc` string
|
|
25
|
+
* with interpolated paths — so a $HOME (or any path) with shell metacharacters
|
|
26
|
+
* is just a single argument, never a parsed shell word. The archive itself
|
|
27
|
+
* rides stdin (`kubectl exec -i … -- tar -x`), so no file content is ever
|
|
28
|
+
* interpolated either.
|
|
29
|
+
*
|
|
30
|
+
* Idempotent: re-running untars over the existing tree (`--overwrite`), so the
|
|
31
|
+
* Pod's skills/plugins converge to the local state on every run.
|
|
32
|
+
*/
|
|
33
|
+
import { type TunnelConfig } from "./config.js";
|
|
34
|
+
/**
|
|
35
|
+
* The ONLY paths synced to Pods, relative to `$HOME`. Skills dir + the three
|
|
36
|
+
* plugin-state pieces that make the resolved plugin cache deterministic. Each
|
|
37
|
+
* is a leaf path: no entry is a parent of a secret file (so tarring it can
|
|
38
|
+
* never drag settings.json / .credentials.json / transcripts along). Anything
|
|
39
|
+
* outside this list — including the rest of ~/.claude/plugins (blocklist.json,
|
|
40
|
+
* known_marketplaces.json, plugin-catalog-cache.json, data/) — is excluded.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SKILLS_SYNC_WHITELIST: readonly string[];
|
|
43
|
+
/** The explicit whitelist as a fresh array (callers cannot mutate the source). */
|
|
44
|
+
export declare function skillsSyncWhitelist(): string[];
|
|
45
|
+
/**
|
|
46
|
+
* `tar` argv that archives ONLY the whitelisted paths, relative to `$HOME`, as
|
|
47
|
+
* a gzip stream on stdout (`-f -`). `-C <home>` keeps members relative so they
|
|
48
|
+
* untar cleanly into the Pod's `$HOME`. `--ignore-failed-read` lets a partial
|
|
49
|
+
* local install still sync (a missing member is skipped, not fatal). Members
|
|
50
|
+
* follow `--` so a leading-dash path can never be mistaken for a flag.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildSkillsTarArgs(home: string): string[];
|
|
53
|
+
/**
|
|
54
|
+
* In-Pod `tar` argv: extract the gzip stream from stdin (`-f -`) into the Pod's
|
|
55
|
+
* `$HOME` (`-C <podHome>`), `--overwrite` so a re-run replaces the existing
|
|
56
|
+
* skills/plugins in place (idempotent). No member is named — extraction takes
|
|
57
|
+
* whatever the archive carries, and the archive only ever carries the
|
|
58
|
+
* whitelist (constrained on the tar side).
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildPodUntarArgs(podHome: string): string[];
|
|
61
|
+
/** A live session resolved to a Pod target for the skills sync. */
|
|
62
|
+
export type SyncPod = {
|
|
63
|
+
sessionId: string;
|
|
64
|
+
profile: string;
|
|
65
|
+
/** Pod `$HOME` (extraction root); defaults to /root (session-agent runs as root). */
|
|
66
|
+
podHome?: string;
|
|
67
|
+
};
|
|
68
|
+
export type SkillsSyncPlan = {
|
|
69
|
+
/** The Pod name (`session-<id>`). */
|
|
70
|
+
pod: string;
|
|
71
|
+
sessionId: string;
|
|
72
|
+
profile: string;
|
|
73
|
+
/** Local archive command: `tar <args>` writing gzip to stdout. */
|
|
74
|
+
tar: {
|
|
75
|
+
cmd: "tar";
|
|
76
|
+
args: string[];
|
|
77
|
+
};
|
|
78
|
+
/** In-Pod extraction command: `tar <args>` reading gzip from stdin. */
|
|
79
|
+
untar: {
|
|
80
|
+
cmd: "tar";
|
|
81
|
+
args: string[];
|
|
82
|
+
};
|
|
83
|
+
/** The whitelist actually transferred (for the recap / dry-run). */
|
|
84
|
+
whitelist: string[];
|
|
85
|
+
/** One-line human-readable plan for `--dry-run` (transfers nothing). */
|
|
86
|
+
dryRun: string;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Compose the local-tar | pod-untar plan for one Pod. Pure: it builds the two
|
|
90
|
+
* argv arrays and a dry-run line, but spawns nothing — the actual transfer is
|
|
91
|
+
* behind the `runSkillsSync` seam so tests never shell out.
|
|
92
|
+
*/
|
|
93
|
+
export declare function buildSkillsSyncPlan(input: {
|
|
94
|
+
home: string;
|
|
95
|
+
pod: SyncPod;
|
|
96
|
+
}): SkillsSyncPlan;
|
|
97
|
+
/**
|
|
98
|
+
* Resolve which live sessions to sync. `--all` => every session; `--pod <ref>`
|
|
99
|
+
* => the single session whose id (or `session-<id>` Pod name) matches. Throws
|
|
100
|
+
* when neither is given, or when `--pod` matches nothing live.
|
|
101
|
+
*/
|
|
102
|
+
export declare function selectSyncPods(sessions: ReadonlyArray<{
|
|
103
|
+
id: string;
|
|
104
|
+
profile: string;
|
|
105
|
+
}>, opts: {
|
|
106
|
+
pod?: string;
|
|
107
|
+
all?: boolean;
|
|
108
|
+
}): SyncPod[];
|
|
109
|
+
/**
|
|
110
|
+
* Pipe `tar <tarArgs>` (local) → `kubectl exec -i <pod> -- tar <untarArgs>`
|
|
111
|
+
* (Pod). Both ends are pure argv arrays; the gzip archive rides the pipe on
|
|
112
|
+
* stdin so no path/content is ever interpolated into a shell. Resolves on a
|
|
113
|
+
* clean (0/0) exit of both processes, rejects with the first non-zero status.
|
|
114
|
+
*/
|
|
115
|
+
export type SkillsSyncRunner = (plan: SkillsSyncPlan, tunnel: TunnelConfig) => Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* `remote plugin sync-skills [--pod <name>|--all] [--dry-run]` — copy the local
|
|
118
|
+
* Claude Code skills + plugin cache (whitelist only) into the selected live
|
|
119
|
+
* session Pod(s). `--dry-run` prints the tar/exec plan and transfers nothing.
|
|
120
|
+
*/
|
|
121
|
+
export declare function syncSkills(url: string, opts: {
|
|
122
|
+
pod?: string;
|
|
123
|
+
all?: boolean;
|
|
124
|
+
dryRun?: boolean;
|
|
125
|
+
}, stderr?: NodeJS.WriteStream, run?: SkillsSyncRunner): Promise<void>;
|
|
126
|
+
//# sourceMappingURL=skills-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-sync.d.ts","sourceRoot":"","sources":["../src/skills-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3D;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAKlD,CAAC;AAEF,kFAAkF;AAClF,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAYzD;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3D;AAED,mEAAmE;AACnE,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAKF,MAAM,MAAM,cAAc,GAAG;IAC3B,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,GAAG,EAAE;QAAE,GAAG,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACpC,uEAAuE;IACvE,KAAK,EAAE;QAAE,GAAG,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtC,oEAAoE;IACpE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,cAAc,CAmBjB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,OAAO,EAAE,CAeX;AAgBD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,YAAY,KACjB,OAAO,CAAC,IAAI,CAAC,CAAC;AAoEnB;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EACvD,MAAM,GAAE,MAAM,CAAC,WAA4B,EAC3C,GAAG,GAAE,gBAAkC,GACtC,OAAO,CAAC,IAAI,CAAC,CAiDf"}
|