@contentrain/mcp 1.2.1 → 1.4.0

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 (183) hide show
  1. package/README.md +93 -25
  2. package/dist/annotations-Clhbw2lh.mjs +126 -0
  3. package/dist/annotations-Clhbw2lh.mjs.map +1 -0
  4. package/dist/{apply-manager-BkPMfpsN.mjs → apply-manager-D5ym5Jba.mjs} +7 -7
  5. package/dist/{apply-manager-BkPMfpsN.mjs.map → apply-manager-D5ym5Jba.mjs.map} +1 -1
  6. package/dist/{astro-parser-BJ-54JGe.mjs → astro-parser-B-nLl0zE.mjs} +3 -3
  7. package/dist/{astro-parser-BJ-54JGe.mjs.map → astro-parser-B-nLl0zE.mjs.map} +1 -1
  8. package/dist/{branch-lifecycle-wGJg25LT.mjs → branch-lifecycle-CFVpTpNT.mjs} +33 -3
  9. package/dist/{branch-lifecycle-wGJg25LT.mjs.map → branch-lifecycle-CFVpTpNT.mjs.map} +1 -1
  10. package/dist/{compiler-rIC4ETHv.mjs → compiler-k4yttlzM.mjs} +2 -2
  11. package/dist/{compiler-rIC4ETHv.mjs.map → compiler-k4yttlzM.mjs.map} +1 -1
  12. package/dist/{compiler-sfc.cjs-BbD04rn_.mjs → compiler-sfc.cjs-D0d_OicF.mjs} +2 -2
  13. package/dist/{compiler-sfc.cjs-BbD04rn_.mjs.map → compiler-sfc.cjs-D0d_OicF.mjs.map} +1 -1
  14. package/dist/config-BIl5Ybj0.mjs +40 -0
  15. package/dist/config-BIl5Ybj0.mjs.map +1 -0
  16. package/dist/content-manager-DqDLSNQ-.d.mts +63 -0
  17. package/dist/content-manager-DqDLSNQ-.d.mts.map +1 -0
  18. package/dist/context-J0OU9Nfp.mjs +102 -0
  19. package/dist/context-J0OU9Nfp.mjs.map +1 -0
  20. package/dist/contracts-DfL0BfrD.mjs +2 -0
  21. package/dist/core/apply-manager.mjs +10 -10
  22. package/dist/core/config.d.mts +13 -0
  23. package/dist/core/config.d.mts.map +1 -1
  24. package/dist/core/config.mjs +2 -3
  25. package/dist/core/content-manager.d.mts +2 -45
  26. package/dist/core/content-manager.mjs +3 -4
  27. package/dist/core/context.d.mts +32 -2
  28. package/dist/core/context.d.mts.map +1 -1
  29. package/dist/core/context.mjs +7 -7
  30. package/dist/core/contracts/index.d.mts +2 -0
  31. package/dist/core/contracts/index.mjs +2 -0
  32. package/dist/core/doctor.d.mts +76 -0
  33. package/dist/core/doctor.d.mts.map +1 -0
  34. package/dist/core/doctor.mjs +8 -0
  35. package/dist/core/graph-builder.mjs +3 -4
  36. package/dist/core/meta-manager.mjs +2 -3
  37. package/dist/core/model-manager.d.mts +34 -1
  38. package/dist/core/model-manager.d.mts.map +1 -1
  39. package/dist/core/model-manager.mjs +3 -4
  40. package/dist/core/ops/index.d.mts +137 -0
  41. package/dist/core/ops/index.d.mts.map +1 -0
  42. package/dist/core/ops/index.mjs +4 -0
  43. package/dist/core/overlay-reader.d.mts +42 -0
  44. package/dist/core/overlay-reader.d.mts.map +1 -0
  45. package/dist/core/overlay-reader.mjs +2 -0
  46. package/dist/core/scan-config.mjs +2 -3
  47. package/dist/core/scanner.mjs +4 -5
  48. package/dist/core/validator/index.d.mts +129 -0
  49. package/dist/core/validator/index.d.mts.map +1 -0
  50. package/dist/core/validator/index.mjs +6 -0
  51. package/dist/{detect-DinOQAmK.mjs → detect-DL9mFmaS.mjs} +2 -2
  52. package/dist/{detect-DinOQAmK.mjs.map → detect-DL9mFmaS.mjs.map} +1 -1
  53. package/dist/doctor-CgBoT6h1.mjs +338 -0
  54. package/dist/doctor-CgBoT6h1.mjs.map +1 -0
  55. package/dist/{fs-BnIQ4dKj.mjs → fs-DLbVB-Ek.mjs} +2 -2
  56. package/dist/fs-DLbVB-Ek.mjs.map +1 -0
  57. package/dist/git/branch-lifecycle.d.mts +30 -1
  58. package/dist/git/branch-lifecycle.d.mts.map +1 -1
  59. package/dist/git/branch-lifecycle.mjs +4 -5
  60. package/dist/git/transaction.d.mts +2 -2
  61. package/dist/git/transaction.d.mts.map +1 -1
  62. package/dist/git/transaction.mjs +8 -8
  63. package/dist/{graph-builder-tM7zj-SX.mjs → graph-builder-DXv2JEp-.mjs} +3 -3
  64. package/dist/{graph-builder-tM7zj-SX.mjs.map → graph-builder-DXv2JEp-.mjs.map} +1 -1
  65. package/dist/{id-DV_T9Ic8.mjs → id-CIO9s0x_.mjs} +1 -1
  66. package/dist/{id-DV_T9Ic8.mjs.map → id-CIO9s0x_.mjs.map} +1 -1
  67. package/dist/index-D0wQJSgs.d.mts +2 -0
  68. package/dist/index.mjs +22 -17
  69. package/dist/index.mjs.map +1 -1
  70. package/dist/local-DvP4Y4T-.mjs +182 -0
  71. package/dist/local-DvP4Y4T-.mjs.map +1 -0
  72. package/dist/{meta-manager--0IwAPCl.mjs → meta-manager-C900rEyG.mjs} +2 -2
  73. package/dist/{meta-manager--0IwAPCl.mjs.map → meta-manager-C900rEyG.mjs.map} +1 -1
  74. package/dist/{model-manager-DW_fOGRM.mjs → model-manager-BhLsUgaB.mjs} +241 -49
  75. package/dist/model-manager-BhLsUgaB.mjs.map +1 -0
  76. package/dist/{node-Cbq5eR5i.mjs → node-DN9hZeil.mjs} +1 -1
  77. package/dist/{node-Cbq5eR5i.mjs.map → node-DN9hZeil.mjs.map} +1 -1
  78. package/dist/ops-DjEWi5Wa.mjs +486 -0
  79. package/dist/ops-DjEWi5Wa.mjs.map +1 -0
  80. package/dist/overlay-reader-DOdyDRIv.mjs +74 -0
  81. package/dist/overlay-reader-DOdyDRIv.mjs.map +1 -0
  82. package/dist/paths-C3xNyc7z.mjs +52 -0
  83. package/dist/paths-C3xNyc7z.mjs.map +1 -0
  84. package/dist/paths-CYl5vCBD.mjs +54 -0
  85. package/dist/paths-CYl5vCBD.mjs.map +1 -0
  86. package/dist/providers/github/index.d.mts +201 -0
  87. package/dist/providers/github/index.d.mts.map +1 -0
  88. package/dist/providers/github/index.mjs +494 -0
  89. package/dist/providers/github/index.mjs.map +1 -0
  90. package/dist/providers/gitlab/index.d.mts +158 -0
  91. package/dist/providers/gitlab/index.d.mts.map +1 -0
  92. package/dist/providers/gitlab/index.mjs +361 -0
  93. package/dist/providers/gitlab/index.mjs.map +1 -0
  94. package/dist/providers/local/index.d.mts +106 -0
  95. package/dist/providers/local/index.d.mts.map +1 -0
  96. package/dist/providers/local/index.mjs +12 -0
  97. package/dist/{scan-config-QgnJ1-52.mjs → scan-config-jC6XmiqF.mjs} +2 -2
  98. package/dist/{scan-config-QgnJ1-52.mjs.map → scan-config-jC6XmiqF.mjs.map} +1 -1
  99. package/dist/{scanner-DUoXnmtI.mjs → scanner-DKMwc03k.mjs} +7 -7
  100. package/dist/{scanner-DUoXnmtI.mjs.map → scanner-DKMwc03k.mjs.map} +1 -1
  101. package/dist/serialization-B1CEzR4H.mjs +2 -0
  102. package/dist/server/http/index.d.mts +107 -0
  103. package/dist/server/http/index.d.mts.map +1 -0
  104. package/dist/server/http/index.mjs +248 -0
  105. package/dist/server/http/index.mjs.map +1 -0
  106. package/dist/{server-Dtq8vqbK.mjs → server-BkhhtEE2.mjs} +486 -355
  107. package/dist/server-BkhhtEE2.mjs.map +1 -0
  108. package/dist/server-WqGx6ait.d.mts +50 -0
  109. package/dist/server-WqGx6ait.d.mts.map +1 -0
  110. package/dist/server.d.mts +2 -7
  111. package/dist/server.mjs +22 -17
  112. package/dist/{source-map-generator-DpO-ejrt.mjs → source-map-generator-BWDva49I.mjs} +1 -1
  113. package/dist/{source-map-generator-DpO-ejrt.mjs.map → source-map-generator-BWDva49I.mjs.map} +1 -1
  114. package/dist/{svelte-parser-1bBcMx3T.mjs → svelte-parser-Dr9mmZuk.mjs} +3 -3
  115. package/dist/{svelte-parser-1bBcMx3T.mjs.map → svelte-parser-Dr9mmZuk.mjs.map} +1 -1
  116. package/dist/templates/index.mjs +1 -1
  117. package/dist/{templates-bRPzYq4M.mjs → templates-VrLVqfe5.mjs} +1 -1
  118. package/dist/{templates-bRPzYq4M.mjs.map → templates-VrLVqfe5.mjs.map} +1 -1
  119. package/dist/testing/conformance.d.mts +59 -0
  120. package/dist/testing/conformance.d.mts.map +1 -0
  121. package/dist/testing/conformance.mjs +59 -0
  122. package/dist/testing/conformance.mjs.map +1 -0
  123. package/dist/tools/annotations.d.mts +24 -0
  124. package/dist/tools/annotations.d.mts.map +1 -0
  125. package/dist/tools/annotations.mjs +2 -0
  126. package/dist/{transaction-C_Pvux78.mjs → transaction-DgkNgWSI.mjs} +61 -32
  127. package/dist/transaction-DgkNgWSI.mjs.map +1 -0
  128. package/dist/tsx-parser-BOMZE_yQ.mjs +2 -0
  129. package/dist/{tsx-parser-BWiMGAIR.mjs → tsx-parser-CQc6nr-o.mjs} +1 -1
  130. package/dist/{tsx-parser-BWiMGAIR.mjs.map → tsx-parser-CQc6nr-o.mjs.map} +1 -1
  131. package/dist/util/detect.mjs +2 -3
  132. package/dist/util/fs.mjs +1 -2
  133. package/dist/util/id.mjs +1 -1
  134. package/dist/validator-B0nNRFeU.mjs +906 -0
  135. package/dist/validator-B0nNRFeU.mjs.map +1 -0
  136. package/dist/{vue-parser-DTPTN3Yb.mjs → vue-parser-COgjArqv.mjs} +3 -3
  137. package/dist/{vue-parser-DTPTN3Yb.mjs.map → vue-parser-COgjArqv.mjs.map} +1 -1
  138. package/package.json +82 -23
  139. package/testing/conformance/01-new-collection-entry/expected/.contentrain/config.json +15 -0
  140. package/testing/conformance/01-new-collection-entry/expected/.contentrain/content/blog/blog/en.json +6 -0
  141. package/testing/conformance/01-new-collection-entry/expected/.contentrain/context.json +22 -0
  142. package/testing/conformance/01-new-collection-entry/expected/.contentrain/meta/blog/en.json +7 -0
  143. package/testing/conformance/01-new-collection-entry/expected/.contentrain/models/blog.json +16 -0
  144. package/testing/conformance/01-new-collection-entry/scenario.json +19 -0
  145. package/testing/conformance/01-new-collection-entry/setup/.contentrain/config.json +15 -0
  146. package/testing/conformance/01-new-collection-entry/setup/.contentrain/models/blog.json +16 -0
  147. package/testing/conformance/02-new-singleton/expected/.contentrain/config.json +15 -0
  148. package/testing/conformance/02-new-singleton/expected/.contentrain/content/marketing/hero/en.json +4 -0
  149. package/testing/conformance/02-new-singleton/expected/.contentrain/context.json +22 -0
  150. package/testing/conformance/02-new-singleton/expected/.contentrain/meta/hero/en.json +5 -0
  151. package/testing/conformance/02-new-singleton/expected/.contentrain/models/hero.json +16 -0
  152. package/testing/conformance/02-new-singleton/scenario.json +18 -0
  153. package/testing/conformance/02-new-singleton/setup/.contentrain/config.json +15 -0
  154. package/testing/conformance/02-new-singleton/setup/.contentrain/models/hero.json +16 -0
  155. package/testing/conformance/03-new-dictionary/expected/.contentrain/config.json +15 -0
  156. package/testing/conformance/03-new-dictionary/expected/.contentrain/content/marketing/ui-strings/en.json +5 -0
  157. package/testing/conformance/03-new-dictionary/expected/.contentrain/context.json +22 -0
  158. package/testing/conformance/03-new-dictionary/expected/.contentrain/meta/ui-strings/en.json +5 -0
  159. package/testing/conformance/03-new-dictionary/expected/.contentrain/models/ui-strings.json +7 -0
  160. package/testing/conformance/03-new-dictionary/scenario.json +19 -0
  161. package/testing/conformance/03-new-dictionary/setup/.contentrain/config.json +15 -0
  162. package/testing/conformance/03-new-dictionary/setup/.contentrain/models/ui-strings.json +7 -0
  163. package/testing/conformance/README.md +77 -0
  164. package/testing/conformance/scenarios.json +36 -0
  165. package/dist/config-B5kc2oeV.mjs +0 -27
  166. package/dist/config-B5kc2oeV.mjs.map +0 -1
  167. package/dist/context-DIDt_TxX.mjs +0 -46
  168. package/dist/context-DIDt_TxX.mjs.map +0 -1
  169. package/dist/core/content-manager.d.mts.map +0 -1
  170. package/dist/core/validator.d.mts +0 -23
  171. package/dist/core/validator.d.mts.map +0 -1
  172. package/dist/core/validator.mjs +0 -7
  173. package/dist/fs-BnIQ4dKj.mjs.map +0 -1
  174. package/dist/model-manager-DW_fOGRM.mjs.map +0 -1
  175. package/dist/serializer-CnHTtmc1.mjs +0 -2
  176. package/dist/server-Dtq8vqbK.mjs.map +0 -1
  177. package/dist/server.d.mts.map +0 -1
  178. package/dist/transaction-C_Pvux78.mjs.map +0 -1
  179. package/dist/tsx-parser-BFLv292Y.mjs +0 -2
  180. package/dist/util/serializer.d.mts +0 -2
  181. package/dist/util/serializer.mjs +0 -2
  182. package/dist/validator-SQYUV2JP.mjs +0 -581
  183. package/dist/validator-SQYUV2JP.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,21 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import "./serializer-CnHTtmc1.mjs";
