@penclipai/server 2026.704.0 → 2026.714.0
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/dist/adapters/index.d.ts +1 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/process/execute.d.ts.map +1 -1
- package/dist/adapters/process/execute.js +1 -0
- package/dist/adapters/process/execute.js.map +1 -1
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +79 -51
- package/dist/adapters/registry.js.map +1 -1
- package/dist/adapters/utils.d.ts +5 -0
- package/dist/adapters/utils.d.ts.map +1 -1
- package/dist/adapters/utils.js.map +1 -1
- package/dist/agent-auth-jwt.d.ts +5 -1
- package/dist/agent-auth-jwt.d.ts.map +1 -1
- package/dist/agent-auth-jwt.js +72 -20
- package/dist/agent-auth-jwt.js.map +1 -1
- package/dist/app.d.ts +2 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +10 -0
- package/dist/app.js.map +1 -1
- package/dist/built-ins/agents/reflection-coach/AGENTS.md +47 -0
- package/dist/built-ins/agents/reflection-coach/routines/recent-agent-reflection.md +77 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +2 -2
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +208 -116
- package/dist/index.js.map +1 -1
- package/dist/middleware/api-compression.d.ts +8 -0
- package/dist/middleware/api-compression.d.ts.map +1 -0
- package/dist/middleware/api-compression.js +207 -0
- package/dist/middleware/api-compression.js.map +1 -0
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +130 -3
- package/dist/middleware/auth.js.map +1 -1
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +27 -0
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/onboarding-assets/default/AGENTS.md +1 -0
- package/dist/redaction.d.ts.map +1 -1
- package/dist/redaction.js +11 -0
- package/dist/redaction.js.map +1 -1
- package/dist/routes/access.d.ts.map +1 -1
- package/dist/routes/access.js +4 -3
- package/dist/routes/access.js.map +1 -1
- package/dist/routes/adapters.d.ts.map +1 -1
- package/dist/routes/adapters.js +2 -0
- package/dist/routes/adapters.js.map +1 -1
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +222 -87
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/attention.d.ts +3 -0
- package/dist/routes/attention.d.ts.map +1 -0
- package/dist/routes/attention.js +24 -0
- package/dist/routes/attention.js.map +1 -0
- package/dist/routes/authz.d.ts.map +1 -1
- package/dist/routes/authz.js +29 -1
- package/dist/routes/authz.js.map +1 -1
- package/dist/routes/board-chat.d.ts.map +1 -1
- package/dist/routes/board-chat.js +4 -1
- package/dist/routes/board-chat.js.map +1 -1
- package/dist/routes/built-in-agents.d.ts +3 -0
- package/dist/routes/built-in-agents.d.ts.map +1 -0
- package/dist/routes/built-in-agents.js +267 -0
- package/dist/routes/built-in-agents.js.map +1 -0
- package/dist/routes/cases.d.ts +46 -0
- package/dist/routes/cases.d.ts.map +1 -0
- package/dist/routes/cases.js +1395 -0
- package/dist/routes/cases.js.map +1 -0
- package/dist/routes/companies.d.ts.map +1 -1
- package/dist/routes/companies.js +4 -1
- package/dist/routes/companies.js.map +1 -1
- package/dist/routes/company-skills.d.ts.map +1 -1
- package/dist/routes/company-skills.js +453 -33
- package/dist/routes/company-skills.js.map +1 -1
- package/dist/routes/environments.d.ts.map +1 -1
- package/dist/routes/environments.js +71 -8
- package/dist/routes/environments.js.map +1 -1
- package/dist/routes/execution-workspaces.d.ts.map +1 -1
- package/dist/routes/execution-workspaces.js +89 -3
- package/dist/routes/execution-workspaces.js.map +1 -1
- package/dist/routes/health.d.ts +2 -0
- package/dist/routes/health.d.ts.map +1 -1
- package/dist/routes/health.js +30 -0
- package/dist/routes/health.js.map +1 -1
- package/dist/routes/inbox-dismissals.d.ts.map +1 -1
- package/dist/routes/inbox-dismissals.js +80 -19
- package/dist/routes/inbox-dismissals.js.map +1 -1
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +2 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/issues.d.ts +25 -0
- package/dist/routes/issues.d.ts.map +1 -1
- package/dist/routes/issues.js +1455 -46
- package/dist/routes/issues.js.map +1 -1
- package/dist/routes/openapi.d.ts.map +1 -1
- package/dist/routes/openapi.js +448 -11
- package/dist/routes/openapi.js.map +1 -1
- package/dist/routes/pipelines.js +2 -2
- package/dist/routes/pipelines.js.map +1 -1
- package/dist/routes/resource-memberships.d.ts.map +1 -1
- package/dist/routes/resource-memberships.js +13 -5
- package/dist/routes/resource-memberships.js.map +1 -1
- package/dist/routes/secrets.d.ts.map +1 -1
- package/dist/routes/secrets.js +261 -1
- package/dist/routes/secrets.js.map +1 -1
- package/dist/routes/sidebar-badges.d.ts.map +1 -1
- package/dist/routes/sidebar-badges.js +18 -2
- package/dist/routes/sidebar-badges.js.map +1 -1
- package/dist/routes/user-profiles.d.ts.map +1 -1
- package/dist/routes/user-profiles.js +5 -4
- package/dist/routes/user-profiles.js.map +1 -1
- package/dist/server-info.d.ts +2 -0
- package/dist/server-info.d.ts.map +1 -1
- package/dist/server-info.js +20 -5
- package/dist/server-info.js.map +1 -1
- package/dist/services/access.d.ts +4 -4
- package/dist/services/access.d.ts.map +1 -1
- package/dist/services/activity.d.ts +3 -3
- package/dist/services/activity.d.ts.map +1 -1
- package/dist/services/activity.js +5 -4
- package/dist/services/activity.js.map +1 -1
- package/dist/services/adapter-registry-bootstrap.reconcile.test.js +1 -0
- package/dist/services/adapter-registry-bootstrap.reconcile.test.js.map +1 -1
- package/dist/services/agent-secret-bindings.d.ts +15 -0
- package/dist/services/agent-secret-bindings.d.ts.map +1 -1
- package/dist/services/agent-secret-bindings.js +43 -0
- package/dist/services/agent-secret-bindings.js.map +1 -1
- package/dist/services/agents.d.ts +194 -133
- package/dist/services/agents.d.ts.map +1 -1
- package/dist/services/agents.js +107 -4
- package/dist/services/agents.js.map +1 -1
- package/dist/services/approvals.d.ts +10 -10
- package/dist/services/approvals.d.ts.map +1 -1
- package/dist/services/approvals.js +9 -1
- package/dist/services/approvals.js.map +1 -1
- package/dist/services/assets.d.ts +5 -5
- package/dist/services/attention.d.ts +11 -0
- package/dist/services/attention.d.ts.map +1 -0
- package/dist/services/attention.js +1024 -0
- package/dist/services/attention.js.map +1 -0
- package/dist/services/authorization.d.ts +15 -2
- package/dist/services/authorization.d.ts.map +1 -1
- package/dist/services/authorization.js +324 -8
- package/dist/services/authorization.js.map +1 -1
- package/dist/services/board-auth.d.ts +2 -2
- package/dist/services/budgets.d.ts.map +1 -1
- package/dist/services/budgets.js +8 -7
- package/dist/services/budgets.js.map +1 -1
- package/dist/services/built-in-agent-metadata.d.ts +9 -0
- package/dist/services/built-in-agent-metadata.d.ts.map +1 -0
- package/dist/services/built-in-agent-metadata.js +39 -0
- package/dist/services/built-in-agent-metadata.js.map +1 -0
- package/dist/services/built-in-agents.d.ts +394 -0
- package/dist/services/built-in-agents.d.ts.map +1 -0
- package/dist/services/built-in-agents.js +1426 -0
- package/dist/services/built-in-agents.js.map +1 -0
- package/dist/services/change-consent-gate.d.ts +18 -0
- package/dist/services/change-consent-gate.d.ts.map +1 -0
- package/dist/services/change-consent-gate.js +170 -0
- package/dist/services/change-consent-gate.js.map +1 -0
- package/dist/services/companies.d.ts +14 -8
- package/dist/services/companies.d.ts.map +1 -1
- package/dist/services/companies.js +6 -1
- package/dist/services/companies.js.map +1 -1
- package/dist/services/company-artifacts.d.ts +4 -1
- package/dist/services/company-artifacts.d.ts.map +1 -1
- package/dist/services/company-artifacts.js +9 -1
- package/dist/services/company-artifacts.js.map +1 -1
- package/dist/services/company-member-roles.d.ts.map +1 -1
- package/dist/services/company-member-roles.js +2 -0
- package/dist/services/company-member-roles.js.map +1 -1
- package/dist/services/company-portability.d.ts +1 -1
- package/dist/services/company-portability.d.ts.map +1 -1
- package/dist/services/company-portability.js +113 -8
- package/dist/services/company-portability.js.map +1 -1
- package/dist/services/company-search.d.ts.map +1 -1
- package/dist/services/company-search.js +843 -294
- package/dist/services/company-search.js.map +1 -1
- package/dist/services/company-skills.d.ts +64 -3
- package/dist/services/company-skills.d.ts.map +1 -1
- package/dist/services/company-skills.js +1205 -20
- package/dist/services/company-skills.js.map +1 -1
- package/dist/services/costs.d.ts +9 -8
- package/dist/services/costs.d.ts.map +1 -1
- package/dist/services/costs.js +9 -2
- package/dist/services/costs.js.map +1 -1
- package/dist/services/dashboard.d.ts +2 -0
- package/dist/services/dashboard.d.ts.map +1 -1
- package/dist/services/dashboard.js +60 -17
- package/dist/services/dashboard.js.map +1 -1
- package/dist/services/database-backup-health.d.ts +34 -0
- package/dist/services/database-backup-health.d.ts.map +1 -0
- package/dist/services/database-backup-health.js +104 -0
- package/dist/services/database-backup-health.js.map +1 -0
- package/dist/services/document-annotations.d.ts +169 -1
- package/dist/services/document-annotations.d.ts.map +1 -1
- package/dist/services/document-annotations.js +272 -1
- package/dist/services/document-annotations.js.map +1 -1
- package/dist/services/documents.d.ts +368 -0
- package/dist/services/documents.d.ts.map +1 -1
- package/dist/services/documents.js +2 -2
- package/dist/services/documents.js.map +1 -1
- package/dist/services/environment-config.d.ts.map +1 -1
- package/dist/services/environment-config.js +6 -0
- package/dist/services/environment-config.js.map +1 -1
- package/dist/services/environment-custom-image-runtime.d.ts +28 -0
- package/dist/services/environment-custom-image-runtime.d.ts.map +1 -1
- package/dist/services/environment-custom-image-runtime.js +106 -7
- package/dist/services/environment-custom-image-runtime.js.map +1 -1
- package/dist/services/environment-custom-images.d.ts +31 -1
- package/dist/services/environment-custom-images.d.ts.map +1 -1
- package/dist/services/environment-custom-images.js +110 -4
- package/dist/services/environment-custom-images.js.map +1 -1
- package/dist/services/environment-execution-target.d.ts.map +1 -1
- package/dist/services/environment-execution-target.js +1 -3
- package/dist/services/environment-execution-target.js.map +1 -1
- package/dist/services/environment-probe.d.ts +1 -0
- package/dist/services/environment-probe.d.ts.map +1 -1
- package/dist/services/environment-probe.js +99 -5
- package/dist/services/environment-probe.js.map +1 -1
- package/dist/services/environments.d.ts +3 -1
- package/dist/services/environments.d.ts.map +1 -1
- package/dist/services/environments.js +98 -3
- package/dist/services/environments.js.map +1 -1
- package/dist/services/execution-workspace-policy.d.ts +29 -3
- package/dist/services/execution-workspace-policy.d.ts.map +1 -1
- package/dist/services/execution-workspace-policy.js +44 -1
- package/dist/services/execution-workspace-policy.js.map +1 -1
- package/dist/services/execution-workspaces.d.ts +64 -1
- package/dist/services/execution-workspaces.d.ts.map +1 -1
- package/dist/services/execution-workspaces.js +634 -3
- package/dist/services/execution-workspaces.js.map +1 -1
- package/dist/services/external-objects.d.ts +26 -26
- package/dist/services/feedback.d.ts +2 -2
- package/dist/services/finance.d.ts +5 -5
- package/dist/services/goals.d.ts +8 -8
- package/dist/services/heartbeat-stop-metadata.d.ts +2 -2
- package/dist/services/heartbeat-stop-metadata.d.ts.map +1 -1
- package/dist/services/heartbeat-stop-metadata.js +4 -0
- package/dist/services/heartbeat-stop-metadata.js.map +1 -1
- package/dist/services/heartbeat-stop-metadata.test.js +9 -0
- package/dist/services/heartbeat-stop-metadata.test.js.map +1 -1
- package/dist/services/heartbeat.d.ts +133 -28
- package/dist/services/heartbeat.d.ts.map +1 -1
- package/dist/services/heartbeat.js +1963 -239
- package/dist/services/heartbeat.js.map +1 -1
- package/dist/services/inbox-dismissals.d.ts +26 -0
- package/dist/services/inbox-dismissals.d.ts.map +1 -1
- package/dist/services/inbox-dismissals.js +33 -18
- package/dist/services/inbox-dismissals.js.map +1 -1
- package/dist/services/index.d.ts +3 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +3 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance-settings.d.ts +25 -1
- package/dist/services/instance-settings.d.ts.map +1 -1
- package/dist/services/instance-settings.js +103 -5
- package/dist/services/instance-settings.js.map +1 -1
- package/dist/services/issue-continuation-summary.js +1 -1
- package/dist/services/issue-continuation-summary.js.map +1 -1
- package/dist/services/issue-recovery-actions.d.ts +3 -0
- package/dist/services/issue-recovery-actions.d.ts.map +1 -1
- package/dist/services/issue-recovery-actions.js +9 -0
- package/dist/services/issue-recovery-actions.js.map +1 -1
- package/dist/services/issue-rewake-throttle.d.ts +92 -0
- package/dist/services/issue-rewake-throttle.d.ts.map +1 -0
- package/dist/services/issue-rewake-throttle.js +139 -0
- package/dist/services/issue-rewake-throttle.js.map +1 -0
- package/dist/services/issue-thread-interactions.d.ts +8 -1
- package/dist/services/issue-thread-interactions.d.ts.map +1 -1
- package/dist/services/issue-thread-interactions.js +231 -16
- package/dist/services/issue-thread-interactions.js.map +1 -1
- package/dist/services/issue-visibility.d.ts +4 -0
- package/dist/services/issue-visibility.d.ts.map +1 -0
- package/dist/services/issue-visibility.js +9 -0
- package/dist/services/issue-visibility.js.map +1 -0
- package/dist/services/issues.d.ts +225 -105
- package/dist/services/issues.d.ts.map +1 -1
- package/dist/services/issues.js +540 -18
- package/dist/services/issues.js.map +1 -1
- package/dist/services/local-service-supervisor.d.ts +3 -0
- package/dist/services/local-service-supervisor.d.ts.map +1 -1
- package/dist/services/local-service-supervisor.js +51 -0
- package/dist/services/local-service-supervisor.js.map +1 -1
- package/dist/services/pipeline-case-outputs.d.ts.map +1 -1
- package/dist/services/pipeline-case-outputs.js +2 -1
- package/dist/services/pipeline-case-outputs.js.map +1 -1
- package/dist/services/pipelines-aggregation.d.ts.map +1 -1
- package/dist/services/pipelines-aggregation.js +3 -2
- package/dist/services/pipelines-aggregation.js.map +1 -1
- package/dist/services/pipelines.d.ts +165 -165
- package/dist/services/pipelines.d.ts.map +1 -1
- package/dist/services/pipelines.js +6 -4
- package/dist/services/pipelines.js.map +1 -1
- package/dist/services/plugin-database.d.ts +2 -2
- package/dist/services/plugin-environment-driver.d.ts +1 -1
- package/dist/services/plugin-host-services.d.ts.map +1 -1
- package/dist/services/plugin-host-services.js +3 -1
- package/dist/services/plugin-host-services.js.map +1 -1
- package/dist/services/plugin-managed-routines.d.ts +1 -0
- package/dist/services/plugin-managed-routines.d.ts.map +1 -1
- package/dist/services/plugin-registry.d.ts +21 -21
- package/dist/services/productivity-review.d.ts +1 -0
- package/dist/services/productivity-review.d.ts.map +1 -1
- package/dist/services/productivity-review.js +6 -5
- package/dist/services/productivity-review.js.map +1 -1
- package/dist/services/projects.d.ts +9 -9
- package/dist/services/recovery/service.d.ts +82 -54
- package/dist/services/recovery/service.d.ts.map +1 -1
- package/dist/services/recovery/service.js +200 -35
- package/dist/services/recovery/service.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.d.ts +1 -0
- package/dist/services/recovery/successful-run-handoff.d.ts.map +1 -1
- package/dist/services/recovery/successful-run-handoff.js +2 -0
- package/dist/services/recovery/successful-run-handoff.js.map +1 -1
- package/dist/services/recovery/successful-run-handoff.test.js +20 -0
- package/dist/services/recovery/successful-run-handoff.test.js.map +1 -1
- package/dist/services/resource-memberships.d.ts +13 -10
- package/dist/services/resource-memberships.d.ts.map +1 -1
- package/dist/services/resource-memberships.js +89 -20
- package/dist/services/resource-memberships.js.map +1 -1
- package/dist/services/responsible-user-denial-run-outcomes.d.ts +60 -0
- package/dist/services/responsible-user-denial-run-outcomes.d.ts.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.js +56 -0
- package/dist/services/responsible-user-denial-run-outcomes.js.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.d.ts +2 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.d.ts.map +1 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.js +75 -0
- package/dist/services/responsible-user-denial-run-outcomes.test.js.map +1 -0
- package/dist/services/routines.d.ts +30 -8
- package/dist/services/routines.d.ts.map +1 -1
- package/dist/services/routines.js +241 -18
- package/dist/services/routines.js.map +1 -1
- package/dist/services/run-liveness.d.ts.map +1 -1
- package/dist/services/run-liveness.js +21 -0
- package/dist/services/run-liveness.js.map +1 -1
- package/dist/services/run-log-store.d.ts +1 -0
- package/dist/services/run-log-store.d.ts.map +1 -1
- package/dist/services/run-log-store.js +4 -0
- package/dist/services/run-log-store.js.map +1 -1
- package/dist/services/run-scratch.d.ts +42 -0
- package/dist/services/run-scratch.d.ts.map +1 -0
- package/dist/services/run-scratch.js +111 -0
- package/dist/services/run-scratch.js.map +1 -0
- package/dist/services/run-scratch.test.d.ts +2 -0
- package/dist/services/run-scratch.test.d.ts.map +1 -0
- package/dist/services/run-scratch.test.js +98 -0
- package/dist/services/run-scratch.test.js.map +1 -0
- package/dist/services/secrets.d.ts +1261 -64
- package/dist/services/secrets.d.ts.map +1 -1
- package/dist/services/secrets.js +1089 -96
- package/dist/services/secrets.js.map +1 -1
- package/dist/services/task-watchdogs.d.ts +1 -0
- package/dist/services/task-watchdogs.d.ts.map +1 -1
- package/dist/services/task-watchdogs.js +78 -9
- package/dist/services/task-watchdogs.js.map +1 -1
- package/dist/services/work-timeline.d.ts.map +1 -1
- package/dist/services/work-timeline.js +34 -2
- package/dist/services/work-timeline.js.map +1 -1
- package/dist/services/workspace-runtime-read-model.d.ts +30 -29
- package/dist/services/workspace-runtime-read-model.d.ts.map +1 -1
- package/dist/services/workspace-runtime-read-model.js.map +1 -1
- package/dist/services/workspace-runtime.d.ts +59 -13
- package/dist/services/workspace-runtime.d.ts.map +1 -1
- package/dist/services/workspace-runtime.js +1121 -102
- package/dist/services/workspace-runtime.js.map +1 -1
- package/dist/skills-catalog/catalog/bundled/paperclip-operations/reflection-coach/SKILL.md +202 -0
- package/dist/skills-catalog/catalog/bundled/product/paperclip-capsules/SKILL.md +1 -1
- package/dist/skills-catalog/catalog/bundled/product/wireframe/SKILL.md +1 -1
- package/dist/skills-catalog/catalog/optional/content/release-announcement/SKILL.md +90 -0
- package/dist/skills-catalog/catalog/optional/finance/ramp/SKILL.md +98 -0
- package/dist/skills-catalog/generated/catalog.json +84 -12
- package/dist/ui-branding.d.ts +7 -0
- package/dist/ui-branding.d.ts.map +1 -1
- package/dist/ui-branding.js +8 -2
- package/dist/ui-branding.js.map +1 -1
- package/dist/version.d.ts +14 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +114 -3
- package/dist/version.js.map +1 -1
- package/package.json +19 -20
- package/skills/paperclip/SKILL.md +45 -10
- package/skills/paperclip/references/api-reference.md +246 -1
- package/skills/paperclip/references/cases.md +295 -0
- package/skills/paperclip/references/company-skills.md +1 -1
- package/skills/paperclip-board/SKILL.md +3 -4
- package/skills/paperclip-converting-plans-to-tasks/SKILL.md +3 -7
- package/skills/para-memory-files/SKILL.md +3 -7
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-BsFz2IiG.js → abnfDiagram-VRR7QNED-Dtgfy1PK.js} +1 -1
- package/ui-dist/assets/{arc-HZhAwbOs.js → arc-BGdvNvs8.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-BteMjuOn.js → architectureDiagram-ZJ3FMSHR-CK19SQDx.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-Iq66uZjf.js → blockDiagram-677ZJIJ3-Kh4N3XG4.js} +1 -1
- package/ui-dist/assets/{browser-ponyfill-BBsuyZJt.js → browser-ponyfill-B3hXtEFW.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-_nlglj7I.js → c4Diagram-LMCZKHZV-CBHpGrgU.js} +1 -1
- package/ui-dist/assets/channel-4fjB8e8N.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-Cvz7WwSQ.js → chunk-2Q5K7J3B-BdHbqi7k.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-LLubniCS.js → chunk-32BRIVSS-DxtzZzpt.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-BOst5hcr.js → chunk-5VM5RSS4-DMKxBbgu.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-D5WNShVm.js → chunk-EX3LRPZG-BaIOPi4v.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-CA07x4av.js → chunk-JWPE2WC7-DGo3MPmr.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-Clfi83rK.js → chunk-MOJQB5TN-BEhQg0uD.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-BhZ6p7YJ.js → chunk-RYQCIY6F-HPJ6zRpJ.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-CdexJGoV.js → chunk-V7JOEXUC-Bl_6cAJD.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-8vjmBhr1.js → chunk-VR4S4FIN-KMjgGCsw.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-CqmCaplj.js → chunk-XXDRQBXY-oWGAIKjr.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CTXxO5l9.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CTXxO5l9.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-CY-zAygY.js → cose-bilkent-JH36ORCC-Ckqse1pH.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-BQSQ1HKr.js → cynefin-VYW2F7L2-DfZ8Hzqi.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-NJCuFrZL.js → cynefinDiagram-TSTJHNR4-BkDQo9oi.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-DAUPIc8g.js → dagre-VKFMJZFB-ClghXQ6E.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-DvMwJlCi.js → diagram-FQU43EPY-D5a0CwpV.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-DPY0Jz_y.js → diagram-G47NLZAW-hVjYR_xl.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-BpopeEhp.js → diagram-NH7WQ7WH-BlDPgD5Z.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-Qpu05z9X.js → diagram-OA4YK3LP-D0iZKIS3.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-DHnvw9XU.js → diagram-WEI45ONY-m6hrfD0J.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-D61S54_7.js → ebnfDiagram-CCIWWBDH-D4SQYLod.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-pplAN_x2.js → erDiagram-Q63AITRT-Byzb6-I5.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-BaBcbyDq.js → flowDiagram-23GEKE2U-CaTUkFO6.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-BOJSII2b.js → ganttDiagram-NO4QXBWP-DmdMQ3ES.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-aYAaO4a2.js → gitGraphDiagram-IHSO6WYX-Bt-1g2CS.js} +1 -1
- package/ui-dist/assets/{index-CZxYajxF.js → index-2Dk9yO0W.js} +1 -1
- package/ui-dist/assets/{index-B8H0SHw1.js → index-8jLpgFNU.js} +1 -1
- package/ui-dist/assets/{index-3EKATXgc.js → index-AP_iimxs.js} +1 -1
- package/ui-dist/assets/{index-C2JgdjPa.js → index-BNJasQY9.js} +1 -1
- package/ui-dist/assets/{index-BaiskB3o.js → index-BO-aNmyX.js} +1 -1
- package/ui-dist/assets/{index-B5YenxAQ.js → index-BPCzCn1Y.js} +1 -1
- package/ui-dist/assets/{index-Da2kqT1M.js → index-BSLnLTb2.js} +1 -1
- package/ui-dist/assets/{index-By0oeEvz.js → index-CCZ2qgHN.js} +1 -1
- package/ui-dist/assets/{index-bUFCSEgv.js → index-CLZXR1k9.js} +1 -1
- package/ui-dist/assets/{index-CJlw4l9L.js → index-CTNfrE1s.js} +1 -1
- package/ui-dist/assets/{index-TmpY6Xh_.js → index-ChNd25s7.js} +1 -1
- package/ui-dist/assets/{index-BRgdHUNR.js → index-CjHiMOEO.js} +1 -1
- package/ui-dist/assets/{index-DrL6pHSJ.js → index-CmeJQpXZ.js} +1 -1
- package/ui-dist/assets/index-CyuYtn7U.css +1 -0
- package/ui-dist/assets/{index-CKKytnOd.js → index-CzZjM8eh.js} +1 -1
- package/ui-dist/assets/{index-Dceamza_.js → index-D-6T0Aft.js} +1 -1
- package/ui-dist/assets/{index-CjDqB1SX.js → index-DG_7V1pG.js} +1 -1
- package/ui-dist/assets/index-DIKcgxCt.js +676 -0
- package/ui-dist/assets/{index-BKVeJ3Jh.js → index-DiUerHmi.js} +1 -1
- package/ui-dist/assets/{index-C-nKjFZh.js → index-NZ7v5Fc2.js} +1 -1
- package/ui-dist/assets/{index-CvPPuNs1.js → index-Py70EvBg.js} +1 -1
- package/ui-dist/assets/{index-LHkZdu0h.js → index-R3aYn0qM.js} +1 -1
- package/ui-dist/assets/{index-BT8b79Bd.js → index-YXpm7gW-.js} +1 -1
- package/ui-dist/assets/{index-CemenVOf.js → index-n4q3gzki.js} +1 -1
- package/ui-dist/assets/{index-D3ODiUup.js → index-vlZ3GoYY.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-C7_90qGq.js → infoDiagram-FWYZ7A6U-jdi5ciVg.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-T-nPPdTt.js → ishikawaDiagram-FXEZZL3T-CMz5VvYp.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-C3hqQN0R.js → journeyDiagram-5HDEW3XC-DK6dk2R-.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-CPoD9DUm.js → kanban-definition-HUTT4EX6-DX5cZL-D.js} +1 -1
- package/ui-dist/assets/{linear-D-S8yr3Z.js → linear-CI96ABKp.js} +1 -1
- package/ui-dist/assets/{mermaid.core-DhvH8shK.js → mermaid.core-DnsEVfbd.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-CxCIKrKo.js → mindmap-definition-LN4V7U3C-BdDCY7hf.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-D4G-PC6N.js → pegDiagram-2B236MQR-DuY4TF-f.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-N4X8UvqY.js → pieDiagram-ENE6RG2P-bgFw7dm3.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-CZohoDln.js → quadrantDiagram-ABIIQ3AL-BCZVWyWS.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-fMGQVhwF.js → railroadDiagram-RFXS5EU6-D9V5_Cgc.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-CK0IuUmk.js → requirementDiagram-TGXJPOKE-CItsya2r.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-pSfb3CqG.js → sankeyDiagram-HTMAVEWB-Cz9IHsZO.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-CbhkqIeq.js → sequenceDiagram-DBY2YBRQ-hMSqTiwK.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-B6vqqPx-.js → sizeCapture-X5ZJPWSS-0g9M5wMf.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-DIJf9h5C.js → stateDiagram-2N3HPSRC-F8_YhgWl.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-fZImUBtq.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-DIX_LV8O.js → swimlanes-5IMT3BWC-CCZqPbpE.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-9C1UT51R.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-CD-Pxb_g.js → timeline-definition-FHXFAJF6-BeUIr18x.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-BAZsWL0R.js → vennDiagram-L72KCM5P-D3d5h_G4.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-CnNyfwX5.js → wardleyDiagram-EHGQE667-Bzt-As9A.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-j9YgsD3Y.js → xychartDiagram-FW5EYKEG-C2mly0xf.js} +1 -1
- package/ui-dist/fonts/InterVariable-Italic.woff2 +0 -0
- package/ui-dist/fonts/InterVariable.woff2 +0 -0
- package/ui-dist/fonts/NOTICE.md +17 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/locales/en/common.json +1142 -5
- package/ui-dist/locales/zh-CN/common.json +1140 -3
- package/ui-dist/assets/channel-CsiI2LYw.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-CBn1Jqo8.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-CBn1Jqo8.js +0 -1
- package/ui-dist/assets/index-BsL8K1vL.css +0 -1
- package/ui-dist/assets/index-D__fTsb2.js +0 -643
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-DpwLD7YL.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Cklauutg.js +0 -8
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PAP-13775: throttle no-information issue re-wakes.
|
|
3
|
+
*
|
|
4
|
+
* After a process death (or any stall), external drivers — assignment pollers,
|
|
5
|
+
* stranded-issue reconcilers, on-demand invokes — can re-wake the same agent
|
|
6
|
+
* for the same issue every few seconds for as long as the issue stays
|
|
7
|
+
* `in_progress`. When each of those runs ends without changing any
|
|
8
|
+
* issue-visible state, every wake pays a full adapter session for zero new
|
|
9
|
+
* information (the Phase 4 interruption-recovery smoke paid 25 sessions and
|
|
10
|
+
* 2.4x cost for one recovery this way).
|
|
11
|
+
*
|
|
12
|
+
* This module decides when such a wake should be skipped: once an issue has
|
|
13
|
+
* accumulated a streak of consecutive succeeded-but-no-issue-progress runs by
|
|
14
|
+
* the same agent, further event-free wakes are held back for an escalating
|
|
15
|
+
* cooldown anchored to the last run's finish time. Any genuinely new input —
|
|
16
|
+
* a comment wake, fresh issue activity, an explicit resume, forceFreshSession,
|
|
17
|
+
* or an event-carrying wake reason — bypasses the throttle entirely.
|
|
18
|
+
*
|
|
19
|
+
* Server-side recovery retries (process-loss retries, missing-comment
|
|
20
|
+
* follow-ups) insert their runs directly and never pass through this gate, so
|
|
21
|
+
* crash recovery stays immediate; only repeated no-op re-invocations slow
|
|
22
|
+
* down.
|
|
23
|
+
*/
|
|
24
|
+
/** Consecutive no-progress runs required before the cooldown engages. */
|
|
25
|
+
export declare const ISSUE_REWAKE_NO_PROGRESS_THRESHOLD = 2;
|
|
26
|
+
/** Cooldown after the threshold streak; doubles per additional no-progress run. */
|
|
27
|
+
export declare const ISSUE_REWAKE_BASE_COOLDOWN_MS = 120000;
|
|
28
|
+
/** Upper bound for the escalating cooldown. */
|
|
29
|
+
export declare const ISSUE_REWAKE_MAX_COOLDOWN_MS: number;
|
|
30
|
+
/** Only runs newer than this feed the streak; older history is ignored. */
|
|
31
|
+
export declare const ISSUE_REWAKE_LOOKBACK_MS: number;
|
|
32
|
+
/** How many recent terminal runs to sample when computing the streak. */
|
|
33
|
+
export declare const ISSUE_REWAKE_RUN_SAMPLE_LIMIT = 8;
|
|
34
|
+
/**
|
|
35
|
+
* Wake reasons that assert issue state rather than deliver a new event.
|
|
36
|
+
* These (plus reason-less on-demand invokes) are the only wakes the throttle
|
|
37
|
+
* applies to; every event-shaped reason (comments, mentions, blockers
|
|
38
|
+
* resolved, interactions, approvals, monitors, reviews, …) passes through.
|
|
39
|
+
*/
|
|
40
|
+
export declare const THROTTLED_ISSUE_REWAKE_REASONS: ReadonlySet<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Activity actions that count as issue-visible progress when attributed to a
|
|
43
|
+
* run. Deliberately narrower than run-liveness "concrete action evidence":
|
|
44
|
+
* tool calls inside the workspace do not move the issue, so they do not reset
|
|
45
|
+
* the streak — a run must leave a comment, mutation, document, work product,
|
|
46
|
+
* interaction, or scheduled continuation behind.
|
|
47
|
+
*/
|
|
48
|
+
export declare const ISSUE_PROGRESS_ACTIVITY_ACTIONS: string[];
|
|
49
|
+
/**
|
|
50
|
+
* Activity on the issue that counts as new external input since the last run
|
|
51
|
+
* finished — anything a waiting agent should be woken for, including board
|
|
52
|
+
* responses to interactions.
|
|
53
|
+
*/
|
|
54
|
+
export declare const ISSUE_NEW_INPUT_ACTIVITY_ACTIONS: string[];
|
|
55
|
+
export interface IssueRewakeCandidateInput {
|
|
56
|
+
reason: string | null;
|
|
57
|
+
wakeCommentId: string | null;
|
|
58
|
+
forceFreshSession: boolean;
|
|
59
|
+
hasExplicitResume: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Whether a wake is even a candidate for throttling. Wakes that carry new
|
|
63
|
+
* information or an explicit operator escalation always pass.
|
|
64
|
+
*/
|
|
65
|
+
export declare function isThrottleCandidateIssueRewake(input: IssueRewakeCandidateInput): boolean;
|
|
66
|
+
export interface RecentIssueRunSample {
|
|
67
|
+
id: string;
|
|
68
|
+
status: string;
|
|
69
|
+
finishedAt: Date | null;
|
|
70
|
+
}
|
|
71
|
+
export interface IssueRewakeThrottleInput {
|
|
72
|
+
now: Date;
|
|
73
|
+
/** Terminal runs for the same (agent, issue), newest finish first. */
|
|
74
|
+
recentTerminalRuns: RecentIssueRunSample[];
|
|
75
|
+
/** Runs among the sample that produced issue-visible progress. */
|
|
76
|
+
runIdsWithIssueProgress: ReadonlySet<string>;
|
|
77
|
+
/** New issue input landed after the newest run finished. */
|
|
78
|
+
hasNewIssueInputSinceLastRun: boolean;
|
|
79
|
+
}
|
|
80
|
+
export type IssueRewakeThrottleDecision = {
|
|
81
|
+
blocked: false;
|
|
82
|
+
noProgressStreak: number;
|
|
83
|
+
} | {
|
|
84
|
+
blocked: true;
|
|
85
|
+
noProgressStreak: number;
|
|
86
|
+
cooldownMs: number;
|
|
87
|
+
lastRunFinishedAt: Date;
|
|
88
|
+
nextAllowedAt: Date;
|
|
89
|
+
};
|
|
90
|
+
export declare function computeIssueRewakeCooldownMs(noProgressStreak: number): number;
|
|
91
|
+
export declare function evaluateIssueRewakeThrottle(input: IssueRewakeThrottleInput): IssueRewakeThrottleDecision;
|
|
92
|
+
//# sourceMappingURL=issue-rewake-throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-rewake-throttle.d.ts","sourceRoot":"","sources":["../../src/services/issue-rewake-throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,yEAAyE;AACzE,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,mFAAmF;AACnF,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD,+CAA+C;AAC/C,eAAO,MAAM,4BAA4B,QAAc,CAAC;AAExD,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,QAAkB,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,CAAC,MAAM,CAK7D,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,EAuBnD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,EAAE,MAAM,EAMpD,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAMxF;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,IAAI,CAAC;IACV,sEAAsE;IACtE,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;IAC3C,kEAAkE;IAClE,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,4DAA4D;IAC5D,4BAA4B,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAC5C;IACE,OAAO,EAAE,IAAI,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,IAAI,CAAC;IACxB,aAAa,EAAE,IAAI,CAAC;CACrB,CAAC;AAEN,wBAAgB,4BAA4B,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAK7E;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,wBAAwB,GAAG,2BAA2B,CA2BxG"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PAP-13775: throttle no-information issue re-wakes.
|
|
3
|
+
*
|
|
4
|
+
* After a process death (or any stall), external drivers — assignment pollers,
|
|
5
|
+
* stranded-issue reconcilers, on-demand invokes — can re-wake the same agent
|
|
6
|
+
* for the same issue every few seconds for as long as the issue stays
|
|
7
|
+
* `in_progress`. When each of those runs ends without changing any
|
|
8
|
+
* issue-visible state, every wake pays a full adapter session for zero new
|
|
9
|
+
* information (the Phase 4 interruption-recovery smoke paid 25 sessions and
|
|
10
|
+
* 2.4x cost for one recovery this way).
|
|
11
|
+
*
|
|
12
|
+
* This module decides when such a wake should be skipped: once an issue has
|
|
13
|
+
* accumulated a streak of consecutive succeeded-but-no-issue-progress runs by
|
|
14
|
+
* the same agent, further event-free wakes are held back for an escalating
|
|
15
|
+
* cooldown anchored to the last run's finish time. Any genuinely new input —
|
|
16
|
+
* a comment wake, fresh issue activity, an explicit resume, forceFreshSession,
|
|
17
|
+
* or an event-carrying wake reason — bypasses the throttle entirely.
|
|
18
|
+
*
|
|
19
|
+
* Server-side recovery retries (process-loss retries, missing-comment
|
|
20
|
+
* follow-ups) insert their runs directly and never pass through this gate, so
|
|
21
|
+
* crash recovery stays immediate; only repeated no-op re-invocations slow
|
|
22
|
+
* down.
|
|
23
|
+
*/
|
|
24
|
+
/** Consecutive no-progress runs required before the cooldown engages. */
|
|
25
|
+
export const ISSUE_REWAKE_NO_PROGRESS_THRESHOLD = 2;
|
|
26
|
+
/** Cooldown after the threshold streak; doubles per additional no-progress run. */
|
|
27
|
+
export const ISSUE_REWAKE_BASE_COOLDOWN_MS = 120_000;
|
|
28
|
+
/** Upper bound for the escalating cooldown. */
|
|
29
|
+
export const ISSUE_REWAKE_MAX_COOLDOWN_MS = 30 * 60_000;
|
|
30
|
+
/** Only runs newer than this feed the streak; older history is ignored. */
|
|
31
|
+
export const ISSUE_REWAKE_LOOKBACK_MS = 6 * 60 * 60_000;
|
|
32
|
+
/** How many recent terminal runs to sample when computing the streak. */
|
|
33
|
+
export const ISSUE_REWAKE_RUN_SAMPLE_LIMIT = 8;
|
|
34
|
+
/**
|
|
35
|
+
* Wake reasons that assert issue state rather than deliver a new event.
|
|
36
|
+
* These (plus reason-less on-demand invokes) are the only wakes the throttle
|
|
37
|
+
* applies to; every event-shaped reason (comments, mentions, blockers
|
|
38
|
+
* resolved, interactions, approvals, monitors, reviews, …) passes through.
|
|
39
|
+
*/
|
|
40
|
+
export const THROTTLED_ISSUE_REWAKE_REASONS = new Set([
|
|
41
|
+
"issue_assigned",
|
|
42
|
+
"issue_continuation_needed",
|
|
43
|
+
"issue_assignment_recovery",
|
|
44
|
+
"issue_graph_liveness_backstop",
|
|
45
|
+
]);
|
|
46
|
+
/**
|
|
47
|
+
* Activity actions that count as issue-visible progress when attributed to a
|
|
48
|
+
* run. Deliberately narrower than run-liveness "concrete action evidence":
|
|
49
|
+
* tool calls inside the workspace do not move the issue, so they do not reset
|
|
50
|
+
* the streak — a run must leave a comment, mutation, document, work product,
|
|
51
|
+
* interaction, or scheduled continuation behind.
|
|
52
|
+
*/
|
|
53
|
+
export const ISSUE_PROGRESS_ACTIVITY_ACTIONS = [
|
|
54
|
+
"issue.updated",
|
|
55
|
+
"issue.comment_added",
|
|
56
|
+
"issue.created",
|
|
57
|
+
"issue.child_created",
|
|
58
|
+
"issue.assigned",
|
|
59
|
+
"issue.released",
|
|
60
|
+
"issue.blockers_updated",
|
|
61
|
+
"issue.document_upserted",
|
|
62
|
+
"issue.document_updated",
|
|
63
|
+
"issue.document_deleted",
|
|
64
|
+
"issue.document_restored",
|
|
65
|
+
"issue.document_annotation_comment_added",
|
|
66
|
+
"issue.document_annotation_thread_created",
|
|
67
|
+
"issue.document_annotation_thread_resolved",
|
|
68
|
+
"issue.work_product_created",
|
|
69
|
+
"issue.work_product_updated",
|
|
70
|
+
"issue.work_product_deleted",
|
|
71
|
+
"issue.attachment_added",
|
|
72
|
+
"issue.attachment_removed",
|
|
73
|
+
"issue.thread_interaction_created",
|
|
74
|
+
"issue.monitor_scheduled",
|
|
75
|
+
"issue.approval_linked",
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Activity on the issue that counts as new external input since the last run
|
|
79
|
+
* finished — anything a waiting agent should be woken for, including board
|
|
80
|
+
* responses to interactions.
|
|
81
|
+
*/
|
|
82
|
+
export const ISSUE_NEW_INPUT_ACTIVITY_ACTIONS = [
|
|
83
|
+
...ISSUE_PROGRESS_ACTIVITY_ACTIONS,
|
|
84
|
+
"issue.thread_interaction_accepted",
|
|
85
|
+
"issue.thread_interaction_answered",
|
|
86
|
+
"issue.thread_interaction_item_verdicts_submitted",
|
|
87
|
+
"issue.blockers_resolved_wake_emitted",
|
|
88
|
+
];
|
|
89
|
+
/**
|
|
90
|
+
* Whether a wake is even a candidate for throttling. Wakes that carry new
|
|
91
|
+
* information or an explicit operator escalation always pass.
|
|
92
|
+
*/
|
|
93
|
+
export function isThrottleCandidateIssueRewake(input) {
|
|
94
|
+
if (input.forceFreshSession)
|
|
95
|
+
return false;
|
|
96
|
+
if (input.wakeCommentId)
|
|
97
|
+
return false;
|
|
98
|
+
if (input.hasExplicitResume)
|
|
99
|
+
return false;
|
|
100
|
+
if (input.reason === null)
|
|
101
|
+
return true;
|
|
102
|
+
return THROTTLED_ISSUE_REWAKE_REASONS.has(input.reason);
|
|
103
|
+
}
|
|
104
|
+
export function computeIssueRewakeCooldownMs(noProgressStreak) {
|
|
105
|
+
const doublings = Math.max(0, noProgressStreak - ISSUE_REWAKE_NO_PROGRESS_THRESHOLD);
|
|
106
|
+
// Guard the exponent so an absurd streak can't overflow into Infinity.
|
|
107
|
+
const factor = 2 ** Math.min(doublings, 16);
|
|
108
|
+
return Math.min(ISSUE_REWAKE_BASE_COOLDOWN_MS * factor, ISSUE_REWAKE_MAX_COOLDOWN_MS);
|
|
109
|
+
}
|
|
110
|
+
export function evaluateIssueRewakeThrottle(input) {
|
|
111
|
+
const runs = input.recentTerminalRuns;
|
|
112
|
+
if (runs.length === 0)
|
|
113
|
+
return { blocked: false, noProgressStreak: 0 };
|
|
114
|
+
if (input.hasNewIssueInputSinceLastRun)
|
|
115
|
+
return { blocked: false, noProgressStreak: 0 };
|
|
116
|
+
let noProgressStreak = 0;
|
|
117
|
+
for (const run of runs) {
|
|
118
|
+
// A failed/cancelled/interrupted run breaks the streak: its follow-up is
|
|
119
|
+
// recovery, not a redundant re-poll, and must not be delayed.
|
|
120
|
+
if (run.status !== "succeeded" || !run.finishedAt)
|
|
121
|
+
break;
|
|
122
|
+
if (input.runIdsWithIssueProgress.has(run.id))
|
|
123
|
+
break;
|
|
124
|
+
noProgressStreak += 1;
|
|
125
|
+
}
|
|
126
|
+
if (noProgressStreak < ISSUE_REWAKE_NO_PROGRESS_THRESHOLD) {
|
|
127
|
+
return { blocked: false, noProgressStreak };
|
|
128
|
+
}
|
|
129
|
+
const lastRunFinishedAt = runs[0]?.finishedAt;
|
|
130
|
+
if (!lastRunFinishedAt)
|
|
131
|
+
return { blocked: false, noProgressStreak };
|
|
132
|
+
const cooldownMs = computeIssueRewakeCooldownMs(noProgressStreak);
|
|
133
|
+
const nextAllowedAt = new Date(lastRunFinishedAt.getTime() + cooldownMs);
|
|
134
|
+
if (input.now.getTime() < nextAllowedAt.getTime()) {
|
|
135
|
+
return { blocked: true, noProgressStreak, cooldownMs, lastRunFinishedAt, nextAllowedAt };
|
|
136
|
+
}
|
|
137
|
+
return { blocked: false, noProgressStreak };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=issue-rewake-throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issue-rewake-throttle.js","sourceRoot":"","sources":["../../src/services/issue-rewake-throttle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Db } from "@penclipai/db";
|
|
2
2
|
import { issueThreadInteractions } from "@penclipai/db";
|
|
3
|
-
import type { AcceptIssueThreadInteraction, CancelIssueThreadInteraction, CreateIssueThreadInteraction, IssueThreadInteraction, RejectIssueThreadInteraction, RespondIssueThreadInteraction } from "@penclipai/shared";
|
|
3
|
+
import type { AcceptIssueThreadInteraction, CancelIssueThreadInteraction, CreateIssueThreadInteraction, IssueThreadInteraction, RejectIssueThreadInteraction, RespondIssueThreadInteraction, SubmitIssueThreadInteractionVerdicts } from "@penclipai/shared";
|
|
4
4
|
type InteractionActor = {
|
|
5
5
|
agentId?: string | null;
|
|
6
6
|
userId?: string | null;
|
|
@@ -43,6 +43,13 @@ export declare function issueThreadInteractionService(db: Db): {
|
|
|
43
43
|
id: string;
|
|
44
44
|
companyId: string;
|
|
45
45
|
}, interactionId: string, input: RejectIssueThreadInteraction, actor: InteractionActor) => Promise<IssueThreadInteraction>;
|
|
46
|
+
submitItemVerdicts: (issue: {
|
|
47
|
+
id: string;
|
|
48
|
+
companyId: string;
|
|
49
|
+
}, interactionId: string, input: SubmitIssueThreadInteractionVerdicts, actor: InteractionActor) => Promise<{
|
|
50
|
+
interaction: IssueThreadInteraction;
|
|
51
|
+
newlyResolvedItemIds: string[];
|
|
52
|
+
}>;
|
|
46
53
|
rejectSuggestedTasks: (issue: {
|
|
47
54
|
id: string;
|
|
48
55
|
companyId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-thread-interactions.d.ts","sourceRoot":"","sources":["../../src/services/issue-thread-interactions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAML,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EACV,4BAA4B,EAG5B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,
|
|
1
|
+
{"version":3,"file":"issue-thread-interactions.d.ts","sourceRoot":"","sources":["../../src/services/issue-thread-interactions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAML,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EACV,4BAA4B,EAG5B,4BAA4B,EAC5B,4BAA4B,EAC5B,sBAAsB,EAOtB,4BAA4B,EAC5B,6BAA6B,EAG7B,oCAAoC,EACrC,MAAM,mBAAmB,CAAC;AAuB3B,KAAK,gBAAgB,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAKF,KAAK,eAAe,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,WAAW,EAAE,sBAAsB,CAAC;IACpC,aAAa,EAAE,eAAe,EAAE,CAAC;IACjC,iBAAiB,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAC5C,CAAC;AAEF,KAAK,yBAAyB,GAAG,OAAO,uBAAuB,CAAC,YAAY,CAAC;AA6wB7E,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,EAAE;4BA8NlB,MAAM;6BAUL,MAAM;oBAW5B;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,SACjC,4BAA4B,SAC5B,gBAAgB;+BAsGhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,iBAC1E,MAAM,SACd,4BAA4B,SAC5B,gBAAgB,KACtB,OAAO,CAAC,yBAAyB,CAAC;kCA2C5B;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,iBAC1E,MAAM,SACd,4BAA4B,SAC5B,gBAAgB;;;;+BAoJhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,iBACzB,MAAM,SACd,4BAA4B,SAC5B,gBAAgB;gCAqBhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,iBACzB,MAAM,SACd,oCAAoC,SACpC,gBAAgB,KACtB,OAAO,CAAC;QAAE,WAAW,EAAE,sBAAsB,CAAC;QAAC,oBAAoB,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;kCAgG1E;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,iBACzB,MAAM,SACd,4BAA4B,SAC5B,gBAAgB,WACd,yBAAyB;2DA0C3B;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,WAC/B;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,SACxE,gBAAgB;sEAyDhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;6DA4IjC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,YAC9B;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,SAC7G,gBAAgB;6BAsEhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,iBACzB,MAAM,SACd,6BAA6B,SAC7B,gBAAgB;6BAwDhB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,iBACzB,MAAM,SACd,4BAA4B,SAC5B,gBAAgB;EAqD5B"}
|
|
@@ -2,7 +2,7 @@ import { isDeepStrictEqual } from "node:util";
|
|
|
2
2
|
import { and, asc, eq, inArray, isNotNull } from "drizzle-orm";
|
|
3
3
|
import { agents, documents, heartbeatRuns, issueComments, issueDocuments, issueThreadInteractions, issues, } from "@penclipai/db";
|
|
4
4
|
import { trackInteractionResolved } from "@penclipai/shared/telemetry";
|
|
5
|
-
import { acceptIssueThreadInteractionSchema, askUserQuestionsPayloadSchema, askUserQuestionsResultSchema, cancelIssueThreadInteractionSchema, createIssueThreadInteractionSchema, rejectIssueThreadInteractionSchema, requestCheckboxConfirmationPayloadSchema, requestCheckboxConfirmationResultSchema, requestConfirmationPayloadSchema, requestConfirmationResultSchema, suggestTasksPayloadSchema, suggestTasksResultSchema, } from "@penclipai/shared";
|
|
5
|
+
import { acceptIssueThreadInteractionSchema, askUserQuestionsPayloadSchema, askUserQuestionsResultSchema, cancelIssueThreadInteractionSchema, createIssueThreadInteractionSchema, rejectIssueThreadInteractionSchema, requestCheckboxConfirmationPayloadSchema, requestCheckboxConfirmationResultSchema, requestConfirmationPayloadSchema, requestConfirmationResultSchema, requestItemVerdictsPayloadSchema, requestItemVerdictsResultSchema, suggestTasksPayloadSchema, suggestTasksResultSchema, submitIssueThreadInteractionVerdictsSchema, } from "@penclipai/shared";
|
|
6
6
|
import { conflict, notFound, unprocessable } from "../errors.js";
|
|
7
7
|
import { isUniqueViolation } from "./db-errors.js";
|
|
8
8
|
import { getTelemetryClient } from "../telemetry.js";
|
|
@@ -12,13 +12,20 @@ const REQUEST_CONFIRMATION_INTERACTION_KINDS = [
|
|
|
12
12
|
"request_confirmation",
|
|
13
13
|
"request_checkbox_confirmation",
|
|
14
14
|
];
|
|
15
|
-
const
|
|
15
|
+
const TARGET_BOUND_INTERACTION_KINDS = [
|
|
16
16
|
...REQUEST_CONFIRMATION_INTERACTION_KINDS,
|
|
17
|
+
"request_item_verdicts",
|
|
18
|
+
];
|
|
19
|
+
const USER_COMMENT_SUPERSEDABLE_INTERACTION_KINDS = [
|
|
20
|
+
...TARGET_BOUND_INTERACTION_KINDS,
|
|
17
21
|
"ask_user_questions",
|
|
18
22
|
];
|
|
19
23
|
function isRequestConfirmationLikeKind(kind) {
|
|
20
24
|
return REQUEST_CONFIRMATION_INTERACTION_KINDS.includes(kind);
|
|
21
25
|
}
|
|
26
|
+
function isTargetBoundInteractionKind(kind) {
|
|
27
|
+
return TARGET_BOUND_INTERACTION_KINDS.includes(kind);
|
|
28
|
+
}
|
|
22
29
|
function isUserCommentSupersedableKind(kind) {
|
|
23
30
|
return USER_COMMENT_SUPERSEDABLE_INTERACTION_KINDS.includes(kind);
|
|
24
31
|
}
|
|
@@ -73,6 +80,13 @@ function hydrateInteraction(row) {
|
|
|
73
80
|
payload: requestCheckboxConfirmationPayloadSchema.parse(row.payload),
|
|
74
81
|
result: row.result ? requestCheckboxConfirmationResultSchema.parse(row.result) : null,
|
|
75
82
|
};
|
|
83
|
+
case "request_item_verdicts":
|
|
84
|
+
return {
|
|
85
|
+
...base,
|
|
86
|
+
kind: "request_item_verdicts",
|
|
87
|
+
payload: requestItemVerdictsPayloadSchema.parse(row.payload),
|
|
88
|
+
result: row.result ? requestItemVerdictsResultSchema.parse(row.result) : null,
|
|
89
|
+
};
|
|
76
90
|
default:
|
|
77
91
|
throw unprocessable(`Unknown interaction kind: ${row.kind}`);
|
|
78
92
|
}
|
|
@@ -130,6 +144,14 @@ function normalizeCreateInteractionInput(input) {
|
|
|
130
144
|
supersedeOnUserComment: input.payload.supersedeOnUserComment ?? true,
|
|
131
145
|
},
|
|
132
146
|
};
|
|
147
|
+
case "request_item_verdicts":
|
|
148
|
+
return {
|
|
149
|
+
...input,
|
|
150
|
+
payload: {
|
|
151
|
+
...input.payload,
|
|
152
|
+
supersedeOnUserComment: input.payload.supersedeOnUserComment ?? true,
|
|
153
|
+
},
|
|
154
|
+
};
|
|
133
155
|
default:
|
|
134
156
|
return input;
|
|
135
157
|
}
|
|
@@ -144,12 +166,39 @@ function buildSupersededByCommentResult(row, commentId) {
|
|
|
144
166
|
summaryMarkdown: null,
|
|
145
167
|
};
|
|
146
168
|
}
|
|
169
|
+
if (row.kind === "request_item_verdicts") {
|
|
170
|
+
const interaction = hydrateInteraction(row);
|
|
171
|
+
return {
|
|
172
|
+
version: 1,
|
|
173
|
+
outcome: "superseded_by_comment",
|
|
174
|
+
complete: false,
|
|
175
|
+
items: interaction.result?.items ?? [],
|
|
176
|
+
commentId,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
147
179
|
return {
|
|
148
180
|
version: 1,
|
|
149
181
|
outcome: "superseded_by_comment",
|
|
150
182
|
commentId,
|
|
151
183
|
};
|
|
152
184
|
}
|
|
185
|
+
function buildStaleTargetResult(row, staleTarget) {
|
|
186
|
+
if (row.kind === "request_item_verdicts") {
|
|
187
|
+
const interaction = hydrateInteraction(row);
|
|
188
|
+
return {
|
|
189
|
+
version: 1,
|
|
190
|
+
outcome: "stale_target",
|
|
191
|
+
complete: false,
|
|
192
|
+
items: interaction.result?.items ?? [],
|
|
193
|
+
staleTarget,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
version: 1,
|
|
198
|
+
outcome: "stale_target",
|
|
199
|
+
staleTarget,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
153
202
|
function resolveActorKind(interaction) {
|
|
154
203
|
if (interaction.resolvedByAgentId)
|
|
155
204
|
return "agent";
|
|
@@ -165,10 +214,14 @@ function resolveCreatorKind(interaction) {
|
|
|
165
214
|
return undefined;
|
|
166
215
|
}
|
|
167
216
|
function deriveTargetType(interaction) {
|
|
168
|
-
|
|
169
|
-
|
|
217
|
+
switch (interaction.kind) {
|
|
218
|
+
case "request_confirmation":
|
|
219
|
+
case "request_checkbox_confirmation":
|
|
220
|
+
case "request_item_verdicts":
|
|
221
|
+
return interaction.payload.target?.type ?? "none";
|
|
222
|
+
default:
|
|
223
|
+
return "none";
|
|
170
224
|
}
|
|
171
|
-
return interaction.payload.target?.type ?? "none";
|
|
172
225
|
}
|
|
173
226
|
function deriveResolutionReason(interaction) {
|
|
174
227
|
switch (interaction.status) {
|
|
@@ -185,8 +238,17 @@ function deriveResolutionReason(interaction) {
|
|
|
185
238
|
if (interaction.kind === "request_confirmation" || interaction.kind === "request_checkbox_confirmation") {
|
|
186
239
|
return interaction.result?.outcome ?? "expired";
|
|
187
240
|
}
|
|
241
|
+
if (interaction.kind === "request_item_verdicts") {
|
|
242
|
+
return interaction.result?.outcome ?? "expired";
|
|
243
|
+
}
|
|
188
244
|
return "expired";
|
|
189
245
|
}
|
|
246
|
+
case "answered": {
|
|
247
|
+
if (interaction.kind === "request_item_verdicts") {
|
|
248
|
+
return interaction.result?.outcome ?? "answered";
|
|
249
|
+
}
|
|
250
|
+
return "answered";
|
|
251
|
+
}
|
|
190
252
|
default:
|
|
191
253
|
return undefined;
|
|
192
254
|
}
|
|
@@ -213,6 +275,11 @@ function buildInteractionResolvedCounts(interaction, args) {
|
|
|
213
275
|
questionCount: nonNegativeInteger(interaction.payload.questions.length),
|
|
214
276
|
answeredQuestionCount: nonNegativeInteger(interaction.result?.answers?.length ?? 0),
|
|
215
277
|
};
|
|
278
|
+
case "request_item_verdicts":
|
|
279
|
+
return {
|
|
280
|
+
itemCount: nonNegativeInteger(interaction.payload.items.length),
|
|
281
|
+
resolvedItemCount: nonNegativeInteger(interaction.result?.items?.length ?? 0),
|
|
282
|
+
};
|
|
216
283
|
default:
|
|
217
284
|
return {};
|
|
218
285
|
}
|
|
@@ -366,6 +433,56 @@ function resolveSelectedCheckboxConfirmationOptions(args) {
|
|
|
366
433
|
.filter((option) => selectedOptionIdSet.has(option.id))
|
|
367
434
|
.map((option) => option.id);
|
|
368
435
|
}
|
|
436
|
+
function resolveRequestItemVerdictSubmissions(args) {
|
|
437
|
+
if (!args.actor.userId) {
|
|
438
|
+
throw unprocessable("request_item_verdicts submissions require a user actor");
|
|
439
|
+
}
|
|
440
|
+
const existingItems = args.interaction.result?.items ?? [];
|
|
441
|
+
const existingById = new Map(existingItems.map((item) => [item.id, item]));
|
|
442
|
+
const payloadItemIds = new Set(args.interaction.payload.items.map((item) => item.id));
|
|
443
|
+
const enabledVerdicts = new Set(args.interaction.payload.verdicts ?? ["approve", "reject"]);
|
|
444
|
+
const requireReasonOn = new Set(args.interaction.payload.requireReasonOn ?? ["reject"]);
|
|
445
|
+
const newlyResolvedById = new Map();
|
|
446
|
+
const newlyResolvedItemIds = [];
|
|
447
|
+
for (const submitted of args.input.verdicts) {
|
|
448
|
+
if (!payloadItemIds.has(submitted.id)) {
|
|
449
|
+
throw unprocessable(`Unknown item verdict id: ${submitted.id}`);
|
|
450
|
+
}
|
|
451
|
+
if (existingById.has(submitted.id)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
if (!enabledVerdicts.has(submitted.verdict)) {
|
|
455
|
+
throw unprocessable(`Verdict ${submitted.verdict} is not enabled for this item verdict request`);
|
|
456
|
+
}
|
|
457
|
+
const reason = submitted.reason?.trim() ?? "";
|
|
458
|
+
if (requireReasonOn.has(submitted.verdict) && reason.length === 0) {
|
|
459
|
+
throw unprocessable(`A reason is required when verdict is ${submitted.verdict}`);
|
|
460
|
+
}
|
|
461
|
+
if (newlyResolvedById.has(submitted.id)) {
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
newlyResolvedById.set(submitted.id, {
|
|
465
|
+
id: submitted.id,
|
|
466
|
+
verdict: submitted.verdict,
|
|
467
|
+
...(reason ? { reason } : {}),
|
|
468
|
+
resolvedByUserId: args.actor.userId,
|
|
469
|
+
resolvedAt: args.now,
|
|
470
|
+
});
|
|
471
|
+
newlyResolvedItemIds.push(submitted.id);
|
|
472
|
+
}
|
|
473
|
+
const nextById = new Map(existingItems.map((item) => [item.id, item]));
|
|
474
|
+
for (const [id, item] of newlyResolvedById) {
|
|
475
|
+
nextById.set(id, item);
|
|
476
|
+
}
|
|
477
|
+
const items = args.interaction.payload.items
|
|
478
|
+
.map((item) => nextById.get(item.id))
|
|
479
|
+
.filter((item) => Boolean(item));
|
|
480
|
+
return {
|
|
481
|
+
items,
|
|
482
|
+
complete: items.length === args.interaction.payload.items.length,
|
|
483
|
+
newlyResolvedItemIds,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
369
486
|
function normalizeQuestionAnswers(args) {
|
|
370
487
|
const questionById = new Map(args.questions.map((question) => [question.id, question]));
|
|
371
488
|
const answerByQuestionId = new Map();
|
|
@@ -469,7 +586,7 @@ async function assertRequestConfirmationTargetIsCurrent(db, args) {
|
|
|
469
586
|
}
|
|
470
587
|
}
|
|
471
588
|
async function expireStaleRequestConfirmationTarget(db, args) {
|
|
472
|
-
if (!
|
|
589
|
+
if (!isTargetBoundInteractionKind(args.row.kind) || args.row.status !== "pending")
|
|
473
590
|
return null;
|
|
474
591
|
const interaction = hydrateInteraction(args.row);
|
|
475
592
|
const target = interaction.payload.target ?? null;
|
|
@@ -503,9 +620,7 @@ async function expireStaleRequestConfirmationTarget(db, args) {
|
|
|
503
620
|
}
|
|
504
621
|
: interaction.payload,
|
|
505
622
|
result: {
|
|
506
|
-
|
|
507
|
-
outcome: "stale_target",
|
|
508
|
-
staleTarget: target,
|
|
623
|
+
...buildStaleTargetResult(args.row, target),
|
|
509
624
|
},
|
|
510
625
|
resolvedByAgentId: args.actor.agentId ?? null,
|
|
511
626
|
resolvedByUserId: args.actor.userId ?? null,
|
|
@@ -743,7 +858,9 @@ export function issueThreadInteractionService(db) {
|
|
|
743
858
|
throw unprocessable("sourceRunId must belong to the same company");
|
|
744
859
|
}
|
|
745
860
|
}
|
|
746
|
-
if (data.kind === "request_confirmation"
|
|
861
|
+
if (data.kind === "request_confirmation"
|
|
862
|
+
|| data.kind === "request_checkbox_confirmation"
|
|
863
|
+
|| data.kind === "request_item_verdicts") {
|
|
747
864
|
await assertRequestConfirmationTargetIsCurrent(db, {
|
|
748
865
|
companyId: issue.companyId,
|
|
749
866
|
issueId: issue.id,
|
|
@@ -982,6 +1099,90 @@ export function issueThreadInteractionService(db) {
|
|
|
982
1099
|
throw unprocessable(`Interactions of kind ${current.kind} cannot be rejected`);
|
|
983
1100
|
}
|
|
984
1101
|
},
|
|
1102
|
+
submitItemVerdicts: async (issue, interactionId, input, actor) => {
|
|
1103
|
+
const data = submitIssueThreadInteractionVerdictsSchema.parse(input);
|
|
1104
|
+
const submission = await db.transaction(async (tx) => {
|
|
1105
|
+
const current = await tx
|
|
1106
|
+
.select()
|
|
1107
|
+
.from(issueThreadInteractions)
|
|
1108
|
+
.where(eq(issueThreadInteractions.id, interactionId))
|
|
1109
|
+
.for("update")
|
|
1110
|
+
.then((rows) => rows[0] ?? null);
|
|
1111
|
+
if (!current)
|
|
1112
|
+
throw notFound("Interaction not found");
|
|
1113
|
+
if (current.companyId !== issue.companyId || current.issueId !== issue.id) {
|
|
1114
|
+
throw notFound("Interaction not found");
|
|
1115
|
+
}
|
|
1116
|
+
if (current.kind !== "request_item_verdicts") {
|
|
1117
|
+
throw unprocessable("Only request_item_verdicts interactions can receive item verdicts");
|
|
1118
|
+
}
|
|
1119
|
+
const interaction = hydrateInteraction(current);
|
|
1120
|
+
if (current.status !== "pending") {
|
|
1121
|
+
if (current.status === "answered") {
|
|
1122
|
+
const resolvedIds = new Set(interaction.result?.items.map((item) => item.id) ?? []);
|
|
1123
|
+
const payloadIds = new Set(interaction.payload.items.map((item) => item.id));
|
|
1124
|
+
for (const submitted of data.verdicts) {
|
|
1125
|
+
if (!payloadIds.has(submitted.id)) {
|
|
1126
|
+
throw unprocessable(`Unknown item verdict id: ${submitted.id}`);
|
|
1127
|
+
}
|
|
1128
|
+
if (!resolvedIds.has(submitted.id)) {
|
|
1129
|
+
throw conflict("Interaction has already been resolved");
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
return { interaction, newlyResolvedItemIds: [], resolved: false };
|
|
1133
|
+
}
|
|
1134
|
+
throw conflict("Interaction has already been resolved");
|
|
1135
|
+
}
|
|
1136
|
+
const expired = await expireStaleRequestConfirmationTarget(tx, {
|
|
1137
|
+
row: current,
|
|
1138
|
+
actor,
|
|
1139
|
+
});
|
|
1140
|
+
if (expired) {
|
|
1141
|
+
return { interaction: expired, newlyResolvedItemIds: [], resolved: false };
|
|
1142
|
+
}
|
|
1143
|
+
const now = new Date();
|
|
1144
|
+
const { items, complete, newlyResolvedItemIds } = resolveRequestItemVerdictSubmissions({
|
|
1145
|
+
interaction,
|
|
1146
|
+
input: data,
|
|
1147
|
+
actor,
|
|
1148
|
+
now,
|
|
1149
|
+
});
|
|
1150
|
+
if (newlyResolvedItemIds.length === 0) {
|
|
1151
|
+
return { interaction, newlyResolvedItemIds: [], resolved: false };
|
|
1152
|
+
}
|
|
1153
|
+
const result = {
|
|
1154
|
+
version: 1,
|
|
1155
|
+
outcome: "resolved",
|
|
1156
|
+
complete,
|
|
1157
|
+
items,
|
|
1158
|
+
};
|
|
1159
|
+
const [updated] = await tx
|
|
1160
|
+
.update(issueThreadInteractions)
|
|
1161
|
+
.set({
|
|
1162
|
+
status: complete ? "answered" : "pending",
|
|
1163
|
+
result,
|
|
1164
|
+
resolvedByAgentId: complete ? actor.agentId ?? null : null,
|
|
1165
|
+
resolvedByUserId: complete ? actor.userId ?? null : null,
|
|
1166
|
+
resolvedAt: complete ? now : null,
|
|
1167
|
+
updatedAt: now,
|
|
1168
|
+
})
|
|
1169
|
+
.where(and(eq(issueThreadInteractions.id, interactionId), eq(issueThreadInteractions.status, "pending")))
|
|
1170
|
+
.returning();
|
|
1171
|
+
if (!updated) {
|
|
1172
|
+
throw conflict("Interaction has already been resolved");
|
|
1173
|
+
}
|
|
1174
|
+
await touchIssue(tx, issue.id);
|
|
1175
|
+
return {
|
|
1176
|
+
interaction: hydrateInteraction(updated),
|
|
1177
|
+
newlyResolvedItemIds,
|
|
1178
|
+
resolved: complete,
|
|
1179
|
+
};
|
|
1180
|
+
});
|
|
1181
|
+
if (submission.resolved) {
|
|
1182
|
+
await emitInteractionResolvedTelemetry(db, submission.interaction);
|
|
1183
|
+
}
|
|
1184
|
+
return submission;
|
|
1185
|
+
},
|
|
985
1186
|
rejectSuggestedTasks: async (issue, interactionId, input, actor, current) => {
|
|
986
1187
|
if (current.companyId !== issue.companyId || current.issueId !== issue.id) {
|
|
987
1188
|
throw notFound("Interaction not found");
|
|
@@ -1109,6 +1310,8 @@ export function issueThreadInteractionService(db) {
|
|
|
1109
1310
|
const confirmationRowIds = commentRows
|
|
1110
1311
|
.filter((row) => isRequestConfirmationLikeKind(row.kind))
|
|
1111
1312
|
.map((row) => row.id);
|
|
1313
|
+
const itemVerdictRows = commentRows
|
|
1314
|
+
.filter((row) => row.kind === "request_item_verdicts");
|
|
1112
1315
|
if (questionRowIds.length > 0) {
|
|
1113
1316
|
const sampleQuestionRow = commentRows.find((row) => row.kind === "ask_user_questions");
|
|
1114
1317
|
if (!sampleQuestionRow)
|
|
@@ -1145,6 +1348,22 @@ export function issueThreadInteractionService(db) {
|
|
|
1145
1348
|
.returning();
|
|
1146
1349
|
expired.push(...updatedRows.map(hydrateInteraction));
|
|
1147
1350
|
}
|
|
1351
|
+
for (const row of itemVerdictRows) {
|
|
1352
|
+
const [updated] = await db
|
|
1353
|
+
.update(issueThreadInteractions)
|
|
1354
|
+
.set({
|
|
1355
|
+
status: "expired",
|
|
1356
|
+
result: buildSupersededByCommentResult(row, comment.id),
|
|
1357
|
+
resolvedByAgentId: null,
|
|
1358
|
+
resolvedByUserId: comment.authorUserId,
|
|
1359
|
+
resolvedAt: now,
|
|
1360
|
+
updatedAt: now,
|
|
1361
|
+
})
|
|
1362
|
+
.where(and(eq(issueThreadInteractions.id, row.id), eq(issueThreadInteractions.status, "pending")))
|
|
1363
|
+
.returning();
|
|
1364
|
+
if (updated)
|
|
1365
|
+
expired.push(hydrateInteraction(updated));
|
|
1366
|
+
}
|
|
1148
1367
|
}
|
|
1149
1368
|
if (expired.length > 0) {
|
|
1150
1369
|
await touchIssue(db, issue.id);
|
|
@@ -1156,7 +1375,7 @@ export function issueThreadInteractionService(db) {
|
|
|
1156
1375
|
const rows = await db
|
|
1157
1376
|
.select()
|
|
1158
1377
|
.from(issueThreadInteractions)
|
|
1159
|
-
.where(and(eq(issueThreadInteractions.companyId, issue.companyId), eq(issueThreadInteractions.issueId, issue.id), inArray(issueThreadInteractions.kind, [...
|
|
1378
|
+
.where(and(eq(issueThreadInteractions.companyId, issue.companyId), eq(issueThreadInteractions.issueId, issue.id), inArray(issueThreadInteractions.kind, [...TARGET_BOUND_INTERACTION_KINDS]), eq(issueThreadInteractions.status, "pending")));
|
|
1160
1379
|
const staleRows = rows.filter((row) => {
|
|
1161
1380
|
const interaction = hydrateInteraction(row);
|
|
1162
1381
|
const target = interaction.payload.target;
|
|
@@ -1195,11 +1414,7 @@ export function issueThreadInteractionService(db) {
|
|
|
1195
1414
|
target: currentTarget,
|
|
1196
1415
|
}
|
|
1197
1416
|
: interaction.payload,
|
|
1198
|
-
result:
|
|
1199
|
-
version: 1,
|
|
1200
|
-
outcome: "stale_target",
|
|
1201
|
-
staleTarget: target,
|
|
1202
|
-
},
|
|
1417
|
+
result: buildStaleTargetResult(row, target),
|
|
1203
1418
|
resolvedByAgentId: actor.agentId ?? null,
|
|
1204
1419
|
resolvedByUserId: actor.userId ?? null,
|
|
1205
1420
|
resolvedAt: now,
|