lurqrun 0.1.6 → 0.1.8

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 (239) hide show
  1. package/README.md +311 -139
  2. package/dist/auditHandler-VWCXSDVO.js +24 -0
  3. package/dist/autopilotInit-Q62MX5M6.js +178 -0
  4. package/dist/bin/lurq.js +3255 -23319
  5. package/dist/browserAuth-J7APSD4P.js +96 -0
  6. package/dist/cache-AEAKCV4I.js +12 -0
  7. package/dist/check-2JTQDQA6.js +2613 -0
  8. package/dist/check-PQSQ2MMA.js +192 -0
  9. package/dist/checkUpgrade-5YW77OBL.js +24 -0
  10. package/dist/chunk-2GAYNIHG.js +40 -0
  11. package/dist/chunk-2O6Z37IT.js +423 -0
  12. package/dist/chunk-2WD4QAH4.js +116 -0
  13. package/dist/chunk-3676XOBU.js +2235 -0
  14. package/dist/chunk-3D2MPGOQ.js +181 -0
  15. package/dist/chunk-3GHJR7XR.js +2049 -0
  16. package/dist/chunk-4ESO33J6.js +34 -0
  17. package/dist/chunk-4JHDSVIN.js +1229 -0
  18. package/dist/chunk-4KCPOMG6.js +68 -0
  19. package/dist/chunk-53SG6XWA.js +141 -0
  20. package/dist/chunk-5ABNDB3I.js +37 -0
  21. package/dist/chunk-5ALIJFDA.js +114 -0
  22. package/dist/chunk-63MUJNZL.js +318 -0
  23. package/dist/chunk-64ZF7KO4.js +1571 -0
  24. package/dist/chunk-6DM6UQFD.js +318 -0
  25. package/dist/chunk-6EQ3ARXA.js +304 -0
  26. package/dist/chunk-6L67QMCP.js +92 -0
  27. package/dist/chunk-72Y2FDVS.js +172 -0
  28. package/dist/chunk-A3TYI2TF.js +288 -0
  29. package/dist/chunk-B2UUYRBX.js +536 -0
  30. package/dist/chunk-BJT2LHAR.js +320 -0
  31. package/dist/chunk-BM3LF5T6.js +132 -0
  32. package/dist/chunk-BN3NM47Q.js +214 -0
  33. package/dist/chunk-BUALU27S.js +123 -0
  34. package/dist/chunk-C6GLE626.js +160 -0
  35. package/dist/chunk-D3K6IZVR.js +12845 -0
  36. package/dist/chunk-D3VTZS7V.js +222 -0
  37. package/dist/chunk-DM37MTOO.js +636 -0
  38. package/dist/chunk-DONTW3NE.js +171 -0
  39. package/dist/chunk-DSROTZ3Z.js +38 -0
  40. package/dist/chunk-ELGCAM7P.js +184 -0
  41. package/dist/chunk-EQCXENKZ.js +130 -0
  42. package/dist/chunk-EYAKM6YN.js +96 -0
  43. package/dist/chunk-FDFPMBCA.js +112 -0
  44. package/dist/chunk-FVYFV5HA.js +154 -0
  45. package/dist/chunk-GE37NVLN.js +15 -0
  46. package/dist/chunk-GM5Y555O.js +143 -0
  47. package/dist/chunk-GRJXQBQZ.js +793 -0
  48. package/dist/chunk-HWFX4BC4.js +177 -0
  49. package/dist/chunk-I3M2KJXB.js +56 -0
  50. package/dist/chunk-IFNONGRQ.js +603 -0
  51. package/dist/chunk-J3U2CPSK.js +136 -0
  52. package/dist/chunk-J6XQ7OPZ.js +74 -0
  53. package/dist/chunk-KMV4Y6R3.js +127 -0
  54. package/dist/chunk-KP5ZDDPE.js +340 -0
  55. package/dist/chunk-KYKSZ3XZ.js +202 -0
  56. package/dist/chunk-LEGPB7DO.js +81 -0
  57. package/dist/chunk-LUAKDHLZ.js +40 -0
  58. package/dist/chunk-MHUEVBVO.js +35 -0
  59. package/dist/chunk-MYGSLK44.js +37 -0
  60. package/dist/chunk-NEZNAPPN.js +41 -0
  61. package/dist/chunk-NPVN2THM.js +197 -0
  62. package/dist/chunk-NYZU5NCW.js +23 -0
  63. package/dist/chunk-O4KHCV6I.js +320 -0
  64. package/dist/chunk-ONDVTXUO.js +240 -0
  65. package/dist/chunk-OTJFHESY.js +176 -0
  66. package/dist/chunk-P6MIKSPY.js +243 -0
  67. package/dist/chunk-Q5VPF4WI.js +26 -0
  68. package/dist/chunk-QCRBX3LV.js +165 -0
  69. package/dist/chunk-QKGYDMWB.js +7409 -0
  70. package/dist/chunk-QSL6QN5X.js +115 -0
  71. package/dist/chunk-QUIMQ7YL.js +73 -0
  72. package/dist/chunk-RG3YLU6E.js +49 -0
  73. package/dist/chunk-SHCEBP3J.js +107 -0
  74. package/dist/chunk-SHZFOSXC.js +462 -0
  75. package/dist/chunk-SOXFMMXC.js +151 -0
  76. package/dist/chunk-TDTYV6QI.js +119 -0
  77. package/dist/chunk-TNTXWSYA.js +19 -0
  78. package/dist/chunk-TUXQ32WE.js +2251 -0
  79. package/dist/chunk-VGCDRK3S.js +37 -0
  80. package/dist/chunk-VLRHFMGJ.js +58 -0
  81. package/dist/chunk-WHX2ZFCG.js +4048 -0
  82. package/dist/chunk-X4W64MHU.js +2005 -0
  83. package/dist/chunk-XBQA4I36.js +92 -0
  84. package/dist/chunk-XGOV6KV4.js +413 -0
  85. package/dist/chunk-XIFQIFSZ.js +940 -0
  86. package/dist/chunk-XLXPVN3Y.js +15393 -0
  87. package/dist/chunk-ZJMLQ37G.js +90 -0
  88. package/dist/client-MU4EUDZV.js +15 -0
  89. package/dist/commands-UOOTMBKA.js +1023 -0
  90. package/dist/compat-Q5DVPITN.js +201 -0
  91. package/dist/constants-DJFOFZ44.js +24 -0
  92. package/dist/dashboardIssue-KBKLQMGC.js +274 -0
  93. package/dist/diff-I4SNUHU3.js +13 -0
  94. package/dist/dist-4XXIXHHZ.js +12945 -0
  95. package/dist/domains-VRT4BRVZ.js +14 -0
  96. package/dist/e2b-FVPHDULZ.js +172 -0
  97. package/dist/env-UN6KGZ7S.js +15 -0
  98. package/dist/envCheck-KUPTORFQ.js +71 -0
  99. package/dist/extract-6WG265BL.js +455 -0
  100. package/dist/fetch-PJ3SC32M.js +22 -0
  101. package/dist/firstTouch-COJCMOB3.js +55 -0
  102. package/dist/fix-3EDWNKW3.js +220 -0
  103. package/dist/handlers-4Q37WIFT.js +55 -0
  104. package/dist/hook-NA66XJLC.js +412 -0
  105. package/dist/http-25GJ6SKK.js +6928 -0
  106. package/dist/ingestQueue-FSVJC3AA.js +37 -0
  107. package/dist/install-G2HHXYJ2.js +20 -0
  108. package/dist/installSkill-5TIMYIJZ.js +70 -0
  109. package/dist/inventory-5AWSLJYU.js +31 -0
  110. package/dist/local-XPZMRH5R.js +13 -0
  111. package/dist/manifest-ENMIC54B.js +13 -0
  112. package/dist/mcp-PENLL2PK.js +500 -0
  113. package/dist/mcpConfig-3LYPRY5Q.js +80 -0
  114. package/dist/mcpHandlers-PO7GENA7.js +22 -0
  115. package/dist/mcpScan-ULP626TQ.js +1735 -0
  116. package/dist/mcpScanWorkflow-27O44FOE.js +98 -0
  117. package/dist/mcpStack-ZNYIFXZ5.js +20 -0
  118. package/dist/model-ASMZWLM7.js +214 -0
  119. package/dist/packages-RWF2LXST.js +40 -0
  120. package/dist/plan-SDILIDZT.js +465 -0
  121. package/dist/planView-ZAKRTGVS.js +82 -0
  122. package/dist/policy-JAGNMQJI.js +115 -0
  123. package/dist/probe-3IK646WN.js +610 -0
  124. package/dist/publicUpgrades-WTBGLDIK.js +42 -0
  125. package/dist/references-I6Y4BSRR.js +16 -0
  126. package/dist/release-7IU2R4YG.js +128 -0
  127. package/dist/remote-FN6225AH.js +42 -0
  128. package/dist/rename-OS6JYBZQ.js +204 -0
  129. package/dist/reportRuns-O4X7ZFTX.js +77 -0
  130. package/dist/safeFetch-COERXGFN.js +19 -0
  131. package/dist/sandbox-SAPSRKEI.js +39 -0
  132. package/dist/sarif-WLVJFJ7U.js +125 -0
  133. package/dist/server-OLTY3NYT.js +59 -0
  134. package/dist/surface-7MHE3RL7.js +143 -0
  135. package/dist/surface-JS2XU3U3.js +38 -0
  136. package/dist/surfaceHandlers-4B6TMZ34.js +20 -0
  137. package/dist/typecheck-NGOKNAJY.js +282 -0
  138. package/dist/types-M5JP2W3D.js +10 -0
  139. package/dist/uninstall-I2IJP5JZ.js +200 -0
  140. package/dist/upgrade-FS26DJGG.js +650 -0
  141. package/dist/upgradePlan-ZS5IOVMZ.js +181 -0
  142. package/dist/upkeepHandler-VFGYXJKB.js +13 -0
  143. package/dist/userConfig-ICASHI47.js +20 -0
  144. package/dist/watch-OCNEUXG6.js +204 -0
  145. package/package.json +26 -20
  146. package/templates/agent-rules.md +4 -4
  147. package/templates/skill-instructions.md +35 -17
  148. package/dist/bin/lurq.js.map +0 -1
  149. package/dist/index.d.ts +0 -805
  150. package/dist/index.js +0 -23570
  151. package/dist/index.js.map +0 -1
  152. package/drizzle/0000_confused_fabian_cortez.sql +0 -54
  153. package/drizzle/0001_aspiring_timeslip.sql +0 -15
  154. package/drizzle/0002_lyrical_lila_cheney.sql +0 -14
  155. package/drizzle/0003_violet_giant_girl.sql +0 -14
  156. package/drizzle/0004_slim_valeria_richards.sql +0 -15
  157. package/drizzle/0005_petite_luke_cage.sql +0 -12
  158. package/drizzle/0006_calm_nighthawk.sql +0 -3
  159. package/drizzle/0007_slimy_naoko.sql +0 -1
  160. package/drizzle/0008_peaceful_tigra.sql +0 -1
  161. package/drizzle/0009_smooth_harrier.sql +0 -10
  162. package/drizzle/0010_curved_amphibian.sql +0 -2
  163. package/drizzle/0011_compat_provenance_closures.sql +0 -11
  164. package/drizzle/0012_api_surfaces.sql +0 -9
  165. package/drizzle/0013_nice_thanos.sql +0 -1
  166. package/drizzle/0014_luxuriant_malcolm_colcord.sql +0 -10
  167. package/drizzle/0015_past_fat_cobra.sql +0 -11
  168. package/drizzle/0016_futuristic_junta.sql +0 -50
  169. package/drizzle/0017_absent_grandmaster.sql +0 -20
  170. package/drizzle/0018_rainy_proemial_gods.sql +0 -1
  171. package/drizzle/0019_dashing_korvac.sql +0 -11
  172. package/drizzle/0020_normal_vulture.sql +0 -3
  173. package/drizzle/0021_dazzling_blue_shield.sql +0 -17
  174. package/drizzle/0022_massive_ghost_rider.sql +0 -24
  175. package/drizzle/0023_next_shatterstar.sql +0 -1
  176. package/drizzle/0024_dusty_maelstrom.sql +0 -15
  177. package/drizzle/0025_gifted_harpoon.sql +0 -5
  178. package/drizzle/0026_awesome_mordo.sql +0 -1
  179. package/drizzle/0027_charming_ulik.sql +0 -2
  180. package/drizzle/0028_romantic_loners.sql +0 -2
  181. package/drizzle/0029_busy_korvac.sql +0 -16
  182. package/drizzle/0030_steady_mathemanic.sql +0 -6
  183. package/drizzle/0031_redundant_maginty.sql +0 -2
  184. package/drizzle/0032_stack_resolutions.sql +0 -14
  185. package/drizzle/0033_graceful_tyger_tiger.sql +0 -3
  186. package/drizzle/0034_uneven_thunderbird.sql +0 -1
  187. package/drizzle/0035_api_key_scopes.sql +0 -1
  188. package/drizzle/0036_policy_audit.sql +0 -21
  189. package/drizzle/0037_subscription_seats.sql +0 -1
  190. package/drizzle/0038_symbol_offsets.sql +0 -2
  191. package/drizzle/0039_mcp_runtime_scans.sql +0 -80
  192. package/drizzle/0040_subscription_overage_and_interval.sql +0 -4
  193. package/drizzle/0041_account_email.sql +0 -38
  194. package/drizzle/0042_alert_channels.sql +0 -21
  195. package/drizzle/meta/0000_snapshot.json +0 -370
  196. package/drizzle/meta/0001_snapshot.json +0 -482
  197. package/drizzle/meta/0002_snapshot.json +0 -575
  198. package/drizzle/meta/0003_snapshot.json +0 -667
  199. package/drizzle/meta/0004_snapshot.json +0 -769
  200. package/drizzle/meta/0005_snapshot.json +0 -864
  201. package/drizzle/meta/0006_snapshot.json +0 -882
  202. package/drizzle/meta/0007_snapshot.json +0 -876
  203. package/drizzle/meta/0008_snapshot.json +0 -882
  204. package/drizzle/meta/0009_snapshot.json +0 -948
  205. package/drizzle/meta/0010_snapshot.json +0 -969
  206. package/drizzle/meta/0011_snapshot.json +0 -1049
  207. package/drizzle/meta/0012_snapshot.json +0 -1115
  208. package/drizzle/meta/0013_snapshot.json +0 -1121
  209. package/drizzle/meta/0014_snapshot.json +0 -1190
  210. package/drizzle/meta/0015_snapshot.json +0 -1280
  211. package/drizzle/meta/0016_snapshot.json +0 -1683
  212. package/drizzle/meta/0017_snapshot.json +0 -1834
  213. package/drizzle/meta/0018_snapshot.json +0 -1834
  214. package/drizzle/meta/0019_snapshot.json +0 -1909
  215. package/drizzle/meta/0020_snapshot.json +0 -1921
  216. package/drizzle/meta/0021_snapshot.json +0 -2045
  217. package/drizzle/meta/0022_snapshot.json +0 -2246
  218. package/drizzle/meta/0023_snapshot.json +0 -2252
  219. package/drizzle/meta/0024_snapshot.json +0 -2375
  220. package/drizzle/meta/0025_snapshot.json +0 -2407
  221. package/drizzle/meta/0026_snapshot.json +0 -2413
  222. package/drizzle/meta/0027_snapshot.json +0 -2425
  223. package/drizzle/meta/0028_snapshot.json +0 -2438
  224. package/drizzle/meta/0029_snapshot.json +0 -2546
  225. package/drizzle/meta/0030_snapshot.json +0 -2586
  226. package/drizzle/meta/0031_snapshot.json +0 -2598
  227. package/drizzle/meta/0032_snapshot.json +0 -2699
  228. package/drizzle/meta/0033_snapshot.json +0 -2712
  229. package/drizzle/meta/0034_snapshot.json +0 -2719
  230. package/drizzle/meta/0035_snapshot.json +0 -2726
  231. package/drizzle/meta/0036_snapshot.json +0 -2876
  232. package/drizzle/meta/0037_snapshot.json +0 -2883
  233. package/drizzle/meta/0038_snapshot.json +0 -2895
  234. package/drizzle/meta/0039_snapshot.json +0 -3501
  235. package/drizzle/meta/0040_snapshot.json +0 -3527
  236. package/drizzle/meta/0041_snapshot.json +0 -3824
  237. package/drizzle/meta/0042_snapshot.json +0 -3960
  238. package/drizzle/meta/_journal.json +0 -307
  239. package/src/data/seed.json +0 -253
