@agentuity/cli 0.1.37 → 0.1.39

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 (89) hide show
  1. package/bin/cli.ts +31 -9
  2. package/dist/agent-detection.d.ts +71 -0
  3. package/dist/agent-detection.d.ts.map +1 -0
  4. package/dist/agent-detection.js +232 -0
  5. package/dist/agent-detection.js.map +1 -0
  6. package/dist/cache/index.d.ts +1 -0
  7. package/dist/cache/index.d.ts.map +1 -1
  8. package/dist/cache/index.js +1 -0
  9. package/dist/cache/index.js.map +1 -1
  10. package/dist/cache/project-cache.d.ts +16 -0
  11. package/dist/cache/project-cache.d.ts.map +1 -0
  12. package/dist/cache/project-cache.js +36 -0
  13. package/dist/cache/project-cache.js.map +1 -0
  14. package/dist/cli.d.ts.map +1 -1
  15. package/dist/cli.js +10 -2
  16. package/dist/cli.js.map +1 -1
  17. package/dist/cmd/auth/index.d.ts.map +1 -1
  18. package/dist/cmd/auth/index.js +0 -2
  19. package/dist/cmd/auth/index.js.map +1 -1
  20. package/dist/cmd/auth/org/enroll.d.ts +2 -0
  21. package/dist/cmd/auth/org/enroll.d.ts.map +1 -0
  22. package/dist/cmd/auth/{machine/setup.js → org/enroll.js} +14 -14
  23. package/dist/cmd/auth/org/enroll.js.map +1 -0
  24. package/dist/cmd/auth/org/index.d.ts.map +1 -1
  25. package/dist/cmd/auth/org/index.js +53 -10
  26. package/dist/cmd/auth/org/index.js.map +1 -1
  27. package/dist/cmd/auth/org/status.d.ts +2 -0
  28. package/dist/cmd/auth/org/status.d.ts.map +1 -0
  29. package/dist/cmd/auth/org/status.js +60 -0
  30. package/dist/cmd/auth/org/status.js.map +1 -0
  31. package/dist/cmd/auth/org/unenroll.d.ts +2 -0
  32. package/dist/cmd/auth/org/unenroll.d.ts.map +1 -0
  33. package/dist/cmd/auth/org/unenroll.js +68 -0
  34. package/dist/cmd/auth/org/unenroll.js.map +1 -0
  35. package/dist/cmd/build/vite/registry-generator.d.ts.map +1 -1
  36. package/dist/cmd/build/vite/registry-generator.js +24 -3
  37. package/dist/cmd/build/vite/registry-generator.js.map +1 -1
  38. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  39. package/dist/cmd/cloud/deploy.js +11 -4
  40. package/dist/cmd/cloud/deploy.js.map +1 -1
  41. package/dist/cmd/dev/templates.d.ts.map +1 -1
  42. package/dist/cmd/dev/templates.js +1 -4
  43. package/dist/cmd/dev/templates.js.map +1 -1
  44. package/dist/cmd/project/reconcile.d.ts.map +1 -1
  45. package/dist/cmd/project/reconcile.js +15 -2
  46. package/dist/cmd/project/reconcile.js.map +1 -1
  47. package/dist/cmd/support/report.d.ts.map +1 -1
  48. package/dist/cmd/support/report.js.map +1 -1
  49. package/dist/cmd/support/system.d.ts.map +1 -1
  50. package/dist/cmd/support/system.js +5 -0
  51. package/dist/cmd/support/system.js.map +1 -1
  52. package/dist/internal-logger.d.ts +4 -0
  53. package/dist/internal-logger.d.ts.map +1 -1
  54. package/dist/internal-logger.js +18 -0
  55. package/dist/internal-logger.js.map +1 -1
  56. package/dist/types.d.ts +13 -0
  57. package/dist/types.d.ts.map +1 -1
  58. package/dist/types.js.map +1 -1
  59. package/package.json +6 -6
  60. package/src/agent-detection.ts +262 -0
  61. package/src/cache/index.ts +2 -0
  62. package/src/cache/project-cache.ts +41 -0
  63. package/src/cli.ts +10 -2
  64. package/src/cmd/auth/index.ts +0 -2
  65. package/src/cmd/auth/{machine/setup.ts → org/enroll.ts} +13 -13
  66. package/src/cmd/auth/org/index.ts +54 -10
  67. package/src/cmd/auth/org/status.ts +64 -0
  68. package/src/cmd/auth/org/unenroll.ts +80 -0
  69. package/src/cmd/build/vite/registry-generator.ts +24 -3
  70. package/src/cmd/cloud/deploy.ts +11 -4
  71. package/src/cmd/dev/templates.ts +1 -5
  72. package/src/cmd/project/reconcile.ts +15 -2
  73. package/src/cmd/support/report.ts +1 -3
  74. package/src/cmd/support/system.ts +6 -0
  75. package/src/internal-logger.ts +18 -0
  76. package/src/types.ts +13 -0
  77. package/dist/cmd/auth/machine/index.d.ts +0 -2
  78. package/dist/cmd/auth/machine/index.d.ts.map +0 -1
  79. package/dist/cmd/auth/machine/index.js +0 -16
  80. package/dist/cmd/auth/machine/index.js.map +0 -1
  81. package/dist/cmd/auth/machine/setup.d.ts +0 -2
  82. package/dist/cmd/auth/machine/setup.d.ts.map +0 -1
  83. package/dist/cmd/auth/machine/setup.js.map +0 -1
  84. package/dist/legacy-check.d.ts +0 -6
  85. package/dist/legacy-check.d.ts.map +0 -1
  86. package/dist/legacy-check.js +0 -112
  87. package/dist/legacy-check.js.map +0 -1
  88. package/src/cmd/auth/machine/index.ts +0 -16
  89. package/src/legacy-check.ts +0 -137
