devchain-cli 0.19.1 → 0.20.1
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/drizzle/0069_fluffy_exodus.sql +2 -0
- package/dist/drizzle/0070_lyrical_tombstone.sql +1 -0
- package/dist/drizzle/0071_special_avengers.sql +22 -0
- package/dist/drizzle/meta/0069_snapshot.json +5767 -0
- package/dist/drizzle/meta/0070_snapshot.json +5774 -0
- package/dist/drizzle/meta/0071_snapshot.json +5931 -0
- package/dist/drizzle/meta/_journal.json +22 -1
- package/dist/node_modules/@devchain/shared/__fixtures__/phase2-frames.d.ts +0 -1
- package/dist/node_modules/@devchain/shared/__fixtures__/phase2-frames.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/__fixtures__/phase2-frames.js +0 -2
- package/dist/node_modules/@devchain/shared/__fixtures__/phase2-frames.js.map +1 -1
- package/dist/node_modules/@devchain/shared/e2ee/base64.js +1 -1
- package/dist/node_modules/@devchain/shared/e2ee/base64.js.map +1 -1
- package/dist/node_modules/@devchain/shared/host-resolver.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/host-resolver.js.map +1 -1
- package/dist/node_modules/@devchain/shared/schemas/claude-launch-settings.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/schemas/claude-launch-settings.js +23 -0
- package/dist/node_modules/@devchain/shared/schemas/claude-launch-settings.js.map +1 -1
- package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts +475 -15
- package/dist/node_modules/@devchain/shared/schemas/export-schema.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/schemas/export-schema.js +22 -9
- package/dist/node_modules/@devchain/shared/schemas/export-schema.js.map +1 -1
- package/dist/node_modules/@devchain/shared/tsconfig.tsbuildinfo +1 -1
- package/dist/node_modules/@devchain/shared/tunnel-protocol.d.ts.map +1 -1
- package/dist/node_modules/@devchain/shared/tunnel-protocol.js +0 -1
- package/dist/node_modules/@devchain/shared/tunnel-protocol.js.map +1 -1
- package/dist/server/app.main.module.js +0 -2
- package/dist/server/app.main.module.js.map +1 -1
- package/dist/server/app.normal.module.js +0 -2
- package/dist/server/app.normal.module.js.map +1 -1
- package/dist/server/common/config/container-scope.d.ts +4 -0
- package/dist/server/common/config/container-scope.js +11 -0
- package/dist/server/common/config/container-scope.js.map +1 -0
- package/dist/server/common/test/app-bootstrap.helper.js +1 -0
- package/dist/server/common/test/app-bootstrap.helper.js.map +1 -1
- package/dist/server/modules/agent-message-delivery/adapters/legacy-delivery-formatter.adapter.js +11 -4
- package/dist/server/modules/agent-message-delivery/adapters/legacy-delivery-formatter.adapter.js.map +1 -1
- package/dist/server/modules/agent-message-delivery/adapters/legacy-recipient-resolver.adapter.d.ts +1 -3
- package/dist/server/modules/agent-message-delivery/adapters/legacy-recipient-resolver.adapter.js +1 -1
- package/dist/server/modules/agent-message-delivery/adapters/legacy-recipient-resolver.adapter.js.map +1 -1
- package/dist/server/modules/agent-message-delivery/agent-message-delivery.module.js +0 -2
- package/dist/server/modules/agent-message-delivery/agent-message-delivery.module.js.map +1 -1
- package/dist/server/modules/agent-message-delivery/agent-message-delivery.service.d.ts +1 -0
- package/dist/server/modules/agent-message-delivery/agent-message-delivery.service.js +19 -7
- package/dist/server/modules/agent-message-delivery/agent-message-delivery.service.js.map +1 -1
- package/dist/server/modules/agent-message-delivery/dtos/delivery.types.d.ts +16 -5
- package/dist/server/modules/agent-message-delivery/ports/delivery-recipient-resolver.d.ts +1 -3
- package/dist/server/modules/agent-message-delivery/ports/delivery-recipient-resolver.js.map +1 -1
- package/dist/server/modules/agents/controllers/agents.controller.d.ts +1 -0
- package/dist/server/modules/agents/controllers/agents.controller.js +7 -1
- package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
- package/dist/server/modules/cloud-tunnel/services/mobile-chat-rpc.service.js.map +1 -1
- package/dist/server/modules/cloud-tunnel/services/tunnel-event-forwarder.service.d.ts +1 -1
- package/dist/server/modules/cloud-tunnel/services/tunnel-event-forwarder.service.js +0 -8
- package/dist/server/modules/cloud-tunnel/services/tunnel-event-forwarder.service.js.map +1 -1
- package/dist/server/modules/epics/services/epics.service.d.ts +2 -0
- package/dist/server/modules/epics/services/epics.service.js +17 -3
- package/dist/server/modules/epics/services/epics.service.js.map +1 -1
- package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.d.ts +6 -0
- package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.js +111 -34
- package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.js.map +1 -1
- package/dist/server/modules/events/catalog/agent.message.sent.d.ts +89 -0
- package/dist/server/modules/events/catalog/agent.message.sent.js +16 -0
- package/dist/server/modules/events/catalog/agent.message.sent.js.map +1 -1
- package/dist/server/modules/events/catalog/broadcast-registry.js +1 -21
- package/dist/server/modules/events/catalog/broadcast-registry.js.map +1 -1
- package/dist/server/modules/events/catalog/index.d.ts +103 -22
- package/dist/server/modules/events/catalog/index.js +9 -3
- package/dist/server/modules/events/catalog/index.js.map +1 -1
- package/dist/server/modules/events/catalog/review.created.d.ts +4 -4
- package/dist/server/modules/events/catalog/session.recommendation.d.ts +2 -2
- package/dist/server/modules/events/catalog/session.stopped.d.ts +14 -0
- package/dist/server/modules/events/catalog/session.stopped.js +10 -1
- package/dist/server/modules/events/catalog/session.stopped.js.map +1 -1
- package/dist/server/modules/events/services/event-log.service.d.ts +3 -3
- package/dist/server/modules/events/services/event-log.service.js +58 -26
- package/dist/server/modules/events/services/event-log.service.js.map +1 -1
- package/dist/server/modules/events/services/events.service.d.ts +1 -1
- package/dist/server/modules/events/services/events.service.js +5 -0
- package/dist/server/modules/events/services/events.service.js.map +1 -1
- package/dist/server/modules/mcp/constants.d.ts +0 -4
- package/dist/server/modules/mcp/constants.js +1 -15
- package/dist/server/modules/mcp/constants.js.map +1 -1
- package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +34 -308
- package/dist/server/modules/mcp/dtos/mcp.dto.js +22 -94
- package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
- package/dist/server/modules/mcp/mcp-full.module.js +2 -2
- package/dist/server/modules/mcp/mcp-full.module.js.map +1 -1
- package/dist/server/modules/mcp/services/handlers/chat-context.d.ts +2 -4
- package/dist/server/modules/mcp/services/handlers/chat-tools.d.ts +0 -3
- package/dist/server/modules/mcp/services/handlers/chat-tools.js +81 -382
- package/dist/server/modules/mcp/services/handlers/chat-tools.js.map +1 -1
- package/dist/server/modules/mcp/services/handlers/epic-tools.js +7 -3
- package/dist/server/modules/mcp/services/handlers/epic-tools.js.map +1 -1
- package/dist/server/modules/mcp/services/handlers/project-context.d.ts +6 -0
- package/dist/server/modules/mcp/services/handlers/{activity-context.js → project-context.js} +1 -1
- package/dist/server/modules/mcp/services/handlers/project-context.js.map +1 -0
- package/dist/server/modules/mcp/services/handlers/project-tools.d.ts +3 -0
- package/dist/server/modules/mcp/services/handlers/project-tools.js +32 -0
- package/dist/server/modules/mcp/services/handlers/project-tools.js.map +1 -0
- package/dist/server/modules/mcp/services/mappers/dto-mappers.js +1 -0
- package/dist/server/modules/mcp/services/mappers/dto-mappers.js.map +1 -1
- package/dist/server/modules/mcp/services/mcp.service.d.ts +4 -4
- package/dist/server/modules/mcp/services/mcp.service.js +46 -51
- package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
- package/dist/server/modules/mcp/tool-descriptors/chat.bindings.js +0 -3
- package/dist/server/modules/mcp/tool-descriptors/chat.bindings.js.map +1 -1
- package/dist/server/modules/mcp/tool-descriptors/chat.metadata.js +8 -58
- package/dist/server/modules/mcp/tool-descriptors/chat.metadata.js.map +1 -1
- package/dist/server/modules/mcp/tool-descriptors/index.js +4 -4
- package/dist/server/modules/mcp/tool-descriptors/index.js.map +1 -1
- package/dist/server/modules/mcp/tool-descriptors/project.bindings.d.ts +2 -0
- package/dist/server/modules/mcp/tool-descriptors/project.bindings.js +8 -0
- package/dist/server/modules/mcp/tool-descriptors/project.bindings.js.map +1 -0
- package/dist/server/modules/mcp/tool-descriptors/project.metadata.d.ts +2 -0
- package/dist/server/modules/mcp/tool-descriptors/project.metadata.js +37 -0
- package/dist/server/modules/mcp/tool-descriptors/project.metadata.js.map +1 -0
- package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js +0 -2
- package/dist/server/modules/orchestrator/worktrees/services/worktrees.service.js.map +1 -1
- package/dist/server/modules/profiles/dto.d.ts +4 -4
- package/dist/server/modules/project-communication/dtos/project-communication.types.d.ts +44 -0
- package/dist/server/modules/project-communication/dtos/project-communication.types.js +3 -0
- package/dist/server/modules/project-communication/dtos/project-communication.types.js.map +1 -0
- package/dist/server/modules/project-communication/project-communication.module.d.ts +2 -0
- package/dist/server/modules/project-communication/project-communication.module.js +24 -0
- package/dist/server/modules/project-communication/project-communication.module.js.map +1 -0
- package/dist/server/modules/project-communication/project-communication.service.d.ts +16 -0
- package/dist/server/modules/project-communication/project-communication.service.js +224 -0
- package/dist/server/modules/project-communication/project-communication.service.js.map +1 -0
- package/dist/server/modules/projects/controllers/projects.controller.d.ts +4 -11
- package/dist/server/modules/projects/controllers/projects.controller.js +3 -10
- package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
- package/dist/server/modules/projects/helpers/project-export.d.ts +2 -5
- package/dist/server/modules/projects/helpers/project-runtime.helpers.d.ts +2 -5
- package/dist/server/modules/projects/helpers/project-runtime.helpers.js.map +1 -1
- package/dist/server/modules/projects/services/projects.service.d.ts +2 -5
- package/dist/server/modules/projects/template-codec/codecs/agents.codec.d.ts +2 -0
- package/dist/server/modules/projects/template-codec/codecs/agents.codec.js +2 -0
- package/dist/server/modules/projects/template-codec/codecs/agents.codec.js.map +1 -1
- package/dist/server/modules/projects/template-codec/codecs/subscribers.codec.d.ts +3 -10
- package/dist/server/modules/projects/template-codec/codecs/subscribers.codec.js.map +1 -1
- package/dist/server/modules/providers/adapters/capabilities/index.d.ts +2 -2
- package/dist/server/modules/providers/adapters/capabilities/index.js +2 -1
- package/dist/server/modules/providers/adapters/capabilities/index.js.map +1 -1
- package/dist/server/modules/providers/adapters/capabilities/provider-plugin.capability.d.ts +6 -0
- package/dist/server/modules/providers/adapters/capabilities/provider-plugin.capability.js +3 -0
- package/dist/server/modules/providers/adapters/capabilities/provider-plugin.capability.js.map +1 -0
- package/dist/server/modules/providers/adapters/capabilities/type-guards.d.ts +3 -0
- package/dist/server/modules/providers/adapters/capabilities/type-guards.js +6 -0
- package/dist/server/modules/providers/adapters/capabilities/type-guards.js.map +1 -1
- package/dist/server/modules/providers/adapters/claude.adapter.d.ts +6 -2
- package/dist/server/modules/providers/adapters/claude.adapter.js +53 -0
- package/dist/server/modules/providers/adapters/claude.adapter.js.map +1 -1
- package/dist/server/modules/providers/adapters/codex.adapter.d.ts +7 -2
- package/dist/server/modules/providers/adapters/codex.adapter.js +46 -0
- package/dist/server/modules/providers/adapters/codex.adapter.js.map +1 -1
- package/dist/server/modules/providers/adapters/plugin-catalog.utils.d.ts +15 -0
- package/dist/server/modules/providers/adapters/plugin-catalog.utils.js +62 -0
- package/dist/server/modules/providers/adapters/plugin-catalog.utils.js.map +1 -0
- package/dist/server/modules/providers/controllers/provider-plugin-policy.controller.d.ts +18 -0
- package/dist/server/modules/providers/controllers/provider-plugin-policy.controller.js +149 -0
- package/dist/server/modules/providers/controllers/provider-plugin-policy.controller.js.map +1 -0
- package/dist/server/modules/providers/controllers/provider-plugins.controller.d.ts +8 -0
- package/dist/server/modules/providers/controllers/provider-plugins.controller.js +78 -0
- package/dist/server/modules/providers/controllers/provider-plugins.controller.js.map +1 -0
- package/dist/server/modules/providers/dtos/provider-plugin.dto.d.ts +28 -0
- package/dist/server/modules/providers/dtos/provider-plugin.dto.js +3 -0
- package/dist/server/modules/providers/dtos/provider-plugin.dto.js.map +1 -0
- package/dist/server/modules/providers/providers.module.js +15 -1
- package/dist/server/modules/providers/providers.module.js.map +1 -1
- package/dist/server/modules/providers/services/provider-plugin-policy.service.d.ts +20 -0
- package/dist/server/modules/providers/services/provider-plugin-policy.service.js +146 -0
- package/dist/server/modules/providers/services/provider-plugin-policy.service.js.map +1 -0
- package/dist/server/modules/providers/services/provider-plugins.service.d.ts +21 -0
- package/dist/server/modules/providers/services/provider-plugins.service.js +169 -0
- package/dist/server/modules/providers/services/provider-plugins.service.js.map +1 -0
- package/dist/server/modules/registry/controllers/templates.controller.d.ts +14 -2
- package/dist/server/modules/reviews/dtos/review.dto.d.ts +2 -2
- package/dist/server/modules/reviews/subscribers/review-comment-notifier.subscriber.js +0 -1
- package/dist/server/modules/reviews/subscribers/review-comment-notifier.subscriber.js.map +1 -1
- package/dist/server/modules/runtime-context-capture/claude-launch-settings-materializer.service.d.ts +9 -1
- package/dist/server/modules/runtime-context-capture/claude-launch-settings-materializer.service.js +102 -16
- package/dist/server/modules/runtime-context-capture/claude-launch-settings-materializer.service.js.map +1 -1
- package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.d.ts +53 -0
- package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js +842 -0
- package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js.map +1 -0
- package/dist/server/modules/runtime-context-capture/index.d.ts +2 -1
- package/dist/server/modules/runtime-context-capture/index.js +5 -1
- package/dist/server/modules/runtime-context-capture/index.js.map +1 -1
- package/dist/server/modules/runtime-context-capture/runtime-context-capture.module.js +11 -2
- package/dist/server/modules/runtime-context-capture/runtime-context-capture.module.js.map +1 -1
- package/dist/server/modules/scheduled-epics/dtos/scheduled-epic.dto.d.ts +1 -1
- package/dist/server/modules/session-reader/data/pricing.json +32 -19
- package/dist/server/modules/sessions/controllers/sessions.controller.js +4 -1
- package/dist/server/modules/sessions/controllers/sessions.controller.js.map +1 -1
- package/dist/server/modules/sessions/services/delivery-failure-disclosure.d.ts +12 -0
- package/dist/server/modules/sessions/services/delivery-failure-disclosure.js +25 -0
- package/dist/server/modules/sessions/services/delivery-failure-disclosure.js.map +1 -0
- package/dist/server/modules/sessions/services/delivery-failure-notifier.service.js +7 -3
- package/dist/server/modules/sessions/services/delivery-failure-notifier.service.js.map +1 -1
- package/dist/server/modules/sessions/services/message-enqueue.service.d.ts +2 -1
- package/dist/server/modules/sessions/services/message-enqueue.service.js +1 -0
- package/dist/server/modules/sessions/services/message-enqueue.service.js.map +1 -1
- package/dist/server/modules/sessions/services/message-pool.types.d.ts +4 -1
- package/dist/server/modules/sessions/services/session-lifecycle-facade.service.js +8 -2
- package/dist/server/modules/sessions/services/session-lifecycle-facade.service.js.map +1 -1
- package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.d.ts +20 -0
- package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js +26 -2
- package/dist/server/modules/sessions/services/session-runtime/__test-utils__/pipeline-harness.js.map +1 -1
- package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.d.ts +5 -1
- package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js +70 -12
- package/dist/server/modules/sessions/services/session-runtime/session-launch-pipeline.service.js.map +1 -1
- package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.d.ts +5 -1
- package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js +68 -10
- package/dist/server/modules/sessions/services/session-runtime/session-restore-pipeline.service.js.map +1 -1
- package/dist/server/modules/sessions/services/sessions-message-pool.service.d.ts +2 -1
- package/dist/server/modules/sessions/services/sessions-message-pool.service.js +63 -28
- package/dist/server/modules/sessions/services/sessions-message-pool.service.js.map +1 -1
- package/dist/server/modules/sessions/services/sessions.service.d.ts +6 -3
- package/dist/server/modules/sessions/services/sessions.service.js +82 -92
- package/dist/server/modules/sessions/services/sessions.service.js.map +1 -1
- package/dist/server/modules/sessions/utils/profile-options.d.ts +1 -0
- package/dist/server/modules/sessions/utils/profile-options.js +7 -0
- package/dist/server/modules/sessions/utils/profile-options.js.map +1 -1
- package/dist/server/modules/storage/db/schema.d.ts +255 -0
- package/dist/server/modules/storage/db/schema.js +34 -3
- package/dist/server/modules/storage/db/schema.js.map +1 -1
- package/dist/server/modules/storage/interfaces/storage.interface.d.ts +15 -3
- package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
- package/dist/server/modules/storage/local/delegates/agent.delegate.d.ts +1 -0
- package/dist/server/modules/storage/local/delegates/agent.delegate.js +43 -1
- package/dist/server/modules/storage/local/delegates/agent.delegate.js.map +1 -1
- package/dist/server/modules/storage/local/delegates/epic.delegate.js +6 -0
- package/dist/server/modules/storage/local/delegates/epic.delegate.js.map +1 -1
- package/dist/server/modules/storage/local/delegates/project.delegate.d.ts +1 -0
- package/dist/server/modules/storage/local/delegates/project.delegate.js +21 -0
- package/dist/server/modules/storage/local/delegates/project.delegate.js.map +1 -1
- package/dist/server/modules/storage/local/delegates/provider-plugin-policy.delegate.d.ts +13 -0
- package/dist/server/modules/storage/local/delegates/provider-plugin-policy.delegate.js +90 -0
- package/dist/server/modules/storage/local/delegates/provider-plugin-policy.delegate.js.map +1 -0
- package/dist/server/modules/storage/local/delegates/review.delegate.d.ts +0 -1
- package/dist/server/modules/storage/local/delegates/review.delegate.js +0 -20
- package/dist/server/modules/storage/local/delegates/review.delegate.js.map +1 -1
- package/dist/server/modules/storage/local/local-storage.service.d.ts +12 -2
- package/dist/server/modules/storage/local/local-storage.service.js +33 -3
- package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
- package/dist/server/modules/storage/models/domain.models.d.ts +26 -5
- package/dist/server/modules/subscribers/actions/restart-agent.action.js +4 -1
- package/dist/server/modules/subscribers/actions/restart-agent.action.js.map +1 -1
- package/dist/server/modules/subscribers/actions/send-message.action.js +47 -12
- package/dist/server/modules/subscribers/actions/send-message.action.js.map +1 -1
- package/dist/server/modules/subscribers/dtos/subscriber.dto.d.ts +231 -23
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js +10 -5
- package/dist/server/modules/subscribers/dtos/subscriber.dto.js.map +1 -1
- package/dist/server/modules/subscribers/events/event-fields-catalog.js +6 -1
- package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -1
- package/dist/server/modules/subscribers/services/subscriber-executor.service.d.ts +3 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js +44 -0
- package/dist/server/modules/subscribers/services/subscriber-executor.service.js.map +1 -1
- package/dist/server/modules/teams/services/teams.service.js +4 -1
- package/dist/server/modules/teams/services/teams.service.js.map +1 -1
- package/dist/server/modules/teams/subscribers/team-membership-changed-notifier.subscriber.js +3 -1
- package/dist/server/modules/teams/subscribers/team-membership-changed-notifier.subscriber.js.map +1 -1
- package/dist/server/modules/terminal/gateways/terminal.gateway.d.ts +0 -6
- package/dist/server/modules/terminal/gateways/terminal.gateway.js +1 -33
- package/dist/server/modules/terminal/gateways/terminal.gateway.js.map +1 -1
- package/dist/server/modules/terminal/services/terminal-io/lifecycle.d.ts +2 -1
- package/dist/server/modules/terminal/services/terminal-io/lifecycle.js +38 -0
- package/dist/server/modules/terminal/services/terminal-io/lifecycle.js.map +1 -1
- package/dist/server/modules/terminal/services/terminal-io/terminal-io.service.d.ts +13 -2
- package/dist/server/modules/terminal/services/terminal-io/terminal-io.service.js +141 -25
- package/dist/server/modules/terminal/services/terminal-io/terminal-io.service.js.map +1 -1
- package/dist/server/modules/terminal/services/terminal-io/types.d.ts +15 -0
- package/dist/server/modules/terminal/services/terminal-registry-rehydrator.service.js +8 -5
- package/dist/server/modules/terminal/services/terminal-registry-rehydrator.service.js.map +1 -1
- package/dist/server/modules/watchers/dtos/watcher.dto.d.ts +2 -2
- package/dist/server/templates/teams-dev.json +157 -104
- package/dist/server/tsconfig.tsbuildinfo +1 -1
- package/dist/server/ui/assets/{ReviewDetailPage-yOe1a_fn.js → ReviewDetailPage-BZoAe0G2.js} +1 -1
- package/dist/server/ui/assets/{ReviewsPage-Bib-IgPo.js → ReviewsPage-J3XZDw7k.js} +1 -1
- package/dist/server/ui/assets/index-CxmSxl5f.css +32 -0
- package/dist/server/ui/assets/index-DoKUmi74.js +1153 -0
- package/dist/server/ui/assets/{useReviewSubscription-BmU3yczR.js → useReviewSubscription-CNUx-AWQ.js} +19 -19
- package/dist/server/ui/index.html +2 -2
- package/dist/templates/teams-dev.json +157 -104
- package/package.json +16 -2
- package/dist/drizzle/PHASE2_MIGRATION_GUIDE.md +0 -109
- package/dist/server/modules/agent-message-delivery/subscribers/chat-message-delivery.subscriber.d.ts +0 -22
- package/dist/server/modules/agent-message-delivery/subscribers/chat-message-delivery.subscriber.js +0 -64
- package/dist/server/modules/agent-message-delivery/subscribers/chat-message-delivery.subscriber.js.map +0 -1
- package/dist/server/modules/chat/chat.module.d.ts +0 -2
- package/dist/server/modules/chat/chat.module.js +0 -38
- package/dist/server/modules/chat/chat.module.js.map +0 -1
- package/dist/server/modules/chat/controllers/chat-settings.controller.d.ts +0 -8
- package/dist/server/modules/chat/controllers/chat-settings.controller.js +0 -67
- package/dist/server/modules/chat/controllers/chat-settings.controller.js.map +0 -1
- package/dist/server/modules/chat/controllers/chat.controller.d.ts +0 -15
- package/dist/server/modules/chat/controllers/chat.controller.js +0 -153
- package/dist/server/modules/chat/controllers/chat.controller.js.map +0 -1
- package/dist/server/modules/chat/dtos/chat-settings.dto.d.ts +0 -31
- package/dist/server/modules/chat/dtos/chat-settings.dto.js +0 -17
- package/dist/server/modules/chat/dtos/chat-settings.dto.js.map +0 -1
- package/dist/server/modules/chat/dtos/chat.dto.d.ts +0 -309
- package/dist/server/modules/chat/dtos/chat.dto.js +0 -80
- package/dist/server/modules/chat/dtos/chat.dto.js.map +0 -1
- package/dist/server/modules/chat/services/chat-session-invite.service.d.ts +0 -16
- package/dist/server/modules/chat/services/chat-session-invite.service.js +0 -200
- package/dist/server/modules/chat/services/chat-session-invite.service.js.map +0 -1
- package/dist/server/modules/chat/services/chat-settings.service.d.ts +0 -12
- package/dist/server/modules/chat/services/chat-settings.service.js +0 -123
- package/dist/server/modules/chat/services/chat-settings.service.js.map +0 -1
- package/dist/server/modules/chat/services/chat.service.d.ts +0 -47
- package/dist/server/modules/chat/services/chat.service.js +0 -693
- package/dist/server/modules/chat/services/chat.service.js.map +0 -1
- package/dist/server/modules/chat/services/invite-template.util.d.ts +0 -17
- package/dist/server/modules/chat/services/invite-template.util.js +0 -70
- package/dist/server/modules/chat/services/invite-template.util.js.map +0 -1
- package/dist/server/modules/events/catalog/chat.message.read.d.ts +0 -21
- package/dist/server/modules/events/catalog/chat.message.read.js +0 -14
- package/dist/server/modules/events/catalog/chat.message.read.js.map +0 -1
- package/dist/server/modules/mcp/services/handlers/activity-context.d.ts +0 -6
- package/dist/server/modules/mcp/services/handlers/activity-context.js.map +0 -1
- package/dist/server/modules/mcp/services/handlers/activity-tools.d.ts +0 -4
- package/dist/server/modules/mcp/services/handlers/activity-tools.js +0 -179
- package/dist/server/modules/mcp/services/handlers/activity-tools.js.map +0 -1
- package/dist/server/modules/mcp/tool-descriptors/activity.bindings.d.ts +0 -2
- package/dist/server/modules/mcp/tool-descriptors/activity.bindings.js +0 -9
- package/dist/server/modules/mcp/tool-descriptors/activity.bindings.js.map +0 -1
- package/dist/server/modules/mcp/tool-descriptors/activity.metadata.d.ts +0 -2
- package/dist/server/modules/mcp/tool-descriptors/activity.metadata.js +0 -49
- package/dist/server/modules/mcp/tool-descriptors/activity.metadata.js.map +0 -1
- package/dist/server/ui/assets/index-B2TO-QTO.js +0 -1156
- package/dist/server/ui/assets/index-DowJ3ZtQ.css +0 -32
package/dist/server/modules/runtime-context-capture/codex-plugin-profile-materializer.service.js
ADDED
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.CODEX_PROFILE_HELPER_SOURCE = exports.CodexPluginProfileMaterializerService = exports.CODEX_PLUGIN_PROFILE_ROOT = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const crypto_1 = require("crypto");
|
|
18
|
+
const fs_1 = require("fs");
|
|
19
|
+
const promises_1 = require("fs/promises");
|
|
20
|
+
const path_1 = require("path");
|
|
21
|
+
const error_types_1 = require("../../common/errors/error-types");
|
|
22
|
+
const runtime_context_capture_files_1 = require("./runtime-context-capture-files");
|
|
23
|
+
const PRIVATE_DIRECTORY_MODE = 0o700;
|
|
24
|
+
const PRIVATE_FILE_MODE = 0o600;
|
|
25
|
+
const EXECUTABLE_FILE_MODE = 0o700;
|
|
26
|
+
const MAX_PLUGIN_ID_LENGTH = 512;
|
|
27
|
+
const MAX_PROJECT_SLUG_LENGTH = 64;
|
|
28
|
+
const ASCII_CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
|
|
29
|
+
const PROFILE_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]{0,254}$/;
|
|
30
|
+
const DIGEST_PATTERN = /^[0-9a-f]{64}$/;
|
|
31
|
+
const NONCE_PATTERN = /^[A-Za-z0-9_-]{16,128}$/;
|
|
32
|
+
exports.CODEX_PLUGIN_PROFILE_ROOT = Symbol('CODEX_PLUGIN_PROFILE_ROOT');
|
|
33
|
+
const CODEX_PROFILE_HELPER_SOURCE = String.raw `#!/usr/bin/env node
|
|
34
|
+
"use strict";
|
|
35
|
+
|
|
36
|
+
const crypto = require("crypto");
|
|
37
|
+
const fs = require("fs");
|
|
38
|
+
const path = require("path");
|
|
39
|
+
|
|
40
|
+
const DIRECTORY_MODE = 0o700;
|
|
41
|
+
const FILE_MODE = 0o600;
|
|
42
|
+
const PROFILE_NAME = /^[a-z0-9][a-z0-9_-]{0,254}$/;
|
|
43
|
+
const DIGEST = /^[0-9a-f]{64}$/;
|
|
44
|
+
const NONCE = /^[A-Za-z0-9_-]{16,128}$/;
|
|
45
|
+
|
|
46
|
+
function fail(code) {
|
|
47
|
+
process.stderr.write("DEVCHAIN_CODEX_PROFILE_ERROR:" + code + "\n");
|
|
48
|
+
process.exit(78);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function parseArguments(argv) {
|
|
52
|
+
const separator = argv.indexOf("--");
|
|
53
|
+
if (separator === -1) fail("invalid_arguments");
|
|
54
|
+
const control = argv.slice(0, separator);
|
|
55
|
+
const codexArgs = argv.slice(separator + 1);
|
|
56
|
+
const values = Object.create(null);
|
|
57
|
+
for (let index = 0; index < control.length; index += 2) {
|
|
58
|
+
const flag = control[index];
|
|
59
|
+
const value = control[index + 1];
|
|
60
|
+
if (!flag || !flag.startsWith("--") || value === undefined || values[flag] !== undefined) {
|
|
61
|
+
fail("invalid_arguments");
|
|
62
|
+
}
|
|
63
|
+
values[flag] = value;
|
|
64
|
+
}
|
|
65
|
+
const required = [
|
|
66
|
+
"--source",
|
|
67
|
+
"--profile",
|
|
68
|
+
"--project-id",
|
|
69
|
+
"--session-id",
|
|
70
|
+
"--project-digest",
|
|
71
|
+
"--policy-hash",
|
|
72
|
+
"--reference",
|
|
73
|
+
"--locator",
|
|
74
|
+
"--ack",
|
|
75
|
+
"--nonce",
|
|
76
|
+
"--codex-bin"
|
|
77
|
+
];
|
|
78
|
+
if (Object.keys(values).length !== required.length || required.some((flag) => !values[flag])) {
|
|
79
|
+
fail("invalid_arguments");
|
|
80
|
+
}
|
|
81
|
+
return { values, codexArgs };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function sha256(content) {
|
|
85
|
+
return crypto.createHash("sha256").update(content, "utf8").digest("hex");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function ensureDirectory(directory) {
|
|
89
|
+
fs.mkdirSync(directory, { recursive: true, mode: DIRECTORY_MODE });
|
|
90
|
+
const stat = fs.lstatSync(directory);
|
|
91
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) fail("unsafe_private_root");
|
|
92
|
+
fs.chmodSync(directory, DIRECTORY_MODE);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ensureCodexHome(directory) {
|
|
96
|
+
fs.mkdirSync(directory, { recursive: true, mode: DIRECTORY_MODE });
|
|
97
|
+
const resolved = fs.realpathSync(directory);
|
|
98
|
+
if (!fs.statSync(resolved).isDirectory()) fail("invalid_codex_home");
|
|
99
|
+
return resolved;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function containedRegularFile(candidate, directory, code) {
|
|
103
|
+
const resolvedDirectory = fs.realpathSync(directory);
|
|
104
|
+
const resolvedCandidate = fs.realpathSync(candidate);
|
|
105
|
+
if (
|
|
106
|
+
path.dirname(resolvedCandidate) !== resolvedDirectory ||
|
|
107
|
+
!fs.lstatSync(resolvedCandidate).isFile() ||
|
|
108
|
+
fs.lstatSync(candidate).isSymbolicLink()
|
|
109
|
+
) {
|
|
110
|
+
fail(code);
|
|
111
|
+
}
|
|
112
|
+
return resolvedCandidate;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function containedDestination(candidate, directory, suffix, code) {
|
|
116
|
+
const resolvedDirectory = fs.realpathSync(directory);
|
|
117
|
+
const resolvedCandidate = path.resolve(candidate);
|
|
118
|
+
if (
|
|
119
|
+
path.dirname(resolvedCandidate) !== resolvedDirectory ||
|
|
120
|
+
!path.basename(resolvedCandidate).endsWith(suffix)
|
|
121
|
+
) {
|
|
122
|
+
fail(code);
|
|
123
|
+
}
|
|
124
|
+
return resolvedCandidate;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function writeExclusive(destination, content) {
|
|
128
|
+
const temporary = destination + ".tmp-" + process.pid + "-" + crypto.randomUUID();
|
|
129
|
+
let descriptor;
|
|
130
|
+
try {
|
|
131
|
+
descriptor = fs.openSync(temporary, "wx", FILE_MODE);
|
|
132
|
+
fs.writeFileSync(descriptor, content, { encoding: "utf8" });
|
|
133
|
+
fs.fsyncSync(descriptor);
|
|
134
|
+
fs.closeSync(descriptor);
|
|
135
|
+
descriptor = undefined;
|
|
136
|
+
try {
|
|
137
|
+
fs.linkSync(temporary, destination);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
if (!error || error.code !== "EEXIST") throw error;
|
|
140
|
+
fail("lifecycle_collision");
|
|
141
|
+
}
|
|
142
|
+
fs.chmodSync(destination, FILE_MODE);
|
|
143
|
+
} finally {
|
|
144
|
+
if (descriptor !== undefined) {
|
|
145
|
+
try { fs.closeSync(descriptor); } catch {}
|
|
146
|
+
}
|
|
147
|
+
try { fs.unlinkSync(temporary); } catch {}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function processStartIdentity(pid) {
|
|
152
|
+
try {
|
|
153
|
+
const value = fs.readFileSync("/proc/" + pid + "/stat", "utf8");
|
|
154
|
+
const fields = value.slice(value.lastIndexOf(")") + 2).trim().split(/\s+/);
|
|
155
|
+
return fields[19] || null;
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error && (error.code === "ENOENT" || error.code === "ESRCH")) return false;
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function sleep(milliseconds) {
|
|
163
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function acquireTargetLock(locksRoot, canonicalTargetPath, attemptNonce) {
|
|
167
|
+
const lockKey = sha256(canonicalTargetPath);
|
|
168
|
+
const lockPath = path.join(locksRoot, lockKey + ".lock");
|
|
169
|
+
const deadline = Date.now() + 5000;
|
|
170
|
+
while (Date.now() < deadline) {
|
|
171
|
+
try {
|
|
172
|
+
fs.mkdirSync(lockPath, { mode: DIRECTORY_MODE });
|
|
173
|
+
const startIdentity = processStartIdentity(process.pid);
|
|
174
|
+
if (typeof startIdentity !== "string") fail("process_identity_unavailable");
|
|
175
|
+
fs.writeFileSync(
|
|
176
|
+
path.join(lockPath, "owner.json"),
|
|
177
|
+
JSON.stringify({ version: 1, pid: process.pid, startIdentity, attemptNonce }),
|
|
178
|
+
{ encoding: "utf8", mode: FILE_MODE, flag: "wx" }
|
|
179
|
+
);
|
|
180
|
+
return {
|
|
181
|
+
lockKey,
|
|
182
|
+
release() {
|
|
183
|
+
try { fs.rmSync(lockPath, { recursive: true, force: true }); } catch {}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (!error || error.code !== "EEXIST") fail("lock_failure");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let owner;
|
|
191
|
+
try {
|
|
192
|
+
owner = JSON.parse(fs.readFileSync(path.join(lockPath, "owner.json"), "utf8"));
|
|
193
|
+
} catch {
|
|
194
|
+
sleep(25);
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const actual = Number.isSafeInteger(owner.pid) ? processStartIdentity(owner.pid) : null;
|
|
198
|
+
if (actual === false || (typeof actual === "string" && actual !== owner.startIdentity)) {
|
|
199
|
+
const stalePath = lockPath + ".stale-" + process.pid + "-" + crypto.randomUUID();
|
|
200
|
+
try {
|
|
201
|
+
fs.renameSync(lockPath, stalePath);
|
|
202
|
+
fs.rmSync(stalePath, { recursive: true, force: true });
|
|
203
|
+
continue;
|
|
204
|
+
} catch {
|
|
205
|
+
sleep(25);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
sleep(25);
|
|
210
|
+
}
|
|
211
|
+
fail("lock_timeout");
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function writeOrValidateMarker(markerPath, marker) {
|
|
215
|
+
try {
|
|
216
|
+
const metadata = fs.lstatSync(markerPath);
|
|
217
|
+
if (!metadata.isFile() || metadata.isSymbolicLink()) fail("unsafe_target_marker");
|
|
218
|
+
const existing = JSON.parse(fs.readFileSync(markerPath, "utf8"));
|
|
219
|
+
if (
|
|
220
|
+
existing.canonicalTargetPath !== marker.canonicalTargetPath ||
|
|
221
|
+
existing.profileName !== marker.profileName ||
|
|
222
|
+
existing.policyHash !== marker.policyHash
|
|
223
|
+
) {
|
|
224
|
+
fail("target_marker_mismatch");
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
if (!error || error.code !== "ENOENT") throw error;
|
|
229
|
+
}
|
|
230
|
+
writeExclusive(markerPath, JSON.stringify(marker));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function materializeProfile(destination, content) {
|
|
234
|
+
try {
|
|
235
|
+
const stat = fs.lstatSync(destination);
|
|
236
|
+
if (!stat.isFile() || stat.isSymbolicLink()) fail("unsafe_profile_target");
|
|
237
|
+
if (fs.readFileSync(destination, "utf8") !== content) fail("profile_content_mismatch");
|
|
238
|
+
fs.chmodSync(destination, FILE_MODE);
|
|
239
|
+
return;
|
|
240
|
+
} catch (error) {
|
|
241
|
+
if (!error || error.code !== "ENOENT") throw error;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const temporary = destination + ".tmp-" + process.pid + "-" + crypto.randomUUID();
|
|
245
|
+
let descriptor;
|
|
246
|
+
try {
|
|
247
|
+
descriptor = fs.openSync(temporary, "wx", FILE_MODE);
|
|
248
|
+
fs.writeFileSync(descriptor, content, { encoding: "utf8" });
|
|
249
|
+
fs.fsyncSync(descriptor);
|
|
250
|
+
fs.closeSync(descriptor);
|
|
251
|
+
descriptor = undefined;
|
|
252
|
+
try {
|
|
253
|
+
fs.linkSync(temporary, destination);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
if (!error || error.code !== "EEXIST") throw error;
|
|
256
|
+
const stat = fs.lstatSync(destination);
|
|
257
|
+
if (
|
|
258
|
+
!stat.isFile() ||
|
|
259
|
+
stat.isSymbolicLink() ||
|
|
260
|
+
fs.readFileSync(destination, "utf8") !== content
|
|
261
|
+
) {
|
|
262
|
+
fail("profile_content_mismatch");
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
fs.chmodSync(destination, FILE_MODE);
|
|
266
|
+
} finally {
|
|
267
|
+
if (descriptor !== undefined) {
|
|
268
|
+
try { fs.closeSync(descriptor); } catch {}
|
|
269
|
+
}
|
|
270
|
+
try { fs.unlinkSync(temporary); } catch {}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function resolveExecutable(binary) {
|
|
275
|
+
if (path.isAbsolute(binary)) {
|
|
276
|
+
try { fs.accessSync(binary, fs.constants.X_OK); } catch { fail("codex_binary_unavailable"); }
|
|
277
|
+
return binary;
|
|
278
|
+
}
|
|
279
|
+
if (binary.includes("/") || binary.includes("\\") || binary.length === 0) {
|
|
280
|
+
fail("invalid_codex_binary");
|
|
281
|
+
}
|
|
282
|
+
for (const entry of (process.env.PATH || "").split(path.delimiter)) {
|
|
283
|
+
const candidate = path.resolve(entry || process.cwd(), binary);
|
|
284
|
+
try {
|
|
285
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
286
|
+
if (fs.statSync(candidate).isFile()) return candidate;
|
|
287
|
+
} catch {}
|
|
288
|
+
}
|
|
289
|
+
fail("codex_binary_unavailable");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function main() {
|
|
293
|
+
const { values, codexArgs } = parseArguments(process.argv.slice(2));
|
|
294
|
+
const profileName = values["--profile"];
|
|
295
|
+
const projectDigest = values["--project-digest"];
|
|
296
|
+
const policyHash = values["--policy-hash"];
|
|
297
|
+
const nonce = values["--nonce"];
|
|
298
|
+
if (!PROFILE_NAME.test(profileName)) fail("invalid_profile_name");
|
|
299
|
+
if (!DIGEST.test(projectDigest) || !DIGEST.test(policyHash)) fail("invalid_digest");
|
|
300
|
+
if (!NONCE.test(nonce)) fail("invalid_nonce");
|
|
301
|
+
if (sha256(values["--project-id"]) !== projectDigest) fail("project_digest_mismatch");
|
|
302
|
+
if (!profileName.endsWith("-" + projectDigest.slice(0, 16) + "-" + policyHash)) {
|
|
303
|
+
fail("profile_identity_mismatch");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const privateRoot = path.dirname(path.dirname(fs.realpathSync(__filename)));
|
|
307
|
+
const sourceRoot = path.join(privateRoot, "source-revisions");
|
|
308
|
+
const lifecycleRoot = path.join(privateRoot, "lifecycle");
|
|
309
|
+
const locksRoot = path.join(privateRoot, "locks");
|
|
310
|
+
const targetsRoot = path.join(privateRoot, "targets");
|
|
311
|
+
ensureDirectory(sourceRoot);
|
|
312
|
+
ensureDirectory(lifecycleRoot);
|
|
313
|
+
ensureDirectory(locksRoot);
|
|
314
|
+
ensureDirectory(targetsRoot);
|
|
315
|
+
const sourcePath = containedRegularFile(values["--source"], sourceRoot, "unsafe_source_path");
|
|
316
|
+
if (path.basename(sourcePath) !== profileName + ".config.toml") fail("source_identity_mismatch");
|
|
317
|
+
const referencePath = containedDestination(
|
|
318
|
+
values["--reference"],
|
|
319
|
+
lifecycleRoot,
|
|
320
|
+
".reference.json",
|
|
321
|
+
"unsafe_reference_path"
|
|
322
|
+
);
|
|
323
|
+
const locatorPath = containedDestination(
|
|
324
|
+
values["--locator"],
|
|
325
|
+
lifecycleRoot,
|
|
326
|
+
".locator.json",
|
|
327
|
+
"unsafe_locator_path"
|
|
328
|
+
);
|
|
329
|
+
const acknowledgementPath = containedDestination(
|
|
330
|
+
values["--ack"],
|
|
331
|
+
lifecycleRoot,
|
|
332
|
+
".ack.json",
|
|
333
|
+
"unsafe_ack_path"
|
|
334
|
+
);
|
|
335
|
+
const attemptKey = sha256(values["--project-id"] + "\0" + nonce);
|
|
336
|
+
if (referencePath !== path.join(lifecycleRoot, attemptKey + ".reference.json")) {
|
|
337
|
+
fail("reference_identity_mismatch");
|
|
338
|
+
}
|
|
339
|
+
if (acknowledgementPath !== path.join(lifecycleRoot, attemptKey + ".ack.json")) {
|
|
340
|
+
fail("ack_identity_mismatch");
|
|
341
|
+
}
|
|
342
|
+
if (locatorPath !== path.join(lifecycleRoot, attemptKey + ".locator.json")) {
|
|
343
|
+
fail("locator_identity_mismatch");
|
|
344
|
+
}
|
|
345
|
+
const content = fs.readFileSync(sourcePath, "utf8");
|
|
346
|
+
if (sha256(content) !== policyHash) fail("source_hash_mismatch");
|
|
347
|
+
|
|
348
|
+
const configuredHome = process.env.CODEX_HOME;
|
|
349
|
+
const inheritedHome = process.env.HOME;
|
|
350
|
+
const homeCandidate = configuredHome && configuredHome.length > 0
|
|
351
|
+
? configuredHome
|
|
352
|
+
: inheritedHome && inheritedHome.length > 0
|
|
353
|
+
? path.join(inheritedHome, ".codex")
|
|
354
|
+
: null;
|
|
355
|
+
if (!homeCandidate) fail("codex_home_unavailable");
|
|
356
|
+
const codexHome = ensureCodexHome(path.resolve(homeCandidate));
|
|
357
|
+
const canonicalTargetPath = path.join(codexHome, profileName + ".config.toml");
|
|
358
|
+
if (path.dirname(canonicalTargetPath) !== codexHome) fail("profile_path_escape");
|
|
359
|
+
const codexBinary = resolveExecutable(values["--codex-bin"]);
|
|
360
|
+
if (typeof process.execve !== "function") fail("exec_unavailable");
|
|
361
|
+
const targetLock = acquireTargetLock(locksRoot, canonicalTargetPath, nonce);
|
|
362
|
+
try {
|
|
363
|
+
materializeProfile(canonicalTargetPath, content);
|
|
364
|
+
if (sha256(fs.readFileSync(canonicalTargetPath, "utf8")) !== policyHash) {
|
|
365
|
+
fail("target_hash_mismatch");
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const acknowledgement = {
|
|
369
|
+
version: 1,
|
|
370
|
+
canonicalTargetPath,
|
|
371
|
+
projectId: values["--project-id"],
|
|
372
|
+
sessionId: values["--session-id"],
|
|
373
|
+
projectDigest,
|
|
374
|
+
profileName,
|
|
375
|
+
policyHash,
|
|
376
|
+
nonce
|
|
377
|
+
};
|
|
378
|
+
const markerPath = path.join(targetsRoot, targetLock.lockKey + ".target.json");
|
|
379
|
+
writeOrValidateMarker(markerPath, acknowledgement);
|
|
380
|
+
writeExclusive(referencePath, JSON.stringify({
|
|
381
|
+
...acknowledgement,
|
|
382
|
+
acknowledgementPath,
|
|
383
|
+
locatorPath
|
|
384
|
+
}));
|
|
385
|
+
writeExclusive(locatorPath, JSON.stringify({
|
|
386
|
+
...acknowledgement,
|
|
387
|
+
referencePath,
|
|
388
|
+
acknowledgementPath,
|
|
389
|
+
markerPath,
|
|
390
|
+
lockKey: targetLock.lockKey
|
|
391
|
+
}));
|
|
392
|
+
writeExclusive(acknowledgementPath, JSON.stringify(acknowledgement));
|
|
393
|
+
} finally {
|
|
394
|
+
targetLock.release();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
process.execve(codexBinary, [values["--codex-bin"], ...codexArgs], process.env);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
try {
|
|
401
|
+
main();
|
|
402
|
+
} catch {
|
|
403
|
+
fail("internal_failure");
|
|
404
|
+
}
|
|
405
|
+
`;
|
|
406
|
+
exports.CODEX_PROFILE_HELPER_SOURCE = CODEX_PROFILE_HELPER_SOURCE;
|
|
407
|
+
let CodexPluginProfileMaterializerService = class CodexPluginProfileMaterializerService {
|
|
408
|
+
rootPath;
|
|
409
|
+
constructor(rootPath) {
|
|
410
|
+
this.rootPath = (0, path_1.resolve)(rootPath ?? (0, path_1.join)((0, runtime_context_capture_files_1.getRuntimeContextCaptureRoot)(), 'codex-plugin-profiles'));
|
|
411
|
+
}
|
|
412
|
+
async prepare(input) {
|
|
413
|
+
if (input.pluginPolicy.length === 0)
|
|
414
|
+
return null;
|
|
415
|
+
this.validateIdentity(input);
|
|
416
|
+
const profileToml = this.serializePolicy(input.pluginPolicy);
|
|
417
|
+
const projectDigest = this.sha256(input.projectId);
|
|
418
|
+
const policyHash = this.sha256(profileToml);
|
|
419
|
+
const projectSlug = this.toProjectSlug(input.projectName);
|
|
420
|
+
const profileName = `devchain-${projectSlug}-${projectDigest.slice(0, 16)}-${policyHash}`;
|
|
421
|
+
if (!PROFILE_NAME_PATTERN.test(profileName) || profileName.length > 255) {
|
|
422
|
+
throw new error_types_1.ValidationError('Codex plugin profile name is not filesystem-safe.', {
|
|
423
|
+
field: 'projectName',
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
const sourceRoot = (0, path_1.join)(this.rootPath, 'source-revisions');
|
|
427
|
+
const helperRoot = (0, path_1.join)(this.rootPath, 'bin');
|
|
428
|
+
const lifecycleRoot = (0, path_1.join)(this.rootPath, 'lifecycle');
|
|
429
|
+
const locksRoot = (0, path_1.join)(this.rootPath, 'locks');
|
|
430
|
+
const targetsRoot = (0, path_1.join)(this.rootPath, 'targets');
|
|
431
|
+
await Promise.all([
|
|
432
|
+
this.ensurePrivateDirectory(this.rootPath),
|
|
433
|
+
this.ensurePrivateDirectory(sourceRoot),
|
|
434
|
+
this.ensurePrivateDirectory(helperRoot),
|
|
435
|
+
this.ensurePrivateDirectory(lifecycleRoot),
|
|
436
|
+
this.ensurePrivateDirectory(locksRoot),
|
|
437
|
+
this.ensurePrivateDirectory(targetsRoot),
|
|
438
|
+
]);
|
|
439
|
+
const helperHash = this.sha256(CODEX_PROFILE_HELPER_SOURCE);
|
|
440
|
+
const sourceRevisionPath = (0, path_1.join)(sourceRoot, `${profileName}.config.toml`);
|
|
441
|
+
const helperPath = (0, path_1.join)(helperRoot, `devchain-codex-profile-helper-${helperHash}`);
|
|
442
|
+
const attemptKey = this.sha256(`${input.projectId}\0${input.attemptNonce}`);
|
|
443
|
+
const referencePath = (0, path_1.join)(lifecycleRoot, `${attemptKey}.reference.json`);
|
|
444
|
+
const locatorPath = (0, path_1.join)(lifecycleRoot, `${attemptKey}.locator.json`);
|
|
445
|
+
const acknowledgementPath = (0, path_1.join)(lifecycleRoot, `${attemptKey}.ack.json`);
|
|
446
|
+
await Promise.all([
|
|
447
|
+
this.materializeImmutable(sourceRevisionPath, profileToml, PRIVATE_FILE_MODE),
|
|
448
|
+
this.materializeImmutable(helperPath, CODEX_PROFILE_HELPER_SOURCE, EXECUTABLE_FILE_MODE),
|
|
449
|
+
]);
|
|
450
|
+
return {
|
|
451
|
+
profileName,
|
|
452
|
+
projectDigest,
|
|
453
|
+
policyHash,
|
|
454
|
+
sourceRevisionPath,
|
|
455
|
+
helperPath,
|
|
456
|
+
sessionId: input.sessionId,
|
|
457
|
+
attemptNonce: input.attemptNonce,
|
|
458
|
+
referencePath,
|
|
459
|
+
locatorPath,
|
|
460
|
+
acknowledgementPath,
|
|
461
|
+
providerOptionArgs: ['--profile', profileName],
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
buildHelperArgv(prepared, codexBinary, codexArgv, input) {
|
|
465
|
+
this.validateCodexBinary(codexBinary);
|
|
466
|
+
if (!PROFILE_NAME_PATTERN.test(prepared.profileName)) {
|
|
467
|
+
throw new error_types_1.ValidationError('Codex plugin profile name is not filesystem-safe.', {
|
|
468
|
+
field: 'profileName',
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
if (!DIGEST_PATTERN.test(prepared.projectDigest) || !DIGEST_PATTERN.test(prepared.policyHash)) {
|
|
472
|
+
throw new error_types_1.ValidationError('Codex plugin profile digests are invalid.', {
|
|
473
|
+
field: 'policyHash',
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
if (!NONCE_PATTERN.test(input.attemptNonce)) {
|
|
477
|
+
throw new error_types_1.ValidationError('Codex plugin profile attempt nonce is invalid.', {
|
|
478
|
+
field: 'attemptNonce',
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
if (codexArgv.some((argument) => typeof argument !== 'string' || argument.includes('\0'))) {
|
|
482
|
+
throw new error_types_1.ValidationError('Codex launch arguments are invalid.', { field: 'codexArgv' });
|
|
483
|
+
}
|
|
484
|
+
return [
|
|
485
|
+
prepared.helperPath,
|
|
486
|
+
'--source',
|
|
487
|
+
prepared.sourceRevisionPath,
|
|
488
|
+
'--profile',
|
|
489
|
+
prepared.profileName,
|
|
490
|
+
'--project-id',
|
|
491
|
+
input.projectId,
|
|
492
|
+
'--session-id',
|
|
493
|
+
prepared.sessionId,
|
|
494
|
+
'--project-digest',
|
|
495
|
+
prepared.projectDigest,
|
|
496
|
+
'--policy-hash',
|
|
497
|
+
prepared.policyHash,
|
|
498
|
+
'--reference',
|
|
499
|
+
prepared.referencePath,
|
|
500
|
+
'--locator',
|
|
501
|
+
prepared.locatorPath,
|
|
502
|
+
'--ack',
|
|
503
|
+
prepared.acknowledgementPath,
|
|
504
|
+
'--nonce',
|
|
505
|
+
input.attemptNonce,
|
|
506
|
+
'--codex-bin',
|
|
507
|
+
codexBinary,
|
|
508
|
+
'--',
|
|
509
|
+
...codexArgv,
|
|
510
|
+
];
|
|
511
|
+
}
|
|
512
|
+
async awaitAcknowledgement(prepared, input, timeoutMs = 5_000) {
|
|
513
|
+
const deadline = Date.now() + timeoutMs;
|
|
514
|
+
while (Date.now() <= deadline) {
|
|
515
|
+
const acknowledgement = await this.readJsonFile(prepared.acknowledgementPath);
|
|
516
|
+
if (acknowledgement) {
|
|
517
|
+
const locator = await this.readJsonFile(prepared.locatorPath);
|
|
518
|
+
if (!locator) {
|
|
519
|
+
throw new error_types_1.IOError('Codex profile acknowledgement has no matching locator.', {
|
|
520
|
+
stage: 'profile_acknowledgement',
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
this.assertAcknowledgement(acknowledgement, prepared, input);
|
|
524
|
+
this.assertAcknowledgement(locator, prepared, input);
|
|
525
|
+
if (locator.canonicalTargetPath !== acknowledgement.canonicalTargetPath ||
|
|
526
|
+
locator.referencePath !== prepared.referencePath ||
|
|
527
|
+
locator.acknowledgementPath !== prepared.acknowledgementPath ||
|
|
528
|
+
locator.lockKey !== this.sha256(locator.canonicalTargetPath)) {
|
|
529
|
+
throw new error_types_1.IOError('Codex profile locator does not match its launch attempt.', {
|
|
530
|
+
stage: 'profile_locator',
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return acknowledgement.canonicalTargetPath;
|
|
534
|
+
}
|
|
535
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, 25));
|
|
536
|
+
}
|
|
537
|
+
throw new error_types_1.TimeoutError('Timed out waiting for Codex profile acknowledgement.', {
|
|
538
|
+
stage: 'profile_acknowledgement',
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
async cleanupPrepared(prepared) {
|
|
542
|
+
const locator = await this.readJsonFile(prepared.locatorPath);
|
|
543
|
+
if (!locator) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
await this.cleanupLocator(prepared.locatorPath, locator);
|
|
547
|
+
}
|
|
548
|
+
async cleanupSession(sessionId) {
|
|
549
|
+
await this.cleanupLifecycleLocators((locator) => locator.sessionId === sessionId);
|
|
550
|
+
}
|
|
551
|
+
async reconcileStartup(nonLiveSessionIds) {
|
|
552
|
+
await this.cleanupLifecycleLocators((locator) => nonLiveSessionIds.has(locator.sessionId));
|
|
553
|
+
}
|
|
554
|
+
serializePolicy(policy) {
|
|
555
|
+
const byPluginId = new Map();
|
|
556
|
+
for (const entry of policy) {
|
|
557
|
+
this.validatePolicyEntry(entry);
|
|
558
|
+
if (byPluginId.has(entry.pluginId)) {
|
|
559
|
+
throw new error_types_1.ValidationError('Resolved Codex plugin policy contains duplicate plugin IDs.', {
|
|
560
|
+
field: 'pluginPolicy',
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
byPluginId.set(entry.pluginId, entry.enabled);
|
|
564
|
+
}
|
|
565
|
+
return [...byPluginId.entries()]
|
|
566
|
+
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
|
|
567
|
+
.map(([pluginId, enabled]) => `[plugins.${JSON.stringify(pluginId)}]\nenabled = ${enabled ? 'true' : 'false'}\n`)
|
|
568
|
+
.join('\n');
|
|
569
|
+
}
|
|
570
|
+
async cleanupLifecycleLocators(predicate) {
|
|
571
|
+
const lifecycleRoot = (0, path_1.join)(this.rootPath, 'lifecycle');
|
|
572
|
+
let entries;
|
|
573
|
+
try {
|
|
574
|
+
entries = await (0, promises_1.readdir)(lifecycleRoot, { withFileTypes: true });
|
|
575
|
+
}
|
|
576
|
+
catch (error) {
|
|
577
|
+
if (error.code === 'ENOENT')
|
|
578
|
+
return;
|
|
579
|
+
throw error;
|
|
580
|
+
}
|
|
581
|
+
for (const entry of entries) {
|
|
582
|
+
if (!entry.isFile() || !entry.name.endsWith('.locator.json'))
|
|
583
|
+
continue;
|
|
584
|
+
const locatorPath = (0, path_1.join)(lifecycleRoot, entry.name);
|
|
585
|
+
const locator = await this.readJsonFile(locatorPath);
|
|
586
|
+
if (!locator || !predicate(locator))
|
|
587
|
+
continue;
|
|
588
|
+
await this.cleanupLocator(locatorPath, locator);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
async cleanupLocator(locatorPath, locator) {
|
|
592
|
+
if (!(0, path_1.isAbsolute)(locator.canonicalTargetPath) ||
|
|
593
|
+
locator.lockKey !== this.sha256(locator.canonicalTargetPath) ||
|
|
594
|
+
locatorPath !==
|
|
595
|
+
(0, path_1.join)(this.rootPath, 'lifecycle', `${this.sha256(`${locator.projectId}\0${locator.nonce}`)}.locator.json`) ||
|
|
596
|
+
locator.referencePath !== locatorPath.replace(/\.locator\.json$/, '.reference.json') ||
|
|
597
|
+
locator.acknowledgementPath !== locatorPath.replace(/\.locator\.json$/, '.ack.json') ||
|
|
598
|
+
locator.markerPath !== (0, path_1.join)(this.rootPath, 'targets', `${locator.lockKey}.target.json`)) {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
const release = await this.acquireTargetLock(locator.canonicalTargetPath, `cleanup:${locator.nonce}`);
|
|
602
|
+
try {
|
|
603
|
+
await (0, promises_1.rm)(locator.referencePath, { force: true });
|
|
604
|
+
if (!(await this.hasLiveReference(locator.canonicalTargetPath))) {
|
|
605
|
+
const marker = await this.readJsonFile(locator.markerPath);
|
|
606
|
+
const targetHash = await this.hashRegularFile(locator.canonicalTargetPath);
|
|
607
|
+
if (marker &&
|
|
608
|
+
marker.canonicalTargetPath === locator.canonicalTargetPath &&
|
|
609
|
+
marker.profileName === locator.profileName &&
|
|
610
|
+
marker.policyHash === locator.policyHash &&
|
|
611
|
+
targetHash === locator.policyHash) {
|
|
612
|
+
await (0, promises_1.rm)(locator.canonicalTargetPath, { force: true });
|
|
613
|
+
await (0, promises_1.rm)(locator.markerPath, { force: true });
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
finally {
|
|
618
|
+
await release();
|
|
619
|
+
}
|
|
620
|
+
await Promise.all([
|
|
621
|
+
(0, promises_1.rm)(locator.acknowledgementPath, { force: true }),
|
|
622
|
+
(0, promises_1.rm)(locatorPath, { force: true }),
|
|
623
|
+
]);
|
|
624
|
+
}
|
|
625
|
+
async hasLiveReference(canonicalTargetPath) {
|
|
626
|
+
const lifecycleRoot = (0, path_1.join)(this.rootPath, 'lifecycle');
|
|
627
|
+
const entries = await (0, promises_1.readdir)(lifecycleRoot, { withFileTypes: true });
|
|
628
|
+
for (const entry of entries) {
|
|
629
|
+
if (!entry.isFile() || !entry.name.endsWith('.reference.json'))
|
|
630
|
+
continue;
|
|
631
|
+
const reference = await this.readJsonFile((0, path_1.join)(lifecycleRoot, entry.name));
|
|
632
|
+
if (!reference || reference.canonicalTargetPath === canonicalTargetPath)
|
|
633
|
+
return true;
|
|
634
|
+
}
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
637
|
+
async acquireTargetLock(canonicalTargetPath, attemptNonce) {
|
|
638
|
+
const locksRoot = (0, path_1.join)(this.rootPath, 'locks');
|
|
639
|
+
await this.ensurePrivateDirectory(locksRoot);
|
|
640
|
+
const lockPath = (0, path_1.join)(locksRoot, `${this.sha256(canonicalTargetPath)}.lock`);
|
|
641
|
+
const deadline = Date.now() + 5_000;
|
|
642
|
+
while (Date.now() < deadline) {
|
|
643
|
+
try {
|
|
644
|
+
await (0, promises_1.mkdir)(lockPath, { mode: PRIVATE_DIRECTORY_MODE });
|
|
645
|
+
const startIdentity = await this.readProcessStartIdentity(process.pid);
|
|
646
|
+
if (typeof startIdentity !== 'string') {
|
|
647
|
+
await (0, promises_1.rm)(lockPath, { recursive: true, force: true });
|
|
648
|
+
throw new error_types_1.IOError('Process identity unavailable for Codex profile lock.');
|
|
649
|
+
}
|
|
650
|
+
await (0, promises_1.writeFile)((0, path_1.join)(lockPath, 'owner.json'), JSON.stringify({ version: 1, pid: process.pid, startIdentity, attemptNonce }), { encoding: 'utf8', mode: PRIVATE_FILE_MODE, flag: 'wx' });
|
|
651
|
+
return async () => (0, promises_1.rm)(lockPath, { recursive: true, force: true });
|
|
652
|
+
}
|
|
653
|
+
catch (error) {
|
|
654
|
+
if (error.code !== 'EEXIST')
|
|
655
|
+
throw error;
|
|
656
|
+
}
|
|
657
|
+
const owner = await this.readJsonFile((0, path_1.join)(lockPath, 'owner.json'));
|
|
658
|
+
if (owner && Number.isSafeInteger(owner.pid) && typeof owner.startIdentity === 'string') {
|
|
659
|
+
const actual = await this.readProcessStartIdentity(owner.pid);
|
|
660
|
+
if (actual === false || (typeof actual === 'string' && actual !== owner.startIdentity)) {
|
|
661
|
+
const stalePath = `${lockPath}.stale-${process.pid}-${(0, crypto_1.randomUUID)()}`;
|
|
662
|
+
try {
|
|
663
|
+
await (0, promises_1.rename)(lockPath, stalePath);
|
|
664
|
+
await (0, promises_1.rm)(stalePath, { recursive: true, force: true });
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
await new Promise((resolveDelay) => setTimeout(resolveDelay, 25));
|
|
672
|
+
}
|
|
673
|
+
throw new error_types_1.TimeoutError('Timed out acquiring Codex profile lifecycle lock.', {
|
|
674
|
+
stage: 'profile_lock',
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
async readProcessStartIdentity(pid) {
|
|
678
|
+
try {
|
|
679
|
+
const value = await (0, promises_1.readFile)(`/proc/${pid}/stat`, 'utf8');
|
|
680
|
+
return (value
|
|
681
|
+
.slice(value.lastIndexOf(')') + 2)
|
|
682
|
+
.trim()
|
|
683
|
+
.split(/\s+/)[19] ?? null);
|
|
684
|
+
}
|
|
685
|
+
catch (error) {
|
|
686
|
+
const code = error.code;
|
|
687
|
+
return code === 'ENOENT' || code === 'ESRCH' ? false : null;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
async readJsonFile(path) {
|
|
691
|
+
try {
|
|
692
|
+
const metadata = await (0, promises_1.lstat)(path);
|
|
693
|
+
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
694
|
+
return null;
|
|
695
|
+
return JSON.parse(await (0, promises_1.readFile)(path, 'utf8'));
|
|
696
|
+
}
|
|
697
|
+
catch (error) {
|
|
698
|
+
if (error.code === 'ENOENT')
|
|
699
|
+
return null;
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async hashRegularFile(path) {
|
|
704
|
+
try {
|
|
705
|
+
const metadata = await (0, promises_1.lstat)(path);
|
|
706
|
+
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
707
|
+
return null;
|
|
708
|
+
return this.sha256(await (0, promises_1.readFile)(path, 'utf8'));
|
|
709
|
+
}
|
|
710
|
+
catch {
|
|
711
|
+
return null;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
assertAcknowledgement(acknowledgement, prepared, input) {
|
|
715
|
+
if (acknowledgement.version !== 1 ||
|
|
716
|
+
acknowledgement.projectId !== input.projectId ||
|
|
717
|
+
acknowledgement.sessionId !== prepared.sessionId ||
|
|
718
|
+
acknowledgement.projectDigest !== prepared.projectDigest ||
|
|
719
|
+
acknowledgement.profileName !== prepared.profileName ||
|
|
720
|
+
acknowledgement.policyHash !== prepared.policyHash ||
|
|
721
|
+
acknowledgement.nonce !== input.attemptNonce ||
|
|
722
|
+
!(0, path_1.isAbsolute)(acknowledgement.canonicalTargetPath)) {
|
|
723
|
+
throw new error_types_1.IOError('Codex profile acknowledgement does not match its launch attempt.', {
|
|
724
|
+
stage: 'profile_acknowledgement',
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
validateIdentity(input) {
|
|
729
|
+
if (typeof input.projectId !== 'string' ||
|
|
730
|
+
input.projectId.length === 0 ||
|
|
731
|
+
ASCII_CONTROL_PATTERN.test(input.projectId)) {
|
|
732
|
+
throw new error_types_1.ValidationError('Codex plugin profile project identity is invalid.', {
|
|
733
|
+
field: 'projectId',
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
if (typeof input.projectName !== 'string') {
|
|
737
|
+
throw new error_types_1.ValidationError('Codex plugin profile project name is invalid.', {
|
|
738
|
+
field: 'projectName',
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
if (typeof input.sessionId !== 'string' ||
|
|
742
|
+
input.sessionId.length === 0 ||
|
|
743
|
+
ASCII_CONTROL_PATTERN.test(input.sessionId)) {
|
|
744
|
+
throw new error_types_1.ValidationError('Codex plugin profile session identity is invalid.', {
|
|
745
|
+
field: 'sessionId',
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
if (!NONCE_PATTERN.test(input.attemptNonce)) {
|
|
749
|
+
throw new error_types_1.ValidationError('Codex plugin profile attempt nonce is invalid.', {
|
|
750
|
+
field: 'attemptNonce',
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
validatePolicyEntry(entry) {
|
|
755
|
+
const characterCount = typeof entry.pluginId === 'string' ? Array.from(entry.pluginId).length : 0;
|
|
756
|
+
if (typeof entry.pluginId !== 'string' ||
|
|
757
|
+
characterCount === 0 ||
|
|
758
|
+
characterCount > MAX_PLUGIN_ID_LENGTH ||
|
|
759
|
+
ASCII_CONTROL_PATTERN.test(entry.pluginId) ||
|
|
760
|
+
typeof entry.enabled !== 'boolean') {
|
|
761
|
+
throw new error_types_1.ValidationError('Resolved Codex plugin policy entry is invalid.', {
|
|
762
|
+
field: 'pluginPolicy',
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
validateCodexBinary(codexBinary) {
|
|
767
|
+
if (typeof codexBinary !== 'string' ||
|
|
768
|
+
codexBinary.length === 0 ||
|
|
769
|
+
ASCII_CONTROL_PATTERN.test(codexBinary) ||
|
|
770
|
+
(!(0, path_1.isAbsolute)(codexBinary) && (codexBinary.includes('/') || codexBinary.includes('\\')))) {
|
|
771
|
+
throw new error_types_1.ValidationError('Codex binary must be a bare command or absolute path.', {
|
|
772
|
+
field: 'codexBinary',
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
toProjectSlug(projectName) {
|
|
777
|
+
const slug = projectName
|
|
778
|
+
.normalize('NFKD')
|
|
779
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
780
|
+
.toLowerCase()
|
|
781
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
782
|
+
.replace(/^-+|-+$/g, '')
|
|
783
|
+
.slice(0, MAX_PROJECT_SLUG_LENGTH)
|
|
784
|
+
.replace(/-+$/g, '');
|
|
785
|
+
return slug || 'project';
|
|
786
|
+
}
|
|
787
|
+
sha256(content) {
|
|
788
|
+
return (0, crypto_1.createHash)('sha256').update(content, 'utf8').digest('hex');
|
|
789
|
+
}
|
|
790
|
+
async ensurePrivateDirectory(path) {
|
|
791
|
+
await (0, promises_1.mkdir)(path, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
792
|
+
const metadata = await (0, promises_1.lstat)(path);
|
|
793
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
|
|
794
|
+
throw new Error('Codex plugin profile private path is unsafe');
|
|
795
|
+
}
|
|
796
|
+
await (0, promises_1.chmod)(path, PRIVATE_DIRECTORY_MODE);
|
|
797
|
+
}
|
|
798
|
+
async materializeImmutable(path, content, mode) {
|
|
799
|
+
try {
|
|
800
|
+
await (0, promises_1.access)(path, fs_1.constants.F_OK);
|
|
801
|
+
const metadata = await (0, promises_1.lstat)(path);
|
|
802
|
+
if (!metadata.isFile() || metadata.isSymbolicLink()) {
|
|
803
|
+
throw new Error('Immutable Codex profile artifact path is unsafe');
|
|
804
|
+
}
|
|
805
|
+
if ((await (0, promises_1.readFile)(path, 'utf8')) !== content) {
|
|
806
|
+
throw new Error('Immutable Codex profile artifact content mismatch');
|
|
807
|
+
}
|
|
808
|
+
await (0, promises_1.chmod)(path, mode);
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
if (error.code !== 'ENOENT')
|
|
813
|
+
throw error;
|
|
814
|
+
}
|
|
815
|
+
const temporaryPath = `${path}.tmp-${process.pid}-${(0, crypto_1.randomUUID)()}`;
|
|
816
|
+
try {
|
|
817
|
+
await (0, promises_1.writeFile)(temporaryPath, content, {
|
|
818
|
+
encoding: 'utf8',
|
|
819
|
+
mode,
|
|
820
|
+
flag: 'wx',
|
|
821
|
+
});
|
|
822
|
+
await (0, promises_1.link)(temporaryPath, path).catch(async (error) => {
|
|
823
|
+
if (error.code !== 'EEXIST')
|
|
824
|
+
throw error;
|
|
825
|
+
if ((await (0, promises_1.readFile)(path, 'utf8')) !== content)
|
|
826
|
+
throw error;
|
|
827
|
+
});
|
|
828
|
+
await (0, promises_1.chmod)(path, mode);
|
|
829
|
+
}
|
|
830
|
+
finally {
|
|
831
|
+
await (0, promises_1.unlink)(temporaryPath).catch(() => undefined);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
exports.CodexPluginProfileMaterializerService = CodexPluginProfileMaterializerService;
|
|
836
|
+
exports.CodexPluginProfileMaterializerService = CodexPluginProfileMaterializerService = __decorate([
|
|
837
|
+
(0, common_1.Injectable)(),
|
|
838
|
+
__param(0, (0, common_1.Optional)()),
|
|
839
|
+
__param(0, (0, common_1.Inject)(exports.CODEX_PLUGIN_PROFILE_ROOT)),
|
|
840
|
+
__metadata("design:paramtypes", [String])
|
|
841
|
+
], CodexPluginProfileMaterializerService);
|
|
842
|
+
//# sourceMappingURL=codex-plugin-profile-materializer.service.js.map
|