vskill 1.2.0 → 1.2.2

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 (106) hide show
  1. package/agents.json +1 -1
  2. package/dist/api/client.js +7 -6
  3. package/dist/api/client.js.map +1 -1
  4. package/dist/blocklist/blocklist.d.ts +12 -0
  5. package/dist/blocklist/blocklist.js +19 -0
  6. package/dist/blocklist/blocklist.js.map +1 -1
  7. package/dist/commands/add.js +71 -43
  8. package/dist/commands/add.js.map +1 -1
  9. package/dist/commands/auth.js +32 -1
  10. package/dist/commands/auth.js.map +1 -1
  11. package/dist/commands/diff.js +8 -0
  12. package/dist/commands/diff.js.map +1 -1
  13. package/dist/commands/eval/run.js +5 -0
  14. package/dist/commands/eval/run.js.map +1 -1
  15. package/dist/commands/info.js +7 -0
  16. package/dist/commands/info.js.map +1 -1
  17. package/dist/commands/outdated.js +24 -7
  18. package/dist/commands/outdated.js.map +1 -1
  19. package/dist/commands/pin.js +7 -2
  20. package/dist/commands/pin.js.map +1 -1
  21. package/dist/commands/submit.js +8 -0
  22. package/dist/commands/submit.js.map +1 -1
  23. package/dist/commands/update.js +14 -5
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/commands/versions.js +11 -0
  26. package/dist/commands/versions.js.map +1 -1
  27. package/dist/discovery/github-tree.js +14 -2
  28. package/dist/discovery/github-tree.js.map +1 -1
  29. package/dist/eval/anthropic-catalog.d.ts +7 -1
  30. package/dist/eval/anthropic-catalog.js +81 -8
  31. package/dist/eval/anthropic-catalog.js.map +1 -1
  32. package/dist/eval/credential-resolver.js +5 -3
  33. package/dist/eval/credential-resolver.js.map +1 -1
  34. package/dist/eval/integration-runner.js +4 -4
  35. package/dist/eval/integration-runner.js.map +1 -1
  36. package/dist/eval/llm.d.ts +2 -0
  37. package/dist/eval/llm.js +39 -8
  38. package/dist/eval/llm.js.map +1 -1
  39. package/dist/eval/model-catalog.d.ts +27 -0
  40. package/dist/eval/model-catalog.js +101 -0
  41. package/dist/eval/model-catalog.js.map +1 -0
  42. package/dist/eval/pricing.d.ts +5 -0
  43. package/dist/eval/pricing.js +16 -2
  44. package/dist/eval/pricing.js.map +1 -1
  45. package/dist/eval/test-case-parser.js +35 -16
  46. package/dist/eval/test-case-parser.js.map +1 -1
  47. package/dist/eval-server/api-routes.d.ts +2 -10
  48. package/dist/eval-server/api-routes.js +35 -85
  49. package/dist/eval-server/api-routes.js.map +1 -1
  50. package/dist/eval-server/install-skill-routes.d.ts +2 -0
  51. package/dist/eval-server/install-skill-routes.js +7 -0
  52. package/dist/eval-server/install-skill-routes.js.map +1 -1
  53. package/dist/eval-server/model-compare-routes.js +4 -2
  54. package/dist/eval-server/model-compare-routes.js.map +1 -1
  55. package/dist/eval-server/oauth-github-routes.js +32 -2
  56. package/dist/eval-server/oauth-github-routes.js.map +1 -1
  57. package/dist/eval-server/origin-resolver.d.ts +6 -0
  58. package/dist/eval-server/origin-resolver.js +35 -5
  59. package/dist/eval-server/origin-resolver.js.map +1 -1
  60. package/dist/eval-server/platform-proxy.d.ts +3 -3
  61. package/dist/eval-server/platform-proxy.js +10 -25
  62. package/dist/eval-server/platform-proxy.js.map +1 -1
  63. package/dist/eval-server/skill-create-routes.d.ts +1 -1
  64. package/dist/eval-server/skill-create-routes.js +1 -71
  65. package/dist/eval-server/skill-create-routes.js.map +1 -1
  66. package/dist/eval-server/skill-md-emitter.d.ts +17 -0
  67. package/dist/eval-server/skill-md-emitter.js +70 -0
  68. package/dist/eval-server/skill-md-emitter.js.map +1 -0
  69. package/dist/eval-server/studio-privacy.d.ts +26 -0
  70. package/dist/eval-server/studio-privacy.js +129 -0
  71. package/dist/eval-server/studio-privacy.js.map +1 -0
  72. package/dist/eval-ui/assets/{AdvancedTab-DOgbx7u0.js → AdvancedTab-CSWhj_MZ.js} +1 -1
  73. package/dist/eval-ui/assets/{CreateSkillPage-ENMve2K8.js → CreateSkillPage-BJzNKgad.js} +1 -1
  74. package/dist/eval-ui/assets/{FindSkillsPalette-BMVKCk6E.js → FindSkillsPalette-XckIggJi.js} +2 -2
  75. package/dist/eval-ui/assets/{GeneralTab-AwK9sIkP.js → GeneralTab-Gbc-K6UI.js} +1 -1
  76. package/dist/eval-ui/assets/{PrivacyTab-BtNrxpVV.js → PrivacyTab-BXCIX8cQ.js} +1 -1
  77. package/dist/eval-ui/assets/SearchPaletteCore-CTZ8CI14.js +14 -0
  78. package/dist/eval-ui/assets/SkillDetailPanel-NPnDnA3H.js +1 -0
  79. package/dist/eval-ui/assets/{UpdateDropdown-C4BH7W_M.js → UpdateDropdown-CPP1t9LD.js} +1 -1
  80. package/dist/eval-ui/assets/{UpdatesTab-DTmo-vVb.js → UpdatesTab-BFGUaUtu.js} +1 -1
  81. package/dist/eval-ui/assets/{main-tzMA8J07.js → main-jiMosYzo.js} +40 -41
  82. package/dist/eval-ui/assets/{preferences-DCdw0Kvu.js → preferences-D2BPT0OT.js} +2 -2
  83. package/dist/eval-ui/assets/useDesktopBridge-BKz-gcRg.js +2 -0
  84. package/dist/eval-ui/index.html +2 -2
  85. package/dist/eval-ui/preferences.html +2 -2
  86. package/dist/lib/frontmatter.d.ts +2 -5
  87. package/dist/lib/frontmatter.js +15 -40
  88. package/dist/lib/frontmatter.js.map +1 -1
  89. package/dist/lib/github-fetch.d.ts +2 -0
  90. package/dist/lib/github-fetch.js +27 -1
  91. package/dist/lib/github-fetch.js.map +1 -1
  92. package/dist/lib/keychain.js +8 -1
  93. package/dist/lib/keychain.js.map +1 -1
  94. package/dist/lib/private-source.d.ts +77 -0
  95. package/dist/lib/private-source.js +392 -0
  96. package/dist/lib/private-source.js.map +1 -0
  97. package/dist/lib/repo-visibility.d.ts +16 -0
  98. package/dist/lib/repo-visibility.js +43 -3
  99. package/dist/lib/repo-visibility.js.map +1 -1
  100. package/dist/utils/version.d.ts +5 -10
  101. package/dist/utils/version.js +82 -40
  102. package/dist/utils/version.js.map +1 -1
  103. package/package.json +1 -1
  104. package/dist/eval-ui/assets/SearchPaletteCore-C9G-ySXc.js +0 -14
  105. package/dist/eval-ui/assets/SkillDetailPanel-BCJj8p79.js +0 -1
  106. package/dist/eval-ui/assets/useDesktopBridge-9oZFQsrw.js +0 -2
