@pipod/cli 0.1.19 → 0.1.20

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.
@@ -0,0 +1,100 @@
1
+ // src/log.ts
2
+ import { stripVTControlCharacters } from "util";
3
+
4
+ // src/redact.ts
5
+ var MIN_REDACTABLE_LENGTH = 4;
6
+ var secrets = /* @__PURE__ */ new Set();
7
+ function registerSecret(value) {
8
+ if (!value) return;
9
+ const v = String(value);
10
+ if (v.length < MIN_REDACTABLE_LENGTH) return;
11
+ secrets.add(v);
12
+ }
13
+ function registerSecrets(values) {
14
+ for (const v of Object.values(values)) registerSecret(v);
15
+ }
16
+ function redact(input) {
17
+ if (secrets.size === 0) return input;
18
+ let out2 = input;
19
+ for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {
20
+ if (out2.includes(secret)) out2 = out2.split(secret).join("[redacted]");
21
+ }
22
+ return out2;
23
+ }
24
+
25
+ // src/log.ts
26
+ var verbose = false;
27
+ var colorEnabled = process.stderr.isTTY === true && !process.env.NO_COLOR;
28
+ function setVerbose(v) {
29
+ verbose = v;
30
+ }
31
+ function isVerbose() {
32
+ return verbose;
33
+ }
34
+ var CODES = {
35
+ reset: "\x1B[0m",
36
+ dim: "\x1B[2m",
37
+ bold: "\x1B[1m",
38
+ red: "\x1B[31m",
39
+ yellow: "\x1B[33m",
40
+ cyan: "\x1B[36m",
41
+ green: "\x1B[32m"
42
+ };
43
+ function paint(code, s) {
44
+ return colorEnabled ? `${CODES[code]}${s}${CODES.reset}` : s;
45
+ }
46
+ var color = {
47
+ dim: (s) => paint("dim", s),
48
+ bold: (s) => paint("bold", s),
49
+ red: (s) => paint("red", s),
50
+ yellow: (s) => paint("yellow", s),
51
+ cyan: (s) => paint("cyan", s),
52
+ green: (s) => paint("green", s)
53
+ };
54
+ function write(line) {
55
+ process.stderr.write(redact(line) + "\n");
56
+ }
57
+ function info(msg) {
58
+ write(`${paint("cyan", "pi pod")} ${msg}`);
59
+ }
60
+ function step(phase, msg) {
61
+ write(`${paint("cyan", "pi pod")} ${paint("dim", `[${phase}]`)} ${msg}`);
62
+ }
63
+ function warn(msg) {
64
+ write(`${paint("yellow", "warning")} ${msg}`);
65
+ }
66
+ function error(msg) {
67
+ write(`${paint("red", "error")} ${msg}`);
68
+ }
69
+ function hint(msg) {
70
+ const lines = msg.split("\n");
71
+ write(`${paint("dim", " hint:")} ${lines[0] ?? ""}`);
72
+ for (const line of lines.slice(1)) write(paint("dim", ` ${line}`));
73
+ }
74
+ function debug(msg) {
75
+ if (verbose) write(`${paint("dim", "debug")} ${paint("dim", msg)}`);
76
+ }
77
+ function plain(msg) {
78
+ write(msg);
79
+ }
80
+ function out(msg) {
81
+ const line = redact(msg);
82
+ process.stdout.write((process.stdout.isTTY === true ? line : stripVTControlCharacters(line)) + "\n");
83
+ }
84
+
85
+ export {
86
+ registerSecret,
87
+ registerSecrets,
88
+ setVerbose,
89
+ isVerbose,
90
+ color,
91
+ info,
92
+ step,
93
+ warn,
94
+ error,
95
+ hint,
96
+ debug,
97
+ plain,
98
+ out
99
+ };
100
+ //# sourceMappingURL=chunk-7TJWBDVX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/log.ts","../src/redact.ts"],"sourcesContent":["/**\n * src/log.ts — the launcher's logger. Everything user-visible goes through here so that\n * redaction (§7.3) is structural rather than something each call site has to remember.\n */\nimport { stripVTControlCharacters } from \"node:util\";\nimport { redact } from \"./redact.js\";\n\nlet verbose = false;\nlet colorEnabled = process.stderr.isTTY === true && !process.env.NO_COLOR;\n\nexport function setVerbose(v: boolean): void {\n verbose = v;\n}\n\nexport function isVerbose(): boolean {\n return verbose;\n}\n\nexport function setColor(enabled: boolean): void {\n colorEnabled = enabled;\n}\n\nconst CODES = {\n reset: \"\\u001b[0m\",\n dim: \"\\u001b[2m\",\n bold: \"\\u001b[1m\",\n red: \"\\u001b[31m\",\n yellow: \"\\u001b[33m\",\n cyan: \"\\u001b[36m\",\n green: \"\\u001b[32m\",\n} as const;\n\nfunction paint(code: keyof typeof CODES, s: string): string {\n return colorEnabled ? `${CODES[code]}${s}${CODES.reset}` : s;\n}\n\nexport const color = {\n dim: (s: string) => paint(\"dim\", s),\n bold: (s: string) => paint(\"bold\", s),\n red: (s: string) => paint(\"red\", s),\n yellow: (s: string) => paint(\"yellow\", s),\n cyan: (s: string) => paint(\"cyan\", s),\n green: (s: string) => paint(\"green\", s),\n};\n\n/**\n * Diagnostics go to stderr so that stdout stays clean for the PTY stream and for\n * machine-readable output (`--dry-run`, `--version`).\n */\nfunction write(line: string): void {\n process.stderr.write(redact(line) + \"\\n\");\n}\n\nexport function info(msg: string): void {\n write(`${paint(\"cyan\", \"pi pod\")} ${msg}`);\n}\n\nexport function step(phase: string, msg: string): void {\n write(`${paint(\"cyan\", \"pi pod\")} ${paint(\"dim\", `[${phase}]`)} ${msg}`);\n}\n\nexport function warn(msg: string): void {\n write(`${paint(\"yellow\", \"warning\")} ${msg}`);\n}\n\nexport function error(msg: string): void {\n write(`${paint(\"red\", \"error\")} ${msg}`);\n}\n\n/** Multi-line hints are one hint: the prefix appears once, continuation lines align under it. */\nexport function hint(msg: string): void {\n const lines = msg.split(\"\\n\");\n write(`${paint(\"dim\", \" hint:\")} ${lines[0] ?? \"\"}`);\n for (const line of lines.slice(1)) write(paint(\"dim\", ` ${line}`));\n}\n\nexport function debug(msg: string): void {\n if (verbose) write(`${paint(\"dim\", \"debug\")} ${paint(\"dim\", msg)}`);\n}\n\nexport function plain(msg: string): void {\n write(msg);\n}\n\n/**\n * Direct stdout writer for command results and machine-readable output; still redacted.\n * Color is useful at a terminal but must never leak into a pipe or redirected file.\n */\nexport function out(msg: string): void {\n const line = redact(msg);\n process.stdout.write((process.stdout.isTTY === true ? line : stripVTControlCharacters(line)) + \"\\n\");\n}\n\n/**\n * Wall-clock phase timings for one launch/attach, so the summary line can say where the\n * time went. Overlapping (parallelized) phases each record their own duration; the summary\n * total is wall time, not the sum.\n */\nexport interface PhaseTiming {\n phase: string;\n ms: number;\n}\n\nconst phaseTimings: PhaseTiming[] = [];\n\nexport function resetPhaseTimings(): void {\n phaseTimings.length = 0;\n}\n\nexport function recordPhase(phase: string, ms: number): void {\n phaseTimings.push({ phase, ms });\n}\n\nexport async function timePhase<T>(phase: string, work: () => Promise<T>): Promise<T> {\n const startedAt = Date.now();\n try {\n return await work();\n } finally {\n recordPhase(phase, Date.now() - startedAt);\n }\n}\n\nfunction fmtSeconds(ms: number): string {\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\n/** One line naming total wall time and every phase that cost at least 100ms. */\nexport function phaseSummary(label: string, totalMs: number): string {\n const parts = phaseTimings.filter((t) => t.ms >= 100).map((t) => `${t.phase} ${fmtSeconds(t.ms)}`);\n const breakdown = parts.length > 0 ? ` (${parts.join(\" · \")})` : \"\";\n return `${label} in ${fmtSeconds(totalMs)}${breakdown}`;\n}\n\n/**\n * Print a periodic \"still …\" line while a long provider operation runs, so a multi-minute\n * wait is distinguishable from a hang. The line names the elapsed time and, when known,\n * roughly how long the wait usually takes.\n */\nexport const LIVENESS_INTERVAL_MS = 15_000;\n\nexport async function withLiveness<T>(\n label: string,\n work: () => Promise<T>,\n opts: { intervalMs?: number; expectation?: string } = {},\n): Promise<T> {\n const intervalMs = opts.intervalMs ?? LIVENESS_INTERVAL_MS;\n const startedAt = Date.now();\n const timer = setInterval(() => {\n const elapsed = Math.round((Date.now() - startedAt) / 1000);\n const usually = opts.expectation ? `, ${opts.expectation}` : \"\";\n write(`${paint(\"cyan\", \"pi pod\")} ${paint(\"dim\", `still ${label} (${elapsed}s elapsed${usually})`)}`);\n }, intervalMs);\n timer.unref?.();\n try {\n return await work();\n } finally {\n clearInterval(timer);\n }\n}\n\n/**\n * Stream a child stream to the terminal with a prefix (`[init]`, §4.3). Handles partial\n * lines so a chunk boundary never splits a prefix.\n */\nexport function prefixedStreamer(prefix: string): (chunk: Uint8Array) => void {\n let pending = \"\";\n const flushLine = (line: string) => write(`${paint(\"dim\", prefix)} ${line}`);\n return (chunk: Uint8Array) => {\n pending += Buffer.from(chunk).toString(\"utf8\");\n const lines = pending.split(/\\r?\\n/);\n pending = lines.pop() ?? \"\";\n for (const line of lines) flushLine(line);\n // Guard against a runaway line with no newline ever arriving.\n if (pending.length > 8192) {\n flushLine(pending);\n pending = \"\";\n }\n };\n}\n","/**\n * src/redact.ts — secret-aware log redaction (§7.3).\n *\n * Every value originating from the env file is registered here; the logger runs all output\n * through `redact()`. The conformance suite (§14) asserts that no registered value ever\n * appears in captured logs.\n */\n\n/** Values short enough to appear coincidentally are not worth redacting (and would mangle output). */\nconst MIN_REDACTABLE_LENGTH = 4;\n\nconst secrets = new Set<string>();\n\nexport function registerSecret(value: string | undefined | null): void {\n if (!value) return;\n const v = String(value);\n if (v.length < MIN_REDACTABLE_LENGTH) return;\n secrets.add(v);\n}\n\nexport function registerSecrets(values: Record<string, string>): void {\n for (const v of Object.values(values)) registerSecret(v);\n}\n\n/** Test/reset hook. */\nexport function clearSecrets(): void {\n secrets.clear();\n}\n\nexport function registeredSecretCount(): number {\n return secrets.size;\n}\n\n/**\n * Replace every registered secret with `[redacted]`. Longest-first so that a secret which\n * contains another secret as a substring is not partially revealed.\n */\nexport function redact(input: string): string {\n if (secrets.size === 0) return input;\n let out = input;\n for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {\n if (out.includes(secret)) out = out.split(secret).join(\"[redacted]\");\n }\n return out;\n}\n\nexport function redactBytes(input: Uint8Array): Uint8Array {\n if (secrets.size === 0) return input;\n const text = Buffer.from(input).toString(\"utf8\");\n const cleaned = redact(text);\n return cleaned === text ? input : Buffer.from(cleaned, \"utf8\");\n}\n\n/** Redact an arbitrary structure for debug dumps. Keys are preserved, values scrubbed. */\nexport function redactDeep<T>(value: T): T {\n if (typeof value === \"string\") return redact(value) as unknown as T;\n if (Array.isArray(value)) return value.map((v) => redactDeep(v)) as unknown as T;\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) out[k] = redactDeep(v);\n return out as unknown as T;\n }\n return value;\n}\n"],"mappings":"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","names":["out"]}
package/dist/cli.js CHANGED
@@ -4,6 +4,21 @@ import {
4
4
  POD_SUBCOMMANDS,
5
5
  PodCommandRouter
6
6
  } from "./chunk-GNKF75X7.js";