@@ -0,0 +1,178 @@
1
+ import { createRequire as __lurqCreateRequire } from 'node:module'; const require = __lurqCreateRequire(import.meta.url);
2
+ import {
3
+ WORKFLOW_PATH,
4
+ detectInstallCommand,
5
+ renderWorkflow
6
+ } from "./chunk-A3TYI2TF.js";
7
+ import {
8
+ bold,
9
+ dim,
10
+ green,
11
+ yellow
12
+ } from "./chunk-4KCPOMG6.js";
13
+ import {
14
+ logger
15
+ } from "./chunk-MYGSLK44.js";
16
+ import {
17
+ resolveApiKey
18
+ } from "./chunk-J6XQ7OPZ.js";
19
+ import "./chunk-72Y2FDVS.js";
20
+ import {
21
+ init_esm_shims
22
+ } from "./chunk-I3M2KJXB.js";
23
+
24
+ // src/cli/autopilotInit.ts
25
+ init_esm_shims();
26
+ import { spawnSync } from "child_process";
27
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
28
+ import { dirname, join } from "path";
29
+ var LOCKFILES = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml", "bun.lockb", "bun.lock"];
30
+ function parseRepoFromRemote(url) {
31
+ const trimmed = url.trim().replace(/\.git$/, "");
32
+ if (!trimmed) return null;
33
+ const match = (
34
+ // git@github.com:owner/name | ssh://git@github.com/owner/name
35
+ trimmed.match(/^(?:ssh:\/\/)?git@[^:/]+[:/]([^/]+)\/([^/]+)$/) ?? // https://github.com/owner/name
36
+ trimmed.match(/^https?:\/\/[^/]+\/([^/]+)\/([^/]+)$/)
37
+ );
38
+ if (!match) return null;
39
+ const [, owner, name] = match;
40
+ return owner && name ? `${owner}/${name}` : null;
41
+ }
42
+ function needsAgentCredential(mode) {
43
+ return mode === "pr";
44
+ }
45
+ function parseMode(raw) {
46
+ if (!raw) return "fix";
47
+ if (raw === "comment" || raw === "fix" || raw === "pr") return raw;
48
+ throw new Error(`Unknown mode "${raw}". Use comment, fix, or pr.`);
49
+ }
50
+ function run(cmd, args, cwd) {
51
+ return spawnSync(cmd, args, { cwd, encoding: "utf8" });
52
+ }
53
+ function have(cmd) {
54
+ const res = run(cmd, ["--version"]);
55
+ return res.status === 0;
56
+ }
57
+ function setSecret(repo, name, value) {
58
+ const res = spawnSync("gh", ["secret", "set", name, "--repo", repo], {
59
+ input: value,
60
+ encoding: "utf8"
61
+ });
62
+ if (res.status !== 0) {
63
+ logger.error(` could not set ${name}: ${(res.stderr || res.stdout || "").trim()}`);
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+ function mintClaudeToken() {
69
+ const res = spawnSync("claude", ["setup-token"], {
70
+ stdio: ["inherit", "pipe", "inherit"],
71
+ encoding: "utf8"
72
+ });
73
+ if (res.status !== 0) return null;
74
+ const lines = (res.stdout ?? "").split("\n").map((l) => l.trim()).filter(Boolean);
75
+ const token = lines[lines.length - 1];
76
+ if (!token || token.includes(" ") || token.length < 20) return null;
77
+ return token;
78
+ }
79
+ async function runAutopilotInit(opts) {
80
+ const cwd = opts.cwd ?? process.cwd();
81
+ const mode = parseMode(opts.mode);
82
+ const done = [];
83
+ const todo = [];
84
+ let repo = opts.repo?.trim();
85
+ if (!repo) {
86
+ const remote = run("git", ["remote", "get-url", "origin"], cwd);
87
+ repo = remote.status === 0 && parseRepoFromRemote(remote.stdout) || void 0;
88
+ }
89
+ if (!repo) {
90
+ logger.error("Could not work out which repository this is.");
91
+ logger.error("Pass it: lurq autopilot init --repo owner/name");
92
+ process.exitCode = 1;
93
+ return;
94
+ }
95
+ const apiKey = resolveApiKey(opts.apiKey);
96
+ if (!apiKey) {
97
+ logger.error("No lurq API key on this machine. Run `lurq setup` first, then this again.");
98
+ process.exitCode = 1;
99
+ return;
100
+ }
101
+ if (!have("gh")) {
102
+ logger.error("The GitHub CLI (`gh`) is not installed. https://cli.github.com");
103
+ process.exitCode = 1;
104
+ return;
105
+ }
106
+ if (run("gh", ["auth", "status"]).status !== 0) {
107
+ logger.error("`gh` is not signed in. Run `gh auth login`, then this again.");
108
+ process.exitCode = 1;
109
+ return;
110
+ }
111
+ logger.info(`${bold("repository")} ${repo}`);
112
+ logger.info(`${bold("mode")} ${mode}
113
+ `);
114
+ if (setSecret(repo, "LURQ_API_KEY", apiKey)) done.push("LURQ_API_KEY set as a repository secret");
115
+ else {
116
+ process.exitCode = 1;
117
+ return;
118
+ }
119
+ const path = join(cwd, WORKFLOW_PATH);
120
+ if (existsSync(path) && !opts.force) {
121
+ done.push(`${WORKFLOW_PATH} already exists (left alone; --force overwrites)`);
122
+ } else {
123
+ const lockfiles = LOCKFILES.filter((f) => existsSync(join(cwd, f)));
124
+ mkdirSync(dirname(path), { recursive: true });
125
+ writeFileSync(path, renderWorkflow({ mode, installCommand: detectInstallCommand(lockfiles) }));
126
+ done.push(`${WORKFLOW_PATH} written`);
127
+ }
128
+ if (needsAgentCredential(mode) && opts.credential !== false) {
129
+ if (!have("claude")) {
130
+ todo.push(
131
+ `Set ANTHROPIC_API_KEY (from the Anthropic console) as a repository secret \u2014 pr mode fails without a credential:
132
+ gh secret set ANTHROPIC_API_KEY --repo ${repo}`
133
+ );
134
+ } else {
135
+ logger.info(dim("Minting a Claude token \u2014 sign in when prompted."));
136
+ const token = mintClaudeToken();
137
+ if (token && setSecret(repo, "CLAUDE_CODE_OAUTH_TOKEN", token)) {
138
+ done.push("CLAUDE_CODE_OAUTH_TOKEN set as a repository secret");
139
+ todo.push(
140
+ yellow("That token expires one year from today, with no warning.") + " This is a scheduled job, so it will work for a year and then stop.\n An ANTHROPIC_API_KEY from the console does not expire, and is the right one if anyone else maintains this repo."
141
+ );
142
+ } else {
143
+ todo.push(
144
+ `Could not read a token back from \`claude setup-token\`. Set one by hand:
145
+ claude setup-token
146
+ gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo ${repo}`
147
+ );
148
+ }
149
+ }
150
+ }
151
+ todo.push(
152
+ `Read the workflow, then commit it \u2014 that commit is what grants write access:
153
+ git add ${WORKFLOW_PATH} && git commit -m "ci: lurq upgrade autopilot" && git push`
154
+ );
155
+ if (opts.json) {
156
+ logger.info(JSON.stringify({ repo, mode, done, todo: todo.length }, null, 2));
157
+ return;
158
+ }
159
+ logger.info("");
160
+ for (const line of done) logger.info(`${green("\u2713")} ${line}`);
161
+ logger.info(`
162
+ ${bold("Next")}`);
163
+ for (const line of todo) logger.info(` \xB7 ${line}`);
164
+ }
165
+ function workflowExists(cwd) {
166
+ return existsSync(join(cwd, WORKFLOW_PATH));
167
+ }
168
+ function readWorkflow(cwd) {
169
+ const path = join(cwd, WORKFLOW_PATH);
170
+ return existsSync(path) ? readFileSync(path, "utf8") : null;
171
+ }
172
+ export {
173
+ needsAgentCredential,
174
+ parseRepoFromRemote,
175
+ readWorkflow,
176
+ runAutopilotInit,
177
+ workflowExists
178
+ };