vigthoria-cli 1.8.3 → 1.8.4

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.
@@ -1616,14 +1616,9 @@ class ChatCommand {
1616
1616
  ...runtimeContext,
1617
1617
  onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
1618
1618
  });
1619
- const response = await (rescueEligible
1620
- ? Promise.race([
1621
- workflowPromise,
1622
- new Promise((_, reject) => {
1623
- setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), 3600000);
1624
- }),
1625
- ])
1626
- : workflowPromise);
1619
+ // No hard timeout — SSE stream stays open until the server
1620
+ // sends complete/error/[DONE]. We never cut off a working workflow.
1621
+ const response = await workflowPromise;
1627
1622
  if (spinner) {
1628
1623
  spinner.stop();
1629
1624
  }
package/dist/utils/api.js CHANGED
@@ -89,20 +89,24 @@ function formatCLIError(err) {
89
89
  return `${tag} ${err.message}`;
90
90
  }
91
91
  }
92
+ // SSE-based architecture: NO hard timeouts. Streams stay open until
93
+ // complete/error/disconnect. Liveness is checked via heartbeat events.
94
+ // Set to 0 (disabled) by default. Only use a timeout as an emergency
95
+ // safety net when explicitly configured via env vars.
92
96
  const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
93
- const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '1200000';
97
+ const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '0';
94
98
  const parsed = Number.parseInt(rawValue, 10);
95
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 1200000;
99
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
96
100
  })();
97
101
  const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
98
- const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS || '90000';
102
+ const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS || '0';
99
103
  const parsed = Number.parseInt(rawValue, 10);
100
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 90000;
104
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
101
105
  })();
102
106
  const DEFAULT_OPERATOR_TIMEOUT_MS = (() => {
103
- const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS || '1800000';
107
+ const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS || '0';
104
108
  const parsed = Number.parseInt(rawValue, 10);
105
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 1800000;
109
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
106
110
  })();
107
111
  class APIClient {
108
112
  client;
@@ -2732,7 +2736,6 @@ document.addEventListener('DOMContentLoaded', () => {
2732
2736
  && context.localMachineCapable !== false;
2733
2737
  const rescueEligibleSaaS = preferLocalV3
2734
2738
  && /(saas|dashboard|analytics|billing|team management|activity feed|login screen)/i.test(message);
2735
- const timeoutMs = rescueEligibleSaaS ? Math.min(baseTimeoutMs, 3600000) : baseTimeoutMs;
2736
2739
  const maxAttempts = preferLocalV3 ? 2 : 1;
2737
2740
  let lastErrors = [];
2738
2741
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
@@ -2765,8 +2768,9 @@ document.addEventListener('DOMContentLoaded', () => {
2765
2768
  stream: true,
2766
2769
  };
2767
2770
  for (const baseUrl of this.getV3AgentBaseUrls(preferLocalV3)) {
2771
+ // No hard timeout — SSE stream stays alive until server sends
2772
+ // complete/error/[DONE] or the TCP connection drops.
2768
2773
  const controller = new AbortController();
2769
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
2770
2774
  try {
2771
2775
  const response = await this.executeV3AgentRunRequest(baseUrl, requestBody, requestExecutionContext, controller.signal);
2772
2776
  if (!response.ok) {
@@ -2798,7 +2802,6 @@ document.addEventListener('DOMContentLoaded', () => {
2798
2802
  stream: true,
2799
2803
  };
2800
2804
  const continueController = new AbortController();
2801
- const continueTimeoutId = setTimeout(() => continueController.abort(), timeoutMs);
2802
2805
  try {
2803
2806
  const continueHeaders = await this.getV3AgentHeaders();
2804
2807
  const continueResponse = await fetch(this.getV3AgentContinueUrl(baseUrl), {
@@ -2816,7 +2819,7 @@ document.addEventListener('DOMContentLoaded', () => {
2816
2819
  break; // Fall through to normal completion with partial data
2817
2820
  }
2818
2821
  finally {
2819
- clearTimeout(continueTimeoutId);
2822
+ // no timeout to clear — SSE stream ends naturally
2820
2823
  }
2821
2824
  }
2822
2825
  // Use the final continuation data for workspace recovery
@@ -2872,9 +2875,6 @@ document.addEventListener('DOMContentLoaded', () => {
2872
2875
  }
2873
2876
  errors.push(`${baseUrl}: ${error?.message || String(error)}`);
2874
2877
  }
2875
- finally {
2876
- clearTimeout(timeoutId);
2877
- }
2878
2878
  }
2879
2879
  lastErrors = errors;
2880
2880
  const shouldRetry = attempt < maxAttempts
@@ -2940,7 +2940,6 @@ document.addEventListener('DOMContentLoaded', () => {
2940
2940
  }
2941
2941
  async runOperatorWorkflow(message, context = {}) {
2942
2942
  const executionContext = await this.bindExecutionContext(context);
2943
- const timeoutMs = context.operatorTimeoutMs || DEFAULT_OPERATOR_TIMEOUT_MS;
2944
2943
  const errors = [];
2945
2944
  const authToken = this.config.get('authToken');
2946
2945
  // Collect a lightweight workspace file listing so the operator can
@@ -2948,8 +2947,10 @@ document.addEventListener('DOMContentLoaded', () => {
2948
2947
  const workspacePath = executionContext.workspacePath || executionContext.projectPath || executionContext.targetPath || process.cwd();
2949
2948
  const workspaceSummary = this.buildLocalWorkspaceSummary(workspacePath);
2950
2949
  for (const baseUrl of this.getOperatorBaseUrls()) {
2950
+ // No hard timeout — SSE stream stays open until result/error/disconnect.
2951
+ // BMAD sends heartbeat events every 15s; if the TCP connection drops,
2952
+ // the fetch will throw naturally.
2951
2953
  const controller = new AbortController();
2952
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
2953
2954
  try {
2954
2955
  const response = await fetch(this.getOperatorStreamUrl(baseUrl), {
2955
2956
  method: 'POST',
@@ -3088,16 +3089,8 @@ document.addEventListener('DOMContentLoaded', () => {
3088
3089
  };
3089
3090
  }
3090
3091
  catch (error) {
3091
- const isAbort = error?.name === 'AbortError' || error?.code === 'ABORT_ERR';
3092
- if (isAbort) {
3093
- const mins = Math.round(timeoutMs / 60000);
3094
- throw new CLIError(`Operator workflow timed out after ${mins} minute(s). You can increase the timeout with VIGTHORIA_OPERATOR_TIMEOUT_MS.`, 'timeout', error);
3095
- }
3096
3092
  errors.push(`${baseUrl}: ${error?.message || String(error)}`);
3097
3093
  }
3098
- finally {
3099
- clearTimeout(timeoutId);
3100
- }
3101
3094
  }
3102
3095
  throw new CLIError(`Operator workflow failed on all endpoints: ${errors.join(' | ')}`, 'model_backend');
3103
3096
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.8.3",
3
+ "version": "1.8.4",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "main": "dist/index.js",
6
6
  "files": [