3
- import "./fs-BnIQ4dKj.mjs";
4
- import "./config-B5kc2oeV.mjs";
5
- import "./meta-manager--0IwAPCl.mjs";
6
- import "./model-manager-DW_fOGRM.mjs";
7
- import "./context-DIDt_TxX.mjs";
8
- import "./detect-DinOQAmK.mjs";
9
- import "./branch-lifecycle-wGJg25LT.mjs";
10
- import { t as createServer } from "./server-Dtq8vqbK.mjs";
11
- import "./id-DV_T9Ic8.mjs";
12
- import "./transaction-C_Pvux78.mjs";
13
- import "./validator-SQYUV2JP.mjs";
14
- import "./scan-config-QgnJ1-52.mjs";
15
- import "./graph-builder-tM7zj-SX.mjs";
16
- import "./scanner-DUoXnmtI.mjs";
17
- import "./tsx-parser-BWiMGAIR.mjs";
18
- import "./apply-manager-BkPMfpsN.mjs";
2
+ import "./contracts-DfL0BfrD.mjs";
3
+ import "./ops-DjEWi5Wa.mjs";
4
+ import "./serialization-B1CEzR4H.mjs";
5
+ import "./fs-DLbVB-Ek.mjs";
6
+ import "./config-BIl5Ybj0.mjs";
7
+ import "./model-manager-BhLsUgaB.mjs";
8
+ import "./meta-manager-C900rEyG.mjs";
9
+ import "./context-J0OU9Nfp.mjs";
10
+ import "./id-CIO9s0x_.mjs";
11
+ import "./transaction-DgkNgWSI.mjs";
12
+ import "./local-DvP4Y4T-.mjs";
13
+ import "./detect-DL9mFmaS.mjs";
14
+ import "./branch-lifecycle-CFVpTpNT.mjs";
15
+ import "./annotations-Clhbw2lh.mjs";
16
+ import { t as createServer } from "./server-BkhhtEE2.mjs";
17
+ import "./validator-B0nNRFeU.mjs";
18
+ import "./scan-config-jC6XmiqF.mjs";
19
+ import "./graph-builder-DXv2JEp-.mjs";
20
+ import "./scanner-DKMwc03k.mjs";
21
+ import "./tsx-parser-CQc6nr-o.mjs";
22
+ import "./apply-manager-D5ym5Jba.mjs";
23
+ import "./doctor-CgBoT6h1.mjs";
19
24
  import { resolve } from "node:path";
