@humwick/server 0.130.1 → 0.130.3
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/README.md +5 -0
- package/bundled/prompts/manifest.json +1 -0
- package/bundled/prompts/task.hydration.md +1 -1
- package/bundled/roles/builder.md +1 -1
- package/docs/guides/sub-coordinators.md +12 -5
- package/docs/guides/tools-administration.md +4 -0
- package/docs/guides/tools-coordination.md +2 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +74 -0
- package/docs/openapi.json +486 -4
- package/package.json +10 -18
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/agent-profiles-cxtRBn6O.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-B_rFEbnL.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/index-CqqgOI5R.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/project-profile-instructions-DETKFn_E.js +2 -0
- package/public/assets/projects-M_m6AHws.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-V9Z-GxUd.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-CXU75HRF.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/use-project-list-CpWl6eHQ.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/versioned-prompt-editor-CIVg7XB1.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/claude-headless.ts +1 -1
- package/runner/src/adapters/claude-launch-exit.ts +26 -0
- package/runner/src/adapters/claude-session-probe.ts +1 -1
- package/runner/src/adapters/claude-tmux.ts +38 -10
- package/runner/src/adapters/claude.ts +28 -75
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/adapters/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -4
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/launch-assembly.ts +14 -10
- package/runner/src/profile-home.ts +1 -1
- package/runner/src/project-instructions.ts +2 -2
- package/runner/src/provider-command.ts +18 -0
- package/runner/src/provider-setup.ts +35 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +32 -38
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -1
- package/scripts/cd-config.ts +8 -0
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/scripts/steward-policy-cleanup.ts +2 -2
- package/src/agent-authz.ts +2 -2
- package/src/agent-drive-arbiter.ts +3 -8
- package/src/agent-exit-cleanup-async.ts +2 -2
- package/src/agent-exit-cleanup.ts +23 -19
- package/src/agent-lifecycle-events.ts +112 -85
- package/src/agent-ref.ts +3 -2
- package/src/agent-status-events.ts +43 -14
- package/src/auth/password.ts +4 -3
- package/src/auth/session-refresh.ts +1 -1
- package/src/auth/session.test-fixture.ts +2 -2
- package/src/auth/session.ts +7 -7
- package/src/automations/crud.ts +8 -81
- package/src/automations/dispatch.ts +33 -58
- package/src/automations/index.ts +1 -1
- package/src/automations/persistence.ts +65 -0
- package/src/automations/precheck.ts +18 -16
- package/src/automations/read-async.ts +11 -0
- package/src/automations/reconcile.ts +30 -39
- package/src/automations/storage.ts +33 -10
- package/src/automations/write-async.ts +33 -0
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +31 -98
- package/src/bus.ts +40 -39
- package/src/cd-deploy-notify.ts +32 -4
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +4 -9
- package/src/ci/transition-notify.ts +12 -44
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +19 -4
- package/src/commands-db.ts +7 -7
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +12 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-action-write.ts +36 -0
- package/src/db/agent-control-async.ts +9 -0
- package/src/db/agent-control-write.ts +49 -0
- package/src/db/agent-effort-observe.ts +22 -0
- package/src/db/agent-meta.ts +14 -3
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +59 -9
- package/src/db/agents-write-ops.ts +12 -3
- package/src/db/agents.ts +95 -65
- package/src/db/auth-identities.ts +2 -2
- package/src/db/automation-read-ops.ts +11 -0
- package/src/db/automation-write-ops.ts +46 -0
- package/src/db/blackboard.ts +2 -2
- package/src/db/browser-session-write.ts +32 -0
- package/src/db/bus-outbox-write-ops.ts +3 -1
- package/src/db/checkout-refresh-schema.ts +47 -0
- package/src/db/checkout-refresh.ts +5 -5
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/command-agent-profile-backfill.ts +39 -0
- package/src/db/command-agent-profiles.ts +5 -1
- package/src/db/command-retention.ts +126 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/config-store-write-ops.ts +7 -2
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +7 -0
- package/src/db/continuations.ts +6 -6
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -17
- package/src/db/index.ts +2 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +23 -0
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +15 -16
- package/src/db/kernel-event-log-schema.ts +2 -0
- package/src/db/land-boundaries.ts +51 -5
- package/src/db/land-gate-attestations.ts +2 -2
- package/src/db/landing-receipts.ts +2 -2
- package/src/db/lifecycle-context-write.ts +5 -0
- package/src/db/lifecycle-tail-async.ts +76 -0
- package/src/db/lifecycle-tail-write-ops.ts +62 -0
- package/src/db/lifecycle-write-window.ts +2 -1
- package/src/db/lineage-pair-dedupe-sql.ts +3 -3
- package/src/db/long-running-work.ts +2 -2
- package/src/db/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +41 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +25 -16
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +14 -76
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +42 -61
- package/src/db/plan-dispatch-schema.ts +5 -1
- package/src/db/plan-ready-notices.ts +43 -0
- package/src/db/plan-tools-include-migration.ts +36 -0
- package/src/db/plans-write-ops.ts +2 -0
- package/src/db/presence-buffer.ts +5 -0
- package/src/db/presence-loop.ts +18 -23
- package/src/db/presence-write.ts +0 -6
- package/src/db/project-entries-async.ts +14 -0
- package/src/db/project-entries-read-ops.ts +5 -1
- package/src/db/project-entries-write-ops.ts +8 -0
- package/src/db/project-entries.ts +15 -12
- package/src/db/project-journal.ts +2 -2
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/project-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/read-op-marshaling-fixtures.ts +23 -0
- package/src/db/read-ops.ts +8 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- package/src/db/routing-policy.ts +2 -3
- package/src/db/runtime-admin-async.ts +19 -0
- package/src/db/runtime-admin-write-ops.ts +36 -0
- package/src/db/runtime-tail-async.ts +288 -0
- package/src/db/runtime-tail-write-ops.ts +97 -0
- package/src/db/schema.ts +13 -4
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +9 -6
- package/src/db/task-entity.ts +28 -6
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-claim-policy.ts +60 -0
- package/src/db/teams-async.ts +4 -0
- package/src/db/teams-write-ops.ts +4 -0
- package/src/db/terminal-events.ts +15 -0
- package/src/db/timer-cutover-bodies.ts +292 -0
- package/src/db/timer-cutover-core.ts +37 -278
- package/src/db/timer-cutover-state.ts +40 -0
- package/src/db/timer-cutover-write-ops.ts +1 -40
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/token-db-write-ops.ts +19 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +21 -20
- package/src/db/token-usage-retention.ts +33 -0
- package/src/db/token-usage-write-ops.ts +1 -1
- package/src/db/token-usage.ts +4 -1
- package/src/db/user-invites-async.ts +13 -0
- package/src/db/user-invites.ts +3 -3
- package/src/db/users.ts +14 -6
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/workspaces.ts +8 -5
- package/src/db/write-ops.ts +37 -12
- package/src/db/writer-fault-seam.ts +2 -9
- package/src/db/writer-fault-test-ops.ts +18 -0
- package/src/db/writer-gateway.ts +58 -56
- package/src/dev.ts +8 -3
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/event-loop-lag.ts +4 -2
- package/src/event-loop-yield.ts +2 -2
- package/src/events.ts +10 -8
- package/src/host/disk-alert.ts +121 -0
- package/src/host-provider-store.ts +5 -4
- package/src/hub-metrics-report.ts +5 -1
- package/src/hub-metrics.ts +38 -18
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/land-gate-notifications.ts +11 -10
- package/src/land-gate-queue-progress.ts +3 -3
- package/src/land-settle-dispatch.ts +52 -92
- package/src/lifecycle-context-pressure.ts +11 -10
- package/src/lifecycle-manager.ts +107 -100
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +19 -20
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +32 -69
- package/src/maintenance/long-running-work.ts +3 -1
- package/src/maintenance/offline-agent-prune-job.ts +28 -0
- package/src/maintenance/orphaned-sessions.ts +5 -4
- package/src/maintenance/pauses.ts +4 -10
- package/src/maintenance/plan-ready-notice-job.ts +71 -0
- package/src/maintenance/scheduler.ts +98 -137
- package/src/maintenance/stalled-delivery-pager.ts +10 -9
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +18 -28
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +32 -28
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +12 -9
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +6 -5
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/runtime-output.ts +6 -1
- package/src/mcp/self-care-visibility.ts +2 -2
- package/src/mcp/spawn-targets-matrix.ts +10 -1
- package/src/mcp/tool-groups.ts +4 -3
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp/tools-workspace.ts +1 -1
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-blackboard-tools.ts +6 -5
- package/src/mcp-decision-tools.ts +7 -7
- package/src/mcp-egress-tools.ts +10 -9
- package/src/mcp-issue-activity-tools.ts +2 -2
- package/src/mcp-issue-association-tools.ts +4 -4
- package/src/mcp-issue-ref-tools.ts +13 -12
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-merge-tools.ts +5 -5
- package/src/mcp-notification-subscription-tools.ts +14 -15
- package/src/mcp-output-levels.test-fixture.ts +1 -1
- package/src/mcp-profile-trust-tools.ts +5 -5
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +13 -4
- package/src/memory-area-injection.ts +13 -12
- package/src/memory-boundary-capture.ts +6 -6
- package/src/memory-injection.ts +45 -43
- package/src/merge-pause-maintenance.ts +5 -4
- package/src/notification-router.ts +44 -17
- package/src/notification-types.ts +2 -1
- package/src/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +23 -11
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +12 -1
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +6 -5
- package/src/repo-config-source.ts +10 -4
- package/src/retention-config-store.ts +4 -3
- package/src/reviewer-pipeline.ts +11 -10
- package/src/routes/_route.ts +4 -4
- package/src/routes/_shared.ts +13 -12
- package/src/routes/agent-effort.ts +5 -5
- package/src/routes/agent-heartbeat-quota.ts +23 -0
- package/src/routes/agent-keep.ts +1 -1
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agent-reporting.ts +1 -1
- package/src/routes/agent-self-effort.ts +5 -5
- package/src/routes/agent-sessions.ts +24 -24
- package/src/routes/agents-spawn.ts +2 -2
- package/src/routes/agents.ts +19 -121
- package/src/routes/auth.ts +14 -15
- package/src/routes/authority-audit.ts +2 -2
- package/src/routes/automations.ts +6 -5
- package/src/routes/channel-binding-delete.ts +1 -1
- package/src/routes/channel-output.ts +3 -3
- package/src/routes/claude-api-budget.ts +5 -5
- package/src/routes/commands-listing.ts +5 -1
- package/src/routes/commands.ts +31 -29
- package/src/routes/context-resets.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/coordinator-teams.ts +1 -1
- package/src/routes/decisions.ts +2 -2
- package/src/routes/host-secret-files.ts +1 -1
- package/src/routes/hosts.ts +11 -11
- package/src/routes/inbox.ts +3 -2
- package/src/routes/index.ts +12 -2
- package/src/routes/integrations.ts +32 -56
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +9 -9
- package/src/routes/kernel-timers-operator.ts +1 -1
- package/src/routes/memory.ts +1 -1
- package/src/routes/merges.ts +11 -11
- package/src/routes/messages.ts +23 -17
- package/src/routes/orchestrator-bootstrap.ts +2 -2
- package/src/routes/orchestrator-host-registration.ts +4 -2
- package/src/routes/orchestrator-host-utilization.ts +5 -3
- package/src/routes/orchestrator-proxy.ts +4 -4
- package/src/routes/orchestrator.ts +28 -19
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +3 -3
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- package/src/routes/provider-config.ts +6 -6
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/provider-quotas.ts +10 -10
- package/src/routes/run-command.ts +1 -1
- package/src/routes/secrets-backup.ts +2 -2
- package/src/routes/secrets-import.ts +1 -1
- package/src/routes/secrets-vault.ts +7 -7
- package/src/routes/settings.ts +6 -6
- package/src/routes/shipping.ts +9 -1
- package/src/routes/spawn-policy.ts +8 -7
- package/src/routes/sse.ts +2 -2
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +12 -12
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +30 -22
- package/src/routes/users.ts +24 -24
- package/src/routes/viewer-read.ts +3 -3
- package/src/routes/web-tool-calls.ts +4 -4
- package/src/routes/workflows.ts +22 -7
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-policy-push.ts +6 -6
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +21 -13
- package/src/runtime-tokens.ts +59 -35
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +16 -21
- package/src/self-resume-carry.ts +21 -110
- package/src/self-resume-supersede.ts +4 -3
- package/src/self-resume.ts +54 -66
- package/src/server-background.ts +2 -2
- package/src/server.ts +26 -24
- package/src/services/agent-action.ts +12 -31
- package/src/services/agent-effort.ts +7 -32
- package/src/services/agent-hang-watchdog-job.ts +2 -2
- package/src/services/agent-heartbeat.ts +166 -0
- package/src/services/agent-reporting.ts +1 -1
- package/src/services/browser-inventory.ts +3 -3
- package/src/services/browser-session-state.ts +3 -2
- package/src/services/browser-session.ts +21 -27
- package/src/services/bus-command-update.ts +9 -9
- package/src/services/checkout-refresh-state.ts +1 -0
- package/src/services/checkout-refresh.test-fixture.ts +3 -2
- package/src/services/command-host.ts +7 -2
- package/src/services/coordinator-digest.ts +3 -2
- package/src/services/dispatch-command.ts +12 -13
- package/src/services/effective-launch-driver.ts +14 -9
- package/src/services/host-changed-paths.test-fixture.ts +5 -6
- package/src/services/host-project-readiness.ts +2 -2
- package/src/services/host-providers.ts +1 -1
- package/src/services/host-utilization.ts +27 -4
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +9 -10
- package/src/services/interrupt-agent.ts +12 -9
- package/src/services/issue-activity.ts +3 -3
- package/src/services/issue-associations.ts +15 -18
- package/src/services/issue-lifecycle-comments.ts +3 -2
- package/src/services/issue-lifecycle.ts +69 -72
- package/src/services/issue-refs.ts +10 -15
- package/src/services/kernel-timers-cutover-chaos-worker.ts +11 -8
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +4 -4
- package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
- package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
- package/src/services/kernel-timers-outbox.ts +1 -1
- package/src/services/kernel-timers-stage10-operator.ts +1 -1
- package/src/services/kernel-timers.ts +4 -3
- package/src/services/land-gate-placement.ts +11 -2
- package/src/services/land-issue-relations.ts +5 -4
- package/src/services/land-restart-retry.ts +7 -6
- package/src/services/landed-ancestry.ts +25 -8
- package/src/services/legacy-landing-host.ts +4 -1
- package/src/services/legacy-landing-recovery.ts +8 -6
- package/src/services/managed-running.ts +17 -17
- package/src/services/memory-areas.ts +17 -53
- package/src/services/merge-pause.ts +9 -15
- package/src/services/operator-decisions.ts +37 -41
- package/src/services/orchestrator-registration-recovery.ts +6 -2
- package/src/services/orchestrator-upgrade.ts +14 -12
- package/src/services/permission-decision.ts +4 -3
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-conformance.ts +4 -4
- package/src/services/plan-dispatch-policy.ts +10 -3
- package/src/services/plan-dispatch.ts +35 -14
- package/src/services/plan-graph.ts +39 -261
- package/src/services/plan-import.ts +1 -1
- package/src/services/plan-live-bindings.ts +8 -37
- package/src/services/plan-task-create.ts +1 -1
- package/src/services/plan-terminal-refs.ts +2 -12
- package/src/services/plan-wake-digest.ts +9 -3
- package/src/services/profile-trust.ts +6 -5
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/project.ts +11 -10
- package/src/services/prompt-templates.ts +6 -5
- package/src/services/provider-hold-nudge.ts +9 -9
- package/src/services/provider-hold-record.ts +13 -12
- package/src/services/provider-state-audit.ts +19 -18
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/provisioning-harness/driver.ts +1 -1
- package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
- package/src/services/provisioning-harness/lifecycle.ts +24 -22
- package/src/services/provisioning-harness/prepare.ts +16 -17
- package/src/services/rate-limit-resume.ts +10 -9
- package/src/services/red-main-auto-revert.ts +7 -5
- package/src/services/red-main-controller-deps.ts +20 -3
- package/src/services/red-main-incident.ts +3 -1
- package/src/services/red-main-quarantine.ts +2 -3
- package/src/services/register-agent.ts +22 -22
- package/src/services/restart-project-role.ts +1 -1
- package/src/services/restart-spawn.ts +74 -61
- package/src/services/review-publish.ts +7 -24
- package/src/services/review-ref-reconcile.ts +29 -38
- package/src/services/runtime-dependency-alert.ts +27 -0
- package/src/services/scheduler-command.ts +11 -9
- package/src/services/scheduler.ts +5 -5
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort-grant.ts +5 -25
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +21 -34
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +25 -43
- package/src/services/spawn-chain-inspector.ts +7 -14
- package/src/services/spawn-cwd-placement.ts +21 -5
- package/src/services/spawn-issue-activity.ts +8 -6
- package/src/services/spawn-launch.ts +17 -1
- package/src/services/spawn-loss-escalation.ts +1 -1
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +8 -9
- package/src/services/steward-reaper.ts +4 -4
- package/src/services/task-context-hydration.ts +25 -1
- package/src/services/task-delivery.ts +20 -34
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-entity.ts +40 -203
- package/src/services/task-issue-link.ts +13 -20
- package/src/services/task-issue-weave.ts +12 -11
- package/src/services/task-lifecycle.ts +27 -31
- package/src/services/task-repo-cwd.ts +37 -0
- package/src/services/task-review-hold.ts +4 -17
- package/src/services/task-semantic-events.ts +13 -11
- package/src/services/task-state-reconcile.ts +8 -17
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +12 -11
- package/src/services/team.ts +31 -98
- package/src/services/terminal-provider-exit.ts +6 -5
- package/src/services/timer-message-fire-chaos-worker.ts +7 -3
- package/src/services/timer-message-fire-outbox.ts +1 -1
- package/src/services/transient-agent-reaper.ts +25 -20
- package/src/services/turn-reconcile-audit.ts +9 -9
- package/src/services/user-onboarding.ts +8 -6
- package/src/services/user-profile.ts +6 -9
- package/src/services/work-finality.ts +16 -4
- package/src/services/workflow-auto-start.ts +26 -13
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.ts +1 -1
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-control-proof-worker.ts +1 -1
- package/src/services/workflow-coordinator.ts +8 -2
- package/src/services/workflow-decisions.ts +5 -5
- package/src/services/workflow-deferred-cleanup.ts +5 -3
- package/src/services/workflow-effect-driver.ts +42 -17
- package/src/services/workflow-effects.ts +58 -37
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +14 -11
- package/src/services/workflow-resume-pins.ts +3 -3
- package/src/services/workflow-routing-defaults.ts +18 -0
- package/src/services/workflow-run-view.ts +6 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +61 -33
- package/src/services/workflow-supervisor-state.ts +26 -1
- package/src/services/workflow-supervisor.ts +11 -6
- package/src/services/workspace-recovery.ts +4 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +28 -10
- package/src/spawn-targets.ts +9 -9
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +62 -57
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +9 -8
- package/src/task-dispatch-live.ts +6 -3
- package/src/task-dispatcher.ts +3 -3
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/token-db.ts +2 -2
- package/src/token-usage-async.ts +2 -4
- package/src/user-awaiting-reply.ts +5 -5
- package/src/workspace-actions.ts +24 -29
- package/src/workspace-auto-merge.ts +14 -12
- package/src/workspace-changed-paths-client.ts +16 -5
- package/src/workspace-cleanup-stale.ts +30 -7
- package/src/workspace-command-settle.ts +26 -17
- package/src/workspace-config.ts +1 -1
- package/src/workspace-conflict-resolver.ts +9 -7
- package/src/workspace-dead-owner-recovery.ts +5 -4
- package/src/workspace-escalation.ts +12 -11
- package/src/workspace-human-escalation.ts +3 -3
- package/src/workspace-land-gate-watchdog.ts +3 -3
- package/src/workspace-land-refusal.ts +20 -0
- package/src/workspace-land-stopped.ts +1 -0
- package/src/workspace-merge.ts +10 -26
- package/src/workspace-nothing-to-land-notice.ts +2 -2
- package/src/workspace-orphans.ts +18 -37
- package/src/workspace-pr-completion.ts +10 -8
- package/src/workspace-rekey.ts +3 -3
- package/src/workspace-steward-failure.ts +2 -2
- package/src/workspace-steward-wake.ts +4 -4
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -39
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -42
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BU3uWo2t.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/shipping-Bu8p1gEw.js +0 -2
- package/public/assets/store-BvtFdlGX.js +0 -9
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/db/on-loop-write-transaction.ts +0 -34
- package/src/routing-model-aliases.ts +0 -21
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { getGateway } from "../db/gateway";
|
|
2
|
+
import type { observeEffortBody } from "../db/agent-effort-observe";
|
|
3
|
+
import { sendMessageAsync } from "../db/message-send";
|
|
1
4
|
import type { AgentEffortState } from "@humwick/sdk";
|
|
2
5
|
import { getCommand } from "../commands-db";
|
|
3
6
|
import { emitCommandEvent } from "../command-events";
|
|
4
|
-
import { findMessageByIdempotencyKey,
|
|
7
|
+
import { findMessageByIdempotencyKey, validateAgentSession, writeTransaction } from "../db";
|
|
5
8
|
import { EffortReportRejected, recordEffortObservedInternal, type EffortObservation } from "../db/agent-effort-state";
|
|
6
9
|
import { emitRelayEvent } from "../events";
|
|
7
10
|
import { emitNewMessage } from "../sse";
|
|
@@ -9,47 +12,19 @@ import type { Command, Message } from "../types";
|
|
|
9
12
|
|
|
10
13
|
export { EffortReportRejected };
|
|
11
14
|
|
|
12
|
-
/** #2984 — the prompt that resumes an agent once its own effort change applied. */
|
|
13
|
-
export function selfEffortContinuation(effort: string): string {
|
|
14
|
-
return `Effort is now ${effort}. Continue your work.`;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
15
|
/** Dashboard + runner notice: the agent's desired/observed effort changed. */
|
|
18
16
|
export function emitEffortState(state: AgentEffortState): void {
|
|
19
17
|
emitRelayEvent({ type: "agent.effort", source: "server", subject: state.agentId, data: state as unknown as Record<string, unknown> });
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
/** One continuation per owed resume (keyed by the self request's version): a repeated report finds the first. */
|
|
23
|
-
function enqueueSelfContinuation(agentId: string, version: number, effort: string): Message | undefined {
|
|
24
|
-
const idempotencyKey = `effort-continuation:${agentId}:${version}`;
|
|
25
|
-
if (findMessageByIdempotencyKey("system", idempotencyKey)) return undefined;
|
|
26
|
-
return sendMessage({
|
|
27
|
-
from: "system",
|
|
28
|
-
to: agentId,
|
|
29
|
-
kind: "system",
|
|
30
|
-
subject: "Effort changed",
|
|
31
|
-
body: selfEffortContinuation(effort),
|
|
32
|
-
replyExpected: false,
|
|
33
|
-
idempotencyKey,
|
|
34
|
-
payload: { kind: "agent.effort_continuation", agentId, effortVersion: version, effort },
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
20
|
export interface EffortReport { instanceId: string; version: number; effort: string; previousEffort: string | null }
|
|
39
21
|
|
|
40
|
-
export
|
|
22
|
+
export { EffortReportFenced, selfEffortContinuation } from "../db/agent-effort-observe";
|
|
41
23
|
|
|
42
24
|
/** A runner applied (or verified) a desired version. Fenced to the agent's current incarnation; the
|
|
43
25
|
* observation and the resume it settles are one transaction. */
|
|
44
|
-
export function reportEffortObserved(agentId: string, report: EffortReport, now = Date.now()): EffortObservation {
|
|
45
|
-
|
|
46
|
-
const observed = writeTransaction(() => {
|
|
47
|
-
const session = validateAgentSession(agentId, { instanceId: report.instanceId });
|
|
48
|
-
if (!session.ok) throw new EffortReportFenced(session.error ?? "stale agent instance");
|
|
49
|
-
const result = recordEffortObservedInternal({ agentId, ...report, now });
|
|
50
|
-
if (result.outcome !== "stale" && result.resumeVersion !== undefined) continuation = enqueueSelfContinuation(agentId, result.resumeVersion, report.effort);
|
|
51
|
-
return result;
|
|
52
|
-
});
|
|
26
|
+
export async function reportEffortObserved(agentId: string, report: EffortReport, now = Date.now()): Promise<EffortObservation> {
|
|
27
|
+
const { observed, continuation } = await getGateway().write("agents.observeEffort", { agentId, ...report, now }) as unknown as ReturnType<typeof observeEffortBody>;
|
|
53
28
|
if (observed.outcome === "applied") {
|
|
54
29
|
const command: Command | null = observed.commandId ? getCommand(observed.commandId) : null;
|
|
55
30
|
if (command) emitCommandEvent(command, "command.succeeded");
|
|
@@ -386,7 +386,7 @@ async function deliverSelfCheck(agent: AgentCard, decision: AgentHangDecision, c
|
|
|
386
386
|
},
|
|
387
387
|
});
|
|
388
388
|
|
|
389
|
-
const messages = routeNotification({
|
|
389
|
+
const messages = await routeNotification({
|
|
390
390
|
type: "agent.self_check",
|
|
391
391
|
scope: { agentId: agent.id, parent: agent.spawnedBy, teamId: agent.teamId },
|
|
392
392
|
// Explicit, though the registered `subject-agent` rule resolves the same single recipient: the
|
|
@@ -457,7 +457,7 @@ async function escalate(
|
|
|
457
457
|
|
|
458
458
|
// Reuse the `agent.stuck_busy` notice shape (type, spawn-parent audience, `payload.kind`) so every
|
|
459
459
|
// existing coordinator-side consumer renders it with no new case to handle.
|
|
460
|
-
const messages = routeNotification({
|
|
460
|
+
const messages = await routeNotification({
|
|
461
461
|
type: "agent.stuck_busy",
|
|
462
462
|
scope: { agentId: agent.id, parent: agent.spawnedBy, teamId: agent.teamId },
|
|
463
463
|
message: {
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// The agent liveness exchange (#3606/#3608/#3618): one service behind POST /api/agents/:id/heartbeat
|
|
2
|
+
// and the bus `agent.heartbeat` command frame, so both transports apply status, readiness, the
|
|
3
|
+
// unread inbox and the quota piggyback identically. Transports parse and authorize at their edge.
|
|
4
|
+
import { isRecord, type HeartbeatResult, type ProviderQuotaUpdateInput } from "@humwick/sdk";
|
|
5
|
+
import { ValidationError, getAgent, markReadyAsync, recordHeartbeatAsync, setStatusAsync, validateAgentSession } from "../db";
|
|
6
|
+
import { isAgentUnavailable } from "../db/agent-predicates";
|
|
7
|
+
import type { ViewerScope } from "../db/viewer-scope";
|
|
8
|
+
import { emitAgentStatus } from "../agent-status-events";
|
|
9
|
+
import { VALID_AGENT_STATUSES, agentSessionStatus, auditEvent } from "../routes/_shared";
|
|
10
|
+
import { pollAgentMessages } from "../routes/messages";
|
|
11
|
+
import { cleanProviderQuotaUpdate } from "../routes/provider-quotas";
|
|
12
|
+
import { publishHeartbeatQuota } from "../routes/agent-heartbeat-quota";
|
|
13
|
+
import { announceSpawnedAgentReady } from "./register-agent";
|
|
14
|
+
import { flushQueuedDirectMessages } from "./managed-running";
|
|
15
|
+
import { acquireTeamOnReady } from "./team";
|
|
16
|
+
import { isComponentAuthorizedFor } from "../security";
|
|
17
|
+
import type { AgentCard, AgentSessionGuard, ComponentToken } from "../types";
|
|
18
|
+
|
|
19
|
+
type AgentStatusValue = (typeof VALID_AGENT_STATUSES)[number];
|
|
20
|
+
|
|
21
|
+
export interface AgentHeartbeatReport {
|
|
22
|
+
status?: AgentStatusValue;
|
|
23
|
+
ready?: boolean;
|
|
24
|
+
unread?: boolean;
|
|
25
|
+
providerQuota?: ProviderQuotaUpdateInput;
|
|
26
|
+
quotaLeaseToken?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type AgentHeartbeatOutcome = { ok: true; result: HeartbeatResult } | { ok: false; error: string; status: number };
|
|
30
|
+
|
|
31
|
+
type AgentActivityState = {
|
|
32
|
+
key: "available" | "busy" | "not-ready" | "offline";
|
|
33
|
+
title: string;
|
|
34
|
+
icon: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function agentActivityState(agent?: Pick<AgentCard, "ready" | "status"> | null): AgentActivityState | null {
|
|
38
|
+
if (!agent) return null;
|
|
39
|
+
if (agent.status === "offline") return { key: "offline", title: "Agent offline", icon: "ti-plug-off" };
|
|
40
|
+
if (!agent.ready) return { key: "not-ready", title: "Agent not ready", icon: "ti-loader" };
|
|
41
|
+
if (agent.status === "busy") return { key: "busy", title: "Agent busy", icon: "ti-activity" };
|
|
42
|
+
return { key: "available", title: "Agent available", icon: "ti-circle-check" };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function auditAgentStateTransition(agentId: string, before: AgentCard | null | undefined, after: AgentCard | null | undefined): Promise<void> {
|
|
46
|
+
const previous = agentActivityState(before);
|
|
47
|
+
const next = agentActivityState(after);
|
|
48
|
+
if (!next || previous?.key === next.key) return;
|
|
49
|
+
await auditEvent({
|
|
50
|
+
clientId: "server-agent-" + agentId + "-state-" + next.key + "-" + Date.now(),
|
|
51
|
+
kind: "state",
|
|
52
|
+
title: next.title,
|
|
53
|
+
meta: agentId,
|
|
54
|
+
icon: next.icon,
|
|
55
|
+
view: "agents",
|
|
56
|
+
agentId,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function cleanAgentStatus(value: unknown): AgentStatusValue {
|
|
61
|
+
if (!VALID_AGENT_STATUSES.includes(value as AgentStatusValue)) throw new ValidationError(`status must be one of: ${VALID_AGENT_STATUSES.join(", ")}`);
|
|
62
|
+
return value as AgentStatusValue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Validates a wire heartbeat body; throws ValidationError. `sourceAgentId` is always the reporting agent. */
|
|
66
|
+
export function cleanHeartbeatReport(agentId: string, body: unknown): AgentHeartbeatReport {
|
|
67
|
+
const raw = isRecord(body) ? body : {};
|
|
68
|
+
if (raw.ready !== undefined && typeof raw.ready !== "boolean") throw new ValidationError("ready must be a boolean");
|
|
69
|
+
if (raw.unread !== undefined && typeof raw.unread !== "boolean") throw new ValidationError("unread must be a boolean");
|
|
70
|
+
const quota = raw.providerQuota === undefined ? undefined : cleanProviderQuotaUpdate(raw.providerQuota);
|
|
71
|
+
if (typeof quota === "string") throw new ValidationError(quota);
|
|
72
|
+
if (quota) quota.sourceAgentId = agentId;
|
|
73
|
+
return {
|
|
74
|
+
...(raw.status === undefined ? {} : { status: cleanAgentStatus(raw.status) }),
|
|
75
|
+
...(raw.ready === undefined ? {} : { ready: raw.ready }),
|
|
76
|
+
...(raw.unread ? { unread: true } : {}),
|
|
77
|
+
...(quota ? { providerQuota: quota } : {}),
|
|
78
|
+
...(typeof raw.quotaLeaseToken === "string" ? { quotaLeaseToken: raw.quotaLeaseToken } : {}),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// #3606 — a reported status/readiness equal to the live card is a liveness tick, not a transition: no
|
|
83
|
+
// row write, no agent.status event. Presence still advances through the coalescing heartbeat buffer,
|
|
84
|
+
// except for a terminal row, which a beat would resurrect.
|
|
85
|
+
export async function noteUnchangedLifecycle(agentId: string, current: AgentCard, guard: AgentSessionGuard | undefined): Promise<void> {
|
|
86
|
+
if (current.status !== "offline" && current.status !== "stale") await recordHeartbeatAsync(agentId, { guard });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export async function applyAgentStatus(agentId: string, status: AgentStatusValue, guard: AgentSessionGuard | undefined, before: AgentCard | null): Promise<boolean> {
|
|
90
|
+
// #1895 (S3.2 L10, review finding 3) — routed through the async gateway facade.
|
|
91
|
+
if (!(await setStatusAsync(agentId, status, guard))) return false;
|
|
92
|
+
await auditAgentStateTransition(agentId, before, getAgent(agentId));
|
|
93
|
+
await emitAgentStatus(agentId);
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export async function applyAgentReady(agentId: string, ready: boolean, guard: AgentSessionGuard | undefined, before: AgentCard | null): Promise<boolean> {
|
|
98
|
+
// #1895 (S3.2 L10, review finding 3) — routed through the async gateway facade.
|
|
99
|
+
if (!(await markReadyAsync(agentId, ready, guard))) return false;
|
|
100
|
+
await auditAgentStateTransition(agentId, before, getAgent(agentId));
|
|
101
|
+
// #308/#2432 — a spawned child's false→true ready wakes its parent (announceSpawnedAgentReady dedups).
|
|
102
|
+
// #1927 — the awaited audit lets a same-instance PATCH flip ready back first, so re-read the live
|
|
103
|
+
// card and session guard before firing, never the pre-audit snapshot.
|
|
104
|
+
if (ready && !before?.ready) {
|
|
105
|
+
const live = getAgent(agentId);
|
|
106
|
+
const stillCurrentInstance = validateAgentSession(agentId, guard).ok;
|
|
107
|
+
if (live?.ready === true && stillCurrentInstance) {
|
|
108
|
+
await announceSpawnedAgentReady(agentId, "agent-ready");
|
|
109
|
+
(await acquireTeamOnReady(agentId)); // #3107 — before the flush, so seat mail reaches a new holder
|
|
110
|
+
// #416 — also flush queued direct messages: a not-ready agent that becomes ready
|
|
111
|
+
// may have queued messages waiting (e.g. starting up, clearing context).
|
|
112
|
+
(await flushQueuedDirectMessages(agentId));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
await emitAgentStatus(agentId);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** One liveness tick. Only a value that differs from the live card takes the transition path; the rest is a coalesced beat. */
|
|
120
|
+
export async function applyAgentHeartbeat(agentId: string, report: AgentHeartbeatReport, guard: AgentSessionGuard | undefined, viewer: ViewerScope | null): Promise<AgentHeartbeatOutcome> {
|
|
121
|
+
const session = validateAgentSession(agentId, guard);
|
|
122
|
+
if (!session.ok) return { ok: false, error: session.error!, status: agentSessionStatus(session.error) };
|
|
123
|
+
// #416 — capture unavailability before heartbeat to detect the transition.
|
|
124
|
+
const beforeHeartbeat = getAgent(agentId);
|
|
125
|
+
if (beforeHeartbeat?.kind === "channel" && !beforeHeartbeat.ready) return { ok: false, error: "channel agent not ready; re-register required", status: 409 };
|
|
126
|
+
const notFound = { ok: false, error: "agent not found", status: 404 } as const;
|
|
127
|
+
const wasUnavailable = beforeHeartbeat ? isAgentUnavailable(beforeHeartbeat) : false;
|
|
128
|
+
let current = beforeHeartbeat;
|
|
129
|
+
const { status, ready } = report;
|
|
130
|
+
if (status !== undefined && status !== current?.status) {
|
|
131
|
+
if (!(await applyAgentStatus(agentId, status, guard, current))) return notFound;
|
|
132
|
+
current = getAgent(agentId);
|
|
133
|
+
}
|
|
134
|
+
if (ready !== undefined && ready !== current?.ready) {
|
|
135
|
+
if (!(await applyAgentReady(agentId, ready, guard, current))) return notFound;
|
|
136
|
+
}
|
|
137
|
+
// A reported terminal status must not be undone by the beat's offline/stale resurrection.
|
|
138
|
+
if (status !== "offline" && status !== "stale") {
|
|
139
|
+
// #1468 — route the API heartbeat through the same coalescing buffer as the bus path.
|
|
140
|
+
if (!(await recordHeartbeatAsync(agentId, { guard }))) return notFound;
|
|
141
|
+
}
|
|
142
|
+
if (wasUnavailable) {
|
|
143
|
+
const after = getAgent(agentId);
|
|
144
|
+
if (after && !isAgentUnavailable(after)) (await flushQueuedDirectMessages(agentId));
|
|
145
|
+
}
|
|
146
|
+
const result: HeartbeatResult = { ok: true };
|
|
147
|
+
if (report.unread) result.messages = await pollAgentMessages(viewer, { for: agentId, unread: true, limit: 100, turnDelivery: true });
|
|
148
|
+
if (report.providerQuota) {
|
|
149
|
+
try { result.providerQuota = await publishHeartbeatQuota(report.providerQuota, report.quotaLeaseToken); }
|
|
150
|
+
catch (error) { console.warn(`heartbeat quota publish failed for ${agentId}:`, error); }
|
|
151
|
+
}
|
|
152
|
+
return { ok: true, result };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** #3618 — the bus `agent.heartbeat` frame. A socket reports only for the agent it registered as,
|
|
156
|
+
* under that registration's session guard and the scopes its upgrade credential carries. */
|
|
157
|
+
export async function heartbeatFromBus(conn: { agentId?: string; instanceId: string; epoch: number; componentAuth?: ComponentToken }, target: string, params: Record<string, unknown>): Promise<{ status: "succeeded" | "failed" | "rejected"; result?: Record<string, unknown>; error?: string }> {
|
|
158
|
+
if (!conn.agentId || target !== conn.agentId) return { status: "rejected", error: "agent.heartbeat reports only for the registered agent" };
|
|
159
|
+
let report: AgentHeartbeatReport;
|
|
160
|
+
try { report = cleanHeartbeatReport(conn.agentId, params); }
|
|
161
|
+
catch (error) { if (error instanceof ValidationError) return { status: "failed", error: error.message }; throw error; }
|
|
162
|
+
const denied = (scope: string) => conn.componentAuth && !isComponentAuthorizedFor(conn.componentAuth, { scope, resource: { agentId: conn.agentId, target: conn.agentId } });
|
|
163
|
+
if ((report.unread && denied("message:read")) || (report.providerQuota && denied("quota:write"))) return { status: "rejected", error: "component token lacks heartbeat scope" };
|
|
164
|
+
const outcome = await applyAgentHeartbeat(conn.agentId, report, { instanceId: conn.instanceId, epoch: conn.epoch }, null);
|
|
165
|
+
return outcome.ok ? { status: "succeeded", result: outcome.result as unknown as Record<string, unknown> } : { status: "failed", error: outcome.error };
|
|
166
|
+
}
|
|
@@ -10,7 +10,7 @@ export async function setAgentReportVerbosity(input: {
|
|
|
10
10
|
requestedVia: "http" | "mcp";
|
|
11
11
|
reason?: string;
|
|
12
12
|
}, ctx: AuthContext): Promise<{ action: "reportVerbosity"; reportVerbosity: ReportVerbosity }> {
|
|
13
|
-
authorizeShutdown(ctx, { agentId: input.agentId, requestedVia: input.requestedVia });
|
|
13
|
+
(await authorizeShutdown(ctx, { agentId: input.agentId, requestedVia: input.requestedVia }));
|
|
14
14
|
const agent = getAgent(input.agentId);
|
|
15
15
|
if (!agent) throw new ShutdownTargetError("agent not found");
|
|
16
16
|
if (!isReportVerbosity(input.reportVerbosity)) throw new ValidationError("reportVerbosity must be off, quiet, normal or verbose");
|
|
@@ -34,7 +34,7 @@ export async function reconcileBrowserInventory(orchestratorId: string, inventor
|
|
|
34
34
|
const live = new Set(inventory.liveSessionIds);
|
|
35
35
|
const closed = new Set(inventory.closedSessionIds);
|
|
36
36
|
for (const row of listBrowserSessionRows({ orchestratorId, activeOnly: true, limit: 1000 })) {
|
|
37
|
-
if (getAgent(row.agentId)?.status === "offline") reapAgentBrowserSessions(row.agentId);
|
|
37
|
+
if (getAgent(row.agentId)?.status === "offline") (await reapAgentBrowserSessions(row.agentId));
|
|
38
38
|
const idleMs = inventory.idleMs?.[row.id];
|
|
39
39
|
if (idleMs !== undefined) noteBrowserActivity(row, idleMs, Date.now());
|
|
40
40
|
if (live.has(row.id) || (!registration && !closed.has(row.id))) continue;
|
|
@@ -44,9 +44,9 @@ export async function reconcileBrowserInventory(orchestratorId: string, inventor
|
|
|
44
44
|
if (command?.status === "pending") continue;
|
|
45
45
|
}
|
|
46
46
|
const now = Date.now();
|
|
47
|
-
transitionAndEmit(row.id, [row.status], {
|
|
47
|
+
(await transitionAndEmit(row.id, [row.status], {
|
|
48
48
|
status: row.status === "stopping" || closed.has(row.id) ? "stopped" : "failed", stoppedAt: now,
|
|
49
49
|
error: registration ? "browser absent from orchestrator registration" : "browser process ended on host",
|
|
50
|
-
}, now);
|
|
50
|
+
}, now));
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getGateway } from "../db/gateway";
|
|
1
2
|
// #3489 H4 — the one write path for browser session rows after insert: every change is pushed as
|
|
2
3
|
// `browser.session.<status>`, so the dashboard follows starts, stops, idle expiry and crashes without polling.
|
|
3
4
|
import type { BrowserSession, BrowserSessionStatus } from "@humwick/sdk";
|
|
@@ -26,8 +27,8 @@ export function emitBrowserSession(row: BrowserSessionRow): void {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/** Applies a guarded transition and announces it; undefined when the row already left `from`. */
|
|
29
|
-
export function transitionAndEmit(id: string, from: readonly BrowserSessionStatus[], patch: BrowserSessionPatch, now: number): BrowserSessionRow | undefined {
|
|
30
|
-
const row =
|
|
30
|
+
export async function transitionAndEmit(id: string, from: readonly BrowserSessionStatus[], patch: BrowserSessionPatch, now: number): Promise<BrowserSessionRow | undefined> {
|
|
31
|
+
const row = await getGateway().write("browser.transition", [id, from, patch, now]) as unknown as BrowserSessionRow | undefined;
|
|
31
32
|
if (!row) return undefined;
|
|
32
33
|
if (row.status === "running") lastActivity.set(row.id, lastActivity.get(row.id) ?? now);
|
|
33
34
|
else if (row.status === "stopped" || row.status === "failed") lastActivity.delete(row.id);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { getGateway } from "../db/gateway";
|
|
2
|
+
import type { startBrowserBody, stopBrowserBody } from "../db/browser-session-write";
|
|
1
3
|
// #3489 — Relay-managed browser sessions. The server owns identity, limits and lifecycle state; the agent's own
|
|
2
4
|
// orchestrator owns the Chromium process and executes `browser.start` / `browser.stop` from the command bus.
|
|
3
5
|
// Command results are folded into the row as they arrive (and again on read, which also settles a missed event).
|
|
@@ -6,14 +8,14 @@ import { isRecord, stringValue, type BrowserLimits, type BrowserSession } from "
|
|
|
6
8
|
import { getBrowserLimits } from "../browser-config";
|
|
7
9
|
import { canAccessBrowserSession, type BrowserCaller } from "../browser-authz";
|
|
8
10
|
import { emitCommandEvent } from "../command-events";
|
|
9
|
-
|
|
11
|
+
|
|
10
12
|
import { subscribeRelayEvents } from "../events";
|
|
11
13
|
import type { Command } from "../types";
|
|
12
14
|
import { getCommandAsync } from "../commands-write";
|
|
13
15
|
import { getAgentProfile } from "../config-store";
|
|
14
16
|
import { getAgent, getOrchestrator } from "../db";
|
|
15
17
|
import {
|
|
16
|
-
|
|
18
|
+
getBrowserSessionRow, listBrowserSessionRows, type BrowserSessionRow,
|
|
17
19
|
} from "../db/browser-sessions";
|
|
18
20
|
import { getLaunchFact } from "../db/launch-facts";
|
|
19
21
|
import { generationLaunchParams } from "../db/generation-launch";
|
|
@@ -67,17 +69,13 @@ export async function startBrowserSession(caller: BrowserCaller, input: { agentI
|
|
|
67
69
|
const limits = getBrowserLimits();
|
|
68
70
|
// Settle finished stops first, so a reaped session stops counting against the limits.
|
|
69
71
|
for (const row of [...listBrowserSessionRows({ agentId, activeOnly: true, limit: 100 }), ...listBrowserSessionRows({ orchestratorId: host.id, activeOnly: true, limit: 100 })]) await reconcile(row);
|
|
70
|
-
// Count and insert run in one synchronous stretch, so two concurrent starts cannot both pass the cap.
|
|
71
|
-
if (countActiveBrowserSessions({ agentId }) >= limits.perAgent) {
|
|
72
|
-
throw new BrowserSessionError(`agent ${agentId} already has ${limits.perAgent} browser session(s) (limit from settings browser/default)`, 409);
|
|
73
|
-
}
|
|
74
|
-
if (countActiveBrowserSessions({ orchestratorId: host.id }) >= limits.perHost) {
|
|
75
|
-
throw new BrowserSessionError(`host ${host.id} already runs ${limits.perHost} browser session(s) (limit from settings browser/default)`, 409);
|
|
76
|
-
}
|
|
77
72
|
const id = randomUUID();
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
const result = await getGateway().write("browser.start", { id, commandId: randomUUID(), agentId, instanceId: agent.instanceId, epoch: agent.epoch, orchestratorId: host.id, limits }, { idempotencyKey: id }) as unknown as ReturnType<typeof startBrowserBody>;
|
|
74
|
+
if (result.conflict === "agentLimit") throw new BrowserSessionError(`agent ${agentId} already has ${limits.perAgent} browser session(s) (limit from settings browser/default)`, 409);
|
|
75
|
+
if (result.conflict === "hostLimit") throw new BrowserSessionError(`host ${host.id} already runs ${limits.perHost} browser session(s) (limit from settings browser/default)`, 409);
|
|
76
|
+
if (result.conflict) throw new BrowserSessionError("browser session target changed during admission", 409);
|
|
77
|
+
const { command, row } = result;
|
|
78
|
+
emitBrowserSession(row);
|
|
81
79
|
emitCommandEvent(command, "command.requested");
|
|
82
80
|
return { session: publicView(await settle(id, signal)), limits };
|
|
83
81
|
}
|
|
@@ -92,16 +90,16 @@ async function reconcile(row: BrowserSessionRow): Promise<BrowserSessionRow> {
|
|
|
92
90
|
const patch = command.status === "succeeded"
|
|
93
91
|
? { status: "running" as const, cdpUrl: stringValue(result.cdpUrl), pid: typeof result.pid === "number" ? result.pid : undefined, profileDir: stringValue(result.profileDir) }
|
|
94
92
|
: { status: "failed" as const, error: command.error ?? `browser.start ${command.status}`, stoppedAt: now };
|
|
95
|
-
return transitionAndEmit(row.id, ["starting"], patch, now) ?? getBrowserSessionRow(row.id)!;
|
|
93
|
+
return (await transitionAndEmit(row.id, ["starting"], patch, now)) ?? getBrowserSessionRow(row.id)!;
|
|
96
94
|
}
|
|
97
95
|
if (row.status === "stopping" && row.stopCommandId) {
|
|
98
96
|
const command = await getCommandAsync(row.stopCommandId);
|
|
99
97
|
if (!command || !isTerminalCommandStatus(command.status)) {
|
|
100
98
|
if (now - row.updatedAt < SETTLE_TIMEOUT_MS) return row;
|
|
101
|
-
return transitionAndEmit(row.id, ["stopping"], { status: "failed", stoppedAt: now, error: "browser stop did not settle" }, now) ?? row;
|
|
99
|
+
return (await transitionAndEmit(row.id, ["stopping"], { status: "failed", stoppedAt: now, error: "browser stop did not settle" }, now)) ?? row;
|
|
102
100
|
}
|
|
103
101
|
const error = command.status === "succeeded" ? undefined : command.error ?? `browser.stop ${command.status}`;
|
|
104
|
-
return transitionAndEmit(row.id, ["stopping"], { status: "stopped", stoppedAt: now, ...(error ? { error } : {}) }, now) ?? getBrowserSessionRow(row.id)!;
|
|
102
|
+
return (await transitionAndEmit(row.id, ["stopping"], { status: "stopped", stoppedAt: now, ...(error ? { error } : {}) }, now)) ?? getBrowserSessionRow(row.id)!;
|
|
105
103
|
}
|
|
106
104
|
return row;
|
|
107
105
|
}
|
|
@@ -133,27 +131,23 @@ export async function listBrowserSessions(caller: BrowserCaller, filter: { agent
|
|
|
133
131
|
}
|
|
134
132
|
|
|
135
133
|
/** Issue `browser.stop`; idempotent for a session that is already stopping or over. */
|
|
136
|
-
function requestStop(row: BrowserSessionRow, reason: string): BrowserSessionRow {
|
|
134
|
+
async function requestStop(row: BrowserSessionRow, reason: string): Promise<BrowserSessionRow> {
|
|
137
135
|
if (row.status !== "starting" && row.status !== "running") return row;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
params: { sessionId: row.id, agentId: row.agentId, orchestratorId: host.id, reason } } });
|
|
143
|
-
const stopping = transitionAndEmit(row.id, ["starting", "running"], { status: "stopping", stopCommandId: command.id }, now);
|
|
144
|
-
emitCommandEvent(command, "command.requested");
|
|
145
|
-
return stopping ?? getBrowserSessionRow(row.id)!;
|
|
136
|
+
const result = await getGateway().write("browser.stop", { id: row.id, reason, commandId: randomUUID() }, { idempotencyKey: row.id }) as unknown as ReturnType<typeof stopBrowserBody>;
|
|
137
|
+
if (result.row) emitBrowserSession(result.row);
|
|
138
|
+
if (result.command) emitCommandEvent(result.command, "command.requested");
|
|
139
|
+
return result.row ?? row;
|
|
146
140
|
}
|
|
147
141
|
|
|
148
142
|
export async function stopBrowserSession(caller: BrowserCaller, id: string, signal?: AbortSignal): Promise<BrowserSession> {
|
|
149
|
-
const row = requestStop(await reconcile(accessible(caller, id)), "requested");
|
|
143
|
+
const row = await requestStop(await reconcile(accessible(caller, id)), "requested");
|
|
150
144
|
return publicView(row.status === "stopping" ? await settle(id, signal) : row);
|
|
151
145
|
}
|
|
152
146
|
|
|
153
147
|
/** Agent exit: every live session of the agent is stopped with it. Synchronous; the commands settle later. */
|
|
154
|
-
export function reapAgentBrowserSessions(agentId: string): number {
|
|
148
|
+
export async function reapAgentBrowserSessions(agentId: string): Promise<number> {
|
|
155
149
|
const live = listBrowserSessionRows({ agentId, activeOnly: true, limit: 100 }).filter((row) => row.status !== "stopping");
|
|
156
|
-
for (const row of live) requestStop(row, "agent-exit");
|
|
150
|
+
for (const row of live) await requestStop(row, "agent-exit");
|
|
157
151
|
return live.length;
|
|
158
152
|
}
|
|
159
153
|
|
|
@@ -51,23 +51,23 @@ export async function updateCommandFromBus(input: {
|
|
|
51
51
|
await settleScheduledCommandTimer(updated);
|
|
52
52
|
}
|
|
53
53
|
emitCommandEvent(updated, `command.${updated.status}`);
|
|
54
|
-
settleSelfResumeContinuationIngestion(updated);
|
|
54
|
+
(await settleSelfResumeContinuationIngestion(updated));
|
|
55
55
|
noteCompactionCommandCompleted(updated);
|
|
56
56
|
// #2095 — durable "clear committed vs no-op" signal, fired on terminal compact/clear commands.
|
|
57
57
|
noteCompactionResult(updated);
|
|
58
|
-
enqueueContinuationInjectionAfterSelfResume(updated);
|
|
59
|
-
enqueueLifecycleIdentityInjectionAfterContextCommand(updated);
|
|
60
|
-
notifySelfResumeNoOp(updated);
|
|
61
|
-
settleContextResetCarry(updated);
|
|
62
|
-
settleSelfRestartManagedState(updated);
|
|
63
|
-
settleInterruptRedirectMessage(updated);
|
|
58
|
+
(await enqueueContinuationInjectionAfterSelfResume(updated));
|
|
59
|
+
(await enqueueLifecycleIdentityInjectionAfterContextCommand(updated));
|
|
60
|
+
await notifySelfResumeNoOp(updated);
|
|
61
|
+
(await settleContextResetCarry(updated));
|
|
62
|
+
(await settleSelfRestartManagedState(updated));
|
|
63
|
+
(await settleInterruptRedirectMessage(updated));
|
|
64
64
|
// #1565 P4b — memory rides BESIDE the continuation as its own payload (§7), delta-gated on
|
|
65
65
|
// compact. Ordered LAST and contained (#1565 F8) — see the same call in routes/commands.ts.
|
|
66
|
-
settleMemoryInjectionAfterContextCommand(updated);
|
|
66
|
+
(await settleMemoryInjectionAfterContextCommand(updated));
|
|
67
67
|
// #1951 — the startup context (validation commands, report-up, profile charter, caller context)
|
|
68
68
|
// rides beside them too, recomposed from the DB and delta-gated on compact. Contained the same
|
|
69
69
|
// way: a compose throw here must not abort the settle chain.
|
|
70
|
-
settleStartupContextInjectionAfterContextCommand(updated);
|
|
70
|
+
(await settleStartupContextInjectionAfterContextCommand(updated));
|
|
71
71
|
}
|
|
72
72
|
return { status: "succeeded", result: updated ? { command: updated } : undefined };
|
|
73
73
|
}
|
|
@@ -6,6 +6,7 @@ export function checkoutRefreshHealth(row: CheckoutRefreshStatus, now = Date.now
|
|
|
6
6
|
if (!row.result?.enabled) return undefined;
|
|
7
7
|
if (["pending", "accepted", "running"].includes(row.status) && row.result.status === "waiting") return "waiting";
|
|
8
8
|
if (row.result.reason) return "blocked";
|
|
9
|
+
if (row.status === "succeeded" && ["current", "refreshed"].includes(row.result.status)) return "healthy";
|
|
9
10
|
return !row.result.successAt || now - row.result.successAt > 180_000 ? "stale" : "healthy";
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createCommand, updateCommand } from "../commands-db";
|
|
2
2
|
|
|
3
3
|
/** Record a host checkout's latest refresh receipt, as the executor reports a finished attempt. */
|
|
4
|
-
export function recordRefreshReceipt(projectId: string, orchestratorId: string, rootPath: string, outcome: "hook-failed" | "current" | "behind" | "refreshing"): void {
|
|
4
|
+
export function recordRefreshReceipt(projectId: string, orchestratorId: string, rootPath: string, outcome: "hook-failed" | "current" | "behind" | "refreshing" | "busy"): void {
|
|
5
5
|
const command = createCommand({ type: "project.checkout.refresh", source: "system", target: `orchestrator-${orchestratorId}`,
|
|
6
6
|
params: { projectId, rootPath, orchestratorId, remoteUrl: "https://example.invalid/repo.git", enabled: true } });
|
|
7
|
-
const dependency = { fingerprint: "inputs", attemptId: "attempt", status: outcome === "hook-failed" || outcome === "refreshing" ? "pending" : "current" };
|
|
7
|
+
const dependency = { fingerprint: "inputs", attemptId: "attempt", status: outcome === "hook-failed" || outcome === "refreshing" || outcome === "busy" ? "pending" : "current" };
|
|
8
8
|
updateCommand(command.id, { status: outcome === "refreshing" ? "running" : "succeeded", result: { rootPath, enabled: true, attemptedAt: Date.now(), backups: [], headSha: "head", dependency,
|
|
9
9
|
...(outcome === "hook-failed" ? { status: "error", reason: "dependency hook failed: npm ci exited 1" }
|
|
10
|
+
: outcome === "busy" ? { status: "skipped", reason: "host gate admission busy; retry next refresh cycle" }
|
|
10
11
|
: outcome === "behind" ? { status: "skipped", behind: 3, reason: "fetch failed" }
|
|
11
12
|
: outcome === "refreshing" ? { status: "refreshing" } : { status: "current", successAt: Date.now() }) } });
|
|
12
13
|
}
|
|
@@ -2,11 +2,14 @@ import { stringValue } from "@humwick/sdk";
|
|
|
2
2
|
import type { Orchestrator } from "@humwick/sdk";
|
|
3
3
|
import { getAgent, listOrchestrators, ValidationError } from "../db";
|
|
4
4
|
import type { AuthContext } from "./auth-context";
|
|
5
|
+
import { listManagedOrchestratorsForAgent } from "../orchestrator-lookup";
|
|
5
6
|
import { isPathWithinBase, sameHostIdentity } from "../utils";
|
|
6
7
|
|
|
7
8
|
/** The orchestrator the caller agent is registered on, online or not: its stamped
|
|
8
|
-
* `meta.orchestratorId`, else
|
|
9
|
-
* differs in case/separators).
|
|
9
|
+
* `meta.orchestratorId`, else the one host whose managed-agent roster runs it, else its `machine`
|
|
10
|
+
* matched by host identity (the runner's raw os.hostname() differs in case/separators). The roster
|
|
11
|
+
* covers unpinned system launches (stewards, managed policies) on a host whose OS hostname is not
|
|
12
|
+
* its orchestrator name, e.g. WSL "XPS15" on xps15-wsl (#3822). */
|
|
10
13
|
function callerHost(ctx: AuthContext, hosts: Orchestrator[]): Orchestrator | undefined {
|
|
11
14
|
const agent = ctx.callerAgentId ? getAgent(ctx.callerAgentId) : undefined;
|
|
12
15
|
if (!agent) return undefined;
|
|
@@ -15,6 +18,8 @@ function callerHost(ctx: AuthContext, hosts: Orchestrator[]): Orchestrator | und
|
|
|
15
18
|
const byId = hosts.find((item) => item.id === stamped);
|
|
16
19
|
if (byId) return byId;
|
|
17
20
|
}
|
|
21
|
+
const rostered = listManagedOrchestratorsForAgent({ agentId: agent.id });
|
|
22
|
+
if (rostered.length === 1) return rostered[0];
|
|
18
23
|
if (!agent.machine) return undefined;
|
|
19
24
|
return hosts.find((item) => sameHostIdentity(item.hostname, agent.machine) || sameHostIdentity(item.id, agent.machine));
|
|
20
25
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { framed } from "../hub-metrics";
|
|
1
2
|
import { errMessage } from "@humwick/sdk";
|
|
2
3
|
import { flushCoordinatorDigestsAsync } from "../db/coordinator-digest-async";
|
|
3
4
|
import { emitNewMessages } from "../sse";
|
|
@@ -18,11 +19,11 @@ export function startCoordinatorDigestLoop(): () => Promise<void> {
|
|
|
18
19
|
let stopped = false;
|
|
19
20
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
20
21
|
let pending: Promise<void>;
|
|
21
|
-
const tick = async () => {
|
|
22
|
+
const tick = framed("timer coordinator-digest", async () => {
|
|
22
23
|
try { await flushCoordinatorDigests(); }
|
|
23
24
|
catch (error) { console.error(`coordinator digest flush failed: ${errMessage(error)}`); }
|
|
24
25
|
finally { if (!stopped) timer = setTimeout(() => { pending = tick(); }, 1000).unref(); }
|
|
25
|
-
};
|
|
26
|
+
});
|
|
26
27
|
pending = tick();
|
|
27
28
|
const stop = () => { stopped = true; clearTimeout(timer); removeShutdownHook(); return pending; };
|
|
28
29
|
const removeShutdownHook = onShutdown("coordinator-digest", stop);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createCommandAsync, createKernelCommandIfAbsentAsync } from "../commands-write";
|
|
1
2
|
import { writeChildEnv } from "@humwick/sdk/env";
|
|
2
3
|
import { rejectCallerSealedEnv } from "../spawn-env";
|
|
3
|
-
import { commandSecretMaskValues } from "../command-secrets";
|
|
4
|
+
import { commandSecretMaskValues, omitCommandFenceSecrets, redactCommandSecrets, revealCommandSecrets } from "../command-secrets";
|
|
4
5
|
import { spawnDelegationState } from "../db/spawn-delegation-state";
|
|
5
6
|
import { authorizeShutdown } from "./shutdown-agent";
|
|
6
7
|
import { stewardGenerationCanceled } from "../db/workspace-steward-fence";
|
|
@@ -17,11 +18,9 @@ import { stewardGenerationCanceled } from "../db/workspace-steward-fence";
|
|
|
17
18
|
// owned by the spawn (#349) / shutdown (#347) slices — they are NOT generic dispatch and stay
|
|
18
19
|
// out of this service.
|
|
19
20
|
import { isRecord, stringValue, ValidationError } from "@humwick/sdk";
|
|
20
|
-
|
|
21
|
-
import { createCommandAsync, createKernelCommandIfAbsentAsync } from "../commands-write";
|
|
21
|
+
|
|
22
22
|
import { emitCommandEvent } from "../command-events";
|
|
23
23
|
import { componentConstraintsAllow, hasComponentScope, isComponentAuthorizedFor, isOpenApprovalConstraints } from "../security";
|
|
24
|
-
import { omitCommandFenceSecrets, redactCommandSecrets, revealCommandSecrets } from "../command-secrets";
|
|
25
24
|
import { listOrchestrators } from "../db";
|
|
26
25
|
import { ServiceAuthError } from "./errors";
|
|
27
26
|
import type { AuthContext } from "./auth-context";
|
|
@@ -211,10 +210,10 @@ function assertPathAxesWithinConstraint(input: CreateCommandInput, component: Co
|
|
|
211
210
|
* scope gate at the transport edge — HTTP middleware `isScopedRequestAuthorized`, bus
|
|
212
211
|
* `withRegistered`). HTTP `authorizeRoute` and bus `busCommandAuthorized` both reduce to this:
|
|
213
212
|
* "no component token ⇒ allow; else `isComponentAuthorizedFor(command:write, resource)`". */
|
|
214
|
-
function assertCommandAuthorized(ctx: AuthContext, input: CreateCommandInput, schedulerFire = false): void {
|
|
213
|
+
async function assertCommandAuthorized(ctx: AuthContext, input: CreateCommandInput, schedulerFire = false): Promise<void> {
|
|
215
214
|
if (ctx.callerAgentId && spawnDelegationState(ctx.callerAgentId).participating) {
|
|
216
215
|
if (input.type === "agent.spawn") throw new ValidationError("agent.spawn requires the spawn service to preserve delegated lineage");
|
|
217
|
-
if (input.type === "agent.shutdown") authorizeShutdown(ctx, { agentId: stringValue(input.params?.agentId), spawnRequestId: stringValue(input.params?.spawnRequestId), requestedVia: "bus" });
|
|
216
|
+
if (input.type === "agent.shutdown") (await authorizeShutdown(ctx, { agentId: stringValue(input.params?.agentId), spawnRequestId: stringValue(input.params?.spawnRequestId), requestedVia: "bus" }));
|
|
218
217
|
}
|
|
219
218
|
if (ctx.callerAgentId && stewardGenerationCanceled(ctx.callerAgentId, ctx.constraints?.spawnRequestIds?.[0])) {
|
|
220
219
|
throw new ServiceAuthError("steward job canceled by land withdrawal; host mutations are fenced");
|
|
@@ -304,9 +303,9 @@ export function serializeCommandForRead(command: Command, ctx: AuthContext): Com
|
|
|
304
303
|
}
|
|
305
304
|
|
|
306
305
|
/** Dispatch options. `allowReservedCorrelation` threads the R2 (#1409) kernel-correlation opt-in to
|
|
307
|
-
* `
|
|
306
|
+
* `createCommandAsync` — set ONLY by the kernel command bridge, whose `correlation_id` is a legitimately
|
|
308
307
|
* `kcmd:`-namespaced dedup key. Every other (external) `dispatchCommand` caller omits it, so the
|
|
309
|
-
* reservation stays enforced at the `
|
|
308
|
+
* reservation stays enforced at the `createCommandAsync` choke point. */
|
|
310
309
|
export interface DispatchCommandOptions {
|
|
311
310
|
readonly allowReservedCorrelation?: boolean;
|
|
312
311
|
/** #2392 — INTERNAL ONLY. Set exclusively by the two scheduler FIRE paths
|
|
@@ -340,10 +339,10 @@ function withServerCommandProvenance(input: CreateCommandInput, options: Dispatc
|
|
|
340
339
|
};
|
|
341
340
|
}
|
|
342
341
|
|
|
343
|
-
export function dispatchCommand(input: CreateCommandInput, ctx: AuthContext, options: DispatchCommandOptions = {}): Command {
|
|
342
|
+
export async function dispatchCommand(input: CreateCommandInput, ctx: AuthContext, options: DispatchCommandOptions = {}): Promise<Command> {
|
|
344
343
|
const sanitizedInput = withServerCommandProvenance(input, options);
|
|
345
|
-
assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true);
|
|
346
|
-
const command =
|
|
344
|
+
(await assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true));
|
|
345
|
+
const command = (await createCommandAsync(sanitizedInput, { allowReservedCorrelation: options.allowReservedCorrelation === true }));
|
|
347
346
|
// A freshly created command is always `pending`; emit the literal "command.requested"
|
|
348
347
|
// (the relay auto-fans-out the follow-up "command.dispatched"). HTTP used the status-derived
|
|
349
348
|
// `emitCommand`, bus used `emitCommandEvent(_, "command.requested")` — identical for pending.
|
|
@@ -359,7 +358,7 @@ export async function dispatchCommandAsync(
|
|
|
359
358
|
options: DispatchCommandOptions = {},
|
|
360
359
|
): Promise<Command> {
|
|
361
360
|
const sanitizedInput = withServerCommandProvenance(input, options);
|
|
362
|
-
assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true);
|
|
361
|
+
(await assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true));
|
|
363
362
|
const command = await createCommandAsync(sanitizedInput, {
|
|
364
363
|
allowReservedCorrelation: options.allowReservedCorrelation === true,
|
|
365
364
|
}, ctx.callerAgentId ?? ctx.actor.id, ctx.constraints?.projectId);
|
|
@@ -381,7 +380,7 @@ export async function dispatchKernelCommandAsync(
|
|
|
381
380
|
options: Pick<DispatchCommandOptions, "schedulerFire" | "schedulerRequestedVia"> = {},
|
|
382
381
|
): Promise<Command> {
|
|
383
382
|
const sanitizedInput = withServerCommandProvenance(input, options);
|
|
384
|
-
assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true);
|
|
383
|
+
(await assertCommandAuthorized(ctx, sanitizedInput, options.schedulerFire === true));
|
|
385
384
|
const { command, created } = await createKernelCommandIfAbsentAsync(sanitizedInput, ctx.callerAgentId ?? ctx.actor.id, ctx.constraints?.projectId);
|
|
386
385
|
if (created) emitCommandEvent(command, "command.requested");
|
|
387
386
|
return command;
|