@agentuity/cli 2.0.5 → 2.0.7

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 (128) hide show
  1. package/README.md +11 -0
  2. package/dist/cmd/build/patch/otel-llm.js +2 -2
  3. package/dist/cmd/build/patch/otel-llm.js.map +1 -1
  4. package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
  5. package/dist/cmd/build/vite/bun-dev-server.js +1 -0
  6. package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
  7. package/dist/cmd/build/vite/index.d.ts +0 -28
  8. package/dist/cmd/build/vite/index.d.ts.map +1 -1
  9. package/dist/cmd/build/vite/index.js +1 -104
  10. package/dist/cmd/build/vite/index.js.map +1 -1
  11. package/dist/cmd/build/vite/metadata-generator.d.ts.map +1 -1
  12. package/dist/cmd/build/vite/metadata-generator.js +8 -2
  13. package/dist/cmd/build/vite/metadata-generator.js.map +1 -1
  14. package/dist/cmd/build/vite/vite-asset-server-config.d.ts +2 -0
  15. package/dist/cmd/build/vite/vite-asset-server-config.d.ts.map +1 -1
  16. package/dist/cmd/build/vite/vite-asset-server-config.js +5 -1
  17. package/dist/cmd/build/vite/vite-asset-server-config.js.map +1 -1
  18. package/dist/cmd/build/vite/vite-asset-server.d.ts +2 -0
  19. package/dist/cmd/build/vite/vite-asset-server.d.ts.map +1 -1
  20. package/dist/cmd/build/vite/vite-asset-server.js +2 -1
  21. package/dist/cmd/build/vite/vite-asset-server.js.map +1 -1
  22. package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
  23. package/dist/cmd/build/vite/vite-builder.js +143 -2
  24. package/dist/cmd/build/vite/vite-builder.js.map +1 -1
  25. package/dist/cmd/cloud/task/close.d.ts +3 -0
  26. package/dist/cmd/cloud/task/close.d.ts.map +1 -0
  27. package/dist/cmd/cloud/task/close.js +286 -0
  28. package/dist/cmd/cloud/task/close.js.map +1 -0
  29. package/dist/cmd/cloud/task/delete.d.ts +1 -5
  30. package/dist/cmd/cloud/task/delete.d.ts.map +1 -1
  31. package/dist/cmd/cloud/task/delete.js +15 -38
  32. package/dist/cmd/cloud/task/delete.js.map +1 -1
  33. package/dist/cmd/cloud/task/index.d.ts.map +1 -1
  34. package/dist/cmd/cloud/task/index.js +10 -0
  35. package/dist/cmd/cloud/task/index.js.map +1 -1
  36. package/dist/cmd/cloud/task/list.d.ts.map +1 -1
  37. package/dist/cmd/cloud/task/list.js +97 -3
  38. package/dist/cmd/cloud/task/list.js.map +1 -1
  39. package/dist/cmd/cloud/task/util.d.ts +10 -0
  40. package/dist/cmd/cloud/task/util.d.ts.map +1 -1
  41. package/dist/cmd/cloud/task/util.js +47 -3
  42. package/dist/cmd/cloud/task/util.js.map +1 -1
  43. package/dist/cmd/coder/config/index.d.ts +2 -0
  44. package/dist/cmd/coder/config/index.d.ts.map +1 -0
  45. package/dist/cmd/coder/config/index.js +20 -0
  46. package/dist/cmd/coder/config/index.js.map +1 -0
  47. package/dist/cmd/coder/config/set.d.ts +2 -0
  48. package/dist/cmd/coder/config/set.d.ts.map +1 -0
  49. package/dist/cmd/coder/config/set.js +100 -0
  50. package/dist/cmd/coder/config/set.js.map +1 -0
  51. package/dist/cmd/coder/hub-url.d.ts +21 -10
  52. package/dist/cmd/coder/hub-url.d.ts.map +1 -1
  53. package/dist/cmd/coder/hub-url.js +97 -55
  54. package/dist/cmd/coder/hub-url.js.map +1 -1
  55. package/dist/cmd/coder/index.d.ts.map +1 -1
  56. package/dist/cmd/coder/index.js +6 -1
  57. package/dist/cmd/coder/index.js.map +1 -1
  58. package/dist/cmd/coder/inspect.d.ts.map +1 -1
  59. package/dist/cmd/coder/inspect.js +15 -7
  60. package/dist/cmd/coder/inspect.js.map +1 -1
  61. package/dist/cmd/coder/list.d.ts.map +1 -1
  62. package/dist/cmd/coder/list.js +14 -7
  63. package/dist/cmd/coder/list.js.map +1 -1
  64. package/dist/cmd/coder/start.d.ts.map +1 -1
  65. package/dist/cmd/coder/start.js +38 -23
  66. package/dist/cmd/coder/start.js.map +1 -1
  67. package/dist/cmd/coder/tui-init.d.ts +4 -1
  68. package/dist/cmd/coder/tui-init.d.ts.map +1 -1
  69. package/dist/cmd/coder/tui-init.js +3 -2
  70. package/dist/cmd/coder/tui-init.js.map +1 -1
  71. package/dist/cmd/dev/index.d.ts.map +1 -1
  72. package/dist/cmd/dev/index.js +1 -0
  73. package/dist/cmd/dev/index.js.map +1 -1
  74. package/dist/cmd/dev/sync.js +5 -5
  75. package/dist/cmd/dev/sync.js.map +1 -1
  76. package/dist/coder-config.d.ts +14 -0
  77. package/dist/coder-config.d.ts.map +1 -0
  78. package/dist/coder-config.js +119 -0
  79. package/dist/coder-config.js.map +1 -0
  80. package/dist/coder-hub-url.d.ts +3 -0
  81. package/dist/coder-hub-url.d.ts.map +1 -0
  82. package/dist/coder-hub-url.js +32 -0
  83. package/dist/coder-hub-url.js.map +1 -0
  84. package/dist/config.d.ts +1 -0
  85. package/dist/config.d.ts.map +1 -1
  86. package/dist/config.js +11 -0
  87. package/dist/config.js.map +1 -1
  88. package/dist/internal-logger.d.ts +4 -0
  89. package/dist/internal-logger.d.ts.map +1 -1
  90. package/dist/internal-logger.js +64 -2
  91. package/dist/internal-logger.js.map +1 -1
  92. package/dist/keychain.d.ts +3 -0
  93. package/dist/keychain.d.ts.map +1 -1
  94. package/dist/keychain.js +47 -28
  95. package/dist/keychain.js.map +1 -1
  96. package/dist/types.d.ts +4 -0
  97. package/dist/types.d.ts.map +1 -1
  98. package/dist/types.js +10 -0
  99. package/dist/types.js.map +1 -1
  100. package/package.json +6 -6
  101. package/src/cmd/build/patch/otel-llm.ts +2 -2
  102. package/src/cmd/build/vite/bun-dev-server.ts +1 -0
  103. package/src/cmd/build/vite/index.ts +1 -148
  104. package/src/cmd/build/vite/metadata-generator.ts +8 -2
  105. package/src/cmd/build/vite/vite-asset-server-config.ts +16 -1
  106. package/src/cmd/build/vite/vite-asset-server.ts +4 -0
  107. package/src/cmd/build/vite/vite-builder.ts +171 -9
  108. package/src/cmd/cloud/task/close.ts +319 -0
  109. package/src/cmd/cloud/task/delete.ts +15 -43
  110. package/src/cmd/cloud/task/index.ts +10 -0
  111. package/src/cmd/cloud/task/list.ts +111 -4
  112. package/src/cmd/cloud/task/util.ts +59 -5
  113. package/src/cmd/coder/config/index.ts +20 -0
  114. package/src/cmd/coder/config/set.ts +112 -0
  115. package/src/cmd/coder/hub-url.ts +147 -53
  116. package/src/cmd/coder/index.ts +6 -1
  117. package/src/cmd/coder/inspect.ts +33 -10
  118. package/src/cmd/coder/list.ts +33 -10
  119. package/src/cmd/coder/start.ts +62 -26
  120. package/src/cmd/coder/tui-init.ts +7 -2
  121. package/src/cmd/dev/index.ts +1 -0
  122. package/src/cmd/dev/sync.ts +5 -5
  123. package/src/coder-config.ts +141 -0
  124. package/src/coder-hub-url.ts +32 -0
  125. package/src/config.ts +13 -0
  126. package/src/internal-logger.ts +83 -2
  127. package/src/keychain.ts +68 -39
  128. package/src/types.ts +10 -0
