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
@@ -1,28 +1,24 @@
1
1
  import chalk from 'chalk';
2
2
  import { createSpinner, CH } from '../utils/logger.js';
3
- import { APIClient } from '../utils/api.js';
3
+ import { createAPIClient } from '../utils/api-client-factory.js';
4
4
  import { buildExecutionHints, inferAgentTaskType } from '../utils/requestIntent.js';
5
+ import { redactSensitiveText, redactSensitiveValue } from '../utils/secret-policy.js';
6
+ import { CliCommandError, commandFailure, formatSuccessJson } from '../utils/command-contract.js';
5
7
  export class BackgroundCommand {
6
- config;
7
- logger;
8
8
  api;
9
9
  constructor(config, logger) {
10
- this.config = config;
11
- this.logger = logger;
12
- this.api = new APIClient(config, logger);
10
+ this.api = createAPIClient(config, logger);
13
11
  }
14
12
  async start(promptParts, options = {}) {
15
13
  const prompt = promptParts.join(' ').trim();
16
14
  if (!prompt) {
17
- this.logger.error('Usage: vigthoria background start "<task>"');
18
- return;
15
+ throw new CliCommandError('Usage: vigthoria background start "<task>"', { code: 'BACKGROUND_PROMPT_REQUIRED', category: 'usage' });
19
16
  }
20
17
  const workspacePath = options.workspace || process.cwd();
21
18
  const requestedModel = String(options.model || 'agent').trim().toLowerCase();
22
19
  const allowedModels = new Set(['agent', 'cloud', 'cloud-reason', 'ultra']);
23
20
  if (!allowedModels.has(requestedModel)) {
24
- this.logger.error('Background model must be one of: agent, cloud, cloud-reason, ultra');
25
- return;
21
+ throw new CliCommandError('Background model must be one of: agent, cloud, cloud-reason, ultra', { code: 'BACKGROUND_MODEL_INVALID', category: 'usage' });
26
22
  }
27
23
  const cloudSelected = ['cloud', 'cloud-reason', 'ultra'].includes(requestedModel);
28
24
  const agentTaskType = inferAgentTaskType(prompt);
@@ -53,7 +49,7 @@ export class BackgroundCommand {
53
49
  });
54
50
  spinner.stop();
55
51
  if (options.json) {
56
- console.log(JSON.stringify(job, null, 2));
52
+ console.log(formatSuccessJson('background start', redactSensitiveValue(job)));
57
53
  return;
58
54
  }
59
55
  console.log(chalk.green(`${CH.success} Background job started`));
@@ -67,7 +63,7 @@ export class BackgroundCommand {
67
63
  }
68
64
  catch (error) {
69
65
  spinner.stop();
70
- this.logger.error(error?.message || String(error));
66
+ throw commandFailure(error, { code: 'BACKGROUND_START_FAILED' });
71
67
  }
72
68
  }
