wind-agent-cli 1.37.2 → 1.37.3
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/LICENSE +718 -718
- package/README.md +1 -1
- package/dist/api-docs.html +901 -901
- package/dist/assets/{CodeEditor-B2Wf7Fg0.js → CodeEditor-BqmxpZ_D.js} +1 -1
- package/dist/assets/{FileTree-N2IkkHlv.js → FileTree-DLE7Ioai.js} +1 -1
- package/dist/assets/{GitPanel-DZCeuFZ2.js → GitPanel-f8RMRa8D.js} +1 -1
- package/dist/assets/{MarkdownPreview-C0tqYnVu.js → MarkdownPreview-93h_1tJa.js} +1 -1
- package/dist/assets/{PluginTabContent-Bnuf-fb8.js → PluginTabContent-DU1jjkXP.js} +1 -1
- package/dist/assets/{Shell-BfFnMZ-f.js → Shell-CN_2MRIM.js} +1 -1
- package/dist/assets/{StandaloneShell-QmyYwNAl.js → StandaloneShell-D0avS8UE.js} +1 -1
- package/dist/assets/{TaskMasterPanel-fMsmvN9L.js → TaskMasterPanel-Cpf1Q5Ph.js} +3 -3
- package/dist/assets/{abnfDiagram-N423BO3Z-DjPU7HLs.js → abnfDiagram-N423BO3Z-p3aJIm4T.js} +1 -1
- package/dist/assets/{arc-Pdq6Tvr3.js → arc-CTeud6Fl.js} +1 -1
- package/dist/assets/{architectureDiagram-T3A2C74G-D0JnT0Vh.js → architectureDiagram-T3A2C74G-CG7kRCJU.js} +1 -1
- package/dist/assets/{blockDiagram-VBNYF7ZC-DpaEf3mv.js → blockDiagram-VBNYF7ZC-oSjQ1SgE.js} +1 -1
- package/dist/assets/{c4Diagram-5PPSVZJV-MpqlPGFi.js → c4Diagram-5PPSVZJV-RkzF0DJV.js} +1 -1
- package/dist/assets/channel-BfQbarn9.js +1 -0
- package/dist/assets/{chunk-2GRJ4B5K-DoSdNo8u.js → chunk-2GRJ4B5K-B07uZ07O.js} +1 -1
- package/dist/assets/{chunk-2Q5K7J3B-CE7I3uMn.js → chunk-2Q5K7J3B-DNSfO7xS.js} +1 -1
- package/dist/assets/{chunk-5RXB4S5H-B4UQ8snD.js → chunk-5RXB4S5H-BTeYcgyb.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-B55XgqHZ.js → chunk-5VM5RSS4-B7vZV0zC.js} +1 -1
- package/dist/assets/{chunk-6Q2QTUOP-BS1KpefW.js → chunk-6Q2QTUOP-DuS_xUGG.js} +1 -1
- package/dist/assets/{chunk-GF5L2VYU-DkEPedJP.js → chunk-GF5L2VYU-CKLZ3iVD.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DOtkNhMm.js → chunk-JWPE2WC7-DD2hcXvs.js} +1 -1
- package/dist/assets/{chunk-KBJHAD2P-BXLjviqM.js → chunk-KBJHAD2P-Cz-l38qp.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-C50fjNNz.js → chunk-RYQCIY6F-DGFIU1YM.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-QBYqCkb7.js → chunk-XXDRQBXY-CmfzoYFl.js} +1 -1
- package/dist/assets/classDiagram-JCYQIIEL-Bpfe3kq7.js +1 -0
- package/dist/assets/classDiagram-v2-OCEON4UE-Bpfe3kq7.js +1 -0
- package/dist/assets/{code-xml-VK1YfShP.js → code-xml-CLpHzEOP.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-DrVTo1Nh.js → cose-bilkent-JH36ORCC-DlFcLXCB.js} +1 -1
- package/dist/assets/{cynefin-VYW2F7L2-DnJa_OlQ.js → cynefin-VYW2F7L2-P1HecReO.js} +1 -1
- package/dist/assets/{cynefinDiagram-MW4NZA55-CCxBjw9E.js → cynefinDiagram-MW4NZA55-COgduz5P.js} +1 -1
- package/dist/assets/{dagre-VZM6K2ZE-C_GvE4lu.js → dagre-VZM6K2ZE-Bbb-siGp.js} +1 -1
- package/dist/assets/{diagram-7IWD3JNH-pFzs9HEu.js → diagram-7IWD3JNH-9CWGFMYR.js} +1 -1
- package/dist/assets/{diagram-B4RE2ZJO-CcehQC7x.js → diagram-B4RE2ZJO-TWK59T6V.js} +1 -1
- package/dist/assets/{diagram-LBJQPF4R-hfKcrrxe.js → diagram-LBJQPF4R-ErMC9yaa.js} +1 -1
- package/dist/assets/{diagram-Q27KOJAE-C1semJfK.js → diagram-Q27KOJAE-Dt_-C7hV.js} +1 -1
- package/dist/assets/{diagram-UB23O5K3-57hvXQXO.js → diagram-UB23O5K3-BJ1DnRAF.js} +1 -1
- package/dist/assets/{ebnfDiagram-BXEA7PRR-9KIAlAVw.js → ebnfDiagram-BXEA7PRR-CE1YaQ9s.js} +1 -1
- package/dist/assets/{erDiagram-JOGREHBK-B7OzJ767.js → erDiagram-JOGREHBK-Bqk7N9aY.js} +1 -1
- package/dist/assets/{flowDiagram-UKHOOZJN-CJV8fQPR.js → flowDiagram-UKHOOZJN-DEr2II5V.js} +1 -1
- package/dist/assets/{ganttDiagram-PKOTCBZU-CbMNWWQu.js → ganttDiagram-PKOTCBZU-CWYAUeYN.js} +1 -1
- package/dist/assets/{gitGraphDiagram-DS77QQ5N-I_vZ5waO.js → gitGraphDiagram-DS77QQ5N-tdEcEIM6.js} +1 -1
- package/dist/assets/{index-ZHwIojzi.js → index-B-sTfSZq.js} +1 -1
- package/dist/assets/{index-GFhXZyl2.js → index-BSe3UiFA.js} +1 -1
- package/dist/assets/{index-DFnVoqpx.js → index-B_FDMWar.js} +5 -5
- package/dist/assets/{index-DlSeAkw_.js → index-CWJtg2pR.js} +1 -1
- package/dist/assets/{infoDiagram-6WML65LV-Dh20Tsbq.js → infoDiagram-6WML65LV-A3IqRUnO.js} +1 -1
- package/dist/assets/{ishikawaDiagram-WSZJBQD7-DH2Sm3ko.js → ishikawaDiagram-WSZJBQD7-B2uL6bkK.js} +1 -1
- package/dist/assets/{journeyDiagram-NVQOT4AX-BNFQqlVu.js → journeyDiagram-NVQOT4AX-D9JB-hRW.js} +1 -1
- package/dist/assets/{kanban-definition-27J2QSJJ-B3iL0ztJ.js → kanban-definition-27J2QSJJ-DmlgiV7K.js} +1 -1
- package/dist/assets/{linear-Cwe9dEKA.js → linear-Ct_eoJQk.js} +1 -1
- package/dist/assets/{mermaid.core-BYRQSshi.js → mermaid.core-CQ698HNn.js} +5 -5
- package/dist/assets/{mindmap-definition-FAOFIHXS-BgfBYMzr.js → mindmap-definition-FAOFIHXS-DGtMgQhf.js} +1 -1
- package/dist/assets/{pegDiagram-VL7TDLO6-CNYpECr8.js → pegDiagram-VL7TDLO6-CO6vP4n9.js} +1 -1
- package/dist/assets/{pieDiagram-7S7Q4E2Y-DeSrxc4I.js → pieDiagram-7S7Q4E2Y-DMkt_Zfr.js} +1 -1
- package/dist/assets/{quadrantDiagram-CIZ2JOQS-BXVVQsa6.js → quadrantDiagram-CIZ2JOQS-DgNxRz6t.js} +1 -1
- package/dist/assets/{railroadDiagram-AXF67PYL-JTroIW8F.js → railroadDiagram-AXF67PYL-DKz9UqA9.js} +1 -1
- package/dist/assets/{requirementDiagram-LRYGKXZP-C1Z_inLz.js → requirementDiagram-LRYGKXZP-L84XyGgV.js} +1 -1
- package/dist/assets/{sankeyDiagram-W5VNT64P-DCJgKFUk.js → sankeyDiagram-W5VNT64P-CQqWbJ3j.js} +1 -1
- package/dist/assets/{sequenceDiagram-SI44F4Z6-D8Wrx5Vc.js → sequenceDiagram-SI44F4Z6--tnzS2tb.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-CXqD68vD.js → sizeCapture-X5ZJPWSS-DujwEOtm.js} +1 -1
- package/dist/assets/{stateDiagram-OKZ733FA-CF0Ekqjo.js → stateDiagram-OKZ733FA-BK3TcZY2.js} +1 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-_medyomK.js +1 -0
- package/dist/assets/{swimlanes-SLNWSIFB-DVIax_k4.js → swimlanes-SLNWSIFB-naX-Uv1B.js} +2 -2
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-DstIv3TC.js +8 -0
- package/dist/assets/{timeline-definition-Z64GVDOM-DSqk3ApG.js → timeline-definition-Z64GVDOM-C-vP_ddU.js} +1 -1
- package/dist/assets/{vennDiagram-T6HMQDX7-DNbTqyG5.js → vennDiagram-T6HMQDX7-DN-I7o-7.js} +1 -1
- package/dist/assets/{wardleyDiagram-T6FBY63Y-BNCpsFZV.js → wardleyDiagram-T6FBY63Y-Db9dsaXv.js} +1 -1
- package/dist/assets/{xychartDiagram-ELKLHX3M-XsVZphHr.js → xychartDiagram-ELKLHX3M-DE6OxW_p.js} +1 -1
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/favicon.svg +8 -8
- package/dist/generate-icons.js +48 -48
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +11 -11
- package/dist/icons/icon-144x144.svg +11 -11
- package/dist/icons/icon-152x152.svg +11 -11
- package/dist/icons/icon-192x192.svg +11 -11
- package/dist/icons/icon-384x384.svg +11 -11
- package/dist/icons/icon-512x512.svg +11 -11
- package/dist/icons/icon-72x72.svg +11 -11
- package/dist/icons/icon-96x96.svg +11 -11
- package/dist/icons/icon-template.svg +11 -11
- package/dist/index.html +56 -56
- package/dist/logo.svg +17 -17
- package/dist/manifest.json +60 -60
- package/dist/sw.js +124 -124
- package/dist-server/server/modules/cli/cli.service.js +36 -36
- package/dist-server/server/modules/cli/sandbox.service.js +38 -38
- package/dist-server/server/modules/cli/tests/cli-environment-bootstrap.test.js +74 -74
- package/dist-server/server/modules/commands/commands.routes.js +24 -24
- package/dist-server/server/modules/database/migrations.js +190 -190
- package/dist-server/server/modules/database/repositories/api-keys.js +3 -3
- package/dist-server/server/modules/database/repositories/github-tokens.js +2 -2
- package/dist-server/server/modules/database/repositories/notification-channel-endpoints.js +28 -28
- package/dist-server/server/modules/database/repositories/notification-preferences.js +4 -4
- package/dist-server/server/modules/database/repositories/projects.db.js +61 -61
- package/dist-server/server/modules/database/repositories/provider-models.js +35 -35
- package/dist-server/server/modules/database/repositories/push-subscriptions.js +5 -5
- package/dist-server/server/modules/database/repositories/scan-state.db.js +5 -5
- package/dist-server/server/modules/database/repositories/sessions.db.js +92 -92
- package/dist-server/server/modules/database/schema.js +177 -177
- package/dist-server/server/modules/database/tests/provider-models.db.integration.test.js +6 -6
- package/dist-server/server/modules/git/git.routes.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-models.provider.js +12 -12
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.js +9 -9
- package/dist-server/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +17 -17
- package/dist-server/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.js +25 -25
- package/dist-server/server/modules/providers/list/opencode/opencode-sessions.provider.js +27 -27
- package/dist-server/server/modules/providers/services/provider-token-usage.service.js +9 -9
- package/dist-server/server/modules/providers/tests/mcp.test.js +3 -3
- package/dist-server/server/modules/providers/tests/opencode-sessions.test.js +96 -96
- package/dist-server/server/modules/providers/tests/provider-token-usage.service.test.js +18 -18
- package/dist-server/server/modules/taskmaster/taskmaster.routes.js +419 -419
- package/electron/cloud.js +260 -260
- package/electron/desktopNotifications.js +378 -378
- package/electron/desktopWindow.js +766 -766
- package/electron/launcher/index.html +14 -14
- package/electron/launcher/launcher.css +801 -801
- package/electron/launcher/launcher.js +687 -687
- package/electron/localServer.js +549 -549
- package/electron/main.js +944 -944
- package/electron/preload.cjs +60 -60
- package/electron/scripts/generate-macos-icon.js +62 -62
- package/electron/serverInstaller.js +277 -277
- package/electron/tabs.js +87 -87
- package/electron/viewHost.js +331 -331
- package/package.json +250 -247
- package/public/api-docs.html +901 -901
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/promote-dist-server.mjs +50 -50
- package/scripts/release/build-server-bundle.js +176 -176
- package/scripts/release/prepare-desktop-app.js +152 -152
- package/server/index.ts +399 -399
- package/server/load-env.ts +47 -47
- package/server/modules/agent/agent.module.ts +52 -52
- package/server/modules/agent/agent.routes.ts +1287 -1287
- package/server/modules/agent/index.ts +2 -2
- package/server/modules/agent/tests/agent.routes.test.ts +205 -205
- package/server/modules/assets/assets.routes.ts +150 -150
- package/server/modules/assets/index.ts +3 -3
- package/server/modules/assets/services/image-assets.service.ts +127 -127
- package/server/modules/assets/tests/image-assets.service.test.ts +74 -74
- package/server/modules/auth/auth.middleware.ts +163 -163
- package/server/modules/auth/auth.module.ts +38 -38
- package/server/modules/auth/auth.routes.ts +57 -57
- package/server/modules/auth/auth.service.ts +155 -155
- package/server/modules/auth/index.ts +9 -9
- package/server/modules/auth/tests/auth.service.test.ts +95 -95
- package/server/modules/browser-use/browser-use-mcp.routes.ts +120 -120
- package/server/modules/browser-use/browser-use-mcp.ts +386 -386
- package/server/modules/browser-use/browser-use-runtime.ts +10 -10
- package/server/modules/browser-use/browser-use.routes.ts +96 -96
- package/server/modules/browser-use/browser-use.service.ts +836 -836
- package/server/modules/browser-use/index.ts +11 -11
- package/server/modules/browser-use/tests/browser-use.service.test.ts +10 -10
- package/server/modules/cli/cli.module.ts +93 -93
- package/server/modules/cli/cli.service.ts +248 -248
- package/server/modules/cli/cli.ts +19 -19
- package/server/modules/cli/index.ts +2 -2
- package/server/modules/cli/sandbox.service.ts +398 -398
- package/server/modules/cli/tests/cli-environment-bootstrap.test.ts +186 -186
- package/server/modules/cli/tests/cli.service.test.ts +86 -86
- package/server/modules/cli/tests/sandbox.service.test.ts +58 -58
- package/server/modules/commands/commands.module.ts +22 -22
- package/server/modules/commands/commands.routes.ts +586 -586
- package/server/modules/commands/index.ts +2 -2
- package/server/modules/commands/tests/commands.test.ts +109 -109
- package/server/modules/database/connection.ts +143 -143
- package/server/modules/database/index.ts +17 -17
- package/server/modules/database/init-db.ts +17 -17
- package/server/modules/database/migrations.ts +515 -515
- package/server/modules/database/repositories/api-keys.ts +119 -119
- package/server/modules/database/repositories/app-config.ts +53 -53
- package/server/modules/database/repositories/credentials.ts +106 -106
- package/server/modules/database/repositories/github-tokens.ts +100 -100
- package/server/modules/database/repositories/notification-channel-endpoints.ts +153 -153
- package/server/modules/database/repositories/notification-preferences.ts +117 -117
- package/server/modules/database/repositories/projects.db.ts +196 -196
- package/server/modules/database/repositories/provider-models.ts +168 -168
- package/server/modules/database/repositories/push-subscriptions.ts +80 -80
- package/server/modules/database/repositories/scan-state.db.ts +42 -42
- package/server/modules/database/repositories/sessions.db.ts +524 -524
- package/server/modules/database/repositories/users.ts +140 -140
- package/server/modules/database/repositories/vapid-keys.ts +57 -57
- package/server/modules/database/schema.ts +210 -210
- package/server/modules/database/tests/projects.db.integration.test.ts +72 -72
- package/server/modules/database/tests/provider-models.db.integration.test.ts +125 -125
- package/server/modules/database/tests/sessions-provider-mapping.test.ts +109 -109
- package/server/modules/database/tests/sessions.db.integration.test.ts +116 -116
- package/server/modules/file-tree/file-tree.module.ts +116 -116
- package/server/modules/file-tree/file-tree.routes.ts +258 -258
- package/server/modules/file-tree/file-tree.service.ts +675 -675
- package/server/modules/file-tree/index.ts +2 -2
- package/server/modules/file-tree/tests/file-tree.routes.test.ts +157 -157
- package/server/modules/file-tree/tests/file-tree.service.test.ts +371 -371
- package/server/modules/git/git-branch.service.ts +43 -43
- package/server/modules/git/git-parsing.service.ts +66 -66
- package/server/modules/git/git.module.ts +22 -22
- package/server/modules/git/git.routes.ts +1596 -1596
- package/server/modules/git/index.ts +2 -2
- package/server/modules/git/tests/git-branch.service.test.ts +60 -60
- package/server/modules/git/tests/git-init.routes.test.ts +132 -132
- package/server/modules/git/tests/git.test.ts +106 -106
- package/server/modules/notifications/index.ts +24 -24
- package/server/modules/notifications/notifications.routes.ts +127 -127
- package/server/modules/notifications/services/desktop-notification-clients.service.ts +124 -124
- package/server/modules/notifications/services/notification-orchestrator.service.js +310 -310
- package/server/modules/notifications/tests/notification-orchestrator.integration.test.ts +55 -55
- package/server/modules/notifications/vapid-keys.service.ts +38 -38
- package/server/modules/notifications/websocket/desktop-notifications-websocket.service.ts +109 -109
- package/server/modules/plugins/index.ts +9 -9
- package/server/modules/plugins/plugin-process.service.ts +217 -217
- package/server/modules/plugins/plugin-registry.service.ts +459 -459
- package/server/modules/plugins/plugins.module.ts +33 -33
- package/server/modules/plugins/plugins.routes.ts +66 -66
- package/server/modules/plugins/plugins.service.ts +147 -147
- package/server/modules/plugins/tests/plugins.service.test.ts +32 -32
- package/server/modules/projects/index.ts +11 -11
- package/server/modules/projects/projects.routes.ts +273 -273
- package/server/modules/projects/services/project-clone.service.ts +323 -323
- package/server/modules/projects/services/project-delete.service.ts +90 -90
- package/server/modules/projects/services/project-management.service.ts +144 -144
- package/server/modules/projects/services/project-star.service.ts +78 -78
- package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -248
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +314 -314
- package/server/modules/projects/tests/project-clone.service.test.ts +183 -183
- package/server/modules/projects/tests/project-management.service.test.ts +117 -117
- package/server/modules/projects/tests/project-star.service.test.ts +123 -123
- package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -105
- package/server/modules/providers/README.md +380 -380
- package/server/modules/providers/index.ts +10 -10
- package/server/modules/providers/list/claude/claude-auth.provider.ts +160 -160
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-models.provider.ts +294 -294
- package/server/modules/providers/list/claude/claude-runtime.provider.js +1068 -1068
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +684 -684
- package/server/modules/providers/list/claude/claude-skills.provider.ts +265 -265
- package/server/modules/providers/list/claude/claude.provider.ts +30 -30
- package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -100
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-models.provider.ts +123 -123
- package/server/modules/providers/list/codex/codex-runtime.provider.js +533 -533
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +203 -203
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +938 -938
- package/server/modules/providers/list/codex/codex-skills.provider.ts +73 -73
- package/server/modules/providers/list/codex/codex.provider.ts +28 -28
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-models.provider.ts +119 -119
- package/server/modules/providers/list/cursor/cursor-runtime.provider.js +385 -385
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +159 -159
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +654 -654
- package/server/modules/providers/list/cursor/cursor-skills.provider.ts +39 -39
- package/server/modules/providers/list/cursor/cursor.provider.ts +30 -30
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +110 -110
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +228 -228
- package/server/modules/providers/list/opencode/opencode-models.provider.ts +203 -203
- package/server/modules/providers/list/opencode/opencode-runtime.provider.js +434 -434
- package/server/modules/providers/list/opencode/opencode-runtime.provider.test.js +261 -261
- package/server/modules/providers/list/opencode/opencode-session-synchronizer.provider.ts +179 -179
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +500 -500
- package/server/modules/providers/list/opencode/opencode-skills.provider.ts +78 -78
- package/server/modules/providers/list/opencode/opencode.provider.ts +30 -30
- package/server/modules/providers/provider.registry.ts +36 -36
- package/server/modules/providers/provider.routes.ts +877 -877
- package/server/modules/providers/services/mcp.service.ts +109 -109
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/provider-capabilities.service.ts +97 -97
- package/server/modules/providers/services/provider-models.service.ts +401 -401
- package/server/modules/providers/services/provider-runtime.service.ts +108 -108
- package/server/modules/providers/services/provider-token-usage.service.ts +357 -357
- package/server/modules/providers/services/session-conversations-search.service.ts +1321 -1321
- package/server/modules/providers/services/session-synchronizer.service.ts +74 -74
- package/server/modules/providers/services/sessions-watcher.service.ts +247 -247
- package/server/modules/providers/services/sessions.service.ts +471 -471
- package/server/modules/providers/services/skills.service.ts +39 -39
- package/server/modules/providers/shared/base/abstract.provider.ts +32 -32
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/skills/skills.provider.ts +287 -287
- package/server/modules/providers/tests/claude-auth.test.ts +150 -150
- package/server/modules/providers/tests/claude-sessions.test.ts +61 -61
- package/server/modules/providers/tests/codex-sessions.test.ts +231 -231
- package/server/modules/providers/tests/mcp.test.ts +349 -349
- package/server/modules/providers/tests/opencode-models.test.ts +41 -41
- package/server/modules/providers/tests/opencode-sessions.test.ts +522 -522
- package/server/modules/providers/tests/provider-attachment-history.test.ts +247 -247
- package/server/modules/providers/tests/provider-models.service.test.ts +353 -353
- package/server/modules/providers/tests/provider-runtime.service.test.ts +138 -138
- package/server/modules/providers/tests/provider-token-usage.service.test.ts +186 -186
- package/server/modules/providers/tests/provider.routes.test.ts +244 -244
- package/server/modules/providers/tests/sessions-details.test.ts +73 -73
- package/server/modules/providers/tests/sessions.service.test.ts +127 -127
- package/server/modules/providers/tests/skills.test.ts +692 -692
- package/server/modules/settings/index.ts +2 -2
- package/server/modules/settings/settings.module.ts +50 -50
- package/server/modules/settings/settings.routes.ts +51 -51
- package/server/modules/settings/settings.service.ts +186 -186
- package/server/modules/settings/tests/settings.service.test.ts +54 -54
- package/server/modules/system/index.ts +2 -2
- package/server/modules/system/system.module.ts +62 -62
- package/server/modules/system/system.routes.ts +21 -21
- package/server/modules/system/system.service.ts +76 -76
- package/server/modules/system/tests/system.service.test.ts +118 -118
- package/server/modules/taskmaster/index.ts +2 -2
- package/server/modules/taskmaster/taskmaster.module.ts +24 -24
- package/server/modules/taskmaster/taskmaster.routes.ts +1482 -1482
- package/server/modules/taskmaster/taskmaster.service.ts +132 -132
- package/server/modules/taskmaster/tests/taskmaster.routes.test.ts +144 -144
- package/server/modules/taskmaster/tests/taskmaster.service.test.ts +97 -97
- package/server/modules/user/index.ts +2 -2
- package/server/modules/user/tests/user.service.test.ts +61 -61
- package/server/modules/user/user.module.ts +58 -58
- package/server/modules/user/user.routes.ts +50 -50
- package/server/modules/user/user.service.ts +85 -85
- package/server/modules/voice/index.ts +2 -2
- package/server/modules/voice/tests/voice.service.test.ts +98 -98
- package/server/modules/voice/voice.module.ts +47 -47
- package/server/modules/voice/voice.routes.ts +113 -113
- package/server/modules/voice/voice.service.ts +192 -192
- package/server/modules/websocket/README.md +273 -273
- package/server/modules/websocket/index.ts +3 -3
- package/server/modules/websocket/services/chat-run-registry.service.ts +343 -343
- package/server/modules/websocket/services/chat-session-writer.service.ts +145 -145
- package/server/modules/websocket/services/chat-websocket.service.ts +425 -425
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -65
- package/server/modules/websocket/services/shell-websocket.service.ts +502 -502
- package/server/modules/websocket/services/websocket-auth.service.ts +59 -59
- package/server/modules/websocket/services/websocket-server.service.ts +124 -124
- package/server/modules/websocket/services/websocket-state.service.ts +16 -16
- package/server/modules/websocket/services/websocket-writer.service.ts +38 -38
- package/server/modules/websocket/tests/chat-attachment-filter.test.ts +59 -59
- package/server/modules/websocket/tests/chat-run-registry.test.ts +282 -282
- package/server/modules/websocket/tests/shell-websocket.service.test.ts +100 -100
- package/server/modules/websocket/tests/websocket-heartbeat.service.test.ts +78 -78
- package/server/modules/worktrees/index.ts +2 -2
- package/server/modules/worktrees/services/worktree-create-and-open.service.ts +53 -53
- package/server/modules/worktrees/services/worktree-create.service.ts +104 -104
- package/server/modules/worktrees/services/worktree-git.service.ts +207 -207
- package/server/modules/worktrees/services/worktree-list.service.ts +143 -143
- package/server/modules/worktrees/services/worktree-merge.service.ts +157 -157
- package/server/modules/worktrees/services/worktree-open.service.ts +85 -85
- package/server/modules/worktrees/services/worktree-remove.service.ts +88 -88
- package/server/modules/worktrees/tests/worktree-create-and-open.service.test.ts +68 -68
- package/server/modules/worktrees/tests/worktree-create.service.test.ts +142 -142
- package/server/modules/worktrees/tests/worktree-git.service.test.ts +84 -84
- package/server/modules/worktrees/tests/worktree-list.service.test.ts +45 -45
- package/server/modules/worktrees/tests/worktree-merge.service.test.ts +213 -213
- package/server/modules/worktrees/tests/worktree-open.service.test.ts +122 -122
- package/server/modules/worktrees/tests/worktree-remove.service.test.ts +227 -227
- package/server/modules/worktrees/tests/worktrees.routes.test.ts +199 -199
- package/server/modules/worktrees/worktrees.module.ts +113 -113
- package/server/modules/worktrees/worktrees.routes.ts +116 -116
- package/server/shared/claude-cli-path.ts +139 -139
- package/server/shared/frontmatter.ts +18 -18
- package/server/shared/image-attachments.ts +435 -435
- package/server/shared/interfaces.ts +179 -179
- package/server/shared/tests/claude-cli-path.test.ts +61 -61
- package/server/shared/tests/image-attachments.test.ts +353 -353
- package/server/shared/tests/slice-tail-page.test.ts +42 -42
- package/server/shared/types.ts +1226 -1226
- package/server/shared/utils.ts +1161 -1161
- package/server/tsconfig.json +40 -40
- package/shared/networkHosts.js +22 -22
- package/dist/assets/channel-Bm0ZLE4z.js +0 -1
- package/dist/assets/classDiagram-JCYQIIEL-DqEOcNxw.js +0 -1
- package/dist/assets/classDiagram-v2-OCEON4UE-DqEOcNxw.js +0 -1
- package/dist/assets/stateDiagram-v2-UEYNNEHI-DARLpEFJ.js +0 -1
- package/dist/assets/swimlanesDiagram-ULZ7WXOC-CrgDgaY8.js +0 -8
|
@@ -1,380 +1,380 @@
|
|
|
1
|
-
# Providers Module Guide
|
|
2
|
-
|
|
3
|
-
This file documents the current provider contract in `server/modules/providers`.
|
|
4
|
-
Keep it current whenever provider wiring, skill discovery, or session sync
|
|
5
|
-
behavior changes. The goal is that a human or AI agent can add a new provider
|
|
6
|
-
without guessing which files need to move.
|
|
7
|
-
|
|
8
|
-
## Current Provider Shape
|
|
9
|
-
|
|
10
|
-
Every provider wrapper exposes seven facets:
|
|
11
|
-
|
|
12
|
-
- `runtime`
|
|
13
|
-
- `models`
|
|
14
|
-
- `auth`
|
|
15
|
-
- `mcp`
|
|
16
|
-
- `skills`
|
|
17
|
-
- `sessions`
|
|
18
|
-
- `sessionSynchronizer`
|
|
19
|
-
|
|
20
|
-
These correspond to the shared interfaces in `server/shared/interfaces.ts`:
|
|
21
|
-
|
|
22
|
-
- `IProviderRuntime`
|
|
23
|
-
- `IProviderModels`
|
|
24
|
-
- `IProviderAuth`
|
|
25
|
-
- `IProviderMcp`
|
|
26
|
-
- `IProviderSkills`
|
|
27
|
-
- `IProviderSessions`
|
|
28
|
-
- `IProviderSessionSynchronizer`
|
|
29
|
-
|
|
30
|
-
The services that consume them are:
|
|
31
|
-
|
|
32
|
-
- `providerModelsService`
|
|
33
|
-
- `providerAuthService`
|
|
34
|
-
- `providerMcpService`
|
|
35
|
-
- `providerSkillsService`
|
|
36
|
-
- `sessionsService`
|
|
37
|
-
- `sessionSynchronizerService`
|
|
38
|
-
|
|
39
|
-
Live execution is consumed through `providerRuntimeService`, which resolves the
|
|
40
|
-
provider-owned runtime through the same `providerRegistry` as every other facet.
|
|
41
|
-
|
|
42
|
-
Current provider ids in this repo are:
|
|
43
|
-
|
|
44
|
-
- `claude`
|
|
45
|
-
- `codex`
|
|
46
|
-
- `cursor`
|
|
47
|
-
- `opencode`
|
|
48
|
-
|
|
49
|
-
Those ids are mirrored in backend unions and frontend provider constants. If
|
|
50
|
-
adding a new provider, update every place that hardcodes this list.
|
|
51
|
-
|
|
52
|
-
## Current File Layout
|
|
53
|
-
|
|
54
|
-
Each provider lives under its own folder in `server/modules/providers/list/`:
|
|
55
|
-
|
|
56
|
-
```text
|
|
57
|
-
server/modules/providers/list/<provider>/
|
|
58
|
-
<provider>.provider.ts
|
|
59
|
-
<provider>-runtime.provider.js
|
|
60
|
-
<provider>-auth.provider.ts
|
|
61
|
-
<provider>-models.provider.ts
|
|
62
|
-
<provider>-mcp.provider.ts
|
|
63
|
-
<provider>-skills.provider.ts
|
|
64
|
-
<provider>-sessions.provider.ts
|
|
65
|
-
<provider>-session-synchronizer.provider.ts
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
The existing provider folders are `claude`, `codex`, `cursor`, and `opencode`.
|
|
69
|
-
|
|
70
|
-
Each provider wrapper owns its SDK/CLI runtime alongside its auth, model, and
|
|
71
|
-
session facets. Runtime adapters receive registry-backed model and session
|
|
72
|
-
lookups from `providerRuntimeService` at execution time instead of importing
|
|
73
|
-
those services themselves. This keeps `providerRegistry` as the only provider
|
|
74
|
-
mapping without creating a circular dependency. Application-level consumers
|
|
75
|
-
import the service from `server/modules/providers/index.ts`.
|
|
76
|
-
|
|
77
|
-
## What Each Facet Does
|
|
78
|
-
|
|
79
|
-
| Facet | Responsibility | Base / Service |
|
|
80
|
-
| --- | --- | --- |
|
|
81
|
-
| `runtime` | Run and abort live SDK/CLI sessions | `IProviderRuntime` -> `providerRuntimeService` |
|
|
82
|
-
| `models` | Resolve supported and active models | `IProviderModels` -> `providerModelsService` |
|
|
83
|
-
| `auth` | Report install/auth state for the provider runtime | `IProviderAuth` -> `providerAuthService` |
|
|
84
|
-
| `mcp` | Read, list, write, and remove provider-native MCP config | `McpProvider` -> `providerMcpService` |
|
|
85
|
-
| `skills` | Discover provider-native skill markdown files | `SkillsProvider` -> `providerSkillsService` |
|
|
86
|
-
| `sessions` | Normalize live events and fetch session history | `IProviderSessions` -> `sessionsService` |
|
|
87
|
-
| `sessionSynchronizer` | Scan transcript artifacts and upsert session metadata | `IProviderSessionSynchronizer` -> `sessionSynchronizerService` |
|
|
88
|
-
|
|
89
|
-
`sessions` and `sessionSynchronizer` are separate concerns:
|
|
90
|
-
|
|
91
|
-
- `sessions` handles runtime event normalization and history fetches.
|
|
92
|
-
- `sessionSynchronizer` handles file-backed session indexing into `sessionsDb`.
|
|
93
|
-
|
|
94
|
-
## How To Add A Provider
|
|
95
|
-
|
|
96
|
-
1. Add the provider id everywhere it is part of the contract.
|
|
97
|
-
|
|
98
|
-
- Update `server/shared/types.ts` `LLMProvider`.
|
|
99
|
-
- Update `src/types/app.ts` `LLMProvider` if the frontend should know about it.
|
|
100
|
-
- Update `server/modules/providers/provider.routes.ts`.
|
|
101
|
-
- Update `server/modules/agent/agent.routes.ts` if the provider is launchable from the agent runtime.
|
|
102
|
-
- Update `server/index.ts` if the provider needs runtime boot or shutdown wiring.
|
|
103
|
-
- Update the `PROVIDER_ORDER` list in `public/api-docs.html` if the provider should appear in the public API docs.
|
|
104
|
-
- Update `src/components/chat/hooks/useChatProviderState.ts` and
|
|
105
|
-
`src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx` if
|
|
106
|
-
the provider should be selectable in chat.
|
|
107
|
-
- Update `src/components/provider-auth/view/ProviderLoginModal.tsx` if the
|
|
108
|
-
provider has a login/setup flow.
|
|
109
|
-
|
|
110
|
-
2. Create the wrapper class.
|
|
111
|
-
|
|
112
|
-
- Add `server/modules/providers/list/<provider>/<provider>.provider.ts`.
|
|
113
|
-
- Add `server/modules/providers/list/<provider>/<provider>-runtime.provider.js`
|
|
114
|
-
when the provider supports live SDK/CLI execution.
|
|
115
|
-
- Extend `AbstractProvider`.
|
|
116
|
-
- Expose readonly `auth`, `mcp`, `skills`, `sessions`, and `sessionSynchronizer`.
|
|
117
|
-
- Call `super('<provider>')`.
|
|
118
|
-
|
|
119
|
-
3. Implement auth.
|
|
120
|
-
|
|
121
|
-
- Return a full `ProviderAuthStatus`.
|
|
122
|
-
- Treat normal `not installed` / `not authenticated` states as data, not exceptions.
|
|
123
|
-
- Keep provider-specific credential discovery inside the auth provider.
|
|
124
|
-
- If the provider has no auth step, return a stable unauthenticated or not-installed status instead of omitting the facet.
|
|
125
|
-
|
|
126
|
-
4. Implement MCP.
|
|
127
|
-
|
|
128
|
-
- Extend `McpProvider`.
|
|
129
|
-
- Pass the supported scopes and transports to `super(...)`.
|
|
130
|
-
- Implement the four required methods:
|
|
131
|
-
- `readScopedServers(...)`
|
|
132
|
-
- `writeScopedServers(...)`
|
|
133
|
-
- `buildServerConfig(...)`
|
|
134
|
-
- `normalizeServerConfig(...)`
|
|
135
|
-
- Use the shared validation and normalization behavior from `McpProvider`.
|
|
136
|
-
- Keep the provider-specific config format local to the provider implementation.
|
|
137
|
-
|
|
138
|
-
Current MCP formats in this repo are:
|
|
139
|
-
|
|
140
|
-
| Provider | User / Project Storage | Supported Scopes | Supported Transports |
|
|
141
|
-
| --- | --- | --- | --- |
|
|
142
|
-
| Claude | `.mcp.json` in user / local / project locations | `user`, `local`, `project` | `stdio`, `http`, `sse` |
|
|
143
|
-
| Codex | `.codex/config.toml` | `user`, `project` | `stdio`, `http` |
|
|
144
|
-
| Cursor | `.cursor/mcp.json` | `user`, `project` | `stdio`, `http` |
|
|
145
|
-
| OpenCode | `~/.config/opencode/opencode.json` or `<workspace>/opencode.json` (`.jsonc` is read when present) | `user`, `project` | `stdio`, `http` |
|
|
146
|
-
|
|
147
|
-
5. Implement skills.
|
|
148
|
-
|
|
149
|
-
- Extend `SkillsProvider`.
|
|
150
|
-
- Implement `getSkillSources(workspacePath)`.
|
|
151
|
-
- Return the actual discovery roots for the provider.
|
|
152
|
-
- Skills are discovered from `SKILL.md` files.
|
|
153
|
-
- `readProviderSkillMarkdownDefinition(...)` reads front matter `name` and `description`.
|
|
154
|
-
- If `name` is missing, the parent directory name is used as a fallback.
|
|
155
|
-
- Use `recursive: true` only when the provider stores skills in nested trees.
|
|
156
|
-
- Keep the emitted `command` string aligned with the provider's real skill syntax.
|
|
157
|
-
|
|
158
|
-
Current skill discovery roots are:
|
|
159
|
-
|
|
160
|
-
| Provider | User Roots | Project / Repo Roots | Prefix | Notes |
|
|
161
|
-
| --- | --- | --- | --- | --- |
|
|
162
|
-
| Claude | `~/.claude/skills` | `<workspace>/.claude/skills` | `/` | Also discovers Claude plugin skills from enabled plugin installs. Command skills live under `commands/`; markdown skills live under `skills/` and are scanned recursively. |
|
|
163
|
-
| Codex | `~/.agents/skills`, `~/.codex/skills/.system`, `/etc/codex/skills` | `<workspace>/.agents/skills`, `path.dirname(workspacePath)/.agents/skills`, topmost git root `.agents/skills` | `$` | Overlapping roots are deduplicated before scanning. |
|
|
164
|
-
| Cursor | `~/.cursor/skills` | `<workspace>/.cursor/skills`, `<workspace>/.agents/skills` | `/` | Uses slash-style commands. |
|
|
165
|
-
| OpenCode | `~/.config/opencode/skills`, `~/.claude/skills`, `~/.agents/skills` | Cwd-to-topmost-git-root `.opencode/skills`, `.claude/skills`, and `.agents/skills` | `/` | Reuses OpenCode, Claude, and Agents skill locations. Overlapping roots are deduplicated before scanning. |
|
|
166
|
-
|
|
167
|
-
Command forms currently used by the providers are:
|
|
168
|
-
|
|
169
|
-
- Claude user/project skills: `/skill-name`
|
|
170
|
-
- Claude plugin skills: `/plugin-name:skill-name`
|
|
171
|
-
- Codex skills: `$skill-name`
|
|
172
|
-
- Cursor skills: `/skill-name`
|
|
173
|
-
- OpenCode skills: `/skill-name`
|
|
174
|
-
|
|
175
|
-
6. Implement sessions.
|
|
176
|
-
|
|
177
|
-
- Implement `normalizeMessage(raw, sessionId)` and `fetchHistory(sessionId, options)`.
|
|
178
|
-
- Use `createNormalizedMessage(...)` and `generateMessageId(...)` for emitted messages.
|
|
179
|
-
- Keep normalized message ids unique. If one raw event produces multiple text
|
|
180
|
-
parts, append a discriminator so ids do not collide.
|
|
181
|
-
- Keep pagination consistent:
|
|
182
|
-
- `limit: null` means unbounded/full history.
|
|
183
|
-
- `limit: 0` means an empty page.
|
|
184
|
-
- always return `total`, `hasMore`, `offset`, and `limit` when paginating.
|
|
185
|
-
- Sanitize any filesystem-derived ids before using them in file or database paths.
|
|
186
|
-
- Do not assume a provider's history format matches another provider's format.
|
|
187
|
-
|
|
188
|
-
7. Implement session synchronization.
|
|
189
|
-
|
|
190
|
-
- Implement `synchronize(since?: Date)` to scan provider artifacts and upsert
|
|
191
|
-
sessions into `sessionsDb`.
|
|
192
|
-
- Implement `synchronizeFile(filePath)` for single-file watcher updates.
|
|
193
|
-
- Use the existing helpers when they fit:
|
|
194
|
-
- `buildLookupMap(...)`
|
|
195
|
-
- `extractFirstValidJsonlData(...)`
|
|
196
|
-
- `findFilesRecursivelyCreatedAfter(...)`
|
|
197
|
-
- `normalizeSessionName(...)`
|
|
198
|
-
- `readFileTimestamps(...)`
|
|
199
|
-
- Make the sync resilient to partial, malformed, or missing provider files.
|
|
200
|
-
- The orchestration service runs all provider synchronizers and only advances
|
|
201
|
-
`scan_state.last_scanned_at` when every provider succeeds.
|
|
202
|
-
|
|
203
|
-
Current session sync roots are:
|
|
204
|
-
|
|
205
|
-
| Provider | Scan Roots | Metadata Helpers / Notes |
|
|
206
|
-
| --- | --- | --- |
|
|
207
|
-
| Claude | `~/.claude/projects/**/*.jsonl` | Uses `~/.claude/history.jsonl` for name lookup and the trailing `ai-title`, `last-prompt`, or `custom-title` entries for title recovery. |
|
|
208
|
-
| Codex | `~/.codex/sessions/**/*.jsonl` | Uses `~/.codex/session_index.jsonl` for title lookup and the last `task_complete` message for a fallback title. |
|
|
209
|
-
| Cursor | `~/.cursor/projects/**/*.jsonl` | Uses sibling `worker.log` to recover `workspacePath`, then derives the session title from the first user prompt. |
|
|
210
|
-
| OpenCode | `~/.local/share/opencode/opencode.db` | Reads active sessions/messages/parts from OpenCode's shared SQLite database and stores `jsonl_path` as `null` so deleting one app session cannot remove the shared DB. |
|
|
211
|
-
|
|
212
|
-
8. Register the provider.
|
|
213
|
-
|
|
214
|
-
- Add the new provider class to `server/modules/providers/provider.registry.ts`.
|
|
215
|
-
- Update `server/modules/providers/provider.routes.ts` provider parsing.
|
|
216
|
-
- If the provider introduces a new service or lifecycle hook, export it from the module entrypoint that consumes providers.
|
|
217
|
-
|
|
218
|
-
9. Wire runtime and UI surfaces outside the providers module when needed.
|
|
219
|
-
|
|
220
|
-
If the provider can run live chat sessions, update the runtime entrypoints too:
|
|
221
|
-
|
|
222
|
-
- `server/modules/providers/list/<provider>/<provider>-runtime.provider.js`
|
|
223
|
-
- `server/modules/providers/list/<provider>/<provider>.provider.ts`
|
|
224
|
-
- `server/modules/agent/agent.routes.ts`
|
|
225
|
-
- `server/index.ts`
|
|
226
|
-
|
|
227
|
-
If the provider is visible in the UI, update:
|
|
228
|
-
|
|
229
|
-
- provider model fallback files under `server/modules/providers/list/<provider>/`
|
|
230
|
-
- `src/components/chat/hooks/useChatProviderState.ts`
|
|
231
|
-
- `src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx`
|
|
232
|
-
- `src/components/provider-auth/view/ProviderLoginModal.tsx`
|
|
233
|
-
- `src/components/mcp/constants.ts`
|
|
234
|
-
|
|
235
|
-
## Minimal Wrapper Template
|
|
236
|
-
|
|
237
|
-
```ts
|
|
238
|
-
import { AbstractProvider } from '@/modules/providers/shared/base/abstract.provider.js';
|
|
239
|
-
import { <Provider>ProviderAuth } from './<provider>-auth.provider.js';
|
|
240
|
-
import { <Provider>ProviderModels } from './<provider>-models.provider.js';
|
|
241
|
-
import { <Provider>McpProvider } from './<provider>-mcp.provider.js';
|
|
242
|
-
import { <provider>Runtime } from './<provider>-runtime.provider.js';
|
|
243
|
-
import { <Provider>SkillsProvider } from './<provider>-skills.provider.js';
|
|
244
|
-
import { <Provider>SessionsProvider } from './<provider>-sessions.provider.js';
|
|
245
|
-
import { <Provider>SessionSynchronizer } from './<provider>-session-synchronizer.provider.js';
|
|
246
|
-
import type {
|
|
247
|
-
IProviderAuth,
|
|
248
|
-
IProviderMcp,
|
|
249
|
-
IProviderModels,
|
|
250
|
-
IProviderRuntime,
|
|
251
|
-
IProviderSessionSynchronizer,
|
|
252
|
-
IProviderSessions,
|
|
253
|
-
IProviderSkills,
|
|
254
|
-
} from '@/shared/interfaces.js';
|
|
255
|
-
|
|
256
|
-
export class <Provider>Provider extends AbstractProvider {
|
|
257
|
-
readonly runtime: IProviderRuntime = <provider>Runtime;
|
|
258
|
-
readonly models: IProviderModels = new <Provider>ProviderModels();
|
|
259
|
-
readonly auth: IProviderAuth = new <Provider>ProviderAuth();
|
|
260
|
-
readonly mcp: IProviderMcp = new <Provider>McpProvider();
|
|
261
|
-
readonly skills: IProviderSkills = new <Provider>SkillsProvider();
|
|
262
|
-
readonly sessions: IProviderSessions = new <Provider>SessionsProvider();
|
|
263
|
-
readonly sessionSynchronizer: IProviderSessionSynchronizer =
|
|
264
|
-
new <Provider>SessionSynchronizer();
|
|
265
|
-
|
|
266
|
-
constructor() {
|
|
267
|
-
super('<provider>');
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Minimal Skills Template
|
|
273
|
-
|
|
274
|
-
```ts
|
|
275
|
-
import path from 'node:path';
|
|
276
|
-
|
|
277
|
-
import { SkillsProvider } from '@/modules/providers/shared/skills/skills.provider.js';
|
|
278
|
-
import type { ProviderSkillSource } from '@/shared/types.js';
|
|
279
|
-
|
|
280
|
-
export class <Provider>SkillsProvider extends SkillsProvider {
|
|
281
|
-
constructor() {
|
|
282
|
-
super('<provider>');
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
protected async getSkillSources(workspacePath: string): Promise<ProviderSkillSource[]> {
|
|
286
|
-
return [
|
|
287
|
-
{
|
|
288
|
-
scope: 'project',
|
|
289
|
-
rootDir: path.join(workspacePath, '.<provider>', 'skills'),
|
|
290
|
-
commandPrefix: '/',
|
|
291
|
-
},
|
|
292
|
-
];
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
## Minimal Session Sync Template
|
|
298
|
-
|
|
299
|
-
```ts
|
|
300
|
-
import type { IProviderSessionSynchronizer } from '@/shared/interfaces.js';
|
|
301
|
-
|
|
302
|
-
export class <Provider>SessionSynchronizer implements IProviderSessionSynchronizer {
|
|
303
|
-
async synchronize(since?: Date): Promise<number> {
|
|
304
|
-
return 0;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async synchronizeFile(filePath: string): Promise<string | null> {
|
|
308
|
-
return null;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
## AI Prompt Template
|
|
314
|
-
|
|
315
|
-
Use this prompt when asking an AI agent to add a provider:
|
|
316
|
-
|
|
317
|
-
```text
|
|
318
|
-
Add a new provider "<provider>" using the current provider module architecture.
|
|
319
|
-
|
|
320
|
-
Requirements:
|
|
321
|
-
1) Create:
|
|
322
|
-
- server/modules/providers/list/<provider>/<provider>.provider.ts
|
|
323
|
-
- server/modules/providers/list/<provider>/<provider>-runtime.provider.js
|
|
324
|
-
- server/modules/providers/list/<provider>/<provider>-auth.provider.ts
|
|
325
|
-
- server/modules/providers/list/<provider>/<provider>-models.provider.ts
|
|
326
|
-
- server/modules/providers/list/<provider>/<provider>-mcp.provider.ts
|
|
327
|
-
- server/modules/providers/list/<provider>/<provider>-skills.provider.ts
|
|
328
|
-
- server/modules/providers/list/<provider>/<provider>-sessions.provider.ts
|
|
329
|
-
- server/modules/providers/list/<provider>/<provider>-session-synchronizer.provider.ts
|
|
330
|
-
2) Register in:
|
|
331
|
-
- server/modules/providers/provider.registry.ts
|
|
332
|
-
- server/modules/providers/provider.routes.ts
|
|
333
|
-
- server/shared/types.ts LLMProvider
|
|
334
|
-
- src/types/app.ts LLMProvider
|
|
335
|
-
3) Mirror the nearest existing provider implementation for file naming, style,
|
|
336
|
-
and error handling.
|
|
337
|
-
4) Implement skills support with SkillsProvider and the current skill roots.
|
|
338
|
-
5) Implement session synchronization if the provider stores transcript files.
|
|
339
|
-
6) Ensure sessions use unique ids, safe path handling, and correct pagination.
|
|
340
|
-
7) Keep `sessions` and `sessionSynchronizer` separate.
|
|
341
|
-
8) Run:
|
|
342
|
-
- npx eslint <touched files>
|
|
343
|
-
- npx tsc --noEmit -p server/tsconfig.json
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
## Validation
|
|
347
|
-
|
|
348
|
-
After adding or changing a provider, run the relevant checks:
|
|
349
|
-
|
|
350
|
-
```bash
|
|
351
|
-
npx eslint server/modules/providers/**/*.ts server/shared/types.ts server/shared/interfaces.ts
|
|
352
|
-
npx tsc --noEmit -p server/tsconfig.json
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
Useful tests in this repo:
|
|
356
|
-
|
|
357
|
-
- `server/modules/providers/tests/mcp.test.ts`
|
|
358
|
-
- `server/modules/providers/tests/skills.test.ts`
|
|
359
|
-
- `server/modules/providers/tests/opencode-sessions.test.ts`
|
|
360
|
-
|
|
361
|
-
If you touch sessions or session synchronization, add or update focused tests
|
|
362
|
-
alongside the implementation.
|
|
363
|
-
|
|
364
|
-
## Common Mistakes
|
|
365
|
-
|
|
366
|
-
- Adding provider files but forgetting `provider.registry.ts` or
|
|
367
|
-
`provider.routes.ts`.
|
|
368
|
-
- Adding a live runtime without exposing it from the provider wrapper.
|
|
369
|
-
- Updating backend provider ids but not `src/types/app.ts` or the frontend
|
|
370
|
-
provider constants.
|
|
371
|
-
- Omitting `runtime`, `skills`, or `sessionSynchronizer` from the wrapper.
|
|
372
|
-
- Returning duplicate normalized message ids for split content.
|
|
373
|
-
- Treating `limit === 0` as unbounded history.
|
|
374
|
-
- Building file paths from raw session ids without validation.
|
|
375
|
-
- Hardcoding a skill root without checking the provider's actual discovery rules.
|
|
376
|
-
- Forgetting that Claude plugin skills are discovered differently from normal
|
|
377
|
-
user/project skill folders.
|
|
378
|
-
- Assuming one provider's MCP config file format works for the others.
|
|
379
|
-
|
|
380
|
-
|
|
1
|
+
# Providers Module Guide
|
|
2
|
+
|
|
3
|
+
This file documents the current provider contract in `server/modules/providers`.
|
|
4
|
+
Keep it current whenever provider wiring, skill discovery, or session sync
|
|
5
|
+
behavior changes. The goal is that a human or AI agent can add a new provider
|
|
6
|
+
without guessing which files need to move.
|
|
7
|
+
|
|
8
|
+
## Current Provider Shape
|
|
9
|
+
|
|
10
|
+
Every provider wrapper exposes seven facets:
|
|
11
|
+
|
|
12
|
+
- `runtime`
|
|
13
|
+
- `models`
|
|
14
|
+
- `auth`
|
|
15
|
+
- `mcp`
|
|
16
|
+
- `skills`
|
|
17
|
+
- `sessions`
|
|
18
|
+
- `sessionSynchronizer`
|
|
19
|
+
|
|
20
|
+
These correspond to the shared interfaces in `server/shared/interfaces.ts`:
|
|
21
|
+
|
|
22
|
+
- `IProviderRuntime`
|
|
23
|
+
- `IProviderModels`
|
|
24
|
+
- `IProviderAuth`
|
|
25
|
+
- `IProviderMcp`
|
|
26
|
+
- `IProviderSkills`
|
|
27
|
+
- `IProviderSessions`
|
|
28
|
+
- `IProviderSessionSynchronizer`
|
|
29
|
+
|
|
30
|
+
The services that consume them are:
|
|
31
|
+
|
|
32
|
+
- `providerModelsService`
|
|
33
|
+
- `providerAuthService`
|
|
34
|
+
- `providerMcpService`
|
|
35
|
+
- `providerSkillsService`
|
|
36
|
+
- `sessionsService`
|
|
37
|
+
- `sessionSynchronizerService`
|
|
38
|
+
|
|
39
|
+
Live execution is consumed through `providerRuntimeService`, which resolves the
|
|
40
|
+
provider-owned runtime through the same `providerRegistry` as every other facet.
|
|
41
|
+
|
|
42
|
+
Current provider ids in this repo are:
|
|
43
|
+
|
|
44
|
+
- `claude`
|
|
45
|
+
- `codex`
|
|
46
|
+
- `cursor`
|
|
47
|
+
- `opencode`
|
|
48
|
+
|
|
49
|
+
Those ids are mirrored in backend unions and frontend provider constants. If
|
|
50
|
+
adding a new provider, update every place that hardcodes this list.
|
|
51
|
+
|
|
52
|
+
## Current File Layout
|
|
53
|
+
|
|
54
|
+
Each provider lives under its own folder in `server/modules/providers/list/`:
|
|
55
|
+
|
|
56
|
+
```text
|
|
57
|
+
server/modules/providers/list/<provider>/
|
|
58
|
+
<provider>.provider.ts
|
|
59
|
+
<provider>-runtime.provider.js
|
|
60
|
+
<provider>-auth.provider.ts
|
|
61
|
+
<provider>-models.provider.ts
|
|
62
|
+
<provider>-mcp.provider.ts
|
|
63
|
+
<provider>-skills.provider.ts
|
|
64
|
+
<provider>-sessions.provider.ts
|
|
65
|
+
<provider>-session-synchronizer.provider.ts
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The existing provider folders are `claude`, `codex`, `cursor`, and `opencode`.
|
|
69
|
+
|
|
70
|
+
Each provider wrapper owns its SDK/CLI runtime alongside its auth, model, and
|
|
71
|
+
session facets. Runtime adapters receive registry-backed model and session
|
|
72
|
+
lookups from `providerRuntimeService` at execution time instead of importing
|
|
73
|
+
those services themselves. This keeps `providerRegistry` as the only provider
|
|
74
|
+
mapping without creating a circular dependency. Application-level consumers
|
|
75
|
+
import the service from `server/modules/providers/index.ts`.
|
|
76
|
+
|
|
77
|
+
## What Each Facet Does
|
|
78
|
+
|
|
79
|
+
| Facet | Responsibility | Base / Service |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `runtime` | Run and abort live SDK/CLI sessions | `IProviderRuntime` -> `providerRuntimeService` |
|
|
82
|
+
| `models` | Resolve supported and active models | `IProviderModels` -> `providerModelsService` |
|
|
83
|
+
| `auth` | Report install/auth state for the provider runtime | `IProviderAuth` -> `providerAuthService` |
|
|
84
|
+
| `mcp` | Read, list, write, and remove provider-native MCP config | `McpProvider` -> `providerMcpService` |
|
|
85
|
+
| `skills` | Discover provider-native skill markdown files | `SkillsProvider` -> `providerSkillsService` |
|
|
86
|
+
| `sessions` | Normalize live events and fetch session history | `IProviderSessions` -> `sessionsService` |
|
|
87
|
+
| `sessionSynchronizer` | Scan transcript artifacts and upsert session metadata | `IProviderSessionSynchronizer` -> `sessionSynchronizerService` |
|
|
88
|
+
|
|
89
|
+
`sessions` and `sessionSynchronizer` are separate concerns:
|
|
90
|
+
|
|
91
|
+
- `sessions` handles runtime event normalization and history fetches.
|
|
92
|
+
- `sessionSynchronizer` handles file-backed session indexing into `sessionsDb`.
|
|
93
|
+
|
|
94
|
+
## How To Add A Provider
|
|
95
|
+
|
|
96
|
+
1. Add the provider id everywhere it is part of the contract.
|
|
97
|
+
|
|
98
|
+
- Update `server/shared/types.ts` `LLMProvider`.
|
|
99
|
+
- Update `src/types/app.ts` `LLMProvider` if the frontend should know about it.
|
|
100
|
+
- Update `server/modules/providers/provider.routes.ts`.
|
|
101
|
+
- Update `server/modules/agent/agent.routes.ts` if the provider is launchable from the agent runtime.
|
|
102
|
+
- Update `server/index.ts` if the provider needs runtime boot or shutdown wiring.
|
|
103
|
+
- Update the `PROVIDER_ORDER` list in `public/api-docs.html` if the provider should appear in the public API docs.
|
|
104
|
+
- Update `src/components/chat/hooks/useChatProviderState.ts` and
|
|
105
|
+
`src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx` if
|
|
106
|
+
the provider should be selectable in chat.
|
|
107
|
+
- Update `src/components/provider-auth/view/ProviderLoginModal.tsx` if the
|
|
108
|
+
provider has a login/setup flow.
|
|
109
|
+
|
|
110
|
+
2. Create the wrapper class.
|
|
111
|
+
|
|
112
|
+
- Add `server/modules/providers/list/<provider>/<provider>.provider.ts`.
|
|
113
|
+
- Add `server/modules/providers/list/<provider>/<provider>-runtime.provider.js`
|
|
114
|
+
when the provider supports live SDK/CLI execution.
|
|
115
|
+
- Extend `AbstractProvider`.
|
|
116
|
+
- Expose readonly `auth`, `mcp`, `skills`, `sessions`, and `sessionSynchronizer`.
|
|
117
|
+
- Call `super('<provider>')`.
|
|
118
|
+
|
|
119
|
+
3. Implement auth.
|
|
120
|
+
|
|
121
|
+
- Return a full `ProviderAuthStatus`.
|
|
122
|
+
- Treat normal `not installed` / `not authenticated` states as data, not exceptions.
|
|
123
|
+
- Keep provider-specific credential discovery inside the auth provider.
|
|
124
|
+
- If the provider has no auth step, return a stable unauthenticated or not-installed status instead of omitting the facet.
|
|
125
|
+
|
|
126
|
+
4. Implement MCP.
|
|
127
|
+
|
|
128
|
+
- Extend `McpProvider`.
|
|
129
|
+
- Pass the supported scopes and transports to `super(...)`.
|
|
130
|
+
- Implement the four required methods:
|
|
131
|
+
- `readScopedServers(...)`
|
|
132
|
+
- `writeScopedServers(...)`
|
|
133
|
+
- `buildServerConfig(...)`
|
|
134
|
+
- `normalizeServerConfig(...)`
|
|
135
|
+
- Use the shared validation and normalization behavior from `McpProvider`.
|
|
136
|
+
- Keep the provider-specific config format local to the provider implementation.
|
|
137
|
+
|
|
138
|
+
Current MCP formats in this repo are:
|
|
139
|
+
|
|
140
|
+
| Provider | User / Project Storage | Supported Scopes | Supported Transports |
|
|
141
|
+
| --- | --- | --- | --- |
|
|
142
|
+
| Claude | `.mcp.json` in user / local / project locations | `user`, `local`, `project` | `stdio`, `http`, `sse` |
|
|
143
|
+
| Codex | `.codex/config.toml` | `user`, `project` | `stdio`, `http` |
|
|
144
|
+
| Cursor | `.cursor/mcp.json` | `user`, `project` | `stdio`, `http` |
|
|
145
|
+
| OpenCode | `~/.config/opencode/opencode.json` or `<workspace>/opencode.json` (`.jsonc` is read when present) | `user`, `project` | `stdio`, `http` |
|
|
146
|
+
|
|
147
|
+
5. Implement skills.
|
|
148
|
+
|
|
149
|
+
- Extend `SkillsProvider`.
|
|
150
|
+
- Implement `getSkillSources(workspacePath)`.
|
|
151
|
+
- Return the actual discovery roots for the provider.
|
|
152
|
+
- Skills are discovered from `SKILL.md` files.
|
|
153
|
+
- `readProviderSkillMarkdownDefinition(...)` reads front matter `name` and `description`.
|
|
154
|
+
- If `name` is missing, the parent directory name is used as a fallback.
|
|
155
|
+
- Use `recursive: true` only when the provider stores skills in nested trees.
|
|
156
|
+
- Keep the emitted `command` string aligned with the provider's real skill syntax.
|
|
157
|
+
|
|
158
|
+
Current skill discovery roots are:
|
|
159
|
+
|
|
160
|
+
| Provider | User Roots | Project / Repo Roots | Prefix | Notes |
|
|
161
|
+
| --- | --- | --- | --- | --- |
|
|
162
|
+
| Claude | `~/.claude/skills` | `<workspace>/.claude/skills` | `/` | Also discovers Claude plugin skills from enabled plugin installs. Command skills live under `commands/`; markdown skills live under `skills/` and are scanned recursively. |
|
|
163
|
+
| Codex | `~/.agents/skills`, `~/.codex/skills/.system`, `/etc/codex/skills` | `<workspace>/.agents/skills`, `path.dirname(workspacePath)/.agents/skills`, topmost git root `.agents/skills` | `$` | Overlapping roots are deduplicated before scanning. |
|
|
164
|
+
| Cursor | `~/.cursor/skills` | `<workspace>/.cursor/skills`, `<workspace>/.agents/skills` | `/` | Uses slash-style commands. |
|
|
165
|
+
| OpenCode | `~/.config/opencode/skills`, `~/.claude/skills`, `~/.agents/skills` | Cwd-to-topmost-git-root `.opencode/skills`, `.claude/skills`, and `.agents/skills` | `/` | Reuses OpenCode, Claude, and Agents skill locations. Overlapping roots are deduplicated before scanning. |
|
|
166
|
+
|
|
167
|
+
Command forms currently used by the providers are:
|
|
168
|
+
|
|
169
|
+
- Claude user/project skills: `/skill-name`
|
|
170
|
+
- Claude plugin skills: `/plugin-name:skill-name`
|
|
171
|
+
- Codex skills: `$skill-name`
|
|
172
|
+
- Cursor skills: `/skill-name`
|
|
173
|
+
- OpenCode skills: `/skill-name`
|
|
174
|
+
|
|
175
|
+
6. Implement sessions.
|
|
176
|
+
|
|
177
|
+
- Implement `normalizeMessage(raw, sessionId)` and `fetchHistory(sessionId, options)`.
|
|
178
|
+
- Use `createNormalizedMessage(...)` and `generateMessageId(...)` for emitted messages.
|
|
179
|
+
- Keep normalized message ids unique. If one raw event produces multiple text
|
|
180
|
+
parts, append a discriminator so ids do not collide.
|
|
181
|
+
- Keep pagination consistent:
|
|
182
|
+
- `limit: null` means unbounded/full history.
|
|
183
|
+
- `limit: 0` means an empty page.
|
|
184
|
+
- always return `total`, `hasMore`, `offset`, and `limit` when paginating.
|
|
185
|
+
- Sanitize any filesystem-derived ids before using them in file or database paths.
|
|
186
|
+
- Do not assume a provider's history format matches another provider's format.
|
|
187
|
+
|
|
188
|
+
7. Implement session synchronization.
|
|
189
|
+
|
|
190
|
+
- Implement `synchronize(since?: Date)` to scan provider artifacts and upsert
|
|
191
|
+
sessions into `sessionsDb`.
|
|
192
|
+
- Implement `synchronizeFile(filePath)` for single-file watcher updates.
|
|
193
|
+
- Use the existing helpers when they fit:
|
|
194
|
+
- `buildLookupMap(...)`
|
|
195
|
+
- `extractFirstValidJsonlData(...)`
|
|
196
|
+
- `findFilesRecursivelyCreatedAfter(...)`
|
|
197
|
+
- `normalizeSessionName(...)`
|
|
198
|
+
- `readFileTimestamps(...)`
|
|
199
|
+
- Make the sync resilient to partial, malformed, or missing provider files.
|
|
200
|
+
- The orchestration service runs all provider synchronizers and only advances
|
|
201
|
+
`scan_state.last_scanned_at` when every provider succeeds.
|
|
202
|
+
|
|
203
|
+
Current session sync roots are:
|
|
204
|
+
|
|
205
|
+
| Provider | Scan Roots | Metadata Helpers / Notes |
|
|
206
|
+
| --- | --- | --- |
|
|
207
|
+
| Claude | `~/.claude/projects/**/*.jsonl` | Uses `~/.claude/history.jsonl` for name lookup and the trailing `ai-title`, `last-prompt`, or `custom-title` entries for title recovery. |
|
|
208
|
+
| Codex | `~/.codex/sessions/**/*.jsonl` | Uses `~/.codex/session_index.jsonl` for title lookup and the last `task_complete` message for a fallback title. |
|
|
209
|
+
| Cursor | `~/.cursor/projects/**/*.jsonl` | Uses sibling `worker.log` to recover `workspacePath`, then derives the session title from the first user prompt. |
|
|
210
|
+
| OpenCode | `~/.local/share/opencode/opencode.db` | Reads active sessions/messages/parts from OpenCode's shared SQLite database and stores `jsonl_path` as `null` so deleting one app session cannot remove the shared DB. |
|
|
211
|
+
|
|
212
|
+
8. Register the provider.
|
|
213
|
+
|
|
214
|
+
- Add the new provider class to `server/modules/providers/provider.registry.ts`.
|
|
215
|
+
- Update `server/modules/providers/provider.routes.ts` provider parsing.
|
|
216
|
+
- If the provider introduces a new service or lifecycle hook, export it from the module entrypoint that consumes providers.
|
|
217
|
+
|
|
218
|
+
9. Wire runtime and UI surfaces outside the providers module when needed.
|
|
219
|
+
|
|
220
|
+
If the provider can run live chat sessions, update the runtime entrypoints too:
|
|
221
|
+
|
|
222
|
+
- `server/modules/providers/list/<provider>/<provider>-runtime.provider.js`
|
|
223
|
+
- `server/modules/providers/list/<provider>/<provider>.provider.ts`
|
|
224
|
+
- `server/modules/agent/agent.routes.ts`
|
|
225
|
+
- `server/index.ts`
|
|
226
|
+
|
|
227
|
+
If the provider is visible in the UI, update:
|
|
228
|
+
|
|
229
|
+
- provider model fallback files under `server/modules/providers/list/<provider>/`
|
|
230
|
+
- `src/components/chat/hooks/useChatProviderState.ts`
|
|
231
|
+
- `src/components/chat/view/subcomponents/ProviderSelectionEmptyState.tsx`
|
|
232
|
+
- `src/components/provider-auth/view/ProviderLoginModal.tsx`
|
|
233
|
+
- `src/components/mcp/constants.ts`
|
|
234
|
+
|
|
235
|
+
## Minimal Wrapper Template
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
import { AbstractProvider } from '@/modules/providers/shared/base/abstract.provider.js';
|
|
239
|
+
import { <Provider>ProviderAuth } from './<provider>-auth.provider.js';
|
|
240
|
+
import { <Provider>ProviderModels } from './<provider>-models.provider.js';
|
|
241
|
+
import { <Provider>McpProvider } from './<provider>-mcp.provider.js';
|
|
242
|
+
import { <provider>Runtime } from './<provider>-runtime.provider.js';
|
|
243
|
+
import { <Provider>SkillsProvider } from './<provider>-skills.provider.js';
|
|
244
|
+
import { <Provider>SessionsProvider } from './<provider>-sessions.provider.js';
|
|
245
|
+
import { <Provider>SessionSynchronizer } from './<provider>-session-synchronizer.provider.js';
|
|
246
|
+
import type {
|
|
247
|
+
IProviderAuth,
|
|
248
|
+
IProviderMcp,
|
|
249
|
+
IProviderModels,
|
|
250
|
+
IProviderRuntime,
|
|
251
|
+
IProviderSessionSynchronizer,
|
|
252
|
+
IProviderSessions,
|
|
253
|
+
IProviderSkills,
|
|
254
|
+
} from '@/shared/interfaces.js';
|
|
255
|
+
|
|
256
|
+
export class <Provider>Provider extends AbstractProvider {
|
|
257
|
+
readonly runtime: IProviderRuntime = <provider>Runtime;
|
|
258
|
+
readonly models: IProviderModels = new <Provider>ProviderModels();
|
|
259
|
+
readonly auth: IProviderAuth = new <Provider>ProviderAuth();
|
|
260
|
+
readonly mcp: IProviderMcp = new <Provider>McpProvider();
|
|
261
|
+
readonly skills: IProviderSkills = new <Provider>SkillsProvider();
|
|
262
|
+
readonly sessions: IProviderSessions = new <Provider>SessionsProvider();
|
|
263
|
+
readonly sessionSynchronizer: IProviderSessionSynchronizer =
|
|
264
|
+
new <Provider>SessionSynchronizer();
|
|
265
|
+
|
|
266
|
+
constructor() {
|
|
267
|
+
super('<provider>');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Minimal Skills Template
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import path from 'node:path';
|
|
276
|
+
|
|
277
|
+
import { SkillsProvider } from '@/modules/providers/shared/skills/skills.provider.js';
|
|
278
|
+
import type { ProviderSkillSource } from '@/shared/types.js';
|
|
279
|
+
|
|
280
|
+
export class <Provider>SkillsProvider extends SkillsProvider {
|
|
281
|
+
constructor() {
|
|
282
|
+
super('<provider>');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
protected async getSkillSources(workspacePath: string): Promise<ProviderSkillSource[]> {
|
|
286
|
+
return [
|
|
287
|
+
{
|
|
288
|
+
scope: 'project',
|
|
289
|
+
rootDir: path.join(workspacePath, '.<provider>', 'skills'),
|
|
290
|
+
commandPrefix: '/',
|
|
291
|
+
},
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Minimal Session Sync Template
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import type { IProviderSessionSynchronizer } from '@/shared/interfaces.js';
|
|
301
|
+
|
|
302
|
+
export class <Provider>SessionSynchronizer implements IProviderSessionSynchronizer {
|
|
303
|
+
async synchronize(since?: Date): Promise<number> {
|
|
304
|
+
return 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async synchronizeFile(filePath: string): Promise<string | null> {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## AI Prompt Template
|
|
314
|
+
|
|
315
|
+
Use this prompt when asking an AI agent to add a provider:
|
|
316
|
+
|
|
317
|
+
```text
|
|
318
|
+
Add a new provider "<provider>" using the current provider module architecture.
|
|
319
|
+
|
|
320
|
+
Requirements:
|
|
321
|
+
1) Create:
|
|
322
|
+
- server/modules/providers/list/<provider>/<provider>.provider.ts
|
|
323
|
+
- server/modules/providers/list/<provider>/<provider>-runtime.provider.js
|
|
324
|
+
- server/modules/providers/list/<provider>/<provider>-auth.provider.ts
|
|
325
|
+
- server/modules/providers/list/<provider>/<provider>-models.provider.ts
|
|
326
|
+
- server/modules/providers/list/<provider>/<provider>-mcp.provider.ts
|
|
327
|
+
- server/modules/providers/list/<provider>/<provider>-skills.provider.ts
|
|
328
|
+
- server/modules/providers/list/<provider>/<provider>-sessions.provider.ts
|
|
329
|
+
- server/modules/providers/list/<provider>/<provider>-session-synchronizer.provider.ts
|
|
330
|
+
2) Register in:
|
|
331
|
+
- server/modules/providers/provider.registry.ts
|
|
332
|
+
- server/modules/providers/provider.routes.ts
|
|
333
|
+
- server/shared/types.ts LLMProvider
|
|
334
|
+
- src/types/app.ts LLMProvider
|
|
335
|
+
3) Mirror the nearest existing provider implementation for file naming, style,
|
|
336
|
+
and error handling.
|
|
337
|
+
4) Implement skills support with SkillsProvider and the current skill roots.
|
|
338
|
+
5) Implement session synchronization if the provider stores transcript files.
|
|
339
|
+
6) Ensure sessions use unique ids, safe path handling, and correct pagination.
|
|
340
|
+
7) Keep `sessions` and `sessionSynchronizer` separate.
|
|
341
|
+
8) Run:
|
|
342
|
+
- npx eslint <touched files>
|
|
343
|
+
- npx tsc --noEmit -p server/tsconfig.json
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## Validation
|
|
347
|
+
|
|
348
|
+
After adding or changing a provider, run the relevant checks:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
npx eslint server/modules/providers/**/*.ts server/shared/types.ts server/shared/interfaces.ts
|
|
352
|
+
npx tsc --noEmit -p server/tsconfig.json
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Useful tests in this repo:
|
|
356
|
+
|
|
357
|
+
- `server/modules/providers/tests/mcp.test.ts`
|
|
358
|
+
- `server/modules/providers/tests/skills.test.ts`
|
|
359
|
+
- `server/modules/providers/tests/opencode-sessions.test.ts`
|
|
360
|
+
|
|
361
|
+
If you touch sessions or session synchronization, add or update focused tests
|
|
362
|
+
alongside the implementation.
|
|
363
|
+
|
|
364
|
+
## Common Mistakes
|
|
365
|
+
|
|
366
|
+
- Adding provider files but forgetting `provider.registry.ts` or
|
|
367
|
+
`provider.routes.ts`.
|
|
368
|
+
- Adding a live runtime without exposing it from the provider wrapper.
|
|
369
|
+
- Updating backend provider ids but not `src/types/app.ts` or the frontend
|
|
370
|
+
provider constants.
|
|
371
|
+
- Omitting `runtime`, `skills`, or `sessionSynchronizer` from the wrapper.
|
|
372
|
+
- Returning duplicate normalized message ids for split content.
|
|
373
|
+
- Treating `limit === 0` as unbounded history.
|
|
374
|
+
- Building file paths from raw session ids without validation.
|
|
375
|
+
- Hardcoding a skill root without checking the provider's actual discovery rules.
|
|
376
|
+
- Forgetting that Claude plugin skills are discovered differently from normal
|
|
377
|
+
user/project skill folders.
|
|
378
|
+
- Assuming one provider's MCP config file format works for the others.
|
|
379
|
+
|
|
380
|
+
|