hacklab 0.22.2 → 26.921.1

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 (259) hide show
  1. package/README.md +23 -430
  2. package/dist/index.js +132 -23
  3. package/package.json +20 -42
  4. package/LICENSE +0 -21
  5. package/dist/agent-handoff.d.ts +0 -51
  6. package/dist/agent-handoff.d.ts.map +0 -1
  7. package/dist/agent-handoff.js +0 -91
  8. package/dist/agent-handoff.js.map +0 -1
  9. package/dist/api-client.d.ts +0 -18
  10. package/dist/api-client.d.ts.map +0 -1
  11. package/dist/api-client.js +0 -40
  12. package/dist/api-client.js.map +0 -1
  13. package/dist/belt.d.ts +0 -25
  14. package/dist/belt.d.ts.map +0 -1
  15. package/dist/belt.js +0 -113
  16. package/dist/belt.js.map +0 -1
  17. package/dist/card.d.ts +0 -66
  18. package/dist/card.d.ts.map +0 -1
  19. package/dist/card.js +0 -151
  20. package/dist/card.js.map +0 -1
  21. package/dist/cli.d.ts +0 -2
  22. package/dist/cli.d.ts.map +0 -1
  23. package/dist/cli.js +0 -238
  24. package/dist/cli.js.map +0 -1
  25. package/dist/commands/book.d.ts +0 -14
  26. package/dist/commands/book.d.ts.map +0 -1
  27. package/dist/commands/book.js +0 -90
  28. package/dist/commands/book.js.map +0 -1
  29. package/dist/commands/chat.d.ts +0 -36
  30. package/dist/commands/chat.d.ts.map +0 -1
  31. package/dist/commands/chat.js +0 -642
  32. package/dist/commands/chat.js.map +0 -1
  33. package/dist/commands/config.d.ts +0 -2
  34. package/dist/commands/config.d.ts.map +0 -1
  35. package/dist/commands/config.js +0 -84
  36. package/dist/commands/config.js.map +0 -1
  37. package/dist/commands/daemon.d.ts +0 -19
  38. package/dist/commands/daemon.d.ts.map +0 -1
  39. package/dist/commands/daemon.js +0 -72
  40. package/dist/commands/daemon.js.map +0 -1
  41. package/dist/commands/drop.d.ts +0 -12
  42. package/dist/commands/drop.d.ts.map +0 -1
  43. package/dist/commands/drop.js +0 -103
  44. package/dist/commands/drop.js.map +0 -1
  45. package/dist/commands/drops.d.ts +0 -9
  46. package/dist/commands/drops.d.ts.map +0 -1
  47. package/dist/commands/drops.js +0 -96
  48. package/dist/commands/drops.js.map +0 -1
  49. package/dist/commands/essay.d.ts +0 -40
  50. package/dist/commands/essay.d.ts.map +0 -1
  51. package/dist/commands/essay.js +0 -651
  52. package/dist/commands/essay.js.map +0 -1
  53. package/dist/commands/hackathon.d.ts +0 -2
  54. package/dist/commands/hackathon.d.ts.map +0 -1
  55. package/dist/commands/hackathon.js +0 -893
  56. package/dist/commands/hackathon.js.map +0 -1
  57. package/dist/commands/hacker.d.ts +0 -2
  58. package/dist/commands/hacker.d.ts.map +0 -1
  59. package/dist/commands/hacker.js +0 -87
  60. package/dist/commands/hacker.js.map +0 -1
  61. package/dist/commands/jobs.d.ts +0 -18
  62. package/dist/commands/jobs.d.ts.map +0 -1
  63. package/dist/commands/jobs.js +0 -138
  64. package/dist/commands/jobs.js.map +0 -1
  65. package/dist/commands/keys.d.ts +0 -2
  66. package/dist/commands/keys.d.ts.map +0 -1
  67. package/dist/commands/keys.js +0 -138
  68. package/dist/commands/keys.js.map +0 -1
  69. package/dist/commands/login.d.ts +0 -83
  70. package/dist/commands/login.d.ts.map +0 -1
  71. package/dist/commands/login.js +0 -236
  72. package/dist/commands/login.js.map +0 -1
  73. package/dist/commands/logout.d.ts +0 -2
  74. package/dist/commands/logout.d.ts.map +0 -1
  75. package/dist/commands/logout.js +0 -22
  76. package/dist/commands/logout.js.map +0 -1
  77. package/dist/commands/org-jobs.d.ts +0 -50
  78. package/dist/commands/org-jobs.d.ts.map +0 -1
  79. package/dist/commands/org-jobs.js +0 -383
  80. package/dist/commands/org-jobs.js.map +0 -1
  81. package/dist/commands/org.d.ts +0 -67
  82. package/dist/commands/org.d.ts.map +0 -1
  83. package/dist/commands/org.js +0 -1244
  84. package/dist/commands/org.js.map +0 -1
  85. package/dist/commands/ping.d.ts +0 -2
  86. package/dist/commands/ping.d.ts.map +0 -1
  87. package/dist/commands/ping.js +0 -50
  88. package/dist/commands/ping.js.map +0 -1
  89. package/dist/commands/profile.d.ts +0 -72
  90. package/dist/commands/profile.d.ts.map +0 -1
  91. package/dist/commands/profile.js +0 -672
  92. package/dist/commands/profile.js.map +0 -1
  93. package/dist/commands/project.d.ts +0 -2
  94. package/dist/commands/project.d.ts.map +0 -1
  95. package/dist/commands/project.js +0 -583
  96. package/dist/commands/project.js.map +0 -1
  97. package/dist/commands/referral.d.ts +0 -6
  98. package/dist/commands/referral.d.ts.map +0 -1
  99. package/dist/commands/referral.js +0 -93
  100. package/dist/commands/referral.js.map +0 -1
  101. package/dist/commands/rtfm.d.ts +0 -9
  102. package/dist/commands/rtfm.d.ts.map +0 -1
  103. package/dist/commands/rtfm.js +0 -114
  104. package/dist/commands/rtfm.js.map +0 -1
  105. package/dist/commands/scan.d.ts +0 -13
  106. package/dist/commands/scan.d.ts.map +0 -1
  107. package/dist/commands/scan.js +0 -286
  108. package/dist/commands/scan.js.map +0 -1
  109. package/dist/commands/scout.d.ts +0 -18
  110. package/dist/commands/scout.d.ts.map +0 -1
  111. package/dist/commands/scout.js +0 -232
  112. package/dist/commands/scout.js.map +0 -1
  113. package/dist/commands/setup-rail.d.ts +0 -58
  114. package/dist/commands/setup-rail.d.ts.map +0 -1
  115. package/dist/commands/setup-rail.js +0 -135
  116. package/dist/commands/setup-rail.js.map +0 -1
  117. package/dist/commands/setup.d.ts +0 -29
  118. package/dist/commands/setup.d.ts.map +0 -1
  119. package/dist/commands/setup.js +0 -442
  120. package/dist/commands/setup.js.map +0 -1
  121. package/dist/commands/sync.d.ts +0 -9
  122. package/dist/commands/sync.d.ts.map +0 -1
  123. package/dist/commands/sync.js +0 -345
  124. package/dist/commands/sync.js.map +0 -1
  125. package/dist/commands/update.d.ts +0 -2
  126. package/dist/commands/update.d.ts.map +0 -1
  127. package/dist/commands/update.js +0 -92
  128. package/dist/commands/update.js.map +0 -1
  129. package/dist/commands/whoami.d.ts +0 -2
  130. package/dist/commands/whoami.d.ts.map +0 -1
  131. package/dist/commands/whoami.js +0 -41
  132. package/dist/commands/whoami.js.map +0 -1
  133. package/dist/config.d.ts +0 -78
  134. package/dist/config.d.ts.map +0 -1
  135. package/dist/config.js +0 -93
  136. package/dist/config.js.map +0 -1
  137. package/dist/daily-sync.d.ts +0 -150
  138. package/dist/daily-sync.d.ts.map +0 -1
  139. package/dist/daily-sync.js +0 -665
  140. package/dist/daily-sync.js.map +0 -1
  141. package/dist/dossier.d.ts +0 -73
  142. package/dist/dossier.d.ts.map +0 -1
  143. package/dist/dossier.js +0 -141
  144. package/dist/dossier.js.map +0 -1
  145. package/dist/field-normalize.d.ts +0 -4
  146. package/dist/field-normalize.d.ts.map +0 -1
  147. package/dist/field-normalize.js +0 -8
  148. package/dist/field-normalize.js.map +0 -1
  149. package/dist/index.d.ts +0 -3
  150. package/dist/index.d.ts.map +0 -1
  151. package/dist/index.js.map +0 -1
  152. package/dist/job-fields.d.ts +0 -47
  153. package/dist/job-fields.d.ts.map +0 -1
  154. package/dist/job-fields.js +0 -148
  155. package/dist/job-fields.js.map +0 -1
  156. package/dist/machine.d.ts +0 -15
  157. package/dist/machine.d.ts.map +0 -1
  158. package/dist/machine.js +0 -64
  159. package/dist/machine.js.map +0 -1
  160. package/dist/org-fields.d.ts +0 -57
  161. package/dist/org-fields.d.ts.map +0 -1
  162. package/dist/org-fields.js +0 -167
  163. package/dist/org-fields.js.map +0 -1
  164. package/dist/posthog.d.ts +0 -38
  165. package/dist/posthog.d.ts.map +0 -1
  166. package/dist/posthog.js +0 -224
  167. package/dist/posthog.js.map +0 -1
  168. package/dist/project-fields.d.ts +0 -40
  169. package/dist/project-fields.d.ts.map +0 -1
  170. package/dist/project-fields.js +0 -79
  171. package/dist/project-fields.js.map +0 -1
  172. package/dist/prompt-consent.d.ts +0 -73
  173. package/dist/prompt-consent.d.ts.map +0 -1
  174. package/dist/prompt-consent.js +0 -191
  175. package/dist/prompt-consent.js.map +0 -1
  176. package/dist/prompt-stats.d.ts +0 -226
  177. package/dist/prompt-stats.d.ts.map +0 -1
  178. package/dist/prompt-stats.js +0 -561
  179. package/dist/prompt-stats.js.map +0 -1
  180. package/dist/referral.d.ts +0 -14
  181. package/dist/referral.d.ts.map +0 -1
  182. package/dist/referral.js +0 -28
  183. package/dist/referral.js.map +0 -1
  184. package/dist/registry.d.ts +0 -15
  185. package/dist/registry.d.ts.map +0 -1
  186. package/dist/registry.js +0 -180
  187. package/dist/registry.js.map +0 -1
  188. package/dist/resolve-command.d.ts +0 -20
  189. package/dist/resolve-command.d.ts.map +0 -1
  190. package/dist/resolve-command.js +0 -21
  191. package/dist/resolve-command.js.map +0 -1
  192. package/dist/scanners/antigravity.d.ts +0 -41
  193. package/dist/scanners/antigravity.d.ts.map +0 -1
  194. package/dist/scanners/antigravity.js +0 -210
  195. package/dist/scanners/antigravity.js.map +0 -1
  196. package/dist/scanners/github-copilot-telemetry.d.ts +0 -23
  197. package/dist/scanners/github-copilot-telemetry.d.ts.map +0 -1
  198. package/dist/scanners/github-copilot-telemetry.js +0 -220
  199. package/dist/scanners/github-copilot-telemetry.js.map +0 -1
  200. package/dist/scanners/github-copilot.d.ts +0 -68
  201. package/dist/scanners/github-copilot.d.ts.map +0 -1
  202. package/dist/scanners/github-copilot.js +0 -262
  203. package/dist/scanners/github-copilot.js.map +0 -1
  204. package/dist/scanners/incremental.d.ts +0 -282
  205. package/dist/scanners/incremental.d.ts.map +0 -1
  206. package/dist/scanners/incremental.js +0 -788
  207. package/dist/scanners/incremental.js.map +0 -1
  208. package/dist/scanners/index.d.ts +0 -116
  209. package/dist/scanners/index.d.ts.map +0 -1
  210. package/dist/scanners/index.js +0 -726
  211. package/dist/scanners/index.js.map +0 -1
  212. package/dist/scanners/sqlite.d.ts +0 -18
  213. package/dist/scanners/sqlite.d.ts.map +0 -1
  214. package/dist/scanners/sqlite.js +0 -63
  215. package/dist/scanners/sqlite.js.map +0 -1
  216. package/dist/scanners/util.d.ts +0 -112
  217. package/dist/scanners/util.d.ts.map +0 -1
  218. package/dist/scanners/util.js +0 -167
  219. package/dist/scanners/util.js.map +0 -1
  220. package/dist/session.d.ts +0 -106
  221. package/dist/session.d.ts.map +0 -1
  222. package/dist/session.js +0 -191
  223. package/dist/session.js.map +0 -1
  224. package/dist/share-card-colors.d.ts +0 -19
  225. package/dist/share-card-colors.d.ts.map +0 -1
  226. package/dist/share-card-colors.js +0 -36
  227. package/dist/share-card-colors.js.map +0 -1
  228. package/dist/share-card.d.ts +0 -32
  229. package/dist/share-card.d.ts.map +0 -1
  230. package/dist/share-card.js +0 -420
  231. package/dist/share-card.js.map +0 -1
  232. package/dist/share.d.ts +0 -17
  233. package/dist/share.d.ts.map +0 -1
  234. package/dist/share.js +0 -77
  235. package/dist/share.js.map +0 -1
  236. package/dist/sync.d.ts +0 -100
  237. package/dist/sync.d.ts.map +0 -1
  238. package/dist/sync.js +0 -304
  239. package/dist/sync.js.map +0 -1
  240. package/dist/ui.d.ts +0 -33
  241. package/dist/ui.d.ts.map +0 -1
  242. package/dist/ui.js +0 -127
  243. package/dist/ui.js.map +0 -1
  244. package/dist/utils/npmGlobal.d.ts +0 -30
  245. package/dist/utils/npmGlobal.d.ts.map +0 -1
  246. package/dist/utils/npmGlobal.js +0 -69
  247. package/dist/utils/npmGlobal.js.map +0 -1
  248. package/dist/utils/openBrowser.d.ts +0 -14
  249. package/dist/utils/openBrowser.d.ts.map +0 -1
  250. package/dist/utils/openBrowser.js +0 -47
  251. package/dist/utils/openBrowser.js.map +0 -1
  252. package/dist/utils/updateCheck.d.ts +0 -16
  253. package/dist/utils/updateCheck.d.ts.map +0 -1
  254. package/dist/utils/updateCheck.js +0 -111
  255. package/dist/utils/updateCheck.js.map +0 -1
  256. package/dist/utils/waitForEnter.d.ts +0 -12
  257. package/dist/utils/waitForEnter.d.ts.map +0 -1
  258. package/dist/utils/waitForEnter.js +0 -43
  259. package/dist/utils/waitForEnter.js.map +0 -1
