@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
package/src/project-trust.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { upsertProjectTrustApprovalAsync } from "./db/runtime-tail-async";
|
|
1
2
|
import { createHash } from "node:crypto";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
4
|
import { shellEscape, ValidationError, type AgentProfile, type ProfileAssetCell, type ProfileProjectCells, type ProfileProjectGate, type ProfileProjectReviewMode, type ProfileProjectTrustScope, type Project } from "@humwick/sdk";
|
|
4
5
|
import { rootsForProject, resolveProjectForCwd } from "./db/projects";
|
|
5
|
-
import { getProjectTrustApproval,
|
|
6
|
+
import { getProjectTrustApproval, type ProjectTrustApproval, type ProjectTrustCapability } from "./db/project-trust-approvals";
|
|
6
7
|
import { observeCapabilityReview } from "./project-trust-fingerprint";
|
|
7
8
|
import { canonicalRoot } from "./services/canonical-root";
|
|
8
9
|
import { isPathWithinBase } from "./utils";
|
|
@@ -35,26 +36,26 @@ function repoKeyFor(cwd: string): string {
|
|
|
35
36
|
/** Records `approvedValue` (a `sha256:<hex>` or `commit:<sha>`, matching `mode`) as trusted for
|
|
36
37
|
* this (profile, repo, capability) — the dashboard/API one-click approve action. Format-validated
|
|
37
38
|
* here so a malformed value can never be written through the trust store's only public writer. */
|
|
38
|
-
export function approveProjectCapabilityReview(input: {
|
|
39
|
+
export async function approveProjectCapabilityReview(input: {
|
|
39
40
|
profileName: string;
|
|
40
41
|
repoKey: string;
|
|
41
42
|
capability: ProjectCapability;
|
|
42
43
|
mode: "fingerprint" | "commit";
|
|
43
44
|
approvedValue: string;
|
|
44
45
|
approvedBy: string;
|
|
45
|
-
}): ProjectTrustApproval {
|
|
46
|
+
}): Promise<ProjectTrustApproval> {
|
|
46
47
|
const prefix = input.mode === "commit" ? "commit:" : "sha256:";
|
|
47
48
|
if (!input.approvedValue.startsWith(prefix)) {
|
|
48
49
|
throw new ValidationError(`approved value must be prefixed "${prefix}" for ${input.mode} review`);
|
|
49
50
|
}
|
|
50
|
-
return
|
|
51
|
+
return (await upsertProjectTrustApprovalAsync({
|
|
51
52
|
profileName: input.profileName,
|
|
52
53
|
repoKey: input.repoKey,
|
|
53
54
|
capability: input.capability,
|
|
54
55
|
reviewMode: input.mode,
|
|
55
56
|
approvedValue: input.approvedValue,
|
|
56
57
|
approvedBy: input.approvedBy,
|
|
57
|
-
});
|
|
58
|
+
}));
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/** Stable JSON is intentionally local to this small trust seam. The hash is an
|
|
@@ -142,13 +143,13 @@ export interface ProjectCapabilityGateOpts {
|
|
|
142
143
|
pinnedMcpCommit?: string;
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
export function projectCapabilityGate(
|
|
146
|
+
export async function projectCapabilityGate(
|
|
146
147
|
profile: AgentProfile,
|
|
147
148
|
capability: ProjectCapability,
|
|
148
149
|
cwd: string,
|
|
149
150
|
registeredProject?: Project | null,
|
|
150
151
|
opts?: ProjectCapabilityGateOpts,
|
|
151
|
-
): ProfileProjectGate {
|
|
152
|
+
): Promise<ProfileProjectGate> {
|
|
152
153
|
const project = profile.sources?.project;
|
|
153
154
|
const cell = capabilityCell(profile, capability);
|
|
154
155
|
if (!project || !cell?.enabled) {
|
|
@@ -238,7 +239,7 @@ export function projectCapabilityGate(
|
|
|
238
239
|
// approved instead of failing closed, so shipping G3 does not instantly regress every
|
|
239
240
|
// already-trusted profile. Only a SUBSEQUENT change (a different observed value) fails
|
|
240
241
|
// closed from here on.
|
|
241
|
-
|
|
242
|
+
(await upsertProjectTrustApprovalAsync({ profileName: profile.name, repoKey, capability, reviewMode: mode, approvedValue: observed, approvedBy: "system:grandfathered" }));
|
|
242
243
|
return { allowed: true, reason: "allowed", detail: gateDetail(capability, `${scopeDetail} (grandfathered ${observed})`), observed, repoKey, reviewMode: mode };
|
|
243
244
|
}
|
|
244
245
|
// `commit` review has no grandfather: it is the stricter opt-in mode, so first encounter
|
|
@@ -254,9 +255,9 @@ export function projectCapabilityGate(
|
|
|
254
255
|
/** Stamp the server's per-spawn decisions onto a cloned profile. The source cells
|
|
255
256
|
* remain visible for truthful projection; the runner consumes only these decisions
|
|
256
257
|
* for filesystem materialization. */
|
|
257
|
-
export function applyProjectCapabilityGates(profile: AgentProfile, cwd: string, registeredProject?: Project | null, opts?: ProjectCapabilityGateOpts): AgentProfile {
|
|
258
|
+
export async function applyProjectCapabilityGates(profile: AgentProfile, cwd: string, registeredProject?: Project | null, opts?: ProjectCapabilityGateOpts): Promise<AgentProfile> {
|
|
258
259
|
if (!profile.sources?.project) return profile;
|
|
259
|
-
const hooks = projectCapabilityGate(profile, "hooks", cwd, registeredProject, opts);
|
|
260
|
-
const mcp = projectCapabilityGate(profile, "mcp", cwd, registeredProject, opts);
|
|
260
|
+
const hooks = (await projectCapabilityGate(profile, "hooks", cwd, registeredProject, opts));
|
|
261
|
+
const mcp = (await projectCapabilityGate(profile, "mcp", cwd, registeredProject, opts));
|
|
261
262
|
return { ...profile, projectGates: { hooks, mcp } };
|
|
262
263
|
}
|
package/src/prompt-resolver.ts
CHANGED
|
@@ -250,7 +250,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
|
|
|
250
250
|
"{{context}}",
|
|
251
251
|
"Acceptance — done when:",
|
|
252
252
|
"{{doneWhen}}",
|
|
253
|
-
"",
|
|
253
|
+
"{{afterLand}}",
|
|
254
254
|
"Linked issue spec (resolved server-side once — do NOT re-read GitHub):",
|
|
255
255
|
"{{issues}}",
|
|
256
256
|
"",
|
|
@@ -275,7 +275,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
|
|
|
275
275
|
"{{context}}",
|
|
276
276
|
"Acceptance — done when:",
|
|
277
277
|
"{{doneWhen}}",
|
|
278
|
-
"",
|
|
278
|
+
"{{afterLand}}",
|
|
279
279
|
"Linked issue spec (resolved server-side once — do NOT re-read GitHub):",
|
|
280
280
|
"{{issues}}",
|
|
281
281
|
"",
|
|
@@ -288,7 +288,7 @@ const DEFAULT_PROMPT_TEMPLATES = [
|
|
|
288
288
|
"Latest steer (act on this now):",
|
|
289
289
|
"{{steer}}",
|
|
290
290
|
),
|
|
291
|
-
variables: ["taskId", "title", "status", "stage", "owner", "intent", "context", "doneWhen", "issues", "decisions", "history", "memory", "steer"],
|
|
291
|
+
variables: ["taskId", "title", "status", "stage", "owner", "intent", "context", "doneWhen", "afterLand", "issues", "decisions", "history", "memory", "steer"],
|
|
292
292
|
},
|
|
293
293
|
{
|
|
294
294
|
slug: "context.advisory.warn",
|
|
@@ -51,27 +51,25 @@ export async function upsertProviderQuotaAsync(
|
|
|
51
51
|
* Synchronous in-process compatibility wrapper for direct callers and existing tests. Runs the writer
|
|
52
52
|
* body directly (no gateway hop) and fires the returned effects synchronously.
|
|
53
53
|
*/
|
|
54
|
-
export function upsertProviderQuota(input: ProviderQuotaUpdateInput, now = Date.now()): ProviderQuotaRecord {
|
|
55
|
-
const result =
|
|
56
|
-
invalidateProviderQuotaMatrixCache();
|
|
54
|
+
export async function upsertProviderQuota(input: ProviderQuotaUpdateInput, now = Date.now()): Promise<ProviderQuotaRecord> {
|
|
55
|
+
const result = await upsertProviderQuotaAsync(input, { now });
|
|
57
56
|
if (result.outcome.kind !== "stored") throw new Error("provider quota lease not held");
|
|
58
|
-
deliverProviderQuotaEffects(result, { isolate: false });
|
|
59
57
|
return result.outcome.record;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
/** Fire each event+notification pair in production order; `isolate` logs (not throws) per-pair faults. */
|
|
63
|
-
function deliverProviderQuotaEffects(result: ProviderQuotaUpsertOpResult, options: { isolate: boolean }): void {
|
|
61
|
+
async function deliverProviderQuotaEffects(result: ProviderQuotaUpsertOpResult, options: { isolate: boolean }): Promise<void> {
|
|
64
62
|
for (const effect of result.advisory?.effects ?? []) {
|
|
65
63
|
if (options.isolate) {
|
|
66
64
|
try {
|
|
67
65
|
emitRelayEvent(effect.event);
|
|
68
|
-
if (effect.notification) routeNotification(effect.notification);
|
|
66
|
+
if (effect.notification) await routeNotification(effect.notification);
|
|
69
67
|
} catch (error) {
|
|
70
68
|
console.error("provider quota post-commit effect failed", error);
|
|
71
69
|
}
|
|
72
70
|
} else {
|
|
73
71
|
emitRelayEvent(effect.event);
|
|
74
|
-
if (effect.notification) routeNotification(effect.notification);
|
|
72
|
+
if (effect.notification) await routeNotification(effect.notification);
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isRecord, stringValue } from "@humwick/sdk";
|
|
2
|
-
import {
|
|
2
|
+
import { createActivityEventByClientIdAsync } from "./db/activity-async";
|
|
3
3
|
import { emitRelayEvent } from "./events";
|
|
4
4
|
|
|
5
5
|
interface HasMeta {
|
|
@@ -28,7 +28,7 @@ function numberValue(value: unknown): number | undefined {
|
|
|
28
28
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export function auditRunnerTimelineEvent(agentId: string, timelineEvent: ProviderTimelineEvent | null): void {
|
|
31
|
+
export async function auditRunnerTimelineEvent(agentId: string, timelineEvent: ProviderTimelineEvent | null): Promise<void> {
|
|
32
32
|
if (!timelineEvent) return;
|
|
33
33
|
const metadata = isRecord(timelineEvent.metadata) ? timelineEvent.metadata : {};
|
|
34
34
|
if (metadata.source !== "runner") return;
|
|
@@ -41,10 +41,7 @@ export function auditRunnerTimelineEvent(agentId: string, timelineEvent: Provide
|
|
|
41
41
|
const body = stringValue(timelineEvent.body);
|
|
42
42
|
const icon = stringValue(timelineEvent.icon) ?? "ti-activity";
|
|
43
43
|
try {
|
|
44
|
-
|
|
45
|
-
// into an unawaited gateway write would reorder/drop the audit relative to the frame; moving
|
|
46
|
-
// the whole hot status ingress is the later owner.
|
|
47
|
-
const result = createActivityEventWithResult({
|
|
44
|
+
const result = (await createActivityEventByClientIdAsync({
|
|
48
45
|
clientId: `runner-timeline-${agentId}-${id}`,
|
|
49
46
|
kind: "state",
|
|
50
47
|
title,
|
|
@@ -60,7 +57,7 @@ export function auditRunnerTimelineEvent(agentId: string, timelineEvent: Provide
|
|
|
60
57
|
timelineId: id,
|
|
61
58
|
timelineTimestamp: timestamp,
|
|
62
59
|
},
|
|
63
|
-
});
|
|
60
|
+
}));
|
|
64
61
|
// A repeated frame may still carry the same event during reconnect/retry. The durable activity
|
|
65
62
|
// clientId dedup is authoritative; only a newly inserted row owns an activity.created edge.
|
|
66
63
|
if (!result.created) return;
|
|
@@ -6,8 +6,8 @@ import { getSpawnCapableAgentIds } from "./routing-policy-push";
|
|
|
6
6
|
import { renderBandTransition } from "./quota-band-transition";
|
|
7
7
|
import type { ProviderBandWindow, QuotaBand } from "./quota-band-projection";
|
|
8
8
|
|
|
9
|
-
export function deliverBandTransition(input: { provider: string; window: ProviderBandWindow; previousBand: QuotaBand; recommendedAction: string; now: number }): void {
|
|
9
|
+
export async function deliverBandTransition(input: { provider: string; window: ProviderBandWindow; previousBand: QuotaBand; recommendedAction: string; now: number }): Promise<void> {
|
|
10
10
|
const effect = renderBandTransition(input, getSpawnCapableAgentIds());
|
|
11
11
|
emitRelayEvent(effect.event);
|
|
12
|
-
if (effect.notification) routeNotification(effect.notification);
|
|
12
|
+
if (effect.notification) await routeNotification(effect.notification);
|
|
13
13
|
}
|
package/src/recipe-runner.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createCommandAsync } from "./commands-write";
|
|
1
2
|
import { writeChildEnv } from "@humwick/sdk/env";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
|
-
import {
|
|
4
|
+
import { type CreateCommandWriteArgs } from "./commands-db";
|
|
4
5
|
import { effectiveProviderCatalogListAsync, listOrchestrators } from "./db";
|
|
5
6
|
import { resolveProviderSelection } from "@humwick/sdk/provider-catalog";
|
|
6
7
|
import { getRecipeAsync } from "./recipe-loader";
|
|
@@ -148,13 +149,13 @@ export async function stopRecipe(instanceId: string, stoppedBy = "cli"): Promise
|
|
|
148
149
|
// canceled by beginStop; a claimed one is already ordered before this stop and cannot be
|
|
149
150
|
// targeted with an agent.shutdown command until its spawn result supplies a real agent id.
|
|
150
151
|
if (agent.agentId.startsWith("pending:")) continue;
|
|
151
|
-
const command =
|
|
152
|
+
const command = (await createCommandAsync({
|
|
152
153
|
type: "agent.shutdown",
|
|
153
154
|
source: stoppedBy,
|
|
154
155
|
target: agent.agentId,
|
|
155
156
|
params: { recipeInstanceId: instance.id, role: agent.role },
|
|
156
157
|
ttlMs: 30_000,
|
|
157
|
-
});
|
|
158
|
+
}));
|
|
158
159
|
commands.push(command);
|
|
159
160
|
await updateRecipeAgentInstanceAsync(instance.id, agent.agentId, "stopping");
|
|
160
161
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { setConfigAsync } from "./config-store-write";
|
|
2
|
+
import { getConfig } from "./config-store";
|
|
2
3
|
import {
|
|
3
4
|
RETENTION_CONFIG_DEFAULTS,
|
|
4
5
|
RETENTION_KEY,
|
|
@@ -27,6 +28,6 @@ export function getRetentionConfigEntry(): ConfigEntry<RetentionConfig> {
|
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
export function setRetentionConfig(value: unknown, updatedBy?: string): ConfigEntry<RetentionConfig
|
|
31
|
-
return
|
|
31
|
+
export async function setRetentionConfig(value: unknown, updatedBy?: string): Promise<ConfigEntry<RetentionConfig>> {
|
|
32
|
+
return (await setConfigAsync(RETENTION_NAMESPACE, RETENTION_KEY, value as RetentionConfig, updatedBy));
|
|
32
33
|
}
|
package/src/reviewer-pipeline.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { createCommandAsync } from "./commands-write";
|
|
1
2
|
import { isRecord } from "@humwick/sdk";
|
|
2
3
|
import { planSend } from "./agent-ref";
|
|
3
|
-
|
|
4
|
+
|
|
4
5
|
import { getSpawnPolicy } from "./config-store";
|
|
5
6
|
import { deferLandSettleSideEffect } from "./land-settle-dispatch";
|
|
6
7
|
import { getLifecycleManager } from "./lifecycle-manager";
|
|
@@ -68,7 +69,7 @@ export async function handleReviewerMergeResult(command: Command, result: Record
|
|
|
68
69
|
// it must reach the reviewer even if they're offline a while — not a bystander notice. So, like the
|
|
69
70
|
// landing receipt, it is written SYNCHRONOUSLY on the settle path; only the bystander announcement
|
|
70
71
|
// ping and the eager spawn defer off the hot path below.
|
|
71
|
-
routeNotification({
|
|
72
|
+
await routeNotification({
|
|
72
73
|
type: "workspace.review_request",
|
|
73
74
|
scope: { workspaceId: workspace.id, repoRoot: workspace.repoRoot },
|
|
74
75
|
recipients: [target],
|
|
@@ -102,8 +103,8 @@ export async function handleReviewerMergeResult(command: Command, result: Record
|
|
|
102
103
|
// (`handleReviewerMergeResult` runs inside `settleWorkspaceMergeCommand`). They defer off the hot
|
|
103
104
|
// path; the spawn self-heals via `reconcilePolicy` even if a deferred dispatch is missed, and the
|
|
104
105
|
// review-request obligation it consumes is already durably queued synchronously above.
|
|
105
|
-
deferLandSettleSideEffect("reviewer-review-request", () => {
|
|
106
|
-
emitWorkspaceTaskSemanticNotifications({
|
|
106
|
+
deferLandSettleSideEffect("reviewer-review-request", async () => {
|
|
107
|
+
await emitWorkspaceTaskSemanticNotifications({
|
|
107
108
|
workspace: reviewWorkspace,
|
|
108
109
|
transition: "review-requested",
|
|
109
110
|
actor: "reviewer-pipeline",
|
|
@@ -144,7 +145,7 @@ export async function handleReviewerPipelineScan(
|
|
|
144
145
|
|
|
145
146
|
if (decision === "APPROVED") {
|
|
146
147
|
if (!prNumber && !prUrl) return { skipped: "missing-pr" };
|
|
147
|
-
const command =
|
|
148
|
+
const command = (await createCommandAsync({
|
|
148
149
|
type: "workspace.pr-arm-auto-merge",
|
|
149
150
|
source: "system",
|
|
150
151
|
target: orchestratorAgentId,
|
|
@@ -161,7 +162,7 @@ export async function handleReviewerPipelineScan(
|
|
|
161
162
|
requestedBy: "reviewer-pipeline",
|
|
162
163
|
requestedAt: now,
|
|
163
164
|
},
|
|
164
|
-
});
|
|
165
|
+
}));
|
|
165
166
|
await patchWorkspaceMetadataAsync(workspace.id, {
|
|
166
167
|
autoMergeArmed: true,
|
|
167
168
|
autoMergeArmCommandId: command.id,
|
|
@@ -176,7 +177,7 @@ export async function handleReviewerPipelineScan(
|
|
|
176
177
|
const last = text(workspace.metadata.lastReviewDecision);
|
|
177
178
|
if (last === "CHANGES_REQUESTED") return { skipped: "changes-requested-already-notified" };
|
|
178
179
|
const notifiedOwner = workspace.ownerAgentId
|
|
179
|
-
? notifyReviewChangesRequested(workspace, preview, prUrl, prNumber)
|
|
180
|
+
? await notifyReviewChangesRequested(workspace, preview, prUrl, prNumber)
|
|
180
181
|
: undefined;
|
|
181
182
|
await patchWorkspaceMetadataAsync(workspace.id, {
|
|
182
183
|
lastReviewDecision: decision,
|
|
@@ -198,17 +199,17 @@ function workspaceActiveArm(workspace: WorkspaceRecord): boolean {
|
|
|
198
199
|
return workspace.metadata.autoMergeArmed === true || typeof workspace.metadata.autoMergeArmCommandId === "string";
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
function notifyReviewChangesRequested(
|
|
202
|
+
async function notifyReviewChangesRequested(
|
|
202
203
|
workspace: WorkspaceRecord,
|
|
203
204
|
preview: WorkspaceMergePreview,
|
|
204
205
|
prUrl: string | undefined,
|
|
205
206
|
prNumber: number | undefined,
|
|
206
|
-
): string | undefined {
|
|
207
|
+
): Promise<string | undefined> {
|
|
207
208
|
const target = workspace.ownerAgentId;
|
|
208
209
|
if (!target) return undefined;
|
|
209
210
|
// Durable (ttl null): the owner must learn changes were requested on THEIR workspace even after
|
|
210
211
|
// being offline — store-ahead, not a freshness-gated bystander notice.
|
|
211
|
-
routeNotification({
|
|
212
|
+
await routeNotification({
|
|
212
213
|
type: "workspace.review_changes_requested",
|
|
213
214
|
scope: { workspaceId: workspace.id, repoRoot: workspace.repoRoot, author: target },
|
|
214
215
|
recipients: [target],
|
package/src/routes/_route.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { scopeResourceReads } from "./viewer-read";
|
|
2
|
-
import { captureSyncFrame
|
|
2
|
+
import { captureSyncFrame } from "../loop-block-attribution";
|
|
3
3
|
import { withRelayEventDrain } from "../relay-event-drain";
|
|
4
|
-
import {
|
|
4
|
+
import { runInFrame } from "../hub-metrics";
|
|
5
5
|
import { error, type Handler } from "./_shared";
|
|
6
6
|
import type { LoopCallsiteContext } from "../loop-block-attribution";
|
|
7
7
|
|
|
@@ -42,8 +42,8 @@ export function runMatchedRoute(
|
|
|
42
42
|
req: Request,
|
|
43
43
|
finish: (response: Response) => Promise<Response>,
|
|
44
44
|
): Promise<Response> {
|
|
45
|
-
return
|
|
46
|
-
finish(await captureSyncFrame(matched.loop.frame, () => matched.handler(req, matched.params)))))
|
|
45
|
+
return runInFrame(matched.loop.scope, () => withRelayEventDrain(async () =>
|
|
46
|
+
finish(await captureSyncFrame(matched.loop.frame, () => matched.handler(req, matched.params)))));
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
export function matchRoutes(
|
package/src/routes/_shared.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { sendMessageWithResultAsync } from "../db/message-send";
|
|
1
2
|
import { hasPresentedCredential, relayHeader, canonicalHumanAgentId, DEFAULT_USER_ID, errMessage, fireAndForget, isHumanAgentId, isRecord, userIdFromAddress, userSinkId } from "@humwick/sdk";
|
|
2
3
|
import { authorityDenied } from "../authority-audit";
|
|
3
4
|
// Auto-split from routes.ts (#299). Domain: _shared.
|
|
4
5
|
import { agentVisibleTo, visibleAgentIds, viewerScope, type ViewerScope } from "../db/viewer-scope";
|
|
5
6
|
import { MAX_BODY_BYTES, getIntegrationTokens } from "../config";
|
|
6
|
-
import { ValidationError, createActivityEventAsync, createCallbackDeliveryAsync, finishCallbackDeliveryAsync, getAgent, getTaskAsync, normalizeReactionEmoji
|
|
7
|
+
import { ValidationError, createActivityEventAsync, createCallbackDeliveryAsync, finishCallbackDeliveryAsync, getAgent, getTaskAsync, normalizeReactionEmoji } from "../db";
|
|
7
8
|
import { cleanEpoch, cleanString, optionalEnum } from "../validation";
|
|
8
9
|
import { emitActivityEvent, emitMessageQueued, emitNewMessage } from "../sse";
|
|
9
10
|
import { authorizeAgentForUser, type AgentAction } from "../agent-authz";
|
|
@@ -25,19 +26,19 @@ export const json = (data: unknown, status = 200) =>
|
|
|
25
26
|
export const error = (msg: string, status = 400) =>
|
|
26
27
|
json({ error: msg }, status);
|
|
27
28
|
|
|
28
|
-
export function authorizeRoute(req: Request, check: Parameters<typeof isRequestAuthorizedFor>[1]): Response | null {
|
|
29
|
+
export async function authorizeRoute(req: Request, check: Parameters<typeof isRequestAuthorizedFor>[1]): Promise<Response | null> {
|
|
29
30
|
if (!hasPresentedCredential(req)) return null;
|
|
30
|
-
return isRequestAuthorizedFor(req, check) ? null : authorityDenied(req, "forbidden");
|
|
31
|
+
return isRequestAuthorizedFor(req, check) ? null : (await authorityDenied(req, "forbidden"));
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/** A write about agent `agentId` by that agent's own credential: the agent, its agent:write check and the parsed body. */
|
|
34
35
|
export async function agentWriteRequest(req: Request, agentId: string): Promise<{ agent: NonNullable<ReturnType<typeof getAgent>>; body: Record<string, unknown> } | Response> {
|
|
35
36
|
const agent = getAgent(agentId);
|
|
36
37
|
if (!agent) return error("agent not found", 404);
|
|
37
|
-
const denied = authorizeRoute(req, {
|
|
38
|
+
const denied = (await authorizeRoute(req, {
|
|
38
39
|
scope: "agent:write",
|
|
39
40
|
resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
|
|
40
|
-
});
|
|
41
|
+
}));
|
|
41
42
|
if (denied) return denied;
|
|
42
43
|
const parsed = await parseBody<Record<string, unknown>>(req);
|
|
43
44
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
@@ -49,9 +50,9 @@ export async function agentWriteRequest(req: Request, agentId: string): Promise<
|
|
|
49
50
|
// `command:fleet`-scoped token is authorized here without the sandbox constraint; every other
|
|
50
51
|
// caller falls back to the normal constrained `command:write` check. Use ONLY at those three call
|
|
51
52
|
// sites — everywhere else must keep going through `authorizeRoute`.
|
|
52
|
-
export function authorizeFleetRoute(req: Request, resource?: Parameters<typeof isFleetActionAuthorized>[1]): Response | null {
|
|
53
|
+
export async function authorizeFleetRoute(req: Request, resource?: Parameters<typeof isFleetActionAuthorized>[1]): Promise<Response | null> {
|
|
53
54
|
if (!hasPresentedCredential(req)) return null;
|
|
54
|
-
return isFleetActionAuthorized(req, resource) ? null : authorityDenied(req, "forbidden");
|
|
55
|
+
return isFleetActionAuthorized(req, resource) ? null : (await authorityDenied(req, "forbidden"));
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function authAuditMetadata(req: Request): Record<string, unknown> {
|
|
@@ -181,8 +182,8 @@ export function requestUserAddress(req: Request): string {
|
|
|
181
182
|
* Single-user worlds fail-open inside {@link authorizeAgentForUser}, so existing routes are
|
|
182
183
|
* unchanged until #389 upgrades {@link requestUserId} to the real session user.
|
|
183
184
|
*/
|
|
184
|
-
export function authorizeAgentRoute(req: Request, agentId: string, action: AgentAction, auditAction: string = action): Response | null {
|
|
185
|
-
return authorizeAgentForUser(requestUserId(req), agentId, action) ? null : authorityDenied(req, "agent visibility or role", 403, agentId, auditAction);
|
|
185
|
+
export async function authorizeAgentRoute(req: Request, agentId: string, action: AgentAction, auditAction: string = action): Promise<Response | null> {
|
|
186
|
+
return authorizeAgentForUser(requestUserId(req), agentId, action) ? null : (await authorityDenied(req, "agent visibility or role", 403, agentId, auditAction));
|
|
186
187
|
}
|
|
187
188
|
|
|
188
189
|
/** Machine callers retain their existing reach; user sessions share one read scope. */
|
|
@@ -468,7 +469,7 @@ function reactionNotificationSender(parent: Message, actorId: string): string {
|
|
|
468
469
|
return parent.channel && getAgent(parent.channel) ? parent.channel : "user";
|
|
469
470
|
}
|
|
470
471
|
|
|
471
|
-
export function sendReactionNotificationToAuthor(parent: Message, actorId: string, emoji: string, action: "add" | "remove"): void {
|
|
472
|
+
export async function sendReactionNotificationToAuthor(parent: Message, actorId: string, emoji: string, action: "add" | "remove"): Promise<void> {
|
|
472
473
|
if (isHumanAgentId(parent.from) || parent.from === "system") return;
|
|
473
474
|
const targetAgent = getAgent(parent.from);
|
|
474
475
|
if (!targetAgent || targetAgent.kind === "channel") return;
|
|
@@ -477,7 +478,7 @@ export function sendReactionNotificationToAuthor(parent: Message, actorId: strin
|
|
|
477
478
|
const now = Date.now();
|
|
478
479
|
const actor = reactionActorView(actorId);
|
|
479
480
|
const verb = action === "remove" ? "removed reaction" : "reacted";
|
|
480
|
-
const result =
|
|
481
|
+
const result = (await sendMessageWithResultAsync({
|
|
481
482
|
from,
|
|
482
483
|
to: parent.from,
|
|
483
484
|
kind: "system",
|
|
@@ -505,7 +506,7 @@ export function sendReactionNotificationToAuthor(parent: Message, actorId: strin
|
|
|
505
506
|
},
|
|
506
507
|
},
|
|
507
508
|
},
|
|
508
|
-
});
|
|
509
|
+
}));
|
|
509
510
|
if (result.created) {
|
|
510
511
|
if (result.message.deliveryStatus === "queued") emitMessageQueued(result.message);
|
|
511
512
|
else emitNewMessage(result.message);
|
|
@@ -13,12 +13,12 @@ import { agentWriteRequest, authAuditMetadata, authorizeAgentRoute, authorizeRou
|
|
|
13
13
|
export async function postAgentEffortAction(req: Request, agentId: string, body: Record<string, unknown>): Promise<Response> {
|
|
14
14
|
const agent = getAgent(agentId);
|
|
15
15
|
if (!agent) return error("agent not found", 404);
|
|
16
|
-
const driveDenied = authorizeAgentRoute(req, agent.id, "drive", "effort");
|
|
16
|
+
const driveDenied = (await authorizeAgentRoute(req, agent.id, "drive", "effort"));
|
|
17
17
|
if (driveDenied) return driveDenied;
|
|
18
|
-
const denied = authorizeRoute(req, {
|
|
18
|
+
const denied = (await authorizeRoute(req, {
|
|
19
19
|
scope: "agent:write",
|
|
20
20
|
resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
|
|
21
|
-
});
|
|
21
|
+
}));
|
|
22
22
|
if (denied) return denied;
|
|
23
23
|
try {
|
|
24
24
|
const result = await dispatchAgentAction({
|
|
@@ -54,12 +54,12 @@ export const postAgentEffortObservedRoute: Handler = async (req, params) => {
|
|
|
54
54
|
try {
|
|
55
55
|
const version = body.version;
|
|
56
56
|
if (typeof version !== "number" || !Number.isSafeInteger(version) || version < 1) throw new ValidationError("version must be a positive integer");
|
|
57
|
-
const observed = reportEffortObserved(agent.id, {
|
|
57
|
+
const observed = (await reportEffortObserved(agent.id, {
|
|
58
58
|
instanceId: cleanString(body.instanceId, "instanceId", { required: true, max: 200 })!,
|
|
59
59
|
version,
|
|
60
60
|
effort: cleanString(body.effort, "effort", { required: true, max: 32 })!,
|
|
61
61
|
previousEffort: cleanString(body.previousEffort, "previousEffort", { max: 32 }) ?? null,
|
|
62
|
-
});
|
|
62
|
+
}));
|
|
63
63
|
return json(observed);
|
|
64
64
|
} catch (e) {
|
|
65
65
|
if (e instanceof ValidationError || e instanceof EffortReportRejected) return error(e.message, 400);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { HeartbeatResult, ProviderQuotaUpdateInput } from "@humwick/sdk";
|
|
2
|
+
import { acquireProviderQuotaLeaseAsync } from "../db";
|
|
3
|
+
import { getProviderQuotaConfig } from "../provider-quota-config-store";
|
|
4
|
+
import { upsertProviderQuotaAsync } from "../provider-quota-async";
|
|
5
|
+
import { emitRelayEvent } from "../events";
|
|
6
|
+
|
|
7
|
+
/** Same lease and writer as standalone quota reports, with config resolved on the hub (#3608). */
|
|
8
|
+
export async function publishHeartbeatQuota(input: ProviderQuotaUpdateInput, leaseToken?: string): Promise<NonNullable<HeartbeatResult["providerQuota"]>> {
|
|
9
|
+
const config = getProviderQuotaConfig(input.provider);
|
|
10
|
+
if (!config.enabled) return { reported: false, retryAfterMs: 60_000 };
|
|
11
|
+
const holder = `runner:${input.sourceAgentId}`;
|
|
12
|
+
const lease = await acquireProviderQuotaLeaseAsync({
|
|
13
|
+
provider: input.provider, accountKey: input.accountKey, orchestratorId: holder, leaseToken,
|
|
14
|
+
ttlMs: Math.min(10 * 60_000, config.pollIntervalMs + 60_000),
|
|
15
|
+
});
|
|
16
|
+
if (!lease.acquired || !lease.lease) return { reported: false, retryAfterMs: Math.min(lease.retryAfterMs ?? config.pollIntervalMs, config.pollIntervalMs) };
|
|
17
|
+
const result = await upsertProviderQuotaAsync(input, { requiredLeaseHolder: holder });
|
|
18
|
+
if (result.outcome.kind === "stored") {
|
|
19
|
+
const record = result.outcome.record;
|
|
20
|
+
emitRelayEvent({ type: "provider-quota.updated", source: "server", subject: `${record.provider}:${record.accountKey}`, data: {} });
|
|
21
|
+
}
|
|
22
|
+
return { reported: result.outcome.kind === "stored", retryAfterMs: config.pollIntervalMs, leaseToken: lease.lease.leaseToken };
|
|
23
|
+
}
|
package/src/routes/agent-keep.ts
CHANGED
|
@@ -9,7 +9,7 @@ export const putAgentKeep: Handler = async (req, params) => {
|
|
|
9
9
|
const parsed = await parseBody<unknown>(req);
|
|
10
10
|
if (!parsed.ok) return error(parsed.error, parsed.status);
|
|
11
11
|
if (!isRecord(parsed.body)) return error("keep required");
|
|
12
|
-
const denied = authorizeRoute(req, { scope: "agent:write" });
|
|
12
|
+
const denied = (await authorizeRoute(req, { scope: "agent:write" }));
|
|
13
13
|
if (denied) return denied;
|
|
14
14
|
try {
|
|
15
15
|
const result = await setAgentKeep({
|
|
@@ -6,7 +6,7 @@ import { cleanString } from "../validation";
|
|
|
6
6
|
import { authorizeAgentRoute, authorizeRoute, error, json } from "./_shared";
|
|
7
7
|
|
|
8
8
|
export async function postAgentReportingAction(req: Request, agentId: string, body: Record<string, unknown>): Promise<Response> {
|
|
9
|
-
const denied = authorizeAgentRoute(req, agentId, "drive") ?? authorizeRoute(req, { scope: "agent:write", resource: { agentId } });
|
|
9
|
+
const denied = (await authorizeAgentRoute(req, agentId, "drive")) ?? (await authorizeRoute(req, { scope: "agent:write", resource: { agentId } }));
|
|
10
10
|
if (denied) return denied;
|
|
11
11
|
try {
|
|
12
12
|
return json({ ok: true, ...await setAgentReportVerbosity({ agentId, reportVerbosity: body.reportVerbosity, reason: cleanString(body.reason, "reason", { max: 500 }), requestedVia: "http" }, authContextFromRequest(req)) });
|
|
@@ -9,10 +9,10 @@ import { ShutdownAuthError, ShutdownTargetError } from "../services/shutdown-age
|
|
|
9
9
|
import { authAuditMetadata, authorizeAgentRoute, authorizeRoute, dashboardAttribution, error, json, metaString, parseBody, requestUserAddress, type Handler } from "./_shared";
|
|
10
10
|
import { isRecord } from "../types";
|
|
11
11
|
|
|
12
|
-
export const getAgentSelfEffort: Handler = (req, params) => {
|
|
12
|
+
export const getAgentSelfEffort: Handler = async (req, params) => {
|
|
13
13
|
const agent = getAgent(params.id!);
|
|
14
14
|
if (!agent) return error("agent not found", 404);
|
|
15
|
-
const denied = authorizeAgentRoute(req, agent.id, "view");
|
|
15
|
+
const denied = (await authorizeAgentRoute(req, agent.id, "view"));
|
|
16
16
|
if (denied) return denied;
|
|
17
17
|
return json({ agentId: agent.id, selfEffort: spawnSelfEffortPolicy(agent) ?? null });
|
|
18
18
|
};
|
|
@@ -24,12 +24,12 @@ export const putAgentSelfEffort: Handler = async (req, params) => {
|
|
|
24
24
|
const body = parsed.body;
|
|
25
25
|
const agent = getAgent(params.id!);
|
|
26
26
|
if (!agent) return error("agent not found", 404);
|
|
27
|
-
const driveDenied = authorizeAgentRoute(req, agent.id, "drive");
|
|
27
|
+
const driveDenied = (await authorizeAgentRoute(req, agent.id, "drive"));
|
|
28
28
|
if (driveDenied) return driveDenied;
|
|
29
|
-
const denied = authorizeRoute(req, {
|
|
29
|
+
const denied = (await authorizeRoute(req, {
|
|
30
30
|
scope: "agent:write",
|
|
31
31
|
resource: { agentId: agent.id, policyName: metaString(agent.meta, "policyName"), spawnRequestId: metaString(agent.meta, "spawnRequestId") },
|
|
32
|
-
});
|
|
32
|
+
}));
|
|
33
33
|
if (denied) return denied;
|
|
34
34
|
try {
|
|
35
35
|
const result = await grantSelfEffort({
|