loopat 0.1.52 → 0.1.54

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.
Files changed (175) hide show
  1. package/package.json +1 -1
  2. package/server/src/git-host.ts +1 -0
  3. package/server/src/github.ts +101 -2
  4. package/server/src/index.ts +88 -3
  5. package/server/src/loops.ts +29 -1
  6. package/server/src/paths.ts +2 -0
  7. package/server/src/podman.ts +5 -2
  8. package/server/src/session.ts +25 -0
  9. package/web/dist/assets/{CodeEditor-JV36Z3V5.js → CodeEditor-ROIg2ylA.js} +1 -1
  10. package/web/dist/assets/Editor-BN7Q5g4N.js +1 -0
  11. package/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  12. package/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  13. package/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  14. package/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  15. package/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  16. package/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  17. package/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  18. package/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  19. package/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  20. package/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  21. package/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  22. package/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  23. package/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  24. package/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  25. package/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  26. package/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  27. package/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  28. package/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  29. package/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  30. package/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  31. package/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  32. package/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  33. package/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  34. package/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  35. package/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  36. package/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  37. package/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  38. package/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  39. package/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  40. package/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  41. package/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  42. package/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  43. package/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  44. package/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  45. package/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  46. package/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  47. package/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  48. package/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  49. package/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  50. package/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  51. package/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  52. package/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  53. package/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  54. package/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  55. package/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  56. package/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  57. package/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  58. package/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  59. package/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  60. package/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  61. package/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  62. package/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  63. package/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  64. package/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  65. package/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  66. package/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  67. package/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  68. package/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  69. package/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  70. package/web/dist/assets/Markdown-DvFvJx3d.js +3 -0
  71. package/web/dist/assets/MilkdownEditor-DsqsnlSK.js +123 -0
  72. package/web/dist/assets/{Terminal-Vi3Ufhgi.js → Terminal-DQxchB0u.js} +2 -2
  73. package/web/dist/assets/arc-JSCNOeGh.js +1 -0
  74. package/web/dist/assets/architecture-7EHR7CIX-C6TANlSv.js +1 -0
  75. package/web/dist/assets/architectureDiagram-3BPJPVTR-BiL4yrd-.js +36 -0
  76. package/web/dist/assets/array-CwG8vNfn.js +1 -0
  77. package/web/dist/assets/blockDiagram-GPEHLZMM-BlIpPvY3.js +132 -0
  78. package/web/dist/assets/c4Diagram-AAUBKEIU-CzsNYAS-.js +10 -0
  79. package/web/dist/assets/channel-BadMOAUe.js +1 -0
  80. package/web/dist/assets/chunk-2J33WTMH-jzikTe5Z.js +1 -0
  81. package/web/dist/assets/chunk-3OPIFGDE-CPRLtc-k.js +62 -0
  82. package/web/dist/assets/chunk-4BX2VUAB-C4VZq7p9.js +1 -0
  83. package/web/dist/assets/chunk-4EGX6M5U-BgefWETD.js +1 -0
  84. package/web/dist/assets/chunk-55IACEB6-DUDG-guT.js +1 -0
  85. package/web/dist/assets/chunk-5DO6E6H7-CXaGVrrt.js +1 -0
  86. package/web/dist/assets/chunk-5ZQYHXKU-DAcci771.js +2 -0
  87. package/web/dist/assets/chunk-62oNxeRG.js +1 -0
  88. package/web/dist/assets/chunk-727SXJPM-DB5VAPjb.js +206 -0
  89. package/web/dist/assets/chunk-AQP2D5EJ-zKFdEFYM.js +231 -0
  90. package/web/dist/assets/chunk-BR22UD5L-D9r29Y8a.js +1 -0
  91. package/web/dist/assets/chunk-BSJP7CBP-DF8jhsUx.js +1 -0
  92. package/web/dist/assets/chunk-CSCIHK7Q-KZCheCnJ.js +125 -0
  93. package/web/dist/assets/chunk-FHYWG6QK-5gBLDG6p.js +1 -0
  94. package/web/dist/assets/chunk-FMBD7UC4-BruiH2nG.js +15 -0
  95. package/web/dist/assets/chunk-KSCS5N6A-Cc-HIfIs.js +10 -0
  96. package/web/dist/assets/chunk-L5ZTLDWV-4FtjsXMJ.js +1 -0
  97. package/web/dist/assets/chunk-MPE355IW-RWzERmdt.js +1 -0
  98. package/web/dist/assets/chunk-MZUSXYTE-Xjzy1goZ.js +1 -0
  99. package/web/dist/assets/chunk-N66VUXT2-7wnXYZTH.js +1 -0
  100. package/web/dist/assets/chunk-ND2GUHAM-CLZCc4eF.js +1 -0
  101. package/web/dist/assets/chunk-NNHCCRGN-DHWtWlDY.js +159 -0
  102. package/web/dist/assets/chunk-NZK2D7GU-OE2TAhC6.js +1 -0
  103. package/web/dist/assets/chunk-O5CBEL6O-Bg6sZtyT.js +70 -0
  104. package/web/dist/assets/chunk-PUPMXCY4-C1dr9z9P.js +1 -0
  105. package/web/dist/assets/chunk-QZHKN3VN-DxLqo3gI.js +1 -0
  106. package/web/dist/assets/chunk-UIBZB4QT-DBYf6fSv.js +1 -0
  107. package/web/dist/assets/chunk-WCWK7LTN-DpJdbsk3.js +1 -0
  108. package/web/dist/assets/classDiagram-4FO5ZUOK-DGIJJBY5.js +1 -0
  109. package/web/dist/assets/classDiagram-v2-Q7XG4LA2-BdsZBmZ_.js +1 -0
  110. package/web/dist/assets/cose-bilkent-S5V4N54A-CWucooZw.js +1 -0
  111. package/web/dist/assets/cytoscape.esm-fMM2C9dj.js +321 -0
  112. package/web/dist/assets/dagre-BM42HDAG-CZ5AtThh.js +4 -0
  113. package/web/dist/assets/dagre-DtjYhTY3.js +1 -0
  114. package/web/dist/assets/defaultLocale-Dda4OpKy.js +1 -0
  115. package/web/dist/assets/diagram-2AECGRRQ-DE80i5fc.js +43 -0
  116. package/web/dist/assets/diagram-5GNKFQAL-Egr34zuZ.js +10 -0
  117. package/web/dist/assets/diagram-KO2AKTUF-CvajPPQL.js +3 -0
  118. package/web/dist/assets/diagram-LMA3HP47-f9ekzEBK.js +24 -0
  119. package/web/dist/assets/diagram-OG6HWLK6-CJhcoTKU.js +24 -0
  120. package/web/dist/assets/dist-Qo4xPaJL.js +1 -0
  121. package/web/dist/assets/erDiagram-TEJ5UH35-CYNgf9or.js +85 -0
  122. package/web/dist/assets/eventmodeling-FCH6USID-CFdOE-LK.js +1 -0
  123. package/web/dist/assets/flowDiagram-I6XJVG4X-BXTQ7QRg.js +162 -0
  124. package/web/dist/assets/ganttDiagram-6RSMTGT7-9CPIXrRu.js +292 -0
  125. package/web/dist/assets/gitGraph-WXDBUCRP-CQyqjuxy.js +1 -0
  126. package/web/dist/assets/gitGraphDiagram-PVQCEYII-D8BksuAg.js +106 -0
  127. package/web/dist/assets/graphlib-CVvj2XkR.js +1 -0
  128. package/web/dist/assets/index-BbAx7IhR.js +452 -0
  129. package/web/dist/assets/index-COolIbl3.css +1 -0
  130. package/web/dist/assets/info-J43DQDTF-_TOGLt_U.js +1 -0
  131. package/web/dist/assets/infoDiagram-5YYISTIA-Be0OcURm.js +2 -0
  132. package/web/dist/assets/init-D6KNwrax.js +1 -0
  133. package/web/dist/assets/isObject-6BN_nwjc.js +1 -0
  134. package/web/dist/assets/ishikawaDiagram-YF4QCWOH-BFyPbPqD.js +70 -0
  135. package/web/dist/assets/journeyDiagram-JHISSGLW-DR1RevaB.js +139 -0
  136. package/web/dist/assets/jsx-runtime-ZP0XCtgh.js +1 -0
  137. package/web/dist/assets/kanban-definition-UN3LZRKU-C5BAKIQX.js +89 -0
  138. package/web/dist/assets/katex-SDxE4_FN.js +257 -0
  139. package/web/dist/assets/{lib-B8L80SIn.js → lib-B1ZjR0ui.js} +3 -3
  140. package/web/dist/assets/line-C1hQ6Yic.js +1 -0
  141. package/web/dist/assets/linear-BTFE1p_D.js +1 -0
  142. package/web/dist/assets/mermaid-parser.core-B4wi-4x8.js +4 -0
  143. package/web/dist/assets/mindmap-definition-RKZ34NQL-DqgCcW-r.js +96 -0
  144. package/web/dist/assets/now-CfACN9Ld.js +1 -0
  145. package/web/dist/assets/ordinal-SeL1F7Yj.js +1 -0
  146. package/web/dist/assets/packet-YPE3B663-CsilPsGk.js +1 -0
  147. package/web/dist/assets/path-DNPd7Py7.js +1 -0
  148. package/web/dist/assets/pie-LRSECV5Y-B-D_L-Uc.js +1 -0
  149. package/web/dist/assets/pieDiagram-4H26LBE5-BP9tC1HT.js +30 -0
  150. package/web/dist/assets/quadrantDiagram-W4KKPZXB-BBjjuCms.js +7 -0
  151. package/web/dist/assets/radar-GUYGQ44K-DHD2KQPQ.js +1 -0
  152. package/web/dist/assets/requirementDiagram-4Y6WPE33-B_O_cEpd.js +84 -0
  153. package/web/dist/assets/rough.esm-DEh6Frf9.js +1 -0
  154. package/web/dist/assets/sankeyDiagram-5OEKKPKP-Cv_l_I0A.js +40 -0
  155. package/web/dist/assets/sequenceDiagram-3UESZ5HK-DBBZS2WD.js +162 -0
  156. package/web/dist/assets/src-BTV4tisa.js +1 -0
  157. package/web/dist/assets/stateDiagram-AJRCARHV-BaH2s_og.js +1 -0
  158. package/web/dist/assets/stateDiagram-v2-BHNVJYJU-Ryor5k_i.js +1 -0
  159. package/web/dist/assets/timeline-definition-PNZ67QCA-BNvy_0DN.js +120 -0
  160. package/web/dist/assets/treeView-BLDUP644-C8olDR1G.js +1 -0
  161. package/web/dist/assets/treemap-LRROVOQU-BIYIGzet.js +1 -0
  162. package/web/dist/assets/vennDiagram-CIIHVFJN-D5RSWRYm.js +34 -0
  163. package/web/dist/assets/viz-BR7pXPfi.js +7215 -0
  164. package/web/dist/assets/wardley-L42UT6IY-CfnZRM3V.js +1 -0
  165. package/web/dist/assets/wardleyDiagram-YWT4CUSO-5PntQ1A_.js +78 -0
  166. package/web/dist/assets/xychartDiagram-2RQKCTM6-B_1m_ITe.js +7 -0
  167. package/web/dist/index.html +23 -4
  168. package/web/dist/manifest.json +18 -0
  169. package/web/dist/assets/Editor-9lLPQzvP.js +0 -1
  170. package/web/dist/assets/Markdown-D5ElKjTG.js +0 -5
  171. package/web/dist/assets/MilkdownEditor-t_CG4MJj.js +0 -123
  172. package/web/dist/assets/index-C1GIAoyn.js +0 -145
  173. package/web/dist/assets/index-D-WGDCY6.css +0 -1
  174. package/web/dist/assets/jsx-runtime-DAYmCNe8.js +0 -1
  175. /package/web/dist/assets/{w3c-keyname-DXh_HxYD.js → w3c-keyname-BoNxyEq0.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loopat",
3
- "version": "0.1.52",
3
+ "version": "0.1.54",
4
4
  "description": "Self-hosted AI workspace built around context management — works solo, scales to teams",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/simpx/loopat",
@@ -63,6 +63,7 @@ export type OnboardingView =
63
63
  show:
64
64
  | ({ kind: "form" } & OnboardingForm)
65
65
  | { kind: "route"; path: string; title?: string; description?: string }
66
+ | { kind: "device"; title: string; description?: string }
66
67
  | {
67
68
  kind: "info"
68
69
  title: string
@@ -48,6 +48,48 @@ function fail(op: string, r: { status: number; data: any }): never {
48
48
  throw new Error(`github ${op} failed (${r.status})${msg ? `: ${msg}` : ""}`)
49
49
  }
50
50
 
51
+ /**
52
+ * OAuth Device Flow — login on localhost/cloud/any deployment without a per-user
53
+ * app or a callback URL. One public client_id (NOT a secret — like gh CLI) is
54
+ * baked in, overridable via LOOPAT_GITHUB_CLIENT_ID for self-hosters with their
55
+ * own app. Scope: `repo` only — list/create/clone/push private repos; git is
56
+ * over https-token so no ssh-key scope is needed. The token lands in the vault;
57
+ * from there onboarding is identical to a pasted PAT.
58
+ */
59
+ export const GITHUB_DEVICE_CLIENT_ID = process.env.LOOPAT_GITHUB_CLIENT_ID || "Ov23lijopFG81cPZXsI2"
60
+ export const GITHUB_DEVICE_SCOPE = "repo"
61
+
62
+ /** Step 1: request a device code. Returns the code to show + how long to poll. */
63
+ export async function requestDeviceCode(): Promise<{
64
+ device_code: string; user_code: string; verification_uri: string; interval: number; expires_in: number
65
+ }> {
66
+ const res = await fetch("https://github.com/login/device/code", {
67
+ method: "POST",
68
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
69
+ body: JSON.stringify({ client_id: GITHUB_DEVICE_CLIENT_ID, scope: GITHUB_DEVICE_SCOPE }),
70
+ })
71
+ const d = await res.json().catch(() => null)
72
+ if (!res.ok || !d?.device_code) throw new Error(`github device code request failed (${res.status})`)
73
+ return { device_code: d.device_code, user_code: d.user_code, verification_uri: d.verification_uri, interval: d.interval ?? 5, expires_in: d.expires_in ?? 900 }
74
+ }
75
+
76
+ /** Step 2: poll once for the token. `pending` until the user approves; `slow_down`
77
+ * asks us to back off; any other error is fatal. Returns the token on success. */
78
+ export async function pollDeviceToken(deviceCode: string): Promise<
79
+ { status: "ok"; token: string } | { status: "pending" } | { status: "slow_down" } | { status: "error"; error: string }
80
+ > {
81
+ const res = await fetch("https://github.com/login/oauth/access_token", {
82
+ method: "POST",
83
+ headers: { Accept: "application/json", "Content-Type": "application/json" },
84
+ body: JSON.stringify({ client_id: GITHUB_DEVICE_CLIENT_ID, device_code: deviceCode, grant_type: "urn:ietf:params:oauth:grant-type:device_code" }),
85
+ })
86
+ const d = await res.json().catch(() => null)
87
+ if (d?.access_token) return { status: "ok", token: d.access_token }
88
+ if (d?.error === "authorization_pending") return { status: "pending" }
89
+ if (d?.error === "slow_down") return { status: "slow_down" }
90
+ return { status: "error", error: d?.error_description ?? d?.error ?? `poll failed (${res.status})` }
91
+ }
92
+
51
93
  /** Capability 1 — authenticate: turn a token into the user's login. */
52
94
  export async function getViewer(c: GithubClient): Promise<{ login: string; id: number }> {
53
95
  const r = await gh(c, "GET", "/user")
@@ -133,13 +175,32 @@ export async function ensureCollaborator(
133
175
  export const githubProvider: GitHostProvider = {
134
176
  id: "github",
135
177
  label: "GitHub",
136
- gitAuthMode: "ssh-deploy-key",
178
+ // https-token: the device-flow OAuth token (scope `repo`) does both API and
179
+ // git over https://<login>:<token>@github.com/… — one credential for every
180
+ // repo, no per-repo deploy key. (OAuth-App tokens don't expire by default.)
181
+ gitAuthMode: "https-token",
182
+ // Onboarding step 1: no personal repo yet → device-flow login. loopat drives
183
+ // the device dance (start/poll) and, on token, provisions the repo. Once the
184
+ // repo is imported there's nothing left to gate on, so we're done.
185
+ async onboarding(ctx) {
186
+ if (!ctx.personalRepoImported) {
187
+ return {
188
+ done: false,
189
+ show: {
190
+ kind: "device",
191
+ title: "用 GitHub 登录",
192
+ description: "loopat 不存你的数据 —— 登录后会自动建一个私有个人仓库,你的 key / ssh / memory 都加密存在里面。",
193
+ },
194
+ }
195
+ }
196
+ return { done: true }
197
+ },
137
198
  async authenticate(cred) {
138
199
  return await getViewer(githubClient(cred.token, cred.baseUrl))
139
200
  },
140
201
  async ensureRepo(cred, name, opts) {
141
202
  const r = await ensureUserRepo(githubClient(cred.token, cred.baseUrl), name, { private: opts?.private })
142
- return { url: r.sshUrl, created: r.created }
203
+ return { url: r.httpUrl, created: r.created }
143
204
  },
144
205
  async registerDeployKey(cred, repo, title, pubkey, readOnly) {
145
206
  await ensureDeployKey(githubClient(cred.token, cred.baseUrl), repo.owner, repo.name, title, pubkey, readOnly)
@@ -147,6 +208,12 @@ export const githubProvider: GitHostProvider = {
147
208
  async registerUserKey(cred, title, pubkey) {
148
209
  await ensureUserKey(githubClient(cred.token, cred.baseUrl), title, pubkey)
149
210
  },
211
+ async listRepos(cred) {
212
+ const c = githubClient(cred.token, cred.baseUrl)
213
+ const r = await gh(c, "GET", "/user/repos?per_page=100&affiliation=owner&sort=updated")
214
+ const items = Array.isArray(r.data) ? r.data : []
215
+ return items.map((p: any) => ({ name: p.name, path: p.full_name }))
216
+ },
150
217
  async grantAccess(cred, repo, login, level) {
151
218
  await ensureCollaborator(
152
219
  githubClient(cred.token, cred.baseUrl),
@@ -156,6 +223,38 @@ export const githubProvider: GitHostProvider = {
156
223
  level === "write" ? "push" : "pull",
157
224
  )
158
225
  },
226
+
227
+ // Seed a freshly-created personal repo: one provider default (key goes in the
228
+ // vault later) and an ssh keypair (standard id_ed25519, git-crypt-encrypted)
229
+ // so loops can clone repos with zero config.
230
+ async seedDefaults(ctx) {
231
+ const fs = await import("node:fs/promises")
232
+ const path = await import("node:path")
233
+ const { execFile } = await import("node:child_process")
234
+ const { promisify } = await import("node:util")
235
+ const run = promisify(execFile)
236
+
237
+ const config = {
238
+ providers: {
239
+ default: "anthropic",
240
+ anthropic: {
241
+ model: "claude-opus-4-7",
242
+ baseUrl: "https://api.anthropic.com",
243
+ apiKey: "${ANTHROPIC_API_KEY}",
244
+ maxContextTokens: 200000,
245
+ models: [{ id: "claude-opus-4-7", enabled: true }],
246
+ enabled: true,
247
+ },
248
+ },
249
+ }
250
+ await fs.mkdir(path.join(ctx.repoDir, ".loopat"), { recursive: true })
251
+ await fs.writeFile(path.join(ctx.repoDir, ".loopat", "config.json"), JSON.stringify(config, null, 2) + "\n")
252
+
253
+ const sshDir = path.join(ctx.vaultDir, "mounts", "home", ".ssh")
254
+ await fs.mkdir(sshDir, { recursive: true })
255
+ await run("ssh-keygen", ["-t", "ed25519", "-N", "", "-C", `loopat:${ctx.login}`, "-f", path.join(sshDir, "id_ed25519")])
256
+ await fs.writeFile(path.join(sshDir, "config"), "Host *\n StrictHostKeyChecking accept-new\n")
257
+ },
159
258
  }
160
259
 
161
260
  registerProvider(githubProvider)
@@ -2,10 +2,10 @@ import { Hono } from "hono"
2
2
  import { cors } from "hono/cors"
3
3
  import { createBunWebSocket } from "hono/bun"
4
4
  import { existsSync } from "node:fs"
5
- import { execFile, execFileSync } from "node:child_process"
5
+ import { execFile, execFileSync, spawn } from "node:child_process"
6
6
  import { promisify } from "node:util"
7
- import { listLoops, createLoop, getLoop, loopExists, patchLoopMeta, backfillAllMounts, ensureWorkspaceDirs, provisionUserPersonal, importPersonalFromRepo, setupPersonalViaProvider, listPersonalReposViaProvider, authenticateViaProvider, isPersonalFresh, ensureUiNotesWorktree, syncUiNotes, ffUpdateUiNotes, discardUiNotes, notesBehind, inspectPersonalDirty, syncPersonalToRemote, deletePersonalVault, pullPersonalFromRemote, pushPersonalToRemote, ensureContextMounts, effectiveDriver, isDriver, distillLoop, inspectRepoSync, pullRepoFromRemote, pushRepoToRemote, listVaultPublicKeys, userOnboarding, submitOnboarding } from "./loops"
8
- import { getEphemeralHostPort, probePodman, stopAllWorkspaceContainers, ensureServeContainer, ensurePortProxyContainer, ensureSandboxImage } from "./podman"
7
+ import { listLoops, createLoop, getLoop, loopExists, patchLoopMeta, backfillAllMounts, ensureWorkspaceDirs, provisionUserPersonal, importPersonalFromRepo, setupPersonalViaProvider, listPersonalReposViaProvider, authenticateViaProvider, isPersonalFresh, ensureUiNotesWorktree, syncUiNotes, ffUpdateUiNotes, discardUiNotes, notesBehind, inspectPersonalDirty, syncPersonalToRemote, deletePersonalVault, pullPersonalFromRemote, pushPersonalToRemote, ensureContextMounts, effectiveDriver, isDriver, distillLoop, inspectRepoSync, pullRepoFromRemote, pushRepoToRemote, listVaultPublicKeys, userOnboarding, submitOnboarding, dismissOnboarding, deviceFlowStart, deviceFlowPoll } from "./loops"
8
+ import { getEphemeralHostPort, probePodman, stopAllWorkspaceContainers, ensureServeContainer, ensurePortProxyContainer, ensureSandboxImage, buildPodmanExecArgs, ensureContainer, containerName, V_LOOP_WORKDIR } from "./podman"
9
9
  import { startMcpAuth, completeMcpAuth, probeOAuthSupport, evictOAuthProbe, parseBearerEnvName, mcpRequiredEnvs, parseTemplateVars, type OAuthSupport } from "./mcp-oauth"
10
10
  import { DEFAULT_VAULT, loadVaultEnvs } from "./vaults"
11
11
  import {
@@ -1295,6 +1295,33 @@ app.post("/api/onboarding/submit", requireAuth, async (c) => {
1295
1295
  return c.json(r.next)
1296
1296
  })
1297
1297
 
1298
+ // Dismiss the onboarding gate. When the user clicks "skip / don't show again",
1299
+ // write a marker so `userOnboarding` returns `done` without running any provider
1300
+ // logic. The gate stays cleared until the marker is removed.
1301
+ app.post("/api/onboarding/done", requireAuth, async (c) => {
1302
+ const userId = c.get("userId") as string
1303
+ await dismissOnboarding(userId)
1304
+ return c.json({ ok: true })
1305
+ })
1306
+
1307
+ // GitHub device-flow login — start: returns the user code + verification URL.
1308
+ app.post("/api/onboarding/device/start", requireAuth, async (c) => {
1309
+ try {
1310
+ return c.json(await deviceFlowStart())
1311
+ } catch (e: any) {
1312
+ return c.json({ error: e?.message ?? "device start failed" }, 502)
1313
+ }
1314
+ })
1315
+
1316
+ // Poll: pending until the user approves; on token, hands the token back so the
1317
+ // repo picker takes over. Frontend re-polls on `pending`/`slow_down`.
1318
+ app.post("/api/onboarding/device/poll", requireAuth, async (c) => {
1319
+ const body = await c.req.json().catch(() => ({}))
1320
+ const deviceCode = typeof body?.device_code === "string" ? body.device_code : ""
1321
+ if (!deviceCode) return c.json({ error: "device_code required" }, 400)
1322
+ return c.json(await deviceFlowPoll(deviceCode))
1323
+ })
1324
+
1298
1325
  // Export the user's git-crypt key (base64). Behind a fresh password check
1299
1326
  // to prevent walk-up attacks on an unattended browser. The key decrypts
1300
1327
  // .loopat/vaults/** on any host that holds it, so we don't want a stolen
@@ -3130,6 +3157,8 @@ app.get(
3130
3157
  session.clear(userId ?? "anon")
3131
3158
  } else if (msg?.type === "interrupt") {
3132
3159
  session.interrupt()
3160
+ } else if (msg?.type === "background_tasks") {
3161
+ session.backgroundTasks().catch(() => {})
3133
3162
  } else if (msg?.type === "queue_clear") {
3134
3163
  session.clearQueue()
3135
3164
  } else if (msg?.type === "queue_remove") {
@@ -3197,6 +3226,62 @@ app.get(
3197
3226
  }
3198
3227
  } catch {}
3199
3228
  }
3229
+ } else if (msg?.type === "shell" && typeof msg.command === "string" && typeof msg.id === "string") {
3230
+ // One-shot shell command in the sandbox (CC "!" bang mode).
3231
+ // Runs via podman exec with a 30s timeout; sends back stdout/stderr.
3232
+ const cmd = msg.command.trim()
3233
+ if (cmd.length > 4096) {
3234
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, error: "command too long" })) } catch {}
3235
+ return
3236
+ }
3237
+ if (!meta || (userId && !isDriver(meta, userId))) {
3238
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, error: "only the driver can run shell commands" })) } catch {}
3239
+ return
3240
+ }
3241
+ if (meta.archived) {
3242
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, error: "loop is archived" })) } catch {}
3243
+ return
3244
+ }
3245
+ ;(async () => {
3246
+ try {
3247
+ await ensureContainer({ loopId: id, createdBy: meta.createdBy })
3248
+ const execArgs = ["exec", "--workdir", V_LOOP_WORKDIR(id), containerName(id), "bash", "-c", cmd]
3249
+ const child = spawn("podman", execArgs, { stdio: ["ignore", "pipe", "pipe"] })
3250
+ const chunks: Buffer[] = []
3251
+ const errChunks: Buffer[] = []
3252
+ child.stdout.on("data", (d: Buffer) => chunks.push(d))
3253
+ child.stderr.on("data", (d: Buffer) => errChunks.push(d))
3254
+ const timedOut = await new Promise<boolean>((resolve) => {
3255
+ const t = setTimeout(() => { child.kill(); resolve(true) }, 30_000)
3256
+ child.on("close", () => { clearTimeout(t); resolve(false) })
3257
+ })
3258
+ const out = Buffer.concat(chunks).toString("utf8").replace(/\r\n/g, "\n")
3259
+ const err = Buffer.concat(errChunks).toString("utf8").replace(/\r\n/g, "\n")
3260
+ const now = Date.now()
3261
+ if (timedOut) {
3262
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, _cmd: cmd, stdout: out, stderr: err, exitCode: null, error: "timed out (30s)" })) } catch {}
3263
+ } else {
3264
+ const exitCode = child.exitCode ?? 1
3265
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, _cmd: cmd, stdout: out, stderr: err, exitCode })) } catch {}
3266
+ // Inject into session history so shell output survives refresh
3267
+ // and replays for new subscribers. Use same shape as WS messages.
3268
+ const outText = [out, err].filter(Boolean).join("\n").trim() || "bash completed with no output"
3269
+ const suffix = exitCode !== 0 ? "\n[exit " + exitCode + "]" : ""
3270
+ session.injectHistory({
3271
+ type: "user",
3272
+ message: { role: "user", content: [{ type: "text", text: "$ " + cmd }] },
3273
+ uuid: msg.id,
3274
+ })
3275
+ session.injectHistory({
3276
+ type: "assistant",
3277
+ message: { role: "assistant", content: [{ type: "text", text: "```bash\n" + outText + suffix + "\n```" }] },
3278
+ uuid: "sh_" + msg.id,
3279
+ })
3280
+ }
3281
+ } catch (e: any) {
3282
+ try { ws.send(JSON.stringify({ type: "shell_result", id: msg.id, stdout: "", stderr: "", exitCode: 1, error: e?.message ?? String(e) })) } catch {}
3283
+ }
3284
+ })()
3200
3285
  }
