@humwick/server 0.130.2 → 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/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-coordination.md +1 -0
- package/docs/guides/workflows.md +16 -0
- package/docs/openapi.json +73 -4
- package/package.json +8 -7
- package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-Wimm0Czv.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-CrSurn-r.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-DKbiIhBo.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-cxtRBn6O.js} +2 -2
- package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-B-v66C-4.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-BqCb-LKi.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DJevXcvg.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-D32zyw4Y.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-BpRajx_5.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-D_UjTdzX.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-N3VEh4ao.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-9jopungq.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-CSXrTB3C.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-p1NnmqK0.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-CZdqlDNL.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-30aXTKva.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-DoN6bAb5.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-BrKWFGJz.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-D6XEu8Ng.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-C7jQWbw2.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/{index-CRHep3M9.js → index-CqqgOI5R.js} +5 -5
- package/public/assets/{insights-CzrtkpOE.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-aVsUmigt.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-NfjqFZAk.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-DNsCl6UX.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-DopU1L1X.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-C1DCTzzV.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-DE_m6rrE.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-DETKFn_E.js} +2 -2
- package/public/assets/{projects-Br2Bd2h1.js → projects-M_m6AHws.js} +2 -2
- package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-Cw38_6gW.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/{secrets-DxI-vzSq.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-CKZTVGIx.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-DyUBKyWI.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-Bh7Chr4-.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-bowI7qVY.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-samMQhQf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/{use-project-list-59LheVP7.js → use-project-list-CpWl6eHQ.js} +2 -2
- package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-CIVg7XB1.js} +2 -2
- package/public/assets/{work-queue-CSvpuNLz.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-DdmxRSyg.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +28 -28
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- 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/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- 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 +2 -1
- package/runner/src/runner-core.ts +14 -15
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -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 +3 -3
- package/src/branch-landed.ts +25 -23
- package/src/bus.ts +21 -19
- package/src/cd-deploy-notify.ts +2 -2
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +3 -3
- package/src/ci/transition-notify.ts +5 -5
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/workflow.ts +12 -3
- package/src/commands-db.ts +4 -4
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +2 -2
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- 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/agents-async.ts +8 -5
- package/src/db/agents.ts +15 -12
- 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/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/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuations.ts +4 -4
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -3
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-refs-async.ts +4 -1
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs.ts +8 -8
- 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/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +20 -2
- package/src/db/maintenance-job-runs-async.ts +2 -2
- package/src/db/maintenance-job-write-ops.ts +1 -1
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +18 -1
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +10 -4
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +41 -48
- 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-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/read-op-marshaling-fixtures.ts +18 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- 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 +4 -1
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +5 -3
- package/src/db/task-entity.ts +5 -4
- 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/token-db-write-ops.ts +2 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +6 -9
- 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/workspaces.ts +8 -5
- package/src/db/write-ops.ts +31 -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 +42 -46
- package/src/dev.ts +8 -3
- 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-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 +104 -98
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +3 -3
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/jobs.ts +29 -67
- 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 +18 -13
- package/src/maintenance/stalled-delivery-pager.ts +4 -4
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +17 -27
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +3 -3
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +8 -8
- package/src/mcp/output-descriptions.ts +1 -1
- package/src/mcp/presentation.ts +2 -1
- 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 +3 -2
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-workspace.ts +1 -1
- 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 +3 -3
- 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 +1 -1
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +5 -3
- 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/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +2 -5
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +8 -1
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +4 -3
- 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-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 +1 -1
- package/src/routes/agents.ts +17 -119
- 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 +1 -1
- package/src/routes/commands.ts +29 -27
- package/src/routes/context-resets.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 +2 -1
- package/src/routes/integrations.ts +9 -7
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +3 -3
- 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 +1 -1
- package/src/routes/orchestrator-host-registration.ts +2 -0
- package/src/routes/orchestrator-host-utilization.ts +2 -2
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +27 -18
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +1 -1
- package/src/routes/project-trust.ts +1 -1
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- 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 +1 -1
- 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/team-templates.ts +7 -7
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +18 -17
- 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 +2 -2
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-push.ts +6 -6
- package/src/runtime-grant.ts +17 -11
- package/src/runtime-tokens.ts +20 -28
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +3 -1
- 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 +1 -1
- package/src/server.ts +21 -22
- 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 +9 -9
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +4 -4
- 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 +14 -13
- package/src/services/issue-refs.ts +4 -5
- package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +3 -3
- 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 +6 -5
- 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 +3 -3
- 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 +1 -1
- 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 +8 -3
- package/src/services/profile-trust.ts +2 -2
- 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/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 +17 -16
- 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-effort-grant.ts +5 -25
- package/src/services/send-message.ts +16 -33
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +12 -41
- package/src/services/spawn-chain-inspector.ts +1 -1
- 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-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +7 -8
- 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-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 +3 -4
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +5 -5
- 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 +22 -19
- 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 +2 -1
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.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 +1 -1
- package/src/services/workflow-effect-driver.ts +42 -19
- package/src/services/workflow-effects.ts +41 -27
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +1 -0
- 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 +4 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +34 -22
- package/src/services/workflow-supervisor-state.ts +21 -1
- package/src/services/workflow-supervisor.ts +4 -3
- package/src/services/workspace-recovery.ts +4 -3
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-placement.ts +27 -9
- package/src/spawn-targets.ts +8 -8
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +61 -57
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +2 -2
- package/src/task-dispatch-live.ts +5 -2
- package/src/task-dispatcher.ts +2 -2
- 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 +24 -16
- 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 +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
- package/public/assets/provider-display-DsuWMvVL.js +0 -2
- package/public/assets/run-card-CpKqRbhg.js +0 -2
- package/public/assets/shipping-B9YtnwtG.js +0 -2
- package/public/assets/store-DcClXLH0.js +0 -9
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/src/db/on-loop-write-transaction.ts +0 -34
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { claimWorkspaceHumanEscalationAlertAsync } from "./db/runtime-tail-async";
|
|
1
2
|
import { stewardFallbackTarget } from "./config";
|
|
2
|
-
|
|
3
|
+
|
|
3
4
|
import { routeNotification } from "./notification-router";
|
|
4
5
|
import { raiseOperatorAlarm } from "./operator-alarm";
|
|
5
6
|
import { resolveStewardIdentity } from "./steward-identity";
|
|
@@ -18,7 +19,7 @@ export interface WorkspaceCustodyEscalationInput {
|
|
|
18
19
|
idempotencyKey?: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
export function routeWorkspaceCustodyEscalation(input: WorkspaceCustodyEscalationInput): string[] {
|
|
22
|
+
export async function routeWorkspaceCustodyEscalation(input: WorkspaceCustodyEscalationInput): Promise<string[]> {
|
|
22
23
|
const { ownerAgentId, coordinatorAgentId } = resolveStewardIdentity(input.workspace);
|
|
23
24
|
const fallback = stewardFallbackTarget();
|
|
24
25
|
const recipients = [...new Set([ownerAgentId, coordinatorAgentId, fallback].filter((value): value is string => Boolean(value)))];
|
|
@@ -31,7 +32,7 @@ export function routeWorkspaceCustodyEscalation(input: WorkspaceCustodyEscalatio
|
|
|
31
32
|
// the caller's idempotencyKey (which already bakes in the condition
|
|
32
33
|
// fingerprint) so an unchanged condition never re-sends, while a real change
|
|
33
34
|
// (new key) still alerts.
|
|
34
|
-
if (input.idempotencyKey && !
|
|
35
|
+
if (input.idempotencyKey && !(await claimWorkspaceHumanEscalationAlertAsync(input.idempotencyKey))) {
|
|
35
36
|
const channelId = workspaceHumanEscalationChannelId();
|
|
36
37
|
return channelId ? [channelId] : [];
|
|
37
38
|
}
|
|
@@ -41,18 +42,18 @@ export function routeWorkspaceCustodyEscalation(input: WorkspaceCustodyEscalatio
|
|
|
41
42
|
ownerAgentId,
|
|
42
43
|
fallbackTarget: fallback || undefined,
|
|
43
44
|
};
|
|
44
|
-
const human = notifyWorkspaceHumanEscalation({
|
|
45
|
+
const human = (await notifyWorkspaceHumanEscalation({
|
|
45
46
|
subject: input.subject,
|
|
46
47
|
body: input.body,
|
|
47
48
|
payload,
|
|
48
49
|
source: "workspace-custody",
|
|
49
|
-
});
|
|
50
|
+
}));
|
|
50
51
|
if (human.accepted && human.channelId) return [human.channelId];
|
|
51
52
|
console.warn(`[workspace-escalation] zero agent recipients and no human channel for workspace ${input.workspace.id}: ${human.reason ?? "unknown reason"}`);
|
|
52
53
|
return [];
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
routeNotification({
|
|
56
|
+
await routeNotification({
|
|
56
57
|
type: input.type ?? "workspace.stranded_escalation",
|
|
57
58
|
scope: {
|
|
58
59
|
workspaceId: input.workspace.id,
|
|
@@ -84,13 +85,13 @@ export function routeWorkspaceCustodyEscalation(input: WorkspaceCustodyEscalatio
|
|
|
84
85
|
// undefined) and most `review_requested` auto-abandons have no agent to page by default,
|
|
85
86
|
// so without this the notice is swallowed and the strand loops in the dark. Returns the
|
|
86
87
|
// (possibly empty) recipient list so the caller can still decide whether to stamp state.
|
|
87
|
-
export function routeWorkspaceCustodyEscalationOrAlarm(
|
|
88
|
+
export async function routeWorkspaceCustodyEscalationOrAlarm(
|
|
88
89
|
input: WorkspaceCustodyEscalationInput & { source: string },
|
|
89
|
-
): string[] {
|
|
90
|
+
): Promise<string[]> {
|
|
90
91
|
const { source, ...escalation } = input;
|
|
91
|
-
const targets = routeWorkspaceCustodyEscalation(escalation);
|
|
92
|
+
const targets = await routeWorkspaceCustodyEscalation(escalation);
|
|
92
93
|
if (!targets.length) {
|
|
93
|
-
raiseOperatorAlarm({
|
|
94
|
+
(await raiseOperatorAlarm({
|
|
94
95
|
clientId: `${escalation.idempotencyKey ?? `${escalation.workspace.id}:${escalation.subject}`}:no-recipients`,
|
|
95
96
|
source,
|
|
96
97
|
subject: escalation.subject,
|
|
@@ -101,7 +102,7 @@ export function routeWorkspaceCustodyEscalationOrAlarm(
|
|
|
101
102
|
branch: escalation.workspace.branch,
|
|
102
103
|
status: escalation.workspace.status,
|
|
103
104
|
},
|
|
104
|
-
});
|
|
105
|
+
}));
|
|
105
106
|
}
|
|
106
107
|
return targets;
|
|
107
108
|
}
|
|
@@ -43,7 +43,7 @@ export function warnIfNoHumanReachableEscalationTarget(log: (message: string) =>
|
|
|
43
43
|
return true;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function notifyWorkspaceHumanEscalation(input: WorkspaceHumanEscalationInput): WorkspaceHumanEscalationResult {
|
|
46
|
+
export async function notifyWorkspaceHumanEscalation(input: WorkspaceHumanEscalationInput): Promise<WorkspaceHumanEscalationResult> {
|
|
47
47
|
const channelId = workspaceHumanEscalationChannelId();
|
|
48
48
|
if (!channelId) return { accepted: false, reason: "no human escalation channel configured" };
|
|
49
49
|
if (!getChannel(channelId)) return { accepted: false, reason: `human escalation channel ${channelId} is not registered` };
|
|
@@ -59,9 +59,9 @@ export function notifyWorkspaceHumanEscalation(input: WorkspaceHumanEscalationIn
|
|
|
59
59
|
|
|
60
60
|
try {
|
|
61
61
|
if (channelId === DEFAULT_NTFY_CHANNEL_ID) {
|
|
62
|
-
relayNotifyNtfy(event, input.idempotencyKey);
|
|
62
|
+
(await relayNotifyNtfy(event, input.idempotencyKey));
|
|
63
63
|
} else {
|
|
64
|
-
relayEgressToChannel({ channelId, event }, undefined, input.idempotencyKey);
|
|
64
|
+
(await relayEgressToChannel({ channelId, event }, undefined, input.idempotencyKey));
|
|
65
65
|
}
|
|
66
66
|
return { accepted: true, channelId };
|
|
67
67
|
} catch (error) {
|
|
@@ -41,21 +41,21 @@ export async function runLandGateFailureWatchdog(opts: { now?: number; delayMs?:
|
|
|
41
41
|
const coordinator = resolveCoordinatorAgentId(owner);
|
|
42
42
|
const target = coordinator ?? stewardFallbackTarget() ?? owner;
|
|
43
43
|
if (!target) {
|
|
44
|
-
raiseOperatorAlarm({
|
|
44
|
+
(await raiseOperatorAlarm({
|
|
45
45
|
clientId: `land-gate-failed-unescalatable:${fresh.id}:${failure.notifiedAt}`,
|
|
46
46
|
source: "workspace-land-gate-watchdog",
|
|
47
47
|
subject: "Land gate failure has no escalation recipient",
|
|
48
48
|
detail: `${fresh.branch ?? fresh.id} remains blocked by required gate ${failure.gateName ?? "(unknown)"} with no author, coordinator, or configured fallback.`,
|
|
49
49
|
view: "orchestrators",
|
|
50
50
|
metadata: { workspaceId: fresh.id, repoRoot: fresh.repoRoot, branch: fresh.branch, gateName: failure.gateName },
|
|
51
|
-
});
|
|
51
|
+
}));
|
|
52
52
|
await patchWorkspaceMetadataAsync(fresh.id, { landGateFailureEscalatedAt: now });
|
|
53
53
|
escalated.push(fresh.id);
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
56
56
|
const targetAgent = getAgent(target);
|
|
57
57
|
const enabled = notificationEnabledFor("workspace.land_gate_failed", { agentId: target, teamId: targetAgent?.teamId });
|
|
58
|
-
routeNotification({
|
|
58
|
+
await routeNotification({
|
|
59
59
|
type: "workspace.land_gate_failed",
|
|
60
60
|
scope: { author: owner, parent: coordinator ?? undefined, repoRoot: fresh.repoRoot, workspaceId: fresh.id },
|
|
61
61
|
recipients: [target],
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { WorkspaceRecord } from "@humwick/sdk";
|
|
2
|
+
import { updateWorkspaceStatusAsync } from "./db";
|
|
3
|
+
import { notifyBranchLandFailed } from "./branch-landed";
|
|
4
|
+
import { deferLandSettleSideEffect } from "./land-settle-dispatch";
|
|
5
|
+
import { landStoppedFact, recordLandStopped } from "./workspace-land-stopped";
|
|
6
|
+
|
|
7
|
+
export class LandConfigurationError extends Error {}
|
|
8
|
+
|
|
9
|
+
/** A new delivery arms a new hand-off; base movement cannot repair a refused configuration (#3824). */
|
|
10
|
+
export function workspaceLandRefused(workspace: WorkspaceRecord): boolean {
|
|
11
|
+
const stop = landStoppedFact(workspace.metadata);
|
|
12
|
+
return stop?.reason === "refused" && stop.handoff === workspace.metadata.landRequestAttemptAt;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function refuseWorkspaceLand(workspace: WorkspaceRecord, reason: string, commandId?: string): Promise<void> {
|
|
16
|
+
if (workspaceLandRefused(workspace)) return;
|
|
17
|
+
const current = await updateWorkspaceStatusAsync(workspace.id, "review_requested", { mergeError: reason });
|
|
18
|
+
await recordLandStopped(workspace.id, "refused", reason, { final: true });
|
|
19
|
+
deferLandSettleSideEffect("land-refused", () => notifyBranchLandFailed({ workspace: current ?? workspace, commandId, reason }));
|
|
20
|
+
}
|
package/src/workspace-merge.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { acquireMergeLeaseAsync, releaseMergeLeaseAsync } from "./db/runtime-tail-async";
|
|
2
|
+
import { LandConfigurationError, refuseWorkspaceLand } from "./workspace-land-refusal";
|
|
1
3
|
import { capturedDeliveryGateRefusal } from "./services/captured-delivery-gate";
|
|
2
4
|
import { ValidationError } from "./db/connection";
|
|
3
5
|
import { WORKSPACE_MERGE_HOLD_MESSAGE } from "./db/workspace-merge-hold";
|
|
@@ -6,19 +8,7 @@ import { resolve } from "node:path";
|
|
|
6
8
|
import { randomUUID } from "node:crypto";
|
|
7
9
|
import { errMessage, isRecord, stringValue, type LandingContainmentMode } from "@humwick/sdk";
|
|
8
10
|
import { cancelPendingLegacyLandingsAsync, createLegacyLandingAsync } from "./commands-landing-async";
|
|
9
|
-
import {
|
|
10
|
-
acquireMergeLease,
|
|
11
|
-
exitCertificateMatchesInstance,
|
|
12
|
-
getActiveMergePause,
|
|
13
|
-
getAgent,
|
|
14
|
-
listAgents,
|
|
15
|
-
listOrchestrators,
|
|
16
|
-
patchWorkspaceMetadataAsync,
|
|
17
|
-
releaseMergeLease,
|
|
18
|
-
REVIEW_HOLD_REJECT_MESSAGE,
|
|
19
|
-
updateWorkspaceStatusAsync,
|
|
20
|
-
workspaceLandBarrier,
|
|
21
|
-
} from "./db";
|
|
11
|
+
import { exitCertificateMatchesInstance, getActiveMergePause, getAgent, listAgents, listOrchestrators, patchWorkspaceMetadataAsync, REVIEW_HOLD_REJECT_MESSAGE, updateWorkspaceStatusAsync, workspaceLandBarrier } from "./db";
|
|
22
12
|
import { ensureLegacyOpenLandingOwnershipAsync } from "./db/landing-ingress-async";
|
|
23
13
|
import { OFFLINE_PRUNE_MS } from "./config";
|
|
24
14
|
import { getLandingConfig } from "./config-store";
|
|
@@ -44,8 +34,6 @@ import type { LandingLaneIdentity } from "./landing-lane-key";
|
|
|
44
34
|
import { archiveLandAttempt, CLEAR_LAST_ATTEMPT_VERDICT, CLEAR_MERGE_RETRY, heavyGateQueuePriorityForRetry } from "./workspace-merge-progress";
|
|
45
35
|
import { coalesceWorkspaceMerge } from "./workspace-merge-dispatch";
|
|
46
36
|
|
|
47
|
-
// Re-export so consumers can import the tuple from the strategy home without a
|
|
48
|
-
// second import hop.
|
|
49
37
|
export { AUTO_MERGE_POLICIES } from "./types";
|
|
50
38
|
|
|
51
39
|
// One home for the land-strategy contract, shared by BOTH land surfaces — the HTTP
|
|
@@ -393,12 +381,7 @@ async function dispatchWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
|
|
|
393
381
|
// unauthorized one is refused outright instead of being silently ignored.
|
|
394
382
|
const gate = resolveWorkspaceLandGate(workspace, { level: opts.gateLevel, reason: opts.gateReason, auth: opts.gateAuth });
|
|
395
383
|
if (!gate.ok) return { ok: false, status: gate.status, error: gate.error };
|
|
396
|
-
// #638 —
|
|
397
|
-
// repo. The auto-merge job already honors it (workspace-auto-merge.ts), but gate the
|
|
398
|
-
// shared dispatcher too as defense-in-depth: never let an auto-merge-originated request
|
|
399
|
-
// acquire the lease + storm while paused, regardless of which caller dispatched it. A
|
|
400
|
-
// manual/steward land (any other `requestedBy`) is the intended RECOVERY path during a
|
|
401
|
-
// pause, so it's allowed through.
|
|
384
|
+
// #638 — auto-merge honors the repo pause here too; manual/steward lands remain a recovery path.
|
|
402
385
|
if (!plainGit && opts.requestedBy === "auto-merge" && getActiveMergePause(workspace.repoRoot, workspace.baseRef ?? "main")) {
|
|
403
386
|
return { ok: false, status: 409, error: `auto-merge paused for ${workspace.repoRoot}` };
|
|
404
387
|
}
|
|
@@ -420,9 +403,10 @@ async function dispatchWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
|
|
|
420
403
|
let gatePlacement: Awaited<ReturnType<typeof selectLandGateHost>>;
|
|
421
404
|
try {
|
|
422
405
|
gatePlacement = await selectLandGateHost(workspace, onlineOwner, laneIdentity.remoteIdentity,
|
|
423
|
-
effectiveStrategy !== "pr" && effectiveStrategy !== "auto" && gate.gate.level !== "none" ? laneIdentity.gateRequirements : undefined);
|
|
406
|
+
effectiveStrategy !== "pr" && effectiveStrategy !== "auto" && gate.gate.level !== "none" ? laneIdentity.gateRequirements : undefined, laneIdentity.gateDepsStrategy);
|
|
424
407
|
} catch (error) {
|
|
425
|
-
|
|
408
|
+
if (error instanceof LandConfigurationError) await refuseWorkspaceLand(workspace, error.message);
|
|
409
|
+
return { ok: false, status: error instanceof LandConfigurationError ? 422 : 409, error: errMessage(error) };
|
|
426
410
|
}
|
|
427
411
|
const gateHost = gatePlacement.orchestrator;
|
|
428
412
|
const mergeLeaseKey = laneIdentity.remoteIdentity.startsWith("remote:") ? laneIdentity.remoteIdentity : `remote:${laneIdentity.remoteIdentity}`;
|
|
@@ -438,7 +422,7 @@ async function dispatchWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
|
|
|
438
422
|
let leaseAcquired = false;
|
|
439
423
|
let commandCreated = false;
|
|
440
424
|
if (!plainGit || gatePlacement.delegated) {
|
|
441
|
-
const lease =
|
|
425
|
+
const lease = (await acquireMergeLeaseAsync(mergeLeaseKey, workspace.id, opts.requestedBy));
|
|
442
426
|
if (!lease.ok) {
|
|
443
427
|
if (containmentMode === "cgroup-v2-close-v1") {
|
|
444
428
|
await cleanupLegacyLandingReservationOnHost(gateHost, executionTreeHandle!).catch(() => false);
|
|
@@ -493,7 +477,7 @@ async function dispatchWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
|
|
|
493
477
|
lastWorkspaceActionAt: armAt,
|
|
494
478
|
});
|
|
495
479
|
if (!updated) {
|
|
496
|
-
if (leaseAcquired)
|
|
480
|
+
if (leaseAcquired) (await releaseMergeLeaseAsync({ repoRoot: mergeLeaseKey, workspaceId: workspace.id }));
|
|
497
481
|
if (containmentMode === "cgroup-v2-close-v1") {
|
|
498
482
|
await cleanupLegacyLandingReservationOnHost(gateHost, executionTreeHandle!).catch(() => false);
|
|
499
483
|
}
|
|
@@ -604,7 +588,7 @@ async function dispatchWorkspaceMerge(workspace: WorkspaceRecord, opts: RequestW
|
|
|
604
588
|
} catch (e) {
|
|
605
589
|
// Acquired the lease but failed before dispatch — release it or the repo
|
|
606
590
|
// stays blocked until the TTL expires.
|
|
607
|
-
if (!commandCreated && leaseAcquired)
|
|
591
|
+
if (!commandCreated && leaseAcquired) (await releaseMergeLeaseAsync({ repoRoot: mergeLeaseKey, workspaceId: workspace.id }));
|
|
608
592
|
if (!commandCreated && containmentMode === "cgroup-v2-close-v1") {
|
|
609
593
|
await cleanupLegacyLandingReservationOnHost(gateHost, executionTreeHandle!).catch(() => false);
|
|
610
594
|
}
|
|
@@ -6,14 +6,14 @@ import { withWorkspaceTaskOwnerRoles } from "./task-owner-notices";
|
|
|
6
6
|
import { resolveLandedTaskIds } from "./services/landed-task-attribution";
|
|
7
7
|
import type { WorkspaceRecord } from "./types";
|
|
8
8
|
|
|
9
|
-
export function notifyNothingToLand(workspace: WorkspaceRecord, sha: string, commandId: string, sourceHeadSha?: string): void {
|
|
9
|
+
export async function notifyNothingToLand(workspace: WorkspaceRecord, sha: string, commandId: string, sourceHeadSha?: string): Promise<void> {
|
|
10
10
|
const author = workspace.ownerAgentId;
|
|
11
11
|
const coordinator = resolveCoordinatorAgentId(author);
|
|
12
12
|
const taskOwners = resolveLandedTaskIds({ workspace, sourceHeadSha }).map(id => resolveTaskOwnerAgentId(getTaskDetail(id)));
|
|
13
13
|
const recipients = withWorkspaceTaskOwnerRoles([author, coordinator, ...taskOwners], workspace);
|
|
14
14
|
if (!recipients.length) return;
|
|
15
15
|
const base = workspace.baseRef ?? "base";
|
|
16
|
-
routeNotification({
|
|
16
|
+
await routeNotification({
|
|
17
17
|
type: "branch.landed",
|
|
18
18
|
scope: { author, parent: coordinator ?? undefined, repoRoot: workspace.repoRoot, workspaceId: workspace.id },
|
|
19
19
|
recipients, forceDelivery: true, ttlMs: null,
|
package/src/workspace-orphans.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { pruneWorkspaceOrphanAlertsAsync, pruneStaleWorkspaceHumanEscalationAlertsAsync, claimWorkspaceOrphanAlertAsync } from "./db/runtime-tail-async";
|
|
2
|
+
import { dispatchOrphanCleanup } from "./workspace-cleanup-stale";
|
|
3
|
+
import { emitCommandEvent } from "./command-events";
|
|
1
4
|
// Orphaned-worktree reconciliation (#244). An isolated worktree on disk with no
|
|
2
5
|
// live DB row is "orphaned" — left behind when a session ended without a clean
|
|
3
6
|
// teardown (crash, killed runner, a reaped row). Symmetrically, a live row whose
|
|
@@ -20,8 +23,8 @@
|
|
|
20
23
|
|
|
21
24
|
import { resolve } from "node:path";
|
|
22
25
|
import type { WorkspaceMergePreview, WorkspaceOrphan, WorkspaceProbe, WorkspaceProbeWorktree, WorkspaceRecord, WorkspaceStatus } from "./types";
|
|
23
|
-
import {
|
|
24
|
-
|
|
26
|
+
import { createActivityEventAsync, getWorkspace, listOrchestrators, listWorkspaces, updateWorkspaceStatusAsync } from "./db";
|
|
27
|
+
|
|
25
28
|
import { isPathWithinBase } from "./utils";
|
|
26
29
|
import { IN_FLIGHT_WORKSPACE_STATUSES, TERMINAL_WORKSPACE_STATUSES, worktreeReapable, type WorktreeReapState } from "./workspace-phase";
|
|
27
30
|
import { isOwnerAlive, isOwnerProcessConfirmedGone, liveAgentCwds, worktreeInUseByLiveAgent } from "./workspace-merge";
|
|
@@ -33,7 +36,6 @@ import { READY_TO_LAND_ESCALATION_STATUSES, routeWorkspaceCustodyEscalationOrAla
|
|
|
33
36
|
import { workspaceLandBlocked } from "./land-block";
|
|
34
37
|
import { dispatchDeadOwnerRescue } from "./workspace-dead-owner-recovery";
|
|
35
38
|
import { runWithConcurrency, sortLeastRecentlyProbed } from "./maintenance/workspaces";
|
|
36
|
-
import { emitCommandEvent } from "./command-events";
|
|
37
39
|
import {
|
|
38
40
|
WORKSPACE_ORPHAN_REAPER_DEAD_OWNER_PROBE_BATCH_SIZE,
|
|
39
41
|
WORKSPACE_ORPHAN_REAPER_MISSING_PROBE_BATCH_SIZE,
|
|
@@ -421,27 +423,6 @@ export async function collectWorkspaceOrphans(
|
|
|
421
423
|
return { orphans, missingWorktrees, deadOwnerWorkspaces, ...(moreOrphanEnrichmentWork ? { moreOrphanEnrichmentWork } : {}) };
|
|
422
424
|
}
|
|
423
425
|
|
|
424
|
-
function dispatchCleanup(orch: OnlineOrchestrator, orphan: WorkspaceOrphan): string {
|
|
425
|
-
const command = createCommand({
|
|
426
|
-
type: "workspace.cleanup",
|
|
427
|
-
source: "system",
|
|
428
|
-
target: orch.agentId,
|
|
429
|
-
params: {
|
|
430
|
-
action: "cleanup",
|
|
431
|
-
worktreePath: orphan.worktreePath,
|
|
432
|
-
repoRoot: orphan.repoRoot,
|
|
433
|
-
branch: orphan.branch,
|
|
434
|
-
baseRef: orphan.baseRef,
|
|
435
|
-
baseSha: orphan.baseSha,
|
|
436
|
-
deleteBranch: true,
|
|
437
|
-
reclaim: true,
|
|
438
|
-
requestedBy: "workspace-orphan-reaper",
|
|
439
|
-
requestedAt: Date.now(),
|
|
440
|
-
},
|
|
441
|
-
});
|
|
442
|
-
emitCommandEvent(command, `command.${command.status}`);
|
|
443
|
-
return command.id;
|
|
444
|
-
}
|
|
445
426
|
|
|
446
427
|
/**
|
|
447
428
|
* Scheduled reaper (maintenance job). Auto-removes orphaned worktrees that are
|
|
@@ -520,7 +501,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
520
501
|
if (!reapEnabled) continue; // detect-only mode
|
|
521
502
|
if (nonTerminalRowsByPath.has(resolve(orphan.worktreePath))) continue; // still claimed — never reap (#278)
|
|
522
503
|
if (worktreeInUseByLiveAgent(orphan.worktreePath, liveCwds)) continue; // a live agent runs in it — never reap its cwd
|
|
523
|
-
const commandId =
|
|
504
|
+
const commandId = (await dispatchOrphanCleanup(orch.agentId, orphan));
|
|
524
505
|
reaped.push(orphan.worktreePath);
|
|
525
506
|
await createActivityEventAsync({
|
|
526
507
|
clientId: `workspace-orphan-reaped-${orphan.worktreePath}-${now}`,
|
|
@@ -541,7 +522,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
541
522
|
const alertKey = `disk:${resolve(orphan.worktreePath)}`;
|
|
542
523
|
liveAlertKeys.add(alertKey);
|
|
543
524
|
const fingerprint = orphanAlertFingerprint({ headSha: orphan.headSha, ahead: orphan.ahead, unmergedAhead: orphan.unmergedAhead, dirty: orphan.dirty, safeToReap: orphan.safeToReap });
|
|
544
|
-
if (!
|
|
525
|
+
if (!(await claimWorkspaceOrphanAlertAsync(alertKey, fingerprint, now))) continue;
|
|
545
526
|
flagged.push(orphan.worktreePath);
|
|
546
527
|
const detail = orphan.safeToReap === undefined
|
|
547
528
|
? "host could not be probed for land-state"
|
|
@@ -549,7 +530,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
549
530
|
? "uncommitted changes in the worktree"
|
|
550
531
|
: `${orphan.unmergedAhead ?? orphan.ahead ?? "?"} un-landed commit(s)`;
|
|
551
532
|
if (orphanHasWorkEvidence(orphan)) {
|
|
552
|
-
routeWorkspaceCustodyEscalationOrAlarm({
|
|
533
|
+
await routeWorkspaceCustodyEscalationOrAlarm({
|
|
553
534
|
source: "workspace-orphan-reaper",
|
|
554
535
|
workspace: { id: `orphan:${orphan.worktreePath}`, repoRoot: orphan.repoRoot, branch: orphan.branch, status: "review_requested", ownerAgentId: undefined },
|
|
555
536
|
subject: "Stranded worktree needs attention",
|
|
@@ -586,9 +567,9 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
586
567
|
const inFlight = IN_FLIGHT_WORKSPACE_STATUSES.has(workspace.status);
|
|
587
568
|
if (ownerAlive || inFlight) {
|
|
588
569
|
liveAlertKeys.add(key);
|
|
589
|
-
if (!
|
|
570
|
+
if (!(await claimWorkspaceOrphanAlertAsync(key, orphanAlertFingerprint({ status: workspace.status, ownerAlive, inFlight }), now))) continue;
|
|
590
571
|
if (workspaceNeedsCustodyEscalation(workspace, false)) {
|
|
591
|
-
routeWorkspaceCustodyEscalationOrAlarm({
|
|
572
|
+
await routeWorkspaceCustodyEscalationOrAlarm({
|
|
592
573
|
source: "workspace-orphan-reaper",
|
|
593
574
|
workspace,
|
|
594
575
|
subject: "Workspace row has no worktree on disk",
|
|
@@ -658,7 +639,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
658
639
|
if (!updated) continue;
|
|
659
640
|
autoAbandoned.push(workspace.id);
|
|
660
641
|
if (workspaceNeedsCustodyEscalation(workspace, previewHasWorkEvidence(probe.kind === "preview" ? probe.preview : null))) {
|
|
661
|
-
routeWorkspaceCustodyEscalationOrAlarm({
|
|
642
|
+
await routeWorkspaceCustodyEscalationOrAlarm({
|
|
662
643
|
source: "workspace-orphan-reaper",
|
|
663
644
|
workspace,
|
|
664
645
|
type: "workspace.auto_abandoned",
|
|
@@ -690,7 +671,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
690
671
|
|
|
691
672
|
liveAlertKeys.add(key);
|
|
692
673
|
const missingFingerprint = orphanAlertFingerprint({ status: workspace.status, probe: probe.kind, recoverableTip: probe.kind === "preview" ? probe.preview.recoverableTip : undefined, headSha: probe.kind === "preview" ? probe.preview.headSha : undefined, ahead: probe.kind === "preview" ? probe.preview.ahead : undefined, unmergedAhead: probe.kind === "preview" ? probe.preview.unmergedAhead : undefined });
|
|
693
|
-
if (!
|
|
674
|
+
if (!(await claimWorkspaceOrphanAlertAsync(key, missingFingerprint, now))) continue;
|
|
694
675
|
flaggedMissingWorktrees.push(workspace.id);
|
|
695
676
|
const hasWorkEvidence = probe.kind === "preview" && previewHasWorkEvidence(probe.preview);
|
|
696
677
|
const detail = probe.kind === "preview"
|
|
@@ -701,7 +682,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
701
682
|
? `host could not confirm whether branch ${workspace.branch} has landed`
|
|
702
683
|
: "host could not confirm whether recoverable branch work remains";
|
|
703
684
|
if (workspaceNeedsCustodyEscalation(workspace, hasWorkEvidence)) {
|
|
704
|
-
routeWorkspaceCustodyEscalationOrAlarm({
|
|
685
|
+
await routeWorkspaceCustodyEscalationOrAlarm({
|
|
705
686
|
source: "workspace-orphan-reaper",
|
|
706
687
|
workspace,
|
|
707
688
|
subject: "Missing-worktree workspace needs attention",
|
|
@@ -846,10 +827,10 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
846
827
|
liveDeadOwnerKeys.add(flagKey);
|
|
847
828
|
liveAlertKeys.add(flagKey);
|
|
848
829
|
const deadOwnerFingerprint = orphanAlertFingerprint({ status: workspace.status, headSha: preview?.headSha, ahead: preview?.ahead, unmergedAhead: preview?.unmergedAhead, dirtyCount: preview?.dirtyCount, probeAvailable: Boolean(preview) });
|
|
849
|
-
if (!
|
|
830
|
+
if (!(await claimWorkspaceOrphanAlertAsync(flagKey, deadOwnerFingerprint, now))) continue;
|
|
850
831
|
deadOwnerFlagged.push(workspace.id);
|
|
851
832
|
const rescueCommandId = preview?.originCaptureChecked === true && preview.originCaptured === false && orch
|
|
852
|
-
? dispatchDeadOwnerRescue(orch, workspace)
|
|
833
|
+
? (await dispatchDeadOwnerRescue(orch, workspace))
|
|
853
834
|
: undefined;
|
|
854
835
|
const detail = safeToReap === undefined
|
|
855
836
|
? "host could not be probed for land-state"
|
|
@@ -858,7 +839,7 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
858
839
|
: `${preview?.unmergedAhead ?? preview?.ahead ?? "?"} un-landed commit(s)`;
|
|
859
840
|
const hasWorkEvidence = previewHasWorkEvidence(preview);
|
|
860
841
|
if (workspaceNeedsCustodyEscalation(workspace, hasWorkEvidence)) {
|
|
861
|
-
routeWorkspaceCustodyEscalationOrAlarm({
|
|
842
|
+
await routeWorkspaceCustodyEscalationOrAlarm({
|
|
862
843
|
source: "workspace-orphan-reaper",
|
|
863
844
|
workspace,
|
|
864
845
|
subject: "Dead-owner worktree needs attention",
|
|
@@ -896,8 +877,8 @@ export async function reapOrphanedWorktrees(context: { signal?: AbortSignal } =
|
|
|
896
877
|
// still waiting it out and re-fire orphan alerts already claimed for this condition.
|
|
897
878
|
if (!signal?.aborted) {
|
|
898
879
|
for (const key of deadOwnerTracker.keys()) if (!liveDeadOwnerKeys.has(key)) deadOwnerTracker.delete(key);
|
|
899
|
-
|
|
900
|
-
|
|
880
|
+
(await pruneWorkspaceOrphanAlertsAsync(liveAlertKeys));
|
|
881
|
+
(await pruneStaleWorkspaceHumanEscalationAlertsAsync(now, HUMAN_ESCALATION_ALERT_MAX_AGE_MS));
|
|
901
882
|
}
|
|
902
883
|
|
|
903
884
|
// #2408 — true whenever ANY of the three per-tick probe budgets left candidates un-probed this run.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { createActivityEventAsync } from "./db/activity-async";
|
|
2
|
+
import { createCommandAsync } from "./commands-write";
|
|
1
3
|
import { isRecord } from "@humwick/sdk";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
+
import { getCommand } from "./commands-db";
|
|
5
|
+
import { patchWorkspaceMetadataAsync, workspaceLandBarrier } from "./db";
|
|
4
6
|
import { handleReviewerPipelineScan, isAwaitingReviewerApproval } from "./reviewer-pipeline";
|
|
5
7
|
import { isOwnerAlive, requestWorkspaceMerge } from "./workspace-merge";
|
|
6
8
|
import type { Command, WorkspaceAutoMergePolicy, WorkspaceMergePreview, WorkspaceRecord } from "./types";
|
|
@@ -39,7 +41,7 @@ export async function reconcileLandedPr(workspace: WorkspaceRecord, preview: Wor
|
|
|
39
41
|
},
|
|
40
42
|
});
|
|
41
43
|
if (recycle.ok) {
|
|
42
|
-
|
|
44
|
+
(await createActivityEventAsync({
|
|
43
45
|
clientId: `workspace-pr-recycle-${workspace.id}-${Date.now()}`,
|
|
44
46
|
kind: "state",
|
|
45
47
|
title: "Workspace recycling after PR land",
|
|
@@ -48,7 +50,7 @@ export async function reconcileLandedPr(workspace: WorkspaceRecord, preview: Wor
|
|
|
48
50
|
icon: "ti-git-merge",
|
|
49
51
|
view: "orchestrators",
|
|
50
52
|
metadata: { source: "server", maintenanceJobId: "workspace-conflict-scan", workspaceId: workspace.id, commandId: recycle.command.id, landedVia: "pr" },
|
|
51
|
-
});
|
|
53
|
+
}));
|
|
52
54
|
return { kind: "recycle", command: recycle.command };
|
|
53
55
|
}
|
|
54
56
|
// 409 = lease held by an in-flight merge — retry next sweep, don't finalize (re-strands a
|
|
@@ -199,7 +201,7 @@ async function dispatchRelayPrMergeCommand(workspace: WorkspaceRecord, preview:
|
|
|
199
201
|
const now = Date.now();
|
|
200
202
|
const prNumber = preview.prNumber ?? (typeof workspace.metadata.prNumber === "number" ? workspace.metadata.prNumber : undefined);
|
|
201
203
|
const prUrl = preview.prUrl ?? text(workspace.metadata.prUrl);
|
|
202
|
-
const command =
|
|
204
|
+
const command = (await createCommandAsync({
|
|
203
205
|
type: "workspace.pr-merge",
|
|
204
206
|
source: "system",
|
|
205
207
|
target: orchestratorAgentId,
|
|
@@ -209,7 +211,7 @@ async function dispatchRelayPrMergeCommand(workspace: WorkspaceRecord, preview:
|
|
|
209
211
|
branch: workspace.branch, baseRef: workspace.baseRef, prNumber, prUrl, policy,
|
|
210
212
|
requestedBy: "relay-pr-completion", requestedAt: now,
|
|
211
213
|
},
|
|
212
|
-
});
|
|
214
|
+
}));
|
|
213
215
|
await patchWorkspaceMetadataAsync(workspace.id, {
|
|
214
216
|
relayMerged: true, relayMergeCommandId: command.id, relayMergeDispatchedAt: now, relayMergePolicy: policy,
|
|
215
217
|
relayMergeError: undefined, relayMergeFailedAt: undefined,
|
|
@@ -221,7 +223,7 @@ async function dispatchRelayPrRefreshCommand(workspace: WorkspaceRecord, preview
|
|
|
221
223
|
const now = Date.now();
|
|
222
224
|
const prNumber = preview.prNumber ?? (typeof workspace.metadata.prNumber === "number" ? workspace.metadata.prNumber : undefined);
|
|
223
225
|
const prUrl = preview.prUrl ?? text(workspace.metadata.prUrl);
|
|
224
|
-
const command =
|
|
226
|
+
const command = (await createCommandAsync({
|
|
225
227
|
type: "workspace.pr-refresh",
|
|
226
228
|
source: "system",
|
|
227
229
|
target: orchestratorAgentId,
|
|
@@ -231,7 +233,7 @@ async function dispatchRelayPrRefreshCommand(workspace: WorkspaceRecord, preview
|
|
|
231
233
|
branch: workspace.branch, baseRef: workspace.baseRef, prNumber, prUrl, policy, refreshKey, attempts,
|
|
232
234
|
requestedBy: "relay-pr-completion", requestedAt: now,
|
|
233
235
|
},
|
|
234
|
-
});
|
|
236
|
+
}));
|
|
235
237
|
await patchWorkspaceMetadataAsync(workspace.id, {
|
|
236
238
|
prRefreshCommandId: command.id, prRefreshDispatchedAt: now, prRefreshPolicy: policy, prRefreshPrNumber: prNumber,
|
|
237
239
|
prRefreshKey: refreshKey, prRefreshAttempts: attempts, prRefreshError: undefined, prRefreshFailedAt: undefined,
|
package/src/workspace-rekey.ts
CHANGED
|
@@ -55,7 +55,7 @@ export function fenceWorkspaceRekeyCommand(commandId: string): Promise<{ fenced:
|
|
|
55
55
|
export async function drainStewardRekeyNotices(): Promise<void> {
|
|
56
56
|
for (const row of pendingStewardRekeyNotices()) {
|
|
57
57
|
try {
|
|
58
|
-
const routed = notifyTaskCoordinatorOfRekey(row);
|
|
58
|
+
const routed = await notifyTaskCoordinatorOfRekey(row);
|
|
59
59
|
if (routed) await getGateway().write("workspaceRekey.noticeSent", { eventId: row.id });
|
|
60
60
|
} catch (error) {
|
|
61
61
|
console.warn(`[steward-rekey] notice for task event ${row.id} failed; retrying later: ${error}`);
|
|
@@ -63,7 +63,7 @@ export async function drainStewardRekeyNotices(): Promise<void> {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
function notifyTaskCoordinatorOfRekey(row: StewardRekeyNoticeRow): boolean {
|
|
66
|
+
async function notifyTaskCoordinatorOfRekey(row: StewardRekeyNoticeRow): Promise<boolean> {
|
|
67
67
|
const task = getTaskDetail(row.task_id);
|
|
68
68
|
if (!task) return false;
|
|
69
69
|
const m = parseJson<Record<string, unknown>>(row.metadata, {});
|
|
@@ -82,7 +82,7 @@ function notifyTaskCoordinatorOfRekey(row: StewardRekeyNoticeRow): boolean {
|
|
|
82
82
|
...(rewritten.length ? [`${rewritten.length} commit(s) changed patch identity`] : []),
|
|
83
83
|
...(merges.length ? [`${merges.length} merge commit(s) were re-resolved and cannot be verified by patch-id`] : []),
|
|
84
84
|
];
|
|
85
|
-
const delivered = routeNotification({
|
|
85
|
+
const delivered = await routeNotification({
|
|
86
86
|
type: "task.steward_rekey",
|
|
87
87
|
scope: {
|
|
88
88
|
taskId: String(task.id), transition: "steward-rekey", workspaceId,
|
|
@@ -30,13 +30,13 @@ export async function recordStewardWakeFailure(workspace: WorkspaceRecord, error
|
|
|
30
30
|
const body = `Workspace \`${ws.id}\` (\`${ws.branch ?? ws.id}\` → \`${ws.baseRef ?? "base"}\`): ${error}. Relay will retry after ${Math.ceil(STEWARD_HANDOFF_WATCHDOG_MS / 60_000)} minutes. ${stewardRecoveryAdvice(ws.baseRef ?? "main", capExhausted)}`;
|
|
31
31
|
const payload = { kind: "workspace.steward-spawn-failed", workspaceId: ws.id, branch: ws.branch, reason: error };
|
|
32
32
|
if (recipients.length) {
|
|
33
|
-
routeNotification({
|
|
33
|
+
await routeNotification({
|
|
34
34
|
type: "workspace.stranded_escalation", forceDelivery: true, ttlMs: null,
|
|
35
35
|
scope: { workspaceId: ws.id, repoRoot: ws.repoRoot, author: ownerAgentId, parent: coordinatorAgentId ?? undefined },
|
|
36
36
|
recipients, message: { subject, body, payload, idempotencyKey: `steward-spawn-failed:${ws.id}:${failureId}` },
|
|
37
37
|
});
|
|
38
38
|
} else {
|
|
39
|
-
raiseOperatorAlarm({ clientId: `steward-spawn-failed:${ws.id}:${failureId}`, source: "workspace-steward-failure", subject, detail: body, dedupeEvent: true, metadata: payload });
|
|
39
|
+
(await raiseOperatorAlarm({ clientId: `steward-spawn-failed:${ws.id}:${failureId}`, source: "workspace-steward-failure", subject, detail: body, dedupeEvent: true, metadata: payload }));
|
|
40
40
|
}
|
|
41
41
|
await patchWorkspaceMetadataAsync(ws.id, { stewardWakeFailureNotifiedAt: now });
|
|
42
42
|
}
|
|
@@ -92,7 +92,7 @@ export async function wakeRepoSteward(ws: WorkspaceRecord, reason: string, opts:
|
|
|
92
92
|
stewardHandoffEscalatedAt: undefined, stewardRewakeCount: undefined,
|
|
93
93
|
} : {}),
|
|
94
94
|
});
|
|
95
|
-
routeNotification({
|
|
95
|
+
await routeNotification({
|
|
96
96
|
type: "workspace.steward_task",
|
|
97
97
|
scope: { workspaceId: ws.id, repoRoot: ws.repoRoot, author: ownerAgentId, parent: coordinatorAgentId ?? undefined },
|
|
98
98
|
recipients: [`policy:${policyName}`],
|
|
@@ -139,7 +139,7 @@ export async function wakeRepoSteward(ws: WorkspaceRecord, reason: string, opts:
|
|
|
139
139
|
}, attempt < STEWARD_WAKE_STAMP_ATTEMPTS ? current : undefined);
|
|
140
140
|
if (!stamped) continue;
|
|
141
141
|
if (current.landState === "merge-error") await transitionWorkspaceLandStateAsync(ws.id, "steward-requested");
|
|
142
|
-
notifyStewardHandoff({ workspace: ws, stewardId: policyName, coordinatorAgentId, reason });
|
|
142
|
+
await notifyStewardHandoff({ workspace: ws, stewardId: policyName, coordinatorAgentId, reason });
|
|
143
143
|
return { ok: true, policy: policyName };
|
|
144
144
|
}
|
|
145
145
|
} catch (e) {
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function e(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function t(e){if(typeof e!=`string`)return;let t=e.trim();return t.length>0?t:void 0}function n(e){return e instanceof Error?e.message:String(e)}var r=`provider-enablement`,i=`default`,a=`user`;function o(e){return`user:${e}`}var s=o(`claude-app`);function c(e){return e===`user`||typeof e==`string`&&e.startsWith(`user:`)}function ee(e){if(e===`user`)return i;if(typeof e==`string`&&e.startsWith(`user:`))return e.slice(5)||`default`}function te(e){return e===`user`||e===o(`default`)||e===`user:`?a:e}var ne=[`system`,`control`,`session`];function re(e){return ne.includes(e??``)}var ie=[`memory`,`memory-area`,`instructions`,`tools`,`comms`,`knowledge`,`context`];function ae(e){return typeof e==`string`&&ie.includes(e)}function oe(t){return e(t)&&(t.turnFinal===!0||t.final===!0)}function l(t){return e(t)&&e(t.finality)}function se(t){if(!e(t))return!1;if(l(t))return!0;let n=t.session;return e(n)&&n.final===!0&&n.turnFinal!==!0}function u(t){if(t.messageType===`final-turn`)return!0;let n=e(t.payload?.responseCapture)?t.payload.responseCapture:void 0;return oe(n)&&n.type===`response`}var d=[`decisions`,`actions`,`escalations`,`finalReports`,`failures`];Object.freeze({decisions:`all`,actions:`all`,escalations:`all`,finalReports:`all`,failures:`all`});var ce=/^[a-z][a-z0-9-]*$/,f=new Map,p=[`CLAUDE_CODE_OAUTH_TOKEN`,`ANTHROPIC_API_KEY`,`ANTHROPIC_AUTH_TOKEN`];function m(e){if(!ce.test(e.id))throw Error(`invalid provider id: ${e.id}`);if(!e.label.trim())throw Error(`provider ${e.id} is missing a label`);if(!e.icon.trim())throw Error(`provider ${e.id} is missing an icon`);if(f.has(e.id))throw Error(`provider already registered: ${e.id}`);f.set(e.id,e)}function h(e){return f.get(e)}function g(){return[...f.values()]}function le(e,t){let n=f.get(e)?.capabilityDefaults.session?.shellMode,r=t===`read-only`?n?.readOnly:n?.[t];return!!(r&&r!==`unsupported`)}function _(e){return[`open`,`guarded`,`read-only`].filter(t=>le(e,t))}var v=[`low`,`medium`,`high`,`max`],y=[`low`,`medium`,`high`,`xhigh`,`max`],b={value:2e5,source:`catalog`,confidence:`declared`},x={value:1e6,source:`catalog`,confidence:`declared`},ue={modalities:{input:{text:!0,image:!0},output:{text:!0}},tools:{code:!0,review:!0,debug:!0,refactor:!0},source:`catalog`,confidence:`declared`},S=[{name:`five_hour`,unit:`%`,reset:!0},{name:`seven_day`,unit:`%`,reset:!0}];function C(e){return{...e?{limits:e}:{},capabilities:ue}}var w={id:`claude`,credentialEnvKeys:p,label:`Claude`,icon:`🟠`,launchModes:[`interactive`,`headless`],effortSwitch:!0,launch:{managedPolicyPrompt:{alwaysOn:`append-system-prompt`},taskHydration:{channel:`append-system-prompt`}},catalog:{defaultModel:`sonnet`,models:[{alias:`haiku-5.5`,label:`Haiku 5.5`,providerModel:`claude-haiku-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`opus-5.5`,label:`Opus 5.5`,providerModel:`claude-opus-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`sonnet-5.5`,label:`Sonnet 5.5`,providerModel:`claude-sonnet-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`fable-5.1`,label:`Fable 5.1`,providerModel:`claude-fable-5-1`,efforts:y,defaultEffort:`high`,...C({contextWindowTokens:x})},{alias:`fable-5`,label:`Fable 5`,providerModel:`claude-fable-5`,efforts:y,defaultEffort:`medium`,unavailable:`suspended by export-control directive, 2026-06-12`,...C({contextWindowTokens:x})},{alias:`opus-4.8`,label:`Opus 4.8`,providerModel:`claude-opus-4-8`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:b})},{alias:`opus-4.8[1m]`,label:`Opus 4.8 1M`,providerModel:`claude-opus-4-8[1m]`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`opus-4.7`,label:`Opus 4.7`,providerModel:`claude-opus-4-7`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:b})},{alias:`opus-4.7[1m]`,label:`Opus 4.7 1M`,providerModel:`claude-opus-4-7[1m]`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`opus-4.6`,label:`Opus 4.6`,providerModel:`claude-opus-4-6`,efforts:v,defaultEffort:`medium`,...C({contextWindowTokens:b})},{alias:`opus-4.6[1m]`,label:`Opus 4.6 1M`,providerModel:`claude-opus-4-6[1m]`,efforts:v,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`sonnet-5`,label:`Sonnet 5`,providerModel:`claude-sonnet-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:b})},{alias:`sonnet-5[1m]`,label:`Sonnet 5 1M`,providerModel:`claude-sonnet-5[1m]`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`haiku`,label:`Haiku`,providerModel:`claude-haiku-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`fable`,label:`Fable`,providerModel:`claude-fable-5-1`,efforts:y,defaultEffort:`high`,...C({contextWindowTokens:x})},{alias:`opus`,label:`Opus`,providerModel:`claude-opus-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`opus[1m]`,label:`Opus 1M`,providerModel:`claude-opus-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`sonnet`,label:`Sonnet`,providerModel:`claude-sonnet-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})},{alias:`sonnet[1m]`,label:`Sonnet 1M`,providerModel:`claude-sonnet-5-5`,efforts:y,defaultEffort:`medium`,...C({contextWindowTokens:x})}]},quotaWindows:[...S],capabilityDefaults:{lifecycle:{managed:!0,shutdownHard:{when:`headless`,value:!0,otherwise:!1},restartHard:{when:`headless`,value:!0,otherwise:!1},semanticStatus:!0,reconnect:!0},session:{fileRead:!0,fileWrite:{when:`approval:not-read-only`,value:!0,otherwise:!1},shell:!0,shellMode:{open:`unrestricted`,guarded:`guarded`,readOnly:`read-only-guarded`}},context:{managed:`headless`,compact:{when:`headless`,value:!0,otherwise:!1},clear:{when:`headless`,value:!0,otherwise:!1},inject:!0,resumePreference:[`native`,`clear-inject`,`none`]},quota:{supported:!0,source:`probe`,unit:`%`,windows:[...S]},terminal:{mode:`live`,condition:`headless`,live:{read:!0,write:!0}},liveSession:{capture:!0,inject:!0,interrupt:!0,promptEcho:!0,reasoning:!0,slashCommands:!0}},slashCommands:[`/clear`,`/compact`,`/model`,`/help`],resume:{supported:!0,idFormat:`uuid-v4`,idPattern:`[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`},home:{configDir:`.claude`,envPrefix:`CLAUDE`,configDirEnvVar:`CLAUDE_CONFIG_DIR`,quotaCredentialFile:`.credentials.json`,authItems:[`.credentials.json`,`statsig`],globalInstructionFiles:[`CLAUDE.md`]},provisioning:{pluginManifestPath:`.claude-plugin/plugin.json`,bundledPlugin:{ref:`agent-relay-claude-plugin`,dir:`runner/plugins/claude`,title:`Humwick Claude plugin`,description:`Bundled Humwick Claude plugin, materialized whole through the provisioning registry.`,omitFiles:[`monitors/relay-monitor.provisioned.mjs`,`hooks/gate-run-guard.provisioned.mjs`,`hooks/kill-guard.provisioned.mjs`],fileOverrides:[{path:`monitors/relay-monitor.ts`,sourcePath:`monitors/relay-monitor.provisioned.mjs`},{path:`hooks/gate-run-guard.ts`,sourcePath:`hooks/gate-run-guard.provisioned.mjs`},{path:`hooks/kill-guard.ts`,sourcePath:`hooks/kill-guard.provisioned.mjs`}]},bundledHooks:[{ref:`agent-relay-rg-r-guard`,dir:`runner/hooks/rg-r-guard`,title:`Humwick baseline hook: rg -r guard`,description:"Baseline Humwick PreToolUse hook that blocks the ripgrep `rg -r` replace footgun.",baseline:!0},{ref:`agent-relay-fff-search-redirect`,dir:`runner/hooks/fff-search-redirect`,title:`Humwick fff search redirect`,description:`Redirects standalone repository searches to fff for Claude profiles with a configured fff MCP server.`,omitFiles:[`fff-search-redirect.test.ts`]},{ref:`agent-relay-web-tools-redirect`,dir:`runner/hooks/web-tools-redirect`,title:`Humwick web tools redirect`,description:`Redirects built-in WebSearch/WebFetch to the profile's Relay web_search and local-first page reader tools (#3024).`,omitFiles:[`web-tools-redirect.test.ts`]}]},upgrade:{packages:[`agent-relay-runner`,`agent-relay-plugin`],detectPackages:[`agent-relay-runner`],detectCommands:[`claude`]},harness:{upgrade:{strategy:`self-update`,args:[`update`]}},probe:{command:`claude`,args:[`--version`],healthCheck:`claude --version`,featureChecks:[{name:`rig`,command:`claude-rig`,homeDir:`.claude-rig`}],authCheck:{command:`claude`,args:[`auth`,`status`,`--json`],loginArgs:[`auth`,`login`]}},quotaPoll:{strategy:`none`},shim:{kind:`claude-relay`},mcpToolManifest:{clientNativeToolDeferral:!0,runnerManagedToolDeferral:!1}};m(w),m({...w,id:`claude-b`,label:`Claude B`,home:{...w.home,configDir:`.claude-b`,dedicatedHome:!0}}),m({...w,id:`claude-api`,label:`Claude API`,automaticFamilyRouting:!1,defaultEnabled:!1,resume:{supported:!1},credentialEnvKeys:[`ANTHROPIC_API_KEY`],apiAuth:{keyPrefix:`sk-ant-`,keyEnvVar:`ANTHROPIC_API_KEY`,defaultKeyFile:`~/.config/agent-relay/secrets/anthropic-api.key`,unsetEnvKeys:[...p,`ANTHROPIC_BASE_URL`,`CLAUDE_CODE_USE_BEDROCK`,`CLAUDE_CODE_USE_VERTEX`,`CLAUDE_CODE_USE_FOUNDRY`,`ANTHROPIC_CUSTOM_HEADERS`,`CLAUDE_CODE_API_KEY_HELPER_TTL_MS`]},home:{...w.home,configDir:`.claude-api`,sourceEnvVar:`CLAUDE_API_CONFIG_DIR`,dedicatedHome:!0,authItems:[]},launchModes:void 0,quotaWindows:[],capabilityDefaults:{...w.capabilityDefaults,quota:{supported:!1,source:`runtime`,unit:`USD`,windows:[]}}});var T=[`low`,`medium`,`high`,`xhigh`],E={value:2e5,source:`catalog`,confidence:`declared`},D={value:5e5,source:`catalog`,confidence:`declared`},de={modalities:{input:{text:!0,image:!0},output:{text:!0}},tools:{code:!0,review:!0,debug:!0,refactor:!0},source:`catalog`,confidence:`declared`},O=[{name:`primary`,unit:`%`,reset:!0},{name:`secondary`,unit:`%`,reset:!0}];function k(e){return{...e?{limits:e}:{},capabilities:de}}m({id:`codex`,credentialEnvKeys:[`OPENAI_API_KEY`],label:`Codex`,icon:`⌨️`,launchModes:[`interactive`,`headless`],launch:{secretEnvRequiresManagedHome:!0,managedPolicyPrompt:{alwaysOn:`prompt`},taskHydration:{channel:`prompt`}},catalog:{defaultModel:`sol`,models:[{alias:`sol`,label:`GPT-6.1 Sol`,providerModel:`gpt-6.1-sol`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:D})},{alias:`luna`,label:`GPT-6 Luna`,providerModel:`gpt-6-luna`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-6-sol`,label:`GPT-6 Sol`,providerModel:`gpt-6-sol`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-6.1-sol`,label:`GPT-6.1 Sol`,providerModel:`gpt-6.1-sol`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:D})},{alias:`gpt-6-luna`,label:`GPT-6 Luna`,providerModel:`gpt-6-luna`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.6-terra`,label:`GPT-5.6 Terra`,providerModel:`gpt-5.6-terra`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.5`,label:`GPT-5.5`,providerModel:`gpt-5.5`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.4`,label:`GPT-5.4`,providerModel:`gpt-5.4`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.4-mini`,label:`GPT-5.4 Mini`,providerModel:`gpt-5.4-mini`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.3-codex`,label:`GPT-5.3 Codex`,providerModel:`gpt-5.3-codex`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})},{alias:`gpt-5.3-codex-spark`,label:`GPT-5.3 Codex Spark`,providerModel:`gpt-5.3-codex-spark`,efforts:T,defaultEffort:`high`,...k({contextWindowTokens:E})},{alias:`gpt-5.2`,label:`GPT-5.2`,providerModel:`gpt-5.2`,efforts:T,defaultEffort:`medium`,...k({contextWindowTokens:E})}]},quotaWindows:[...O],capabilityDefaults:{lifecycle:{managed:!0,shutdownHard:!0,restartHard:!0,semanticStatus:!0,reconnect:!0},session:{fileRead:!0,fileWrite:{when:`approval:not-read-only`,value:!0,otherwise:!1},shell:{when:`approval:not-read-only`,value:!0,otherwise:!1},shellMode:{open:`unrestricted`,guarded:`guarded`,readOnly:`none`}},context:{managed:`always`,compact:!0,clear:!0,inject:!0,resumePreference:[`native`,`clear-inject`,`none`]},quota:{supported:!0,source:`probe`,unit:`%`,windows:[...O]},terminal:{mode:`attach`,attach:{create:!0,read:!0,write:!0,detach:!0}},liveSession:{capture:!0,inject:!0,interrupt:!0,promptEcho:!0,reasoning:!0,slashCommands:!0}},slashCommands:[`/compact`,`/new`],resume:{supported:!0,idFormat:`codex-thread-id`,idPattern:`[\\w-]+`},home:{configDir:`.codex`,envPrefix:`CODEX`,configDirEnvVar:`CODEX_HOME`,quotaCredentialFile:`auth.json`,authItems:[`auth.json`,`installation_id`],globalInstructionFiles:[`AGENTS.md`]},provisioning:{pluginManifestPath:`.codex-plugin/plugin.json`,bundledSkills:{refPrefix:`agent-relay-codex-`,dir:`runner/plugins/codex/skills`,titlePrefix:`Humwick Codex skill: `,description:`Bundled Humwick Codex skill, materialized through the provisioning registry.`,entryFile:`SKILL.md`},bundledHooks:[{ref:`agent-relay-rg-r-guard`,dir:`runner/hooks/rg-r-guard`,title:`Humwick baseline hook: rg -r guard`,description:"Baseline Humwick PreToolUse hook that blocks the ripgrep `rg -r` replace footgun.",baseline:!0}]},upgrade:{packages:[`agent-relay-runner`,`agent-relay-codex`],detectPackages:[`agent-relay-runner`,`agent-relay-codex`],detectCommands:[`codex-relay`,`agent-relay-runner`]},harness:{upgrade:{strategy:`self-update`,args:[`update`]}},probe:{command:`codex`,args:[`--version`],healthCheck:`codex --version`,authCheck:{command:`codex`,args:[`login`,`status`],loginArgs:[`login`]}},quotaPoll:{strategy:`codex-app-server`},resetCredits:{supported:!0},shim:{kind:`codex-relay`,extraBinPaths:[`codex/bin/codex`],cleanLegacyHooks:!0},mcpToolManifest:{clientNativeToolDeferral:!1,runnerManagedToolDeferral:!0,runnerManagedToolDeferralRoute:`meta-only-callmux`}});var A={mode:`attach`,attach:{create:!0,read:!0,write:!0,detach:!0}},j=`opencode-ai@latest`;m({id:`opencode`,label:`OpenCode`,icon:`⚡`,launch:{managedPolicyPrompt:{alwaysOn:`prompt`},taskHydration:{channel:`prompt`}},catalog:{defaultModel:`muse-spark`,models:[{alias:`muse-spark`,label:`Muse Spark 1.3 Contributor`,providerModel:`meta/muse-spark-1.3-contributor`,efforts:[],limits:{contextWindowTokens:{value:1048576,source:`catalog`,confidence:`declared`},maxOutputTokens:{value:943718,source:`catalog`,confidence:`declared`}},capabilities:{modalities:{input:{text:!0},output:{text:!0}},tools:{code:!0,shell:!0,fileRead:!0,fileWrite:!0},source:`provider`,confidence:`estimated`}},{alias:`openai/gpt-6.1-sol`,label:`GPT-6.1 Sol · OpenAI API`,providerModel:`openai/gpt-6.1-sol`,efforts:[],limits:{contextWindowTokens:{value:272e3,source:`catalog`,confidence:`declared`},maxOutputTokens:{value:128e3,source:`catalog`,confidence:`declared`}}}]},quotaWindows:[],capabilityDefaults:{lifecycle:{managed:!0,shutdownHard:!0,restartHard:!0,semanticStatus:!0,reconnect:!0},session:{fileRead:!0,fileWrite:!0,shell:!0,shellMode:{open:`unrestricted`,guarded:`unsupported`,readOnly:`unsupported`}},context:{managed:`always`,compact:!0,clear:!0,inject:!0,resumePreference:[`native`,`clear-inject`,`none`]},quota:{supported:!1,source:`runtime`,unit:`%`,windows:[]},terminal:A,liveSession:{capture:!0,inject:!0,interrupt:!0,promptEcho:!0,reasoning:!1,slashCommands:!1}},resume:{supported:!1},home:{configDir:`.config/opencode`,envPrefix:`OPENCODE`},opencode:{opencodeProviderID:`openrouter`,apiKeyEnvVar:`OPENROUTER_API_KEY`},upgrade:{packages:[`agent-relay-runner`],externalPackages:[j],detectPackages:[`opencode-ai`],detectCommands:[`opencode`]},harness:{upgrade:{strategy:`external-packages`}},probe:{command:`opencode`,args:[`--version`],healthCheck:`opencode --version`},shim:{kind:`opencode-relay`},quotaPoll:{strategy:`none`},mcpToolManifest:{clientNativeToolDeferral:!1,runnerManagedToolDeferral:!1}});var M=[{name:`rolling`,unit:`%`,reset:!0,description:`Rolling 5-hour usage window`},{name:`weekly`,unit:`%`,reset:!0,description:`Weekly usage window`},{name:`monthly`,unit:`%`,reset:!0,description:`Monthly usage window (display-only)`}],fe={modalities:{input:{text:!0},output:{text:!0}},tools:{code:!0,shell:!0,fileRead:!0,fileWrite:!0},source:`provider`,confidence:`estimated`};function N(e,t){return{alias:e,label:t,providerModel:e,efforts:[],capabilities:fe}}m({id:`opencode-go`,label:`OpenCode Go`,icon:`⚡`,defaultEnabled:!1,launch:{managedPolicyPrompt:{alwaysOn:`prompt`},taskHydration:{channel:`prompt`}},catalog:{defaultModel:`glm-5.3-flash`,models:[N(`claude-haiku-5-5`,`Claude Haiku 5.5`),N(`deepseek-v4-pro`,`DeepSeek V4 Pro`),N(`deepseek-v4.1-flash`,`DeepSeek V4.1 Flash`),N(`gemini-4-argon-contributor`,`Gemini 4 Argon Contributor`),N(`glm-5.2`,`GLM-5.2`),N(`glm-5.3`,`GLM-5.3`),N(`glm-5.3-flash`,`GLM-5.3 Flash`),N(`gpt-5.6-luna`,`GPT-5.6 Luna`),N(`gpt-6-luna`,`GPT-6 Luna`),N(`grok-4.6`,`Grok 4.6`),N(`grok-4.7`,`Grok 4.7`),N(`hy3`,`Hy3`),N(`hy4-preview`,`Hy4 Preview`),N(`kimi-k2.7-code`,`Kimi K2.7 Code`),N(`kimi-k3`,`Kimi K3`),N(`longcat-2.0`,`LongCat 2.0`),N(`mimo-v2.5`,`MiMo V2.5`),N(`mimo-v2.5-pro`,`MiMo V2.5 Pro`),N(`mimo-v2.6-flash`,`MiMo V2.6 Flash`),N(`mimo-v2.6-pro`,`MiMo V2.6 Pro`),N(`minimax-m2.7`,`MiniMax M2.7`),N(`minimax-m3`,`MiniMax M3`),N(`muse-spark-1.2-contributor`,`Muse Spark 1.2 Contributor`),N(`muse-spark-1.3-contributor`,`Muse Spark 1.3 Contributor`),N(`qwen3.7-plus`,`Qwen3.7 Plus`),N(`qwen3.8-flash`,`Qwen3.8 Flash`),N(`qwen3.8-max`,`Qwen3.8 Max`),N(`space-bunny`,`Space Bunny`)]},quotaWindows:[...M],capabilityDefaults:{lifecycle:{managed:!0,shutdownHard:!0,restartHard:!0,semanticStatus:!0,reconnect:!0},session:{fileRead:!0,fileWrite:!0,shell:!0,shellMode:{open:`unrestricted`,guarded:`unsupported`,readOnly:`unsupported`}},context:{managed:`always`,compact:!0,clear:!0,inject:!0,resumePreference:[`native`,`clear-inject`,`none`]},quota:{supported:!0,source:`runtime`,unit:`%`,windows:[...M]},terminal:A,liveSession:{capture:!0,inject:!0,interrupt:!0,promptEcho:!0,reasoning:!1,slashCommands:!1}},resume:{supported:!1},home:{configDir:`.local/share/opencode`,envPrefix:`OPENCODE_GO`,quotaCredentialFile:`auth.json`},opencode:{opencodeProviderID:`opencode-go`,apiKeyEnvVar:`OPENCODE_API_KEY`,hostAuth:!0},upgrade:{packages:[`agent-relay-runner`],externalPackages:[j],detectPackages:[`opencode-ai`],detectCommands:[`opencode`]},harness:{upgrade:{strategy:`external-packages`}},probe:{command:`opencode`,args:[`--version`],healthCheck:`opencode --version`},shim:{kind:`opencode-relay`},quotaPoll:{strategy:`opencode-go`},quotaAlsoWith:`opencode`,mcpToolManifest:{clientNativeToolDeferral:!1,runnerManagedToolDeferral:!1}});var P={value:1e6,source:`catalog`,confidence:`declared`},F={value:131072,source:`catalog`,confidence:`declared`},pe={modalities:{input:{text:!0},output:{text:!0}},tools:{code:!0,shell:!0,fileRead:!0,fileWrite:!0},source:`provider`,confidence:`declared`},me={modalities:{input:{text:!0,image:!0},output:{text:!0}},tools:{code:!0,shell:!0,fileRead:!0,fileWrite:!0},source:`provider`,confidence:`declared`},I=[{name:`five_hour`,unit:`%`,reset:!0,description:`Rolling 5-hour credit window`},{name:`seven_day`,unit:`%`,reset:!0,description:`Weekly credits, reset from the subscription timestamp`}];m({id:`zai`,label:`z.ai`,icon:`🟣`,launch:{managedPolicyPrompt:{alwaysOn:`prompt`},taskHydration:{channel:`prompt`}},catalog:{defaultModel:`glm-5.3-flash`,models:[{alias:`glm-5.3`,label:`GLM-5.3`,providerModel:`glm-5.3`,efforts:[],limits:{contextWindowTokens:P,maxOutputTokens:F},capabilities:pe},{alias:`glm-5.3-flash`,label:`GLM-5.3 Flash`,providerModel:`glm-5.3-flash`,efforts:[],limits:{contextWindowTokens:P,maxOutputTokens:F},capabilities:me}]},quotaWindows:[...I],capabilityDefaults:{lifecycle:{managed:!0,shutdownHard:!0,restartHard:!0,semanticStatus:!0,reconnect:!0},session:{fileRead:!0,fileWrite:!0,shell:!0,shellMode:{open:`unrestricted`,guarded:`unsupported`,readOnly:`unsupported`}},context:{managed:`always`,compact:!0,clear:!0,inject:!0,resumePreference:[`native`,`clear-inject`,`none`]},quota:{supported:!0,source:`runtime`,unit:`%`,windows:[...I]},terminal:A,liveSession:{capture:!0,inject:!0,interrupt:!0,promptEcho:!0,reasoning:!1,slashCommands:!1}},resume:{supported:!1},home:{configDir:`.config/opencode`,envPrefix:`ZAI`,quotaCredentialFile:`auth.json`},opencode:{opencodeProviderID:`zai`,baseURL:`https://api.z.ai/api/coding/paas/v4`,npm:`@ai-sdk/openai-compatible`,apiKeyEnvVar:`ZAI_API_KEY`},upgrade:{packages:[`agent-relay-runner`],externalPackages:[j],detectPackages:[`opencode-ai`],detectCommands:[`opencode`]},harness:{upgrade:{strategy:`external-packages`}},probe:{command:`opencode`,args:[`--version`],healthCheck:`opencode --version`},shim:{kind:`opencode-relay`},quotaPoll:{strategy:`zai`},mcpToolManifest:{clientNativeToolDeferral:!1,runnerManagedToolDeferral:!1}}),Object.freeze({codex:{"gpt-5.6-terra":`sol`,"gpt-5.6-sol":`sol`,"gpt-6-sol":`sol`,"gpt-6.1-sol":`sol`,"gpt-5.6-luna":`luna`,"gpt-6-luna":`luna`},claude:{"opus-4.8":`opus`,"sonnet-5":`sonnet`,"fable-5":`fable`},"claude-b":{"opus-4.8":`opus`,"sonnet-5":`sonnet`,"fable-5":`fable`}});var L={opencode:{envVar:`OPENCODE_API_KEY`},"opencode-go":{envVar:`OPENCODE_API_KEY`},anthropic:{envVar:`ANTHROPIC_API_KEY`},openai:{envVar:`OPENAI_API_KEY`},openrouter:{envVar:`OPENROUTER_API_KEY`},google:{envVar:`GOOGLE_GENERATIVE_AI_API_KEY`},mistral:{envVar:`MISTRAL_API_KEY`},deepseek:{envVar:`DEEPSEEK_API_KEY`},xai:{envVar:`XAI_API_KEY`},groq:{envVar:`GROQ_API_KEY`},azure:{envVar:`AZURE_API_KEY`},moonshotai:{envVar:`MOONSHOT_API_KEY`},cerebras:{envVar:`CEREBRAS_API_KEY`},cohere:{envVar:`COHERE_API_KEY`},"fireworks-ai":{envVar:`FIREWORKS_API_KEY`},togetherai:{envVar:`TOGETHER_API_KEY`},chutes:{envVar:`CHUTES_API_KEY`},zai:{envVar:`ZAI_API_KEY`,custom:!0}},R=class extends Error{candidates;constructor(e,t){super(e),this.candidates=t,this.name=`OpenCodeModelResolutionError`}},z=8;function B(e,t){let n=e.indexOf(`/`);return n<=0?{backendID:t,modelID:e,qualified:`${t}/${e}`}:{backendID:e.slice(0,n),modelID:e.slice(n+1),qualified:e}}function he(e,t,n){let r=e.trim();if(!r)throw new R(`OpenCode model id is empty.`,[]);let i=r.indexOf(`/`),a=i>0?r.slice(0,i):void 0;if(!n)return a&&(a===t||L[a]!==void 0)?B(r,t):{backendID:t,modelID:r,qualified:`${t}/${r}`};if(n.models.has(r))return B(r,t);if(n.models.has(`${t}/${r}`))return{backendID:t,modelID:r,qualified:`${t}/${r}`};if(a&&n.providers.has(a))return B(r,t);if(!a){let e=[...n.models].filter(e=>e.slice(e.indexOf(`/`)+1)===r);if(e.length===1)return B(e[0],t);if(e.length>1){let t=e.sort().slice(0,z);throw new R(`OpenCode model "${r}" is ambiguous on this host (${n.source} registry); qualify it as one of: ${t.join(`, `)}.`,t)}}let o=ge(r,n),s=o.length?` Did you mean: ${o.join(`, `)}?`:``;throw new R(`OpenCode model "${r}" is not available on this host (${n.source} registry: backend "${a??t}" is not a known opencode provider and no listed model matches).${s}`,o)}function ge(e,t){let n=e.slice(e.lastIndexOf(`/`)+1).toLowerCase();if(!n)return[];let r=[],i=[];for(let e of t.models){let t=e.slice(e.lastIndexOf(`/`)+1).toLowerCase();t===n?r.push(e):t.includes(n)&&i.push(e)}return[...r.sort(),...i.sort()].slice(0,z)}var _e=[`off`,`quiet`,`normal`,`verbose`];g().map(e=>e.id);var V=[`narration`,`tools`,`reasoning`,`memories`,`startup`,`injected`,`agentMessages`,`workflow`,`land`,`task`,`agents`,`other`,`undelivered`],ve=[`workflow`,`land`,`task`,`agents`,`other`];function H(e){return Object.fromEntries(V.map(t=>[t,e(t)]))}var U=H(e=>ve.includes(e)),W={calm:U,everything:H(()=>!0)};function ye(e){let t=e&&typeof e==`object`&&!Array.isArray(e)?e:{};return H(e=>typeof t[e]==`boolean`?t[e]:U[e])}function be(e){for(let[t,n]of Object.entries(W))if(V.every(t=>n[t]===e[t]))return t;return null}function xe(e,t){let n=e?.opencodeProviderID,r=t?.trim();if(!(!n||!r))return he(r,n).qualified}function Se(e){return!e?.disabled}var Ce=.1,we=.9,G=.8,K=.4,q=256e3,J=1e6;function Te(){return g().map(e=>({provider:e.id,label:e.label,models:[],...e.opencode?.opencodeProviderID?{opencodeProviderID:e.opencode.opencodeProviderID}:{},...e.launchModes?.length?{launchModes:[...e.launchModes]}:{},...e.effortSwitch?{effortSwitch:!0}:{}}))}function Ee(e){let t=De(e);return{selfCompactUtilization:t,warnUtilization:Oe(t),hardBackstopUtilization:Math.max(we,t)}}function De(e){return!Number.isFinite(e)||!e||e<=q?G:e>=J?K:Y(G-(e-q)/(J-q)*(G-K))}function Oe(e){return Y(Math.max(0,e-Ce))}function Y(e){return Math.round(e*1e3)/1e3}function X(e,t){if(e)return(t??Te()).find(t=>t.provider===e)}function ke(e,t,n={}){let r=(Array.isArray(t)?t:t?[t]:[]).map(e=>e.trim()).filter(Boolean);if(r.length){for(let t of r){let i=Ae(e,t,n.requireUnambiguous),a=je(e,i,r,n.observedWindowTokens);if(a)return a;if(i)return i}if(!(n.requireUnambiguous||n.exactOnly))for(let t of r){let n=e.models.find(e=>e.alias.startsWith(t+`-`));if(n)return n}}}function Ae(e,t,n=!1){let r=t.toLowerCase(),i=e.models.find(e=>e.alias===t)??e.models.find(e=>e.alias.toLowerCase()===r);if(i)return i;let a=e.models.filter(e=>e.providerModel.toLowerCase()===r);if(a.length>1&&n)throw Error(`ambiguous ${e.provider} provider model: ${t} (select an alias: ${a.map(e=>e.alias).join(`, `)})`);return a[0]}function je(e,t,n,r){if(!Number.isFinite(r)||!r)return;if(t?.limits?.contextWindowTokens?.value===r)return t;let i=new Set([...t?[t.alias,t.providerModel]:[],...n].map(Z));return e.models.find(e=>e.limits?.contextWindowTokens?.value===r&&(i.has(Z(e.alias))||i.has(Z(e.providerModel))))}function Z(e){return e.trim().toLowerCase().replace(/\[[^\]]+\]$/,``)}function Me(e){return!e.disabled&&!e.unavailable}function Ne(e){let t=e.defaultModel,n=t?e.models.find(e=>e.alias===t):void 0;return n&&Me(n)?{alias:n.alias,preferred:t,fellBack:!1}:{alias:void 0,preferred:t,fellBack:!0}}function Pe(e){return h(e)?.resetCredits?.supported===!0}var Q=[`bg-tone-warning/10 text-tone-warning-fg border-tone-warning/30`,`bg-tone-sky/10 text-tone-sky-fg border-tone-sky/30`,`bg-tone-violet/10 text-tone-violet-fg border-tone-violet/30`,`bg-tone-success/10 text-tone-success-fg border-tone-success/30`,`bg-tone-rose/10 text-tone-rose-fg border-tone-rose/30`];function Fe(e){let t=0;for(let n=0;n<e.length;n++)t=t*31+e.charCodeAt(n)>>>0;return t}var $=new Map(g().map((e,t)=>[e.id,Q[t%Q.length]]));function Ie(e){return e?h(e)?.label??e.charAt(0).toUpperCase()+e.slice(1):`Unknown provider`}function Le(e){let t=$.get(e);if(t)return t;let n=Q[Fe(e)%Q.length];return $.set(e,n),n}function Re(){return g().map(e=>e.id)}function ze(e){return h(e)}function Be(e,t){let n=e?.id||e?.alias;if(!e||!n)return;let r=X(e.provider,t),i=r?ke(r,[e.alias||``,n]):void 0;return{label:i?.label||n,...i?{entry:i}:{}}}export{o as A,se as C,te as D,a as E,n as M,e as N,c as O,t as P,ae as S,i as T,_,Pe as a,u as b,X as c,Ne as d,U as f,_e as g,ye as h,ze as i,r as j,ee as k,Se as l,be as m,Le as n,Be as o,W as p,Ie as r,Ee as s,Re as t,xe as u,d as v,s as w,re as x,l as y};
|
|
2
|
-
//# sourceMappingURL=provider-display-DsuWMvVL.js.map
|