vigthoria-cli 1.6.15 → 1.6.16
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/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.js +65 -11
- package/dist/utils/api.d.ts +1 -0
- package/dist/utils/api.js +81 -2
- package/package.json +1 -1
package/dist/commands/chat.d.ts
CHANGED
|
@@ -50,6 +50,9 @@ export declare class ChatCommand {
|
|
|
50
50
|
private buildTaskShapingInstructions;
|
|
51
51
|
private buildExecutionPrompt;
|
|
52
52
|
private getPromptRuntimeContext;
|
|
53
|
+
private v3IterationCount;
|
|
54
|
+
private v3ToolCallCount;
|
|
55
|
+
private v3LastActivity;
|
|
53
56
|
private describeV3AgentTool;
|
|
54
57
|
private updateV3AgentSpinner;
|
|
55
58
|
private updateOperatorSpinner;
|
package/dist/commands/chat.js
CHANGED
|
@@ -47,9 +47,9 @@ const api_js_1 = require("../utils/api.js");
|
|
|
47
47
|
const tools_js_1 = require("../utils/tools.js");
|
|
48
48
|
const session_js_1 = require("../utils/session.js");
|
|
49
49
|
const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
|
|
50
|
-
const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '
|
|
50
|
+
const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS || '3900000';
|
|
51
51
|
const parsed = Number.parseInt(rawValue, 10);
|
|
52
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed :
|
|
52
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 3900000;
|
|
53
53
|
})();
|
|
54
54
|
class ChatCommand {
|
|
55
55
|
config;
|
|
@@ -227,37 +227,87 @@ class ChatCommand {
|
|
|
227
227
|
devtoolsBridgeEndpoint: bridgeStatus.endpoint,
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
|
+
v3IterationCount = 0;
|
|
231
|
+
v3ToolCallCount = 0;
|
|
232
|
+
v3LastActivity = Date.now();
|
|
230
233
|
describeV3AgentTool(toolName) {
|
|
231
234
|
const normalized = String(toolName || '').toLowerCase();
|
|
232
235
|
if (/read|grep|search|list|find|glob/.test(normalized)) {
|
|
233
|
-
return '
|
|
236
|
+
return 'Reading project files';
|
|
234
237
|
}
|
|
235
238
|
if (/write|edit|patch|create|delete|replace|rename/.test(normalized)) {
|
|
236
|
-
return '
|
|
239
|
+
return 'Writing changes';
|
|
237
240
|
}
|
|
238
241
|
if (/test|lint|build|run|exec|terminal/.test(normalized)) {
|
|
239
|
-
return '
|
|
242
|
+
return 'Running verification';
|
|
240
243
|
}
|
|
241
|
-
|
|
244
|
+
if (/hyperloop/.test(normalized)) {
|
|
245
|
+
return 'Hyperloop processing';
|
|
246
|
+
}
|
|
247
|
+
return 'Working';
|
|
242
248
|
}
|
|
243
249
|
updateV3AgentSpinner(spinner, event) {
|
|
244
250
|
if (!event || typeof event !== 'object') {
|
|
245
251
|
return;
|
|
246
252
|
}
|
|
253
|
+
this.v3LastActivity = Date.now();
|
|
247
254
|
if (event.type === 'tool_call') {
|
|
248
|
-
|
|
255
|
+
this.v3ToolCallCount += 1;
|
|
256
|
+
const toolDesc = this.describeV3AgentTool(event.tool || event.name || event.tool_name);
|
|
257
|
+
const toolTarget = event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '';
|
|
258
|
+
const shortTarget = toolTarget ? ` → ${String(toolTarget).split('/').slice(-2).join('/')}` : '';
|
|
259
|
+
spinner.text = chalk_1.default.cyan(`[${this.v3IterationCount}/${this.v3ToolCallCount}] `) + `${toolDesc}${shortTarget}`;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (event.type === 'tool_result') {
|
|
263
|
+
const success = event.success !== false;
|
|
264
|
+
const toolName = event.name || event.tool || '';
|
|
265
|
+
const indicator = success ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
|
|
266
|
+
spinner.text = `${indicator} ${toolName} complete — next step...`;
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (event.type === 'thinking') {
|
|
270
|
+
this.v3IterationCount += 1;
|
|
271
|
+
const iterText = event.content || '';
|
|
272
|
+
const iterMatch = iterText.match(/Iteration (\d+)/i);
|
|
273
|
+
const iterNum = iterMatch ? iterMatch[1] : String(this.v3IterationCount);
|
|
274
|
+
spinner.text = chalk_1.default.cyan(`[Iteration ${iterNum}] `) + 'Analyzing...';
|
|
249
275
|
return;
|
|
250
276
|
}
|
|
251
277
|
if (event.type === 'message') {
|
|
252
|
-
|
|
278
|
+
const preview = String(event.content || '').slice(0, 80).replace(/\n/g, ' ');
|
|
279
|
+
spinner.text = chalk_1.default.cyan('[Response] ') + (preview || 'Writing response...');
|
|
253
280
|
return;
|
|
254
281
|
}
|
|
255
282
|
if (event.type === 'complete') {
|
|
256
|
-
|
|
283
|
+
const elapsed = event.elapsed || '';
|
|
284
|
+
const iters = event.iterations || this.v3IterationCount;
|
|
285
|
+
const tools = event.tool_calls || this.v3ToolCallCount;
|
|
286
|
+
spinner.text = chalk_1.default.green('✓ ') + `Complete — ${iters} iterations, ${tools} tool calls${elapsed ? `, ${elapsed}` : ''}`;
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (event.type === 'plan') {
|
|
290
|
+
const planKind = event.plan?.task_kind || event.task_kind || '';
|
|
291
|
+
spinner.text = chalk_1.default.cyan('[Plan] ') + `Task: ${planKind || 'analyzing'}...`;
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
if (event.type === 'error') {
|
|
295
|
+
if (event.checkpointed) {
|
|
296
|
+
spinner.text = chalk_1.default.yellow('[Checkpoint] ') + 'Budget reached — auto-continuing...';
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
spinner.text = chalk_1.default.red('[Error] ') + (event.message || 'Agent error');
|
|
300
|
+
}
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (event.type === 'context') {
|
|
304
|
+
spinner.text = chalk_1.default.cyan('[Context] ') + 'Workspace bound...';
|
|
257
305
|
return;
|
|
258
306
|
}
|
|
259
|
-
if (event.type === '
|
|
260
|
-
|
|
307
|
+
if (event.type === 'start') {
|
|
308
|
+
this.v3IterationCount = 0;
|
|
309
|
+
this.v3ToolCallCount = 0;
|
|
310
|
+
spinner.text = chalk_1.default.cyan('[Start] ') + 'Agent initialized...';
|
|
261
311
|
}
|
|
262
312
|
}
|
|
263
313
|
updateOperatorSpinner(spinner, event) {
|
|
@@ -856,6 +906,10 @@ class ChatCommand {
|
|
|
856
906
|
const runtimeContext = await this.getPromptRuntimeContext(prompt);
|
|
857
907
|
const routingPolicy = this.resolveAgentExecutionPolicy(prompt);
|
|
858
908
|
const rescueEligible = this.isSaaSRescuePrompt(prompt);
|
|
909
|
+
// Reset streaming counters for new workflow
|
|
910
|
+
this.v3IterationCount = 0;
|
|
911
|
+
this.v3ToolCallCount = 0;
|
|
912
|
+
this.v3LastActivity = Date.now();
|
|
859
913
|
const spinner = this.jsonOutput ? null : (0, ora_1.default)({
|
|
860
914
|
text: routingPolicy.cloudSelected ? 'Routing heavy task to Vigthoria Cloud...' : 'Routing to V3 Agent...',
|
|
861
915
|
spinner: 'clock',
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -188,6 +188,7 @@ export declare class APIClient {
|
|
|
188
188
|
private getAccessToken;
|
|
189
189
|
getV3AgentBaseUrls(preferLocal?: boolean): string[];
|
|
190
190
|
getV3AgentRunUrl(baseUrl: string): string;
|
|
191
|
+
getV3AgentContinueUrl(baseUrl: string): string;
|
|
191
192
|
getOperatorBaseUrls(): string[];
|
|
192
193
|
getOperatorStreamUrl(baseUrl: string): string;
|
|
193
194
|
getMcpBaseUrls(): string[];
|
package/dist/utils/api.js
CHANGED
|
@@ -26,9 +26,9 @@ const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
|
|
|
26
26
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 90000;
|
|
27
27
|
})();
|
|
28
28
|
const DEFAULT_OPERATOR_TIMEOUT_MS = (() => {
|
|
29
|
-
const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS || '
|
|
29
|
+
const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS || '3900000';
|
|
30
30
|
const parsed = Number.parseInt(rawValue, 10);
|
|
31
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed :
|
|
31
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 3900000;
|
|
32
32
|
})();
|
|
33
33
|
class APIClient {
|
|
34
34
|
client;
|
|
@@ -276,6 +276,12 @@ class APIClient {
|
|
|
276
276
|
}
|
|
277
277
|
return `${baseUrl}/api/v3-agent/run`;
|
|
278
278
|
}
|
|
279
|
+
getV3AgentContinueUrl(baseUrl) {
|
|
280
|
+
if (/127\.0\.0\.1:8030|localhost:8030/.test(baseUrl)) {
|
|
281
|
+
return `${baseUrl}/api/agent/continue`;
|
|
282
|
+
}
|
|
283
|
+
return `${baseUrl}/api/v3-agent/continue`;
|
|
284
|
+
}
|
|
279
285
|
getOperatorBaseUrls() {
|
|
280
286
|
const configuredModelsApiUrl = String(this.config.get('modelsApiUrl') || 'https://api.vigthoria.io').replace(/\/$/, '');
|
|
281
287
|
const urls = [
|
|
@@ -2234,6 +2240,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2234
2240
|
}
|
|
2235
2241
|
}
|
|
2236
2242
|
if (event.type === 'error') {
|
|
2243
|
+
if (event.checkpointed && event.task_id) {
|
|
2244
|
+
// Agent checkpointed — return data so caller can auto-continue
|
|
2245
|
+
return {
|
|
2246
|
+
task_id: event.task_id,
|
|
2247
|
+
context_id: contextId,
|
|
2248
|
+
result: final || event,
|
|
2249
|
+
events,
|
|
2250
|
+
files: streamedFiles,
|
|
2251
|
+
partial: true,
|
|
2252
|
+
checkpointed: true,
|
|
2253
|
+
checkpointed_task_id: event.task_id,
|
|
2254
|
+
};
|
|
2255
|
+
}
|
|
2237
2256
|
if (this.hasAgentWorkspaceOutput(context)) {
|
|
2238
2257
|
return {
|
|
2239
2258
|
task_id: events.find((entry) => entry && entry.task_id)?.task_id || null,
|
|
@@ -2312,6 +2331,66 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2312
2331
|
throw new Error(`V3 agent ${response.status}: ${errorText.slice(0, 200)}`);
|
|
2313
2332
|
}
|
|
2314
2333
|
const data = await this.collectV3AgentStream(response, requestExecutionContext);
|
|
2334
|
+
// Auto-continuation: if the agent checkpointed (budget exceeded), continue automatically
|
|
2335
|
+
if (data.checkpointed && data.checkpointed_task_id) {
|
|
2336
|
+
const maxContinuations = 10;
|
|
2337
|
+
let continuationData = data;
|
|
2338
|
+
let continuations = 0;
|
|
2339
|
+
while (continuationData.checkpointed && continuationData.checkpointed_task_id && continuations < maxContinuations) {
|
|
2340
|
+
continuations++;
|
|
2341
|
+
if (typeof requestExecutionContext.onStreamEvent === 'function') {
|
|
2342
|
+
try {
|
|
2343
|
+
requestExecutionContext.onStreamEvent({
|
|
2344
|
+
type: 'message',
|
|
2345
|
+
content: `Auto-continuing task (phase ${continuations + 1})...`,
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2348
|
+
catch { /* ignore */ }
|
|
2349
|
+
}
|
|
2350
|
+
const continueBody = {
|
|
2351
|
+
task_id: continuationData.checkpointed_task_id,
|
|
2352
|
+
context: requestBody.context,
|
|
2353
|
+
context_id: requestBody.context_id,
|
|
2354
|
+
mcp_context_id: requestBody.mcp_context_id,
|
|
2355
|
+
stream: true,
|
|
2356
|
+
};
|
|
2357
|
+
const continueController = new AbortController();
|
|
2358
|
+
const continueTimeoutId = setTimeout(() => continueController.abort(), timeoutMs);
|
|
2359
|
+
try {
|
|
2360
|
+
const continueHeaders = await this.getV3AgentHeaders();
|
|
2361
|
+
const continueResponse = await fetch(this.getV3AgentContinueUrl(baseUrl), {
|
|
2362
|
+
method: 'POST',
|
|
2363
|
+
headers: { ...continueHeaders, 'Content-Type': 'application/json' },
|
|
2364
|
+
body: JSON.stringify(continueBody),
|
|
2365
|
+
signal: continueController.signal,
|
|
2366
|
+
});
|
|
2367
|
+
if (!continueResponse.ok) {
|
|
2368
|
+
break; // Fall through to normal completion with partial data
|
|
2369
|
+
}
|
|
2370
|
+
continuationData = await this.collectV3AgentStream(continueResponse, requestExecutionContext);
|
|
2371
|
+
}
|
|
2372
|
+
catch {
|
|
2373
|
+
break; // Fall through to normal completion with partial data
|
|
2374
|
+
}
|
|
2375
|
+
finally {
|
|
2376
|
+
clearTimeout(continueTimeoutId);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
// Use the final continuation data for workspace recovery
|
|
2380
|
+
this.recoverAgentWorkspaceFiles(executionContext, continuationData.files || {}, expectedFiles);
|
|
2381
|
+
await this.waitForAgentWorkspaceSettle(executionContext, { expectedFiles });
|
|
2382
|
+
await this.ensureAgentFrontendPolish(message, executionContext);
|
|
2383
|
+
const previewGate = await this.runTemplateServicePreviewGate(message, executionContext);
|
|
2384
|
+
const finalContextId = continuationData.context_id || data.context_id || response.headers.get('x-context-id') || requestExecutionContext.contextId || null;
|
|
2385
|
+
return {
|
|
2386
|
+
content: this.formatV3AgentResponse(continuationData) || this.formatV3AgentResponse(data),
|
|
2387
|
+
taskId: continuationData.task_id || data.task_id || null,
|
|
2388
|
+
contextId: finalContextId,
|
|
2389
|
+
backendUrl: baseUrl,
|
|
2390
|
+
partial: continuationData.checkpointed === true,
|
|
2391
|
+
metadata: { source: 'v3-agent', mode: 'agent', contextId: finalContextId, continuations, previewGate },
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2315
2394
|
const contextId = data.context_id || response.headers.get('x-context-id') || requestExecutionContext.contextId || null;
|
|
2316
2395
|
const mcpContextId = response.headers.get('x-mcp-context-id') || requestExecutionContext.mcpContextId || null;
|
|
2317
2396
|
this.recoverAgentWorkspaceFiles(executionContext, data.files || {}, expectedFiles);
|