tinybeeai 0.0.0-stage → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.railway/railway.ts +83 -0
- package/.railway/tsconfig.json +13 -0
- package/AGENTS.md +102 -0
- package/Dockerfile +108 -0
- package/LICENSE +21 -0
- package/README.md +275 -2
- package/bin/localdost.js +29 -0
- package/bin/tinybeeai.js +28 -0
- package/compose.yml +63 -0
- package/demo/payloads/ci_failure.json +46 -0
- package/demo/payloads/outage.json +18 -0
- package/demo/payloads/pr_comment_edited.json +50 -0
- package/demo/payloads/pr_merged.json +80 -0
- package/demo/payloads/pr_opened.json +69 -0
- package/demo/payloads/pr_synchronize.json +69 -0
- package/demo/payloads/ticket_created.json +138 -0
- package/demo/sample-app/playwright.config.ts +20 -0
- package/demo/sample-app/server.ts +163 -0
- package/demo/sample-app/tests/checkout.spec.ts +13 -0
- package/demo/sample-app/tests/smoke.spec.ts +8 -0
- package/dist/agent/approval-retries.js +59 -0
- package/dist/agent/approval-retries.js.map +1 -0
- package/dist/agent/approvals.js +390 -0
- package/dist/agent/approvals.js.map +1 -0
- package/dist/agent/chat-bridge.js +154 -0
- package/dist/agent/chat-bridge.js.map +1 -0
- package/dist/agent/chat-lead.js +475 -0
- package/dist/agent/chat-lead.js.map +1 -0
- package/dist/agent/chat-loop.js +106 -0
- package/dist/agent/chat-loop.js.map +1 -0
- package/dist/agent/chat-mcp.js +49 -0
- package/dist/agent/chat-mcp.js.map +1 -0
- package/dist/agent/chat-tool-blocks.js +453 -0
- package/dist/agent/chat-tool-blocks.js.map +1 -0
- package/dist/agent/chat-view.js +94 -0
- package/dist/agent/chat-view.js.map +1 -0
- package/dist/agent/chat-views.js +781 -0
- package/dist/agent/chat-views.js.map +1 -0
- package/dist/agent/chat.js +1703 -0
- package/dist/agent/chat.js.map +1 -0
- package/dist/agent/destinations.js +150 -0
- package/dist/agent/destinations.js.map +1 -0
- package/dist/agent/llm-cli.js +451 -0
- package/dist/agent/llm-cli.js.map +1 -0
- package/dist/agent/llm-codex.js +493 -0
- package/dist/agent/llm-codex.js.map +1 -0
- package/dist/agent/llm-openai.js +211 -0
- package/dist/agent/llm-openai.js.map +1 -0
- package/dist/agent/llm.js +1464 -0
- package/dist/agent/llm.js.map +1 -0
- package/dist/agent/memory.js +33 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/mock-views.js +93 -0
- package/dist/agent/mock-views.js.map +1 -0
- package/dist/agent/model-availability.js +207 -0
- package/dist/agent/model-availability.js.map +1 -0
- package/dist/agent/model-errors.js +188 -0
- package/dist/agent/model-errors.js.map +1 -0
- package/dist/agent/model-guard.js +311 -0
- package/dist/agent/model-guard.js.map +1 -0
- package/dist/agent/prompts.js +374 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/qa-lenses/qa-auth.md +32 -0
- package/dist/agent/qa-lenses/qa-check-then-act.md +33 -0
- package/dist/agent/qa-lenses/qa-control-has-no-effect.md +32 -0
- package/dist/agent/qa-lenses/qa-dates.md +31 -0
- package/dist/agent/qa-lenses/qa-double-submit.md +34 -0
- package/dist/agent/qa-lenses/qa-feature-flag.md +29 -0
- package/dist/agent/qa-lenses/qa-migration.md +35 -0
- package/dist/agent/qa-lenses/qa-money.md +38 -0
- package/dist/agent/qa-lenses/qa-response-shape-break.md +33 -0
- package/dist/agent/qa-lenses/qa-validation.md +29 -0
- package/dist/agent/qa-prompts.js +660 -0
- package/dist/agent/qa-prompts.js.map +1 -0
- package/dist/agent/reasoning.js +55 -0
- package/dist/agent/reasoning.js.map +1 -0
- package/dist/agent/redact.js +48 -0
- package/dist/agent/redact.js.map +1 -0
- package/dist/agent/rules.js +927 -0
- package/dist/agent/rules.js.map +1 -0
- package/dist/agent/runs.js +440 -0
- package/dist/agent/runs.js.map +1 -0
- package/dist/agent/send-retry.js +62 -0
- package/dist/agent/send-retry.js.map +1 -0
- package/dist/agent/team-notes.js +288 -0
- package/dist/agent/team-notes.js.map +1 -0
- package/dist/agent/token-meter.js +31 -0
- package/dist/agent/token-meter.js.map +1 -0
- package/dist/agent/triage.js +506 -0
- package/dist/agent/triage.js.map +1 -0
- package/dist/api.js +1047 -0
- package/dist/api.js.map +1 -0
- package/dist/approval-targets.js +107 -0
- package/dist/approval-targets.js.map +1 -0
- package/dist/bee/cloudflared.js +108 -0
- package/dist/bee/cloudflared.js.map +1 -0
- package/dist/bee/health.js +99 -0
- package/dist/bee/health.js.map +1 -0
- package/dist/bee/hive-client.js +75 -0
- package/dist/bee/hive-client.js.map +1 -0
- package/dist/bee/identity.js +39 -0
- package/dist/bee/identity.js.map +1 -0
- package/dist/bee/models.js +510 -0
- package/dist/bee/models.js.map +1 -0
- package/dist/bee/pairing.js +351 -0
- package/dist/bee/pairing.js.map +1 -0
- package/dist/bee/relay-client.js +50 -0
- package/dist/bee/relay-client.js.map +1 -0
- package/dist/bee/routes.js +214 -0
- package/dist/bee/routes.js.map +1 -0
- package/dist/bee/setup-page.js +223 -0
- package/dist/bee/setup-page.js.map +1 -0
- package/dist/bee/state.js +41 -0
- package/dist/bee/state.js.map +1 -0
- package/dist/bee/status.js +117 -0
- package/dist/bee/status.js.map +1 -0
- package/dist/bee/tunnel-manager.js +245 -0
- package/dist/bee/tunnel-manager.js.map +1 -0
- package/dist/bee/updater.js +268 -0
- package/dist/bee/updater.js.map +1 -0
- package/dist/boot.js +41 -0
- package/dist/boot.js.map +1 -0
- package/dist/call/index.js +145 -0
- package/dist/call/index.js.map +1 -0
- package/dist/case-folders.js +294 -0
- package/dist/case-folders.js.map +1 -0
- package/dist/cases.js +554 -0
- package/dist/cases.js.map +1 -0
- package/dist/chat-blocks.js +709 -0
- package/dist/chat-blocks.js.map +1 -0
- package/dist/chat-parse-util.js +38 -0
- package/dist/chat-parse-util.js.map +1 -0
- package/dist/chat-results.js +96 -0
- package/dist/chat-results.js.map +1 -0
- package/dist/chat-stats.js +193 -0
- package/dist/chat-stats.js.map +1 -0
- package/dist/chat-view-specs.js +186 -0
- package/dist/chat-view-specs.js.map +1 -0
- package/dist/cli/doctor-ops.js +361 -0
- package/dist/cli/doctor-ops.js.map +1 -0
- package/dist/cli/doctor.js +289 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/dogfood.js +70 -0
- package/dist/cli/dogfood.js.map +1 -0
- package/dist/cli/env-file.js +34 -0
- package/dist/cli/env-file.js.map +1 -0
- package/dist/cli/eval-chat-cases.js +359 -0
- package/dist/cli/eval-chat-cases.js.map +1 -0
- package/dist/cli/eval-chat-results.js +85 -0
- package/dist/cli/eval-chat-results.js.map +1 -0
- package/dist/cli/eval-chat.js +508 -0
- package/dist/cli/eval-chat.js.map +1 -0
- package/dist/cli/eval-designer.js +67 -0
- package/dist/cli/eval-designer.js.map +1 -0
- package/dist/cli/eval-qa-review.js +284 -0
- package/dist/cli/eval-qa-review.js.map +1 -0
- package/dist/cli/golden-export.js +35 -0
- package/dist/cli/golden-export.js.map +1 -0
- package/dist/cli/index.js +90 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.js +746 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan-repo.js +199 -0
- package/dist/cli/scan-repo.js.map +1 -0
- package/dist/cli/seed.js +108 -0
- package/dist/cli/seed.js.map +1 -0
- package/dist/cli/tinybee.js +247 -0
- package/dist/cli/tinybee.js.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/connect/aivision-local.js +833 -0
- package/dist/connect/aivision-local.js.map +1 -0
- package/dist/connect/aivision-token.js +84 -0
- package/dist/connect/aivision-token.js.map +1 -0
- package/dist/connect/crypto.js +65 -0
- package/dist/connect/crypto.js.map +1 -0
- package/dist/connect/deps.js +110 -0
- package/dist/connect/deps.js.map +1 -0
- package/dist/connect/engines.js +144 -0
- package/dist/connect/engines.js.map +1 -0
- package/dist/connect/github-access.js +74 -0
- package/dist/connect/github-access.js.map +1 -0
- package/dist/connect/github-app.js +129 -0
- package/dist/connect/github-app.js.map +1 -0
- package/dist/connect/index.js +9 -0
- package/dist/connect/index.js.map +1 -0
- package/dist/connect/model-choices.js +201 -0
- package/dist/connect/model-choices.js.map +1 -0
- package/dist/connect/providers.js +900 -0
- package/dist/connect/providers.js.map +1 -0
- package/dist/connect/readiness.js +232 -0
- package/dist/connect/readiness.js.map +1 -0
- package/dist/connect/redact.js +16 -0
- package/dist/connect/redact.js.map +1 -0
- package/dist/connect/registry.js +406 -0
- package/dist/connect/registry.js.map +1 -0
- package/dist/connect/store.js +283 -0
- package/dist/connect/store.js.map +1 -0
- package/dist/connect/tunnel.js +134 -0
- package/dist/connect/tunnel.js.map +1 -0
- package/dist/connect/types.js +8 -0
- package/dist/connect/types.js.map +1 -0
- package/dist/connections/index.js +5 -0
- package/dist/connections/index.js.map +1 -0
- package/dist/connections/manager.js +223 -0
- package/dist/connections/manager.js.map +1 -0
- package/dist/connections/presets.js +264 -0
- package/dist/connections/presets.js.map +1 -0
- package/dist/connections/store.js +132 -0
- package/dist/connections/store.js.map +1 -0
- package/dist/connections/tools.js +206 -0
- package/dist/connections/tools.js.map +1 -0
- package/dist/db-schema.js +355 -0
- package/dist/db-schema.js.map +1 -0
- package/dist/db.js +379 -0
- package/dist/db.js.map +1 -0
- package/dist/delivery.js +49 -0
- package/dist/delivery.js.map +1 -0
- package/dist/deploy-wait.js +701 -0
- package/dist/deploy-wait.js.map +1 -0
- package/dist/disk.js +243 -0
- package/dist/disk.js.map +1 -0
- package/dist/dot-health.js +966 -0
- package/dist/dot-health.js.map +1 -0
- package/dist/dot-remove.js +246 -0
- package/dist/dot-remove.js.map +1 -0
- package/dist/events.js +38 -0
- package/dist/events.js.map +1 -0
- package/dist/evidence-pack.js +423 -0
- package/dist/evidence-pack.js.map +1 -0
- package/dist/flows/answers.js +289 -0
- package/dist/flows/answers.js.map +1 -0
- package/dist/flows/change.js +811 -0
- package/dist/flows/change.js.map +1 -0
- package/dist/flows/checkStatus.js +524 -0
- package/dist/flows/checkStatus.js.map +1 -0
- package/dist/flows/ci.js +236 -0
- package/dist/flows/ci.js.map +1 -0
- package/dist/flows/ciFailure.js +76 -0
- package/dist/flows/ciFailure.js.map +1 -0
- package/dist/flows/common.js +522 -0
- package/dist/flows/common.js.map +1 -0
- package/dist/flows/default-branch.js +29 -0
- package/dist/flows/default-branch.js.map +1 -0
- package/dist/flows/defectDraft.js +447 -0
- package/dist/flows/defectDraft.js.map +1 -0
- package/dist/flows/defects.js +623 -0
- package/dist/flows/defects.js.map +1 -0
- package/dist/flows/digest.js +295 -0
- package/dist/flows/digest.js.map +1 -0
- package/dist/flows/impact.js +82 -0
- package/dist/flows/impact.js.map +1 -0
- package/dist/flows/index.js +23 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/intent-sources.js +72 -0
- package/dist/flows/intent-sources.js.map +1 -0
- package/dist/flows/mergeCases.js +169 -0
- package/dist/flows/mergeCases.js.map +1 -0
- package/dist/flows/nightlyRun.js +82 -0
- package/dist/flows/nightlyRun.js.map +1 -0
- package/dist/flows/outage.js +64 -0
- package/dist/flows/outage.js.map +1 -0
- package/dist/flows/postMerge.js +5 -0
- package/dist/flows/postMerge.js.map +1 -0
- package/dist/flows/prCheck.js +5 -0
- package/dist/flows/prCheck.js.map +1 -0
- package/dist/flows/prTarget.js +66 -0
- package/dist/flows/prTarget.js.map +1 -0
- package/dist/flows/qa.js +363 -0
- package/dist/flows/qa.js.map +1 -0
- package/dist/flows/questions.js +160 -0
- package/dist/flows/questions.js.map +1 -0
- package/dist/flows/recovery.js +64 -0
- package/dist/flows/recovery.js.map +1 -0
- package/dist/flows/rerun.js +50 -0
- package/dist/flows/rerun.js.map +1 -0
- package/dist/flows/testDesign.js +294 -0
- package/dist/flows/testDesign.js.map +1 -0
- package/dist/flows/testDesignJob.js +46 -0
- package/dist/flows/testDesignJob.js.map +1 -0
- package/dist/flows/testRepo.js +228 -0
- package/dist/flows/testRepo.js.map +1 -0
- package/dist/flows/testSavings.js +381 -0
- package/dist/flows/testSavings.js.map +1 -0
- package/dist/flows/testStatus.js +343 -0
- package/dist/flows/testStatus.js.map +1 -0
- package/dist/flows/ticketContext.js +425 -0
- package/dist/flows/ticketContext.js.map +1 -0
- package/dist/flows/ticketReview.js +249 -0
- package/dist/flows/ticketReview.js.map +1 -0
- package/dist/flows/ticks.js +73 -0
- package/dist/flows/ticks.js.map +1 -0
- package/dist/hive/admin.js +122 -0
- package/dist/hive/admin.js.map +1 -0
- package/dist/hive/auth.js +130 -0
- package/dist/hive/auth.js.map +1 -0
- package/dist/hive/billing.js +278 -0
- package/dist/hive/billing.js.map +1 -0
- package/dist/hive/config.js +63 -0
- package/dist/hive/config.js.map +1 -0
- package/dist/hive/db.js +186 -0
- package/dist/hive/db.js.map +1 -0
- package/dist/hive/embed.js +76 -0
- package/dist/hive/embed.js.map +1 -0
- package/dist/hive/errors.js +17 -0
- package/dist/hive/errors.js.map +1 -0
- package/dist/hive/google.js +75 -0
- package/dist/hive/google.js.map +1 -0
- package/dist/hive/index.js +25 -0
- package/dist/hive/index.js.map +1 -0
- package/dist/hive/jwt.js +57 -0
- package/dist/hive/jwt.js.map +1 -0
- package/dist/hive/keys.js +61 -0
- package/dist/hive/keys.js.map +1 -0
- package/dist/hive/mail.js +27 -0
- package/dist/hive/mail.js.map +1 -0
- package/dist/hive/native-push.js +255 -0
- package/dist/hive/native-push.js.map +1 -0
- package/dist/hive/pairing.js +342 -0
- package/dist/hive/pairing.js.map +1 -0
- package/dist/hive/presence.js +121 -0
- package/dist/hive/presence.js.map +1 -0
- package/dist/hive/push.js +185 -0
- package/dist/hive/push.js.map +1 -0
- package/dist/hive/relay.js +205 -0
- package/dist/hive/relay.js.map +1 -0
- package/dist/hive/routes.js +228 -0
- package/dist/hive/routes.js.map +1 -0
- package/dist/hive/server.js +12 -0
- package/dist/hive/server.js.map +1 -0
- package/dist/hive/session.js +28 -0
- package/dist/hive/session.js.map +1 -0
- package/dist/hive/tenants.js +287 -0
- package/dist/hive/tenants.js.map +1 -0
- package/dist/hive/tunnel/cloudflare.js +160 -0
- package/dist/hive/tunnel/cloudflare.js.map +1 -0
- package/dist/hive/tunnel/mock.js +52 -0
- package/dist/hive/tunnel/mock.js.map +1 -0
- package/dist/hive/tunnel/provider.js +19 -0
- package/dist/hive/tunnel/provider.js.map +1 -0
- package/dist/hive/updates.js +61 -0
- package/dist/hive/updates.js.map +1 -0
- package/dist/http-error.js +11 -0
- package/dist/http-error.js.map +1 -0
- package/dist/impact/classify.js +226 -0
- package/dist/impact/classify.js.map +1 -0
- package/dist/impact/find.js +259 -0
- package/dist/impact/find.js.map +1 -0
- package/dist/impact/pr.js +54 -0
- package/dist/impact/pr.js.map +1 -0
- package/dist/impact/store.js +365 -0
- package/dist/impact/store.js.map +1 -0
- package/dist/impact/text.js +158 -0
- package/dist/impact/text.js.map +1 -0
- package/dist/index.js +288 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/adf.js +397 -0
- package/dist/integrations/adf.js.map +1 -0
- package/dist/integrations/bot-marker.js +103 -0
- package/dist/integrations/bot-marker.js.map +1 -0
- package/dist/integrations/github-issues.js +705 -0
- package/dist/integrations/github-issues.js.map +1 -0
- package/dist/integrations/github.js +1284 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations/issue-create.js +60 -0
- package/dist/integrations/issue-create.js.map +1 -0
- package/dist/integrations/jira.js +279 -0
- package/dist/integrations/jira.js.map +1 -0
- package/dist/integrations/linear.js +273 -0
- package/dist/integrations/linear.js.map +1 -0
- package/dist/integrations/own-identity-warm.js +47 -0
- package/dist/integrations/own-identity-warm.js.map +1 -0
- package/dist/integrations/own-identity.js +39 -0
- package/dist/integrations/own-identity.js.map +1 -0
- package/dist/integrations/status-change.js +42 -0
- package/dist/integrations/status-change.js.map +1 -0
- package/dist/lead-defects.js +202 -0
- package/dist/lead-defects.js.map +1 -0
- package/dist/lead-digest.js +333 -0
- package/dist/lead-digest.js.map +1 -0
- package/dist/lead-release.js +286 -0
- package/dist/lead-release.js.map +1 -0
- package/dist/lead.js +328 -0
- package/dist/lead.js.map +1 -0
- package/dist/legacy-names.js +51 -0
- package/dist/legacy-names.js.map +1 -0
- package/dist/limits.js +44 -0
- package/dist/limits.js.map +1 -0
- package/dist/link-trust.js +224 -0
- package/dist/link-trust.js.map +1 -0
- package/dist/links.js +219 -0
- package/dist/links.js.map +1 -0
- package/dist/loopback.js +35 -0
- package/dist/loopback.js.map +1 -0
- package/dist/model-cap.js +60 -0
- package/dist/model-cap.js.map +1 -0
- package/dist/model-usage.js +173 -0
- package/dist/model-usage.js.map +1 -0
- package/dist/monitor/backfill.js +39 -0
- package/dist/monitor/backfill.js.map +1 -0
- package/dist/monitor/browser-probe.js +198 -0
- package/dist/monitor/browser-probe.js.map +1 -0
- package/dist/monitor/catch-up.js +31 -0
- package/dist/monitor/catch-up.js.map +1 -0
- package/dist/monitor/pollers.js +1606 -0
- package/dist/monitor/pollers.js.map +1 -0
- package/dist/monitor/probes.js +178 -0
- package/dist/monitor/probes.js.map +1 -0
- package/dist/monitor/self-health.js +228 -0
- package/dist/monitor/self-health.js.map +1 -0
- package/dist/monitor/statuspage.js +105 -0
- package/dist/monitor/statuspage.js.map +1 -0
- package/dist/nightly-scheduler.js +127 -0
- package/dist/nightly-scheduler.js.map +1 -0
- package/dist/nightly.js +141 -0
- package/dist/nightly.js.map +1 -0
- package/dist/notify/headline.js +114 -0
- package/dist/notify/headline.js.map +1 -0
- package/dist/notify/push.js +174 -0
- package/dist/notify/push.js.map +1 -0
- package/dist/object-cards.js +585 -0
- package/dist/object-cards.js.map +1 -0
- package/dist/object-links.js +47 -0
- package/dist/object-links.js.map +1 -0
- package/dist/onboarding-checks.js +141 -0
- package/dist/onboarding-checks.js.map +1 -0
- package/dist/onboarding.js +401 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/path-filters.js +62 -0
- package/dist/path-filters.js.map +1 -0
- package/dist/phone/alerts.js +67 -0
- package/dist/phone/alerts.js.map +1 -0
- package/dist/phone/auth.js +240 -0
- package/dist/phone/auth.js.map +1 -0
- package/dist/phone/pairing.js +442 -0
- package/dist/phone/pairing.js.map +1 -0
- package/dist/phone/prefs.js +27 -0
- package/dist/phone/prefs.js.map +1 -0
- package/dist/phone/tailscale.js +161 -0
- package/dist/phone/tailscale.js.map +1 -0
- package/dist/pr-scope.js +441 -0
- package/dist/pr-scope.js.map +1 -0
- package/dist/proc.js +156 -0
- package/dist/proc.js.map +1 -0
- package/dist/profile/cache.js +108 -0
- package/dist/profile/cache.js.map +1 -0
- package/dist/profile/ci.js +216 -0
- package/dist/profile/ci.js.map +1 -0
- package/dist/profile/index.js +8 -0
- package/dist/profile/index.js.map +1 -0
- package/dist/profile/job.js +135 -0
- package/dist/profile/job.js.map +1 -0
- package/dist/profile/queries/go-tags.scm +47 -0
- package/dist/profile/queries/java-tags.scm +25 -0
- package/dist/profile/queries/javascript-tags.scm +104 -0
- package/dist/profile/queries/python-tags.scm +19 -0
- package/dist/profile/queries/typescript-tags.scm +28 -0
- package/dist/profile/scan-thread.js +42 -0
- package/dist/profile/scan-thread.js.map +1 -0
- package/dist/profile/scan-worker.js +16 -0
- package/dist/profile/scan-worker.js.map +1 -0
- package/dist/profile/scan.js +351 -0
- package/dist/profile/scan.js.map +1 -0
- package/dist/profile/stack.js +528 -0
- package/dist/profile/stack.js.map +1 -0
- package/dist/profile/store.js +35 -0
- package/dist/profile/store.js.map +1 -0
- package/dist/profile/tests.js +399 -0
- package/dist/profile/tests.js.map +1 -0
- package/dist/queue.js +350 -0
- package/dist/queue.js.map +1 -0
- package/dist/refs.js +756 -0
- package/dist/refs.js.map +1 -0
- package/dist/release-notes.js +272 -0
- package/dist/release-notes.js.map +1 -0
- package/dist/reports/build.js +243 -0
- package/dist/reports/build.js.map +1 -0
- package/dist/reports/index.js +211 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/store.js +150 -0
- package/dist/reports/store.js.map +1 -0
- package/dist/reports/ticket-titles.js +124 -0
- package/dist/reports/ticket-titles.js.map +1 -0
- package/dist/reports/trace-map.js +1278 -0
- package/dist/reports/trace-map.js.map +1 -0
- package/dist/reports/traceability.js +422 -0
- package/dist/reports/traceability.js.map +1 -0
- package/dist/repos/mirror.js +356 -0
- package/dist/repos/mirror.js.map +1 -0
- package/dist/repos-github.js +108 -0
- package/dist/repos-github.js.map +1 -0
- package/dist/repos.js +891 -0
- package/dist/repos.js.map +1 -0
- package/dist/review/backend-anthropic.js +90 -0
- package/dist/review/backend-anthropic.js.map +1 -0
- package/dist/review/backend-cli.js +248 -0
- package/dist/review/backend-cli.js.map +1 -0
- package/dist/review/backend-codex.js +81 -0
- package/dist/review/backend-codex.js.map +1 -0
- package/dist/review/backend-mock.js +686 -0
- package/dist/review/backend-mock.js.map +1 -0
- package/dist/review/backend-only.js +168 -0
- package/dist/review/backend-only.js.map +1 -0
- package/dist/review/backend.js +105 -0
- package/dist/review/backend.js.map +1 -0
- package/dist/review/baseline/render-v1.js +483 -0
- package/dist/review/baseline/render-v1.js.map +1 -0
- package/dist/review/change-summary.js +197 -0
- package/dist/review/change-summary.js.map +1 -0
- package/dist/review/changelog.js +40 -0
- package/dist/review/changelog.js.map +1 -0
- package/dist/review/check.js +494 -0
- package/dist/review/check.js.map +1 -0
- package/dist/review/checkout.js +185 -0
- package/dist/review/checkout.js.map +1 -0
- package/dist/review/classify.js +178 -0
- package/dist/review/classify.js.map +1 -0
- package/dist/review/coverage.js +347 -0
- package/dist/review/coverage.js.map +1 -0
- package/dist/review/decision-eval.js +121 -0
- package/dist/review/decision-eval.js.map +1 -0
- package/dist/review/deliver.js +104 -0
- package/dist/review/deliver.js.map +1 -0
- package/dist/review/designer-eval.js +280 -0
- package/dist/review/designer-eval.js.map +1 -0
- package/dist/review/dogfood-digest.js +136 -0
- package/dist/review/dogfood-digest.js.map +1 -0
- package/dist/review/dogfood-eval.js +486 -0
- package/dist/review/dogfood-eval.js.map +1 -0
- package/dist/review/environment.js +109 -0
- package/dist/review/environment.js.map +1 -0
- package/dist/review/eval.js +405 -0
- package/dist/review/eval.js.map +1 -0
- package/dist/review/glob.js +110 -0
- package/dist/review/glob.js.map +1 -0
- package/dist/review/golden-export.js +219 -0
- package/dist/review/golden-export.js.map +1 -0
- package/dist/review/impact.js +406 -0
- package/dist/review/impact.js.map +1 -0
- package/dist/review/imports.js +542 -0
- package/dist/review/imports.js.map +1 -0
- package/dist/review/index.js +512 -0
- package/dist/review/index.js.map +1 -0
- package/dist/review/intent.js +128 -0
- package/dist/review/intent.js.map +1 -0
- package/dist/review/lenses.js +167 -0
- package/dist/review/lenses.js.map +1 -0
- package/dist/review/linked-tickets.js +293 -0
- package/dist/review/linked-tickets.js.map +1 -0
- package/dist/review/merge.js +370 -0
- package/dist/review/merge.js.map +1 -0
- package/dist/review/on-demand.js +218 -0
- package/dist/review/on-demand.js.map +1 -0
- package/dist/review/prompt-eval.js +299 -0
- package/dist/review/prompt-eval.js.map +1 -0
- package/dist/review/prompt-variants.js +37 -0
- package/dist/review/prompt-variants.js.map +1 -0
- package/dist/review/readability-eval.js +217 -0
- package/dist/review/readability-eval.js.map +1 -0
- package/dist/review/readability.js +295 -0
- package/dist/review/readability.js.map +1 -0
- package/dist/review/render.js +2409 -0
- package/dist/review/render.js.map +1 -0
- package/dist/review/repo.js +194 -0
- package/dist/review/repo.js.map +1 -0
- package/dist/review/report-plan.js +90 -0
- package/dist/review/report-plan.js.map +1 -0
- package/dist/review/routes.js +195 -0
- package/dist/review/routes.js.map +1 -0
- package/dist/review/run-summary.js +34 -0
- package/dist/review/run-summary.js.map +1 -0
- package/dist/review/run.js +245 -0
- package/dist/review/run.js.map +1 -0
- package/dist/review/scope.js +454 -0
- package/dist/review/scope.js.map +1 -0
- package/dist/review/security.js +432 -0
- package/dist/review/security.js.map +1 -0
- package/dist/review/signals.js +550 -0
- package/dist/review/signals.js.map +1 -0
- package/dist/review/specs.js +150 -0
- package/dist/review/specs.js.map +1 -0
- package/dist/review/ste.js +133 -0
- package/dist/review/ste.js.map +1 -0
- package/dist/review/test-repo-file.js +18 -0
- package/dist/review/test-repo-file.js.map +1 -0
- package/dist/review/test-repo-lines.js +53 -0
- package/dist/review/test-repo-lines.js.map +1 -0
- package/dist/review/ticket-on-demand.js +232 -0
- package/dist/review/ticket-on-demand.js.map +1 -0
- package/dist/review/yaml.js +298 -0
- package/dist/review/yaml.js.map +1 -0
- package/dist/room.js +361 -0
- package/dist/room.js.map +1 -0
- package/dist/routes/activity.js +219 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/call.js +29 -0
- package/dist/routes/call.js.map +1 -0
- package/dist/routes/cards.js +40 -0
- package/dist/routes/cards.js.map +1 -0
- package/dist/routes/cases.js +133 -0
- package/dist/routes/cases.js.map +1 -0
- package/dist/routes/connect.js +268 -0
- package/dist/routes/connect.js.map +1 -0
- package/dist/routes/connection-presets.js +32 -0
- package/dist/routes/connection-presets.js.map +1 -0
- package/dist/routes/connections.js +177 -0
- package/dist/routes/connections.js.map +1 -0
- package/dist/routes/disk.js +19 -0
- package/dist/routes/disk.js.map +1 -0
- package/dist/routes/docs.js +71 -0
- package/dist/routes/docs.js.map +1 -0
- package/dist/routes/dot-suggest.js +1002 -0
- package/dist/routes/dot-suggest.js.map +1 -0
- package/dist/routes/evidence-pack.js +16 -0
- package/dist/routes/evidence-pack.js.map +1 -0
- package/dist/routes/health.js +121 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/impact.js +48 -0
- package/dist/routes/impact.js.map +1 -0
- package/dist/routes/lead.js +50 -0
- package/dist/routes/lead.js.map +1 -0
- package/dist/routes/links.js +13 -0
- package/dist/routes/links.js.map +1 -0
- package/dist/routes/markdown.js +62 -0
- package/dist/routes/markdown.js.map +1 -0
- package/dist/routes/onboarding.js +47 -0
- package/dist/routes/onboarding.js.map +1 -0
- package/dist/routes/phone.js +231 -0
- package/dist/routes/phone.js.map +1 -0
- package/dist/routes/release-notes.js +30 -0
- package/dist/routes/release-notes.js.map +1 -0
- package/dist/routes/reports.js +102 -0
- package/dist/routes/reports.js.map +1 -0
- package/dist/routes/repos.js +91 -0
- package/dist/routes/repos.js.map +1 -0
- package/dist/routes/review.js +283 -0
- package/dist/routes/review.js.map +1 -0
- package/dist/routes/roles.js +114 -0
- package/dist/routes/roles.js.map +1 -0
- package/dist/routes/room.js +21 -0
- package/dist/routes/room.js.map +1 -0
- package/dist/routes/runner.js +156 -0
- package/dist/routes/runner.js.map +1 -0
- package/dist/routes/runs.js +84 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/routes/setup.js +18 -0
- package/dist/routes/setup.js.map +1 -0
- package/dist/routes/test-runs.js +220 -0
- package/dist/routes/test-runs.js.map +1 -0
- package/dist/routes/ticket-status.js +17 -0
- package/dist/routes/ticket-status.js.map +1 -0
- package/dist/routes/traceability.js +143 -0
- package/dist/routes/traceability.js.map +1 -0
- package/dist/routes/true.js +142 -0
- package/dist/routes/true.js.map +1 -0
- package/dist/routes/updates.js +70 -0
- package/dist/routes/updates.js.map +1 -0
- package/dist/runner/adapters/index.js +12 -0
- package/dist/runner/adapters/index.js.map +1 -0
- package/dist/runner/adapters/playwright.js +68 -0
- package/dist/runner/adapters/playwright.js.map +1 -0
- package/dist/runner/aivision/cases.js +172 -0
- package/dist/runner/aivision/cases.js.map +1 -0
- package/dist/runner/aivision/cli.js +201 -0
- package/dist/runner/aivision/cli.js.map +1 -0
- package/dist/runner/aivision/index.js +281 -0
- package/dist/runner/aivision/index.js.map +1 -0
- package/dist/runner/aivision/server.js +394 -0
- package/dist/runner/aivision/server.js.map +1 -0
- package/dist/runner/aivision/shared.js +140 -0
- package/dist/runner/aivision/shared.js.map +1 -0
- package/dist/runner/artifact-cap.js +189 -0
- package/dist/runner/artifact-cap.js.map +1 -0
- package/dist/runner/artifacts.js +433 -0
- package/dist/runner/artifacts.js.map +1 -0
- package/dist/runner/command.js +564 -0
- package/dist/runner/command.js.map +1 -0
- package/dist/runner/copyfiles.js +221 -0
- package/dist/runner/copyfiles.js.map +1 -0
- package/dist/runner/engines.js +32 -0
- package/dist/runner/engines.js.map +1 -0
- package/dist/runner/evidence.js +114 -0
- package/dist/runner/evidence.js.map +1 -0
- package/dist/runner/host-env.js +160 -0
- package/dist/runner/host-env.js.map +1 -0
- package/dist/runner/index.js +1221 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/observe.js +603 -0
- package/dist/runner/observe.js.map +1 -0
- package/dist/runner/playwright-json.js +108 -0
- package/dist/runner/playwright-json.js.map +1 -0
- package/dist/runner/pwgen/exec.js +192 -0
- package/dist/runner/pwgen/exec.js.map +1 -0
- package/dist/runner/pwgen/explore.js +111 -0
- package/dist/runner/pwgen/explore.js.map +1 -0
- package/dist/runner/pwgen/index.js +423 -0
- package/dist/runner/pwgen/index.js.map +1 -0
- package/dist/runner/pwgen/propose.js +69 -0
- package/dist/runner/pwgen/propose.js.map +1 -0
- package/dist/runner/pwgen/source.js +632 -0
- package/dist/runner/pwgen/source.js.map +1 -0
- package/dist/runner/setup.js +222 -0
- package/dist/runner/setup.js.map +1 -0
- package/dist/runner/step-reporter.js +107 -0
- package/dist/runner/step-reporter.js.map +1 -0
- package/dist/runner/test-repo.js +326 -0
- package/dist/runner/test-repo.js.map +1 -0
- package/dist/runner/typed-value.js +46 -0
- package/dist/runner/typed-value.js.map +1 -0
- package/dist/runner/verify.js +133 -0
- package/dist/runner/verify.js.map +1 -0
- package/dist/runner/worktree.js +349 -0
- package/dist/runner/worktree.js.map +1 -0
- package/dist/sandbox.js +61 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.js +262 -0
- package/dist/server.js.map +1 -0
- package/dist/shadow-week.js +126 -0
- package/dist/shadow-week.js.map +1 -0
- package/dist/shutdown.js +92 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/slack/index.js +645 -0
- package/dist/slack/index.js.map +1 -0
- package/dist/stages/config.js +147 -0
- package/dist/stages/config.js.map +1 -0
- package/dist/stages/index.js +41 -0
- package/dist/stages/index.js.map +1 -0
- package/dist/suites.js +293 -0
- package/dist/suites.js.map +1 -0
- package/dist/target-url.js +116 -0
- package/dist/target-url.js.map +1 -0
- package/dist/test-runs.js +662 -0
- package/dist/test-runs.js.map +1 -0
- package/dist/ticket-keys.js +97 -0
- package/dist/ticket-keys.js.map +1 -0
- package/dist/ticket-supersede.js +105 -0
- package/dist/ticket-supersede.js.map +1 -0
- package/dist/tinybee/ed25519.js +99 -0
- package/dist/tinybee/ed25519.js.map +1 -0
- package/dist/tinybee/models-routes.js +19 -0
- package/dist/tinybee/models-routes.js.map +1 -0
- package/dist/tinybee/pair-payload.js +41 -0
- package/dist/tinybee/pair-payload.js.map +1 -0
- package/dist/tinybee/update-manifest.js +77 -0
- package/dist/tinybee/update-manifest.js.map +1 -0
- package/dist/tinybee/well-known.js +64 -0
- package/dist/tinybee/well-known.js.map +1 -0
- package/dist/tinybee/workflows/activity.js +23 -0
- package/dist/tinybee/workflows/activity.js.map +1 -0
- package/dist/tinybee/workflows/cron.js +210 -0
- package/dist/tinybee/workflows/cron.js.map +1 -0
- package/dist/tinybee/workflows/engine.js +371 -0
- package/dist/tinybee/workflows/engine.js.map +1 -0
- package/dist/tinybee/workflows/from-text.js +203 -0
- package/dist/tinybee/workflows/from-text.js.map +1 -0
- package/dist/tinybee/workflows/routes.js +189 -0
- package/dist/tinybee/workflows/routes.js.map +1 -0
- package/dist/tinybee/workflows/scheduler.js +100 -0
- package/dist/tinybee/workflows/scheduler.js.map +1 -0
- package/dist/tinybee/workflows/skills.js +227 -0
- package/dist/tinybee/workflows/skills.js.map +1 -0
- package/dist/tinybee/workflows/store.js +205 -0
- package/dist/tinybee/workflows/store.js.map +1 -0
- package/dist/tinybee/workflows/types.js +180 -0
- package/dist/tinybee/workflows/types.js.map +1 -0
- package/dist/tinybee/workflows/yaml.js +323 -0
- package/dist/tinybee/workflows/yaml.js.map +1 -0
- package/dist/true/api.js +495 -0
- package/dist/true/api.js.map +1 -0
- package/dist/true/client.js +292 -0
- package/dist/true/client.js.map +1 -0
- package/dist/true/clock.js +36 -0
- package/dist/true/clock.js.map +1 -0
- package/dist/true/events.js +125 -0
- package/dist/true/events.js.map +1 -0
- package/dist/true/hosts.js +98 -0
- package/dist/true/hosts.js.map +1 -0
- package/dist/true/index.js +29 -0
- package/dist/true/index.js.map +1 -0
- package/dist/true/key.js +54 -0
- package/dist/true/key.js.map +1 -0
- package/dist/true/line.js +69 -0
- package/dist/true/line.js.map +1 -0
- package/dist/true/mask.js +31 -0
- package/dist/true/mask.js.map +1 -0
- package/dist/true/names.js +114 -0
- package/dist/true/names.js.map +1 -0
- package/dist/true/outbox.js +233 -0
- package/dist/true/outbox.js.map +1 -0
- package/dist/true/replay.js +164 -0
- package/dist/true/replay.js.map +1 -0
- package/dist/true/settings.js +123 -0
- package/dist/true/settings.js.map +1 -0
- package/dist/true/status.js +189 -0
- package/dist/true/status.js.map +1 -0
- package/dist/true/sync-cases.js +222 -0
- package/dist/true/sync-cases.js.map +1 -0
- package/dist/true/sync-manual.js +295 -0
- package/dist/true/sync-manual.js.map +1 -0
- package/dist/true/sync-runs.js +109 -0
- package/dist/true/sync-runs.js.map +1 -0
- package/dist/true/worker.js +414 -0
- package/dist/true/worker.js.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/dist/updates/asks.js +38 -0
- package/dist/updates/asks.js.map +1 -0
- package/dist/updates/index.js +835 -0
- package/dist/updates/index.js.map +1 -0
- package/dist/updates/owner.js +24 -0
- package/dist/updates/owner.js.map +1 -0
- package/dist/updates/prefs.js +118 -0
- package/dist/updates/prefs.js.map +1 -0
- package/dist/updates/route.js +78 -0
- package/dist/updates/route.js.map +1 -0
- package/dist/updates/sources.js +345 -0
- package/dist/updates/sources.js.map +1 -0
- package/dist/updates/words.js +452 -0
- package/dist/updates/words.js.map +1 -0
- package/dist/version.js +53 -0
- package/dist/version.js.map +1 -0
- package/dist/view-compute.js +382 -0
- package/dist/view-compute.js.map +1 -0
- package/dist/view-spec.js +894 -0
- package/dist/view-spec.js.map +1 -0
- package/dist/web/apple-touch-icon.png +0 -0
- package/dist/web/assets/ApprovalCard-Br_z5z7G.css +1 -0
- package/dist/web/assets/ApprovalCard-CfGhGFo_.js +3 -0
- package/dist/web/assets/CardFromRef-BaTGmZ9c.js +2 -0
- package/dist/web/assets/CardFromRef-DO7i2uDd.css +1 -0
- package/dist/web/assets/Cases-8l_6UcLh.js +2 -0
- package/dist/web/assets/Cases-CpfED0uB.css +1 -0
- package/dist/web/assets/Chat-BKDiR0qt.js +3 -0
- package/dist/web/assets/Chat-DxjdyYUu.css +1 -0
- package/dist/web/assets/ConfirmDialog-CIMveD-b.js +2 -0
- package/dist/web/assets/ConnectSheet-Cm5vbZdR.js +4 -0
- package/dist/web/assets/Docs-HKGuY0WE.js +2 -0
- package/dist/web/assets/Docs-fodKx8S7.css +1 -0
- package/dist/web/assets/DotDetail-DskS3NWe.js +2 -0
- package/dist/web/assets/DotDetail-OWRSD_1x.css +1 -0
- package/dist/web/assets/DotStage-BZDclfzV.css +1 -0
- package/dist/web/assets/DotStage-CtMNzCN3.js +2 -0
- package/dist/web/assets/Dots-BqCsS34m.js +2 -0
- package/dist/web/assets/EvidencePack-DQ3kCJX4.js +2 -0
- package/dist/web/assets/EvidencePack-DV_9ETsA.css +1 -0
- package/dist/web/assets/FailedDeliveries-1F2kFcs9.js +2 -0
- package/dist/web/assets/FailedDeliveries-DXa2_VvI.css +1 -0
- package/dist/web/assets/Feed-5wiHRTFK.js +2 -0
- package/dist/web/assets/GfmView-C-NYaduC.js +4 -0
- package/dist/web/assets/ImpactList-C-RNuDB0.js +2 -0
- package/dist/web/assets/ImpactList-C612dFdw.css +1 -0
- package/dist/web/assets/Inbox-kc1bKVL_.js +2 -0
- package/dist/web/assets/JoinScreen-C3L4wmP3.js +2 -0
- package/dist/web/assets/JoinScreen-COeAUv5v.css +1 -0
- package/dist/web/assets/LeadDialog-N3Zul9Rw.js +8 -0
- package/dist/web/assets/LeadDialog-xyWjAuAS.css +1 -0
- package/dist/web/assets/ListeningLine-BRFNaczY.js +2 -0
- package/dist/web/assets/ListeningLine-pN8CgyiK.css +1 -0
- package/dist/web/assets/Mascots-pIyGpxtD.js +2 -0
- package/dist/web/assets/ModelChoices-BxO1zyyr.js +2 -0
- package/dist/web/assets/ModelChoices-DQJnVxfs.css +1 -0
- package/dist/web/assets/NewDotDialog-CDPUWmgN.js +2 -0
- package/dist/web/assets/NewDotDialog-DrPPqkSZ.css +1 -0
- package/dist/web/assets/NewTestRunDialog-BQBthVHE.js +2 -0
- package/dist/web/assets/NoBreakNames-Csxdqdt6.js +2 -0
- package/dist/web/assets/Pair-omex_K7H.js +2 -0
- package/dist/web/assets/PushSection-CmqHlE_2.js +2 -0
- package/dist/web/assets/ReleaseNotes-B6VqFewP.js +2 -0
- package/dist/web/assets/ReleaseNotes-DBJUL7Vm.css +1 -0
- package/dist/web/assets/ReportPage-BHS1xWEt.js +162 -0
- package/dist/web/assets/Reports-BEHnDIb1.js +2 -0
- package/dist/web/assets/ReviewChangeDialog-BVSt-cw-.js +2 -0
- package/dist/web/assets/ReviewChangeDialog-BbIlHRx0.css +1 -0
- package/dist/web/assets/Room-BoG_uge4.js +2 -0
- package/dist/web/assets/Room-evAfiW_e.css +1 -0
- package/dist/web/assets/RunActions-ZY7yf1AF.js +2 -0
- package/dist/web/assets/RunDetail-C8St20GQ.css +1 -0
- package/dist/web/assets/RunDetail-qADXjBvd.js +9 -0
- package/dist/web/assets/RunRow-BKEJv8ib.js +2 -0
- package/dist/web/assets/RunnerTry-Dgpp67-s.js +6 -0
- package/dist/web/assets/RunnerTry-DsweWOfO.css +1 -0
- package/dist/web/assets/Settings-fs-QJwNM.js +2 -0
- package/dist/web/assets/Setup-DI6hBEP-.js +2 -0
- package/dist/web/assets/TestRows-wh03T5Li.js +4 -0
- package/dist/web/assets/TestRun-DTOyF-Pv.js +2 -0
- package/dist/web/assets/TestRuns-ggDjm1Q8.js +2 -0
- package/dist/web/assets/TinyBeeAddLaptop-bc3pmh3T.js +2 -0
- package/dist/web/assets/TinyBeeAi-CkyOzhm5.js +2 -0
- package/dist/web/assets/TinyBeeConnections-B2K_P38u.js +2 -0
- package/dist/web/assets/TinyBeeHome-DSpxX5KS.js +3 -0
- package/dist/web/assets/TinyBeePlan-BamiLziu.js +2 -0
- package/dist/web/assets/TinyBeeSignup-vHcz0Wen.js +2 -0
- package/dist/web/assets/TinyBeeSkills-By9RLUse.js +2 -0
- package/dist/web/assets/TinyBeeWorkflow-DeNO7Jsh.js +2 -0
- package/dist/web/assets/TinyBeeWorkflowEditor-B6OGC2OT.js +2 -0
- package/dist/web/assets/TinyBeeWorkflows-BN4-h6lt.js +2 -0
- package/dist/web/assets/Trace-BBCI1aIB.css +1 -0
- package/dist/web/assets/Trace-aF92UWaH.js +2 -0
- package/dist/web/assets/UpdatesSection-CCWEbkue.js +2 -0
- package/dist/web/assets/Welcome-CCcy558Q.js +2 -0
- package/dist/web/assets/activity-C3qilrDm.css +1 -0
- package/dist/web/assets/activity-CBfTSxqw.js +2 -0
- package/dist/web/assets/authedMedia-BTYt_tyu.js +2 -0
- package/dist/web/assets/beeApi-BHW8Tx1s.js +2 -0
- package/dist/web/assets/data-CmXvx3Mj.js +2 -0
- package/dist/web/assets/engines-CfdJODFj.css +1 -0
- package/dist/web/assets/format-BBZ8vFyT.js +2 -0
- package/dist/web/assets/forms-Coc7p2UF.css +1 -0
- package/dist/web/assets/hivePush-DZJDokj7.js +2 -0
- package/dist/web/assets/impactModel-MY1OFuiP.js +2 -0
- package/dist/web/assets/index-B6qKm1NW.js +13 -0
- package/dist/web/assets/index-BvKyT1X7.css +1 -0
- package/dist/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/web/assets/lead-BL_P_kri.css +1 -0
- package/dist/web/assets/model-BIQy5IVG.js +2 -0
- package/dist/web/assets/modelsApi-PUSySRQw.js +2 -0
- package/dist/web/assets/newDotModel-BaLLyw57.js +2 -0
- package/dist/web/assets/onboarding-bfKqnM4Z.css +1 -0
- package/dist/web/assets/phone-Rs7FoyG0.css +1 -0
- package/dist/web/assets/phoneApi-BG_1-M-D.js +3 -0
- package/dist/web/assets/releaseModel-EynYMVOC.js +2 -0
- package/dist/web/assets/releaseNotesModel-A1Rtv3cV.js +2 -0
- package/dist/web/assets/reports-BWaA1HhM.js +37 -0
- package/dist/web/assets/reports-DXwdWQsB.css +1 -0
- package/dist/web/assets/router-W6nZsQ33.js +2 -0
- package/dist/web/assets/runs-BY0Owv93.css +1 -0
- package/dist/web/assets/shadowWeekModel-BUUiww09.js +2 -0
- package/dist/web/assets/storage-yvL36AWt.js +2 -0
- package/dist/web/assets/store-IqrqHuFR.js +2 -0
- package/dist/web/assets/testruns-BzIZ0cR0.css +1 -0
- package/dist/web/assets/testruns-DyaqX4ji.js +2 -0
- package/dist/web/assets/true-9Q68cs5b.js +2 -0
- package/dist/web/assets/true-DPGBpoir.css +1 -0
- package/dist/web/assets/ui-DcmhYyYp.js +13 -0
- package/dist/web/assets/ui-DxEDgbIx.css +1 -0
- package/dist/web/assets/usePauseDot-BV60ZVy1.js +2 -0
- package/dist/web/assets/usePauseDot-NrSzMI1C.css +1 -0
- package/dist/web/assets/usePush-Dsm-TjlG.js +2 -0
- package/dist/web/assets/useRefChips-CbafNx59.js +68 -0
- package/dist/web/assets/useRestoreDot-D0B6W82H.js +2 -0
- package/dist/web/assets/view-worker-pyeVAhUT.js +2 -0
- package/dist/web/assets/workflowUi-QYsd3n9J.js +2 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/icon-192.png +0 -0
- package/dist/web/icon-512.png +0 -0
- package/dist/web/icon-maskable-512.png +0 -0
- package/dist/web/index.html +45 -0
- package/dist/web/manifest.webmanifest +23 -0
- package/dist/web/mascots/argus-attention.svg +7 -0
- package/dist/web/mascots/argus-ok.svg +7 -0
- package/dist/web/mascots/argus-outage.svg +7 -0
- package/dist/web/mascots/argus-running.svg +7 -0
- package/dist/web/mascots/bolt-attention.svg +7 -0
- package/dist/web/mascots/bolt-ok.svg +7 -0
- package/dist/web/mascots/bolt-outage.svg +7 -0
- package/dist/web/mascots/bolt-running.svg +7 -0
- package/dist/web/mascots/echo-attention.svg +7 -0
- package/dist/web/mascots/echo-ok.svg +7 -0
- package/dist/web/mascots/echo-outage.svg +7 -0
- package/dist/web/mascots/echo-running.svg +7 -0
- package/dist/web/mascots/lens-attention.svg +7 -0
- package/dist/web/mascots/lens-ok.svg +7 -0
- package/dist/web/mascots/lens-outage.svg +7 -0
- package/dist/web/mascots/lens-running.svg +7 -0
- package/dist/web/mascots/moss-attention.svg +7 -0
- package/dist/web/mascots/moss-ok.svg +7 -0
- package/dist/web/mascots/moss-outage.svg +7 -0
- package/dist/web/mascots/moss-running.svg +7 -0
- package/dist/web/mascots/nit-attention.svg +7 -0
- package/dist/web/mascots/nit-ok.svg +7 -0
- package/dist/web/mascots/nit-outage.svg +7 -0
- package/dist/web/mascots/nit-running.svg +7 -0
- package/dist/web/mascots/nova-attention.svg +7 -0
- package/dist/web/mascots/nova-ok.svg +7 -0
- package/dist/web/mascots/nova-outage.svg +7 -0
- package/dist/web/mascots/nova-running.svg +7 -0
- package/dist/web/mascots/penn-attention.svg +7 -0
- package/dist/web/mascots/penn-ok.svg +7 -0
- package/dist/web/mascots/penn-outage.svg +7 -0
- package/dist/web/mascots/penn-running.svg +7 -0
- package/dist/web/mascots/pip-attention.svg +7 -0
- package/dist/web/mascots/pip-ok.svg +7 -0
- package/dist/web/mascots/pip-outage.svg +7 -0
- package/dist/web/mascots/pip-running.svg +7 -0
- package/dist/web/mascots/ward-attention.svg +7 -0
- package/dist/web/mascots/ward-ok.svg +7 -0
- package/dist/web/mascots/ward-outage.svg +7 -0
- package/dist/web/mascots/ward-running.svg +7 -0
- package/dist/web/sw.js +98 -0
- package/dist/webhook-seen.js +53 -0
- package/dist/webhook-seen.js.map +1 -0
- package/dist/webhooks.js +625 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/zip.js +63 -0
- package/dist/zip.js.map +1 -0
- package/docs/API-V2.md +532 -0
- package/docs/CHAT-EVAL.md +130 -0
- package/docs/CHAT-UI.md +416 -0
- package/docs/CONNECTIONS.md +89 -0
- package/docs/DATA-MODEL.md +518 -0
- package/docs/DEPLOY.md +577 -0
- package/docs/DOGFOOD-LEDGER.md +81 -0
- package/docs/GITHUB.md +148 -0
- package/docs/INTEGRATION-MODEL.md +200 -0
- package/docs/LEAD-DOT.md +553 -0
- package/docs/LIST-PATTERNS.md +52 -0
- package/docs/MULTI-REPO.md +766 -0
- package/docs/PARITY.md +276 -0
- package/docs/PR-REVIEW-QA.md +1266 -0
- package/docs/PR-REVIEW.md +357 -0
- package/docs/SANDBOX.md +320 -0
- package/docs/SETUP.md +776 -0
- package/docs/SLACK.md +80 -0
- package/docs/STAGES.md +619 -0
- package/docs/TRACE-MAP.md +89 -0
- package/docs/TRACKERS.md +225 -0
- package/docs/VOICE.md +36 -0
- package/docs/tinybee/00-README.md +45 -0
- package/docs/tinybee/01-PRD.md +216 -0
- package/docs/tinybee/02-architecture-pairing.md +199 -0
- package/docs/tinybee/03-local-agent.md +222 -0
- package/docs/tinybee/04-local-setup-ui.md +128 -0
- package/docs/tinybee/05-mobile-app-ux.md +199 -0
- package/docs/tinybee/06-environments-and-delivery.md +148 -0
- package/docs/tinybee/07-coding-agent-handoff.md +116 -0
- package/docs/tinybee/OPEN-QUESTIONS.md +26 -0
- package/docs/tinybee/PROGRESS.md +134 -0
- package/package.json +111 -4
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
// `localdost init`: detects the repo in the current folder, writes .env.localdost (references and
|
|
2
|
+
// non-secret config only) and .localdost/config.json, and creates the first dot.
|
|
3
|
+
//
|
|
4
|
+
// Also exports the env-file loader and the service probes that `localdost doctor` and `localdost start` use.
|
|
5
|
+
import { execFile } from 'node:child_process';
|
|
6
|
+
import { createServer } from 'node:net';
|
|
7
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { createInterface } from 'node:readline/promises';
|
|
11
|
+
import { parseArgs } from 'node:util';
|
|
12
|
+
import { reviewChildEnv } from '../review/backend-cli.js';
|
|
13
|
+
import { ENV_FILE, envFilePath, invokedDir, parseEnvFile } from './env-file.js';
|
|
14
|
+
import { dotDir } from '../legacy-names.js';
|
|
15
|
+
// The env file name, the invoked folder, and the file parser live in env-file.ts, which imports nothing from localdost. They stay exported here for the importers that already use them.
|
|
16
|
+
export { ENV_FILE, envFilePath, invokedDir, parseEnvFile };
|
|
17
|
+
export const CONFIG_FILE = path.join('.localdost', 'config.json');
|
|
18
|
+
/** .localdost/config.json in `dir`, or the .qadots/ copy an older init wrote when only that exists. */
|
|
19
|
+
export function configFilePath(dir) {
|
|
20
|
+
return path.join(dotDir(dir), 'config.json');
|
|
21
|
+
}
|
|
22
|
+
/** The default data folder of `dir`: .localdost/data, or .qadots/data when only that folder exists. */
|
|
23
|
+
export function defaultDataDir(dir) {
|
|
24
|
+
return path.join(dotDir(dir), 'data');
|
|
25
|
+
}
|
|
26
|
+
export const DEFAULT_PORT = 4319;
|
|
27
|
+
const PW_CONFIGS = ['playwright.config.ts', 'playwright.config.mts', 'playwright.config.js', 'playwright.config.mjs', 'playwright.config.cjs'];
|
|
28
|
+
/** Binaries a `${cmd:...}` reference may run. Each prints a secret to stdout and needs no shell. */
|
|
29
|
+
const REF_COMMANDS = new Set(['gh', 'op', 'security', 'pass']);
|
|
30
|
+
/**
|
|
31
|
+
* The read-only subcommand each reference binary may run. `gh api -X DELETE ...` or `op item delete`
|
|
32
|
+
* in a .env.localdost would otherwise act with the person's credentials when they run start or doctor.
|
|
33
|
+
*/
|
|
34
|
+
const REF_SUBCOMMANDS = {
|
|
35
|
+
gh: (a) => a[0] === 'auth' && a[1] === 'token',
|
|
36
|
+
op: (a) => a[0] === 'read',
|
|
37
|
+
security: (a) => a[0] === 'find-generic-password' || a[0] === 'find-internet-password',
|
|
38
|
+
pass: (a) => a[0] === 'show' || (a.length === 1 && !a[0].startsWith('-')),
|
|
39
|
+
};
|
|
40
|
+
/** True when a `${cmd:...}` reference names an allowed binary and its read-only subcommand. */
|
|
41
|
+
export function refCommandAllowed(bin, args) {
|
|
42
|
+
return REF_COMMANDS.has(bin) && (REF_SUBCOMMANDS[bin]?.(args) ?? false);
|
|
43
|
+
}
|
|
44
|
+
/** Runs a binary without a shell. Never throws. */
|
|
45
|
+
export function sh(cmd, args, opts = {}) {
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
const child = execFile(cmd, args, { cwd: opts.cwd, timeout: opts.timeoutMs ?? 15_000, env: opts.env ?? process.env, maxBuffer: 4 * 1024 * 1024, encoding: 'utf8' }, (err, stdout, stderr) => {
|
|
48
|
+
const code = err ? (typeof err.code === 'number' ? err.code : null) : 0;
|
|
49
|
+
resolve({ ok: !err, code, stdout: String(stdout ?? ''), stderr: String(stderr ?? '') });
|
|
50
|
+
});
|
|
51
|
+
if (opts.input !== undefined)
|
|
52
|
+
child.stdin?.end(opts.input);
|
|
53
|
+
else
|
|
54
|
+
child.stdin?.end();
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async function resolveRef(ref, env) {
|
|
58
|
+
const envRef = /^\$\{env:([A-Za-z_][A-Za-z0-9_]*)\}$/.exec(ref);
|
|
59
|
+
if (envRef) {
|
|
60
|
+
const v = env[envRef[1]]?.trim();
|
|
61
|
+
return v ? { value: v, source: 'env-ref' } : { source: 'unresolved', error: `${envRef[1]} is not exported in this shell` };
|
|
62
|
+
}
|
|
63
|
+
const cmdRef = /^\$\{cmd:(.+)\}$/.exec(ref);
|
|
64
|
+
if (cmdRef) {
|
|
65
|
+
const [bin, ...args] = cmdRef[1].trim().split(/\s+/);
|
|
66
|
+
if (!REF_COMMANDS.has(bin))
|
|
67
|
+
return { source: 'unresolved', error: `"${bin}" is not an allowed reference command (${[...REF_COMMANDS].join(', ')})` };
|
|
68
|
+
if (!refCommandAllowed(bin, args))
|
|
69
|
+
return {
|
|
70
|
+
source: 'unresolved',
|
|
71
|
+
error: `\`${cmdRef[1].trim()}\` is not a read-only reference (gh auth token, op read, security find-generic-password, pass show)`,
|
|
72
|
+
};
|
|
73
|
+
const r = await sh(bin, args, { timeoutMs: 15_000 });
|
|
74
|
+
const v = r.stdout.trim();
|
|
75
|
+
return r.ok && v ? { value: v, source: 'cmd-ref' } : { source: 'unresolved', error: `\`${cmdRef[1].trim()}\` failed` };
|
|
76
|
+
}
|
|
77
|
+
return { value: ref, source: 'literal' };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Reads .env.localdost in `dir` and resolves `${env:NAME}` and `${cmd:...}` references.
|
|
81
|
+
* A variable already set in the shell wins over the file. Relative LOCALDOST_DATA_DIR resolves against `dir`.
|
|
82
|
+
*/
|
|
83
|
+
export async function loadLocaldostEnv(dir, env = process.env) {
|
|
84
|
+
const file = envFilePath(dir);
|
|
85
|
+
if (!existsSync(file))
|
|
86
|
+
return { vars: {}, refs: [] };
|
|
87
|
+
const parsed = parseEnvFile(readFileSync(file, 'utf8'));
|
|
88
|
+
const vars = {};
|
|
89
|
+
const refs = [];
|
|
90
|
+
for (const [key, ref] of Object.entries(parsed)) {
|
|
91
|
+
if (env[key]?.trim()) {
|
|
92
|
+
refs.push({ key, ref, resolved: true, source: 'shell' });
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (ref === '')
|
|
96
|
+
continue;
|
|
97
|
+
const r = await resolveRef(ref, env);
|
|
98
|
+
if (r.value !== undefined) {
|
|
99
|
+
vars[key] = key === 'LOCALDOST_DATA_DIR' && !path.isAbsolute(r.value) ? path.resolve(dir, r.value) : r.value;
|
|
100
|
+
refs.push({ key, ref, resolved: true, source: r.source });
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
refs.push({ key, ref, resolved: false, source: 'unresolved', error: r.error });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { file, vars, refs };
|
|
107
|
+
}
|
|
108
|
+
/** Loads .env.localdost into process.env without overriding the shell. */
|
|
109
|
+
export async function applyLocaldostEnv(dir) {
|
|
110
|
+
const loaded = await loadLocaldostEnv(dir);
|
|
111
|
+
for (const [k, v] of Object.entries(loaded.vars))
|
|
112
|
+
if (!process.env[k]?.trim())
|
|
113
|
+
process.env[k] = v;
|
|
114
|
+
return loaded;
|
|
115
|
+
}
|
|
116
|
+
export function readLocaldostConfig(dir) {
|
|
117
|
+
const file = configFilePath(dir);
|
|
118
|
+
if (!existsSync(file))
|
|
119
|
+
return undefined;
|
|
120
|
+
try {
|
|
121
|
+
return JSON.parse(readFileSync(file, 'utf8'));
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// ---------- detection ----------
|
|
128
|
+
export function parseGithubRemote(url) {
|
|
129
|
+
const m = /github\.com[:/]+([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/.exec(url.trim());
|
|
130
|
+
return m ? { owner: m[1], name: m[2] } : undefined;
|
|
131
|
+
}
|
|
132
|
+
export async function detectRepo(dir) {
|
|
133
|
+
const remote = await sh('git', ['remote', 'get-url', 'origin'], { cwd: dir });
|
|
134
|
+
const parsed = remote.ok ? parseGithubRemote(remote.stdout) : undefined;
|
|
135
|
+
if (!parsed)
|
|
136
|
+
return undefined;
|
|
137
|
+
return { ...parsed, defaultBranch: await detectDefaultBranch(dir) };
|
|
138
|
+
}
|
|
139
|
+
async function detectDefaultBranch(dir) {
|
|
140
|
+
const head = await sh('git', ['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD'], { cwd: dir });
|
|
141
|
+
if (head.ok && head.stdout.trim())
|
|
142
|
+
return head.stdout.trim().replace(/^origin\//, '');
|
|
143
|
+
for (const b of ['main', 'master']) {
|
|
144
|
+
const r = await sh('git', ['rev-parse', '--verify', '--quiet', `refs/remotes/origin/${b}`], { cwd: dir });
|
|
145
|
+
if (r.ok)
|
|
146
|
+
return b;
|
|
147
|
+
}
|
|
148
|
+
const cur = await sh('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: dir });
|
|
149
|
+
const name = cur.stdout.trim();
|
|
150
|
+
return cur.ok && name && name !== 'HEAD' ? name : 'main';
|
|
151
|
+
}
|
|
152
|
+
/** Finds the Playwright config and the test command from package.json scripts. */
|
|
153
|
+
export function detectTests(dir) {
|
|
154
|
+
const playwrightConfig = PW_CONFIGS.find((f) => existsSync(path.join(dir, f)));
|
|
155
|
+
let scripts = {};
|
|
156
|
+
let deps = {};
|
|
157
|
+
try {
|
|
158
|
+
const pkg = JSON.parse(readFileSync(path.join(dir, 'package.json'), 'utf8'));
|
|
159
|
+
scripts = pkg.scripts ?? {};
|
|
160
|
+
deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
/* no package.json */
|
|
164
|
+
}
|
|
165
|
+
const hasPlaywright = !!deps['@playwright/test'] || !!deps.playwright || !!playwrightConfig;
|
|
166
|
+
let command = 'npx playwright test';
|
|
167
|
+
let note;
|
|
168
|
+
const order = ['test:e2e', 'e2e', 'test:playwright', 'playwright', 'test'];
|
|
169
|
+
const names = [...order.filter((n) => scripts[n]), ...Object.keys(scripts).filter((n) => !order.includes(n))];
|
|
170
|
+
const script = names.find((n) => /playwright\s+test/.test(scripts[n]));
|
|
171
|
+
if (script) {
|
|
172
|
+
const value = scripts[script].trim();
|
|
173
|
+
// The runner spawns the command without a shell, so chained scripts cannot run as-is.
|
|
174
|
+
if (/&&|\|\||[;|<>]/.test(value))
|
|
175
|
+
note = `script "${script}" chains commands; using \`npx playwright test\` instead`;
|
|
176
|
+
else
|
|
177
|
+
command = value.startsWith('npx ') ? value : `npx ${value}`;
|
|
178
|
+
}
|
|
179
|
+
else if (!hasPlaywright) {
|
|
180
|
+
note = 'no Playwright config or dependency found; add @playwright/test or pass --command';
|
|
181
|
+
}
|
|
182
|
+
let baseUrl;
|
|
183
|
+
if (playwrightConfig) {
|
|
184
|
+
const found = baseUrlFromConfig(readFileSync(path.join(dir, playwrightConfig), 'utf8'));
|
|
185
|
+
baseUrl = found.url;
|
|
186
|
+
if (found.note)
|
|
187
|
+
note = note ? `${note}; ${found.note}` : found.note;
|
|
188
|
+
}
|
|
189
|
+
return { command, playwrightConfig, baseUrl, hasPlaywright, note };
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The first http(s) URL in a Playwright config. A port written as `${PORT}` resolves from the
|
|
193
|
+
* constant's numeric default, so `const PORT = Number(process.env.PORT ?? 4400)` gives 4400. Before
|
|
194
|
+
* this, `http://localhost:${PORT}` came out as `http://localhost` with no port (KAT-78).
|
|
195
|
+
*/
|
|
196
|
+
export function baseUrlFromConfig(src) {
|
|
197
|
+
const m = /(https?:\/\/[A-Za-z0-9.-]+)(?::(\d+)|:\$\{\s*([A-Za-z_$][\w$]*)\s*\})?/.exec(src);
|
|
198
|
+
if (!m)
|
|
199
|
+
return {};
|
|
200
|
+
if (m[2])
|
|
201
|
+
return { url: `${m[1]}:${m[2]}` };
|
|
202
|
+
if (!m[3])
|
|
203
|
+
return { url: m[1] };
|
|
204
|
+
const name = m[3].replace(/\$/g, '\\$');
|
|
205
|
+
const decl = new RegExp(`(?:const|let|var)\\s+${name}\\s*=\\s*([^;\\n]+)`).exec(src);
|
|
206
|
+
const port = decl ? /(\d{2,5})\D*$/.exec(decl[1].trim())?.[1] : undefined;
|
|
207
|
+
if (port)
|
|
208
|
+
return { url: `${m[1]}:${port}` };
|
|
209
|
+
return { url: m[1], note: `the base URL port comes from \`${m[3]}\` in the Playwright config; pass --base-url` };
|
|
210
|
+
}
|
|
211
|
+
/** True when `gh auth token` prints a token. The token itself never leaves this function. */
|
|
212
|
+
export async function hasGhToken() {
|
|
213
|
+
const r = await sh('gh', ['auth', 'token'], { timeoutMs: 10_000 });
|
|
214
|
+
return r.ok && !!r.stdout.trim();
|
|
215
|
+
}
|
|
216
|
+
/** Checks the Claude CLI login, and with `roundTrip` that `claude -p` answers. */
|
|
217
|
+
export async function checkClaudeCli(env, roundTrip) {
|
|
218
|
+
const bin = env.LOCALDOST_CLAUDE_BIN?.trim() || 'claude';
|
|
219
|
+
const status = await sh(bin, ['auth', 'status', '--json'], { timeoutMs: 20_000 });
|
|
220
|
+
if (status.code === null && !status.stdout)
|
|
221
|
+
return { ok: false, detail: `"${bin}" is not installed or not on PATH` };
|
|
222
|
+
let loggedIn;
|
|
223
|
+
try {
|
|
224
|
+
loggedIn = !!JSON.parse(status.stdout).loggedIn;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
loggedIn = status.ok;
|
|
228
|
+
}
|
|
229
|
+
if (!loggedIn)
|
|
230
|
+
return { ok: false, detail: 'Claude CLI is not signed in' };
|
|
231
|
+
if (!roundTrip)
|
|
232
|
+
return { ok: true, detail: 'Claude CLI signed in' };
|
|
233
|
+
const cwd = mkdtempSync(path.join(os.tmpdir(), 'localdost-claude-check-'));
|
|
234
|
+
// Same allowlist as the server's Claude CLI children: unrelated host secrets stay out.
|
|
235
|
+
const cleanEnv = reviewChildEnv(env);
|
|
236
|
+
try {
|
|
237
|
+
const args = ['-p', '--output-format', 'json', '--model', env.LOCALDOST_CLAUDE_FAST_MODEL?.trim() || 'haiku'];
|
|
238
|
+
args.push('--tools', '', '--strict-mcp-config', '--setting-sources', '', '--no-session-persistence', '--max-turns', '1');
|
|
239
|
+
const r = await sh(bin, args, { cwd, timeoutMs: 90_000, input: 'Reply with the single word OK.', env: cleanEnv });
|
|
240
|
+
if (!r.ok)
|
|
241
|
+
return { ok: false, detail: `\`claude -p\` failed${r.code === null ? ' (timed out)' : ` (exit ${r.code})`}` };
|
|
242
|
+
let text = r.stdout;
|
|
243
|
+
try {
|
|
244
|
+
text = String(JSON.parse(r.stdout).result ?? '');
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
/* plain text */
|
|
248
|
+
}
|
|
249
|
+
return /ok/i.test(text) ? { ok: true, detail: '`claude -p` answered' } : { ok: false, detail: '`claude -p` gave an unexpected reply' };
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
rmSync(cwd, { recursive: true, force: true });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** Checks the Codex CLI login with `codex login status`. No model call, so no usage is spent. */
|
|
256
|
+
export async function checkCodexCli(env) {
|
|
257
|
+
const bin = env.LOCALDOST_CODEX_BIN?.trim() || 'codex';
|
|
258
|
+
const r = await sh(bin, ['login', 'status'], { timeoutMs: 20_000 });
|
|
259
|
+
if (r.code === null && !r.stdout)
|
|
260
|
+
return { ok: false, detail: `"${bin}" is not installed or not on PATH` };
|
|
261
|
+
const text = `${r.stdout}`.trim().split('\n')[0] ?? '';
|
|
262
|
+
if (!r.ok || /not logged in/i.test(text))
|
|
263
|
+
return { ok: false, detail: 'Codex CLI is not signed in' };
|
|
264
|
+
return { ok: true, detail: text || 'Codex CLI signed in' };
|
|
265
|
+
}
|
|
266
|
+
/** Team keys visible to LINEAR_API_KEY, or undefined when the call fails. */
|
|
267
|
+
export async function linearTeams(env) {
|
|
268
|
+
const key = env.LINEAR_API_KEY?.trim();
|
|
269
|
+
if (!key)
|
|
270
|
+
return undefined;
|
|
271
|
+
try {
|
|
272
|
+
const res = await fetch(env.LINEAR_API_URL?.trim() || 'https://api.linear.app/graphql', {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
headers: { 'content-type': 'application/json', authorization: key },
|
|
275
|
+
body: JSON.stringify({ query: '{ teams(first: 50) { nodes { key } } }' }),
|
|
276
|
+
signal: AbortSignal.timeout(10_000),
|
|
277
|
+
});
|
|
278
|
+
if (!res.ok)
|
|
279
|
+
return undefined;
|
|
280
|
+
const body = (await res.json());
|
|
281
|
+
return body.data?.teams?.nodes?.map((n) => n.key);
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** Jira project keys visible to JIRA_EMAIL and JIRA_API_TOKEN, or undefined when the call fails. */
|
|
288
|
+
export async function jiraProjects(env, baseUrl) {
|
|
289
|
+
const email = env.JIRA_EMAIL?.trim();
|
|
290
|
+
const token = env.JIRA_API_TOKEN?.trim();
|
|
291
|
+
if (!email || !token)
|
|
292
|
+
return undefined;
|
|
293
|
+
try {
|
|
294
|
+
const res = await fetch(`${baseUrl.replace(/\/+$/, '')}/rest/api/3/project/search?maxResults=50`, {
|
|
295
|
+
headers: { accept: 'application/json', authorization: `Basic ${Buffer.from(`${email}:${token}`).toString('base64')}` },
|
|
296
|
+
signal: AbortSignal.timeout(10_000),
|
|
297
|
+
});
|
|
298
|
+
if (!res.ok)
|
|
299
|
+
return undefined;
|
|
300
|
+
const body = (await res.json());
|
|
301
|
+
return body.values?.map((p) => p.key);
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/** True when nothing listens on the port on any interface. */
|
|
308
|
+
export function portFree(port) {
|
|
309
|
+
return new Promise((resolve) => {
|
|
310
|
+
const srv = createServer();
|
|
311
|
+
srv.once('error', () => resolve(false));
|
|
312
|
+
srv.listen({ port, host: '0.0.0.0', exclusive: true }, () => srv.close(() => resolve(true)));
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// ---------- GitHub Issues tracker ----------
|
|
316
|
+
const REPO_ID = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
317
|
+
/** Splits repeatable flag values and comma lists into trimmed, non-empty entries without repeats. */
|
|
318
|
+
function flagList(values, sep) {
|
|
319
|
+
const seen = new Set();
|
|
320
|
+
return (values ?? [])
|
|
321
|
+
.flatMap((v) => v.split(sep))
|
|
322
|
+
.map((v) => v.trim())
|
|
323
|
+
.filter((v) => v && !seen.has(v.toLowerCase()) && !!seen.add(v.toLowerCase()));
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The GitHub Issues tracker of `localdost init` from its flags: `--tracker-repos` (owner/name, repeatable or comma separated),
|
|
327
|
+
* `--require-labels` (an issue needs one of them to be reviewed) and `--milestone` (repeatable or comma separated).
|
|
328
|
+
* No repos means the repo of the folder. Returns the error to print for a repo that is not owner/name.
|
|
329
|
+
*/
|
|
330
|
+
export function githubTrackerFromFlags(f) {
|
|
331
|
+
const repos = flagList(f.repos, /[\s,]+/);
|
|
332
|
+
const bad = repos.find((r) => !REPO_ID.test(r));
|
|
333
|
+
if (bad)
|
|
334
|
+
return { ok: false, error: `--tracker-repos must be owner/name, got "${bad}"` };
|
|
335
|
+
const required = flagList(f.requireLabels, /,/);
|
|
336
|
+
if (required.length > 20 || required.some((l) => l.length > 50))
|
|
337
|
+
return { ok: false, error: '--require-labels takes up to 20 labels, each up to 50 characters' };
|
|
338
|
+
const milestones = flagList(f.milestones, /,/);
|
|
339
|
+
return {
|
|
340
|
+
ok: true,
|
|
341
|
+
tracker: {
|
|
342
|
+
kind: 'github',
|
|
343
|
+
...(repos.length ? { repos } : {}),
|
|
344
|
+
...(required.length ? { labels: { require: required } } : {}),
|
|
345
|
+
...(milestones.length ? { milestones } : {}),
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/** One line for the init summary: `acme/product, label pod:agentic, milestone 2026.11`. */
|
|
350
|
+
function githubTrackerLine(t, fallbackRepo) {
|
|
351
|
+
const repos = t.repos?.length ? t.repos.join(', ') : (fallbackRepo ?? 'this repo');
|
|
352
|
+
const parts = [repos];
|
|
353
|
+
if (t.labels?.require?.length)
|
|
354
|
+
parts.push(`label ${t.labels.require.join(' or ')}`);
|
|
355
|
+
if (t.milestones?.length)
|
|
356
|
+
parts.push(`milestone ${t.milestones.join(', ')}`);
|
|
357
|
+
return parts.join(', ');
|
|
358
|
+
}
|
|
359
|
+
export function renderEnvFile(p) {
|
|
360
|
+
const lines = [
|
|
361
|
+
`# localdost settings${p.slug ? ` for ${p.slug}` : ''}. Written by \`localdost init\`. Keep it out of git.`,
|
|
362
|
+
'# This file holds no secrets. ${env:NAME} reads NAME from your shell and ${cmd:...} runs one of',
|
|
363
|
+
`# ${[...REF_COMMANDS].join(', ')} at start. A variable already set in your shell wins over this file.`,
|
|
364
|
+
'',
|
|
365
|
+
`PORT=${p.port}`,
|
|
366
|
+
'# Local only. Export LOCALDOST_TOKEN in your shell before you change HOST to 0.0.0.0.',
|
|
367
|
+
'HOST=127.0.0.1',
|
|
368
|
+
'LOCALDOST_DATA_DIR=.localdost/data',
|
|
369
|
+
'# Polls GitHub and the tracker, so no public webhook URL is needed.',
|
|
370
|
+
'LOCALDOST_POLL=1',
|
|
371
|
+
'',
|
|
372
|
+
`LOCALDOST_LLM=${p.model}`,
|
|
373
|
+
];
|
|
374
|
+
if (p.model === 'anthropic')
|
|
375
|
+
lines.push('ANTHROPIC_API_KEY=${env:ANTHROPIC_API_KEY}');
|
|
376
|
+
lines.push('');
|
|
377
|
+
lines.push(p.github ? 'GITHUB_TOKEN=${cmd:gh auth token}' : '# GITHUB_TOKEN=${cmd:gh auth token} (run `gh auth login` first)');
|
|
378
|
+
if (p.tracker?.kind === 'linear')
|
|
379
|
+
lines.push('LINEAR_API_KEY=${env:LINEAR_API_KEY}');
|
|
380
|
+
if (p.tracker?.kind === 'jira') {
|
|
381
|
+
lines.push(`JIRA_BASE_URL=${p.tracker.baseUrl}`, 'JIRA_EMAIL=${env:JIRA_EMAIL}', 'JIRA_API_TOKEN=${env:JIRA_API_TOKEN}');
|
|
382
|
+
}
|
|
383
|
+
lines.push('', '# Public HTTPS URL for links and phone push, e.g. a cloudflared tunnel (docs/DEPLOY.md).', '# LOCALDOST_PUBLIC_URL=https://qa.example.com', '');
|
|
384
|
+
return lines.join('\n');
|
|
385
|
+
}
|
|
386
|
+
/** Adds entries to .gitignore when missing. Returns the entries it added. */
|
|
387
|
+
export function ensureGitignore(dir, entries) {
|
|
388
|
+
const file = path.join(dir, '.gitignore');
|
|
389
|
+
const text = existsSync(file) ? readFileSync(file, 'utf8') : '';
|
|
390
|
+
const have = new Set(text.split(/\r?\n/).map((l) => l.trim()));
|
|
391
|
+
const add = entries.filter((e) => !have.has(e));
|
|
392
|
+
if (add.length)
|
|
393
|
+
writeFileSync(file, `${text}${text && !text.endsWith('\n') ? '\n' : ''}# localdost\n${add.join('\n')}\n`);
|
|
394
|
+
return add;
|
|
395
|
+
}
|
|
396
|
+
// ---------- the dot ----------
|
|
397
|
+
function dotInput(cfg, hosted, absWorkdir) {
|
|
398
|
+
const slug = cfg.repo ? `${cfg.repo.owner}/${cfg.repo.name}` : cfg.name;
|
|
399
|
+
return {
|
|
400
|
+
name: cfg.name,
|
|
401
|
+
role: 'qa-lead',
|
|
402
|
+
mission: `Keep ${slug}${cfg.repo ? ` ${cfg.repo.defaultBranch}` : ''} green: the test suite passes after every merge and every PR.`,
|
|
403
|
+
notifyWhen: 'A merge or PR breaks a test, a new ticket carries risk, or the app is down.',
|
|
404
|
+
mustNot: 'Never merge, revert, or push. Never comment on a ticket without asking.',
|
|
405
|
+
...(cfg.repo ? { repo: cfg.repo } : {}),
|
|
406
|
+
...(cfg.tracker ? { tracker: cfg.tracker } : {}),
|
|
407
|
+
...(cfg.baseUrl ? { baseUrl: cfg.baseUrl } : {}),
|
|
408
|
+
// Hosted servers clone the repo per run; a local server runs in this checkout.
|
|
409
|
+
runner: hosted ? { mode: 'local', command: cfg.runner.command } : { mode: 'local', workdir: absWorkdir, command: cfg.runner.command },
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
async function upsertDotApi(server, input, knownId) {
|
|
413
|
+
const headers = { 'content-type': 'application/json' };
|
|
414
|
+
const token = process.env.LOCALDOST_TOKEN?.trim();
|
|
415
|
+
if (token)
|
|
416
|
+
headers.authorization = `Bearer ${token}`;
|
|
417
|
+
const base = server.replace(/\/+$/, '');
|
|
418
|
+
const listRes = await fetch(`${base}/api/dots`, { headers, signal: AbortSignal.timeout(10_000) });
|
|
419
|
+
if (listRes.status === 401)
|
|
420
|
+
throw new Error(`${base} needs a token: export LOCALDOST_TOKEN in this shell`);
|
|
421
|
+
if (!listRes.ok)
|
|
422
|
+
throw new Error(`GET ${base}/api/dots returned ${listRes.status}`);
|
|
423
|
+
const dots = (await listRes.json());
|
|
424
|
+
const existing = dots.find((d) => d.id === knownId) ?? dots.find((d) => d.name === input.name);
|
|
425
|
+
const res = existing
|
|
426
|
+
? await fetch(`${base}/api/dots/${existing.id}`, { method: 'PATCH', headers, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000) })
|
|
427
|
+
: await fetch(`${base}/api/dots`, { method: 'POST', headers, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000) });
|
|
428
|
+
if (!res.ok)
|
|
429
|
+
throw new Error(`${existing ? 'PATCH' : 'POST'} ${base}/api/dots returned ${res.status}`);
|
|
430
|
+
const dot = (await res.json());
|
|
431
|
+
return { id: dot.id, created: !existing };
|
|
432
|
+
}
|
|
433
|
+
async function upsertDotDb(dataDir, input, knownId) {
|
|
434
|
+
// config.ts and db.ts read the data dir at import time.
|
|
435
|
+
process.env.LOCALDOST_DATA_DIR = dataDir;
|
|
436
|
+
delete process.env.LOCALDOST_DB;
|
|
437
|
+
const { createWatch, findOne, get, update } = await import('../db.js');
|
|
438
|
+
const { NO_STAGE_OFFER } = await import('../stages/config.js');
|
|
439
|
+
const existing = (knownId ? get('watches', knownId) : undefined) ?? findOne('watches', { name: input.name });
|
|
440
|
+
if (existing) {
|
|
441
|
+
update('watches', existing.id, { ...input, updatedAt: new Date().toISOString() });
|
|
442
|
+
return { id: existing.id, created: false };
|
|
443
|
+
}
|
|
444
|
+
return { id: createWatch({ ...NO_STAGE_OFFER, ...input }).id, created: true };
|
|
445
|
+
}
|
|
446
|
+
// ---------- command ----------
|
|
447
|
+
const HELP = `Usage: localdost init [options]
|
|
448
|
+
|
|
449
|
+
Sets up localdost for the git repo in the current folder. Writes .env.localdost (no secrets,
|
|
450
|
+
only references) and .localdost/config.json, adds .env.localdost and .localdost/data/ to .gitignore,
|
|
451
|
+
and creates the first dot.
|
|
452
|
+
|
|
453
|
+
-y, --yes Accept every detected value, never prompt
|
|
454
|
+
--dir <path> Repo folder (default: current folder)
|
|
455
|
+
--repo <owner/name> GitHub repo (default: from git remote origin)
|
|
456
|
+
--branch <name> Default branch (default: from origin/HEAD)
|
|
457
|
+
--tracker <kind> linear | jira | github | none (default: from LINEAR_API_KEY or JIRA_* in env)
|
|
458
|
+
--linear-team <KEY> Linear team key, repeatable
|
|
459
|
+
--jira-url <url> Jira base URL (default: JIRA_BASE_URL)
|
|
460
|
+
--jira-project <KEY> Jira project key, repeatable
|
|
461
|
+
--tracker-repos <o/n> GitHub Issues: repo whose issues the dot reviews, repeatable (default: the repo above).
|
|
462
|
+
Defects are filed in the first one
|
|
463
|
+
--require-labels <l,...> GitHub Issues: review only issues with one of these labels, for example pod:agentic.
|
|
464
|
+
The first also goes on the defects the dot files
|
|
465
|
+
--milestone <title> GitHub Issues: review only issues in this milestone, repeatable
|
|
466
|
+
--port <n> Server port (default: ${DEFAULT_PORT})
|
|
467
|
+
--name <text> Dot name (default: repo name)
|
|
468
|
+
--base-url <url> App URL the tests run against (default: from the Playwright config)
|
|
469
|
+
--command <cmd> Test command (default: from package.json scripts)
|
|
470
|
+
--model <kind> claude-cli | codex-cli | anthropic | mock (default: detected)
|
|
471
|
+
--server <url> Create the dot on a running localdost server through the API
|
|
472
|
+
(for a hosted server; sends LOCALDOST_TOKEN from your shell)
|
|
473
|
+
--skip-model-check Do not run a \`claude -p\` round trip
|
|
474
|
+
--no-dot Write the files only
|
|
475
|
+
-h, --help Show this help
|
|
476
|
+
`;
|
|
477
|
+
export async function runInit(argv) {
|
|
478
|
+
const { values } = parseArgs({
|
|
479
|
+
args: argv,
|
|
480
|
+
allowPositionals: false,
|
|
481
|
+
options: {
|
|
482
|
+
yes: { type: 'boolean', short: 'y' },
|
|
483
|
+
dir: { type: 'string' },
|
|
484
|
+
repo: { type: 'string' },
|
|
485
|
+
branch: { type: 'string' },
|
|
486
|
+
tracker: { type: 'string' },
|
|
487
|
+
'linear-team': { type: 'string', multiple: true },
|
|
488
|
+
'jira-url': { type: 'string' },
|
|
489
|
+
'jira-project': { type: 'string', multiple: true },
|
|
490
|
+
'tracker-repos': { type: 'string', multiple: true },
|
|
491
|
+
'require-labels': { type: 'string', multiple: true },
|
|
492
|
+
milestone: { type: 'string', multiple: true },
|
|
493
|
+
port: { type: 'string' },
|
|
494
|
+
name: { type: 'string' },
|
|
495
|
+
'base-url': { type: 'string' },
|
|
496
|
+
command: { type: 'string' },
|
|
497
|
+
model: { type: 'string' },
|
|
498
|
+
server: { type: 'string' },
|
|
499
|
+
'skip-model-check': { type: 'boolean' },
|
|
500
|
+
'no-dot': { type: 'boolean' },
|
|
501
|
+
help: { type: 'boolean', short: 'h' },
|
|
502
|
+
},
|
|
503
|
+
});
|
|
504
|
+
if (values.help) {
|
|
505
|
+
console.log(HELP);
|
|
506
|
+
return 0;
|
|
507
|
+
}
|
|
508
|
+
const dir = path.resolve(values.dir ?? invokedDir());
|
|
509
|
+
const interactive = !values.yes && process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
510
|
+
const rl = interactive ? createInterface({ input: process.stdin, output: process.stdout }) : undefined;
|
|
511
|
+
const ask = async (q, def) => {
|
|
512
|
+
if (!rl)
|
|
513
|
+
return def;
|
|
514
|
+
const a = (await rl.question(`${q}${def ? ` [${def}]` : ''}: `)).trim();
|
|
515
|
+
return a || def;
|
|
516
|
+
};
|
|
517
|
+
const say = (label, value) => console.log(` ${label.padEnd(12)} ${value}`);
|
|
518
|
+
const fail = (msg) => {
|
|
519
|
+
rl?.close();
|
|
520
|
+
console.error(`localdost init: ${msg}`);
|
|
521
|
+
return 1;
|
|
522
|
+
};
|
|
523
|
+
try {
|
|
524
|
+
if (!existsSync(dir))
|
|
525
|
+
return fail(`${dir} does not exist`);
|
|
526
|
+
const prev = readLocaldostConfig(dir);
|
|
527
|
+
// References already in .env.localdost count as set, e.g. LINEAR_API_KEY=${env:...}.
|
|
528
|
+
const env = { ...(await loadLocaldostEnv(dir)).vars, ...process.env };
|
|
529
|
+
console.log(`localdost init in ${dir}\n`);
|
|
530
|
+
// Repo
|
|
531
|
+
let repo = await detectRepo(dir);
|
|
532
|
+
if (values.repo) {
|
|
533
|
+
const [owner, name] = values.repo.split('/');
|
|
534
|
+
if (!owner || !name)
|
|
535
|
+
return fail('--repo must be owner/name');
|
|
536
|
+
repo = { owner, name, defaultBranch: repo?.defaultBranch ?? 'main' };
|
|
537
|
+
}
|
|
538
|
+
if (!repo && rl) {
|
|
539
|
+
const a = await ask('GitHub repo (owner/name), empty for none', '');
|
|
540
|
+
const [owner, name] = a.split('/');
|
|
541
|
+
if (owner && name)
|
|
542
|
+
repo = { owner, name, defaultBranch: 'main' };
|
|
543
|
+
}
|
|
544
|
+
if (repo && values.branch)
|
|
545
|
+
repo.defaultBranch = values.branch;
|
|
546
|
+
if (repo && rl)
|
|
547
|
+
repo.defaultBranch = await ask('Default branch', repo.defaultBranch);
|
|
548
|
+
say('Repo', repo ? `${repo.owner}/${repo.name} (${repo.defaultBranch})` : 'none found (no GitHub remote "origin")');
|
|
549
|
+
// Tests
|
|
550
|
+
const tests = detectTests(dir);
|
|
551
|
+
const command = values.command ?? tests.command;
|
|
552
|
+
say('Tests', `${command}${tests.playwrightConfig ? ` with ${tests.playwrightConfig}` : ''}`);
|
|
553
|
+
if (tests.note && !values.command)
|
|
554
|
+
say('', `note: ${tests.note}`);
|
|
555
|
+
const baseUrl = values['base-url'] ?? tests.baseUrl;
|
|
556
|
+
if (baseUrl)
|
|
557
|
+
say('Base URL', baseUrl);
|
|
558
|
+
// GitHub token
|
|
559
|
+
const gh = await hasGhToken();
|
|
560
|
+
say('GitHub', gh ? '`gh auth token` works (stored as a reference, not the token)' : 'no token: run `gh auth login`');
|
|
561
|
+
// Model
|
|
562
|
+
let model;
|
|
563
|
+
const modelFlag = values.model ?? env.LOCALDOST_LLM?.trim();
|
|
564
|
+
if (modelFlag) {
|
|
565
|
+
if (modelFlag !== 'claude-cli' && modelFlag !== 'codex-cli' && modelFlag !== 'anthropic' && modelFlag !== 'mock')
|
|
566
|
+
return fail('--model must be claude-cli, codex-cli, anthropic, or mock');
|
|
567
|
+
model = modelFlag;
|
|
568
|
+
if (model === 'codex-cli') {
|
|
569
|
+
const codex = await checkCodexCli(env);
|
|
570
|
+
say('Model', `${model}: ${codex.detail}`);
|
|
571
|
+
}
|
|
572
|
+
else
|
|
573
|
+
say('Model', model);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
const claude = await checkClaudeCli(env, !values['skip-model-check']);
|
|
577
|
+
if (claude.ok)
|
|
578
|
+
model = 'claude-cli';
|
|
579
|
+
else if (env.ANTHROPIC_API_KEY?.trim())
|
|
580
|
+
model = 'anthropic';
|
|
581
|
+
else
|
|
582
|
+
model = 'mock';
|
|
583
|
+
const why = model === 'claude-cli'
|
|
584
|
+
? claude.detail
|
|
585
|
+
: model === 'anthropic'
|
|
586
|
+
? `ANTHROPIC_API_KEY is set (${claude.detail})`
|
|
587
|
+
: `${claude.detail}; no ANTHROPIC_API_KEY`;
|
|
588
|
+
say('Model', `${model}: ${why}`);
|
|
589
|
+
}
|
|
590
|
+
// Tracker
|
|
591
|
+
// The GitHub flags name the tracker: --require-labels alone means GitHub Issues.
|
|
592
|
+
const githubFlags = !!(values['tracker-repos']?.length || values['require-labels']?.length || values.milestone?.length);
|
|
593
|
+
let kind = values.tracker ??
|
|
594
|
+
(githubFlags ? 'github' : env.LINEAR_API_KEY?.trim() ? 'linear' : env.JIRA_API_TOKEN?.trim() || env.JIRA_BASE_URL?.trim() ? 'jira' : 'none');
|
|
595
|
+
if (rl && !values.tracker && !githubFlags)
|
|
596
|
+
kind = await ask('Tracker (linear, jira, github, none)', kind);
|
|
597
|
+
if (githubFlags && kind !== 'github')
|
|
598
|
+
return fail('--tracker-repos, --require-labels and --milestone need --tracker github');
|
|
599
|
+
let tracker;
|
|
600
|
+
if (kind === 'linear') {
|
|
601
|
+
let teams = values['linear-team'] ?? [];
|
|
602
|
+
if (!teams.length) {
|
|
603
|
+
const visible = await linearTeams(env);
|
|
604
|
+
if (visible?.length === 1)
|
|
605
|
+
teams = visible;
|
|
606
|
+
else if (rl)
|
|
607
|
+
teams = (await ask(`Linear team keys, comma separated${visible?.length ? ` (${visible.join(', ')})` : ''}`, '')).split(/[,\s]+/).filter(Boolean);
|
|
608
|
+
}
|
|
609
|
+
if (!teams.length)
|
|
610
|
+
return fail('Linear needs a team: pass --linear-team <KEY>');
|
|
611
|
+
tracker = { kind: 'linear', teamKeys: teams };
|
|
612
|
+
say('Tracker', `Linear ${teams.join(', ')}`);
|
|
613
|
+
}
|
|
614
|
+
else if (kind === 'jira') {
|
|
615
|
+
let baseJira = values['jira-url'] ?? env.JIRA_BASE_URL?.trim() ?? '';
|
|
616
|
+
if (!baseJira && rl)
|
|
617
|
+
baseJira = await ask('Jira base URL (https://acme.atlassian.net)', '');
|
|
618
|
+
if (!baseJira)
|
|
619
|
+
return fail('Jira needs a base URL: pass --jira-url or export JIRA_BASE_URL');
|
|
620
|
+
baseJira = baseJira.replace(/\/+$/, '');
|
|
621
|
+
let keys = values['jira-project'] ?? [];
|
|
622
|
+
if (!keys.length) {
|
|
623
|
+
const visible = await jiraProjects(env, baseJira);
|
|
624
|
+
if (visible?.length === 1)
|
|
625
|
+
keys = visible;
|
|
626
|
+
else if (rl)
|
|
627
|
+
keys = (await ask(`Jira project keys, comma separated${visible?.length ? ` (${visible.slice(0, 10).join(', ')})` : ''}`, ''))
|
|
628
|
+
.split(/[,\s]+/)
|
|
629
|
+
.filter(Boolean);
|
|
630
|
+
}
|
|
631
|
+
if (!keys.length)
|
|
632
|
+
return fail('Jira needs a project: pass --jira-project <KEY>');
|
|
633
|
+
tracker = { kind: 'jira', baseUrl: baseJira, projectKeys: keys };
|
|
634
|
+
say('Tracker', `Jira ${keys.join(', ')} on ${new URL(baseJira).host}`);
|
|
635
|
+
}
|
|
636
|
+
else if (kind === 'github') {
|
|
637
|
+
let repos = values['tracker-repos'] ?? [];
|
|
638
|
+
let labels = values['require-labels'] ?? [];
|
|
639
|
+
let milestones = values.milestone ?? [];
|
|
640
|
+
if (rl) {
|
|
641
|
+
if (!repos.length)
|
|
642
|
+
repos = [await ask('GitHub repos whose issues the dot reviews, comma separated (empty: the repo above)', '')];
|
|
643
|
+
if (!labels.length)
|
|
644
|
+
labels = [await ask('Review only issues with one of these labels, comma separated (empty: all issues)', '')];
|
|
645
|
+
if (!milestones.length)
|
|
646
|
+
milestones = [await ask('Review only these milestones, comma separated (empty: all)', '')];
|
|
647
|
+
}
|
|
648
|
+
const made = githubTrackerFromFlags({ repos, requireLabels: labels, milestones });
|
|
649
|
+
if (!made.ok)
|
|
650
|
+
return fail(made.error);
|
|
651
|
+
tracker = made.tracker;
|
|
652
|
+
if (!tracker.repos?.length && !repo)
|
|
653
|
+
return fail('GitHub Issues needs a repo: pass --tracker-repos <owner/name>, or run in a repo with an origin remote');
|
|
654
|
+
say('Tracker', `GitHub Issues in ${githubTrackerLine(tracker, repo ? `${repo.owner}/${repo.name}` : undefined)}`);
|
|
655
|
+
}
|
|
656
|
+
else if (kind === 'none') {
|
|
657
|
+
say('Tracker', 'none');
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
return fail('--tracker must be linear, jira, github, or none');
|
|
661
|
+
}
|
|
662
|
+
// Port and name
|
|
663
|
+
let port = Number(values.port ?? prev?.port ?? DEFAULT_PORT);
|
|
664
|
+
if (!values.port && !prev?.port && !values.server) {
|
|
665
|
+
// Another localdost (the demo, a dogfood run) often holds 4319. Take the next free port.
|
|
666
|
+
let p = port;
|
|
667
|
+
// 4320 is the demo sample shop's port.
|
|
668
|
+
while (p < port + 20 && (p === 4320 || !(await portFree(p))))
|
|
669
|
+
p++;
|
|
670
|
+
if (p !== port)
|
|
671
|
+
say('Port', `${port} is in use, using ${p}`);
|
|
672
|
+
port = p;
|
|
673
|
+
}
|
|
674
|
+
if (rl && !values.port)
|
|
675
|
+
port = Number(await ask('Port', String(port)));
|
|
676
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
677
|
+
return fail('--port must be 1-65535');
|
|
678
|
+
const name = values.name ?? prev?.name ?? repo?.name ?? path.basename(dir);
|
|
679
|
+
// Files
|
|
680
|
+
const cfg = {
|
|
681
|
+
version: 1,
|
|
682
|
+
name,
|
|
683
|
+
...(repo ? { repo } : {}),
|
|
684
|
+
...(tracker ? { tracker } : {}),
|
|
685
|
+
runner: { mode: 'local', workdir: '.', command },
|
|
686
|
+
...(tests.playwrightConfig ? { playwrightConfig: tests.playwrightConfig } : {}),
|
|
687
|
+
...(baseUrl ? { baseUrl } : {}),
|
|
688
|
+
port,
|
|
689
|
+
model,
|
|
690
|
+
...(values.server ? { server: values.server.replace(/\/+$/, '') } : {}),
|
|
691
|
+
...(prev?.dotId ? { dotId: prev.dotId } : {}),
|
|
692
|
+
updatedAt: new Date().toISOString(),
|
|
693
|
+
};
|
|
694
|
+
mkdirSync(path.join(dir, '.localdost'), { recursive: true });
|
|
695
|
+
writeFileSync(path.join(dir, ENV_FILE), renderEnvFile({ port, model, github: gh, tracker, slug: repo ? `${repo.owner}/${repo.name}` : undefined }));
|
|
696
|
+
const added = ensureGitignore(dir, [ENV_FILE, '.localdost/data/']);
|
|
697
|
+
console.log(`\nWrote ${ENV_FILE}, ${CONFIG_FILE}${added.length ? `, and added ${added.join(', ')} to .gitignore` : ''}`);
|
|
698
|
+
// Dot
|
|
699
|
+
if (!values['no-dot']) {
|
|
700
|
+
const server = cfg.server;
|
|
701
|
+
const hosted = !!server && !/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/.test(server);
|
|
702
|
+
const input = dotInput(cfg, hosted, dir);
|
|
703
|
+
try {
|
|
704
|
+
const r = server
|
|
705
|
+
? await upsertDotApi(server, input, prev?.dotId)
|
|
706
|
+
: await upsertDotDb((await loadLocaldostEnv(dir)).vars.LOCALDOST_DATA_DIR ?? defaultDataDir(dir), input, prev?.dotId);
|
|
707
|
+
cfg.dotId = r.id;
|
|
708
|
+
console.log(`${r.created ? 'Created' : 'Updated'} dot "${name}" (${r.id}) ${server ? `on ${server}` : `in .localdost/data`}`);
|
|
709
|
+
}
|
|
710
|
+
catch (err) {
|
|
711
|
+
writeFileSync(configFilePath(dir), `${JSON.stringify(cfg, null, 2)}\n`);
|
|
712
|
+
return fail(`could not create the dot: ${err instanceof Error ? err.message : String(err)}`);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
writeFileSync(configFilePath(dir), `${JSON.stringify(cfg, null, 2)}\n`);
|
|
716
|
+
rl?.close();
|
|
717
|
+
const missing = [];
|
|
718
|
+
if (!gh)
|
|
719
|
+
missing.push('gh auth login');
|
|
720
|
+
if (model === 'mock')
|
|
721
|
+
missing.push('claude auth login (or codex login with LOCALDOST_LLM=codex-cli, or export ANTHROPIC_API_KEY in your shell)');
|
|
722
|
+
if (tracker?.kind === 'linear' && !env.LINEAR_API_KEY?.trim())
|
|
723
|
+
missing.push('export LINEAR_API_KEY=<key from linear.app/settings/api>');
|
|
724
|
+
if (tracker?.kind === 'jira' && !(env.JIRA_EMAIL?.trim() && env.JIRA_API_TOKEN?.trim()))
|
|
725
|
+
missing.push('export JIRA_EMAIL=<you@company.com> JIRA_API_TOKEN=<token from id.atlassian.com>');
|
|
726
|
+
if (!tests.hasPlaywright && !values.command)
|
|
727
|
+
missing.push('npm i -D @playwright/test && npx playwright install chromium');
|
|
728
|
+
console.log('\nNext steps:');
|
|
729
|
+
for (const m of missing)
|
|
730
|
+
console.log(` ${m}`);
|
|
731
|
+
console.log(' localdost doctor check every service');
|
|
732
|
+
if (cfg.server) {
|
|
733
|
+
console.log(` open ${cfg.server} the dot is on that server`);
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
console.log(` localdost start run the server on http://localhost:${port}`);
|
|
737
|
+
console.log(' docs/DEPLOY.md host it on Railway, Docker Compose, or a cloudflared tunnel');
|
|
738
|
+
}
|
|
739
|
+
console.log('\nNever paste a token into a chat or this file. Export it in your shell instead.');
|
|
740
|
+
return 0;
|
|
741
|
+
}
|
|
742
|
+
catch (err) {
|
|
743
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
//# sourceMappingURL=init.js.map
|