@loompad/cli 0.1.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 (177) hide show
  1. package/ARCHITECTURE.md +211 -0
  2. package/CHANGELOG.md +470 -0
  3. package/LICENSE +21 -0
  4. package/README.md +630 -0
  5. package/dist/adapters/base.d.ts +71 -0
  6. package/dist/adapters/base.js +187 -0
  7. package/dist/adapters/base.js.map +1 -0
  8. package/dist/adapters/bridges/antigravity.d.ts +53 -0
  9. package/dist/adapters/bridges/antigravity.js +106 -0
  10. package/dist/adapters/bridges/antigravity.js.map +1 -0
  11. package/dist/adapters/bridges/cdp.d.ts +82 -0
  12. package/dist/adapters/bridges/cdp.js +222 -0
  13. package/dist/adapters/bridges/cdp.js.map +1 -0
  14. package/dist/adapters/bridges/gui-chat.d.ts +113 -0
  15. package/dist/adapters/bridges/gui-chat.js +498 -0
  16. package/dist/adapters/bridges/gui-chat.js.map +1 -0
  17. package/dist/adapters/bridges/kiro.d.ts +19 -0
  18. package/dist/adapters/bridges/kiro.js +22 -0
  19. package/dist/adapters/bridges/kiro.js.map +1 -0
  20. package/dist/adapters/bridges/profiles.d.ts +82 -0
  21. package/dist/adapters/bridges/profiles.js +125 -0
  22. package/dist/adapters/bridges/profiles.js.map +1 -0
  23. package/dist/adapters/claude-code.d.ts +26 -0
  24. package/dist/adapters/claude-code.js +209 -0
  25. package/dist/adapters/claude-code.js.map +1 -0
  26. package/dist/adapters/codex.d.ts +51 -0
  27. package/dist/adapters/codex.js +291 -0
  28. package/dist/adapters/codex.js.map +1 -0
  29. package/dist/adapters/echo.d.ts +20 -0
  30. package/dist/adapters/echo.js +79 -0
  31. package/dist/adapters/echo.js.map +1 -0
  32. package/dist/adapters/grok.d.ts +61 -0
  33. package/dist/adapters/grok.js +217 -0
  34. package/dist/adapters/grok.js.map +1 -0
  35. package/dist/adapters/index.d.ts +9 -0
  36. package/dist/adapters/index.js +33 -0
  37. package/dist/adapters/index.js.map +1 -0
  38. package/dist/adapters/opencode.d.ts +64 -0
  39. package/dist/adapters/opencode.js +426 -0
  40. package/dist/adapters/opencode.js.map +1 -0
  41. package/dist/cli/common.d.ts +11 -0
  42. package/dist/cli/common.js +40 -0
  43. package/dist/cli/common.js.map +1 -0
  44. package/dist/cli/doctor.d.ts +12 -0
  45. package/dist/cli/doctor.js +181 -0
  46. package/dist/cli/doctor.js.map +1 -0
  47. package/dist/cli/index.d.ts +8 -0
  48. package/dist/cli/index.js +641 -0
  49. package/dist/cli/index.js.map +1 -0
  50. package/dist/cli/tui-model.d.ts +73 -0
  51. package/dist/cli/tui-model.js +312 -0
  52. package/dist/cli/tui-model.js.map +1 -0
  53. package/dist/cli/tui.d.ts +15 -0
  54. package/dist/cli/tui.js +451 -0
  55. package/dist/cli/tui.js.map +1 -0
  56. package/dist/cli/ui.d.ts +10 -0
  57. package/dist/cli/ui.js +135 -0
  58. package/dist/cli/ui.js.map +1 -0
  59. package/dist/core/ades.d.ts +79 -0
  60. package/dist/core/ades.js +130 -0
  61. package/dist/core/ades.js.map +1 -0
  62. package/dist/core/baton.d.ts +37 -0
  63. package/dist/core/baton.js +92 -0
  64. package/dist/core/baton.js.map +1 -0
  65. package/dist/core/brain-extract.d.ts +111 -0
  66. package/dist/core/brain-extract.js +248 -0
  67. package/dist/core/brain-extract.js.map +1 -0
  68. package/dist/core/brain-index.d.ts +128 -0
  69. package/dist/core/brain-index.js +338 -0
  70. package/dist/core/brain-index.js.map +1 -0
  71. package/dist/core/brain.d.ts +214 -0
  72. package/dist/core/brain.js +425 -0
  73. package/dist/core/brain.js.map +1 -0
  74. package/dist/core/claude-cli.d.ts +12 -0
  75. package/dist/core/claude-cli.js +47 -0
  76. package/dist/core/claude-cli.js.map +1 -0
  77. package/dist/core/distill.d.ts +19 -0
  78. package/dist/core/distill.js +88 -0
  79. package/dist/core/distill.js.map +1 -0
  80. package/dist/core/eventlog.d.ts +43 -0
  81. package/dist/core/eventlog.js +211 -0
  82. package/dist/core/eventlog.js.map +1 -0
  83. package/dist/core/git.d.ts +203 -0
  84. package/dist/core/git.js +460 -0
  85. package/dist/core/git.js.map +1 -0
  86. package/dist/core/logbook.d.ts +59 -0
  87. package/dist/core/logbook.js +118 -0
  88. package/dist/core/logbook.js.map +1 -0
  89. package/dist/core/memory.d.ts +34 -0
  90. package/dist/core/memory.js +124 -0
  91. package/dist/core/memory.js.map +1 -0
  92. package/dist/core/notify.d.ts +11 -0
  93. package/dist/core/notify.js +30 -0
  94. package/dist/core/notify.js.map +1 -0
  95. package/dist/core/projection.d.ts +20 -0
  96. package/dist/core/projection.js +96 -0
  97. package/dist/core/projection.js.map +1 -0
  98. package/dist/core/registry.d.ts +76 -0
  99. package/dist/core/registry.js +147 -0
  100. package/dist/core/registry.js.map +1 -0
  101. package/dist/core/router.d.ts +42 -0
  102. package/dist/core/router.js +99 -0
  103. package/dist/core/router.js.map +1 -0
  104. package/dist/core/routes.d.ts +93 -0
  105. package/dist/core/routes.js +399 -0
  106. package/dist/core/routes.js.map +1 -0
  107. package/dist/core/search.d.ts +63 -0
  108. package/dist/core/search.js +0 -0
  109. package/dist/core/search.js.map +1 -0
  110. package/dist/core/setup.d.ts +70 -0
  111. package/dist/core/setup.js +250 -0
  112. package/dist/core/setup.js.map +1 -0
  113. package/dist/core/suggestions.d.ts +15 -0
  114. package/dist/core/suggestions.js +38 -0
  115. package/dist/core/suggestions.js.map +1 -0
  116. package/dist/core/worktree.d.ts +32 -0
  117. package/dist/core/worktree.js +83 -0
  118. package/dist/core/worktree.js.map +1 -0
  119. package/dist/daemon/app-page.d.ts +32 -0
  120. package/dist/daemon/app-page.js +6363 -0
  121. package/dist/daemon/app-page.js.map +1 -0
  122. package/dist/daemon/auth.d.ts +51 -0
  123. package/dist/daemon/auth.js +135 -0
  124. package/dist/daemon/auth.js.map +1 -0
  125. package/dist/daemon/board.d.ts +117 -0
  126. package/dist/daemon/board.js +202 -0
  127. package/dist/daemon/board.js.map +1 -0
  128. package/dist/daemon/brand-icons.d.ts +29 -0
  129. package/dist/daemon/brand-icons.js +44 -0
  130. package/dist/daemon/brand-icons.js.map +1 -0
  131. package/dist/daemon/client.d.ts +127 -0
  132. package/dist/daemon/client.js +237 -0
  133. package/dist/daemon/client.js.map +1 -0
  134. package/dist/daemon/geist-font.d.ts +10 -0
  135. package/dist/daemon/geist-font.js +783 -0
  136. package/dist/daemon/geist-font.js.map +1 -0
  137. package/dist/daemon/guards.d.ts +18 -0
  138. package/dist/daemon/guards.js +40 -0
  139. package/dist/daemon/guards.js.map +1 -0
  140. package/dist/daemon/linear.d.ts +59 -0
  141. package/dist/daemon/linear.js +117 -0
  142. package/dist/daemon/linear.js.map +1 -0
  143. package/dist/daemon/push.d.ts +22 -0
  144. package/dist/daemon/push.js +58 -0
  145. package/dist/daemon/push.js.map +1 -0
  146. package/dist/daemon/runtime.d.ts +299 -0
  147. package/dist/daemon/runtime.js +1016 -0
  148. package/dist/daemon/runtime.js.map +1 -0
  149. package/dist/daemon/server.d.ts +125 -0
  150. package/dist/daemon/server.js +1728 -0
  151. package/dist/daemon/server.js.map +1 -0
  152. package/dist/daemon/tasks.d.ts +153 -0
  153. package/dist/daemon/tasks.js +264 -0
  154. package/dist/daemon/tasks.js.map +1 -0
  155. package/dist/daemon/terminals.d.ts +82 -0
  156. package/dist/daemon/terminals.js +372 -0
  157. package/dist/daemon/terminals.js.map +1 -0
  158. package/dist/index.d.ts +20 -0
  159. package/dist/index.js +20 -0
  160. package/dist/index.js.map +1 -0
  161. package/dist/sdk.d.ts +17 -0
  162. package/dist/sdk.js +17 -0
  163. package/dist/sdk.js.map +1 -0
  164. package/dist/types.d.ts +236 -0
  165. package/dist/types.js +18 -0
  166. package/dist/types.js.map +1 -0
  167. package/docs/SETUP.md +265 -0
  168. package/docs/adapters.md +132 -0
  169. package/docs/design-system.md +245 -0
  170. package/docs/img/board-linear.png +0 -0
  171. package/docs/img/board-projects.png +0 -0
  172. package/docs/img/brain.png +0 -0
  173. package/docs/img/settings.png +0 -0
  174. package/docs/img/workspace.png +0 -0
  175. package/docs/integration-notes.md +76 -0
  176. package/docs/proposals/brain.md +262 -0
  177. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-page.js","sourceRoot":"","sources":["../../src/daemon/app-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE9D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,MAAM;IACjB,OAAO,EAAE,YAAY;IACrB,gBAAgB,EAAE,SAAS;IAC3B,WAAW,EAAE,SAAS;IACtB,KAAK,EAAE;QACL;YACE,GAAG,EACD,iYAAiY;YACnY,KAAK,EAAE,KAAK;YACZ,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,KAAK;SACf;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAk4CtB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAgJS,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAqqJ3C,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Daemon auth — bearer tokens + QR pairing.
