@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
|
@@ -0,0 +1,255 @@
|
|
|
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 { spawn, spawnSync } from "node:child_process";
|
|
34
|
+
import { homedir } from "node:os";
|
|
35
|
+
import { join } from "node:path";
|
|
36
|
+
import { listRemoteSessions } from "./attach.js";
|
|
37
|
+
import { getTunnel } from "./config.js";
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Pure helpers (exported for tests)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
/**
|
|
42
|
+
* The ONLY paths synced to Pods, relative to `$HOME`. Skills dir + the three
|
|
43
|
+
* plugin-state pieces that make the resolved plugin cache deterministic. Each
|
|
44
|
+
* is a leaf path: no entry is a parent of a secret file (so tarring it can
|
|
45
|
+
* never drag settings.json / .credentials.json / transcripts along). Anything
|
|
46
|
+
* outside this list — including the rest of ~/.claude/plugins (blocklist.json,
|
|
47
|
+
* known_marketplaces.json, plugin-catalog-cache.json, data/) — is excluded.
|
|
48
|
+
*/
|
|
49
|
+
export const SKILLS_SYNC_WHITELIST = [
|
|
50
|
+
".claude/skills",
|
|
51
|
+
".claude/plugins/installed_plugins.json",
|
|
52
|
+
".claude/plugins/marketplaces",
|
|
53
|
+
".claude/plugins/cache",
|
|
54
|
+
];
|
|
55
|
+
/** The explicit whitelist as a fresh array (callers cannot mutate the source). */
|
|
56
|
+
export function skillsSyncWhitelist() {
|
|
57
|
+
return [...SKILLS_SYNC_WHITELIST];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `tar` argv that archives ONLY the whitelisted paths, relative to `$HOME`, as
|
|
61
|
+
* a gzip stream on stdout (`-f -`). `-C <home>` keeps members relative so they
|
|
62
|
+
* untar cleanly into the Pod's `$HOME`. `--ignore-failed-read` lets a partial
|
|
63
|
+
* local install still sync (a missing member is skipped, not fatal). Members
|
|
64
|
+
* follow `--` so a leading-dash path can never be mistaken for a flag.
|
|
65
|
+
*/
|
|
66
|
+
export function buildSkillsTarArgs(home) {
|
|
67
|
+
return [
|
|
68
|
+
"-c",
|
|
69
|
+
"-z",
|
|
70
|
+
"--ignore-failed-read",
|
|
71
|
+
"-C",
|
|
72
|
+
home,
|
|
73
|
+
"-f",
|
|
74
|
+
"-",
|
|
75
|
+
"--",
|
|
76
|
+
...skillsSyncWhitelist(),
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* In-Pod `tar` argv: extract the gzip stream from stdin (`-f -`) into the Pod's
|
|
81
|
+
* `$HOME` (`-C <podHome>`), `--overwrite` so a re-run replaces the existing
|
|
82
|
+
* skills/plugins in place (idempotent). No member is named — extraction takes
|
|
83
|
+
* whatever the archive carries, and the archive only ever carries the
|
|
84
|
+
* whitelist (constrained on the tar side).
|
|
85
|
+
*/
|
|
86
|
+
export function buildPodUntarArgs(podHome) {
|
|
87
|
+
return ["-x", "-z", "--overwrite", "-C", podHome, "-f", "-"];
|
|
88
|
+
}
|
|
89
|
+
/** Default Pod `$HOME` — the session-agent container runs as root. */
|
|
90
|
+
const DEFAULT_POD_HOME = "/root";
|
|
91
|
+
/**
|
|
92
|
+
* Compose the local-tar | pod-untar plan for one Pod. Pure: it builds the two
|
|
93
|
+
* argv arrays and a dry-run line, but spawns nothing — the actual transfer is
|
|
94
|
+
* behind the `runSkillsSync` seam so tests never shell out.
|
|
95
|
+
*/
|
|
96
|
+
export function buildSkillsSyncPlan(input) {
|
|
97
|
+
const { home, pod } = input;
|
|
98
|
+
const podHome = pod.podHome ?? DEFAULT_POD_HOME;
|
|
99
|
+
const tarArgs = buildSkillsTarArgs(home);
|
|
100
|
+
const untarArgs = buildPodUntarArgs(podHome);
|
|
101
|
+
const podName = `session-${pod.sessionId}`;
|
|
102
|
+
const dryRun = `${podName} (${pod.profile}): tar ${tarArgs.join(" ")} ` +
|
|
103
|
+
`| kubectl exec -i ${podName} -- tar ${untarArgs.join(" ")} ` +
|
|
104
|
+
`[whitelist: ${skillsSyncWhitelist().join(", ")}]`;
|
|
105
|
+
return {
|
|
106
|
+
pod: podName,
|
|
107
|
+
sessionId: pod.sessionId,
|
|
108
|
+
profile: pod.profile,
|
|
109
|
+
tar: { cmd: "tar", args: tarArgs },
|
|
110
|
+
untar: { cmd: "tar", args: untarArgs },
|
|
111
|
+
whitelist: skillsSyncWhitelist(),
|
|
112
|
+
dryRun,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolve which live sessions to sync. `--all` => every session; `--pod <ref>`
|
|
117
|
+
* => the single session whose id (or `session-<id>` Pod name) matches. Throws
|
|
118
|
+
* when neither is given, or when `--pod` matches nothing live.
|
|
119
|
+
*/
|
|
120
|
+
export function selectSyncPods(sessions, opts) {
|
|
121
|
+
if (opts.all) {
|
|
122
|
+
return sessions.map((s) => ({ sessionId: s.id, profile: s.profile }));
|
|
123
|
+
}
|
|
124
|
+
if (opts.pod) {
|
|
125
|
+
const id = opts.pod.startsWith("session-")
|
|
126
|
+
? opts.pod.slice("session-".length)
|
|
127
|
+
: opts.pod;
|
|
128
|
+
const match = sessions.find((s) => s.id === id);
|
|
129
|
+
if (!match) {
|
|
130
|
+
throw new Error(`no live session matches --pod "${opts.pod}"`);
|
|
131
|
+
}
|
|
132
|
+
return [{ sessionId: match.id, profile: match.profile }];
|
|
133
|
+
}
|
|
134
|
+
throw new Error("select sessions with --pod <name> or --all");
|
|
135
|
+
}
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// Spawn seam (thin — tests stub this, never shell out)
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
function expandHome(p) {
|
|
140
|
+
return p.startsWith("~") ? join(homedir(), p.slice(1)) : p;
|
|
141
|
+
}
|
|
142
|
+
function kubeEnv(tunnel) {
|
|
143
|
+
const env = { ...process.env };
|
|
144
|
+
if (tunnel.kubeconfig)
|
|
145
|
+
env.KUBECONFIG = expandHome(tunnel.kubeconfig);
|
|
146
|
+
return env;
|
|
147
|
+
}
|
|
148
|
+
const spawnSkillsSync = (plan, tunnel) => new Promise((resolve, reject) => {
|
|
149
|
+
const kubectlArgs = [
|
|
150
|
+
"-n",
|
|
151
|
+
tunnel.namespace,
|
|
152
|
+
"exec",
|
|
153
|
+
"-i",
|
|
154
|
+
plan.pod,
|
|
155
|
+
"-c",
|
|
156
|
+
"session-agent",
|
|
157
|
+
"--",
|
|
158
|
+
plan.untar.cmd,
|
|
159
|
+
...plan.untar.args,
|
|
160
|
+
];
|
|
161
|
+
const env = kubeEnv(tunnel);
|
|
162
|
+
const tar = spawn(plan.tar.cmd, plan.tar.args, {
|
|
163
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
164
|
+
});
|
|
165
|
+
const kube = spawn("kubectl", kubectlArgs, {
|
|
166
|
+
stdio: ["pipe", "inherit", "pipe"],
|
|
167
|
+
env,
|
|
168
|
+
});
|
|
169
|
+
let tarErr = "";
|
|
170
|
+
let kubeErr = "";
|
|
171
|
+
tar.stderr.on("data", (d) => {
|
|
172
|
+
tarErr += d.toString();
|
|
173
|
+
});
|
|
174
|
+
kube.stderr.on("data", (d) => {
|
|
175
|
+
kubeErr += d.toString();
|
|
176
|
+
});
|
|
177
|
+
tar.on("error", reject);
|
|
178
|
+
kube.on("error", reject);
|
|
179
|
+
tar.stdout.pipe(kube.stdin);
|
|
180
|
+
let tarDone = false;
|
|
181
|
+
let kubeDone = false;
|
|
182
|
+
let failed = false;
|
|
183
|
+
const settle = () => {
|
|
184
|
+
if (tarDone && kubeDone && !failed)
|
|
185
|
+
resolve();
|
|
186
|
+
};
|
|
187
|
+
tar.on("close", (code) => {
|
|
188
|
+
tarDone = true;
|
|
189
|
+
if (code !== 0 && !failed) {
|
|
190
|
+
failed = true;
|
|
191
|
+
reject(new Error(`tar exited ${code}: ${tarErr.trim().slice(0, 200)}`));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
settle();
|
|
195
|
+
});
|
|
196
|
+
kube.on("close", (code) => {
|
|
197
|
+
kubeDone = true;
|
|
198
|
+
if (code !== 0 && !failed) {
|
|
199
|
+
failed = true;
|
|
200
|
+
reject(new Error(`kubectl exec ${plan.pod} exited ${code}: ${kubeErr.trim().slice(0, 200)}`));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
settle();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// Command
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
/**
|
|
210
|
+
* `remote plugin sync-skills [--pod <name>|--all] [--dry-run]` — copy the local
|
|
211
|
+
* Claude Code skills + plugin cache (whitelist only) into the selected live
|
|
212
|
+
* session Pod(s). `--dry-run` prints the tar/exec plan and transfers nothing.
|
|
213
|
+
*/
|
|
214
|
+
export async function syncSkills(url, opts, stderr = process.stderr, run = spawnSkillsSync) {
|
|
215
|
+
const tunnel = getTunnel();
|
|
216
|
+
if (!tunnel) {
|
|
217
|
+
throw new Error("plugin sync-skills needs a tunnel configured (remote config tunnel …)");
|
|
218
|
+
}
|
|
219
|
+
const sessions = await listRemoteSessions(url);
|
|
220
|
+
if (sessions.length === 0) {
|
|
221
|
+
stderr.write("[remote] no live remote sessions to sync\n");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const pods = selectSyncPods(sessions, opts);
|
|
225
|
+
const home = homedir();
|
|
226
|
+
if (opts.dryRun) {
|
|
227
|
+
stderr.write(`[remote] sync-skills DRY-RUN — whitelist (relative to $HOME): ${skillsSyncWhitelist().join(", ")}\n`);
|
|
228
|
+
for (const pod of pods) {
|
|
229
|
+
stderr.write(` ${buildSkillsSyncPlan({ home, pod }).dryRun}\n`);
|
|
230
|
+
}
|
|
231
|
+
stderr.write("[remote] dry-run: nothing transferred\n");
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
// Fail fast if local tar is missing (clearer than a spawn ENOENT mid-loop).
|
|
235
|
+
if (spawnSync("tar", ["--version"], { stdio: "ignore" }).status !== 0) {
|
|
236
|
+
throw new Error("local `tar` not found — required to archive the skills cache");
|
|
237
|
+
}
|
|
238
|
+
let failures = 0;
|
|
239
|
+
for (const pod of pods) {
|
|
240
|
+
const plan = buildSkillsSyncPlan({ home, pod });
|
|
241
|
+
stderr.write(`[remote] ${plan.sessionId} (${plan.profile}): sync-skills…\n`);
|
|
242
|
+
try {
|
|
243
|
+
await run(plan, tunnel);
|
|
244
|
+
stderr.write(` skills/plugins synced (${plan.whitelist.length} whitelist path(s)) -> ${plan.pod}:$HOME\n`);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
failures++;
|
|
248
|
+
stderr.write(` sync-skills FAILED: ${String(error).slice(0, 200)}\n`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
stderr.write(`[remote] sync-skills done: ${pods.length} pod(s)${failures > 0 ? `, ${failures} failure(s)` : ""}\n`);
|
|
252
|
+
if (failures > 0)
|
|
253
|
+
process.exitCode = 1;
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=skills-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills-sync.js","sourceRoot":"","sources":["../src/skills-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/smoke.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CliProfile, SessionTarget } from "./protocol-local.js";
|
|
2
|
+
import { type AuthBundle } from "./auth-bundle.js";
|
|
3
|
+
import { type AuthRefreshResult } from "./auth-refresh.js";
|
|
4
|
+
export type SmokeRemoteProfileOptions = {
|
|
5
|
+
readonly profile: CliProfile;
|
|
6
|
+
readonly baseUrl: string;
|
|
7
|
+
readonly target?: SessionTarget;
|
|
8
|
+
readonly displayName?: string;
|
|
9
|
+
readonly timeoutMs?: number;
|
|
10
|
+
readonly auth?: boolean;
|
|
11
|
+
readonly authRefresh?: boolean;
|
|
12
|
+
readonly fetchImpl?: typeof fetch;
|
|
13
|
+
readonly collectAuth?: (profile: CliProfile) => Promise<AuthBundle>;
|
|
14
|
+
readonly ensureAuthFresh?: (profile: CliProfile) => Promise<AuthRefreshResult>;
|
|
15
|
+
};
|
|
16
|
+
export type SmokeRemoteProfileResult = {
|
|
17
|
+
readonly profile: CliProfile;
|
|
18
|
+
readonly sessionId: string;
|
|
19
|
+
readonly terminalId: string;
|
|
20
|
+
readonly shell: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function smokeRemoteProfile(options: SmokeRemoteProfileOptions): Promise<SmokeRemoteProfileResult>;
|
|
23
|
+
//# sourceMappingURL=smoke.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.d.ts","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EAEV,aAAa,EAEd,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACpE,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,OAAO,EAAE,UAAU,KAChB,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AA2GF,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAgEnC"}
|
package/dist/smoke.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { createRemoteSession, stopRemoteSession } from "./attach.js";
|
|
2
|
+
import { assertRequiredAuthBundle, collectProfileAuth, } from "./auth-bundle.js";
|
|
3
|
+
import { ensureProfileAuthFresh, } from "./auth-refresh.js";
|
|
4
|
+
function joinUrl(base, path) {
|
|
5
|
+
return `${base.replace(/\/$/, "")}${path}`;
|
|
6
|
+
}
|
|
7
|
+
function parseSseEvents(buffer) {
|
|
8
|
+
const events = [];
|
|
9
|
+
const chunks = buffer.split("\n\n");
|
|
10
|
+
const rest = chunks.pop() ?? "";
|
|
11
|
+
for (const chunk of chunks) {
|
|
12
|
+
if (!chunk.trim())
|
|
13
|
+
continue;
|
|
14
|
+
let eventName;
|
|
15
|
+
const dataLines = [];
|
|
16
|
+
for (const line of chunk.split("\n")) {
|
|
17
|
+
if (line.startsWith("event:"))
|
|
18
|
+
eventName = line.slice(6).trim();
|
|
19
|
+
else if (line.startsWith("data:"))
|
|
20
|
+
dataLines.push(line.slice(5).trim());
|
|
21
|
+
}
|
|
22
|
+
if (dataLines.length === 0)
|
|
23
|
+
continue;
|
|
24
|
+
events.push({
|
|
25
|
+
...(eventName !== undefined ? { event: eventName } : {}),
|
|
26
|
+
data: dataLines.join("\n"),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return { events, rest };
|
|
30
|
+
}
|
|
31
|
+
async function waitForTerminalOpened(options) {
|
|
32
|
+
const controller = new AbortController();
|
|
33
|
+
let reader;
|
|
34
|
+
let timedOut = false;
|
|
35
|
+
const timer = setTimeout(() => {
|
|
36
|
+
timedOut = true;
|
|
37
|
+
controller.abort();
|
|
38
|
+
}, options.timeoutMs);
|
|
39
|
+
try {
|
|
40
|
+
const response = await options.fetchImpl(joinUrl(options.baseUrl, `/sessions/${options.sessionId}/events`), {
|
|
41
|
+
headers: { accept: "text/event-stream" },
|
|
42
|
+
signal: controller.signal,
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok || !response.body) {
|
|
45
|
+
throw new Error(`[remote] smoke event stream returned ${response.status} ${response.statusText}`);
|
|
46
|
+
}
|
|
47
|
+
reader = response.body.getReader();
|
|
48
|
+
const decoder = new TextDecoder("utf-8");
|
|
49
|
+
let buffer = "";
|
|
50
|
+
for (;;) {
|
|
51
|
+
const { value, done } = await reader.read();
|
|
52
|
+
if (done)
|
|
53
|
+
break;
|
|
54
|
+
buffer += decoder.decode(value, { stream: true });
|
|
55
|
+
const { events, rest } = parseSseEvents(buffer);
|
|
56
|
+
buffer = rest;
|
|
57
|
+
for (const ev of events) {
|
|
58
|
+
if (ev.event &&
|
|
59
|
+
ev.event !== "terminal.opened" &&
|
|
60
|
+
ev.event !== "terminal.exited") {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const envelope = JSON.parse(ev.data);
|
|
64
|
+
if (envelope.type === "terminal.opened") {
|
|
65
|
+
return envelope.payload;
|
|
66
|
+
}
|
|
67
|
+
if (envelope.type === "terminal.exited") {
|
|
68
|
+
const payload = envelope.payload;
|
|
69
|
+
throw new Error(`[remote] smoke session ${options.sessionId} exited before terminal.opened (exitCode=${payload.exitCode ?? "unknown"})`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
throw new Error(`[remote] smoke event stream ended before terminal.opened for ${options.sessionId}`);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (timedOut) {
|
|
77
|
+
throw new Error(`[remote] smoke timed out waiting for terminal.opened for ${options.sessionId}`);
|
|
78
|
+
}
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
controller.abort();
|
|
84
|
+
await reader?.cancel().catch(() => { });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function smokeRemoteProfile(options) {
|
|
88
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
89
|
+
let credentials;
|
|
90
|
+
if (options.auth !== false) {
|
|
91
|
+
if (options.authRefresh !== false) {
|
|
92
|
+
await (options.ensureAuthFresh ?? ensureProfileAuthFresh)(options.profile);
|
|
93
|
+
}
|
|
94
|
+
const bundle = await (options.collectAuth ?? collectProfileAuth)(options.profile);
|
|
95
|
+
assertRequiredAuthBundle(options.profile, bundle);
|
|
96
|
+
if (Object.keys(bundle).length > 0)
|
|
97
|
+
credentials = bundle;
|
|
98
|
+
}
|
|
99
|
+
let sessionId;
|
|
100
|
+
let result;
|
|
101
|
+
let failure;
|
|
102
|
+
try {
|
|
103
|
+
sessionId = (await createRemoteSession(options.baseUrl, {
|
|
104
|
+
profile: options.profile,
|
|
105
|
+
target: options.target ?? "k3s",
|
|
106
|
+
displayName: options.displayName ?? `smoke-${options.profile}-${Date.now()}`,
|
|
107
|
+
...(credentials ? { credentials } : {}),
|
|
108
|
+
}, fetchImpl)).id;
|
|
109
|
+
const opened = await waitForTerminalOpened({
|
|
110
|
+
baseUrl: options.baseUrl,
|
|
111
|
+
sessionId,
|
|
112
|
+
timeoutMs: options.timeoutMs ?? 120_000,
|
|
113
|
+
fetchImpl,
|
|
114
|
+
});
|
|
115
|
+
result = {
|
|
116
|
+
profile: options.profile,
|
|
117
|
+
sessionId,
|
|
118
|
+
terminalId: opened.terminalId,
|
|
119
|
+
shell: opened.shell,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
failure = error;
|
|
124
|
+
}
|
|
125
|
+
if (sessionId) {
|
|
126
|
+
try {
|
|
127
|
+
await stopRemoteSession(options.baseUrl, sessionId, "remote-profile-smoke", fetchImpl);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (!failure)
|
|
131
|
+
failure = error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (failure)
|
|
135
|
+
throw failure;
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=smoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smoke.js","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft credential refresh: push fresh local creds INTO a running session Pod and
|
|
3
|
+
* relaunch the CLI in place — WITHOUT recreating the Pod (keeps HOME parity, the
|
|
4
|
+
* conversation, the node, no image pull). Fixes the recurring ~8h token logout
|
|
5
|
+
* (the CLI can't self-refresh OAuth in a headless Pod). Also patches the auth
|
|
6
|
+
* Secret so the fresh token survives a future Pod restart.
|
|
7
|
+
*
|
|
8
|
+
* Steps (all via kubectl against the configured tunnel):
|
|
9
|
+
* 1. materialize each bundled cred file into $HOME/<rel> in the Pod,
|
|
10
|
+
* 2. patch session-<id>-auth Secret keys (durability),
|
|
11
|
+
* 3. respawn the Pod's tmux `main` pane: `<cli> --resume <newestConv>` with a
|
|
12
|
+
* UTF-8 locale, dropping to a shell on exit (never kills the session).
|
|
13
|
+
*
|
|
14
|
+
* Unchanged-creds gating (`skipIfUnchanged`, used by `refresh --all/--watch`):
|
|
15
|
+
* the respawn INTERRUPTS the Pod's CLI, so it must only happen when the pushed
|
|
16
|
+
* creds actually differ. We sha256 the bundle and compare it with the previous
|
|
17
|
+
* pass (`previousHash`, in-memory --watch state) and with the hash recorded in
|
|
18
|
+
* the Pod ($HOME/.remote-creds.sha256, written after every push). Identical
|
|
19
|
+
* creds = silent no-op: nothing pushed, no Secret patch, NO respawn.
|
|
20
|
+
*/
|
|
21
|
+
import { type HealthResult, type ProbeableTool } from "./cred-health.js";
|
|
22
|
+
/** HOME-relative file in the Pod recording the sha256 of the last pushed bundle. */
|
|
23
|
+
export declare const CREDS_HASH_FILE = ".remote-creds.sha256";
|
|
24
|
+
/**
|
|
25
|
+
* Deterministic sha256 of an auth bundle (profile + sorted rel -> base64 value),
|
|
26
|
+
* SKIPPING config-only rels (see CONFIG_ONLY_RELS). Values stay opaque: the
|
|
27
|
+
* hash never leaks any secret material.
|
|
28
|
+
*/
|
|
29
|
+
export declare function hashAuthBundle(profile: string, bundle: Readonly<Record<string, string>>): string;
|
|
30
|
+
export type SoftRefreshResult = {
|
|
31
|
+
/** false = creds identical to the Pod's last push — nothing pushed, NO respawn. */
|
|
32
|
+
changed: boolean;
|
|
33
|
+
/** sha256 of the local bundle — feed back as `previousHash` on the next pass. */
|
|
34
|
+
hash: string;
|
|
35
|
+
filesPushed: string[];
|
|
36
|
+
secretKeysPatched: string[];
|
|
37
|
+
convId: string | undefined;
|
|
38
|
+
respawned: boolean;
|
|
39
|
+
};
|
|
40
|
+
export type SoftRefreshOptions = {
|
|
41
|
+
/**
|
|
42
|
+
* Compare the bundle hash with `previousHash` and/or the hash recorded in the
|
|
43
|
+
* Pod, and no-op (no push, no Secret patch, NO respawn) when identical.
|
|
44
|
+
*/
|
|
45
|
+
skipIfUnchanged?: boolean;
|
|
46
|
+
/** Bundle hash from the previous pass (in-memory --watch state): when it matches, skip without even reading the Pod. */
|
|
47
|
+
previousHash?: string;
|
|
48
|
+
stderr?: NodeJS.WriteStream;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Push the profile's fresh creds into the Pod, patch the Secret, and relaunch
|
|
52
|
+
* the CLI in place. `bundle` is the already-collected creds (rel -> content).
|
|
53
|
+
*/
|
|
54
|
+
export declare function softRefreshSession(sessionId: string, profile: string, options?: SoftRefreshOptions): Promise<SoftRefreshResult>;
|
|
55
|
+
/** Result of a per-pod, per-tool probe→push pass. */
|
|
56
|
+
export type ToolHealthAction = {
|
|
57
|
+
readonly tool: ProbeableTool;
|
|
58
|
+
readonly health: HealthResult;
|
|
59
|
+
/** true when ok:false drove a re-bundle+push of this tool's creds. */
|
|
60
|
+
readonly pushed: boolean;
|
|
61
|
+
/** HOME-relative files materialized into the Pod (empty when not pushed / none local). */
|
|
62
|
+
readonly filesPushed: ReadonlyArray<string>;
|
|
63
|
+
readonly secretKeysPatched: ReadonlyArray<string>;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Injectable seams so the executor is unit-testable WITHOUT shelling out to
|
|
67
|
+
* kubectl or reading ~/. Production defaults wire the real plumbing.
|
|
68
|
+
*/
|
|
69
|
+
export type ToolHealthDeps = {
|
|
70
|
+
/** Run the argv-safe probe in the Pod (default: execPodArgv against the tunnel). */
|
|
71
|
+
exec: (argv: ReadonlyArray<string>) => {
|
|
72
|
+
status: number;
|
|
73
|
+
stdout: string;
|
|
74
|
+
};
|
|
75
|
+
/** Re-bundle the LOCAL creds for the tools (default: collectToolAuth). */
|
|
76
|
+
collect: (tools: ReadonlyArray<string>) => Promise<{
|
|
77
|
+
bundle: Record<string, string>;
|
|
78
|
+
bundled: string[];
|
|
79
|
+
}>;
|
|
80
|
+
/** Materialize one base64 file into the Pod's $HOME (default: execPod base64 -d). */
|
|
81
|
+
materialize: (rel: string, base64: string) => void;
|
|
82
|
+
/** Patch one Secret data key with a base64 value (default: kubectl patch). */
|
|
83
|
+
patchSecretKey: (key: string, base64: string) => void;
|
|
84
|
+
stderr?: {
|
|
85
|
+
write: (s: string) => unknown;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Probe ONE covered tool in a live Pod and, if it's unauthenticated, push the
|
|
90
|
+
* tool's LOCAL creds (re-bundle + materialize + Secret patch — the same
|
|
91
|
+
* mechanism as today, an extra trigger). Pure-ish: all IO is injected via
|
|
92
|
+
* `deps`. Returns what happened (probe result + whether/what was pushed).
|
|
93
|
+
* Exported for tests.
|
|
94
|
+
*/
|
|
95
|
+
export declare function probeAndPushToolHealth(tool: ProbeableTool, deps: ToolHealthDeps): Promise<ToolHealthAction>;
|
|
96
|
+
/**
|
|
97
|
+
* Production wiring for `probeAndPushToolHealth` against a configured tunnel +
|
|
98
|
+
* live pod. Builds the default `ToolHealthDeps` (real kubectl exec / patch /
|
|
99
|
+
* collectToolAuth) and probes EACH covered tool, pushing on a 401. Best-effort:
|
|
100
|
+
* a probe/push error for one tool is logged and the others continue. Returns the
|
|
101
|
+
* per-tool actions. NOT pure (does IO); the pure decision lives in
|
|
102
|
+
* `probeAndPushToolHealth` + cred-health. Used by the watch loop.
|
|
103
|
+
*/
|
|
104
|
+
export declare function probePodCredHealth(sessionId: string, tools?: ReadonlyArray<string>, options?: {
|
|
105
|
+
stderr?: NodeJS.WriteStream;
|
|
106
|
+
}): Promise<ToolHealthAction[]>;
|
|
107
|
+
//# sourceMappingURL=soft-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soft-refresh.d.ts","sourceRoot":"","sources":["../src/soft-refresh.ts"],"names":[],"mappings":"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"}
|