7
+ import {
8
+ color,
9
+ debug,
10
+ error,
11
+ hint,
12
+ info,
13
+ isVerbose,
14
+ out,
15
+ plain,
16
+ registerSecret,
17
+ registerSecrets,
18
+ setVerbose,
19
+ step,
20
+ warn
21
+ } from "./chunk-7TJWBDVX.js";
7
22
 
8
23
  // src/cli.ts
9
24
  import * as fs36 from "fs";
@@ -96,90 +111,6 @@ var PodAsleepError = class extends PiPodError {
96
111
  import * as fs7 from "fs";
97
112
  import { Readable } from "stream";
98
113
 
99
- // src/log.ts
100
- import { stripVTControlCharacters } from "util";
101
-
102
- // src/redact.ts
103
- var MIN_REDACTABLE_LENGTH = 4;
104
- var secrets = /* @__PURE__ */ new Set();
105
- function registerSecret(value) {
106
- if (!value) return;
107
- const v = String(value);
108
- if (v.length < MIN_REDACTABLE_LENGTH) return;
109
- secrets.add(v);
110
- }
111
- function registerSecrets(values) {
112
- for (const v of Object.values(values)) registerSecret(v);
113
- }
114
- function redact(input) {
115
- if (secrets.size === 0) return input;
116
- let out2 = input;
117
- for (const secret of [...secrets].sort((a, b) => b.length - a.length)) {
118
- if (out2.includes(secret)) out2 = out2.split(secret).join("[redacted]");
119
- }
120
- return out2;
121
- }
122
-
123
- // src/log.ts
124
- var verbose = false;
125
- var colorEnabled = process.stderr.isTTY === true && !process.env.NO_COLOR;
126
- function setVerbose(v) {
127
- verbose = v;
128
- }
129
- function isVerbose() {
130
- return verbose;
131
- }
132
- var CODES = {
133
- reset: "\x1B[0m",
134
- dim: "\x1B[2m",
135
- bold: "\x1B[1m",
136
- red: "\x1B[31m",
137
- yellow: "\x1B[33m",
138
- cyan: "\x1B[36m",
139
- green: "\x1B[32m"
140
- };
141
- function paint(code, s) {
142
- return colorEnabled ? `${CODES[code]}${s}${CODES.reset}` : s;
143
- }
144
- var color = {
145
- dim: (s) => paint("dim", s),
146
- bold: (s) => paint("bold", s),
147
- red: (s) => paint("red", s),
148
- yellow: (s) => paint("yellow", s),
149
- cyan: (s) => paint("cyan", s),
150
- green: (s) => paint("green", s)
151
- };
152
- function write(line) {
153
- process.stderr.write(redact(line) + "\n");
154
- }
155
- function info(msg) {
156
- write(`${paint("cyan", "pi pod")} ${msg}`);
157
- }
158
- function step(phase, msg) {
159
- write(`${paint("cyan", "pi pod")} ${paint("dim", `[${phase}]`)} ${msg}`);
160
- }
161
- function warn(msg) {
162
- write(`${paint("yellow", "warning")} ${msg}`);
163
- }
164
- function error(msg) {
165
- write(`${paint("red", "error")} ${msg}`);
166
- }
167
- function hint(msg) {
168
- const lines = msg.split("\n");
169
- write(`${paint("dim", " hint:")} ${lines[0] ?? ""}`);
170
- for (const line of lines.slice(1)) write(paint("dim", ` ${line}`));
171
- }
172
- function debug(msg) {
173
- if (verbose) write(`${paint("dim", "debug")} ${paint("dim", msg)}`);
174
- }
175
- function plain(msg) {
176
- write(msg);
177
- }
178
- function out(msg) {
179
- const line = redact(msg);
180
- process.stdout.write((process.stdout.isTTY === true ? line : stripVTControlCharacters(line)) + "\n");
181
- }
182
-
183
114
  // src/account/oidc.ts
184
115
  import { createHash, randomBytes, timingSafeEqual } from "crypto";
185
116
  import { createRemoteJWKSet, jwtVerify } from "jose";
@@ -5284,19 +5215,19 @@ async function archiveIntoPod(opts, plan, flags = {}) {
5284
5215
  const ignored = gitIgnoredPaths(plan.root);
5285
5216
  const tmpDir = opts.tmpDir ?? os3.tmpdir();
5286
5217
  const archivePath = path14.join(tmpDir, `pi-pod-seed-${randomBytes3(8).toString("hex")}.tar.gz`);
5287
- const write2 = opts.tarball ?? createTarball;
5218
+ const write = opts.tarball ?? createTarball;
5288
5219
  try {
5289
5220
  let summary;
5290
5221
  let includeGit = plan.includeGit;
5291
5222
  step("seed", `archiving ${plan.root}${includeGit ? " with .git history" : ""} (${plan.reason})`);
5292
5223
  try {
5293
- summary = await write2(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));
5224
+ summary = await write(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));
5294
5225
  } catch (error2) {
5295
5226
  throwIfCancelled(opts, error2);
5296
5227
  if (!(error2 instanceof TarballLimitError) || !includeGit) throw error2;
5297
5228
  warn(`${error2.message} \u2014 retrying without .git history`);
5298
5229
  includeGit = false;
5299
- summary = await write2(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));
5230
+ summary = await write(tarballOptions(opts, plan.root, archivePath, ignored, includeGit));
5300
5231
  }