3
+ *
4
+ * Trust model (decided in the design interview): the tailnet is the
5
+ * boundary. The daemon binds to localhost or the Tailscale interface only;
6
+ * Tailscale provides device auth + E2E encryption. Tokens here are the
7
+ * second factor that makes a *device on the tailnet* a *paired client*.
8
+ *
9
+ * Pairing: `loom pair` mints a short-lived, single-use pairing token,
10
+ * rendered as a QR code. The phone exchanges it (POST /api/pair/claim) for
11
+ * a long-lived client token. Raw secrets never ride in URLs.
12
+ */
13
+ import type { DaemonConfig } from "../core/registry.js";
14
+ export declare class AuthManager {
15
+ private config;
16
+ private pending;
17
+ constructor(config: DaemonConfig);
18
+ /** True for the admin token (CLI on this machine) or any paired client. */
19
+ isAuthorized(token: string | undefined): boolean;
20
+ isAdmin(token: string | undefined): boolean;
21
+ /** The admin token, for handing to a same-machine (loopback) caller only. */
22
+ adminToken(): string;
23
+ /** Mint a short-lived, single-use pairing token (admin only). */
24
+ newPairingToken(): {
25
+ token: string;
26
+ expiresAt: number;
27
+ };
28
+ /** Exchange a valid pairing token for a long-lived client token. */
29
+ claim(pairingToken: string, name?: string): {
30
+ clientToken: string;
31
+ clientId: string;
32
+ } | null;
33
+ revoke(clientId: string): boolean;
34
+ clients(): Array<{
35
+ id: string;
36
+ name: string;
37
+ createdAt: number;
38
+ push: boolean;
39
+ }>;
40
+ /** Which paired client does this bearer token belong to? (admin → null) */
41
+ clientFor(token: string | undefined): {
42
+ id: string;
43
+ name: string;
44
+ } | null;
45
+ /** Attach/detach a push token on a paired client (read-modify-write). */
46
+ setPushToken(clientId: string, pushToken: string | null, platform?: string): boolean;
47
+ /** Re-read clients from disk (another process may have paired). */
48
+ reload(): void;
49
+ private gc;
50
+ }
51
+ export declare function bearerToken(header: string | undefined): string | undefined;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Daemon auth — bearer tokens + QR pairing.
3
+ *
4
+ * Trust model (decided in the design interview): the tailnet is the
5
+ * boundary. The daemon binds to localhost or the Tailscale interface only;
6
+ * Tailscale provides device auth + E2E encryption. Tokens here are the
7
+ * second factor that makes a *device on the tailnet* a *paired client*.
8
+ *
9
+ * Pairing: `loom pair` mints a short-lived, single-use pairing token,
10
+ * rendered as a QR code. The phone exchanges it (POST /api/pair/claim) for
11
+ * a long-lived client token. Raw secrets never ride in URLs.
12
+ */
13
+ import crypto from "node:crypto";
14
+ import { readDaemonConfig, writeDaemonConfig } from "../core/registry.js";
15
+ const PAIR_TTL_MS = 10 * 60 * 1000;
16
+ export class AuthManager {
17
+ config;
18
+ pending = new Map();
19
+ constructor(config) {
20
+ this.config = config;
21
+ }
22
+ /** True for the admin token (CLI on this machine) or any paired client. */
23
+ isAuthorized(token) {
24
+ if (!token)
25
+ return false;
26
+ if (timingSafeEqualStr(token, this.config.adminToken))
27
+ return true;
28
+ return this.config.clients.some((c) => timingSafeEqualStr(token, c.token));
29
+ }
30
+ isAdmin(token) {
31
+ return Boolean(token && timingSafeEqualStr(token, this.config.adminToken));
32
+ }
33
+ /** The admin token, for handing to a same-machine (loopback) caller only. */
34
+ adminToken() {
35
+ return this.config.adminToken;
36
+ }
37
+ /** Mint a short-lived, single-use pairing token (admin only). */
38
+ newPairingToken() {
39
+ this.gc();
40
+ const token = crypto.randomBytes(16).toString("hex");
41
+ const entry = { token, expiresAt: Date.now() + PAIR_TTL_MS };
42
+ this.pending.set(token, entry);
43
+ return entry;
44
+ }
45
+ /** Exchange a valid pairing token for a long-lived client token. */
46
+ claim(pairingToken, name = "device") {
47
+ this.gc();
48
+ const entry = this.pending.get(pairingToken);
49
+ if (!entry)
50
+ return null;
51
+ this.pending.delete(pairingToken); // single use
52
+ const client = {
53
+ id: crypto.randomBytes(6).toString("hex"),
54
+ name,
55
+ token: crypto.randomBytes(32).toString("hex"),
56
+ createdAt: Date.now(),
57
+ };
58
+ // Read-modify-write: never clobber fields (pid, host, port) that the
59
+ // daemon wrote after this manager snapshotted the config.
60
+ this.reload();
61
+ this.config.clients.push(client);
62
+ writeDaemonConfig(this.config);
63
+ return { clientToken: client.token, clientId: client.id };
64
+ }
65
+ revoke(clientId) {
66
+ this.reload();
67
+ const before = this.config.clients.length;
68
+ this.config.clients = this.config.clients.filter((c) => c.id !== clientId);
69
+ if (this.config.clients.length !== before) {
70
+ writeDaemonConfig(this.config);
71
+ return true;
72
+ }
73
+ return false;
74
+ }
75
+ clients() {
76
+ return this.config.clients.map(({ id, name, createdAt, pushToken }) => ({
77
+ id,
78
+ name,
79
+ createdAt,
80
+ push: Boolean(pushToken),
81
+ }));
82
+ }
83
+ /** Which paired client does this bearer token belong to? (admin → null) */
84
+ clientFor(token) {
85
+ if (!token)
86
+ return null;
87
+ const client = this.config.clients.find((c) => timingSafeEqualStr(token, c.token));
88
+ return client ? { id: client.id, name: client.name } : null;
89
+ }
90
+ /** Attach/detach a push token on a paired client (read-modify-write). */
91
+ setPushToken(clientId, pushToken, platform) {
92
+ this.reload();
93
+ const client = this.config.clients.find((c) => c.id === clientId);
94
+ if (!client)
95
+ return false;
96
+ if (pushToken) {
97
+ client.pushToken = pushToken;
98
+ if (platform)
99
+ client.platform = platform;
100
+ }
101
+ else {
102
+ delete client.pushToken;
103
+ delete client.platform;
104
+ }
105
+ writeDaemonConfig(this.config);
106
+ return true;
107
+ }
108
+ /** Re-read clients from disk (another process may have paired). */
109
+ reload() {
110
+ const fresh = readDaemonConfig();
111
+ if (fresh)
112
+ this.config = fresh;
113
+ }
114
+ gc() {
115
+ const now = Date.now();
116
+ for (const [k, v] of this.pending) {
117
+ if (v.expiresAt < now)
118
+ this.pending.delete(k);
119
+ }
120
+ }
121
+ }
122
+ function timingSafeEqualStr(a, b) {
123
+ const ab = Buffer.from(a);
124
+ const bb = Buffer.from(b);
125
+ if (ab.length !== bb.length)
126
+ return false;
127
+ return crypto.timingSafeEqual(ab, bb);
128
+ }
129
+ export function bearerToken(header) {
130
+ if (!header)
131
+ return undefined;
132
+ const m = header.match(/^Bearer\s+(.+)$/i);
133
+ return m?.[1];
134
+ }
135
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/daemon/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE1E,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAOnC,MAAM,OAAO,WAAW;IACd,MAAM,CAAe;IACrB,OAAO,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEjD,YAAY,MAAoB;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,2EAA2E;IAC3E,YAAY,CAAC,KAAyB;QACpC,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,IAAI,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACnE,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,CAAC,KAAyB;QAC/B,OAAO,OAAO,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,6EAA6E;IAC7E,UAAU;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAChC,CAAC;IAED,iEAAiE;IACjE,eAAe;QACb,IAAI,CAAC,EAAE,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,CAAC;QAC7D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,YAAoB,EAAE,IAAI,GAAG,QAAQ;QACzC,IAAI,CAAC,EAAE,EAAE,CAAC;QACV,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa;QAChD,MAAM,MAAM,GAAG;YACb,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzC,IAAI;YACJ,KAAK,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM,CAAC,QAAgB;QACrB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC1C,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;YACtE,EAAE;YACF,IAAI;YACJ,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC;SACzB,CAAC,CAAC,CAAC;IACN,CAAC;IAED,2EAA2E;IAC3E,SAAS,CAAC,KAAyB;QACjC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;QACnF,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,yEAAyE;IACzE,YAAY,CAAC,QAAgB,EAAE,SAAwB,EAAE,QAAiB;QACxE,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAClE,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;YAC7B,IAAI,QAAQ;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,OAAO,MAAM,CAAC,SAAS,CAAC;YACxB,OAAO,MAAM,CAAC,QAAQ,CAAC;QACzB,CAAC;QACD,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mEAAmE;IACnE,MAAM;QACJ,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC;QACjC,IAAI,KAAK;YAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACjC,CAAC;IAEO,EAAE;QACR,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;gBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;CACF;AAED,SAAS,kBAAkB,CAAC,CAAS,EAAE,CAAS;IAC9C,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1C,OAAO,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAA0B;IACpD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC3C,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The board: every piece of work in a project, in the order it flows —
3
+ * working → needs you → in review → ready to merge.
4
+ *
5
+ * Three sources, no invented rows:
6
+ * - You: cards you wrote (`own: true`). The column you put it in IS its
7
+ * state — there's nothing else it could be — so dragging one really moves
8
+ * it, and it persists in .loom/state.json.
9
+ * - Loom, for work with no PR yet: which agents are running, and which are
10
+ * blocked on a question. The daemon's own state.
11
+ * - The project's GitHub remote via the user's `gh` CLI (see tasks.ts), for
12
+ * everything that reached a pull request: draft, review pending, changes
13
+ * requested, CI red, approved.
14
+ *
15
+ * The last two are *derived* and never stored. Dragging one of those only pins
16
+ * where you want to see it; the badge keeps reporting what GitHub and the
17
+ * daemon actually say, because neither is ours to rewrite from a drag. That's
18
+ * the difference `own` marks.
19
+ */
20
+ import type { BoardTask } from "../core/registry.js";
21
+ import { type TaskUnavailable } from "./tasks.js";
22
+ /** The four columns, in flow order. */
23
+ export declare const BOARD_COLUMNS: readonly ["working", "needs-you", "in-review", "ready"];
24
+ export type BoardColumn = (typeof BOARD_COLUMNS)[number];
25
+ /** What a card is actually waiting on — the badge, and what picks its column. */
26
+ export type BoardState = "working" | "input-needed" | "issue" | "ci-failed" | "changes-requested" | "review-pending" | "draft" | "approved" | "ready";
27
+ export interface BoardCard {
28
+ /** Stable across refreshes: "pr-51", "agent-claude", "task-a1b2". Drag keys on it. */
29
+ id: string;
30
+ title: string;
31
+ /** The agent that owns this work, when we know: an id for ours, a GitHub login for a PR. */
32
+ agent: string;
33
+ /** The agent's adapter kind, when this is one of ours — drives the brand mark. */
34
+ kind?: string;
35
+ state: BoardState;
36
+ column: BoardColumn;
37
+ /** PR branch, when there is a PR. */
38
+ branch?: string;
39
+ pr?: {
40
+ number: number;
41
+ state: string;
42
+ draft: boolean;
43
+ url: string;
44
+ };
45
+ /** An open issue matched by your search — nobody has started it yet. */
46
+ issue?: {
47
+ number: number;
48
+ url: string;
49
+ };
50
+ updatedAt?: string;
51
+ /**
52
+ * A card you wrote. Its column is its state, so dragging one really moves it
53
+ * — nothing to contradict. Derived cards (agents, PRs) report someone else's
54
+ * truth and can only be pinned.
55
+ */
56
+ own?: boolean;
57
+ }
58
+ export interface BoardData {
59
+ available: true;
60
+ /** null when we couldn't read a GitHub repo here — agent cards still work. */
61
+ repo: string | null;
62
+ /** Present only when the PR half failed; the agent half is still real. */
63
+ ghError?: {
64
+ reason: TaskUnavailable["reason"];
65
+ detail: string;
66
+ };
67
+ cards: BoardCard[];
68
+ }
69
+ /**
70
+ * Always available. The agent half of the board is the daemon's own state, so
71
+ * there is no version of "gh is unhappy" that should leave you staring at an
72
+ * error page instead of the agents you're running. gh's failure becomes a note.
73
+ */
74
+ export type BoardResult = BoardData;
75
+ /** The daemon's own view of an agent, as /api/projects/:id reports it. */
76
+ export interface BoardAgent {
77
+ id: string;
78
+ kind: string;
79
+ role: string;
80
+ tier: string;
81
+ busy: boolean;
82
+ }
83
+ interface GhPr {
84
+ number: number;
85
+ title: string;
86
+ author?: {
87
+ login?: string;
88
+ };
89
+ headRefName?: string;
90
+ isDraft?: boolean;
91
+ reviewDecision?: string;
92
+ statusCheckRollup?: {
93
+ conclusion?: string;
94
+ state?: string;
95
+ }[] | null;
96
+ state: string;
97
+ updatedAt: string;
98
+ url: string;
99
+ }
100
+ /** Which column a state belongs in. The one place the flow is defined. */
101
+ export declare function columnFor(state: BoardState): BoardColumn;
102
+ /**
103
+ * Read a PR's real state. Order matters: a red build is worth your attention
104
+ * before a pending review, and a draft is not "waiting on a reviewer".
105
+ */
106
+ export declare function prState(pr: GhPr): BoardState;
107
+ /**
108
+ * Build the board. `agents` is the daemon's live agent state; `blocked` is the
109
+ * set of agent ids that asked a question and are waiting on the human (the
110
+ * caller reads that from the event log — this module doesn't know about logs).
111
+ */
112
+ export declare function buildBoard(dir: string, agents: BoardAgent[], blocked: string[], opts?: {
113
+ limit?: number;
114
+ tasks?: BoardTask[];
115
+ search?: string;
116
+ }): Promise<BoardResult>;
117
+ export {};
@@ -0,0 +1,202 @@
1
+ /**
2
+ * The board: every piece of work in a project, in the order it flows —
3
+ * working → needs you → in review → ready to merge.
4
+ *
5
+ * Three sources, no invented rows:
6
+ * - You: cards you wrote (`own: true`). The column you put it in IS its
7
+ * state — there's nothing else it could be — so dragging one really moves
8
+ * it, and it persists in .loom/state.json.
9
+ * - Loom, for work with no PR yet: which agents are running, and which are
10
+ * blocked on a question. The daemon's own state.
11
+ * - The project's GitHub remote via the user's `gh` CLI (see tasks.ts), for
12
+ * everything that reached a pull request: draft, review pending, changes
13
+ * requested, CI red, approved.
14
+ *
15
+ * The last two are *derived* and never stored. Dragging one of those only pins
16
+ * where you want to see it; the badge keeps reporting what GitHub and the
17
+ * daemon actually say, because neither is ours to rewrite from a drag. That's
18
+ * the difference `own` marks.
19
+ */
20
+ import { classifyGhFailure, ghRepo, runGh } from "./tasks.js";
21
+ /** The four columns, in flow order. */
22
+ export const BOARD_COLUMNS = ["working", "needs-you", "in-review", "ready"];
23
+ /**
24
+ * The badge for a card you wrote, given the column you put it in. Derived
25
+ * cards read their state from the world; yours reads from where you dragged it,
26
+ * which is the only truth it has.
27
+ */
28
+ const TASK_STATE = {
29
+ working: "working",
30
+ "needs-you": "input-needed",
31
+ "in-review": "review-pending",
32
+ ready: "ready",
33
+ };
34
+ /** Which column a state belongs in. The one place the flow is defined. */
35
+ export function columnFor(state) {
36
+ switch (state) {
37
+ case "working":
38
+ return "working";
39
+ case "input-needed":
40
+ case "issue":
41
+ case "ci-failed":
42
+ case "changes-requested":
43
+ return "needs-you";
44
+ case "review-pending":
45
+ case "draft":
46
+ return "in-review";
47
+ case "approved":
48
+ case "ready":
49
+ return "ready";
50
+ }
51
+ }
52
+ /**
53
+ * Read a PR's real state. Order matters: a red build is worth your attention
54
+ * before a pending review, and a draft is not "waiting on a reviewer".
55
+ */
56
+ export function prState(pr) {
57
+ const checks = pr.statusCheckRollup ?? [];
58
+ // gh reports either conclusion (completed) or state (in flight); only a
59
+ // definitive failure is a failure — a queued or skipped check is not.
60
+ const failed = checks.some((c) => {
61
+ const v = String(c.conclusion ?? c.state ?? "").toUpperCase();
62
+ return v === "FAILURE" || v === "TIMED_OUT" || v === "CANCELLED" || v === "ERROR";
63
+ });
64
+ if (failed)
65
+ return "ci-failed";
66
+ if (pr.reviewDecision === "CHANGES_REQUESTED")
67
+ return "changes-requested";
68
+ if (pr.isDraft)
69
+ return "draft";
70
+ if (pr.reviewDecision === "APPROVED") {
71
+ // "ready" claims CI is green, so only say it when checks actually ran
72
+ return checks.length ? "ready" : "approved";
73
+ }
74
+ return "review-pending";
75
+ }
76
+ const PR_FIELDS = "number,title,author,headRefName,isDraft,reviewDecision,statusCheckRollup,state,updatedAt,url";
77
+ /**
78
+ * Build the board. `agents` is the daemon's live agent state; `blocked` is the
79
+ * set of agent ids that asked a question and are waiting on the human (the
80
+ * caller reads that from the event log — this module doesn't know about logs).
81
+ */
82
+ export async function buildBoard(dir, agents, blocked, opts = {}) {
83
+ const cards = [];
84
+ // 0. Yours: cards you wrote. The column you put it in is the whole state.
85
+ for (const t of opts.tasks ?? []) {
86
+ const column = BOARD_COLUMNS.includes(t.column)
87
+ ? t.column
88
+ : "working";
89
+ cards.push({
90
+ id: `task-${t.id}`,
91
+ title: t.title,
92
+ agent: t.agent ?? "",
93
+ ...(t.agent ? { kind: agents.find((a) => a.id === t.agent)?.kind } : {}),
94
+ state: TASK_STATE[column],
95
+ column,
96
+ own: true,
97
+ });
98
+ }
99
+ // 1. Ours: work that has no PR yet. An agent is either running or waiting.
100
+ for (const a of agents) {
101
+ if (a.tier !== "adapter")
102
+ continue; // a bridge never holds the baton
103
+ const isBlocked = blocked.includes(a.id);
104
+ if (!a.busy && !isBlocked)
105
+ continue; // idle agents are not work in flight
106
+ const state = isBlocked ? "input-needed" : "working";
107
+ cards.push({
108
+ id: `agent-${a.id}`,
109
+ title: isBlocked ? `${a.id} is waiting on you` : `${a.id} is working`,
110
+ agent: a.id,
111
+ kind: a.kind,
112
+ state,
113
+ column: columnFor(state),
114
+ });
115
+ }
116
+ // 2. GitHub: everything that reached a PR.
117
+ const repoRes = await ghRepo(dir);
118
+ if (!repoRes.ok) {
119
+ // EVERY gh failure degrades to a note — missing, signed out, no remote, a
120
+ // timeout, a 500. The agents above are the daemon's own state and stay
121
+ // true regardless, so none of these is a reason to show you an error page
122
+ // instead of the work you're running.
123
+ return {
124
+ available: true,
125
+ repo: null,
126
+ ghError: { reason: repoRes.err.reason, detail: repoRes.err.detail },
127
+ cards,
128
+ };
129
+ }
130
+ // Issues only when you search for them. The board is work in flight; a repo's
131
+ // whole backlog would bury that. A query is you asking, so we answer.
132
+ if (opts.search?.trim() && !/\bis:pr\b/i.test(opts.search)) {
133
+ try {
134
+ const out = await runGh([
135
+ "issue",
136
+ "list",
137
+ "--json",
138
+ "number,title,author,updatedAt,url",
139
+ "--limit",
140
+ String(opts.limit ?? 30),
141
+ "--search",
142
+ opts.search.trim(),
143
+ ], dir);
144
+ for (const it of JSON.parse(out)) {
145
+ cards.push({
146
+ id: `issue-${it.number}`,
147
+ title: it.title,
148
+ agent: it.author?.login ?? "",
149
+ state: "issue",
150
+ column: columnFor("issue"),
151
+ issue: { number: it.number, url: it.url },
152
+ updatedAt: it.updatedAt,
153
+ });
154
+ }
155
+ }
156
+ catch {
157
+ // the PR half below still runs; a failed issue search isn't the board
158
+ }
159
+ }
160
+ // `gh pr list --search "is:issue …"` doesn't return nothing — it ignores the
161
+ // qualifier and hands back open PRs, so searching for issues would also fill
162
+ // the board with unrelated pull requests. Ask for what was actually asked for.
163
+ if (opts.search?.trim() && /\bis:issue\b/i.test(opts.search)) {
164
+ return { available: true, repo: repoRes.repo, cards };
165
+ }
166
+ try {
167
+ const args = ["pr", "list", "--json", PR_FIELDS, "--limit", String(opts.limit ?? 30)];
168
+ // Passed through to gh verbatim, so the box takes github.com's own query
169
+ // language. execFile with an args array: it can't reach a shell.
170
+ if (opts.search?.trim())
171
+ args.push("--search", opts.search.trim());
172
+ const out = await runGh(args, dir);
173
+ for (const pr of JSON.parse(out)) {
174
+ const state = prState(pr);
175
+ cards.push({
176
+ id: `pr-${pr.number}`,
177
+ title: pr.title,
178
+ agent: pr.author?.login ?? "",
179
+ state,
180
+ column: columnFor(state),
181
+ ...(pr.headRefName ? { branch: pr.headRefName } : {}),
182
+ pr: {
183
+ number: pr.number,
184
+ state: String(pr.state ?? "").toLowerCase(),
185
+ draft: !!pr.isDraft,
186
+ url: pr.url,
187
+ },
188
+ updatedAt: pr.updatedAt,
189
+ });
190
+ }
191
+ }
192
+ catch (err) {
193
+ return {
194
+ available: true,
195
+ repo: repoRes.repo,
196
+ ghError: classifyGhFailure(String(err.message)),
197
+ cards,
198
+ };
199
+ }
200
+ return { available: true, repo: repoRes.repo, cards };
201
+ }
202
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/daemon/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * ADE brand marks — Claude Code, Antigravity, opencode, Kiro, Codex.
3
+ *
4
+ * GENERATED by scripts/gen-brand-icons.mjs from @lobehub/icons (MIT,
5
+ * github.com/lobehub/lobe-icons). Don't hand-edit; regenerate. The marks are
6
+ * frozen here because the web app has no build step and no CDN — it can't
7
+ * import React components and must work offline on a tailnet. Each logo is the
8
+ * trademark of its owner, used only to identify that agent.
9
+ *
10
+ * It's a sprite, not inline strings: Antigravity and Codex carry internal ids
11
+ * (masks, blur filters, a gradient), so repeating that markup per agent row
12
+ * would duplicate those ids across the document and `url(#id)` would resolve
13
+ * to whichever copy came first. <symbol> defines the art once; <use> draws it.
14
+ */
15
+ /** Agent kinds that have a real mark. Anything else falls back to a monogram. */
16
+ export declare const BRAND_KINDS: readonly ["claude-code", "antigravity", "opencode", "kiro", "codex", "grok-code"];
17
+ /** Human-readable name per kind, for tooltips and accessible names. */
18
+ export declare const BRAND_TITLES: Record<string, string>;
19
+ /**
20
+ * Injected once per page; every mark is drawn with <use href="#brand-<kind>">.
21
+ *
22
+ * Hidden with position:absolute;width:0;height:0 — NOT display:none. A gradient
23
+ * or filter is a paint server, and a paint server inside a display:none subtree
24
+ * is inert: the browser never lays it out, so any <use> that references it (in
25
+ * another SVG) paints nothing and you get a blank badge. That's exactly what
26
+ * turned Codex's colour swirl into a white square. width:0/height:0 keeps the
27
+ * sprite invisible and out of flow while leaving its paint servers live.
28
+ */
29
+ export declare const BRAND_SPRITE = "<svg xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\" style=\"position:absolute;width:0;height:0;overflow:hidden\">\n <symbol id=\"brand-claude-code\" viewBox=\"0 0 24 24\"><path clip-rule=\"evenodd\" d=\"M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z\" fill=\"#D97757\" fill-rule=\"evenodd\"></path></symbol>\n <symbol id=\"brand-antigravity\" viewBox=\"0 0 24 24\"><mask height=\"23\" id=\"loom-antigravity-0\" maskUnits=\"userSpaceOnUse\" width=\"24\" x=\"0\" y=\"1\"><path d=\"M21.751 22.607c1.34 1.005 3.35.335 1.508-1.508C17.73 15.74 18.904 1 12.037 1 5.17 1 6.342 15.74.815 21.1c-2.01 2.009.167 2.511 1.507 1.506 5.192-3.517 4.857-9.714 9.715-9.714 4.857 0 4.522 6.197 9.714 9.715z\" fill=\"#fff\"></path></mask><g mask=\"url(#loom-antigravity-0)\"><g filter=\"url(#loom-antigravity-1)\"><path d=\"M-1.018-3.992c-.408 3.591 2.686 6.89 6.91 7.37 4.225.48 7.98-2.043 8.387-5.633.408-3.59-2.686-6.89-6.91-7.37-4.225-.479-7.98 2.043-8.387 5.633z\" fill=\"#FFE432\"></path></g><g filter=\"url(#loom-antigravity-2)\"><path d=\"M15.269 7.747c1.058 4.557 5.691 7.374 10.348 6.293 4.657-1.082 7.575-5.653 6.516-10.21-1.058-4.556-5.691-7.374-10.348-6.292-4.657 1.082-7.575 5.653-6.516 10.21z\" fill=\"#FC413D\"></path></g><g filter=\"url(#loom-antigravity-3)\"><path d=\"M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z\" fill=\"#00B95C\"></path></g><g filter=\"url(#loom-antigravity-4)\"><path d=\"M-12.443 10.804c1.338 4.703 7.36 7.11 13.453 5.378 6.092-1.733 9.947-6.95 8.61-11.652C8.282-.173 2.26-2.58-3.833-.848-9.925.884-13.78 6.1-12.443 10.804z\" fill=\"#00B95C\"></path></g><g filter=\"url(#loom-antigravity-5)\"><path d=\"M-7.608 14.703c3.352 3.424 9.126 3.208 12.896-.483 3.77-3.69 4.108-9.459.756-12.883C2.69-2.087-3.083-1.871-6.853 1.82c-3.77 3.69-4.108 9.458-.755 12.883z\" fill=\"#00B95C\"></path></g><g filter=\"url(#loom-antigravity-6)\"><path d=\"M9.932 27.617c1.04 4.482 5.384 7.303 9.7 6.3 4.316-1.002 6.971-5.448 5.93-9.93-1.04-4.483-5.384-7.304-9.7-6.301-4.316 1.002-6.971 5.448-5.93 9.93z\" fill=\"#3186FF\"></path></g><g filter=\"url(#loom-antigravity-7)\"><path d=\"M2.572-8.185C.392-3.329 2.778 2.472 7.9 4.771c5.122 2.3 11.042.227 13.222-4.63 2.18-4.855-.205-10.656-5.327-12.955-5.122-2.3-11.042-.227-13.222 4.63z\" fill=\"#FBBC04\"></path></g><g filter=\"url(#loom-antigravity-8)\"><path d=\"M-3.267 38.686c-5.277-2.072 3.742-19.117 5.984-24.83 2.243-5.712 8.34-8.664 13.616-6.592 5.278 2.071 11.533 13.482 9.29 19.195-2.242 5.713-23.613 14.298-28.89 12.227z\" fill=\"#3186FF\"></path></g><g filter=\"url(#loom-antigravity-9)\"><path d=\"M28.71 17.471c-1.413 1.649-5.1.808-8.236-1.878-3.135-2.687-4.531-6.201-3.118-7.85 1.412-1.649 5.1-.808 8.235 1.878s4.532 6.2 3.119 7.85z\" fill=\"#749BFF\"></path></g><g filter=\"url(#loom-antigravity-10)\"><path d=\"M18.163 9.077c5.81 3.93 12.502 4.19 14.946.577 2.443-3.612-.287-9.727-6.098-13.658-5.81-3.931-12.502-4.19-14.946-.577-2.443 3.612.287 9.727 6.098 13.658z\" fill=\"#FC413D\"></path></g><g filter=\"url(#loom-antigravity-11)\"><path d=\"M-.915 2.684c-1.44 3.473-.97 6.967 1.05 7.804 2.02.837 4.824-1.3 6.264-4.772 1.44-3.473.97-6.967-1.05-7.804-2.02-.837-4.824 1.3-6.264 4.772z\" fill=\"#FFEE48\"></path></g></g><defs><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"17.587\" id=\"loom-antigravity-1\" width=\"19.838\" x=\"-3.288\" y=\"-11.917\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"1.117\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"38.565\" id=\"loom-antigravity-2\" width=\"38.9\" x=\"4.251\" y=\"-13.493\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"5.4\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"36.517\" id=\"loom-antigravity-3\" width=\"40.955\" x=\"-21.889\" y=\"-10.592\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"4.591\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"36.517\" id=\"loom-antigravity-4\" width=\"40.955\" x=\"-21.889\" y=\"-10.592\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"4.591\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"36.595\" id=\"loom-antigravity-5\" width=\"36.632\" x=\"-19.099\" y=\"-10.278\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"4.591\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"34.087\" id=\"loom-antigravity-6\" width=\"33.533\" x=\".981\" y=\"8.758\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"4.363\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"35.276\" id=\"loom-antigravity-7\" width=\"35.978\" x=\"-6.143\" y=\"-21.659\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"3.954\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"46.523\" id=\"loom-antigravity-8\" width=\"45.114\" x=\"-11.96\" y=\"-.46\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"3.531\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"24.054\" id=\"loom-antigravity-9\" width=\"25.094\" x=\"10.485\" y=\".58\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"3.159\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"30.007\" id=\"loom-antigravity-10\" width=\"33.508\" x=\"5.833\" y=\"-12.467\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"2.669\"></feGaussianBlur></filter><filter color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\" height=\"26.151\" id=\"loom-antigravity-11\" width=\"22.194\" x=\"-8.355\" y=\"-8.876\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"></feFlood><feBlend in=\"SourceGraphic\" in2=\"BackgroundImageFix\" result=\"shape\"></feBlend><feGaussianBlur result=\"effect1_foregroundBlur_977_115\" stdDeviation=\"3.303\"></feGaussianBlur></filter></defs></symbol>\n <symbol id=\"brand-opencode\" viewBox=\"0 0 24 24\"><path d=\"M16 6H8v12h8V6zm4 16H4V2h16v20z\"></path></symbol>\n <symbol id=\"brand-kiro\" viewBox=\"0 0 24 24\"><path d=\"M18.8 0H5.2A5.2 5.2 0 000 5.2v13.6A5.2 5.2 0 005.2 24h13.6a5.2 5.2 0 005.2-5.2V5.2A5.2 5.2 0 0018.8 0z\" fill=\"#9046FF\"></path><path d=\"M7.97 16.376c-1.644 3.642 1.86 4.556 4.443 2.424.76 2.39 3.608.607 4.631-1.247 2.251-4.084 1.342-8.249 1.108-9.108-1.6-5.859-9.6-5.869-10.976.03-.323 1.033-.328 2.206-.507 3.423-.09.617-.16 1.009-.393 1.655-.139.373-.323.7-.62 1.257-.458.865-.264 2.53 2.101 1.665l.224-.1h-.01l-.001.001z\" fill=\"#fff\"></path><path d=\"M12.722 10.985c-.656 0-.755-.785-.755-1.252 0-.423.074-.756.218-.97a.61.61 0 01.537-.283c.229 0 .428.095.567.289.159.218.243.55.243.964 0 .785-.303 1.252-.805 1.252h-.005zm2.703 0c-.656 0-.755-.785-.755-1.252 0-.423.074-.756.219-.97a.61.61 0 01.536-.283c.229 0 .428.095.567.289.159.218.243.55.243.964 0 .785-.303 1.252-.805 1.252h-.005z\" fill=\"#000\"></path></symbol>\n <symbol id=\"brand-codex\" viewBox=\"0 0 24 24\"><path d=\"M19.503 0H4.496A4.496 4.496 0 000 4.496v15.007A4.496 4.496 0 004.496 24h15.007A4.496 4.496 0 0024 19.503V4.496A4.496 4.496 0 0019.503 0z\" fill=\"#fff\"></path><path d=\"M9.064 3.344a4.578 4.578 0 012.285-.312c1 .115 1.891.54 2.673 1.275.01.01.024.017.037.021a.09.09 0 00.043 0 4.55 4.55 0 013.046.275l.047.022.116.057a4.581 4.581 0 012.188 2.399c.209.51.313 1.041.315 1.595a4.24 4.24 0 01-.134 1.223.123.123 0 00.03.115c.594.607.988 1.33 1.183 2.17.289 1.425-.007 2.71-.887 3.854l-.136.166a4.548 4.548 0 01-2.201 1.388.123.123 0 00-.081.076c-.191.551-.383 1.023-.74 1.494-.9 1.187-2.222 1.846-3.711 1.838-1.187-.006-2.239-.44-3.157-1.302a.107.107 0 00-.105-.024c-.388.125-.78.143-1.204.138a4.441 4.441 0 01-1.945-.466 4.544 4.544 0 01-1.61-1.335c-.152-.202-.303-.392-.414-.617a5.81 5.81 0 01-.37-.961 4.582 4.582 0 01-.014-2.298.124.124 0 00.006-.056.085.085 0 00-.027-.048 4.467 4.467 0 01-1.034-1.651 3.896 3.896 0 01-.251-1.192 5.189 5.189 0 01.141-1.6c.337-1.112.982-1.985 1.933-2.618.212-.141.413-.251.601-.33.215-.089.43-.164.646-.227a.098.098 0 00.065-.066 4.51 4.51 0 01.829-1.615 4.535 4.535 0 011.837-1.388zm3.482 10.565a.637.637 0 000 1.272h3.636a.637.637 0 100-1.272h-3.636zM8.462 9.23a.637.637 0 00-1.106.631l1.272 2.224-1.266 2.136a.636.636 0 101.095.649l1.454-2.455a.636.636 0 00.005-.64L8.462 9.23z\" fill=\"url(#loom-codex-0)\"></path><defs><linearGradient id=\"loom-codex-0\" x1=\"0.5\" x2=\"0.5\" y1=\"0\" y2=\"1\"><stop stop-color=\"#B1A7FF\"></stop><stop offset=\".5\" stop-color=\"#7A9DFF\"></stop><stop offset=\"1\" stop-color=\"#3941FF\"></stop></linearGradient></defs></symbol>\n <symbol id=\"brand-grok-code\" viewBox=\"0 0 24 24\"><path d=\"M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815\"></path></symbol>\n</svg>";