vigthoria-cli 1.8.13 → 1.8.15
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/cancel.d.ts +18 -0
- package/dist/commands/cancel.js +144 -0
- package/dist/commands/chat.js +18 -7
- package/dist/index.js +12 -1
- package/package.json +1 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Config } from '../utils/config.js';
|
|
2
|
+
import { Logger } from '../utils/logger.js';
|
|
3
|
+
interface CancelOptions {
|
|
4
|
+
all?: boolean;
|
|
5
|
+
list?: boolean;
|
|
6
|
+
json?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class CancelCommand {
|
|
9
|
+
private config;
|
|
10
|
+
private logger;
|
|
11
|
+
constructor(config: Config, logger: Logger);
|
|
12
|
+
private getHeaders;
|
|
13
|
+
private getBaseUrl;
|
|
14
|
+
private listActive;
|
|
15
|
+
private cancelOne;
|
|
16
|
+
run(contextId: string | undefined, options: CancelOptions): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CancelCommand = void 0;
|
|
7
|
+
const api_js_1 = require("../utils/api.js");
|
|
8
|
+
/**
|
|
9
|
+
* cancel.ts — Cancel an in-flight V3 agent run, or cancel all active runs.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* vig cancel <context_id> Cancel a single run
|
|
13
|
+
* vig cancel --all Cancel every currently-active run
|
|
14
|
+
* vig cancel --list Just list active runs (no cancellation)
|
|
15
|
+
*/
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
18
|
+
class CancelCommand {
|
|
19
|
+
config;
|
|
20
|
+
logger;
|
|
21
|
+
constructor(config, logger) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
}
|
|
25
|
+
getHeaders() {
|
|
26
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
27
|
+
const token = process.env.VIGTHORIA_TOKEN ||
|
|
28
|
+
process.env.VIGTHORIA_AUTH_TOKEN ||
|
|
29
|
+
this.config.get('authToken');
|
|
30
|
+
if (token) {
|
|
31
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
32
|
+
headers['Cookie'] = `vigthoria-auth-token=${token}`;
|
|
33
|
+
}
|
|
34
|
+
const serviceKey = process.env.VIGTHORIA_V3_SERVICE_KEY;
|
|
35
|
+
if (serviceKey)
|
|
36
|
+
headers['X-Service-Key'] = serviceKey;
|
|
37
|
+
return headers;
|
|
38
|
+
}
|
|
39
|
+
getBaseUrl() {
|
|
40
|
+
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
41
|
+
const allowLocal = (0, api_js_1.isServerRuntime)() && process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
42
|
+
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
43
|
+
process.env.V3_AGENT_URL ||
|
|
44
|
+
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
|
45
|
+
configuredApiUrl);
|
|
46
|
+
}
|
|
47
|
+
async listActive(baseUrl) {
|
|
48
|
+
const resp = await fetch(`${baseUrl}/api/runs/active`, { headers: this.getHeaders() });
|
|
49
|
+
if (!resp.ok) {
|
|
50
|
+
if (resp.status === 404 || resp.status === 502 || resp.status === 503) {
|
|
51
|
+
this.logger.error(`V3 cancel API is not available on ${baseUrl}. Backend may not expose /api/runs/active. ` +
|
|
52
|
+
`(Requires V3 agent server.py with the cancel endpoint patched in.)`);
|
|
53
|
+
}
|
|
54
|
+
else if (resp.status === 401 || resp.status === 403) {
|
|
55
|
+
this.logger.error(`Authentication failed (${resp.status}). Run \`vig login\` first.`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
this.logger.error(`Failed to list active runs: ${resp.status} ${resp.statusText}`);
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return (await resp.json());
|
|
63
|
+
}
|
|
64
|
+
async cancelOne(baseUrl, contextId) {
|
|
65
|
+
const resp = await fetch(`${baseUrl}/api/runs/${encodeURIComponent(contextId)}/cancel`, { method: 'POST', headers: this.getHeaders() });
|
|
66
|
+
if (!resp.ok) {
|
|
67
|
+
if (resp.status === 404) {
|
|
68
|
+
this.logger.warn(`No active run for context_id=${contextId}`);
|
|
69
|
+
}
|
|
70
|
+
else if (resp.status === 401 || resp.status === 403) {
|
|
71
|
+
this.logger.error(`Authentication failed (${resp.status}). Run \`vig login\` first.`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.logger.error(`Cancel failed for ${contextId}: ${resp.status} ${resp.statusText}`);
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return (await resp.json());
|
|
79
|
+
}
|
|
80
|
+
async run(contextId, options) {
|
|
81
|
+
const baseUrl = this.getBaseUrl();
|
|
82
|
+
if (options.list) {
|
|
83
|
+
const spinner = (0, logger_js_1.createSpinner)('Loading active runs...').start();
|
|
84
|
+
const active = await this.listActive(baseUrl);
|
|
85
|
+
spinner.stop();
|
|
86
|
+
if (!active)
|
|
87
|
+
return;
|
|
88
|
+
if (options.json) {
|
|
89
|
+
console.log(JSON.stringify(active, null, 2));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (active.active_count === 0) {
|
|
93
|
+
this.logger.info(chalk_1.default.dim('No active runs.'));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
console.log(chalk_1.default.bold(`\n${logger_js_1.CH.success} Active Runs (${active.active_count}/${active.max_concurrent_runs})\n`));
|
|
97
|
+
for (const cid of active.active_context_ids) {
|
|
98
|
+
console.log(` ${chalk_1.default.cyan(cid)}`);
|
|
99
|
+
}
|
|
100
|
+
console.log();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (options.all) {
|
|
104
|
+
const spinner = (0, logger_js_1.createSpinner)('Loading active runs...').start();
|
|
105
|
+
const active = await this.listActive(baseUrl);
|
|
106
|
+
spinner.stop();
|
|
107
|
+
if (!active)
|
|
108
|
+
return;
|
|
109
|
+
if (active.active_count === 0) {
|
|
110
|
+
this.logger.info(chalk_1.default.dim('No active runs to cancel.'));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const results = [];
|
|
114
|
+
for (const cid of active.active_context_ids) {
|
|
115
|
+
const sp = (0, logger_js_1.createSpinner)(`Cancelling ${cid}...`).start();
|
|
116
|
+
const r = await this.cancelOne(baseUrl, cid);
|
|
117
|
+
sp.stop();
|
|
118
|
+
if (r) {
|
|
119
|
+
results.push(r);
|
|
120
|
+
this.logger.success(`Cancelled ${chalk_1.default.cyan(cid)} (asyncio_cancelled=${r.asyncio_cancelled})`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (options.json)
|
|
124
|
+
console.log(JSON.stringify({ cancelled: results }, null, 2));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (!contextId) {
|
|
128
|
+
this.logger.error('Usage: vig cancel <context_id> | --all | --list');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const spinner = (0, logger_js_1.createSpinner)(`Cancelling ${contextId}...`).start();
|
|
132
|
+
const r = await this.cancelOne(baseUrl, contextId);
|
|
133
|
+
spinner.stop();
|
|
134
|
+
if (!r)
|
|
135
|
+
return;
|
|
136
|
+
if (options.json) {
|
|
137
|
+
console.log(JSON.stringify(r, null, 2));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.logger.success(`Cancelled ${chalk_1.default.cyan(contextId)} ` +
|
|
141
|
+
`(asyncio_cancelled=${r.asyncio_cancelled}, active_runs_after=${r.active_runs_after})`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
exports.CancelCommand = CancelCommand;
|
package/dist/commands/chat.js
CHANGED
|
@@ -458,13 +458,20 @@ class ChatCommand {
|
|
|
458
458
|
const plan = event.plan || {};
|
|
459
459
|
const planKind = plan.task_kind || event.task_kind || '';
|
|
460
460
|
const quality = plan.quality_profile || '';
|
|
461
|
+
const status = typeof plan.status === 'string' ? plan.status : '';
|
|
462
|
+
const summary = typeof plan.summary === 'string' ? plan.summary : '';
|
|
461
463
|
if (spinner.isSpinning)
|
|
462
464
|
spinner.stop();
|
|
463
465
|
process.stderr.write(chalk_1.default.cyan(` [Plan] `) + `Task: ${planKind || 'analyzing'}`);
|
|
464
466
|
if (quality)
|
|
465
467
|
process.stderr.write(chalk_1.default.gray(` (${quality})`));
|
|
466
468
|
process.stderr.write('\n');
|
|
467
|
-
|
|
469
|
+
if (summary) {
|
|
470
|
+
process.stderr.write(chalk_1.default.gray(` ${summary}\n`));
|
|
471
|
+
}
|
|
472
|
+
if (status === 'planning' && Number.isFinite(Number(plan.elapsed_seconds))) {
|
|
473
|
+
process.stderr.write(chalk_1.default.gray(` elapsed: ${plan.elapsed_seconds}s\n`));
|
|
474
|
+
}
|
|
468
475
|
if (Array.isArray(plan.tasks) && plan.tasks.length > 0) {
|
|
469
476
|
process.stderr.write(chalk_1.default.gray(` ${plan.total_tasks || plan.tasks.length} tasks:\n`));
|
|
470
477
|
for (const t of plan.tasks.slice(0, 10)) {
|
|
@@ -475,12 +482,16 @@ class ChatCommand {
|
|
|
475
482
|
process.stderr.write(chalk_1.default.gray(` ... and ${plan.tasks.length - 10} more\n`));
|
|
476
483
|
}
|
|
477
484
|
}
|
|
478
|
-
|
|
485
|
+
if (Array.isArray(plan.notes) && plan.notes.length > 0) {
|
|
486
|
+
for (const note of plan.notes.slice(0, 3)) {
|
|
487
|
+
process.stderr.write(chalk_1.default.gray(` note: ${note}\n`));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
479
490
|
if (Array.isArray(plan.target_files) && plan.target_files.length > 0) {
|
|
480
491
|
process.stderr.write(chalk_1.default.gray(` Files: ${plan.target_files.join(', ')}\n`));
|
|
481
492
|
}
|
|
482
493
|
spinner.start();
|
|
483
|
-
spinner.text = 'Planning...';
|
|
494
|
+
spinner.text = status === 'planning' ? 'Planning...' : 'Executing plan...';
|
|
484
495
|
return;
|
|
485
496
|
}
|
|
486
497
|
if (event.type === 'file_mutation') {
|
|
@@ -1719,18 +1730,18 @@ class ChatCommand {
|
|
|
1719
1730
|
else if (this.v3StreamingStarted) {
|
|
1720
1731
|
// Content was already streamed to stdout in real-time; skip duplicate print.
|
|
1721
1732
|
if (!this.directPromptMode) {
|
|
1722
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1733
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1723
1734
|
}
|
|
1724
1735
|
}
|
|
1725
1736
|
else if (response.content) {
|
|
1726
1737
|
if (!this.directPromptMode) {
|
|
1727
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1738
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1728
1739
|
}
|
|
1729
1740
|
console.log(response.content);
|
|
1730
1741
|
}
|
|
1731
1742
|
else {
|
|
1732
1743
|
if (!this.directPromptMode) {
|
|
1733
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1744
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1734
1745
|
}
|
|
1735
1746
|
console.log('V3 agent workflow completed.');
|
|
1736
1747
|
}
|
|
@@ -1841,7 +1852,7 @@ class ChatCommand {
|
|
|
1841
1852
|
}, null, 2));
|
|
1842
1853
|
}
|
|
1843
1854
|
else {
|
|
1844
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1855
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1845
1856
|
console.log(rescueMessage);
|
|
1846
1857
|
if (previewGate.required) {
|
|
1847
1858
|
if (previewGate.passed) {
|
package/dist/index.js
CHANGED
|
@@ -71,6 +71,7 @@ const legion_js_1 = require("./commands/legion.js");
|
|
|
71
71
|
const history_js_1 = require("./commands/history.js");
|
|
72
72
|
const replay_js_1 = require("./commands/replay.js");
|
|
73
73
|
const fork_js_1 = require("./commands/fork.js");
|
|
74
|
+
const cancel_js_1 = require("./commands/cancel.js");
|
|
74
75
|
const config_js_2 = require("./utils/config.js");
|
|
75
76
|
const logger_js_1 = require("./utils/logger.js");
|
|
76
77
|
const chalk_1 = __importDefault(require("chalk"));
|
|
@@ -163,7 +164,7 @@ async function main() {
|
|
|
163
164
|
const directPromptRequested = process.argv.includes('--prompt') || process.argv.includes('-P');
|
|
164
165
|
if (invokedBinaryName === 'vigthoria-chat') {
|
|
165
166
|
const knownCommands = new Set([
|
|
166
|
-
'chat', 'chat-resume', 'agent', 'edit', 'generate', 'explain', 'fix', 'review',
|
|
167
|
+
'chat', 'chat-resume', 'agent', 'edit', 'generate', 'explain', 'fix', 'review', 'cancel',
|
|
167
168
|
'hub', 'repo', 'deploy', 'operator', 'workflow', 'flow', 'login', 'logout', 'status', 'config', 'update',
|
|
168
169
|
'--help', '-h', '--version', '-V', 'help', 'version',
|
|
169
170
|
]);
|
|
@@ -770,6 +771,16 @@ Examples:
|
|
|
770
771
|
const fork = new fork_js_1.ForkCommand(config, logger);
|
|
771
772
|
await fork.run(runId, message || '', { eventIndex: parseInt(options.eventIndex, 10) || 0, project: options.project, json: options.json });
|
|
772
773
|
});
|
|
774
|
+
program
|
|
775
|
+
.command('cancel [contextId]')
|
|
776
|
+
.description('Cancel an in-flight V3 agent run (by context_id), or use --all to cancel every active run')
|
|
777
|
+
.option('-a, --all', 'Cancel all currently-active runs', false)
|
|
778
|
+
.option('-l, --list', 'List active runs without cancelling', false)
|
|
779
|
+
.option('--json', 'Machine-readable JSON output', false)
|
|
780
|
+
.action(async (contextId, options) => {
|
|
781
|
+
const cancel = new cancel_js_1.CancelCommand(config, logger);
|
|
782
|
+
await cancel.run(contextId, { all: options.all, list: options.list, json: options.json });
|
|
783
|
+
});
|
|
773
784
|
// ==================== AUTH COMMANDS ====================
|
|
774
785
|
// Auth commands
|
|
775
786
|
program
|