crewly 1.20.185 → 1.20.187
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/config/skills/agent/core/remember/SKILL.md +1 -0
- package/config/skills/agent/core/remember/execute.sh +12 -0
- package/config/skills/agent/core/report-status/SKILL.md +7 -1
- package/config/skills/agent/core/report-status/execute.sh +41 -0
- package/config/skills/agent/core/slack-post/SKILL.md +1 -0
- package/config/skills/agent/core/slack-post/execute.sh +9 -2
- package/config/skills/team-leader/_common/lib.sh +45 -0
- package/config/skills/team-leader/start-agent/SKILL.md +6 -6
- package/config/skills/team-leader/start-agent/execute.sh +3 -12
- package/config/skills/team-leader/stop-agent/SKILL.md +6 -6
- package/config/skills/team-leader/stop-agent/execute.sh +3 -12
- package/dist/backend/backend/src/constants.d.ts +64 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +64 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +62 -0
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/request/open-items.controller.js +1 -1
- package/dist/backend/backend/src/controllers/request/open-items.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +4 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts +18 -1
- package/dist/backend/backend/src/controllers/standing/standing.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/standing/standing.controller.js +77 -4
- package/dist/backend/backend/src/controllers/standing/standing.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/spend.controller.d.ts +32 -0
- package/dist/backend/backend/src/controllers/system/spend.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/system/spend.controller.js +100 -0
- package/dist/backend/backend/src/controllers/system/spend.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/system/system.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/system.controller.js +28 -3
- package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +7 -0
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +64 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +59 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/system.routes.js +3 -0
- package/dist/backend/backend/src/routes/modules/system.routes.js.map +1 -1
- package/dist/backend/backend/src/scripts/open-items-stale-followups.d.ts +51 -0
- package/dist/backend/backend/src/scripts/open-items-stale-followups.d.ts.map +1 -0
- package/dist/backend/backend/src/scripts/open-items-stale-followups.js +142 -0
- package/dist/backend/backend/src/scripts/open-items-stale-followups.js.map +1 -0
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +32 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts +9 -0
- package/dist/backend/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js +37 -1
- package/dist/backend/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts +28 -0
- package/dist/backend/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js +83 -2
- package/dist/backend/backend/src/services/event-bus/event-bus.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.d.ts +14 -2
- package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.js +12 -1
- package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.d.ts +18 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.js +38 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts +11 -0
- package/dist/backend/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/standing-answers.service.js +40 -2
- package/dist/backend/backend/src/services/memory/standing-answers.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/offline-agent-message.d.ts +70 -0
- package/dist/backend/backend/src/services/messaging/offline-agent-message.d.ts.map +1 -0
- package/dist/backend/backend/src/services/messaging/offline-agent-message.js +92 -0
- package/dist/backend/backend/src/services/messaging/offline-agent-message.js.map +1 -0
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts +5 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js +11 -2
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js +2 -0
- package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js +9 -1
- package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +41 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js +87 -2
- package/dist/backend/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts +30 -12
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +83 -13
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +25 -0
- package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js +45 -1
- package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-item-extractor.d.ts +10 -1
- package/dist/backend/backend/src/services/open-items/open-item-extractor.d.ts.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-item-extractor.js +86 -5
- package/dist/backend/backend/src/services/open-items/open-item-extractor.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts +2 -1
- package/dist/backend/backend/src/services/open-items/open-items-backfill.d.ts.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items-backfill.js +17 -6
- package/dist/backend/backend/src/services/open-items/open-items-backfill.js.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts +62 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/open-items/open-items.service.js +203 -9
- package/dist/backend/backend/src/services/open-items/open-items.service.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.d.ts +40 -0
- package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.js +82 -0
- package/dist/backend/backend/src/services/reconciler/idle-holder-surfacer.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +29 -0
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +49 -0
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +6 -11
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +23 -0
- package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js +55 -1
- package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.js +10 -4
- package/dist/backend/backend/src/services/slack/slack-agent-post.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts +13 -2
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js +19 -5
- package/dist/backend/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts +99 -0
- package/dist/backend/backend/src/services/spend/spend-cap-command.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap-command.js +190 -0
- package/dist/backend/backend/src/services/spend/spend-cap-command.js.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts +64 -0
- package/dist/backend/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.gate.js +71 -0
- package/dist/backend/backend/src/services/spend/spend-cap.gate.js.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts +225 -0
- package/dist/backend/backend/src/services/spend/spend-cap.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.service.js +503 -0
- package/dist/backend/backend/src/services/spend/spend-cap.service.js.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts +85 -0
- package/dist/backend/backend/src/services/spend/spend-cap.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.store.js +95 -0
- package/dist/backend/backend/src/services/spend/spend-cap.store.js.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts +50 -0
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.js +98 -0
- package/dist/backend/backend/src/services/spend/spend-cap.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts +124 -0
- package/dist/backend/backend/src/services/spend/spend-ledger.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/spend/spend-ledger.service.js +189 -0
- package/dist/backend/backend/src/services/spend/spend-ledger.service.js.map +1 -0
- package/dist/backend/backend/src/services/task-pool/claim-target-waker.d.ts +51 -0
- package/dist/backend/backend/src/services/task-pool/claim-target-waker.d.ts.map +1 -0
- package/dist/backend/backend/src/services/task-pool/claim-target-waker.js +43 -0
- package/dist/backend/backend/src/services/task-pool/claim-target-waker.js.map +1 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +38 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +73 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts +44 -0
- package/dist/backend/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -0
- package/dist/backend/backend/src/services/task-pool/work-item-usage.js +37 -0
- package/dist/backend/backend/src/services/task-pool/work-item-usage.js.map +1 -0
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.js +11 -14
- package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts +25 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +50 -0
- package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts +9 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +16 -2
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/decision.types.d.ts +5 -1
- package/dist/backend/backend/src/types/decision.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts +9 -1
- package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
- package/dist/backend/backend/src/types/review-reason.types.d.ts +3 -1
- package/dist/backend/backend/src/types/review-reason.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/review-reason.types.js +1 -0
- package/dist/backend/backend/src/types/review-reason.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/open-item.types.d.ts +5 -1
- package/dist/backend/backend/src/types/v2/open-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/open-item.types.js +1 -1
- package/dist/backend/backend/src/types/v2/open-item.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +64 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +64 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +32 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts +9 -0
- package/dist/cli/backend/src/services/decisions/decision.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/decisions/decision.service.js +37 -1
- package/dist/cli/backend/src/services/decisions/decision.service.js.map +1 -1
- package/dist/cli/backend/src/services/event-bus/event-bus.service.d.ts +28 -0
- package/dist/cli/backend/src/services/event-bus/event-bus.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/event-bus/event-bus.service.js +83 -2
- package/dist/cli/backend/src/services/event-bus/event-bus.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.d.ts +14 -2
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.js +12 -1
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts +18 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.js +38 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts +11 -0
- package/dist/cli/backend/src/services/memory/standing-answers.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/standing-answers.service.js +40 -2
- package/dist/cli/backend/src/services/memory/standing-answers.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts +5 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js +11 -2
- package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js +9 -1
- package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts +41 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js +87 -2
- package/dist/cli/backend/src/services/messaging/sub-agent-message-queue.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts +30 -12
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js +83 -13
- package/dist/cli/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/cli/backend/src/services/monitoring/model-pricing.d.ts +97 -0
- package/dist/cli/backend/src/services/monitoring/model-pricing.d.ts.map +1 -0
- package/dist/cli/backend/src/services/monitoring/model-pricing.js +120 -0
- package/dist/cli/backend/src/services/monitoring/model-pricing.js.map +1 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +25 -0
- package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js +45 -1
- package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-item-extractor.d.ts +10 -1
- package/dist/cli/backend/src/services/open-items/open-item-extractor.d.ts.map +1 -1
- package/dist/cli/backend/src/services/open-items/open-item-extractor.js +86 -5
- package/dist/cli/backend/src/services/open-items/open-item-extractor.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts +13 -2
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js +19 -5
- package/dist/cli/backend/src/services/slack/slack-typing-placeholder.service.js.map +1 -1
- package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts +64 -0
- package/dist/cli/backend/src/services/spend/spend-cap.gate.d.ts.map +1 -0
- package/dist/cli/backend/src/services/spend/spend-cap.gate.js +71 -0
- package/dist/cli/backend/src/services/spend/spend-cap.gate.js.map +1 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +38 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +73 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts +44 -0
- package/dist/cli/backend/src/services/task-pool/work-item-usage.d.ts.map +1 -0
- package/dist/cli/backend/src/services/task-pool/work-item-usage.js +37 -0
- package/dist/cli/backend/src/services/task-pool/work-item-usage.js.map +1 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/v3/v3-data.service.js +11 -14
- package/dist/cli/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/cli/backend/src/types/decision.types.d.ts +5 -1
- package/dist/cli/backend/src/types/decision.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/event-bus.types.d.ts +9 -1
- package/dist/cli/backend/src/types/event-bus.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/event-bus.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/open-item.types.d.ts +5 -1
- package/dist/cli/backend/src/types/v2/open-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/open-item.types.js +1 -1
- package/dist/cli/backend/src/types/v2/open-item.types.js.map +1 -1
- package/frontend/dist/assets/{index-1ee8a9a2.js → index-15c2faf2.js} +279 -279
- package/frontend/dist/assets/{index-a79c7852.css → index-20a67829.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-agent daily spend cap with a hard stop.
|
|
3
|
+
*
|
|
4
|
+
* - Caps are the owner's own limits (unlike the runtime fallback, which
|
|
5
|
+
* reacts to a provider's usage limit). All are OFF until the owner sets
|
|
6
|
+
* one: a default per-agent cap, per-agent overrides, and an optional
|
|
7
|
+
* all-agents daily total.
|
|
8
|
+
* - At {@link SPEND_CAP_CONSTANTS.WARN_FRACTION} of a cap the owner gets ONE
|
|
9
|
+
* heads-up.
|
|
10
|
+
* - At 100% the agent is hard-stopped: {@link stopOf} answers the delivery
|
|
11
|
+
* and wake gates, so no new turn starts (the current one may finish) and
|
|
12
|
+
* messages stay queued. The owner gets ONE decision card: "Raise to $Y
|
|
13
|
+
* today" / "Keep stopped".
|
|
14
|
+
* - Local midnight resets everything; raises last for the day they were
|
|
15
|
+
* made. When a stop lifts (midnight, raise, cap change) the queued
|
|
16
|
+
* messages are released.
|
|
17
|
+
*
|
|
18
|
+
* Spend comes from {@link SpendLedger} (the shared token ledger and its one
|
|
19
|
+
* cost computation).
|
|
20
|
+
*
|
|
21
|
+
* specs/2026-10-02-spend-cap.md
|
|
22
|
+
*
|
|
23
|
+
* @module services/spend/spend-cap.service
|
|
24
|
+
*/
|
|
25
|
+
import { ORCHESTRATOR_SESSION_NAME, SPEND_CAP_CONSTANTS as C } from '../../constants.js';
|
|
26
|
+
import { localDateKey, localMidnight } from '../project-tickets/ticket-autopilot-decision.js';
|
|
27
|
+
import { formatUsd, spendCapReason } from './spend-cap.gate.js';
|
|
28
|
+
import { cents } from './spend-ledger.service.js';
|
|
29
|
+
import { emptyDay, emptySpendCapFile } from './spend-cap.store.js';
|
|
30
|
+
/** A rejected cap change. */
|
|
31
|
+
export class SpendCapError extends Error {
|
|
32
|
+
status;
|
|
33
|
+
/**
|
|
34
|
+
* @param status - HTTP status
|
|
35
|
+
* @param message - Owner-facing reason
|
|
36
|
+
*/
|
|
37
|
+
constructor(status, message) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.status = status;
|
|
40
|
+
this.name = 'SpendCapError';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Whether a cap value is usable.
|
|
45
|
+
*
|
|
46
|
+
* @param v - Value
|
|
47
|
+
* @returns True for a finite positive number
|
|
48
|
+
*/
|
|
49
|
+
function isCap(v) {
|
|
50
|
+
return typeof v === 'number' && Number.isFinite(v) && v > 0;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate a cap from the API.
|
|
54
|
+
*
|
|
55
|
+
* @param v - Value
|
|
56
|
+
* @param what - Field name for the error
|
|
57
|
+
* @returns The cap (whole cents) or null
|
|
58
|
+
* @throws SpendCapError
|
|
59
|
+
*/
|
|
60
|
+
function parseCap(v, what) {
|
|
61
|
+
if (v === null)
|
|
62
|
+
return null;
|
|
63
|
+
const n = typeof v === 'string' ? Number(v.replace(/^\$/, '')) : v;
|
|
64
|
+
if (!isCap(n))
|
|
65
|
+
throw new SpendCapError(400, `${what} must be a positive amount in USD (e.g. 5) or null to turn it off`);
|
|
66
|
+
return cents(n);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The "Raise to $Y today" amount: the cap times RAISE_FACTOR, rounded up to
|
|
70
|
+
* whole dollars, and always above what was already spent.
|
|
71
|
+
*
|
|
72
|
+
* @param capUsd - Cap in force
|
|
73
|
+
* @param spentUsd - Spent today
|
|
74
|
+
* @returns USD
|
|
75
|
+
*/
|
|
76
|
+
export function suggestedRaise(capUsd, spentUsd) {
|
|
77
|
+
return Math.max(Math.ceil(capUsd * C.RAISE_FACTOR), Math.ceil(spentUsd) + 1);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Read the amount out of a "Raise to $Y today" option label.
|
|
81
|
+
*
|
|
82
|
+
* @param label - Option label
|
|
83
|
+
* @returns USD, or null when the label is not a raise
|
|
84
|
+
*/
|
|
85
|
+
export function raiseAmountOf(label) {
|
|
86
|
+
const m = /^Raise to \$(\d+(?:\.\d+)?) today/i.exec(label ?? '');
|
|
87
|
+
return m ? Number(m[1]) : null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Per-agent daily spend cap service.
|
|
91
|
+
*/
|
|
92
|
+
export class SpendCapService {
|
|
93
|
+
deps;
|
|
94
|
+
file;
|
|
95
|
+
now;
|
|
96
|
+
logger;
|
|
97
|
+
timer = null;
|
|
98
|
+
/** Sessions stopped at the last evaluation (to release them when the stop lifts) */
|
|
99
|
+
lastStopped = new Set();
|
|
100
|
+
/** Evaluation passes run one after another */
|
|
101
|
+
chain = Promise.resolve();
|
|
102
|
+
queuedPass = null;
|
|
103
|
+
/**
|
|
104
|
+
* @param deps - Collaborators
|
|
105
|
+
*/
|
|
106
|
+
constructor(deps) {
|
|
107
|
+
this.deps = deps;
|
|
108
|
+
this.now = deps.now ?? (() => new Date());
|
|
109
|
+
this.logger = deps.logger;
|
|
110
|
+
this.file = deps.store.read() ?? emptySpendCapFile(localDateKey(this.now()));
|
|
111
|
+
}
|
|
112
|
+
/** Start the enforcement tick. */
|
|
113
|
+
start() {
|
|
114
|
+
if (this.timer)
|
|
115
|
+
return;
|
|
116
|
+
this.timer = setInterval(() => void this.evaluate(), C.TICK_MS);
|
|
117
|
+
this.timer.unref?.();
|
|
118
|
+
void this.evaluate();
|
|
119
|
+
}
|
|
120
|
+
/** Stop the tick. */
|
|
121
|
+
stop() {
|
|
122
|
+
if (this.timer)
|
|
123
|
+
clearInterval(this.timer);
|
|
124
|
+
this.timer = null;
|
|
125
|
+
}
|
|
126
|
+
// ---------------------------------------------------------------- caps
|
|
127
|
+
/** @returns The owner's caps (a copy) */
|
|
128
|
+
getConfig() {
|
|
129
|
+
return JSON.parse(JSON.stringify(this.file.config));
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Change caps. Takes effect at once (a stop can lift or start).
|
|
133
|
+
*
|
|
134
|
+
* @param patch - Changes
|
|
135
|
+
* @returns The new caps
|
|
136
|
+
* @throws SpendCapError on a bad value
|
|
137
|
+
*/
|
|
138
|
+
async setCaps(patch) {
|
|
139
|
+
if (!patch || typeof patch !== 'object')
|
|
140
|
+
throw new SpendCapError(400, 'Send the caps to change as JSON');
|
|
141
|
+
const next = this.getConfig();
|
|
142
|
+
if ('defaultAgentCapUsd' in patch)
|
|
143
|
+
next.defaultAgentCapUsd = parseCap(patch.defaultAgentCapUsd, 'defaultAgentCapUsd');
|
|
144
|
+
if ('totalCapUsd' in patch)
|
|
145
|
+
next.totalCapUsd = parseCap(patch.totalCapUsd, 'totalCapUsd');
|
|
146
|
+
if (patch.agents !== undefined) {
|
|
147
|
+
if (!patch.agents || typeof patch.agents !== 'object')
|
|
148
|
+
throw new SpendCapError(400, 'agents must be an object: { "<session>": 5 | null | "default" }');
|
|
149
|
+
for (const [session, value] of Object.entries(patch.agents)) {
|
|
150
|
+
if (!session.trim())
|
|
151
|
+
throw new SpendCapError(400, 'agents keys must be agent session names');
|
|
152
|
+
if (value === 'default')
|
|
153
|
+
delete next.agentCapsUsd[session];
|
|
154
|
+
else
|
|
155
|
+
next.agentCapsUsd[session] = parseCap(value, `agents.${session}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
next.updatedAt = this.now().toISOString();
|
|
159
|
+
this.file.config = next;
|
|
160
|
+
this.persist();
|
|
161
|
+
this.logger?.info('Spend caps changed', { caps: next });
|
|
162
|
+
await this.evaluate();
|
|
163
|
+
return this.getConfig();
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Lift a cap for today only.
|
|
167
|
+
*
|
|
168
|
+
* @param target - Agent session, or `*` for the all-agents total
|
|
169
|
+
* @param usd - New cap for today (must be above today's spend)
|
|
170
|
+
* @returns The new cap for today
|
|
171
|
+
* @throws SpendCapError when the amount is not above today's spend
|
|
172
|
+
*/
|
|
173
|
+
async raiseToday(target, usd) {
|
|
174
|
+
const cap = parseCap(usd, 'capUsd');
|
|
175
|
+
if (cap === null)
|
|
176
|
+
throw new SpendCapError(400, 'capUsd must be a positive amount in USD');
|
|
177
|
+
this.rollDay();
|
|
178
|
+
const spent = target === C.TOTAL_TARGET ? this.deps.ledger.totalToday() : this.deps.ledger.spentToday(target);
|
|
179
|
+
if (cap <= spent) {
|
|
180
|
+
throw new SpendCapError(400, `${formatUsd(cap)} is not above what ${this.nameOf(target)} already spent today (${formatUsd(spent)}); pick a higher amount`);
|
|
181
|
+
}
|
|
182
|
+
this.file.day.raised[target] = cap;
|
|
183
|
+
this.persist();
|
|
184
|
+
this.logger?.info('Spend cap raised for today', { target, capUsd: cap, spentUsd: cents(spent) });
|
|
185
|
+
await this.evaluate();
|
|
186
|
+
return cap;
|
|
187
|
+
}
|
|
188
|
+
// ---------------------------------------------------------------- gate
|
|
189
|
+
/**
|
|
190
|
+
* The stop in force for a session (the delivery / wake gate). Synchronous
|
|
191
|
+
* and live: it reads today's spend now, not at the last tick.
|
|
192
|
+
*
|
|
193
|
+
* @param session - Agent session
|
|
194
|
+
* @returns Stop, or null when the agent may run
|
|
195
|
+
*/
|
|
196
|
+
stopOf(session) {
|
|
197
|
+
this.rollDay();
|
|
198
|
+
const stop = this.computeStop(session);
|
|
199
|
+
if (stop && !this.file.day.stopped.includes(this.stopKey(stop)))
|
|
200
|
+
this.scheduleEvaluate();
|
|
201
|
+
return stop;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Owner-facing name.
|
|
205
|
+
*
|
|
206
|
+
* @param session - Agent session
|
|
207
|
+
* @returns Name
|
|
208
|
+
*/
|
|
209
|
+
displayNameOf(session) {
|
|
210
|
+
return this.nameOf(session);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Cap in force today for a target, and where it comes from.
|
|
214
|
+
*
|
|
215
|
+
* @param target - Agent session, or `*`
|
|
216
|
+
* @returns Cap (null = none) and source
|
|
217
|
+
*/
|
|
218
|
+
capOf(target) {
|
|
219
|
+
const raised = this.file.day.raised[target];
|
|
220
|
+
if (isCap(raised))
|
|
221
|
+
return { capUsd: raised, source: 'raised' };
|
|
222
|
+
const cfg = this.file.config;
|
|
223
|
+
if (target === C.TOTAL_TARGET)
|
|
224
|
+
return isCap(cfg.totalCapUsd) ? { capUsd: cfg.totalCapUsd, source: 'default' } : { capUsd: null, source: 'none' };
|
|
225
|
+
if (Object.prototype.hasOwnProperty.call(cfg.agentCapsUsd, target)) {
|
|
226
|
+
const v = cfg.agentCapsUsd[target];
|
|
227
|
+
return isCap(v) ? { capUsd: v, source: 'override' } : { capUsd: null, source: 'exempt' };
|
|
228
|
+
}
|
|
229
|
+
return isCap(cfg.defaultAgentCapUsd) ? { capUsd: cfg.defaultAgentCapUsd, source: 'default' } : { capUsd: null, source: 'none' };
|
|
230
|
+
}
|
|
231
|
+
// ---------------------------------------------------------------- view
|
|
232
|
+
/**
|
|
233
|
+
* Spend plus caps for the API / Settings panel.
|
|
234
|
+
*
|
|
235
|
+
* @param days - Window
|
|
236
|
+
* @returns View
|
|
237
|
+
*/
|
|
238
|
+
async view(days = C.DEFAULT_DAYS) {
|
|
239
|
+
this.rollDay();
|
|
240
|
+
const summary = this.deps.ledger.summarize(days);
|
|
241
|
+
const known = (await this.deps.knownSessions?.().catch(() => [])) ?? [];
|
|
242
|
+
const rows = new Map(summary.agents.map((a) => [a.session, a]));
|
|
243
|
+
for (const s of known) {
|
|
244
|
+
if (!rows.has(s))
|
|
245
|
+
rows.set(s, { session: s, runtimes: [], todayUsd: 0, windowUsd: 0, daily: summary.days.map(() => 0) });
|
|
246
|
+
}
|
|
247
|
+
const agents = [...rows.values()].map((a) => {
|
|
248
|
+
const cap = this.capOf(a.session);
|
|
249
|
+
const stop = this.computeStop(a.session);
|
|
250
|
+
return {
|
|
251
|
+
...a,
|
|
252
|
+
name: this.nameOf(a.session),
|
|
253
|
+
capUsd: cap.capUsd,
|
|
254
|
+
capSource: cap.source,
|
|
255
|
+
stopped: !!stop,
|
|
256
|
+
...(stop ? { stopReason: spendCapReason(stop, this.nameOf(a.session)) } : {}),
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
const total = this.capOf(C.TOTAL_TARGET).capUsd;
|
|
260
|
+
return {
|
|
261
|
+
...summary,
|
|
262
|
+
agents,
|
|
263
|
+
caps: this.getConfig(),
|
|
264
|
+
raisedToday: { ...this.file.day.raised },
|
|
265
|
+
totalCapTodayUsd: total,
|
|
266
|
+
suggestedAgentCapUsd: summary.p90AgentDayUsd > 0 ? Math.max(1, Math.ceil(summary.p90AgentDayUsd)) : null,
|
|
267
|
+
totalStopped: total !== null && this.deps.ledger.totalToday() >= total,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// ---------------------------------------------------------------- enforcement
|
|
271
|
+
/**
|
|
272
|
+
* One enforcement pass: day roll, 80% notices, stop announcements (one
|
|
273
|
+
* card per stop), and releasing agents whose stop lifted. Passes run
|
|
274
|
+
* one at a time; a call during a pass gets another pass after it.
|
|
275
|
+
*/
|
|
276
|
+
evaluate() {
|
|
277
|
+
// Coalesce: a pass not yet started is shared; a call during a running
|
|
278
|
+
// pass gets a fresh pass after it (so it sees the latest change).
|
|
279
|
+
if (this.queuedPass)
|
|
280
|
+
return this.queuedPass;
|
|
281
|
+
const pass = this.chain.then(async () => {
|
|
282
|
+
this.queuedPass = null;
|
|
283
|
+
try {
|
|
284
|
+
await this.evaluateOnce();
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
this.logger?.warn('Spend cap evaluation failed', { error: err instanceof Error ? err.message : String(err) });
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
this.queuedPass = pass;
|
|
291
|
+
this.chain = pass;
|
|
292
|
+
return pass;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* React to a settled "cap reached" card (decision kind `spend_cap`).
|
|
296
|
+
*
|
|
297
|
+
* @param d - The settled decision
|
|
298
|
+
* @returns Always null (nobody else is told)
|
|
299
|
+
*/
|
|
300
|
+
async onSettled(d) {
|
|
301
|
+
if (d.kind !== C.DECISION_KIND || !d.system)
|
|
302
|
+
return null;
|
|
303
|
+
const target = d.system.key;
|
|
304
|
+
this.rollDay();
|
|
305
|
+
if (this.file.day.cards[target] !== d.id) {
|
|
306
|
+
if (d.status === 'resolved')
|
|
307
|
+
await this.reply(d.id, 'This card is from an earlier day; the cap has already reset at midnight.');
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
const name = this.nameOf(target);
|
|
311
|
+
if (d.status !== 'resolved')
|
|
312
|
+
return null;
|
|
313
|
+
const label = d.options.find((o) => o.key === d.chosenKey)?.label;
|
|
314
|
+
const amount = raiseAmountOf(label);
|
|
315
|
+
if (amount === null) {
|
|
316
|
+
await this.reply(d.id, `OK, ${name} stays stopped until midnight. Its messages stay queued.`);
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
const cap = await this.raiseToday(target, amount);
|
|
321
|
+
await this.reply(d.id, `Raised ${name}'s cap to ${formatUsd(cap)} for today. Queued messages are being delivered.`);
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
await this.reply(d.id, `Could not raise the cap: ${err instanceof Error ? err.message : String(err)}`);
|
|
325
|
+
}
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
// ---------------------------------------------------------------- internals
|
|
329
|
+
async evaluateOnce() {
|
|
330
|
+
this.rollDay();
|
|
331
|
+
if (!this.anyCap() && this.lastStopped.size === 0)
|
|
332
|
+
return;
|
|
333
|
+
this.deps.ledger.invalidate();
|
|
334
|
+
const summary = this.deps.ledger.summarize(1);
|
|
335
|
+
const known = (await this.deps.knownSessions?.().catch(() => [])) ?? [];
|
|
336
|
+
const sessions = new Set([...known, ...summary.agents.map((a) => a.session), ...Object.keys(this.file.day.raised).filter((t) => t !== C.TOTAL_TARGET)]);
|
|
337
|
+
if (this.lastStopped.size > 0)
|
|
338
|
+
for (const s of this.lastStopped)
|
|
339
|
+
sessions.add(s);
|
|
340
|
+
const stoppedNow = new Set();
|
|
341
|
+
// The all-agents total first: its notice names the whole crew once.
|
|
342
|
+
const total = this.capOf(C.TOTAL_TARGET).capUsd;
|
|
343
|
+
if (total !== null) {
|
|
344
|
+
const spent = this.deps.ledger.totalToday();
|
|
345
|
+
await this.checkThresholds(C.TOTAL_TARGET, total, spent);
|
|
346
|
+
}
|
|
347
|
+
for (const session of sessions) {
|
|
348
|
+
const cap = this.capOf(session).capUsd;
|
|
349
|
+
if (cap !== null)
|
|
350
|
+
await this.checkThresholds(session, cap, this.deps.ledger.spentToday(session));
|
|
351
|
+
if (this.computeStop(session))
|
|
352
|
+
stoppedNow.add(session);
|
|
353
|
+
}
|
|
354
|
+
const released = [...this.lastStopped].filter((s) => !stoppedNow.has(s));
|
|
355
|
+
this.lastStopped = stoppedNow;
|
|
356
|
+
if (released.length > 0) {
|
|
357
|
+
this.logger?.info('Spend cap stop lifted — releasing queued messages', { sessions: released });
|
|
358
|
+
await this.deps.onReleased?.(released).catch((err) => this.logger?.warn('Releasing queued messages failed', { sessions: released, error: err instanceof Error ? err.message : String(err) }));
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async checkThresholds(target, cap, spent) {
|
|
362
|
+
const key = `${target}@${cap}`;
|
|
363
|
+
const day = this.file.day;
|
|
364
|
+
const name = this.nameOf(target);
|
|
365
|
+
if (spent >= cap) {
|
|
366
|
+
if (day.stopped.includes(key))
|
|
367
|
+
return;
|
|
368
|
+
day.stopped.push(key);
|
|
369
|
+
if (!day.warned.includes(key))
|
|
370
|
+
day.warned.push(key);
|
|
371
|
+
this.persist();
|
|
372
|
+
this.logger?.warn('Daily spend cap reached — hard stop (no new turns until midnight)', { target, capUsd: cap, spentUsd: cents(spent) });
|
|
373
|
+
await this.announceStop(target, name, cap, spent);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (spent >= cap * C.WARN_FRACTION && !day.warned.includes(key)) {
|
|
377
|
+
day.warned.push(key);
|
|
378
|
+
this.persist();
|
|
379
|
+
const pct = Math.floor((spent / cap) * 100);
|
|
380
|
+
const who = target === C.TOTAL_TARGET ? 'All agents together have' : `${name} has`;
|
|
381
|
+
const its = target === C.TOTAL_TARGET ? 'the' : 'its';
|
|
382
|
+
const stops = target === C.TOTAL_TARGET ? 'every agent stops' : 'it stops';
|
|
383
|
+
await this.notify(`Heads-up: ${who} spent ${formatUsd(spent)} of ${its} ${formatUsd(cap)} daily spend cap today (${pct}%). At ${formatUsd(cap)} ${stops} taking new turns until midnight.`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async announceStop(target, name, cap, spent) {
|
|
387
|
+
const raise = suggestedRaise(cap, spent);
|
|
388
|
+
const who = target === C.TOTAL_TARGET ? 'total' : target === ORCHESTRATOR_SESSION_NAME ? 'orc' : name;
|
|
389
|
+
const headline = target === C.TOTAL_TARGET
|
|
390
|
+
? `All agents together hit the daily total spend cap (${formatUsd(cap)}); every agent is stopped until midnight.`
|
|
391
|
+
: `${name} hit its daily spend cap (${formatUsd(cap)}) and is stopped until midnight.`;
|
|
392
|
+
const decisions = this.deps.decisions?.() ?? null;
|
|
393
|
+
if (decisions) {
|
|
394
|
+
try {
|
|
395
|
+
const d = await decisions.askSystem({
|
|
396
|
+
kind: C.DECISION_KIND,
|
|
397
|
+
system: { key: target, defaultIsDecline: true },
|
|
398
|
+
title: 'Daily spend cap reached',
|
|
399
|
+
question: `${headline} Raise it for today?`,
|
|
400
|
+
body: [
|
|
401
|
+
`Spent today: ${formatUsd(spent)}. The current turn was allowed to finish; no new turns start. Messages are kept and delivered when it runs again.`,
|
|
402
|
+
],
|
|
403
|
+
options: [`Raise to $${raise} today — runs again until midnight`, `${C.OPTIONS.KEEP} — resets at midnight`],
|
|
404
|
+
default: C.OPTIONS.KEEP,
|
|
405
|
+
deadline: this.nextMidnight(),
|
|
406
|
+
sensitive: 'spend',
|
|
407
|
+
});
|
|
408
|
+
this.file.day.cards[target] = d.id;
|
|
409
|
+
this.persist();
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
catch (err) {
|
|
413
|
+
this.logger?.warn('Could not post the spend cap card — sending a notice instead', { target, error: err instanceof Error ? err.message : String(err) });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
await this.notify(`${headline} Its messages are queued. Reply \`raise cap for ${who} to $${raise} today\` to raise it.`);
|
|
417
|
+
}
|
|
418
|
+
anyCap() {
|
|
419
|
+
const cfg = this.file.config;
|
|
420
|
+
return (isCap(cfg.defaultAgentCapUsd) ||
|
|
421
|
+
isCap(cfg.totalCapUsd) ||
|
|
422
|
+
Object.values(cfg.agentCapsUsd).some(isCap) ||
|
|
423
|
+
Object.values(this.file.day.raised).some(isCap));
|
|
424
|
+
}
|
|
425
|
+
computeStop(session) {
|
|
426
|
+
const own = this.capOf(session).capUsd;
|
|
427
|
+
if (own !== null) {
|
|
428
|
+
const spent = this.deps.ledger.spentToday(session);
|
|
429
|
+
if (spent >= own)
|
|
430
|
+
return { session, scope: 'agent', capUsd: own, spentUsd: spent };
|
|
431
|
+
}
|
|
432
|
+
const total = this.capOf(C.TOTAL_TARGET).capUsd;
|
|
433
|
+
if (total !== null) {
|
|
434
|
+
const spent = this.deps.ledger.totalToday();
|
|
435
|
+
if (spent >= total)
|
|
436
|
+
return { session, scope: 'total', capUsd: total, spentUsd: spent };
|
|
437
|
+
}
|
|
438
|
+
return null;
|
|
439
|
+
}
|
|
440
|
+
stopKey(stop) {
|
|
441
|
+
return `${stop.scope === 'total' ? C.TOTAL_TARGET : stop.session}@${stop.capUsd}`;
|
|
442
|
+
}
|
|
443
|
+
scheduleEvaluate() {
|
|
444
|
+
void this.evaluate();
|
|
445
|
+
}
|
|
446
|
+
/** Reset today's bookkeeping when the local day changed. */
|
|
447
|
+
rollDay() {
|
|
448
|
+
const today = localDateKey(this.now());
|
|
449
|
+
if (this.file.day.date === today)
|
|
450
|
+
return;
|
|
451
|
+
const had = Object.keys(this.file.day.raised).length + this.file.day.stopped.length;
|
|
452
|
+
this.file.day = emptyDay(today);
|
|
453
|
+
this.deps.ledger.invalidate();
|
|
454
|
+
this.persist();
|
|
455
|
+
if (had > 0)
|
|
456
|
+
this.logger?.info('Spend caps reset for the new day', { date: today });
|
|
457
|
+
}
|
|
458
|
+
nextMidnight() {
|
|
459
|
+
const next = localMidnight(this.now());
|
|
460
|
+
next.setDate(next.getDate() + 1);
|
|
461
|
+
// A card must have a future deadline even in the last minute of the day.
|
|
462
|
+
return next.getTime() - this.now().getTime() < 60_000 ? new Date(this.now().getTime() + 60_000) : next;
|
|
463
|
+
}
|
|
464
|
+
nameOf(target) {
|
|
465
|
+
if (target === C.TOTAL_TARGET)
|
|
466
|
+
return 'All agents';
|
|
467
|
+
try {
|
|
468
|
+
return this.deps.displayNameOf?.(target) || target;
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
return target;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
async notify(text) {
|
|
475
|
+
try {
|
|
476
|
+
await this.deps.notifyOwner(text);
|
|
477
|
+
}
|
|
478
|
+
catch (err) {
|
|
479
|
+
this.logger?.warn('Could not send the spend cap notice', { error: err instanceof Error ? err.message : String(err) });
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async reply(decisionId, text) {
|
|
483
|
+
await this.deps.decisions?.()?.replyInThread(decisionId, text).catch(() => undefined);
|
|
484
|
+
}
|
|
485
|
+
persist() {
|
|
486
|
+
try {
|
|
487
|
+
this.deps.store.write(this.file);
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
this.logger?.warn('Could not save spend caps', { error: err instanceof Error ? err.message : String(err) });
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
let instance = null;
|
|
495
|
+
/** @returns The backend's service, or null before it is wired */
|
|
496
|
+
export function getSpendCapService() {
|
|
497
|
+
return instance;
|
|
498
|
+
}
|
|
499
|
+
/** @param service - Instance (null clears) */
|
|
500
|
+
export function setSpendCapService(service) {
|
|
501
|
+
instance = service;
|
|
502
|
+
}
|
|
503
|
+
//# sourceMappingURL=spend-cap.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spend-cap.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/spend/spend-cap.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spend caps on disk: the owner's caps plus today's bookkeeping (raises,
|
|
3
|
+
* the 80% notices and stop cards already sent). One small JSON file under
|
|
4
|
+
* CREWLY_HOME, written atomically.
|
|
5
|
+
*
|
|
6
|
+
* specs/2026-10-02-spend-cap.md
|
|
7
|
+
*
|
|
8
|
+
* @module services/spend/spend-cap.store
|
|
9
|
+
*/
|
|
10
|
+
/** The owner's caps (USD per local day). */
|
|
11
|
+
export interface SpendCapConfig {
|
|
12
|
+
/** Cap for every agent without an override; null = off (the default) */
|
|
13
|
+
defaultAgentCapUsd: number | null;
|
|
14
|
+
/** Cap on all agents together; null = off */
|
|
15
|
+
totalCapUsd: number | null;
|
|
16
|
+
/** Session → its own cap; null = no cap for this agent even when a default is set */
|
|
17
|
+
agentCapsUsd: Record<string, number | null>;
|
|
18
|
+
updatedAt?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Today's bookkeeping; reset at local midnight. */
|
|
21
|
+
export interface SpendCapDayState {
|
|
22
|
+
/** `YYYY-MM-DD`, local */
|
|
23
|
+
date: string;
|
|
24
|
+
/** Target (session, or `*` for the total) → cap raised to for today (USD) */
|
|
25
|
+
raised: Record<string, number>;
|
|
26
|
+
/** `target@cap` keys whose 80% notice was sent */
|
|
27
|
+
warned: string[];
|
|
28
|
+
/** `target@cap` keys whose stop was announced */
|
|
29
|
+
stopped: string[];
|
|
30
|
+
/** Target → id of today's "cap reached" decision card */
|
|
31
|
+
cards: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
/** The file. */
|
|
34
|
+
export interface SpendCapFile {
|
|
35
|
+
config: SpendCapConfig;
|
|
36
|
+
day: SpendCapDayState;
|
|
37
|
+
}
|
|
38
|
+
/** Storage the service uses (tests pass an in-memory one). */
|
|
39
|
+
export interface SpendCapStoreLike {
|
|
40
|
+
read(): SpendCapFile | null;
|
|
41
|
+
write(file: SpendCapFile): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Caps off, nothing recorded.
|
|
45
|
+
*
|
|
46
|
+
* @param date - Local day
|
|
47
|
+
* @returns Fresh file
|
|
48
|
+
*/
|
|
49
|
+
export declare function emptySpendCapFile(date: string): SpendCapFile;
|
|
50
|
+
/**
|
|
51
|
+
* Empty day state.
|
|
52
|
+
*
|
|
53
|
+
* @param date - Local day
|
|
54
|
+
* @returns State
|
|
55
|
+
*/
|
|
56
|
+
export declare function emptyDay(date: string): SpendCapDayState;
|
|
57
|
+
/**
|
|
58
|
+
* JSON file store.
|
|
59
|
+
*/
|
|
60
|
+
export declare class FileSpendCapStore implements SpendCapStoreLike {
|
|
61
|
+
private readonly file;
|
|
62
|
+
/**
|
|
63
|
+
* @param file - Absolute path
|
|
64
|
+
*/
|
|
65
|
+
constructor(file: string);
|
|
66
|
+
/**
|
|
67
|
+
* @returns The file, or null when absent / unreadable
|
|
68
|
+
*/
|
|
69
|
+
read(): SpendCapFile | null;
|
|
70
|
+
/**
|
|
71
|
+
* @param file - Contents to persist
|
|
72
|
+
*/
|
|
73
|
+
write(file: SpendCapFile): void;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* In-memory store (tests).
|
|
77
|
+
*/
|
|
78
|
+
export declare class MemorySpendCapStore implements SpendCapStoreLike {
|
|
79
|
+
file: SpendCapFile | null;
|
|
80
|
+
/** @returns Stored copy */
|
|
81
|
+
read(): SpendCapFile | null;
|
|
82
|
+
/** @param file - Contents */
|
|
83
|
+
write(file: SpendCapFile): void;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=spend-cap.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spend-cap.store.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/spend/spend-cap.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,6CAA6C;IAC7C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC/B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,kDAAkD;IAClD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iDAAiD;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,gBAAgB;AAChB,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,GAAG,EAAE,gBAAgB,CAAC;CACvB;AAED,8DAA8D;AAC9D,MAAM,WAAW,iBAAiB;IAChC,IAAI,IAAI,YAAY,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAK5D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAEvD;AAED;;GAEG;AACH,qBAAa,iBAAkB,YAAW,iBAAiB;IAI7C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC;;OAEG;gBAC0B,IAAI,EAAE,MAAM;IAEzC;;OAEG;IACH,IAAI,IAAI,YAAY,GAAG,IAAI;IAsB3B;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;CAMhC;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,IAAI,EAAE,YAAY,GAAG,IAAI,CAAQ;IAEjC,2BAA2B;IAC3B,IAAI,IAAI,YAAY,GAAG,IAAI;IAI3B,6BAA6B;IAC7B,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;CAGhC"}
|