@specverse/engines 5.2.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/prompts/core/standard/default/analyse.prompt.yaml +12 -3
- package/assets/prompts/core/standard/default/behavior.prompt.yaml +37 -30
- package/assets/prompts/core/standard/default/create.prompt.yaml +11 -3
- package/assets/prompts/core/standard/v9/analyse.prompt.yaml +12 -3
- package/assets/prompts/core/standard/v9/behavior.prompt.yaml +37 -30
- package/assets/prompts/core/standard/v9/create.prompt.yaml +11 -3
- package/dist/ai/behavior-ai-service.d.ts +35 -28
- package/dist/ai/behavior-ai-service.d.ts.map +1 -1
- package/dist/ai/behavior-ai-service.js +95 -128
- package/dist/ai/behavior-ai-service.js.map +1 -1
- package/dist/ai/index.d.ts +26 -26
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +40 -29
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/model-resolver.d.ts +15 -0
- package/dist/ai/model-resolver.d.ts.map +1 -0
- package/dist/ai/model-resolver.js +87 -0
- package/dist/ai/model-resolver.js.map +1 -0
- package/dist/ai/providers/claude-cli.d.ts +25 -0
- package/dist/ai/providers/claude-cli.d.ts.map +1 -0
- package/dist/ai/providers/claude-cli.js +187 -0
- package/dist/ai/providers/claude-cli.js.map +1 -0
- package/dist/ai/providers/index.d.ts +8 -5
- package/dist/ai/providers/index.d.ts.map +1 -1
- package/dist/ai/providers/index.js +7 -5
- package/dist/ai/providers/index.js.map +1 -1
- package/dist/ai/providers/stub.d.ts +15 -0
- package/dist/ai/providers/stub.d.ts.map +1 -0
- package/dist/ai/providers/stub.js +64 -0
- package/dist/ai/providers/stub.js.map +1 -0
- package/dist/ai/skill-detection.d.ts +5 -0
- package/dist/ai/skill-detection.d.ts.map +1 -0
- package/dist/ai/skill-detection.js +27 -0
- package/dist/ai/skill-detection.js.map +1 -0
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +2 -2
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +2 -2
- package/package.json +8 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
2
|
+
export type ProviderId = 'claude-cli' | 'anthropic' | 'openai-compatible' | 'stub';
|
|
3
|
+
/** Return the configured provider id, resolving defaults if unset. */
|
|
4
|
+
export declare function resolveProviderId(): ProviderId;
|
|
5
|
+
export interface ResolveModelOptions {
|
|
6
|
+
/** Model name override; if omitted, picks a sensible provider default. */
|
|
7
|
+
model?: string;
|
|
8
|
+
/** Per-call timeout (claude-cli provider only). Default 300_000ms. */
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
/** Resolve an AI SDK v3 LanguageModel based on environment + options. */
|
|
12
|
+
export declare function resolveModel(options?: ResolveModelOptions): LanguageModelV3;
|
|
13
|
+
/** Best-effort diagnostic description of the active provider + model. */
|
|
14
|
+
export declare function describeActiveProvider(): string;
|
|
15
|
+
//# sourceMappingURL=model-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/ai/model-resolver.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,MAAM,MAAM,UAAU,GAAG,YAAY,GAAG,WAAW,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAEnF,sEAAsE;AACtE,wBAAgB,iBAAiB,IAAI,UAAU,CAc9C;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,yEAAyE;AACzE,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,eAAe,CAwC/E;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,IAAI,MAAM,CAc/C"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model resolver — picks the right LanguageModel implementation based on
|
|
3
|
+
* environment configuration. One call site, four providers:
|
|
4
|
+
*
|
|
5
|
+
* SPECVERSE_AI_PROVIDER=claude-cli Max user, spawns claude --print
|
|
6
|
+
* SPECVERSE_AI_PROVIDER=anthropic API-keyed Claude (metered)
|
|
7
|
+
* SPECVERSE_AI_PROVIDER=openai-compatible DeepSeek/Groq/Together/Ollama/etc.
|
|
8
|
+
* SPECVERSE_AI_PROVIDER=stub No LLM; emit prompt for ambient executor
|
|
9
|
+
*
|
|
10
|
+
* Defaults:
|
|
11
|
+
* - Inside an MCP server context (MCP_SERVER=1) → stub
|
|
12
|
+
* - Claude CLI available on PATH → claude-cli
|
|
13
|
+
* - ANTHROPIC_API_KEY set → anthropic
|
|
14
|
+
* - Else → stub (with a clear diagnostic comment)
|
|
15
|
+
*/
|
|
16
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
17
|
+
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
18
|
+
import { claudeCli, isClaudeCliAvailable } from './providers/claude-cli.js';
|
|
19
|
+
import { stubModel } from './providers/stub.js';
|
|
20
|
+
/** Return the configured provider id, resolving defaults if unset. */
|
|
21
|
+
export function resolveProviderId() {
|
|
22
|
+
const explicit = process.env.SPECVERSE_AI_PROVIDER;
|
|
23
|
+
if (explicit) {
|
|
24
|
+
if (['claude-cli', 'anthropic', 'openai-compatible', 'stub'].includes(explicit)) {
|
|
25
|
+
return explicit;
|
|
26
|
+
}
|
|
27
|
+
throw new Error(`SPECVERSE_AI_PROVIDER="${explicit}" is not recognized. Use one of: claude-cli, anthropic, openai-compatible, stub.`);
|
|
28
|
+
}
|
|
29
|
+
if (process.env.MCP_SERVER === '1')
|
|
30
|
+
return 'stub';
|
|
31
|
+
if (isClaudeCliAvailable())
|
|
32
|
+
return 'claude-cli';
|
|
33
|
+
if (process.env.ANTHROPIC_API_KEY)
|
|
34
|
+
return 'anthropic';
|
|
35
|
+
return 'stub';
|
|
36
|
+
}
|
|
37
|
+
/** Resolve an AI SDK v3 LanguageModel based on environment + options. */
|
|
38
|
+
export function resolveModel(options = {}) {
|
|
39
|
+
const provider = resolveProviderId();
|
|
40
|
+
const modelOverride = options.model ?? process.env.SPECVERSE_AI_MODEL;
|
|
41
|
+
switch (provider) {
|
|
42
|
+
case 'claude-cli':
|
|
43
|
+
return claudeCli({ model: modelOverride, timeout: options.timeout });
|
|
44
|
+
case 'anthropic': {
|
|
45
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
46
|
+
if (!apiKey) {
|
|
47
|
+
throw new Error('SPECVERSE_AI_PROVIDER=anthropic requires ANTHROPIC_API_KEY. ' +
|
|
48
|
+
'Set it or pick a different provider (claude-cli, openai-compatible, stub).');
|
|
49
|
+
}
|
|
50
|
+
const anthropic = createAnthropic({ apiKey });
|
|
51
|
+
return anthropic(modelOverride ?? 'claude-3-5-sonnet-latest');
|
|
52
|
+
}
|
|
53
|
+
case 'openai-compatible': {
|
|
54
|
+
const baseURL = process.env.SPECVERSE_AI_BASE_URL;
|
|
55
|
+
if (!baseURL) {
|
|
56
|
+
throw new Error('SPECVERSE_AI_PROVIDER=openai-compatible requires SPECVERSE_AI_BASE_URL ' +
|
|
57
|
+
'(e.g. https://api.together.xyz/v1 or http://localhost:11434/v1 for Ollama).');
|
|
58
|
+
}
|
|
59
|
+
const apiKey = process.env.SPECVERSE_AI_API_KEY;
|
|
60
|
+
const openaiCompatible = createOpenAICompatible({
|
|
61
|
+
name: 'specverse-ai',
|
|
62
|
+
baseURL,
|
|
63
|
+
apiKey,
|
|
64
|
+
});
|
|
65
|
+
return openaiCompatible(modelOverride ?? 'deepseek-chat');
|
|
66
|
+
}
|
|
67
|
+
case 'stub':
|
|
68
|
+
return stubModel();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Best-effort diagnostic description of the active provider + model. */
|
|
72
|
+
export function describeActiveProvider() {
|
|
73
|
+
const provider = resolveProviderId();
|
|
74
|
+
const model = process.env.SPECVERSE_AI_MODEL;
|
|
75
|
+
const modelStr = model ? ` (${model})` : '';
|
|
76
|
+
switch (provider) {
|
|
77
|
+
case 'claude-cli':
|
|
78
|
+
return `claude-cli${modelStr} — local Claude CLI, using your Max subscription auth`;
|
|
79
|
+
case 'anthropic':
|
|
80
|
+
return `anthropic${modelStr} — Anthropic API (metered tokens)`;
|
|
81
|
+
case 'openai-compatible':
|
|
82
|
+
return `openai-compatible${modelStr} — ${process.env.SPECVERSE_AI_BASE_URL ?? '(no BASE_URL)'}`;
|
|
83
|
+
case 'stub':
|
|
84
|
+
return 'stub — no LLM calls; prompt emitted verbatim for ambient executor';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=model-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-resolver.js","sourceRoot":"","sources":["../../src/ai/model-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
2
|
+
export interface ClaudeCliOptions {
|
|
3
|
+
/** Explicit path to the claude binary. Auto-detected if omitted. */
|
|
4
|
+
claudePath?: string;
|
|
5
|
+
/** Model override (e.g. "claude-opus-4", "claude-sonnet-4-5"). Defaults to whatever claude CLI picks. */
|
|
6
|
+
model?: string;
|
|
7
|
+
/** Timeout in milliseconds for each call. Default: 120_000. */
|
|
8
|
+
timeout?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Find the first working `claude` binary. Tries:
|
|
12
|
+
* 1. Explicit path override if given
|
|
13
|
+
* 2. ~/.claude/local/claude (Claude Code's user install)
|
|
14
|
+
* 3. `claude` on PATH (Homebrew / manual installs)
|
|
15
|
+
* Returns null if none respond to `--version`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectClaudePath(override?: string): string | null;
|
|
18
|
+
/** True if any candidate claude binary responds to --version. */
|
|
19
|
+
export declare function isClaudeCliAvailable(override?: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Factory for a claude-cli-backed LanguageModelV3. Session state is held
|
|
22
|
+
* inside the closure, so each call to claudeCli() gets its own session.
|
|
23
|
+
*/
|
|
24
|
+
export declare function claudeCli(options?: ClaudeCliOptions): LanguageModelV3;
|
|
25
|
+
//# sourceMappingURL=claude-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-cli.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/claude-cli.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EACV,eAAe,EAMhB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yGAAyG;IACzG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBjE;AAED,iEAAiE;AACjE,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/D;AAmCD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,eAAe,CA4GzE"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* claude-cli provider — wraps the locally-installed `claude` binary as an
|
|
3
|
+
* AI SDK v3 LanguageModel. Preserves the Max-subscription zero-cost path
|
|
4
|
+
* by spawning `claude --print` with the user's authenticated session.
|
|
5
|
+
*
|
|
6
|
+
* Session caching: first call uses `--session-id <uuid>`, subsequent calls
|
|
7
|
+
* `--resume <uuid>` — gives the same 98% token savings the Claude Code
|
|
8
|
+
* session mechanism provides.
|
|
9
|
+
*
|
|
10
|
+
* If the user has run `spv skill install --global`, the SpecVerse skill is
|
|
11
|
+
* auto-loaded by Claude Code into every session started by this provider.
|
|
12
|
+
* See detectInstalledSkill() in ../skill-detection.ts.
|
|
13
|
+
*/
|
|
14
|
+
import { spawn, execSync } from 'child_process';
|
|
15
|
+
import { existsSync } from 'fs';
|
|
16
|
+
import { randomUUID } from 'crypto';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
/**
|
|
19
|
+
* Find the first working `claude` binary. Tries:
|
|
20
|
+
* 1. Explicit path override if given
|
|
21
|
+
* 2. ~/.claude/local/claude (Claude Code's user install)
|
|
22
|
+
* 3. `claude` on PATH (Homebrew / manual installs)
|
|
23
|
+
* Returns null if none respond to `--version`.
|
|
24
|
+
*/
|
|
25
|
+
export function detectClaudePath(override) {
|
|
26
|
+
const home = process.env.HOME || '';
|
|
27
|
+
const candidates = override
|
|
28
|
+
? [override]
|
|
29
|
+
: [join(home, '.claude', 'local', 'claude'), 'claude'];
|
|
30
|
+
for (const candidate of candidates) {
|
|
31
|
+
// For explicit paths, require existence on disk before exec.
|
|
32
|
+
if (candidate !== 'claude' && !existsSync(candidate))
|
|
33
|
+
continue;
|
|
34
|
+
try {
|
|
35
|
+
execSync(`${candidate} --version`, { stdio: 'ignore', timeout: 5000 });
|
|
36
|
+
return candidate;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
/* try next */
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/** True if any candidate claude binary responds to --version. */
|
|
45
|
+
export function isClaudeCliAvailable(override) {
|
|
46
|
+
return detectClaudePath(override) !== null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Extract a flat { system, user } pair from the AI SDK's message array.
|
|
50
|
+
* The claude CLI's --system-prompt / -p flags only accept one string each.
|
|
51
|
+
* For now we concatenate any system messages, and join all user turns with
|
|
52
|
+
* blank lines. (In practice behavior generation is single-turn; this
|
|
53
|
+
* provider isn't targeting multi-turn conversational use.)
|
|
54
|
+
*/
|
|
55
|
+
function flattenPrompt(messages) {
|
|
56
|
+
const systemChunks = [];
|
|
57
|
+
const userChunks = [];
|
|
58
|
+
for (const msg of messages) {
|
|
59
|
+
if (msg.role === 'system') {
|
|
60
|
+
systemChunks.push(msg.content);
|
|
61
|
+
}
|
|
62
|
+
else if (msg.role === 'user') {
|
|
63
|
+
for (const part of msg.content) {
|
|
64
|
+
if (part.type === 'text')
|
|
65
|
+
userChunks.push(part.text);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (msg.role === 'assistant') {
|
|
69
|
+
// Prior assistant turns get included into the user prompt as context
|
|
70
|
+
// so the CLI can see them. Unusual for our use case.
|
|
71
|
+
const text = msg.content
|
|
72
|
+
.filter((p) => p.type === 'text')
|
|
73
|
+
.map((p) => p.text)
|
|
74
|
+
.join('');
|
|
75
|
+
if (text)
|
|
76
|
+
userChunks.push(`[Assistant previously said]\n${text}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
system: systemChunks.join('\n\n').trim(),
|
|
81
|
+
user: userChunks.join('\n\n').trim(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Factory for a claude-cli-backed LanguageModelV3. Session state is held
|
|
86
|
+
* inside the closure, so each call to claudeCli() gets its own session.
|
|
87
|
+
*/
|
|
88
|
+
export function claudeCli(options = {}) {
|
|
89
|
+
const claudePath = options.claudePath || detectClaudePath() || 'claude';
|
|
90
|
+
// Behavior gen calls are short; analyse calls can take a couple of minutes
|
|
91
|
+
// on larger codebases. 5 minutes is a sane upper bound for either.
|
|
92
|
+
const timeout = options.timeout ?? 300_000;
|
|
93
|
+
const modelId = options.model ?? 'default';
|
|
94
|
+
const sessionId = randomUUID();
|
|
95
|
+
let initialized = false;
|
|
96
|
+
async function spawnClaude(args, stdinPrompt) {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const proc = spawn(claudePath, args, {
|
|
99
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
100
|
+
env: { ...process.env },
|
|
101
|
+
});
|
|
102
|
+
let out = '';
|
|
103
|
+
let err = '';
|
|
104
|
+
const timer = setTimeout(() => {
|
|
105
|
+
proc.kill();
|
|
106
|
+
reject(new Error(`claude-cli timed out after ${timeout}ms`));
|
|
107
|
+
}, timeout);
|
|
108
|
+
proc.stdout?.on('data', (d) => {
|
|
109
|
+
out += d.toString();
|
|
110
|
+
});
|
|
111
|
+
proc.stderr?.on('data', (d) => {
|
|
112
|
+
err += d.toString();
|
|
113
|
+
});
|
|
114
|
+
proc.on('close', (code) => {
|
|
115
|
+
clearTimeout(timer);
|
|
116
|
+
if (code !== 0) {
|
|
117
|
+
reject(new Error(`claude-cli exited ${code}: ${err || out}`));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
resolve(out);
|
|
121
|
+
});
|
|
122
|
+
proc.on('error', (e) => {
|
|
123
|
+
clearTimeout(timer);
|
|
124
|
+
reject(e);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const model = {
|
|
129
|
+
specificationVersion: 'v3',
|
|
130
|
+
provider: 'claude-cli',
|
|
131
|
+
modelId,
|
|
132
|
+
supportedUrls: {},
|
|
133
|
+
async doGenerate(opts) {
|
|
134
|
+
const { system, user } = flattenPrompt(opts.prompt);
|
|
135
|
+
const args = ['--print'];
|
|
136
|
+
if (!initialized) {
|
|
137
|
+
args.push('--session-id', sessionId);
|
|
138
|
+
if (system)
|
|
139
|
+
args.push('--system-prompt', system);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
args.push('--resume', sessionId);
|
|
143
|
+
}
|
|
144
|
+
if (modelId !== 'default')
|
|
145
|
+
args.push('--model', modelId);
|
|
146
|
+
args.push('-p', user);
|
|
147
|
+
const out = await spawnClaude(args, user);
|
|
148
|
+
initialized = true;
|
|
149
|
+
return {
|
|
150
|
+
content: [{ type: 'text', text: out.trim() }],
|
|
151
|
+
finishReason: { unified: 'stop', raw: undefined },
|
|
152
|
+
usage: {
|
|
153
|
+
// The CLI doesn't expose token counts in --print mode.
|
|
154
|
+
inputTokens: { total: undefined, noCache: undefined, cacheRead: undefined, cacheWrite: undefined },
|
|
155
|
+
outputTokens: { total: undefined, text: undefined, reasoning: undefined },
|
|
156
|
+
},
|
|
157
|
+
warnings: [],
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
async doStream(opts) {
|
|
161
|
+
// v1 of this provider: no real streaming — buffer the doGenerate result
|
|
162
|
+
// and emit it as a single chunk. Revisit if behavior-service ever wants
|
|
163
|
+
// partial-output UX.
|
|
164
|
+
const result = await model.doGenerate(opts);
|
|
165
|
+
const text = result.content
|
|
166
|
+
.filter((c) => c.type === 'text')
|
|
167
|
+
.map((c) => c.text)
|
|
168
|
+
.join('');
|
|
169
|
+
const parts = [
|
|
170
|
+
{ type: 'text-start', id: 'single' },
|
|
171
|
+
{ type: 'text-delta', id: 'single', delta: text },
|
|
172
|
+
{ type: 'text-end', id: 'single' },
|
|
173
|
+
{ type: 'finish', finishReason: { unified: 'stop', raw: undefined }, usage: result.usage },
|
|
174
|
+
];
|
|
175
|
+
const stream = new ReadableStream({
|
|
176
|
+
start(controller) {
|
|
177
|
+
for (const part of parts)
|
|
178
|
+
controller.enqueue(part);
|
|
179
|
+
controller.close();
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
return { stream };
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
return model;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=claude-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-cli.js","sourceRoot":"","sources":["../../../src/ai/providers/claude-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* AI providers — custom LanguageModelV3 implementations that plug into the
|
|
3
|
+
* Vercel AI SDK. Most consumers should call `resolveModel()` from the parent
|
|
4
|
+
* module rather than instantiating these directly.
|
|
5
|
+
*/
|
|
6
|
+
export { claudeCli, isClaudeCliAvailable, detectClaudePath } from './claude-cli.js';
|
|
7
|
+
export type { ClaudeCliOptions } from './claude-cli.js';
|
|
8
|
+
export { stubModel } from './stub.js';
|
|
6
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACpF,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* AI providers — custom LanguageModelV3 implementations that plug into the
|
|
3
|
+
* Vercel AI SDK. Most consumers should call `resolveModel()` from the parent
|
|
4
|
+
* module rather than instantiating these directly.
|
|
5
|
+
*/
|
|
6
|
+
export { claudeCli, isClaudeCliAvailable, detectClaudePath } from './claude-cli.js';
|
|
7
|
+
export { stubModel } from './stub.js';
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai/providers/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ai/providers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEpF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stub provider — an AI SDK v3 LanguageModel that doesn't call any LLM.
|
|
3
|
+
* Emits the user prompt verbatim with a marker comment so the ambient
|
|
4
|
+
* runtime (MCP client, user's editor, etc.) can see what was asked and
|
|
5
|
+
* execute it themselves.
|
|
6
|
+
*
|
|
7
|
+
* Used in two scenarios:
|
|
8
|
+
* 1. Inside an MCP server context (MCP_SERVER=1) — the Claude Desktop /
|
|
9
|
+
* client session IS the LLM; calling a separate API would be wasteful.
|
|
10
|
+
* 2. As the safe default when no provider is configured — gives a clear
|
|
11
|
+
* diagnostic instead of a silent failure or a cryptic auth error.
|
|
12
|
+
*/
|
|
13
|
+
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
14
|
+
export declare function stubModel(): LanguageModelV3;
|
|
15
|
+
//# sourceMappingURL=stub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/stub.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EACV,eAAe,EAMhB,MAAM,kBAAkB,CAAC;AAkB1B,wBAAgB,SAAS,IAAI,eAAe,CAqD3C"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
function formatAsText(messages) {
|
|
2
|
+
const sections = [];
|
|
3
|
+
for (const msg of messages) {
|
|
4
|
+
if (msg.role === 'system') {
|
|
5
|
+
sections.push(`--- system ---\n${msg.content}`);
|
|
6
|
+
}
|
|
7
|
+
else if (msg.role === 'user') {
|
|
8
|
+
const text = msg.content
|
|
9
|
+
.filter((p) => p.type === 'text')
|
|
10
|
+
.map((p) => p.text)
|
|
11
|
+
.join('');
|
|
12
|
+
sections.push(`--- user ---\n${text}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return sections.join('\n\n');
|
|
16
|
+
}
|
|
17
|
+
export function stubModel() {
|
|
18
|
+
const model = {
|
|
19
|
+
specificationVersion: 'v3',
|
|
20
|
+
provider: 'specverse-stub',
|
|
21
|
+
modelId: 'stub',
|
|
22
|
+
supportedUrls: {},
|
|
23
|
+
async doGenerate(opts) {
|
|
24
|
+
const text = '// SPECVERSE_AI_PROVIDER=stub — no LLM was called.\n' +
|
|
25
|
+
'// The ambient runtime (MCP client, agent, or user) is expected to\n' +
|
|
26
|
+
'// execute the prompt below. To enable real generation, set\n' +
|
|
27
|
+
'// SPECVERSE_AI_PROVIDER to one of: claude-cli, anthropic, openai-compatible.\n' +
|
|
28
|
+
'\n' +
|
|
29
|
+
formatAsText(opts.prompt);
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: 'text', text }],
|
|
32
|
+
finishReason: { unified: 'stop', raw: undefined },
|
|
33
|
+
usage: {
|
|
34
|
+
inputTokens: { total: 0, noCache: 0, cacheRead: 0, cacheWrite: 0 },
|
|
35
|
+
outputTokens: { total: 0, text: 0, reasoning: 0 },
|
|
36
|
+
},
|
|
37
|
+
warnings: [],
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
async doStream(opts) {
|
|
41
|
+
const result = await model.doGenerate(opts);
|
|
42
|
+
const text = result.content
|
|
43
|
+
.filter((c) => c.type === 'text')
|
|
44
|
+
.map((c) => c.text)
|
|
45
|
+
.join('');
|
|
46
|
+
const parts = [
|
|
47
|
+
{ type: 'text-start', id: 'stub' },
|
|
48
|
+
{ type: 'text-delta', id: 'stub', delta: text },
|
|
49
|
+
{ type: 'text-end', id: 'stub' },
|
|
50
|
+
{ type: 'finish', finishReason: { unified: 'stop', raw: undefined }, usage: result.usage },
|
|
51
|
+
];
|
|
52
|
+
const stream = new ReadableStream({
|
|
53
|
+
start(controller) {
|
|
54
|
+
for (const part of parts)
|
|
55
|
+
controller.enqueue(part);
|
|
56
|
+
controller.close();
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
return { stream };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
return model;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=stub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stub.js","sourceRoot":"","sources":["../../../src/ai/providers/stub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-detection.d.ts","sourceRoot":"","sources":["../../src/ai/skill-detection.ts"],"names":[],"mappings":"AAgBA,wBAAgB,oBAAoB,CAAC,SAAS,SAAc,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CASzG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect whether the SpecVerse Claude skill is installed in a location
|
|
3
|
+
* that Claude Code will auto-load.
|
|
4
|
+
*
|
|
5
|
+
* Claude Code discovers skills from:
|
|
6
|
+
* - ~/.claude/skills/<name>/ (global — shipped by `spv skill install --global`)
|
|
7
|
+
* - <cwd>/.claude/skills/<name>/ (project-local — `spv skill install --project`)
|
|
8
|
+
*
|
|
9
|
+
* If either is present with a SKILL.md, we assume Claude-CLI-backed behavior
|
|
10
|
+
* generation will benefit from the skill's auto-loaded context — meaning we
|
|
11
|
+
* can send a leaner system prompt (skip the fullContext block).
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync } from 'fs';
|
|
14
|
+
import { homedir } from 'os';
|
|
15
|
+
import { join } from 'path';
|
|
16
|
+
export function detectInstalledSkill(skillName = 'specverse') {
|
|
17
|
+
const candidates = [
|
|
18
|
+
join(process.cwd(), '.claude', 'skills', skillName, 'SKILL.md'),
|
|
19
|
+
join(homedir(), '.claude', 'skills', skillName, 'SKILL.md'),
|
|
20
|
+
];
|
|
21
|
+
for (const path of candidates) {
|
|
22
|
+
if (existsSync(path))
|
|
23
|
+
return { found: true, location: path };
|
|
24
|
+
}
|
|
25
|
+
return { found: false, location: null };
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=skill-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-detection.js","sourceRoot":"","sources":["../../src/ai/skill-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,UAAU,oBAAoB,CAAC,SAAS,GAAG,WAAW;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC;QAC/D,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC;KAC5D,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -130,9 +130,9 @@ function generatePackageJson(version, description) {
|
|
|
130
130
|
},
|
|
131
131
|
dependencies: {
|
|
132
132
|
"@modelcontextprotocol/sdk": "^1.17.4",
|
|
133
|
-
"@specverse/engines": "^
|
|
133
|
+
"@specverse/engines": "^6.0.0",
|
|
134
134
|
"@specverse/entities": "^5.1.0",
|
|
135
|
-
"@specverse/self": "^5.
|
|
135
|
+
"@specverse/self": "^5.3.0",
|
|
136
136
|
"js-yaml": "^4.1.0"
|
|
137
137
|
},
|
|
138
138
|
devDependencies: {
|
|
@@ -208,9 +208,9 @@ function generatePackageJson(version: string, description: string): string {
|
|
|
208
208
|
},
|
|
209
209
|
dependencies: {
|
|
210
210
|
'@modelcontextprotocol/sdk': '^1.17.4',
|
|
211
|
-
'@specverse/engines': '^
|
|
211
|
+
'@specverse/engines': '^6.0.0',
|
|
212
212
|
'@specverse/entities': '^5.1.0',
|
|
213
|
-
'@specverse/self': '^5.
|
|
213
|
+
'@specverse/self': '^5.3.0',
|
|
214
214
|
'js-yaml': '^4.1.0',
|
|
215
215
|
},
|
|
216
216
|
devDependencies: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@specverse/engines",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "SpecVerse toolchain
|
|
3
|
+
"version": "6.0.1",
|
|
4
|
+
"description": "SpecVerse toolchain — parser, inference, realize, generators, AI, registry, bundles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -46,16 +46,21 @@
|
|
|
46
46
|
"clean": "rm -rf dist"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
+
"@ai-sdk/anthropic": "^3.0.71",
|
|
50
|
+
"@ai-sdk/openai-compatible": "^2.0.41",
|
|
51
|
+
"@ai-sdk/provider": "^3.0.8",
|
|
49
52
|
"@specverse/entities": "^5.1.0",
|
|
50
53
|
"@specverse/runtime": "^5.0.1",
|
|
51
54
|
"@specverse/types": "^5.1.0",
|
|
55
|
+
"ai": "^6.0.168",
|
|
52
56
|
"ajv": "^8.17.0",
|
|
53
57
|
"ajv-formats": "^2.1.0",
|
|
54
58
|
"glob": "^10.0.0",
|
|
55
59
|
"handlebars": "^4.7.9",
|
|
56
60
|
"js-yaml": "^4.1.0",
|
|
57
61
|
"semver": "^7.0.0",
|
|
58
|
-
"yaml": "^2.8.1"
|
|
62
|
+
"yaml": "^2.8.1",
|
|
63
|
+
"zod": "^4.3.6"
|
|
59
64
|
},
|
|
60
65
|
"devDependencies": {
|
|
61
66
|
"@types/node": "^25.5.0",
|