20
25
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
21
26
  //#region src/index.ts
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve } from 'node:path'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nconst projectRoot = resolve(process.env['CONTENTRAIN_PROJECT_ROOT'] ?? process.cwd())\nconst server = createServer(projectRoot)\nconst transport = new StdioServerTransport()\n\nawait server.connect(transport)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAMA,MAAM,SAAS,aADK,QAAQ,QAAQ,IAAI,+BAA+B,QAAQ,KAAK,CAAC,CAC7C;AACxC,MAAM,YAAY,IAAI,sBAAsB;AAE5C,MAAM,OAAO,QAAQ,UAAU"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { resolve } from 'node:path'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { createServer } from './server.js'\n\nconst projectRoot = resolve(process.env['CONTENTRAIN_PROJECT_ROOT'] ?? process.cwd())\nconst server = createServer(projectRoot)\nconst transport = new StdioServerTransport()\n\nawait server.connect(transport)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,MAAM,SAAS,aADK,QAAQ,QAAQ,IAAI,+BAA+B,QAAQ,KAAK,CAAC,CAC7C;AACxC,MAAM,YAAY,IAAI,sBAAsB;AAE5C,MAAM,OAAO,QAAQ,UAAU"}
@@ -0,0 +1,182 @@
1
+ import { t as LOCAL_CAPABILITIES } from "./contracts-DfL0BfrD.mjs";
2
+ import { a as applyChangesToWorktree } from "./ops-DjEWi5Wa.mjs";
3
+ import { t as readConfig } from "./config-BIl5Ybj0.mjs";
4
+ import { C as LocalReader } from "./model-manager-BhLsUgaB.mjs";
5
+ import { i as mergeBranch$1, n as createTransaction } from "./transaction-DgkNgWSI.mjs";
6
+ import { CONTENTRAIN_BRANCH } from "@contentrain/types";
7
+ import { simpleGit } from "simple-git";
8
+ //#region src/providers/local/branch-ops.ts
9
+ /**
10
+ * Branch/merge/diff helpers backed by the local simple-git worktree flow.
11
+ *
12
+ * Pure functions composed into `LocalProvider` — mirroring the shape of
13
+ * `providers/github/branch-ops.ts` so the two providers share the same
14
+ * surface at the `RepoProvider` boundary.
15
+ */
16
+ async function getDefaultBranch(projectRoot) {
17
+ const config = await readConfig(projectRoot);
18
+ if (config?.repository?.default_branch) return config.repository.default_branch;
19
+ const envBranch = process.env["CONTENTRAIN_BRANCH"];
20
+ if (envBranch) return envBranch;
21
+ return (await simpleGit(projectRoot).raw(["branch", "--show-current"])).trim() || "main";
22
+ }
23
+ async function listBranches(projectRoot, prefix) {
24
+ const summary = await simpleGit(projectRoot).branchLocal();
25
+ const names = prefix ? summary.all.filter((n) => n.startsWith(prefix)) : summary.all;
26
+ const branches = [];
27
+ for (const name of names) {
28
+ const info = summary.branches[name];
29
+ branches.push({
30
+ name,
31
+ sha: info?.commit ?? ""
32
+ });
33
+ }
34
+ return branches;
35
+ }
36
+ async function createBranch(projectRoot, name, fromRef) {
37
+ await simpleGit(projectRoot).raw([
38
+ "branch",
39
+ name,
40
+ fromRef
41
+ ]);
42
+ }
43
+ async function deleteBranch(projectRoot, name) {
44
+ await simpleGit(projectRoot).deleteLocalBranch(name, true);
45
+ }
46
+ async function getBranchDiff(projectRoot, branch, base) {
47
+ const raw = await simpleGit(projectRoot).raw([
48
+ "diff",
49
+ "--name-status",
50
+ `${base}...${branch}`
51
+ ]);
52
+ const diffs = [];
53
+ for (const line of raw.split("\n")) {
54
+ if (!line.trim()) continue;
55
+ const [code, ...pathParts] = line.split(" ");
56
+ const path = pathParts[pathParts.length - 1];
57
+ if (!code || !path) continue;
58
+ const status = code.startsWith("A") ? "added" : code.startsWith("D") ? "removed" : "modified";
59
+ diffs.push({
60
+ path,
61
+ status,
62
+ before: null,
63
+ after: null
64
+ });
65
+ }
66
+ return diffs;
67
+ }
68
+ async function mergeBranch(projectRoot, branch, into) {
69
+ if (into !== CONTENTRAIN_BRANCH) throw Object.assign(/* @__PURE__ */ new Error(`LocalProvider.mergeBranch only supports merging into "${CONTENTRAIN_BRANCH}" (got "${into}"). The local flow merges feature branches into the content-tracking branch and fast-forwards the base branch via update-ref.`), {
70
+ code: "UNSUPPORTED_MERGE_TARGET",
71
+ agent_hint: `Pass "${CONTENTRAIN_BRANCH}" as the merge target, or use a non-local provider that supports arbitrary targets.`,
72
+ developer_action: `Merge "${branch}" into "${CONTENTRAIN_BRANCH}" instead.`
73
+ });
74
+ const result = await mergeBranch$1(projectRoot, branch);
75
+ return {
76
+ merged: true,
77
+ sha: result.commit,
78
+ pullRequestUrl: null,
79
+ sync: result.sync
80
+ };
81
+ }
82
+ async function isMerged(projectRoot, branch, into) {
83
+ const git = simpleGit(projectRoot);
84
+ try {
85
+ const raw = await git.raw([
86
+ "branch",
87
+ "--merged",
88
+ into
89
+ ]);
90
+ return new Set(raw.split("\n").map((b) => b.replace(/^\*?\s+/, "").trim()).filter(Boolean)).has(branch);
91
+ } catch {
92
+ return false;
93
+ }
94
+ }
95
+ //#endregion
96
+ //#region src/providers/local/provider.ts
97
+ const DEFAULT_AUTHOR_NAME = "Contentrain";
98
+ const DEFAULT_AUTHOR_EMAIL = "mcp@contentrain.io";
99
+ /**
100
+ * LocalProvider — the local-filesystem, worktree-backed content provider.
101
+ *
102
+ * Implements the full `RepoProvider` surface:
103
+ * - Reader methods delegate to `LocalReader`.
104
+ * - `applyPlan` wraps `createTransaction` and returns `LocalApplyResult`
105
+ * (a superset of `Commit` carrying workflow action + selective sync).
106
+ * - Branch ops mirror `GitHubProvider` — thin wrappers over the local
107
+ * simple-git helpers in `./branch-ops.ts`.
108
+ *
109
+ * `mergeBranch` only supports merging into the singleton
110
+ * `CONTENTRAIN_BRANCH`; the local flow advances the base branch via
111
+ * `update-ref` in `transaction.mergeBranch`, so arbitrary merge targets
112
+ * would bypass that invariant.
113
+ */
114
+ var LocalProvider = class {
115
+ capabilities = LOCAL_CAPABILITIES;
116
+ reader;
117
+ constructor(projectRoot) {
118
+ this.projectRoot = projectRoot;
119
+ this.reader = new LocalReader(projectRoot);
120
+ }
121
+ readFile(path, ref) {
122
+ return this.reader.readFile(path, ref);
123
+ }
124
+ listDirectory(path, ref) {
125
+ return this.reader.listDirectory(path, ref);
126
+ }
127
+ fileExists(path, ref) {
128
+ return this.reader.fileExists(path, ref);
129
+ }
130
+ async applyPlan(input) {
131
+ const tx = await createTransaction(this.projectRoot, input.branch, { workflowOverride: input.workflowOverride });
132
+ try {
133
+ await tx.write(async (wt) => {
134
+ await applyChangesToWorktree(wt, input.changes);
135
+ });
136
+ await tx.commit(input.message, input.context);
137
+ const gitResult = await tx.complete();
138
+ return {
139
+ sha: gitResult.commit,
140
+ message: input.message,
141
+ author: {
142
+ name: process.env["CONTENTRAIN_AUTHOR_NAME"] ?? DEFAULT_AUTHOR_NAME,
143
+ email: process.env["CONTENTRAIN_AUTHOR_EMAIL"] ?? DEFAULT_AUTHOR_EMAIL
144
+ },
145
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
146
+ workflowAction: gitResult.action,
147
+ sync: gitResult.sync,
148
+ warning: gitResult.warning
149
+ };
150
+ } finally {
151
+ await tx.cleanup();
152
+ }
153
+ }
154
+ listBranches(prefix) {
155
+ return listBranches(this.projectRoot, prefix);
156
+ }
157
+ async createBranch(name, fromRef) {
158
+ const resolved = fromRef ?? CONTENTRAIN_BRANCH;
159
+ await createBranch(this.projectRoot, name, resolved);
160
+ }
161
+ deleteBranch(name) {
162
+ return deleteBranch(this.projectRoot, name);
163
+ }
164
+ getBranchDiff(branch, base) {
165
+ const resolved = base ?? CONTENTRAIN_BRANCH;
166
+ return getBranchDiff(this.projectRoot, branch, resolved);
167
+ }
168
+ mergeBranch(branch, into) {
169
+ return mergeBranch(this.projectRoot, branch, into);
170
+ }
171
+ isMerged(branch, into) {
172
+ const resolved = into ?? CONTENTRAIN_BRANCH;
173
+ return isMerged(this.projectRoot, branch, resolved);
174
+ }
175
+ getDefaultBranch() {
176
+ return getDefaultBranch(this.projectRoot);
177
+ }
178
+ };
179
+ //#endregion
180
+ export { LocalProvider as t };
181
+
182
+ //# sourceMappingURL=local-DvP4Y4T-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-DvP4Y4T-.mjs","names":["mergeBranchOp","listBranchesOp","createBranchOp","deleteBranchOp","getBranchDiffOp","mergeBranchOp","isMergedOp","getDefaultBranchOp"],"sources":["../src/providers/local/branch-ops.ts","../src/providers/local/provider.ts"],"sourcesContent":["import { simpleGit } from 'simple-git'\nimport { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type { Branch, FileDiff, MergeResult } from '../../core/contracts/index.js'\nimport { readConfig } from '../../core/config.js'\nimport { mergeBranch as mergeBranchOp } from '../../git/transaction.js'\n\n/**\n * Branch/merge/diff helpers backed by the local simple-git worktree flow.\n *\n * Pure functions composed into `LocalProvider` — mirroring the shape of\n * `providers/github/branch-ops.ts` so the two providers share the same\n * surface at the `RepoProvider` boundary.\n */\n\nexport async function getDefaultBranch(projectRoot: string): Promise<string> {\n const config = await readConfig(projectRoot)\n if (config?.repository?.default_branch) return config.repository.default_branch\n const envBranch = process.env['CONTENTRAIN_BRANCH']\n if (envBranch) return envBranch\n const git = simpleGit(projectRoot)\n const current = (await git.raw(['branch', '--show-current'])).trim()\n return current || 'main'\n}\n\nexport async function listBranches(\n projectRoot: string,\n prefix?: string,\n): Promise<Branch[]> {\n const git = simpleGit(projectRoot)\n const summary = await git.branchLocal()\n const names = prefix\n ? summary.all.filter(n => n.startsWith(prefix))\n : summary.all\n const branches: Branch[] = []\n for (const name of names) {\n const info = summary.branches[name]\n branches.push({ name, sha: info?.commit ?? '' })\n }\n return branches\n}\n\nexport async function createBranch(\n projectRoot: string,\n name: string,\n fromRef: string,\n): Promise<void> {\n const git = simpleGit(projectRoot)\n await git.raw(['branch', name, fromRef])\n}\n\nexport async function deleteBranch(\n projectRoot: string,\n name: string,\n): Promise<void> {\n const git = simpleGit(projectRoot)\n await git.deleteLocalBranch(name, true)\n}\n\nexport async function getBranchDiff(\n projectRoot: string,\n branch: string,\n base: string,\n): Promise<FileDiff[]> {\n const git = simpleGit(projectRoot)\n const raw = await git.raw(['diff', '--name-status', `${base}...${branch}`])\n const diffs: FileDiff[] = []\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue\n const [code, ...pathParts] = line.split('\\t')\n const path = pathParts[pathParts.length - 1]\n if (!code || !path) continue\n const status: FileDiff['status'] = code.startsWith('A')\n ? 'added'\n : code.startsWith('D')\n ? 'removed'\n : 'modified'\n diffs.push({ path, status, before: null, after: null })\n }\n return diffs\n}\n\nexport async function mergeBranch(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<MergeResult> {\n if (into !== CONTENTRAIN_BRANCH) {\n throw Object.assign(new Error(\n `LocalProvider.mergeBranch only supports merging into \"${CONTENTRAIN_BRANCH}\" (got \"${into}\"). `\n + `The local flow merges feature branches into the content-tracking branch and fast-forwards the base branch via update-ref.`,\n ), {\n code: 'UNSUPPORTED_MERGE_TARGET',\n agent_hint: `Pass \"${CONTENTRAIN_BRANCH}\" as the merge target, or use a non-local provider that supports arbitrary targets.`,\n developer_action: `Merge \"${branch}\" into \"${CONTENTRAIN_BRANCH}\" instead.`,\n })\n }\n const result = await mergeBranchOp(projectRoot, branch)\n return {\n merged: true,\n sha: result.commit,\n pullRequestUrl: null,\n sync: result.sync,\n }\n}\n\nexport async function isMerged(\n projectRoot: string,\n branch: string,\n into: string,\n): Promise<boolean> {\n const git = simpleGit(projectRoot)\n try {\n const raw = await git.raw(['branch', '--merged', into])\n const merged = new Set(\n raw.split('\\n').map(b => b.replace(/^\\*?\\s+/, '').trim()).filter(Boolean),\n )\n return merged.has(branch)\n } catch {\n return false\n }\n}\n","import { CONTENTRAIN_BRANCH } from '@contentrain/types'\nimport type {\n Branch,\n FileDiff,\n MergeResult,\n ProviderCapabilities,\n RepoProvider,\n} from '../../core/contracts/index.js'\nimport { LOCAL_CAPABILITIES } from '../../core/contracts/index.js'\nimport { applyChangesToWorktree } from '../../core/ops/index.js'\nimport { createTransaction } from '../../git/transaction.js'\nimport {\n createBranch as createBranchOp,\n deleteBranch as deleteBranchOp,\n getBranchDiff as getBranchDiffOp,\n getDefaultBranch as getDefaultBranchOp,\n isMerged as isMergedOp,\n listBranches as listBranchesOp,\n mergeBranch as mergeBranchOp,\n} from './branch-ops.js'\nimport { LocalReader } from './reader.js'\nimport type { LocalApplyPlanInput, LocalApplyResult } from './types.js'\n\nconst DEFAULT_AUTHOR_NAME = 'Contentrain'\nconst DEFAULT_AUTHOR_EMAIL = 'mcp@contentrain.io'\n\n/**\n * LocalProvider — the local-filesystem, worktree-backed content provider.\n *\n * Implements the full `RepoProvider` surface:\n * - Reader methods delegate to `LocalReader`.\n * - `applyPlan` wraps `createTransaction` and returns `LocalApplyResult`\n * (a superset of `Commit` carrying workflow action + selective sync).\n * - Branch ops mirror `GitHubProvider` — thin wrappers over the local\n * simple-git helpers in `./branch-ops.ts`.\n *\n * `mergeBranch` only supports merging into the singleton\n * `CONTENTRAIN_BRANCH`; the local flow advances the base branch via\n * `update-ref` in `transaction.mergeBranch`, so arbitrary merge targets\n * would bypass that invariant.\n */\nexport class LocalProvider implements RepoProvider {\n readonly capabilities: ProviderCapabilities = LOCAL_CAPABILITIES\n private readonly reader: LocalReader\n\n constructor(public readonly projectRoot: string) {\n this.reader = new LocalReader(projectRoot)\n }\n\n readFile(path: string, ref?: string): Promise<string> {\n return this.reader.readFile(path, ref)\n }\n\n listDirectory(path: string, ref?: string): Promise<string[]> {\n return this.reader.listDirectory(path, ref)\n }\n\n fileExists(path: string, ref?: string): Promise<boolean> {\n return this.reader.fileExists(path, ref)\n }\n\n async applyPlan(input: LocalApplyPlanInput): Promise<LocalApplyResult> {\n const tx = await createTransaction(this.projectRoot, input.branch, {\n workflowOverride: input.workflowOverride,\n })\n try {\n await tx.write(async (wt) => {\n await applyChangesToWorktree(wt, input.changes)\n })\n await tx.commit(input.message, input.context)\n const gitResult = await tx.complete()\n return {\n sha: gitResult.commit,\n message: input.message,\n author: {\n name: process.env['CONTENTRAIN_AUTHOR_NAME'] ?? DEFAULT_AUTHOR_NAME,\n email: process.env['CONTENTRAIN_AUTHOR_EMAIL'] ?? DEFAULT_AUTHOR_EMAIL,\n },\n timestamp: new Date().toISOString(),\n workflowAction: gitResult.action,\n sync: gitResult.sync,\n warning: gitResult.warning,\n }\n } finally {\n await tx.cleanup()\n }\n }\n\n listBranches(prefix?: string): Promise<Branch[]> {\n return listBranchesOp(this.projectRoot, prefix)\n }\n\n async createBranch(name: string, fromRef?: string): Promise<void> {\n const resolved = fromRef ?? CONTENTRAIN_BRANCH\n await createBranchOp(this.projectRoot, name, resolved)\n }\n\n deleteBranch(name: string): Promise<void> {\n return deleteBranchOp(this.projectRoot, name)\n }\n\n getBranchDiff(branch: string, base?: string): Promise<FileDiff[]> {\n const resolved = base ?? CONTENTRAIN_BRANCH\n return getBranchDiffOp(this.projectRoot, branch, resolved)\n }\n\n mergeBranch(branch: string, into: string): Promise<MergeResult> {\n return mergeBranchOp(this.projectRoot, branch, into)\n }\n\n isMerged(branch: string, into?: string): Promise<boolean> {\n const resolved = into ?? CONTENTRAIN_BRANCH\n return isMergedOp(this.projectRoot, branch, resolved)\n }\n\n getDefaultBranch(): Promise<string> {\n return getDefaultBranchOp(this.projectRoot)\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { a as readJson, s as writeJson, t as contentrainDir } from "./fs-BnIQ4dKj.mjs";
1
+ import { a as readJson, s as writeJson, t as contentrainDir } from "./fs-DLbVB-Ek.mjs";
2
2
  import { join } from "node:path";
