@flisk-sh/flisk 0.0.0-stage → 1.3.190

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 (440) hide show
  1. package/CHANGELOG.md +492 -0
  2. package/LICENSE +21 -0
  3. package/README.md +479 -2
  4. package/Tiltfile +151 -0
  5. package/cli/bin/flisk.js +42 -0
  6. package/cli/dist/agent-runtimes/custom.js +335 -0
  7. package/cli/dist/agent-runtimes/registry.js +34 -0
  8. package/cli/dist/backend-frameworks/elysia.js +38 -0
  9. package/cli/dist/backend-frameworks/express.js +49 -0
  10. package/cli/dist/backend-frameworks/fastify.js +43 -0
  11. package/cli/dist/backend-frameworks/h3.js +37 -0
  12. package/cli/dist/backend-frameworks/koa.js +47 -0
  13. package/cli/dist/backend-frameworks/mcp.js +86 -0
  14. package/cli/dist/backend-frameworks/nestjs.js +55 -0
  15. package/cli/dist/backend-frameworks/registry.js +134 -0
  16. package/cli/dist/backend-frameworks/types.js +1 -0
  17. package/cli/dist/backend-languages/bun.js +76 -0
  18. package/cli/dist/backend-languages/go.js +125 -0
  19. package/cli/dist/backend-languages/node.js +122 -0
  20. package/cli/dist/backend-languages/python.js +94 -0
  21. package/cli/dist/backend-languages/registry.js +37 -0
  22. package/cli/dist/backend-languages/rust.js +82 -0
  23. package/cli/dist/backend-languages/types.js +1 -0
  24. package/cli/dist/cli.js +29 -0
  25. package/cli/dist/commands/__tests__/project-e2e-helpers.js +49 -0
  26. package/cli/dist/commands/__tests__/ui-loading-screen.test.js +16 -0
  27. package/cli/dist/commands/agent.js +182 -0
  28. package/cli/dist/commands/completion-candidates.js +116 -0
  29. package/cli/dist/commands/completion.js +843 -0
  30. package/cli/dist/commands/config.js +362 -0
  31. package/cli/dist/commands/doctor.js +1504 -0
  32. package/cli/dist/commands/down.js +114 -0
  33. package/cli/dist/commands/eject.js +108 -0
  34. package/cli/dist/commands/help.js +152 -0
  35. package/cli/dist/commands/import.js +164 -0
  36. package/cli/dist/commands/logs.js +119 -0
  37. package/cli/dist/commands/maintainers.js +102 -0
  38. package/cli/dist/commands/mcp.js +28 -0
  39. package/cli/dist/commands/networks.js +306 -0
  40. package/cli/dist/commands/project.js +447 -0
  41. package/cli/dist/commands/projects.js +103 -0
  42. package/cli/dist/commands/registry.js +53 -0
  43. package/cli/dist/commands/resource.js +992 -0
  44. package/cli/dist/commands/resources.js +127 -0
  45. package/cli/dist/commands/restart.js +89 -0
  46. package/cli/dist/commands/runtime.js +75 -0
  47. package/cli/dist/commands/stack.js +171 -0
  48. package/cli/dist/commands/stacks.js +71 -0
  49. package/cli/dist/commands/status.js +211 -0
  50. package/cli/dist/commands/ui.js +725 -0
  51. package/cli/dist/commands/up.js +609 -0
  52. package/cli/dist/commands/upgrade.js +840 -0
  53. package/cli/dist/commands/version.js +10 -0
  54. package/cli/dist/components/Accessible.js +11 -0
  55. package/cli/dist/components/BaseTooltip.js +30 -0
  56. package/cli/dist/components/DetailPanel.js +33 -0
  57. package/cli/dist/components/FileTree.js +51 -0
  58. package/cli/dist/components/ResourceSelectInput.js +42 -0
  59. package/cli/dist/components/ResourceTable.js +35 -0
  60. package/cli/dist/components/ServiceIssues.js +13 -0
  61. package/cli/dist/components/TUIHeader.js +27 -0
  62. package/cli/dist/components/TabBar.js +27 -0
  63. package/cli/dist/components/Tooltip.js +13 -0
  64. package/cli/dist/components/index.js +11 -0
  65. package/cli/dist/components/ui-theme.js +120 -0
  66. package/cli/dist/config/platform-standards.js +182 -0
  67. package/cli/dist/frontend-frameworks/lit.js +64 -0
  68. package/cli/dist/frontend-frameworks/preact.js +62 -0
  69. package/cli/dist/frontend-frameworks/qwik.js +61 -0
  70. package/cli/dist/frontend-frameworks/react.js +69 -0
  71. package/cli/dist/frontend-frameworks/registry.js +83 -0
  72. package/cli/dist/frontend-frameworks/solid.js +62 -0
  73. package/cli/dist/frontend-frameworks/svelte.js +67 -0
  74. package/cli/dist/frontend-frameworks/tanstack-router.js +101 -0
  75. package/cli/dist/frontend-frameworks/types.js +1 -0
  76. package/cli/dist/frontend-frameworks/vanilla.js +59 -0
  77. package/cli/dist/frontend-frameworks/vue.js +72 -0
  78. package/cli/dist/generator/__tests__/golden-helpers.js +43 -0
  79. package/cli/dist/generator/extension-fetch.js +291 -0
  80. package/cli/dist/generator/resource-templates.js +133 -0
  81. package/cli/dist/generator/template-engine.js +801 -0
  82. package/cli/dist/index.js +10 -0
  83. package/cli/dist/mcp/server.js +101 -0
  84. package/cli/dist/mcp/tools.js +351 -0
  85. package/cli/dist/program.js +37 -0
  86. package/cli/dist/types/index.js +38 -0
  87. package/cli/dist/utils/agent-host.js +36 -0
  88. package/cli/dist/utils/atomic-write.js +36 -0
  89. package/cli/dist/utils/bun-floor.js +9 -0
  90. package/cli/dist/utils/bun-requirement.js +10 -0
  91. package/cli/dist/utils/cache.js +63 -0
  92. package/cli/dist/utils/cold-preflight.js +257 -0
  93. package/cli/dist/utils/command-helpers.js +57 -0
  94. package/cli/dist/utils/constants.js +160 -0
  95. package/cli/dist/utils/discovery-context.js +71 -0
  96. package/cli/dist/utils/discovery-paths.js +93 -0
  97. package/cli/dist/utils/docker.js +34 -0
  98. package/cli/dist/utils/doctor-crashloop.js +161 -0
  99. package/cli/dist/utils/doctor-fix.js +391 -0
  100. package/cli/dist/utils/doctor-host.js +66 -0
  101. package/cli/dist/utils/doctor-report.js +78 -0
  102. package/cli/dist/utils/doctor-runtime.js +880 -0
  103. package/cli/dist/utils/doctor-starlark.js +132 -0
  104. package/cli/dist/utils/doctor-wiring.js +698 -0
  105. package/cli/dist/utils/down-cleanup.js +125 -0
  106. package/cli/dist/utils/env-validator.js +266 -0
  107. package/cli/dist/utils/errors.js +175 -0
  108. package/cli/dist/utils/exec-async.js +31 -0
  109. package/cli/dist/utils/file-helpers.js +104 -0
  110. package/cli/dist/utils/formatting.js +165 -0
  111. package/cli/dist/utils/generated-paths.js +51 -0
  112. package/cli/dist/utils/help-command.js +11 -0
  113. package/cli/dist/utils/host-port-config.js +140 -0
  114. package/cli/dist/utils/host-port-plan.js +100 -0
  115. package/cli/dist/utils/json-output.js +29 -0
  116. package/cli/dist/utils/machine-output.js +33 -0
  117. package/cli/dist/utils/paths.js +43 -0
  118. package/cli/dist/utils/platform.js +58 -0
  119. package/cli/dist/utils/port-assignment.js +75 -0
  120. package/cli/dist/utils/port-conflict-fix.js +25 -0
  121. package/cli/dist/utils/port-fallback-notice.js +17 -0
  122. package/cli/dist/utils/port-listener-probe.js +20 -0
  123. package/cli/dist/utils/project-config-defaults.js +17 -0
  124. package/cli/dist/utils/project-features.js +91 -0
  125. package/cli/dist/utils/project-templates.js +32 -0
  126. package/cli/dist/utils/prompt.js +97 -0
  127. package/cli/dist/utils/resource-features.js +184 -0
  128. package/cli/dist/utils/resource-kind.js +9 -0
  129. package/cli/dist/utils/schema-version-gate.js +45 -0
  130. package/cli/dist/utils/search-status.js +12 -0
  131. package/cli/dist/utils/secret-redaction.js +73 -0
  132. package/cli/dist/utils/service-config-checks.js +189 -0
  133. package/cli/dist/utils/service-manifest.js +254 -0
  134. package/cli/dist/utils/service-runtime-state.js +66 -0
  135. package/cli/dist/utils/service-urls.js +112 -0
  136. package/cli/dist/utils/services.js +360 -0
  137. package/cli/dist/utils/shared-infra.js +45 -0
  138. package/cli/dist/utils/shared-platform-postgres.js +232 -0
  139. package/cli/dist/utils/single-flight.js +21 -0
  140. package/cli/dist/utils/smoke.js +401 -0
  141. package/cli/dist/utils/spinner.js +40 -0
  142. package/cli/dist/utils/stack-features.js +15 -0
  143. package/cli/dist/utils/stack-status.js +14 -0
  144. package/cli/dist/utils/startup-report.js +78 -0
  145. package/cli/dist/utils/status-message.js +21 -0
  146. package/cli/dist/utils/status-ports.js +33 -0
  147. package/cli/dist/utils/suggestions.js +63 -0
  148. package/cli/dist/utils/tar.js +46 -0
  149. package/cli/dist/utils/tdk-version.js +51 -0
  150. package/cli/dist/utils/terminal-layout.js +19 -0
  151. package/cli/dist/utils/tilt-events.js +194 -0
  152. package/cli/dist/utils/tilt-logs.js +61 -0
  153. package/cli/dist/utils/tilt-port-owner.js +63 -0
  154. package/cli/dist/utils/tilt-process.js +54 -0
  155. package/cli/dist/utils/tilt-resource-state.js +32 -0
  156. package/cli/dist/utils/tilt-startup.js +49 -0
  157. package/cli/dist/utils/tilt-unreachable-message.js +9 -0
  158. package/cli/dist/utils/tilt.js +104 -0
  159. package/cli/dist/utils/ui-keymap.js +129 -0
  160. package/cli/dist/utils/ui-service-state.js +34 -0
  161. package/cli/dist/utils/up-only.js +28 -0
  162. package/cli/dist/utils/up-readiness.js +118 -0
  163. package/cli/dist/utils/url-actions.js +103 -0
  164. package/cli/dist/utils/validation.js +62 -0
  165. package/cli/dist/utils/which.js +56 -0
  166. package/cli/dist/utils/windows-doctor.js +176 -0
  167. package/cli/dist-bundle/chunk-6EA4DGCY.js +2 -0
  168. package/cli/dist-bundle/chunk-BZ4H7MM4.js +3 -0
  169. package/cli/dist-bundle/chunk-CLCUIDBH.js +510 -0
  170. package/cli/dist-bundle/cli.js +2017 -0
  171. package/cli/dist-bundle/cold-preflight-SY26O2IG.js +2 -0
  172. package/cli/dist-bundle/devtools-ZUHXW33W.js +5 -0
  173. package/cli/dist-bundle/extension-fetch-J4FFH7TJ.js +2 -0
  174. package/cli/package.json +83 -0
  175. package/cli/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  176. package/cli/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  177. package/cli/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  178. package/cli/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  179. package/cli/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  180. package/cli/templates/.tiltignore.hbs +72 -0
  181. package/cli/templates/TILT_RESOURCE_DEFAULTS.star.hbs +220 -0
  182. package/cli/templates/TILT_TECH_STACK.star.hbs +149 -0
  183. package/cli/templates/Tiltfile.hbs +381 -0
  184. package/cli/templates/spec.master.hbs +192 -0
  185. package/discovery/AGENTS.md +362 -0
  186. package/discovery/TILT_DISCOVERY.star +429 -0
  187. package/discovery/Tiltfile +58 -0
  188. package/discovery/config.star +265 -0
  189. package/discovery/constants.star +167 -0
  190. package/discovery/deterministic.star +213 -0
  191. package/discovery/discovery_daemon.star +193 -0
  192. package/discovery/discovery_orchestrator.star +492 -0
  193. package/discovery/filtering.star +7 -0
  194. package/discovery/identity-management-backend/service.yaml +26 -0
  195. package/discovery/identity-management-frontend/service.yaml +29 -0
  196. package/discovery/identity-sdk/service.yaml +9 -0
  197. package/discovery/incremental_discovery.star +215 -0
  198. package/discovery/indexing.star +9 -0
  199. package/discovery/json_manifest_scanner.star +57 -0
  200. package/discovery/libraries.star +48 -0
  201. package/discovery/loading.star +25 -0
  202. package/discovery/manifest/constants.star +106 -0
  203. package/discovery/manifest/loading.star +418 -0
  204. package/discovery/manifest/normalize.star +289 -0
  205. package/discovery/manifest/validation.star +110 -0
  206. package/discovery/normalization.star +13 -0
  207. package/discovery/registry.star +562 -0
  208. package/discovery/resource_snapshot.py +384 -0
  209. package/discovery/resource_snapshot.star +145 -0
  210. package/discovery/schemas.star +3 -0
  211. package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
  212. package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
  213. package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
  214. package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
  215. package/discovery/test_resource_snapshot.py +253 -0
  216. package/discovery/validation.star +80 -0
  217. package/discovery/versioning.star +3 -0
  218. package/engine/AGENTS.md +706 -0
  219. package/engine/README.md +31 -0
  220. package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
  221. package/engine/Tiltfile +86 -0
  222. package/engine/assets/docker/golden-layers.Dockerfile +204 -0
  223. package/engine/assets/docker/wake-gateway/Dockerfile +28 -0
  224. package/engine/assets/docker/wake-gateway/decide.test.ts +177 -0
  225. package/engine/assets/docker/wake-gateway/decide.ts +135 -0
  226. package/engine/assets/docker/wake-gateway/server.ts +363 -0
  227. package/engine/assets/scripts/cleanup-completed-migrator-images.sh +39 -0
  228. package/engine/assets/scripts/cleanup-tilt-images.sh +122 -0
  229. package/engine/assets/scripts/mac-m1-resource-monitor.sh +123 -0
  230. package/engine/config.star +5 -0
  231. package/engine/entrypoint.star +101 -0
  232. package/engine/lifecycle/orchestrator.star +263 -0
  233. package/engine/paths.star +719 -0
  234. package/engine/schemas/project-schema.json +147 -0
  235. package/engine/schemas/service-schema.json +537 -0
  236. package/engine/scripts/README.md +89 -0
  237. package/engine/scripts/build-and-publish-lib.sh +207 -0
  238. package/engine/scripts/check-lib-publish.sh +87 -0
  239. package/engine/scripts/debug-container.sh +265 -0
  240. package/engine/scripts/generate-manifest.sh +200 -0
  241. package/engine/spec.master +702 -0
  242. package/engine/spec.master.example +341 -0
  243. package/engine/topologies/README.md +33 -0
  244. package/engine/topologies/platform/docker/AGENTS.md +59 -0
  245. package/engine/topologies/platform/docker/auth/auth.star +207 -0
  246. package/engine/topologies/platform/docker/build/frontend_build_plan.star +65 -0
  247. package/engine/topologies/platform/docker/build/golden_image.star +37 -0
  248. package/engine/topologies/platform/docker/build/golden_image_build.star +144 -0
  249. package/engine/topologies/platform/docker/build/golden_image_constants.star +100 -0
  250. package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +263 -0
  251. package/engine/topologies/platform/docker/compose/compose.star +637 -0
  252. package/engine/topologies/platform/docker/compose/compose_helpers.star +54 -0
  253. package/engine/topologies/platform/docker/compose/traefik_standalone.star +171 -0
  254. package/engine/topologies/platform/docker/config/bunignore.star +144 -0
  255. package/engine/topologies/platform/docker/config/dockerignore.star +152 -0
  256. package/engine/topologies/platform/docker/config/healthcheck.star +58 -0
  257. package/engine/topologies/platform/docker/constants.star +211 -0
  258. package/engine/topologies/platform/docker/dockerfile/dockerfile.star +56 -0
  259. package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +264 -0
  260. package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +76 -0
  261. package/engine/topologies/platform/docker/index.star +40 -0
  262. package/engine/topologies/platform/docker/layers/bun_helpers.star +25 -0
  263. package/engine/topologies/platform/docker/layers/infisical/index.star +42 -0
  264. package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +264 -0
  265. package/engine/topologies/platform/docker/layers/l1_base_layers.star +89 -0
  266. package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +147 -0
  267. package/engine/topologies/platform/docker/layers/l3_builder_layers.star +229 -0
  268. package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +282 -0
  269. package/engine/topologies/platform/docker/layers/prisma/constants.star +138 -0
  270. package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +98 -0
  271. package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +131 -0
  272. package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +100 -0
  273. package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +128 -0
  274. package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +205 -0
  275. package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +121 -0
  276. package/engine/topologies/platform/docker/networking/api_path_constants.star +206 -0
  277. package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +31 -0
  278. package/engine/topologies/platform/docker/networking/traefik.star +266 -0
  279. package/engine/topologies/platform/docker/networking/traefik_constants.star +148 -0
  280. package/engine/topologies/platform/docker/networking/traefik_helpers.star +162 -0
  281. package/engine/topologies/platform/docker/networking/traefik_static_routes.star +165 -0
  282. package/engine/topologies/platform/docker/secrets/env_secrets.star +74 -0
  283. package/engine/topologies/platform/docker/secrets/infisical.star +109 -0
  284. package/engine/topologies/platform/net/AGENTS.md +64 -0
  285. package/engine/topologies/platform/net/proxy.star +6 -0
  286. package/engine/topologies/platform/registries/local.star +6 -0
  287. package/engine/topologies/platform/registries/verdaccio_loader.star +20 -0
  288. package/engine/topologies/platform/security/AGENTS.md +49 -0
  289. package/engine/topologies/platform/security/secrets.star +241 -0
  290. package/engine/topologies/platform/state/AGENTS.md +64 -0
  291. package/engine/topologies/platform/state/relational.star +6 -0
  292. package/engine/topologies/tilt/common/AGENTS.md +59 -0
  293. package/engine/topologies/tilt/common/utils.star +409 -0
  294. package/engine/topologies/tilt/common/utils_debug.star +71 -0
  295. package/engine/topologies/tilt/common/utils_deterministic.star +170 -0
  296. package/engine/topologies/tilt/common/utils_docker_networks.star +54 -0
  297. package/engine/topologies/tilt/common/utils_env.star +92 -0
  298. package/engine/topologies/tilt/common/utils_output.star +99 -0
  299. package/engine/topologies/tilt/config/AGENTS.md +68 -0
  300. package/engine/topologies/tilt/config/defaults.star +5 -0
  301. package/engine/topologies/tilt/config/feature_flags.star +12 -0
  302. package/engine/topologies/tilt/config/global.star +57 -0
  303. package/engine/topologies/tilt/config/profiles.star +398 -0
  304. package/engine/topologies/tilt/generators/agents_md.star +64 -0
  305. package/engine/topologies/tilt/generators/api_gateway.star +147 -0
  306. package/engine/topologies/tilt/generators/index.star +126 -0
  307. package/engine/topologies/tilt/generators/infisical/README.md +424 -0
  308. package/engine/topologies/tilt/generators/infisical/examples.star +314 -0
  309. package/engine/topologies/tilt/generators/infisical/index.star +59 -0
  310. package/engine/topologies/tilt/generators/infisical/machine_identity.star +422 -0
  311. package/engine/topologies/tilt/generators/infisical/organization.star +536 -0
  312. package/engine/topologies/tilt/generators/infisical/path_manager.star +478 -0
  313. package/engine/topologies/tilt/generators/infisical/secrets_generator.star +422 -0
  314. package/engine/topologies/tilt/generators/nginx_conf.star +145 -0
  315. package/engine/topologies/tilt/generators/npmrc.star +132 -0
  316. package/engine/topologies/tilt/generators/tsconfig.star +25 -0
  317. package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +73 -0
  318. package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +137 -0
  319. package/engine/topologies/tilt/generators/typescript/common.star +9 -0
  320. package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +78 -0
  321. package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +140 -0
  322. package/engine/topologies/tilt/generators/typescript/include.star +25 -0
  323. package/engine/topologies/tilt/generators/typescript/playwright_config.star +42 -0
  324. package/engine/topologies/tilt/generators/typescript/prisma_config.star +51 -0
  325. package/engine/topologies/tilt/generators/validators.star +868 -0
  326. package/engine/topologies/tilt/generators/vite/backend.star +80 -0
  327. package/engine/topologies/tilt/generators/vite/frameworks/lit.star +92 -0
  328. package/engine/topologies/tilt/generators/vite/frameworks/preact.star +94 -0
  329. package/engine/topologies/tilt/generators/vite/frameworks/qwik.star +94 -0
  330. package/engine/topologies/tilt/generators/vite/frameworks/react.star +128 -0
  331. package/engine/topologies/tilt/generators/vite/frameworks/solid.star +94 -0
  332. package/engine/topologies/tilt/generators/vite/frameworks/svelte.star +94 -0
  333. package/engine/topologies/tilt/generators/vite/frameworks/vanilla.star +92 -0
  334. package/engine/topologies/tilt/generators/vite/frameworks/vue.star +94 -0
  335. package/engine/topologies/tilt/generators/vite/frontend.star +153 -0
  336. package/engine/topologies/tilt/generators/vite/generators.star +45 -0
  337. package/engine/topologies/tilt/generators/vite/helpers.star +256 -0
  338. package/engine/topologies/tilt/generators/vite/library.star +67 -0
  339. package/engine/topologies/tilt/generators/vite/sdk.star +75 -0
  340. package/engine/topologies/tilt/generators/vite/templates.star +460 -0
  341. package/engine/topologies/tilt/generators/vite_config.star +24 -0
  342. package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
  343. package/engine/topologies/tilt/manifest/README.md +679 -0
  344. package/engine/topologies/tilt/manifest/__init__.star +220 -0
  345. package/engine/topologies/tilt/manifest/constants.star +262 -0
  346. package/engine/topologies/tilt/manifest/errors.star +268 -0
  347. package/engine/topologies/tilt/manifest/integration.star +348 -0
  348. package/engine/topologies/tilt/manifest/json_to_yaml.py +61 -0
  349. package/engine/topologies/tilt/manifest/loader.star +239 -0
  350. package/engine/topologies/tilt/manifest/mapper.star +229 -0
  351. package/engine/topologies/tilt/manifest/parser.star +490 -0
  352. package/engine/topologies/tilt/manifest/schema.star +502 -0
  353. package/engine/topologies/tilt/manifest/tests/test_integration.star +278 -0
  354. package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +475 -0
  355. package/engine/topologies/tilt/manifest/tests/test_manifest.star +319 -0
  356. package/engine/topologies/tilt/manifest/tests/test_validator.star +472 -0
  357. package/engine/topologies/tilt/manifest/validator.star +744 -0
  358. package/engine/topologies/tilt/manifest/yaml_to_json.py +20 -0
  359. package/engine/topologies/tilt/resources/AGENTS.md +71 -0
  360. package/engine/topologies/tilt/resources/build_concurrency.star +56 -0
  361. package/engine/topologies/tilt/resources/conditions.star +5 -0
  362. package/engine/topologies/tilt/resources/databases.star +246 -0
  363. package/engine/topologies/tilt/resources/declaration.star +5 -0
  364. package/engine/topologies/tilt/resources/deps.star +5 -0
  365. package/engine/topologies/tilt/resources/infra-loader.star +504 -0
  366. package/engine/topologies/tilt/resources/libs.star +32 -0
  367. package/engine/topologies/tilt/resources/libs_discovery.star +104 -0
  368. package/engine/topologies/tilt/resources/libs_paths.star +81 -0
  369. package/engine/topologies/tilt/resources/libs_resource_definition.star +153 -0
  370. package/engine/topologies/tilt/resources/libs_setup.star +166 -0
  371. package/engine/topologies/tilt/resources/libs_tsconfig.star +39 -0
  372. package/engine/topologies/tilt/resources/orchestrator/apply.star +79 -0
  373. package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +864 -0
  374. package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +90 -0
  375. package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +150 -0
  376. package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +38 -0
  377. package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +46 -0
  378. package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +193 -0
  379. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
  380. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +23 -0
  381. package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +136 -0
  382. package/engine/topologies/tilt/resources/orchestrator/generators/env.star +219 -0
  383. package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +172 -0
  384. package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +577 -0
  385. package/engine/topologies/tilt/resources/orchestrator/helpers.star +35 -0
  386. package/engine/topologies/tilt/resources/orchestrator.star +56 -0
  387. package/engine/topologies/tilt/resources/ordering.star +5 -0
  388. package/engine/topologies/tilt/resources/shared-platform-postgres.star +30 -0
  389. package/engine/topologies/tilt/resources/triggers.star +5 -0
  390. package/engine/topologies/tilt/resources/watchers.star +304 -0
  391. package/engine/where-things-live.star +719 -0
  392. package/examples/tdk-example/LICENSE +21 -0
  393. package/examples/tdk-example/README.md +23 -0
  394. package/examples/tdk-example/TILT_SERVICE_DEFAULTS.star +42 -0
  395. package/examples/tdk-example/TILT_TECH_STACK.star +67 -0
  396. package/examples/tdk-example/Tiltfile +25 -0
  397. package/examples/tdk-example/services/platform/messaging/docker-compose.yml +26 -0
  398. package/examples/tdk-example/services/shop/orders-api/package.json +20 -0
  399. package/examples/tdk-example/services/shop/orders-api/service.json +14 -0
  400. package/examples/tdk-example/services/shop/orders-api/src/index.ts +81 -0
  401. package/examples/tdk-example/services/shop/orders-app/index.html +12 -0
  402. package/examples/tdk-example/services/shop/orders-app/package.json +23 -0
  403. package/examples/tdk-example/services/shop/orders-app/public/.gitkeep +0 -0
  404. package/examples/tdk-example/services/shop/orders-app/service.json +9 -0
  405. package/examples/tdk-example/services/shop/orders-app/src/main.tsx +9 -0
  406. package/examples/tdk-example/services/shop/orders-app/src/orders.tsx +67 -0
  407. package/examples/tdk-example/services/shop/orders-app/src/style.css +15 -0
  408. package/examples/tdk-example/services/shop/orders-worker/package.json +18 -0
  409. package/examples/tdk-example/services/shop/orders-worker/service.json +13 -0
  410. package/examples/tdk-example/services/shop/orders-worker/src/index.ts +33 -0
  411. package/ext/Tiltfile +66 -0
  412. package/ext/ide-components/README.md +221 -0
  413. package/ext/ide-components/code_viewer/server.py +208 -0
  414. package/ext/ide-components/config_inspector/server.py +1052 -0
  415. package/ext/ide-components/file_browser/server.py +287 -0
  416. package/ext/ide-components/shared/config_service.py +471 -0
  417. package/ext/ide-components/shared/file_utils.py +300 -0
  418. package/ext/ide-components/shared/http_utils.py +234 -0
  419. package/ext/ide-components/shared/static/styles.css +1334 -0
  420. package/ext/ide-components/shared/syntax_highlighter.py +142 -0
  421. package/ext/ide-components/shared/template_engine.py +125 -0
  422. package/ext/ide-components/shared/templates/base.html +121 -0
  423. package/ext/ide-components/shared/test_config_service.py +328 -0
  424. package/ext/ide-components/shared/tilt_integration.py +160 -0
  425. package/ext/ui-enhancements/cron-status-server.sh +51 -0
  426. package/ext/ui-enhancements/cron-status-tracker.sh +148 -0
  427. package/ext/ui-enhancements/extension.yaml +36 -0
  428. package/ext/ui-enhancements/tiltfile.py +101 -0
  429. package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
  430. package/ext/ui-enhancements/ui/help-panel.css +279 -0
  431. package/ext/ui-enhancements/ui/icons.css +125 -0
  432. package/ext/ui-enhancements/ui/tooltips.css +114 -0
  433. package/package.json +94 -4
  434. package/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
  435. package/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
  436. package/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
  437. package/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
  438. package/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
  439. package/specs/specs/TILT_SERVICE_DEFAULTS.star +207 -0
  440. package/specs/specs/TILT_TECH_STACK.star +161 -0
