nstantpage-agent 0.2.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.
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Start command — launch the nstantpage agent
3
+ *
4
+ * Architecture:
5
+ * 1. Start local API server (handles /live/* requests for file sync, checks, etc.)
6
+ * 2. Start local dev server (Vite/Next.js — runs project on user's machine)
7
+ * 3. Connect tunnel to gateway (relays requests from cloud to local machine)
8
+ *
9
+ * The agent fully replaces Docker containers:
10
+ * - Files are on the user's disk (no docker cp needed)
11
+ * - Dev server runs natively (no container overhead)
12
+ * - Type checking runs locally (full IDE speed)
13
+ * - Package installation uses local npm/pnpm
14
+ */
15
+ import chalk from 'chalk';
16
+ import path from 'path';
17
+ import fs from 'fs';
18
+ import { getConfig } from '../config.js';
19
+ import { TunnelClient } from '../tunnel.js';
20
+ import { LocalServer } from '../localServer.js';
21
+ export async function startCommand(directory, options) {
22
+ const conf = getConfig();
23
+ // Check authentication
24
+ const token = conf.get('token');
25
+ if (!token) {
26
+ console.log(chalk.red('✗ Not authenticated. Run "nstantpage login" first.'));
27
+ process.exit(1);
28
+ }
29
+ // Resolve project directory
30
+ const projectDir = path.resolve(directory);
31
+ if (!fs.existsSync(projectDir)) {
32
+ console.log(chalk.red(`✗ Directory not found: ${projectDir}`));
33
+ process.exit(1);
34
+ }
35
+ // Verify it's a project directory
36
+ if (!fs.existsSync(path.join(projectDir, 'package.json'))) {
37
+ console.log(chalk.red(`✗ No package.json found in ${projectDir}`));
38
+ console.log(chalk.gray(' Make sure you\'re in a project directory'));
39
+ process.exit(1);
40
+ }
41
+ const devPort = parseInt(options.port, 10);
42
+ const apiPort = parseInt(options.apiPort, 10);
43
+ // Determine project ID
44
+ let projectId = options.projectId || conf.get('projectId');
45
+ // Try .nstantpage.json in project dir
46
+ const localConfig = path.join(projectDir, '.nstantpage.json');
47
+ if (!projectId && fs.existsSync(localConfig)) {
48
+ try {
49
+ const data = JSON.parse(fs.readFileSync(localConfig, 'utf-8'));
50
+ projectId = data.projectId;
51
+ }
52
+ catch { }
53
+ }
54
+ if (!projectId) {
55
+ console.log(chalk.yellow('⚠ No project ID specified.'));
56
+ console.log(chalk.gray(' Use --project-id <id> or create a .nstantpage.json file'));
57
+ console.log(chalk.gray(' with { "projectId": "<your-project-id>" }'));
58
+ process.exit(1);
59
+ }
60
+ // Save project ID
61
+ conf.set('projectId', projectId);
62
+ console.log(chalk.blue(`\n🚀 nstantpage agent v0.2.0\n`));
63
+ console.log(chalk.gray(` Directory: ${projectDir}`));
64
+ console.log(chalk.gray(` Project ID: ${projectId}`));
65
+ console.log(chalk.gray(` Dev server: port ${devPort}`));
66
+ console.log(chalk.gray(` API server: port ${apiPort}`));
67
+ console.log(chalk.gray(` Gateway: ${options.gateway}\n`));
68
+ // 1. Start local server (API + dev server)
69
+ const localServer = new LocalServer({
70
+ projectDir,
71
+ projectId,
72
+ apiPort,
73
+ devPort,
74
+ });
75
+ // 2. Create tunnel client
76
+ const tunnel = new TunnelClient({
77
+ gatewayUrl: options.gateway,
78
+ token,
79
+ projectId,
80
+ apiPort,
81
+ devPort,
82
+ });
83
+ // Handle graceful shutdown
84
+ const shutdown = async () => {
85
+ console.log(chalk.yellow('\n\n Shutting down...\n'));
86
+ tunnel.disconnect();
87
+ await localServer.stop();
88
+ conf.delete('agentPid');
89
+ process.exit(0);
90
+ };
91
+ process.on('SIGTERM', shutdown);
92
+ process.on('SIGINT', shutdown);
93
+ // Store PID for "nstantpage stop"
94
+ conf.set('agentPid', process.pid);
95
+ try {
96
+ // Start local API server
97
+ console.log(chalk.gray(' Starting local API server...'));
98
+ await localServer.start();
99
+ console.log(chalk.green(` ✓ API server on port ${apiPort}`));
100
+ // Start dev server unless --no-dev flag
101
+ if (!options.noDev) {
102
+ console.log(chalk.gray(' Starting dev server...'));
103
+ try {
104
+ const devServer = localServer.getDevServer();
105
+ await devServer.start();
106
+ console.log(chalk.green(` ✓ Dev server on port ${devPort}`));
107
+ }
108
+ catch (err) {
109
+ console.log(chalk.yellow(` ⚠ Dev server failed to start: ${err.message}`));
110
+ console.log(chalk.gray(' You can start it later from the editor'));
111
+ }
112
+ }
113
+ else {
114
+ console.log(chalk.gray(' Dev server skipped (--no-dev)'));
115
+ }
116
+ // Connect tunnel to gateway
117
+ console.log(chalk.gray(' Connecting to gateway...'));
118
+ await tunnel.connect();
119
+ console.log(chalk.green(` ✓ Tunnel connected\n`));
120
+ // Display status
121
+ console.log(chalk.blue.bold(` ┌──────────────────────────────────────────────┐`));
122
+ console.log(chalk.blue.bold(` │ Your project is live! │`));
123
+ console.log(chalk.blue.bold(` ├──────────────────────────────────────────────┤`));
124
+ console.log(chalk.white(` │ Cloud: https://${projectId}.webprev.live`));
125
+ console.log(chalk.white(` │ Local: http://localhost:${devPort}`));
126
+ console.log(chalk.blue.bold(` └──────────────────────────────────────────────┘\n`));
127
+ console.log(chalk.gray(` Mode: ${chalk.green('Agent')} (no containers needed)`));
128
+ console.log(chalk.gray(` All builds, checks, and previews run on this machine.`));
129
+ console.log(chalk.gray(` Press Ctrl+C to stop\n`));
130
+ // Keep alive
131
+ await new Promise(() => { });
132
+ }
133
+ catch (err) {
134
+ console.error(chalk.red(`\n✗ Failed to start: ${err.message}`));
135
+ await localServer.stop();
136
+ conf.delete('agentPid');
137
+ process.exit(1);
138
+ }
139
+ }
140
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Status command — show agent connection status
3
+ */
4
+ export declare function statusCommand(): Promise<void>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Status command — show agent connection status
3
+ */
4
+ import chalk from 'chalk';
5
+ import { getConfig } from '../config.js';
6
+ export async function statusCommand() {
7
+ const conf = getConfig();
8
+ const token = conf.get('token');
9
+ const projectId = conf.get('projectId');
10
+ const pid = conf.get('agentPid');
11
+ const lastConnected = conf.get('lastConnected');
12
+ const devPort = conf.get('devPort') || 3000;
13
+ const apiPort = conf.get('apiPort') || 18924;
14
+ console.log(chalk.blue('\n nstantpage agent v0.2.0\n'));
15
+ // Auth
16
+ if (token) {
17
+ console.log(chalk.green(' ✓ Authenticated'));
18
+ }
19
+ else {
20
+ console.log(chalk.red(' ✗ Not authenticated (run "nstantpage login")'));
21
+ }
22
+ // Project
23
+ if (projectId) {
24
+ console.log(chalk.gray(` Project: ${projectId}`));
25
+ console.log(chalk.gray(` Preview: https://${projectId}.webprev.live`));
26
+ }
27
+ else {
28
+ console.log(chalk.gray(' No project linked'));
29
+ }
30
+ // Running
31
+ if (pid) {
32
+ try {
33
+ process.kill(pid, 0); // Check if process exists
34
+ console.log(chalk.green(` ✓ Agent running (PID ${pid})`));
35
+ console.log(chalk.gray(` Dev server: http://localhost:${devPort}`));
36
+ console.log(chalk.gray(` API server: http://localhost:${apiPort}`));
37
+ }
38
+ catch {
39
+ console.log(chalk.gray(' Agent not running'));
40
+ conf.delete('agentPid');
41
+ }
42
+ }
43
+ else {
44
+ console.log(chalk.gray(' Agent not running'));
45
+ }
46
+ // Last connected
47
+ if (lastConnected) {
48
+ console.log(chalk.gray(` Last connected: ${lastConnected}`));
49
+ }
50
+ console.log(chalk.gray(`\n Mode: Agent (replaces cloud containers)`));
51
+ console.log('');
52
+ }
53
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Agent configuration store (persisted to disk)
3
+ */
4
+ import Conf from 'conf';
5
+ export declare function getConfig(): Conf;
package/dist/config.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Agent configuration store (persisted to disk)
3
+ */
4
+ import Conf from 'conf';
5
+ let _conf = null;
6
+ export function getConfig() {
7
+ if (!_conf) {
8
+ _conf = new Conf({
9
+ projectName: 'nstantpage-agent',
10
+ schema: {
11
+ token: { type: 'string', default: '' },
12
+ gatewayUrl: { type: 'string', default: 'wss://webprev.live' },
13
+ projectId: { type: 'string', default: '' },
14
+ agentPid: { type: 'number' },
15
+ lastConnected: { type: 'string' },
16
+ devPort: { type: 'number', default: 3000 },
17
+ apiPort: { type: 'number', default: 18924 },
18
+ },
19
+ });
20
+ }
21
+ return _conf;
22
+ }
23
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Dev Server — manages the local development server process.
3
+ * Enhanced version of runner.ts with log capturing and lifecycle management.
4
+ *
5
+ * Replaces the container-based dev server (docker exec npx vite).
6
+ */
7
+ export interface DevServerOptions {
8
+ projectDir: string;
9
+ port: number;
10
+ env?: Record<string, string>;
11
+ }
12
+ export interface LogEntry {
13
+ timestamp: number;
14
+ type: 'stdout' | 'stderr';
15
+ message: string;
16
+ }
17
+ export declare class DevServer {
18
+ private options;
19
+ private process;
20
+ private backendProcess;
21
+ private logs;
22
+ private maxLogs;
23
+ private _isRunning;
24
+ private startedAt;
25
+ constructor(options: DevServerOptions);
26
+ get isRunning(): boolean;
27
+ get port(): number;
28
+ get uptime(): number;
29
+ /**
30
+ * Start the dev server based on project type detection.
31
+ */
32
+ start(): Promise<void>;
33
+ /**
34
+ * Stop all dev server processes.
35
+ */
36
+ stop(): Promise<void>;
37
+ /**
38
+ * Restart the dev server.
39
+ */
40
+ restart(): Promise<void>;
41
+ /**
42
+ * Get recent logs.
43
+ */
44
+ getLogs(limit?: number): LogEntry[];
45
+ /**
46
+ * Get resource usage stats.
47
+ */
48
+ getStats(): {
49
+ cpuPercent: number;
50
+ memoryMb: number;
51
+ pid: number | null;
52
+ };
53
+ /**
54
+ * Execute a command in the project directory.
55
+ */
56
+ exec(command: string, timeoutMs?: number): Promise<{
57
+ exitCode: number;
58
+ stdout: string;
59
+ stderr: string;
60
+ }>;
61
+ private captureOutput;
62
+ private addLog;
63
+ private killProcess;
64
+ private waitForReady;
65
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Dev Server — manages the local development server process.
3
+ * Enhanced version of runner.ts with log capturing and lifecycle management.
4
+ *
5
+ * Replaces the container-based dev server (docker exec npx vite).
6
+ */
7
+ import { spawn, execSync } from 'child_process';
8
+ import path from 'path';
9
+ import fs from 'fs';
10
+ import http from 'http';
11
+ import os from 'os';
12
+ export class DevServer {
13
+ options;
14
+ process = null;
15
+ backendProcess = null;
16
+ logs = [];
17
+ maxLogs = 500;
18
+ _isRunning = false;
19
+ startedAt = 0;
20
+ constructor(options) {
21
+ this.options = options;
22
+ }
23
+ get isRunning() {
24
+ return this._isRunning;
25
+ }
26
+ get port() {
27
+ return this.options.port;
28
+ }
29
+ get uptime() {
30
+ return this._isRunning ? Date.now() - this.startedAt : 0;
31
+ }
32
+ /**
33
+ * Start the dev server based on project type detection.
34
+ */
35
+ async start() {
36
+ if (this._isRunning) {
37
+ console.log(' [DevServer] Already running, restarting...');
38
+ await this.stop();
39
+ }
40
+ const { projectDir, port } = this.options;
41
+ const extraEnv = this.options.env || {};
42
+ // Detect project type
43
+ const pkgPath = path.join(projectDir, 'package.json');
44
+ if (!fs.existsSync(pkgPath)) {
45
+ throw new Error(`No package.json found in ${projectDir}`);
46
+ }
47
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
48
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
49
+ const hasVite = 'vite' in deps;
50
+ const hasNext = 'next' in deps;
51
+ const hasBackend = fs.existsSync(path.join(projectDir, 'server', 'index.ts')) ||
52
+ fs.existsSync(path.join(projectDir, 'server', 'index.js'));
53
+ this.logs = [];
54
+ this.startedAt = Date.now();
55
+ // Start backend if present
56
+ if (hasBackend) {
57
+ const backendPort = port + 1000;
58
+ const backendEntry = fs.existsSync(path.join(projectDir, 'server', 'index.ts'))
59
+ ? 'server/index.ts'
60
+ : 'server/index.js';
61
+ console.log(` [DevServer] Starting backend (port ${backendPort})...`);
62
+ this.backendProcess = spawn('npx', ['tsx', backendEntry], {
63
+ cwd: projectDir,
64
+ env: {
65
+ ...process.env,
66
+ ...extraEnv,
67
+ PORT: String(backendPort),
68
+ NODE_ENV: 'development',
69
+ },
70
+ shell: true,
71
+ stdio: ['pipe', 'pipe', 'pipe'],
72
+ });
73
+ this.captureOutput(this.backendProcess, 'backend');
74
+ }
75
+ // Start frontend dev server
76
+ let cmd;
77
+ let args;
78
+ if (hasNext) {
79
+ cmd = 'npx';
80
+ args = ['next', 'dev', '-p', String(port)];
81
+ }
82
+ else if (hasVite) {
83
+ cmd = 'npx';
84
+ args = ['vite', '--port', String(port), '--host', '0.0.0.0', '--strictPort'];
85
+ }
86
+ else if (pkg.scripts?.dev) {
87
+ cmd = 'npm';
88
+ args = ['run', 'dev'];
89
+ }
90
+ else if (pkg.scripts?.start) {
91
+ cmd = 'npm';
92
+ args = ['start'];
93
+ }
94
+ else {
95
+ throw new Error('Could not detect dev server command');
96
+ }
97
+ const frontendEnv = {
98
+ ...process.env,
99
+ ...extraEnv,
100
+ PORT: String(port),
101
+ };
102
+ if (hasBackend) {
103
+ frontendEnv['VITE_BACKEND_PORT'] = String(port + 1000);
104
+ }
105
+ console.log(` [DevServer] Starting: ${cmd} ${args.join(' ')} (port ${port})`);
106
+ this.process = spawn(cmd, args, {
107
+ cwd: projectDir,
108
+ env: frontendEnv,
109
+ shell: true,
110
+ stdio: ['pipe', 'pipe', 'pipe'],
111
+ });
112
+ this.captureOutput(this.process, 'frontend');
113
+ this.process.on('close', (code) => {
114
+ this._isRunning = false;
115
+ this.addLog('stderr', `Dev server exited with code ${code}`);
116
+ console.log(` [DevServer] Process exited (code ${code})`);
117
+ });
118
+ this.process.on('error', (err) => {
119
+ this._isRunning = false;
120
+ this.addLog('stderr', `Dev server error: ${err.message}`);
121
+ console.error(` [DevServer] Error: ${err.message}`);
122
+ });
123
+ this._isRunning = true;
124
+ // Wait for server to be ready
125
+ try {
126
+ await this.waitForReady(port, 30_000);
127
+ console.log(` [DevServer] Ready on port ${port}`);
128
+ }
129
+ catch {
130
+ console.warn(` [DevServer] Health check timed out, but server may still be starting`);
131
+ }
132
+ }
133
+ /**
134
+ * Stop all dev server processes.
135
+ */
136
+ async stop() {
137
+ const kills = [];
138
+ if (this.process) {
139
+ kills.push(this.killProcess(this.process));
140
+ this.process = null;
141
+ }
142
+ if (this.backendProcess) {
143
+ kills.push(this.killProcess(this.backendProcess));
144
+ this.backendProcess = null;
145
+ }
146
+ await Promise.all(kills);
147
+ this._isRunning = false;
148
+ console.log(' [DevServer] Stopped');
149
+ }
150
+ /**
151
+ * Restart the dev server.
152
+ */
153
+ async restart() {
154
+ await this.stop();
155
+ await new Promise(r => setTimeout(r, 500));
156
+ await this.start();
157
+ }
158
+ /**
159
+ * Get recent logs.
160
+ */
161
+ getLogs(limit = 100) {
162
+ return this.logs.slice(-limit);
163
+ }
164
+ /**
165
+ * Get resource usage stats.
166
+ */
167
+ getStats() {
168
+ if (!this.process || !this.process.pid) {
169
+ return { cpuPercent: 0, memoryMb: 0, pid: null };
170
+ }
171
+ try {
172
+ const pid = this.process.pid;
173
+ const platform = os.platform();
174
+ let output;
175
+ if (platform === 'win32') {
176
+ // Windows: use wmic or tasklist
177
+ output = execSync(`wmic process where ProcessId=${pid} get WorkingSetSize /format:value`, { encoding: 'utf-8', timeout: 3000 }).trim();
178
+ const match = output.match(/WorkingSetSize=(\d+)/);
179
+ const bytes = match ? parseInt(match[1], 10) : 0;
180
+ return {
181
+ cpuPercent: 0, // CPU% hard to get on Windows without sampling
182
+ memoryMb: bytes / (1024 * 1024),
183
+ pid,
184
+ };
185
+ }
186
+ else {
187
+ // macOS / Linux: use ps
188
+ output = execSync(`ps -p ${pid} -o %cpu=,rss= 2>/dev/null`, { encoding: 'utf-8', timeout: 2000 }).trim();
189
+ const [cpu, rss] = output.split(/\s+/).map(Number);
190
+ return {
191
+ cpuPercent: cpu || 0,
192
+ memoryMb: (rss || 0) / 1024, // rss is in KB
193
+ pid,
194
+ };
195
+ }
196
+ }
197
+ catch {
198
+ return { cpuPercent: 0, memoryMb: 0, pid: this.process.pid };
199
+ }
200
+ }
201
+ /**
202
+ * Execute a command in the project directory.
203
+ */
204
+ async exec(command, timeoutMs = 30_000) {
205
+ return new Promise((resolve) => {
206
+ const isWin = os.platform() === 'win32';
207
+ const shell = isWin ? 'cmd' : 'sh';
208
+ const shellArgs = isWin ? ['/c', command] : ['-c', command];
209
+ const proc = spawn(shell, shellArgs, {
210
+ cwd: this.options.projectDir,
211
+ env: process.env,
212
+ stdio: ['pipe', 'pipe', 'pipe'],
213
+ });
214
+ let stdout = '';
215
+ let stderr = '';
216
+ proc.stdout?.on('data', (d) => { stdout += d.toString(); });
217
+ proc.stderr?.on('data', (d) => { stderr += d.toString(); });
218
+ proc.on('close', (code) => {
219
+ resolve({ exitCode: code ?? 1, stdout, stderr });
220
+ });
221
+ proc.on('error', (err) => {
222
+ resolve({ exitCode: 1, stdout, stderr: err.message });
223
+ });
224
+ setTimeout(() => {
225
+ try {
226
+ proc.kill();
227
+ }
228
+ catch { }
229
+ resolve({ exitCode: 1, stdout, stderr: stderr + '\nCommand timed out' });
230
+ }, timeoutMs);
231
+ });
232
+ }
233
+ captureOutput(proc, source) {
234
+ proc.stdout?.on('data', (data) => {
235
+ const msg = data.toString().trim();
236
+ if (msg) {
237
+ this.addLog('stdout', msg);
238
+ process.stdout.write(` [${source}] ${msg}\n`);
239
+ }
240
+ });
241
+ proc.stderr?.on('data', (data) => {
242
+ const msg = data.toString().trim();
243
+ if (msg) {
244
+ this.addLog('stderr', msg);
245
+ // Only print actual errors, not noisy warnings
246
+ if (!msg.includes('[BABEL] Note:') && !msg.includes('at-rule-no-unknown')) {
247
+ process.stderr.write(` [${source}] ${msg}\n`);
248
+ }
249
+ }
250
+ });
251
+ }
252
+ addLog(type, message) {
253
+ this.logs.push({ timestamp: Date.now(), type, message });
254
+ if (this.logs.length > this.maxLogs) {
255
+ this.logs = this.logs.slice(-this.maxLogs);
256
+ }
257
+ }
258
+ killProcess(proc) {
259
+ return new Promise((resolve) => {
260
+ if (!proc.pid) {
261
+ resolve();
262
+ return;
263
+ }
264
+ try {
265
+ // Try graceful shutdown first
266
+ proc.kill('SIGTERM');
267
+ const forceKill = setTimeout(() => {
268
+ try {
269
+ proc.kill();
270
+ }
271
+ catch { }
272
+ resolve();
273
+ }, 5000);
274
+ proc.on('close', () => {
275
+ clearTimeout(forceKill);
276
+ resolve();
277
+ });
278
+ }
279
+ catch {
280
+ resolve();
281
+ }
282
+ });
283
+ }
284
+ waitForReady(port, timeoutMs) {
285
+ return new Promise((resolve, reject) => {
286
+ const start = Date.now();
287
+ const check = () => {
288
+ if (Date.now() - start > timeoutMs) {
289
+ reject(new Error('Timeout'));
290
+ return;
291
+ }
292
+ const req = http.get(`http://localhost:${port}/`, (res) => {
293
+ res.resume();
294
+ resolve();
295
+ });
296
+ req.on('error', () => {
297
+ setTimeout(check, 500);
298
+ });
299
+ req.setTimeout(2000, () => {
300
+ req.destroy();
301
+ setTimeout(check, 500);
302
+ });
303
+ };
304
+ setTimeout(check, 1000);
305
+ });
306
+ }
307
+ }
308
+ //# sourceMappingURL=devServer.js.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Error Store — tracks build, type, lint, and runtime errors for a project.
3
+ * This replaces the container-based error tracking from the gateway.
4
+ */
5
+ export interface StructuredError {
6
+ file?: string;
7
+ line?: number;
8
+ col?: number;
9
+ message: string;
10
+ type: 'build' | 'type' | 'lint' | 'hard' | 'runtime';
11
+ code?: string;
12
+ signature: string;
13
+ raw?: string;
14
+ }
15
+ export declare class ErrorStore {
16
+ private buildErrors;
17
+ private typeErrors;
18
+ private lintErrors;
19
+ private runtimeErrors;
20
+ setBuildErrors(errors: StructuredError[]): void;
21
+ setTypeErrors(errors: StructuredError[]): void;
22
+ setLintErrors(errors: StructuredError[]): void;
23
+ addRuntimeError(error: StructuredError): void;
24
+ clearRuntimeErrors(): void;
25
+ clearAll(): void;
26
+ getAllErrors(): StructuredError[];
27
+ getErrorsByType(): {
28
+ buildErrors: string[];
29
+ typeErrors: string[];
30
+ lintErrors: string[];
31
+ runtimeErrors: string[];
32
+ };
33
+ getStructuredByType(): {
34
+ buildErrors: StructuredError[];
35
+ typeErrors: StructuredError[];
36
+ lintErrors: StructuredError[];
37
+ runtimeErrors: StructuredError[];
38
+ };
39
+ }
40
+ /**
41
+ * Convert structured error to display string.
42
+ */
43
+ export declare function structuredErrorToString(error: StructuredError): string;
44
+ /**
45
+ * Parse a raw error string into a structured error.
46
+ */
47
+ export declare function parseErrorString(errorStr: string, defaultType?: StructuredError['type']): StructuredError;
48
+ /**
49
+ * Filter non-error messages (Babel notes, CSS at-rule warnings, etc.)
50
+ */
51
+ export declare function filterNonErrors(errors: string[]): string[];