3
3
  import { rm } from "node:fs/promises";
4
4
  //#region src/core/meta-manager.ts
@@ -50,4 +50,4 @@ async function deleteMeta(projectRoot, model, opts) {
50
50
  //#endregion
51
51
  export { readMeta as n, writeMeta as r, deleteMeta as t };
52
52
 
53
- //# sourceMappingURL=meta-manager--0IwAPCl.mjs.map
53
+ //# sourceMappingURL=meta-manager-C900rEyG.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"meta-manager--0IwAPCl.mjs","names":[],"sources":["../src/core/meta-manager.ts"],"sourcesContent":["import type { ModelDefinition, EntryMeta } from '@contentrain/types'\nimport { join } from 'node:path'\nimport { rm } from 'node:fs/promises'\nimport { contentrainDir, readJson, writeJson } from '../util/fs.js'\n\ninterface MetaOpts {\n locale?: string\n entryId?: string\n slug?: string\n}\n\nfunction metaPath(projectRoot: string, model: ModelDefinition, opts: MetaOpts): string {\n const base = join(contentrainDir(projectRoot), 'meta', model.id)\n\n if (model.kind === 'document' && opts.slug) {\n return join(base, opts.slug, `${opts.locale ?? 'en'}.json`)\n }\n\n return join(base, `${opts.locale ?? 'en'}.json`)\n}\n\nexport async function readMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n): Promise<EntryMeta | Record<string, EntryMeta> | null> {\n return readJson(metaPath(projectRoot, model, opts))\n}\n\nexport async function writeMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n meta: EntryMeta,\n): Promise<void> {\n const filePath = metaPath(projectRoot, model, opts)\n\n if (model.kind === 'collection' && opts.entryId) {\n const existing = await readJson<Record<string, EntryMeta>>(filePath) ?? {}\n existing[opts.entryId] = meta\n await writeJson(filePath, existing)\n } else {\n await writeJson(filePath, meta)\n }\n}\n\nexport async function deleteMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n): Promise<void> {\n if (model.kind === 'collection' && opts.entryId) {\n const filePath = metaPath(projectRoot, model, opts)\n const existing = await readJson<Record<string, EntryMeta>>(filePath)\n if (existing && opts.entryId in existing) {\n delete existing[opts.entryId]\n if (Object.keys(existing).length > 0) {\n await writeJson(filePath, existing)\n } else {\n await rm(filePath, { force: true })\n }\n }\n } else if (model.kind === 'document' && opts.slug) {\n const slugDir = join(contentrainDir(projectRoot), 'meta', model.id, opts.slug)\n if (opts.locale) {\n await rm(join(slugDir, `${opts.locale}.json`), { force: true })\n } else {\n try {\n await rm(slugDir, { recursive: true, force: true })\n } catch {\n // directory may not exist\n }\n }\n } else if (opts.locale) {\n const filePath = metaPath(projectRoot, model, opts)\n await rm(filePath, { force: true })\n } else {\n // No locale specified — remove all meta for this model (non-i18n or full cleanup)\n const metaDir = join(contentrainDir(projectRoot), 'meta', model.id)\n try {\n await rm(metaDir, { recursive: true, force: true })\n } catch {\n // directory may not exist\n }\n }\n}\n"],"mappings":";;;;AAWA,SAAS,SAAS,aAAqB,OAAwB,MAAwB;CACrF,MAAM,OAAO,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,GAAG;AAEhE,KAAI,MAAM,SAAS,cAAc,KAAK,KACpC,QAAO,KAAK,MAAM,KAAK,MAAM,GAAG,KAAK,UAAU,KAAK,OAAO;AAG7D,QAAO,KAAK,MAAM,GAAG,KAAK,UAAU,KAAK,OAAO;;AAGlD,eAAsB,SACpB,aACA,OACA,MACuD;AACvD,QAAO,SAAS,SAAS,aAAa,OAAO,KAAK,CAAC;;AAGrD,eAAsB,UACpB,aACA,OACA,MACA,MACe;CACf,MAAM,WAAW,SAAS,aAAa,OAAO,KAAK;AAEnD,KAAI,MAAM,SAAS,gBAAgB,KAAK,SAAS;EAC/C,MAAM,WAAW,MAAM,SAAoC,SAAS,IAAI,EAAE;AAC1E,WAAS,KAAK,WAAW;AACzB,QAAM,UAAU,UAAU,SAAS;OAEnC,OAAM,UAAU,UAAU,KAAK;;AAInC,eAAsB,WACpB,aACA,OACA,MACe;AACf,KAAI,MAAM,SAAS,gBAAgB,KAAK,SAAS;EAC/C,MAAM,WAAW,SAAS,aAAa,OAAO,KAAK;EACnD,MAAM,WAAW,MAAM,SAAoC,SAAS;AACpE,MAAI,YAAY,KAAK,WAAW,UAAU;AACxC,UAAO,SAAS,KAAK;AACrB,OAAI,OAAO,KAAK,SAAS,CAAC,SAAS,EACjC,OAAM,UAAU,UAAU,SAAS;OAEnC,OAAM,GAAG,UAAU,EAAE,OAAO,MAAM,CAAC;;YAG9B,MAAM,SAAS,cAAc,KAAK,MAAM;EACjD,MAAM,UAAU,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,IAAI,KAAK,KAAK;AAC9E,MAAI,KAAK,OACP,OAAM,GAAG,KAAK,SAAS,GAAG,KAAK,OAAO,OAAO,EAAE,EAAE,OAAO,MAAM,CAAC;MAE/D,KAAI;AACF,SAAM,GAAG,SAAS;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;UAC7C;YAID,KAAK,OAEd,OAAM,GADW,SAAS,aAAa,OAAO,KAAK,EAChC,EAAE,OAAO,MAAM,CAAC;MAC9B;EAEL,MAAM,UAAU,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,GAAG;AACnE,MAAI;AACF,SAAM,GAAG,SAAS;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;UAC7C"}
1
+ {"version":3,"file":"meta-manager-C900rEyG.mjs","names":[],"sources":["../src/core/meta-manager.ts"],"sourcesContent":["import type { ModelDefinition, EntryMeta } from '@contentrain/types'\nimport { join } from 'node:path'\nimport { rm } from 'node:fs/promises'\nimport { contentrainDir, readJson, writeJson } from '../util/fs.js'\n\ninterface MetaOpts {\n locale?: string\n entryId?: string\n slug?: string\n}\n\nfunction metaPath(projectRoot: string, model: ModelDefinition, opts: MetaOpts): string {\n const base = join(contentrainDir(projectRoot), 'meta', model.id)\n\n if (model.kind === 'document' && opts.slug) {\n return join(base, opts.slug, `${opts.locale ?? 'en'}.json`)\n }\n\n return join(base, `${opts.locale ?? 'en'}.json`)\n}\n\nexport async function readMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n): Promise<EntryMeta | Record<string, EntryMeta> | null> {\n return readJson(metaPath(projectRoot, model, opts))\n}\n\nexport async function writeMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n meta: EntryMeta,\n): Promise<void> {\n const filePath = metaPath(projectRoot, model, opts)\n\n if (model.kind === 'collection' && opts.entryId) {\n const existing = await readJson<Record<string, EntryMeta>>(filePath) ?? {}\n existing[opts.entryId] = meta\n await writeJson(filePath, existing)\n } else {\n await writeJson(filePath, meta)\n }\n}\n\nexport async function deleteMeta(\n projectRoot: string,\n model: ModelDefinition,\n opts: MetaOpts,\n): Promise<void> {\n if (model.kind === 'collection' && opts.entryId) {\n const filePath = metaPath(projectRoot, model, opts)\n const existing = await readJson<Record<string, EntryMeta>>(filePath)\n if (existing && opts.entryId in existing) {\n delete existing[opts.entryId]\n if (Object.keys(existing).length > 0) {\n await writeJson(filePath, existing)\n } else {\n await rm(filePath, { force: true })\n }\n }\n } else if (model.kind === 'document' && opts.slug) {\n const slugDir = join(contentrainDir(projectRoot), 'meta', model.id, opts.slug)\n if (opts.locale) {\n await rm(join(slugDir, `${opts.locale}.json`), { force: true })\n } else {\n try {\n await rm(slugDir, { recursive: true, force: true })\n } catch {\n // directory may not exist\n }\n }\n } else if (opts.locale) {\n const filePath = metaPath(projectRoot, model, opts)\n await rm(filePath, { force: true })\n } else {\n // No locale specified — remove all meta for this model (non-i18n or full cleanup)\n const metaDir = join(contentrainDir(projectRoot), 'meta', model.id)\n try {\n await rm(metaDir, { recursive: true, force: true })\n } catch {\n // directory may not exist\n }\n }\n}\n"],"mappings":";;;;AAWA,SAAS,SAAS,aAAqB,OAAwB,MAAwB;CACrF,MAAM,OAAO,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,GAAG;AAEhE,KAAI,MAAM,SAAS,cAAc,KAAK,KACpC,QAAO,KAAK,MAAM,KAAK,MAAM,GAAG,KAAK,UAAU,KAAK,OAAO;AAG7D,QAAO,KAAK,MAAM,GAAG,KAAK,UAAU,KAAK,OAAO;;AAGlD,eAAsB,SACpB,aACA,OACA,MACuD;AACvD,QAAO,SAAS,SAAS,aAAa,OAAO,KAAK,CAAC;;AAGrD,eAAsB,UACpB,aACA,OACA,MACA,MACe;CACf,MAAM,WAAW,SAAS,aAAa,OAAO,KAAK;AAEnD,KAAI,MAAM,SAAS,gBAAgB,KAAK,SAAS;EAC/C,MAAM,WAAW,MAAM,SAAoC,SAAS,IAAI,EAAE;AAC1E,WAAS,KAAK,WAAW;AACzB,QAAM,UAAU,UAAU,SAAS;OAEnC,OAAM,UAAU,UAAU,KAAK;;AAInC,eAAsB,WACpB,aACA,OACA,MACe;AACf,KAAI,MAAM,SAAS,gBAAgB,KAAK,SAAS;EAC/C,MAAM,WAAW,SAAS,aAAa,OAAO,KAAK;EACnD,MAAM,WAAW,MAAM,SAAoC,SAAS;AACpE,MAAI,YAAY,KAAK,WAAW,UAAU;AACxC,UAAO,SAAS,KAAK;AACrB,OAAI,OAAO,KAAK,SAAS,CAAC,SAAS,EACjC,OAAM,UAAU,UAAU,SAAS;OAEnC,OAAM,GAAG,UAAU,EAAE,OAAO,MAAM,CAAC;;YAG9B,MAAM,SAAS,cAAc,KAAK,MAAM;EACjD,MAAM,UAAU,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,IAAI,KAAK,KAAK;AAC9E,MAAI,KAAK,OACP,OAAM,GAAG,KAAK,SAAS,GAAG,KAAK,OAAO,OAAO,EAAE,EAAE,OAAO,MAAM,CAAC;MAE/D,KAAI;AACF,SAAM,GAAG,SAAS;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;UAC7C;YAID,KAAK,OAEd,OAAM,GADW,SAAS,aAAa,OAAO,KAAK,EAChC,EAAE,OAAO,MAAM,CAAC;MAC9B;EAEL,MAAM,UAAU,KAAK,eAAe,YAAY,EAAE,QAAQ,MAAM,GAAG;AACnE,MAAI;AACF,SAAM,GAAG,SAAS;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;UAC7C"}