@guildai/cli 0.11.0 → 0.12.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 (198) hide show
  1. package/dist/auth-CRMO5O3N.js +29 -0
  2. package/dist/auth-CRMO5O3N.js.map +7 -0
  3. package/dist/chat-5VX2WJH2.js +303 -0
  4. package/dist/chat-5VX2WJH2.js.map +7 -0
  5. package/dist/chat-SIKDYZQK.js +31 -0
  6. package/dist/chat-SIKDYZQK.js.map +7 -0
  7. package/dist/chunk-56YCMGL3.js +522 -0
  8. package/dist/chunk-56YCMGL3.js.map +7 -0
  9. package/dist/chunk-6EX6E7WP.js +7042 -0
  10. package/dist/chunk-6EX6E7WP.js.map +7 -0
  11. package/dist/chunk-B7VAF5UG.js +532 -0
  12. package/dist/chunk-B7VAF5UG.js.map +7 -0
  13. package/dist/chunk-DOIYVBNY.js +3057 -0
  14. package/dist/chunk-DOIYVBNY.js.map +7 -0
  15. package/dist/chunk-ENKEEJ45.js +17 -0
  16. package/dist/chunk-ENKEEJ45.js.map +7 -0
  17. package/dist/chunk-IBRKVGMZ.js +97041 -0
  18. package/dist/chunk-IBRKVGMZ.js.map +7 -0
  19. package/dist/chunk-LFMQJOKC.js +19778 -0
  20. package/dist/chunk-LFMQJOKC.js.map +7 -0
  21. package/dist/chunk-M347HP6M.js +22896 -0
  22. package/dist/chunk-M347HP6M.js.map +7 -0
  23. package/dist/chunk-OYQ476FQ.js +44 -0
  24. package/dist/chunk-OYQ476FQ.js.map +7 -0
  25. package/dist/chunk-PNCUR4OB.js +257 -0
  26. package/dist/chunk-PNCUR4OB.js.map +7 -0
  27. package/dist/chunk-RIG2HZWM.js +317 -0
  28. package/dist/chunk-RIG2HZWM.js.map +7 -0
  29. package/dist/chunk-SPZPZXUN.js +826 -0
  30. package/dist/chunk-SPZPZXUN.js.map +7 -0
  31. package/dist/chunk-VVSOU6ON.js +53 -0
  32. package/dist/chunk-VVSOU6ON.js.map +7 -0
  33. package/dist/chunk-X3ADGWOF.js +3643 -0
  34. package/dist/chunk-X3ADGWOF.js.map +7 -0
  35. package/dist/commands/skill/create.d.ts +3 -0
  36. package/dist/commands/skill/get.d.ts +3 -0
  37. package/dist/commands/skill/list.d.ts +3 -0
  38. package/dist/commands/skill/update.d.ts +3 -0
  39. package/dist/commands/skill/version/create.d.ts +3 -0
  40. package/dist/commands/skill/version/get.d.ts +3 -0
  41. package/dist/commands/skill/version/list.d.ts +3 -0
  42. package/dist/devtools-AO7YSDOD.js +67 -0
  43. package/dist/devtools-AO7YSDOD.js.map +7 -0
  44. package/dist/dist-4CBK6X5H.js +1566 -0
  45. package/dist/dist-4CBK6X5H.js.map +7 -0
  46. package/dist/esm-FRAVZP4J.js +13 -0
  47. package/dist/esm-FRAVZP4J.js.map +7 -0
  48. package/dist/execa-XQMWSABC.js +35 -0
  49. package/dist/execa-XQMWSABC.js.map +7 -0
  50. package/dist/index.js +8230 -263
  51. package/dist/index.js.map +7 -0
  52. package/dist/lib/api-types.d.ts +44 -0
  53. package/dist/lib/config.d.ts +9 -0
  54. package/dist/lib/errors.d.ts +1 -1
  55. package/dist/lib/output.d.ts +11 -1
  56. package/dist/lib/session-events.d.ts +1 -1
  57. package/dist/lib/session-polling.d.ts +24 -1
  58. package/dist/lib/websocket-client.d.ts +46 -0
  59. package/dist/open-RF4X5MOP.js +13 -0
  60. package/dist/open-RF4X5MOP.js.map +7 -0
  61. package/dist/server-JYVH64FD.js +27659 -0
  62. package/dist/server-JYVH64FD.js.map +7 -0
  63. package/dist/test-SNIYRJ32.js +692 -0
  64. package/dist/test-SNIYRJ32.js.map +7 -0
  65. package/docs/skills/codex-agent-dev.md +2 -2
  66. package/package.json +8 -12
  67. package/dist/commands/agent/chat.js +0 -281
  68. package/dist/commands/agent/clone.js +0 -118
  69. package/dist/commands/agent/code.js +0 -87
  70. package/dist/commands/agent/fork.js +0 -220
  71. package/dist/commands/agent/get.js +0 -37
  72. package/dist/commands/agent/grep.js +0 -107
  73. package/dist/commands/agent/init.js +0 -403
  74. package/dist/commands/agent/list.js +0 -110
  75. package/dist/commands/agent/logs.js +0 -62
  76. package/dist/commands/agent/owners.js +0 -74
  77. package/dist/commands/agent/publish.js +0 -91
  78. package/dist/commands/agent/pull.js +0 -194
  79. package/dist/commands/agent/revalidate.js +0 -56
  80. package/dist/commands/agent/save.js +0 -345
  81. package/dist/commands/agent/search.js +0 -61
  82. package/dist/commands/agent/tags/add.js +0 -73
  83. package/dist/commands/agent/tags/list.js +0 -43
  84. package/dist/commands/agent/tags/remove.js +0 -84
  85. package/dist/commands/agent/tags/set.js +0 -71
  86. package/dist/commands/agent/test.js +0 -489
  87. package/dist/commands/agent/unpublish.js +0 -64
  88. package/dist/commands/agent/update.js +0 -118
  89. package/dist/commands/agent/versions.js +0 -55
  90. package/dist/commands/agent/workspaces.js +0 -54
  91. package/dist/commands/auth/login.js +0 -31
  92. package/dist/commands/auth/logout.js +0 -24
  93. package/dist/commands/auth/status.js +0 -38
  94. package/dist/commands/auth/token.js +0 -19
  95. package/dist/commands/chat.js +0 -1416
  96. package/dist/commands/config/get.js +0 -64
  97. package/dist/commands/config/list.js +0 -46
  98. package/dist/commands/config/path.js +0 -37
  99. package/dist/commands/config/set.js +0 -132
  100. package/dist/commands/credentials/endpoint-list.js +0 -88
  101. package/dist/commands/credentials/list.js +0 -50
  102. package/dist/commands/credentials/policy-create.js +0 -66
  103. package/dist/commands/credentials/policy-delete.js +0 -33
  104. package/dist/commands/credentials/policy-list.js +0 -45
  105. package/dist/commands/credentials/policy-update.js +0 -66
  106. package/dist/commands/doctor.js +0 -233
  107. package/dist/commands/integration/connect.js +0 -76
  108. package/dist/commands/integration/create.js +0 -298
  109. package/dist/commands/integration/get.js +0 -95
  110. package/dist/commands/integration/list.js +0 -62
  111. package/dist/commands/integration/operation/create.js +0 -164
  112. package/dist/commands/integration/operation/list.js +0 -92
  113. package/dist/commands/integration/update.js +0 -139
  114. package/dist/commands/integration/version/build.js +0 -86
  115. package/dist/commands/integration/version/create.js +0 -45
  116. package/dist/commands/integration/version/get.js +0 -72
  117. package/dist/commands/integration/version/list.js +0 -45
  118. package/dist/commands/integration/version/publish.js +0 -79
  119. package/dist/commands/integration/version/test.js +0 -104
  120. package/dist/commands/job/get-step.js +0 -40
  121. package/dist/commands/job/get.js +0 -44
  122. package/dist/commands/mcp.js +0 -34
  123. package/dist/commands/session/create.js +0 -59
  124. package/dist/commands/session/events.js +0 -56
  125. package/dist/commands/session/get.js +0 -33
  126. package/dist/commands/session/interrupt.js +0 -33
  127. package/dist/commands/session/list.js +0 -59
  128. package/dist/commands/session/send.js +0 -54
  129. package/dist/commands/session/tasks.js +0 -45
  130. package/dist/commands/setup.js +0 -260
  131. package/dist/commands/trigger/activate.js +0 -41
  132. package/dist/commands/trigger/create.js +0 -197
  133. package/dist/commands/trigger/deactivate.js +0 -41
  134. package/dist/commands/trigger/get.js +0 -33
  135. package/dist/commands/trigger/list.js +0 -57
  136. package/dist/commands/trigger/sessions.js +0 -48
  137. package/dist/commands/trigger/update.js +0 -128
  138. package/dist/commands/version.js +0 -24
  139. package/dist/commands/workspace/agent/add.js +0 -114
  140. package/dist/commands/workspace/agent/list.js +0 -78
  141. package/dist/commands/workspace/agent/remove.js +0 -78
  142. package/dist/commands/workspace/clear.js +0 -45
  143. package/dist/commands/workspace/context/edit.js +0 -107
  144. package/dist/commands/workspace/context/get.js +0 -47
  145. package/dist/commands/workspace/context/list.js +0 -51
  146. package/dist/commands/workspace/context/publish.js +0 -42
  147. package/dist/commands/workspace/create.js +0 -51
  148. package/dist/commands/workspace/current.js +0 -63
  149. package/dist/commands/workspace/get.js +0 -39
  150. package/dist/commands/workspace/list.js +0 -70
  151. package/dist/commands/workspace/select.js +0 -184
  152. package/dist/components/AgentInstallPrompt.js +0 -97
  153. package/dist/components/SplashAnimation.js +0 -321
  154. package/dist/components/TaskView.js +0 -268
  155. package/dist/lib/agent-helpers.js +0 -306
  156. package/dist/lib/alternate-screen.js +0 -59
  157. package/dist/lib/api-client.js +0 -154
  158. package/dist/lib/api-types.js +0 -10
  159. package/dist/lib/auth.js +0 -284
  160. package/dist/lib/braille-canvas.js +0 -321
  161. package/dist/lib/colors.js +0 -46
  162. package/dist/lib/config-cache.js +0 -45
  163. package/dist/lib/config.js +0 -153
  164. package/dist/lib/did-you-mean.js +0 -144
  165. package/dist/lib/errors.js +0 -375
  166. package/dist/lib/event-filter.js +0 -91
  167. package/dist/lib/generated-types.js +0 -56
  168. package/dist/lib/git.js +0 -176
  169. package/dist/lib/gk.js +0 -91
  170. package/dist/lib/guild-config.js +0 -178
  171. package/dist/lib/iap.js +0 -117
  172. package/dist/lib/integration-helpers.js +0 -38
  173. package/dist/lib/loading-messages.js +0 -72
  174. package/dist/lib/logo.js +0 -141
  175. package/dist/lib/lottie-serverside.js +0 -181
  176. package/dist/lib/markdown.js +0 -38
  177. package/dist/lib/npmrc.js +0 -59
  178. package/dist/lib/output-mode.js +0 -54
  179. package/dist/lib/output.js +0 -622
  180. package/dist/lib/owner-helpers.js +0 -112
  181. package/dist/lib/polling.js +0 -76
  182. package/dist/lib/progress.js +0 -324
  183. package/dist/lib/session-events-fetch.js +0 -25
  184. package/dist/lib/session-events.js +0 -126
  185. package/dist/lib/session-polling.js +0 -166
  186. package/dist/lib/session-resume.js +0 -229
  187. package/dist/lib/spinners.js +0 -770
  188. package/dist/lib/splash.js +0 -42
  189. package/dist/lib/stdin.js +0 -91
  190. package/dist/lib/svg-to-braille.js +0 -76
  191. package/dist/lib/table.js +0 -59
  192. package/dist/lib/update-check.js +0 -65
  193. package/dist/lib/validate-input-schema.js +0 -208
  194. package/dist/lib/version-helpers.js +0 -137
  195. package/dist/lib/workspace-helpers.js +0 -49
  196. package/dist/mcp/resources.js +0 -67
  197. package/dist/mcp/server.js +0 -64
  198. package/dist/mcp/tools.js +0 -753
