vigthoria-cli 1.11.28 → 1.11.29
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
CHANGED
|
@@ -185,7 +185,6 @@ export declare class ChatCommand {
|
|
|
185
185
|
*/
|
|
186
186
|
private tryTemplateInstantPath;
|
|
187
187
|
private tryDirectSingleFileFlow;
|
|
188
|
-
private isConfirmationFollowUp;
|
|
189
188
|
private taskRequiresWorkspaceChanges;
|
|
190
189
|
private getPreviousActionablePrompt;
|
|
191
190
|
private buildContextualAgentPrompt;
|
package/dist/commands/chat.js
CHANGED
|
@@ -17,7 +17,7 @@ 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, isAgentContinuePrompt, isAgentRetryPrompt, isBuiltContinuePrompt, isBuiltRetryPrompt, } from '../utils/requestIntent.js';
|
|
20
|
+
import { inferAgentTaskType as sharedInferAgentTaskType, inferAgentTaskTypeWithContext, isTrivialHtmlPageRequest, resolvePlannerAgentTimeoutMs, resolveWorkflowType, shouldSkipAnalysisRescue, taskRequiresWorkspaceChanges as promptRequiresWorkspaceChanges, taskRequiresWorkspaceChangesWithContext, buildExecutionHints, isAgentContinuePrompt, isAgentRetryPrompt, isBuiltContinuePrompt, isBuiltRetryPrompt, isBuiltWriteConfirmationPrompt, isConfirmationFollowUp, isWritePermissionGrant, } 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 = (() => {
|
|
@@ -2044,7 +2044,22 @@ export class ChatCommand {
|
|
|
2044
2044
|
}
|
|
2045
2045
|
async runSimplePrompt(prompt) {
|
|
2046
2046
|
if (!this.directPromptMode && !this.operatorMode) {
|
|
2047
|
-
const
|
|
2047
|
+
const isWriteFollowUp = isConfirmationFollowUp(prompt) || isWritePermissionGrant(prompt);
|
|
2048
|
+
if (isWriteFollowUp && (this.lastActionableUserInput || this.getPreviousActionablePrompt())) {
|
|
2049
|
+
if (!this.tools) {
|
|
2050
|
+
throw new Error('Agent tools are not initialized.');
|
|
2051
|
+
}
|
|
2052
|
+
this.agentMode = true;
|
|
2053
|
+
this.syncInteractiveModeModel('agent');
|
|
2054
|
+
if (this.currentSession) {
|
|
2055
|
+
this.currentSession.agentMode = true;
|
|
2056
|
+
this.currentSession.model = this.currentModel;
|
|
2057
|
+
}
|
|
2058
|
+
console.log(chalk.yellow('Write confirmation detected — switching to Agent mode with full file access.'));
|
|
2059
|
+
await this.runAgentTurn(prompt);
|
|
2060
|
+
return;
|
|
2061
|
+
}
|
|
2062
|
+
const promptToRun = isConfirmationFollowUp(prompt) && this.lastActionableUserInput && this.isRepoGroundedPrompt(this.lastActionableUserInput)
|
|
2048
2063
|
? this.lastActionableUserInput
|
|
2049
2064
|
: prompt;
|
|
2050
2065
|
if (this.isRepoGroundedPrompt(promptToRun) || /\b(build|implement|complete|fix|create|make|edit|write|change|finish)\b/i.test(promptToRun)) {
|
|
@@ -2215,7 +2230,7 @@ export class ChatCommand {
|
|
|
2215
2230
|
await this.runLocalAgentLoop(resolvedPrompt);
|
|
2216
2231
|
}
|
|
2217
2232
|
resolveAgentTurnPrompt(prompt) {
|
|
2218
|
-
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt)) {
|
|
2233
|
+
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt) || isBuiltWriteConfirmationPrompt(prompt)) {
|
|
2219
2234
|
return prompt;
|
|
2220
2235
|
}
|
|
2221
2236
|
if (isAgentContinuePrompt(prompt)) {
|
|
@@ -2236,6 +2251,15 @@ export class ChatCommand {
|
|
|
2236
2251
|
return followUp;
|
|
2237
2252
|
}
|
|
2238
2253
|
}
|
|
2254
|
+
if ((isConfirmationFollowUp(prompt) || isWritePermissionGrant(prompt)) && !isAgentContinuePrompt(prompt)) {
|
|
2255
|
+
const expanded = this.buildContextualAgentPrompt(prompt);
|
|
2256
|
+
if (expanded !== prompt) {
|
|
2257
|
+
if (!this.jsonOutput) {
|
|
2258
|
+
console.log(chalk.cyan('↪ Treating your message as write confirmation — applying the previous task with full write access.'));
|
|
2259
|
+
}
|
|
2260
|
+
return expanded;
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2239
2263
|
return prompt;
|
|
2240
2264
|
}
|
|
2241
2265
|
shouldPreserveBuildOutcomeForContinue(runPrompt, prior) {
|
|
@@ -2822,15 +2846,11 @@ export class ChatCommand {
|
|
|
2822
2846
|
}
|
|
2823
2847
|
return true;
|
|
2824
2848
|
}
|
|
2825
|
-
isConfirmationFollowUp(prompt) {
|
|
2826
|
-
const normalized = prompt.trim().toLowerCase().replace(/[.!?]+$/g, '').replace(/\s+/g, ' ');
|
|
2827
|
-
return /^(ja|ja bitte|ja bitte mach das|mach das|bitte mach das|genau|ok|okay|yes|yes please|please do|do it|go ahead|continue|proceed|make it so)$/.test(normalized);
|
|
2828
|
-
}
|
|
2829
2849
|
taskRequiresWorkspaceChanges(prompt) {
|
|
2830
2850
|
return promptRequiresWorkspaceChanges(prompt);
|
|
2831
2851
|
}
|
|
2832
2852
|
getPreviousActionablePrompt() {
|
|
2833
|
-
if (this.lastActionableUserInput && !
|
|
2853
|
+
if (this.lastActionableUserInput && !isConfirmationFollowUp(this.lastActionableUserInput)) {
|
|
2834
2854
|
return this.lastActionableUserInput;
|
|
2835
2855
|
}
|
|
2836
2856
|
for (let i = this.messages.length - 1; i >= 0; i -= 1) {
|
|
@@ -2838,7 +2858,9 @@ export class ChatCommand {
|
|
|
2838
2858
|
if (message.role !== 'user')
|
|
2839
2859
|
continue;
|
|
2840
2860
|
const content = (message.content || '').trim();
|
|
2841
|
-
if (!content ||
|
|
2861
|
+
if (!content || isConfirmationFollowUp(content) || isWritePermissionGrant(content))
|
|
2862
|
+
continue;
|
|
2863
|
+
if (isBuiltWriteConfirmationPrompt(content) || isBuiltContinuePrompt(content) || isBuiltRetryPrompt(content))
|
|
2842
2864
|
continue;
|
|
2843
2865
|
return content
|
|
2844
2866
|
.replace(/\n\nProject root:[\s\S]*$/i, '')
|
|
@@ -2848,7 +2870,7 @@ export class ChatCommand {
|
|
|
2848
2870
|
return '';
|
|
2849
2871
|
}
|
|
2850
2872
|
buildContextualAgentPrompt(prompt) {
|
|
2851
|
-
if (!
|
|
2873
|
+
if (!isConfirmationFollowUp(prompt) && !isWritePermissionGrant(prompt)) {
|
|
2852
2874
|
return prompt;
|
|
2853
2875
|
}
|
|
2854
2876
|
const previousPrompt = this.getPreviousActionablePrompt();
|
|
@@ -2856,13 +2878,14 @@ export class ChatCommand {
|
|
|
2856
2878
|
return prompt;
|
|
2857
2879
|
}
|
|
2858
2880
|
return [
|
|
2859
|
-
'The user confirmed
|
|
2881
|
+
'The user confirmed they want file changes applied. Execute the original task with full write access.',
|
|
2860
2882
|
'',
|
|
2861
2883
|
'Original task:',
|
|
2862
2884
|
previousPrompt,
|
|
2863
2885
|
'',
|
|
2864
|
-
`
|
|
2886
|
+
`User confirmation: ${prompt}`,
|
|
2865
2887
|
'',
|
|
2888
|
+
'Apply the requested file changes now. Do not stop at analysis or ask for permission again.',
|
|
2866
2889
|
'Do not reinterpret this confirmation as a new website, landing page, template, or index.html task.',
|
|
2867
2890
|
].join('\n');
|
|
2868
2891
|
}
|
|
@@ -2880,7 +2903,7 @@ export class ChatCommand {
|
|
|
2880
2903
|
}
|
|
2881
2904
|
const workspacePath = promptWorkspacePath || this.currentProjectPath;
|
|
2882
2905
|
const contextualPrompt = this.buildContextualAgentPrompt(prompt);
|
|
2883
|
-
if (contextualPrompt === prompt && !
|
|
2906
|
+
if (contextualPrompt === prompt && !isConfirmationFollowUp(prompt) && !isWritePermissionGrant(prompt)) {
|
|
2884
2907
|
this.lastActionableUserInput = prompt;
|
|
2885
2908
|
}
|
|
2886
2909
|
this.messages.push({ role: 'user', content: contextualPrompt });
|
|
@@ -2970,10 +2993,15 @@ export class ChatCommand {
|
|
|
2970
2993
|
}
|
|
2971
2994
|
};
|
|
2972
2995
|
const executionPrompt = this.buildExecutionPrompt(contextualPrompt);
|
|
2973
|
-
const
|
|
2974
|
-
const
|
|
2975
|
-
const
|
|
2996
|
+
const priorPrompt = this.getPreviousActionablePrompt();
|
|
2997
|
+
const intentContext = { priorPrompt: priorPrompt || null };
|
|
2998
|
+
const classificationPrompt = contextualPrompt;
|
|
2999
|
+
const agentTaskType = this.lastAgentRoute?.taskKind
|
|
3000
|
+
|| inferAgentTaskTypeWithContext(classificationPrompt, intentContext);
|
|
3001
|
+
const workflowType = resolveWorkflowType(agentTaskType, classificationPrompt, intentContext);
|
|
3002
|
+
const executionHints = buildExecutionHints(agentTaskType, classificationPrompt, {
|
|
2976
3003
|
fastPath: this.lastAgentRoute?.fastPath,
|
|
3004
|
+
priorPrompt: priorPrompt || null,
|
|
2977
3005
|
});
|
|
2978
3006
|
const workspaceContext = {
|
|
2979
3007
|
workspacePath: workspacePath,
|
|
@@ -3110,7 +3138,7 @@ export class ChatCommand {
|
|
|
3110
3138
|
const previewGate = (response.metadata?.previewGate || null);
|
|
3111
3139
|
const workspaceHasOutput = this.api.hasAgentWorkspaceOutput(workspaceContext);
|
|
3112
3140
|
const changedFileCount = response.changedFiles ? Object.keys(response.changedFiles).length : 0;
|
|
3113
|
-
const requiresWorkspaceChanges =
|
|
3141
|
+
const requiresWorkspaceChanges = taskRequiresWorkspaceChangesWithContext(contextualPrompt, intentContext);
|
|
3114
3142
|
const answerContent = normalizeAgentAnswerContent(response.content, this.v3StreamedAnswerBuffer);
|
|
3115
3143
|
liveOutcome.changedFileCount = changedFileCount;
|
|
3116
3144
|
liveOutcome.requiresWorkspaceChanges = requiresWorkspaceChanges;
|
|
@@ -3472,7 +3500,9 @@ export class ChatCommand {
|
|
|
3472
3500
|
this.v3StreamingStarted = false;
|
|
3473
3501
|
this.v3StartSeen = false;
|
|
3474
3502
|
try {
|
|
3475
|
-
const
|
|
3503
|
+
const retryPriorPrompt = this.getPreviousActionablePrompt();
|
|
3504
|
+
const retryContext = { priorPrompt: retryPriorPrompt || null };
|
|
3505
|
+
const retryTaskType = inferAgentTaskTypeWithContext(rawPrompt, retryContext);
|
|
3476
3506
|
const retryResponse = await this.api.runV3AgentWorkflow(executionPrompt, {
|
|
3477
3507
|
workspace: { path: this.currentProjectPath },
|
|
3478
3508
|
...workspaceContext,
|
|
@@ -3480,7 +3510,7 @@ export class ChatCommand {
|
|
|
3480
3510
|
clientSurface: 'cli',
|
|
3481
3511
|
localMachineCapable: true,
|
|
3482
3512
|
agentTaskType: retryTaskType,
|
|
3483
|
-
workflowType: resolveWorkflowType(retryTaskType, rawPrompt),
|
|
3513
|
+
workflowType: resolveWorkflowType(retryTaskType, rawPrompt, retryContext),
|
|
3484
3514
|
agentTimeoutMs: resolvePlannerAgentTimeoutMs(DEFAULT_V3_AGENT_TIMEOUT_MS, retryTaskType, rawPrompt),
|
|
3485
3515
|
agentIdleTimeoutMs: DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS,
|
|
3486
3516
|
agentSoftTimeoutMs: DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS,
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Shared prompt intent detection for CLI routing, V3 hints, and rescue gating.
|
|
3
3
|
* Keep aligned with V3-Code-Agent/agent.py _classify_request heuristics.
|
|
4
4
|
*/
|
|
5
|
+
export type IntentContext = {
|
|
6
|
+
priorPrompt?: string | null;
|
|
7
|
+
};
|
|
5
8
|
/** Strip CLI-appended platform / mode shaping so it cannot flip quality profiles. */
|
|
6
9
|
export declare function stripExecutionShaping(prompt: string): string;
|
|
7
10
|
export declare function hasBuildVerb(prompt: string): boolean;
|
|
@@ -17,10 +20,20 @@ export declare function isContinueOrRetryPrompt(prompt: string): boolean;
|
|
|
17
20
|
export declare function hasWebPageIntent(prompt: string): boolean;
|
|
18
21
|
export declare function isTrivialHtmlPageRequest(prompt: string): boolean;
|
|
19
22
|
export declare function hasCloneBuildIntent(prompt: string): boolean;
|
|
23
|
+
export declare function isWritePermissionGrant(prompt: string): boolean;
|
|
24
|
+
/** Short or extended confirmations that should chain to the prior actionable request. */
|
|
25
|
+
export declare function isConfirmationFollowUp(prompt: string): boolean;
|
|
26
|
+
/** True when the CLI expanded a write-confirmation follow-up for V3. */
|
|
27
|
+
export declare function isBuiltWriteConfirmationPrompt(prompt: string): boolean;
|
|
28
|
+
export declare function hasFixOrCorrectIntent(prompt: string): boolean;
|
|
29
|
+
export declare function isReadOnlyCheckIntent(prompt: string): boolean;
|
|
20
30
|
export declare function hasExplicitWriteIntent(prompt: string): boolean;
|
|
21
31
|
export declare function taskRequiresWorkspaceChanges(prompt: string): boolean;
|
|
32
|
+
export declare function resolveClassificationPrompt(prompt: string, context?: IntentContext): string;
|
|
33
|
+
export declare function taskRequiresWorkspaceChangesWithContext(prompt: string, context?: IntentContext): boolean;
|
|
22
34
|
export declare function hasAnalyzeAndBuildIntent(prompt: string): boolean;
|
|
23
35
|
export declare function inferAgentTaskType(prompt: string): string;
|
|
36
|
+
export declare function inferAgentTaskTypeWithContext(prompt: string, context?: IntentContext): string;
|
|
24
37
|
export declare function shouldSkipAnalysisRescue(liveOutcome: {
|
|
25
38
|
tasksTotal?: number;
|
|
26
39
|
changedFileCount?: number;
|
|
@@ -29,9 +42,10 @@ export declare function shouldSkipAnalysisRescue(liveOutcome: {
|
|
|
29
42
|
export declare function isPlannerBuildTask(agentTaskType: string, prompt: string): boolean;
|
|
30
43
|
export declare function resolvePlannerAgentTimeoutMs(baseTimeoutMs: number, agentTaskType: string, prompt: string): number;
|
|
31
44
|
/** V3 workflow mode: suppress write path when the user did not ask for file changes. */
|
|
32
|
-
export declare function resolveWorkflowType(agentTaskType: string, prompt: string): 'analysis_only' | 'full';
|
|
45
|
+
export declare function resolveWorkflowType(agentTaskType: string, prompt: string, context?: IntentContext): 'analysis_only' | 'full';
|
|
33
46
|
export declare function buildExecutionHints(agentTaskType: string, prompt: string, options?: {
|
|
34
47
|
fastPath?: string;
|
|
48
|
+
priorPrompt?: string | null;
|
|
35
49
|
}): {
|
|
36
50
|
task_kind: string;
|
|
37
51
|
requires_file_changes: boolean | undefined;
|
|
@@ -11,8 +11,14 @@ const GAME_INTENT = /\b(game|spiel|playable|html5\s+(?:game|canvas)|html5\s+game
|
|
|
11
11
|
const WEB_PAGE_INTENT = /\b(website|web\s*site|webpage|web\s*page|landing\s+page|home\s*page|index\.html|html\s+page|static\s+page|single\s+page|popup|alert|modal|hello\s+world)\b/i;
|
|
12
12
|
const CLONE_BUILD = /\bclone\s+of\b|\b(build|create|make)\s+(?:a|an|the|us|me)?\s*(?:clone|replica|remake|port)\b/i;
|
|
13
13
|
const READ_ONLY_INTENT = /\b(analy[sz]e|analyse|analysis|audit|review|inspect|proof|understand|summari[sz]e|scan|read[\s-]?only|where we left|what is|how does|show me|tell me|identify\s+gaps?|gap\s+analysis|production\s+blockers?)\b/i;
|
|
14
|
-
const EXPLICIT_WRITE_VERBS = /\b(implement|write|edit|modify|update|fix|repair|create|build|generate|scaffold|deploy|refactor|develop|integrate)\b/i;
|
|
14
|
+
const EXPLICIT_WRITE_VERBS = /\b(implement|write|edit|modify|update|fix|repair|create|build|generate|scaffold|deploy|refactor|develop|integrate|correct|apply|patch)\b/i;
|
|
15
15
|
const TRIVIAL_HTML_PAGE = /\b(hello\s*world|simple\s+(?:html|web|page|site)|html5\s+website|html\s+5\s+website|popup|alert\s*\(|show\s+a\s+popup|one\s+page|single\s+html)\b/i;
|
|
16
|
+
/** User explicitly grants write permission after an analysis or confirmation gate. */
|
|
17
|
+
const WRITE_PERMISSION_GRANT = /\b(?:hereby\s+confirm|i\s+confirm|confirm(?:ed)?\s+that|give\s+(?:you|permission)|granting\s+permission|allow\s+(?:you|me\s+to)|you\s+(?:may|can|have\s+permission\s+to)|permission\s+to|authorized?\s+to|approve(?:d)?\s+(?:the\s+)?(?:changes?|writes?|edits?)|go\s+ahead\s+and(?:\s+write|\s+apply|\s+make|\s+do)?|do\s+all\s+the\s+changes|apply\s+(?:the\s+)?(?:changes?|fixes?|fix)|proceed\s+with\s+(?:the\s+)?(?:changes?|fixes?|implementation|writes?)|make\s+(?:the\s+)?changes|please\s+write)\b/i;
|
|
18
|
+
/** Fix/correct/repair syntax or errors — write path without requiring artifact nouns. */
|
|
19
|
+
const FIX_CORRECT_INTENT = /\b(correct|fix|repair|resolve|patch|address|remedy)\b[\s\S]{0,48}\b(syntax|errors?|bugs?|issues?|mistakes?|typos?)\b|\b(syntax|errors?|bugs?|issues?)\b[\s\S]{0,48}\b(correct|fix|repair|resolve|patch)\b/i;
|
|
20
|
+
/** Read-only audit: check/review/find issues without an paired fix/implement verb nearby. */
|
|
21
|
+
const READ_ONLY_CHECK = /\b(check|verify|audit|inspect|review|investigate|look\s+for|find|scan|validate|examine)\b[\s\S]{0,60}\b(syntax|errors?|bugs?|issues?|missing|gaps?|functionality)\b/i;
|
|
16
22
|
/** Strip CLI-appended platform / mode shaping so it cannot flip quality profiles. */
|
|
17
23
|
export function stripExecutionShaping(prompt) {
|
|
18
24
|
return String(prompt || '')
|
|
@@ -120,8 +126,57 @@ export function isTrivialHtmlPageRequest(prompt) {
|
|
|
120
126
|
export function hasCloneBuildIntent(prompt) {
|
|
121
127
|
return CLONE_BUILD.test(stripExecutionShaping(prompt)) && hasBuildVerb(prompt);
|
|
122
128
|
}
|
|
129
|
+
export function isWritePermissionGrant(prompt) {
|
|
130
|
+
const text = stripExecutionShaping(prompt);
|
|
131
|
+
return WRITE_PERMISSION_GRANT.test(text)
|
|
132
|
+
|| /\ballow\s+you\s+to\s+do\s+all\s+the\s+changes\b/i.test(text)
|
|
133
|
+
|| /\b(?:i\s+)?(?:allow|permit)\s+you\s+to\s+write\b/i.test(text);
|
|
134
|
+
}
|
|
135
|
+
/** Short or extended confirmations that should chain to the prior actionable request. */
|
|
136
|
+
export function isConfirmationFollowUp(prompt) {
|
|
137
|
+
const normalized = stripExecutionShaping(prompt).trim().toLowerCase().replace(/[.!?]+$/g, '').replace(/\s+/g, ' ');
|
|
138
|
+
if (!normalized) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
if (/^(ja|ja bitte|ja bitte mach das|mach das|bitte mach das|genau|ok|okay|yes|yes please|please do|do it|go ahead|continue|proceed|make it so)$/.test(normalized)) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
if (/^(please\s+)?(?:do\s+it|make\s+(?:the\s+)?changes|apply\s+(?:them|the\s+fixes|changes|the\s+fix)|fix\s+(?:them|it|now)|go\s+ahead)$/.test(normalized)) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
return isWritePermissionGrant(prompt);
|
|
148
|
+
}
|
|
149
|
+
/** True when the CLI expanded a write-confirmation follow-up for V3. */
|
|
150
|
+
export function isBuiltWriteConfirmationPrompt(prompt) {
|
|
151
|
+
return /^The user confirmed they want file changes applied/i.test(stripExecutionShaping(prompt));
|
|
152
|
+
}
|
|
153
|
+
export function hasFixOrCorrectIntent(prompt) {
|
|
154
|
+
return FIX_CORRECT_INTENT.test(stripExecutionShaping(prompt));
|
|
155
|
+
}
|
|
156
|
+
export function isReadOnlyCheckIntent(prompt) {
|
|
157
|
+
const text = stripExecutionShaping(prompt);
|
|
158
|
+
if (!READ_ONLY_CHECK.test(text)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
if (hasFixOrCorrectIntent(prompt) || isWritePermissionGrant(prompt)) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (/\b(?:fix|correct|repair|implement|apply|write|change|update)\b/i.test(text)) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
123
169
|
export function hasExplicitWriteIntent(prompt) {
|
|
124
170
|
const text = stripExecutionShaping(prompt);
|
|
171
|
+
if (isWritePermissionGrant(prompt)) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
if (hasFixOrCorrectIntent(prompt)) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
if (isReadOnlyCheckIntent(prompt)) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
125
180
|
return (BUILD_VERBS.test(text) && ARTIFACT_NOUNS.test(text))
|
|
126
181
|
|| hasCloneBuildIntent(prompt)
|
|
127
182
|
|| (BUILD_VERBS.test(text) && hasGameIntent(prompt));
|
|
@@ -129,13 +184,41 @@ export function hasExplicitWriteIntent(prompt) {
|
|
|
129
184
|
export function taskRequiresWorkspaceChanges(prompt) {
|
|
130
185
|
const text = String(prompt || '').trim();
|
|
131
186
|
const shaped = stripExecutionShaping(text);
|
|
132
|
-
const readOnlyIntent = READ_ONLY_INTENT.test(shaped);
|
|
187
|
+
const readOnlyIntent = READ_ONLY_INTENT.test(shaped) || isReadOnlyCheckIntent(text);
|
|
133
188
|
const explicitWriteIntent = hasExplicitWriteIntent(text);
|
|
134
189
|
if (readOnlyIntent && !explicitWriteIntent) {
|
|
135
190
|
return false;
|
|
136
191
|
}
|
|
137
192
|
return explicitWriteIntent;
|
|
138
193
|
}
|
|
194
|
+
export function resolveClassificationPrompt(prompt, context = {}) {
|
|
195
|
+
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt) || isBuiltWriteConfirmationPrompt(prompt)) {
|
|
196
|
+
return prompt;
|
|
197
|
+
}
|
|
198
|
+
const prior = String(context.priorPrompt || '').trim();
|
|
199
|
+
if (prior && (isConfirmationFollowUp(prompt) || isWritePermissionGrant(prompt))) {
|
|
200
|
+
return `${prompt}\n\nPrior actionable request:\n${prior}`;
|
|
201
|
+
}
|
|
202
|
+
return prompt;
|
|
203
|
+
}
|
|
204
|
+
export function taskRequiresWorkspaceChangesWithContext(prompt, context = {}) {
|
|
205
|
+
if (isBuiltWriteConfirmationPrompt(prompt) || isWritePermissionGrant(prompt)) {
|
|
206
|
+
const prior = String(context.priorPrompt || '').trim();
|
|
207
|
+
if (prior) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return isWritePermissionGrant(prompt);
|
|
211
|
+
}
|
|
212
|
+
const effective = resolveClassificationPrompt(prompt, context);
|
|
213
|
+
if (taskRequiresWorkspaceChanges(effective)) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
const prior = String(context.priorPrompt || '').trim();
|
|
217
|
+
if (prior && isConfirmationFollowUp(prompt)) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
139
222
|
export function hasAnalyzeAndBuildIntent(prompt) {
|
|
140
223
|
const text = stripExecutionShaping(prompt);
|
|
141
224
|
return /\b(analy[sz]e|analyse)\b/i.test(text)
|
|
@@ -144,6 +227,21 @@ export function hasAnalyzeAndBuildIntent(prompt) {
|
|
|
144
227
|
}
|
|
145
228
|
export function inferAgentTaskType(prompt) {
|
|
146
229
|
const text = stripExecutionShaping(prompt);
|
|
230
|
+
if (isBuiltWriteConfirmationPrompt(prompt)) {
|
|
231
|
+
if (hasGameIntent(prompt)) {
|
|
232
|
+
return 'game-build';
|
|
233
|
+
}
|
|
234
|
+
if (hasFixOrCorrectIntent(prompt) || /\bsyntax\b/i.test(text)) {
|
|
235
|
+
return 'repair';
|
|
236
|
+
}
|
|
237
|
+
return 'implementation';
|
|
238
|
+
}
|
|
239
|
+
if (hasFixOrCorrectIntent(prompt)) {
|
|
240
|
+
if (hasGameIntent(prompt)) {
|
|
241
|
+
return 'game-build';
|
|
242
|
+
}
|
|
243
|
+
return 'repair';
|
|
244
|
+
}
|
|
147
245
|
if (hasAnalyzeAndBuildIntent(prompt)) {
|
|
148
246
|
if (hasGameIntent(prompt)) {
|
|
149
247
|
return 'game-build';
|
|
@@ -153,7 +251,10 @@ export function inferAgentTaskType(prompt) {
|
|
|
153
251
|
}
|
|
154
252
|
return 'implementation';
|
|
155
253
|
}
|
|
156
|
-
if (
|
|
254
|
+
if (isReadOnlyCheckIntent(prompt)) {
|
|
255
|
+
return 'debugging';
|
|
256
|
+
}
|
|
257
|
+
if (/\b(inspect|analyze|analyse|audit|review|find|diagnose|debug|trace|compare|diff|investigate)\b/i.test(text)
|
|
157
258
|
&& !hasExplicitWriteIntent(prompt)) {
|
|
158
259
|
return 'debugging';
|
|
159
260
|
}
|
|
@@ -170,7 +271,31 @@ export function inferAgentTaskType(prompt) {
|
|
|
170
271
|
}
|
|
171
272
|
return 'implementation';
|
|
172
273
|
}
|
|
173
|
-
|
|
274
|
+
if (hasExplicitWriteIntent(prompt)) {
|
|
275
|
+
return 'implementation';
|
|
276
|
+
}
|
|
277
|
+
return 'general';
|
|
278
|
+
}
|
|
279
|
+
export function inferAgentTaskTypeWithContext(prompt, context = {}) {
|
|
280
|
+
const prior = String(context.priorPrompt || '').trim();
|
|
281
|
+
if ((isConfirmationFollowUp(prompt) || isWritePermissionGrant(prompt) || isBuiltWriteConfirmationPrompt(prompt)) && prior) {
|
|
282
|
+
const priorType = inferAgentTaskType(prior);
|
|
283
|
+
if (isWritePermissionGrant(prompt) || isBuiltWriteConfirmationPrompt(prompt)) {
|
|
284
|
+
if (priorType === 'analysis' || priorType === 'debugging' || priorType === 'general') {
|
|
285
|
+
if (hasFixOrCorrectIntent(prior) || /\bsyntax\b/i.test(prior)) {
|
|
286
|
+
return 'repair';
|
|
287
|
+
}
|
|
288
|
+
if (hasGameIntent(prior)) {
|
|
289
|
+
return 'game-build';
|
|
290
|
+
}
|
|
291
|
+
return 'implementation';
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (priorType !== 'general') {
|
|
295
|
+
return priorType;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return inferAgentTaskType(resolveClassificationPrompt(prompt, context));
|
|
174
299
|
}
|
|
175
300
|
export function shouldSkipAnalysisRescue(liveOutcome) {
|
|
176
301
|
if (liveOutcome.requiresWorkspaceChanges) {
|
|
@@ -209,25 +334,36 @@ export function resolvePlannerAgentTimeoutMs(baseTimeoutMs, agentTaskType, promp
|
|
|
209
334
|
return Math.max(baseTimeoutMs, extended);
|
|
210
335
|
}
|
|
211
336
|
/** V3 workflow mode: suppress write path when the user did not ask for file changes. */
|
|
212
|
-
export function resolveWorkflowType(agentTaskType, prompt) {
|
|
337
|
+
export function resolveWorkflowType(agentTaskType, prompt, context = {}) {
|
|
338
|
+
if (isBuiltWriteConfirmationPrompt(prompt) || isWritePermissionGrant(prompt)) {
|
|
339
|
+
return 'full';
|
|
340
|
+
}
|
|
213
341
|
if (hasAnalyzeAndBuildIntent(prompt)) {
|
|
214
342
|
return 'full';
|
|
215
343
|
}
|
|
216
344
|
if (isBuiltContinuePrompt(prompt) || isBuiltRetryPrompt(prompt)) {
|
|
217
|
-
return
|
|
345
|
+
return taskRequiresWorkspaceChangesWithContext(prompt, context) ? 'full' : 'analysis_only';
|
|
346
|
+
}
|
|
347
|
+
const prior = String(context.priorPrompt || '').trim();
|
|
348
|
+
if (prior && isConfirmationFollowUp(prompt)) {
|
|
349
|
+
return 'full';
|
|
218
350
|
}
|
|
219
|
-
if (!
|
|
351
|
+
if (!taskRequiresWorkspaceChangesWithContext(prompt, context)) {
|
|
220
352
|
return 'analysis_only';
|
|
221
353
|
}
|
|
222
354
|
const kind = String(agentTaskType || '').toLowerCase();
|
|
223
|
-
if (kind === 'analysis' || kind === 'debugging' || kind === 'verification')
|
|
355
|
+
if ((kind === 'analysis' || kind === 'debugging' || kind === 'verification')
|
|
356
|
+
&& !hasFixOrCorrectIntent(prompt)
|
|
357
|
+
&& !isWritePermissionGrant(prompt)) {
|
|
224
358
|
return 'analysis_only';
|
|
225
359
|
}
|
|
226
360
|
return 'full';
|
|
227
361
|
}
|
|
228
362
|
export function buildExecutionHints(agentTaskType, prompt, options = {}) {
|
|
229
|
-
const
|
|
230
|
-
const
|
|
363
|
+
const context = { priorPrompt: options.priorPrompt ?? null };
|
|
364
|
+
const effectiveTaskType = inferAgentTaskTypeWithContext(prompt, context);
|
|
365
|
+
const workflowType = resolveWorkflowType(effectiveTaskType, prompt, context);
|
|
366
|
+
const kind = String(effectiveTaskType || agentTaskType || 'general').toLowerCase();
|
|
231
367
|
const hints = {
|
|
232
368
|
task_kind: kind,
|
|
233
369
|
requires_file_changes: workflowType === 'analysis_only' ? false : undefined,
|
package/package.json
CHANGED
|
@@ -97,9 +97,23 @@ python3 - << 'PY'
|
|
|
97
97
|
import json
|
|
98
98
|
ids={m.get('id','') for m in json.load(open('/tmp/vig-models.json')).get('data',[])}
|
|
99
99
|
if ids:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
has_router = any(
|
|
101
|
+
m in ids for m in (
|
|
102
|
+
'vigthoria-balanced-4b', 'vigthoria-balanced-4b:latest',
|
|
103
|
+
'vigthoria-v3-balanced-4b', 'vigthoria-v3-balanced-4b:latest',
|
|
104
|
+
'vigthoria-fast-9b', 'vigthoria-fast-9b:latest',
|
|
105
|
+
)
|
|
106
|
+
)
|
|
107
|
+
has_creative = any(
|
|
108
|
+
m in ids for m in (
|
|
109
|
+
'vigthoria-creative-9b-v4', 'vigthoria-creative-9b-v4:latest',
|
|
110
|
+
'vigthoria-fast-9b', 'vigthoria-fast-9b:latest',
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
has_code = any('vigthoria-v3-code-35b' in i for i in ids)
|
|
114
|
+
assert has_router, f'missing router model in inventory: {sorted(ids)}'
|
|
115
|
+
assert has_creative, f'missing creative/fast model in inventory: {sorted(ids)}'
|
|
116
|
+
assert has_code, f'missing code model in inventory: {sorted(ids)}'
|
|
103
117
|
else:
|
|
104
118
|
print('[warn] model inventory empty on this host; route proof above is authoritative')
|
|
105
119
|
print('[pass] model inventory gates')
|