package/package.json CHANGED
@@ -1,53 +1,31 @@
1
1
  {
2
2
  "name": "hacklab",
3
- "version": "0.22.2",
4
- "private": false,
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/hacklabubu/cli.git"
11
- },
12
- "type": "module",
13
- "packageManager": "pnpm@10.11.1",
14
- "engines": {
15
- "node": ">=20"
16
- },
3
+ "version": "26.921.1",
4
+ "description": "Bun CLI for agent-assisted Hacklab profile onboarding",
17
5
  "bin": {
18
6
  "hacklab": "./dist/index.js"
19
7
  },
20
- "files": ["dist"],
21
- "scripts": {
22
- "build": "rm -rf dist && tsc -p tsconfig.json && chmod +x dist/index.js",
23
- "prepack": "npm run build",
24
- "dev": "tsx src/index.ts",
25
- "test": "vitest run",
26
- "check": "pnpm run build && pnpm run test"
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "type": "module",
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "tag": "beta"
27
15
  },
28
- "dependencies": {
29
- "@clack/prompts": "^1.1.0",
30
- "@resvg/resvg-js": "^2.6.2",
31
- "@vercel/og": "^0.11.1",
32
- "chalk": "^5.6.2",
33
- "jsonc-parser": "^3.3.1",
34
- "posthog-node": "^5.45.2",
35
- "protobufjs": "^8.8.0",
36
- "satori": "^0.26.0",
37
- "sql.js": "^1.14.1",
38
- "string-width": "^7.2.0",
39
- "yaml": "^2.8.3",
40
- "zod": "^4.3.6"
16
+ "scripts": {
17
+ "build": "bun build src/index.ts --target=bun --outdir=dist && chmod +x dist/index.js",
18
+ "start": "bun src/index.ts",
19
+ "lint": "oxlint .",
20
+ "check-types": "tsc --noEmit",
21
+ "prepack": "bun run build",
22
+ "test": "bun test"
41
23
  },
42
24
  "devDependencies": {
43
- "@biomejs/biome": "2.4.9",
44
- "@types/node": "^25.5.0",
45
- "@types/sql.js": "^1.4.11",
46
- "tsx": "^4.21.0",
47
- "typescript": "^5.9.3",
48
- "vitest": "^4.1.2"
25
+ "@types/bun": "^1.4.2",
26
+ "typescript": "^7.0.2"
49
27
  },
50
- "pnpm": {
51
- "onlyBuiltDependencies": []
28
+ "engines": {
29
+ "bun": ">=1.4.2"
52
30
  }
53
31
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Homebrew Hackers Club inc
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,51 +0,0 @@
1
- /**
2
- * The handoff: at the end of `hacklab setup` we look for a coding-agent CLI on
3
- * the machine and, with one keypress of consent, hand it the profile-setup
4
- * prompt. The agent runs interactively in the same terminal — the user watches
5
- * it, answers its permission prompts, and (if the agent CLI is installed but
6
- * logged out) walks its own login flow. Nothing here is silent or headless.
7
- *
8
- * Every outcome is reported to the backend, because the web onboarding waits
9
- * only on positive evidence: a `launched` says an agent is running and the page
10
- * should sit on "waiting for your agent"; `declined` / `unavailable` (and no
11
- * signal at all) put the manual paste-the-prompt step up instead.
12
- */
13
- export type AgentCli = {
14
- /** Executable name, as it appears on PATH. */
15
- bin: string;
16
- /** What we call it in the terminal. */
17
- name: string;
18
- /** argv for "open interactively, seeded with this prompt". */
19
- args: (prompt: string) => string[];
20
- };
21
- /**
22
- * Probed in order — first one on PATH wins. All three take the prompt as a
23
- * single positional argument today; the shape stays per-entry so one of them
24
- * can diverge without touching the others.
25
- */
26
- export declare const AGENT_CLIS: AgentCli[];
27
- /** The first agent CLI installed on this machine, or null if there is none. */
28
- export declare function findAgentCli(): AgentCli | null;
29
- /**
30
- * Hand the terminal to `agent`, seeded with `prompt`, and block until its
31
- * session exits. Returns false when the process never started (ENOENT, a broken
32
- * shim) — the caller then treats the agent as unavailable. A non-zero exit is
33
- * still a launch: the user was there and saw whatever happened.
34
- */
35
- export declare function launchAgentCli(agent: AgentCli, prompt: string): boolean;
36
- /**
37
- * Tell the backend what happened to the profile work, so the web onboarding
38
- * knows which state to show: `launched` is the positive evidence that an agent
39
- * is now running and the page should wait for it; `declined` and `unavailable`
40
- * mean nobody took it, so the page shows the manual paste-the-prompt step
41
- * instead of waiting for a ping that is never coming.
42
- *
43
- * Best effort by design: a failure (offline, or a backend too old to know the
44
- * `launched` outcome and 400ing it) must never break the end of setup.
45
- *
46
- * Server contract (POST /api/cli/agent-handoff):
47
- * `Authorization: Bearer <session token>`, body `{ outcome, agent? }`,
48
- * where `agent` is the binary name we launched or offered (e.g. `claude`).
49
- */
50
- export declare function notifyAgentHandoff(appUrl: string, token: string, outcome: 'launched' | 'unavailable' | 'declined', agent?: string): Promise<void>;
51
- //# sourceMappingURL=agent-handoff.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-handoff.d.ts","sourceRoot":"","sources":["../src/agent-handoff.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACrB,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAA;IACX,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAA;IACZ,8DAA8D;IAC9D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,EAAE,CAAA;CACnC,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,QAAQ,EAIhC,CAAA;AA2BD,+EAA+E;AAC/E,wBAAgB,YAAY,IAAI,QAAQ,GAAG,IAAI,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAWvE;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,EAChD,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -1,91 +0,0 @@
1
- import { spawnSync } from 'node:child_process';
2
- import { accessSync, constants } from 'node:fs';
3
- import { delimiter, join } from 'node:path';
4
- /**
5
- * Probed in order — first one on PATH wins. All three take the prompt as a
6
- * single positional argument today; the shape stays per-entry so one of them
7
- * can diverge without touching the others.
8
- */
9
- export const AGENT_CLIS = [
10
- { bin: 'claude', name: 'Claude Code', args: (prompt) => [prompt] },
11
- { bin: 'codex', name: 'Codex', args: (prompt) => [prompt] },
12
- { bin: 'grok', name: 'Grok', args: (prompt) => [prompt] },
13
- ];
14
- /** Is `bin` an executable file in one of the PATH directories? */
15
- function onPath(bin) {
16
- const dirs = (process.env.PATH ?? '').split(delimiter).filter(Boolean);
17
- // On Windows the thing on PATH is `claude.cmd` / `claude.exe`, never a
18
- // bare-named file, so every candidate needs the PATHEXT suffixes tried.
19
- const exts = process.platform === 'win32'
20
- ? (process.env.PATHEXT ?? '.COM;.EXE;.BAT;.CMD')
21
- .split(';')
22
- .filter(Boolean)
23
- : [''];
24
- for (const dir of dirs) {
25
- for (const ext of exts) {
26
- try {
27
- accessSync(join(dir, bin + ext), constants.X_OK);
28
- return true;
29
- }
30
- catch {
31
- // Not here (missing, or not executable) — keep looking.
32
- }
33
- }
34
- }
35
- return false;
36
- }
37
- /** The first agent CLI installed on this machine, or null if there is none. */
38
- export function findAgentCli() {
39
- return AGENT_CLIS.find((agent) => onPath(agent.bin)) ?? null;
40
- }
41
- /**
42
- * Hand the terminal to `agent`, seeded with `prompt`, and block until its
43
- * session exits. Returns false when the process never started (ENOENT, a broken
44
- * shim) — the caller then treats the agent as unavailable. A non-zero exit is
45
- * still a launch: the user was there and saw whatever happened.
46
- */
47
- export function launchAgentCli(agent, prompt) {
48
- // Windows agent CLIs are `.cmd` shims, which Node refuses to spawn without a
49
- // shell; cmd.exe joins argv verbatim, so the prompt needs its own quotes.
50
- const win = process.platform === 'win32';
51
- const args = agent.args(prompt).map((arg) => (win ? `"${arg}"` : arg));
52
- try {
53
- const res = spawnSync(agent.bin, args, { stdio: 'inherit', shell: win });
54
- return !res.error;
55
- }
56
- catch {
57
- return false;
58
- }
59
- }
60
- const HANDOFF_TIMEOUT_MS = 8000;
61
- /**
62
- * Tell the backend what happened to the profile work, so the web onboarding
63
- * knows which state to show: `launched` is the positive evidence that an agent
64
- * is now running and the page should wait for it; `declined` and `unavailable`
65
- * mean nobody took it, so the page shows the manual paste-the-prompt step
66
- * instead of waiting for a ping that is never coming.
67
- *
68
- * Best effort by design: a failure (offline, or a backend too old to know the
69
- * `launched` outcome and 400ing it) must never break the end of setup.
70
- *
71
- * Server contract (POST /api/cli/agent-handoff):
72
- * `Authorization: Bearer <session token>`, body `{ outcome, agent? }`,
73
- * where `agent` is the binary name we launched or offered (e.g. `claude`).
74
- */
75
- export async function notifyAgentHandoff(appUrl, token, outcome, agent) {
76
- try {
77
- await fetch(`${appUrl}/api/cli/agent-handoff`, {
78
- method: 'POST',
79
- headers: {
80
- 'Content-Type': 'application/json',
81
- Authorization: `Bearer ${token}`,
82
- },
83
- body: JSON.stringify({ outcome, ...(agent ? { agent } : {}) }),
84
- signal: AbortSignal.timeout(HANDOFF_TIMEOUT_MS),
85
- });
86
- }
87
- catch {
88
- // Best effort — setup is already done, and this only steers the web page.
89
- }
90
- }
91
- //# sourceMappingURL=agent-handoff.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-handoff.js","sourceRoot":"","sources":["../src/agent-handoff.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- import { type Session } from './session.js';
2
- /** Print the versioned JSON error envelope and exit 1 (agent mode). */
3
- export declare function emitJsonError(code: string, message: string): never;
4
- /** Login gate: returns the session or exits with mode-appropriate copy. */
5
- export declare function requireSession(json: boolean): Promise<Session>;
6
- /**
7
- * Human-readable message for a non-2xx envelope body. 401 gets the per-backend
8
- * re-login hint (an --env mismatch names the exact login command), 429 the
9
- * slow-down copy; anything else relays the server's message.
10
- */
11
- export declare function apiErrorMessage(status: number, body: {
12
- error?: {
13
- message?: string;
14
- };
15
- } | null, session: Session): string;
16
- /** Read a failed Response's envelope and shape it via apiErrorMessage. */
17
- export declare function readApiError(res: Response, session: Session): Promise<string>;
18
- //# sourceMappingURL=api-client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,OAAO,EAAoB,MAAM,cAAc,CAAA;AAO1E,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAGlE;AAED,2EAA2E;AAC3E,wBAAsB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CASpE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAAG,IAAI,EAC7C,OAAO,EAAE,OAAO,GACf,MAAM,CAIR;AAED,0EAA0E;AAC1E,wBAAsB,YAAY,CAChC,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,MAAM,CAAC,CAKjB"}
@@ -1,40 +0,0 @@
1
- import { loadSession, unauthorizedHint } from './session.js';
2
- import { dim, error, info } from './ui.js';
3
- // Shared plumbing for authenticated agent-friendly commands (profile, hacker):
4
- // one login gate, one JSON error envelope, one reader for the server's
5
- // {schemaVersion, error} shape — so the 401/429 copy can't drift per command.
6
- /** Print the versioned JSON error envelope and exit 1 (agent mode). */
7
- export function emitJsonError(code, message) {
8
- console.log(JSON.stringify({ schemaVersion: 1, error: { code, message } }));
9
- process.exit(1);
10
- }
11
- /** Login gate: returns the session or exits with mode-appropriate copy. */
12
- export async function requireSession(json) {
13
- const session = await loadSession();
14
- if (!session) {
15
- if (json)
16
- emitJsonError('unauthorized', 'not logged in');
17
- error('not logged in');
18
- info(`run ${dim('hacklab login')} first`);
19
- process.exit(1);
20
- }
21
- return session;
22
- }
23
- /**
24
- * Human-readable message for a non-2xx envelope body. 401 gets the per-backend
25
- * re-login hint (an --env mismatch names the exact login command), 429 the
26
- * slow-down copy; anything else relays the server's message.
27
- */
28
- export function apiErrorMessage(status, body, session) {
29
- if (status === 401)
30
- return unauthorizedHint(session);
31
- if (status === 429)
32
- return 'slow down. try again in a minute.';
33
- return body?.error?.message ?? `request failed (${status})`;
34
- }
35
- /** Read a failed Response's envelope and shape it via apiErrorMessage. */
36
- export async function readApiError(res, session) {
37
- const body = (await res.json().catch(() => null));
38
- return apiErrorMessage(res.status, body, session);
39
- }
40
- //# sourceMappingURL=api-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAgB,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C,+EAA+E;AAC/E,uEAAuE;AACvE,8EAA8E;AAE9E,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IAC3E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAa;IAChD,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAA;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,IAAI;YAAE,aAAa,CAAC,cAAc,EAAE,eAAe,CAAC,CAAA;QACxD,KAAK,CAAC,eAAe,CAAC,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAA;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAc,EACd,IAA6C,EAC7C,OAAgB;IAEhB,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACpD,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,mCAAmC,CAAA;IAC9D,OAAO,IAAI,EAAE,KAAK,EAAE,OAAO,IAAI,mBAAmB,MAAM,GAAG,CAAA;AAC7D,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAa,EACb,OAAgB;IAEhB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAExC,CAAA;IACR,OAAO,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;AACnD,CAAC"}
package/dist/belt.d.ts DELETED
@@ -1,25 +0,0 @@
1
- export type BeltColor = 'white' | 'orange' | 'red' | 'blue' | 'cyan' | 'yellow' | 'lime' | 'green' | 'pink' | 'purple' | 'black';
2
- export type Title = 'gaijin' | 'deshi' | 'ronin' | 'shinobi' | 'samurai' | 'senpai' | 'tatsujin' | 'kensei' | 'oni' | 'ryujin';
3
- export type DanTitle = 'shodan' | 'nidan' | 'sandan' | 'yondan' | 'godan' | 'rokudan' | 'nanadan' | 'hachidan' | 'kudan' | 'judan';
4
- export type GrandMasterTitle = 'shihan' | 'hanshi' | 'meijin' | 'oyama';
5
- /** Convert raw token count to Pyro XP. 1,000 tokens = 1 XP. */
6
- export declare function tokensToXp(tokens: number): number;
7
- /** Convert total XP to level (fractional). */
8
- export declare function xpToLevel(xp: number): number;
9
- /** Convert level to minimum XP required. */
10
- export declare function levelToMinXp(level: number): number;
11
- /** Get the integer level (floor of fractional level). */
12
- export declare function getLevel(xp: number): number;
13
- /** Get belt color for a given level. */
14
- export declare function getBeltColor(level: number): BeltColor;
15
- /** Get title for a given level. */
16
- export declare function getTitle(level: number): Title | DanTitle | GrandMasterTitle;
17
- export type BeltProgress = {
18
- level: number;
19
- title: Title | DanTitle | GrandMasterTitle;
20
- beltColor: BeltColor;
21
- progressPercent: number;
22
- };
23
- /** Belt info for a raw token total (pyro-only — correct for a fresh account). */
24
- export declare function beltForTokens(tokensTotal: number): BeltProgress;
25
- //# sourceMappingURL=belt.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"belt.d.ts","sourceRoot":"","sources":["../src/belt.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,SAAS,GACjB,OAAO,GACP,QAAQ,GACR,KAAK,GACL,MAAM,GACN,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,MAAM,GACN,QAAQ,GACR,OAAO,CAAA;AAEX,MAAM,MAAM,KAAK,GACb,QAAQ,GACR,OAAO,GACP,OAAO,GACP,SAAS,GACT,SAAS,GACT,QAAQ,GACR,UAAU,GACV,QAAQ,GACR,KAAK,GACL,QAAQ,CAAA;AAEZ,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,SAAS,GACT,SAAS,GACT,UAAU,GACV,OAAO,GACP,OAAO,CAAA;AAEX,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;AAqCvE,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAMrD;AAED,mCAAmC;AACnC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,gBAAgB,CAkB3E;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,gBAAgB,CAAA;IAC1C,SAAS,EAAE,SAAS,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAgB/D"}
package/dist/belt.js DELETED
@@ -1,113 +0,0 @@
1
- // Belt / level math — ported verbatim from @hacklab/db `levels.ts` so the CLI
2
- // can render the share card instantly (locally) without waiting on the server.
3
- // The CLI is a standalone published package and must not pull in @hacklab/db
4
- // (drizzle/pg/etc.), so we copy the small, stable curve here.
5
- //
6
- // One curve: xp(level) = 23 × level^3.32 up to level 100, exponential above.
7
- // Pyro XP = tokens / 1000. For a brand-new account, hacker + mason XP are 0, so
8
- // belt XP == pyro XP — which is exactly what the server computes right after
9
- // the first sync. Kept in sync via belt.test.ts (anchored to the known points).
10
- const K = 3.32;
11
- const A = 23;
12
- const LEVEL_100_XP = 100_000_000; // 100M XP
13
- const BELT_TIERS = [
14
- { minLevel: 0, color: 'white', title: 'gaijin' },
15
- { minLevel: 10, color: 'orange', title: 'deshi' },
16
- { minLevel: 20, color: 'red', title: 'ronin' },
17
- { minLevel: 30, color: 'blue', title: 'shinobi' },
18
- { minLevel: 40, color: 'cyan', title: 'samurai' },
19
- { minLevel: 50, color: 'yellow', title: 'senpai' },
20
- { minLevel: 60, color: 'lime', title: 'tatsujin' },
21
- { minLevel: 70, color: 'green', title: 'kensei' },
22
- { minLevel: 80, color: 'pink', title: 'oni' },
23
- { minLevel: 90, color: 'purple', title: 'ryujin' },
24
- ];
25
- const DAN_TITLES = [
26
- 'shodan',
27
- 'nidan',
28
- 'sandan',
29
- 'yondan',
30
- 'godan',
31
- 'rokudan',
32
- 'nanadan',
33
- 'hachidan',
34
- 'kudan',
35
- 'judan',
36
- ];
37
- const GRAND_MASTER_TIERS = [
38
- { minLevel: 200, title: 'shihan' },
39
- { minLevel: 300, title: 'hanshi' },
40
- { minLevel: 400, title: 'meijin' },
41
- { minLevel: 500, title: 'oyama' },
42
- ];
43
- /** Convert raw token count to Pyro XP. 1,000 tokens = 1 XP. */
44
- export function tokensToXp(tokens) {
45
- return Math.floor(tokens / 1_000);
46
- }
47
- /** Convert total XP to level (fractional). */
48
- export function xpToLevel(xp) {
49
- if (xp <= 0)
50
- return 0;
51
- if (xp >= LEVEL_100_XP) {
52
- return 100 + 100 * Math.log10(xp / LEVEL_100_XP);
53
- }
54
- return (xp / A) ** (1 / K);
55
- }
56
- /** Convert level to minimum XP required. */
57
- export function levelToMinXp(level) {
58
- if (level <= 0)
59
- return 0;
60
- if (level >= 100) {
61
- return Math.round(LEVEL_100_XP * 10 ** ((level - 100) / 100));
62
- }
63
- return Math.round(A * level ** K);
64
- }
65
- /** Get the integer level (floor of fractional level). */
66
- export function getLevel(xp) {
67
- return Math.floor(xpToLevel(xp));
68
- }
69
- /** Get belt color for a given level. */
70
- export function getBeltColor(level) {
71
- if (level >= 100)
72
- return 'black';
73
- for (let i = BELT_TIERS.length - 1; i >= 0; i--) {
74
- if (level >= BELT_TIERS[i].minLevel)
75
- return BELT_TIERS[i].color;
76
- }
77
- return 'white';
78
- }
79
- /** Get title for a given level. */
80
- export function getTitle(level) {
81
- if (level >= 200) {
82
- for (let i = GRAND_MASTER_TIERS.length - 1; i >= 0; i--) {
83
- if (level >= GRAND_MASTER_TIERS[i].minLevel)
84
- return GRAND_MASTER_TIERS[i].title;
85
- }
86
- }
87
- if (level >= 100) {
88
- const danIndex = Math.min(Math.floor((level - 100) / 10), DAN_TITLES.length - 1);
89
- return DAN_TITLES[danIndex];
90
- }
91
- for (let i = BELT_TIERS.length - 1; i >= 0; i--) {
92
- if (level >= BELT_TIERS[i].minLevel)
93
- return BELT_TIERS[i].title;
94
- }
95
- return 'gaijin';
96
- }
97
- /** Belt info for a raw token total (pyro-only — correct for a fresh account). */
98
- export function beltForTokens(tokensTotal) {
99
- const xp = tokensToXp(tokensTotal);
100
- const level = getLevel(xp);
101
- const currentLevelXp = levelToMinXp(level);
102
- const nextLevelXp = levelToMinXp(level + 1);
103
- const xpIntoLevel = xp - currentLevelXp;
104
- const xpNeeded = nextLevelXp - currentLevelXp;
105
- const progressPercent = xpNeeded > 0 ? Math.min(Math.round((xpIntoLevel / xpNeeded) * 100), 100) : 0;
106
- return {
107
- level,
108
- title: getTitle(level),
109
- beltColor: getBeltColor(level),
110
- progressPercent,
111
- };
112
- }
113
- //# sourceMappingURL=belt.js.map
package/dist/belt.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"belt.js","sourceRoot":"","sources":["../src/belt.ts"],"names":[],"mappings":"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"}
package/dist/card.d.ts DELETED
@@ -1,66 +0,0 @@
1
- export type HackerCardData = {
2
- handle: string;
3
- displayName: string | null;
4
- bio: string | null;
5
- joinedAt: string;
6
- claimedAt: string | null;
7
- level: number;
8
- tokensTotal: number;
9
- tokens30d: number;
10
- estimatedCost: number;
11
- rank: number | null;
12
- topModels30d: {
13
- model: string;
14
- tokens: number;
15
- pct: number;
16
- }[];
17
- currentStreak: number;
18
- longestStreak: number;
19
- activeDays30: number;
20
- activity30: number[];
21
- counts: {
22
- projects: number;
23
- essays: number;
24
- drops: number;
25
- followers: number;
26
- };
27
- recent: {
28
- projects: {
29
- title: string;
30
- description: string | null;
31
- }[];
32
- essays: {
33
- title: string;
34
- publishedAt: string | null;
35
- }[];
36
- drops: {
37
- text: string;
38
- createdAt: string;
39
- }[];
40
- };
41
- links: {
42
- profile: string;
43
- website: string | null;
44
- github: string | null;
45
- x: string | null;
46
- };
47
- openToWork: boolean;
48
- };
49
- export type RenderCardOptions = {
50
- /** Terminal columns. Clamped to [MIN_WIDTH, DESIGN_WIDTH]. */
51
- columns?: number;
52
- now?: Date;
53
- };
54
- /**
55
- * Render the full one-screen card as an array of lines (caller joins with \n).
56
- * Pure: no I/O, deterministic given `now`. Every user-supplied string is passed
57
- * through stripControl before it reaches the terminal.
58
- */
59
- export declare function renderCard(card: HackerCardData, opts?: RenderCardOptions): string[];
60
- /**
61
- * The compact in-chat card (`/who`): 4 lines, no rules, no sparkline. Same
62
- * strip discipline. Returned as separate lines so the chat renderer can push
63
- * them as one Entry per row (preserving the one-row-per-entry invariant).
64
- */
65
- export declare function renderCompact(card: HackerCardData): string[];
66
- //# sourceMappingURL=card.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC9D,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9E,MAAM,EAAE;QACN,QAAQ,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,EAAE,CAAA;QACzD,MAAM,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,EAAE,CAAA;QACvD,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAC7C,CAAA;IACD,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KACjB,CAAA;IACD,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAQD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,IAAI,CAAA;CACX,CAAA;AAyFD;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,cAAc,EACpB,IAAI,GAAE,iBAAsB,GAC3B,MAAM,EAAE,CAiHV;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM,EAAE,CAY5D"}