factory-factory 0.3.7 → 0.3.9
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/client/assets/{_basePickBy-BsuMuaCZ.js → _basePickBy-CoLLbaiQ.js} +1 -1
- package/dist/client/assets/{_baseUniq-BDd8f52s.js → _baseUniq-xRgxfXUW.js} +1 -1
- package/dist/client/assets/{arc-BWbaJQoA.js → arc-De4Ny3V9.js} +1 -1
- package/dist/client/assets/{architectureDiagram-VXUJARFQ-C_FQG3JS.js → architectureDiagram-VXUJARFQ-DM0j158z.js} +1 -1
- package/dist/client/assets/{blockDiagram-VD42YOAC-CLwvH-wA.js → blockDiagram-VD42YOAC-DKBZN-sz.js} +1 -1
- package/dist/client/assets/{c4Diagram-YG6GDRKO-Ba80_haP.js → c4Diagram-YG6GDRKO-CIA6AVRp.js} +1 -1
- package/dist/client/assets/channel-DW2o9xrZ.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-CSlDSMiy.js → chunk-4BX2VUAB-BrHsCtgI.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-Dm3keBAf.js → chunk-55IACEB6-DLwlJB2L.js} +1 -1
- package/dist/client/assets/{chunk-B4BG7PRW-BSrvNYuP.js → chunk-B4BG7PRW-cqTY9ldj.js} +1 -1
- package/dist/client/assets/{chunk-DI55MBZ5-DFQPoLQZ.js → chunk-DI55MBZ5-PAp7fYLU.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-C1KS438H.js → chunk-FMBD7UC4-CsvpScij.js} +1 -1
- package/dist/client/assets/{chunk-QN33PNHL-4rPPxHo4.js → chunk-QN33PNHL-DmkkCoc-.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-B_sF5IzV.js → chunk-QZHKN3VN-Ds5Tjlpo.js} +1 -1
- package/dist/client/assets/{chunk-TZMSLE5B-L-qbjoBp.js → chunk-TZMSLE5B-4Gu0uKkR.js} +1 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-CUeZuC6S.js +1 -0
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-CUeZuC6S.js +1 -0
- package/dist/client/assets/clone-Df9JDgIw.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DB7lwAnl.js → cose-bilkent-S5V4N54A-CQJ_MgcD.js} +1 -1
- package/dist/client/assets/{dagre-6UL2VRFP-z2fl_1iD.js → dagre-6UL2VRFP-CfyncTju.js} +1 -1
- package/dist/client/assets/{diagram-PSM6KHXK-BL2iv8II.js → diagram-PSM6KHXK-BL2QA0bQ.js} +1 -1
- package/dist/client/assets/{diagram-QEK2KX5R-DgMZW0D1.js → diagram-QEK2KX5R-BDcBrJO4.js} +1 -1
- package/dist/client/assets/{diagram-S2PKOQOG-Ct2QBl2c.js → diagram-S2PKOQOG-BxofoMik.js} +1 -1
- package/dist/client/assets/{erDiagram-Q2GNP2WA-DII-pqkb.js → erDiagram-Q2GNP2WA-CDGe-bUA.js} +1 -1
- package/dist/client/assets/{flowDiagram-NV44I4VS-BV4CMZAZ.js → flowDiagram-NV44I4VS-CodDw20I.js} +1 -1
- package/dist/client/assets/{ganttDiagram-JELNMOA3-Dfj064tE.js → ganttDiagram-JELNMOA3-BHJlNcF5.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-Cg2b-j3t.js → gitGraphDiagram-V2S2FVAM-DsFPFnxn.js} +1 -1
- package/dist/client/assets/{graph-wzICjOO_.js → graph-DtyTGYVa.js} +1 -1
- package/dist/client/assets/index-BkwQogmx.css +1 -0
- package/dist/client/assets/index-CSanKe06.js +436 -0
- package/dist/client/assets/{infoDiagram-HS3SLOUP-D09mbfgG.js → infoDiagram-HS3SLOUP-CczckdeY.js} +1 -1
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-BebsQbuf.js → journeyDiagram-XKPGCS4Q-CIDlGmYi.js} +1 -1
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-DOuawTNU.js → kanban-definition-3W4ZIXB7-Dvuu9eqr.js} +1 -1
- package/dist/client/assets/{layout-Bj6cMfF5.js → layout-Cth5sJm6.js} +1 -1
- package/dist/client/assets/{linear-B58HS9F4.js → linear-DRv-Y17x.js} +1 -1
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-hSFgcTL2.js → mindmap-definition-VGOIOE7T-AXsc24V4.js} +1 -1
- package/dist/client/assets/{mobile-baseline-CmdjqYSm.js → mobile-baseline-DXBPdrir.js} +1 -1
- package/dist/client/assets/{pieDiagram-ADFJNKIX-D1vkoKs3.js → pieDiagram-ADFJNKIX-oIn8Bgi4.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-pMQj9xcS.js → quadrantDiagram-AYHSOK5B-rGTqNh3q.js} +1 -1
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-DvRtxnIi.js → requirementDiagram-UZGBJVZJ-DgE2dYES.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BWoDxXkR.js → sankeyDiagram-TZEHDZUN-BWRLa217.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-Dz5i1ly3.js → sequenceDiagram-WL72ISMW-lYEkh9VX.js} +1 -1
- package/dist/client/assets/{stateDiagram-FKZM4ZOC-BFd_gXUo.js → stateDiagram-FKZM4ZOC-CV9VCuVK.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-DQ10FejB.js +1 -0
- package/dist/client/assets/{terminal-instance-BTIzq32H.js → terminal-instance-C3nwiweh.js} +1 -1
- package/dist/client/assets/{timeline-definition-IT6M3QCI-BFEIWW6m.js → timeline-definition-IT6M3QCI-Bzm_qoWF.js} +1 -1
- package/dist/client/assets/{treemap-GDKQZRPO-CC2Fh6RQ.js → treemap-GDKQZRPO-gouxKMUq.js} +1 -1
- package/dist/client/assets/{xychartDiagram-PRI3JC2R-DFygXQrm.js → xychartDiagram-PRI3JC2R-DqSTMw-l.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/prisma/generated/enums.d.ts +1 -0
- package/dist/prisma/generated/enums.d.ts.map +1 -1
- package/dist/prisma/generated/enums.js +1 -0
- package/dist/prisma/generated/enums.js.map +1 -1
- package/dist/prisma/generated/internal/class.js +4 -4
- package/dist/prisma/generated/internal/class.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts +1 -0
- package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.js +1 -0
- package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +1 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +1 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/prisma/generated/models/Workspace.d.ts +44 -1
- package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
- package/dist/src/backend/app-context.d.ts +2 -1
- package/dist/src/backend/app-context.d.ts.map +1 -1
- package/dist/src/backend/app-context.js +22 -5
- package/dist/src/backend/app-context.js.map +1 -1
- package/dist/src/backend/domains/github/github-cli/mappers.d.ts +1 -1
- package/dist/src/backend/domains/github/github-cli/mappers.d.ts.map +1 -1
- package/dist/src/backend/domains/github/github-cli/mappers.js +2 -37
- package/dist/src/backend/domains/github/github-cli/mappers.js.map +1 -1
- package/dist/src/backend/domains/github/github-cli.service.test.js +20 -0
- package/dist/src/backend/domains/github/github-cli.service.test.js.map +1 -1
- package/dist/src/backend/domains/linear/linear-state-sync.service.d.ts.map +1 -1
- package/dist/src/backend/domains/linear/linear-state-sync.service.js.map +1 -1
- package/dist/src/backend/domains/ratchet/bridges.d.ts +4 -0
- package/dist/src/backend/domains/ratchet/bridges.d.ts.map +1 -1
- package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.d.ts +15 -0
- package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.d.ts.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.js +126 -0
- package/dist/src/backend/domains/ratchet/ratchet-active-session.helpers.js.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.d.ts +14 -0
- package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.d.ts.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.js +55 -0
- package/dist/src/backend/domains/ratchet/ratchet-fixer-dispatch.helpers.js.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.d.ts +107 -0
- package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.d.ts.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.js +246 -0
- package/dist/src/backend/domains/ratchet/ratchet-pr-state.helpers.js.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.d.ts +16 -0
- package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.d.ts.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.js +52 -0
- package/dist/src/backend/domains/ratchet/ratchet-review-poll.helpers.js.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet.service.d.ts +6 -40
- package/dist/src/backend/domains/ratchet/ratchet.service.d.ts.map +1 -1
- package/dist/src/backend/domains/ratchet/ratchet.service.js +99 -426
- package/dist/src/backend/domains/ratchet/ratchet.service.js.map +1 -1
- package/dist/src/backend/domains/ratchet/ratchet.types.d.ts +86 -0
- package/dist/src/backend/domains/ratchet/ratchet.types.d.ts.map +1 -0
- package/dist/src/backend/domains/ratchet/ratchet.types.js +2 -0
- package/dist/src/backend/domains/ratchet/ratchet.types.js.map +1 -0
- package/dist/src/backend/domains/ratchet/reconciliation.service.d.ts.map +1 -1
- package/dist/src/backend/domains/ratchet/reconciliation.service.js +1 -2
- package/dist/src/backend/domains/ratchet/reconciliation.service.js.map +1 -1
- package/dist/src/backend/domains/ratchet/reconciliation.service.test.js +8 -10
- package/dist/src/backend/domains/ratchet/reconciliation.service.test.js.map +1 -1
- package/dist/src/backend/domains/run-script/index.d.ts +1 -1
- package/dist/src/backend/domains/run-script/index.d.ts.map +1 -1
- package/dist/src/backend/domains/run-script/index.js +1 -1
- package/dist/src/backend/domains/run-script/index.js.map +1 -1
- package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js +5 -4
- package/dist/src/backend/domains/run-script/run-script-domain-exports.test.js.map +1 -1
- package/dist/src/backend/domains/run-script/run-script.service.d.ts +13 -1
- package/dist/src/backend/domains/run-script/run-script.service.d.ts.map +1 -1
- package/dist/src/backend/domains/run-script/run-script.service.js +175 -10
- package/dist/src/backend/domains/run-script/run-script.service.js.map +1 -1
- package/dist/src/backend/domains/run-script/run-script.service.test.js +204 -0
- package/dist/src/backend/domains/run-script/run-script.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-event-translator.d.ts +13 -1
- package/dist/src/backend/domains/session/acp/acp-event-translator.d.ts.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-event-translator.js +86 -1
- package/dist/src/backend/domains/session/acp/acp-event-translator.js.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-event-translator.test.js +39 -0
- package/dist/src/backend/domains/session/acp/acp-event-translator.test.js.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.d.ts +5 -0
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.d.ts.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.js +16 -13
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.js.map +1 -1
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.test.js +3 -12
- package/dist/src/backend/domains/session/acp/acp-runtime-manager.test.js.map +1 -1
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts +24 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js +79 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/acp-adapter-utils.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts +97 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js +2 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/adapter-state.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts +17 -39
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts.map +1 -1
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js +109 -1694
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js.map +1 -1
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js +0 -191
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-app-server-acp-adapter.test.js.map +1 -1
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/codex-zod.d.ts +3 -3
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts +16 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js +292 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts +2 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js +56 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/command-metadata.test.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts +19 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js +369 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts +2 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js +91 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/protocol-permission-handler.test.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.d.ts +16 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.js +53 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/retry-logic.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.d.ts +20 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.js +341 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-config-resolver.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.d.ts +41 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.js +137 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-negotiation.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.d.ts +25 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.js +47 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/session-state-container.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.d.ts +8 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.js +37 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/shape-drift-reporter.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts +53 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js +419 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.js.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts +2 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js +95 -0
- package/dist/src/backend/domains/session/acp/codex-app-server-adapter/stream-event-handler.test.js.map +1 -0
- package/dist/src/backend/domains/session/acp/index.d.ts +1 -1
- package/dist/src/backend/domains/session/acp/index.d.ts.map +1 -1
- package/dist/src/backend/domains/session/acp/index.js +1 -1
- package/dist/src/backend/domains/session/acp/index.js.map +1 -1
- package/dist/src/backend/domains/session/bridges.d.ts +5 -0
- package/dist/src/backend/domains/session/bridges.d.ts.map +1 -1
- package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.d.ts.map +1 -1
- package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.js +2 -2
- package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.js.map +1 -1
- package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.test.js +1 -1
- package/dist/src/backend/domains/session/chat/chat-message-handlers/handlers/load-session.handler.test.js.map +1 -1
- package/dist/src/backend/domains/session/chat/chat-message-handlers.service.js +2 -2
- package/dist/src/backend/domains/session/chat/chat-message-handlers.service.js.map +1 -1
- package/dist/src/backend/domains/session/data/codex-session-history-loader.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js +77 -24
- package/dist/src/backend/domains/session/data/codex-session-history-loader.service.js.map +1 -1
- package/dist/src/backend/domains/session/data/session-data.service.d.ts +2 -0
- package/dist/src/backend/domains/session/data/session-data.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.d.ts → session-history-loader.service.d.ts} +1 -1
- package/dist/src/backend/domains/session/data/session-history-loader.service.d.ts.map +1 -0
- package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.js → session-history-loader.service.js} +23 -9
- package/dist/src/backend/domains/session/data/session-history-loader.service.js.map +1 -0
- package/dist/src/backend/domains/session/data/session-history-loader.service.test.d.ts +2 -0
- package/dist/src/backend/domains/session/data/session-history-loader.service.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/data/{claude-session-history-loader.service.test.js → session-history-loader.service.test.js} +6 -3
- package/dist/src/backend/domains/session/data/session-history-loader.service.test.js.map +1 -0
- package/dist/src/backend/domains/session/index.d.ts +3 -1
- package/dist/src/backend/domains/session/index.d.ts.map +1 -1
- package/dist/src/backend/domains/session/index.js +2 -1
- package/dist/src/backend/domains/session/index.js.map +1 -1
- package/dist/src/backend/domains/session/interceptor.bridge.d.ts +8 -0
- package/dist/src/backend/domains/session/interceptor.bridge.d.ts.map +1 -0
- package/dist/src/backend/domains/session/interceptor.bridge.js +7 -0
- package/dist/src/backend/domains/session/interceptor.bridge.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/acp-event-processor.d.ts +71 -0
- package/dist/src/backend/domains/session/lifecycle/acp-event-processor.d.ts.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/acp-event-processor.js +404 -0
- package/dist/src/backend/domains/session/lifecycle/acp-event-processor.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts +59 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.d.ts.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.js +635 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts +2 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js +552 -0
- package/dist/src/backend/domains/session/lifecycle/session.config.service.test.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts +17 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.d.ts.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.js +86 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts +2 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.d.ts.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js +137 -0
- package/dist/src/backend/domains/session/lifecycle/session.permission.service.test.js.map +1 -0
- package/dist/src/backend/domains/session/lifecycle/session.repository.d.ts +0 -2
- package/dist/src/backend/domains/session/lifecycle/session.repository.d.ts.map +1 -1
- package/dist/src/backend/domains/session/lifecycle/session.repository.js +0 -3
- package/dist/src/backend/domains/session/lifecycle/session.repository.js.map +1 -1
- package/dist/src/backend/domains/session/lifecycle/session.repository.test.js +0 -1
- package/dist/src/backend/domains/session/lifecycle/session.repository.test.js.map +1 -1
- package/dist/src/backend/domains/session/lifecycle/session.service.d.ts +24 -56
- package/dist/src/backend/domains/session/lifecycle/session.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/lifecycle/session.service.js +140 -1083
- package/dist/src/backend/domains/session/lifecycle/session.service.js.map +1 -1
- package/dist/src/backend/domains/session/lifecycle/session.service.test.js +62 -689
- package/dist/src/backend/domains/session/lifecycle/session.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/logging/acp-trace-logger.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/logging/acp-trace-logger.service.js +2 -13
- package/dist/src/backend/domains/session/logging/acp-trace-logger.service.js.map +1 -1
- package/dist/src/backend/domains/session/logging/acp-trace-logger.service.test.js +15 -3
- package/dist/src/backend/domains/session/logging/acp-trace-logger.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/logging/session-file-logger.service.js +1 -1
- package/dist/src/backend/domains/session/logging/session-file-logger.service.js.map +1 -1
- package/dist/src/backend/domains/session/logging/session-file-logger.service.test.js +3 -0
- package/dist/src/backend/domains/session/logging/session-file-logger.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/session-domain.service.d.ts +1 -2
- package/dist/src/backend/domains/session/session-domain.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/session-domain.service.js +21 -2
- package/dist/src/backend/domains/session/session-domain.service.js.map +1 -1
- package/dist/src/backend/domains/session/session-domain.service.test.js +34 -0
- package/dist/src/backend/domains/session/session-domain.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/store/file-lock.service.d.ts.map +1 -1
- package/dist/src/backend/domains/session/store/file-lock.service.js +25 -6
- package/dist/src/backend/domains/session/store/file-lock.service.js.map +1 -1
- package/dist/src/backend/domains/session/store/file-lock.service.test.js +3 -0
- package/dist/src/backend/domains/session/store/file-lock.service.test.js.map +1 -1
- package/dist/src/backend/domains/session/zod-issue-summary.d.ts +3 -0
- package/dist/src/backend/domains/session/zod-issue-summary.d.ts.map +1 -0
- package/dist/src/backend/domains/session/zod-issue-summary.js +7 -0
- package/dist/src/backend/domains/session/zod-issue-summary.js.map +1 -0
- package/dist/src/backend/domains/workspace/index.d.ts +0 -1
- package/dist/src/backend/domains/workspace/index.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/index.js +0 -1
- package/dist/src/backend/domains/workspace/index.js.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts +7 -0
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.js +98 -85
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.js.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js +41 -1
- package/dist/src/backend/domains/workspace/lifecycle/creation.service.test.js.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts +9 -1
- package/dist/src/backend/domains/workspace/lifecycle/data.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/data.service.js +2 -1
- package/dist/src/backend/domains/workspace/lifecycle/data.service.js.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.d.ts +8 -0
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.js +47 -5
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.js.map +1 -1
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.test.js +117 -22
- package/dist/src/backend/domains/workspace/lifecycle/state-machine.service.test.js.map +1 -1
- package/dist/src/backend/domains/workspace/query/project-management.service.d.ts +2 -0
- package/dist/src/backend/domains/workspace/query/project-management.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts +4 -1
- package/dist/src/backend/domains/workspace/query/workspace-query.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/query/workspace-query.service.js +51 -36
- package/dist/src/backend/domains/workspace/query/workspace-query.service.js.map +1 -1
- package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js +141 -44
- package/dist/src/backend/domains/workspace/query/workspace-query.service.test.js.map +1 -1
- package/dist/src/backend/domains/workspace/state/flow-state.d.ts +2 -2
- package/dist/src/backend/domains/workspace/state/flow-state.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/state/flow-state.js.map +1 -1
- package/dist/src/backend/domains/workspace/state/init-policy.js +1 -1
- package/dist/src/backend/domains/workspace/state/init-policy.js.map +1 -1
- package/dist/src/backend/domains/workspace/state/kanban-state.d.ts +2 -1
- package/dist/src/backend/domains/workspace/state/kanban-state.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/state/kanban-state.js +9 -5
- package/dist/src/backend/domains/workspace/state/kanban-state.js.map +1 -1
- package/dist/src/backend/domains/workspace/state/kanban-state.test.js +23 -0
- package/dist/src/backend/domains/workspace/state/kanban-state.test.js.map +1 -1
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts +3 -6
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js +7 -116
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.js.map +1 -1
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js +38 -65
- package/dist/src/backend/domains/workspace/worktree/worktree-lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/interceptors/conversation-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/conversation-rename.interceptor.js +22 -6
- package/dist/src/backend/interceptors/conversation-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js +25 -13
- package/dist/src/backend/interceptors/conversation-rename.interceptor.test.js.map +1 -1
- package/dist/src/backend/interceptors/index.d.ts +2 -0
- package/dist/src/backend/interceptors/index.d.ts.map +1 -1
- package/dist/src/backend/interceptors/index.js +6 -0
- package/dist/src/backend/interceptors/index.js.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js +8 -0
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js +5 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js.map +1 -1
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.js +3 -0
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/registry.d.ts +5 -0
- package/dist/src/backend/interceptors/registry.d.ts.map +1 -1
- package/dist/src/backend/interceptors/registry.js +51 -0
- package/dist/src/backend/interceptors/registry.js.map +1 -1
- package/dist/src/backend/interceptors/types.d.ts +2 -0
- package/dist/src/backend/interceptors/types.d.ts.map +1 -1
- package/dist/src/backend/lib/file-helpers.d.ts +2 -0
- package/dist/src/backend/lib/file-helpers.d.ts.map +1 -1
- package/dist/src/backend/lib/file-helpers.js +64 -1
- package/dist/src/backend/lib/file-helpers.js.map +1 -1
- package/dist/src/backend/lib/workspace-derived-state.d.ts +47 -0
- package/dist/src/backend/lib/workspace-derived-state.d.ts.map +1 -0
- package/dist/src/backend/lib/workspace-derived-state.js +31 -0
- package/dist/src/backend/lib/workspace-derived-state.js.map +1 -0
- package/dist/src/backend/lib/workspace-derived-state.test.d.ts +2 -0
- package/dist/src/backend/lib/workspace-derived-state.test.d.ts.map +1 -0
- package/dist/src/backend/lib/workspace-derived-state.test.js +66 -0
- package/dist/src/backend/lib/workspace-derived-state.test.js.map +1 -0
- package/dist/src/backend/middleware/cors.middleware.d.ts +1 -2
- package/dist/src/backend/middleware/cors.middleware.d.ts.map +1 -1
- package/dist/src/backend/middleware/cors.middleware.js +0 -2
- package/dist/src/backend/middleware/cors.middleware.js.map +1 -1
- package/dist/src/backend/middleware/index.d.ts +1 -1
- package/dist/src/backend/middleware/index.d.ts.map +1 -1
- package/dist/src/backend/middleware/index.js +1 -1
- package/dist/src/backend/middleware/index.js.map +1 -1
- package/dist/src/backend/orchestration/data-backup.service.test.js +1 -0
- package/dist/src/backend/orchestration/data-backup.service.test.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +26 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +24 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +19 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts +8 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.js +41 -21
- package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +19 -4
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts +6 -2
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js +8 -3
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +19 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +21 -13
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +103 -77
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts +18 -0
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts.map +1 -0
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.js +75 -0
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.js.map +1 -0
- package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js +105 -106
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +137 -18
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
- package/dist/src/backend/resource_accessors/project.accessor.js +1 -1
- package/dist/src/backend/resource_accessors/project.accessor.js.map +1 -1
- package/dist/src/backend/resource_accessors/workspace.accessor.d.ts +1 -0
- package/dist/src/backend/resource_accessors/workspace.accessor.d.ts.map +1 -1
- package/dist/src/backend/resource_accessors/workspace.accessor.js.map +1 -1
- package/dist/src/backend/routers/websocket/index.d.ts +1 -0
- package/dist/src/backend/routers/websocket/index.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/index.js +1 -0
- package/dist/src/backend/routers/websocket/index.js.map +1 -1
- package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts +9 -0
- package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts.map +1 -0
- package/dist/src/backend/routers/websocket/post-run-logs.handler.js +52 -0
- package/dist/src/backend/routers/websocket/post-run-logs.handler.js.map +1 -0
- package/dist/src/backend/routers/websocket/snapshots.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/snapshots.handler.js +17 -6
- package/dist/src/backend/routers/websocket/snapshots.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/snapshots.handler.test.js +40 -5
- package/dist/src/backend/routers/websocket/snapshots.handler.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/websocket.integration.test.js +1 -0
- package/dist/src/backend/routers/websocket/websocket.integration.test.js.map +1 -1
- package/dist/src/backend/server.d.ts.map +1 -1
- package/dist/src/backend/server.js +16 -6
- package/dist/src/backend/server.js.map +1 -1
- package/dist/src/backend/server.upgrade.test.js +4 -0
- package/dist/src/backend/server.upgrade.test.js.map +1 -1
- package/dist/src/backend/services/check-single-writer.test.d.ts +2 -0
- package/dist/src/backend/services/check-single-writer.test.d.ts.map +1 -0
- package/dist/src/backend/services/check-single-writer.test.js +132 -0
- package/dist/src/backend/services/check-single-writer.test.js.map +1 -0
- package/dist/src/backend/services/config.service.d.ts +14 -6
- package/dist/src/backend/services/config.service.d.ts.map +1 -1
- package/dist/src/backend/services/config.service.js +31 -9
- package/dist/src/backend/services/config.service.js.map +1 -1
- package/dist/src/backend/services/env-schemas.d.ts +7 -3
- package/dist/src/backend/services/env-schemas.d.ts.map +1 -1
- package/dist/src/backend/services/env-schemas.js +19 -3
- package/dist/src/backend/services/env-schemas.js.map +1 -1
- package/dist/src/backend/services/run-script-config-persistence.service.d.ts +37 -0
- package/dist/src/backend/services/run-script-config-persistence.service.d.ts.map +1 -0
- package/dist/src/backend/services/run-script-config-persistence.service.js +73 -0
- package/dist/src/backend/services/run-script-config-persistence.service.js.map +1 -0
- package/dist/src/backend/services/run-script-config-persistence.service.test.d.ts +2 -0
- package/dist/src/backend/services/run-script-config-persistence.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/run-script-config-persistence.service.test.js +111 -0
- package/dist/src/backend/services/run-script-config-persistence.service.test.js.map +1 -0
- package/dist/src/backend/services/run-script-proxy.service.d.ts.map +1 -1
- package/dist/src/backend/services/run-script-proxy.service.js +2 -1
- package/dist/src/backend/services/run-script-proxy.service.js.map +1 -1
- package/dist/src/backend/services/run-script-proxy.service.test.js +4 -0
- package/dist/src/backend/services/run-script-proxy.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.d.ts +5 -3
- package/dist/src/backend/services/workspace-snapshot-store.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.js +20 -15
- package/dist/src/backend/services/workspace-snapshot-store.service.js.map +1 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.test.js +3 -0
- package/dist/src/backend/services/workspace-snapshot-store.service.test.js.map +1 -1
- package/dist/src/backend/trpc/admin.router.test.js +0 -2
- package/dist/src/backend/trpc/admin.router.test.js.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.d.ts +2 -7
- package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.js +2 -3
- package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
- package/dist/src/backend/trpc/index.d.ts +49 -14
- package/dist/src/backend/trpc/index.d.ts.map +1 -1
- package/dist/src/backend/trpc/project.trpc.d.ts +17 -3
- package/dist/src/backend/trpc/project.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/project.trpc.js +22 -0
- package/dist/src/backend/trpc/project.trpc.js.map +1 -1
- package/dist/src/backend/trpc/session.router.test.js +1 -0
- package/dist/src/backend/trpc/session.router.test.js.map +1 -1
- package/dist/src/backend/trpc/session.trpc.d.ts +4 -0
- package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/session.trpc.js +2 -2
- package/dist/src/backend/trpc/session.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/files.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/files.trpc.js +1 -64
- package/dist/src/backend/trpc/workspace/files.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/init.router.test.js +1 -1
- package/dist/src/backend/trpc/workspace/init.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/init.trpc.d.ts +1 -0
- package/dist/src/backend/trpc/workspace/init.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/init.trpc.js +2 -3
- package/dist/src/backend/trpc/workspace/init.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.router.test.js +31 -4
- package/dist/src/backend/trpc/workspace/run-script.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts +2 -0
- package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.trpc.js +8 -8
- package/dist/src/backend/trpc/workspace/run-script.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts +2 -0
- package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace.router.test.js +45 -1
- package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.d.ts +26 -4
- package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.js +25 -16
- package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
- package/dist/src/cli/index.js +17 -5
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/shared/core/ci-status.d.ts +6 -4
- package/dist/src/shared/core/ci-status.d.ts.map +1 -1
- package/dist/src/shared/core/ci-status.js +47 -13
- package/dist/src/shared/core/ci-status.js.map +1 -1
- package/dist/src/shared/core/enums.d.ts +1 -0
- package/dist/src/shared/core/enums.d.ts.map +1 -1
- package/dist/src/shared/core/enums.js +1 -0
- package/dist/src/shared/core/enums.js.map +1 -1
- package/dist/src/shared/core/index.d.ts +1 -1
- package/dist/src/shared/core/index.d.ts.map +1 -1
- package/dist/src/shared/core/index.js +1 -1
- package/dist/src/shared/core/index.js.map +1 -1
- package/dist/src/shared/schemas/export-data.schema.d.ts +2 -0
- package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -1
- package/dist/src/shared/schemas/factory-config.schema.d.ts +1 -0
- package/dist/src/shared/schemas/factory-config.schema.d.ts.map +1 -1
- package/dist/src/shared/schemas/factory-config.schema.js +1 -0
- package/dist/src/shared/schemas/factory-config.schema.js.map +1 -1
- package/dist/src/shared/schemas/issue-tracker-config.schema.d.ts +2 -2
- package/dist/src/shared/schemas/persisted-stores.schema.d.ts +0 -2
- package/dist/src/shared/schemas/persisted-stores.schema.d.ts.map +1 -1
- package/dist/src/shared/schemas/persisted-stores.schema.js +0 -1
- package/dist/src/shared/schemas/persisted-stores.schema.js.map +1 -1
- package/dist/src/shared/workspace-flow-state.d.ts +3 -0
- package/dist/src/shared/workspace-flow-state.d.ts.map +1 -0
- package/dist/src/shared/workspace-flow-state.js +2 -0
- package/dist/src/shared/workspace-flow-state.js.map +1 -0
- package/dist/tsconfig.backend.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260222120000_add_post_run_command/migration.sql +1 -0
- package/prisma/migrations/20260224150000_add_workspace_archiving_state/migration.sql +4 -0
- package/prisma/schema.prisma +2 -0
- package/dist/client/assets/channel-B2z94T-9.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-B2LoFG_o.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-B2LoFG_o.js +0 -1
- package/dist/client/assets/clone-C8LA0zQQ.js +0 -1
- package/dist/client/assets/index-DvtmO7DV.css +0 -1
- package/dist/client/assets/index-EVrp_NXm.js +0 -429
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-CO6XGRkL.js +0 -1
- package/dist/src/backend/domains/session/data/claude-session-history-loader.service.d.ts.map +0 -1
- package/dist/src/backend/domains/session/data/claude-session-history-loader.service.js.map +0 -1
- package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.d.ts +0 -2
- package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.d.ts.map +0 -1
- package/dist/src/backend/domains/session/data/claude-session-history-loader.service.test.js.map +0 -1
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.d.ts +0 -10
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.d.ts.map +0 -1
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.js +0 -24
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.js.map +0 -1
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.d.ts +0 -2
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.d.ts.map +0 -1
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.js +0 -17
- package/dist/src/backend/domains/workspace/lifecycle/archive-tracker.service.test.js.map +0 -1
|
@@ -1,147 +1,17 @@
|
|
|
1
1
|
import { Readable, Writable } from 'node:stream';
|
|
2
2
|
import { AgentSideConnection, ndJsonStream, PROTOCOL_VERSION, RequestError, } from '@agentclientprotocol/sdk';
|
|
3
|
+
import { asString, dedupeStrings, extractLocations, isRecord, resolveToolCallId, } from './acp-adapter-utils.js';
|
|
3
4
|
import { CodexRequestError, CodexRpcClient } from './codex-rpc-client.js';
|
|
4
|
-
import {
|
|
5
|
+
import { turnStartResponseSchema } from './codex-zod.js';
|
|
6
|
+
import { resolveCommandDisplay } from './command-metadata.js';
|
|
7
|
+
import { handleCodexServerPermissionRequest } from './protocol-permission-handler.js';
|
|
8
|
+
import { attachCloseWatcherWithRetry } from './retry-logic.js';
|
|
9
|
+
import { buildConfigOptions, createSandboxPolicyFromMode, getCollaborationModeValues, getExecutionPresets, isKnownModel, isReasoningEffortSupportedForModel, resolveCollaborationModeLabel, resolveDefaultCollaborationMode, resolveDefaultModel, resolveReasoningEffortForModel, resolveSandboxPolicy, resolveSessionModel, resolveTurnCollaborationMode, } from './session-config-resolver.js';
|
|
10
|
+
import { loadCollaborationModes, loadConfigRequirements, loadModelCatalog, negotiateNewSession, negotiateSessionResume, } from './session-negotiation.js';
|
|
11
|
+
import { CodexAdapterSessionStateContainer } from './session-state-container.js';
|
|
12
|
+
import { ShapeDriftReporter } from './shape-drift-reporter.js';
|
|
13
|
+
import { CodexStreamEventHandler } from './stream-event-handler.js';
|
|
5
14
|
const PENDING_TURN_ID = '__pending_turn__';
|
|
6
|
-
const MAX_CLOSE_WATCHER_ATTACH_RETRIES = 50;
|
|
7
|
-
const DEFAULT_APPROVAL_POLICIES = ['on-failure', 'on-request', 'never'];
|
|
8
|
-
const DEFAULT_SANDBOX_MODES = ['read-only', 'workspace-write', 'danger-full-access'];
|
|
9
|
-
const SHAPE_DRIFT_DETAILS_LIMIT = 700;
|
|
10
|
-
const COMMAND_EXECUTION_SESSION_HANDOFF_LINE_PATTERN = /^process running with session id(?:\s*[:#-]?\s*[a-z0-9_-]+)?\.?$/i;
|
|
11
|
-
function toTurnItemKey(turnId, itemId) {
|
|
12
|
-
return `${turnId}:${itemId}`;
|
|
13
|
-
}
|
|
14
|
-
function toShapeDriftDetails(value) {
|
|
15
|
-
try {
|
|
16
|
-
const text = JSON.stringify(value);
|
|
17
|
-
if (typeof text !== 'string') {
|
|
18
|
-
return '[unserializable]';
|
|
19
|
-
}
|
|
20
|
-
return text.length > SHAPE_DRIFT_DETAILS_LIMIT
|
|
21
|
-
? `${text.slice(0, SHAPE_DRIFT_DETAILS_LIMIT)}...`
|
|
22
|
-
: text;
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return '[unserializable]';
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function isNonEmptyString(value) {
|
|
29
|
-
return typeof value === 'string' && value.trim().length > 0;
|
|
30
|
-
}
|
|
31
|
-
function dedupeStrings(values) {
|
|
32
|
-
return Array.from(new Set(values));
|
|
33
|
-
}
|
|
34
|
-
function humanizeToken(value) {
|
|
35
|
-
return value
|
|
36
|
-
.split(/[-_]/)
|
|
37
|
-
.filter((part) => part.length > 0)
|
|
38
|
-
.map((part) => part.slice(0, 1).toUpperCase() + part.slice(1))
|
|
39
|
-
.join(' ');
|
|
40
|
-
}
|
|
41
|
-
function sanitizeModeName(mode) {
|
|
42
|
-
return mode
|
|
43
|
-
.split('_')
|
|
44
|
-
.map((part) => part.slice(0, 1).toUpperCase() + part.slice(1))
|
|
45
|
-
.join(' ');
|
|
46
|
-
}
|
|
47
|
-
function formatApprovalPolicyLabel(policy) {
|
|
48
|
-
if (policy === 'on-request') {
|
|
49
|
-
return 'On Request';
|
|
50
|
-
}
|
|
51
|
-
if (policy === 'on-failure') {
|
|
52
|
-
return 'On Failure';
|
|
53
|
-
}
|
|
54
|
-
if (policy === 'never') {
|
|
55
|
-
return 'Never Ask';
|
|
56
|
-
}
|
|
57
|
-
if (policy === 'untrusted') {
|
|
58
|
-
return 'Untrusted';
|
|
59
|
-
}
|
|
60
|
-
return humanizeToken(policy);
|
|
61
|
-
}
|
|
62
|
-
function formatSandboxModeLabel(mode) {
|
|
63
|
-
if (mode === 'workspace-write') {
|
|
64
|
-
return 'Workspace Write';
|
|
65
|
-
}
|
|
66
|
-
if (mode === 'read-only') {
|
|
67
|
-
return 'Read-only';
|
|
68
|
-
}
|
|
69
|
-
if (mode === 'danger-full-access') {
|
|
70
|
-
return 'Full Access';
|
|
71
|
-
}
|
|
72
|
-
return humanizeToken(mode);
|
|
73
|
-
}
|
|
74
|
-
function formatExecutionPresetName(approvalPolicy, sandboxMode) {
|
|
75
|
-
if (approvalPolicy === 'never' && sandboxMode === 'danger-full-access') {
|
|
76
|
-
return 'YOLO (Full Access)';
|
|
77
|
-
}
|
|
78
|
-
return `${formatApprovalPolicyLabel(approvalPolicy)} (${formatSandboxModeLabel(sandboxMode)})`;
|
|
79
|
-
}
|
|
80
|
-
function createWorkspaceWriteSandboxPolicy(cwd) {
|
|
81
|
-
return {
|
|
82
|
-
type: 'workspaceWrite',
|
|
83
|
-
writableRoots: [cwd],
|
|
84
|
-
readOnlyAccess: { type: 'fullAccess' },
|
|
85
|
-
networkAccess: true,
|
|
86
|
-
excludeTmpdirEnvVar: false,
|
|
87
|
-
excludeSlashTmp: false,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
function createDangerFullAccessSandboxPolicy() {
|
|
91
|
-
return {
|
|
92
|
-
type: 'dangerFullAccess',
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
function parseSandboxModeFromPolicy(policy) {
|
|
96
|
-
if (!isRecord(policy)) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
const policyType = asString(policy.type);
|
|
100
|
-
if (policyType === 'workspaceWrite') {
|
|
101
|
-
return 'workspace-write';
|
|
102
|
-
}
|
|
103
|
-
if (policyType === 'readOnly') {
|
|
104
|
-
return 'read-only';
|
|
105
|
-
}
|
|
106
|
-
if (policyType === 'dangerFullAccess') {
|
|
107
|
-
return 'danger-full-access';
|
|
108
|
-
}
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
function createSandboxPolicyFromMode(mode, cwd) {
|
|
112
|
-
if (mode === 'danger-full-access') {
|
|
113
|
-
return createDangerFullAccessSandboxPolicy();
|
|
114
|
-
}
|
|
115
|
-
if (mode === 'read-only') {
|
|
116
|
-
return {
|
|
117
|
-
type: 'readOnly',
|
|
118
|
-
access: { type: 'fullAccess' },
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
return createWorkspaceWriteSandboxPolicy(cwd);
|
|
122
|
-
}
|
|
123
|
-
function toSessionId(threadId) {
|
|
124
|
-
return `sess_${threadId}`;
|
|
125
|
-
}
|
|
126
|
-
function toThreadId(sessionId) {
|
|
127
|
-
return sessionId.startsWith('sess_') ? sessionId.slice('sess_'.length) : sessionId;
|
|
128
|
-
}
|
|
129
|
-
function extractToolCallIdFromUnknown(value) {
|
|
130
|
-
if (!isRecord(value)) {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
return asString(value.callId) ?? asString(value.call_id) ?? null;
|
|
134
|
-
}
|
|
135
|
-
function resolveToolCallId(params) {
|
|
136
|
-
return extractToolCallIdFromUnknown(params.source) ?? params.itemId;
|
|
137
|
-
}
|
|
138
|
-
function isCommandExecutionSessionHandoffOutput(output) {
|
|
139
|
-
const trimmedOutput = output.trim();
|
|
140
|
-
if (trimmedOutput.length === 0 || /[\r\n]/.test(trimmedOutput)) {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
return COMMAND_EXECUTION_SESSION_HANDOFF_LINE_PATTERN.test(trimmedOutput);
|
|
144
|
-
}
|
|
145
15
|
function isPlanLikeMode(mode) {
|
|
146
16
|
return /plan/i.test(mode);
|
|
147
17
|
}
|
|
@@ -280,393 +150,6 @@ function toCodexMcpConfigMap(mcpServers) {
|
|
|
280
150
|
}
|
|
281
151
|
return mcpServersByName;
|
|
282
152
|
}
|
|
283
|
-
function buildToolUserInputPermissionOptions(questions) {
|
|
284
|
-
if (questions.length !== 1) {
|
|
285
|
-
return [
|
|
286
|
-
{ optionId: 'allow_once', name: 'Submit', kind: 'allow_once' },
|
|
287
|
-
{ optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' },
|
|
288
|
-
];
|
|
289
|
-
}
|
|
290
|
-
const firstQuestionWithOptions = questions.find((question) => Array.isArray(question.options) && question.options.length > 0);
|
|
291
|
-
if (!firstQuestionWithOptions?.options) {
|
|
292
|
-
return [
|
|
293
|
-
{ optionId: 'allow_once', name: 'Submit', kind: 'allow_once' },
|
|
294
|
-
{ optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' },
|
|
295
|
-
];
|
|
296
|
-
}
|
|
297
|
-
const mappedOptions = firstQuestionWithOptions.options.slice(0, 6).map((option, index) => ({
|
|
298
|
-
optionId: `answer_${index}`,
|
|
299
|
-
name: option.label,
|
|
300
|
-
kind: 'allow_once',
|
|
301
|
-
}));
|
|
302
|
-
mappedOptions.push({ optionId: 'reject_once', name: 'Cancel', kind: 'reject_once' });
|
|
303
|
-
return mappedOptions;
|
|
304
|
-
}
|
|
305
|
-
function buildToolUserInputAnswers(params) {
|
|
306
|
-
if (params.selectedOptionId === null || params.selectedOptionId === 'reject_once') {
|
|
307
|
-
return {};
|
|
308
|
-
}
|
|
309
|
-
const parsedAnswers = parseToolUserInputAnswersFromPermissionMeta({
|
|
310
|
-
questions: params.questions,
|
|
311
|
-
permission: params.permission,
|
|
312
|
-
});
|
|
313
|
-
if (parsedAnswers) {
|
|
314
|
-
return parsedAnswers;
|
|
315
|
-
}
|
|
316
|
-
if (params.questions.length !== 1) {
|
|
317
|
-
throw new Error('Missing structured answers for multi-question requestUserInput');
|
|
318
|
-
}
|
|
319
|
-
const selectedIndex = params.selectedOptionId.startsWith('answer_')
|
|
320
|
-
? Number.parseInt(params.selectedOptionId.slice('answer_'.length), 10)
|
|
321
|
-
: Number.NaN;
|
|
322
|
-
const answers = {};
|
|
323
|
-
const [question] = params.questions;
|
|
324
|
-
if (!(question && Array.isArray(question.options)) || question.options.length === 0) {
|
|
325
|
-
return answers;
|
|
326
|
-
}
|
|
327
|
-
const selectedOption = Number.isNaN(selectedIndex)
|
|
328
|
-
? question.options[0]
|
|
329
|
-
: (question.options[selectedIndex] ?? question.options[0]);
|
|
330
|
-
if (!selectedOption) {
|
|
331
|
-
return answers;
|
|
332
|
-
}
|
|
333
|
-
answers[question.id] = { answers: [selectedOption.label] };
|
|
334
|
-
return answers;
|
|
335
|
-
}
|
|
336
|
-
function isRecord(value) {
|
|
337
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
338
|
-
}
|
|
339
|
-
function parseToolUserInputAnswersFromPermissionMeta(params) {
|
|
340
|
-
const meta = params.permission._meta;
|
|
341
|
-
if (!isRecord(meta)) {
|
|
342
|
-
return null;
|
|
343
|
-
}
|
|
344
|
-
const factoryFactoryMeta = isRecord(meta.factoryFactory) ? meta.factoryFactory : null;
|
|
345
|
-
const answersRaw = (factoryFactoryMeta?.toolUserInputAnswers ?? meta.toolUserInputAnswers);
|
|
346
|
-
if (!isRecord(answersRaw)) {
|
|
347
|
-
return null;
|
|
348
|
-
}
|
|
349
|
-
const knownQuestionIds = new Set(params.questions.map((question) => question.id));
|
|
350
|
-
const answers = {};
|
|
351
|
-
for (const [questionId, value] of Object.entries(answersRaw)) {
|
|
352
|
-
if (!knownQuestionIds.has(questionId)) {
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
const values = (Array.isArray(value) ? value : [value])
|
|
356
|
-
.filter((entry) => typeof entry === 'string')
|
|
357
|
-
.map((entry) => entry.trim())
|
|
358
|
-
.filter((entry) => entry.length > 0);
|
|
359
|
-
if (values.length === 0) {
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
answers[questionId] = { answers: values };
|
|
363
|
-
}
|
|
364
|
-
return answers;
|
|
365
|
-
}
|
|
366
|
-
function asString(value) {
|
|
367
|
-
return typeof value === 'string' ? value : null;
|
|
368
|
-
}
|
|
369
|
-
function trimOptionalQuotes(token) {
|
|
370
|
-
if (token.length >= 2 && token.startsWith('"') && token.endsWith('"')) {
|
|
371
|
-
return { text: token.slice(1, -1), quote: '"' };
|
|
372
|
-
}
|
|
373
|
-
if (token.length >= 2 && token.startsWith("'") && token.endsWith("'")) {
|
|
374
|
-
return { text: token.slice(1, -1), quote: "'" };
|
|
375
|
-
}
|
|
376
|
-
return { text: token, quote: null };
|
|
377
|
-
}
|
|
378
|
-
function unescapeCommandToken(token, quote) {
|
|
379
|
-
if (quote === "'") {
|
|
380
|
-
return token.replace(/\\'/g, "'").replace(/\\\\/g, '\\');
|
|
381
|
-
}
|
|
382
|
-
return token.replace(/\\(["'\\\s|&;])/g, '$1');
|
|
383
|
-
}
|
|
384
|
-
function sanitizeCommandToken(token) {
|
|
385
|
-
const trimmed = token.trim();
|
|
386
|
-
const { text, quote } = trimOptionalQuotes(trimmed);
|
|
387
|
-
return unescapeCommandToken(text, quote).trim();
|
|
388
|
-
}
|
|
389
|
-
function tokenizeCommand(command) {
|
|
390
|
-
return (command.match(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+/g) ?? [])
|
|
391
|
-
.map((token) => sanitizeCommandToken(token))
|
|
392
|
-
.filter((token) => token.length > 0);
|
|
393
|
-
}
|
|
394
|
-
function commandName(token) {
|
|
395
|
-
const unix = token.split('/').at(-1) ?? token;
|
|
396
|
-
return (unix.split('\\').at(-1) ?? unix).toLowerCase();
|
|
397
|
-
}
|
|
398
|
-
function isChainSeparatorChar(char) {
|
|
399
|
-
return char === ';' || char === '\n' || char === '|' || char === '&';
|
|
400
|
-
}
|
|
401
|
-
function readChainSeparatorLength(command, index) {
|
|
402
|
-
const char = command[index];
|
|
403
|
-
if (!(char && isChainSeparatorChar(char))) {
|
|
404
|
-
return 0;
|
|
405
|
-
}
|
|
406
|
-
const next = command[index + 1];
|
|
407
|
-
if ((char === '|' || char === '&') && next === char) {
|
|
408
|
-
return 2;
|
|
409
|
-
}
|
|
410
|
-
return 1;
|
|
411
|
-
}
|
|
412
|
-
function isLikelyPathToken(token) {
|
|
413
|
-
if (!token || token.startsWith('-')) {
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
if (token.startsWith('./') ||
|
|
417
|
-
token.startsWith('../') ||
|
|
418
|
-
token.startsWith('/') ||
|
|
419
|
-
token.startsWith('~')) {
|
|
420
|
-
return true;
|
|
421
|
-
}
|
|
422
|
-
return (token.includes('/') ||
|
|
423
|
-
token.includes('\\') ||
|
|
424
|
-
token.endsWith('.') ||
|
|
425
|
-
/\.[a-z0-9]+$/i.test(token));
|
|
426
|
-
}
|
|
427
|
-
function normalizeLocationPath(pathToken, cwd) {
|
|
428
|
-
if (pathToken.startsWith('/')) {
|
|
429
|
-
return pathToken;
|
|
430
|
-
}
|
|
431
|
-
if (pathToken.startsWith('~')) {
|
|
432
|
-
return pathToken;
|
|
433
|
-
}
|
|
434
|
-
const base = cwd.endsWith('/') ? cwd.slice(0, -1) : cwd;
|
|
435
|
-
return `${base}/${pathToken}`;
|
|
436
|
-
}
|
|
437
|
-
const READ_COMMANDS = new Set(['cat', 'head', 'tail', 'less', 'more']);
|
|
438
|
-
const LIST_OR_FIND_COMMANDS = new Set(['ls', 'tree', 'find', 'fd']);
|
|
439
|
-
const GREP_LIKE_COMMANDS = new Set(['rg', 'ripgrep', 'grep', 'ag']);
|
|
440
|
-
const SHELL_META_COMMANDS = new Set(['cd', 'export', 'set', 'unset', 'alias', 'unalias', 'source']);
|
|
441
|
-
function pushCommandChainPart(state) {
|
|
442
|
-
const trimmed = state.current.trim();
|
|
443
|
-
if (trimmed.length > 0) {
|
|
444
|
-
state.parts.push(trimmed);
|
|
445
|
-
}
|
|
446
|
-
state.current = '';
|
|
447
|
-
}
|
|
448
|
-
function consumeEscapedCommandChar(state, char) {
|
|
449
|
-
if (!state.escaped) {
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
452
|
-
state.current += char;
|
|
453
|
-
state.escaped = false;
|
|
454
|
-
return true;
|
|
455
|
-
}
|
|
456
|
-
function consumeEscapeInitiator(state, char) {
|
|
457
|
-
if (!(char === '\\' && state.quote !== "'")) {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
state.current += char;
|
|
461
|
-
state.escaped = true;
|
|
462
|
-
return true;
|
|
463
|
-
}
|
|
464
|
-
function hasOddTrailingBackslashes(value) {
|
|
465
|
-
let count = 0;
|
|
466
|
-
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
467
|
-
if (value[index] !== '\\') {
|
|
468
|
-
break;
|
|
469
|
-
}
|
|
470
|
-
count += 1;
|
|
471
|
-
}
|
|
472
|
-
return count % 2 === 1;
|
|
473
|
-
}
|
|
474
|
-
function consumeQuotedCommandChar(state, char) {
|
|
475
|
-
if (!state.quote) {
|
|
476
|
-
return false;
|
|
477
|
-
}
|
|
478
|
-
const escapedSingleQuote = state.quote === "'" && char === "'" && hasOddTrailingBackslashes(state.current);
|
|
479
|
-
state.current += char;
|
|
480
|
-
if (char === state.quote && !escapedSingleQuote) {
|
|
481
|
-
state.quote = null;
|
|
482
|
-
}
|
|
483
|
-
return true;
|
|
484
|
-
}
|
|
485
|
-
function consumeQuoteStart(state, char) {
|
|
486
|
-
if (!(char === '"' || char === "'")) {
|
|
487
|
-
return false;
|
|
488
|
-
}
|
|
489
|
-
state.quote = char;
|
|
490
|
-
state.current += char;
|
|
491
|
-
return true;
|
|
492
|
-
}
|
|
493
|
-
function consumeCommandChainSeparator(state, command, index) {
|
|
494
|
-
const separatorLength = readChainSeparatorLength(command, index);
|
|
495
|
-
if (separatorLength <= 0) {
|
|
496
|
-
return 0;
|
|
497
|
-
}
|
|
498
|
-
pushCommandChainPart(state);
|
|
499
|
-
return separatorLength;
|
|
500
|
-
}
|
|
501
|
-
function splitCommandChain(command) {
|
|
502
|
-
const state = {
|
|
503
|
-
parts: [],
|
|
504
|
-
current: '',
|
|
505
|
-
quote: null,
|
|
506
|
-
escaped: false,
|
|
507
|
-
};
|
|
508
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
509
|
-
const char = command[index];
|
|
510
|
-
if (!char) {
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
if (consumeEscapedCommandChar(state, char)) {
|
|
514
|
-
continue;
|
|
515
|
-
}
|
|
516
|
-
if (consumeEscapeInitiator(state, char)) {
|
|
517
|
-
continue;
|
|
518
|
-
}
|
|
519
|
-
if (consumeQuotedCommandChar(state, char)) {
|
|
520
|
-
continue;
|
|
521
|
-
}
|
|
522
|
-
if (consumeQuoteStart(state, char)) {
|
|
523
|
-
continue;
|
|
524
|
-
}
|
|
525
|
-
const consumedSeparatorLength = consumeCommandChainSeparator(state, command, index);
|
|
526
|
-
if (consumedSeparatorLength > 0) {
|
|
527
|
-
index += consumedSeparatorLength - 1;
|
|
528
|
-
continue;
|
|
529
|
-
}
|
|
530
|
-
state.current += char;
|
|
531
|
-
}
|
|
532
|
-
pushCommandChainPart(state);
|
|
533
|
-
return state.parts;
|
|
534
|
-
}
|
|
535
|
-
function buildCommandDisplayContexts(rawCommand, cwd) {
|
|
536
|
-
const command = rawCommand?.trim();
|
|
537
|
-
if (!command) {
|
|
538
|
-
return [];
|
|
539
|
-
}
|
|
540
|
-
const contexts = [];
|
|
541
|
-
const segments = splitCommandChain(command);
|
|
542
|
-
for (const segment of segments) {
|
|
543
|
-
const tokens = tokenizeCommand(segment);
|
|
544
|
-
if (tokens.length === 0) {
|
|
545
|
-
continue;
|
|
546
|
-
}
|
|
547
|
-
const [firstToken] = tokens;
|
|
548
|
-
if (!firstToken) {
|
|
549
|
-
continue;
|
|
550
|
-
}
|
|
551
|
-
const firstCommand = commandName(firstToken);
|
|
552
|
-
const nonFlagArgs = tokens.slice(1).filter((token) => !token.startsWith('-'));
|
|
553
|
-
const pathArg = nonFlagArgs.find(isLikelyPathToken) ?? null;
|
|
554
|
-
const commandPath = pathArg ? normalizeLocationPath(pathArg, cwd) : null;
|
|
555
|
-
const locations = commandPath ? [{ path: commandPath }] : [];
|
|
556
|
-
contexts.push({
|
|
557
|
-
command: segment,
|
|
558
|
-
firstCommand,
|
|
559
|
-
nonFlagArgs,
|
|
560
|
-
pathArg,
|
|
561
|
-
cwd,
|
|
562
|
-
locations,
|
|
563
|
-
isShellMeta: SHELL_META_COMMANDS.has(firstCommand),
|
|
564
|
-
});
|
|
565
|
-
}
|
|
566
|
-
return contexts;
|
|
567
|
-
}
|
|
568
|
-
function chooseActionableCommandContexts(contexts) {
|
|
569
|
-
const actionable = contexts.filter((context) => !context.isShellMeta);
|
|
570
|
-
return actionable.length > 0 ? actionable : contexts;
|
|
571
|
-
}
|
|
572
|
-
function selectCombinedCommandKind(displays) {
|
|
573
|
-
const firstNonExecute = displays.find((display) => display.kind !== 'execute');
|
|
574
|
-
return firstNonExecute?.kind ?? 'execute';
|
|
575
|
-
}
|
|
576
|
-
function resolveCommandDisplay(params) {
|
|
577
|
-
const contexts = chooseActionableCommandContexts(buildCommandDisplayContexts(params.command, params.cwd));
|
|
578
|
-
if (contexts.length === 0) {
|
|
579
|
-
return { title: 'commandExecution', kind: 'execute', locations: [] };
|
|
580
|
-
}
|
|
581
|
-
const [singleContext] = contexts;
|
|
582
|
-
if (singleContext && contexts.length === 1) {
|
|
583
|
-
return resolveCommandDisplayFromContext(singleContext);
|
|
584
|
-
}
|
|
585
|
-
const displays = contexts.map((context) => resolveCommandDisplayFromContext(context));
|
|
586
|
-
const title = dedupeStrings(displays.map((display) => display.title)).join(', ');
|
|
587
|
-
const kind = selectCombinedCommandKind(displays);
|
|
588
|
-
const locations = dedupeLocations(displays.flatMap((display) => display.locations)).map((location) => ({ path: location.path }));
|
|
589
|
-
return { title, kind, locations };
|
|
590
|
-
}
|
|
591
|
-
function resolveCommandDisplayFromContext(context) {
|
|
592
|
-
if (READ_COMMANDS.has(context.firstCommand)) {
|
|
593
|
-
const label = context.pathArg ?? context.command;
|
|
594
|
-
return { title: `Read ${label}`, kind: 'read', locations: context.locations };
|
|
595
|
-
}
|
|
596
|
-
if (LIST_OR_FIND_COMMANDS.has(context.firstCommand)) {
|
|
597
|
-
const target = context.pathArg
|
|
598
|
-
? normalizeLocationPath(context.pathArg, context.cwd)
|
|
599
|
-
: context.cwd;
|
|
600
|
-
const title = context.firstCommand === 'find' || context.firstCommand === 'fd'
|
|
601
|
-
? `Search ${target}`
|
|
602
|
-
: `List ${target}`;
|
|
603
|
-
return { title, kind: 'search', locations: context.locations };
|
|
604
|
-
}
|
|
605
|
-
if (GREP_LIKE_COMMANDS.has(context.firstCommand)) {
|
|
606
|
-
const query = context.nonFlagArgs.find((token) => !isLikelyPathToken(token));
|
|
607
|
-
const target = context.pathArg ? ` in ${context.pathArg}` : '';
|
|
608
|
-
const title = query ? `Search ${query}${target}` : `Search ${context.command}`;
|
|
609
|
-
return { title, kind: 'search', locations: context.locations };
|
|
610
|
-
}
|
|
611
|
-
return { title: context.command, kind: 'execute', locations: context.locations };
|
|
612
|
-
}
|
|
613
|
-
function normalizeCwdForScope(cwd) {
|
|
614
|
-
if (cwd.length > 1 && cwd.endsWith('/')) {
|
|
615
|
-
return cwd.slice(0, -1);
|
|
616
|
-
}
|
|
617
|
-
return cwd;
|
|
618
|
-
}
|
|
619
|
-
function normalizeScopeToken(token) {
|
|
620
|
-
return token.replace(/\s+/g, ' ').trim();
|
|
621
|
-
}
|
|
622
|
-
function buildCommandApprovalScopeKey(params) {
|
|
623
|
-
const contexts = buildCommandDisplayContexts(params.command, params.cwd);
|
|
624
|
-
if (contexts.length === 0) {
|
|
625
|
-
return null;
|
|
626
|
-
}
|
|
627
|
-
let scopeCwd = normalizeCwdForScope(params.cwd);
|
|
628
|
-
const segments = [];
|
|
629
|
-
for (const context of contexts) {
|
|
630
|
-
if (context.firstCommand === 'cd') {
|
|
631
|
-
const rawTarget = context.nonFlagArgs[0];
|
|
632
|
-
const target = rawTarget ? normalizeScopeToken(rawTarget) : '';
|
|
633
|
-
if (target.length > 0) {
|
|
634
|
-
scopeCwd = normalizeCwdForScope(normalizeLocationPath(target, scopeCwd));
|
|
635
|
-
segments.push(`cd ${target} -> ${scopeCwd}`);
|
|
636
|
-
}
|
|
637
|
-
else {
|
|
638
|
-
segments.push('cd');
|
|
639
|
-
}
|
|
640
|
-
continue;
|
|
641
|
-
}
|
|
642
|
-
const args = context.nonFlagArgs.map(normalizeScopeToken).filter((arg) => arg.length > 0);
|
|
643
|
-
const normalized = normalizeScopeToken([context.firstCommand, ...args].join(' '));
|
|
644
|
-
if (normalized.length === 0) {
|
|
645
|
-
continue;
|
|
646
|
-
}
|
|
647
|
-
segments.push(`[cwd=${scopeCwd}] ${normalized}`);
|
|
648
|
-
}
|
|
649
|
-
const normalizedSegments = segments
|
|
650
|
-
.map(normalizeScopeToken)
|
|
651
|
-
.filter((segment) => segment.length > 0);
|
|
652
|
-
if (normalizedSegments.length === 0) {
|
|
653
|
-
return null;
|
|
654
|
-
}
|
|
655
|
-
return `cwd=${normalizeCwdForScope(params.cwd)}|${normalizedSegments.join(' && ')}`;
|
|
656
|
-
}
|
|
657
|
-
function dedupeLocations(locations) {
|
|
658
|
-
const seen = new Set();
|
|
659
|
-
const result = [];
|
|
660
|
-
for (const location of locations) {
|
|
661
|
-
const key = `${location.path}:${location.line ?? ''}`;
|
|
662
|
-
if (seen.has(key)) {
|
|
663
|
-
continue;
|
|
664
|
-
}
|
|
665
|
-
seen.add(key);
|
|
666
|
-
result.push(location);
|
|
667
|
-
}
|
|
668
|
-
return result;
|
|
669
|
-
}
|
|
670
153
|
function parseTextFromPromptBlock(block) {
|
|
671
154
|
if (block.type === 'text') {
|
|
672
155
|
return block.text;
|
|
@@ -690,123 +173,34 @@ function parseTextFromPromptBlock(block) {
|
|
|
690
173
|
}
|
|
691
174
|
return JSON.stringify(block);
|
|
692
175
|
}
|
|
693
|
-
function toToolStatus(status) {
|
|
694
|
-
if (status === 'inProgress') {
|
|
695
|
-
return 'in_progress';
|
|
696
|
-
}
|
|
697
|
-
if (status === 'completed') {
|
|
698
|
-
return 'completed';
|
|
699
|
-
}
|
|
700
|
-
if (status === 'failed' || status === 'declined') {
|
|
701
|
-
return 'failed';
|
|
702
|
-
}
|
|
703
|
-
return undefined;
|
|
704
|
-
}
|
|
705
|
-
function createCollaborationModeConfigOption(currentMode, collaborationModes) {
|
|
706
|
-
const options = collaborationModes
|
|
707
|
-
.filter((entry) => isNonEmptyString(entry.mode))
|
|
708
|
-
.map((entry) => ({
|
|
709
|
-
value: entry.mode,
|
|
710
|
-
name: entry.name,
|
|
711
|
-
}));
|
|
712
|
-
if (!options.some((option) => option.value === currentMode)) {
|
|
713
|
-
options.unshift({ value: currentMode, name: sanitizeModeName(currentMode) });
|
|
714
|
-
}
|
|
715
|
-
return {
|
|
716
|
-
id: 'mode',
|
|
717
|
-
category: 'mode',
|
|
718
|
-
name: 'Collaboration Mode',
|
|
719
|
-
type: 'select',
|
|
720
|
-
currentValue: currentMode,
|
|
721
|
-
options,
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
function createModelConfigOption(currentModel, modelCatalog) {
|
|
725
|
-
const options = modelCatalog.map((model) => ({
|
|
726
|
-
value: model.id,
|
|
727
|
-
name: model.displayName,
|
|
728
|
-
description: model.description,
|
|
729
|
-
}));
|
|
730
|
-
if (!options.some((option) => option.value === currentModel)) {
|
|
731
|
-
options.unshift({ value: currentModel, name: currentModel });
|
|
732
|
-
}
|
|
733
|
-
return {
|
|
734
|
-
id: 'model',
|
|
735
|
-
category: 'model',
|
|
736
|
-
name: 'Model',
|
|
737
|
-
type: 'select',
|
|
738
|
-
currentValue: currentModel,
|
|
739
|
-
options,
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
function createReasoningEffortConfigOption(currentReasoningEffort, modelCatalog, currentModel) {
|
|
743
|
-
const modelEntry = modelCatalog.find((model) => model.id === currentModel);
|
|
744
|
-
if (!modelEntry) {
|
|
745
|
-
return null;
|
|
746
|
-
}
|
|
747
|
-
const supportedEntries = modelEntry.supportedReasoningEfforts.filter((entry) => isNonEmptyString(entry.reasoningEffort));
|
|
748
|
-
if (supportedEntries.length === 0) {
|
|
749
|
-
return null;
|
|
750
|
-
}
|
|
751
|
-
const supportedByValue = new Map();
|
|
752
|
-
for (const entry of supportedEntries) {
|
|
753
|
-
if (!supportedByValue.has(entry.reasoningEffort)) {
|
|
754
|
-
supportedByValue.set(entry.reasoningEffort, entry.description);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
const supportedValues = [...supportedByValue.keys()];
|
|
758
|
-
const resolvedCurrent = currentReasoningEffort && supportedByValue.has(currentReasoningEffort)
|
|
759
|
-
? currentReasoningEffort
|
|
760
|
-
: supportedByValue.has(modelEntry.defaultReasoningEffort)
|
|
761
|
-
? modelEntry.defaultReasoningEffort
|
|
762
|
-
: supportedValues[0];
|
|
763
|
-
if (!resolvedCurrent) {
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
return {
|
|
767
|
-
id: 'reasoning_effort',
|
|
768
|
-
category: 'thought_level',
|
|
769
|
-
name: 'Reasoning Effort',
|
|
770
|
-
type: 'select',
|
|
771
|
-
currentValue: resolvedCurrent,
|
|
772
|
-
options: supportedValues.map((value) => ({
|
|
773
|
-
value,
|
|
774
|
-
name: value,
|
|
775
|
-
...(supportedByValue.get(value) ? { description: supportedByValue.get(value) } : {}),
|
|
776
|
-
})),
|
|
777
|
-
};
|
|
778
|
-
}
|
|
779
|
-
function createExecutionModeConfigOption(currentPresetId, presets) {
|
|
780
|
-
return {
|
|
781
|
-
id: 'execution_mode',
|
|
782
|
-
category: 'permission',
|
|
783
|
-
name: 'Execution Mode',
|
|
784
|
-
type: 'select',
|
|
785
|
-
currentValue: currentPresetId,
|
|
786
|
-
options: presets.map((preset) => ({
|
|
787
|
-
value: preset.id,
|
|
788
|
-
name: preset.name,
|
|
789
|
-
...(preset.description ? { description: preset.description } : {}),
|
|
790
|
-
})),
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
function toExecutionPresetId(approvalPolicy, sandboxMode) {
|
|
794
|
-
return JSON.stringify([approvalPolicy, sandboxMode]);
|
|
795
|
-
}
|
|
796
176
|
export class CodexAppServerAcpAdapter {
|
|
797
177
|
connection;
|
|
798
178
|
codex;
|
|
799
|
-
|
|
800
|
-
sessionIdByThreadId = new Map();
|
|
179
|
+
stateContainer = new CodexAdapterSessionStateContainer();
|
|
801
180
|
modelCatalog = [];
|
|
802
181
|
allowedApprovalPolicies = [];
|
|
803
182
|
allowedSandboxModes = [];
|
|
804
183
|
collaborationModes = [];
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
184
|
+
shapeDriftReporter;
|
|
185
|
+
streamEventHandler;
|
|
186
|
+
get sessions() {
|
|
187
|
+
return this.stateContainer.sessions;
|
|
188
|
+
}
|
|
189
|
+
get sessionIdByThreadId() {
|
|
190
|
+
return this.stateContainer.sessionIdByThreadId;
|
|
191
|
+
}
|
|
192
|
+
get mcpServersByThreadId() {
|
|
193
|
+
return this.stateContainer.mcpServersByThreadId;
|
|
194
|
+
}
|
|
195
|
+
get appliedMcpServerConfigJson() {
|
|
196
|
+
return this.stateContainer.appliedMcpServerConfigJson;
|
|
197
|
+
}
|
|
198
|
+
set appliedMcpServerConfigJson(value) {
|
|
199
|
+
this.stateContainer.appliedMcpServerConfigJson = value;
|
|
200
|
+
}
|
|
201
|
+
constructor(connection, codexClient, options) {
|
|
809
202
|
this.connection = connection;
|
|
203
|
+
this.shapeDriftReporter = new ShapeDriftReporter(options?.shapeDriftWarn);
|
|
810
204
|
this.codex =
|
|
811
205
|
codexClient ??
|
|
812
206
|
new CodexRpcClient({
|
|
@@ -832,31 +226,33 @@ export class CodexAppServerAcpAdapter {
|
|
|
832
226
|
process.stderr.write(`[codex-app-server-acp] protocol-error: ${error.reason}\n`);
|
|
833
227
|
},
|
|
834
228
|
});
|
|
229
|
+
this.streamEventHandler = new CodexStreamEventHandler({
|
|
230
|
+
codex: this.codex,
|
|
231
|
+
sessionIdByThreadId: this.sessionIdByThreadId,
|
|
232
|
+
sessions: this.sessions,
|
|
233
|
+
requireSession: (sessionId) => this.requireSession(sessionId),
|
|
234
|
+
emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
|
|
235
|
+
reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
|
|
236
|
+
buildToolCallState: (session, item, turnId) => this.buildToolCallState(session, item, turnId),
|
|
237
|
+
emitReasoningThoughtChunkFromItem: (sessionId, item) => this.emitReasoningThoughtChunkFromItem(sessionId, item),
|
|
238
|
+
shouldHoldTurnForPlanApproval: (session, item, turnId) => this.shouldHoldTurnForPlanApproval(session, item, turnId),
|
|
239
|
+
holdTurnUntilPlanApprovalResolves: (session, turnId) => this.holdTurnUntilPlanApprovalResolves(session, turnId),
|
|
240
|
+
maybeRequestPlanApproval: (session, item, turnId, completedPlanToolCall) => this.maybeRequestPlanApproval(session, item, turnId, completedPlanToolCall),
|
|
241
|
+
hasPendingPlanApprovals: (session, turnId) => this.hasPendingPlanApprovals(session, turnId),
|
|
242
|
+
settleTurn: (session, stopReason) => this.settleTurn(session, stopReason),
|
|
243
|
+
emitTurnFailureMessage: (sessionId, errorMessage) => this.emitTurnFailureMessage(sessionId, errorMessage),
|
|
244
|
+
});
|
|
835
245
|
this.monitorConnectionClose();
|
|
836
246
|
}
|
|
837
247
|
monitorConnectionClose() {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
});
|
|
847
|
-
}
|
|
848
|
-
catch {
|
|
849
|
-
attachAttempts += 1;
|
|
850
|
-
if (attachAttempts >= MAX_CLOSE_WATCHER_ATTACH_RETRIES) {
|
|
851
|
-
process.stderr.write(`[codex-app-server-acp] failed to attach close watcher after ${MAX_CLOSE_WATCHER_ATTACH_RETRIES} attempts\n`);
|
|
852
|
-
void this.codex.stop();
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
|
-
const retryTimer = setTimeout(attachCloseWatcher, 0);
|
|
856
|
-
retryTimer.unref?.();
|
|
857
|
-
}
|
|
858
|
-
};
|
|
859
|
-
queueMicrotask(attachCloseWatcher);
|
|
248
|
+
attachCloseWatcherWithRetry({
|
|
249
|
+
getClosed: () => this.connection.closed,
|
|
250
|
+
onClose: async () => this.codex.stop(),
|
|
251
|
+
onAttachRetryLimitReached: (maxAttempts) => {
|
|
252
|
+
process.stderr.write(`[codex-app-server-acp] failed to attach close watcher after ${maxAttempts} attempts\n`);
|
|
253
|
+
void this.codex.stop();
|
|
254
|
+
},
|
|
255
|
+
});
|
|
860
256
|
}
|
|
861
257
|
async initialize(_params) {
|
|
862
258
|
this.codex.start();
|
|
@@ -870,11 +266,11 @@ export class CodexAppServerAcpAdapter {
|
|
|
870
266
|
},
|
|
871
267
|
});
|
|
872
268
|
this.codex.notify('initialized');
|
|
873
|
-
const configRequirements = await this.
|
|
269
|
+
const configRequirements = await loadConfigRequirements({ codex: this.codex });
|
|
874
270
|
this.allowedApprovalPolicies = configRequirements.allowedApprovalPolicies;
|
|
875
271
|
this.allowedSandboxModes = configRequirements.allowedSandboxModes;
|
|
876
|
-
this.collaborationModes = await this.
|
|
877
|
-
this.modelCatalog = await this.
|
|
272
|
+
this.collaborationModes = await loadCollaborationModes({ codex: this.codex });
|
|
273
|
+
this.modelCatalog = await loadModelCatalog({ codex: this.codex });
|
|
878
274
|
return {
|
|
879
275
|
protocolVersion: PROTOCOL_VERSION,
|
|
880
276
|
agentInfo: {
|
|
@@ -892,91 +288,42 @@ export class CodexAppServerAcpAdapter {
|
|
|
892
288
|
};
|
|
893
289
|
}
|
|
894
290
|
async newSession(params) {
|
|
895
|
-
const
|
|
896
|
-
|
|
291
|
+
const negotiatedSession = await negotiateNewSession({
|
|
292
|
+
codex: this.codex,
|
|
897
293
|
cwd: params.cwd,
|
|
898
|
-
|
|
294
|
+
resolveDefaultModel: () => this.resolveDefaultModel(),
|
|
295
|
+
resolveSessionModel: (model, fallbackModel) => this.resolveSessionModel(model, fallbackModel),
|
|
296
|
+
resolveSandboxPolicy: (sandbox, cwd) => this.resolveSandboxPolicy(sandbox, cwd),
|
|
297
|
+
resolveReasoningEffortForModel: (modelId, candidateReasoningEffort) => this.resolveReasoningEffortForModel(modelId, candidateReasoningEffort),
|
|
298
|
+
resolveDefaultCollaborationMode: () => this.resolveDefaultCollaborationMode(),
|
|
899
299
|
});
|
|
900
|
-
const
|
|
901
|
-
|
|
902
|
-
const approvalPolicy = this.requireApprovalPolicy(response.approvalPolicy, 'thread/start');
|
|
903
|
-
const model = this.resolveSessionModel(response.model, defaultModel);
|
|
904
|
-
const sandboxPolicy = this.resolveSandboxPolicy(response.sandbox, params.cwd);
|
|
905
|
-
const reasoningEffort = this.resolveReasoningEffortForModel(model, response.reasoningEffort);
|
|
906
|
-
const collaborationMode = this.resolveDefaultCollaborationMode();
|
|
907
|
-
const session = {
|
|
908
|
-
sessionId,
|
|
909
|
-
threadId: response.thread.id,
|
|
910
|
-
cwd: params.cwd,
|
|
911
|
-
defaults: {
|
|
912
|
-
model,
|
|
913
|
-
approvalPolicy,
|
|
914
|
-
sandboxPolicy,
|
|
915
|
-
reasoningEffort,
|
|
916
|
-
collaborationMode,
|
|
917
|
-
},
|
|
918
|
-
activeTurn: null,
|
|
919
|
-
toolCallsByItemId: new Map(),
|
|
920
|
-
syntheticallyCompletedToolItemIds: new Set(),
|
|
921
|
-
reasoningDeltaItemIds: new Set(),
|
|
922
|
-
planTextByItemId: new Map(),
|
|
923
|
-
planApprovalRequestedByTurnId: new Set(),
|
|
924
|
-
pendingPlanApprovalsByTurnId: new Map(),
|
|
925
|
-
pendingTurnCompletionsByTurnId: new Map(),
|
|
926
|
-
commandApprovalScopes: new Set(),
|
|
927
|
-
replayedTurnItemKeys: new Set(),
|
|
928
|
-
};
|
|
929
|
-
this.sessions.set(sessionId, session);
|
|
930
|
-
this.sessionIdByThreadId.set(session.threadId, sessionId);
|
|
300
|
+
const session = this.stateContainer.createSession(negotiatedSession);
|
|
301
|
+
this.stateContainer.registerSession(session);
|
|
931
302
|
try {
|
|
932
303
|
await this.applyMcpServers(session.threadId, params.mcpServers);
|
|
933
304
|
}
|
|
934
305
|
catch (error) {
|
|
935
|
-
this.
|
|
936
|
-
this.sessionIdByThreadId.delete(session.threadId);
|
|
306
|
+
this.stateContainer.deleteSession(negotiatedSession.sessionId);
|
|
937
307
|
throw error;
|
|
938
308
|
}
|
|
939
309
|
return {
|
|
940
|
-
sessionId,
|
|
310
|
+
sessionId: negotiatedSession.sessionId,
|
|
941
311
|
configOptions: this.buildConfigOptions(session),
|
|
942
312
|
};
|
|
943
313
|
}
|
|
944
314
|
async loadSession(params) {
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
threadId,
|
|
948
|
-
cwd: params.cwd,
|
|
949
|
-
});
|
|
950
|
-
const response = threadResumeResponseSchema.parse(responseRaw);
|
|
951
|
-
const approvalPolicy = this.requireApprovalPolicy(response.approvalPolicy, 'thread/resume');
|
|
952
|
-
const model = this.resolveSessionModel(response.model, this.resolveDefaultModel());
|
|
953
|
-
const sandboxPolicy = this.resolveSandboxPolicy(response.sandbox, params.cwd);
|
|
954
|
-
const reasoningEffort = this.resolveReasoningEffortForModel(model, response.reasoningEffort);
|
|
955
|
-
const collaborationMode = this.resolveDefaultCollaborationMode();
|
|
956
|
-
const session = {
|
|
315
|
+
const negotiatedSession = await negotiateSessionResume({
|
|
316
|
+
codex: this.codex,
|
|
957
317
|
sessionId: params.sessionId,
|
|
958
|
-
threadId: response.thread.id,
|
|
959
318
|
cwd: params.cwd,
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
toolCallsByItemId: new Map(),
|
|
969
|
-
syntheticallyCompletedToolItemIds: new Set(),
|
|
970
|
-
reasoningDeltaItemIds: new Set(),
|
|
971
|
-
planTextByItemId: new Map(),
|
|
972
|
-
planApprovalRequestedByTurnId: new Set(),
|
|
973
|
-
pendingPlanApprovalsByTurnId: new Map(),
|
|
974
|
-
pendingTurnCompletionsByTurnId: new Map(),
|
|
975
|
-
commandApprovalScopes: new Set(),
|
|
976
|
-
replayedTurnItemKeys: new Set(),
|
|
977
|
-
};
|
|
978
|
-
this.sessions.set(session.sessionId, session);
|
|
979
|
-
this.sessionIdByThreadId.set(session.threadId, session.sessionId);
|
|
319
|
+
resolveDefaultModel: () => this.resolveDefaultModel(),
|
|
320
|
+
resolveSessionModel: (model, fallbackModel) => this.resolveSessionModel(model, fallbackModel),
|
|
321
|
+
resolveSandboxPolicy: (sandbox, cwd) => this.resolveSandboxPolicy(sandbox, cwd),
|
|
322
|
+
resolveReasoningEffortForModel: (modelId, candidateReasoningEffort) => this.resolveReasoningEffortForModel(modelId, candidateReasoningEffort),
|
|
323
|
+
resolveDefaultCollaborationMode: () => this.resolveDefaultCollaborationMode(),
|
|
324
|
+
});
|
|
325
|
+
const session = this.stateContainer.createSession(negotiatedSession);
|
|
326
|
+
this.stateContainer.registerSession(session);
|
|
980
327
|
try {
|
|
981
328
|
await this.applyMcpServers(session.threadId, params.mcpServers);
|
|
982
329
|
await this.replayThreadHistory(session.sessionId, session.threadId);
|
|
@@ -987,8 +334,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
987
334
|
}
|
|
988
335
|
catch {
|
|
989
336
|
}
|
|
990
|
-
this.
|
|
991
|
-
this.sessionIdByThreadId.delete(session.threadId);
|
|
337
|
+
this.stateContainer.deleteSession(session.sessionId);
|
|
992
338
|
throw error;
|
|
993
339
|
}
|
|
994
340
|
return {
|
|
@@ -1040,7 +386,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
1040
386
|
break;
|
|
1041
387
|
}
|
|
1042
388
|
case 'model': {
|
|
1043
|
-
if (!this.modelCatalog
|
|
389
|
+
if (!isKnownModel(this.modelCatalog, params.value)) {
|
|
1044
390
|
throw RequestError.invalidParams({
|
|
1045
391
|
configId: params.configId,
|
|
1046
392
|
value: params.value,
|
|
@@ -1052,12 +398,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
1052
398
|
}
|
|
1053
399
|
case 'reasoning_effort':
|
|
1054
400
|
case 'thought_level': {
|
|
1055
|
-
|
|
1056
|
-
const supportedReasoningEfforts = modelEntry?.supportedReasoningEfforts ?? [];
|
|
1057
|
-
const supportedValues = new Set(supportedReasoningEfforts
|
|
1058
|
-
.map((entry) => entry.reasoningEffort)
|
|
1059
|
-
.filter((effort) => isNonEmptyString(effort)));
|
|
1060
|
-
if (!supportedValues.has(params.value)) {
|
|
401
|
+
if (!isReasoningEffortSupportedForModel(this.modelCatalog, session.defaults.model, params.value)) {
|
|
1061
402
|
throw RequestError.invalidParams({
|
|
1062
403
|
configId: params.configId,
|
|
1063
404
|
value: params.value,
|
|
@@ -1207,15 +548,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
1207
548
|
}
|
|
1208
549
|
}
|
|
1209
550
|
resolveDefaultModel() {
|
|
1210
|
-
|
|
1211
|
-
const fallback = this.modelCatalog[0]?.id;
|
|
1212
|
-
if (preferred?.id) {
|
|
1213
|
-
return preferred.id;
|
|
1214
|
-
}
|
|
1215
|
-
if (fallback) {
|
|
1216
|
-
return fallback;
|
|
1217
|
-
}
|
|
1218
|
-
throw new Error('Codex app-server model/list returned no models');
|
|
551
|
+
return resolveDefaultModel(this.modelCatalog);
|
|
1219
552
|
}
|
|
1220
553
|
buildMergedMcpServersConfig() {
|
|
1221
554
|
const merged = {};
|
|
@@ -1288,414 +621,41 @@ export class CodexAppServerAcpAdapter {
|
|
|
1288
621
|
}
|
|
1289
622
|
}
|
|
1290
623
|
buildConfigOptions(session) {
|
|
1291
|
-
|
|
1292
|
-
const currentExecutionPreset = this.resolveExecutionPresetId(session, executionPresets);
|
|
1293
|
-
const configOptions = [
|
|
1294
|
-
createModelConfigOption(session.defaults.model, this.modelCatalog),
|
|
1295
|
-
createCollaborationModeConfigOption(session.defaults.collaborationMode, this.collaborationModes),
|
|
1296
|
-
createExecutionModeConfigOption(currentExecutionPreset, executionPresets),
|
|
1297
|
-
];
|
|
1298
|
-
const reasoningOption = createReasoningEffortConfigOption(session.defaults.reasoningEffort, this.modelCatalog, session.defaults.model);
|
|
1299
|
-
if (reasoningOption) {
|
|
1300
|
-
configOptions.push(reasoningOption);
|
|
1301
|
-
}
|
|
1302
|
-
return configOptions;
|
|
1303
|
-
}
|
|
1304
|
-
requireApprovalPolicy(approvalPolicy, source) {
|
|
1305
|
-
if (!isNonEmptyString(approvalPolicy)) {
|
|
1306
|
-
throw new Error(`Codex ${source} response did not include approvalPolicy`);
|
|
1307
|
-
}
|
|
1308
|
-
return approvalPolicy;
|
|
624
|
+
return buildConfigOptions(session, this.modelCatalog, this.collaborationModes, this.allowedApprovalPolicies, this.allowedSandboxModes);
|
|
1309
625
|
}
|
|
1310
626
|
resolveSessionModel(model, fallbackModel) {
|
|
1311
|
-
return
|
|
627
|
+
return resolveSessionModel(model, fallbackModel);
|
|
1312
628
|
}
|
|
1313
629
|
resolveSandboxPolicy(sandbox, cwd) {
|
|
1314
|
-
return
|
|
630
|
+
return resolveSandboxPolicy(sandbox, cwd);
|
|
1315
631
|
}
|
|
1316
632
|
resolveDefaultCollaborationMode() {
|
|
1317
|
-
|
|
1318
|
-
throw new Error('Codex collaborationMode/list returned no modes');
|
|
1319
|
-
}
|
|
1320
|
-
const preferredDefault = this.collaborationModes.find((entry) => entry.mode === 'default');
|
|
1321
|
-
const firstMode = this.collaborationModes[0]?.mode;
|
|
1322
|
-
if (!firstMode) {
|
|
1323
|
-
throw new Error('Codex collaborationMode/list returned an invalid mode entry');
|
|
1324
|
-
}
|
|
1325
|
-
return preferredDefault?.mode ?? firstMode;
|
|
633
|
+
return resolveDefaultCollaborationMode(this.collaborationModes);
|
|
1326
634
|
}
|
|
1327
635
|
resolveTurnCollaborationMode(session) {
|
|
1328
|
-
|
|
1329
|
-
return {
|
|
1330
|
-
mode: modeEntry?.mode ?? session.defaults.collaborationMode,
|
|
1331
|
-
settings: {
|
|
1332
|
-
model: modeEntry?.model ?? session.defaults.model,
|
|
1333
|
-
reasoning_effort: modeEntry?.reasoningEffort ?? session.defaults.reasoningEffort,
|
|
1334
|
-
developer_instructions: modeEntry?.developerInstructions ?? null,
|
|
1335
|
-
},
|
|
1336
|
-
};
|
|
636
|
+
return resolveTurnCollaborationMode(this.collaborationModes, session);
|
|
1337
637
|
}
|
|
1338
638
|
resolveReasoningEffortForModel(modelId, candidateReasoningEffort) {
|
|
1339
|
-
|
|
1340
|
-
if (!modelEntry) {
|
|
1341
|
-
return null;
|
|
1342
|
-
}
|
|
1343
|
-
const supportedEntries = modelEntry.supportedReasoningEfforts.filter((entry) => isNonEmptyString(entry.reasoningEffort));
|
|
1344
|
-
if (supportedEntries.length === 0) {
|
|
1345
|
-
return null;
|
|
1346
|
-
}
|
|
1347
|
-
const supportedValues = dedupeStrings(supportedEntries.map((entry) => entry.reasoningEffort));
|
|
1348
|
-
if (isNonEmptyString(candidateReasoningEffort) &&
|
|
1349
|
-
supportedValues.includes(candidateReasoningEffort)) {
|
|
1350
|
-
return candidateReasoningEffort;
|
|
1351
|
-
}
|
|
1352
|
-
if (supportedValues.includes(modelEntry.defaultReasoningEffort)) {
|
|
1353
|
-
return modelEntry.defaultReasoningEffort;
|
|
1354
|
-
}
|
|
1355
|
-
return supportedValues[0] ?? null;
|
|
639
|
+
return resolveReasoningEffortForModel(this.modelCatalog, modelId, candidateReasoningEffort);
|
|
1356
640
|
}
|
|
1357
641
|
getCollaborationModeValues(currentMode) {
|
|
1358
|
-
|
|
1359
|
-
.map((entry) => entry.mode)
|
|
1360
|
-
.filter((mode) => isNonEmptyString(mode));
|
|
1361
|
-
if (!values.includes(currentMode)) {
|
|
1362
|
-
values.unshift(currentMode);
|
|
1363
|
-
}
|
|
1364
|
-
return dedupeStrings(values);
|
|
1365
|
-
}
|
|
1366
|
-
resolveCurrentSandboxMode(session) {
|
|
1367
|
-
const currentSandboxMode = parseSandboxModeFromPolicy(session.defaults.sandboxPolicy);
|
|
1368
|
-
if (currentSandboxMode) {
|
|
1369
|
-
return currentSandboxMode;
|
|
1370
|
-
}
|
|
1371
|
-
const allowedSandboxMode = this.allowedSandboxModes[0];
|
|
1372
|
-
if (allowedSandboxMode) {
|
|
1373
|
-
return allowedSandboxMode;
|
|
1374
|
-
}
|
|
1375
|
-
throw new Error('Unable to resolve current sandbox mode for execution-mode options');
|
|
642
|
+
return getCollaborationModeValues(this.collaborationModes, currentMode);
|
|
1376
643
|
}
|
|
1377
644
|
getExecutionPresets(session) {
|
|
1378
|
-
|
|
1379
|
-
const policies = this.allowedApprovalPolicies.length > 0
|
|
1380
|
-
? this.allowedApprovalPolicies
|
|
1381
|
-
: [session.defaults.approvalPolicy];
|
|
1382
|
-
const sandboxModes = this.allowedSandboxModes.length > 0 ? this.allowedSandboxModes : [currentSandboxMode];
|
|
1383
|
-
const presets = [];
|
|
1384
|
-
const seen = new Set();
|
|
1385
|
-
const addPreset = (approvalPolicy, sandboxMode, description) => {
|
|
1386
|
-
const id = toExecutionPresetId(approvalPolicy, sandboxMode);
|
|
1387
|
-
if (seen.has(id)) {
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
seen.add(id);
|
|
1391
|
-
presets.push({
|
|
1392
|
-
id,
|
|
1393
|
-
name: formatExecutionPresetName(approvalPolicy, sandboxMode),
|
|
1394
|
-
...(description ? { description } : {}),
|
|
1395
|
-
approvalPolicy,
|
|
1396
|
-
sandboxMode,
|
|
1397
|
-
});
|
|
1398
|
-
};
|
|
1399
|
-
addPreset(session.defaults.approvalPolicy, currentSandboxMode, `Current session: ${formatExecutionPresetName(session.defaults.approvalPolicy, currentSandboxMode)}`);
|
|
1400
|
-
for (const policy of policies) {
|
|
1401
|
-
for (const sandboxMode of sandboxModes) {
|
|
1402
|
-
addPreset(policy, sandboxMode);
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
return presets;
|
|
1406
|
-
}
|
|
1407
|
-
resolveExecutionPresetId(session, presets) {
|
|
1408
|
-
const currentSandboxMode = this.resolveCurrentSandboxMode(session);
|
|
1409
|
-
const currentPresetId = toExecutionPresetId(session.defaults.approvalPolicy, currentSandboxMode);
|
|
1410
|
-
const fallbackPresetId = presets[0]?.id;
|
|
1411
|
-
if (!fallbackPresetId) {
|
|
1412
|
-
throw new Error('Execution-mode presets are unavailable for this session');
|
|
1413
|
-
}
|
|
1414
|
-
return presets.some((preset) => preset.id === currentPresetId)
|
|
1415
|
-
? currentPresetId
|
|
1416
|
-
: fallbackPresetId;
|
|
645
|
+
return getExecutionPresets(session, this.allowedApprovalPolicies, this.allowedSandboxModes);
|
|
1417
646
|
}
|
|
1418
647
|
requireSession(sessionId) {
|
|
1419
|
-
const session = this.
|
|
648
|
+
const session = this.stateContainer.getSession(sessionId);
|
|
1420
649
|
if (!session) {
|
|
1421
650
|
throw RequestError.invalidParams({ sessionId });
|
|
1422
651
|
}
|
|
1423
652
|
return session;
|
|
1424
653
|
}
|
|
1425
|
-
async loadConfigRequirements() {
|
|
1426
|
-
const raw = await this.codex.request('configRequirements/read', undefined);
|
|
1427
|
-
const parsed = configRequirementsReadResponseSchema.parse(raw);
|
|
1428
|
-
const requirements = parsed.requirements;
|
|
1429
|
-
const allowedApprovalPolicies = dedupeStrings((requirements?.allowedApprovalPolicies ?? []).filter(isNonEmptyString));
|
|
1430
|
-
const allowedSandboxModes = dedupeStrings((requirements?.allowedSandboxModes ?? []).filter((mode) => mode === 'read-only' || mode === 'workspace-write' || mode === 'danger-full-access'));
|
|
1431
|
-
const hasExplicitApprovalPolicies = Array.isArray(requirements?.allowedApprovalPolicies);
|
|
1432
|
-
const hasExplicitSandboxModes = Array.isArray(requirements?.allowedSandboxModes);
|
|
1433
|
-
return {
|
|
1434
|
-
allowedApprovalPolicies: allowedApprovalPolicies.length > 0
|
|
1435
|
-
? allowedApprovalPolicies
|
|
1436
|
-
: hasExplicitApprovalPolicies
|
|
1437
|
-
? []
|
|
1438
|
-
: DEFAULT_APPROVAL_POLICIES,
|
|
1439
|
-
allowedSandboxModes: allowedSandboxModes.length > 0
|
|
1440
|
-
? allowedSandboxModes
|
|
1441
|
-
: hasExplicitSandboxModes
|
|
1442
|
-
? []
|
|
1443
|
-
: DEFAULT_SANDBOX_MODES,
|
|
1444
|
-
};
|
|
1445
|
-
}
|
|
1446
|
-
async loadCollaborationModes() {
|
|
1447
|
-
const entries = [];
|
|
1448
|
-
let cursor = null;
|
|
1449
|
-
for (;;) {
|
|
1450
|
-
const response = await this.requestCollaborationModeListWithRetry(cursor);
|
|
1451
|
-
entries.push(...response.data.flatMap((entry) => isNonEmptyString(entry.mode)
|
|
1452
|
-
? [
|
|
1453
|
-
{
|
|
1454
|
-
mode: entry.mode,
|
|
1455
|
-
name: entry.name,
|
|
1456
|
-
model: entry.model ?? null,
|
|
1457
|
-
reasoningEffort: entry.reasoning_effort ?? null,
|
|
1458
|
-
developerInstructions: entry.developer_instructions ?? null,
|
|
1459
|
-
},
|
|
1460
|
-
]
|
|
1461
|
-
: []));
|
|
1462
|
-
cursor = response.nextCursor ?? null;
|
|
1463
|
-
if (!cursor) {
|
|
1464
|
-
break;
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
if (entries.length === 0) {
|
|
1468
|
-
throw new Error('Codex collaborationMode/list returned no modes');
|
|
1469
|
-
}
|
|
1470
|
-
return entries;
|
|
1471
|
-
}
|
|
1472
|
-
async requestCollaborationModeListWithRetry(cursor, maxAttempts = 3) {
|
|
1473
|
-
let attempt = 0;
|
|
1474
|
-
let lastError;
|
|
1475
|
-
while (attempt < maxAttempts) {
|
|
1476
|
-
attempt += 1;
|
|
1477
|
-
try {
|
|
1478
|
-
const raw = await this.codex.request('collaborationMode/list', cursor ? { cursor } : {});
|
|
1479
|
-
return collaborationModeListResponseSchema.parse(raw);
|
|
1480
|
-
}
|
|
1481
|
-
catch (error) {
|
|
1482
|
-
lastError = error;
|
|
1483
|
-
if (!(error instanceof CodexRequestError) ||
|
|
1484
|
-
error.code !== -32_001 ||
|
|
1485
|
-
attempt >= maxAttempts) {
|
|
1486
|
-
throw error;
|
|
1487
|
-
}
|
|
1488
|
-
const delayMs = Math.round(2 ** attempt * 100 + Math.random() * 120);
|
|
1489
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
1490
|
-
}
|
|
1491
|
-
}
|
|
1492
|
-
throw lastError;
|
|
1493
|
-
}
|
|
1494
|
-
async loadModelCatalog() {
|
|
1495
|
-
const models = [];
|
|
1496
|
-
let cursor = null;
|
|
1497
|
-
for (;;) {
|
|
1498
|
-
const response = await this.requestModelListWithRetry(cursor);
|
|
1499
|
-
models.push(...response.data.map((model) => ({
|
|
1500
|
-
id: model.id,
|
|
1501
|
-
displayName: model.displayName,
|
|
1502
|
-
description: model.description,
|
|
1503
|
-
defaultReasoningEffort: model.defaultReasoningEffort,
|
|
1504
|
-
supportedReasoningEfforts: (model.supportedReasoningEfforts ?? [])
|
|
1505
|
-
.filter((entry) => isNonEmptyString(entry.reasoningEffort))
|
|
1506
|
-
.map((entry) => ({
|
|
1507
|
-
reasoningEffort: entry.reasoningEffort,
|
|
1508
|
-
description: entry.description,
|
|
1509
|
-
})),
|
|
1510
|
-
inputModalities: model.inputModalities ?? [],
|
|
1511
|
-
isDefault: model.isDefault ?? false,
|
|
1512
|
-
})));
|
|
1513
|
-
cursor = response.nextCursor ?? null;
|
|
1514
|
-
if (!cursor) {
|
|
1515
|
-
return models;
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
async requestModelListWithRetry(cursor, maxAttempts = 3) {
|
|
1520
|
-
let attempt = 0;
|
|
1521
|
-
let lastError;
|
|
1522
|
-
while (attempt < maxAttempts) {
|
|
1523
|
-
attempt += 1;
|
|
1524
|
-
try {
|
|
1525
|
-
const raw = await this.codex.request('model/list', cursor ? { cursor } : {});
|
|
1526
|
-
return modelListResponseSchema.parse(raw);
|
|
1527
|
-
}
|
|
1528
|
-
catch (error) {
|
|
1529
|
-
lastError = error;
|
|
1530
|
-
if (!(error instanceof CodexRequestError) ||
|
|
1531
|
-
error.code !== -32_001 ||
|
|
1532
|
-
attempt >= maxAttempts) {
|
|
1533
|
-
throw error;
|
|
1534
|
-
}
|
|
1535
|
-
const delayMs = Math.round(2 ** attempt * 100 + Math.random() * 120);
|
|
1536
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
1537
|
-
}
|
|
1538
|
-
}
|
|
1539
|
-
throw lastError;
|
|
1540
|
-
}
|
|
1541
654
|
async replayThreadHistory(sessionId, threadId) {
|
|
1542
|
-
|
|
1543
|
-
const threadReadRaw = await this.codex.request('thread/read', {
|
|
1544
|
-
threadId,
|
|
1545
|
-
includeTurns: true,
|
|
1546
|
-
});
|
|
1547
|
-
const threadRead = threadReadResponseSchema.parse(threadReadRaw);
|
|
1548
|
-
for (const turn of threadRead.thread.turns) {
|
|
1549
|
-
for (const item of turn.items) {
|
|
1550
|
-
await this.replayThreadHistoryItem(session, sessionId, turn.id, item);
|
|
1551
|
-
}
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
async replayThreadHistoryItem(session, sessionId, turnId, item) {
|
|
1555
|
-
if (item.type === 'userMessage') {
|
|
1556
|
-
await this.replayUserMessageHistoryItem(sessionId, item);
|
|
1557
|
-
return;
|
|
1558
|
-
}
|
|
1559
|
-
if (item.type === 'agentMessage') {
|
|
1560
|
-
await this.replayAgentMessageHistoryItem(sessionId, item);
|
|
1561
|
-
return;
|
|
1562
|
-
}
|
|
1563
|
-
await this.replayToolLikeHistoryItem(session, sessionId, turnId, item);
|
|
1564
|
-
}
|
|
1565
|
-
async replayUserMessageHistoryItem(sessionId, item) {
|
|
1566
|
-
const contentBlocks = Array.isArray(item.content) ? item.content : [];
|
|
1567
|
-
for (const content of contentBlocks) {
|
|
1568
|
-
if (!isRecord(content) || content.type !== 'text' || typeof content.text !== 'string') {
|
|
1569
|
-
continue;
|
|
1570
|
-
}
|
|
1571
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1572
|
-
sessionUpdate: 'user_message_chunk',
|
|
1573
|
-
content: { type: 'text', text: content.text },
|
|
1574
|
-
});
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
async replayAgentMessageHistoryItem(sessionId, item) {
|
|
1578
|
-
const text = asString(item.text);
|
|
1579
|
-
if (!text) {
|
|
1580
|
-
return;
|
|
1581
|
-
}
|
|
1582
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1583
|
-
sessionUpdate: 'agent_message_chunk',
|
|
1584
|
-
content: { type: 'text', text },
|
|
1585
|
-
});
|
|
1586
|
-
}
|
|
1587
|
-
async replayToolLikeHistoryItem(session, sessionId, turnId, item) {
|
|
1588
|
-
if (item.type === 'reasoning') {
|
|
1589
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1590
|
-
sessionUpdate: 'tool_call',
|
|
1591
|
-
toolCallId: resolveToolCallId({ itemId: item.id, source: item }),
|
|
1592
|
-
title: 'reasoning',
|
|
1593
|
-
kind: 'think',
|
|
1594
|
-
status: 'completed',
|
|
1595
|
-
rawInput: item,
|
|
1596
|
-
rawOutput: item,
|
|
1597
|
-
});
|
|
1598
|
-
await this.emitReasoningThoughtChunkFromItem(sessionId, item);
|
|
1599
|
-
session.replayedTurnItemKeys.add(toTurnItemKey(turnId, item.id));
|
|
1600
|
-
return;
|
|
1601
|
-
}
|
|
1602
|
-
const toolInfo = this.buildToolCallState(session, item, turnId);
|
|
1603
|
-
if (!toolInfo) {
|
|
1604
|
-
this.reportShapeDrift('unhandled_replay_item', {
|
|
1605
|
-
turnId,
|
|
1606
|
-
itemType: item.type,
|
|
1607
|
-
itemId: item.id,
|
|
1608
|
-
});
|
|
1609
|
-
return;
|
|
1610
|
-
}
|
|
1611
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1612
|
-
sessionUpdate: 'tool_call',
|
|
1613
|
-
toolCallId: toolInfo.toolCallId,
|
|
1614
|
-
title: toolInfo.title,
|
|
1615
|
-
kind: toolInfo.kind,
|
|
1616
|
-
status: 'completed',
|
|
1617
|
-
rawInput: item,
|
|
1618
|
-
rawOutput: item,
|
|
1619
|
-
});
|
|
1620
|
-
session.replayedTurnItemKeys.add(toTurnItemKey(turnId, item.id));
|
|
655
|
+
await this.streamEventHandler.replayThreadHistory(sessionId, threadId);
|
|
1621
656
|
}
|
|
1622
657
|
async handleCodexNotification(method, params) {
|
|
1623
|
-
|
|
1624
|
-
if (!parsed.success) {
|
|
1625
|
-
this.reportShapeDrift('malformed_notification', {
|
|
1626
|
-
method,
|
|
1627
|
-
issues: parsed.error.issues.slice(0, 3).map((issue) => issue.message),
|
|
1628
|
-
});
|
|
1629
|
-
return;
|
|
1630
|
-
}
|
|
1631
|
-
const notification = parsed.data;
|
|
1632
|
-
if (notification.method === 'error' || notification.method === 'turn/started') {
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
const sessionId = this.sessionIdByThreadId.get(notification.params.threadId);
|
|
1636
|
-
if (!sessionId) {
|
|
1637
|
-
return;
|
|
1638
|
-
}
|
|
1639
|
-
const session = this.sessions.get(sessionId);
|
|
1640
|
-
if (!session) {
|
|
1641
|
-
return;
|
|
1642
|
-
}
|
|
1643
|
-
if (notification.method === 'item/agentMessage/delta') {
|
|
1644
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1645
|
-
sessionUpdate: 'agent_message_chunk',
|
|
1646
|
-
content: {
|
|
1647
|
-
type: 'text',
|
|
1648
|
-
text: notification.params.delta,
|
|
1649
|
-
},
|
|
1650
|
-
});
|
|
1651
|
-
return;
|
|
1652
|
-
}
|
|
1653
|
-
if (notification.method === 'item/plan/delta') {
|
|
1654
|
-
await this.handlePlanDelta(sessionId, session, notification.params.itemId, notification.params.delta);
|
|
1655
|
-
return;
|
|
1656
|
-
}
|
|
1657
|
-
if (notification.method === 'item/reasoning/summaryTextDelta') {
|
|
1658
|
-
await this.emitReasoningThoughtDelta(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta);
|
|
1659
|
-
return;
|
|
1660
|
-
}
|
|
1661
|
-
if (notification.method === 'item/commandExecution/outputDelta') {
|
|
1662
|
-
await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta, 'commandExecution');
|
|
1663
|
-
return;
|
|
1664
|
-
}
|
|
1665
|
-
if (notification.method === 'item/fileChange/outputDelta') {
|
|
1666
|
-
await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.delta, 'fileChange');
|
|
1667
|
-
return;
|
|
1668
|
-
}
|
|
1669
|
-
if (notification.method === 'item/mcpToolCall/progress') {
|
|
1670
|
-
await this.emitToolCallProgress(sessionId, session, notification.params.turnId, notification.params.itemId, notification.params.message, 'mcpToolCall');
|
|
1671
|
-
return;
|
|
1672
|
-
}
|
|
1673
|
-
if (notification.method === 'item/started') {
|
|
1674
|
-
await this.handleItemStarted(session, notification.params.item, notification.params.turnId);
|
|
1675
|
-
return;
|
|
1676
|
-
}
|
|
1677
|
-
if (notification.method === 'item/completed') {
|
|
1678
|
-
await this.handleItemCompleted(session, notification.params.item, notification.params.turnId);
|
|
1679
|
-
return;
|
|
1680
|
-
}
|
|
1681
|
-
if (notification.method === 'turn/completed') {
|
|
1682
|
-
await this.handleTurnCompletedNotification(session, notification.params.turn.id, notification.params.turn.status, notification.params.turn.error?.message);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
async handlePlanDelta(sessionId, session, itemId, delta) {
|
|
1686
|
-
const previous = session.planTextByItemId.get(itemId) ?? '';
|
|
1687
|
-
const next = `${previous}${delta}`;
|
|
1688
|
-
session.planTextByItemId.set(itemId, next);
|
|
1689
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1690
|
-
sessionUpdate: 'plan',
|
|
1691
|
-
entries: [
|
|
1692
|
-
{
|
|
1693
|
-
content: next,
|
|
1694
|
-
priority: 'medium',
|
|
1695
|
-
status: 'in_progress',
|
|
1696
|
-
},
|
|
1697
|
-
],
|
|
1698
|
-
});
|
|
658
|
+
await this.streamEventHandler.handleCodexNotification({ method, params });
|
|
1699
659
|
}
|
|
1700
660
|
async emitReasoningThoughtChunkFromItem(sessionId, item) {
|
|
1701
661
|
const text = extractReasoningTextLocal(item);
|
|
@@ -1707,262 +667,11 @@ export class CodexAppServerAcpAdapter {
|
|
|
1707
667
|
content: { type: 'text', text },
|
|
1708
668
|
});
|
|
1709
669
|
}
|
|
1710
|
-
|
|
1711
|
-
return
|
|
1712
|
-
}
|
|
1713
|
-
async emitReasoningThoughtDelta(sessionId, session, turnId, itemId, delta) {
|
|
1714
|
-
if (this.isReplayedTurnItem(session, turnId, itemId)) {
|
|
1715
|
-
return;
|
|
1716
|
-
}
|
|
1717
|
-
if (delta.length === 0) {
|
|
1718
|
-
return;
|
|
1719
|
-
}
|
|
1720
|
-
const existing = session.toolCallsByItemId.get(itemId);
|
|
1721
|
-
if (!existing) {
|
|
1722
|
-
const toolCallId = resolveToolCallId({
|
|
1723
|
-
itemId,
|
|
1724
|
-
});
|
|
1725
|
-
session.toolCallsByItemId.set(itemId, {
|
|
1726
|
-
toolCallId,
|
|
1727
|
-
title: 'reasoning',
|
|
1728
|
-
kind: 'think',
|
|
1729
|
-
locations: [],
|
|
1730
|
-
});
|
|
1731
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1732
|
-
sessionUpdate: 'tool_call',
|
|
1733
|
-
toolCallId,
|
|
1734
|
-
title: 'reasoning',
|
|
1735
|
-
kind: 'think',
|
|
1736
|
-
status: 'pending',
|
|
1737
|
-
rawInput: {
|
|
1738
|
-
type: 'reasoning',
|
|
1739
|
-
id: itemId,
|
|
1740
|
-
},
|
|
1741
|
-
});
|
|
1742
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1743
|
-
sessionUpdate: 'tool_call_update',
|
|
1744
|
-
toolCallId,
|
|
1745
|
-
title: 'reasoning',
|
|
1746
|
-
kind: 'think',
|
|
1747
|
-
status: 'in_progress',
|
|
1748
|
-
});
|
|
1749
|
-
}
|
|
1750
|
-
session.reasoningDeltaItemIds.add(itemId);
|
|
1751
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1752
|
-
sessionUpdate: 'agent_thought_chunk',
|
|
1753
|
-
content: { type: 'text', text: delta },
|
|
1754
|
-
});
|
|
1755
|
-
}
|
|
1756
|
-
async emitToolCallProgress(sessionId, session, turnId, itemId, output, source) {
|
|
1757
|
-
if (this.isReplayedTurnItem(session, turnId, itemId)) {
|
|
1758
|
-
return;
|
|
1759
|
-
}
|
|
1760
|
-
const toolCall = session.toolCallsByItemId.get(itemId);
|
|
1761
|
-
if (!toolCall) {
|
|
1762
|
-
this.reportShapeDrift('tool_progress_without_tool_call', { turnId, itemId });
|
|
1763
|
-
return;
|
|
1764
|
-
}
|
|
1765
|
-
if (session.syntheticallyCompletedToolItemIds.has(itemId)) {
|
|
1766
|
-
return;
|
|
1767
|
-
}
|
|
1768
|
-
if (source === 'commandExecution' && isCommandExecutionSessionHandoffOutput(output)) {
|
|
1769
|
-
session.syntheticallyCompletedToolItemIds.add(itemId);
|
|
1770
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1771
|
-
sessionUpdate: 'tool_call_update',
|
|
1772
|
-
toolCallId: toolCall.toolCallId,
|
|
1773
|
-
status: 'completed',
|
|
1774
|
-
kind: toolCall.kind,
|
|
1775
|
-
title: toolCall.title,
|
|
1776
|
-
...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
|
|
1777
|
-
rawOutput: output,
|
|
1778
|
-
});
|
|
1779
|
-
return;
|
|
1780
|
-
}
|
|
1781
|
-
await this.emitSessionUpdate(sessionId, {
|
|
1782
|
-
sessionUpdate: 'tool_call_update',
|
|
1783
|
-
toolCallId: toolCall.toolCallId,
|
|
1784
|
-
status: 'in_progress',
|
|
1785
|
-
...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
|
|
1786
|
-
rawOutput: output,
|
|
1787
|
-
});
|
|
1788
|
-
}
|
|
1789
|
-
async handleTurnCompletedNotification(session, turnId, status, errorMessage) {
|
|
1790
|
-
if (status === 'inProgress') {
|
|
1791
|
-
return;
|
|
1792
|
-
}
|
|
1793
|
-
const completionStatus = status;
|
|
1794
|
-
if (this.shouldDeferTurnCompletion(session, turnId, completionStatus)) {
|
|
1795
|
-
session.pendingTurnCompletionsByTurnId.set(turnId, this.buildPendingTurnCompletion(completionStatus, errorMessage));
|
|
1796
|
-
return;
|
|
1797
|
-
}
|
|
1798
|
-
await this.finalizeTurnCompletion(session, completionStatus, errorMessage);
|
|
1799
|
-
}
|
|
1800
|
-
shouldDeferTurnCompletion(session, turnId, status) {
|
|
1801
|
-
if (!session.activeTurn || session.activeTurn.turnId !== turnId) {
|
|
1802
|
-
return true;
|
|
1803
|
-
}
|
|
1804
|
-
return status !== 'interrupted' && this.hasPendingPlanApprovals(session, turnId);
|
|
1805
|
-
}
|
|
1806
|
-
buildPendingTurnCompletion(status, errorMessage) {
|
|
1807
|
-
const stopReason = status === 'interrupted' ? 'cancelled' : 'end_turn';
|
|
1808
|
-
if (status === 'failed' && errorMessage) {
|
|
1809
|
-
return { stopReason, errorMessage };
|
|
1810
|
-
}
|
|
1811
|
-
return { stopReason };
|
|
1812
|
-
}
|
|
1813
|
-
async finalizeTurnCompletion(session, status, errorMessage) {
|
|
1814
|
-
if (status === 'interrupted') {
|
|
1815
|
-
this.settleTurn(session, 'cancelled');
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
if (status === 'failed' && errorMessage) {
|
|
1819
|
-
await this.emitTurnFailureMessage(session.sessionId, errorMessage);
|
|
1820
|
-
}
|
|
1821
|
-
if (status === 'failed') {
|
|
1822
|
-
this.settleTurn(session, 'end_turn');
|
|
1823
|
-
return;
|
|
1824
|
-
}
|
|
1825
|
-
this.settleTurn(session, session.activeTurn?.cancelRequested ? 'cancelled' : 'end_turn');
|
|
1826
|
-
}
|
|
1827
|
-
async handleItemStarted(session, item, turnId) {
|
|
1828
|
-
if (this.isReplayedTurnItem(session, turnId, item.id)) {
|
|
1829
|
-
return;
|
|
1830
|
-
}
|
|
1831
|
-
if (item.type === 'reasoning') {
|
|
1832
|
-
const existing = session.toolCallsByItemId.get(item.id);
|
|
1833
|
-
const toolInfo = existing ??
|
|
1834
|
-
{
|
|
1835
|
-
toolCallId: resolveToolCallId({
|
|
1836
|
-
itemId: item.id,
|
|
1837
|
-
source: item,
|
|
1838
|
-
}),
|
|
1839
|
-
title: 'reasoning',
|
|
1840
|
-
kind: 'think',
|
|
1841
|
-
locations: [],
|
|
1842
|
-
};
|
|
1843
|
-
if (!existing) {
|
|
1844
|
-
session.syntheticallyCompletedToolItemIds.delete(item.id);
|
|
1845
|
-
session.toolCallsByItemId.set(item.id, toolInfo);
|
|
1846
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1847
|
-
sessionUpdate: 'tool_call',
|
|
1848
|
-
toolCallId: toolInfo.toolCallId,
|
|
1849
|
-
title: toolInfo.title,
|
|
1850
|
-
kind: toolInfo.kind,
|
|
1851
|
-
status: 'pending',
|
|
1852
|
-
rawInput: item,
|
|
1853
|
-
});
|
|
1854
|
-
}
|
|
1855
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1856
|
-
sessionUpdate: 'tool_call_update',
|
|
1857
|
-
toolCallId: toolInfo.toolCallId,
|
|
1858
|
-
title: toolInfo.title,
|
|
1859
|
-
kind: toolInfo.kind,
|
|
1860
|
-
status: 'in_progress',
|
|
1861
|
-
});
|
|
1862
|
-
return;
|
|
1863
|
-
}
|
|
1864
|
-
const toolInfo = this.buildToolCallState(session, item, turnId);
|
|
1865
|
-
if (!toolInfo) {
|
|
1866
|
-
this.reportShapeDrift('unhandled_item_started_type', {
|
|
1867
|
-
turnId,
|
|
1868
|
-
itemType: item.type,
|
|
1869
|
-
itemId: item.id,
|
|
1870
|
-
});
|
|
1871
|
-
return;
|
|
1872
|
-
}
|
|
1873
|
-
session.syntheticallyCompletedToolItemIds.delete(item.id);
|
|
1874
|
-
session.toolCallsByItemId.set(item.id, toolInfo);
|
|
1875
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1876
|
-
sessionUpdate: 'tool_call',
|
|
1877
|
-
toolCallId: toolInfo.toolCallId,
|
|
1878
|
-
title: toolInfo.title,
|
|
1879
|
-
kind: toolInfo.kind,
|
|
1880
|
-
status: 'pending',
|
|
1881
|
-
...(toolInfo.locations.length > 0 ? { locations: toolInfo.locations } : {}),
|
|
1882
|
-
rawInput: item,
|
|
1883
|
-
});
|
|
1884
|
-
const itemStatus = toToolStatus(item.status);
|
|
1885
|
-
if (itemStatus === 'in_progress') {
|
|
1886
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1887
|
-
sessionUpdate: 'tool_call_update',
|
|
1888
|
-
toolCallId: toolInfo.toolCallId,
|
|
1889
|
-
status: 'in_progress',
|
|
1890
|
-
});
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
async handleItemCompleted(session, item, turnId) {
|
|
1894
|
-
if (this.isReplayedTurnItem(session, turnId, item.id)) {
|
|
1895
|
-
return;
|
|
1896
|
-
}
|
|
1897
|
-
if (item.type === 'reasoning') {
|
|
1898
|
-
const existing = session.toolCallsByItemId.get(item.id);
|
|
1899
|
-
const reasoningToolCallId = existing?.toolCallId ??
|
|
1900
|
-
resolveToolCallId({
|
|
1901
|
-
itemId: item.id,
|
|
1902
|
-
source: item,
|
|
1903
|
-
});
|
|
1904
|
-
if (existing) {
|
|
1905
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1906
|
-
sessionUpdate: 'tool_call_update',
|
|
1907
|
-
toolCallId: reasoningToolCallId,
|
|
1908
|
-
title: existing.title,
|
|
1909
|
-
kind: existing.kind,
|
|
1910
|
-
status: toToolStatus(item.status) ?? 'completed',
|
|
1911
|
-
rawOutput: item,
|
|
1912
|
-
});
|
|
1913
|
-
}
|
|
1914
|
-
else {
|
|
1915
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1916
|
-
sessionUpdate: 'tool_call',
|
|
1917
|
-
toolCallId: reasoningToolCallId,
|
|
1918
|
-
title: 'reasoning',
|
|
1919
|
-
kind: 'think',
|
|
1920
|
-
status: toToolStatus(item.status) ?? 'completed',
|
|
1921
|
-
rawInput: item,
|
|
1922
|
-
rawOutput: item,
|
|
1923
|
-
});
|
|
1924
|
-
}
|
|
1925
|
-
session.toolCallsByItemId.delete(item.id);
|
|
1926
|
-
session.syntheticallyCompletedToolItemIds.delete(item.id);
|
|
1927
|
-
const sawDelta = session.reasoningDeltaItemIds.has(item.id);
|
|
1928
|
-
session.reasoningDeltaItemIds.delete(item.id);
|
|
1929
|
-
if (!sawDelta) {
|
|
1930
|
-
await this.emitReasoningThoughtChunkFromItem(session.sessionId, item);
|
|
1931
|
-
}
|
|
1932
|
-
return;
|
|
1933
|
-
}
|
|
1934
|
-
const existing = session.toolCallsByItemId.get(item.id);
|
|
1935
|
-
if (!existing) {
|
|
1936
|
-
this.reportShapeDrift('item_completed_without_started_state', {
|
|
1937
|
-
turnId,
|
|
1938
|
-
itemType: item.type,
|
|
1939
|
-
itemId: item.id,
|
|
1940
|
-
});
|
|
1941
|
-
return;
|
|
1942
|
-
}
|
|
1943
|
-
const shouldHoldTurnForPlanApproval = item.type === 'plan' &&
|
|
670
|
+
shouldHoldTurnForPlanApproval(session, item, turnId) {
|
|
671
|
+
return (item.type === 'plan' &&
|
|
1944
672
|
isPlanLikeMode(session.defaults.collaborationMode) &&
|
|
1945
673
|
!session.planApprovalRequestedByTurnId.has(turnId) &&
|
|
1946
|
-
this.extractPlanApprovalText(session, item) !== null;
|
|
1947
|
-
if (shouldHoldTurnForPlanApproval) {
|
|
1948
|
-
this.holdTurnUntilPlanApprovalResolves(session, turnId);
|
|
1949
|
-
}
|
|
1950
|
-
const statusFromItem = toToolStatus(item.status);
|
|
1951
|
-
const status = statusFromItem ?? 'completed';
|
|
1952
|
-
const completionLocations = this.extractLocations(item);
|
|
1953
|
-
const locations = dedupeLocations([...existing.locations, ...completionLocations]);
|
|
1954
|
-
await this.emitSessionUpdate(session.sessionId, {
|
|
1955
|
-
sessionUpdate: 'tool_call_update',
|
|
1956
|
-
toolCallId: existing.toolCallId,
|
|
1957
|
-
status,
|
|
1958
|
-
kind: existing.kind,
|
|
1959
|
-
title: existing.title,
|
|
1960
|
-
...(locations.length > 0 ? { locations } : {}),
|
|
1961
|
-
rawOutput: item,
|
|
1962
|
-
});
|
|
1963
|
-
session.toolCallsByItemId.delete(item.id);
|
|
1964
|
-
session.syntheticallyCompletedToolItemIds.delete(item.id);
|
|
1965
|
-
await this.maybeRequestPlanApproval(session, item, turnId, existing);
|
|
674
|
+
this.extractPlanApprovalText(session, item) !== null);
|
|
1966
675
|
}
|
|
1967
676
|
buildPlanApprovalInput(planText, sourceItemId) {
|
|
1968
677
|
return {
|
|
@@ -2001,11 +710,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
2001
710
|
return left.localeCompare(right);
|
|
2002
711
|
}
|
|
2003
712
|
resolveCollaborationModeLabel(modeId) {
|
|
2004
|
-
|
|
2005
|
-
if (entry?.name) {
|
|
2006
|
-
return entry.name;
|
|
2007
|
-
}
|
|
2008
|
-
return sanitizeModeName(modeId);
|
|
713
|
+
return resolveCollaborationModeLabel(this.collaborationModes, modeId);
|
|
2009
714
|
}
|
|
2010
715
|
buildPlanApprovalOptions(session) {
|
|
2011
716
|
const currentMode = session.defaults.collaborationMode;
|
|
@@ -2145,27 +850,6 @@ export class CodexAppServerAcpAdapter {
|
|
|
2145
850
|
await this.releaseTurnHoldForPlanApproval(session, turnId);
|
|
2146
851
|
}
|
|
2147
852
|
}
|
|
2148
|
-
extractLocations(item) {
|
|
2149
|
-
if (!isRecord(item) || item.type !== 'fileChange') {
|
|
2150
|
-
return [];
|
|
2151
|
-
}
|
|
2152
|
-
const changes = item.changes;
|
|
2153
|
-
if (!Array.isArray(changes)) {
|
|
2154
|
-
return [];
|
|
2155
|
-
}
|
|
2156
|
-
const locations = [];
|
|
2157
|
-
for (const change of changes) {
|
|
2158
|
-
if (!isRecord(change)) {
|
|
2159
|
-
continue;
|
|
2160
|
-
}
|
|
2161
|
-
const path = asString(change.path);
|
|
2162
|
-
if (!path) {
|
|
2163
|
-
continue;
|
|
2164
|
-
}
|
|
2165
|
-
locations.push({ path });
|
|
2166
|
-
}
|
|
2167
|
-
return locations;
|
|
2168
|
-
}
|
|
2169
853
|
buildToolCallState(session, item, _turnId) {
|
|
2170
854
|
const kindByType = {
|
|
2171
855
|
commandExecution: 'execute',
|
|
@@ -2191,7 +875,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
2191
875
|
}
|
|
2192
876
|
else if (item.type === 'fileChange') {
|
|
2193
877
|
title = 'fileChange';
|
|
2194
|
-
locations =
|
|
878
|
+
locations = extractLocations(item);
|
|
2195
879
|
}
|
|
2196
880
|
else if (item.type === 'mcpToolCall') {
|
|
2197
881
|
const server = asString(item.server) ?? 'mcp';
|
|
@@ -2212,280 +896,15 @@ export class CodexAppServerAcpAdapter {
|
|
|
2212
896
|
locations,
|
|
2213
897
|
};
|
|
2214
898
|
}
|
|
2215
|
-
buildPermissionOptions(params) {
|
|
2216
|
-
if (params.method === 'item/tool/requestUserInput') {
|
|
2217
|
-
return buildToolUserInputPermissionOptions(params.questions);
|
|
2218
|
-
}
|
|
2219
|
-
if (params.method === 'item/commandExecution/requestApproval') {
|
|
2220
|
-
return [
|
|
2221
|
-
{
|
|
2222
|
-
optionId: 'allow_always',
|
|
2223
|
-
name: 'Allow for session',
|
|
2224
|
-
kind: 'allow_always',
|
|
2225
|
-
},
|
|
2226
|
-
{
|
|
2227
|
-
optionId: 'allow_once',
|
|
2228
|
-
name: 'Allow once',
|
|
2229
|
-
kind: 'allow_once',
|
|
2230
|
-
},
|
|
2231
|
-
{
|
|
2232
|
-
optionId: 'reject_once',
|
|
2233
|
-
name: 'Reject',
|
|
2234
|
-
kind: 'reject_once',
|
|
2235
|
-
},
|
|
2236
|
-
];
|
|
2237
|
-
}
|
|
2238
|
-
return [
|
|
2239
|
-
{
|
|
2240
|
-
optionId: 'allow_once',
|
|
2241
|
-
name: 'Allow once',
|
|
2242
|
-
kind: 'allow_once',
|
|
2243
|
-
},
|
|
2244
|
-
{
|
|
2245
|
-
optionId: 'reject_once',
|
|
2246
|
-
name: 'Reject',
|
|
2247
|
-
kind: 'reject_once',
|
|
2248
|
-
},
|
|
2249
|
-
];
|
|
2250
|
-
}
|
|
2251
|
-
async maybeAutoApproveCommandRequest(params) {
|
|
2252
|
-
if (params.request.method !== 'item/commandExecution/requestApproval') {
|
|
2253
|
-
return false;
|
|
2254
|
-
}
|
|
2255
|
-
const scopeKey = buildCommandApprovalScopeKey({
|
|
2256
|
-
command: asString(params.request.params.command),
|
|
2257
|
-
cwd: asString(params.request.params.cwd) ?? params.session.cwd,
|
|
2258
|
-
});
|
|
2259
|
-
if (!(scopeKey && params.session.commandApprovalScopes.has(scopeKey))) {
|
|
2260
|
-
return false;
|
|
2261
|
-
}
|
|
2262
|
-
await this.respondToCodexPermissionRequest({
|
|
2263
|
-
request: params.request,
|
|
2264
|
-
permission: {
|
|
2265
|
-
outcome: { outcome: 'selected', optionId: 'allow_always' },
|
|
2266
|
-
},
|
|
2267
|
-
session: params.session,
|
|
2268
|
-
toolCallId: params.toolCallId,
|
|
2269
|
-
questions: [],
|
|
2270
|
-
});
|
|
2271
|
-
return true;
|
|
2272
|
-
}
|
|
2273
899
|
async handleCodexServerRequest(request) {
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
code: -32_602,
|
|
2283
|
-
message: 'Unsupported codex server request payload',
|
|
2284
|
-
});
|
|
2285
|
-
return;
|
|
2286
|
-
}
|
|
2287
|
-
const typed = parsed.data;
|
|
2288
|
-
const sessionId = this.sessionIdByThreadId.get(typed.params.threadId);
|
|
2289
|
-
if (!sessionId) {
|
|
2290
|
-
this.reportShapeDrift('request_for_unknown_thread', {
|
|
2291
|
-
method: typed.method,
|
|
2292
|
-
threadId: typed.params.threadId,
|
|
2293
|
-
itemId: typed.params.itemId,
|
|
2294
|
-
});
|
|
2295
|
-
this.codex.respondError(typed.id, {
|
|
2296
|
-
code: -32_603,
|
|
2297
|
-
message: 'No ACP session mapped for this thread',
|
|
2298
|
-
});
|
|
2299
|
-
return;
|
|
2300
|
-
}
|
|
2301
|
-
const session = this.sessions.get(sessionId);
|
|
2302
|
-
if (!session) {
|
|
2303
|
-
this.reportShapeDrift('request_for_missing_session', {
|
|
2304
|
-
method: typed.method,
|
|
2305
|
-
sessionId,
|
|
2306
|
-
itemId: typed.params.itemId,
|
|
2307
|
-
});
|
|
2308
|
-
this.codex.respondError(typed.id, {
|
|
2309
|
-
code: -32_603,
|
|
2310
|
-
message: 'No ACP session mapped for this thread',
|
|
2311
|
-
});
|
|
2312
|
-
return;
|
|
2313
|
-
}
|
|
2314
|
-
const existingTool = session.toolCallsByItemId.get(typed.params.itemId);
|
|
2315
|
-
const toolCall = existingTool ??
|
|
2316
|
-
this.buildApprovalToolCallState(session, typed.method, typed.params.itemId, typed.params.turnId, typed.params);
|
|
2317
|
-
session.toolCallsByItemId.set(typed.params.itemId, toolCall);
|
|
2318
|
-
if (!existingTool) {
|
|
2319
|
-
await this.emitSessionUpdate(sessionId, {
|
|
2320
|
-
sessionUpdate: 'tool_call',
|
|
2321
|
-
toolCallId: toolCall.toolCallId,
|
|
2322
|
-
title: toolCall.title,
|
|
2323
|
-
kind: toolCall.kind,
|
|
2324
|
-
status: 'pending',
|
|
2325
|
-
...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
|
|
2326
|
-
rawInput: typed.params,
|
|
2327
|
-
});
|
|
2328
|
-
}
|
|
2329
|
-
if (await this.maybeAutoApproveCommandRequest({
|
|
2330
|
-
request: typed,
|
|
2331
|
-
session,
|
|
2332
|
-
toolCallId: toolCall.toolCallId,
|
|
2333
|
-
})) {
|
|
2334
|
-
return;
|
|
2335
|
-
}
|
|
2336
|
-
const questions = typed.method === 'item/tool/requestUserInput' ? typed.params.questions : [];
|
|
2337
|
-
const permissionOptions = this.buildPermissionOptions({
|
|
2338
|
-
method: typed.method,
|
|
2339
|
-
questions,
|
|
2340
|
-
});
|
|
2341
|
-
await this.emitSessionUpdate(sessionId, {
|
|
2342
|
-
sessionUpdate: 'tool_call_update',
|
|
2343
|
-
toolCallId: toolCall.toolCallId,
|
|
2344
|
-
title: toolCall.title,
|
|
2345
|
-
kind: toolCall.kind,
|
|
2346
|
-
status: 'pending',
|
|
2347
|
-
...(toolCall.locations.length > 0 ? { locations: toolCall.locations } : {}),
|
|
2348
|
-
});
|
|
2349
|
-
const permissionResult = await this.connection.requestPermission({
|
|
2350
|
-
sessionId,
|
|
2351
|
-
toolCall: {
|
|
2352
|
-
toolCallId: toolCall.toolCallId,
|
|
2353
|
-
title: toolCall.title,
|
|
2354
|
-
kind: toolCall.kind,
|
|
2355
|
-
status: 'pending',
|
|
2356
|
-
rawInput: typed.params,
|
|
2357
|
-
},
|
|
2358
|
-
options: permissionOptions,
|
|
2359
|
-
});
|
|
2360
|
-
await this.respondToCodexPermissionRequest({
|
|
2361
|
-
request: typed,
|
|
2362
|
-
permission: permissionResult,
|
|
2363
|
-
session,
|
|
2364
|
-
toolCallId: toolCall.toolCallId,
|
|
2365
|
-
questions,
|
|
2366
|
-
});
|
|
2367
|
-
}
|
|
2368
|
-
catch (error) {
|
|
2369
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2370
|
-
this.codex.respondError(request.id, {
|
|
2371
|
-
code: -32_600,
|
|
2372
|
-
message: 'Failed to process codex approval request',
|
|
2373
|
-
data: { error: message },
|
|
2374
|
-
});
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
buildApprovalToolCallState(session, method, itemId, _turnId, params) {
|
|
2378
|
-
if (method === 'item/commandExecution/requestApproval') {
|
|
2379
|
-
const command = asString(params.command);
|
|
2380
|
-
const cwd = asString(params.cwd) ?? session.cwd;
|
|
2381
|
-
const parsed = resolveCommandDisplay({ command, cwd });
|
|
2382
|
-
return {
|
|
2383
|
-
toolCallId: resolveToolCallId({
|
|
2384
|
-
itemId,
|
|
2385
|
-
source: params,
|
|
2386
|
-
}),
|
|
2387
|
-
title: parsed.title,
|
|
2388
|
-
kind: parsed.kind,
|
|
2389
|
-
locations: parsed.locations,
|
|
2390
|
-
};
|
|
2391
|
-
}
|
|
2392
|
-
if (method === 'item/fileChange/requestApproval') {
|
|
2393
|
-
const grantRoot = asString(params.grantRoot);
|
|
2394
|
-
return {
|
|
2395
|
-
toolCallId: resolveToolCallId({
|
|
2396
|
-
itemId,
|
|
2397
|
-
source: params,
|
|
2398
|
-
}),
|
|
2399
|
-
title: 'fileChange',
|
|
2400
|
-
kind: 'edit',
|
|
2401
|
-
locations: grantRoot ? [{ path: grantRoot }] : [],
|
|
2402
|
-
};
|
|
2403
|
-
}
|
|
2404
|
-
return {
|
|
2405
|
-
toolCallId: resolveToolCallId({
|
|
2406
|
-
itemId,
|
|
2407
|
-
source: params,
|
|
2408
|
-
}),
|
|
2409
|
-
title: 'item/tool/requestUserInput',
|
|
2410
|
-
kind: 'other',
|
|
2411
|
-
locations: [],
|
|
2412
|
-
};
|
|
2413
|
-
}
|
|
2414
|
-
isAllowedPermissionSelection(selectedOptionId) {
|
|
2415
|
-
return selectedOptionId === 'allow_once' || selectedOptionId === 'allow_always';
|
|
2416
|
-
}
|
|
2417
|
-
async handleToolUserInputPermissionResponse(params) {
|
|
2418
|
-
if (params.request.method !== 'item/tool/requestUserInput') {
|
|
2419
|
-
return false;
|
|
2420
|
-
}
|
|
2421
|
-
const rejected = params.selectedOptionId === null || params.selectedOptionId === 'reject_once';
|
|
2422
|
-
let answers;
|
|
2423
|
-
try {
|
|
2424
|
-
answers = buildToolUserInputAnswers({
|
|
2425
|
-
questions: params.questions,
|
|
2426
|
-
permission: params.permission,
|
|
2427
|
-
selectedOptionId: params.selectedOptionId,
|
|
2428
|
-
});
|
|
2429
|
-
}
|
|
2430
|
-
catch (error) {
|
|
2431
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2432
|
-
this.codex.respondError(params.request.id, {
|
|
2433
|
-
code: -32_602,
|
|
2434
|
-
message: 'Failed to map requestUserInput answers',
|
|
2435
|
-
data: { error: message },
|
|
2436
|
-
});
|
|
2437
|
-
await this.emitSessionUpdate(params.session.sessionId, {
|
|
2438
|
-
sessionUpdate: 'tool_call_update',
|
|
2439
|
-
toolCallId: params.toolCallId,
|
|
2440
|
-
status: 'failed',
|
|
2441
|
-
rawOutput: { error: message },
|
|
2442
|
-
});
|
|
2443
|
-
return true;
|
|
2444
|
-
}
|
|
2445
|
-
this.codex.respondSuccess(params.request.id, {
|
|
2446
|
-
answers,
|
|
2447
|
-
});
|
|
2448
|
-
await this.emitSessionUpdate(params.session.sessionId, {
|
|
2449
|
-
sessionUpdate: 'tool_call_update',
|
|
2450
|
-
toolCallId: params.toolCallId,
|
|
2451
|
-
status: rejected ? 'failed' : 'completed',
|
|
2452
|
-
rawOutput: rejected ? { outcome: 'rejected' } : { answers },
|
|
2453
|
-
});
|
|
2454
|
-
return true;
|
|
2455
|
-
}
|
|
2456
|
-
async respondToCodexPermissionRequest(params) {
|
|
2457
|
-
const selected = params.permission.outcome.outcome === 'selected' ? params.permission.outcome.optionId : null;
|
|
2458
|
-
if (await this.handleToolUserInputPermissionResponse({
|
|
2459
|
-
...params,
|
|
2460
|
-
selectedOptionId: selected,
|
|
2461
|
-
})) {
|
|
2462
|
-
return;
|
|
2463
|
-
}
|
|
2464
|
-
if (params.request.method === 'item/commandExecution/requestApproval' &&
|
|
2465
|
-
selected === 'allow_always') {
|
|
2466
|
-
const scopeKey = buildCommandApprovalScopeKey({
|
|
2467
|
-
command: asString(params.request.params.command),
|
|
2468
|
-
cwd: asString(params.request.params.cwd) ?? params.session.cwd,
|
|
2469
|
-
});
|
|
2470
|
-
if (scopeKey) {
|
|
2471
|
-
params.session.commandApprovalScopes.add(scopeKey);
|
|
2472
|
-
}
|
|
2473
|
-
else {
|
|
2474
|
-
this.reportShapeDrift('allow_always_without_scope_key', {
|
|
2475
|
-
itemId: params.request.params.itemId,
|
|
2476
|
-
command: params.request.params.command,
|
|
2477
|
-
});
|
|
2478
|
-
}
|
|
2479
|
-
}
|
|
2480
|
-
const allow = this.isAllowedPermissionSelection(selected);
|
|
2481
|
-
this.codex.respondSuccess(params.request.id, {
|
|
2482
|
-
decision: allow ? 'accept' : 'decline',
|
|
2483
|
-
});
|
|
2484
|
-
await this.emitSessionUpdate(params.session.sessionId, {
|
|
2485
|
-
sessionUpdate: 'tool_call_update',
|
|
2486
|
-
toolCallId: params.toolCallId,
|
|
2487
|
-
status: allow ? 'in_progress' : 'failed',
|
|
2488
|
-
rawOutput: { decision: allow ? 'accept' : 'decline' },
|
|
900
|
+
await handleCodexServerPermissionRequest({
|
|
901
|
+
request,
|
|
902
|
+
sessionIdByThreadId: this.sessionIdByThreadId,
|
|
903
|
+
sessions: this.sessions,
|
|
904
|
+
connection: this.connection,
|
|
905
|
+
codex: this.codex,
|
|
906
|
+
emitSessionUpdate: (sessionId, update) => this.emitSessionUpdate(sessionId, update),
|
|
907
|
+
reportShapeDrift: (event, details) => this.reportShapeDrift(event, details),
|
|
2489
908
|
});
|
|
2490
909
|
}
|
|
2491
910
|
settleTurn(session, stopReason) {
|
|
@@ -2504,11 +923,7 @@ export class CodexAppServerAcpAdapter {
|
|
|
2504
923
|
session.pendingTurnCompletionsByTurnId.clear();
|
|
2505
924
|
}
|
|
2506
925
|
reportShapeDrift(event, details) {
|
|
2507
|
-
|
|
2508
|
-
this.shapeDriftCounts.set(event, count);
|
|
2509
|
-
const includeDetails = details !== undefined && (count <= 5 || count % 50 === 0);
|
|
2510
|
-
const detailsSuffix = includeDetails ? ` details=${toShapeDriftDetails(details)}` : '';
|
|
2511
|
-
process.stderr.write(`[codex-app-server-acp] shape-drift event=${event} count=${count}${detailsSuffix}\n`);
|
|
926
|
+
this.shapeDriftReporter.report(event, details);
|
|
2512
927
|
}
|
|
2513
928
|
async emitSessionUpdate(sessionId, update) {
|
|
2514
929
|
try {
|
|
@@ -2518,10 +933,10 @@ export class CodexAppServerAcpAdapter {
|
|
|
2518
933
|
}
|
|
2519
934
|
}
|
|
2520
935
|
}
|
|
2521
|
-
export function runCodexAppServerAcpAdapter() {
|
|
936
|
+
export function runCodexAppServerAcpAdapter(options) {
|
|
2522
937
|
const output = Writable.toWeb(process.stdout);
|
|
2523
938
|
const input = Readable.toWeb(process.stdin);
|
|
2524
939
|
const stream = ndJsonStream(output, input);
|
|
2525
|
-
new AgentSideConnection((connection) => new CodexAppServerAcpAdapter(connection), stream);
|
|
940
|
+
new AgentSideConnection((connection) => new CodexAppServerAcpAdapter(connection, undefined, options), stream);
|
|
2526
941
|
}
|
|
2527
942
|
//# sourceMappingURL=codex-app-server-acp-adapter.js.map
|