@shrkcrft/ai 0.1.0-alpha.12 → 0.1.0-alpha.14

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/dist/index.d.ts CHANGED
@@ -8,4 +8,6 @@ export * from './ollama/ollama-provider.js';
8
8
  export * from './llamacpp/llama-cpp-provider.js';
9
9
  export * from './provider-resolver.js';
10
10
  export * from './pipeline/enhancement-pipeline.js';
11
+ export * from './llm-hints.js';
12
+ export * from './llm-recommendations.js';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,oCAAoC,CAAC;AACnD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -8,3 +8,5 @@ export * from "./ollama/ollama-provider.js";
8
8
  export * from "./llamacpp/llama-cpp-provider.js";
9
9
  export * from "./provider-resolver.js";
10
10
  export * from "./pipeline/enhancement-pipeline.js";
11
+ export * from "./llm-hints.js";
12
+ export * from "./llm-recommendations.js";
@@ -0,0 +1,36 @@
1
+ import type { AiProviderKind } from './provider-resolver.js';
2
+ import type { IAiProvider } from './ai-provider.js';
3
+ export type AiHintLevel = 'setup' | 'upgrade' | 'info';
4
+ export interface IAiHint {
5
+ level: AiHintLevel;
6
+ title: string;
7
+ steps: readonly string[];
8
+ }
9
+ export interface IAiBlock {
10
+ reachable: boolean;
11
+ requestedProvider: AiProviderKind;
12
+ providerId: string | null;
13
+ enhancementSkipped: boolean;
14
+ hints: readonly IAiHint[];
15
+ }
16
+ export interface IBuildAiBlockInput {
17
+ /** What `selectAiProvider` returned, or null if the caller didn't try. */
18
+ selection?: {
19
+ requested: AiProviderKind;
20
+ provider: IAiProvider | null;
21
+ } | null;
22
+ /** True when --no-enhance was passed (user opted out — don't nag). */
23
+ userOptedOut?: boolean;
24
+ }
25
+ /**
26
+ * Produces the structured `ai` block that lives on every audit report
27
+ * and any command using `enrichWithLlmRecommendations`. Without the
28
+ * AI block, `--no-enhance` and "no provider reachable" look the same
29
+ * to a downstream agent. The block disambiguates.
30
+ *
31
+ * Lives in `@shrkcrft/ai` so any package (CLI, packs, MCP server's
32
+ * read-only surfaces) can construct the same shape.
33
+ */
34
+ export declare function buildAiBlock(input?: IBuildAiBlockInput): IAiBlock;
35
+ export declare function renderAiBlockMarkdown(block: IAiBlock): string;
36
+ //# sourceMappingURL=llm-hints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-hints.d.ts","sourceRoot":"","sources":["../src/llm-hints.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,WAAW,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,EAAE,cAAc,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,SAAS,CAAC,EAAE;QAAE,SAAS,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC/E,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,kBAAuB,GAAG,QAAQ,CAiErE;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAiB7D"}
@@ -0,0 +1,92 @@
1
+ import { selectAiProvider } from "./provider-resolver.js";
2
+ /**
3
+ * Produces the structured `ai` block that lives on every audit report
4
+ * and any command using `enrichWithLlmRecommendations`. Without the
5
+ * AI block, `--no-enhance` and "no provider reachable" look the same
6
+ * to a downstream agent. The block disambiguates.
7
+ *
8
+ * Lives in `@shrkcrft/ai` so any package (CLI, packs, MCP server's
9
+ * read-only surfaces) can construct the same shape.
10
+ */
11
+ export function buildAiBlock(input = {}) {
12
+ // Honour an explicitly-passed selection (including {provider: null} when
13
+ // --no-enhance is in play) without re-probing the auto chain. Only fall
14
+ // back to live probing when the caller didn't supply a selection at all.
15
+ const selection = input.selection !== undefined && input.selection !== null
16
+ ? input.selection
17
+ : input.userOptedOut
18
+ ? { requested: 'auto', provider: null }
19
+ : selectAiProvider(undefined);
20
+ const reachable = selection.provider !== null;
21
+ const providerId = selection.provider?.id ?? null;
22
+ const requested = selection.requested;
23
+ const userOptedOut = Boolean(input.userOptedOut);
24
+ const hints = [];
25
+ if (!reachable && !userOptedOut) {
26
+ hints.push({
27
+ level: 'setup',
28
+ title: 'Enable LLM enrichment for deeper analysis',
29
+ steps: [
30
+ 'Local-first: install Ollama (https://ollama.com/download) or set LLAMACPP_MODEL_PATH for in-process inference.',
31
+ 'Pull a model that fits your machine — e.g. `ollama pull llama3.2` (good general-purpose) or `ollama pull qwen2.5-coder:7b` (code-aware).',
32
+ 'Optional: export OLLAMA_HOST=http://localhost:11434 (default) or point at a remote daemon.',
33
+ 'Optional: export OLLAMA_MODEL=<id> to pin the model used by shrk.',
34
+ 'Re-run without --no-enhance. The deterministic findings are unchanged; LLM critique appears under `llmFindings`.',
35
+ ],
36
+ });
37
+ }
38
+ else if (!reachable && userOptedOut) {
39
+ hints.push({
40
+ level: 'info',
41
+ title: 'LLM enrichment disabled by --no-enhance',
42
+ steps: [
43
+ 'Deterministic findings are first-class; LLM is purely additive.',
44
+ 'Drop --no-enhance to layer LLM critique on top when a provider is available.',
45
+ ],
46
+ });
47
+ }
48
+ else {
49
+ hints.push({
50
+ level: 'info',
51
+ title: `LLM enrichment active via ${providerId}`,
52
+ steps: [
53
+ 'LLM-derived findings appear with `[llm]` tags and a confidence score.',
54
+ 'Tune behavior: --provider ollama|llamacpp, --model <id>, AI_PROVIDER env var (overrides --provider when unset).',
55
+ ],
56
+ });
57
+ hints.push({
58
+ level: 'upgrade',
59
+ title: 'Sharpen LLM output if findings feel thin',
60
+ steps: [
61
+ 'Prefer a code-aware model for technical staleness checks (e.g. qwen2.5-coder:7b, deepseek-coder-v2).',
62
+ 'Larger models notice more drift but cost latency — try 7B for code, 14B+ for nuanced doc-content review.',
63
+ 'For fix-plan enrichment, the same provider is reused; no separate config needed.',
64
+ ],
65
+ });
66
+ }
67
+ return {
68
+ reachable,
69
+ requestedProvider: requested,
70
+ providerId,
71
+ enhancementSkipped: userOptedOut,
72
+ hints,
73
+ };
74
+ }
75
+ export function renderAiBlockMarkdown(block) {
76
+ const out = [];
77
+ const status = block.reachable
78
+ ? `active via \`${block.providerId}\``
79
+ : block.enhancementSkipped
80
+ ? 'disabled by `--no-enhance`'
81
+ : 'unavailable (no local LLM detected)';
82
+ out.push(`## AI configuration — ${status}`);
83
+ out.push('');
84
+ for (const hint of block.hints) {
85
+ out.push(`### [${hint.level}] ${hint.title}`);
86
+ for (const step of hint.steps) {
87
+ out.push(`- ${step}`);
88
+ }
89
+ out.push('');
90
+ }
91
+ return out.join('\n');
92
+ }
@@ -0,0 +1,72 @@
1
+ import type { IAiProvider } from './ai-provider.js';
2
+ import { type IAiBlock } from './llm-hints.js';
3
+ export type RecommendationSeverity = 'info' | 'warn' | 'error';
4
+ export interface ILlmRecommendation {
5
+ severity: RecommendationSeverity;
6
+ category: string;
7
+ /** Short, one-sentence description of what's recommended. */
8
+ title: string;
9
+ /** Detailed prose; typically 1-3 sentences with concrete next-steps. */
10
+ detail: string;
11
+ /** Optional target identifier (rule id, template id, file path) the recommendation applies to. */
12
+ target?: string;
13
+ /** Confidence in [0, 1]; lower for fuzzier judgments. */
14
+ confidence: number;
15
+ }
16
+ export interface IRecommendationEnvelope {
17
+ /** Always present, even when LLM is unavailable. */
18
+ ai: IAiBlock;
19
+ recommendations: readonly ILlmRecommendation[];
20
+ }
21
+ export interface IEnrichWithLlmRecommendationsInput {
22
+ /**
23
+ * The shape of the deterministic surface (e.g., 'doctor', 'templates-drift').
24
+ * Used in the LLM prompt so the model knows what it's looking at.
25
+ */
26
+ surface: string;
27
+ /**
28
+ * Human-readable description of the deterministic findings (what's already
29
+ * known). Should be tight — the prompt fits into one LLM call.
30
+ */
31
+ deterministicSummary: string;
32
+ /**
33
+ * Provider kind to request. Defaults to 'auto' (local-first walk).
34
+ */
35
+ providerKind?: string;
36
+ /**
37
+ * Override the auto-selection by passing an already-resolved provider
38
+ * (useful for tests).
39
+ */
40
+ providerOverride?: IAiProvider | null;
41
+ /**
42
+ * True when the caller's --no-enhance equivalent was passed.
43
+ * When true, no LLM call is made and the AI block records the opt-out.
44
+ */
45
+ userOptedOut?: boolean;
46
+ /**
47
+ * Per-surface ask: what should the LLM produce on top of the
48
+ * deterministic summary? E.g. "for each warning, produce one concrete
49
+ * next-step the user can run from the CLI."
50
+ */
51
+ ask: string;
52
+ /**
53
+ * Optional override for the model used by the provider.
54
+ */
55
+ model?: string;
56
+ maxTokens?: number;
57
+ }
58
+ /**
59
+ * Shared utility for layering LLM recommendations onto any deterministic
60
+ * surface. The deterministic portion is the caller's responsibility; this
61
+ * helper only adds the `ai` block and a structured `recommendations` array.
62
+ *
63
+ * Hard guarantee: if no LLM is reachable (or `userOptedOut` is true), the
64
+ * call is a no-op apart from emitting the `ai` block with setup hints.
65
+ *
66
+ * Lives in `@shrkcrft/ai` so any callable surface (CLI commands, packs,
67
+ * read-only MCP tools that want recommendations alongside their data)
68
+ * can reuse the same envelope shape.
69
+ */
70
+ export declare function enrichWithLlmRecommendations(input: IEnrichWithLlmRecommendationsInput): Promise<IRecommendationEnvelope>;
71
+ export declare function renderRecommendationsMarkdown(envelope: IRecommendationEnvelope): string;
72
+ //# sourceMappingURL=llm-recommendations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-recommendations.d.ts","sourceRoot":"","sources":["../src/llm-recommendations.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE7D,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,sBAAsB,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,oDAAoD;IACpD,EAAE,EAAE,QAAQ,CAAC;IACb,eAAe,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACtC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,KAAK,EAAE,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,CAAC,CAoClC;AA2FD,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,uBAAuB,GAAG,MAAM,CA+BvF"}
@@ -0,0 +1,188 @@
1
+ import { AiMessageRole } from "./ai-request.js";
2
+ import { selectAiProvider } from "./provider-resolver.js";
3
+ import { buildAiBlock } from "./llm-hints.js";
4
+ /**
5
+ * Shared utility for layering LLM recommendations onto any deterministic
6
+ * surface. The deterministic portion is the caller's responsibility; this
7
+ * helper only adds the `ai` block and a structured `recommendations` array.
8
+ *
9
+ * Hard guarantee: if no LLM is reachable (or `userOptedOut` is true), the
10
+ * call is a no-op apart from emitting the `ai` block with setup hints.
11
+ *
12
+ * Lives in `@shrkcrft/ai` so any callable surface (CLI commands, packs,
13
+ * read-only MCP tools that want recommendations alongside their data)
14
+ * can reuse the same envelope shape.
15
+ */
16
+ export async function enrichWithLlmRecommendations(input) {
17
+ if (input.userOptedOut) {
18
+ const aiBlock = buildAiBlock({
19
+ selection: { requested: normaliseKind(input.providerKind), provider: null },
20
+ userOptedOut: true,
21
+ });
22
+ return { ai: aiBlock, recommendations: [] };
23
+ }
24
+ const selection = input.providerOverride !== undefined
25
+ ? { requested: normaliseKind(input.providerKind), provider: input.providerOverride }
26
+ : selectAiProvider(input.providerKind);
27
+ if (!selection.provider) {
28
+ const aiBlock = buildAiBlock({ selection, userOptedOut: false });
29
+ return { ai: aiBlock, recommendations: [] };
30
+ }
31
+ if (input.model)
32
+ selection.provider.configure({ model: input.model });
33
+ const messages = buildRecommendationMessages(input);
34
+ let recommendations = [];
35
+ try {
36
+ const res = await selection.provider.send({
37
+ messages,
38
+ maxTokens: input.maxTokens ?? 1024,
39
+ });
40
+ if (res.ok) {
41
+ recommendations = parseRecommendations(res.value.content);
42
+ }
43
+ }
44
+ catch {
45
+ // Swallow — recommendations stay empty; ai block still carries provider info.
46
+ }
47
+ const aiBlock = buildAiBlock({ selection, userOptedOut: false });
48
+ return { ai: aiBlock, recommendations };
49
+ }
50
+ function buildRecommendationMessages(input) {
51
+ const system = {
52
+ role: AiMessageRole.System,
53
+ content: [
54
+ `You are a critic layering concrete next-step recommendations on top of a deterministic SharkCraft "${input.surface}" report.`,
55
+ 'The deterministic report is supplied verbatim — treat its findings as facts. Your job is to translate them into actions a developer (or an AI coding agent) can take immediately.',
56
+ '',
57
+ 'The user-specified ask is:',
58
+ input.ask,
59
+ '',
60
+ 'Return ONLY a JSON object with this exact shape, no preface, no fences:',
61
+ '{',
62
+ ' "recommendations": [',
63
+ ' {',
64
+ ' "severity": "info" | "warn" | "error",',
65
+ ' "category": "<short kebab-case category>",',
66
+ ' "title": "<one-sentence summary>",',
67
+ ' "detail": "<one to three sentences with concrete next-steps; name files, commands, or symbols when possible>",',
68
+ ' "target": "<optional id or path>",',
69
+ ' "confidence": 0.0',
70
+ ' }',
71
+ ' ]',
72
+ '}',
73
+ 'Skip the bullet entirely if you cannot say anything specific. Better silence than ceremony.',
74
+ ].join('\n'),
75
+ };
76
+ const user = {
77
+ role: AiMessageRole.User,
78
+ content: [`# Deterministic ${input.surface} summary`, '', input.deterministicSummary].join('\n'),
79
+ };
80
+ return [system, user];
81
+ }
82
+ function parseRecommendations(raw) {
83
+ const trimmed = raw.trim();
84
+ let jsonText = trimmed;
85
+ const fenced = trimmed.match(/```(?:json)?\s*([\s\S]*?)```/);
86
+ if (fenced)
87
+ jsonText = fenced[1].trim();
88
+ let parsed;
89
+ try {
90
+ parsed = JSON.parse(jsonText);
91
+ }
92
+ catch {
93
+ const first = jsonText.indexOf('{');
94
+ const last = jsonText.lastIndexOf('}');
95
+ if (first < 0 || last <= first)
96
+ return [];
97
+ try {
98
+ parsed = JSON.parse(jsonText.slice(first, last + 1));
99
+ }
100
+ catch {
101
+ return [];
102
+ }
103
+ }
104
+ if (!parsed || typeof parsed !== 'object')
105
+ return [];
106
+ const list = parsed.recommendations;
107
+ if (!Array.isArray(list))
108
+ return [];
109
+ const out = [];
110
+ for (const item of list) {
111
+ if (!item || typeof item !== 'object')
112
+ continue;
113
+ const obj = item;
114
+ const severity = coerceSeverity(obj.severity);
115
+ const category = typeof obj.category === 'string' && obj.category.trim()
116
+ ? obj.category.trim()
117
+ : 'other';
118
+ const title = typeof obj.title === 'string' ? obj.title.trim() : '';
119
+ const detail = typeof obj.detail === 'string' ? obj.detail.trim() : '';
120
+ if (!title || !detail)
121
+ continue;
122
+ const confidence = typeof obj.confidence === 'number' && obj.confidence >= 0 && obj.confidence <= 1
123
+ ? obj.confidence
124
+ : 0.5;
125
+ const target = typeof obj.target === 'string' && obj.target.trim() ? obj.target.trim() : undefined;
126
+ out.push({ severity, category, title, detail, confidence, ...(target ? { target } : {}) });
127
+ }
128
+ return out;
129
+ }
130
+ function coerceSeverity(value) {
131
+ if (value === 'error' || value === 'warn' || value === 'info')
132
+ return value;
133
+ if (value === 'warning')
134
+ return 'warn';
135
+ return 'info';
136
+ }
137
+ function normaliseKind(kind) {
138
+ const known = new Set(['claude', 'gemini', 'ollama', 'llamacpp']);
139
+ if (kind && known.has(kind.toLowerCase()))
140
+ return kind.toLowerCase();
141
+ return 'auto';
142
+ }
143
+ export function renderRecommendationsMarkdown(envelope) {
144
+ const out = [];
145
+ if (envelope.recommendations.length === 0) {
146
+ out.push('## LLM recommendations');
147
+ out.push('');
148
+ out.push(envelope.ai.reachable
149
+ ? '(LLM returned no actionable recommendations — the deterministic output already covers the surface.)'
150
+ : '(LLM unavailable — see the AI configuration block below to enable.)');
151
+ out.push('');
152
+ }
153
+ else {
154
+ out.push(`## LLM recommendations (${envelope.recommendations.length})`);
155
+ out.push('');
156
+ const order = ['error', 'warn', 'info'];
157
+ for (const sev of order) {
158
+ const group = envelope.recommendations.filter((r) => r.severity === sev);
159
+ if (group.length === 0)
160
+ continue;
161
+ for (const rec of group) {
162
+ out.push(`- **[${sev}]** \`${rec.category}\`${rec.target ? ` (${rec.target})` : ''} — ${rec.title} _(confidence ${rec.confidence.toFixed(2)})_`);
163
+ out.push(` - ${rec.detail}`);
164
+ }
165
+ }
166
+ out.push('');
167
+ }
168
+ out.push('---');
169
+ out.push('');
170
+ out.push(renderAiHintsCompact(envelope.ai));
171
+ return out.join('\n');
172
+ }
173
+ function renderAiHintsCompact(ai) {
174
+ const out = [];
175
+ const status = ai.reachable
176
+ ? `active via \`${ai.providerId}\``
177
+ : ai.enhancementSkipped
178
+ ? 'disabled by user'
179
+ : 'unavailable';
180
+ out.push(`### AI configuration — ${status}`);
181
+ for (const hint of ai.hints) {
182
+ out.push(`- [${hint.level}] **${hint.title}**`);
183
+ for (const step of hint.steps) {
184
+ out.push(` - ${step}`);
185
+ }
186
+ }
187
+ return out.join('\n');
188
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shrkcrft/ai",
3
- "version": "0.1.0-alpha.12",
3
+ "version": "0.1.0-alpha.14",
4
4
  "description": "SharkCraft local LLM provider abstraction: Ollama (HTTP) + llama.cpp (in-process) + multi-pass enhancement pipeline.",
5
5
  "license": "MIT",
6
6
  "author": "SharkCraft contributors",
@@ -43,8 +43,8 @@
43
43
  "typecheck": "tsc --noEmit -p tsconfig.json"
44
44
  },
45
45
  "dependencies": {
46
- "@shrkcrft/core": "^0.1.0-alpha.12",
47
- "@shrkcrft/context": "^0.1.0-alpha.12",
46
+ "@shrkcrft/core": "^0.1.0-alpha.14",
47
+ "@shrkcrft/context": "^0.1.0-alpha.14",
48
48
  "node-llama-cpp": "^3.16.0"
49
49
  },
50
50
  "publishConfig": {