vigthoria-cli 1.11.25 → 1.11.28
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 +5 -0
- package/dist/commands/chat.js +137 -34
- package/dist/utils/agentRoute.js +14 -4
- package/dist/utils/api.js +115 -93
- package/dist/utils/requestIntent.d.ts +6 -0
- package/dist/utils/requestIntent.js +61 -5
- package/dist/utils/v3-workspace-path.js +1 -1
- package/package.json +1 -1
package/dist/commands/chat.d.ts
CHANGED
|
@@ -171,6 +171,11 @@ export declare class ChatCommand {
|
|
|
171
171
|
private runOperatorDirectAnswer;
|
|
172
172
|
private runSimplePrompt;
|
|
173
173
|
private runAgentTurn;
|
|
174
|
+
private resolveAgentTurnPrompt;
|
|
175
|
+
private shouldPreserveBuildOutcomeForContinue;
|
|
176
|
+
private resolveOriginalPrompt;
|
|
177
|
+
private commitAgentRunOutcome;
|
|
178
|
+
private printResumeContinuationHint;
|
|
174
179
|
private buildLocalLoopLiveOutcome;
|
|
175
180
|
private persistLocalLoopOutcome;
|
|
176
181
|
private runLocalAgentLoop;
|
package/dist/commands/chat.js
CHANGED
|
@@ -17,32 +17,29 @@ import { runAgentSessionMenu, shouldShowAgentSessionMenu } from './agent-session
|
|
|
17
17
|
import { createLiveOutcome, evaluateExecutorSuccess, handleTaskEvent, isSubstantiveAgentAnswer, isToolEvidenceStubAnswer, normalizeAgentAnswerContent, noteAnalysisToolUse, } from '../utils/agentRunOutcome.js';
|
|
18
18
|
import { looksLikeMarkdownReport, renderMarkdownToTerminal, summarizeMarkdownReport, } from '../utils/terminalMarkdown.js';
|
|
19
19
|
import { emitDeckEvent, isDeckModeEnabled } from '../utils/deckEvents.js';
|
|
20
|
-
import { inferAgentTaskType as sharedInferAgentTaskType, isTrivialHtmlPageRequest, resolvePlannerAgentTimeoutMs, resolveWorkflowType, shouldSkipAnalysisRescue, taskRequiresWorkspaceChanges as promptRequiresWorkspaceChanges, buildExecutionHints, } from '../utils/requestIntent.js';
|
|
20
|
+
import { inferAgentTaskType as sharedInferAgentTaskType, isTrivialHtmlPageRequest, resolvePlannerAgentTimeoutMs, resolveWorkflowType, shouldSkipAnalysisRescue, taskRequiresWorkspaceChanges as promptRequiresWorkspaceChanges, buildExecutionHints, isAgentContinuePrompt, isAgentRetryPrompt, isBuiltContinuePrompt, isBuiltRetryPrompt, } from '../utils/requestIntent.js';
|
|
21
21
|
import { resolveAgentRoute } from '../utils/agentRoute.js';
|
|
22
22
|
import { runTemplateInstantPath } from '../utils/templateInstantPath.js';
|
|
23
23
|
const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
|
|
24
24
|
const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS;
|
|
25
25
|
if (!rawValue) {
|
|
26
|
-
return
|
|
26
|
+
return 0;
|
|
27
27
|
}
|
|
28
28
|
const parsed = Number.parseInt(rawValue, 10);
|
|
29
|
-
return Number.isFinite(parsed) && parsed
|
|
29
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
30
30
|
})();
|
|
31
31
|
const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
|
|
32
32
|
const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS;
|
|
33
33
|
if (!rawValue) {
|
|
34
|
-
return
|
|
34
|
+
return 0;
|
|
35
35
|
}
|
|
36
36
|
const parsed = Number.parseInt(rawValue, 10);
|
|
37
|
-
return Number.isFinite(parsed) && parsed
|
|
37
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
38
38
|
})();
|
|
39
39
|
const DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS = (() => {
|
|
40
|
-
const rawValue = process.env.VIGTHORIA_AGENT_SOFT_TIMEOUT_MS || process.env.V3_AGENT_SOFT_TIMEOUT_MS;
|
|
41
|
-
if (!rawValue) {
|
|
42
|
-
return 180000;
|
|
43
|
-
}
|
|
40
|
+
const rawValue = process.env.VIGTHORIA_AGENT_SOFT_TIMEOUT_MS || process.env.V3_AGENT_SOFT_TIMEOUT_MS || '300000';
|
|
44
41
|
const parsed = Number.parseInt(rawValue, 10);
|
|
45
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed :
|
|
42
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 300000;
|
|
46
43
|
})();
|
|
47
44
|
export class ChatCommand {
|
|
48
45
|
config;
|
|
@@ -1408,6 +1405,9 @@ export class ChatCommand {
|
|
|
1408
1405
|
this.directToolContinuationCount = 0;
|
|
1409
1406
|
this.tools = new AgenticTools(this.logger, this.currentProjectPath, async (action) => this.requestPermission(action), this.autoApprove);
|
|
1410
1407
|
this.initializeSession(options.resume === true || options.retry === true || options.continue === true);
|
|
1408
|
+
if (options.resume && this.lastAgentRunOutcome && !this.jsonOutput && !options.prompt) {
|
|
1409
|
+
this.printResumeContinuationHint();
|
|
1410
|
+
}
|
|
1411
1411
|
// ── Commando Bridge: connect if --bridge was specified ──────────
|
|
1412
1412
|
if (options.bridge) {
|
|
1413
1413
|
const bridgeClient = new BridgeClient({
|
|
@@ -1680,7 +1680,11 @@ export class ChatCommand {
|
|
|
1680
1680
|
this.operatorMode = this.currentSession.operatorMode || this.operatorMode;
|
|
1681
1681
|
this.currentModel = this.currentSession.model || this.currentModel;
|
|
1682
1682
|
if (this.currentSession.lastAgentRunOutcome) {
|
|
1683
|
-
|
|
1683
|
+
const saved = this.currentSession.lastAgentRunOutcome;
|
|
1684
|
+
this.lastAgentRunOutcome = {
|
|
1685
|
+
...saved,
|
|
1686
|
+
originalPrompt: saved.originalPrompt ?? null,
|
|
1687
|
+
};
|
|
1684
1688
|
}
|
|
1685
1689
|
return;
|
|
1686
1690
|
}
|
|
@@ -2168,7 +2172,8 @@ export class ChatCommand {
|
|
|
2168
2172
|
if (!this.tools) {
|
|
2169
2173
|
throw new Error('Agent tools are not initialized.');
|
|
2170
2174
|
}
|
|
2171
|
-
|
|
2175
|
+
const resolvedPrompt = this.resolveAgentTurnPrompt(prompt);
|
|
2176
|
+
this.lastAgentRoute = await resolveAgentRoute(this.api, resolvedPrompt);
|
|
2172
2177
|
if (!this.jsonOutput) {
|
|
2173
2178
|
const r = this.lastAgentRoute;
|
|
2174
2179
|
const routerNote = r.routerLatencyMs
|
|
@@ -2176,13 +2181,13 @@ export class ChatCommand {
|
|
|
2176
2181
|
: '';
|
|
2177
2182
|
this.logger.debug(`Agent route: ${r.path} / ${r.taskKind} [${r.source}]${routerNote} — ${r.reason}`);
|
|
2178
2183
|
}
|
|
2179
|
-
const requiresV3Workflow = this.shouldRequireV3AgentWorkflow(
|
|
2180
|
-
const handledByTemplateInstant = await this.tryTemplateInstantPath(
|
|
2184
|
+
const requiresV3Workflow = this.shouldRequireV3AgentWorkflow(resolvedPrompt);
|
|
2185
|
+
const handledByTemplateInstant = await this.tryTemplateInstantPath(resolvedPrompt);
|
|
2181
2186
|
if (handledByTemplateInstant) {
|
|
2182
2187
|
this.saveSession();
|
|
2183
2188
|
return;
|
|
2184
2189
|
}
|
|
2185
|
-
const handledByDirectFileFlow = await this.tryDirectSingleFileFlow(
|
|
2190
|
+
const handledByDirectFileFlow = await this.tryDirectSingleFileFlow(resolvedPrompt);
|
|
2186
2191
|
if (handledByDirectFileFlow) {
|
|
2187
2192
|
this.saveSession();
|
|
2188
2193
|
return;
|
|
@@ -2190,12 +2195,12 @@ export class ChatCommand {
|
|
|
2190
2195
|
// Prime the message context with the target file when the direct-file flow was
|
|
2191
2196
|
// bypassed (e.g. HTML files routed to V3) so the local agent loop has file
|
|
2192
2197
|
// awareness and the ⚙ Executing: read_file banner is always emitted.
|
|
2193
|
-
await this.primeBypassedTargetFileContext(
|
|
2194
|
-
if (this.shouldPreferLocalAgentLoop(
|
|
2195
|
-
await this.runLocalAgentLoop(
|
|
2198
|
+
await this.primeBypassedTargetFileContext(resolvedPrompt);
|
|
2199
|
+
if (this.shouldPreferLocalAgentLoop(resolvedPrompt)) {
|
|
2200
|
+
await this.runLocalAgentLoop(resolvedPrompt);
|
|
2196
2201
|
return;
|
|
2197
2202
|
}
|
|
2198
|
-
const handledByV3Workflow = await this.tryV3AgentWorkflow(
|
|
2203
|
+
const handledByV3Workflow = await this.tryV3AgentWorkflow(resolvedPrompt);
|
|
2199
2204
|
if (handledByV3Workflow) {
|
|
2200
2205
|
this.saveSession();
|
|
2201
2206
|
return;
|
|
@@ -2207,7 +2212,95 @@ export class ChatCommand {
|
|
|
2207
2212
|
this.saveSession();
|
|
2208
2213
|
return;
|
|
2209
2214
|
}
|
|
2210
|
-
await this.runLocalAgentLoop(
|
|
2215
|
+
await this.runLocalAgentLoop(resolvedPrompt);
|
|
2216
|
+
}
|
|
2217
|
+
resolveAgentTurnPrompt(prompt) {
|
|
2218
|
+
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt)) {
|
|
2219
|
+
return prompt;
|
|
2220
|
+
}
|
|
2221
|
+
if (isAgentContinuePrompt(prompt)) {
|
|
2222
|
+
const followUp = this.buildContinuePrompt();
|
|
2223
|
+
if (followUp) {
|
|
2224
|
+
if (!this.jsonOutput) {
|
|
2225
|
+
console.log(chalk.cyan('↪ Treating your message as /continue — resuming the previous agent run.'));
|
|
2226
|
+
}
|
|
2227
|
+
return followUp;
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
if (isAgentRetryPrompt(prompt)) {
|
|
2231
|
+
const followUp = this.buildRetryPrompt();
|
|
2232
|
+
if (followUp) {
|
|
2233
|
+
if (!this.jsonOutput) {
|
|
2234
|
+
console.log(chalk.cyan('↪ Treating your message as /retry — re-running failed tasks from the previous run.'));
|
|
2235
|
+
}
|
|
2236
|
+
return followUp;
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
return prompt;
|
|
2240
|
+
}
|
|
2241
|
+
shouldPreserveBuildOutcomeForContinue(runPrompt, prior) {
|
|
2242
|
+
if (this.taskRequiresWorkspaceChanges(runPrompt)) {
|
|
2243
|
+
return false;
|
|
2244
|
+
}
|
|
2245
|
+
if (isBuiltContinuePrompt(runPrompt) || isBuiltRetryPrompt(runPrompt)) {
|
|
2246
|
+
return false;
|
|
2247
|
+
}
|
|
2248
|
+
const chainPrompt = prior.originalPrompt || prior.prompt;
|
|
2249
|
+
if (!this.taskRequiresWorkspaceChanges(chainPrompt)) {
|
|
2250
|
+
return false;
|
|
2251
|
+
}
|
|
2252
|
+
return isAgentContinuePrompt(runPrompt);
|
|
2253
|
+
}
|
|
2254
|
+
resolveOriginalPrompt(runPrompt) {
|
|
2255
|
+
const prior = this.lastAgentRunOutcome;
|
|
2256
|
+
if (prior?.originalPrompt) {
|
|
2257
|
+
return prior.originalPrompt;
|
|
2258
|
+
}
|
|
2259
|
+
if (this.taskRequiresWorkspaceChanges(runPrompt) && !isBuiltContinuePrompt(runPrompt) && !isBuiltRetryPrompt(runPrompt)) {
|
|
2260
|
+
return runPrompt;
|
|
2261
|
+
}
|
|
2262
|
+
if (prior && this.taskRequiresWorkspaceChanges(prior.originalPrompt || prior.prompt)) {
|
|
2263
|
+
return prior.originalPrompt || prior.prompt;
|
|
2264
|
+
}
|
|
2265
|
+
return null;
|
|
2266
|
+
}
|
|
2267
|
+
commitAgentRunOutcome(outcome, runPrompt) {
|
|
2268
|
+
const prior = this.lastAgentRunOutcome;
|
|
2269
|
+
if (prior && this.shouldPreserveBuildOutcomeForContinue(runPrompt, prior)) {
|
|
2270
|
+
if (!this.jsonOutput) {
|
|
2271
|
+
console.log(chalk.yellow('↪ Keeping the previous build run state — use /continue to resume implementation.'));
|
|
2272
|
+
}
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
outcome.originalPrompt = this.resolveOriginalPrompt(runPrompt);
|
|
2276
|
+
this.lastAgentRunOutcome = outcome;
|
|
2277
|
+
}
|
|
2278
|
+
printResumeContinuationHint() {
|
|
2279
|
+
const outcome = this.lastAgentRunOutcome;
|
|
2280
|
+
if (!outcome) {
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
const sourcePrompt = outcome.originalPrompt || outcome.prompt;
|
|
2284
|
+
const isBuild = this.taskRequiresWorkspaceChanges(sourcePrompt);
|
|
2285
|
+
const openWork = outcome.failedTaskIds.length > 0
|
|
2286
|
+
|| outcome.unfinishedTaskIds.length > 0
|
|
2287
|
+
|| (outcome.tasksTotal > 0 && outcome.tasksSucceeded < outcome.tasksTotal);
|
|
2288
|
+
if (!isBuild && !openWork) {
|
|
2289
|
+
return;
|
|
2290
|
+
}
|
|
2291
|
+
console.log('');
|
|
2292
|
+
console.log(chalk.cyan('Prior agent run restored for this project.'));
|
|
2293
|
+
if (openWork) {
|
|
2294
|
+
const taskIds = [...new Set([...outcome.failedTaskIds, ...outcome.unfinishedTaskIds])].slice(0, 8);
|
|
2295
|
+
if (taskIds.length > 0) {
|
|
2296
|
+
console.log(chalk.gray(` Unfinished tasks: ${taskIds.join(', ')}`));
|
|
2297
|
+
}
|
|
2298
|
+
else {
|
|
2299
|
+
console.log(chalk.gray(` Progress: ${outcome.tasksSucceeded}/${outcome.tasksTotal} tasks completed`));
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
console.log(chalk.gray(' Type ') + chalk.cyan('/continue') + chalk.gray(' to resume implementation, or ') + chalk.cyan('/retry') + chalk.gray(' for failed tasks only.'));
|
|
2303
|
+
console.log('');
|
|
2211
2304
|
}
|
|
2212
2305
|
buildLocalLoopLiveOutcome(prompt) {
|
|
2213
2306
|
const liveOutcome = createLiveOutcome();
|
|
@@ -2223,8 +2316,9 @@ export class ChatCommand {
|
|
|
2223
2316
|
return liveOutcome;
|
|
2224
2317
|
}
|
|
2225
2318
|
persistLocalLoopOutcome(prompt, evaluation, liveOutcome) {
|
|
2226
|
-
this.
|
|
2319
|
+
this.commitAgentRunOutcome({
|
|
2227
2320
|
prompt,
|
|
2321
|
+
originalPrompt: null,
|
|
2228
2322
|
taskId: null,
|
|
2229
2323
|
contextId: null,
|
|
2230
2324
|
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
@@ -2245,7 +2339,7 @@ export class ChatCommand {
|
|
|
2245
2339
|
workspacePath: this.currentProjectPath || null,
|
|
2246
2340
|
workspaceSyncIssue: null,
|
|
2247
2341
|
finishedAt: Date.now(),
|
|
2248
|
-
};
|
|
2342
|
+
}, prompt);
|
|
2249
2343
|
}
|
|
2250
2344
|
async runLocalAgentLoop(prompt) {
|
|
2251
2345
|
if (!this.tools) {
|
|
@@ -2583,8 +2677,9 @@ export class ChatCommand {
|
|
|
2583
2677
|
liveOutcome.tasksSucceeded = 1;
|
|
2584
2678
|
liveOutcome.answerContent = summary;
|
|
2585
2679
|
const evaluation = evaluateExecutorSuccess(liveOutcome);
|
|
2586
|
-
this.
|
|
2680
|
+
this.commitAgentRunOutcome({
|
|
2587
2681
|
prompt,
|
|
2682
|
+
originalPrompt: null,
|
|
2588
2683
|
taskId: null,
|
|
2589
2684
|
contextId: null,
|
|
2590
2685
|
tasksSucceeded: 1,
|
|
@@ -2605,7 +2700,7 @@ export class ChatCommand {
|
|
|
2605
2700
|
workspacePath: workspacePath || null,
|
|
2606
2701
|
workspaceSyncIssue: null,
|
|
2607
2702
|
finishedAt: Date.now(),
|
|
2608
|
-
};
|
|
2703
|
+
}, prompt);
|
|
2609
2704
|
if (!this.jsonOutput) {
|
|
2610
2705
|
console.log(chalk.green(`✓ ${summary}`));
|
|
2611
2706
|
console.log(chalk.gray(' Run: vigthoria preview'));
|
|
@@ -3201,8 +3296,9 @@ export class ChatCommand {
|
|
|
3201
3296
|
if (!executorSucceeded) {
|
|
3202
3297
|
process.exitCode = 1;
|
|
3203
3298
|
}
|
|
3204
|
-
this.
|
|
3299
|
+
this.commitAgentRunOutcome({
|
|
3205
3300
|
prompt,
|
|
3301
|
+
originalPrompt: null,
|
|
3206
3302
|
taskId: response.taskId || null,
|
|
3207
3303
|
contextId: response.contextId || null,
|
|
3208
3304
|
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
@@ -3225,9 +3321,11 @@ export class ChatCommand {
|
|
|
3225
3321
|
? 'Local workspace has files but the agent did not confirm tracked changes.'
|
|
3226
3322
|
: null,
|
|
3227
3323
|
finishedAt: Date.now(),
|
|
3228
|
-
};
|
|
3324
|
+
}, prompt);
|
|
3229
3325
|
if (!this.jsonOutput && !this.directPromptMode) {
|
|
3230
|
-
|
|
3326
|
+
if (this.lastAgentRunOutcome) {
|
|
3327
|
+
this.printAgentRunSummary(this.lastAgentRunOutcome, runEvaluation, changedFileCount);
|
|
3328
|
+
}
|
|
3231
3329
|
}
|
|
3232
3330
|
if (this.jsonOutput) {
|
|
3233
3331
|
if (!executorSucceeded) {
|
|
@@ -3299,8 +3397,9 @@ export class ChatCommand {
|
|
|
3299
3397
|
taskDisplay.finalize();
|
|
3300
3398
|
}
|
|
3301
3399
|
catch (_) { /* render is best-effort */ }
|
|
3302
|
-
this.
|
|
3400
|
+
this.commitAgentRunOutcome({
|
|
3303
3401
|
prompt,
|
|
3402
|
+
originalPrompt: null,
|
|
3304
3403
|
taskId: null,
|
|
3305
3404
|
contextId: null,
|
|
3306
3405
|
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
@@ -3321,7 +3420,7 @@ export class ChatCommand {
|
|
|
3321
3420
|
workspacePath: workspacePath || null,
|
|
3322
3421
|
workspaceSyncIssue: null,
|
|
3323
3422
|
finishedAt: Date.now(),
|
|
3324
|
-
};
|
|
3423
|
+
}, prompt);
|
|
3325
3424
|
if (!this.jsonOutput) {
|
|
3326
3425
|
process.exitCode = 1;
|
|
3327
3426
|
}
|
|
@@ -3349,7 +3448,9 @@ export class ChatCommand {
|
|
|
3349
3448
|
requiresWorkspaceChanges: this.taskRequiresWorkspaceChanges(prompt),
|
|
3350
3449
|
workspaceHasOutput: this.api.hasAgentWorkspaceOutput(workspaceContext),
|
|
3351
3450
|
});
|
|
3352
|
-
|
|
3451
|
+
if (this.lastAgentRunOutcome) {
|
|
3452
|
+
this.printAgentRunSummary(this.lastAgentRunOutcome, failedEval, 0);
|
|
3453
|
+
}
|
|
3353
3454
|
}
|
|
3354
3455
|
return true;
|
|
3355
3456
|
}
|
|
@@ -3800,6 +3901,7 @@ export class ChatCommand {
|
|
|
3800
3901
|
const o = this.lastAgentRunOutcome;
|
|
3801
3902
|
if (!o || !o.prompt)
|
|
3802
3903
|
return null;
|
|
3904
|
+
const sourcePrompt = o.originalPrompt || o.prompt;
|
|
3803
3905
|
const runtime = this.getRuntimeEnvironmentContext();
|
|
3804
3906
|
const remaining = [...new Set([...o.failedTaskIds, ...o.unfinishedTaskIds])];
|
|
3805
3907
|
const taskList = remaining.length > 0 ? remaining.join(', ') : '';
|
|
@@ -3814,9 +3916,9 @@ export class ChatCommand {
|
|
|
3814
3916
|
? '\nUse local workspace tools and local filesystem paths first; do not assume server-side workspace access.'
|
|
3815
3917
|
: '';
|
|
3816
3918
|
if (taskList) {
|
|
3817
|
-
return `Resume the previous agent run. Re-execute only these tasks and make them pass: ${taskList}.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${
|
|
3919
|
+
return `Resume the previous agent run. Re-execute only these tasks and make them pass: ${taskList}.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${sourcePrompt}`;
|
|
3818
3920
|
}
|
|
3819
|
-
return `Retry the previous request and make sure it finishes successfully.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${
|
|
3921
|
+
return `Retry the previous request and make sure it finishes successfully.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${sourcePrompt}`;
|
|
3820
3922
|
}
|
|
3821
3923
|
computeRetryPromptSignature() {
|
|
3822
3924
|
const o = this.lastAgentRunOutcome;
|
|
@@ -3834,9 +3936,10 @@ export class ChatCommand {
|
|
|
3834
3936
|
const o = this.lastAgentRunOutcome;
|
|
3835
3937
|
if (!o || !o.prompt)
|
|
3836
3938
|
return null;
|
|
3939
|
+
const sourcePrompt = o.originalPrompt || o.prompt;
|
|
3837
3940
|
const remaining = [...new Set([...o.failedTaskIds, ...o.unfinishedTaskIds])];
|
|
3838
3941
|
const taskList = remaining.length > 0 ? `\nRemaining tasks to finish: ${remaining.join(', ')}.` : '';
|
|
3839
|
-
const mustChangeFiles = this.taskRequiresWorkspaceChanges(
|
|
3942
|
+
const mustChangeFiles = this.taskRequiresWorkspaceChanges(sourcePrompt)
|
|
3840
3943
|
? '\nThis was a build/edit request. Do not stop after analysis or tool JSON; make real workspace file changes and verify them before finishing.'
|
|
3841
3944
|
: '';
|
|
3842
3945
|
const blockerLine = o.qualityBlockers.length > 0
|
|
@@ -3845,7 +3948,7 @@ export class ChatCommand {
|
|
|
3845
3948
|
const missingLine = o.qualityMissing.length > 0
|
|
3846
3949
|
? `\nMissing pieces: ${o.qualityMissing.slice(0, 6).join(', ')}.`
|
|
3847
3950
|
: '';
|
|
3848
|
-
return `Continue the previous agent run from the current workspace state without re-doing already-completed work.${taskList}${mustChangeFiles}${blockerLine}${missingLine}\nOriginal request was: ${
|
|
3951
|
+
return `Continue the previous agent run from the current workspace state without re-doing already-completed work.${taskList}${mustChangeFiles}${blockerLine}${missingLine}\nOriginal request was: ${sourcePrompt}`;
|
|
3849
3952
|
}
|
|
3850
3953
|
/**
|
|
3851
3954
|
* Re-print the last agent run summary, or guide the user when there isn't one.
|
package/dist/utils/agentRoute.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unified agent routing: regex (instant) → optional Balanced 4B → V3 execution hints.
|
|
3
3
|
*/
|
|
4
|
-
import { inferAgentTaskType, isTrivialHtmlPageRequest,
|
|
4
|
+
import { inferAgentTaskType, isTrivialHtmlPageRequest, isAgentContinuePrompt, isAgentRetryPrompt, hasGameIntent, hasWebPageIntent, taskRequiresWorkspaceChanges, stripExecutionShaping, } from './requestIntent.js';
|
|
5
5
|
import { isFastInferenceRouterAvailable, routeWithBalanced4b, shouldUseBalancedRouter, } from './fastAgentRouter.js';
|
|
6
6
|
function normalizeTaskKind(value, fallback) {
|
|
7
7
|
const kind = String(value || fallback).trim().toLowerCase();
|
|
@@ -74,13 +74,23 @@ function mergeLlmRoute(regexTask, prompt, parsed) {
|
|
|
74
74
|
}
|
|
75
75
|
export async function resolveAgentRoute(api, prompt) {
|
|
76
76
|
const stripped = stripExecutionShaping(prompt);
|
|
77
|
-
if (
|
|
77
|
+
if (isAgentContinuePrompt(stripped)) {
|
|
78
78
|
const regexTask = inferAgentTaskType(stripped);
|
|
79
79
|
return {
|
|
80
80
|
path: 'v3-agent',
|
|
81
81
|
taskKind: regexTask === 'analysis' ? 'implementation' : regexTask,
|
|
82
|
-
confidence: 0.
|
|
83
|
-
reason: 'continue
|
|
82
|
+
confidence: 0.92,
|
|
83
|
+
reason: 'continue follow-up (regex)',
|
|
84
|
+
source: 'regex',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (isAgentRetryPrompt(stripped)) {
|
|
88
|
+
const regexTask = inferAgentTaskType(stripped);
|
|
89
|
+
return {
|
|
90
|
+
path: 'v3-agent',
|
|
91
|
+
taskKind: regexTask === 'analysis' ? 'implementation' : regexTask,
|
|
92
|
+
confidence: 0.92,
|
|
93
|
+
reason: 'retry follow-up (regex)',
|
|
84
94
|
source: 'regex',
|
|
85
95
|
};
|
|
86
96
|
}
|
package/dist/utils/api.js
CHANGED
|
@@ -259,15 +259,18 @@ export function propagateError(err) {
|
|
|
259
259
|
const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
|
|
260
260
|
const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS;
|
|
261
261
|
if (!rawValue) {
|
|
262
|
-
return
|
|
262
|
+
return 0;
|
|
263
263
|
}
|
|
264
264
|
const parsed = Number.parseInt(rawValue, 10);
|
|
265
|
-
return Number.isFinite(parsed) && parsed
|
|
265
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
266
266
|
})();
|
|
267
267
|
const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
|
|
268
|
-
const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS
|
|
268
|
+
const rawValue = process.env.VIGTHORIA_AGENT_IDLE_TIMEOUT_MS || process.env.V3_AGENT_IDLE_TIMEOUT_MS;
|
|
269
|
+
if (!rawValue) {
|
|
270
|
+
return 0;
|
|
271
|
+
}
|
|
269
272
|
const parsed = Number.parseInt(rawValue, 10);
|
|
270
|
-
return Number.isFinite(parsed) && parsed
|
|
273
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
271
274
|
})();
|
|
272
275
|
const DEFAULT_OPERATOR_TIMEOUT_MS = (() => {
|
|
273
276
|
const rawValue = process.env.VIGTHORIA_OPERATOR_TIMEOUT_MS || process.env.OPERATOR_TIMEOUT_MS;
|
|
@@ -2643,48 +2646,18 @@ menu {
|
|
|
2643
2646
|
}
|
|
2644
2647
|
return;
|
|
2645
2648
|
}
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
if (event.type !== 'tool_call') {
|
|
2659
|
-
if (event.type === 'tool_result' && event.success) {
|
|
2660
|
-
const name = String(event.name || event.tool || '').trim();
|
|
2661
|
-
const args = event.arguments || {};
|
|
2662
|
-
const targetPath = typeof event.target === 'string'
|
|
2663
|
-
? event.target
|
|
2664
|
-
: (typeof args.path === 'string' ? args.path : '');
|
|
2665
|
-
if ((name === 'write_file' || name === 'edit_file') && targetPath) {
|
|
2666
|
-
const filePath = this.normalizeAgentWorkspaceRelativePath(targetPath, serverRoot || undefined);
|
|
2667
|
-
if (filePath && typeof args.content === 'string') {
|
|
2668
|
-
streamedFiles[filePath] = args.content;
|
|
2669
|
-
}
|
|
2670
|
-
}
|
|
2671
|
-
}
|
|
2672
|
-
return;
|
|
2673
|
-
}
|
|
2674
|
-
const args = event.arguments || {};
|
|
2675
|
-
if ((event.name === 'write_file' || event.name === 'edit_file') && typeof args.path === 'string') {
|
|
2676
|
-
const filePath = this.normalizeAgentWorkspaceRelativePath(args.path, serverRoot || undefined);
|
|
2677
|
-
if (!filePath) {
|
|
2678
|
-
return;
|
|
2679
|
-
}
|
|
2680
|
-
if (event.name === 'write_file' && typeof args.content === 'string') {
|
|
2681
|
-
streamedFiles[filePath] = args.content;
|
|
2682
|
-
return;
|
|
2683
|
-
}
|
|
2684
|
-
if (event.name === 'edit_file' && typeof args.old_string === 'string' && typeof args.new_string === 'string') {
|
|
2685
|
-
const existing = streamedFiles[filePath];
|
|
2686
|
-
if (typeof existing === 'string' && existing.includes(args.old_string)) {
|
|
2687
|
-
streamedFiles[filePath] = existing.replace(args.old_string, args.new_string);
|
|
2649
|
+
// Only count confirmed mutations — not workspace snapshots (hydrated baseline)
|
|
2650
|
+
// or tool_call previews that may still fail client-side / read-only guards.
|
|
2651
|
+
if (event.type === 'tool_result' && event.success) {
|
|
2652
|
+
const name = String(event.name || event.tool || '').trim();
|
|
2653
|
+
const args = event.arguments || {};
|
|
2654
|
+
const targetPath = typeof event.target === 'string'
|
|
2655
|
+
? event.target
|
|
2656
|
+
: (typeof args.path === 'string' ? args.path : '');
|
|
2657
|
+
if ((name === 'write_file' || name === 'edit_file') && targetPath) {
|
|
2658
|
+
const filePath = this.normalizeAgentWorkspaceRelativePath(targetPath, serverRoot || undefined);
|
|
2659
|
+
if (filePath && typeof args.content === 'string') {
|
|
2660
|
+
streamedFiles[filePath] = args.content;
|
|
2688
2661
|
}
|
|
2689
2662
|
}
|
|
2690
2663
|
}
|
|
@@ -2851,9 +2824,30 @@ menu {
|
|
|
2851
2824
|
return { success: true, output: matches.slice(0, 100).join('\n') || '(no matches)' };
|
|
2852
2825
|
}
|
|
2853
2826
|
if (name === 'syntax_check') {
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2827
|
+
if (!fs.existsSync(target.absolutePath)) {
|
|
2828
|
+
return {
|
|
2829
|
+
success: false,
|
|
2830
|
+
output: '',
|
|
2831
|
+
error: `File not found: ${target.relativePath}. Write the file before running syntax_check.`,
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
const ext = path.extname(target.absolutePath).toLowerCase();
|
|
2835
|
+
if (ext === '.json') {
|
|
2836
|
+
JSON.parse(fs.readFileSync(target.absolutePath, 'utf8'));
|
|
2837
|
+
return { success: true, output: `Syntax check passed: ${target.relativePath}` };
|
|
2838
|
+
}
|
|
2839
|
+
if (ext === '.js' || ext === '.mjs' || ext === '.cjs') {
|
|
2840
|
+
const { execSync } = await import('child_process');
|
|
2841
|
+
try {
|
|
2842
|
+
execSync(`node --check "${target.absolutePath}"`, { stdio: 'pipe' });
|
|
2843
|
+
return { success: true, output: `Syntax check passed: ${target.relativePath}` };
|
|
2844
|
+
}
|
|
2845
|
+
catch (error) {
|
|
2846
|
+
const stderr = error?.stderr?.toString?.() || error?.message || String(error);
|
|
2847
|
+
return { success: false, output: '', error: stderr.trim() || `Syntax check failed: ${target.relativePath}` };
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
fs.readFileSync(target.absolutePath, 'utf8');
|
|
2857
2851
|
return { success: true, output: `Syntax check passed: ${target.relativePath}` };
|
|
2858
2852
|
}
|
|
2859
2853
|
if (name === 'run_command') {
|
|
@@ -3563,48 +3557,71 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3563
3557
|
this.activeV3StreamContext = context;
|
|
3564
3558
|
context.__v3StreamedFiles = streamedFiles;
|
|
3565
3559
|
const idleTimeoutMs = (() => {
|
|
3566
|
-
const base = context.agentIdleTimeoutMs
|
|
3567
|
-
if (
|
|
3568
|
-
|
|
3569
|
-
const extended = Number.parseInt(raw, 10);
|
|
3570
|
-
return Math.max(base, Number.isFinite(extended) && extended > 0 ? extended : 300000);
|
|
3560
|
+
const base = context.agentIdleTimeoutMs ?? DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS;
|
|
3561
|
+
if (base <= 0) {
|
|
3562
|
+
return 0;
|
|
3571
3563
|
}
|
|
3572
|
-
|
|
3564
|
+
if (!isPlannerBuildTask(String(context.agentTaskType || ''), String(context.rawPrompt || ''))) {
|
|
3565
|
+
return base;
|
|
3566
|
+
}
|
|
3567
|
+
const raw = process.env.VIGTHORIA_AGENT_PLANNER_IDLE_TIMEOUT_MS || process.env.V3_AGENT_PLANNER_IDLE_TIMEOUT_MS;
|
|
3568
|
+
if (!raw) {
|
|
3569
|
+
return base;
|
|
3570
|
+
}
|
|
3571
|
+
const extended = Number.parseInt(raw, 10);
|
|
3572
|
+
return Number.isFinite(extended) && extended > 0 ? Math.max(base, extended) : base;
|
|
3573
3573
|
})();
|
|
3574
3574
|
try {
|
|
3575
3575
|
while (true) {
|
|
3576
3576
|
let chunk;
|
|
3577
3577
|
try {
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
if (result !== timeoutSentinel) {
|
|
3590
|
-
chunk = result;
|
|
3591
|
-
break;
|
|
3592
|
-
}
|
|
3593
|
-
if (this.pendingV3ClientToolTasks.size > 0) {
|
|
3594
|
-
continue;
|
|
3595
|
-
}
|
|
3596
|
-
if (this.hasAgentWorkspaceOutput(context)) {
|
|
3597
|
-
const stalledError = new Error('V3 agent stream stalled after writing workspace output');
|
|
3598
|
-
stalledError.name = 'AbortError';
|
|
3599
|
-
stalledError.partialData = {
|
|
3600
|
-
task_id: events.find((event) => event && event.task_id)?.task_id || null,
|
|
3601
|
-
context_id: contextId,
|
|
3602
|
-
result: final,
|
|
3603
|
-
events,
|
|
3604
|
-
files: streamedFiles,
|
|
3578
|
+
if (idleTimeoutMs <= 0) {
|
|
3579
|
+
chunk = await reader.read();
|
|
3580
|
+
}
|
|
3581
|
+
else {
|
|
3582
|
+
chunk = await new Promise((resolve, reject) => {
|
|
3583
|
+
let idleTimer = null;
|
|
3584
|
+
const clearIdleTimer = () => {
|
|
3585
|
+
if (idleTimer) {
|
|
3586
|
+
clearTimeout(idleTimer);
|
|
3587
|
+
idleTimer = null;
|
|
3588
|
+
}
|
|
3605
3589
|
};
|
|
3606
|
-
|
|
3607
|
-
|
|
3590
|
+
const scheduleIdleTimer = () => {
|
|
3591
|
+
clearIdleTimer();
|
|
3592
|
+
idleTimer = setTimeout(() => {
|
|
3593
|
+
if (this.pendingV3ClientToolTasks.size > 0) {
|
|
3594
|
+
scheduleIdleTimer();
|
|
3595
|
+
return;
|
|
3596
|
+
}
|
|
3597
|
+
if (this.hasAgentWorkspaceOutput(context)) {
|
|
3598
|
+
const stalledError = new Error('V3 agent stream stalled after writing workspace output');
|
|
3599
|
+
stalledError.name = 'AbortError';
|
|
3600
|
+
stalledError.partialData = {
|
|
3601
|
+
task_id: events.find((event) => event && event.task_id)?.task_id || null,
|
|
3602
|
+
context_id: contextId,
|
|
3603
|
+
result: final,
|
|
3604
|
+
events,
|
|
3605
|
+
files: streamedFiles,
|
|
3606
|
+
};
|
|
3607
|
+
clearIdleTimer();
|
|
3608
|
+
reject(stalledError);
|
|
3609
|
+
return;
|
|
3610
|
+
}
|
|
3611
|
+
scheduleIdleTimer();
|
|
3612
|
+
}, idleTimeoutMs);
|
|
3613
|
+
};
|
|
3614
|
+
scheduleIdleTimer();
|
|
3615
|
+
reader.read()
|
|
3616
|
+
.then((result) => {
|
|
3617
|
+
clearIdleTimer();
|
|
3618
|
+
resolve(result);
|
|
3619
|
+
})
|
|
3620
|
+
.catch((error) => {
|
|
3621
|
+
clearIdleTimer();
|
|
3622
|
+
reject(error);
|
|
3623
|
+
});
|
|
3624
|
+
});
|
|
3608
3625
|
}
|
|
3609
3626
|
}
|
|
3610
3627
|
catch (error) {
|
|
@@ -3770,11 +3787,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3770
3787
|
const resolvedModel = this.resolvePermittedModelId(requestedModel);
|
|
3771
3788
|
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)
|
|
3772
3789
|
&& context.localMachineCapable !== false;
|
|
3773
|
-
const
|
|
3774
|
-
&& /(saas|dashboard|analytics|billing|team management|activity feed|login screen)/i.test(message);
|
|
3775
|
-
const timeoutMs = rescueEligibleSaaS
|
|
3776
|
-
? Math.min(resolvePlannerAgentTimeoutMs(baseTimeoutMs, String(executionContext.agentTaskType || ''), String(executionContext.rawPrompt || message || '')), 210000)
|
|
3777
|
-
: resolvePlannerAgentTimeoutMs(baseTimeoutMs, String(executionContext.agentTaskType || ''), String(executionContext.rawPrompt || message || ''));
|
|
3790
|
+
const timeoutMs = resolvePlannerAgentTimeoutMs(baseTimeoutMs, String(executionContext.agentTaskType || ''), String(executionContext.rawPrompt || message || ''));
|
|
3778
3791
|
const maxAttempts = preferLocalV3 ? 2 : 1;
|
|
3779
3792
|
let lastErrors = [];
|
|
3780
3793
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
@@ -5560,11 +5573,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
5560
5573
|
'vigthoria-code': 'vigthoria-v3-code-35b',
|
|
5561
5574
|
'vigthoria-agent': 'vigthoria-v3-code-35b',
|
|
5562
5575
|
// ═══════════════════════════════════════════════════════════════
|
|
5563
|
-
// VIGTHORIA CLOUD -
|
|
5576
|
+
// VIGTHORIA CLOUD - current billing catalog aliases
|
|
5564
5577
|
// ═══════════════════════════════════════════════════════════════
|
|
5565
|
-
'cloud': 'vigthoria-cloud-
|
|
5566
|
-
'cloud-
|
|
5567
|
-
'
|
|
5578
|
+
'cloud': 'vigthoria-cloud-balanced',
|
|
5579
|
+
'cloud-code': 'vigthoria-cloud-code',
|
|
5580
|
+
'cloud-balanced': 'vigthoria-cloud-balanced',
|
|
5581
|
+
'cloud-fast': 'vigthoria-cloud-fast',
|
|
5582
|
+
'cloud-power': 'vigthoria-cloud-power',
|
|
5583
|
+
'cloud-maximum': 'vigthoria-cloud-maximum',
|
|
5584
|
+
'cloud-reason': 'vigthoria-cloud-power',
|
|
5585
|
+
'ultra': 'vigthoria-cloud-maximum',
|
|
5586
|
+
// Legacy aliases kept for backward compatibility
|
|
5587
|
+
'cloud-pro': 'vigthoria-cloud-power',
|
|
5588
|
+
'cloud-k2': 'vigthoria-cloud-power',
|
|
5589
|
+
'cloud-ultra': 'vigthoria-cloud-maximum',
|
|
5568
5590
|
};
|
|
5569
5591
|
// If already a full model ID, return as-is
|
|
5570
5592
|
if (shortName.includes('vigthoria') || shortName.includes('/') || shortName.includes(':')) {
|
|
@@ -7,6 +7,12 @@ export declare function stripExecutionShaping(prompt: string): string;
|
|
|
7
7
|
export declare function hasBuildVerb(prompt: string): boolean;
|
|
8
8
|
export declare function hasArtifactNoun(prompt: string): boolean;
|
|
9
9
|
export declare function hasGameIntent(prompt: string): boolean;
|
|
10
|
+
/** True when the CLI already expanded a /continue-style follow-up prompt. */
|
|
11
|
+
export declare function isBuiltContinuePrompt(prompt: string): boolean;
|
|
12
|
+
/** True when the CLI already expanded a /retry-style follow-up prompt. */
|
|
13
|
+
export declare function isBuiltRetryPrompt(prompt: string): boolean;
|
|
14
|
+
export declare function isAgentContinuePrompt(prompt: string): boolean;
|
|
15
|
+
export declare function isAgentRetryPrompt(prompt: string): boolean;
|
|
10
16
|
export declare function isContinueOrRetryPrompt(prompt: string): boolean;
|
|
11
17
|
export declare function hasWebPageIntent(prompt: string): boolean;
|
|
12
18
|
export declare function isTrivialHtmlPageRequest(prompt: string): boolean;
|
|
@@ -41,9 +41,57 @@ export function hasGameIntent(prompt) {
|
|
|
41
41
|
}
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
|
+
const CONTINUE_VERB = /\b(?:continue|contiune|continu|proceed|resume|keep\s+going|go\s+on|carry\s+on|pick\s+up\s+where)\b/i;
|
|
45
|
+
const CONTINUE_OBJECT = /\b(?:task|tasks|work|build|building|implementation|project|run|plan|planning|remaining|unfinished|missing|components?|next\s+steps?|previous|last|where\s+we\s+left|hyperloop|report)\b/i;
|
|
46
|
+
/** True when the CLI already expanded a /continue-style follow-up prompt. */
|
|
47
|
+
export function isBuiltContinuePrompt(prompt) {
|
|
48
|
+
return /^Continue the previous agent run/i.test(stripExecutionShaping(prompt));
|
|
49
|
+
}
|
|
50
|
+
/** True when the CLI already expanded a /retry-style follow-up prompt. */
|
|
51
|
+
export function isBuiltRetryPrompt(prompt) {
|
|
52
|
+
const text = stripExecutionShaping(prompt);
|
|
53
|
+
return /^(?:Resume the previous agent run|Retry the previous request)/i.test(text);
|
|
54
|
+
}
|
|
55
|
+
export function isAgentContinuePrompt(prompt) {
|
|
56
|
+
const text = stripExecutionShaping(prompt).trim();
|
|
57
|
+
if (!text) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (isBuiltContinuePrompt(text) || isBuiltRetryPrompt(text)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (/^\/(?:continue|contiune|contiunue)$/i.test(text)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (/\bcontinue\s+(?:the\s+)?(?:previous|last|current)\s+(?:agent\s+)?run\b/i.test(text)) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
if (/\bresume\s+(?:the\s+)?(?:failed|unfinished)\b/i.test(text)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
if (/\bplanner\s+produced\s+\d+\s+execution\s+tasks\b/i.test(text)) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (CONTINUE_VERB.test(text) && CONTINUE_OBJECT.test(text)) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
if (/^(?:please\s+)?(?:continue|contiune|proceed)(?:[!?.]|$)/i.test(text)) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
export function isAgentRetryPrompt(prompt) {
|
|
84
|
+
const text = stripExecutionShaping(prompt).trim();
|
|
85
|
+
if (!text || isBuiltContinuePrompt(text) || isBuiltRetryPrompt(text)) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (/^\/retry$/i.test(text)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return /\b(?:retry|re-?try)\s+(?:the\s+)?(?:failed|last|previous|unfinished)\b/i.test(text);
|
|
92
|
+
}
|
|
44
93
|
export function isContinueOrRetryPrompt(prompt) {
|
|
45
|
-
|
|
46
|
-
return /\b(continue\s+(?:the\s+)?(?:previous|last|current)\s+(?:agent\s+)?run|\/retry|\/continue|resume\s+(?:the\s+)?(?:failed|unfinished)|planner\s+produced\s+\d+\s+execution\s+tasks)\b/i.test(text);
|
|
94
|
+
return isAgentContinuePrompt(prompt) || isAgentRetryPrompt(prompt);
|
|
47
95
|
}
|
|
48
96
|
export function hasWebPageIntent(prompt) {
|
|
49
97
|
const text = stripExecutionShaping(prompt);
|
|
@@ -150,16 +198,24 @@ export function resolvePlannerAgentTimeoutMs(baseTimeoutMs, agentTaskType, promp
|
|
|
150
198
|
if (!isPlannerBuildTask(agentTaskType, prompt)) {
|
|
151
199
|
return baseTimeoutMs;
|
|
152
200
|
}
|
|
153
|
-
const raw = process.env.VIGTHORIA_AGENT_PLANNER_TIMEOUT_MS || process.env.V3_AGENT_PLANNER_TIMEOUT_MS
|
|
201
|
+
const raw = process.env.VIGTHORIA_AGENT_PLANNER_TIMEOUT_MS || process.env.V3_AGENT_PLANNER_TIMEOUT_MS;
|
|
202
|
+
if (!raw) {
|
|
203
|
+
return baseTimeoutMs;
|
|
204
|
+
}
|
|
154
205
|
const extended = Number.parseInt(raw, 10);
|
|
155
|
-
|
|
156
|
-
|
|
206
|
+
if (!Number.isFinite(extended) || extended <= 0) {
|
|
207
|
+
return baseTimeoutMs;
|
|
208
|
+
}
|
|
209
|
+
return Math.max(baseTimeoutMs, extended);
|
|
157
210
|
}
|
|
158
211
|
/** V3 workflow mode: suppress write path when the user did not ask for file changes. */
|
|
159
212
|
export function resolveWorkflowType(agentTaskType, prompt) {
|
|
160
213
|
if (hasAnalyzeAndBuildIntent(prompt)) {
|
|
161
214
|
return 'full';
|
|
162
215
|
}
|
|
216
|
+
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt)) {
|
|
217
|
+
return taskRequiresWorkspaceChanges(prompt) ? 'full' : 'analysis_only';
|
|
218
|
+
}
|
|
163
219
|
if (!taskRequiresWorkspaceChanges(prompt)) {
|
|
164
220
|
return 'analysis_only';
|
|
165
221
|
}
|
|
@@ -36,7 +36,7 @@ export function normalizeV3WorkspaceRelativePath(rawPath, rootPath) {
|
|
|
36
36
|
return null;
|
|
37
37
|
};
|
|
38
38
|
const decodeBoundaryUri = (value) => {
|
|
39
|
-
const match = value.match(/^vigthoria:\/\/(?:workspace|server-internal)\/?(.*)$/i);
|
|
39
|
+
const match = value.match(/^vigthoria:\/\/(?:workspace|server-internal|local-workspace)\/?(.*)$/i);
|
|
40
40
|
if (match) {
|
|
41
41
|
return safeRelative(match[1] || '');
|
|
42
42
|
}
|