vigthoria-cli 1.13.31 → 1.13.42
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/README.md +11 -56
- package/SECURITY_HARDENING.md +2 -4
- package/dist/commands/auth.js +16 -14
- package/dist/commands/cancel.d.ts +1 -0
- package/dist/commands/cancel.js +21 -4
- package/dist/commands/chat.d.ts +13 -0
- package/dist/commands/chat.js +170 -14
- package/dist/commands/fork.js +8 -3
- package/dist/commands/history.js +8 -3
- package/dist/commands/legion.js +1 -1
- package/dist/commands/replay.js +8 -3
- package/dist/commands/update-registration.js +63 -206
- package/dist/commands/v4-menu.d.ts +0 -1
- package/dist/commands/v4-menu.js +8 -6
- package/dist/commands/v4-registration.js +0 -2
- package/dist/commands/v4.js +9 -4
- package/dist/commands/wallet.d.ts +1 -1
- package/dist/commands/wallet.js +3 -3
- package/dist/index.js +2 -3
- package/dist/utils/agent-stream-state.d.ts +7 -0
- package/dist/utils/agent-stream-state.js +31 -0
- package/dist/utils/agentRunOutcome.js +5 -1
- package/dist/utils/api.d.ts +21 -3
- package/dist/utils/api.js +379 -550
- package/dist/utils/frontend-preview-service.d.ts +12 -2
- package/dist/utils/frontend-preview-service.js +214 -24
- package/dist/utils/javascript-syntax.d.ts +19 -0
- package/dist/utils/javascript-syntax.js +35 -0
- package/dist/utils/localTestMode.js +1 -1
- package/dist/utils/mutation-journal.d.ts +10 -0
- package/dist/utils/mutation-journal.js +104 -76
- package/dist/utils/network-policy.js +7 -10
- package/dist/utils/preview-screenshot-adapter.d.ts +111 -1
- package/dist/utils/preview-screenshot-adapter.js +990 -7
- package/dist/utils/release-install.d.ts +0 -1
- package/dist/utils/release-install.js +44 -7
- package/dist/utils/requestIntent.d.ts +1 -1
- package/dist/utils/requestIntent.js +17 -3
- package/dist/utils/tools.js +21 -15
- package/dist/utils/update-policy.d.ts +0 -4
- package/dist/utils/update-policy.js +5 -9
- package/dist/utils/v3-agent-client.js +25 -11
- package/install.ps1 +30 -50
- package/install.sh +12 -23
- package/package.json +4 -2
- package/release-policy.json +1 -5
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +6 -7
- package/scripts/release/install-release.mjs +5 -4
- package/scripts/release/publish-cli-release.mjs +21 -8
- package/scripts/release/test-balanced-model-live.sh +4 -1
- package/scripts/release/validate-live-service-gates.sh +27 -5
package/README.md
CHANGED
|
@@ -35,78 +35,33 @@ The `vigthoria-cli` package installs the `vigthoria`, `vig`, and `vigthoria-chat
|
|
|
35
35
|
### Quick Install (Linux/macOS)
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
curl -fsSL https://
|
|
38
|
+
curl -fsSL https://extension.vigthoria.io/downloads/install.sh | bash
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
### Quick Install (Windows PowerShell)
|
|
42
42
|
|
|
43
43
|
```powershell
|
|
44
|
-
irm https://
|
|
44
|
+
irm https://extension.vigthoria.io/downloads/install.ps1 | iex
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
npm install -g vigthoria-cli
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Manual Install
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
# Clone from Vigthoria Market
|
|
57
|
-
git clone https://market.vigthoria.io/vigthoria/vigthoria-cli.git
|
|
58
|
-
cd vigthoria-cli
|
|
59
|
-
|
|
60
|
-
# Or from Vigthoria Community
|
|
61
|
-
git clone https://community.vigthoria.io/repos/vigthoria-cli.git
|
|
62
|
-
cd vigthoria-cli
|
|
63
|
-
|
|
64
|
-
# Install dependencies
|
|
65
|
-
npm install
|
|
66
|
-
|
|
67
|
-
# Build
|
|
68
|
-
npm run build
|
|
69
|
-
|
|
70
|
-
# Link globally
|
|
71
|
-
npm link
|
|
72
|
-
```
|
|
47
|
+
The installer downloads the signed release manifest and package only from
|
|
48
|
+
`extension.vigthoria.io`, verifies the detached Ed25519 signature and SHA-256
|
|
49
|
+
identity, and installs the verified local archive transactionally.
|
|
73
50
|
|
|
74
51
|
## Troubleshooting Installation
|
|
75
52
|
|
|
76
|
-
### Network Issues
|
|
53
|
+
### Network Issues
|
|
77
54
|
|
|
78
|
-
If
|
|
55
|
+
If the canonical extension endpoint cannot be reached:
|
|
79
56
|
|
|
80
57
|
1. **Check internet connection:**
|
|
81
58
|
```bash
|
|
82
|
-
|
|
59
|
+
curl -I https://extension.vigthoria.io/downloads/manifest.json
|
|
83
60
|
```
|
|
84
61
|
|
|
85
|
-
2.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
npm config set https-proxy http://proxy.company.com:8080
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
3. **Try an alternative npm registry:**
|
|
92
|
-
```bash
|
|
93
|
-
npm config set registry https://registry.npmmirror.com
|
|
94
|
-
npm install -g vigthoria-cli
|
|
95
|
-
# Reset to default after:
|
|
96
|
-
npm config delete registry
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
4. **Direct tarball download:**
|
|
100
|
-
```bash
|
|
101
|
-
# Download directly
|
|
102
|
-
npm install -g https://coder.vigthoria.io/releases/vigthoria-cli-latest.tgz
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
5. **Use Git clone method (no npm registry needed):**
|
|
106
|
-
```bash
|
|
107
|
-
git clone https://market.vigthoria.io/vigthoria/vigthoria-cli.git
|
|
108
|
-
cd vigthoria-cli && npm install && npm run build && npm link
|
|
109
|
-
```
|
|
62
|
+
2. Permit outbound HTTPS to `extension.vigthoria.io` through the corporate
|
|
63
|
+
proxy or firewall. Do not substitute a registry, mirror, Git clone, or
|
|
64
|
+
alternate download host for the signed release path.
|
|
110
65
|
|
|
111
66
|
### Windows-Specific Issues
|
|
112
67
|
|
package/SECURITY_HARDENING.md
CHANGED
|
@@ -21,7 +21,7 @@ The code model is now branded as **Vigthoria_v3_Code_30B**:
|
|
|
21
21
|
|
|
22
22
|
1. **Installation:**
|
|
23
23
|
```bash
|
|
24
|
-
|
|
24
|
+
curl -fsSL https://extension.vigthoria.io/downloads/install.sh | bash
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
2. **Login:**
|
|
@@ -57,14 +57,12 @@ When users with version < 1.4.0 run the CLI, they will see:
|
|
|
57
57
|
⚠️ SECURITY UPDATE AVAILABLE
|
|
58
58
|
Version 1.3.0 has security vulnerabilities.
|
|
59
59
|
Please update to 1.4.0 immediately:
|
|
60
|
-
|
|
60
|
+
vigthoria update
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
### Update Command
|
|
64
64
|
```bash
|
|
65
65
|
vigthoria update
|
|
66
|
-
# or
|
|
67
|
-
npm install -g vigthoria-cli@latest
|
|
68
66
|
```
|
|
69
67
|
|
|
70
68
|
## Vulnerabilities Fixed
|
package/dist/commands/auth.js
CHANGED
|
@@ -525,25 +525,27 @@ export async function statusAction() {
|
|
|
525
525
|
console.log(chalk.yellow('Not logged in.'));
|
|
526
526
|
return;
|
|
527
527
|
}
|
|
528
|
-
const authProbeHeaders = {
|
|
529
|
-
Authorization: `Bearer ${effectiveToken}`,
|
|
530
|
-
Cookie: `vigthoria-auth-token=${effectiveToken}`,
|
|
531
|
-
};
|
|
532
|
-
let authLooksValid = true;
|
|
533
528
|
try {
|
|
534
|
-
|
|
535
|
-
if (authProbe.status === 401 || authProbe.status === 403) {
|
|
536
|
-
authLooksValid = false;
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
catch {
|
|
540
|
-
// Network failures should not force logout status.
|
|
529
|
+
validateTokenStructure(effectiveToken, effectiveApiUrl);
|
|
541
530
|
}
|
|
542
|
-
|
|
531
|
+
catch (error) {
|
|
543
532
|
throw new CliCommandError('Not logged in. Session expired or invalid. Run: vigthoria login', {
|
|
544
|
-
code: 'AUTH_SESSION_INVALID', category: 'authentication',
|
|
533
|
+
code: 'AUTH_SESSION_INVALID', category: 'authentication', cause: error,
|
|
545
534
|
});
|
|
546
535
|
}
|
|
536
|
+
try {
|
|
537
|
+
await new AuthSessionService(sharedConfig).validateServerAcceptance(effectiveToken, effectiveApiUrl);
|
|
538
|
+
}
|
|
539
|
+
catch (error) {
|
|
540
|
+
// An explicit authorization rejection invalidates the session. Network
|
|
541
|
+
// and optional-route failures keep local status available as degraded,
|
|
542
|
+
// matching the health-probe behavior below.
|
|
543
|
+
if (/HTTP\s+(?:401|403)\b/i.test(humanMessage(error))) {
|
|
544
|
+
throw new CliCommandError('Not logged in. Session expired or invalid. Run: vigthoria login', {
|
|
545
|
+
code: 'AUTH_SESSION_INVALID', category: 'authentication', cause: error,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
}
|
|
547
549
|
let user = legacyConfig.user;
|
|
548
550
|
try {
|
|
549
551
|
user = await whoami();
|
package/dist/commands/cancel.js
CHANGED
|
@@ -10,6 +10,18 @@ import chalk from 'chalk';
|
|
|
10
10
|
import { createSpinner, CH } from '../utils/logger.js';
|
|
11
11
|
import { SessionManager } from '../utils/session.js';
|
|
12
12
|
import { CliCommandError, formatSuccessJson } from '../utils/command-contract.js';
|
|
13
|
+
export function resolveCancelRunsPath(baseUrl) {
|
|
14
|
+
try {
|
|
15
|
+
return new Set(['8032', '18032']).has(new URL(String(baseUrl)).port)
|
|
16
|
+
? '/api/runs'
|
|
17
|
+
: '/api/runs-cli';
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return /(?:127\.0\.0\.1|localhost|172\.19\.0\.1|host\.lan):(?:8032|18032)(?:\/|$)/i.test(String(baseUrl))
|
|
21
|
+
? '/api/runs'
|
|
22
|
+
: '/api/runs-cli';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
13
25
|
export class CancelCommand {
|
|
14
26
|
config;
|
|
15
27
|
logger;
|
|
@@ -19,7 +31,11 @@ export class CancelCommand {
|
|
|
19
31
|
this.logger = logger;
|
|
20
32
|
}
|
|
21
33
|
getHeaders() {
|
|
22
|
-
const headers = {
|
|
34
|
+
const headers = {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'X-Vigthoria-Agent-Lane': 'cli',
|
|
37
|
+
'X-Vigthoria-Source-Product': 'vigthoria-cli',
|
|
38
|
+
};
|
|
23
39
|
const token = process.env.VIGTHORIA_TOKEN ||
|
|
24
40
|
process.env.VIGTHORIA_AUTH_TOKEN ||
|
|
25
41
|
this.config.get('authToken');
|
|
@@ -37,11 +53,12 @@ export class CancelCommand {
|
|
|
37
53
|
const allowLocal = process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
38
54
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
39
55
|
process.env.V3_AGENT_URL ||
|
|
40
|
-
(allowLocal ? 'http://127.0.0.1:
|
|
56
|
+
(allowLocal ? 'http://127.0.0.1:8032' : null) ||
|
|
41
57
|
configuredApiUrl);
|
|
42
58
|
}
|
|
43
59
|
async listActive(baseUrl) {
|
|
44
|
-
const
|
|
60
|
+
const runsPath = resolveCancelRunsPath(baseUrl);
|
|
61
|
+
const resp = await fetch(`${baseUrl}${runsPath}/active`, { headers: this.getHeaders() });
|
|
45
62
|
if (!resp.ok) {
|
|
46
63
|
if (resp.status === 404 || resp.status === 502 || resp.status === 503) {
|
|
47
64
|
throw new CliCommandError(`V3 cancel API is not available on ${baseUrl}. Backend may not expose /api/runs/active.`, { code: 'CANCEL_API_UNAVAILABLE', category: 'network', status: resp.status });
|
|
@@ -59,7 +76,7 @@ export class CancelCommand {
|
|
|
59
76
|
return (await resp.json());
|
|
60
77
|
}
|
|
61
78
|
async cancelOne(baseUrl, contextId) {
|
|
62
|
-
const resp = await fetch(`${baseUrl}
|
|
79
|
+
const resp = await fetch(`${baseUrl}${resolveCancelRunsPath(baseUrl)}/${encodeURIComponent(contextId)}/cancel`, { method: 'POST', headers: this.getHeaders() });
|
|
63
80
|
if (!resp.ok) {
|
|
64
81
|
if (resp.status === 404) {
|
|
65
82
|
throw new CliCommandError(`No active run for context_id=${contextId}`, { code: 'ACTIVE_RUN_NOT_FOUND', status: resp.status });
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -52,6 +52,9 @@ export declare class ChatCommand {
|
|
|
52
52
|
private retryPromptSignature;
|
|
53
53
|
private retryPromptStreak;
|
|
54
54
|
private readonly streamState;
|
|
55
|
+
private processInterruptHandled;
|
|
56
|
+
private readonly onSigint;
|
|
57
|
+
private readonly onSigterm;
|
|
55
58
|
private lastAgentRoute;
|
|
56
59
|
private pendingGoaContext;
|
|
57
60
|
private lastAgentRunOutcome;
|
|
@@ -131,6 +134,16 @@ export declare class ChatCommand {
|
|
|
131
134
|
private updateOperatorSpinner;
|
|
132
135
|
constructor(config: Config, logger: Logger, commandProgram?: Command);
|
|
133
136
|
run(options: ChatOptions): Promise<void>;
|
|
137
|
+
private installProcessInterruptHandlers;
|
|
138
|
+
private removeProcessInterruptHandlers;
|
|
139
|
+
private handleProcessInterrupt;
|
|
140
|
+
/**
|
|
141
|
+
* Signal handlers cannot await the normal run lifecycle. Persist the
|
|
142
|
+
* terminal checkpoint synchronously after workspace rollback so a killed
|
|
143
|
+
* foreground process is never advertised as resumable work still running.
|
|
144
|
+
*/
|
|
145
|
+
private finalizeInterruptedAgentCheckpoint;
|
|
146
|
+
private runWithLifecycle;
|
|
134
147
|
/** Handle an inbound admin command from the Commando Bridge. */
|
|
135
148
|
private handleAdminCommand;
|
|
136
149
|
private ensureProjectWorkspace;
|
package/dist/commands/chat.js
CHANGED
|
@@ -33,8 +33,9 @@ import { resolveAutoApproval } from '../utils/process-policy.js';
|
|
|
33
33
|
import { hasLocalV3ServiceIdentity } from '../utils/runtime-capability.js';
|
|
34
34
|
import { ChatToolCallParser } from '../utils/chat-tool-call-parser.js';
|
|
35
35
|
import { ChatPromptPolicy } from '../utils/chat-prompt-policy.js';
|
|
36
|
-
import { AgentStreamState } from '../utils/agent-stream-state.js';
|
|
36
|
+
import { AgentStreamState, classifyAgentToolResultPresentation, normalizeAgentToolOutputForDisplay, } from '../utils/agent-stream-state.js';
|
|
37
37
|
import { CliCommandError, commandFailure, commandNameFromArgv, failureEnvelope, normalizeCommandError, successEnvelope, } from '../utils/command-contract.js';
|
|
38
|
+
import { rollbackActiveMutationJournals } from '../utils/mutation-journal.js';
|
|
38
39
|
// Stream health policy (corrected 2026-07-04 after TestFarm incident with
|
|
39
40
|
// Gideon Lenz / C:\vigthoria\Apps\monopoly): agentic tasks have no
|
|
40
41
|
// predictable duration, so there is intentionally NO overall wall-clock
|
|
@@ -161,6 +162,9 @@ export class ChatCommand {
|
|
|
161
162
|
retryPromptSignature = null;
|
|
162
163
|
retryPromptStreak = 0;
|
|
163
164
|
streamState;
|
|
165
|
+
processInterruptHandled = false;
|
|
166
|
+
onSigint = () => this.handleProcessInterrupt('SIGINT');
|
|
167
|
+
onSigterm = () => this.handleProcessInterrupt('SIGTERM');
|
|
164
168
|
lastAgentRoute = null;
|
|
165
169
|
pendingGoaContext = null;
|
|
166
170
|
// Last completed Agent run — used by /retry, /continue, and the final summary block.
|
|
@@ -788,10 +792,7 @@ export class ChatCommand {
|
|
|
788
792
|
return `${visible.slice(0, Math.max(1, width - 1))}…`;
|
|
789
793
|
}
|
|
790
794
|
normalizeToolOutputForDisplay(output) {
|
|
791
|
-
return
|
|
792
|
-
.replace(/\/r\/n|\/n|\\n/g, '\n')
|
|
793
|
-
.replace(/\/r|\\r/g, '')
|
|
794
|
-
.replace(/\t/g, ' ');
|
|
795
|
+
return normalizeAgentToolOutputForDisplay(output);
|
|
795
796
|
}
|
|
796
797
|
toolEventKey(event) {
|
|
797
798
|
const name = String(event?.name || event?.tool || event?.tool_name || '').trim();
|
|
@@ -908,6 +909,9 @@ export class ChatCommand {
|
|
|
908
909
|
if (!event || typeof event !== 'object') {
|
|
909
910
|
return;
|
|
910
911
|
}
|
|
912
|
+
if (event.user_visible === false || String(event.visibility || '').toLowerCase() === 'internal') {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
911
915
|
this.streamState.noteActivity();
|
|
912
916
|
if (isV3StreamKeepaliveEvent(event)) {
|
|
913
917
|
return;
|
|
@@ -960,12 +964,24 @@ export class ChatCommand {
|
|
|
960
964
|
this.streamState.seenToolResults.add(eventKey);
|
|
961
965
|
const success = event.success !== false;
|
|
962
966
|
const toolName = event.name || event.tool || '';
|
|
967
|
+
const presentation = classifyAgentToolResultPresentation(event);
|
|
963
968
|
emitDeckEvent({
|
|
964
969
|
type: 'tool_end',
|
|
965
970
|
tool: toolName,
|
|
966
971
|
success,
|
|
967
972
|
index: this.streamState.toolCallCount,
|
|
968
973
|
});
|
|
974
|
+
if (presentation === 'hidden')
|
|
975
|
+
return;
|
|
976
|
+
if (presentation === 'correcting') {
|
|
977
|
+
if (!this.streamState.shouldShowCorrectionNotice())
|
|
978
|
+
return;
|
|
979
|
+
if (spinner.isSpinning)
|
|
980
|
+
spinner.stop();
|
|
981
|
+
this.writeAgentActivityLine(chalk.gray(' ↻ Agent adjusted this step and is continuing.\n'));
|
|
982
|
+
spinner.text = 'Correcting step...';
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
969
985
|
const indicator = success ? chalk.green(' ✓') : chalk.red(' ✗');
|
|
970
986
|
if (spinner.isSpinning)
|
|
971
987
|
spinner.stop();
|
|
@@ -1337,6 +1353,73 @@ export class ChatCommand {
|
|
|
1337
1353
|
this.sessionManager = new SessionManager(this.config.getStateRoot());
|
|
1338
1354
|
}
|
|
1339
1355
|
async run(options) {
|
|
1356
|
+
this.installProcessInterruptHandlers();
|
|
1357
|
+
try {
|
|
1358
|
+
await this.runWithLifecycle(options);
|
|
1359
|
+
}
|
|
1360
|
+
finally {
|
|
1361
|
+
this.removeProcessInterruptHandlers();
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
installProcessInterruptHandlers() {
|
|
1365
|
+
this.processInterruptHandled = false;
|
|
1366
|
+
process.once('SIGINT', this.onSigint);
|
|
1367
|
+
process.once('SIGTERM', this.onSigterm);
|
|
1368
|
+
}
|
|
1369
|
+
removeProcessInterruptHandlers() {
|
|
1370
|
+
process.off('SIGINT', this.onSigint);
|
|
1371
|
+
process.off('SIGTERM', this.onSigterm);
|
|
1372
|
+
}
|
|
1373
|
+
handleProcessInterrupt(signal) {
|
|
1374
|
+
if (this.processInterruptHandled)
|
|
1375
|
+
return;
|
|
1376
|
+
this.processInterruptHandled = true;
|
|
1377
|
+
const ownedMutation = this.api.destroy();
|
|
1378
|
+
const fallbackMutations = rollbackActiveMutationJournals();
|
|
1379
|
+
const mutation = ownedMutation || fallbackMutations[0] || null;
|
|
1380
|
+
this.finalizeInterruptedAgentCheckpoint(signal);
|
|
1381
|
+
this.workspaceBrain?.destroy();
|
|
1382
|
+
getBridgeClient()?.destroy();
|
|
1383
|
+
if (!this.jsonOutput) {
|
|
1384
|
+
const restored = mutation?.rolledBack
|
|
1385
|
+
? ` Workspace changes were restored (${mutation.affectedPaths.length} path(s)).`
|
|
1386
|
+
: mutation?.partialMutation
|
|
1387
|
+
? ' WARNING: the workspace could not be restored completely; inspect the mutation journal before continuing.'
|
|
1388
|
+
: '';
|
|
1389
|
+
process.stderr.write(`\nAgent interrupted.${restored}\n`);
|
|
1390
|
+
}
|
|
1391
|
+
this.removeProcessInterruptHandlers();
|
|
1392
|
+
// Rollback is synchronous and complete before ownership returns to the OS.
|
|
1393
|
+
// Re-raise the original signal after removing our handlers so the central
|
|
1394
|
+
// process lifecycle retains the conventional 130/143 shell status without
|
|
1395
|
+
// letting a command implementation terminate the process directly.
|
|
1396
|
+
process.kill(process.pid, signal);
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Signal handlers cannot await the normal run lifecycle. Persist the
|
|
1400
|
+
* terminal checkpoint synchronously after workspace rollback so a killed
|
|
1401
|
+
* foreground process is never advertised as resumable work still running.
|
|
1402
|
+
*/
|
|
1403
|
+
finalizeInterruptedAgentCheckpoint(signal) {
|
|
1404
|
+
const checkpoint = this.currentSession?.activeAgentRun;
|
|
1405
|
+
if (!checkpoint || ['completed', 'cancelled'].includes(checkpoint.status)) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
try {
|
|
1409
|
+
assertAgentStatusTransition(checkpoint.status, 'cancelled');
|
|
1410
|
+
this.currentSession.activeAgentRun = {
|
|
1411
|
+
...checkpoint,
|
|
1412
|
+
status: 'cancelled',
|
|
1413
|
+
updatedAt: new Date().toISOString(),
|
|
1414
|
+
error: `Interrupted by ${signal}; workspace rollback completed before process exit.`,
|
|
1415
|
+
};
|
|
1416
|
+
this.sessionManager.save(this.currentSession);
|
|
1417
|
+
}
|
|
1418
|
+
catch (error) {
|
|
1419
|
+
this.logger.warn('Workspace rollback completed, but the interrupted session checkpoint could not be persisted.', error);
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
async runWithLifecycle(options) {
|
|
1340
1423
|
this.agentMode = options.agent === true;
|
|
1341
1424
|
this.operatorMode = options.operator === true;
|
|
1342
1425
|
const hasRuntimeToken = Boolean(process.env.VIGTHORIA_TOKEN || process.env.VIGTHORIA_AUTH_TOKEN);
|
|
@@ -2934,6 +3017,9 @@ export class ChatCommand {
|
|
|
2934
3017
|
liveOutcome.workspaceHasOutput = requiresWorkspaceChanges ? workspaceHasOutput : false;
|
|
2935
3018
|
liveOutcome.answerContent = answerContent;
|
|
2936
3019
|
const workflowError = response.metadata?.workflowError;
|
|
3020
|
+
const workflowErrorCode = typeof workflowError === 'object' && workflowError
|
|
3021
|
+
? String(workflowError.code || '').trim().toUpperCase()
|
|
3022
|
+
: '';
|
|
2937
3023
|
if (workflowError && !liveOutcome.executorError) {
|
|
2938
3024
|
liveOutcome.executorError = typeof workflowError === 'string'
|
|
2939
3025
|
? workflowError
|
|
@@ -2952,10 +3038,36 @@ export class ChatCommand {
|
|
|
2952
3038
|
watcher?.stop();
|
|
2953
3039
|
return false;
|
|
2954
3040
|
}
|
|
2955
|
-
const
|
|
3041
|
+
const workflowFailure = workflowError
|
|
3042
|
+
? (typeof workflowError === 'string'
|
|
3043
|
+
? workflowError
|
|
3044
|
+
: String(workflowError.message || ''))
|
|
3045
|
+
: '';
|
|
3046
|
+
const actionableFailure = sanitizeUserFacingErrorText(liveOutcome.plannerError
|
|
3047
|
+
|| workflowFailure
|
|
3048
|
+
|| liveOutcome.executorError
|
|
3049
|
+
|| previewGate?.error
|
|
3050
|
+
|| 'The agent stopped before it could validate the requested workspace changes.');
|
|
3051
|
+
const reportedMutation = response.metadata?.mutation
|
|
3052
|
+
|| previewGate?.mutation;
|
|
3053
|
+
const rollbackNote = reportedMutation?.rolledBack === true
|
|
3054
|
+
? ' Unvalidated workspace changes were rolled back; your prior files were preserved.'
|
|
3055
|
+
: '';
|
|
3056
|
+
const errorMessage = `${actionableFailure}${rollbackNote}`.trim();
|
|
2956
3057
|
const partialMutation = resolveAgentPartialMutation(changedFileCount, response.metadata?.partialMutation);
|
|
2957
|
-
|
|
2958
|
-
|
|
3058
|
+
const preservedTerminalCodes = new Set([
|
|
3059
|
+
'AGENT_PLAN_INVALID',
|
|
3060
|
+
'AGENT_CAPACITY_BUSY',
|
|
3061
|
+
'V3_RUNTIME_IDENTITY_MISMATCH',
|
|
3062
|
+
]);
|
|
3063
|
+
const terminalCode = preservedTerminalCodes.has(workflowErrorCode)
|
|
3064
|
+
? workflowErrorCode
|
|
3065
|
+
: '';
|
|
3066
|
+
liveOutcome.executorError = actionableFailure;
|
|
3067
|
+
liveOutcome.failedTaskIds.add(terminalCode === 'AGENT_PLAN_INVALID' ? 'agent-plan'
|
|
3068
|
+
: terminalCode === 'AGENT_CAPACITY_BUSY' ? 'architect-capacity'
|
|
3069
|
+
: terminalCode === 'V3_RUNTIME_IDENTITY_MISMATCH' ? 'runtime-identity'
|
|
3070
|
+
: 'preview-gate');
|
|
2959
3071
|
liveOutcome.unfinishedTaskIds.delete('agent-run-in-progress');
|
|
2960
3072
|
if (spinner) {
|
|
2961
3073
|
spinner.stop();
|
|
@@ -2965,10 +3077,19 @@ export class ChatCommand {
|
|
|
2965
3077
|
this.messages.push({ role: 'assistant', content: errorMessage });
|
|
2966
3078
|
watcher?.stop();
|
|
2967
3079
|
throw new CliCommandError(errorMessage, {
|
|
2968
|
-
code: 'AGENT_PREVIEW_FAILED',
|
|
2969
|
-
category:
|
|
3080
|
+
code: terminalCode || 'AGENT_PREVIEW_FAILED',
|
|
3081
|
+
category: terminalCode === 'V3_RUNTIME_IDENTITY_MISMATCH'
|
|
3082
|
+
? 'configuration'
|
|
3083
|
+
: partialMutation === false ? 'execution' : 'partial_mutation',
|
|
2970
3084
|
partialMutation,
|
|
2971
|
-
details: {
|
|
3085
|
+
details: {
|
|
3086
|
+
executionPath: 'v3-agent',
|
|
3087
|
+
previewGate,
|
|
3088
|
+
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
3089
|
+
tasksTotal: liveOutcome.tasksTotal,
|
|
3090
|
+
failedTaskIds: [...liveOutcome.failedTaskIds],
|
|
3091
|
+
nextAction: 'Resolve the first reported blocker, then retry from the same workspace.',
|
|
3092
|
+
},
|
|
2972
3093
|
});
|
|
2973
3094
|
}
|
|
2974
3095
|
if (!this.jsonOutput && previewGate?.required) {
|
|
@@ -3219,7 +3340,12 @@ export class ChatCommand {
|
|
|
3219
3340
|
liveOutcome.executorError = safeFailure;
|
|
3220
3341
|
if (failure.code === 'AGENT_PLAN_INVALID')
|
|
3221
3342
|
liveOutcome.failedTaskIds.add('agent-plan');
|
|
3222
|
-
|
|
3343
|
+
if (failure.code === 'AGENT_OUTCOME_UNKNOWN') {
|
|
3344
|
+
liveOutcome.unfinishedTaskIds.add('agent-run-in-progress');
|
|
3345
|
+
}
|
|
3346
|
+
else {
|
|
3347
|
+
liveOutcome.unfinishedTaskIds.delete('agent-run-in-progress');
|
|
3348
|
+
}
|
|
3223
3349
|
this.commitAgentRunOutcome({
|
|
3224
3350
|
prompt,
|
|
3225
3351
|
originalPrompt: null,
|
|
@@ -3263,6 +3389,27 @@ export class ChatCommand {
|
|
|
3263
3389
|
persistTypedAgentFailure(planFailure);
|
|
3264
3390
|
throw planFailure;
|
|
3265
3391
|
}
|
|
3392
|
+
if (error?.code === 'AGENT_OUTCOME_UNKNOWN') {
|
|
3393
|
+
const interruptedFailure = new CliCommandError(error.message, {
|
|
3394
|
+
code: 'AGENT_OUTCOME_UNKNOWN',
|
|
3395
|
+
category: 'partial_mutation',
|
|
3396
|
+
partialMutation: 'unknown',
|
|
3397
|
+
details: {
|
|
3398
|
+
operationId: error?.operationId || null,
|
|
3399
|
+
contextId: error?.contextId || executionId,
|
|
3400
|
+
resumeCommand: '/continue',
|
|
3401
|
+
},
|
|
3402
|
+
cause: error,
|
|
3403
|
+
});
|
|
3404
|
+
if (spinner)
|
|
3405
|
+
spinner.stop();
|
|
3406
|
+
persistTypedAgentFailure(interruptedFailure);
|
|
3407
|
+
if (!this.jsonOutput && !this.directPromptMode) {
|
|
3408
|
+
console.log(chalk.yellow('Agent connection interrupted after the run started.'));
|
|
3409
|
+
console.log(chalk.gray('The task was not submitted again. Type /continue to resume the saved run without duplicating changes.'));
|
|
3410
|
+
}
|
|
3411
|
+
throw interruptedFailure;
|
|
3412
|
+
}
|
|
3266
3413
|
if (error instanceof CliCommandError) {
|
|
3267
3414
|
if (spinner)
|
|
3268
3415
|
spinner.stop();
|
|
@@ -3348,10 +3495,15 @@ export class ChatCommand {
|
|
|
3348
3495
|
this.printAgentRunSummary(this.lastAgentRunOutcome, failedEval, 0);
|
|
3349
3496
|
}
|
|
3350
3497
|
}
|
|
3498
|
+
const reportedMutation = error?.mutation;
|
|
3499
|
+
const reportedPartialMutation = reportedMutation?.rolledBack === true
|
|
3500
|
+
? false
|
|
3501
|
+
: (error?.partialMutation ?? reportedMutation?.partialMutation);
|
|
3502
|
+
const partialMutation = resolveAgentPartialMutation(liveOutcome.changedFileCount, reportedPartialMutation);
|
|
3351
3503
|
throw new CliCommandError(errorMessage, {
|
|
3352
3504
|
code: 'AGENT_EXECUTION_FAILED',
|
|
3353
|
-
category:
|
|
3354
|
-
partialMutation
|
|
3505
|
+
category: partialMutation === false ? 'execution' : 'partial_mutation',
|
|
3506
|
+
partialMutation,
|
|
3355
3507
|
details: {
|
|
3356
3508
|
executionPath: 'v3-agent',
|
|
3357
3509
|
mode: 'agent',
|
|
@@ -3359,12 +3511,16 @@ export class ChatCommand {
|
|
|
3359
3511
|
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
3360
3512
|
tasksTotal: liveOutcome.tasksTotal,
|
|
3361
3513
|
statusHeadline: evaluateExecutorSuccess(liveOutcome).statusHeadline,
|
|
3514
|
+
...(reportedMutation ? { mutation: reportedMutation } : {}),
|
|
3362
3515
|
},
|
|
3363
3516
|
cause: error,
|
|
3364
3517
|
});
|
|
3365
3518
|
}
|
|
3366
3519
|
}
|
|
3367
3520
|
async tryRecoverV3ServiceAndRetry(executionPrompt, rawPrompt, workspaceContext, routingPolicy, spinner, error) {
|
|
3521
|
+
if (error?.code === 'AGENT_OUTCOME_UNKNOWN') {
|
|
3522
|
+
return false;
|
|
3523
|
+
}
|
|
3368
3524
|
const recovery = await this.api.attemptV3ServiceRecovery((error && error.message) || '');
|
|
3369
3525
|
if (!recovery.recovered) {
|
|
3370
3526
|
return false;
|
package/dist/commands/fork.js
CHANGED
|
@@ -16,7 +16,11 @@ export class ForkCommand {
|
|
|
16
16
|
this.logger = logger;
|
|
17
17
|
}
|
|
18
18
|
getHeaders() {
|
|
19
|
-
const headers = {
|
|
19
|
+
const headers = {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
'X-Vigthoria-Agent-Lane': 'cli',
|
|
22
|
+
'X-Vigthoria-Source-Product': 'vigthoria-cli',
|
|
23
|
+
};
|
|
20
24
|
const token = process.env.VIGTHORIA_TOKEN ||
|
|
21
25
|
process.env.VIGTHORIA_AUTH_TOKEN ||
|
|
22
26
|
this.config.get('authToken');
|
|
@@ -34,7 +38,7 @@ export class ForkCommand {
|
|
|
34
38
|
const allowLocal = hasLocalV3AgentCapability();
|
|
35
39
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
36
40
|
process.env.V3_AGENT_URL ||
|
|
37
|
-
(allowLocal ? 'http://127.0.0.1:
|
|
41
|
+
(allowLocal ? 'http://127.0.0.1:8032' : null) ||
|
|
38
42
|
configuredApiUrl);
|
|
39
43
|
}
|
|
40
44
|
buildForkHistory(events, eventIndex) {
|
|
@@ -92,7 +96,8 @@ export class ForkCommand {
|
|
|
92
96
|
local_workspace_path: workspaceRef,
|
|
93
97
|
project_path: workspaceRef,
|
|
94
98
|
});
|
|
95
|
-
const
|
|
99
|
+
const runsPath = /:8032\/?$/.test(baseUrl) ? '/api/runs' : '/api/runs-cli';
|
|
100
|
+
const resp = await guardedFetch(`${baseUrl}${runsPath}/${encodeURIComponent(runId)}/events?${params}`, {
|
|
96
101
|
headers: this.getHeaders(),
|
|
97
102
|
signal: streamController.signal,
|
|
98
103
|
}, { audience: 'v3' });
|
package/dist/commands/history.js
CHANGED
|
@@ -15,7 +15,11 @@ export class HistoryCommand {
|
|
|
15
15
|
this.logger = logger;
|
|
16
16
|
}
|
|
17
17
|
getHeaders() {
|
|
18
|
-
const headers = {
|
|
18
|
+
const headers = {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'X-Vigthoria-Agent-Lane': 'cli',
|
|
21
|
+
'X-Vigthoria-Source-Product': 'vigthoria-cli',
|
|
22
|
+
};
|
|
19
23
|
const token = process.env.VIGTHORIA_TOKEN ||
|
|
20
24
|
process.env.VIGTHORIA_AUTH_TOKEN ||
|
|
21
25
|
this.config.get('authToken');
|
|
@@ -33,7 +37,7 @@ export class HistoryCommand {
|
|
|
33
37
|
const allowLocal = hasLocalV3AgentCapability();
|
|
34
38
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
35
39
|
process.env.V3_AGENT_URL ||
|
|
36
|
-
(allowLocal ? 'http://127.0.0.1:
|
|
40
|
+
(allowLocal ? 'http://127.0.0.1:8032' : null) ||
|
|
37
41
|
configuredApiUrl);
|
|
38
42
|
}
|
|
39
43
|
async run(options) {
|
|
@@ -49,7 +53,8 @@ export class HistoryCommand {
|
|
|
49
53
|
local_workspace_path: workspaceRef,
|
|
50
54
|
project_path: workspaceRef,
|
|
51
55
|
});
|
|
52
|
-
const
|
|
56
|
+
const runsPath = /:8032\/?$/.test(baseUrl) ? '/api/runs' : '/api/runs-cli';
|
|
57
|
+
const resp = await guardedFetch(`${baseUrl}${runsPath}?${params}`, {
|
|
53
58
|
headers: this.getHeaders(),
|
|
54
59
|
}, { audience: 'v3' });
|
|
55
60
|
if (!resp.ok) {
|
package/dist/commands/legion.js
CHANGED
|
@@ -303,7 +303,7 @@ export class LegionCommand {
|
|
|
303
303
|
console.log(chalk.yellow('Budget depleted for current round. Additional paid loop required.'));
|
|
304
304
|
console.log(chalk.gray(` Next round: ${nextRound}`));
|
|
305
305
|
console.log(chalk.gray(` Failed step: ${execution.failedStepId || 'unknown'} (${execution.failedWorker || 'unknown'})`));
|
|
306
|
-
console.log(chalk.gray(` Additional estimate: $${nextQuote.finalUsd.toFixed(4)} / ${nextQuote.vigcoinRequired.toFixed(3)}
|
|
306
|
+
console.log(chalk.gray(` Additional estimate: $${nextQuote.finalUsd.toFixed(4)} / ${nextQuote.vigcoinRequired.toFixed(3)} credits`));
|
|
307
307
|
const answer = (await rl.question('Confirm additional PAYG credit deduction and continue? (y/N): ')).trim().toLowerCase();
|
|
308
308
|
return answer === 'y' || answer === 'yes';
|
|
309
309
|
}
|
package/dist/commands/replay.js
CHANGED
|
@@ -13,7 +13,11 @@ export class ReplayCommand {
|
|
|
13
13
|
this.config = config;
|
|
14
14
|
}
|
|
15
15
|
getHeaders() {
|
|
16
|
-
const headers = {
|
|
16
|
+
const headers = {
|
|
17
|
+
'Content-Type': 'application/json',
|
|
18
|
+
'X-Vigthoria-Agent-Lane': 'cli',
|
|
19
|
+
'X-Vigthoria-Source-Product': 'vigthoria-cli',
|
|
20
|
+
};
|
|
17
21
|
const token = process.env.VIGTHORIA_TOKEN ||
|
|
18
22
|
process.env.VIGTHORIA_AUTH_TOKEN ||
|
|
19
23
|
this.config.get('authToken');
|
|
@@ -31,7 +35,7 @@ export class ReplayCommand {
|
|
|
31
35
|
const allowLocal = hasLocalV3AgentCapability();
|
|
32
36
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
33
37
|
process.env.V3_AGENT_URL ||
|
|
34
|
-
(allowLocal ? 'http://127.0.0.1:
|
|
38
|
+
(allowLocal ? 'http://127.0.0.1:8032' : null) ||
|
|
35
39
|
configuredApiUrl);
|
|
36
40
|
}
|
|
37
41
|
sleep(ms) {
|
|
@@ -49,7 +53,8 @@ export class ReplayCommand {
|
|
|
49
53
|
local_workspace_path: workspaceRef,
|
|
50
54
|
project_path: workspaceRef,
|
|
51
55
|
});
|
|
52
|
-
const
|
|
56
|
+
const runsPath = /:8032\/?$/.test(baseUrl) ? '/api/runs' : '/api/runs-cli';
|
|
57
|
+
const resp = await guardedFetch(`${baseUrl}${runsPath}/${encodeURIComponent(runId)}/events?${params}`, {
|
|
53
58
|
headers: this.getHeaders(),
|
|
54
59
|
}, { audience: 'v3' });
|
|
55
60
|
if (!resp.ok) {
|