package/bin/cli.ts CHANGED
@@ -1,4 +1,13 @@
1
1
  #!/usr/bin/env bun
2
+
3
+ // Fast-path for version command - check before loading heavy modules
4
+ const versionArgs = process.argv.slice(2);
5
+ if (versionArgs.length === 1 && ['version', '-v', '--version', '-V'].includes(versionArgs[0])) {
6
+ const { getVersion } = await import('../src/version');
7
+ console.log(getVersion());
8
+ process.exit(0);
9
+ }
10
+
2
11
  import { ConsoleLogger } from '@agentuity/server';
3
12
  import { isStructuredError } from '@agentuity/core';
4
13
  import { createCLI, registerCommands } from '../src/cli';
@@ -8,7 +17,7 @@ import { discoverCommands } from '../src/cmd';
8
17
  import { detectColorScheme } from '../src/terminal';
9
18
  import { setColorScheme } from '../src/tui';
10
19
  import { getVersion, getPackageName } from '../src/version';
11
- import { checkLegacyCLI } from '../src/legacy-check';
20
+
12
21
  import type { CommandContext, LogLevel } from '../src/types';
13
22
  import { generateCLISchema } from '../src/schema-generator';
14
23
  import { setOutputOptions } from '../src/output';
@@ -19,6 +28,12 @@ import { closeDatabase } from '../src/cache';
19
28
  import { createInternalLogger } from '../src/internal-logger';
20
29
  import { createCompositeLogger } from '../src/composite-logger';
21
30
  import { getAuth } from '../src/config';
31
+ import {
32
+ startAgentDetection,
33
+ isExecutingFromAgent,
34
+ onAgentDetected,
35
+ flushAgentDetection,
36
+ } from '../src/agent-detection';
22
37
 