3201
3286
  } catch (e) {
3202
3287
  console.error("ws message parse error", e)
@@ -1,9 +1,9 @@
1
+ import { join, dirname } from "node:path"
1
2
  import { chmod, copyFile, mkdir, mkdtemp, readdir, readFile, rename, writeFile, stat, symlink, lstat, rm } from "node:fs/promises"
2
3
  import { randomUUID } from "node:crypto"
3
4
  import { execFile } from "node:child_process"
4
5
  import { promisify } from "node:util"
5
6
  import { existsSync, chmodSync } from "node:fs"
6
- import { join } from "node:path"
7
7
  import { tmpdir } from "node:os"
8
8
  import {
9
9
  loopsDir,
@@ -36,6 +36,7 @@ import {
36
36
  workspaceMemoryDir,
37
37
  hostDeployKeyPath,
38
38
  personalGitCryptKeyPath,
39
+ onboardingDismissedPath,
39
40
  loopHistoryPath,
40
41
  loopChatHistoryPath,
41
42
  loopKindClaudePath,
@@ -719,6 +720,8 @@ export type OnboardingStatus = {
719
720
  /** Resolve the active provider's current onboarding view (done, or next form).
720
721
  * The provider owns the whole flow; loopat just feeds it context. */
721
722
  async function onboardingView(userId: string, vault: string): Promise<OnboardingStatus> {
723
+ // User dismissed the onboarding gate → skip all provider checks.
724
+ if (existsSync(onboardingDismissedPath(userId))) return { gated: false, done: true }
722
725
  const provider = await resolveProvider()
723
726
  if (!provider?.onboarding) return { gated: false, done: true }
724
727
  const personalRepoImported = !(await isPersonalFresh(userId))
@@ -740,6 +743,14 @@ export async function userOnboarding(userId: string, vault: string = "default"):
740
743
  return onboardingView(userId, vault)
741
744
  }
742
745
 
746
+ /** Dismiss the onboarding gate — write a marker that `onboardingView` checks
747
+ * before running any provider logic. Idempotent; the gate stays cleared. */
748
+ export async function dismissOnboarding(userId: string): Promise<void> {
749
+ const p = onboardingDismissedPath(userId)
750
+ try { await mkdir(dirname(p), { recursive: true }) } catch {}
751
+ await writeFile(p, `${new Date().toISOString()}\n`)
752
+ }
753
+
743
754
  /**
744
755
  * Run one onboarding form submission. Fetches the provider's CURRENT form (to
745
756
  * learn each field's action), then executes the submitted values:
@@ -793,6 +804,23 @@ export async function submitOnboarding(
793
804
  return { ok: true, next: await onboardingView(userId, vault) }
794
805
  }
795
806
 
807
+ /** Start a GitHub device-flow login: returns the code to show + poll interval. */
808
+ export async function deviceFlowStart(): Promise<{ device_code: string; user_code: string; verification_uri: string; interval: number }> {
809
+ const { requestDeviceCode } = await import("./github")
810
+ const d = await requestDeviceCode()
811
+ return { device_code: d.device_code, user_code: d.user_code, verification_uri: d.verification_uri, interval: d.interval }
812
+ }
813
+
814
+ /** Poll once. While the user hasn't approved, report pending. On approval, hand
815
+ * the token back so the picker (existing repo + git-crypt flow) takes over — we
816
+ * do NOT auto-create a repo. */
817
+ export async function deviceFlowPoll(
818
+ deviceCode: string,
819
+ ): Promise<{ status: "pending" | "slow_down" } | { status: "error"; error: string } | { status: "ok"; token: string }> {
820
+ const { pollDeviceToken } = await import("./github")
821
+ return pollDeviceToken(deviceCode)
822
+ }
823
+
796
824
  /**
797
825
  * Detect whether `personal/<user>/` is "fresh" — i.e. only has the
798
826
  * scaffolding we put there (`.git`, `memory/`). If yes, it's safe to wipe +
@@ -160,6 +160,8 @@ export const hostSecretsDir = (user: string) => join(LOOPAT_HOME, "host-secrets"
160
160
  export const hostDeployKeyPath = (user: string) => join(hostSecretsDir(user), "deploy-key")
161
161
  export const hostDeployKeyPubPath = (user: string) => join(hostSecretsDir(user), "deploy-key.pub")
162
162
  export const personalGitCryptKeyPath = (user: string) => join(hostSecretsDir(user), "git-crypt.key")
163
+ /** Marker file — when present the onboarding gate is dismissed even if incomplete. */
164
+ export const onboardingDismissedPath = (user: string) => join(hostSecretsDir(user), "onboarding-dismissed")
163
165
  export const personalTokenUsagePath = (user: string) => join(personalLoopatDir(user), "token-usage.json")
164
166
  export const workspaceSecretsDir = () => join(workspaceDir(), "secrets")
165
167
 
@@ -27,7 +27,7 @@
27
27
  * SDK and PTY are `podman exec` siblings of this.
28
28
  *
29
29
  * Two mount-authority tiers (same model as bwrap):
30
- * - operator: ~/.dashscope/config.json `mounts` (any host path)
30
+ * - operator: ~/.loopat/config.json `mounts` (any host path)
31
31
  * - member: convention-based via `vaults/<v>/mounts/home/<rel>/...` → $HOME/<rel>/...
32
32
  * - admin: no mount capability
33
33
  *
@@ -213,7 +213,7 @@ export async function buildVolumeMounts(opts: ContainerOptions): Promise<VolumeM
213
213
  const mounts: VolumeMount[] = []
214
214
 
215
215
  // /tmp: shared with host (for socat / mktemp / IPC sockets). Same as today.
216
- mounts.push({ src: "/tmp", dst: "/tmp" })
216
+ // mounts.push({ src: "/tmp", dst: "/tmp" })
217
217
 
218
218
  // $HOME: per-loop upper layer, persistent across container restarts. We
219
219
  // place it under /loopat/home/<user> instead of host's actual homedir so
@@ -394,6 +394,9 @@ export async function buildPodmanCreateArgs(opts: ContainerOptions): Promise<str
394
394
 
395
395
  const args: string[] = [
396
396
  "--name", containerName(opts.loopId),
397
+ // Self-heal a stale name collision (orphan with our name from a crash) so a
398
+ // recreate doesn't loop on "name already in use" → 137; we own the name.
399
+ "--replace",
397
400
  "--label", `${LABEL_LOOP}=${opts.loopId}`,
398
401
  "--label", `${LABEL_WORKSPACE}=${WORKSPACE}`,
399
402
  // --userns=keep-id:uid=2000,gid=2000 maps whatever uid is running
@@ -536,6 +536,12 @@ class LoopSession {
536
536
  // Required by SDK when using permissionMode: "bypassPermissions"
537
537
  ...(this.currentPermissionMode === "bypassPermissions" ? { allowDangerouslySkipPermissions: true } : {}),
538
538
  systemPrompt: { type: "preset", preset: "claude_code", append: loopatAppend },
539
+ // Stream full subagent conversations (text + thinking) and AI-generated
540
+ // progress summaries so the inline AgentRenderer card shows real-time
541
+ // activity instead of just a spinner. AgentRenderer + childMessagesByAgentId
542
+ // on the FE side are already wired to consume these.
543
+ forwardSubagentText: true,
544
+ agentProgressSummaries: true,
539
545
  mcpServers,
540
546
  // External marketplace plugins (enabledPlugins in settings.json) are
541
547
  // resolved natively by the inner SDK now — ~/.claude/plugins/ is
@@ -1172,6 +1178,13 @@ class LoopSession {
1172
1178
  console.log(`[loop:${this.id.slice(0, 8)}] detach → viewers=${this.subscribers.size}`)
1173
1179
  }
1174
1180
 
1181
+ /** Push an arbitrary message into history + persist (no broadcast — caller
1182
+ * sends the result via another channel). Used by shell (!) commands. */
1183
+ injectHistory(msg: any) {
1184
+ this.history.push(msg)
1185
+ this.persist(msg)
1186
+ }
1187
+
1175
1188
  async sendUserText(text: string, permissionMode?: SdkPermissionMode) {
1176
1189
  updateLoopStatus(this.id, `User: ${text.slice(0, 50)}${text.length > 50 ? "..." : ""}`)
1177
1190
  if (this.generating || this.messageQueue.length > 0 || this.queueProcessing) {
@@ -1313,6 +1326,18 @@ class LoopSession {
1313
1326
  if (this.q) await this.q.interrupt().catch(() => {})
1314
1327
  }
1315
1328
 
1329
+ /** Background in-flight foreground tasks (Bash commands + subagents) so the
1330
+ * turn finalizes and the queue can drain. Returns false if there was
1331
+ * nothing to background — useful for telling the caller whether the next
1332
+ * user message will actually go through immediately. */
1333
+ async backgroundTasks(): Promise<boolean> {
1334
+ if (!this.q) return false
1335
+ return this.q.backgroundTasks().catch((e: any) => {
1336
+ console.warn(`[sdk:${this.id.slice(0, 8)}] backgroundTasks failed: ${e?.message ?? e}`)
1337
+ return false
1338
+ })
1339
+ }
1340
+
1316
1341
  getQueueLength(): number {
1317
1342
  return this.messageQueue.length
1318
1343
  }
@@ -1,4 +1,4 @@
1
- import{n as e,o as t,t as n}from"./jsx-runtime-DAYmCNe8.js";import{n as r,r as i,t as a}from"./w3c-keyname-DXh_HxYD.js";var o=t(e(),1),s=[],c=[];(()=>{let e=`lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o`.split(`,`).map(e=>e?parseInt(e,36):1);for(let t=0,n=0;t<e.length;t++)(t%2?c:s).push(n+=e[t])})();function l(e){if(e<768)return!1;for(let t=0,n=s.length;;){let r=t+n>>1;if(e<s[r])n=r;else if(e>=c[r])t=r+1;else return!0;if(t==n)return!1}}function u(e){return e>=127462&&e<=127487}var d=8205;function f(e,t,n=!0,r=!0){return(n?p:m)(e,t,r)}function p(e,t,n){if(t==e.length)return t;t&&g(e.charCodeAt(t))&&_(e.charCodeAt(t-1))&&t--;let r=h(e,t);for(t+=v(r);t<e.length;){let i=h(e,t);if(r==d||i==d||n&&l(i))t+=v(i),r=i;else if(u(i)){let n=0,r=t-2;for(;r>=0&&u(h(e,r));)n++,r-=2;if(n%2==0)break;t+=2}else break}return t}function m(e,t,n){for(;t>0;){let r=p(e,t-2,n);if(r<t)return r;t--}return 0}function h(e,t){let n=e.charCodeAt(t);if(!_(n)||t+1==e.length)return n;let r=e.charCodeAt(t+1);return g(r)?(n-55296<<10)+(r-56320)+65536:n}function g(e){return e>=56320&&e<57344}function _(e){return e>=55296&&e<56320}function v(e){return e<65536?1:2}var y=class e{lineAt(e){if(e<0||e>this.length)throw RangeError(`Invalid position ${e} in document of length ${this.length}`);return this.lineInner(e,!1,1,0)}line(e){if(e<1||e>this.lines)throw RangeError(`Invalid line number ${e} in ${this.lines}-line document`);return this.lineInner(e,!0,1,0)}replace(e,t,n){[e,t]=w(this,e,t);let r=[];return this.decompose(0,e,r,2),n.length&&n.decompose(0,n.length,r,3),this.decompose(t,this.length,r,1),x.from(r,this.length-(t-e)+n.length)}append(e){return this.replace(this.length,this.length,e)}slice(e,t=this.length){[e,t]=w(this,e,t);let n=[];return this.decompose(e,t,n,0),x.from(n,t-e)}eq(e){if(e==this)return!0;if(e.length!=this.length||e.lines!=this.lines)return!1;let t=this.scanIdentical(e,1),n=this.length-this.scanIdentical(e,-1),r=new C(this),i=new C(e);for(let e=t,a=t;;){if(r.next(e),i.next(e),e=0,r.lineBreak!=i.lineBreak||r.done!=i.done||r.value!=i.value)return!1;if(a+=r.value.length,r.done||a>=n)return!0}}iter(e=1){return new C(this,e)}iterRange(e,t=this.length){return new ne(this,e,t)}iterLines(e,t){let n;if(e==null)n=this.iter();else{t??=this.lines+1;let r=this.line(e).from;n=this.iterRange(r,Math.max(r,t==this.lines+1?this.length:t<=1?0:this.line(t-1).to))}return new re(n)}toString(){return this.sliceString(0)}toJSON(){let e=[];return this.flatten(e),e}constructor(){}static of(t){if(t.length==0)throw RangeError(`A document must have at least one line`);return t.length==1&&!t[0]?e.empty:t.length<=32?new b(t):x.from(b.split(t,[]))}},b=class e extends y{constructor(e,t=ee(e)){super(),this.text=e,this.length=t}get lines(){return this.text.length}get children(){return null}lineInner(e,t,n,r){for(let i=0;;i++){let a=this.text[i],o=r+a.length;if((t?n:o)>=e)return new ie(r,o,n,a);r=o+1,n++}}decompose(t,n,r,i){let a=t<=0&&n>=this.length?this:new e(S(this.text,t,n),Math.min(n,this.length)-Math.max(0,t));if(i&1){let t=r.pop(),n=te(a.text,t.text.slice(),0,a.length);if(n.length<=32)r.push(new e(n,t.length+a.length));else{let t=n.length>>1;r.push(new e(n.slice(0,t)),new e(n.slice(t)))}}else r.push(a)}replace(t,n,r){if(!(r instanceof e))return super.replace(t,n,r);[t,n]=w(this,t,n);let i=te(this.text,te(r.text,S(this.text,0,t)),n),a=this.length+r.length-(n-t);return i.length<=32?new e(i,a):x.from(e.split(i,[]),a)}sliceString(e,t=this.length,n=`
1
+ import{i as e}from"./chunk-62oNxeRG.js";import{n as t,t as n}from"./jsx-runtime-ZP0XCtgh.js";import{n as r,r as i,t as a}from"./w3c-keyname-BoNxyEq0.js";var o=e(t(),1),s=[],c=[];(()=>{let e=`lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o`.split(`,`).map(e=>e?parseInt(e,36):1);for(let t=0,n=0;t<e.length;t++)(t%2?c:s).push(n+=e[t])})();function l(e){if(e<768)return!1;for(let t=0,n=s.length;;){let r=t+n>>1;if(e<s[r])n=r;else if(e>=c[r])t=r+1;else return!0;if(t==n)return!1}}function u(e){return e>=127462&&e<=127487}var d=8205;function f(e,t,n=!0,r=!0){return(n?p:m)(e,t,r)}function p(e,t,n){if(t==e.length)return t;t&&g(e.charCodeAt(t))&&_(e.charCodeAt(t-1))&&t--;let r=h(e,t);for(t+=v(r);t<e.length;){let i=h(e,t);if(r==d||i==d||n&&l(i))t+=v(i),r=i;else if(u(i)){let n=0,r=t-2;for(;r>=0&&u(h(e,r));)n++,r-=2;if(n%2==0)break;t+=2}else break}return t}function m(e,t,n){for(;t>0;){let r=p(e,t-2,n);if(r<t)return r;t--}return 0}function h(e,t){let n=e.charCodeAt(t);if(!_(n)||t+1==e.length)return n;let r=e.charCodeAt(t+1);return g(r)?(n-55296<<10)+(r-56320)+65536:n}function g(e){return e>=56320&&e<57344}function _(e){return e>=55296&&e<56320}function v(e){return e<65536?1:2}var y=class e{lineAt(e){if(e<0||e>this.length)throw RangeError(`Invalid position ${e} in document of length ${this.length}`);return this.lineInner(e,!1,1,0)}line(e){if(e<1||e>this.lines)throw RangeError(`Invalid line number ${e} in ${this.lines}-line document`);return this.lineInner(e,!0,1,0)}replace(e,t,n){[e,t]=w(this,e,t);let r=[];return this.decompose(0,e,r,2),n.length&&n.decompose(0,n.length,r,3),this.decompose(t,this.length,r,1),x.from(r,this.length-(t-e)+n.length)}append(e){return this.replace(this.length,this.length,e)}slice(e,t=this.length){[e,t]=w(this,e,t);let n=[];return this.decompose(e,t,n,0),x.from(n,t-e)}eq(e){if(e==this)return!0;if(e.length!=this.length||e.lines!=this.lines)return!1;let t=this.scanIdentical(e,1),n=this.length-this.scanIdentical(e,-1),r=new C(this),i=new C(e);for(let e=t,a=t;;){if(r.next(e),i.next(e),e=0,r.lineBreak!=i.lineBreak||r.done!=i.done||r.value!=i.value)return!1;if(a+=r.value.length,r.done||a>=n)return!0}}iter(e=1){return new C(this,e)}iterRange(e,t=this.length){return new ne(this,e,t)}iterLines(e,t){let n;if(e==null)n=this.iter();else{t??=this.lines+1;let r=this.line(e).from;n=this.iterRange(r,Math.max(r,t==this.lines+1?this.length:t<=1?0:this.line(t-1).to))}return new re(n)}toString(){return this.sliceString(0)}toJSON(){let e=[];return this.flatten(e),e}constructor(){}static of(t){if(t.length==0)throw RangeError(`A document must have at least one line`);return t.length==1&&!t[0]?e.empty:t.length<=32?new b(t):x.from(b.split(t,[]))}},b=class e extends y{constructor(e,t=ee(e)){super(),this.text=e,this.length=t}get lines(){return this.text.length}get children(){return null}lineInner(e,t,n,r){for(let i=0;;i++){let a=this.text[i],o=r+a.length;if((t?n:o)>=e)return new ie(r,o,n,a);r=o+1,n++}}decompose(t,n,r,i){let a=t<=0&&n>=this.length?this:new e(S(this.text,t,n),Math.min(n,this.length)-Math.max(0,t));if(i&1){let t=r.pop(),n=te(a.text,t.text.slice(),0,a.length);if(n.length<=32)r.push(new e(n,t.length+a.length));else{let t=n.length>>1;r.push(new e(n.slice(0,t)),new e(n.slice(t)))}}else r.push(a)}replace(t,n,r){if(!(r instanceof e))return super.replace(t,n,r);[t,n]=w(this,t,n);let i=te(this.text,te(r.text,S(this.text,0,t)),n),a=this.length+r.length-(n-t);return i.length<=32?new e(i,a):x.from(e.split(i,[]),a)}sliceString(e,t=this.length,n=`
2
2
  `){[e,t]=w(this,e,t);let r=``;for(let i=0,a=0;i<=t&&a<this.text.length;a++){let o=this.text[a],s=i+o.length;i>e&&a&&(r+=n),e<s&&t>i&&(r+=o.slice(Math.max(0,e-i),t-i)),i=s+1}return r}flatten(e){for(let t of this.text)e.push(t)}scanIdentical(){return 0}static split(t,n){let r=[],i=-1;for(let a of t)r.push(a),i+=a.length+1,r.length==32&&(n.push(new e(r,i)),r=[],i=-1);return i>-1&&n.push(new e(r,i)),n}},x=class e extends y{constructor(e,t){super(),this.children=e,this.length=t,this.lines=0;for(let t of e)this.lines+=t.lines}lineInner(e,t,n,r){for(let i=0;;i++){let a=this.children[i],o=r+a.length,s=n+a.lines-1;if((t?s:o)>=e)return a.lineInner(e,t,n,r);r=o+1,n=s+1}}decompose(e,t,n,r){for(let i=0,a=0;a<=t&&i<this.children.length;i++){let o=this.children[i],s=a+o.length;if(e<=s&&t>=a){let i=r&(a<=e|(s>=t?2:0));a>=e&&s<=t&&!i?n.push(o):o.decompose(e-a,t-a,n,i)}a=s+1}}replace(t,n,r){if([t,n]=w(this,t,n),r.lines<this.lines)for(let i=0,a=0;i<this.children.length;i++){let o=this.children[i],s=a+o.length;if(t>=a&&n<=s){let c=o.replace(t-a,n-a,r),l=this.lines-o.lines+c.lines;if(c.lines<l>>4&&c.lines>l>>6){let a=this.children.slice();return a[i]=c,new e(a,this.length-(n-t)+r.length)}return super.replace(a,s,c)}a=s+1}return super.replace(t,n,r)}sliceString(e,t=this.length,n=`
3
3
  `){[e,t]=w(this,e,t);let r=``;for(let i=0,a=0;i<this.children.length&&a<=t;i++){let o=this.children[i],s=a+o.length;a>e&&i&&(r+=n),e<s&&t>a&&(r+=o.sliceString(e-a,t-a,n)),a=s+1}return r}flatten(e){for(let t of this.children)t.flatten(e)}scanIdentical(t,n){if(!(t instanceof e))return 0;let r=0,[i,a,o,s]=n>0?[0,0,this.children.length,t.children.length]:[this.children.length-1,t.children.length-1,-1,-1];for(;;i+=n,a+=n){if(i==o||a==s)return r;let e=this.children[i],c=t.children[a];if(e!=c)return r+e.scanIdentical(c,n);r+=e.length+1}}static from(t,n=t.reduce((e,t)=>e+t.length+1,-1)){let r=0;for(let e of t)r+=e.lines;if(r<32){let e=[];for(let n of t)n.flatten(e);return new b(e,n)}let i=Math.max(32,r>>5),a=i<<1,o=i>>1,s=[],c=0,l=-1,u=[];function d(t){let n;if(t.lines>a&&t instanceof e)for(let e of t.children)d(e);else t.lines>o&&(c>o||!c)?(f(),s.push(t)):t instanceof b&&c&&(n=u[u.length-1])instanceof b&&t.lines+n.lines<=32?(c+=t.lines,l+=t.length+1,u[u.length-1]=new b(n.text.concat(t.text),n.length+1+t.length)):(c+t.lines>i&&f(),c+=t.lines,l+=t.length+1,u.push(t))}function f(){c!=0&&(s.push(u.length==1?u[0]:e.from(u,l)),l=-1,c=u.length=0)}for(let e of t)d(e);return f(),s.length==1?s[0]:new e(s,n)}};y.empty=new b([``],0);function ee(e){let t=-1;for(let n of e)t+=n.length+1;return t}function te(e,t,n=0,r=1e9){for(let i=0,a=0,o=!0;a<e.length&&i<=r;a++){let s=e[a],c=i+s.length;c>=n&&(c>r&&(s=s.slice(0,r-i)),i<n&&(s=s.slice(n-i)),o?(t[t.length-1]+=s,o=!1):t.push(s)),i=c+1}return t}function S(e,t,n){return te(e,[``],t,n)}var C=class{constructor(e,t=1){this.dir=t,this.done=!1,this.lineBreak=!1,this.value=``,this.nodes=[e],this.offsets=[t>0?1:(e instanceof b?e.text.length:e.children.length)<<1]}nextInner(e,t){for(this.done=this.lineBreak=!1;;){let n=this.nodes.length-1,r=this.nodes[n],i=this.offsets[n],a=i>>1,o=r instanceof b?r.text.length:r.children.length;if(a==(t>0?o:0)){if(n==0)return this.done=!0,this.value=``,this;t>0&&this.offsets[n-1]++,this.nodes.pop(),this.offsets.pop()}else if((i&1)==(t>0?0:1)){if(this.offsets[n]+=t,e==0)return this.lineBreak=!0,this.value=`
4
4
  `,this;e--}else if(r instanceof b){let i=r.text[a+(t<0?-1:0)];if(this.offsets[n]+=t,i.length>Math.max(0,e))return this.value=e==0?i:t>0?i.slice(e):i.slice(0,i.length-e),this;e-=i.length}else{let i=r.children[a+(t<0?-1:0)];e>i.length?(e-=i.length,this.offsets[n]+=t):(t<0&&this.offsets[n]--,this.nodes.push(i),this.offsets.push(t>0?1:(i instanceof b?i.text.length:i.children.length)<<1))}}}next(e=0){return e<0&&(this.nextInner(-e,-this.dir),e=this.value.length),this.nextInner(e,this.dir)}},ne=class{constructor(e,t,n){this.value=``,this.done=!1,this.cursor=new C(e,t>n?-1:1),this.pos=t>n?e.length:0,this.from=Math.min(t,n),this.to=Math.max(t,n)}nextInner(e,t){if(t<0?this.pos<=this.from:this.pos>=this.to)return this.value=``,this.done=!0,this;e+=Math.max(0,t<0?this.pos-this.to:this.from-this.pos);let n=t<0?this.pos-this.from:this.to-this.pos;e>n&&(e=n),n-=e;let{value:r}=this.cursor.next(e);return this.pos+=(r.length+e)*t,this.value=r.length<=n?r:t<0?r.slice(r.length-n):r.slice(0,n),this.done=!this.value,this}next(e=0){return e<0?e=Math.max(e,this.from-this.pos):e>0&&(e=Math.min(e,this.to-this.pos)),this.nextInner(e,this.cursor.dir)}get lineBreak(){return this.cursor.lineBreak&&this.value!=``}},re=class{constructor(e){this.inner=e,this.afterBreak=!0,this.value=``,this.done=!1}next(e=0){let{done:t,lineBreak:n,value:r}=this.inner.next(e);return t&&this.afterBreak?(this.value=``,this.afterBreak=!1):t?(this.done=!0,this.value=``):n?this.afterBreak?this.value=``:(this.afterBreak=!0,this.next()):(this.value=r,this.afterBreak=!1),this}get lineBreak(){return!1}};typeof Symbol<`u`&&(y.prototype[Symbol.iterator]=function(){return this.iter()},C.prototype[Symbol.iterator]=ne.prototype[Symbol.iterator]=re.prototype[Symbol.iterator]=function(){return this});var ie=class{constructor(e,t,n,r){this.from=e,this.to=t,this.number=n,this.text=r}get length(){return this.to-this.from}};function w(e,t,n){return t=Math.max(0,Math.min(e.length,t)),[t,Math.max(t,Math.min(e.length,n))]}function T(e,t,n=!0,r=!0){return f(e,t,n,r)}function ae(e){return e>=56320&&e<57344}function oe(e){return e>=55296&&e<56320}function se(e,t){let n=e.charCodeAt(t);if(!oe(n)||t+1==e.length)return n;let r=e.charCodeAt(t+1);return ae(r)?(n-55296<<10)+(r-56320)+65536:n}function ce(e){return e<=65535?String.fromCharCode(e):(e-=65536,String.fromCharCode((e>>10)+55296,(e&1023)+56320))}function le(e){return e<65536?1:2}var ue=/\r\n?|\n/,de=(function(e){return e[e.Simple=0]=`Simple`,e[e.TrackDel=1]=`TrackDel`,e[e.TrackBefore=2]=`TrackBefore`,e[e.TrackAfter=3]=`TrackAfter`,e})(de||={}),fe=class e{constructor(e){this.sections=e}get length(){let e=0;for(let t=0;t<this.sections.length;t+=2)e+=this.sections[t];return e}get newLength(){let e=0;for(let t=0;t<this.sections.length;t+=2){let n=this.sections[t+1];e+=n<0?this.sections[t]:n}return e}get empty(){return this.sections.length==0||this.sections.length==2&&this.sections[1]<0}iterGaps(e){for(let t=0,n=0,r=0;t<this.sections.length;){let i=this.sections[t++],a=this.sections[t++];a<0?(e(n,r,i),r+=i):r+=a,n+=i}}iterChangedRanges(e,t=!1){ge(this,e,t)}get invertedDesc(){let t=[];for(let e=0;e<this.sections.length;){let n=this.sections[e++],r=this.sections[e++];r<0?t.push(n,r):t.push(r,n)}return new e(t)}composeDesc(e){return this.empty?e:e.empty?this:ve(this,e)}mapDesc(e,t=!1){return e.empty?this:_e(this,e,t)}mapPos(e,t=-1,n=de.Simple){let r=0,i=0;for(let a=0;a<this.sections.length;){let o=this.sections[a++],s=this.sections[a++],c=r+o;if(s<0){if(c>e)return i+(e-r);i+=o}else{if(n!=de.Simple&&c>=e&&(n==de.TrackDel&&r<e&&c>e||n==de.TrackBefore&&r<e||n==de.TrackAfter&&c>e))return null;if(c>e||c==e&&t<0&&!o)return e==r||t<0?i:i+s;i+=s}r=c}if(e>r)throw RangeError(`Position ${e} is out of range for changeset of length ${r}`);return i}touchesRange(e,t=e){for(let n=0,r=0;n<this.sections.length&&r<=t;){let i=this.sections[n++],a=this.sections[n++],o=r+i;if(a>=0&&r<=t&&o>=e)return r<e&&o>t?`cover`:!0;r=o}return!1}toString(){let e=``;for(let t=0;t<this.sections.length;){let n=this.sections[t++],r=this.sections[t++];e+=(e?` `:``)+n+(r>=0?`:`+r:``)}return e}toJSON(){return this.sections}static fromJSON(t){if(!Array.isArray(t)||t.length%2||t.some(e=>typeof e!=`number`))throw RangeError(`Invalid JSON representation of ChangeDesc`);return new e(t)}static create(t){return new e(t)}},pe=class e extends fe{constructor(e,t){super(e),this.inserted=t}apply(e){if(this.length!=e.length)throw RangeError(`Applying change set to a document with the wrong length`);return ge(this,(t,n,r,i,a)=>e=e.replace(r,r+(n-t),a),!1),e}mapDesc(e,t=!1){return _e(this,e,t,!0)}invert(t){let n=this.sections.slice(),r=[];for(let e=0,i=0;e<n.length;e+=2){let a=n[e],o=n[e+1];if(o>=0){n[e]=o,n[e+1]=a;let s=e>>1;for(;r.length<s;)r.push(y.empty);r.push(a?t.slice(i,i+a):y.empty)}i+=a}return new e(n,r)}compose(e){return this.empty?e:e.empty?this:ve(this,e,!0)}map(e,t=!1){return e.empty?this:_e(this,e,t,!0)}iterChanges(e,t=!1){ge(this,e,t)}get desc(){return fe.create(this.sections)}filter(t){let n=[],r=[],i=[],a=new ye(this);done:for(let e=0,o=0;;){let s=e==t.length?1e9:t[e++];for(;o<s||o==s&&a.len==0;){if(a.done)break done;let e=Math.min(a.len,s-o);me(i,e,-1);let t=a.ins==-1?-1:a.off==0?a.ins:0;me(n,e,t),t>0&&he(r,n,a.text),a.forward(e),o+=e}let c=t[e++];for(;o<c;){if(a.done)break done;let e=Math.min(a.len,c-o);me(n,e,-1),me(i,e,a.ins==-1?-1:a.off==0?a.ins:0),a.forward(e),o+=e}}return{changes:new e(n,r),filtered:fe.create(i)}}toJSON(){let e=[];for(let t=0;t<this.sections.length;t+=2){let n=this.sections[t],r=this.sections[t+1];r<0?e.push(n):r==0?e.push([n]):e.push([n].concat(this.inserted[t>>1].toJSON()))}return e}static of(t,n,r){let i=[],a=[],o=0,s=null;function c(t=!1){if(!t&&!i.length)return;o<n&&me(i,n-o,-1);let r=new e(i,a);s=s?s.compose(r.map(s)):r,i=[],a=[],o=0}function l(t){if(Array.isArray(t))for(let e of t)l(e);else if(t instanceof e){if(t.length!=n)throw RangeError(`Mismatched change set length (got ${t.length}, expected ${n})`);c(),s=s?s.compose(t.map(s)):t}else{let{from:e,to:s=e,insert:l}=t;if(e>s||e<0||s>n)throw RangeError(`Invalid change range ${e} to ${s} (in doc of length ${n})`);let u=l?typeof l==`string`?y.of(l.split(r||ue)):l:y.empty,d=u.length;if(e==s&&d==0)return;e<o&&c(),e>o&&me(i,e-o,-1),me(i,s-e,d),he(a,i,u),o=s}}return l(t),c(!s),s}static empty(t){return new e(t?[t,-1]:[],[])}static fromJSON(t){if(!Array.isArray(t))throw RangeError(`Invalid JSON representation of ChangeSet`);let n=[],r=[];for(let e=0;e<t.length;e++){let i=t[e];if(typeof i==`number`)n.push(i,-1);else if(!Array.isArray(i)||typeof i[0]!=`number`||i.some((e,t)=>t&&typeof e!=`string`))throw RangeError(`Invalid JSON representation of ChangeSet`);else if(i.length==1)n.push(i[0],0);else{for(;r.length<e;)r.push(y.empty);r[e]=y.of(i.slice(1)),n.push(i[0],r[e].length)}}return new e(n,r)}static createSet(t,n){return new e(t,n)}};function me(e,t,n,r=!1){if(t==0&&n<=0)return;let i=e.length-2;i>=0&&n<=0&&n==e[i+1]?e[i]+=t:i>=0&&t==0&&e[i]==0?e[i+1]+=n:r?(e[i]+=t,e[i+1]+=n):e.push(t,n)}function he(e,t,n){if(n.length==0)return;let r=t.length-2>>1;if(r<e.length)e[e.length-1]=e[e.length-1].append(n);else{for(;e.length<r;)e.push(y.empty);e.push(n)}}function ge(e,t,n){let r=e.inserted;for(let i=0,a=0,o=0;o<e.sections.length;){let s=e.sections[o++],c=e.sections[o++];if(c<0)i+=s,a+=s;else{let l=i,u=a,d=y.empty;for(;l+=s,u+=c,c&&r&&(d=d.append(r[o-2>>1])),!(n||o==e.sections.length||e.sections[o+1]<0);)s=e.sections[o++],c=e.sections[o++];t(i,l,a,u,d),i=l,a=u}}}function _e(e,t,n,r=!1){let i=[],a=r?[]:null,o=new ye(e),s=new ye(t);for(let e=-1;;)if(o.done&&s.len||s.done&&o.len)throw Error(`Mismatched change set lengths`);else if(o.ins==-1&&s.ins==-1){let e=Math.min(o.len,s.len);me(i,e,-1),o.forward(e),s.forward(e)}else if(s.ins>=0&&(o.ins<0||e==o.i||o.off==0&&(s.len<o.len||s.len==o.len&&!n))){let t=s.len;for(me(i,s.ins,-1);t;){let n=Math.min(o.len,t);o.ins>=0&&e<o.i&&o.len<=n&&(me(i,0,o.ins),a&&he(a,i,o.text),e=o.i),o.forward(n),t-=n}s.next()}else if(o.ins>=0){let t=0,n=o.len;for(;n;)if(s.ins==-1){let e=Math.min(n,s.len);t+=e,n-=e,s.forward(e)}else if(s.ins==0&&s.len<n)n-=s.len,s.next();else break;me(i,t,e<o.i?o.ins:0),a&&e<o.i&&he(a,i,o.text),e=o.i,o.forward(o.len-n)}else if(o.done&&s.done)return a?pe.createSet(i,a):fe.create(i);else throw Error(`Mismatched change set lengths`)}function ve(e,t,n=!1){let r=[],i=n?[]:null,a=new ye(e),o=new ye(t);for(let e=!1;;)if(a.done&&o.done)return i?pe.createSet(r,i):fe.create(r);else if(a.ins==0)me(r,a.len,0,e),a.next();else if(o.len==0&&!o.done)me(r,0,o.ins,e),i&&he(i,r,o.text),o.next();else if(a.done||o.done)throw Error(`Mismatched change set lengths`);else{let t=Math.min(a.len2,o.len),n=r.length;if(a.ins==-1){let n=o.ins==-1?-1:o.off?0:o.ins;me(r,t,n,e),i&&n&&he(i,r,o.text)}else o.ins==-1?(me(r,a.off?0:a.len,t,e),i&&he(i,r,a.textBit(t))):(me(r,a.off?0:a.len,o.off?0:o.ins,e),i&&!o.off&&he(i,r,o.text));e=(a.ins>t||o.ins>=0&&o.len>t)&&(e||r.length>n),a.forward2(t),o.forward(t)}}var ye=class{constructor(e){this.set=e,this.i=0,this.next()}next(){let{sections:e}=this.set;this.i<e.length?(this.len=e[this.i++],this.ins=e[this.i++]):(this.len=0,this.ins=-2),this.off=0}get done(){return this.ins==-2}get len2(){return this.ins<0?this.len:this.ins}get text(){let{inserted:e}=this.set,t=this.i-2>>1;return t>=e.length?y.empty:e[t]}textBit(e){let{inserted:t}=this.set,n=this.i-2>>1;return n>=t.length&&!e?y.empty:t[n].slice(this.off,e==null?void 0:this.off+e)}forward(e){e==this.len?this.next():(this.len-=e,this.off+=e)}forward2(e){this.ins==-1?this.forward(e):e==this.ins?this.next():(this.ins-=e,this.off+=e)}},be=class e{constructor(e,t,n){this.from=e,this.to=t,this.flags=n}get anchor(){return this.flags&32?this.to:this.from}get head(){return this.flags&32?this.from:this.to}get empty(){return this.from==this.to}get assoc(){return this.flags&8?-1:this.flags&16?1:0}get bidiLevel(){let e=this.flags&7;return e==7?null:e}get goalColumn(){let e=this.flags>>6;return e==16777215?void 0:e}map(t,n=-1){let r,i;return this.empty?r=i=t.mapPos(this.from,n):(r=t.mapPos(this.from,1),i=t.mapPos(this.to,-1)),r==this.from&&i==this.to?this:new e(r,i,this.flags)}extend(e,t=e,n=0){if(e<=this.anchor&&t>=this.anchor)return E.range(e,t,void 0,void 0,n);let r=Math.abs(e-this.anchor)>Math.abs(t-this.anchor)?e:t;return E.range(this.anchor,r,void 0,void 0,n)}eq(e,t=!1){return this.anchor==e.anchor&&this.head==e.head&&this.goalColumn==e.goalColumn&&(!t||!this.empty||this.assoc==e.assoc)}toJSON(){return{anchor:this.anchor,head:this.head}}static fromJSON(e){if(!e||typeof e.anchor!=`number`||typeof e.head!=`number`)throw RangeError(`Invalid JSON representation for SelectionRange`);return E.range(e.anchor,e.head)}static create(t,n,r){return new e(t,n,r)}},E=class e{constructor(e,t){this.ranges=e,this.mainIndex=t}map(t,n=-1){return t.empty?this:e.create(this.ranges.map(e=>e.map(t,n)),this.mainIndex)}eq(e,t=!1){if(this.ranges.length!=e.ranges.length||this.mainIndex!=e.mainIndex)return!1;for(let n=0;n<this.ranges.length;n++)if(!this.ranges[n].eq(e.ranges[n],t))return!1;return!0}get main(){return this.ranges[this.mainIndex]}asSingle(){return this.ranges.length==1?this:new e([this.main],0)}addRange(t,n=!0){return e.create([t].concat(this.ranges),n?0:this.mainIndex+1)}replaceRange(t,n=this.mainIndex){let r=this.ranges.slice();return r[n]=t,e.create(r,this.mainIndex)}toJSON(){return{ranges:this.ranges.map(e=>e.toJSON()),main:this.mainIndex}}static fromJSON(t){if(!t||!Array.isArray(t.ranges)||typeof t.main!=`number`||t.main>=t.ranges.length)throw RangeError(`Invalid JSON representation for EditorSelection`);return new e(t.ranges.map(e=>be.fromJSON(e)),t.main)}static single(t,n=t){return new e([e.range(t,n)],0)}static create(t,n=0){if(t.length==0)throw RangeError(`A selection needs at least one range`);for(let r=0,i=0;i<t.length;i++){let a=t[i];if(a.empty?a.from<=r:a.from<r)return e.normalized(t.slice(),n);r=a.to}return new e(t,n)}static cursor(e,t=0,n,r){return be.create(e,e,(t==0?0:t<0?8:16)|(n==null?7:Math.min(6,n))|(r??16777215)<<6)}static range(e,t,n,r,i){let a=(n??16777215)<<6|(r==null?7:Math.min(6,r));return!i&&e!=t&&(i=t<e?1:-1),t<e?be.create(t,e,48|a):be.create(e,t,(i?i<0?8:16:0)|a)}static normalized(t,n=0){let r=t[n];t.sort((e,t)=>e.from-t.from),n=t.indexOf(r);for(let r=1;r<t.length;r++){let i=t[r],a=t[r-1];if(i.empty?i.from<=a.to:i.from<a.to){let o=a.from,s=Math.max(i.to,a.to);r<=n&&n--,t.splice(--r,2,i.anchor>i.head?e.range(s,o):e.range(o,s))}}return new e(t,n)}};function xe(e,t){for(let n of e.ranges)if(n.to>t)throw RangeError(`Selection points outside of document`)}var Se=0,D=class e{constructor(e,t,n,r,i){this.combine=e,this.compareInput=t,this.compare=n,this.isStatic=r,this.id=Se++,this.default=e([]),this.extensions=typeof i==`function`?i(this):i}get reader(){return this}static define(t={}){return new e(t.combine||(e=>e),t.compareInput||((e,t)=>e===t),t.compare||(t.combine?(e,t)=>e===t:Ce),!!t.static,t.enables)}of(e){return new we([],this,0,e)}compute(e,t){if(this.isStatic)throw Error(`Can't compute a static facet`);return new we(e,this,1,t)}computeN(e,t){if(this.isStatic)throw Error(`Can't compute a static facet`);return new we(e,this,2,t)}from(e,t){return t||=e=>e,this.compute([e],n=>t(n.field(e)))}};function Ce(e,t){return e==t||e.length==t.length&&e.every((e,n)=>e===t[n])}var we=class{constructor(e,t,n,r){this.dependencies=e,this.facet=t,this.type=n,this.value=r,this.id=Se++}dynamicSlot(e){let t=this.value,n=this.facet.compareInput,r=this.id,i=e[r]>>1,a=this.type==2,o=!1,s=!1,c=[];for(let t of this.dependencies)t==`doc`?o=!0:t==`selection`?s=!0:(e[t.id]??1)&1||c.push(e[t.id]);return{create(e){return e.values[i]=t(e),1},update(e,r){if(o&&r.docChanged||s&&(r.docChanged||r.selection)||Ee(e,c)){let r=t(e);if(a?!Te(r,e.values[i],n):!n(r,e.values[i]))return e.values[i]=r,1}return 0},reconfigure:(e,o)=>{let s,c=o.config.address[r];if(c!=null){let r=ze(o,c);if(this.dependencies.every(t=>t instanceof D?o.facet(t)===e.facet(t):t instanceof ke?o.field(t,!1)==e.field(t,!1):!0)||(a?Te(s=t(e),r,n):n(s=t(e),r)))return e.values[i]=r,0}else s=t(e);return e.values[i]=s,1}}}};function Te(e,t,n){if(e.length!=t.length)return!1;for(let r=0;r<e.length;r++)if(!n(e[r],t[r]))return!1;return!0}function Ee(e,t){let n=!1;for(let r of t)Re(e,r)&1&&(n=!0);return n}function De(e,t,n){let r=n.map(t=>e[t.id]),i=n.map(e=>e.type),a=r.filter(e=>!(e&1)),o=e[t.id]>>1;function s(e){let n=[];for(let t=0;t<r.length;t++){let a=ze(e,r[t]);if(i[t]==2)for(let e of a)n.push(e);else n.push(a)}return t.combine(n)}return{create(e){for(let t of r)Re(e,t);return e.values[o]=s(e),1},update(e,n){if(!Ee(e,a))return 0;let r=s(e);return t.compare(r,e.values[o])?0:(e.values[o]=r,1)},reconfigure(e,i){let a=Ee(e,r),c=i.config.facets[t.id],l=i.facet(t);if(c&&!a&&Ce(n,c))return e.values[o]=l,0;let u=s(e);return t.compare(u,l)?(e.values[o]=l,0):(e.values[o]=u,1)}}}var Oe=D.define({static:!0}),ke=class e{constructor(e,t,n,r,i){this.id=e,this.createF=t,this.updateF=n,this.compareF=r,this.spec=i,this.provides=void 0}static define(t){let n=new e(Se++,t.create,t.update,t.compare||((e,t)=>e===t),t);return t.provide&&(n.provides=t.provide(n)),n}create(e){return(e.facet(Oe).find(e=>e.field==this)?.create||this.createF)(e)}slot(e){let t=e[this.id]>>1;return{create:e=>(e.values[t]=this.create(e),1),update:(e,n)=>{let r=e.values[t],i=this.updateF(r,n);return this.compareF(r,i)?0:(e.values[t]=i,1)},reconfigure:(e,n)=>{let r=e.facet(Oe),i=n.facet(Oe),a;return(a=r.find(e=>e.field==this))&&a!=i.find(e=>e.field==this)?(e.values[t]=a.create(e),1):n.config.address[this.id]==null?(e.values[t]=this.create(e),1):(e.values[t]=n.field(this),0)}}}init(e){return[this,Oe.of({field:this,create:e})]}get extension(){return this}},Ae={lowest:4,low:3,default:2,high:1,highest:0};function je(e){return t=>new Ne(t,e)}var Me={highest:je(Ae.highest),high:je(Ae.high),default:je(Ae.default),low:je(Ae.low),lowest:je(Ae.lowest)},Ne=class{constructor(e,t){this.inner=e,this.prec=t}},Pe=class e{of(e){return new Fe(this,e)}reconfigure(t){return e.reconfigure.of({compartment:this,extension:t})}get(e){return e.config.compartments.get(this)}},Fe=class{constructor(e,t){this.compartment=e,this.inner=t}},Ie=class e{constructor(e,t,n,r,i,a){for(this.base=e,this.compartments=t,this.dynamicSlots=n,this.address=r,this.staticValues=i,this.facets=a,this.statusTemplate=[];this.statusTemplate.length<n.length;)this.statusTemplate.push(0)}staticFacet(e){let t=this.address[e.id];return t==null?e.default:this.staticValues[t>>1]}static resolve(t,n,r){let i=[],a=Object.create(null),o=new Map;for(let e of Le(t,n,o))e instanceof ke?i.push(e):(a[e.facet.id]||(a[e.facet.id]=[])).push(e);let s=Object.create(null),c=[],l=[];for(let e of i)s[e.id]=l.length<<1,l.push(t=>e.slot(t));let u=r?.config.facets;for(let e in a){let t=a[e],n=t[0].facet,i=u&&u[e]||[];if(t.every(e=>e.type==0))if(s[n.id]=c.length<<1|1,Ce(i,t))c.push(r.facet(n));else{let e=n.combine(t.map(e=>e.value));c.push(r&&n.compare(e,r.facet(n))?r.facet(n):e)}else{for(let e of t)e.type==0?(s[e.id]=c.length<<1|1,c.push(e.value)):(s[e.id]=l.length<<1,l.push(t=>e.dynamicSlot(t)));s[n.id]=l.length<<1,l.push(e=>De(e,n,t))}}return new e(t,o,l.map(e=>e(s)),s,c,a)}};function Le(e,t,n){let r=[[],[],[],[],[]],i=new Map;function a(e,o){let s=i.get(e);if(s!=null){if(s<=o)return;let t=r[s].indexOf(e);t>-1&&r[s].splice(t,1),e instanceof Fe&&n.delete(e.compartment)}if(i.set(e,o),Array.isArray(e))for(let t of e)a(t,o);else if(e instanceof Fe){if(n.has(e.compartment))throw RangeError(`Duplicate use of compartment in extensions`);let r=t.get(e.compartment)||e.inner;n.set(e.compartment,r),a(r,o)}else if(e instanceof Ne)a(e.inner,e.prec);else if(e instanceof ke)r[o].push(e),e.provides&&a(e.provides,o);else if(e instanceof we)r[o].push(e),e.facet.extensions&&a(e.facet.extensions,Ae.default);else{let t=e.extension;if(!t)throw Error(`Unrecognized extension value in extension set (${e}). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks.`);a(t,o)}}return a(e,Ae.default),r.reduce((e,t)=>e.concat(t))}function Re(e,t){if(t&1)return 2;let n=t>>1,r=e.status[n];if(r==4)throw Error(`Cyclic dependency between fields and/or facets`);if(r&2)return r;e.status[n]=4;let i=e.computeSlot(e,e.config.dynamicSlots[n]);return e.status[n]=2|i}function ze(e,t){return t&1?e.config.staticValues[t>>1]:e.values[t>>1]}var Be=D.define(),Ve=D.define({combine:e=>e.some(e=>e),static:!0}),He=D.define({combine:e=>e.length?e[0]:void 0,static:!0}),Ue=D.define(),We=D.define(),Ge=D.define(),Ke=D.define({combine:e=>e.length?e[0]:!1}),qe=class{constructor(e,t){this.type=e,this.value=t}static define(){return new Je}},Je=class{of(e){return new qe(this,e)}},Ye=class{constructor(e){this.map=e}of(e){return new O(this,e)}},O=class e{constructor(e,t){this.type=e,this.value=t}map(t){let n=this.type.map(this.value,t);return n===void 0?void 0:n==this.value?this:new e(this.type,n)}is(e){return this.type==e}static define(e={}){return new Ye(e.map||(e=>e))}static mapEffects(e,t){if(!e.length)return e;let n=[];for(let r of e){let e=r.map(t);e&&n.push(e)}return n}};O.reconfigure=O.define(),O.appendConfig=O.define();var Xe=class e{constructor(t,n,r,i,a,o){this.startState=t,this.changes=n,this.selection=r,this.effects=i,this.annotations=a,this.scrollIntoView=o,this._doc=null,this._state=null,r&&xe(r,n.newLength),a.some(t=>t.type==e.time)||(this.annotations=a.concat(e.time.of(Date.now())))}static create(t,n,r,i,a,o){return new e(t,n,r,i,a,o)}get newDoc(){return this._doc||=this.changes.apply(this.startState.doc)}get newSelection(){return this.selection||this.startState.selection.map(this.changes)}get state(){return this._state||this.startState.applyTransaction(this),this._state}annotation(e){for(let t of this.annotations)if(t.type==e)return t.value}get docChanged(){return!this.changes.empty}get reconfigured(){return this.startState.config!=this.state.config}isUserEvent(t){let n=this.annotation(e.userEvent);return!!(n&&(n==t||n.length>t.length&&n.slice(0,t.length)==t&&n[t.length]==`.`))}};Xe.time=qe.define(),Xe.userEvent=qe.define(),Xe.addToHistory=qe.define(),Xe.remote=qe.define();function Ze(e,t){let n=[];for(let r=0,i=0;;){let a,o;if(r<e.length&&(i==t.length||t[i]>=e[r]))a=e[r++],o=e[r++];else if(i<t.length)a=t[i++],o=t[i++];else return n;!n.length||n[n.length-1]<a?n.push(a,o):n[n.length-1]<o&&(n[n.length-1]=o)}}function Qe(e,t,n){let r,i,a;return n?(r=t.changes,i=pe.empty(t.changes.length),a=e.changes.compose(t.changes)):(r=t.changes.map(e.changes),i=e.changes.mapDesc(t.changes,!0),a=e.changes.compose(r)),{changes:a,selection:t.selection?t.selection.map(i):e.selection?.map(r),effects:O.mapEffects(e.effects,r).concat(O.mapEffects(t.effects,i)),annotations:e.annotations.length?e.annotations.concat(t.annotations):t.annotations,scrollIntoView:e.scrollIntoView||t.scrollIntoView}}function $e(e,t,n){let r=t.selection,i=it(t.annotations);return t.userEvent&&(i=i.concat(Xe.userEvent.of(t.userEvent))),{changes:t.changes instanceof pe?t.changes:pe.of(t.changes||[],n,e.facet(He)),selection:r&&(r instanceof E?r:E.single(r.anchor,r.head)),effects:it(t.effects),annotations:i,scrollIntoView:!!t.scrollIntoView}}function et(e,t,n){let r=$e(e,t.length?t[0]:{},e.doc.length);t.length&&t[0].filter===!1&&(n=!1);for(let i=1;i<t.length;i++){t[i].filter===!1&&(n=!1);let a=!!t[i].sequential;r=Qe(r,$e(e,t[i],a?r.changes.newLength:e.doc.length),a)}let i=Xe.create(e,r.changes,r.selection,r.effects,r.annotations,r.scrollIntoView);return nt(n?tt(i):i)}function tt(e){let t=e.startState,n=!0;for(let r of t.facet(Ue)){let t=r(e);if(t===!1){n=!1;break}Array.isArray(t)&&(n=n===!0?t:Ze(n,t))}if(n!==!0){let r,i;if(n===!1)i=e.changes.invertedDesc,r=pe.empty(t.doc.length);else{let t=e.changes.filter(n);r=t.changes,i=t.filtered.mapDesc(t.changes).invertedDesc}e=Xe.create(t,r,e.selection&&e.selection.map(i),O.mapEffects(e.effects,i),e.annotations,e.scrollIntoView)}let r=t.facet(We);for(let n=r.length-1;n>=0;n--){let i=r[n](e);e=i instanceof Xe?i:Array.isArray(i)&&i.length==1&&i[0]instanceof Xe?i[0]:et(t,it(i),!1)}return e}function nt(e){let t=e.startState,n=t.facet(Ge),r=e;for(let i=n.length-1;i>=0;i--){let a=n[i](e);a&&Object.keys(a).length&&(r=Qe(r,$e(t,a,e.changes.newLength),!0))}return r==e?e:Xe.create(t,e.changes,e.selection,r.effects,r.annotations,r.scrollIntoView)}var rt=[];function it(e){return e==null?rt:Array.isArray(e)?e:[e]}var k=(function(e){return e[e.Word=0]=`Word`,e[e.Space=1]=`Space`,e[e.Other=2]=`Other`,e})(k||={}),at=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,ot;try{ot=RegExp(`[\\p{Alphabetic}\\p{Number}_]`,`u`)}catch{}function st(e){if(ot)return ot.test(e);for(let t=0;t<e.length;t++){let n=e[t];if(/\w/.test(n)||n>`€`&&(n.toUpperCase()!=n.toLowerCase()||at.test(n)))return!0}return!1}function ct(e){return t=>{if(!/\S/.test(t))return k.Space;if(st(t))return k.Word;for(let n=0;n<e.length;n++)if(t.indexOf(e[n])>-1)return k.Word;return k.Other}}var A=class e{constructor(e,t,n,r,i,a){this.config=e,this.doc=t,this.selection=n,this.values=r,this.status=e.statusTemplate.slice(),this.computeSlot=i,a&&(a._state=this);for(let e=0;e<this.config.dynamicSlots.length;e++)Re(this,e<<1);this.computeSlot=null}field(e,t=!0){let n=this.config.address[e.id];if(n==null){if(t)throw RangeError(`Field is not present in this state`);return}return Re(this,n),ze(this,n)}update(...e){return et(this,e,!0)}applyTransaction(t){let n=this.config,{base:r,compartments:i}=n;for(let e of t.effects)e.is(Pe.reconfigure)?(n&&=(i=new Map,n.compartments.forEach((e,t)=>i.set(t,e)),null),i.set(e.value.compartment,e.value.extension)):e.is(O.reconfigure)?(n=null,r=e.value):e.is(O.appendConfig)&&(n=null,r=it(r).concat(e.value));let a;n?a=t.startState.values.slice():(n=Ie.resolve(r,i,this),a=new e(n,this.doc,this.selection,n.dynamicSlots.map(()=>null),(e,t)=>t.reconfigure(e,this),null).values);let o=t.startState.facet(Ve)?t.newSelection:t.newSelection.asSingle();new e(n,t.newDoc,o,a,(e,n)=>n.update(e,t),t)}replaceSelection(e){return typeof e==`string`&&(e=this.toText(e)),this.changeByRange(t=>({changes:{from:t.from,to:t.to,insert:e},range:E.cursor(t.from+e.length)}))}changeByRange(e){let t=this.selection,n=e(t.ranges[0]),r=this.changes(n.changes),i=[n.range],a=it(n.effects);for(let n=1;n<t.ranges.length;n++){let o=e(t.ranges[n]),s=this.changes(o.changes),c=s.map(r);for(let e=0;e<n;e++)i[e]=i[e].map(c);let l=r.mapDesc(s,!0);i.push(o.range.map(l)),r=r.compose(c),a=O.mapEffects(a,c).concat(O.mapEffects(it(o.effects),l))}return{changes:r,selection:E.create(i,t.mainIndex),effects:a}}changes(t=[]){return t instanceof pe?t:pe.of(t,this.doc.length,this.facet(e.lineSeparator))}toText(t){return y.of(t.split(this.facet(e.lineSeparator)||ue))}sliceDoc(e=0,t=this.doc.length){return this.doc.sliceString(e,t,this.lineBreak)}facet(e){let t=this.config.address[e.id];return t==null?e.default:(Re(this,t),ze(this,t))}toJSON(e){let t={doc:this.sliceDoc(),selection:this.selection.toJSON()};if(e)for(let n in e){let r=e[n];r instanceof ke&&this.config.address[r.id]!=null&&(t[n]=r.spec.toJSON(this.field(e[n]),this))}return t}static fromJSON(t,n={},r){if(!t||typeof t.doc!=`string`)throw RangeError(`Invalid JSON representation for EditorState`);let i=[];if(r){for(let e in r)if(Object.prototype.hasOwnProperty.call(t,e)){let n=r[e],a=t[e];i.push(n.init(e=>n.spec.fromJSON(a,e)))}}return e.create({doc:t.doc,selection:E.fromJSON(t.selection),extensions:n.extensions?i.concat([n.extensions]):i})}static create(t={}){let n=Ie.resolve(t.extensions||[],new Map),r=t.doc instanceof y?t.doc:y.of((t.doc||``).split(n.staticFacet(e.lineSeparator)||ue)),i=t.selection?t.selection instanceof E?t.selection:E.single(t.selection.anchor,t.selection.head):E.single(0);return xe(i,r.length),n.staticFacet(Ve)||(i=i.asSingle()),new e(n,r,i,n.dynamicSlots.map(()=>null),(e,t)=>t.create(e),null)}get tabSize(){return this.facet(e.tabSize)}get lineBreak(){return this.facet(e.lineSeparator)||`
@@ -0,0 +1 @@
1
+ import{i as e}from"./chunk-62oNxeRG.js";import{n as t,t as n}from"./jsx-runtime-ZP0XCtgh.js";import{d as r,f as i,u as a}from"./index-BbAx7IhR.js";import{CodeEditor as o}from"./CodeEditor-ROIg2ylA.js";var s=e(t(),1),c=n();function l(){try{if(localStorage.getItem(`loopat:editor:wordWrap`)===`0`)return!1}catch{}return!0}function u({loopId:e,path:t,onSelectionChange:n}){let[u,d]=(0,s.useState)(``),[f,p]=(0,s.useState)(``),[m,h]=(0,s.useState)(!1),[g,_]=(0,s.useState)(!1),[v,y]=(0,s.useState)(l);(0,s.useEffect)(()=>{if(!t){d(``),p(``);return}h(!0),a(e,t).then(e=>{let t=e?.content??``;d(t),p(t)}).finally(()=>h(!1))},[e,t]);let b=t&&f!==u,x=async()=>{if(!(!t||g)){_(!0);try{await r(e,t,f)&&d(f)}finally{_(!1)}}};return t?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(`div`,{className:`flex-1 min-h-0 relative`,onKeyDown:e=>{(e.metaKey||e.ctrlKey)&&e.key===`s`&&(e.preventDefault(),x())},children:m?(0,c.jsx)(`div`,{className:`h-full w-full flex items-center justify-center text-[12px] text-gray-400`,children:`loading…`}):(0,c.jsx)(o,{path:t,value:f,onChange:p,wordWrap:v,onSelectionChange:n})}),(0,c.jsxs)(`div`,{className:`border-t border-gray-200 px-3 py-1.5 text-[11px] text-gray-500 flex items-center gap-3`,children:[(0,c.jsx)(`span`,{className:`truncate`,children:t}),b&&(0,c.jsx)(`button`,{onClick:x,className:`text-orange-600 hover:underline`,title:`ctrl/⌘+S`,children:g?`saving…`:`unsaved · save`}),(0,c.jsx)(`span`,{className:`flex-1`}),(0,c.jsx)(`button`,{onClick:()=>{let e=!v;y(e);try{localStorage.setItem(`loopat:editor:wordWrap`,e?`1`:`0`)}catch{}},className:`flex items-center gap-1 hover:text-gray-700 transition-colors ${v?`text-gray-500`:`text-gray-300`}`,title:v?`word wrap: on`:`word wrap: off`,children:(0,c.jsx)(i,{size:13})}),(0,c.jsx)(`span`,{children:`utf-8 · LF`})]})]}):(0,c.jsx)(`div`,{className:`flex-1 min-h-0 flex items-center justify-center text-[13px] text-gray-500 px-8 text-center`,children:`没打开文件 · 在 ▤ workdir 里点一个`})}export{u as Editor};