@haystackeditor/cli 0.4.0 → 0.6.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.
package/README.md CHANGED
@@ -9,7 +9,7 @@ npx @haystackeditor/cli init
9
9
  ```
10
10
 
11
11
  This auto-detects your framework, package manager, and ports, then creates:
12
- - `.haystack.yml` - Configuration for the verification agent
12
+ - `.haystack.json` - Configuration for the verification agent
13
13
  - `.agents/skills/haystack.md` - Skill file for AI agent discovery
14
14
 
15
15
  ## Commands
@@ -75,7 +75,7 @@ npx @haystackeditor/cli secrets set API_KEY xxx --scope repo --scope-id owner/re
75
75
 
76
76
  ## Configuration
77
77
 
78
- The `init` command creates `.haystack.yml`:
78
+ The `init` command creates `.haystack.json`:
79
79
 
80
80
  ```yaml
81
81
  version: "1"
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Config commands - manage user preferences stored on Haystack Platform
3
+ */
4
+ /**
5
+ * Get current sandbox status
6
+ */
7
+ export declare function getSandboxStatus(): Promise<void>;
8
+ /**
9
+ * Enable sandbox mode
10
+ */
11
+ export declare function enableSandbox(): Promise<void>;
12
+ /**
13
+ * Disable sandbox mode
14
+ */
15
+ export declare function disableSandbox(): Promise<void>;
16
+ /**
17
+ * Handle sandbox subcommand
18
+ */
19
+ export declare function handleSandbox(action?: string): Promise<void>;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Config commands - manage user preferences stored on Haystack Platform
3
+ */
4
+ import chalk from 'chalk';
5
+ import { loadToken } from './login.js';
6
+ const API_BASE = 'https://haystackeditor.com/api/preferences';
7
+ async function requireAuth() {
8
+ const token = await loadToken();
9
+ if (!token) {
10
+ console.error(chalk.red('\nNot logged in. Run `haystack login` first.\n'));
11
+ process.exit(1);
12
+ }
13
+ return token;
14
+ }
15
+ async function apiRequest(method, token, body) {
16
+ const response = await fetch(API_BASE, {
17
+ method,
18
+ headers: {
19
+ 'Authorization': `Bearer ${token}`,
20
+ 'Content-Type': 'application/json',
21
+ 'User-Agent': 'Haystack-CLI',
22
+ },
23
+ body: body ? JSON.stringify(body) : undefined,
24
+ });
25
+ return response;
26
+ }
27
+ /**
28
+ * Get current sandbox status
29
+ */
30
+ export async function getSandboxStatus() {
31
+ const token = await requireAuth();
32
+ console.log(chalk.dim('\nFetching preferences...\n'));
33
+ try {
34
+ const response = await apiRequest('GET', token);
35
+ if (!response.ok) {
36
+ if (response.status === 401) {
37
+ console.error(chalk.red('Session expired. Run `haystack login` again.\n'));
38
+ process.exit(1);
39
+ }
40
+ throw new Error(`Failed to get preferences: ${response.status}`);
41
+ }
42
+ const data = await response.json();
43
+ console.log(chalk.bold('Sandbox mode:'), data.sandbox_enabled
44
+ ? chalk.green('enabled')
45
+ : chalk.yellow('disabled'));
46
+ console.log();
47
+ if (data.sandbox_enabled) {
48
+ console.log(chalk.dim('Haystack can clone and store your repos for verification.'));
49
+ console.log(chalk.dim('All data is deleted after 24 hours.'));
50
+ }
51
+ else {
52
+ console.log(chalk.dim('Sandbox mode is disabled. Automated verification will not work.'));
53
+ console.log(chalk.dim('Enable with: haystack config sandbox on'));
54
+ }
55
+ console.log();
56
+ }
57
+ catch (error) {
58
+ console.error(chalk.red(`\nError: ${error.message}\n`));
59
+ process.exit(1);
60
+ }
61
+ }
62
+ /**
63
+ * Enable sandbox mode
64
+ */
65
+ export async function enableSandbox() {
66
+ const token = await requireAuth();
67
+ console.log(chalk.dim('\nEnabling sandbox mode...'));
68
+ try {
69
+ const response = await apiRequest('PUT', token, { sandbox_enabled: true });
70
+ if (!response.ok) {
71
+ if (response.status === 401) {
72
+ console.error(chalk.red('Session expired. Run `haystack login` again.\n'));
73
+ process.exit(1);
74
+ }
75
+ const error = await response.json().catch(() => ({}));
76
+ throw new Error(error.error || `Failed to update preferences: ${response.status}`);
77
+ }
78
+ console.log(chalk.green('\nSandbox mode enabled.\n'));
79
+ console.log(chalk.dim('Haystack can now clone and store your repos for verification.'));
80
+ console.log(chalk.dim('All data is deleted after 24 hours.\n'));
81
+ }
82
+ catch (error) {
83
+ console.error(chalk.red(`\nError: ${error.message}\n`));
84
+ process.exit(1);
85
+ }
86
+ }
87
+ /**
88
+ * Disable sandbox mode
89
+ */
90
+ export async function disableSandbox() {
91
+ const token = await requireAuth();
92
+ console.log(chalk.dim('\nDisabling sandbox mode...'));
93
+ try {
94
+ const response = await apiRequest('PUT', token, { sandbox_enabled: false });
95
+ if (!response.ok) {
96
+ if (response.status === 401) {
97
+ console.error(chalk.red('Session expired. Run `haystack login` again.\n'));
98
+ process.exit(1);
99
+ }
100
+ const error = await response.json().catch(() => ({}));
101
+ throw new Error(error.error || `Failed to update preferences: ${response.status}`);
102
+ }
103
+ console.log(chalk.yellow('\nSandbox mode disabled.\n'));
104
+ console.log(chalk.dim('Automated verification will not work until you re-enable sandbox mode.'));
105
+ console.log(chalk.dim('Re-enable with: haystack config sandbox on\n'));
106
+ }
107
+ catch (error) {
108
+ console.error(chalk.red(`\nError: ${error.message}\n`));
109
+ process.exit(1);
110
+ }
111
+ }
112
+ /**
113
+ * Handle sandbox subcommand
114
+ */
115
+ export async function handleSandbox(action) {
116
+ switch (action?.toLowerCase()) {
117
+ case 'on':
118
+ case 'enable':
119
+ case 'true':
120
+ return enableSandbox();
121
+ case 'off':
122
+ case 'disable':
123
+ case 'false':
124
+ return disableSandbox();
125
+ case 'status':
126
+ case undefined:
127
+ return getSandboxStatus();
128
+ default:
129
+ console.error(chalk.red(`\nUnknown action: ${action}`));
130
+ console.log('\nUsage: haystack config sandbox [on|off|status]\n');
131
+ process.exit(1);
132
+ }
133
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * haystack init - Interactive setup wizard
3
3
  *
4
- * Creates .haystack.yml with auto-detected settings.
4
+ * Creates .haystack.json with auto-detected settings.
5
5
  */
6
6
  interface InitOptions {
7
7
  yes?: boolean;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * haystack init - Interactive setup wizard
3
3
  *
4
- * Creates .haystack.yml with auto-detected settings.
4
+ * Creates .haystack.json with auto-detected settings.
5
5
  */
6
6
  import inquirer from 'inquirer';
7
7
  import chalk from 'chalk';
@@ -24,7 +24,7 @@ export async function initCommand(options) {
24
24
  {
25
25
  type: 'confirm',
26
26
  name: 'overwrite',
27
- message: '.haystack.yml already exists. Overwrite?',
27
+ message: '.haystack.json already exists. Overwrite?',
28
28
  default: false,
29
29
  },
30
30
  ]);
@@ -62,20 +62,32 @@ export async function initCommand(options) {
62
62
  console.log(chalk.green(`✓ Created ${commandPath} (use /haystack in Claude Code)\n`));
63
63
  // Security validation
64
64
  await runSecurityCheck(configPath);
65
- // Explain purpose and next steps
65
+ // Print the prompt for the AI agent to follow
66
66
  console.log(chalk.cyan('━'.repeat(70)));
67
- console.log(chalk.cyan.bold('\n📋 WHAT IS HAYSTACK?\n'));
68
- console.log(chalk.white('When a PR is opened, Haystack spins up your app in a sandbox and'));
69
- console.log(chalk.white('an AI agent verifies the changes work correctly by:\n'));
70
- console.log(chalk.white(' Frontend: Navigating pages, clicking buttons, taking screenshots'));
71
- console.log(chalk.white(' • Backend: Calling API endpoints, checking responses\n'));
72
- console.log(chalk.white('The "flows" in .haystack.yml tell the agent WHAT to verify.\n'));
73
- console.log(chalk.cyan.bold('⚠️ ACTION REQUIRED:\n'));
74
- console.log(chalk.white('The config above only has dev server settings. You MUST add flows.\n'));
75
- console.log(chalk.white.bold('1. Run: cat .agents/skills/haystack.md'));
76
- console.log(chalk.white.bold('2. Read the "Codebase Discovery Guide" section'));
77
- console.log(chalk.white.bold('3. Follow it to discover features and add flows to .haystack.yml\n'));
78
- console.log(chalk.dim('Without flows, Haystack has nothing to verify.\n'));
67
+ console.log(chalk.cyan.bold('\n📋 NEXT STEP: Add verification flows\n'));
68
+ console.log(chalk.white('The config has dev server settings. Now add flows to tell Haystack'));
69
+ console.log(chalk.white('what to verify when PRs are opened.\n'));
70
+ console.log(chalk.yellow.bold('Give this prompt to your AI coding agent:\n'));
71
+ console.log(chalk.cyan(''.repeat(70)));
72
+ console.log(`
73
+ ${chalk.white('Add Haystack verification flows to .haystack.json')}
74
+
75
+ ${chalk.bold('STEP 1: Understand the app')}
76
+ - Read src/App.tsx and the main components
77
+ - Write 2 sentences: What does this app do? What's the core feature?
78
+
79
+ ${chalk.bold('STEP 2: Identify what PRs would touch')}
80
+ - List the 5 most important UI areas that PRs change
81
+ - These need the most thorough flows
82
+
83
+ ${chalk.bold('STEP 3: Add flows')}
84
+ - Read .agents/skills/haystack.md for the flow format
85
+ - Add flows for the 5 core areas first, then secondary pages
86
+
87
+ ${chalk.bold('STEP 4: Validate')}
88
+ - Confirm the core feature from Step 1 has flows
89
+ - Verify selectors are specific (not generic like "#root")
90
+ `);
79
91
  console.log(chalk.cyan('━'.repeat(70)));
80
92
  return;
81
93
  }
@@ -129,8 +141,7 @@ export async function initCommand(options) {
129
141
  // Show the generated config
130
142
  console.log(chalk.dim('Generated configuration:'));
131
143
  console.log(chalk.dim('─'.repeat(40)));
132
- const yaml = await import('yaml');
133
- console.log(yaml.stringify(config));
144
+ console.log(JSON.stringify(config, null, 2));
134
145
  console.log(chalk.dim('─'.repeat(40)));
135
146
  // Security validation
136
147
  await runSecurityCheck(configPath);
@@ -252,12 +263,15 @@ async function configureMonorepo(detected, name) {
252
263
  const [key, value] = authBypass.split('=');
253
264
  env[key] = value || 'true';
254
265
  }
266
+ // Check if this service has detected dependencies
267
+ const dependsOn = detectedService?.suggestedDependsOn?.filter((dep) => selectedServices.includes(dep));
255
268
  services[serviceName] = {
256
269
  ...(answers.root !== './' ? { root: answers.root } : {}),
257
270
  command: answers.command,
258
271
  ...(answers.type === 'server' ? { port: answers.port } : { type: 'batch' }),
259
272
  ready_pattern: 'ready|started|listening|Local:',
260
273
  ...(Object.keys(env).length > 0 ? { env } : {}),
274
+ ...(dependsOn?.length ? { depends_on: dependsOn } : {}),
261
275
  };
262
276
  }
263
277
  return {
@@ -282,6 +296,7 @@ function buildConfigFromDetection(detected) {
282
296
  ...(s.type === 'batch' ? { type: 'batch' } : {}),
283
297
  ready_pattern: 'ready|started|listening|Local:',
284
298
  ...(Object.keys(env).length > 0 ? { env } : {}),
299
+ ...(s.suggestedDependsOn?.length ? { depends_on: s.suggestedDependsOn } : {}),
285
300
  };
286
301
  }
287
302
  return {
@@ -315,8 +330,8 @@ function buildConfigFromDetection(detected) {
315
330
  }
316
331
  function printNextSteps() {
317
332
  console.log(chalk.cyan('Next steps:'));
318
- console.log(` 1. Review .haystack.yml and adjust as needed`);
333
+ console.log(` 1. Review .haystack.json and adjust as needed`);
319
334
  console.log(` 2. Add auth bypass env var if your app requires login`);
320
335
  console.log(` 3. Add flows to describe key user journeys to verify`);
321
- console.log(` 4. Commit: ${chalk.green('git add .haystack.yml .agents/ && git commit -m "Add Haystack"')}\n`);
336
+ console.log(` 4. Commit: ${chalk.green('git add .haystack.json .agents/ && git commit -m "Add Haystack"')}\n`);
322
337
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * haystack status - Check if .haystack.yml exists and is valid
2
+ * haystack status - Check if .haystack.json exists and is valid
3
3
  */
4
4
  export declare function statusCommand(): Promise<void>;
@@ -1,12 +1,12 @@
1
1
  /**
2
- * haystack status - Check if .haystack.yml exists and is valid
2
+ * haystack status - Check if .haystack.json exists and is valid
3
3
  */
4
4
  import chalk from 'chalk';
5
5
  import { loadConfig, findConfigPath } from '../utils/config.js';
6
6
  export async function statusCommand() {
7
7
  const configPath = await findConfigPath();
8
8
  if (!configPath) {
9
- console.log(chalk.yellow('⚠ No .haystack.yml found'));
9
+ console.log(chalk.yellow('⚠ No .haystack.json found'));
10
10
  console.log(chalk.dim('\nRun `haystack init` to create one.\n'));
11
11
  process.exit(1);
12
12
  }
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * This enables AI agents to spin up sandboxes of your app for testing.
7
7
  *
8
8
  * Usage:
9
- * npx @haystackeditor/cli init # Set up .haystack.yml
9
+ * npx @haystackeditor/cli init # Set up .haystack.json
10
10
  * npx @haystackeditor/cli status # Check configuration
11
11
  * npx @haystackeditor/cli login # Authenticate with GitHub
12
12
  * npx @haystackeditor/cli secrets list # List stored secrets
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * This enables AI agents to spin up sandboxes of your app for testing.
7
7
  *
8
8
  * Usage:
9
- * npx @haystackeditor/cli init # Set up .haystack.yml
9
+ * npx @haystackeditor/cli init # Set up .haystack.json
10
10
  * npx @haystackeditor/cli status # Check configuration
11
11
  * npx @haystackeditor/cli login # Authenticate with GitHub
12
12
  * npx @haystackeditor/cli secrets list # List stored secrets
@@ -16,6 +16,7 @@ import { statusCommand } from './commands/status.js';
16
16
  import { initCommand } from './commands/init.js';
17
17
  import { loginCommand, logoutCommand } from './commands/login.js';
18
18
  import { listSecrets, setSecret, deleteSecret } from './commands/secrets.js';
19
+ import { handleSandbox } from './commands/config.js';
19
20
  const program = new Command();
20
21
  program
21
22
  .name('haystack')
@@ -23,10 +24,10 @@ program
23
24
  .version('0.3.0');
24
25
  program
25
26
  .command('init')
26
- .description('Create .haystack.yml configuration')
27
+ .description('Create .haystack.json configuration')
27
28
  .option('-y, --yes', 'Use auto-detected defaults without prompting')
28
29
  .addHelpText('after', `
29
- This creates a .haystack.yml file that configures:
30
+ This creates a .haystack.json file that configures:
30
31
  • How to start your dev server
31
32
  • Verification commands (build, lint, typecheck)
32
33
  • Auth bypass for sandbox environments
@@ -36,7 +37,7 @@ Once set up, AI agents can automatically spin up and test your app.
36
37
  .action(initCommand);
37
38
  program
38
39
  .command('status')
39
- .description('Check if .haystack.yml exists and is valid')
40
+ .description('Check if .haystack.json exists and is valid')
40
41
  .action(statusCommand);
41
42
  program
42
43
  .command('login')
@@ -66,6 +67,25 @@ secrets
66
67
  .command('delete <key>')
67
68
  .description('Delete a secret')
68
69
  .action(deleteSecret);
70
+ // Config subcommands
71
+ const config = program
72
+ .command('config')
73
+ .description('Manage user preferences');
74
+ config
75
+ .command('sandbox [action]')
76
+ .description('Manage sandbox mode (on|off|status)')
77
+ .addHelpText('after', `
78
+ Actions:
79
+ on, enable Enable sandbox mode (allow repo cloning)
80
+ off, disable Disable sandbox mode
81
+ status Show current status (default)
82
+
83
+ Examples:
84
+ haystack config sandbox # Show current status
85
+ haystack config sandbox on # Enable sandbox mode
86
+ haystack config sandbox off # Disable sandbox mode
87
+ `)
88
+ .action(handleSandbox);
69
89
  // Show help if no command provided
70
90
  if (process.argv.length === 2) {
71
91
  program.help();
package/dist/types.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Haystack CLI Types
3
3
  *
4
- * These types define the .haystack.yml schema that sandbox.py reads.
4
+ * These types define the .haystack.json schema that sandbox.py reads.
5
5
  */
6
6
  /**
7
- * Main configuration file schema (.haystack.yml)
7
+ * Main configuration file schema (.haystack.json)
8
8
  */
9
9
  export interface HaystackConfig {
10
10
  /** Schema version - must be "1" */
@@ -27,6 +27,26 @@ export interface HaystackConfig {
27
27
  services?: Record<string, Service>;
28
28
  /** Verification configuration */
29
29
  verification?: VerificationConfig;
30
+ /**
31
+ * Network egress configuration for the sandbox.
32
+ * By default, sandbox can only reach Cloudflare + GitHub IPs.
33
+ * Add your own destinations here (staging servers, S3, etc.).
34
+ */
35
+ network?: NetworkConfig;
36
+ /**
37
+ * Secrets for fixture fetching and other operations.
38
+ * These are injected as environment variables in the sandbox.
39
+ * Supports tokens for staging APIs, S3 credentials, etc.
40
+ *
41
+ * ⚠️ SECURITY: Never commit real secrets to git!
42
+ * Use environment variable references: $ENV_VAR or ${ENV_VAR}
43
+ *
44
+ * @example
45
+ * secrets:
46
+ * STAGING_TOKEN: "$STAGING_API_TOKEN" # Read from local env
47
+ * AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}"
48
+ */
49
+ secrets?: Record<string, string>;
30
50
  }
31
51
  /**
32
52
  * Dev server configuration (simple mode)
@@ -57,6 +77,16 @@ export interface Service {
57
77
  type?: 'server' | 'batch';
58
78
  /** Environment variables to set */
59
79
  env?: Record<string, string>;
80
+ /**
81
+ * Services that must be started before this service.
82
+ * Used when a service proxies to another (e.g., frontend → API worker).
83
+ * Auto-detected from vite.config.ts proxy configuration.
84
+ *
85
+ * @example
86
+ * depends_on:
87
+ * - haystack-worker # Start review-chat worker first
88
+ */
89
+ depends_on?: string[];
60
90
  }
61
91
  /**
62
92
  * Verification configuration
@@ -67,6 +97,28 @@ export interface VerificationConfig {
67
97
  /** Fixture definitions - array of pattern/source pairs */
68
98
  fixtures?: Fixture[];
69
99
  }
100
+ /**
101
+ * Network egress configuration
102
+ */
103
+ export interface NetworkConfig {
104
+ /**
105
+ * Additional hosts/domains to allow egress to.
106
+ * The sandbox always allows Cloudflare and GitHub IPs.
107
+ * Add your own destinations here.
108
+ *
109
+ * Supports:
110
+ * - Exact domains: "staging.mycompany.com"
111
+ * - Wildcards: "*.s3.amazonaws.com"
112
+ * - CIDR blocks: "10.0.0.0/8"
113
+ *
114
+ * @example
115
+ * allow:
116
+ * - "staging.mycompany.com"
117
+ * - "*.s3.amazonaws.com"
118
+ * - "internal-api.example.com"
119
+ */
120
+ allow?: string[];
121
+ }
70
122
  /**
71
123
  * Fixture definition - pattern to match and source to load from
72
124
  */
@@ -155,6 +207,21 @@ export interface DetectedService {
155
207
  framework?: string;
156
208
  suggestedCommand?: string;
157
209
  suggestedPort?: number;
210
+ /** Auto-detected dependencies from proxy configuration */
211
+ suggestedDependsOn?: string[];
212
+ }
213
+ /**
214
+ * Proxy dependency detection result
215
+ */
216
+ export interface ProxyDependency {
217
+ /** Proxy path pattern (e.g., "/api/review-chat") */
218
+ path: string;
219
+ /** Target port (e.g., 8787) */
220
+ port: number;
221
+ /** Target host (usually localhost) */
222
+ host: string;
223
+ /** Matched service name if found */
224
+ matchedService?: string;
158
225
  }
159
226
  /**
160
227
  * Auth credentials stored in Haystack
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Haystack CLI Types
3
3
  *
4
- * These types define the .haystack.yml schema that sandbox.py reads.
4
+ * These types define the .haystack.json schema that sandbox.py reads.
5
5
  */
6
6
  export {};
@@ -19,6 +19,6 @@ export declare function saveConfig(config: HaystackConfig, configPath?: string):
19
19
  */
20
20
  export declare function configExists(startDir?: string): Promise<boolean>;
21
21
  /**
22
- * Get the project root (directory containing .haystack.yml or current dir)
22
+ * Get the project root (directory containing .haystack.json or current dir)
23
23
  */
24
24
  export declare function getProjectRoot(): Promise<string>;
@@ -3,8 +3,7 @@
3
3
  */
4
4
  import * as fs from 'fs/promises';
5
5
  import * as path from 'path';
6
- import * as yaml from 'yaml';
7
- const CONFIG_FILENAME = '.haystack.yml';
6
+ const CONFIG_FILENAME = '.haystack.json';
8
7
  /**
9
8
  * Find the config file by walking up the directory tree
10
9
  */
@@ -37,7 +36,7 @@ export async function loadConfig(configPath) {
37
36
  }
38
37
  try {
39
38
  const content = await fs.readFile(resolvedPath, 'utf-8');
40
- return yaml.parse(content);
39
+ return JSON.parse(content);
41
40
  }
42
41
  catch (err) {
43
42
  throw new Error(`Failed to parse ${resolvedPath}: ${err.message}`);
@@ -48,10 +47,7 @@ export async function loadConfig(configPath) {
48
47
  */
49
48
  export async function saveConfig(config, configPath) {
50
49
  const resolvedPath = configPath || path.join(process.cwd(), CONFIG_FILENAME);
51
- const content = yaml.stringify(config, {
52
- indent: 2,
53
- lineWidth: 0, // Don't wrap lines
54
- });
50
+ const content = JSON.stringify(config, null, 2);
55
51
  await fs.writeFile(resolvedPath, content, 'utf-8');
56
52
  return resolvedPath;
57
53
  }
@@ -63,7 +59,7 @@ export async function configExists(startDir) {
63
59
  return configPath !== null;
64
60
  }
65
61
  /**
66
- * Get the project root (directory containing .haystack.yml or current dir)
62
+ * Get the project root (directory containing .haystack.json or current dir)
67
63
  */
68
64
  export async function getProjectRoot() {
69
65
  const configPath = await findConfigPath();
@@ -1,10 +1,43 @@
1
1
  /**
2
2
  * Project detection utilities
3
3
  *
4
- * Auto-detects framework, package manager, monorepo structure, and services.
4
+ * Auto-detects framework, package manager, monorepo structure, services,
5
+ * and inter-service dependencies from proxy configurations.
5
6
  */
6
- import type { DetectedProject } from '../types.js';
7
+ import type { DetectedProject, DetectedService, ProxyDependency } from '../types.js';
7
8
  /**
8
9
  * Detect project configuration
9
10
  */
10
11
  export declare function detectProject(rootDir?: string): Promise<DetectedProject>;
12
+ /**
13
+ * Detect proxy dependencies from vite.config.ts/js
14
+ *
15
+ * Parses the vite config file to find proxy targets that point to localhost,
16
+ * which indicate dependencies on other local services.
17
+ *
18
+ * @example
19
+ * // vite.config.ts with proxy
20
+ * server: {
21
+ * proxy: {
22
+ * '/api/review-chat': {
23
+ * target: 'http://localhost:8787',
24
+ * }
25
+ * }
26
+ * }
27
+ * // Returns: [{ path: '/api/review-chat', port: 8787, host: 'localhost' }]
28
+ */
29
+ export declare function detectProxyDependencies(rootDir: string): Promise<ProxyDependency[]>;
30
+ /**
31
+ * Match proxy dependencies to detected services
32
+ *
33
+ * Given a list of proxy targets (ports) and detected services,
34
+ * determines which services are dependencies based on port matching.
35
+ */
36
+ export declare function matchProxyToServices(proxyDeps: ProxyDependency[], services: DetectedService[]): Map<string, string[]>;
37
+ /**
38
+ * Suggest depends_on for services based on proxy configuration
39
+ *
40
+ * For the main service (usually frontend), detect if it proxies to other local services
41
+ * and suggest those as dependencies.
42
+ */
43
+ export declare function suggestServiceDependencies(rootDir: string, services: DetectedService[]): Promise<DetectedService[]>;