23
38
  /**
24
39
  * Extract --dir flag from process.argv before command parsing
@@ -80,6 +95,10 @@ process.on('SIGTERM', () => {
80
95
  validateRuntime();
81
96
  await ensureBunOnPath();
82
97
 
98
+ // Start agent detection early (non-blocking) so it runs in the background
99
+ // while the rest of CLI initialization happens
100
+ startAgentDetection();
101
+
83
102
  // Preprocess arguments to convert --help=json to --help json
84
103
  // Commander.js doesn't support --option=value syntax for optional values
85
104
  const preprocessedArgs = process.argv.slice(2).flatMap((arg) => {
@@ -113,14 +132,7 @@ if (
113
132
  exit(0);
114
133
  }
115
134
 
116
- // Check for legacy CLI and warn user (skip via flag or env var)
117
- // Env var is preferred for programmatic use (e.g., test runners) since Commander.js
118
- // would fail on unknown CLI flags
119
- const skipLegacyCheck =
120
- process.argv.includes('--skip-legacy-check') || process.env.AGENTUITY_SKIP_LEGACY_CHECK === '1';
121
- if (!skipLegacyCheck) {
122
- await checkLegacyCLI();
123
- }
135
+
124
136
 
125
137
  const version = getVersion();
126
138
  const program = await createCLI(version);
@@ -217,6 +229,13 @@ if (shouldSkipInternalLogging) {
217
229
 
218
230
  // Set session ID in environment so forked child processes can share the same log file
219
231
  process.env.AGENTUITY_INTERNAL_SESSION_ID = internalLogger.getSessionId();
232
+
233
+ // Register callback to update session with detected agent (non-blocking)
234
+ onAgentDetected((agent) => {
235
+ if (agent) {
236
+ internalLogger.setDetectedAgent(agent);
237
+ }
238
+ });
220
239
  }
221
240
 
222
241
  // Create composite logger that writes to both console and internal log
@@ -243,6 +262,7 @@ const ctx = {
243
262
  config,
244
263
  logger,
245
264
  options: earlyOpts,
265
+ isExecutingFromAgent,
246
266
  };
247
267
 
248
268
  // Set global output options for utilities to use
@@ -275,6 +295,8 @@ await registerCommands(program, commands, ctx as unknown as CommandContext);
275
295
 
276
296
  try {
277
297
  await program.parseAsync(process.argv);
298
+ // Flush agent detection to ensure it's written to session logs before exit
299
+ await flushAgentDetection();
278
300
  } catch (error) {
279
301
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
280
302
  const exit = (globalThis as any).AGENTUITY_PROCESS_EXIT || process.exit;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Map of process names to internal agent short names.
3
+ * The key is the process name (or substring) that appears in the parent process command line.
4
+ * The value is the internal short name used to identify the agent.
5
+ *
6
+ * Process names verified via `agentuity cloud sandbox run --runtime <agent>:latest`:
7
+ * - opencode: binary 'opencode' (from bun install -g opencode-ai)
8
+ * - codex: binary 'codex' (from npm install -g @openai/codex)
9
+ * - cursor: binary 'cursor-agent' (from curl installer)
10
+ * - claude-code: binary 'claude', shows as 'node /usr/local/bin/claude'
11
+ * - copilot: binary 'copilot', shows as 'node /usr/local/bin/copilot' and spawns native binary
12
+ * - gemini: binary 'gemini', shows as 'node /usr/local/bin/gemini'
13
+ * - amp: binary 'amp', shows as 'node --no-warnings /usr/local/bin/amp'
14
+ *
15
+ * IMPORTANT: Order matters! More specific patterns should come before less specific ones.
16
+ * For example, 'opencode' must be checked before 'code' to avoid false matches.
17
+ */
18
+ export declare const KNOWN_AGENTS: [string, string][];
19
+ export type KnownAgent = (typeof KNOWN_AGENTS)[number][1];
20
+ /**
21
+ * Start agent detection immediately (non-blocking).
22
+ * Call this early in CLI startup to begin detection in the background.
23
+ */
24
+ export declare function startAgentDetection(): void;
25
+ /**
26
+ * Register a callback to be invoked when agent detection completes.
27
+ * If detection has already completed, the callback is invoked immediately.
28
+ * This is non-blocking and does not return a promise.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * onAgentDetected((agent) => {
33
+ * if (agent) {
34
+ * console.log(`Detected agent: ${agent}`);
35
+ * }
36
+ * });
37
+ * ```
38
+ */
39
+ export declare function onAgentDetected(callback: (agent: string | undefined) => void): void;
40
+ /**
41
+ * Get the cached detection result synchronously.
42
+ * Returns undefined if detection hasn't completed yet or no agent was detected.
43
+ * Returns null if detection hasn't started or completed yet.
44
+ *
45
+ * Use this for synchronous access when you don't want to wait for detection.
46
+ */
47
+ export declare function getDetectedAgent(): string | undefined | null;
48
+ /**
49
+ * Wait for agent detection to complete and ensure all callbacks have been invoked.
50
+ * Call this before CLI exit to ensure the detected agent is written to session logs.
51
+ *
52
+ * This is a no-op if detection hasn't started or has already completed.
53
+ */
54
+ export declare function flushAgentDetection(): Promise<void>;
55
+ /**
56
+ * Check if the CLI is being executed from a known coding agent.
57
+ * Returns the agent name if detected, undefined otherwise.
58
+ *
59
+ * This function returns immediately if detection has already completed,
60
+ * otherwise it awaits the detection promise started by startAgentDetection().
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * const agent = await isExecutingFromAgent();
65
+ * if (agent) {
66
+ * logger.debug(`Running from agent: ${agent}`);
67
+ * }
68
+ * ```
69
+ */
70
+ export declare function isExecutingFromAgent(): Promise<string | undefined>;
71
+ //# sourceMappingURL=agent-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detection.d.ts","sourceRoot":"","sources":["../src/agent-detection.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAgB1C,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAwH1D;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAkB1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,GAAG,IAAI,CAanF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,GAAG,IAAI,CAE5D;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAaxE"}
@@ -0,0 +1,232 @@
1
+ import { spawn } from 'node:child_process';
2
+ /**
3
+ * Map of process names to internal agent short names.
4
+ * The key is the process name (or substring) that appears in the parent process command line.
5
+ * The value is the internal short name used to identify the agent.
6
+ *
7
+ * Process names verified via `agentuity cloud sandbox run --runtime <agent>:latest`:
8
+ * - opencode: binary 'opencode' (from bun install -g opencode-ai)
9
+ * - codex: binary 'codex' (from npm install -g @openai/codex)
10
+ * - cursor: binary 'cursor-agent' (from curl installer)
11
+ * - claude-code: binary 'claude', shows as 'node /usr/local/bin/claude'
12
+ * - copilot: binary 'copilot', shows as 'node /usr/local/bin/copilot' and spawns native binary
13
+ * - gemini: binary 'gemini', shows as 'node /usr/local/bin/gemini'
14
+ * - amp: binary 'amp', shows as 'node --no-warnings /usr/local/bin/amp'
15
+ *
16
+ * IMPORTANT: Order matters! More specific patterns should come before less specific ones.
17
+ * For example, 'opencode' must be checked before 'code' to avoid false matches.
18
+ */
19
+ export const KNOWN_AGENTS = [
20
+ // Verified via cloud sandbox runtime - most specific patterns first
21
+ ['opencode', 'opencode'],
22
+ ['codex', 'codex'],
23
+ ['cursor-agent', 'cursor'],
24
+ ['claude', 'claude-code'],
25
+ ['copilot', 'copilot'],
26
+ ['gemini', 'gemini'],
27
+ ['cline', 'cline'],
28
+ ['roo-code', 'roo'],
29
+ ['windsurf', 'windsurf'],
30
+ ['zed', 'zed'],
31
+ ['amp', 'amp'],
32
+ // TODO: VSCode Agent Mode detection - need to find a reliable way to detect
33
+ // when VSCode's built-in agent (Copilot Chat) is running commands vs just
34
+ // running in VSCode's integrated terminal. May need env var detection.
35
+ ];
36
+ /**
37
+ * Promise for the detection result (set when detection starts)
38
+ */
39
+ let detectionPromise = null;
40
+ /**
41
+ * Cached result after detection completes (null = not yet resolved)
42
+ */
43
+ let cachedResult = null;
44
+ /**
45
+ * Callbacks to invoke when agent detection completes
46
+ */
47
+ const detectionCallbacks = [];
48
+ /**
49
+ * Get the command line and parent PID for a given PID in a single ps call
50
+ */
51
+ function getProcessInfo(pid) {
52
+ return new Promise((resolve) => {
53
+ const ps = spawn('ps', ['-p', String(pid), '-o', 'ppid=,command='], {
54
+ stdio: ['ignore', 'pipe', 'ignore'],
55
+ });
56
+ let output = '';
57
+ ps.stdout.on('data', (data) => {
58
+ output += data.toString();
59
+ });
60
+ ps.on('close', () => {
61
+ const trimmed = output.trim();
62
+ if (!trimmed) {
63
+ resolve(undefined);
64
+ return;
65
+ }
66
+ // Output format: " PPID COMMAND" (ppid is right-aligned, then space, then command)
67
+ const match = trimmed.match(/^\s*(\d+)\s+(.+)$/);
68
+ if (!match) {
69
+ resolve(undefined);
70
+ return;
71
+ }
72
+ const ppid = parseInt(match[1], 10);
73
+ const command = match[2].toLowerCase();
74
+ if (isNaN(ppid) || ppid <= 1 || !command) {
75
+ resolve(undefined);
76
+ return;
77
+ }
78
+ resolve({ command, ppid });
79
+ });
80
+ ps.on('error', () => {
81
+ resolve(undefined);
82
+ });
83
+ });
84
+ }
85
+ /**
86
+ * Check if a command matches any known agent
87
+ */
88
+ function matchAgent(command) {
89
+ for (const [processName, agentName] of KNOWN_AGENTS) {
90
+ if (command.includes(processName)) {
91
+ return agentName;
92
+ }
93
+ }
94
+ return undefined;
95
+ }
96
+ /**
97
+ * Detect the parent process command and check if it matches a known agent.
98
+ * Walks up the process tree to find the first matching agent.
99
+ */
100
+ function detectParentAgent() {
101
+ return new Promise((resolve) => {
102
+ // TODO: Implement Windows support using wmic or PowerShell
103
+ if (process.platform === 'win32') {
104
+ resolve(undefined);
105
+ return;
106
+ }
107
+ const maxDepth = 10; // Limit how far up we walk the tree
108
+ async function walkTree(pid, depth) {
109
+ if (depth >= maxDepth || pid <= 1) {
110
+ return undefined;
111
+ }
112
+ // Get both command and parent PID in a single ps call
113
+ const info = await getProcessInfo(pid);
114
+ if (!info) {
115
+ return undefined;
116
+ }
117
+ // Check if this process matches a known agent
118
+ const agent = matchAgent(info.command);
119
+ if (agent) {
120
+ return agent;
121
+ }
122
+ // Walk up to parent
123
+ return walkTree(info.ppid, depth + 1);
124
+ }
125
+ const ppid = process.ppid;
126
+ if (!ppid) {
127
+ resolve(undefined);
128
+ return;
129
+ }
130
+ walkTree(ppid, 0).then(resolve).catch(() => resolve(undefined));
131
+ });
132
+ }
133
+ /**
134
+ * Start agent detection immediately (non-blocking).
135
+ * Call this early in CLI startup to begin detection in the background.
136
+ */
137
+ export function startAgentDetection() {
138
+ if (detectionPromise !== null) {
139
+ // Already started
140
+ return;
141
+ }
142
+ detectionPromise = detectParentAgent().then((result) => {
143
+ cachedResult = result;
144
+ // Invoke all registered callbacks
145
+ for (const callback of detectionCallbacks) {
146
+ try {
147
+ callback(result);
148
+ }
149
+ catch {
150
+ // Ignore callback errors
151
+ }
152
+ }
153
+ return result;
154
+ });
155
+ }
156
+ /**
157
+ * Register a callback to be invoked when agent detection completes.
158
+ * If detection has already completed, the callback is invoked immediately.
159
+ * This is non-blocking and does not return a promise.
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * onAgentDetected((agent) => {
164
+ * if (agent) {
165
+ * console.log(`Detected agent: ${agent}`);
166
+ * }
167
+ * });
168
+ * ```
169
+ */
170
+ export function onAgentDetected(callback) {
171
+ // If detection already completed, invoke immediately
172
+ if (cachedResult !== null) {
173
+ try {
174
+ callback(cachedResult);
175
+ }
176
+ catch {
177
+ // Ignore callback errors
178
+ }
179
+ return;
180
+ }
181
+ // Otherwise, register for later invocation
182
+ detectionCallbacks.push(callback);
183
+ }
184
+ /**
185
+ * Get the cached detection result synchronously.
186
+ * Returns undefined if detection hasn't completed yet or no agent was detected.
187
+ * Returns null if detection hasn't started or completed yet.
188
+ *
189
+ * Use this for synchronous access when you don't want to wait for detection.
190
+ */
191
+ export function getDetectedAgent() {
192
+ return cachedResult;
193
+ }
194
+ /**
195
+ * Wait for agent detection to complete and ensure all callbacks have been invoked.
196
+ * Call this before CLI exit to ensure the detected agent is written to session logs.
197
+ *
198
+ * This is a no-op if detection hasn't started or has already completed.
199
+ */
200
+ export async function flushAgentDetection() {
201
+ if (detectionPromise !== null) {
202
+ await detectionPromise;
203
+ }
204
+ }
205
+ /**
206
+ * Check if the CLI is being executed from a known coding agent.
207
+ * Returns the agent name if detected, undefined otherwise.
208
+ *
209
+ * This function returns immediately if detection has already completed,
210
+ * otherwise it awaits the detection promise started by startAgentDetection().
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const agent = await isExecutingFromAgent();
215
+ * if (agent) {
216
+ * logger.debug(`Running from agent: ${agent}`);
217
+ * }
218
+ * ```
219
+ */
220
+ export async function isExecutingFromAgent() {
221
+ // Return cached result if detection has completed
222
+ if (cachedResult !== null) {
223
+ return cachedResult;
224
+ }
225
+ // If detection hasn't started yet, start it now
226
+ if (detectionPromise === null) {
227
+ startAgentDetection();
228
+ }
229
+ // Wait for detection to complete
230
+ return detectionPromise;
231
+ }
232
+ //# sourceMappingURL=agent-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-detection.js","sourceRoot":"","sources":["../src/agent-detection.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,3 @@
1
1
  export { getResourceInfo, getResourceRegion, setResourceInfo, setResourceRegion, deleteResourceRegion, clearProfileCache, closeDatabase, type ResourceType, type ResourceInfo, } from './resource-region';
