vigthoria-cli 1.13.18 → 1.13.22
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/completions/_vigthoria +49 -0
- package/completions/vigthoria.bash +6 -0
- package/completions/vigthoria.fish +41 -0
- package/dist/commands/auth.d.ts +1 -0
- package/dist/commands/auth.js +84 -135
- package/dist/commands/background.d.ts +0 -2
- package/dist/commands/background.js +26 -34
- package/dist/commands/bridge.js +45 -41
- package/dist/commands/cancel.d.ts +1 -0
- package/dist/commands/cancel.js +22 -16
- package/dist/commands/chat.d.ts +5 -42
- package/dist/commands/chat.js +462 -1122
- package/dist/commands/coding-registration.d.ts +4 -0
- package/dist/commands/coding-registration.js +24 -0
- package/dist/commands/config.js +32 -42
- package/dist/commands/conversation-registration.d.ts +4 -0
- package/dist/commands/conversation-registration.js +122 -0
- package/dist/commands/deploy.d.ts +8 -2
- package/dist/commands/deploy.js +92 -90
- package/dist/commands/device.d.ts +1 -2
- package/dist/commands/device.js +37 -21
- package/dist/commands/doctor-registration.d.ts +4 -0
- package/dist/commands/doctor-registration.js +200 -0
- package/dist/commands/edit.js +22 -33
- package/dist/commands/explain.js +7 -10
- package/dist/commands/fork.d.ts +1 -2
- package/dist/commands/fork.js +72 -22
- package/dist/commands/game.d.ts +1 -1
- package/dist/commands/game.js +17 -6
- package/dist/commands/generate.js +7 -9
- package/dist/commands/history.js +11 -7
- package/dist/commands/hub.d.ts +2 -2
- package/dist/commands/hub.js +34 -35
- package/dist/commands/legion.d.ts +0 -1
- package/dist/commands/legion.js +62 -79
- package/dist/commands/music.d.ts +1 -2
- package/dist/commands/music.js +62 -27
- package/dist/commands/platform-registration.d.ts +4 -0
- package/dist/commands/platform-registration.js +45 -0
- package/dist/commands/preview.d.ts +0 -1
- package/dist/commands/preview.js +82 -35
- package/dist/commands/product-run-registration.d.ts +4 -0
- package/dist/commands/product-run-registration.js +490 -0
- package/dist/commands/replay.d.ts +1 -2
- package/dist/commands/replay.js +15 -11
- package/dist/commands/repo.d.ts +14 -7
- package/dist/commands/repo.js +245 -196
- package/dist/commands/review.js +9 -12
- package/dist/commands/security.d.ts +1 -2
- package/dist/commands/security.js +12 -6
- package/dist/commands/update-registration.d.ts +3 -0
- package/dist/commands/update-registration.js +338 -0
- package/dist/commands/v4-registration.d.ts +4 -0
- package/dist/commands/v4-registration.js +24 -0
- package/dist/commands/v4.d.ts +1 -1
- package/dist/commands/v4.js +46 -8
- package/dist/commands/wallet.d.ts +1 -3
- package/dist/commands/wallet.js +18 -45
- package/dist/commands/workflow.d.ts +2 -0
- package/dist/commands/workflow.js +52 -39
- package/dist/index.js +122 -1498
- package/dist/utils/agent-stream-state.d.ts +27 -0
- package/dist/utils/agent-stream-state.js +93 -0
- package/dist/utils/agentRoute.d.ts +2 -1
- package/dist/utils/agentRoute.js +22 -9
- package/dist/utils/agentRunOutcome.d.ts +16 -0
- package/dist/utils/agentRunOutcome.js +37 -2
- package/dist/utils/api-client-factory.d.ts +8 -0
- package/dist/utils/api-client-factory.js +8 -0
- package/dist/utils/api.d.ts +45 -269
- package/dist/utils/api.js +664 -3210
- package/dist/utils/auth-session.d.ts +41 -0
- package/dist/utils/auth-session.js +224 -0
- package/dist/utils/brain-hub-client.d.ts +0 -4
- package/dist/utils/brain-hub-client.js +6 -3
- package/dist/utils/bridge-client.js +2 -0
- package/dist/utils/capability-health-service.d.ts +48 -0
- package/dist/utils/capability-health-service.js +64 -0
- package/dist/utils/chat-prompt-policy.d.ts +18 -0
- package/dist/utils/chat-prompt-policy.js +61 -0
- package/dist/utils/chat-tool-call-parser.d.ts +11 -0
- package/dist/utils/chat-tool-call-parser.js +71 -0
- package/dist/utils/cli-state.d.ts +22 -4
- package/dist/utils/cli-state.js +105 -47
- package/dist/utils/code-operations-service.d.ts +104 -0
- package/dist/utils/code-operations-service.js +837 -0
- package/dist/utils/codebase-indexer.d.ts +1 -0
- package/dist/utils/codebase-indexer.js +28 -8
- package/dist/utils/command-contract.d.ts +61 -0
- package/dist/utils/command-contract.js +149 -0
- package/dist/utils/command-policy.d.ts +10 -0
- package/dist/utils/command-policy.js +54 -0
- package/dist/utils/config.d.ts +13 -5
- package/dist/utils/config.js +227 -99
- package/dist/utils/context-ranker.js +11 -2
- package/dist/utils/context-state.d.ts +39 -0
- package/dist/utils/context-state.js +52 -0
- package/dist/utils/deckEvents.d.ts +0 -5
- package/dist/utils/deckEvents.js +3 -2
- package/dist/utils/desktop-bridge-client.js +2 -0
- package/dist/utils/direct-output-policy.d.ts +3 -0
- package/dist/utils/direct-output-policy.js +76 -0
- package/dist/utils/durable-json.d.ts +57 -0
- package/dist/utils/durable-json.js +319 -0
- package/dist/utils/fastAgentRouter.d.ts +6 -7
- package/dist/utils/fastAgentRouter.js +21 -30
- package/dist/utils/files.js +21 -13
- package/dist/utils/frontend-preview-service.d.ts +76 -0
- package/dist/utils/frontend-preview-service.js +482 -0
- package/dist/utils/goaEvents.d.ts +0 -4
- package/dist/utils/goaEvents.js +5 -2
- package/dist/utils/logger.d.ts +2 -1
- package/dist/utils/logger.js +27 -20
- package/dist/utils/mcp-context-client.d.ts +24 -0
- package/dist/utils/mcp-context-client.js +58 -0
- package/dist/utils/model-governance.d.ts +18 -0
- package/dist/utils/model-governance.js +75 -0
- package/dist/utils/model-transport-service.d.ts +44 -0
- package/dist/utils/model-transport-service.js +111 -0
- package/dist/utils/mutation-journal.d.ts +42 -0
- package/dist/utils/mutation-journal.js +387 -0
- package/dist/utils/network-policy.d.ts +24 -0
- package/dist/utils/network-policy.js +202 -0
- package/dist/utils/operator-client.d.ts +45 -0
- package/dist/utils/operator-client.js +159 -0
- package/dist/utils/post-write-validator.js +7 -9
- package/dist/utils/preview-screenshot-adapter.d.ts +13 -0
- package/dist/utils/preview-screenshot-adapter.js +36 -0
- package/dist/utils/process-policy.d.ts +23 -0
- package/dist/utils/process-policy.js +284 -0
- package/dist/utils/project-memory.d.ts +13 -3
- package/dist/utils/project-memory.js +70 -17
- package/dist/utils/prompt-workspace-resolver.d.ts +14 -0
- package/dist/utils/prompt-workspace-resolver.js +64 -0
- package/dist/utils/release-install.d.ts +11 -0
- package/dist/utils/release-install.js +155 -0
- package/dist/utils/release-policy.d.ts +64 -0
- package/dist/utils/release-policy.js +293 -0
- package/dist/utils/requestIntent.js +22 -3
- package/dist/utils/runtime-capability.d.ts +8 -0
- package/dist/utils/runtime-capability.js +16 -0
- package/dist/utils/secret-policy.d.ts +20 -0
- package/dist/utils/secret-policy.js +160 -0
- package/dist/utils/session.d.ts +34 -2
- package/dist/utils/session.js +354 -110
- package/dist/utils/tool-approval-service.d.ts +17 -0
- package/dist/utils/tool-approval-service.js +78 -0
- package/dist/utils/tool-capability-providers.d.ts +57 -0
- package/dist/utils/tool-capability-providers.js +57 -0
- package/dist/utils/tools.d.ts +2 -23
- package/dist/utils/tools.js +216 -508
- package/dist/utils/update-policy.d.ts +18 -0
- package/dist/utils/update-policy.js +137 -0
- package/dist/utils/v3-agent-client.d.ts +40 -0
- package/dist/utils/v3-agent-client.js +165 -0
- package/dist/utils/v3-workspace-service.d.ts +28 -0
- package/dist/utils/v3-workspace-service.js +279 -0
- package/dist/utils/vigflow-client.d.ts +95 -0
- package/dist/utils/vigflow-client.js +105 -0
- package/dist/utils/workspace-boundary.d.ts +45 -0
- package/dist/utils/workspace-boundary.js +377 -0
- package/dist/utils/workspace-brain-service.d.ts +2 -0
- package/dist/utils/workspace-brain-service.js +11 -1
- package/dist/utils/workspace-cache.js +37 -15
- package/dist/utils/workspace-stream.js +35 -10
- package/install.ps1 +86 -143
- package/install.sh +76 -81
- package/package.json +44 -9
- package/release-policy.json +43 -0
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
- package/scripts/release/generate-completions.mjs +24 -0
- package/scripts/release/install-release.mjs +10 -0
- package/scripts/release/publish-cli-release.mjs +116 -0
- package/scripts/release/publish-cli-release.sh +2 -70
- package/scripts/release/resolve-release-manifest.mjs +26 -0
- package/scripts/release/test-balanced-model-live.sh +42 -0
- package/scripts/release/validate-live-service-gates.sh +90 -0
- package/scripts/release/validate-no-go-gates.sh +135 -172
- package/scripts/release/verify-runtime-consistency.mjs +4 -1
- package/dist/commands/index.d.ts +0 -12
- package/dist/commands/index.js +0 -194
- package/dist/commands/update.d.ts +0 -9
- package/dist/commands/update.js +0 -301
- package/dist/utils/templateInstantPath.d.ts +0 -18
- package/dist/utils/templateInstantPath.js +0 -228
package/dist/utils/logger.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
+
import { redactSensitiveText, redactSensitiveValue } from './secret-policy.js';
|
|
6
7
|
/**
|
|
7
8
|
* Platform-aware character map.
|
|
8
9
|
*
|
|
@@ -68,56 +69,60 @@ export function createSpinner(textOrOpts) {
|
|
|
68
69
|
}
|
|
69
70
|
export class Logger {
|
|
70
71
|
verbose = false;
|
|
72
|
+
safeArgs(args) {
|
|
73
|
+
return args.map((value) => redactSensitiveValue(value));
|
|
74
|
+
}
|
|
71
75
|
setVerbose(verbose) {
|
|
72
76
|
this.verbose = verbose;
|
|
73
77
|
}
|
|
74
78
|
debug(...args) {
|
|
75
79
|
if (this.verbose) {
|
|
76
|
-
console.log(chalk.gray('[DEBUG]'), ...args);
|
|
80
|
+
console.log(chalk.gray('[DEBUG]'), ...this.safeArgs(args));
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
info(...args) {
|
|
80
|
-
console.log(chalk.blue(CH.info), ...args);
|
|
84
|
+
console.log(chalk.blue(CH.info), ...this.safeArgs(args));
|
|
81
85
|
}
|
|
82
86
|
warn(...args) {
|
|
83
|
-
console.log(chalk.yellow(CH.warn), ...args);
|
|
87
|
+
console.log(chalk.yellow(CH.warn), ...this.safeArgs(args));
|
|
84
88
|
}
|
|
85
89
|
error(...args) {
|
|
86
90
|
// Write error messages to stdout (not stderr) to avoid triggering
|
|
87
91
|
// PowerShell NativeCommandError styling. The red ✗ prefix already
|
|
88
92
|
// signals an error visually; stderr redirection is unnecessary.
|
|
89
|
-
console.log(chalk.red(CH.error), ...args);
|
|
93
|
+
console.log(chalk.red(CH.error), ...this.safeArgs(args));
|
|
90
94
|
}
|
|
91
95
|
success(...args) {
|
|
92
|
-
console.log(chalk.green(CH.success), ...args);
|
|
96
|
+
console.log(chalk.green(CH.success), ...this.safeArgs(args));
|
|
93
97
|
}
|
|
94
98
|
// AI response formatting
|
|
95
99
|
ai(message) {
|
|
96
|
-
console.log(chalk.cyan(CH.ai), message);
|
|
100
|
+
console.log(chalk.cyan(CH.ai), redactSensitiveText(message));
|
|
97
101
|
}
|
|
98
102
|
// User input formatting
|
|
99
103
|
user(message) {
|
|
100
|
-
console.log(chalk.white(CH.user), message);
|
|
104
|
+
console.log(chalk.white(CH.user), redactSensitiveText(message));
|
|
101
105
|
}
|
|
102
106
|
// Code block
|
|
103
|
-
code(code,
|
|
107
|
+
code(code, _language) {
|
|
104
108
|
console.log(chalk.gray(CH.hLine.repeat(60)));
|
|
105
|
-
console.log(chalk.yellow(code));
|
|
109
|
+
console.log(chalk.yellow(redactSensitiveText(code)));
|
|
106
110
|
console.log(chalk.gray(CH.hLine.repeat(60)));
|
|
107
111
|
}
|
|
108
112
|
// Diff output - enhanced with syntax-highlighted unified diff
|
|
109
113
|
diff(added, removed) {
|
|
110
|
-
removed.forEach(line => console.log(chalk.red(`- ${line}`)));
|
|
111
|
-
added.forEach(line => console.log(chalk.green(`+ ${line}`)));
|
|
114
|
+
removed.forEach(line => console.log(chalk.red(`- ${redactSensitiveText(line)}`)));
|
|
115
|
+
added.forEach(line => console.log(chalk.green(`+ ${redactSensitiveText(line)}`)));
|
|
112
116
|
}
|
|
113
117
|
// Unified diff display with file context
|
|
114
118
|
unifiedDiff(filePath, oldText, newText) {
|
|
115
|
-
const oldLines = oldText.split('\n');
|
|
116
|
-
const newLines = newText.split('\n');
|
|
117
|
-
const
|
|
119
|
+
const oldLines = redactSensitiveText(oldText).split('\n');
|
|
120
|
+
const newLines = redactSensitiveText(newText).split('\n');
|
|
121
|
+
const safeFilePath = redactSensitiveText(filePath);
|
|
122
|
+
const fileName = safeFilePath.split('/').pop() || safeFilePath;
|
|
118
123
|
console.log(chalk.bold.white(`\n ${CH.hLine.repeat(3)} ${fileName} ${CH.hLine.repeat(Math.max(1, 50 - fileName.length))}`));
|
|
119
|
-
console.log(chalk.gray(` --- a/${
|
|
120
|
-
console.log(chalk.gray(` +++ b/${
|
|
124
|
+
console.log(chalk.gray(` --- a/${safeFilePath}`));
|
|
125
|
+
console.log(chalk.gray(` +++ b/${safeFilePath}`));
|
|
121
126
|
// Find diff ranges with context
|
|
122
127
|
const contextLines = 3;
|
|
123
128
|
let i = 0;
|
|
@@ -130,7 +135,6 @@ export class Logger {
|
|
|
130
135
|
}
|
|
131
136
|
// Found a difference - show context
|
|
132
137
|
const startOld = Math.max(0, i - contextLines);
|
|
133
|
-
const startNew = Math.max(0, j - contextLines);
|
|
134
138
|
// Context before
|
|
135
139
|
for (let c = startOld; c < i; c++) {
|
|
136
140
|
console.log(chalk.gray(` ${String(c + 1).padStart(4)} │ ${oldLines[c] || ''}`));
|
|
@@ -168,7 +172,7 @@ export class Logger {
|
|
|
168
172
|
// conservative width so the separator line never overflows even when
|
|
169
173
|
// the reported column count is larger than the real usable width.
|
|
170
174
|
const width = Math.max(24, Number(process.stdout.columns || 80));
|
|
171
|
-
const cleanTitle = String(title || '').replace(/\s+/g, ' ').trim();
|
|
175
|
+
const cleanTitle = redactSensitiveText(String(title || '')).replace(/\s+/g, ' ').trim();
|
|
172
176
|
const maxTitle = Math.max(10, width - 10);
|
|
173
177
|
const fittedTitle = cleanTitle.length > maxTitle ? `${cleanTitle.slice(0, maxTitle - 1)}…` : cleanTitle;
|
|
174
178
|
const side = Math.max(3, Math.floor((Math.min(width, 44) - fittedTitle.length - 2) / 2));
|
|
@@ -178,7 +182,7 @@ export class Logger {
|
|
|
178
182
|
}
|
|
179
183
|
// Progress
|
|
180
184
|
progress(message) {
|
|
181
|
-
process.stdout.write(chalk.gray(`${message}\r`));
|
|
185
|
+
process.stdout.write(chalk.gray(`${redactSensitiveText(message)}\r`));
|
|
182
186
|
}
|
|
183
187
|
// Clear line
|
|
184
188
|
clearLine() {
|
|
@@ -186,7 +190,8 @@ export class Logger {
|
|
|
186
190
|
}
|
|
187
191
|
// Box output
|
|
188
192
|
box(content, title) {
|
|
189
|
-
const lines = content.split('\n');
|
|
193
|
+
const lines = redactSensitiveText(content).split('\n');
|
|
194
|
+
title = title ? redactSensitiveText(title) : title;
|
|
190
195
|
// Strip ANSI codes when calculating length for proper alignment
|
|
191
196
|
const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
192
197
|
const maxLen = Math.max(...lines.map(l => stripAnsi(l).length), title?.length || 0);
|
|
@@ -206,6 +211,8 @@ export class Logger {
|
|
|
206
211
|
}
|
|
207
212
|
// Table output
|
|
208
213
|
table(headers, rows) {
|
|
214
|
+
headers = headers.map((entry) => redactSensitiveText(entry));
|
|
215
|
+
rows = rows.map((row) => row.map((entry) => redactSensitiveText(entry)));
|
|
209
216
|
const colWidths = headers.map((h, i) => {
|
|
210
217
|
const maxData = Math.max(...rows.map(r => (r[i] || '').length));
|
|
211
218
|
return Math.max(h.length, maxData);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface McpContextBinding {
|
|
2
|
+
mcpContextId: string;
|
|
3
|
+
backendUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export interface McpContextBindInput {
|
|
6
|
+
existing?: McpContextBinding | null;
|
|
7
|
+
userId: string;
|
|
8
|
+
metadata: Record<string, unknown>;
|
|
9
|
+
data: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
export interface McpContextClientDependencies {
|
|
12
|
+
getBaseUrls(): string[];
|
|
13
|
+
getAccessToken(): string | null;
|
|
14
|
+
fetch(input: string, init: RequestInit): Promise<Response>;
|
|
15
|
+
sanitizeError(text: string): string;
|
|
16
|
+
debug(message: string, detail?: unknown): void;
|
|
17
|
+
}
|
|
18
|
+
export declare class McpContextClient {
|
|
19
|
+
private readonly dependencies;
|
|
20
|
+
constructor(dependencies: McpContextClientDependencies);
|
|
21
|
+
private headers;
|
|
22
|
+
private update;
|
|
23
|
+
bind(input: McpContextBindInput): Promise<McpContextBinding | null>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { scanOutboundContext } from './secret-policy.js';
|
|
2
|
+
export class McpContextClient {
|
|
3
|
+
dependencies;
|
|
4
|
+
constructor(dependencies) {
|
|
5
|
+
this.dependencies = dependencies;
|
|
6
|
+
}
|
|
7
|
+
headers() {
|
|
8
|
+
const headers = { 'Content-Type': 'application/json', Accept: 'application/json' };
|
|
9
|
+
const token = this.dependencies.getAccessToken();
|
|
10
|
+
if (token) {
|
|
11
|
+
headers.Authorization = `Bearer ${token}`;
|
|
12
|
+
headers.Cookie = `vigthoria-auth-token=${token}`;
|
|
13
|
+
headers['X-Vigthoria-Token'] = token;
|
|
14
|
+
headers['X-Auth-Token'] = token;
|
|
15
|
+
}
|
|
16
|
+
return headers;
|
|
17
|
+
}
|
|
18
|
+
async update(binding, data) {
|
|
19
|
+
const response = await this.dependencies.fetch(`${binding.backendUrl}/mcp/context/${encodeURIComponent(binding.mcpContextId)}`, { method: 'PUT', headers: this.headers(), body: JSON.stringify(scanOutboundContext({ data }).value) });
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const detail = await response.text().catch(() => '');
|
|
22
|
+
throw new Error(`MCP context update ${response.status}: ${this.dependencies.sanitizeError(detail).slice(0, 200)}`);
|
|
23
|
+
}
|
|
24
|
+
return binding;
|
|
25
|
+
}
|
|
26
|
+
async bind(input) {
|
|
27
|
+
if (input.existing) {
|
|
28
|
+
try {
|
|
29
|
+
return await this.update(input.existing, input.data);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
this.dependencies.debug('Failed to refresh existing MCP context binding', error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const baseUrl of this.dependencies.getBaseUrls()) {
|
|
36
|
+
try {
|
|
37
|
+
const response = await this.dependencies.fetch(`${baseUrl}/mcp/context/create`, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: this.headers(),
|
|
40
|
+
body: JSON.stringify(scanOutboundContext({ userId: input.userId, metadata: input.metadata }).value),
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const detail = await response.text().catch(() => '');
|
|
44
|
+
throw new Error(`MCP context create ${response.status}: ${this.dependencies.sanitizeError(detail).slice(0, 200)}`);
|
|
45
|
+
}
|
|
46
|
+
const payload = await response.json();
|
|
47
|
+
const mcpContextId = String(payload.contextId || '').trim();
|
|
48
|
+
if (!mcpContextId)
|
|
49
|
+
throw new Error('MCP context create response did not include a contextId');
|
|
50
|
+
return await this.update({ mcpContextId, backendUrl: baseUrl }, input.data);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.dependencies.debug(`Failed to bind MCP context via ${baseUrl}`, error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ModelGovernanceDependencies {
|
|
2
|
+
hasCloudAccess(): boolean;
|
|
3
|
+
hasSelfHostedEndpoint(): boolean;
|
|
4
|
+
simulateCloudFailure(): boolean;
|
|
5
|
+
debug(message: string): void;
|
|
6
|
+
}
|
|
7
|
+
export declare class ModelGovernance {
|
|
8
|
+
private readonly dependencies;
|
|
9
|
+
constructor(dependencies: ModelGovernanceDependencies);
|
|
10
|
+
resolveModelId(shortName: string): string;
|
|
11
|
+
isCloudModelId(modelId: string): boolean;
|
|
12
|
+
resolvePermittedModelId(shortName: string): string;
|
|
13
|
+
shouldSkipCloudRoutes(modelId: string): boolean;
|
|
14
|
+
getFallbackModelId(modelId: string): string | null;
|
|
15
|
+
isSelfHostedPreferredModel(modelId: string, requestedModel: string): boolean;
|
|
16
|
+
shouldTrySelfHostedFallback(modelId: string, requestedModel: string): boolean;
|
|
17
|
+
getSelfHostedFallbackModelId(modelId: string, requestedModel: string): string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const MODEL_ALIASES = {
|
|
2
|
+
fast: 'Vigthoria-v4-Assistant-9B', mini: 'vigthoria-mini-0.6b', balanced: 'Vigthoria-v4-Assistant-9B',
|
|
3
|
+
'balanced-4b': 'Vigthoria-v4-Assistant-9B', assistant: 'Vigthoria-v4-Assistant-9B', creative: 'Vigthoria-v4-Creative-27B',
|
|
4
|
+
architect: 'Vigthoria-v4-Creative-27B', code: 'Vigthoria-v4-Code-27B', 'code-30b': 'Vigthoria-v4-Code-27B',
|
|
5
|
+
'code-35b': 'Vigthoria-v4-Code-27B', 'code-8b': 'Vigthoria-v4-Assistant-9B', 'code-9b': 'Vigthoria-v4-Assistant-9B',
|
|
6
|
+
pro: 'Vigthoria-v4-Code-27B', agent: 'Vigthoria-v4-Code-27B', 'vigthoria-code': 'Vigthoria-v4-Code-27B',
|
|
7
|
+
'vigthoria-agent': 'Vigthoria-v4-Code-27B', cloud: 'vigthoria-cloud-balanced', 'cloud-code': 'vigthoria-cloud-code',
|
|
8
|
+
'cloud-balanced': 'vigthoria-cloud-balanced', 'cloud-fast': 'vigthoria-cloud-fast', 'cloud-power': 'vigthoria-cloud-power',
|
|
9
|
+
'cloud-maximum': 'vigthoria-cloud-maximum', 'cloud-reason': 'vigthoria-cloud-power', ultra: 'vigthoria-cloud-maximum',
|
|
10
|
+
'cloud-pro': 'vigthoria-cloud-power', 'cloud-k2': 'vigthoria-cloud-power', 'cloud-ultra': 'vigthoria-cloud-maximum',
|
|
11
|
+
};
|
|
12
|
+
const RETIRED_MODELS = new Set(['mini', 'creative-v3', 'creative-v4']);
|
|
13
|
+
const LEGACY_CLOUD_IDS = new Set(['deepseek-v3.1:671b-cloud', 'moonshotai/kimi-k2.5']);
|
|
14
|
+
const SELF_HOSTED_MODELS = new Set([
|
|
15
|
+
'Vigthoria-v4-Creative-27B', 'Vigthoria-v4-Code-27B', 'Vigthoria-v4-Assistant-9B',
|
|
16
|
+
'vigthoria-v3-code-35b', 'vigthoria-v3-code-35b:latest', 'vigthoria-v3-code-9b',
|
|
17
|
+
'vigthoria-v3-code-9b:latest', 'vigthoria-v3-balanced-4b', 'vigthoria-v3-balanced-4b:latest', 'qwen3-coder:latest',
|
|
18
|
+
]);
|
|
19
|
+
const SELF_HOSTED_ALIASES = new Set([
|
|
20
|
+
'agent', 'architect', 'assistant', 'code', 'code-30b', 'code-35b', 'code-9b', 'balanced', 'balanced-4b', 'pro',
|
|
21
|
+
]);
|
|
22
|
+
export class ModelGovernance {
|
|
23
|
+
dependencies;
|
|
24
|
+
constructor(dependencies) {
|
|
25
|
+
this.dependencies = dependencies;
|
|
26
|
+
}
|
|
27
|
+
resolveModelId(shortName) {
|
|
28
|
+
const requested = String(shortName || '');
|
|
29
|
+
const normalized = requested.toLowerCase();
|
|
30
|
+
if (normalized.includes('vigthoria') || requested.includes('/') || requested.includes(':')) {
|
|
31
|
+
return MODEL_ALIASES[normalized] || requested;
|
|
32
|
+
}
|
|
33
|
+
return MODEL_ALIASES[normalized] || 'Vigthoria-v4-Code-27B';
|
|
34
|
+
}
|
|
35
|
+
isCloudModelId(modelId) {
|
|
36
|
+
const normalized = String(modelId || '').toLowerCase();
|
|
37
|
+
return normalized.startsWith('vigthoria-cloud-') || LEGACY_CLOUD_IDS.has(normalized);
|
|
38
|
+
}
|
|
39
|
+
resolvePermittedModelId(shortName) {
|
|
40
|
+
const normalized = String(shortName || '').trim().toLowerCase();
|
|
41
|
+
if (RETIRED_MODELS.has(normalized)) {
|
|
42
|
+
this.dependencies.debug(`Blocked retired model ${shortName}; using fallback Vigthoria-v4-Code-27B`);
|
|
43
|
+
return 'Vigthoria-v4-Code-27B';
|
|
44
|
+
}
|
|
45
|
+
const resolved = this.resolveModelId(shortName);
|
|
46
|
+
if (this.isCloudModelId(resolved) && !this.dependencies.hasCloudAccess()) {
|
|
47
|
+
const fallback = this.getSelfHostedFallbackModelId(resolved, shortName);
|
|
48
|
+
this.dependencies.debug(`Blocked unauthorized cloud model ${shortName}; using fallback ${fallback}`);
|
|
49
|
+
return fallback;
|
|
50
|
+
}
|
|
51
|
+
return resolved;
|
|
52
|
+
}
|
|
53
|
+
shouldSkipCloudRoutes(modelId) {
|
|
54
|
+
return this.dependencies.simulateCloudFailure() && this.isCloudModelId(modelId);
|
|
55
|
+
}
|
|
56
|
+
getFallbackModelId(modelId) {
|
|
57
|
+
return this.isCloudModelId(modelId) ? 'Vigthoria-v4-Code-27B' : null;
|
|
58
|
+
}
|
|
59
|
+
isSelfHostedPreferredModel(modelId, requestedModel) {
|
|
60
|
+
return SELF_HOSTED_MODELS.has(modelId) || SELF_HOSTED_ALIASES.has(String(requestedModel || '').toLowerCase());
|
|
61
|
+
}
|
|
62
|
+
shouldTrySelfHostedFallback(modelId, requestedModel) {
|
|
63
|
+
if (!this.dependencies.hasSelfHostedEndpoint())
|
|
64
|
+
return false;
|
|
65
|
+
const requested = String(requestedModel || '').toLowerCase();
|
|
66
|
+
return this.isSelfHostedPreferredModel(modelId, requestedModel)
|
|
67
|
+
|| requested === 'cloud' || requested === 'cloud-reason' || requested === 'ultra';
|
|
68
|
+
}
|
|
69
|
+
getSelfHostedFallbackModelId(modelId, requestedModel) {
|
|
70
|
+
if (this.isSelfHostedPreferredModel(modelId, requestedModel)) {
|
|
71
|
+
return modelId === 'qwen3-coder:latest' ? 'Vigthoria-v4-Code-27B' : modelId;
|
|
72
|
+
}
|
|
73
|
+
return 'Vigthoria-v4-Code-27B';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface ChatMessage {
|
|
2
|
+
role: 'user' | 'assistant' | 'system';
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ChatResponse {
|
|
6
|
+
id: string;
|
|
7
|
+
message: string;
|
|
8
|
+
model: string;
|
|
9
|
+
usage?: {
|
|
10
|
+
prompt_tokens: number;
|
|
11
|
+
completion_tokens: number;
|
|
12
|
+
total_tokens: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface ModelTransportDependencies {
|
|
16
|
+
resolveModelId(model: string): string;
|
|
17
|
+
resolvePermittedModelId(model: string): string;
|
|
18
|
+
hasCloudAccess(): boolean;
|
|
19
|
+
isAuthenticated(): boolean;
|
|
20
|
+
isCloudModelId(model: string): boolean;
|
|
21
|
+
shouldSkipCloudRoutes(model: string): boolean;
|
|
22
|
+
isSelfHostedPreferred(model: string, requested: string): boolean;
|
|
23
|
+
shouldTrySelfHosted(model: string, requested: string): boolean;
|
|
24
|
+
getSelfHostedFallback(model: string, requested: string): string;
|
|
25
|
+
getFallbackModel(model: string): string | null;
|
|
26
|
+
getMaxTokens(): number;
|
|
27
|
+
hasSelfHostedTransport(): boolean;
|
|
28
|
+
postModels(body: Record<string, unknown>): Promise<any>;
|
|
29
|
+
postCoder(body: Record<string, unknown>): Promise<any>;
|
|
30
|
+
postCanonicalCoder(body: Record<string, unknown>): Promise<any>;
|
|
31
|
+
postSelfHosted(body: Record<string, unknown>): Promise<any>;
|
|
32
|
+
debug(message: string): void;
|
|
33
|
+
}
|
|
34
|
+
export declare class ModelTransportService {
|
|
35
|
+
private readonly dependencies;
|
|
36
|
+
private lastErrors;
|
|
37
|
+
constructor(dependencies: ModelTransportDependencies);
|
|
38
|
+
getLastErrors(): string[];
|
|
39
|
+
chat(messages: ChatMessage[], requestedModel: string): Promise<ChatResponse | null>;
|
|
40
|
+
complete(systemPrompt: string, userPrompt: string, model?: string, maxTokens?: number): Promise<string>;
|
|
41
|
+
private response;
|
|
42
|
+
private tryModel;
|
|
43
|
+
private trySelfHosted;
|
|
44
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { scanOutboundContext } from './secret-policy.js';
|
|
2
|
+
export class ModelTransportService {
|
|
3
|
+
dependencies;
|
|
4
|
+
lastErrors = [];
|
|
5
|
+
constructor(dependencies) {
|
|
6
|
+
this.dependencies = dependencies;
|
|
7
|
+
}
|
|
8
|
+
getLastErrors() { return [...this.lastErrors]; }
|
|
9
|
+
async chat(messages, requestedModel) {
|
|
10
|
+
this.lastErrors = [];
|
|
11
|
+
const safeMessages = scanOutboundContext(messages).value;
|
|
12
|
+
const resolvedModel = this.dependencies.resolveModelId(requestedModel);
|
|
13
|
+
const candidateModels = this.dependencies.isCloudModelId(resolvedModel) && !this.dependencies.hasCloudAccess()
|
|
14
|
+
? [this.dependencies.getSelfHostedFallback(resolvedModel, requestedModel)]
|
|
15
|
+
: [resolvedModel];
|
|
16
|
+
const fallback = this.dependencies.getFallbackModel(resolvedModel);
|
|
17
|
+
if (fallback && fallback !== resolvedModel)
|
|
18
|
+
candidateModels.push(fallback);
|
|
19
|
+
for (const candidate of candidateModels) {
|
|
20
|
+
const response = await this.tryModel(safeMessages, candidate, requestedModel);
|
|
21
|
+
if (response) {
|
|
22
|
+
if (candidate !== resolvedModel)
|
|
23
|
+
this.dependencies.debug(`Recovered chat request using fallback model: ${candidate}`);
|
|
24
|
+
return response;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
async complete(systemPrompt, userPrompt, model, maxTokens) {
|
|
30
|
+
const resolvedModel = model ? this.dependencies.resolvePermittedModelId(model) : 'Vigthoria-v4-Code-27B';
|
|
31
|
+
const response = await this.dependencies.postModels({
|
|
32
|
+
model: resolvedModel,
|
|
33
|
+
messages: scanOutboundContext([{ role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }]).value,
|
|
34
|
+
max_tokens: maxTokens || this.dependencies.getMaxTokens() || 4096,
|
|
35
|
+
temperature: 0.3,
|
|
36
|
+
stream: false,
|
|
37
|
+
});
|
|
38
|
+
const content = response?.choices?.[0]?.message?.content || response?.choices?.[0]?.text || '';
|
|
39
|
+
return typeof content === 'string' ? content : '';
|
|
40
|
+
}
|
|
41
|
+
response(data, model, requested, prefix) {
|
|
42
|
+
const content = data?.choices?.[0]?.message?.content || data?.choices?.[0]?.text || data?.response || data?.message || data?.content;
|
|
43
|
+
if (typeof content !== 'string' || !content.trim() || data?.success === false)
|
|
44
|
+
return null;
|
|
45
|
+
return { id: data.id || `${prefix}-${Date.now()}`, message: content, model: data.model || model || requested, usage: data.usage };
|
|
46
|
+
}
|
|
47
|
+
async tryModel(messages, resolvedModel, requestedModel) {
|
|
48
|
+
const failures = [];
|
|
49
|
+
const preferSelfHosted = this.dependencies.isSelfHostedPreferred(resolvedModel, requestedModel);
|
|
50
|
+
if (preferSelfHosted) {
|
|
51
|
+
const local = await this.trySelfHosted(messages, resolvedModel, requestedModel);
|
|
52
|
+
if (local)
|
|
53
|
+
return local;
|
|
54
|
+
}
|
|
55
|
+
const body = { model: resolvedModel, messages, max_tokens: this.dependencies.getMaxTokens(), temperature: 0.7, stream: false };
|
|
56
|
+
if (!this.dependencies.shouldSkipCloudRoutes(resolvedModel) && !this.dependencies.isCloudModelId(resolvedModel)) {
|
|
57
|
+
try {
|
|
58
|
+
const response = this.response(await this.dependencies.postModels(body), resolvedModel, requestedModel, 'vigthoria');
|
|
59
|
+
if (response)
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
failures.push(`models:${String(error?.response?.data?.error || error?.message || 'Unknown error').slice(0, 120)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (this.dependencies.isAuthenticated() && !this.dependencies.shouldSkipCloudRoutes(resolvedModel)) {
|
|
67
|
+
const coderBody = {
|
|
68
|
+
messages, model: resolvedModel, maxTokens: this.dependencies.getMaxTokens(), temperature: 0.7,
|
|
69
|
+
cloudConsent: this.dependencies.isCloudModelId(resolvedModel),
|
|
70
|
+
};
|
|
71
|
+
try {
|
|
72
|
+
const response = this.response(await this.dependencies.postCoder(coderBody), resolvedModel, requestedModel, 'vigthoria-coder');
|
|
73
|
+
if (response)
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
failures.push(`coder:${String(error?.response?.data?.error || error?.message || 'Unknown error').slice(0, 120)}`);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const response = this.response(await this.dependencies.postCanonicalCoder(coderBody), resolvedModel, requestedModel, 'vigthoria-coder-canonical');
|
|
81
|
+
if (response)
|
|
82
|
+
return response;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
failures.push(`coder-canonical:${String(error?.response?.data?.error || error?.message || 'Unknown error').slice(0, 120)}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!preferSelfHosted) {
|
|
89
|
+
const local = await this.trySelfHosted(messages, resolvedModel, requestedModel);
|
|
90
|
+
if (local)
|
|
91
|
+
return local;
|
|
92
|
+
}
|
|
93
|
+
if (failures.length > 0)
|
|
94
|
+
this.lastErrors = failures;
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
async trySelfHosted(messages, resolvedModel, requestedModel) {
|
|
98
|
+
if (!this.dependencies.hasSelfHostedTransport() || !this.dependencies.shouldTrySelfHosted(resolvedModel, requestedModel))
|
|
99
|
+
return null;
|
|
100
|
+
const model = this.dependencies.getSelfHostedFallback(resolvedModel, requestedModel);
|
|
101
|
+
try {
|
|
102
|
+
return this.response(await this.dependencies.postSelfHosted({
|
|
103
|
+
model, messages, max_tokens: this.dependencies.getMaxTokens(), temperature: 0.7, stream: false,
|
|
104
|
+
}), model, requestedModel, 'vigthoria-dedicated');
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
this.dependencies.debug(`Dedicated model endpoint failed for ${model}: ${error?.message || 'Unknown error'}`);
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type MutationJournalStatus = 'open' | 'committed' | 'rolled_back' | 'partial_mutation';
|
|
2
|
+
export interface MutationJournalReport {
|
|
3
|
+
operationId: string;
|
|
4
|
+
status: MutationJournalStatus;
|
|
5
|
+
affectedPaths: string[];
|
|
6
|
+
rolledBack: boolean;
|
|
7
|
+
partialMutation: boolean;
|
|
8
|
+
rollbackFailures: string[];
|
|
9
|
+
snapshotIssues: string[];
|
|
10
|
+
manifestPath: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function createOperationId(value?: string): string;
|
|
13
|
+
export declare class MutationJournal {
|
|
14
|
+
private readonly limits;
|
|
15
|
+
readonly operationId: string;
|
|
16
|
+
readonly rootPath: string;
|
|
17
|
+
readonly manifestPath: string;
|
|
18
|
+
private readonly journalDirectory;
|
|
19
|
+
private readonly backupDirectory;
|
|
20
|
+
private readonly baseline;
|
|
21
|
+
private readonly baselineDirectories;
|
|
22
|
+
private readonly snapshotIssues;
|
|
23
|
+
private status;
|
|
24
|
+
constructor(rootPath: string, requestedOperationId?: string, limits?: {
|
|
25
|
+
maxBackupBytes: number;
|
|
26
|
+
maxFileBytes: number;
|
|
27
|
+
maxFiles: number;
|
|
28
|
+
});
|
|
29
|
+
private listWorkspaceDirectories;
|
|
30
|
+
private captureBaselineDirectories;
|
|
31
|
+
private listWorkspaceFiles;
|
|
32
|
+
private captureBaseline;
|
|
33
|
+
private changedPaths;
|
|
34
|
+
hasMutations(): boolean;
|
|
35
|
+
private resolveRollbackDestination;
|
|
36
|
+
private removeRollbackDestination;
|
|
37
|
+
private persist;
|
|
38
|
+
private report;
|
|
39
|
+
commit(): MutationJournalReport;
|
|
40
|
+
rollback(): MutationJournalReport;
|
|
41
|
+
}
|
|
42
|
+
export declare function finalizeMutationTransaction(journal: MutationJournal, proofSucceeded: boolean): MutationJournalReport;
|