vigthoria-cli 1.6.57 → 1.6.59
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/auth.d.ts +1 -2
- package/dist/commands/auth.js +29 -29
- package/dist/commands/chat.d.ts +1 -0
- package/dist/commands/chat.js +55 -10
- package/dist/commands/deploy.js +2 -0
- package/dist/commands/fork.d.ts +1 -0
- package/dist/commands/fork.js +22 -2
- package/dist/commands/history.d.ts +1 -0
- package/dist/commands/history.js +26 -3
- package/dist/commands/replay.d.ts +1 -0
- package/dist/commands/replay.js +22 -2
- package/package.json +1 -1
package/dist/commands/auth.d.ts
CHANGED
|
@@ -12,8 +12,7 @@ export declare class AuthCommand {
|
|
|
12
12
|
private api;
|
|
13
13
|
constructor(config: Config, logger: Logger);
|
|
14
14
|
login(options: LoginOptions): Promise<void>;
|
|
15
|
-
private
|
|
16
|
-
private loginWithTokenPrompt;
|
|
15
|
+
private doCredentialLogin;
|
|
17
16
|
private loginWithToken;
|
|
18
17
|
private loginWithBrowser;
|
|
19
18
|
logout(): Promise<void>;
|
package/dist/commands/auth.js
CHANGED
|
@@ -29,7 +29,11 @@ class AuthCommand {
|
|
|
29
29
|
console.log();
|
|
30
30
|
console.log(chalk_1.default.cyan(`${logger_js_1.CH.hDouble.repeat(3)} Vigthoria Login ${logger_js_1.CH.hDouble.repeat(3)}`));
|
|
31
31
|
console.log();
|
|
32
|
-
//
|
|
32
|
+
// Collect ALL interactive input in a single inquirer.prompt() call.
|
|
33
|
+
// inquirer 9.x creates and destroys a readline interface per prompt()
|
|
34
|
+
// call; on Node 20 TTY the second readline on the same process.stdin
|
|
35
|
+
// throws ERR_USE_AFTER_CLOSE. Using `when` conditionals keeps one
|
|
36
|
+
// readline alive for the entire login flow.
|
|
33
37
|
const answers = await inquirer_1.default.prompt([
|
|
34
38
|
{
|
|
35
39
|
type: 'list',
|
|
@@ -41,25 +45,11 @@ class AuthCommand {
|
|
|
41
45
|
{ name: 'Browser Login', value: 'browser' },
|
|
42
46
|
],
|
|
43
47
|
},
|
|
44
|
-
]);
|
|
45
|
-
switch (answers.method) {
|
|
46
|
-
case 'credentials':
|
|
47
|
-
await this.loginWithCredentials();
|
|
48
|
-
break;
|
|
49
|
-
case 'token':
|
|
50
|
-
await this.loginWithTokenPrompt();
|
|
51
|
-
break;
|
|
52
|
-
case 'browser':
|
|
53
|
-
await this.loginWithBrowser();
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
async loginWithCredentials() {
|
|
58
|
-
const credentials = await inquirer_1.default.prompt([
|
|
59
48
|
{
|
|
60
49
|
type: 'input',
|
|
61
50
|
name: 'email',
|
|
62
51
|
message: 'Email:',
|
|
52
|
+
when: (ans) => ans.method === 'credentials',
|
|
63
53
|
validate: (input) => {
|
|
64
54
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
65
55
|
return emailRegex.test(input) || 'Please enter a valid email';
|
|
@@ -70,11 +60,33 @@ class AuthCommand {
|
|
|
70
60
|
name: 'password',
|
|
71
61
|
message: 'Password:',
|
|
72
62
|
mask: '*',
|
|
63
|
+
when: (ans) => ans.method === 'credentials',
|
|
73
64
|
validate: (input) => input.length >= 6 || 'Password must be at least 6 characters',
|
|
74
65
|
},
|
|
66
|
+
{
|
|
67
|
+
type: 'password',
|
|
68
|
+
name: 'token',
|
|
69
|
+
message: 'API Token:',
|
|
70
|
+
mask: '*',
|
|
71
|
+
when: (ans) => ans.method === 'token',
|
|
72
|
+
validate: (input) => input.length > 0 || 'Please enter your API token',
|
|
73
|
+
},
|
|
75
74
|
]);
|
|
75
|
+
switch (answers.method) {
|
|
76
|
+
case 'credentials':
|
|
77
|
+
await this.doCredentialLogin(answers.email, answers.password);
|
|
78
|
+
break;
|
|
79
|
+
case 'token':
|
|
80
|
+
await this.loginWithToken(answers.token);
|
|
81
|
+
break;
|
|
82
|
+
case 'browser':
|
|
83
|
+
await this.loginWithBrowser();
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async doCredentialLogin(email, password) {
|
|
76
88
|
const spinner = (0, logger_js_1.createSpinner)('Logging in...').start();
|
|
77
|
-
const success = await this.api.login(
|
|
89
|
+
const success = await this.api.login(email, password);
|
|
78
90
|
spinner.stop();
|
|
79
91
|
if (success) {
|
|
80
92
|
this.printLoginSuccess();
|
|
@@ -83,18 +95,6 @@ class AuthCommand {
|
|
|
83
95
|
this.logger.error('Login failed. Please check your credentials.');
|
|
84
96
|
}
|
|
85
97
|
}
|
|
86
|
-
async loginWithTokenPrompt() {
|
|
87
|
-
const { token } = await inquirer_1.default.prompt([
|
|
88
|
-
{
|
|
89
|
-
type: 'password',
|
|
90
|
-
name: 'token',
|
|
91
|
-
message: 'API Token:',
|
|
92
|
-
mask: '*',
|
|
93
|
-
validate: (input) => input.length > 0 || 'Please enter your API token',
|
|
94
|
-
},
|
|
95
|
-
]);
|
|
96
|
-
await this.loginWithToken(token);
|
|
97
|
-
}
|
|
98
98
|
async loginWithToken(token) {
|
|
99
99
|
const spinner = (0, logger_js_1.createSpinner)('Validating token...').start();
|
|
100
100
|
const success = await this.api.loginWithToken(token);
|
package/dist/commands/chat.d.ts
CHANGED
package/dist/commands/chat.js
CHANGED
|
@@ -298,6 +298,7 @@ class ChatCommand {
|
|
|
298
298
|
v3IterationCount = 0;
|
|
299
299
|
v3ToolCallCount = 0;
|
|
300
300
|
v3LastActivity = Date.now();
|
|
301
|
+
v3StreamingStarted = false;
|
|
301
302
|
describeV3AgentTool(toolName) {
|
|
302
303
|
const normalized = String(toolName || '').toLowerCase();
|
|
303
304
|
if (/read|grep|search|list|find|glob/.test(normalized)) {
|
|
@@ -324,6 +325,9 @@ class ChatCommand {
|
|
|
324
325
|
const toolDesc = this.describeV3AgentTool(event.tool || event.name || event.tool_name);
|
|
325
326
|
const toolTarget = event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '';
|
|
326
327
|
const shortTarget = toolTarget ? ` → ${String(toolTarget).split('/').slice(-2).join('/')}` : '';
|
|
328
|
+
if (this.v3StreamingStarted && !spinner.isSpinning) {
|
|
329
|
+
spinner.start();
|
|
330
|
+
}
|
|
327
331
|
spinner.text = chalk_1.default.cyan(`[${this.v3IterationCount}/${this.v3ToolCallCount}] `) + `${toolDesc}${shortTarget}`;
|
|
328
332
|
return;
|
|
329
333
|
}
|
|
@@ -331,6 +335,9 @@ class ChatCommand {
|
|
|
331
335
|
const success = event.success !== false;
|
|
332
336
|
const toolName = event.name || event.tool || '';
|
|
333
337
|
const indicator = success ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
|
|
338
|
+
if (this.v3StreamingStarted && !spinner.isSpinning) {
|
|
339
|
+
spinner.start();
|
|
340
|
+
}
|
|
334
341
|
spinner.text = `${indicator} ${toolName} complete — next step...`;
|
|
335
342
|
return;
|
|
336
343
|
}
|
|
@@ -339,12 +346,32 @@ class ChatCommand {
|
|
|
339
346
|
const iterText = event.content || '';
|
|
340
347
|
const iterMatch = iterText.match(/Iteration (\d+)/i);
|
|
341
348
|
const iterNum = iterMatch ? iterMatch[1] : String(this.v3IterationCount);
|
|
349
|
+
if (this.v3StreamingStarted && !spinner.isSpinning) {
|
|
350
|
+
spinner.start();
|
|
351
|
+
}
|
|
342
352
|
spinner.text = chalk_1.default.cyan(`[Iteration ${iterNum}] `) + 'Analyzing...';
|
|
343
353
|
return;
|
|
344
354
|
}
|
|
345
|
-
if (event.type === 'message') {
|
|
346
|
-
const
|
|
347
|
-
|
|
355
|
+
if (event.type === 'message' || event.type === 'assistant' || event.type === 'text' || event.type === 'content_block_delta') {
|
|
356
|
+
const text = event.type === 'content_block_delta'
|
|
357
|
+
? (event.delta?.text || '')
|
|
358
|
+
: (event.content || '');
|
|
359
|
+
if (text) {
|
|
360
|
+
if (!this.v3StreamingStarted) {
|
|
361
|
+
this.v3StreamingStarted = true;
|
|
362
|
+
spinner.stop();
|
|
363
|
+
if (!this.directPromptMode) {
|
|
364
|
+
console.log();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
spinner.stop();
|
|
369
|
+
}
|
|
370
|
+
process.stdout.write(text);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
spinner.text = chalk_1.default.cyan('[Response] ') + 'Writing response...';
|
|
374
|
+
}
|
|
348
375
|
return;
|
|
349
376
|
}
|
|
350
377
|
if (event.type === 'complete') {
|
|
@@ -828,13 +855,19 @@ class ChatCommand {
|
|
|
828
855
|
await this.runOperatorDirectAnswer(prompt);
|
|
829
856
|
return;
|
|
830
857
|
}
|
|
831
|
-
// ── Repo-grounded operator path:
|
|
858
|
+
// ── Repo-grounded operator path: try V3 agent first, then fall back ──
|
|
832
859
|
// Prompts that reference files, code symbols, or analysis verbs need
|
|
833
860
|
// tool access to read actual file contents. Route these through the
|
|
834
|
-
//
|
|
835
|
-
//
|
|
861
|
+
// V3 agent (which archives runs for history/replay/fork and supports
|
|
862
|
+
// workspace hydration) first. Falls back to local agent loop if V3
|
|
863
|
+
// is unreachable.
|
|
836
864
|
if (this.isRepoGroundedPrompt(prompt) && this.tools) {
|
|
837
865
|
this.operatorMode = true;
|
|
866
|
+
const handledByV3 = await this.tryV3AgentWorkflow(prompt);
|
|
867
|
+
if (handledByV3) {
|
|
868
|
+
this.saveSession();
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
838
871
|
await this.runLocalAgentLoop(prompt);
|
|
839
872
|
return;
|
|
840
873
|
}
|
|
@@ -1431,6 +1464,7 @@ class ChatCommand {
|
|
|
1431
1464
|
this.v3IterationCount = 0;
|
|
1432
1465
|
this.v3ToolCallCount = 0;
|
|
1433
1466
|
this.v3LastActivity = Date.now();
|
|
1467
|
+
this.v3StreamingStarted = false;
|
|
1434
1468
|
const spinner = this.jsonOutput ? null : (0, logger_js_1.createSpinner)({
|
|
1435
1469
|
text: routingPolicy.cloudSelected ? 'Routing heavy task to Vigthoria Cloud...' : 'Routing to V3 Agent...',
|
|
1436
1470
|
spinner: 'clock',
|
|
@@ -1484,6 +1518,10 @@ class ChatCommand {
|
|
|
1484
1518
|
if (spinner) {
|
|
1485
1519
|
spinner.stop();
|
|
1486
1520
|
}
|
|
1521
|
+
// End streaming line if we streamed text inline
|
|
1522
|
+
if (this.v3StreamingStarted) {
|
|
1523
|
+
process.stdout.write('\n');
|
|
1524
|
+
}
|
|
1487
1525
|
const previewGate = (response.metadata?.previewGate || null);
|
|
1488
1526
|
const workspaceHasOutput = this.api.hasAgentWorkspaceOutput(workspaceContext);
|
|
1489
1527
|
const success = previewGate?.required === true
|
|
@@ -1536,6 +1574,12 @@ class ChatCommand {
|
|
|
1536
1574
|
metadata: response.metadata || {},
|
|
1537
1575
|
}, null, 2));
|
|
1538
1576
|
}
|
|
1577
|
+
else if (this.v3StreamingStarted) {
|
|
1578
|
+
// Content was already streamed to stdout in real-time; skip duplicate print.
|
|
1579
|
+
if (!this.directPromptMode) {
|
|
1580
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1539
1583
|
else if (response.content) {
|
|
1540
1584
|
if (!this.directPromptMode) {
|
|
1541
1585
|
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
|
|
@@ -1976,10 +2020,11 @@ class ChatCommand {
|
|
|
1976
2020
|
if (!this.directPromptMode) {
|
|
1977
2021
|
return false;
|
|
1978
2022
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2023
|
+
// Always prefer V3 agent first — it supports workspace hydration for
|
|
2024
|
+
// non-server-bindable workspaces (Windows paths, remote machines).
|
|
2025
|
+
// The V3 path will fall back to local-agent-loop if V3 is unreachable.
|
|
2026
|
+
// This ensures runs get archived for history/replay/fork.
|
|
2027
|
+
return false;
|
|
1983
2028
|
}
|
|
1984
2029
|
shouldRequireV3AgentWorkflow(prompt) {
|
|
1985
2030
|
if (!this.directPromptMode) {
|
package/dist/commands/deploy.js
CHANGED
|
@@ -127,6 +127,7 @@ class DeployCommand {
|
|
|
127
127
|
* Deploy to preview URL (free)
|
|
128
128
|
*/
|
|
129
129
|
async deployToPreview(projectPath) {
|
|
130
|
+
this.requireAuth();
|
|
130
131
|
const spinner = (0, logger_js_1.createSpinner)('Deploying to preview...').start();
|
|
131
132
|
try {
|
|
132
133
|
const projectDir = projectPath || process.cwd();
|
|
@@ -155,6 +156,7 @@ class DeployCommand {
|
|
|
155
156
|
this.logger.error('Deploy failed');
|
|
156
157
|
const errMsg = error instanceof Error ? error.message : 'Unknown error';
|
|
157
158
|
console.log(chalk_1.default.red(`\n❌ Error: ${errMsg}\n`));
|
|
159
|
+
process.exitCode = 1;
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
/**
|
package/dist/commands/fork.d.ts
CHANGED
package/dist/commands/fork.js
CHANGED
|
@@ -31,18 +31,35 @@ class ForkCommand {
|
|
|
31
31
|
return headers;
|
|
32
32
|
}
|
|
33
33
|
getBaseUrl() {
|
|
34
|
+
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
35
|
+
const allowLocal = process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
34
36
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
35
37
|
process.env.V3_AGENT_URL ||
|
|
36
|
-
'http://127.0.0.1:8030')
|
|
38
|
+
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
|
39
|
+
configuredApiUrl);
|
|
40
|
+
}
|
|
41
|
+
resolveWorkspaceRoot(project) {
|
|
42
|
+
if (/^[a-zA-Z]:[\\/]/.test(project) || /^\\\\/.test(project))
|
|
43
|
+
return '';
|
|
44
|
+
if (typeof require !== 'undefined') {
|
|
45
|
+
try {
|
|
46
|
+
const path = require('path');
|
|
47
|
+
if (!path.isAbsolute(project))
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
return project;
|
|
37
53
|
}
|
|
38
54
|
async run(runId, message, options) {
|
|
39
55
|
const project = options.project || process.cwd();
|
|
56
|
+
const workspace = this.resolveWorkspaceRoot(project);
|
|
40
57
|
const eventIndex = options.eventIndex || 0;
|
|
41
58
|
const spinner = (0, logger_js_1.createSpinner)(`Forking run ${runId}...`).start();
|
|
42
59
|
try {
|
|
43
60
|
const baseUrl = this.getBaseUrl();
|
|
44
61
|
const body = {
|
|
45
|
-
workspace_root:
|
|
62
|
+
workspace_root: workspace,
|
|
46
63
|
from_event_index: eventIndex,
|
|
47
64
|
new_request: message || '',
|
|
48
65
|
stream: true,
|
|
@@ -58,6 +75,9 @@ class ForkCommand {
|
|
|
58
75
|
if (resp.status === 404) {
|
|
59
76
|
this.logger.error(`Run ${runId} not found or has no event log.`);
|
|
60
77
|
}
|
|
78
|
+
else if (resp.status === 502 || resp.status === 503) {
|
|
79
|
+
this.logger.error(`V3 run-history route is not available on ${baseUrl}. Backend may not expose /api/runs.`);
|
|
80
|
+
}
|
|
61
81
|
else {
|
|
62
82
|
this.logger.error(`Fork failed: ${resp.status} ${resp.statusText}`);
|
|
63
83
|
}
|
package/dist/commands/history.js
CHANGED
|
@@ -31,26 +31,49 @@ class HistoryCommand {
|
|
|
31
31
|
return headers;
|
|
32
32
|
}
|
|
33
33
|
getBaseUrl() {
|
|
34
|
+
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
35
|
+
const allowLocal = process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
34
36
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
35
37
|
process.env.V3_AGENT_URL ||
|
|
36
|
-
'http://127.0.0.1:8030')
|
|
38
|
+
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
|
39
|
+
configuredApiUrl);
|
|
40
|
+
}
|
|
41
|
+
resolveWorkspaceRoot(project) {
|
|
42
|
+
// On Windows or non-absolute paths, send empty so the server uses its fallback root
|
|
43
|
+
if (/^[a-zA-Z]:[\\/]/.test(project) || /^\\\\/.test(project))
|
|
44
|
+
return '';
|
|
45
|
+
if (typeof require !== 'undefined') {
|
|
46
|
+
try {
|
|
47
|
+
const path = require('path');
|
|
48
|
+
if (!path.isAbsolute(project))
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
catch { }
|
|
52
|
+
}
|
|
53
|
+
return project;
|
|
37
54
|
}
|
|
38
55
|
async run(options) {
|
|
39
56
|
const limit = options.limit || 20;
|
|
40
57
|
const project = options.project || process.cwd();
|
|
58
|
+
const workspace = this.resolveWorkspaceRoot(project);
|
|
41
59
|
const spinner = (0, logger_js_1.createSpinner)('Loading run history...').start();
|
|
42
60
|
try {
|
|
43
61
|
const baseUrl = this.getBaseUrl();
|
|
44
62
|
const params = new URLSearchParams({
|
|
45
63
|
limit: String(limit),
|
|
46
|
-
workspace_root:
|
|
64
|
+
workspace_root: workspace,
|
|
47
65
|
});
|
|
48
66
|
const resp = await fetch(`${baseUrl}/api/runs?${params}`, {
|
|
49
67
|
headers: this.getHeaders(),
|
|
50
68
|
});
|
|
51
69
|
if (!resp.ok) {
|
|
52
70
|
spinner.stop();
|
|
53
|
-
|
|
71
|
+
if (resp.status === 404 || resp.status === 502 || resp.status === 503) {
|
|
72
|
+
this.logger.error(`V3 run-history route is not available on ${baseUrl}. Backend may not expose /api/runs.`);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
this.logger.error(`Failed to fetch runs: ${resp.status} ${resp.statusText}`);
|
|
76
|
+
}
|
|
54
77
|
return;
|
|
55
78
|
}
|
|
56
79
|
const data = (await resp.json());
|
package/dist/commands/replay.js
CHANGED
|
@@ -31,9 +31,25 @@ class ReplayCommand {
|
|
|
31
31
|
return headers;
|
|
32
32
|
}
|
|
33
33
|
getBaseUrl() {
|
|
34
|
+
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
35
|
+
const allowLocal = process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
34
36
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
35
37
|
process.env.V3_AGENT_URL ||
|
|
36
|
-
'http://127.0.0.1:8030')
|
|
38
|
+
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
|
39
|
+
configuredApiUrl);
|
|
40
|
+
}
|
|
41
|
+
resolveWorkspaceRoot(project) {
|
|
42
|
+
if (/^[a-zA-Z]:[\\/]/.test(project) || /^\\\\/.test(project))
|
|
43
|
+
return '';
|
|
44
|
+
if (typeof require !== 'undefined') {
|
|
45
|
+
try {
|
|
46
|
+
const path = require('path');
|
|
47
|
+
if (!path.isAbsolute(project))
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
return project;
|
|
37
53
|
}
|
|
38
54
|
sleep(ms) {
|
|
39
55
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -41,10 +57,11 @@ class ReplayCommand {
|
|
|
41
57
|
async run(runId, options) {
|
|
42
58
|
const speed = options.speed || 200;
|
|
43
59
|
const project = options.project || process.cwd();
|
|
60
|
+
const workspace = this.resolveWorkspaceRoot(project);
|
|
44
61
|
const spinner = (0, logger_js_1.createSpinner)(`Loading events for run ${runId}...`).start();
|
|
45
62
|
try {
|
|
46
63
|
const baseUrl = this.getBaseUrl();
|
|
47
|
-
const params = new URLSearchParams({ workspace_root:
|
|
64
|
+
const params = new URLSearchParams({ workspace_root: workspace });
|
|
48
65
|
const resp = await fetch(`${baseUrl}/api/runs/${encodeURIComponent(runId)}/events?${params}`, {
|
|
49
66
|
headers: this.getHeaders(),
|
|
50
67
|
});
|
|
@@ -53,6 +70,9 @@ class ReplayCommand {
|
|
|
53
70
|
if (resp.status === 404) {
|
|
54
71
|
this.logger.error(`No event log found for run ${runId}. Events are only recorded for runs made after the replay system was deployed.`);
|
|
55
72
|
}
|
|
73
|
+
else if (resp.status === 502 || resp.status === 503) {
|
|
74
|
+
this.logger.error(`V3 run-history route is not available on ${baseUrl}. Backend may not expose /api/runs.`);
|
|
75
|
+
}
|
|
56
76
|
else {
|
|
57
77
|
this.logger.error(`Failed to fetch events: ${resp.status} ${resp.statusText}`);
|
|
58
78
|
}
|