infra-kit 0.41.0 → 0.42.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.
Files changed (42) hide show
  1. package/dist/{boot-ST2534PA.js → boot-26CWOALE.js} +2 -2
  2. package/dist/{boot-ST2534PA.js.map → boot-26CWOALE.js.map} +1 -1
  3. package/dist/{chunk-QS7RKE5P.js → chunk-HIGOL4H4.js} +2 -2
  4. package/dist/chunk-HMXEV7ZN.js +16 -0
  5. package/dist/chunk-HMXEV7ZN.js.map +7 -0
  6. package/dist/chunk-K5KNXRTF.js +6 -0
  7. package/dist/chunk-K5KNXRTF.js.map +7 -0
  8. package/dist/chunk-K5YNW3DE.js +4 -0
  9. package/dist/chunk-K5YNW3DE.js.map +7 -0
  10. package/dist/{chunk-GCOYOWGH.js → chunk-RVMKL6T4.js} +1 -1
  11. package/dist/{chunk-GCOYOWGH.js.map → chunk-RVMKL6T4.js.map} +1 -1
  12. package/dist/chunk-S23ECFH4.js +5 -0
  13. package/dist/chunk-S23ECFH4.js.map +7 -0
  14. package/dist/{chunk-PP44RGIU.js → chunk-VZAXKGEY.js} +2 -2
  15. package/dist/{chunk-KFQKVU6O.js → chunk-YSR7UND3.js} +2 -2
  16. package/dist/{chunk-KFQKVU6O.js.map → chunk-YSR7UND3.js.map} +2 -2
  17. package/dist/{chunk-2SDWSDM2.js → chunk-ZY6BBGHH.js} +3 -3
  18. package/dist/cli.js +153 -136
  19. package/dist/cli.js.map +4 -4
  20. package/dist/dev-server.js +19 -19
  21. package/dist/dev-server.js.map +4 -4
  22. package/dist/dev-wizard-run-PF3FTXA7.js +2 -0
  23. package/dist/{dev-wizard-run-THLLE77N.js.map → dev-wizard-run-PF3FTXA7.js.map} +2 -2
  24. package/dist/mcp-proxy.js +1 -1
  25. package/dist/{persistent-ink-dev-ui-D6ALK2P3.js → persistent-ink-dev-ui-HHTHZ24S.js} +2 -2
  26. package/dist/secrets-download-DXRM5M6F.js +2 -0
  27. package/dist/update-check.js +1 -1
  28. package/package.json +14 -15
  29. package/readme.md +1 -1
  30. package/dist/chunk-4G7F5ELE.js +0 -16
  31. package/dist/chunk-4G7F5ELE.js.map +0 -7
  32. package/dist/chunk-6EGHDLFA.js +0 -7
  33. package/dist/chunk-6EGHDLFA.js.map +0 -7
  34. package/dist/chunk-A67SJCCI.js +0 -12
  35. package/dist/chunk-A67SJCCI.js.map +0 -7
  36. package/dist/dev-wizard-run-THLLE77N.js +0 -2
  37. package/dist/env-load-RIZVNG3D.js +0 -2
  38. /package/dist/{chunk-QS7RKE5P.js.map → chunk-HIGOL4H4.js.map} +0 -0
  39. /package/dist/{chunk-PP44RGIU.js.map → chunk-VZAXKGEY.js.map} +0 -0
  40. /package/dist/{chunk-2SDWSDM2.js.map → chunk-ZY6BBGHH.js.map} +0 -0
  41. /package/dist/{persistent-ink-dev-ui-D6ALK2P3.js.map → persistent-ink-dev-ui-HHTHZ24S.js.map} +0 -0
  42. /package/dist/{env-load-RIZVNG3D.js.map → secrets-download-DXRM5M6F.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/lib/constants/constants.ts"],
4
- "sourcesContent": ["import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\n\nexport const ENV_LOAD_FILE = 'env-load.sh'\nexport const ENV_CLEAR_FILE = 'env-clear.sh'\n/**\n * Sidecar of `env-load.sh`: the directories, one per line, the loaded env belongs to. The session is\n * per terminal, not per repo, so without it a shell or agent in repo A sourced repo B's env.\n */\nexport const ENV_LOAD_ROOT_FILE = 'env-load.root'\n\nexport const INFRA_KIT_SESSION_VAR = 'INFRA_KIT_SESSION'\n/**\n * Directory under the user's home that holds all machine-local infra-kit config:\n * the runtime `infra-kit.json` merge layer, per-project overrides, the factory\n * registry (`vendor.json`), and the `portless` package link. Single source of\n * truth for `.infra-kit`.\n *\n * Defined HERE, not in `lib/infra-kit-config`, because that module pulls in zod\n * and the `ik-mcp` proxy bundle must stay Node-builtins-only (guarded in\n * `entry/__tests__/dist-shebang.test.ts`); `lib/infra-kit-config` re-exports it\n * for its existing consumers.\n */\nexport const USER_CONFIG_DIR_NAME = '.infra-kit'\n/**\n * The active environment/config NAME (e.g. `dev`, `arthur`), exported plainly so\n * non-shell consumers can read it from `process.env`. Notably `infra-kit/vite`'s\n * `infraKitDev()` reads this to interpolate the `<env>` placeholder in cloud proxy\n * targets. Mirrors {@link INFRA_KIT_ENV_CONFIG_VAR} (same value) but is the stable,\n * purpose-named handle for tooling rather than the shell session-metadata var.\n */\nexport const INFRA_KIT_ENV_VAR = 'INFRA_KIT_ENV'\nexport const INFRA_KIT_ENV_CONFIG_VAR = 'INFRA_KIT_ENV_CONFIG'\nexport const INFRA_KIT_ENV_PROJECT_VAR = 'INFRA_KIT_ENV_PROJECT'\n/**\n * Absolute project root (git top-level) the loaded env belongs to, so a shell can\n * tell whose secrets it is carrying after a `cd` into another project.\n */\nexport const INFRA_KIT_ENV_PROJECT_ROOT_VAR = 'INFRA_KIT_ENV_PROJECT_ROOT'\nexport const INFRA_KIT_ENV_LOADED_AT_VAR = 'INFRA_KIT_ENV_LOADED_AT'\n\n/**\n * Matches a line of the form `KEY=...` where KEY is an env-var identifier\n * (letter or underscore, then word chars). Capture group 1 is the name. Shared\n * between env-load (validation, var counting) and parseVarNamesFromEnvFile.\n */\nexport const ENV_VAR_LINE_PATTERN = /^([A-Z_]\\w*)=/i\n\n/**\n * The `unset NAME` line env-clear.sh is made of. Anchored at both ends so a value that merely\n * starts with the word is not a match.\n */\nconst UNSET_LINE_PATTERN = /^unset ([A-Z_]\\w*)$/i\n\n/**\n * Track whether a physical line leaves us inside an open single-quoted value,\n * mirroring how `shellSingleQuote` emits values (`'\u2026'`, with literal quotes as\n * `'\\''`). Outside a quote a backslash escapes the next char; inside a quote a\n * `'` closes it. Lets the parser skip the continuation lines of a multiline value.\n */\nconst advanceSingleQuoteState = (line: string, startInQuote: boolean): boolean => {\n let inQuote = startInQuote\n\n for (let i = 0; i < line.length; i++) {\n if (!inQuote && line[i] === '\\\\') {\n i++\n continue\n }\n\n if (line[i] === \"'\") {\n inQuote = !inQuote\n }\n }\n\n return inQuote\n}\n\n/** One `KEY=value` assignment recovered from an env file, value already unescaped. */\nexport interface EnvAssignment {\n name: string\n value: string\n}\n\n/**\n * Undo {@link shellSingleQuote}: drop the wrapping quotes, then turn each `'\\''`\n * back into a literal `'`. Order matters \u2014 unescaping first would let an embedded\n * `'\\''` be mistaken for the closing quote.\n */\nconst decodeSingleQuoted = (raw: string): string => {\n const withoutOpen = raw.startsWith(\"'\") ? raw.slice(1) : raw\n const body = withoutOpen.endsWith(\"'\") ? withoutOpen.slice(0, -1) : withoutOpen\n\n return body.split(\"'\\\\''\").join(\"'\")\n}\n\n/** File contents, or '' when the path is absent, a directory, or unreadable. */\nconst readEnvFileContent = (filePath: string): string => {\n try {\n return fs.readFileSync(filePath, 'utf-8')\n } catch {\n return ''\n }\n}\n\n/**\n * Walk every assignment in an env-load.sh body, skipping the continuation lines of\n * multiline values. {@link parseVarNamesFromEnvFile}, {@link parseVarsFromEnvFile}\n * and {@link parseUnsetNamesFromEnvFile} all go through here, so they can never\n * disagree about where a value ends \u2014 an `unset X` inside a quoted value is a\n * continuation line to every one of them.\n */\nconst forEachAssignment = (\n content: string,\n visit: (assignment: EnvAssignment) => void,\n visitUnset?: (name: string) => void,\n): void => {\n // A trailing CR is stripped per line: a CRLF file would otherwise hand back values\n // ending in '\\r' \u2014 a token that looks right in a diff and fails every request.\n const lines = content.split('\\n').map((line) => {\n return line.endsWith('\\r') ? line.slice(0, -1) : line\n })\n\n let index = 0\n let inQuote = false\n\n while (index < lines.length) {\n const line = lines[index]!\n\n // Only a line that starts OUTSIDE a quoted value can be a real assignment;\n // continuation lines of a multiline secret value are skipped.\n if (inQuote) {\n inQuote = advanceSingleQuoteState(line, inQuote)\n index += 1\n continue\n }\n\n const match = ENV_VAR_LINE_PATTERN.exec(line)\n\n if (!match) {\n const unset = UNSET_LINE_PATTERN.exec(line)\n\n if (unset) visitUnset?.(unset[1]!)\n\n inQuote = advanceSingleQuoteState(line, false)\n index += 1\n continue\n }\n\n const name = match[1]!\n const rest = line.slice(match[0].length)\n\n // An unquoted value cannot span lines (`CONNECTION_STRING=host=db;user=admin`).\n if (!rest.startsWith(\"'\")) {\n visit({ name, value: rest })\n inQuote = advanceSingleQuoteState(line, false)\n index += 1\n continue\n }\n\n const parts = [rest]\n let open = advanceSingleQuoteState(rest, false)\n\n while (open && index + 1 < lines.length) {\n index += 1\n const continuation = lines[index]!\n\n parts.push(continuation)\n open = advanceSingleQuoteState(continuation, true)\n }\n\n visit({ name, value: decodeSingleQuoted(parts.join('\\n')) })\n inQuote = open\n index += 1\n }\n}\n\nexport const parseVarNamesFromEnvFile = (filePath: string): string[] => {\n const names: string[] = []\n\n forEachAssignment(readEnvFileContent(filePath), ({ name }) => {\n names.push(name)\n })\n\n return names\n}\n\n/**\n * Same walk as {@link parseVarNamesFromEnvFile}, but keeping the values. Later\n * assignments win, matching what `source`ing the file would do.\n */\nexport const parseVarsFromEnvFile = (filePath: string): Record<string, string> => {\n const vars: Record<string, string> = {}\n\n forEachAssignment(readEnvFileContent(filePath), ({ name, value }) => {\n vars[name] = value\n })\n\n return vars\n}\n\n/**\n * The names the file `unset`s \u2014 everything env-clear.sh does. Absent file \u2192 `[]`, like\n * its siblings.\n */\nexport const parseUnsetNamesFromEnvFile = (filePath: string): string[] => {\n const names: string[] = []\n\n forEachAssignment(\n readEnvFileContent(filePath),\n () => {},\n (name) => {\n names.push(name)\n },\n )\n\n return names\n}\n\n/**\n * Root cache dir for infra-kit across all sessions. Resolved from\n * $XDG_CACHE_HOME when set, falling back to ~/.cache/infra-kit. Keep in sync\n * with the shell block emitted by `infra-kit setup` (src/commands/init/init.ts).\n */\nexport const getCacheRoot = (): string => {\n const xdg = process.env.XDG_CACHE_HOME\n const base = xdg && xdg.length > 0 ? xdg : path.join(os.homedir(), '.cache')\n\n return path.join(base, 'infra-kit')\n}\n\nexport const getSessionCacheDir = (): string => {\n const session = process.env[INFRA_KIT_SESSION_VAR]\n\n if (!session) {\n throw new Error(\n `${INFRA_KIT_SESSION_VAR} is not set. Run \\`infra-kit setup --skip-tools\\` then \\`source ~/.zshrc\\`.`,\n )\n }\n\n return path.join(getCacheRoot(), session)\n}\n\n/**\n * Write content atomically: write to a pid-suffixed temp file in the same\n * directory, then rename. fs.renameSync is atomic on a single filesystem, so\n * concurrent writers can't produce a half-written secret file.\n */\nexport const atomicWriteFileSync = (filePath: string, content: string, mode: number): void => {\n const tmpPath = `${filePath}.tmp.${process.pid}`\n\n fs.writeFileSync(tmpPath, content, { mode })\n\n try {\n fs.renameSync(tmpPath, filePath)\n } catch (error) {\n fs.rmSync(tmpPath, { force: true })\n throw error\n }\n}\n\nexport const WORKTREES_DIR_SUFFIX = '-worktrees'\n\n/**\n * Whether `cwd` is one of the directories in an {@link ENV_LOAD_ROOT_FILE}, or under one. Mirrors the\n * `~/.zshenv` check in `init.ts`, symlinks resolved on both sides. No sidecar is in scope everywhere:\n * that is an `env-load.sh` written before the sidecar existed, and it stays usable until the next load.\n */\nexport const isInEnvLoadScope = (rootFile: string, cwd: string): boolean => {\n let content: string\n\n try {\n content = fs.readFileSync(rootFile, 'utf-8')\n } catch {\n return true\n }\n\n const realCwd = safeRealpath(cwd)\n\n return content\n .split('\\n')\n .filter(Boolean)\n .some((root) => {\n return realCwd === root || realCwd.startsWith(`${root}${path.sep}`)\n })\n}\n\nconst safeRealpath = (target: string): string => {\n try {\n return fs.realpathSync(target)\n } catch {\n return path.resolve(target)\n }\n}\n\n/**\n * Canonical `<repo>-worktrees` subdirectory names, shared by every command that lays worktrees\n * out under it (`init`'s scaffold, `worktrees add`) or reasons about that layout (`worktrees\n * sync`/`remove`, `gh merge-dev`'s scratch checkout) \u2014 one literal each, not re-typed per site.\n */\nexport const WORKTREE_SUBDIRS = { release: 'release', feature: 'feature', mergeDev: 'merge-dev' } as const\n"],
4
+ "sourcesContent": ["import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport process from 'node:process'\n\nexport const ENV_LOAD_FILE = 'env-load.sh'\nexport const ENV_CLEAR_FILE = 'env-clear.sh'\n/**\n * Sidecar of `env-load.sh`: the directories, one per line, the loaded env belongs to. The session is\n * per terminal, not per repo, so without it a shell or agent in repo A sourced repo B's env.\n */\nexport const ENV_LOAD_ROOT_FILE = 'env-load.root'\n\nexport const INFRA_KIT_SESSION_VAR = 'INFRA_KIT_SESSION'\n/**\n * Directory under the user's home that holds all machine-local infra-kit config:\n * the runtime `infra-kit.json` merge layer, per-project overrides, the factory\n * registry (`vendor.json`), and the `portless` package link. Single source of\n * truth for `.infra-kit`.\n *\n * Defined HERE, not in `lib/infra-kit-config`, because that module pulls in zod\n * and the `ik-mcp` proxy bundle must stay Node-builtins-only (guarded in\n * `entry/__tests__/dist-shebang.test.ts`); `lib/infra-kit-config` re-exports it\n * for its existing consumers.\n */\nexport const USER_CONFIG_DIR_NAME = '.infra-kit'\n/**\n * The active environment/config NAME (e.g. `dev`, `arthur`), exported plainly so\n * non-shell consumers can read it from `process.env`. Notably `infra-kit/vite`'s\n * `infraKitDev()` reads this to interpolate the `<env>` placeholder in cloud proxy\n * targets. Mirrors {@link INFRA_KIT_ENV_CONFIG_VAR} (same value) but is the stable,\n * purpose-named handle for tooling rather than the shell session-metadata var.\n */\nexport const INFRA_KIT_ENV_VAR = 'INFRA_KIT_ENV'\nexport const INFRA_KIT_ENV_CONFIG_VAR = 'INFRA_KIT_ENV_CONFIG'\nexport const INFRA_KIT_ENV_PROJECT_VAR = 'INFRA_KIT_ENV_PROJECT'\n/**\n * Absolute project root (git top-level) the loaded env belongs to, so a shell can\n * tell whose secrets it is carrying after a `cd` into another project.\n */\nexport const INFRA_KIT_ENV_PROJECT_ROOT_VAR = 'INFRA_KIT_ENV_PROJECT_ROOT'\nexport const INFRA_KIT_ENV_LOADED_AT_VAR = 'INFRA_KIT_ENV_LOADED_AT'\n\n/**\n * Matches a line of the form `KEY=...` where KEY is an env-var identifier\n * (letter or underscore, then word chars). Capture group 1 is the name. Shared\n * between env-load (validation, var counting) and parseVarNamesFromEnvFile.\n */\nexport const ENV_VAR_LINE_PATTERN = /^([A-Z_]\\w*)=/i\n\n/**\n * The `unset NAME` line env-clear.sh is made of. Anchored at both ends so a value that merely\n * starts with the word is not a match.\n */\nconst UNSET_LINE_PATTERN = /^unset ([A-Z_]\\w*)$/i\n\n/**\n * Track whether a physical line leaves us inside an open single-quoted value,\n * mirroring how `shellSingleQuote` emits values (`'\u2026'`, with literal quotes as\n * `'\\''`). Outside a quote a backslash escapes the next char; inside a quote a\n * `'` closes it. Lets the parser skip the continuation lines of a multiline value.\n */\nconst advanceSingleQuoteState = (line: string, startInQuote: boolean): boolean => {\n let inQuote = startInQuote\n\n for (let i = 0; i < line.length; i++) {\n if (!inQuote && line[i] === '\\\\') {\n i++\n continue\n }\n\n if (line[i] === \"'\") {\n inQuote = !inQuote\n }\n }\n\n return inQuote\n}\n\n/** One `KEY=value` assignment recovered from an env file, value already unescaped. */\nexport interface EnvAssignment {\n name: string\n value: string\n}\n\n/**\n * Undo {@link shellSingleQuote}: drop the wrapping quotes, then turn each `'\\''`\n * back into a literal `'`. Order matters \u2014 unescaping first would let an embedded\n * `'\\''` be mistaken for the closing quote.\n */\nconst decodeSingleQuoted = (raw: string): string => {\n const withoutOpen = raw.startsWith(\"'\") ? raw.slice(1) : raw\n const body = withoutOpen.endsWith(\"'\") ? withoutOpen.slice(0, -1) : withoutOpen\n\n return body.split(\"'\\\\''\").join(\"'\")\n}\n\n/** File contents, or '' when the path is absent, a directory, or unreadable. */\nconst readEnvFileContent = (filePath: string): string => {\n try {\n return fs.readFileSync(filePath, 'utf-8')\n } catch {\n return ''\n }\n}\n\n/**\n * Walk every assignment in an env-load.sh body, skipping the continuation lines of\n * multiline values. {@link parseVarNamesFromEnvFile}, {@link parseVarsFromEnvFile}\n * and {@link parseUnsetNamesFromEnvFile} all go through here, so they can never\n * disagree about where a value ends \u2014 an `unset X` inside a quoted value is a\n * continuation line to every one of them.\n */\nconst forEachAssignment = (\n content: string,\n visit: (assignment: EnvAssignment) => void,\n visitUnset?: (name: string) => void,\n): void => {\n // A trailing CR is stripped per line: a CRLF file would otherwise hand back values\n // ending in '\\r' \u2014 a token that looks right in a diff and fails every request.\n const lines = content.split('\\n').map((line) => {\n return line.endsWith('\\r') ? line.slice(0, -1) : line\n })\n\n let index = 0\n let inQuote = false\n\n while (index < lines.length) {\n const line = lines[index]!\n\n // Only a line that starts OUTSIDE a quoted value can be a real assignment;\n // continuation lines of a multiline secret value are skipped.\n if (inQuote) {\n inQuote = advanceSingleQuoteState(line, inQuote)\n index += 1\n continue\n }\n\n const match = ENV_VAR_LINE_PATTERN.exec(line)\n\n if (!match) {\n const unset = UNSET_LINE_PATTERN.exec(line)\n\n if (unset) visitUnset?.(unset[1]!)\n\n inQuote = advanceSingleQuoteState(line, false)\n index += 1\n continue\n }\n\n const name = match[1]!\n const rest = line.slice(match[0].length)\n\n // An unquoted value cannot span lines (`CONNECTION_STRING=host=db;user=admin`).\n if (!rest.startsWith(\"'\")) {\n visit({ name, value: rest })\n inQuote = advanceSingleQuoteState(line, false)\n index += 1\n continue\n }\n\n const parts = [rest]\n let open = advanceSingleQuoteState(rest, false)\n\n while (open && index + 1 < lines.length) {\n index += 1\n const continuation = lines[index]!\n\n parts.push(continuation)\n open = advanceSingleQuoteState(continuation, true)\n }\n\n visit({ name, value: decodeSingleQuoted(parts.join('\\n')) })\n inQuote = open\n index += 1\n }\n}\n\nexport const parseVarNamesFromEnvFile = (filePath: string): string[] => {\n const names: string[] = []\n\n forEachAssignment(readEnvFileContent(filePath), ({ name }) => {\n names.push(name)\n })\n\n return names\n}\n\n/**\n * Same walk as {@link parseVarNamesFromEnvFile}, but keeping the values. Later\n * assignments win, matching what `source`ing the file would do.\n */\nexport const parseVarsFromEnvFile = (filePath: string): Record<string, string> => {\n const vars: Record<string, string> = {}\n\n forEachAssignment(readEnvFileContent(filePath), ({ name, value }) => {\n vars[name] = value\n })\n\n return vars\n}\n\n/**\n * The names the file `unset`s \u2014 everything env-clear.sh does. Absent file \u2192 `[]`, like\n * its siblings.\n */\nexport const parseUnsetNamesFromEnvFile = (filePath: string): string[] => {\n const names: string[] = []\n\n forEachAssignment(\n readEnvFileContent(filePath),\n () => {},\n (name) => {\n names.push(name)\n },\n )\n\n return names\n}\n\n/**\n * Root cache dir for infra-kit across all sessions. Resolved from\n * $XDG_CACHE_HOME when set, falling back to ~/.cache/infra-kit. Keep in sync\n * with the shell block emitted by `infra-kit setup` (src/lib/init/init.ts).\n */\nexport const getCacheRoot = (): string => {\n const xdg = process.env.XDG_CACHE_HOME\n const base = xdg && xdg.length > 0 ? xdg : path.join(os.homedir(), '.cache')\n\n return path.join(base, 'infra-kit')\n}\n\nexport const getSessionCacheDir = (): string => {\n const session = process.env[INFRA_KIT_SESSION_VAR]\n\n if (!session) {\n throw new Error(\n `${INFRA_KIT_SESSION_VAR} is not set. Run \\`infra-kit setup --skip-tools\\` then \\`source ~/.zshrc\\`.`,\n )\n }\n\n return path.join(getCacheRoot(), session)\n}\n\n/**\n * Write content atomically: write to a pid-suffixed temp file in the same\n * directory, then rename. fs.renameSync is atomic on a single filesystem, so\n * concurrent writers can't produce a half-written secret file.\n */\nexport const atomicWriteFileSync = (filePath: string, content: string, mode: number): void => {\n const tmpPath = `${filePath}.tmp.${process.pid}`\n\n fs.writeFileSync(tmpPath, content, { mode })\n\n try {\n fs.renameSync(tmpPath, filePath)\n } catch (error) {\n fs.rmSync(tmpPath, { force: true })\n throw error\n }\n}\n\nexport const WORKTREES_DIR_SUFFIX = '-worktrees'\n\n/**\n * Whether `cwd` is one of the directories in an {@link ENV_LOAD_ROOT_FILE}, or under one. Mirrors the\n * `~/.zshenv` check in `init.ts`, symlinks resolved on both sides. No sidecar is in scope everywhere:\n * that is an `env-load.sh` written before the sidecar existed, and it stays usable until the next load.\n */\nexport const isInEnvLoadScope = (rootFile: string, cwd: string): boolean => {\n let content: string\n\n try {\n content = fs.readFileSync(rootFile, 'utf-8')\n } catch {\n return true\n }\n\n const realCwd = safeRealpath(cwd)\n\n return content\n .split('\\n')\n .filter(Boolean)\n .some((root) => {\n return realCwd === root || realCwd.startsWith(`${root}${path.sep}`)\n })\n}\n\nconst safeRealpath = (target: string): string => {\n try {\n return fs.realpathSync(target)\n } catch {\n return path.resolve(target)\n }\n}\n\n/**\n * Canonical `<repo>-worktrees` subdirectory names, shared by every command that lays worktrees\n * out under it (`init`'s scaffold, `worktrees add`) or reasons about that layout (`worktrees\n * sync`/`remove`, `gh merge-dev`'s scratch checkout) \u2014 one literal each, not re-typed per site.\n */\nexport const WORKTREE_SUBDIRS = { release: 'release', feature: 'feature', mergeDev: 'merge-dev' } as const\n"],
5
5
  "mappings": "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",
6
6
  "names": ["fs", "os", "path", "process", "ENV_LOAD_FILE", "ENV_CLEAR_FILE", "ENV_LOAD_ROOT_FILE", "INFRA_KIT_SESSION_VAR", "USER_CONFIG_DIR_NAME", "INFRA_KIT_ENV_VAR", "INFRA_KIT_ENV_CONFIG_VAR", "INFRA_KIT_ENV_PROJECT_VAR", "INFRA_KIT_ENV_PROJECT_ROOT_VAR", "INFRA_KIT_ENV_LOADED_AT_VAR", "ENV_VAR_LINE_PATTERN", "UNSET_LINE_PATTERN", "advanceSingleQuoteState", "line", "startInQuote", "inQuote", "i", "decodeSingleQuoted", "raw", "withoutOpen", "readEnvFileContent", "filePath", "forEachAssignment", "content", "visit", "visitUnset", "lines", "index", "match", "unset", "name", "rest", "parts", "open", "continuation", "parseVarNamesFromEnvFile", "names", "parseVarsFromEnvFile", "vars", "value", "parseUnsetNamesFromEnvFile", "getCacheRoot", "xdg", "base", "getSessionCacheDir", "session", "atomicWriteFileSync", "mode", "tmpPath", "error", "WORKTREES_DIR_SUFFIX", "isInEnvLoadScope", "rootFile", "cwd", "realCwd", "safeRealpath", "root", "target", "WORKTREE_SUBDIRS"]
7
7
  }
