@runeya/apps-cli 0.1.0 → 0.1.2
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/agent/index.js +5303 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent-manager-3S4FUNJS-MYT5X6XQ.js +8 -0
- package/dist/agent-manager-3S4FUNJS-MYT5X6XQ.js.map +1 -0
- package/dist/chunk-32HTB3XS.js +350 -0
- package/dist/chunk-32HTB3XS.js.map +1 -0
- package/dist/chunk-ERJIU7R4.js +195 -0
- package/dist/chunk-ERJIU7R4.js.map +1 -0
- package/dist/chunk-XZPCEGWS.js +2452 -0
- package/dist/chunk-XZPCEGWS.js.map +1 -0
- package/dist/dist-MFM5N25P.js +10985 -0
- package/dist/dist-MFM5N25P.js.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/kanban-commands-VEVMJTFS-OIYWEHUP.js +14 -0
- package/dist/kanban-commands-VEVMJTFS-OIYWEHUP.js.map +1 -0
- package/dist/package.json +36 -0
- package/dist/runeya +4 -0
- package/dist/web/assets/AddressBar.vue-dB66q4DS.js +1 -0
- package/dist/web/assets/AgentPage-B3wrH3gG.js +2 -0
- package/dist/web/assets/AgentPage-BTWkJvqr.css +1 -0
- package/dist/web/assets/AgentScalarChatInterface.vue-CJVuZIB9.js +13 -0
- package/dist/web/assets/AgentTerminalPage-Cj5fRr-j.js +36 -0
- package/dist/web/assets/AgentTerminalPage-EX_n6P3x.css +1 -0
- package/dist/web/assets/AiChatPage-Dhsx3B9B.js +1 -0
- package/dist/web/assets/ApiDocsPage-BddLJuUF.js +5 -0
- package/dist/web/assets/ApiDocsPage-D2Z0wqGZ.css +1 -0
- package/dist/web/assets/AppLayout-AfhaeKlp.js +1 -0
- package/dist/web/assets/AppLayout-sngalCCj.css +1 -0
- package/dist/web/assets/AuditPage-BBV9FW9y.css +1 -0
- package/dist/web/assets/AuditPage-DqycuiVb.js +1 -0
- package/dist/web/assets/CodeInput.vue-Dyew7ml-.js +1 -0
- package/dist/web/assets/Collection.vue-DePdVAHM.js +1 -0
- package/dist/web/assets/CollectionAuthentication.vue-DagSEg45.js +1 -0
- package/dist/web/assets/CollectionCookies.vue-vMKPCgg1.js +1 -0
- package/dist/web/assets/CollectionEnvironment.vue-B0JkZ6GC.js +1 -0
- package/dist/web/assets/CollectionOverview.vue-Bm7OsMWM.js +1 -0
- package/dist/web/assets/CollectionScripts.vue-CZiBq0rT.js +1 -0
- package/dist/web/assets/CollectionServers.vue-bziJbP-5.js +1 -0
- package/dist/web/assets/CollectionSettings.vue-D4oBu-fT.js +1 -0
- package/dist/web/assets/CollectionSync.vue-BG50-Lo4.js +1 -0
- package/dist/web/assets/CommandActionInput.vue-DmZld2w7.js +1 -0
- package/dist/web/assets/Cookies.vue-DjxMLL79.js +1 -0
- package/dist/web/assets/DashboardPage-QjYCF0Kd.js +1 -0
- package/dist/web/assets/DashboardPage-gZJ4_s8T.css +1 -0
- package/dist/web/assets/DataTable.vue-BV9IuUNB.js +1 -0
- package/dist/web/assets/DataTableCheckbox.vue-Cx0exaNK.js +1 -0
- package/dist/web/assets/DataTableHeader.vue-ZtUdyiLV.js +1 -0
- package/dist/web/assets/DataTableInput.vue-C4NF8kJn.js +1 -0
- package/dist/web/assets/DeleteSidebarListElement.vue-CcAW4Pdn.js +1 -0
- package/dist/web/assets/EditSidebarListElement.vue-Crbagha4.js +1 -0
- package/dist/web/assets/EditorIcon-BaDORp4k.js +15 -0
- package/dist/web/assets/EditorIcon-zS3bHXe1.css +1 -0
- package/dist/web/assets/EmptyState.vue-2hJbVxAi.js +22 -0
- package/dist/web/assets/Environment.vue-CcERFnQq.js +1 -0
- package/dist/web/assets/EnvironmentForm-DSKxdDGW.js +108 -0
- package/dist/web/assets/EnvironmentForm-DVMc303P.css +1 -0
- package/dist/web/assets/EnvironmentFormPage-BDhR07CG.js +1 -0
- package/dist/web/assets/EnvironmentFormPage-OaDJvyrc.css +1 -0
- package/dist/web/assets/EnvironmentListPage-BDqcug66.css +1 -0
- package/dist/web/assets/EnvironmentListPage-BzdxgZdS.js +1 -0
- package/dist/web/assets/EnvironmentModal.vue-DvsPa6V9.js +1 -0
- package/dist/web/assets/EnvironmentSelector-B9SZvB3I.css +1 -0
- package/dist/web/assets/EnvironmentSelector-BWljvJWP.js +1 -0
- package/dist/web/assets/Form.vue-BxhIukSx.js +1 -0
- package/dist/web/assets/IconSelector.vue-SxFpYToZ.js +1 -0
- package/dist/web/assets/KanbanBoardPage-7nOYpwHn.css +1 -0
- package/dist/web/assets/KanbanBoardPage-Bbyn-iLC.js +141 -0
- package/dist/web/assets/KanbanListPage-BEX3MKW0.js +1 -0
- package/dist/web/assets/KanbanListPage-DbdjvTCx.css +1 -0
- package/dist/web/assets/LaunchProjectPage-DB_XBa86.js +1 -0
- package/dist/web/assets/LaunchProjectPage-_L_i2xo0.css +1 -0
- package/dist/web/assets/LaunchServicesPage-BABQz-ey.css +1 -0
- package/dist/web/assets/LaunchServicesPage-fmsU-_p0.js +1 -0
- package/dist/web/assets/LogViewer-CJcXcTP0.css +1 -0
- package/dist/web/assets/LogViewer-CV9OmAb1.js +3 -0
- package/dist/web/assets/ProcessControls-CKmB6sB9.css +1 -0
- package/dist/web/assets/ProcessControls-L_hld0kN.js +1 -0
- package/dist/web/assets/ProcessDetailPage-B0qGKtvQ.css +1 -0
- package/dist/web/assets/ProcessDetailPage-CW0F6wvO.js +1 -0
- package/dist/web/assets/ProcessMetrics-BgEFMdnW.css +1 -0
- package/dist/web/assets/ProcessMetrics-D2vCK15o.js +1 -0
- package/dist/web/assets/ProjectDetailPage-Bo04MsdE.js +1 -0
- package/dist/web/assets/ProjectDetailPage-CZBB6F-t.css +1 -0
- package/dist/web/assets/ProjectListPage-BGU6SKAr.css +1 -0
- package/dist/web/assets/ProjectListPage-CG-r82FQ.js +1 -0
- package/dist/web/assets/RandomJobTestPage-C1mgTTSY.css +1 -0
- package/dist/web/assets/RandomJobTestPage-COnuE_dj.js +2 -0
- package/dist/web/assets/Request.vue-CeAzdpVl.js +1 -0
- package/dist/web/assets/RequestAuth.vue-DABBKM9M.js +1 -0
- package/dist/web/assets/RequestRoot.vue-CRaiGtgb.js +19 -0
- package/dist/web/assets/ScalarAsciiArt.vue-mR3JflbN.js +2 -0
- package/dist/web/assets/ScalarIconEyeSlash.vue-JQCpS43o.js +1 -0
- package/dist/web/assets/ScalarIconTrash.vue-D7zGeCPC.js +1 -0
- package/dist/web/assets/ScenarioEditorPage-BVnDp-fS.js +14 -0
- package/dist/web/assets/ScenarioEditorPage-CfBKebp6.css +1 -0
- package/dist/web/assets/ServerVariablesForm.vue-DbVG31Dx.js +1 -0
- package/dist/web/assets/ServiceControlsBar-Cp2VUifX.js +1 -0
- package/dist/web/assets/ServiceControlsBar-D_S_sGQj.css +1 -0
- package/dist/web/assets/ServiceDetailPage-BriHTCpT.css +1 -0
- package/dist/web/assets/ServiceDetailPage-DMoXJliU.js +2 -0
- package/dist/web/assets/ServiceFormPage-BXTTwyWP.js +1 -0
- package/dist/web/assets/ServiceFormPage-CyY-14jH.css +1 -0
- package/dist/web/assets/Settings.vue-BtjfBYMB.js +1 -0
- package/dist/web/assets/SettingsPage-BFqYvm6R.js +508 -0
- package/dist/web/assets/SettingsPage-vGhb_tlY.css +1 -0
- package/dist/web/assets/SetupKeyPage-CrmikLTx.js +1 -0
- package/dist/web/assets/SetupKeyPage-DoY1Ua1s.css +1 -0
- package/dist/web/assets/SetupPage-CRuL5LXc.js +1 -0
- package/dist/web/assets/SetupPage-_KXpCQSU.css +1 -0
- package/dist/web/assets/Sidebar.vue-CLpz7l3s.js +1 -0
- package/dist/web/assets/SidebarButton.vue-DAvh-OoW.js +1 -0
- package/dist/web/assets/SidebarListElement.vue-CfQ22Epo.js +1 -0
- package/dist/web/assets/UnlockPage-Cx3PYgUl.css +1 -0
- package/dist/web/assets/UnlockPage-UxunGumn.js +1 -0
- package/dist/web/assets/VariablesTable-BtdK5olT.css +1 -0
- package/dist/web/assets/VariablesTable-CKe8mApI.js +1 -0
- package/dist/web/assets/ViewLayout.vue-D30IFsIP.js +1 -0
- package/dist/web/assets/ViewLayoutContent.vue-B4BXKBtQ.js +1 -0
- package/dist/web/assets/ViewLayoutSection.vue-BGkXXzBQ.js +1 -0
- package/dist/web/assets/_plugin-vue_export-helper-C7ztIXtE.js +1 -0
- package/dist/web/assets/abap-C4tHUUCU.js +1 -0
- package/dist/web/assets/active-entities-DMSK8Kvo.js +1 -0
- package/dist/web/assets/apex-6cG6aG-w.js +1 -0
- package/dist/web/assets/api-reference-DUBKG98-.js +1 -0
- package/dist/web/assets/autocomplete-Bx5M86A5.js +308 -0
- package/dist/web/assets/azcli-51BngrSU.js +1 -0
- package/dist/web/assets/base64-uZi92-DX.js +1 -0
- package/dist/web/assets/bat-BDcdVSIt.js +1 -0
- package/dist/web/assets/bicep-Cg0BCcky.js +2 -0
- package/dist/web/assets/cameligo-C3ekVui9.js +1 -0
- package/dist/web/assets/card-6r6P_U-q.js +32 -0
- package/dist/web/assets/checkbox-CQpllPXd.js +141 -0
- package/dist/web/assets/chip-gp-_w98f.js +54 -0
- package/dist/web/assets/clojure-Ci5xNgh_.js +1 -0
- package/dist/web/assets/codicon-DCmgc-ay.ttf +0 -0
- package/dist/web/assets/coffee-xsRz4GKy.js +1 -0
- package/dist/web/assets/column-CE6TbiAC.js +763 -0
- package/dist/web/assets/core-CLjfGkKM.js +1 -0
- package/dist/web/assets/cpp-B2gW4e23.js +1 -0
- package/dist/web/assets/csharp-SRujvHqy.js +1 -0
- package/dist/web/assets/csp-Cr-ll6gP.js +1 -0
- package/dist/web/assets/css-BYTJZCno.js +3 -0
- package/dist/web/assets/cssMode-Bl7Y9u0B.js +4 -0
- package/dist/web/assets/cypher-AmQ0R_D3.js +1 -0
- package/dist/web/assets/dart-Du01a0J5.js +1 -0
- package/dist/web/assets/dist-CNJKy0Au.js +192 -0
- package/dist/web/assets/dist-DGrDIHmK.js +1 -0
- package/dist/web/assets/dist-DkaYBczY.js +1 -0
- package/dist/web/assets/dist-E9g7EMme.js +1 -0
- package/dist/web/assets/dist-wHtavuXf.js +33 -0
- package/dist/web/assets/divider-J1wJyhb6.js +82 -0
- package/dist/web/assets/dockerfile-Dtlk9wqf.js +1 -0
- package/dist/web/assets/ecl-CpmVnLkK.js +1 -0
- package/dist/web/assets/editor.store-CIIP294U.js +1 -0
- package/dist/web/assets/editor.worker-Di51weDy.js +12 -0
- package/dist/web/assets/elixir-B3MVAC8k.js +1 -0
- package/dist/web/assets/fieldset-BRuU3VW2.js +88 -0
- package/dist/web/assets/flow9-Chkly0RN.js +1 -0
- package/dist/web/assets/freemarker2-C-5i2Fhr.js +3 -0
- package/dist/web/assets/fsharp-CZvMkppk.js +1 -0
- package/dist/web/assets/go-dT2iT7lt.js +1 -0
- package/dist/web/assets/graphql-DmObWyBD.js +1 -0
- package/dist/web/assets/handlebars-Bq-uEMhK.js +1 -0
- package/dist/web/assets/hcl-D1x5Oyp4.js +1 -0
- package/dist/web/assets/html-B-mweV_C.js +1 -0
- package/dist/web/assets/htmlMode-BlnuAGDY.js +4 -0
- package/dist/web/assets/index-BRDI9Dib.css +1 -0
- package/dist/web/assets/index-gfmcW9Sb.js +4220 -0
- package/dist/web/assets/ini-Bg2o1S3s.js +1 -0
- package/dist/web/assets/java-XviKSSn5.js +1 -0
- package/dist/web/assets/javascript-D61EWPTf.js +1 -0
- package/dist/web/assets/jsonMode-DmSJWG69.js +10 -0
- package/dist/web/assets/julia-DfTIwUGh.js +1 -0
- package/dist/web/assets/keyboard-nBda2f6m.js +4 -0
- package/dist/web/assets/kotlin-CNaIBh9d.js +1 -0
- package/dist/web/assets/less-D7o76tXd.js +2 -0
- package/dist/web/assets/lexon-Dd374QjV.js +1 -0
- package/dist/web/assets/lib-CegStMAw.js +5 -0
- package/dist/web/assets/library-BwIJAfg0.js +1 -0
- package/dist/web/assets/liquid-BRXADGhu.js +1 -0
- package/dist/web/assets/lua-DZKuiFbY.js +1 -0
- package/dist/web/assets/m3-CbwRx9Bb.js +1 -0
- package/dist/web/assets/markdown-DwLB5Rib.js +1 -0
- package/dist/web/assets/mdx-DXlefD6G.js +1 -0
- package/dist/web/assets/mediaTypes-BtSbXDUA.js +2 -0
- package/dist/web/assets/message-EfwB0RVQ.js +316 -0
- package/dist/web/assets/minus-DCEEn9ly.js +2 -0
- package/dist/web/assets/mips-DLbIq1yM.js +1 -0
- package/dist/web/assets/msdax-D4IjoZ6m.js +1 -0
- package/dist/web/assets/multiselect-BMOAw1qo.js +251 -0
- package/dist/web/assets/mysql-DQL_jy6H.js +1 -0
- package/dist/web/assets/objective-c-D74wM5bv.js +1 -0
- package/dist/web/assets/pascal-5tRlZk4O.js +1 -0
- package/dist/web/assets/pascaligo-CAE4rAEt.js +1 -0
- package/dist/web/assets/password-B0kJu8RE.js +101 -0
- package/dist/web/assets/perl-DREAbuQT.js +1 -0
- package/dist/web/assets/pgsql-DASKdyAW.js +1 -0
- package/dist/web/assets/php-C37ZWqoO.js +1 -0
- package/dist/web/assets/pla-v5u9R8i1.js +1 -0
- package/dist/web/assets/plus-CaknAInj.js +197 -0
- package/dist/web/assets/postiats-Szt5m-7G.js +1 -0
- package/dist/web/assets/powerquery-BzVrUSu3.js +1 -0
- package/dist/web/assets/powershell-BdbPbX_X.js +1 -0
- package/dist/web/assets/pretty-ms-CG-W6pSW.js +202 -0
- package/dist/web/assets/primeicons-C6QP2o4f.woff2 +0 -0
- package/dist/web/assets/primeicons-DMOk5skT.eot +0 -0
- package/dist/web/assets/primeicons-Dr5RGzOO.svg +345 -0
- package/dist/web/assets/primeicons-MpK4pl85.ttf +0 -0
- package/dist/web/assets/primeicons-WjwUDZjB.woff +0 -0
- package/dist/web/assets/process.store-DxDr1XKZ.js +1 -0
- package/dist/web/assets/project.store-CUclo-tf.js +1 -0
- package/dist/web/assets/protobuf-qqDa50tu.js +2 -0
- package/dist/web/assets/pug-Cu20UQ5w.js +1 -0
- package/dist/web/assets/python-BeJzJfgr.js +1 -0
- package/dist/web/assets/qsharp-DcbHL5X7.js +1 -0
- package/dist/web/assets/r-Bvig6Flk.js +1 -0
- package/dist/web/assets/radiobutton-Dpp9kpvR.js +145 -0
- package/dist/web/assets/razor-C8GjTcdm.js +1 -0
- package/dist/web/assets/redis-BxHDcW3-.js +1 -0
- package/dist/web/assets/redshift-B8dvlzjH.js +1 -0
- package/dist/web/assets/restructuredtext-npodtAFM.js +1 -0
- package/dist/web/assets/router-BAq_YY48.js +1 -0
- package/dist/web/assets/ruby-DiofbcJD.js +1 -0
- package/dist/web/assets/rust-BjYid3-m.js +1 -0
- package/dist/web/assets/sb-CzcPAP71.js +1 -0
- package/dist/web/assets/scala-Ci4wFrYi.js +1 -0
- package/dist/web/assets/scheme-D3iWhvP7.js +1 -0
- package/dist/web/assets/scss-DdlqDgmu.js +3 -0
- package/dist/web/assets/settings.store-RtV37pb_.js +1 -0
- package/dist/web/assets/shell-Bawb9gbH.js +1 -0
- package/dist/web/assets/solidity-Z2Sq8PBC.js +1 -0
- package/dist/web/assets/sophia--yD-H1Ow.js +1 -0
- package/dist/web/assets/sparql-0vv3-wLi.js +1 -0
- package/dist/web/assets/sql-0gdWKhmJ.js +1 -0
- package/dist/web/assets/st-rE-x-DTZ.js +1 -0
- package/dist/web/assets/store-BSUCffsu.js +1840 -0
- package/dist/web/assets/style-4Pk2icOw.css +1 -0
- package/dist/web/assets/swift-CSKeG8Ne.js +1 -0
- package/dist/web/assets/systemverilog-CblNM3Im.js +1 -0
- package/dist/web/assets/tabpanel-CXo9Yhvl.js +150 -0
- package/dist/web/assets/tag-BsP7PdQ9.js +54 -0
- package/dist/web/assets/tcl-BYnzj-GZ.js +1 -0
- package/dist/web/assets/toggleswitch-C0fuTzJt.js +115 -0
- package/dist/web/assets/trpc-DgyerAaK.js +1 -0
- package/dist/web/assets/ts.worker-DHQ2j8_R.js +51339 -0
- package/dist/web/assets/tsMode-CaqfXb40.js +11 -0
- package/dist/web/assets/twig-DiGWiEtp.js +1 -0
- package/dist/web/assets/typescript-D23_zyMA.js +1 -0
- package/dist/web/assets/typespec-a6xMcpXw.js +1 -0
- package/dist/web/assets/urls-D4kou9RH.js +12 -0
- package/dist/web/assets/use-tree-walker-BebEauYQ.js +1 -0
- package/dist/web/assets/useAiChatDrawer-DDBZQU71.js +1 -0
- package/dist/web/assets/useClipboard-BgE-EP5h.js +1 -0
- package/dist/web/assets/useLayout-BtC8xLAa.js +1 -0
- package/dist/web/assets/usePluginManager-MFUURiUn.js +1 -0
- package/dist/web/assets/useSidebar-DC34K6Vb.js +1 -0
- package/dist/web/assets/uuid-B9GFVXPm.js +1 -0
- package/dist/web/assets/vb---51HVMC.js +1 -0
- package/dist/web/assets/vue-router-CCwpUNtv.js +1 -0
- package/dist/web/assets/w3c-keyname-DDCGDLuI.js +1 -0
- package/dist/web/assets/wgsl-2A8z4pT5.js +298 -0
- package/dist/web/assets/xml-e0SmIpRt.js +1 -0
- package/dist/web/assets/yaml-ChhAbF6s.js +1 -0
- package/dist/web/index.html +14 -0
- package/package.json +8 -8
- package/Dockerfile +0 -54
- package/scripts/post-build.mjs +0 -61
- package/src/__tests__/cli-port.test.ts +0 -93
- package/src/index.ts +0 -298
- package/src/port-resolution.ts +0 -19
- package/tsconfig.json +0 -9
- package/tsup.config.bundled_lh0xis3zdq.mjs +0 -10
- package/tsup.config.bundled_qj1zdvku09a.mjs +0 -10
- package/tsup.config.ts +0 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../server/src/create-server.ts","../../server/src/trpc/trpc.ts","../../server/src/services/auth-token.ts","../../server/src/services/api-key-store.ts","../../server/src/trpc/routers/health.ts","../../server/src/trpc/routers/project.ts","../../server/src/services/project-store.ts","../../server/src/services/environment-overrides-store.ts","../../server/src/services/environment-resolver.ts","../../server/src/services/audit-service.ts","../../server/src/trpc/routers/service.ts","../../server/src/services/settings-manager.ts","../../server/src/trpc/routers/agent.ts","../../server/src/trpc/routers/process.ts","../../server/src/trpc/routers/audit.ts","../../server/src/trpc/routers/setup.ts","../../server/src/trpc/routers/environment.ts","../../server/src/trpc/routers/settings.ts","../../server/src/trpc/routers/editor.ts","../../server/src/services/user-config-manager.ts","../../server/src/trpc/routers/api-keys.ts","../../server/src/trpc/routers/chat.ts","../../server/src/trpc/shared-schemas.ts","../../server/src/services/llms-txt-generator.ts","../../../packages/ai-capabilities/src/capabilities.ts","../../../packages/ai-capabilities/src/adapters/anthropic.ts","../../../packages/ai-capabilities/src/adapters/openai.ts","../../../packages/ai-capabilities/src/adapters/prompt.ts","../../../packages/ai-capabilities/src/trpc-caller.ts","../../server/src/services/chat-tools.ts","../../server/src/services/conversation-store.ts","../../server/src/services/claude-usage.ts","../../server/src/services/codex-usage.ts","../../server/src/services/active-session-registry.ts","../../server/src/services/scenario-store.ts","../../server/src/services/scenario-run-store.ts","../../server/src/services/run-store-utils.ts","../../server/src/services/ai-provider-utils.ts","../../server/src/services/image-storage.service.ts","../../server/src/services/message-images.ts","../../server/src/services/ai-runners/claude-code-runner.ts","../../server/src/services/ai-runners/runeya-api-docs.ts","../../server/src/services/ai-runners/scenario-tokens.ts","../../server/src/services/ai-runners/codex-app-server-client.ts","../../server/src/services/ai-runners/codex-runner.ts","../../server/src/trpc/routers/git.ts","../../server/src/trpc/routers/scenario.ts","../../server/src/trpc/crud-procedure-utils.ts","../../server/src/trpc/ai-generation-procedure-utils.ts","../../server/src/services/ai-generation.ts","../../server/src/services/scenario-runner.ts","../../server/src/services/scenario-presets.ts","../../server/src/trpc/routers/debug.ts","../../server/src/trpc/routers/kanban.ts","../../server/src/trpc/routers/kanban-queue.ts","../../server/src/services/kanban-queue.ts","../../server/src/trpc/routers/terminal.ts","../../server/src/trpc/routers/utility.ts","../../server/src/trpc/router.ts","../../server/src/middleware/error-handler.ts","../../server/src/services/migration-engine.ts","../../server/src/services/file-security.ts","../../server/src/utils/ensure-data-gitignore.ts","../../server/src/migrations/migrate-from-legacy.ts","../../server/src/services/master-password.ts","../../server/src/services/server-state.ts","../../server/src/services/openapi.ts","../../server/src/services/image-cleanup.service.ts","../../server/src/index.ts","../../server/src/commands/pull-env.ts"],"sourcesContent":["import express from 'express';\nimport cors from 'cors';\nimport { createServer, type Server } from 'node:http';\nimport { resolve } from 'node:path';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { createExpressMiddleware } from '@trpc/server/adapters/express';\nimport { applyWSSHandler } from '@trpc/server/adapters/ws';\nimport { appRouter } from './trpc/router.js';\nimport { createContext } from './trpc/trpc.js';\nimport { errorHandler } from './middleware/error-handler.js';\nimport { agentManager } from './services/agent-manager.js';\nimport { agentSpawner } from './services/agent-spawner.js';\nimport { settingsManager } from './services/settings-manager.js';\nimport { migrationEngine } from './services/migration-engine.js';\nimport { ensureFilePermissions } from './services/file-security.js';\nimport { auditService } from './services/audit-service.js';\nimport { environmentStore } from './services/environment-store.js';\nimport { ensureDataGitignore } from './utils/ensure-data-gitignore.js';\nimport { projectStore } from './services/project-store.js';\nimport { serviceStore } from './services/service-store.js';\nimport { runLegacyMigration, runOverrideOnlyMigration, findLegacyKeyInBackup } from './migrations/migrate-from-legacy.js';\nimport { env } from './config/env.js';\nimport {\n setEncryptionKeyInMemory,\n loadFromEnv,\n hasEncryptionKey,\n isCiMode,\n setPendingLegacyKey,\n getPendingLegacyKey,\n clearPendingLegacyKey,\n hasPendingLegacyKey,\n} from './utils/encryption-key.js';\nimport {\n generateJwtSecret,\n signJwt,\n verifyJwt,\n getJwtSecretGeneratedAt,\n} from './services/auth-token.js';\nimport {\n writeEncryptedKey,\n readEncryptedKey,\n writeVerifyFile,\n verifyEncryptionKey,\n hasEncryptedKeyFile,\n hasVerifyFile,\n} from './services/master-password.js';\nimport { getServerState } from './services/server-state.js';\nimport { apiKeyStore } from './services/api-key-store.js';\nimport { generateLlmsTxt } from './services/llms-txt-generator.js';\nimport { getOpenApiDocument } from './services/openapi.js';\nimport rateLimit from 'express-rate-limit';\nimport { existsSync, createReadStream } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport multer from 'multer';\nimport { imageStorageService, ALLOWED_MIME_TYPES, MAX_IMAGE_SIZE_BYTES } from './services/image-storage.service.js';\nimport { imageCleanupService } from './services/image-cleanup.service.js';\n\nexport interface ServerInstance {\n app: express.Express;\n server: Server;\n wss: WebSocketServer;\n shutdown(): Promise<void>;\n}\n\nfunction csrfMiddleware(req: express.Request, res: express.Response, next: express.NextFunction): void {\n const contentType = req.headers['content-type'] ?? '';\n if (!contentType.includes('application/json')) {\n res.status(415).json({ error: 'Content-Type must be application/json' });\n return;\n }\n const origin = req.headers['origin'];\n if (origin) {\n const allowedOrigins = [\n `http://localhost:${env.PORT}`,\n `http://127.0.0.1:${env.PORT}`,\n 'http://localhost:5173', // dev Vite\n 'http://127.0.0.1:5173',\n ];\n // In LAN mode, allow any origin pointing to the server port (e.g. tablet on local network)\n if (env.RUNEYA_LAN_PROXY) {\n try {\n const parsed = new URL(origin);\n const originPort = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n if (originPort === String(env.PORT) || originPort === '5173') {\n next();\n return;\n }\n } catch {\n // invalid origin URL — fall through to deny\n }\n }\n if (!allowedOrigins.includes(origin)) {\n res.status(403).json({ error: 'Forbidden origin' });\n return;\n }\n }\n next();\n}\n\nconst authLimiter = rateLimit({\n windowMs: 15 * 60 * 1000,\n max: 5,\n standardHeaders: true,\n legacyHeaders: false,\n message: { error: 'Trop de tentatives. Réessayez dans 15 minutes.' },\n});\n\nconst llmsLimiter = rateLimit({\n windowMs: 60 * 1000, // 1 minute\n max: 60,\n standardHeaders: true,\n legacyHeaders: false,\n message: { error: 'Rate limit exceeded. Retry in 1 minute.' },\n});\n\nexport async function createLocalServer(): Promise<ServerInstance> {\n // Generate JWT signing secret first\n generateJwtSecret();\n\n // Load encryption key from env var (CI mode) or check state\n const ciMode = await loadFromEnv();\n\n // Run legacy migration FIRST — loads key temporarily, re-encrypts, then stores in pending holder\n await runLegacyMigration(env.DATA_DIR);\n\n // Handle server restart between migration and setup:\n // The pending key is in-memory only, so recover it from backup if needed.\n // Only attempt recovery if .runeya-verify doesn't exist — if it does, setup\n // was already completed at least once and we should not treat this as a migration.\n if (!ciMode && !hasPendingLegacyKey() && !(await hasEncryptedKeyFile(env.DATA_DIR)) && !(await hasVerifyFile(env.DATA_DIR))) {\n const recoveredKey = await findLegacyKeyInBackup(env.DATA_DIR);\n if (recoveredKey) {\n setPendingLegacyKey(recoveredKey);\n console.log('[server] Legacy key recovered from backup — setup required to migrate');\n }\n }\n\n if (!ciMode) {\n const { state } = await getServerState();\n if (state === 'locked') {\n console.log('[server] Serveur verrouillé — master password requis');\n } else if (state === 'setup') {\n console.log('[server] Premier lancement — setup requis');\n }\n }\n\n if(!existsSync(env.DATA_DIR)) await mkdir(env.DATA_DIR);\n const absoluteDataDir = resolve(env.DATA_DIR);\n console.log(`[server] Data directory: ${absoluteDataDir}`);\n // Ensure data/.gitignore exists (prevents committing secrets & backups)\n await ensureDataGitignore(env.DATA_DIR);\n\n // Initialize settings and run migrations\n await settingsManager.getSettings();\n await migrationEngine.run();\n\n // Enforce secure file permissions on sensitive data files\n await ensureFilePermissions();\n\n // Clean up old audit log entries\n auditService.cleanup().catch((err) => console.error('[server] Audit cleanup failed:', err));\n\n const app = express();\n\n // CORS: restrict to localhost in dev, configurable via env\n // In LAN mode, allow any origin pointing to the server port or Vite dev port\n const corsOrigin = env.CORS_ORIGIN ?? (env.RUNEYA_LAN_PROXY\n ? (origin: string | undefined, cb: (err: Error | null, allow?: boolean) => void) => {\n if (!origin) { cb(null, false); return; }\n try {\n const parsed = new URL(origin);\n const port = parsed.port || (parsed.protocol === 'https:' ? '443' : '80');\n cb(null, port === String(env.PORT) || port === '5173');\n } catch {\n cb(null, false);\n }\n }\n : 'http://localhost:5173');\n app.use(cors({\n origin: corsOrigin,\n credentials: true,\n }));\n\n // Called once after the encryption key is set in memory (unlock or setup).\n // Idempotent: safe to call even if already done.\n let postUnlockDone = false;\n async function runPostUnlock(): Promise<void> {\n if (postUnlockDone) return;\n postUnlockDone = true;\n\n await runOverrideOnlyMigration(env.DATA_DIR);\n\n if (env.MODE === 'local-simple') {\n const projects = await projectStore.list();\n if (projects.length === 0) {\n const project = await projectStore.create({\n name: 'My Local Project',\n description: 'Auto-generated default project for local development',\n });\n const localEnv = await environmentStore.create({\n projectId: project.id,\n name: 'Local',\n description: 'Default local environment (immutable)',\n variables: {},\n parentIds: [],\n color: '#22c55e',\n immutable: true,\n });\n await projectStore.update({\n id: project.id,\n environmentIds: [localEnv.id],\n activeEnvironmentId: localEnv.id,\n });\n console.log('[server] Created default project with Local environment');\n }\n }\n\n // Initialize agent manager (loads persisted remote agents — requires encryption key)\n await agentManager.init();\n\n await agentSpawner.spawnLocalAgent();\n }\n\n // If key is already available at startup (CI mode or legacy plaintext key), run now\n if (hasEncryptionKey()) {\n await runPostUnlock();\n }\n\n // GET /api/status — public\n app.get('/api/status', async (_req, res) => {\n try {\n const state = await getServerState();\n res.json({ ...state, ciMode: isCiMode() });\n } catch {\n res.status(500).json({ error: 'Internal server error' });\n }\n });\n\n // POST /api/unlock — public, rate limited + CSRF\n app.post('/api/unlock', authLimiter, csrfMiddleware, express.json({ limit: '10kb' }), async (req, res) => {\n try {\n const body = req.body as { masterPassword?: unknown };\n const masterPassword = body.masterPassword;\n if (typeof masterPassword !== 'string' || masterPassword.length < 1 || masterPassword.length > 1024) {\n res.status(400).json({ error: 'masterPassword invalide' });\n return;\n }\n const encKey = await readEncryptedKey(env.DATA_DIR, masterPassword);\n setEncryptionKeyInMemory(encKey);\n await runPostUnlock();\n const token = await signJwt();\n res.json({ token });\n } catch (err) {\n console.error('[server] Unlock error:', err);\n res.status(401).json({ error: 'Master password incorrect' });\n }\n });\n\n // POST /api/setup — public, rate limited + CSRF\n app.post('/api/setup', authLimiter, csrfMiddleware, express.json({ limit: '10kb' }), async (req, res) => {\n try {\n const { state, hasVerifyFile: hasVerify, isLegacyMigration } = await getServerState();\n\n // Reject if already unlocked\n if (state === 'unlocked') {\n res.status(409).json({ error: 'Serveur déjà déverrouillé' });\n return;\n }\n\n const body = req.body as { masterPassword?: unknown; encryptionKey?: unknown };\n const masterPassword = body.masterPassword;\n if (typeof masterPassword !== 'string' || masterPassword.length < 1 || masterPassword.length > 1024) {\n res.status(400).json({ error: 'masterPassword invalide' });\n return;\n }\n\n let encKey: Buffer;\n\n if (isLegacyMigration) {\n // Read pending legacy key from in-memory holder\n const legacyKey = getPendingLegacyKey();\n if (!legacyKey) {\n res.status(500).json({ error: 'Clé legacy introuvable — redémarrez le serveur' });\n return;\n }\n encKey = legacyKey;\n } else if (hasVerify) {\n // New member: encryptionKey required\n const encryptionKeyHex = body.encryptionKey;\n if (typeof encryptionKeyHex !== 'string' || !/^[0-9a-f]{64}$/i.test(encryptionKeyHex)) {\n res.status(400).json({ error: 'encryptionKey invalide (attendu 64 hex)' });\n return;\n }\n encKey = Buffer.from(encryptionKeyHex, 'hex');\n // Verify against canary\n await verifyEncryptionKey(env.DATA_DIR, encKey);\n } else {\n // Fresh setup: generate new key or use provided key\n if (body.encryptionKey !== undefined) {\n const encryptionKeyHex = body.encryptionKey;\n if (typeof encryptionKeyHex !== 'string' || !/^[0-9a-f]{64}$/i.test(encryptionKeyHex)) {\n res.status(400).json({ error: 'encryptionKey invalide (attendu 64 hex)' });\n return;\n }\n encKey = Buffer.from(encryptionKeyHex, 'hex');\n } else {\n const { randomBytes } = await import('node:crypto');\n encKey = randomBytes(32);\n }\n }\n\n // Write .encryption.key.enc\n await writeEncryptedKey(env.DATA_DIR, masterPassword, encKey);\n\n // Verify round-trip (critical for legacy migration)\n const readBack = await readEncryptedKey(env.DATA_DIR, masterPassword);\n if (!readBack.equals(encKey)) {\n res.status(500).json({ error: 'Erreur de vérification round-trip — opération annulée' });\n return;\n }\n\n // Write .runeya-verify if not exists\n if (!hasVerify) {\n await writeVerifyFile(env.DATA_DIR, encKey);\n }\n\n setEncryptionKeyInMemory(encKey);\n if (isLegacyMigration) {\n clearPendingLegacyKey();\n }\n await runPostUnlock();\n const token = await signJwt();\n res.json({ token });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Erreur interne';\n if (message.includes('incorrecte')) {\n res.status(400).json({ error: message });\n } else {\n console.error('[server] Setup error:', err);\n res.status(500).json({ error: 'Erreur interne' });\n }\n }\n });\n\n // GET /:apikey/llms.txt — LLM API keys scopées\n app.get('/:apikey/llms.txt', llmsLimiter, async (req, res) => {\n const apikey = Array.isArray(req.params['apikey']) ? req.params['apikey'][0] : req.params['apikey'];\n // Validate format first — always 401 to avoid oracle\n if (!apikey || !/^[0-9a-f]{64}$/i.test(apikey)) {\n res.status(401).send('Unauthorized');\n return;\n }\n try {\n const key = await apiKeyStore.validateKey(apikey);\n if (!key) {\n res.status(401).send('Unauthorized');\n return;\n }\n if (!hasEncryptionKey()) {\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n const uiUrl = process.env.NODE_ENV === 'development' ? 'http://localhost:5173' : `http://localhost:${env.PORT}`;\n res.status(503).send(`# Runeya — Service Management API\\n\\n> Server is locked. Unlock with your master password at ${uiUrl} to access the full service list.\\n`);\n return;\n }\n const allServices = await serviceStore.list();\n const services = allServices.filter(s =>\n key.scopes.services.some(p => p.serviceId === s.id),\n );\n\n const content = generateLlmsTxt(key, services);\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n res.setHeader('Cache-Control', 'no-store');\n res.send(content);\n } catch (err) {\n console.error('[server] llms.txt error:', err);\n res.status(500).send('Internal server error');\n }\n });\n\n // GET /api/docs — Scalar API reference UI (standalone HTML, no auth required)\n app.get('/api/docs', (_req, res) => {\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.send(`<!doctype html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Runeya API Docs</title>\n <style>body { margin: 0; }</style>\n</head>\n<body>\n <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n <script>\n Scalar.createApiReference(document.body, { url: '/api/openapi.json' });\n </script>\n</body>\n</html>`);\n });\n\n // GET /api/openapi.json — OpenAPI specification (public, no auth required)\n app.get('/api/openapi.json', (_req, res) => {\n try {\n res.json(getOpenApiDocument());\n } catch (err) {\n console.error('[server] openapi.json error:', err instanceof Error ? err.stack : err);\n res.status(500).json({ error: 'Failed to generate OpenAPI document', detail: err instanceof Error ? err.message : String(err) });\n }\n });\n\n // ── Image upload & serve endpoints ──────────────────────────────────────\n const memStorage = multer.memoryStorage();\n const upload = multer({\n storage: memStorage,\n limits: { fileSize: MAX_IMAGE_SIZE_BYTES },\n fileFilter: (_req, file, cb) => {\n if (ALLOWED_MIME_TYPES.has(file.mimetype)) {\n cb(null, true);\n } else {\n cb(new Error(`Unsupported MIME type: ${file.mimetype}`));\n }\n },\n });\n\n const CONV_ID_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;\n const IMAGE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n app.post('/api/images/upload', upload.single('image'), async (req, res) => {\n try {\n if (!req.file) {\n res.status(400).json({ error: 'No image file provided' });\n return;\n }\n const conversationId = (req.query?.['conversationId'] ?? req.body?.conversationId) as string | undefined;\n if (!conversationId || !CONV_ID_RE.test(conversationId)) {\n res.status(400).json({ error: 'Missing or invalid conversationId' });\n return;\n }\n const stored = await imageStorageService.saveImage(\n req.file.buffer,\n req.file.originalname,\n req.file.mimetype,\n conversationId,\n );\n res.json({\n imageId: stored.imageId,\n url: `/api/images/${conversationId}/${stored.imageId}`,\n mimeType: stored.mimeType,\n });\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Upload failed';\n res.status(400).json({ error: message });\n }\n });\n\n app.get('/api/images/:conversationId/:imageId', async (req, res) => {\n try {\n const { conversationId, imageId } = req.params as { conversationId: string; imageId: string };\n if (!conversationId || !CONV_ID_RE.test(conversationId)) {\n res.status(400).json({ error: 'Invalid conversationId' });\n return;\n }\n if (!imageId || !IMAGE_ID_RE.test(imageId)) {\n res.status(400).json({ error: 'Invalid imageId' });\n return;\n }\n const result = await imageStorageService.getImagePath(imageId);\n if (!result) {\n res.status(404).json({ error: 'Image not found' });\n return;\n }\n res.setHeader('Content-Type', result.mimeType);\n res.setHeader('Cache-Control', 'no-store');\n createReadStream(result.filePath).pipe(res);\n } catch (err) {\n console.error('[server] image serve error:', err);\n res.status(500).json({ error: 'Internal server error' });\n }\n });\n\n // tRPC HTTP handler\n app.use('/api/trpc', createExpressMiddleware({\n router: appRouter,\n createContext,\n }));\n\n // Global error handler\n app.use(errorHandler);\n\n const server = createServer(app);\n\n // tRPC WebSocket handler — noServer mode so we control the upgrade\n const wss = new WebSocketServer({ noServer: true });\n applyWSSHandler({\n wss,\n router: appRouter,\n createContext: ({ req }) => {\n const headerAuth = req.headers.authorization ?? null;\n // Browser WebSocket can't set headers — also accept token from query param\n const urlObj = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const queryToken = urlObj.searchParams.get('token');\n const queryAuth = queryToken ? `Bearer ${queryToken}` : null;\n return { authorization: headerAuth ?? queryAuth };\n },\n });\n\n // Registry of active WS connections (stores only exp + iat, never the JWT)\n interface WsConnMeta { exp: number; iat: number; }\n const wsConnRegistry = new Map<WebSocket, WsConnMeta>();\n\n // Intercept HTTP→WS upgrade: validate JWT BEFORE handleUpgrade (spec Point 3)\n // Mirror protectedProcedure: skip JWT check when encryption key is in memory\n // (covers both CI mode and normal mode after master-password unlock).\n server.on('upgrade', async (req, socket, head) => {\n const auth = req.headers['authorization'] as string | undefined;\n const headerToken = auth?.startsWith('Bearer ') ? auth.slice(7) : null;\n // Browser WebSocket API can't set headers — accept token from query param as fallback\n const urlObj = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const queryToken = urlObj.searchParams.get('token');\n const token = headerToken ?? queryToken;\n\n if (!hasEncryptionKey()) {\n // Encryption key not in memory — require JWT (not yet unlocked)\n if (!token) {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n try {\n await verifyJwt(token);\n } catch {\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n return;\n }\n }\n\n wss.handleUpgrade(req, socket, head, (ws) => {\n wss.emit('connection', ws, req);\n });\n });\n\n // Register connection — JWT already verified at upgrade, safe to use verifyJwt for exp/iat\n wss.on('connection', (ws, req) => {\n const auth = req.headers['authorization'] as string | undefined;\n const headerToken = auth?.startsWith('Bearer ') ? auth.slice(7) : null;\n const urlObj2 = new URL(req.url ?? '/', `http://localhost:${env.PORT}`);\n const token = headerToken ?? urlObj2.searchParams.get('token');\n if (token) {\n verifyJwt(token).then(({ exp, iat }) => {\n wsConnRegistry.set(ws, { exp, iat });\n }).catch(() => {});\n }\n ws.on('close', () => wsConnRegistry.delete(ws));\n });\n\n // Tick every 30s — close expired connections\n const wsTickInterval = setInterval(() => {\n const now = Math.floor(Date.now() / 1000);\n const secretGeneratedAt = getJwtSecretGeneratedAt();\n for (const [ws, meta] of wsConnRegistry) {\n if (meta.exp <= now || meta.iat < secretGeneratedAt) {\n ws.close(4401, 'JWT expired or signing secret rotated');\n wsConnRegistry.delete(ws);\n }\n }\n }, 30_000);\n\n const shutdown = async () => {\n console.log('[server] Shutting down...');\n clearInterval(wsTickInterval);\n imageCleanupService.stop();\n // Kill agent immediately (SIGKILL, stateless) and close WS bridges in parallel\n await Promise.all([\n agentSpawner.shutdown(),\n agentManager.shutdown(),\n ]);\n // Force-close all active connections so the port is released instantly\n server.closeAllConnections();\n await Promise.race([\n new Promise<void>((resolve) => wss.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 2_000)),\n ]);\n await Promise.race([\n new Promise<void>((resolve) => server.close(() => resolve())),\n new Promise<void>((resolve) => setTimeout(resolve, 2_000)),\n ]);\n console.log('[server] Shutdown complete');\n };\n\n return { app, server, wss, shutdown };\n}\n","import { initTRPC, TRPCError } from '@trpc/server';\nimport type { OpenApiMeta } from 'trpc-to-openapi';\nimport type { CreateExpressContextOptions } from '@trpc/server/adapters/express';\nimport { verifyJwt } from '../services/auth-token.js';\nimport { hasEncryptionKey, isCiMode } from '../utils/encryption-key.js';\nimport { apiKeyStore } from '../services/api-key-store.js';\nimport type { ApiKey, ApiServiceAction, ApiEnvAction } from '@runeya/packages-shared';\n\nexport type CallerType = 'app' | 'api';\n\nexport function createContext({ req }: CreateExpressContextOptions) {\n return {\n authorization: req.headers.authorization ?? null,\n };\n}\n\nexport type Context = Awaited<ReturnType<typeof createContext>>;\n\nexport type AuthContext = Context & {\n callerType: CallerType;\n apiKey: ApiKey | null;\n};\n\nconst t = initTRPC.context<Context>().meta<OpenApiMeta>().create({\n errorFormatter({ shape, error }) {\n return {\n ...shape,\n data: {\n ...shape.data,\n message: error.message,\n },\n };\n },\n});\n\nexport const router = t.router;\nexport const publicProcedure = t.procedure;\n\nconst API_KEY_REGEX = /^[0-9a-f]{64}$/i;\n\nconst authMiddleware = t.middleware(async ({ ctx, next }) => {\n const { authorization } = ctx;\n\n // API API key: 64 hex chars — checked before the JWT/encryption-key bypass\n if (authorization?.startsWith('Bearer ') && API_KEY_REGEX.test(authorization.slice(7))) {\n if (!hasEncryptionKey()) {\n throw new TRPCError({ code: 'PRECONDITION_FAILED', message: 'Server is locked — master password must be unlocked before using API API keys' });\n }\n const token = authorization.slice(7);\n const apiKey = await apiKeyStore.validateKey(token);\n if (!apiKey) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid API API key' });\n }\n return next({ ctx: { ...ctx, callerType: 'api' as CallerType, apiKey } });\n }\n\n // CI mode: key loaded from RUNEYA_ENCRYPTION_KEY env var — no JWT in circulation, bypass auth.\n if (isCiMode()) {\n return next({ ctx: { ...ctx, callerType: 'app' as CallerType, apiKey: null } });\n }\n\n if (!authorization?.startsWith('Bearer ')) {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Missing or invalid Authorization header' });\n }\n\n const token = authorization.slice(7);\n\n try {\n await verifyJwt(token);\n } catch {\n throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Invalid or expired token' });\n }\n\n return next({ ctx: { ...ctx, callerType: 'app' as CallerType, apiKey: null } });\n});\n\nexport const protectedProcedure = t.procedure.use(authMiddleware);\n\n// ---------------------------------------------------------------------------\n// API scope enforcement helpers\n// Call these at the top of route handlers that API callers can reach.\n// App callers (callerType === 'app') always pass through.\n// ---------------------------------------------------------------------------\n\n/** Throw FORBIDDEN if an API caller lacks `action` on `serviceId`. */\nexport function requireServiceAction(\n ctx: AuthContext,\n serviceId: string,\n action: ApiServiceAction,\n): void {\n if (ctx.callerType !== 'api') return;\n const perm = ctx.apiKey!.scopes.services.find(p => p.serviceId === serviceId);\n if (!perm?.actions.includes(action)) {\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: `API key lacks '${action}' permission on service ${serviceId}`,\n });\n }\n}\n\n/**\n * Return the set of service IDs an API caller is allowed to see.\n * Returns null for app callers (= all services allowed).\n */\nexport function getAllowedServiceIds(ctx: AuthContext): Set<string> | null {\n if (ctx.callerType !== 'api') return null;\n return new Set(ctx.apiKey!.scopes.services.map(p => p.serviceId));\n}\n\n/**\n * Throw FORBIDDEN if an API caller lacks `action` on `environmentId`.\n * Returns whether secrets are allowed (always true for app callers).\n *\n * @param serviceId - when provided, the check is restricted to the permission entry for that\n * specific service. This prevents cross-service escalation: a global env ID shared across\n * multiple services cannot grant access via a different service's permission entry.\n */\nexport function requireEnvAction(\n ctx: AuthContext,\n environmentId: string,\n action: ApiEnvAction,\n serviceId?: string,\n): { includeSecrets: boolean } {\n if (ctx.callerType !== 'api') return { includeSecrets: true };\n const permsToCheck = serviceId\n ? ctx.apiKey!.scopes.services.filter(p => p.serviceId === serviceId)\n : ctx.apiKey!.scopes.services;\n for (const svcPerm of permsToCheck) {\n const envPerm = svcPerm.environments.find(e => e.environmentId === environmentId);\n if (envPerm?.actions.includes(action)) {\n return { includeSecrets: envPerm.includeSecrets };\n }\n }\n throw new TRPCError({\n code: 'FORBIDDEN',\n message: `API key lacks '${action}' permission on environment ${environmentId}`,\n });\n}\n","import { randomBytes } from 'node:crypto';\nimport { SignJWT, jwtVerify } from 'jose';\n\ntype CallerType = 'app'; // 'api' via API keys (future)\n\nlet jwtSecret: Uint8Array | null = null;\nlet jwtSecretGeneratedAt: number = 0; // Unix timestamp seconds\n\nexport function generateJwtSecret(): void {\n jwtSecret = new Uint8Array(randomBytes(32));\n jwtSecretGeneratedAt = Math.floor(Date.now() / 1000);\n}\n\nexport function getJwtSecretGeneratedAt(): number {\n return jwtSecretGeneratedAt;\n}\n\nfunction getJwtSecret(): Uint8Array {\n if (!jwtSecret) throw new Error('JWT secret not yet generated');\n return jwtSecret;\n}\n\n/** Sign a JWT valid for 8 hours */\nexport async function signJwt(): Promise<string> {\n const secret = getJwtSecret();\n return new SignJWT({ sub: 'app' })\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setExpirationTime('8h')\n .sign(secret);\n}\n\nexport interface JwtPayload {\n exp: number;\n iat: number;\n}\n\n/** Verify a JWT — throws if invalid/expired */\nexport async function verifyJwt(token: string): Promise<JwtPayload> {\n const secret = getJwtSecret();\n const { payload } = await jwtVerify(token, secret);\n return { exp: payload.exp as number, iat: payload.iat as number };\n}\n","import { randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { ApiKeysFileSchema, type ApiKey, type ApiKeyScope } from '@runeya/packages-shared';\n\nconst FILE_PUBLIC = 'api-keys.json';\nconst FILE_PRIVATE = 'api-keys.private.json';\n\nclass ApiKeyStore {\n private keys: Map<string, ApiKey> = new Map();\n private loaded = false;\n\n private filePath(isPublic: boolean): string {\n return join(env.DATA_DIR, isPublic ? FILE_PUBLIC : FILE_PRIVATE);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async persistFile(isPublic: boolean): Promise<void> {\n await this.ensureDir();\n const path = this.filePath(isPublic);\n const keys = Array.from(this.keys.values()).filter(k => k.isPublic === isPublic);\n const tmp = path + '.tmp';\n await writeFile(tmp, JSON.stringify({ keys }, null, 2), 'utf-8');\n await rename(tmp, path);\n await chmod(path, 0o600);\n }\n\n private async persist(isPublic: boolean): Promise<void> {\n await this.persistFile(isPublic);\n }\n\n private async loadFile(path: string): Promise<void> {\n try {\n const raw = await readFile(path, 'utf-8');\n const parsed = ApiKeysFileSchema.safeParse(JSON.parse(raw));\n if (parsed.success) {\n for (const k of parsed.data.keys) {\n this.keys.set(k.id, k);\n }\n }\n } catch {\n // File doesn't exist yet — start empty\n }\n }\n\n async load(): Promise<void> {\n if (this.loaded) return;\n this.loaded = true;\n await this.loadFile(this.filePath(true));\n await this.loadFile(this.filePath(false));\n }\n\n async list(): Promise<ApiKey[]> {\n await this.load();\n return Array.from(this.keys.values());\n }\n\n async create(name: string, scopes: ApiKeyScope, isPublic: boolean): Promise<ApiKey> {\n await this.load();\n const apiKey: ApiKey = {\n id: `apikey-${randomUUID()}`,\n name,\n key: randomBytes(32).toString('hex'),\n scopes,\n createdAt: new Date().toISOString(),\n isPublic,\n };\n this.keys.set(apiKey.id, apiKey);\n await this.persist(isPublic);\n return apiKey;\n }\n\n async update(id: string, name: string, scopes: ApiKeyScope, isPublic: boolean): Promise<ApiKey | null> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return null;\n const updated: ApiKey = { ...existing, name, scopes, isPublic };\n this.keys.set(id, updated);\n // If isPublic changed, persist both files (remove from old, add to new)\n if (existing.isPublic !== isPublic) {\n await this.persistFile(existing.isPublic);\n await this.persistFile(isPublic);\n } else {\n await this.persist(isPublic);\n }\n return updated;\n }\n\n async remove(id: string): Promise<boolean> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return false;\n this.keys.delete(id);\n await this.persist(existing.isPublic);\n return true;\n }\n\n async renewKey(id: string): Promise<ApiKey | null> {\n await this.load();\n const existing = this.keys.get(id);\n if (!existing) return null;\n const renewed: ApiKey = { ...existing, key: randomBytes(32).toString('hex') };\n this.keys.set(id, renewed);\n await this.persist(renewed.isPublic);\n return renewed;\n }\n\n async validateKey(candidateHex: string): Promise<ApiKey | null> {\n await this.load();\n if (!/^[0-9a-f]{64}$/i.test(candidateHex)) return null;\n const candidate = Buffer.from(candidateHex, 'hex');\n for (const apiKey of this.keys.values()) {\n const stored = Buffer.from(apiKey.key, 'hex');\n if (candidate.length === stored.length && timingSafeEqual(candidate, stored)) {\n return apiKey;\n }\n }\n return null;\n }\n}\n\nexport const apiKeyStore = new ApiKeyStore();\n","import { z } from 'zod';\nimport { router, publicProcedure } from '../trpc.js';\n\nconst startedAt = Date.now();\n\nexport const healthRouter = router({\n check: publicProcedure\n .meta({ openapi: { method: 'GET', path: '/health', tags: ['health'], summary: 'Health check' } })\n .output(z.object({ status: z.literal('ok'), uptime: z.number() }))\n .query(() => {\n return {\n status: 'ok' as const,\n uptime: Date.now() - startedAt,\n };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\n\nexport const projectRouter = router({\n list: protectedProcedure.query(async () => {\n return projectStore.list();\n }),\n\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const project = await projectStore.get(input.id);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n return project;\n }),\n\n create: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(10000).optional(),\n orgId: z.string().max(128).nullable().optional(),\n serviceIds: z.array(z.string().max(128)).max(10000).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n // Create the project first (with empty environmentIds, will be updated after creating local env)\n const project = await projectStore.create({\n ...input,\n description: input.description ?? '',\n serviceIds: input.serviceIds ?? [],\n environmentIds: [],\n });\n\n // Create the default 'local' immutable environment for this project\n const localEnv = await environmentStore.create({\n projectId: project.id,\n name: 'local',\n description: 'Default local environment (immutable)',\n parentIds: [],\n immutable: true,\n });\n\n // Update the project with the local environment\n const result = await projectStore.update({\n id: project.id,\n environmentIds: [localEnv.id],\n activeEnvironmentId: localEnv.id,\n });\n\n await auditService.log({ userId: 'local', action: 'create', entityType: 'project', entityId: project.id, metadata: { name: input.name } });\n return result!;\n }),\n\n update: protectedProcedure\n .input(\n z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(200).optional(),\n description: z.string().max(10000).optional(),\n orgId: z.string().max(128).nullable().optional(),\n serviceIds: z.array(z.string().max(128)).max(10000).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n const project = await projectStore.update(input);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'update', entityType: 'project', entityId: input.id });\n return project;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const deleted = await projectStore.delete(input.id);\n if (!deleted) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'delete', entityType: 'project', entityId: input.id });\n return { success: true as const };\n }),\n\n addService: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), serviceId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.addService(input.projectId, input.serviceId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n\n // Auto-create service-scoped environments for each global env in the project\n const service = await serviceStore.get(input.serviceId);\n if (service) {\n const globalEnvs = await environmentStore.listByScope(input.projectId, 'global');\n for (const globalEnv of globalEnvs) {\n const svcEnv = await environmentStore.create({\n projectId: input.projectId,\n name: `${service.name} (${globalEnv.name})`,\n scope: 'service',\n reference: input.serviceId,\n activateOn: globalEnv.id,\n parentIds: [globalEnv.id],\n variables: {},\n });\n await projectStore.addEnvironment(input.projectId, svcEnv.id);\n }\n }\n\n await auditService.log({\n userId: 'local',\n action: 'update',\n entityType: 'project',\n entityId: input.projectId,\n metadata: { operation: 'addService', serviceId: input.serviceId },\n });\n return project;\n }),\n\n removeService: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), serviceId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.removeService(input.projectId, input.serviceId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n await auditService.log({\n userId: 'local',\n action: 'update',\n entityType: 'project',\n entityId: input.projectId,\n metadata: { operation: 'removeService', serviceId: input.serviceId },\n });\n return project;\n }),\n\n setActiveEnvironment: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), environmentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const project = await projectStore.get(input.projectId);\n if (!project) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Project ${input.projectId} not found` });\n }\n\n // Validate environment exists\n const environment = await environmentStore.get(input.environmentId);\n if (!environment) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n }\n if (environment.projectId !== input.projectId) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Environment does not belong to this project' });\n }\n\n // Collect running services before changing environment\n const runningServices: { serviceId: string; agentId: string }[] = [];\n\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service || !service.agentId) continue;\n\n const agentStatus = agentManager.getStatus(service.agentId);\n if (!agentStatus?.connected) continue;\n\n try {\n const processStatus = await agentManager.agentQuery<{ status: string }>(\n service.agentId,\n 'process.get',\n { id: serviceId }\n );\n\n if (processStatus?.status === 'running' || processStatus?.status === 'starting') {\n runningServices.push({ serviceId, agentId: service.agentId });\n }\n } catch {\n // Agent unreachable or process not deployed — skip\n }\n }\n\n // Update environment\n const updated = await projectStore.setActiveEnvironment(input.projectId, input.environmentId);\n\n if (!updated) {\n throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to set active environment' });\n }\n\n // Push resolved config to ALL assigned services (running or not)\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service || !service.agentId) continue;\n\n const agentStatus = agentManager.getStatus(service.agentId);\n if (!agentStatus?.connected) continue;\n\n // Always resolve — the resolver handles empty service variables\n let resolvedService = service;\n try {\n const resolved = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: input.environmentId,\n });\n\n resolvedService = {\n ...service,\n env: { ...resolved.env },\n envSecrets: [...resolved.envSecrets],\n };\n } catch (err) {\n console.error('[project-router] Failed to resolve variables for service', serviceId + ':', (err as Error).message);\n }\n\n const wasRunning = runningServices.some(rs => rs.serviceId === serviceId);\n\n if (wasRunning) {\n // Stop → deploy (with new env) → start\n // Uses deploy instead of updateConfig for consistency with the lazy deploy pattern\n try {\n await agentManager.agentMutation(service.agentId, 'process.stop', { id: serviceId });\n await agentManager.agentMutation(service.agentId, 'process.deploy', resolvedService);\n await agentManager.agentMutation(service.agentId, 'process.start', { id: serviceId });\n } catch (err) {\n console.error('[project-router] Failed to restart service', serviceId + ':', (err as Error).message);\n }\n }\n // Stopped services: no need to push config — the next start will\n // lazy-deploy with the freshly resolved environment anyway.\n }\n\n return updated;\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport type { Project, CreateProject, UpdateProject } from '@runeya/packages-shared';\nimport { environmentStore } from './environment-store.js';\n\nconst FILENAME = 'projects.json';\n\nclass ProjectStore {\n private projects: Map<string, Project> = new Map();\n private loaded = false;\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const data: Project[] = JSON.parse(raw);\n for (const p of data) {\n const projectEnvs = await environmentStore.getByProjectId(p.id).catch(() => []);\n const defaultEnv = projectEnvs.find(e => e.default);\n this.projects.set(p.id, {\n ...p,\n environmentIds: p.environmentIds ?? [],\n // Prefer the env marked default, fall back to first env\n activeEnvironmentId: defaultEnv?.id ?? p.environmentIds?.[0],\n });\n }\n } catch {\n // File doesn't exist yet, start empty\n }\n this.loaded = true;\n }\n\n private async save(): Promise<void> {\n await this.ensureDir();\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n\n // Omit activeEnvironmentId from persistence (runtime-only field)\n const projectsToSave = Array.from(this.projects.values()).map(({ activeEnvironmentId, ...rest }) => rest);\n\n const data = JSON.stringify(projectsToSave, null, 2);\n await writeFile(tmpPath, data, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n async list(): Promise<Project[]> {\n await this.load();\n return Array.from(this.projects.values());\n }\n\n async get(id: string): Promise<Project | null> {\n await this.load();\n return this.projects.get(id) ?? null;\n }\n\n async create(input: CreateProject): Promise<Project> {\n await this.load();\n const project: Project = {\n id: randomUUID(),\n orgId: input.orgId ?? null,\n name: input.name,\n description: input.description ?? '',\n serviceIds: input.serviceIds ?? [],\n environmentIds: input.environmentIds ?? [],\n activeEnvironmentId: input.activeEnvironmentId,\n };\n this.projects.set(project.id, project);\n await this.save();\n return project;\n }\n\n async update(input: UpdateProject): Promise<Project | null> {\n await this.load();\n const existing = this.projects.get(input.id);\n if (!existing) return null;\n const updated: Project = {\n ...existing,\n ...(input.name !== undefined && { name: input.name }),\n ...(input.description !== undefined && { description: input.description }),\n ...(input.serviceIds !== undefined && { serviceIds: input.serviceIds }),\n ...(input.environmentIds !== undefined && { environmentIds: input.environmentIds }),\n ...(input.activeEnvironmentId !== undefined && { activeEnvironmentId: input.activeEnvironmentId }),\n ...(input.orgId !== undefined && { orgId: input.orgId }),\n };\n this.projects.set(input.id, updated);\n await this.save();\n return updated;\n }\n\n async delete(id: string): Promise<boolean> {\n await this.load();\n if (!this.projects.has(id)) return false;\n this.projects.delete(id);\n await this.save();\n return true;\n }\n\n async addService(projectId: string, serviceId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n if (project.serviceIds.includes(serviceId)) return project;\n const updated = { ...project, serviceIds: [...project.serviceIds, serviceId] };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async removeService(projectId: string, serviceId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n const updated = { ...project, serviceIds: project.serviceIds.filter(id => id !== serviceId) };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async addEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n if (project.environmentIds?.includes(environmentId)) return project;\n const updated = {\n ...project,\n environmentIds: [...(project.environmentIds ?? []), environmentId],\n };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async removeEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n const updated = {\n ...project,\n environmentIds: (project.environmentIds ?? []).filter(id => id !== environmentId),\n // Clear activeEnvironmentId if it was the removed environment\n ...(project.activeEnvironmentId === environmentId && { activeEnvironmentId: undefined }),\n };\n this.projects.set(projectId, updated);\n await this.save();\n return updated;\n }\n\n async setActiveEnvironment(projectId: string, environmentId: string): Promise<Project | null> {\n await this.load();\n const project = this.projects.get(projectId);\n if (!project) return null;\n\n // Update activeEnvironmentId in memory only (not persisted to JSON)\n // Do NOT update updatedAt since this is a runtime preference, not a project modification\n const updated: Project = {\n ...project,\n activeEnvironmentId: environmentId,\n };\n\n this.projects.set(projectId, updated);\n // No save() call - activeEnvironmentId is runtime-only\n return updated;\n }\n}\n\nexport const projectStore = new ProjectStore();\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { getEncryptionKey } from '../utils/encryption-key.js';\nimport {\n encryptVariableSlots,\n decryptVariableSlots,\n extractEncryptedVariableSlots,\n} from './crypto-helpers.js';\nimport type { Variable, VariableSlot } from '@runeya/packages-shared';\n\nconst FILENAME = 'environment-overrides.json';\n\n// On disk: flat Record<variableId, Variable>\ntype OverridesData = Record<string, Variable>;\n\nclass EnvironmentOverridesStore {\n private data: OverridesData = {};\n private loaded = false;\n private diskEncryptedSlots: Record<string, string> = {};\n private saveQueue: Promise<void> = Promise.resolve();\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const parsed: OverridesData = JSON.parse(raw);\n\n if (!getEncryptionKey()) {\n this.loaded = true;\n return;\n }\n\n // Cache encrypted slots then decrypt\n this.diskEncryptedSlots = extractEncryptedVariableSlots(\n parsed as Record<string, { value: VariableSlot }>,\n );\n this.data = decryptVariableSlots(\n parsed as Record<string, { value: VariableSlot }>,\n 'environment-overrides',\n ) as OverridesData;\n } catch {\n this.data = {};\n }\n this.loaded = true;\n }\n\n private save(): Promise<void> {\n this.saveQueue = this.saveQueue.then(() => this.doSave()).catch(() => this.doSave());\n return this.saveQueue;\n }\n\n private async doSave(): Promise<void> {\n await this.ensureDir();\n const filePath = this.getFilePath();\n const tmpPath = filePath + '.tmp';\n\n const encrypted = encryptVariableSlots(\n this.data as Record<string, { value: VariableSlot }>,\n this.diskEncryptedSlots,\n ) as OverridesData;\n this.diskEncryptedSlots = extractEncryptedVariableSlots(\n encrypted as Record<string, { value: VariableSlot }>,\n );\n\n const json = JSON.stringify(encrypted, null, 2);\n await writeFile(tmpPath, json, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n async getOverride(variableId: string): Promise<Variable | null> {\n await this.load();\n return this.data[variableId] ?? null;\n }\n\n async setOverride(variableId: string, variable: Variable): Promise<void> {\n await this.load();\n this.data[variableId] = variable;\n await this.save();\n }\n\n async removeOverride(variableId: string): Promise<void> {\n await this.load();\n if (!this.data[variableId]) return;\n delete this.data[variableId];\n await this.save();\n }\n\n async getAll(): Promise<Record<string, Variable>> {\n await this.load();\n return { ...this.data };\n }\n\n async removeOverridesForVariables(variableIds: string[]): Promise<void> {\n await this.load();\n let changed = false;\n for (const id of variableIds) {\n if (this.data[id]) {\n delete this.data[id];\n changed = true;\n }\n }\n if (changed) await this.save();\n }\n}\n\nexport const environmentOverridesStore = new EnvironmentOverridesStore();\n","import type { Variable, ResolvedEnvironment } from '@runeya/packages-shared';\nimport { environmentStore } from './environment-store.js';\nimport { environmentOverridesStore } from './environment-overrides-store.js';\n\ninterface VariableSource {\n environmentId: string;\n environmentName: string;\n overridden: boolean;\n resolvedFrom?: { environmentId: string; environmentName: string };\n}\n\ninterface DagResult {\n variables: Record<string, Variable>;\n sources: Record<string, VariableSource>;\n /** Concrete parent values keyed by variable key (pre-dedup), used for interpolation context */\n parentEnv: Record<string, string>;\n /** Keys in parentEnv that are secret */\n parentSecretKeys: Set<string>;\n /** Maps variable key → source environment info for parent variables (before child override) */\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>;\n}\n\n/**\n * Interpolate {{environment.KEY}} references in a value string.\n * envContext is the flat dict of resolved environment values.\n * Returns the interpolated string.\n * Missing keys are left as-is ({{environment.MISSING}} -> unchanged).\n */\nfunction interpolateValue(raw: string, envContext: Record<string, string>): string {\n return raw.replace(/\\{\\{environment\\.([^}]+)\\}\\}/g, (match, key) => {\n return envContext[key] !== undefined ? envContext[key] : match;\n });\n}\n\n/**\n * Resolve a Variable to its final string value.\n * Uses variable.value slot, computes pre + interpolate(value) + post.\n */\nfunction resolveVariable(\n variable: Variable,\n envContext: Record<string, string>,\n): { value: string; isSecret: boolean } {\n const slot = variable.value;\n const interpolated = interpolateValue(slot.value, envContext);\n const finalValue = slot.pre + interpolated + slot.post;\n return { value: finalValue, isSecret: slot.isSecret };\n}\n\nclass EnvironmentResolver {\n async resolveForService(ctx: { serviceId: string; activeEnvironmentId: string }): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n if (!ctx.activeEnvironmentId) {\n return { env: {}, envSecrets: [] };\n }\n\n // Find the service-scoped environment for this service + active global env\n const serviceEnv = await environmentStore.findServiceEnvironment(ctx.serviceId, ctx.activeEnvironmentId);\n\n if (!serviceEnv) {\n // No service env: resolve just the global env\n return this.resolveEnvironment(ctx.activeEnvironmentId);\n }\n\n // Resolve the service env (which inherits from global via parentIds)\n return this.resolveEnvironment(serviceEnv.id);\n }\n\n async resolveEnvironment(environmentId: string): Promise<{ env: Record<string, string>; envSecrets: string[] }> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides\n const allOverrides = await environmentOverridesStore.getAll();\n for (const [varId, override] of Object.entries(allOverrides)) {\n if (result.variables[varId]) {\n result.variables[varId] = override;\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context:\n // Start from parent concrete values, then overlay with current concrete values.\n // This ensures {{environment.KEY}} resolves against parent values when the child\n // redefines KEY as an interpolation reference.\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || this.interpolatesSecretKey(variable.value.value, ctxSecretKeys)) {\n envSecrets.push(variable.key);\n }\n }\n\n return { env, envSecrets };\n }\n\n async resolveEnvironmentWithSources(environmentId: string): Promise<ResolvedEnvironment> {\n const visited = new Set<string>();\n const result = await this.resolveDag(environmentId, visited);\n\n // Apply overrides\n const allOverrides = await environmentOverridesStore.getAll();\n for (const [varId, override] of Object.entries(allOverrides)) {\n if (result.variables[varId]) {\n result.variables[varId] = override;\n result.sources[varId] = {\n ...result.sources[varId],\n overridden: true,\n };\n }\n }\n\n // First pass: build raw env dict (no interpolation yet)\n const rawEnv: Record<string, string> = {};\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const slot = variable.value;\n rawEnv[variable.key] = slot.pre + slot.value + slot.post;\n }\n\n // Build interpolation context\n const { ctx: interpolationCtx, secretKeys: ctxSecretKeys, keySources } = await this.buildInterpolationContext(environmentId, rawEnv, result.parentEnv, result.parentSecretKeys, result.parentKeySources);\n\n // Second pass: interpolate and build final env dict\n const env: Record<string, string> = {};\n const envSecrets: string[] = [];\n for (const [_varId, variable] of Object.entries(result.variables)) {\n const { value, isSecret } = resolveVariable(variable, interpolationCtx);\n env[variable.key] = value;\n if (isSecret || this.interpolatesSecretKey(variable.value.value, ctxSecretKeys)) {\n envSecrets.push(variable.key);\n }\n }\n\n // Post-process: for pure interpolation references, annotate `resolvedFrom`\n // so the frontend knows where the resolved value actually comes from,\n // while keeping the source pointing to where the variable is defined.\n const refPattern = /^\\{\\{environment\\.([^}]+)\\}\\}$/;\n for (const [varId, variable] of Object.entries(result.variables)) {\n const match = variable.value.value.match(refPattern);\n if (match) {\n const refSource = keySources[match[1]];\n if (refSource && result.sources[varId]?.environmentId !== refSource.environmentId) {\n result.sources[varId] = {\n ...result.sources[varId],\n resolvedFrom: refSource,\n };\n }\n }\n }\n\n return {\n variables: result.variables,\n env,\n envSecrets,\n sources: result.sources,\n };\n }\n\n /** Check if a raw value string interpolates any key that is secret in the context */\n private interpolatesSecretKey(rawValue: string, ctxSecretKeys: Set<string>): boolean {\n const refs = [...rawValue.matchAll(/\\{\\{environment\\.([^}]+)\\}\\}/g)].map(m => m[1]);\n return refs.some(ref => ctxSecretKeys.has(ref));\n }\n\n /**\n * Build the interpolation context for an environment.\n *\n * For inheriting envs (has parents): start from parent concrete values,\n * then overlay with current concrete values. This ensures that\n * {{environment.KEY}} resolves against the parent's value when the child\n * redefines KEY as an interpolation reference.\n *\n * For isolated service envs (scope=service, activateOn set, no parents):\n * the global env is resolved and used as fallback.\n */\n private async buildInterpolationContext(\n environmentId: string,\n rawEnv: Record<string, string>,\n parentEnv: Record<string, string>,\n parentSecretKeys: Set<string>,\n parentKeySources: Record<string, { environmentId: string; environmentName: string }>,\n ): Promise<{ ctx: Record<string, string>; secretKeys: Set<string>; keySources: Record<string, { environmentId: string; environmentName: string }> }> {\n const environment = await environmentStore.get(environmentId);\n\n // Isolated service env: resolve global env for interpolation context\n if (\n environment\n && environment.scope === 'service'\n && environment.activateOn\n && (!environment.parentIds || environment.parentIds.length === 0)\n ) {\n const globalResolved = await this.resolveEnvironmentWithSources(environment.activateOn);\n const secretKeys = new Set(globalResolved.envSecrets);\n // Build keySources from global env variables\n const keySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(globalResolved.variables)) {\n const source = globalResolved.sources[varId];\n if (source) {\n keySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Start with global values, then override with local values that are\n // concrete (not themselves interpolation references)\n const ctx = { ...globalResolved.env };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys, keySources };\n }\n\n // Inheriting env: start from parent concrete values, overlay with concrete rawEnv values\n const ctx = { ...parentEnv };\n for (const [key, value] of Object.entries(rawEnv)) {\n if (!/\\{\\{environment\\.[^}]+\\}\\}/.test(value)) {\n ctx[key] = value;\n }\n }\n return { ctx, secretKeys: parentSecretKeys, keySources: parentKeySources };\n }\n\n private async resolveDag(environmentId: string, visited: Set<string>): Promise<DagResult> {\n if (visited.has(environmentId)) {\n throw new Error(`Circular dependency detected in environment inheritance for ${environmentId}`);\n }\n\n const environment = await environmentStore.get(environmentId);\n if (!environment) {\n throw new Error(`Environment \"${environmentId}\" not found`);\n }\n\n visited.add(environmentId);\n\n // Resolve all parents first\n const parentResults: DagResult[] = [];\n for (const parentId of environment.parentIds) {\n const parentVisited = new Set(visited);\n const parentResult = await this.resolveDag(parentId, parentVisited);\n parentResults.push(parentResult);\n }\n\n // Merge parent variables (left-to-right, later parents override earlier)\n const mergedVariables: Record<string, Variable> = {};\n const sources: Record<string, VariableSource> = {};\n\n for (const result of parentResults) {\n // Dedup by key: if a later parent has a variable with the same key, remove the earlier one\n for (const [varId, variable] of Object.entries(result.variables)) {\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = result.sources[varId] ?? sources[varId];\n }\n }\n\n // Build parentEnv: concrete values from parents BEFORE child dedup/override\n // Used as interpolation context so {{environment.KEY}} resolves against parent values\n const parentEnv: Record<string, string> = {};\n const parentSecretKeys = new Set<string>();\n const parentKeySources: Record<string, { environmentId: string; environmentName: string }> = {};\n for (const [varId, variable] of Object.entries(mergedVariables)) {\n const slot = variable.value;\n parentEnv[variable.key] = slot.pre + slot.value + slot.post;\n if (slot.isSecret) {\n parentSecretKeys.add(variable.key);\n }\n const source = sources[varId];\n if (source) {\n parentKeySources[variable.key] = { environmentId: source.environmentId, environmentName: source.environmentName };\n }\n }\n // Also include parent-of-parent values for deeper chains\n for (const result of parentResults) {\n for (const [key, value] of Object.entries(result.parentEnv)) {\n if (!(key in parentEnv)) {\n parentEnv[key] = value;\n }\n }\n for (const key of result.parentSecretKeys) {\n parentSecretKeys.add(key);\n }\n for (const [key, source] of Object.entries(result.parentKeySources)) {\n if (!(key in parentKeySources)) {\n parentKeySources[key] = source;\n }\n }\n }\n\n // Apply current environment's own variables\n for (const [varId, variable] of Object.entries(environment.variables)) {\n // Remove any parent variable with the same key but different variableId (dedup by key)\n let wasInherited = varId in mergedVariables;\n for (const [existingId, existingVar] of Object.entries(mergedVariables)) {\n if (existingVar.key === variable.key && existingId !== varId) {\n delete mergedVariables[existingId];\n delete sources[existingId];\n wasInherited = true;\n }\n }\n mergedVariables[varId] = variable;\n sources[varId] = {\n environmentId: environment.id,\n environmentName: environment.name,\n overridden: wasInherited,\n };\n }\n\n return {\n variables: mergedVariables,\n sources,\n parentEnv,\n parentSecretKeys,\n parentKeySources,\n };\n }\n}\n\nexport const environmentResolver = new EnvironmentResolver();\n","import { appendFile, readFile, stat, rename, unlink, readdir, mkdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\n\nexport interface AuditEntry {\n timestamp: string;\n userId: string;\n action: string;\n entityType: string;\n entityId: string;\n metadata?: Record<string, unknown>;\n}\n\nconst AUDIT_FILENAME = 'audit.log';\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\nconst MAX_AGE_DAYS = 30;\n\nclass AuditService {\n private getFilePath(): string {\n return join(env.DATA_DIR, AUDIT_FILENAME);\n }\n\n private getRotatedPath(): string {\n return join(env.DATA_DIR, `audit.log.${Date.now()}.bak`);\n }\n\n /** Append an audit entry (newline-delimited JSON) */\n async log(entry: Omit<AuditEntry, 'timestamp'>): Promise<void> {\n const record: AuditEntry = {\n ...entry,\n timestamp: new Date().toISOString(),\n };\n const line = JSON.stringify(record) + '\\n';\n const filepath = this.getFilePath();\n\n try {\n await mkdir(env.DATA_DIR, { recursive: true });\n await appendFile(filepath, line, 'utf-8');\n await this.rotateIfNeeded();\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n console.error('[audit] Failed to write audit log:', message);\n }\n }\n\n /** Read audit entries, optionally filtered */\n async list(options?: {\n action?: string;\n entityType?: string;\n entityId?: string;\n limit?: number;\n offset?: number;\n }): Promise<{ entries: AuditEntry[]; total: number }> {\n const filepath = this.getFilePath();\n let lines: string[];\n try {\n const content = await readFile(filepath, 'utf-8');\n lines = content.trim().split('\\n').filter(Boolean);\n } catch {\n return { entries: [], total: 0 };\n }\n\n let entries: AuditEntry[] = lines\n .map((line) => {\n try { return JSON.parse(line) as AuditEntry; } catch { return null; }\n })\n .filter((e): e is AuditEntry => e !== null)\n .reverse(); // newest first\n\n // Apply filters\n if (options?.action) {\n entries = entries.filter((e) => e.action === options.action);\n }\n if (options?.entityType) {\n entries = entries.filter((e) => e.entityType === options.entityType);\n }\n if (options?.entityId) {\n entries = entries.filter((e) => e.entityId === options.entityId);\n }\n\n const total = entries.length;\n const offset = options?.offset ?? 0;\n const limit = options?.limit ?? 50;\n entries = entries.slice(offset, offset + limit);\n\n return { entries, total };\n }\n\n /** Rotate log file if it exceeds MAX_FILE_SIZE */\n private async rotateIfNeeded(): Promise<void> {\n const filepath = this.getFilePath();\n try {\n const stats = await stat(filepath);\n if (stats.size > MAX_FILE_SIZE) {\n await rename(filepath, this.getRotatedPath());\n }\n } catch {\n // File doesn't exist, nothing to rotate\n }\n }\n\n /** Clean up old rotated logs (older than MAX_AGE_DAYS) */\n async cleanup(): Promise<void> {\n const files = await readdir(env.DATA_DIR);\n const cutoff = Date.now() - MAX_AGE_DAYS * 24 * 60 * 60 * 1000;\n\n for (const file of files) {\n if (file.startsWith('audit.log.') && file.endsWith('.bak')) {\n const tsStr = file.replace('audit.log.', '').replace('.bak', '');\n const ts = parseInt(tsStr, 10);\n if (!isNaN(ts) && ts < cutoff) {\n try {\n await unlink(join(env.DATA_DIR, file));\n } catch {\n // Ignore\n }\n }\n }\n }\n }\n}\n\nexport const auditService = new AuditService();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { HealthCheckSchema, RestartStrategySchema } from '@runeya/packages-shared';\nimport type { ProcessStatus } from '@runeya/packages-shared';\nimport { router, protectedProcedure, requireServiceAction, getAllowedServiceIds } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { settingsManager } from '../../services/settings-manager.js';\nimport { nativeParsers } from '@runeya/packages-shared';\nimport { ServiceShortcutSchema, ServiceCommandSchema, DockerConfigSchema, LogSourceConfigSchema, AGENT_STOP_FETCH_TIMEOUT } from '@runeya/packages-shared';\nimport type { ServiceConfig } from '@runeya/packages-shared';\nimport { env } from '../../config/env.js';\n\n/**\n * Resolve the effective agentId for a service.\n * Priority: service.agentId (explicit override) → activeEnvironment.agentId → null\n */\nexport async function resolveEffectiveAgentId(service: ServiceConfig): Promise<string | null> {\n if (service.agentId) return service.agentId;\n const projects = await projectStore.list();\n const project = projects.find(p => p.serviceIds.includes(service.id));\n if (!project?.activeEnvironmentId) return null;\n const activeEnv = await environmentStore.get(project.activeEnvironmentId);\n return activeEnv?.agentId ?? null;\n}\n\n/**\n * Helper to resolve service variables to env dict before deployment.\n * Finds the project containing this service and uses its activeEnvironmentId.\n * Also resolves parserIds to full parser definitions.\n */\nexport async function resolveServiceVariables(service: ServiceConfig): Promise<ServiceConfig> {\n // Find the project containing this service\n const projects = await projectStore.list();\n const project = projects.find(p => p.serviceIds.includes(service.id));\n\n let resolvedService: ServiceConfig = service;\n\n // Resolve parser IDs to full parser definitions (always, regardless of environment)\n try {\n if (service.parserIds && service.parserIds.length > 0) {\n const settings = await settingsManager.getSettings();\n const allParsers = [...nativeParsers, ...(settings.logParsers || [])];\n const resolvedParsers = service.parserIds\n .map(id => allParsers.find(p => p.id === id))\n .filter((p) => p !== undefined);\n resolvedService = { ...resolvedService, resolvedLogParsers: resolvedParsers };\n }\n } catch (err) {\n console.error('[service-router] Failed to resolve parsers for service', service.id + ':', (err as Error).message);\n }\n\n if (!project || !project.activeEnvironmentId) {\n // No project or no active environment — nothing more to resolve\n return resolvedService;\n }\n\n // Resolve variables to env dict\n try {\n const resolved = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: project.activeEnvironmentId,\n });\n\n // Populate transient env/envSecrets on service config for agent consumption\n const serviceBuiltins: Record<string, string> = {\n HOST: env.HOST,\n HOST_LAN: '0.0.0.0',\n };\n\n // Interpolate {{service.KEY}} placeholders left untouched by the environment resolver\n const interpolatedEnv: Record<string, string> = {};\n for (const [key, value] of Object.entries(resolved.env)) {\n interpolatedEnv[key] = value.replace(/\\{\\{service\\.([^}]+)\\}\\}/g, (match, k) =>\n serviceBuiltins[k] !== undefined ? serviceBuiltins[k] : match,\n );\n }\n\n resolvedService = {\n ...resolvedService,\n env: interpolatedEnv,\n envSecrets: [...resolved.envSecrets],\n };\n } catch (err) {\n console.error('[service-router] Failed to resolve variables for service', service.id + ':', (err as Error).message);\n }\n\n return resolvedService;\n}\n\n\nconst DockerConfigInput = DockerConfigSchema;\n\nexport const serviceRouter = router({\n list: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/services', tags: ['services'], summary: 'List all services', protect: true } })\n .output(z.any())\n .query(async ({ ctx }) => {\n const all = await serviceStore.list();\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n const filtered = allowedIds ? all.filter(s => allowedIds.has(s.id)) : all;\n return Promise.all(filtered.map(async (s) => ({\n ...s,\n effectiveAgentId: await resolveEffectiveAgentId(s),\n })));\n }),\n\n get: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/services/{id}', tags: ['services'], summary: 'Get a service by ID', protect: true } })\n .input(z.object({ id: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.id, 'service:read');\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n return service;\n }),\n\n create: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/services', tags: ['services'], summary: 'Create a new service', protect: true } })\n .output(z.any())\n .input(\n z.object({\n agentId: z.string().max(128).optional(),\n name: z.string().min(1).max(200),\n commands: z.array(ServiceCommandSchema).max(50).optional(),\n cwd: z.string().max(4096).optional(),\n ports: z.array(z.number().int().min(1).max(65535)).max(20).optional(),\n groups: z.array(z.string().max(200)).max(20).optional(),\n description: z.string().max(2000).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional(),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n runner: z.enum(['native', 'docker']).optional().default('native'),\n dockerConfig: DockerConfigInput.optional(),\n healthCheck: HealthCheckSchema.optional(),\n autoRestart: z.boolean().optional().default(false),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional().default(1000),\n orgId: z.string().max(128).nullable().optional(),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional(),\n parserIds: z.array(z.string().max(128)).max(50).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n // Validate agent exists (only if explicitly provided)\n if (input.agentId) {\n const status = agentManager.getStatus(input.agentId);\n if (!status) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: `Agent ${input.agentId} not found`\n });\n }\n }\n\n if (input.runner === 'docker') {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Docker runner is not yet supported. Use \"native\" runner.' });\n }\n const service = await serviceStore.create({\n ...input,\n agentId: input.agentId,\n });\n await auditService.log({ userId: 'local', action: 'create', entityType: 'service', entityId: service.id, metadata: { name: input.name } });\n return service;\n }),\n\n update: protectedProcedure\n .meta({ openapi: { method: 'PATCH', path: '/services/{id}', tags: ['services'], summary: 'Update a service', protect: true } })\n .output(z.any())\n .input(\n z.object({\n id: z.string().max(128),\n agentId: z.string().max(128).nullable().optional(), // null = clear (inherit from env)\n name: z.string().min(1).max(200).optional(),\n commands: z.array(ServiceCommandSchema).max(50).optional(),\n cwd: z.string().max(4096).nullable().optional(),\n ports: z.array(z.number().int().min(1).max(65535)).max(20).optional(),\n groups: z.array(z.string().max(200)).max(20).optional(),\n description: z.string().max(2000).optional(),\n url: z.string().max(2048).optional(),\n localUrls: z.array(z.object({\n url: z.string().max(253),\n port: z.number().int().min(1).max(65535),\n })).max(20).optional(),\n openapiUrl: z.string().max(2048).optional(),\n git: z.object({ remote: z.string().max(2048).optional(), home: z.string().max(2048).optional() }).nullable().optional(),\n meta: z.record(z.string().max(256), z.string().max(2000)).nullable().optional()\n .refine((obj) => !obj || Object.keys(obj).length <= 100, { message: 'Too many meta keys (max 100)' }),\n runner: z.enum(['native', 'docker']).optional(),\n dockerConfig: DockerConfigInput.optional(),\n healthCheck: HealthCheckSchema.nullable().optional(),\n autoRestart: z.boolean().optional(),\n clearLogsOnStart: z.boolean().optional(),\n restartStrategy: RestartStrategySchema.optional(),\n maxRestarts: z.number().int().nonnegative().optional(),\n restartBackoffMs: z.number().int().positive().optional(),\n orgId: z.string().max(128).nullable().optional(),\n shortcuts: z.array(ServiceShortcutSchema).max(50).optional(),\n parserIds: z.array(z.string().max(128)).max(50).optional(),\n logSources: z.array(LogSourceConfigSchema).max(20).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n const existing = await serviceStore.get(input.id);\n if (!existing) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n\n // If changing agentId (including clearing it), stop the service on the old agent if running\n let stoppedForAgentChange = false;\n if (input.agentId !== undefined && input.agentId !== existing.agentId && existing.agentId) {\n const oldAgentStatus = agentManager.getStatus(existing.agentId);\n if (oldAgentStatus?.connected) {\n try {\n const processes = await agentManager.agentQuery<ProcessStatus[]>(existing.agentId, 'process.list');\n const proc = processes.find((p) => p.serviceId === input.id);\n if (proc && (proc.state === 'running' || proc.state === 'starting')) {\n await agentManager.agentMutation(existing.agentId, 'process.stop', { id: input.id }, AGENT_STOP_FETCH_TIMEOUT);\n stoppedForAgentChange = true;\n }\n } catch {\n // Agent unreachable or stop failed — allow the config change anyway\n }\n }\n\n // Validate new agent exists (only when setting a non-null agentId)\n if (input.agentId) {\n const newAgentStatus = agentManager.getStatus(input.agentId);\n if (!newAgentStatus) {\n throw new TRPCError({\n code: 'NOT_FOUND',\n message: `Agent ${input.agentId} not found`\n });\n }\n }\n }\n\n const service = await serviceStore.update(input);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n\n // If service was renamed, cascade to service-scoped environment names\n if (input.name && input.name !== existing.name) {\n await environmentStore.renameByReference(input.id, input.name);\n }\n\n // Propagate config to assigned agent (only if service has an explicit agentId)\n if (service.agentId) {\n const agentStatus = agentManager.getStatus(service.agentId);\n if (agentStatus?.connected) {\n try {\n const resolvedService = await resolveServiceVariables(service);\n await agentManager.agentMutation(service.agentId, 'process.updateConfig', {\n serviceId: service.id,\n config: resolvedService,\n });\n } catch (err) {\n console.debug('[service-router] Failed to propagate config to agent', service.agentId + ':', (err as Error).message);\n }\n }\n }\n\n await auditService.log({ userId: 'local', action: 'update', entityType: 'service', entityId: input.id });\n return { ...service, effectiveAgentId: await resolveEffectiveAgentId(service), stoppedForAgentChange };\n }),\n\n delete: protectedProcedure\n .meta({ openapi: { method: 'DELETE', path: '/services/{id}', tags: ['services'], summary: 'Delete a service', protect: true } })\n .input(z.object({ id: z.string().max(128) }))\n .output(z.object({ success: z.literal(true) }))\n .mutation(async ({ input }) => {\n const deleted = await serviceStore.delete(input.id);\n if (!deleted) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n await auditService.log({ userId: 'local', action: 'delete', entityType: 'service', entityId: input.id });\n return { success: true as const };\n }),\n\n checkCwd: protectedProcedure\n .input(z.object({ id: z.string().max(128), checkReachability: z.boolean().optional() }))\n .query(async ({ input }) => {\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n const effectiveAgentId = await resolveEffectiveAgentId(service);\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n\n // Delegate entirely to the agent — it resolves $VAR from its own process.env\n const agentResult = await agentManager.agentQuery<{\n exists: boolean;\n actualRemote: string | null;\n unreachable: boolean;\n resolvedCwd: string;\n unresolvedVars: string[];\n }>(effectiveAgentId, 'git.checkCwd', {\n cwd: service.cwd || '.',\n remote: service.git?.remote,\n checkReachability: input.checkReachability,\n });\n\n const { exists, actualRemote, unreachable, resolvedCwd, unresolvedVars } = agentResult;\n\n if (unresolvedVars.length > 0) {\n return { exists: false, canClone: false, unresolvedVars, resolvedCwd, gitMismatch: null };\n }\n\n const canClone = !!service.git?.remote && (!exists || actualRemote === null);\n\n let gitMismatch: { actual: string | null; configured: string; unreachable?: boolean } | null = null;\n if (exists && service.git?.remote && !canClone) {\n if (actualRemote === null) {\n gitMismatch = { actual: null, configured: service.git.remote };\n } else if (actualRemote !== service.git.remote) {\n gitMismatch = { actual: actualRemote, configured: service.git.remote };\n } else if (unreachable) {\n gitMismatch = { actual: actualRemote, configured: service.git.remote, unreachable: true };\n }\n }\n\n return { exists, canClone, unresolvedVars: [], resolvedCwd, gitMismatch };\n }),\n\n cloneRepository: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const service = await serviceStore.get(input.id);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Service ${input.id} not found` });\n }\n if (!service.git?.remote) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Service has no git remote configured' });\n }\n const effectiveAgentId = await resolveEffectiveAgentId(service);\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n\n // Delegate entirely to the agent — it resolves $VAR from its own process.env\n await agentManager.agentMutation(effectiveAgentId, 'git.clone', {\n remote: service.git.remote,\n cwd: service.cwd || '.',\n }, 5 * 60 * 1000);\n\n return { success: true as const };\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\nimport { SettingsSchema, SchemaVersionSchema, SettingsPrivateSchema } from '@runeya/packages-shared';\nimport type { Settings, SchemaVersion, SettingsPrivate } from '@runeya/packages-shared';\n\nconst SETTINGS_FILE = 'settings.json';\nconst SETTINGS_PRIVATE_FILE = 'settings.private.json';\nconst SCHEMA_VERSION_FILE = 'schema-version.json';\nconst CURRENT_SCHEMA_VERSION = 4;\n\nclass SettingsManager {\n private settings: Settings | null = null;\n private settingsPrivate: SettingsPrivate | null = null;\n private schemaVersion: SchemaVersion | null = null;\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private async atomicWrite(filename: string, data: unknown): Promise<void> {\n await this.ensureDir();\n const filePath = join(env.DATA_DIR, filename);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n private async readJson<T>(filename: string): Promise<T | null> {\n try {\n const raw = await readFile(join(env.DATA_DIR, filename), 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n }\n\n async getSettings(): Promise<Settings> {\n if (!this.settings) {\n const raw = await this.readJson<unknown>(SETTINGS_FILE);\n const parsed = raw ? SettingsSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.settings = parsed.data;\n } else {\n this.settings = SettingsSchema.parse({ mode: env.MODE, cloudUrl: env.CLOUD_URL ?? null });\n await this.saveSettings(this.settings);\n }\n }\n return this.settings;\n }\n\n async saveSettings(settings: Settings): Promise<void> {\n this.settings = settings;\n await this.atomicWrite(SETTINGS_FILE, settings);\n }\n\n async getPrivateSettings(): Promise<SettingsPrivate> {\n if (!this.settingsPrivate) {\n const raw = await this.readJson<unknown>(SETTINGS_PRIVATE_FILE);\n const parsed = raw ? SettingsPrivateSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.settingsPrivate = parsed.data;\n } else {\n this.settingsPrivate = SettingsPrivateSchema.parse({});\n await this.savePrivateSettings(this.settingsPrivate);\n }\n }\n return this.settingsPrivate;\n }\n\n async savePrivateSettings(settings: SettingsPrivate): Promise<void> {\n this.settingsPrivate = settings;\n await this.atomicWrite(SETTINGS_PRIVATE_FILE, settings);\n }\n\n async getSchemaVersion(): Promise<SchemaVersion> {\n if (!this.schemaVersion) {\n const raw = await this.readJson<unknown>(SCHEMA_VERSION_FILE);\n const parsed = raw ? SchemaVersionSchema.safeParse(raw) : null;\n if (parsed?.success) {\n this.schemaVersion = parsed.data;\n } else {\n this.schemaVersion = { version: CURRENT_SCHEMA_VERSION, migratedAt: new Date() };\n await this.saveSchemaVersion(this.schemaVersion);\n }\n }\n return this.schemaVersion;\n }\n\n async saveSchemaVersion(sv: SchemaVersion): Promise<void> {\n this.schemaVersion = sv;\n await this.atomicWrite(SCHEMA_VERSION_FILE, sv);\n }\n\n getCurrentSchemaVersion(): number {\n return CURRENT_SCHEMA_VERSION;\n }\n}\n\nexport const settingsManager = new SettingsManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { LOG_BUFFER_SIZE } from '@runeya/packages-shared';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport type { AgentStatus } from '@runeya/packages-shared';\n\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\nexport const agentRouter = router({\n /** List all registered agents with their connection status */\n list: protectedProcedure.query(() => {\n return agentManager.listAgents();\n }),\n\n /** Get a single agent's config and status */\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(({ input }) => {\n const agent = agentManager.getAgent(input.id);\n if (!agent) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.id} not found` });\n }\n return {\n config: { ...agent.config, passphrase: '***' },\n status: agent.status,\n };\n }),\n\n /** Test connectivity to an agent given url + passphrase */\n testConnection: protectedProcedure\n .input(\n z.object({\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024).optional(),\n agentId: z.string().max(128).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n let passphrase = input.passphrase;\n let targetUrl = input.url;\n if (!passphrase && input.agentId) {\n const agent = agentManager.getAgentConfig(input.agentId);\n if (!agent) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Agent not found' });\n }\n passphrase = agent.passphrase;\n // SECURITY: When using a stored passphrase, always use the stored agent URL\n // to prevent exfiltration of the passphrase to an attacker-controlled URL\n targetUrl = agent.url;\n }\n if (!passphrase) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Passphrase is required' });\n }\n\n const url = new URL('/api/trpc/health.check', targetUrl);\n try {\n const res = await fetch(url.toString(), {\n headers: { 'Authorization': `Bearer ${passphrase}`, 'Content-Type': 'application/json' },\n signal: AbortSignal.timeout(5000),\n });\n if (!res.ok) {\n return { success: false as const, error: `HTTP ${res.status} ${res.statusText}` };\n }\n const json = await res.json() as { error?: { message?: string }; result?: { data?: { uptime?: number } } };\n if (json.error) {\n return { success: false as const, error: json.error.message ?? 'Agent returned an error' };\n }\n return { success: true as const, uptime: json.result?.data?.uptime };\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Unknown error';\n return { success: false as const, error: msg };\n }\n }),\n\n /** Register a new agent */\n register: protectedProcedure\n .input(\n z.object({\n name: z.string().min(1).max(100),\n url: z.string().url().max(2048),\n passphrase: z.string().min(1).max(1024),\n }),\n )\n .mutation(async ({ input }) => {\n const config = await agentManager.register(input.name, input.url, input.passphrase);\n return { ...config, passphrase: '***' };\n }),\n\n /** Update an existing agent */\n update: protectedProcedure\n .input(\n z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(100).optional(),\n url: z.string().url().max(2048).optional(),\n passphrase: z.string().min(1).max(1024).optional(),\n passthroughEnv: z.array(\n z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(256),\n ).max(100).optional(),\n }),\n )\n .mutation(async ({ input }) => {\n try {\n const { id, ...fields } = input;\n const config = await agentManager.update(id, fields);\n return { ...config, passphrase: '***' };\n } catch (err) {\n if (err instanceof Error) {\n if (err.message.includes('not found')) {\n throw new TRPCError({ code: 'NOT_FOUND', message: err.message });\n }\n if (err.message.includes('Cannot modify')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: err.message });\n }\n }\n throw err;\n }\n }),\n\n /** Get resolved passthrough env values from an agent */\n getPassthroughEnv: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n try {\n return await agentManager.agentQuery<Record<string, string>>(input.id, 'config.getPassthroughEnv');\n } catch {\n return {};\n }\n }),\n\n /** Remove a registered agent */\n remove: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n try {\n const removed = await agentManager.remove(input.id);\n if (!removed) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.id} not found` });\n }\n return { success: true as const };\n } catch (err) {\n if (err instanceof Error && err.message === 'Cannot remove the local agent') {\n throw new TRPCError({ code: 'FORBIDDEN', message: err.message });\n }\n throw err;\n }\n }),\n\n /** Subscribe to real-time agent status changes */\n onStatus: protectedProcedure.subscription(async function* () {\n // Yield current state of all agents immediately so the client\n // doesn't have to wait for the next health tick.\n for (const agent of agentManager.listAgents()) {\n yield { agentId: agent.config.id, status: agent.status };\n }\n\n const queue: Array<{ agentId: string; status: AgentStatus }> = [];\n let resolve: (() => void) | null = null;\n\n const handler = (event: { agentId: string; status: AgentStatus }) => {\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(event);\n if (resolve) {\n resolve();\n resolve = null;\n }\n };\n\n agentManager.on('status', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off('status', handler);\n }\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { LOG_BUFFER_SIZE, ServiceShortcutSchema, AGENT_LONG_FETCH_TIMEOUT, AGENT_STOP_FETCH_TIMEOUT } from '@runeya/packages-shared';\nimport type { ProcessStatus, ProcessMetrics } from '@runeya/packages-shared';\nimport { router, protectedProcedure, requireServiceAction, getAllowedServiceIds } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { auditService } from '../../services/audit-service.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { resolveServiceVariables, resolveEffectiveAgentId } from './service.js';\n\n/** Max items in a subscription queue before dropping oldest */\nconst SUBSCRIPTION_QUEUE_MAX = LOG_BUFFER_SIZE;\n\n/**\n * Helper that creates a queued async generator forwarding events from agentManager.\n * Deduplicates the queue+handler pattern used by all process subscriptions.\n */\nasync function* forwardEvents<T = Record<string, unknown>>(\n eventName: string,\n filter?: (data: Record<string, unknown>) => boolean,\n): AsyncGenerator<T> {\n const queue: T[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (data: Record<string, unknown>) => {\n if (filter && !filter(data)) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(data as T);\n if (resolve) { resolve(); resolve = null; }\n };\n\n agentManager.on(eventName, handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off(eventName, handler);\n }\n}\n\n/**\n * Helper for log batch forwarding. The AgentWSBridge wraps array data as\n * `{ batch: ParsedLog[], agentId }`. We filter by agentId + processId,\n * then yield the filtered batch to the frontend.\n */\nasync function* forwardLogBatches(\n agentId: string,\n processId: string,\n): AsyncGenerator<unknown[]> {\n const queue: unknown[][] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (data: Record<string, unknown>) => {\n if (data.agentId !== agentId) return;\n const batch = data.batch as Array<Record<string, unknown>>;\n if (!Array.isArray(batch)) return;\n const filtered = batch.filter((log) => log.processId === processId);\n if (filtered.length === 0) return;\n if (queue.length >= SUBSCRIPTION_QUEUE_MAX) queue.shift();\n queue.push(filtered);\n if (resolve) { resolve(); resolve = null; }\n };\n\n agentManager.on('process:log', handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n agentManager.off('process:log', handler);\n }\n}\n\nexport const processRouter = router({\n /** List all processes across all connected agents */\n list: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes', tags: ['processes'], summary: 'List all processes', protect: true } })\n .output(z.any())\n .query(async () => {\n const agents = agentManager.listAgents();\n const results: Array<ProcessStatus & { agentId: string }> = [];\n\n await Promise.allSettled(\n agents\n .filter(a => a.status.connected)\n .map(async (a) => {\n try {\n const processes = await agentManager.agentQuery<ProcessStatus[]>(a.config.id, 'process.list');\n for (const proc of processes) {\n results.push({ ...proc, agentId: a.config.id });\n }\n } catch {\n // Agent unreachable, skip\n }\n }),\n );\n\n return results;\n }),\n\n\n /** Get a single process from a specific agent */\n get: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes/{agentId}/{id}', tags: ['processes'], summary: 'Get a process by agent and ID', protect: true } })\n .input(z.object({ agentId: z.string().max(128), id: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.id, 'service:read');\n const status = agentManager.getStatus(input.agentId);\n if (!status) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Agent ${input.agentId} not found` });\n }\n\n const proc = await agentManager.agentQuery<ProcessStatus>(input.agentId, 'process.get', { id: input.id });\n return { ...proc, agentId: input.agentId };\n }),\n\n\n /** Start a process on an agent.\n * Lazy deploy: the agent only learns about a service when it is first started\n * (or restarted). This avoids pushing configs for every service at agent boot,\n * which would be wasteful when many services are never started.\n * The deploy call is idempotent — creates the process if missing, updates config if it exists. */\n start: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/start', tags: ['processes'], summary: 'Start a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128).optional(), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:start');\n const service = await serviceStore.get(input.processId);\n\n // Resolve effective agentId: service.agentId > environment.agentId > explicit input (fallback)\n // Service/environment config always wins so that changing the agent takes effect immediately.\n const effectiveAgentId = (service ? await resolveEffectiveAgentId(service) : null) ?? input.agentId ?? null;\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent assigned to this service. Set an agent on the service or on the active environment.' });\n }\n\n // Always deploy first (idempotent — creates process if missing, updates config if exists)\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(effectiveAgentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before start for', input.processId + ':', (err as Error).message);\n }\n }\n\n if (service?.clearLogsOnStart) {\n try {\n await agentManager.agentMutation(effectiveAgentId, 'process.clearLogBuffer', { id: input.processId });\n agentManager.emit('process:log', { agentId: effectiveAgentId, batch: [{ processId: input.processId, __clearLogBuffer: true }] });\n } catch (err) {\n console.debug('[process-router] Failed to clear logs before start for', input.processId + ':', (err as Error).message);\n }\n }\n\n let result: ProcessStatus;\n try {\n result = await agentManager.agentMutation<ProcessStatus>(effectiveAgentId, 'process.start', { id: input.processId });\n } catch (err: unknown) {\n const err_ = err as { cause?: { code?: string }; message?: string; name?: string };\n const isFetchError = err_?.cause?.code === 'ECONNREFUSED' || err_?.message === 'fetch failed' || err_?.name === 'TypeError';\n throw new TRPCError({\n code: 'INTERNAL_SERVER_ERROR',\n message: isFetchError\n ? `Cannot reach agent — make sure the agent is running`\n : (err_?.message ?? 'Failed to start process'),\n });\n }\n await auditService.log({ userId: 'local', action: 'start', entityType: 'process', entityId: input.processId, metadata: { agentId: effectiveAgentId } });\n return { ...result, agentId: effectiveAgentId };\n }),\n\n /** Stop a process on an agent */\n stop: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/stop', tags: ['processes'], summary: 'Stop a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:stop');\n const result = await agentManager.agentMutation<ProcessStatus>(input.agentId, 'process.stop', { id: input.processId }, AGENT_STOP_FETCH_TIMEOUT);\n await auditService.log({ userId: 'local', action: 'stop', entityType: 'process', entityId: input.processId, metadata: { agentId: input.agentId } });\n return { ...result, agentId: input.agentId };\n }),\n\n /** Restart a process on an agent.\n * Sends stop → deploy (latest resolved config) → start so that\n * config/variable changes take effect. Same lazy deploy pattern as start. */\n restart: protectedProcedure\n .meta({ openapi: { method: 'POST', path: '/processes/{agentId}/{processId}/restart', tags: ['processes'], summary: 'Restart a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128).optional(), processId: z.string().max(128) }))\n .output(z.any())\n .mutation(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'service:restart');\n const service = await serviceStore.get(input.processId);\n\n // Resolve effective agentId: service.agentId > environment.agentId > explicit input (fallback)\n // Service/environment config always wins so that changing the agent takes effect immediately.\n const effectiveAgentId = (service ? await resolveEffectiveAgentId(service) : null) ?? input.agentId ?? null;\n if (!effectiveAgentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent assigned to this service. Set an agent on the service or on the active environment.' });\n }\n\n // 1. Stop the process (ignore \"not found\" — process may not exist on this agent yet)\n try {\n await agentManager.agentMutation<{ success: true }>(effectiveAgentId, 'process.stop', { id: input.processId }, AGENT_STOP_FETCH_TIMEOUT);\n } catch (err) {\n console.debug('[process-router] Stop before restart ignored (process not found on agent?):', (err as Error).message);\n }\n\n // 2. Re-deploy with latest config (idempotent — updates config now that process is stopped)\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(effectiveAgentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before restart for', input.processId + ':', (err as Error).message);\n }\n }\n\n // 3. Clear logs if configured\n if (service?.clearLogsOnStart) {\n try {\n await agentManager.agentMutation(effectiveAgentId, 'process.clearLogBuffer', { id: input.processId });\n agentManager.emit('process:log', { agentId: effectiveAgentId, batch: [{ processId: input.processId, __clearLogBuffer: true }] });\n } catch (err) {\n console.debug('[process-router] Failed to clear logs before restart for', input.processId + ':', (err as Error).message);\n }\n }\n\n // 4. Start with updated config\n const result = await agentManager.agentMutation<ProcessStatus>(effectiveAgentId, 'process.start', { id: input.processId });\n await auditService.log({ userId: 'local', action: 'restart', entityType: 'process', entityId: input.processId, metadata: { agentId: effectiveAgentId } });\n return { ...result, agentId: effectiveAgentId };\n }),\n\n /** Get buffered logs for a process from an agent */\n logs: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/processes/{agentId}/{processId}/logs', tags: ['processes'], summary: 'Get buffered logs for a process', protect: true } })\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .output(z.any())\n .query(async ({ input, ctx }) => {\n requireServiceAction(ctx as AuthContext, input.processId, 'logs:read');\n return agentManager.agentQuery(input.agentId, 'process.logs', { id: input.processId });\n }),\n\n /** Clear buffered logs for a process on an agent */\n clearLogBuffer: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.clearLogBuffer', { id: input.processId });\n await auditService.log({ userId: 'local', action: 'clearLogBuffer', entityType: 'process', entityId: input.processId, metadata: { agentId: input.agentId } });\n return { success: true };\n }),\n\n /** Execute a shortcut command on an agent, streaming output into the process log */\n executeShortcut: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n shortcut: ServiceShortcutSchema,\n }))\n .mutation(async ({ input }) => {\n // Lazy deploy: ensure the agent knows about this service (same pattern as start/restart)\n const service = await serviceStore.get(input.processId);\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(input.agentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before executeShortcut for', input.processId + ':', (err as Error).message);\n }\n }\n\n const result = await agentManager.agentMutation<{ exitCode: number | null }>(\n input.agentId, 'process.executeShortcut',\n { id: input.processId, shortcut: input.shortcut },\n AGENT_LONG_FETCH_TIMEOUT,\n );\n await auditService.log({\n userId: 'local',\n action: 'executeShortcut',\n entityType: 'process',\n entityId: input.processId,\n metadata: { agentId: input.agentId, shortcutId: input.shortcut.id, shortcutLabel: input.shortcut.label },\n });\n return result;\n }),\n\n /** Execute an ad-hoc command on an agent, streaming output into the process log */\n executeAdHocCommand: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n command: z.string().min(1).max(4096),\n cwd: z.string().max(4096).optional(),\n }))\n .mutation(async ({ input }) => {\n // Lazy deploy: ensure the agent knows about this service (same pattern as start/restart)\n const service = await serviceStore.get(input.processId);\n if (service) {\n try {\n const resolved = await resolveServiceVariables(service);\n await agentManager.agentMutation(input.agentId, 'process.deploy', resolved);\n } catch (err) {\n console.debug('[process-router] Failed to deploy before executeAdHocCommand for', input.processId + ':', (err as Error).message);\n }\n }\n\n const result = await agentManager.agentMutation<{ exitCode: number | null }>(\n input.agentId, 'process.executeAdHocCommand',\n { id: input.processId, command: input.command, cwd: input.cwd },\n AGENT_LONG_FETCH_TIMEOUT,\n );\n await auditService.log({\n userId: 'local',\n action: 'executeAdHocCommand',\n entityType: 'process',\n entityId: input.processId,\n metadata: { agentId: input.agentId, command: input.command },\n });\n return result;\n }),\n\n /** Cancel a running shortcut command on an agent */\n cancelShortcut: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n shortcutId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.cancelShortcut', { id: input.processId, shortcutId: input.shortcutId });\n return { success: true };\n }),\n\n /** Cancel a running ad-hoc command on an agent */\n cancelAdHocCommand: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n processId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(input.agentId, 'process.cancelAdHocCommand', { id: input.processId });\n return { success: true };\n }),\n\n /** Get current metrics for a process from an agent */\n metrics: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<ProcessMetrics>(input.agentId, 'process.metrics', { id: input.processId });\n }),\n\n /**\n * Subscribe to real-time log stream for a process.\n * Forwards batched events from the AgentWSBridge in real-time.\n * Historical logs are fetched separately via process.logs query.\n */\n onLog: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), processId: z.string().max(128) }))\n .subscription(async function* ({ input, ctx }) {\n requireServiceAction(ctx as AuthContext, input.processId, 'logs:read');\n yield* forwardLogBatches(input.agentId, input.processId);\n }),\n\n /**\n * Subscribe to real-time status changes for processes.\n * Input is optional — omit agentId/processId for global monitoring (dashboard).\n * Forwards events from the AgentWSBridge in real-time.\n */\n onStatus: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:status');\n\n // Yield initial state\n try {\n const agents = agentManager.listAgents();\n for (const agent of agents.filter(a => a.status.connected)) {\n if (input?.agentId && agent.config.id !== input.agentId) continue;\n try {\n const processes = await agentManager.agentQuery<any[]>(agent.config.id, 'process.list');\n for (const proc of processes) {\n if (input?.processId && proc.id !== input.processId) continue;\n if (allowedIds && !allowedIds.has(proc.id)) continue;\n yield { ...proc, agentId: agent.config.id };\n }\n } catch {\n // Agent unreachable, skip\n }\n }\n } catch {\n // Ignore errors during initial load\n }\n\n yield* forwardEvents('process:status', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n\n /** Subscribe to real-time metrics for a process. */\n onMetrics: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:status');\n\n yield* forwardEvents<ProcessMetrics>('process:metrics', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n\n /** Subscribe to real-time health status changes. */\n onHealth: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128).optional(),\n processId: z.string().max(128).optional(),\n }).optional())\n .subscription(async function* ({ input, ctx }) {\n const allowedIds = getAllowedServiceIds(ctx as AuthContext);\n if (input?.processId) requireServiceAction(ctx as AuthContext, input.processId, 'service:healthcheck');\n\n yield* forwardEvents('process:health', (d) => {\n if (input?.agentId && d.agentId !== input.agentId) return false;\n if (input?.processId && d.processId !== input.processId) return false;\n if (allowedIds && !allowedIds.has(d.processId as string)) return false;\n return true;\n });\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { auditService } from '../../services/audit-service.js';\n\nexport const auditRouter = router({\n list: protectedProcedure\n .input(z.object({\n action: z.string().max(50).optional(),\n entityType: z.string().max(50).optional(),\n entityId: z.string().max(100).optional(),\n limit: z.number().int().positive().max(100).default(50),\n offset: z.number().int().nonnegative().default(0),\n }).optional())\n .query(async ({ input }) => {\n return auditService.list(input ?? {});\n }),\n});\n","import { z } from 'zod';\nimport { router, publicProcedure, protectedProcedure } from '../trpc.js';\nimport { hasEncryptionKey, setEncryptionKey, getEncryptionKey } from '../../utils/encryption-key.js';\nimport { agentStore } from '../../services/agent-store.js';\nimport { agentSpawner } from '../../services/agent-spawner.js';\nimport { env } from '../../config/env.js';\n\nexport const setupRouter = router({\n /**\n * Check if encryption key is required (project initialized but no key).\n */\n needsEncryptionKey: publicProcedure.query(async () => {\n return {\n needsKey: !hasEncryptionKey(),\n };\n }),\n\n /**\n * Get current encryption key in hex format (for sharing with team).\n * Only available in local-simple mode for security.\n */\n getEncryptionKeyHex: protectedProcedure.query(async () => {\n if (env.MODE !== 'local-simple') {\n throw new Error('Encryption key export only available in local-simple mode');\n }\n\n const key = getEncryptionKey();\n if (!key) {\n throw new Error('No encryption key loaded');\n }\n\n return {\n keyHex: key.toString('hex'),\n };\n }),\n\n /**\n * Submit and validate encryption key.\n * Attempts to decrypt existing data to validate the key.\n * Spawns the local agent if in local-simple mode.\n */\n submitEncryptionKey: publicProcedure\n .input(\n z.object({\n keyHex: z.string().length(64).regex(/^[0-9a-f]+$/i, 'Invalid hex format'),\n }),\n )\n .mutation(async ({ input }) => {\n try {\n // Set the key\n await setEncryptionKey(input.keyHex);\n\n // Validate by attempting to read encrypted data\n // If agents.json exists with encrypted data, this will decrypt it\n await agentStore.list();\n\n // Spawn the local agent now that the encryption key is available\n // (in local-simple mode, the agent couldn't spawn during server startup\n // because the key wasn't available yet)\n if (env.MODE === 'local-simple') {\n console.log('[setup] Encryption key validated, spawning local agent...');\n await agentSpawner.spawnLocalAgent();\n }\n\n return { success: true };\n } catch (err: unknown) {\n // If decryption fails, the key is invalid\n const message = err instanceof Error ? err.message : 'Unknown error';\n throw new Error(`Invalid encryption key: ${message}`);\n }\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { protectedProcedure, router, requireEnvAction } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport { environmentStore } from '../../services/environment-store.js';\nimport { environmentOverridesStore } from '../../services/environment-overrides-store.js';\nimport { environmentResolver } from '../../services/environment-resolver.js';\nimport { projectStore } from '../../services/project-store.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { CreateEnvironmentSchema, UpdateEnvironmentSchema, VariableSchema } from '@runeya/packages-shared';\n\nexport const environmentRouter = router({\n list: protectedProcedure\n .input(z.object({ projectId: z.string().max(128) }))\n .query(async ({ input }) => {\n return await environmentStore.list(input.projectId);\n }),\n\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const env = await environmentStore.get(input.id);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n return env;\n }),\n\n listByScope: protectedProcedure\n .input(z.object({ projectId: z.string().max(128), scope: z.enum(['global', 'service']) }))\n .query(async ({ input }) => {\n return await environmentStore.listByScope(input.projectId, input.scope);\n }),\n\n findServiceEnvironment: protectedProcedure\n .input(z.object({ serviceId: z.string().max(128), globalEnvId: z.string().max(128) }))\n .query(async ({ input }) => {\n return await environmentStore.findServiceEnvironment(input.serviceId, input.globalEnvId);\n }),\n\n create: protectedProcedure\n .input(CreateEnvironmentSchema)\n .mutation(async ({ input }) => {\n const env = await environmentStore.create(input);\n\n // Add environment to project's environmentIds list\n const project = await projectStore.get(input.projectId);\n if (project && !project.environmentIds?.includes(env.id)) {\n await projectStore.addEnvironment(input.projectId, env.id);\n }\n\n // If creating a global env, auto-create service-scoped envs for each service in the project\n if (env.scope === 'global' && project) {\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (!service) continue;\n const svcEnv = await environmentStore.create({\n projectId: input.projectId,\n name: `${service.name} (${env.name})`,\n scope: 'service',\n reference: serviceId,\n activateOn: env.id,\n parentIds: [env.id],\n variables: {},\n });\n await projectStore.addEnvironment(input.projectId, svcEnv.id);\n }\n }\n\n return env;\n }),\n\n update: protectedProcedure\n .input(UpdateEnvironmentSchema)\n .mutation(async ({ input }) => {\n const existing = await environmentStore.get(input.id);\n if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n const env = await environmentStore.update(input);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n // If a global environment was renamed, cascade to service-scoped environment names\n if (env.scope === 'global' && input.name && input.name !== existing.name) {\n const project = await projectStore.get(env.projectId);\n if (project) {\n const serviceNames = new Map<string, string>();\n for (const serviceId of project.serviceIds) {\n const service = await serviceStore.get(serviceId);\n if (service) serviceNames.set(serviceId, service.name);\n }\n await environmentStore.renameByActivateOn(env.id, input.name, serviceNames);\n }\n }\n\n return env;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const env = await environmentStore.get(input.id);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.id} not found` });\n\n if (env.immutable) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot delete immutable environment' });\n }\n\n // If deleting a global env, also delete all service-scoped envs that activateOn it\n if (env.scope === 'global') {\n await environmentStore.deleteByActivateOn(input.id);\n }\n\n const deleted = await environmentStore.delete(input.id);\n if (!deleted) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to delete environment' });\n\n // Remove environment from project\n await projectStore.removeEnvironment(env.projectId, input.id);\n\n return { success: true };\n }),\n\n resolve: protectedProcedure\n .input(z.object({ environmentId: z.string().max(128) }))\n .query(async ({ input, ctx }) => {\n const { includeSecrets } = requireEnvAction(ctx as AuthContext, input.environmentId, 'env:read');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n\n const resolved = await environmentResolver.resolveEnvironmentWithSources(input.environmentId);\n\n if (!includeSecrets) {\n // Strip secret values — replace with empty string to preserve variable shape\n const sanitized = { ...resolved };\n if (sanitized.variables) {\n sanitized.variables = Object.fromEntries(\n Object.entries(sanitized.variables).map(([id, v]) => [\n id,\n v.value?.isSecret ? { ...v, value: { ...v.value, value: '' } } : v,\n ]),\n );\n }\n return sanitized;\n }\n\n return resolved;\n }),\n\n resolveFlat: protectedProcedure\n .meta({ openapi: { method: 'GET', path: '/environments/{environmentId}/resolve-flat', tags: ['environments'], summary: 'Resolve environment variables as a flat key-value map', protect: true } })\n .input(z.object({ environmentId: z.string().max(128) }))\n .output(z.record(z.string(), z.string()))\n .query(async ({ input, ctx }) => {\n const { includeSecrets } = requireEnvAction(ctx as AuthContext, input.environmentId, 'env:read');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n\n const { env: resolved, envSecrets } = await environmentResolver.resolveEnvironment(input.environmentId);\n\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(resolved)) {\n if (!includeSecrets && envSecrets.includes(key)) {\n result[key] = '*****';\n } else {\n result[key] = value;\n }\n }\n return result;\n }),\n\n // --- Overrides (flat, by variableId) ---\n\n setOverride: protectedProcedure\n .input(z.object({\n variableId: z.string().max(128),\n variable: VariableSchema,\n }))\n .mutation(async ({ input }) => {\n await environmentOverridesStore.setOverride(input.variableId, input.variable);\n return { success: true };\n }),\n\n removeOverride: protectedProcedure\n .input(z.object({\n variableId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await environmentOverridesStore.removeOverride(input.variableId);\n return { success: true };\n }),\n\n getOverrides: protectedProcedure\n .query(async () => {\n return await environmentOverridesStore.getAll();\n }),\n\n upsertVariable: protectedProcedure\n .meta({ openapi: { method: 'PUT', path: '/environments/{environmentId}/variables/{variableId}', tags: ['environments'], summary: 'Upsert a variable in an environment', protect: true } })\n .output(z.any())\n .input(z.object({\n environmentId: z.string().max(128),\n variableId: z.string().max(128),\n variable: VariableSchema,\n }))\n .mutation(async ({ input, ctx }) => {\n requireEnvAction(ctx as AuthContext, input.environmentId, 'env:write');\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n const result = await environmentStore.upsertVariable(input.environmentId, input.variableId, input.variable);\n if (!result) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to update variable' });\n return result;\n }),\n\n removeVariable: protectedProcedure\n .input(z.object({\n environmentId: z.string().max(128),\n variableId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n const env = await environmentStore.get(input.environmentId);\n if (!env) throw new TRPCError({ code: 'NOT_FOUND', message: `Environment ${input.environmentId} not found` });\n const result = await environmentStore.removeVariable(input.environmentId, input.variableId);\n if (!result) throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Failed to remove variable' });\n return result;\n }),\n});\n","import { promises as dns } from 'node:dns';\nimport { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { JSLogParserSchema, NotificationPreferencesSchema, SettingsSchema, type JSLogParserDef, nativeParsers, AIProviderSchema, type AIProvider, JSLogParser } from '@runeya/packages-shared';\nimport { settingsManager } from '../../services/settings-manager.js';\nimport { encryptValue, decryptValue, stableEncryptValue } from '../../services/crypto-helpers.js';\nimport { traefikManager } from '../../services/traefik-manager.js';\nimport { agentStore } from '../../services/agent-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { TraefikConfigSchema } from '@runeya/packages-shared';\n\nconst NotificationPreferencesPatchSchema = NotificationPreferencesSchema.partial().strict();\n\nfunction maskApiKey(plaintext: string): string {\n if (plaintext.length <= 8) return '****';\n return plaintext.slice(0, 4) + '****' + plaintext.slice(-4);\n}\n\nexport const settingsRouter = router({\n /**\n * Get all settings\n */\n get: protectedProcedure.query(async () => {\n const settings = await settingsManager.getSettings();\n return settings;\n }),\n\n /**\n * Update settings (mode, cloudUrl)\n */\n update: protectedProcedure\n .input(SettingsSchema.pick({ mode: true, cloudUrl: true }).partial())\n .mutation(async ({ input }) => {\n const current = await settingsManager.getSettings();\n const updated = {\n ...current,\n ...input,\n };\n await settingsManager.saveSettings(updated);\n return updated;\n }),\n\n /**\n * Get notification preferences\n */\n getNotificationPreferences: protectedProcedure.query(async () => {\n const priv = await settingsManager.getPrivateSettings();\n return NotificationPreferencesSchema.parse(priv.notifications ?? {});\n }),\n\n /**\n * Update notification preferences (granular mute)\n */\n updateNotificationPreferences: protectedProcedure\n .input(NotificationPreferencesPatchSchema)\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const currentPrefs = NotificationPreferencesSchema.parse(priv.notifications ?? {});\n const updatedPrefs = {\n ...currentPrefs,\n ...input,\n };\n await settingsManager.savePrivateSettings({\n ...priv,\n notifications: updatedPrefs,\n });\n return updatedPrefs;\n }),\n\n /**\n * List all parsers\n */\n listParsers: protectedProcedure.query(async () => {\n const settings = await settingsManager.getSettings();\n return [...nativeParsers, ...(settings.logParsers || [])];\n }),\n\n /**\n * Get single parser by ID\n */\n getParser: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const parser = (settings.logParsers || []).find((p: JSLogParserDef) => p.id === input.id);\n if (!parser) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n return parser;\n }),\n\n /**\n * Create new parser\n */\n createParser: protectedProcedure\n .input(\n JSLogParserSchema.omit({\n id: true,\n createdAt: true,\n updatedAt: true,\n })\n )\n .mutation(async ({ input }) => {\n // Basic code validation (schema already validated forbiden patterns)\n if (!input.code.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Parser code cannot be empty' });\n }\n\n const id = `parser-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n const now = new Date();\n const parser = {\n id,\n ...input,\n createdAt: now,\n updatedAt: now,\n };\n\n const settings = await settingsManager.getSettings();\n await settingsManager.saveSettings({\n ...settings,\n logParsers: [...(settings.logParsers || []), parser],\n });\n\n return parser;\n }),\n\n /**\n * Update existing parser\n */\n updateParser: protectedProcedure\n .input(\n JSLogParserSchema.omit({\n createdAt: true,\n updatedAt: true,\n }).partial()\n .required({ id: true })\n )\n .mutation(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const parserIndex = (settings.logParsers || []).findIndex(\n (p: JSLogParserDef) => p.id === input.id\n );\n\n if (parserIndex === -1) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n\n if (input.id.startsWith('native:')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot modify built-in parsers' });\n }\n\n const existing = (settings.logParsers || [])[parserIndex];\n\n // If code changed, do basic validation\n if (input.code && !input.code.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Parser code cannot be empty' });\n }\n\n const updated = {\n ...existing,\n ...input,\n updatedAt: new Date(),\n };\n\n const newParsers = [...(settings.logParsers || [])];\n newParsers[parserIndex] = updated;\n\n await settingsManager.saveSettings({\n ...settings,\n logParsers: newParsers,\n });\n\n return updated;\n }),\n\n /**\n * Delete parser by ID\n */\n deleteParser: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const settings = await settingsManager.getSettings();\n const newParsers = (settings.logParsers || []).filter(\n (p: JSLogParserDef) => p.id !== input.id\n );\n\n if (input.id.startsWith('native:')) {\n throw new TRPCError({ code: 'FORBIDDEN', message: 'Cannot delete built-in parsers' });\n }\n\n if (newParsers.length === (settings.logParsers || []).length) {\n throw new TRPCError({ code: 'NOT_FOUND', message: `Parser not found: ${input.id}` });\n }\n\n await settingsManager.saveSettings({\n ...settings,\n logParsers: newParsers,\n });\n\n return { deleted: true };\n }),\n\n // ---------------------------------------------------------------------------\n // AI Providers\n // ---------------------------------------------------------------------------\n\n /**\n * List AI providers (API keys are masked)\n */\n listAIProviders: protectedProcedure.query(async () => {\n const priv = await settingsManager.getPrivateSettings();\n return (priv.aiProviders ?? []).map((p: AIProvider) => {\n let maskedKey = '(aucune)';\n if (p.encryptedApiKey) {\n try {\n maskedKey = maskApiKey(decryptValue(p.encryptedApiKey));\n } catch { maskedKey = '(clé invalide)'; }\n }\n return { id: p.id, name: p.name, provider: p.provider, model: p.model, active: p.active, maskedKey, createdAt: p.createdAt, updatedAt: p.updatedAt };\n });\n }),\n\n /**\n * Create AI provider\n */\n createAIProvider: protectedProcedure\n .input(z.object({\n name: z.string().min(1).max(200),\n provider: AIProviderSchema.shape.provider,\n apiKey: z.string().max(500).optional(), // optional for providers like Ollama\n model: z.string().max(200).optional(),\n }))\n .mutation(async ({ input }) => {\n if (input.provider !== 'ollama' && !input.apiKey?.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Une clé API est requise pour ce provider.' });\n }\n const priv = await settingsManager.getPrivateSettings();\n const id = `aiprovider-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const now = new Date();\n const plainKey = input.apiKey ?? '';\n const newProvider: AIProvider = {\n id,\n name: input.name,\n provider: input.provider,\n encryptedApiKey: plainKey ? encryptValue(plainKey) : '',\n model: input.model,\n active: (priv.aiProviders ?? []).length === 0, // first one is active by default\n createdAt: now,\n updatedAt: now,\n };\n await settingsManager.savePrivateSettings({\n ...priv,\n aiProviders: [...(priv.aiProviders ?? []), newProvider],\n });\n return { ...newProvider, maskedKey: plainKey ? maskApiKey(plainKey) : '(aucune)', encryptedApiKey: undefined };\n }),\n\n /**\n * Update AI provider (apiKey optional — omit to keep existing)\n */\n updateAIProvider: protectedProcedure\n .input(z.object({\n id: z.string().min(1).max(128),\n name: z.string().min(1).max(200).optional(),\n provider: AIProviderSchema.shape.provider.optional(),\n apiKey: z.string().min(1).max(500).optional(),\n model: z.string().max(200).optional(),\n }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const idx = providers.findIndex((p: AIProvider) => p.id === input.id);\n if (idx === -1) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n const existing = providers[idx];\n const encryptedApiKey = input.apiKey\n ? stableEncryptValue(input.apiKey, existing.encryptedApiKey)\n : existing.encryptedApiKey;\n const updated: AIProvider = {\n ...existing,\n ...(input.name ? { name: input.name } : {}),\n ...(input.provider ? { provider: input.provider } : {}),\n ...(input.model !== undefined ? { model: input.model || undefined } : {}),\n encryptedApiKey,\n updatedAt: new Date(),\n };\n const newProviders = [...providers];\n newProviders[idx] = updated;\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: newProviders });\n let maskedKey = '(aucune)';\n if (updated.encryptedApiKey) {\n try { maskedKey = maskApiKey(decryptValue(updated.encryptedApiKey)); } catch { /* */ }\n }\n return { ...updated, maskedKey, encryptedApiKey: undefined };\n }),\n\n /**\n * Delete AI provider\n */\n deleteAIProvider: protectedProcedure\n .input(z.object({ id: z.string().min(1).max(128) }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const filtered = providers.filter((p: AIProvider) => p.id !== input.id);\n if (filtered.length === providers.length) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n // If deleted was active, promote first remaining to active\n const deletedWasActive = providers.find((p: AIProvider) => p.id === input.id)?.active ?? false;\n if (deletedWasActive && filtered.length > 0) filtered[0].active = true;\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: filtered });\n return { deleted: true };\n }),\n\n /**\n * Set one provider as active (clears active flag on all others)\n */\n setActiveAIProvider: protectedProcedure\n .input(z.object({ id: z.string().min(1).max(128) }))\n .mutation(async ({ input }) => {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const idx = providers.findIndex((p: AIProvider) => p.id === input.id);\n if (idx === -1) throw new TRPCError({ code: 'NOT_FOUND', message: `AI provider not found: ${input.id}` });\n const updated = providers.map((p: AIProvider) => ({ ...p, active: p.id === input.id }));\n await settingsManager.savePrivateSettings({ ...priv, aiProviders: updated });\n return { id: input.id, active: true };\n }),\n\n // ---------------------------------------------------------------------------\n // Traefik config\n // ---------------------------------------------------------------------------\n\n /**\n * Get Traefik config for a specific agent (never returns credentials or cert key in plain text)\n */\n getAgentTraefikConfig: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n return {\n enabled: config?.enabled ?? false,\n acmeEmail: config?.acmeEmail,\n wildcardDomain: config?.wildcardDomain,\n httpPort: config?.httpPort ?? 80,\n httpsPort: config?.httpsPort ?? 443,\n dnsProvider: config?.dnsProvider,\n hasDnsCredentials: Object.keys(config?.dnsCredentials ?? {}).length > 0,\n dnsCredentialKeys: Object.keys(config?.dnsCredentials ?? {}),\n hasCert: !!config?.encryptedCert,\n acmeStaging: config?.acmeStaging ?? false,\n };\n }),\n\n /**\n * Update Traefik config for a specific agent (credentials are encrypted before saving)\n */\n updateAgentTraefikConfig: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n enabled: z.boolean().optional(),\n acmeEmail: z.string().email().max(256).optional(),\n wildcardDomain: z.string().max(253).optional(),\n httpPort: z.number().int().min(1).max(65535).optional(),\n httpsPort: z.number().int().min(1).max(65535).optional(),\n dnsProvider: z.string().max(64).optional(),\n dnsCredentials: z.record(z.string().max(64), z.string().max(2048)).optional(),\n acmeStaging: z.boolean().optional(),\n }))\n .mutation(async ({ input }) => {\n const { agentId, ...fields } = input;\n const raw = agentStore.getTraefikConfig(agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const existing = parsed?.success ? parsed.data : { enabled: false, dnsCredentials: {}, httpPort: 80, httpsPort: 443 };\n\n const encryptedCredentials = fields.dnsCredentials\n ? traefikManager.encryptDnsCredentials(fields.dnsCredentials)\n : existing.dnsCredentials;\n\n const updated = {\n ...existing,\n ...(fields.enabled !== undefined && { enabled: fields.enabled }),\n ...(fields.acmeEmail !== undefined && { acmeEmail: fields.acmeEmail }),\n ...(fields.wildcardDomain !== undefined && { wildcardDomain: fields.wildcardDomain }),\n ...(fields.httpPort !== undefined && { httpPort: fields.httpPort }),\n ...(fields.httpsPort !== undefined && { httpsPort: fields.httpsPort }),\n ...(fields.dnsProvider !== undefined && { dnsProvider: fields.dnsProvider }),\n ...(fields.acmeStaging !== undefined && { acmeStaging: fields.acmeStaging }),\n dnsCredentials: encryptedCredentials,\n };\n\n await agentStore.saveTraefikConfig(agentId, updated);\n\n // Déchiffrer les credentials avant push à l'agent\n const configToPush = {\n ...updated,\n dnsCredentials: traefikManager.decryptDnsCredentials(updated.dnsCredentials ?? {}),\n };\n // Push to connected agent\n await agentManager.pushTraefikConfig(agentId, configToPush);\n\n return { success: true };\n }),\n\n /**\n * Get Traefik config files content for a specific agent\n */\n getAgentTraefikConfigFiles: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<{ static: string; dynamic: string }>(\n input.agentId,\n 'config.getTraefikConfigFiles',\n );\n }),\n\n getAgentTraefikFileTree: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n return agentManager.agentQuery<Array<{ path: string; content: string }>>(\n input.agentId,\n 'config.getTraefikFileTree',\n );\n }),\n\n /**\n * Get Traefik container logs for a specific agent (snapshot)\n */\n getAgentTraefikLogs: protectedProcedure\n .input(z.object({ agentId: z.string().max(128), lines: z.number().int().min(1).max(500).default(100) }))\n .query(async ({ input }) => {\n const result = await agentManager.agentQuery<{ logs: string }>(\n input.agentId,\n 'config.getTraefikLogs',\n { lines: input.lines },\n );\n return result;\n }),\n\n /**\n * Stream Traefik logs in real-time (subscription, yields new lines every 500ms)\n */\n streamAgentTraefikLogs: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .subscription(async function* ({ input, signal }) {\n let seen = 0;\n while (!signal?.aborted) {\n try {\n const result = await agentManager.agentQuery<{ logs: string }>(\n input.agentId,\n 'config.getTraefikLogs',\n { lines: 500 },\n );\n const lines = result.logs?.trim() ? result.logs.split('\\n') : [];\n if (lines.length > seen) {\n const newLines = lines.slice(seen);\n seen = lines.length;\n yield { lines: newLines };\n }\n } catch {\n // agent not reachable yet — wait and retry\n }\n await new Promise(resolve => setTimeout(resolve, 500));\n }\n }),\n\n /**\n * Restart Traefik container on a specific agent (re-pushes config first to handle agent restarts)\n */\n restartAgentTraefik: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n if (!config?.enabled) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Traefik non activé sur cet agent' });\n const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };\n await agentManager.agentMutation(input.agentId, 'config.initTraefikConfig', decrypted, 5000);\n await agentManager.agentMutation(input.agentId, 'config.restartTraefik', undefined, 30000);\n return { success: true };\n }),\n\n /**\n * Force certificate renewal for a specific agent (wipes acme.json + restarts container)\n */\n renewAgentTraefikCert: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n if (!config?.enabled) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Traefik non activé sur cet agent' });\n const decrypted = { ...config, dnsCredentials: traefikManager.decryptDnsCredentials(config.dnsCredentials ?? {}) };\n await agentManager.agentMutation(input.agentId, 'config.initTraefikConfig', decrypted, 5000);\n await agentManager.agentMutation(input.agentId, 'config.renewTraefikCert', undefined, 30000);\n return { success: true };\n }),\n\n /**\n * Validate Traefik configuration for a specific agent\n */\n validateAgentTraefikConfig: protectedProcedure\n .input(z.object({ agentId: z.string().max(128) }))\n .query(async ({ input }) => {\n const raw = agentStore.getTraefikConfig(input.agentId);\n const parsed = raw ? TraefikConfigSchema.safeParse(raw) : null;\n const config = parsed?.success ? parsed.data : null;\n\n const checks: Array<{ id: string; ok: boolean; message: string }> = [];\n\n // Config completeness checks (server-side)\n checks.push({\n id: 'enabled',\n ok: config?.enabled === true,\n message: config?.enabled ? 'Traefik activé' : 'Traefik non activé',\n });\n checks.push({\n id: 'domain',\n ok: !!config?.wildcardDomain?.trim(),\n message: config?.wildcardDomain ? `Domaine : ${config.wildcardDomain}` : 'Domaine wildcard non configuré',\n });\n checks.push({\n id: 'email',\n ok: !!config?.acmeEmail?.trim(),\n message: config?.acmeEmail ? `Email ACME : ${config.acmeEmail}` : 'Email ACME non configuré',\n });\n checks.push({\n id: 'dns_provider',\n ok: !!config?.dnsProvider?.trim(),\n message: config?.dnsProvider ? `Provider DNS : ${config.dnsProvider}` : 'Provider DNS non configuré',\n });\n checks.push({\n id: 'credentials',\n ok: Object.keys(config?.dnsCredentials ?? {}).length > 0,\n message: Object.keys(config?.dnsCredentials ?? {}).length > 0\n ? `${Object.keys(config!.dnsCredentials!).length} variable(s) configurée(s)`\n : 'Variables d\\'environnement DNS manquantes',\n });\n\n // DNS resolution check — only proceed if domain contains valid hostname characters.\n if (config?.wildcardDomain?.trim()) {\n const sanitisedDomain = config.wildcardDomain.replace(/^\\*\\./, '').replace(/[^a-z0-9.\\-]/gi, '');\n const probe = `probe.${sanitisedDomain}`;\n try {\n const addresses = await dns.resolve4(probe);\n const pointsToLocalhost = addresses.some(a => a === '127.0.0.1');\n checks.push({\n id: 'dns_resolution',\n ok: pointsToLocalhost,\n message: pointsToLocalhost\n ? `${probe} → 127.0.0.1 ✓`\n : `${probe} résout vers ${addresses.join(', ')} (attendu : 127.0.0.1)`,\n });\n } catch {\n checks.push({\n id: 'dns_resolution',\n ok: false,\n message: `${probe} ne résout pas — vérifiez le DNS wildcard`,\n });\n }\n }\n\n // Agent-side checks (Docker, container status)\n let agentChecks: Array<{ id: string; ok: boolean; message: string }> = [];\n try {\n const status = await agentManager.agentQuery<{\n containerRunning: boolean;\n dockerAvailable: boolean;\n configFileExists: boolean;\n cert: { hasCert: boolean; domain: string | null; expiresAt: string | null; daysLeft: number | null; expired: boolean };\n }>(input.agentId, 'config.getTraefikStatus');\n agentChecks.push({\n id: 'docker',\n ok: status.dockerAvailable,\n message: status.dockerAvailable ? 'Docker disponible' : 'Docker non trouvé dans PATH',\n });\n agentChecks.push({\n id: 'container',\n ok: status.containerRunning,\n message: status.containerRunning ? 'Container Traefik en cours d\\'exécution' : 'Container Traefik arrêté',\n });\n agentChecks.push({\n id: 'config_file',\n ok: status.configFileExists,\n message: status.configFileExists ? 'Fichier de configuration présent' : 'Fichier traefik.yml absent (enregistrez la config)',\n });\n const c = status.cert;\n if (c.hasCert && !c.expired) {\n agentChecks.push({\n id: 'ssl_cert',\n ok: true,\n message: `Certificat SSL valide pour ${c.domain} — expire dans ${c.daysLeft} jour(s) (${c.expiresAt})`,\n });\n } else if (c.hasCert && c.expired) {\n agentChecks.push({\n id: 'ssl_cert',\n ok: false,\n message: `Certificat SSL expiré pour ${c.domain} (depuis ${c.expiresAt})`,\n });\n } else {\n agentChecks.push({\n id: 'ssl_cert',\n ok: false,\n message: c.domain\n ? `Aucun certificat SSL pour ${c.domain} — Traefik doit être actif pour déclencher le challenge DNS-01`\n : 'Aucun certificat SSL trouvé dans acme.json',\n });\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isNotFound = msg.includes('not found') || msg.includes('not connected');\n agentChecks.push({\n id: 'agent_reachable',\n ok: false,\n message: isNotFound\n ? `Agent non connecté au serveur (id: ${input.agentId})`\n : `Agent non joignable — ${msg}`,\n });\n }\n\n return { checks: [...checks, ...agentChecks] };\n }),\n\n /**\n * Test parser code: compile and run it against sample logs, return per-line results\n */\n testParser: protectedProcedure\n .input(\n z.object({\n code: z.string().max(50000),\n sampleLogs: z\n .array(\n z.object({\n raw: z.string().max(16384),\n stream: z.enum(['stdout', 'stderr']),\n })\n )\n .max(100)\n .default([]),\n })\n )\n .mutation(async ({ input }) => {\n // Compile via shared JSLogParser (same implementation as the agent)\n let jsParser: JSLogParser;\n try {\n jsParser = new JSLogParser([{\n id: 'preview',\n name: 'preview',\n code: input.code,\n enabled: true,\n version: 2,\n createdAt: new Date(),\n updatedAt: new Date(),\n }]);\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: err instanceof Error ? err.message : String(err),\n });\n }\n\n let idCounter = 0;\n const results = input.sampleLogs.map((log) => {\n const inputLine = {\n raw: log.raw,\n stream: log.stream as 'stdout' | 'stderr',\n level: 'info' as const,\n message: log.raw,\n hidden: false,\n metadata: {} as Record<string, unknown>,\n };\n\n try {\n const output = jsParser.parse({ ...inputLine });\n const logCard = output.json\n ? { id: `sim-${++idCounter}`, type: 'json', header: output.jsonHeader ?? 'JSON', state: 'self' as const, collapsable: true }\n : undefined;\n return { input: inputLine, output: { ...output, logCard }, error: null };\n } catch (err) {\n return { input: inputLine, output: null, error: err instanceof Error ? err.message : String(err) };\n }\n });\n\n return { validated: true, results };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { execFile, spawn } from 'node:child_process';\nimport { stat } from 'node:fs/promises';\nimport { resolve, join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { SUPPORTED_EDITORS, EDITOR_BY_KEY } from '@runeya/packages-shared';\nimport { userConfigManager } from '../../services/user-config-manager.js';\nimport { serviceStore } from '../../services/service-store.js';\n\nfunction resolveCwd(cwd: string): string {\n const withHome = cwd.replace(/^~(\\/|$)/, `${homedir()}$1`);\n return withHome.replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (match, braced, plain) => {\n const name = braced ?? plain;\n return process.env[name] ?? match;\n });\n}\n\nasync function getServiceCwd(serviceId: string): Promise<string> {\n const services = await serviceStore.list();\n const service = services.find((s) => s.id === serviceId);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Service not found' });\n }\n const rawCwd = service.cwd?.trim() || '.';\n return resolveCwd(rawCwd);\n}\n\nasync function isCommandAvailable(command: string): Promise<boolean> {\n return new Promise((resolve) => {\n execFile('which', [command], { timeout: 5_000 }, (err) => {\n resolve(!err);\n });\n });\n}\n\nexport const editorRouter = router({\n listAvailable: protectedProcedure.query(async () => {\n const results = await Promise.all(\n SUPPORTED_EDITORS.map(async (editor) => ({\n ...editor,\n installed: await isCommandAvailable(editor.command),\n })),\n );\n return results;\n }),\n\n getPreferences: protectedProcedure\n .input(z.object({ projectId: z.string().max(128) }))\n .query(async ({ input }) => {\n return userConfigManager.getEditorPreferences(input.projectId);\n }),\n\n setDefault: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n editorKey: z.string().max(64),\n }))\n .mutation(async ({ input }) => {\n if (!EDITOR_BY_KEY.has(input.editorKey)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n await userConfigManager.setEditorPreference(input.projectId, 'default', input.editorKey);\n return { success: true };\n }),\n\n setServiceEditor: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n serviceId: z.string().max(128),\n editorKey: z.string().max(64),\n }))\n .mutation(async ({ input }) => {\n if (!EDITOR_BY_KEY.has(input.editorKey)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n await userConfigManager.setEditorPreference(input.projectId, input.serviceId, input.editorKey);\n return { success: true };\n }),\n\n removeServiceEditor: protectedProcedure\n .input(z.object({\n projectId: z.string().max(128),\n serviceId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await userConfigManager.removeEditorPreference(input.projectId, input.serviceId);\n return { success: true };\n }),\n\n open: protectedProcedure\n .input(z.object({\n editorKey: z.string().max(64),\n path: z.string().max(4096),\n }))\n .mutation(async ({ input }) => {\n const editor = EDITOR_BY_KEY.get(input.editorKey);\n if (!editor) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n\n // Expand ~ and $VAR/${VAR} from process.env, then resolve relative paths\n const expanded = input.path\n .replace(/^~(\\/|$)/, `${process.env['HOME'] ?? '/tmp'}$1`)\n .replace(/\\$\\{(\\w+)\\}|\\$(\\w+)/g, (_, a, b) => process.env[a || b] ?? '');\n const resolvedPath = resolve(expanded || '.');\n\n // Validate path exists (directory or file)\n try {\n await stat(resolvedPath);\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Path does not exist: ${resolvedPath}` });\n }\n\n const child = spawn(editor.command, [resolvedPath], {\n shell: false,\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n\n return { success: true };\n }),\n\n openFile: protectedProcedure\n .input(z.object({\n editorKey: z.string().max(64),\n serviceId: z.string().max(128),\n relativePath: z.string().max(4096),\n }))\n .mutation(async ({ input }) => {\n const editor = EDITOR_BY_KEY.get(input.editorKey);\n if (!editor) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Unknown editor: ${input.editorKey}` });\n }\n\n const cwd = await getServiceCwd(input.serviceId);\n const filePath = join(cwd, input.relativePath);\n\n // Prevent path traversal\n if (!filePath.startsWith(cwd)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Path traversal not allowed' });\n }\n\n try {\n await stat(filePath);\n } catch {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `File does not exist: ${filePath}` });\n }\n\n const child = spawn(editor.command, [filePath], {\n shell: false,\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n child.unref();\n\n return { success: true };\n }),\n});\n","import { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { z } from 'zod';\n\nconst CONFIG_DIR = join(homedir(), '.runeya');\nconst CONFIG_FILE = 'runeya.conf';\n\nconst EditorPreferencesSchema = z.object({\n default: z.string().max(64).optional(),\n}).catchall(z.string().max(64))\n .refine((obj) => Object.keys(obj).length <= 500, 'Too many editor preferences');\n\nconst ProjectSettingsSchema = z.object({\n settings: z.object({\n editors: EditorPreferencesSchema.optional(),\n }).optional(),\n});\n\nconst UserConfigSchema = z.record(\n z.string().max(128),\n ProjectSettingsSchema,\n).refine((obj) => Object.keys(obj).length <= 100, 'Too many projects in config');\n\ntype UserConfig = z.infer<typeof UserConfigSchema>;\n\nclass UserConfigManager {\n private config: UserConfig | null = null;\n\n private async ensureDir(): Promise<void> {\n await mkdir(CONFIG_DIR, { recursive: true });\n }\n\n private async atomicWrite(data: unknown): Promise<void> {\n await this.ensureDir();\n const filePath = join(CONFIG_DIR, CONFIG_FILE);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n async getConfig(): Promise<UserConfig> {\n if (!this.config) {\n try {\n const raw = await readFile(join(CONFIG_DIR, CONFIG_FILE), 'utf-8');\n const parsed = UserConfigSchema.safeParse(JSON.parse(raw));\n this.config = parsed.success ? parsed.data : {};\n } catch {\n this.config = {};\n }\n }\n return this.config;\n }\n\n async saveConfig(config: UserConfig): Promise<void> {\n this.config = config;\n await this.atomicWrite(config);\n }\n\n async getEditorPreferences(projectId: string): Promise<Record<string, string>> {\n const config = await this.getConfig();\n return config[projectId]?.settings?.editors ?? {};\n }\n\n async setEditorPreference(projectId: string, target: string, editorKey: string): Promise<void> {\n const config = await this.getConfig();\n if (!config[projectId]) config[projectId] = {};\n if (!config[projectId].settings) config[projectId].settings = {};\n if (!config[projectId].settings!.editors) config[projectId].settings!.editors = {};\n config[projectId].settings!.editors![target] = editorKey;\n await this.saveConfig(config);\n }\n\n async removeEditorPreference(projectId: string, target: string): Promise<void> {\n const config = await this.getConfig();\n const editors = config[projectId]?.settings?.editors;\n if (editors && target in editors) {\n delete editors[target];\n await this.saveConfig(config);\n }\n }\n}\n\nexport const userConfigManager = new UserConfigManager();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join, dirname } from 'node:path';\nimport { protectedProcedure, router } from '../trpc.js';\nimport { apiKeyStore } from '../../services/api-key-store.js';\nimport { ApiKeyScopeSchema } from '@runeya/packages-shared';\n\nconst ALLOWED_SKILL_PATHS = new Set([\n '.claude/skills/runeya/SKILL.md',\n '.cursor/rules/runeya.mdc',\n '.windsurf/rules/runeya.md',\n]);\n\nconst KeyInputSchema = z.object({\n name: z.string().min(1).max(200),\n scopes: ApiKeyScopeSchema,\n isPublic: z.boolean().default(false),\n});\n\nexport const apiKeysRouter = router({\n list: protectedProcedure\n .query(() => apiKeyStore.list()),\n\n create: protectedProcedure\n .input(KeyInputSchema)\n .mutation(({ input }) =>\n apiKeyStore.create(input.name, input.scopes, input.isPublic),\n ),\n\n update: protectedProcedure\n .input(KeyInputSchema.extend({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const updated = await apiKeyStore.update(input.id, input.name, input.scopes, input.isPublic);\n if (!updated) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return updated;\n }),\n\n remove: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const removed = await apiKeyStore.remove(input.id);\n if (!removed) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return { success: true };\n }),\n\n renewKey: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const renewed = await apiKeyStore.renewKey(input.id);\n if (!renewed) throw new TRPCError({ code: 'NOT_FOUND', message: 'API key not found' });\n return renewed;\n }),\n\n writeSkillFile: protectedProcedure\n .input(z.object({\n relativePath: z.string().max(256),\n content: z.string().max(32768),\n }))\n .mutation(async ({ input }) => {\n if (!ALLOWED_SKILL_PATHS.has(input.relativePath)) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Chemin non autorisé' });\n }\n const abs = join(process.cwd(), input.relativePath);\n await mkdir(dirname(abs), { recursive: true });\n await writeFile(abs, input.content, { encoding: 'utf-8', mode: 0o644 });\n return { path: input.relativePath };\n }),\n});\n","import { z } from 'zod';\nimport Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { fileURLToPath } from 'node:url';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport type { AuthContext } from '../trpc.js';\nimport {\n ConversationIdSchema,\n Id128Schema,\n ShortString200Schema,\n} from '../shared-schemas.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { generateLlmsTxt, generateAdminLlmsTxt } from '../../services/llms-txt-generator.js';\nimport { CHAT_TOOLS, CHAT_TOOLS_OPENAI, TOOL_SAFETY_INSTRUCTION, executeTool } from '../../services/chat-tools.js';\nimport { env } from '../../config/env.js';\nimport { resolveServiceVariables } from './service.js';\nimport { conversationStore } from '../../services/conversation-store.js';\nimport type { ConversationChangeEvent, MessagePart } from '../../services/conversation-store.js';\nimport type { ApiKey } from '@runeya/packages-shared';\nimport { getClaudeUsageEntries } from '../../services/claude-usage.js';\nimport { getCodexUsageEntries } from '../../services/codex-usage.js';\nimport { activeSessionRegistry } from '../../services/active-session-registry.js';\nimport type { ActiveSession, QueueItem } from '../../services/active-session-registry.js';\nimport { scenarioStore } from '../../services/scenario-store.js';\nimport { scenarioRunStore } from '../../services/scenario-run-store.js';\nimport {\n DEFAULT_MODELS,\n OPENAI_COMPAT_BASE_URLS,\n fetchProviderModels,\n getActiveProvider,\n} from '../../services/ai-provider-utils.js';\nimport { resolveImagesToBase64 } from '../../services/message-images.js';\nimport { imageStorageService } from '../../services/image-storage.service.js';\nimport { generateKanbanSystemPrompt, generateKanbanPopulatePrompt } from '../../services/kanban-commands.js';\nimport { kanbanStore } from '../../services/kanban-store.js';\nimport { ClaudeCodeRunner } from '../../services/ai-runners/claude-code-runner.js';\nimport { CodexRunner } from '../../services/ai-runners/codex-runner.js';\nimport { agentManager } from '../../services/agent-manager.js';\n\nconst execFileAsync = promisify(execFile);\n\nconst MessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string().max(100_000),\n});\n\nconst ImagePartSchema = z.object({\n type: z.literal('image'),\n imageId: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),\n url: z.string().max(500),\n mimeType: z.string().max(100),\n altText: z.string().max(500).optional(),\n});\nconst ImagePartsSchema = z.array(ImagePartSchema).max(5).optional();\n\nconst LANGUAGE_INSTRUCTION = 'Always respond in the same language the user writes in.';\n\n\nasync function buildSystemPrompt(apiKey: ApiKey | null): Promise<string> {\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const context = apiKey\n ? generateLlmsTxt(apiKey, resolvedServices.filter(s => apiKey.scopes.services.some(p => p.serviceId === s.id)))\n : generateAdminLlmsTxt(resolvedServices);\n const runeya_ai_vars = Object.entries(process.env)\n .filter(([k]) => k.startsWith('RUNEYA_AI_'))\n .map(([k, v]) => `${k}=${v}`)\n .join('\\n');\n const envSection = runeya_ai_vars ? `\\n\\n## Environment\\n\\n${runeya_ai_vars}` : '';\n return `${LANGUAGE_INSTRUCTION}\\n\\n${context}${envSection}`;\n}\n\n// ─── Event types yielded by the subscription ─────────────────────────────────\n\ntype ChatEvent =\n | { type: 'delta'; text: string }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' };\n\n// ─── Anthropic tool-use loop ──────────────────────────────────────────────────\n\nasync function* runAnthropic(\n client: Anthropic,\n model: string,\n system: string,\n initialMessages: Anthropic.MessageParam[],\n apiKey: ApiKey | null,\n authToken: string,\n signal?: AbortSignal,\n): AsyncGenerator<ChatEvent> {\n const messages: Anthropic.MessageParam[] = [...initialMessages];\n const MAX_TOOL_ROUNDS = 10;\n\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n // Buffer tool_use blocks; stream text deltas live\n const toolUseBlocks: Anthropic.ToolUseBlock[] = [];\n // Accumulate partial JSON for each tool use block (keyed by block index)\n const partialJson = new Map<number, string>();\n let assistantText = '';\n\n if (signal?.aborted) return;\n const stream = client.messages.stream({\n model,\n max_tokens: 16384,\n system,\n tools: CHAT_TOOLS as Anthropic.Tool[],\n messages,\n }, { signal });\n\n for await (const event of stream) {\n if (event.type === 'content_block_start' && event.content_block.type === 'tool_use') {\n toolUseBlocks.push({ ...event.content_block, input: {} } as Anthropic.ToolUseBlock);\n } else if (event.type === 'content_block_delta') {\n if (event.delta.type === 'text_delta') {\n assistantText += event.delta.text;\n yield { type: 'delta', text: event.delta.text };\n } else if (event.delta.type === 'input_json_delta') {\n const idx = toolUseBlocks.length - 1;\n if (idx >= 0) {\n partialJson.set(idx, (partialJson.get(idx) ?? '') + event.delta.partial_json);\n }\n }\n } else if (event.type === 'content_block_stop') {\n const idx = toolUseBlocks.length - 1;\n const last = toolUseBlocks[idx];\n const partial = partialJson.get(idx);\n if (last && partial !== undefined) {\n try { last.input = JSON.parse(partial); } catch { last.input = {}; }\n partialJson.delete(idx);\n }\n }\n }\n\n const finalMsg = await stream.finalMessage();\n\n // No tool calls → done\n if (finalMsg.stop_reason !== 'tool_use' || toolUseBlocks.length === 0) {\n yield { type: 'done', text: '' };\n return;\n }\n\n // Build assistant message with all content blocks\n const assistantContent: Anthropic.MessageParam['content'] = [];\n if (assistantText) assistantContent.push({ type: 'text', text: assistantText } as Anthropic.TextBlockParam);\n assistantContent.push(...toolUseBlocks);\n messages.push({ role: 'assistant', content: assistantContent });\n\n // Execute each tool and collect results\n const toolResults: Anthropic.ToolResultBlockParam[] = [];\n for (const block of toolUseBlocks) {\n yield { type: 'tool_call', id: block.id, name: block.name, input: block.input as Record<string, unknown> };\n let result: unknown;\n let isError = false;\n try {\n result = await executeTool(block.name, block.input as Record<string, unknown>, apiKey, authToken);\n } catch (err) {\n result = (err as Error).message;\n isError = true;\n }\n yield { type: 'tool_result', id: block.id, name: block.name, result, isError };\n toolResults.push({\n type: 'tool_result',\n tool_use_id: block.id,\n content: typeof result === 'string' ? result : JSON.stringify(result, null, 2),\n is_error: isError,\n });\n }\n\n messages.push({ role: 'user', content: toolResults });\n // Loop: send tool results back to AI\n }\n yield { type: 'done', text: '' };\n}\n\n// ─── OpenAI tool-use loop ─────────────────────────────────────────────────────\n\nasync function* runOpenAI(\n client: OpenAI,\n model: string,\n initialMessages: OpenAI.Chat.ChatCompletionMessageParam[],\n apiKey: ApiKey | null,\n authToken: string,\n signal?: AbortSignal,\n): AsyncGenerator<ChatEvent> {\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [...initialMessages];\n const MAX_TOOL_ROUNDS = 10;\n\n for (let round = 0; round < MAX_TOOL_ROUNDS; round++) {\n type ToolCallAcc = { id: string; name: string; args: string };\n const toolCallsAcc: Record<number, ToolCallAcc> = {};\n\n if (signal?.aborted) return;\n const stream = await client.chat.completions.create({\n model,\n messages,\n tools: CHAT_TOOLS_OPENAI,\n stream: true,\n max_tokens: 16384,\n temperature: 0,\n }, { signal });\n\n let finishReason: string | null = null;\n\n for await (const chunk of stream) {\n const choice = chunk.choices[0];\n if (!choice) continue;\n\n if (choice.delta?.content) {\n yield { type: 'delta', text: choice.delta.content };\n }\n\n // Accumulate tool call deltas\n for (const tc of choice.delta?.tool_calls ?? []) {\n const acc = toolCallsAcc[tc.index] ?? { id: '', name: '', args: '' };\n if (tc.id) acc.id = tc.id;\n if (tc.function?.name) acc.name = tc.function.name;\n if (tc.function?.arguments) acc.args += tc.function.arguments;\n toolCallsAcc[tc.index] = acc;\n }\n\n if (choice.finish_reason) finishReason = choice.finish_reason;\n }\n\n // Some Ollama models return finish_reason 'stop' even when they made tool calls.\n // Fall back to checking if any tool calls were accumulated.\n if (Object.keys(toolCallsAcc).length === 0) {\n yield { type: 'done', text: '' };\n return;\n }\n\n // Build assistant message with tool calls\n const toolCallsList = Object.values(toolCallsAcc);\n messages.push({\n role: 'assistant',\n tool_calls: toolCallsList.map(tc => ({\n id: tc.id,\n type: 'function' as const,\n function: { name: tc.name, arguments: tc.args },\n })),\n });\n\n // Execute tools\n for (const tc of toolCallsList) {\n let input: Record<string, unknown> = {};\n try { input = JSON.parse(tc.args); } catch { /* empty */ }\n\n yield { type: 'tool_call', id: tc.id, name: tc.name, input };\n\n let result: unknown;\n let isError = false;\n try {\n result = await executeTool(tc.name, input, apiKey, authToken);\n } catch (err) {\n result = (err as Error).message;\n isError = true;\n }\n\n yield { type: 'tool_result', id: tc.id, name: tc.name, result, isError };\n messages.push({\n role: 'tool',\n tool_call_id: tc.id,\n content: typeof result === 'string' ? result : JSON.stringify(result, null, 2),\n });\n }\n // Loop\n }\n yield { type: 'done', text: '' };\n}\n\n// ─── Session drainer (shared by new-message and reconnect) ───────────────────\n\nasync function* drainSession(\n session: ActiveSession,\n signal: AbortSignal | undefined,\n isReconnect: boolean,\n): AsyncGenerator<\n | { type: 'delta'; text: string }\n | { type: 'status'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'context_usage'; inputTokens: number; contextWindow: number }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown> }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' }\n> {\n if(process.env.DEBUG) console.log('[chat]: drainSession')\n // On reconnect, replay accumulated parts + current status\n if (isReconnect) {\n for (const part of session.parts) {\n if (part.type === 'thinking') {\n yield { type: 'thinking', text: part.text };\n } else if (part.type === 'text') {\n yield { type: 'delta', text: part.text };\n } else if (part.type === 'tool') {\n yield { type: 'tool_call', id: part.id, name: part.name, input: part.input ?? {} };\n if (!part.pending) yield { type: 'tool_result', id: part.id, name: part.name, result: part.result, isError: part.isError ?? false };\n }\n }\n if (session.lastStatus) {\n yield { type: 'status', text: session.lastStatus };\n }\n // If session already finished, yield done immediately\n if (session.status === 'done') {\n yield { type: 'done', text: '' };\n return;\n }\n }\n\n // Consumer cursor: skip buffered items, start receiving only NEW events\n // On reconnect we already replayed fullContent, so skip all existing buffer items\n let cursor = isReconnect ? session.totalProduced : (session.totalProduced - session.buffer.length);\n\n while (true) {\n // Drain any pending items\n while (cursor < session.totalProduced) {\n const idx = cursor - (session.totalProduced - session.buffer.length);\n const item: QueueItem | undefined = idx >= 0 ? session.buffer[idx] : undefined;\n cursor++;\n if (!item) continue;\n\n if (item.type === 'done') {\n yield { type: 'done', text: '' };\n return;\n }\n if (item.type === 'error') {\n yield { type: 'delta', text: `\\n\\n⚠️ ${item.message}` };\n continue;\n }\n if (item.type === 'status') {\n yield { type: 'status', text: item.text };\n continue;\n }\n if (item.type === 'thinking') {\n yield { type: 'thinking', text: item.text };\n continue;\n }\n if (item.type === 'context_usage') {\n yield { type: 'context_usage', inputTokens: item.inputTokens, contextWindow: item.contextWindow };\n continue;\n }\n if (item.type === 'tool_call') {\n yield { type: 'tool_call', id: item.id, name: item.name, input: item.input };\n continue;\n }\n if (item.type === 'tool_result') {\n yield { type: 'tool_result', id: item.id, name: item.name, result: item.result, isError: item.isError };\n continue;\n }\n yield item;\n }\n\n // If signal aborted, just stop yielding — process survives\n if (signal?.aborted) return;\n\n // Wait for next event from the registry, or signal abort\n await new Promise<void>(r => {\n if (cursor < session.totalProduced) { r(); return; }\n session.notify.add(r);\n const cleanup = () => { session.notify.delete(r); r(); };\n signal?.addEventListener('abort', cleanup, { once: true });\n });\n if (signal?.aborted) return;\n }\n}\n\n// ─── Shared CLI session starters (used by tRPC handlers + kanban queue) ──────\n\nasync function buildCliSystemContext(conv: Awaited<ReturnType<typeof conversationStore.get>>, jwt: string | undefined): Promise<string> {\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv?.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n return systemContext;\n}\n\nexport interface StartCliSessionOpts {\n model?: string;\n effort?: 'low' | 'medium' | 'high' | 'normal';\n jwt?: string;\n /** Extra metadata stored on the user message (for UI display) */\n userMessageParts?: MessagePart[];\n userMessageContextNote?: string;\n}\n\n/**\n * Start a Claude Code session for a conversation.\n * Registers the session in activeSessionRegistry (so the frontend can subscribe),\n * builds the system context (services + kanban), and fires the runner.\n * Returns `{ session, done }` where `done` resolves when the runner finishes.\n * Throws if a session is already running for this conversation.\n */\nexport async function startClaudeCodeSession(\n convId: string,\n prompt: string,\n opts: StartCliSessionOpts = {},\n): Promise<{ session: ActiveSession; done: Promise<void> }> {\n const conv = await conversationStore.get(convId);\n if (!conv) throw new Error(`Conversation ${convId} not found`);\n\n const isResume = conv.messages.length > 0;\n conv.messages.push({\n role: 'user',\n content: prompt,\n parts: opts.userMessageParts,\n contextNote: opts.userMessageContextNote,\n });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const systemContext = await buildCliSystemContext(conv, opts.jwt);\n\n const mcpServerPath = fileURLToPath(import.meta.resolve('@runeya/packages-mcp-server'));\n const mcpConfig = JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [mcpServerPath],\n env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...(opts.jwt ? { RUNEYA_API_TOKEN: opts.jwt } : {}) },\n },\n },\n });\n\n const ac = new AbortController();\n const session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n let capturedFinalResult = '';\n\n const resolvedAgentId = agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n const done = new ClaudeCodeRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.id,\n prompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: opts.jwt ?? '',\n model: opts.model ?? 'claude-opus-4-6',\n effort: opts.effort ?? 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n mcpConfig,\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n onContextUsage: (inputTokens, contextWindow) => activeSessionRegistry.pushEvent(convId, { type: 'context_usage', inputTokens, contextWindow }),\n onResult: (result) => { if (result) capturedFinalResult = result; },\n }).then(() => {\n if (process.env.DEBUG) console.log('[chat]: claude end...');\n if (activeSessionRegistry.get(convId) !== session) return;\n if (capturedFinalResult && capturedFinalResult.length > session.fullContent.length) {\n const missing = capturedFinalResult.slice(session.fullContent.length);\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text: missing });\n }\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (process.env.DEBUG) console.error('[chat]: error...', err?.message, err);\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Claude Code error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n return { session, done };\n}\n\nexport interface StartCodexSessionOpts {\n model?: string;\n jwt?: string;\n images?: { imageId: string; base64: string; mimeType: string; altText?: string }[];\n userMessageParts?: MessagePart[];\n userMessageContextNote?: string;\n}\n\n/**\n * Start a Codex session for a conversation.\n * Same contract as startClaudeCodeSession.\n */\nexport async function startCodexSession(\n convId: string,\n prompt: string,\n opts: StartCodexSessionOpts = {},\n): Promise<{ session: ActiveSession; done: Promise<void> }> {\n const conv = await conversationStore.get(convId);\n if (!conv) throw new Error(`Conversation ${convId} not found`);\n\n const isResume = !!conv.codexThreadId;\n conv.messages.push({\n role: 'user',\n content: prompt,\n parts: opts.userMessageParts,\n contextNote: opts.userMessageContextNote,\n });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const systemContext = await buildCliSystemContext(conv, opts.jwt);\n\n const ac = new AbortController();\n const session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n\n const resolvedAgentId = agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n const done = new CodexRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.codexThreadId ?? '',\n prompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: opts.jwt ?? '',\n model: opts.model ?? '',\n effort: 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n images: opts.images,\n onThreadId: (threadId) => conversationStore.update(conv.id, { codexThreadId: threadId }).catch(() => {}),\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Codex error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n return { session, done };\n}\n\n// ─── Router ───────────────────────────────────────────────────────────────────\n\nconst MessagePartSchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('thinking'), text: z.string().max(100_000) }),\n z.object({ type: z.literal('text'), text: z.string().max(100_000) }),\n z.object({\n type: z.literal('tool'),\n id: Id128Schema,\n name: Id128Schema,\n input: z.record(z.string(), z.unknown()).optional(),\n rawInput: z.string().max(10_000).optional(),\n result: z.unknown().optional(),\n isError: z.boolean().optional(),\n pending: z.boolean(),\n }),\n]);\n\nconst StoredMessageSchema = z.object({\n role: z.enum(['user', 'assistant']),\n content: z.string().max(100_000),\n parts: z.array(MessagePartSchema).max(200).optional(),\n});\n\nexport const chatRouter = router({\n conversations: router({\n onChanged: protectedProcedure.subscription(async function* () {\n const initial = await conversationStore.list();\n yield { type: 'initial' as const, conversations: initial };\n\n const queue: ConversationChangeEvent[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (event: ConversationChangeEvent) => {\n if (queue.length >= 500) queue.shift();\n queue.push(event);\n if (resolve) {\n resolve();\n resolve = null;\n }\n };\n\n conversationStore.onChanged(handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n conversationStore.offChanged(handler);\n }\n }),\n\n list: protectedProcedure\n .query(() => conversationStore.list()),\n\n get: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(async ({ input }) => {\n const conv = await conversationStore.get(input.id);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n\n create: protectedProcedure\n .input(z.object({\n title: ShortString200Schema.optional(),\n isCli: z.boolean().optional(),\n runner: z.enum(['claude-code', 'codex']).optional(),\n providerId: Id128Schema.optional(),\n scenarioId: Id128Schema.optional(),\n scenarioInput: z.string().max(100_000).optional(),\n kanbanBoardId: Id128Schema.optional(),\n kanbanCardId: Id128Schema.optional(),\n }))\n .mutation(async ({ input }) => {\n let scenario = null;\n if (input.scenarioId) {\n scenario = await scenarioStore.get(input.scenarioId);\n if (!scenario) throw new TRPCError({ code: 'NOT_FOUND', message: 'Scenario not found' });\n }\n\n const conv = await conversationStore.create(\n input.title,\n input.isCli ?? false,\n input.scenarioId,\n input.scenarioId ? 'scenario' : undefined,\n input.runner,\n input.kanbanBoardId,\n input.kanbanCardId,\n input.providerId,\n );\n\n if (scenario) {\n await scenarioRunStore.initializeConversationWorkspace(\n conv.id,\n scenario,\n input.scenarioInput ?? '',\n );\n }\n\n return conv;\n }),\n\n update: protectedProcedure\n .input(z.object({\n id: Id128Schema,\n title: ShortString200Schema.optional(),\n messages: z.array(StoredMessageSchema).max(500).optional(),\n contextUsage: z.object({\n inputTokens: z.number().int().nonnegative(),\n contextWindow: z.number().int().positive(),\n }).optional(),\n }))\n .mutation(async ({ input }) => {\n const conv = await conversationStore.update(input.id, { title: input.title, messages: input.messages, contextUsage: input.contextUsage });\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .mutation(async ({ input }) => {\n const existing = await conversationStore.get(input.id);\n if (!existing) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n await conversationStore.delete(input.id);\n await scenarioRunStore.deleteRunDir(input.id);\n // Fire-and-forget: delete the whole conversation images directory\n imageStorageService.deleteByContextId(input.id).catch((err) =>\n console.error('[chat.delete] Image cleanup error:', err),\n );\n }),\n\n archive: protectedProcedure\n .input(z.object({ id: Id128Schema, archived: z.boolean() }))\n .mutation(async ({ input }) => {\n const conv = await conversationStore.update(input.id, { archived: input.archived });\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n return conv;\n }),\n }),\n\n listModels: protectedProcedure\n .input(z.object({ providerId: Id128Schema.optional() }).optional())\n .query(async ({ input }) => {\n const active = await getActiveProvider(input?.providerId);\n if (!active) return [];\n try {\n return await fetchProviderModels(active.provider, active.plaintextKey);\n } catch {\n return [];\n }\n }),\n\n checkCliAvailability: protectedProcedure\n .input(z.object({ agentId: Id128Schema.optional() }).optional())\n .query(async ({ input }) => {\n if (input?.agentId) {\n try {\n const res = await agentManager.agentQuery<{ claudeAvailable: boolean; codexAvailable: boolean }>(\n input.agentId,\n 'health.checkCli',\n );\n return { available: res.claudeAvailable, codexAvailable: res.codexAvailable };\n } catch {\n return { available: false, codexAvailable: false };\n }\n }\n const [claudeOk, codexOk] = await Promise.all([\n execFileAsync('claude', ['--version'], { timeout: 5000, shell: false }).then(() => true).catch(() => false),\n execFileAsync('codex', ['--version'], { timeout: 5000, shell: false }).then(() => true).catch(() => false),\n ]);\n return { available: claudeOk, codexAvailable: codexOk };\n }),\n\n enhanceScenarioPrompt: protectedProcedure\n .input(z.object({ text: z.string().max(10_000), providerId: Id128Schema.optional() }))\n .mutation(async ({ input }) => {\n const active = await getActiveProvider(input.providerId);\n if (!active) throw new TRPCError({ code: 'BAD_REQUEST', message: 'No AI provider configured' });\n\n const systemPrompt = `You are an expert at writing clear, concise user request briefs for AI-powered workflows.\nWhen given a rough user request, rewrite it to be:\n- Clear and well-structured\n- Specific about the expected outcome\n- Written in the same language as the input\n- Concise but complete (no fluff)\nReturn ONLY the improved text, no explanation, no preamble.`;\n\n const { provider, plaintextKey } = active;\n const model = provider.model || DEFAULT_MODELS[provider.provider] || 'claude-opus-4-6';\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.messages.create({\n model,\n max_tokens: 2048,\n system: systemPrompt,\n messages: [{ role: 'user', content: input.text }],\n });\n const block = res.content[0];\n return { enhanced: block?.type === 'text' ? block.text : input.text };\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: input.text },\n ],\n });\n return { enhanced: res.choices[0]?.message?.content ?? input.text };\n }\n\n return { enhanced: input.text };\n }),\n\n listClaudeCodeModels: protectedProcedure\n .query(() => ['opus', 'sonnet', 'haiku']),\n\n getClaudeUsage: protectedProcedure\n .query(async () => {\n try {\n return await getClaudeUsageEntries();\n } catch {\n return null;\n }\n }),\n\n getCodexUsage: protectedProcedure\n .query(async () => {\n try {\n return await getCodexUsageEntries();\n } catch {\n return null;\n }\n }),\n\n getStreamingStatus: protectedProcedure\n .query(() => activeSessionRegistry.listActive()),\n\n stopSession: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .mutation(({ input }) => {\n if(process.env.DEBUG) console.log('[chat]: stopSession')\n const killed = activeSessionRegistry.kill(input.conversationId);\n if (!killed) throw new TRPCError({ code: 'NOT_FOUND', message: 'No active session for this conversation' });\n return { ok: true };\n }),\n\n streamViaClaudeCode: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n prompt: z.string().max(100_000),\n contextNote: z.string().max(200_000).optional(),\n model: ShortString200Schema.optional(),\n effort: z.enum(['low', 'medium', 'high']).optional(),\n reconnect: z.boolean().optional(),\n agentId: Id128Schema.optional(),\n imageIds: z.array(z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path: attach to an existing session ───────────────────\n if(process.env.DEBUG) console.log('[chat]: Reconnect')\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n // ── New message path ────────────────────────────────────────────────\n if (!input.prompt) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Prompt is required for new messages' });\n\n const conv = await conversationStore.get(input.conversationId);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n\n console.log(`[kanban-debug] streamViaClaudeCode start — convId=${conv.id} kanbanBoardId=${conv.kanbanBoardId ?? 'null'}`);\n\n const isResume = conv.messages.length > 0;\n\n const userParts = input.imageParts && input.imageParts.length > 0\n ? [...(input.prompt.trim() ? [{ type: 'text' as const, text: input.prompt }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: 'user', content: input.prompt, parts: userParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n if(process.env.DEBUG) console.log('[chat]: update')\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => { });\n\n const cliPrompt = input.contextNote ? `${input.contextNote}\\n\\n${input.prompt}` : input.prompt;\n\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const jwt = ctx.authorization?.startsWith('Bearer ') ? ctx.authorization.slice(7) : undefined;\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n const mcpServerPath = fileURLToPath(import.meta.resolve('@runeya/packages-mcp-server'));\n const mcpConfig = JSON.stringify({\n mcpServers: {\n runeya: {\n command: 'node',\n args: [mcpServerPath],\n env: { RUNEYA_BASE_URL: `http://localhost:${env.PORT}`, ...(jwt ? { RUNEYA_API_TOKEN: jwt } : {}) },\n },\n },\n });\n\n // Claude Code has filesystem access — pass image paths directly in the prompt\n const imagePaths: string[] = [];\n if (input.imageIds && input.imageIds.length > 0) {\n for (const id of input.imageIds) {\n const result = await imageStorageService.getImagePath(id);\n if (result) imagePaths.push(result.filePath);\n }\n }\n const promptWithImages = imagePaths.length > 0\n ? `${cliPrompt}\\n\\n${imagePaths.map(p => `Image: ${p}`).join('\\n')}`\n : cliPrompt;\n\n const convId = input.conversationId;\n const ac = new AbortController();\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n let capturedFinalResult = '';\n\n const resolvedAgentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n if(process.env.DEBUG) console.log('[chat]: claude run...')\n new ClaudeCodeRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.id,\n prompt: promptWithImages,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: jwt ?? '',\n model: input.model ?? 'claude-opus-4-6',\n effort: input.effort ?? 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n mcpConfig,\n onDelta: (text) => {\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text });\n },\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n onContextUsage: (inputTokens: number, contextWindow: number) => activeSessionRegistry.pushEvent(convId, { type: 'context_usage', inputTokens, contextWindow }),\n onResult: (result: string) => { if (result) capturedFinalResult = result; },\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n\n // Reconcile: push any content captured in the result event but missed by text_delta\n if (capturedFinalResult && capturedFinalResult.length > session.fullContent.length) {\n const missing = capturedFinalResult.slice(session.fullContent.length);\n activeSessionRegistry.pushEvent(convId, { type: 'delta', text: missing });\n }\n\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Claude Code error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n if(process.env.DEBUG) console.log('[chat]: drainSession...')\n yield* drainSession(session, signal, false);\n }),\n\n streamViaCodex: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n prompt: z.string().max(100_000),\n contextNote: z.string().max(200_000).optional(),\n model: ShortString200Schema.optional(),\n reconnect: z.boolean().optional(),\n agentId: Id128Schema.optional(),\n imageIds: z.array(z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path ───────────────────────────────────────────────────\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n if (!input.prompt) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Prompt is required' });\n\n const conv = await conversationStore.get(input.conversationId);\n if (!conv) throw new TRPCError({ code: 'NOT_FOUND', message: 'Conversation not found' });\n\n const isResume = !!conv.codexThreadId;\n\n const codexUserParts = input.imageParts && input.imageParts.length > 0\n ? [...(input.prompt.trim() ? [{ type: 'text' as const, text: input.prompt }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: 'user', content: input.prompt, parts: codexUserParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n conversationStore.update(conv.id, { messages: conv.messages }, { silent: true }).catch(() => {});\n\n const cliPrompt = input.contextNote ? `${input.contextNote}\\n\\n${input.prompt}` : input.prompt;\n\n const allServices = await serviceStore.list();\n const resolvedServices = await Promise.all(allServices.map(resolveServiceVariables));\n const jwt = ctx.authorization?.startsWith('Bearer ') ? ctx.authorization.slice(7) : undefined;\n let systemContext = generateAdminLlmsTxt(resolvedServices, jwt);\n\n if (conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n systemContext += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n const resolvedImages = input.imageIds && input.imageIds.length > 0\n ? await resolveImagesToBase64(input.imageIds.map(id => ({ imageId: id, mimeType: '' })))\n : [];\n\n const convId = input.conversationId;\n const ac = new AbortController();\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerProviderApiSession(convId, ac);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n\n const resolvedAgentId = input.agentId ?? agentManager.getDefaultAgentId();\n if (resolvedAgentId) {\n session.agentId = resolvedAgentId;\n }\n\n new CodexRunner().run({\n agentId: resolvedAgentId ?? undefined,\n sessionId: conv.codexThreadId ?? '',\n prompt: cliPrompt,\n isResume,\n systemContext,\n apiBaseUrl: `http://localhost:${env.PORT}`,\n apiToken: jwt ?? '',\n model: input.model ?? '',\n effort: 'normal',\n signal: ac.signal,\n skipTokenInstructions: true,\n images: resolvedImages,\n onThreadId: (threadId) => conversationStore.update(conv.id, { codexThreadId: threadId }).catch(() => {}),\n onDelta: (text) => activeSessionRegistry.pushEvent(convId, { type: 'delta', text }),\n onStatus: (text) => activeSessionRegistry.pushEvent(convId, { type: 'status', text }),\n onThinking: (text) => activeSessionRegistry.pushEvent(convId, { type: 'thinking', text }),\n onToolCall: (id, name, input_) => activeSessionRegistry.pushEvent(convId, { type: 'tool_call', id, name, input: input_ }),\n onToolResult: (id, result, isError) => activeSessionRegistry.pushEvent(convId, { type: 'tool_result', id, name: '', result, isError }),\n }).then(() => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n }).catch((err: Error) => {\n if (activeSessionRegistry.get(convId) !== session) return;\n activeSessionRegistry.pushEvent(convId, { type: 'error', message: `Codex error: ${err.message}` });\n activeSessionRegistry.pushEvent(convId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(convId);\n });\n\n yield* drainSession(session, signal, false);\n }),\n\n send: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n messages: z.array(MessageSchema).min(0).max(100),\n model: ShortString200Schema.optional(),\n contextNote: z.string().max(200_000).optional(),\n reconnect: z.boolean().optional(),\n imageIds: z.array(z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i)).max(5).optional(),\n imageParts: ImagePartsSchema,\n }))\n .subscription(async function* ({ input, ctx, signal }) {\n // ── Reconnect path: attach to an existing session ───────────────────\n const existingSession = activeSessionRegistry.get(input.conversationId);\n if (input.reconnect && existingSession) {\n yield* drainSession(existingSession, signal, true);\n return;\n }\n\n // ── New message path ────────────────────────────────────────────────\n if (input.messages.length === 0) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Messages are required for new messages' });\n }\n\n // Persist user message immediately — don't wait for the frontend\n const conv = await conversationStore.get(input.conversationId);\n\n const active = await getActiveProvider(conv?.providerId);\n\n if (!active) {\n throw new TRPCError({\n code: 'PRECONDITION_FAILED',\n message: 'No AI provider configured for this conversation. Please select one when starting a new chat.',\n });\n }\n if (conv) {\n const lastUserMsg = input.messages[input.messages.length - 1];\n if (lastUserMsg) {\n const sendUserParts = input.imageParts && input.imageParts.length > 0\n ? [...(lastUserMsg.content.trim() ? [{ type: 'text' as const, text: lastUserMsg.content }] : []), ...input.imageParts]\n : undefined;\n conv.messages.push({ role: lastUserMsg.role, content: lastUserMsg.content, parts: sendUserParts, contextNote: input.contextNote });\n conv.messages.push({ role: 'assistant', content: '' });\n await conversationStore.update(conv.id, { messages: conv.messages }, { silent: true });\n }\n }\n\n const { provider, plaintextKey } = active;\n const model = input.model ?? provider.model ?? DEFAULT_MODELS[provider.provider] ?? 'gpt-4o';\n const apiKey = (ctx as AuthContext).apiKey ?? null;\n const authToken = ctx.authorization?.replace(/^Bearer\\s+/i, '') ?? '';\n let system = await buildSystemPrompt(apiKey);\n system += '\\n\\n' + TOOL_SAFETY_INSTRUCTION;\n\n // Append kanban context if this conversation is linked to a kanban board/card\n if (conv && conv.kanbanBoardId) {\n const kanbanBoard = await kanbanStore.get(conv.kanbanBoardId);\n if (kanbanBoard) {\n system += '\\n\\n' + (conv.kanbanCardId\n ? generateKanbanSystemPrompt(kanbanBoard, conv.kanbanCardId)\n : generateKanbanPopulatePrompt(kanbanBoard));\n }\n }\n\n // Resolve images if any imageIds provided\n const resolvedImages = input.imageIds && input.imageIds.length > 0\n ? await resolveImagesToBase64(input.imageIds.map(id => ({ imageId: id, mimeType: '' })))\n : [];\n\n // Register in the session registry — stream survives WS disconnection\n let session: ActiveSession;\n try {\n session = activeSessionRegistry.registerDirectProviderApiSession(input.conversationId);\n } catch {\n throw new TRPCError({ code: 'CONFLICT', message: 'A session is already running for this conversation. Stop it first.' });\n }\n const apiSignal = session.abortController!.signal;\n\n // Fire-and-forget: run the API stream, pushing events into the registry\n const runStream = async () => {\n try {\n let gen: AsyncGenerator<ChatEvent>;\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const msgs: Anthropic.MessageParam[] = input.messages.map((m, i) => {\n const isLast = i === input.messages.length - 1;\n if (isLast && resolvedImages.length > 0) {\n const content: Anthropic.ContentBlockParam[] = resolvedImages.map(img => ({\n type: 'image' as const,\n source: { type: 'base64' as const, media_type: img.mimeType as Anthropic.Base64ImageSource['media_type'], data: img.base64 },\n }));\n content.push({ type: 'text', text: m.content });\n return { role: m.role, content };\n }\n return { role: m.role, content: m.content };\n });\n gen = runAnthropic(client, model, system, msgs, apiKey, authToken, apiSignal);\n } else if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const msgs: OpenAI.Chat.ChatCompletionMessageParam[] = [\n { role: 'system', content: system },\n ...input.messages.map((m, i) => {\n const isLast = i === input.messages.length - 1;\n if (isLast && resolvedImages.length > 0) {\n const content: OpenAI.Chat.ChatCompletionContentPart[] = resolvedImages.map(img => ({\n type: 'image_url' as const,\n image_url: { url: `data:${img.mimeType};base64,${img.base64}` },\n }));\n content.push({ type: 'text', text: m.content });\n return { role: m.role, content } as OpenAI.Chat.ChatCompletionMessageParam;\n }\n return { role: m.role, content: m.content } as OpenAI.Chat.ChatCompletionMessageParam;\n }),\n ];\n gen = runOpenAI(client, model, msgs, apiKey, authToken, apiSignal);\n } else {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'error', message: `Provider \"${provider.provider}\" is not supported.` });\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n activeSessionRegistry.markDone(input.conversationId);\n return;\n }\n\n for await (const event of gen) {\n if (event.type === 'delta') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'delta', text: event.text });\n } else if (event.type === 'tool_call') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'tool_call', id: event.id, name: event.name, input: event.input });\n } else if (event.type === 'tool_result') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'tool_result', id: event.id, name: event.name, result: event.result, isError: event.isError });\n } else if (event.type === 'done') {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n }\n }\n } catch (err) {\n if (!apiSignal.aborted) {\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'error', message: (err as Error).message });\n activeSessionRegistry.pushEvent(input.conversationId, { type: 'done', text: '' });\n }\n } finally {\n activeSessionRegistry.markDone(input.conversationId);\n }\n };\n\n // Start the stream in the background — it won't be cancelled by tRPC signal\n runStream();\n\n // Drain from registry (WS disconnection stops yielding but stream continues)\n yield* drainSession(session, signal, false);\n }),\n});\n","import { z } from 'zod';\n\nexport const Id128Schema = z.string().max(128);\nexport const ConversationIdSchema = z.string().max(128);\nexport const NameSchema = z.string().min(1).max(200);\nexport const ShortString200Schema = z.string().max(200);\nexport const DescriptionSchema = z.string().max(2000);\nexport const OptionalProviderIdSchema = Id128Schema.optional();\n","import { env } from '../config/env.js';\nimport type { ApiKey, ApiServicePerm, ServiceConfig } from '@runeya/packages-shared';\n\n/**\n * Generate a llms.txt for a JWT-authenticated admin caller (full access, all services).\n * Pass a JWT so Claude Code can authenticate its HTTP calls against the Runeya API.\n */\nexport function generateAdminLlmsTxt(services: ServiceConfig[], jwt?: string): string {\n const baseUrl = `http://localhost:${env.PORT}`;\n const trpcBase = `${baseUrl}/api/trpc`;\n\n const lines: string[] = [];\n\n lines.push('# Runeya — Service Management API');\n lines.push('');\n lines.push('> You are operating as an authenticated admin with full access to all services.');\n lines.push(`> Base URL: ${trpcBase}`);\n if (jwt) {\n // Token is injected via RUNEYA_API_TOKEN env var — do not embed raw value in CLI args.\n lines.push('> Authentication: pass `Authorization: Bearer $RUNEYA_API_TOKEN` on all tRPC requests.');\n }\n lines.push('');\n\n if (services.length === 0) {\n lines.push('No services configured.');\n return lines.join('\\n');\n }\n\n lines.push('## Services');\n lines.push('');\n\n for (const svc of services) {\n lines.push(`### ${svc.name}`);\n lines.push(`- **ID**: \\`${svc.id}\\``);\n if (svc.agentId) lines.push(`- **Agent ID**: \\`${svc.agentId}\\``);\n if (svc.description) lines.push(`- **Description**: ${svc.description}`);\n if (svc.cwd) lines.push(`- **Working directory**: \\`${svc.cwd}\\``);\n lines.push('- **Permitted actions**: all');\n lines.push('');\n }\n\n lines.push('## MCP Tools');\n lines.push('');\n lines.push('You have access to Runeya MCP tools to manage services. **Always prefer MCP tools** over raw HTTP calls.');\n lines.push('Available tools: `list_services`, `get_service_status`, `start_service`, `stop_service`, `restart_service`, `get_logs`.');\n lines.push('');\n if (jwt) {\n lines.push('**Important**: Pass the `authToken` parameter with value `$RUNEYA_API_TOKEN` (from environment) on every MCP tool call for authentication.');\n lines.push('');\n }\n lines.push('Use the service IDs and agent IDs listed above when calling these tools.');\n lines.push('');\n\n lines.push('## API Reference (fallback)');\n lines.push('');\n lines.push('Only use raw HTTP calls if MCP tools are unavailable.');\n lines.push('All endpoints use tRPC v11 over HTTP (`Content-Type: application/json`).');\n lines.push('');\n lines.push('**tRPC v11 request format:**');\n lines.push('- **GET queries**: `?input={\"id\":\"abc\"}`');\n lines.push('- **POST mutations**: JSON body `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n lines.push(`### List services\\n\\`GET ${trpcBase}/service.list\\``);\n lines.push('');\n lines.push(`### Get service\\n\\`GET ${trpcBase}/service.get?input={\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Read logs\\n\\`GET ${trpcBase}/process.logs?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Start service\\n\\`POST ${trpcBase}/process.start\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Stop service\\n\\`POST ${trpcBase}/process.stop\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Restart service\\n\\`POST ${trpcBase}/process.restart\\`\\nBody: \\`{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n lines.push(`### Get service status\\n\\`GET ${trpcBase}/process.status?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n\n return lines.join('\\n');\n}\n\n/**\n * Generate a llms.txt document describing the available API endpoints\n * for this key's scopes. Services are pre-filtered by the caller.\n */\nexport function generateLlmsTxt(\n apiKey: ApiKey,\n services: ServiceConfig[],\n): string {\n const { scopes } = apiKey;\n const baseUrl = `http://localhost:${env.PORT}`;\n const trpcBase = `${baseUrl}/api/trpc`;\n\n const lines: string[] = [];\n\n lines.push('# Runeya — Service Management API');\n lines.push('');\n lines.push('> This file describes the API surface available for this key.');\n lines.push(`> Base URL: ${trpcBase}`);\n lines.push(`> Authentication: pass this key as \\`Authorization: Bearer ${apiKey.key}\\` on all tRPC requests.`);\n lines.push('');\n\n if (services.length === 0) {\n lines.push('No services accessible with this key.');\n return lines.join('\\n');\n }\n\n // Build a quick lookup: serviceId → permission\n const permByServiceId = new Map<string, ApiServicePerm>(\n scopes.services.map(p => [p.serviceId, p]),\n );\n\n // --- Services ---\n lines.push('## Services');\n lines.push('');\n\n for (const svc of services) {\n const perm = permByServiceId.get(svc.id);\n const actions = perm?.actions ?? [];\n\n lines.push(`### ${svc.name}`);\n lines.push(`- **ID**: \\`${svc.id}\\``);\n if (svc.agentId) lines.push(`- **Agent ID**: \\`${svc.agentId}\\``);\n if (svc.description) lines.push(`- **Description**: ${svc.description}`);\n if (svc.cwd) lines.push(`- **Working directory**: \\`${svc.cwd}\\``);\n\n lines.push('- **Permitted actions**:');\n if (actions.length === 0) {\n lines.push(' - _(none)_');\n } else {\n for (const a of actions) lines.push(` - \\`${a}\\``);\n }\n\n const envPerms = perm?.environments ?? [];\n if (envPerms.length > 0) {\n lines.push('- **Environment access**:');\n for (const ep of envPerms) {\n const envActions = ep.actions.join(', ');\n const secrets = ep.includeSecrets ? ' _(includes secrets)_' : '';\n lines.push(` - \\`${ep.environmentId}\\`: ${envActions}${secrets}`);\n }\n }\n\n lines.push('');\n }\n\n // --- API Reference ---\n lines.push('## API Reference');\n lines.push('');\n lines.push('All endpoints use tRPC v11 over HTTP (`Content-Type: application/json`).');\n lines.push('');\n lines.push('**Important — tRPC v11 request format:**');\n lines.push('- **GET queries**: pass input as a plain JSON-encoded string in the `input` query param (no `{\"json\":...}` wrapper).');\n lines.push(' Example: `?input={\"id\":\"abc\"}`');\n lines.push('- **POST mutations**: send the input object as a plain JSON body (no `{\"json\":...}` wrapper).');\n lines.push(' Example body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('- The `agentId` is listed per service above.');\n lines.push('- The `processId` is the same as the service `ID` listed above.');\n lines.push('');\n\n // Collect union of actions across all services for the reference section\n const allActions = new Set(scopes.services.flatMap(p => p.actions));\n const hasEnvRead = scopes.services.some(p => p.environments.some(e => e.actions.includes('env:read')));\n const hasEnvWrite = scopes.services.some(p => p.environments.some(e => e.actions.includes('env:write')));\n\n if (allActions.has('service:read')) {\n lines.push('### List services');\n lines.push(`\\`GET ${trpcBase}/service.list\\``);\n lines.push('');\n lines.push('### Get service');\n lines.push(`\\`GET ${trpcBase}/service.get?input={\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('logs:read')) {\n lines.push('### Read logs');\n lines.push(`\\`GET ${trpcBase}/process.logs?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('service:start')) {\n lines.push('### Start service');\n lines.push(`\\`POST ${trpcBase}/process.start\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:stop')) {\n lines.push('### Stop service');\n lines.push(`\\`POST ${trpcBase}/process.stop\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:restart')) {\n lines.push('### Restart service');\n lines.push(`\\`POST ${trpcBase}/process.restart\\``);\n lines.push('Body: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`');\n lines.push('');\n }\n\n if (allActions.has('service:status')) {\n lines.push('### Get service status');\n lines.push(`\\`GET ${trpcBase}/process.status?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (allActions.has('service:healthcheck')) {\n lines.push('### Get service health');\n lines.push(`\\`GET ${trpcBase}/process.health?input={\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}\\``);\n lines.push('');\n }\n\n if (hasEnvRead) {\n lines.push('### Read environment variables (flat KEY=VALUE — secrets shown as *****)');\n lines.push(`\\`GET ${trpcBase}/environment.resolveFlat?input={\"environmentId\":\"<environmentId>\"}\\``);\n lines.push('Returns a flat `Record<string, string>`. Secret variables you are not authorized to see are shown as `*****`.');\n lines.push('');\n }\n\n if (hasEnvWrite) {\n lines.push('### Write environment variable');\n lines.push(`\\`POST ${trpcBase}/environment.upsertVariable\\``);\n lines.push('Body: `{\"environmentId\":\"<environmentId>\",\"key\":\"<key>\",\"value\":\"<value>\"}`');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","// ─── Runeya AI Capabilities — Single Source of Truth ─────────────────────────\n//\n// Adding a new capability:\n// 1. Add an entry to RUNEYA_CAPABILITIES below.\n// 2. Done. Anthropic tools, OpenAI tools, runner prompt docs, and MCP routes\n// are all generated automatically from this list.\n\nexport interface CapabilityParam {\n name: string;\n description: string;\n required: boolean;\n}\n\nexport interface RuneyaCapability {\n /** Tool name (snake_case, used as function name by LLMs). */\n name: string;\n /** Human-readable description shown to the LLM. */\n description: string;\n /** tRPC route segment, e.g. \"service.list\" or \"process.start\". */\n route: string;\n /** HTTP method for the tRPC call. */\n method: 'GET' | 'POST';\n /** Input parameters exposed to the LLM. */\n params: CapabilityParam[];\n /** Build the tRPC input object from raw LLM params. */\n buildInput: (params: Record<string, string | undefined>) => Record<string, unknown> | undefined;\n /** If true, safety instructions will warn the LLM to require explicit user intent. */\n destructive?: boolean;\n /**\n * Optional usage hint injected into the system prompt so the LLM knows when to use this tool.\n * Example: '\"wait 5s\" or \"pause for 10 seconds\" → call wait'\n */\n usageHint?: string;\n}\n\nexport const RUNEYA_CAPABILITIES: RuneyaCapability[] = [\n {\n name: 'list_services',\n description: 'List all available services. Returns serviceId and agentId for each — use these exact fields in other calls.',\n route: 'service.list',\n method: 'GET',\n params: [],\n buildInput: () => undefined,\n },\n {\n name: 'get_service_status',\n description: 'Get the current status (running, stopped, etc.) of a service.',\n route: 'process.get',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, id: p.serviceId }),\n },\n {\n name: 'get_logs',\n description: 'Get the recent buffered logs for a service.',\n route: 'process.logs',\n method: 'GET',\n params: [\n { name: 'serviceId', description: 'The service ID', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n },\n {\n name: 'start_service',\n description: 'Start a service on an agent.',\n route: 'process.start',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to start', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'stop_service',\n description: 'Stop a running service on an agent.',\n route: 'process.stop',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to stop', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n {\n name: 'restart_service',\n description: 'Restart a service on an agent (stop → redeploy → start).',\n route: 'process.restart',\n method: 'POST',\n params: [\n { name: 'serviceId', description: 'The service ID to restart', required: true },\n { name: 'agentId', description: 'The agent ID hosting this service', required: true },\n ],\n buildInput: (p) => ({ agentId: p.agentId, processId: p.serviceId }),\n destructive: true,\n },\n\n // ─── Utility ─────────────────────────────────────────────────────────────\n\n {\n name: 'wait',\n description: 'Wait for a given number of milliseconds before continuing.',\n route: 'utility.wait',\n method: 'POST',\n params: [\n { name: 'ms', description: 'Number of MILLISECONDS to wait. Convert from seconds: 1s=1000, 10s=10000, 1min=60000. Max 300000.', required: true },\n ],\n buildInput: (p) => ({ ms: Number(p.ms) }),\n usageHint: '\"wait 5s\" → wait(ms=5000), \"pause 10 seconds\" → wait(ms=10000), \"attends 3 secondes\" → wait(ms=3000). Always convert to milliseconds.',\n },\n\n // ─── Kanban ───────────────────────────────────────────────────────────────\n\n {\n name: 'kanban_move_card',\n description: 'Move a kanban card to another column. Use the exact column name.',\n route: 'kanban.moveCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID to move', required: true },\n { name: 'targetColumn', description: 'Exact name of the target column', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, targetColumn: p.targetColumn }),\n },\n {\n name: 'kanban_add_comment',\n description: 'Add a comment to a kanban card.',\n route: 'kanban.addComment',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'cardId', description: 'The card ID', required: true },\n { name: 'comment', description: 'The comment text (markdown supported)', required: true },\n ],\n buildInput: (p) => ({ boardId: p.boardId, cardId: p.cardId, comment: p.comment }),\n },\n {\n name: 'kanban_add_card',\n description: 'Add a new card to a kanban column.',\n route: 'kanban.addCard',\n method: 'POST',\n params: [\n { name: 'boardId', description: 'The kanban board ID', required: true },\n { name: 'column', description: 'Exact name of the target column', required: true },\n { name: 'title', description: 'Card title', required: true },\n { name: 'content', description: 'Card content in markdown', required: false },\n ],\n buildInput: (p) => ({ boardId: p.boardId, column: p.column, title: p.title, content: p.content }),\n },\n];\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n [k: string]: unknown;\n };\n}\n\nexport function buildAnthropicTools(capabilities: RuneyaCapability[]): AnthropicTool[] {\n return capabilities.map(cap => ({\n name: cap.name,\n description: cap.description,\n input_schema: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\n\nexport interface OpenAITool {\n type: 'function';\n function: {\n name: string;\n description: string;\n parameters: {\n type: 'object';\n properties: Record<string, { type: string; description: string }>;\n required: string[];\n };\n };\n}\n\nexport function buildOpenAITools(capabilities: RuneyaCapability[]): OpenAITool[] {\n return capabilities.map(cap => ({\n type: 'function' as const,\n function: {\n name: cap.name,\n description: cap.description,\n parameters: {\n type: 'object' as const,\n properties: Object.fromEntries(\n cap.params.map(p => [p.name, { type: 'string', description: p.description }]),\n ),\n required: cap.params.filter(p => p.required).map(p => p.name),\n },\n },\n }));\n}\n","import type { RuneyaCapability } from '../capabilities.js';\nexport type { RuneyaCapability };\n\n/**\n * Build the tool safety instruction block injected into cloud provider system prompts.\n * Generated from capabilities so it stays in sync automatically.\n */\nexport function buildToolSafetyInstruction(capabilities: RuneyaCapability[]): string {\n const destructive = capabilities.filter(c => c.destructive).map(c => c.name);\n const withHints = capabilities.filter(c => c.usageHint);\n\n const lines = ['## Tool use safety rules'];\n\n if (destructive.length > 0) {\n lines.push(`CRITICAL: Never call ${destructive.join(', ')} unless the user has EXPLICITLY and UNAMBIGUOUSLY requested it.`);\n lines.push(`- Only call destructive tools (${destructive.join(', ')}) when the user explicitly uses action words for a specific service.`);\n }\n\n if (withHints.length > 0) {\n lines.push('');\n lines.push('## Tool usage hints');\n for (const cap of withHints) {\n lines.push(`- ${cap.usageHint}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Build a markdown documentation block injected into runner system prompts.\n * Runners (ClaudeCodeRunner, CodexRunner) use this to know how to call the Runeya API.\n *\n * The generated doc is the single source of truth for all runner-facing API docs —\n * no need to maintain a separate runeya-api-docs.ts.\n */\nexport function buildPromptDocs(baseUrl: string, token: string, capabilities: RuneyaCapability[]): string {\n if (!token) return '';\n\n const lines: string[] = [\n '## Runeya API',\n '',\n `Tu peux interagir avec Runeya via l'API HTTP tRPC ci-dessous.`,\n `Base URL : ${baseUrl}/api/trpc`,\n 'Auth header : Authorization: Bearer $RUNEYA_API_TOKEN',\n '',\n ];\n\n const gets = capabilities.filter(c => c.method === 'GET');\n const posts = capabilities.filter(c => c.method === 'POST');\n\n if (gets.length > 0) {\n lines.push('### GET routes (paramètres en query string ?input=<JSON encodé>)', '');\n for (const cap of gets) {\n const example = cap.params.length > 0\n ? `?input=${JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'id' : p.name, '...'])))}`\n : '';\n lines.push(`- \\`${cap.route}${example}\\` — ${cap.description}`);\n }\n lines.push('');\n }\n\n if (posts.length > 0) {\n lines.push('### POST routes (body JSON)', '');\n for (const cap of posts) {\n const bodyExample = cap.params.length > 0\n ? JSON.stringify(Object.fromEntries(cap.params.map(p => [p.name === 'serviceId' ? 'processId' : p.name, '...'])))\n : '{}';\n lines.push(`- \\`${cap.route}\\` — \\`${bodyExample}\\``);\n }\n lines.push('');\n }\n\n const hints = capabilities.filter(c => c.usageHint);\n if (hints.length > 0) {\n lines.push('### Usage hints', '');\n for (const cap of hints) {\n lines.push(`- ${cap.usageHint}`);\n }\n lines.push('');\n }\n\n lines.push(\n '### Exemple curl',\n '',\n '```bash',\n `curl -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ` \"${baseUrl}/api/trpc/service.list\"`,\n '',\n `curl -X POST -H \"Authorization: Bearer $RUNEYA_API_TOKEN\" \\\\`,\n ' -H \"Content-Type: application/json\" \\\\',\n ` -d '{\"agentId\":\"local\",\"processId\":\"my-service\"}' \\\\`,\n ` \"${baseUrl}/api/trpc/process.start\"`,\n '```',\n '',\n 'La réponse est de la forme `{\"result\":{\"data\":<résultat>}}`.',\n );\n\n return lines.join('\\n');\n}\n","/**\n * Shared tRPC HTTP caller used by:\n * - Server-side cloud tool executor (proxies cloud LLM tool calls to local tRPC)\n * - MCP server (calls tRPC on behalf of CLI runners)\n */\nexport async function callTrpc(\n baseUrl: string,\n route: string,\n method: 'GET' | 'POST',\n input: Record<string, unknown> | undefined,\n authToken: string,\n): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${authToken}`,\n };\n\n const url = method === 'GET' && input\n ? `${baseUrl}/api/trpc/${route}?input=${encodeURIComponent(JSON.stringify(input))}`\n : `${baseUrl}/api/trpc/${route}`;\n\n const res = await fetch(url, {\n method,\n headers,\n ...(method === 'POST' ? { body: JSON.stringify(input ?? {}) } : {}),\n signal: AbortSignal.timeout(15_000),\n });\n\n const json = await res.json() as Record<string, unknown>;\n if (json['error']) throw new Error(JSON.stringify(json['error']));\n const result = json['result'] as Record<string, unknown> | undefined;\n return result?.['data'] ?? result ?? json;\n}\n","import {\n RUNEYA_CAPABILITIES,\n buildAnthropicTools,\n buildOpenAITools,\n buildToolSafetyInstruction,\n callTrpc,\n} from '@runeya/packages-ai-capabilities';\nimport type { ApiKey, ApiServiceAction } from '@runeya/packages-shared';\nimport { env } from '../config/env.js';\n\n// ─── Tool definitions (generated from capabilities) ───────────────────────────\n\nexport const CHAT_TOOLS = buildAnthropicTools(RUNEYA_CAPABILITIES);\nexport const CHAT_TOOLS_OPENAI = buildOpenAITools(RUNEYA_CAPABILITIES);\nexport const TOOL_SAFETY_INSTRUCTION = buildToolSafetyInstruction(RUNEYA_CAPABILITIES);\n\n// ─── Scope check ──────────────────────────────────────────────────────────────\n\nfunction hasServiceAction(apiKey: ApiKey | null, serviceId: string, action: ApiServiceAction): boolean {\n if (!apiKey) return true; // JWT = full access\n const perm = apiKey.scopes.services.find(p => p.serviceId === serviceId);\n return perm?.actions.includes(action) ?? false;\n}\n\n// ─── Tool name normalization ─────────────────────────────────────────────────\n// Some models (Groq, Ollama, …) hallucinate suffixes like `<|channel|>commentary`\n// after the real tool name. Match against known names to recover gracefully.\n\nconst KNOWN_TOOL_NAMES = RUNEYA_CAPABILITIES.map(c => c.name);\n\nfunction normalizeToolName(raw: string): string {\n if (KNOWN_TOOL_NAMES.includes(raw)) return raw;\n const match = KNOWN_TOOL_NAMES.find(t => raw.startsWith(t));\n return match ?? raw;\n}\n\n// ─── Tool executor — proxies to local tRPC API ────────────────────────────────\n//\n// Cloud LLMs cannot reach localhost directly, so the server acts as a proxy:\n// cloud tool_call → executeTool() → HTTP → /api/trpc/...\n//\n// This keeps the execution path identical to what runners (ClaudeCode, Codex)\n// do when they call the API themselves.\n\nexport async function executeTool(\n rawName: string,\n input: Record<string, unknown>,\n apiKey: ApiKey | null,\n authToken: string,\n): Promise<unknown> {\n const name = normalizeToolName(rawName);\n const cap = RUNEYA_CAPABILITIES.find(c => c.name === name);\n if (!cap) throw new Error(`Unknown tool: ${name}`);\n\n // Scope check for service-level actions\n const serviceId = (input['serviceId'] ?? input['id'] ?? input['processId']) as string | undefined;\n if (serviceId) {\n const actionMap: Record<string, ApiServiceAction> = {\n get_service_status: 'service:status',\n get_logs: 'logs:read',\n start_service: 'service:start',\n stop_service: 'service:stop',\n restart_service: 'service:restart',\n };\n const action = actionMap[name];\n if (action && !hasServiceAction(apiKey, serviceId, action)) {\n throw new Error(`No '${action}' permission for service ${serviceId}`);\n }\n }\n\n const params = Object.fromEntries(\n Object.entries(input).map(([k, v]) => [k, v != null ? String(v) : undefined]),\n ) as Record<string, string | undefined>;\n\n const baseUrl = `http://localhost:${env.PORT}`;\n return callTrpc(baseUrl, cap.route, cap.method, cap.buildInput(params), authToken);\n}\n","import { randomUUID } from 'node:crypto';\nimport { readFile, writeFile, rename, mkdir, chmod } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { EventEmitter } from 'node:events';\nimport { env } from '../config/env.js';\nimport { getEncryptionKey } from '../utils/encryption-key.js';\nimport { encryptValue, decryptValue } from './crypto-helpers.js';\n\nconst FILENAME = 'conversations.private.json';\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport type MessagePart =\n | { type: 'thinking'; text: string }\n | { type: 'text'; text: string }\n | { type: 'tool'; id: string; name: string; input?: Record<string, unknown>; rawInput?: string; result?: unknown; isError?: boolean; pending: boolean }\n | { type: 'image'; imageId: string; url: string; mimeType: string; altText?: string };\n\nexport interface Message {\n role: 'user' | 'assistant';\n content: string;\n parts?: MessagePart[];\n contextNote?: string;\n}\n\nexport interface ContextUsage {\n inputTokens: number;\n contextWindow: number;\n}\n\nexport type WorkflowType = 'scenario';\n\nexport interface Conversation {\n id: string;\n title: string;\n messages: Message[];\n isCli: boolean;\n runner?: 'claude-code' | 'codex';\n providerId?: string;\n codexThreadId?: string;\n contextUsage?: ContextUsage;\n workflowId?: string;\n workflowType?: WorkflowType;\n kanbanBoardId?: string;\n kanbanCardId?: string;\n archived?: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\ninterface ConversationSummary {\n id: string;\n title: string;\n isCli: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\nexport type ConversationChangeEvent =\n | { type: 'created'; conversation: Conversation }\n | { type: 'updated'; conversation: Conversation }\n | { type: 'deleted'; id: string };\n\ninterface ConversationOnDisk {\n id: string;\n title: string;\n encryptedMessages: string;\n isCli?: boolean;\n isClaudeCode?: boolean;\n runner?: 'claude-code' | 'codex';\n providerId?: string;\n codexThreadId?: string;\n contextUsage?: ContextUsage;\n workflowId?: string;\n workflowType?: WorkflowType;\n kanbanBoardId?: string;\n kanbanCardId?: string;\n // Legacy field from before workflowType was introduced — used only for migration in fromDisk\n scenarioId?: string;\n archived?: boolean;\n createdAt: number;\n updatedAt: number;\n}\n\n// ─── Store ─────────────────────────────────────────────────────────────────\n\nclass ConversationStore {\n private conversations: Map<string, Conversation> = new Map();\n private loaded = false;\n private readonly events = new EventEmitter();\n private saveQueue: Promise<void> = Promise.resolve();\n\n private snapshotConversation(conv: Conversation): Conversation {\n return structuredClone(conv);\n }\n\n private getFilePath(): string {\n return join(env.DATA_DIR, FILENAME);\n }\n\n private async ensureDir(): Promise<void> {\n await mkdir(env.DATA_DIR, { recursive: true });\n }\n\n private encryptMessages(messages: Message[]): string {\n return encryptValue(JSON.stringify(messages));\n }\n\n private decryptMessages(encrypted: string): Message[] {\n const json = decryptValue(encrypted);\n return JSON.parse(json) as Message[];\n }\n\n private toDisk(conv: Conversation): ConversationOnDisk {\n return {\n id: conv.id,\n title: conv.title,\n encryptedMessages: this.encryptMessages(conv.messages),\n isCli: conv.isCli,\n runner: conv.runner,\n providerId: conv.providerId,\n codexThreadId: conv.codexThreadId,\n contextUsage: conv.contextUsage,\n workflowId: conv.workflowId,\n workflowType: conv.workflowType,\n kanbanBoardId: conv.kanbanBoardId,\n kanbanCardId: conv.kanbanCardId,\n archived: conv.archived,\n createdAt: conv.createdAt,\n updatedAt: conv.updatedAt,\n };\n }\n\n private fromDisk(disk: ConversationOnDisk): Conversation {\n // Derive workflowType from legacy fields for conversations created before this field existed\n const workflowType: WorkflowType | undefined =\n (disk.workflowType === 'scenario' ? 'scenario' : undefined)\n ?? (disk.scenarioId ? 'scenario' : undefined);\n\n return {\n id: disk.id,\n title: disk.title,\n messages: this.decryptMessages(disk.encryptedMessages),\n isCli: disk.isCli ?? disk.isClaudeCode ?? false,\n runner: disk.runner,\n providerId: disk.providerId,\n codexThreadId: disk.codexThreadId,\n contextUsage: disk.contextUsage,\n workflowId: disk.workflowId ?? disk.scenarioId,\n workflowType,\n kanbanBoardId: disk.kanbanBoardId,\n kanbanCardId: disk.kanbanCardId,\n archived: disk.archived,\n createdAt: disk.createdAt,\n updatedAt: disk.updatedAt,\n };\n }\n\n private async load(): Promise<void> {\n if (this.loaded) return;\n if (!getEncryptionKey()) {\n this.loaded = true;\n return;\n }\n try {\n const raw = await readFile(this.getFilePath(), 'utf-8');\n const data: ConversationOnDisk[] = JSON.parse(raw);\n for (const item of data) {\n try {\n this.conversations.set(item.id, this.fromDisk(item));\n } catch {\n // Skip corrupted entries\n }\n }\n } catch {\n // File doesn't exist yet — start empty\n }\n this.loaded = true;\n }\n\n private async saveInternal(): Promise<void> {\n await this.ensureDir();\n if (!getEncryptionKey()) return;\n const data: ConversationOnDisk[] = Array.from(this.conversations.values()).map(c => this.toDisk(c));\n const filePath = this.getFilePath();\n const tmpPath = `${filePath}.tmp`;\n await writeFile(tmpPath, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n }\n\n private async save(): Promise<void> {\n const write = this.saveQueue.then(() => this.saveInternal());\n this.saveQueue = write.catch(() => {});\n return write;\n }\n\n async list(): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values())\n .sort((a, b) => b.updatedAt - a.updatedAt);\n }\n\n async get(id: string): Promise<Conversation | null> {\n await this.load();\n return this.conversations.get(id) ?? null;\n }\n\n async create(title?: string, isCli = false, workflowId?: string, workflowType?: WorkflowType, runner?: 'claude-code' | 'codex', kanbanBoardId?: string, kanbanCardId?: string, providerId?: string): Promise<Conversation> {\n await this.load();\n const now = Date.now();\n const conv: Conversation = {\n id: randomUUID(),\n title: title ?? 'New conversation',\n messages: [],\n isCli,\n runner,\n providerId,\n workflowId,\n workflowType,\n kanbanBoardId,\n kanbanCardId,\n createdAt: now,\n updatedAt: now,\n };\n this.conversations.set(conv.id, conv);\n await this.save();\n this.events.emit('changed', { type: 'created', conversation: this.snapshotConversation(conv) } as ConversationChangeEvent);\n return conv;\n }\n\n async update(id: string, patch: { title?: string; messages?: Message[]; contextUsage?: ContextUsage; workflowId?: string; archived?: boolean; codexThreadId?: string }, options?: { silent?: boolean }): Promise<Conversation | null> {\n await this.load();\n const conv = this.conversations.get(id);\n if (!conv) return null;\n if (patch.title !== undefined) conv.title = patch.title;\n if (patch.messages !== undefined) conv.messages = patch.messages;\n if (patch.contextUsage !== undefined) conv.contextUsage = patch.contextUsage;\n if (patch.workflowId !== undefined) conv.workflowId = patch.workflowId;\n if (patch.archived !== undefined) conv.archived = patch.archived;\n if (patch.codexThreadId !== undefined) conv.codexThreadId = patch.codexThreadId;\n conv.updatedAt = Date.now();\n await this.save();\n if (!options?.silent) {\n this.events.emit('changed', { type: 'updated', conversation: this.snapshotConversation(conv) } as ConversationChangeEvent);\n }\n return conv;\n }\n\n /**\n * Synchronously update the last assistant message content in memory, then schedule a save.\n * Used by activeSessionRegistry.persistNow() to avoid the async get() → .then() race.\n */\n updateLastAssistantContent(id: string, content: string, parts?: MessagePart[]): void {\n const conv = this.conversations.get(id);\n if (!conv) return;\n const lastMsg = conv.messages[conv.messages.length - 1];\n if (!lastMsg || lastMsg.role !== 'assistant') return;\n lastMsg.content = content;\n if (parts !== undefined) lastMsg.parts = parts;\n conv.updatedAt = Date.now();\n this.save().catch(() => {});\n }\n\n async listByKanbanBoardId(boardId: string): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values()).filter(c => c.kanbanBoardId === boardId);\n }\n\n async listByKanbanCardId(cardId: string): Promise<Conversation[]> {\n await this.load();\n return Array.from(this.conversations.values()).filter(c => c.kanbanCardId === cardId);\n }\n\n async delete(id: string): Promise<void> {\n await this.load();\n const existed = this.conversations.delete(id);\n await this.save();\n if (existed) {\n this.events.emit('changed', { type: 'deleted', id } as ConversationChangeEvent);\n }\n }\n\n onChanged(handler: (event: ConversationChangeEvent) => void): void {\n this.events.on('changed', handler);\n }\n\n offChanged(handler: (event: ConversationChangeEvent) => void): void {\n this.events.off('changed', handler);\n }\n}\n\nexport const conversationStore = new ConversationStore();\n","import pty from 'node-pty';\nimport { execSync } from 'child_process';\n\nexport interface CliUsageEntry {\n label: string;\n percentage: number | null;\n next_reset: string | null;\n}\n\ninterface UsageEntry {\n percent: number | null;\n resetsAt: string | null;\n}\n\ninterface ExtraUsage extends UsageEntry {\n spent: number | null;\n limit: number | null;\n}\n\ninterface ClaudeUsage {\n current_session?: UsageEntry;\n current_week_all?: UsageEntry;\n current_week_sonnet?: UsageEntry;\n extra_usage?: ExtraUsage;\n}\n\nconst MONTHS: Record<string, number> = {\n jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,\n jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11,\n};\n\nfunction parseResetsAt(str: string): string {\n const tzMatch = str.match(/\\(([^)]+)\\)/);\n const tz = tzMatch?.[1] ?? 'UTC';\n const dateStr = str.replace(/\\([^)]+\\)/, '').replace(/·/g, '').trim();\n\n const withTime = dateStr.match(/^([A-Za-z]{3})(\\d+),(\\d+)(am|pm)$/i);\n const withoutTime = dateStr.match(/^([A-Za-z]{3})(\\d+)$/i);\n // Time-only format: \"7:59am\" or \"10am\" — means today/tomorrow in the given tz\n const timeOnly = dateStr.match(/^(\\d+)(?::(\\d+))?(am|pm)$/i);\n\n let month: number, day: number, hour = 0, minute = 0; // minute used for timeOnly format\n\n const year = new Date().getFullYear();\n\n if (withTime) {\n month = MONTHS[withTime[1].toLowerCase()] ?? 0;\n day = parseInt(withTime[2]);\n hour = parseInt(withTime[3]);\n if (withTime[4].toLowerCase() === 'pm' && hour !== 12) hour += 12;\n if (withTime[4].toLowerCase() === 'am' && hour === 12) hour = 0;\n } else if (withoutTime) {\n month = MONTHS[withoutTime[1].toLowerCase()] ?? 0;\n day = parseInt(withoutTime[2]);\n } else if (timeOnly) {\n hour = parseInt(timeOnly[1]);\n minute = timeOnly[2] ? parseInt(timeOnly[2]) : 0;\n if (timeOnly[3].toLowerCase() === 'pm' && hour !== 12) hour += 12;\n if (timeOnly[3].toLowerCase() === 'am' && hour === 12) hour = 0;\n // Use today's local date in the target timezone\n const now = new Date();\n const parts = new Intl.DateTimeFormat('en', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(now);\n month = parseInt(parts.find(p => p.type === 'month')!.value) - 1;\n day = parseInt(parts.find(p => p.type === 'day')!.value);\n } else {\n return str;\n }\n const approxUtc = new Date(Date.UTC(year, month, day, hour, 0));\n const offsetStr = new Intl.DateTimeFormat('en', {\n timeZone: tz,\n timeZoneName: 'shortOffset',\n }).formatToParts(approxUtc).find(p => p.type === 'timeZoneName')?.value ?? 'GMT+0';\n\n const offsetMatch = offsetStr.match(/GMT([+-])(\\d+)(?::(\\d+))?/);\n const sign = offsetMatch?.[1] === '-' ? -1 : 1;\n const offsetMinutes = sign * (parseInt(offsetMatch?.[2] ?? '0') * 60 + parseInt(offsetMatch?.[3] ?? '0'));\n\n const utc = new Date(Date.UTC(year, month, day, hour, minute) - offsetMinutes * 60000);\n return utc.toISOString();\n}\n\nfunction extractSection(text: string, startPattern: RegExp, endPattern: RegExp | null): string | null {\n const start = text.search(startPattern);\n if (start === -1) return null;\n const after = text.slice(start);\n const end = endPattern ? after.search(endPattern) : after.length;\n return end === -1 ? after : after.slice(0, end);\n}\n\nfunction extractPercent(section: string | null): number | null {\n const m = section?.match(/(\\d+)%\\s*used/i);\n return m ? parseInt(m[1]) : null;\n}\n\nfunction extractResets(section: string | null): string | null {\n const m = section?.match(/Rese[ts]+\\s*(.+?)(?=Current|Extra|$)/is);\n return m ? m[1].replace(/\\s+/g, ' ').trim() : null;\n}\n\nfunction parse(text: string): ClaudeUsage {\n // Flatten to single line for cross-line regex matching (handles Windows ConPTY output)\n const flat = text.replace(/\\n/g, ' ').replace(/\\s+/g, ' ');\n const result: ClaudeUsage = {};\n\n const sessionSec = extractSection(flat, /Current\\s*session/i, /Current\\s*week|Extra\\s*usage/i);\n if (sessionSec) {\n const resets = extractResets(sessionSec);\n result.current_session = {\n percent: extractPercent(sessionSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const weekAllSec = extractSection(flat, /Current\\s*week\\s*\\(all\\s*models?\\)/i, /Current\\s*week\\s*\\(Sonnet/i);\n if (weekAllSec) {\n const resets = extractResets(weekAllSec);\n result.current_week_all = {\n percent: extractPercent(weekAllSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const weekSonnetSec = extractSection(flat, /Current\\s*week\\s*\\(Sonnet\\s*only\\)/i, /Extra\\s*usage/i);\n if (weekSonnetSec) {\n const resets = extractResets(weekSonnetSec);\n result.current_week_sonnet = {\n percent: extractPercent(weekSonnetSec),\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n const extraSec = extractSection(flat, /Extra\\s*usage(?!\\s*not)/i, null);\n if (extraSec && !/not\\s*enabled/i.test(extraSec.slice(0, 40))) {\n const spent = extraSec.match(/\\$([\\d.]+)\\s*\\/\\s*\\$([\\d.]+)\\s*spent/i);\n const resets = extractResets(extraSec);\n result.extra_usage = {\n percent: extractPercent(extraSec),\n spent: spent ? parseFloat(spent[1]) : null,\n limit: spent ? parseFloat(spent[2]) : null,\n resetsAt: resets ? parseResetsAt(resets) : null,\n };\n }\n\n return result;\n}\n\nfunction getClaudeUsage(): Promise<ClaudeUsage> {\n return new Promise((resolve, reject) => {\n const env = { ...process.env };\n delete env['CLAUDECODE'];\n\n let claudeBin = 'claude';\n try {\n const cmd = process.platform === 'win32' ? 'where claude' : 'which claude';\n claudeBin = execSync(cmd, { encoding: 'utf8' }).trim().split('\\n')[0].trim();\n } catch { /* fallback to 'claude' */ }\n\n let term: ReturnType<typeof pty.spawn> | null = null;\n try {\n term = pty.spawn(claudeBin, ['/usage'], {\n name: 'xterm-256color',\n cols: 200,\n rows: 40,\n env,\n });\n } catch (err) {\n reject(err);\n return;\n }\n\n let buffer = '';\n let done = false;\n let debounce: ReturnType<typeof setTimeout> | null = null;\n\n function finish() {\n if (done) return;\n done = true;\n if (debounce) clearTimeout(debounce);\n clearTimeout(hardTimeout);\n term?.kill();\n const clean = buffer\n .replace(/\\x1b\\[[0-9;]*X/g, '\\n') // ECH separators on Windows ConPTY\n .replace(/\\x1b\\[[0-9;]*[mGKHFABCDJsu]/g, '')\n .replace(/\\x1b[^a-zA-Z]*[a-zA-Z]/g, '')\n .replace(/\\r/g, '');\n resolve(parse(clean));\n }\n\n const hardTimeout = setTimeout(() => {\n if (!done) finish();\n }, 15_000);\n\n term.onData((data: string) => {\n buffer += data;\n // Start debounce only after actual usage data has arrived\n if (buffer.includes('%')) {\n if (debounce) clearTimeout(debounce);\n debounce = setTimeout(finish, 800);\n }\n });\n\n term.onExit(() => {\n finish();\n });\n });\n}\n\nexport async function getClaudeUsageEntries(): Promise<CliUsageEntry[]> {\n const usage = await getClaudeUsage();\n const entries: CliUsageEntry[] = [];\n\n if (usage.current_session) {\n entries.push({\n label: 'Session',\n percentage: usage.current_session.percent,\n next_reset: usage.current_session.resetsAt,\n });\n }\n\n if (usage.current_week_all) {\n entries.push({\n label: 'Week',\n percentage: usage.current_week_all.percent,\n next_reset: usage.current_week_all.resetsAt,\n });\n }\n\n if (usage.current_week_sonnet) {\n entries.push({\n label: 'Sonnet',\n percentage: usage.current_week_sonnet.percent,\n next_reset: usage.current_week_sonnet.resetsAt,\n });\n }\n\n if (usage.extra_usage) {\n entries.push({\n label: 'Extra',\n percentage: usage.extra_usage.percent,\n next_reset: usage.extra_usage.resetsAt,\n });\n }\n\n return entries;\n}\n","import pty from 'node-pty';\nimport type { CliUsageEntry } from './claude-usage.js';\n\nconst MONTHS: Record<string, number> = {\n jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5,\n jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11,\n};\n\nfunction parseResetToIso(raw: string): string | null {\n const value = raw\n .replace(/^\\(*/, '')\n .replace(/\\)*$/, '')\n .replace(/^resets?\\s*/i, '')\n .trim();\n\n const now = new Date();\n\n const timeOnly = value.match(/^(\\d{1,2}):(\\d{2})$/);\n if (timeOnly) {\n const hour = parseInt(timeOnly[1], 10);\n const minute = parseInt(timeOnly[2], 10);\n const date = new Date(now);\n date.setHours(hour, minute, 0, 0);\n if (date.getTime() <= now.getTime()) {\n date.setDate(date.getDate() + 1);\n }\n return date.toISOString();\n }\n\n const withDate = value.match(/^(\\d{1,2}):(\\d{2})\\s+on\\s+(\\d{1,2})\\s+([A-Za-z]{3})$/i);\n if (withDate) {\n const hour = parseInt(withDate[1], 10);\n const minute = parseInt(withDate[2], 10);\n const day = parseInt(withDate[3], 10);\n const month = MONTHS[withDate[4].toLowerCase()];\n if (month === undefined) return null;\n\n let year = now.getFullYear();\n let date = new Date(year, month, day, hour, minute, 0, 0);\n if (date.getTime() <= now.getTime()) {\n year += 1;\n date = new Date(year, month, day, hour, minute, 0, 0);\n }\n return date.toISOString();\n }\n\n return null;\n}\n\nfunction stripAnsi(text: string): string {\n return text\n .replace(/[\\u001b\\u009b][[\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')\n .replace(/\\r/g, '');\n}\n\nexport function parseCodexStatusText(text: string): CliUsageEntry[] {\n const clean = stripAnsi(text);\n const normalizedLines = clean\n .replace(/[│╭╰╮╯─]/g, ' ')\n .split('\\n')\n .map((line) => line.replace(/\\s+/g, ' ').trim())\n .filter(Boolean);\n\n const entries: CliUsageEntry[] = [];\n let pendingIndex: number | null = null;\n\n for (const line of normalizedLines) {\n const sameLine = line.match(/^(.+?limit)\\s*:\\s*(?:\\[[^\\]]*\\]\\s*)?(\\d+)%\\s*left(?:\\s*\\((?:resets?\\s+)?([^)]+)\\))?$/i);\n if (sameLine) {\n const label = sameLine[1].trim();\n const left = parseInt(sameLine[2], 10);\n const used = Number.isNaN(left) ? null : Math.max(0, Math.min(100, 100 - left));\n const nextReset = sameLine[3] ? (parseResetToIso(sameLine[3]) ?? null) : null;\n entries.push({ label, percentage: used, next_reset: nextReset });\n pendingIndex = nextReset ? null : entries.length - 1;\n continue;\n }\n\n const splitReset = line.match(/^\\(?\\s*resets?\\s+([^)]+)\\)?$/i);\n if (splitReset && pendingIndex !== null) {\n entries[pendingIndex].next_reset = parseResetToIso(splitReset[1]) ?? null;\n pendingIndex = null;\n }\n }\n\n if (entries.length === 0) {\n // Fallback: parse statusline format \"· X% left\" emitted by codex bottom bar\n // e.g. \"gpt-5.4 default · 43% left · ~/Projects/runeya-rust\"\n const statuslineMatch = clean.match(/·\\s*(\\d+)%\\s*left/i);\n if (statuslineMatch) {\n const left = parseInt(statuslineMatch[1], 10);\n const used = Number.isNaN(left) ? null : Math.max(0, Math.min(100, 100 - left));\n entries.push({ label: 'Usage', percentage: used, next_reset: null });\n }\n }\n\n return entries;\n}\n\nexport function getCodexUsageEntries(): Promise<CliUsageEntry[]> {\n return new Promise((resolve, reject) => {\n let term: ReturnType<typeof pty.spawn> | null = null;\n try {\n term = pty.spawn('codex', [], {\n name: 'xterm-256color',\n cols: 220,\n rows: 40,\n env: process.env,\n });\n } catch (err) {\n reject(err);\n return;\n }\n\n let buffer = '';\n let done = false;\n const queuedInputs = ['/status', '/status', '/status', '/exit'];\n let queuedIndex = 0;\n let inputDrainDebounce: ReturnType<typeof setTimeout> | null = null;\n let promptSeen = false;\n\n const finish = () => {\n if (done) return;\n done = true;\n if (inputDrainDebounce) clearTimeout(inputDrainDebounce);\n clearTimeout(initialTrigger);\n clearTimeout(hardTimeout);\n term?.kill();\n if (process.env['CODEX_USAGE_DEBUG'] === '1') {\n const debugClean = stripAnsi(buffer).slice(-6000);\n process.stdout.write('[codex-usage] raw tail:\\n' + debugClean + '\\n');\n }\n resolve(parseCodexStatusText(buffer));\n };\n\n const hardTimeout = setTimeout(() => {\n finish();\n }, 25_000);\n\n const sendNextInputIfReady = () => {\n if (done) return;\n if (!promptSeen) return;\n if (queuedIndex >= queuedInputs.length) return;\n const value = queuedInputs[queuedIndex];\n queuedIndex += 1;\n promptSeen = false;\n term?.write(`${value}\\r`);\n };\n\n const initialTrigger = setTimeout(() => {\n promptSeen = true;\n sendNextInputIfReady();\n }, 6_000);\n\n term.onData((data: string) => {\n buffer += data;\n if (data.includes('\\x1b[6n')) {\n // Answer DSR (cursor position report), matching pty-runner behavior.\n term?.write('\\x1b[25;1R');\n }\n\n if (data.includes('›')) {\n promptSeen = true;\n }\n\n if (inputDrainDebounce) clearTimeout(inputDrainDebounce);\n inputDrainDebounce = setTimeout(sendNextInputIfReady, 120);\n\n if (/(\\d+)\\s*h\\s+limit\\s*:/i.test(buffer) && /weekly\\s+limit\\s*:/i.test(buffer)) {\n setTimeout(finish, 800);\n }\n\n // Codex hasn't loaded limits yet — no point waiting the full 25s\n if (/data not available yet/i.test(buffer) && queuedIndex >= queuedInputs.length - 1) {\n setTimeout(finish, 400);\n }\n });\n\n term.onExit(() => {\n clearTimeout(initialTrigger);\n finish();\n });\n });\n}\n","import type { ChildProcess } from 'node:child_process';\nimport { conversationStore } from './conversation-store.js';\nimport { agentManager } from './agent-manager.js';\n\ntype SessionPart =\n | { type: 'thinking'; text: string }\n | { type: 'text'; text: string }\n | { type: 'tool'; id: string; name: string; input?: Record<string, unknown>; rawInput?: string; result?: unknown; isError?: boolean; pending: boolean };\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport type QueueItem =\n | { type: 'delta'; text: string }\n | { type: 'status'; text: string }\n | { type: 'thinking'; text: string }\n | { type: 'context_usage'; inputTokens: number; contextWindow: number }\n | { type: 'tool_call'; id: string; name: string; input: Record<string, unknown>; rawInput?: string }\n | { type: 'tool_result'; id: string; name: string; result: unknown; isError: boolean }\n | { type: 'done'; text: '' }\n | { type: 'error'; message: string };\n\nexport type AiRunnerType = 'claude-code' | 'provider-api';\n\nexport interface ActiveSession {\n proc: ChildProcess | null;\n abortController: AbortController | null;\n sessionType: AiRunnerType;\n conversationId: string;\n buffer: QueueItem[];\n totalProduced: number;\n fullContent: string;\n parts: SessionPart[];\n lastStatus: string;\n status: 'running' | 'done';\n persistTimer: ReturnType<typeof setTimeout> | null;\n cleanupTimer: ReturnType<typeof setTimeout> | null;\n notify: Set<() => void>;\n /** Agent ID when the AI CLI runs on a remote agent. */\n agentId?: string;\n /** Spawn ID on the remote agent (for kill / reconnect). */\n agentSpawnId?: string;\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER = 5_000;\nconst PERSIST_DEBOUNCE_MS = 100;\n\n// ─── Registry ──────────────────────────────────────────────────────────────\n\nclass ActiveSessionRegistry {\n private sessions = new Map<string, ActiveSession>();\n\n registerClaudeCodeSession(conversationId: string, proc: ChildProcess): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc,\n abortController: null,\n sessionType: 'claude-code',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n registerProviderApiSession(conversationId: string, ac: AbortController): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc: null,\n abortController: ac,\n sessionType: 'provider-api',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n registerDirectProviderApiSession(conversationId: string): ActiveSession {\n this.assertNoActiveSession(conversationId);\n\n const session: ActiveSession = {\n proc: null,\n abortController: new AbortController(),\n sessionType: 'provider-api',\n conversationId,\n buffer: [],\n totalProduced: 0,\n fullContent: '',\n parts: [],\n lastStatus: '',\n status: 'running',\n persistTimer: null,\n cleanupTimer: null,\n notify: new Set(),\n };\n\n this.sessions.set(conversationId, session);\n return session;\n }\n\n private assertNoActiveSession(conversationId: string): void {\n const existing = this.sessions.get(conversationId);\n if (existing && existing.status === 'running') {\n throw new Error(`A session is already running for conversation ${conversationId}. Stop it first.`);\n }\n }\n\n pushEvent(conversationId: string, event: QueueItem): void {\n if(process.env.DEBUG) console.log('[chat]: event - ', event.type)\n const session = this.sessions.get(conversationId);\n if (!session) return;\n if(process.env.DEBUG) console.log('[chat]: event - ', event.type, 'session', session.conversationId)\n\n // Accumulate parts for replay/persist\n if (event.type === 'delta') {\n session.fullContent += event.text;\n const last = session.parts[session.parts.length - 1];\n if (last?.type === 'text') last.text += event.text;\n else session.parts.push({ type: 'text', text: event.text });\n this.schedulePersist(session);\n }\n if (event.type === 'tool_call') {\n const existing = session.parts.find(p => p.type === 'tool' && p.id === event.id) as Extract<SessionPart, { type: 'tool' }> | undefined;\n if (existing) { existing.name = event.name; existing.input = event.input; }\n else session.parts.push({ type: 'tool', id: event.id, name: event.name, input: event.input, rawInput: event.rawInput, pending: true });\n this.schedulePersist(session);\n }\n if (event.type === 'tool_result') {\n const te = session.parts.find(p => p.type === 'tool' && p.id === event.id) as Extract<SessionPart, { type: 'tool' }> | undefined;\n if (te) {\n te.result = event.result;\n te.isError = event.isError;\n te.pending = false;\n } else {\n session.parts.push({ type: 'tool', id: event.id, name: event.name, result: event.result, isError: event.isError, pending: false });\n }\n this.schedulePersist(session);\n }\n if (event.type === 'thinking') {\n const last = session.parts[session.parts.length - 1];\n if (last?.type === 'thinking') last.text += event.text;\n else session.parts.push({ type: 'thinking', text: event.text });\n }\n if (event.type === 'status') {\n session.lastStatus = event.text;\n }\n\n // Cap buffer size — drop oldest if full\n if (session.buffer.length >= MAX_BUFFER) {\n session.buffer.shift();\n }\n if(process.env.DEBUG) console.log('[chat]: event - ', event.type, 'push buffer')\n session.buffer.push(event);\n session.totalProduced++;\n\n // Wake all consumers (multiple tabs/windows)\n if(process.env.DEBUG) console.log('[chat]: event - ', event.type, 'notify', session.notify.size)\n for (const cb of session.notify) cb();\n session.notify.clear();\n }\n\n markDone(conversationId: string): void {\n if(process.env.DEBUG) console.log('[chat]: markdone....', conversationId)\n const session = this.sessions.get(conversationId);\n if (!session) return;\n\n session.status = 'done';\n\n // Persist final content immediately\n this.persistNow(session);\n }\n\n get(conversationId: string): ActiveSession | undefined {\n return this.sessions.get(conversationId);\n }\n\n listActive(): { conversationId: string; status: 'running' | 'done'; sessionType: AiRunnerType }[] {\n const result: { conversationId: string; status: 'running' | 'done'; sessionType: AiRunnerType }[] = [];\n for (const session of this.sessions.values()) {\n result.push({ conversationId: session.conversationId, status: session.status, sessionType: session.sessionType });\n }\n return result;\n }\n\n kill(conversationId: string): boolean {\n const session = this.sessions.get(conversationId);\n if (!session) return false;\n\n if (session.status === 'running') {\n // Remote agent kill\n if (session.agentId && session.agentSpawnId) {\n agentManager.agentMutation(session.agentId, 'ai.kill', { spawnId: session.agentSpawnId }).catch(() => { /* best-effort */ });\n }\n if (session.proc) {\n try { session.proc.kill(); } catch { /* already dead */ }\n }\n if (session.abortController) {\n session.abortController.abort();\n }\n }\n return true;\n }\n\n // ── Internal helpers ────────────────────────────────────────────────────\n\n private schedulePersist(session: ActiveSession): void {\n if (session.persistTimer) return;\n session.persistTimer = setTimeout(() => {\n session.persistTimer = null;\n this.persistNow(session);\n }, PERSIST_DEBOUNCE_MS);\n }\n\n private persistNow(session: ActiveSession): void {\n if (session.persistTimer) {\n clearTimeout(session.persistTimer);\n session.persistTimer = null;\n }\n\n const fullContent = session.fullContent;\n const parts = session.parts.length > 0 ? [...session.parts] : undefined;\n // Synchronous mutation + async save — avoids the async get()→.then() race where a\n // debounced partial-persist .then() could run after a markDone full-persist .then()\n // and overwrite the complete content with stale partial content.\n conversationStore.updateLastAssistantContent(session.conversationId, fullContent, parts);\n }\n\n private cleanupTimers(session: ActiveSession): void {\n if (session.persistTimer) {\n clearTimeout(session.persistTimer);\n session.persistTimer = null;\n }\n if (session.cleanupTimer) {\n clearTimeout(session.cleanupTimer);\n session.cleanupTimer = null;\n }\n }\n}\n\nexport const activeSessionRegistry = new ActiveSessionRegistry();\n","import { settingsManager } from './settings-manager.js';\nimport { ScenarioSchema } from '@runeya/packages-shared';\nimport type { Scenario, ScenarioNode } from '@runeya/packages-shared';\n\nfunction normalizeNode(raw: ScenarioNode & { parentId?: string | null }): ScenarioNode {\n const aiCli = raw.aiCli ?? 'claude-code';\n const defaultModel = aiCli === 'codex' ? '' : 'sonnet';\n // Migrate legacy parentId → parentIds\n let parentIds = raw.parentIds ?? [];\n if (raw.parentId && !parentIds.includes(raw.parentId)) {\n parentIds = [raw.parentId, ...parentIds];\n }\n return {\n ...raw,\n parentIds,\n groupId: raw.groupId ?? null,\n label: raw.label?.trim() ?? '',\n prompt: raw.prompt ?? '',\n autoGenerated: raw.autoGenerated ?? true,\n canAddNode: raw.canAddNode ?? false,\n aiCli,\n model: raw.model?.trim() || defaultModel,\n };\n}\n\nclass ScenarioStore {\n async list(): Promise<Scenario[]> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n return [...(settings.scenarios ?? []), ...(priv.scenarios ?? [])];\n }\n\n async get(id: string): Promise<Scenario | null> {\n const list = await this.list();\n return list.find((e) => e.id === id) ?? null;\n }\n\n async create(scenario: Scenario): Promise<Scenario> {\n const normalized = this.normalizeScenario(scenario);\n const parsed = ScenarioSchema.parse(normalized);\n this.validateHierarchy(parsed);\n\n if (parsed.isPublished) {\n const settings = await settingsManager.getSettings();\n await settingsManager.saveSettings({ ...settings, scenarios: [...(settings.scenarios ?? []), parsed] });\n } else {\n const priv = await settingsManager.getPrivateSettings();\n await settingsManager.savePrivateSettings({ ...priv, scenarios: [...(priv.scenarios ?? []), parsed] });\n }\n\n return parsed;\n }\n\n async update(id: string, patch: Partial<Scenario>): Promise<Scenario | null> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n\n const publicScenarios = [...(settings.scenarios ?? [])];\n const privateScenarios = [...(priv.scenarios ?? [])];\n\n const publicIdx = publicScenarios.findIndex((e) => e.id === id);\n const privateIdx = privateScenarios.findIndex((e) => e.id === id);\n\n const existing = publicIdx !== -1 ? publicScenarios[publicIdx] : privateIdx !== -1 ? privateScenarios[privateIdx] : null;\n if (!existing) return null;\n\n const merged = { ...existing, ...patch, id, updatedAt: Date.now() } as Scenario;\n const normalized = this.normalizeScenario(merged);\n const parsed = ScenarioSchema.parse(normalized);\n this.validateHierarchy(parsed);\n\n const wasPublic = publicIdx !== -1;\n const isNowPublic = parsed.isPublished;\n\n if (wasPublic && isNowPublic) {\n publicScenarios[publicIdx] = parsed;\n await settingsManager.saveSettings({ ...settings, scenarios: publicScenarios });\n } else if (!wasPublic && !isNowPublic) {\n privateScenarios[privateIdx] = parsed;\n await settingsManager.savePrivateSettings({ ...priv, scenarios: privateScenarios });\n } else if (wasPublic && !isNowPublic) {\n // moved public → private\n publicScenarios.splice(publicIdx, 1);\n await Promise.all([\n settingsManager.saveSettings({ ...settings, scenarios: publicScenarios }),\n settingsManager.savePrivateSettings({ ...priv, scenarios: [...privateScenarios, parsed] }),\n ]);\n } else {\n // moved private → public\n privateScenarios.splice(privateIdx, 1);\n await Promise.all([\n settingsManager.savePrivateSettings({ ...priv, scenarios: privateScenarios }),\n settingsManager.saveSettings({ ...settings, scenarios: [...publicScenarios, parsed] }),\n ]);\n }\n\n return parsed;\n }\n\n async delete(id: string): Promise<boolean> {\n const [settings, priv] = await Promise.all([\n settingsManager.getSettings(),\n settingsManager.getPrivateSettings(),\n ]);\n\n const publicFiltered = (settings.scenarios ?? []).filter((e) => e.id !== id);\n const privateFiltered = (priv.scenarios ?? []).filter((e) => e.id !== id);\n\n const removedFromPublic = publicFiltered.length < (settings.scenarios ?? []).length;\n const removedFromPrivate = privateFiltered.length < (priv.scenarios ?? []).length;\n\n if (!removedFromPublic && !removedFromPrivate) return false;\n\n await Promise.all([\n removedFromPublic ? settingsManager.saveSettings({ ...settings, scenarios: publicFiltered }) : Promise.resolve(),\n removedFromPrivate ? settingsManager.savePrivateSettings({ ...priv, scenarios: privateFiltered }) : Promise.resolve(),\n ]);\n\n return true;\n }\n\n private normalizeScenario(scenario: Scenario): Scenario {\n const nodes = scenario.nodes.map((p) => normalizeNode(p));\n let leaderId = scenario.leaderId;\n if (!nodes.some((p) => p.id === leaderId)) {\n leaderId = nodes[0]?.id ?? leaderId;\n }\n\n return {\n ...scenario,\n leaderId,\n groups: scenario.groups ?? [],\n nodes,\n };\n }\n\n private validateHierarchy(scenario: Scenario): void {\n const groupIds = new Set<string>();\n for (const group of scenario.groups) {\n if (groupIds.has(group.id)) {\n throw new Error(`Duplicate group id: ${group.id}`);\n }\n groupIds.add(group.id);\n }\n\n const nodeIds = new Set<string>();\n for (const node of scenario.nodes) {\n if (nodeIds.has(node.id)) {\n throw new Error(`Duplicate node id: ${node.id}`);\n }\n nodeIds.add(node.id);\n }\n\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n if (!nodesById.has(scenario.leaderId)) {\n throw new Error('Leader must be a valid node in the scenario');\n }\n\n for (const node of scenario.nodes) {\n for (const pid of (node.parentIds ?? [])) {\n if (!nodesById.has(pid)) {\n throw new Error(`Node ${node.id} references unknown parent ${pid}`);\n }\n if (node.id === pid) {\n throw new Error(`Node ${node.id} cannot be their own parent`);\n }\n }\n if (node.groupId && !groupIds.has(node.groupId)) {\n throw new Error(`Node ${node.id} references unknown group ${node.groupId}`);\n }\n }\n\n const visited = new Set<string>();\n const inPath = new Set<string>();\n\n const walk = (nodeId: string): void => {\n if (inPath.has(nodeId)) throw new Error('Scenario hierarchy contains a cycle');\n if (visited.has(nodeId)) return;\n inPath.add(nodeId);\n const node = nodesById.get(nodeId);\n for (const pid of (node?.parentIds ?? [])) walk(pid);\n inPath.delete(nodeId);\n visited.add(nodeId);\n };\n\n for (const p of scenario.nodes) walk(p.id);\n }\n}\n\nexport const scenarioStore = new ScenarioStore();\n","import { mkdir, rm, readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { Scenario } from '@runeya/packages-shared';\nimport {\n atomicWriteJsonSecure,\n atomicWriteSecure,\n readJsonFileSafe,\n resolveConversationRunDir,\n} from './run-store-utils.js';\n\nfunction sanitizeSlug(value: string): string {\n return value\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 60) || 'member';\n}\n\nfunction sanitizeFilePart(value: string, fallback: string): string {\n const sanitized = value\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return sanitized || fallback;\n}\n\nexport type NodeState = 'idle' | 'running' | 'waiting' | 'waiting_input' | 'done' | 'synthesized' | 'error';\n\nexport interface RunState {\n nodeStates: Record<string, NodeState>;\n nodeOutputs: Record<string, string>;\n activeNodeId?: string;\n waitingInputs: Record<string, string>;\n}\n\nexport interface PersistedRunState {\n nodeStates: Record<string, NodeState>;\n nodeOutputs: Record<string, string>;\n waitingInputs?: Record<string, string>;\n}\n\nclass ScenarioRunStore {\n private static readonly SCENARIO_SNAPSHOT_FILE = 'SCENARIO.json';\n private activeRuns = new Map<string, RunState>();\n\n private getRunDir(conversationId: string): string {\n return resolveConversationRunDir('scenario-runs', conversationId);\n }\n\n async initializeConversationWorkspace(conversationId: string, scenario: Scenario, userInput: string): Promise<void> {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n await this.saveScenarioSnapshot(conversationId, scenario);\n\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n\n const teamMap = new Map(scenario.groups.map((t) => [t.id, t.name]));\n const leader = nodesById.get(scenario.leaderId) ?? scenario.nodes[0];\n\n const overview = [\n `# Scenario Conversation Workspace`,\n '',\n `- Scenario: ${scenario.name}`,\n `- Conversation ID: ${conversationId}`,\n `- Leader: ${leader?.label ?? ''}`,\n '',\n '## Members',\n ...scenario.nodes.map((p) => {\n const parent = p.parentIds[0] ? nodesById.get(p.parentIds[0]) : null;\n const group = p.groupId ? (teamMap.get(p.groupId) ?? p.groupId) : 'No group';\n return `- ${p.label} (${p.id}) | Group: ${group} | Reports to: ${parent ? parent.label : 'None'}`;\n }),\n '',\n '## Rules',\n '- Every node writes in their own markdown file.',\n '- Responses should be sent back to the requester.',\n '- Use read-only references from linked upstream files as context.',\n '',\n ].join('\\n');\n\n await atomicWriteSecure(join(dir, 'README.md'), overview);\n await atomicWriteSecure(join(dir, 'USER_REQUEST.md'), `# User request\\n\\n${userInput.trim() || '(empty)'}\\n`);\n\n for (const node of scenario.nodes) {\n const nodeName = node.label.trim();\n const safeNodeId = sanitizeFilePart(node.id, 'node');\n const fileName = `${sanitizeSlug(nodeName || node.id)}_${safeNodeId}.md`;\n const parent = node.parentIds[0] ? nodesById.get(node.parentIds[0]) : null;\n const reports = scenario.nodes.filter((p) => p.parentIds[0] === node.id);\n const teamName = node.groupId ? (teamMap.get(node.groupId) ?? node.groupId) : 'No group';\n const content = [\n `# ${nodeName || node.id}`,\n '',\n `- ID: ${node.id}`,\n `- Group: ${teamName}`,\n `- Reports to: ${parent ? parent.label : 'None'}`,\n `- Manages: ${reports.length ? reports.map((r) => r.label).join(', ') : 'No direct reports'}`,\n '',\n '## Prompt',\n node.prompt || '(No prompt defined)',\n '',\n '## Work Log',\n '- Waiting for assignment.',\n '',\n ].join('\\n');\n await atomicWriteSecure(join(dir, fileName), content);\n }\n }\n\n async deleteRunDir(conversationId: string): Promise<void> {\n await rm(this.getRunDir(conversationId), { recursive: true, force: true });\n this.activeRuns.delete(conversationId);\n }\n\n private ensureRunState(conversationId: string): RunState {\n let runState = this.activeRuns.get(conversationId);\n if (!runState) {\n runState = { nodeStates: {}, nodeOutputs: {}, waitingInputs: {} };\n this.activeRuns.set(conversationId, runState);\n }\n return runState;\n }\n\n setNodeState(conversationId: string, nodeId: string, state: NodeState): void {\n this.ensureRunState(conversationId).nodeStates[nodeId] = state;\n }\n\n setNodeOutput(conversationId: string, nodeId: string, output: string): void {\n this.ensureRunState(conversationId).nodeOutputs[nodeId] = output;\n }\n\n setActiveNodeId(conversationId: string, nodeId?: string): void {\n this.ensureRunState(conversationId).activeNodeId = nodeId;\n }\n\n setWaitingInput(conversationId: string, nodeId: string, question: string): void {\n this.ensureRunState(conversationId).waitingInputs[nodeId] = question;\n }\n\n clearWaitingInput(conversationId: string, nodeId: string): void {\n const runState = this.activeRuns.get(conversationId);\n if (runState?.waitingInputs) delete runState.waitingInputs[nodeId];\n }\n\n getRunState(conversationId: string): RunState | null {\n return this.activeRuns.get(conversationId) ?? null;\n }\n\n async persistRunState(conversationId: string): Promise<void> {\n const runState = this.activeRuns.get(conversationId);\n if (!runState) return;\n try {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n const data: PersistedRunState = {\n nodeStates: { ...runState.nodeStates },\n nodeOutputs: { ...runState.nodeOutputs },\n ...(Object.keys(runState.waitingInputs).length > 0 ? { waitingInputs: { ...runState.waitingInputs } } : {}),\n };\n await atomicWriteJsonSecure(join(dir, 'run-state.json'), data);\n } catch {\n // Non-fatal\n }\n }\n\n async loadPersistedRunState(conversationId: string): Promise<PersistedRunState | null> {\n const dir = this.getRunDir(conversationId);\n return readJsonFileSafe<PersistedRunState>(join(dir, 'run-state.json'));\n }\n\n async readUserRequest(conversationId: string): Promise<string | null> {\n try {\n const dir = this.getRunDir(conversationId);\n const content = await readFile(join(dir, 'USER_REQUEST.md'), 'utf-8');\n return content.replace(/^#\\s*User request\\s*\\n+/, '').trim() || null;\n } catch {\n return null;\n }\n }\n\n async readReadme(conversationId: string): Promise<string | null> {\n try {\n const dir = this.getRunDir(conversationId);\n return await readFile(join(dir, 'README.md'), 'utf-8');\n } catch {\n return null;\n }\n }\n\n async saveScenarioSnapshot(conversationId: string, scenario: Scenario): Promise<void> {\n const dir = this.getRunDir(conversationId);\n await mkdir(dir, { recursive: true });\n await atomicWriteJsonSecure(\n join(dir, ScenarioRunStore.SCENARIO_SNAPSHOT_FILE),\n scenario,\n true,\n );\n }\n\n async loadScenarioSnapshot(conversationId: string): Promise<Scenario | null> {\n const dir = this.getRunDir(conversationId);\n return readJsonFileSafe<Scenario>(join(dir, ScenarioRunStore.SCENARIO_SNAPSHOT_FILE));\n }\n}\n\nexport const scenarioRunStore = new ScenarioRunStore();\n","import { chmod, mkdir, rename, writeFile } from 'node:fs/promises';\nimport { dirname, resolve, sep } from 'node:path';\nimport { env } from '../config/env.js';\nimport { readFile } from 'node:fs/promises';\n\nconst SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/;\n\nexport function resolveConversationRunDir(rootDirName: string, conversationId: string): string {\n if (!SAFE_PATH_SEGMENT_RE.test(conversationId)) {\n throw new Error('Invalid conversationId');\n }\n const base = resolve(env.DATA_DIR, rootDirName);\n const dir = resolve(base, conversationId);\n if (!dir.startsWith(base + sep)) {\n throw new Error('Invalid conversationId');\n }\n return dir;\n}\n\nexport async function atomicWriteSecure(filePath: string, content: string): Promise<void> {\n await mkdir(dirname(filePath), { recursive: true });\n const tmpPath = `${filePath}.tmp`;\n await writeFile(tmpPath, content, 'utf-8');\n await rename(tmpPath, filePath);\n await chmod(filePath, 0o600);\n}\n\nexport async function atomicWriteJsonSecure(filePath: string, data: unknown, pretty = false): Promise<void> {\n await atomicWriteSecure(filePath, JSON.stringify(data, null, pretty ? 2 : 0));\n}\n\nexport async function readJsonFileSafe<T>(filePath: string): Promise<T | null> {\n try {\n const raw = await readFile(filePath, 'utf-8');\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport type { AIProvider } from '@runeya/packages-shared';\nimport { settingsManager } from './settings-manager.js';\nimport { decryptValue } from './crypto-helpers.js';\n\nexport const OPENAI_COMPAT_BASE_URLS: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n groq: 'https://api.groq.com/openai/v1',\n mistral: 'https://api.mistral.ai/v1',\n ollama: 'http://localhost:11434/v1',\n};\n\nexport const DEFAULT_MODELS: Record<string, string> = {\n anthropic: 'claude-opus-4-6',\n openai: 'gpt-4o',\n groq: 'llama-3.3-70b-versatile',\n mistral: 'mistral-large-latest',\n ollama: 'llama3',\n};\n\nexport async function getActiveProvider(providerId?: string): Promise<{ provider: AIProvider; plaintextKey: string } | null> {\n const priv = await settingsManager.getPrivateSettings();\n const providers = priv.aiProviders ?? [];\n const selected = providerId\n ? providers.find((p: AIProvider) => p.id === providerId)\n : providers.find((p: AIProvider) => p.active);\n if (!selected) return null;\n const plaintextKey = selected.encryptedApiKey ? decryptValue(selected.encryptedApiKey) : '';\n return { provider: selected, plaintextKey };\n}\n\nexport async function fetchProviderModels(provider: AIProvider, plaintextKey: string): Promise<string[]> {\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.models.list();\n return res.data.map(m => m.id).sort();\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.models.list();\n return res.data.map(m => m.id).sort();\n }\n\n return [];\n}\n","import { randomUUID } from 'node:crypto';\nimport { mkdir, writeFile, readFile, unlink, readdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, extname, resolve, sep } from 'node:path';\n\nexport const ALLOWED_MIME_TYPES = new Set([\n 'image/png',\n 'image/jpeg',\n 'image/webp',\n 'image/gif',\n]);\n\nconst ALLOWED_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.webp', '.gif']);\nexport const MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024; // 5 MB\nexport const IMAGE_TTL_MS = 24 * 60 * 60 * 1000; // 24h\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport interface StoredImage {\n imageId: string;\n filePath: string;\n mimeType: string;\n originalName: string;\n createdAt: number;\n /** Optional tag for grouping (e.g. conversationId, kanban cardId) */\n contextId?: string;\n}\n\nexport class ImageStorageService {\n private dir: string;\n\n constructor(dir: string) {\n this.dir = dir;\n }\n\n async ensureTmpDir(): Promise<void> {\n await mkdir(this.dir, { recursive: true, mode: 0o700 });\n }\n\n async saveImage(buffer: Buffer, originalName: string, mimeType: string, contextId?: string): Promise<StoredImage> {\n if (!ALLOWED_MIME_TYPES.has(mimeType)) {\n throw new Error(`Unsupported MIME type: ${mimeType}. Allowed: ${[...ALLOWED_MIME_TYPES].join(', ')}`);\n }\n if (buffer.length > MAX_IMAGE_SIZE_BYTES) {\n throw new Error(`Image too large: ${buffer.length} bytes (max ${MAX_IMAGE_SIZE_BYTES})`);\n }\n if (!checkMagicBytes(buffer, mimeType)) {\n throw new Error('File content does not match declared MIME type');\n }\n\n const ext = extname(originalName).toLowerCase() || mimeToExt(mimeType);\n if (!ALLOWED_EXTENSIONS.has(ext)) {\n throw new Error(`Unsupported extension: ${ext}`);\n }\n\n await this.ensureTmpDir();\n\n const imageId = randomUUID();\n const safeExt = ext.replace(/[^a-z.]/g, '');\n const fileName = `${imageId}${safeExt}`;\n const filePath = join(this.dir, fileName);\n const resolvedPath = resolve(filePath);\n const resolvedDir = resolve(this.dir);\n if (resolvedPath !== resolvedDir && !resolvedPath.startsWith(resolvedDir + sep)) {\n throw new Error('Invalid file path');\n }\n\n await writeFile(filePath, buffer, { mode: 0o600 });\n const meta: StoredImage = { imageId, filePath, mimeType, originalName, createdAt: Date.now(), contextId };\n await writeFile(`${filePath}.meta.json`, JSON.stringify(meta), { encoding: 'utf-8', mode: 0o600 });\n return meta;\n }\n\n async getImagePath(imageId: string): Promise<{ filePath: string; mimeType: string } | null> {\n if (!UUID_RE.test(imageId)) return null;\n try {\n const files = await readdir(this.dir);\n const metaFile = files.find(f => f.startsWith(imageId) && f.endsWith('.meta.json'));\n if (!metaFile) return null;\n const raw = JSON.parse(await readFile(join(this.dir, metaFile), 'utf-8')) as StoredImage;\n if (!existsSync(raw.filePath)) return null;\n return { filePath: raw.filePath, mimeType: raw.mimeType };\n } catch {\n return null;\n }\n }\n\n async deleteImage(imageId: string): Promise<void> {\n const result = await this.getImagePath(imageId);\n if (!result) return;\n await unlink(result.filePath).catch(() => {});\n await unlink(`${result.filePath}.meta.json`).catch(() => {});\n }\n\n async deleteByContextId(contextId: string): Promise<void> {\n let files: string[];\n try {\n files = await readdir(this.dir);\n } catch {\n return;\n }\n await Promise.all(\n files\n .filter(f => f.endsWith('.meta.json'))\n .map(async (file) => {\n try {\n const raw = JSON.parse(await readFile(join(this.dir, file), 'utf-8')) as StoredImage;\n if (raw.contextId === contextId) {\n await unlink(raw.filePath).catch(() => {});\n await unlink(`${raw.filePath}.meta.json`).catch(() => {});\n }\n } catch {\n // skip malformed\n }\n }),\n );\n }\n\n async readImageAsBase64(imageId: string): Promise<{ base64: string; mimeType: string } | null> {\n const result = await this.getImagePath(imageId);\n if (!result) return null;\n const buffer = await readFile(result.filePath);\n return { base64: buffer.toString('base64'), mimeType: result.mimeType };\n }\n\n async listExpiredImages(ttlMs = IMAGE_TTL_MS): Promise<StoredImage[]> {\n const expired: StoredImage[] = [];\n let files: string[];\n try {\n files = await readdir(this.dir);\n } catch {\n return [];\n }\n const now = Date.now();\n for (const file of files) {\n if (!file.endsWith('.meta.json')) continue;\n try {\n const raw = JSON.parse(await readFile(join(this.dir, file), 'utf-8')) as StoredImage;\n if (now - raw.createdAt > ttlMs) expired.push(raw);\n } catch {\n // skip malformed\n }\n }\n return expired;\n }\n}\n\nlet _singleton: ImageStorageService | undefined;\nfunction getSingleton(): ImageStorageService {\n if (!_singleton) {\n const dataDir = process.env['DATA_DIR'] ?? '.runeya';\n _singleton = new ImageStorageService(resolve(dataDir, 'images'));\n }\n return _singleton;\n}\nexport const imageStorageService = new Proxy({} as ImageStorageService, {\n get(_target, prop: string | symbol) {\n const svc = getSingleton();\n const val = (svc as unknown as Record<string | symbol, unknown>)[prop];\n return typeof val === 'function' ? (val as (...args: unknown[]) => unknown).bind(svc) : val;\n },\n});\n\nfunction checkMagicBytes(buf: Buffer, mime: string): boolean {\n if (buf.length < 12) return false;\n switch (mime) {\n case 'image/png':\n return buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47;\n case 'image/jpeg':\n return buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF;\n case 'image/gif':\n return buf.slice(0, 6).toString('ascii') === 'GIF87a' || buf.slice(0, 6).toString('ascii') === 'GIF89a';\n case 'image/webp':\n return buf.slice(0, 4).toString('ascii') === 'RIFF' && buf.slice(8, 12).toString('ascii') === 'WEBP';\n default:\n return false;\n }\n}\n\nfunction mimeToExt(mime: string): string {\n const map: Record<string, string> = {\n 'image/png': '.png',\n 'image/jpeg': '.jpg',\n 'image/webp': '.webp',\n 'image/gif': '.gif',\n };\n return map[mime] ?? '.bin';\n}\n","import { imageStorageService } from './image-storage.service.js';\n\nexport interface MessageImageRef {\n imageId: string;\n mimeType: string;\n altText?: string;\n}\n\n/**\n * Extracts all image parts from a message's parts array.\n * Parts come from the stored conversation messages.\n */\nexport function extractImagesFromMessage(parts: Array<{ type: string; [key: string]: unknown }>): MessageImageRef[] {\n const images: MessageImageRef[] = [];\n for (const part of parts) {\n if (\n part['type'] === 'image' &&\n typeof part['imageId'] === 'string' &&\n typeof part['mimeType'] === 'string'\n ) {\n images.push({\n imageId: part['imageId'] as string,\n mimeType: part['mimeType'] as string,\n altText: typeof part['altText'] === 'string' ? part['altText'] : undefined,\n });\n }\n }\n return images;\n}\n\n/**\n * Resolves a single image ref to base64, returning null if not found.\n */\nexport async function resolveImageToBase64(\n imageId: string,\n): Promise<{ base64: string; mimeType: string } | null> {\n return imageStorageService.readImageAsBase64(imageId);\n}\n\n/**\n * Resolves all image refs to base64, skipping missing ones (with a warning).\n */\nexport async function resolveImagesToBase64(\n images: MessageImageRef[],\n): Promise<Array<{ imageId: string; base64: string; mimeType: string; altText?: string }>> {\n const results = await Promise.all(\n images.map(async (img) => {\n const resolved = await imageStorageService.readImageAsBase64(img.imageId);\n if (!resolved) {\n console.warn('[message-images] Image not found (imageId redacted from log)');\n return null;\n }\n return { imageId: img.imageId, base64: resolved.base64, mimeType: resolved.mimeType, altText: img.altText };\n }),\n );\n return results.filter((r): r is NonNullable<typeof r> => r !== null);\n}\n","import { spawn } from 'node:child_process';\nimport { buildApiDocs } from './runeya-api-docs.js';\nimport { parseEndToken, TOKEN_INSTRUCTIONS } from './scenario-tokens.js';\nimport type { AiRunner, AiRunnerParams, NodeResult } from './ai-runner.js';\n\n// Lazy import to avoid pulling in env validation in test contexts\nasync function getAgentManager() {\n const { agentManager } = await import('../agent-manager.js');\n return agentManager;\n}\n\n// ─── Claude stream parser ──────────────────────────────────────────────────\n\ninterface ClaudeStreamState {\n fullContent: string;\n thinkingEmitted: boolean;\n textDeltaReceived: boolean;\n currentToolName: string;\n currentToolId: string;\n currentToolInputJson: string;\n toolInputAccumulator: Map<string, { name: string; json: string }>;\n actualSessionId: string | undefined;\n}\n\nfunction createClaudeStreamState(): ClaudeStreamState {\n return {\n fullContent: '',\n thinkingEmitted: false,\n textDeltaReceived: false,\n currentToolName: '',\n currentToolId: '',\n currentToolInputJson: '',\n toolInputAccumulator: new Map(),\n actualSessionId: undefined,\n };\n}\n\ninterface ClaudeStreamCallbacks {\n onDelta: (text: string) => void;\n onStatus: (text: string) => void;\n onThinking?: (text: string) => void;\n onToolCall?: (id: string, name: string, input: Record<string, unknown>) => void;\n onToolResult?: (id: string, name: string, result: string, isError: boolean) => void;\n onContextUsage?: (inputTokens: number, contextWindow: number) => void;\n onResult?: (result: string, sessionId: string | undefined, isError: boolean) => void;\n}\n\nfunction parseClaudeStreamLine(\n line: string,\n state: ClaudeStreamState,\n cb: ClaudeStreamCallbacks,\n): Record<string, unknown> | null {\n const trimmed = line.trim();\n if (!trimmed) return null;\n let event: Record<string, unknown>;\n try { event = JSON.parse(trimmed) as Record<string, unknown>; } catch { return null; }\n\n if (event['type'] === 'stream_event') {\n const ev = event['event'] as Record<string, unknown> | undefined;\n const evType = ev?.['type'];\n const delta = ev?.['delta'] as Record<string, unknown> | undefined;\n const contentBlock = ev?.['content_block'] as Record<string, unknown> | undefined;\n\n if (delta?.['type'] === 'thinking_delta' && typeof delta['thinking'] === 'string') {\n if (!state.thinkingEmitted) {\n state.thinkingEmitted = true;\n cb.onStatus('💭 En réflexion…');\n }\n cb.onThinking?.(delta['thinking'] as string);\n }\n\n if (evType === 'content_block_start' && contentBlock?.['type'] === 'tool_use') {\n state.currentToolName = typeof contentBlock['name'] === 'string' ? contentBlock['name'] : 'tool';\n state.currentToolId = typeof contentBlock['id'] === 'string' ? contentBlock['id'] : '';\n state.currentToolInputJson = '';\n if (state.currentToolId) {\n state.toolInputAccumulator.set(state.currentToolId, { name: state.currentToolName, json: '' });\n }\n cb.onStatus(`🔧 ${state.currentToolName}`);\n }\n\n if (delta?.['type'] === 'input_json_delta' && typeof delta['partial_json'] === 'string') {\n state.currentToolInputJson += delta['partial_json'] as string;\n if (state.currentToolId) {\n const acc = state.toolInputAccumulator.get(state.currentToolId);\n if (acc) acc.json = state.currentToolInputJson;\n }\n }\n\n if (evType === 'content_block_stop' && state.currentToolId && state.toolInputAccumulator.has(state.currentToolId)) {\n const acc = state.toolInputAccumulator.get(state.currentToolId)!;\n let parsedInput: Record<string, unknown> = {};\n try { parsedInput = JSON.parse(acc.json || '{}') as Record<string, unknown>; } catch { /* keep empty */ }\n cb.onToolCall?.(state.currentToolId, acc.name, parsedInput);\n state.currentToolId = '';\n state.currentToolInputJson = '';\n }\n\n if (delta?.['type'] === 'text_delta' && typeof delta['text'] === 'string') {\n state.textDeltaReceived = true;\n state.thinkingEmitted = false;\n state.fullContent += delta['text'];\n cb.onStatus('');\n cb.onDelta(delta['text']);\n }\n\n if (evType === 'message_start') {\n const msg = ev?.['message'] as Record<string, unknown> | undefined;\n const usage = msg?.['usage'] as Record<string, unknown> | undefined;\n if (usage && typeof usage['input_tokens'] === 'number' && cb.onContextUsage) {\n const inputTokens = (usage['input_tokens'] as number)\n + (typeof usage['cache_read_input_tokens'] === 'number' ? usage['cache_read_input_tokens'] : 0)\n + (typeof usage['cache_creation_input_tokens'] === 'number' ? usage['cache_creation_input_tokens'] : 0);\n const modelName = typeof msg?.['model'] === 'string' ? msg['model'] : '';\n const contextWindow = /claude-instant/i.test(modelName) ? 100_000 : 200_000;\n cb.onContextUsage(inputTokens, contextWindow);\n }\n }\n }\n\n if (event['type'] === 'user') {\n const msg = event['message'] as Record<string, unknown> | undefined;\n const content = msg?.['content'];\n const blocks = Array.isArray(content) ? content as Record<string, unknown>[] : [];\n for (const block of blocks) {\n if (block['type'] === 'tool_result' && typeof block['tool_use_id'] === 'string') {\n const id = block['tool_use_id'] as string;\n const isError = block['is_error'] === true;\n const blockContent = block['content'];\n let result = '';\n if (typeof blockContent === 'string') {\n result = blockContent;\n } else if (Array.isArray(blockContent)) {\n result = (blockContent as Record<string, unknown>[])\n .filter(b => b['type'] === 'text')\n .map(b => b['text'] as string)\n .join('');\n }\n const toolName = state.toolInputAccumulator.get(id)?.name ?? '';\n cb.onToolResult?.(id, toolName, result, isError);\n }\n }\n }\n\n if (event['type'] === 'result') {\n if (typeof event['session_id'] === 'string' && event['session_id']) {\n state.actualSessionId = event['session_id'];\n }\n const isError = event['is_error'] === true;\n const resultText = typeof event['result'] === 'string' ? event['result'] : '';\n if (!state.textDeltaReceived && resultText) {\n state.fullContent += resultText;\n cb.onStatus('');\n cb.onDelta(resultText);\n }\n cb.onResult?.(resultText, state.actualSessionId, isError);\n }\n\n return event;\n}\n\nconst EFFORT_THINKING_BUDGET: Record<string, number> = {\n low: 0,\n normal: 5000,\n high: 10000,\n};\n\n/** Build CLI args, env, and stdinData from runner params. Shared by runLocal and runViaAgent.\n * When `excludeMcp` is true, omit --mcp-config from args (agent builds it locally). */\nfunction buildClaudeSpawnConfig(params: AiRunnerParams, opts?: { excludeMcp?: boolean }) {\n const { sessionId, prompt, isResume, systemContext, apiBaseUrl, apiToken, model, effort, images, mcpConfig, skipTokenInstructions } = params;\n\n const hasImages = images && images.length > 0;\n const sessionArg = isResume\n ? ['--resume', sessionId]\n : (sessionId ? ['--session-id', sessionId] : []);\n\n const thinkingBudget = EFFORT_THINKING_BUDGET[effort] ?? 0;\n const thinkingArgs = thinkingBudget > 0 ? ['--thinking', 'enabled'] : [];\n\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const fullSystemContext = apiDocs ? `${systemContext}\\n\\n${apiDocs}` : systemContext;\n const systemPrompt = skipTokenInstructions\n ? fullSystemContext\n : `${fullSystemContext}\\n\\n${TOKEN_INSTRUCTIONS}`;\n\n const inputArgs = hasImages\n ? ['--input-format', 'stream-json']\n : ['-p', prompt];\n\n const mcpArgs = (mcpConfig && !opts?.excludeMcp) ? ['--mcp-config', mcpConfig] : [];\n\n const args = [\n ...sessionArg,\n '--output-format', 'stream-json',\n '--verbose',\n '--include-partial-messages',\n '--dangerously-skip-permissions',\n '--model', model,\n ...thinkingArgs,\n '--append-system-prompt', systemPrompt,\n ...mcpArgs,\n ...inputArgs,\n ];\n\n // Env: unset CLAUDECODE, pass apiToken via env var\n const env: Record<string, string> = {\n ...Object.fromEntries(Object.entries(process.env).filter(([k]) => k !== 'CLAUDECODE')) as Record<string, string>,\n ...(apiToken ? { RUNEYA_API_TOKEN: apiToken } : {}),\n };\n\n // Build stdin data for images\n let stdinData: string | undefined;\n if (hasImages) {\n const contentBlocks: unknown[] = [{ type: 'text', text: prompt }];\n for (const img of images!) {\n contentBlocks.push({\n type: 'image',\n source: { type: 'base64', media_type: img.mimeType, data: img.base64 },\n });\n }\n stdinData = JSON.stringify({ role: 'user', content: contentBlocks }) + '\\n';\n }\n\n return { args, env, stdinData, sessionArg, hasImages };\n}\n\n/** Mutable state shared across stdout processing calls. */\ninterface ClaudeProcessingCtx {\n settled: boolean;\n earlyResult: NodeResult | null;\n lastResultError: string;\n rawStdoutLines: string[];\n}\n\n/** Process raw stdout lines from the claude CLI stream. Shared by runLocal and runViaAgent. */\nfunction processClaudeStdoutLines(\n lines: string[],\n streamState: ClaudeStreamState,\n params: AiRunnerParams,\n ctx: ClaudeProcessingCtx,\n): void {\n const { onDelta, onStatus, onThinking, onToolCall, onToolResult, skipTokenInstructions } = params;\n\n const settle = (result: NodeResult) => {\n if (ctx.settled) return;\n ctx.settled = true;\n ctx.earlyResult = result;\n // For local runs, don't remove abort listener here — let the process finish\n // to capture actualSessionId from the result event.\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n ctx.rawStdoutLines.push(trimmed);\n if (ctx.rawStdoutLines.length > 50) ctx.rawStdoutLines.shift();\n\n if (ctx.settled) {\n try {\n const ev = JSON.parse(trimmed) as Record<string, unknown>;\n if (ev['type'] === 'result' && typeof ev['session_id'] === 'string') {\n streamState.actualSessionId = ev['session_id'];\n }\n if (ev['type'] === 'result' && ev['is_error'] === true) {\n const errMsg = typeof ev['error'] === 'string' ? ev['error']\n : typeof (ev['error'] as Record<string, unknown>)?.['message'] === 'string' ? (ev['error'] as Record<string, unknown>)['message'] as string : '';\n if (errMsg) ctx.lastResultError = errMsg.slice(-2000);\n }\n } catch { /* ignore */ }\n continue;\n }\n\n const event = parseClaudeStreamLine(line, streamState, {\n onDelta: (text) => {\n onDelta(text);\n if (!skipTokenInstructions) {\n const { status, message, branchChoice } = parseEndToken(streamState.fullContent);\n if (status !== 'none') {\n settle({ output: streamState.fullContent, tokenStatus: status, tokenMessage: message, branchChoice, actualSessionId: streamState.actualSessionId });\n }\n }\n },\n onStatus,\n onThinking,\n onToolCall: (id, name, input) => onToolCall?.(id, name, input),\n onToolResult: (id, _name, result, isError) => onToolResult?.(id, result, isError),\n onContextUsage: params.onContextUsage,\n onResult: (result, _sessionId, isError) => {\n if (isError) {\n const errMsg = typeof result === 'string' ? result : '';\n if (errMsg) ctx.lastResultError = errMsg.slice(-2000);\n }\n if (result) params.onResult?.(result);\n },\n });\n\n if (!event) {\n if (!ctx.lastResultError) ctx.lastResultError = trimmed.slice(-2000);\n }\n }\n}\n\nexport class ClaudeCodeRunner implements AiRunner {\n run(params: AiRunnerParams): Promise<NodeResult> {\n if (params.agentId) {\n return this.runViaAgent(params);\n }\n return this.runLocal(params);\n }\n\n // ── Run via agent (remote spawn, local parsing) ─────────────────────────\n\n private async runViaAgent(params: AiRunnerParams): Promise<NodeResult> {\n const { agentId, signal, skipTokenInstructions } = params;\n const { args, env, stdinData, sessionArg } = buildClaudeSpawnConfig(params, { excludeMcp: true });\n const agentMgr = await getAgentManager();\n\n const totalArgSize = args.reduce((s, a) => s + a.length + 1, 0);\n console.log(`[claude-code-runner] [agent:${agentId}] arg size: ${totalArgSize} bytes, session: ${sessionArg.join(' ')}, images: ${params.images?.length ?? 0}`);\n const displayArgs = args.map(a => {\n if (a === params.prompt) return '<prompt>';\n if (a.includes(TOKEN_INSTRUCTIONS)) return '<system-context>';\n return a;\n });\n params.onCommand?.(`claude ${displayArgs.join(' ')}`);\n\n return new Promise<NodeResult>((resolve, reject) => {\n const streamState = createClaudeStreamState();\n const ctx: ClaudeProcessingCtx = { settled: false, earlyResult: null, lastResultError: '', rawStdoutLines: [] };\n let stdoutBuffer = '';\n let stderrBuffer = '';\n let spawnId: string | null = null;\n let unsubscribe: (() => void) | null = null;\n\n const onAbort = () => {\n if (spawnId && agentId) {\n agentMgr.agentMutation(agentId, 'ai.kill', { spawnId }).catch(() => { /* best-effort */ });\n }\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n const cleanup = () => {\n signal.removeEventListener('abort', onAbort);\n if (unsubscribe) { unsubscribe(); unsubscribe = null; }\n };\n\n // Step 1: spawn on agent\n agentMgr.agentMutation<{ spawnId: string }>(agentId!, 'ai.spawn', {\n cli: 'claude',\n args,\n env,\n stdinData,\n enableMcp: !!params.mcpConfig,\n mcpApiBaseUrl: params.apiBaseUrl || undefined,\n }).then(({ spawnId: id }) => {\n spawnId = id;\n if (signal.aborted) {\n cleanup();\n reject(new Error('Aborted'));\n return;\n }\n\n // Step 2: subscribe to stream\n unsubscribe = agentMgr.agentSubscribe(\n agentId!,\n 'ai.stream',\n { spawnId, fromOffset: 0 },\n (data: unknown) => {\n const item = data as { offset: number; chunk: { type: string; data: string; code?: number } };\n const chunk = item.chunk;\n\n if (chunk.type === 'stdout') {\n stdoutBuffer += chunk.data;\n const lines = stdoutBuffer.split('\\n');\n stdoutBuffer = lines.pop() ?? '';\n processClaudeStdoutLines(lines, streamState, params, ctx);\n }\n\n if (chunk.type === 'stderr') {\n stderrBuffer += chunk.data;\n }\n\n if (chunk.type === 'exit') {\n const code = chunk.code ?? 0;\n cleanup();\n\n if (ctx.earlyResult) {\n resolve({ ...ctx.earlyResult, actualSessionId: streamState.actualSessionId });\n return;\n }\n\n if (signal.aborted) { reject(new Error('Aborted')); return; }\n if (code !== 0 && !streamState.fullContent) {\n const stderr = stderrBuffer.trim().slice(-2000);\n const rawStdout = ctx.rawStdoutLines.slice(-10).join('\\n').trim();\n console.error(`[claude-code-runner] [agent] exit code ${code} | stderr: ${stderr || '(empty)'} | last stdout lines: ${rawStdout || '(empty)'}`);\n const detail = ctx.lastResultError || stderr || rawStdout;\n reject(new Error(`Claude Code exited with code ${code}${detail ? `: ${detail}` : ''}`));\n return;\n }\n const { status, message, branchChoice } = skipTokenInstructions\n ? { status: 'none' as const, message: '', branchChoice: undefined }\n : parseEndToken(streamState.fullContent);\n resolve({ output: streamState.fullContent, tokenStatus: status, tokenMessage: message, branchChoice, actualSessionId: streamState.actualSessionId });\n }\n },\n () => {\n // onStop — subscription ended without exit event (WS disconnect)\n // Don't resolve/reject: the spawn continues on the agent.\n // The caller (chat/scenario) should handle reconnection.\n },\n );\n }).catch((err) => {\n cleanup();\n reject(new Error(`Failed to spawn claude on agent: ${(err as Error).message}`));\n });\n });\n }\n\n // ── Run locally (original implementation) ───────────────────────────────\n\n private runLocal(params: AiRunnerParams): Promise<NodeResult> {\n const { signal, skipTokenInstructions } = params;\n const { args, env, stdinData, sessionArg, hasImages } = buildClaudeSpawnConfig(params);\n\n return new Promise<NodeResult>((resolve, reject) => {\n const totalArgSize = args.reduce((s, a) => s + a.length + 1, 0);\n console.log(`[claude-code-runner] arg size: ${totalArgSize} bytes (${(totalArgSize / 1024 / 1024).toFixed(2)} MB), session: ${sessionArg.join(' ')}, images: ${params.images?.length ?? 0}`);\n const displayArgs = args.map(a => {\n if (a === params.prompt) return '<prompt>';\n if (a.includes(TOKEN_INSTRUCTIONS)) return '<system-context>';\n return a;\n });\n params.onCommand?.(`claude ${displayArgs.join(' ')}`);\n const proc = spawn('claude', args, {\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: false,\n env,\n });\n\n if (stdinData) {\n proc.stdin!.write(stdinData);\n proc.stdin!.end();\n } else {\n proc.stdin!.end();\n }\n\n const streamState = createClaudeStreamState();\n const ctx: ClaudeProcessingCtx = { settled: false, earlyResult: null, lastResultError: '', rawStdoutLines: [] };\n let stdoutBuffer = '';\n\n const onAbort = () => {\n try { proc.kill('SIGTERM'); } catch { /* ignore */ }\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n let stderrBuffer = '';\n\n proc.stdout!.on('data', (chunk: Buffer) => {\n stdoutBuffer += chunk.toString('utf-8');\n const lines = stdoutBuffer.split('\\n');\n stdoutBuffer = lines.pop() ?? '';\n processClaudeStdoutLines(lines, streamState, params, ctx);\n });\n\n proc.stderr!.on('data', (chunk: Buffer) => { stderrBuffer += chunk.toString('utf-8'); });\n\n proc.on('close', (code) => {\n if (ctx.earlyResult) { resolve({ ...ctx.earlyResult, actualSessionId: streamState.actualSessionId }); return; }\n\n signal.removeEventListener('abort', onAbort);\n if (signal.aborted) { reject(new Error('Aborted')); return; }\n if (code !== 0 && !streamState.fullContent) {\n const stderr = stderrBuffer.trim().slice(-2000);\n const rawStdout = ctx.rawStdoutLines.slice(-10).join('\\n').trim();\n console.error(`[claude-code-runner] exit code ${code} | stderr: ${stderr || '(empty)'} | last stdout lines: ${rawStdout || '(empty)'}`);\n const detail = ctx.lastResultError || stderr || rawStdout;\n reject(new Error(`Claude Code exited with code ${code}${detail ? `: ${detail}` : ''}`));\n return;\n }\n const { status, message, branchChoice } = skipTokenInstructions\n ? { status: 'none' as const, message: '', branchChoice: undefined }\n : parseEndToken(streamState.fullContent);\n resolve({ output: streamState.fullContent, tokenStatus: status, tokenMessage: message, branchChoice, actualSessionId: streamState.actualSessionId });\n });\n\n proc.on('error', (err) => {\n if (ctx.settled) return;\n signal.removeEventListener('abort', onAbort);\n reject(err);\n });\n });\n }\n}\n\n","import { RUNEYA_CAPABILITIES, buildPromptDocs } from '@runeya/packages-ai-capabilities';\n\nexport function buildApiDocs(apiBaseUrl: string, apiToken: string): string {\n return buildPromptDocs(apiBaseUrl, apiToken, RUNEYA_CAPABILITIES);\n}\n","// ─── Token-based node completion signals ──────────────────────────────────\n//\n// Shared between all runners (ClaudeCodeRunner, CodexRunner) and the scenario\n// runner orchestration layer. Not used in chat mode.\n\nexport function parseEndToken(output: string): { status: 'pass' | 'error' | 'ask_user' | 'none'; message: string; branchChoice?: number } {\n const tail = output.trimEnd().slice(-2000);\n\n // <pass branch=\"N\" />\n const branchMatch = tail.match(/<pass\\s+branch=\"(\\d+)\"\\s*\\/>/);\n if (branchMatch) {\n return { status: 'pass', message: '', branchChoice: parseInt(branchMatch[1], 10) };\n }\n\n // <pass />\n if (/<pass\\s*\\/>/.test(tail)) {\n return { status: 'pass', message: '' };\n }\n\n // <error>message</error>\n const errorMatch = tail.match(/<error>([\\s\\S]*?)<\\/error>/);\n if (errorMatch) {\n return { status: 'error', message: errorMatch[1].trim() };\n }\n\n // <ask_user>question</ask_user>\n const askMatch = tail.match(/<ask_user>([\\s\\S]*?)<\\/ask_user>/);\n if (askMatch) {\n return { status: 'ask_user', message: askMatch[1].trim() };\n }\n\n return { status: 'none', message: '' };\n}\n\nexport const TOKEN_INSTRUCTIONS = `\n## Instructions de signalisation (OBLIGATOIRE)\n\nÀ la fin de CHAQUE réponse, tu DOIS terminer par exactement l'un de ces tags XML :\n\n- Si tu as terminé avec succès (chemin par défaut) : \\`<pass />\\`\n- Si le nœud propose plusieurs branches de sortie numérotées : \\`<pass branch=\"1\" />\\`, \\`<pass branch=\"2\" />\\`, etc. (choisis la branche qui correspond le mieux au résultat)\n- Si tu as rencontré une erreur bloquante : \\`<error>description courte</error>\\`\n- Si tu es bloqué par une information que personne dans l'équipe ne peut fournir (secret, décision business, credential externe) : \\`<ask_user>ta question</ask_user>\\` — NE PAS utiliser pour demander une confirmation ou un accord (\"es-tu prêt ?\", \"puis-je continuer ?\")\n\nNe jamais omettre ce tag. Il doit être la toute dernière ligne de ta réponse.\n`.trim();\n\nconst RESUME_PROMPT_BRANCH_INVALID = (max: number) =>\n `Tu as répondu avec un tag de branche invalide. Tu dois choisir exactement l'un des tags : ` +\n Array.from({ length: max }, (_, i) => `\\`<pass branch=\"${i + 1}\" />\\``).join(', ') + `.`;\n\nconst RESUME_PROMPT_NO_TOKEN =\n \"Tu n'as pas terminé ta réponse par un tag d'action. \" +\n 'Indique maintenant ton statut avec exactement l\\'un de : ' +\n '`<pass />`, `<error>msg</error>`, ou `<ask_user>question</ask_user>`.';\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline';\nimport { EventEmitter } from 'node:events';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\ninterface JsonRpcRequest {\n jsonrpc?: '2.0';\n method: string;\n id?: number;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc?: '2.0';\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n}\n\ninterface JsonRpcNotification {\n jsonrpc?: '2.0';\n method: string;\n params?: Record<string, unknown>;\n}\n\ntype NotificationHandler = (method: string, params: Record<string, unknown>) => void;\n\ninterface PendingRequest {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\n// ─── Client ─────────────────────────────────────────────────────────────────\n\nexport class CodexAppServerClient extends EventEmitter {\n private proc: ChildProcess | null = null;\n private rl: ReadlineInterface | null = null;\n private nextId = 1;\n private pending = new Map<number, PendingRequest>();\n private notificationHandlers = new Map<string, NotificationHandler[]>();\n private catchAllHandlers: NotificationHandler[] = [];\n private requestTimeoutMs: number;\n\n constructor(opts?: { requestTimeoutMs?: number }) {\n super();\n this.requestTimeoutMs = opts?.requestTimeoutMs ?? 120_000;\n }\n\n /** Spawn codex app-server, perform initialize handshake, return server info. */\n async connect(): Promise<Record<string, unknown>> {\n this.proc = spawn('codex', ['app-server'], {\n stdio: ['pipe', 'pipe', 'pipe'],\n env: { ...process.env },\n });\n\n this.rl = createInterface({ input: this.proc.stdout! });\n this.rl.on('line', (line) => this.handleLine(line));\n\n this.proc.on('exit', (code, signal) => {\n this.rejectAllPending(new Error(`codex app-server exited (code=${code}, signal=${signal})`));\n this.emit('exit', code, signal);\n });\n\n this.proc.on('error', (err) => {\n this.rejectAllPending(err);\n this.emit('error', err);\n });\n\n // Initialize handshake\n const result = await this.sendRequest('initialize', {\n clientInfo: { name: 'runeya', title: 'Runeya', version: '1.0.0' },\n capabilities: { experimentalApi: false },\n }, 0) as Record<string, unknown>;\n\n // Send initialized notification\n this.sendNotification('initialized', {});\n\n return result;\n }\n\n /** Send a JSON-RPC request and return a promise for the result. */\n sendRequest(method: string, params?: Record<string, unknown>, forceId?: number): Promise<unknown> {\n const id = forceId ?? this.nextId++;\n // If forceId was used and equals nextId range, bump to avoid collision\n if (forceId !== undefined && forceId >= this.nextId) {\n this.nextId = forceId + 1;\n }\n\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n this.pending.delete(id);\n reject(new Error(`Request ${method} (id=${id}) timed out after ${this.requestTimeoutMs}ms`));\n }, this.requestTimeoutMs);\n\n this.pending.set(id, { resolve, reject, timer });\n this.writeLine({ jsonrpc: '2.0', method, id, params: params ?? {} });\n });\n }\n\n /** Send a JSON-RPC notification (no id, no response expected). */\n sendNotification(method: string, params: Record<string, unknown>): void {\n this.writeLine({ jsonrpc: '2.0', method, params });\n }\n\n /** Respond to a server-initiated request (e.g. approval workflow). */\n respond(id: number, result: unknown): void {\n this.writeLine({ jsonrpc: '2.0', id, result });\n }\n\n respondError(id: number, code: number, message: string): void {\n this.writeLine({ jsonrpc: '2.0', id, error: { code, message } });\n }\n\n /** Register a handler for a specific notification method. */\n onNotification(method: string, handler: NotificationHandler): void {\n const list = this.notificationHandlers.get(method) ?? [];\n list.push(handler);\n this.notificationHandlers.set(method, list);\n }\n\n /** Register a catch-all notification handler. */\n onAnyNotification(handler: NotificationHandler): void {\n this.catchAllHandlers.push(handler);\n }\n\n /** Gracefully shut down the child process. */\n async shutdown(): Promise<void> {\n if (!this.proc) return;\n this.rl?.close();\n this.rl = null;\n\n const proc = this.proc;\n this.proc = null;\n\n return new Promise<void>((resolve) => {\n proc.on('exit', () => resolve());\n proc.kill('SIGTERM');\n // Force kill after 5s\n const forceTimer = setTimeout(() => {\n proc.kill('SIGKILL');\n }, 5000);\n proc.on('exit', () => clearTimeout(forceTimer));\n });\n }\n\n // ─── Internal ───────────────────────────────────────────────────────────\n\n private writeLine(obj: Record<string, unknown>): void {\n if (!this.proc?.stdin?.writable) {\n throw new Error('codex app-server stdin not writable');\n }\n this.proc.stdin.write(JSON.stringify(obj) + '\\n');\n }\n\n private handleLine(line: string): void {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(trimmed);\n } catch {\n return; // ignore malformed lines\n }\n\n // Response to a pending request\n if ('id' in msg && typeof msg['id'] === 'number' && ('result' in msg || 'error' in msg)) {\n const pending = this.pending.get(msg['id'] as number);\n if (pending) {\n this.pending.delete(msg['id'] as number);\n clearTimeout(pending.timer);\n if ('error' in msg && msg['error']) {\n const err = msg['error'] as { code: number; message: string };\n pending.reject(new Error(`JSON-RPC error ${err.code}: ${err.message}`));\n } else {\n pending.resolve(msg['result']);\n }\n }\n return;\n }\n\n // Server-initiated request (has id + method, no result/error)\n if ('id' in msg && 'method' in msg && typeof msg['method'] === 'string') {\n this.emit('server-request', msg);\n return;\n }\n\n // Notification (method, no id)\n if ('method' in msg && typeof msg['method'] === 'string' && !('id' in msg)) {\n const method = msg['method'] as string;\n const params = (msg['params'] ?? {}) as Record<string, unknown>;\n\n const handlers = this.notificationHandlers.get(method);\n if (handlers) {\n for (const h of handlers) h(method, params);\n }\n for (const h of this.catchAllHandlers) h(method, params);\n }\n }\n\n private rejectAllPending(error: Error): void {\n for (const [id, pending] of this.pending) {\n clearTimeout(pending.timer);\n pending.reject(error);\n this.pending.delete(id);\n }\n }\n}\n","import { buildApiDocs } from './runeya-api-docs.js';\nimport { parseEndToken, TOKEN_INSTRUCTIONS } from './scenario-tokens.js';\nimport type { AiRunner, AiRunnerParams, NodeResult } from './ai-runner.js';\nimport { CodexAppServerClient } from './codex-app-server-client.js';\n\n// ─── Singleton app-server client ───────────────────────────────────────────\n\nlet appServerClient: CodexAppServerClient | null = null;\nlet appServerConnecting: Promise<void> | null = null;\n\nasync function getAppServerClient(): Promise<CodexAppServerClient> {\n if (appServerClient) return appServerClient;\n if (appServerConnecting) {\n await appServerConnecting;\n return appServerClient!;\n }\n const client = new CodexAppServerClient({ requestTimeoutMs: 300_000 });\n appServerConnecting = client.connect().then(() => {\n appServerClient = client;\n appServerConnecting = null;\n }).catch((err) => {\n appServerConnecting = null;\n throw err;\n });\n // Handle unexpected exit — reset singleton so next call reconnects\n client.on('exit', () => {\n if (appServerClient === client) {\n appServerClient = null;\n }\n });\n await appServerConnecting;\n return appServerClient!;\n}\n\n/** Gracefully shut down the singleton codex app-server process. */\nexport async function shutdownCodexAppServer(): Promise<void> {\n if (appServerClient) {\n const client = appServerClient;\n appServerClient = null;\n await client.shutdown();\n }\n}\n\nasync function getAgentManager() {\n const { agentManager } = await import('../agent-manager.js');\n return agentManager;\n}\n\n// ─── Codex CLI runner ──────────────────────────────────────────────────────\n//\n// Local mode: uses `codex app-server` (persistent JSON-RPC 2.0 process).\n// Agent mode: uses agent-side `codex app-server` via ai.codexRequest/ai.codexNotifications tRPC routes.\n//\n// Both modes use the app-server protocol for thread management (start/resume)\n// and turn execution with structured notifications.\n\n/** Extract route name + parsed input from a curl command targeting the Runeya tRPC API. */\nfunction parseRuneyaCurlCommand(command: string): { route: string; input: Record<string, unknown> } | null {\n // Match /api/trpc/<route> in URL\n const routeMatch = command.match(/\\/api\\/trpc\\/([\\w.]+)/);\n if (!routeMatch) return null;\n const route = routeMatch[1];\n // Try to extract JSON body from -d '...' or -d \"...\"\n let input: Record<string, unknown> = {};\n const bodyMatch = command.match(/-d\\s+'([^']+)'/) ?? command.match(/-d\\s+\"((?:[^\"\\\\]|\\\\.)*)\"/);\n if (bodyMatch) {\n try { input = JSON.parse(bodyMatch[1]) as Record<string, unknown>; } catch { /* keep empty */ }\n }\n // Also check ?input= for GET requests\n const inputQsMatch = command.match(/[?&]input=([^&\\s'\"]+)/);\n if (inputQsMatch) {\n try { input = JSON.parse(decodeURIComponent(inputQsMatch[1])) as Record<string, unknown>; } catch { /* keep empty */ }\n }\n return { route, input };\n}\n\nfunction getCommandExecutionInput(item: Record<string, unknown> | undefined): Record<string, unknown> {\n if (!item) return {};\n const command = typeof item['command'] === 'string' ? item['command'] : '';\n const parsed = command ? parseRuneyaCurlCommand(command) : null;\n if (parsed) return parsed.input;\n const input: Record<string, unknown> = {};\n if (command) input.command = command;\n if (typeof item['status'] === 'string' && item['status']) input.status = item['status'];\n if (typeof item['exit_code'] === 'number') input.exit_code = item['exit_code'];\n return input;\n}\n\nfunction getCommandExecutionName(item: Record<string, unknown> | undefined): string {\n if (!item) return 'command_execution';\n const command = typeof item['command'] === 'string' ? item['command'] : '';\n const parsed = command ? parseRuneyaCurlCommand(command) : null;\n return parsed ? parsed.route : 'command_execution';\n}\n\nfunction getCommandExecutionResult(item: Record<string, unknown> | undefined): string {\n if (!item) return '';\n if (typeof item['aggregated_output'] === 'string' && item['aggregated_output']) {\n return item['aggregated_output'] as string;\n }\n const fallback = {\n command: typeof item['command'] === 'string' ? item['command'] : undefined,\n status: typeof item['status'] === 'string' ? item['status'] : undefined,\n exit_code: typeof item['exit_code'] === 'number' ? item['exit_code'] : undefined,\n };\n return JSON.stringify(fallback, null, 2);\n}\n\n/** Map Runeya effort levels to Codex app-server effort values. */\nfunction mapEffort(effort: string): string | undefined {\n const map: Record<string, string> = { low: 'low', normal: 'medium', medium: 'medium', high: 'high' };\n return map[effort];\n}\n\nexport class CodexRunner implements AiRunner {\n /** Codex thread_id captured from `thread.started`, used for resume. */\n private lastThreadId: string | null = null;\n\n run(params: AiRunnerParams): Promise<NodeResult> {\n if (params.agentId) {\n return this.runViaAgent(params);\n }\n return this.runLocal(params);\n }\n\n // ── Run via agent (app-server JSON-RPC via agent tRPC routes) ───────────\n\n private async runViaAgent(params: AiRunnerParams): Promise<NodeResult> {\n const { agentId, prompt, systemContext, signal, model, effort, isResume, images, skipTokenInstructions, apiBaseUrl, apiToken } = params;\n const agentMgr = await getAgentManager();\n\n if (isResume && params.sessionId && !this.lastThreadId) {\n this.lastThreadId = params.sessionId;\n }\n\n params.onStatus('🔧 Codex en cours…');\n params.onCommand?.('codex app-server (agent JSON-RPC)');\n\n // Env vars to inject into the agent-side app-server process\n const codexEnv = apiToken ? { RUNEYA_API_TOKEN: apiToken } : undefined;\n\n // 1. Start or resume thread on agent-side app-server\n let threadId: string;\n if (isResume && this.lastThreadId) {\n const res = await agentMgr.agentMutation<{ result: { thread: { id: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'thread/resume',\n params: { threadId: this.lastThreadId },\n env: codexEnv,\n });\n threadId = res.result.thread.id;\n } else {\n const res = await agentMgr.agentMutation<{ result: { thread: { id: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'thread/start',\n params: {\n model: model || undefined,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'danger-full-access',\n },\n env: codexEnv,\n });\n threadId = res.result.thread.id;\n this.lastThreadId = threadId;\n params.onThreadId?.(threadId);\n }\n\n // 2. Build turn input (same as runLocal)\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const systemParts = [systemContext, ...(skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]), apiDocs].filter(Boolean);\n const fullSystemContext = systemParts.join('\\n\\n');\n const fullPrompt = (isResume && this.lastThreadId)\n ? prompt\n : `${fullSystemContext}\\n\\n---\\n\\n${prompt}`;\n\n const input: Array<Record<string, unknown>> = [];\n if (images && images.length > 0) {\n for (const img of images) {\n input.push({ type: 'image', url: `data:${img.mimeType};base64,${img.base64}` });\n }\n }\n input.push({ type: 'text', text: fullPrompt });\n\n // 3. Subscribe to notifications BEFORE starting the turn\n // Mutable ref so the notification handler can access turnId set after turn/start\n const turnRef: { id: string | null } = { id: null };\n\n return new Promise<NodeResult>((resolve, reject) => {\n let settled = false;\n let fullContent = '';\n let thinkingEmitted = false;\n const startedCommandExecutions = new Set<string>();\n const completedCommandExecutions = new Set<string>();\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', onAbort);\n if (unsubscribe) { unsubscribe(); unsubscribe = null; }\n fn();\n };\n\n const onAbort = () => {\n if (settled) return;\n if (turnRef.id) {\n agentMgr.agentMutation(agentId!, 'ai.codexRequest', {\n method: 'turn/interrupt',\n params: { threadId, turnId: turnRef.id },\n }).catch(() => { /* best-effort */ });\n }\n settle(() => reject(new Error('Aborted')));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n\n let unsubscribe: (() => void) | null = agentMgr.agentSubscribe(\n agentId!,\n 'ai.codexNotifications',\n { threadId },\n (data: unknown) => {\n if (settled) return;\n const notif = data as { method: string; params: Record<string, unknown> };\n const method = notif.method;\n const p = notif.params;\n\n // Filter by threadId\n const notifThreadId = p['threadId'] as string | undefined;\n if (notifThreadId && notifThreadId !== threadId) return;\n\n // Filter by turnId if present\n const notifTurnId = (p['turnId'] ?? (p['turn'] as Record<string, unknown> | undefined)?.['id']) as string | undefined;\n if (notifTurnId && turnRef.id && notifTurnId !== turnRef.id) return;\n\n if (method === 'item/agentMessage/delta') {\n const delta = p['delta'] as string;\n if (delta) {\n thinkingEmitted = false;\n fullContent += delta;\n params.onDelta(delta);\n const { status, message, branchChoice } = parseEndToken(fullContent);\n if (status !== 'none') {\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n }\n }\n } else if (method === 'item/reasoning/summaryTextDelta' || method === 'item/reasoning/textDelta') {\n const delta = p['delta'] as string;\n if (delta) {\n if (!thinkingEmitted) {\n thinkingEmitted = true;\n params.onStatus('💭 En réflexion…');\n }\n params.onThinking?.(delta);\n }\n } else if (method === 'item/started') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const cmdName = getCommandExecutionName(item);\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n params.onStatus(`🔧 ${cmdName}`);\n if (effectiveId && !startedCommandExecutions.has(effectiveId)) {\n startedCommandExecutions.add(effectiveId);\n params.onToolCall?.(effectiveId, cmdName, getCommandExecutionInput(item));\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n const rawName = typeof item['tool'] === 'string' ? item['tool'] as string\n : typeof item['name'] === 'string' ? item['name'] as string : 'tool';\n const server = typeof item['server'] === 'string' ? item['server'] as string : '';\n const displayName = server ? `${server}.${rawName}` : rawName;\n params.onStatus(`🔧 ${displayName}`);\n if (itemId) {\n let toolInput: Record<string, unknown> = {};\n const rawArgs = item['arguments'];\n if (typeof rawArgs === 'string') {\n try { toolInput = JSON.parse(rawArgs) as Record<string, unknown>; } catch { /* keep empty */ }\n } else if (rawArgs && typeof rawArgs === 'object') {\n toolInput = rawArgs as Record<string, unknown>;\n }\n params.onToolCall?.(itemId, displayName, toolInput);\n }\n }\n } else if (method === 'item/completed') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n if (effectiveId && !completedCommandExecutions.has(effectiveId)) {\n completedCommandExecutions.add(effectiveId);\n const exitCode = typeof item['exit_code'] === 'number' ? item['exit_code'] as number : 0;\n params.onToolResult?.(effectiveId, getCommandExecutionResult(item), exitCode !== 0);\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n if (itemId) {\n const output = item['output'];\n const result = typeof output === 'string' ? output : (output ? JSON.stringify(output) : '');\n params.onToolResult?.(itemId, result, false);\n }\n }\n } else if (method === 'turn/completed') {\n const turn = p['turn'] as Record<string, unknown> | undefined;\n const error = turn?.['error'] as Record<string, unknown> | undefined;\n if (error) {\n const msg = typeof error['message'] === 'string' ? error['message'] as string : 'Codex turn failed';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n return;\n }\n const { status, message, branchChoice } = parseEndToken(fullContent);\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n } else if (method === 'turn/errored') {\n const error = p['error'] as Record<string, unknown> | undefined;\n const msg = typeof error?.['message'] === 'string' ? error['message'] as string : 'Codex turn errored';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n }\n },\n () => {\n // onStop — WS disconnect\n },\n );\n\n // 4. Start turn on agent-side app-server\n agentMgr.agentMutation<{ result: { turn: { id: string; status: string } } }>(agentId!, 'ai.codexRequest', {\n method: 'turn/start',\n params: {\n threadId,\n input,\n model: model || undefined,\n effort: mapEffort(effort),\n approvalPolicy: 'never',\n sandboxPolicy: { type: 'dangerFullAccess' },\n },\n }).then((turnRes) => {\n turnRef.id = turnRes.result.turn.id;\n }).catch((err) => {\n settle(() => reject(new Error(`Failed to start codex turn on agent: ${(err as Error).message}`)));\n });\n });\n }\n\n // ── Run locally via app-server client ────────────────────────────────────\n\n private async runLocal(params: AiRunnerParams): Promise<NodeResult> {\n const { prompt, systemContext, signal, model, effort, isResume, images, skipTokenInstructions, apiBaseUrl, apiToken } = params;\n\n if (isResume && params.sessionId && !this.lastThreadId) {\n this.lastThreadId = params.sessionId;\n }\n\n params.onStatus('🔧 Codex en cours…');\n params.onCommand?.('codex app-server (JSON-RPC)');\n\n // 1. Get or create the singleton client\n const client = await getAppServerClient();\n\n // 2. Start or resume thread\n let threadId: string;\n if (isResume && this.lastThreadId) {\n const res = await client.sendRequest('thread/resume', { threadId: this.lastThreadId }) as { thread: { id: string } };\n threadId = res.thread.id;\n } else {\n const res = await client.sendRequest('thread/start', {\n model: model || undefined,\n cwd: process.cwd(),\n approvalPolicy: 'never',\n sandbox: 'danger-full-access',\n }) as { thread: { id: string } };\n threadId = res.thread.id;\n this.lastThreadId = threadId;\n params.onThreadId?.(threadId);\n }\n\n // 3. Build turn input\n const apiDocs = buildApiDocs(apiBaseUrl, apiToken);\n const systemParts = [systemContext, ...(skipTokenInstructions ? [] : [TOKEN_INSTRUCTIONS]), apiDocs].filter(Boolean);\n const fullSystemContext = systemParts.join('\\n\\n');\n const fullPrompt = (isResume && this.lastThreadId)\n ? prompt\n : `${fullSystemContext}\\n\\n---\\n\\n${prompt}`;\n\n const input: Array<Record<string, unknown>> = [];\n if (images && images.length > 0) {\n for (const img of images) {\n input.push({ type: 'image', url: `data:${img.mimeType};base64,${img.base64}` });\n }\n }\n input.push({ type: 'text', text: fullPrompt });\n\n // 4. Start turn\n const turnRes = await client.sendRequest('turn/start', {\n threadId,\n input,\n model: model || undefined,\n effort: mapEffort(effort),\n approvalPolicy: 'never',\n sandboxPolicy: { type: 'dangerFullAccess' },\n }) as { turn: { id: string; status: string } };\n const turnId = turnRes.turn.id;\n\n // 5. Listen for notifications and resolve on turn/completed\n return new Promise<NodeResult>((resolve, reject) => {\n let settled = false;\n let fullContent = '';\n let thinkingEmitted = false;\n const startedCommandExecutions = new Set<string>();\n const completedCommandExecutions = new Set<string>();\n\n const settle = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', onAbort);\n fn();\n };\n\n const handler = (method: string, p: Record<string, unknown>) => {\n if (settled) return;\n\n // Filter by threadId to scope to this conversation\n const notifThreadId = p['threadId'] as string | undefined;\n if (notifThreadId && notifThreadId !== threadId) return;\n\n // Also filter by turnId if present\n const notifTurnId = (p['turnId'] ?? (p['turn'] as Record<string, unknown> | undefined)?.['id']) as string | undefined;\n if (notifTurnId && notifTurnId !== turnId) return;\n\n if (method === 'item/agentMessage/delta') {\n const delta = p['delta'] as string;\n if (delta) {\n thinkingEmitted = false;\n fullContent += delta;\n params.onDelta(delta);\n const { status, message, branchChoice } = parseEndToken(fullContent);\n if (status !== 'none') {\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n }\n }\n } else if (method === 'item/reasoning/summaryTextDelta' || method === 'item/reasoning/textDelta') {\n const delta = p['delta'] as string;\n if (delta) {\n if (!thinkingEmitted) {\n thinkingEmitted = true;\n params.onStatus('💭 En réflexion…');\n }\n params.onThinking?.(delta);\n }\n } else if (method === 'item/started') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const cmdName = getCommandExecutionName(item);\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n params.onStatus(`🔧 ${cmdName}`);\n if (effectiveId && !startedCommandExecutions.has(effectiveId)) {\n startedCommandExecutions.add(effectiveId);\n params.onToolCall?.(effectiveId, cmdName, getCommandExecutionInput(item));\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n const rawName = typeof item['tool'] === 'string' ? item['tool'] as string\n : typeof item['name'] === 'string' ? item['name'] as string : 'tool';\n const server = typeof item['server'] === 'string' ? item['server'] as string : '';\n const displayName = server ? `${server}.${rawName}` : rawName;\n params.onStatus(`🔧 ${displayName}`);\n if (itemId) {\n let toolInput: Record<string, unknown> = {};\n const rawArgs = item['arguments'];\n if (typeof rawArgs === 'string') {\n try { toolInput = JSON.parse(rawArgs) as Record<string, unknown>; } catch { /* keep empty */ }\n } else if (rawArgs && typeof rawArgs === 'object') {\n toolInput = rawArgs as Record<string, unknown>;\n }\n params.onToolCall?.(itemId, displayName, toolInput);\n }\n }\n } else if (method === 'item/completed') {\n const item = p['item'] as Record<string, unknown> | undefined;\n if (!item) return;\n const itemType = item['type'] as string;\n const itemId = item['id'] as string ?? '';\n\n if (itemType === 'commandExecution') {\n const command = typeof item['command'] === 'string' ? item['command'] as string : '';\n const effectiveId = itemId || (command ? `cmd-${command.slice(0, 80)}` : '');\n if (effectiveId && !completedCommandExecutions.has(effectiveId)) {\n completedCommandExecutions.add(effectiveId);\n const exitCode = typeof item['exit_code'] === 'number' ? item['exit_code'] as number : 0;\n params.onToolResult?.(effectiveId, getCommandExecutionResult(item), exitCode !== 0);\n }\n } else if (itemType === 'mcpToolCall' || itemType === 'tool_call') {\n if (itemId) {\n const output = item['output'];\n const result = typeof output === 'string' ? output : (output ? JSON.stringify(output) : '');\n params.onToolResult?.(itemId, result, false);\n }\n }\n } else if (method === 'turn/completed') {\n const turn = p['turn'] as Record<string, unknown> | undefined;\n const error = turn?.['error'] as Record<string, unknown> | undefined;\n if (error) {\n const msg = typeof error['message'] === 'string' ? error['message'] as string : 'Codex turn failed';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n return;\n }\n // Turn finished normally — resolve with accumulated content\n const { status, message, branchChoice } = parseEndToken(fullContent);\n settle(() => resolve({ output: fullContent, tokenStatus: status, tokenMessage: message, branchChoice }));\n } else if (method === 'turn/errored') {\n const error = p['error'] as Record<string, unknown> | undefined;\n const msg = typeof error?.['message'] === 'string' ? error['message'] as string : 'Codex turn errored';\n settle(() => reject(new Error(`Codex: ${msg}`)));\n }\n };\n\n client.onAnyNotification(handler);\n\n const onAbort = () => {\n if (settled) return;\n client.sendRequest('turn/interrupt', { threadId, turnId }).catch(() => { /* best-effort */ });\n settle(() => reject(new Error('Aborted')));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n}\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { serviceStore } from '../../services/service-store.js';\nimport { agentManager } from '../../services/agent-manager.js';\nimport { getActiveProvider, DEFAULT_MODELS, OPENAI_COMPAT_BASE_URLS } from '../../services/ai-provider-utils.js';\nimport { resolveEffectiveAgentId } from './service.js';\n\nconst SERVICE_ID_SCHEMA = z.string().max(128);\nconst SAFE_PATH_SCHEMA = z\n .string()\n .min(1)\n .max(4096)\n .refine((p) => !p.startsWith('/') && !p.includes('../'), {\n message: 'Path must be relative and not traverse up',\n });\nconst REMOTE_SCHEMA = z.string().min(1).max(128).regex(/^[a-zA-Z0-9_\\-\\.]+$/);\nconst BRANCH_SCHEMA = z.string().min(1).max(256).regex(/^[a-zA-Z0-9._\\-\\/]+$/);\n\n/**\n * Resolve the effective agentId and absolute cwd for a service.\n * Throws if service not found or no agent is configured.\n */\nasync function resolveServiceContext(serviceId: string): Promise<{ agentId: string; cwd: string }> {\n const service = await serviceStore.get(serviceId);\n if (!service) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Service not found' });\n }\n const agentId = await resolveEffectiveAgentId(service);\n if (!agentId) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No agent configured for this service' });\n }\n // Pass the raw cwd — the agent resolves $VAR from its own process.env\n return { agentId, cwd: service.cwd || '.' };\n}\n\nexport const gitRouter = router({\n /** Get full git status */\n status: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentQuery(agentId, 'git.status', { cwd });\n }),\n\n /** Get commit log */\n log: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, limit: z.number().int().min(1).max(200).default(50) }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentQuery(agentId, 'git.log', { cwd, limit: input.limit });\n }),\n\n /** List local and remote branches */\n branches: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentQuery(agentId, 'git.branches', { cwd });\n }),\n\n /** Checkout a branch */\n checkout: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, branch: BRANCH_SCHEMA, create: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.checkout', { cwd, branch: input.branch, create: input.create });\n }),\n\n /** Stage files */\n stage: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.stage', { cwd, paths: input.paths });\n }),\n\n /** Stage all files */\n stageAll: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.stageAll', { cwd });\n }),\n\n /** Unstage files */\n unstage: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.unstage', { cwd, paths: input.paths });\n }),\n\n /** Commit staged changes */\n commit: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, message: z.string().min(1).max(4096) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.commit', { cwd, message: input.message });\n }),\n\n /** Push to remote */\n push: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, remote: REMOTE_SCHEMA.default('origin'), setUpstream: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.push', { cwd, remote: input.remote, setUpstream: input.setUpstream });\n }),\n\n /** Pull from remote */\n pull: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.pull', { cwd, remote: input.remote });\n }),\n\n /** Fetch from remote */\n fetch: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, remote: REMOTE_SCHEMA.default('origin') }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.fetch', { cwd, remote: input.remote });\n }),\n\n /** Get diff for a file or the whole index */\n diff: protectedProcedure\n .input(z.object({\n serviceId: SERVICE_ID_SCHEMA,\n path: z.string().max(4096).optional(),\n staged: z.boolean().default(false),\n untracked: z.boolean().default(false),\n }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentQuery(agentId, 'git.diff', { cwd, path: input.path, staged: input.staged, untracked: input.untracked });\n }),\n\n /** Discard changes to working tree files */\n discard: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, paths: z.array(SAFE_PATH_SCHEMA).min(1).max(500) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.discard', { cwd, paths: input.paths });\n }),\n\n /** Generate a commit message from staged diffs using AI (diff fetched from agent, AI runs on server) */\n generateCommitMessage: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n const { diff } = await agentManager.agentQuery<{ diff: string }>(agentId, 'git.stagedDiff', { cwd });\n\n if (!diff.trim()) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No staged changes to generate a commit message from' });\n }\n\n const active = await getActiveProvider();\n if (!active) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'No AI provider configured' });\n }\n\n const systemPrompt = `You are a git commit message generator. Given a git diff, write a concise and meaningful conventional commit message (e.g. feat:, fix:, refactor:, chore:, docs:, style:, test:).\nRules:\n- First line: type(optional scope): short summary (max 72 chars)\n- Optionally add a blank line and a brief body if the changes are complex\n- Write in English\n- Return ONLY the commit message, nothing else`;\n\n const { provider, plaintextKey } = active;\n const model = provider.model || DEFAULT_MODELS[provider.provider] || 'claude-opus-4-6';\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const res = await client.messages.create({\n model,\n max_tokens: 512,\n system: systemPrompt,\n messages: [{ role: 'user', content: diff }],\n });\n const block = res.content[0];\n return { message: block?.type === 'text' ? block.text.trim() : '' };\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const res = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: diff },\n ],\n });\n return { message: res.choices[0]?.message?.content?.trim() ?? '' };\n }\n\n throw new TRPCError({ code: 'BAD_REQUEST', message: 'Unsupported AI provider' });\n }),\n\n /** Merge a branch into the current branch */\n merge: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, branch: BRANCH_SCHEMA, noFf: z.boolean().default(false) }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.merge', { cwd, branch: input.branch, noFf: input.noFf });\n }),\n\n /** Rebase current branch onto another branch */\n rebase: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA, branch: BRANCH_SCHEMA }))\n .mutation(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentMutation(agentId, 'git.rebase', { cwd, branch: input.branch });\n }),\n\n /** Watch .git/ for changes and stream updated status */\n onStatusChange: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .subscription(async function* ({ input }) {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n\n const queue: unknown[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n let unsubscribe: (() => void) | undefined;\n try {\n unsubscribe = agentManager.agentSubscribe(\n agentId,\n 'git.onStatusChange',\n { cwd },\n (data) => {\n queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n },\n () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n },\n );\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: `Cannot subscribe to git status: ${(err as Error).message}`,\n });\n }\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n unsubscribe?.();\n }\n }),\n\n /** List remotes */\n remotes: protectedProcedure\n .input(z.object({ serviceId: SERVICE_ID_SCHEMA }))\n .query(async ({ input }) => {\n const { agentId, cwd } = await resolveServiceContext(input.serviceId);\n return agentManager.agentQuery(agentId, 'git.remotes', { cwd });\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { TRPCError } from '@trpc/server';\nimport { z } from 'zod';\nimport { ScenarioNodeSchema, ScenarioGroupSchema } from '@runeya/packages-shared';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { createOrBadRequest, deleteOrNotFound, getOrNotFound, updateOrThrow } from '../crud-procedure-utils.js';\nimport { streamWithActiveProvider } from '../ai-generation-procedure-utils.js';\nimport {\n ConversationIdSchema,\n DescriptionSchema,\n Id128Schema,\n NameSchema,\n OptionalProviderIdSchema,\n} from '../shared-schemas.js';\nimport { scenarioStore } from '../../services/scenario-store.js';\nimport { scenarioRunStore } from '../../services/scenario-run-store.js';\nimport { runScenario, tapBus, isScenarioRunning, abortScenario, resolveNodeInput } from '../../services/scenario-runner.js';\nimport { listPresets, getPreset } from '../../services/scenario-presets.js';\n\n// ─── AI generation helpers ────────────────────────────────────────────────────\n\nconst SCENARIO_SYSTEM_PROMPT = `You are an scenario org-chart builder assistant. You generate JSON structures representing an scenario hierarchy.\n\nIMPORTANT: Respond with ONLY a valid JSON object. No markdown, no code fences, no explanation. Pure JSON only.\n\nOutput schema:\n{\n \"leaderId\": \"string — id of the leader node\",\n \"groups\": [{ \"id\": \"string\", \"name\": \"string\", \"position\": { \"x\": number, \"y\": number }, \"width\": number, \"height\": number }],\n \"nodes\": [{ \"id\": \"string\", \"label\": \"string\", \"role\": \"manager|engineer|designer|analyst|qa|devops|product|writer|researcher|other\", \"groupId\": \"string (must match a group id)\", \"parentId\": \"string|null (null only for the leader)\", \"prompt\": \"string — detailed role description and instructions for this AI agent\", \"autoGenerated\": true, \"canAddNode\": false, \"position\": { \"x\": number, \"y\": number } }]\n}\n\nRules:\n- Every node MUST have a groupId that references an existing group id.\n- Exactly one node is the leader: parentId=null, their id = leaderId.\n- All other nodes MUST have parentId set to their manager's id.\n- The leader MUST always be in the group with id \"group-management\" and name \"Management\".\n- The leader MUST always have role \"manager\".\n- Use role to reflect each node's actual function: managers coordinate and delegate (never implement), engineers write code, etc.\n- Use short readable ids: \"group-engineering\", \"node-alice\", etc.\n- Groups: position spaced 400px apart (e.g. x=0, x=400, x=800). width >= 300, height >= 200.\n- Nodes positions are relative to their group: x/y in 30-260 range.\n- The \"prompt\" field must be detailed: role, responsibilities, communication style, expected outputs.`;\n\nfunction buildScenarioUserMessage(\n userPrompt: string,\n current?: { leaderId: string; groups: unknown[]; nodes: unknown[] },\n): string {\n if (current && (current.groups.length > 0 || current.nodes.length > 0)) {\n return `Current scenario:\\n${JSON.stringify(current, null, 2)}\\n\\nUser request: ${userPrompt}\\n\\nModify the scenario. Keep existing ids when possible.`;\n }\n return `Generate an scenario org-chart based on: ${userPrompt}`;\n}\n\nexport const scenarioRouter = router({\n list: protectedProcedure.query(() => scenarioStore.list()),\n\n get: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(({ input }) => getOrNotFound(() => scenarioStore.get(input.id), 'Scenario not found')),\n\n create: protectedProcedure\n .input(z.object({\n name: NameSchema,\n icon: z.string().max(64).optional(),\n description: DescriptionSchema.optional(),\n leaderId: Id128Schema,\n groups: z.array(ScenarioGroupSchema).max(100).optional(),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500),\n traversalMode: z.enum(['hierarchical', 'topological']).optional(),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().optional(),\n }))\n .mutation(({ input }) => {\n const now = Date.now();\n return createOrBadRequest(() => scenarioStore.create({\n id: randomUUID(),\n name: input.name,\n icon: input.icon,\n description: input.description,\n leaderId: input.leaderId,\n groups: input.groups ?? [],\n nodes: input.nodes,\n traversalMode: input.traversalMode ?? 'hierarchical',\n presetId: input.presetId,\n isPublished: input.isPublished ?? false,\n createdAt: now,\n updatedAt: now,\n }));\n }),\n\n update: protectedProcedure\n .input(z.object({\n id: Id128Schema,\n name: NameSchema.optional(),\n icon: z.string().max(64).optional(),\n description: DescriptionSchema.optional(),\n leaderId: Id128Schema.optional(),\n groups: z.array(ScenarioGroupSchema).max(100).optional(),\n nodes: z.array(ScenarioNodeSchema).min(1).max(500).optional(),\n traversalMode: z.enum(['hierarchical', 'topological']).optional(),\n presetId: z.string().max(128).optional(),\n isPublished: z.boolean().optional(),\n }))\n .mutation(({ input }) => updateOrThrow(\n () => scenarioStore.update(input.id, {\n name: input.name,\n icon: input.icon,\n description: input.description,\n leaderId: input.leaderId,\n groups: input.groups,\n nodes: input.nodes,\n traversalMode: input.traversalMode,\n presetId: input.presetId,\n isPublished: input.isPublished,\n updatedAt: Date.now(),\n }),\n 'Scenario not found',\n )),\n\n delete: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .mutation(({ input }) => deleteOrNotFound(() => scenarioStore.delete(input.id), 'Scenario not found')),\n\n run: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n scenarioId: Id128Schema,\n userRequest: z.string().max(100_000),\n runnerOverride: z.enum(['claude-code', 'codex']).optional(),\n modelOverride: Id128Schema.optional(),\n agentId: Id128Schema.optional(),\n resume: z.boolean().optional(),\n }))\n .subscription(async function* ({ input, signal }) {\n const scenario = await scenarioStore.get(input.scenarioId);\n if (!scenario) throw new TRPCError({ code: 'NOT_FOUND', message: 'Scenario not found' });\n\n // Start only on explicit user request or resume.\n // Reconnect/resubscribe paths pass an empty request and must never restart runs.\n const canStart = input.userRequest.trim().length > 0 || !!input.resume;\n if (!isScenarioRunning(input.conversationId) && canStart) {\n // On resume, load original user request from workspace if not provided\n let userRequest = input.userRequest;\n if (input.resume && !userRequest.trim()) {\n userRequest = await scenarioRunStore.readUserRequest(input.conversationId) ?? '';\n }\n runScenario(input.conversationId, input.scenarioId, userRequest, {\n runnerOverride: input.runnerOverride,\n modelOverride: input.modelOverride,\n agentId: input.agentId,\n }, !!input.resume);\n // Small yield to let the bus be created before tapping\n await new Promise(r => setTimeout(r, 10));\n }\n\n // Tap into the live event bus (replays buffer for late subscribers)\n yield* tapBus(input.conversationId, signal ?? new AbortController().signal);\n }),\n\n stop: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .mutation(({ input }) => {\n abortScenario(input.conversationId);\n return { ok: true };\n }),\n\n sendNodeInput: protectedProcedure\n .input(z.object({\n conversationId: ConversationIdSchema,\n nodeId: Id128Schema,\n text: z.string().min(1).max(100_000),\n }))\n .mutation(({ input }) => {\n const resolved = resolveNodeInput(input.conversationId, input.nodeId, input.text);\n if (!resolved) throw new TRPCError({ code: 'NOT_FOUND', message: 'No pending input request for this node' });\n return { ok: true };\n }),\n\n isRunning: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(({ input }) => ({ running: isScenarioRunning(input.conversationId) })),\n\n runState: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(({ input }) => {\n const runState = scenarioRunStore.getRunState(input.conversationId);\n return runState ?? { nodeStates: {}, nodeOutputs: {}, activeNodeId: undefined };\n }),\n\n getPersistedRunState: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.loadPersistedRunState(input.conversationId);\n }),\n\n getReadme: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.readReadme(input.conversationId);\n }),\n\n getSnapshot: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .query(async ({ input }) => {\n return await scenarioRunStore.loadScenarioSnapshot(input.conversationId);\n }),\n\n streamGenerateWithAI: protectedProcedure\n .input(z.object({\n prompt: z.string().min(1).max(10_000),\n providerId: OptionalProviderIdSchema,\n current: z.object({\n leaderId: Id128Schema,\n groups: z.array(ScenarioGroupSchema).max(100),\n nodes: z.array(ScenarioNodeSchema).max(500),\n }).optional(),\n }))\n .subscription(async function* ({ input, signal }) {\n const userMessage = buildScenarioUserMessage(input.prompt, input.current);\n yield* streamWithActiveProvider({\n providerId: input.providerId,\n systemPrompt: SCENARIO_SYSTEM_PROMPT,\n userMessage,\n maxTokens: 8192,\n signal: signal ?? undefined,\n });\n }),\n\n streamRunEvents: protectedProcedure\n .input(z.object({ conversationId: ConversationIdSchema }))\n .subscription(async function* ({ input }) {\n const convId = input.conversationId;\n // For now, yield the current state once\n // In a real implementation, this would track state changes over time\n const runState = scenarioRunStore.getRunState(convId);\n if (runState) {\n for (const [nodeId, state] of Object.entries(runState.nodeStates)) {\n yield { type: 'node_state' as const, nodeId, state };\n }\n }\n }),\n\n listPresets: protectedProcedure.query(() => listPresets()),\n\n getPreset: protectedProcedure\n .input(z.object({ id: Id128Schema }))\n .query(({ input }) => {\n const preset = getPreset(input.id);\n if (!preset) throw new TRPCError({ code: 'NOT_FOUND', message: 'Preset not found' });\n return preset;\n }),\n});\n","import { TRPCError } from '@trpc/server';\n\nexport async function getOrNotFound<T>(\n getter: () => Promise<T | null>,\n notFoundMessage: string,\n): Promise<T> {\n const entity = await getter();\n if (!entity) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return entity;\n}\n\nexport async function createOrBadRequest<T>(creator: () => Promise<T>): Promise<T> {\n try {\n return await creator();\n } catch (err) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: (err as Error).message });\n }\n}\n\nexport async function updateOrThrow<T>(\n updater: () => Promise<T | null>,\n notFoundMessage: string,\n): Promise<T> {\n try {\n const entity = await updater();\n if (!entity) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return entity;\n } catch (err) {\n if (err instanceof TRPCError) throw err;\n throw new TRPCError({ code: 'BAD_REQUEST', message: (err as Error).message });\n }\n}\n\nexport async function deleteOrNotFound(\n deleter: () => Promise<boolean>,\n notFoundMessage: string,\n): Promise<{ ok: true }> {\n const deleted = await deleter();\n if (!deleted) throw new TRPCError({ code: 'NOT_FOUND', message: notFoundMessage });\n return { ok: true };\n}\n","import { TRPCError } from '@trpc/server';\nimport { completeProviderText, streamProviderText } from '../services/ai-generation.js';\nimport { DEFAULT_MODELS, getActiveProvider } from '../services/ai-provider-utils.js';\n\ninterface ActiveProviderGenerationOptions {\n providerId?: string;\n systemPrompt: string;\n userMessage: string;\n maxTokens?: number;\n signal?: AbortSignal;\n}\n\nexport async function* streamWithActiveProvider(\n opts: ActiveProviderGenerationOptions,\n): AsyncGenerator<{ type: 'delta' | 'done'; text: string }> {\n const active = await getActiveProvider(opts.providerId);\n if (!active) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun fournisseur IA configuré' });\n\n const { provider, plaintextKey } = active;\n const model = provider.model ?? DEFAULT_MODELS[provider.provider] ?? '';\n\n try {\n for await (const text of streamProviderText({\n provider,\n plaintextKey,\n model,\n systemPrompt: opts.systemPrompt,\n userMessage: opts.userMessage,\n maxTokens: opts.maxTokens,\n signal: opts.signal,\n })) {\n yield { type: 'delta', text };\n }\n yield { type: 'done', text: '' };\n } catch (err) {\n if (String((err as Error)?.message ?? '').startsWith('Unsupported provider:')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Fournisseur non supporté: ${provider.provider}` });\n }\n throw err;\n }\n}\n\nasync function completeWithActiveProvider(opts: ActiveProviderGenerationOptions): Promise<string> {\n const active = await getActiveProvider(opts.providerId);\n if (!active) throw new TRPCError({ code: 'BAD_REQUEST', message: 'Aucun fournisseur IA configuré' });\n\n const { provider, plaintextKey } = active;\n const model = provider.model ?? DEFAULT_MODELS[provider.provider] ?? '';\n\n try {\n return await completeProviderText({\n provider,\n plaintextKey,\n model,\n systemPrompt: opts.systemPrompt,\n userMessage: opts.userMessage,\n maxTokens: opts.maxTokens,\n signal: opts.signal,\n });\n } catch (err) {\n if (String((err as Error)?.message ?? '').startsWith('Unsupported provider:')) {\n throw new TRPCError({ code: 'BAD_REQUEST', message: `Fournisseur non supporté: ${provider.provider}` });\n }\n throw err;\n }\n}\n","import Anthropic from '@anthropic-ai/sdk';\nimport OpenAI from 'openai';\nimport type { AIProvider } from '@runeya/packages-shared';\nimport { OPENAI_COMPAT_BASE_URLS } from './ai-provider-utils.js';\n\nexport interface ProviderGenerationInput {\n provider: AIProvider;\n plaintextKey: string;\n model: string;\n systemPrompt: string;\n userMessage: string;\n maxTokens?: number;\n signal?: AbortSignal;\n}\n\nexport async function* streamProviderText(input: ProviderGenerationInput): AsyncGenerator<string> {\n const {\n provider,\n plaintextKey,\n model,\n systemPrompt,\n userMessage,\n maxTokens = 8192,\n signal,\n } = input;\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const stream = client.messages.stream({\n model,\n max_tokens: maxTokens,\n system: systemPrompt,\n messages: [{ role: 'user', content: userMessage }],\n });\n for await (const event of stream) {\n if (signal?.aborted) return;\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n yield event.delta.text;\n }\n }\n return;\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const stream = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n stream: true,\n max_tokens: maxTokens,\n }, { signal: signal ?? undefined });\n for await (const chunk of stream) {\n if (signal?.aborted) return;\n const text = chunk.choices[0]?.delta?.content;\n if (text) yield text;\n }\n return;\n }\n\n throw new Error(`Unsupported provider: ${provider.provider}`);\n}\n\nexport async function completeProviderText(input: ProviderGenerationInput): Promise<string> {\n const {\n provider,\n plaintextKey,\n model,\n systemPrompt,\n userMessage,\n maxTokens = 512,\n signal,\n } = input;\n\n if (provider.provider === 'anthropic') {\n const client = new Anthropic({ apiKey: plaintextKey });\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n system: systemPrompt,\n messages: [{ role: 'user', content: userMessage }],\n }, { signal: signal ?? undefined });\n const textBlock = response.content.find((b) => b.type === 'text');\n return textBlock?.type === 'text' ? textBlock.text.trim() : '';\n }\n\n if (provider.provider in OPENAI_COMPAT_BASE_URLS) {\n const baseURL = OPENAI_COMPAT_BASE_URLS[provider.provider]!;\n const client = new OpenAI({ apiKey: plaintextKey || 'ollama', baseURL });\n const response = await client.chat.completions.create({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n max_tokens: maxTokens,\n }, { signal: signal ?? undefined });\n return response.choices[0]?.message?.content?.trim() ?? '';\n }\n\n throw new Error(`Unsupported provider: ${provider.provider}`);\n}\n","import { mkdir } from 'node:fs/promises';\nimport { randomUUID } from 'node:crypto';\nimport { join } from 'node:path';\nimport { scenarioStore } from './scenario-store.js';\nimport { scenarioRunStore, type NodeState } from './scenario-run-store.js';\nimport type { Scenario, ScenarioNode } from '@runeya/packages-shared';\nimport { getPreset } from './scenario-presets.js';\nimport { atomicWriteSecure, resolveConversationRunDir } from './run-store-utils.js';\nimport { ClaudeCodeRunner } from './ai-runners/claude-code-runner.js';\nimport { CodexRunner } from './ai-runners/codex-runner.js';\nimport type { AiRunner } from './ai-runners/ai-runner.js';\nimport { agentManager } from './agent-manager.js';\n\nconst DEFAULT_NODE_MODELS: Record<'claude-code' | 'codex', string> = {\n 'claude-code': 'sonnet',\n codex: '',\n};\n\nexport interface ScenarioRunOverrides {\n runnerOverride?: 'claude-code' | 'codex';\n modelOverride?: string;\n agentId?: string;\n}\n\n// ─── Event types ──────────────────────────────────────────────────────────────\n\nexport type ScenarioEvent =\n | { type: 'node_started'; nodeId: string }\n | { type: 'node_delta'; nodeId: string; text: string }\n | { type: 'node_status'; nodeId: string; text: string }\n | { type: 'node_tool_call'; nodeId: string; id: string; name: string; input: Record<string, unknown>; rawInput?: string }\n | { type: 'node_tool_result'; nodeId: string; id: string; result: string; isError: boolean }\n | { type: 'node_thinking'; nodeId: string; text: string }\n | { type: 'node_command'; nodeId: string; command: string }\n | { type: 'node_duration'; nodeId: string; durationMs: number }\n | { type: 'node_done'; nodeId: string; output: string; state: string }\n | { type: 'node_state_change'; nodeId: string; state: string }\n | { type: 'node_error'; nodeId: string; error: string }\n | { type: 'node_waiting_input'; nodeId: string; question: string }\n | { type: 'node_prompt'; nodeId: string; label: string; systemContext: string; userMessage: string }\n | { type: 'readme_append'; text: string }\n | { type: 'scenario_complete'; summary: string }\n | { type: 'scenario_error'; error: string };\n\n// ─── Event bus ────────────────────────────────────────────────────────────────\n\nconst MAX_BUFFER = 500;\n\ninterface RunBus {\n buffer: ScenarioEvent[];\n /** Absolute index of buffer[0] in the full event stream */\n baseIndex: number;\n listeners: Set<(evt: ScenarioEvent | null) => void>;\n done: boolean;\n}\n\nconst activeBuses = new Map<string, RunBus>();\nconst activeAbortControllers = new Map<string, AbortController>();\n\nfunction formatTs(): string {\n const d = new Date();\n const off = -d.getTimezoneOffset();\n const sign = off >= 0 ? '+' : '-';\n const pad2 = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())} ${sign}${pad2(Math.floor(Math.abs(off) / 60))}:${pad2(Math.abs(off) % 60)}`;\n}\n\n// ─── Pending user-input requests (keyed by conversationId:nodeId) ──────────\n\nconst pendingNodeInputs = new Map<string, (text: string) => void>();\n\nfunction pendingNodeKey(conversationId: string, nodeId: string) {\n return `${conversationId}:${nodeId}`;\n}\n\n/** Called by scenario.sendNodeInput tRPC mutation when the user submits their reply. */\nexport function resolveNodeInput(conversationId: string, nodeId: string, text: string): boolean {\n const key = pendingNodeKey(conversationId, nodeId);\n const resolver = pendingNodeInputs.get(key);\n if (!resolver) return false;\n pendingNodeInputs.delete(key);\n resolver(text);\n return true;\n}\n\nfunction createBus(conversationId: string): RunBus {\n const bus: RunBus = { buffer: [], baseIndex: 0, listeners: new Set(), done: false };\n activeBuses.set(conversationId, bus);\n return bus;\n}\n\n// Events that are only useful in real-time and should not be replayed to late subscribers\nconst NO_BUFFER_EVENTS = new Set<ScenarioEvent['type']>(['node_status', 'node_thinking']);\n\nfunction publishToBus(bus: RunBus, evt: ScenarioEvent | null): void {\n if (evt !== null) {\n if (!NO_BUFFER_EVENTS.has(evt.type)) {\n bus.buffer.push(evt);\n while (bus.buffer.length > MAX_BUFFER) {\n const idx = bus.buffer.findIndex(e => e.type === 'node_delta');\n bus.buffer.splice(idx >= 0 ? idx : 0, 1);\n bus.baseIndex += 1;\n }\n }\n } else {\n bus.done = true;\n }\n for (const listener of bus.listeners) listener(evt);\n bus.listeners.clear();\n}\n\nexport async function* tapBus(conversationId: string, signal: AbortSignal): AsyncGenerator<ScenarioEvent> {\n const bus = activeBuses.get(conversationId);\n if (!bus) return;\n\n let cursor = bus.baseIndex;\n\n while (true) {\n if (cursor < bus.baseIndex) {\n // Buffer rotated (old events dropped). Jump forward to oldest still available.\n cursor = bus.baseIndex;\n }\n while (cursor < bus.baseIndex + bus.buffer.length) {\n const evt = bus.buffer[cursor - bus.baseIndex]!;\n cursor += 1;\n yield evt;\n }\n if (bus.done) return;\n if (signal.aborted) return;\n\n await new Promise<void>((resolve) => {\n const onAbort = () => {\n bus.listeners.delete(notify);\n resolve();\n };\n const notify = () => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n bus.listeners.add(notify);\n signal.addEventListener('abort', onAbort, { once: true });\n // Race guard: if an event was published between the last buffer drain and\n // listener registration, wake immediately instead of waiting forever.\n if (cursor < bus.baseIndex + bus.buffer.length || bus.done || signal.aborted) {\n bus.listeners.delete(notify);\n signal.removeEventListener('abort', onAbort);\n resolve();\n }\n });\n }\n}\n\nexport function isScenarioRunning(conversationId: string): boolean {\n const bus = activeBuses.get(conversationId);\n return bus !== undefined && !bus.done;\n}\n\nexport function abortScenario(conversationId: string): boolean {\n const ctrl = activeAbortControllers.get(conversationId);\n if (!ctrl) return false;\n ctrl.abort();\n return true;\n}\n\n// ─── Hierarchy helpers ────────────────────────────────────────────────────────\n\nconst FINISHED_STATES = new Set(['done', 'error', 'synthesized']);\nconst MAX_MANAGER_REVIEW_ROUNDS = Infinity;\n\n/**\n * After a BFS level completes, promote any 'waiting' ancestor to 'done'\n * if all their descendants (recursively) are now in a finished state.\n */\nfunction resolveWaitingStates(\n nodes: ScenarioNode[],\n conversationId: string,\n byParent: Map<string, ScenarioNode[]>,\n publish: (evt: ScenarioEvent) => void,\n skipNodeIds: Set<string> = new Set(),\n): void {\n function allDescendantsDone(nodeId: string): boolean {\n for (const child of byParent.get(nodeId) ?? []) {\n const s = scenarioRunStore.getRunState(conversationId)?.nodeStates[child.id];\n if (!s || !FINISHED_STATES.has(s)) return false;\n if (!allDescendantsDone(child.id)) return false;\n }\n return true;\n }\n\n for (const node of nodes) {\n if (skipNodeIds.has(node.id)) continue;\n const s = scenarioRunStore.getRunState(conversationId)?.nodeStates[node.id];\n if (s === 'waiting' && allDescendantsDone(node.id)) {\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n }\n }\n}\n\nfunction normalizeForMatch(value: string): string {\n return value\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, ' ')\n .trim();\n}\n\nfunction getDirectReports(nodes: ScenarioNode[], managerId: string): ScenarioNode[] {\n return nodes.filter((p) => p.parentIds[0] === managerId);\n}\n\n/**\n * Parse <next_person> directives from AI output.\n *\n * Supported forms:\n * <next_person name=\"Alice Martin\">specific instruction (multiline ok)</next_person>\n * <next_person name=\"STOP\" />\n */\nfunction parseRuneyaNextNodeDirectives(output: string): { name: string; instruction: string | null }[] {\n const results: { name: string; instruction: string | null }[] = [];\n // Self-closing form: <next_person name=\"STOP\" />\n for (const m of output.matchAll(/<next_person\\s+name=\"([^\"]*?)\"\\s*\\/>/g)) {\n results.push({ name: m[1].trim(), instruction: null });\n }\n // Content form: <next_person name=\"Alice\">instruction</next_person>\n for (const m of output.matchAll(/<next_person\\s+name=\"([^\"]*?)\">([\\s\\S]*?)<\\/next_person>/g)) {\n results.push({ name: m[1].trim(), instruction: m[2].trim() || null });\n }\n return results;\n}\n\ninterface HireDirectivePayload {\n label: string;\n role: string;\n prompt: string;\n}\n\n/**\n * Parse <hire_person> directives from AI output.\n *\n * <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>\n */\nfunction parseRuneyaHireDirectives(output: string): HireDirectivePayload[] {\n const results: HireDirectivePayload[] = [];\n for (const m of output.matchAll(/<hire_person\\s+label=\"([^\"]*?)\"\\s+role=\"([^\"]*?)\">([\\s\\S]*?)<\\/hire_person>/g)) {\n const label = m[1].trim();\n const role = m[2].trim();\n const prompt = m[3].trim();\n if (label && role && prompt) results.push({ label, role, prompt });\n }\n return results;\n}\n\nconst HIRE_LAYOUT = {\n startY: 88,\n siblingGap: 24,\n minXInTeam: 20,\n minYInTeam: 36,\n nodeWidthEstimate: 180,\n nodeHeightEstimate: 50,\n groupRightPadding: 24,\n groupBottomPadding: 28,\n minGroupWidth: 300,\n minGroupHeight: 200,\n} as const;\n\nfunction computeHirePosition(manager: ScenarioNode, nodes: ScenarioNode[]): { x: number; y: number } {\n const sameTeamReports = nodes.filter((p) => p.parentIds[0] === manager.id && p.groupId === (manager.groupId ?? null));\n const managerX = Number.isFinite(manager.position?.x) ? manager.position.x : 140;\n const managerY = Number.isFinite(manager.position?.y) ? manager.position.y : 40;\n const baseY = managerY + HIRE_LAYOUT.startY;\n const rightMost = sameTeamReports\n .filter((p) => Number.isFinite(p.position?.x))\n .sort((a, b) => (a.position?.x ?? 0) - (b.position?.x ?? 0))\n .at(-1);\n\n let x = managerX;\n let y = baseY;\n if (rightMost) {\n x = (rightMost.position?.x ?? managerX) + HIRE_LAYOUT.nodeWidthEstimate + HIRE_LAYOUT.siblingGap;\n y = Math.max(baseY, rightMost.position?.y ?? baseY);\n }\n\n if (manager.groupId) {\n x = Math.max(HIRE_LAYOUT.minXInTeam, x);\n y = Math.max(HIRE_LAYOUT.minYInTeam, y);\n } else {\n x = Math.max(0, x);\n y = Math.max(0, y);\n }\n\n return { x, y };\n}\n\nfunction ensureGroupCanContainNode(scenario: Scenario, groupId: string | null, position: { x: number; y: number }): void {\n if (!groupId) return;\n const group = scenario.groups.find((t) => t.id === groupId);\n if (!group) return;\n\n const width = Number.isFinite(group.width) ? group.width : HIRE_LAYOUT.minGroupWidth;\n const height = Number.isFinite(group.height) ? group.height : HIRE_LAYOUT.minGroupHeight;\n\n const neededWidth = position.x + HIRE_LAYOUT.nodeWidthEstimate + HIRE_LAYOUT.groupRightPadding;\n const neededHeight = position.y + HIRE_LAYOUT.nodeHeightEstimate + HIRE_LAYOUT.groupBottomPadding;\n\n group.width = Math.max(width, HIRE_LAYOUT.minGroupWidth, neededWidth);\n group.height = Math.max(height, HIRE_LAYOUT.minGroupHeight, neededHeight);\n}\n\nfunction applyHireDirectivesFromOutput(\n manager: ScenarioNode,\n scenario: Scenario,\n output: string,\n): ScenarioNode[] {\n const hireDirectives = parseRuneyaHireDirectives(output);\n if (hireDirectives.length === 0) return [];\n if (!manager.canAddNode) {\n throw new Error(`${manager.label} attempted to hire without permission`);\n }\n\n const hired: ScenarioNode[] = [];\n for (const payload of hireDirectives) {\n const id = `hire-${randomUUID().slice(0, 8)}`;\n const position = computeHirePosition(manager, scenario.nodes);\n ensureGroupCanContainNode(scenario, manager.groupId ?? null, position);\n const node: ScenarioNode = {\n id,\n type: 'ai',\n parentIds: [manager.id],\n groupId: manager.groupId ?? null,\n label: payload.label,\n role: payload.role,\n prompt: payload.prompt,\n question: '',\n autoGenerated: true,\n canAddNode: false,\n aiCli: manager.aiCli ?? 'claude-code',\n model: '',\n position,\n injectParentOutputs: false,\n injectedAncestorIds: [],\n };\n scenario.nodes.push(node);\n hired.push(node);\n }\n return hired;\n}\n\nfunction selectExplicitDirectReportsFromOutput(\n manager: ScenarioNode,\n nodes: ScenarioNode[],\n managerOutput: string,\n): { selected: ScenarioNode[]; unknownNames: string[]; assignments: Map<string, string>; missingAssignments: string[] } {\n const directReports = getDirectReports(nodes, manager.id);\n\n const directives = parseRuneyaNextNodeDirectives(managerOutput);\n const normalizedDirectives = directives.map((d) => ({ norm: normalizeForMatch(d.name), instruction: d.instruction }));\n const stopDirective = normalizedDirectives.length === 1 && normalizedDirectives[0]!.norm === 'stop';\n if (normalizedDirectives.length === 0 || stopDirective) return { selected: [], unknownNames: [], assignments: new Map(), missingAssignments: [] };\n\n const selected: ScenarioNode[] = [];\n const assignments = new Map<string, string>();\n const matchedDirectives = new Set<string>();\n for (const report of directReports) {\n const fullName = normalizeForMatch(report.label);\n const reverseName = normalizeForMatch(`${report.label}`);\n const matched = normalizedDirectives.find((d) => d.norm === fullName || d.norm === reverseName);\n if (matched) {\n selected.push(report);\n matchedDirectives.add(matched.norm);\n if (matched.instruction) assignments.set(report.id, matched.instruction);\n }\n }\n const unknownNames = normalizedDirectives.filter((d) => d.norm !== 'stop' && !matchedDirectives.has(d.norm)).map((d) => d.norm);\n const missingAssignments = selected.filter((r) => !assignments.has(r.id)).map((r) => r.label);\n return { selected, unknownNames, assignments, missingAssignments };\n}\n\n\n\nfunction hasExplicitNoDelegationDecision(output: string): boolean {\n const nextDirectives = parseRuneyaNextNodeDirectives(output);\n // STOP is only valid when it is the single NEXT_PERSON directive.\n return nextDirectives.length === 1 && normalizeForMatch(nextDirectives[0]?.name ?? '') === 'stop';\n}\n\nfunction buildDelegationRetryMessage(\n manager: ScenarioNode,\n directReports: ScenarioNode[],\n userRequest: string,\n previousOutput: string,\n): string {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n\n return [\n `## Original Request`,\n userRequest,\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Delegation Retry (mandatory)`,\n `You must explicitly choose which direct reports to contact now.`,\n `Use the exact full names from the allowed list below.`,\n `If you still do not provide explicit names, your run will fail.`,\n ``,\n `## Allowed Direct Reports`,\n reportsList || '(none)',\n ``,\n ...(manager.canAddNode ? [\n `## Optional Hire Command`,\n `You may hire temporary contractors with:`,\n `<hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to run now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ``,\n ] : []),\n `## Output Format`,\n `Write one XML tag per selected node including their specific instruction:`,\n `<next_person name=\"FirstName LastName\">their specific task (multiline ok)</next_person>`,\n `Or explicitly choose no delegation with: <next_person name=\"STOP\" />`,\n ].join('\\n');\n}\n\nfunction buildMissingAssignmentsRetryMessage(\n _manager: ScenarioNode,\n missingNames: string[],\n previousOutput: string,\n): string {\n return [\n `## Missing Assignments`,\n `You selected the following nodes but did not provide a specific instruction for each:`,\n missingNames.map((n) => `- ${n}`).join('\\n'),\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Required Format`,\n `For each node listed above, output one XML tag with their instruction:`,\n `<next_person name=\"FirstName LastName\">their specific task instruction (multiline ok)</next_person>`,\n `The instruction content is mandatory. Be concise and actionable.`,\n ].join('\\n');\n}\n\nfunction buildManagerReviewMessage(\n manager: ScenarioNode,\n directReports: ScenarioNode[],\n userRequest: string,\n previousOutput: string,\n childReportsSection: string,\n): string {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n\n return [\n `## Original Request`,\n userRequest,\n ``,\n `## Your Previous Output`,\n `<previous_output>`,\n previousOutput,\n `</previous_output>`,\n ``,\n `## Children Reports Collected`,\n childReportsSection || '(none)',\n ``,\n `## Parent Review Decision (mandatory)`,\n `You are now in review mode after collecting child reports.`,\n `Your decision rule is simple:`,\n `- If the deliverable is complete and satisfies the original request → output <next_person name=\"STOP\" /> immediately. Do NOT re-run for process reasons (wrong node assigned, style preferences, etc.).`,\n `- If something is factually missing or incorrect in the deliverable → request a targeted re-run with precise instructions.`,\n `Use the exact full names from your direct reports list below.`,\n ``,\n `## Allowed Direct Reports`,\n reportsList || '(none)',\n ``,\n ...(manager.canAddNode ? [\n `## Optional Hire Command`,\n `You may hire temporary contractors with:`,\n `<hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to run now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ``,\n ] : []),\n `## Output Format`,\n `If no more child work is needed: output <next_person name=\"STOP\" /> first, then immediately write a complete synthesis of all children's deliverables so your parent can evaluate the result. Do NOT summarize — include the full content (scripts, outputs, data, etc.).`,\n `If refinement is needed, output one XML tag per selected node with their specific instruction:`,\n `<next_person name=\"FirstName LastName\">precise refinement instruction (multiline ok)</next_person>`,\n ].join('\\n');\n}\n\n// ─── Prompt builders ──────────────────────────────────────────────────────────\n\n\nfunction buildSystemPrompt(\n node: ScenarioNode,\n scenario: Scenario,\n): string {\n const group = scenario.groups.find(t => t.id === node.groupId);\n const manager = node.parentIds[0] ? scenario.nodes.find(p => p.id === node.parentIds[0]) : null;\n const reports = getDirectReports(scenario.nodes, node.id);\n\n const preset = scenario.presetId ? getPreset(scenario.presetId) : undefined;\n const presetRole = preset?.roles.find(r => r.id === (node.role ?? 'other'));\n const roleBehavior = presetRole?.systemPrompt ?? '';\n const rolePrompt = presetRole?.prompt ?? '';\n\n const lines = [\n `You are ${node.label}${group ? `, member of the ${group.name} group` : ''}.`,\n `Your role type: **${(node.role ?? 'other').toUpperCase()}**.`,\n '',\n ];\n\n if (roleBehavior) {\n lines.push('## Role Behavior (strictly enforce)', roleBehavior, '');\n }\n\n const profileSection = [node.prompt, rolePrompt].filter(Boolean).join('\\n\\n');\n lines.push('## Your Profile & Instructions', profileSection || '(No profile provided)', '');\n\n if (manager) {\n lines.push(`## Reporting Line`, `You report to ${manager.label} (${manager.role ?? 'other'}).`, '');\n } else {\n lines.push(`## Position`, `You are the leader of this scenario. You coordinate all groups.`, '');\n }\n\n if (reports.length > 0) {\n lines.push(\n `## Your Direct Reports`,\n ...reports.map(r => {\n const rGroup = scenario.groups.find(g => g.id === r.groupId);\n const groupInfo = rGroup\n ? ` | group: ${rGroup.name}${rGroup.description ? ` (${rGroup.description})` : ''}`\n : '';\n return `- ${r.label} (${r.role ?? 'other'})${groupInfo}: ${r.prompt || '(No profile provided)'}`;\n }),\n '',\n );\n }\n\n if (node.canAddNode) {\n lines.push(\n '## Hiring Capability',\n 'You are allowed to hire temporary contractors for this run.',\n 'Use exactly: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>',\n 'Any hired node will automatically be placed in your own group.',\n 'To execute the hired node in this run, also output: <next_person name=\"Jane Doe\">their task</next_person>',\n '',\n );\n }\n\n lines.push(\n '## Output Instructions',\n 'Write your output clearly and in a structured format.',\n 'Stay strictly within your role — do not produce deliverables that belong to a different role.',\n 'Be concise and actionable.',\n 'Only use <ask_user>...</ask_user> when you are genuinely blocked by missing information that no one in the group can provide (e.g. a secret, a business decision, an external credential). NEVER use it to ask for confirmation, approval, or readiness (e.g. \"are you ready?\", \"shall I proceed?\"). Always proceed autonomously unless truly blocked.',\n );\n\n // Inject RUNEYA_AI_* environment variables\n const runeya_ai_vars = Object.entries(process.env)\n .filter(([k]) => k.startsWith('RUNEYA_AI_'))\n .map(([k, v]) => `${k}=${v}`)\n .join('\\n');\n if (runeya_ai_vars) {\n lines.push('', '## Environment', '', runeya_ai_vars);\n }\n\n return lines.join('\\n');\n}\n\nfunction buildUserMessage(\n node: ScenarioNode,\n scenario: Scenario,\n userRequest: string,\n managerOutput: string | null,\n isLeaderSynthesis: boolean,\n isLeaderDispatch: boolean,\n allOutputs?: Map<string, string>,\n): string {\n const parts: string[] = [];\n\n if (node.prompt) {\n parts.push(`## Your Profile & Instructions (reminder)\\n\\n${node.prompt}`);\n }\n\n parts.push(`## Original Request\\n\\n${userRequest}`);\n\n if (isLeaderSynthesis && allOutputs) {\n // Leader's final synthesis pass: receive all group outputs\n const teamSection = scenario.nodes\n .filter(p => p.id !== scenario.leaderId && allOutputs.has(p.id))\n .map(p => {\n const name = p.label.trim() || p.id;\n const output = allOutputs.get(p.id) ?? '';\n return `<team_member id=\"${p.id}\" name=\"${name}\">\\n${output}\\n</team_member>`;\n })\n .join('\\n\\n');\n\n if (teamSection) {\n parts.push(`## Your Group's Outputs\\n\\n${teamSection}`);\n }\n\n parts.push(\n `## Your Task`,\n `Synthesize all group outputs above and deliver a final, comprehensive answer to the original request.`,\n `Highlight key results, decisions, and any remaining open points.`,\n );\n } else if (isLeaderDispatch) {\n // Leader's dispatch pass: break down the request and assign sub-tasks\n const directReports = getDirectReports(scenario.nodes, node.id);\n const reportsList = directReports\n .map(r => {\n const group = scenario.groups.find(t => t.id === r.groupId);\n return `- ${r.label} | role: ${r.role ?? 'other'}${group ? ` | group: ${group.name}${group.description ? ` (${group.description})` : ''}` : ''} | profile: ${r.prompt || 'no description'}`;\n })\n .join('\\n');\n\n parts.push(\n `## Your Direct Reports\\n\\n${reportsList || '(none)'}`,\n `## Your Task`,\n `As the leader, your role here is STRICTLY to delegate — NEVER to solve the request yourself.`,\n `Do NOT ask yourself whether you should answer directly or delegate. You ALWAYS delegate.`,\n `⚠️ IMPORTANT: Before selecting anyone, re-read your Profile & Instructions above. Any constraint written there (e.g. \"do not contact X\", \"must hire someone\") is MANDATORY and overrides everything else.`,\n `Instead, analyze the request and produce a clear **delegation plan**:`,\n `1. Break down the request into concrete sub-tasks, one per direct report (or group of reports if relevant).`,\n `2. For each node, write a specific, actionable assignment that fits their role and expertise.`,\n `3. Provide any strategic context, constraints, or success criteria they need.`,\n `4. Do NOT produce the final answer — your group will do that. You coordinate.`,\n `5. IMPORTANT: explicitly mention the exact full name of each direct report you want to contact. Only explicitly mentioned nodes will be executed.`,\n `6. For each node you assign, output one XML tag with their name AND specific instruction: <next_person name=\"FirstName LastName\">their specific instruction (multiline ok)</next_person>`,\n `7. If you intentionally decide to contact nobody, write exactly: <next_person name=\"STOP\" />`,\n ...(node.canAddNode ? [\n `8. You may hire temporary contractors with: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `9. Hired nodes are always placed in your own group (no group field needed).`,\n `10. If you hire someone and want them to execute now, also include: <next_person name=\"Jane Doe\">their task</next_person>`,\n ] : []),\n ``,\n `Format your output as a brief intro followed by one clearly labeled section per direct report.`,\n );\n } else {\n if (managerOutput) {\n const manager = scenario.nodes.find(p => p.id === node.parentIds[0]);\n const managerName = manager ? manager.label.trim() : 'your manager';\n parts.push(\n `## Assignment from ${managerName}\\n\\n<manager_output>\\n${managerOutput}\\n</manager_output>`,\n );\n }\n\n // Inject outputs from explicitly selected ancestor nodes\n if (allOutputs && !isLeaderSynthesis) {\n const injectedIds = new Set<string>();\n // Always inject all parent outputs when the node has multiple parents (aggregation node),\n // or when explicitly requested via injectParentOutputs.\n if (node.injectParentOutputs || node.parentIds.length > 1) {\n for (const pid of node.parentIds) injectedIds.add(pid);\n }\n for (const aid of (node.injectedAncestorIds ?? [])) injectedIds.add(aid);\n // Remove first parent since its output is already shown as \"Assignment from manager\" (avoid duplicate)\n injectedIds.delete(node.parentIds[0] ?? '');\n\n const prevOutputs = scenario.nodes\n .filter(p => injectedIds.has(p.id) && allOutputs.has(p.id))\n .map(p => {\n const name = p.label.trim() || p.id;\n const output = allOutputs.get(p.id) ?? '';\n return `<context_node id=\"${p.id}\" name=\"${name}\">\\n${output}\\n</context_node>`;\n })\n .join('\\n\\n');\n if (prevOutputs) {\n parts.push(`## Context from Related Nodes\\n\\n${prevOutputs}`);\n }\n }\n\n parts.push(\n `## Your Task`,\n `Based on the original request${managerOutput ? ' and your manager\\'s assignment above' : ''}${allOutputs && !isLeaderSynthesis && ((node.parentIds.length > 1 || node.injectParentOutputs) || (node.injectedAncestorIds ?? []).length > 0) ? ' and the context from related nodes above' : ''}, ` +\n `complete your specific part according to your role and expertise. ` +\n `Be thorough and actionable. Report your output clearly — your manager will use it for the final synthesis.`,\n );\n\n const directReports = getDirectReports(scenario.nodes, node.id);\n if (directReports.length > 0) {\n const reportsList = directReports\n .map((r) => `- ${r.label} | role: ${r.role ?? 'other'} | profile: ${r.prompt || 'no description'}`)\n .join('\\n');\n parts.push(\n ...(node.canAddNode ? [\n `## Hiring (available to you)`,\n `You may hire a temporary contractor for this run: <hire_person label=\"Jane Doe\" role=\"engineer\">Task focus prompt</hire_person>`,\n `If you hire someone and want them to execute immediately, also add: <next_person name=\"Jane Doe\">their task</next_person>`,\n `Hired nodes join your group automatically — no group field needed.`,\n ] : []),\n `## Direct Reports You Can Also Contact\\n\\n${reportsList}`,\n `⚠️ MANDATORY: Re-read your Profile & Instructions above before selecting anyone. Any constraint there (e.g. \"do not contact X\", \"must hire\") overrides everything.`,\n `For each node you assign, output one XML tag with their name AND specific instruction: <next_person name=\"FirstName LastName\">their specific instruction (multiline ok)</next_person>`,\n `Only names declared with <next_person> will run.`,\n `If you intentionally choose to delegate to nobody, write: <next_person name=\"STOP\" />`,\n );\n }\n }\n\n return parts.join('\\n\\n');\n}\n\n// ─── Single-node AI call (streaming) ───────────────────────────────────────\n\nfunction resolveNodeExecutionConfig(\n node: ScenarioNode,\n runOverrides?: ScenarioRunOverrides,\n): { aiCli: 'claude-code' | 'codex'; model: string } {\n const baseCli = node.aiCli ?? 'claude-code';\n const aiCli = runOverrides?.runnerOverride ?? baseCli;\n const crossFamily = !!runOverrides?.runnerOverride && runOverrides.runnerOverride !== baseCli;\n const modelOverride = runOverrides?.modelOverride?.trim() ?? '';\n const nodeModel = node.model?.trim() ?? '';\n const model = modelOverride || (crossFamily ? DEFAULT_NODE_MODELS[aiCli] : (nodeModel || DEFAULT_NODE_MODELS[aiCli]));\n return { aiCli, model };\n}\n\n// ─── Per-node runner state (session continuity across ASK_USER loops) ───────\n\ninterface NodeRunnerState {\n runner: AiRunner;\n sessionId: string;\n isResume: boolean;\n}\n\nfunction createNodeRunnerState(aiCli: 'claude-code' | 'codex'): NodeRunnerState {\n return {\n runner: aiCli === 'codex' ? new CodexRunner() : new ClaudeCodeRunner(),\n sessionId: '',\n isResume: false,\n };\n}\n\nasync function runNodeCall(\n conversationId: string,\n node: ScenarioNode,\n systemContext: string,\n userMessage: string,\n runOverrides: ScenarioRunOverrides | undefined,\n signal: AbortSignal,\n publish: (evt: ScenarioEvent) => void,\n onDelta: (text: string) => void,\n runnerStates: Map<string, NodeRunnerState>,\n label = 'call',\n readme?: (text: string) => Promise<void>,\n): Promise<string> {\n publish({ type: 'node_prompt', nodeId: node.id, label, systemContext, userMessage });\n const { aiCli, model } = resolveNodeExecutionConfig(node, runOverrides);\n\n if (!runnerStates.has(node.id)) {\n runnerStates.set(node.id, createNodeRunnerState(aiCli));\n }\n const state = runnerStates.get(node.id)!;\n\n let currentPrompt = userMessage;\n let accumulated = '';\n let persistTimer: ReturnType<typeof setTimeout> | null = null;\n\n const schedulePersist = () => {\n if (persistTimer) return;\n persistTimer = setTimeout(() => {\n persistTimer = null;\n appendNodeOutput(conversationId, node, accumulated).catch(() => {});\n }, 500);\n };\n\n const flushPersist = () => {\n if (persistTimer) { clearTimeout(persistTimer); persistTimer = null; }\n };\n\n while (true) {\n const turnStart = Date.now();\n\n const result = await state.runner.run({\n agentId: runOverrides?.agentId ?? agentManager.getDefaultAgentId() ?? undefined,\n sessionId: state.sessionId,\n prompt: currentPrompt,\n isResume: state.isResume,\n systemContext,\n apiBaseUrl: '',\n apiToken: '',\n model,\n effort: 'normal',\n signal,\n onDelta: (text) => {\n accumulated += text;\n onDelta(text);\n schedulePersist();\n },\n onStatus: (text) => publish({ type: 'node_status', nodeId: node.id, text }),\n onToolCall: (id, name, input, rawInput) => publish({ type: 'node_tool_call', nodeId: node.id, id, name, input, rawInput }),\n onToolResult: (id, result, isError) => publish({ type: 'node_tool_result', nodeId: node.id, id, result, isError }),\n onThinking: (text) => publish({ type: 'node_thinking', nodeId: node.id, text }),\n onCommand: (cmd) => publish({ type: 'node_command', nodeId: node.id, command: cmd }),\n });\n\n flushPersist();\n // Update to the actual session ID reported by claude (may differ from our initial UUID)\n if (result.actualSessionId) state.sessionId = result.actualSessionId;\n state.isResume = true;\n\n if (result.tokenStatus === 'ask_user') {\n publish({ type: 'node_duration', nodeId: node.id, durationMs: Date.now() - turnStart });\n scenarioRunStore.setNodeState(conversationId, node.id, 'waiting_input');\n scenarioRunStore.setWaitingInput(conversationId, node.id, result.tokenMessage);\n flushPersist();\n publish({ type: 'node_waiting_input', nodeId: node.id, question: result.tokenMessage });\n await readme?.(`- ❓ [${formatTs()}] **${node.label}** — waiting for user input\\n`);\n\n const answer = await new Promise<string>((resolve, reject) => {\n const key = pendingNodeKey(conversationId, node.id);\n pendingNodeInputs.set(key, resolve);\n signal.addEventListener('abort', () => {\n pendingNodeInputs.delete(key);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n\n scenarioRunStore.clearWaitingInput(conversationId, node.id);\n await readme?.(`- 💬 [${formatTs()}] **User replied** to ${node.label}\\n`);\n const qaBlock = `\\n\\n---\\n**Question:** ${result.tokenMessage}\\n\\n**Your answer:** ${answer}\\n`;\n await appendNodeOutput(conversationId, node, qaBlock);\n publish({ type: 'node_delta', nodeId: node.id, text: qaBlock });\n accumulated = '';\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n publish({ type: 'node_started', nodeId: node.id });\n currentPrompt = `L'utilisateur a répondu : ${answer}`;\n continue;\n }\n\n publish({ type: 'node_duration', nodeId: node.id, durationMs: Date.now() - turnStart });\n return result.output;\n }\n}\n\n// ─── Persist output to workspace file ────────────────────────────────────────\n\nfunction getScenarioRunDir(conversationId: string): string | null {\n try {\n return resolveConversationRunDir('scenario-runs', conversationId);\n } catch {\n return null;\n }\n}\n\nasync function appendNodeOutput(conversationId: string, node: ScenarioNode, output: string): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const slug = node.label.toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 60) || 'member';\n const safeId = node.id.replace(/[^a-z0-9_-]/gi, '-').slice(0, 80);\n const filePath = join(dir, `${slug}_${safeId}.md`);\n\n const content = `## Output\\n\\n${output}\\n`;\n await atomicWriteSecure(filePath, content);\n}\n\nasync function appendToReadme(\n conversationId: string,\n bus: RunBus,\n text: string,\n): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const line = `${text}\\n`;\n try {\n await mkdir(dir, { recursive: true });\n const { appendFile } = await import('node:fs/promises');\n await appendFile(join(dir, 'README.md'), line, 'utf-8');\n } catch {\n // Non-fatal — still publish the event even if disk write fails\n }\n publishToBus(bus, { type: 'readme_append', text: line });\n}\n\nasync function writeFinalMd(\n conversationId: string,\n bus: RunBus,\n userRequest: string,\n content: string,\n): Promise<void> {\n const dir = getScenarioRunDir(conversationId);\n if (!dir) return;\n\n const fullContent = `# Final Report\\n\\n## User Request\\n\\n> ${userRequest.replace(/\\n/g, '\\n> ')}\\n\\n---\\n\\n## Result\\n\\n${content}\\n`;\n\n const filePath = join(dir, 'FINAL.md');\n await atomicWriteSecure(filePath, fullContent);\n\n // Stream FINAL.md content as readme_append so UI sees it inline\n await appendToReadme(conversationId, bus,\n `\\n---\\n\\n## ✅ FINAL REPORT\\n\\n**User request:**\\n\\n> ${userRequest.replace(/\\n/g, '\\n> ')}\\n\\n${content}\\n`,\n );\n}\n\n// ─── Main orchestration ───────────────────────────────────────────────────────\n\n/**\n * Runs the scenario multi-agent workflow for a given conversation.\n * Execution order: BFS level by level (leader → direct reports → their reports, …).\n * Nodes at the same level run in parallel.\n * After all agents complete, the leader runs a synthesis pass.\n * All events are published to the run bus so late subscribers can reconnect.\n */\nfunction applyRunOverridesToScenario(\n scenario: Scenario,\n runOverrides?: ScenarioRunOverrides,\n): Scenario {\n if (!runOverrides?.runnerOverride && !runOverrides?.modelOverride?.trim()) return scenario;\n return {\n ...scenario,\n nodes: scenario.nodes.map((node) => {\n const { aiCli, model } = resolveNodeExecutionConfig(node, runOverrides);\n return { ...node, aiCli, model };\n }),\n };\n}\n\nexport async function runScenario(\n conversationId: string,\n scenarioId: string,\n userRequest: string,\n runOverrides?: ScenarioRunOverrides,\n resume?: boolean,\n): Promise<void> {\n if (isScenarioRunning(conversationId)) return;\n\n const bus = createBus(conversationId);\n const ctrl = new AbortController();\n activeAbortControllers.set(conversationId, ctrl);\n const signal = ctrl.signal;\n\n const publish = (evt: ScenarioEvent) => publishToBus(bus, evt);\n const readme = (text: string) => appendToReadme(conversationId, bus, text);\n // Bullet list item with automatic timestamp prefix: `- emoji [ts] rest`\n const li = (emoji: string, content: string) => readme(`- ${emoji} [${formatTs()}] ${content}\\n`);\n\n const ts = () => formatTs();\n const fmtDuration = (startMs: number) => {\n const ms = Math.max(0, Date.now() - startMs);\n const sec = ms / 1000;\n return sec < 10 ? `${sec.toFixed(1)}s` : `${Math.round(sec)}s`;\n };\n\n let finalWritten = false;\n\n async function execute() {\n try {\n const scenario: Scenario = await (async () => {\n const base = await scenarioRunStore.loadScenarioSnapshot(conversationId)\n ?? await scenarioStore.get(scenarioId);\n if (!base) throw new Error(`Scenario ${scenarioId} not found`);\n // Apply overrides in memory only — snapshot on disk stays clean\n return applyRunOverridesToScenario(base, runOverrides);\n })();\n const leader = scenario.nodes.find((p) => p.id === scenario.leaderId);\n if (!leader) throw new Error('Scenario has no leader');\n\n // Build parent→children map for hierarchy lookups\n const byParent = new Map<string, ScenarioNode[]>();\n const nodesById = new Map(scenario.nodes.map((p) => [p.id, p]));\n\n // outputs[nodeId] = full text output of that node\n const outputs = new Map<string, string>();\n let leaderDispatchOutput: string | null = null;\n let leaderDispatchAssignments: Map<string, string> = new Map();\n\n // Runner state per node — preserves session for ASK_USER continuations\n const runnerStates = new Map<string, NodeRunnerState>();\n\n // ── Resume: load persisted state and pre-populate outputs for done persons ──\n const persistedState = resume\n ? await scenarioRunStore.loadPersistedRunState(conversationId)\n : null;\n\n function isSubtreeComplete(nodeId: string): boolean {\n if (!persistedState) return false;\n const state = persistedState.nodeStates[nodeId];\n if (state !== 'done' && state !== 'synthesized') return false;\n for (const child of getDirectReports(scenario.nodes, nodeId)) {\n if (!isSubtreeComplete(child.id)) return false;\n }\n return true;\n }\n\n if (persistedState) {\n for (const [nodeId, output] of Object.entries(persistedState.nodeOutputs)) {\n const state = persistedState.nodeStates[nodeId];\n if (state === 'done' || state === 'synthesized') {\n outputs.set(nodeId, output);\n scenarioRunStore.setNodeState(conversationId, nodeId, state as NodeState);\n scenarioRunStore.setNodeOutput(conversationId, nodeId, output);\n }\n }\n }\n\n if (resume) {\n await readme(`\\n---\\n\\n## ♻️ Run resumed — ${ts()}\\n`);\n } else {\n await readme(`\\n## Run started — ${ts()}\\n\\n**User request:**\\n\\n> ${userRequest.replace(/\\n/g, '\\n> ')}\\n`);\n }\n\n // Resume: restore leader dispatch from cache if available\n let leaderDispatchHandled = false;\n if (persistedState && outputs.has(leader.id)) {\n const cachedOut = outputs.get(leader.id)!;\n leaderDispatchOutput = cachedOut;\n const leaderResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, cachedOut);\n byParent.set(leader.id, leaderResult.selected);\n leaderDispatchAssignments = leaderResult.assignments;\n const leaderState = leaderResult.selected.length > 0 ? 'waiting' : 'done';\n scenarioRunStore.setNodeState(conversationId, leader.id, leaderState);\n publish({ type: 'node_state_change', nodeId: leader.id, state: leaderState });\n publish({ type: 'node_done', nodeId: leader.id, output: cachedOut, state: leaderState });\n await li('♻️', `**${leader.label}** (Leader) — restored from previous run`);\n leaderDispatchHandled = true;\n }\n\n // Leader dispatch phase — hierarchical mode only\n if (scenario.traversalMode !== 'topological' && !leaderDispatchHandled) {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: leader.id });\n scenarioRunStore.setNodeState(conversationId, leader.id, 'running');\n await readme(`### [${ts()}] 📋 ${leader.label} (Leader) — dispatching assignments\\n`);\n await li('▶️', `**${leader.label}** — started`);\n\n try {\n const systemPrompt = buildSystemPrompt(leader, scenario);\n const userMsg = buildUserMessage(leader, scenario, userRequest, null, false, true);\n const out = await runNodeCall(conversationId, leader, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: leader.id, text: delta });\n }, runnerStates, 'dispatch', readme);\n\n outputs.set(leader.id, out);\n leaderDispatchOutput = out;\n const hiredByLeader = applyHireDirectivesFromOutput(leader, scenario, out);\n if (hiredByLeader.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${leader.label} hired: ${hiredByLeader.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const directReports = getDirectReports(scenario.nodes, leader.id);\n const leaderResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, out);\n // Auto-include hired nodes not already named in NEXT_PERSON\n const seenIds = new Set(leaderResult.selected.map((r) => r.id));\n for (const h of hiredByLeader) { if (!seenIds.has(h.id)) { leaderResult.selected.push(h); seenIds.add(h.id); } }\n let assignedReports = leaderResult.selected;\n let leaderAssignments = leaderResult.assignments;\n let explicitStop = hasExplicitNoDelegationDecision(out);\n let finalLeaderOutput = out;\n const needsRetry = directReports.length > 0 && assignedReports.length === 0 && !explicitStop;\n const hasUnknown = leaderResult.unknownNames.length > 0;\n const hasMissingAssignments = leaderResult.missingAssignments.length > 0;\n if (needsRetry || hasUnknown || hasMissingAssignments) {\n if (hasUnknown) await li('⚠️', `Unknown node(s) named by ${leader.label}: ${leaderResult.unknownNames.join(', ')}. Retrying.`);\n else if (hasMissingAssignments) await li('⚠️', `Missing assignments for ${leaderResult.missingAssignments.join(', ')} from ${leader.label}. Retrying.`);\n else await li('⚠️', `No explicit assignees parsed for ${leader.label}. Retrying once to force explicit selection.`);\n const retryUserMsg = hasMissingAssignments\n ? buildMissingAssignmentsRetryMessage(leader, leaderResult.missingAssignments, out)\n : buildDelegationRetryMessage(leader, directReports, userRequest, out);\n // Fresh session for retry — --resume on a killed/early-exited process is unreliable\n runnerStates.delete(leader.id);\n const retryOut = await runNodeCall(conversationId, leader, systemPrompt, retryUserMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: leader.id, text: delta });\n }, runnerStates, 'dispatch-retry', readme);\n const hiredOnRetry = applyHireDirectivesFromOutput(leader, scenario, retryOut);\n if (hiredOnRetry.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${leader.label} hired on retry: ${hiredOnRetry.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const retryResult = selectExplicitDirectReportsFromOutput(leader, scenario.nodes, retryOut);\n const seenRetryIds = new Set(retryResult.selected.map((r) => r.id));\n for (const h of hiredOnRetry) { if (!seenRetryIds.has(h.id)) { retryResult.selected.push(h); seenRetryIds.add(h.id); } }\n assignedReports = retryResult.selected;\n leaderAssignments = new Map([...leaderAssignments, ...retryResult.assignments]);\n explicitStop = hasExplicitNoDelegationDecision(retryOut);\n finalLeaderOutput = `${out}\\n\\n## Delegation Retry Output\\n${retryOut}`;\n if (assignedReports.length === 0 && !explicitStop) {\n throw new Error(`No explicit assignees parsed for ${leader.label} after retry`);\n }\n if (assignedReports.length > 0) {\n await li('✅', `Explicit assignees parsed for ${leader.label} after retry.`);\n }\n }\n if (assignedReports.length === 0 && explicitStop) {\n await li('⏹️', `${leader.label} explicitly chose to delegate to nobody (STOP).`);\n }\n\n outputs.set(leader.id, finalLeaderOutput);\n leaderDispatchOutput = finalLeaderOutput;\n await appendNodeOutput(conversationId, leader, finalLeaderOutput);\n\n byParent.set(leader.id, assignedReports);\n scenarioRunStore.setNodeState(conversationId, leader.id, assignedReports.length > 0 ? 'waiting' : 'done');\n scenarioRunStore.setNodeOutput(conversationId, leader.id, finalLeaderOutput);\n await scenarioRunStore.persistRunState(conversationId);\n\n for (const report of assignedReports) {\n await li('→', `**${report.label}** assigned by ${leader.label}`);\n }\n leaderDispatchAssignments = leaderAssignments;\n await li('✅', `**${leader.label}** (Leader) — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: leader.id, output: finalLeaderOutput, state: scenarioRunStore.getRunState(conversationId)?.nodeStates[leader.id] ?? 'done' });\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, leader.id, 'error');\n await readme(`### [${ts()}] ❌ ${leader.label} (Leader) — FAILED after ${fmtDuration(startedAt)}: ${msg}\\n`);\n publish({ type: 'node_error', nodeId: leader.id, error: msg });\n runnerStates.delete(leader.id);\n const leaderErrorOutput = `❌ Leader failed: ${msg}`;\n scenarioRunStore.setNodeOutput(conversationId, leader.id, leaderErrorOutput);\n await appendNodeOutput(conversationId, leader, leaderErrorOutput);\n publish({ type: 'node_delta', nodeId: leader.id, text: `\\n\\n${leaderErrorOutput}` });\n throw new Error(`Leader failed: ${msg}`);\n }\n }\n\n // Group execution with parent review loops:\n // manager executes -> children execute -> manager reviews and decides STOP or targeted re-run.\n async function runDelegationPass(\n node: ScenarioNode,\n userMsg: string,\n modeLabel: string,\n ): Promise<{ finalOutput: string; assignedReports: ScenarioNode[]; assignments: Map<string, string> }> {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n await li('▶️', `**${node.label}** — started`);\n try {\n const manager = node.parentIds[0] ? nodesById.get(node.parentIds[0]) ?? null : null;\n const systemPrompt = buildSystemPrompt(node, scenario);\n const out = await runNodeCall(conversationId, node, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, modeLabel, readme);\n const hiredByNode = applyHireDirectivesFromOutput(node, scenario, out);\n if (hiredByNode.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${node.label} hired: ${hiredByNode.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n\n const directReports = getDirectReports(scenario.nodes, node.id);\n let nodeResult = selectExplicitDirectReportsFromOutput(node, scenario.nodes, out);\n const seenIds = new Set(nodeResult.selected.map((r) => r.id));\n for (const h of hiredByNode) { if (!seenIds.has(h.id)) { nodeResult.selected.push(h); seenIds.add(h.id); } }\n let assignedReports = nodeResult.selected;\n let assignments = nodeResult.assignments;\n let explicitStop = hasExplicitNoDelegationDecision(out);\n let finalOutput = out;\n const needsRetry = directReports.length > 0 && assignedReports.length === 0 && !explicitStop;\n const hasUnknown = nodeResult.unknownNames.length > 0;\n const hasMissingAssignments = nodeResult.missingAssignments.length > 0;\n if (needsRetry || hasUnknown || hasMissingAssignments) {\n if (hasUnknown) await li('⚠️', `Unknown node(s) named by ${node.label}: ${nodeResult.unknownNames.join(', ')}. Retrying.`);\n else if (hasMissingAssignments) await li('⚠️', `Missing assignments for ${nodeResult.missingAssignments.join(', ')} from ${node.label}. Retrying.`);\n else await li('⚠️', `No explicit assignees parsed for ${node.label}. Retrying once to force explicit selection.`);\n const retryUserMsg = hasMissingAssignments\n ? buildMissingAssignmentsRetryMessage(node, nodeResult.missingAssignments, out)\n : buildDelegationRetryMessage(node, directReports, userRequest, out);\n // Fresh session for retry — --resume on a killed/early-exited process is unreliable\n runnerStates.delete(node.id);\n const retryOut = await runNodeCall(conversationId, node, systemPrompt, retryUserMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, `${modeLabel}-retry`, readme);\n const hiredOnRetry = applyHireDirectivesFromOutput(node, scenario, retryOut);\n if (hiredOnRetry.length > 0) {\n await scenarioRunStore.saveScenarioSnapshot(conversationId, scenario);\n await li('🆕', `${node.label} hired on retry: ${hiredOnRetry.map((p) => `${p.label} (${p.role})`).join(', ')}`);\n }\n const retryResult = selectExplicitDirectReportsFromOutput(node, scenario.nodes, retryOut);\n const seenRetryIds = new Set(retryResult.selected.map((r) => r.id));\n for (const h of hiredOnRetry) { if (!seenRetryIds.has(h.id)) { retryResult.selected.push(h); seenRetryIds.add(h.id); } }\n assignedReports = retryResult.selected;\n assignments = new Map([...assignments, ...retryResult.assignments]);\n explicitStop = hasExplicitNoDelegationDecision(retryOut);\n finalOutput = `${out}\\n\\n## Delegation Retry Output\\n${retryOut}`;\n if (assignedReports.length === 0 && !explicitStop) {\n throw new Error(`No explicit assignees parsed for ${node.label} after retry`);\n }\n if (assignedReports.length > 0) {\n await li('✅', `Explicit assignees parsed for ${node.label} after retry.`);\n }\n }\n if (assignedReports.length === 0 && explicitStop) {\n await li('⏹️', `${node.label} explicitly chose to delegate to nobody (STOP).`);\n }\n\n outputs.set(node.id, finalOutput);\n await appendNodeOutput(conversationId, node, finalOutput);\n byParent.set(node.id, assignedReports);\n\n scenarioRunStore.setNodeState(conversationId, node.id, assignedReports.length > 0 ? 'waiting' : 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, finalOutput);\n await scenarioRunStore.persistRunState(conversationId);\n\n if (assignedReports.length > 0) {\n for (const report of assignedReports) {\n await li('→', `**${report.label}** assigned by ${node.label}`);\n }\n }\n const reportTo = manager ? manager.label : 'Leader';\n await li('✅', `**${node.label}** (${node.role ?? 'other'}) — done in ${fmtDuration(startedAt)}, reporting to ${reportTo}`);\n publish({ type: 'node_done', nodeId: node.id, output: finalOutput, state: scenarioRunStore.getRunState(conversationId)?.nodeStates[node.id] ?? 'done' });\n return { finalOutput, assignedReports, assignments };\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, node.id, 'error');\n await li('❌', `**${node.label}** — error after ${fmtDuration(startedAt)}: ${msg}`);\n publish({ type: 'node_error', nodeId: node.id, error: msg });\n // Reset runner state so next retry starts a fresh session\n runnerStates.delete(node.id);\n const errorOutput = `[ERROR: ${node.label} failed — ${msg}]\\n\\n${outputs.get(node.id) ?? ''}`.trim();\n outputs.set(node.id, errorOutput);\n scenarioRunStore.setNodeOutput(conversationId, node.id, errorOutput);\n await appendNodeOutput(conversationId, node, `\\n\\n❌ Error: ${msg}`);\n publish({ type: 'node_delta', nodeId: node.id, text: `\\n\\n❌ Error: ${msg}` });\n return { finalOutput: errorOutput, assignedReports: [], assignments: new Map() };\n }\n }\n\n async function runAskNode(node: ScenarioNode): Promise<string> {\n const question = node.question?.trim() || node.label || node.id;\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'waiting_input');\n scenarioRunStore.setWaitingInput(conversationId, node.id, question);\n publish({ type: 'node_waiting_input', nodeId: node.id, question });\n await readme(`- ❓ [${ts()}] **${node.label || node.id}** — waiting for user input\\n`);\n\n const answer = await new Promise<string>((resolve, reject) => {\n const key = pendingNodeKey(conversationId, node.id);\n pendingNodeInputs.set(key, resolve);\n signal.addEventListener('abort', () => {\n pendingNodeInputs.delete(key);\n reject(new Error('Aborted'));\n }, { once: true });\n });\n\n scenarioRunStore.clearWaitingInput(conversationId, node.id);\n await readme(`- 💬 [${ts()}] **User replied** to ${node.label || node.id}\\n`);\n const output = `**Question:** ${question}\\n\\n**Answer:** ${answer}`;\n scenarioRunStore.setNodeOutput(conversationId, node.id, output);\n outputs.set(node.id, output);\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n publish({ type: 'node_done', nodeId: node.id, output, state: 'done' });\n return output;\n }\n\n async function runNodeSubtree(node: ScenarioNode, managerOutput: string | null): Promise<void> {\n // Ask node: skip AI entirely, wait for human input\n if (node.type === 'ask') {\n if (!isSubtreeComplete(node.id)) await runAskNode(node);\n else {\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id) ?? '', state: 'done' });\n }\n return;\n }\n\n // Resume: skip entire subtree if all persons in it are done\n if (isSubtreeComplete(node.id)) {\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id) ?? '', state: 'done' });\n return;\n }\n\n // Resume: if this node's own execution is cached but children aren't all done,\n // use cached output to derive delegation (skip the AI call for this node only)\n let firstPassResult: { finalOutput: string; assignedReports: ScenarioNode[]; assignments: Map<string, string> };\n if (persistedState && outputs.has(node.id)) {\n const cachedOut = outputs.get(node.id)!;\n const result = selectExplicitDirectReportsFromOutput(node, scenario.nodes, cachedOut);\n byParent.set(node.id, result.selected);\n const newState = result.selected.length > 0 ? 'waiting' : 'done';\n scenarioRunStore.setNodeState(conversationId, node.id, newState);\n scenarioRunStore.setNodeOutput(conversationId, node.id, cachedOut);\n publish({ type: 'node_state_change', nodeId: node.id, state: newState });\n publish({ type: 'node_done', nodeId: node.id, output: cachedOut, state: newState });\n await li('♻️', `**${node.label}** — restored from previous run`);\n firstPassResult = { finalOutput: cachedOut, assignedReports: result.selected, assignments: result.assignments };\n } else {\n const initialUserMsg = buildUserMessage(node, scenario, userRequest, managerOutput, false, false);\n firstPassResult = await runDelegationPass(node, initialUserMsg, '(execution)');\n }\n\n let { finalOutput, assignedReports, assignments } = firstPassResult;\n\n let reviewRound = 0;\n while (assignedReports.length > 0) {\n if (signal.aborted) throw new Error('Aborted');\n reviewRound += 1;\n if (reviewRound > MAX_MANAGER_REVIEW_ROUNDS) {\n throw new Error(`${node.label} exceeded review loop limit (${MAX_MANAGER_REVIEW_ROUNDS})`);\n }\n\n await readme(`\\n### [${ts()}] Review loop ${reviewRound} for ${node.label} — collecting child reports\\n`);\n await Promise.all(assignedReports.map((report) => {\n const instruction = assignments.get(report.id) ?? null;\n return runNodeSubtree(report, instruction ?? finalOutput);\n }));\n\n const childReportsSection = assignedReports\n .map((report) => {\n const reportOut = outputs.get(report.id) ?? '';\n return `<child_report node=\"${report.label}\" id=\"${report.id}\">\\n${reportOut}\\n</child_report>`;\n })\n .join('\\n\\n');\n\n const reviewUserMsg = buildManagerReviewMessage(\n node,\n getDirectReports(scenario.nodes, node.id),\n userRequest,\n finalOutput,\n childReportsSection,\n );\n const pass = await runDelegationPass(node, reviewUserMsg, `(review round ${reviewRound})`);\n finalOutput = pass.finalOutput;\n assignedReports = pass.assignedReports;\n assignments = pass.assignments;\n }\n }\n\n if (scenario.traversalMode === 'topological') {\n // ── Topological mode: level-by-level, siblings run in parallel ──\n // Helper: get all parent IDs of a node (parentId + parentIds)\n const allParentIds = (n: ScenarioNode): string[] => n.parentIds ?? [];\n // Helper: get all children of a node (nodes that list it as any parent)\n const allChildren = (nodeId: string): ScenarioNode[] =>\n scenario.nodes.filter((n) => allParentIds(n).includes(nodeId));\n\n // Build levels: a node's level = max(parent levels) + 1\n const nodeLevelMap = new Map<string, number>();\n nodeLevelMap.set(leader.id, 0);\n // BFS to assign levels\n const bfsQueue: ScenarioNode[] = [leader];\n while (bfsQueue.length > 0) {\n const cur = bfsQueue.shift()!;\n const curLevel = nodeLevelMap.get(cur.id) ?? 0;\n for (const child of allChildren(cur.id)) {\n const newLevel = curLevel + 1;\n const existing = nodeLevelMap.get(child.id) ?? -1;\n if (newLevel > existing) {\n nodeLevelMap.set(child.id, newLevel);\n bfsQueue.push(child);\n }\n }\n }\n // Group nodes by level\n const maxLevel = Math.max(...nodeLevelMap.values());\n const levels: ScenarioNode[][] = Array.from({ length: maxLevel + 1 }, () => []);\n for (const node of scenario.nodes) {\n const lvl = nodeLevelMap.get(node.id);\n if (lvl !== undefined) levels[lvl].push(node);\n }\n\n const runTopoNode = async (node: ScenarioNode) => {\n if (signal.aborted) throw new Error('Aborted');\n\n // Ask node: skip AI entirely, wait for human input\n if (node.type === 'ask') {\n if (persistedState && outputs.has(node.id)) {\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, outputs.get(node.id)!);\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: outputs.get(node.id)!, state: 'done' });\n await li('♻️', `**${node.label}** — restored from previous run`);\n } else {\n await runAskNode(node);\n }\n return;\n }\n\n // Resume: skip already-done nodes\n if (persistedState && outputs.has(node.id)) {\n const cached = outputs.get(node.id)!;\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, cached);\n publish({ type: 'node_state_change', nodeId: node.id, state: 'done' });\n publish({ type: 'node_done', nodeId: node.id, output: cached, state: 'done' });\n await li('♻️', `**${node.label}** — restored from previous run`);\n return;\n }\n\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: node.id });\n scenarioRunStore.setNodeState(conversationId, node.id, 'running');\n await readme(`### [${ts()}] ▶️ ${node.label} — started\\n`);\n await li('▶️', `**${node.label}** — started`);\n\n try {\n const parentOutput = node.parentIds[0] ? outputs.get(node.parentIds[0]) ?? null : null;\n const systemPrompt = buildSystemPrompt(node, scenario);\n const userMsg = buildUserMessage(node, scenario, userRequest, parentOutput, false, false, new Map(outputs));\n const out = await runNodeCall(conversationId, node, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: node.id, text: delta });\n }, runnerStates, '(topological)', readme);\n\n outputs.set(node.id, out);\n scenarioRunStore.setNodeState(conversationId, node.id, 'done');\n scenarioRunStore.setNodeOutput(conversationId, node.id, out);\n await scenarioRunStore.persistRunState(conversationId);\n await appendNodeOutput(conversationId, node, out);\n await li('✅', `**${node.label}** — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: node.id, output: out, state: 'done' });\n } catch (err) {\n if (signal.aborted) throw err;\n const msg = (err as Error).message;\n scenarioRunStore.setNodeState(conversationId, node.id, 'error');\n await readme(`### [${ts()}] ❌ ${node.label} — FAILED after ${fmtDuration(startedAt)}: ${msg}\\n`);\n publish({ type: 'node_error', nodeId: node.id, error: msg });\n runnerStates.delete(node.id);\n throw new Error(`${node.label} failed: ${msg}`);\n }\n };\n\n for (const level of levels) {\n // Run all nodes in the same level in parallel, wait before next level\n await Promise.all(level.map(runTopoNode));\n }\n } else {\n // ── Hierarchical mode: leader review loops + recursive subtree runs ──\n let leaderAssignedReports = byParent.get(leader.id) ?? [];\n let leaderCurrentOutput = leaderDispatchOutput ?? outputs.get(leader.id) ?? '';\n let leaderAssignments: Map<string, string> = leaderDispatchAssignments;\n let leaderReviewRound = 0;\n\n while (leaderAssignedReports.length > 0) {\n if (signal.aborted) throw new Error('Aborted');\n leaderReviewRound += 1;\n if (leaderReviewRound > MAX_MANAGER_REVIEW_ROUNDS) {\n throw new Error(`${leader.label} exceeded review loop limit (${MAX_MANAGER_REVIEW_ROUNDS})`);\n }\n\n await readme(`\\n### [${ts()}] Leader review loop ${leaderReviewRound} — running assigned children in parallel\\n`);\n await Promise.all(leaderAssignedReports.map((report) => {\n const instruction = leaderAssignments.get(report.id) ?? null;\n return runNodeSubtree(report, instruction ?? leaderCurrentOutput);\n }));\n\n const leaderChildReportsSection = leaderAssignedReports\n .map((report) => {\n const reportOut = outputs.get(report.id) ?? '';\n return `<child_report node=\"${report.label}\" id=\"${report.id}\">\\n${reportOut}\\n</child_report>`;\n })\n .join('\\n\\n');\n\n const leaderReviewMsg = buildManagerReviewMessage(\n leader,\n getDirectReports(scenario.nodes, leader.id),\n userRequest,\n leaderCurrentOutput,\n leaderChildReportsSection,\n );\n const leaderPass = await runDelegationPass(leader, leaderReviewMsg, `(leader review round ${leaderReviewRound})`);\n leaderCurrentOutput = leaderPass.finalOutput;\n leaderDispatchOutput = leaderCurrentOutput;\n leaderAssignedReports = leaderPass.assignedReports;\n leaderAssignments = leaderPass.assignments;\n }\n\n resolveWaitingStates(scenario.nodes, conversationId, byParent, publish, new Set([scenario.leaderId]));\n }\n\n // ── Phase 2: Leader synthesis → writes FINAL.md ────────────────────────\n const synthesisKey = `${leader.id}:synthesis`;\n const synthesisAlreadyDone = persistedState?.nodeStates[synthesisKey] === 'synthesized'\n && !!persistedState?.nodeOutputs[synthesisKey];\n\n if (synthesisAlreadyDone) {\n const summary = persistedState!.nodeOutputs[synthesisKey]!;\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n scenarioRunStore.setNodeState(conversationId, synthesisKey, 'synthesized');\n publish({ type: 'node_state_change', nodeId: synthesisKey, state: 'synthesized' });\n publish({ type: 'scenario_complete', summary });\n await li('♻️', `Synthesis restored from previous run`);\n } else if (scenario.nodes.length > 1) {\n const startedAt = Date.now();\n publish({ type: 'node_started', nodeId: `${leader.id}:synthesis` });\n await readme(`\\n### [${ts()}] 🔄 ${leader.label} (Leader) — synthesizing all outputs\\n`);\n await li('▶️', `**${leader.label}** synthesis — started`);\n\n try {\n const systemPrompt = buildSystemPrompt(leader, scenario);\n const userMsg = buildUserMessage(leader, scenario, userRequest, null, true, false, outputs);\n\n let summary = '';\n summary = await runNodeCall(conversationId, leader, systemPrompt, userMsg, runOverrides, signal, publish, (delta) => {\n publish({ type: 'node_delta', nodeId: `${leader.id}:synthesis`, text: delta });\n }, runnerStates, 'synthesis', readme);\n\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n\n scenarioRunStore.setNodeState(conversationId, `${leader.id}:synthesis`, 'synthesized');\n scenarioRunStore.setNodeOutput(conversationId, `${leader.id}:synthesis`, summary);\n await scenarioRunStore.persistRunState(conversationId);\n\n await li('✅', `**${leader.label}** synthesis — done in ${fmtDuration(startedAt)}`);\n publish({ type: 'node_done', nodeId: `${leader.id}:synthesis`, output: summary, state: 'synthesized' });\n publish({ type: 'scenario_complete', summary });\n } catch (err) {\n if (signal.aborted) throw err;\n // Synthesis failed — write FINAL.md with what we have as fallback\n const fallback = [...outputs.entries()]\n .map(([id, out]) => {\n const p = scenario.nodes.find(x => x.id === id);\n const name = p ? p.label.trim() : id;\n return `### ${name}\\n\\n${out}`;\n })\n .join('\\n\\n---\\n\\n');\n await readme(`\\n⚠️ Leader synthesis failed — writing partial FINAL.md\\n`);\n await li('❌', `**${leader.label}** synthesis — failed after ${fmtDuration(startedAt)}`);\n await writeFinalMd(conversationId, bus, userRequest, fallback);\n finalWritten = true;\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n publish({ type: 'scenario_complete', summary: fallback });\n }\n } else {\n // Solo leader — their output IS the final\n const summary = leaderDispatchOutput ?? outputs.get(leader.id) ?? '';\n await writeFinalMd(conversationId, bus, userRequest, summary);\n finalWritten = true;\n // Leader completion condition: FINAL.md has been written.\n scenarioRunStore.setNodeState(conversationId, leader.id, 'done');\n publish({ type: 'node_state_change', nodeId: leader.id, state: 'done' });\n publish({ type: 'scenario_complete', summary });\n }\n } catch (err) {\n if (!signal.aborted) {\n const msg = (err as Error).message;\n // Guard: if we exit without FINAL.md, report it explicitly\n if (!finalWritten) {\n await appendToReadme(conversationId, bus,\n `\\n### [${ts()}] 🚨 GUARD: Run ended without FINAL.md — ${msg}\\n`,\n ).catch(() => {/* non-fatal */});\n }\n publish({ type: 'scenario_error', error: msg });\n }\n } finally {\n if (!finalWritten && !signal.aborted) {\n // Secondary guard: bus closing without FINAL.md written\n await appendToReadme(conversationId, bus,\n `\\n### [${ts()}] 🚨 GUARD: No FINAL.md detected at end of run. Check individual agent outputs.\\n`,\n ).catch(() => {/* non-fatal */});\n }\n publishToBus(bus, null); // signal end-of-stream\n activeAbortControllers.delete(conversationId);\n }\n }\n\n // Fire-and-forget — run asynchronously so callers can subscribe immediately\n execute().catch(() => {/* errors published to bus */});\n}\n","import type { ScenarioPreset } from '@runeya/packages-shared';\n\nconst BUILT_IN_PRESETS: ScenarioPreset[] = [\n {\n id: 'enterprise',\n name: 'Enterprise',\n icon: 'pi-building',\n labels: {\n group: { en: 'Department', fr: 'Département' },\n node: { en: 'Employee', fr: 'Employé' },\n role: { en: 'Position', fr: 'Poste' },\n leader: { en: 'Director', fr: 'Directeur' },\n },\n defaultTraversalMode: 'hierarchical',\n canChangeTraversalMode: false,\n initialData: {\n leaderId: 'leader',\n groups: [\n { id: 'group-management', name: 'Management', position: { x: 0, y: 0 }, width: 300, height: 200 },\n ],\n nodes: [\n {\n id: 'leader',\n type: 'ai' as const,\n parentIds: [],\n groupId: 'group-management',\n label: 'Leader One',\n role: 'manager',\n prompt: 'Analyze the objective. Break it into concrete tasks and assign each to the right team member with a clear expected output. Do not do the technical work yourself.',\n question: '',\n autoGenerated: false,\n canAddNode: false,\n aiCli: 'claude-code',\n model: 'sonnet',\n position: { x: 50, y: 50 },\n },\n ],\n },\n roles: [\n {\n id: 'manager',\n name: 'Manager',\n systemPrompt: [\n 'You are a MANAGER. Your only job is to coordinate, plan, and delegate.',\n 'NEVER write code, scripts, or any technical artifact — not even as an example.',\n 'NEVER answer a technical question directly — always assign it to the right person.',\n 'Output only: task breakdowns, assignments, decisions, and synthesis.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'engineer',\n name: 'Engineer',\n systemPrompt: [\n 'You are an ENGINEER. Write working, production-ready code.',\n 'Always prefer real implementation over pseudocode or high-level descriptions.',\n 'Be concise in prose; let the code speak.',\n 'Output: source files, architecture decisions, technical specifications.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'designer',\n name: 'Designer',\n systemPrompt: [\n 'You are a DESIGNER. Define UX flows, visual hierarchy, and interaction patterns.',\n 'NEVER write code or CSS.',\n 'Describe interfaces in structured text: component name, layout, states, behavior.',\n 'Output: text wireframes, design decisions, component specs, UX guidelines.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'analyst',\n name: 'Analyst',\n systemPrompt: [\n 'You are an ANALYST. Investigate data, identify patterns, and surface actionable insights.',\n 'NEVER write code or scripts — if you need data processed, request it from an Engineer.',\n 'Output: structured analysis, metrics, findings, and evidence-based recommendations.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'qa',\n name: 'QA',\n systemPrompt: [\n 'You are a QA ENGINEER. Define what must be tested and how.',\n 'NEVER write implementation code.',\n 'You may write Gherkin / BDD scenarios or structured test cases as plain text.',\n 'Output: test plans, test cases, edge cases, risk assessments, acceptance criteria.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'devops',\n name: 'DevOps',\n systemPrompt: [\n 'You are a DEVOPS ENGINEER. Own infrastructure, deployment, and operations.',\n 'Write actual scripts and configuration files (shell, YAML, HCL, Dockerfile…) — no pseudocode.',\n 'Output: scripts, CI/CD pipelines, infrastructure-as-code, runbooks.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'product',\n name: 'Product',\n systemPrompt: [\n 'You are a PRODUCT MANAGER. Own requirements and priorities.',\n 'NEVER write code or technical specifications.',\n 'Output: PRDs, user stories with acceptance criteria, prioritization decisions, roadmap items.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'writer',\n name: 'Writer',\n systemPrompt: [\n 'You are a TECHNICAL WRITER. Produce clear, accurate, well-structured written content.',\n 'NEVER write code. If a code example is needed, flag it for an Engineer.',\n 'Output: documentation, guides, release notes, changelogs, communication drafts.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'researcher',\n name: 'Researcher',\n systemPrompt: [\n 'You are a RESEARCHER. Gather information, compare options, and synthesize knowledge into actionable insights.',\n 'NEVER write code.',\n 'Output: research summaries, comparisons, pros/cons analyses, evidence-based recommendations.',\n ].join('\\n'),\n prompt: '',\n },\n {\n id: 'other',\n name: 'Other',\n systemPrompt: '',\n prompt: '',\n },\n ],\n },\n];\n\nexport function listPresets(): ScenarioPreset[] {\n return BUILT_IN_PRESETS;\n}\n\nexport function getPreset(id: string): ScenarioPreset | undefined {\n return BUILT_IN_PRESETS.find(p => p.id === id);\n}\n","import { randomUUID } from 'node:crypto';\nimport { TRPCError } from '@trpc/server';\nimport { z } from 'zod';\nimport { protectedProcedure, router } from '../trpc.js';\n\ntype RandomTickEvent = {\n type: 'tick';\n jobId: string;\n index: number;\n value: number;\n at: number;\n};\n\ntype RandomDoneEvent = {\n type: 'done';\n jobId: string;\n reason: 'stopped' | 'max_ticks';\n at: number;\n};\n\ntype RandomJobEvent = RandomTickEvent | RandomDoneEvent;\n\ninterface RandomJob {\n id: string;\n startedAt: number;\n intervalMs: number;\n maxTicks: number;\n tick: number;\n done: boolean;\n timer: ReturnType<typeof setInterval>;\n buffer: RandomJobEvent[];\n baseIndex: number;\n listeners: Set<(event: RandomJobEvent | null) => void>;\n}\n\nconst MAX_BUFFER = 300;\nconst jobs = new Map<string, RandomJob>();\n\nfunction publish(job: RandomJob, event: RandomJobEvent | null): void {\n if (event) {\n job.buffer.push(event);\n if (job.buffer.length > MAX_BUFFER) {\n job.buffer.shift();\n job.baseIndex += 1;\n }\n } else {\n job.done = true;\n }\n\n for (const listener of job.listeners) listener(event);\n job.listeners.clear();\n}\n\nfunction stopJob(jobId: string, reason: 'stopped' | 'max_ticks'): boolean {\n const job = jobs.get(jobId);\n if (!job) return false;\n if (job.done) return true;\n\n clearInterval(job.timer);\n publish(job, { type: 'done', jobId, reason, at: Date.now() });\n publish(job, null);\n jobs.delete(jobId);\n return true;\n}\n\nasync function* tapJob(job: RandomJob, signal: AbortSignal): AsyncGenerator<RandomJobEvent> {\n let cursor = job.baseIndex;\n\n while (true) {\n if (cursor < job.baseIndex) cursor = job.baseIndex;\n while (cursor < job.baseIndex + job.buffer.length) {\n const evt = job.buffer[cursor - job.baseIndex];\n cursor += 1;\n if (!evt) continue;\n yield evt;\n }\n\n if (job.done || signal.aborted) return;\n\n await new Promise<void>((resolve) => {\n const onAbort = () => {\n job.listeners.delete(notify);\n resolve();\n };\n\n const notify = () => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n };\n\n job.listeners.add(notify);\n signal.addEventListener('abort', onAbort, { once: true });\n if (cursor < job.baseIndex + job.buffer.length || job.done || signal.aborted) {\n job.listeners.delete(notify);\n signal.removeEventListener('abort', onAbort);\n resolve();\n }\n });\n }\n}\n\nexport const debugRouter = router({\n startRandomJob: protectedProcedure\n .input(z.object({\n intervalMs: z.number().int().min(100).max(5000).optional(),\n maxTicks: z.number().int().min(1).max(10000).optional(),\n }).optional())\n .mutation(({ input }) => {\n const jobId = randomUUID();\n const intervalMs = input?.intervalMs ?? 400;\n const maxTicks = input?.maxTicks ?? 500;\n\n const job: RandomJob = {\n id: jobId,\n startedAt: Date.now(),\n intervalMs,\n maxTicks,\n tick: 0,\n done: false,\n timer: setInterval(() => {\n const current = jobs.get(jobId);\n if (!current || current.done) return;\n\n current.tick += 1;\n publish(current, {\n type: 'tick',\n jobId,\n index: current.tick,\n value: Math.random(),\n at: Date.now(),\n });\n\n if (current.tick >= current.maxTicks) {\n stopJob(jobId, 'max_ticks');\n }\n }, intervalMs),\n buffer: [],\n baseIndex: 0,\n listeners: new Set(),\n };\n\n jobs.set(jobId, job);\n return { jobId, intervalMs, maxTicks, startedAt: job.startedAt };\n }),\n\n streamRandomJob: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .subscription(async function* ({ input, signal }) {\n const job = jobs.get(input.jobId);\n if (!job) {\n throw new TRPCError({ code: 'NOT_FOUND', message: 'Random job not found' });\n }\n\n yield* tapJob(job, signal ?? new AbortController().signal);\n }),\n\n stopRandomJob: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .mutation(({ input }) => ({ ok: stopJob(input.jobId, 'stopped') })),\n\n randomJobStatus: protectedProcedure\n .input(z.object({ jobId: z.string().max(128) }))\n .query(({ input }) => {\n const job = jobs.get(input.jobId);\n return {\n running: !!job && !job.done,\n tick: job?.tick ?? 0,\n };\n }),\n});\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { kanbanStore, type KanbanChangeEvent } from '../../services/kanban-store.js';\nimport { KanbanColumnSchema } from '@runeya/packages-shared';\nimport { conversationStore } from '../../services/conversation-store.js';\nimport { scenarioRunStore } from '../../services/scenario-run-store.js';\nimport { imageStorageService } from '../../services/image-storage.service.js';\n\nasync function deleteConversationsForIds(conversationIds: string[]): Promise<void> {\n await Promise.all(conversationIds.map(async (id) => {\n await conversationStore.delete(id);\n await scenarioRunStore.deleteRunDir(id);\n imageStorageService.deleteByContextId(id).catch((err) =>\n console.error('[kanban] Image cleanup error:', err),\n );\n }));\n}\n\nexport const kanbanRouter = router({\n list: protectedProcedure\n .input(z.object({ includeArchived: z.boolean().optional() }).optional())\n .query(async ({ input }) => {\n return kanbanStore.list(input?.includeArchived ?? false);\n }),\n\n get: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .query(async ({ input }) => {\n const board = await kanbanStore.get(input.id);\n if (!board) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.id} not found` });\n return board;\n }),\n\n create: protectedProcedure\n .input(z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(10_000).optional(),\n }))\n .mutation(async ({ input }) => {\n return kanbanStore.create(input);\n }),\n\n update: protectedProcedure\n .input(z.object({\n id: z.string().max(128),\n name: z.string().min(1).max(200).optional(),\n description: z.string().max(10_000).optional(),\n columns: z.array(KanbanColumnSchema).optional(),\n archived: z.boolean().optional(),\n }))\n .mutation(async ({ input }) => {\n let removedCardIds: string[] = [];\n if (input.columns !== undefined) {\n const existing = await kanbanStore.get(input.id);\n if (existing) {\n const oldCardIds = new Set(existing.columns.flatMap(col => col.cards.map(c => c.id)));\n const newCardIds = new Set(input.columns.flatMap(col => col.cards.map(c => c.id)));\n removedCardIds = Array.from(oldCardIds).filter(id => !newCardIds.has(id));\n }\n }\n const board = await kanbanStore.update(input);\n if (!board) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.id} not found` });\n if (removedCardIds.length > 0) {\n const convsByCard = await Promise.all(removedCardIds.map(cardId => conversationStore.listByKanbanCardId(cardId)));\n const convIds = convsByCard.flat().map(c => c.id);\n if (convIds.length > 0) await deleteConversationsForIds(convIds);\n }\n return board;\n }),\n\n moveCard: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n targetColumn: z.string().min(1).max(200),\n }))\n .mutation(async ({ input }) => {\n const board = await kanbanStore.get(input.boardId);\n if (!board) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.boardId} not found` });\n const { executeKanbanCommands } = await import('../../services/kanban-commands.js');\n await executeKanbanCommands(input.boardId, input.cardId, [{ type: 'move_card', columnTitle: input.targetColumn }]);\n return { success: true as const };\n }),\n\n addComment: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n comment: z.string().min(1).max(10_000),\n }))\n .mutation(async ({ input }) => {\n const board = await kanbanStore.get(input.boardId);\n if (!board) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.boardId} not found` });\n const { executeKanbanCommands } = await import('../../services/kanban-commands.js');\n await executeKanbanCommands(input.boardId, input.cardId, [{ type: 'add_comment', comment: input.comment }]);\n return { success: true as const };\n }),\n\n addCard: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n column: z.string().min(1).max(200),\n title: z.string().min(1).max(500),\n content: z.string().max(50_000).optional(),\n }))\n .mutation(async ({ input }) => {\n const board = await kanbanStore.get(input.boardId);\n if (!board) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.boardId} not found` });\n const { executeKanbanBoardCommands } = await import('../../services/kanban-commands.js');\n await executeKanbanBoardCommands(input.boardId, [{ type: 'add_card', columnTitle: input.column, cardTitle: input.title, cardContent: input.content }]);\n return { success: true as const };\n }),\n\n delete: protectedProcedure\n .input(z.object({ id: z.string().max(128) }))\n .mutation(async ({ input }) => {\n const conversations = await conversationStore.listByKanbanBoardId(input.id);\n const deleted = await kanbanStore.delete(input.id);\n if (!deleted) throw new TRPCError({ code: 'NOT_FOUND', message: `Board ${input.id} not found` });\n await deleteConversationsForIds(conversations.map(c => c.id));\n return { success: true as const };\n }),\n\n onChanged: protectedProcedure.subscription(async function* () {\n const queue: KanbanChangeEvent[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = (event: KanbanChangeEvent) => {\n if (queue.length >= 200) queue.shift();\n queue.push(event);\n if (resolve) {\n resolve();\n resolve = null;\n }\n };\n\n kanbanStore.onChanged(handler);\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n kanbanStore.offChanged(handler);\n }\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { kanbanQueue } from '../../services/kanban-queue.js';\nimport type { KanbanQueueState } from '../../services/kanban-queue.js';\n\nexport const kanbanQueueRouter = router({\n getState: protectedProcedure.query(() => kanbanQueue.getState()),\n\n add: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n cardId: z.string().max(128),\n runner: z.enum(['claude-code', 'codex']).optional(),\n model: z.string().max(128).optional(),\n scenarioId: z.string().max(128).optional(),\n }))\n .mutation(({ input }) => kanbanQueue.add(input)),\n\n addColumn: protectedProcedure\n .input(z.object({\n boardId: z.string().max(128),\n columnId: z.string().max(128),\n runner: z.enum(['claude-code', 'codex']).optional(),\n model: z.string().max(128).optional(),\n scenarioId: z.string().max(128).optional(),\n }))\n .mutation(async ({ input }) => {\n const { boardId, columnId, ...options } = input;\n return kanbanQueue.addColumn(boardId, columnId, options);\n }),\n\n remove: protectedProcedure\n .input(z.object({ itemId: z.string().max(128) }))\n .mutation(({ input }) => ({ removed: kanbanQueue.remove(input.itemId) })),\n\n stopAll: protectedProcedure\n .mutation(() => { kanbanQueue.stopAll(); return { ok: true }; }),\n\n setMaxConcurrent: protectedProcedure\n .input(z.object({ max: z.number().int().min(1).max(20) }))\n .mutation(({ input }) => { kanbanQueue.setMaxConcurrent(input.max); return kanbanQueue.getState(); }),\n\n onChanged: protectedProcedure.subscription(async function* () {\n const queue: KanbanQueueState[] = [];\n let resolve: (() => void) | null = null;\n\n const handler = () => {\n if (queue.length >= 50) queue.shift();\n queue.push(kanbanQueue.getState());\n if (resolve) { resolve(); resolve = null; }\n };\n\n kanbanQueue.on('changed', handler);\n // Emit initial state\n queue.push(kanbanQueue.getState());\n\n try {\n while (true) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n kanbanQueue.off('changed', handler);\n }\n }),\n});\n","import { randomUUID } from 'node:crypto';\nimport { EventEmitter } from 'node:events';\nimport { kanbanStore } from './kanban-store.js';\nimport { conversationStore } from './conversation-store.js';\nimport { scenarioRunStore } from './scenario-run-store.js';\nimport { scenarioStore } from './scenario-store.js';\nimport { runScenario, tapBus, abortScenario } from './scenario-runner.js';\nimport { activeSessionRegistry } from './active-session-registry.js';\nimport { startClaudeCodeSession, startCodexSession } from '../trpc/routers/chat.js';\n\nexport interface KanbanQueueItem {\n id: string;\n boardId: string;\n cardId: string;\n runner?: 'claude-code' | 'codex';\n model?: string;\n scenarioId?: string;\n addedAt: string;\n}\n\nexport interface KanbanRunningItem {\n id: string;\n boardId: string;\n cardId: string;\n conversationId: string;\n startedAt: string;\n}\n\nexport interface KanbanQueueState {\n items: KanbanQueueItem[];\n running: KanbanRunningItem[];\n maxConcurrent: number;\n}\n\nclass KanbanQueueService extends EventEmitter {\n private items: KanbanQueueItem[] = [];\n private running: KanbanRunningItem[] = [];\n private maxConcurrent = 1;\n private startingCount = 0; // items whose startItem() is in-flight but not yet in this.running\n\n getState(): KanbanQueueState {\n return {\n items: [...this.items],\n running: [...this.running],\n maxConcurrent: this.maxConcurrent,\n };\n }\n\n add(item: Omit<KanbanQueueItem, 'id' | 'addedAt'>): KanbanQueueItem {\n const alreadyQueued = this.items.find(i => i.boardId === item.boardId && i.cardId === item.cardId);\n if (alreadyQueued) return alreadyQueued;\n const alreadyRunning = this.running.find(r => r.boardId === item.boardId && r.cardId === item.cardId);\n if (alreadyRunning) {\n // Return a fake item representing the running entry\n return { id: alreadyRunning.id, addedAt: alreadyRunning.startedAt, ...item };\n }\n\n const queueItem: KanbanQueueItem = {\n id: randomUUID(),\n ...item,\n addedAt: new Date().toISOString(),\n };\n this.items.push(queueItem);\n this.emit('changed');\n this.tick();\n return queueItem;\n }\n\n async addColumn(\n boardId: string,\n columnId: string,\n options: { runner?: 'claude-code' | 'codex'; model?: string; scenarioId?: string },\n ): Promise<KanbanQueueItem[]> {\n const board = await kanbanStore.get(boardId);\n if (!board) return [];\n const col = board.columns.find(c => c.id === columnId);\n if (!col) return [];\n return col.cards.map(card => this.add({ boardId, cardId: card.id, ...options }));\n }\n\n remove(itemId: string): boolean {\n const idx = this.items.findIndex(i => i.id === itemId);\n if (idx >= 0) {\n this.items.splice(idx, 1);\n this.emit('changed');\n return true;\n }\n const runIdx = this.running.findIndex(r => r.id === itemId);\n if (runIdx >= 0) {\n const run = this.running[runIdx];\n abortScenario(run.conversationId);\n activeSessionRegistry.kill(run.conversationId);\n this.running.splice(runIdx, 1);\n this.emit('changed');\n this.tick();\n return true;\n }\n return false;\n }\n\n stopAll(): void {\n this.items = [];\n for (const run of this.running) {\n abortScenario(run.conversationId);\n activeSessionRegistry.kill(run.conversationId);\n }\n this.running = [];\n this.emit('changed');\n }\n\n setMaxConcurrent(max: number): void {\n this.maxConcurrent = Math.max(1, max);\n this.emit('changed');\n this.tick();\n }\n\n private tick(): void {\n while (this.running.length + this.startingCount < this.maxConcurrent && this.items.length > 0) {\n const item = this.items.shift()!;\n this.startingCount++;\n this.startItem(item).catch(err => {\n console.error('[kanban-queue] startItem error:', err);\n }).finally(() => {\n this.startingCount--;\n });\n }\n }\n\n private async startItem(item: KanbanQueueItem): Promise<void> {\n const board = await kanbanStore.get(item.boardId);\n if (!board) { this.tick(); return; }\n\n let card = null;\n for (const col of board.columns) {\n card = col.cards.find(c => c.id === item.cardId) ?? null;\n if (card) break;\n }\n if (!card) { this.tick(); return; }\n\n const conv = await conversationStore.create(\n `Queue: ${card.title}`,\n !!item.runner,\n item.scenarioId,\n item.scenarioId ? 'scenario' : undefined,\n item.runner,\n item.boardId,\n item.cardId,\n );\n\n const cardContent = card.title + (card.markdown ? '\\n\\n' + card.markdown : '');\n\n if (item.scenarioId) {\n const scenario = await scenarioStore.get(item.scenarioId);\n if (scenario) {\n await scenarioRunStore.initializeConversationWorkspace(conv.id, scenario, cardContent);\n }\n }\n\n const runItem: KanbanRunningItem = {\n id: item.id,\n boardId: item.boardId,\n cardId: item.cardId,\n conversationId: conv.id,\n startedAt: new Date().toISOString(),\n };\n this.running.push(runItem);\n this.emit('changed');\n\n // Write conversation_started history entry so the frontend can show status badges\n const eventType = item.scenarioId ? 'scenario_started' : 'conversation_started';\n for (const col of board.columns) {\n const target = col.cards.find(c => c.id === item.cardId);\n if (target) {\n target.history = [...(target.history ?? []), {\n type: eventType,\n timestamp: new Date().toISOString(),\n detail: conv.id,\n }];\n kanbanStore.update({ id: board.id, columns: board.columns }).catch(() => {});\n break;\n }\n }\n\n if (item.scenarioId) {\n runScenario(conv.id, item.scenarioId, cardContent, {\n runnerOverride: item.runner,\n modelOverride: item.model,\n });\n this.monitorCompletion(runItem).catch(() => {});\n } else if (item.runner) {\n this.runWithRunner(runItem, item, cardContent).catch(err => {\n console.error('[kanban-queue] runWithRunner error:', err);\n this.finishItem(item.id);\n });\n } else {\n this.finishItem(item.id);\n }\n }\n\n private async runWithRunner(\n runItem: KanbanRunningItem,\n item: KanbanQueueItem,\n cardContent: string,\n ): Promise<void> {\n try {\n const model = item.model || (item.runner === 'codex' ? '' : 'claude-opus-4-6');\n const starter = item.runner === 'codex' ? startCodexSession : startClaudeCodeSession;\n const { done } = await starter(runItem.conversationId, cardContent, { model });\n await done;\n } finally {\n this.finishItem(runItem.id);\n }\n }\n\n private async monitorCompletion(runItem: KanbanRunningItem): Promise<void> {\n // Wait a bit for the scenario bus to be created\n await new Promise(r => setTimeout(r, 100));\n const abortCtrl = new AbortController();\n try {\n for await (const event of tapBus(runItem.conversationId, abortCtrl.signal)) {\n if (event.type === 'scenario_complete') break;\n }\n } catch {\n // Aborted or ended\n } finally {\n this.finishItem(runItem.id);\n }\n }\n\n private finishItem(itemId: string): void {\n const idx = this.running.findIndex(r => r.id === itemId);\n if (idx >= 0) this.running.splice(idx, 1);\n this.emit('changed');\n this.tick();\n }\n}\n\nexport const kanbanQueue = new KanbanQueueService();\n","import { z } from 'zod';\nimport { TRPCError } from '@trpc/server';\nimport { router, protectedProcedure } from '../trpc.js';\nimport { agentManager } from '../../services/agent-manager.js';\n\nexport const terminalRouter = router({\n /** Create a PTY shell session on the target agent */\n create: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n cwd: z.string().max(512).optional(),\n cols: z.number().int().min(1).max(512).optional(),\n rows: z.number().int().min(1).max(256).optional(),\n }))\n .mutation(async ({ input }) => {\n const result = await agentManager.agentMutation<{ sessionId: string }>(\n input.agentId,\n 'terminal.create',\n { cwd: input.cwd, cols: input.cols, rows: input.rows },\n );\n return result;\n }),\n\n /** Send keystrokes / data to a PTY session */\n write: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n data: z.string().max(65536),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.write',\n { sessionId: input.sessionId, data: input.data },\n );\n return { ok: true as const };\n }),\n\n /** Resize the PTY */\n resize: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n cols: z.number().int().min(1).max(512),\n rows: z.number().int().min(1).max(256),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.resize',\n { sessionId: input.sessionId, cols: input.cols, rows: input.rows },\n );\n return { ok: true as const };\n }),\n\n /** Destroy a PTY session */\n destroy: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n }))\n .mutation(async ({ input }) => {\n await agentManager.agentMutation(\n input.agentId,\n 'terminal.destroy',\n { sessionId: input.sessionId },\n );\n return { ok: true as const };\n }),\n\n /** Stream PTY output — proxied via AgentWSBridge dynamic subscription */\n onData: protectedProcedure\n .input(z.object({\n agentId: z.string().max(128),\n sessionId: z.string().max(128),\n }))\n .subscription(async function* ({ input }) {\n const queue: string[] = [];\n let resolve: (() => void) | null = null;\n let done = false;\n\n let unsubscribe: (() => void) | undefined;\n try {\n unsubscribe = agentManager.agentSubscribe(\n input.agentId,\n 'terminal.onData',\n { sessionId: input.sessionId },\n (data) => {\n if (typeof data === 'string') queue.push(data);\n if (resolve) { resolve(); resolve = null; }\n },\n () => {\n done = true;\n if (resolve) { resolve(); resolve = null; }\n },\n );\n } catch (err) {\n throw new TRPCError({\n code: 'BAD_REQUEST',\n message: `Cannot subscribe to terminal: ${(err as Error).message}`,\n });\n }\n\n try {\n while (!done || queue.length > 0) {\n if (queue.length > 0) {\n yield queue.shift()!;\n } else {\n await new Promise<void>((r) => { resolve = r; });\n }\n }\n } finally {\n unsubscribe?.();\n }\n }),\n});\n","import { z } from 'zod';\nimport { router, protectedProcedure } from '../trpc.js';\n\nconst MAX_WAIT_MS = 5 * 60 * 1000; // 5 minutes max\n\nexport const utilityRouter = router({\n wait: protectedProcedure\n .input(z.object({\n ms: z.number().int().min(0).max(MAX_WAIT_MS),\n }))\n .mutation(async ({ input }) => {\n await new Promise(resolve => setTimeout(resolve, input.ms));\n return { waited: input.ms };\n }),\n});\n","import { router } from './trpc.js';\nimport { healthRouter } from './routers/health.js';\nimport { projectRouter } from './routers/project.js';\nimport { serviceRouter } from './routers/service.js';\nimport { agentRouter } from './routers/agent.js';\nimport { processRouter } from './routers/process.js';\nimport { auditRouter } from './routers/audit.js';\nimport { setupRouter } from './routers/setup.js';\nimport { environmentRouter } from './routers/environment.js';\nimport { settingsRouter } from './routers/settings.js';\nimport { editorRouter } from './routers/editor.js';\nimport { apiKeysRouter } from './routers/api-keys.js';\nimport { chatRouter } from './routers/chat.js';\nimport { gitRouter } from './routers/git.js';\nimport { scenarioRouter } from './routers/scenario.js';\nimport { debugRouter } from './routers/debug.js';\nimport { kanbanRouter } from './routers/kanban.js';\nimport { kanbanQueueRouter } from './routers/kanban-queue.js';\nimport { terminalRouter } from './routers/terminal.js';\nimport { utilityRouter } from './routers/utility.js';\n\n// Re-export server types used in AppRouter so consumers can name them (avoids TS4023)\nexport type { AuditEntry } from '../services/audit-service.js';\nexport type { CliUsageEntry } from '../services/claude-usage.js';\nexport type { Conversation } from '../services/conversation-store.js';\nexport type { KanbanQueueItem, KanbanQueueState } from '../services/kanban-queue.js';\nexport type { PersistedRunState, RunState } from '../services/scenario-run-store.js';\n\nexport const appRouter = router({\n health: healthRouter,\n project: projectRouter,\n service: serviceRouter,\n agent: agentRouter,\n process: processRouter,\n audit: auditRouter,\n setup: setupRouter,\n environment: environmentRouter,\n settings: settingsRouter,\n editor: editorRouter,\n apiKeys: apiKeysRouter,\n chat: chatRouter,\n scenario: scenarioRouter,\n git: gitRouter,\n debug: debugRouter,\n kanban: kanbanRouter,\n kanbanQueue: kanbanQueueRouter,\n terminal: terminalRouter,\n utility: utilityRouter,\n});\n\nexport type AppRouter = typeof appRouter;\n","import { Request, Response, NextFunction } from 'express';\n\nexport function errorHandler(err: Error, _req: Request, res: Response, _next: NextFunction): void {\n console.error('[server] Unhandled error:', err);\n res.status(500).json({ error: 'Internal server error' });\n}\n","import { settingsManager } from './settings-manager.js';\n\n\ninterface Migration {\n version: number;\n name: string;\n up: () => Promise<void>;\n}\n\n// Migrations are registered here. Each adds a transform function.\nconst migrations: Migration[] = [\n];\n\nclass MigrationEngine {\n async run(): Promise<void> {\n const schemaVersion = await settingsManager.getSchemaVersion();\n const currentVersion = schemaVersion.version;\n const targetVersion = settingsManager.getCurrentSchemaVersion();\n\n if (currentVersion >= targetVersion) {\n console.log(`[migration] Schema is up to date (v${currentVersion})`);\n return;\n }\n\n console.log(`[migration] Migrating from v${currentVersion} to v${targetVersion}`);\n const pending = migrations.filter(m => m.version > currentVersion && m.version <= targetVersion);\n pending.sort((a, b) => a.version - b.version);\n\n for (const migration of pending) {\n console.log(`[migration] Running: ${migration.name} (v${migration.version})`);\n await migration.up();\n await settingsManager.saveSchemaVersion({ version: migration.version, migratedAt: new Date() });\n console.log(`[migration] Done: ${migration.name}`);\n }\n\n console.log(`[migration] All migrations complete. Now at v${targetVersion}`);\n }\n}\n\nexport const migrationEngine = new MigrationEngine();\n","import { chmod, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { env } from '../config/env.js';\n\nconst SENSITIVE_FILES = [\n 'agents.json',\n 'settings.json',\n 'services.json',\n 'projects.json',\n 'deployments.json',\n 'schema-version.json',\n];\n\nconst SECURE_MODE = 0o600;\n\n/**\n * Ensure all sensitive data files have restrictive permissions (0600).\n * Logs warnings for files with overly permissive modes and auto-fixes them.\n */\nexport async function ensureFilePermissions(): Promise<void> {\n for (const filename of SENSITIVE_FILES) {\n const filepath = join(env.DATA_DIR, filename);\n try {\n const stats = await stat(filepath);\n const mode = stats.mode & 0o777;\n if (mode !== SECURE_MODE) {\n console.warn('[security] File', filename, 'has mode', mode.toString(8) + ', fixing to 600');\n await chmod(filepath, SECURE_MODE);\n }\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n console.warn('[security] Cannot check permissions for', filename + ':', err instanceof Error ? err.message : String(err));\n }\n // ENOENT is fine — file doesn't exist yet\n }\n }\n}\n\n/**\n * Set secure permissions on a single file after creation/write.\n */\nasync function setSecurePermissions(filepath: string): Promise<void> {\n try {\n await chmod(filepath, SECURE_MODE);\n } catch (err: unknown) {\n console.warn('[security] Cannot set permissions on', filepath + ':', err instanceof Error ? err.message : String(err));\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nconst GITIGNORE_CONTENT = `\n#################\n# Do not edit this file #\n#################\n\n\n# Encryption key (contains secrets — never commit)\n.encryption.key\n.encryption.key.enc\n\n\n# Key verification canary — MUST be committed so new team members can validate their encryption key\n!.runeya-verify\n\n# Backup in local only\nbackup-*\n\n# Per-user environment overrides (never commit — each dev has their own)\nenvironment-overrides.json\n\n# Private user data (conversations, personal state — never commit)\n*.private\n*.private.json*\nconversations/\nconversations.private.json\n\n\n\n# Runtime logs\n*.log\n*.log.*\n`;\n\n/**\n * Writes data/.gitignore on every startup to keep it in sync with the codebase.\n */\nexport async function ensureDataGitignore(dataDir: string): Promise<void> {\n const gitignorePath = join(dataDir, '.gitignore');\n await writeFile(gitignorePath, GITIGNORE_CONTENT, 'utf-8');\n}\n","/**\n * Legacy Runeya → Runeya migration\n *\n * Triggered automatically when DATA_DIR/.runeya/dbs/encryption-key.json is found.\n * Must run BEFORE any store initialisation (called at the top of createLocalServer).\n *\n * Steps:\n * 1. Backup existing DATA_DIR contents\n * 2. Extract legacy libsodium key → load in memory for re-encryption\n * 3. Decrypt all .encrypted.json files with libsodium crypto_secretbox\n * 4. Map legacy structures → Runeya JSON files\n * 5. Clear singleton, store key in pending holder → server enters setup state\n * 6. Rename .runeya → backup to prevent re-running\n */\n\nimport { createRequire } from 'module';\nimport { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { randomUUID } from 'node:crypto';\nimport {\n readFile, writeFile, rename, mkdir, access, readdir,\n} from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { setEncryptionKey, getEncryptionKey, clearEncryptionKey, setPendingLegacyKey } from '../utils/encryption-key.js';\nimport type { Variable } from '@runeya/packages-shared';\nimport { env } from '../config/env.js';\n\n// CJS interop for libsodium-wrappers\nconst _require = createRequire(import.meta.url);\n\n/** Minimal type for the libsodium-wrappers API used in this migration */\ninterface Sodium {\n ready: Promise<void>;\n crypto_secretbox_NONCEBYTES: number;\n crypto_secretbox_open_easy(ciphertext: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array;\n from_base64(input: string): Uint8Array;\n}\n\n// Parser ID remapping\nconst PARSER_ID_MAP: Record<string, string> = {\n 'stack-monitor-parser-jsons': 'native:json',\n 'stack-monitor-parser-debug': 'native:debug',\n 'stack-monitor-parser-links': 'native:links',\n 'runeya-parser-jsons': 'native:json',\n 'runeya-parser-debug': 'native:debug',\n 'runeya-parser-links': 'native:links',\n};\n\n// ── Runeya AES-256-GCM encryption (matches service-store / environment-store) ──\n\nfunction encryptValue(plaintext: string): string {\n const key = getEncryptionKey();\n if (!key) throw new Error('[legacy-migration] Encryption key not loaded');\n const iv = randomBytes(16);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n let enc = cipher.update(plaintext, 'utf-8', 'hex');\n enc += cipher.final('hex');\n const authTag = cipher.getAuthTag().toString('hex');\n return `${iv.toString('hex')}:${authTag}:${enc}`;\n}\n\n/** Strip legacy suffixes from a variable key: _RUNEYA_OVERRIDE → _RUNEYA → base */\nfunction cleanVarKey(key: string): string {\n return key.replace(/_RUNEYA(?:_OVERRIDE)?$|_OVERRIDE$/, '');\n}\n\n/** Valid interpolation token: {{VAR_NAME}} or {{environment.VAR_NAME}} — simple identifiers only, no expressions */\nconst VALID_INTERP_RE = /^\\{\\{(?:environment\\.)?[A-Z_][A-Z0-9_]*\\}\\}$/i;\n\n/** Detect interpolation patterns like ${VAR}, $VAR, {{VAR}} */\nfunction hasInterpolation(value: string): boolean {\n return /\\$\\{[^}]+\\}|\\$[A-Z_][A-Z0-9_]*|\\{\\{[^}]+\\}\\}/.test(value);\n}\n\n/** Returns true only for simple variable references — rejects expressions, ternaries, nested accessors */\nfunction isValidInterpolation(token: string): boolean {\n return VALID_INTERP_RE.test(token.trim());\n}\n\n/** Returns true if the value contains any {{...}} token that is not a valid variable reference */\nfunction hasInvalidInterpolation(value: string): boolean {\n const tokens = value.matchAll(/\\{\\{[^}]+\\}\\}/g);\n for (const match of tokens) {\n if (!isValidInterpolation(match[0])) return true;\n }\n return false;\n}\n\n/**\n * Rewrite legacy {{KEY}} interpolation to Runeya's {{environment.KEY}} format.\n * Strips legacy suffixes (_RUNEYA, _OVERRIDE, _RUNEYA_OVERRIDE).\n * Leaves ${VAR} and $VAR patterns untouched (shell interpolation, handled at runtime).\n */\nfunction rewriteInterpolation(value: string): string {\n return value.replace(/\\{\\{(?!environment\\.)([^}]+)\\}\\}/g, (match, key: string) => {\n // Only rewrite simple variable references — leave expressions untouched (will be encrypted)\n if (!isValidInterpolation(match)) return match;\n return `{{environment.${cleanVarKey(key)}}}`;\n });\n}\n\n/**\n * Detect composite interpolation: a value that contains exactly one {{VAR}} token\n * with surrounding text (e.g. \"{{DATABASE_URL}}/onboarding?authSource=admin\").\n * Returns { pre, interp, post } if composite, null otherwise.\n * Values with multiple {{...}} tokens or $VAR/${{VAR}} patterns are left untouched.\n */\nfunction splitCompositeInterpolation(value: string): { pre: string; interp: string; post: string } | null {\n const tokens = [...value.matchAll(/\\{\\{[^}]+\\}\\}/g)];\n if (tokens.length !== 1) return null; // 0 or 2+ interpolations — skip\n if (/\\$\\{[^}]+\\}|\\$[A-Z_][A-Z0-9_]*/.test(value)) return null; // shell vars — skip\n const match = tokens[0];\n if (!isValidInterpolation(match[0])) return null; // expression/ternary — treat as literal\n const pre = value.slice(0, match.index);\n const post = value.slice((match.index ?? 0) + match[0].length);\n if (!pre && !post) return null; // pure interpolation — nothing to split\n return { pre, interp: match[0], post };\n}\n\n/** Decrypt a migration-encrypted value (same AES-256-GCM as encryptValue above) */\nfunction decryptMigrationValue(encrypted: string): string | null {\n try {\n const key = getEncryptionKey();\n if (!key) return null;\n const parts = encrypted.split(':');\n if (parts.length !== 3) return null;\n const [ivHex, authHex, ct] = parts;\n const dec = createDecipheriv('aes-256-gcm', key, Buffer.from(ivHex, 'hex'), { authTagLength: 16 });\n dec.setAuthTag(Buffer.from(authHex, 'hex'));\n return dec.update(ct, 'hex', 'utf-8') + dec.final('utf-8');\n } catch { return null; }\n}\n\n/**\n * Returns true if the override raw value is identical to the base variable's stored value.\n * Skips writing a redundant override when base and override resolve to the same thing.\n */\nfunction isSameAsBase(overrideRawValue: string, baseVar: Variable | undefined): boolean {\n if (!baseVar) return false;\n const baseSlot = baseVar.value;\n if (!baseSlot.isSecret) {\n return baseSlot.value === rewriteInterpolation(overrideRawValue);\n }\n const decrypted = decryptMigrationValue(baseSlot.value);\n return decrypted === overrideRawValue;\n}\n\n/** Build a Variable with key and value slot — encrypted if secret, plaintext (with rewritten interpolation) otherwise */\nfunction makeVariable(key: string, value: string, pre = '', post = ''): Variable {\n // Auto-detect composite interpolation and ventilate into pre/value/post\n const composite = splitCompositeInterpolation(value);\n if (composite) {\n return {\n key,\n value: {\n value: rewriteInterpolation(composite.interp),\n pre: rewriteInterpolation(pre + composite.pre),\n post: rewriteInterpolation(composite.post + post),\n isSecret: false,\n },\n };\n }\n\n const secret = !hasInterpolation(value);\n return {\n key,\n value: {\n value: secret ? encryptValue(value) : rewriteInterpolation(value),\n pre: rewriteInterpolation(pre),\n post: rewriteInterpolation(post),\n isSecret: secret,\n },\n };\n}\n\n// ── libsodium decryption ──────────────────────────────────────────────────────\n\nasync function getSodium(): Promise<Sodium> {\n const _sodium = _require('libsodium-wrappers') as Sodium;\n await _sodium.ready;\n return _sodium;\n}\n\nasync function decryptLegacyFile(\n filePath: string,\n key: Uint8Array,\n sodium: Sodium,\n): Promise<unknown> {\n const raw = (await readFile(filePath, 'utf-8')).trim();\n if (!raw || raw === '[]' || raw === '{}') {\n try { return JSON.parse(raw); } catch { return {}; }\n }\n\n const buf = Buffer.from(raw, 'base64');\n const nonce = buf.subarray(0, sodium.crypto_secretbox_NONCEBYTES as number);\n const ciphertext = buf.subarray(sodium.crypto_secretbox_NONCEBYTES as number);\n const decrypted = sodium.crypto_secretbox_open_easy(\n new Uint8Array(ciphertext),\n new Uint8Array(nonce),\n key,\n ) as Uint8Array;\n\n return JSON.parse(Buffer.from(decrypted).toString('utf-8'));\n}\n\n// ── Atomic write helper ───────────────────────────────────────────────────────\n\nasync function atomicWrite(path: string, data: unknown): Promise<void> {\n const tmp = path + '.tmp';\n await writeFile(tmp, JSON.stringify(data, null, 2), 'utf-8');\n await rename(tmp, path);\n}\n\n// ── Main migration entry point ────────────────────────────────────────────────\n\nexport async function runLegacyMigration(dataDir: string): Promise<boolean> {\n // Legacy .runeya sits in the working directory (apps/server/.runeya/)\n // We resolve dataDir to an absolute path to avoid false-positive overlap\n const { resolve } = await import('node:path');\n const abCwd = resolve(process.cwd());\n const legacyRoot = join(abCwd, env.DATA_DIR);\n const legacyKeyPath = join(legacyRoot, 'dbs', 'encryption-key.json');\n\n // Detect legacy installation\n try {\n await access(legacyKeyPath);\n } catch {\n return false;\n }\n\n console.log('[legacy-migration] Legacy Runeya data detected, starting migration…');\n\n // ── 1. Move legacy .runeya → .runeya/backup-<date>, create fresh DATA_DIR ───\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-').substring(0, 19);\n const legacyTmp = join(abCwd, '.runeya-tmp');\n await rename(legacyRoot, legacyTmp); // free up the .runeya name\n await mkdir(dataDir, { recursive: true }); // create fresh .runeya/\n const legacyOld = join(dataDir, `backup-${timestamp}`);\n await rename(legacyTmp, legacyOld); // move into .runeya/backup-<date>\n console.log(`[legacy-migration] Legacy data backed up to ${legacyOld}`);\n\n // ── 2. Extract legacy key and initialise Runeya encryption ─────────────────\n const keyJson = JSON.parse(await readFile(join(legacyOld, 'dbs', 'encryption-key.json'), 'utf-8')) as { encryptionKey: string };\n const sodium = await getSodium();\n const sodiumKey = sodium.from_base64(keyJson.encryptionKey) as Uint8Array;\n\n // Load key into singleton temporarily — needed by encryptValue/makeVariable during re-encryption\n const keyBuffer = Buffer.from(sodiumKey);\n const runyeaKeyHex = keyBuffer.toString('hex');\n await setEncryptionKey(runyeaKeyHex);\n console.log('[legacy-migration] Encryption key loaded in memory (temporary)');\n\n // ── 3. Decrypt all legacy files ─────────────────────────────────────────────\n const dbsDir = join(legacyOld, 'dbs');\n\n async function readEncrypted(filePath: string): Promise<any> {\n try {\n return await decryptLegacyFile(filePath, sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[legacy-migration] Failed to decrypt ${filePath}: ${(err as Error).message}`);\n return null;\n }\n }\n\n // Environments\n const envsDir = join(dbsDir, 'envs');\n const envFiles = (await readdir(envsDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyEnvs: Record<string, any> = {};\n for (const file of envFiles) {\n const name = file.replace('.encrypted.json', '');\n legacyEnvs[name] = await readEncrypted(join(envsDir, file));\n }\n\n // Services\n const servicesDir = join(dbsDir, 'services');\n const serviceFiles = (await readdir(servicesDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyServices: Record<string, any> = {};\n for (const file of serviceFiles) {\n const name = file.replace('.encrypted.json', '');\n if (!name) continue; // skip empty default service\n const data = await readEncrypted(join(servicesDir, file));\n if (data?.label) legacyServices[name] = data;\n }\n\n // Overrides\n const overridesDir = join(dbsDir, 'overrides');\n const overrideFiles = (await readdir(overridesDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyServiceOverrides: Record<string, any> = {};\n const legacyEnvOverrides: Record<string, any> = {};\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n const data = await readEncrypted(join(overridesDir, file));\n if (!data) continue;\n\n if (baseName.endsWith('-envs')) {\n legacyServiceOverrides[baseName.slice(0, -5)] = data;\n } else if (baseName.endsWith('-environment')) {\n legacyEnvOverrides[baseName.slice(0, -12)] = data;\n }\n }\n\n // Custom parsers\n const parsersDir = join(dbsDir, 'parsers');\n const parserFiles = (await readdir(parsersDir).catch(() => [] as string[]))\n .filter(f => f.endsWith('.encrypted.json'));\n\n const legacyParsers: any[] = [];\n for (const file of parserFiles) {\n const data = await readEncrypted(join(parsersDir, file));\n if (data?.id) legacyParsers.push(data);\n }\n\n // ── 4. Build Runeya data structures ─────────────────────────────────────────\n\n // Projects\n const projectMonoId = randomUUID();\n\n // Environments — two-pass to resolve parentIds after all IDs are known\n // envIdMap keyed by filename (without extension) for ID lookup\n const envIdMap: Record<string, string> = {};\n // labelToKey maps label → filename key, for resolving extends references\n const labelToKey: Record<string, string> = {};\n for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {\n envIdMap[name] = randomUUID();\n if (legacyEnv?.label) labelToKey[legacyEnv.label] = name;\n }\n\n const runeEnvs: any[] = [];\n const defaultEnvName = Object.entries(legacyEnvs).find(([, v]) => v?.default)?.[0];\n\n // Lookup map: `${envId}:${cleanedVarName}` → variableId (UUID)\n const varIdLookup = new Map<string, string>();\n\n for (const [name, legacyEnv] of Object.entries(legacyEnvs)) {\n if (!legacyEnv) continue;\n\n // Collect all variables inherited from parent envs (union, first-parent wins)\n const inheritedVars: Record<string, string> = {};\n for (const parentLabel of legacyEnv.extends || []) {\n const parentKey = labelToKey[parentLabel] ?? parentLabel;\n const parentEnv = legacyEnvs[parentKey];\n for (const [k, v] of Object.entries(parentEnv?.envs ?? {})) {\n if (typeof v === 'string') {\n const cleaned = cleanVarKey(k);\n if (!(cleaned in inheritedVars)) inheritedVars[cleaned] = v;\n }\n }\n }\n\n const variables: Record<string, Variable> = {};\n for (const [key, value] of Object.entries(legacyEnv.envs || {})) {\n if (typeof value === 'string') {\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n // Skip if identical to inherited value — the child inherits it anyway\n if (inheritedVars[cleaned] === value) continue;\n const varId = randomUUID();\n variables[varId] = makeVariable(cleaned, value);\n varIdLookup.set(`${envIdMap[name]}:${cleaned}`, varId);\n }\n }\n\n runeEnvs.push({\n id: envIdMap[name],\n projectId: projectMonoId,\n name: legacyEnv.label || name,\n description: '',\n scope: 'global' as const,\n parentIds: (legacyEnv.extends || [])\n .map((p: string) => envIdMap[labelToKey[p] ?? p])\n .filter(Boolean),\n immutable: false,\n default: name === defaultEnvName,\n color: legacyEnv.bgColor || '#22c55e',\n variables,\n });\n }\n\n // Services\n const serviceIdMap: Record<string, string> = {};\n const runeServices: any[] = [];\n\n for (const [name, legacy] of Object.entries(legacyServices)) {\n const id = randomUUID();\n serviceIdMap[name] = id;\n\n // rootPath = legacy global working directory for this service\n const rootPath: string = legacy.rootPath || '';\n const rootPathCwd = rootPath && rootPath !== '.' ? rootPath : '';\n\n // Commands: spawnCmd + spawnArgs → single command string\n // Command cwd only set if the command has its own explicit cwd (not inherited from rootPath)\n const commands: any[] = [];\n for (const cmd of legacy.commands || []) {\n const parts = [cmd.spawnCmd, ...(cmd.spawnArgs || [])].filter(Boolean);\n if (!parts.length) continue;\n commands.push({\n id: cmd.id || randomUUID(),\n label: 'Launch',\n command: parts.join(' '),\n cwd: cmd.spawnOptions?.cwd || '',\n shell: false,\n });\n }\n\n // Parser IDs — deduplicated, remapped\n const effectiveParsers: any[] =\n legacy.commands?.[0]?.effectiveParsers\n ?? legacy.parsers\n ?? [];\n\n const parserIds: string[] = [];\n for (const parser of effectiveParsers) {\n const rawId: string = typeof parser === 'string' ? parser : (parser.id ?? '');\n const mapped = PARSER_ID_MAP[rawId] ?? rawId;\n if (mapped && !parserIds.includes(mapped)) {\n if (!PARSER_ID_MAP[rawId]) {\n console.warn(`[legacy-migration] Unknown parser \"${rawId}\" on service \"${name}\" — kept as-is`);\n }\n parserIds.push(mapped);\n }\n }\n\n // Health check — extract path from URL, rename returnCode → expectedStatus\n // Only migrate if explicitly enabled (or if enabled field absent, presence of URL implies intent)\n let healthCheck: any;\n if (legacy.health?.url && legacy.health?.enabled !== false) {\n try {\n const healthUrl = new URL(legacy.health.url);\n healthCheck = {\n path: healthUrl.pathname || '/',\n method: legacy.health.method || 'GET',\n ...(typeof legacy.health.interval === 'number' && { interval: legacy.health.interval }),\n expectedStatus: legacy.health.returnCode || 200,\n };\n } catch {\n // Invalid URL — skip health check\n }\n }\n\n // Docker config — map legacy container fields to DockerConfig\n // Legacy structure: container.build (Dockerfile content), container.bootstrap.commands,\n // container.volumes, container.ports, container.name, container.ignoreVolumes, etc.\n let dockerConfig: any;\n const container = legacy.container;\n if (container?.enabled) {\n dockerConfig = {\n volumes: container.volumes || [],\n ports: container.ports || [],\n networkMode: container.networkMode || 'host',\n };\n\n // Dockerfile — legacy uses \"build\" field (not \"dockerfile\")\n // buildContext defaults to \".\" (Docker needs a valid context for COPY/ADD)\n if (container.build) {\n dockerConfig.dockerfile = container.build;\n dockerConfig.buildContext = '.';\n }\n\n // Image (pull mode, mutually exclusive with Dockerfile in UI)\n // Legacy \"name\" field can serve as image if no explicit \"image\" field\n if (container.image) {\n dockerConfig.image = container.image;\n } else if (container.name && !container.build) {\n dockerConfig.image = container.name;\n }\n\n // Build args — legacy uses container.buildArgs (Record<string, string>)\n if (container.buildArgs && typeof container.buildArgs === 'object') {\n dockerConfig.buildArgs = container.buildArgs;\n }\n\n // Target stage — legacy uses container.targetStage\n if (container.targetStage) {\n dockerConfig.targetStage = container.targetStage;\n }\n\n // User — legacy uses container.user or bootstrap command user\n if (container.user) {\n dockerConfig.user = container.user;\n }\n\n // Bootstrap commands — legacy uses container.bootstrap.commands[]\n // Each entry has { entrypoint, cmd, user }\n // Migrate ALL commands as bootstrapCommands[] (structured array)\n const legacyBootstrapCmds: any[] = container.bootstrap?.commands || [];\n if (legacyBootstrapCmds.length > 0) {\n dockerConfig.bootstrapCommands = legacyBootstrapCmds\n .filter((bs: any) => bs.cmd || bs.entrypoint)\n .map((bs: any, idx: number) => ({\n id: bs.id || randomUUID(),\n label: bs.label || `Bootstrap ${idx + 1}`,\n command: bs.cmd || '',\n ...(bs.entrypoint ? { entrypoint: bs.entrypoint } : {}),\n ...(bs.user ? { user: bs.user } : {}),\n }));\n\n // Also set top-level entrypoint/command from first bootstrap for backwards compat\n const first = legacyBootstrapCmds[0];\n if (first?.entrypoint) dockerConfig.entrypoint = first.entrypoint;\n if (first?.cmd) dockerConfig.command = first.cmd;\n\n // Inherit user from first bootstrap if not set at container level\n if (!dockerConfig.user && first?.user) {\n dockerConfig.user = first.user;\n }\n }\n\n // ignoreVolumes → convert to real bind-mount volumes\n // Legacy used ignoreVolumes to mask container paths with a persistent host directory.\n // We convert each to ~/runeya/docker-persistence/<service-id>/<internal-path>:<internal-path>\n const sharedVolume: string = container.sharedVolume || '~/.runeya';\n const ignoreVolumes: string[] = (container.ignoreVolumes || [])\n .filter((v: string) => !v.startsWith(sharedVolume));\n if (ignoreVolumes.length > 0) {\n for (const ignoredPath of ignoreVolumes) {\n // Strip leading slash for the host sub-directory\n const subDir = ignoredPath.replace(/^\\/+/, '');\n const hostPath = `~/runeya/docker-persistence/${id}/${subDir}`;\n dockerConfig.volumes.push(`${hostPath}:${ignoredPath}`);\n }\n console.log(`[legacy-migration] Service \"${legacy.label}\": converted ${ignoreVolumes.length} ignoreVolumes to bind-mount volumes`);\n }\n\n // Native commands (spawnCmd) exist alongside Docker →\n // the service runs its native command inside the container\n if (commands.length > 0) {\n dockerConfig.useNativeCommand = true;\n dockerConfig.nativeCommandMode = 'isolated';\n }\n }\n\n // Port: extract from url (e.g. http://localhost:3034/... → 3034)\n let port: number | undefined;\n const serviceUrl: string = legacy.url || '';\n if (serviceUrl) {\n try {\n const parsed = new URL(serviceUrl);\n const p = parseInt(parsed.port, 10);\n if (p > 0 && p <= 65535) port = p;\n } catch { /* invalid URL */ }\n }\n\n // Top-level cwd = legacy rootPath (global working directory for the service)\n const serviceCwd = rootPathCwd;\n\n const runeService: any = {\n id,\n orgId: null,\n agentId: 'local-agent',\n name: legacy.label,\n commands,\n cwd: serviceCwd,\n runner: dockerConfig ? 'docker' : 'native',\n shortcuts: (legacy.shortcuts || [])\n .filter((s: any) => s.spawnCmd || s.label)\n .map((s: any) => ({\n id: s.id || randomUUID(),\n label: s.label || s.spawnCmd || '',\n command: [s.spawnCmd, ...(s.spawnArgs || [])].filter(Boolean).join(' '),\n ...(s.spawnOptions?.cwd ? { cwd: s.spawnOptions.cwd } : {}),\n })),\n autoRestart: false,\n restartBackoffMs: 1000,\n groups: legacy.groups || [],\n description: legacy.description || '',\n url: legacy.url || '',\n openapiUrl: legacy.openapiURL || '',\n git: {\n remote: legacy.git?.remote || '',\n home: legacy.git?.home || '',\n },\n env: {},\n envSecrets: [],\n parserIds,\n meta: legacy.meta || {},\n ...(port !== undefined ? { ports: [port] } : {}),\n };\n\n if (healthCheck) runeService.healthCheck = healthCheck;\n if (dockerConfig) runeService.dockerConfig = dockerConfig;\n\n runeServices.push(runeService);\n }\n\n // Service inline envs → service-scoped environments (shared base variables)\n // Legacy stores per-service env vars as: service.envs = { \"LOCAL\": { \"KEY\": { value, key } }, ... }\n // These are the shared/committed base values — processed FIRST so overrides can reference their variableIds\n for (const [name, legacy] of Object.entries(legacyServices)) {\n const serviceId = serviceIdMap[name];\n if (!serviceId) continue;\n const service = runeServices.find((s: any) => s.id === serviceId);\n const svcEnvs: Record<string, Record<string, any>> = legacy.envs || {};\n\n for (const [envName, vars] of Object.entries(svcEnvs)) {\n if (!vars || typeof vars !== 'object' || Object.keys(vars).length === 0) continue;\n const globalEnvId = envIdMap[envName];\n const globalEnv = runeEnvs.find((e: any) => e.id === globalEnvId);\n if (!globalEnvId || !globalEnv) continue;\n\n let svcScopedEnv = runeEnvs.find(\n (e: any) => e.scope === 'service' && e.reference === serviceId && e.activateOn === globalEnvId,\n );\n\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: projectMonoId,\n name: `${service?.name || name} (${globalEnv.name})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n runeEnvs.push(svcScopedEnv);\n }\n\n const existingKeys = new Set(\n Object.values(svcScopedEnv.variables as Record<string, Variable>).map((v: Variable) => v.key),\n );\n for (const [, varData] of Object.entries(vars as Record<string, any>)) {\n const varKey: string = typeof varData === 'object' ? String(varData.key ?? '') : '';\n const varValue: string = typeof varData === 'object' ? String(varData.value ?? '') : String(varData ?? '');\n const varPre: string = typeof varData === 'object' ? String(varData.prefix ?? '') : '';\n const varPost: string = typeof varData === 'object' ? String(varData.suffix ?? '') : '';\n if (!varKey || existingKeys.has(cleanVarKey(varKey))) continue;\n const cleaned = cleanVarKey(varKey);\n const varId = randomUUID();\n svcScopedEnv.variables[varId] = makeVariable(cleaned, varValue, varPre, varPost);\n existingKeys.add(cleaned);\n }\n }\n }\n\n // Service overrides → environment-overrides.json (personal/local overrides)\n // Legacy *-envs.encrypted.json files are per-user overrides of service-level env vars.\n // Service-scoped environments share the same override mechanism as global environments,\n // so these go into environment-overrides.json keyed by variableId.\n // If the base variable doesn't exist yet (no entry in service.envs), it is created with an\n // empty value so the override has something to reference.\n const svcFlatOverrides: Record<string, Variable> = {};\n for (const [serviceName, envOverrides] of Object.entries(legacyServiceOverrides)) {\n const serviceId = serviceIdMap[serviceName];\n if (!serviceId) continue;\n const service = runeServices.find((s: any) => s.id === serviceId);\n\n for (const [envName, vars] of Object.entries(envOverrides as Record<string, Record<string, string>>)) {\n const globalEnvId = envIdMap[envName];\n const globalEnv = runeEnvs.find((e: any) => e.id === globalEnvId);\n if (!globalEnv || !vars || typeof vars !== 'object') continue;\n\n // Find or create the service-scoped env for this (service, globalEnv) pair\n let svcScopedEnv = runeEnvs.find(\n (e: any) => e.scope === 'service' && e.reference === serviceId && e.activateOn === globalEnvId,\n );\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: projectMonoId,\n name: `${service?.name || serviceName} (${globalEnv.name})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n runeEnvs.push(svcScopedEnv);\n }\n\n for (const [key, value] of Object.entries(vars)) {\n if (typeof value !== 'string') continue;\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n\n // Find the base variable in the service-scoped env by key name\n const baseEntry = Object.entries(svcScopedEnv.variables as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned);\n let varId = baseEntry?.[0];\n\n if (!varId) {\n // No base variable exists — create an empty base so the override has something to reference\n varId = randomUUID();\n svcScopedEnv.variables[varId] = {\n key: cleaned,\n value: { value: '', pre: '', post: '', isSecret: false },\n };\n }\n\n // Carry pre/post from the base variable — overrides only replace the value\n const basePre = baseEntry?.[1]?.value?.pre ?? '';\n const basePost = baseEntry?.[1]?.value?.post ?? '';\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseEntry?.[1])) continue;\n svcFlatOverrides[varId] = makeVariable(cleaned, value, basePre, basePost);\n }\n }\n }\n\n // Environment overrides — from *-environment.encrypted.json files\n // Keys ending in _OVERRIDE → environment-overrides.json (flat Record<variableId, Variable>)\n // Other keys → merged into environment.variables (additional values)\n const flatOverrides: Record<string, Variable> = { ...svcFlatOverrides };\n for (const [envName, data] of Object.entries(legacyEnvOverrides)) {\n const envId = envIdMap[envName];\n const env = runeEnvs.find((e: any) => e.id === envId);\n if (!envId || !env || !data) continue;\n\n const envVars: Record<string, string> = (data as Record<string, unknown>).envs as Record<string, string> ?? {};\n\n for (const [key, value] of Object.entries(envVars)) {\n if (typeof value !== 'string') continue;\n\n if (key.endsWith('_OVERRIDE')) {\n // Strip all legacy suffixes → goes into environment-overrides.json\n const cleaned = cleanVarKey(key);\n const varId = varIdLookup.get(`${envId}:${cleaned}`);\n if (varId) {\n const baseVar = (env.variables as Record<string, Variable>)[varId];\n // Skip redundant override — value identical to base\n if (!isSameAsBase(value, baseVar)) {\n flatOverrides[varId] = makeVariable(cleaned, value);\n }\n } else {\n // Variable not found in env — create a new UUID entry\n flatOverrides[randomUUID()] = makeVariable(cleaned, value);\n }\n } else {\n // Regular variable → merge into environment.variables (with _RUNEYA stripped)\n const cleaned = cleanVarKey(key);\n // Check if this var already exists in env.variables (by key name)\n const existingVarId = Object.entries(env.variables as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned)?.[0];\n if (!existingVarId) {\n const varId = randomUUID();\n env.variables[varId] = makeVariable(cleaned, value);\n varIdLookup.set(`${envId}:${cleaned}`, varId);\n }\n }\n }\n }\n\n // Projects — single project containing all services\n // Built AFTER service-scoped envs so allEnvIds includes them\n // Priority: explicit default flag → env named LOCAL → first env\n const localEnvName = Object.keys(legacyEnvs).find(n => n.toUpperCase() === 'LOCAL');\n const activeEnvId = defaultEnvName\n ? (envIdMap[defaultEnvName] ?? runeEnvs[0]?.id)\n : (localEnvName ? (envIdMap[localEnvName] ?? runeEnvs[0]?.id) : runeEnvs[0]?.id);\n const allEnvIds = runeEnvs.map(e => e.id);\n const allServiceIds = runeServices.map(s => s.id);\n\n const runeProjects: any[] = [];\n if (allServiceIds.length > 0 || allEnvIds.length > 0) {\n runeProjects.push({\n id: projectMonoId,\n orgId: null,\n name: 'Migrated Project',\n description: '',\n serviceIds: allServiceIds,\n environmentIds: allEnvIds,\n activeEnvironmentId: activeEnvId,\n });\n }\n\n const primaryProjectId = projectMonoId;\n for (const env of runeEnvs) {\n env.projectId = primaryProjectId;\n }\n\n // Settings — preserve existing + add migrated custom parsers\n let existingSettings: any = {};\n try {\n existingSettings = JSON.parse(await readFile(join(dataDir, 'settings.json'), 'utf-8'));\n } catch { /* first run */ }\n\n const migratedParsers = legacyParsers.map(p => ({\n id: p.id,\n name: p.label,\n // Legacy transform uses module.exports API — kept for reference, must be rewritten\n code: `// Migrated from legacy parser \"${p.label}\"\\n// TODO: rewrite using new API: (raw: string, stream: 'stdout'|'stderr') => ParseResult | null\\n// Legacy code (module.exports style — NOT compatible):\\n${p.transform ?? ''}`,\n enabled: false, // disabled until manually rewritten\n }));\n\n const newSettings = {\n ...existingSettings,\n logParsers: [\n ...(existingSettings.logParsers ?? []),\n ...migratedParsers,\n ],\n };\n\n // ── 5. Write output files ────────────────────────────────────────────────────\n await atomicWrite(join(dataDir, 'projects.json'), runeProjects);\n await atomicWrite(join(dataDir, 'services.json'), runeServices);\n await atomicWrite(join(dataDir, 'environments.json'), runeEnvs);\n await atomicWrite(join(dataDir, 'environment-overrides.json'), flatOverrides);\n await atomicWrite(join(dataDir, 'settings.json'), newSettings);\n\n const svcEnvCount = runeEnvs.filter((e: any) => e.scope === 'service').length;\n console.log(`[legacy-migration] Written: ${runeProjects.length} projects, ${runeServices.length} services, ${runeEnvs.length} environments (${svcEnvCount} service-scoped)`);\n console.log(`[legacy-migration] Overrides: ${Object.keys(flatOverrides).length}, custom parsers: ${migratedParsers.length} (all disabled — rewrite required)`);\n\n // Clear the main singleton so hasEncryptionKey() returns false → state = setup\n // Store the key in the pending holder for /api/setup to consume\n clearEncryptionKey();\n setPendingLegacyKey(keyBuffer);\n console.log('[legacy-migration] Done. Data migrated to .runeya — master password setup required');\n\n return true;\n}\n\n// ── Find legacy key in backup (restart between migration and setup) ─────────\n//\n// If the server restarts after runLegacyMigration but before /api/setup,\n// the pending key is lost (in-memory only). This function scans backup dirs\n// to recover the libsodium key so the user can still complete setup.\n\nexport async function findLegacyKeyInBackup(dataDir: string): Promise<Buffer | null> {\n try {\n const entries = await readdir(dataDir);\n const backupDirs = entries.filter(e => e.startsWith('backup-')).sort().reverse();\n for (const dir of backupDirs) {\n const keyJsonPath = join(dataDir, dir, 'dbs', 'encryption-key.json');\n try {\n const raw = await readFile(keyJsonPath, 'utf-8');\n const parsed = JSON.parse(raw) as { encryptionKey?: string };\n if (!parsed.encryptionKey) continue;\n const sodium = await getSodium();\n const sodiumKey = sodium.from_base64(parsed.encryptionKey) as Uint8Array;\n const buf = Buffer.from(sodiumKey);\n if (buf.length === 32) {\n console.log(`[legacy-migration] Recovered legacy key from ${keyJsonPath}`);\n return buf;\n }\n } catch {\n // This backup dir doesn't have a valid key — try next\n }\n }\n } catch {\n // dataDir doesn't exist or isn't readable\n }\n return null;\n}\n\n// ── Override-only migration (User B scenario) ──────────────────────────────\n//\n// When the data dir is tracked by git and User A already ran the full migration:\n// - Git deleted dbs/encryption-key.json (was tracked)\n// - Git delivered the migrated JSON files (projects, services, environments…)\n// - But User B's dbs/overrides/*.encrypted.json are still on disk (gitignored)\n// - The full migration didn't trigger (no encryption-key.json)\n// - User B's overrides were never migrated → orphaned\n//\n// This function runs AFTER .encryption.key is available (same 32 bytes as\n// the legacy libsodium key, just in hex format). It decrypts User B's local\n// override files and writes environment-overrides.json.\n\nexport async function runOverrideOnlyMigration(dataDir: string): Promise<boolean> {\n const { resolve } = await import('node:path');\n const abDataDir = resolve(dataDir);\n\n // Match the full migration: legacy data lives under cwd/.runeya, which may\n // differ from DATA_DIR. Check both locations; prefer cwd-based path (the\n // one git tracks), fall back to dataDir-based path.\n const abCwd = resolve(process.cwd());\n const candidateDirs = [\n join(abCwd, '.runeya', 'dbs', 'overrides'),\n join(abDataDir, 'dbs', 'overrides'),\n ];\n\n let overridesDir: string | null = null;\n let overrideFiles: string[] = [];\n for (const dir of candidateDirs) {\n try {\n const files = (await readdir(dir)).filter(f => f.endsWith('.encrypted.json'));\n if (files.length > 0) {\n overridesDir = dir;\n overrideFiles = files;\n break;\n }\n } catch { /* dir doesn't exist */ }\n }\n if (!overridesDir || overrideFiles.length === 0) return false;\n\n // If the full migration trigger still exists, let the full migration handle it\n const legacyKeyPath = join(overridesDir, '..', 'encryption-key.json');\n try {\n await access(legacyKeyPath);\n return false; // Full migration should run instead\n } catch {\n // Expected — key was deleted by git\n }\n\n // We need .encryption.key to decrypt (it's the same 32 bytes)\n const encKey = getEncryptionKey();\n if (!encKey) {\n console.warn('[override-migration] Cannot migrate overrides: encryption key not loaded yet');\n return false;\n }\n\n console.log(`[override-migration] Found ${overrideFiles.length} orphaned override file(s) in ${overridesDir}, migrating…`);\n\n const sodium = await getSodium();\n // .encryption.key is the same 32 bytes as the legacy libsodium key\n const sodiumKey = new Uint8Array(encKey);\n\n // Load existing environments.json to build lookups\n const varIdLookup = new Map<string, string>();\n const envNameToId: Record<string, string> = {};\n let envsRaw: unknown[];\n try {\n envsRaw = JSON.parse(await readFile(join(abDataDir, 'environments.json'), 'utf-8')) as unknown[];\n for (const _env of envsRaw) {\n const env = _env as Record<string, unknown>;\n if (env['name'] && env['id']) {\n envNameToId[env['name'] as string] = env['id'] as string;\n }\n if (env['variables'] && env['id']) {\n for (const [varId, variable] of Object.entries(env['variables'] as Record<string, Variable>)) {\n varIdLookup.set(`${env['id'] as string}:${variable.key}`, varId);\n }\n }\n }\n } catch {\n console.warn('[override-migration] Cannot read environments.json — skipping');\n return false;\n }\n\n // Load services.json for service-override matching (legacy fileName → service name)\n let servicesRaw: unknown[] = [];\n const serviceNameToId: Record<string, string> = {};\n try {\n servicesRaw = JSON.parse(await readFile(join(abDataDir, 'services.json'), 'utf-8')) as unknown[];\n for (const _svc of servicesRaw) {\n const svc = _svc as Record<string, unknown>;\n if (svc['name'] && svc['id']) serviceNameToId[svc['name'] as string] = svc['id'] as string;\n }\n } catch { /* services.json missing — service overrides won't match */ }\n\n // Helper: find env ID by name (exact or case-insensitive)\n function findEnvId(name: string): string | undefined {\n return envNameToId[name]\n ?? Object.entries(envNameToId).find(([n]) => n.toLowerCase() === name.toLowerCase())?.[1];\n }\n\n // ── 1. Environment overrides (*-environment.encrypted.json) → environment-overrides.json ──\n const flatOverrides: Record<string, Variable> = {};\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n if (!baseName.endsWith('-environment')) continue;\n const envName = baseName.slice(0, -'-environment'.length);\n\n let data: any;\n try {\n data = await decryptLegacyFile(join(overridesDir, file), sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[override-migration] Failed to decrypt ${file}: ${(err as Error).message}`);\n continue;\n }\n if (!data) continue;\n\n const envId = findEnvId(envName);\n if (!envId) {\n console.warn(`[override-migration] No matching environment for \"${envName}\" — skipping`);\n continue;\n }\n\n const envVars: Record<string, string> = data.envs ?? {};\n for (const [key, value] of Object.entries(envVars)) {\n if (typeof value !== 'string') continue;\n if (!key.endsWith('_OVERRIDE')) continue;\n\n const cleaned = cleanVarKey(key);\n const varId = varIdLookup.get(`${envId}:${cleaned}`);\n if (varId) {\n const baseVar = ((envsRaw as Record<string, unknown>[]).find((e) => e['id'] === envId)?.['variables'] as Record<string, Variable> | undefined)?.[varId];\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseVar)) continue;\n flatOverrides[varId] = makeVariable(cleaned, value);\n } else {\n flatOverrides[randomUUID()] = makeVariable(cleaned, value);\n }\n }\n }\n\n if (Object.keys(flatOverrides).length > 0) {\n await atomicWrite(join(abDataDir, 'environment-overrides.json'), flatOverrides);\n console.log(`[override-migration] Written ${Object.keys(flatOverrides).length} override(s) to environment-overrides.json`);\n }\n\n // ── 2. Service overrides (*-envs.encrypted.json) → environment-overrides.json ──\n // Service-scoped environments share the same override mechanism as global environments.\n // Personal service variable overrides go into environment-overrides.json (keyed by variableId).\n // If the base variable doesn't exist in the service-scoped env, an empty base is created first.\n let envsModified = false;\n\n for (const file of overrideFiles) {\n const baseName = file.replace('.encrypted.json', '');\n if (!baseName.endsWith('-envs')) continue;\n const serviceName = baseName.slice(0, -'-envs'.length);\n\n let data: any;\n try {\n data = await decryptLegacyFile(join(overridesDir, file), sodiumKey, sodium);\n } catch (err: unknown) {\n console.warn(`[override-migration] Failed to decrypt ${file}: ${(err as Error).message}`);\n continue;\n }\n if (!data || typeof data !== 'object') continue;\n\n // Find service ID: try by legacy filename, then case-insensitive name match\n const serviceId = serviceNameToId[serviceName]\n ?? Object.entries(serviceNameToId).find(([n]) => n.toLowerCase() === serviceName.toLowerCase())?.[1];\n if (!serviceId) {\n console.warn(`[override-migration] No matching service for \"${serviceName}\" — skipping service overrides`);\n continue;\n }\n\n const service = (servicesRaw as Record<string, unknown>[]).find((s) => s['id'] === serviceId);\n\n for (const [envName, vars] of Object.entries(data as Record<string, Record<string, string>>)) {\n const globalEnvId = findEnvId(envName);\n if (!globalEnvId || !vars || typeof vars !== 'object') continue;\n const globalEnv = (envsRaw as Record<string, unknown>[]).find((e) => e['id'] === globalEnvId);\n if (!globalEnv) continue;\n\n // Find or create the service-scoped env for this (service, globalEnv) pair\n let svcScopedEnv = (envsRaw as Record<string, unknown>[]).find(\n (e) => e['scope'] === 'service' && e['reference'] === serviceId && e['activateOn'] === globalEnvId,\n );\n if (!svcScopedEnv) {\n svcScopedEnv = {\n id: randomUUID(),\n projectId: globalEnv['projectId'],\n name: `${(service?.['name'] as string | undefined) || serviceName} (${globalEnv['name'] as string})`,\n scope: 'service' as const,\n reference: serviceId,\n activateOn: globalEnvId,\n parentIds: [],\n variables: {} as Record<string, Variable>,\n description: '',\n immutable: false,\n default: false,\n };\n envsRaw.push(svcScopedEnv);\n envsModified = true;\n }\n\n for (const [key, value] of Object.entries(vars)) {\n if (typeof value !== 'string') continue;\n if (hasInvalidInterpolation(value)) continue;\n const cleaned = cleanVarKey(key);\n\n // Find the base variable in the service-scoped env by key name\n const baseEntry = Object.entries(svcScopedEnv['variables'] as Record<string, Variable>)\n .find(([, v]) => v.key === cleaned);\n let varId = baseEntry?.[0];\n\n if (!varId) {\n // No base variable — create an empty base so the override has something to reference\n varId = randomUUID();\n (svcScopedEnv['variables'] as Record<string, Variable>)[varId] = {\n key: cleaned,\n value: { value: '', pre: '', post: '', isSecret: false },\n };\n envsModified = true;\n }\n\n // Carry pre/post from the base variable — overrides only replace the value\n const basePre = baseEntry?.[1]?.value?.pre ?? '';\n const basePost = baseEntry?.[1]?.value?.post ?? '';\n // Skip redundant override — value identical to base\n if (isSameAsBase(value, baseEntry?.[1])) continue;\n flatOverrides[varId] = makeVariable(cleaned, value, basePre, basePost);\n }\n }\n }\n\n if (envsModified) {\n await atomicWrite(join(abDataDir, 'environments.json'), envsRaw);\n console.log('[override-migration] Merged service overrides into environments.json');\n }\n\n // Move dbs/overrides/ → dbs/overrides-migrated/ to prevent re-running\n const migratedDir = overridesDir.replace(/overrides$/, 'overrides-migrated');\n try {\n await rename(overridesDir, migratedDir);\n console.log(`[override-migration] Moved overrides/ → overrides-migrated/`);\n } catch (err: unknown) {\n console.warn(`[override-migration] Could not rename overrides dir: ${(err as Error).message}`);\n }\n\n console.log('[override-migration] Done');\n return true;\n}\n","import { randomBytes, createCipheriv, createDecipheriv } from 'node:crypto';\nimport { readFile, writeFile, chmod, stat, rename } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { Entry } from '@napi-rs/keyring';\nimport { hashRaw as argon2HashRaw } from '@node-rs/argon2';\n\nconst KEYRING_SERVICE = 'runeya';\nconst KEYRING_ACCOUNT = 'pepper';\nconst VERIFY_FILENAME = '.runeya-verify';\nconst ENCRYPTED_KEY_FILENAME = '.encryption.key.enc';\nconst PEPPER_FILENAME = '.pepper.private';\nconst CANARY_PLAINTEXT = 'runeya:v1:key-verification';\nconst MAX_KEY_FILE_SIZE = 1024; // 1 KB\nconst ARGON2_OPTIONS = { memoryCost: 65536, timeCost: 3, parallelism: 4, outputLen: 32 };\n\n// Helper: validate file size before reading\nasync function readKeyFile(filePath: string): Promise<Buffer> {\n const s = await stat(filePath);\n if (s.size > MAX_KEY_FILE_SIZE) throw new Error(`Fichier suspect : ${filePath} (${s.size} octets)`);\n return readFile(filePath);\n}\n\n// AES-256-GCM encrypt\nfunction aesEncrypt(key: Buffer, plaintext: Buffer): Buffer {\n const iv = randomBytes(12);\n const cipher = createCipheriv('aes-256-gcm', key, iv);\n const encrypted = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, authTag, encrypted]); // 12 + 16 + N bytes\n}\n\n// AES-256-GCM decrypt — throws if authTag invalid\nfunction aesDecrypt(key: Buffer, data: Buffer): Buffer {\n const iv = data.subarray(0, 12);\n const authTag = data.subarray(12, 28);\n const ciphertext = data.subarray(28);\n const decipher = createDecipheriv('aes-256-gcm', key, iv, { authTagLength: 16 });\n decipher.setAuthTag(authTag);\n return Buffer.concat([decipher.update(ciphertext), decipher.final()]);\n}\n\n// Fallback: store pepper as a file in dataDir (chmod 600)\nasync function getPepperFromFile(dataDir: string): Promise<Buffer | null> {\n try {\n const raw = await readKeyFile(join(dataDir, PEPPER_FILENAME));\n const hex = raw.toString('utf-8').trim();\n if (/^[0-9a-f]{64}$/i.test(hex)) return Buffer.from(hex, 'hex');\n } catch { /* not found */ }\n return null;\n}\n\nasync function writePepperToFile(dataDir: string, pepper: Buffer): Promise<void> {\n const filePath = join(dataDir, PEPPER_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, pepper.toString('hex'), 'utf-8');\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, filePath);\n}\n\nfunction tryKeyringGet(): string | null {\n try { return new Entry(KEYRING_SERVICE, KEYRING_ACCOUNT).getPassword(); } catch { return null; }\n}\n\nfunction tryKeyringSet(value: string): boolean {\n try { new Entry(KEYRING_SERVICE, KEYRING_ACCOUNT).setPassword(value); return true; } catch { return false; }\n}\n\n// Get or generate pepper — keyring first, file fallback\nasync function getOrCreatePepper(dataDir: string): Promise<Buffer> {\n // Try keyring read\n const pepperHex = tryKeyringGet();\n if (pepperHex && /^[0-9a-f]{64}$/i.test(pepperHex)) {\n return Buffer.from(pepperHex, 'hex');\n }\n // Keyring failed or empty — try file fallback\n const filePepper = await getPepperFromFile(dataDir);\n if (filePepper) return filePepper;\n // Generate new pepper, persist in keyring if possible, else file\n const pepper = randomBytes(32);\n const saved = tryKeyringSet(pepper.toString('hex'));\n if (!saved) {\n console.warn('[master-password] Keyring unavailable, storing pepper in dataDir (fallback)');\n await writePepperToFile(dataDir, pepper);\n }\n return pepper;\n}\n\n// Derive key from master password + pepper using Argon2id\n// Returns 32-byte derived key (never stored)\nasync function deriveKey(masterPassword: string, pepper: Buffer, salt: Buffer): Promise<Buffer> {\n const combined = masterPassword + pepper.toString('hex');\n const derived = await argon2HashRaw(combined, {\n ...ARGON2_OPTIONS,\n salt,\n });\n return Buffer.from(derived);\n}\n\n// Encrypt encryption key and write to .encryption.key.enc\n// Format: base64(salt_16 + iv_12 + authTag_16 + ciphertext_32)\nexport async function writeEncryptedKey(dataDir: string, masterPassword: string, encryptionKey: Buffer): Promise<void> {\n const pepper = await getOrCreatePepper(dataDir);\n const salt = randomBytes(16);\n const derivedKey = await deriveKey(masterPassword, pepper, salt);\n const payload = aesEncrypt(derivedKey, encryptionKey); // iv(12) + authTag(16) + ciphertext(32)\n const fileContent = Buffer.concat([salt, payload]);\n const encoded = fileContent.toString('base64');\n const filePath = join(dataDir, ENCRYPTED_KEY_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, encoded, 'utf-8');\n await chmod(tmpPath, 0o600);\n await rename(tmpPath, filePath);\n}\n\n// Read and decrypt .encryption.key.enc — throws on wrong password\nexport async function readEncryptedKey(dataDir: string, masterPassword: string): Promise<Buffer> {\n const filePath = join(dataDir, ENCRYPTED_KEY_FILENAME);\n const raw = await readKeyFile(filePath);\n const fileContent = Buffer.from(raw.toString('utf-8').trim(), 'base64');\n const salt = fileContent.subarray(0, 16);\n const payload = fileContent.subarray(16); // iv(12) + authTag(16) + ciphertext(32)\n const pepper = await getPepperFromKeychain(dataDir);\n const derivedKey = await deriveKey(masterPassword, pepper, salt);\n // throws if authTag invalid → wrong password\n return aesDecrypt(derivedKey, payload);\n}\n\n// Get pepper from keychain, file fallback (must exist — throws if not found anywhere)\nasync function getPepperFromKeychain(dataDir: string): Promise<Buffer> {\n const pepperHex = tryKeyringGet();\n if (pepperHex && /^[0-9a-f]{64}$/i.test(pepperHex)) {\n return Buffer.from(pepperHex, 'hex');\n }\n // Fallback to file\n const filePepper = await getPepperFromFile(dataDir);\n if (filePepper) return filePepper;\n throw new Error('Pepper introuvable (keyring et fichier). Re-setup requis.');\n}\n\n// Write canary file .runeya-verify\nexport async function writeVerifyFile(dataDir: string, encryptionKey: Buffer): Promise<void> {\n const payload = aesEncrypt(encryptionKey, Buffer.from(CANARY_PLAINTEXT, 'utf-8'));\n const filePath = join(dataDir, VERIFY_FILENAME);\n const tmpPath = filePath + '.tmp';\n await writeFile(tmpPath, payload.toString('base64'), 'utf-8');\n await rename(tmpPath, filePath);\n}\n\n// Verify encryption key against .runeya-verify — throws if wrong key\nexport async function verifyEncryptionKey(dataDir: string, encryptionKey: Buffer): Promise<void> {\n const filePath = join(dataDir, VERIFY_FILENAME);\n const raw = await readKeyFile(filePath);\n const payload = Buffer.from(raw.toString('utf-8').trim(), 'base64');\n const plaintext = aesDecrypt(encryptionKey, payload);\n if (plaintext.toString('utf-8') !== CANARY_PLAINTEXT) {\n throw new Error('Clé d\\'encryption incorrecte');\n }\n}\n\n// Check if .runeya-verify exists\nexport async function hasVerifyFile(dataDir: string): Promise<boolean> {\n try {\n await stat(join(dataDir, VERIFY_FILENAME));\n return true;\n } catch {\n return false;\n }\n}\n\n// Check if .encryption.key.enc exists\nexport async function hasEncryptedKeyFile(dataDir: string): Promise<boolean> {\n try {\n await stat(join(dataDir, ENCRYPTED_KEY_FILENAME));\n return true;\n } catch {\n return false;\n }\n}\n\n","import { join } from 'node:path';\nimport { stat } from 'node:fs/promises';\nimport { hasEncryptionKey, hasPendingLegacyKey } from '../utils/encryption-key.js';\nimport { env } from '../config/env.js';\n\nexport type ServerState = 'locked' | 'setup' | 'unlocked';\n\nconst ENCRYPTED_KEY_FILENAME = '.encryption.key.enc';\nconst VERIFY_FILENAME = '.runeya-verify';\n\nexport async function getServerState(): Promise<{ state: ServerState; hasVerifyFile: boolean; isLegacyMigration: boolean; hasExistingData: boolean }> {\n const dataDir = env.DATA_DIR;\n\n let hasEncFile = false;\n let hasVerify = false;\n let hasData = false;\n\n try { await stat(join(dataDir, ENCRYPTED_KEY_FILENAME)); hasEncFile = true; } catch {}\n try { await stat(join(dataDir, VERIFY_FILENAME)); hasVerify = true; } catch {}\n try { await stat(join(dataDir, 'projects.json')); hasData = true; } catch {}\n\n if (hasEncryptionKey()) {\n return { state: 'unlocked', hasVerifyFile: false, isLegacyMigration: false, hasExistingData: hasData };\n }\n\n if (hasEncFile) {\n return { state: 'locked', hasVerifyFile: hasVerify, isLegacyMigration: false, hasExistingData: hasData };\n }\n\n // SETUP state — legacy migration detected via in-memory pending key holder\n return {\n state: 'setup',\n hasVerifyFile: hasVerify,\n isLegacyMigration: hasPendingLegacyKey(),\n hasExistingData: hasData,\n };\n}\n","import { env } from '../config/env.js';\n\nconst BASE = `http://localhost:${env.PORT}/api/trpc`;\n\nexport function getOpenApiDocument() {\n return {\n openapi: '3.1.0',\n info: {\n title: 'Runeya API',\n version: '1.0.0',\n description: 'Runeya service management API — tRPC over HTTP.\\n\\n**Queries** use `GET /{procedure}?input={json}`.\\n**Mutations** use `POST /{procedure}` with a JSON body.\\n\\nAll protected routes require `Authorization: Bearer <jwt>` header.',\n },\n servers: [{ url: BASE }],\n paths: {\n '/health.check': {\n get: {\n tags: ['Health'],\n summary: 'Health check',\n operationId: 'health.check',\n responses: {\n '200': { description: 'Server is up', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', properties: { status: { type: 'string', example: 'ok' }, uptime: { type: 'number' } } } } } } } } } },\n },\n },\n },\n '/service.list': {\n get: {\n tags: ['Services'],\n summary: 'List all services',\n operationId: 'service.list',\n security: [{ BearerAuth: [] }],\n responses: {\n '200': { description: 'Array of services', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'array', items: { $ref: '#/components/schemas/Service' } } } } } } } } },\n },\n },\n },\n '/service.get': {\n get: {\n tags: ['Services'],\n summary: 'Get a service by ID',\n operationId: 'service.get',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"id\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"id\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Service object', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.create': {\n post: {\n tags: ['Services'],\n summary: 'Create a new service',\n operationId: 'service.create',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'name'], properties: {\n agentId: { type: 'string' },\n name: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n runner: { type: 'string', enum: ['native', 'docker'], default: 'native' },\n } } } },\n },\n responses: {\n '200': { description: 'Created service', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.update': {\n post: {\n tags: ['Services'],\n summary: 'Update a service',\n operationId: 'service.update',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['id'], properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Updated service', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { $ref: '#/components/schemas/Service' } } } } } } } },\n },\n },\n },\n '/service.delete': {\n post: {\n tags: ['Services'],\n summary: 'Delete a service',\n operationId: 'service.delete',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['id'], properties: { id: { type: 'string' } } } } },\n },\n responses: {\n '200': { description: 'Deletion result', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', properties: { success: { type: 'boolean' } } } } } } } } } },\n },\n },\n },\n '/process.list': {\n get: {\n tags: ['Processes'],\n summary: 'List all processes across all connected agents',\n operationId: 'process.list',\n security: [{ BearerAuth: [] }],\n responses: {\n '200': { description: 'Array of processes', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'array', items: { $ref: '#/components/schemas/Process' } } } } } } } } },\n },\n },\n },\n '/process.get': {\n get: {\n tags: ['Processes'],\n summary: 'Get a process by agent and service ID',\n operationId: 'process.get',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"agentId\":\"<agentId>\",\"id\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Process object' },\n },\n },\n },\n '/process.logs': {\n get: {\n tags: ['Processes'],\n summary: 'Get buffered logs for a process',\n operationId: 'process.logs',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}',\n description: 'JSON-encoded input: `{\"agentId\":\"<agentId>\",\"processId\":\"<serviceId>\"}`',\n }],\n responses: {\n '200': { description: 'Array of log lines' },\n },\n },\n },\n '/process.start': {\n post: {\n tags: ['Processes'],\n summary: 'Start a process',\n operationId: 'process.start',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Start result' },\n },\n },\n },\n '/process.stop': {\n post: {\n tags: ['Processes'],\n summary: 'Stop a process',\n operationId: 'process.stop',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Stop result' },\n },\n },\n },\n '/process.restart': {\n post: {\n tags: ['Processes'],\n summary: 'Restart a process',\n operationId: 'process.restart',\n security: [{ BearerAuth: [] }],\n requestBody: {\n required: true,\n content: { 'application/json': { schema: { type: 'object', required: ['agentId', 'processId'], properties: {\n agentId: { type: 'string' },\n processId: { type: 'string' },\n } } } },\n },\n responses: {\n '200': { description: 'Restart result' },\n },\n },\n },\n '/environment.resolveFlat': {\n get: {\n tags: ['Environments'],\n summary: 'Resolve environment variables as a flat key-value map',\n operationId: 'environment.resolveFlat',\n security: [{ BearerAuth: [] }],\n parameters: [{\n name: 'input',\n in: 'query',\n required: true,\n schema: { type: 'string' },\n example: '{\"environmentId\":\"<environmentId>\"}',\n description: 'JSON-encoded input: `{\"environmentId\":\"<environmentId>\"}`',\n }],\n responses: {\n '200': { description: 'Flat key-value map of resolved variables', content: { 'application/json': { schema: { type: 'object', properties: { result: { type: 'object', properties: { data: { type: 'object', additionalProperties: { type: 'string' } } } } } } } } },\n },\n },\n },\n },\n components: {\n securitySchemes: {\n BearerAuth: { type: 'http', scheme: 'bearer', description: 'JWT token from /api/unlock or /api/setup' },\n },\n schemas: {\n Service: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n name: { type: 'string' },\n agentId: { type: 'string' },\n commands: { type: 'array', items: { type: 'object' } },\n cwd: { type: 'string' },\n port: { type: 'integer' },\n description: { type: 'string' },\n url: { type: 'string' },\n runner: { type: 'string', enum: ['native', 'docker'] },\n },\n },\n Process: {\n type: 'object',\n properties: {\n id: { type: 'string' },\n agentId: { type: 'string' },\n state: { type: 'string', enum: ['stopped', 'starting', 'running', 'stopping', 'errored'] },\n pid: { type: 'integer', nullable: true },\n exitCode: { type: 'integer', nullable: true },\n },\n },\n },\n },\n };\n}\n","import { imageStorageService } from './image-storage.service.js';\n\nexport class ImageCleanupService {\n private timer: ReturnType<typeof setInterval> | null = null;\n\n async runCleanup(): Promise<{ deleted: number; errors: number }> {\n const expired = await imageStorageService.listExpiredImages();\n let deleted = 0;\n let errors = 0;\n await Promise.all(\n expired.map(async (img) => {\n try {\n await imageStorageService.deleteImage(img.imageId);\n deleted++;\n } catch {\n errors++;\n }\n }),\n );\n return { deleted, errors };\n }\n\n start(intervalMs = 60 * 60 * 1000): void {\n if (this.timer) return;\n this.runCleanup().catch((err) => console.error('[image-cleanup] error:', err));\n this.timer = setInterval(() => {\n this.runCleanup().catch((err) => console.error('[image-cleanup] error:', err));\n }, intervalMs);\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n\nexport const imageCleanupService = new ImageCleanupService();\n","import type { Server } from 'node:http';\nimport type { WebSocketServer } from 'ws';\nimport { env } from './config/env.js';\nimport { createLocalServer } from './create-server.js';\nimport { shutdownCodexAppServer } from './services/ai-runners/codex-runner.js';\nimport dotenv from 'dotenv'\ndotenv.config()\n\n// Re-export for CLI usage\nexport { createLocalServer } from './create-server.js';\nexport type { ServerInstance } from './create-server.js';\nexport { pullEnv, PullEnvError } from './commands/pull-env.js';\n\n/**\n * Listen with retry for EADDRINUSE — handles the race condition when the CLI\n * restarts the server before the old process has fully released the port.\n *\n * The `wss` parameter is needed because the `ws` library re-emits HTTP server\n * errors on the WebSocketServer — without a handler the error becomes unhandled.\n */\nfunction listenWithRetry(\n server: Server,\n port: number,\n host: string,\n wss?: WebSocketServer,\n maxRetries = 20,\n delay = 500,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n let attempts = 0;\n\n // Absorb EADDRINUSE errors re-emitted by the ws library on the WSS\n // during the retry window. Without this, Node.js crashes on unhandled error.\n const wssErrorHandler = () => { /* absorbed — handled via server 'error' */ };\n wss?.on('error', wssErrorHandler);\n\n const tryListen = () => {\n const onError = (err: NodeJS.ErrnoException) => {\n // Clean up the 'listening' callback that server.listen() registered\n server.removeAllListeners('listening');\n\n if (err.code === 'EADDRINUSE' && attempts < maxRetries) {\n attempts++;\n console.log(`[server] Port ${port} in use, retrying in ${delay}ms (${attempts}/${maxRetries})...`);\n setTimeout(tryListen, delay);\n } else {\n wss?.removeListener('error', wssErrorHandler);\n reject(err);\n }\n };\n\n server.once('error', onError);\n server.listen(port, host, () => {\n server.removeListener('error', onError);\n wss?.removeListener('error', wssErrorHandler);\n resolve();\n });\n };\n\n tryListen();\n });\n}\n\nasync function main() {\n console.log('Hello World 2');\n const { server, wss, shutdown } = await createLocalServer();\n\n await listenWithRetry(server, env.PORT, env.HOST, wss);\n console.log(`[server] Local server listening on ${env.HOST}:${env.PORT}`);\n console.log(`[server] tRPC HTTP: http://${env.HOST}:${env.PORT}/api/trpc`);\n console.log(`[server] tRPC WS: ws://${env.HOST}:${env.PORT}`); // nosemgrep:javascript.lang.security.detect-insecure-websocket.detect-insecure-websocket\n console.log(`[server] Mode: ${env.MODE}`);\n if (env.RUNEYA_LAN_PROXY) {\n console.log('[server] LAN mode: server exposed on local network (0.0.0.0)');\n console.log('[server] LAN mode: {{service.HOST}} resolves to 0.0.0.0 — configure your services accordingly');\n }\n\n let shuttingDown = false;\n const gracefulShutdown = async (signal: string) => {\n if (shuttingDown) {\n console.log(`[server] Forced exit (second ${signal})`);\n process.exit(1);\n }\n shuttingDown = true;\n console.log(`[server] Received ${signal}, shutting down gracefully...`);\n\n // In dev, exit immediately — ports are freed on process death,\n // and the 'exit' handler in agent-spawner SIGKILLs the agent.\n if (process.env.NODE_ENV === 'development') {\n process.exit(0);\n }\n\n await shutdownCodexAppServer();\n await shutdown();\n process.exit(0);\n };\n\n process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));\n process.on('SIGINT', () => gracefulShutdown('SIGINT'));\n}\n\n// Only run main if this file is executed directly (not imported)\nif (import.meta.url === `file://${process.argv[1]}`) {\n main().catch((err) => {\n console.error('[server] Fatal error:', err);\n process.exit(1);\n });\n}\n","import { serviceStore } from '../services/service-store.js';\nimport { environmentStore } from '../services/environment-store.js';\nimport { environmentResolver } from '../services/environment-resolver.js';\nimport { ensureEncryptionKey } from '../utils/encryption-key.js';\n\nexport class PullEnvError extends Error {\n constructor(\n message: string,\n public readonly exitCode: number,\n ) {\n super(message);\n this.name = 'PullEnvError';\n }\n}\n\n/**\n * Resolve env vars for a service+environment and return them as KEY=VALUE lines.\n * Throws PullEnvError if the service or environment is not found.\n */\nexport async function pullEnv(opts: { service: string; environment: string }): Promise<string> {\n await ensureEncryptionKey();\n\n const services = await serviceStore.list();\n const service = services.find(\n (s) => s.id === opts.service || s.name === opts.service,\n );\n if (!service) {\n throw new PullEnvError(`service \"${opts.service}\" not found`, 1);\n }\n\n const globalEnvs = await environmentStore.listAllGlobal();\n const globalEnv = globalEnvs.find(\n (e) => e.id === opts.environment || e.name === opts.environment,\n );\n if (!globalEnv) {\n throw new PullEnvError(`environment \"${opts.environment}\" not found`, 1);\n }\n\n const { env } = await environmentResolver.resolveForService({\n serviceId: service.id,\n activeEnvironmentId: globalEnv.id,\n });\n\n return Object.entries(env)\n .map(([key, value]) => `${key}=${value}`)\n .join('\\n');\n}\n"],"mappings":"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","names":["resolve","randomBytes","z","TRPCError","randomUUID","readFile","writeFile","rename","mkdir","chmod","join","stat","homedir","Anthropic","OpenAI","execFile","pty","dirname","unlink","readdir","sep","spawn","EventEmitter","createCipheriv","createDecipheriv","existsSync","token","FILENAME","env","ctx","SUBSCRIPTION_QUEUE_MAX","t","MONTHS","agentManager","getAgentManager","MAX_BUFFER","publish","buildSystemPrompt","result","appendFile","isSubtreeComplete","startedAt","encryptValue","ENCRYPTED_KEY_FILENAME","VERIFY_FILENAME"]}
|