@@ -0,0 +1,40 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import chalk from "chalk";
4
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
5
+ export function startSpinner(initialText) {
6
+ const stream = process.stderr;
7
+ const animate = stream.isTTY === true;
8
+ let frame = 0;
9
+ let text = initialText;
10
+ let timer;
11
+ const render = () => stream.write(`\r\x1b[2K${chalk.cyan(FRAMES[frame])} ${text}`);
12
+ if (animate) {
13
+ render();
14
+ timer = setInterval(() => {
15
+ frame = (frame + 1) % FRAMES.length;
16
+ render();
17
+ }, 80);
18
+ }
19
+ else {
20
+ stream.write(`- ${text}\n`);
21
+ }
22
+ const finish = (symbol, message) => {
23
+ if (timer)
24
+ clearInterval(timer);
25
+ stream.write(`${animate ? "\r\x1b[2K" : ""}${symbol} ${message ?? text}\n`);
26
+ };
27
+ return {
28
+ get text() {
29
+ return text;
30
+ },
31
+ set text(value) {
32
+ text = value;
33
+ if (!animate)
34
+ stream.write(`- ${text}\n`);
35
+ },
36
+ succeed: (message) => finish(chalk.green("✔"), message),
37
+ fail: (message) => finish(chalk.red("✖"), message),
38
+ warn: (message) => finish(chalk.yellow("⚠"), message),
39
+ };
40
+ }
@@ -0,0 +1,15 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import { DATABASE_MANAGEMENT_FEATURE } from "./constants.js";
4
+ export const STACK_FEATURES = {
5
+ [DATABASE_MANAGEMENT_FEATURE]: {
6
+ name: DATABASE_MANAGEMENT_FEATURE,
7
+ description: "Generate and load the stack-level PostgreSQL docker-compose file",
8
+ generatedFiles: ["services/platform/database-management/docker-compose.yml"],
9
+ },
10
+ };
11
+ export function isStackFeatureEnabledInStacks(stacks, featureName) {
12
+ if (!STACK_FEATURES[featureName])
13
+ return false;
14
+ return ["pre_alpha", "alpha", "beta"].some((phase) => stacks[phase]?.enabledStacks?.includes(featureName));
15
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A stack with no known service status has not been checked, so it is "unknown", not "error". Once any service has a
3
+ * status, the share of ready services decides it.
4
+ */
5
+ export function deriveStackStatus(statuses) {
6
+ if (statuses.length === 0 || statuses.every((status) => status === "unknown"))
7
+ return "unknown";
8
+ const ratio = statuses.filter((status) => status === "ready").length / statuses.length;
9
+ if (ratio > 0.9)
10
+ return "healthy";
11
+ if (ratio > 0.5)
12
+ return "degraded";
13
+ return "error";
14
+ }
@@ -0,0 +1,78 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import { parseTiltResourceFailures, summarizeTiltBuildError } from "./doctor-runtime.js";
4
+ import { portConflictFix } from "./port-conflict-fix.js";
5
+ import { effectiveRuntimeStatus, isTiltResourcePending } from "./tilt-resource-state.js";
6
+ import { onlyEnabledResources } from "./up-readiness.js";
7
+ export function transitiveDependencies(name, dependsOn) {
8
+ const seen = new Set();
9
+ const visit = (current) => {
10
+ for (const dep of dependsOn[current] ?? []) {
11
+ if (seen.has(dep))
12
+ continue;
13
+ seen.add(dep);
14
+ visit(dep);
15
+ }
16
+ };
17
+ visit(name);
18
+ return seen;
19
+ }
20
+ function isPending(item) {
21
+ return isTiltResourcePending(item.status?.updateStatus ?? "", effectiveRuntimeStatus(item.status));
22
+ }
23
+ export function buildStartupReport(jsonText, dependsOn, deferred = new Set()) {
24
+ const enabledJson = onlyEnabledResources(jsonText);
25
+ const failures = parseTiltResourceFailures(enabledJson, deferred).failures;
26
+ const failed = failures.map((failure) => ({
27
+ name: failure.name,
28
+ message: failure.error
29
+ ? summarizeTiltBuildError(failure.error)
30
+ : `${failure.updateStatus}/${failure.runtimeStatus}`,
31
+ }));
32
+ const failedNames = new Set(failed.map((entry) => entry.name));
33
+ const items = JSON.parse(enabledJson).items ?? [];
34
+ const blocked = [];
35
+ const starting = [];
36
+ for (const item of items) {
37
+ const name = item.metadata?.name ?? "unknown";
38
+ if (name === "(Tiltfile)" || failedNames.has(name) || deferred.has(name))
39
+ continue;
40
+ const because = [...transitiveDependencies(name, dependsOn)]
41
+ .filter((dep) => failedNames.has(dep))
42
+ .sort();
43
+ if (because.length > 0)
44
+ blocked.push({ name, because });
45
+ else if (isPending(item))
46
+ starting.push(name);
47
+ }
48
+ return { failed, blocked, starting };
49
+ }
50
+ /** A failure exists and everything still pending is blocked by it, so waiting longer cannot help. */
51
+ export function isStartupStalled(jsonText, dependsOn, deferred = new Set()) {
52
+ const report = buildStartupReport(jsonText, dependsOn, deferred);
53
+ return report.failed.length > 0 && report.starting.length === 0;
54
+ }
55
+ export function formatStartupReport(report, timedOut) {
56
+ const lines = [];
57
+ for (const { name, message } of report.failed) {
58
+ lines.push(`✗ ${name} failed: ${message}`);
59
+ const fix = portConflictFix(message);
60
+ if (fix)
61
+ lines.push(` ${fix}`);
62
+ }
63
+ for (const { name, because } of report.blocked) {
64
+ lines.push(`✗ ${name} is not ready because ${because.join(", ")} failed`);
65
+ }
66
+ if (report.starting.length > 0) {
67
+ lines.push(`${timedOut ? "Timed out waiting for" : "Still starting:"} ${report.starting.join(", ")}`);
68
+ }
69
+ if (lines.length > 0) {
70
+ const causes = [...new Set(report.blocked.flatMap((entry) => entry.because))].sort();
71
+ const count = report.blocked.length;
72
+ const summary = count > 0
73
+ ? `: ${causes.join(", ")} failed, so ${count} dependent ${count === 1 ? "service is" : "services are"} not ready`
74
+ : "";
75
+ lines.push(`The environment is not ready${summary}. Tilt is still running; inspect it or run: flisk down`);
76
+ }
77
+ return lines;
78
+ }
@@ -0,0 +1,21 @@
1
+ export function createStatusMessageController(setMessage) {
2
+ let timer;
3
+ return {
4
+ show(message, durationMs = 1500) {
5
+ if (timer !== undefined) {
6
+ clearTimeout(timer);
7
+ }
8
+ setMessage(message);
9
+ timer = setTimeout(() => {
10
+ timer = undefined;
11
+ setMessage("");
12
+ }, durationMs);
13
+ },
14
+ dispose() {
15
+ if (timer !== undefined) {
16
+ clearTimeout(timer);
17
+ timer = undefined;
18
+ }
19
+ },
20
+ };
21
+ }
@@ -0,0 +1,33 @@
1
+ import { STANDARD_PORTS } from "./constants.js";
2
+ import { isApiServiceType } from "./resource-kind.js";
3
+ import { resolveServicePath, resolveSubdomainBases } from "./service-urls.js";
4
+ export function buildServicePorts(resource, ingressHttp) {
5
+ const appType = resource.config?.appType;
6
+ const routable = appType === "frontend" || isApiServiceType(appType);
7
+ let url = null;
8
+ if (routable) {
9
+ const { appBase, apiBase } = resolveSubdomainBases(ingressHttp);
10
+ url = `${isApiServiceType(appType) ? apiBase : appBase}${resolveServicePath(resource)}`;
11
+ }
12
+ const containerPort = resource.port ?? resource.config?.port ?? null;
13
+ const directUrl = !routable && containerPort ? `http://localhost:${containerPort}` : null;
14
+ return { url, containerPort, hostPort: null, directUrl };
15
+ }
16
+ /** Ports a client should forward or open: ingress, Tilt UI, and the published datastore. Not one per service. */
17
+ export function buildStackPorts(plan, tiltPort) {
18
+ const ports = [];
19
+ if (plan) {
20
+ ports.push({ name: "ingress-http", hostPort: plan.ingressHttp, purpose: "Traefik HTTP ingress" }, { name: "ingress-https", hostPort: plan.ingressHttps, purpose: "Traefik HTTPS ingress" });
21
+ }
22
+ // `flisk up` may move Tilt off 10350 and records that only in its own process, so this is the default or TILT_PORT.
23
+ const validTiltPort = tiltPort !== undefined && Number.isInteger(tiltPort) && tiltPort > 0;
24
+ ports.push({
25
+ name: "tilt-ui",
26
+ hostPort: validTiltPort ? tiltPort : STANDARD_PORTS.tiltUi,
27
+ purpose: "Tilt UI",
28
+ });
29
+ if (plan) {
30
+ ports.push({ name: "postgres", hostPort: plan.postgres, purpose: "Published Postgres" });
31
+ }
32
+ return ports;
33
+ }
@@ -0,0 +1,63 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ // Every cell is written before it is read, so the fallback never changes the result.
4
+ function cell(row, index) {
5
+ return row[index] ?? 0;
6
+ }
7
+ function levenshteinDistance(left, right) {
8
+ let previousRow = Array.from({ length: right.length + 1 }, (_, index) => index);
9
+ for (let leftIndex = 1; leftIndex <= left.length; leftIndex++) {
10
+ const currentRow = [leftIndex];
11
+ for (let rightIndex = 1; rightIndex <= right.length; rightIndex++) {
12
+ const substitutionCost = left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1;
13
+ currentRow[rightIndex] = Math.min(cell(currentRow, rightIndex - 1) + 1, cell(previousRow, rightIndex) + 1, cell(previousRow, rightIndex - 1) + substitutionCost);
14
+ }
15
+ previousRow = currentRow;
16
+ }
17
+ return cell(previousRow, right.length);
18
+ }
19
+ function isAdjacentTransposition(left, right) {
20
+ if (left.length !== right.length)
21
+ return false;
22
+ for (let index = 0; index < left.length - 1; index++) {
23
+ if (left[index] !== right[index] &&
24
+ left[index] === right[index + 1] &&
25
+ left[index + 1] === right[index] &&
26
+ left.slice(0, index) === right.slice(0, index) &&
27
+ left.slice(index + 2) === right.slice(index + 2)) {
28
+ return true;
29
+ }
30
+ }
31
+ return false;
32
+ }
33
+ /**
34
+ * Bases the threshold on the longer name and caps it at two edits.
35
+ * An adjacent transposition counts as one typo; ties use deterministic code-unit order.
36
+ */
37
+ export function suggestClosest(input, candidates) {
38
+ if (input.length < 2 || candidates.length === 0)
39
+ return undefined;
40
+ // stackExists and findUnknownServices are case-sensitive, so case-only mismatches need the canonical spelling.
41
+ if (candidates.includes(input))
42
+ return undefined;
43
+ const normalizedInput = input.toLowerCase();
44
+ let closest;
45
+ let closestDistance = Number.POSITIVE_INFINITY;
46
+ for (const candidate of candidates) {
47
+ if (candidate.length === 0)
48
+ continue;
49
+ const normalizedCandidate = candidate.toLowerCase();
50
+ const distance = isAdjacentTransposition(normalizedInput, normalizedCandidate)
51
+ ? 1
52
+ : levenshteinDistance(normalizedInput, normalizedCandidate);
53
+ const threshold = Math.max(1, Math.min(2, Math.floor(Math.max(normalizedInput.length, normalizedCandidate.length) / 3)));
54
+ if (distance > threshold)
55
+ continue;
56
+ if (distance < closestDistance ||
57
+ (distance === closestDistance && (closest === undefined || candidate < closest))) {
58
+ closest = candidate;
59
+ closestDistance = distance;
60
+ }
61
+ }
62
+ return closest;
63
+ }
@@ -0,0 +1,46 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import { spawnSync } from "node:child_process";
4
+ import { existsSync, mkdirSync, mkdtempSync, readdirSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join } from "node:path";
7
+ /**
8
+ * Extracts a gzipped tarball (as an in-memory buffer) into destDir.
9
+ * Shells out to the system `tar` binary rather than pulling in a JS tar
10
+ * implementation - available by default on macOS and Linux.
11
+ */
12
+ export function extractTarball(data, destDir) {
13
+ const tempDir = mkdtempSync(join(tmpdir(), "flisk-ext-"));
14
+ const tmpFile = join(tempDir, "bundle.tar.gz");
15
+ writeFileSync(tmpFile, data);
16
+ mkdirSync(destDir, { recursive: true });
17
+ const tarBin = process.platform === "win32" ? "tar.exe" : "tar";
18
+ const result = spawnSync(tarBin, ["xzf", tmpFile, "-C", destDir, "--strip-components=1"], {
19
+ stdio: "pipe",
20
+ windowsHide: true,
21
+ });
22
+ if (result.status !== 0) {
23
+ const fallbackDir = join(tempDir, "fallback");
24
+ mkdirSync(fallbackDir, { recursive: true });
25
+ const fallback = spawnSync(tarBin, ["xzf", tmpFile, "-C", fallbackDir], {
26
+ stdio: "pipe",
27
+ windowsHide: true,
28
+ });
29
+ if (fallback.status !== 0) {
30
+ rmSync(tempDir, { recursive: true, force: true });
31
+ throw new Error(`tar extraction failed: ${fallback.stderr?.toString() || result.stderr?.toString() || "unknown error"}`);
32
+ }
33
+ const entries = readdirSync(fallbackDir);
34
+ const [only] = entries;
35
+ const sourceDir = entries.length === 1 &&
36
+ only !== undefined &&
37
+ existsSync(join(fallbackDir, only)) &&
38
+ statSync(join(fallbackDir, only)).isDirectory()
39
+ ? join(fallbackDir, only)
40
+ : fallbackDir;
41
+ for (const entry of readdirSync(sourceDir)) {
42
+ renameSync(join(sourceDir, entry), join(destDir, entry));
43
+ }
44
+ }
45
+ rmSync(tempDir, { recursive: true, force: true });
46
+ }
@@ -0,0 +1,51 @@
1
+ // Copyright (c) 2026 Flisk Landscape contributors
2
+ // SPDX-License-Identifier: MIT
3
+ import { readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { PROJECT_JSON } from "./constants.js";
6
+ function toParts(raw) {
7
+ const match = raw.trim().match(/(\d+)\.(\d+)(?:\.(\d+))?/);
8
+ return match ? [Number(match[1]), Number(match[2]), Number(match[3] ?? 0)] : null;
9
+ }
10
+ function readMinTdkVersion(projectRoot) {
11
+ try {
12
+ const parsed = JSON.parse(readFileSync(join(projectRoot, ".tdk", PROJECT_JSON), "utf-8"));
13
+ return parsed?.minTdkVersion;
14
+ }
15
+ catch {
16
+ return undefined;
17
+ }
18
+ }
19
+ export function evaluateTdkVersionFloor(projectRoot, currentVersion) {
20
+ const minimum = readMinTdkVersion(projectRoot);
21
+ if (minimum === undefined)
22
+ return { status: "none" };
23
+ const required = typeof minimum === "string" ? toParts(minimum) : null;
24
+ if (!required || !/^\d+\.\d+\.\d+$/.test(String(minimum).trim())) {
25
+ return {
26
+ status: "malformed",
27
+ message: `.tdk/project.json minTdkVersion ${JSON.stringify(minimum)} is not a version like "1.3.80"`,
28
+ fix: 'Set minTdkVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".',
29
+ };
30
+ }
31
+ const current = toParts(currentVersion);
32
+ const meets = current !== null &&
33
+ (() => {
34
+ for (const [index, need] of required.entries()) {
35
+ const actual = current[index] ?? 0;
36
+ if (actual !== need)
37
+ return actual > need;
38
+ }
39
+ return true;
40
+ })();
41
+ const requiredText = required.join(".");
42
+ if (!meets) {
43
+ return {
44
+ status: "too-old",
45
+ required: requiredText,
46
+ message: `flisk ${currentVersion} is older than the ${requiredText} this project requires (minTdkVersion)`,
47
+ fix: "Run: flisk upgrade",
48
+ };
49
+ }
50
+ return { status: "ok", required: requiredText };
51
+ }
@@ -0,0 +1,19 @@
1
+ const COMPACT_TAB_WIDTH = 76;
2
+ const WIDE_TAB_WIDTH = 100;
3
+ export function getTerminalRuleWidth(terminalWidth) {
4
+ return Math.max(0, Math.min(terminalWidth - 4, 100));
5
+ }
6
+ export function getTabBarDensity(terminalWidth) {
7
+ if (terminalWidth < COMPACT_TAB_WIDTH)
8
+ return "compact";
9
+ if (terminalWidth < WIDE_TAB_WIDTH)
10
+ return "standard";
11
+ return "wide";
12
+ }
13
+ /**
14
+ * Convert an SGR mouse row (1-based) to an Ink layout row (0-based).
15
+ * The UI uses Ink's alternate screen with no Static content, so the live region starts at row 1.
16
+ */
17
+ export function getListRowFromMouseY(mouseY, listTop) {
18
+ return mouseY - 1 - listTop;
19
+ }
@@ -0,0 +1,194 @@
1
+ import { STANDARD_PORTS } from "./constants.js";
2
+ import { runTilt } from "./tilt.js";
3
+ export class TiltEventsLoadError extends Error {
4
+ kind;
5
+ constructor(message, kind) {
6
+ super(message);
7
+ this.kind = kind;
8
+ this.name = "TiltEventsLoadError";
9
+ }
10
+ }
11
+ function asRecord(value) {
12
+ return typeof value === "object" && value !== null && !Array.isArray(value)
13
+ ? value
14
+ : null;
15
+ }
16
+ // Tilt-controlled text is rendered in the terminal, so drop ANSI/OSC escape sequences and
17
+ // other control characters (keeping tab/newline for later whitespace normalization).
18
+ const ESC = String.fromCharCode(0x1b);
19
+ const BEL = String.fromCharCode(0x07);
20
+ const ANSI_SEQUENCE = new RegExp(`${ESC}(?:\\[[0-?]*[ -/]*[@-~]|\\][^${BEL}${ESC}]*(?:${BEL}|${ESC}\\\\)?|[@-Z\\\\-_])`, "g");
21
+ // A regex literal would trip noControlCharactersInRegex, so this stays a string; keep the autofix from rewriting it.
22
+ // biome-ignore lint/complexity/useRegexLiterals: the control-character range must stay in a string
23
+ const CONTROL_CHARS = new RegExp("[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f]", "g");
24
+ export function stripTerminalControls(value) {
25
+ return value.replace(ANSI_SEQUENCE, "").replace(CONTROL_CHARS, "");
26
+ }
27
+ function readString(value) {
28
+ if (typeof value !== "string")
29
+ return undefined;
30
+ const cleaned = stripTerminalControls(value).trim();
31
+ return cleaned || undefined;
32
+ }
33
+ function readStringArray(value) {
34
+ return Array.isArray(value)
35
+ ? value.flatMap((item) => {
36
+ const cleaned = readString(item);
37
+ return cleaned ? [cleaned] : [];
38
+ })
39
+ : [];
40
+ }
41
+ export function parseTiltUiResourceList(value) {
42
+ const list = asRecord(value);
43
+ if (!list || !Array.isArray(list.items)) {
44
+ throw new Error("Tilt returned an invalid UIResource list");
45
+ }
46
+ const resources = [];
47
+ const events = [];
48
+ for (const value of list.items) {
49
+ const item = asRecord(value);
50
+ const metadata = asRecord(item?.metadata);
51
+ const resourceName = readString(metadata?.name);
52
+ if (!item || !resourceName)
53
+ continue;
54
+ const status = asRecord(item.status);
55
+ resources.push({
56
+ name: resourceName,
57
+ runtimeStatus: readString(status?.runtimeStatus),
58
+ updateStatus: readString(status?.updateStatus),
59
+ hasPendingChanges: typeof status?.hasPendingChanges === "boolean" ? status.hasPendingChanges : undefined,
60
+ });
61
+ const history = Array.isArray(status?.buildHistory) ? status.buildHistory : [];
62
+ for (const [buildIndex, value] of history.entries()) {
63
+ const build = asRecord(value);
64
+ if (!build)
65
+ continue;
66
+ const error = readString(build.error);
67
+ const warnings = readStringArray(build.warnings);
68
+ const details = [error, ...warnings].filter((entry) => Boolean(entry));
69
+ const spanId = readString(build.spanID);
70
+ events.push({
71
+ id: `${resourceName}:build:${spanId ?? String(buildIndex)}`,
72
+ resourceName,
73
+ kind: error ? "failed" : warnings.length ? "warning" : "success",
74
+ title: error
75
+ ? "Build failed"
76
+ : warnings.length
77
+ ? "Build completed with warnings"
78
+ : "Build completed",
79
+ occurredAt: readString(build.finishTime) ?? readString(build.startTime),
80
+ details: details.length ? details.join("; ") : undefined,
81
+ });
82
+ }
83
+ const currentBuild = asRecord(status?.currentBuild);
84
+ if (currentBuild) {
85
+ events.push({
86
+ id: `${resourceName}:current-build`,
87
+ resourceName,
88
+ kind: "running",
89
+ title: "Build in progress",
90
+ occurredAt: readString(currentBuild.startTime),
91
+ });
92
+ }
93
+ const pendingSince = readString(status?.pendingBuildSince);
94
+ if (!currentBuild && (status?.queued === true || pendingSince)) {
95
+ events.push({
96
+ id: `${resourceName}:queued`,
97
+ resourceName,
98
+ kind: "warning",
99
+ title: "Update queued",
100
+ occurredAt: pendingSince,
101
+ });
102
+ }
103
+ const lastDeployTime = readString(status?.lastDeployTime);
104
+ const deployTimestamp = lastDeployTime ? Date.parse(lastDeployTime) : Number.NaN;
105
+ const matchingBuild = events.some((event) => event.resourceName === resourceName &&
106
+ event.kind === "success" &&
107
+ event.occurredAt !== undefined &&
108
+ Date.parse(event.occurredAt) === deployTimestamp);
109
+ if (lastDeployTime && !matchingBuild) {
110
+ events.push({
111
+ id: `${resourceName}:last-deploy`,
112
+ resourceName,
113
+ kind: "success",
114
+ title: "Last deployed",
115
+ occurredAt: lastDeployTime,
116
+ });
117
+ }
118
+ const conditions = Array.isArray(status?.conditions) ? status.conditions : [];
119
+ for (const [conditionIndex, value] of conditions.entries()) {
120
+ const condition = asRecord(value);
121
+ if (!condition)
122
+ continue;
123
+ const type = readString(condition.type);
124
+ const state = readString(condition.status);
125
+ const reason = readString(condition.reason);
126
+ const message = readString(condition.message);
127
+ if ((!type && !reason && !message) || (state === "True" && !reason && !message))
128
+ continue;
129
+ const detail = [reason, message]
130
+ .filter((entry) => Boolean(entry))
131
+ .join(": ");
132
+ events.push({
133
+ id: `${resourceName}:condition:${conditionIndex}:${type ?? "status"}`,
134
+ resourceName,
135
+ kind: state === "False" ? "warning" : "status",
136
+ title: `Condition ${type ?? "status"}${state ? `: ${state}` : ""}`,
137
+ occurredAt: readString(condition.lastTransitionTime),
138
+ details: detail || undefined,
139
+ });
140
+ }
141
+ }
142
+ events.sort((left, right) => {
143
+ if (left.kind === "running" && right.kind !== "running")
144
+ return -1;
145
+ if (right.kind === "running" && left.kind !== "running")
146
+ return 1;
147
+ const leftTime = left.occurredAt ? Date.parse(left.occurredAt) : Number.NaN;
148
+ const rightTime = right.occurredAt ? Date.parse(right.occurredAt) : Number.NaN;
149
+ if (Number.isNaN(leftTime)) {
150
+ return Number.isNaN(rightTime) ? left.resourceName.localeCompare(right.resourceName) : 1;
151
+ }
152
+ if (Number.isNaN(rightTime))
153
+ return -1;
154
+ return rightTime - leftTime;
155
+ });
156
+ return { resources, events };
157
+ }
158
+ export async function loadTiltEvents() {
159
+ const port = process.env.TILT_PORT ?? String(STANDARD_PORTS.tiltUi);
160
+ let result;
161
+ try {
162
+ result = await runTilt("get", ["uiresources", "-o", "json", "--port", port], {
163
+ inheritStdio: false,
164
+ timeoutMs: 10_000,
165
+ });
166
+ }
167
+ catch (error) {
168
+ const message = error instanceof Error ? error.message : String(error);
169
+ const kind = /ENOENT|not found|no such file|connection refused|failed to connect|could not connect|unable to connect|Tilt is not running/i.test(message)
170
+ ? "unavailable"
171
+ : "error";
172
+ throw new TiltEventsLoadError(message, kind);
173
+ }
174
+ if (result.exitCode !== 0) {
175
+ const message = result.stderr.trim() || `tilt get exited with code ${result.exitCode}`;
176
+ const kind = /connection refused|failed to connect|could not connect|unable to connect|Tilt is not running|no running Tilt/i.test(message)
177
+ ? "unavailable"
178
+ : "error";
179
+ throw new TiltEventsLoadError(message, kind);
180
+ }
181
+ let parsed;
182
+ try {
183
+ parsed = JSON.parse(result.stdout);
184
+ }
185
+ catch {
186
+ throw new TiltEventsLoadError("Tilt returned invalid UIResource JSON", "error");
187
+ }
188
+ try {
189
+ return parseTiltUiResourceList(parsed);
190
+ }
191
+ catch (error) {
192
+ throw new TiltEventsLoadError(error instanceof Error ? error.message : "Tilt returned an invalid UIResource list", "error");
193
+ }
194
+ }
@@ -0,0 +1,61 @@
1
+ export const DEFAULT_LOG_TAIL = 200;
2
+ /** Upper bound for --tail so a snapshot stays small enough for an agent to read. */
3
+ export const MAX_LOG_TAIL = 10_000;
4
+ const NANOSECONDS = {
5
+ ns: 1,
6
+ us: 1e3,
7
+ µs: 1e3,
8
+ ms: 1e6,
9
+ s: 1e9,
10
+ m: 6e10,
11
+ h: 3.6e12,
12
+ };
13
+ // Go's time.Duration is an int64 of nanoseconds, so anything beyond this is rejected by `tilt logs`.
14
+ const MAX_DURATION_NANOSECONDS = 2 ** 63 - 1;
15
+ /**
16
+ * Go-style duration such as 30s, 5m, 1h or 1h30m, within roughly the range Go's ParseDuration accepts.
17
+ * The sum is a JS number, so values within a few nanoseconds of the int64 limit can disagree with Go; this only needs to
18
+ * reject absurd input, and Tilt remains the final judge (its rejection is reported as TILT_LOGS_FAILED).
19
+ */
20
+ export function isValidSince(value) {
21
+ if (!/^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/.test(value))
22
+ return false;
23
+ let total = 0;
24
+ for (const [, amount, unit] of value.matchAll(/(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)/g)) {
25
+ total += Number(amount) * (NANOSECONDS[unit] ?? 0);
26
+ }
27
+ return total <= MAX_DURATION_NANOSECONDS;
28
+ }
29
+ export function isValidPort(value) {
30
+ return /^[1-9]\d{0,4}$/.test(value) && Number(value) <= 65535;
31
+ }
32
+ export function isValidTail(value) {
33
+ return /^[1-9]\d*$/.test(value) && Number(value) <= MAX_LOG_TAIL;
34
+ }
35
+ /** Parse `tilt logs --json` (JSON Lines) into normalized lines, keeping at most the last `limit`. Unparseable lines are skipped. */
36
+ export function parseTiltLogLines(output, limit) {
37
+ const lines = [];
38
+ for (const raw of output.split("\n")) {
39
+ if (!raw.trim())
40
+ continue;
41
+ try {
42
+ const entry = JSON.parse(raw);
43
+ const str = (value) => typeof value === "string" && value !== "" ? value : null;
44
+ lines.push({
45
+ time: str(entry.time),
46
+ resource: str(entry.resource),
47
+ level: str(entry.level),
48
+ source: str(entry.source),
49
+ text: typeof entry.message === "string" ? entry.message : "",
50
+ });
51
+ }
52
+ catch {
53
+ // Tilt can print a non-JSON notice before the stream; it is not a log line.
54
+ }
55
+ }
56
+ return lines.slice(-limit);
57
+ }
58
+ /** True when `tilt logs` failed because no Tilt server answered, as opposed to rejecting its arguments. */
59
+ export function isTiltConnectionFailure(stderr) {
60
+ return /connection refused|connecting to Tilt|no such host|dial tcp|websocket_token/i.test(stderr);
61
+ }