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/refs.js
ADDED
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
// Titled references (KAT-225). Every reference a person reads (a PR, an issue, a ticket in Jira, Linear,
|
|
2
|
+
// or GitHub Issues, a run, a defect) shows a short plain title with its link embedded, never a bare number
|
|
3
|
+
// such as "PR #30" or "KAT-142":
|
|
4
|
+
//
|
|
5
|
+
// markdown [Queued checks show at once (#30)](https://github.com/acme/shop/pull/30)
|
|
6
|
+
// mrkdwn <https://github.com/acme/shop/pull/30|Queued checks show at once (#30)>
|
|
7
|
+
// text Queued checks show at once (#30) (push, voice, Activity rows: no link syntax)
|
|
8
|
+
//
|
|
9
|
+
// renderRefs() is the post-processor every model answer passes through (web chat, Slack, voice, digests,
|
|
10
|
+
// notifications). It finds bare references, looks the title up (cache, then the dot's GitHub data and the
|
|
11
|
+
// connected tracker, then the runs already stored), and rewrites them. A reference with a keyword
|
|
12
|
+
// ("PR #999") that no source knows becomes a plain link when its repo is certain; anything else is left as
|
|
13
|
+
// written. Code, existing links, and URLs it cannot title are never touched, so a second pass changes nothing.
|
|
14
|
+
import { config, liveEnv, log } from './config.js';
|
|
15
|
+
import { get, list } from './db.js';
|
|
16
|
+
import { watchRepos } from './repos.js';
|
|
17
|
+
import { trackerProjectKeys } from './ticket-keys.js';
|
|
18
|
+
// ---------- cache ----------
|
|
19
|
+
const HIT_TTL_MS = 10 * 60_000;
|
|
20
|
+
const MISS_TTL_MS = 60_000;
|
|
21
|
+
const CACHE_CAP = 500;
|
|
22
|
+
const LOOKUP_TIMEOUT_MS = 3000;
|
|
23
|
+
const MAX_REPOS = 6;
|
|
24
|
+
const MAX_TITLE = 80;
|
|
25
|
+
const cache = new Map();
|
|
26
|
+
function cacheGet(key) {
|
|
27
|
+
const e = cache.get(key);
|
|
28
|
+
if (!e)
|
|
29
|
+
return undefined;
|
|
30
|
+
if (Date.now() - e.at > (e.hit ? HIT_TTL_MS : MISS_TTL_MS)) {
|
|
31
|
+
cache.delete(key);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return e.hit;
|
|
35
|
+
}
|
|
36
|
+
function cachePut(key, hit) {
|
|
37
|
+
cache.delete(key);
|
|
38
|
+
cache.set(key, { at: Date.now(), hit });
|
|
39
|
+
if (cache.size > CACHE_CAP) {
|
|
40
|
+
const oldest = cache.keys().next().value;
|
|
41
|
+
if (oldest !== undefined)
|
|
42
|
+
cache.delete(oldest);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const inflight = new Map();
|
|
46
|
+
/** Two references to the same item in one answer share one lookup. */
|
|
47
|
+
function once(key, fn) {
|
|
48
|
+
const running = inflight.get(key);
|
|
49
|
+
if (running)
|
|
50
|
+
return running;
|
|
51
|
+
const p = fn().finally(() => inflight.delete(key));
|
|
52
|
+
inflight.set(key, p);
|
|
53
|
+
return p;
|
|
54
|
+
}
|
|
55
|
+
/** Forgets every cached title. Tests call it between cases. */
|
|
56
|
+
export function clearRefCache() {
|
|
57
|
+
cache.clear();
|
|
58
|
+
}
|
|
59
|
+
let depsOverride;
|
|
60
|
+
/** Test and eval seam: answer lookups from `d` instead of GitHub and the trackers. Pass undefined to reset. */
|
|
61
|
+
export function setRefDeps(d) {
|
|
62
|
+
depsOverride = d;
|
|
63
|
+
cache.clear();
|
|
64
|
+
}
|
|
65
|
+
// ---------- titles ----------
|
|
66
|
+
/**
|
|
67
|
+
* Untrusted text (a PR, ticket, finding or action title, test output) made safe to join into Markdown that
|
|
68
|
+
* toMrkdwn turns into Slack mrkdwn: `[` and `]` become full-width look-alikes, so `[x](https://evil)` cannot
|
|
69
|
+
* parse as a link and only the links the server builds become Slack links.
|
|
70
|
+
*/
|
|
71
|
+
export function mdText(s) {
|
|
72
|
+
return s.replace(/\[/g, '\uff3b').replace(/\]/g, '\uff3d');
|
|
73
|
+
}
|
|
74
|
+
/** A short plain title: one line, no brackets, no trailing "(#30)" a squash merge adds, at most 80 characters. */
|
|
75
|
+
export function cleanTitle(raw) {
|
|
76
|
+
const one = raw
|
|
77
|
+
.replace(/\s+/g, ' ')
|
|
78
|
+
.replace(/\[/g, '(')
|
|
79
|
+
.replace(/\]/g, ')')
|
|
80
|
+
.replace(/\s*\((?:#\d+|[A-Z][A-Z0-9]{1,9}-\d+)\)\s*$/, '')
|
|
81
|
+
.trim()
|
|
82
|
+
.replace(/[.:;,]+$/, '');
|
|
83
|
+
return one.length > MAX_TITLE ? `${one.slice(0, MAX_TITLE - 3).trimEnd()}...` : one;
|
|
84
|
+
}
|
|
85
|
+
/** The short plain title of the PR a trigger is about, or an empty string. */
|
|
86
|
+
export function prTitleOf(t) {
|
|
87
|
+
return t?.title ? cleanTitle(stripPrefix(t.title)) : '';
|
|
88
|
+
}
|
|
89
|
+
/** "PR #12: Fix it", "Merged PR #12: Fix it", "Merge #12: Fix it" -> "Fix it". */
|
|
90
|
+
function stripPrefix(title) {
|
|
91
|
+
return title.replace(/^\s*(?:merged\s+)?(?:PR|pull request|merge)\s*#?\d+\s*[:\-–—]?\s*/i, '').trim();
|
|
92
|
+
}
|
|
93
|
+
const RUN_LABEL = {
|
|
94
|
+
workflow: 'Workflow run',
|
|
95
|
+
pr_check: 'PR check',
|
|
96
|
+
post_merge: 'Merge check',
|
|
97
|
+
ci_failure: 'CI failure triage',
|
|
98
|
+
ticket_review: 'Ticket review',
|
|
99
|
+
outage: 'Outage',
|
|
100
|
+
recovery: 'Recovery',
|
|
101
|
+
digest: 'Daily digest',
|
|
102
|
+
rerun: 'Test rerun',
|
|
103
|
+
repo_scan: 'Repo scan',
|
|
104
|
+
test_design: 'Test design',
|
|
105
|
+
nightly_run: 'Nightly test run',
|
|
106
|
+
};
|
|
107
|
+
/** The title a person sees for a run: what it did and what it was about. */
|
|
108
|
+
export function runTitle(run) {
|
|
109
|
+
const label = RUN_LABEL[run.kind] ?? 'Run';
|
|
110
|
+
const raw = run.trigger?.title ? stripPrefix(run.trigger.title).replace(/^[A-Z][A-Z0-9]{1,9}-\d+\s*:\s*/, '') : '';
|
|
111
|
+
// The nightly run's trigger title is "Nightly, Thu 22 Oct, 02:00": the label and the time, said once.
|
|
112
|
+
if (raw && run.kind === 'nightly_run')
|
|
113
|
+
return cleanTitle(`${label}, ${raw.replace(/^Nightly,\s*/i, '')}`);
|
|
114
|
+
if (raw && run.kind !== 'digest')
|
|
115
|
+
return cleanTitle(`${label}: ${raw}`);
|
|
116
|
+
return `${label}, ${run.createdAt.slice(0, 10)}`;
|
|
117
|
+
}
|
|
118
|
+
const webBase = () => (liveEnv.GITHUB_SERVER_URL ?? 'https://github.com').replace(/\/$/, '');
|
|
119
|
+
function runUrl(id, absolute) {
|
|
120
|
+
if (!absolute)
|
|
121
|
+
return `/#/runs/${id}`;
|
|
122
|
+
const base = config.publicUrl?.replace(/\/$/, '');
|
|
123
|
+
return base ? `${base}/#/runs/${id}` : undefined;
|
|
124
|
+
}
|
|
125
|
+
// ---------- stored runs ----------
|
|
126
|
+
function repoOfRun(r, watchOf) {
|
|
127
|
+
const t = r.trigger?.repo;
|
|
128
|
+
if (t?.owner && t.name)
|
|
129
|
+
return `${t.owner}/${t.name}`.toLowerCase();
|
|
130
|
+
const w = watchOf(r.watchId);
|
|
131
|
+
const first = w ? watchRepos(w)[0] : undefined;
|
|
132
|
+
return first ? first.id.toLowerCase() : undefined;
|
|
133
|
+
}
|
|
134
|
+
/** Titles of the PRs and tickets that the given runs were about. Newest run wins. */
|
|
135
|
+
export function buildRefIndex(runs, watchOf = (id) => get('watches', id)) {
|
|
136
|
+
const idx = { prs: new Map(), tickets: new Map() };
|
|
137
|
+
for (const r of runs) {
|
|
138
|
+
const t = r.trigger;
|
|
139
|
+
if (!t)
|
|
140
|
+
continue;
|
|
141
|
+
if (t.pr) {
|
|
142
|
+
const repo = repoOfRun(r, watchOf);
|
|
143
|
+
const title = cleanTitle(stripPrefix(t.title ?? ''));
|
|
144
|
+
const key = repo ? `${repo}#${t.pr.number}` : '';
|
|
145
|
+
if (key && title && !idx.prs.has(key)) {
|
|
146
|
+
const url = t.url && /\/pull\/\d+/.test(t.url) ? t.url : `${webBase()}/${repo}/pull/${t.pr.number}`;
|
|
147
|
+
idx.prs.set(key, { title, url, id: `#${t.pr.number}`, kind: 'pr' });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (t.ticket) {
|
|
151
|
+
const key = t.ticket.key.toUpperCase();
|
|
152
|
+
const raw = t.inlineTicket?.title ?? (t.title ?? '').replace(new RegExp(`^\\s*${escapeRe(t.ticket.key)}\\s*[:\\-–—]?\\s*`, 'i'), '');
|
|
153
|
+
const title = cleanTitle(raw);
|
|
154
|
+
if (title && !idx.tickets.has(key)) {
|
|
155
|
+
const url = t.inlineTicket?.url ?? (t.url && !/\/pull\/\d+/.test(t.url) ? t.url : undefined);
|
|
156
|
+
idx.tickets.set(key, { title, ...(url ? { url } : {}), id: t.ticket.key, kind: 'ticket' });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return idx;
|
|
161
|
+
}
|
|
162
|
+
/** A trigger's title with its number moved behind the title: "Fix it (#12)", "Review it (KAT-3)". */
|
|
163
|
+
export function titledTrigger(t) {
|
|
164
|
+
const trig = t;
|
|
165
|
+
if (!trig || typeof trig.title !== 'string')
|
|
166
|
+
return undefined;
|
|
167
|
+
if (trig.pr) {
|
|
168
|
+
const title = cleanTitle(stripPrefix(trig.title));
|
|
169
|
+
return title ? `${title} (#${trig.pr.number})` : undefined;
|
|
170
|
+
}
|
|
171
|
+
if (trig.ticket) {
|
|
172
|
+
const title = cleanTitle(trig.title.replace(new RegExp(`^\\s*${escapeRe(trig.ticket.key)}\\s*[:\\-–—]?\\s*`, 'i'), ''));
|
|
173
|
+
return title ? `${title} (${trig.ticket.key})` : undefined;
|
|
174
|
+
}
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
function localIndex(watches) {
|
|
178
|
+
const runs = [];
|
|
179
|
+
const per = Math.max(40, Math.floor(300 / Math.max(1, watches.length)));
|
|
180
|
+
for (const w of watches)
|
|
181
|
+
runs.push(...list('runs', { watchId: w.id }, { orderBy: 'id DESC', limit: per }));
|
|
182
|
+
runs.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
183
|
+
const byId = new Map(watches.map((w) => [w.id, w]));
|
|
184
|
+
return buildRefIndex(runs, (id) => byId.get(id) ?? get('watches', id));
|
|
185
|
+
}
|
|
186
|
+
// ---------- finding references ----------
|
|
187
|
+
function escapeRe(s) {
|
|
188
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
189
|
+
}
|
|
190
|
+
/** Places the rewriter never edits: code, links, angle brackets, URLs, HTML entities. */
|
|
191
|
+
const PROTECT = new RegExp([
|
|
192
|
+
String.raw `(?<fence>\x60{3}[\s\S]*?(?:\x60{3}|$))`,
|
|
193
|
+
String.raw `(?<code>\x60[^\x60\n]+\x60)`,
|
|
194
|
+
String.raw `(?<mdlink>(?<!!)\[(?<ltext>[^\]\n]*)\]\((?<lurl>[^)\s]*)(?:\s+"[^"]*")?\))`,
|
|
195
|
+
String.raw `(?<angle><[^>\n]+>)`,
|
|
196
|
+
String.raw `(?<url>https?://[^\s<>)\]]+)`,
|
|
197
|
+
String.raw `(?<entity>&#?\w+;)`,
|
|
198
|
+
].join('|'), 'g');
|
|
199
|
+
const KW = String.raw `(?:PRs?|pull\s+requests?|merged?|issues?|defects?|bugs?)`;
|
|
200
|
+
const REF = new RegExp([
|
|
201
|
+
String.raw `(?<![\w./-])(?<repo>[\w.-]+/[\w.-]+)#(?<rn>\d{1,6})(?![\w-])`,
|
|
202
|
+
String.raw `(?:(?<kw>\b${KW})\s+)?(?<![\w&/])#(?<n>\d{1,6})(?![\w-])`,
|
|
203
|
+
String.raw `(?<kw2>\b(?:PR|pull\s+request))\s+(?<n2>\d{1,6})(?![\w-])`,
|
|
204
|
+
String.raw `(?<![\w/#.-])(?<key>[A-Z][A-Z0-9]{1,9}-\d{1,9})(?![\w-])`,
|
|
205
|
+
String.raw `(?:(?<rkw>\bruns?)\s+)?(?<![\w-])(?<rid>(?=[0-9a-z]*\d)[0-9a-z]{18})(?![\w-])`,
|
|
206
|
+
// A commit: 7 to 40 lower-case hex characters. Without the word "commit" it needs a digit and a letter, so a count, a date, or a word is not a sha.
|
|
207
|
+
String.raw `(?:(?<ckw>\bcommits?)\s+)?(?<![\w./#-])(?<sha>[0-9a-f]{7,40})(?![\w.-]*\w)`,
|
|
208
|
+
].join('|'), 'gi');
|
|
209
|
+
const PR_URL = /^https?:\/\/([^/]+)\/([\w.-]+)\/([\w.-]+)\/(pull|issues)\/(\d{1,9})(?:[/?#].*)?$/i;
|
|
210
|
+
const JIRA_URL = /^https?:\/\/[^/]+\/(?:browse\/|[^\s]*?[?&](?:selectedIssue|issueKey)=)([A-Z][A-Z0-9_]{0,19}-\d{1,9})(?:[/?#&].*)?$/;
|
|
211
|
+
const LINEAR_URL = /^https?:\/\/linear\.app\/[\w-]+\/issue\/([A-Z][A-Z0-9]{0,9}-\d{1,9})(?:[/?#].*)?$/;
|
|
212
|
+
function trackerPrefixes(w) {
|
|
213
|
+
return trackerProjectKeys(w);
|
|
214
|
+
}
|
|
215
|
+
function wantOf(kw) {
|
|
216
|
+
if (!kw)
|
|
217
|
+
return undefined;
|
|
218
|
+
return /^(issue|defect|bug)/i.test(kw) ? 'issue' : 'pr';
|
|
219
|
+
}
|
|
220
|
+
/** Reads one reference that spans exactly `s` (a link text), or null. */
|
|
221
|
+
function wholeRef(s, scope) {
|
|
222
|
+
const t = s.trim();
|
|
223
|
+
if (!t)
|
|
224
|
+
return null;
|
|
225
|
+
const re = new RegExp(REF.source, 'i');
|
|
226
|
+
const m = re.exec(t);
|
|
227
|
+
if (!m || m.index !== 0 || m[0].length !== t.length)
|
|
228
|
+
return null;
|
|
229
|
+
return fromMatch(m, scope);
|
|
230
|
+
}
|
|
231
|
+
function fromMatch(m, scope) {
|
|
232
|
+
const g = m.groups ?? {};
|
|
233
|
+
if (g.repo)
|
|
234
|
+
return { kind: 'num', n: Number(g.rn), repo: g.repo.toLowerCase(), keyworded: true };
|
|
235
|
+
if (g.n)
|
|
236
|
+
return { kind: 'num', n: Number(g.n), ...(g.kw ? { want: wantOf(g.kw), keyworded: true } : {}) };
|
|
237
|
+
if (g.n2)
|
|
238
|
+
return { kind: 'num', n: Number(g.n2), want: 'pr', keyworded: true };
|
|
239
|
+
if (g.key) {
|
|
240
|
+
// Ticket keys are upper case, and the prefix must belong to a tracker the dots use.
|
|
241
|
+
if (g.key !== g.key.toUpperCase() || !scope.prefixes.has(g.key.split('-')[0]))
|
|
242
|
+
return null;
|
|
243
|
+
return { kind: 'ticket', key: g.key };
|
|
244
|
+
}
|
|
245
|
+
if (g.rid) {
|
|
246
|
+
if (g.rid !== g.rid.toLowerCase())
|
|
247
|
+
return null;
|
|
248
|
+
return { kind: 'run', id: g.rid };
|
|
249
|
+
}
|
|
250
|
+
if (g.sha) {
|
|
251
|
+
if (g.sha !== g.sha.toLowerCase())
|
|
252
|
+
return null;
|
|
253
|
+
if (!g.ckw && !(/\d/.test(g.sha) && /[a-f]/.test(g.sha)))
|
|
254
|
+
return null;
|
|
255
|
+
return { kind: 'commit', sha: g.sha, ...(g.ckw ? { keyworded: true } : {}) };
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
function fromUrl(url) {
|
|
260
|
+
const gh = PR_URL.exec(url);
|
|
261
|
+
if (gh) {
|
|
262
|
+
const host = gh[1].toLowerCase();
|
|
263
|
+
let web = 'github.com';
|
|
264
|
+
try {
|
|
265
|
+
web = new URL(webBase()).host.toLowerCase();
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
/* keep github.com */
|
|
269
|
+
}
|
|
270
|
+
if (host !== 'github.com' && host !== web)
|
|
271
|
+
return null;
|
|
272
|
+
return { kind: 'num', n: Number(gh[5]), repo: `${gh[2]}/${gh[3]}`.toLowerCase(), want: gh[4].toLowerCase() === 'pull' ? 'pr' : 'issue', keyworded: true };
|
|
273
|
+
}
|
|
274
|
+
const key = JIRA_URL.exec(url)?.[1] ?? LINEAR_URL.exec(url)?.[1];
|
|
275
|
+
if (key && !/^https?:\/\/(?:www\.)?github\.com\//i.test(url))
|
|
276
|
+
return { kind: 'ticket', key: key.toUpperCase() };
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
function collect(text, scope) {
|
|
280
|
+
const out = [];
|
|
281
|
+
const free = (from, to) => {
|
|
282
|
+
if (to <= from)
|
|
283
|
+
return;
|
|
284
|
+
const re = new RegExp(REF.source, 'gi');
|
|
285
|
+
re.lastIndex = from;
|
|
286
|
+
for (let m = re.exec(text); m && m.index < to; m = re.exec(text)) {
|
|
287
|
+
if (m.index + m[0].length > to)
|
|
288
|
+
break;
|
|
289
|
+
const c = fromMatch(m, scope);
|
|
290
|
+
if (c)
|
|
291
|
+
out.push({ ...c, start: m.index, end: m.index + m[0].length, text: m[0], mode: 'plain' });
|
|
292
|
+
if (m[0].length === 0)
|
|
293
|
+
re.lastIndex++;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
let last = 0;
|
|
297
|
+
for (const m of text.matchAll(PROTECT)) {
|
|
298
|
+
const g = m.groups ?? {};
|
|
299
|
+
const start = m.index ?? 0;
|
|
300
|
+
free(last, start);
|
|
301
|
+
last = start + m[0].length;
|
|
302
|
+
if (g.mdlink) {
|
|
303
|
+
// [#30](url): the link text is a bare number. Give it a title and keep the link.
|
|
304
|
+
const c = wholeRef(g.ltext ?? '', scope);
|
|
305
|
+
if (c) {
|
|
306
|
+
// A link that already points into a repo names it: the number belongs to that repo, not to the dot's primary one.
|
|
307
|
+
const target = c.kind === 'num' && !c.repo && g.lurl ? fromUrl(g.lurl) : null;
|
|
308
|
+
const named = target?.kind === 'num' && target.repo ? { repo: target.repo, ...(target.want ? { want: target.want } : {}) } : {};
|
|
309
|
+
out.push({ ...c, ...named, start, end: last, text: g.ltext ?? '', mode: 'mdlink', givenUrl: g.lurl });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if (g.url) {
|
|
313
|
+
// A bare URL: strip the punctuation a sentence puts after it.
|
|
314
|
+
const trail = /[.,;:!?]+$/.exec(g.url)?.[0] ?? '';
|
|
315
|
+
const url = trail ? g.url.slice(0, -trail.length) : g.url;
|
|
316
|
+
const c = fromUrl(url);
|
|
317
|
+
if (c)
|
|
318
|
+
out.push({ ...c, start, end: start + url.length, text: url, mode: 'url', givenUrl: url });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
free(last, text.length);
|
|
322
|
+
return out.sort((a, b) => a.start - b.start);
|
|
323
|
+
}
|
|
324
|
+
function withTimeout(p, ms = LOOKUP_TIMEOUT_MS) {
|
|
325
|
+
let timer;
|
|
326
|
+
const limit = new Promise((resolve) => {
|
|
327
|
+
timer = setTimeout(() => resolve(undefined), ms);
|
|
328
|
+
timer.unref?.();
|
|
329
|
+
});
|
|
330
|
+
return Promise.race([p, limit]).finally(() => clearTimeout(timer));
|
|
331
|
+
}
|
|
332
|
+
function repoCandidates(c, scope) {
|
|
333
|
+
const out = [];
|
|
334
|
+
const seen = new Set();
|
|
335
|
+
for (const w of scope.watches) {
|
|
336
|
+
const repos = watchRepos(w);
|
|
337
|
+
const extra = w.tracker?.kind === 'github' ? (w.tracker.repos ?? []).map((r) => r.toLowerCase()) : [];
|
|
338
|
+
const ids = [...repos.map((r) => r.id.toLowerCase()), ...extra];
|
|
339
|
+
ids.forEach((id, i) => {
|
|
340
|
+
if (seen.has(id) || (c.repo && c.repo !== id))
|
|
341
|
+
return;
|
|
342
|
+
seen.add(id);
|
|
343
|
+
out.push({ repo: id, watch: w, primary: i === 0 });
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
return out.slice(0, MAX_REPOS);
|
|
347
|
+
}
|
|
348
|
+
const prUrl = (repo, n, kind) => `${webBase()}/${repo}/${kind === 'pr' ? 'pull' : 'issues'}/${n}`;
|
|
349
|
+
async function defaultDeps() {
|
|
350
|
+
const gh = await import('./integrations/github.js');
|
|
351
|
+
const issues = await import('./integrations/github-issues.js');
|
|
352
|
+
const tickets = await import('./review/ticket-on-demand.js');
|
|
353
|
+
return {
|
|
354
|
+
async pull(repo, n, watch) {
|
|
355
|
+
const [owner, name] = repo.split('/');
|
|
356
|
+
const found = await gh.githubFor(watch, { repo: { owner, name } }).getPull(n);
|
|
357
|
+
return found ? { title: found.summary.title, ...(found.summary.url ? { url: found.summary.url } : {}) } : null;
|
|
358
|
+
},
|
|
359
|
+
async issue(repo, n) {
|
|
360
|
+
if (gh.githubMode() === 'demo')
|
|
361
|
+
return null;
|
|
362
|
+
try {
|
|
363
|
+
const t = await issues.issueApi(repo).getIssue(n);
|
|
364
|
+
return { title: t.title, ...(t.url ? { url: t.url } : {}) };
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
async commit(repo, sha, watch) {
|
|
371
|
+
const [owner, name] = repo.split('/');
|
|
372
|
+
const found = await gh.githubFor(watch, { repo: { owner, name } }).getCommit(sha);
|
|
373
|
+
const title = found?.message.split('\n', 1)[0] ?? '';
|
|
374
|
+
return found && title ? { title, ...(found.url ? { url: found.url } : {}) } : null;
|
|
375
|
+
},
|
|
376
|
+
async ticket(key, watch) {
|
|
377
|
+
const parsed = tickets.parseTicketInput(key, watch);
|
|
378
|
+
if (!parsed.ok)
|
|
379
|
+
return null;
|
|
380
|
+
const res = await tickets.fetchTicketRef(watch, parsed.ref);
|
|
381
|
+
return res.ok ? { title: res.ticket.title, ...(res.ticket.url ? { url: res.ticket.url } : {}) } : null;
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
let defaults;
|
|
386
|
+
async function deps() {
|
|
387
|
+
defaults ??= defaultDeps();
|
|
388
|
+
const base = await defaults;
|
|
389
|
+
return { ...base, ...depsOverride };
|
|
390
|
+
}
|
|
391
|
+
/** One repo, one number: cache, then GitHub, then the stored runs. A pull request is tried before an issue unless the text said issue. */
|
|
392
|
+
function lookupNumber(repo, n, watch, want, scope, remote) {
|
|
393
|
+
return once(`num:${repo}#${n}:${want ?? ''}:${remote}`, () => lookupNumberOnce(repo, n, watch, want, scope, remote));
|
|
394
|
+
}
|
|
395
|
+
async function lookupNumberOnce(repo, n, watch, want, scope, remote) {
|
|
396
|
+
const key = `num:${repo}#${n}:${want ?? ''}`;
|
|
397
|
+
const cached = cacheGet(key);
|
|
398
|
+
if (cached !== undefined)
|
|
399
|
+
return cached;
|
|
400
|
+
let hit = null;
|
|
401
|
+
const order = want === 'issue' ? ['issue', 'pr'] : ['pr', 'issue'];
|
|
402
|
+
if (remote) {
|
|
403
|
+
const d = await deps();
|
|
404
|
+
for (const kind of order) {
|
|
405
|
+
try {
|
|
406
|
+
const found = await withTimeout(kind === 'pr' ? d.pull(repo, n, watch) : d.issue(repo, n, watch));
|
|
407
|
+
const title = found ? cleanTitle(found.title) : '';
|
|
408
|
+
if (found && title) {
|
|
409
|
+
hit = { title, url: found.url ?? prUrl(repo, n, kind), id: `#${n}`, kind };
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
catch (err) {
|
|
414
|
+
log.warn(`refs: could not read ${repo}#${n}: ${err instanceof Error ? err.message : String(err)}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
hit ??= scope.index.prs.get(`${repo}#${n}`) ?? null;
|
|
419
|
+
if (remote)
|
|
420
|
+
cachePut(key, hit);
|
|
421
|
+
return hit;
|
|
422
|
+
}
|
|
423
|
+
async function resolveNumber(c, scope, remote) {
|
|
424
|
+
const n = c.n;
|
|
425
|
+
const cands = repoCandidates(c, scope);
|
|
426
|
+
// owner/name#N for a repo no dot holds: the stored runs may still know it.
|
|
427
|
+
if (!cands.length && c.repo) {
|
|
428
|
+
const local = scope.index.prs.get(`${c.repo}#${n}`);
|
|
429
|
+
return local ? { hit: local } : { plainUrl: prUrl(c.repo, n, c.want ?? 'pr'), repo: c.repo };
|
|
430
|
+
}
|
|
431
|
+
if (!cands.length)
|
|
432
|
+
return {};
|
|
433
|
+
const hits = (await Promise.all(cands.map(async (r) => ({ r, hit: await lookupNumber(r.repo, n, r.watch, c.want, scope, remote) })))).filter((x) => x.hit);
|
|
434
|
+
if (hits.length === 1)
|
|
435
|
+
return { hit: hits[0].hit };
|
|
436
|
+
if (hits.length > 1) {
|
|
437
|
+
// The same number in two repos: the dot's primary repo wins when only it matches; otherwise the text is ambiguous.
|
|
438
|
+
const primary = hits.filter((h) => h.r.primary);
|
|
439
|
+
if (scope.watches.length === 1 && primary.length === 1)
|
|
440
|
+
return { hit: primary[0].hit };
|
|
441
|
+
return {};
|
|
442
|
+
}
|
|
443
|
+
// Nobody knows it. With a keyword and one possible repo the link is still certain.
|
|
444
|
+
return c.keyworded && cands.length === 1 ? { plainUrl: prUrl(cands[0].repo, n, c.want ?? 'pr'), repo: cands[0].repo } : {};
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* The cache key of a ticket. The same key can name different tickets in different trackers (SHOP-12 in two Jira
|
|
448
|
+
* sites), and each dot reads its own tracker, so the key also names the dots that answer for it.
|
|
449
|
+
*/
|
|
450
|
+
function ticketCacheKey(key, owners) {
|
|
451
|
+
return `ticket:${owners.map((w) => w.id).join(',')}:${key}`;
|
|
452
|
+
}
|
|
453
|
+
const ownersOf = (key, scope) => scope.watches.filter((w) => trackerPrefixes(w).includes(key.split('-')[0]));
|
|
454
|
+
async function ticketHit(key, owners, scope, remote) {
|
|
455
|
+
const cacheKey = ticketCacheKey(key, owners);
|
|
456
|
+
const cached = cacheGet(cacheKey);
|
|
457
|
+
if (cached !== undefined)
|
|
458
|
+
return cached;
|
|
459
|
+
let hit = null;
|
|
460
|
+
if (remote && owners.length) {
|
|
461
|
+
const d = await deps();
|
|
462
|
+
for (const w of owners) {
|
|
463
|
+
try {
|
|
464
|
+
const found = await withTimeout(d.ticket(key, w));
|
|
465
|
+
const title = found ? cleanTitle(found.title) : '';
|
|
466
|
+
if (found && title) {
|
|
467
|
+
hit = { title, ...(found.url ? { url: found.url } : {}), id: key, kind: 'ticket' };
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
catch (err) {
|
|
472
|
+
log.warn(`refs: could not read ${key}: ${err instanceof Error ? err.message : String(err)}`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
hit ??= scope.index.tickets.get(key) ?? null;
|
|
477
|
+
if (remote)
|
|
478
|
+
cachePut(cacheKey, hit);
|
|
479
|
+
return hit;
|
|
480
|
+
}
|
|
481
|
+
async function resolveTicket(c, scope, remote) {
|
|
482
|
+
const key = c.key.toUpperCase();
|
|
483
|
+
const owners = ownersOf(key, scope);
|
|
484
|
+
const hit = await once(`${ticketCacheKey(key, owners)}:${remote}`, () => ticketHit(key, owners, scope, remote));
|
|
485
|
+
if (hit)
|
|
486
|
+
return { hit };
|
|
487
|
+
// Jira keys have a fixed address; Linear and GitHub Issues keys do not.
|
|
488
|
+
const jira = owners.find((w) => w.tracker?.kind === 'jira');
|
|
489
|
+
if (jira?.tracker?.kind === 'jira' && jira.tracker.baseUrl)
|
|
490
|
+
return { plainUrl: `${jira.tracker.baseUrl.replace(/\/$/, '')}/browse/${key}` };
|
|
491
|
+
return {};
|
|
492
|
+
}
|
|
493
|
+
/** One repo, one sha: cache, then GitHub. */
|
|
494
|
+
function lookupCommit(repo, sha, watch, remote) {
|
|
495
|
+
return once(`commit:${repo}@${sha}:${remote}`, async () => {
|
|
496
|
+
const key = `commit:${repo}@${sha}`;
|
|
497
|
+
const cached = cacheGet(key);
|
|
498
|
+
if (cached !== undefined)
|
|
499
|
+
return cached;
|
|
500
|
+
let hit = null;
|
|
501
|
+
if (remote) {
|
|
502
|
+
try {
|
|
503
|
+
const found = await withTimeout((await deps()).commit(repo, sha, watch));
|
|
504
|
+
const title = found ? cleanTitle(found.title) : '';
|
|
505
|
+
if (found && title)
|
|
506
|
+
hit = { title, url: found.url ?? commitUrl(repo, sha), id: sha.slice(0, 7), kind: 'commit' };
|
|
507
|
+
}
|
|
508
|
+
catch (err) {
|
|
509
|
+
log.warn(`refs: could not read commit ${sha} of ${repo}: ${err instanceof Error ? err.message : String(err)}`);
|
|
510
|
+
}
|
|
511
|
+
cachePut(key, hit);
|
|
512
|
+
}
|
|
513
|
+
return hit;
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
async function resolveCommit(c, scope, remote) {
|
|
517
|
+
const sha = c.sha;
|
|
518
|
+
const cands = repoCandidates(c, scope);
|
|
519
|
+
if (!cands.length)
|
|
520
|
+
return {};
|
|
521
|
+
const hits = (await Promise.all(cands.map((r) => lookupCommit(r.repo, sha, r.watch, remote)))).filter((h) => Boolean(h));
|
|
522
|
+
if (hits.length === 1)
|
|
523
|
+
return { hit: hits[0] };
|
|
524
|
+
if (hits.length > 1)
|
|
525
|
+
return {};
|
|
526
|
+
return c.keyworded && cands.length === 1 ? { plainUrl: commitUrl(cands[0].repo, sha), repo: cands[0].repo } : {};
|
|
527
|
+
}
|
|
528
|
+
function resolveRun(c, absolute) {
|
|
529
|
+
const run = get('runs', c.id);
|
|
530
|
+
if (!run)
|
|
531
|
+
return {};
|
|
532
|
+
const url = runUrl(run.id, absolute);
|
|
533
|
+
return { hit: { title: runTitle(run), ...(url ? { url } : {}), id: '', kind: 'run' } };
|
|
534
|
+
}
|
|
535
|
+
// ---------- writing ----------
|
|
536
|
+
function mrkdwnText(s) {
|
|
537
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\|/g, '/');
|
|
538
|
+
}
|
|
539
|
+
function mdUrl(u) {
|
|
540
|
+
return u.replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\s/g, '%20');
|
|
541
|
+
}
|
|
542
|
+
function labelOf(h) {
|
|
543
|
+
return h.id ? `${h.title} (${h.id})` : h.title;
|
|
544
|
+
}
|
|
545
|
+
function link(label, url, format) {
|
|
546
|
+
if (!url || format === 'text')
|
|
547
|
+
return label;
|
|
548
|
+
return format === 'mrkdwn' ? `<${url}|${mrkdwnText(label)}>` : `[${label}](${mdUrl(url)})`;
|
|
549
|
+
}
|
|
550
|
+
/** True when `given` is the address `canon` with a fragment, a query or a longer path added: the same host and the same pull request or issue. */
|
|
551
|
+
function continuesAddress(given, canon) {
|
|
552
|
+
if (!given || !canon || given === canon || !given.startsWith(canon))
|
|
553
|
+
return false;
|
|
554
|
+
return /^[#/?]/.test(given.slice(canon.length));
|
|
555
|
+
}
|
|
556
|
+
function apply(text, cands, results, format, trust) {
|
|
557
|
+
let out = '';
|
|
558
|
+
let cursor = 0;
|
|
559
|
+
cands.forEach((c, i) => {
|
|
560
|
+
const r = results[i];
|
|
561
|
+
if (c.start < cursor)
|
|
562
|
+
return;
|
|
563
|
+
if (r.hit) {
|
|
564
|
+
let start = c.start;
|
|
565
|
+
let end = c.end;
|
|
566
|
+
if (c.mode === 'plain') {
|
|
567
|
+
const title = r.hit.title;
|
|
568
|
+
// "PR #12: Fix cart total rounding": the writer already gave the title. One title, one link.
|
|
569
|
+
const after = new RegExp(`^\\s*[:\\-–—,]?\\s*["“'‘]?${escapeRe(title)}["”'’]?(?![\\w])`, 'i').exec(text.slice(end));
|
|
570
|
+
if (after)
|
|
571
|
+
end += after[0].length;
|
|
572
|
+
else if (!c.keyworded && text[end] === ')') {
|
|
573
|
+
// "Fix cart total rounding (#12)": the title stands before the number.
|
|
574
|
+
const before = new RegExp(`(?:^|[\\s"“'‘])(${escapeRe(title)})\\s*\\($`, 'id').exec(text.slice(cursor, start));
|
|
575
|
+
if (before?.indices?.[1]) {
|
|
576
|
+
start = cursor + before.indices[1][0];
|
|
577
|
+
end += 1;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
// The address the lookup gave comes first: a link the text carried is the writer's, and it keeps only when the lookup has none (KAT-380).
|
|
582
|
+
// A bare address that goes on from the lookup's own (a comment's fragment, the Files tab) keeps what it adds, so it opens that place.
|
|
583
|
+
const url = c.mode !== 'mdlink' && continuesAddress(c.givenUrl, r.hit.url) ? c.givenUrl : (r.hit.url ?? c.givenUrl);
|
|
584
|
+
if (url && url === r.hit.url && format !== 'text')
|
|
585
|
+
trust?.add(url);
|
|
586
|
+
out += text.slice(cursor, start) + link(labelOf(r.hit), url, format);
|
|
587
|
+
cursor = end;
|
|
588
|
+
}
|
|
589
|
+
else if (r.plainUrl && c.mode === 'plain' && format !== 'text') {
|
|
590
|
+
trust?.add(r.plainUrl);
|
|
591
|
+
out += text.slice(cursor, c.start) + link(c.text, r.plainUrl, format);
|
|
592
|
+
cursor = c.end;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
return out + text.slice(cursor);
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* True when the text names a repo other than `repo` ("issue #9 in acme/other"). A plain link built from the
|
|
599
|
+
* dot's own repo would then point at the wrong place, so the number stays as written. Sentences with a
|
|
600
|
+
* slash such as "pass/fail" also stop the link, which is the safe side.
|
|
601
|
+
*/
|
|
602
|
+
function namesOtherRepo(text, repo) {
|
|
603
|
+
const bare = text.replace(/https?:\/\/\S+/g, ' ').replace(/\x60[^\x60]*\x60/g, ' ');
|
|
604
|
+
for (const m of bare.matchAll(/(?<![\w/.-])([A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*)(?![\w/-])/g))
|
|
605
|
+
if (m[1].toLowerCase() !== repo)
|
|
606
|
+
return true;
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
/** Drops plain links the text contradicts. */
|
|
610
|
+
function guardPlain(text, results) {
|
|
611
|
+
return results.map((r) => (r.plainUrl && r.repo && namesOtherRepo(text, r.repo) ? {} : r));
|
|
612
|
+
}
|
|
613
|
+
// ---------- entry points ----------
|
|
614
|
+
/** Quick test: false means the text cannot hold a reference, so callers can skip the (async) rewrite. */
|
|
615
|
+
export function mayHaveRefs(text) {
|
|
616
|
+
return MAYBE_REF.test(text);
|
|
617
|
+
}
|
|
618
|
+
const MAYBE_REF = /#\d|(?<![\w-])(?=[0-9a-f]*\d)[0-9a-f]{7,40}(?![\w-])|[A-Z][A-Z0-9]{1,9}-\d|\b(?=[0-9a-z]*\d)[0-9a-z]{18}\b|\/(?:pull|issues|browse|issue)\/|\bPR\s+\d|pull\s+request\s+\d/i;
|
|
619
|
+
function scopeFor(opts) {
|
|
620
|
+
const watches = opts.dotId ? [get('watches', opts.dotId)].filter((w) => Boolean(w)) : list('watches').filter((w) => !w.archived);
|
|
621
|
+
let index = opts.index;
|
|
622
|
+
const lazy = {
|
|
623
|
+
watches,
|
|
624
|
+
get index() {
|
|
625
|
+
index ??= localIndex(watches);
|
|
626
|
+
return index;
|
|
627
|
+
},
|
|
628
|
+
get prefixes() {
|
|
629
|
+
const set = new Set(watches.flatMap(trackerPrefixes));
|
|
630
|
+
for (const k of this.index.tickets.keys())
|
|
631
|
+
set.add(k.split('-')[0]);
|
|
632
|
+
return set;
|
|
633
|
+
},
|
|
634
|
+
};
|
|
635
|
+
return lazy;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Rewrites the bare references in `text` into titled links. Looks titles up in the cache, GitHub, the
|
|
639
|
+
* connected trackers, and the stored runs, in that order. Never throws: on any failure the text comes back
|
|
640
|
+
* unchanged.
|
|
641
|
+
*/
|
|
642
|
+
export async function renderRefs(text, opts = {}) {
|
|
643
|
+
if (!text || !MAYBE_REF.test(text))
|
|
644
|
+
return text;
|
|
645
|
+
try {
|
|
646
|
+
const format = opts.format ?? 'markdown';
|
|
647
|
+
const absolute = opts.absolute ?? format !== 'markdown';
|
|
648
|
+
const scope = scopeFor(opts);
|
|
649
|
+
const cands = collect(text, scope);
|
|
650
|
+
if (!cands.length)
|
|
651
|
+
return text;
|
|
652
|
+
const results = await Promise.all(cands.map((c) => c.kind === 'num'
|
|
653
|
+
? resolveNumber(c, scope, true)
|
|
654
|
+
: c.kind === 'ticket'
|
|
655
|
+
? resolveTicket(c, scope, true)
|
|
656
|
+
: c.kind === 'commit'
|
|
657
|
+
? resolveCommit(c, scope, true)
|
|
658
|
+
: resolveRun(c, absolute)));
|
|
659
|
+
return apply(text, cands, guardPlain(text, results), format, opts.trust);
|
|
660
|
+
}
|
|
661
|
+
catch (err) {
|
|
662
|
+
log.warn(`refs: could not title the references: ${err instanceof Error ? err.message : String(err)}`);
|
|
663
|
+
return text;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* The same rewrite without a network call: the cache, the runs in `opts.index`, and the stored runs. For
|
|
668
|
+
* code that cannot wait, such as the Activity list.
|
|
669
|
+
*/
|
|
670
|
+
export function renderRefsSync(text, opts = {}) {
|
|
671
|
+
if (!text || !MAYBE_REF.test(text))
|
|
672
|
+
return text;
|
|
673
|
+
try {
|
|
674
|
+
const format = opts.format ?? 'text';
|
|
675
|
+
const absolute = opts.absolute ?? format !== 'markdown';
|
|
676
|
+
const scope = scopeFor(opts);
|
|
677
|
+
const cands = collect(text, scope);
|
|
678
|
+
if (!cands.length)
|
|
679
|
+
return text;
|
|
680
|
+
const results = cands.map((c) => {
|
|
681
|
+
if (c.kind === 'run')
|
|
682
|
+
return resolveRun(c, absolute);
|
|
683
|
+
if (c.kind === 'commit') {
|
|
684
|
+
const hits = repoCandidates(c, scope)
|
|
685
|
+
.map((r) => cacheGet(`commit:${r.repo}@${c.sha}`))
|
|
686
|
+
.filter((h) => Boolean(h));
|
|
687
|
+
return hits.length === 1 ? { hit: hits[0] } : {};
|
|
688
|
+
}
|
|
689
|
+
if (c.kind === 'ticket') {
|
|
690
|
+
const key = c.key.toUpperCase();
|
|
691
|
+
const hit = cacheGet(ticketCacheKey(key, ownersOf(key, scope))) ?? scope.index.tickets.get(key);
|
|
692
|
+
return hit ? { hit } : {};
|
|
693
|
+
}
|
|
694
|
+
const repos = repoCandidates(c, scope);
|
|
695
|
+
const hits = repos
|
|
696
|
+
.map((r) => cacheGet(`num:${r.repo}#${c.n}:${c.want ?? ''}`) ?? scope.index.prs.get(`${r.repo}#${c.n}`))
|
|
697
|
+
.filter((h) => Boolean(h));
|
|
698
|
+
return hits.length === 1 ? { hit: hits[0] } : {};
|
|
699
|
+
});
|
|
700
|
+
return apply(text, cands, results, format);
|
|
701
|
+
}
|
|
702
|
+
catch (err) {
|
|
703
|
+
log.warn(`refs: could not title the references: ${err instanceof Error ? err.message : String(err)}`);
|
|
704
|
+
return text;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* The title and link of one reference written as `KAT-295` or `owner/name#12`, or undefined when nobody knows it.
|
|
709
|
+
* The same lookup renderRefs uses (cache, GitHub, the dot's tracker, the stored runs), for code that needs the
|
|
710
|
+
* title as data, such as the Inbox. Never throws.
|
|
711
|
+
*/
|
|
712
|
+
export async function lookupRef(text, opts = {}) {
|
|
713
|
+
const t = text.trim();
|
|
714
|
+
if (!t || !MAYBE_REF.test(t))
|
|
715
|
+
return undefined;
|
|
716
|
+
try {
|
|
717
|
+
const scope = scopeFor(opts);
|
|
718
|
+
const c = collect(t, scope).find((x) => x.start === 0 && x.end === t.length);
|
|
719
|
+
if (!c || c.kind === 'run')
|
|
720
|
+
return undefined;
|
|
721
|
+
if (opts.want && c.kind === 'num')
|
|
722
|
+
c.want = opts.want;
|
|
723
|
+
const remote = opts.remote ?? true;
|
|
724
|
+
const res = c.kind === 'num'
|
|
725
|
+
? await resolveNumber(c, scope, remote)
|
|
726
|
+
: c.kind === 'commit'
|
|
727
|
+
? await resolveCommit(c, scope, remote)
|
|
728
|
+
: await resolveTicket(c, scope, remote);
|
|
729
|
+
return res.hit;
|
|
730
|
+
}
|
|
731
|
+
catch (err) {
|
|
732
|
+
log.warn(`refs: could not look up ${t}: ${err instanceof Error ? err.message : String(err)}`);
|
|
733
|
+
return undefined;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* The titles of the PRs and tickets that the stored runs of one dot (or of every live dot) were about. Reading them costs a
|
|
738
|
+
* pass over recent runs, so a caller that looks up many references builds it once and passes it as `index`.
|
|
739
|
+
*/
|
|
740
|
+
export function storedRefIndex(dotId) {
|
|
741
|
+
const watches = dotId ? [get('watches', dotId)].filter((w) => Boolean(w)) : list('watches').filter((w) => !w.archived);
|
|
742
|
+
return localIndex(watches);
|
|
743
|
+
}
|
|
744
|
+
/** The web address of a commit on the GitHub the server talks to. */
|
|
745
|
+
export function commitUrl(repo, sha) {
|
|
746
|
+
return `${webBase()}/${repo}/commit/${sha}`;
|
|
747
|
+
}
|
|
748
|
+
/** A verdict with its headline as plain text and its summary as Markdown, references titled. */
|
|
749
|
+
export async function renderVerdictRefs(verdict, opts = {}) {
|
|
750
|
+
const [headline, summary] = await Promise.all([
|
|
751
|
+
renderRefs(verdict.headline, { ...opts, format: 'text' }),
|
|
752
|
+
renderRefs(verdict.summary, { ...opts, format: 'markdown' }),
|
|
753
|
+
]);
|
|
754
|
+
return { ...verdict, headline, summary };
|
|
755
|
+
}
|
|
756
|
+
//# sourceMappingURL=refs.js.map
|