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
|
@@ -0,0 +1,781 @@
|
|
|
1
|
+
// Composed views on the server (KAT-366, docs/CHAT-UI.md "Composed views"). The model calls `compose_view` with a view spec.
|
|
2
|
+
// This module checks the spec (src/view-spec.ts), binds it to the tool results of the turn, and streams it.
|
|
3
|
+
//
|
|
4
|
+
// - Data comes from tool results only. Each lookup result of a turn gets an id (r1, r2, ...), and the model refers to it. The
|
|
5
|
+
// server holds the full rows; the model sees the columns, a count, and a sample. A record node (runs, pulls, ...) gets the block
|
|
6
|
+
// the server builds from the result, the same block the lookup tool shows alone, so the model never writes a row, a link, or an
|
|
7
|
+
// approval id. A table, stats, or chart node reads a dataset: the rows of a result run through the steps of src/view-compute.ts.
|
|
8
|
+
// - The server runs the pipelines once to check them (a column that is not there drops the dataset and its nodes, and the model is
|
|
9
|
+
// told why). The client runs them again in a Web Worker for what it draws. Nothing computed here reaches an action: a button of a
|
|
10
|
+
// block calls the route of that block, and the route reads the server's own records.
|
|
11
|
+
// - The view streams as a `loading` view block, then one `view_node` event per node of the root, then the finished block, which
|
|
12
|
+
// replaces the rest. A node that has not arrived shows as a placeholder.
|
|
13
|
+
import { get } from '../db.js';
|
|
14
|
+
import { config } from '../config.js';
|
|
15
|
+
import { parseChatBlock } from '../chat-blocks.js';
|
|
16
|
+
import { isObj } from '../chat-parse-util.js';
|
|
17
|
+
import { computeView } from '../view-compute.js';
|
|
18
|
+
import { MAX_CELL_TEXT, MAX_SOURCE_CELLS, MAX_SOURCE_COLUMNS, MAX_SOURCE_ROWS, VIEW_RECORD_TYPES, fieldsUsed, isResultId, parseViewHead, parseViewNode, parseViewTree, rawNodes, viewBlocks, viewKinds, viewNodes, viewSpecGuide, } from '../view-spec.js';
|
|
19
|
+
import { blocksFromToolResult } from './chat-tool-blocks.js';
|
|
20
|
+
export const COMPOSE_VIEW_TOOL = 'compose_view';
|
|
21
|
+
/** Tools whose result a view may read: the lookups, the stats tools, and the test results. */
|
|
22
|
+
export const VIEW_SOURCE_TOOLS = [
|
|
23
|
+
'list_runs',
|
|
24
|
+
'runs_in_progress',
|
|
25
|
+
'open_prs',
|
|
26
|
+
'pending_approvals',
|
|
27
|
+
'recent_defects',
|
|
28
|
+
'probe_status',
|
|
29
|
+
'get_memory',
|
|
30
|
+
'list_tickets_reviewed',
|
|
31
|
+
'get_ticket',
|
|
32
|
+
'list_cases',
|
|
33
|
+
'pass_rate',
|
|
34
|
+
'flaky_by_spec',
|
|
35
|
+
'test_results',
|
|
36
|
+
'release_call',
|
|
37
|
+
];
|
|
38
|
+
/** The results of one chat turn, by id. */
|
|
39
|
+
export class ResultRegistry {
|
|
40
|
+
entries = new Map();
|
|
41
|
+
add(name, input, value, blocks) {
|
|
42
|
+
const id = `r${this.entries.size + 1}`;
|
|
43
|
+
const entry = { id, name, input, value, blocks: [...blocks, ...(value && typeof value === 'object' ? (viewBlocksHeld.get(value) ?? []) : [])] };
|
|
44
|
+
this.entries.set(id, entry);
|
|
45
|
+
return entry;
|
|
46
|
+
}
|
|
47
|
+
get(id) {
|
|
48
|
+
return this.entries.get(id);
|
|
49
|
+
}
|
|
50
|
+
ids() {
|
|
51
|
+
return [...this.entries.keys()];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const rowsHeld = new WeakMap();
|
|
55
|
+
const refusedHeld = new WeakMap();
|
|
56
|
+
const viewBlocksHeld = new WeakMap();
|
|
57
|
+
const idsHeld = new WeakMap();
|
|
58
|
+
/** Hands the full rows of a result to a view without putting them in what the model reads. */
|
|
59
|
+
export function holdRows(value, table) {
|
|
60
|
+
rowsHeld.set(value, table);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
/** Hands blocks the call built (the cards of get_ticket) to a view without streaming them alone. */
|
|
64
|
+
export function holdViewBlocks(value, blocks) {
|
|
65
|
+
viewBlocksHeld.set(value, blocks);
|
|
66
|
+
return value;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The dot a result was looked up for when that is not the dot the chat is scoped to, else undefined. A composed view binds only the
|
|
70
|
+
* results of the chat's own dot: a lookup with an explicit `dotId` of another dot (test_results, list_runs, ...) would show that
|
|
71
|
+
* dot's data in this chat. A chat with no dot (the overview) has no dot to protect.
|
|
72
|
+
*/
|
|
73
|
+
export function foreignDotOf(input, watch) {
|
|
74
|
+
if (!watch)
|
|
75
|
+
return undefined;
|
|
76
|
+
const id = typeof input.dotId === 'string' ? input.dotId.trim() : '';
|
|
77
|
+
return id && id !== watch.id ? id : undefined;
|
|
78
|
+
}
|
|
79
|
+
/** The line the model reads for a lookup result that no view may read, and why. */
|
|
80
|
+
export function foreignSourceLine(otherDot, watch) {
|
|
81
|
+
const other = get('watches', otherDot)?.name ?? otherDot;
|
|
82
|
+
return `Not a view source: this result is for dot ${other}, and this chat is for dot ${watch.name}. A view reads only results for ${watch.name}, so look the data up again without dotId (or with ${watch.id}) before you compose the view.`;
|
|
83
|
+
}
|
|
84
|
+
/** Marks a result as one that no view may read, with the line the model reads (see foreignSourceLine). */
|
|
85
|
+
export function refuseResult(value, line) {
|
|
86
|
+
if (value && typeof value === 'object')
|
|
87
|
+
refusedHeld.set(value, line);
|
|
88
|
+
}
|
|
89
|
+
export function tagResult(value, id) {
|
|
90
|
+
if (value && typeof value === 'object')
|
|
91
|
+
idsHeld.set(value, id);
|
|
92
|
+
}
|
|
93
|
+
export function resultIdOf(value) {
|
|
94
|
+
return value && typeof value === 'object' ? idsHeld.get(value) : undefined;
|
|
95
|
+
}
|
|
96
|
+
/** The rows a result holds for a view: the held table, or the first list of objects in the value. */
|
|
97
|
+
export function rowsOfResult(value) {
|
|
98
|
+
return value && typeof value === 'object' ? rowsHeld.get(value) : undefined;
|
|
99
|
+
}
|
|
100
|
+
/** What the model reads for a result: the value with its id, so it can name the result in compose_view. */
|
|
101
|
+
export function modelFacing(value) {
|
|
102
|
+
const refused = value && typeof value === 'object' ? refusedHeld.get(value) : undefined;
|
|
103
|
+
if (refused)
|
|
104
|
+
return Array.isArray(value) ? { viewSource: refused, rows: value } : { ...value, viewSource: refused };
|
|
105
|
+
const id = resultIdOf(value);
|
|
106
|
+
if (id && value && typeof value === 'object')
|
|
107
|
+
return Array.isArray(value) ? { resultId: id, rows: value } : { resultId: id, ...value };
|
|
108
|
+
if (isObj(value) && value.repeated === true && 'result' in value)
|
|
109
|
+
return { ...value, result: modelFacing(value.result) };
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
// ---------- Rows of a result, as a table ----------
|
|
113
|
+
const LIST_KEYS = ['rows', 'runs', 'prs', 'approvals', 'defects', 'probes', 'items', 'results', 'cases'];
|
|
114
|
+
function listOf(value) {
|
|
115
|
+
if (Array.isArray(value))
|
|
116
|
+
return value.filter(isObj);
|
|
117
|
+
if (!isObj(value))
|
|
118
|
+
return [];
|
|
119
|
+
for (const k of LIST_KEYS)
|
|
120
|
+
if (Array.isArray(value[k]) && value[k].some(isObj))
|
|
121
|
+
return value[k].filter(isObj);
|
|
122
|
+
for (const v of Object.values(value))
|
|
123
|
+
if (Array.isArray(v) && v.some(isObj))
|
|
124
|
+
return v.filter(isObj);
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
/** An object as dotted keys, two levels deep. A list of plain values becomes one text; a list of objects is left out. */
|
|
128
|
+
function flatten(o, prefix = '', depth = 0, out = {}) {
|
|
129
|
+
for (const [k, v] of Object.entries(o)) {
|
|
130
|
+
const key = prefix ? `${prefix}.${k}` : k;
|
|
131
|
+
if (v === null || v === undefined)
|
|
132
|
+
out[key] = null;
|
|
133
|
+
else if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')
|
|
134
|
+
out[key] = typeof v === 'number' && !Number.isFinite(v) ? null : v;
|
|
135
|
+
else if (Array.isArray(v)) {
|
|
136
|
+
if (v.every((x) => x === null || typeof x !== 'object'))
|
|
137
|
+
out[key] = v.join(', ');
|
|
138
|
+
}
|
|
139
|
+
else if (isObj(v) && depth < 2)
|
|
140
|
+
flatten(v, key, depth + 1, out);
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
144
|
+
/** The columns of a result a view can read, in the order they first show. */
|
|
145
|
+
export function columnsOfResult(value) {
|
|
146
|
+
const held = rowsOfResult(value);
|
|
147
|
+
if (held)
|
|
148
|
+
return held.columns;
|
|
149
|
+
const cols = [];
|
|
150
|
+
for (const row of listOf(value).slice(0, 200))
|
|
151
|
+
for (const k of Object.keys(flatten(row)))
|
|
152
|
+
if (!cols.includes(k))
|
|
153
|
+
cols.push(k);
|
|
154
|
+
return cols;
|
|
155
|
+
}
|
|
156
|
+
/** The result cut to the columns the view uses (all of them when `fields` is null), and to the rows and cells the client takes. */
|
|
157
|
+
function sourceTable(value, fields) {
|
|
158
|
+
const held = rowsOfResult(value);
|
|
159
|
+
let columns;
|
|
160
|
+
let rows;
|
|
161
|
+
if (held) {
|
|
162
|
+
columns = held.columns.filter((c) => !fields || fields.has(c));
|
|
163
|
+
const at = columns.map((c) => held.columns.indexOf(c));
|
|
164
|
+
rows = held.rows.map((r) => at.map((i) => r[i] ?? null));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const flat = listOf(value).map((r) => flatten(r));
|
|
168
|
+
columns = columnsOfResult(value).filter((c) => !fields || fields.has(c));
|
|
169
|
+
rows = flat.map((r) => columns.map((c) => r[c] ?? null));
|
|
170
|
+
}
|
|
171
|
+
columns = columns.slice(0, MAX_SOURCE_COLUMNS);
|
|
172
|
+
// A long text (a test title) is cut as the client cuts it, so a stored view is no bigger than the client keeps.
|
|
173
|
+
rows = rows.map((r) => r.slice(0, columns.length).map((c) => (typeof c === 'string' && c.length > MAX_CELL_TEXT ? `${c.slice(0, MAX_CELL_TEXT - 1)}…` : c)));
|
|
174
|
+
const keep = Math.min(MAX_SOURCE_ROWS, Math.floor(MAX_SOURCE_CELLS / Math.max(1, columns.length)));
|
|
175
|
+
const more = (held?.more ?? 0) + Math.max(0, rows.length - keep);
|
|
176
|
+
return { columns, rows: rows.slice(0, keep), ...(more > 0 ? { more } : {}) };
|
|
177
|
+
}
|
|
178
|
+
// ---------- What the model is told about a result ----------
|
|
179
|
+
/** The part of a tool result the model reads for the rows a view holds: the columns, a count, and a few rows. */
|
|
180
|
+
export function rowsSummary(table, total) {
|
|
181
|
+
const sample = table.rows.slice(0, 5).map((r) => Object.fromEntries(table.columns.map((c, i) => [c, r[i] ?? null])));
|
|
182
|
+
return { count: total, rowsHeld: table.rows.length, columns: table.columns, sample };
|
|
183
|
+
}
|
|
184
|
+
const tick = () => new Promise((resolve) => setImmediate(resolve));
|
|
185
|
+
function dotOf(entry, host) {
|
|
186
|
+
const id = typeof entry.input.dotId === 'string' ? entry.input.dotId : undefined;
|
|
187
|
+
return (id ? get('watches', id) : undefined) ?? host.watch;
|
|
188
|
+
}
|
|
189
|
+
/** The blocks a result can show: the ones its call built, then what the lookup tool would show for it. */
|
|
190
|
+
function blocksOf(entry, host) {
|
|
191
|
+
const dot = dotOf(entry, host);
|
|
192
|
+
// A view that names a ticket review asks for it, so the stored review of get_ticket shows.
|
|
193
|
+
const built = blocksFromToolResult(entry.name, entry.value, { ...entry.input, context: false }, { ...(dot ? { dot } : {}), showTicketReview: true });
|
|
194
|
+
return [...entry.blocks, ...built];
|
|
195
|
+
}
|
|
196
|
+
/** A block cut to `limit` rows, the rest counted in `more`. */
|
|
197
|
+
function trim(block, limit) {
|
|
198
|
+
if (!limit)
|
|
199
|
+
return block;
|
|
200
|
+
const cut = (rows) => [rows.slice(0, limit), Math.max(0, rows.length - limit)];
|
|
201
|
+
const more = (n) => (n > 0 ? { more: (block.more ?? 0) + n } : {});
|
|
202
|
+
switch (block.kind) {
|
|
203
|
+
case 'runs': {
|
|
204
|
+
const [runs, n] = cut(block.runs);
|
|
205
|
+
return { ...block, runs, ...more(n) };
|
|
206
|
+
}
|
|
207
|
+
case 'pulls': {
|
|
208
|
+
const [pulls, n] = cut(block.pulls);
|
|
209
|
+
return { ...block, pulls, ...more(n) };
|
|
210
|
+
}
|
|
211
|
+
case 'approvals': {
|
|
212
|
+
const [approvals, n] = cut(block.approvals);
|
|
213
|
+
return { ...block, approvals, ...more(n) };
|
|
214
|
+
}
|
|
215
|
+
case 'defects': {
|
|
216
|
+
const [defects, n] = cut(block.defects);
|
|
217
|
+
return { ...block, defects, ...more(n) };
|
|
218
|
+
}
|
|
219
|
+
case 'probes': {
|
|
220
|
+
const [probes, n] = cut(block.probes);
|
|
221
|
+
return { ...block, probes, ...more(n) };
|
|
222
|
+
}
|
|
223
|
+
case 'memory': {
|
|
224
|
+
const [items, n] = cut(block.items);
|
|
225
|
+
return { ...block, items, ...more(n) };
|
|
226
|
+
}
|
|
227
|
+
case 'test_cases': {
|
|
228
|
+
const [cases, n] = cut(block.cases);
|
|
229
|
+
return { ...block, cases, ...more(n) };
|
|
230
|
+
}
|
|
231
|
+
case 'cards': {
|
|
232
|
+
const [cards, n] = cut(block.cards);
|
|
233
|
+
return { ...block, cards, ...more(n) };
|
|
234
|
+
}
|
|
235
|
+
case 'table': {
|
|
236
|
+
const [rows, n] = cut(block.rows);
|
|
237
|
+
return { ...block, rows, ...more(n) };
|
|
238
|
+
}
|
|
239
|
+
default:
|
|
240
|
+
return block;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/** Binds the record, triage, and `from` nodes of a parsed tree to blocks. A node that cannot be bound is dropped and noted. */
|
|
244
|
+
function bindTree(root, host, notes) {
|
|
245
|
+
const bind = (node) => {
|
|
246
|
+
switch (node.type) {
|
|
247
|
+
case 'column':
|
|
248
|
+
case 'row': {
|
|
249
|
+
const children = node.children.map(bind).filter((n) => n !== null);
|
|
250
|
+
return children.length || node === root ? { ...node, children } : null;
|
|
251
|
+
}
|
|
252
|
+
case 'section': {
|
|
253
|
+
const children = node.children.map(bind).filter((n) => n !== null);
|
|
254
|
+
return children.length ? { ...node, children } : null;
|
|
255
|
+
}
|
|
256
|
+
case 'tabs': {
|
|
257
|
+
const tabs = node.tabs.map((t) => ({ ...t, children: t.children.map(bind).filter((n) => n !== null) })).filter((t) => t.children.length);
|
|
258
|
+
return tabs.length ? { ...node, tabs } : null;
|
|
259
|
+
}
|
|
260
|
+
case 'text':
|
|
261
|
+
return node;
|
|
262
|
+
case 'triage': {
|
|
263
|
+
const parsed = host.triage ? parseChatBlock(host.triage(node.window)) : undefined;
|
|
264
|
+
if (!parsed?.ok || parsed.block.kind !== 'triage') {
|
|
265
|
+
notes.push('triage: the failure triage could not be built');
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
return { ...node, block: node.title ? { ...parsed.block, title: node.title } : parsed.block };
|
|
269
|
+
}
|
|
270
|
+
case 'table':
|
|
271
|
+
case 'stats':
|
|
272
|
+
case 'chart':
|
|
273
|
+
if (!node.from)
|
|
274
|
+
return node;
|
|
275
|
+
return bindFrom(node, node.type, node.from);
|
|
276
|
+
default:
|
|
277
|
+
return bindFrom(node, node.type, node.from ?? '');
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
const bindFrom = (node, kind, from) => {
|
|
281
|
+
const entry = host.results.get(from);
|
|
282
|
+
if (!entry) {
|
|
283
|
+
notes.push(`${kind}: there is no result ${from} in this turn. The results are ${host.results.ids().join(', ') || 'none yet'}`);
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const foreign = foreignDotOf(entry.input, host.watch);
|
|
287
|
+
if (foreign) {
|
|
288
|
+
notes.push(`${kind}: ${from} (${entry.name}) is for dot ${foreign}, not the dot of this chat, so it is not shown`);
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
const nth = 'nth' in node && typeof node.nth === 'number' ? node.nth : 0;
|
|
292
|
+
const block = blocksOf(entry, host).filter((b) => b.kind === kind)[nth];
|
|
293
|
+
if (!block) {
|
|
294
|
+
notes.push(`${kind}: ${from} (${entry.name}) has no ${kind} block to show${nth ? ` at ${nth}` : ''}`);
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
const limited = trim(block, 'limit' in node && typeof node.limit === 'number' ? node.limit : undefined);
|
|
298
|
+
const title = 'title' in node && typeof node.title === 'string' ? node.title : undefined;
|
|
299
|
+
return { ...node, block: title ? { ...limited, title } : limited };
|
|
300
|
+
};
|
|
301
|
+
return bind(root);
|
|
302
|
+
}
|
|
303
|
+
/** Drops the nodes that read a dataset that failed, or a column the dataset does not have. */
|
|
304
|
+
function checkNodes(root, out, notes) {
|
|
305
|
+
const check = (node) => {
|
|
306
|
+
switch (node.type) {
|
|
307
|
+
case 'column':
|
|
308
|
+
case 'row': {
|
|
309
|
+
const children = node.children.map(check).filter((n) => n !== null);
|
|
310
|
+
return children.length || node === root ? { ...node, children } : null;
|
|
311
|
+
}
|
|
312
|
+
case 'section': {
|
|
313
|
+
const children = node.children.map(check).filter((n) => n !== null);
|
|
314
|
+
return children.length ? { ...node, children } : null;
|
|
315
|
+
}
|
|
316
|
+
case 'tabs': {
|
|
317
|
+
const tabs = node.tabs
|
|
318
|
+
.map((t) => ({ ...t, children: t.children.map(check).filter((n) => n !== null) }))
|
|
319
|
+
.filter((t) => t.children.length);
|
|
320
|
+
return tabs.length ? { ...node, tabs } : null;
|
|
321
|
+
}
|
|
322
|
+
case 'chart':
|
|
323
|
+
case 'table': {
|
|
324
|
+
if (!node.data)
|
|
325
|
+
return node;
|
|
326
|
+
const table = Object.hasOwn(out.datasets, node.data) ? out.datasets[node.data] : undefined;
|
|
327
|
+
if (!table) {
|
|
328
|
+
notes.push(`${node.type}: dataset ${node.data} could not be computed: ${out.errors.datasets[node.data] ?? 'unknown'}`);
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
// A chart or a table of no rows says nothing, so the view leaves it out and the answer says so in words.
|
|
332
|
+
if (!table.rows.length) {
|
|
333
|
+
notes.push(`${node.type}: dataset ${node.data} has no rows`);
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
const wanted = node.type === 'chart' ? [node.x ?? '', ...(node.series ?? []).map((s) => s.field)] : (node.columns ?? []).map((c) => c.field);
|
|
337
|
+
const missing = wanted.find((f) => f && !table.columns.includes(f));
|
|
338
|
+
if (missing) {
|
|
339
|
+
notes.push(`${node.type}: dataset ${node.data} has no column "${missing}". It has ${table.columns.join(', ')}`);
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
return node;
|
|
343
|
+
}
|
|
344
|
+
default:
|
|
345
|
+
return node;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
return check(root);
|
|
349
|
+
}
|
|
350
|
+
/** What the model learns from the server's own run of the view: the vars, and the first rows of each dataset. */
|
|
351
|
+
function factsOf(out) {
|
|
352
|
+
const vars = Object.fromEntries(Object.entries(out.vars).map(([k, v]) => [k, v.text]));
|
|
353
|
+
const datasets = Object.fromEntries(Object.entries(out.datasets).map(([k, t]) => [
|
|
354
|
+
k,
|
|
355
|
+
{ columns: t.columns, rows: t.rows.slice(0, 8), ...(t.rows.length > 8 ? { moreRows: t.rows.length - 8 } : {}) },
|
|
356
|
+
]));
|
|
357
|
+
return { ...(Object.keys(vars).length ? { vars } : {}), ...(Object.keys(datasets).length ? { datasets } : {}) };
|
|
358
|
+
}
|
|
359
|
+
const LINK_TEXT = 'The full view is in the chat';
|
|
360
|
+
/**
|
|
361
|
+
* The line a Slack thread or a call carries in place of the view: where it opens. Undefined in the app chat, which shows it. With the
|
|
362
|
+
* id of the stored reply the link opens that answer, not only the chat of the dot. Slack has no link without a public address, like every
|
|
363
|
+
* other link from the app, so the line says where to look.
|
|
364
|
+
*/
|
|
365
|
+
export function viewLinkLine(watch, channel, messageId) {
|
|
366
|
+
if (channel !== 'slack' && channel !== 'call')
|
|
367
|
+
return undefined;
|
|
368
|
+
const path = `#/chat${watch ? `/${encodeURIComponent(watch.id)}` : ''}${messageId ? `?m=${encodeURIComponent(messageId)}` : ''}`;
|
|
369
|
+
if (channel === 'call')
|
|
370
|
+
return `[${LINK_TEXT}](${path})`;
|
|
371
|
+
const base = config.publicUrl?.replace(/\/$/, '');
|
|
372
|
+
return base ? `[${LINK_TEXT}](${base}/${path})` : `${LINK_TEXT} of ${watch ? watch.name : 'the dot'}, in the localdost app.`;
|
|
373
|
+
}
|
|
374
|
+
const LEAF_TYPES = [...VIEW_RECORD_TYPES, 'triage', 'table', 'stats', 'chart'];
|
|
375
|
+
/**
|
|
376
|
+
* A failed spec falls back to the blocks it holds, then to text (docs/CHAT-UI.md, Composed views: Fallback). Every node of a block kind
|
|
377
|
+
* that reads a tool result by id comes back as the block the server builds from it: the record kinds, the triage, and a stats, chart, or
|
|
378
|
+
* table with `from`. A node built from a dataset has no block of its own, so it is left out.
|
|
379
|
+
*/
|
|
380
|
+
function fallbackBlocks(raw, host) {
|
|
381
|
+
const out = [];
|
|
382
|
+
const notes = [];
|
|
383
|
+
for (const n of rawNodes(raw)) {
|
|
384
|
+
if (!LEAF_TYPES.includes(String(n.type)))
|
|
385
|
+
continue;
|
|
386
|
+
const node = parseViewNode(n, {});
|
|
387
|
+
if (!node)
|
|
388
|
+
continue;
|
|
389
|
+
const bound = bindTree(node, host, notes);
|
|
390
|
+
if (bound && 'block' in bound && bound.block)
|
|
391
|
+
out.push(bound.block);
|
|
392
|
+
}
|
|
393
|
+
return out;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* The rows each dataset reads, cut to the columns the view uses (`fields` null keeps them all), and the datasets that can be built. A
|
|
397
|
+
* dataset whose result is not there is dropped with a note, and so is one that reads a dropped dataset.
|
|
398
|
+
*/
|
|
399
|
+
function prepare(raw, host, fields, notes) {
|
|
400
|
+
const sources = {};
|
|
401
|
+
const datasets = {};
|
|
402
|
+
const { results } = host;
|
|
403
|
+
for (const [name, d] of Object.entries(raw ?? {})) {
|
|
404
|
+
if (isResultId(d.from)) {
|
|
405
|
+
const entry = results.get(d.from);
|
|
406
|
+
if (!entry) {
|
|
407
|
+
notes.push(`dataset ${name} dropped: there is no result ${d.from} in this turn. The results are ${results.ids().join(', ') || 'none yet'}`);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
const foreign = foreignDotOf(entry.input, host.watch);
|
|
411
|
+
if (foreign) {
|
|
412
|
+
notes.push(`dataset ${name} dropped: result ${d.from} (${entry.name}) is for dot ${foreign}, not the dot of this chat`);
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
if (!Object.hasOwn(sources, d.from))
|
|
416
|
+
sources[d.from] = sourceTable(entry.value, fields);
|
|
417
|
+
}
|
|
418
|
+
else if (!Object.hasOwn(datasets, d.from)) {
|
|
419
|
+
notes.push(`dataset ${name} dropped: ${d.from} was dropped`);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
datasets[name] = d;
|
|
423
|
+
}
|
|
424
|
+
return { sources, datasets };
|
|
425
|
+
}
|
|
426
|
+
/** Runs the pipelines once, on the server. What fails is dropped and noted; the client runs them again for what it draws. */
|
|
427
|
+
function runPipelines(prep, rawVars, tzOffsetMin, notes) {
|
|
428
|
+
const out = computeView({ sources: prep.sources, datasets: prep.datasets, tzOffsetMin, ...(rawVars ? { vars: rawVars } : {}) });
|
|
429
|
+
for (const [name, why] of Object.entries(out.errors.datasets))
|
|
430
|
+
notes.push(`dataset ${name} dropped: ${why}`);
|
|
431
|
+
for (const [name, why] of Object.entries(out.errors.vars))
|
|
432
|
+
notes.push(`var ${name} dropped: ${why}`);
|
|
433
|
+
const datasets = Object.fromEntries(Object.entries(prep.datasets).filter(([name]) => !Object.hasOwn(out.errors.datasets, name)));
|
|
434
|
+
const vars = Object.fromEntries(Object.entries(rawVars ?? {}).filter(([k]) => !Object.hasOwn(out.errors.vars, k)));
|
|
435
|
+
// Only the rows of the results a surviving dataset reads go to the client.
|
|
436
|
+
const wanted = new Set(Object.values(datasets).map((d) => d.from));
|
|
437
|
+
const sources = Object.fromEntries(Object.entries(prep.sources).filter(([id]) => wanted.has(id)));
|
|
438
|
+
return { out, datasets, vars, sources };
|
|
439
|
+
}
|
|
440
|
+
/** The results a view reads whose rows were cut: the source holds fewer rows than the tool found, so counts and rates cover part of the data. */
|
|
441
|
+
export function partialSources(sources, results) {
|
|
442
|
+
return Object.entries(sources)
|
|
443
|
+
.filter(([, t]) => (t.more ?? 0) > 0)
|
|
444
|
+
.map(([id, t]) => ({ result: id, ...(results.get(id) ? { tool: results.get(id).name } : {}), rows: t.rows.length, more: t.more }));
|
|
445
|
+
}
|
|
446
|
+
// ---------- Streaming while the model writes the call ----------
|
|
447
|
+
/** Characters of a call input the stream reads before it gives up. The finished view does not depend on it. */
|
|
448
|
+
const MAX_STREAM_CHARS = 96_000;
|
|
449
|
+
function tryParse(text) {
|
|
450
|
+
try {
|
|
451
|
+
return JSON.parse(text);
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
return undefined;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Reads the JSON of a compose_view input as far as it has come, without waiting for the end. It finds the complete top-level values
|
|
459
|
+
* of `title`, `datasets`, and `vars`, and each child of `root.children` the moment its closing brace arrives. Nothing is run or
|
|
460
|
+
* evaluated: this only walks the brackets, and a half-written node is left for the next chunk.
|
|
461
|
+
*/
|
|
462
|
+
export function scanViewInput(text) {
|
|
463
|
+
const head = {};
|
|
464
|
+
const children = [];
|
|
465
|
+
let rootStarted = false;
|
|
466
|
+
const stack = [];
|
|
467
|
+
const starts = [];
|
|
468
|
+
let inString = false;
|
|
469
|
+
let escaped = false;
|
|
470
|
+
let strStart = 0;
|
|
471
|
+
for (let i = 0; i < text.length; i++) {
|
|
472
|
+
const c = text[i];
|
|
473
|
+
if (inString) {
|
|
474
|
+
if (escaped)
|
|
475
|
+
escaped = false;
|
|
476
|
+
else if (c === '\\')
|
|
477
|
+
escaped = true;
|
|
478
|
+
else if (c === '"') {
|
|
479
|
+
inString = false;
|
|
480
|
+
const top = stack[stack.length - 1];
|
|
481
|
+
if (top?.open === '{' && top.expectKey) {
|
|
482
|
+
const key = tryParse(text.slice(strStart, i + 1));
|
|
483
|
+
if (typeof key === 'string')
|
|
484
|
+
top.key = key;
|
|
485
|
+
else
|
|
486
|
+
delete top.key;
|
|
487
|
+
top.expectKey = false;
|
|
488
|
+
}
|
|
489
|
+
else if (stack.length === 1 && top?.open === '{' && top.key === 'title')
|
|
490
|
+
head.title = tryParse(text.slice(strStart, i + 1));
|
|
491
|
+
}
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (c === '"') {
|
|
495
|
+
inString = true;
|
|
496
|
+
strStart = i;
|
|
497
|
+
}
|
|
498
|
+
else if (c === '{' || c === '[') {
|
|
499
|
+
stack.push({ open: c, expectKey: c === '{' });
|
|
500
|
+
starts.push(i);
|
|
501
|
+
if (stack.length === 2 && c === '{' && stack[0].key === 'root')
|
|
502
|
+
rootStarted = true;
|
|
503
|
+
}
|
|
504
|
+
else if (c === '}' || c === ']') {
|
|
505
|
+
const closed = stack.pop();
|
|
506
|
+
const start = starts.pop();
|
|
507
|
+
if (!closed || start === undefined)
|
|
508
|
+
break;
|
|
509
|
+
const key = stack[0]?.key;
|
|
510
|
+
if (stack.length === 1 && key && (key === 'datasets' || key === 'vars'))
|
|
511
|
+
head[key] = tryParse(text.slice(start, i + 1));
|
|
512
|
+
else if (stack.length === 3 && closed.open === '{' && key === 'root' && stack[1].key === 'children' && stack[2].open === '[')
|
|
513
|
+
children.push(tryParse(text.slice(start, i + 1)));
|
|
514
|
+
}
|
|
515
|
+
else if (c === ',') {
|
|
516
|
+
const top = stack[stack.length - 1];
|
|
517
|
+
if (top?.open === '{')
|
|
518
|
+
top.expectKey = true;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return { head, rootStarted, children };
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Sends a view to the client while the model is still writing the compose_view call: the shell once the first node of the root has
|
|
525
|
+
* closed, then each node as its closing brace arrives (docs/CHAT-UI.md, Composed views: Streaming). Each node goes through the checks of
|
|
526
|
+
* the finished view: the registry, the binding to a tool result, and the run of the pipelines. It is a preview. When the call ends,
|
|
527
|
+
* composeView checks the whole spec, and the finished block replaces what streamed, with the same id, so a node the full check drops
|
|
528
|
+
* disappears then. Anything this class cannot read, or reads wrong, only means fewer nodes stream; it never changes what is stored.
|
|
529
|
+
*/
|
|
530
|
+
export class ViewStream {
|
|
531
|
+
host;
|
|
532
|
+
/** The id of the view block, set when the shell has been sent. */
|
|
533
|
+
id;
|
|
534
|
+
text = '';
|
|
535
|
+
done = 0;
|
|
536
|
+
sent = 0;
|
|
537
|
+
stopped = false;
|
|
538
|
+
claimed = false;
|
|
539
|
+
finalInput;
|
|
540
|
+
ready;
|
|
541
|
+
constructor(host) {
|
|
542
|
+
this.host = host;
|
|
543
|
+
}
|
|
544
|
+
/** True once the shell has been sent. */
|
|
545
|
+
get started() {
|
|
546
|
+
return this.id !== undefined;
|
|
547
|
+
}
|
|
548
|
+
/** Nodes sent so far. */
|
|
549
|
+
get nodes() {
|
|
550
|
+
return this.sent;
|
|
551
|
+
}
|
|
552
|
+
/** A piece of the input, as it arrives. Never throws: a stream that cannot go on stops, and the finished view is unaffected. */
|
|
553
|
+
feed(chunk) {
|
|
554
|
+
if (this.stopped)
|
|
555
|
+
return;
|
|
556
|
+
this.text += chunk;
|
|
557
|
+
if (this.text.length > MAX_STREAM_CHARS) {
|
|
558
|
+
this.stopped = true;
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
// Nothing closes without a closing bracket, so a piece with none changes nothing and the walk is skipped.
|
|
562
|
+
if (!/[}\]]/.test(chunk))
|
|
563
|
+
return;
|
|
564
|
+
try {
|
|
565
|
+
this.advance();
|
|
566
|
+
}
|
|
567
|
+
catch {
|
|
568
|
+
this.stopped = true;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/** The input is complete. */
|
|
572
|
+
end() {
|
|
573
|
+
if (this.stopped)
|
|
574
|
+
return;
|
|
575
|
+
try {
|
|
576
|
+
this.advance();
|
|
577
|
+
this.finalInput = JSON.stringify(JSON.parse(this.text));
|
|
578
|
+
}
|
|
579
|
+
catch {
|
|
580
|
+
this.stopped = true;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
/** True when the finished call carries the input this stream read, and nothing else has claimed the stream. */
|
|
584
|
+
claim(input) {
|
|
585
|
+
if (this.claimed || this.finalInput === undefined)
|
|
586
|
+
return false;
|
|
587
|
+
try {
|
|
588
|
+
this.claimed = JSON.stringify(input) === this.finalInput;
|
|
589
|
+
}
|
|
590
|
+
catch {
|
|
591
|
+
this.claimed = false;
|
|
592
|
+
}
|
|
593
|
+
return this.claimed;
|
|
594
|
+
}
|
|
595
|
+
/** Takes a streamed view away from the client: the call failed, or no call came to finish it. */
|
|
596
|
+
drop() {
|
|
597
|
+
if (this.id === undefined)
|
|
598
|
+
return;
|
|
599
|
+
const id = this.id;
|
|
600
|
+
this.id = undefined;
|
|
601
|
+
this.host.emit({ type: 'view_drop', id });
|
|
602
|
+
}
|
|
603
|
+
/** The turn is over: a stream no call claimed has no finished view to replace it, so it goes. */
|
|
604
|
+
close() {
|
|
605
|
+
if (!this.claimed)
|
|
606
|
+
this.drop();
|
|
607
|
+
this.stopped = true;
|
|
608
|
+
}
|
|
609
|
+
advance() {
|
|
610
|
+
const scan = scanViewInput(this.text);
|
|
611
|
+
if (!scan.rootStarted || scan.children.length <= this.done)
|
|
612
|
+
return;
|
|
613
|
+
if (!this.started && !this.begin(scan.head)) {
|
|
614
|
+
this.stopped = true;
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
for (; this.done < scan.children.length; this.done++)
|
|
618
|
+
this.send(scan.children[this.done]);
|
|
619
|
+
}
|
|
620
|
+
/** Sends the shell: the title, the datasets the tool results can feed, and their rows. False when it cannot be sent. */
|
|
621
|
+
begin(head) {
|
|
622
|
+
if (this.host.channel === 'call')
|
|
623
|
+
return false;
|
|
624
|
+
const notes = [];
|
|
625
|
+
const h = parseViewHead(head);
|
|
626
|
+
// Every column goes in the shell: which ones the nodes read is not known yet. The finished view cuts them down.
|
|
627
|
+
const prep = prepare(h.datasets, this.host, null, notes);
|
|
628
|
+
const tz = this.host.tzOffsetMin ?? new Date().getTimezoneOffset();
|
|
629
|
+
const computed = runPipelines(prep, h.vars, tz, notes);
|
|
630
|
+
const id = this.host.nextId();
|
|
631
|
+
const shell = parseChatBlock({
|
|
632
|
+
id,
|
|
633
|
+
kind: 'view',
|
|
634
|
+
tool: COMPOSE_VIEW_TOOL,
|
|
635
|
+
...(this.host.watch ? { dotId: this.host.watch.id } : {}),
|
|
636
|
+
state: 'loading',
|
|
637
|
+
view: {
|
|
638
|
+
v: 1,
|
|
639
|
+
...(h.title ? { title: h.title } : {}),
|
|
640
|
+
tzOffsetMin: tz,
|
|
641
|
+
...(Object.keys(computed.sources).length ? { sources: computed.sources } : {}),
|
|
642
|
+
...(Object.keys(computed.datasets).length ? { datasets: computed.datasets } : {}),
|
|
643
|
+
...(Object.keys(computed.vars).length ? { vars: computed.vars } : {}),
|
|
644
|
+
root: { type: 'column', children: [] },
|
|
645
|
+
},
|
|
646
|
+
});
|
|
647
|
+
if (!shell.ok)
|
|
648
|
+
return false;
|
|
649
|
+
this.id = id;
|
|
650
|
+
this.ready = { datasets: computed.datasets, vars: computed.vars, out: computed.out };
|
|
651
|
+
this.host.emit({ type: 'block', block: shell.block });
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
/** Checks one closed child of the root, binds it to its tool result, and sends it. A child that fails any check is skipped. */
|
|
655
|
+
send(raw) {
|
|
656
|
+
if (!this.ready || this.id === undefined || raw === undefined)
|
|
657
|
+
return;
|
|
658
|
+
const notes = [];
|
|
659
|
+
const node = parseViewNode(raw, { datasets: this.ready.datasets, vars: this.ready.vars });
|
|
660
|
+
if (!node)
|
|
661
|
+
return;
|
|
662
|
+
const wrapper = { type: 'column', children: [node] };
|
|
663
|
+
const bound = bindTree(wrapper, this.host, notes);
|
|
664
|
+
const checked = bound ? checkNodes(bound, this.ready.out, notes) : null;
|
|
665
|
+
const child = checked && checked.type === 'column' ? checked.children[0] : undefined;
|
|
666
|
+
if (!child)
|
|
667
|
+
return;
|
|
668
|
+
this.host.emit({ type: 'view_node', id: this.id, at: this.sent++, node: child });
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
// ---------- compose_view ----------
|
|
672
|
+
/**
|
|
673
|
+
* Runs compose_view: checks the spec, binds it, streams it, and answers the model with what showed and what was dropped. A spec that
|
|
674
|
+
* fails shows the blocks it holds, and when it holds none the answer is an error and the chat answers in text.
|
|
675
|
+
*/
|
|
676
|
+
export async function composeView(rawInput, host) {
|
|
677
|
+
const input = isObj(rawInput) ? rawInput : {};
|
|
678
|
+
// The spec is the input itself, or sits under `spec` for a model that wraps it.
|
|
679
|
+
const raw = isObj(input.spec) && input.root === undefined ? input.spec : input;
|
|
680
|
+
const parsed = parseViewTree(raw);
|
|
681
|
+
const notes = [...parsed.notes];
|
|
682
|
+
const failWith = (reason) => {
|
|
683
|
+
// Nodes that streamed while the model wrote the call were a preview of a view that cannot be built.
|
|
684
|
+
host.stream?.drop();
|
|
685
|
+
const blocks = host.channel === 'call' ? [] : fallbackBlocks(raw, host);
|
|
686
|
+
if (blocks.length) {
|
|
687
|
+
for (const b of blocks)
|
|
688
|
+
host.finish({ ...b, tool: COMPOSE_VIEW_TOOL });
|
|
689
|
+
return {
|
|
690
|
+
ok: true,
|
|
691
|
+
fallback: true,
|
|
692
|
+
shown: blocks.map((b) => b.kind),
|
|
693
|
+
dropped: notes,
|
|
694
|
+
note: `The view could not be built (${reason}), so the blocks it holds show as they are. Write one or two sentences.`,
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
return { error: `The view could not be built: ${reason}. Answer in text instead.`, dropped: notes };
|
|
698
|
+
};
|
|
699
|
+
if (!parsed.ok)
|
|
700
|
+
return failWith(parsed.reason);
|
|
701
|
+
const view = parsed.view;
|
|
702
|
+
// 1. Blocks for the record nodes.
|
|
703
|
+
const bound = bindTree(view.root, host, notes);
|
|
704
|
+
if (!bound || bound.type !== 'column')
|
|
705
|
+
return failWith('no node could be bound to a result');
|
|
706
|
+
// 2. The rows each dataset reads, cut to the columns the view uses. A table that names no columns shows every column of its
|
|
707
|
+
// dataset, so its sources keep all of theirs.
|
|
708
|
+
const used = fieldsUsed({ ...view, root: bound });
|
|
709
|
+
const allColumns = viewNodes(bound).some((n) => n.type === 'table' && n.data && !n.columns);
|
|
710
|
+
const prep = prepare(view.datasets, host, allColumns ? null : used, notes);
|
|
711
|
+
// 3. The server runs the pipelines once to check them.
|
|
712
|
+
const tzOffsetMin = host.tzOffsetMin ?? new Date().getTimezoneOffset();
|
|
713
|
+
const { out, datasets, vars, sources } = runPipelines(prep, view.vars, tzOffsetMin, notes);
|
|
714
|
+
const checked = checkNodes(bound, out, notes);
|
|
715
|
+
if (!checked || checked.type !== 'column' || !checked.children.length)
|
|
716
|
+
return failWith('no node had data to show');
|
|
717
|
+
const full = {
|
|
718
|
+
v: 1,
|
|
719
|
+
...(view.title ? { title: view.title } : {}),
|
|
720
|
+
tzOffsetMin,
|
|
721
|
+
...(Object.keys(sources).length ? { sources } : {}),
|
|
722
|
+
...(Object.keys(datasets).length ? { datasets } : {}),
|
|
723
|
+
...(Object.keys(vars).length ? { vars } : {}),
|
|
724
|
+
root: { type: 'column', children: checked.children },
|
|
725
|
+
total: checked.children.length,
|
|
726
|
+
};
|
|
727
|
+
// 4. Stream it: the shell with the datasets, each node of the root, then the finished block, which replaces the rest. A view whose
|
|
728
|
+
// nodes already went out while the model wrote the call has its shell and nodes on the client, so only the finished block goes.
|
|
729
|
+
const streamed = host.stream?.started === true;
|
|
730
|
+
const id = streamed ? host.stream.id : host.nextId();
|
|
731
|
+
const base = { id, kind: 'view', tool: COMPOSE_VIEW_TOOL, ...(host.watch ? { dotId: host.watch.id } : {}) };
|
|
732
|
+
const quiet = host.channel === 'call';
|
|
733
|
+
if (!quiet && !streamed) {
|
|
734
|
+
const shell = parseChatBlock({ ...base, state: 'loading', view: { ...full, root: { type: 'column', children: [] } } });
|
|
735
|
+
if (shell.ok)
|
|
736
|
+
host.emit({ type: 'block', block: shell.block });
|
|
737
|
+
for (const [at, node] of checked.children.entries()) {
|
|
738
|
+
await tick();
|
|
739
|
+
host.emit({ type: 'view_node', id, at, node });
|
|
740
|
+
}
|
|
741
|
+
await tick();
|
|
742
|
+
}
|
|
743
|
+
const finished = host.finish({ ...base, state: 'ready', view: full }, { quiet });
|
|
744
|
+
if (!finished) {
|
|
745
|
+
host.stream?.drop();
|
|
746
|
+
return { error: 'The view could not be shown.', dropped: notes };
|
|
747
|
+
}
|
|
748
|
+
host.hide(viewBlocks(full).map((b) => b.id));
|
|
749
|
+
const link = viewLinkLine(host.watch, host.channel, host.messageId);
|
|
750
|
+
if (link)
|
|
751
|
+
host.line(link);
|
|
752
|
+
// A source cut to its first rows makes every count and rate cover part of the data. The view says so, and so does the model's note.
|
|
753
|
+
const partial = partialSources(sources, host.results);
|
|
754
|
+
const cut = partial.map((p) => `${p.result} holds ${p.rows.toLocaleString('en-US')} of ${(p.rows + p.more).toLocaleString('en-US')} rows`).join(', ');
|
|
755
|
+
return {
|
|
756
|
+
ok: true,
|
|
757
|
+
shown: viewKinds(full),
|
|
758
|
+
...(notes.length ? { dropped: notes } : {}),
|
|
759
|
+
...(partial.length ? { partial } : {}),
|
|
760
|
+
...factsOf(out),
|
|
761
|
+
note: partial.length
|
|
762
|
+
? `The view is in the answer with a notice that its numbers cover part of the data: ${cut}. Say so in your sentence and give no total as a fact. Or call the lookup again with fewer days, one branch, or one spec, and compose the view again. Write one or two sentences of judgement, and do not repeat what the view shows.`
|
|
763
|
+
: 'The view is in the answer. Write one or two sentences of judgement with the key number, and do not repeat what the view shows.',
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
/** The tool definition of compose_view. The description is the format, written from the registry in src/view-spec.ts. */
|
|
767
|
+
export const COMPOSE_VIEW_DEFINITION = {
|
|
768
|
+
name: COMPOSE_VIEW_TOOL,
|
|
769
|
+
description: viewSpecGuide(),
|
|
770
|
+
input_schema: {
|
|
771
|
+
type: 'object',
|
|
772
|
+
properties: {
|
|
773
|
+
title: { type: 'string', description: 'A short title for the view.' },
|
|
774
|
+
datasets: { type: 'object', description: 'Named tables: { name: { from: "r1", steps: [...] } }.' },
|
|
775
|
+
vars: { type: 'object', description: 'Named values out of a dataset, for {name} marks in text.' },
|
|
776
|
+
root: { type: 'object', description: 'A column node: { "type": "column", "children": [ ...nodes ] }.' },
|
|
777
|
+
},
|
|
778
|
+
required: ['root'],
|
|
779
|
+
},
|
|
780
|
+
};
|
|
781
|
+
//# sourceMappingURL=chat-views.js.map
|