@@ -0,0 +1,5 @@
1
+ import{S as m,ea as E}from"./chunk-HMXEV7ZN.js";import{p as w}from"./chunk-RVMKL6T4.js";import i from"node:fs/promises";import o from"node:path";import{z as a}from"zod";var c=class extends Error{env;constructor(e,r=null){super(e),this.name="EnvAuthError",this.env=r}};var x="tokens.json",d=1,k=384,u=448,y=a.object({version:a.literal(d).default(d),envs:a.record(a.string().min(1),a.string().min(1))}).strict(),l=async()=>{let t=await E();return o.join(o.dirname(t.userProject),x)},h=async()=>{let t=await l(),e;try{e=await i.readFile(t,"utf-8")}catch{return null}let r;try{r=JSON.parse(e)}catch(s){throw new c(`Invalid JSON in the token store at ${m(t)}: ${s.message}
2
+ Fix or delete the file, then re-add the token with \`infra-kit env-token-set <env>\`.`)}let n=y.safeParse(r);if(!n.success)throw new c(`Invalid token store at ${m(t)}: ${a.prettifyError(n.error)}
3
+ Fix or delete the file, then re-add the token with \`infra-kit env-token-set <env>\`.`);return n.data},v=async t=>{let e=await l(),r=o.dirname(e),n=o.dirname(r),s=o.dirname(n);for(let f of[s,n,r])await i.mkdir(f,{recursive:!0,mode:u}),await i.chmod(f,u);w(e,`${JSON.stringify(t,null,2)}
4
+ `,k),await i.chmod(e,k)},P=async()=>{let t=await l().catch(()=>null);if(t===null)return null;let e=o.dirname(t),r=o.dirname(e),s=[[o.dirname(r),u],[r,u],[e,u],[t,k]];if(!await i.stat(t).then(()=>!0,()=>!1))return null;let g=[];for(let[p,S]of s){let T=(await i.stat(p)).mode&511;T!==S&&(await i.chmod(p,S),g.push(`${m(p)} was 0${T.toString(8)}`))}return g};var j=async t=>{let e=await h();await v({version:d,envs:{...e?.envs,...t}})},O=async t=>{let e=await h();if(!e||!(t in e.envs))return;let r={...e.envs};delete r[t],await v({version:d,envs:r})};var D=(t,e,r)=>t.map(({env:n,source:s})=>({env:n,source:s,hasToken:!!(r||e[n])}));export{c as a,D as b,l as c,h as d,P as e,j as f,O as g};
5
+ //# sourceMappingURL=chunk-S23ECFH4.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/lib/env-tokens/env-tokens.ts", "../src/lib/errors/env-auth-error.ts", "../src/lib/env-tokens/env-token-status.ts"],
4
+ "sourcesContent": ["// DEFAULT import, deliberately \u2014 the same reason config-bootstrap.ts documents: the module is used as\n// `fs.readFile(...)` / `fs.mkdir(...)` so every call is a property lookup on the live module object,\n// which is what `vi.spyOn(fs, \u2026)` patches. A named import (`import { readFile }`) is bound at import\n// time and the spy silently does NOT intercept it \u2014 the assertion goes green while the real call\n// still hits disk. Do not \"modernize\" this import.\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { z } from 'zod'\n\nimport { atomicWriteFileSync } from 'src/lib/constants'\nimport { EnvAuthError } from 'src/lib/errors/env-auth-error'\nimport { getInfraKitConfigPaths } from 'src/lib/infra-kit-config'\nimport { tildify } from 'src/lib/path-display'\n\n/**\n * Basename of the token store. A SIBLING of the layer-3 `infra-kit.json`, never a key inside it:\n * `getInfraKitConfig` only ever globs the three hardcoded `infra-kit.json` paths and its schema is\n * `.strict()`, so an unknown key throws at the LAYER parse and bricks every command on every pinned\n * version. A sibling file is structurally invisible to that loader \u2014 `config-bootstrap.ts` already\n * relies on exactly this for its `.example.jsonc`. That invisibility is the blast-radius guarantee:\n * a corrupt `tokens.json` can only break the readers below, never `worktrees-list`.\n */\nconst TOKEN_STORE_FILE = 'tokens.json'\n\n/** Schema version of the on-disk store. Bump only alongside a migration. */\nconst TOKEN_STORE_VERSION = 1\n\n/** Mode of `tokens.json` itself \u2014 owner read/write only. It holds live credentials. */\nconst TOKEN_FILE_MODE = 0o600\n\n/** Mode of every directory on the way to the store \u2014 owner-only traversal. */\nconst TOKEN_DIR_MODE = 0o700\n\n/**\n * The store's OWN schema: `{ version?: 1, envs: { <env>: <token> } }`. Deliberately NOT derived from\n * `infraKitConfigObject`: this file is not a merge layer, so `.strict()` here is free (a typo is a\n * loud error in three readers, not a bricked CLI).\n */\n// HAND-AUTHORABILITY IS THE CONSTRAINT THIS SHAPE IS CHOSEN FOR, and two earlier fields were\n// dropped for it \u2014 do not re-add either without re-deciding that:\n//\n// - `version` is OPTIONAL (defaulted to 1) because a store typed by a human carries no version\n// key, and a store the CLI refuses to read is a store the human cannot write.\n// - `repoRoot` is GONE, and with it the refusal that compared it against the current checkout.\n// That guard was real: the store directory is keyed on `path.basename(mainRepoRoot)`, so\n// `~/work/api` and `~/oss/api` share ONE token directory and repo B could load (and then\n// overwrite) repo A's credentials. It was removed anyway, knowingly: it also made the CLI refuse\n// every hand-written store, which carries no such field. Hand-authorability wins; the\n// basename-collision risk is ACCEPTED. A weakened version of the guard (warn-and-continue, or\n// \"only check when present\") is NOT the compromise here \u2014 it would re-introduce the same refusal\n// for anyone who did write the field. If you want the guard back, key the store directory on\n// something collision-free instead.\nconst tokenStoreSchema = z\n .object({\n version: z.literal(TOKEN_STORE_VERSION).default(TOKEN_STORE_VERSION),\n envs: z.record(z.string().min(1), z.string().min(1)),\n })\n .strict()\n\n/** The parsed `tokens.json` shape: `{ version, envs }` \u2014 `version` defaulted to 1 when absent on disk. */\nexport type TokenStore = z.infer<typeof tokenStoreSchema>\n\n/**\n * Absolute path to the per-project token store: `~/.infra-kit/projects/<repo>/tokens.json`.\n *\n * Derived from {@link getInfraKitConfigPaths} rather than re-deriving the home/projects/repo chain \u2014\n * that resolver already keys the directory off the MAIN repo root (so every worktree of a repo shares\n * one store) and memoizes the two `git rev-parse` spawns.\n *\n * @example\n * await getTokenStorePath() // => '/Users/arthur/.infra-kit/projects/infra-kit/tokens.json'\n */\nexport const getTokenStorePath = async (): Promise<string> => {\n const paths = await getInfraKitConfigPaths()\n\n return path.join(path.dirname(paths.userProject), TOKEN_STORE_FILE)\n}\n\n/**\n * Read the token store, or `null` when it does not exist.\n *\n * ABSENCE IS NOT AN ERROR \u2014 a fresh machine has no store, and every caller must be able to say \"no\n * tokens yet\" without a try/catch. The two things that DO throw are malformed JSON and a schema\n * mismatch: both are states only a human can fix, so both are loud.\n *\n * @example\n * const store = await readTokenStore()\n * store?.envs.dev // => 'dp.st.dev.xxxx' | undefined\n * // no file on disk => null\n * // garbage on disk => throws 'Invalid token store at ~/.infra-kit/projects/api/tokens.json: \u2026'\n */\nexport const readTokenStore = async (): Promise<TokenStore | null> => {\n const storePath = await getTokenStorePath()\n\n let raw: string\n\n try {\n raw = await fs.readFile(storePath, 'utf-8')\n } catch {\n return null\n }\n\n // Every refusal below is an EnvAuthError, not a plain Error. A broken store is the MOST durable\n // env-auth failure there is \u2014 only a human can fix it \u2014 and downstream callers classify on that\n // CLASS (see EnvAuthError's doc). `env` is null: no ONE environment is at fault.\n let parsedRaw: unknown\n\n try {\n parsedRaw = JSON.parse(raw)\n } catch (err) {\n throw new EnvAuthError(\n `Invalid JSON in the token store at ${tildify(storePath)}: ${(err as Error).message}\\n` +\n `Fix or delete the file, then re-add the token with \\`infra-kit env-token-set <env>\\`.`,\n )\n }\n\n const result = tokenStoreSchema.safeParse(parsedRaw)\n\n if (!result.success) {\n throw new EnvAuthError(\n `Invalid token store at ${tildify(storePath)}: ${z.prettifyError(result.error)}\\n` +\n `Fix or delete the file, then re-add the token with \\`infra-kit env-token-set <env>\\`.`,\n )\n }\n\n return result.data\n}\n\n/**\n * Persist the store atomically at 0600, tightening every directory on the way to it to 0700.\n *\n * The chmods are not belt-and-braces: the config bootstrap already seeds\n * `~/.infra-kit/projects/<repo>/` at the default umask (0755), so an EXISTING directory is\n * world-readable and `mkdir`'s mode argument is a no-op for it. The same holds for the file \u2014 a\n * hand-written `tokens.json` is 0644 \u2014 so the modes of the whole credential path are (re)asserted on\n * EVERY write, not only on the writes that created it. Self-healing by construction: a plain\n * `env-token-set` is enough to fix a store a human typed.\n *\n * @example\n * await writeTokenStore({ version: 1, envs: { dev: 'dp.st.dev.x' } })\n * // ~/.infra-kit/projects/api/tokens.json -rw-------\n * // ~/.infra-kit/projects/api/ drwx------\n */\nexport const writeTokenStore = async (store: TokenStore): Promise<void> => {\n const storePath = await getTokenStorePath()\n\n const projectDir = path.dirname(storePath)\n const projectsDir = path.dirname(projectDir)\n const userConfigDir = path.dirname(projectsDir)\n\n for (const dir of [userConfigDir, projectsDir, projectDir]) {\n await fs.mkdir(dir, { recursive: true, mode: TOKEN_DIR_MODE })\n await fs.chmod(dir, TOKEN_DIR_MODE)\n }\n\n atomicWriteFileSync(storePath, `${JSON.stringify(store, null, 2)}\\n`, TOKEN_FILE_MODE)\n\n // The rename above already lands a fresh 0600 inode, but the mode of a credential file is not a\n // thing to leave to the umask that happened to be in effect \u2014 assert it outright.\n await fs.chmod(storePath, TOKEN_FILE_MODE)\n}\n\n/**\n * Re-assert the store's 0600 / 0700 modes without rewriting it, for a store something other than\n * {@link writeTokenStore} touched (an editor's save-and-rename, a `cp -r`, a synced dotfiles dir).\n * Returns the paths it changed, or `null` when there is no store to protect.\n *\n * @example\n * await tightenTokenStoreModes() // => ['~/.infra-kit/projects/api/tokens.json was 0644']\n */\nexport const tightenTokenStoreModes = async (): Promise<string[] | null> => {\n // Outside a git repo there is no project, so no store either.\n const storePath = await getTokenStorePath().catch(() => {\n return null\n })\n\n if (storePath === null) return null\n\n const projectDir = path.dirname(storePath)\n const projectsDir = path.dirname(projectDir)\n const userConfigDir = path.dirname(projectsDir)\n\n const chain: Array<[target: string, mode: number]> = [\n [userConfigDir, TOKEN_DIR_MODE],\n [projectsDir, TOKEN_DIR_MODE],\n [projectDir, TOKEN_DIR_MODE],\n [storePath, TOKEN_FILE_MODE],\n ]\n\n const exists = await fs.stat(storePath).then(\n () => {\n return true\n },\n () => {\n return false\n },\n )\n\n if (!exists) return null\n\n const tightened: string[] = []\n\n for (const [target, mode] of chain) {\n const actual = (await fs.stat(target)).mode & 0o777\n\n if (actual === mode) continue\n\n await fs.chmod(target, mode)\n tightened.push(`${tildify(target)} was 0${actual.toString(8)}`)\n }\n\n return tightened\n}\n\n/**\n * Add or replace one environment's token, read-modify-write, stamping the current `version`. Inherits\n * {@link readTokenStore}'s refusals: a corrupt store is never silently overwritten.\n *\n * @example\n * await setToken('dev', 'dp.st.dev.xxxxxxxx')\n * // tokens.json => { version: 1, envs: { dev: 'dp.st.dev.xxxxxxxx' } }\n */\nexport const setToken = async (env: string, token: string): Promise<void> => {\n await setTokens({ [env]: token })\n}\n\n/**\n * Add or replace several environments' tokens in ONE read-modify-write, so a bulk import never leaves\n * the store half-written between two of its entries.\n *\n * @example\n * await setTokens({ dev: 'dp.st.dev.x', arthur: 'dp.st.arthur.y' })\n * // tokens.json => { version: 1, envs: { \u2026existing, dev: 'dp.st.dev.x', arthur: 'dp.st.arthur.y' } }\n */\nexport const setTokens = async (tokens: Record<string, string>): Promise<void> => {\n const existing = await readTokenStore()\n\n await writeTokenStore({\n version: TOKEN_STORE_VERSION,\n envs: { ...existing?.envs, ...tokens },\n })\n}\n\n/**\n * Drop one environment's token. A no-op when the store (or the key) is absent \u2014 removing something\n * that is not there is the state the caller asked for.\n *\n * Removing a token here does NOT revoke it in Doppler; callers say so.\n *\n * @example\n * await removeToken('dev')\n * // tokens.json => { version: 1, envs: {} }\n */\nexport const removeToken = async (env: string): Promise<void> => {\n const existing = await readTokenStore()\n\n if (!existing || !(env in existing.envs)) return\n\n const envs = { ...existing.envs }\n\n delete envs[env]\n\n await writeTokenStore({\n version: TOKEN_STORE_VERSION,\n envs,\n })\n}\n", "/**\n * The DURABLE, USER-FIXABLE env-auth failure \u2014 as a TYPE rather than a string.\n *\n * Throw this (or a subclass) \u2014 never a plain `Error` \u2014 for anything a user must fix before\n * env-load can work: no token minted, a corrupt token store, a foreign token store.\n * `DopplerAuthError extends EnvAuthError` for the subset that is specifically \"Doppler refused the\n * token we sent\".\n *\n * @example\n * // no token minted for this env (integrations/doppler/token-resolver.ts)\n * throw new EnvAuthError(buildMissingTokenMessage('dev', storePath), 'dev')\n * @example\n * // the token store itself is unusable \u2014 no single env is at fault, so `env` stays null\n * throw new EnvAuthError(`Invalid JSON in the token store at ${storePath} \u2026`)\n */\n// WHY THIS EXISTS (and why it is deliberately NOT a Doppler type): every consumer of the auth\n// channel needs to classify a failure by its CLASS, not by re-deriving the answer from a message\n// some other module owns \u2014 and it has to be throwable from EVERY module that can produce the\n// class. `lib/env-tokens` (the store) is a layer BELOW `integrations/doppler`, so a Doppler-owned\n// base type could not be thrown there without a layering inversion and an import cycle. Hence a\n// neutral base here in `lib/errors`.\nexport class EnvAuthError extends Error {\n /**\n * The env (= Doppler config) whose token is at fault, or `null` when the failure is not attributable\n * to ONE env (a corrupt or foreign token store breaks every env at once). `null` is honest: do NOT\n * invent an env to fill it \u2014 the consumer names the env it was TRYING to load, which it already\n * knows.\n */\n readonly env: string | null\n\n constructor(message: string, env: string | null = null) {\n super(message)\n this.name = 'EnvAuthError'\n this.env = env\n }\n}\n\n/**\n * The TYPE GUARD every consumer of the auth channel classifies on \u2014 the single question \"is this a\n * durable, user-fixable env-auth failure?\", answered by the error's CLASS and never by its text.\n *\n * Deliberately WIDER than `isDopplerAuthError`: that one means \"Doppler refused us\", which is only\n * one of the durable failures \u2014 a missing token never reaches Doppler at all, and a corrupt store\n * never reaches the resolver.\n *\n * @example\n * isEnvAuthFailure(new EnvAuthError('No Doppler service token for env \"dev\".', 'dev')) // => true\n * isEnvAuthFailure(new DopplerAuthError('dev', 'revoked')) // => true (subclass)\n * isEnvAuthFailure(new Error('connect ETIMEDOUT')) // => false (transient)\n */\nexport const isEnvAuthFailure = (error: unknown): error is EnvAuthError => {\n return error instanceof EnvAuthError\n}\n", "import type { ProjectEnv, ProjectEnvSource } from 'src/lib/project-envs'\n\n/** One row of the token column: an env, where we learned it exists, and whether a token resolves. */\nexport interface EnvTokenStatus {\n env: string\n /** `gh-workflow` \u2014 declared in a workflow's dispatch options. `token-only` \u2014 we hold a token, no workflow names it. */\n source: ProjectEnvSource\n hasToken: boolean\n}\n\n/**\n * Build the token column: one row per known environment, reporting only WHETHER a token resolves \u2014\n * never the token itself. Mirrors `resolveEnvToken`'s precedence (`INFRA_KIT_ENV_TOKEN` shadows the\n * store for every env) without importing it, so this stays a pure, no-I/O function the same way\n * `buildEnvTokenRows` in `env-token-list` is.\n *\n * @example\n * buildEnvTokenStatus([{ env: 'dev', source: 'gh-workflow' }], { dev: 'dp.st.dev.xxxx' }, undefined)\n * // => [{ env: 'dev', source: 'gh-workflow', hasToken: true }]\n */\nexport const buildEnvTokenStatus = (\n envs: ProjectEnv[],\n storeTokens: Record<string, string>,\n envToken: string | undefined,\n): EnvTokenStatus[] => {\n return envs.map(({ env, source }) => {\n return { env, source, hasToken: Boolean(envToken || storeTokens[env]) }\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["fs", "path", "z", "EnvAuthError", "message", "env", "TOKEN_STORE_FILE", "TOKEN_STORE_VERSION", "TOKEN_FILE_MODE", "TOKEN_DIR_MODE", "tokenStoreSchema", "z", "getTokenStorePath", "paths", "getInfraKitConfigPaths", "path", "readTokenStore", "storePath", "raw", "fs", "parsedRaw", "err", "EnvAuthError", "tildify", "result", "writeTokenStore", "store", "projectDir", "projectsDir", "userConfigDir", "dir", "atomicWriteFileSync", "tightenTokenStoreModes", "chain", "tightened", "target", "mode", "actual", "setTokens", "tokens", "existing", "readTokenStore", "writeTokenStore", "TOKEN_STORE_VERSION", "removeToken", "env", "envs", "buildEnvTokenStatus", "envs", "storeTokens", "envToken", "env", "source"]
7
+ }
@@ -1,3 +1,3 @@
1
- import{j as C,m as O,n as D}from"./chunk-REDCBY4O.js";import{e as S}from"./chunk-GCOYOWGH.js";import k from"node:fs";import{homedir as Te}from"node:os";import{dirname as _,join as W}from"node:path";import d from"node:process";import{fileURLToPath as Fe}from"node:url";import{execFile as re}from"node:child_process";import{createHash as ne}from"node:crypto";import{existsSync as F,readFileSync as h}from"node:fs";import oe from"node:http";import se from"node:https";import ie from"node:net";import{homedir as le}from"node:os";import{dirname as N,join as p}from"node:path";import f from"node:process";import ae from"node:tls";import{fileURLToPath as ce}from"node:url";import{promisify as ue}from"node:util";var ee=/^[\w@%+=:,./-]+$/,te="'\\''",T=e=>ee.test(e)?e:`'${e.replaceAll("'",te)}'`,x=e=>e.map(T).join(" ");var de=ue(re),me=e=>{let t=JSON.parse(h(e,"utf-8")),r=typeof t.bin=="string"?t.bin:t.bin?.portless;return r==null||r===""?null:r},E=()=>{try{let e=N(ce(import.meta.url));for(;;){let t=p(e,"node_modules","portless","package.json");if(F(t)){let n=me(t);return n==null?null:p(N(t),n)}let r=N(e);if(r===e)return null;e=r}}catch{return null}},v,M=()=>(v===void 0&&(v=E()),v),U=(e,t)=>{let r=[t.execPath??f.execPath,t.bin,...e];return(t.sudo===!0?"sudo ":"")+x(r)},pe=1500,L=1500,fe="x-portless",I="127.0.0.1",ge="localhost",Pe="sh.portless.proxy",he=`/Library/LaunchDaemons/${Pe}.plist`,ye="/etc/systemd/system/portless.service",it="portless",Se=(e=F)=>{try{return f.platform==="darwin"?e(he)?"yes":"no":f.platform==="linux"?e(ye)?"yes":"no":"unknown"}catch{return"unknown"}},ke=e=>new Promise(t=>{let r=ie.connect({host:I,port:e}),n=o=>{r.destroy(),t(o)};r.setTimeout(L),r.once("connect",()=>{n(!0)}),r.once("timeout",()=>{n(!1)}),r.once("error",()=>{n(!1)})}),be=(e,t)=>new Promise(r=>{let o=(t?se.request:oe.request)({host:I,port:e,method:"HEAD",path:"/",timeout:L,...t?{rejectUnauthorized:!1,servername:ge}:{}},s=>{s.resume(),r(s.headers[fe]==="1")});o.on("error",()=>{r(!1)}),o.on("timeout",()=>{o.destroy(),r(!1)}),o.end()}),xe=async(e,{timeoutMs:t})=>{let r=M();if(r==null)throw new Error("portless is not installed (not resolvable from node_modules)");await de(f.execPath,[r,...e],{signal:AbortSignal.timeout(t),encoding:"utf-8",env:D(f.env)})},w=()=>f.env.PORTLESS_STATE_DIR??p(le(),".portless"),Ne="ca.pem",ve="ca.trusted",B=()=>p(w(),Ne),lt=()=>{try{let e=h(p(w(),ve),"utf-8").trim();return e===""?!1:ne("sha256").update(h(B())).digest("hex")===e.toLowerCase()}catch{return!1}},at=(e,t)=>new Promise(r=>{let n;try{n=h(B())}catch{r({ok:!1,code:"ENOENT"});return}let o=ae.connect({host:I,port:e,servername:t,ca:[n],rejectUnauthorized:!0},()=>{let s=o.authorizationError,i=o.authorized;o.destroy(),r(i?{ok:!0}:{ok:!1,code:s?.code??s?.message??"UNKNOWN"})});o.setTimeout(L),o.once("timeout",()=>{o.destroy(),r({ok:!1,code:"ETIMEDOUT"})}),o.once("error",s=>{o.destroy(),r({ok:!1,code:s.code??"UNKNOWN"})})}),ct=()=>{try{let e=JSON.parse(h(p(w(),"routes.json"),"utf-8"));return Array.isArray(e)?e.flatMap(t=>{let{hostname:r,port:n}=t??{};return typeof r!="string"||r===""||typeof n!="number"?[]:[{name:r,port:n}]}):[]}catch{return[]}},ut=(e={})=>{let t=e.bin===void 0?M():e.bin,r=e.run??xe,n=e.isListening??ke,o=e.isProxyServing??be,s=e.isServiceInstalled??Se,i=e.timeoutMs??pe,a=null,l=async u=>{try{return await r(u,{timeoutMs:i}),!0}catch{return!1}},c=async()=>(a??=await l(["--version"]),a);return{binPath:()=>t,isAvailable:c,isProxyServing:async(u,P)=>!await c()||!await n(u)?!1:o(u,P),probeProxy:async(u,P)=>await n(u)?await o(u,P)?"serving":"not-portless":"daemon-down",isServiceInstalled:s,registerAlias:async(u,P)=>await c()?l(["alias",u,String(P)]):!1,removeAlias:async u=>{await c()&&await l(["alias","--remove",u])}}};import y from"node:fs";import{basename as z,dirname as $,join as j}from"node:path";import G from"node:process";var R=e=>j(e,S,"node"),H=e=>`${R(e)}.source.json`,Ee=e=>{if(typeof e!="object"||e===null)return!1;let t=e,r=["version","arch","platform","source","refreshedAt","versionChangedAt"];return(t.method==="hardlink"||t.method==="copy")&&r.every(n=>typeof t[n]=="string")&&(t.sourceSize===void 0||typeof t.sourceSize=="number")},Le=y.constants.COPYFILE_FICLONE|y.constants.COPYFILE_EXCL,Ie=493,we=(e,t=y)=>{try{let r=JSON.parse(t.readFileSync(H(e),"utf8"));return Ee(r)?r:null}catch{return null}},J=(e,t)=>e.ino===t.ino&&e.dev===t.dev,K=e=>{let{home:t,execPath:r,fs:n=y}=e,o=R(t);try{let s=n.lstatSync(o,{throwIfNoEntry:!1}),i=n.statSync(r,{throwIfNoEntry:!1});return s===void 0||i===void 0||!s.isFile()?null:J(s,i)?o:null}catch{return null}},Y=(e,t)=>e.version===t.version&&e.arch===t.arch&&e.platform===t.platform,Re=(e,t,r,n)=>Y(r,n)?J(e,t)?!0:r.method==="copy"&&r.sourceSize===t.size:!1,A=(e,t)=>{try{t.unlinkSync(e)}catch{}},Ae=(e,t,r)=>{let n;try{n=r.readdirSync(e)}catch{return}for(let o of n)t.some(i=>o.startsWith(i))&&A(j(e,o),r)},_e=(e,t,r)=>{try{return r.linkSync(e,t),"hardlink"}catch{return r.copyFileSync(e,t,Le),r.chmodSync(t,Ie),"copy"}},Ce=(e,t,r)=>{let n=`${t}.tmp-${G.pid}`;try{let o=_e(e,n,r);return r.renameSync(n,t),o}catch(o){throw A(n,r),o}},Oe=(e,t,r)=>{let n=`${e}.tmp-${G.pid}`;try{r.writeFileSync(n,`${JSON.stringify(t,null,2)}
1
+ import{j as C,m as O,n as D}from"./chunk-REDCBY4O.js";import{e as S}from"./chunk-RVMKL6T4.js";import k from"node:fs";import{homedir as Te}from"node:os";import{dirname as _,join as W}from"node:path";import d from"node:process";import{fileURLToPath as Fe}from"node:url";import{execFile as re}from"node:child_process";import{createHash as ne}from"node:crypto";import{existsSync as F,readFileSync as h}from"node:fs";import oe from"node:http";import se from"node:https";import ie from"node:net";import{homedir as le}from"node:os";import{dirname as N,join as p}from"node:path";import f from"node:process";import ae from"node:tls";import{fileURLToPath as ce}from"node:url";import{promisify as ue}from"node:util";var ee=/^[\w@%+=:,./-]+$/,te="'\\''",T=e=>ee.test(e)?e:`'${e.replaceAll("'",te)}'`,x=e=>e.map(T).join(" ");var de=ue(re),me=e=>{let t=JSON.parse(h(e,"utf-8")),r=typeof t.bin=="string"?t.bin:t.bin?.portless;return r==null||r===""?null:r},E=()=>{try{let e=N(ce(import.meta.url));for(;;){let t=p(e,"node_modules","portless","package.json");if(F(t)){let n=me(t);return n==null?null:p(N(t),n)}let r=N(e);if(r===e)return null;e=r}}catch{return null}},v,M=()=>(v===void 0&&(v=E()),v),U=(e,t)=>{let r=[t.execPath??f.execPath,t.bin,...e];return(t.sudo===!0?"sudo ":"")+x(r)},pe=1500,L=1500,fe="x-portless",I="127.0.0.1",ge="localhost",Pe="sh.portless.proxy",he=`/Library/LaunchDaemons/${Pe}.plist`,ye="/etc/systemd/system/portless.service",it="portless",Se=(e=F)=>{try{return f.platform==="darwin"?e(he)?"yes":"no":f.platform==="linux"?e(ye)?"yes":"no":"unknown"}catch{return"unknown"}},ke=e=>new Promise(t=>{let r=ie.connect({host:I,port:e}),n=o=>{r.destroy(),t(o)};r.setTimeout(L),r.once("connect",()=>{n(!0)}),r.once("timeout",()=>{n(!1)}),r.once("error",()=>{n(!1)})}),be=(e,t)=>new Promise(r=>{let o=(t?se.request:oe.request)({host:I,port:e,method:"HEAD",path:"/",timeout:L,...t?{rejectUnauthorized:!1,servername:ge}:{}},s=>{s.resume(),r(s.headers[fe]==="1")});o.on("error",()=>{r(!1)}),o.on("timeout",()=>{o.destroy(),r(!1)}),o.end()}),xe=async(e,{timeoutMs:t})=>{let r=M();if(r==null)throw new Error("portless is not installed (not resolvable from node_modules)");await de(f.execPath,[r,...e],{signal:AbortSignal.timeout(t),encoding:"utf-8",env:D(f.env)})},w=()=>f.env.PORTLESS_STATE_DIR??p(le(),".portless"),Ne="ca.pem",ve="ca.trusted",B=()=>p(w(),Ne),lt=()=>{try{let e=h(p(w(),ve),"utf-8").trim();return e===""?!1:ne("sha256").update(h(B())).digest("hex")===e.toLowerCase()}catch{return!1}},at=(e,t)=>new Promise(r=>{let n;try{n=h(B())}catch{r({ok:!1,code:"ENOENT"});return}let o=ae.connect({host:I,port:e,servername:t,ca:[n],rejectUnauthorized:!0},()=>{let s=o.authorizationError,i=o.authorized;o.destroy(),r(i?{ok:!0}:{ok:!1,code:s?.code??s?.message??"UNKNOWN"})});o.setTimeout(L),o.once("timeout",()=>{o.destroy(),r({ok:!1,code:"ETIMEDOUT"})}),o.once("error",s=>{o.destroy(),r({ok:!1,code:s.code??"UNKNOWN"})})}),ct=()=>{try{let e=JSON.parse(h(p(w(),"routes.json"),"utf-8"));return Array.isArray(e)?e.flatMap(t=>{let{hostname:r,port:n}=t??{};return typeof r!="string"||r===""||typeof n!="number"?[]:[{name:r,port:n}]}):[]}catch{return[]}},ut=(e={})=>{let t=e.bin===void 0?M():e.bin,r=e.run??xe,n=e.isListening??ke,o=e.isProxyServing??be,s=e.isServiceInstalled??Se,i=e.timeoutMs??pe,a=null,l=async u=>{try{return await r(u,{timeoutMs:i}),!0}catch{return!1}},c=async()=>(a??=await l(["--version"]),a);return{binPath:()=>t,isAvailable:c,isProxyServing:async(u,P)=>!await c()||!await n(u)?!1:o(u,P),probeProxy:async(u,P)=>await n(u)?await o(u,P)?"serving":"not-portless":"daemon-down",isServiceInstalled:s,registerAlias:async(u,P)=>await c()?l(["alias",u,String(P)]):!1,removeAlias:async u=>{await c()&&await l(["alias","--remove",u])}}};import y from"node:fs";import{basename as z,dirname as $,join as j}from"node:path";import G from"node:process";var R=e=>j(e,S,"node"),H=e=>`${R(e)}.source.json`,Ee=e=>{if(typeof e!="object"||e===null)return!1;let t=e,r=["version","arch","platform","source","refreshedAt","versionChangedAt"];return(t.method==="hardlink"||t.method==="copy")&&r.every(n=>typeof t[n]=="string")&&(t.sourceSize===void 0||typeof t.sourceSize=="number")},Le=y.constants.COPYFILE_FICLONE|y.constants.COPYFILE_EXCL,Ie=493,we=(e,t=y)=>{try{let r=JSON.parse(t.readFileSync(H(e),"utf8"));return Ee(r)?r:null}catch{return null}},J=(e,t)=>e.ino===t.ino&&e.dev===t.dev,K=e=>{let{home:t,execPath:r,fs:n=y}=e,o=R(t);try{let s=n.lstatSync(o,{throwIfNoEntry:!1}),i=n.statSync(r,{throwIfNoEntry:!1});return s===void 0||i===void 0||!s.isFile()?null:J(s,i)?o:null}catch{return null}},Y=(e,t)=>e.version===t.version&&e.arch===t.arch&&e.platform===t.platform,Re=(e,t,r,n)=>Y(r,n)?J(e,t)?!0:r.method==="copy"&&r.sourceSize===t.size:!1,A=(e,t)=>{try{t.unlinkSync(e)}catch{}},Ae=(e,t,r)=>{let n;try{n=r.readdirSync(e)}catch{return}for(let o of n)t.some(i=>o.startsWith(i))&&A(j(e,o),r)},_e=(e,t,r)=>{try{return r.linkSync(e,t),"hardlink"}catch{return r.copyFileSync(e,t,Le),r.chmodSync(t,Ie),"copy"}},Ce=(e,t,r)=>{let n=`${t}.tmp-${G.pid}`;try{let o=_e(e,n,r);return r.renameSync(n,t),o}catch(o){throw A(n,r),o}},Oe=(e,t,r)=>{let n=`${e}.tmp-${G.pid}`;try{r.writeFileSync(n,`${JSON.stringify(t,null,2)}
2
2
  `),r.renameSync(n,e)}catch(o){throw A(n,r),o}},De=(e,t,r,n,o)=>{let s=e!==null&&Y(e,n)&&(e.sourceSize===void 0||e.sourceSize===r.size);return{method:t,version:n.version,arch:n.arch,platform:n.platform,source:n.execPath,...t==="copy"?{sourceSize:r.size}:{},refreshedAt:o,versionChangedAt:s?e.versionChangedAt:o}},q=e=>{let{home:t,execPath:r,version:n,fs:o=y,now:s=()=>new Date}=e,i=R(t),a=H(t),l=(c,m)=>({kind:"node",outcome:c,node:i,source:r,version:n,method:m});if(e.platform!=="darwin"&&e.platform!=="linux")return l("skipped-platform",null);if(!e.isGlobal())return l("skipped-local",null);try{o.mkdirSync($(i),{recursive:!0});let c=o.lstatSync(i,{throwIfNoEntry:!1});if(c!==void 0&&!c.isFile())return l("failed",null);let m=o.statSync(r,{throwIfNoEntry:!1});if(m===void 0)return l("failed",null);let g=we(t,o);if(c!==void 0&&g!==null&&Re(c,m,g,e))return l("unchanged",g.method);Ae($(i),[`${z(i)}.tmp-`,`${z(a)}.tmp-`],o);let b=Ce(r,i,o);return Oe(a,De(g,b,m,e,s().toISOString()),o),l(c===void 0?"created":"refreshed",b)}catch{return l("failed",null)}};var Q=e=>W(e,S,"portless"),Me=(e,t=k.existsSync)=>{let r=W(Q(e),"dist","cli.js");return t(r)?r:null},Lt=(e,t)=>{let r=t.execPath??d.execPath,n=t.stableNode===void 0?K({home:t.home,execPath:r}):t.stableNode;return U(["service","install"],{sudo:!0,bin:Me(t.home,t.exists)??e,execPath:n??r})},X=Symbol("absent"),Z=Symbol("not-a-symlink"),Ue=(e,t)=>{let r=t.lstatSync(e,{throwIfNoEntry:!1});return r===void 0?X:r.isSymbolicLink()?t.readlinkSync(e):Z},Be=(e,t,r)=>{let n=`${t}.tmp-${d.pid}`;try{r.unlinkSync(n)}catch{}r.symlinkSync(e,n);try{r.renameSync(n,t)}catch(o){try{r.unlinkSync(n)}catch{}throw o}},ze=e=>{let{resolveBin:t,isGlobal:r,home:n,fs:o=k}=e,s=Q(n),i=t();if(i===null)return{kind:"link",outcome:"skipped-unresolved",target:null,link:s};let a=_(_(i));if(!r())return{kind:"link",outcome:"skipped-local",target:a,link:s};try{o.mkdirSync(_(s),{recursive:!0});let l=Ue(s,o);return l===a?{kind:"link",outcome:"unchanged",target:a,link:s}:l===Z?{kind:"link",outcome:"failed",target:a,link:s}:(Be(a,s,o),{kind:"link",outcome:l===X?"created":"repointed",target:a,link:s})}catch{return{kind:"link",outcome:"failed",target:a,link:s}}},$e=()=>{let e=Te(),t,r=()=>(t??=C({selfRealPath:k.realpathSync(Fe(import.meta.url)),env:d.env,realpath:O,home:e,exists:k.existsSync}),t);return{link:{resolveBin:E,isGlobal:r,home:e},node:{isGlobal:r,home:e,execPath:d.execPath,version:d.version,arch:d.arch,platform:d.platform}}},V=(e,t,r)=>{try{e(r(),t)}catch{}},It=(e,t)=>{let r=t??$e();V(e,"portless link",()=>ze(r.link)),V(e,"portless node",()=>q(r.node))};export{T as a,x as b,E as c,U as d,Pe as e,he as f,ye as g,it as h,ke as i,be as j,w as k,B as l,lt as m,at as n,ct as o,ut as p,R as q,we as r,q as s,Q as t,Me as u,Lt as v,ze as w,$e as x,It as y};
3
- //# sourceMappingURL=chunk-PP44RGIU.js.map
3
+ //# sourceMappingURL=chunk-VZAXKGEY.js.map
@@ -1,2 +1,2 @@
1
- var i={name:"infra-kit",type:"module",version:"0.41.0",repository:{type:"git",url:"git+https://github.com/ArthurSaenz/infra-kit.git",directory:"apps/infra-kit/cli"},files:["dist"],description:"infra-kit",bin:{"infra-kit":"dist/cli.js",ik:"dist/cli.js","ik-mcp":"dist/mcp-proxy.js"},engines:{node:">=24.x"},scripts:{build:"pnpm run clean-artifacts && node ./scripts/build.js",prepack:"pnpm run build","infra-kit-check":"pnpm exec infra-kit audit","clean-artifacts":"rm -rf dist","clean-cache":"rm -rf node_modules/.cache .eslintcache tsconfig.tsbuildinfo .turbo .swc","prettier-fix":"pnpm exec prettier **/* --write --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore","prettier-check":"pnpm exec prettier **/* --check --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore","eslint-check":"pnpm exec eslint --cache --report-unused-disable-directives ./src","eslint-fix":"pnpm exec eslint --cache --quiet --report-unused-disable-directives ./src --fix","ts-check":"tsc --noEmit",test:"pnpm exec vitest run --reporter=minimal","test-watch":"pnpm exec vitest --watch --silent passed-only","test-ui":"pnpm exec vitest --ui --silent passed-only","test-report":"pnpm exec vitest run --coverage --silent passed-only","qa:pty":"INFRA_KIT_REQUIRE_PTY=1 pnpm exec vitest run --reporter=minimal src/tui/__tests__/stdin-pause-pty.test.ts src/entry/__tests__/quit-keys-pty.test.ts src/entry/__tests__/post-run-pause-pty.test.ts",qa:"pnpm run prettier-check && pnpm run eslint-check && pnpm run ts-check && pnpm run test && echo \u2705 Success",fix:"pnpm run prettier-fix && pnpm run eslint-fix && pnpm run qa"},dependencies:{"@aws-lambda-powertools/logger":"^2.35.0","@inquirer/checkbox":"^5.2.6","@inquirer/confirm":"^6.3.3","@inquirer/input":"^5.1.7","@inquirer/password":"^5.2.3","@inquirer/select":"^5.2.6","@slip-stream-kit/config":"workspace:^",chalk:"^6.0.1",chokidar:"^5.0.0",commander:"^15.0.0",fastify:"^5.12.5",ink:"^8.0.0",pino:"^10.4.0","pino-pretty":"^13.2.0",portless:"^0.15.7",react:"19.3.0",yaml:"^2.9.1",zod:"^4.6.5",zx:"^8.8.5"},devDependencies:{"@slip-stream-kit/eslint-plugin":"workspace:*","@types/aws-lambda":"catalog:","@types/react":"catalog:","@wl/eslint-config":"workspace:*","@wl/vitest-config":"workspace:*",esbuild:"^0.28.2","ink-testing-library":"^4.0.0",typescript:"^6.0.3"}};export{i as a};
2
- //# sourceMappingURL=chunk-KFQKVU6O.js.map
1
+ var i={name:"infra-kit",type:"module",version:"0.42.0",repository:{type:"git",url:"git+https://github.com/ArthurSaenz/infra-kit.git",directory:"apps/infra-kit/cli"},files:["dist"],description:"infra-kit",bin:{"infra-kit":"dist/cli.js",ik:"dist/cli.js","ik-mcp":"dist/mcp-proxy.js"},engines:{node:">=24.x"},scripts:{build:"pnpm run clean-artifacts && node ./scripts/build.js",prepack:"pnpm run build","infra-kit-check":"pnpm exec infra-kit audit","clean-artifacts":"rm -rf dist","clean-cache":"rm -rf node_modules/.cache .eslintcache tsconfig.tsbuildinfo .turbo .swc","prettier-fix":"pnpm exec prettier **/* --write --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore","prettier-check":"pnpm exec prettier **/* --check --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore","eslint-check":"pnpm exec eslint --cache --report-unused-disable-directives ./src","eslint-fix":"pnpm exec eslint --cache --quiet --report-unused-disable-directives ./src --fix","ts-check":"tsc --noEmit",test:"pnpm exec vitest run --reporter=minimal","test-watch":"pnpm exec vitest --watch --silent passed-only","test-ui":"pnpm exec vitest --ui --silent passed-only","test-report":"pnpm exec vitest run --coverage --silent passed-only","qa:pty":"INFRA_KIT_REQUIRE_PTY=1 pnpm exec vitest run --reporter=minimal src/tui/__tests__/stdin-pause-pty.test.ts src/entry/__tests__/quit-keys-pty.test.ts src/entry/__tests__/post-run-pause-pty.test.ts",qa:"pnpm run prettier-check && pnpm run eslint-check && pnpm run ts-check && pnpm run test && echo \u2705 Success",fix:"pnpm run prettier-fix && pnpm run eslint-fix && pnpm run qa"},dependencies:{"@inquirer/checkbox":"^5.2.8","@inquirer/confirm":"^6.3.5","@inquirer/input":"^5.1.9","@inquirer/password":"^5.2.5","@inquirer/select":"^5.2.8","@slip-stream-kit/config":"workspace:^",chalk:"^6.0.1",chokidar:"^6.0.0",commander:"^15.0.0",fastify:"^5.12.7",ink:"^8.0.0",pino:"^10.4.0","pino-pretty":"^13.2.0",portless:"^0.15.12",react:"19.3.1",yaml:"^2.9.1",zod:"^4.6.7",zx:"^8.8.5"},devDependencies:{"@slip-stream-kit/eslint-plugin":"workspace:*","@types/aws-lambda":"catalog:","@types/react":"catalog:","@wl/eslint-config":"workspace:*","@wl/vitest-config":"workspace:*",esbuild:"^0.28.2","ink-testing-library":"^4.0.0",typescript:"^6.0.3"}};export{i as a};
2
+ //# sourceMappingURL=chunk-YSR7UND3.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"infra-kit\",\n \"type\": \"module\",\n \"version\": \"0.41.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ArthurSaenz/infra-kit.git\",\n \"directory\": \"apps/infra-kit/cli\"\n },\n \"files\": [\n \"dist\"\n ],\n \"description\": \"infra-kit\",\n \"bin\": {\n \"infra-kit\": \"dist/cli.js\",\n \"ik\": \"dist/cli.js\",\n \"ik-mcp\": \"dist/mcp-proxy.js\"\n },\n \"engines\": {\n \"node\": \">=24.x\"\n },\n \"scripts\": {\n \"build\": \"pnpm run clean-artifacts && node ./scripts/build.js\",\n \"prepack\": \"pnpm run build\",\n \"infra-kit-check\": \"pnpm exec infra-kit audit\",\n \"clean-artifacts\": \"rm -rf dist\",\n \"clean-cache\": \"rm -rf node_modules/.cache .eslintcache tsconfig.tsbuildinfo .turbo .swc\",\n \"prettier-fix\": \"pnpm exec prettier **/* --write --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore\",\n \"prettier-check\": \"pnpm exec prettier **/* --check --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore\",\n \"eslint-check\": \"pnpm exec eslint --cache --report-unused-disable-directives ./src\",\n \"eslint-fix\": \"pnpm exec eslint --cache --quiet --report-unused-disable-directives ./src --fix\",\n \"ts-check\": \"tsc --noEmit\",\n \"test\": \"pnpm exec vitest run --reporter=minimal\",\n \"test-watch\": \"pnpm exec vitest --watch --silent passed-only\",\n \"test-ui\": \"pnpm exec vitest --ui --silent passed-only\",\n \"test-report\": \"pnpm exec vitest run --coverage --silent passed-only\",\n \"qa:pty\": \"INFRA_KIT_REQUIRE_PTY=1 pnpm exec vitest run --reporter=minimal src/tui/__tests__/stdin-pause-pty.test.ts src/entry/__tests__/quit-keys-pty.test.ts src/entry/__tests__/post-run-pause-pty.test.ts\",\n \"qa\": \"pnpm run prettier-check && pnpm run eslint-check && pnpm run ts-check && pnpm run test && echo \u2705 Success\",\n \"fix\": \"pnpm run prettier-fix && pnpm run eslint-fix && pnpm run qa\"\n },\n \"dependencies\": {\n \"@aws-lambda-powertools/logger\": \"^2.35.0\",\n \"@inquirer/checkbox\": \"^5.2.6\",\n \"@inquirer/confirm\": \"^6.3.3\",\n \"@inquirer/input\": \"^5.1.7\",\n \"@inquirer/password\": \"^5.2.3\",\n \"@inquirer/select\": \"^5.2.6\",\n \"@slip-stream-kit/config\": \"workspace:^\",\n \"chalk\": \"^6.0.1\",\n \"chokidar\": \"^5.0.0\",\n \"commander\": \"^15.0.0\",\n \"fastify\": \"^5.12.5\",\n \"ink\": \"^8.0.0\",\n \"pino\": \"^10.4.0\",\n \"pino-pretty\": \"^13.2.0\",\n \"portless\": \"^0.15.7\",\n \"react\": \"19.3.0\",\n \"yaml\": \"^2.9.1\",\n \"zod\": \"^4.6.5\",\n \"zx\": \"^8.8.5\"\n },\n \"devDependencies\": {\n \"@slip-stream-kit/eslint-plugin\": \"workspace:*\",\n \"@types/aws-lambda\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"@wl/eslint-config\": \"workspace:*\",\n \"@wl/vitest-config\": \"workspace:*\",\n \"esbuild\": \"^0.28.2\",\n \"ink-testing-library\": \"^4.0.0\",\n \"typescript\": \"^6.0.3\"\n }\n}\n"],
5
- "mappings": "AAAA,IAAAA,EAAA,CACE,KAAQ,YACR,KAAQ,SACR,QAAW,SACX,WAAc,CACZ,KAAQ,MACR,IAAO,mDACP,UAAa,oBACf,EACA,MAAS,CACP,MACF,EACA,YAAe,YACf,IAAO,CACL,YAAa,cACb,GAAM,cACN,SAAU,mBACZ,EACA,QAAW,CACT,KAAQ,QACV,EACA,QAAW,CACT,MAAS,sDACT,QAAW,iBACX,kBAAmB,4BACnB,kBAAmB,cACnB,cAAe,2EACf,eAAgB,4HAChB,iBAAkB,4HAClB,eAAgB,oEAChB,aAAc,kFACd,WAAY,eACZ,KAAQ,0CACR,aAAc,gDACd,UAAW,6CACX,cAAe,uDACf,SAAU,qMACV,GAAM,gHACN,IAAO,6DACT,EACA,aAAgB,CACd,gCAAiC,UACjC,qBAAsB,SACtB,oBAAqB,SACrB,kBAAmB,SACnB,qBAAsB,SACtB,mBAAoB,SACpB,0BAA2B,cAC3B,MAAS,SACT,SAAY,SACZ,UAAa,UACb,QAAW,UACX,IAAO,SACP,KAAQ,UACR,cAAe,UACf,SAAY,UACZ,MAAS,SACT,KAAQ,SACR,IAAO,SACP,GAAM,QACR,EACA,gBAAmB,CACjB,iCAAkC,cAClC,oBAAqB,WACrB,eAAgB,WAChB,oBAAqB,cACrB,oBAAqB,cACrB,QAAW,UACX,sBAAuB,SACvB,WAAc,QAChB,CACF",
4
+ "sourcesContent": ["{\n \"name\": \"infra-kit\",\n \"type\": \"module\",\n \"version\": \"0.42.0\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/ArthurSaenz/infra-kit.git\",\n \"directory\": \"apps/infra-kit/cli\"\n },\n \"files\": [\n \"dist\"\n ],\n \"description\": \"infra-kit\",\n \"bin\": {\n \"infra-kit\": \"dist/cli.js\",\n \"ik\": \"dist/cli.js\",\n \"ik-mcp\": \"dist/mcp-proxy.js\"\n },\n \"engines\": {\n \"node\": \">=24.x\"\n },\n \"scripts\": {\n \"build\": \"pnpm run clean-artifacts && node ./scripts/build.js\",\n \"prepack\": \"pnpm run build\",\n \"infra-kit-check\": \"pnpm exec infra-kit audit\",\n \"clean-artifacts\": \"rm -rf dist\",\n \"clean-cache\": \"rm -rf node_modules/.cache .eslintcache tsconfig.tsbuildinfo .turbo .swc\",\n \"prettier-fix\": \"pnpm exec prettier **/* --write --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore\",\n \"prettier-check\": \"pnpm exec prettier **/* --check --no-error-on-unmatched-pattern --log-level silent --ignore-path ../../../.prettierignore\",\n \"eslint-check\": \"pnpm exec eslint --cache --report-unused-disable-directives ./src\",\n \"eslint-fix\": \"pnpm exec eslint --cache --quiet --report-unused-disable-directives ./src --fix\",\n \"ts-check\": \"tsc --noEmit\",\n \"test\": \"pnpm exec vitest run --reporter=minimal\",\n \"test-watch\": \"pnpm exec vitest --watch --silent passed-only\",\n \"test-ui\": \"pnpm exec vitest --ui --silent passed-only\",\n \"test-report\": \"pnpm exec vitest run --coverage --silent passed-only\",\n \"qa:pty\": \"INFRA_KIT_REQUIRE_PTY=1 pnpm exec vitest run --reporter=minimal src/tui/__tests__/stdin-pause-pty.test.ts src/entry/__tests__/quit-keys-pty.test.ts src/entry/__tests__/post-run-pause-pty.test.ts\",\n \"qa\": \"pnpm run prettier-check && pnpm run eslint-check && pnpm run ts-check && pnpm run test && echo \u2705 Success\",\n \"fix\": \"pnpm run prettier-fix && pnpm run eslint-fix && pnpm run qa\"\n },\n \"dependencies\": {\n \"@inquirer/checkbox\": \"^5.2.8\",\n \"@inquirer/confirm\": \"^6.3.5\",\n \"@inquirer/input\": \"^5.1.9\",\n \"@inquirer/password\": \"^5.2.5\",\n \"@inquirer/select\": \"^5.2.8\",\n \"@slip-stream-kit/config\": \"workspace:^\",\n \"chalk\": \"^6.0.1\",\n \"chokidar\": \"^6.0.0\",\n \"commander\": \"^15.0.0\",\n \"fastify\": \"^5.12.7\",\n \"ink\": \"^8.0.0\",\n \"pino\": \"^10.4.0\",\n \"pino-pretty\": \"^13.2.0\",\n \"portless\": \"^0.15.12\",\n \"react\": \"19.3.1\",\n \"yaml\": \"^2.9.1\",\n \"zod\": \"^4.6.7\",\n \"zx\": \"^8.8.5\"\n },\n \"devDependencies\": {\n \"@slip-stream-kit/eslint-plugin\": \"workspace:*\",\n \"@types/aws-lambda\": \"catalog:\",\n \"@types/react\": \"catalog:\",\n \"@wl/eslint-config\": \"workspace:*\",\n \"@wl/vitest-config\": \"workspace:*\",\n \"esbuild\": \"^0.28.2\",\n \"ink-testing-library\": \"^4.0.0\",\n \"typescript\": \"^6.0.3\"\n }\n}\n"],
5
+ "mappings": "AAAA,IAAAA,EAAA,CACE,KAAQ,YACR,KAAQ,SACR,QAAW,SACX,WAAc,CACZ,KAAQ,MACR,IAAO,mDACP,UAAa,oBACf,EACA,MAAS,CACP,MACF,EACA,YAAe,YACf,IAAO,CACL,YAAa,cACb,GAAM,cACN,SAAU,mBACZ,EACA,QAAW,CACT,KAAQ,QACV,EACA,QAAW,CACT,MAAS,sDACT,QAAW,iBACX,kBAAmB,4BACnB,kBAAmB,cACnB,cAAe,2EACf,eAAgB,4HAChB,iBAAkB,4HAClB,eAAgB,oEAChB,aAAc,kFACd,WAAY,eACZ,KAAQ,0CACR,aAAc,gDACd,UAAW,6CACX,cAAe,uDACf,SAAU,qMACV,GAAM,gHACN,IAAO,6DACT,EACA,aAAgB,CACd,qBAAsB,SACtB,oBAAqB,SACrB,kBAAmB,SACnB,qBAAsB,SACtB,mBAAoB,SACpB,0BAA2B,cAC3B,MAAS,SACT,SAAY,SACZ,UAAa,UACb,QAAW,UACX,IAAO,SACP,KAAQ,UACR,cAAe,UACf,SAAY,WACZ,MAAS,SACT,KAAQ,SACR,IAAO,SACP,GAAM,QACR,EACA,gBAAmB,CACjB,iCAAkC,cAClC,oBAAqB,WACrB,eAAgB,WAChB,oBAAqB,cACrB,oBAAqB,cACrB,QAAW,UACX,sBAAuB,SACvB,WAAc,QAChB,CACF",
6
6
  "names": ["package_default"]
7
7
  }
@@ -1,4 +1,4 @@
1
- import{P as f,l as $,r as F}from"./chunk-4G7F5ELE.js";import{execFile as te,execFileSync as oe}from"node:child_process";import b from"node:process";var ne=5e3,ae=100,W=2e3,U="/bin/ps",se=1e3,J=["-eo","pid=,ppid=,pgid=,lstart="],V=8<<20,B=e=>e.split(`
1
+ import{P as f,l as $,r as F}from"./chunk-HMXEV7ZN.js";import{execFile as te,execFileSync as oe}from"node:child_process";import b from"node:process";var ne=5e3,ae=100,W=2e3,U="/bin/ps",se=1e3,J=["-eo","pid=,ppid=,pgid=,lstart="],V=8<<20,B=e=>e.split(`
2
2
  `).flatMap(r=>{let[t,o,n,...i]=r.trim().split(/\s+/);if(t==null||o==null||n==null)return[];let l=Number(t),s=Number(o),c=Number(n);return!Number.isInteger(l)||!Number.isInteger(s)||!Number.isInteger(c)?[]:[{pid:l,ppid:s,pgid:c,lstart:i.join(" ")}]}),H=e=>{let r=new Map;for(let t of e)t.pid===t.pgid&&r.set(t.pgid,t.lstart);return r},ie=(e,r,t)=>{let o=H(r);return j(e,r,t).flatMap(n=>{let i=o.get(n);return i==null||i===""?[]:[{pgid:n,leaderStart:i}]})},K=(e,r)=>{let t=H(r);return e.flatMap(({pgid:o,leaderStart:n})=>t.get(o)===n?[o]:[])},D=(e,r)=>K(e,r).flatMap(t=>{try{b.kill(-t,"SIGKILL")}catch{return[]}return[t]}),j=(e,r,t)=>{let o=new Map;for(let s of r){let c=o.get(s.ppid);c?c.push(s):o.set(s.ppid,[s])}let n=new Set([e]),i=new Set([e]),l=[e];for(let s=0;s<l.length;s+=1)for(let c of o.get(l[s]??-1)??[])i.has(c.pid)||(i.add(c.pid),n.add(c.pgid),l.push(c.pid));return[...n].filter(s=>s>1&&s!==t)},A=()=>{try{return B(oe(U,[...J],{encoding:"utf8",maxBuffer:V}))}catch{return[]}},ce=async()=>new Promise(e=>{te(U,[...J],{encoding:"utf8",maxBuffer:V},(r,t)=>{e(r?[]:B(t))})}),le=(e,r,t)=>t.some(o=>o.pid===e&&o.ppid===r),L=(e,r)=>{let t=r.find(o=>o.pid===b.pid)?.pgid;return j(e,r,t)},q=e=>{try{return b.kill(-e,0),!0}catch{return!1}},C=(e,r)=>{for(let t of e)try{b.kill(-t,r)}catch{}},S=new Set,ue=(e,r,t)=>{let o=L(e,r),n=t.flatMap(i=>K(i,r));return[...new Set([...o,...n])]},z=()=>{let e=A(),r=[...S].map(t=>t());C(ue(b.pid,e,r),"SIGKILL")},pe=async e=>new Promise(r=>{setTimeout(r,e)}),v=async(e,r)=>{let t=Date.now()+r,o=e;for(;o.length>0&&Date.now()<t&&(o=o.filter(q),o.length!==0);)await pe(ae);return o};function or(e,r=ne,t,o=A){e.unref();let n=!1,i=!1,l=[],s=null,c=()=>l;S.add(c);let m=()=>{s&&clearInterval(s),s=null},w=async()=>{await v(l.map(a=>a.pgid),W),S.delete(c)},h=a=>{let u=e.pid;if(u==null||i||n||a.length===0)return;let R=a.find(_=>_.pid===b.pid)?.pgid,x=ie(u,a,R);x.length>0&&(l=x)},y=async()=>{e.pid==null||i||n||h(await ce())};h(A()),s=setInterval(()=>{y()},se),s.unref();let T=a=>{n||t?.(a)};return e.on("exit",(a,u)=>{i=!0,m(),n||(D(l,o()),w()),T(`exited unexpectedly (code=${a??"null"}, signal=${u??"null"})`)}),e.on("error",a=>{T(`failed to spawn: ${a.message}`)}),{kill:async()=>{n=!0,m();let a=e.pid;if(a==null){S.delete(c);return}if(e.exitCode!==null||e.signalCode!==null){D(l,o()),await w();return}let u=o();if(u.length>0&&!le(a,b.pid,u))return;let R=L(a,u);C(R,"SIGTERM");let x=await v(R,r);if(x.length===0){S.delete(c);return}let _=L(a,o()),G=[...new Set([...x,..._])].filter(q);C(G,"SIGKILL"),await v(G,W),S.delete(c)}}}import{constants as de}from"node:os";import k from"node:process";var me=["SIGINT","SIGTERM","SIGHUP"],fe=de.signals,ge=2,N=e=>128+(fe[e]??ge),Oe=2e4,be=e=>{k.exit(e)},we=(e,r)=>{k.on(e,r)},he=(e,r)=>{k.off(e,r)},ye=(e,r)=>{let t=setTimeout(e,r);return t.unref(),()=>{clearTimeout(t)}},I=e=>{try{k.stderr.write(e)}catch{}},Se=(e,r)=>{let t=r instanceof Error?`${r.message}
3
3
  ${r.stack??"(no stack)"}`:String(r);I(`
4
4
  \u2717 Teardown failed while handling ${e}: ${t}
@@ -6,5 +6,5 @@ ${r.stack??"(no stack)"}`:String(r);I(`
6
6
  \u26A0 Received ${a} again \u2014 force-quitting.
7
7
  `),w?.(),n(),y(),r(N(a));return}m=a,w=l(()=>{let u=`
8
8
  \u26A0 Teardown deadline exceeded at stage=${s()} after ${i}ms \u2014 force-quitting.
9
- `;I(u),c(u),n(),y(),r(N(a))},i),(async()=>{try{await e(a)}catch(u){Se(a,u)}finally{w?.(),y(),r(N(a))}})()};for(let a of me){let u=()=>T(a);h.set(a,u),t(a,u)}return y};var Pe=new Set(["ExitPromptError","AbortPromptError","PromptCancelledError"]),X=e=>e instanceof Error&&Pe.has(e.name),ur=e=>{if(X(e))return!0;let r=e?.cause;return X(r)};import{$ as xe}from"zx";var d=class extends Error{code;data;constructor(r){super(r.message),this.name="OrcaError",this.code=r.code,this.data=r.data}},P=class extends Error{exitCode;stderrTail;constructor(r,t){super(`orca: stdout is not a JSON envelope (exit ${r??"signal"})`),this.name="OrcaMalformedError",this.exitCode=r,this.stderrTail=t}},g=class extends Error{constructor(){super("orca: command not found \u2014 the CLI is registered from Orca \u2192 Settings \u2192 Experimental \u2192 CLI"),this.name="OrcaAbsentError"}},Te=400,Re=127,ke=e=>typeof e=="object"&&e!==null&&e.code==="ENOENT",Ee=async e=>{try{return await xe({nothrow:!0,quiet:!0})`orca ${e} --json`}catch(r){throw ke(r)?new g:r}},_e=e=>{try{let r=JSON.parse(e);return typeof r=="object"&&r!==null&&typeof r.ok=="boolean"?r:null}catch{return null}},p=async e=>{let r=await Ee(e),t=_e(r.stdout);if(f.debug({argv:e,ok:t?.ok,code:t?.error?.code,exitCode:r.exitCode},"orca"),!t)throw r.exitCode===Re?new g:new P(r.exitCode,r.stderr.slice(-Te));if(!t.ok)throw new d(t.error??{code:"unknown",message:"orca: ok:false without an error payload"});return t.result};var ve=async()=>{try{let e=await p(["status"]);return f.debug({appVersion:e.runtime?.appVersion},"orca: status"),e.app?.running===!0&&e.runtime?.reachable===!0?"ready":"unreachable"}catch(e){return e instanceof g?"absent":(f.debug({error:e},"orca: status probe failed"),"unreachable")}};import{realpath as Ae}from"node:fs/promises";var O=async e=>{try{return await Ae(e)}catch{return e}};var Le=async e=>{let[{repos:r=[]},t]=await Promise.all([p(["repo","list"]),O(e)]);for(let o of r)if(await O(o.path)===t)return{registered:!0,visibility:o.externalWorktreeVisibility};return{registered:!1}},Ce=async e=>{let{repo:r}=await p(["repo","add","--path",e]);return{visibility:r?.externalWorktreeVisibility}};var Ne="500",Ie=async(e,r)=>{let[{worktrees:t=[]},o]=await Promise.all([p(["worktree","list","--repo",`path:${e}`,"--limit",Ne]),O(r)]);for(let n of t)if(await O(n.path)===o)return!0;return!1};import Me from"node:process";var Y="::",Ge=e=>{let r=e.ORCA_WORKTREE_ID;if(!r)return null;let t=r.indexOf(Y);if(t<0)return null;let o=r.slice(t+Y.length);return o.length>0?o:null},$e=async(e,r=Me.env)=>{let t=Ge(r);if(t===null)return null;let o=await O(t);for(let n of e)if(await O(n)===o)return n;return null};var Q="200",M=async e=>{try{let r=await p(["terminal","list","--worktree",`path:${e}`,"--limit",Q]),t=r.truncated===!0;return t&&f.debug({cwd:e,limit:Q},"orca: terminal list truncated"),{terminals:r.terminals??[],truncated:t}}catch(r){if(r instanceof d&&r.code==="selector_not_found")return{terminals:[],truncated:!1};throw r}};var Fe=async e=>{try{return await p(["terminal","close","--worktree",`path:${e}`,"--all"]),"retired"}catch(r){if(r instanceof d&&r.code==="selector_not_found")return"not_found";if(r instanceof d&&r.code==="terminal_close_incomplete")return f.debug({cwd:e,error:r},"orca: surfaces not retired"),"retired";throw r}},We=async e=>{let{terminals:r}=await M(e);for(let o of r)await p(["terminal","close","--terminal",o.handle]);let t=await Fe(e);return r.length===0&&t==="not_found"?{closed:!1,skipped:"not_found"}:{closed:!0,count:r.length}},De=(e,r)=>r instanceof g?{closed:!1,skipped:"absent"}:r instanceof d?{closed:!1,error:r}:r instanceof P?{closed:!1,error:new d({code:"orca_malformed_output",message:r.message,data:{exitCode:r.exitCode,stderrTail:r.stderrTail}})}:(f.debug({cwd:e,error:r},"orca: close failed outside the Orca contract"),{closed:!1,error:new d({code:"orca_close_failed",message:r instanceof Error?r.message:String(r)})}),Ue=async(e,r)=>{if(r!=="ready")return{closed:!1,skipped:r};try{return await We(e)}catch(t){return De(e,t)}};import{setTimeout as Je}from"node:timers/promises";var Ve=3,Be=300,ee=(e={})=>({attempts:e.attempts??Ve,delayMs:e.delayMs??Be,exhausted:!1}),He=async e=>{try{return{created:await p(e)}}catch(r){if(r instanceof d&&r.code==="selector_not_found")return{notSelectable:r};throw r}},Ke=async(e,r,t)=>{let o=t.exhausted?1:t.attempts,n=Array.from({length:o},(l,s)=>s+1),i;for(let l of n){let s=await He(e);if("created"in s)return s.created.terminal.handle;i=s.notSelectable,l<o&&await Je(t.delayMs)}throw t.exhausted=!0,new d({code:"orca_worktree_not_selectable",message:`orca: worktree ${r} is not selectable after ${o} attempt(s): ${i?.message??""}`,data:{cwd:r,attempts:o,cause:i?.data}})},Z=async(e,r)=>(await p(["terminal","split","--terminal",e,"--direction",r])).split.handle,je=async e=>{let{cwd:r,title:t,focus:o,layout:n,panes:i,poll:l=ee()}=e,s=["terminal","create","--worktree",`path:${r}`,"--title",t,...o?["--focus"]:[]],c=await Ke(s,r,l),m=[c];return n==="full"&&(m.push(await Z(c,"horizontal")),i==="three-pane"&&m.push(await Z(c,"vertical"))),{handles:m,layout:n}};var qe=e=>{let{branch:r}=e,t=$(r);return t?F(t):r};var Yr=e=>typeof e=="object",E=async e=>(await e.body?.cancel(),{kind:"foreign",status:e.status,contentType:e.headers.get("content-type")}),Qr=(e,r)=>{let t=r.contentType?.split(";")[0]?.trim(),o=t==null||t===""?`${r.status}`:`${r.status} ${t}`;return`port ${e} answered ${o}, not vite's ping \u2014 liveness cannot be verified`};var re={accept:"text/x-vite-ping"},ze=e=>e.kind==="api"?`http://127.0.0.1:${e.port}/__health`:`http://127.0.0.1:${e.port}/`,Xe=(e,r)=>{try{return new URL(e,r)}catch{return null}},Ye=async(e,r)=>{let t=await fetch(e,{signal:r});return t.ok?(await t.body?.cancel(),"ok"):E(t)},Qe=async(e,r)=>{let t=await fetch(e,{headers:re,redirect:"manual",signal:r});if(t.status===204)return"ok";if(t.status<300||t.status>=400)return E(t);let o=t.headers.get("location"),n=o==null?null:Xe(o,e);if(n==null||n.origin!==new URL(e).origin)return E(t);await t.body?.cancel();let i=await fetch(n,{headers:re,redirect:"manual",signal:r});return i.status!==204?E(i):(await i.body?.cancel(),"ok")},Zr=async e=>{let r=ze(e),t=AbortSignal.timeout(1500);try{return e.kind==="api"?await Ye(r,t):await Qe(r,t)}catch{return"refused"}};import{readRelease as Ze}from"@slip-stream-kit/config/internal";var er=e=>Ze(e);export{z as a,or as b,N as c,cr as d,d as e,p as f,ve as g,$e as h,M as i,Ue as j,Le as k,Ce as l,Ie as m,ee as n,je as o,qe as p,Yr as q,Qr as r,Zr as s,er as t,ur as u};
10
- //# sourceMappingURL=chunk-2SDWSDM2.js.map
9
+ `;I(u),c(u),n(),y(),r(N(a))},i),(async()=>{try{await e(a)}catch(u){Se(a,u)}finally{w?.(),y(),r(N(a))}})()};for(let a of me){let u=()=>T(a);h.set(a,u),t(a,u)}return y};var Pe=new Set(["ExitPromptError","AbortPromptError","PromptCancelledError"]),X=e=>e instanceof Error&&Pe.has(e.name),ur=e=>{if(X(e))return!0;let r=e?.cause;return X(r)};import{$ as xe}from"zx";var d=class extends Error{code;data;constructor(r){super(r.message),this.name="OrcaError",this.code=r.code,this.data=r.data}},P=class extends Error{exitCode;stderrTail;constructor(r,t){super(`orca: stdout is not a JSON envelope (exit ${r??"signal"})`),this.name="OrcaMalformedError",this.exitCode=r,this.stderrTail=t}},g=class extends Error{constructor(){super("orca: command not found \u2014 the CLI is registered from Orca \u2192 Settings \u2192 Experimental \u2192 CLI"),this.name="OrcaAbsentError"}},Te=400,Re=127,ke=e=>typeof e=="object"&&e!==null&&e.code==="ENOENT",Ee=async e=>{try{return await xe({nothrow:!0,quiet:!0})`orca ${e} --json`}catch(r){throw ke(r)?new g:r}},_e=e=>{try{let r=JSON.parse(e);return typeof r=="object"&&r!==null&&typeof r.ok=="boolean"?r:null}catch{return null}},p=async e=>{let r=await Ee(e),t=_e(r.stdout);if(f.debug({argv:e,ok:t?.ok,code:t?.error?.code,exitCode:r.exitCode},"orca"),!t)throw r.exitCode===Re?new g:new P(r.exitCode,r.stderr.slice(-Te));if(!t.ok)throw new d(t.error??{code:"unknown",message:"orca: ok:false without an error payload"});return t.result};var ve=async()=>{try{let e=await p(["status"]);return f.debug({appVersion:e.runtime?.appVersion},"orca: status"),e.app?.running===!0&&e.runtime?.reachable===!0?"ready":"unreachable"}catch(e){return e instanceof g?"absent":(f.debug({error:e},"orca: status probe failed"),"unreachable")}};import{realpath as Ae}from"node:fs/promises";var O=async e=>{try{return await Ae(e)}catch{return e}};var Le=async e=>{let[{repos:r=[]},t]=await Promise.all([p(["repo","list"]),O(e)]);for(let o of r)if(await O(o.path)===t)return{registered:!0,visibility:o.externalWorktreeVisibility};return{registered:!1}},Ce=async e=>{let{repo:r}=await p(["repo","add","--path",e]);return{visibility:r?.externalWorktreeVisibility}};var Ne="500",Ie=async(e,r)=>{let[{worktrees:t=[]},o]=await Promise.all([p(["worktree","list","--repo",`path:${e}`,"--limit",Ne]),O(r)]);for(let n of t)if(await O(n.path)===o)return!0;return!1};import Me from"node:process";var Y="::",Ge=e=>{let r=e.ORCA_WORKTREE_ID;if(!r)return null;let t=r.indexOf(Y);if(t<0)return null;let o=r.slice(t+Y.length);return o.length>0?o:null},$e=async(e,r=Me.env)=>{let t=Ge(r);if(t===null)return null;let o=await O(t);for(let n of e)if(await O(n)===o)return n;return null};var Q="200",M=async e=>{try{let r=await p(["terminal","list","--worktree",`path:${e}`,"--limit",Q]),t=r.truncated===!0;return t&&f.debug({cwd:e,limit:Q},"orca: terminal list truncated"),{terminals:r.terminals??[],truncated:t}}catch(r){if(r instanceof d&&r.code==="selector_not_found")return{terminals:[],truncated:!1};throw r}};var Fe=async e=>{try{return await p(["terminal","close","--worktree",`path:${e}`,"--all"]),"retired"}catch(r){if(r instanceof d&&r.code==="selector_not_found")return"not_found";if(r instanceof d&&r.code==="terminal_close_incomplete")return f.debug({cwd:e,error:r},"orca: surfaces not retired"),"retired";throw r}},We=async e=>{let{terminals:r}=await M(e);for(let o of r)await p(["terminal","close","--terminal",o.handle]);let t=await Fe(e);return r.length===0&&t==="not_found"?{closed:!1,skipped:"not_found"}:{closed:!0,count:r.length}},De=(e,r)=>r instanceof g?{closed:!1,skipped:"absent"}:r instanceof d?{closed:!1,error:r}:r instanceof P?{closed:!1,error:new d({code:"orca_malformed_output",message:r.message,data:{exitCode:r.exitCode,stderrTail:r.stderrTail}})}:(f.debug({cwd:e,error:r},"orca: close failed outside the Orca contract"),{closed:!1,error:new d({code:"orca_close_failed",message:r instanceof Error?r.message:String(r)})}),Ue=async(e,r)=>{if(r!=="ready")return{closed:!1,skipped:r};try{return await We(e)}catch(t){return De(e,t)}};import{setTimeout as Je}from"node:timers/promises";var Ve=3,Be=300,ee=(e={})=>({attempts:e.attempts??Ve,delayMs:e.delayMs??Be,exhausted:!1}),He=async e=>{try{return{created:await p(e)}}catch(r){if(r instanceof d&&r.code==="selector_not_found")return{notSelectable:r};throw r}},Ke=async(e,r,t)=>{let o=t.exhausted?1:t.attempts,n=Array.from({length:o},(l,s)=>s+1),i;for(let l of n){let s=await He(e);if("created"in s)return s.created.terminal.handle;i=s.notSelectable,l<o&&await Je(t.delayMs)}throw t.exhausted=!0,new d({code:"orca_worktree_not_selectable",message:`orca: worktree ${r} is not selectable after ${o} attempt(s): ${i?.message??""}`,data:{cwd:r,attempts:o,cause:i?.data}})},Z=async(e,r)=>(await p(["terminal","split","--terminal",e,"--direction",r])).split.handle,je=async e=>{let{cwd:r,title:t,focus:o,layout:n,panes:i,poll:l=ee()}=e,s=["terminal","create","--worktree",`path:${r}`,"--title",t,...o?["--focus"]:[]],c=await Ke(s,r,l),m=[c];return n==="full"&&(m.push(await Z(c,"horizontal")),i==="three-pane"&&m.push(await Z(c,"vertical"))),{handles:m,layout:n}};var qe=e=>{let{branch:r}=e,t=$(r);return t?F(t):r};var Yr=e=>typeof e=="object",E=async e=>(await e.body?.cancel(),{kind:"foreign",status:e.status,contentType:e.headers.get("content-type")}),Qr=(e,r)=>{let t=r.contentType?.split(";")[0]?.trim(),o=t==null||t===""?`${r.status}`:`${r.status} ${t}`;return`port ${e} answered ${o}, not vite's ping \u2014 liveness cannot be verified`};var re={accept:"text/x-vite-ping"},ze=e=>e.kind==="api"?`http://127.0.0.1:${e.port}/__health`:`http://127.0.0.1:${e.port}/`,Xe=(e,r)=>{try{return new URL(e,r)}catch{return null}},Ye=async(e,r)=>{let t=await fetch(e,{signal:r});return t.ok?(await t.body?.cancel(),"ok"):E(t)},Qe=async(e,r)=>{let t=await fetch(e,{headers:re,redirect:"manual",signal:r});if(t.status===204)return"ok";if(t.status<300||t.status>=400)return E(t);let o=t.headers.get("location"),n=o==null?null:Xe(o,e);if(n==null||n.origin!==new URL(e).origin)return E(t);await t.body?.cancel();let i=await fetch(n,{headers:re,redirect:"manual",signal:r});return i.status!==204?E(i):(await i.body?.cancel(),"ok")},Zr=async e=>{let r=ze(e),t=AbortSignal.timeout(1500);try{return e.kind==="api"?await Ye(r,t):await Qe(r,t)}catch{return"refused"}};import{readRelease as Ze}from"@slip-stream-kit/config/internal";var er=e=>Ze(e);export{d as a,p as b,ve as c,$e as d,M as e,Ue as f,Le as g,Ce as h,Ie as i,ee as j,je as k,qe as l,Yr as m,Qr as n,Zr as o,er as p,z as q,or as r,N as s,cr as t,ur as u};
10
+ //# sourceMappingURL=chunk-ZY6BBGHH.js.map