2
+ export { getCachedProject, setCachedProject, clearProjectCache } from './project-cache';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,YAAY,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { getResourceInfo, getResourceRegion, setResourceInfo, setResourceRegion, deleteResourceRegion, clearProfileCache, closeDatabase, } from './resource-region';
2
+ export { getCachedProject, setCachedProject, clearProjectCache } from './project-cache';
2
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,GAGb,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,aAAa,GAGb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { Project } from '@agentuity/server';
2
+ /**
3
+ * Get a cached project by profile and project ID.
4
+ * Returns null if not found in cache.
5
+ */
6
+ export declare function getCachedProject(profile: string, projectId: string): Project | null;
7
+ /**
8
+ * Store a project in the cache.
9
+ */
10
+ export declare function setCachedProject(profile: string, projectId: string, project: Project): void;
11
+ /**
12
+ * Clear all cached projects.
13
+ * Useful for testing or when switching contexts.
14
+ */
15
+ export declare function clearProjectCache(): void;
16
+ //# sourceMappingURL=project-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-cache.d.ts","sourceRoot":"","sources":["../../src/cache/project-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAiBjD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAGnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAG3F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * In-memory cache for project data to avoid duplicate API calls within a single CLI command execution.
3
+ * This cache is NOT persisted to disk - it only lives for the duration of the CLI process.
4
+ *
5
+ * The cache key is `{profile}:{projectId}` to ensure proper isolation between profiles.
6
+ */
7
+ const projectCache = new Map();
8
+ /**
9
+ * Generate a cache key from profile and project ID
10
+ */
11
+ function getCacheKey(profile, projectId) {
12
+ return `${profile}:${projectId}`;
13
+ }
14
+ /**
15
+ * Get a cached project by profile and project ID.
16
+ * Returns null if not found in cache.
17
+ */
18
+ export function getCachedProject(profile, projectId) {
19
+ const key = getCacheKey(profile, projectId);
20
+ return projectCache.get(key) ?? null;
21
+ }
22
+ /**
23
+ * Store a project in the cache.
24
+ */
25
+ export function setCachedProject(profile, projectId, project) {
26
+ const key = getCacheKey(profile, projectId);
27
+ projectCache.set(key, project);
28
+ }
29
+ /**
30
+ * Clear all cached projects.
31
+ * Useful for testing or when switching contexts.
32
+ */
33
+ export function clearProjectCache() {
34
+ projectCache.clear();
35
+ }
36
+ //# sourceMappingURL=project-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-cache.js","sourceRoot":"","sources":["../../src/cache/project-cache.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,YAAY,GAAG,IAAI,GAAG,EAAmB,CAAC;AAEhD;;GAEG;AACH,SAAS,WAAW,CAAC,OAAe,EAAE,SAAiB;IACtD,OAAO,GAAG,OAAO,IAAI,SAAS,EAAE,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,SAAiB;IAClE,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5C,OAAO,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,SAAiB,EAAE,OAAgB;IACpF,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC5C,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAChC,YAAY,CAAC,KAAK,EAAE,CAAC;AACtB,CAAC"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EACX,iBAAiB,EAEjB,cAAc,EAQd,MAAM,SAAS,CAAC;AAgcjB,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA4MjE;AA6jCD,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,OAAO,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAiOf"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EACX,iBAAiB,EAEjB,cAAc,EAQd,MAAM,SAAS,CAAC;AAicjB,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA4MjE;AAokCD,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,OAAO,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAiOf"}
package/dist/cli.js CHANGED
@@ -15,6 +15,7 @@ import { getCommand } from './command-prefix';
15
15
  import { isValidateMode, outputValidation } from './output';
