@p4code/cli 0.1.21 → 0.1.23
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/bin.mjs +815 -65
- package/dist/client/assets/Diagram-CP713Hf0.js +3 -0
- package/dist/client/assets/DiffPanel-D0McnRVJ.js +98 -0
- package/dist/client/assets/FilePreviewPanel-CBdYEmtx.js +1778 -0
- package/dist/client/assets/PreviewPanel-F4V0X333.js +2 -0
- package/dist/client/assets/abnfDiagram-N423BO3Z-BYQKJNsP.js +2 -0
- package/dist/client/assets/angular-html-BVBpGdXr.js +2 -0
- package/dist/client/assets/{angular-ts-CxZFyQM4.js → angular-ts-BfdufMKP.js} +2 -2
- package/dist/client/assets/{apl-D8rOr4fH.js → apl-DWBSSoBH.js} +2 -2
- package/dist/client/assets/arc-BjSQqbzd.js +2 -0
- package/dist/client/assets/architecture-TIHT7OUA-DOwndo9a.js +1 -0
- package/dist/client/assets/architectureDiagram-T3A2C74G-Dkoxezw8.js +37 -0
- package/dist/client/assets/array-BifhSqXX.js +2 -0
- package/dist/client/assets/arrow-right-Fc_jCzG8.js +2 -0
- package/dist/client/assets/{astro-DYSYdOU9.js → astro-3LtMP0Sq.js} +2 -2
- package/dist/client/assets/{blade-DaHnYPa_.js → blade-llJRbbtR.js} +2 -2
- package/dist/client/assets/blockDiagram-VBNYF7ZC-sVeCAPAa.js +133 -0
- package/dist/client/assets/c-Wt1voDr2.js +2 -0
- package/dist/client/assets/c4Diagram-5PPSVZJV-CW_Wfxep.js +11 -0
- package/dist/client/assets/channel-Cc8SQh1U.js +2 -0
- package/dist/client/assets/chunk-2GRJ4B5K-ChihPphX.js +2 -0
- package/dist/client/assets/chunk-2Q5K7J3B-C1jixKkw.js +2 -0
- package/dist/client/assets/chunk-3NCLNEKW-lgePDcrq.js +2 -0
- package/dist/client/assets/chunk-4I5QYGJK-CYvb6li-.js +2 -0
- package/dist/client/assets/chunk-5RXB4S5H-BzE89W2t.js +232 -0
- package/dist/client/assets/chunk-5VM5RSS4-ZNzvKenW.js +16 -0
- package/dist/client/assets/chunk-6Q2QTUOP-CyDe-FPc.js +89 -0
- package/dist/client/assets/chunk-7BUUIJ7U-Bb538aSH.js +2 -0
- package/dist/client/assets/chunk-7Z6QIM7H-kaZRbPTV.js +11 -0
- package/dist/client/assets/chunk-GF5L2VYU-CHJWyX-t.js +207 -0
- package/dist/client/assets/chunk-I66GZJ75-CJWXi3bs.js +128 -0
- package/dist/client/assets/chunk-J7OUQ5F2-D19QWtqC.js +3 -0
- package/dist/client/assets/chunk-JQJVKLGR-oHxUxbQ4.js +157 -0
- package/dist/client/assets/chunk-JWPE2WC7-DVXcaiue.js +2 -0
- package/dist/client/assets/chunk-KBJHAD2P-D81b6htr.js +2 -0
- package/dist/client/assets/chunk-KEIR6QF5-BfrZ3jm6.js +162 -0
- package/dist/client/assets/chunk-NSK5VX7P-CoeZ_Lgi.js +3 -0
- package/dist/client/assets/chunk-QR6OTTB3-D0IyLhez.js +63 -0
- package/dist/client/assets/chunk-RYQCIY6F-CZ4ia6G4.js +2 -0
- package/dist/client/assets/chunk-UBXNYLIW-F4hmeeiG.js +2 -0
- package/dist/client/assets/chunk-W5SLKNZC-Bwmo9x3j.js +2 -0
- package/dist/client/assets/chunk-WRU74C26-C2Rb3ATV.js +71 -0
- package/dist/client/assets/chunk-XXDRQBXY-BuE3VzE_.js +2 -0
- package/dist/client/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +2 -0
- package/dist/client/assets/chunk-ZIRB5QZD-C6fEPe3t.js +33 -0
- package/dist/client/assets/classDiagram-JCYQIIEL-oYJOinll.js +2 -0
- package/dist/client/assets/classDiagram-v2-OCEON4UE-oYJOinll.js +2 -0
- package/dist/client/assets/{cobol-Djebq6RA.js → cobol-x_HIyl2P.js} +2 -2
- package/dist/client/assets/{coffee-CKhxS88r.js → coffee-CThvmt4R.js} +2 -2
- package/dist/client/assets/compiler-runtime-CLAvuQ-D.js +2 -0
- package/dist/client/assets/cose-bilkent-JH36ORCC-CU59zlcZ.js +2 -0
- package/dist/client/assets/cpp-NtAeskI3.js +2 -0
- package/dist/client/assets/{crystal-DXzIaEKx.js → crystal-DNu_sX0G.js} +2 -2
- package/dist/client/assets/css-DJp_X0uY.js +2 -0
- package/dist/client/assets/cynefin-VYW2F7L2-CjLioxN7.js +1 -0
- package/dist/client/assets/cynefinDiagram-MW4NZA55-DvNvdTNB.js +63 -0
- package/dist/client/assets/cytoscape.esm-B3I8pqwA.js +322 -0
- package/dist/client/assets/dagre-CXRCoUWR.js +2 -0
- package/dist/client/assets/dagre-VZM6K2ZE-bNpBL3bS.js +5 -0
- package/dist/client/assets/defaultLocale-C8Fc0cco.js +2 -0
- package/dist/client/assets/diagram-7IWD3JNH-DJveh2nY.js +31 -0
- package/dist/client/assets/diagram-B4RE2ZJO-CslhjucF.js +4 -0
- package/dist/client/assets/diagram-LBJQPF4R-DrVsyR2w.js +25 -0
- package/dist/client/assets/diagram-Q27KOJAE-Dp_H6G_V.js +25 -0
- package/dist/client/assets/diagram-UB23O5K3-ttWj4O6A.js +42 -0
- package/dist/client/assets/dist-D9sYb5Oa.js +2 -0
- package/dist/client/assets/ebnfDiagram-BXEA7PRR-DU7xTW-M.js +2 -0
- package/dist/client/assets/{edge-B3VgcX6t.js → edge-ozw5tpLl.js} +2 -2
- package/dist/client/assets/{elixir-DGUU7Wwf.js → elixir-VhA6FeZt.js} +2 -2
- package/dist/client/assets/{elm-B9tr8qBJ.js → elm-dREJmIFz.js} +2 -2
- package/dist/client/assets/erDiagram-JOGREHBK-J8OGMeJ9.js +86 -0
- package/dist/client/assets/{erb-BgSl2c_f.js → erb-CIg6G69l.js} +2 -2
- package/dist/client/assets/eventmodeling-45OFAUF4-bPdt--LC.js +1 -0
- package/dist/client/assets/fileCommentAnnotations-BvEFhUAB.js +2 -0
- package/dist/client/assets/flowDiagram-UKHOOZJN-Xh4ZxM-b.js +1 -0
- package/dist/client/assets/ganttDiagram-PKOTCBZU-CTzbq3xg.js +293 -0
- package/dist/client/assets/{git-rebase-CJMhrhmS.js → git-rebase-B44mJPta.js} +2 -2
- package/dist/client/assets/gitGraph-TEB2WS4Q-D4WztIzM.js +1 -0
- package/dist/client/assets/gitGraphDiagram-DS77QQ5N-BYWChpgP.js +107 -0
- package/dist/client/assets/{glimmer-js-Dzf5VMSx.js → glimmer-js-vH_gHG0-.js} +2 -2
- package/dist/client/assets/{glimmer-ts-CHD8gl5-.js → glimmer-ts--abOzSAQ.js} +2 -2
- package/dist/client/assets/glsl-Dv5r7kPw.js +2 -0
- package/dist/client/assets/graphlib-B8gBHxth.js +2 -0
- package/dist/client/assets/graphql-CB4jsw2E.js +2 -0
- package/dist/client/assets/{hack-NU-7p0gC.js → hack-DvEYX148.js} +2 -2
- package/dist/client/assets/haml-zE6W3STP.js +2 -0
- package/dist/client/assets/{handlebars-BOvzNDfr.js → handlebars-CzBR2SDs.js} +2 -2
- package/dist/client/assets/html-C8UlPnhE.js +2 -0
- package/dist/client/assets/{html-derivative-CcTOncd6.js → html-derivative-CY6NRz-J.js} +2 -2
- package/dist/client/assets/{http-CGr88I6S.js → http-Cyd7bS_S.js} +2 -2
- package/dist/client/assets/{hurl-BfdIF20D.js → hurl-CWPsiEpf.js} +2 -2
- package/dist/client/assets/index-DN4UQwOg.js +853 -0
- package/dist/client/assets/index-jIQiqqGn.css +1 -0
- package/dist/client/assets/info-DKCQHKI2-a_IxCZlD.js +1 -0
- package/dist/client/assets/infoDiagram-6WML65LV-CNHt7MRQ.js +3 -0
- package/dist/client/assets/init-D6jRqBbL.js +2 -0
- package/dist/client/assets/ishikawaDiagram-WSZJBQD7-GfzwW5bv.js +71 -0
- package/dist/client/assets/java-CGc3VwQr.js +2 -0
- package/dist/client/assets/javascript-CUt1pgmJ.js +2 -0
- package/dist/client/assets/{jinja-BP-z74Sl.js → jinja-CD-Z-FLd.js} +2 -2
- package/dist/client/assets/{jison-DTU_ib6_.js → jison-imPNup1l.js} +2 -2
- package/dist/client/assets/journeyDiagram-NVQOT4AX-BSwGpG7U.js +140 -0
- package/dist/client/assets/json-Bg9ijW3F.js +2 -0
- package/dist/client/assets/jsx-CY6oMTks.js +2 -0
- package/dist/client/assets/{julia-BFtTfktg.js → julia-Dc3O-irA.js} +2 -2
- package/dist/client/assets/{just-CBZfmiGm.js → just-BhOq_Kbv.js} +2 -2
- package/dist/client/assets/kanban-definition-27J2QSJJ-D_T9V6VW.js +90 -0
- package/dist/client/assets/katex-CddkPoXu.js +258 -0
- package/dist/client/assets/{latex-B9jcgQKp.js → latex-Cu4Y1d5w.js} +2 -2
- package/dist/client/assets/line-DSV8zekT.js +2 -0
- package/dist/client/assets/linear-B7l8qgEw.js +2 -0
- package/dist/client/assets/{liquid-D-PCb97a.js → liquid-CvXMrjlQ.js} +2 -2
- package/dist/client/assets/lua-BjLEUjKY.js +2 -0
- package/dist/client/assets/map-DsCK-0Cs.js +2 -0
- package/dist/client/assets/{marko-D2oCpzm8.js → marko-DvhNOisQ.js} +2 -2
- package/dist/client/assets/{mdc-BN4ff7dr.js → mdc-Bm9TpL1X.js} +2 -2
- package/dist/client/assets/mdx-host-BSmJn2Ra.css +1 -0
- package/dist/client/assets/mdx-host-ykYobBl4.js +4 -0
- package/dist/client/assets/mermaid-parser.core-B5tsyPlM.js +8 -0
- package/dist/client/assets/mermaid.core-0eNWrEyK.js +12 -0
- package/dist/client/assets/mindmap-definition-FAOFIHXS-CCatf1G5.js +97 -0
- package/dist/client/assets/{nginx-TigpgX3q.js → nginx-Bhc82uuv.js} +2 -2
- package/dist/client/assets/{nim-BbkIxZP5.js → nim-DXTVBFnF.js} +2 -2
- package/dist/client/assets/ordinal-hYBb2elL.js +2 -0
- package/dist/client/assets/packet-7NZHBO7P-TVG5WLAg.js +1 -0
- package/dist/client/assets/path-BWPyau1x.js +2 -0
- package/dist/client/assets/pegDiagram-VL7TDLO6-cVET6VY2.js +2 -0
- package/dist/client/assets/{perl-Dq3UNlmA.js → perl-C7veXV9z.js} +2 -2
- package/dist/client/assets/{php-CDBbIDUr.js → php-BRiuMnnr.js} +2 -2
- package/dist/client/assets/pie-RZYD4A2V-_HnCx0-n.js +1 -0
- package/dist/client/assets/pieDiagram-7S7Q4E2Y-my4weM7I.js +40 -0
- package/dist/client/assets/preload-helper-CEhsl8MR.js +10 -0
- package/dist/client/assets/{pug-X1om8_0C.js → pug-C5hz5LQ7.js} +2 -2
- package/dist/client/assets/{qml-C_aweCjl.js → qml-BdUV3aTS.js} +2 -2
- package/dist/client/assets/quadrantDiagram-CIZ2JOQS-DbbX4CCn.js +8 -0
- package/dist/client/assets/r-8R7vtdQc.js +2 -0
- package/dist/client/assets/radar-I7S5WNFK-CxNqBWNL.js +1 -0
- package/dist/client/assets/railroad-3IZDKUUU-x01a2S92.js +1 -0
- package/dist/client/assets/railroad-abnf-AHOZXSZD-CMSmMh88.js +1 -0
- package/dist/client/assets/railroad-ebnf-EBAXGLYW-BtYYxacN.js +1 -0
- package/dist/client/assets/railroad-peg-LSFZ7HO6-BlXAsNZI.js +1 -0
- package/dist/client/assets/railroadDiagram-AXF67PYL-CA2XP-eT.js +2 -0
- package/dist/client/assets/{razor-DFd9duVt.js → razor-DRL52XO2.js} +2 -2
- package/dist/client/assets/regexp-Omp9DhTb.js +2 -0
- package/dist/client/assets/requirementDiagram-LRYGKXZP-DPky6FEM.js +85 -0
- package/dist/client/assets/rolldown-runtime-QTnfLwEv.js +1 -0
- package/dist/client/assets/rough.esm-CSKSodPl.js +2 -0
- package/dist/client/assets/{rst-DS4ajG1_.js → rst-BHX71KW9.js} +2 -2
- package/dist/client/assets/{ruby-rrP3E-yX.js → ruby-B--HzjGU.js} +2 -2
- package/dist/client/assets/sankeyDiagram-W5VNT64P-Im_lfZl5.js +41 -0
- package/dist/client/assets/{sas-qOp3AbMp.js → sas-DrLaYOK_.js} +2 -2
- package/dist/client/assets/scss-DdSxiZKl.js +2 -0
- package/dist/client/assets/sequenceDiagram-SI44F4Z6-DaepaQXs.js +163 -0
- package/dist/client/assets/shellscript-DwcUjJBL.js +2 -0
- package/dist/client/assets/{shellsession-DS-qEJoT.js → shellsession-CPZkydE6.js} +2 -2
- package/dist/client/assets/sizeCapture-X5ZJPWSS-B0uUizjq.js +2 -0
- package/dist/client/assets/{soy-CT_pCK5o.js → soy-Br5FhD7c.js} +2 -2
- package/dist/client/assets/sql-DNssxck8.js +2 -0
- package/dist/client/assets/src-_wZywoZs.js +2 -0
- package/dist/client/assets/{stata-B2fKxQHN.js → stata-DXn1tqOr.js} +2 -2
- package/dist/client/assets/stateDiagram-OKZ733FA-CfYrJbpr.js +2 -0
- package/dist/client/assets/stateDiagram-v2-UEYNNEHI-Dj9TN_Qe.js +2 -0
- package/dist/client/assets/{surrealql-BOcosx9e.js → surrealql-IeLNQw0f.js} +2 -2
- package/dist/client/assets/{svelte-BQBQ3ysY.js → svelte-DOdLCIlh.js} +2 -2
- package/dist/client/assets/swimlanes-SLNWSIFB-DaoN2lsp.js +3 -0
- package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-BKWIjosV.js +9 -0
- package/dist/client/assets/{templ-cinsfbYE.js → templ-CIwIngms.js} +2 -2
- package/dist/client/assets/terminal-links-B96vwInV.js +46 -0
- package/dist/client/assets/{tex-PiJ0CI8J.js → tex-D8QMumu5.js} +2 -2
- package/dist/client/assets/timeline-definition-Z64GVDOM-I6R4kaBM.js +121 -0
- package/dist/client/assets/treeView-QDETBFTQ-FHUGB9GE.js +1 -0
- package/dist/client/assets/treemap-6X3UGDF4-C2oSUZ4V.js +1 -0
- package/dist/client/assets/{ts-tags-jRjqE2jk.js → ts-tags-BMVY4q-l.js} +2 -2
- package/dist/client/assets/tsx-5Eka4NBX.js +2 -0
- package/dist/client/assets/{twig-5U1Vd9zl.js → twig-C8o_5mgw.js} +2 -2
- package/dist/client/assets/typescript-DOu2WMV5.js +2 -0
- package/dist/client/assets/vennDiagram-T6HMQDX7-uVbqilLL.js +35 -0
- package/dist/client/assets/{vue-BOE7yHne.js → vue-BU18DNDL.js} +2 -2
- package/dist/client/assets/{vue-html-roHe5KnN.js → vue-html-BeluIYX0.js} +2 -2
- package/dist/client/assets/{vue-vine-YC-R0SEx.js → vue-vine-DGUAbOCX.js} +2 -2
- package/dist/client/assets/wardley-OPB4EBWU-C8z79vwT.js +1 -0
- package/dist/client/assets/wardleyDiagram-T6FBY63Y-Bh4kXS4j.js +79 -0
- package/dist/client/assets/xml-DIqSwXR3.js +2 -0
- package/dist/client/assets/{xsl-CyPKxPW7.js → xsl-Ct_-YIAy.js} +2 -2
- package/dist/client/assets/xychartDiagram-ELKLHX3M-aKLyYtge.js +8 -0
- package/dist/client/assets/yaml-DTtCYNlS.js +2 -0
- package/dist/client/index.html +6 -3
- package/dist/client/mdx-host.html +25 -0
- package/dist/client/mdx-jsx-runtime.js +23 -0
- package/package.json +4 -1
- package/dist/client/assets/DiffPanel-2Gqo7b0N.js +0 -98
- package/dist/client/assets/FilePreviewPanel-Po3D7bHa.js +0 -1778
- package/dist/client/assets/PreviewPanel-ebSBxbsf.js +0 -2
- package/dist/client/assets/angular-html-BhHAxMde.js +0 -2
- package/dist/client/assets/arrow-right-Dseaz2v4.js +0 -2
- package/dist/client/assets/c-oRWOBveW.js +0 -2
- package/dist/client/assets/cpp-BjVgWq1h.js +0 -2
- package/dist/client/assets/css-7AulbBAq.js +0 -2
- package/dist/client/assets/fileCommentAnnotations-C06ZwrTh.js +0 -2
- package/dist/client/assets/glsl-CDpKClnF.js +0 -2
- package/dist/client/assets/graphql-DX6Ul3G5.js +0 -2
- package/dist/client/assets/haml-Cf7Y-ZgP.js +0 -2
- package/dist/client/assets/html-CokKN6Uo.js +0 -2
- package/dist/client/assets/index-BwGqPoA8.js +0 -847
- package/dist/client/assets/index-eSuLivhH.css +0 -1
- package/dist/client/assets/java-DjcrYPKU.js +0 -2
- package/dist/client/assets/javascript-C1msiELJ.js +0 -2
- package/dist/client/assets/json-n2oR8huX.js +0 -2
- package/dist/client/assets/jsx-DLc8ZGPF.js +0 -2
- package/dist/client/assets/lua-CeAbwjz7.js +0 -2
- package/dist/client/assets/r-BH02pZo7.js +0 -2
- package/dist/client/assets/regexp-BYgWQcZZ.js +0 -2
- package/dist/client/assets/scss-BePdknOf.js +0 -2
- package/dist/client/assets/shellscript-Di7DOIUv.js +0 -2
- package/dist/client/assets/sql-CVynNG6j.js +0 -2
- package/dist/client/assets/textarea-DV6gvhvo.js +0 -46
- package/dist/client/assets/tsx-DqzTbomV.js +0 -2
- package/dist/client/assets/typescript-DmYNCX8k.js +0 -2
- package/dist/client/assets/xml-B-QQaugn.js +0 -2
- package/dist/client/assets/yaml-Bq2pe1E4.js +0 -2
package/dist/bin.mjs
CHANGED
|
@@ -77,6 +77,10 @@ import * as HttpClientResponse$1 from "effect/unstable/http/HttpClientResponse";
|
|
|
77
77
|
import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder";
|
|
78
78
|
import * as Tracer from "effect/Tracer";
|
|
79
79
|
import "effect/unstable/observability";
|
|
80
|
+
import * as NodeFSP from "node:fs/promises";
|
|
81
|
+
import { compile } from "@mdx-js/mdx";
|
|
82
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
83
|
+
import remarkGfm from "remark-gfm";
|
|
80
84
|
import * as Cookies from "effect/unstable/http/Cookies";
|
|
81
85
|
import * as HttpEffect from "effect/unstable/http/HttpEffect";
|
|
82
86
|
import { RpcSerialization, RpcServer } from "effect/unstable/rpc";
|
|
@@ -86,7 +90,6 @@ import * as TxQueue from "effect/TxQueue";
|
|
|
86
90
|
import * as TxRef from "effect/TxRef";
|
|
87
91
|
import * as Fiber from "effect/Fiber";
|
|
88
92
|
import * as SynchronizedRef from "effect/SynchronizedRef";
|
|
89
|
-
import * as NodeFSP from "node:fs/promises";
|
|
90
93
|
import * as RcMap from "effect/RcMap";
|
|
91
94
|
import { FileFinder } from "@ff-labs/fff-node";
|
|
92
95
|
import * as LayerMap from "effect/LayerMap";
|
|
@@ -233,7 +236,7 @@ const make$76 = () => {
|
|
|
233
236
|
const layer$72 = Layer.sync(NetService, make$76);
|
|
234
237
|
//#endregion
|
|
235
238
|
//#region package.json
|
|
236
|
-
var version = "0.1.
|
|
239
|
+
var version = "0.1.23";
|
|
237
240
|
//#endregion
|
|
238
241
|
//#region src/config.ts
|
|
239
242
|
/**
|
|
@@ -261,6 +264,7 @@ const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
|
|
|
261
264
|
const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
|
|
262
265
|
const dbPath = join(stateDir, "state.sqlite");
|
|
263
266
|
const attachmentsDir = join(stateDir, "attachments");
|
|
267
|
+
const mdxBuildsDir = join(stateDir, "mdx-builds");
|
|
264
268
|
const logsDir = join(stateDir, "logs");
|
|
265
269
|
const providerLogsDir = join(logsDir, "provider");
|
|
266
270
|
const providerStatusCacheDir = join(baseDir, "caches");
|
|
@@ -272,6 +276,7 @@ const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
|
|
|
272
276
|
providerStatusCacheDir,
|
|
273
277
|
worktreesDir: join(baseDir, "worktrees"),
|
|
274
278
|
attachmentsDir,
|
|
279
|
+
mdxBuildsDir,
|
|
275
280
|
logsDir,
|
|
276
281
|
serverLogPath: join(logsDir, "server.log"),
|
|
277
282
|
serverTracePath: join(logsDir, "server.trace.ndjson"),
|
|
@@ -293,6 +298,7 @@ const ensureServerDirectories = Effect.fn(function* (derivedPaths) {
|
|
|
293
298
|
fs.makeDirectory(derivedPaths.providerLogsDir, { recursive: true }),
|
|
294
299
|
fs.makeDirectory(derivedPaths.terminalLogsDir, { recursive: true }),
|
|
295
300
|
fs.makeDirectory(derivedPaths.attachmentsDir, { recursive: true }),
|
|
301
|
+
fs.makeDirectory(derivedPaths.mdxBuildsDir, { recursive: true }),
|
|
296
302
|
fs.makeDirectory(derivedPaths.worktreesDir, { recursive: true }),
|
|
297
303
|
fs.makeDirectory(path.dirname(derivedPaths.keybindingsConfigPath), { recursive: true }),
|
|
298
304
|
fs.makeDirectory(path.dirname(derivedPaths.settingsPath), { recursive: true }),
|
|
@@ -7773,13 +7779,18 @@ const ProjectReadFileResult = Schema$1.Struct({
|
|
|
7773
7779
|
relativePath: TrimmedNonEmptyString,
|
|
7774
7780
|
contents: Schema$1.String,
|
|
7775
7781
|
byteLength: NonNegativeInt,
|
|
7776
|
-
truncated: Schema$1.Boolean
|
|
7782
|
+
truncated: Schema$1.Boolean,
|
|
7783
|
+
/**
|
|
7784
|
+
* The file is not UTF-8 text, so `contents` is empty and only the metadata
|
|
7785
|
+
* is meaningful. Reported rather than raised because a `.docx` in a preview
|
|
7786
|
+
* panel is an ordinary file to describe, not a failed read to apologise for.
|
|
7787
|
+
*/
|
|
7788
|
+
binary: Schema$1.Boolean
|
|
7777
7789
|
});
|
|
7778
7790
|
const ProjectFileFailure = Schema$1.Literals([
|
|
7779
7791
|
"workspace_path_outside_root",
|
|
7780
7792
|
"resolved_path_outside_root",
|
|
7781
7793
|
"path_not_file",
|
|
7782
|
-
"binary_file",
|
|
7783
7794
|
"operation_failed"
|
|
7784
7795
|
]);
|
|
7785
7796
|
const ProjectFileOperation = Schema$1.Literals([
|
|
@@ -7858,11 +7869,21 @@ var ProjectWriteFileError = class extends Schema$1.TaggedErrorClass()("ProjectWr
|
|
|
7858
7869
|
* is a URL as often as an id, and which tracker a bare `MOBILE-12262` belongs
|
|
7859
7870
|
* to is a question only the resolver can answer.
|
|
7860
7871
|
*/
|
|
7861
|
-
const TicketResolveInput = Schema$1.Struct({ reference: TrimmedNonEmptyString });
|
|
7872
|
+
const TicketResolveInput = Schema$1.Struct({ reference: TrimmedNonEmptyString.pipe(Schema$1.annotateEncoded({ description: "The ticket as it was written: an identifier like MOBILE-12241, or a tracker URL. Pass it through verbatim rather than reformatting it." })) });
|
|
7862
7873
|
const TicketResolveResult = Schema$1.Struct({
|
|
7863
7874
|
externalRef: TaskExternalRef,
|
|
7864
7875
|
/** The issue title as the tracker reports it, for the task that mirrors it. */
|
|
7865
|
-
title: TrimmedNonEmptyString
|
|
7876
|
+
title: TrimmedNonEmptyString,
|
|
7877
|
+
/**
|
|
7878
|
+
* The issue body, when the tracker reports one.
|
|
7879
|
+
*
|
|
7880
|
+
* Optional because it is the one field here that has a legitimate empty
|
|
7881
|
+
* value - plenty of tickets are a title and nothing else - and because the
|
|
7882
|
+
* composer, which only ever renders a chip, does not read it. It is carried
|
|
7883
|
+
* for the caller that does: an agent handed a ticket id needs the
|
|
7884
|
+
* requirements, and the title alone sends it back to ask for them.
|
|
7885
|
+
*/
|
|
7886
|
+
description: Schema$1.optional(TrimmedNonEmptyString)
|
|
7866
7887
|
});
|
|
7867
7888
|
/**
|
|
7868
7889
|
* Why a reference could not be turned into a ticket.
|
|
@@ -8903,6 +8924,8 @@ const AssetResource = Schema$1.Union([
|
|
|
8903
8924
|
threadId: ThreadId,
|
|
8904
8925
|
path: TrimmedNonEmptyString.check(Schema$1.isMaxLength(ASSET_PATH_MAX_LENGTH))
|
|
8905
8926
|
}),
|
|
8927
|
+
Schema$1.TaggedStruct("local-file", { path: TrimmedNonEmptyString.check(Schema$1.isMaxLength(ASSET_PATH_MAX_LENGTH)) }),
|
|
8928
|
+
Schema$1.TaggedStruct("mdx-preview", { path: TrimmedNonEmptyString.check(Schema$1.isMaxLength(ASSET_PATH_MAX_LENGTH)) }),
|
|
8906
8929
|
Schema$1.TaggedStruct("attachment", { attachmentId: TrimmedNonEmptyString.check(Schema$1.isMaxLength(256)) }),
|
|
8907
8930
|
Schema$1.TaggedStruct("project-favicon", { cwd: TrimmedNonEmptyString.check(Schema$1.isMaxLength(ASSET_PATH_MAX_LENGTH)) })
|
|
8908
8931
|
]);
|
|
@@ -8992,6 +9015,32 @@ var AssetProjectFaviconNotFoundError = class extends Schema$1.TaggedErrorClass()
|
|
|
8992
9015
|
return "Project favicon was not found.";
|
|
8993
9016
|
}
|
|
8994
9017
|
};
|
|
9018
|
+
var AssetLocalFileNotFoundError = class extends Schema$1.TaggedErrorClass()("AssetLocalFileNotFoundError", { resource: AssetResource }) {
|
|
9019
|
+
get message() {
|
|
9020
|
+
return "Local file was not found.";
|
|
9021
|
+
}
|
|
9022
|
+
};
|
|
9023
|
+
var AssetLocalFileInspectionError = class extends Schema$1.TaggedErrorClass()("AssetLocalFileInspectionError", {
|
|
9024
|
+
resource: AssetResource,
|
|
9025
|
+
cause: Schema$1.Defect()
|
|
9026
|
+
}) {
|
|
9027
|
+
get message() {
|
|
9028
|
+
return "Failed to inspect the local file.";
|
|
9029
|
+
}
|
|
9030
|
+
};
|
|
9031
|
+
var AssetLocalPathValidationError = class extends Schema$1.TaggedErrorClass()("AssetLocalPathValidationError", { resource: AssetResource }) {
|
|
9032
|
+
get message() {
|
|
9033
|
+
return "Local file path must be absolute.";
|
|
9034
|
+
}
|
|
9035
|
+
};
|
|
9036
|
+
var AssetMdxBuildError = class extends Schema$1.TaggedErrorClass()("AssetMdxBuildError", {
|
|
9037
|
+
resource: AssetResource,
|
|
9038
|
+
cause: Schema$1.Defect()
|
|
9039
|
+
}) {
|
|
9040
|
+
get message() {
|
|
9041
|
+
return "Failed to prepare the MDX preview build.";
|
|
9042
|
+
}
|
|
9043
|
+
};
|
|
8995
9044
|
var AssetSigningKeyLoadError = class extends Schema$1.TaggedErrorClass()("AssetSigningKeyLoadError", {
|
|
8996
9045
|
resource: AssetResource,
|
|
8997
9046
|
cause: Schema$1.Defect()
|
|
@@ -9013,6 +9062,10 @@ const AssetAccessError = Schema$1.Union([
|
|
|
9013
9062
|
AssetProjectFaviconResolutionError,
|
|
9014
9063
|
AssetProjectFaviconInspectionError,
|
|
9015
9064
|
AssetProjectFaviconNotFoundError,
|
|
9065
|
+
AssetLocalFileNotFoundError,
|
|
9066
|
+
AssetLocalFileInspectionError,
|
|
9067
|
+
AssetLocalPathValidationError,
|
|
9068
|
+
AssetMdxBuildError,
|
|
9016
9069
|
AssetSigningKeyLoadError
|
|
9017
9070
|
]);
|
|
9018
9071
|
//#endregion
|
|
@@ -16097,7 +16150,7 @@ function buildSkillOverrides(disabled, discovered) {
|
|
|
16097
16150
|
*
|
|
16098
16151
|
* @module provider/Drivers/ClaudeSkills
|
|
16099
16152
|
*/
|
|
16100
|
-
const FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
|
|
16153
|
+
const FRONTMATTER_PATTERN$1 = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
|
|
16101
16154
|
/**
|
|
16102
16155
|
* The `name`/`description` header a skill and a subagent definition both carry.
|
|
16103
16156
|
*
|
|
@@ -16107,7 +16160,7 @@ const FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
|
|
|
16107
16160
|
* one question both callers are asking.
|
|
16108
16161
|
*/
|
|
16109
16162
|
function parseMarkdownFrontmatter(contents) {
|
|
16110
|
-
const match = FRONTMATTER_PATTERN.exec(contents);
|
|
16163
|
+
const match = FRONTMATTER_PATTERN$1.exec(contents);
|
|
16111
16164
|
if (!match) return { kind: "missing" };
|
|
16112
16165
|
let parsed;
|
|
16113
16166
|
try {
|
|
@@ -30494,6 +30547,374 @@ function isWorkspacePreviewEntryPath(path) {
|
|
|
30494
30547
|
return isWorkspaceBrowserPreviewPath(path) || isWorkspaceImagePreviewPath(path);
|
|
30495
30548
|
}
|
|
30496
30549
|
//#endregion
|
|
30550
|
+
//#region src/assets/mdxCompile.ts
|
|
30551
|
+
/**
|
|
30552
|
+
* Pure MDX compilation for the preview renderer.
|
|
30553
|
+
*
|
|
30554
|
+
* Compilation only: nothing here touches the filesystem, resolves a module, or
|
|
30555
|
+
* runs a bundler. The output is a single ES module that imports only the host
|
|
30556
|
+
* page's runtime shim, so the build directory it lands in never needs a
|
|
30557
|
+
* `node_modules` beside it.
|
|
30558
|
+
*
|
|
30559
|
+
* @module mdxCompile
|
|
30560
|
+
*/
|
|
30561
|
+
/**
|
|
30562
|
+
* Stable, unhashed module the host page publishes its React JSX runtime and
|
|
30563
|
+
* component provider on. Compiled documents are cached across app versions, so
|
|
30564
|
+
* this specifier must not carry a build hash.
|
|
30565
|
+
*/
|
|
30566
|
+
const MDX_RUNTIME_SPECIFIER = "/mdx-jsx-runtime.js";
|
|
30567
|
+
/**
|
|
30568
|
+
* Scheme the compiler rewrites relative asset references to.
|
|
30569
|
+
*
|
|
30570
|
+
* The compiled module is served from the build directory, so `./diagram.png`
|
|
30571
|
+
* would resolve against the wrong origin path. Rather than copying referenced
|
|
30572
|
+
* files into the build directory, the reference is rewritten to a marker the
|
|
30573
|
+
* host page resolves against the source-directory grant carried by the same
|
|
30574
|
+
* asset token. Cached builds therefore stay valid when the token rotates.
|
|
30575
|
+
*/
|
|
30576
|
+
const MDX_ASSET_SCHEME = "p4-asset:";
|
|
30577
|
+
const FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/;
|
|
30578
|
+
const EMPTY_FRONTMATTER = {
|
|
30579
|
+
title: null,
|
|
30580
|
+
created: null,
|
|
30581
|
+
status: null,
|
|
30582
|
+
rest: {}
|
|
30583
|
+
};
|
|
30584
|
+
function scalarToString(value) {
|
|
30585
|
+
if (typeof value === "string") return value;
|
|
30586
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
30587
|
+
if (value instanceof Date) return value.toISOString().slice(0, 10);
|
|
30588
|
+
return null;
|
|
30589
|
+
}
|
|
30590
|
+
/**
|
|
30591
|
+
* Read the leading YAML block.
|
|
30592
|
+
*
|
|
30593
|
+
* Parsed here rather than through a remark plugin because the renderer needs
|
|
30594
|
+
* the values as data for the document header, while remark-frontmatter's job
|
|
30595
|
+
* is only to keep the block from reaching the body as literal text.
|
|
30596
|
+
*/
|
|
30597
|
+
function parseMdxFrontmatter(source) {
|
|
30598
|
+
const match = FRONTMATTER_PATTERN.exec(source);
|
|
30599
|
+
if (!match?.[1]) return EMPTY_FRONTMATTER;
|
|
30600
|
+
let parsed;
|
|
30601
|
+
try {
|
|
30602
|
+
parsed = parse(match[1]);
|
|
30603
|
+
} catch {
|
|
30604
|
+
return EMPTY_FRONTMATTER;
|
|
30605
|
+
}
|
|
30606
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return EMPTY_FRONTMATTER;
|
|
30607
|
+
const entries = Object.entries(parsed);
|
|
30608
|
+
const rest = {};
|
|
30609
|
+
for (const [key, value] of entries) {
|
|
30610
|
+
if (key === "title" || key === "created" || key === "status") continue;
|
|
30611
|
+
const scalar = scalarToString(value);
|
|
30612
|
+
if (scalar !== null) rest[key] = scalar;
|
|
30613
|
+
}
|
|
30614
|
+
return {
|
|
30615
|
+
title: scalarToString(parsed.title),
|
|
30616
|
+
created: scalarToString(parsed.created),
|
|
30617
|
+
status: scalarToString(parsed.status),
|
|
30618
|
+
rest
|
|
30619
|
+
};
|
|
30620
|
+
}
|
|
30621
|
+
function isRewritableAssetUrl(url) {
|
|
30622
|
+
if (url.length === 0) return false;
|
|
30623
|
+
if (url.startsWith("#") || url.startsWith("/")) return false;
|
|
30624
|
+
if (url.startsWith("data:") || url.startsWith("p4-asset:")) return false;
|
|
30625
|
+
return !/^[A-Za-z][A-Za-z\d+.-]*:/.test(url);
|
|
30626
|
+
}
|
|
30627
|
+
function walk(node, visit) {
|
|
30628
|
+
const stack = [{
|
|
30629
|
+
node,
|
|
30630
|
+
parent: null
|
|
30631
|
+
}];
|
|
30632
|
+
while (stack.length > 0) {
|
|
30633
|
+
const current = stack.pop();
|
|
30634
|
+
if (!current) break;
|
|
30635
|
+
if (!visit(current.node, current.parent)) continue;
|
|
30636
|
+
for (const child of current.node.children ?? []) stack.push({
|
|
30637
|
+
node: child,
|
|
30638
|
+
parent: current.node
|
|
30639
|
+
});
|
|
30640
|
+
}
|
|
30641
|
+
}
|
|
30642
|
+
/**
|
|
30643
|
+
* Drop `import`/`export` statements before compilation.
|
|
30644
|
+
*
|
|
30645
|
+
* Dropping rather than rejecting is deliberate: authored plans never contain
|
|
30646
|
+
* imports, third-party `.mdx` found on disk usually does, and a dropped import
|
|
30647
|
+
* is never resolved or executed either way. The component that would have come
|
|
30648
|
+
* from the import is then undefined, which the host page's fallback renders as
|
|
30649
|
+
* a labeled placeholder instead of blanking the document.
|
|
30650
|
+
*/
|
|
30651
|
+
function remarkDropEsm(state) {
|
|
30652
|
+
return (tree) => {
|
|
30653
|
+
walk(tree, (node) => {
|
|
30654
|
+
if (!node.children) return true;
|
|
30655
|
+
const kept = node.children.filter((child) => child.type !== "mdxjsEsm");
|
|
30656
|
+
if (kept.length !== node.children.length) {
|
|
30657
|
+
state.droppedImports = true;
|
|
30658
|
+
node.children = kept;
|
|
30659
|
+
}
|
|
30660
|
+
return true;
|
|
30661
|
+
});
|
|
30662
|
+
};
|
|
30663
|
+
}
|
|
30664
|
+
/**
|
|
30665
|
+
* Collect every capitalised element the document renders.
|
|
30666
|
+
*
|
|
30667
|
+
* MDX resolves components through `{...provideComponents(), ...props.components}`,
|
|
30668
|
+
* a plain object, and throws `Expected component X to be defined` for a name
|
|
30669
|
+
* neither supplies — which would blank the whole document over one unresolved
|
|
30670
|
+
* tag. A proxy cannot help, because the spread copies own keys only. Naming
|
|
30671
|
+
* the components at compile time lets the host page put a real placeholder in
|
|
30672
|
+
* the map for each one it does not provide.
|
|
30673
|
+
*/
|
|
30674
|
+
function remarkCollectComponentNames(state) {
|
|
30675
|
+
return (tree) => {
|
|
30676
|
+
walk(tree, (node) => {
|
|
30677
|
+
if (node.type !== "mdxJsxFlowElement" && node.type !== "mdxJsxTextElement") return true;
|
|
30678
|
+
const name = node.name;
|
|
30679
|
+
if (typeof name !== "string" || name.length === 0) return true;
|
|
30680
|
+
const base = name.split(".")[0] ?? name;
|
|
30681
|
+
if (base[0] === base[0]?.toUpperCase()) state.names.add(base);
|
|
30682
|
+
return true;
|
|
30683
|
+
});
|
|
30684
|
+
};
|
|
30685
|
+
}
|
|
30686
|
+
/** Rewrite relative image references to the host page's asset marker. */
|
|
30687
|
+
function remarkRewriteRelativeAssets() {
|
|
30688
|
+
return (tree) => {
|
|
30689
|
+
walk(tree, (node) => {
|
|
30690
|
+
if (node.type === "image" && typeof node.url === "string" && isRewritableAssetUrl(node.url)) {
|
|
30691
|
+
node.url = `${MDX_ASSET_SCHEME}${node.url}`;
|
|
30692
|
+
return true;
|
|
30693
|
+
}
|
|
30694
|
+
if (node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") for (const attribute of node.attributes ?? []) {
|
|
30695
|
+
if (attribute.type !== "mdxJsxAttribute") continue;
|
|
30696
|
+
if (attribute.name !== "src" && attribute.name !== "poster") continue;
|
|
30697
|
+
if (typeof attribute.value !== "string" || !isRewritableAssetUrl(attribute.value)) continue;
|
|
30698
|
+
attribute.value = `${MDX_ASSET_SCHEME}${attribute.value}`;
|
|
30699
|
+
}
|
|
30700
|
+
return true;
|
|
30701
|
+
});
|
|
30702
|
+
};
|
|
30703
|
+
}
|
|
30704
|
+
/**
|
|
30705
|
+
* Point every surviving import at the host page's runtime shim.
|
|
30706
|
+
*
|
|
30707
|
+
* After the author's statements are dropped, the only imports left are the
|
|
30708
|
+
* ones MDX itself emits (the JSX runtime and the component provider). Both are
|
|
30709
|
+
* satisfied by one unhashed module, which is what lets the compiled output be
|
|
30710
|
+
* cached independently of the app build.
|
|
30711
|
+
*/
|
|
30712
|
+
function recmaPinRuntimeImports() {
|
|
30713
|
+
return (tree) => {
|
|
30714
|
+
for (const statement of tree.body) {
|
|
30715
|
+
if (statement.type !== "ImportDeclaration" || !statement.source) continue;
|
|
30716
|
+
statement.source.value = MDX_RUNTIME_SPECIFIER;
|
|
30717
|
+
statement.source.raw = JSON.stringify(MDX_RUNTIME_SPECIFIER);
|
|
30718
|
+
}
|
|
30719
|
+
};
|
|
30720
|
+
}
|
|
30721
|
+
function errorPosition(error) {
|
|
30722
|
+
const place = error?.place;
|
|
30723
|
+
const point = place?.start ?? place;
|
|
30724
|
+
const line = point?.line ?? error.line;
|
|
30725
|
+
const column = point?.column ?? error.column;
|
|
30726
|
+
return {
|
|
30727
|
+
line: typeof line === "number" ? line : null,
|
|
30728
|
+
column: typeof column === "number" ? column : null
|
|
30729
|
+
};
|
|
30730
|
+
}
|
|
30731
|
+
/** Compile MDX source into a single self-contained ES module. */
|
|
30732
|
+
async function compileMdxDocument(source) {
|
|
30733
|
+
const frontmatter = parseMdxFrontmatter(source);
|
|
30734
|
+
const state = { droppedImports: false };
|
|
30735
|
+
const collected = { names: /* @__PURE__ */ new Set() };
|
|
30736
|
+
try {
|
|
30737
|
+
const compiled = await compile(source, {
|
|
30738
|
+
development: false,
|
|
30739
|
+
jsx: false,
|
|
30740
|
+
outputFormat: "program",
|
|
30741
|
+
providerImportSource: MDX_RUNTIME_SPECIFIER,
|
|
30742
|
+
remarkPlugins: [
|
|
30743
|
+
remarkFrontmatter,
|
|
30744
|
+
remarkGfm,
|
|
30745
|
+
() => remarkDropEsm(state),
|
|
30746
|
+
() => remarkCollectComponentNames(collected),
|
|
30747
|
+
remarkRewriteRelativeAssets
|
|
30748
|
+
],
|
|
30749
|
+
recmaPlugins: [recmaPinRuntimeImports]
|
|
30750
|
+
});
|
|
30751
|
+
return {
|
|
30752
|
+
ok: true,
|
|
30753
|
+
code: String(compiled),
|
|
30754
|
+
droppedImports: state.droppedImports,
|
|
30755
|
+
componentNames: [...collected.names],
|
|
30756
|
+
frontmatter
|
|
30757
|
+
};
|
|
30758
|
+
} catch (cause) {
|
|
30759
|
+
const { line, column } = errorPosition(cause);
|
|
30760
|
+
return {
|
|
30761
|
+
ok: false,
|
|
30762
|
+
message: cause instanceof Error ? cause.message : "Failed to compile MDX.",
|
|
30763
|
+
line,
|
|
30764
|
+
column,
|
|
30765
|
+
frontmatter
|
|
30766
|
+
};
|
|
30767
|
+
}
|
|
30768
|
+
}
|
|
30769
|
+
//#endregion
|
|
30770
|
+
//#region src/assets/mdxPreviewStore.ts
|
|
30771
|
+
/**
|
|
30772
|
+
* On-disk cache of compiled MDX previews.
|
|
30773
|
+
*
|
|
30774
|
+
* A build is keyed by the source file's real path, mtime and size, so opening
|
|
30775
|
+
* the same unchanged document twice reuses the cached output and touching the
|
|
30776
|
+
* file invalidates it. Output lives under the server state directory, next to
|
|
30777
|
+
* `attachments`, because it is generated data that must never be written back
|
|
30778
|
+
* into the user's workspace.
|
|
30779
|
+
*
|
|
30780
|
+
* @module mdxPreviewStore
|
|
30781
|
+
*/
|
|
30782
|
+
/** Bumping this invalidates every cached build after a renderer change. */
|
|
30783
|
+
const BUILD_FORMAT_VERSION = 1;
|
|
30784
|
+
const MDX_BUILD_DOCUMENT_FILE = "document.js";
|
|
30785
|
+
const MDX_BUILD_META_FILE = "meta.json";
|
|
30786
|
+
/** Only these two names resolve inside a build directory. */
|
|
30787
|
+
const MDX_BUILD_FILES = /* @__PURE__ */ new Set([MDX_BUILD_DOCUMENT_FILE, MDX_BUILD_META_FILE]);
|
|
30788
|
+
const BUILD_ID_PATTERN = /^[0-9a-f]{32}$/;
|
|
30789
|
+
const CACHE_MAX_AGE_MS = 10080 * 60 * 1e3;
|
|
30790
|
+
const CACHE_MAX_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
30791
|
+
function isMdxBuildId(value) {
|
|
30792
|
+
return BUILD_ID_PATTERN.test(value);
|
|
30793
|
+
}
|
|
30794
|
+
function buildIdFor(input) {
|
|
30795
|
+
return NodeCrypto.createHash("sha256").update(`${BUILD_FORMAT_VERSION}\0${input.realPath}\0${input.mtimeMs}\0${input.size}`).digest("hex").slice(0, 32);
|
|
30796
|
+
}
|
|
30797
|
+
function metaFor(input) {
|
|
30798
|
+
return {
|
|
30799
|
+
title: input.frontmatter.title,
|
|
30800
|
+
created: input.frontmatter.created,
|
|
30801
|
+
status: input.frontmatter.status,
|
|
30802
|
+
rest: input.frontmatter.rest,
|
|
30803
|
+
sourceName: input.sourceName,
|
|
30804
|
+
droppedImports: input.droppedImports,
|
|
30805
|
+
componentNames: input.componentNames,
|
|
30806
|
+
error: input.error,
|
|
30807
|
+
source: input.source
|
|
30808
|
+
};
|
|
30809
|
+
}
|
|
30810
|
+
async function directorySize(path) {
|
|
30811
|
+
const entries = await NodeFSP.readdir(path, { withFileTypes: true }).catch(() => []);
|
|
30812
|
+
let total = 0;
|
|
30813
|
+
for (const entry of entries) {
|
|
30814
|
+
if (!entry.isFile()) continue;
|
|
30815
|
+
const info = await NodeFSP.stat(NodePath.join(path, entry.name)).catch(() => null);
|
|
30816
|
+
total += info?.size ?? 0;
|
|
30817
|
+
}
|
|
30818
|
+
return total;
|
|
30819
|
+
}
|
|
30820
|
+
/**
|
|
30821
|
+
* Drop builds that aged out, then oldest-first until the directory fits.
|
|
30822
|
+
*
|
|
30823
|
+
* Both bounds exist because either alone leaks: a TTL lets a burst of large
|
|
30824
|
+
* documents blow past any disk budget within the window, and a size cap alone
|
|
30825
|
+
* keeps stale builds alive indefinitely on a quiet machine.
|
|
30826
|
+
*/
|
|
30827
|
+
async function evictStaleBuilds(buildsDir, keepBuildId, now) {
|
|
30828
|
+
const entries = await NodeFSP.readdir(buildsDir, { withFileTypes: true }).catch(() => []);
|
|
30829
|
+
const surviving = [];
|
|
30830
|
+
for (const entry of entries) {
|
|
30831
|
+
if (!entry.isDirectory() || entry.name === keepBuildId) continue;
|
|
30832
|
+
const path = NodePath.join(buildsDir, entry.name);
|
|
30833
|
+
if (!isMdxBuildId(entry.name)) {
|
|
30834
|
+
await NodeFSP.rm(path, {
|
|
30835
|
+
recursive: true,
|
|
30836
|
+
force: true
|
|
30837
|
+
}).catch(() => void 0);
|
|
30838
|
+
continue;
|
|
30839
|
+
}
|
|
30840
|
+
const info = await NodeFSP.stat(path).catch(() => null);
|
|
30841
|
+
if (!info) continue;
|
|
30842
|
+
if (now - info.mtimeMs > CACHE_MAX_AGE_MS) {
|
|
30843
|
+
await NodeFSP.rm(path, {
|
|
30844
|
+
recursive: true,
|
|
30845
|
+
force: true
|
|
30846
|
+
}).catch(() => void 0);
|
|
30847
|
+
continue;
|
|
30848
|
+
}
|
|
30849
|
+
surviving.push({
|
|
30850
|
+
path,
|
|
30851
|
+
mtimeMs: info.mtimeMs,
|
|
30852
|
+
size: await directorySize(path)
|
|
30853
|
+
});
|
|
30854
|
+
}
|
|
30855
|
+
let total = surviving.reduce((sum, entry) => sum + entry.size, 0);
|
|
30856
|
+
if (total <= CACHE_MAX_TOTAL_BYTES) return;
|
|
30857
|
+
for (const entry of surviving.toSorted((a, b) => a.mtimeMs - b.mtimeMs)) {
|
|
30858
|
+
if (total <= CACHE_MAX_TOTAL_BYTES) break;
|
|
30859
|
+
await NodeFSP.rm(entry.path, {
|
|
30860
|
+
recursive: true,
|
|
30861
|
+
force: true
|
|
30862
|
+
}).catch(() => void 0);
|
|
30863
|
+
total -= entry.size;
|
|
30864
|
+
}
|
|
30865
|
+
}
|
|
30866
|
+
/**
|
|
30867
|
+
* Compile `sourcePath` if needed and return the build that serves it.
|
|
30868
|
+
*
|
|
30869
|
+
* A compile failure is not an error here: it produces a build whose `meta.json`
|
|
30870
|
+
* carries the diagnostic, so the renderer can show an error card with the
|
|
30871
|
+
* source rather than a blank page.
|
|
30872
|
+
*/
|
|
30873
|
+
async function prepareMdxBuild(input) {
|
|
30874
|
+
const realPath = await NodeFSP.realpath(input.sourcePath);
|
|
30875
|
+
const stat = await NodeFSP.stat(realPath);
|
|
30876
|
+
if (!stat.isFile()) throw new Error(`MDX preview source is not a file: ${realPath}`);
|
|
30877
|
+
const buildId = buildIdFor({
|
|
30878
|
+
realPath,
|
|
30879
|
+
mtimeMs: stat.mtimeMs,
|
|
30880
|
+
size: stat.size
|
|
30881
|
+
});
|
|
30882
|
+
const buildDir = NodePath.join(input.buildsDir, buildId);
|
|
30883
|
+
const sourceDir = NodePath.dirname(realPath);
|
|
30884
|
+
const metaPath = NodePath.join(buildDir, MDX_BUILD_META_FILE);
|
|
30885
|
+
if ((await NodeFSP.stat(metaPath).catch(() => null))?.isFile()) {
|
|
30886
|
+
const touchedAtSeconds = input.now / 1e3;
|
|
30887
|
+
await NodeFSP.utimes(buildDir, touchedAtSeconds, touchedAtSeconds).catch(() => void 0);
|
|
30888
|
+
await evictStaleBuilds(input.buildsDir, buildId, input.now);
|
|
30889
|
+
return {
|
|
30890
|
+
buildId,
|
|
30891
|
+
sourceDir
|
|
30892
|
+
};
|
|
30893
|
+
}
|
|
30894
|
+
const source = await NodeFSP.readFile(realPath, "utf8");
|
|
30895
|
+
const outcome = await compileMdxDocument(source);
|
|
30896
|
+
const sourceName = NodePath.basename(realPath);
|
|
30897
|
+
await NodeFSP.mkdir(buildDir, { recursive: true });
|
|
30898
|
+
if (outcome.ok) await NodeFSP.writeFile(NodePath.join(buildDir, MDX_BUILD_DOCUMENT_FILE), outcome.code, "utf8");
|
|
30899
|
+
const meta = metaFor({
|
|
30900
|
+
frontmatter: outcome.frontmatter,
|
|
30901
|
+
sourceName,
|
|
30902
|
+
droppedImports: outcome.ok ? outcome.droppedImports : false,
|
|
30903
|
+
componentNames: outcome.ok ? outcome.componentNames : [],
|
|
30904
|
+
error: outcome.ok ? null : {
|
|
30905
|
+
message: outcome.message,
|
|
30906
|
+
line: outcome.line
|
|
30907
|
+
},
|
|
30908
|
+
source: outcome.ok ? null : source
|
|
30909
|
+
});
|
|
30910
|
+
await NodeFSP.writeFile(metaPath, JSON.stringify(meta), "utf8");
|
|
30911
|
+
await evictStaleBuilds(input.buildsDir, buildId, input.now);
|
|
30912
|
+
return {
|
|
30913
|
+
buildId,
|
|
30914
|
+
sourceDir
|
|
30915
|
+
};
|
|
30916
|
+
}
|
|
30917
|
+
//#endregion
|
|
30497
30918
|
//#region ../../packages/shared/src/projectFavicon.ts
|
|
30498
30919
|
const PROJECT_FAVICON_FALLBACK_MARKER = "project-favicon-missing";
|
|
30499
30920
|
//#endregion
|
|
@@ -30712,6 +31133,10 @@ const PREVIEW_ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
30712
31133
|
".woff",
|
|
30713
31134
|
".woff2"
|
|
30714
31135
|
]);
|
|
31136
|
+
/** Relative references inside a compiled MDX document resolve to images only. */
|
|
31137
|
+
const MDX_SOURCE_ASSET_EXTENSIONS = new Set(WORKSPACE_IMAGE_PREVIEW_EXTENSIONS);
|
|
31138
|
+
/** Path prefix under an MDX build token that maps to the source directory. */
|
|
31139
|
+
const MDX_SOURCE_ASSET_PREFIX = "assets/";
|
|
30715
31140
|
const AssetClaimsSchema = Schema$1.Union([
|
|
30716
31141
|
Schema$1.Struct({
|
|
30717
31142
|
version: Schema$1.Literal(1),
|
|
@@ -30727,6 +31152,25 @@ const AssetClaimsSchema = Schema$1.Union([
|
|
|
30727
31152
|
relativePath: Schema$1.String,
|
|
30728
31153
|
expiresAt: Schema$1.Number
|
|
30729
31154
|
}),
|
|
31155
|
+
Schema$1.Struct({
|
|
31156
|
+
version: Schema$1.Literal(1),
|
|
31157
|
+
kind: Schema$1.Literal("local-file"),
|
|
31158
|
+
baseDirectory: Schema$1.String,
|
|
31159
|
+
expiresAt: Schema$1.Number
|
|
31160
|
+
}),
|
|
31161
|
+
Schema$1.Struct({
|
|
31162
|
+
version: Schema$1.Literal(1),
|
|
31163
|
+
kind: Schema$1.Literal("local-file-exact"),
|
|
31164
|
+
filePath: Schema$1.String,
|
|
31165
|
+
expiresAt: Schema$1.Number
|
|
31166
|
+
}),
|
|
31167
|
+
Schema$1.Struct({
|
|
31168
|
+
version: Schema$1.Literal(1),
|
|
31169
|
+
kind: Schema$1.Literal("mdx-build"),
|
|
31170
|
+
buildId: Schema$1.String,
|
|
31171
|
+
sourceDirectory: Schema$1.String,
|
|
31172
|
+
expiresAt: Schema$1.Number
|
|
31173
|
+
}),
|
|
30730
31174
|
Schema$1.Struct({
|
|
30731
31175
|
version: Schema$1.Literal(1),
|
|
30732
31176
|
kind: Schema$1.Literal("attachment"),
|
|
@@ -30776,6 +31220,41 @@ const resolveCanonicalWorkspaceFileForRequest = (input) => resolveCanonicalWorks
|
|
|
30776
31220
|
relativePath: input.relativePath,
|
|
30777
31221
|
cause
|
|
30778
31222
|
})), Effect.orElseSucceed(() => null));
|
|
31223
|
+
/**
|
|
31224
|
+
* Reject anything that could walk out of a directory grant.
|
|
31225
|
+
*
|
|
31226
|
+
* Shared by every directory-scoped claim so the workspace grant and the two
|
|
31227
|
+
* new local grants cannot drift apart: a rule relaxed for one of them would
|
|
31228
|
+
* otherwise silently relax for none of the others, which is how the
|
|
31229
|
+
* out-of-workspace path becomes the weak one.
|
|
31230
|
+
*/
|
|
31231
|
+
function isSafeGrantRelativePath(decodedPath, allowedExtensions, extname) {
|
|
31232
|
+
if (decodedPath.length === 0 || decodedPath.includes("\0")) return false;
|
|
31233
|
+
if (decodedPath.split(/[\\/]/).some((segment) => segment === "." || segment === ".." || segment.startsWith("."))) return false;
|
|
31234
|
+
return allowedExtensions.has(extname(decodedPath).toLowerCase());
|
|
31235
|
+
}
|
|
31236
|
+
/**
|
|
31237
|
+
* Resolve a relative path inside a directory grant, following symlinks.
|
|
31238
|
+
*
|
|
31239
|
+
* The realpath comparison is the point: without it a symlink inside the
|
|
31240
|
+
* granted directory would hand out any file on disk while every textual check
|
|
31241
|
+
* above still passed.
|
|
31242
|
+
*/
|
|
31243
|
+
const resolveCanonicalFileWithinDirectory = Effect.fn("AssetAccess.resolveCanonicalFileWithinDirectory")(function* (input) {
|
|
31244
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
31245
|
+
const path = yield* Path.Path;
|
|
31246
|
+
const [canonicalBase, canonicalFile] = yield* Effect.all([optionOnNotFound(fileSystem.realPath(input.baseDirectory)), optionOnNotFound(fileSystem.realPath(path.join(input.baseDirectory, input.relativePath)))]);
|
|
31247
|
+
if (Option.isNone(canonicalBase) || Option.isNone(canonicalFile)) return null;
|
|
31248
|
+
const relative = path.relative(canonicalBase.value, canonicalFile.value);
|
|
31249
|
+
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) return null;
|
|
31250
|
+
const info = yield* optionOnNotFound(fileSystem.stat(canonicalFile.value));
|
|
31251
|
+
return Option.isSome(info) && info.value.type === "File" ? canonicalFile.value : null;
|
|
31252
|
+
});
|
|
31253
|
+
const resolveCanonicalFileWithinDirectoryForRequest = (input) => resolveCanonicalFileWithinDirectory(input).pipe(Effect.tapError((cause) => Effect.logError("Failed to resolve a granted asset path.", {
|
|
31254
|
+
baseDirectory: input.baseDirectory,
|
|
31255
|
+
relativePath: input.relativePath,
|
|
31256
|
+
cause
|
|
31257
|
+
})), Effect.orElseSucceed(() => null));
|
|
30779
31258
|
const issueAssetUrl = Effect.fn("AssetAccess.issueAssetUrl")(function* (input) {
|
|
30780
31259
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
30781
31260
|
const path = yield* Path.Path;
|
|
@@ -30826,6 +31305,59 @@ const issueAssetUrl = Effect.fn("AssetAccess.issueAssetUrl")(function* (input) {
|
|
|
30826
31305
|
fileName = path.basename(resolved.relativePath);
|
|
30827
31306
|
break;
|
|
30828
31307
|
}
|
|
31308
|
+
case "local-file": {
|
|
31309
|
+
if (!path.isAbsolute(input.resource.path)) return yield* new AssetLocalPathValidationError({ resource: input.resource });
|
|
31310
|
+
if (!isWorkspacePreviewEntryPath(input.resource.path)) return yield* new AssetPreviewTypeValidationError({ resource: input.resource });
|
|
31311
|
+
const canonicalFile = yield* optionOnNotFound(fileSystem.realPath(input.resource.path)).pipe(Effect.mapError((cause) => new AssetLocalFileInspectionError({
|
|
31312
|
+
resource: input.resource,
|
|
31313
|
+
cause
|
|
31314
|
+
})));
|
|
31315
|
+
if (Option.isNone(canonicalFile)) return yield* new AssetLocalFileNotFoundError({ resource: input.resource });
|
|
31316
|
+
const info = yield* optionOnNotFound(fileSystem.stat(canonicalFile.value)).pipe(Effect.mapError((cause) => new AssetLocalFileInspectionError({
|
|
31317
|
+
resource: input.resource,
|
|
31318
|
+
cause
|
|
31319
|
+
})));
|
|
31320
|
+
if (Option.isNone(info) || info.value.type !== "File") return yield* new AssetLocalFileNotFoundError({ resource: input.resource });
|
|
31321
|
+
claims = isWorkspaceImagePreviewPath(canonicalFile.value) ? {
|
|
31322
|
+
version: 1,
|
|
31323
|
+
kind: "local-file-exact",
|
|
31324
|
+
filePath: canonicalFile.value,
|
|
31325
|
+
expiresAt
|
|
31326
|
+
} : {
|
|
31327
|
+
version: 1,
|
|
31328
|
+
kind: "local-file",
|
|
31329
|
+
baseDirectory: path.dirname(canonicalFile.value),
|
|
31330
|
+
expiresAt
|
|
31331
|
+
};
|
|
31332
|
+
fileName = path.basename(canonicalFile.value);
|
|
31333
|
+
break;
|
|
31334
|
+
}
|
|
31335
|
+
case "mdx-preview": {
|
|
31336
|
+
if (!path.isAbsolute(input.resource.path)) return yield* new AssetLocalPathValidationError({ resource: input.resource });
|
|
31337
|
+
const config = yield* ServerConfig$1;
|
|
31338
|
+
const now = yield* Clock.currentTimeMillis;
|
|
31339
|
+
const sourcePath = input.resource.path;
|
|
31340
|
+
const build = yield* Effect.tryPromise({
|
|
31341
|
+
try: () => prepareMdxBuild({
|
|
31342
|
+
buildsDir: config.mdxBuildsDir,
|
|
31343
|
+
sourcePath,
|
|
31344
|
+
now
|
|
31345
|
+
}),
|
|
31346
|
+
catch: (cause) => new AssetMdxBuildError({
|
|
31347
|
+
resource: input.resource,
|
|
31348
|
+
cause
|
|
31349
|
+
})
|
|
31350
|
+
});
|
|
31351
|
+
claims = {
|
|
31352
|
+
version: 1,
|
|
31353
|
+
kind: "mdx-build",
|
|
31354
|
+
buildId: build.buildId,
|
|
31355
|
+
sourceDirectory: build.sourceDir,
|
|
31356
|
+
expiresAt
|
|
31357
|
+
};
|
|
31358
|
+
fileName = "meta.json";
|
|
31359
|
+
break;
|
|
31360
|
+
}
|
|
30829
31361
|
case "attachment": {
|
|
30830
31362
|
const attachmentPath = resolveAttachmentPathById({
|
|
30831
31363
|
attachmentsDir: (yield* ServerConfig$1).attachmentsDir,
|
|
@@ -30922,6 +31454,54 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
30922
31454
|
const decodedPath = decodeRelativePath(relativePath);
|
|
30923
31455
|
if (decodedPath === null) return null;
|
|
30924
31456
|
const path = yield* Path.Path;
|
|
31457
|
+
if (claims.kind === "local-file-exact") {
|
|
31458
|
+
if (decodedPath !== path.basename(claims.filePath)) return null;
|
|
31459
|
+
const fileSystem = yield* FileSystem.FileSystem;
|
|
31460
|
+
const info = yield* optionOnNotFound(fileSystem.stat(claims.filePath)).pipe(Effect.tapError((cause) => Effect.logError("Failed to inspect local asset.", {
|
|
31461
|
+
path: claims.filePath,
|
|
31462
|
+
cause
|
|
31463
|
+
})), Effect.orElseSucceed(() => Option.none()));
|
|
31464
|
+
return Option.isSome(info) && info.value.type === "File" ? {
|
|
31465
|
+
kind: "file",
|
|
31466
|
+
path: claims.filePath
|
|
31467
|
+
} : null;
|
|
31468
|
+
}
|
|
31469
|
+
if (claims.kind === "local-file") {
|
|
31470
|
+
if (!isSafeGrantRelativePath(decodedPath, PREVIEW_ASSET_EXTENSIONS, path.extname)) return null;
|
|
31471
|
+
const localFile = yield* resolveCanonicalFileWithinDirectoryForRequest({
|
|
31472
|
+
baseDirectory: claims.baseDirectory,
|
|
31473
|
+
relativePath: decodedPath
|
|
31474
|
+
});
|
|
31475
|
+
return localFile ? {
|
|
31476
|
+
kind: "file",
|
|
31477
|
+
path: localFile
|
|
31478
|
+
} : null;
|
|
31479
|
+
}
|
|
31480
|
+
if (claims.kind === "mdx-build") {
|
|
31481
|
+
if (!isMdxBuildId(claims.buildId)) return null;
|
|
31482
|
+
const config = yield* ServerConfig$1;
|
|
31483
|
+
if (MDX_BUILD_FILES.has(decodedPath)) {
|
|
31484
|
+
const buildFile = yield* resolveCanonicalFileWithinDirectoryForRequest({
|
|
31485
|
+
baseDirectory: path.join(config.mdxBuildsDir, claims.buildId),
|
|
31486
|
+
relativePath: decodedPath
|
|
31487
|
+
});
|
|
31488
|
+
return buildFile ? {
|
|
31489
|
+
kind: "file",
|
|
31490
|
+
path: buildFile
|
|
31491
|
+
} : null;
|
|
31492
|
+
}
|
|
31493
|
+
if (!decodedPath.startsWith(MDX_SOURCE_ASSET_PREFIX)) return null;
|
|
31494
|
+
const sourceRelativePath = decodedPath.slice(7);
|
|
31495
|
+
if (!isSafeGrantRelativePath(sourceRelativePath, MDX_SOURCE_ASSET_EXTENSIONS, path.extname)) return null;
|
|
31496
|
+
const sourceFile = yield* resolveCanonicalFileWithinDirectoryForRequest({
|
|
31497
|
+
baseDirectory: claims.sourceDirectory,
|
|
31498
|
+
relativePath: sourceRelativePath
|
|
31499
|
+
});
|
|
31500
|
+
return sourceFile ? {
|
|
31501
|
+
kind: "file",
|
|
31502
|
+
path: sourceFile
|
|
31503
|
+
} : null;
|
|
31504
|
+
}
|
|
30925
31505
|
if (claims.kind === "workspace-file-exact") {
|
|
30926
31506
|
if (decodedPath !== path.basename(claims.relativePath)) return null;
|
|
30927
31507
|
const exactWorkspaceFile = yield* resolveCanonicalWorkspaceFileForRequest({
|
|
@@ -30933,8 +31513,7 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
30933
31513
|
path: exactWorkspaceFile
|
|
30934
31514
|
} : null;
|
|
30935
31515
|
}
|
|
30936
|
-
|
|
30937
|
-
if (decodedPath.length === 0 || decodedPath.includes("\0") || segments.some((segment) => segment === "." || segment === ".." || segment.startsWith(".")) || !PREVIEW_ASSET_EXTENSIONS.has(path.extname(decodedPath).toLowerCase())) return null;
|
|
31516
|
+
if (!isSafeGrantRelativePath(decodedPath, PREVIEW_ASSET_EXTENSIONS, path.extname)) return null;
|
|
30938
31517
|
const joinedRelativePath = claims.baseRelativePath === "." ? decodedPath : path.join(claims.baseRelativePath, decodedPath);
|
|
30939
31518
|
const workspaceFile = yield* resolveCanonicalWorkspaceFileForRequest({
|
|
30940
31519
|
workspaceRoot: claims.workspaceRoot,
|
|
@@ -34864,6 +35443,7 @@ const TASK_PLAN_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
|
34864
35443
|
"task_get",
|
|
34865
35444
|
"task_current",
|
|
34866
35445
|
"task_propose",
|
|
35446
|
+
"ticket_resolve",
|
|
34867
35447
|
"taskcreate",
|
|
34868
35448
|
"taskupdate",
|
|
34869
35449
|
"tasklist",
|
|
@@ -36571,13 +37151,16 @@ const make$36 = Effect.gen(function* () {
|
|
|
36571
37151
|
reason: "not_found",
|
|
36572
37152
|
detail: `Linear returned nothing usable for ${identifier}.`
|
|
36573
37153
|
});
|
|
37154
|
+
const externalRef = {
|
|
37155
|
+
source: "linear",
|
|
37156
|
+
identifier: stringField$1(issue, "identifier") ?? identifier,
|
|
37157
|
+
url
|
|
37158
|
+
};
|
|
37159
|
+
const description = stringField$1(issue, "description");
|
|
36574
37160
|
return {
|
|
36575
|
-
externalRef
|
|
36576
|
-
|
|
36577
|
-
|
|
36578
|
-
url
|
|
36579
|
-
},
|
|
36580
|
-
title
|
|
37161
|
+
externalRef,
|
|
37162
|
+
title,
|
|
37163
|
+
...description === void 0 ? {} : { description }
|
|
36581
37164
|
};
|
|
36582
37165
|
}) };
|
|
36583
37166
|
});
|
|
@@ -39808,20 +40391,10 @@ var WorkspacePathNotFileError = class extends Schema$1.TaggedErrorClass()("Works
|
|
|
39808
40391
|
return `Workspace path '${this.relativePath}' in '${this.workspaceRoot}' is not a file: ${this.resolvedPath}`;
|
|
39809
40392
|
}
|
|
39810
40393
|
};
|
|
39811
|
-
var WorkspaceBinaryFileError = class extends Schema$1.TaggedErrorClass()("WorkspaceBinaryFileError", {
|
|
39812
|
-
workspaceRoot: Schema$1.String,
|
|
39813
|
-
relativePath: Schema$1.String,
|
|
39814
|
-
resolvedPath: Schema$1.String
|
|
39815
|
-
}) {
|
|
39816
|
-
get message() {
|
|
39817
|
-
return `Workspace file '${this.relativePath}' in '${this.workspaceRoot}' is binary and cannot be previewed as text.`;
|
|
39818
|
-
}
|
|
39819
|
-
};
|
|
39820
40394
|
Schema$1.Union([
|
|
39821
40395
|
WorkspaceFileSystemOperationError,
|
|
39822
40396
|
WorkspaceFilePathEscapeError,
|
|
39823
|
-
WorkspacePathNotFileError
|
|
39824
|
-
WorkspaceBinaryFileError
|
|
40397
|
+
WorkspacePathNotFileError
|
|
39825
40398
|
]);
|
|
39826
40399
|
/** Service tag for workspace file operations. */
|
|
39827
40400
|
var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
|
|
@@ -39905,16 +40478,19 @@ const make$29 = Effect.gen(function* () {
|
|
|
39905
40478
|
})
|
|
39906
40479
|
});
|
|
39907
40480
|
const fileBytes = buffer.subarray(0, bytesRead);
|
|
39908
|
-
if (fileBytes.includes(0)) return
|
|
39909
|
-
|
|
39910
|
-
|
|
39911
|
-
|
|
39912
|
-
|
|
40481
|
+
if (fileBytes.includes(0)) return {
|
|
40482
|
+
relativePath: target.relativePath,
|
|
40483
|
+
contents: "",
|
|
40484
|
+
byteLength: stat.size,
|
|
40485
|
+
truncated: false,
|
|
40486
|
+
binary: true
|
|
40487
|
+
};
|
|
39913
40488
|
return {
|
|
39914
40489
|
relativePath: target.relativePath,
|
|
39915
40490
|
contents: new TextDecoder("utf-8").decode(fileBytes),
|
|
39916
40491
|
byteLength: stat.size,
|
|
39917
|
-
truncated: stat.size > PROJECT_READ_FILE_MAX_BYTES
|
|
40492
|
+
truncated: stat.size > PROJECT_READ_FILE_MAX_BYTES,
|
|
40493
|
+
binary: false
|
|
39918
40494
|
};
|
|
39919
40495
|
}), (handle) => Effect.tryPromise({
|
|
39920
40496
|
try: () => handle.close(),
|
|
@@ -45743,10 +46319,6 @@ function projectFileFailureContext(error) {
|
|
|
45743
46319
|
failure: "path_not_file",
|
|
45744
46320
|
resolvedPath: error.resolvedPath
|
|
45745
46321
|
};
|
|
45746
|
-
case "WorkspaceBinaryFileError": return {
|
|
45747
|
-
failure: "binary_file",
|
|
45748
|
-
resolvedPath: error.resolvedPath
|
|
45749
|
-
};
|
|
45750
46322
|
default: return unexpectedCompatibilityError(error);
|
|
45751
46323
|
}
|
|
45752
46324
|
}
|
|
@@ -47727,6 +48299,18 @@ const ProviderEventLoggersLive = Layer.effect(ProviderEventLoggers, Effect.gen(f
|
|
|
47727
48299
|
var ProviderService = class extends Context.Service()("@p4code/cli/provider/Services/ProviderService") {};
|
|
47728
48300
|
//#endregion
|
|
47729
48301
|
//#region src/mcp/McpProviderSession.ts
|
|
48302
|
+
/**
|
|
48303
|
+
* The name p4code declares its own toolkit under, in every provider.
|
|
48304
|
+
*
|
|
48305
|
+
* One constant because it is one name in the agent's world: prompts, skills and
|
|
48306
|
+
* the tool categories all say `p4-code`, whichever runtime is reading them.
|
|
48307
|
+
* Every adapter also excludes it from the user's registered servers, so a
|
|
48308
|
+
* registration of the same name cannot displace the built-in one and take the
|
|
48309
|
+
* per-thread credential's tools (`task_current`, `thread_*`) with it.
|
|
48310
|
+
*/
|
|
48311
|
+
const P4CODE_MCP_SERVER_NAME = "p4-code";
|
|
48312
|
+
/** The reserved names, as the set the mappers take. */
|
|
48313
|
+
const P4CODE_MCP_SERVER_NAMES = /* @__PURE__ */ new Set([P4CODE_MCP_SERVER_NAME]);
|
|
47730
48314
|
const sessionsByThread = /* @__PURE__ */ new Map();
|
|
47731
48315
|
function setMcpProviderSession(config) {
|
|
47732
48316
|
sessionsByThread.set(config.threadId, config);
|
|
@@ -71563,6 +72147,81 @@ const SERVER_NOTIFICATION_PARAMS = {
|
|
|
71563
72147
|
"account/login/completed": V2AccountLoginCompletedNotification
|
|
71564
72148
|
};
|
|
71565
72149
|
//#endregion
|
|
72150
|
+
//#region src/provider/Layers/codexMcpArgs.ts
|
|
72151
|
+
/** Codex's own name for the token variable of p4code's built-in server. */
|
|
72152
|
+
const CODEX_P4CODE_BEARER_TOKEN_ENV_VAR = "P4_MCP_BEARER_TOKEN";
|
|
72153
|
+
/** Prefix for the per-server variables the registered servers get. */
|
|
72154
|
+
const BEARER_TOKEN_ENV_VAR_PREFIX = "P4_MCP_BEARER_TOKEN_";
|
|
72155
|
+
/** TOML bare keys; anything else has to be quoted inside the dotted path. */
|
|
72156
|
+
const BARE_KEY = /^[A-Za-z0-9_-]+$/;
|
|
72157
|
+
const AUTHORIZATION_HEADER = "authorization";
|
|
72158
|
+
const BEARER_PREFIX = /^Bearer\s+/;
|
|
72159
|
+
const configKey = (name, field) => `mcp_servers.${BARE_KEY.test(name) ? name : JSON.stringify(name)}.${field}`;
|
|
72160
|
+
/**
|
|
72161
|
+
* A variable name derived from the server's, uniquely.
|
|
72162
|
+
*
|
|
72163
|
+
* Uppercased with every character a shell would not accept replaced, which can
|
|
72164
|
+
* collide (`a.b` and `a-b`), so the sanitized name is the prefix and the index
|
|
72165
|
+
* keeps it unique. The index is stable within one call, which is all that is
|
|
72166
|
+
* needed: the variable and the reference to it are emitted together.
|
|
72167
|
+
*/
|
|
72168
|
+
const bearerTokenEnvVar = (name, index) => `${BEARER_TOKEN_ENV_VAR_PREFIX}${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_${index}`;
|
|
72169
|
+
/**
|
|
72170
|
+
* @param resolved - Servers keyed by name, as the registry resolved them.
|
|
72171
|
+
* @param exclude - Names p4code declares itself. A registration cannot displace
|
|
72172
|
+
* the built-in `p4-code` server, whose per-thread credential is the only
|
|
72173
|
+
* thing that makes `task_current` and the thread tools work.
|
|
72174
|
+
*/
|
|
72175
|
+
const toCodexMcpConfig = (resolved, exclude = /* @__PURE__ */ new Set()) => {
|
|
72176
|
+
const args = [];
|
|
72177
|
+
const env = {};
|
|
72178
|
+
const skipped = [];
|
|
72179
|
+
const push = (name, field, value) => {
|
|
72180
|
+
args.push("-c", `${configKey(name, field)}=${value}`);
|
|
72181
|
+
};
|
|
72182
|
+
let index = 0;
|
|
72183
|
+
for (const [name, server] of Object.entries(resolved)) {
|
|
72184
|
+
if (exclude.has(name)) continue;
|
|
72185
|
+
if (server.type === "stdio") {
|
|
72186
|
+
push(name, "command", JSON.stringify(server.command));
|
|
72187
|
+
push(name, "args", JSON.stringify(server.args));
|
|
72188
|
+
if (Object.keys(server.env).length > 0) push(name, "env", `{ ${Object.entries(server.env).map(([key, value]) => `${JSON.stringify(key)} = ${JSON.stringify(value)}`).join(", ")} }`);
|
|
72189
|
+
index += 1;
|
|
72190
|
+
continue;
|
|
72191
|
+
}
|
|
72192
|
+
if (server.type === "sse") {
|
|
72193
|
+
skipped.push({
|
|
72194
|
+
name,
|
|
72195
|
+
reason: "Codex speaks streamable HTTP, not SSE."
|
|
72196
|
+
});
|
|
72197
|
+
continue;
|
|
72198
|
+
}
|
|
72199
|
+
const headerNames = Object.keys(server.headers);
|
|
72200
|
+
const authorization = headerNames.find((key) => key.toLowerCase() === AUTHORIZATION_HEADER);
|
|
72201
|
+
const otherHeaders = headerNames.filter((key) => key !== authorization);
|
|
72202
|
+
if (otherHeaders.length > 0) {
|
|
72203
|
+
skipped.push({
|
|
72204
|
+
name,
|
|
72205
|
+
reason: `Codex sends no custom headers, and this server needs ${otherHeaders.join(", ")}.`
|
|
72206
|
+
});
|
|
72207
|
+
continue;
|
|
72208
|
+
}
|
|
72209
|
+
push(name, "url", JSON.stringify(server.url));
|
|
72210
|
+
if (authorization !== void 0) {
|
|
72211
|
+
const token = server.headers[authorization]?.replace(BEARER_PREFIX, "") ?? "";
|
|
72212
|
+
const variable = bearerTokenEnvVar(name, index);
|
|
72213
|
+
env[variable] = token;
|
|
72214
|
+
push(name, "bearer_token_env_var", JSON.stringify(variable));
|
|
72215
|
+
}
|
|
72216
|
+
index += 1;
|
|
72217
|
+
}
|
|
72218
|
+
return {
|
|
72219
|
+
args,
|
|
72220
|
+
env,
|
|
72221
|
+
skipped
|
|
72222
|
+
};
|
|
72223
|
+
};
|
|
72224
|
+
//#endregion
|
|
71566
72225
|
//#region ../../packages/effect-codex-app-server/src/_internal/shared.ts
|
|
71567
72226
|
const JsonRpcId$1 = Schema$1.Union([Schema$1.Number, Schema$1.String]);
|
|
71568
72227
|
const JsonRpcError = Schema$1.Struct({
|
|
@@ -73959,6 +74618,11 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* (codexConfig, o
|
|
|
73959
74618
|
if (existing && !existing.stopped) yield* Effect.suspend(() => stopSessionInternal(existing));
|
|
73960
74619
|
const serviceTier = input.modelSelection?.instanceId === boundInstanceId ? getCodexServiceTierOptionValue(input.modelSelection) : void 0;
|
|
73961
74620
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
74621
|
+
const externalMcp = toCodexMcpConfig(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers, P4CODE_MCP_SERVER_NAMES);
|
|
74622
|
+
for (const dropped of externalMcp.skipped) yield* Effect.logWarning("codex cannot express an mcp registration", {
|
|
74623
|
+
server: dropped.name,
|
|
74624
|
+
reason: dropped.reason
|
|
74625
|
+
});
|
|
73962
74626
|
const runtimeInput = {
|
|
73963
74627
|
threadId: input.threadId,
|
|
73964
74628
|
providerInstanceId: boundInstanceId,
|
|
@@ -73971,17 +74635,18 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* (codexConfig, o
|
|
|
73971
74635
|
runtimeMode: input.runtimeMode,
|
|
73972
74636
|
...input.modelSelection?.instanceId === boundInstanceId ? { model: input.modelSelection.model } : {},
|
|
73973
74637
|
...serviceTier ? { serviceTier } : {},
|
|
73974
|
-
...mcpSession ? {
|
|
74638
|
+
...externalMcp.args.length > 0 || mcpSession ? {
|
|
73975
74639
|
environment: {
|
|
73976
74640
|
...options?.environment ?? process.env,
|
|
73977
|
-
|
|
74641
|
+
...externalMcp.env,
|
|
74642
|
+
...mcpSession ? { [CODEX_P4CODE_BEARER_TOKEN_ENV_VAR]: mcpSession.authorizationHeader.replace(/^Bearer\s+/, "") } : {}
|
|
73978
74643
|
},
|
|
73979
|
-
appServerArgs: [
|
|
74644
|
+
appServerArgs: [...externalMcp.args, ...mcpSession ? [
|
|
73980
74645
|
"-c",
|
|
73981
|
-
`mcp_servers.
|
|
74646
|
+
`mcp_servers.${P4CODE_MCP_SERVER_NAME}.url=${mcpSession.endpoint}`,
|
|
73982
74647
|
"-c",
|
|
73983
|
-
|
|
73984
|
-
]
|
|
74648
|
+
`mcp_servers.${P4CODE_MCP_SERVER_NAME}.bearer_token_env_var="${CODEX_P4CODE_BEARER_TOKEN_ENV_VAR}"`
|
|
74649
|
+
] : []]
|
|
73985
74650
|
} : {}
|
|
73986
74651
|
};
|
|
73987
74652
|
const sessionScope = yield* Scope.make("sequential");
|
|
@@ -74484,6 +75149,7 @@ const CodexDriver = {
|
|
|
74484
75149
|
const adapter = yield* makeCodexAdapter(effectiveConfig, {
|
|
74485
75150
|
instanceId,
|
|
74486
75151
|
environment: processEnv,
|
|
75152
|
+
resolveMcpServers: (yield* McpRegistry).resolveForSession,
|
|
74487
75153
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
|
|
74488
75154
|
});
|
|
74489
75155
|
const textGeneration = yield* makeCodexTextGeneration(effectiveConfig, processEnv);
|
|
@@ -80076,6 +80742,31 @@ const makeCursorTextGeneration = Effect.fn("makeCursorTextGeneration")(function*
|
|
|
80076
80742
|
};
|
|
80077
80743
|
});
|
|
80078
80744
|
//#endregion
|
|
80745
|
+
//#region src/provider/acp/acpMcpServers.ts
|
|
80746
|
+
const namedPairs = (values) => Object.entries(values).map(([name, value]) => ({
|
|
80747
|
+
name,
|
|
80748
|
+
value
|
|
80749
|
+
}));
|
|
80750
|
+
/**
|
|
80751
|
+
* @param resolved - Servers keyed by name, as the registry resolved them.
|
|
80752
|
+
* @param exclude - Names p4code declares itself, which win over a registration
|
|
80753
|
+
* of the same name. The built-in `p4-code` server carries a per-thread
|
|
80754
|
+
* credential no registration can reproduce, so a same-named registration must
|
|
80755
|
+
* not be able to displace it — it would take `task_current` with it, and the
|
|
80756
|
+
* failure would look like the agent forgetting which task it is on.
|
|
80757
|
+
*/
|
|
80758
|
+
const toAcpMcpServers = (resolved, exclude = /* @__PURE__ */ new Set()) => Object.entries(resolved).filter(([name]) => !exclude.has(name)).map(([name, server]) => server.type === "stdio" ? {
|
|
80759
|
+
name,
|
|
80760
|
+
command: server.command,
|
|
80761
|
+
args: [...server.args],
|
|
80762
|
+
env: namedPairs(server.env)
|
|
80763
|
+
} : {
|
|
80764
|
+
type: server.type,
|
|
80765
|
+
name,
|
|
80766
|
+
url: server.url,
|
|
80767
|
+
headers: namedPairs(server.headers)
|
|
80768
|
+
});
|
|
80769
|
+
//#endregion
|
|
80079
80770
|
//#region src/provider/acp/AcpAdapterSupport.ts
|
|
80080
80771
|
const isAcpProcessExitedError = Schema$1.is(AcpProcessExitedError);
|
|
80081
80772
|
const isAcpRequestError = Schema$1.is(AcpRequestError);
|
|
@@ -80560,6 +81251,15 @@ function makeCursorAdapter(cursorSettings, options) {
|
|
|
80560
81251
|
});
|
|
80561
81252
|
const effectiveCursorSettings = options?.resolveSettings ? yield* options.resolveSettings : cursorSettings;
|
|
80562
81253
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
81254
|
+
const mcpServers = [...toAcpMcpServers(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers, P4CODE_MCP_SERVER_NAMES), ...mcpSession ? [{
|
|
81255
|
+
type: "http",
|
|
81256
|
+
name: P4CODE_MCP_SERVER_NAME,
|
|
81257
|
+
url: mcpSession.endpoint,
|
|
81258
|
+
headers: [{
|
|
81259
|
+
name: "Authorization",
|
|
81260
|
+
value: mcpSession.authorizationHeader
|
|
81261
|
+
}]
|
|
81262
|
+
}] : []];
|
|
80563
81263
|
const acp = yield* makeCursorAcpRuntime({
|
|
80564
81264
|
cursorSettings: effectiveCursorSettings,
|
|
80565
81265
|
...options?.environment ? { environment: options.environment } : {},
|
|
@@ -80567,18 +81267,10 @@ function makeCursorAdapter(cursorSettings, options) {
|
|
|
80567
81267
|
cwd,
|
|
80568
81268
|
...resumeSessionId ? { resumeSessionId } : {},
|
|
80569
81269
|
clientInfo: {
|
|
80570
|
-
name:
|
|
81270
|
+
name: P4CODE_MCP_SERVER_NAME,
|
|
80571
81271
|
version: "0.0.0"
|
|
80572
81272
|
},
|
|
80573
|
-
...
|
|
80574
|
-
type: "http",
|
|
80575
|
-
name: "p4-code",
|
|
80576
|
-
url: mcpSession.endpoint,
|
|
80577
|
-
headers: [{
|
|
80578
|
-
name: "Authorization",
|
|
80579
|
-
value: mcpSession.authorizationHeader
|
|
80580
|
-
}]
|
|
80581
|
-
}] } : {},
|
|
81273
|
+
...mcpServers.length > 0 ? { mcpServers } : {},
|
|
80582
81274
|
...acpNativeLoggers
|
|
80583
81275
|
}).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.provideService(Scope.Scope, sessionScope), Effect.mapError((cause) => new ProviderAdapterProcessError({
|
|
80584
81276
|
provider: PROVIDER$3,
|
|
@@ -81059,6 +81751,7 @@ const CursorDriver = {
|
|
|
81059
81751
|
});
|
|
81060
81752
|
const adapter = yield* makeCursorAdapter(effectiveConfig, {
|
|
81061
81753
|
environment: processEnv,
|
|
81754
|
+
resolveMcpServers: (yield* McpRegistry).resolveForSession,
|
|
81062
81755
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {},
|
|
81063
81756
|
instanceId
|
|
81064
81757
|
});
|
|
@@ -81781,6 +82474,15 @@ function makeGrokAdapter(grokSettings, options) {
|
|
|
81781
82474
|
threadId: input.threadId
|
|
81782
82475
|
});
|
|
81783
82476
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
82477
|
+
const mcpServers = [...toAcpMcpServers(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers, P4CODE_MCP_SERVER_NAMES), ...mcpSession ? [{
|
|
82478
|
+
type: "http",
|
|
82479
|
+
name: P4CODE_MCP_SERVER_NAME,
|
|
82480
|
+
url: mcpSession.endpoint,
|
|
82481
|
+
headers: [{
|
|
82482
|
+
name: "Authorization",
|
|
82483
|
+
value: mcpSession.authorizationHeader
|
|
82484
|
+
}]
|
|
82485
|
+
}] : []];
|
|
81784
82486
|
const acp = yield* makeGrokAcpRuntime({
|
|
81785
82487
|
grokSettings,
|
|
81786
82488
|
...options?.environment ? { environment: options.environment } : {},
|
|
@@ -81788,18 +82490,10 @@ function makeGrokAdapter(grokSettings, options) {
|
|
|
81788
82490
|
cwd,
|
|
81789
82491
|
...resumeSessionId ? { resumeSessionId } : {},
|
|
81790
82492
|
clientInfo: {
|
|
81791
|
-
name:
|
|
82493
|
+
name: P4CODE_MCP_SERVER_NAME,
|
|
81792
82494
|
version: "0.0.0"
|
|
81793
82495
|
},
|
|
81794
|
-
...
|
|
81795
|
-
type: "http",
|
|
81796
|
-
name: "p4-code",
|
|
81797
|
-
url: mcpSession.endpoint,
|
|
81798
|
-
headers: [{
|
|
81799
|
-
name: "Authorization",
|
|
81800
|
-
value: mcpSession.authorizationHeader
|
|
81801
|
-
}]
|
|
81802
|
-
}] } : {},
|
|
82496
|
+
...mcpServers.length > 0 ? { mcpServers } : {},
|
|
81803
82497
|
...acpNativeLoggers
|
|
81804
82498
|
}).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.provideService(Scope.Scope, sessionScope), Effect.mapError((cause) => new ProviderAdapterProcessError({
|
|
81805
82499
|
provider: PROVIDER$2,
|
|
@@ -82615,6 +83309,7 @@ const GrokDriver = {
|
|
|
82615
83309
|
});
|
|
82616
83310
|
const adapter = yield* makeGrokAdapter(effectiveConfig, {
|
|
82617
83311
|
environment: processEnv,
|
|
83312
|
+
resolveMcpServers: (yield* McpRegistry).resolveForSession,
|
|
82618
83313
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {},
|
|
82619
83314
|
instanceId
|
|
82620
83315
|
});
|
|
@@ -84452,6 +85147,27 @@ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(funct
|
|
|
84452
85147
|
};
|
|
84453
85148
|
});
|
|
84454
85149
|
//#endregion
|
|
85150
|
+
//#region src/provider/Layers/openCodeMcpServers.ts
|
|
85151
|
+
/**
|
|
85152
|
+
* @param resolved - Servers keyed by name, as the registry resolved them.
|
|
85153
|
+
* @param exclude - Names p4code declares itself, which a registration must not
|
|
85154
|
+
* be able to displace: the built-in `p4-code` server carries the per-thread
|
|
85155
|
+
* credential behind `task_current` and the thread tools.
|
|
85156
|
+
*/
|
|
85157
|
+
const toOpenCodeMcpServers = (resolved, exclude = /* @__PURE__ */ new Set()) => Object.entries(resolved).filter(([name]) => !exclude.has(name)).map(([name, server]) => ({
|
|
85158
|
+
name,
|
|
85159
|
+
config: server.type === "stdio" ? {
|
|
85160
|
+
type: "local",
|
|
85161
|
+
command: [server.command, ...server.args],
|
|
85162
|
+
...Object.keys(server.env).length > 0 ? { environment: server.env } : {}
|
|
85163
|
+
} : {
|
|
85164
|
+
type: "remote",
|
|
85165
|
+
url: server.url,
|
|
85166
|
+
...Object.keys(server.headers).length > 0 ? { headers: server.headers } : {},
|
|
85167
|
+
oauth: false
|
|
85168
|
+
}
|
|
85169
|
+
}));
|
|
85170
|
+
//#endregion
|
|
84455
85171
|
//#region src/provider/Layers/OpenCodeAdapter.ts
|
|
84456
85172
|
const PROVIDER = ProviderDriverKind.make("opencode");
|
|
84457
85173
|
/**
|
|
@@ -85128,8 +85844,15 @@ function makeOpenCodeAdapter(openCodeSettings, options) {
|
|
|
85128
85844
|
...server.external && serverPassword ? { serverPassword } : {}
|
|
85129
85845
|
});
|
|
85130
85846
|
const mcpSession = readMcpProviderSession(input.threadId);
|
|
85847
|
+
if (!server.external) {
|
|
85848
|
+
const externalMcpServers = toOpenCodeMcpServers(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers, P4CODE_MCP_SERVER_NAMES);
|
|
85849
|
+
for (const entry of externalMcpServers) yield* runOpenCodeSdk("mcp.add", () => client.mcp.add(entry)).pipe(Effect.catchCause((cause) => Effect.logWarning("opencode rejected an mcp registration", {
|
|
85850
|
+
server: entry.name,
|
|
85851
|
+
cause
|
|
85852
|
+
})));
|
|
85853
|
+
}
|
|
85131
85854
|
if (mcpSession && !server.external) yield* runOpenCodeSdk("mcp.add", () => client.mcp.add({
|
|
85132
|
-
name:
|
|
85855
|
+
name: P4CODE_MCP_SERVER_NAME,
|
|
85133
85856
|
config: {
|
|
85134
85857
|
type: "remote",
|
|
85135
85858
|
url: mcpSession.endpoint,
|
|
@@ -85818,6 +86541,7 @@ const BUILT_IN_DRIVERS = [
|
|
|
85818
86541
|
const adapter = yield* makeOpenCodeAdapter(effectiveConfig, {
|
|
85819
86542
|
instanceId,
|
|
85820
86543
|
environment: processEnv,
|
|
86544
|
+
resolveMcpServers: (yield* McpRegistry).resolveForSession,
|
|
85821
86545
|
...eventLoggers.native ? { nativeEventLogger: eventLoggers.native } : {}
|
|
85822
86546
|
});
|
|
85823
86547
|
const textGeneration = yield* makeOpenCodeTextGeneration(effectiveConfig, processEnv);
|
|
@@ -86490,7 +87214,29 @@ const TaskProposeTool = Tool.make("task_propose", {
|
|
|
86490
87214
|
failure: TaskToolError,
|
|
86491
87215
|
dependencies
|
|
86492
87216
|
}).annotate(Tool.Title, "Propose a task").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
|
|
86493
|
-
|
|
87217
|
+
/**
|
|
87218
|
+
* Reading a tracker ticket, for every provider rather than only the ones that
|
|
87219
|
+
* can talk to the tracker themselves.
|
|
87220
|
+
*
|
|
87221
|
+
* p4code resolves this server-side through the Linear server the user
|
|
87222
|
+
* registered once in Settings, so an agent gets the ticket whether or not its
|
|
87223
|
+
* own runtime was handed that registration. Without it, a thread started from
|
|
87224
|
+
* "MOBILE-12241" on a provider with no tracker of its own can only ask the user
|
|
87225
|
+
* to paste the description back in - which is the question they already
|
|
87226
|
+
* answered by quoting the id.
|
|
87227
|
+
*
|
|
87228
|
+
* On the task toolkit rather than a toolkit of its own because it is board
|
|
87229
|
+
* work: a resolved ticket's next step is `task_create` with the `externalRef`
|
|
87230
|
+
* this returns, and the two share the one capability a session is granted.
|
|
87231
|
+
*/
|
|
87232
|
+
const TicketResolveTool = Tool.make("ticket_resolve", {
|
|
87233
|
+
description: "Read a tracker ticket by id or URL (e.g. MOBILE-12241, or a linear.app link), returning its identifier, canonical URL, title and description. Use this whenever the user names a ticket rather than asking them to paste it. Pass the returned externalRef straight to task_create to mirror the ticket onto the board. Fails when no tracker is registered on this machine, which is a thing only the user can fix.",
|
|
87234
|
+
parameters: TicketResolveInput,
|
|
87235
|
+
success: TicketResolveResult,
|
|
87236
|
+
failure: Schema$1.Union([TaskToolUnavailableError, TicketResolveError]),
|
|
87237
|
+
dependencies: [McpInvocationContext, TicketResolver]
|
|
87238
|
+
}).annotate(Tool.Title, "Resolve a ticket").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
|
|
87239
|
+
const TaskToolkit = Toolkit.make(TaskListTool, TaskGetTool, TaskCurrentTool, TaskCreateTool, TaskUpdateTool, TaskProposeTool, TicketResolveTool);
|
|
86494
87240
|
//#endregion
|
|
86495
87241
|
//#region src/mcp/toolkits/tasks/handlers.ts
|
|
86496
87242
|
const nowIso$1 = Effect.map(DateTime.now, DateTime.formatIso);
|
|
@@ -86576,6 +87322,10 @@ const TaskToolkitHandlersLive = TaskToolkit.toLayer({
|
|
|
86576
87322
|
if (Option.isNone(patched)) return yield* new TaskNotFoundError({ taskId: input.taskId });
|
|
86577
87323
|
return patched.value;
|
|
86578
87324
|
}),
|
|
87325
|
+
ticket_resolve: (input) => Effect.gen(function* () {
|
|
87326
|
+
yield* requireTaskCapability();
|
|
87327
|
+
return yield* (yield* TicketResolver).resolve(input.reference);
|
|
87328
|
+
}),
|
|
86579
87329
|
task_propose: () => Effect.gen(function* () {
|
|
86580
87330
|
yield* requireTaskCapability();
|
|
86581
87331
|
return { awaitingConfirmation: true };
|