73
69
  async list(options = {}) {
@@ -76,7 +72,7 @@ export class BackgroundCommand {
76
72
  const jobs = await this.api.listV3BackgroundJobs(options.limit || 20);
77
73
  spinner.stop();
78
74
  if (options.json) {
79
- console.log(JSON.stringify({ jobs }, null, 2));
75
+ console.log(formatSuccessJson('background list', redactSensitiveValue({ jobs })));
80
76
  return;
81
77
  }
82
78
  if (jobs.length === 0) {
@@ -87,20 +83,19 @@ export class BackgroundCommand {
87
83
  for (const job of jobs) {
88
84
  const color = job.status === 'completed' ? chalk.green : job.status === 'failed' ? chalk.red : job.status === 'cancelled' ? chalk.yellow : chalk.cyan;
89
85
  console.log(`${color(String(job.status || 'unknown').padEnd(10))} ${chalk.cyan(job.job_id)} ${chalk.gray(job.updated_at || '')}`);
90
- console.log(chalk.gray(` ${String(job.request || '').slice(0, 100)}`));
86
+ console.log(chalk.gray(` ${redactSensitiveText(String(job.request || '')).slice(0, 100)}`));
91
87
  console.log(chalk.gray(` files: ${job.file_count || 0} workspace: ${job.local_workspace_path || job.workspace_name || '-'}`));
92
88
  }
93
89
  console.log();
94
90
  }
95
91
  catch (error) {
96
92
  spinner.stop();
97
- this.logger.error(error?.message || String(error));
93
+ throw commandFailure(error, { code: 'BACKGROUND_LIST_FAILED' });
98
94
  }
99
95
  }
100
96
  async status(jobId, options = {}) {
101
97
  if (!jobId) {
102
- this.logger.error('Usage: vigthoria background status <job-id>');
103
- return;
98
+ throw new CliCommandError('Usage: vigthoria background status <job-id>', { code: 'BACKGROUND_JOB_ID_REQUIRED', category: 'usage' });
104
99
  }
105
100
  const spinner = createSpinner('Loading background job...').start();
106
101
  try {
@@ -108,7 +103,7 @@ export class BackgroundCommand {
108
103
  spinner.stop();
109
104
  const outcome = this.extractBackgroundOutcome(job);
110
105
  if (options.json) {
111
- console.log(JSON.stringify({ ...job, outcomeTruth: outcome }, null, 2));
106
+ console.log(formatSuccessJson('background status', redactSensitiveValue({ ...job, outcomeTruth: outcome })));
112
107
  return;
113
108
  }
114
109
  console.log(chalk.bold(`\nBackground Job ${chalk.cyan(job.job_id)}\n`));
@@ -123,29 +118,28 @@ export class BackgroundCommand {
123
118
  console.log(chalk.gray(`Outcome: ${outcome.headline}`));
124
119
  }
125
120
  if (job.error)
126
- console.log(chalk.red(`Error: ${job.error}`));
121
+ console.log(chalk.red(`Error: ${redactSensitiveText(String(job.error))}`));
127
122
  const approvals = Array.isArray(job.pending_approvals) ? job.pending_approvals : [];
128
123
  if (approvals.length > 0) {
129
124
  console.log(chalk.yellow(`Gate: ${approvals.length} command approval(s) required`));
130
125
  for (const approval of approvals) {
131
- console.log(chalk.gray(` ${approval.approval_id}: ${approval.command || '(empty command)'}`));
126
+ console.log(chalk.gray(` ${approval.approval_id}: ${redactSensitiveText(String(approval.command || '(empty command)'))}`));
132
127
  console.log(chalk.gray(` Resolve: vigthoria background approve ${job.job_id} ${approval.approval_id}`));
133
128
  }
134
129
  }
135
- console.log(chalk.gray(`\n${String(job.request || '').slice(0, 500)}`));
130
+ console.log(chalk.gray(`\n${redactSensitiveText(String(job.request || '')).slice(0, 500)}`));
136
131
  if (job.status === 'completed' && (job.file_count || 0) > 0) {
137
132
  console.log(chalk.gray(`\nUse ${chalk.cyan(`vigthoria background apply ${job.job_id}`)} to apply files locally.`));
138
133
  }
139
134
  }
140
135
  catch (error) {
141
136
  spinner.stop();
142
- this.logger.error(error?.message || String(error));
137
+ throw commandFailure(error, { code: 'BACKGROUND_STATUS_FAILED' });
143
138
  }
144
139
  }
145
140
  async apply(jobId, options = {}) {
146
141
  if (!jobId) {
147
- this.logger.error('Usage: vigthoria background apply <job-id>');
148
- return;
142
+ throw new CliCommandError('Usage: vigthoria background apply <job-id>', { code: 'BACKGROUND_JOB_ID_REQUIRED', category: 'usage' });
149
143
  }
150
144
  const workspacePath = options.workspace || process.cwd();
151
145
  const spinner = createSpinner('Applying background job files...').start();
@@ -157,7 +151,7 @@ export class BackgroundCommand {
157
151
  });
158
152
  spinner.stop();
159
153
  if (options.json) {
160
- console.log(JSON.stringify(result, null, 2));
154
+ console.log(formatSuccessJson('background apply', redactSensitiveValue(result)));
161
155
  return;
162
156
  }
163
157
  console.log(chalk.green(`${CH.success} Applied ${result.applied.length} file(s) from ${jobId}`));
@@ -173,27 +167,26 @@ export class BackgroundCommand {
173
167
  }
174
168
  catch (error) {
175
169
  spinner.stop();
176
- this.logger.error(error?.message || String(error));
170
+ throw commandFailure(error, { code: 'BACKGROUND_APPLY_FAILED' });
177
171
  }
178
172
  }
179
173
  async cancel(jobId, options = {}) {
180
174
  if (!jobId) {
181
- this.logger.error('Usage: vigthoria background cancel <job-id>');
182
- return;
175
+ throw new CliCommandError('Usage: vigthoria background cancel <job-id>', { code: 'BACKGROUND_JOB_ID_REQUIRED', category: 'usage' });
183
176
  }
184
177
  const spinner = createSpinner('Cancelling background job...').start();
185
178
  try {
186
179
  const result = await this.api.cancelV3BackgroundJob(jobId);
187
180
  spinner.stop();
188
181
  if (options.json) {
189
- console.log(JSON.stringify(result, null, 2));
182
+ console.log(formatSuccessJson('background cancel', redactSensitiveValue(result)));
190
183
  return;
191
184
  }
192
185
  console.log(chalk.yellow(`${CH.warn} Background job cancelled: ${jobId}`));
193
186
  }
194
187
  catch (error) {
195
188
  spinner.stop();
196
- this.logger.error(error?.message || String(error));
189
+ throw commandFailure(error, { code: 'BACKGROUND_CANCEL_FAILED' });
197
190
  }
198
191
  }
199
192
  extractBackgroundOutcome(job) {
@@ -247,8 +240,7 @@ export class BackgroundCommand {
247
240
  }
248
241
  async approve(jobId, approvalId, options = {}) {
249
242
  if (!jobId || !approvalId) {
250
- this.logger.error('Usage: vigthoria background approve <job-id> <approval-id>');
251
- return;
243
+ throw new CliCommandError('Usage: vigthoria background approve <job-id> <approval-id>', { code: 'BACKGROUND_APPROVAL_ID_REQUIRED', category: 'usage' });
252
244
  }
253
245
  const approved = !options.deny;
254
246
  const spinner = createSpinner(`${approved ? 'Approving' : 'Denying'} background command...`).start();
@@ -256,7 +248,7 @@ export class BackgroundCommand {
256
248
  const result = await this.api.resolveV3BackgroundApproval(jobId, approvalId, approved, 'once');
257
249
  spinner.stop();
258
250
  if (options.json) {
259
- console.log(JSON.stringify({ ...result, job_id: jobId, approval_id: approvalId, approved }, null, 2));
251
+ console.log(formatSuccessJson('background approve', redactSensitiveValue({ ...result, job_id: jobId, approval_id: approvalId, approved })));
260
252
  return;
261
253
  }
262
254
  console.log(approved
@@ -265,7 +257,7 @@ export class BackgroundCommand {
265
257
  }
266
258
  catch (error) {
267
259
  spinner.stop();
268
- this.logger.error(error?.message || String(error));
260
+ throw commandFailure(error, { code: 'BACKGROUND_APPROVAL_FAILED' });
269
261
  }
270
262
  }
271
263
  }
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import { createSpinner } from '../utils/logger.js';
3
- import { APIClient } from '../utils/api.js';
3
+ import { createAPIClient } from '../utils/api-client-factory.js';
4
4
  import { getDesktopBridgeStatus } from '../utils/desktop-bridge-client.js';
5
5
  function displayEndpoint(endpoint) {
6
6
  if (/^(?:wss?|https?):\/\/(?:127\.0\.0\.1|localhost)(?::\d+)?/i.test(endpoint)) {
@@ -11,50 +11,54 @@ function displayEndpoint(endpoint) {
11
11
  export class BridgeCommand {
12
12
  api;
13
13
  constructor(config, logger) {
14
- this.api = new APIClient(config, logger);
14
+ this.api = createAPIClient(config, logger);
15
15
  }
16
16
  async status() {
17
17
  const spinner = createSpinner('Checking bridges...').start();
18
- const [devtoolsBridge, desktopBridge] = await Promise.all([
19
- this.api.getDevtoolsBridgeStatus(),
20
- getDesktopBridgeStatus(),
21
- ]);
22
- spinner.stop();
23
- console.log();
24
- console.log(chalk.white('DevTools Bridge (browser, port 4016):'));
25
- console.log(chalk.gray(' Status: ') + (devtoolsBridge.ok ? chalk.green('Reachable') : chalk.yellow('Not running')));
26
- if (devtoolsBridge.ok) {
27
- console.log(chalk.gray(' Endpoint: ') + displayEndpoint(devtoolsBridge.endpoint));
18
+ try {
19
+ const [devtoolsBridge, desktopBridge] = await Promise.all([
20
+ this.api.getDevtoolsBridgeStatus(),
21
+ getDesktopBridgeStatus(),
22
+ ]);
23
+ spinner.stop();
24
+ console.log();
25
+ console.log(chalk.white('DevTools Bridge (browser, port 4016):'));
26
+ console.log(chalk.gray(' Status: ') + (devtoolsBridge.ok ? chalk.green('Reachable') : chalk.yellow('Not running')));
27
+ if (devtoolsBridge.ok) {
28
+ console.log(chalk.gray(' Endpoint: ') + displayEndpoint(devtoolsBridge.endpoint));
29
+ }
30
+ else {
31
+ const detail = String(devtoolsBridge.error || 'Connection refused').trim() || 'Connection refused';
32
+ console.log(chalk.gray(' Error: ') + chalk.yellow(detail));
33
+ }
34
+ console.log(chalk.gray(' Use for: ') + (devtoolsBridge.ok
35
+ ? chalk.green('Local browser observability in CLI chat flows.')
36
+ : chalk.gray('Start vigthoria-devtools-bridge on port 4016.')));
37
+ console.log();
38
+ console.log(chalk.white('Desktop Bridge (Windows desktop, port 49160):'));
39
+ console.log(chalk.gray(' Status: ') + (desktopBridge.ok ? chalk.green('Reachable') : chalk.yellow('Not running')));
40
+ if (desktopBridge.ok) {
41
+ console.log(chalk.gray(' Endpoint: ') + displayEndpoint(desktopBridge.endpoint));
42
+ if (desktopBridge.service)
43
+ console.log(chalk.gray(' Service: ') + desktopBridge.service);
44
+ if (desktopBridge.version)
45
+ console.log(chalk.gray(' Version: ') + desktopBridge.version);
46
+ console.log(chalk.gray(' Control: ') + (desktopBridge.controlEnabled ? chalk.green('enabled') : chalk.yellow('disabled')));
47
+ }
48
+ else {
49
+ const detail = String(desktopBridge.error || 'Connection refused').trim() || 'Connection refused';
50
+ console.log(chalk.gray(' Error: ') + chalk.yellow(detail));
51
+ console.log(chalk.gray(' Windows setup: ') + 'Run extension.vigthoria.io/downloads/vigthoria-desktop-bridge-bringup.ps1');
52
+ console.log(chalk.gray(' Tunnel: ') + 'ssh -N -R 127.0.0.1:49160:127.0.0.1:49160 root@78.46.154.201');
53
+ }
54
+ console.log(chalk.gray(' Use for: ') + (desktopBridge.ok
55
+ ? chalk.green('Remote Vigthoria Code screenshots, input, and Electron DevTools (9229).')
56
+ : chalk.gray('Start local-desktop-bridge.js on Windows, then open the SSH reverse tunnel.')));
57
+ console.log();
28
58
  }
29
- else {
30
- const detail = String(devtoolsBridge.error || 'Connection refused').trim() || 'Connection refused';
31
- console.log(chalk.gray(' Error: ') + chalk.yellow(detail));
59
+ finally {
60
+ spinner.stop();
61
+ this.api.destroy();
32
62
  }
33
- console.log(chalk.gray(' Use for: ') + (devtoolsBridge.ok
34
- ? chalk.green('Local browser observability in CLI chat flows.')
35
- : chalk.gray('Start vigthoria-devtools-bridge on port 4016.')));
36
- console.log();
37
- console.log(chalk.white('Desktop Bridge (Windows desktop, port 49160):'));
38
- console.log(chalk.gray(' Status: ') + (desktopBridge.ok ? chalk.green('Reachable') : chalk.yellow('Not running')));
39
- if (desktopBridge.ok) {
40
- console.log(chalk.gray(' Endpoint: ') + displayEndpoint(desktopBridge.endpoint));
41
- if (desktopBridge.service)
42
- console.log(chalk.gray(' Service: ') + desktopBridge.service);
43
- if (desktopBridge.version)
44
- console.log(chalk.gray(' Version: ') + desktopBridge.version);
45
- console.log(chalk.gray(' Control: ') + (desktopBridge.controlEnabled ? chalk.green('enabled') : chalk.yellow('disabled')));
46
- }
47
- else {
48
- const detail = String(desktopBridge.error || 'Connection refused').trim() || 'Connection refused';
49
- console.log(chalk.gray(' Error: ') + chalk.yellow(detail));
50
- console.log(chalk.gray(' Windows setup: ') + 'Run extension.vigthoria.io/downloads/vigthoria-desktop-bridge-bringup.ps1');
51
- console.log(chalk.gray(' Tunnel: ') + 'ssh -N -R 127.0.0.1:49160:127.0.0.1:49160 root@78.46.154.201');
52
- }
53
- console.log(chalk.gray(' Use for: ') + (desktopBridge.ok
54
- ? chalk.green('Remote Vigthoria Code screenshots, input, and Electron DevTools (9229).')
55
- : chalk.gray('Start local-desktop-bridge.js on Windows, then open the SSH reverse tunnel.')));
56
- console.log();
57
- this.api.destroy();
58
- process.exitCode = 0;
59
63
  }
60
64
  }
@@ -8,6 +8,7 @@ interface CancelOptions {
8
8
  export declare class CancelCommand {
9
9
  private config;
10
10
  private logger;
11
+ private sessions;
11
12
  constructor(config: Config, logger: Logger);
12
13
  private getHeaders;
13
14
  private getBaseUrl;
@@ -1,4 +1,3 @@
1
- import { isServerRuntime } from '../utils/api.js';
2
1
  /**
3
2
  * cancel.ts — Cancel an in-flight V3 agent run, or cancel all active runs.
4
3
  *
@@ -9,9 +8,12 @@ import { isServerRuntime } from '../utils/api.js';
9
8
  */
10
9
  import chalk from 'chalk';
11
10
  import { createSpinner, CH } from '../utils/logger.js';
11
+ import { SessionManager } from '../utils/session.js';
12
+ import { CliCommandError, formatSuccessJson } from '../utils/command-contract.js';
12
13
  export class CancelCommand {
13
14
  config;
14
15
  logger;
16
+ sessions = new SessionManager();
15
17
  constructor(config, logger) {
16
18
  this.config = config;
17
19
  this.logger = logger;
@@ -32,7 +34,7 @@ export class CancelCommand {
32
34
  }
33
35
  getBaseUrl() {
34
36
  const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
35
- const allowLocal = !isServerRuntime() || process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
37
+ const allowLocal = process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
36
38
  return (process.env.VIGTHORIA_V3_AGENT_URL ||
37
39
  process.env.V3_AGENT_URL ||
38
40
  (allowLocal ? 'http://127.0.0.1:8030' : null) ||
@@ -42,16 +44,17 @@ export class CancelCommand {
42
44
  const resp = await fetch(`${baseUrl}/api/runs/active`, { headers: this.getHeaders() });
43
45
  if (!resp.ok) {
44
46
  if (resp.status === 404 || resp.status === 502 || resp.status === 503) {
45
- this.logger.error(`V3 cancel API is not available on ${baseUrl}. Backend may not expose /api/runs/active. ` +
46
- `(Requires V3 agent server.py with the cancel endpoint patched in.)`);
47
+ throw new CliCommandError(`V3 cancel API is not available on ${baseUrl}. Backend may not expose /api/runs/active.`, { code: 'CANCEL_API_UNAVAILABLE', category: 'network', status: resp.status });
47
48
  }
48
49
  else if (resp.status === 401 || resp.status === 403) {
49
- this.logger.error(`Authentication failed (${resp.status}). Run \`vig login\` first.`);
50
+ throw new CliCommandError(`Authentication failed (${resp.status}). Run \`vigthoria login\` first.`, {
51
+ code: resp.status === 401 ? 'AUTH_SESSION_INVALID' : 'AUTH_FORBIDDEN',
52
+ category: resp.status === 401 ? 'authentication' : 'authorization', status: resp.status,
53
+ });
50
54
  }
51
55
  else {
52
- this.logger.error(`Failed to list active runs: ${resp.status} ${resp.statusText}`);
56
+ throw new CliCommandError(`Failed to list active runs: ${resp.status} ${resp.statusText}`, { code: 'CANCEL_LIST_FAILED', status: resp.status });
53
57
  }
54
- return null;
55
58
  }
56
59
  return (await resp.json());
57
60
  }
@@ -59,15 +62,17 @@ export class CancelCommand {
59
62
  const resp = await fetch(`${baseUrl}/api/runs/${encodeURIComponent(contextId)}/cancel`, { method: 'POST', headers: this.getHeaders() });
60
63
  if (!resp.ok) {
61
64
  if (resp.status === 404) {
62
- this.logger.warn(`No active run for context_id=${contextId}`);
65
+ throw new CliCommandError(`No active run for context_id=${contextId}`, { code: 'ACTIVE_RUN_NOT_FOUND', status: resp.status });
63
66
  }
64
67
  else if (resp.status === 401 || resp.status === 403) {
65
- this.logger.error(`Authentication failed (${resp.status}). Run \`vig login\` first.`);
68
+ throw new CliCommandError(`Authentication failed (${resp.status}). Run \`vigthoria login\` first.`, {
69
+ code: resp.status === 401 ? 'AUTH_SESSION_INVALID' : 'AUTH_FORBIDDEN',
70
+ category: resp.status === 401 ? 'authentication' : 'authorization', status: resp.status,
71
+ });
66
72
  }
67
73
  else {
68
- this.logger.error(`Cancel failed for ${contextId}: ${resp.status} ${resp.statusText}`);
74
+ throw new CliCommandError(`Cancel failed for ${contextId}: ${resp.status} ${resp.statusText}`, { code: 'CANCEL_FAILED', status: resp.status });
69
75
  }
70
- return null;
71
76
  }
72
77
  return (await resp.json());
73
78
  }
@@ -80,7 +85,7 @@ export class CancelCommand {
80
85
  if (!active)
81
86
  return;
82
87
  if (options.json) {
83
- console.log(JSON.stringify(active, null, 2));
88
+ console.log(formatSuccessJson('cancel', active, { operation: 'list' }));
84
89
  return;
85
90
  }
86
91
  if (active.active_count === 0) {
@@ -111,24 +116,25 @@ export class CancelCommand {
111
116
  sp.stop();
112
117
  if (r) {
113
118
  results.push(r);
119
+ this.sessions.markCancelledByContext(cid);
114
120
  this.logger.success(`Cancelled ${chalk.cyan(cid)} (asyncio_cancelled=${r.asyncio_cancelled})`);
115
121
  }
116
122
  }
117
123
  if (options.json)
118
- console.log(JSON.stringify({ cancelled: results }, null, 2));
124
+ console.log(formatSuccessJson('cancel', { cancelled: results }, { operation: 'cancel-all' }));
119
125
  return;
120
126
  }
121
127
  if (!contextId) {
122
- this.logger.error('Usage: vig cancel <context_id> | --all | --list');
123
- return;
128
+ throw new CliCommandError('Usage: vigthoria cancel <context_id> | --all | --list', { code: 'CANCEL_TARGET_REQUIRED', category: 'usage' });
124
129
  }
125
130
  const spinner = createSpinner(`Cancelling ${contextId}...`).start();
126
131
  const r = await this.cancelOne(baseUrl, contextId);
127
132
  spinner.stop();
128
133
  if (!r)
129
134
  return;
135
+ this.sessions.markCancelledByContext(contextId);
130
136
  if (options.json) {
131
- console.log(JSON.stringify(r, null, 2));
137
+ console.log(formatSuccessJson('cancel', r, { operation: 'cancel-one' }));
132
138
  return;
133
139
  }
134
140
  this.logger.success(`Cancelled ${chalk.cyan(contextId)} ` +
@@ -41,6 +41,8 @@ export declare class ChatCommand {
41
41
  private modelExplicitlySelected;
42
42
  private autoApprove;
43
43
  private personaOverride;
44
+ private readonly toolCallParser;
45
+ private readonly promptPolicy;
44
46
  private agentToolEvidence;
45
47
  private operatorMode;
46
48
  private workflowTarget;
@@ -49,12 +51,7 @@ export declare class ChatCommand {
49
51
  private modelGovernanceFallback;
50
52
  private retryPromptSignature;
51
53
  private retryPromptStreak;
52
- private v3SuppressThinkingStream;
53
- private v3StreamedAnswerBuffer;
54
- private v3StreamedAnswerDisplayed;
55
- private v3SeenToolCalls;
56
- private v3SeenToolResults;
57
- private v3StartSeen;
54
+ private readonly streamState;
58
55
  private lastAgentRoute;
59
56
  private pendingGoaContext;
60
57
  private lastAgentRunOutcome;
@@ -85,11 +82,6 @@ export declare class ChatCommand {
85
82
  * Returns true when the prompt is a simple lookup / analysis / read-only
86
83
  * question — these should use analysis_only workflow, not full_autonomy.
87
84
  */
88
- private isAnalysisLookupPrompt;
89
- private extractExplicitLocalPath;
90
- private isUnscopedPromptPathOverrideAllowed;
91
- private isPathWithinRoot;
92
- private getPromptPathAllowedRoots;
93
85
  private resolvePromptWorkspacePath;
94
86
  private isBrowserTaskPrompt;
95
87
  /**
@@ -106,8 +98,6 @@ export declare class ChatCommand {
106
98
  * instead of the toolless BMAD/direct-answer path.
107
99
  */
108
100
  private isRepoGroundedPrompt;
109
- private inferAgentTaskType;
110
- private buildTaskShapingInstructions;
111
101
  private buildExecutionPrompt;
112
102
  private isProjectBrainRuntimeDisabled;
113
103
  private getWorkspaceBrainService;
@@ -117,18 +107,11 @@ export declare class ChatCommand {
117
107
  private buildWorkspaceBrainRuntimeContext;
118
108
  private rememberBrainEvent;
119
109
  private getPromptRuntimeContext;
120
- private v3IterationCount;
121
- private v3ToolCallCount;
122
- private v3LastActivity;
123
- private v3IdleWatchInterval;
124
- private v3IdleNoticeShown;
125
- private v3StreamingStarted;
126
110
  /**
127
111
  * Strip server-internal path prefixes from tool output strings.
128
112
  * Prevents exposing paths like /var/www/V3-Code-Agent/... to end users.
129
113
  */
130
114
  private sanitizeServerPath;
131
- private stripHiddenThoughtBlocks;
132
115
  private startV3IdleWatch;
133
116
  private stopV3IdleWatch;
134
117
  private describeV3AgentTool;
@@ -188,11 +171,6 @@ export declare class ChatCommand {
188
171
  private persistLocalLoopOutcome;
189
172
  private runLocalAgentLoop;
190
173
  private primeBypassedTargetFileContext;
191
- /**
192
- * Sub-second path for trivial HTML/hello-world: Template Service → index.html (no V3 planner).
193
- */
194
- private tryTemplateInstantPath;
195
- private tryDirectSingleFileFlow;
196
174
  private taskRequiresWorkspaceChanges;
197
175
  private getPreviousActionablePrompt;
198
176
  private buildContextualAgentPrompt;
@@ -228,14 +206,11 @@ export declare class ChatCommand {
228
206
  private buildScopedUserPrompt;
229
207
  private inferTargetFilesFromPrompt;
230
208
  private inferTargetFileFromPrompt;
231
- private workspaceContainsHtmlEntry;
232
209
  private shouldBypassDirectSingleFileFlow;
233
- private shouldPreferLocalAgentLoop;
234
210
  private getRuntimeEnvironmentContext;
235
211
  private shouldRequireV3AgentWorkflow;
236
212
  private isServerBindableWorkspace;
237
213
  private isProtectedFileReferenceSafe;
238
- private isProtectedFileReference;
239
214
  private buildContinuationPrompt;
240
215
  /**
241
216
  * Extract Key* / event-handler identifiers from tool results grouped by
@@ -244,11 +219,7 @@ export declare class ChatCommand {
244
219
  */
245
220
  private computeCrossFileKeyEvidence;
246
221
  private extractToolCalls;
247
- private normalizeCliToolName;
248
- private parseLegacyFunctionToolCalls;
249
- private parseToolPayload;
250
222
  private stripToolPayloads;
251
- private extractFinalFileContent;
252
223
  /**
253
224
  * Synthesize a best-effort answer from tool evidence already collected
254
225
  * in the message history. Used as a fallback when the model API fails
@@ -256,22 +227,14 @@ export declare class ChatCommand {
256
227
  */
257
228
  private synthesizeEvidenceFromHistory;
258
229
  private resolveDirectModeCompletion;
259
- /**
260
- * Strip system-prompt echoes, tool execution headers, grounding-rule
261
- * parroting, recovery banners, and multi-line tool output blocks from
262
- * the model's final answer so that --json output contains only the
263
- * substantive answer.
264
- */
265
- private sanitizeDirectModeOutput;
266
- private isDirectModeFollowUpQuestion;
267
230
  private buildLocalAnalysisFallback;
268
- private tryDeterministicSingleFileRewrite;
269
- private extractExactTextRequirement;
270
231
  private executeToolCalls;
271
232
  private formatToolResult;
272
233
  private truncateText;
273
234
  private getLastUserPrompt;
274
235
  private saveSession;
236
+ private persistAgentExecutionCheckpoint;
237
+ private updateAgentExecutionCheckpoint;
275
238
  private requestPermission;
276
239
  getCurrentSessionInfo(): string;
277
240
  getChatHistory(): ChatMessage[];