@penclipai/server 2026.704.0 → 2026.714.0-canary.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-Cy91Tlk9.js} +1 -1
- package/ui-dist/assets/{arc-HZhAwbOs.js → arc-BBAQu311.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-BteMjuOn.js → architectureDiagram-ZJ3FMSHR-BrTSDi88.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-Iq66uZjf.js → blockDiagram-677ZJIJ3-e5uziFO5.js} +1 -1
- package/ui-dist/assets/{browser-ponyfill-BBsuyZJt.js → browser-ponyfill-D8l5pq-s.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-_nlglj7I.js → c4Diagram-LMCZKHZV-DQjqZvNw.js} +1 -1
- package/ui-dist/assets/channel-FQ5LRr4r.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-Cvz7WwSQ.js → chunk-2Q5K7J3B-ff7RVJIE.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-LLubniCS.js → chunk-32BRIVSS-DUJjWWOm.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-BOst5hcr.js → chunk-5VM5RSS4-0Yi4VBgb.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-D5WNShVm.js → chunk-EX3LRPZG-NKvQ4wVr.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-CA07x4av.js → chunk-JWPE2WC7-C9fJ6g-i.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-Clfi83rK.js → chunk-MOJQB5TN-DEFFsbL_.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-BhZ6p7YJ.js → chunk-RYQCIY6F-B3v41_7G.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-CdexJGoV.js → chunk-V7JOEXUC-DVUU3xAk.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-8vjmBhr1.js → chunk-VR4S4FIN-bemyw0k2.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY-CqmCaplj.js → chunk-XXDRQBXY-CWvhgyeb.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-QaL1os8Q.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-QaL1os8Q.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-CY-zAygY.js → cose-bilkent-JH36ORCC-E-2cLOc1.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-BQSQ1HKr.js → cynefin-VYW2F7L2-CxotRukv.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-NJCuFrZL.js → cynefinDiagram-TSTJHNR4-AGQOPMl5.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-DAUPIc8g.js → dagre-VKFMJZFB-BxLGfVbk.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-DvMwJlCi.js → diagram-FQU43EPY-DWXO_O6m.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-DPY0Jz_y.js → diagram-G47NLZAW-C3WsiNNv.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-BpopeEhp.js → diagram-NH7WQ7WH-CbLSRXTf.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-Qpu05z9X.js → diagram-OA4YK3LP-hwvxJr04.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-DHnvw9XU.js → diagram-WEI45ONY-xwXsnT5Q.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-D61S54_7.js → ebnfDiagram-CCIWWBDH-G311pLCP.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-pplAN_x2.js → erDiagram-Q63AITRT-BnnuR_2P.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-BaBcbyDq.js → flowDiagram-23GEKE2U-CSHgefz-.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-BOJSII2b.js → ganttDiagram-NO4QXBWP-CERr9vTh.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-aYAaO4a2.js → gitGraphDiagram-IHSO6WYX-DHFHVLdn.js} +1 -1
- package/ui-dist/assets/{index-TmpY6Xh_.js → index-B-quLPan.js} +1 -1
- package/ui-dist/assets/{index-LHkZdu0h.js → index-B6QznFjN.js} +1 -1
- package/ui-dist/assets/{index-3EKATXgc.js → index-B7BUwUuV.js} +1 -1
- package/ui-dist/assets/{index-CvPPuNs1.js → index-BDiZss3L.js} +1 -1
- package/ui-dist/assets/{index-BaiskB3o.js → index-BHdxZ8mW.js} +1 -1
- package/ui-dist/assets/{index-CZxYajxF.js → index-BP3GWFFq.js} +1 -1
- package/ui-dist/assets/{index-B5YenxAQ.js → index-BPjK1nba.js} +1 -1
- package/ui-dist/assets/{index-BKVeJ3Jh.js → index-BUGIBR28.js} +1 -1
- package/ui-dist/assets/{index-BRgdHUNR.js → index-BVe5Mpsj.js} +1 -1
- package/ui-dist/assets/{index-Dceamza_.js → index-B_vsK1nr.js} +1 -1
- package/ui-dist/assets/{index-DrL6pHSJ.js → index-BbtsvYoS.js} +1 -1
- package/ui-dist/assets/{index-CemenVOf.js → index-CCptD5rH.js} +1 -1
- package/ui-dist/assets/{index-C-nKjFZh.js → index-CPd0SXS5.js} +1 -1
- package/ui-dist/assets/index-C_R8L9b5.js +676 -0
- package/ui-dist/assets/{index-B8H0SHw1.js → index-CuR0ldHA.js} +1 -1
- package/ui-dist/assets/{index-CKKytnOd.js → index-CvKZQ7p2.js} +1 -1
- package/ui-dist/assets/index-CyuYtn7U.css +1 -0
- package/ui-dist/assets/{index-D3ODiUup.js → index-DSwKPLnt.js} +1 -1
- package/ui-dist/assets/{index-CJlw4l9L.js → index-Daq0pXqe.js} +1 -1
- package/ui-dist/assets/{index-bUFCSEgv.js → index-DmsO--MD.js} +1 -1
- package/ui-dist/assets/{index-Da2kqT1M.js → index-DozP52ue.js} +1 -1
- package/ui-dist/assets/{index-C2JgdjPa.js → index-DxjbpC1V.js} +1 -1
- package/ui-dist/assets/{index-By0oeEvz.js → index-H1y6lR4h.js} +1 -1
- package/ui-dist/assets/{index-BT8b79Bd.js → index-ICaKahDe.js} +1 -1
- package/ui-dist/assets/{index-CjDqB1SX.js → index-q2ZXRiiu.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-C7_90qGq.js → infoDiagram-FWYZ7A6U-BX-kzcCv.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-T-nPPdTt.js → ishikawaDiagram-FXEZZL3T-CRO2OGCv.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-C3hqQN0R.js → journeyDiagram-5HDEW3XC-Di6QSKTh.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-CPoD9DUm.js → kanban-definition-HUTT4EX6-D9TB3XsU.js} +1 -1
- package/ui-dist/assets/{linear-D-S8yr3Z.js → linear-DNuyBs03.js} +1 -1
- package/ui-dist/assets/{mermaid.core-DhvH8shK.js → mermaid.core-CRXbfGc8.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-CxCIKrKo.js → mindmap-definition-LN4V7U3C-BVxJgBfB.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-D4G-PC6N.js → pegDiagram-2B236MQR-BuMRgd7M.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-N4X8UvqY.js → pieDiagram-ENE6RG2P-DFT7WuwK.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-CZohoDln.js → quadrantDiagram-ABIIQ3AL-HOLkwSzD.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-fMGQVhwF.js → railroadDiagram-RFXS5EU6-BND-mOri.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-CK0IuUmk.js → requirementDiagram-TGXJPOKE-BOa8A9lE.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-pSfb3CqG.js → sankeyDiagram-HTMAVEWB-B7cM3qvd.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-CbhkqIeq.js → sequenceDiagram-DBY2YBRQ-ClQvkzoo.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-B6vqqPx-.js → sizeCapture-X5ZJPWSS-D4r_s7na.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-DIJf9h5C.js → stateDiagram-2N3HPSRC-Cx0UQpxD.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-C8L1NW8Q.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-DIX_LV8O.js → swimlanes-5IMT3BWC-cGIUWMIm.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Dj9aJ1a_.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-CD-Pxb_g.js → timeline-definition-FHXFAJF6-BUHQ5Auj.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-BAZsWL0R.js → vennDiagram-L72KCM5P-TvbS6VWx.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-CnNyfwX5.js → wardleyDiagram-EHGQE667-VkQDXzb8.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-j9YgsD3Y.js → xychartDiagram-FW5EYKEG-ButPn9aQ.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 +1002 -2
- package/ui-dist/locales/zh-CN/common.json +1003 -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
package/dist/routes/agents.js
CHANGED
|
@@ -3,12 +3,12 @@ import { generateKeyPairSync, randomUUID } from "node:crypto";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { agents as agentsTable, companies, heartbeatRuns, issues as issuesTable, projects as projectsTable } from "@penclipai/db";
|
|
5
5
|
import { and, desc, eq, inArray, not, sql } from "drizzle-orm";
|
|
6
|
-
import { agentSkillSyncSchema, agentMineInboxQuerySchema, AGENT_DEFAULT_MAX_CONCURRENT_RUNS, createAgentKeySchema, createAgentHireSchema, createAgentSchema, deriveAgentUrlKey, isUuidLike, normalizeIssueIdentifier, resetAgentSessionSchema, testAdapterEnvironmentSchema, upsertAgentInstructionsFileSchema, updateAgentInstructionsBundleSchema, updateAgentPermissionsSchema, updateAgentInstructionsPathSchema, wakeAgentSchema, updateAgentSchema, supportedEnvironmentDriversForAdapter, LOW_TRUST_REVIEW_PRESET, } from "@penclipai/shared";
|
|
6
|
+
import { agentSkillSyncSchema, agentMineInboxQuerySchema, ADAPTER_AGNOSTIC_KEYS, AGENT_DEFAULT_MAX_CONCURRENT_RUNS, createAgentKeySchema, createAgentHireSchema, createAgentSchema, deriveAgentUrlKey, isUuidLike, normalizeIssueIdentifier, resetAgentSessionSchema, testAdapterEnvironmentSchema, upsertAgentInstructionsFileSchema, updateAgentInstructionsBundleSchema, updateAgentPermissionsSchema, updateAgentInstructionsPathSchema, wakeAgentSchema, updateAgentSchema, supportedEnvironmentDriversForAdapter, LOW_TRUST_REVIEW_PRESET, } from "@penclipai/shared";
|
|
7
7
|
import { resolvePaperclipInstanceRootForAdapter, readPaperclipSkillSyncPreference, writePaperclipSkillSyncPreference, } from "@penclipai/adapter-utils/server-utils";
|
|
8
8
|
import { trackAgentCreated } from "@penclipai/shared/telemetry";
|
|
9
9
|
import { validate } from "../middleware/validate.js";
|
|
10
|
-
import { agentService, agentInstructionsService, accessService, approvalService, companySkillService, budgetService, heartbeatService, ISSUE_LIST_DEFAULT_LIMIT, issueApprovalService, issueRecoveryActionService, issueService, logActivity, syncInstructionsBundleConfigFromFilePath, workspaceOperationService, } from "../services/index.js";
|
|
11
|
-
import { conflict, forbidden, notFound, unprocessable } from "../errors.js";
|
|
10
|
+
import { agentService, agentInstructionsService, accessService, approvalService, builtInAgentService, companySkillService, budgetService, heartbeatService, ISSUE_LIST_DEFAULT_LIMIT, issueApprovalService, issueRecoveryActionService, issueService, logActivity, syncInstructionsBundleConfigFromFilePath, workspaceOperationService, } from "../services/index.js";
|
|
11
|
+
import { conflict, forbidden, HttpError, notFound, unprocessable } from "../errors.js";
|
|
12
12
|
import { assertBoard, assertCompanyAccess, assertInstanceAdmin, getActorInfo } from "./authz.js";
|
|
13
13
|
import { assertNoAgentHostWorkspaceCommandMutation, collectAgentAdapterWorkspaceCommandPaths, } from "./workspace-command-authz.js";
|
|
14
14
|
import { environmentService } from "../services/environments.js";
|
|
@@ -16,15 +16,15 @@ import { resolveEnvironmentExecutionTarget } from "../services/environment-execu
|
|
|
16
16
|
import { environmentRuntimeService } from "../services/environment-runtime.js";
|
|
17
17
|
import { skillVersionSelectionMap } from "../services/runtime-skill-selections.js";
|
|
18
18
|
import { secretService } from "../services/secrets.js";
|
|
19
|
+
import { authorizationDeniedDetails } from "../services/authorization.js";
|
|
19
20
|
import { detectAdapterModel, findActiveServerAdapter, findServerAdapter, listAdapterModels, listAdapterModelProfiles, refreshAdapterModels, requireServerAdapter, } from "../adapters/index.js";
|
|
20
21
|
import { redactEventPayload } from "../redaction.js";
|
|
21
22
|
import { redactCurrentUserValue } from "../log-redaction.js";
|
|
22
23
|
import { resolveExplicitRequestUiLocale } from "../ui-locale.js";
|
|
23
24
|
import { getBundledPaperclipSkillIdentity } from "../services/bundled-paperclip-skills.js";
|
|
24
25
|
import { renderOrgChartSvg, renderOrgChartPng, ORG_CHART_STYLES } from "./org-chart-svg.js";
|
|
25
|
-
import { instanceSettingsService } from "../services/instance-settings.js";
|
|
26
|
+
import { instanceSettingsService, isTruthyRuntimeEnvValue, resolveWorktreeRunExecutionActivationState, } from "../services/instance-settings.js";
|
|
26
27
|
import { runClaudeLogin } from "@penclipai/adapter-claude-local/server";
|
|
27
|
-
import { DEFAULT_ACPX_LOCAL_AGENT, DEFAULT_ACPX_LOCAL_MODE, DEFAULT_ACPX_LOCAL_NON_INTERACTIVE_PERMISSIONS, DEFAULT_ACPX_LOCAL_PERMISSION_MODE, } from "@penclipai/adapter-acpx-local";
|
|
28
28
|
import { DEFAULT_CODEX_LOCAL_BYPASS_APPROVALS_AND_SANDBOX } from "@penclipai/adapter-codex-local";
|
|
29
29
|
import { DEFAULT_CURSOR_LOCAL_MODEL } from "@penclipai/adapter-cursor-local";
|
|
30
30
|
import { DEFAULT_GEMINI_LOCAL_MODEL } from "@penclipai/adapter-gemini-local";
|
|
@@ -37,6 +37,7 @@ import { recoveryService } from "../services/recovery/service.js";
|
|
|
37
37
|
import { resolveCoreTrustPreset } from "../services/trust-preset-resolver.js";
|
|
38
38
|
import { readObject } from "../lib/objects.js";
|
|
39
39
|
import { listInvalidOrgChainDescendantIds } from "../services/agent-invokability.js";
|
|
40
|
+
import { AGENT_PROFILE_CHANGE_CONSENT_FIELDS, agentInstructionsChangeTargetKey, agentProfileChangeTargetKey, changeConsentGateService, touchesAgentProfileChangeConsentFields, } from "../services/change-consent-gate.js";
|
|
40
41
|
const RUN_LOG_DEFAULT_LIMIT_BYTES = 256_000;
|
|
41
42
|
const RUN_LOG_MAX_LIMIT_BYTES = 1024 * 1024;
|
|
42
43
|
function readRunLogLimitBytes(value) {
|
|
@@ -65,7 +66,6 @@ export function agentRoutes(db, options = {}) {
|
|
|
65
66
|
// Legacy hardcoded maps — used as fallback when adapter module does not
|
|
66
67
|
// declare capability flags explicitly.
|
|
67
68
|
const DEFAULT_INSTRUCTIONS_PATH_KEYS = {
|
|
68
|
-
acpx_local: "instructionsFilePath",
|
|
69
69
|
claude_local: "instructionsFilePath",
|
|
70
70
|
codex_local: "instructionsFilePath",
|
|
71
71
|
droid_local: "instructionsFilePath",
|
|
@@ -101,6 +101,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
101
101
|
"instructionsFilePath",
|
|
102
102
|
"agentsMdPath",
|
|
103
103
|
];
|
|
104
|
+
const KNOWN_INSTRUCTIONS_BUNDLE_KEY_SET = new Set(KNOWN_INSTRUCTIONS_BUNDLE_KEYS);
|
|
104
105
|
const router = Router();
|
|
105
106
|
const svc = agentService(db);
|
|
106
107
|
const access = accessService(db);
|
|
@@ -260,11 +261,26 @@ export function agentRoutes(db, options = {}) {
|
|
|
260
261
|
// run id to heartbeat_runs.id, and we don't want to manufacture a fake
|
|
261
262
|
// run row. Cleanup goes through the driver's `releaseRunLease` directly
|
|
262
263
|
// (by lease record), since the batch helper queries by heartbeatRunId.
|
|
264
|
+
//
|
|
265
|
+
// Sandbox tests boot a fresh throwaway sandbox (never resume a retained
|
|
266
|
+
// agent lease) and archive it on release instead of deleting it, so the
|
|
267
|
+
// operator can inspect the exact sandbox from the provider dashboard while
|
|
268
|
+
// provider-side expiry reaps it later.
|
|
269
|
+
const testEnvironment = environment.driver === "sandbox"
|
|
270
|
+
? {
|
|
271
|
+
...environment,
|
|
272
|
+
config: {
|
|
273
|
+
...(environment.config ?? {}),
|
|
274
|
+
reuseLease: false,
|
|
275
|
+
archiveOnRelease: true,
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
: environment;
|
|
263
279
|
let leaseRecord;
|
|
264
280
|
try {
|
|
265
281
|
leaseRecord = await environmentRuntime.acquireRunLease({
|
|
266
282
|
companyId: input.companyId,
|
|
267
|
-
environment,
|
|
283
|
+
environment: testEnvironment,
|
|
268
284
|
issueId: null,
|
|
269
285
|
heartbeatRunId: null,
|
|
270
286
|
persistedExecutionWorkspace: null,
|
|
@@ -296,7 +312,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
296
312
|
try {
|
|
297
313
|
if (driver) {
|
|
298
314
|
await driver.releaseRunLease({
|
|
299
|
-
environment,
|
|
315
|
+
environment: testEnvironment,
|
|
300
316
|
lease: leaseRecord.lease,
|
|
301
317
|
status,
|
|
302
318
|
});
|
|
@@ -314,7 +330,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
314
330
|
let realizedCwd = null;
|
|
315
331
|
try {
|
|
316
332
|
const realized = await environmentRuntime.realizeWorkspace({
|
|
317
|
-
environment,
|
|
333
|
+
environment: testEnvironment,
|
|
318
334
|
lease: leaseRecord.lease,
|
|
319
335
|
// No host workspace to copy for a Test invocation; sandbox/plugin
|
|
320
336
|
// realize implementations use the lease metadata's remoteCwd to
|
|
@@ -353,9 +369,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
353
369
|
companyId: input.companyId,
|
|
354
370
|
adapterType: input.adapterType,
|
|
355
371
|
environment: {
|
|
356
|
-
id:
|
|
357
|
-
driver:
|
|
358
|
-
config:
|
|
372
|
+
id: testEnvironment.id,
|
|
373
|
+
driver: testEnvironment.driver,
|
|
374
|
+
config: testEnvironment.config ?? null,
|
|
359
375
|
},
|
|
360
376
|
leaseId: leaseRecord.lease.id,
|
|
361
377
|
leaseMetadata: leaseMetadataForTarget,
|
|
@@ -398,9 +414,64 @@ export function agentRoutes(db, options = {}) {
|
|
|
398
414
|
executionTarget: target,
|
|
399
415
|
environmentName: environment.name,
|
|
400
416
|
fallbackChecks: [],
|
|
417
|
+
sandboxIdentityCheck: buildSandboxIdentityCheck({
|
|
418
|
+
environmentName: environment.name,
|
|
419
|
+
lease: leaseRecord.lease,
|
|
420
|
+
}),
|
|
401
421
|
release: releaseLease,
|
|
402
422
|
};
|
|
403
423
|
}
|
|
424
|
+
function readMetadataString(metadata, keys) {
|
|
425
|
+
for (const key of keys) {
|
|
426
|
+
const value = metadata[key];
|
|
427
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
428
|
+
return value.trim();
|
|
429
|
+
}
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
function buildSandboxIdentityCheck(input) {
|
|
433
|
+
const metadata = input.lease.metadata ?? {};
|
|
434
|
+
const provider = input.lease.provider ?? readMetadataString(metadata, ["provider"]);
|
|
435
|
+
const sandboxId = readMetadataString(metadata, ["sandboxId", "sandboxID", "sandbox_id", "id"]);
|
|
436
|
+
const sandboxName = readMetadataString(metadata, ["sandboxName", "sandbox_name", "name"]);
|
|
437
|
+
const snapshotRef = readMetadataString(metadata, [
|
|
438
|
+
"snapshot",
|
|
439
|
+
"snapshotId",
|
|
440
|
+
"snapshotID",
|
|
441
|
+
"snapshotRef",
|
|
442
|
+
"snapshot_ref",
|
|
443
|
+
"templateRef",
|
|
444
|
+
"template_ref",
|
|
445
|
+
"templateId",
|
|
446
|
+
"templateID",
|
|
447
|
+
"image",
|
|
448
|
+
"imageId",
|
|
449
|
+
"imageID",
|
|
450
|
+
"imageRef",
|
|
451
|
+
"image_ref",
|
|
452
|
+
]);
|
|
453
|
+
const templateKind = readMetadataString(metadata, [
|
|
454
|
+
"templateKind",
|
|
455
|
+
"template_kind",
|
|
456
|
+
"templateRefKind",
|
|
457
|
+
"template_ref_kind",
|
|
458
|
+
]);
|
|
459
|
+
const detailParts = [
|
|
460
|
+
`paperclipLeaseId=${input.lease.id}`,
|
|
461
|
+
input.lease.providerLeaseId ? `providerLeaseId=${input.lease.providerLeaseId}` : null,
|
|
462
|
+
provider ? `provider=${provider}` : null,
|
|
463
|
+
sandboxId ? `sandboxId=${sandboxId}` : null,
|
|
464
|
+
sandboxName ? `sandboxName=${sandboxName}` : null,
|
|
465
|
+
snapshotRef ? `${templateKind ? `${templateKind}Ref` : "snapshotOrTemplateRef"}=${snapshotRef}` : null,
|
|
466
|
+
].filter((part) => Boolean(part));
|
|
467
|
+
return {
|
|
468
|
+
code: "sandbox_test_identity",
|
|
469
|
+
level: "info",
|
|
470
|
+
message: `Sandbox test identity for "${input.environmentName}".`,
|
|
471
|
+
detail: detailParts.join("; "),
|
|
472
|
+
hint: "Use these provider-neutral IDs when comparing model-test output with provider logs or refreshed sandbox snapshots.",
|
|
473
|
+
};
|
|
474
|
+
}
|
|
404
475
|
async function getCurrentUserRedactionOptions() {
|
|
405
476
|
return {
|
|
406
477
|
enabled: (await instanceSettings.getGeneral()).censorUsernameInLogs,
|
|
@@ -539,7 +610,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
539
610
|
resource: { type: "company", companyId },
|
|
540
611
|
});
|
|
541
612
|
if (!decision.allowed) {
|
|
542
|
-
throw forbidden(decision.explanation);
|
|
613
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
543
614
|
}
|
|
544
615
|
if (req.actor.type !== "agent")
|
|
545
616
|
return null;
|
|
@@ -559,33 +630,29 @@ export function agentRoutes(db, options = {}) {
|
|
|
559
630
|
});
|
|
560
631
|
if (decision.allowed)
|
|
561
632
|
return;
|
|
562
|
-
throw forbidden(decision.explanation);
|
|
633
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
563
634
|
}
|
|
564
635
|
async function assertCanReadConfigurations(req, companyId) {
|
|
565
636
|
// Reading agent configurations, skills, and config revisions is a
|
|
566
637
|
// read-only operation available to any board (human) member of the
|
|
567
638
|
// company. Responses go through `redactAgentConfiguration` so secrets
|
|
568
639
|
// are never exposed. Mutations and environment probes still gate on
|
|
569
|
-
// agents:create via
|
|
640
|
+
// agents:create or agents:configure via the mutating route helpers.
|
|
570
641
|
//
|
|
571
|
-
// For AGENT actors we keep
|
|
572
|
-
//
|
|
573
|
-
//
|
|
574
|
-
// non-human principals — they should not be able to introspect peer
|
|
575
|
-
// agents' configurations just by virtue of being in the same company.
|
|
642
|
+
// For AGENT actors we keep a stricter gate: an agent must have either
|
|
643
|
+
// agents:configure or agents:suggest-changes before it can inspect peer
|
|
644
|
+
// agent configuration for a proposed diff.
|
|
576
645
|
assertCompanyAccess(req, companyId);
|
|
577
646
|
if (req.actor.type === "agent") {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
if (!allowedByGrant && !canCreateAgents(actorAgent)) {
|
|
586
|
-
throw forbidden("Missing permission: can create agents");
|
|
647
|
+
const decision = await access.decide({
|
|
648
|
+
actor: req.actor,
|
|
649
|
+
action: "agent_config:read",
|
|
650
|
+
resource: { type: "company", companyId },
|
|
651
|
+
});
|
|
652
|
+
if (!decision.allowed) {
|
|
653
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
587
654
|
}
|
|
588
|
-
return
|
|
655
|
+
return req.actor.agentId ? await svc.getById(req.actor.agentId) : null;
|
|
589
656
|
}
|
|
590
657
|
return null;
|
|
591
658
|
}
|
|
@@ -603,10 +670,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
603
670
|
}
|
|
604
671
|
async function actorCanReadConfigurationsForCompany(req, companyId) {
|
|
605
672
|
// Mirrors assertCanReadConfigurations but returns a boolean instead of
|
|
606
|
-
// throwing. Board actors only need company access; agent actors must
|
|
607
|
-
//
|
|
608
|
-
//
|
|
609
|
-
// configurations.
|
|
673
|
+
// throwing. Board actors only need company access; agent actors must pass
|
|
674
|
+
// the agent configuration read grant ladder so peer agents cannot snoop
|
|
675
|
+
// each others' configurations.
|
|
610
676
|
try {
|
|
611
677
|
assertCompanyAccess(req, companyId);
|
|
612
678
|
}
|
|
@@ -615,13 +681,12 @@ export function agentRoutes(db, options = {}) {
|
|
|
615
681
|
}
|
|
616
682
|
if (req.actor.type === "board")
|
|
617
683
|
return true;
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
return allowedByGrant || canCreateAgents(actorAgent);
|
|
684
|
+
const decision = await access.decide({
|
|
685
|
+
actor: req.actor,
|
|
686
|
+
action: "agent_config:read",
|
|
687
|
+
resource: { type: "company", companyId },
|
|
688
|
+
});
|
|
689
|
+
return decision.allowed;
|
|
625
690
|
}
|
|
626
691
|
async function buildSkippedWakeupResponse(agent, payload) {
|
|
627
692
|
const issueId = typeof payload?.issueId === "string" && payload.issueId.trim() ? payload.issueId : null;
|
|
@@ -690,7 +755,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
690
755
|
});
|
|
691
756
|
if (decision.allowed)
|
|
692
757
|
return;
|
|
693
|
-
throw forbidden(decision.explanation);
|
|
758
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
694
759
|
}
|
|
695
760
|
async function assertCanReadAgent(req, targetAgent) {
|
|
696
761
|
assertCompanyAccess(req, targetAgent.companyId);
|
|
@@ -704,6 +769,14 @@ export function agentRoutes(db, options = {}) {
|
|
|
704
769
|
if (!actorAgent || actorAgent.companyId !== targetAgent.companyId) {
|
|
705
770
|
throw forbidden("Agent key cannot access another company");
|
|
706
771
|
}
|
|
772
|
+
const decision = await access.decide({
|
|
773
|
+
actor: req.actor,
|
|
774
|
+
action: "agent_config:read",
|
|
775
|
+
resource: { type: "agent", companyId: targetAgent.companyId, agentId: targetAgent.id },
|
|
776
|
+
});
|
|
777
|
+
if (decision.allowed)
|
|
778
|
+
return;
|
|
779
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
707
780
|
}
|
|
708
781
|
function assertKnownAdapterType(type) {
|
|
709
782
|
const adapterType = typeof type === "string" ? type.trim() : "";
|
|
@@ -984,21 +1057,6 @@ export function agentRoutes(db, options = {}) {
|
|
|
984
1057
|
}
|
|
985
1058
|
function applyCreateDefaultsByAdapterType(adapterType, adapterConfig) {
|
|
986
1059
|
const next = { ...adapterConfig };
|
|
987
|
-
if (adapterType === "acpx_local") {
|
|
988
|
-
if (!asNonEmptyString(next.agent)) {
|
|
989
|
-
next.agent = DEFAULT_ACPX_LOCAL_AGENT;
|
|
990
|
-
}
|
|
991
|
-
if (!asNonEmptyString(next.mode)) {
|
|
992
|
-
next.mode = DEFAULT_ACPX_LOCAL_MODE;
|
|
993
|
-
}
|
|
994
|
-
if (!asNonEmptyString(next.permissionMode)) {
|
|
995
|
-
next.permissionMode = DEFAULT_ACPX_LOCAL_PERMISSION_MODE;
|
|
996
|
-
}
|
|
997
|
-
if (!asNonEmptyString(next.nonInteractivePermissions)) {
|
|
998
|
-
next.nonInteractivePermissions = DEFAULT_ACPX_LOCAL_NON_INTERACTIVE_PERMISSIONS;
|
|
999
|
-
}
|
|
1000
|
-
return ensureGatewayDeviceKey(adapterType, next);
|
|
1001
|
-
}
|
|
1002
1060
|
if (adapterType === "codex_local") {
|
|
1003
1061
|
const hasBypassFlag = typeof next.dangerouslyBypassApprovalsAndSandbox === "boolean" ||
|
|
1004
1062
|
typeof next.dangerouslyBypassSandbox === "boolean";
|
|
@@ -1062,7 +1120,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
1062
1120
|
delete nextAdapterConfig.bootstrapPromptTemplate;
|
|
1063
1121
|
if (!hadLegacyPrompt)
|
|
1064
1122
|
return agent;
|
|
1065
|
-
const updated = await svc.update(agent.id, { adapterConfig: nextAdapterConfig }
|
|
1123
|
+
const updated = await svc.update(agent.id, { adapterConfig: nextAdapterConfig }, {
|
|
1124
|
+
allowPendingApprovalConfigUpdate: true,
|
|
1125
|
+
});
|
|
1066
1126
|
return updated ?? { ...agent, adapterConfig: nextAdapterConfig };
|
|
1067
1127
|
}
|
|
1068
1128
|
const files = input?.files
|
|
@@ -1071,7 +1131,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
1071
1131
|
const nextAdapterConfig = { ...materialized.adapterConfig };
|
|
1072
1132
|
delete nextAdapterConfig.promptTemplate;
|
|
1073
1133
|
delete nextAdapterConfig.bootstrapPromptTemplate;
|
|
1074
|
-
const updated = await svc.update(agent.id, { adapterConfig: nextAdapterConfig }
|
|
1134
|
+
const updated = await svc.update(agent.id, { adapterConfig: nextAdapterConfig }, {
|
|
1135
|
+
allowPendingApprovalConfigUpdate: true,
|
|
1136
|
+
});
|
|
1075
1137
|
return updated ?? { ...agent, adapterConfig: nextAdapterConfig };
|
|
1076
1138
|
}
|
|
1077
1139
|
function assertNoNewAgentLegacyPromptTemplate(adapterType, adapterConfig) {
|
|
@@ -1082,12 +1144,51 @@ export function agentRoutes(db, options = {}) {
|
|
|
1082
1144
|
throw unprocessable("New agents must use instructionsBundle/AGENTS.md instead of adapterConfig.promptTemplate or bootstrapPromptTemplate");
|
|
1083
1145
|
}
|
|
1084
1146
|
}
|
|
1085
|
-
async function
|
|
1147
|
+
async function assertCanApplyProtectedAgentChange(req, targetAgent, targetKeys) {
|
|
1086
1148
|
assertCompanyAccess(req, targetAgent.companyId);
|
|
1087
|
-
|
|
1088
|
-
|
|
1149
|
+
const changeScope = { requiresChangeGrant: true };
|
|
1150
|
+
const decision = await access.decide({
|
|
1151
|
+
actor: req.actor,
|
|
1152
|
+
action: "agent_config:update",
|
|
1153
|
+
resource: { type: "agent", companyId: targetAgent.companyId, agentId: targetAgent.id },
|
|
1154
|
+
scope: changeScope,
|
|
1155
|
+
});
|
|
1156
|
+
if (decision.allowed) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
if (decision.reason === "deny_missing_consent" && req.actor.type === "agent" && targetKeys.length > 0) {
|
|
1160
|
+
try {
|
|
1161
|
+
await changeConsentGateService(db).assertConsented({
|
|
1162
|
+
companyId: targetAgent.companyId,
|
|
1163
|
+
actorAgentId: req.actor.agentId,
|
|
1164
|
+
actorRunId: req.actor.runId ?? null,
|
|
1165
|
+
targetKeys,
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
catch (err) {
|
|
1169
|
+
if (err instanceof HttpError && err.status === 403) {
|
|
1170
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
1171
|
+
}
|
|
1172
|
+
throw err;
|
|
1173
|
+
}
|
|
1174
|
+
const consentedDecision = await access.decide({
|
|
1175
|
+
actor: req.actor,
|
|
1176
|
+
action: "agent_config:update",
|
|
1177
|
+
resource: { type: "agent", companyId: targetAgent.companyId, agentId: targetAgent.id },
|
|
1178
|
+
scope: { ...changeScope, consentedChange: true },
|
|
1179
|
+
});
|
|
1180
|
+
if (consentedDecision.allowed) {
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
throw forbidden(consentedDecision.explanation, authorizationDeniedDetails(consentedDecision));
|
|
1089
1184
|
}
|
|
1090
|
-
|
|
1185
|
+
throw forbidden(decision.explanation, authorizationDeniedDetails(decision));
|
|
1186
|
+
}
|
|
1187
|
+
async function assertCanManageInstructionsPath(req, targetAgent) {
|
|
1188
|
+
await assertCanApplyProtectedAgentChange(req, targetAgent, [agentInstructionsChangeTargetKey(targetAgent.id)]);
|
|
1189
|
+
}
|
|
1190
|
+
async function assertCanApplyAgentProfileChange(req, targetAgent) {
|
|
1191
|
+
await assertCanApplyProtectedAgentChange(req, targetAgent, [agentProfileChangeTargetKey(targetAgent.id)]);
|
|
1091
1192
|
}
|
|
1092
1193
|
function assertNoAgentInstructionsConfigMutation(req, adapterConfig, path = "adapterConfig") {
|
|
1093
1194
|
if (req.actor.type !== "agent" || !adapterConfig)
|
|
@@ -1175,7 +1276,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
1175
1276
|
paperclipRuntimeSkills: runtimeSkillEntries,
|
|
1176
1277
|
};
|
|
1177
1278
|
}
|
|
1178
|
-
async function resolveDesiredSkillAssignment(companyId, adapterType, adapterConfig, requestedDesiredSkills) {
|
|
1279
|
+
async function resolveDesiredSkillAssignment(companyId, adapterType, adapterConfig, requestedDesiredSkills, options = {}) {
|
|
1179
1280
|
if (!requestedDesiredSkills) {
|
|
1180
1281
|
return {
|
|
1181
1282
|
adapterConfig,
|
|
@@ -1184,18 +1285,22 @@ export function agentRoutes(db, options = {}) {
|
|
|
1184
1285
|
runtimeSkillEntries: null,
|
|
1185
1286
|
};
|
|
1186
1287
|
}
|
|
1187
|
-
const resolvedRequestedSkillEntries = await companySkills.resolveRequestedSkillEntries(companyId, requestedDesiredSkills
|
|
1288
|
+
const { resolved: resolvedRequestedSkillEntries, unresolved: unresolvedDesiredSkillKeys } = await companySkills.resolveRequestedSkillEntries(companyId, requestedDesiredSkills, {
|
|
1289
|
+
tolerateUnknownReferences: options.tolerateUnknownDesiredSkills,
|
|
1290
|
+
});
|
|
1291
|
+
// Runtime materialization + version selection only ever consider skills that
|
|
1292
|
+
// actually resolve to the company library; stale keys can't be materialized.
|
|
1188
1293
|
const runtimeSkillEntries = await companySkills.listRuntimeSkillEntries(companyId, {
|
|
1189
1294
|
materializeMissing: shouldMaterializeRuntimeSkillsForAdapter(adapterType),
|
|
1190
1295
|
versionSelections: skillVersionSelectionMap(resolvedRequestedSkillEntries),
|
|
1191
1296
|
});
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
1297
|
+
const resolvedDesiredSkillEntries = resolvedRequestedSkillEntries.filter((entry, index, entries) => entries.findIndex((candidate) => candidate.key === entry.key) === index);
|
|
1298
|
+
// Preserve stale/unresolvable keys in the persisted desired set so they stay
|
|
1299
|
+
// visible (and explicitly removable) instead of vanishing on the next save.
|
|
1195
1300
|
const desiredSkillEntries = [
|
|
1196
|
-
...
|
|
1197
|
-
...
|
|
1198
|
-
]
|
|
1301
|
+
...resolvedDesiredSkillEntries,
|
|
1302
|
+
...unresolvedDesiredSkillKeys.map((key) => ({ key, versionId: null })),
|
|
1303
|
+
];
|
|
1199
1304
|
const desiredSkills = desiredSkillEntries.map((entry) => entry.key);
|
|
1200
1305
|
return {
|
|
1201
1306
|
adapterConfig: writePaperclipSkillSyncPreference(adapterConfig, desiredSkillEntries),
|
|
@@ -1324,7 +1429,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
1324
1429
|
: null;
|
|
1325
1430
|
const normalizedAdapterConfig = await secretsSvc.normalizeAdapterConfigForPersistence(companyId, inputAdapterConfig, { strictMode: strictSecretsMode, adapterType: type });
|
|
1326
1431
|
const { config: runtimeAdapterConfig } = await secretsSvc.resolveAdapterConfigForRuntime(companyId, normalizedAdapterConfig, undefined, { adapterType: type });
|
|
1327
|
-
const { executionTarget, environmentName, fallbackChecks, release } = await resolveAdapterTestExecutionContext({
|
|
1432
|
+
const { executionTarget, environmentName, fallbackChecks, sandboxIdentityCheck, release } = await resolveAdapterTestExecutionContext({
|
|
1328
1433
|
companyId,
|
|
1329
1434
|
adapterType: type,
|
|
1330
1435
|
environmentId: requestedEnvironmentId,
|
|
@@ -1360,7 +1465,10 @@ export function agentRoutes(db, options = {}) {
|
|
|
1360
1465
|
});
|
|
1361
1466
|
if (result.status === "fail")
|
|
1362
1467
|
releaseStatus = "failed";
|
|
1363
|
-
res.json(
|
|
1468
|
+
res.json({
|
|
1469
|
+
...result,
|
|
1470
|
+
checks: sandboxIdentityCheck ? [sandboxIdentityCheck, ...result.checks] : result.checks,
|
|
1471
|
+
});
|
|
1364
1472
|
}
|
|
1365
1473
|
catch (err) {
|
|
1366
1474
|
releaseStatus = "failed";
|
|
@@ -1385,7 +1493,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
1385
1493
|
res.json(buildUnsupportedSkillSnapshot(agent.adapterType, desiredSkillEntries));
|
|
1386
1494
|
return;
|
|
1387
1495
|
}
|
|
1388
|
-
const { config: runtimeConfig } = await secretsSvc.resolveAdapterConfigForRuntime(agent.companyId, agent.adapterConfig);
|
|
1496
|
+
const { config: runtimeConfig } = await secretsSvc.resolveAdapterConfigForRuntime(agent.companyId, agent.adapterConfig, undefined, { adapterType: agent.adapterType, skipUserSecrets: true });
|
|
1389
1497
|
const runtimeSkillConfig = await buildRuntimeSkillConfig(agent.companyId, agent.adapterType, runtimeConfig, { materializeMissing: false });
|
|
1390
1498
|
const snapshot = await adapter.listSkills({
|
|
1391
1499
|
agentId: agent.id,
|
|
@@ -1404,7 +1512,11 @@ export function agentRoutes(db, options = {}) {
|
|
|
1404
1512
|
}
|
|
1405
1513
|
await assertCanUpdateAgent(req, agent);
|
|
1406
1514
|
const requestedSkills = normalizeDesiredSkillSelections(req.body.desiredSkills);
|
|
1407
|
-
const { adapterConfig: nextAdapterConfig, desiredSkills, desiredSkillEntries, runtimeSkillEntries, } = await resolveDesiredSkillAssignment(agent.companyId, agent.adapterType, agent.adapterConfig, requestedSkills
|
|
1515
|
+
const { adapterConfig: nextAdapterConfig, desiredSkills, desiredSkillEntries, runtimeSkillEntries, } = await resolveDesiredSkillAssignment(agent.companyId, agent.adapterType, agent.adapterConfig, requestedSkills,
|
|
1516
|
+
// Toggling a resolvable skill must not fail just because the agent
|
|
1517
|
+
// already carries stale desired keys (e.g. a skill removed from the
|
|
1518
|
+
// library). Preserve those keys so they remain visible/removable.
|
|
1519
|
+
{ tolerateUnknownDesiredSkills: true });
|
|
1408
1520
|
if (!desiredSkills || !desiredSkillEntries || !runtimeSkillEntries) {
|
|
1409
1521
|
throw unprocessable("Skill sync requires desiredSkills.");
|
|
1410
1522
|
}
|
|
@@ -1423,7 +1535,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
1423
1535
|
return;
|
|
1424
1536
|
}
|
|
1425
1537
|
const adapter = findActiveServerAdapter(updated.adapterType);
|
|
1426
|
-
const { config: runtimeConfig } = await secretsSvc.resolveAdapterConfigForRuntime(updated.companyId, updated.adapterConfig);
|
|
1538
|
+
const { config: runtimeConfig } = await secretsSvc.resolveAdapterConfigForRuntime(updated.companyId, updated.adapterConfig, undefined, { adapterType: updated.adapterType, skipUserSecrets: true });
|
|
1427
1539
|
const runtimeSkillConfig = {
|
|
1428
1540
|
...runtimeConfig,
|
|
1429
1541
|
paperclipRuntimeSkills: runtimeSkillEntries,
|
|
@@ -1619,12 +1731,21 @@ export function agentRoutes(db, options = {}) {
|
|
|
1619
1731
|
includeRoutineExecutions: true,
|
|
1620
1732
|
limit: ISSUE_LIST_DEFAULT_LIMIT,
|
|
1621
1733
|
});
|
|
1622
|
-
const
|
|
1734
|
+
const worktreeActivation = await resolveWorktreeRunExecutionActivationState({
|
|
1735
|
+
getExperimental: () => instanceSettingsService(db).getExperimental(),
|
|
1736
|
+
});
|
|
1737
|
+
const isWorktreeRuntime = isTruthyRuntimeEnvValue(process.env.PAPERCLIP_IN_WORKTREE);
|
|
1738
|
+
const eligibleRows = !isWorktreeRuntime
|
|
1739
|
+
? rows
|
|
1740
|
+
: worktreeActivation.armed
|
|
1741
|
+
? rows.filter((issue) => new Date(issue.createdAt) >= new Date(worktreeActivation.cutoff))
|
|
1742
|
+
: [];
|
|
1743
|
+
const issueIds = eligibleRows.map((issue) => issue.id);
|
|
1623
1744
|
const [dependencyReadiness, recoveryActionByIssue] = await Promise.all([
|
|
1624
1745
|
issuesSvc.listDependencyReadiness(req.actor.companyId, issueIds),
|
|
1625
1746
|
recoveryActionsSvc.listActiveForIssues(req.actor.companyId, issueIds),
|
|
1626
1747
|
]);
|
|
1627
|
-
res.json(
|
|
1748
|
+
res.json(eligibleRows.map((issue) => ({
|
|
1628
1749
|
id: issue.id,
|
|
1629
1750
|
identifier: issue.identifier,
|
|
1630
1751
|
title: issue.title,
|
|
@@ -2004,6 +2125,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2004
2125
|
trackAgentCreated(telemetryClient, { agentRole: agent.role, agentId: agent.id });
|
|
2005
2126
|
}
|
|
2006
2127
|
await applyDefaultAgentTaskAssignGrant(companyId, agent.id, req.actor.type === "board" ? (req.actor.userId ?? null) : null);
|
|
2128
|
+
await builtInAgentService(db).ensureCompanyDefaultAgentGrants(companyId);
|
|
2007
2129
|
if (agent.budgetMonthlyCents > 0) {
|
|
2008
2130
|
await budgets.upsertPolicy(companyId, {
|
|
2009
2131
|
scopeType: "agent",
|
|
@@ -2264,7 +2386,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2264
2386
|
res.status(404).json({ error: "Agent not found" });
|
|
2265
2387
|
return;
|
|
2266
2388
|
}
|
|
2267
|
-
|
|
2389
|
+
assertCompanyAccess(req, existing.companyId);
|
|
2268
2390
|
if (hasOwn(req.body, "permissions")) {
|
|
2269
2391
|
res.status(422).json({ error: "Use /api/agents/:id/permissions for permission changes" });
|
|
2270
2392
|
return;
|
|
@@ -2319,11 +2441,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
2319
2441
|
// Preserve adapter-agnostic keys (env, cwd, etc.) from the existing config
|
|
2320
2442
|
// when the adapter type changes. Without this, a PATCH that includes
|
|
2321
2443
|
// adapterConfig but omits these keys would silently drop them.
|
|
2322
|
-
const ADAPTER_AGNOSTIC_KEYS = [
|
|
2323
|
-
"env", "cwd", "timeoutSec", "graceSec",
|
|
2324
|
-
"promptTemplate", "bootstrapPromptTemplate",
|
|
2325
|
-
];
|
|
2326
2444
|
for (const key of ADAPTER_AGNOSTIC_KEYS) {
|
|
2445
|
+
if (KNOWN_INSTRUCTIONS_BUNDLE_KEY_SET.has(key))
|
|
2446
|
+
continue;
|
|
2327
2447
|
if (rawEffectiveAdapterConfig[key] === undefined && existingAdapterConfig[key] !== undefined) {
|
|
2328
2448
|
rawEffectiveAdapterConfig = { ...rawEffectiveAdapterConfig, [key]: existingAdapterConfig[key] };
|
|
2329
2449
|
}
|
|
@@ -2350,6 +2470,14 @@ export function agentRoutes(db, options = {}) {
|
|
|
2350
2470
|
allowedSandboxProviders: allowedSandboxProvidersForAgent(requestedAdapterType),
|
|
2351
2471
|
});
|
|
2352
2472
|
}
|
|
2473
|
+
const touchesProfileFields = touchesAgentProfileChangeConsentFields(patchData);
|
|
2474
|
+
const profileOnlyChange = touchesProfileFields && Object.keys(patchData).every((key) => AGENT_PROFILE_CHANGE_CONSENT_FIELDS.includes(key));
|
|
2475
|
+
if (profileOnlyChange) {
|
|
2476
|
+
await assertCanApplyAgentProfileChange(req, existing);
|
|
2477
|
+
}
|
|
2478
|
+
else {
|
|
2479
|
+
await assertCanUpdateAgent(req, existing);
|
|
2480
|
+
}
|
|
2353
2481
|
const actor = getActorInfo(req);
|
|
2354
2482
|
const agent = await svc.update(id, patchData, {
|
|
2355
2483
|
recordRevision: {
|
|
@@ -2602,7 +2730,9 @@ export function agentRoutes(db, options = {}) {
|
|
|
2602
2730
|
if (!agent) {
|
|
2603
2731
|
return;
|
|
2604
2732
|
}
|
|
2605
|
-
const key = await svc.createApiKey(id, req.body.name, req.body.scope
|
|
2733
|
+
const key = await svc.createApiKey(id, req.body.name, req.body.scope, {
|
|
2734
|
+
responsibleUserId: req.actor.userId ?? null,
|
|
2735
|
+
});
|
|
2606
2736
|
await logActivity(db, {
|
|
2607
2737
|
companyId: agent.companyId,
|
|
2608
2738
|
actorType: "user",
|
|
@@ -2610,7 +2740,12 @@ export function agentRoutes(db, options = {}) {
|
|
|
2610
2740
|
action: "agent.key_created",
|
|
2611
2741
|
entityType: "agent",
|
|
2612
2742
|
entityId: agent.id,
|
|
2613
|
-
details: {
|
|
2743
|
+
details: {
|
|
2744
|
+
keyId: key.id,
|
|
2745
|
+
name: key.name,
|
|
2746
|
+
scope: key.scope,
|
|
2747
|
+
responsibleUserId: key.responsibleUserId,
|
|
2748
|
+
},
|
|
2614
2749
|
});
|
|
2615
2750
|
res.status(201).json(key);
|
|
2616
2751
|
});
|
|
@@ -2692,7 +2827,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2692
2827
|
actorType: actor.actorType,
|
|
2693
2828
|
actorId: actor.actorId,
|
|
2694
2829
|
agentId: actor.agentId,
|
|
2695
|
-
runId:
|
|
2830
|
+
runId: run.id,
|
|
2696
2831
|
action: "heartbeat.invoked",
|
|
2697
2832
|
entityType: "heartbeat_run",
|
|
2698
2833
|
entityId: run.id,
|
|
@@ -2775,7 +2910,7 @@ export function agentRoutes(db, options = {}) {
|
|
|
2775
2910
|
actorType: actor.actorType,
|
|
2776
2911
|
actorId: actor.actorId,
|
|
2777
2912
|
agentId: actor.agentId,
|
|
2778
|
-
runId:
|
|
2913
|
+
runId: run.id,
|
|
2779
2914
|
action: "heartbeat.invoked",
|
|
2780
2915
|
entityType: "heartbeat_run",
|
|
2781
2916
|
entityId: run.id,
|