16
16
  import { StructuredError } from '@agentuity/core';
17
17
  import { setProgram } from './program-ref';
18
+ import { getCachedProject, setCachedProject } from './cache';
18
19
  /**
19
20
  * Check if an error is a CLI input validation error (Zod error from schema parsing),
20
21
  * and not an API response validation error (ValidationOutputError).
@@ -835,8 +836,15 @@ async function registerSubcommand(parent, subcommand, baseCtx, hidden) {
835
836
  },
836
837
  };
837
838
  const apiClient = createAPIClient(baseCtx, configWithAuth);
838
- const { projectGet } = await import('@agentuity/server');
839
- const projectDetails = await projectGet(apiClient, { id: projectId, mask: true });
839
+ // Check cache first to avoid duplicate API calls
840
+ const profile = baseCtx.config?.name ?? 'default';
841
+ let projectDetails = getCachedProject(profile, projectId);
842
+ if (!projectDetails) {
843
+ const { projectGet } = await import('@agentuity/server');
844
+ // Use keys: false to match other callers and ensure cache consistency
845
+ projectDetails = await projectGet(apiClient, { id: projectId, keys: false });
846
+ setCachedProject(profile, projectId, projectDetails);
847
+ }
840
848
  project = {
841
849
  projectId: projectDetails.id,
842
850
  orgId: projectDetails.orgId,