@shrkcrft/cli 0.1.0-alpha.11 → 0.1.0-alpha.13
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/audit/knowledge-audit-llm.d.ts +19 -0
- package/dist/audit/knowledge-audit-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-audit-llm.js +164 -0
- package/dist/audit/knowledge-audit.d.ts +61 -0
- package/dist/audit/knowledge-audit.d.ts.map +1 -0
- package/dist/audit/knowledge-audit.js +203 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts +11 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan-llm.js +141 -0
- package/dist/audit/knowledge-fix-plan.d.ts +41 -0
- package/dist/audit/knowledge-fix-plan.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan.js +125 -0
- package/dist/audit/pipeline-audit-llm.d.ts +11 -0
- package/dist/audit/pipeline-audit-llm.d.ts.map +1 -0
- package/dist/audit/pipeline-audit-llm.js +134 -0
- package/dist/audit/pipeline-audit.d.ts +69 -0
- package/dist/audit/pipeline-audit.d.ts.map +1 -0
- package/dist/audit/pipeline-audit.js +166 -0
- package/dist/audit/templates-audit-llm.d.ts +19 -0
- package/dist/audit/templates-audit-llm.d.ts.map +1 -0
- package/dist/audit/templates-audit-llm.js +207 -0
- package/dist/audit/templates-audit.d.ts +63 -0
- package/dist/audit/templates-audit.d.ts.map +1 -0
- package/dist/audit/templates-audit.js +171 -0
- package/dist/audit/templates-fix-plan-llm.d.ts +19 -0
- package/dist/audit/templates-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan-llm.js +162 -0
- package/dist/audit/templates-fix-plan.d.ts +37 -0
- package/dist/audit/templates-fix-plan.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan.js +174 -0
- package/dist/commands/ai-status.command.d.ts +19 -0
- package/dist/commands/ai-status.command.d.ts.map +1 -0
- package/dist/commands/ai-status.command.js +94 -0
- package/dist/commands/ask.command.d.ts.map +1 -1
- package/dist/commands/ask.command.js +10 -9
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +110 -1
- package/dist/commands/deps-audit.command.d.ts +23 -0
- package/dist/commands/deps-audit.command.d.ts.map +1 -0
- package/dist/commands/deps-audit.command.js +266 -0
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +100 -3
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -1
- package/dist/commands/graph-code-subverbs.js +144 -26
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +3 -2
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +22 -1
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +3 -2
- package/dist/commands/move-plan.command.d.ts +23 -0
- package/dist/commands/move-plan.command.d.ts.map +1 -0
- package/dist/commands/move-plan.command.js +360 -0
- package/dist/commands/scaffold-validate.command.d.ts +22 -0
- package/dist/commands/scaffold-validate.command.d.ts.map +1 -0
- package/dist/commands/scaffold-validate.command.js +215 -0
- package/dist/commands/smart-context.command.d.ts +58 -0
- package/dist/commands/smart-context.command.d.ts.map +1 -0
- package/dist/commands/smart-context.command.js +4524 -0
- package/dist/commands/spike.command.d.ts +22 -0
- package/dist/commands/spike.command.d.ts.map +1 -0
- package/dist/commands/spike.command.js +235 -0
- package/dist/commands/surface.command.d.ts +1 -0
- package/dist/commands/surface.command.d.ts.map +1 -1
- package/dist/commands/surface.command.js +10 -3
- package/dist/commands/template-quality.command.d.ts.map +1 -1
- package/dist/commands/template-quality.command.js +39 -3
- package/dist/commands/templates.command.d.ts.map +1 -1
- package/dist/commands/templates.command.js +37 -2
- package/dist/commands/watch.command.d.ts +26 -0
- package/dist/commands/watch.command.d.ts.map +1 -0
- package/dist/commands/watch.command.js +456 -0
- package/dist/env/load-dotenv.d.ts +15 -0
- package/dist/env/load-dotenv.d.ts.map +1 -0
- package/dist/env/load-dotenv.js +70 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +105 -2
- package/dist/schemas/json-schemas.d.ts +384 -36
- package/dist/schemas/json-schemas.d.ts.map +1 -1
- package/dist/schemas/json-schemas.js +247 -36
- package/package.json +33 -31
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
const TEMPLATES_FILE = 'sharkcraft/templates.ts';
|
|
2
|
+
export function buildFixPlan(report) {
|
|
3
|
+
const fixes = [];
|
|
4
|
+
const skipped = [];
|
|
5
|
+
for (const entry of report.templates) {
|
|
6
|
+
for (const f of entry.deterministicFindings) {
|
|
7
|
+
const out = dispatchDeterministic(entry, f);
|
|
8
|
+
if (out.kind === 'fix')
|
|
9
|
+
fixes.push(out.fix);
|
|
10
|
+
else
|
|
11
|
+
skipped.push(out.skip);
|
|
12
|
+
}
|
|
13
|
+
for (const f of entry.llmFindings) {
|
|
14
|
+
fixes.push(makeLlmFix(entry, f));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const summary = {
|
|
18
|
+
fixCount: fixes.length,
|
|
19
|
+
highConfidence: fixes.filter((f) => f.confidence === 'high').length,
|
|
20
|
+
mediumConfidence: fixes.filter((f) => f.confidence === 'medium').length,
|
|
21
|
+
lowConfidence: fixes.filter((f) => f.confidence === 'low').length,
|
|
22
|
+
skipped: skipped.length,
|
|
23
|
+
};
|
|
24
|
+
const generatedAt = new Date().toISOString();
|
|
25
|
+
return {
|
|
26
|
+
fixPlanId: `fix-${generatedAt.replace(/[:.]/g, '-')}`,
|
|
27
|
+
generatedAt,
|
|
28
|
+
auditId: report.auditId,
|
|
29
|
+
sourceFiles: [TEMPLATES_FILE],
|
|
30
|
+
fixes,
|
|
31
|
+
skipped,
|
|
32
|
+
summary,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function dispatchDeterministic(entry, f) {
|
|
36
|
+
switch (f.category) {
|
|
37
|
+
case 'unsafe-target':
|
|
38
|
+
return {
|
|
39
|
+
kind: 'skip',
|
|
40
|
+
skip: {
|
|
41
|
+
templateId: entry.templateId,
|
|
42
|
+
findingCategory: f.category,
|
|
43
|
+
finding: f.message,
|
|
44
|
+
reason: 'security-sensitive — requires human review',
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
case 'missing-name':
|
|
48
|
+
return makeFix(entry, f, 'high', 'Add a `name` field to this template.', [
|
|
49
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
50
|
+
`Add a \`name: '<human-readable name>'\` field next to \`id\`.`,
|
|
51
|
+
`The name should briefly describe what the template scaffolds (e.g. "CLI command (shrk subcommand)").`,
|
|
52
|
+
`Do not change other fields. Verify the file still parses.`,
|
|
53
|
+
].join('\n'));
|
|
54
|
+
case 'missing-description':
|
|
55
|
+
return makeFix(entry, f, 'high', 'Add a `description` field to this template.', [
|
|
56
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
57
|
+
`Add a \`description: '<one-sentence description>'\` field. The description appears in \`shrk templates list\` and should explain what the template generates.`,
|
|
58
|
+
`Do not change other fields. Verify the file still parses.`,
|
|
59
|
+
].join('\n'));
|
|
60
|
+
case 'related-id-unresolved': {
|
|
61
|
+
const id = extractQuoted(f.message);
|
|
62
|
+
if (!id) {
|
|
63
|
+
return makeFix(entry, f, 'medium', 'Remove an unresolved related id (id could not be auto-extracted from the message).', [
|
|
64
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
65
|
+
`The finding is: "${f.message}"`,
|
|
66
|
+
`Remove the unresolved related id from the \`related\` array. Do not invent a replacement; if no real id applies, leave the array empty or omit the field.`,
|
|
67
|
+
`Verify the file still parses.`,
|
|
68
|
+
].join('\n'));
|
|
69
|
+
}
|
|
70
|
+
return makeFix(entry, f, 'high', `Remove "${id}" from the \`related\` array.`, [
|
|
71
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
72
|
+
`In its \`related\` array, remove the string "${id}". Do not change any other entries.`,
|
|
73
|
+
`Verify the file still parses and that "${id}" is not referenced elsewhere in the file.`,
|
|
74
|
+
].join('\n'));
|
|
75
|
+
}
|
|
76
|
+
case 'undocumented-var': {
|
|
77
|
+
const varName = extractQuoted(f.message);
|
|
78
|
+
const where = varName ? `the variable named "${varName}"` : 'the variable referenced in the finding';
|
|
79
|
+
return makeFix(entry, f, 'medium', varName
|
|
80
|
+
? `Add a description to variable "${varName}".`
|
|
81
|
+
: 'Add a description to an undocumented variable.', [
|
|
82
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
83
|
+
`Locate ${where} inside the \`variables\` array.`,
|
|
84
|
+
`Add a \`description: '<short explanation>'\` field. The description should explain what the variable controls and where its value ends up in the generated output.`,
|
|
85
|
+
`Verify the file still parses.`,
|
|
86
|
+
].join('\n'));
|
|
87
|
+
}
|
|
88
|
+
case 'required-var-no-example': {
|
|
89
|
+
const varName = extractQuoted(f.message);
|
|
90
|
+
const where = varName ? `the variable named "${varName}"` : 'the required variable referenced in the finding';
|
|
91
|
+
return makeFix(entry, f, 'medium', varName
|
|
92
|
+
? `Add an example value to required variable "${varName}".`
|
|
93
|
+
: 'Add an example value to a required variable that lacks one.', [
|
|
94
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
95
|
+
`Locate ${where} inside the \`variables\` array.`,
|
|
96
|
+
`Add an \`examples: ['<sample value>']\` field. Choose a sample that's representative of real usage — readable by humans, valid against any \`pattern\` that may also be defined.`,
|
|
97
|
+
`Verify the file still parses.`,
|
|
98
|
+
].join('\n'));
|
|
99
|
+
}
|
|
100
|
+
case 'undeclared-var': {
|
|
101
|
+
const varName = extractPlaceholder(f.message);
|
|
102
|
+
const where = varName ? `\`{{${varName}}}\`` : 'the undeclared placeholder named in the finding';
|
|
103
|
+
return makeFix(entry, f, 'medium', varName
|
|
104
|
+
? `Resolve undeclared placeholder ${where}.`
|
|
105
|
+
: 'Resolve an undeclared placeholder in the template body.', [
|
|
106
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
107
|
+
`The template body uses placeholder ${where} that isn't declared in \`variables[]\`.`,
|
|
108
|
+
`Pick one:`,
|
|
109
|
+
` (a) Add a corresponding entry to \`variables[]\` (with \`name\`, \`required\`, and ideally a \`description\` + \`examples\`). This is right if the placeholder represents intended user input.`,
|
|
110
|
+
` (b) Remove the placeholder from the template body. This is right if it was a typo or leftover.`,
|
|
111
|
+
`Choose based on what the surrounding body and template description imply. Verify the file still parses.`,
|
|
112
|
+
].join('\n'));
|
|
113
|
+
}
|
|
114
|
+
case 'path-no-convention': {
|
|
115
|
+
const samplePath = extractQuoted(f.message);
|
|
116
|
+
return makeFix(entry, f, 'low', samplePath
|
|
117
|
+
? `Align template targetPath with path conventions (sample: "${samplePath}").`
|
|
118
|
+
: 'Align template targetPath with path conventions.', [
|
|
119
|
+
`The sample target path${samplePath ? ` "${samplePath}"` : ''} doesn't match any entry in \`sharkcraft/paths.ts\`.`,
|
|
120
|
+
`Decide between two fixes:`,
|
|
121
|
+
` (a) Update the template's \`targetPath\` so its rendered output matches an existing path convention. Edit ${TEMPLATES_FILE}, find template "${entry.templateId}", and adjust its \`targetPath\` function/string.`,
|
|
122
|
+
` (b) Add a matching entry to \`sharkcraft/paths.ts\` if this template's output really does belong in a new location.`,
|
|
123
|
+
`Prefer (a) unless the template represents a genuinely new file-shape for the project. Verify both files parse.`,
|
|
124
|
+
].join('\n'));
|
|
125
|
+
}
|
|
126
|
+
default:
|
|
127
|
+
return makeFix(entry, f, 'low', `Address finding "${f.category}".`, [
|
|
128
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
129
|
+
`The audit reported: ${f.message}`,
|
|
130
|
+
f.suggestion ? `Suggested fix from the inspector: ${f.suggestion}` : 'No specific suggestion was supplied — use judgment.',
|
|
131
|
+
`Apply a minimal change that resolves the finding without touching unrelated fields. Verify the file still parses.`,
|
|
132
|
+
].filter(Boolean).join('\n'));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function makeFix(entry, f, confidence, intent, agentPrompt) {
|
|
136
|
+
return {
|
|
137
|
+
kind: 'fix',
|
|
138
|
+
fix: {
|
|
139
|
+
templateId: entry.templateId,
|
|
140
|
+
findingCategory: f.category,
|
|
141
|
+
finding: f.message,
|
|
142
|
+
severity: f.severity,
|
|
143
|
+
intent,
|
|
144
|
+
agentPrompt,
|
|
145
|
+
confidence,
|
|
146
|
+
source: 'deterministic',
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function makeLlmFix(entry, f) {
|
|
151
|
+
return {
|
|
152
|
+
templateId: entry.templateId,
|
|
153
|
+
findingCategory: f.category,
|
|
154
|
+
finding: f.message,
|
|
155
|
+
severity: f.severity,
|
|
156
|
+
intent: `Review the LLM-flagged "${f.category}" finding and decide whether to act.`,
|
|
157
|
+
agentPrompt: [
|
|
158
|
+
`Open ${TEMPLATES_FILE}. Find the template literal with id "${entry.templateId}".`,
|
|
159
|
+
`An LLM critique flagged (confidence ${f.confidence.toFixed(2)}): ${f.message}`,
|
|
160
|
+
`LLM findings are advisory — verify against the template body and sibling templates before acting.`,
|
|
161
|
+
`If you choose to act, keep the change minimal and scoped to the finding. If you don't, that's also a valid outcome — record the decision in your response.`,
|
|
162
|
+
].join('\n'),
|
|
163
|
+
confidence: 'low',
|
|
164
|
+
source: 'llm',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function extractQuoted(message) {
|
|
168
|
+
const m = message.match(/"([^"]+)"/);
|
|
169
|
+
return m ? m[1] : null;
|
|
170
|
+
}
|
|
171
|
+
function extractPlaceholder(message) {
|
|
172
|
+
const m = message.match(/\{\{\s*([A-Za-z_$][A-Za-z0-9_$]*)\s*\}\}/);
|
|
173
|
+
return m ? m[1] : null;
|
|
174
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ICommandHandler } from '../command-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shrk ai-status` — one-shot self-check of the LLM wiring.
|
|
4
|
+
*
|
|
5
|
+
* Designed for agents (like Claude) that want to know whether shrk's
|
|
6
|
+
* LLM enrichment is going to do anything useful, without having to
|
|
7
|
+
* run a full audit. Three pieces of information:
|
|
8
|
+
* 1. Which provider, if any, the local-first walk would pick.
|
|
9
|
+
* 2. The structured `ai` block (the same one every audit emits) so
|
|
10
|
+
* the agent can act on the hints.
|
|
11
|
+
* 3. Optional `--ping`: a tiny live request that proves the
|
|
12
|
+
* provider really responds (the resolver only checks env vars).
|
|
13
|
+
*
|
|
14
|
+
* The deterministic baseline contract: works without LLM. With no
|
|
15
|
+
* provider reachable, the output is still useful — it carries the
|
|
16
|
+
* setup hints.
|
|
17
|
+
*/
|
|
18
|
+
export declare const aiStatusCommand: ICommandHandler;
|
|
19
|
+
//# sourceMappingURL=ai-status.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-status.command.d.ts","sourceRoot":"","sources":["../../src/commands/ai-status.command.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,EAAE,eAkD7B,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { AiMessageRole, buildAiBlock, renderAiBlockMarkdown, selectAiProvider, } from '@shrkcrft/ai';
|
|
2
|
+
import { flagBool, flagNumber, flagString, } from "../command-registry.js";
|
|
3
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
4
|
+
/**
|
|
5
|
+
* `shrk ai-status` — one-shot self-check of the LLM wiring.
|
|
6
|
+
*
|
|
7
|
+
* Designed for agents (like Claude) that want to know whether shrk's
|
|
8
|
+
* LLM enrichment is going to do anything useful, without having to
|
|
9
|
+
* run a full audit. Three pieces of information:
|
|
10
|
+
* 1. Which provider, if any, the local-first walk would pick.
|
|
11
|
+
* 2. The structured `ai` block (the same one every audit emits) so
|
|
12
|
+
* the agent can act on the hints.
|
|
13
|
+
* 3. Optional `--ping`: a tiny live request that proves the
|
|
14
|
+
* provider really responds (the resolver only checks env vars).
|
|
15
|
+
*
|
|
16
|
+
* The deterministic baseline contract: works without LLM. With no
|
|
17
|
+
* provider reachable, the output is still useful — it carries the
|
|
18
|
+
* setup hints.
|
|
19
|
+
*/
|
|
20
|
+
export const aiStatusCommand = {
|
|
21
|
+
name: 'ai-status',
|
|
22
|
+
description: 'Report which AI provider shrk would use right now, with setup or upgrade hints. `--ping` verifies the provider actually responds. Read-only.',
|
|
23
|
+
usage: 'shrk ai-status [--provider auto|ollama|llamacpp|claude|gemini] [--ping] [--ping-timeout <ms>] [--json]',
|
|
24
|
+
async run(args) {
|
|
25
|
+
const providerKind = flagString(args, 'provider');
|
|
26
|
+
const json = flagBool(args, 'json');
|
|
27
|
+
const wantPing = flagBool(args, 'ping');
|
|
28
|
+
const pingTimeoutMs = flagNumber(args, 'ping-timeout') ?? 8000;
|
|
29
|
+
const selection = selectAiProvider(providerKind);
|
|
30
|
+
const ai = buildAiBlock({ selection, userOptedOut: false });
|
|
31
|
+
let ping = null;
|
|
32
|
+
if (wantPing) {
|
|
33
|
+
ping = selection.provider
|
|
34
|
+
? await pingProvider(selection.provider, pingTimeoutMs)
|
|
35
|
+
: { ok: false, reason: 'no provider reachable — nothing to ping', elapsedMs: 0 };
|
|
36
|
+
}
|
|
37
|
+
if (json) {
|
|
38
|
+
process.stdout.write(asJson({
|
|
39
|
+
ai,
|
|
40
|
+
...(ping ? { ping } : {}),
|
|
41
|
+
}) + '\n');
|
|
42
|
+
return ai.reachable && (!ping || ping.ok) ? 0 : 1;
|
|
43
|
+
}
|
|
44
|
+
process.stdout.write(header('AI status'));
|
|
45
|
+
process.stdout.write(kv('reachable', ai.reachable ? 'yes' : 'no') + '\n');
|
|
46
|
+
process.stdout.write(kv('requested provider', ai.requestedProvider) + '\n');
|
|
47
|
+
process.stdout.write(kv('resolved provider', ai.providerId ?? '(none)') + '\n');
|
|
48
|
+
if (ping) {
|
|
49
|
+
process.stdout.write(kv('ping', ping.ok
|
|
50
|
+
? `ok in ${ping.elapsedMs}ms` + (ping.model ? ` (model: ${ping.model})` : '')
|
|
51
|
+
: `failed: ${ping.reason}`) + '\n');
|
|
52
|
+
}
|
|
53
|
+
process.stdout.write('\n');
|
|
54
|
+
process.stdout.write(renderAiBlockMarkdown(ai));
|
|
55
|
+
return ai.reachable && (!ping || ping.ok) ? 0 : 1;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
async function pingProvider(provider, timeoutMs) {
|
|
59
|
+
const start = Date.now();
|
|
60
|
+
// Tiny prompt with bounded output — we just want to prove the round-trip works.
|
|
61
|
+
const requestPromise = provider.send({
|
|
62
|
+
messages: [
|
|
63
|
+
{ role: AiMessageRole.System, content: 'Respond with the single word: ok' },
|
|
64
|
+
{ role: AiMessageRole.User, content: 'ping' },
|
|
65
|
+
],
|
|
66
|
+
maxTokens: 8,
|
|
67
|
+
});
|
|
68
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
69
|
+
setTimeout(() => resolve({ ok: false, error: new Error(`timed out after ${timeoutMs}ms`) }), timeoutMs);
|
|
70
|
+
});
|
|
71
|
+
try {
|
|
72
|
+
const res = (await Promise.race([requestPromise, timeoutPromise]));
|
|
73
|
+
const elapsedMs = Date.now() - start;
|
|
74
|
+
if (!('value' in res) || !res.ok) {
|
|
75
|
+
const reason = 'error' in res
|
|
76
|
+
? res.error.message ?? String(res.error)
|
|
77
|
+
: 'no response';
|
|
78
|
+
return { ok: false, reason, elapsedMs };
|
|
79
|
+
}
|
|
80
|
+
const value = res.value;
|
|
81
|
+
return {
|
|
82
|
+
ok: true,
|
|
83
|
+
elapsedMs,
|
|
84
|
+
...(value.model ? { model: value.model } : {}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
reason: e.message,
|
|
91
|
+
elapsedMs: Date.now() - start,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask.command.d.ts","sourceRoot":"","sources":["../../src/commands/ask.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ask.command.d.ts","sourceRoot":"","sources":["../../src/commands/ask.command.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAIhC,eAAO,MAAM,UAAU,EAAE,eA6DxB,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { inspectSharkcraft, buildProjectOverview, renderOverviewText } from '@shrkcrft/inspector';
|
|
2
2
|
import { buildContext } from '@shrkcrft/context';
|
|
3
|
-
import {
|
|
3
|
+
import { AiMessageRole, buildPromptMessages, selectAiProvider, } from '@shrkcrft/ai';
|
|
4
4
|
import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { header } from "../output/format-output.js";
|
|
6
6
|
import { printError } from "../output/print-error.js";
|
|
7
7
|
export const askCommand = {
|
|
8
8
|
name: 'ask',
|
|
9
|
-
description: 'Ask a question. Builds repository context, sends prompt to
|
|
10
|
-
usage: 'shrk ask "<question>" [--max-tokens 3000] [--model
|
|
9
|
+
description: 'Ask a question. Builds repository context, sends prompt to the local LLM (Ollama / llama.cpp).',
|
|
10
|
+
usage: 'shrk ask "<question>" [--max-tokens 3000] [--provider auto|ollama|llamacpp] [--model <id>] [--dry-run]',
|
|
11
11
|
async run(args) {
|
|
12
12
|
const question = args.positional.join(' ').trim();
|
|
13
13
|
if (!question) {
|
|
@@ -16,6 +16,7 @@ export const askCommand = {
|
|
|
16
16
|
}
|
|
17
17
|
const maxTokens = flagNumber(args, 'max-tokens') ?? 3000;
|
|
18
18
|
const model = flagString(args, 'model');
|
|
19
|
+
const providerKind = flagString(args, 'provider');
|
|
19
20
|
const dryRun = flagBool(args, 'dry-run');
|
|
20
21
|
const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
|
|
21
22
|
const overview = buildProjectOverview(inspection.workspace, inspection.config?.projectName);
|
|
@@ -36,14 +37,14 @@ export const askCommand = {
|
|
|
36
37
|
}
|
|
37
38
|
return 0;
|
|
38
39
|
}
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
if (!provider.isReady()) {
|
|
43
|
-
process.stderr.write('ANTHROPIC_API_KEY is not set. Use --dry-run to print the prompt instead.\n');
|
|
40
|
+
const selection = selectAiProvider(providerKind);
|
|
41
|
+
if (!selection.provider) {
|
|
42
|
+
process.stderr.write('No local LLM is ready. Start Ollama (`ollama serve`) or set LLAMACPP_MODEL_PATH=/path/to/model.gguf in .env. Use --dry-run to print the prompt instead.\n');
|
|
44
43
|
return 1;
|
|
45
44
|
}
|
|
46
|
-
|
|
45
|
+
if (model)
|
|
46
|
+
selection.provider.configure({ model });
|
|
47
|
+
const res = await selection.provider.send({
|
|
47
48
|
messages: [...messages, { role: AiMessageRole.User, content: question }],
|
|
48
49
|
maxTokens: 1024,
|
|
49
50
|
model,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../src/commands/command-catalog.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,QAAQ,cAAc;IACtB,iBAAiB,mBAAmB;IACpC,gBAAgB,kBAAkB;IAClC,YAAY,kBAAkB;IAC9B,SAAS,eAAe;IACxB,cAAc,oBAAoB;CACnC;AAED;;;;;;GAMG;AACH,oBAAY,cAAc;IACxB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,8BAA8B;AAC9B,oBAAY,eAAe;IACzB,KAAK,UAAU;IACf,KAAK,UAAU;IACf,EAAE,OAAO;IACT,UAAU,gBAAgB;IAC1B,UAAU,eAAe;CAC1B;AAED;;;;;;GAMG;AACH,oBAAY,eAAe;IACzB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,OAAO,YAAY;IACnB,KAAK,UAAU;IACf,MAAM,WAAW;CAClB;AAED;;;;;;GAMG;AACH,oBAAY,gBAAgB;IAC1B,MAAM,WAAW;IACjB,SAAS,cAAc;IACvB,KAAK,UAAU;IACf,UAAU,eAAe;IACzB,OAAO,YAAY;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,oBAAY,WAAW;IACrB,IAAI,SAAS;IACb,QAAQ,aAAa;IACrB,YAAY,iBAAiB;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,kCAAkC;IAClC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,oBAAoB,
|
|
1
|
+
{"version":3,"file":"command-catalog.d.ts","sourceRoot":"","sources":["../../src/commands/command-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -115,6 +115,16 @@ export const COMMAND_CATALOG = Object.freeze([
|
|
|
115
115
|
intendedAudience: [CommandAudience.Human, CommandAudience.Agent, CommandAudience.Ci],
|
|
116
116
|
taskRole: CommandTaskRole.Diagnose,
|
|
117
117
|
}),
|
|
118
|
+
entry({
|
|
119
|
+
command: 'ai-status',
|
|
120
|
+
description: 'Report which AI provider shrk would use right now, with setup or upgrade hints. `--ping` verifies the provider actually responds.',
|
|
121
|
+
category: 'core',
|
|
122
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
123
|
+
mcpAvailable: false,
|
|
124
|
+
surface: CommandSurface.Common,
|
|
125
|
+
intendedAudience: [CommandAudience.Human, CommandAudience.Agent],
|
|
126
|
+
taskRole: CommandTaskRole.Diagnose,
|
|
127
|
+
}),
|
|
118
128
|
entry({
|
|
119
129
|
command: 'context',
|
|
120
130
|
description: 'Focused context for a task (rules / paths / templates). For "what should I do?" prefer `shrk recommend "<task>"`.',
|
|
@@ -256,7 +266,7 @@ export const COMMAND_CATALOG = Object.freeze([
|
|
|
256
266
|
}),
|
|
257
267
|
entry({
|
|
258
268
|
command: 'graph',
|
|
259
|
-
description: 'Knowledge graph
|
|
269
|
+
description: 'Knowledge graph plus code-intelligence subverbs (`index`, `status`, `search`, `context`, `impact`, `callers`, `cycles`, `unresolved`, `deps`, `why`, `export`).',
|
|
260
270
|
category: 'core',
|
|
261
271
|
safetyLevel: SafetyLevel.ReadOnly,
|
|
262
272
|
mcpAvailable: true,
|
|
@@ -1182,6 +1192,104 @@ export const COMMAND_CATALOG = Object.freeze([
|
|
|
1182
1192
|
category: 'core',
|
|
1183
1193
|
safetyLevel: SafetyLevel.ReadOnly,
|
|
1184
1194
|
}),
|
|
1195
|
+
entry({
|
|
1196
|
+
command: 'smart-context',
|
|
1197
|
+
description: 'Build deterministic context and ask an AI provider to synthesise an enriched brief (default), structured plan (--plan), or two-stage development plan (--ai-plan). Opt-in; defaults to Gemini. CLAUDE.md is auto-included in the seed.',
|
|
1198
|
+
category: 'core',
|
|
1199
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1200
|
+
taskRole: CommandTaskRole.Context,
|
|
1201
|
+
}),
|
|
1202
|
+
entry({
|
|
1203
|
+
command: 'smart-context plan-ahead',
|
|
1204
|
+
description: 'Batch-generate AI-backed plans for a queue of upcoming tasks and save each under .sharkcraft/smart-context/.',
|
|
1205
|
+
category: 'core',
|
|
1206
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1207
|
+
taskRole: CommandTaskRole.Context,
|
|
1208
|
+
}),
|
|
1209
|
+
entry({
|
|
1210
|
+
command: 'smart-context list',
|
|
1211
|
+
description: 'List saved smart-context entries under .sharkcraft/smart-context/.',
|
|
1212
|
+
category: 'core',
|
|
1213
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1214
|
+
taskRole: CommandTaskRole.Inspect,
|
|
1215
|
+
}),
|
|
1216
|
+
entry({
|
|
1217
|
+
command: 'smart-context show',
|
|
1218
|
+
description: 'Print a saved smart-context entry by slug.',
|
|
1219
|
+
category: 'core',
|
|
1220
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1221
|
+
taskRole: CommandTaskRole.Inspect,
|
|
1222
|
+
}),
|
|
1223
|
+
entry({
|
|
1224
|
+
command: 'smart-context embeddings-build',
|
|
1225
|
+
description: 'Build or incrementally refresh the semantic file index used by smart-context. Downloads the embedding model on first run.',
|
|
1226
|
+
category: 'core',
|
|
1227
|
+
safetyLevel: SafetyLevel.WritesSessionOnly,
|
|
1228
|
+
taskRole: CommandTaskRole.Context,
|
|
1229
|
+
}),
|
|
1230
|
+
entry({
|
|
1231
|
+
command: 'smart-context embeddings-status',
|
|
1232
|
+
description: 'Report semantic index freshness without loading the embedding model.',
|
|
1233
|
+
category: 'core',
|
|
1234
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1235
|
+
taskRole: CommandTaskRole.Inspect,
|
|
1236
|
+
}),
|
|
1237
|
+
entry({
|
|
1238
|
+
command: 'spike',
|
|
1239
|
+
description: 'Scaffold starter files for a saved smart-context plan\'s recommended MVP. Reads .sharkcraft/smart-context/<slug>.plan.json.',
|
|
1240
|
+
category: 'core',
|
|
1241
|
+
safetyLevel: SafetyLevel.WritesSource,
|
|
1242
|
+
taskRole: CommandTaskRole.Generate,
|
|
1243
|
+
}),
|
|
1244
|
+
entry({
|
|
1245
|
+
command: 'deps-audit',
|
|
1246
|
+
description: 'Compare declared package dependencies (package.json) with actually imported specifiers (graph). Reports missing + unused deps. Read-only.',
|
|
1247
|
+
category: 'core',
|
|
1248
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1249
|
+
taskRole: CommandTaskRole.Inspect,
|
|
1250
|
+
}),
|
|
1251
|
+
entry({
|
|
1252
|
+
command: 'scaffold-validate',
|
|
1253
|
+
description: 'Validate that the files in a saved generation plan exist on disk and look intact (size envelope + type match). Read-only.',
|
|
1254
|
+
category: 'core',
|
|
1255
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1256
|
+
taskRole: CommandTaskRole.Validate,
|
|
1257
|
+
}),
|
|
1258
|
+
entry({
|
|
1259
|
+
command: 'move-plan',
|
|
1260
|
+
description: 'Plan a file move: graph-traced importer rewrites, export touch-ups, cross-package warnings, rollback steps. Read-only.',
|
|
1261
|
+
category: 'core',
|
|
1262
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1263
|
+
taskRole: CommandTaskRole.Generate,
|
|
1264
|
+
}),
|
|
1265
|
+
entry({
|
|
1266
|
+
command: 'watch',
|
|
1267
|
+
description: 'Emit a focused-context packet on stdout JSONL each time the workspace changes. Designed to feed a parallel Claude agent.',
|
|
1268
|
+
category: 'core',
|
|
1269
|
+
safetyLevel: SafetyLevel.WritesSessionOnly,
|
|
1270
|
+
taskRole: CommandTaskRole.Context,
|
|
1271
|
+
}),
|
|
1272
|
+
entry({
|
|
1273
|
+
command: 'watch list',
|
|
1274
|
+
description: 'List active shrk-watch daemons (one per task slug).',
|
|
1275
|
+
category: 'core',
|
|
1276
|
+
safetyLevel: SafetyLevel.ReadOnly,
|
|
1277
|
+
taskRole: CommandTaskRole.Inspect,
|
|
1278
|
+
}),
|
|
1279
|
+
entry({
|
|
1280
|
+
command: 'watch stop',
|
|
1281
|
+
description: 'Stop a running shrk-watch daemon by slug.',
|
|
1282
|
+
category: 'core',
|
|
1283
|
+
safetyLevel: SafetyLevel.WritesSessionOnly,
|
|
1284
|
+
taskRole: CommandTaskRole.Config,
|
|
1285
|
+
}),
|
|
1286
|
+
entry({
|
|
1287
|
+
command: 'watch prune',
|
|
1288
|
+
description: 'Remove stale shrk-watch manifests whose owning processes are no longer alive.',
|
|
1289
|
+
category: 'core',
|
|
1290
|
+
safetyLevel: SafetyLevel.WritesSessionOnly,
|
|
1291
|
+
taskRole: CommandTaskRole.Config,
|
|
1292
|
+
}),
|
|
1185
1293
|
entry({
|
|
1186
1294
|
command: 'safety audit',
|
|
1187
1295
|
description: 'Audit the SharkCraft safety model (commands, MCP, packs, plan signing).',
|
|
@@ -3251,6 +3359,7 @@ const PRIMARY_VERBS_ALLOWLIST = new Set([
|
|
|
3251
3359
|
'search',
|
|
3252
3360
|
'impact',
|
|
3253
3361
|
'graph',
|
|
3362
|
+
'code-intel',
|
|
3254
3363
|
// Generate code safely
|
|
3255
3364
|
'gen',
|
|
3256
3365
|
'apply',
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ICommandHandler } from '../command-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shrk deps-audit` — for each workspace package, compare the
|
|
4
|
+
* `package.json` `dependencies` / `devDependencies` / `peerDependencies`
|
|
5
|
+
* against the *specifiers actually imported* from source under
|
|
6
|
+
* `<pkg>/src/` (per the SharkCraft graph).
|
|
7
|
+
*
|
|
8
|
+
* Reports:
|
|
9
|
+
* - missing deps: imported but not declared (likely build failure
|
|
10
|
+
* in the wild — the package depends on its host's resolution)
|
|
11
|
+
* - unused deps: declared but never imported (lint waste)
|
|
12
|
+
*
|
|
13
|
+
* Read-only. JSON output via `--json`. Optionally restricted to one
|
|
14
|
+
* package via `--package <name>`.
|
|
15
|
+
*
|
|
16
|
+
* Known limitations:
|
|
17
|
+
* - Type-only imports (`import type x from 'y'`) still count; the
|
|
18
|
+
* graph can't tell them apart in v3.
|
|
19
|
+
* - Subpath imports (`pkg/sub`) are reduced to their root specifier.
|
|
20
|
+
* - Built-in node modules (`node:fs`, `fs`, …) are ignored.
|
|
21
|
+
*/
|
|
22
|
+
export declare const depsAuditCommand: ICommandHandler;
|
|
23
|
+
//# sourceMappingURL=deps-audit.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps-audit.command.d.ts","sourceRoot":"","sources":["../../src/commands/deps-audit.command.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAmBhC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAmE9B,CAAC"}
|