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/team-cli.js
ADDED
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
import { constants, closeSync, existsSync, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
5
|
+
import { createInterface } from 'node:readline/promises';
|
|
6
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
7
|
+
import { envelopeJson } from './envelope.js';
|
|
8
|
+
import { sessionServiceOrigin } from './session-cli.js';
|
|
9
|
+
import { databasePath } from './store.js';
|
|
10
|
+
import { configBase, namedPath } from './names.js';
|
|
11
|
+
export const TEAM_CLI_ACTIONS = ['connect', 'lead list', 'lead create', 'lead update', 'lead member', 'lead transfer', 'conversation list', 'conversation create', 'conversation show', 'conversation member', 'conversation edit', 'conversation withdraw', 'conversation read', 'conversation follow', 'conversation stop'];
|
|
12
|
+
const HELP = `toolroll connect <HTTPS-origin> --as <account> --token-stdin
|
|
13
|
+
Use --token-file <private-file> or --local-login for your existing local sign-in.
|
|
14
|
+
Optional: --profile <name> (saved as the active profile).
|
|
15
|
+
toolroll lead list|create|update|member|transfer [--profile <name>] [--json]
|
|
16
|
+
create: --name <name> --instructions <text> --project <server-path> (repeatable)
|
|
17
|
+
update: --lead <id> --revision <number> with --name, --instructions or --status
|
|
18
|
+
member: --lead <id> --account <name> --role viewer|contributor|manager
|
|
19
|
+
--active true|false --revision <lead-revision>
|
|
20
|
+
transfer: --task <id> --lead <id> --revision <number>
|
|
21
|
+
toolroll conversation list|create|show|member|edit|withdraw|read|follow|stop
|
|
22
|
+
list: [--lead <id>]
|
|
23
|
+
create: --lead <id> --title <title> --visibility private|team --project <server-path>
|
|
24
|
+
member: --conversation <id> --account <name> --role viewer|contributor|manager
|
|
25
|
+
--active true|false --revision <conversation-revision>
|
|
26
|
+
edit/withdraw: --conversation <id> --message <id> --revision <message-revision> [--text <text>]
|
|
27
|
+
read/stop: --conversation <id> --message <id>
|
|
28
|
+
follow: --conversation <id> --enabled true|false (automatic summaries within authorized limits)
|
|
29
|
+
toolroll chat --lead <id> --conversation <id> [--say <text>] [--follow] [--json]
|
|
30
|
+
Without --say, a terminal opens interactive chat. --follow only reads updates.
|
|
31
|
+
Enable paid chat with --authorize --terms-digest <digest> after reviewing its terms.
|
|
32
|
+
--request-id <32-hex-id> identifies one message; after a lost response, inspect it
|
|
33
|
+
with brief --conversation <id> --request-id <id>, without sending it again.
|
|
34
|
+
toolroll brief --lead <id> --conversation <id> [--json]
|
|
35
|
+
|
|
36
|
+
Saved profiles select the central service for chat and brief. Use --local for the
|
|
37
|
+
existing local commands. Credentials stay in a private file, never in URLs or arguments.
|
|
38
|
+
Reads and attachment do not start model work. Server permissions remain authoritative.`;
|
|
39
|
+
class UsageError extends Error {
|
|
40
|
+
}
|
|
41
|
+
const value = (flags, name) => typeof flags[name] === 'string' ? flags[name] : '';
|
|
42
|
+
const required = (flags, name) => { const result = value(flags, name); if (!result)
|
|
43
|
+
throw new UsageError(`--${name} is required.`); return result; };
|
|
44
|
+
const number = (flags, name) => { const result = required(flags, name); if (!/^\d+$/.test(result) || !Number.isSafeInteger(Number(result)))
|
|
45
|
+
throw new UsageError(`--${name} must be a whole number.`); return Number(result); };
|
|
46
|
+
const bool = (flags, name) => { const result = required(flags, name); if (!['true', 'false'].includes(result))
|
|
47
|
+
throw new UsageError(`--${name} must be true or false.`); return result === 'true'; };
|
|
48
|
+
const text = (raw) => raw.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, '');
|
|
49
|
+
const record = (input) => !!input && typeof input === 'object' && !Array.isArray(input);
|
|
50
|
+
const strings = (input) => Array.isArray(input) && input.every(one => typeof one === 'string');
|
|
51
|
+
const accountValid = (input) => !!input && input.length <= 200 && !/[\s:\x00-\x1f\x7f]/.test(input);
|
|
52
|
+
const tokenValid = (input) => !!input && input.length <= 8192 && !/[\s\x00-\x1f\x7f]/.test(input);
|
|
53
|
+
const profilePath = (options) => options.profileFile ?? namedPath(configBase(options.env ?? process.env, options.home ?? homedir()), ['remote', 'profiles.json']);
|
|
54
|
+
/** Open the file itself without following a symlink; nonblocking also rejects FIFOs safely. */
|
|
55
|
+
function privateFile(path, limit) {
|
|
56
|
+
let fd;
|
|
57
|
+
try {
|
|
58
|
+
fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
|
|
59
|
+
const stat = fstatSync(fd);
|
|
60
|
+
if (!stat.isFile() || (stat.mode & 0o777) !== 0o600 || (process.getuid && stat.uid !== process.getuid()) || stat.size > limit)
|
|
61
|
+
throw new Error();
|
|
62
|
+
const bytes = readFileSync(fd);
|
|
63
|
+
if (bytes.length > limit)
|
|
64
|
+
throw new Error();
|
|
65
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
throw new UsageError('The credential file must be an owned, private (chmod 600), regular UTF-8 file.');
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
if (fd !== undefined)
|
|
72
|
+
closeSync(fd);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function profiles(options) {
|
|
76
|
+
const path = profilePath(options);
|
|
77
|
+
// lstat distinguishes a dangling symlink from a missing profile.
|
|
78
|
+
try {
|
|
79
|
+
lstatSync(path);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error.code === 'ENOENT')
|
|
83
|
+
return null;
|
|
84
|
+
throw new UsageError('The remote profile cannot be read.');
|
|
85
|
+
}
|
|
86
|
+
const raw = privateFile(path, 128 * 1024);
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(raw);
|
|
89
|
+
if (!record(parsed) || parsed.version !== 1 || typeof parsed.active !== 'string' || !record(parsed.profiles))
|
|
90
|
+
throw new Error();
|
|
91
|
+
for (const [name, one] of Object.entries(parsed.profiles)) {
|
|
92
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(name) || !record(one) || typeof one.origin !== 'string' || sessionServiceOrigin(one.origin) !== one.origin || typeof one.account !== 'string' || !accountValid(one.account) || typeof one.token !== 'string' || !tokenValid(one.token))
|
|
93
|
+
throw new Error();
|
|
94
|
+
}
|
|
95
|
+
if (!Object.hasOwn(parsed.profiles, parsed.active))
|
|
96
|
+
throw new Error();
|
|
97
|
+
return parsed;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
throw new UsageError('The remote profile is invalid. Connect again using a private credential source.');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function saveProfile(options, name, profile) {
|
|
104
|
+
const path = profilePath(options), directory = dirname(path);
|
|
105
|
+
const saved = profiles(options) ?? { version: 1, active: name, profiles: {} };
|
|
106
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
107
|
+
const parent = lstatSync(directory);
|
|
108
|
+
if (!parent.isDirectory() || (parent.mode & 0o777) !== 0o700 || (process.getuid && parent.uid !== process.getuid()))
|
|
109
|
+
throw new UsageError('The remote profile directory must be owned and private (chmod 700).');
|
|
110
|
+
saved.active = name;
|
|
111
|
+
Object.defineProperty(saved.profiles, name, { value: profile, enumerable: true, configurable: true, writable: true });
|
|
112
|
+
const temporary = join(directory, `.profile-${randomBytes(16).toString('hex')}`);
|
|
113
|
+
let fd;
|
|
114
|
+
try {
|
|
115
|
+
fd = openSync(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
116
|
+
writeFileSync(fd, `${JSON.stringify(saved)}\n`);
|
|
117
|
+
fsyncSync(fd);
|
|
118
|
+
closeSync(fd);
|
|
119
|
+
fd = undefined;
|
|
120
|
+
renameSync(temporary, path);
|
|
121
|
+
fd = openSync(directory, constants.O_RDONLY);
|
|
122
|
+
fsyncSync(fd);
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
if (fd !== undefined)
|
|
126
|
+
closeSync(fd);
|
|
127
|
+
if (existsSync(temporary))
|
|
128
|
+
unlinkSync(temporary);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function stdinSecret() {
|
|
132
|
+
if (process.stdin.isTTY)
|
|
133
|
+
throw new UsageError('Pipe your sign-in secret into --token-stdin, or use --token-file.');
|
|
134
|
+
const chunks = [];
|
|
135
|
+
let size = 0;
|
|
136
|
+
for await (const part of process.stdin) {
|
|
137
|
+
const chunk = Buffer.from(part);
|
|
138
|
+
size += chunk.length;
|
|
139
|
+
if (size > 8192)
|
|
140
|
+
throw new UsageError('The sign-in secret is too large.');
|
|
141
|
+
chunks.push(chunk);
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
return new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks));
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
throw new UsageError('The sign-in secret must be UTF-8.');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function parse(argv) {
|
|
151
|
+
const command = argv[0] ?? '', action = ['lead', 'conversation'].includes(command) ? argv[1] ?? '' : '';
|
|
152
|
+
const start = action ? 2 : 1;
|
|
153
|
+
const common = ['profile', 'json', 'help'];
|
|
154
|
+
const allowed = new Set([...common, ...(command === 'connect' ? ['as', 'token-stdin', 'token-file', 'local-login', 'login-file'] : command === 'chat' ? ['lead', 'conversation', 'say', 'follow', 'authorize', 'terms-digest', 'request-id'] : command === 'brief' ? ['lead', 'conversation', 'request-id'] : command === 'lead' ? action === 'list' ? [] : action === 'create' ? ['name', 'instructions', 'project'] : action === 'update' ? ['lead', 'revision', 'name', 'instructions', 'status'] : action === 'member' ? ['lead', 'account', 'role', 'active', 'revision'] : action === 'transfer' ? ['task', 'lead', 'revision'] : [] : action === 'list' ? ['lead'] : action === 'create' ? ['lead', 'title', 'visibility', 'project'] : action === 'member' ? ['conversation', 'account', 'role', 'active', 'revision'] : action === 'edit' ? ['conversation', 'message', 'revision', 'text'] : action === 'withdraw' ? ['conversation', 'message', 'revision'] : action === 'read' || action === 'stop' ? ['conversation', 'message'] : action === 'follow' ? ['conversation', 'enabled'] : ['conversation'])]);
|
|
155
|
+
const switches = new Set(['json', 'help', 'token-stdin', 'local-login', 'follow', 'authorize']);
|
|
156
|
+
const flags = {}, positions = [];
|
|
157
|
+
for (let index = start; index < argv.length; index++) {
|
|
158
|
+
const arg = argv[index];
|
|
159
|
+
if (!arg.startsWith('--')) {
|
|
160
|
+
positions.push(arg);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const name = arg.slice(2);
|
|
164
|
+
if (!allowed.has(name))
|
|
165
|
+
throw new UsageError('Unsupported option. Use --help for this command; secrets must come from stdin or a private file.');
|
|
166
|
+
if (Object.hasOwn(flags, name) && name !== 'project')
|
|
167
|
+
throw new UsageError(`Use --${name} only once.`);
|
|
168
|
+
if (switches.has(name))
|
|
169
|
+
flags[name] = true;
|
|
170
|
+
else {
|
|
171
|
+
const next = argv[++index];
|
|
172
|
+
if (!next || next.startsWith('--'))
|
|
173
|
+
throw new UsageError(`--${name} needs a value.`);
|
|
174
|
+
if (name === 'project')
|
|
175
|
+
flags[name] = [...(Array.isArray(flags[name]) ? flags[name] : []), next];
|
|
176
|
+
else
|
|
177
|
+
flags[name] = next;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (positions.length !== (command === 'connect' ? 1 : 0) && !flags.help)
|
|
181
|
+
throw new UsageError(command === 'connect' ? 'Name one service origin.' : 'Use named options for this command.');
|
|
182
|
+
return { command, action, flags, positions };
|
|
183
|
+
}
|
|
184
|
+
function isMessage(one) {
|
|
185
|
+
return record(one) && Number.isSafeInteger(one.id) && typeof one.author === 'string' && ['operator', 'assistant'].includes(String(one.role)) && typeof one.text === 'string' && ['queued', 'running', 'answered', 'failed', 'cancelled', 'uncertain'].includes(String(one.status)) && Number.isSafeInteger(one.revision) && typeof one.createdAt === 'string' && (one.requestId === null || typeof one.requestId === 'string') && (one.turnId === null || Number.isSafeInteger(one.turnId)) && (one.error === null || typeof one.error === 'string');
|
|
186
|
+
}
|
|
187
|
+
function isSnapshot(one) {
|
|
188
|
+
if (!record(one) || !Array.isArray(one.leads) || !one.leads.every(lead => record(lead) && typeof lead.id === 'string' && typeof lead.name === 'string') || !Array.isArray(one.conversations) || !one.conversations.every(conversation => record(conversation) && typeof conversation.id === 'string' && typeof conversation.leadId === 'string' && typeof conversation.title === 'string') || !(one.selected === null || record(one.selected) && typeof one.selected.id === 'string' && typeof one.selected.leadId === 'string' && typeof one.selected.title === 'string') || !Array.isArray(one.participants) || !one.participants.every(participant => record(participant) && typeof participant.account === 'string' && ['viewer', 'contributor', 'manager'].includes(String(participant.role)) && typeof participant.active === 'boolean') || !Array.isArray(one.messages) || !one.messages.every(isMessage) || typeof one.canManage !== 'boolean' || typeof one.canSend !== 'boolean' || !Number.isSafeInteger(one.cursor) || typeof one.truncated !== 'boolean' || !strings(one.projects) || !strings(one.accounts))
|
|
189
|
+
return false;
|
|
190
|
+
if (one.chatAuthorization !== undefined) {
|
|
191
|
+
const grant = one.chatAuthorization;
|
|
192
|
+
if (!record(grant) || typeof grant.enabled !== 'boolean' || !(grant.provider === null || typeof grant.provider === 'string') || !(grant.model === null || typeof grant.model === 'string') || !Number.isSafeInteger(grant.dailyTurns) || ![grant.weeklyCeilingUsd, grant.conversationCeilingUsd].every(amount => amount === null || typeof amount === 'number' && Number.isFinite(amount) && amount >= 0) || typeof grant.termsDigest !== 'string')
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
if (one.tasks !== undefined) {
|
|
196
|
+
const tasks = one.tasks;
|
|
197
|
+
if (!record(tasks) || !record(tasks.totals) || !['all', 'needs-you', 'running', 'completed'].every(key => Number.isSafeInteger(tasks.totals[key])) || !Array.isArray(tasks.items) || !tasks.items.every(task => record(task) && typeof task.rootId === 'string' && typeof task.activeTaskId === 'string' && typeof task.title === 'string' && record(task.status) && typeof task.status.label === 'string') || !(tasks.nextCursor === null || typeof tasks.nextCursor === 'string'))
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
if (one.proposals !== undefined && (!Array.isArray(one.proposals) || !one.proposals.every(proposal => record(proposal) && Number.isSafeInteger(proposal.id) && typeof proposal.title === 'string' && typeof proposal.state === 'string' && typeof proposal.href === 'string')))
|
|
201
|
+
return false;
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
async function responseBody(response) {
|
|
205
|
+
if (!response.body)
|
|
206
|
+
throw new Error();
|
|
207
|
+
const reader = response.body.getReader(), chunks = [];
|
|
208
|
+
let size = 0;
|
|
209
|
+
try {
|
|
210
|
+
while (true) {
|
|
211
|
+
const chunk = await reader.read();
|
|
212
|
+
if (chunk.done)
|
|
213
|
+
break;
|
|
214
|
+
size += chunk.value.byteLength;
|
|
215
|
+
if (size > 2 * 1024 * 1024) {
|
|
216
|
+
await reader.cancel();
|
|
217
|
+
throw new Error();
|
|
218
|
+
}
|
|
219
|
+
chunks.push(chunk.value);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
finally {
|
|
223
|
+
reader.releaseLock();
|
|
224
|
+
}
|
|
225
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks)));
|
|
226
|
+
}
|
|
227
|
+
function failure(code, message, result) { return { version: 1, ok: false, code, message, ...(result === undefined ? {} : { result }) }; }
|
|
228
|
+
async function perform(profile, request, options) {
|
|
229
|
+
const reading = ['list', 'show'].includes(request.operation);
|
|
230
|
+
const unconfirmed = () => failure(reading ? 'service-unavailable' : 'delivery-unconfirmed', reading ? 'The service response could not be read.' : 'The response could not be confirmed. Inspect saved messages before continuing; this request was not retried.', { operation: request.operation, ...(request.args.conversationId ? { conversationId: request.args.conversationId } : {}), ...(request.args.requestId ? { requestId: request.args.requestId } : {}) });
|
|
231
|
+
try {
|
|
232
|
+
const response = await (options.fetch ?? fetch)(`${profile.origin}/api/team`, { method: 'POST', redirect: 'manual', credentials: 'omit', signal: options.signal ? AbortSignal.any([options.signal, AbortSignal.timeout(30_000)]) : AbortSignal.timeout(30_000), headers: { authorization: `Bearer ${profile.account}:${profile.token}`, 'content-type': 'application/json', accept: 'application/json' }, body: JSON.stringify(request) });
|
|
233
|
+
if (response.status >= 300 && response.status < 400) {
|
|
234
|
+
await response.body?.cancel();
|
|
235
|
+
return unconfirmed();
|
|
236
|
+
}
|
|
237
|
+
const payload = await responseBody(response);
|
|
238
|
+
if (!record(payload) || payload.version !== 1 || typeof payload.ok !== 'boolean' || typeof payload.code !== 'string' || typeof payload.message !== 'string' || payload.snapshot !== undefined && !isSnapshot(payload.snapshot) || payload.ok && !response.ok)
|
|
239
|
+
return unconfirmed();
|
|
240
|
+
const reply = payload;
|
|
241
|
+
if (reply.ok && reading && !reply.snapshot)
|
|
242
|
+
return unconfirmed();
|
|
243
|
+
if (reply.ok && request.args.conversationId && reply.snapshot && reply.snapshot.selected?.id !== request.args.conversationId)
|
|
244
|
+
return unconfirmed();
|
|
245
|
+
if (reply.ok && request.operation === 'send' && !reply.snapshot?.messages.some(message => message.requestId === request.args.requestId && message.role === 'operator' && message.author === profile.account && message.text === request.args.text))
|
|
246
|
+
return unconfirmed();
|
|
247
|
+
return request.operation === 'send'
|
|
248
|
+
? { ...reply, result: { ...(record(reply.result) ? reply.result : {}), requestId: request.args.requestId, conversationId: request.args.conversationId } }
|
|
249
|
+
: reply;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return unconfirmed();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function terms(grant) {
|
|
256
|
+
return `Paid chat: ${grant.provider ?? 'not configured'} / ${grant.model ?? 'not configured'}\nDaily turns: ${grant.dailyTurns}\nWeekly ceiling: ${grant.weeklyCeilingUsd === null ? 'not set' : `$${grant.weeklyCeilingUsd}`}\nConversation ceiling: ${grant.conversationCeilingUsd === null ? 'not set' : `$${grant.conversationCeilingUsd}`}\nTerms: ${grant.termsDigest}${grant.waitingReason ? `\n${grant.waitingReason}` : ''}`;
|
|
257
|
+
}
|
|
258
|
+
function render(reply, listing) {
|
|
259
|
+
const lines = [reply.message], snapshot = reply.snapshot;
|
|
260
|
+
if (snapshot && listing) {
|
|
261
|
+
if (listing === 'leads')
|
|
262
|
+
for (const lead of snapshot.leads)
|
|
263
|
+
lines.push(`${lead.id} ${lead.name} · ${lead.status} · revision ${lead.revision}`);
|
|
264
|
+
else
|
|
265
|
+
for (const conversation of snapshot.conversations)
|
|
266
|
+
lines.push(`${conversation.id} ${conversation.title} · lead ${conversation.leadId} · ${conversation.visibility} · revision ${conversation.revision}`);
|
|
267
|
+
if (lines.length === 1)
|
|
268
|
+
lines.push(listing === 'leads' ? 'No leads yet.' : 'No conversations yet.');
|
|
269
|
+
return text(lines.join('\n'));
|
|
270
|
+
}
|
|
271
|
+
if (snapshot) {
|
|
272
|
+
if (snapshot.selected)
|
|
273
|
+
lines.push(`${snapshot.selected.title} · ${snapshot.selected.id} · revision ${snapshot.selected.revision}`, `Lead: ${snapshot.selected.leadId}`);
|
|
274
|
+
else {
|
|
275
|
+
for (const lead of snapshot.leads)
|
|
276
|
+
lines.push(`${lead.id} ${lead.name}`);
|
|
277
|
+
for (const conversation of snapshot.conversations)
|
|
278
|
+
lines.push(`${conversation.id} ${conversation.title} (${conversation.leadId})`);
|
|
279
|
+
}
|
|
280
|
+
for (const message of snapshot.messages)
|
|
281
|
+
lines.push(`${message.author} · ${message.status} · message ${message.id} · revision ${message.revision}${message.requestId ? ` · request ${message.requestId}` : ''}\n${message.text}${message.error ? `\n${message.error}` : ''}`);
|
|
282
|
+
if (snapshot.tasks) {
|
|
283
|
+
const totals = snapshot.tasks.totals;
|
|
284
|
+
lines.push(`Work: ${totals.all} total · ${totals['needs-you']} need you · ${totals.running} running · ${totals.completed} complete`);
|
|
285
|
+
for (const task of snapshot.tasks.items)
|
|
286
|
+
lines.push(`${task.activeTaskId} ${task.status.label} ${task.title}`);
|
|
287
|
+
if (snapshot.tasks.nextCursor)
|
|
288
|
+
lines.push('More tasks are available in the browser.');
|
|
289
|
+
}
|
|
290
|
+
for (const proposal of snapshot.proposals ?? [])
|
|
291
|
+
lines.push(`Proposal ${proposal.id} · ${proposal.state}: ${proposal.title}\n${proposal.href}`);
|
|
292
|
+
if (snapshot.truncated)
|
|
293
|
+
lines.push('Earlier messages are available in the browser.');
|
|
294
|
+
}
|
|
295
|
+
if (reply.code === 'grant-needed' && snapshot?.chatAuthorization)
|
|
296
|
+
lines.push(terms(snapshot.chatAuthorization), 'Review these terms, then use --authorize --terms-digest with this exact digest.');
|
|
297
|
+
if (record(reply.result)) {
|
|
298
|
+
for (const [key, label] of [['leadId', 'Lead'], ['conversationId', 'Conversation'], ['taskId', 'Task'], ['messageId', 'Message'], ['revision', 'Revision'], ['requestId', 'Request']]) {
|
|
299
|
+
if (typeof reply.result[key] === 'string' || typeof reply.result[key] === 'number')
|
|
300
|
+
lines.push(`${label}: ${reply.result[key]}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return text(lines.join('\n'));
|
|
304
|
+
}
|
|
305
|
+
/** null means preserve the existing local command path. Nothing here opens a database. */
|
|
306
|
+
export async function maybeRunTeamCommand(argv, write, options = {}) {
|
|
307
|
+
const command = argv[0];
|
|
308
|
+
if (!['connect', 'lead', 'conversation', 'chat', 'brief'].includes(command ?? '') && !argv.includes('--profile'))
|
|
309
|
+
return null;
|
|
310
|
+
const json = argv.includes('--json');
|
|
311
|
+
let secret = '';
|
|
312
|
+
const stderr = (line) => (options.stderr ?? (line => process.stderr.write(`${line}\n`)))(text(secret ? line.replaceAll(secret, '[redacted]') : line));
|
|
313
|
+
const emit = (reply) => {
|
|
314
|
+
const safe = JSON.parse(JSON.stringify(reply, (_key, one) => typeof one === 'string' && secret ? one.replaceAll(secret, '[redacted]') : one));
|
|
315
|
+
const listing = argv[1] === 'list' ? command === 'lead' ? 'leads' : command === 'conversation' ? 'conversations' : undefined : undefined;
|
|
316
|
+
write(json ? envelopeJson({ ...safe, command: `team ${command}` }) : render(safe, listing));
|
|
317
|
+
};
|
|
318
|
+
try {
|
|
319
|
+
if (!['connect', 'lead', 'conversation', 'chat', 'brief'].includes(command ?? ''))
|
|
320
|
+
throw new UsageError('--profile is supported by lead, conversation, chat and brief. No local command was run.');
|
|
321
|
+
if ((command === 'chat' || command === 'brief') && argv.includes('--local')) {
|
|
322
|
+
if (argv.some(arg => ['--profile', '--lead', '--conversation', '--authorize', '--terms-digest', '--request-id'].includes(arg)))
|
|
323
|
+
throw new UsageError('--local cannot be combined with central team options.');
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
const explicit = ['connect', 'lead', 'conversation'].includes(command) || argv.some(arg => ['--profile', '--lead', '--conversation', '--authorize', '--terms-digest', '--request-id'].includes(arg));
|
|
327
|
+
if (explicit && (argv.includes('--help') || ['lead', 'conversation'].includes(command) && argv.length === 1)) {
|
|
328
|
+
write(HELP);
|
|
329
|
+
return 0;
|
|
330
|
+
}
|
|
331
|
+
const saved = profiles(options);
|
|
332
|
+
if (!explicit && !saved)
|
|
333
|
+
return null;
|
|
334
|
+
const parsed = parse(argv), { flags, action } = parsed;
|
|
335
|
+
if (flags.help || ((command === 'lead' || command === 'conversation') && !action)) {
|
|
336
|
+
write(HELP);
|
|
337
|
+
return 0;
|
|
338
|
+
}
|
|
339
|
+
const profileName = value(flags, 'profile') || (command === 'connect' ? 'default' : saved?.active ?? 'default');
|
|
340
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(profileName))
|
|
341
|
+
throw new UsageError('Profile names use 1–64 letters, digits, underscores or hyphens.');
|
|
342
|
+
if (command === 'connect') {
|
|
343
|
+
let origin;
|
|
344
|
+
try {
|
|
345
|
+
origin = sessionServiceOrigin(parsed.positions[0]);
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
throw new UsageError('Use an HTTPS service origin (loopback HTTP is allowed), without credentials, paths, query or fragment.');
|
|
349
|
+
}
|
|
350
|
+
if (['token-stdin', 'token-file', 'local-login'].filter(name => flags[name]).length !== 1)
|
|
351
|
+
throw new UsageError('Choose one credential source: --token-stdin, --token-file or --local-login.');
|
|
352
|
+
if (flags['login-file'] && !flags['local-login'])
|
|
353
|
+
throw new UsageError('--login-file requires --local-login.');
|
|
354
|
+
let account = value(flags, 'as');
|
|
355
|
+
if (flags['local-login']) {
|
|
356
|
+
const login = privateFile(value(flags, 'login-file') || join(dirname(databasePath(options.env ?? process.env, options.home ?? homedir())), 'up-login.txt'), 8192).trim().split(/\s+/);
|
|
357
|
+
if (login.length !== 2 || account && account !== login[0])
|
|
358
|
+
throw new UsageError('The local sign-in does not match the requested account.');
|
|
359
|
+
account = login[0];
|
|
360
|
+
secret = login[1];
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
secret = (flags['token-file'] ? privateFile(value(flags, 'token-file'), 8192) : await (options.readStdin ?? stdinSecret)()).trim();
|
|
364
|
+
if (!accountValid(account) || !tokenValid(secret))
|
|
365
|
+
throw new UsageError('Provide an account name and a valid sign-in secret from your selected source.');
|
|
366
|
+
const profile = { origin, account, token: secret }, checked = await perform(profile, { operation: 'list', args: {} }, options);
|
|
367
|
+
if (!checked.ok) {
|
|
368
|
+
emit(checked);
|
|
369
|
+
return 1;
|
|
370
|
+
}
|
|
371
|
+
saveProfile(options, profileName, profile);
|
|
372
|
+
emit({ version: 1, ok: true, code: 'connected', message: `Connected to ${origin} as ${account}.`, result: { profile: profileName, origin, account } });
|
|
373
|
+
return 0;
|
|
374
|
+
}
|
|
375
|
+
const profile = saved?.profiles[profileName];
|
|
376
|
+
if (!profile || !Object.hasOwn(saved.profiles, profileName))
|
|
377
|
+
throw new UsageError('No saved connection. Use connect with your individual sign-in first.');
|
|
378
|
+
secret = profile.token;
|
|
379
|
+
const call = (operation, args) => perform(profile, { operation, args }, options);
|
|
380
|
+
if (command === 'chat' || command === 'brief')
|
|
381
|
+
return await chat(command, flags, profile.account, call, emit, options, stderr);
|
|
382
|
+
let operation, args = {};
|
|
383
|
+
if (action === 'list') {
|
|
384
|
+
operation = 'list';
|
|
385
|
+
if (flags.lead)
|
|
386
|
+
args.leadId = value(flags, 'lead');
|
|
387
|
+
}
|
|
388
|
+
else if (command === 'lead') {
|
|
389
|
+
if (action === 'create') {
|
|
390
|
+
operation = 'create-lead';
|
|
391
|
+
args = { name: required(flags, 'name'), instructions: required(flags, 'instructions'), projects: flags.project ?? [] };
|
|
392
|
+
}
|
|
393
|
+
else if (action === 'update') {
|
|
394
|
+
operation = 'update-lead';
|
|
395
|
+
args = { leadId: required(flags, 'lead'), expectedRevision: number(flags, 'revision') };
|
|
396
|
+
for (const name of ['name', 'instructions', 'status'])
|
|
397
|
+
if (flags[name])
|
|
398
|
+
args[name] = value(flags, name);
|
|
399
|
+
}
|
|
400
|
+
else if (action === 'member') {
|
|
401
|
+
operation = 'member';
|
|
402
|
+
args = { leadId: required(flags, 'lead'), account: required(flags, 'account'), role: required(flags, 'role'), active: bool(flags, 'active'), expectedRevision: number(flags, 'revision') };
|
|
403
|
+
}
|
|
404
|
+
else if (action === 'transfer') {
|
|
405
|
+
operation = 'transfer';
|
|
406
|
+
args = { leadId: required(flags, 'lead'), taskId: required(flags, 'task'), expectedRevision: number(flags, 'revision') };
|
|
407
|
+
}
|
|
408
|
+
else
|
|
409
|
+
throw new UsageError('Choose lead list, create, update, member or transfer.');
|
|
410
|
+
}
|
|
411
|
+
else if (action === 'create') {
|
|
412
|
+
operation = 'create-conversation';
|
|
413
|
+
args = { leadId: required(flags, 'lead'), title: required(flags, 'title'), visibility: required(flags, 'visibility'), projects: flags.project ?? [] };
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
args.conversationId = required(flags, 'conversation');
|
|
417
|
+
if (action === 'show')
|
|
418
|
+
operation = 'show';
|
|
419
|
+
else if (action === 'member') {
|
|
420
|
+
operation = 'member';
|
|
421
|
+
Object.assign(args, { account: required(flags, 'account'), role: required(flags, 'role'), active: bool(flags, 'active'), expectedRevision: number(flags, 'revision') });
|
|
422
|
+
}
|
|
423
|
+
else if (action === 'edit' || action === 'withdraw') {
|
|
424
|
+
operation = action;
|
|
425
|
+
Object.assign(args, { messageId: number(flags, 'message'), expectedRevision: number(flags, 'revision'), ...(action === 'edit' ? { text: required(flags, 'text') } : {}) });
|
|
426
|
+
}
|
|
427
|
+
else if (action === 'read' || action === 'stop') {
|
|
428
|
+
operation = action;
|
|
429
|
+
args.messageId = number(flags, 'message');
|
|
430
|
+
}
|
|
431
|
+
else if (action === 'follow') {
|
|
432
|
+
operation = 'follow';
|
|
433
|
+
args.enabled = bool(flags, 'enabled');
|
|
434
|
+
}
|
|
435
|
+
else
|
|
436
|
+
throw new UsageError('Choose a conversation operation from --help.');
|
|
437
|
+
}
|
|
438
|
+
const reply = await call(operation, args);
|
|
439
|
+
emit(reply);
|
|
440
|
+
return reply.ok ? 0 : 1;
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
const reply = failure('usage', error instanceof UsageError ? error.message : 'The remote command could not be prepared. Check the private profile and credential files.');
|
|
444
|
+
if (json)
|
|
445
|
+
emit(reply);
|
|
446
|
+
else
|
|
447
|
+
stderr(text(reply.message));
|
|
448
|
+
return 2;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async function chat(command, flags, account, call, emit, options, stderr) {
|
|
452
|
+
const conversationId = required(flags, 'conversation'), leadId = value(flags, 'lead'), requestId = value(flags, 'request-id');
|
|
453
|
+
if (requestId && !/^[0-9a-f]{32}$/.test(requestId))
|
|
454
|
+
throw new UsageError('--request-id must be 32 lowercase hexadecimal characters.');
|
|
455
|
+
if (flags['terms-digest'] && !flags.authorize)
|
|
456
|
+
throw new UsageError('--terms-digest requires --authorize.');
|
|
457
|
+
if (command === 'chat' && requestId && !flags.say)
|
|
458
|
+
throw new UsageError('Use brief --request-id to inspect a previous message.');
|
|
459
|
+
const show = async () => {
|
|
460
|
+
const reply = await call('show', { conversationId });
|
|
461
|
+
if (reply.ok && (!reply.snapshot || reply.snapshot.selected?.id !== conversationId || leadId && reply.snapshot.selected.leadId !== leadId))
|
|
462
|
+
return failure('conversation-mismatch', 'The service returned a different conversation or lead. Nothing was sent.');
|
|
463
|
+
return reply;
|
|
464
|
+
};
|
|
465
|
+
let current = await show();
|
|
466
|
+
if (!current.ok) {
|
|
467
|
+
emit(current);
|
|
468
|
+
return 1;
|
|
469
|
+
}
|
|
470
|
+
if (command === 'brief') {
|
|
471
|
+
if (requestId) {
|
|
472
|
+
const message = current.snapshot.messages.find(one => one.requestId === requestId && one.author === account && one.role === 'operator');
|
|
473
|
+
current = { ...current, result: { requestId, receipt: message ?? null, receiptStatus: message ? 'recorded' : 'not-in-current-page' }, message: message ? `Saved message ${message.id}: ${message.status}.` : 'This request is not in the current message page. Inspect the conversation before sending anything again.' };
|
|
474
|
+
}
|
|
475
|
+
emit(current);
|
|
476
|
+
return 0;
|
|
477
|
+
}
|
|
478
|
+
const interactive = !flags.say && !flags.follow && !flags.json && (options.isTTY ?? process.stdin.isTTY ?? false);
|
|
479
|
+
const controller = new AbortController();
|
|
480
|
+
const signal = options.signal ? AbortSignal.any([options.signal, controller.signal]) : controller.signal;
|
|
481
|
+
const readline = interactive && !options.readLine ? createInterface({ input: process.stdin, output: process.stderr, terminal: true }) : undefined;
|
|
482
|
+
const interrupt = () => controller.abort();
|
|
483
|
+
if (interactive || flags.follow)
|
|
484
|
+
process.once('SIGINT', interrupt);
|
|
485
|
+
const ask = options.readLine ?? (async (prompt) => { try {
|
|
486
|
+
return await readline.question(prompt, { signal });
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
489
|
+
return null;
|
|
490
|
+
} });
|
|
491
|
+
const observed = new Map();
|
|
492
|
+
let observedView = '';
|
|
493
|
+
const viewKey = (reply) => JSON.stringify(reply.snapshot && { selected: reply.snapshot.selected, participants: reply.snapshot.participants, tasks: reply.snapshot.tasks, proposals: reply.snapshot.proposals, authorization: reply.snapshot.chatAuthorization, canSend: reply.snapshot.canSend });
|
|
494
|
+
const remember = (reply) => { observedView = viewKey(reply); for (const message of reply.snapshot?.messages ?? [])
|
|
495
|
+
observed.set(message.id, JSON.stringify(message)); };
|
|
496
|
+
const updated = (reply) => {
|
|
497
|
+
const changes = reply.snapshot?.messages.filter(message => observed.get(message.id) !== JSON.stringify(message)) ?? [];
|
|
498
|
+
if (changes.length || viewKey(reply) !== observedView) {
|
|
499
|
+
emit({ ...reply, message: 'Conversation updated.', snapshot: { ...reply.snapshot, messages: changes } });
|
|
500
|
+
remember(reply);
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
const authorize = async (explicit) => {
|
|
504
|
+
const grant = current.snapshot?.chatAuthorization;
|
|
505
|
+
if (grant?.enabled)
|
|
506
|
+
return true;
|
|
507
|
+
if (!grant) {
|
|
508
|
+
emit(failure('grant-unavailable', 'Paid chat terms are unavailable. Open this conversation in the browser.'));
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
if (explicit) {
|
|
512
|
+
if (value(flags, 'terms-digest') !== grant.termsDigest) {
|
|
513
|
+
emit({ ...failure('grant-needed', 'Review the current paid chat terms before enabling chat.'), snapshot: current.snapshot });
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
else if (interactive) {
|
|
518
|
+
stderr(text(terms(grant)));
|
|
519
|
+
if ((await ask('Enable paid chat with these terms? [y/N] '))?.trim().toLowerCase() !== 'y')
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
emit({ ...failure('grant-needed', 'Enable paid chat before sending a message.'), snapshot: current.snapshot });
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
526
|
+
const reply = await call('authorize', { conversationId, termsDigest: grant.termsDigest });
|
|
527
|
+
if (!reply.ok || !reply.snapshot?.chatAuthorization?.enabled) {
|
|
528
|
+
emit(reply.ok ? failure('grant-unconfirmed', 'Chat authorization was not confirmed. Inspect the conversation before continuing.') : reply);
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
current = reply;
|
|
532
|
+
return true;
|
|
533
|
+
};
|
|
534
|
+
const send = async (message) => {
|
|
535
|
+
if (message.length > 2000 || !message.trim())
|
|
536
|
+
throw new UsageError('Messages must contain 1–2,000 characters.');
|
|
537
|
+
// Re-read current permissions and terms before each explicit message. Attachment never authorizes.
|
|
538
|
+
current = await show();
|
|
539
|
+
if (!current.ok) {
|
|
540
|
+
emit(current);
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
if (!await authorize(!!flags.authorize))
|
|
544
|
+
return false;
|
|
545
|
+
if (!current.snapshot?.canSend) {
|
|
546
|
+
emit(failure('forbidden', 'This account cannot send to the selected conversation.'));
|
|
547
|
+
return false;
|
|
548
|
+
}
|
|
549
|
+
const id = requestId || randomBytes(16).toString('hex');
|
|
550
|
+
const reply = await call('send', { conversationId, requestId: id, text: message.trim() });
|
|
551
|
+
emit(reply);
|
|
552
|
+
if (reply.ok) {
|
|
553
|
+
current = reply;
|
|
554
|
+
remember(reply);
|
|
555
|
+
}
|
|
556
|
+
return reply.ok;
|
|
557
|
+
};
|
|
558
|
+
let pollResult = 0;
|
|
559
|
+
const poll = async () => {
|
|
560
|
+
while (!signal.aborted) {
|
|
561
|
+
try {
|
|
562
|
+
await (options.sleep ?? ((ms, abort) => delay(ms, undefined, { signal: abort })))(2_000, signal);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
if (signal.aborted)
|
|
568
|
+
break;
|
|
569
|
+
const next = await show();
|
|
570
|
+
if (!next.ok) {
|
|
571
|
+
emit(next);
|
|
572
|
+
pollResult = 1;
|
|
573
|
+
controller.abort();
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
current = next;
|
|
577
|
+
updated(next);
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
let polling;
|
|
581
|
+
try {
|
|
582
|
+
if (flags.say) {
|
|
583
|
+
if (!await send(required(flags, 'say')))
|
|
584
|
+
return 1;
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
if (flags.authorize && !await authorize(true))
|
|
588
|
+
return 1;
|
|
589
|
+
emit(current);
|
|
590
|
+
remember(current);
|
|
591
|
+
}
|
|
592
|
+
if (flags.follow) {
|
|
593
|
+
await poll();
|
|
594
|
+
return pollResult;
|
|
595
|
+
}
|
|
596
|
+
if (!interactive)
|
|
597
|
+
return 0;
|
|
598
|
+
polling = poll();
|
|
599
|
+
while (!signal.aborted) {
|
|
600
|
+
const line = await ask('You> ');
|
|
601
|
+
if (line === null || line.trim() === '/quit')
|
|
602
|
+
break;
|
|
603
|
+
if (!line.trim())
|
|
604
|
+
continue;
|
|
605
|
+
if (!await send(line)) {
|
|
606
|
+
pollResult = 1;
|
|
607
|
+
break;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return pollResult;
|
|
611
|
+
}
|
|
612
|
+
finally {
|
|
613
|
+
controller.abort();
|
|
614
|
+
readline?.close();
|
|
615
|
+
process.removeListener('SIGINT', interrupt);
|
|
616
|
+
await polling;
|
|
617
|
+
}
|
|
618
|
+
}
|