vigthoria-cli 1.8.7 → 1.8.8

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.
@@ -49,9 +49,28 @@ const session_js_1 = require("../utils/session.js");
49
49
  const bridge_client_js_1 = require("../utils/bridge-client.js");
50
50
  const workspace_stream_js_1 = require("../utils/workspace-stream.js");
51
51
  const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
52
- const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '3900000';
52
+ const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS;
53
+ if (!rawValue) {
54
+ return 0;
55
+ }
56
+ const parsed = Number.parseInt(rawValue, 10);
57
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
58
+ })();
59
+ const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
60
+ const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS;
61
+ if (!rawValue) {
62
+ return 0;
63
+ }
64
+ const parsed = Number.parseInt(rawValue, 10);
65
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
66
+ })();
67
+ const DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS = (() => {
68
+ const rawValue = process.env.VIGTHORIA_AGENT_SOFT_TIMEOUT_MS || process.env.V3_AGENT_SOFT_TIMEOUT_MS;
69
+ if (!rawValue) {
70
+ return 0;
71
+ }
53
72
  const parsed = Number.parseInt(rawValue, 10);
54
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 3900000;
73
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
55
74
  })();
56
75
  class ChatCommand {
57
76
  config;
@@ -122,13 +141,9 @@ class ChatCommand {
122
141
  return this.getDefaultChatModel();
123
142
  }
124
143
  isLegacyAgentFallbackAllowed() {
125
- // CLI always has local file access, so fallback to local agent loop
126
- // is safe and should be the default when V3 agent is unreachable or
127
- // rejects the request (e.g. context too large).
128
- if (process.env.VIGTHORIA_ALLOW_LEGACY_AGENT_FALLBACK === '0') {
129
- return false;
130
- }
131
- return true;
144
+ // Hosted V3 Agent Mode must fail loudly by default so clients do not silently drop into legacy mode.
145
+ // Operators can still opt in during emergency local debugging.
146
+ return process.env.VIGTHORIA_ALLOW_LEGACY_AGENT_FALLBACK === '1';
132
147
  }
133
148
  resolveAgentExecutionPolicy(prompt) {
134
149
  const explicitModel = this.modelExplicitlySelected;
@@ -1624,7 +1639,7 @@ class ChatCommand {
1624
1639
  clientSurface: 'cli',
1625
1640
  localMachineCapable: true,
1626
1641
  agentTimeoutMs: DEFAULT_V3_AGENT_TIMEOUT_MS,
1627
- agentIdleTimeoutMs: 90000,
1642
+ agentIdleTimeoutMs: DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS,
1628
1643
  model: routingPolicy.selectedModel,
1629
1644
  requestedModel: this.currentModel,
1630
1645
  agentExecutionPolicy: routingPolicy,
@@ -1634,11 +1649,11 @@ class ChatCommand {
1634
1649
  ...runtimeContext,
1635
1650
  onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
1636
1651
  });
1637
- const response = await (rescueEligible
1652
+ const response = await (rescueEligible && DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS > 0
1638
1653
  ? Promise.race([
1639
1654
  workflowPromise,
1640
1655
  new Promise((_, reject) => {
1641
- setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), 240000);
1656
+ setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS);
1642
1657
  }),
1643
1658
  ])
1644
1659
  : workflowPromise);
package/dist/utils/api.js CHANGED
@@ -90,19 +90,31 @@ function formatCLIError(err) {
90
90
  }
91
91
  }
92
92
  const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
93
- const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '1200000';
93
+ const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS;
94
+ if (!rawValue) {
95
+ // No total timeout by default for long-running SSE agent workflows.
96
+ return 0;
97
+ }
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;
103
+ if (!rawValue) {
104
+ // Keep stream open indefinitely unless user configures an idle limit.
105
+ return 0;
106
+ }
99
107
  const parsed = Number.parseInt(rawValue, 10);
100
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 90000;
108
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
101
109
  })();
102
110
  const DEFAULT_OPERATOR_TIMEOUT_MS = (() => {
103
- const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS || '300000';
111
+ const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS;
112
+ if (!rawValue) {
113
+ // BMAD/operator flows can be long-running; do not cap by default.
114
+ return 0;
115
+ }
104
116
  const parsed = Number.parseInt(rawValue, 10);
105
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 300000;
117
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
106
118
  })();
