@humwick/server 0.130.2 → 0.130.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/prompts/manifest.json +1 -0
- package/bundled/prompts/task.hydration.md +1 -1
- package/bundled/roles/builder.md +1 -1
- package/docs/guides/sub-coordinators.md +12 -5
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/workflows.md +16 -0
- package/docs/openapi.json +73 -4
- package/package.json +8 -7
- package/public/assets/{MessageBubble-BWLqMGKG.js → MessageBubble-Bq9kr21N.js} +2 -2
- package/public/assets/{PlanGraphPanel-3TlIQpjk.js → PlanGraphPanel-Dqiroy06.js} +2 -2
- package/public/assets/{TraceView-Wimm0Czv.js → TraceView-DYU962-H.js} +2 -2
- package/public/assets/{VaultDecisionCard-Bau_vNax.js → VaultDecisionCard-DhPfzioE.js} +2 -2
- package/public/assets/{activity-CrSurn-r.js → activity-DzCcQTee.js} +2 -2
- package/public/assets/{agent-lineage-CknAJKcb.js → agent-lineage-SgDt9i3T.js} +2 -2
- package/public/assets/agent-liveness-Bq-s73jW.js +2 -0
- package/public/assets/{agent-name-DKbiIhBo.js → agent-name-CcY3Aijy.js} +2 -2
- package/public/assets/{agent-profiles-DwF6EQ4R.js → agent-profiles-cxtRBn6O.js} +2 -2
- package/public/assets/{agent-project-badge-Diz4Sjjb.js → agent-project-badge-DGYbIhaI.js} +2 -2
- package/public/assets/{agent-tools-CRhpRQza.js → agent-tools-DHbftV0N.js} +2 -2
- package/public/assets/{agent-type-icon-LrUEU3lB.js → agent-type-icon-CY113sp-.js} +2 -2
- package/public/assets/{agents-B-v66C-4.js → agents-BPzY7IlQ.js} +2 -2
- package/public/assets/{analytics-BqCb-LKi.js → analytics-DENFPv_a.js} +2 -2
- package/public/assets/{artifact-viewer-kf4pGuAR.js → artifact-viewer-KRvSc7sl.js} +2 -2
- package/public/assets/{artifacts-DJevXcvg.js → artifacts-C9gSmL3s.js} +2 -2
- package/public/assets/{artifacts-D32zyw4Y.js → artifacts-DT-HkI5O.js} +2 -2
- package/public/assets/{automation-BpRajx_5.js → automation-BsmjQhKD.js} +2 -2
- package/public/assets/{backlog-D_UjTdzX.js → backlog-8NYH_62t.js} +2 -2
- package/public/assets/{busy-health-N3VEh4ao.js → busy-health-D3hwvYb4.js} +2 -2
- package/public/assets/{channels-9jopungq.js → channels-DCJ5WL7O.js} +2 -2
- package/public/assets/{chat-CSXrTB3C.js → chat-DAIl357U.js} +3 -3
- package/public/assets/{code-preview-p1NnmqK0.js → code-preview-CzrZfr9U.js} +2 -2
- package/public/assets/{connectors-CZdqlDNL.js → connectors-xTxtlyou.js} +2 -2
- package/public/assets/{cosmos-BgdsE4dG.js → cosmos-BpebFLK2.js} +2 -2
- package/public/assets/{crate-agent-30aXTKva.js → crate-agent-BHvI5wXC.js} +2 -2
- package/public/assets/{dependency-graph-B_jvw2GE.js → dependency-graph-DGT0o3wJ.js} +2 -2
- package/public/assets/{deploys-DoN6bAb5.js → deploys-hqWOHSHE.js} +2 -2
- package/public/assets/{display-BrKWFGJz.js → display-CDeH4I8T.js} +2 -2
- package/public/assets/{files-D6XEu8Ng.js → files-BTeGVmTg.js} +2 -2
- package/public/assets/{fleet-C7jQWbw2.js → fleet-DgXtNgCa.js} +2 -2
- package/public/assets/{fleet-metrics-BiDs3MLx.js → fleet-metrics-BHEt5yc_.js} +2 -2
- package/public/assets/{formatted-body-CQBwc1fb.js → formatted-body-MLtodyPp.js} +3 -3
- package/public/assets/{formatted-body-impl-DyG0WsQS.js → formatted-body-impl-CAe664Z8.js} +2 -2
- package/public/assets/{host-providers-dialog-DKaW31dN.js → host-providers-dialog-mapF4Fj9.js} +2 -2
- package/public/assets/{index-CRHep3M9.js → index-CqqgOI5R.js} +5 -5
- package/public/assets/{insights-CzrtkpOE.js → insights-DNyf7IzF.js} +2 -2
- package/public/assets/{integrations-aVsUmigt.js → integrations-DlYOHq7T.js} +2 -2
- package/public/assets/{issue-ref-chip-BnSlM_95.js → issue-ref-chip-CeWBNWn7.js} +2 -2
- package/public/assets/{log-viewer-qe7Ee47Z.js → log-viewer-Cib8nqdE.js} +2 -2
- package/public/assets/{maintenance-NfjqFZAk.js → maintenance-DSn1cPm7.js} +2 -2
- package/public/assets/{managed-agents-BiH0HgaE.js → managed-agents-C3CkM81m.js} +2 -2
- package/public/assets/{markdown-preview-BixaT3Xr.js → markdown-preview-W4VQQPAv.js} +3 -3
- package/public/assets/{markdown-preview-impl-DNGlWIS3.js → markdown-preview-impl-CMsTdhjq.js} +2 -2
- package/public/assets/{memory-DNsCl6UX.js → memory-BV17qtO4.js} +2 -2
- package/public/assets/{messages-DopU1L1X.js → messages-Bm_1AqSA.js} +2 -2
- package/public/assets/{orchestrators-Cq7ckLQT.js → orchestrators-Dg-vfP09.js} +2 -2
- package/public/assets/{overview-C1DCTzzV.js → overview-DcYCrvlr.js} +2 -2
- package/public/assets/{pairs-DE_m6rrE.js → pairs-8o9nuG3V.js} +2 -2
- package/public/assets/{profile-icon-B3rfh77F.js → profile-icon-BsRyBMea.js} +2 -2
- package/public/assets/{project-profile-instructions-DQWZE0kA.js → project-profile-instructions-DETKFn_E.js} +2 -2
- package/public/assets/{projects-Br2Bd2h1.js → projects-M_m6AHws.js} +2 -2
- package/public/assets/{prompt-settings-BKvFsvGD.js → prompt-settings-C_mNCgeL.js} +2 -2
- package/public/assets/provider-display-BEeLXC_D.js +2 -0
- package/public/assets/{registry-Cw38_6gW.js → registry-DDHHHE5N.js} +2 -2
- package/public/assets/run-card-Dt4I4jaP.js +2 -0
- package/public/assets/{secrets-DxI-vzSq.js → secrets-BkVwxI5O.js} +2 -2
- package/public/assets/{service-access-settings-D9s_VJbd.js → service-access-settings-Crq-6a-B.js} +2 -2
- package/public/assets/{settings-CKZTVGIx.js → settings-CYcavMFu.js} +2 -2
- package/public/assets/shipping-H6gzEeZB.js +2 -0
- package/public/assets/{stats-DyUBKyWI.js → stats-BJVeWkpV.js} +2 -2
- package/public/assets/{status-dot-DYqlEUhJ.js → status-dot-BcHyw1Vw.js} +2 -2
- package/public/assets/store-DKPDIZBe.js +9 -0
- package/public/assets/{tasks-Bh7Chr4-.js → tasks-qJjlQPpx.js} +2 -2
- package/public/assets/{teams-bowI7qVY.js → teams-Cd5Sk1uX.js} +2 -2
- package/public/assets/{terminal-viewer-BgVLHdsU.js → terminal-viewer-CpY5_m7W.js} +3 -3
- package/public/assets/{terminal-viewer-impl-Dz22UPy6.js → terminal-viewer-impl-DI_2llFR.js} +2 -2
- package/public/assets/{use-agent-terminal-DSQQ-iY7.js → use-agent-terminal-0yJA_buM.js} +2 -2
- package/public/assets/{use-decisions-samMQhQf.js → use-decisions-uJXHf34W.js} +2 -2
- package/public/assets/{use-project-list-59LheVP7.js → use-project-list-CpWl6eHQ.js} +2 -2
- package/public/assets/{use-selectors-BZa25xEB.js → use-selectors-BdxBW8mL.js} +2 -2
- package/public/assets/{user-avatar-DHxlvUvV.js → user-avatar-3IndfpOc.js} +2 -2
- package/public/assets/{versioned-prompt-editor-BmED5DnJ.js → versioned-prompt-editor-CIVg7XB1.js} +2 -2
- package/public/assets/{work-queue-CSvpuNLz.js → work-queue-B9rnLwHZ.js} +2 -2
- package/public/assets/{workflow-marker-DAZcj5qt.js → workflow-marker-X8wxyhzC.js} +2 -2
- package/public/assets/{workflows-DdmxRSyg.js → workflows-o5YyMFW7.js} +2 -2
- package/public/assets/{workspaces-BxeKfVuF.js → workspaces-CzEGoAng.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +28 -28
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/src/adapters/claude-headless.ts +1 -1
- package/runner/src/adapters/claude-launch-exit.ts +26 -0
- package/runner/src/adapters/claude-session-probe.ts +1 -1
- package/runner/src/adapters/claude-tmux.ts +38 -10
- package/runner/src/adapters/claude.ts +28 -75
- package/runner/src/adapters/provider-quota-harvest.ts +20 -71
- package/runner/src/agent-runner/lifecycle-milestones.ts +2 -2
- package/runner/src/agent-runner/liveness-exchange.ts +104 -0
- package/runner/src/claude-system-prompt.ts +49 -0
- package/runner/src/launch-assembly.ts +14 -10
- package/runner/src/profile-home.ts +1 -1
- package/runner/src/project-instructions.ts +2 -2
- package/runner/src/provider-command.ts +18 -0
- package/runner/src/provider-setup.ts +2 -1
- package/runner/src/runner-core.ts +14 -15
- package/runner/src/runner-helpers.ts +0 -8
- package/runner/src/session-scratch.ts +6 -2
- package/runner/test-support/provisioning-context.ts +4 -2
- package/runner/test-support/runner-harness.ts +2 -1
- package/scripts/steward-policy-cleanup.ts +2 -2
- package/src/agent-authz.ts +2 -2
- package/src/agent-drive-arbiter.ts +3 -8
- package/src/agent-exit-cleanup-async.ts +2 -2
- package/src/agent-exit-cleanup.ts +23 -19
- package/src/agent-lifecycle-events.ts +112 -85
- package/src/agent-ref.ts +3 -2
- package/src/agent-status-events.ts +43 -14
- package/src/auth/password.ts +4 -3
- package/src/auth/session-refresh.ts +1 -1
- package/src/auth/session.test-fixture.ts +2 -2
- package/src/auth/session.ts +7 -7
- package/src/automations/crud.ts +8 -81
- package/src/automations/dispatch.ts +33 -58
- package/src/automations/index.ts +1 -1
- package/src/automations/persistence.ts +65 -0
- package/src/automations/precheck.ts +18 -16
- package/src/automations/read-async.ts +11 -0
- package/src/automations/reconcile.ts +30 -39
- package/src/automations/storage.ts +33 -10
- package/src/automations/write-async.ts +33 -0
- package/src/branch-land-notice.ts +3 -3
- package/src/branch-landed.ts +25 -23
- package/src/bus.ts +21 -19
- package/src/cd-deploy-notify.ts +2 -2
- package/src/ci/notifications.ts +4 -4
- package/src/ci/root-missing.ts +3 -3
- package/src/ci/transition-notify.ts +5 -5
- package/src/claude-app/oauth-http.ts +3 -3
- package/src/cli/workflow.ts +12 -3
- package/src/commands-db.ts +4 -4
- package/src/commands-write.ts +8 -0
- package/src/compaction-watch.ts +10 -8
- package/src/config-store-write.ts +2 -2
- package/src/config.ts +4 -11
- package/src/connectors.ts +10 -8
- package/src/context-advisory.ts +22 -21
- package/src/db/agent-action-write.ts +36 -0
- package/src/db/agent-control-async.ts +9 -0
- package/src/db/agent-control-write.ts +49 -0
- package/src/db/agent-effort-observe.ts +22 -0
- package/src/db/agent-meta.ts +14 -3
- package/src/db/agents-async.ts +8 -5
- package/src/db/agents.ts +15 -12
- package/src/db/auth-identities.ts +2 -2
- package/src/db/automation-read-ops.ts +11 -0
- package/src/db/automation-write-ops.ts +46 -0
- package/src/db/blackboard.ts +2 -2
- package/src/db/browser-session-write.ts +32 -0
- package/src/db/bus-outbox-write-ops.ts +3 -1
- package/src/db/checkout-refresh-schema.ts +47 -0
- package/src/db/checkout-refresh.ts +5 -5
- package/src/db/command-agent-profile-backfill.ts +39 -0
- package/src/db/command-agent-profiles.ts +5 -1
- package/src/db/command-retention.ts +126 -0
- package/src/db/commands-planner-stats.test-fixture.ts +8 -0
- package/src/db/commands-read-ops.ts +16 -0
- package/src/db/connection.ts +1 -182
- package/src/db/context-carry-write.ts +74 -0
- package/src/db/continuations.ts +4 -4
- package/src/db/db-error-registry.ts +12 -0
- package/src/db/gateway.ts +26 -133
- package/src/db/history-retention-ops.ts +13 -0
- package/src/db/inbox-async.ts +2 -2
- package/src/db/inbox-read-ops.ts +1 -1
- package/src/db/inbox.ts +9 -3
- package/src/db/issue-associations.ts +2 -2
- package/src/db/issue-refs-async.ts +4 -1
- package/src/db/issue-refs-read-ops.ts +6 -0
- package/src/db/issue-refs.ts +8 -8
- package/src/db/kernel-event-log-schema.ts +2 -0
- package/src/db/land-boundaries.ts +51 -5
- package/src/db/land-gate-attestations.ts +2 -2
- package/src/db/landing-receipts.ts +2 -2
- package/src/db/lifecycle-context-write.ts +5 -0
- package/src/db/lifecycle-tail-async.ts +76 -0
- package/src/db/lifecycle-tail-write-ops.ts +62 -0
- package/src/db/lifecycle-write-window.ts +2 -1
- package/src/db/lineage-pair-dedupe-sql.ts +3 -3
- package/src/db/main-connection-mode.ts +11 -0
- package/src/db/main-connection-writes.ts +20 -2
- package/src/db/maintenance-job-runs-async.ts +2 -2
- package/src/db/maintenance-job-write-ops.ts +1 -1
- package/src/db/maintenance-pauses.ts +2 -2
- package/src/db/message-send.ts +4 -0
- package/src/db/messages.ts +31 -25
- package/src/db/migrations.ts +18 -1
- package/src/db/notification-write-ops.ts +19 -0
- package/src/db/operator-answer-write.ts +19 -0
- package/src/db/orchestrators.ts +10 -4
- package/src/db/pairs-async.ts +22 -1
- package/src/db/pairs-write-ops.ts +8 -3
- package/src/db/pairs.ts +41 -48
- package/src/db/plan-dispatch-schema.ts +5 -1
- package/src/db/plan-ready-notices.ts +43 -0
- package/src/db/plan-tools-include-migration.ts +36 -0
- package/src/db/plans-write-ops.ts +2 -0
- package/src/db/presence-buffer.ts +5 -0
- package/src/db/presence-loop.ts +18 -23
- package/src/db/presence-write.ts +0 -6
- package/src/db/project-entries-async.ts +14 -0
- package/src/db/project-entries-read-ops.ts +5 -1
- package/src/db/project-entries-write-ops.ts +8 -0
- package/src/db/project-entries.ts +15 -12
- package/src/db/project-journal.ts +2 -2
- package/src/db/project-trust-approvals.ts +2 -2
- package/src/db/prompt-templates.ts +4 -4
- package/src/db/read-op-marshaling-fixtures.ts +18 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/retention.ts +13 -2
- package/src/db/review-publish-write.ts +8 -0
- package/src/db/runtime-admin-async.ts +19 -0
- package/src/db/runtime-admin-write-ops.ts +36 -0
- package/src/db/runtime-tail-async.ts +288 -0
- package/src/db/runtime-tail-write-ops.ts +97 -0
- package/src/db/schema.ts +4 -1
- package/src/db/spawn-budget.ts +5 -0
- package/src/db/spawn-delegation.ts +1 -11
- package/src/db/sql-audit-indexes.ts +3 -0
- package/src/db/stats-async.ts +5 -3
- package/src/db/task-entity.ts +5 -4
- package/src/db/team-claim-policy.ts +60 -0
- package/src/db/teams-async.ts +4 -0
- package/src/db/teams-write-ops.ts +4 -0
- package/src/db/terminal-events.ts +15 -0
- package/src/db/timer-cutover-bodies.ts +292 -0
- package/src/db/timer-cutover-core.ts +37 -278
- package/src/db/timer-cutover-state.ts +40 -0
- package/src/db/timer-cutover-write-ops.ts +1 -40
- package/src/db/token-db-write-ops.ts +2 -0
- package/src/db/token-standing-async.ts +12 -0
- package/src/db/token-standing.ts +6 -9
- package/src/db/token-usage-retention.ts +33 -0
- package/src/db/token-usage-write-ops.ts +1 -1
- package/src/db/token-usage.ts +4 -1
- package/src/db/user-invites-async.ts +13 -0
- package/src/db/user-invites.ts +3 -3
- package/src/db/users.ts +14 -6
- package/src/db/workspaces.ts +8 -5
- package/src/db/write-ops.ts +31 -12
- package/src/db/writer-fault-seam.ts +2 -9
- package/src/db/writer-fault-test-ops.ts +18 -0
- package/src/db/writer-gateway.ts +42 -46
- package/src/dev.ts +8 -3
- package/src/event-loop-lag.ts +4 -2
- package/src/event-loop-yield.ts +2 -2
- package/src/events.ts +10 -8
- package/src/host-provider-store.ts +5 -4
- package/src/hub-metrics-report.ts +5 -1
- package/src/hub-metrics.ts +38 -18
- package/src/injection-sweep-pacing.ts +6 -8
- package/src/land-gate-notifications.ts +11 -10
- package/src/land-gate-queue-progress.ts +3 -3
- package/src/land-settle-dispatch.ts +52 -92
- package/src/lifecycle-context-pressure.ts +11 -10
- package/src/lifecycle-manager.ts +104 -98
- package/src/maintenance/breaker.ts +18 -16
- package/src/maintenance/checkout-refresh.ts +18 -1
- package/src/maintenance/critical-job-watchdog.ts +3 -3
- package/src/maintenance/events.ts +3 -3
- package/src/maintenance/history-retention-job.ts +30 -0
- package/src/maintenance/jobs.ts +29 -67
- package/src/maintenance/long-running-work.ts +3 -1
- package/src/maintenance/offline-agent-prune-job.ts +28 -0
- package/src/maintenance/orphaned-sessions.ts +5 -4
- package/src/maintenance/pauses.ts +4 -10
- package/src/maintenance/plan-ready-notice-job.ts +71 -0
- package/src/maintenance/scheduler.ts +18 -13
- package/src/maintenance/stalled-delivery-pager.ts +4 -4
- package/src/maintenance/teams.ts +19 -30
- package/src/maintenance/workspaces.ts +17 -27
- package/src/managed-policy-escalation.ts +7 -7
- package/src/managed-policy.ts +3 -3
- package/src/managed-provider-gate.ts +5 -4
- package/src/managed-spawn-reservation.ts +5 -4
- package/src/mcp/index.ts +8 -8
- package/src/mcp/output-descriptions.ts +1 -1
- package/src/mcp/presentation.ts +2 -1
- package/src/mcp/runtime-output.ts +6 -1
- package/src/mcp/self-care-visibility.ts +2 -2
- package/src/mcp/spawn-targets-matrix.ts +10 -1
- package/src/mcp/tool-groups.ts +3 -2
- package/src/mcp/tool-roles.ts +81 -0
- package/src/mcp/tools-workspace.ts +1 -1
- package/src/mcp-blackboard-tools.ts +6 -5
- package/src/mcp-decision-tools.ts +7 -7
- package/src/mcp-egress-tools.ts +10 -9
- package/src/mcp-issue-activity-tools.ts +2 -2
- package/src/mcp-issue-association-tools.ts +4 -4
- package/src/mcp-issue-ref-tools.ts +3 -3
- package/src/mcp-merge-tools.ts +5 -5
- package/src/mcp-notification-subscription-tools.ts +14 -15
- package/src/mcp-output-levels.test-fixture.ts +1 -1
- package/src/mcp-profile-trust-tools.ts +1 -1
- package/src/mcp-project-journal-tools.ts +4 -12
- package/src/mcp-project-tools.ts +17 -18
- package/src/mcp-routing-policy-tools.ts +3 -2
- package/src/mcp-team-tools.ts +6 -6
- package/src/mcp-workflow-tools.ts +5 -3
- package/src/memory-area-injection.ts +13 -12
- package/src/memory-boundary-capture.ts +6 -6
- package/src/memory-injection.ts +45 -43
- package/src/merge-pause-maintenance.ts +5 -4
- package/src/notification-router.ts +44 -17
- package/src/notify.ts +5 -5
- package/src/observed-reset-refresh.ts +4 -4
- package/src/operator-alarm.ts +2 -5
- package/src/project-ingest.ts +6 -6
- package/src/project-instructions.ts +8 -1
- package/src/project-trust.ts +12 -11
- package/src/prompt-resolver.ts +3 -3
- package/src/provider-quota-async.ts +5 -7
- package/src/provider-timeline-event.ts +4 -7
- package/src/quota-band-delivery.ts +2 -2
- package/src/recipe-runner.ts +4 -3
- package/src/retention-config-store.ts +4 -3
- package/src/reviewer-pipeline.ts +11 -10
- package/src/routes/_route.ts +4 -4
- package/src/routes/_shared.ts +13 -12
- package/src/routes/agent-effort.ts +5 -5
- package/src/routes/agent-heartbeat-quota.ts +23 -0
- package/src/routes/agent-keep.ts +1 -1
- package/src/routes/agent-reporting.ts +1 -1
- package/src/routes/agent-self-effort.ts +5 -5
- package/src/routes/agent-sessions.ts +24 -24
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +17 -119
- package/src/routes/auth.ts +14 -15
- package/src/routes/authority-audit.ts +2 -2
- package/src/routes/automations.ts +6 -5
- package/src/routes/channel-binding-delete.ts +1 -1
- package/src/routes/channel-output.ts +3 -3
- package/src/routes/claude-api-budget.ts +5 -5
- package/src/routes/commands-listing.ts +1 -1
- package/src/routes/commands.ts +29 -27
- package/src/routes/context-resets.ts +2 -2
- package/src/routes/coordinator-teams.ts +1 -1
- package/src/routes/decisions.ts +2 -2
- package/src/routes/host-secret-files.ts +1 -1
- package/src/routes/hosts.ts +11 -11
- package/src/routes/inbox.ts +3 -2
- package/src/routes/index.ts +2 -1
- package/src/routes/integrations.ts +9 -7
- package/src/routes/issue-activity.ts +2 -2
- package/src/routes/issue-associations.ts +4 -4
- package/src/routes/issue-refs.ts +3 -3
- package/src/routes/kernel-timers-operator.ts +1 -1
- package/src/routes/memory.ts +1 -1
- package/src/routes/merges.ts +11 -11
- package/src/routes/messages.ts +23 -17
- package/src/routes/orchestrator-bootstrap.ts +1 -1
- package/src/routes/orchestrator-host-registration.ts +2 -0
- package/src/routes/orchestrator-host-utilization.ts +2 -2
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +27 -18
- package/src/routes/pairs.ts +8 -8
- package/src/routes/project-profile-instructions.ts +1 -1
- package/src/routes/project-trust.ts +1 -1
- package/src/routes/projects.ts +16 -16
- package/src/routes/prompt-templates.ts +12 -12
- package/src/routes/provider-quotas.ts +10 -10
- package/src/routes/run-command.ts +1 -1
- package/src/routes/secrets-backup.ts +2 -2
- package/src/routes/secrets-import.ts +1 -1
- package/src/routes/secrets-vault.ts +7 -7
- package/src/routes/settings.ts +1 -1
- package/src/routes/shipping.ts +9 -1
- package/src/routes/spawn-policy.ts +8 -7
- package/src/routes/sse.ts +2 -2
- package/src/routes/team-templates.ts +7 -7
- package/src/routes/teams.ts +10 -10
- package/src/routes/tokens.ts +18 -17
- package/src/routes/users.ts +24 -24
- package/src/routes/viewer-read.ts +3 -3
- package/src/routes/web-tool-calls.ts +4 -4
- package/src/routes/workflows.ts +2 -2
- package/src/routes/workspaces.ts +17 -16
- package/src/routing-policy-push.ts +6 -6
- package/src/runtime-grant.ts +17 -11
- package/src/runtime-tokens.ts +20 -28
- package/src/secrets-broker/config.ts +1 -1
- package/src/secrets-broker/service.ts +2 -2
- package/src/security.ts +3 -1
- package/src/self-resume-carry.ts +21 -110
- package/src/self-resume-supersede.ts +4 -3
- package/src/self-resume.ts +54 -66
- package/src/server-background.ts +1 -1
- package/src/server.ts +21 -22
- package/src/services/agent-action.ts +12 -31
- package/src/services/agent-effort.ts +7 -32
- package/src/services/agent-hang-watchdog-job.ts +2 -2
- package/src/services/agent-heartbeat.ts +166 -0
- package/src/services/agent-reporting.ts +1 -1
- package/src/services/browser-inventory.ts +3 -3
- package/src/services/browser-session-state.ts +3 -2
- package/src/services/browser-session.ts +21 -27
- package/src/services/bus-command-update.ts +9 -9
- package/src/services/checkout-refresh-state.ts +1 -0
- package/src/services/checkout-refresh.test-fixture.ts +3 -2
- package/src/services/command-host.ts +7 -2
- package/src/services/coordinator-digest.ts +3 -2
- package/src/services/dispatch-command.ts +12 -13
- package/src/services/effective-launch-driver.ts +14 -9
- package/src/services/host-changed-paths.test-fixture.ts +5 -6
- package/src/services/host-project-readiness.ts +2 -2
- package/src/services/host-providers.ts +1 -1
- package/src/services/host-utilization.ts +9 -9
- package/src/services/idle-agent-digest.ts +17 -12
- package/src/services/idle-epics.ts +4 -4
- package/src/services/interrupt-agent.ts +12 -9
- package/src/services/issue-activity.ts +3 -3
- package/src/services/issue-associations.ts +15 -18
- package/src/services/issue-lifecycle-comments.ts +3 -2
- package/src/services/issue-lifecycle.ts +14 -13
- package/src/services/issue-refs.ts +4 -5
- package/src/services/kernel-timers-cutover-chaos-worker.ts +1 -1
- package/src/services/kernel-timers-ingress-chaos-worker.ts +6 -1
- package/src/services/kernel-timers-ingress.ts +3 -3
- package/src/services/kernel-timers-message-authority-chaos-worker.ts +3 -10
- package/src/services/kernel-timers-operator-chaos-worker.ts +3 -2
- package/src/services/kernel-timers-outbox.ts +1 -1
- package/src/services/kernel-timers-stage10-operator.ts +1 -1
- package/src/services/kernel-timers.ts +4 -3
- package/src/services/land-gate-placement.ts +11 -2
- package/src/services/land-issue-relations.ts +5 -4
- package/src/services/land-restart-retry.ts +7 -6
- package/src/services/landed-ancestry.ts +6 -5
- package/src/services/legacy-landing-host.ts +4 -1
- package/src/services/legacy-landing-recovery.ts +8 -6
- package/src/services/managed-running.ts +17 -17
- package/src/services/memory-areas.ts +3 -3
- package/src/services/merge-pause.ts +9 -15
- package/src/services/operator-decisions.ts +37 -41
- package/src/services/orchestrator-registration-recovery.ts +6 -2
- package/src/services/orchestrator-upgrade.ts +14 -12
- package/src/services/permission-decision.ts +4 -3
- package/src/services/plan-ci-notice.ts +1 -1
- package/src/services/plan-conformance.ts +4 -4
- package/src/services/plan-dispatch-policy.ts +10 -3
- package/src/services/plan-dispatch.ts +35 -14
- package/src/services/plan-graph.ts +39 -261
- package/src/services/plan-import.ts +1 -1
- package/src/services/plan-live-bindings.ts +8 -37
- package/src/services/plan-task-create.ts +1 -1
- package/src/services/plan-terminal-refs.ts +2 -12
- package/src/services/plan-wake-digest.ts +8 -3
- package/src/services/profile-trust.ts +2 -2
- package/src/services/project.ts +11 -10
- package/src/services/prompt-templates.ts +6 -5
- package/src/services/provider-hold-nudge.ts +9 -9
- package/src/services/provider-hold-record.ts +13 -12
- package/src/services/provider-state-audit.ts +19 -18
- package/src/services/provisioning-harness/driver.ts +1 -1
- package/src/services/provisioning-harness/fixture-matrix.ts +3 -3
- package/src/services/provisioning-harness/lifecycle.ts +24 -22
- package/src/services/provisioning-harness/prepare.ts +16 -17
- package/src/services/rate-limit-resume.ts +10 -9
- package/src/services/red-main-auto-revert.ts +7 -5
- package/src/services/red-main-controller-deps.ts +20 -3
- package/src/services/red-main-incident.ts +3 -1
- package/src/services/red-main-quarantine.ts +2 -3
- package/src/services/register-agent.ts +22 -22
- package/src/services/restart-project-role.ts +1 -1
- package/src/services/restart-spawn.ts +17 -16
- package/src/services/review-publish.ts +7 -24
- package/src/services/review-ref-reconcile.ts +29 -38
- package/src/services/runtime-dependency-alert.ts +27 -0
- package/src/services/scheduler-command.ts +11 -9
- package/src/services/scheduler.ts +5 -5
- package/src/services/self-effort-grant.ts +5 -25
- package/src/services/send-message.ts +16 -33
- package/src/services/shutdown-agent.ts +17 -14
- package/src/services/spawn-agent.ts +12 -41
- package/src/services/spawn-chain-inspector.ts +1 -1
- package/src/services/spawn-cwd-placement.ts +21 -5
- package/src/services/spawn-issue-activity.ts +8 -6
- package/src/services/spawn-launch.ts +17 -1
- package/src/services/spawn-loss-escalation.ts +1 -1
- package/src/services/spawn-registration-watchdog.ts +2 -2
- package/src/services/spawn-repo-probe.ts +7 -5
- package/src/services/spawn-tree-cleanup.ts +7 -8
- package/src/services/steward-reaper.ts +4 -4
- package/src/services/task-context-hydration.ts +25 -1
- package/src/services/task-delivery.ts +20 -34
- package/src/services/task-entity.ts +40 -203
- package/src/services/task-issue-link.ts +13 -20
- package/src/services/task-issue-weave.ts +12 -11
- package/src/services/task-lifecycle.ts +27 -31
- package/src/services/task-repo-cwd.ts +37 -0
- package/src/services/task-review-hold.ts +4 -17
- package/src/services/task-semantic-events.ts +13 -11
- package/src/services/task-state-reconcile.ts +3 -4
- package/src/services/task-validation.ts +2 -2
- package/src/services/team-templates.ts +5 -5
- package/src/services/team.ts +31 -98
- package/src/services/terminal-provider-exit.ts +6 -5
- package/src/services/timer-message-fire-chaos-worker.ts +7 -3
- package/src/services/timer-message-fire-outbox.ts +1 -1
- package/src/services/transient-agent-reaper.ts +22 -19
- package/src/services/turn-reconcile-audit.ts +9 -9
- package/src/services/user-onboarding.ts +8 -6
- package/src/services/user-profile.ts +6 -9
- package/src/services/work-finality.ts +16 -4
- package/src/services/workflow-auto-start.ts +2 -1
- package/src/services/workflow-caller.ts +61 -4
- package/src/services/workflow-child-proof-worker.ts +1 -1
- package/src/services/workflow-control-proof-worker.ts +1 -1
- package/src/services/workflow-coordinator.ts +8 -2
- package/src/services/workflow-decisions.ts +5 -5
- package/src/services/workflow-deferred-cleanup.ts +1 -1
- package/src/services/workflow-effect-driver.ts +42 -19
- package/src/services/workflow-effects.ts +41 -27
- package/src/services/workflow-pins.ts +7 -4
- package/src/services/workflow-reconcile.ts +1 -0
- package/src/services/workflow-resume-pins.ts +3 -3
- package/src/services/workflow-routing-defaults.ts +18 -0
- package/src/services/workflow-run-view.ts +4 -3
- package/src/services/workflow-run.test-fixture.ts +1 -1
- package/src/services/workflow-runs.ts +34 -22
- package/src/services/workflow-supervisor-state.ts +21 -1
- package/src/services/workflow-supervisor.ts +4 -3
- package/src/services/workspace-recovery.ts +4 -3
- package/src/spawn-admission.ts +10 -2
- package/src/spawn-placement.ts +27 -9
- package/src/spawn-targets.ts +8 -8
- package/src/sse-agent-status.ts +15 -6
- package/src/sse.ts +49 -24
- package/src/startup-context-injection.ts +61 -57
- package/src/steward-handoff.ts +4 -3
- package/src/steward-policy-cleanup.ts +9 -8
- package/src/steward.ts +2 -2
- package/src/task-dispatch-live.ts +5 -2
- package/src/task-dispatcher.ts +2 -2
- package/src/token-db.ts +2 -2
- package/src/token-usage-async.ts +2 -4
- package/src/user-awaiting-reply.ts +5 -5
- package/src/workspace-actions.ts +24 -29
- package/src/workspace-auto-merge.ts +14 -12
- package/src/workspace-changed-paths-client.ts +16 -5
- package/src/workspace-cleanup-stale.ts +30 -7
- package/src/workspace-command-settle.ts +24 -16
- package/src/workspace-config.ts +1 -1
- package/src/workspace-conflict-resolver.ts +9 -7
- package/src/workspace-dead-owner-recovery.ts +5 -4
- package/src/workspace-escalation.ts +12 -11
- package/src/workspace-human-escalation.ts +3 -3
- package/src/workspace-land-gate-watchdog.ts +3 -3
- package/src/workspace-land-refusal.ts +20 -0
- package/src/workspace-land-stopped.ts +1 -0
- package/src/workspace-merge.ts +10 -26
- package/src/workspace-nothing-to-land-notice.ts +2 -2
- package/src/workspace-orphans.ts +18 -37
- package/src/workspace-pr-completion.ts +10 -8
- package/src/workspace-rekey.ts +3 -3
- package/src/workspace-steward-failure.ts +2 -2
- package/src/workspace-steward-wake.ts +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +0 -2
- package/public/assets/provider-display-DsuWMvVL.js +0 -2
- package/public/assets/run-card-CpKqRbhg.js +0 -2
- package/public/assets/shipping-B9YtnwtG.js +0 -2
- package/public/assets/store-DcClXLH0.js +0 -9
- package/runner/src/agent-runner/http-liveness.ts +0 -85
- package/src/db/on-loop-write-transaction.ts +0 -34
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { clearAgentNoticeAsync, recordCrashReportAsync, recordTerminalEventAsync } from "./db/lifecycle-tail-async";
|
|
2
|
+
import { hasAgentExitNotice } from "./db/terminal-events";
|
|
2
3
|
import { requestAgentExitCleanup } from "./agent-exit-cleanup";
|
|
3
4
|
import { emitRelayEvent } from "./events";
|
|
4
|
-
import { routeNotification } from "./notification-router";
|
|
5
|
+
import { routeAgentNotice, routeNotification } from "./notification-router";
|
|
5
6
|
import { LIFECYCLE_STATE_WORKING, childSignalKey, stampLifecycleSignal, taskSignalKey } from "./lifecycle-signal-registry";
|
|
6
|
-
import { currentCoordinatorOf, deliverableTaskIdsBySpawnRequestId, getAgent,
|
|
7
|
+
import { currentCoordinatorOf, deliverableTaskIdsBySpawnRequestId, getAgent, markAgentReadyNotifiedAsync, workflowRunIdOf } from "./db";
|
|
7
8
|
import { crashReportFor } from "./agent-death-diagnosis";
|
|
8
9
|
import { renderTemplate } from "./prompt-resolver";
|
|
9
10
|
import { markAgentWorkFinal } from "./services/work-finality";
|
|
@@ -57,6 +58,19 @@ function diagnosisSuffix(diagnosis?: AgentDeathDiagnosis): string {
|
|
|
57
58
|
// it guards is same-moment, so a relay restart between the two is not a concern.
|
|
58
59
|
type SpawnTerminal = "agent.ready" | "agent.spawn_failed";
|
|
59
60
|
const spawnTerminalBySpawnRequest = new Map<string, SpawnTerminal>();
|
|
61
|
+
const pendingSpawnNotices = new Map<string, Promise<void>>();
|
|
62
|
+
function spawnQueueKey(agentId: string): string {
|
|
63
|
+
const child = getAgent(agentId);
|
|
64
|
+
return (child && spawnRequestIdOf(child)) || agentId;
|
|
65
|
+
}
|
|
66
|
+
// #1870 — terminal guards advance only after commit; serialize one generation across writer awaits.
|
|
67
|
+
function serializeSpawnNotice(key: string, work: () => Promise<void>): Promise<void> {
|
|
68
|
+
const prior = pendingSpawnNotices.get(key);
|
|
69
|
+
const result = prior ? prior.catch(() => {}).then(work) : work();
|
|
70
|
+
pendingSpawnNotices.set(key, result);
|
|
71
|
+
void result.finally(() => { if (pendingSpawnNotices.get(key) === result) pendingSpawnNotices.delete(key); }).catch(() => {});
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
60
74
|
|
|
61
75
|
// #1513 — spawns we've already told the spawner are queued-for-host-memory, keyed by spawnRequestId
|
|
62
76
|
// (falling back to the parent id when a request has no id). The orchestrator re-reports the whole
|
|
@@ -76,13 +90,6 @@ function recordSpawnTerminal(spawnRequestId: string | undefined, outcome: SpawnT
|
|
|
76
90
|
spawnTerminalBySpawnRequest.set(spawnRequestId, outcome);
|
|
77
91
|
}
|
|
78
92
|
|
|
79
|
-
function tryRecordSpawnFailed(spawnRequestId: string | undefined): boolean {
|
|
80
|
-
if (spawnRequestId === undefined) return true;
|
|
81
|
-
if (spawnTerminalBySpawnRequest.has(spawnRequestId)) return false;
|
|
82
|
-
spawnTerminalBySpawnRequest.set(spawnRequestId, "agent.spawn_failed");
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
93
|
/** A child counts as "had become ready" once its durable readiness stamp exists. */
|
|
87
94
|
function everReady(child: AgentCard): boolean {
|
|
88
95
|
return typeof child.meta?.readyNotifiedAt === "number";
|
|
@@ -128,50 +135,49 @@ function stampChildLifecycleSignal(parent: string, child: AgentCard): void {
|
|
|
128
135
|
* `spawned_by` parent a one-shot notice so it can stop block-polling. No-op for non-spawned agents
|
|
129
136
|
* and for a child whose ready was already announced (reconnect / heartbeat re-registration).
|
|
130
137
|
*/
|
|
131
|
-
export function notifyAgentReady(childId: string): void {
|
|
138
|
+
export async function notifyAgentReady(childId: string): Promise<void> {
|
|
139
|
+
return serializeSpawnNotice(spawnQueueKey(childId), () => notifyAgentReadyBody(childId));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function notifyAgentReadyBody(childId: string): Promise<void> {
|
|
132
143
|
const child = getAgent(childId);
|
|
133
144
|
const parent = child?.spawnedBy;
|
|
134
145
|
// A workflow step agent with no spawner (a run a dashboard user started) still records its ready edge on its run (#3160).
|
|
135
146
|
if (!child || (!parent && !workflowRunIdOf(child))) return;
|
|
136
147
|
if (isSpawnIntentCanceled(child.meta?.spawnRequestId)) return;
|
|
137
148
|
// Idempotent — only stamped on first ready; classifies a later offline edge as exited.
|
|
138
|
-
|
|
149
|
+
await markAgentReadyNotifiedAsync(childId);
|
|
139
150
|
// #2899 — a self-compact flips ready again; the generation slot keeps the push one-shot.
|
|
140
|
-
|
|
151
|
+
await announceReady(child, parent);
|
|
141
152
|
}
|
|
142
153
|
|
|
143
|
-
function announceReady(child: AgentCard, spawner: string | undefined): void {
|
|
154
|
+
async function announceReady(child: AgentCard, spawner: string | undefined): Promise<void> {
|
|
144
155
|
const childId = child.id;
|
|
145
156
|
const spawnRequestId = spawnRequestIdOf(child);
|
|
146
157
|
// #648 — if a spawn_failed was already emitted for this request, this ready RETRACTS it: the agent
|
|
147
158
|
// actually came up, so the earlier failure was a false negative. Emit a corrective recovery instead
|
|
148
159
|
// of a plain ready notice so a coordinator that acted on the failure can reconcile.
|
|
149
160
|
const recovered = spawnTerminalOf(spawnRequestId) === "agent.spawn_failed";
|
|
150
|
-
recordSpawnTerminal(spawnRequestId, "agent.ready");
|
|
151
161
|
|
|
152
162
|
const workflowRunId = workflowRunIdOf(child);
|
|
153
|
-
|
|
154
|
-
type: "agent.ready",
|
|
155
|
-
|
|
156
|
-
subject: childId,
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
source: "server",
|
|
166
|
-
subject: childId,
|
|
167
|
-
data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, supersedes: "agent.spawn_failed" },
|
|
168
|
-
});
|
|
163
|
+
const readyEvent = () => {
|
|
164
|
+
emitRelayEvent({ type: "agent.ready", source: "server", subject: childId,
|
|
165
|
+
data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, ...(workflowRunId ? { workflowRunId } : {}) } });
|
|
166
|
+
if (recovered && spawner) emitRelayEvent({ type: "agent.spawn_recovered", source: "server", subject: childId,
|
|
167
|
+
data: { agentId: childId, parent: spawner, provider: providerOf(child), label: child.label, spawnRequestId, supersedes: "agent.spawn_failed" } });
|
|
168
|
+
};
|
|
169
|
+
const slot = { child, kind: "agent.ready" };
|
|
170
|
+
if (!spawner) {
|
|
171
|
+
const created = await routeAgentNotice(slot);
|
|
172
|
+
recordSpawnTerminal(spawnRequestId, "agent.ready");
|
|
173
|
+
if (created) readyEvent();
|
|
174
|
+
return;
|
|
169
175
|
}
|
|
170
|
-
|
|
176
|
+
const parent = noticeRecipient(child, spawner);
|
|
171
177
|
if (recovered) {
|
|
172
178
|
// A correction must always reach a parent that got the (false) failure — gate only on the global
|
|
173
179
|
// switch, NOT the agentReady sub-toggle, so the retraction lands even if ready pushes are off.
|
|
174
|
-
|
|
180
|
+
const created = await routeAgentNotice(slot, {
|
|
175
181
|
type: "agent.spawn_recovered",
|
|
176
182
|
scope: { agentId: childId, parent },
|
|
177
183
|
recipients: [parent],
|
|
@@ -186,9 +192,11 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
|
|
|
186
192
|
replyExpected: false,
|
|
187
193
|
},
|
|
188
194
|
});
|
|
195
|
+
recordSpawnTerminal(spawnRequestId, "agent.ready");
|
|
196
|
+
if (created) readyEvent();
|
|
189
197
|
return;
|
|
190
198
|
}
|
|
191
|
-
|
|
199
|
+
const created = await routeAgentNotice(slot, {
|
|
192
200
|
type: "agent.ready",
|
|
193
201
|
scope: { agentId: childId, parent },
|
|
194
202
|
recipients: [parent],
|
|
@@ -199,7 +207,8 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
|
|
|
199
207
|
replyExpected: false,
|
|
200
208
|
},
|
|
201
209
|
});
|
|
202
|
-
|
|
210
|
+
recordSpawnTerminal(spawnRequestId, "agent.ready");
|
|
211
|
+
if (created) { readyEvent(); stampChildLifecycleSignal(parent, child); }
|
|
203
212
|
}
|
|
204
213
|
|
|
205
214
|
/**
|
|
@@ -209,16 +218,20 @@ function announceReady(child: AgentCard, spawner: string | undefined): void {
|
|
|
209
218
|
* No-op for non-spawned agents.
|
|
210
219
|
* `reason` is the offline cause (e.g. "heartbeat lost", "shutdown").
|
|
211
220
|
*/
|
|
212
|
-
export function notifyAgentOffline(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): void {
|
|
213
|
-
|
|
221
|
+
export async function notifyAgentOffline(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): Promise<void> {
|
|
222
|
+
return serializeSpawnNotice(spawnQueueKey(childId), () => notifyAgentOfflineBody(childId, reason, diagnosis));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async function notifyAgentOfflineBody(childId: string, reason: string, diagnosis?: AgentDeathDiagnosis): Promise<void> {
|
|
226
|
+
(await requestAgentExitCleanup(childId));
|
|
214
227
|
const child = getAgent(childId);
|
|
215
228
|
const parent = child?.spawnedBy;
|
|
216
229
|
if (!child) return;
|
|
217
230
|
if (!parent) {
|
|
218
231
|
// A workflow step agent with no spawner records its exit on its run (#3160); nobody else is told.
|
|
219
232
|
if (workflowRunIdOf(child) && everReady(child)) {
|
|
220
|
-
|
|
221
|
-
notifyAgentExit(child, reason, diagnosis);
|
|
233
|
+
await clearAgentNoticeAsync(child, "agent.ready");
|
|
234
|
+
await notifyAgentExit(child, reason, diagnosis);
|
|
222
235
|
}
|
|
223
236
|
return;
|
|
224
237
|
}
|
|
@@ -228,38 +241,32 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
|
|
|
228
241
|
// later signal (relay_workspace_ready, task→done) is coming from a process that no longer exists.
|
|
229
242
|
// Idempotent (flushWorkFinalReports no-ops once the ring is empty), so a redundant call from a
|
|
230
243
|
// second offline classification of the same agent is harmless.
|
|
231
|
-
markAgentWorkFinal(childId, "edge-fallback");
|
|
244
|
+
(await markAgentWorkFinal(childId, "edge-fallback"));
|
|
232
245
|
// Classify from the durable readiness stamp; re-arm this generation's ready push for a return.
|
|
233
246
|
const wasReady = everReady(child);
|
|
234
|
-
|
|
247
|
+
await clearAgentNoticeAsync(child, "agent.ready");
|
|
235
248
|
// #636 — persist the post-mortem keyed by agentId so the WHY survives the reaper, regardless of
|
|
236
249
|
// whether the parent push is enabled. Recorded once per terminal-event emission.
|
|
237
|
-
if (diagnosis)
|
|
250
|
+
if (diagnosis) await recordCrashReportAsync(crashReportFor(child, reason, diagnosis));
|
|
238
251
|
if (hasAgentExitNotice(child)) return;
|
|
239
252
|
|
|
240
253
|
// #645 — persist a terminal marker for ANY offline terminus (clean exit or spawn-fail) keyed by
|
|
241
254
|
// agentId so it outlives the reaper. The #634 watchdog reads this to skip a benign shutdown; it
|
|
242
255
|
// must fire ONLY on a genuine silent death that emitted no terminal event at all.
|
|
243
|
-
|
|
256
|
+
await recordTerminalEventAsync({ agentId: childId, reason, kind: wasReady ? "agent.exited" : "agent.spawn_failed", epoch: child.epoch, createdAt: Date.now() });
|
|
244
257
|
|
|
245
258
|
if (wasReady) {
|
|
246
|
-
notifyAgentExit(child, reason, diagnosis);
|
|
259
|
+
await notifyAgentExit(child, reason, diagnosis);
|
|
247
260
|
return;
|
|
248
261
|
}
|
|
249
262
|
|
|
250
|
-
|
|
263
|
+
|
|
251
264
|
const recipient = noticeRecipient(child, parent);
|
|
252
265
|
// #648 — record the terminal outcome so a (defensive) later ready for the same request is detected
|
|
253
266
|
// as a recovery and corrected, keeping the one-terminal-per-spawn invariant across both fail paths.
|
|
254
267
|
const spawnRequestId = spawnRequestIdOf(child);
|
|
255
|
-
if (
|
|
256
|
-
|
|
257
|
-
type: "agent.spawn_failed",
|
|
258
|
-
source: "server",
|
|
259
|
-
subject: childId,
|
|
260
|
-
data: { agentId: childId, parent, reason, provider: providerOf(child), spawnRequestId, neverReady: true, ...(diagnosis ? { diagnosis } : {}) },
|
|
261
|
-
});
|
|
262
|
-
routeNotification({
|
|
268
|
+
if (spawnTerminalOf(spawnRequestId)) return;
|
|
269
|
+
const created = await routeAgentNotice({ child, kind: "agent.spawn_failed" }, {
|
|
263
270
|
type: "agent.spawn_failed",
|
|
264
271
|
scope: { agentId: childId, parent: recipient },
|
|
265
272
|
recipients: [recipient],
|
|
@@ -274,7 +281,15 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
|
|
|
274
281
|
replyExpected: false,
|
|
275
282
|
},
|
|
276
283
|
});
|
|
277
|
-
|
|
284
|
+
recordSpawnTerminal(spawnRequestId, "agent.spawn_failed");
|
|
285
|
+
if (created) {
|
|
286
|
+
emitRelayEvent({
|
|
287
|
+
type: "agent.spawn_failed",
|
|
288
|
+
source: "server",
|
|
289
|
+
subject: childId,
|
|
290
|
+
data: { agentId: childId, parent, reason, provider: providerOf(child), spawnRequestId, neverReady: true, ...(diagnosis ? { diagnosis } : {}) },
|
|
291
|
+
});
|
|
292
|
+
}
|
|
278
293
|
}
|
|
279
294
|
|
|
280
295
|
/**
|
|
@@ -286,21 +301,19 @@ export function notifyAgentOffline(childId: string, reason: string, diagnosis?:
|
|
|
286
301
|
* the subsequent agent.ready / agent.spawn_failed — no separate "admitted" event needed. Non-terminal:
|
|
287
302
|
* it deliberately does NOT touch the one-terminal-per-spawn guard.
|
|
288
303
|
*/
|
|
289
|
-
export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): void {
|
|
304
|
+
export async function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
|
|
305
|
+
return serializeSpawnNotice(input.spawnRequestId ?? `parent:${input.parent}`, () => notifyAgentSpawnQueuedBody(input));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function notifyAgentSpawnQueuedBody(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
|
|
290
309
|
const dedupeKey = input.spawnRequestId ?? `parent:${input.parent}`;
|
|
291
310
|
if (spawnQueuedNotified.has(dedupeKey)) return;
|
|
292
311
|
// A queued spawn whose terminal outcome already landed (a fast admit→ready, or a fail) must not now
|
|
293
312
|
// emit a stale "queued" notice out of order. Ready/failed is authoritative; suppress a late queue.
|
|
294
313
|
if (spawnTerminalOf(input.spawnRequestId)) return;
|
|
295
|
-
|
|
296
|
-
emitRelayEvent({
|
|
297
|
-
type: "agent.spawn_queued",
|
|
298
|
-
source: "server",
|
|
299
|
-
subject: input.spawnRequestId ?? input.parent,
|
|
300
|
-
data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
|
|
301
|
-
});
|
|
314
|
+
|
|
302
315
|
const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
|
|
303
|
-
routeNotification({
|
|
316
|
+
await routeNotification({
|
|
304
317
|
type: "agent.spawn_queued",
|
|
305
318
|
scope: { parent: recipient },
|
|
306
319
|
recipients: [recipient],
|
|
@@ -314,6 +327,13 @@ export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?:
|
|
|
314
327
|
replyExpected: false,
|
|
315
328
|
},
|
|
316
329
|
});
|
|
330
|
+
spawnQueuedNotified.add(dedupeKey);
|
|
331
|
+
emitRelayEvent({
|
|
332
|
+
type: "agent.spawn_queued",
|
|
333
|
+
source: "server",
|
|
334
|
+
subject: input.spawnRequestId ?? input.parent,
|
|
335
|
+
data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
|
|
336
|
+
});
|
|
317
337
|
}
|
|
318
338
|
|
|
319
339
|
/**
|
|
@@ -321,18 +341,17 @@ export function notifyAgentSpawnQueued(input: { parent: string; spawnRequestId?:
|
|
|
321
341
|
* (provider unavailable, bad cwd, launch error) before any child agent registered. Routes directly
|
|
322
342
|
* to the spawning parent threaded on the command, since there is no child agent record to resolve.
|
|
323
343
|
*/
|
|
324
|
-
export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): void {
|
|
344
|
+
export async function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
|
|
345
|
+
return serializeSpawnNotice(input.spawnRequestId ?? `parent:${input.parent}`, () => notifyAgentSpawnFailedBody(input));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async function notifyAgentSpawnFailedBody(input: { parent: string; spawnRequestId?: string; provider?: string; reason: string }): Promise<void> {
|
|
325
349
|
// #648/#864 — if the spawn already reached any terminal outcome, a later command-failure report
|
|
326
350
|
// for the same request is stale or duplicate. Ready is authoritative; failed is already reported.
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
type: "agent.spawn_failed",
|
|
330
|
-
source: "server",
|
|
331
|
-
subject: input.spawnRequestId ?? input.parent,
|
|
332
|
-
data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
|
|
333
|
-
});
|
|
351
|
+
if (spawnTerminalOf(input.spawnRequestId)) return;
|
|
352
|
+
|
|
334
353
|
const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
|
|
335
|
-
routeNotification({
|
|
354
|
+
await routeNotification({
|
|
336
355
|
type: "agent.spawn_failed",
|
|
337
356
|
scope: { parent: recipient },
|
|
338
357
|
recipients: [recipient],
|
|
@@ -346,6 +365,13 @@ export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?:
|
|
|
346
365
|
replyExpected: false,
|
|
347
366
|
},
|
|
348
367
|
});
|
|
368
|
+
recordSpawnTerminal(input.spawnRequestId, "agent.spawn_failed");
|
|
369
|
+
emitRelayEvent({
|
|
370
|
+
type: "agent.spawn_failed",
|
|
371
|
+
source: "server",
|
|
372
|
+
subject: input.spawnRequestId ?? input.parent,
|
|
373
|
+
data: { parent: input.parent, spawnRequestId: input.spawnRequestId, provider: input.provider, reason: input.reason },
|
|
374
|
+
});
|
|
349
375
|
}
|
|
350
376
|
|
|
351
377
|
/**
|
|
@@ -353,7 +379,7 @@ export function notifyAgentSpawnFailed(input: { parent: string; spawnRequestId?:
|
|
|
353
379
|
* deliberately non-terminal: the runner can still register after the watchdog fires, so callers
|
|
354
380
|
* must not retry or infer that a new spawn is safe.
|
|
355
381
|
*/
|
|
356
|
-
export function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnRequestId: string; provider?: string; reason: string; phase: "dispatch_unacknowledged" | "registration_unconfirmed" }): void {
|
|
382
|
+
export async function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnRequestId: string; provider?: string; reason: string; phase: "dispatch_unacknowledged" | "registration_unconfirmed" }): Promise<void> {
|
|
357
383
|
emitRelayEvent({
|
|
358
384
|
type: "agent.spawn_unconfirmed",
|
|
359
385
|
source: "server",
|
|
@@ -361,7 +387,7 @@ export function notifyAgentSpawnUnconfirmed(input: { parent: string; spawnReques
|
|
|
361
387
|
data: input,
|
|
362
388
|
});
|
|
363
389
|
const recipient = spawnerRecipient(input.parent, input.spawnRequestId);
|
|
364
|
-
routeNotification({
|
|
390
|
+
await routeNotification({
|
|
365
391
|
type: "agent.spawn_unconfirmed",
|
|
366
392
|
scope: { parent: recipient },
|
|
367
393
|
recipients: [recipient],
|
|
@@ -392,24 +418,18 @@ export function notifyAgentRegistered(agent: AgentCard): void {
|
|
|
392
418
|
}
|
|
393
419
|
|
|
394
420
|
/** Emit one parent exit notice per generation, including automatic reaps before the offline report. */
|
|
395
|
-
export function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: AgentDeathDiagnosis, context: { workspaceId?: string; workspaceStatus?: string } = {}): void {
|
|
421
|
+
export async function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: AgentDeathDiagnosis, context: { workspaceId?: string; workspaceStatus?: string } = {}): Promise<void> {
|
|
396
422
|
const parent = child.spawnedBy;
|
|
397
423
|
const workflowRunId = workflowRunIdOf(child);
|
|
398
|
-
|
|
399
|
-
emitRelayEvent({
|
|
400
|
-
type: "agent.exited",
|
|
401
|
-
source: "server",
|
|
402
|
-
subject: child.id,
|
|
403
|
-
data: { ...context, agentId: child.id, parent, reason, provider: providerOf(child), spawnRequestId: spawnRequestIdOf(child), ...(workflowRunId ? { workflowRunId } : {}), ...(diagnosis ? { diagnosis } : {}) },
|
|
404
|
-
});
|
|
424
|
+
|
|
405
425
|
// The parent already got a shutdown command receipt for requesting this exit, so the
|
|
406
426
|
// exit itself is expected — including a non-zero code from a force-reap kill. Keep the
|
|
407
427
|
// terminal event for timeline consumers; only skip the parent wake-up. An exit nobody
|
|
408
428
|
// requested (no shutdown command from the parent) still wakes: crashes and spawn failures
|
|
409
429
|
// keep their notice.
|
|
410
|
-
|
|
430
|
+
const suppressed = parent && parentRequestedShutdown(child.id, spawnRequestIdOf(child) ?? "", parent, Date.now() - 5 * 60_000);
|
|
411
431
|
const recipient = parent ? noticeRecipient(child, parent) : undefined;
|
|
412
|
-
|
|
432
|
+
const created = await routeAgentNotice({ child, kind: "agent.exited" }, suppressed ? undefined : {
|
|
413
433
|
type: "agent.exited",
|
|
414
434
|
scope: { agentId: child.id, parent: recipient },
|
|
415
435
|
recipients: [recipient],
|
|
@@ -424,5 +444,12 @@ export function notifyAgentExit(child: AgentCard, reason: string, diagnosis?: Ag
|
|
|
424
444
|
replyExpected: false,
|
|
425
445
|
},
|
|
426
446
|
});
|
|
427
|
-
|
|
447
|
+
if (created) {
|
|
448
|
+
emitRelayEvent({
|
|
449
|
+
type: "agent.exited",
|
|
450
|
+
source: "server",
|
|
451
|
+
subject: child.id,
|
|
452
|
+
data: { ...context, agentId: child.id, parent, reason, provider: providerOf(child), spawnRequestId: spawnRequestIdOf(child), ...(workflowRunId ? { workflowRunId } : {}), ...(diagnosis ? { diagnosis } : {}) },
|
|
453
|
+
});
|
|
454
|
+
}
|
|
428
455
|
}
|
package/src/agent-ref.ts
CHANGED
|
@@ -160,8 +160,9 @@ export function resolveAgentRef(ref: string, agents: AgentCard[], opts: ResolveO
|
|
|
160
160
|
return { status: "not_found", offlineMatches: matches };
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
export function targetMatchesAgent(target: string, agentId: string, agent?: AgentCard | null): boolean {
|
|
164
|
-
|
|
163
|
+
export function targetMatchesAgent(target: string | null | undefined, agentId: string, agent?: AgentCard | null): boolean {
|
|
164
|
+
// Untargeted task events have no agent recipient, on live streams or replay (#3801).
|
|
165
|
+
if (!agent || typeof target !== "string" || !target) return false;
|
|
165
166
|
if (target.startsWith("coordinator:")) return resolveTeamCoordinatorAgentId(target.slice(12)) === agentId;
|
|
166
167
|
return targetMatchesAgentIdentity(target, {
|
|
167
168
|
id: agentId,
|
|
@@ -1,18 +1,41 @@
|
|
|
1
|
-
// The ONE agent.status emitter (#3606): every seam lands here
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// The ONE agent.status emitter (#3606): every seam lands here. A card unchanged but for lastSeen and
|
|
2
|
+
// statusSeq is dropped (the dashboard reads heartbeat age from its roster poll; nothing orders by
|
|
3
|
+
// statusSeq). #3614 — a change only in liveness telemetry (timestamps, ages, gauges the next tick
|
|
4
|
+
// supersedes) goes out live-only, with no outbox row; replay keeps every real state change.
|
|
5
5
|
|
|
6
6
|
import { getAgentRuntimeAsync } from "./db";
|
|
7
7
|
import { projectAgentStatusData } from "./agent-card-projection";
|
|
8
|
-
import { emitRelayEvent } from "./events";
|
|
8
|
+
import { emitEphemeralRelayEvent, emitRelayEvent } from "./events";
|
|
9
9
|
import { emitNotificationCreated, notificationForAgentStatus } from "./dashboard-notifications";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
type Fingerprint = number | bigint;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const UNEMITTED_KEYS = [["lastSeen"], ["statusSeq"]] as const;
|
|
14
|
+
const LIVENESS_KEYS = [
|
|
15
|
+
...UNEMITTED_KEYS,
|
|
16
|
+
["context", "lastUpdatedAt"], ["context", "tokensUsed"], ["context", "utilization"],
|
|
17
|
+
["meta", "unreportedTokenUsage"], ["meta", "lastProviderEventAt"],
|
|
18
|
+
["meta", "transport", "lastServerFrameAt"], ["meta", "transport", "lastHeartbeatAckAt"],
|
|
19
|
+
["meta", "liveness", "transportLiveAt"], ["meta", "liveness", "lastProgressAt"],
|
|
20
|
+
["meta", "busyHealth", "activeWorkAgeMs"], ["meta", "busyHealth", "staleForMs"], ["meta", "busyHealth", "lastProgressAt"],
|
|
21
|
+
["meta", "busyHealth", "transportLiveAt"], ["meta", "busyHealth", "transportStaleForMs"],
|
|
22
|
+
] as const;
|
|
23
|
+
|
|
24
|
+
const lastEmitted = new Map<string, { card: Fingerprint; durable: Fingerprint }>();
|
|
25
|
+
|
|
26
|
+
/** Hash of the card without `paths`; copies only the objects on a stripped path. */
|
|
27
|
+
function fingerprint(data: Record<string, unknown>, paths: ReadonlyArray<readonly string[]>): Fingerprint {
|
|
28
|
+
const root = { ...data };
|
|
29
|
+
for (const path of paths) {
|
|
30
|
+
let parent: Record<string, unknown> = root;
|
|
31
|
+
for (const key of path.slice(0, -1)) {
|
|
32
|
+
const child = parent[key];
|
|
33
|
+
if (!child || typeof child !== "object" || Array.isArray(child)) { parent = {}; break; }
|
|
34
|
+
parent = parent[key] = { ...child as Record<string, unknown> };
|
|
35
|
+
}
|
|
36
|
+
delete parent[path[path.length - 1]!];
|
|
37
|
+
}
|
|
38
|
+
return Bun.hash(JSON.stringify(root));
|
|
16
39
|
}
|
|
17
40
|
|
|
18
41
|
export async function emitAgentStatus(agentId: string): Promise<void> {
|
|
@@ -20,15 +43,21 @@ export async function emitAgentStatus(agentId: string): Promise<void> {
|
|
|
20
43
|
// Enrich with the branch-state badge fields (#236) and the resolved issueRepo (#533) so
|
|
21
44
|
// the dashboard's live agent updates carry the same projection as GET /api/agents (#560).
|
|
22
45
|
const data = await projectAgentStatusData(agentId, agent) as unknown as Record<string, unknown>;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
46
|
+
const next = { card: fingerprint(data, UNEMITTED_KEYS), durable: fingerprint(data, LIVENESS_KEYS) };
|
|
47
|
+
const previous = lastEmitted.get(agentId);
|
|
48
|
+
if (previous?.card === next.card) return;
|
|
49
|
+
lastEmitted.set(agentId, next);
|
|
50
|
+
const event = { type: "agent.status", source: "server", subject: agentId, data };
|
|
51
|
+
if (previous?.durable === next.durable) {
|
|
52
|
+
emitEphemeralRelayEvent(event);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
26
55
|
try {
|
|
27
56
|
// Awaited: a bus registration must not install its socket before its own status event is durable.
|
|
28
|
-
await emitRelayEvent(
|
|
57
|
+
await emitRelayEvent(event);
|
|
29
58
|
} catch (error) {
|
|
30
59
|
// Never let an append that did not happen suppress the next identical card.
|
|
31
|
-
if (lastEmitted.get(agentId) ===
|
|
60
|
+
if (lastEmitted.get(agentId) === next) lastEmitted.delete(agentId);
|
|
32
61
|
throw error;
|
|
33
62
|
}
|
|
34
63
|
const notification = agent ? notificationForAgentStatus(agent) : undefined;
|
package/src/auth/password.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { createAuthIdentityAsync } from "../db/runtime-tail-async";
|
|
1
2
|
// Password authentication provider (#389). The only built-in provider in Phase 1. Secrets are
|
|
2
3
|
// hashed with scrypt (node:crypto — no dependency) and compared with `timingSafeEqual`, the same
|
|
3
4
|
// constant-time primitive the token layer uses. The hash is stored in `auth_identities.secret_hash`
|
|
4
5
|
// keyed by (provider="password", provider_subject=<username>).
|
|
5
6
|
import { randomBytes, scrypt, timingSafeEqual } from "node:crypto";
|
|
6
|
-
import {
|
|
7
|
+
import { getAuthIdentity, type AuthIdentity } from "../db/auth-identities.ts";
|
|
7
8
|
import { isRecord } from "@humwick/sdk";
|
|
8
9
|
import type { AuthProvider, AuthVerifyResult } from "./provider.ts";
|
|
9
10
|
|
|
@@ -98,13 +99,13 @@ export async function createPasswordIdentity(input: {
|
|
|
98
99
|
password: string;
|
|
99
100
|
metadata?: Record<string, unknown>;
|
|
100
101
|
}): Promise<AuthIdentity> {
|
|
101
|
-
return
|
|
102
|
+
return (await createAuthIdentityAsync({
|
|
102
103
|
userId: input.userId,
|
|
103
104
|
provider: PASSWORD_PROVIDER_ID,
|
|
104
105
|
providerSubject: input.username,
|
|
105
106
|
secretHash: await hashPassword(input.password),
|
|
106
107
|
metadata: input.metadata,
|
|
107
|
-
});
|
|
108
|
+
}));
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
/** Parse `{ username, password }` from a login request body. */
|
|
@@ -31,7 +31,7 @@ export async function refreshUserSession(refreshToken: string, nowMs = Date.now(
|
|
|
31
31
|
expiresAt: Math.min(nowMs + REFRESH_GRACE_MS, (resolved.payload.exp ?? Infinity) * 1000),
|
|
32
32
|
result: (async () => {
|
|
33
33
|
if (!(await revokeTokenAsync(jti, "rotation"))) return null;
|
|
34
|
-
const session = mintUserSession(resolved.user, resolved.payload.constraints?.sessionId);
|
|
34
|
+
const session = (await mintUserSession(resolved.user, resolved.payload.constraints?.sessionId));
|
|
35
35
|
return { accessJti: session.accessJti, refreshJti: session.refreshJti };
|
|
36
36
|
})(),
|
|
37
37
|
};
|
|
@@ -4,7 +4,7 @@ import { mintUserSession } from "./session.ts";
|
|
|
4
4
|
|
|
5
5
|
/** An `authorization` header carrying a fresh access token for `userId`. An unknown id models a
|
|
6
6
|
* session whose user no longer exists (it carries operator scopes). */
|
|
7
|
-
export function sessionAuthHeader(userId: string): Record<string, string
|
|
7
|
+
export async function sessionAuthHeader(userId: string): Promise<Record<string, string>> {
|
|
8
8
|
const user = getUser(userId) ?? { id: userId, handle: userId, displayName: userId, role: "operator" as const, status: "active" as const, tenantId: "default", avatarArtifactId: null, avatarUrl: null, createdAt: 0, updatedAt: 0 };
|
|
9
|
-
return { authorization: `Bearer ${mintUserSession(user).accessToken}` };
|
|
9
|
+
return { authorization: `Bearer ${(await mintUserSession(user)).accessToken}` };
|
|
10
10
|
}
|
package/src/auth/session.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// `role` ("user"), so no machine-token path branches on it.
|
|
6
6
|
import { userSinkId, userIdFromAddress, isHumanAgentId, type User, type UserRole } from "@humwick/sdk";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { revokeTokenAsync } from "../token-db-write.ts";
|
|
9
|
-
import {
|
|
8
|
+
import { createTokenAsync, revokeTokenAsync } from "../token-db-write.ts";
|
|
9
|
+
import { liveTokenJtisForSession } from "../token-db.ts";
|
|
10
10
|
import { verifyComponentToken } from "../security.ts";
|
|
11
11
|
import { getUser } from "../db/users.ts";
|
|
12
12
|
import { scopesForRole } from "./role-scopes";
|
|
@@ -50,25 +50,25 @@ export interface MintedSession {
|
|
|
50
50
|
* SaaS seam (identity-only — enforces nothing). Both tokens share the `user:<id>` sub so a single
|
|
51
51
|
* "sign out everywhere" revoke (by sub) kills the whole session family.
|
|
52
52
|
*/
|
|
53
|
-
export function mintUserSession(user: User, sessionId: string = randomUUID()): MintedSession {
|
|
53
|
+
export async function mintUserSession(user: User, sessionId: string = randomUUID()): Promise<MintedSession> {
|
|
54
54
|
const sub = userSinkId(user.id);
|
|
55
55
|
const constraints = { sessionId, ...(user.tenantId ? { tenantId: user.tenantId } : {}) };
|
|
56
|
-
const access =
|
|
56
|
+
const access = (await createTokenAsync({
|
|
57
57
|
sub,
|
|
58
58
|
role: USER_TOKEN_ROLE,
|
|
59
59
|
scope: scopesForUserRole(user.role),
|
|
60
60
|
constraints,
|
|
61
61
|
ttlSeconds: ACCESS_TTL_SECONDS,
|
|
62
62
|
createdBy: `auth:login:${user.id}`,
|
|
63
|
-
});
|
|
64
|
-
const refresh =
|
|
63
|
+
}));
|
|
64
|
+
const refresh = (await createTokenAsync({
|
|
65
65
|
sub,
|
|
66
66
|
role: USER_TOKEN_ROLE,
|
|
67
67
|
scope: [REFRESH_SCOPE],
|
|
68
68
|
constraints,
|
|
69
69
|
ttlSeconds: REFRESH_TTL_SECONDS,
|
|
70
70
|
createdBy: `auth:refresh:${user.id}`,
|
|
71
|
-
});
|
|
71
|
+
}));
|
|
72
72
|
return {
|
|
73
73
|
accessToken: access.token,
|
|
74
74
|
refreshToken: refresh.token,
|