@@ -43,6 +43,16 @@ const SENSITIVE_ENV_PATTERNS = [
43
43
  /AUTH/i,
44
44
  ];
45
45
 
46
+ const MASKED_ARG_VALUE = '***MASKED***';
47
+ const SENSITIVE_ARG_PATTERNS = [
48
+ /^--?api[-_]?key$/i,
49
+ /^--?token$/i,
50
+ /^--?secret$/i,
51
+ /^--?password$/i,
52
+ /^--?client[-_]?secret$/i,
53
+ /^--?auth[-_]?value$/i,
54
+ ];
55
+
46
56
  interface SessionMetadata {
47
57
  sessionId: string;
48
58
  bucket: number;
@@ -102,6 +112,75 @@ function maskEnvironment(): Record<string, string> {
102
112
  return masked;
103
113
  }
104
114
 
115
+ function isSensitiveArgFlag(arg: string): boolean {
116
+ return SENSITIVE_ARG_PATTERNS.some((pattern) => pattern.test(arg));
117
+ }
118
+
119
+ function sanitizeArgsForLogging(args: string[]): string[] {
120
+ const sanitized: string[] = [];
121
+ let maskNextValue = false;
122
+
123
+ for (let i = 0; i < args.length; i += 1) {
124
+ const arg = args[i]!;
125
+
126
+ if (maskNextValue) {
127
+ if (!arg.startsWith('-')) {
128
+ sanitized.push(MASKED_ARG_VALUE);
129
+ maskNextValue = false;
130
+ continue;
131
+ }
132
+
133
+ sanitized.push(MASKED_ARG_VALUE);
134
+ maskNextValue = false;
135
+ i -= 1;
136
+ continue;
137
+ }
138
+
139
+ if (!arg.startsWith('-')) {
140
+ sanitized.push(arg);
141
+ continue;
142
+ }
143
+
144
+ const equalsIndex = arg.indexOf('=');
145
+ if (equalsIndex > 0) {
146
+ const flag = arg.slice(0, equalsIndex);
147
+ if (isSensitiveArgFlag(flag)) {
148
+ sanitized.push(`${flag}=${MASKED_ARG_VALUE}`);
149
+ continue;
150
+ }
151
+ }
152
+
153
+ sanitized.push(arg);
154
+ if (isSensitiveArgFlag(arg)) {
155
+ maskNextValue = true;
156
+ }
157
+ }
158
+
159
+ return sanitized;
160
+ }
161
+
162
+ export function sanitizeCliCommandForLogging(
163
+ command: string,
164
+ args: string[]
165
+ ): { command: string; args: string[] } {
166
+ const commandTokens = command ? command.split(' ') : [];
167
+
168
+ if (
169
+ commandTokens.length >= 5 &&
170
+ commandTokens[0] === 'coder' &&
171
+ commandTokens[1] === 'config' &&
172
+ commandTokens[2] === 'set' &&
173
+ commandTokens[3] === 'apikey'
174
+ ) {
175
+ commandTokens[4] = MASKED_ARG_VALUE;
176
+ }
177
+
178
+ return {
179
+ command: commandTokens.join(' '),
180
+ args: sanitizeArgsForLogging(args),
181
+ };
182
+ }
183
+
105
184
  /**
106
185
  * Get the logs directory path
107
186
  */
@@ -266,14 +345,16 @@ export class InternalLogger implements Logger {
266
345
  // Use workingDir as cwd in session metadata
267
346
  const cwd = workingDir;
268
347
 
348
+ const sanitizedInvocation = sanitizeCliCommandForLogging(command, args);
349
+
269
350
  // Gather session metadata
270
351
  const sessionMetadata: SessionMetadata = {
271
352
  sessionId: this.sessionId,
272
353
  bucket: this.bucket,
273
354
  pid: process.pid,
274
355
  ppid: process.ppid,
275
- command,
276
- args,
356
+ command: sanitizedInvocation.command,
357
+ args: sanitizedInvocation.args,
277
358
  timestamp: new Date().toISOString(),
278
359
  cli: {
279
360
  version: this.cliVersion,
package/src/keychain.ts CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  const SERVICE_PREFIX = 'com.agentuity.cli';
9
9
  const KEY_ACCOUNT = 'aes-encryption-key';
10
+ const AUTH_ACCOUNT = 'auth-token';
11
+ const CODER_API_KEY_ACCOUNT = 'coder-hub-api-key';
10
12
 
11
13
  /**
12
14
  * Check if we're running on macOS
@@ -88,26 +90,15 @@ async function decrypt(combined: Uint8Array, keyBytes: Uint8Array): Promise<stri
88
90
  return new TextDecoder().decode(plaintext);
89
91
  }
90
92
 
91
- /**
92
- * Store auth data in macOS Keychain
93
- */
94
- export async function saveAuthToKeychain(
95
- profileName: string,
96
- authData: { api_key: string; user_id: string; expires: number }
93
+ async function saveEncryptedValueToKeychain(
94
+ service: string,
95
+ account: string,
96
+ value: string
97
97
  ): Promise<void> {
98
- const service = `${SERVICE_PREFIX}.${profileName}`;
99
- const account = 'auth-token';
100
-
101
- // Get or create encryption key
102
98
  const key = await ensureEncryptionKey(service);
103
-
104
- // Encrypt the auth data
105
- const json = JSON.stringify(authData);
106
- const encrypted = await encrypt(json, key);
99
+ const encrypted = await encrypt(value, key);
107
100
  const b64 = Buffer.from(encrypted).toString('base64');
108
101
 
109
- // Store encrypted auth in keychain
110
- // First try to delete if exists, then add
111
102
  const del = Bun.spawn(['security', 'delete-generic-password', '-s', service, '-a', account], {
112
103
  stderr: 'ignore',
113
104
  });
@@ -127,6 +118,43 @@ export async function saveAuthToKeychain(
127
118
  await add.exited;
128
119
  }
129
120
 
121
+ async function getEncryptedValueFromKeychain(
122
+ service: string,
123
+ account: string
124
+ ): Promise<string | null> {
125
+ const find = Bun.spawn(
126
+ ['security', 'find-generic-password', '-s', service, '-a', account, '-w'],
127
+ { stderr: 'ignore' }
128
+ );
129
+
130
+ const stdout = await new Response(find.stdout).text();
131
+ if (stdout.length === 0) {
132
+ return null;
133
+ }
134
+
135
+ const encrypted = Uint8Array.from(Buffer.from(stdout.trim(), 'base64'));
136
+ const key = await ensureEncryptionKey(service);
137
+ return decrypt(encrypted, key);
138
+ }
139
+
140
+ async function deleteValueFromKeychain(service: string, account: string): Promise<void> {
141
+ const del = Bun.spawn(['security', 'delete-generic-password', '-s', service, '-a', account], {
142
+ stderr: 'ignore',
143
+ });
144
+ await del.exited;
145
+ }
146
+
147
+ /**
148
+ * Store auth data in macOS Keychain
149
+ */
150
+ export async function saveAuthToKeychain(
151
+ profileName: string,
152
+ authData: { api_key: string; user_id: string; expires: number }
153
+ ): Promise<void> {
154
+ const service = `${SERVICE_PREFIX}.${profileName}`;
155
+ await saveEncryptedValueToKeychain(service, AUTH_ACCOUNT, JSON.stringify(authData));
156
+ }
157
+
130
158
  /**
131
159
  * Retrieve auth data from macOS Keychain
132
160
  */
@@ -134,28 +162,12 @@ export async function getAuthFromKeychain(
134
162
  profileName: string
135
163
  ): Promise<{ api_key: string; user_id: string; expires: number } | null> {
136
164
  const service = `${SERVICE_PREFIX}.${profileName}`;
137
- const account = 'auth-token';
138
165
 
139
166
  try {
140
- // Get the encrypted auth data
141
- const find = Bun.spawn(
142
- ['security', 'find-generic-password', '-s', service, '-a', account, '-w'],
143
- { stderr: 'ignore' }
144
- );
145
-
146
- const stdout = await new Response(find.stdout).text();
147
- if (stdout.length === 0) {
167
+ const json = await getEncryptedValueFromKeychain(service, AUTH_ACCOUNT);
168
+ if (!json) {
148
169
  return null;
149
170
  }
150
-
151
- const b64 = stdout.trim();
152
- const encrypted = Uint8Array.from(Buffer.from(b64, 'base64'));
153
-
154
- // Get the encryption key
155
- const key = await ensureEncryptionKey(service);
156
-
157
- // Decrypt the auth data
158
- const json = await decrypt(encrypted, key);
159
171
  return JSON.parse(json);
160
172
  } catch {
161
173
  return null;
@@ -167,10 +179,27 @@ export async function getAuthFromKeychain(
167
179
  */
168
180
  export async function deleteAuthFromKeychain(profileName: string): Promise<void> {
169
181
  const service = `${SERVICE_PREFIX}.${profileName}`;
170
- const account = 'auth-token';
182
+ await deleteValueFromKeychain(service, AUTH_ACCOUNT);
183
+ }
171
184
 
172
- const del = Bun.spawn(['security', 'delete-generic-password', '-s', service, '-a', account], {
173
- stderr: 'ignore',
174
- });
175
- await del.exited;
185
+ export async function saveCoderApiKeyToKeychain(
186
+ profileName: string,
187
+ apiKey: string
188
+ ): Promise<void> {
189
+ const service = `${SERVICE_PREFIX}.${profileName}`;
190
+ await saveEncryptedValueToKeychain(service, CODER_API_KEY_ACCOUNT, apiKey);
191
+ }
192
+
193
+ export async function getCoderApiKeyFromKeychain(profileName: string): Promise<string | null> {
194
+ const service = `${SERVICE_PREFIX}.${profileName}`;
195
+ try {
196
+ return await getEncryptedValueFromKeychain(service, CODER_API_KEY_ACCOUNT);
197
+ } catch {
198
+ return null;
199
+ }
200
+ }
201
+
202
+ export async function deleteCoderApiKeyFromKeychain(profileName: string): Promise<void> {
203
+ const service = `${SERVICE_PREFIX}.${profileName}`;
204
+ await deleteValueFromKeychain(service, CODER_API_KEY_ACCOUNT);
176
205
  }
package/src/types.ts CHANGED
@@ -61,6 +61,16 @@ export const ConfigSchema = zod.object({
61
61
  })
62
62
  .optional()
63
63
  .describe('User preferences'),
64
+ coder: zod
65
+ .object({
66
+ hubUrl: zod.string().optional().describe('Default Coder Hub URL'),
67
+ apiKey: zod
68
+ .string()
69
+ .optional()
70
+ .describe('Stored Coder Hub API key when secure keychain storage is unavailable'),
71
+ })
72
+ .optional()
73
+ .describe('Coder Hub configuration managed by coder config commands'),
64
74
  gravity: zod
65
75
  .object({
66
76
  version: zod.string().optional().describe('The current gravity version'),