toolroll 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1113 -0
- package/THIRD_PARTY_NOTICES.md +449 -0
- package/dist/accent-colors.d.ts +48 -0
- package/dist/accent-colors.js +122 -0
- package/dist/action-ledger.d.ts +26 -0
- package/dist/action-ledger.js +75 -0
- package/dist/agent-fence.d.ts +42 -0
- package/dist/agent-fence.js +183 -0
- package/dist/agentconfig.d.ts +216 -0
- package/dist/agentconfig.js +454 -0
- package/dist/api-tokens.d.ts +16 -0
- package/dist/api-tokens.js +27 -0
- package/dist/approval-policy.d.ts +69 -0
- package/dist/approval-policy.js +137 -0
- package/dist/approval-rules-ui.d.ts +25 -0
- package/dist/approval-rules-ui.js +39 -0
- package/dist/assignment-adapters.d.ts +180 -0
- package/dist/assignment-adapters.js +239 -0
- package/dist/assignment-brief.d.ts +71 -0
- package/dist/assignment-brief.js +129 -0
- package/dist/assignment-delivery.d.ts +56 -0
- package/dist/assignment-delivery.js +160 -0
- package/dist/assignment-presentation.d.ts +26 -0
- package/dist/assignment-presentation.js +80 -0
- package/dist/assignment-status.d.ts +62 -0
- package/dist/assignment-status.js +152 -0
- package/dist/assignment-ui.d.ts +71 -0
- package/dist/assignment-ui.js +103 -0
- package/dist/assignment.d.ts +222 -0
- package/dist/assignment.js +399 -0
- package/dist/attest.d.ts +56 -0
- package/dist/attest.js +153 -0
- package/dist/backend.d.ts +97 -0
- package/dist/backend.js +166 -0
- package/dist/backup-ui.d.ts +22 -0
- package/dist/backup-ui.js +59 -0
- package/dist/backup.d.ts +84 -0
- package/dist/backup.js +421 -0
- package/dist/beads.d.ts +34 -0
- package/dist/beads.js +135 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +22 -0
- package/dist/board.d.ts +150 -0
- package/dist/board.js +210 -0
- package/dist/boot-identity.d.ts +63 -0
- package/dist/boot-identity.js +99 -0
- package/dist/browser/THIRD_PARTY_NOTICES.txt +2295 -0
- package/dist/browser/workspace.css +4 -0
- package/dist/browser/workspace.js +225 -0
- package/dist/browser-crew.d.ts +11 -0
- package/dist/browser-crew.js +50 -0
- package/dist/browser-shell.d.ts +8 -0
- package/dist/browser-shell.js +60 -0
- package/dist/browser-workspace.d.ts +780 -0
- package/dist/browser-workspace.js +47 -0
- package/dist/budget-alerts.d.ts +19 -0
- package/dist/budget-alerts.js +46 -0
- package/dist/builder.d.ts +370 -0
- package/dist/builder.js +3262 -0
- package/dist/capscan.d.ts +35 -0
- package/dist/capscan.js +113 -0
- package/dist/chat-acceptance.d.ts +71 -0
- package/dist/chat-acceptance.js +120 -0
- package/dist/chat-actions.d.ts +265 -0
- package/dist/chat-actions.js +1273 -0
- package/dist/chat-channel.d.ts +109 -0
- package/dist/chat-channel.js +652 -0
- package/dist/chat-continuity.d.ts +32 -0
- package/dist/chat-continuity.js +317 -0
- package/dist/chat-controls.d.ts +113 -0
- package/dist/chat-controls.js +53 -0
- package/dist/chat-delivery-state.d.ts +159 -0
- package/dist/chat-delivery-state.js +309 -0
- package/dist/chat-delivery.d.ts +38 -0
- package/dist/chat-delivery.js +693 -0
- package/dist/chat-display.d.ts +1 -0
- package/dist/chat-display.js +18 -0
- package/dist/chat-evidence.d.ts +123 -0
- package/dist/chat-evidence.js +207 -0
- package/dist/chat-flow.d.ts +44 -0
- package/dist/chat-flow.js +215 -0
- package/dist/chat-inbox.d.ts +57 -0
- package/dist/chat-inbox.js +123 -0
- package/dist/chat-polish.d.ts +16 -0
- package/dist/chat-polish.js +135 -0
- package/dist/chat-review.d.ts +46 -0
- package/dist/chat-review.js +98 -0
- package/dist/chat-rooms.d.ts +123 -0
- package/dist/chat-rooms.js +216 -0
- package/dist/chat-task-actions.d.ts +44 -0
- package/dist/chat-task-actions.js +79 -0
- package/dist/check-progress.d.ts +51 -0
- package/dist/check-progress.js +290 -0
- package/dist/child-database.d.ts +12 -0
- package/dist/child-database.js +30 -0
- package/dist/claim.d.ts +688 -0
- package/dist/claim.js +1740 -0
- package/dist/cli.d.ts +137 -0
- package/dist/cli.js +1461 -0
- package/dist/codex-limits.d.ts +15 -0
- package/dist/codex-limits.js +145 -0
- package/dist/coding-context.d.ts +55 -0
- package/dist/coding-context.js +92 -0
- package/dist/coding-handoff.d.ts +57 -0
- package/dist/coding-handoff.js +277 -0
- package/dist/coding-provider.d.ts +72 -0
- package/dist/coding-provider.js +424 -0
- package/dist/coding-shipping-ui.d.ts +4 -0
- package/dist/coding-shipping-ui.js +12 -0
- package/dist/coding-types.d.ts +62 -0
- package/dist/coding-types.js +1 -0
- package/dist/coding-ui.d.ts +17 -0
- package/dist/coding-ui.js +364 -0
- package/dist/coding-update.d.ts +15 -0
- package/dist/coding-update.js +149 -0
- package/dist/coding-workspace.d.ts +124 -0
- package/dist/coding-workspace.js +768 -0
- package/dist/container-state.d.ts +5 -0
- package/dist/container-state.js +62 -0
- package/dist/containment.d.ts +197 -0
- package/dist/containment.js +559 -0
- package/dist/contest.d.ts +318 -0
- package/dist/contest.js +753 -0
- package/dist/control-setup.d.ts +35 -0
- package/dist/control-setup.js +40 -0
- package/dist/control-ui.d.ts +29 -0
- package/dist/control-ui.js +53 -0
- package/dist/controller-service.d.ts +1 -0
- package/dist/controller-service.js +19 -0
- package/dist/controller-supervisor.d.ts +30 -0
- package/dist/controller-supervisor.js +104 -0
- package/dist/converse.d.ts +304 -0
- package/dist/converse.js +849 -0
- package/dist/coordinator-proposals.d.ts +29 -0
- package/dist/coordinator-proposals.js +137 -0
- package/dist/coordinator.d.ts +186 -0
- package/dist/coordinator.js +447 -0
- package/dist/credentials-ui.d.ts +25 -0
- package/dist/credentials-ui.js +48 -0
- package/dist/daemon.d.ts +209 -0
- package/dist/daemon.js +604 -0
- package/dist/decision.d.ts +120 -0
- package/dist/decision.js +388 -0
- package/dist/demo.d.ts +55 -0
- package/dist/demo.js +992 -0
- package/dist/desktop-access.d.ts +28 -0
- package/dist/desktop-access.js +88 -0
- package/dist/desktop-bundle.d.ts +16 -0
- package/dist/desktop-bundle.js +74 -0
- package/dist/desktop-host.d.ts +54 -0
- package/dist/desktop-host.js +508 -0
- package/dist/desktop-update-gate.d.ts +12 -0
- package/dist/desktop-update-gate.js +91 -0
- package/dist/desktop-update-recovery.d.ts +14 -0
- package/dist/desktop-update-recovery.js +243 -0
- package/dist/desktop-update.d.ts +110 -0
- package/dist/desktop-update.js +740 -0
- package/dist/discord-api.d.ts +20 -0
- package/dist/discord-api.js +138 -0
- package/dist/discord-chat.d.ts +16 -0
- package/dist/discord-chat.js +381 -0
- package/dist/discord-settings.d.ts +7 -0
- package/dist/discord-settings.js +75 -0
- package/dist/discord.d.ts +10 -0
- package/dist/discord.js +169 -0
- package/dist/discover.d.ts +75 -0
- package/dist/discover.js +150 -0
- package/dist/dispatch.d.ts +100 -0
- package/dist/dispatch.js +311 -0
- package/dist/dispose.d.ts +161 -0
- package/dist/dispose.js +803 -0
- package/dist/email-settings.d.ts +34 -0
- package/dist/email-settings.js +50 -0
- package/dist/envelope.d.ts +47 -0
- package/dist/envelope.js +105 -0
- package/dist/evidence-pack.d.ts +185 -0
- package/dist/evidence-pack.js +258 -0
- package/dist/evidence.d.ts +345 -0
- package/dist/evidence.js +782 -0
- package/dist/exec.d.ts +285 -0
- package/dist/exec.js +1841 -0
- package/dist/exhaustion.d.ts +85 -0
- package/dist/exhaustion.js +141 -0
- package/dist/export-ui.d.ts +4 -0
- package/dist/export-ui.js +17 -0
- package/dist/export.d.ts +48 -0
- package/dist/export.js +305 -0
- package/dist/flow-actions.d.ts +77 -0
- package/dist/flow-actions.js +203 -0
- package/dist/flow-code.d.ts +50 -0
- package/dist/flow-code.js +159 -0
- package/dist/flow-draft.d.ts +38 -0
- package/dist/flow-draft.js +80 -0
- package/dist/flow-engine.d.ts +66 -0
- package/dist/flow-engine.js +416 -0
- package/dist/flow-insights.d.ts +95 -0
- package/dist/flow-insights.js +149 -0
- package/dist/flow-live.d.ts +24 -0
- package/dist/flow-live.js +150 -0
- package/dist/flow-people.d.ts +24 -0
- package/dist/flow-people.js +91 -0
- package/dist/flow-replies.d.ts +48 -0
- package/dist/flow-replies.js +113 -0
- package/dist/flow-scripts.d.ts +38 -0
- package/dist/flow-scripts.js +73 -0
- package/dist/flow-secrets.d.ts +13 -0
- package/dist/flow-secrets.js +45 -0
- package/dist/flow-sort.d.ts +82 -0
- package/dist/flow-sort.js +153 -0
- package/dist/flow-steps.d.ts +40 -0
- package/dist/flow-steps.js +408 -0
- package/dist/flow-triggers.d.ts +244 -0
- package/dist/flow-triggers.js +959 -0
- package/dist/flows-ui.d.ts +20 -0
- package/dist/flows-ui.js +175 -0
- package/dist/flows.d.ts +229 -0
- package/dist/flows.js +968 -0
- package/dist/fonts.d.ts +19 -0
- package/dist/fonts.js +19 -0
- package/dist/gaps.d.ts +35 -0
- package/dist/gaps.js +101 -0
- package/dist/gate-failure.d.ts +40 -0
- package/dist/gate-failure.js +66 -0
- package/dist/git.d.ts +54 -0
- package/dist/git.js +94 -0
- package/dist/google-mail.d.ts +58 -0
- package/dist/google-mail.js +151 -0
- package/dist/grant.d.ts +136 -0
- package/dist/grant.js +238 -0
- package/dist/graph.d.ts +164 -0
- package/dist/graph.js +383 -0
- package/dist/guides.d.ts +22 -0
- package/dist/guides.js +363 -0
- package/dist/held.d.ts +150 -0
- package/dist/held.js +799 -0
- package/dist/invoke.d.ts +112 -0
- package/dist/invoke.js +780 -0
- package/dist/issues.d.ts +41 -0
- package/dist/issues.js +131 -0
- package/dist/job-object-helper.ps1 +252 -0
- package/dist/jsonl-discriminants.d.ts +11 -0
- package/dist/jsonl-discriminants.js +93 -0
- package/dist/keys.d.ts +104 -0
- package/dist/keys.js +229 -0
- package/dist/kits-ui.d.ts +17 -0
- package/dist/kits-ui.js +46 -0
- package/dist/kits.d.ts +86 -0
- package/dist/kits.js +215 -0
- package/dist/knowledge-cli.d.ts +101 -0
- package/dist/knowledge-cli.js +92 -0
- package/dist/knowledge-ui.d.ts +24 -0
- package/dist/knowledge-ui.js +40 -0
- package/dist/lead-context.d.ts +8 -0
- package/dist/lead-context.js +56 -0
- package/dist/lead-follow.d.ts +22 -0
- package/dist/lead-follow.js +167 -0
- package/dist/lead-status.d.ts +75 -0
- package/dist/lead-status.js +285 -0
- package/dist/ledger-chain.d.ts +46 -0
- package/dist/ledger-chain.js +187 -0
- package/dist/ledger-csv.d.ts +4 -0
- package/dist/ledger-csv.js +11 -0
- package/dist/ledger-view.d.ts +24 -0
- package/dist/ledger-view.js +58 -0
- package/dist/limits-ui.d.ts +26 -0
- package/dist/limits-ui.js +67 -0
- package/dist/link.d.ts +72 -0
- package/dist/link.js +217 -0
- package/dist/live.d.ts +96 -0
- package/dist/live.js +366 -0
- package/dist/liveness.d.ts +30 -0
- package/dist/liveness.js +42 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +25 -0
- package/dist/mailbox.d.ts +57 -0
- package/dist/mailbox.js +150 -0
- package/dist/maintenance.d.ts +11 -0
- package/dist/maintenance.js +35 -0
- package/dist/mate-cli.d.ts +52 -0
- package/dist/mate-cli.js +345 -0
- package/dist/mate-contract.d.ts +10 -0
- package/dist/mate-contract.js +30 -0
- package/dist/mate-doors.d.ts +69 -0
- package/dist/mate-doors.js +548 -0
- package/dist/mate-progress.d.ts +29 -0
- package/dist/mate-progress.js +121 -0
- package/dist/mate-tools.d.ts +94 -0
- package/dist/mate-tools.js +1878 -0
- package/dist/mate.d.ts +92 -0
- package/dist/mate.js +435 -0
- package/dist/mcp-connect.d.ts +103 -0
- package/dist/mcp-connect.js +252 -0
- package/dist/mcp.d.ts +27 -0
- package/dist/mcp.js +651 -0
- package/dist/memory-cli.d.ts +466 -0
- package/dist/memory-cli.js +111 -0
- package/dist/memory-pass.d.ts +160 -0
- package/dist/memory-pass.js +409 -0
- package/dist/metrics.d.ts +3 -0
- package/dist/metrics.js +56 -0
- package/dist/mobile-viewport.d.ts +3 -0
- package/dist/mobile-viewport.js +37 -0
- package/dist/model-catalog.d.ts +118 -0
- package/dist/model-catalog.js +376 -0
- package/dist/models-cli.d.ts +102 -0
- package/dist/models-cli.js +66 -0
- package/dist/models-ui.d.ts +34 -0
- package/dist/models-ui.js +68 -0
- package/dist/modes.d.ts +80 -0
- package/dist/modes.js +182 -0
- package/dist/monitoring-settings.d.ts +44 -0
- package/dist/monitoring-settings.js +173 -0
- package/dist/monitoring-ui.d.ts +20 -0
- package/dist/monitoring-ui.js +51 -0
- package/dist/monitoring.d.ts +34 -0
- package/dist/monitoring.js +221 -0
- package/dist/names.d.ts +67 -0
- package/dist/names.js +102 -0
- package/dist/observations.d.ts +40 -0
- package/dist/observations.js +211 -0
- package/dist/oidc.d.ts +71 -0
- package/dist/oidc.js +182 -0
- package/dist/onboard.d.ts +108 -0
- package/dist/onboard.js +325 -0
- package/dist/openrouter-models.d.ts +30 -0
- package/dist/openrouter-models.js +120 -0
- package/dist/operate.d.ts +118 -0
- package/dist/operate.js +11321 -0
- package/dist/peek-cli.d.ts +97 -0
- package/dist/peek-cli.js +215 -0
- package/dist/peek.d.ts +134 -0
- package/dist/peek.js +578 -0
- package/dist/phase-routing.d.ts +307 -0
- package/dist/phase-routing.js +658 -0
- package/dist/plan-auto.d.ts +14 -0
- package/dist/plan-auto.js +92 -0
- package/dist/plan.d.ts +186 -0
- package/dist/plan.js +401 -0
- package/dist/planner-source.d.ts +251 -0
- package/dist/planner-source.js +460 -0
- package/dist/planner.d.ts +75 -0
- package/dist/planner.js +992 -0
- package/dist/policy-ui.d.ts +20 -0
- package/dist/policy-ui.js +41 -0
- package/dist/policy.d.ts +111 -0
- package/dist/policy.js +231 -0
- package/dist/prepared-evidence.d.ts +16 -0
- package/dist/prepared-evidence.js +96 -0
- package/dist/pricing.d.ts +45 -0
- package/dist/pricing.js +77 -0
- package/dist/principal.d.ts +42 -0
- package/dist/principal.js +82 -0
- package/dist/probe.d.ts +46 -0
- package/dist/probe.js +79 -0
- package/dist/process-custody.d.ts +17 -0
- package/dist/process-custody.js +91 -0
- package/dist/process-liveness.d.ts +10 -0
- package/dist/process-liveness.js +81 -0
- package/dist/process-recovery-anchor.d.ts +75 -0
- package/dist/process-recovery-anchor.js +188 -0
- package/dist/process-recovery-coalition.d.ts +25 -0
- package/dist/process-recovery-coalition.js +105 -0
- package/dist/process-recovery-eligibility.d.ts +178 -0
- package/dist/process-recovery-eligibility.js +170 -0
- package/dist/process-recovery-native.d.ts +172 -0
- package/dist/process-recovery-native.js +592 -0
- package/dist/process-recovery-provenance.d.ts +163 -0
- package/dist/process-recovery-provenance.js +292 -0
- package/dist/process-recovery-services.d.ts +56 -0
- package/dist/process-recovery-services.js +191 -0
- package/dist/process-recovery-settlement.d.ts +32 -0
- package/dist/process-recovery-settlement.js +132 -0
- package/dist/process-recovery.d.ts +41 -0
- package/dist/process-recovery.js +91 -0
- package/dist/process-tree.d.ts +41 -0
- package/dist/process-tree.js +264 -0
- package/dist/project-access.d.ts +14 -0
- package/dist/project-access.js +34 -0
- package/dist/project-cli.d.ts +18 -0
- package/dist/project-cli.js +104 -0
- package/dist/project-delete-ui.d.ts +22 -0
- package/dist/project-delete-ui.js +48 -0
- package/dist/project-delete.d.ts +55 -0
- package/dist/project-delete.js +413 -0
- package/dist/project-knowledge.d.ts +111 -0
- package/dist/project-knowledge.js +241 -0
- package/dist/project-learning.d.ts +100 -0
- package/dist/project-learning.js +438 -0
- package/dist/project-memory.d.ts +81 -0
- package/dist/project-memory.js +264 -0
- package/dist/project-skills.d.ts +152 -0
- package/dist/project-skills.js +660 -0
- package/dist/project-tools.d.ts +219 -0
- package/dist/project-tools.js +796 -0
- package/dist/project.d.ts +61 -0
- package/dist/project.js +125 -0
- package/dist/prompt.d.ts +22 -0
- package/dist/prompt.js +72 -0
- package/dist/proof.d.ts +513 -0
- package/dist/proof.js +1140 -0
- package/dist/proposal.d.ts +82 -0
- package/dist/proposal.js +210 -0
- package/dist/provider-connection.d.ts +22 -0
- package/dist/provider-connection.js +98 -0
- package/dist/provider-limits.d.ts +35 -0
- package/dist/provider-limits.js +95 -0
- package/dist/provider.d.ts +279 -0
- package/dist/provider.js +935 -0
- package/dist/publish.d.ts +107 -0
- package/dist/publish.js +650 -0
- package/dist/pulls.d.ts +118 -0
- package/dist/pulls.js +240 -0
- package/dist/push.d.ts +95 -0
- package/dist/push.js +353 -0
- package/dist/quality.d.ts +8 -0
- package/dist/quality.js +6 -0
- package/dist/recipe-ui.d.ts +18 -0
- package/dist/recipe-ui.js +152 -0
- package/dist/recipes.d.ts +81 -0
- package/dist/recipes.js +332 -0
- package/dist/remote.d.ts +67 -0
- package/dist/remote.js +122 -0
- package/dist/render.d.ts +64 -0
- package/dist/render.js +587 -0
- package/dist/report-summary.d.ts +13 -0
- package/dist/report-summary.js +15 -0
- package/dist/repos.d.ts +65 -0
- package/dist/repos.js +277 -0
- package/dist/repository-context-ui.d.ts +2 -0
- package/dist/repository-context-ui.js +10 -0
- package/dist/repository-context.d.ts +67 -0
- package/dist/repository-context.js +376 -0
- package/dist/restart-certification.d.ts +134 -0
- package/dist/restart-certification.js +226 -0
- package/dist/result-actions.d.ts +28 -0
- package/dist/result-actions.js +270 -0
- package/dist/result-completion.d.ts +18 -0
- package/dist/result-completion.js +66 -0
- package/dist/result-review.d.ts +213 -0
- package/dist/result-review.js +430 -0
- package/dist/retention-ui.d.ts +12 -0
- package/dist/retention-ui.js +39 -0
- package/dist/retention.d.ts +72 -0
- package/dist/retention.js +288 -0
- package/dist/review-context.d.ts +243 -0
- package/dist/review-context.js +1043 -0
- package/dist/review-evidence.d.ts +33 -0
- package/dist/review-evidence.js +56 -0
- package/dist/reviewer.d.ts +97 -0
- package/dist/reviewer.js +202 -0
- package/dist/routine.d.ts +228 -0
- package/dist/routine.js +764 -0
- package/dist/runner.d.ts +266 -0
- package/dist/runner.js +399 -0
- package/dist/scan.d.ts +32 -0
- package/dist/scan.js +92 -0
- package/dist/scope.d.ts +695 -0
- package/dist/scope.js +1176 -0
- package/dist/scout-report.d.ts +42 -0
- package/dist/scout-report.js +108 -0
- package/dist/scout.d.ts +69 -0
- package/dist/scout.js +351 -0
- package/dist/serve.d.ts +313 -0
- package/dist/serve.js +21776 -0
- package/dist/session-brief.d.ts +8 -0
- package/dist/session-brief.js +24 -0
- package/dist/session-cli.d.ts +13 -0
- package/dist/session-cli.js +284 -0
- package/dist/session-contract.d.ts +183 -0
- package/dist/session-contract.js +122 -0
- package/dist/session-http.d.ts +19 -0
- package/dist/session-http.js +154 -0
- package/dist/session-server.d.ts +12 -0
- package/dist/session-server.js +37 -0
- package/dist/session-service.d.ts +22 -0
- package/dist/session-service.js +157 -0
- package/dist/setup-guide.d.ts +39 -0
- package/dist/setup-guide.js +93 -0
- package/dist/sign-in-guard.d.ts +45 -0
- package/dist/sign-in-guard.js +74 -0
- package/dist/skills-ui.d.ts +11 -0
- package/dist/skills-ui.js +58 -0
- package/dist/skills.d.ts +97 -0
- package/dist/skills.js +276 -0
- package/dist/slack-api.d.ts +55 -0
- package/dist/slack-api.js +229 -0
- package/dist/slack-chat.d.ts +28 -0
- package/dist/slack-chat.js +413 -0
- package/dist/slack-settings.d.ts +7 -0
- package/dist/slack-settings.js +75 -0
- package/dist/slack-state.d.ts +13 -0
- package/dist/slack-state.js +9 -0
- package/dist/slack.d.ts +13 -0
- package/dist/slack.js +167 -0
- package/dist/spend-ui.d.ts +28 -0
- package/dist/spend-ui.js +95 -0
- package/dist/spend.d.ts +142 -0
- package/dist/spend.js +313 -0
- package/dist/sqlite-runtime.d.ts +3 -0
- package/dist/sqlite-runtime.js +6 -0
- package/dist/sso-settings.d.ts +33 -0
- package/dist/sso-settings.js +103 -0
- package/dist/sso-ui.d.ts +22 -0
- package/dist/sso-ui.js +39 -0
- package/dist/storage.d.ts +15 -0
- package/dist/storage.js +84 -0
- package/dist/store.d.ts +7754 -0
- package/dist/store.js +23279 -0
- package/dist/structured-output.d.ts +58 -0
- package/dist/structured-output.js +103 -0
- package/dist/style-asset.d.ts +7 -0
- package/dist/style-asset.js +41 -0
- package/dist/subscription-chat.d.ts +46 -0
- package/dist/subscription-chat.js +275 -0
- package/dist/summary.d.ts +33 -0
- package/dist/summary.js +71 -0
- package/dist/supervisor.mjs +297 -0
- package/dist/surface.d.ts +63 -0
- package/dist/surface.js +352 -0
- package/dist/sync.d.ts +94 -0
- package/dist/sync.js +279 -0
- package/dist/task-composer.d.ts +13 -0
- package/dist/task-composer.js +52 -0
- package/dist/task-control.d.ts +165 -0
- package/dist/task-control.js +214 -0
- package/dist/task-outcome-cli.d.ts +10 -0
- package/dist/task-outcome-cli.js +92 -0
- package/dist/task-text.d.ts +30 -0
- package/dist/task-text.js +41 -0
- package/dist/team-cli.d.ts +15 -0
- package/dist/team-cli.js +618 -0
- package/dist/team-contract.d.ts +92 -0
- package/dist/team-contract.js +1 -0
- package/dist/team-http.d.ts +17 -0
- package/dist/team-http.js +144 -0
- package/dist/team-leads.d.ts +81 -0
- package/dist/team-leads.js +565 -0
- package/dist/team-runtime.d.ts +27 -0
- package/dist/team-runtime.js +264 -0
- package/dist/team-ui.d.ts +3 -0
- package/dist/team-ui.js +9 -0
- package/dist/team-updates.d.ts +8 -0
- package/dist/team-updates.js +57 -0
- package/dist/teammate-admin.d.ts +53 -0
- package/dist/teammate-admin.js +111 -0
- package/dist/teammate-desk.d.ts +60 -0
- package/dist/teammate-desk.js +154 -0
- package/dist/teammate-memory.d.ts +64 -0
- package/dist/teammate-memory.js +196 -0
- package/dist/teammate-question.d.ts +59 -0
- package/dist/teammate-question.js +175 -0
- package/dist/teammate-tools.d.ts +108 -0
- package/dist/teammate-tools.js +271 -0
- package/dist/teammate-week.d.ts +68 -0
- package/dist/teammate-week.js +132 -0
- package/dist/teammate-work.d.ts +76 -0
- package/dist/teammate-work.js +280 -0
- package/dist/teammates-ui.d.ts +20 -0
- package/dist/teammates-ui.js +166 -0
- package/dist/teammates.d.ts +180 -0
- package/dist/teammates.js +253 -0
- package/dist/teams-api.d.ts +33 -0
- package/dist/teams-api.js +204 -0
- package/dist/teams-chat.d.ts +26 -0
- package/dist/teams-chat.js +215 -0
- package/dist/teams-settings.d.ts +12 -0
- package/dist/teams-settings.js +57 -0
- package/dist/teams.d.ts +21 -0
- package/dist/teams.js +124 -0
- package/dist/telegram-flow.d.ts +49 -0
- package/dist/telegram-flow.js +110 -0
- package/dist/telegram-mate.d.ts +137 -0
- package/dist/telegram-mate.js +707 -0
- package/dist/telegram-progress.d.ts +14 -0
- package/dist/telegram-progress.js +129 -0
- package/dist/telegram-settings.d.ts +9 -0
- package/dist/telegram-settings.js +36 -0
- package/dist/telegram-status.d.ts +75 -0
- package/dist/telegram-status.js +265 -0
- package/dist/telegram-team.d.ts +85 -0
- package/dist/telegram-team.js +359 -0
- package/dist/telegram.d.ts +230 -0
- package/dist/telegram.js +1931 -0
- package/dist/templates.d.ts +65 -0
- package/dist/templates.js +118 -0
- package/dist/tool-launcher.d.ts +1 -0
- package/dist/tool-launcher.js +101 -0
- package/dist/tools-ui.d.ts +30 -0
- package/dist/tools-ui.js +40 -0
- package/dist/transitions-recipes.d.ts +1 -0
- package/dist/transitions-recipes.js +203 -0
- package/dist/tree-proof.d.ts +34 -0
- package/dist/tree-proof.js +58 -0
- package/dist/verification-evidence.d.ts +44 -0
- package/dist/verification-evidence.js +238 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +10 -0
- package/dist/webhooks.d.ts +91 -0
- package/dist/webhooks.js +283 -0
- package/dist/work-index.d.ts +68 -0
- package/dist/work-index.js +384 -0
- package/dist/work-summary.d.ts +57 -0
- package/dist/work-summary.js +116 -0
- package/dist/workspace-motion.d.ts +4 -0
- package/dist/workspace-motion.js +133 -0
- package/dist/workspace-revision.d.ts +19 -0
- package/dist/workspace-revision.js +92 -0
- package/dist/workspace-ui.d.ts +204 -0
- package/dist/workspace-ui.js +411 -0
- package/dist/worktree-notices.d.ts +13 -0
- package/dist/worktree-notices.js +17 -0
- package/dist/worktree.d.ts +249 -0
- package/dist/worktree.js +720 -0
- package/package.json +122 -0
- package/scripts/canary-assertions.mjs +42 -0
- package/scripts/crash-canary.mjs +253 -0
- package/scripts/fixtures/crash-process.mjs +74 -0
- package/scripts/fixtures/pilot-scenarios.mjs +85 -0
- package/scripts/fixtures/restart-service.mjs +27 -0
- package/scripts/launchd-certification.mjs +143 -0
- package/scripts/pilot.mjs +121 -0
- package/scripts/proof-preflight.mjs +140 -0
- package/scripts/provider-canary.mjs +379 -0
- package/scripts/recovery-canary.mjs +135 -0
- package/scripts/restart-certification.mjs +98 -0
package/dist/keys.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider API keys, managed instead of ambient (the gap the gemini
|
|
3
|
+
* live-auth work exposed): one 0600 file per provider under
|
|
4
|
+
* ~/.toolroll/keys/ (or an older ~/.standing-orders/keys/), written from the settings card or piped into
|
|
5
|
+
* the CLI — never typed into an argv, never rendered back, never stored
|
|
6
|
+
* in the database a backup might carry.
|
|
7
|
+
*
|
|
8
|
+
* The injection contract lives in the invocation gateway: a stored key is
|
|
9
|
+
* added to EXACTLY its own provider's child environment at spawn, where
|
|
10
|
+
* the adapter's foreign-credential strip has already shed everybody
|
|
11
|
+
* else's. The plane's own process never needs the key in its environment
|
|
12
|
+
* at all — a restart or a rotation is a file write, not a relaunch — and
|
|
13
|
+
* an ambient env var still works as the fallback it always was (the file,
|
|
14
|
+
* being deliberate, wins).
|
|
15
|
+
*/
|
|
16
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
import { namedPath } from "./names.js";
|
|
20
|
+
/** The ONE env name each provider's own harness reads its key from —
|
|
21
|
+
* where a managed key is INJECTED. */
|
|
22
|
+
export const PROVIDER_KEY_ENV = {
|
|
23
|
+
claude: "ANTHROPIC_API_KEY",
|
|
24
|
+
codex: "OPENAI_API_KEY",
|
|
25
|
+
openrouter: "OPENROUTER_API_KEY",
|
|
26
|
+
gemini: "GEMINI_API_KEY",
|
|
27
|
+
};
|
|
28
|
+
/** EVERY env name a provider reads its OWN key from — what subscription
|
|
29
|
+
* mode STRIPS so an ambient key cannot override the login. gemini reads
|
|
30
|
+
* two; the rest read one. */
|
|
31
|
+
export const OWN_KEY_ENV = {
|
|
32
|
+
// v105: the bearer-token and Codex-specific aliases bill a key just the same, so a sign-in run sheds them too.
|
|
33
|
+
claude: ["ANTHROPIC_API_KEY", "ANTHROPIC_AUTH_TOKEN"],
|
|
34
|
+
codex: ["OPENAI_API_KEY", "CODEX_API_KEY"],
|
|
35
|
+
openrouter: ["OPENROUTER_API_KEY"],
|
|
36
|
+
gemini: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
37
|
+
};
|
|
38
|
+
export function keysDir(home = homedir()) {
|
|
39
|
+
return namedPath(home, ["keys"], { dot: true });
|
|
40
|
+
}
|
|
41
|
+
/** Providers that CAN authenticate without an API key (a subscription or
|
|
42
|
+
* cached login). openrouter cannot — it is api-key only. */
|
|
43
|
+
export const SUBSCRIPTION_CAPABLE = {
|
|
44
|
+
claude: true,
|
|
45
|
+
codex: true,
|
|
46
|
+
gemini: true,
|
|
47
|
+
openrouter: false,
|
|
48
|
+
};
|
|
49
|
+
/** The default when nothing is set: subscription where it exists (prefer
|
|
50
|
+
* the plan the operator already pays for), api-key otherwise. */
|
|
51
|
+
export const DEFAULT_AUTH_MODE = {
|
|
52
|
+
// Claude and Codex have first-class subscriptions most operators
|
|
53
|
+
// already pay for — prefer them. Gemini support here is key-based (a
|
|
54
|
+
// Google cached login is possible but not our road), and openrouter is
|
|
55
|
+
// key-only — both default to the key. Every default is switchable.
|
|
56
|
+
claude: "subscription",
|
|
57
|
+
codex: "subscription",
|
|
58
|
+
gemini: "api-key",
|
|
59
|
+
openrouter: "api-key",
|
|
60
|
+
};
|
|
61
|
+
function authModeFileFor(provider, home) {
|
|
62
|
+
return join(keysDir(home), `${provider}.auth`);
|
|
63
|
+
}
|
|
64
|
+
export function readAuthMode(provider, home = homedir()) {
|
|
65
|
+
if (!SUBSCRIPTION_CAPABLE[provider])
|
|
66
|
+
return "api-key";
|
|
67
|
+
try {
|
|
68
|
+
const value = readFileSync(authModeFileFor(provider, home), "utf8").trim();
|
|
69
|
+
return value === "api-key" ? "api-key" : "subscription";
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return DEFAULT_AUTH_MODE[provider];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The auth mode as an AUTHORITY reads it (raw authority repair): an absent
|
|
77
|
+
* file is the provider's default, but a file that is present and says
|
|
78
|
+
* neither `subscription` nor `api-key` is a stated problem — never the
|
|
79
|
+
* subscription default a lenient read would coerce it to. A provider with
|
|
80
|
+
* no subscription login is the key, whatever the file says.
|
|
81
|
+
*/
|
|
82
|
+
export function readAuthModeStrict(provider, home = homedir()) {
|
|
83
|
+
if (!SUBSCRIPTION_CAPABLE[provider])
|
|
84
|
+
return { ok: true, mode: "api-key" };
|
|
85
|
+
let raw;
|
|
86
|
+
try {
|
|
87
|
+
raw = readFileSync(authModeFileFor(provider, home), "utf8");
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error.code === "ENOENT")
|
|
91
|
+
return { ok: true, mode: DEFAULT_AUTH_MODE[provider] };
|
|
92
|
+
return { ok: false, problem: `the ${provider} auth-mode file cannot be read (${error.code ?? "error"}) — run \`keys auth ${provider} subscription|api-key\` to restate it` };
|
|
93
|
+
}
|
|
94
|
+
const value = raw.trim();
|
|
95
|
+
if (value !== "subscription" && value !== "api-key") {
|
|
96
|
+
return { ok: false, problem: `the ${provider} auth-mode file says ${JSON.stringify(value.slice(0, 40))}, not subscription or api-key — run \`keys auth ${provider} subscription|api-key\` to restate it` };
|
|
97
|
+
}
|
|
98
|
+
return { ok: true, mode: value };
|
|
99
|
+
}
|
|
100
|
+
export function setAuthMode(provider, mode, home = homedir()) {
|
|
101
|
+
if (mode === "subscription" && !SUBSCRIPTION_CAPABLE[provider]) {
|
|
102
|
+
return { ok: false, reason: "no-subscription" };
|
|
103
|
+
}
|
|
104
|
+
mkdirSync(keysDir(home), { recursive: true, mode: 0o700 });
|
|
105
|
+
writeFileSync(authModeFileFor(provider, home), mode, { mode: 0o600 });
|
|
106
|
+
return { ok: true };
|
|
107
|
+
}
|
|
108
|
+
export function keyFileFor(provider, home = homedir()) {
|
|
109
|
+
return join(keysDir(home), provider);
|
|
110
|
+
}
|
|
111
|
+
/** Shape check only — never a validity claim. A key is printable ASCII
|
|
112
|
+
* without whitespace, bounded; anything else is a paste accident. */
|
|
113
|
+
export function plausibleKey(value) {
|
|
114
|
+
return value.length >= 8 && value.length <= 512 && /^[\x21-\x7e]+$/.test(value);
|
|
115
|
+
}
|
|
116
|
+
export function saveProviderKey(provider, value, home = homedir()) {
|
|
117
|
+
const trimmed = value.trim();
|
|
118
|
+
if (!plausibleKey(trimmed))
|
|
119
|
+
return { ok: false, reason: "implausible" };
|
|
120
|
+
mkdirSync(keysDir(home), { recursive: true, mode: 0o700 });
|
|
121
|
+
writeFileSync(keyFileFor(provider, home), trimmed, { mode: 0o600 });
|
|
122
|
+
// An existing file keeps its old mode through writeFileSync — restate it.
|
|
123
|
+
chmodSync(keyFileFor(provider, home), 0o600);
|
|
124
|
+
return { ok: true };
|
|
125
|
+
}
|
|
126
|
+
export function readProviderKey(provider, home = homedir()) {
|
|
127
|
+
try {
|
|
128
|
+
const value = readFileSync(keyFileFor(provider, home), "utf8").trim();
|
|
129
|
+
return plausibleKey(value) ? value : null;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export function clearProviderKey(provider, home = homedir()) {
|
|
136
|
+
const file = keyFileFor(provider, home);
|
|
137
|
+
if (!existsSync(file))
|
|
138
|
+
return false;
|
|
139
|
+
rmSync(file, { force: true });
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
const VERIFY_ENDPOINT = {
|
|
143
|
+
gemini: {
|
|
144
|
+
// The key rides the x-goog-api-key HEADER (round 2, finding 6):
|
|
145
|
+
// Google's current guidance, and it keeps the secret out of the URL
|
|
146
|
+
// where a diagnostic or intermediary could surface it.
|
|
147
|
+
url: "https://generativelanguage.googleapis.com/v1beta/models",
|
|
148
|
+
headers: key => ({ "x-goog-api-key": key }),
|
|
149
|
+
},
|
|
150
|
+
codex: {
|
|
151
|
+
url: "https://api.openai.com/v1/models",
|
|
152
|
+
headers: key => ({ authorization: `Bearer ${key}` }),
|
|
153
|
+
},
|
|
154
|
+
openrouter: {
|
|
155
|
+
url: "https://openrouter.ai/api/v1/key",
|
|
156
|
+
headers: key => ({ authorization: `Bearer ${key}` }),
|
|
157
|
+
},
|
|
158
|
+
claude: {
|
|
159
|
+
url: "https://api.anthropic.com/v1/models",
|
|
160
|
+
headers: key => ({ "x-api-key": key, "anthropic-version": "2023-06-01" }),
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
export async function verifyProviderKey(provider, value, fetcher = fetch, timeoutMs = 10_000) {
|
|
164
|
+
const key = value.trim();
|
|
165
|
+
if (!plausibleKey(key))
|
|
166
|
+
return { ok: false, reason: "rejected", status: 0 };
|
|
167
|
+
const endpoint = VERIFY_ENDPOINT[provider];
|
|
168
|
+
const controller = new AbortController();
|
|
169
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
170
|
+
let response;
|
|
171
|
+
try {
|
|
172
|
+
response = await fetcher(endpoint.url, { headers: endpoint.headers(key), redirect: "error", signal: controller.signal });
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return { ok: false, reason: "unreachable" };
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
}
|
|
180
|
+
if (response.status === 200)
|
|
181
|
+
return { ok: true };
|
|
182
|
+
// 401/403 are the auth boundary saying no, on every provider (round 2,
|
|
183
|
+
// finding 6). A 400 is AMBIGUOUS — malformed request vs a bad key — so
|
|
184
|
+
// it is a rejection ONLY when the body names a key/auth failure; our
|
|
185
|
+
// request is a trivial GET, so a 400 that is NOT about the key is a
|
|
186
|
+
// genuine surprise and reads as `unexpected`, not a false rejection.
|
|
187
|
+
if (response.status === 401 || response.status === 403) {
|
|
188
|
+
return { ok: false, reason: "rejected", status: response.status };
|
|
189
|
+
}
|
|
190
|
+
if (response.status === 400) {
|
|
191
|
+
let body = "";
|
|
192
|
+
try {
|
|
193
|
+
body = (await response.text()).slice(0, 2048).toLowerCase();
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
body = "";
|
|
197
|
+
}
|
|
198
|
+
// A 400 is a rejection ONLY with an actual NEGATIVE marker near the
|
|
199
|
+
// key/auth phrase (round 3, finding 6) — "API key not valid" rejects,
|
|
200
|
+
// but "API key accepted; malformed page size" does not.
|
|
201
|
+
const negativeAuth = /(api[ _]?key[^.]{0,30}(invalid|not valid|expired|missing|revoked))|((invalid|expired|missing|revoked)[^.]{0,20}api[ _]?key)|unauthenticated|permission[ _]denied|invalid authentication|api_key_invalid/;
|
|
202
|
+
if (negativeAuth.test(body)) {
|
|
203
|
+
return { ok: false, reason: "rejected", status: 400 };
|
|
204
|
+
}
|
|
205
|
+
return { ok: false, reason: "unexpected", status: 400 };
|
|
206
|
+
}
|
|
207
|
+
return { ok: false, reason: "unexpected", status: response.status };
|
|
208
|
+
}
|
|
209
|
+
/** Words for a verdict, safe to render on any surface (never the key). */
|
|
210
|
+
export function verdictWords(provider, verdict) {
|
|
211
|
+
if (verdict.ok)
|
|
212
|
+
return `the ${provider} key works`;
|
|
213
|
+
if (verdict.reason === "rejected")
|
|
214
|
+
return `${provider} rejected this key — check the paste, or whether it is the right provider`;
|
|
215
|
+
if (verdict.reason === "unreachable")
|
|
216
|
+
return `couldn't reach ${provider} to check the key — it is stored; verify later`;
|
|
217
|
+
return `${provider} gave an unexpected response (${verdict.status}) — the key is stored, but unverified`;
|
|
218
|
+
}
|
|
219
|
+
/** What a surface may say about a key: that it exists and when it last
|
|
220
|
+
* changed — NEVER the value, never a prefix, never a length. */
|
|
221
|
+
export function keyStatus(provider, home = homedir()) {
|
|
222
|
+
try {
|
|
223
|
+
const stat = statSync(keyFileFor(provider, home));
|
|
224
|
+
return { set: true, updatedAt: stat.mtime.toISOString() };
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return { set: false, updatedAt: null };
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starter kits pages: the gallery — each kit's promise, what it sets
|
|
3
|
+
* up, one button — and a kit's own page: its checklist, with the next step on
|
|
4
|
+
* each line (connect email, connect a tool, try a sample card).
|
|
5
|
+
*/
|
|
6
|
+
import type { Store } from "./store.js";
|
|
7
|
+
import { type Kit } from "./kits.js";
|
|
8
|
+
export declare const KITS_CSS: string;
|
|
9
|
+
/** The gallery: every kit, set up in a project with one button (or opened, when it's already there). */
|
|
10
|
+
export declare function kitsGalleryHtml(store: Store, projects: readonly string[], projectName: (repo: string) => string, csrf: string, canSetUp: boolean, notice: {
|
|
11
|
+
problem?: string | null;
|
|
12
|
+
}): string;
|
|
13
|
+
/** A kit's own page: what's set up, and the next step on each line. */
|
|
14
|
+
export declare function kitPageHtml(store: Store, kit: Kit, repo: string, dir: string | null, csrf: string, canSetUp: boolean, notice: {
|
|
15
|
+
said?: string | null;
|
|
16
|
+
problem?: string | null;
|
|
17
|
+
}): string;
|
package/dist/kits-ui.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { kitChecklist, kitInstalled, KITS } from "./kits.js";
|
|
2
|
+
import { TEAMMATE_TEMPLATES } from "./teammates.js";
|
|
3
|
+
const e = (text) => text.replace(/[&<>"']/g, one => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[one]);
|
|
4
|
+
const hidden = (csrf) => `<input type="hidden" name="csrf" value="${e(csrf)}">`;
|
|
5
|
+
const CHECK = `<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>`;
|
|
6
|
+
const RING = `<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg>`;
|
|
7
|
+
export const KITS_CSS = `.kits{max-width:960px;min-width:0}.kits-lede{color:var(--so-muted);margin:.25rem 0 1.5rem;max-width:40rem}.kit-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}` +
|
|
8
|
+
`.kit{display:flex;flex-direction:column;gap:10px;padding:20px;border:1px solid var(--so-line);border-radius:12px;background:var(--so-paper)}.kit h2{font-size:1.1rem;margin:0}.kit p{margin:0}.kit .kit-promise{line-height:1.5}` +
|
|
9
|
+
`.kit .kit-gets{font-size:.85rem;color:var(--so-muted);line-height:1.5}.kit form{display:flex;flex-wrap:wrap;gap:8px;align-items:flex-end;margin-top:auto;padding-top:6px}.kit form label{display:grid;gap:4px;font-size:.85rem;flex:1 1 140px}` +
|
|
10
|
+
`.kit button,.kit .kit-open{min-height:44px}.kit .kit-open{display:inline-flex;align-items:center;margin-top:auto;font-weight:600}` +
|
|
11
|
+
`.kit-steps{list-style:none;padding:0;margin:1rem 0;display:grid;gap:2px;max-width:44rem}.kit-steps li{display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--so-line);border-radius:10px;background:var(--so-paper)}` +
|
|
12
|
+
`.kit-steps svg{flex:none;width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round}.kit-steps li[data-done="true"] svg{color:var(--so-success)}.kit-steps li[data-done="false"] svg{color:var(--so-muted)}` +
|
|
13
|
+
`.kit-steps .kit-step-said{flex:1;min-width:0}.kit-steps li[data-done="true"] .kit-step-said{color:var(--so-muted)}.kit-steps form{margin:0}.kit-steps button,.kit-steps .kit-step-go{min-height:40px;white-space:nowrap}` +
|
|
14
|
+
`.kit-steps .kit-step-go{display:inline-flex;align-items:center;padding:0 12px;border:1px solid var(--so-line);border-radius:8px;text-decoration:none;font-size:.9rem}` +
|
|
15
|
+
`@media(max-width:600px){.kit-steps li{flex-wrap:wrap}.kit-steps .kit-step-said{flex-basis:calc(100% - 40px)}.kit form select{font-size:16px}}`;
|
|
16
|
+
const teammateWords = (kit) => { const template = TEAMMATE_TEMPLATES.find(one => one.id === kit.teammate.template); return template === undefined ? kit.teammate.handle : template.label.toLowerCase(); };
|
|
17
|
+
/** The gallery: every kit, set up in a project with one button (or opened, when it's already there). */
|
|
18
|
+
export function kitsGalleryHtml(store, projects, projectName, csrf, canSetUp, notice) {
|
|
19
|
+
const cards = KITS.map(kit => {
|
|
20
|
+
const here = projects.filter(repo => kitInstalled(store, kit, repo) !== null);
|
|
21
|
+
const open = projects.length === 1 && here.length === 1;
|
|
22
|
+
const name = kit.teammate.handle.charAt(0).toUpperCase() + kit.teammate.handle.slice(1);
|
|
23
|
+
const gets = `${name} (${teammateWords(kit)}) · the ${kit.flowName} flow${kit.tools.length === 0 ? "" : ` · works with ${kit.tools.map(one => one.label).join(" and ")}`}`;
|
|
24
|
+
const action = open ? `<a class="kit-open" href="/kits/${kit.id}?repo=${encodeURIComponent(projects[0])}">Open ${e(kit.name)} →</a>`
|
|
25
|
+
: !canSetUp || projects.length === 0 ? ""
|
|
26
|
+
: `<form method="post" action="/kits/${kit.id}/setup">${hidden(csrf)}${projects.length === 1 ? `<input type="hidden" name="repo" value="${e(projects[0])}">`
|
|
27
|
+
: `<label>Project<select name="repo">${projects.map(repo => `<option value="${e(repo)}">${e(projectName(repo))}${here.includes(repo) ? " (set up)" : ""}</option>`).join("")}</select></label>`}<button>Set it up</button></form>`;
|
|
28
|
+
return `<article class="kit" data-kit="${kit.id}"><h2>${e(kit.name)}</h2><p class="kit-promise">${e(kit.promise)}</p><p class="kit-gets">${e(gets)}</p>${action}</article>`;
|
|
29
|
+
}).join("");
|
|
30
|
+
return `<section class="kits">${notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : ""}<p class="kits-lede">A working setup in one click: an AI teammate, the flow it works, and what to connect next. Nothing goes out without you approving it.</p><div class="kit-grid">${cards}</div></section>`;
|
|
31
|
+
}
|
|
32
|
+
/** A kit's own page: what's set up, and the next step on each line. */
|
|
33
|
+
export function kitPageHtml(store, kit, repo, dir, csrf, canSetUp, notice) {
|
|
34
|
+
const steps = kitChecklist(store, kit, repo, dir);
|
|
35
|
+
const set = kitInstalled(store, kit, repo);
|
|
36
|
+
const rows = steps.map(step => {
|
|
37
|
+
const go = step.done ? (step.href === null ? "" : `<a class="kit-step-go" href="${e(step.href)}">Open</a>`)
|
|
38
|
+
: step.action === "sample" || step.action === "github"
|
|
39
|
+
? (canSetUp ? `<form method="post" action="/kits/${kit.id}/${step.action}">${hidden(csrf)}<input type="hidden" name="repo" value="${e(repo)}"><button${step.action === "sample" ? "" : ' class="secondary"'}>${step.action === "sample" ? "Try it" : "Bring them in"}</button></form>` : "")
|
|
40
|
+
: step.href === null ? "" : `<a class="kit-step-go" href="${e(step.href)}">${step.action === "connect" ? "Connect" : "Set up"}</a>`;
|
|
41
|
+
return `<li data-step="${e(step.id)}" data-done="${step.done}">${step.done ? CHECK : RING}<span class="kit-step-said">${e(step.said)}</span>${go}</li>`;
|
|
42
|
+
}).join("");
|
|
43
|
+
const setUp = set === null && canSetUp ? `<form method="post" action="/kits/${kit.id}/setup">${hidden(csrf)}<input type="hidden" name="repo" value="${e(repo)}"><button>Set up ${e(kit.name)}</button></form>` : "";
|
|
44
|
+
return `<section class="kits">${notice.problem ? `<p class="problem" role="alert">${e(notice.problem)}</p>` : ""}${notice.said ? `<p class="said" role="status">${e(notice.said)}</p>` : ""}` +
|
|
45
|
+
`<p class="kits-lede">${e(kit.promise)}</p>${setUp}${rows === "" ? "" : `<ol class="kit-steps">${rows}</ol>`}<p class="meta"><a href="/kits">All starter kits</a></p></section>`;
|
|
46
|
+
}
|
package/dist/kits.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { type FlowStepInput } from "./flows.js";
|
|
2
|
+
import type { FlowRow, Store, TeammateRow } from "./store.js";
|
|
3
|
+
import { type ToolIo } from "./teammate-tools.js";
|
|
4
|
+
/** A tool a kit's teammate works better with: the catalog entry that connects it, and why. */
|
|
5
|
+
export type KitTool = {
|
|
6
|
+
tool: string;
|
|
7
|
+
label: string;
|
|
8
|
+
why: string;
|
|
9
|
+
};
|
|
10
|
+
export type Kit = {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
promise: string;
|
|
14
|
+
/** The teammate it hires: a template, and the name it starts with. */
|
|
15
|
+
teammate: {
|
|
16
|
+
template: string;
|
|
17
|
+
handle: string;
|
|
18
|
+
};
|
|
19
|
+
flowName: string;
|
|
20
|
+
steps: FlowStepInput[];
|
|
21
|
+
/** Triggers safe to add at once: buttons (they fire only when pressed). */
|
|
22
|
+
buttons: {
|
|
23
|
+
label: string;
|
|
24
|
+
questions: string[];
|
|
25
|
+
}[];
|
|
26
|
+
/** Other ways in, offered on its checklist. */
|
|
27
|
+
email?: boolean;
|
|
28
|
+
github?: boolean;
|
|
29
|
+
tools: KitTool[];
|
|
30
|
+
sample: {
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export declare const KITS: readonly Kit[];
|
|
36
|
+
export declare const kitOf: (id: string) => Kit | null;
|
|
37
|
+
type Done = {
|
|
38
|
+
ok: true;
|
|
39
|
+
said: string;
|
|
40
|
+
flow: number;
|
|
41
|
+
teammate: number;
|
|
42
|
+
} | {
|
|
43
|
+
ok: false;
|
|
44
|
+
said: string;
|
|
45
|
+
};
|
|
46
|
+
/** A kit set up in a project: its flow (by name) and its teammate, when both are there. */
|
|
47
|
+
export declare function kitInstalled(store: Store, kit: Kit, repo: string): {
|
|
48
|
+
flow: FlowRow;
|
|
49
|
+
mate: TeammateRow;
|
|
50
|
+
} | null;
|
|
51
|
+
/**
|
|
52
|
+
* Set a kit up: its teammate (kept if one of that name is already there), its
|
|
53
|
+
* flow, and its button triggers; then its teammate may use whichever of the
|
|
54
|
+
* kit's tools the project already has (reading free, writing asking first).
|
|
55
|
+
*/
|
|
56
|
+
export declare function setUpKit(store: Store, kit: Kit, repo: string, by: string, now: Date, dir: string | null, io?: ToolIo): Promise<Done>;
|
|
57
|
+
/** The same, all at once (a chat confirmation can't wait on a tool): its teammate is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
|
|
58
|
+
export declare function setUpKitNow(store: Store, kit: Kit, repo: string, by: string, now: Date, dir: string | null, grantByName?: boolean): Done;
|
|
59
|
+
/** One line of a kit's checklist: done, or the next step with where to take it. */
|
|
60
|
+
export type KitStep = {
|
|
61
|
+
id: string;
|
|
62
|
+
done: boolean;
|
|
63
|
+
said: string;
|
|
64
|
+
href: string | null;
|
|
65
|
+
action?: "sample" | "github" | "connect";
|
|
66
|
+
tool?: string;
|
|
67
|
+
};
|
|
68
|
+
/** What's set up and what's left, read fresh each time. */
|
|
69
|
+
export declare function kitChecklist(store: Store, kit: Kit, repo: string, dir: string | null): KitStep[];
|
|
70
|
+
/** A sample card in the kit's first zone, so its teammate starts on it at once. */
|
|
71
|
+
export declare function addKitSample(store: Store, kit: Kit, repo: string, by: string, now: Date): {
|
|
72
|
+
ok: true;
|
|
73
|
+
href: string;
|
|
74
|
+
} | {
|
|
75
|
+
ok: false;
|
|
76
|
+
said: string;
|
|
77
|
+
};
|
|
78
|
+
/** Bring new issues from the project's GitHub repository into the kit's flow (issues from anyone, polled). */
|
|
79
|
+
export declare function addKitGithubTrigger(store: Store, kit: Kit, repo: string, by: string, now: Date, dir: string | null): {
|
|
80
|
+
ok: true;
|
|
81
|
+
said: string;
|
|
82
|
+
} | {
|
|
83
|
+
ok: false;
|
|
84
|
+
said: string;
|
|
85
|
+
};
|
|
86
|
+
export {};
|
package/dist/kits.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starter kits: a working setup in one click — an AI teammate, the flow
|
|
3
|
+
* it works, and the triggers that are safe to add straight away — plus a
|
|
4
|
+
* checklist of what's left (connect email, connect a tool) and a sample card
|
|
5
|
+
* that shows the teammate at work within seconds.
|
|
6
|
+
*
|
|
7
|
+
* A kit adds nothing a person couldn't add by hand, and nothing that acts
|
|
8
|
+
* outside: replies go out only after you approve them, a code change is filed
|
|
9
|
+
* as an ordinary task you approve, and tools start with reading free and
|
|
10
|
+
* writing asking first.
|
|
11
|
+
*/
|
|
12
|
+
import { addCardToFlow, flowCardHref, flowDefinitionOf } from "./flow-engine.js";
|
|
13
|
+
import { flowFromSteps } from "./flows.js";
|
|
14
|
+
import { addFlowTriggerTo, githubRepoOf, triggerConfigOf } from "./flow-triggers.js";
|
|
15
|
+
import { googleConnected } from "./google-mail.js";
|
|
16
|
+
import { readEmailSettings } from "./email-settings.js";
|
|
17
|
+
import { mailboxReady } from "./mailbox.js";
|
|
18
|
+
import { projectToolsOf } from "./project-tools.js";
|
|
19
|
+
import { createTeammateFrom, nameOf } from "./teammate-admin.js";
|
|
20
|
+
import { grantListed, grantTool } from "./teammate-tools.js";
|
|
21
|
+
import { TEAMMATE_TEMPLATES } from "./teammates.js";
|
|
22
|
+
export const KITS = [
|
|
23
|
+
{
|
|
24
|
+
id: "support-desk", name: "Support desk",
|
|
25
|
+
promise: "Maya answers customer emails, looks orders up and refunds within limits you set. You approve each reply before it goes out.",
|
|
26
|
+
teammate: { template: "support", handle: "maya" },
|
|
27
|
+
flowName: "Support desk",
|
|
28
|
+
steps: [
|
|
29
|
+
{ id: "answer", title: "Maya answers", kind: "teammate", teammate: "maya",
|
|
30
|
+
instructions: "Read the customer's message. Look things up (and refund, within your rules) with your tools when it helps. Write the reply we'd send in \"text\". Pick Reply when it's ready for the customer, or Needs a person when your rules say to ask first or you can't help.",
|
|
31
|
+
routes: [{ answer: "Reply", goesTo: "You check the reply" }, { answer: "Needs a person", goesTo: "For you" }], ifFails: "For you" },
|
|
32
|
+
{ id: "check", title: "You check the reply", kind: "approval", decider: "owner", next: "Send it", ifFails: "Maya answers" },
|
|
33
|
+
{ id: "send", title: "Send it", kind: "email", to: "{{card.email}}", subject: "Re: {{card.title}}", body: "{{stage.answer}}", next: "Done", ifFails: "For you" },
|
|
34
|
+
{ id: "person", title: "For you", kind: "inbox" },
|
|
35
|
+
{ id: "done", title: "Done", kind: "done" },
|
|
36
|
+
],
|
|
37
|
+
buttons: [], email: true,
|
|
38
|
+
tools: [
|
|
39
|
+
{ tool: "stripe", label: "Stripe", why: "so Maya can look payments up and refund within its limit" },
|
|
40
|
+
{ tool: "intercom", label: "Intercom", why: "so Maya can read and answer your support conversations" },
|
|
41
|
+
],
|
|
42
|
+
sample: { title: "Where's my order? It's been 9 days", description: "Hi! I ordered a desk lamp on the 14th (order #1042) and it still hasn't arrived. Could you check where it is? Thanks, Priya (priya@example.com)\n\nOrder #1042 in the shop: shipped on the 15th by UPS, out for delivery tomorrow." },
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "bug-triage", name: "Bug triage",
|
|
46
|
+
promise: "Theo reads every new issue, says what it is and how urgent, answers questions, and turns real bugs into fixes you approve.",
|
|
47
|
+
teammate: { template: "triage", handle: "theo" },
|
|
48
|
+
flowName: "Bug triage",
|
|
49
|
+
steps: [
|
|
50
|
+
{ id: "sort", title: "Theo sorts it", kind: "teammate", teammate: "theo",
|
|
51
|
+
instructions: "Read the report. In \"text\", say in one or two sentences what it is and how urgent (for a bug, add what you'd check first; for a question, write the answer). Pick Bug for something broken in this project's code, Question for someone asking how something works, or Duplicate or noise for anything else, saying why.",
|
|
52
|
+
routes: [{ answer: "Bug", goesTo: "Fix it" }, { answer: "Question", goesTo: "Answered" }, { answer: "Duplicate or noise", goesTo: "Closed" }], ifFails: "For you" },
|
|
53
|
+
{ id: "fix", title: "Fix it", kind: "task", planning: "auto", instructions: "Fix the bug this card reports. Theo's notes on it: {{stage.sort}}", next: "You review the fix" },
|
|
54
|
+
{ id: "review", title: "You review the fix", kind: "approval", decider: "owner", next: "Done", ifFails: "Fix it" },
|
|
55
|
+
{ id: "answered", title: "Answered", kind: "inbox" },
|
|
56
|
+
{ id: "person", title: "For you", kind: "inbox" },
|
|
57
|
+
{ id: "closed", title: "Closed", kind: "done" },
|
|
58
|
+
{ id: "done", title: "Done", kind: "done" },
|
|
59
|
+
],
|
|
60
|
+
buttons: [{ label: "Report a bug", questions: ["What's wrong?", "How do we see it happen?"] }], github: true,
|
|
61
|
+
tools: [
|
|
62
|
+
{ tool: "sentry", label: "Sentry", why: "so Theo can see the errors behind a report" },
|
|
63
|
+
{ tool: "linear", label: "Linear", why: "so Theo can find duplicates in your issues" },
|
|
64
|
+
],
|
|
65
|
+
sample: { title: "Checkout button does nothing on Safari", description: "On Safari 18 (Mac), pressing Checkout on the cart page does nothing: no error on screen, no redirect. Chrome works fine. Started after yesterday's release." },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: "sales-follow-up", name: "Sales follow-up",
|
|
69
|
+
promise: "Leo writes back to every new lead within minutes, you approve the email, and it waits for their answer, so no lead goes cold.",
|
|
70
|
+
teammate: { template: "sales", handle: "leo" },
|
|
71
|
+
flowName: "Sales follow-up",
|
|
72
|
+
steps: [
|
|
73
|
+
{ id: "write", title: "Leo writes back", kind: "teammate", teammate: "leo",
|
|
74
|
+
instructions: "Read the lead. In \"text\", write a short, friendly first reply that answers what they asked and suggests one clear next step. Pick Write back, or Not a fit (say why).",
|
|
75
|
+
routes: [{ answer: "Write back", goesTo: "You check it" }, { answer: "Not a fit", goesTo: "Not a fit" }], ifFails: "Not a fit" },
|
|
76
|
+
{ id: "check", title: "You check it", kind: "approval", decider: "owner", next: "Send it", ifFails: "Leo writes back" },
|
|
77
|
+
{ id: "send", title: "Send it", kind: "email", to: "{{card.email}}", subject: "Re: {{card.title}}", body: "{{stage.write}}", next: "Wait for them", ifFails: "Not a fit" },
|
|
78
|
+
{ id: "wait", title: "Wait for them", kind: "wait", waitFor: "reply", wait: "3 days", next: "They replied", ifNoReply: "No reply yet" },
|
|
79
|
+
{ id: "replied", title: "They replied", kind: "inbox" },
|
|
80
|
+
{ id: "quiet", title: "No reply yet", kind: "inbox" },
|
|
81
|
+
{ id: "no-fit", title: "Not a fit", kind: "done" },
|
|
82
|
+
],
|
|
83
|
+
buttons: [{ label: "New lead", questions: ["Who are they?", "Their email", "What do they want?"] }], email: true,
|
|
84
|
+
tools: [{ tool: "attio", label: "Attio", why: "so Leo can look leads up in your CRM and log each reply" }],
|
|
85
|
+
sample: { title: "Acme Co wants a demo", description: "Hi, I'm Dana, head of ops at Acme Co (about 40 people). We're looking for a better way to handle customer requests and would love a demo next week. dana@acme.example" },
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "ops-requests", name: "Ops requests",
|
|
89
|
+
promise: "Ada approves routine requests under $200 without you and brings you everything else, so the team gets answers the same day.",
|
|
90
|
+
teammate: { template: "ops", handle: "ada" },
|
|
91
|
+
flowName: "Ops requests",
|
|
92
|
+
steps: [
|
|
93
|
+
{ id: "decide", title: "Ada decides", kind: "approval", teammate: "ada", decider: "owner", next: "Tell the team", ifFails: "Needs more" },
|
|
94
|
+
{ id: "tell", title: "Tell the team", kind: "notify", message: "Approved: {{card.title}}", next: "Done" },
|
|
95
|
+
{ id: "more", title: "Needs more", kind: "inbox" },
|
|
96
|
+
{ id: "done", title: "Done", kind: "done" },
|
|
97
|
+
],
|
|
98
|
+
buttons: [{ label: "Ask for something", questions: ["What do you need?", "Why?", "What will it cost?"] }],
|
|
99
|
+
tools: [
|
|
100
|
+
{ tool: "notion", label: "Notion", why: "so Ada can check your team's policies and past requests" },
|
|
101
|
+
{ tool: "atlassian", label: "Jira", why: "so Ada can file the ticket once something's approved" },
|
|
102
|
+
],
|
|
103
|
+
sample: { title: "New monitor for Sam", description: "Sam's monitor died this morning. A replacement 27\" monitor, same model as the rest of the team: $180. Sam needs it to work. Owner: Sam." },
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
export const kitOf = (id) => KITS.find(one => one.id === id) ?? null;
|
|
107
|
+
/** A kit set up in a project: its flow (by name) and its teammate, when both are there. */
|
|
108
|
+
export function kitInstalled(store, kit, repo) {
|
|
109
|
+
const mate = store.teammateByHandle(repo, kit.teammate.handle);
|
|
110
|
+
const flow = store.listFlows([repo]).find(one => one.name === kit.flowName && one.state === "active") ?? null;
|
|
111
|
+
return mate === null || flow === null ? null : { flow, mate };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Set a kit up: its teammate (kept if one of that name is already there), its
|
|
115
|
+
* flow, and its button triggers; then its teammate may use whichever of the
|
|
116
|
+
* kit's tools the project already has (reading free, writing asking first).
|
|
117
|
+
*/
|
|
118
|
+
export async function setUpKit(store, kit, repo, by, now, dir, io = {}) {
|
|
119
|
+
const made = setUpKitNow(store, kit, repo, by, now, dir);
|
|
120
|
+
if (!made.ok || made.said.endsWith("already set up here."))
|
|
121
|
+
return made;
|
|
122
|
+
const mate = store.getTeammate(made.teammate);
|
|
123
|
+
const present = new Set(projectToolsOf(store, repo).map(one => one.name));
|
|
124
|
+
for (const tool of kit.tools.filter(one => present.has(one.tool))) {
|
|
125
|
+
try {
|
|
126
|
+
await grantTool(store, mate, tool.tool, by, now, io);
|
|
127
|
+
}
|
|
128
|
+
catch { /* it can be given the tool on its page */ }
|
|
129
|
+
}
|
|
130
|
+
return made;
|
|
131
|
+
}
|
|
132
|
+
/** The same, all at once (a chat confirmation can't wait on a tool): its teammate is given the kit's connected tools by the names their last test found, and each is listed properly on its first turn. */
|
|
133
|
+
export function setUpKitNow(store, kit, repo, by, now, dir, grantByName = false) {
|
|
134
|
+
const had = kitInstalled(store, kit, repo);
|
|
135
|
+
if (had !== null)
|
|
136
|
+
return { ok: true, said: `${kit.name} is already set up here.`, flow: had.flow.id, teammate: had.mate.id };
|
|
137
|
+
let mate = store.teammateByHandle(repo, kit.teammate.handle);
|
|
138
|
+
if (mate === null) {
|
|
139
|
+
const template = TEAMMATE_TEMPLATES.find(one => one.id === kit.teammate.template);
|
|
140
|
+
if (template === undefined)
|
|
141
|
+
return { ok: false, said: "That kit's teammate template is missing." };
|
|
142
|
+
const made = createTeammateFrom(store, { repo, template: template.id, by }, now);
|
|
143
|
+
if (!made.ok)
|
|
144
|
+
return { ok: false, said: made.said };
|
|
145
|
+
mate = store.getTeammate(made.id);
|
|
146
|
+
}
|
|
147
|
+
let definition;
|
|
148
|
+
try {
|
|
149
|
+
definition = flowFromSteps(kit.steps, null);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
return { ok: false, said: `The kit's flow didn't fit: ${error instanceof Error ? error.message : "unknown"}` };
|
|
153
|
+
}
|
|
154
|
+
const flowId = store.createFlow({ repo, name: kit.flowName, definitionJson: JSON.stringify(definition), by }, now);
|
|
155
|
+
const flow = store.getFlow(flowId);
|
|
156
|
+
for (const button of kit.buttons)
|
|
157
|
+
addFlowTriggerTo(store, flow, { kind: "button", label: button.label, questions: button.questions, zone: definition.start }, by, now, dir);
|
|
158
|
+
if (grantByName)
|
|
159
|
+
for (const tool of projectToolsOf(store, repo).filter(one => kit.tools.some(each => each.tool === one.name)))
|
|
160
|
+
grantListed(store, mate, tool, null, by, now);
|
|
161
|
+
return { ok: true, said: `${kit.name} is ready: ${nameOf(mate)} works its ${kit.flowName} flow.`, flow: flowId, teammate: mate.id };
|
|
162
|
+
}
|
|
163
|
+
/** What's set up and what's left, read fresh each time. */
|
|
164
|
+
export function kitChecklist(store, kit, repo, dir) {
|
|
165
|
+
const set = kitInstalled(store, kit, repo);
|
|
166
|
+
if (set === null)
|
|
167
|
+
return [];
|
|
168
|
+
const name = nameOf(set.mate);
|
|
169
|
+
const steps = [
|
|
170
|
+
{ id: "teammate", done: true, said: `${name} joined the team`, href: `/teammates/${set.mate.id}` },
|
|
171
|
+
{ id: "flow", done: true, said: `The ${kit.flowName} flow is ready`, href: `/flows/${set.flow.id}` },
|
|
172
|
+
];
|
|
173
|
+
if (kit.email === true) {
|
|
174
|
+
// (flow-actions' sendingReady, without its imports: kits load beside the chat actions.)
|
|
175
|
+
const ready = (googleConnected(dir) !== null || readEmailSettings(dir) !== null) && mailboxReady(dir);
|
|
176
|
+
steps.push({ id: "email", done: ready, said: ready ? "Email is connected" : "Connect your email so replies go out and answers come back", href: "/settings#email" });
|
|
177
|
+
}
|
|
178
|
+
if (kit.github === true) {
|
|
179
|
+
const github = githubRepoOf(repo);
|
|
180
|
+
const watching = store.flowTriggers(set.flow.id).some(one => one.state !== "removed" && triggerConfigOf(one)?.kind === "github");
|
|
181
|
+
if (github !== null)
|
|
182
|
+
steps.push({ id: "github", done: watching, said: watching ? `New issues on ${github} come in` : `Bring in new issues from ${github}`, href: watching ? `/flows/${set.flow.id}` : null, ...(watching ? {} : { action: "github" }) });
|
|
183
|
+
}
|
|
184
|
+
const tools = projectToolsOf(store, repo);
|
|
185
|
+
for (const tool of kit.tools) {
|
|
186
|
+
const connected = tools.some(one => one.name === tool.tool);
|
|
187
|
+
const granted = store.teammateGrant(set.mate.id, tool.tool) !== null;
|
|
188
|
+
steps.push(connected && granted
|
|
189
|
+
? { id: `tool-${tool.tool}`, done: true, said: `${name} can use ${tool.label}`, href: `/teammates/${set.mate.id}#tools` }
|
|
190
|
+
: connected
|
|
191
|
+
? { id: `tool-${tool.tool}`, done: false, said: `Let ${name} use ${tool.label}, ${tool.why}`, href: `/teammates/${set.mate.id}#tools` }
|
|
192
|
+
: { id: `tool-${tool.tool}`, done: false, said: `Connect ${tool.label}, ${tool.why}`, href: `/settings/tools?repo=${encodeURIComponent(repo)}&kit=${kit.id}&connect=${tool.tool}#connect`, action: "connect", tool: tool.tool });
|
|
193
|
+
}
|
|
194
|
+
const tried = store.flowCards(set.flow.id, true).length > 0;
|
|
195
|
+
steps.push({ id: "sample", done: tried, said: tried ? `${name} has worked a card` : `See ${name} work a sample card`, href: tried ? `/flows/${set.flow.id}` : null, ...(tried ? {} : { action: "sample" }) });
|
|
196
|
+
return steps;
|
|
197
|
+
}
|
|
198
|
+
/** A sample card in the kit's first zone, so its teammate starts on it at once. */
|
|
199
|
+
export function addKitSample(store, kit, repo, by, now) {
|
|
200
|
+
const set = kitInstalled(store, kit, repo);
|
|
201
|
+
if (set === null)
|
|
202
|
+
return { ok: false, said: `Set ${kit.name} up first.` };
|
|
203
|
+
const definition = flowDefinitionOf(set.flow);
|
|
204
|
+
const added = addCardToFlow(store, set.flow, { title: kit.sample.title, description: kit.sample.description, stage: definition?.start ?? null }, by, now);
|
|
205
|
+
return added.ok ? { ok: true, href: flowCardHref(set.flow.id, added.card) } : { ok: false, said: added.message };
|
|
206
|
+
}
|
|
207
|
+
/** Bring new issues from the project's GitHub repository into the kit's flow (issues from anyone, polled). */
|
|
208
|
+
export function addKitGithubTrigger(store, kit, repo, by, now, dir) {
|
|
209
|
+
const set = kitInstalled(store, kit, repo);
|
|
210
|
+
const github = githubRepoOf(repo);
|
|
211
|
+
if (set === null || github === null)
|
|
212
|
+
return { ok: false, said: "This project isn't on GitHub." };
|
|
213
|
+
const made = addFlowTriggerTo(store, set.flow, { kind: "github", repo: github, watch: "issues", from: "anyone", delivery: "poll", zone: flowDefinitionOf(set.flow)?.start }, by, now, dir);
|
|
214
|
+
return made.ok ? { ok: true, said: `New issues on ${github} now come into ${kit.flowName}.` } : { ok: false, said: made.message };
|
|
215
|
+
}
|