@humwick/server 0.130.2 → 0.130.4
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 +175 -4
- package/package.json +8 -7
- package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-BOkmEvgZ.js} +2 -2
- package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-BkaDJp0r.js} +2 -2
- package/public/assets/{TraceView-Wimm0Czv.js → TraceView-B99Uu2yT.js} +2 -2
- package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DUIfTTFF.js} +2 -2
- package/public/assets/{activity-CrSurn-r.js → activity-ZIX0N1El.js} +2 -2
- package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-kq9TPYFw.js} +2 -2
- package/public/assets/agent-liveness-DSQY1Aa_.js +2 -0
- package/public/assets/{agent-name-DKbiIhBo.js → agent-name-C_7F4DFR.js} +2 -2
- package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-BNOcrGcY.js} +2 -2
- package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-B6yAh70a.js} +2 -2
- package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-CcrhmOzF.js} +2 -2
- package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CXSLrKiq.js} +2 -2
- package/public/assets/{agents-B-v66C-4.js → agents-DIZG97_X.js} +2 -2
- package/public/assets/{analytics-BqCb-LKi.js → analytics-rasmoPjR.js} +2 -2
- package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-tBpTrEPb.js} +2 -2
- package/public/assets/{artifacts-DJevXcvg.js → artifacts-BNkrynP1.js} +2 -2
- package/public/assets/{artifacts-D32zyw4Y.js → artifacts-Bjq-ZyBA.js} +2 -2
- package/public/assets/{automation-BpRajx_5.js → automation-Cx422L3L.js} +2 -2
- package/public/assets/{backlog-D_UjTdzX.js → backlog-RuFQ8PUu.js} +2 -2
- package/public/assets/{busy-health-N3VEh4ao.js → busy-health-BvNQ9g5x.js} +2 -2
- package/public/assets/{channels-9jopungq.js → channels-DNbKAS0I.js} +2 -2
- package/public/assets/{chat-CSXrTB3C.js → chat-Bp3Fx73h.js} +3 -3
- package/public/assets/{code-preview-p1NnmqK0.js → code-preview-KIRZA6cz.js} +2 -2
- package/public/assets/{connectors-CZdqlDNL.js → connectors-k7vO4vvc.js} +2 -2
- package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BuVoq1aw.js} +2 -2
- package/public/assets/{crate-agent-30aXTKva.js → crate-agent-irqlt4NH.js} +2 -2
- package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-D_rurNBz.js} +2 -2
- package/public/assets/{deploys-DoN6bAb5.js → deploys-yzZqIpxE.js} +2 -2
- package/public/assets/{display-BrKWFGJz.js → display-BemJG1f_.js} +2 -2
- package/public/assets/{files-D6XEu8Ng.js → files-DXWcrxOz.js} +2 -2
- package/public/assets/{fleet-C7jQWbw2.js → fleet-TEuOCZXE.js} +2 -2
- package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BGoDAFI-.js} +2 -2
- package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-BB9eq9nN.js} +2 -2
- package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-qy2nTD_1.js} +3 -3
- package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-BGPHxuwT.js} +2 -2
- package/public/assets/{index-CRHep3M9.js → index-BC5XZc0z.js} +5 -5
- package/public/assets/{index-MYAIwYTX.css → index-D8Rp9pz2.css} +1 -1
- package/public/assets/{insights-CzrtkpOE.js → insights-C-KQG0h-.js} +2 -2
- package/public/assets/{integrations-aVsUmigt.js → integrations-ClPRPyKU.js} +2 -2
- package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-DbH8J9Ak.js} +2 -2
- package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-PH4zVn24.js} +2 -2
- package/public/assets/{maintenance-NfjqFZAk.js → maintenance-5lV43uTL.js} +2 -2
- package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-BdgU35aX.js} +2 -2
- package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-DNT4OUwQ.js} +3 -3
- package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CnCcPy0A.js} +2 -2
- package/public/assets/{memory-DNsCl6UX.js → memory--GgWH1gH.js} +2 -2
- package/public/assets/{messages-DopU1L1X.js → messages-CzFl_97O.js} +2 -2
- package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-CVvJVkzv.js} +2 -2
- package/public/assets/overview-DsrZvE86.js +2 -0
- package/public/assets/{pairs-DE_m6rrE.js → pairs-D2d0d2py.js} +2 -2
- package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-_SMuSbYF.js} +2 -2
- package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-Apn15y43.js} +2 -2
- package/public/assets/{projects-Br2Bd2h1.js → projects-D3B6kto5.js} +2 -2
- package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-DnPB6Ez6.js} +2 -2
- package/public/assets/provider-display-bWwiuedV.js +2 -0
- package/public/assets/{registry-Cw38_6gW.js → registry-D790cIhN.js} +2 -2
- package/public/assets/run-card-BCro-Odj.js +2 -0
- package/public/assets/{secrets-DxI-vzSq.js → secrets-CVXvfvbU.js} +2 -2
- package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-D3Xxqb9w.js} +2 -2
- package/public/assets/{settings-CKZTVGIx.js → settings-CoUC7Jci.js} +2 -2
- package/public/assets/shipping-D_Lp9n_J.js +2 -0
- package/public/assets/{stats-DyUBKyWI.js → stats-CXiNjB9S.js} +2 -2
- package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-C703YIy1.js} +2 -2
- package/public/assets/store-BgDALGIX.js +9 -0
- package/public/assets/{tasks-Bh7Chr4-.js → tasks-DO0WpJCx.js} +2 -2
- package/public/assets/{teams-bowI7qVY.js → teams-FGkdi_tL.js} +2 -2
- package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-Dh8dSC7e.js} +3 -3
- package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-B5Zriip3.js} +2 -2
- package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-CRUVDvLC.js} +2 -2
- package/public/assets/{use-decisions-samMQhQf.js → use-decisions-CoaqRh4l.js} +2 -2
- package/public/assets/{use-project-list-59LheVP7.js → use-project-list-X-BgT53X.js} +2 -2
- package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-0X_UZkk-.js} +2 -2
- package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-CkLhVBGu.js} +2 -2
- package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-BkTi7eim.js} +2 -2
- package/public/assets/{work-queue-CSvpuNLz.js → work-queue-DDOLEyKo.js} +2 -2
- package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-CzOsB8BM.js} +2 -2
- package/public/assets/{workflows-DdmxRSyg.js → workflows-DJilvmRM.js} +2 -2
- package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CHcfbLR3.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +29 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/src/adapters/claude-api.ts +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 +3 -2
- 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/login-link.ts +35 -0
- 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/index.ts +7 -1
- package/src/cli/init.ts +53 -0
- package/src/cli/orchestrator.ts +1 -7
- package/src/cli/setup.ts +6 -4
- 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 +3 -12
- 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/workflow-execution.ts +3 -3
- 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 +12 -16
- 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/init.ts +299 -0
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/invite-link.ts +16 -9
- 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 +44 -17
- 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-providers.ts +18 -0
- 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 +7 -3
- 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 +3 -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 +4 -5
- package/src/routes/secrets-import.ts +3 -4
- package/src/routes/secrets-vault.ts +12 -14
- 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-install.ts +30 -0
- 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 +25 -26
- 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/auth-context.ts +6 -0
- 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-api-key.ts +73 -0
- 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/setup.ts +47 -8
- 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/utils.ts +7 -0
- 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/overview-C1DCTzzV.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
package/src/self-resume.ts
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
|
+
import { updateContinuationObjectiveAsync, markSelfResumeContinuationIngestedAsync, ensureContinuationEnvelopeAsync } from "./db/runtime-tail-async";
|
|
2
|
+
import { sendMessageAsync } from "./db/message-send";
|
|
3
|
+
import { createCommandAsync } from "./commands-write";
|
|
1
4
|
import { renderSelfCareState } from "./services/self-care-state";
|
|
2
5
|
import { agentPrincipalSink } from "./db/agent-ownership";
|
|
3
6
|
import { isRecord } from "@humwick/sdk";
|
|
4
|
-
import {
|
|
7
|
+
import { listCommands, listInjectionAttempts, listPendingInjectionAttemptIds } from "./commands-db";
|
|
5
8
|
import type { InjectionAttempt } from "./db/injection-attempts";
|
|
6
9
|
import { emitCommandEvent } from "./command-events";
|
|
7
10
|
import { INJECTION_SWEEP_BACKLOG_INTERVAL_MS, pacedInjectionSweep } from "./injection-sweep-pacing";
|
|
8
11
|
import { MAX_BODY_BYTES, REAP_INTERVAL_MS } from "./config";
|
|
9
12
|
import { getSelfResumeConfig } from "./config-store";
|
|
10
|
-
import {
|
|
11
|
-
archiveAndAdvanceContinuationAsync,
|
|
12
|
-
archiveContinuationSegmentAsync,
|
|
13
|
-
ensureContinuationEnvelope,
|
|
14
|
-
findMessageByIdempotencyKey,
|
|
15
|
-
getAgent,
|
|
16
|
-
getContinuationEnvelope,
|
|
17
|
-
getMessage,
|
|
18
|
-
listUncommandedContextResets,
|
|
19
|
-
markSelfResumeContinuationIngested,
|
|
20
|
-
selfResumeContinuationIngested,
|
|
21
|
-
sendMessage,
|
|
22
|
-
updateContinuationAfterCompact,
|
|
23
|
-
updateContinuationObjective,
|
|
24
|
-
ValidationError,
|
|
25
|
-
} from "./db";
|
|
13
|
+
import { archiveAndAdvanceContinuationAsync, archiveContinuationSegmentAsync, findMessageByIdempotencyKey, getAgent, getContinuationEnvelope, getMessage, listUncommandedContextResets, selfResumeContinuationIngested, updateContinuationAfterCompact, ValidationError } from "./db";
|
|
26
14
|
import { emitRelayEvent } from "./events";
|
|
27
15
|
import { emitMessageDeliveryUpdated } from "./sse";
|
|
28
16
|
import { boundaryCaptureClause } from "./memory-boundary-capture";
|
|
@@ -73,13 +61,13 @@ export async function compactAndResume(input: CompactAndResumeInput): Promise<Co
|
|
|
73
61
|
else assertResumeSupported(agent, mode);
|
|
74
62
|
|
|
75
63
|
const now = Date.now();
|
|
76
|
-
let envelope =
|
|
64
|
+
let envelope = (await ensureContinuationEnvelopeAsync({
|
|
77
65
|
agentId: agent.id,
|
|
78
66
|
objective: input.objective,
|
|
79
67
|
now,
|
|
80
|
-
});
|
|
68
|
+
}));
|
|
81
69
|
if (input.objective !== undefined && envelope.objective !== input.objective) {
|
|
82
|
-
envelope =
|
|
70
|
+
envelope = (await updateContinuationObjectiveAsync({ agentId: agent.id, objective: input.objective, now }));
|
|
83
71
|
}
|
|
84
72
|
|
|
85
73
|
const workingState = input.workingState.trim();
|
|
@@ -101,19 +89,19 @@ export async function compactAndResume(input: CompactAndResumeInput): Promise<Co
|
|
|
101
89
|
// half is elsewhere on purpose (src/context-advisory.ts) — it has to reach the agent while the
|
|
102
90
|
// generation it asks about still exists, and no line written at this point can do that.
|
|
103
91
|
const fullContinuation = renderContinuation(updated.envelope, {
|
|
104
|
-
memoryCapture: boundaryCaptureClause({ seam: "post", agentId: agent.id, now }),
|
|
92
|
+
memoryCapture: (await boundaryCaptureClause({ seam: "post", agentId: agent.id, now })),
|
|
105
93
|
liveRuns: renderSelfCareState(agent.id),
|
|
106
94
|
});
|
|
107
95
|
// #2836: no core copy here — the startup-context seam re-injects it beside this.
|
|
108
|
-
const continuationMessage = createContinuationRecoveryMessage(agent.id, generation, fullContinuation, now);
|
|
96
|
+
const continuationMessage = (await createContinuationRecoveryMessage(agent.id, generation, fullContinuation, now));
|
|
109
97
|
const continuation = insertRecoveryPointerAfterIntro(fullContinuation, continuationMessage.id);
|
|
110
|
-
openContextRecovery(agent.id, generation, now);
|
|
98
|
+
(await openContextRecovery(agent.id, generation, now));
|
|
111
99
|
const command = input.restart
|
|
112
100
|
? await createSelfRestartCommandAsync(agent, generation, continuation, continuationMessage.id, input.reason ?? "manual", now)
|
|
113
101
|
: mode === "native"
|
|
114
|
-
? createNativeCompact(agent.id, generation, continuation, continuationMessage.id)
|
|
115
|
-
: createClearThenInject(agent.id, generation, continuation, continuationMessage.id);
|
|
116
|
-
attachContextRecoveryCommand(agent.id, generation, command.id);
|
|
102
|
+
? (await createNativeCompact(agent.id, generation, continuation, continuationMessage.id))
|
|
103
|
+
: (await createClearThenInject(agent.id, generation, continuation, continuationMessage.id));
|
|
104
|
+
(await attachContextRecoveryCommand(agent.id, generation, command.id));
|
|
117
105
|
emitCommandEvent(command, "command.requested");
|
|
118
106
|
return {
|
|
119
107
|
ok: true,
|
|
@@ -169,7 +157,7 @@ export interface ForcedResumePlan {
|
|
|
169
157
|
// shapes, so the reactive/sweep reinjection (#1023) plus the #1998 objective-epoch render guarantees
|
|
170
158
|
// apply unchanged. Returns null (→ caller falls back to a bare compact) when the provider has no
|
|
171
159
|
// resume route / no re-injection channel OR the agent has no stored envelope yet.
|
|
172
|
-
export function buildForcedResumePlan(agentId: string, now = Date.now()): ForcedResumePlan | null {
|
|
160
|
+
export async function buildForcedResumePlan(agentId: string, now = Date.now()): Promise<ForcedResumePlan | null> {
|
|
173
161
|
const agent = getAgent(agentId);
|
|
174
162
|
if (!agent) return null;
|
|
175
163
|
const context = agent.providerCapabilities?.context;
|
|
@@ -192,10 +180,10 @@ export function buildForcedResumePlan(agentId: string, now = Date.now()): Forced
|
|
|
192
180
|
if (!envelope) return null;
|
|
193
181
|
const generation = envelope.generation;
|
|
194
182
|
const fullContinuation = renderContinuation(envelope, {
|
|
195
|
-
memoryCapture: boundaryCaptureClause({ seam: "post", agentId, now }),
|
|
183
|
+
memoryCapture: (await boundaryCaptureClause({ seam: "post", agentId, now })),
|
|
196
184
|
liveRuns: renderSelfCareState(agentId),
|
|
197
185
|
});
|
|
198
|
-
const continuationMessage = createContinuationRecoveryMessage(agentId, generation, fullContinuation, now);
|
|
186
|
+
const continuationMessage = (await createContinuationRecoveryMessage(agentId, generation, fullContinuation, now));
|
|
199
187
|
const continuation = insertRecoveryPointerAfterIntro(fullContinuation, continuationMessage.id);
|
|
200
188
|
if (useNativeCompact) {
|
|
201
189
|
// Preserve the provider's in-place summary; re-inject the (possibly stale) envelope AFTER.
|
|
@@ -235,11 +223,11 @@ function insertRecoveryPointerAfterIntro(continuation: string, messageId: number
|
|
|
235
223
|
return `${continuation.slice(0, firstNewline).trimEnd()}\n${pointer}${continuation.slice(firstNewline)}`;
|
|
236
224
|
}
|
|
237
225
|
|
|
238
|
-
function createContinuationRecoveryMessage(agentId: string, generation: number, continuation: string, now: number) {
|
|
226
|
+
async function createContinuationRecoveryMessage(agentId: string, generation: number, continuation: string, now: number) {
|
|
239
227
|
const idempotencyKey = `self-resume-continuation:${agentId}:${generation}`;
|
|
240
228
|
const existing = findMessageByIdempotencyKey("system", idempotencyKey);
|
|
241
229
|
if (existing) return existing;
|
|
242
|
-
return
|
|
230
|
+
return (await sendMessageAsync({
|
|
243
231
|
from: "system",
|
|
244
232
|
to: agentId,
|
|
245
233
|
kind: "system",
|
|
@@ -258,7 +246,7 @@ function createContinuationRecoveryMessage(agentId: string, generation: number,
|
|
|
258
246
|
// provider session accepted it. The runner promotes this only after turn/start acceptance.
|
|
259
247
|
delivery: { state: "stored" },
|
|
260
248
|
},
|
|
261
|
-
});
|
|
249
|
+
}));
|
|
262
250
|
}
|
|
263
251
|
|
|
264
252
|
// #1023 — the ruledOut ledger bound (see updateContinuationAfterCompact) drops the
|
|
@@ -325,7 +313,7 @@ function continuationDeliveredInline(command: Command): boolean {
|
|
|
325
313
|
|
|
326
314
|
/** Promote the persisted recovery artifact only from delivery evidence emitted by the runner.
|
|
327
315
|
* A successful clear command or a stored chat row alone is never enough. */
|
|
328
|
-
export function settleSelfResumeContinuationIngestion(command: Command): void {
|
|
316
|
+
export async function settleSelfResumeContinuationIngestion(command: Command): Promise<void> {
|
|
329
317
|
const result = isRecord(command.result) ? command.result : undefined;
|
|
330
318
|
const provider = result && isRecord(result.providerResult) ? result.providerResult : undefined;
|
|
331
319
|
let fullContextMessageId: number | undefined;
|
|
@@ -337,18 +325,18 @@ export function settleSelfResumeContinuationIngestion(command: Command): void {
|
|
|
337
325
|
fullContextMessageId = typeof resume?.fullContextMessageId === "number" ? resume.fullContextMessageId : undefined;
|
|
338
326
|
}
|
|
339
327
|
if (fullContextMessageId === undefined) return;
|
|
340
|
-
const message =
|
|
328
|
+
const message = (await markSelfResumeContinuationIngestedAsync(fullContextMessageId));
|
|
341
329
|
if (message) emitMessageDeliveryUpdated(message);
|
|
342
330
|
}
|
|
343
331
|
|
|
344
332
|
/** #2619 — a runner parks a continuation the provider refused under a usage/overload hold as a
|
|
345
333
|
* message to itself (payload.selfResumeFullContextMessageId). Its delivered report is the same
|
|
346
334
|
* delivery evidence an ingested injectContext result is: promote the recovery artifact. */
|
|
347
|
-
export function settleParkedSelfResumeContinuation(message: Message): void {
|
|
335
|
+
export async function settleParkedSelfResumeContinuation(message: Message): Promise<void> {
|
|
348
336
|
const fullContextMessageId = message.payload?.selfResumeFullContextMessageId;
|
|
349
337
|
if (typeof fullContextMessageId !== "number" || message.from !== message.to) return;
|
|
350
338
|
if (getMessage(fullContextMessageId)?.to !== message.to) return;
|
|
351
|
-
const promoted =
|
|
339
|
+
const promoted = (await markSelfResumeContinuationIngestedAsync(fullContextMessageId));
|
|
352
340
|
if (promoted) emitMessageDeliveryUpdated(promoted);
|
|
353
341
|
}
|
|
354
342
|
|
|
@@ -402,38 +390,38 @@ export function isFailedClearInjectSelfResume(command: Command): boolean {
|
|
|
402
390
|
}
|
|
403
391
|
|
|
404
392
|
/** #3662 — an older generation's boundary is retired (its queued injects canceled), never delivered. */
|
|
405
|
-
function retireIfSuperseded(command: Command): boolean {
|
|
393
|
+
async function retireIfSuperseded(command: Command): Promise<boolean> {
|
|
406
394
|
const current = supersedingGeneration(command);
|
|
407
395
|
if (current === null) return false;
|
|
408
|
-
cancelSupersededInjects(listPendingInjectionAttemptIds(command.id, CONTINUATION_INJECTION_REASON), current);
|
|
396
|
+
(await cancelSupersededInjects(listPendingInjectionAttemptIds(command.id, CONTINUATION_INJECTION_REASON), current));
|
|
409
397
|
return true;
|
|
410
398
|
}
|
|
411
399
|
|
|
412
|
-
export function enqueueContinuationInjectionAfterSelfResume(command: Command): Command | null {
|
|
400
|
+
export async function enqueueContinuationInjectionAfterSelfResume(command: Command): Promise<Command | null> {
|
|
413
401
|
if (command.status !== "succeeded" && !isFailedClearInjectSelfResume(command)) return null;
|
|
414
402
|
const injection = extractPendingInjection(command);
|
|
415
|
-
if (!injection || retireIfSuperseded(command)) return null;
|
|
403
|
+
if (!injection || (await retireIfSuperseded(command))) return null;
|
|
416
404
|
if (continuationDeliveredInline(command)) return null;
|
|
417
405
|
if (injectionAttemptsFor(command, CONTINUATION_INJECTION_REASON).length) return null;
|
|
418
|
-
const inject =
|
|
406
|
+
const inject = (await createCommandAsync({
|
|
419
407
|
type: "agent.injectContext",
|
|
420
408
|
source: "system",
|
|
421
409
|
target: command.target,
|
|
422
410
|
correlationId: command.id,
|
|
423
411
|
params: buildInjectionParams(command, injection, undefined, registrationReplayEpoch(command.target)),
|
|
424
|
-
});
|
|
412
|
+
}));
|
|
425
413
|
emitCommandEvent(inject, "command.requested");
|
|
426
414
|
return inject;
|
|
427
415
|
}
|
|
428
416
|
|
|
429
|
-
export function enqueueLifecycleIdentityInjectionAfterContextCommand(command: Command): Command | null {
|
|
417
|
+
export async function enqueueLifecycleIdentityInjectionAfterContextCommand(command: Command): Promise<Command | null> {
|
|
430
418
|
if (command.status !== "succeeded") return null;
|
|
431
419
|
if (command.type !== "agent.clearContext" && command.type !== "agent.compact") return null;
|
|
432
420
|
if (extractPendingInjection(command)) return null;
|
|
433
421
|
const content = identityContentForLifecycleCommand(command);
|
|
434
422
|
if (!content) return null;
|
|
435
423
|
if (injectionAttemptsFor(command, IDENTITY_INJECTION_REASON).length) return null;
|
|
436
|
-
const inject =
|
|
424
|
+
const inject = (await createCommandAsync({
|
|
437
425
|
type: "agent.injectContext",
|
|
438
426
|
source: "system",
|
|
439
427
|
target: command.target,
|
|
@@ -446,13 +434,13 @@ export function enqueueLifecycleIdentityInjectionAfterContextCommand(command: Co
|
|
|
446
434
|
...(command.type === "agent.compact" ? { afterCompactCommandId: command.id } : {}),
|
|
447
435
|
},
|
|
448
436
|
},
|
|
449
|
-
});
|
|
437
|
+
}));
|
|
450
438
|
emitCommandEvent(inject, "command.requested");
|
|
451
439
|
return inject;
|
|
452
440
|
}
|
|
453
441
|
|
|
454
|
-
export function enqueueContinuationInjectionAfterClear(command: Command): Command | null {
|
|
455
|
-
return enqueueContinuationInjectionAfterSelfResume(command);
|
|
442
|
+
export async function enqueueContinuationInjectionAfterClear(command: Command): Promise<Command | null> {
|
|
443
|
+
return (await enqueueContinuationInjectionAfterSelfResume(command));
|
|
456
444
|
}
|
|
457
445
|
|
|
458
446
|
const CLEAR_OR_COMPACT_TYPES = ["agent.clearContext", "agent.compact"] as const;
|
|
@@ -613,7 +601,7 @@ function continuationInjectionAttemptDecision(command: Command, replayEpoch?: st
|
|
|
613
601
|
// lost, and a redundant-but-harmless re-injection is preferable to a permanent
|
|
614
602
|
// silent mind-wipe. The sweep creates only a missing initial attempt; it never retries a failed
|
|
615
603
|
// attempt by itself, so an unavailable-but-still-registered provider cannot grow commands forever.
|
|
616
|
-
export function sweepMissedContinuationInjections(now: number = Date.now(), signal?: AbortSignal, targetAgentId?: string, replayEpoch?: string): { enqueuedCommandIds: string[]; aborted?: true } {
|
|
604
|
+
export async function sweepMissedContinuationInjections(now: number = Date.now(), signal?: AbortSignal, targetAgentId?: string, replayEpoch?: string): Promise<{ enqueuedCommandIds: string[]; aborted?: true }> {
|
|
617
605
|
const enqueuedCommandIds: string[] = [];
|
|
618
606
|
// #1726 — shared across every candidate this tick: the identity rebuild only depends on the
|
|
619
607
|
// target agent, and every target must already exist in the (bounded) agent roster, so this
|
|
@@ -628,27 +616,27 @@ export function sweepMissedContinuationInjections(now: number = Date.now(), sign
|
|
|
628
616
|
// between candidates simply leaves the rest for the next tick. SYNCHRONOUS job — inert on one
|
|
629
617
|
// thread until this grows an await.
|
|
630
618
|
for (const command of sweepableBoundaryCommands(now, signal, targetAgentId)) {
|
|
631
|
-
sweepContinuationBoundary(command, identityCache, enqueuedCommandIds, replayEpoch);
|
|
619
|
+
(await sweepContinuationBoundary(command, identityCache, enqueuedCommandIds, replayEpoch));
|
|
632
620
|
}
|
|
633
621
|
return { enqueuedCommandIds, ...(signal?.aborted ? { aborted: true as const } : {}) };
|
|
634
622
|
}
|
|
635
623
|
|
|
636
|
-
function sweepContinuationBoundary(command: Command, identityCache: WhoamiIdentityCache, enqueuedCommandIds: string[], replayEpoch?: string): void {
|
|
624
|
+
async function sweepContinuationBoundary(command: Command, identityCache: WhoamiIdentityCache, enqueuedCommandIds: string[], replayEpoch?: string): Promise<void> {
|
|
637
625
|
const injection = extractPendingInjection(command);
|
|
638
|
-
if (!injection || retireIfSuperseded(command)) return;
|
|
626
|
+
if (!injection || (await retireIfSuperseded(command))) return;
|
|
639
627
|
if (continuationDeliveredInline(command)) return;
|
|
640
628
|
const agent = getAgent(command.target);
|
|
641
629
|
if (!agent || agent.status === "offline") return;
|
|
642
630
|
const attemptEpoch = replayEpoch ?? registrationReplayEpoch(command.target);
|
|
643
631
|
const { decision } = continuationInjectionAttemptDecision(command, attemptEpoch);
|
|
644
632
|
if (decision !== "enqueue") return;
|
|
645
|
-
const inject =
|
|
633
|
+
const inject = (await createCommandAsync({
|
|
646
634
|
type: "agent.injectContext",
|
|
647
635
|
source: "system",
|
|
648
636
|
target: command.target,
|
|
649
637
|
correlationId: command.id,
|
|
650
638
|
params: buildInjectionParams(command, injection, identityCache, attemptEpoch),
|
|
651
|
-
});
|
|
639
|
+
}));
|
|
652
640
|
emitCommandEvent(inject, "command.requested");
|
|
653
641
|
enqueuedCommandIds.push(inject.id);
|
|
654
642
|
}
|
|
@@ -658,14 +646,14 @@ function sweepContinuationBoundary(command: Command, identityCache: WhoamiIdenti
|
|
|
658
646
|
async function sweepMissedContinuationInjectionsPaced(now: number, signal?: AbortSignal): Promise<{ enqueuedCommandIds: string[]; aborted?: true; moreWork?: true }> {
|
|
659
647
|
const enqueuedCommandIds: string[] = [];
|
|
660
648
|
const identityCache: WhoamiIdentityCache = new Map();
|
|
661
|
-
const { moreWork } = await pacedInjectionSweep(() => sweepableBoundaryCommands(now, signal), (command) => sweepContinuationBoundary(command, identityCache, enqueuedCommandIds), signal);
|
|
649
|
+
const { moreWork } = await pacedInjectionSweep(() => sweepableBoundaryCommands(now, signal), async (command) => (await sweepContinuationBoundary(command, identityCache, enqueuedCommandIds)), signal);
|
|
662
650
|
return { enqueuedCommandIds, ...(signal?.aborted ? { aborted: true as const } : {}), ...(moreWork ? { moreWork: true as const } : {}) };
|
|
663
651
|
}
|
|
664
652
|
|
|
665
653
|
/** Replay one parked continuation attempt for a new ready/idle or registration epoch. The epoch is
|
|
666
654
|
* persisted on the inject command, making repeated observations of the same lifecycle edge inert. */
|
|
667
|
-
export function replayParkedContinuationInjections(agentId: string, lifecycleEpoch: string, now = Date.now()): { enqueuedCommandIds: string[] } {
|
|
668
|
-
return sweepMissedContinuationInjections(now, undefined, agentId, lifecycleEpoch);
|
|
655
|
+
export async function replayParkedContinuationInjections(agentId: string, lifecycleEpoch: string, now = Date.now()): Promise<{ enqueuedCommandIds: string[] }> {
|
|
656
|
+
return (await sweepMissedContinuationInjections(now, undefined, agentId, lifecycleEpoch));
|
|
669
657
|
}
|
|
670
658
|
|
|
671
659
|
export const SELF_RESUME_INJECTION_SWEEP_JOB = {
|
|
@@ -681,14 +669,14 @@ export const SELF_RESUME_INJECTION_SWEEP_JOB = {
|
|
|
681
669
|
},
|
|
682
670
|
};
|
|
683
671
|
|
|
684
|
-
function notifyContinuationInjectionExhausted(command: Command, attempts: number): void {
|
|
672
|
+
async function notifyContinuationInjectionExhausted(command: Command, attempts: number): Promise<void> {
|
|
685
673
|
const idempotencyKey = `self-resume-injection-exhausted:${command.target}:${command.id}`;
|
|
686
674
|
if (findMessageByIdempotencyKey(command.target, idempotencyKey)) return;
|
|
687
675
|
const agent = getAgent(command.target);
|
|
688
676
|
const payload = { kind: "agent.resume_injection_failed", agentId: command.target, commandId: command.id, attempts };
|
|
689
677
|
emitRelayEvent({ type: "agent.resume_injection_failed", source: "server", subject: command.target, data: payload });
|
|
690
678
|
const recipient = agent?.spawnedBy ?? agentPrincipalSink(command.target);
|
|
691
|
-
routeNotification({
|
|
679
|
+
await routeNotification({
|
|
692
680
|
type: "agent.resume_injection_failed",
|
|
693
681
|
scope: { agentId: command.target, parent: agent?.spawnedBy },
|
|
694
682
|
recipients: [recipient],
|
|
@@ -708,7 +696,7 @@ function notifyContinuationInjectionExhausted(command: Command, attempts: number
|
|
|
708
696
|
// silent no-op that let the #2043 runaway climb to ~750K tokens undetected. Surface it to the spawn
|
|
709
697
|
// parent (and as a durable relay event) instead of swallowing it. Idempotent per command. This is
|
|
710
698
|
// the ALARM; the continuation re-injection backstop (F2) is the separate recovery path.
|
|
711
|
-
export function notifySelfResumeNoOp(command: Command): void {
|
|
699
|
+
export async function notifySelfResumeNoOp(command: Command): Promise<void> {
|
|
712
700
|
if (command.status !== "failed" && command.status !== "timed_out") return;
|
|
713
701
|
if (command.type !== "agent.clearContext" && command.type !== "agent.compact") return;
|
|
714
702
|
const injection = extractPendingInjection(command);
|
|
@@ -731,7 +719,7 @@ export function notifySelfResumeNoOp(command: Command): void {
|
|
|
731
719
|
const recovery = command.type === "agent.clearContext" || command.status === "timed_out"
|
|
732
720
|
? "The relay re-injects the continuation as a backstop, but check the agent and consider a manual relay_compact_and_resume or restart."
|
|
733
721
|
: "The continuation remains persisted; check the agent and retry relay_compact_and_resume once it is responsive.";
|
|
734
|
-
routeNotification({
|
|
722
|
+
await routeNotification({
|
|
735
723
|
type: "agent.self_resume_noop",
|
|
736
724
|
scope: { agentId: command.target, parent: agent?.spawnedBy },
|
|
737
725
|
recipients: [recipient],
|
|
@@ -827,8 +815,8 @@ function assertResumeSupported(agent: AgentCard, mode: SelfResumeMode): void {
|
|
|
827
815
|
}
|
|
828
816
|
}
|
|
829
817
|
|
|
830
|
-
function createNativeCompact(agentId: string, generation: number, continuation: string, fullContextMessageId: number): Command {
|
|
831
|
-
return
|
|
818
|
+
async function createNativeCompact(agentId: string, generation: number, continuation: string, fullContextMessageId: number): Promise<Command> {
|
|
819
|
+
return (await createCommandAsync({
|
|
832
820
|
type: "agent.compact",
|
|
833
821
|
source: "system",
|
|
834
822
|
target: agentId,
|
|
@@ -837,16 +825,16 @@ function createNativeCompact(agentId: string, generation: number, continuation:
|
|
|
837
825
|
instructions: continuation,
|
|
838
826
|
selfResume: { generation, mode: "native", continuation, fullContextMessageId },
|
|
839
827
|
},
|
|
840
|
-
});
|
|
828
|
+
}));
|
|
841
829
|
}
|
|
842
830
|
|
|
843
|
-
function createClearThenInject(agentId: string, generation: number, continuation: string, fullContextMessageId: number): Command {
|
|
831
|
+
async function createClearThenInject(agentId: string, generation: number, continuation: string, fullContextMessageId: number): Promise<Command> {
|
|
844
832
|
// #1588 — store the fully-built (identity-augmented) continuation in the clear command's params so
|
|
845
833
|
// the runner can deliver it inline as a coupled unit, race-free, while preserving the #1206 identity
|
|
846
834
|
// re-injection that the separate reactive inject used to add via buildInjectionParams. The backstop
|
|
847
835
|
// path re-augments idempotently, so embedding it here causes no drift.
|
|
848
836
|
const coupledContinuation = augmentContinuationWithIdentity(agentId, continuation);
|
|
849
|
-
return
|
|
837
|
+
return (await createCommandAsync({
|
|
850
838
|
type: "agent.clearContext",
|
|
851
839
|
source: "system",
|
|
852
840
|
target: agentId,
|
|
@@ -854,7 +842,7 @@ function createClearThenInject(agentId: string, generation: number, continuation
|
|
|
854
842
|
reason: "self-resume",
|
|
855
843
|
selfResume: { generation, mode: "clear-inject", continuation: coupledContinuation, fullContextMessageId },
|
|
856
844
|
},
|
|
857
|
-
});
|
|
845
|
+
}));
|
|
858
846
|
}
|
|
859
847
|
|
|
860
848
|
function parseRuledOut(value: unknown, generation: number, now: number): ContinuationLedgerEntry[] {
|
package/src/server-background.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { notifyCdDeployLive } from "./cd-deploy-notify";
|
|
|
9
9
|
import { isEphemeralMode } from "./execution-mode";
|
|
10
10
|
import { startClaudeAppOAuth } from "./claude-app/oauth-http";
|
|
11
11
|
|
|
12
|
-
export function startServerBackgroundJobs(): void {
|
|
12
|
+
export async function startServerBackgroundJobs(): Promise<void> {
|
|
13
13
|
startPostBindJobs([
|
|
14
14
|
{ name: "claude-app-oauth", start: startClaudeAppOAuth },
|
|
15
15
|
{ name: "user-awaiting-reply", start: () => { startUserAwaitingReply(); } },
|
package/src/server.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { framed } from "./hub-metrics";
|
|
2
|
+
import { setConfigAsync } from "./config-store-write";
|
|
1
3
|
import { drainWriterOnShutdown } from "./db/writer-gateway";
|
|
2
4
|
import { relayHeaderConflict, errMessage, reapEphemeralSelf, startArtifactCheckoutLease, startEphemeralWatchdogFromEnv } from "@humwick/sdk";
|
|
3
5
|
import { authorityDenied } from "./authority-audit";
|
|
4
6
|
import { openTerminalProxy, sendTerminalProxyFrame, closeTerminalProxy, type TerminalProxySocketData, type TerminalProxySocket } from "./stream-proxy";
|
|
5
7
|
import { startServerBackgroundJobs } from "./server-background";
|
|
6
|
-
import {
|
|
8
|
+
import { dashboardLinkRedirect } from "./invite-link";
|
|
7
9
|
import { claudeAppBoundary, CLAUDE_APP_PATH, isClaudeAppPath } from "./claude-app-auth";
|
|
8
10
|
import { handleClaudeApp } from "./claude-app-gateway";
|
|
9
11
|
import { handleClaudeAppOAuth } from "./claude-app/oauth-http";
|
|
@@ -12,7 +14,7 @@ import { beginMainWriteBootPhase, endMainWriteBootPhase } from "./db/main-connec
|
|
|
12
14
|
import { markServerBound, timePostBindPhase } from "./post-bind-startup";
|
|
13
15
|
import type { ServerWebSocket } from "bun";
|
|
14
16
|
import { beginStartupPhase, enableStartupTiming, timeStartupPhase } from "./startup-timing";
|
|
15
|
-
import { initDb, getOrchestrator, startPresenceFlushLoop, primeHostAliasMemoFromDb } from "./db";
|
|
17
|
+
import { initDb, getOrchestrator, startPresenceFlushLoop, primeHostAliasMemoFromDb, onWorkspaceCreate } from "./db";
|
|
16
18
|
import { initGateway, shutdownGatewayReader } from "./db/gateway";
|
|
17
19
|
import { flushRelayEvents } from "./relay-event-drain";
|
|
18
20
|
import { startWalCheckpointer } from "./db/wal-checkpointer";
|
|
@@ -25,7 +27,7 @@ import { emitRelayEvent } from "./events";
|
|
|
25
27
|
import { reconcileAutomationRuns, runDueAutomationsAsync, type AutomationDispatchResult, type AutomationReconcileResult } from "./automations";
|
|
26
28
|
import { getLifecycleManager } from "./lifecycle-manager";
|
|
27
29
|
import { reconcileStewardPolicyModels } from "./steward-policy-model-reconcile";
|
|
28
|
-
import { getConfig
|
|
30
|
+
import { getConfig } from "./config-store";
|
|
29
31
|
export { reconcileProviderModelSeed } from "./provider-model-seed";
|
|
30
32
|
import { ensureEscalationChannelRegistered } from "./connectors";
|
|
31
33
|
import { installNotificationSubscriptionRule } from "./notification-subscription-rules";
|
|
@@ -33,7 +35,6 @@ import { startPlanLiveBindings } from "./services/plan-live-bindings";
|
|
|
33
35
|
import { startEventLoopLagSampler } from "./event-loop-lag";
|
|
34
36
|
import { installLoopBlockRegressionAlarm } from "./loop-block-regression-alarm";
|
|
35
37
|
import { recordWorkspaceIssueActivity } from "./services/spawn-issue-activity";
|
|
36
|
-
import { onWorkspaceCreate } from "./db";
|
|
37
38
|
import { warnIfNoHumanReachableEscalationTarget } from "./workspace-human-escalation";
|
|
38
39
|
import { isTerminalSessionRequestAuthorized } from "./terminal-authz";
|
|
39
40
|
import { resolveBrowserStream } from "./routes/browser";
|
|
@@ -84,16 +85,16 @@ import type { Command } from "./types";
|
|
|
84
85
|
//
|
|
85
86
|
// `relay-version` is still tracked for observability/telemetry, but it no longer
|
|
86
87
|
// triggers restarts.
|
|
87
|
-
export function reconcileRelayVersion(): void {
|
|
88
|
+
export async function reconcileRelayVersion(): Promise<void> {
|
|
88
89
|
const storedVersion = getConfig<string>("system", "relay-version")?.value;
|
|
89
|
-
if (storedVersion !== VERSION)
|
|
90
|
+
if (storedVersion !== VERSION) (await setConfigAsync("system", "relay-version", VERSION, "server-startup"));
|
|
90
91
|
|
|
91
92
|
const storedProtocol = getConfig<string>("system", "runner-protocol-version")?.value;
|
|
92
93
|
const currentProtocol = String(CONTRACT_VERSIONS.runnerProtocol);
|
|
93
94
|
if (storedProtocol === currentProtocol) return;
|
|
94
95
|
// Skip the very first run (no stored protocol yet) — that's initial bootstrap, not an upgrade.
|
|
95
96
|
if (storedProtocol) getLifecycleManager().onRelayUpdated(VERSION);
|
|
96
|
-
|
|
97
|
+
(await setConfigAsync("system", "runner-protocol-version", currentProtocol, "server-startup"));
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
export function runServerStartupRecoveries(): ReturnType<typeof sweepDeferredLineageReportsOnStartup> {
|
|
@@ -116,9 +117,7 @@ export async function startServer(): Promise<void> {
|
|
|
116
117
|
timeStartupPhase("server.database", () => initDb(DB_PATH));
|
|
117
118
|
// #1960 T2 — stand the gateway up EXPLICITLY here rather than leaving it to the lazy self-init
|
|
118
119
|
// (`getGateway()` on first call, gateway.ts), which would race the rest of this boot sequence.
|
|
119
|
-
//
|
|
120
|
-
// ADR 0001 §7 Phase 1); the writer is deliberately left at its in-process default — Phase W (a
|
|
121
|
-
// worker writer surrendering the sole RW connection) remains the #1870 migration.
|
|
120
|
+
// File-backed reads and writes default off-loop; memory fixtures retain local connections (#3339).
|
|
122
121
|
timeStartupPhase("server.gateway", () => initGateway({ readerBackend: gatewayReaderBackendFromEnv() }));
|
|
123
122
|
onShutdown("gateway-reader", shutdownGatewayReader);
|
|
124
123
|
onShutdown("gateway-writer", drainWriterOnShutdown, "drain");
|
|
@@ -137,11 +136,11 @@ export async function startServer(): Promise<void> {
|
|
|
137
136
|
const finishServices = beginStartupPhase("server.services");
|
|
138
137
|
installNotificationSubscriptionRule();
|
|
139
138
|
startPlanLiveBindings();
|
|
140
|
-
reconcileRelayVersion();
|
|
139
|
+
(await reconcileRelayVersion());
|
|
141
140
|
// Register the ntfy escalation channel row from persisted connector config BEFORE the
|
|
142
141
|
// warning check, so a correctly-configured relay doesn't spuriously warn while the async
|
|
143
142
|
// channels-host connect is still in flight (#1510).
|
|
144
|
-
ensureEscalationChannelRegistered();
|
|
143
|
+
(await ensureEscalationChannelRegistered());
|
|
145
144
|
warnIfNoHumanReachableEscalationTarget();
|
|
146
145
|
startEventLoopLagSampler();
|
|
147
146
|
// #1882 (S5, ADR 0001 §5) — per-callsite on-loop-block attribution + the >50ms regression alarm.
|
|
@@ -167,12 +166,12 @@ export async function startServer(): Promise<void> {
|
|
|
167
166
|
},
|
|
168
167
|
});
|
|
169
168
|
} else {
|
|
170
|
-
setInterval(() => {
|
|
169
|
+
setInterval(framed("timer automations", () => {
|
|
171
170
|
void timePostBindPhase("automations.reconcile", reconcileAutomationRuns)
|
|
172
171
|
.then(emitAutomationReconciliations)
|
|
173
172
|
.catch((e) => console.error(`[automations] reconcile failed: ${errMessage(e)}`));
|
|
174
173
|
void timePostBindPhase("automations.dispatch", runDueAutomationsAsync).then(emitAutomationDispatches).catch((e) => console.error(`[automations] dispatch failed: ${errMessage(e)}`));
|
|
175
|
-
}, AUTOMATION_INTERVAL_MS);
|
|
174
|
+
}), AUTOMATION_INTERVAL_MS);
|
|
176
175
|
}
|
|
177
176
|
|
|
178
177
|
installTimerIngressSchema();
|
|
@@ -186,7 +185,7 @@ export async function startServer(): Promise<void> {
|
|
|
186
185
|
websocket: createWebSocketHandlers(),
|
|
187
186
|
}));
|
|
188
187
|
markServerBound();
|
|
189
|
-
startServerBackgroundJobs();
|
|
188
|
+
await startServerBackgroundJobs();
|
|
190
189
|
finishStartup();
|
|
191
190
|
console.log(`humwick ${VERSION} running on http://${HOST}:${PORT}`);
|
|
192
191
|
|
|
@@ -280,12 +279,12 @@ export function createFetchHandler(
|
|
|
280
279
|
const terminalStreamMatch = url.pathname.match(/^\/api\/orchestrators\/([^/]+)\/terminal\/([^/]+)\/stream$/);
|
|
281
280
|
if (req.method === "GET" && terminalStreamMatch) {
|
|
282
281
|
if (!server) return new Response("WebSocket upgrade unavailable", { status: 400 });
|
|
283
|
-
if (!isOriginAllowed(req)) return authorityDenied(req, "origin not allowed", 403);
|
|
284
|
-
if (!isAuthorized(req)) return applyCors(req, authorityDenied(req, "unauthorized", 401));
|
|
282
|
+
if (!isOriginAllowed(req)) return (await authorityDenied(req, "origin not allowed", 403));
|
|
283
|
+
if (!isAuthorized(req)) return applyCors(req, (await authorityDenied(req, "unauthorized", 401)));
|
|
285
284
|
const orchestratorId = decodeURIComponent(terminalStreamMatch[1]!);
|
|
286
285
|
const session = decodeURIComponent(terminalStreamMatch[2]!);
|
|
287
286
|
if (!isTerminalSessionRequestAuthorized(req, orchestratorId, session, "read")) {
|
|
288
|
-
return applyCors(req, authorityDenied(req, "forbidden"));
|
|
287
|
+
return applyCors(req, (await authorityDenied(req, "forbidden")));
|
|
289
288
|
}
|
|
290
289
|
const writeAuthorized = isTerminalSessionRequestAuthorized(req, orchestratorId, session, "write");
|
|
291
290
|
const orch = getOrchestrator(orchestratorId);
|
|
@@ -312,7 +311,7 @@ export function createFetchHandler(
|
|
|
312
311
|
}
|
|
313
312
|
const matched = matchRoute(req.method, url.pathname);
|
|
314
313
|
if (!isOriginAllowed(req) && !(req.headers.get("origin") === "null" && matched?.handler === postSecretUpload)) {
|
|
315
|
-
return authorityDenied(req, "origin not allowed", 403);
|
|
314
|
+
return (await authorityDenied(req, "origin not allowed", 403));
|
|
316
315
|
}
|
|
317
316
|
|
|
318
317
|
// KAPI-1 §4.2 — the live `/api/kernel` control mount. Handled as a dedicated subtree (not through
|
|
@@ -322,7 +321,7 @@ export function createFetchHandler(
|
|
|
322
321
|
// default-denies. A request that fails the coarse gate 403s here (matching the resolver's own 403 for
|
|
323
322
|
// a missing/invalid/non-component credential), including `GET /api/kernel/openapi.json`.
|
|
324
323
|
if (isKernelControlPath(url.pathname)) {
|
|
325
|
-
if (!isKernelControlRequestAuthorized(req)) return applyCors(req, authorityDenied(req, "forbidden"));
|
|
324
|
+
if (!isKernelControlRequestAuthorized(req)) return applyCors(req, (await authorityDenied(req, "forbidden")));
|
|
326
325
|
const response = await handleKernelControlRequest(req);
|
|
327
326
|
applyCors(req, response);
|
|
328
327
|
if (logRequests) console.log(`${req.method} ${url.pathname} → ${response.status}`);
|
|
@@ -346,7 +345,7 @@ export function createFetchHandler(
|
|
|
346
345
|
// the way a session is obtained. Each handler self-authenticates (login verifies credentials,
|
|
347
346
|
// refresh validates the refresh token, logout revokes the presented token). Everything else
|
|
348
347
|
// still flows through the component-token gate below.
|
|
349
|
-
const publicAuthPaths = ["/api/auth/providers", "/api/auth/login", "/api/auth/refresh", "/api/auth/logout", "/api/auth/invites/accept"];
|
|
348
|
+
const publicAuthPaths = ["/api/auth/providers", "/api/auth/login", "/api/auth/refresh", "/api/auth/logout", "/api/auth/invites/accept", "/api/auth/login-links/redeem"];
|
|
350
349
|
if (!isSecretUploadRequest(req, url.pathname, server) && !publicPaths.includes(url.pathname) && !publicAuthPaths.includes(url.pathname)) {
|
|
351
350
|
const integrationAuth = getIntegrationAuth(req);
|
|
352
351
|
const componentAuth = getComponentAuth(req);
|
|
@@ -367,11 +366,11 @@ export function createFetchHandler(
|
|
|
367
366
|
// full server scope), so it stays the authoritative reject for a revoked/
|
|
368
367
|
// invalid session token — it just answers in the caller's protocol.
|
|
369
368
|
if (url.pathname === "/api/mcp") return unauthorizedMcp(req);
|
|
370
|
-
return applyCors(req, authorityDenied(req, "unauthorized", 401));
|
|
369
|
+
return applyCors(req, (await authorityDenied(req, "unauthorized", 401)));
|
|
371
370
|
}
|
|
372
|
-
if (!handlerOwnsScopedAuth && !isScopedRequestAuthorized(req)) return applyCors(req, authorityDenied(req, "forbidden"));
|
|
371
|
+
if (!handlerOwnsScopedAuth && !isScopedRequestAuthorized(req)) return applyCors(req, (await authorityDenied(req, "forbidden")));
|
|
373
372
|
}
|
|
374
|
-
if (componentAuth && !handlerOwnsScopedAuth && !isScopedRequestAuthorized(req)) return applyCors(req, authorityDenied(req, "forbidden"));
|
|
373
|
+
if (componentAuth && !handlerOwnsScopedAuth && !isScopedRequestAuthorized(req)) return applyCors(req, (await authorityDenied(req, "forbidden")));
|
|
375
374
|
}
|
|
376
375
|
const response = await runMatchedRoute(matched, req, (body) => maybeCompressApiResponse(req, url, body));
|
|
377
376
|
applyCors(req, response);
|
|
@@ -381,8 +380,8 @@ export function createFetchHandler(
|
|
|
381
380
|
return response;
|
|
382
381
|
}
|
|
383
382
|
|
|
384
|
-
const
|
|
385
|
-
if (
|
|
383
|
+
const linkRedirect = dashboardLinkRedirect(url.pathname);
|
|
384
|
+
if (linkRedirect) return linkRedirect;
|
|
386
385
|
// Dashboard — serve static files, rejecting path traversal and directory requests
|
|
387
386
|
let requested = url.pathname === "/" ? "/index.html" : url.pathname;
|
|
388
387
|
if (requested.endsWith("/")) requested += "index.html";
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { getGateway } from "../db/gateway";
|
|
2
|
+
import type { admitAgentActionBody } from "../db/agent-action-write";
|
|
1
3
|
import { isHumanAgentId } from "@humwick/sdk";
|
|
2
4
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
+
import { getCommand } from "../commands-db";
|
|
6
|
+
import { getAgentEffortState } from "../db/agent-effort-state";
|
|
5
7
|
import { emitEffortState } from "./agent-effort";
|
|
6
|
-
import { ValidationError, createActivityEventAsync, getAgent
|
|
8
|
+
import { ValidationError, createActivityEventAsync, getAgent } from "../db";
|
|
7
9
|
import { emitCommandEvent } from "../command-events";
|
|
8
10
|
import { emitActivityEvent, emitNewMessage } from "../sse";
|
|
9
11
|
import { effectiveProviderCatalogList } from "../provider-catalog-store";
|
|
@@ -112,15 +114,6 @@ function catalogEffort(agent: AgentCard, effort: string | undefined): { level: s
|
|
|
112
114
|
return { level, efforts: known?.efforts };
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
function sessionMessageForInject(agentId: string, ctx: AuthContext, body: string) {
|
|
116
|
-
const from = ctx.callerAgentId && getAgent(ctx.callerAgentId) ? ctx.callerAgentId : "system";
|
|
117
|
-
return sendMessage({
|
|
118
|
-
from,
|
|
119
|
-
to: agentId,
|
|
120
|
-
kind: "session",
|
|
121
|
-
body,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
117
|
|
|
125
118
|
export function revalidateAgentInstance(snapshot: AgentCard): AgentCard {
|
|
126
119
|
const current = getAgent(snapshot.id);
|
|
@@ -136,7 +129,7 @@ export async function dispatchAgentAction(input: AgentActionInput, ctx: AuthCont
|
|
|
136
129
|
|
|
137
130
|
// #2950 — an agent may change its own effort (only that), gated by its spawn's selfEffort ceiling below.
|
|
138
131
|
const self = input.action === "effort" && Boolean(ctx.callerAgentId) && ctx.callerAgentId === agent.id;
|
|
139
|
-
if (!self) authorizeShutdown(ctx, { agentId: input.agentId, requestedVia: input.requestedVia }, input.action);
|
|
132
|
+
if (!self) (await authorizeShutdown(ctx, { agentId: input.agentId, requestedVia: input.requestedVia }, input.action));
|
|
140
133
|
const requestId = input.action === "effort" ? input.requestId?.trim() || undefined : undefined;
|
|
141
134
|
if (requestId && !REQUEST_ID.test(requestId)) throw new ValidationError("requestId must be a UUID");
|
|
142
135
|
const retried = admittedEffortRequest(agent.id, requestId);
|
|
@@ -210,24 +203,12 @@ export async function dispatchAgentAction(input: AgentActionInput, ctx: AuthCont
|
|
|
210
203
|
// a stale command built from the predecessor's capabilities/session data.
|
|
211
204
|
const event = await createActivityEventAsync(activityInput);
|
|
212
205
|
const current = revalidateAgentInstance(agent);
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const
|
|
219
|
-
// A concurrent retry of the same request committed first.
|
|
220
|
-
if ((raced = admittedEffortRequest(current.id, requestId))) return raced.command;
|
|
221
|
-
// #2966 — a revoke committed during the audit await wins: recheck where the command is inserted.
|
|
222
|
-
if (selfPolicy) assertSelfEffortAllowed(current, requested!.level, requested!.efforts);
|
|
223
|
-
if (effort) {
|
|
224
|
-
// #2984 — the desired version is the change; the command is its audit row, never executed.
|
|
225
|
-
admitted = admitDesiredEffortInternal({ agentId: current.id, effort, role: requestedByRole, commandId, now: Date.now() });
|
|
226
|
-
commandInput.params.effortVersion = admitted.state.desiredVersion;
|
|
227
|
-
}
|
|
228
|
-
return createCommandInternal({ input: commandInput, id: commandId });
|
|
229
|
-
});
|
|
230
|
-
if (raced) return raced;
|
|
206
|
+
const from = ctx.callerAgentId && getAgent(ctx.callerAgentId) ? ctx.callerAgentId : "system";
|
|
207
|
+
const result = await getGateway().write("agents.admitAction", { agent: current, commandId, commandInput, requestId, effort, role: requestedByRole,
|
|
208
|
+
...(selfPolicy ? { selfEffort: requested } : {}), ...(body ? { message: { from, to: current.id, kind: "session", body } } : {}) }, { idempotencyKey: commandId }) as unknown as ReturnType<typeof admitAgentActionBody>;
|
|
209
|
+
const { command } = result;
|
|
210
|
+
if (result.raced) return { action: input.action, command, effortState: result.effortState };
|
|
211
|
+
const { admitted, sessionMessage } = result;
|
|
231
212
|
if (sessionMessage) emitNewMessage(sessionMessage);
|
|
232
213
|
for (const id of admitted?.superseded ?? []) { const canceled = getCommand(id); if (canceled) emitCommandEvent(canceled, "command.canceled"); }
|
|
233
214
|
// No `command.requested` for effort: nothing executes the audit row. `command.pending` only tells the target runner to reconcile.
|