107
119
  class APIClient {
108
120
  client;
@@ -2122,6 +2134,11 @@ menu {
2122
2134
  if (!looksLikeFrontendTask) {
2123
2135
  return;
2124
2136
  }
2137
+ // Skip motion/scroll enhancements for games — they use canvas, not section-based layouts
2138
+ const looksLikeGame = /\bgame\b|arcade|pac.?man|tetris|platformer|roguelike|breakout|pong|snake\s+game|tower\s+defense|playable/i.test(prompt);
2139
+ if (looksLikeGame) {
2140
+ return;
2141
+ }
2125
2142
  const htmlPath = path_1.default.join(rootPath, 'index.html');
2126
2143
  if (!fs_1.default.existsSync(htmlPath)) {
2127
2144
  return;
@@ -2568,7 +2585,7 @@ document.addEventListener('DOMContentLoaded', () => {
2568
2585
  let contextId = response.headers.get('x-context-id') || String(context.contextId || '').trim() || null;
2569
2586
  let serverWorkspaceRoot = null;
2570
2587
  const streamedFiles = {};
2571
- const idleTimeoutMs = context.agentIdleTimeoutMs || DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS;
2588
+ const idleTimeoutMs = context.agentIdleTimeoutMs ?? DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS;
2572
2589
  while (true) {
2573
2590
  let chunk;
2574
2591
  try {
@@ -2724,15 +2741,13 @@ document.addEventListener('DOMContentLoaded', () => {
2724
2741
  }
2725
2742
  async runV3AgentWorkflow(message, context = {}) {
2726
2743
  const executionContext = await this.bindExecutionContext(context);
2727
- const baseTimeoutMs = executionContext.agentTimeoutMs || DEFAULT_V3_AGENT_TIMEOUT_MS;
2744
+ const baseTimeoutMs = executionContext.agentTimeoutMs ?? DEFAULT_V3_AGENT_TIMEOUT_MS;
2728
2745
  const expectedFiles = this.extractExpectedWorkspaceFiles(message, executionContext);
2729
2746
  const requestedModel = String(executionContext.model || executionContext.requestedModel || 'agent');
2730
2747
  const resolvedModel = this.resolvePermittedModelId(requestedModel);
2731
2748
  const preferLocalV3 = /(premium|polished|landing|site|page|dashboard|saas|frontend|ui|responsive|animated|create the required project files and write them to the workspace)/i.test(message)
2732
2749
  && context.localMachineCapable !== false;
2733
- const rescueEligibleSaaS = preferLocalV3
2734
- && /(saas|dashboard|analytics|billing|team management|activity feed|login screen)/i.test(message);
2735
- const timeoutMs = rescueEligibleSaaS ? Math.min(baseTimeoutMs, 210000) : baseTimeoutMs;
2750
+ const timeoutMs = baseTimeoutMs;
2736
2751
  const maxAttempts = preferLocalV3 ? 2 : 1;
2737
2752
  let lastErrors = [];
2738
2753
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
@@ -2766,7 +2781,7 @@ document.addEventListener('DOMContentLoaded', () => {
2766
2781
  };
2767
2782
  for (const baseUrl of this.getV3AgentBaseUrls(preferLocalV3)) {
2768
2783
  const controller = new AbortController();
2769
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
2784
+ const timeoutId = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
2770
2785
  try {
2771
2786
  const response = await this.executeV3AgentRunRequest(baseUrl, requestBody, requestExecutionContext, controller.signal);
2772
2787
  if (!response.ok) {
@@ -2798,7 +2813,7 @@ document.addEventListener('DOMContentLoaded', () => {
2798
2813
  stream: true,
2799
2814
  };
2800
2815
  const continueController = new AbortController();
2801
- const continueTimeoutId = setTimeout(() => continueController.abort(), timeoutMs);
2816
+ const continueTimeoutId = timeoutMs > 0 ? setTimeout(() => continueController.abort(), timeoutMs) : null;
2802
2817
  try {
2803
2818
  const continueHeaders = await this.getV3AgentHeaders();
2804
2819
  const continueResponse = await fetch(this.getV3AgentContinueUrl(baseUrl), {
@@ -2816,7 +2831,9 @@ document.addEventListener('DOMContentLoaded', () => {
2816
2831
  break; // Fall through to normal completion with partial data
2817
2832
  }
2818
2833
  finally {
2819
- clearTimeout(continueTimeoutId);
2834
+ if (continueTimeoutId) {
2835
+ clearTimeout(continueTimeoutId);
2836
+ }
2820
2837
  }
2821
2838
  }
2822
2839
  // Use the final continuation data for workspace recovery
@@ -2873,7 +2890,9 @@ document.addEventListener('DOMContentLoaded', () => {
2873
2890
  errors.push(`${baseUrl}: ${error?.message || String(error)}`);
2874
2891
  }
2875
2892
  finally {
2876
- clearTimeout(timeoutId);
2893
+ if (timeoutId) {
2894
+ clearTimeout(timeoutId);
2895
+ }
2877
2896
  }
2878
2897
  }
2879
2898
  lastErrors = errors;
@@ -2940,7 +2959,7 @@ document.addEventListener('DOMContentLoaded', () => {
2940
2959
  }
2941
2960
  async runOperatorWorkflow(message, context = {}) {
2942
2961
  const executionContext = await this.bindExecutionContext(context);
2943
- const timeoutMs = context.operatorTimeoutMs || DEFAULT_OPERATOR_TIMEOUT_MS;
2962
+ const timeoutMs = context.operatorTimeoutMs ?? DEFAULT_OPERATOR_TIMEOUT_MS;
2944
2963
  const errors = [];
2945
2964
  const authToken = this.config.get('authToken');
2946
2965
  // Collect a lightweight workspace file listing so the operator can
@@ -2949,7 +2968,7 @@ document.addEventListener('DOMContentLoaded', () => {
2949
2968
  const workspaceSummary = this.buildLocalWorkspaceSummary(workspacePath);
2950
2969
  for (const baseUrl of this.getOperatorBaseUrls()) {
2951
2970
  const controller = new AbortController();
2952
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
2971
+ const timeoutId = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
2953
2972
  try {
2954
2973
  const response = await fetch(this.getOperatorStreamUrl(baseUrl), {
2955
2974
  method: 'POST',
@@ -3096,7 +3115,9 @@ document.addEventListener('DOMContentLoaded', () => {
3096
3115
  errors.push(`${baseUrl}: ${error?.message || String(error)}`);
3097
3116
  }
3098
3117
  finally {
3099
- clearTimeout(timeoutId);
3118
+ if (timeoutId) {
3119
+ clearTimeout(timeoutId);
3120
+ }
3100
3121
  }
3101
3122
  }
3102
3123
  throw new CLIError(`Operator workflow failed on all endpoints: ${errors.join(' | ')}`, 'model_backend');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.8.7",
3
+ "version": "1.8.8",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "main": "dist/index.js",
6
6
  "files": [