vigthoria-cli 1.13.13 → 1.13.20

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.
@@ -56,8 +56,18 @@ export function resolveClientOsSlug() {
56
56
  }
57
57
  export function buildClientManifest(overrides = {}) {
58
58
  const ios = isIOSEnvironment() && !overrides.os;
59
+ const productId = overrides.product_id || process.env.VIGTHORIA_SOURCE_PRODUCT_ID || 'vigthoria-cli';
59
60
  return {
60
- product_id: overrides.product_id || 'vigthoria-cli',
61
+ product_id: productId,
62
+ context_contract_version: overrides.context_contract_version || '2.0',
63
+ source_product_id: overrides.source_product_id || process.env.VIGTHORIA_SOURCE_PRODUCT_ID || productId,
64
+ active_application_id: overrides.active_application_id || process.env.VIGTHORIA_ACTIVE_APPLICATION_ID || 'cli-agent-chat',
65
+ active_surface_id: overrides.active_surface_id || process.env.VIGTHORIA_ACTIVE_SURFACE_ID || 'agent-session',
66
+ target_product_id: overrides.target_product_id || 'none',
67
+ workspace_kind: overrides.workspace_kind || process.env.VIGTHORIA_WORKSPACE_KIND || 'local-development-workspace',
68
+ selected_engine_id: overrides.selected_engine_id || 'none',
69
+ capability_catalog_version: overrides.capability_catalog_version || process.env.VIGTHORIA_CAPABILITY_CATALOG_VERSION || '2026.08.03.1',
70
+ capability_scope_id: overrides.capability_scope_id || process.env.VIGTHORIA_CAPABILITY_SCOPE_ID || 'cli.ecosystem-user',
61
71
  version: overrides.version || readPackageVersion(),
62
72
  os: overrides.os || resolveClientOsSlug(),
63
73
  execution_mode: overrides.execution_mode || (ios ? 'mobile-terminal-sandbox' : 'local-user-machine'),
@@ -3,6 +3,10 @@ const AGENT_COMMANDS = new Set([
3
3
  'agent', 'chat', 'chat-resume', 'operator', 'legion', 'workflow',
4
4
  'history', 'replay', 'fork', 'cancel',
5
5
  ]);
6
+ // Subprocess protocols are not user-facing commands. Presenting one in the
7
+ // root picker caused `v4-menu` to be launched without its required output
8
+ // file, which is exactly the failure reported from CLI 1.13.13.
9
+ const INTERNAL_COMMANDS = new Set(['v4-menu']);
6
10
  function familyFor(commandPath) {
7
11
  const root = commandPath.split(' ')[0];
8
12
  if (root === 'repo')
@@ -15,6 +19,8 @@ export function buildCommandCatalog(program) {
15
19
  const entries = [];
16
20
  const visit = (command, parents) => {
17
21
  const commandPath = [...parents, command.name()].join(' ');
22
+ if (parents.length === 0 && INTERNAL_COMMANDS.has(commandPath))
23
+ return;
18
24
  entries.push({
19
25
  path: commandPath,
20
26
  description: command.description() || '',
@@ -195,11 +195,13 @@ export class Config {
195
195
  // Vigthoria server infrastructure operational models
196
196
  // ═══════════════════════════════════════════════════════════════
197
197
  const models = [
198
- { id: 'code', name: 'Vigthoria v3 Code 35B', description: 'Native 35B coding model on Blackwell (V3 pipeline)', tier: 'local', backendModel: 'vigthoria-v3-code-35b' },
199
- { id: 'code-35b', name: 'Vigthoria v3 Code 35B', description: 'Same flagship model as code', tier: 'local', backendModel: 'vigthoria-v3-code-35b' },
200
- { id: 'code-9b', name: 'Vigthoria v3 Code 9B', description: 'Efficient coding specialist for quick tasks', tier: 'local', backendModel: 'vigthoria-v3-code-9b' },
201
- { id: 'balanced', name: 'Vigthoria Balanced 4B', description: 'Balanced general-purpose local model', tier: 'local', backendModel: 'vigthoria-v3-balanced-4b' },
202
- { id: 'balanced-4b', name: 'Vigthoria Balanced 4B', description: 'Efficient 4B general-purpose model (Qwen3.5-4B based)', tier: 'local', backendModel: 'vigthoria-v3-balanced-4b' },
198
+ { id: 'architect', name: 'Vigthoria v4 Creative 27B', description: 'Architect, planning, deep reasoning, and creative systems work', tier: 'local', backendModel: 'Vigthoria-v4-Creative-27B' },
199
+ { id: 'code', name: 'Vigthoria v4 Code 27B', description: 'Dense production executor for coding, debugging, and repository changes', tier: 'local', backendModel: 'Vigthoria-v4-Code-27B' },
200
+ { id: 'assistant', name: 'Vigthoria v4 Assistant 9B', description: 'Low-latency FIM, completion, voice, and diagnostic model', tier: 'local', backendModel: 'Vigthoria-v4-Assistant-9B' },
201
+ { id: 'code-35b', name: 'Vigthoria v4 Code 27B', description: 'Legacy selector mapped to the V4 executor', tier: 'local', backendModel: 'Vigthoria-v4-Code-27B' },
202
+ { id: 'code-9b', name: 'Vigthoria v4 Assistant 9B', description: 'Legacy selector mapped to the V4 assistant', tier: 'local', backendModel: 'Vigthoria-v4-Assistant-9B' },
203
+ { id: 'balanced', name: 'Vigthoria v4 Assistant 9B', description: 'Legacy selector mapped to the V4 assistant', tier: 'local', backendModel: 'Vigthoria-v4-Assistant-9B' },
204
+ { id: 'balanced-4b', name: 'Vigthoria v4 Assistant 9B', description: 'Legacy selector mapped to the V4 assistant', tier: 'local', backendModel: 'Vigthoria-v4-Assistant-9B' },
203
205
  ];
204
206
  if (this.hasCloudAccess()) {
205
207
  models.push({ id: 'cloud-fast', name: 'Vigthoria Cloud Fast', description: 'Fast cloud responses for lighter work', tier: 'cloud', backendModel: 'vigthoria-cloud-fast' }, { id: 'cloud-balanced', name: 'Vigthoria Cloud Balanced', description: 'Default quality/cost balance for chat and coding', tier: 'cloud', backendModel: 'vigthoria-cloud-balanced' }, { id: 'cloud-code', name: 'Vigthoria Cloud Code', description: 'Economical cloud coding and completion', tier: 'cloud', backendModel: 'vigthoria-cloud-code' }, { id: 'cloud-power', name: 'Vigthoria Cloud Power', description: 'Premium general intelligence for demanding work', tier: 'cloud', backendModel: 'vigthoria-cloud-power' }, { id: 'cloud-maximum', name: 'Vigthoria Cloud Maximum', description: 'Maximum power for complex architecture and reviews', tier: 'cloud', backendModel: 'vigthoria-cloud-maximum' },
@@ -15,7 +15,11 @@ export declare function estimateJsonTokens(value: unknown): number;
15
15
  export declare function resolveInputBudget(runtimeNctx?: number, maxOutput?: number): number;
16
16
  /**
17
17
  * Char limit for the initial V3 context JSON payload.
18
- * ~45% of input token budget × 4 chars/token, clamped 32k–100k.
18
+ * The hydration payload is transport-only: the server writes workspaceFiles
19
+ * to an isolated directory and exposes only a compact filename summary to the
20
+ * model. It can therefore use the full calculated input envelope without
21
+ * consuming system/tool framing tokens. Clamp at 180k, far below the gateway
22
+ * body limit, while preserving compaction for genuinely large workspaces.
19
23
  */
20
24
  export declare function resolveV3ContextCharLimit(runtimeNctx?: number): number;
21
25
  export declare function compactToolListingOutput(name: string, output: string, charCap: number): string;
@@ -29,13 +29,16 @@ export function resolveInputBudget(runtimeNctx = DEFAULT_CODE_RUNTIME_CTX, maxOu
29
29
  }
30
30
  /**
31
31
  * Char limit for the initial V3 context JSON payload.
32
- * ~45% of input token budget × 4 chars/token, clamped 32k–100k.
32
+ * The hydration payload is transport-only: the server writes workspaceFiles
33
+ * to an isolated directory and exposes only a compact filename summary to the
34
+ * model. It can therefore use the full calculated input envelope without
35
+ * consuming system/tool framing tokens. Clamp at 180k, far below the gateway
36
+ * body limit, while preserving compaction for genuinely large workspaces.
33
37
  */
34
38
  export function resolveV3ContextCharLimit(runtimeNctx = DEFAULT_CODE_RUNTIME_CTX) {
35
39
  const inputBudget = resolveInputBudget(runtimeNctx);
36
- const initialTurnTokens = Math.floor(inputBudget * 0.45);
37
- const charLimit = initialTurnTokens * CHARS_PER_TOKEN_EST;
38
- return Math.min(100_000, Math.max(32_000, charLimit));
40
+ const hydrationChars = inputBudget * CHARS_PER_TOKEN_EST;
41
+ return Math.min(180_000, Math.max(32_000, hydrationChars));
39
42
  }
40
43
  export function compactToolListingOutput(name, output, charCap) {
41
44
  const text = String(output || '');
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Vigthoria Balanced 4B — fast agent path classifier (~0.7–2s on local inference :8016).
2
+ * Vigthoria v4 Assistant 9B — fast agent path classifier through the governed router.
3
3
  * Regex/trivial detection always wins; LLM router refines ambiguous build prompts only.
4
4
  */
5
5
  export type AgentRoutePath = 'template-instant' | 'v3-agent' | 'analysis-only';
@@ -23,7 +23,7 @@ export interface BalancedRouterResult {
23
23
  }
24
24
  export declare function parseBalancedRouterJson(raw: string): BalancedRouterJson | null;
25
25
  /**
26
- * Inference bases for Balanced 4B routing only.
26
+ * Inference bases for the V4 Assistant routing lane only.
27
27
  * Local developer machines must opt in (env) — avoids ~1.5s localhost probe on every Windows turn.
28
28
  */
29
29
  export declare function getInferenceRouterBaseUrls(selfHostedUrl: string | null): string[];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Vigthoria Balanced 4B — fast agent path classifier (~0.7–2s on local inference :8016).
2
+ * Vigthoria v4 Assistant 9B — fast agent path classifier through the governed router.
3
3
  * Regex/trivial detection always wins; LLM router refines ambiguous build prompts only.
4
4
  */
5
5
  const ROUTER_SYSTEM = `You are Vigthoria Agent Router. Reply with ONE JSON object only. No markdown, no HTML, no code fences.
@@ -14,8 +14,7 @@ fast_path: "template-instant" or null
14
14
 
15
15
  Example: {"path":"template-instant","task_kind":"web-build","fast_path":"template-instant","confidence":0.95,"reason":"trivial html popup page"}`;
16
16
  const INFERENCE_MODEL_IDS = [
17
- 'vigthoria-balanced-4b',
18
- 'vigthoria-v3-balanced-4b',
17
+ 'Vigthoria-v4-Assistant-9B',
19
18
  ];
20
19
  function normalizePath(value) {
21
20
  const p = String(value || '').trim().toLowerCase();
@@ -56,7 +55,7 @@ export function parseBalancedRouterJson(raw) {
56
55
  return null;
57
56
  }
58
57
  /**
59
- * Inference bases for Balanced 4B routing only.
58
+ * Inference bases for the V4 Assistant routing lane only.
60
59
  * Local developer machines must opt in (env) — avoids ~1.5s localhost probe on every Windows turn.
61
60
  */
62
61
  export function getInferenceRouterBaseUrls(selfHostedUrl) {
@@ -69,7 +68,7 @@ export function getInferenceRouterBaseUrls(selfHostedUrl) {
69
68
  || process.env.VIGTHORIA_AGENT_LLM_ROUTER === '1'
70
69
  || process.platform === 'linux';
71
70
  if (allowLocalhost) {
72
- urls.push('http://127.0.0.1:8016');
71
+ urls.push('http://127.0.0.1:4009');
73
72
  }
74
73
  return [...new Set(urls)];
75
74
  }
@@ -4,14 +4,15 @@
4
4
  */
5
5
  const CLI_SHAPING_BLOCK = /(?:^|\n\n)Platform:\s*(?:Windows|macOS|Linux)\.[\s\S]*?(?=\n\n[A-Z][^\n]{0,40}:|\s*$)/i;
6
6
  const READONLY_SHAPING_BLOCK = /(?:^|\n\n)(?:Read-only analysis mode is active\.|Diagnostic mode is active\.)[\s\S]*?(?=\n\n[A-Z][^\n]{0,40}:|\s*$)/i;
7
- const BUILD_VERBS = /\b(build|create|make|implement|complete|fix|repair|edit|modify|write|generate|add|finish|scaffold|develop|update|change|refactor|want|need|require|looking for|let's|let us|we need|we should|erstelle|erstellen|schreib|schreibe|bearbeite)\b/i;
8
- const ARTIFACT_NOUNS = /\b(file|files|project|game|spiel|app|website|html5|frontend|component|feature|code|workspace|repo|clone|replica|remake|page|site|screen|button|popup|modal|alert|canvas|sprite|level|levels|enemy|enemies|character|npc|world|scene|script|module|api|database|config|landing|dashboard|platformer|arcade|playable|collectible|scoreboard|leaderboard|pitfall|pacman|rogue|html|css|javascript|typescript)\b/i;
7
+ const BUILD_VERBS = /\b(build|create|make|implement|complete|redesign|overhaul|rebuild|transform|polish|art-direct|fix|repair|edit|modify|write|generate|add|finish|scaffold|develop|update|change|refactor|want|need|require|looking for|let's|let us|we need|we should|erstelle|erstellen|schreib|schreibe|bearbeite)\b/i;
8
+ const ARTIFACT_NOUNS = /\b(file|files|project|game|spiel|app|website|html5|frontend|component|feature|code|workspace|repo|clone|replica|remake|page|site|design|showcase|screen|button|popup|modal|alert|canvas|sprite|level|levels|enemy|enemies|character|npc|world|scene|script|module|api|database|config|landing|dashboard|platformer|arcade|playable|collectible|scoreboard|leaderboard|pitfall|pacman|rogue|html|css|javascript|typescript)\b/i;
9
9
  /** Canvas/playable games only — bare "html5" or "website" must NOT match. */
10
10
  const GAME_INTENT = /\b(game|spiel|playable|babylon(?:\.js|js)?|vge|webgl|3d\s+(?:game|runner|prototype|world|experience)|html5\s+(?:game|canvas)|html5\s+game|canvas\s+game|game\s+canvas|arcade|platformer|side[- ]?scroller|pitfall|pac[- ]?man|tetris|snake|breakout|pong|roguelike|metroidvania|tower\s+defense|clone\s+of\s+(?:a\s+)?(?:game|pitfall|pac|mario|zelda|arcade)|gameplay|collectible|boss\s+fight|level\s+design|sprite\s+sheet|wild\s+(?:boar|pig|forest)|forest\s+pig)\b/i;
11
11
  const WEB_PAGE_INTENT = /\b(website|web\s*site|webpage|web\s*page|landing\s+page|home\s*page|index\.html|html\s+page|static\s+page|single\s+page|popup|alert|modal|hello\s+world)\b/i;
12
+ const WEB_SHOWCASE_INTENT = /\b(web[- ]?design\s+showcase|frontend|marketing\s+site|dashboard|saas)\b/i;
12
13
  const CLONE_BUILD = /\bclone\s+of\b|\b(build|create|make)\s+(?:a|an|the|us|me)?\s*(?:clone|replica|remake|port)\b/i;
13
14
  const READ_ONLY_INTENT = /\b(analy[sz]e|analyse|analysis|audit|review|inspect|proof|understand|summari[sz]e|scan|read[\s-]?only|where we left|what is|how does|show me|tell me|identify\s+gaps?|gap\s+analysis|production\s+blockers?)\b/i;
14
- const EXPLICIT_WRITE_VERBS = /\b(implement|write|edit|modify|update|fix|repair|create|build|generate|scaffold|deploy|refactor|develop|integrate|correct|apply|patch)\b/i;
15
+ const EXPLICIT_WRITE_VERBS = /\b(implement|write|edit|modify|update|redesign|overhaul|rebuild|transform|polish|art-direct|fix|repair|create|build|generate|scaffold|deploy|refactor|develop|integrate|correct|apply|patch)\b/i;
15
16
  const TRIVIAL_HTML_PAGE = /\b(hello\s*world|simple\s+(?:html|web|page|site)|html5\s+website|html\s+5\s+website|popup|alert\s*\(|show\s+a\s+popup|one\s+page|single\s+html)\b/i;
16
17
  /** User explicitly grants write permission after an analysis or confirmation gate. */
17
18
  const WRITE_PERMISSION_GRANT = /\b(?:hereby\s+confirm|i\s+confirm|confirm(?:ed)?\s+that|give\s+(?:you|permission)|granting\s+permission|allow\s+(?:you|me\s+to)|you\s+(?:may|can|have\s+permission\s+to)|permission\s+to|authorized?\s+to|approve(?:d)?\s+(?:the\s+)?(?:changes?|writes?|edits?)|go\s+ahead\s+and(?:\s+write|\s+apply|\s+make|\s+do)?|do\s+all\s+the\s+changes|apply\s+(?:the\s+)?(?:changes?|fixes?|fix)|proceed\s+with\s+(?:the\s+)?(?:changes?|fixes?|implementation|writes?)|make\s+(?:the\s+)?changes|please\s+write)\b/i;
@@ -111,7 +112,7 @@ export function isContinueOrRetryPrompt(prompt) {
111
112
  }
112
113
  export function hasWebPageIntent(prompt) {
113
114
  const text = stripExecutionShaping(prompt);
114
- return WEB_PAGE_INTENT.test(text) || /\bhtml5\s+website\b/i.test(text);
115
+ return WEB_PAGE_INTENT.test(text) || WEB_SHOWCASE_INTENT.test(text) || /\bhtml5\s+website\b/i.test(text);
115
116
  }
116
117
  export function isTrivialHtmlPageRequest(prompt) {
117
118
  const text = stripExecutionShaping(prompt);
@@ -47,6 +47,24 @@ export interface Session {
47
47
  agentMode: boolean;
48
48
  operatorMode?: boolean;
49
49
  lastAgentRunOutcome?: Record<string, unknown> | null;
50
+ activeAgentRun?: AgentExecutionCheckpoint | null;
51
+ }
52
+ export interface AgentExecutionCheckpoint {
53
+ executionId: string;
54
+ parentExecutionId?: string | null;
55
+ contextId: string;
56
+ prompt: string;
57
+ originalPrompt: string;
58
+ workspacePath: string;
59
+ userTier: string | null;
60
+ taskType: string;
61
+ workflowType: string;
62
+ status: 'submitted' | 'running' | 'completed' | 'failed';
63
+ submittedAt: string;
64
+ updatedAt: string;
65
+ failedTaskIds: string[];
66
+ unfinishedTaskIds: string[];
67
+ error?: string | null;
50
68
  }
51
69
  export declare class SessionManager {
52
70
  private sessionsDir;
@@ -4,7 +4,7 @@ function stripInlineWorkspacePlaceholders(value) {
4
4
  // Only strip placeholders when they were appended to a segment (e.g. pitfall[Vigthoria service]).
5
5
  // Keep canonical scrubbed segments like /[internal]/ intact for dedicated mapping logic.
6
6
  return String(value || '')
7
- .replace(/(^|[^/])\[(?:internal|Vigthoria service|Vigthoria Agent|Vigthoria storage|temp|home|workspace)\](?=(?:\/|$))/ig, '$1')
7
+ .replace(/([^/])\[(?:internal|Vigthoria service|Vigthoria Agent|Vigthoria storage|temp|home|workspace)\](?=(?:\/|$))/ig, '$1')
8
8
  .replace(/\/+$/g, '');
9
9
  }
10
10
  /**
@@ -16,6 +16,9 @@ export function normalizeV3WorkspaceRelativePath(rawPath, rootPath) {
16
16
  if (!input) {
17
17
  return '';
18
18
  }
19
+ input = input
20
+ .replace(/^var\/?\[internal\]/i, '[internal]')
21
+ .replace(/^varwww\[internal\]/i, '[internal]');
19
22
  input = stripInlineWorkspacePlaceholders(input);
20
23
  const safeRelative = (candidate) => {
21
24
  const stripped = String(candidate || '').replace(/^\/+/, '');
@@ -64,6 +67,8 @@ export function normalizeV3WorkspaceRelativePath(rawPath, rootPath) {
64
67
  }
65
68
  const placeholderPatterns = [
66
69
  [/^(?:var\/)?www\/\[internal\](?:\/(.*))?$/i, 1],
70
+ [/^var\/?\[internal\](?:\/(.*))?$/i, 1],
71
+ [/^varwww\[internal\](?:\/(.*))?$/i, 1],
67
72
  [/^\[internal\](?:\/(.*))?$/i, 1],
68
73
  [/^\[Vigthoria service\](?:\/(.*))?$/i, 1],
69
74
  [/^\[Vigthoria Agent\](?:\/(.*))?$/i, 1],
@@ -134,6 +139,9 @@ export function normalizeV3WorkspaceRelativePath(rawPath, rootPath) {
134
139
  }
135
140
  const rootNoLeadingSlash = normalizedRoot.replace(/^\//, '');
136
141
  const rootBase = path.posix.basename(normalizedRoot);
142
+ if (input.replace(/\/+$/g, '').toLowerCase() === normalizedRoot.toLowerCase()) {
143
+ return '';
144
+ }
137
145
  const prefixes = [
138
146
  `${normalizedRoot}/`,
139
147
  `${rootNoLeadingSlash}/`,
@@ -150,6 +158,11 @@ export function normalizeV3WorkspaceRelativePath(rawPath, rootPath) {
150
158
  return safeRelative(input.slice(embeddedIndex + embeddedRoot.length));
151
159
  }
152
160
  }
161
+ // An unmatched POSIX absolute path belongs to another filesystem boundary.
162
+ // Never reinterpret it as a workspace-relative path by merely trimming '/'.
163
+ if (input.startsWith('/')) {
164
+ return '';
165
+ }
153
166
  const relative = safeRelative(input);
154
167
  if (relative === 'workspace') {
155
168
  return '';
@@ -167,7 +180,11 @@ export function isV3WorkspaceRootAliasPath(rawPath, rootPath) {
167
180
  if (!original || original === '.') {
168
181
  return true;
169
182
  }
170
- const sanitized = stripInlineWorkspacePlaceholders(original).replace(/\\/g, '/').trim();
183
+ const compactCanonical = original
184
+ .replace(/\\/g, '/')
185
+ .replace(/^var\/?\[internal\]/i, '[internal]')
186
+ .replace(/^varwww\[internal\]/i, '[internal]');
187
+ const sanitized = stripInlineWorkspacePlaceholders(compactCanonical).trim();
171
188
  if (!sanitized || sanitized === '.' || sanitized === '/') {
172
189
  return true;
173
190
  }
@@ -181,6 +198,9 @@ export function isV3WorkspaceRootAliasPath(rawPath, rootPath) {
181
198
  || lowered === '[internal]'
182
199
  || lowered === 'www/[internal]'
183
200
  || lowered === 'var/www/[internal]'
201
+ || lowered === 'var[internal]'
202
+ || lowered === 'var/[internal]'
203
+ || lowered === 'varwww[internal]'
184
204
  || lowered === '[vigthoria service]'
185
205
  || lowered === 'var/www/[vigthoria service]') {
186
206
  return true;
package/install.ps1 CHANGED
@@ -5,7 +5,7 @@
5
5
  $ErrorActionPreference = "Stop"
6
6
 
7
7
  # Configuration
8
- $CLI_VERSION = "1.13.13"
8
+ $CLI_VERSION = "1.13.20"
9
9
  $INSTALL_DIR = "$env:USERPROFILE\.vigthoria"
10
10
  $NPM_PACKAGE = "vigthoria-cli"
11
11
  $GIT_PACKAGE_URL = "git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
package/install.sh CHANGED
@@ -26,7 +26,7 @@ else
26
26
  fi
27
27
 
28
28
  # Configuration
29
- CLI_VERSION="1.13.13"
29
+ CLI_VERSION="1.13.20"
30
30
  INSTALL_DIR="$HOME/.vigthoria"
31
31
  REPO_URL="https://market.vigthoria.io/vigthoria/vigthoria-cli"
32
32
  GIT_PACKAGE_URL="git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.13.13",
3
+ "version": "1.13.20",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,9 @@
72
72
  "test:legion:billing:e2e": "npm run build && node scripts/test-legion-godmode-billing-e2e.js",
73
73
  "test:windows:v3-sync": "npm run build && node scripts/test-windows-v3-sync-recovery.js",
74
74
  "test:v3-workspace-path": "npm run build && node scripts/test-v3-workspace-path.js",
75
+ "test:v3-server-tool-execution": "npm run build && node scripts/test-v3-server-tool-execution.js",
75
76
  "test:session:project-match": "npm run build && node scripts/test-session-project-match.mjs",
77
+ "test:external-client-resume": "npm run build && node scripts/test-external-client-resume.mjs",
76
78
  "test:v3-stream-mutation": "npm run build && node scripts/test-v3-stream-mutation.js",
77
79
  "test:context:budget": "npm run build && node scripts/test-context-budget.js",
78
80
  "test:v3-client-tool-quality": "npm run build && node scripts/test-v3-client-tool-quality.mjs",
@@ -5,6 +5,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
5
  cd "$ROOT"
6
6
 
7
7
  CLI="node dist/index.js"
8
+ SERVICE_IDENTITY_MODE="${VIGTHORIA_TEST_SERVICE_IDENTITY:-0}"
8
9
  unset V3_SERVICE_KEY
9
10
  unset HYPERLOOP_SERVICE_KEY
10
11
  # Release validation runs against local model-router in this environment
@@ -27,6 +28,7 @@ printf '%s
27
28
  ' "$AUTH_JSON" > /tmp/vig-auth-preflight.json
28
29
  python3 - << 'PY'
29
30
  import json
31
+ import re
30
32
  with open('/tmp/vig-auth-preflight.json','r',encoding='utf-8') as f:
31
33
  j=json.load(f)
32
34
  msg='Vigthoria Gate way user authentification failed. Please log out and login again.'
@@ -35,6 +37,15 @@ assert j.get('error') == msg, f"unexpected auth message: {j.get('error')}"
35
37
  print('[pass] auth preflight message')
36
38
  PY
37
39
 
40
+ if [[ "$SERVICE_IDENTITY_MODE" == "1" ]]; then
41
+ # From this point onward the no-go suite exercises server-local model and
42
+ # tool routes without borrowing a human account session. The invalid-token
43
+ # gateway assertion above always runs against the canonical public boundary.
44
+ export VIGTHORIA_LOCAL_TEST_MODE=1
45
+ export VIGTHORIA_LOCAL_TEST_TOKEN="vigthoria-release-service-identity"
46
+ export VIGTHORIA_AUTH_TOKEN="$VIGTHORIA_LOCAL_TEST_TOKEN"
47
+ fi
48
+
38
49
  echo "[1.1] ranker includes agent.py top10 for SSE prompt"
39
50
  node - << 'EOF2'
40
51
  import('./dist/utils/context-ranker.js').then((m)=>{
@@ -62,12 +73,22 @@ if (!tsc || !tsc.ran || !tsc.passed) process.exit(1);
62
73
  EOF2
63
74
 
64
75
  echo "[6.2] balanced-4b no-agent path"
65
- $CLI chat --no-agent --model balanced-4b --prompt "reply exactly: ok" --json >/tmp/vig-balanced.json
76
+ for attempt in 1 2 3; do
77
+ if $CLI chat --no-agent --model balanced-4b --prompt "reply exactly: ok" --json >/tmp/vig-balanced.json; then
78
+ break
79
+ fi
80
+ if [[ "$attempt" == "3" ]]; then
81
+ echo "[fail] balanced-4b remained unavailable after 3 attempts"
82
+ exit 1
83
+ fi
84
+ echo "[retry] balanced-4b transient failure ($attempt/3)"
85
+ sleep 2
86
+ done
66
87
  python3 - << 'PY'
67
88
  import json
68
89
  j=json.load(open('/tmp/vig-balanced.json'))
69
90
  assert j.get('success') is True
70
- assert j.get('model') in ('vigthoria-balanced-4b', 'vigthoria-v3-balanced-4b'), j
91
+ assert j.get('model') in ('Vigthoria-v4-Assistant-9B', 'vigthoria-balanced-4b', 'vigthoria-v3-balanced-4b'), j
71
92
  print('[pass] balanced-4b')
72
93
  PY
73
94
 
@@ -76,13 +97,17 @@ $CLI hyper-loop status >/tmp/vig-hyperloop.txt
76
97
  $CLI devtools connect >/tmp/vig-devtools.txt
77
98
 
78
99
  echo "[6.11] operator flow"
79
- $CLI operator --prompt "reply with exactly: OK" --json >/tmp/vig-operator.json
80
- python3 - << 'PY'
100
+ if [[ "$SERVICE_IDENTITY_MODE" == "1" ]]; then
101
+ echo "[skip] paid-user operator probe (isolated release service identity)"
102
+ else
103
+ $CLI operator --prompt "reply with exactly: OK" --json >/tmp/vig-operator.json
104
+ python3 - << 'PY'
81
105
  import json
82
106
  j=json.load(open('/tmp/vig-operator.json'))
83
107
  assert j.get('success') is True, j
84
108
  print('[pass] operator flow')
85
109
  PY
110
+ fi
86
111
 
87
112
  echo "[7.1/7.3/7.4] local service health"
88
113
  for u in http://localhost:8030/health http://localhost:4009/health http://localhost:4011/health; do
@@ -95,10 +120,12 @@ echo "[7.2/7.8/12.3] models inventory"
95
120
  curl -s http://localhost:4009/v1/models >/tmp/vig-models.json
96
121
  python3 - << 'PY'
97
122
  import json
123
+ import re
98
124
  ids={m.get('id','') for m in json.load(open('/tmp/vig-models.json')).get('data',[])}
99
125
  if ids:
100
126
  has_router = any(
101
127
  m in ids for m in (
128
+ 'Vigthoria-v4-Assistant-9B',
102
129
  'vigthoria-balanced-4b', 'vigthoria-balanced-4b:latest',
103
130
  'vigthoria-v3-balanced-4b', 'vigthoria-v3-balanced-4b:latest',
104
131
  'vigthoria-fast-9b', 'vigthoria-fast-9b:latest',
@@ -106,11 +133,12 @@ if ids:
106
133
  )
107
134
  has_creative = any(
108
135
  m in ids for m in (
136
+ 'Vigthoria-v4-Creative-27B',
109
137
  'vigthoria-creative-9b-v4', 'vigthoria-creative-9b-v4:latest',
110
138
  'vigthoria-fast-9b', 'vigthoria-fast-9b:latest',
111
139
  )
112
140
  )
113
- has_code = any('vigthoria-v3-code-35b' in i for i in ids)
141
+ has_code = 'Vigthoria-v4-Code-27B' in ids or any(re.search(r'^vigthoria-v3(?:\.\d+)?-code-35b(?:-|:|$)', i) for i in ids)
114
142
  assert has_router, f'missing router model in inventory: {sorted(ids)}'
115
143
  assert has_creative, f'missing creative/fast model in inventory: {sorted(ids)}'
116
144
  assert has_code, f'missing code model in inventory: {sorted(ids)}'
@@ -136,12 +164,22 @@ rg -n "coder.vigthoria.io/releases" install.ps1 install.sh README.md >/tmp/vig-r
136
164
  cat /tmp/vig-release-urls.txt
137
165
 
138
166
  echo "[12.1] no-agent governance fallback"
139
- $CLI chat --no-agent --model creative --prompt "say ok" --json >/tmp/vig-creative.json
167
+ for attempt in 1 2 3; do
168
+ if $CLI chat --no-agent --model creative-v4 --prompt "say ok" --json >/tmp/vig-creative.json; then
169
+ break
170
+ fi
171
+ if [[ "$attempt" == "3" ]]; then
172
+ echo "[fail] governance fallback remained unavailable after 3 attempts"
173
+ exit 1
174
+ fi
175
+ echo "[retry] governance fallback transient failure ($attempt/3)"
176
+ sleep 2
177
+ done
140
178
  python3 - << 'PY'
141
179
  import json
142
180
  j=json.load(open('/tmp/vig-creative.json'))
143
181
  assert j.get('success') is True
144
- assert j.get('model') == 'vigthoria-v3-code-35b', j
182
+ assert j.get('model') == 'Vigthoria-v4-Code-27B', j
145
183
  md=j.get('metadata') or {}
146
184
  fb=md.get('modelFallback') or {}
147
185
  assert fb.get('reason') == 'governance-blocked-model', j