@@ -0,0 +1,101 @@
1
+ // Shared provider picker catalog. Explicit new IDs do not change saved/default choices.
2
+ import { ANTHROPIC_CATALOG_SNAPSHOT, findAnthropicModel } from "./anthropic-catalog.js";
3
+ // Verified 2026-10-09 against https://developers.openai.com/api/docs/models/
4
+ // gpt-6.1-sol, gpt-6-astra and gpt-6-luna. Standard short-context pricing;
5
+ // above 272K input tokens, the full request costs 2x input and 1.5x output.
6
+ export const CURRENT_OPENAI_MODELS = [
7
+ { id: "gpt-6.1-sol", displayName: "GPT-6.1 Sol", inputPerMillion: 2, outputPerMillion: 10 },
8
+ { id: "gpt-6-astra", displayName: "GPT-6 Astra", inputPerMillion: 10, outputPerMillion: 50 },
9
+ { id: "gpt-6-luna", displayName: "GPT-6 Luna", inputPerMillion: 0.1, outputPerMillion: 0.5 },
10
+ ];
11
+ // 0711 — Anthropic models + pricing now derive from the dated catalog
12
+ // snapshot at `src/eval/anthropic-catalog.ts`. Manual maintenance of this
13
+ // list led to stale prices (Opus 4.7 shown at $15/$75 instead of $5/$25)
14
+ // because three different files held copies of the same fact. The catalog
15
+ // file is the single source of truth; CI fails if its snapshotDate is
16
+ // older than 6 months.
17
+ function buildAnthropicProviderModels() {
18
+ return ANTHROPIC_CATALOG_SNAPSHOT.models
19
+ .filter((m) => m.status === "active")
20
+ .map((m) => ({
21
+ id: m.id,
22
+ label: `${m.displayName} (API)${m.pricing.longContext ? " · base rate ≤100K input" : ""}`,
23
+ pricing: {
24
+ prompt: m.pricing.promptUsdPer1M,
25
+ completion: m.pricing.completionUsdPer1M,
26
+ },
27
+ }));
28
+ }
29
+ function aliasInfo(alias, fallbackLabel) {
30
+ const entry = findAnthropicModel(alias);
31
+ if (!entry)
32
+ return { label: fallbackLabel };
33
+ return { label: entry.displayName, resolvedId: entry.id };
34
+ }
35
+ export const PROVIDER_MODELS = {
36
+ // Opus first so it is the default when no override is set
37
+ // (getEffectiveRawModel returns models[0]). Labels come from the catalog so
38
+ // the picker shows the exact dated version (e.g. "Claude Opus 4.7"), not the
39
+ // bare family name — keeps the Studio truthful when a model is bumped.
40
+ "claude-cli": [
41
+ { id: "opus", ...aliasInfo("opus", "Claude Opus") },
42
+ { id: "sonnet", ...aliasInfo("sonnet", "Claude Sonnet") },
43
+ { id: "haiku", ...aliasInfo("haiku", "Claude Haiku") },
44
+ ...ANTHROPIC_CATALOG_SNAPSHOT.models
45
+ .filter((m) => m.capabilities.includes("modern_thinking_budget"))
46
+ .map((m) => ({ id: m.id, label: m.displayName, resolvedId: m.id })),
47
+ ],
48
+ "anthropic": buildAnthropicProviderModels(),
49
+ // Ollama's model list is dynamic — populated by probeOllama() from GET
50
+ // /api/tags. Empty by default (parity with "lm-studio") so an unreachable
51
+ // or timed-out probe surfaces zero models instead of leaking a hardcoded
52
+ // fallback that isn't actually installed (0876 US-001).
53
+ "ollama": [],
54
+ "gemini-cli": [
55
+ { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" },
56
+ { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" },
57
+ ],
58
+ "codex-cli": [
59
+ { id: "o3", label: "OpenAI o3" },
60
+ { id: "o4-mini", label: "OpenAI o4-mini" },
61
+ ...CURRENT_OPENAI_MODELS.map((m) => ({ id: m.id, label: m.displayName })),
62
+ ],
63
+ "openai": [
64
+ { id: "gpt-4o-mini", label: "GPT-4o mini (API)", pricing: { prompt: 0.15, completion: 0.60 } },
65
+ { id: "gpt-4o", label: "GPT-4o (API)", pricing: { prompt: 2.50, completion: 10 } },
66
+ { id: "gpt-4.1", label: "GPT-4.1 (API)", pricing: { prompt: 2, completion: 8 } },
67
+ { id: "gpt-4.1-mini", label: "GPT-4.1 mini (API)", pricing: { prompt: 0.40, completion: 1.60 } },
68
+ { id: "o4-mini", label: "o4-mini (API)", pricing: { prompt: 1.10, completion: 4.40 } },
69
+ ...CURRENT_OPENAI_MODELS.map((m) => ({
70
+ id: m.id, label: `${m.displayName} (API) · base rate ≤272K input`,
71
+ pricing: { prompt: m.inputPerMillion, completion: m.outputPerMillion },
72
+ })),
73
+ ],
74
+ "openrouter": [
75
+ // Anthropic via OpenRouter
76
+ { id: "anthropic/claude-opus-4", label: "Claude Opus 4 (via OpenRouter)" },
77
+ { id: "anthropic/claude-sonnet-4", label: "Claude Sonnet 4 (via OpenRouter)" },
78
+ { id: "anthropic/claude-haiku-4", label: "Claude Haiku 4 (via OpenRouter)" },
79
+ // OpenAI via OpenRouter (0698 polish — Anton wants OpenAI first-class)
80
+ { id: "openai/gpt-5", label: "GPT-5 (via OpenRouter)" },
81
+ { id: "openai/gpt-5-mini", label: "GPT-5 mini (via OpenRouter)" },
82
+ { id: "openai/o4-mini", label: "o4-mini (via OpenRouter)" },
83
+ { id: "openai/o3", label: "OpenAI o3 (via OpenRouter)" },
84
+ { id: "openai/gpt-4.1", label: "GPT-4.1 (via OpenRouter)" },
85
+ // Google + Meta
86
+ { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro (via OpenRouter)" },
87
+ { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash (via OpenRouter)" },
88
+ { id: "meta-llama/llama-3.3-70b-instruct", label: "Llama 3.3 70B (via OpenRouter)" },
89
+ ],
90
+ // LM Studio's default model list is empty because the actual list depends on
91
+ // what models the user has loaded. The probe at probeLmStudio() populates
92
+ // this dynamically from GET /v1/models.
93
+ "lm-studio": [],
94
+ // 0857: `stub` is a deterministic TEST SEAM (src/eval/llm.ts createStubClient),
95
+ // NOT a user-facing provider. This empty list exists only to satisfy the
96
+ // `Record<ProviderName, ModelOption[]>` exhaustiveness check — `stub` is
97
+ // deliberately excluded from `detectAvailableProviders()` and
98
+ // `KNOWN_PROVIDER_NAMES`, so it never reaches /api/config or the picker.
99
+ "stub": [],
100
+ };
101
+ //# sourceMappingURL=model-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-catalog.js","sourceRoot":"","sources":["../../src/eval/model-catalog.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,11 @@ export interface ModelPricing {
3
3
  inputPerMillion: number;
4
4
  outputPerMillion: number;
5
5
  updatedAt: string;
6
+ longContext?: {
7
+ aboveInputTokens: number;
8
+ inputPerMillion: number;
9
+ outputPerMillion: number;
10
+ };
6
11
  }
7
12
  /**
8
13
  * Get the billing mode for a provider.
@@ -7,6 +7,7 @@
7
7
  // catalog (tracked in 0711 follow-ups).
8
8
  // ---------------------------------------------------------------------------
9
9
  import { ANTHROPIC_CATALOG_SNAPSHOT } from "./anthropic-catalog.js";
10
+ import { CURRENT_OPENAI_MODELS } from "./model-catalog.js";
10
11
  // ---------------------------------------------------------------------------
11
12
  // Pricing table — update rates here when providers change pricing
12
13
  // ---------------------------------------------------------------------------
@@ -17,6 +18,11 @@ function buildAnthropicPricing() {
17
18
  inputPerMillion: m.pricing.promptUsdPer1M,
18
19
  outputPerMillion: m.pricing.completionUsdPer1M,
19
20
  updatedAt: ANTHROPIC_CATALOG_SNAPSHOT.snapshotDate,
21
+ ...(m.pricing.longContext ? { longContext: {
22
+ aboveInputTokens: m.pricing.longContext.aboveInputTokens,
23
+ inputPerMillion: m.pricing.longContext.promptUsdPer1M,
24
+ outputPerMillion: m.pricing.longContext.completionUsdPer1M,
25
+ } } : {}),
20
26
  };
21
27
  }
22
28
  return out;
@@ -24,6 +30,12 @@ function buildAnthropicPricing() {
24
30
  const PRICING = {
25
31
  anthropic: buildAnthropicPricing(),
26
32
  openai: {
33
+ ...Object.fromEntries(CURRENT_OPENAI_MODELS.map((m) => [m.id, {
34
+ inputPerMillion: m.inputPerMillion,
35
+ outputPerMillion: m.outputPerMillion,
36
+ updatedAt: "2026-10-09",
37
+ longContext: { aboveInputTokens: 272_000, inputPerMillion: 2 * m.inputPerMillion, outputPerMillion: 1.5 * m.outputPerMillion },
38
+ }])),
27
39
  "o4-mini": { inputPerMillion: 1.10, outputPerMillion: 4.40, updatedAt: "2025-05-01" },
28
40
  "gpt-4.1": { inputPerMillion: 2, outputPerMillion: 8, updatedAt: "2025-05-01" },
29
41
  "gpt-4.1-mini": { inputPerMillion: 0.40, outputPerMillion: 1.60, updatedAt: "2025-05-01" },
@@ -125,8 +137,10 @@ export function calculateCost(provider, model, inputTokens, outputTokens) {
125
137
  const pricing = getProviderPricing(provider, model);
126
138
  if (!pricing)
127
139
  return null;
128
- const inputCost = (inputTokens / 1_000_000) * pricing.inputPerMillion;
129
- const outputCost = (outputTokens / 1_000_000) * pricing.outputPerMillion;
140
+ const rates = pricing.longContext && inputTokens > pricing.longContext.aboveInputTokens
141
+ ? pricing.longContext : pricing;
142
+ const inputCost = (inputTokens / 1_000_000) * rates.inputPerMillion;
143
+ const outputCost = (outputTokens / 1_000_000) * rates.outputPerMillion;
130
144
  return inputCost + outputCost;
131
145
  }
132
146
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/eval/pricing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/eval/pricing.ts"],"names":[],"mappings":"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"}
@@ -8,15 +8,15 @@
8
8
  //
9
9
  // See increment 0776 for the why.
10
10
  // ---------------------------------------------------------------------------
11
- const SECTION_RE = /## Test Cases\s*\n([\s\S]*?)(?=\n## |\n---|\n$|$)/i;
11
+ const HEADING_RE = /^## Test Cases[ \t]*\r?\n/im;
12
12
  const PAIR_RE = /-\s*Prompt:\s*"([^"]+)"\s*\n\s*Expected:\s*"([^"]+)"/gi;
13
13
  export function parseTestCases(content) {
14
14
  if (!content)
15
15
  return [];
16
- const sectionMatch = content.match(SECTION_RE);
17
- if (!sectionMatch)
16
+ const bounds = findSection(content);
17
+ if (!bounds)
18
18
  return [];
19
- const section = sectionMatch[1];
19
+ const section = content.slice(bounds.bodyStart, bounds.end);
20
20
  const cases = [];
21
21
  // Reset lastIndex via a fresh regex each call to keep this function pure
22
22
  const pair = new RegExp(PAIR_RE.source, "gi");
@@ -36,25 +36,44 @@ export function serializeTestCases(prompts) {
36
36
  // section entirely (keeps SKILL.md clean when the author clears fixtures).
37
37
  export function upsertTestCasesIntoSkillMd(content, prompts) {
38
38
  const trimmed = content.replace(/\s+$/, "");
39
- const hasSection = SECTION_RE.test(trimmed);
39
+ const section = findSection(trimmed);
40
40
  if (prompts.length === 0) {
41
- if (!hasSection)
41
+ if (!section)
42
42
  return content;
43
- return removeSection(trimmed) + "\n";
43
+ return (trimmed.slice(0, section.start) + trimmed.slice(section.end))
44
+ .replace(/\n{3,}/g, "\n\n").trimEnd() + "\n";
44
45
  }
45
46
  const block = serializeTestCases(prompts).trimEnd();
46
- if (hasSection) {
47
- return trimmed.replace(SECTION_RE, block) + "\n";
47
+ if (section) {
48
+ // Slices preserve literal $&, $` and $' in user-authored prompts.
49
+ return trimmed.slice(0, section.start) + block + trimmed.slice(section.end) + "\n";
48
50
  }
49
51
  return trimmed + "\n\n" + block + "\n";
50
52
  }
51
- function removeSection(content) {
52
- // Match the heading + body + trailing whitespace up to the next section
53
- // boundary, then collapse the gap to a single blank line.
54
- return content
55
- .replace(/\n*## Test Cases\s*\n[\s\S]*?(?=\n## |\n---|\n$|$)/i, "")
56
- .replace(/\n{3,}/g, "\n\n")
57
- .replace(/\s+$/, "");
53
+ /** Locate real section boundaries, ignoring headings inside a quoted prompt.
54
+ * Keep raw prompt text for compatibility with existing published SKILL.md files.
55
+ */
56
+ function findSection(content) {
57
+ const heading = HEADING_RE.exec(content);
58
+ if (!heading)
59
+ return null;
60
+ const bodyStart = heading.index + heading[0].length;
61
+ const body = content.slice(bodyStart);
62
+ const pairs = [...body.matchAll(new RegExp(PAIR_RE.source, "gi"))];
63
+ const boundaries = body.matchAll(/^##[ \t]+|^---[ \t]*(?:\r?$)/gm);
64
+ for (const boundary of boundaries) {
65
+ const index = boundary.index;
66
+ if (pairs.some((pair) => index >= pair.index && index < pair.index + pair[0].length))
67
+ continue;
68
+ // Leave the newline before the next heading intact when replacing.
69
+ let end = bodyStart + index;
70
+ if (content[end - 1] === "\n")
71
+ end--;
72
+ if (content[end - 1] === "\r")
73
+ end--;
74
+ return { start: heading.index, bodyStart, end };
75
+ }
76
+ return { start: heading.index, bodyStart, end: content.length };
58
77
  }
59
78
  function textToExpected(raw) {
60
79
  const norm = raw.trim().toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"test-case-parser.js","sourceRoot":"","sources":["../../src/eval/test-case-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-case-parser.js","sourceRoot":"","sources":["../../src/eval/test-case-parser.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  import type { Router } from "./router.js";
2
2
  import type { SkillInfo } from "../eval/skill-scanner.js";
3
+ import { type ModelOption } from "../eval/model-catalog.js";
4
+ export { PROVIDER_MODELS } from "../eval/model-catalog.js";
3
5
  import type { ProviderName } from "../eval/llm.js";
4
6
  import type { AgentDefinition } from "../agents/agents-registry.js";
5
7
  export interface InstalledAgentEntry {
@@ -159,16 +161,6 @@ export declare function buildSkillMetadata(skillDir: string, origin: "source" |
159
161
  * vitest can simulate a fresh server boot per-case.
160
162
  */
161
163
  export declare function resetStudioRestoreState(): void;
162
- interface ModelOption {
163
- id: string;
164
- label: string;
165
- pricing?: {
166
- prompt: number;
167
- completion: number;
168
- };
169
- resolvedId?: string;
170
- }
171
- export declare const PROVIDER_MODELS: Record<ProviderName, ModelOption[]>;
172
164
  type OpenRouterCacheEntry = {
173
165
  value: Array<{
174
166
  id: string;
@@ -12,6 +12,8 @@ import { classifyError } from "./error-classifier.js";
12
12
  import { readLockfile, writeLockfile } from "../lockfile/lockfile.js";
13
13
  import { resolveSkillApiName as resolveSkillApiNameImpl } from "./skill-name-resolver.js";
14
14
  import { resolveSkillOrigin } from "./origin-resolver.js";
15
+ import { isPrivateOrUnknownRepo } from "../lib/private-source.js";
16
+ import { isPrivateStudioSkill, isPrivateStudioSkillAt, readStudioLocks } from "./studio-privacy.js";
15
17
  import { runBenchmarkSSE, runSingleCaseSSE } from "./benchmark-runner.js";
16
18
  import { getSkillSemaphore } from "./concurrency.js";
17
19
  import { resolveSkillDir, resolveAllowedSkillDir } from "./skill-resolver.js";
@@ -26,7 +28,8 @@ import { classifyOrigin, scanSkillsTriScope, dedupeByDir } from "../eval/skill-s
26
28
  import { scanInstalledPluginSkills, scanAuthoredPluginSkills, } from "../eval/plugin-scanner.js";
27
29
  import { resolveGlobalSkillsDir } from "../eval/path-utils.js";
28
30
  import { loadAndValidateEvals, EvalValidationError } from "../eval/schema.js";
29
- import { ANTHROPIC_CATALOG_SNAPSHOT, findAnthropicModel } from "../eval/anthropic-catalog.js";
31
+ import { PROVIDER_MODELS } from "../eval/model-catalog.js";
32
+ export { PROVIDER_MODELS } from "../eval/model-catalog.js";
30
33
  import { readBenchmark } from "../eval/benchmark.js";
31
34
  import { writeHistoryEntry, listHistory, readHistoryEntry, computeRegressions, deleteHistoryEntry, getCaseHistory, computeStats } from "../eval/benchmark-history.js";
32
35
  import { judgeAssertion } from "../eval/judge.js";
@@ -856,88 +859,6 @@ function computeBenchmarkStatus(benchmark, evalIds, hasEvals) {
856
859
  // Use overall_pass_rate as single source of truth
857
860
  return (benchmark.overall_pass_rate ?? 0) >= 1 ? "pass" : "fail";
858
861
  }
859
- // 0711 — Anthropic models + pricing now derive from the dated catalog
860
- // snapshot at `src/eval/anthropic-catalog.ts`. Manual maintenance of this
861
- // list led to stale prices (Opus 4.7 shown at $15/$75 instead of $5/$25)
862
- // because three different files held copies of the same fact. The catalog
863
- // file is the single source of truth; CI fails if its snapshotDate is
864
- // older than 6 months.
865
- function buildAnthropicProviderModels() {
866
- return ANTHROPIC_CATALOG_SNAPSHOT.models
867
- .filter((m) => m.status === "active")
868
- .map((m) => ({
869
- id: m.id,
870
- label: `${m.displayName} (API)`,
871
- pricing: {
872
- prompt: m.pricing.promptUsdPer1M,
873
- completion: m.pricing.completionUsdPer1M,
874
- },
875
- }));
876
- }
877
- function aliasInfo(alias, fallbackLabel) {
878
- const entry = findAnthropicModel(alias);
879
- if (!entry)
880
- return { label: fallbackLabel };
881
- return { label: entry.displayName, resolvedId: entry.id };
882
- }
883
- export const PROVIDER_MODELS = {
884
- // Opus first so it is the default when no override is set
885
- // (getEffectiveRawModel returns models[0]). Labels come from the catalog so
886
- // the picker shows the exact dated version (e.g. "Claude Opus 4.7"), not the
887
- // bare family name — keeps the Studio truthful when a model is bumped.
888
- "claude-cli": [
889
- { id: "opus", ...aliasInfo("opus", "Claude Opus") },
890
- { id: "sonnet", ...aliasInfo("sonnet", "Claude Sonnet") },
891
- { id: "haiku", ...aliasInfo("haiku", "Claude Haiku") },
892
- ],
893
- "anthropic": buildAnthropicProviderModels(),
894
- // Ollama's model list is dynamic — populated by probeOllama() from GET
895
- // /api/tags. Empty by default (parity with "lm-studio") so an unreachable
896
- // or timed-out probe surfaces zero models instead of leaking a hardcoded
897
- // fallback that isn't actually installed (0876 US-001).
898
- "ollama": [],
899
- "gemini-cli": [
900
- { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" },
901
- { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" },
902
- ],
903
- "codex-cli": [
904
- { id: "o3", label: "OpenAI o3" },
905
- { id: "o4-mini", label: "OpenAI o4-mini" },
906
- ],
907
- "openai": [
908
- { id: "gpt-4o-mini", label: "GPT-4o mini (API)", pricing: { prompt: 0.15, completion: 0.60 } },
909
- { id: "gpt-4o", label: "GPT-4o (API)", pricing: { prompt: 2.50, completion: 10 } },
910
- { id: "gpt-4.1", label: "GPT-4.1 (API)", pricing: { prompt: 2, completion: 8 } },
911
- { id: "gpt-4.1-mini", label: "GPT-4.1 mini (API)", pricing: { prompt: 0.40, completion: 1.60 } },
912
- { id: "o4-mini", label: "o4-mini (API)", pricing: { prompt: 1.10, completion: 4.40 } },
913
- ],
914
- "openrouter": [
915
- // Anthropic via OpenRouter
916
- { id: "anthropic/claude-opus-4", label: "Claude Opus 4 (via OpenRouter)" },
917
- { id: "anthropic/claude-sonnet-4", label: "Claude Sonnet 4 (via OpenRouter)" },
918
- { id: "anthropic/claude-haiku-4", label: "Claude Haiku 4 (via OpenRouter)" },
919
- // OpenAI via OpenRouter (0698 polish — Anton wants OpenAI first-class)
920
- { id: "openai/gpt-5", label: "GPT-5 (via OpenRouter)" },
921
- { id: "openai/gpt-5-mini", label: "GPT-5 mini (via OpenRouter)" },
922
- { id: "openai/o4-mini", label: "o4-mini (via OpenRouter)" },
923
- { id: "openai/o3", label: "OpenAI o3 (via OpenRouter)" },
924
- { id: "openai/gpt-4.1", label: "GPT-4.1 (via OpenRouter)" },
925
- // Google + Meta
926
- { id: "google/gemini-2.5-pro", label: "Gemini 2.5 Pro (via OpenRouter)" },
927
- { id: "google/gemini-2.5-flash", label: "Gemini 2.5 Flash (via OpenRouter)" },
928
- { id: "meta-llama/llama-3.3-70b-instruct", label: "Llama 3.3 70B (via OpenRouter)" },
929
- ],
930
- // LM Studio's default model list is empty because the actual list depends on
931
- // what models the user has loaded. The probe at probeLmStudio() populates
932
- // this dynamically from GET /v1/models.
933
- "lm-studio": [],
934
- // 0857: `stub` is a deterministic TEST SEAM (src/eval/llm.ts createStubClient),
935
- // NOT a user-facing provider. This empty list exists only to satisfy the
936
- // `Record<ProviderName, ModelOption[]>` exhaustiveness check — `stub` is
937
- // deliberately excluded from `detectAvailableProviders()` and
938
- // `KNOWN_PROVIDER_NAMES`, so it never reaches /api/config or the picker.
939
- "stub": [],
940
- };
941
862
  // ---------------------------------------------------------------------------
942
863
  // Local provider detection caches — avoid 500ms+ probes on every /api/config
943
864
  // request. Without the caches, page load blocks on the timeout when the
@@ -1561,6 +1482,10 @@ export function registerRoutes(router, rootArg, projectName) {
1561
1482
  // overwrites currentVersion. Stamping it server-side from the lockfile
1562
1483
  // collapses the race so badges render their final source on first paint.
1563
1484
  const lockForCurrentVersion = readLockfile(root);
1485
+ // Skills from a private repo (or one GitHub does not confirm is public)
1486
+ // are flagged so the Studio never sends them to the platform; see
1487
+ // studio-privacy.ts for how installed, plugin and authored skills map.
1488
+ const studioLocks = readStudioLocks(root);
1564
1489
  const enriched = await Promise.all(skills.map(async (s) => {
1565
1490
  let evalCount = 0;
1566
1491
  let assertionCount = 0;
@@ -1583,9 +1508,11 @@ export function registerRoutes(router, rootArg, projectName) {
1583
1508
  // currentVersion=null — the resolver then falls through to frontmatter,
1584
1509
  // preserving non-italic styling for author-declared versions.
1585
1510
  const currentVersion = lockForCurrentVersion?.skills?.[s.skill]?.version ?? null;
1511
+ const sourcePrivate = await isPrivateStudioSkill({ ...s, origin }, studioLocks);
1586
1512
  return {
1587
1513
  ...s,
1588
1514
  origin,
1515
+ ...(sourcePrivate ? { sourcePrivate: true } : {}),
1589
1516
  scope: s.scope ?? (origin === "installed" ? "installed" : "own"),
1590
1517
  isSymlink: s.isSymlink ?? false,
1591
1518
  symlinkTarget: s.symlinkTarget ?? null,
@@ -1740,6 +1667,12 @@ export function registerRoutes(router, rootArg, projectName) {
1740
1667
  // `/versions/diff` as needed.
1741
1668
  async function buildSkillApiPath(skill, plugin) {
1742
1669
  const origin = await resolveSkillOrigin(skill, plugin, getRoot());
1670
+ // Private (or unconfirmed) skills never reach the platform: lockfile
1671
+ // entries (incl. plugin installs), authored skills in private checkouts,
1672
+ // and installed skills nobody recorded.
1673
+ if (origin.private || (await isPrivateStudioSkillAt(skill, plugin, getRoot()))) {
1674
+ return { apiPathRoot: null, origin };
1675
+ }
1743
1676
  if (origin.owner && origin.repo) {
1744
1677
  return {
1745
1678
  apiPathRoot: `/api/v1/skills/${encodeURIComponent(origin.owner)}/${encodeURIComponent(origin.repo)}/${encodeURIComponent(skill)}`,
@@ -1750,6 +1683,9 @@ export function registerRoutes(router, rootArg, projectName) {
1750
1683
  // whose origin comes from a git remote, not a lockfile.
1751
1684
  const fullName = await resolveSkillApiName(skill, plugin);
1752
1685
  const parts = fullName.split("/");
1686
+ if (parts.length === 3 && (await isPrivateOrUnknownRepo(parts[0], parts[1]))) {
1687
+ return { apiPathRoot: null, origin };
1688
+ }
1753
1689
  const apiPathRoot = parts.length === 3
1754
1690
  ? `/api/v1/skills/${parts.map(encodeURIComponent).join("/")}`
1755
1691
  : `/api/v1/skills/${encodeURIComponent(fullName)}`;
@@ -1759,7 +1695,6 @@ export function registerRoutes(router, rootArg, projectName) {
1759
1695
  const root = getRoot();
1760
1696
  // 0823: comprehensive origin resolver via shared buildSkillApiPath.
1761
1697
  const { apiPathRoot, origin } = await buildSkillApiPath(params.skill, params.plugin);
1762
- const apiPath = `${apiPathRoot}/versions`;
1763
1698
  const emptyEnvelope = () => {
1764
1699
  res.setHeader("X-Skill-VCS", "unavailable");
1765
1700
  sendJson(res, {
@@ -1770,6 +1705,13 @@ export function registerRoutes(router, rootArg, projectName) {
1770
1705
  trackedForUpdates: false,
1771
1706
  }, 200, req);
1772
1707
  };
1708
+ // A skill from a private (or unconfirmed) repo has no platform history,
1709
+ // and its name and repo must not be sent there.
1710
+ if (apiPathRoot === null) {
1711
+ emptyEnvelope();
1712
+ return;
1713
+ }
1714
+ const apiPath = `${apiPathRoot}/versions`;
1773
1715
  let fetchResp;
1774
1716
  try {
1775
1717
  fetchResp = await fetch(`${PLATFORM_BASE}${apiPath}`, {
@@ -1859,6 +1801,10 @@ export function registerRoutes(router, rootArg, projectName) {
1859
1801
  // so Anthropic-shipped skills (slack-messaging, pptx, etc.) get the
1860
1802
  // matching upstream URL for diff requests, not the legacy bare-name path.
1861
1803
  const { apiPathRoot } = await buildSkillApiPath(params.skill, params.plugin);
1804
+ if (apiPathRoot === null) {
1805
+ sendJson(res, { error: "This skill comes from a private repository; version diffs are not available from verified-skill.com." }, 404, req);
1806
+ return;
1807
+ }
1862
1808
  const basePath = `${apiPathRoot}/versions/diff`;
1863
1809
  try {
1864
1810
  const resp = await fetch(`${PLATFORM_BASE}${basePath}?from=${encodeURIComponent(from)}&to=${encodeURIComponent(to)}`, { signal: AbortSignal.timeout(10_000) });
@@ -1964,7 +1910,11 @@ export function registerRoutes(router, rootArg, projectName) {
1964
1910
  let versions = [];
1965
1911
  try {
1966
1912
  const origin = await resolveSkillOrigin(skill, plugin, root);
1967
- if (origin.owner && origin.repo) {
1913
+ // Private (or unconfirmed) skills never reach the platform.
1914
+ if (!origin.private &&
1915
+ origin.owner &&
1916
+ origin.repo &&
1917
+ !(await isPrivateStudioSkillAt(skill, plugin, root))) {
1968
1918
  const apiPath = `/api/v1/skills/${encodeURIComponent(origin.owner)}/${encodeURIComponent(origin.repo)}/${encodeURIComponent(skill)}/versions`;
1969
1919
  try {
1970
1920
  const fetchResp = await fetch(`${PLATFORM_BASE}${apiPath}`, {