5301
5232
  if (summary.entries === 0) {
5302
5233
  info("nothing to seed \u2014 the local directory is empty");
@@ -14346,9 +14277,9 @@ async function runAccountInteractive(opts) {
14346
14277
  latestConnectionState = state;
14347
14278
  noteAsleep(state);
14348
14279
  if (runtimeRef) {
14349
- const paint2 = () => applyConnectionStatus(runtimeRef?.bridge.ui, state, rpc?.podId ?? opts.pod.id);
14350
- if (runtimeRef.bridge.ui) paint2();
14351
- else runtimeRef.bridge.onUiBound(paint2);
14280
+ const paint = () => applyConnectionStatus(runtimeRef?.bridge.ui, state, rpc?.podId ?? opts.pod.id);
14281
+ if (runtimeRef.bridge.ui) paint();
14282
+ else runtimeRef.bridge.onUiBound(paint);
14352
14283
  if (state.kind === "lost") {
14353
14284
  runtimeRef.bridge.notify(
14354
14285
  state.reason ? `could not reconnect: ${state.reason}` : "connection lost",
@@ -14694,20 +14625,27 @@ ${choices.join("\n")}`,
14694
14625
  };
14695
14626
  let unwireDisconnectedQuit = () => {
14696
14627
  };
14628
+ let unwireKeyRepeat = () => {
14629
+ };
14697
14630
  let mode;
14698
14631
  try {
14699
14632
  await runtime.init();
14700
14633
  const { InteractiveMode } = await import("@earendil-works/pi-coding-agent");
14701
14634
  const { wirePodChords } = await import("./chords-SOJBLC6R.js");
14635
+ const { wireKeyRepeatGuard } = await import("./key-repeat-guard-7OVKW5KD.js");
14636
+ const { guardStdinFragments } = await import("./stdin-fragment-guard-SPIJC7GT.js");
14637
+ guardStdinFragments();
14702
14638
  const chords = context.config.pi.chords;
14703
14639
  runtime.bridge.setOnUiBound(() => {
14704
14640
  unwireChords();
14705
14641
  unwireDisconnectedQuit();
14642
+ unwireKeyRepeat();
14706
14643
  unwireChords = wirePodChords(runtime.bridge, runtime.router, chords);
14707
14644
  unwireDisconnectedQuit = wireDisconnectedQuit(
14708
14645
  runtime.bridge,
14709
14646
  () => connectionAllowsQuit(latestConnectionState)
14710
14647
  );
14648
+ unwireKeyRepeat = wireKeyRepeatGuard(runtime.bridge.ui);
14711
14649
  });
14712
14650
  const tuiMode = opts.tuiMode ?? tuiModeFromArgv(context.config.pi.args);
14713
14651
  process.env["PI_SKIP_VERSION_CHECK"] ??= "1";
@@ -14737,6 +14675,7 @@ ${choices.join("\n")}`,
14737
14675
  runtime.bridge.setOnUiBound(null);
14738
14676
  unwireChords();
14739
14677
  unwireDisconnectedQuit();
14678
+ unwireKeyRepeat();
14740
14679
  rpc.close();
14741
14680
  derived?.dispose();
14742
14681
  throw error2;
@@ -14763,6 +14702,7 @@ ${choices.join("\n")}`,
14763
14702
  runtime.bridge.setOnUiBound(null);
14764
14703
  unwireChords();
14765
14704
  unwireDisconnectedQuit();
14705
+ unwireKeyRepeat();
14766
14706
  process.off("SIGHUP", onHangUp);
14767
14707
  process.off("SIGTERM", onHangUp);
14768
14708
  }
@@ -18671,10 +18611,10 @@ async function showCmd(client, args) {
18671
18611
  if (t.piSettings && Object.keys(t.piSettings).length > 0) {
18672
18612
  info(`Pi settings ${describePiSettings(flatPiSettings(t.piSettings))}`);
18673
18613
  }
18674
- const secrets2 = await client.listSecrets("template", t.id).catch(() => null);
18675
- if (secrets2 && secrets2.secrets.length > 0) {
18614
+ const secrets = await client.listSecrets("template", t.id).catch(() => null);
18615
+ if (secrets && secrets.secrets.length > 0) {
18676
18616
  out("");
18677
- info(`template secrets: ${secrets2.secrets.map((s) => s.name).join(", ")}`);
18617
+ info(`template secrets: ${secrets.secrets.map((s) => s.name).join(", ")}`);
18678
18618
  }
18679
18619
  return 0;
18680
18620
  }
@@ -18684,9 +18624,9 @@ function describePiSettings(settings) {
18684
18624
  const packageCount = Array.isArray(packages) ? packages.length : 0;
18685
18625
  return `${names.join(", ") || "empty"}${packageCount > 0 ? ` (${packageCount} package(s))` : ""}`;
18686
18626
  }
18687
- async function writeTemplateSnapshot(write2) {
18627
+ async function writeTemplateSnapshot(write) {
18688
18628
  try {
18689
- return await write2();
18629
+ return await write();
18690
18630
  } catch (error2) {
18691
18631
  if (error2 instanceof PiPodError && error2.status === 400 && /(?:unrecognized|unknown|unexpected)[^\n]*piSettings|piSettings[^\n]*(?:unrecognized|unknown|unexpected)/i.test(error2.message)) {
18692
18632
  throw new PiPodError("the pi pod server does not support template-owned Pi settings", {