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.
Files changed (185) hide show
  1. package/completions/_vigthoria +49 -0
  2. package/completions/vigthoria.bash +6 -0
  3. package/completions/vigthoria.fish +41 -0
  4. package/dist/commands/auth.d.ts +1 -0
  5. package/dist/commands/auth.js +84 -135
  6. package/dist/commands/background.d.ts +0 -2
  7. package/dist/commands/background.js +26 -34
  8. package/dist/commands/bridge.js +45 -41
  9. package/dist/commands/cancel.d.ts +1 -0
  10. package/dist/commands/cancel.js +22 -16
  11. package/dist/commands/chat.d.ts +5 -42
  12. package/dist/commands/chat.js +462 -1122
  13. package/dist/commands/coding-registration.d.ts +4 -0
  14. package/dist/commands/coding-registration.js +24 -0
  15. package/dist/commands/config.js +32 -42
  16. package/dist/commands/conversation-registration.d.ts +4 -0
  17. package/dist/commands/conversation-registration.js +122 -0
  18. package/dist/commands/deploy.d.ts +8 -2
  19. package/dist/commands/deploy.js +92 -90
  20. package/dist/commands/device.d.ts +1 -2
  21. package/dist/commands/device.js +37 -21
  22. package/dist/commands/doctor-registration.d.ts +4 -0
  23. package/dist/commands/doctor-registration.js +200 -0
  24. package/dist/commands/edit.js +22 -33
  25. package/dist/commands/explain.js +7 -10
  26. package/dist/commands/fork.d.ts +1 -2
  27. package/dist/commands/fork.js +72 -22
  28. package/dist/commands/game.d.ts +1 -1
  29. package/dist/commands/game.js +17 -6
  30. package/dist/commands/generate.js +7 -9
  31. package/dist/commands/history.js +11 -7
  32. package/dist/commands/hub.d.ts +2 -2
  33. package/dist/commands/hub.js +34 -35
  34. package/dist/commands/legion.d.ts +0 -1
  35. package/dist/commands/legion.js +62 -79
  36. package/dist/commands/music.d.ts +1 -2
  37. package/dist/commands/music.js +62 -27
  38. package/dist/commands/platform-registration.d.ts +4 -0
  39. package/dist/commands/platform-registration.js +45 -0
  40. package/dist/commands/preview.d.ts +0 -1
  41. package/dist/commands/preview.js +82 -35
  42. package/dist/commands/product-run-registration.d.ts +4 -0
  43. package/dist/commands/product-run-registration.js +490 -0
  44. package/dist/commands/replay.d.ts +1 -2
  45. package/dist/commands/replay.js +15 -11
  46. package/dist/commands/repo.d.ts +14 -7
  47. package/dist/commands/repo.js +245 -196
  48. package/dist/commands/review.js +9 -12
  49. package/dist/commands/security.d.ts +1 -2
  50. package/dist/commands/security.js +12 -6
  51. package/dist/commands/update-registration.d.ts +3 -0
  52. package/dist/commands/update-registration.js +338 -0
  53. package/dist/commands/v4-registration.d.ts +4 -0
  54. package/dist/commands/v4-registration.js +24 -0
  55. package/dist/commands/v4.d.ts +1 -1
  56. package/dist/commands/v4.js +46 -8
  57. package/dist/commands/wallet.d.ts +1 -3
  58. package/dist/commands/wallet.js +18 -45
  59. package/dist/commands/workflow.d.ts +2 -0
  60. package/dist/commands/workflow.js +52 -39
  61. package/dist/index.js +122 -1498
  62. package/dist/utils/agent-stream-state.d.ts +27 -0
  63. package/dist/utils/agent-stream-state.js +93 -0
  64. package/dist/utils/agentRoute.d.ts +2 -1
  65. package/dist/utils/agentRoute.js +22 -9
  66. package/dist/utils/agentRunOutcome.d.ts +16 -0
  67. package/dist/utils/agentRunOutcome.js +37 -2
  68. package/dist/utils/api-client-factory.d.ts +8 -0
  69. package/dist/utils/api-client-factory.js +8 -0
  70. package/dist/utils/api.d.ts +45 -269
  71. package/dist/utils/api.js +664 -3210
  72. package/dist/utils/auth-session.d.ts +41 -0
  73. package/dist/utils/auth-session.js +224 -0
  74. package/dist/utils/brain-hub-client.d.ts +0 -4
  75. package/dist/utils/brain-hub-client.js +6 -3
  76. package/dist/utils/bridge-client.js +2 -0
  77. package/dist/utils/capability-health-service.d.ts +48 -0
  78. package/dist/utils/capability-health-service.js +64 -0
  79. package/dist/utils/chat-prompt-policy.d.ts +18 -0
  80. package/dist/utils/chat-prompt-policy.js +61 -0
  81. package/dist/utils/chat-tool-call-parser.d.ts +11 -0
  82. package/dist/utils/chat-tool-call-parser.js +71 -0
  83. package/dist/utils/cli-state.d.ts +22 -4
  84. package/dist/utils/cli-state.js +105 -47
  85. package/dist/utils/code-operations-service.d.ts +104 -0
  86. package/dist/utils/code-operations-service.js +837 -0
  87. package/dist/utils/codebase-indexer.d.ts +1 -0
  88. package/dist/utils/codebase-indexer.js +28 -8
  89. package/dist/utils/command-contract.d.ts +61 -0
  90. package/dist/utils/command-contract.js +149 -0
  91. package/dist/utils/command-policy.d.ts +10 -0
  92. package/dist/utils/command-policy.js +54 -0
  93. package/dist/utils/config.d.ts +13 -5
  94. package/dist/utils/config.js +227 -99
  95. package/dist/utils/context-ranker.js +11 -2
  96. package/dist/utils/context-state.d.ts +39 -0
  97. package/dist/utils/context-state.js +52 -0
  98. package/dist/utils/deckEvents.d.ts +0 -5
  99. package/dist/utils/deckEvents.js +3 -2
  100. package/dist/utils/desktop-bridge-client.js +2 -0
  101. package/dist/utils/direct-output-policy.d.ts +3 -0
  102. package/dist/utils/direct-output-policy.js +76 -0
  103. package/dist/utils/durable-json.d.ts +57 -0
  104. package/dist/utils/durable-json.js +319 -0
  105. package/dist/utils/fastAgentRouter.d.ts +6 -7
  106. package/dist/utils/fastAgentRouter.js +21 -30
  107. package/dist/utils/files.js +21 -13
  108. package/dist/utils/frontend-preview-service.d.ts +76 -0
  109. package/dist/utils/frontend-preview-service.js +482 -0
  110. package/dist/utils/goaEvents.d.ts +0 -4
  111. package/dist/utils/goaEvents.js +5 -2
  112. package/dist/utils/logger.d.ts +2 -1
  113. package/dist/utils/logger.js +27 -20
  114. package/dist/utils/mcp-context-client.d.ts +24 -0
  115. package/dist/utils/mcp-context-client.js +58 -0
  116. package/dist/utils/model-governance.d.ts +18 -0
  117. package/dist/utils/model-governance.js +75 -0
  118. package/dist/utils/model-transport-service.d.ts +44 -0
  119. package/dist/utils/model-transport-service.js +111 -0
  120. package/dist/utils/mutation-journal.d.ts +42 -0
  121. package/dist/utils/mutation-journal.js +387 -0
  122. package/dist/utils/network-policy.d.ts +24 -0
  123. package/dist/utils/network-policy.js +202 -0
  124. package/dist/utils/operator-client.d.ts +45 -0
  125. package/dist/utils/operator-client.js +159 -0
  126. package/dist/utils/post-write-validator.js +7 -9
  127. package/dist/utils/preview-screenshot-adapter.d.ts +13 -0
  128. package/dist/utils/preview-screenshot-adapter.js +36 -0
  129. package/dist/utils/process-policy.d.ts +23 -0
  130. package/dist/utils/process-policy.js +284 -0
  131. package/dist/utils/project-memory.d.ts +13 -3
  132. package/dist/utils/project-memory.js +70 -17
  133. package/dist/utils/prompt-workspace-resolver.d.ts +14 -0
  134. package/dist/utils/prompt-workspace-resolver.js +64 -0
  135. package/dist/utils/release-install.d.ts +11 -0
  136. package/dist/utils/release-install.js +155 -0
  137. package/dist/utils/release-policy.d.ts +64 -0
  138. package/dist/utils/release-policy.js +293 -0
  139. package/dist/utils/requestIntent.js +22 -3
  140. package/dist/utils/runtime-capability.d.ts +8 -0
  141. package/dist/utils/runtime-capability.js +16 -0
  142. package/dist/utils/secret-policy.d.ts +20 -0
  143. package/dist/utils/secret-policy.js +160 -0
  144. package/dist/utils/session.d.ts +34 -2
  145. package/dist/utils/session.js +354 -110
  146. package/dist/utils/tool-approval-service.d.ts +17 -0
  147. package/dist/utils/tool-approval-service.js +78 -0
  148. package/dist/utils/tool-capability-providers.d.ts +57 -0
  149. package/dist/utils/tool-capability-providers.js +57 -0
  150. package/dist/utils/tools.d.ts +2 -23
  151. package/dist/utils/tools.js +216 -508
  152. package/dist/utils/update-policy.d.ts +18 -0
  153. package/dist/utils/update-policy.js +137 -0
  154. package/dist/utils/v3-agent-client.d.ts +40 -0
  155. package/dist/utils/v3-agent-client.js +165 -0
  156. package/dist/utils/v3-workspace-service.d.ts +28 -0
  157. package/dist/utils/v3-workspace-service.js +279 -0
  158. package/dist/utils/vigflow-client.d.ts +95 -0
  159. package/dist/utils/vigflow-client.js +105 -0
  160. package/dist/utils/workspace-boundary.d.ts +45 -0
  161. package/dist/utils/workspace-boundary.js +377 -0
  162. package/dist/utils/workspace-brain-service.d.ts +2 -0
  163. package/dist/utils/workspace-brain-service.js +11 -1
  164. package/dist/utils/workspace-cache.js +37 -15
  165. package/dist/utils/workspace-stream.js +35 -10
  166. package/install.ps1 +86 -143
  167. package/install.sh +76 -81
  168. package/package.json +44 -9
  169. package/release-policy.json +43 -0
  170. package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
  171. package/scripts/release/generate-completions.mjs +24 -0
  172. package/scripts/release/install-release.mjs +10 -0
  173. package/scripts/release/publish-cli-release.mjs +116 -0
  174. package/scripts/release/publish-cli-release.sh +2 -70
  175. package/scripts/release/resolve-release-manifest.mjs +26 -0
  176. package/scripts/release/test-balanced-model-live.sh +42 -0
  177. package/scripts/release/validate-live-service-gates.sh +90 -0
  178. package/scripts/release/validate-no-go-gates.sh +135 -172
  179. package/scripts/release/verify-runtime-consistency.mjs +4 -1
  180. package/dist/commands/index.d.ts +0 -12
  181. package/dist/commands/index.js +0 -194
  182. package/dist/commands/update.d.ts +0 -9
  183. package/dist/commands/update.js +0 -301
  184. package/dist/utils/templateInstantPath.d.ts +0 -18
  185. package/dist/utils/templateInstantPath.js +0 -228
@@ -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, language) {
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 fileName = filePath.split('/').pop() || filePath;
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/${filePath}`));
120
- console.log(chalk.gray(` +++ b/${filePath}`));
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;