vigthoria-cli 1.9.21 → 1.10.0
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.js +1 -1
- package/dist/commands/chat.d.ts +4 -4
- package/dist/commands/chat.js +118 -15
- package/dist/commands/config.d.ts +9 -1
- package/dist/commands/config.js +79 -39
- package/dist/commands/fork.js +1 -1
- package/dist/commands/history.js +1 -1
- package/dist/commands/replay.js +1 -1
- package/dist/index.js +47 -17
- package/dist/utils/api.d.ts +2 -0
- package/dist/utils/api.js +79 -12
- package/dist/utils/tools.js +14 -14
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +1 -1
package/dist/commands/cancel.js
CHANGED
|
@@ -32,7 +32,7 @@ export class CancelCommand {
|
|
|
32
32
|
}
|
|
33
33
|
getBaseUrl() {
|
|
34
34
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
35
|
-
const allowLocal = isServerRuntime()
|
|
35
|
+
const allowLocal = !isServerRuntime() || process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
36
36
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
37
37
|
process.env.V3_AGENT_URL ||
|
|
38
38
|
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export declare class ChatCommand {
|
|
|
40
40
|
private savePlanToVigFlow;
|
|
41
41
|
private jsonOutput;
|
|
42
42
|
private modelGovernanceFallback;
|
|
43
|
+
private retryPromptSignature;
|
|
44
|
+
private retryPromptStreak;
|
|
43
45
|
private lastAgentRunOutcome;
|
|
44
46
|
private isJwtExpirationError;
|
|
45
47
|
private isNetworkError;
|
|
@@ -155,10 +157,7 @@ export declare class ChatCommand {
|
|
|
155
157
|
* Resumes only the failed/unfinished tasks from the previous run.
|
|
156
158
|
*/
|
|
157
159
|
private buildRetryPrompt;
|
|
158
|
-
|
|
159
|
-
* Build the prompt sent to the agent when the user types `/continue`.
|
|
160
|
-
* Tells the agent to keep working from the current workspace state.
|
|
161
|
-
*/
|
|
160
|
+
private computeRetryPromptSignature;
|
|
162
161
|
private buildContinuePrompt;
|
|
163
162
|
/**
|
|
164
163
|
* Re-print the last agent run summary, or guide the user when there isn't one.
|
|
@@ -175,6 +174,7 @@ export declare class ChatCommand {
|
|
|
175
174
|
private workspaceContainsHtmlEntry;
|
|
176
175
|
private shouldBypassDirectSingleFileFlow;
|
|
177
176
|
private shouldPreferLocalAgentLoop;
|
|
177
|
+
private getRuntimeEnvironmentContext;
|
|
178
178
|
private shouldRequireV3AgentWorkflow;
|
|
179
179
|
private isServerBindableWorkspace;
|
|
180
180
|
private isProtectedFileReferenceSafe;
|
package/dist/commands/chat.js
CHANGED
|
@@ -59,6 +59,8 @@ export class ChatCommand {
|
|
|
59
59
|
savePlanToVigFlow = false;
|
|
60
60
|
jsonOutput = false;
|
|
61
61
|
modelGovernanceFallback = null;
|
|
62
|
+
retryPromptSignature = null;
|
|
63
|
+
retryPromptStreak = 0;
|
|
62
64
|
// Last completed Agent run — used by /retry, /continue, and the final summary block.
|
|
63
65
|
lastAgentRunOutcome = null;
|
|
64
66
|
isJwtExpirationError(error) {
|
|
@@ -381,15 +383,22 @@ export class ChatCommand {
|
|
|
381
383
|
}
|
|
382
384
|
buildTaskShapingInstructions(prompt) {
|
|
383
385
|
const instructions = [];
|
|
386
|
+
const runtime = this.getRuntimeEnvironmentContext();
|
|
384
387
|
// Platform-aware routing hints
|
|
385
|
-
if (
|
|
388
|
+
if (runtime.platform === 'windows') {
|
|
386
389
|
instructions.push('Platform: Windows. Use list_dir, glob, read_file, and the grep tool for searching.', 'The grep tool handles Windows automatically — do not use bash to call grep, findstr, or Select-String manually.', 'Do not use bash for Unix commands (cat, head, tail, awk, sed, wc).', 'Use read_file to inspect file contents instead of shell commands.', 'All file paths use forward slashes internally.');
|
|
387
390
|
}
|
|
391
|
+
else if (runtime.platform === 'macos') {
|
|
392
|
+
instructions.push('Platform: macOS. Prefer list_dir, grep, and read_file tools for deterministic results.', 'Use workspace-relative paths and verify file existence before claiming a file is missing.');
|
|
393
|
+
}
|
|
394
|
+
else if (runtime.platform === 'linux') {
|
|
395
|
+
instructions.push('Platform: Linux. Prefer list_dir, grep, and read_file for grounded repository inspection.', 'Use exact file paths from tool output when reporting findings or fixes.');
|
|
396
|
+
}
|
|
388
397
|
if (this.isDiagnosticPrompt(prompt)) {
|
|
389
398
|
instructions.push('Diagnostic mode is active.', 'Treat this as a debugging task, not a generic code review or feature request.', 'Start with concrete evidence: logs, runtime errors, config, launch files, and exact symbol references.', 'If log files exist, inspect them before proposing fixes.', 'Do not claim a file, definition, asset, or symbol is missing until you verify that with tools.', 'If a prior diagnosis mentioned a missing symbol or YAML entry, re-check the actual files before repeating it.', 'Prefer grep plus read_file around the exact references involved in the failure.', 'Separate your reasoning into: Evidence, Confirmed Cause, and Remaining Hypotheses.', 'Do not suggest speculative fixes when the current evidence contradicts them.', 'CRITICAL GROUNDING RULE: Every key name, variable name, symbol, or identifier you mention in your final answer MUST appear verbatim in the tool output you received. If a key/symbol does NOT appear in tool output, you MUST NOT mention it as involved in any conflict or issue.', 'CROSS-FILE ATTRIBUTION: When reporting conflicts between two files, a key/symbol is conflicting ONLY if it appears in BOTH files. Read each file carefully and list only the exact keys that appear in the relevant handler/function of EACH file. Do not assume that because one file handles a key, the other file does too.', 'When reporting conflicts between files, cite the exact file name, line number, and the exact string/key from the tool output. Do not paraphrase or substitute key names.', 'Before concluding, re-check: (1) does every key/symbol in my answer actually appear in the evidence I gathered? (2) for each claimed conflict, did I verify the key appears in BOTH files? If not, correct your answer.');
|
|
390
399
|
}
|
|
391
400
|
if (this.isBrowserTaskPrompt(prompt)) {
|
|
392
|
-
instructions.push('Browser-debug mode is active.', 'Prefer concrete browser evidence such as console errors, network failures, DOM state, and websocket behavior.', '
|
|
401
|
+
instructions.push('Browser-debug mode is active.', 'Prefer concrete browser evidence such as console errors, network failures, DOM state, and websocket behavior.', 'Use the DevTools Bridge only when the user has explicitly enabled it for this run; otherwise ask for permission before requiring local browser tooling.');
|
|
393
402
|
}
|
|
394
403
|
if (instructions.length === 0) {
|
|
395
404
|
return '';
|
|
@@ -444,7 +453,9 @@ export class ChatCommand {
|
|
|
444
453
|
}
|
|
445
454
|
}
|
|
446
455
|
async getPromptRuntimeContext(prompt) {
|
|
447
|
-
const runtimeContext = {
|
|
456
|
+
const runtimeContext = {
|
|
457
|
+
agentRuntime: this.getRuntimeEnvironmentContext(),
|
|
458
|
+
};
|
|
448
459
|
const brainContext = this.buildProjectBrainRuntimeContext(prompt, this.operatorMode ? 'vigthoria-cli.operator' : this.agentMode ? 'vigthoria-cli.agent' : 'vigthoria-cli.chat');
|
|
449
460
|
if (brainContext) {
|
|
450
461
|
runtimeContext.vigthoriaBrain = brainContext;
|
|
@@ -452,6 +463,19 @@ export class ChatCommand {
|
|
|
452
463
|
if (!this.isBrowserTaskPrompt(prompt)) {
|
|
453
464
|
return runtimeContext;
|
|
454
465
|
}
|
|
466
|
+
const devtoolsBridgeAllowed = /^(1|true|yes)$/i.test(String(process.env.VIGTHORIA_DEVTOOLS_BRIDGE_ALLOWED || process.env.VIGTHORIA_BRIDGE_ALLOWED || ''));
|
|
467
|
+
if (!devtoolsBridgeAllowed) {
|
|
468
|
+
if (!this.jsonOutput) {
|
|
469
|
+
console.log(chalk.yellow('Browser task detected. DevTools Bridge is opt-in; the agent will ask before relying on local browser tooling.'));
|
|
470
|
+
}
|
|
471
|
+
return {
|
|
472
|
+
...runtimeContext,
|
|
473
|
+
browserTask: true,
|
|
474
|
+
devtoolsBridgeAvailable: false,
|
|
475
|
+
devtoolsBridgeAllowed: false,
|
|
476
|
+
devtoolsBridgeEndpoint: null,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
455
479
|
const bridgeStatus = await this.callApi('Checking DevTools Bridge status', () => this.api.getDevtoolsBridgeStatus(), 0);
|
|
456
480
|
if (!this.jsonOutput && bridgeStatus.ok) {
|
|
457
481
|
console.log(chalk.gray(`Browser task detected. DevTools Bridge is reachable at ${bridgeStatus.endpoint}.`));
|
|
@@ -463,6 +487,7 @@ export class ChatCommand {
|
|
|
463
487
|
...runtimeContext,
|
|
464
488
|
browserTask: true,
|
|
465
489
|
devtoolsBridgeAvailable: bridgeStatus.ok,
|
|
490
|
+
devtoolsBridgeAllowed: true,
|
|
466
491
|
devtoolsBridgeEndpoint: bridgeStatus.endpoint,
|
|
467
492
|
};
|
|
468
493
|
}
|
|
@@ -2527,6 +2552,27 @@ export class ChatCommand {
|
|
|
2527
2552
|
console.log(chalk.yellow('Nothing to retry — run an agent task first.'));
|
|
2528
2553
|
continue;
|
|
2529
2554
|
}
|
|
2555
|
+
const nextSignature = this.computeRetryPromptSignature();
|
|
2556
|
+
if (nextSignature && this.retryPromptSignature === nextSignature) {
|
|
2557
|
+
this.retryPromptStreak += 1;
|
|
2558
|
+
}
|
|
2559
|
+
else {
|
|
2560
|
+
this.retryPromptSignature = nextSignature;
|
|
2561
|
+
this.retryPromptStreak = 1;
|
|
2562
|
+
}
|
|
2563
|
+
if (this.retryPromptStreak >= 3) {
|
|
2564
|
+
const continuePrompt = this.buildContinuePrompt();
|
|
2565
|
+
if (continuePrompt) {
|
|
2566
|
+
console.log(chalk.yellow('Repeated /retry detected with the same failing task set. Escalating to /continue to avoid planner loops.'));
|
|
2567
|
+
if (!this.agentMode) {
|
|
2568
|
+
this.agentMode = true;
|
|
2569
|
+
this.syncInteractiveModeModel('agent');
|
|
2570
|
+
console.log(chalk.gray('Agent mode re-enabled for continuation.'));
|
|
2571
|
+
}
|
|
2572
|
+
await this.runAgentTurn(continuePrompt);
|
|
2573
|
+
continue;
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2530
2576
|
if (!this.agentMode) {
|
|
2531
2577
|
this.agentMode = true;
|
|
2532
2578
|
this.syncInteractiveModeModel('agent');
|
|
@@ -2681,6 +2727,7 @@ export class ChatCommand {
|
|
|
2681
2727
|
const o = this.lastAgentRunOutcome;
|
|
2682
2728
|
if (!o || !o.prompt)
|
|
2683
2729
|
return null;
|
|
2730
|
+
const runtime = this.getRuntimeEnvironmentContext();
|
|
2684
2731
|
const remaining = [...new Set([...o.failedTaskIds, ...o.unfinishedTaskIds])];
|
|
2685
2732
|
const taskList = remaining.length > 0 ? remaining.join(', ') : '';
|
|
2686
2733
|
const blockerLine = o.qualityBlockers.length > 0
|
|
@@ -2689,15 +2736,27 @@ export class ChatCommand {
|
|
|
2689
2736
|
const missingLine = o.qualityMissing.length > 0
|
|
2690
2737
|
? `\nMissing pieces: ${o.qualityMissing.slice(0, 6).join(', ')}.`
|
|
2691
2738
|
: '';
|
|
2739
|
+
const envLine = `\nExecution environment: ${runtime.platform}; machine scope: ${runtime.machineScope}; workspace path: ${runtime.workspacePath}.`;
|
|
2740
|
+
const localPreferenceLine = runtime.machineScope === 'local-machine'
|
|
2741
|
+
? '\nUse local workspace tools and local filesystem paths first; do not assume server-side workspace access.'
|
|
2742
|
+
: '';
|
|
2692
2743
|
if (taskList) {
|
|
2693
|
-
return `Resume the previous agent run. Re-execute only these tasks and make them pass: ${taskList}.${blockerLine}${missingLine}\nOriginal request was: ${o.prompt}`;
|
|
2744
|
+
return `Resume the previous agent run. Re-execute only these tasks and make them pass: ${taskList}.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${o.prompt}`;
|
|
2694
2745
|
}
|
|
2695
|
-
return `Retry the previous request and make sure it finishes successfully.${blockerLine}${missingLine}\nOriginal request was: ${o.prompt}`;
|
|
2746
|
+
return `Retry the previous request and make sure it finishes successfully.${blockerLine}${missingLine}${envLine}${localPreferenceLine}\nOriginal request was: ${o.prompt}`;
|
|
2747
|
+
}
|
|
2748
|
+
computeRetryPromptSignature() {
|
|
2749
|
+
const o = this.lastAgentRunOutcome;
|
|
2750
|
+
if (!o) {
|
|
2751
|
+
return null;
|
|
2752
|
+
}
|
|
2753
|
+
const remaining = [...new Set([...o.failedTaskIds, ...o.unfinishedTaskIds])].sort();
|
|
2754
|
+
if (remaining.length === 0) {
|
|
2755
|
+
return null;
|
|
2756
|
+
}
|
|
2757
|
+
const blockers = [...(o.qualityBlockers || [])].slice(0, 3).sort();
|
|
2758
|
+
return `${remaining.join('|')}::${blockers.join('|')}`;
|
|
2696
2759
|
}
|
|
2697
|
-
/**
|
|
2698
|
-
* Build the prompt sent to the agent when the user types `/continue`.
|
|
2699
|
-
* Tells the agent to keep working from the current workspace state.
|
|
2700
|
-
*/
|
|
2701
2760
|
buildContinuePrompt() {
|
|
2702
2761
|
const o = this.lastAgentRunOutcome;
|
|
2703
2762
|
if (!o || !o.prompt)
|
|
@@ -2743,6 +2802,14 @@ export class ChatCommand {
|
|
|
2743
2802
|
else {
|
|
2744
2803
|
console.log(chalk.gray('No compact session memory summary yet.'));
|
|
2745
2804
|
}
|
|
2805
|
+
const runtime = this.getRuntimeEnvironmentContext();
|
|
2806
|
+
console.log();
|
|
2807
|
+
console.log(chalk.white('Runtime Environment:'));
|
|
2808
|
+
console.log(chalk.gray(`Platform: ${runtime.platform} (${runtime.osPlatform})`));
|
|
2809
|
+
console.log(chalk.gray(`Machine scope: ${runtime.machineScope}`));
|
|
2810
|
+
console.log(chalk.gray(`Workspace: ${runtime.workspacePath}`));
|
|
2811
|
+
console.log(chalk.gray(`CWD: ${runtime.cwd}`));
|
|
2812
|
+
console.log(chalk.gray(`Server-bindable workspace: ${runtime.serverBindableWorkspace ? 'yes' : 'no'}`));
|
|
2746
2813
|
this.showProjectMemory();
|
|
2747
2814
|
}
|
|
2748
2815
|
showProjectMemory() {
|
|
@@ -2801,6 +2868,9 @@ export class ChatCommand {
|
|
|
2801
2868
|
return [
|
|
2802
2869
|
'Vigthoria CLI agent operating contract.',
|
|
2803
2870
|
`You are operating inside the project root: ${this.currentProjectPath}`,
|
|
2871
|
+
`You are operating on the user's LOCAL machine. This CLI is not a server-only runtime.`,
|
|
2872
|
+
`All file reads/writes and command execution must target the local project/workspace path unless the user explicitly requests remote/server execution.`,
|
|
2873
|
+
'For command execution: ask for confirmation before risky commands; never redirect normal local work to server paths.',
|
|
2804
2874
|
'CRITICAL: Begin working on the user\'s task IMMEDIATELY. Your very first response MUST contain <tool_call> blocks to gather evidence. Do NOT acknowledge instructions, restate the task, describe your plan, or discuss tool policies. Act, do not talk.',
|
|
2805
2875
|
'FILE CREATION RULE: When the user asks you to build, create, or generate files, you MUST use the write_file tool to actually create each file on disk. NEVER output code snippets as markdown text — always write them to files using write_file. If the task requires a new project, create a new directory first, then write all files into it.',
|
|
2806
2876
|
'Stay inside that project unless the user explicitly asks otherwise.',
|
|
@@ -2901,19 +2971,52 @@ export class ChatCommand {
|
|
|
2901
2971
|
if (this.shouldRequireV3AgentWorkflow(prompt)) {
|
|
2902
2972
|
return false;
|
|
2903
2973
|
}
|
|
2904
|
-
|
|
2974
|
+
const forceV3 = /^(1|true|yes)$/i.test(String(process.env.VIGTHORIA_FORCE_V3_AGENT || ''));
|
|
2975
|
+
if (forceV3) {
|
|
2905
2976
|
return false;
|
|
2906
2977
|
}
|
|
2907
|
-
|
|
2908
|
-
// non-server-bindable workspaces
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2978
|
+
const runtime = this.getRuntimeEnvironmentContext();
|
|
2979
|
+
// Local machines and non-server-bindable workspaces should run locally first.
|
|
2980
|
+
if (!runtime.serverBindableWorkspace) {
|
|
2981
|
+
return true;
|
|
2982
|
+
}
|
|
2983
|
+
// Interactive sessions should prioritize local edits unless V3 is explicitly forced.
|
|
2984
|
+
if (!this.directPromptMode) {
|
|
2985
|
+
return true;
|
|
2986
|
+
}
|
|
2987
|
+
// For direct prompts on server-bindable Linux roots, keep V3-first behavior.
|
|
2988
|
+
return runtime.platform !== 'linux';
|
|
2989
|
+
}
|
|
2990
|
+
getRuntimeEnvironmentContext() {
|
|
2991
|
+
const osPlatform = os.platform();
|
|
2992
|
+
const platform = osPlatform === 'win32'
|
|
2993
|
+
? 'windows'
|
|
2994
|
+
: osPlatform === 'darwin'
|
|
2995
|
+
? 'macos'
|
|
2996
|
+
: osPlatform === 'linux'
|
|
2997
|
+
? 'linux'
|
|
2998
|
+
: 'unknown';
|
|
2999
|
+
const workspacePath = this.currentProjectPath || process.cwd();
|
|
3000
|
+
const serverBindableWorkspace = this.isServerBindableWorkspace(workspacePath);
|
|
3001
|
+
return {
|
|
3002
|
+
osPlatform,
|
|
3003
|
+
platform,
|
|
3004
|
+
nodeVersion: process.version,
|
|
3005
|
+
cwd: process.cwd(),
|
|
3006
|
+
workspacePath,
|
|
3007
|
+
directPromptMode: this.directPromptMode,
|
|
3008
|
+
serverBindableWorkspace,
|
|
3009
|
+
machineScope: serverBindableWorkspace ? 'server-workspace' : 'local-machine',
|
|
3010
|
+
};
|
|
2912
3011
|
}
|
|
2913
3012
|
shouldRequireV3AgentWorkflow(prompt) {
|
|
2914
3013
|
if (!this.directPromptMode) {
|
|
2915
3014
|
return false;
|
|
2916
3015
|
}
|
|
3016
|
+
const runtime = this.getRuntimeEnvironmentContext();
|
|
3017
|
+
if (runtime.machineScope === 'local-machine') {
|
|
3018
|
+
return false;
|
|
3019
|
+
}
|
|
2917
3020
|
if (this.inferTargetFilesFromPrompt(prompt).length > 0) {
|
|
2918
3021
|
return false;
|
|
2919
3022
|
}
|
|
@@ -9,12 +9,20 @@ interface ConfigOptions {
|
|
|
9
9
|
list?: boolean;
|
|
10
10
|
reset?: boolean;
|
|
11
11
|
}
|
|
12
|
+
interface InitOptions {
|
|
13
|
+
model?: string;
|
|
14
|
+
ignorePatterns?: string;
|
|
15
|
+
autoApplyFixes?: boolean;
|
|
16
|
+
profile?: 'safe' | 'balanced' | 'fast';
|
|
17
|
+
yes?: boolean;
|
|
18
|
+
nonInteractive?: boolean;
|
|
19
|
+
}
|
|
12
20
|
export declare class ConfigCommand {
|
|
13
21
|
private config;
|
|
14
22
|
private logger;
|
|
15
23
|
constructor(config: Config, logger: Logger);
|
|
16
24
|
run(options: ConfigOptions): Promise<void>;
|
|
17
|
-
init(): Promise<void>;
|
|
25
|
+
init(options?: InitOptions): Promise<void>;
|
|
18
26
|
private setConfig;
|
|
19
27
|
private formatConfigValueForDisplay;
|
|
20
28
|
private redactConfigUrl;
|
package/dist/commands/config.js
CHANGED
|
@@ -33,56 +33,93 @@ export class ConfigCommand {
|
|
|
33
33
|
// Interactive mode
|
|
34
34
|
await this.interactiveConfig();
|
|
35
35
|
}
|
|
36
|
-
async init() {
|
|
36
|
+
async init(options = {}) {
|
|
37
37
|
console.log();
|
|
38
38
|
console.log(chalk.cyan(`${CH.hDouble.repeat(3)} Initialize Vigthoria in Project ${CH.hDouble.repeat(3)}`));
|
|
39
39
|
console.log();
|
|
40
40
|
const cwd = process.cwd();
|
|
41
41
|
const configFile = path.join(cwd, '.vigthoria.json');
|
|
42
|
+
const allowedModels = new Set(['code', 'code-35b', 'code-9b', 'balanced', 'balanced-4b']);
|
|
43
|
+
const hasOverrides = Boolean(options.model ||
|
|
44
|
+
options.ignorePatterns !== undefined ||
|
|
45
|
+
options.autoApplyFixes !== undefined ||
|
|
46
|
+
options.profile);
|
|
47
|
+
const nonInteractive = Boolean(options.nonInteractive || options.yes || hasOverrides);
|
|
42
48
|
if (fs.existsSync(configFile)) {
|
|
43
|
-
|
|
49
|
+
if (nonInteractive) {
|
|
50
|
+
if (!options.yes) {
|
|
51
|
+
this.logger.error('.vigthoria.json already exists. Re-run with --yes to overwrite in non-interactive mode.');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const { overwrite } = await inquirer.prompt([
|
|
57
|
+
{
|
|
58
|
+
type: 'confirm',
|
|
59
|
+
name: 'overwrite',
|
|
60
|
+
message: '.vigthoria.json already exists. Overwrite?',
|
|
61
|
+
default: false,
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
if (!overwrite) {
|
|
65
|
+
this.logger.info('Initialization cancelled');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let settings;
|
|
71
|
+
if (nonInteractive) {
|
|
72
|
+
const profileDefaults = {
|
|
73
|
+
safe: { defaultModel: 'balanced', autoApplyFixes: false },
|
|
74
|
+
balanced: { defaultModel: 'code', autoApplyFixes: false },
|
|
75
|
+
fast: { defaultModel: 'code-9b', autoApplyFixes: true },
|
|
76
|
+
};
|
|
77
|
+
const profile = options.profile && profileDefaults[options.profile] ? options.profile : 'balanced';
|
|
78
|
+
const defaults = profileDefaults[profile];
|
|
79
|
+
const model = options.model || defaults.defaultModel;
|
|
80
|
+
if (!allowedModels.has(model)) {
|
|
81
|
+
this.logger.error(`Invalid --model: ${model}`);
|
|
82
|
+
this.logger.info('Allowed values: code, code-35b, code-9b, balanced, balanced-4b');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
settings = {
|
|
86
|
+
defaultModel: model,
|
|
87
|
+
ignorePatterns: options.ignorePatterns || '',
|
|
88
|
+
autoApplyFixes: options.autoApplyFixes !== undefined ? options.autoApplyFixes : defaults.autoApplyFixes,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Gather project settings interactively
|
|
93
|
+
settings = await inquirer.prompt([
|
|
94
|
+
{
|
|
95
|
+
type: 'list',
|
|
96
|
+
name: 'defaultModel',
|
|
97
|
+
message: 'Default AI model:',
|
|
98
|
+
choices: [
|
|
99
|
+
{ name: '═══ Code Models ═══', disabled: true },
|
|
100
|
+
{ name: 'Vigthoria v3 Code 35B - Flagship coding model', value: 'code' },
|
|
101
|
+
{ name: 'Vigthoria v3 Code 35B - Explicit 35B selection', value: 'code-35b' },
|
|
102
|
+
{ name: 'Vigthoria v3 Code 9B - Fast coding specialist', value: 'code-9b' },
|
|
103
|
+
{ name: '═══ General Models ═══', disabled: true },
|
|
104
|
+
{ name: 'Vigthoria Master 7.6B - Balanced general model', value: 'balanced' },
|
|
105
|
+
{ name: 'Vigthoria v3 Balanced 4B - Efficient general purpose', value: 'balanced-4b' },
|
|
106
|
+
],
|
|
107
|
+
default: 'code',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: 'input',
|
|
111
|
+
name: 'ignorePatterns',
|
|
112
|
+
message: 'Additional ignore patterns (comma-separated):',
|
|
113
|
+
default: '',
|
|
114
|
+
},
|
|
44
115
|
{
|
|
45
116
|
type: 'confirm',
|
|
46
|
-
name: '
|
|
47
|
-
message: '
|
|
117
|
+
name: 'autoApplyFixes',
|
|
118
|
+
message: 'Auto-apply fixes without confirmation?',
|
|
48
119
|
default: false,
|
|
49
120
|
},
|
|
50
121
|
]);
|
|
51
|
-
if (!overwrite) {
|
|
52
|
-
this.logger.info('Initialization cancelled');
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
122
|
}
|
|
56
|
-
// Gather project settings
|
|
57
|
-
const settings = await inquirer.prompt([
|
|
58
|
-
{
|
|
59
|
-
type: 'list',
|
|
60
|
-
name: 'defaultModel',
|
|
61
|
-
message: 'Default AI model:',
|
|
62
|
-
choices: [
|
|
63
|
-
{ name: '═══ Code Models ═══', disabled: true },
|
|
64
|
-
{ name: 'Vigthoria v3 Code 35B - Flagship coding model', value: 'code' },
|
|
65
|
-
{ name: 'Vigthoria v3 Code 35B - Explicit 35B selection', value: 'code-35b' },
|
|
66
|
-
{ name: 'Vigthoria v3 Code 9B - Fast coding specialist', value: 'code-9b' },
|
|
67
|
-
{ name: '═══ General Models ═══', disabled: true },
|
|
68
|
-
{ name: 'Vigthoria Master 7.6B - Balanced general model', value: 'balanced' },
|
|
69
|
-
{ name: 'Vigthoria v3 Balanced 4B - Efficient general purpose', value: 'balanced-4b' },
|
|
70
|
-
],
|
|
71
|
-
default: 'code',
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
type: 'input',
|
|
75
|
-
name: 'ignorePatterns',
|
|
76
|
-
message: 'Additional ignore patterns (comma-separated):',
|
|
77
|
-
default: '',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'confirm',
|
|
81
|
-
name: 'autoApplyFixes',
|
|
82
|
-
message: 'Auto-apply fixes without confirmation?',
|
|
83
|
-
default: false,
|
|
84
|
-
},
|
|
85
|
-
]);
|
|
86
123
|
// Create project config
|
|
87
124
|
const projectConfig = {
|
|
88
125
|
defaultModel: settings.defaultModel,
|
|
@@ -104,7 +141,10 @@ export class ConfigCommand {
|
|
|
104
141
|
}
|
|
105
142
|
}
|
|
106
143
|
console.log();
|
|
107
|
-
|
|
144
|
+
if (nonInteractive) {
|
|
145
|
+
console.log(chalk.gray('Project initialized in non-interactive mode.'));
|
|
146
|
+
}
|
|
147
|
+
console.log(chalk.gray('Project initialized! Run vigthoria start for a beginner guide or vigthoria chat to begin.'));
|
|
108
148
|
console.log();
|
|
109
149
|
}
|
|
110
150
|
setConfig(keyValue) {
|
package/dist/commands/fork.js
CHANGED
|
@@ -29,7 +29,7 @@ export class ForkCommand {
|
|
|
29
29
|
}
|
|
30
30
|
getBaseUrl() {
|
|
31
31
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
32
|
-
const allowLocal = isServerRuntime()
|
|
32
|
+
const allowLocal = !isServerRuntime() || process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
33
33
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
34
34
|
process.env.V3_AGENT_URL ||
|
|
35
35
|
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
package/dist/commands/history.js
CHANGED
|
@@ -29,7 +29,7 @@ export class HistoryCommand {
|
|
|
29
29
|
}
|
|
30
30
|
getBaseUrl() {
|
|
31
31
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
32
|
-
const allowLocal = isServerRuntime()
|
|
32
|
+
const allowLocal = !isServerRuntime() || process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
33
33
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
34
34
|
process.env.V3_AGENT_URL ||
|
|
35
35
|
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
package/dist/commands/replay.js
CHANGED
|
@@ -29,7 +29,7 @@ export class ReplayCommand {
|
|
|
29
29
|
}
|
|
30
30
|
getBaseUrl() {
|
|
31
31
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
32
|
-
const allowLocal = isServerRuntime()
|
|
32
|
+
const allowLocal = !isServerRuntime() || process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
|
|
33
33
|
return (process.env.VIGTHORIA_V3_AGENT_URL ||
|
|
34
34
|
process.env.V3_AGENT_URL ||
|
|
35
35
|
(allowLocal ? 'http://127.0.0.1:8030' : null) ||
|
package/dist/index.js
CHANGED
|
@@ -1357,6 +1357,41 @@ Examples:
|
|
|
1357
1357
|
}
|
|
1358
1358
|
process.exitCode = 0;
|
|
1359
1359
|
});
|
|
1360
|
+
// Start command - beginner quick guide
|
|
1361
|
+
program
|
|
1362
|
+
.command('start')
|
|
1363
|
+
.alias('guide')
|
|
1364
|
+
.description('Show beginner quick-start steps and recommended first commands')
|
|
1365
|
+
.option('--json', 'Emit machine-readable guide output', false)
|
|
1366
|
+
.action(async (options) => {
|
|
1367
|
+
const steps = [
|
|
1368
|
+
'1. Authenticate: vigthoria login',
|
|
1369
|
+
'2. Verify account: vigthoria status',
|
|
1370
|
+
'3. Initialize project: vigthoria init',
|
|
1371
|
+
'4. Start coding: vigthoria chat --agent',
|
|
1372
|
+
'5. Check for updates: vigthoria update --check',
|
|
1373
|
+
];
|
|
1374
|
+
if (options.json) {
|
|
1375
|
+
console.log(JSON.stringify({
|
|
1376
|
+
command: 'start',
|
|
1377
|
+
steps,
|
|
1378
|
+
tips: [
|
|
1379
|
+
'Use vigthoria init --non-interactive for CI/bootstrap scripts.',
|
|
1380
|
+
'Run vigthoria doctor when environment checks fail.',
|
|
1381
|
+
],
|
|
1382
|
+
}, null, 2));
|
|
1383
|
+
}
|
|
1384
|
+
else {
|
|
1385
|
+
console.log();
|
|
1386
|
+
console.log(chalk.bold('Vigthoria quick start'));
|
|
1387
|
+
for (const step of steps) {
|
|
1388
|
+
console.log(chalk.gray('- ' + step));
|
|
1389
|
+
}
|
|
1390
|
+
console.log();
|
|
1391
|
+
console.log(chalk.gray('Tip: use vigthoria init --profile safe --non-interactive for conservative defaults.'));
|
|
1392
|
+
}
|
|
1393
|
+
process.exitCode = 0;
|
|
1394
|
+
});
|
|
1360
1395
|
// Config command
|
|
1361
1396
|
program
|
|
1362
1397
|
.command('config')
|
|
@@ -1385,7 +1420,6 @@ Examples:
|
|
|
1385
1420
|
const manifestUrl = typeof options.manifest === 'string' ? options.manifest.trim() : VIGTHORIA_DEFAULT_MANIFEST_URL.trim();
|
|
1386
1421
|
const channel = typeof options.channel === 'string' ? options.channel.trim() : 'stable';
|
|
1387
1422
|
const allowDowngrade = !!options.allowDowngrade;
|
|
1388
|
-
const gitPackageSpec = 'git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git';
|
|
1389
1423
|
if (updateTarget) {
|
|
1390
1424
|
if (!isSafeNpmPackageSpec(updateTarget)) {
|
|
1391
1425
|
console.error(chalk.red('Refusing to run installer with unsafe package spec.'));
|
|
@@ -1483,7 +1517,7 @@ Examples:
|
|
|
1483
1517
|
}
|
|
1484
1518
|
catch (error) {
|
|
1485
1519
|
console.error(chalk.red('Failed to process manifest update:'), error.message);
|
|
1486
|
-
console.log(chalk.gray('Falling back to npm
|
|
1520
|
+
console.log(chalk.gray('Falling back to npm registry update channel...'));
|
|
1487
1521
|
}
|
|
1488
1522
|
}
|
|
1489
1523
|
if (isOfflineMode()) {
|
|
@@ -1518,21 +1552,11 @@ Examples:
|
|
|
1518
1552
|
catch (error) {
|
|
1519
1553
|
console.error(chalk.red('Failed to check/install via npm registry:'), error.message);
|
|
1520
1554
|
if (options.check) {
|
|
1521
|
-
console.log(chalk.gray(
|
|
1555
|
+
console.log(chalk.gray('npm registry check failed. Try again later or use --manifest with a valid release manifest URL.'));
|
|
1522
1556
|
return;
|
|
1523
1557
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
await installGlobalPackageWithNpm(gitPackageSpec);
|
|
1527
|
-
console.log(chalk.green('Updated via git package fallback'));
|
|
1528
|
-
console.log(chalk.gray('Please restart the CLI to use the new version'));
|
|
1529
|
-
}
|
|
1530
|
-
catch (fallbackError) {
|
|
1531
|
-
console.error(chalk.red('Fallback update also failed:'), fallbackError.message);
|
|
1532
|
-
console.log(chalk.gray('Try manually: npm install -g vigthoria-cli@latest'));
|
|
1533
|
-
console.log(chalk.gray(`Or: npm install -g ${gitPackageSpec}`));
|
|
1534
|
-
process.exitCode = 1;
|
|
1535
|
-
}
|
|
1558
|
+
console.log(chalk.gray('Try manually: npm install -g vigthoria-cli@latest'));
|
|
1559
|
+
process.exitCode = 1;
|
|
1536
1560
|
}
|
|
1537
1561
|
});
|
|
1538
1562
|
// Hyper Loop command alias (maps to legion --status for checklist gate 6.9)
|
|
@@ -1569,9 +1593,15 @@ Examples:
|
|
|
1569
1593
|
program
|
|
1570
1594
|
.command('init')
|
|
1571
1595
|
.description('Initialize Vigthoria in current project')
|
|
1572
|
-
.
|
|
1596
|
+
.option('--model <model>', 'Default model (code, code-35b, code-9b, balanced, balanced-4b)')
|
|
1597
|
+
.option('--ignore-patterns <patterns>', 'Comma-separated ignore patterns for this project')
|
|
1598
|
+
.option('--auto-apply-fixes', 'Enable auto-apply fixes for this project profile')
|
|
1599
|
+
.option('--profile <preset>', 'Quick preset: safe, balanced, fast')
|
|
1600
|
+
.option('-y, --yes', 'Overwrite existing .vigthoria.json without prompting')
|
|
1601
|
+
.option('--non-interactive', 'Do not prompt; use provided flags/defaults')
|
|
1602
|
+
.action(async (options) => {
|
|
1573
1603
|
const configCmd = new ConfigCommand(config, logger);
|
|
1574
|
-
await configCmd.init();
|
|
1604
|
+
await configCmd.init(options);
|
|
1575
1605
|
});
|
|
1576
1606
|
const codingCommandDefinitions = [
|
|
1577
1607
|
{ name: 'edit', description: 'Edit code by describing the desired change', instruction: 'Edit the project according to this request' },
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -302,6 +302,8 @@ export declare class APIClient {
|
|
|
302
302
|
private resolveAgentTargetPath;
|
|
303
303
|
private isLikelyWindowsPath;
|
|
304
304
|
private resolveServerBindableWorkspacePath;
|
|
305
|
+
private buildPublicWorkspaceDescriptor;
|
|
306
|
+
private buildPublicRuntimeEnvironment;
|
|
305
307
|
private buildLocalWorkspaceSummary;
|
|
306
308
|
/**
|
|
307
309
|
* Collect text file contents from the workspace for V3 agent hydration.
|
package/dist/utils/api.js
CHANGED
|
@@ -136,6 +136,8 @@ export function sanitizeUserFacingPathText(input) {
|
|
|
136
136
|
.replace(/\bBound server workspace:\s*\S+/gi, 'Bound workspace: workspace/')
|
|
137
137
|
.replace(/\bserver filesystem\b/gi, 'workspace sandbox')
|
|
138
138
|
.replace(/\bon the server\b/gi, 'in the workspace')
|
|
139
|
+
.replace(/Blocked: shell operator '\\|' is not supported; run commands directly without shell piping or redirection/gi, 'Blocked command syntax from remote runner. Re-run locally using a single command, or ask for approval to run an equivalent local command.')
|
|
140
|
+
.replace(/command references a path outside the workspace\. Use paths relative to the workspace root[^.]*\./gi, 'The command path must resolve inside your local project workspace. Use local workspace-relative paths.')
|
|
139
141
|
.replace(/\[(?:\s*)\]/g, '[workspace]')
|
|
140
142
|
.replace(/(^|\s)\.\//g, '$1')
|
|
141
143
|
.replace(/([^:])\/\/+/g, '$1/')
|
|
@@ -579,7 +581,9 @@ export class APIClient {
|
|
|
579
581
|
}
|
|
580
582
|
getV3AgentBaseUrls(preferLocal = false) {
|
|
581
583
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
582
|
-
const allowLocalV3Agent =
|
|
584
|
+
const allowLocalV3Agent = preferLocal
|
|
585
|
+
|| process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1'
|
|
586
|
+
|| !isServerRuntime();
|
|
583
587
|
const urls = [
|
|
584
588
|
process.env.VIGTHORIA_V3_AGENT_URL,
|
|
585
589
|
process.env.V3_AGENT_URL,
|
|
@@ -1261,13 +1265,22 @@ export class APIClient {
|
|
|
1261
1265
|
const localWorkspaceSummary = this.buildLocalWorkspaceSummary(localWorkspacePath);
|
|
1262
1266
|
const requestedModel = String(resolvedContext.model || resolvedContext.requestedModel || 'agent');
|
|
1263
1267
|
const resolvedModel = this.resolvePermittedModelId(requestedModel);
|
|
1268
|
+
const localWorkspaceName = localWorkspacePath ? path.basename(localWorkspacePath) : null;
|
|
1269
|
+
const localWorkspaceRef = localWorkspaceName ? `vigthoria://local-workspace/${localWorkspaceName}` : null;
|
|
1270
|
+
const publicRuntimeEnvironment = this.buildPublicRuntimeEnvironment(resolvedContext.agentRuntime, {
|
|
1271
|
+
localWorkspacePath,
|
|
1272
|
+
serverWorkspacePath,
|
|
1273
|
+
});
|
|
1264
1274
|
// When the server cannot directly access the workspace (e.g. Windows
|
|
1265
1275
|
// client), use the local path as a hint and flag that the workspace
|
|
1266
1276
|
// files are provided inline in localWorkspaceSummary.workspaceFiles.
|
|
1267
1277
|
const effectiveWorkspacePath = serverWorkspacePath || null;
|
|
1268
1278
|
const needsHydration = !serverWorkspacePath && !!localWorkspacePath;
|
|
1269
1279
|
const payload = {
|
|
1270
|
-
workspace: resolvedContext.workspace
|
|
1280
|
+
workspace: this.buildPublicWorkspaceDescriptor(resolvedContext.workspace, {
|
|
1281
|
+
localWorkspacePath,
|
|
1282
|
+
serverWorkspacePath,
|
|
1283
|
+
}),
|
|
1271
1284
|
activeFile: resolvedContext.activeFile || null,
|
|
1272
1285
|
history: resolvedContext.history || [],
|
|
1273
1286
|
agentTaskType: resolvedContext.agentTaskType || 'general',
|
|
@@ -1279,11 +1292,16 @@ export class APIClient {
|
|
|
1279
1292
|
executionSurface: resolvedContext.executionSurface || 'cli',
|
|
1280
1293
|
clientSurface: resolvedContext.clientSurface || 'cli',
|
|
1281
1294
|
localMachineCapable: resolvedContext.localMachineCapable !== false,
|
|
1295
|
+
runtimeEnvironment: publicRuntimeEnvironment,
|
|
1282
1296
|
workspacePath: effectiveWorkspacePath,
|
|
1283
1297
|
projectPath: effectiveWorkspacePath,
|
|
1284
1298
|
targetPath: effectiveWorkspacePath,
|
|
1285
|
-
|
|
1286
|
-
|
|
1299
|
+
// Never send a client-local absolute path to the V3 model boundary.
|
|
1300
|
+
// The server only needs a stable label; file contents are carried by
|
|
1301
|
+
// localWorkspaceSummary.workspaceFiles and hydrated into a temp workspace.
|
|
1302
|
+
localWorkspacePath: serverWorkspacePath ? serverWorkspacePath : localWorkspaceRef,
|
|
1303
|
+
localWorkspaceRef,
|
|
1304
|
+
localWorkspaceName,
|
|
1287
1305
|
localWorkspaceSummary,
|
|
1288
1306
|
// Signal to the server that the workspace filesystem is not locally
|
|
1289
1307
|
// accessible — it must hydrate a temp directory from the provided
|
|
@@ -1391,19 +1409,30 @@ export class APIClient {
|
|
|
1391
1409
|
|| resolvedContext.workspacePath
|
|
1392
1410
|
|| resolvedContext.projectRoot
|
|
1393
1411
|
|| process.cwd();
|
|
1412
|
+
const serverWorkspacePath = this.resolveServerBindableWorkspacePath(resolvedContext);
|
|
1413
|
+
const localWorkspaceName = targetPath ? path.basename(targetPath) : null;
|
|
1414
|
+
const localWorkspaceRef = localWorkspaceName ? `vigthoria://local-workspace/${localWorkspaceName}` : null;
|
|
1394
1415
|
return JSON.stringify({
|
|
1395
|
-
workspace: resolvedContext.workspace
|
|
1416
|
+
workspace: this.buildPublicWorkspaceDescriptor(resolvedContext.workspace, {
|
|
1417
|
+
localWorkspacePath: targetPath,
|
|
1418
|
+
serverWorkspacePath,
|
|
1419
|
+
}),
|
|
1396
1420
|
activeFile: resolvedContext.activeFile || null,
|
|
1397
1421
|
history: resolvedContext.history || [],
|
|
1398
1422
|
agentTaskType: resolvedContext.agentTaskType || 'general',
|
|
1399
1423
|
executionSurface: resolvedContext.executionSurface || 'cli',
|
|
1400
1424
|
clientSurface: resolvedContext.clientSurface || 'cli',
|
|
1401
1425
|
localMachineCapable: resolvedContext.localMachineCapable !== false,
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1426
|
+
runtimeEnvironment: this.buildPublicRuntimeEnvironment(resolvedContext.agentRuntime, {
|
|
1427
|
+
localWorkspacePath: targetPath,
|
|
1428
|
+
serverWorkspacePath,
|
|
1429
|
+
}),
|
|
1430
|
+
workspacePath: serverWorkspacePath || null,
|
|
1431
|
+
projectPath: serverWorkspacePath || null,
|
|
1432
|
+
targetPath: serverWorkspacePath || null,
|
|
1433
|
+
localWorkspacePath: serverWorkspacePath || localWorkspaceRef,
|
|
1434
|
+
localWorkspaceRef,
|
|
1435
|
+
localWorkspaceName,
|
|
1407
1436
|
contextId: resolvedContext.contextId,
|
|
1408
1437
|
traceId: resolvedContext.traceId,
|
|
1409
1438
|
requestStartedAt: resolvedContext.requestStartedAt,
|
|
@@ -1890,6 +1919,7 @@ menu {
|
|
|
1890
1919
|
workspacePath: workspacePath || null,
|
|
1891
1920
|
localWorkspacePath: localWorkspacePath || null,
|
|
1892
1921
|
localWorkspaceSummary,
|
|
1922
|
+
runtimeEnvironment: executionContext.agentRuntime || null,
|
|
1893
1923
|
requestStartedAt: executionContext.requestStartedAt,
|
|
1894
1924
|
subscriptionPlan: this.config.getNormalizedPlan() || null,
|
|
1895
1925
|
email: this.config.get('email') || null,
|
|
@@ -1903,6 +1933,7 @@ menu {
|
|
|
1903
1933
|
targetPath: workspacePath || null,
|
|
1904
1934
|
localWorkspacePath: localWorkspacePath || null,
|
|
1905
1935
|
localWorkspaceSummary,
|
|
1936
|
+
runtimeEnvironment: executionContext.agentRuntime || null,
|
|
1906
1937
|
activeFile: executionContext.activeFile || null,
|
|
1907
1938
|
executionSurface: executionContext.executionSurface || 'cli',
|
|
1908
1939
|
clientSurface: executionContext.clientSurface || 'cli',
|
|
@@ -1971,7 +2002,7 @@ menu {
|
|
|
1971
2002
|
}
|
|
1972
2003
|
resolveServerBindableWorkspacePath(context = {}) {
|
|
1973
2004
|
const candidate = this.resolveAgentTargetPath(context);
|
|
1974
|
-
if (!candidate ||
|
|
2005
|
+
if (!candidate || !path.isAbsolute(candidate) || !fs.existsSync(candidate)) {
|
|
1975
2006
|
return '';
|
|
1976
2007
|
}
|
|
1977
2008
|
const configuredRoots = (process.env.VIGTHORIA_SERVER_WORKSPACE_ROOTS || '/var/www/vigthoria-user-workspaces,/var/lib/vigthoria-workspaces')
|
|
@@ -1995,13 +2026,49 @@ menu {
|
|
|
1995
2026
|
}
|
|
1996
2027
|
return '';
|
|
1997
2028
|
}
|
|
2029
|
+
buildPublicWorkspaceDescriptor(workspace, paths = {}) {
|
|
2030
|
+
const localName = paths.localWorkspacePath ? path.basename(paths.localWorkspacePath) : null;
|
|
2031
|
+
const isServerBindable = !!paths.serverWorkspacePath;
|
|
2032
|
+
const descriptor = {
|
|
2033
|
+
name: localName,
|
|
2034
|
+
path: isServerBindable ? paths.serverWorkspacePath : (localName ? `vigthoria://local-workspace/${localName}` : null),
|
|
2035
|
+
scheme: isServerBindable ? 'server-bindable' : 'local-workspace',
|
|
2036
|
+
};
|
|
2037
|
+
if (workspace && typeof workspace === 'object') {
|
|
2038
|
+
for (const [key, value] of Object.entries(workspace)) {
|
|
2039
|
+
if (key === 'path' || key === 'workspacePath' || key === 'projectPath' || key === 'targetPath' || key === 'cwd') {
|
|
2040
|
+
continue;
|
|
2041
|
+
}
|
|
2042
|
+
descriptor[key] = value;
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
return descriptor.name || descriptor.path ? descriptor : null;
|
|
2046
|
+
}
|
|
2047
|
+
buildPublicRuntimeEnvironment(runtime, paths = {}) {
|
|
2048
|
+
if (!runtime || typeof runtime !== 'object') {
|
|
2049
|
+
return null;
|
|
2050
|
+
}
|
|
2051
|
+
const localName = paths.localWorkspacePath ? path.basename(paths.localWorkspacePath) : null;
|
|
2052
|
+
const serverBindableWorkspace = !!paths.serverWorkspacePath || runtime.serverBindableWorkspace === true;
|
|
2053
|
+
return {
|
|
2054
|
+
osPlatform: runtime.osPlatform || null,
|
|
2055
|
+
platform: runtime.platform || null,
|
|
2056
|
+
nodeVersion: runtime.nodeVersion || null,
|
|
2057
|
+
directPromptMode: runtime.directPromptMode === true,
|
|
2058
|
+
serverBindableWorkspace,
|
|
2059
|
+
machineScope: serverBindableWorkspace ? 'server-workspace' : 'local-machine',
|
|
2060
|
+
workspaceName: localName,
|
|
2061
|
+
workspacePath: serverBindableWorkspace ? paths.serverWorkspacePath || null : (localName ? `vigthoria://local-workspace/${localName}` : null),
|
|
2062
|
+
cwd: serverBindableWorkspace ? paths.serverWorkspacePath || null : (localName ? `vigthoria://local-workspace/${localName}` : null),
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
1998
2065
|
buildLocalWorkspaceSummary(rootPath) {
|
|
1999
2066
|
if (!rootPath || !fs.existsSync(rootPath)) {
|
|
2000
2067
|
return null;
|
|
2001
2068
|
}
|
|
2002
2069
|
try {
|
|
2003
2070
|
const summary = {
|
|
2004
|
-
path:
|
|
2071
|
+
path: 'vigthoria://workspace/',
|
|
2005
2072
|
name: path.basename(rootPath),
|
|
2006
2073
|
files: [],
|
|
2007
2074
|
};
|
package/dist/utils/tools.js
CHANGED
|
@@ -835,8 +835,19 @@ export class AgenticTools {
|
|
|
835
835
|
}
|
|
836
836
|
// Check permission for dangerous/modifying actions
|
|
837
837
|
if (tool.requiresPermission && !this.autoApprove) {
|
|
838
|
-
|
|
839
|
-
if (
|
|
838
|
+
const requiresPerCommandApproval = normalizedCall.tool === 'bash';
|
|
839
|
+
if (requiresPerCommandApproval) {
|
|
840
|
+
const approved = await this.permissionCallback(this.formatPermissionRequest(normalizedCall, tool), { batchApproval: false });
|
|
841
|
+
if (approved === false) {
|
|
842
|
+
return {
|
|
843
|
+
success: false,
|
|
844
|
+
error: 'Permission denied by user',
|
|
845
|
+
canRetry: true,
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
else if (this.hasPersistentPermission(normalizedCall.tool)) {
|
|
850
|
+
// Check persistent permissions first (project-scoped), then session
|
|
840
851
|
this.logger.info(`${call.tool}: Auto-approved (persistent)`);
|
|
841
852
|
}
|
|
842
853
|
else if (this.sessionApprovedTools.has(normalizedCall.tool)) {
|
|
@@ -1542,18 +1553,7 @@ export class AgenticTools {
|
|
|
1542
1553
|
for (const part of cmdParts) {
|
|
1543
1554
|
const firstWord = part.trim().split(/\s+/)[0].toLowerCase();
|
|
1544
1555
|
if (unixOnlyCommands.includes(firstWord)) {
|
|
1545
|
-
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Command '${firstWord}' is not available on Windows`, `Use
|
|
1546
|
-
`or use 'fetch_url' for web requests. ` +
|
|
1547
|
-
`PowerShell alternatives: dir (ls), type (cat), findstr (grep), select-string (grep)`);
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
// Check for pipe to Unix command
|
|
1551
|
-
if (args.command.includes('|')) {
|
|
1552
|
-
const pipedCommands = args.command.split('|').map(c => c.trim().split(/\s+/)[0].toLowerCase());
|
|
1553
|
-
for (const cmd of pipedCommands) {
|
|
1554
|
-
if (unixOnlyCommands.includes(cmd)) {
|
|
1555
|
-
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Piped command '${cmd}' is not available on Windows`, `Windows doesn't have '${cmd}'. Use 'ssh_exec' tool to run this command on the Vigthoria server instead.`);
|
|
1556
|
-
}
|
|
1556
|
+
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Command '${firstWord}' is not available on Windows`, `Use a local PowerShell equivalent instead: dir (ls), type (cat), findstr (grep), select-string (grep), or rerun with a Windows-safe command.`);
|
|
1557
1557
|
}
|
|
1558
1558
|
}
|
|
1559
1559
|
}
|
package/install.ps1
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
$ErrorActionPreference = "Stop"
|
|
6
6
|
|
|
7
7
|
# Configuration
|
|
8
|
-
$CLI_VERSION = "1.9.
|
|
8
|
+
$CLI_VERSION = "1.9.22"
|
|
9
9
|
$INSTALL_DIR = "$env:USERPROFILE\.vigthoria"
|
|
10
10
|
$NPM_PACKAGE = "vigthoria-cli"
|
|
11
11
|
$GIT_PACKAGE_URL = "git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
|
package/install.sh
CHANGED
|
@@ -26,7 +26,7 @@ else
|
|
|
26
26
|
fi
|
|
27
27
|
|
|
28
28
|
# Configuration
|
|
29
|
-
CLI_VERSION="1.9.
|
|
29
|
+
CLI_VERSION="1.9.22"
|
|
30
30
|
INSTALL_DIR="$HOME/.vigthoria"
|
|
31
31
|
REPO_URL="https://market.vigthoria.io/vigthoria/vigthoria-cli"
|
|
32
32
|
GIT_PACKAGE_URL="git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
|