@humwick/server 0.130.0 → 0.130.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/docs/guides/tools-administration.md +6 -1
- package/docs/guides/tools-coordination.md +1 -0
- package/docs/guides/tools-tasks.md +8 -0
- package/docs/guides/workflows.md +58 -0
- package/docs/openapi.json +414 -1
- package/package.json +8 -17
- package/public/assets/{MessageBubble-BWpoBjl4.js → MessageBubble-BWLqMGKG.js} +2 -2
- package/public/assets/{PlanGraphPanel-C0auck3n.js → PlanGraphPanel-3TlIQpjk.js} +2 -2
- package/public/assets/{TraceView-DBnOx7AQ.js → TraceView-Wimm0Czv.js} +2 -2
- package/public/assets/{VaultDecisionCard-0kp2oNBC.js → VaultDecisionCard-Bau_vNax.js} +2 -2
- package/public/assets/{activity-yLztXEBt.js → activity-CrSurn-r.js} +2 -2
- package/public/assets/{agent-lineage-BbJDR1dW.js → agent-lineage-CknAJKcb.js} +2 -2
- package/public/assets/agent-liveness-CaNwK0Zf.js +2 -0
- package/public/assets/{agent-name-CTZBrSD9.js → agent-name-DKbiIhBo.js} +2 -2
- package/public/assets/agent-profiles-DwF6EQ4R.js +2 -0
- package/public/assets/{agent-project-badge-9TqzUUYE.js → agent-project-badge-Diz4Sjjb.js} +2 -2
- package/public/assets/{agent-tools-D4n40pn8.js → agent-tools-CRhpRQza.js} +2 -2
- package/public/assets/{agent-type-icon-D6FUarOf.js → agent-type-icon-LrUEU3lB.js} +2 -2
- package/public/assets/{agents-BYDslkJc.js → agents-B-v66C-4.js} +2 -2
- package/public/assets/{analytics-B-XSbEMC.js → analytics-BqCb-LKi.js} +2 -2
- package/public/assets/{artifact-viewer-DdWIfV6M.js → artifact-viewer-kf4pGuAR.js} +2 -2
- package/public/assets/{artifacts-oBOqks-2.js → artifacts-D32zyw4Y.js} +2 -2
- package/public/assets/{artifacts-DPN1q4pA.js → artifacts-DJevXcvg.js} +2 -2
- package/public/assets/{automation-4KcRFXEu.js → automation-BpRajx_5.js} +2 -2
- package/public/assets/{backlog-Cw9xPTCF.js → backlog-D_UjTdzX.js} +2 -2
- package/public/assets/{busy-health-CTu32MZt.js → busy-health-N3VEh4ao.js} +2 -2
- package/public/assets/{channels-BiXzg1G9.js → channels-9jopungq.js} +2 -2
- package/public/assets/{chat-Ctk2qwvA.js → chat-CSXrTB3C.js} +2 -2
- package/public/assets/{code-preview-Bm1wWqAp.js → code-preview-p1NnmqK0.js} +2 -2
- package/public/assets/{connectors-C36ax4Vw.js → connectors-CZdqlDNL.js} +2 -2
- package/public/assets/{cosmos-Jj9LK2Wf.js → cosmos-BgdsE4dG.js} +2 -2
- package/public/assets/{crate-agent-H6S7-B9T.js → crate-agent-30aXTKva.js} +2 -2
- package/public/assets/{dependency-graph-Cd1E23wa.js → dependency-graph-B_jvw2GE.js} +2 -2
- package/public/assets/{deploys-Bwfq146q.js → deploys-DoN6bAb5.js} +2 -2
- package/public/assets/{display-CfO7rTuF.js → display-BrKWFGJz.js} +2 -2
- package/public/assets/{files-DhhZI2Ih.js → files-D6XEu8Ng.js} +2 -2
- package/public/assets/fleet-C7jQWbw2.js +2 -0
- package/public/assets/{fleet-metrics-BkHP-P3R.js → fleet-metrics-BiDs3MLx.js} +2 -2
- package/public/assets/{formatted-body-Cm1RrzmN.js → formatted-body-CQBwc1fb.js} +3 -3
- package/public/assets/{formatted-body-impl-DQiOuOD1.js → formatted-body-impl-DyG0WsQS.js} +2 -2
- package/public/assets/{host-providers-dialog-CHqwXTov.js → host-providers-dialog-DKaW31dN.js} +2 -2
- package/public/assets/index-CRHep3M9.js +15 -0
- package/public/assets/index-MYAIwYTX.css +2 -0
- package/public/assets/{insights-fH1EL-qZ.js → insights-CzrtkpOE.js} +2 -2
- package/public/assets/{integrations-C5Oix6ng.js → integrations-aVsUmigt.js} +2 -2
- package/public/assets/{issue-ref-chip-ODyondIa.js → issue-ref-chip-BnSlM_95.js} +2 -2
- package/public/assets/{log-viewer-Cvfy6PW7.js → log-viewer-qe7Ee47Z.js} +2 -2
- package/public/assets/{maintenance-D8CDH5wZ.js → maintenance-NfjqFZAk.js} +2 -2
- package/public/assets/{managed-agents-egllbpij.js → managed-agents-BiH0HgaE.js} +2 -2
- package/public/assets/{markdown-preview-CYSFgVgK.js → markdown-preview-BixaT3Xr.js} +3 -3
- package/public/assets/{markdown-preview-impl-BteVIjX4.js → markdown-preview-impl-DNGlWIS3.js} +2 -2
- package/public/assets/{memory-C8WmXsyr.js → memory-DNsCl6UX.js} +2 -2
- package/public/assets/{messages-BzQdqlO6.js → messages-DopU1L1X.js} +2 -2
- package/public/assets/{orchestrators-B1HxzkNw.js → orchestrators-Cq7ckLQT.js} +2 -2
- package/public/assets/{overview-DCUnI4Z7.js → overview-C1DCTzzV.js} +2 -2
- package/public/assets/{pairs-ftCd2XcD.js → pairs-DE_m6rrE.js} +2 -2
- package/public/assets/{profile-icon-B2zH8DMH.js → profile-icon-B3rfh77F.js} +2 -2
- package/public/assets/project-profile-instructions-DQWZE0kA.js +2 -0
- package/public/assets/projects-Br2Bd2h1.js +2 -0
- package/public/assets/{prompt-settings-Bftq9czX.js → prompt-settings-BKvFsvGD.js} +2 -2
- package/public/assets/provider-display-DsuWMvVL.js +2 -0
- package/public/assets/{registry-DWCU5c8q.js → registry-Cw38_6gW.js} +2 -2
- package/public/assets/run-card-CpKqRbhg.js +2 -0
- package/public/assets/scroll-text-BKXS1ahr.js +2 -0
- package/public/assets/{secrets-C7GIUATz.js → secrets-DxI-vzSq.js} +2 -2
- package/public/assets/{service-access-settings-C3aujqTG.js → service-access-settings-D9s_VJbd.js} +2 -2
- package/public/assets/{settings-C6sZ9eBa.js → settings-CKZTVGIx.js} +2 -2
- package/public/assets/{shipping-Bu8p1gEw.js → shipping-B9YtnwtG.js} +2 -2
- package/public/assets/{stats-V9Z-GxUd.js → stats-DyUBKyWI.js} +2 -2
- package/public/assets/{status-dot-CVv0iGHL.js → status-dot-DYqlEUhJ.js} +2 -2
- package/public/assets/{store-BvtFdlGX.js → store-DcClXLH0.js} +3 -3
- package/public/assets/{tasks-CXU75HRF.js → tasks-Bh7Chr4-.js} +2 -2
- package/public/assets/{teams-BPf976zb.js → teams-bowI7qVY.js} +2 -2
- package/public/assets/{terminal-viewer-DE9BOe-8.js → terminal-viewer-BgVLHdsU.js} +3 -3
- package/public/assets/{terminal-viewer-impl-D04pjmGh.js → terminal-viewer-impl-Dz22UPy6.js} +2 -2
- package/public/assets/token-estimate-Co-Jdphh.js +2 -0
- package/public/assets/{use-agent-terminal-B1yR456R.js → use-agent-terminal-DSQQ-iY7.js} +2 -2
- package/public/assets/{use-decisions-D-S4tpDf.js → use-decisions-samMQhQf.js} +2 -2
- package/public/assets/use-project-list-59LheVP7.js +2 -0
- package/public/assets/{use-selectors-CnrAk2YP.js → use-selectors-BZa25xEB.js} +2 -2
- package/public/assets/{user-avatar-nBFIcR4M.js → user-avatar-DHxlvUvV.js} +2 -2
- package/public/assets/versioned-prompt-editor-BmED5DnJ.js +8 -0
- package/public/assets/{work-queue-TCjJxeT-.js → work-queue-CSvpuNLz.js} +2 -2
- package/public/assets/{workflow-marker-Cf3Hf2fN.js → workflow-marker-DAZcj5qt.js} +2 -2
- package/public/assets/{workflows-CXQX20Qj.js → workflows-DdmxRSyg.js} +2 -2
- package/public/assets/{workspaces-qSYzKYMA.js → workspaces-BxeKfVuF.js} +2 -2
- package/public/cosmos.html +4 -4
- package/public/index.html +31 -29
- package/runner/plugins/claude/.claude-plugin/plugin.json +1 -1
- package/runner/plugins/claude/hooks/gate-run-guard.provisioned.mjs +31 -1
- package/runner/src/adapters/claude-effort.ts +2 -4
- package/runner/src/adapters/codex-launch-config.ts +4 -5
- package/runner/src/adapters/codex.ts +1 -1
- package/runner/src/adapters/opencode-provider.ts +7 -22
- package/runner/src/adapters/opencode.ts +4 -4
- package/runner/src/agent-runner/credentials.ts +42 -12
- package/runner/src/agent-runner/inbox.ts +27 -0
- package/runner/src/agent-runner/lifecycle-milestones.ts +0 -2
- package/runner/src/bin/claude.ts +4 -0
- package/runner/src/bin/codex.ts +4 -0
- package/runner/src/bin/opencode.ts +4 -0
- package/runner/src/index.ts +5 -2
- package/runner/src/provider-setup.ts +34 -0
- package/runner/src/providers.ts +2 -1
- package/runner/src/runner-core.ts +18 -23
- package/runner/src/spawn-input.ts +2 -1
- package/runner/src/test-run-dedup.ts +59 -56
- package/scripts/cd-config.ts +24 -3
- package/scripts/gate-run-lease.ts +10 -7
- package/scripts/gate.sh +5 -1
- package/src/branch-land-notice.ts +93 -0
- package/src/branch-landed.ts +7 -76
- package/src/bus.ts +19 -20
- package/src/cd-deploy-notify.ts +30 -2
- package/src/cd-host-lag-notify.ts +7 -6
- package/src/ci/incidents.ts +2 -2
- package/src/ci/monitor.ts +5 -8
- package/src/ci/root-missing.ts +2 -7
- package/src/ci/transition-notify.ts +7 -39
- package/src/cli/cd-pauses.ts +19 -0
- package/src/cli/orchestrator.ts +1 -1
- package/src/cli/state.ts +2 -19
- package/src/cli/task-edit.ts +22 -0
- package/src/cli/task.ts +3 -1
- package/src/cli/workflow.ts +8 -2
- package/src/commands-db.ts +10 -6
- package/src/commands-write.ts +8 -0
- package/src/config-store-write.ts +13 -1
- package/src/config-store.ts +25 -14
- package/src/db/activity-async.ts +6 -1
- package/src/db/activity-write-ops.ts +13 -1
- package/src/db/activity.ts +1 -14
- package/src/db/agent-lifecycle-write-ops.ts +1 -0
- package/src/db/agent-meta.ts +2 -2
- package/src/db/agent-ownership-write-ops.ts +4 -0
- package/src/db/agent-search.ts +1 -15
- package/src/db/agents-async.ts +58 -7
- package/src/db/agents-write-ops.ts +28 -5
- package/src/db/agents.ts +81 -54
- package/src/db/artifacts-write-ops.ts +8 -3
- package/src/db/bus-outbox-write-ops.ts +1 -0
- package/src/db/channels-write-ops.ts +4 -0
- package/src/db/ci-incidents-async.ts +5 -5
- package/src/db/ci-incidents-write-ops.ts +2 -2
- package/src/db/claude-api-budget-ops.ts +5 -5
- package/src/db/claude-app-oauth.ts +4 -4
- package/src/db/codex-reset-consumes-write-ops.ts +3 -0
- package/src/db/command-row.ts +10 -2
- package/src/db/commands-list-query.ts +2 -0
- package/src/db/commands-spawn-read.ts +1 -1
- package/src/db/commands-write-ops.ts +21 -0
- package/src/db/config-store-write-ops.ts +9 -2
- package/src/db/continuation-archives-async.ts +5 -0
- package/src/db/continuation-archives-write-ops.ts +9 -0
- package/src/db/continuations.ts +2 -2
- package/src/db/db-writer-worker.ts +8 -1
- package/src/db/delivery-write-ops.ts +5 -0
- package/src/db/deploy-events-async.ts +1 -0
- package/src/db/deploy-events-read-ops.ts +2 -1
- package/src/db/deploy-events.ts +35 -4
- package/src/db/hosts-registration.ts +10 -2
- package/src/db/hosts-write-ops.ts +14 -0
- package/src/db/hosts.ts +9 -6
- package/src/db/inbox-write-ops.ts +4 -0
- package/src/db/inbox.ts +0 -14
- package/src/db/index.ts +2 -0
- package/src/db/insights-write-ops.ts +1 -0
- package/src/db/integrations-async.ts +8 -0
- package/src/db/integrations-ops.ts +15 -0
- package/src/db/integrations.ts +15 -21
- package/src/db/issue-lifecycle.ts +3 -4
- package/src/db/issue-refs-async.ts +20 -0
- package/src/db/issue-refs-write-ops.ts +29 -0
- package/src/db/issue-refs.ts +7 -8
- package/src/db/long-running-work.ts +2 -2
- package/src/db/macos-privacy.ts +1 -1
- package/src/db/main-connection-writes.ts +23 -2
- package/src/db/maintenance-job-reconcile.ts +61 -0
- package/src/db/maintenance-job-runs-async.ts +14 -0
- package/src/db/maintenance-job-write-ops.ts +9 -0
- package/src/db/mappers.ts +2 -14
- package/src/db/merge-lease.ts +1 -15
- package/src/db/message-reads-write-ops.ts +3 -0
- package/src/db/message-write-ops.ts +4 -0
- package/src/db/migrations.ts +7 -15
- package/src/db/orchestrators-async.ts +7 -3
- package/src/db/orchestrators-write-ops.ts +7 -1
- package/src/db/orchestrators.ts +21 -77
- package/src/db/pairs.ts +1 -13
- package/src/db/project-profile-instructions.ts +50 -0
- package/src/db/prompt-versions-ops.ts +1 -0
- package/src/db/prompt-versions.ts +9 -2
- package/src/db/provider-catalog-write-ops.ts +4 -4
- package/src/db/provider-config-history.ts +8 -3
- package/src/db/provider-flap-messages-write-ops.ts +1 -0
- package/src/db/provider-model-seed.ts +34 -0
- package/src/db/provider-quota-lease-write-ops.ts +1 -0
- package/src/db/provider-quota-write-ops.ts +2 -0
- package/src/db/provisioning-write-ops.ts +9 -8
- package/src/db/read-op-marshaling-fixtures.ts +5 -0
- package/src/db/read-ops.ts +4 -0
- package/src/db/routing-policy.ts +3 -4
- package/src/db/schema.ts +9 -3
- package/src/db/secrets-broker-write-ops.ts +5 -5
- package/src/db/secrets-vault-write.ts +7 -7
- package/src/db/services-write-ops.ts +3 -0
- package/src/db/spawn-delegation-state.ts +11 -4
- package/src/db/spawn-tree-cleanup.ts +3 -0
- package/src/db/stats-async.ts +4 -3
- package/src/db/task-entity.ts +23 -2
- package/src/db/task-list.ts +3 -1
- package/src/db/tasks.ts +1 -17
- package/src/db/team-spawn-delegation.ts +1 -1
- package/src/db/teams-write-ops.ts +4 -4
- package/src/db/timer-cutover-write-ops.ts +7 -0
- package/src/db/timer-ingress-write-ops.ts +9 -0
- package/src/db/timer-ingress.ts +7 -1
- package/src/db/timer-operator-write-ops.ts +14 -0
- package/src/db/timer-transfer-write-ops.ts +4 -0
- package/src/db/timer-write-ops.ts +14 -0
- package/src/db/token-db-write-ops.ts +21 -0
- package/src/db/token-standing.ts +15 -11
- package/src/db/user-settings-write-ops.ts +1 -0
- package/src/db/vault-backup.ts +2 -2
- package/src/db/vault-expiry.ts +2 -2
- package/src/db/vault-health.ts +3 -3
- package/src/db/vault-token-ops.ts +8 -8
- package/src/db/web-tool-call-ops.ts +3 -3
- package/src/db/workflow-contact.ts +1 -1
- package/src/db/workflow-task-read-ops.ts +30 -0
- package/src/db/write-ops.ts +15 -1
- package/src/db/writer-fault-seam.ts +5 -2
- package/src/db/writer-gateway.ts +21 -12
- package/src/dispatch-availability.ts +10 -6
- package/src/ephemeral/{landing-ingress-proof-worker.ts → landing-ingress-proof.test-fixture.ts} +4 -2
- package/src/host/disk-alert.ts +121 -0
- package/src/lifecycle-manager.ts +3 -2
- package/src/maintenance/cd-watcher.ts +3 -3
- package/src/maintenance/critical-job-watchdog.ts +16 -17
- package/src/maintenance/index.ts +1 -0
- package/src/maintenance/jobs.ts +3 -2
- package/src/maintenance/scheduler.ts +84 -128
- package/src/maintenance/stalled-delivery-pager.ts +6 -5
- package/src/maintenance/workspaces.ts +1 -1
- package/src/managed-policy.ts +31 -27
- package/src/mcp/index.ts +5 -2
- package/src/mcp/output-descriptions.ts +8 -8
- package/src/mcp/presentation.ts +4 -4
- package/src/mcp/project-profile-instructions.ts +32 -0
- package/src/mcp/tool-groups.ts +1 -1
- package/src/mcp/tools-spawn.ts +4 -3
- package/src/mcp-agent-action.ts +1 -2
- package/src/mcp-host-tools.ts +1 -1
- package/src/mcp-issue-ref-tools.ts +12 -11
- package/src/mcp-maintenance-tools.ts +2 -2
- package/src/mcp-profile-trust-tools.ts +4 -4
- package/src/mcp-provider-catalog.ts +2 -2
- package/src/mcp-task-tools.ts +11 -5
- package/src/mcp-team-template-tools.ts +3 -3
- package/src/mcp-workflow-tools.ts +10 -3
- package/src/notification-types.ts +2 -1
- package/src/operator-alarm.ts +26 -11
- package/src/package-pack.ts +42 -39
- package/src/project-instructions.ts +4 -0
- package/src/project-profile-instruction-text.ts +6 -0
- package/src/project-profile-instructions.ts +20 -0
- package/src/provider-catalog-store.ts +3 -49
- package/src/provider-config-store.ts +12 -11
- package/src/provider-model-seed.ts +1 -18
- package/src/provider-quota-config-store.ts +5 -4
- package/src/provider-secrets.test-fixture.ts +3 -3
- package/src/recipe-runner.ts +2 -2
- package/src/repo-config-source.ts +10 -4
- package/src/routes/agent-profiles.ts +6 -6
- package/src/routes/agents-spawn.ts +1 -1
- package/src/routes/agents.ts +6 -6
- package/src/routes/commands-listing.ts +4 -0
- package/src/routes/commands.ts +2 -2
- package/src/routes/continuation-archives.ts +2 -2
- package/src/routes/host-resource-control.ts +4 -1
- package/src/routes/index.ts +10 -1
- package/src/routes/integrations.ts +24 -50
- package/src/routes/issue-refs.ts +7 -7
- package/src/routes/orchestrator-bootstrap.ts +3 -3
- package/src/routes/orchestrator-host-registration.ts +2 -2
- package/src/routes/orchestrator-host-utilization.ts +3 -1
- package/src/routes/orchestrator-proxy.ts +2 -2
- package/src/routes/orchestrator.ts +4 -4
- package/src/routes/project-profile-instructions.ts +27 -0
- package/src/routes/project-trust.ts +2 -2
- package/src/routes/provider-config.ts +9 -8
- package/src/routes/provider-quota-config.ts +2 -2
- package/src/routes/settings.ts +5 -5
- package/src/routes/stats.ts +6 -6
- package/src/routes/task-http.ts +15 -1
- package/src/routes/task-issues.ts +11 -26
- package/src/routes/tasks.ts +22 -53
- package/src/routes/team-templates.ts +5 -5
- package/src/routes/teams-config.ts +2 -2
- package/src/routes/tokens.ts +12 -5
- package/src/routes/workflows.ts +20 -5
- package/src/routing-policy-normalize.ts +1 -2
- package/src/routing-step-defaults.ts +0 -2
- package/src/runner-token-mint-limit.ts +63 -0
- package/src/runtime-grant.ts +4 -2
- package/src/runtime-tokens.ts +50 -9
- package/src/security.ts +13 -20
- package/src/server-background.ts +1 -1
- package/src/server.ts +5 -2
- package/src/services/host-utilization.ts +23 -0
- package/src/services/idle-epics.ts +5 -6
- package/src/services/issue-lifecycle.ts +57 -61
- package/src/services/issue-refs.ts +9 -13
- package/src/services/kernel-timers-cutover-chaos-worker.ts +12 -7
- package/src/services/kernel-timers-ingress.ts +1 -1
- package/src/services/kernel-timers-request-key-migration-chaos-worker.ts +4 -1
- package/src/services/landed-ancestry.ts +19 -3
- package/src/services/memory-areas.ts +15 -51
- package/src/services/plan-ci-notice.ts +57 -0
- package/src/services/plan-ci-recovery.ts +2 -55
- package/src/services/plan-wake-digest.ts +1 -0
- package/src/services/profile-trust.ts +4 -3
- package/src/services/project-config-read.ts +70 -0
- package/src/services/project-profile-instructions.ts +54 -0
- package/src/services/provisioning-harness/budget-baseline.json +4 -4
- package/src/services/restart-spawn.ts +61 -49
- package/src/services/self-care-state.ts +2 -1
- package/src/services/self-effort.ts +5 -5
- package/src/services/send-message.ts +5 -1
- package/src/services/spawn-agent.ts +13 -2
- package/src/services/spawn-chain-inspector.ts +6 -13
- package/src/services/spawn-policy.ts +68 -0
- package/src/services/spawn-tree-cleanup.ts +2 -2
- package/src/services/task-dispatch.ts +3 -0
- package/src/services/task-state-reconcile.ts +6 -14
- package/src/services/team-templates.ts +9 -8
- package/src/services/transient-agent-reaper.ts +3 -1
- package/src/services/workflow-auto-start.ts +25 -13
- package/src/services/workflow-ci-main.ts +1 -1
- package/src/services/workflow-deferred-cleanup.ts +4 -2
- package/src/services/workflow-effect-driver.ts +2 -0
- package/src/services/workflow-effects.ts +18 -11
- package/src/services/workflow-land-notice.ts +10 -0
- package/src/services/workflow-pause-text.ts +43 -0
- package/src/services/workflow-reconcile.ts +13 -11
- package/src/services/workflow-run-view.ts +2 -0
- package/src/services/workflow-runs.ts +29 -13
- package/src/services/workflow-supervisor-state.ts +5 -0
- package/src/services/workflow-supervisor.ts +7 -3
- package/src/settings/registry.ts +1 -2
- package/src/spawn-command.ts +4 -4
- package/src/spawn-models.ts +10 -12
- package/src/spawn-placement.ts +1 -1
- package/src/spawn-targets.ts +1 -1
- package/src/startup-context-injection.ts +1 -0
- package/src/state-adoption/cd-cutover.ts +53 -7
- package/src/state-adoption/fleet-cutover.ts +35 -0
- package/src/state-adoption/fleet-plan.ts +36 -0
- package/src/state-adoption/index.ts +2 -2
- package/src/state-adoption/linux-plan.ts +2 -2
- package/src/state-adoption/linux.ts +2 -2
- package/src/state-adoption/macos-plan.ts +2 -2
- package/src/state-adoption/macos.ts +1 -1
- package/src/steward.ts +7 -6
- package/src/task-dispatch-live.ts +1 -1
- package/src/task-dispatcher.ts +1 -1
- package/src/teams-config-store.ts +4 -3
- package/src/token-db-write.ts +10 -0
- package/src/workspace-command-settle.ts +2 -1
- package/src/workspace-steward-wake.ts +2 -2
- package/node_modules/@humwick/kernel/LICENSE +0 -167
- package/node_modules/@humwick/kernel/async-entity-persistence.ts +0 -344
- package/node_modules/@humwick/kernel/async-event-log.ts +0 -107
- package/node_modules/@humwick/kernel/automations.pilot.ts +0 -147
- package/node_modules/@humwick/kernel/config.ts +0 -111
- package/node_modules/@humwick/kernel/contract.ts +0 -572
- package/node_modules/@humwick/kernel/control-authz.ts +0 -281
- package/node_modules/@humwick/kernel/control.ts +0 -645
- package/node_modules/@humwick/kernel/effects.ts +0 -493
- package/node_modules/@humwick/kernel/event-log.ts +0 -319
- package/node_modules/@humwick/kernel/http-transport.ts +0 -384
- package/node_modules/@humwick/kernel/identity-grammar.ts +0 -20
- package/node_modules/@humwick/kernel/identity.ts +0 -248
- package/node_modules/@humwick/kernel/index.ts +0 -28
- package/node_modules/@humwick/kernel/kernel-persistence.ts +0 -181
- package/node_modules/@humwick/kernel/landing-incident.ts +0 -306
- package/node_modules/@humwick/kernel/landing.ts +0 -953
- package/node_modules/@humwick/kernel/manifest-validation.ts +0 -460
- package/node_modules/@humwick/kernel/mcp-transport.ts +0 -109
- package/node_modules/@humwick/kernel/message-authority-chaos-worker.ts +0 -200
- package/node_modules/@humwick/kernel/message-authority.ts +0 -281
- package/node_modules/@humwick/kernel/module-host.ts +0 -722
- package/node_modules/@humwick/kernel/openapi-init.ts +0 -14
- package/node_modules/@humwick/kernel/package.json +0 -47
- package/node_modules/@humwick/kernel/persistence-schema.ts +0 -248
- package/node_modules/@humwick/kernel/persistence.ts +0 -510
- package/node_modules/@humwick/kernel/registry.ts +0 -60
- package/node_modules/@humwick/kernel/sqlite-kernel-persistence.ts +0 -499
- package/node_modules/@humwick/kernel/sqlite-module-host.ts +0 -87
- package/node_modules/@humwick/kernel/timers-chaos-worker.ts +0 -186
- package/node_modules/@humwick/kernel/timers.pilot.ts +0 -1411
- package/node_modules/@humwick/kernel/workflow-activation.ts +0 -25
- package/node_modules/@humwick/kernel/workflow-backstop.ts +0 -40
- package/node_modules/@humwick/kernel/workflow-cancel-tree.ts +0 -20
- package/node_modules/@humwick/kernel/workflow-chaos-worker.ts +0 -213
- package/node_modules/@humwick/kernel/workflow-composition.ts +0 -231
- package/node_modules/@humwick/kernel/workflow-container.ts +0 -72
- package/node_modules/@humwick/kernel/workflow-control.test-fixture.ts +0 -42
- package/node_modules/@humwick/kernel/workflow-control.ts +0 -178
- package/node_modules/@humwick/kernel/workflow-definition.ts +0 -507
- package/node_modules/@humwick/kernel/workflow-dispatch.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-foreach.ts +0 -167
- package/node_modules/@humwick/kernel/workflow-journal-codec.ts +0 -339
- package/node_modules/@humwick/kernel/workflow-journal.ts +0 -922
- package/node_modules/@humwick/kernel/workflow-lane.ts +0 -48
- package/node_modules/@humwick/kernel/workflow-lease-owner.ts +0 -60
- package/node_modules/@humwick/kernel/workflow-recovery.test-fixture.ts +0 -19
- package/node_modules/@humwick/kernel/workflow-runtime.ts +0 -938
- package/node_modules/@humwick/kernel/workflow-script.ts +0 -11
- package/node_modules/@humwick/kernel/workflow-state.ts +0 -299
- package/node_modules/@humwick/kernel/workflow-step-commit.ts +0 -195
- package/node_modules/@humwick/kernel/workflow-transitions.ts +0 -317
- package/node_modules/@humwick/kernel/workflow-values.ts +0 -153
- package/node_modules/@humwick/kernel/workflow.pilot.ts +0 -376
- package/node_modules/@humwick/offload/LICENSE +0 -167
- package/node_modules/@humwick/offload/README.md +0 -57
- package/node_modules/@humwick/offload/dist/async-runner.d.ts +0 -18
- package/node_modules/@humwick/offload/dist/async-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/async-runner.js +0 -158
- package/node_modules/@humwick/offload/dist/async-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.d.ts +0 -25
- package/node_modules/@humwick/offload/dist/envelope.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/envelope.js +0 -80
- package/node_modules/@humwick/offload/dist/envelope.js.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts +0 -10
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js +0 -59
- package/node_modules/@humwick/offload/dist/fixtures/worker-task.js.map +0 -1
- package/node_modules/@humwick/offload/dist/index.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/index.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/index.js +0 -5
- package/node_modules/@humwick/offload/dist/index.js.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts +0 -62
- package/node_modules/@humwick/offload/dist/subprocess-runner.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/subprocess-runner.js +0 -295
- package/node_modules/@humwick/offload/dist/subprocess-runner.js.map +0 -1
- package/node_modules/@humwick/offload/dist/types.d.ts +0 -111
- package/node_modules/@humwick/offload/dist/types.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/types.js +0 -176
- package/node_modules/@humwick/offload/dist/types.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts +0 -23
- package/node_modules/@humwick/offload/dist/worker-pool.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-pool.js +0 -435
- package/node_modules/@humwick/offload/dist/worker-pool.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts +0 -2
- package/node_modules/@humwick/offload/dist/worker-runtime.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker-runtime.js +0 -27
- package/node_modules/@humwick/offload/dist/worker-runtime.js.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.d.ts +0 -5
- package/node_modules/@humwick/offload/dist/worker.d.ts.map +0 -1
- package/node_modules/@humwick/offload/dist/worker.js +0 -1
- package/node_modules/@humwick/offload/dist/worker.js.map +0 -1
- package/node_modules/@humwick/offload/package.json +0 -46
- package/node_modules/@humwick/offload/src/async-runner.ts +0 -170
- package/node_modules/@humwick/offload/src/envelope.ts +0 -92
- package/node_modules/@humwick/offload/src/fixtures/worker-task.ts +0 -49
- package/node_modules/@humwick/offload/src/index.ts +0 -4
- package/node_modules/@humwick/offload/src/subprocess-runner.ts +0 -334
- package/node_modules/@humwick/offload/src/types.ts +0 -235
- package/node_modules/@humwick/offload/src/worker-pool.ts +0 -463
- package/node_modules/@humwick/offload/src/worker-runtime.ts +0 -32
- package/node_modules/@humwick/offload/src/worker.ts +0 -5
- package/public/assets/agent-liveness-DyqxfB-t.js +0 -2
- package/public/assets/agent-profiles-BpI_jTxq.js +0 -2
- package/public/assets/fleet-BL4UXS_k.js +0 -2
- package/public/assets/index-B7ZerHLY.css +0 -2
- package/public/assets/index-BK0WV6hF.js +0 -15
- package/public/assets/projects-B_lmcqfO.js +0 -2
- package/public/assets/provider-display-DbLWpP3j.js +0 -2
- package/public/assets/run-card-CO_bguQf.js +0 -2
- package/public/assets/use-project-list-B-T2Bnnn.js +0 -2
- package/public/assets/versioned-prompt-editor-Diu8BIaM.js +0 -8
- package/runner/src/gate-run-lease-probe.ts +0 -38
- package/src/db/claude-catalog-reconcile.ts +0 -27
- package/src/routing-model-aliases.ts +0 -21
|
@@ -5,7 +5,7 @@ import { McpAuthError } from "./mcp-errors";
|
|
|
5
5
|
import { ValidationError } from "./db";
|
|
6
6
|
import { authContextFromMcp } from "./services/auth-context";
|
|
7
7
|
import { ServiceAuthError } from "./services/errors";
|
|
8
|
-
import { cancelWorkflowRun, getWorkflowRun, resumeWorkflowRun, startWorkflowRun } from "./services/workflow-runs";
|
|
8
|
+
import { cancelWorkflowRun, getWorkflowRun, pauseWorkflowRun, resumeWorkflowRun, startWorkflowRun } from "./services/workflow-runs";
|
|
9
9
|
import { parseWorkflowPins } from "./services/workflow-pins";
|
|
10
10
|
import { cleanString, taskIdField } from "./validation";
|
|
11
11
|
|
|
@@ -48,7 +48,7 @@ export const WORKFLOW_TOOLS = [
|
|
|
48
48
|
{
|
|
49
49
|
name: "relay_workflow_resume",
|
|
50
50
|
description:
|
|
51
|
-
"Resume or answer/escalate a decision.",
|
|
51
|
+
"Resume, pause/unpause, or answer/escalate a decision.",
|
|
52
52
|
requiredScopes: ["task:write"],
|
|
53
53
|
inputSchema: {
|
|
54
54
|
type: "object",
|
|
@@ -66,6 +66,7 @@ export const WORKFLOW_TOOLS = [
|
|
|
66
66
|
activationId: { type: "string" },
|
|
67
67
|
step: { type: "string" },
|
|
68
68
|
note: { type: "string" },
|
|
69
|
+
pause: { type: "boolean" },
|
|
69
70
|
pins: PINS_PROP,
|
|
70
71
|
},
|
|
71
72
|
required: ["runId"],
|
|
@@ -112,7 +113,7 @@ type McpAuthLike = Parameters<typeof authContextFromMcp>[0];
|
|
|
112
113
|
|
|
113
114
|
function mutationReceipt(full: Record<string, unknown>, verbose: unknown): Record<string, unknown> {
|
|
114
115
|
if (verbose === true) return full;
|
|
115
|
-
const fields = ["runId", "taskId", "workflow", "status", "step", "round", "callerAgentId", "budget", "existing", "resumed", "cancelled", "reason", "warnings"];
|
|
116
|
+
const fields = ["runId", "taskId", "workflow", "status", "step", "round", "callerAgentId", "budget", "existing", "resumed", "cancelled", "paused", "reason", "warnings"];
|
|
116
117
|
return Object.fromEntries(fields.filter(key => full[key] !== undefined).map(key => [key, full[key]]));
|
|
117
118
|
}
|
|
118
119
|
|
|
@@ -132,6 +133,12 @@ export async function relayWorkflowTool(auth: McpAuthLike, name: string, args: R
|
|
|
132
133
|
if (!runId) throw new ValidationError("runId is required");
|
|
133
134
|
const step = cleanString(args.step, "step", { max: 64 });
|
|
134
135
|
const note = cleanString(args.note, "note", { max: 8000 });
|
|
136
|
+
if (args.pause !== undefined) {
|
|
137
|
+
// #3757 — pause (note is the required reason) or unpause; nothing else rides along.
|
|
138
|
+
if (typeof args.pause !== "boolean") throw new ValidationError("pause must be a boolean");
|
|
139
|
+
if (step || args.pins !== undefined || args.decision !== undefined || args.activationId !== undefined) throw new ValidationError("pause takes only runId and, to pause, note as the reason");
|
|
140
|
+
return mutationReceipt(await pauseWorkflowRun({ runId, pause: args.pause, ...(note ? { reason: note } : {}) }, ctx), args.verbose);
|
|
141
|
+
}
|
|
135
142
|
const pins = parseWorkflowPins(args.pins);
|
|
136
143
|
return mutationReceipt(await resumeWorkflowRun({ runId, decision: parseWorkflowDecisionResponse(args.decision), activationId: cleanString(args.activationId, "activationId", { max: 2000 }), ...(step ? { step } : {}), ...(note ? { note } : {}), ...(pins ? { pins } : {}) }, ctx), args.verbose);
|
|
137
144
|
}
|
|
@@ -97,7 +97,8 @@ export type NotificationType =
|
|
|
97
97
|
| "ci.config_mismatch"
|
|
98
98
|
| "ci.root_missing"
|
|
99
99
|
// #1645 — a critical maintenance job is not running (disabled, held indefinitely, a lapsed pause
|
|
100
|
-
// nobody resumed, or simply silent past several of its own intervals).
|
|
100
|
+
// nobody resumed, or simply silent past several of its own intervals). Also carries host disk
|
|
101
|
+
// alerts (#3762) — a new type would grow three MCP tool schemas past their pinned budgets.
|
|
101
102
|
| "maintenance.degraded";
|
|
102
103
|
|
|
103
104
|
/**
|
package/src/operator-alarm.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createActivityEventWithResult } from "./db";
|
|
2
|
+
import { createActivityEventByClientIdAsync } from "./db/activity-async";
|
|
2
3
|
import { emitRelayEvent } from "./events";
|
|
3
4
|
|
|
4
5
|
export interface OperatorAlarmInput {
|
|
@@ -20,22 +21,36 @@ export interface OperatorAlarmInput {
|
|
|
20
21
|
// done. This raises a distinct `operator.alarm` relay event (dashboard banner) plus a
|
|
21
22
|
// persisted `operator`-kind activity event, so a relay with no reachable escalation target
|
|
22
23
|
// is observable instead of looping forever in the dark.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
const alarmEvent = (input: OperatorAlarmInput) => ({
|
|
25
|
+
clientId: input.clientId,
|
|
26
|
+
kind: "operator" as const,
|
|
27
|
+
title: input.subject,
|
|
28
|
+
body: input.detail,
|
|
29
|
+
icon: "ti-alert-octagon",
|
|
30
|
+
view: input.view ?? "orchestrators",
|
|
31
|
+
metadata: { source: input.source, operatorAlarm: true, ...(input.metadata ?? {}) },
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
function emitAlarm(input: OperatorAlarmInput): void {
|
|
34
35
|
emitRelayEvent({
|
|
35
36
|
type: "operator.alarm",
|
|
36
37
|
source: input.source,
|
|
37
38
|
subject: input.subject,
|
|
38
39
|
data: { subject: input.subject, detail: input.detail, ...(input.metadata ?? {}) },
|
|
39
40
|
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function raiseOperatorAlarm(input: OperatorAlarmInput): boolean {
|
|
44
|
+
const { created } = createActivityEventWithResult(alarmEvent(input));
|
|
45
|
+
if (input.dedupeEvent && !created) return false;
|
|
46
|
+
emitAlarm(input);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Same as `raiseOperatorAlarm`, with the activity row written on the writer thread. */
|
|
51
|
+
export async function raiseOperatorAlarmAsync(input: OperatorAlarmInput): Promise<boolean> {
|
|
52
|
+
const { created } = await createActivityEventByClientIdAsync(alarmEvent(input));
|
|
53
|
+
if (input.dedupeEvent && !created) return false;
|
|
54
|
+
emitAlarm(input);
|
|
40
55
|
return true;
|
|
41
56
|
}
|
package/src/package-pack.ts
CHANGED
|
@@ -131,6 +131,42 @@ export function privateWorkspaceDependencies(packageDir: string): string[] {
|
|
|
131
131
|
return privateDeps;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
type DependencyMap = Record<string, string>;
|
|
135
|
+
export type ConsumerManifest = {
|
|
136
|
+
dependencies?: DependencyMap;
|
|
137
|
+
optionalDependencies?: DependencyMap;
|
|
138
|
+
bundleDependencies?: string[];
|
|
139
|
+
};
|
|
140
|
+
export type VendoredManifest = {
|
|
141
|
+
version?: string;
|
|
142
|
+
dependencies?: DependencyMap;
|
|
143
|
+
optionalDependencies?: DependencyMap;
|
|
144
|
+
peerDependencies?: DependencyMap;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Pin and bundle a vendored private dep on its consumer (bundleDependencies keeps the nested copy
|
|
148
|
+
// across reinstall/prune, #1772), and move the dep's own dependencies onto the consumer. npm counts
|
|
149
|
+
// every dependency a bundled package declares as bundled too and never extracts it, so a global
|
|
150
|
+
// install left @humwick/sdk, hono, zod … as empty folders (#3301). The vendored code still resolves
|
|
151
|
+
// them by walking up node_modules.
|
|
152
|
+
export function bundleVendoredDependency(consumer: ConsumerManifest, depName: string, vendored: VendoredManifest): void {
|
|
153
|
+
delete consumer.optionalDependencies?.[depName];
|
|
154
|
+
consumer.dependencies ??= {};
|
|
155
|
+
consumer.dependencies[depName] = vendored.version ?? "0.0.0";
|
|
156
|
+
consumer.bundleDependencies ??= [];
|
|
157
|
+
if (!consumer.bundleDependencies.includes(depName)) consumer.bundleDependencies.push(depName);
|
|
158
|
+
for (const field of ["dependencies", "optionalDependencies", "peerDependencies"] as const) {
|
|
159
|
+
for (const [name, spec] of Object.entries(vendored[field] ?? {})) {
|
|
160
|
+
const declared = consumer.dependencies[name] ?? consumer.optionalDependencies?.[name];
|
|
161
|
+
if (declared !== undefined && declared !== spec) {
|
|
162
|
+
fail(`package-pack: bundled ${depName} needs ${name}@${spec} but its consumer declares ${name}@${declared}; align the two specs`);
|
|
163
|
+
}
|
|
164
|
+
if (declared === undefined) consumer.dependencies[name] = spec;
|
|
165
|
+
}
|
|
166
|
+
delete vendored[field];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
134
170
|
// Vendor a PRIVATE (unpublished, `workspace:*`) workspace dependency into the packed
|
|
135
171
|
// tarball as a nested `node_modules/<dep>` package, pin its bundled version in
|
|
136
172
|
// the packed manifest, and merge its own runtime dependencies up into the consumer so
|
|
@@ -148,31 +184,19 @@ async function bundlePrivateWorkspaceDeps(cwd: string, packageDir: string, tarba
|
|
|
148
184
|
try {
|
|
149
185
|
tar(["-xzf", tarball, "-C", stage]);
|
|
150
186
|
const pkgRoot = join(stage, "package");
|
|
151
|
-
const packed = JSON.parse(readFileSync(join(pkgRoot, "package.json"), "utf8")) as
|
|
152
|
-
dependencies?: Record<string, string>;
|
|
153
|
-
optionalDependencies?: Record<string, string>;
|
|
154
|
-
bundleDependencies?: string[];
|
|
155
|
-
};
|
|
187
|
+
const packed = JSON.parse(readFileSync(join(pkgRoot, "package.json"), "utf8")) as ConsumerManifest;
|
|
156
188
|
|
|
157
189
|
for (const depName of privateDeps) {
|
|
158
190
|
const depDir = dirByName.get(depName);
|
|
159
191
|
if (!depDir) fail(`package-pack: private workspace dep ${depName} not found in root workspaces`);
|
|
160
192
|
const depSrc = resolve(cwd, depDir);
|
|
161
|
-
const depManifest = JSON.parse(readFileSync(join(depSrc, "package.json"), "utf8")) as {
|
|
162
|
-
version?: string;
|
|
163
|
-
dependencies?: Record<string, string>;
|
|
164
|
-
};
|
|
165
193
|
|
|
166
194
|
// Vendor the private package's REAL published file set by packing it exactly as it would be
|
|
167
195
|
// published — `npm pack` honors the dep's own `files`/`exports` and runs its `prepack` build —
|
|
168
196
|
// then extract the packed `package/` into node_modules/<dep>. Copying only flat root *.ts (the
|
|
169
197
|
// pre-#1838 behavior) silently shipped a package.json-ONLY stub for any dep whose entrypoint is
|
|
170
|
-
// a BUILT dist or lives in a nested dir
|
|
171
|
-
//
|
|
172
|
-
// import with "Cannot find package '@humwick/offload'". Packing is the canonical publish
|
|
173
|
-
// representation and works for BOTH a raw-.ts dep (@humwick/kernel, exports ./index.ts) and a
|
|
174
|
-
// built-dist dep (@humwick/offload) — and for any future published-package offload adopter
|
|
175
|
-
// (orchestrator #1807, later waves) with no per-dep special-casing here.
|
|
198
|
+
// a BUILT dist or lives in a nested dir (@humwick/offload's `main` is ./dist/index.js). Packing
|
|
199
|
+
// works for BOTH a raw-.ts dep (@humwick/kernel) and a built-dist dep with no special-casing.
|
|
176
200
|
const vendorDir = join(pkgRoot, "node_modules", depName);
|
|
177
201
|
const depStage = mkdtempSync(join(packDir, "dep-pack-"));
|
|
178
202
|
try {
|
|
@@ -186,30 +210,9 @@ async function bundlePrivateWorkspaceDeps(cwd: string, packageDir: string, tarba
|
|
|
186
210
|
} finally {
|
|
187
211
|
rmSync(depStage, { recursive: true, force: true });
|
|
188
212
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// package: the nested node_modules/<dep> is treated as an intentional, protected part of
|
|
193
|
-
// the tarball — preserved on install, never fetched from the registry (bundled wins over
|
|
194
|
-
// the pinned version), and — critically — never pruned as "extraneous" on a second
|
|
195
|
-
// `npm install` / `npm ci` / dedupe / prune pass. Merely DROPPING the workspace:* spec
|
|
196
|
-
// (the pre-#1772 behavior) let the FIRST install keep the vendored copy but any later
|
|
197
|
-
// tree reconciliation deleted node_modules/<dep> entirely, breaking every
|
|
198
|
-
// `<dep>/<subpath>` import at runtime (e.g. @humwick/kernel/workflow-journal-codec
|
|
199
|
-
// → CLI crash at startup). See #1772.
|
|
200
|
-
for (const field of ["dependencies", "optionalDependencies"] as const) {
|
|
201
|
-
if (packed[field]) delete packed[field][depName];
|
|
202
|
-
}
|
|
203
|
-
packed.dependencies ??= {};
|
|
204
|
-
packed.dependencies[depName] = depManifest.version ?? "0.0.0";
|
|
205
|
-
packed.bundleDependencies ??= [];
|
|
206
|
-
if (!packed.bundleDependencies.includes(depName)) packed.bundleDependencies.push(depName);
|
|
207
|
-
|
|
208
|
-
// Hoist the private dep's own runtime deps so the clean-env install resolves them from
|
|
209
|
-
// the registry (kernel imports zod/hono/…).
|
|
210
|
-
for (const [name, spec] of Object.entries(depManifest.dependencies ?? {})) {
|
|
211
|
-
packed.dependencies[name] ??= spec;
|
|
212
|
-
}
|
|
213
|
+
const vendored = JSON.parse(readFileSync(join(vendorDir, "package.json"), "utf8")) as VendoredManifest;
|
|
214
|
+
bundleVendoredDependency(packed, depName, vendored);
|
|
215
|
+
writeFileSync(join(vendorDir, "package.json"), JSON.stringify(vendored, null, 2) + "\n");
|
|
213
216
|
}
|
|
214
217
|
|
|
215
218
|
writeFileSync(join(pkgRoot, "package.json"), JSON.stringify(packed, null, 2) + "\n");
|
|
@@ -2,6 +2,7 @@ import { composeMemoryPreambleAsync } from "./memory-preamble-async";
|
|
|
2
2
|
import { composeHostAwareness } from "./host-awareness";
|
|
3
3
|
import { composeGuideIndex } from "./guides";
|
|
4
4
|
import { profileInstructionBlocks } from "./profile-instruction-blocks";
|
|
5
|
+
import { projectProfileInstructionBlock } from "./project-profile-instructions";
|
|
5
6
|
// Spawn-time instruction sources (#557) — the relay-owned composer that assembles what a spawned
|
|
6
7
|
// agent's systemPromptAppend says, from declared sources only, never from host CLAUDE.md.
|
|
7
8
|
//
|
|
@@ -283,6 +284,7 @@ export function composeSpawnInstructionsWithEvents(input: {
|
|
|
283
284
|
* host → project`, audience-filtered by `profile`). Absent → no memory block at all, so a
|
|
284
285
|
* caller that does not know the identity produces a byte-identical pre-#1565 spawn. */
|
|
285
286
|
memoryIdentity?: MemoryIdentity;
|
|
287
|
+
projectId?: string;
|
|
286
288
|
profile?: Pick<AgentProfile, "instructions" | "maxSpawnedAgents" | "hostAwareness" | "roleAssets"> & { name?: string; relay?: AgentProfile["relay"] };
|
|
287
289
|
spawnedBy?: string;
|
|
288
290
|
/** #3045 — a workflow step agent: its step reporting block replaces the spawned-child report-up. */
|
|
@@ -475,6 +477,8 @@ export function composeSpawnInstructionsWithEvents(input: {
|
|
|
475
477
|
const { system: profileSystem, append: profileAppend } = profileInstructionBlocks(input.profile, input.memoryIdentity?.provider);
|
|
476
478
|
if (profileSystem) appendBlocks.push(profileSystem);
|
|
477
479
|
appendBlocks.push(...profileAppend);
|
|
480
|
+
const projectProfile = projectProfileInstructionBlock(input.projectId ?? input.memoryIdentity?.projectId, input.profile?.name ?? input.memoryIdentity?.profile);
|
|
481
|
+
if (projectProfile) { appendBlocks.push(projectProfile.content); relayInjectionEvents.push(projectProfile.event); }
|
|
478
482
|
// After the profile, so the step rule is the last word over a charter's report-to-spawner text.
|
|
479
483
|
if (input.workflowRunId) {
|
|
480
484
|
const instruction = renderTemplate("spawn.reportup.workflow-step", { runId: input.workflowRunId });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { assertNoControlBytes, ValidationError } from "@humwick/sdk";
|
|
2
|
+
|
|
3
|
+
export function validateProjectProfileInstructionText(value: unknown, source: string): asserts value is string {
|
|
4
|
+
if (typeof value !== "string" || value.length > 16_000) throw new ValidationError(`${source} must be a string up to 16000 characters`);
|
|
5
|
+
assertNoControlBytes(value, source);
|
|
6
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { errMessage } from "@humwick/sdk";
|
|
2
|
+
import { getProjectProfileInstructions } from "./db/project-profile-instructions";
|
|
3
|
+
import { validateProjectProfileInstructionText } from "./project-profile-instruction-text";
|
|
4
|
+
|
|
5
|
+
/** #3515 — one optional block at the charter seam, independent of project memory's switch. */
|
|
6
|
+
export function projectProfileInstructionBlock(projectId: string | undefined, profile: string | undefined) {
|
|
7
|
+
if (!projectId || !profile) return;
|
|
8
|
+
const source = `project ${projectId} profile ${profile} instructions`;
|
|
9
|
+
try {
|
|
10
|
+
const entry = getProjectProfileInstructions({ projectId, profile });
|
|
11
|
+
validateProjectProfileInstructionText(entry.template, source);
|
|
12
|
+
const content = entry.template.trim();
|
|
13
|
+
if (!content) return;
|
|
14
|
+
return { content, event: { category: "instructions" as const,
|
|
15
|
+
summary: `injected ${source} v${entry.version}`,
|
|
16
|
+
detail: { source: "project-profile-instructions", projectId, profile, version: entry.version, content } } };
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.warn(`[launch] skipped ${source}: ${errMessage(error)}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deriveProviderDisabledState,
|
|
3
3
|
disabledProviderSet,
|
|
4
|
-
|
|
4
|
+
providerMetadataList,
|
|
5
5
|
type ProviderCatalogEntry,
|
|
6
6
|
type ProviderContextThreshold,
|
|
7
7
|
type ProviderEnablementSetting,
|
|
@@ -44,7 +44,7 @@ export interface ProviderModelOverrideInput {
|
|
|
44
44
|
|
|
45
45
|
function listProviderModelOverrides(): ProviderModelOverride[] {
|
|
46
46
|
const rows = getDb()
|
|
47
|
-
.query("SELECT * FROM provider_model_overrides ORDER BY provider ASC,
|
|
47
|
+
.query("SELECT * FROM provider_model_overrides ORDER BY provider ASC, rowid ASC")
|
|
48
48
|
.all() as ProviderModelOverrideRow[];
|
|
49
49
|
return rows.map(rowToOverride).filter((entry): entry is ProviderModelOverride => Boolean(entry));
|
|
50
50
|
}
|
|
@@ -120,7 +120,7 @@ export function setProviderDefaultModel(provider: SpawnProvider, alias: string,
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
export function effectiveProviderCatalogList(now = Date.now()): ProviderCatalogEntry[] {
|
|
123
|
-
const catalog = mergeProviderCatalog(
|
|
123
|
+
const catalog = mergeProviderCatalog(providerMetadataList(), listProviderModelOverrides());
|
|
124
124
|
const defaults = getDb().query("SELECT provider, alias FROM provider_model_defaults").all() as Array<{ provider: string; alias: string }>;
|
|
125
125
|
for (const { provider, alias } of defaults) {
|
|
126
126
|
const entry = catalog.find((item) => item.provider === provider);
|
|
@@ -215,9 +215,6 @@ function normalizeOverrideInput(input: ProviderModelOverrideInput): ProviderMode
|
|
|
215
215
|
if (limits) entry.limits = limits;
|
|
216
216
|
else delete entry.limits;
|
|
217
217
|
delete entry.disabled;
|
|
218
|
-
// #368 — unavailable is a static catalog fact (provider-side suspension), not an operator toggle;
|
|
219
|
-
// strip it from DB overrides so an admin can't accidentally clear a catalog-level suspension.
|
|
220
|
-
delete entry.unavailable;
|
|
221
218
|
// #2598 — `deleted` is a row-level tombstone column, never part of a stored entry blob.
|
|
222
219
|
delete (entry as unknown as Record<string, unknown>).deleted;
|
|
223
220
|
return {
|
|
@@ -288,49 +285,6 @@ function allowlistedLimitConfidence(value: unknown): ProviderModelLimitWindow["c
|
|
|
288
285
|
: "declared";
|
|
289
286
|
}
|
|
290
287
|
|
|
291
|
-
/**
|
|
292
|
-
* #2598 — additive, idempotent backfill of every static-catalog model into `provider_model_overrides`,
|
|
293
|
-
* so the whole catalogue is uniformly DB-backed and operator-editable. Rules:
|
|
294
|
-
* - INSERT-ONLY-IF-ABSENT (`ON CONFLICT DO NOTHING`): an existing row — a prior seed OR an operator
|
|
295
|
-
* edit OR an operator delete-tombstone — is never touched, so operator edits ALWAYS win and a
|
|
296
|
-
* deleted static model is never resurrected. Re-runnable; a re-run inserts only genuinely NEW
|
|
297
|
-
* static models (e.g. added by a later release).
|
|
298
|
-
* - SKIP disabled/unavailable static models: materializing them would strip those flags at the
|
|
299
|
-
* write chokepoint (#368/#643) and resurrect a suspended model as spawnable. They stay
|
|
300
|
-
* static-only until an operator explicitly adds them.
|
|
301
|
-
* Stamped `updated_by = <stamp>` (e.g. `seed:<version>`) purely for provenance; precedence is decided
|
|
302
|
-
* by row EXISTENCE, not by parsing the stamp.
|
|
303
|
-
*/
|
|
304
|
-
export function seedProviderModelOverrides(stamp: string, now = Date.now()): { inserted: number } {
|
|
305
|
-
const db = getDb();
|
|
306
|
-
const existing = new Map<string, Set<string>>();
|
|
307
|
-
for (const row of db.query("SELECT provider, alias FROM provider_model_overrides").all() as Array<{ provider: string; alias: string }>) {
|
|
308
|
-
let aliases = existing.get(row.provider);
|
|
309
|
-
if (!aliases) existing.set(row.provider, (aliases = new Set()));
|
|
310
|
-
aliases.add(row.alias);
|
|
311
|
-
}
|
|
312
|
-
let inserted = 0;
|
|
313
|
-
const insert = db.query(`
|
|
314
|
-
INSERT INTO provider_model_overrides (provider, alias, entry, deleted, disabled, updated_at, updated_by)
|
|
315
|
-
VALUES (?, ?, ?, 0, 0, ?, ?)
|
|
316
|
-
ON CONFLICT(provider, alias) DO NOTHING
|
|
317
|
-
`);
|
|
318
|
-
const seed = db.transaction(() => {
|
|
319
|
-
for (const providerEntry of providerCatalogList()) {
|
|
320
|
-
const seen = existing.get(providerEntry.provider);
|
|
321
|
-
for (const model of providerEntry.models) {
|
|
322
|
-
if (model.disabled || model.unavailable) continue;
|
|
323
|
-
if (seen?.has(model.alias)) continue;
|
|
324
|
-
const normalized = normalizeOverrideInput({ provider: providerEntry.provider, alias: model.alias, entry: model, updatedBy: stamp });
|
|
325
|
-
const result = insert.run(normalized.provider, normalized.alias, JSON.stringify(normalized.entry), now, normalized.updatedBy ?? null);
|
|
326
|
-
if (result.changes > 0) inserted++;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
seed();
|
|
331
|
-
return { inserted };
|
|
332
|
-
}
|
|
333
|
-
|
|
334
288
|
function rowToOverride(row: ProviderModelOverrideRow): ProviderModelOverride | undefined {
|
|
335
289
|
const parsed = parseJson<ProviderModelCatalogEntry | undefined>(row.entry, undefined);
|
|
336
290
|
if (!parsed || typeof parsed.alias !== "string") return undefined;
|
|
@@ -4,7 +4,8 @@ import { hostname } from "node:os";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { ValidationError, listOrchestrators } from "./db";
|
|
6
6
|
import { isSecretEnvKey } from "./db/provider-config-secrets";
|
|
7
|
-
import { getConfig, listConfig
|
|
7
|
+
import { getConfig, listConfig } from "./config-store";
|
|
8
|
+
import { setConfigAsync } from "./config-store-write";
|
|
8
9
|
import { localOrchestratorIdFromEnv, providerConfigHomeFromEnv } from "./config";
|
|
9
10
|
import { cleanString, cleanStringArray, optionalEnum } from "./validation";
|
|
10
11
|
import { emitConfigChanged } from "./sse";
|
|
@@ -90,11 +91,11 @@ export function listProviderConfigEntries(host = defaultProviderConfigHost()): R
|
|
|
90
91
|
) as Record<SpawnProvider, ProviderConfigEntry>;
|
|
91
92
|
}
|
|
92
93
|
|
|
93
|
-
export function
|
|
94
|
+
export async function setProviderConfigAsync(
|
|
94
95
|
provider: string,
|
|
95
96
|
value: unknown,
|
|
96
97
|
opts: { host?: string; updatedBy?: string } = {},
|
|
97
|
-
): ProviderConfigEntry {
|
|
98
|
+
): Promise<ProviderConfigEntry> {
|
|
98
99
|
const cleanProvider = normalizeProviderConfigProvider(provider);
|
|
99
100
|
const host = normalizeProviderConfigHost(opts.host ?? defaultProviderConfigHost());
|
|
100
101
|
const normalized = cleanProviderConfig(cleanProvider, resolveMaskedEnvSentinels(value, host, cleanProvider));
|
|
@@ -102,7 +103,7 @@ export function setProviderConfig(
|
|
|
102
103
|
ensureProviderConfigDescriptors([key]);
|
|
103
104
|
const validation = validateSettingValue(PROVIDER_CONFIG_NAMESPACE, key, normalized);
|
|
104
105
|
if (!validation.valid) throw new ValidationError(validation.errors.join("; "));
|
|
105
|
-
return
|
|
106
|
+
return await setConfigAsync(PROVIDER_CONFIG_NAMESPACE, key, normalized, opts.updatedBy) as ProviderConfigEntry;
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
export function providerConfigPublic(entry: ProviderConfigEntry, opts: { maskEnv?: boolean } = {}): Record<string, unknown> {
|
|
@@ -138,11 +139,11 @@ export function providerConfigPublic(entry: ProviderConfigEntry, opts: { maskEnv
|
|
|
138
139
|
* This is the server-authority write path: callers are in-process (local migration
|
|
139
140
|
* or the orchestrator command-bus result handler), so no HTTP scope is required.
|
|
140
141
|
*/
|
|
141
|
-
export function
|
|
142
|
+
export async function seedProviderConfigsAsync(
|
|
142
143
|
host: string,
|
|
143
144
|
rawByProvider: Record<string, unknown>,
|
|
144
145
|
opts: { legacyHost?: string } = {},
|
|
145
|
-
): ProviderConfigEntry[] {
|
|
146
|
+
): Promise<ProviderConfigEntry[]> {
|
|
146
147
|
const seeded: ProviderConfigEntry[] = [];
|
|
147
148
|
const cleanHost = normalizeProviderConfigHost(host);
|
|
148
149
|
const legacyHost = opts.legacyHost ? normalizeProviderConfigHost(opts.legacyHost) : undefined;
|
|
@@ -159,7 +160,7 @@ export function seedProviderConfigs(
|
|
|
159
160
|
// still validates; the relay owns the schema, the reporter stays dumb.
|
|
160
161
|
const value = legacy?.value ?? { ...providerConfigDefaults(provider), ...(isRecord(raw) ? raw : {}) };
|
|
161
162
|
try {
|
|
162
|
-
const entry =
|
|
163
|
+
const entry = await setProviderConfigAsync(provider, value, { host: cleanHost, updatedBy: `migration:${cleanHost}` });
|
|
163
164
|
emitConfigChanged(entry.namespace, entry.key, entry.version);
|
|
164
165
|
seeded.push(entry);
|
|
165
166
|
} catch {
|
|
@@ -174,16 +175,16 @@ export function seedProviderConfigs(
|
|
|
174
175
|
* owns the stable-id/legacy-hostname resolution together so command routes do
|
|
175
176
|
* not re-parse or accidentally bypass the migration authority rules.
|
|
176
177
|
*/
|
|
177
|
-
export function
|
|
178
|
+
export async function seedMigratedProviderConfigsAsync(result: unknown): Promise<{ host: string; seeded: ProviderConfigEntry[] } | null> {
|
|
178
179
|
if (!isRecord(result)) return null;
|
|
179
180
|
const host = cleanString(result.host, "result.host", { max: 120 });
|
|
180
181
|
const hostname = cleanString(result.hostname, "result.hostname", { max: 120 });
|
|
181
182
|
const configs = isRecord(result.configs) ? result.configs : undefined;
|
|
182
183
|
if (!host || !configs) return null;
|
|
183
|
-
return { host, seeded:
|
|
184
|
+
return { host, seeded: await seedProviderConfigsAsync(host, configs, { legacyHost: hostname }) };
|
|
184
185
|
}
|
|
185
186
|
|
|
186
|
-
export function
|
|
187
|
+
export async function migrateLocalProviderConfigsAsync(home = humwickHome(), host = defaultProviderConfigHost()): Promise<ProviderConfigEntry[]> {
|
|
187
188
|
const dir = join(home, "providers");
|
|
188
189
|
if (!existsSync(dir)) return [];
|
|
189
190
|
const raw: Record<string, unknown> = {};
|
|
@@ -192,7 +193,7 @@ export function migrateLocalProviderConfigs(home = humwickHome(), host = default
|
|
|
192
193
|
if (!VALID_PROVIDER_CONFIGS.includes(provider as SpawnProvider)) continue;
|
|
193
194
|
raw[provider] = loadLocalProviderConfig(provider, home);
|
|
194
195
|
}
|
|
195
|
-
return
|
|
196
|
+
return seedProviderConfigsAsync(host, raw);
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
function normalizeProviderConfigHost(host: string): string {
|
|
@@ -1,18 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { seedProviderModelOverrides } from "./provider-catalog-store";
|
|
3
|
-
import { reconcileClaudeCatalogSeeds } from "./db/claude-catalog-reconcile";
|
|
4
|
-
import { VERSION } from "./config";
|
|
5
|
-
import { errMessage } from "@humwick/sdk";
|
|
6
|
-
|
|
7
|
-
// Stamp only after the transactional seed succeeds so a failure retries next boot.
|
|
8
|
-
export function reconcileProviderModelSeed(): void {
|
|
9
|
-
try {
|
|
10
|
-
reconcileClaudeCatalogSeeds();
|
|
11
|
-
const stamp = `seed:${VERSION}`;
|
|
12
|
-
if (getConfig<string>("system", "provider-model-seed-version")?.value === stamp) return;
|
|
13
|
-
seedProviderModelOverrides(stamp);
|
|
14
|
-
setConfig("system", "provider-model-seed-version", stamp, "server-startup");
|
|
15
|
-
} catch (err) {
|
|
16
|
-
console.warn(`[provider-model-seed] skipped: ${errMessage(err)}`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
1
|
+
export { reconcileProviderModelSeed, seedProviderModelOverrides } from "./db/provider-model-seed";
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
// provider *spawn* config (provider-config-store.ts) by design — different scope,
|
|
10
10
|
// different cardinality.
|
|
11
11
|
import { ValidationError } from "./db";
|
|
12
|
-
import { getConfig, listConfig
|
|
12
|
+
import { getConfig, listConfig } from "./config-store";
|
|
13
|
+
import { setConfigAsync } from "./config-store-write";
|
|
13
14
|
import { emitConfigChanged } from "./sse";
|
|
14
15
|
import {
|
|
15
16
|
DEFAULT_PROVIDER_QUOTA_CONFIG,
|
|
@@ -47,14 +48,14 @@ export function listProviderQuotaConfigs(): ProviderQuotaConfigMap {
|
|
|
47
48
|
* clamped to 5m–15m, unset fields defaulted), so a partial body still validates.
|
|
48
49
|
* Emits `config.changed` so the orchestrator + dashboard pick it up live.
|
|
49
50
|
*/
|
|
50
|
-
export function
|
|
51
|
+
export async function setProviderQuotaConfigAsync(
|
|
51
52
|
provider: string,
|
|
52
53
|
value: unknown,
|
|
53
54
|
opts: { updatedBy?: string } = {},
|
|
54
|
-
): ProviderQuotaConfig {
|
|
55
|
+
): Promise<ProviderQuotaConfig> {
|
|
55
56
|
const clean = assertValidProvider(provider);
|
|
56
57
|
const normalized = normalizeProviderQuotaConfig(value);
|
|
57
|
-
const entry =
|
|
58
|
+
const entry = await setConfigAsync(PROVIDER_QUOTA_CONFIG_NAMESPACE, clean, normalized, opts.updatedBy);
|
|
58
59
|
emitConfigChanged(entry.namespace, entry.key, entry.version);
|
|
59
60
|
return normalized;
|
|
60
61
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getDb } from "./db";
|
|
2
|
-
import {
|
|
2
|
+
import { setProviderConfigAsync } from "./provider-config-store";
|
|
3
3
|
|
|
4
4
|
// #3402 — fake values under every key name the hub's central provider config holds, plus one no masking
|
|
5
5
|
// list knows, so a test proves masking follows the configured values rather than key names.
|
|
@@ -25,9 +25,9 @@ export function leakedProviderSecrets(text: string): string[] {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/** Seeds the central provider config of `host` and returns its rows the way `sqlite3 ... select` prints them. */
|
|
28
|
-
export function seedProviderSecrets(host: string): string {
|
|
28
|
+
export async function seedProviderSecrets(host: string): Promise<string> {
|
|
29
29
|
for (const [provider, env] of Object.entries(PROVIDER_SECRET_ENV)) {
|
|
30
|
-
|
|
30
|
+
await setProviderConfigAsync(provider, { command: provider, env: { ...env, OPENCODE_CONFIG: "/srv/opencode.json" } }, { host });
|
|
31
31
|
}
|
|
32
32
|
return (getDb().query("SELECT namespace, key, value FROM config WHERE namespace = 'provider-config'").all() as Array<Record<string, string>>)
|
|
33
33
|
.map((row) => `${row.namespace}|${row.key}|${row.value}`).join("\n");
|
package/src/recipe-runner.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
validateRecipeArtifactRefsAsync,
|
|
16
16
|
} from "./recipe-async";
|
|
17
17
|
import type { AttachmentRef, Command, RecipeInstance } from "./types";
|
|
18
|
-
import { SYSTEM_LAUNCH,
|
|
18
|
+
import { SYSTEM_LAUNCH, runnerRuntimeTokenEnvAsync } from "./runtime-tokens";
|
|
19
19
|
import { generateSpawnAgentId } from "./services/spawn-identity";
|
|
20
20
|
|
|
21
21
|
interface StartRecipeInput {
|
|
@@ -114,7 +114,7 @@ export async function startRecipe(input: StartRecipeInput): Promise<StartRecipeR
|
|
|
114
114
|
env: {
|
|
115
115
|
...(agent.env ?? {}),
|
|
116
116
|
...(attachments.length ? writeChildEnv({}, { AGENT_RELAY_RECIPE_ARTIFACTS: JSON.stringify(attachments) }) : {}),
|
|
117
|
-
...
|
|
117
|
+
...await runnerRuntimeTokenEnvAsync({ authority: SYSTEM_LAUNCH,
|
|
118
118
|
agentId,
|
|
119
119
|
orchestratorId: orchestrator.id,
|
|
120
120
|
cwd,
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
import { dirname, resolve } from "node:path";
|
|
7
7
|
import { isRecord, stringValue } from "@humwick/sdk";
|
|
8
8
|
import { isTrustedOrchestratorApiUrl, relayAuthHeaders } from "./config";
|
|
9
|
-
import { getConfig
|
|
9
|
+
import { getConfig } from "./config-store";
|
|
10
|
+
import { setConfigAsync } from "./config-store-write";
|
|
10
11
|
import { listOrchestrators, reportedRepoRootForCwd } from "./db";
|
|
11
12
|
import { hostIsRelayHost } from "./relay-host-locality";
|
|
12
13
|
import { normalizeHostToken, parseJson, sameHostIdentity } from "./utils";
|
|
@@ -70,11 +71,16 @@ export function hostRepoConfigSource<T>(spec: HostRepoConfigSpec<T>): HostRepoCo
|
|
|
70
71
|
return null;
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
/** #1870 S7: writes on the writer thread, and only when the answer changed. `at` is evidence, not a
|
|
75
|
+
* TTL, so re-stamping an identical answer on every read only bumped the version and history. */
|
|
76
|
+
async function writeCached(host: string, keys: readonly string[], found: RepoConfigSource<T> | null): Promise<void> {
|
|
74
77
|
const at = Date.now();
|
|
78
|
+
const answer = JSON.stringify(found);
|
|
75
79
|
for (const key of keys) {
|
|
76
80
|
try {
|
|
77
|
-
|
|
81
|
+
const current = getConfig<CachedRepoConfigSource<T>>(spec.cacheNamespace, cacheKey(host, key))?.value;
|
|
82
|
+
if (current?.at && JSON.stringify(current.found) === answer) continue;
|
|
83
|
+
await setConfigAsync<CachedRepoConfigSource<T>>(spec.cacheNamespace, cacheKey(host, key), { found, at }, spec.cacheNamespace);
|
|
78
84
|
} catch {
|
|
79
85
|
// The cache is an optimization for the sync paths; failing to record it must never fail a caller.
|
|
80
86
|
}
|
|
@@ -149,7 +155,7 @@ export function hostRepoConfigSource<T>(spec: HostRepoConfigSpec<T>): HostRepoCo
|
|
|
149
155
|
if (hostIsRelayHost(host)) return { known: true, found: await spec.findLocalAsync(cwd) };
|
|
150
156
|
const read = await readFromHost(cwd, host!);
|
|
151
157
|
if (read.known) {
|
|
152
|
-
writeCached(host!, cacheWriteKeys(cwd, read.found, opts.alsoCacheFor), read.found);
|
|
158
|
+
await writeCached(host!, cacheWriteKeys(cwd, read.found, opts.alsoCacheFor), read.found);
|
|
153
159
|
return read;
|
|
154
160
|
}
|
|
155
161
|
return cachedLookup(host!, cwd);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { PromptVersionConflictError } from "../prompt-version-errors";
|
|
2
2
|
import { versionedPromptsEnabled } from "../versioned-prompts";
|
|
3
3
|
import { promptActor } from "../services/prompt-version-writer";
|
|
4
|
-
import { setConfigAsync } from "../config-store-write";
|
|
4
|
+
import { deleteAgentProfileAsync, setAgentProfileAsync, setConfigAsync } from "../config-store-write";
|
|
5
5
|
import { memoryRetirementMessage } from "../memory-retirement";
|
|
6
6
|
// Auto-split from routes.ts (#299). Domain: agent-profiles.
|
|
7
7
|
import { ValidationError, withResolvedProvisioningAsync } from "../db";
|
|
8
8
|
import { cleanString, optionalEnum } from "../validation";
|
|
9
|
-
import {
|
|
9
|
+
import { getAgentProfile, listAgentProfiles, resolveAgentProfileKey, validateAgentProfile } from "../config-store";
|
|
10
10
|
import { RELAY_TOOL_GROUPS } from "../mcp";
|
|
11
11
|
import { emitConfigChanged } from "../sse";
|
|
12
12
|
import { error, isAdminRequest, json, normalizeConfigPathParam, parseBody, type Handler } from "./_shared";
|
|
@@ -140,8 +140,8 @@ export const putAgentProfileRoute: Handler = async (req, params) => {
|
|
|
140
140
|
return json(saved);
|
|
141
141
|
}
|
|
142
142
|
const profile = existing?.value.builtIn && isAdminRequest(req)
|
|
143
|
-
?
|
|
144
|
-
:
|
|
143
|
+
? await setAgentProfileAsync({ ...parsed.body, name } as AgentProfile, updatedBy, { overrideBuiltIn: true })
|
|
144
|
+
: await setAgentProfileAsync({ ...parsed.body, name } as AgentProfile, updatedBy);
|
|
145
145
|
emitConfigChanged(profile.namespace, profile.key, profile.version);
|
|
146
146
|
return json(profile, existing ? 200 : profile.version === 1 ? 201 : 200);
|
|
147
147
|
} catch (e) {
|
|
@@ -151,14 +151,14 @@ export const putAgentProfileRoute: Handler = async (req, params) => {
|
|
|
151
151
|
}
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
-
export const deleteAgentProfileRoute: Handler = (req, params) => {
|
|
154
|
+
export const deleteAgentProfileRoute: Handler = async (req, params) => {
|
|
155
155
|
try {
|
|
156
156
|
const name = normalizeConfigPathParam(params.name, "name");
|
|
157
157
|
const existing = getAgentProfile(name);
|
|
158
158
|
if (!existing) return error(memoryRetirementMessage(name) ?? "agent profile not found", 404);
|
|
159
159
|
const updatedBy = versionedPromptsEnabled() ? promptActor(req) : cleanString(new URL(req.url).searchParams.get("updatedBy") ?? undefined, "updatedBy", { max: 200 });
|
|
160
160
|
if (existing.value.builtIn && !isAdminRequest(req)) return error("built-in agent profiles are managed by Relay", 400);
|
|
161
|
-
|
|
161
|
+
await deleteAgentProfileAsync(name, updatedBy, { resetBuiltInOverride: existing.value.builtIn });
|
|
162
162
|
emitConfigChanged(existing.namespace, existing.key, existing.version + 1);
|
|
163
163
|
return json({ ok: true });
|
|
164
164
|
} catch (e) {
|
|
@@ -208,7 +208,7 @@ export const postAgentSpawn: Handler = async (req) => {
|
|
|
208
208
|
// strip the heavy inlined provisioning file contents from the echoed-back summary.
|
|
209
209
|
return json({
|
|
210
210
|
ok: true, spawnRequestId: result.spawnRequestId, harnessSubagents: result.harnessSubagents, orchestratorId: result.orchestratorId, placementReason: result.placementReason, provider: result.provider, command: summarizeSpawnCommandForCaller(result.command),
|
|
211
|
-
...(result.task ? { task: result.task } : {}), ...(result.warnings ? { warnings: result.warnings } : {}), ...(result.dispatchDecision ? { dispatchDecision: result.dispatchDecision } : {}), ...(workflow.reason ? { workflow: { started: false, reason: workflow.reason } } : {}),
|
|
211
|
+
...(result.task ? { task: result.task } : {}), ...(result.warnings ? { warnings: result.warnings } : {}), ...(result.spawnPolicy ? { spawnPolicy: result.spawnPolicy } : {}), ...(result.dispatchDecision ? { dispatchDecision: result.dispatchDecision } : {}), ...(workflow.reason ? { workflow: { started: false, reason: workflow.reason } } : {}),
|
|
212
212
|
}, 202);
|
|
213
213
|
} catch (e) {
|
|
214
214
|
if (e instanceof McpAuthError) return error(e.message, 403);
|