package/dist/lib/auth.js DELETED
@@ -1,284 +0,0 @@
1
- // Copyright 2026 Guild.ai
2
- // SPDX-License-Identifier: Apache-2.0
3
- import { AsyncEntry } from '@napi-rs/keyring';
4
- import axios, { AxiosError } from 'axios';
5
- import chalk from 'chalk';
6
- import cliBoxes from 'cli-boxes';
7
- import inquirer from 'inquirer';
8
- import { handleAxiosError } from './errors.js';
9
- import { createSpinner } from './progress.js';
10
- import { getGuildcoreUrl } from './config.js';
11
- import { getIapHeaders } from './iap.js';
12
- import { brand, warn } from './colors.js';
13
- import { isInteractive } from './stdin.js';
14
- const SERVICE_NAME = 'guild-cli';
15
- /**
16
- * Get account name for keyring, keyed by host to support multiple backends
17
- */
18
- function getAccountName() {
19
- const url = getGuildcoreUrl();
20
- try {
21
- const host = new URL(url).host;
22
- return `auth-token:${host}`;
23
- }
24
- catch {
25
- return 'auth-token';
26
- }
27
- }
28
- /**
29
- * Display verification code in a styled box
30
- */
31
- function displayVerificationCode(code, authUrl) {
32
- const box = cliBoxes.round;
33
- const maxWidth = 95; // Increased to fit UUID-based device flow URLs
34
- const lines = [
35
- '',
36
- ` ${chalk.bold('Verification code:')} ${brand.bold(code)}`,
37
- '',
38
- ` ${chalk.dim('Open:')} ${brand(authUrl)}`,
39
- '',
40
- ];
41
- // Calculate box width based on longest line (accounting for ANSI codes)
42
- const strippedLines = lines.map((line) => line.replace(/\x1b\[[0-9;]*m/g, ''));
43
- const contentWidth = Math.max(...strippedLines.map((line) => line.length));
44
- const boxWidth = Math.min(contentWidth + 4, maxWidth);
45
- // Build the box
46
- const horizontalLine = box.top.repeat(boxWidth - 2);
47
- const topBorder = box.topLeft + horizontalLine + box.topRight;
48
- const bottomBorder = box.bottomLeft + box.bottom.repeat(boxWidth - 2) + box.bottomRight;
49
- console.log('\n' + chalk.dim(topBorder));
50
- lines.forEach((line) => {
51
- const strippedLine = line.replace(/\x1b\[[0-9;]*m/g, '');
52
- const padding = ' '.repeat(Math.max(0, boxWidth - strippedLine.length - 2));
53
- console.log(chalk.dim(box.left) + line + padding + chalk.dim(box.right));
54
- });
55
- console.log(chalk.dim(bottomBorder) + '\n');
56
- }
57
- /**
58
- * Save authentication token to system keyring
59
- */
60
- export async function saveAuthToken(token) {
61
- const entry = new AsyncEntry(SERVICE_NAME, getAccountName());
62
- await entry.setPassword(token);
63
- }
64
- /**
65
- * Get authentication token from system keyring or state file
66
- * Returns null if no token is stored
67
- *
68
- * In test environments, checks GUILD_STATE_DIR/auth-state.json ONLY (no fallback)
69
- * In production, checks system keyring
70
- */
71
- export async function getAuthToken() {
72
- // Check for token in state directory (used by E2E tests)
73
- const stateDir = process.env.GUILD_STATE_DIR;
74
- if (stateDir) {
75
- try {
76
- const fs = await import('fs/promises');
77
- const path = await import('path');
78
- const authStatePath = path.join(stateDir, 'auth-state.json');
79
- const authStateContent = await fs.readFile(authStatePath, 'utf-8');
80
- const authState = JSON.parse(authStateContent);
81
- if (authState.token && authState.authenticated) {
82
- return authState.token;
83
- }
84
- }
85
- catch {
86
- // In test mode (GUILD_STATE_DIR set), do NOT fall back to keyring
87
- // This ensures test isolation - tests must explicitly authenticate
88
- return null;
89
- }
90
- return null;
91
- }
92
- // Check system keyring (production use)
93
- try {
94
- const entry = new AsyncEntry(SERVICE_NAME, getAccountName());
95
- const token = await entry.getPassword();
96
- return token || null;
97
- }
98
- catch {
99
- return null;
100
- }
101
- }
102
- /**
103
- * Clear authentication token from system keyring
104
- */
105
- export async function clearAuthToken() {
106
- try {
107
- const entry = new AsyncEntry(SERVICE_NAME, getAccountName());
108
- await entry.deletePassword();
109
- }
110
- catch {
111
- // Ignore if token doesn't exist
112
- }
113
- }
114
- /**
115
- * Start OAuth device flow
116
- * @param authUrl - Base URL of the OAuth provider (guildcore)
117
- * @param returnUrl - Optional custom URL to redirect to after authentication
118
- * @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
119
- * @returns Device code response with verification URL and code
120
- */
121
- export async function startDeviceFlow(authUrl = getGuildcoreUrl(), returnUrl, returnLabel) {
122
- const requestBody = {};
123
- if (returnUrl) {
124
- requestBody.return_url = returnUrl;
125
- }
126
- if (returnLabel) {
127
- requestBody.return_label = returnLabel;
128
- }
129
- // Get IAP headers for IAP-protected hosts
130
- const iapHeaders = await getIapHeaders(authUrl);
131
- const response = await axios.post(`${authUrl}/oauth/device/initiate`, requestBody, { headers: iapHeaders });
132
- return response.data;
133
- }
134
- /**
135
- * Poll for OAuth token
136
- * @param authUrl - Base URL of the OAuth provider (guildcore)
137
- * @param code - Device code from startDeviceFlow
138
- * @returns Access token if successful, null if failed/expired
139
- */
140
- export async function pollForToken(authUrl, code, interval) {
141
- const isTTY = process.stderr.isTTY || false;
142
- const spinner = createSpinner('Waiting for authorization...');
143
- spinner.start();
144
- const maxAttempts = 90; // 3 minutes (90 * 2 seconds)
145
- let attempts = 0;
146
- // Get IAP headers for IAP-protected hosts (fetch once, reuse for all polls)
147
- const iapHeaders = await getIapHeaders(authUrl);
148
- while (attempts < maxAttempts) {
149
- attempts++;
150
- await new Promise((resolve) => setTimeout(resolve, interval * 1000));
151
- try {
152
- const response = await axios.post(`${authUrl}/oauth/device/token`, {
153
- grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
154
- device_code: code,
155
- }, { headers: iapHeaders });
156
- if (response.data.access_token) {
157
- spinner.succeed('Authorization successful!');
158
- return response.data.access_token;
159
- }
160
- else {
161
- spinner.fail('Missing access token');
162
- return null;
163
- }
164
- }
165
- catch (error) {
166
- if (error instanceof AxiosError && error.status === 400) {
167
- if (error.response?.data?.error === 'slow_down') {
168
- interval += 5;
169
- }
170
- if (error.response?.data?.error === 'authorization_pending' ||
171
- error.response?.data?.error === 'slow_down') {
172
- if (isTTY) {
173
- spinner.text = `Waiting for authorization... (${attempts}/${maxAttempts})`;
174
- }
175
- continue;
176
- }
177
- }
178
- spinner.fail('Authorization polling failed');
179
- const formattedError = handleAxiosError(error);
180
- console.error(chalk.red('\nError:'), formattedError.error);
181
- console.error(warn(formattedError.details));
182
- throw error;
183
- }
184
- }
185
- spinner.fail('Authorization timed out');
186
- return null;
187
- }
188
- /**
189
- * Perform complete login flow
190
- * @param returnUrl - Optional custom URL to redirect to after authentication
191
- * @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
192
- * @returns true if successful, false otherwise
193
- */
194
- export async function login(returnUrl, returnLabel) {
195
- const authUrl = getGuildcoreUrl();
196
- try {
197
- console.log(chalk.bold('\nGuild.ai Authentication'));
198
- const deviceCode = await startDeviceFlow(authUrl, returnUrl, returnLabel);
199
- const skipBrowser = !isInteractive();
200
- if (skipBrowser) {
201
- console.log(`\nVerification code: ${deviceCode.user_code}`);
202
- console.log(`Open to authenticate: ${deviceCode.verification_uri_complete}\n`);
203
- }
204
- else {
205
- displayVerificationCode(deviceCode.user_code, deviceCode.verification_uri_complete);
206
- // Wait for user to press Enter before opening browser
207
- // This gives them time to see and copy the code before browser opens
208
- // Critical for VSCode integration where browser may open full screen
209
- const { openBrowser } = await inquirer.prompt([
210
- {
211
- type: 'confirm',
212
- name: 'openBrowser',
213
- message: 'Press Enter to open browser in your default web browser...',
214
- default: true,
215
- },
216
- ]);
217
- if (!openBrowser) {
218
- console.error(chalk.red('✗ Authentication cancelled by user'));
219
- return false;
220
- }
221
- // Open URL in default browser after user confirmation
222
- try {
223
- const open = (await import('open')).default;
224
- await open(deviceCode.verification_uri_complete);
225
- }
226
- catch {
227
- // Fallback if open fails - user can manually open URL
228
- console.log(chalk.red('✗ Could not open browser automatically. Please visit the URL manually.\n'));
229
- }
230
- }
231
- const token = await pollForToken(authUrl, deviceCode.device_code, deviceCode.interval);
232
- if (token) {
233
- await saveAuthToken(token);
234
- return true;
235
- }
236
- return false;
237
- }
238
- catch (error) {
239
- console.log(''); // Blank line for spacing
240
- const formattedError = handleAxiosError(error);
241
- console.error(chalk.red('✗ Authentication failed'));
242
- console.error(warn(`\nError: ${formattedError.error}`));
243
- console.error(chalk.dim(formattedError.details));
244
- if (formattedError.code) {
245
- console.error(chalk.dim(`\nError code: ${formattedError.code}`));
246
- }
247
- return false;
248
- }
249
- }
250
- /**
251
- * Perform logout
252
- */
253
- export async function logout() {
254
- await clearAuthToken();
255
- console.log(chalk.green('\n✓ Logged out successfully\n'));
256
- }
257
- /**
258
- * Get current authentication status
259
- * @returns Object with authenticated flag and optional token
260
- */
261
- export async function getAuthStatus() {
262
- const token = await getAuthToken();
263
- return {
264
- authenticated: !!token,
265
- token: token || undefined,
266
- };
267
- }
268
- /**
269
- * Create an authenticated URL by embedding the auth token.
270
- * Used for operations requiring x-access-token authentication.
271
- * @param targetUrl - The URL to authenticate
272
- * @returns URL with x-access-token credentials embedded, or null if not authenticated
273
- */
274
- export async function getAuthenticatedUrl(targetUrl) {
275
- const token = await getAuthToken();
276
- if (!token) {
277
- return null;
278
- }
279
- const url = new URL(targetUrl);
280
- url.username = 'x-access-token';
281
- url.password = token;
282
- return url.toString();
283
- }
284
- //# sourceMappingURL=auth.js.map
@@ -1,321 +0,0 @@
1
- // Copyright 2026 Guild.ai
2
- // SPDX-License-Identifier: Apache-2.0
3
- /**
4
- * Braille Canvas - A tiny pixel canvas using Unicode braille characters
5
- *
6
- * Each braille character represents a 2x4 pixel grid (8 dots total).
7
- * Multiple characters side-by-side create a wider canvas.
8
- *
9
- * Braille dot positions:
10
- * 1 4
11
- * 2 5
12
- * 3 6
13
- * 7 8
14
- *
15
- * Unicode encoding: U+2800 + bit pattern
16
- * dot1=0x01, dot2=0x02, dot3=0x04, dot4=0x08
17
- * dot5=0x10, dot6=0x20, dot7=0x40, dot8=0x80
18
- */
19
- import chalk from 'chalk';
20
- // Braille base character (blank)
21
- const BRAILLE_BASE = 0x2800;
22
- // Dot bit positions indexed by (x, y) where x is 0-1, y is 0-3
23
- const DOT_BITS = [
24
- [0x01, 0x08], // y=0: dot1, dot4
25
- [0x02, 0x10], // y=1: dot2, dot5
26
- [0x04, 0x20], // y=2: dot3, dot6
27
- [0x40, 0x80], // y=3: dot7, dot8
28
- ];
29
- /**
30
- * A braille-based pixel canvas
31
- *
32
- * Canvas dimensions are in "pixels" (dots), internally stored as braille chars.
33
- * Width should be even (each braille char is 2 pixels wide).
34
- * Height should be multiple of 4 (each braille char is 4 pixels tall).
35
- */
36
- export class BrailleCanvas {
37
- width; // Width in pixels (dots)
38
- height; // Height in pixels (dots)
39
- charWidth; // Width in braille characters
40
- charHeight; // Height in braille characters
41
- pixels; // 2D array of pixel states
42
- colors; // Color per braille character cell
43
- constructor(width, height) {
44
- // Round up to braille character boundaries
45
- this.charWidth = Math.ceil(width / 2);
46
- this.charHeight = Math.ceil(height / 4);
47
- this.width = this.charWidth * 2;
48
- this.height = this.charHeight * 4;
49
- // Initialize pixel array (all off)
50
- this.pixels = Array(this.height)
51
- .fill(null)
52
- .map(() => Array(this.width).fill(false));
53
- // Initialize colors (default: no color override)
54
- this.colors = Array(this.charHeight)
55
- .fill(null)
56
- .map(() => Array(this.charWidth)
57
- .fill(null)
58
- .map(() => ({})));
59
- }
60
- /**
61
- * Clear the canvas
62
- */
63
- clear() {
64
- for (let y = 0; y < this.height; y++) {
65
- for (let x = 0; x < this.width; x++) {
66
- this.pixels[y][x] = false;
67
- }
68
- }
69
- for (let cy = 0; cy < this.charHeight; cy++) {
70
- for (let cx = 0; cx < this.charWidth; cx++) {
71
- this.colors[cy][cx] = {};
72
- }
73
- }
74
- }
75
- /**
76
- * Set a single pixel
77
- */
78
- setPixel(x, y, on = true) {
79
- if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
80
- this.pixels[y][x] = on;
81
- }
82
- }
83
- /**
84
- * Get a pixel value
85
- */
86
- getPixel(x, y) {
87
- if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
88
- return this.pixels[y][x];
89
- }
90
- return false;
91
- }
92
- /**
93
- * Set color for a braille character cell
94
- * @param cx - Character x position (0 to charWidth-1)
95
- * @param cy - Character y position (0 to charHeight-1)
96
- * @param color - Color specification
97
- */
98
- setCellColor(cx, cy, color) {
99
- if (cx >= 0 && cx < this.charWidth && cy >= 0 && cy < this.charHeight) {
100
- this.colors[cy][cx] = color;
101
- }
102
- }
103
- /**
104
- * Set color for a pixel (affects the containing braille cell)
105
- */
106
- setPixelColor(x, y, color) {
107
- const cx = Math.floor(x / 2);
108
- const cy = Math.floor(y / 4);
109
- this.setCellColor(cx, cy, color);
110
- }
111
- /**
112
- * Draw a line using Bresenham's algorithm
113
- */
114
- drawLine(x0, y0, x1, y1) {
115
- const dx = Math.abs(x1 - x0);
116
- const dy = Math.abs(y1 - y0);
117
- const sx = x0 < x1 ? 1 : -1;
118
- const sy = y0 < y1 ? 1 : -1;
119
- let err = dx - dy;
120
- let x = x0;
121
- let y = y0;
122
- while (true) {
123
- this.setPixel(x, y, true);
124
- if (x === x1 && y === y1)
125
- break;
126
- const e2 = 2 * err;
127
- if (e2 > -dy) {
128
- err -= dy;
129
- x += sx;
130
- }
131
- if (e2 < dx) {
132
- err += dx;
133
- y += sy;
134
- }
135
- }
136
- }
137
- /**
138
- * Draw a filled rectangle
139
- */
140
- fillRect(x, y, w, h) {
141
- for (let py = y; py < y + h; py++) {
142
- for (let px = x; px < x + w; px++) {
143
- this.setPixel(px, py, true);
144
- }
145
- }
146
- }
147
- /**
148
- * Draw a circle outline
149
- */
150
- drawCircle(cx, cy, r) {
151
- let x = r;
152
- let y = 0;
153
- let err = 0;
154
- while (x >= y) {
155
- this.setPixel(cx + x, cy + y, true);
156
- this.setPixel(cx + y, cy + x, true);
157
- this.setPixel(cx - y, cy + x, true);
158
- this.setPixel(cx - x, cy + y, true);
159
- this.setPixel(cx - x, cy - y, true);
160
- this.setPixel(cx - y, cy - x, true);
161
- this.setPixel(cx + y, cy - x, true);
162
- this.setPixel(cx + x, cy - y, true);
163
- y += 1;
164
- err += 1 + 2 * y;
165
- if (2 * (err - x) + 1 > 0) {
166
- x -= 1;
167
- err += 1 - 2 * x;
168
- }
169
- }
170
- }
171
- /**
172
- * Convert canvas to a single row of braille characters with colors
173
- * Returns an array of cells, one per braille character
174
- */
175
- toCells() {
176
- const result = [];
177
- for (let cy = 0; cy < this.charHeight; cy++) {
178
- const row = [];
179
- for (let cx = 0; cx < this.charWidth; cx++) {
180
- // Calculate braille character for this 2x4 cell
181
- let bits = 0;
182
- const px = cx * 2;
183
- const py = cy * 4;
184
- for (let dy = 0; dy < 4; dy++) {
185
- for (let dx = 0; dx < 2; dx++) {
186
- if (this.getPixel(px + dx, py + dy)) {
187
- bits |= DOT_BITS[dy][dx];
188
- }
189
- }
190
- }
191
- row.push({
192
- char: String.fromCharCode(BRAILLE_BASE + bits),
193
- color: this.colors[cy][cx],
194
- });
195
- }
196
- result.push(row);
197
- }
198
- return result;
199
- }
200
- /**
201
- * Render canvas to a string with ANSI colors
202
- */
203
- render() {
204
- const cells = this.toCells();
205
- const lines = [];
206
- for (const row of cells) {
207
- let line = '';
208
- for (const cell of row) {
209
- let colored = cell.char;
210
- if (cell.color.fg || cell.color.bg) {
211
- let colorFn = chalk;
212
- if (cell.color.fg) {
213
- if (cell.color.fg.startsWith('#')) {
214
- colorFn = colorFn.hex(cell.color.fg);
215
- }
216
- else {
217
- // Try to use named color
218
- const colorName = cell.color.fg;
219
- if (typeof chalk[colorName] === 'function') {
220
- colorFn = chalk[colorName];
221
- }
222
- }
223
- }
224
- if (cell.color.bg) {
225
- if (cell.color.bg.startsWith('#')) {
226
- colorFn = colorFn.bgHex(cell.color.bg);
227
- }
228
- else {
229
- // Try to use named background color
230
- const bgName = `bg${cell.color.bg.charAt(0).toUpperCase()}${cell.color.bg.slice(1)}`;
231
- if (typeof chalk[bgName] === 'function') {
232
- colorFn = chalk[bgName];
233
- }
234
- }
235
- }
236
- colored = colorFn(cell.char);
237
- }
238
- line += colored;
239
- }
240
- lines.push(line);
241
- }
242
- return lines.join('\n');
243
- }
244
- /**
245
- * Render to a single line (for single-row canvases)
246
- */
247
- renderLine() {
248
- const cells = this.toCells();
249
- if (cells.length === 0)
250
- return '';
251
- let line = '';
252
- for (const cell of cells[0]) {
253
- let colored = cell.char;
254
- if (cell.color.fg || cell.color.bg) {
255
- let colorFn = chalk;
256
- if (cell.color.fg) {
257
- if (cell.color.fg.startsWith('#')) {
258
- colorFn = colorFn.hex(cell.color.fg);
259
- }
260
- else {
261
- const colorName = cell.color.fg;
262
- if (typeof chalk[colorName] === 'function') {
263
- colorFn = chalk[colorName];
264
- }
265
- }
266
- }
267
- if (cell.color.bg) {
268
- if (cell.color.bg.startsWith('#')) {
269
- colorFn = colorFn.bgHex(cell.color.bg);
270
- }
271
- else {
272
- const bgName = `bg${cell.color.bg.charAt(0).toUpperCase()}${cell.color.bg.slice(1)}`;
273
- if (typeof chalk[bgName] === 'function') {
274
- colorFn = chalk[bgName];
275
- }
276
- }
277
- }
278
- colored = colorFn(cell.char);
279
- }
280
- line += colored;
281
- }
282
- return line;
283
- }
284
- /**
285
- * Get canvas dimensions
286
- */
287
- getWidth() {
288
- return this.width;
289
- }
290
- getHeight() {
291
- return this.height;
292
- }
293
- getCharWidth() {
294
- return this.charWidth;
295
- }
296
- getCharHeight() {
297
- return this.charHeight;
298
- }
299
- }
300
- /**
301
- * Create a simple braille character from an 8-bit pattern
302
- */
303
- export function brailleFromBits(bits) {
304
- return String.fromCharCode(BRAILLE_BASE + (bits & 0xff));
305
- }
306
- /**
307
- * Create a braille character from a 2x4 boolean array
308
- * array[y][x] where y is 0-3, x is 0-1
309
- */
310
- export function brailleFromArray(dots) {
311
- let bits = 0;
312
- for (let y = 0; y < 4 && y < dots.length; y++) {
313
- for (let x = 0; x < 2 && x < (dots[y]?.length || 0); x++) {
314
- if (dots[y][x]) {
315
- bits |= DOT_BITS[y][x];
316
- }
317
- }
318
- }
319
- return String.fromCharCode(BRAILLE_BASE + bits);
320
- }
321
- //# sourceMappingURL=braille-canvas.js.map
@@ -1,46 +0,0 @@
1
- // Copyright 2026 Guild.ai
2
- // SPDX-License-Identifier: Apache-2.0
3
- /**
4
- * Guild brand colors for CLI output
5
- */
6
- import chalk from 'chalk';
7
- /**
8
- * Brand accent color - muted cyan (complement of rust orange)
9
- * rgb(62, 166, 196) - visible on dark terminals while staying on-brand
10
- */
11
- // export const BRAND_COLOR = '#3ea6c4';
12
- export const BRAND_COLOR = '#c6541e';
13
- /**
14
- * Chalk instance for brand-colored text
15
- */
16
- export const brand = chalk.hex(BRAND_COLOR);
17
- /**
18
- * Warning/highlight color - readable on both light and dark terminals.
19
- * Replaces chalk.yellow which is invisible on light backgrounds.
20
- */
21
- export const warn = chalk.hex('#b8860b');
22
- /**
23
- * Inline code color - readable on both light and dark terminals.
24
- * Replaces chalk.yellow for code highlighting.
25
- */
26
- export const code = chalk.hex('#b8860b');
27
- /**
28
- * Wrap text in an OSC8 terminal hyperlink.
29
- *
30
- * In supported terminals (iTerm2, VS Code, Windows Terminal, etc.),
31
- * the text becomes clickable. Falls back to plain text when:
32
- * - Output is piped (non-TTY)
33
- * - FORCE_HYPERLINK=0
34
- *
35
- * Set FORCE_HYPERLINK=1 to force hyperlinks even in non-TTY.
36
- */
37
- export function hyperlink(text, url) {
38
- const force = process.env.FORCE_HYPERLINK;
39
- if (force === '0')
40
- return text;
41
- const supported = force === '1' || process.stderr.isTTY;
42
- if (!supported)
43
- return text;
44
- return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
45
- }
46
- //# sourceMappingURL=colors.js.map
@@ -1,45 +0,0 @@
1
- // Copyright 2026 Guild.ai
2
- // SPDX-License-Identifier: Apache-2.0
3
- /**
4
- * Synchronous config cache for early-init flags (debug, json, quiet).
5
- *
6
- * isDebugMode(), getOutputMode(), and isQuietMode() are sync functions
7
- * called before any async init can run. This module reads
8
- * ~/.guild/config.json synchronously and caches the result.
9
- *
10
- * Path logic is duplicated from guild-config.ts to avoid circular
11
- * imports (guild-config.ts → errors.ts → config-cache.ts → guild-config.ts).
12
- */
13
- import { readFileSync, existsSync } from 'fs';
14
- import path from 'path';
15
- import os from 'os';
16
- let cached = null;
17
- function loadSync() {
18
- if (cached !== null)
19
- return cached;
20
- const configPath = path.join(os.homedir(), '.guild', 'config.json');
21
- if (!existsSync(configPath)) {
22
- cached = {};
23
- return cached;
24
- }
25
- try {
26
- const content = readFileSync(configPath, 'utf-8');
27
- const parsed = JSON.parse(content);
28
- cached = {
29
- debug: parsed.debug === true,
30
- json: parsed.json === true,
31
- quiet: parsed.quiet === true,
32
- };
33
- }
34
- catch {
35
- cached = {};
36
- }
37
- return cached;
38
- }
39
- /**
40
- * Get a boolean config flag from ~/.guild/config.json (sync, cached).
41
- */
42
- export function getConfigFlag(key) {
43
- return loadSync()[key] === true;
44
- }
45
- //# sourceMappingURL=config-cache.js.map