vigthoria-cli 1.8.15 → 1.8.19

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.
@@ -118,8 +118,7 @@ export declare class ChatCommand {
118
118
  private runLocalAgentLoop;
119
119
  private tryDirectSingleFileFlow;
120
120
  private tryV3AgentWorkflow;
121
- private isSaaSRescuePrompt;
122
- private tryCommandLevelSaaSRescue;
121
+ private tryRecoverV3ServiceAndRetry;
123
122
  private startInteractiveChat;
124
123
  private showHelp;
125
124
  private showContext;
@@ -494,6 +494,43 @@ class ChatCommand {
494
494
  spinner.text = status === 'planning' ? 'Planning...' : 'Executing plan...';
495
495
  return;
496
496
  }
497
+ if (event.type === 'executor_start') {
498
+ if (spinner.isSpinning)
499
+ spinner.stop();
500
+ process.stderr.write(chalk_1.default.cyan(' [Executor] ') + `Starting ${event.task_id || 'task'}${event.title ? ` - ${event.title}` : ''}
501
+ `);
502
+ spinner.start();
503
+ spinner.text = 'Vigthoria Executor running...';
504
+ return;
505
+ }
506
+ if (event.type === 'executor_error') {
507
+ if (spinner.isSpinning)
508
+ spinner.stop();
509
+ const msg = (0, api_js_1.sanitizeUserFacingErrorText)(String(event.error || 'Executor error')) || 'Executor error';
510
+ process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor encountered an issue: ${msg}
511
+ `);
512
+ spinner.start();
513
+ spinner.text = 'Recovering executor...';
514
+ return;
515
+ }
516
+ if (event.type === 'executor_complete') {
517
+ if (spinner.isSpinning)
518
+ spinner.stop();
519
+ const summary = event.summary || {};
520
+ const status = String(summary.status || 'completed');
521
+ const changed = Array.isArray(summary.changed_files) ? summary.changed_files.length : 0;
522
+ if (status === 'failed') {
523
+ process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor task failed${summary.task_id ? ` (${summary.task_id})` : ''}.
524
+ `);
525
+ }
526
+ else {
527
+ process.stderr.write(chalk_1.default.green(' [Executor] ') + `Task completed${summary.task_id ? ` (${summary.task_id})` : ''}${changed ? `, ${changed} files changed` : ''}.
528
+ `);
529
+ }
530
+ spinner.start();
531
+ spinner.text = 'Continuing plan...';
532
+ return;
533
+ }
497
534
  if (event.type === 'file_mutation') {
498
535
  const rawPath = typeof event.path === 'string' ? this.sanitizeServerPath(event.path) : '';
499
536
  const filePath = rawPath ? rawPath.replace(/\\/g, '/').split('/').slice(-2).join('/') : '';
@@ -516,7 +553,18 @@ class ChatCommand {
516
553
  else {
517
554
  if (spinner.isSpinning)
518
555
  spinner.stop();
519
- process.stderr.write(chalk_1.default.red(' [Error] ') + (event.message || 'Agent error') + '\n');
556
+ const message = (0, api_js_1.sanitizeUserFacingErrorText)(String(event.message || 'Agent error')) || 'Agent error';
557
+ const plannerLike = /plan|planner|dependency graph/i.test(message);
558
+ const executorLike = /executor|task failed|iteration/i.test(message);
559
+ if (plannerLike) {
560
+ process.stderr.write(chalk_1.default.red(' [Planner] ') + `Vigthoria Planner encountered an issue: ${message}\n`);
561
+ }
562
+ else if (executorLike) {
563
+ process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor encountered an issue: ${message}\n`);
564
+ }
565
+ else {
566
+ process.stderr.write(chalk_1.default.red(' [Error] ') + message + '\n');
567
+ }
520
568
  }
521
569
  return;
522
570
  }
@@ -1612,7 +1660,6 @@ class ChatCommand {
1612
1660
  async tryV3AgentWorkflow(prompt) {
1613
1661
  const runtimeContext = await this.getPromptRuntimeContext(prompt);
1614
1662
  const routingPolicy = this.resolveAgentExecutionPolicy(prompt);
1615
- const rescueEligible = this.isSaaSRescuePrompt(prompt);
1616
1663
  // Reset streaming counters for new workflow
1617
1664
  this.v3IterationCount = 0;
1618
1665
  this.v3ToolCallCount = 0;
@@ -1660,14 +1707,7 @@ class ChatCommand {
1660
1707
  ...runtimeContext,
1661
1708
  onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
1662
1709
  });
1663
- const response = await (rescueEligible && DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS > 0
1664
- ? Promise.race([
1665
- workflowPromise,
1666
- new Promise((_, reject) => {
1667
- setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS);
1668
- }),
1669
- ])
1670
- : workflowPromise);
1710
+ const response = await workflowPromise;
1671
1711
  if (spinner) {
1672
1712
  spinner.stop();
1673
1713
  }
@@ -1773,9 +1813,9 @@ class ChatCommand {
1773
1813
  }
1774
1814
  catch (error) {
1775
1815
  watcher?.stop();
1776
- if (rescueEligible && !this.api.hasAgentWorkspaceOutput(workspaceContext)) {
1777
- const rescued = await this.tryCommandLevelSaaSRescue(executionPrompt, prompt, workspaceContext, routingPolicy, spinner, error);
1778
- if (rescued) {
1816
+ if (!this.api.hasAgentWorkspaceOutput(workspaceContext)) {
1817
+ const recovered = await this.tryRecoverV3ServiceAndRetry(executionPrompt, prompt, workspaceContext, routingPolicy, spinner, error);
1818
+ if (recovered) {
1779
1819
  return true;
1780
1820
  }
1781
1821
  }
@@ -1811,60 +1851,67 @@ class ChatCommand {
1811
1851
  return true;
1812
1852
  }
1813
1853
  }
1814
- isSaaSRescuePrompt(prompt) {
1815
- return /(saas|dashboard|analytics|billing|team management|activity feed|login screen)/i.test(prompt);
1816
- }
1817
- async tryCommandLevelSaaSRescue(executionPrompt, rawPrompt, workspaceContext, routingPolicy, spinner, error) {
1818
- const apiAny = this.api;
1819
- if (typeof apiAny.materializeEmergencySaaSWorkspace !== 'function') {
1854
+ async tryRecoverV3ServiceAndRetry(executionPrompt, rawPrompt, workspaceContext, routingPolicy, spinner, error) {
1855
+ const recovery = await this.api.attemptV3ServiceRecovery((error && error.message) || '');
1856
+ if (!recovery.recovered) {
1820
1857
  return false;
1821
1858
  }
1822
- const appName = apiAny.materializeEmergencySaaSWorkspace(executionPrompt, workspaceContext);
1823
- if (!appName) {
1824
- return false;
1825
- }
1826
- if (typeof apiAny.ensureAgentFrontendPolish === 'function') {
1827
- await apiAny.ensureAgentFrontendPolish(executionPrompt, workspaceContext);
1828
- }
1829
- const previewGate = await this.api.runTemplateServicePreviewGate(executionPrompt, {
1830
- ...workspaceContext,
1831
- rawPrompt,
1832
- });
1833
- if (spinner) {
1859
+ if (spinner && spinner.isSpinning) {
1834
1860
  spinner.stop();
1835
1861
  }
1836
- const rescueMessage = `Recovered a local SaaS workspace scaffold for ${appName} after the V3 workflow stalled without writing files.`;
1837
- if (this.jsonOutput) {
1838
- console.log(JSON.stringify({
1839
- success: true,
1840
- mode: 'agent',
1841
- model: routingPolicy.selectedModel,
1842
- routingPolicy,
1843
- taskId: null,
1844
- contextId: null,
1845
- partial: true,
1846
- content: rescueMessage,
1847
- metadata: {
1848
- source: 'cli-saas-rescue',
1849
- previewGate,
1850
- rescueReason: error.message,
1851
- },
1852
- }, null, 2));
1862
+ if (!this.jsonOutput) {
1863
+ console.log(chalk_1.default.yellow(`V3 recovery: ${recovery.message} Retrying once...`));
1853
1864
  }
1854
- else {
1855
- console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
1856
- console.log(rescueMessage);
1857
- if (previewGate.required) {
1858
- if (previewGate.passed) {
1859
- console.log(chalk_1.default.gray(`Template Service preview gate: passed via ${previewGate.backendUrl || 'unknown backend'}`));
1860
- }
1861
- else {
1862
- console.log(chalk_1.default.yellow(`Template Service preview gate: failed${previewGate.error ? ` - ${previewGate.error}` : ''}`));
1863
- }
1865
+ this.v3IterationCount = 0;
1866
+ this.v3ToolCallCount = 0;
1867
+ this.v3LastActivity = Date.now();
1868
+ this.v3StreamingStarted = false;
1869
+ try {
1870
+ const retryResponse = await this.api.runV3AgentWorkflow(executionPrompt, {
1871
+ workspace: { path: this.currentProjectPath },
1872
+ ...workspaceContext,
1873
+ executionSurface: 'cli',
1874
+ clientSurface: 'cli',
1875
+ localMachineCapable: true,
1876
+ agentTimeoutMs: DEFAULT_V3_AGENT_TIMEOUT_MS,
1877
+ agentIdleTimeoutMs: DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS,
1878
+ model: routingPolicy.selectedModel,
1879
+ requestedModel: this.currentModel,
1880
+ agentExecutionPolicy: routingPolicy,
1881
+ legacyFallbackAllowed: this.isLegacyAgentFallbackAllowed(),
1882
+ rawPrompt,
1883
+ history: this.getMessagesForModel(),
1884
+ onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
1885
+ });
1886
+ if (spinner && spinner.isSpinning) {
1887
+ spinner.stop();
1888
+ }
1889
+ if (this.v3StreamingStarted) {
1890
+ process.stdout.write('\n');
1891
+ }
1892
+ if (this.jsonOutput) {
1893
+ console.log(JSON.stringify({
1894
+ success: true,
1895
+ mode: 'agent',
1896
+ model: routingPolicy.selectedModel,
1897
+ routingPolicy,
1898
+ taskId: retryResponse.taskId || null,
1899
+ contextId: retryResponse.contextId || null,
1900
+ partial: retryResponse.partial === true,
1901
+ content: retryResponse.content || 'V3 agent workflow completed after recovery.',
1902
+ metadata: { ...(retryResponse.metadata || {}), recoveryAttempted: true },
1903
+ }, null, 2));
1904
+ }
1905
+ else if (!this.v3StreamingStarted && retryResponse.content) {
1906
+ console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
1907
+ console.log(retryResponse.content);
1864
1908
  }
1909
+ this.messages.push({ role: 'assistant', content: retryResponse.content || 'V3 agent workflow completed after recovery.' });
1910
+ return true;
1911
+ }
1912
+ catch {
1913
+ return false;
1865
1914
  }
1866
- this.messages.push({ role: 'assistant', content: rescueMessage });
1867
- return true;
1868
1915
  }
1869
1916
  async startInteractiveChat() {
1870
1917
  const chatTitle = this.operatorMode
package/dist/index.js CHANGED
@@ -77,6 +77,9 @@ const logger_js_1 = require("./utils/logger.js");
77
77
  const chalk_1 = __importDefault(require("chalk"));
78
78
  const fs = __importStar(require("fs"));
79
79
  const path = __importStar(require("path"));
80
+ const os = __importStar(require("os"));
81
+ const crypto_1 = require("crypto");
82
+ const axios_1 = __importDefault(require("axios"));
80
83
  function getInvokedBinaryName() {
81
84
  const executable = process.argv[1] || 'vigthoria';
82
85
  return path.basename(executable, path.extname(executable)).toLowerCase();
@@ -107,6 +110,7 @@ function getVersion() {
107
110
  return '1.6.27';
108
111
  }
109
112
  const VERSION = getVersion();
113
+ const VIGTHORIA_DEFAULT_MANIFEST_URL = process.env.VIGTHORIA_UPDATE_MANIFEST_URL || "https://coder.vigthoria.io/releases/manifest.json";
110
114
  /**
111
115
  * Compare semantic versions properly
112
116
  * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
@@ -124,6 +128,40 @@ function compareVersions(v1, v2) {
124
128
  }
125
129
  return 0;
126
130
  }
131
+ function resolveManifestEntry(manifest, channel) {
132
+ const normalized = String(channel || 'stable').trim() || 'stable';
133
+ if (manifest.channels && manifest.channels[normalized]) {
134
+ return manifest.channels[normalized];
135
+ }
136
+ const direct = manifest[normalized];
137
+ if (direct && typeof direct === 'object') {
138
+ return direct;
139
+ }
140
+ if (normalized === 'stable') {
141
+ const rootVersion = typeof manifest.version === 'string' ? manifest.version : '';
142
+ const rootUrl = typeof manifest.url === 'string' ? manifest.url : '';
143
+ const rootSha = typeof manifest.sha256 === 'string' ? manifest.sha256 : undefined;
144
+ if (rootVersion && rootUrl) {
145
+ return { version: rootVersion, url: rootUrl, sha256: rootSha };
146
+ }
147
+ }
148
+ return null;
149
+ }
150
+ async function downloadFile(url, targetPath) {
151
+ const response = await axios_1.default.get(url, {
152
+ responseType: 'arraybuffer',
153
+ timeout: 20000,
154
+ maxRedirects: 5,
155
+ validateStatus: (status) => status >= 200 && status < 300,
156
+ });
157
+ fs.writeFileSync(targetPath, Buffer.from(response.data));
158
+ }
159
+ function sha256File(filePath) {
160
+ const hash = (0, crypto_1.createHash)('sha256');
161
+ const data = fs.readFileSync(filePath);
162
+ hash.update(data);
163
+ return hash.digest('hex');
164
+ }
127
165
  // Check for updates silently on startup (non-blocking)
128
166
  async function checkForUpdatesQuietly() {
129
167
  try {
@@ -821,11 +859,111 @@ Examples:
821
859
  program
822
860
  .command('update')
823
861
  .alias('upgrade')
824
- .description('Check for updates and upgrade Vigthoria CLI')
862
+ .description('Check for updates and upgrade Vigthoria CLI. Default manifest: https://coder.vigthoria.io/releases/manifest.json')
825
863
  .option('-c, --check', 'Only check for updates, don\'t install')
864
+ .option('-f, --from <target>', 'Install update from npm spec, local .tgz path, or URL')
865
+ .option('-m, --manifest <url>', 'Update manifest URL for server-driven releases')
866
+ .option('--channel <name>', 'Release channel to use from manifest (default: stable)', 'stable')
867
+ .option('--allow-downgrade', 'Allow installing an older version from custom update source')
826
868
  .action(async (options) => {
827
- const { execSync } = await import('child_process');
828
- console.log(chalk_1.default.cyan('🔍 Checking for updates...'));
869
+ const { execSync, execFileSync } = await import('child_process');
870
+ const updateTarget = typeof options.from === 'string' ? options.from.trim() : '';
871
+ const manifestUrl = typeof options.manifest === 'string' ? options.manifest.trim() : VIGTHORIA_DEFAULT_MANIFEST_URL.trim();
872
+ const channel = typeof options.channel === 'string' ? options.channel.trim() : 'stable';
873
+ const allowDowngrade = !!options.allowDowngrade;
874
+ if (updateTarget) {
875
+ try {
876
+ if (options.check) {
877
+ console.log(chalk_1.default.cyan(`Update source configured: ${updateTarget}`));
878
+ console.log(chalk_1.default.gray('Run `vigthoria update --from <target>` to install from this source'));
879
+ return;
880
+ }
881
+ console.log(chalk_1.default.cyan(`Installing update from ${updateTarget}...`));
882
+ execFileSync('npm', ['install', '-g', updateTarget], {
883
+ stdio: 'inherit',
884
+ windowsHide: true,
885
+ });
886
+ console.log(chalk_1.default.green('Update installed successfully'));
887
+ console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
888
+ return;
889
+ }
890
+ catch (error) {
891
+ console.error(chalk_1.default.red('Failed to install update from target:'), error.message);
892
+ console.log(chalk_1.default.gray(`Try manually: npm install -g ${updateTarget}`));
893
+ return;
894
+ }
895
+ }
896
+ if (manifestUrl) {
897
+ try {
898
+ console.log(chalk_1.default.cyan(`Checking manifest channel ${channel}...`));
899
+ const response = await axios_1.default.get(manifestUrl, {
900
+ timeout: 10000,
901
+ maxRedirects: 5,
902
+ validateStatus: (status) => status >= 200 && status < 300,
903
+ });
904
+ const entry = resolveManifestEntry(response.data || {}, channel);
905
+ if (!entry || !entry.version || !entry.url) {
906
+ console.error(chalk_1.default.red(`Manifest missing valid release entry for channel: ${channel}`));
907
+ console.log(chalk_1.default.gray('Expected: channels.<channel>.version and channels.<channel>.url'));
908
+ return;
909
+ }
910
+ const currentVersion = VERSION;
911
+ const comparison = compareVersions(entry.version, currentVersion);
912
+ if (!allowDowngrade && comparison <= 0) {
913
+ console.log(chalk_1.default.green(`You are running the latest version for channel ${channel} (${currentVersion})`));
914
+ return;
915
+ }
916
+ console.log(chalk_1.default.yellow(`Update available from manifest: ${currentVersion} -> ${entry.version} (${channel})`));
917
+ if (entry.notes) {
918
+ console.log(chalk_1.default.gray(` ${entry.notes}`));
919
+ }
920
+ if (options.check) {
921
+ console.log(chalk_1.default.gray(`Install with: vigthoria update --manifest ${manifestUrl} --channel ${channel}`));
922
+ return;
923
+ }
924
+ const tmpFile = path.join(os.tmpdir(), `vigthoria-update-${Date.now()}.tgz`);
925
+ try {
926
+ console.log(chalk_1.default.cyan('Downloading release package...'));
927
+ await downloadFile(entry.url, tmpFile);
928
+ if (entry.sha256) {
929
+ const expected = entry.sha256.toLowerCase();
930
+ const actual = sha256File(tmpFile).toLowerCase();
931
+ if (actual !== expected) {
932
+ console.error(chalk_1.default.red('Release checksum verification failed'));
933
+ console.error(chalk_1.default.red(`Expected: ${expected}`));
934
+ console.error(chalk_1.default.red(`Actual: ${actual}`));
935
+ return;
936
+ }
937
+ console.log(chalk_1.default.green('Checksum verification passed'));
938
+ }
939
+ else {
940
+ console.log(chalk_1.default.yellow('Manifest entry has no sha256; install proceeded without checksum verification'));
941
+ }
942
+ console.log(chalk_1.default.cyan('Installing update...'));
943
+ execFileSync('npm', ['install', '-g', tmpFile], {
944
+ stdio: 'inherit',
945
+ windowsHide: true,
946
+ });
947
+ console.log(chalk_1.default.green(`Updated to version ${entry.version}`));
948
+ console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
949
+ return;
950
+ }
951
+ finally {
952
+ if (fs.existsSync(tmpFile)) {
953
+ try {
954
+ fs.unlinkSync(tmpFile);
955
+ }
956
+ catch { }
957
+ }
958
+ }
959
+ }
960
+ catch (error) {
961
+ console.error(chalk_1.default.red('Failed to process manifest update:'), error.message);
962
+ console.log(chalk_1.default.gray('You can still update via npm: npm install -g vigthoria-cli@latest'));
963
+ return;
964
+ }
965
+ }
966
+ console.log(chalk_1.default.cyan('Checking for updates...'));
829
967
  try {
830
968
  // Get latest version from npm - cross-platform
831
969
  const latestVersion = execSync('npm view vigthoria-cli version', {
@@ -837,21 +975,21 @@ Examples:
837
975
  // Use semantic version comparison (1.6.0 > 1.5.9)
838
976
  const comparison = compareVersions(latestVersion, currentVersion);
839
977
  if (comparison <= 0) {
840
- console.log(chalk_1.default.green(`✅ You are running the latest version (${currentVersion})`));
978
+ console.log(chalk_1.default.green(`You are running the latest version (${currentVersion})`));
841
979
  return;
842
980
  }
843
- console.log(chalk_1.default.yellow(`📦 Update available: ${currentVersion} ${latestVersion}`));
981
+ console.log(chalk_1.default.yellow(`Update available: ${currentVersion} -> ${latestVersion}`));
844
982
  if (options.check) {
845
983
  console.log(chalk_1.default.gray('Run `vigthoria update` to install the update'));
846
984
  return;
847
985
  }
848
- console.log(chalk_1.default.cyan('📥 Installing update...'));
986
+ console.log(chalk_1.default.cyan('Installing update...'));
849
987
  execSync('npm install -g vigthoria-cli@latest', { stdio: 'inherit' });
850
- console.log(chalk_1.default.green(`✅ Updated to version ${latestVersion}`));
988
+ console.log(chalk_1.default.green(`Updated to version ${latestVersion}`));
851
989
  console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
852
990
  }
853
991
  catch (error) {
854
- console.error(chalk_1.default.red('Failed to check for updates:'), error.message);
992
+ console.error(chalk_1.default.red('Failed to check for updates:'), error.message);
855
993
  console.log(chalk_1.default.gray('Try manually: npm install -g vigthoria-cli@latest'));
856
994
  }
857
995
  });
@@ -19,6 +19,9 @@ export declare class CLIError extends Error {
19
19
  export declare function classifyError(error: unknown, fallbackCategory?: CLIErrorCategory): CLIError;
20
20
  /** Format a CLIError for user-facing display. */
21
21
  export declare function formatCLIError(err: CLIError): string;
22
+ export declare function sanitizeUserFacingErrorText(input: string): string;
23
+ export declare function isServerRuntime(): boolean;
24
+ export declare function describeUpstreamStatus(status: number): string;
22
25
  export interface ChatMessage {
23
26
  role: 'user' | 'assistant' | 'system';
24
27
  content: string;
@@ -39,8 +42,8 @@ export interface V3AgentWorkflowResponse {
39
42
  contextId?: string | null;
40
43
  backendUrl: string;
41
44
  partial?: boolean;
42
- changedFiles?: Record<string, string>;
43
45
  metadata?: Record<string, unknown>;
46
+ changedFiles?: Record<string, string>;
44
47
  }
45
48
  export interface FrontendPreviewGateResult {
46
49
  required: boolean;
@@ -186,9 +189,6 @@ export interface VigthoriUser {
186
189
  adminAccess: boolean;
187
190
  };
188
191
  }
189
- export declare function sanitizeUserFacingErrorText(input: string): string;
190
- export declare function isServerRuntime(): boolean;
191
- export declare function describeUpstreamStatus(status: number): string;
192
192
  export declare class APIClient {
193
193
  private client;
194
194
  private modelRouterClient;
@@ -197,18 +197,12 @@ export declare class APIClient {
197
197
  private logger;
198
198
  private ws;
199
199
  private vigFlowTokens;
200
- private _httpsAgent;
201
200
  constructor(config: Config, logger: Logger);
202
- /**
203
- * Destroy keep-alive sockets so the Node.js event loop can drain
204
- * naturally. Call this before exiting commands that run HTTP probes
205
- * (e.g. `status`) to avoid the libuv UV_HANDLE_CLOSING assertion
206
- * on Windows / Node 25+.
207
- */
208
201
  destroy(): void;
209
202
  private getSelfHostedModelsApiUrl;
210
203
  login(email: string, password: string): Promise<boolean>;
211
204
  loginWithToken(token: string): Promise<boolean>;
205
+ private decodeJwtPayload;
212
206
  private extractUserProfile;
213
207
  private refreshToken;
214
208
  getSubscriptionStatus(): Promise<void>;
@@ -292,7 +286,6 @@ export declare class APIClient {
292
286
  private compactV3Context;
293
287
  buildMinimalV3AgentContext(context?: Record<string, any>): string;
294
288
  private extractEmergencyAppName;
295
- private materializeEmergencySaaSWorkspace;
296
289
  private ensureExecutionContext;
297
290
  bindExecutionContext(context?: Record<string, any>): Promise<Record<string, any>>;
298
291
  private resolveAgentTargetPath;
@@ -363,11 +356,6 @@ export declare class APIClient {
363
356
  * Ensure code has balanced curly braces by appending missing closing braces.
364
357
  */
365
358
  private ensureBalancedBraces;
366
- /**
367
- * Quick JS/TS syntax validation using Node's built-in parser.
368
- * Returns true if the code parses without errors.
369
- */
370
- private validateJsSyntax;
371
359
  /**
372
360
  * Extract the first complete function/class from code.
373
361
  * Used as last-resort when the model keeps over-producing.
@@ -455,6 +443,14 @@ export declare class APIClient {
455
443
  private getCoderHealth;
456
444
  private getModelsHealth;
457
445
  private getSelfHostedHealth;
446
+ attemptV3ServiceRecovery(reason?: string, options?: {
447
+ attempts?: number;
448
+ delayMs?: number;
449
+ }): Promise<{
450
+ recovered: boolean;
451
+ message: string;
452
+ endpoint?: string;
453
+ }>;
458
454
  private getV3AgentHealth;
459
455
  private getHyperLoopHealth;
460
456
  private getRepoMemoryHealth;