ai-wingman 0.0.2 → 0.0.4
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/wingman.js +566 -575
- package/package.json +17 -2
- package/skills/SKILL.md +149 -0
package/dist/wingman.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/add/index.ts
|
|
7
|
-
import * as
|
|
8
|
-
import
|
|
7
|
+
import * as clack43 from "@clack/prompts";
|
|
8
|
+
import process22 from "process";
|
|
9
9
|
|
|
10
10
|
// src/registry/providers.ts
|
|
11
11
|
var providers = [
|
|
@@ -1625,254 +1625,8 @@ var backgroundAgentPattern = {
|
|
|
1625
1625
|
}
|
|
1626
1626
|
};
|
|
1627
1627
|
|
|
1628
|
-
// src/patterns/eval-dataset/prompt-config.ts
|
|
1629
|
-
import * as clack10 from "@clack/prompts";
|
|
1630
|
-
import path8 from "path";
|
|
1631
|
-
async function promptEvalDatasetConfig(shared, opts = {}) {
|
|
1632
|
-
const { pathAlias, targetDir } = shared;
|
|
1633
|
-
const datasetResult = await promptPath(
|
|
1634
|
-
"Dataset file output path",
|
|
1635
|
-
"evals/dataset.jsonl",
|
|
1636
|
-
targetDir,
|
|
1637
|
-
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
1638
|
-
);
|
|
1639
|
-
const runnerResult = await promptPath(
|
|
1640
|
-
"Runner script output path",
|
|
1641
|
-
"evals/dataset-runner.ts",
|
|
1642
|
-
targetDir,
|
|
1643
|
-
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
1644
|
-
);
|
|
1645
|
-
const workflowResult = await promptPath(
|
|
1646
|
-
"GitHub Actions workflow output path",
|
|
1647
|
-
".github/workflows/eval.yml",
|
|
1648
|
-
targetDir,
|
|
1649
|
-
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
1650
|
-
);
|
|
1651
|
-
if (!opts.yes) {
|
|
1652
|
-
clack10.log.info(`Run evals: npx tsx ${runnerResult.value}`);
|
|
1653
|
-
}
|
|
1654
|
-
const runnerDir = path8.dirname(runnerResult.value);
|
|
1655
|
-
const datasetRelativeFromRunner = path8.relative(runnerDir, datasetResult.value);
|
|
1656
|
-
return {
|
|
1657
|
-
paths: {
|
|
1658
|
-
dataset: datasetResult.value,
|
|
1659
|
-
runner: runnerResult.value,
|
|
1660
|
-
workflow: workflowResult.value,
|
|
1661
|
-
datasetRelativeFromRunner
|
|
1662
|
-
},
|
|
1663
|
-
pathOverwrites: {
|
|
1664
|
-
...datasetResult.overwrite && { dataset: true },
|
|
1665
|
-
...runnerResult.overwrite && { runner: true },
|
|
1666
|
-
...workflowResult.overwrite && { workflow: true }
|
|
1667
|
-
},
|
|
1668
|
-
provider: shared.provider,
|
|
1669
|
-
pathAlias,
|
|
1670
|
-
targetDir
|
|
1671
|
-
};
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
// src/patterns/eval-dataset/execute.ts
|
|
1675
|
-
import * as clack11 from "@clack/prompts";
|
|
1676
|
-
import path9 from "path";
|
|
1677
|
-
|
|
1678
|
-
// src/generators/eval-dataset-jsonl.ts
|
|
1679
|
-
function generateEvalDatasetJsonl() {
|
|
1680
|
-
const records = [
|
|
1681
|
-
{ input: "What is the capital of France?", expectedOutput: "Paris" },
|
|
1682
|
-
{ input: "What is 2 + 2?", expectedOutput: "4" },
|
|
1683
|
-
{ input: "Translate 'hello' to Spanish.", expectedOutput: "hola" },
|
|
1684
|
-
{ input: "Name a primary colour.", expectedOutput: "red, blue, or yellow" },
|
|
1685
|
-
{ input: "What does HTTP stand for?", expectedOutput: "HyperText Transfer Protocol" }
|
|
1686
|
-
];
|
|
1687
|
-
return records.map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
// src/generators/eval-dataset-runner.ts
|
|
1691
|
-
function generateEvalDatasetRunner(config) {
|
|
1692
|
-
const lines = [];
|
|
1693
|
-
lines.push("// Generated by ai-wingman \u2014 edit freely, you own this file.");
|
|
1694
|
-
lines.push("//");
|
|
1695
|
-
lines.push(`// Run with: npx tsx ${config.paths.runner}`);
|
|
1696
|
-
lines.push("//");
|
|
1697
|
-
lines.push("// Reads every record from dataset.jsonl, calls the model, then uses an");
|
|
1698
|
-
lines.push("// LLM judge to score each output 0\u20131 against expectedOutput.");
|
|
1699
|
-
lines.push("// Exits with code 1 if the mean score falls below PASS_THRESHOLD.");
|
|
1700
|
-
lines.push("");
|
|
1701
|
-
lines.push("import { createReadStream } from 'node:fs'");
|
|
1702
|
-
lines.push("import { createInterface } from 'node:readline'");
|
|
1703
|
-
lines.push("import path from 'node:path'");
|
|
1704
|
-
lines.push("import { generateText } from 'ai'");
|
|
1705
|
-
lines.push(`import { ${config.provider.importName} } from '${config.provider.package}'`);
|
|
1706
|
-
lines.push("");
|
|
1707
|
-
lines.push("// \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1708
|
-
lines.push(`const DATASET_PATH = path.resolve(import.meta.dirname, '${config.paths.datasetRelativeFromRunner}')`);
|
|
1709
|
-
lines.push(`const MODEL = ${config.provider.modelFactory}`);
|
|
1710
|
-
lines.push(`const JUDGE_MODEL = ${config.provider.modelFactory}`);
|
|
1711
|
-
lines.push("const PASS_THRESHOLD = 0.8 // mean score below this \u2192 exit 1");
|
|
1712
|
-
lines.push("");
|
|
1713
|
-
lines.push("// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1714
|
-
lines.push("interface DatasetRecord {");
|
|
1715
|
-
lines.push(" input: string");
|
|
1716
|
-
lines.push(" expectedOutput: string");
|
|
1717
|
-
lines.push("}");
|
|
1718
|
-
lines.push("");
|
|
1719
|
-
lines.push("// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1720
|
-
lines.push("async function loadDataset(): Promise<DatasetRecord[]> {");
|
|
1721
|
-
lines.push(" const records: DatasetRecord[] = []");
|
|
1722
|
-
lines.push(" const rl = createInterface({ input: createReadStream(DATASET_PATH), crlfDelay: Infinity })");
|
|
1723
|
-
lines.push(" for await (const line of rl) {");
|
|
1724
|
-
lines.push(" if (line.trim()) records.push(JSON.parse(line) as DatasetRecord)");
|
|
1725
|
-
lines.push(" }");
|
|
1726
|
-
lines.push(" return records");
|
|
1727
|
-
lines.push("}");
|
|
1728
|
-
lines.push("");
|
|
1729
|
-
lines.push("async function scoreWithJudge(output: string, expected: string): Promise<{ score: number; reason: string }> {");
|
|
1730
|
-
lines.push(" const { text } = await generateText({");
|
|
1731
|
-
lines.push(" model: JUDGE_MODEL,");
|
|
1732
|
-
lines.push(" system: 'You are an evaluator. Score whether the output satisfies the expected answer. Respond ONLY with valid JSON.',");
|
|
1733
|
-
lines.push(" prompt: [");
|
|
1734
|
-
lines.push(" 'Expected answer (or a close paraphrase of it): ' + expected,");
|
|
1735
|
-
lines.push(" 'Model output: ' + output,");
|
|
1736
|
-
lines.push(" '',");
|
|
1737
|
-
lines.push(" 'Score 1 if the output is correct or equivalent, 0.5 if partially correct, 0 if wrong.',");
|
|
1738
|
-
lines.push(` 'Respond with JSON: { "score": <0|0.5|1>, "reason": "<one sentence>" }',`);
|
|
1739
|
-
lines.push(" ].join('\\n'),");
|
|
1740
|
-
lines.push(" })");
|
|
1741
|
-
lines.push(" try {");
|
|
1742
|
-
lines.push(" const json = JSON.parse(text.match(/\\{[^}]+\\}/)?.[0] ?? '{}') as { score?: number; reason?: string }");
|
|
1743
|
-
lines.push(" return { score: json.score ?? 0, reason: json.reason ?? text }");
|
|
1744
|
-
lines.push(" } catch {");
|
|
1745
|
-
lines.push(" return { score: 0, reason: 'Judge returned non-JSON: ' + text }");
|
|
1746
|
-
lines.push(" }");
|
|
1747
|
-
lines.push("}");
|
|
1748
|
-
lines.push("");
|
|
1749
|
-
lines.push("// \u2500\u2500 Runner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
1750
|
-
lines.push("async function run() {");
|
|
1751
|
-
lines.push(" console.log('Loading dataset...')");
|
|
1752
|
-
lines.push(" const records = await loadDataset()");
|
|
1753
|
-
lines.push(" console.log(`Running ${records.length} eval cases\\n`)");
|
|
1754
|
-
lines.push("");
|
|
1755
|
-
lines.push(" const results: Array<{ input: string; score: number; reason: string }> = []");
|
|
1756
|
-
lines.push("");
|
|
1757
|
-
lines.push(" for (const record of records) {");
|
|
1758
|
-
lines.push(" process.stdout.write(` ${record.input.slice(0, 60).padEnd(62)} `)");
|
|
1759
|
-
lines.push("");
|
|
1760
|
-
lines.push(" const { text: output } = await generateText({");
|
|
1761
|
-
lines.push(" model: MODEL,");
|
|
1762
|
-
lines.push(" system: 'You are a helpful assistant. Answer concisely.',");
|
|
1763
|
-
lines.push(" prompt: record.input,");
|
|
1764
|
-
lines.push(" })");
|
|
1765
|
-
lines.push("");
|
|
1766
|
-
lines.push(" const { score, reason } = await scoreWithJudge(output, record.expectedOutput)");
|
|
1767
|
-
lines.push(" results.push({ input: record.input, score, reason })");
|
|
1768
|
-
lines.push("");
|
|
1769
|
-
lines.push(" const icon = score >= 0.8 ? '\u2713' : score >= 0.5 ? '~' : '\u2717'");
|
|
1770
|
-
lines.push(" console.log(`${icon} ${score.toFixed(2)} ${reason}`)");
|
|
1771
|
-
lines.push(" }");
|
|
1772
|
-
lines.push("");
|
|
1773
|
-
lines.push(" const mean = results.reduce((s, r) => s + r.score, 0) / results.length");
|
|
1774
|
-
lines.push(" console.log(`\\nMean score: ${mean.toFixed(2)} / 1.00 (threshold: ${PASS_THRESHOLD})`)");
|
|
1775
|
-
lines.push("");
|
|
1776
|
-
lines.push(" const failures = results.filter((r) => r.score < PASS_THRESHOLD)");
|
|
1777
|
-
lines.push(" if (failures.length > 0) {");
|
|
1778
|
-
lines.push(" console.log('\\nFailing cases:')");
|
|
1779
|
-
lines.push(" for (const f of failures) {");
|
|
1780
|
-
lines.push(" console.log(` \u2717 ${f.input.slice(0, 60)}: ${f.reason}`)");
|
|
1781
|
-
lines.push(" }");
|
|
1782
|
-
lines.push(" }");
|
|
1783
|
-
lines.push("");
|
|
1784
|
-
lines.push(" if (mean < PASS_THRESHOLD) {");
|
|
1785
|
-
lines.push(" console.error(`\\n\u2717 Eval failed \u2014 mean score ${mean.toFixed(2)} below threshold ${PASS_THRESHOLD}`)");
|
|
1786
|
-
lines.push(" process.exit(1)");
|
|
1787
|
-
lines.push(" }");
|
|
1788
|
-
lines.push(" console.log('\\n\u2713 Eval passed')");
|
|
1789
|
-
lines.push("}");
|
|
1790
|
-
lines.push("");
|
|
1791
|
-
lines.push("run().catch((err) => { console.error(err); process.exit(1) })");
|
|
1792
|
-
return lines.join("\n") + "\n";
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
// src/generators/eval-dataset-workflow.ts
|
|
1796
|
-
function generateEvalDatasetWorkflow(config) {
|
|
1797
|
-
const lines = [];
|
|
1798
|
-
lines.push("# Generated by ai-wingman \u2014 edit freely, you own this file.");
|
|
1799
|
-
lines.push("#");
|
|
1800
|
-
lines.push("# Runs the dataset eval suite on every pull request targeting main.");
|
|
1801
|
-
lines.push("# The job fails if the mean LLM-judge score drops below PASS_THRESHOLD.");
|
|
1802
|
-
lines.push("# Set OPENAI_API_KEY (or your provider key) as a repository secret.");
|
|
1803
|
-
lines.push("");
|
|
1804
|
-
lines.push("name: AI Eval");
|
|
1805
|
-
lines.push("");
|
|
1806
|
-
lines.push("on:");
|
|
1807
|
-
lines.push(" pull_request:");
|
|
1808
|
-
lines.push(" branches: [main]");
|
|
1809
|
-
lines.push(" workflow_dispatch:");
|
|
1810
|
-
lines.push("");
|
|
1811
|
-
lines.push("jobs:");
|
|
1812
|
-
lines.push(" eval:");
|
|
1813
|
-
lines.push(" name: Dataset eval");
|
|
1814
|
-
lines.push(" runs-on: ubuntu-latest");
|
|
1815
|
-
lines.push(" steps:");
|
|
1816
|
-
lines.push(" - uses: actions/checkout@v4");
|
|
1817
|
-
lines.push("");
|
|
1818
|
-
lines.push(" - uses: actions/setup-node@v4");
|
|
1819
|
-
lines.push(" with:");
|
|
1820
|
-
lines.push(" node-version: 20");
|
|
1821
|
-
lines.push(" cache: npm");
|
|
1822
|
-
lines.push("");
|
|
1823
|
-
lines.push(" - run: npm ci");
|
|
1824
|
-
lines.push("");
|
|
1825
|
-
lines.push(` - run: npx tsx ${config.paths.runner}`);
|
|
1826
|
-
lines.push(" env:");
|
|
1827
|
-
lines.push(` ${config.provider.envVar}: \${{ secrets.${config.provider.envVar} }}`);
|
|
1828
|
-
return lines.join("\n") + "\n";
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
// src/patterns/eval-dataset/execute.ts
|
|
1832
|
-
async function executeEvalDatasetPattern(config, _shared) {
|
|
1833
|
-
const write = (relPath) => (content) => {
|
|
1834
|
-
writeFile(path9.join(config.targetDir, relPath), content);
|
|
1835
|
-
clack11.log.success(`Created ${relPath}`);
|
|
1836
|
-
};
|
|
1837
|
-
write(config.paths.dataset)(generateEvalDatasetJsonl());
|
|
1838
|
-
write(config.paths.runner)(generateEvalDatasetRunner(config));
|
|
1839
|
-
write(config.paths.workflow)(generateEvalDatasetWorkflow(config));
|
|
1840
|
-
clack11.log.info(`Run evals: npx tsx ${config.paths.runner}`);
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
// src/patterns/eval-dataset/index.ts
|
|
1844
|
-
function getPackages2(config) {
|
|
1845
|
-
return [config.provider.package, "ai", "tsx"];
|
|
1846
|
-
}
|
|
1847
|
-
function getPlanEntries2(config) {
|
|
1848
|
-
return [
|
|
1849
|
-
{ kind: "create", path: config.paths.dataset, ...config.pathOverwrites.dataset && { overwrite: true } },
|
|
1850
|
-
{ kind: "create", path: config.paths.runner, ...config.pathOverwrites.runner && { overwrite: true } },
|
|
1851
|
-
{ kind: "create", path: config.paths.workflow, ...config.pathOverwrites.workflow && { overwrite: true } }
|
|
1852
|
-
];
|
|
1853
|
-
}
|
|
1854
|
-
var evalDatasetPattern = {
|
|
1855
|
-
id: "eval-dataset",
|
|
1856
|
-
description: "Dataset-driven eval suite \u2014 JSONL test cases, LLM judge scoring, GitHub Actions CI workflow",
|
|
1857
|
-
async promptConfig(shared, opts) {
|
|
1858
|
-
return promptEvalDatasetConfig(shared, opts ?? {});
|
|
1859
|
-
},
|
|
1860
|
-
getPackages(config) {
|
|
1861
|
-
return getPackages2(config);
|
|
1862
|
-
},
|
|
1863
|
-
getPlanEntries(config) {
|
|
1864
|
-
return getPlanEntries2(config);
|
|
1865
|
-
},
|
|
1866
|
-
getEnvVars(config) {
|
|
1867
|
-
return [config.provider.envVar];
|
|
1868
|
-
},
|
|
1869
|
-
async execute(config, shared) {
|
|
1870
|
-
return executeEvalDatasetPattern(config, shared);
|
|
1871
|
-
}
|
|
1872
|
-
};
|
|
1873
|
-
|
|
1874
1628
|
// src/patterns/content-moderation/prompt-config.ts
|
|
1875
|
-
import * as
|
|
1629
|
+
import * as clack10 from "@clack/prompts";
|
|
1876
1630
|
import process5 from "process";
|
|
1877
1631
|
async function promptContentModerationConfig(shared, opts = {}) {
|
|
1878
1632
|
const { pathAlias, hasSrcDir, targetDir } = shared;
|
|
@@ -1893,12 +1647,12 @@ async function promptContentModerationConfig(shared, opts = {}) {
|
|
|
1893
1647
|
if (opts.auth !== void 0) {
|
|
1894
1648
|
auth = opts.auth;
|
|
1895
1649
|
} else if (!opts.yes) {
|
|
1896
|
-
const wantsAuth = await
|
|
1650
|
+
const wantsAuth = await clack10.confirm({
|
|
1897
1651
|
message: "Add NextAuth v5 authentication?",
|
|
1898
1652
|
initialValue: false
|
|
1899
1653
|
});
|
|
1900
|
-
if (
|
|
1901
|
-
|
|
1654
|
+
if (clack10.isCancel(wantsAuth)) {
|
|
1655
|
+
clack10.cancel("Cancelled.");
|
|
1902
1656
|
process5.exit(0);
|
|
1903
1657
|
}
|
|
1904
1658
|
auth = wantsAuth === true;
|
|
@@ -1920,8 +1674,8 @@ async function promptContentModerationConfig(shared, opts = {}) {
|
|
|
1920
1674
|
}
|
|
1921
1675
|
|
|
1922
1676
|
// src/patterns/content-moderation/execute.ts
|
|
1923
|
-
import * as
|
|
1924
|
-
import
|
|
1677
|
+
import * as clack11 from "@clack/prompts";
|
|
1678
|
+
import path8 from "path";
|
|
1925
1679
|
|
|
1926
1680
|
// src/generators/content-moderation-route.ts
|
|
1927
1681
|
function toImportPath5(filePath, pathAlias) {
|
|
@@ -2028,20 +1782,20 @@ async function executeContentModerationPattern(config, _shared) {
|
|
|
2028
1782
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
2029
1783
|
const freshConfig = { ...config, pathAlias };
|
|
2030
1784
|
const write = (relPath) => (content) => {
|
|
2031
|
-
writeFile(
|
|
2032
|
-
|
|
1785
|
+
writeFile(path8.join(config.targetDir, relPath), content);
|
|
1786
|
+
clack11.log.success(`Created ${relPath}`);
|
|
2033
1787
|
};
|
|
2034
1788
|
write(freshConfig.paths.apiRoute)(generateContentModerationRoute(freshConfig));
|
|
2035
1789
|
write(freshConfig.paths.policy)(generateContentModerationPolicy());
|
|
2036
1790
|
}
|
|
2037
1791
|
|
|
2038
1792
|
// src/patterns/content-moderation/index.ts
|
|
2039
|
-
function
|
|
1793
|
+
function getPackages2(config) {
|
|
2040
1794
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
2041
1795
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
2042
1796
|
return pkgs;
|
|
2043
1797
|
}
|
|
2044
|
-
function
|
|
1798
|
+
function getPlanEntries2(config) {
|
|
2045
1799
|
return [
|
|
2046
1800
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
2047
1801
|
{ kind: "create", path: config.paths.policy, ...config.pathOverwrites.policy && { overwrite: true } }
|
|
@@ -2054,10 +1808,10 @@ var contentModerationPattern = {
|
|
|
2054
1808
|
return promptContentModerationConfig(shared, opts ?? {});
|
|
2055
1809
|
},
|
|
2056
1810
|
getPackages(config) {
|
|
2057
|
-
return
|
|
1811
|
+
return getPackages2(config);
|
|
2058
1812
|
},
|
|
2059
1813
|
getPlanEntries(config) {
|
|
2060
|
-
return
|
|
1814
|
+
return getPlanEntries2(config);
|
|
2061
1815
|
},
|
|
2062
1816
|
getEnvVars(config) {
|
|
2063
1817
|
return [config.provider.envVar];
|
|
@@ -2068,7 +1822,7 @@ var contentModerationPattern = {
|
|
|
2068
1822
|
};
|
|
2069
1823
|
|
|
2070
1824
|
// src/patterns/hybrid-search/prompt-config.ts
|
|
2071
|
-
import * as
|
|
1825
|
+
import * as clack12 from "@clack/prompts";
|
|
2072
1826
|
import process6 from "process";
|
|
2073
1827
|
function defaultEmbeddingModel(providerId) {
|
|
2074
1828
|
if (providerId === "openai") return "text-embedding-3-small";
|
|
@@ -2106,12 +1860,12 @@ async function promptHybridSearchConfig(shared, opts = {}) {
|
|
|
2106
1860
|
if (opts.embeddingModel) {
|
|
2107
1861
|
embeddingModel = opts.embeddingModel;
|
|
2108
1862
|
} else if (!opts.yes) {
|
|
2109
|
-
const input = await
|
|
1863
|
+
const input = await clack12.text({
|
|
2110
1864
|
message: "Embedding model ID?",
|
|
2111
1865
|
initialValue: embeddingModel
|
|
2112
1866
|
});
|
|
2113
|
-
if (
|
|
2114
|
-
|
|
1867
|
+
if (clack12.isCancel(input)) {
|
|
1868
|
+
clack12.cancel("Cancelled.");
|
|
2115
1869
|
process6.exit(0);
|
|
2116
1870
|
}
|
|
2117
1871
|
embeddingModel = String(input).trim() || embeddingModel;
|
|
@@ -2120,12 +1874,12 @@ async function promptHybridSearchConfig(shared, opts = {}) {
|
|
|
2120
1874
|
if (opts.auth !== void 0) {
|
|
2121
1875
|
auth = opts.auth;
|
|
2122
1876
|
} else if (!opts.yes) {
|
|
2123
|
-
const wantsAuth = await
|
|
1877
|
+
const wantsAuth = await clack12.confirm({
|
|
2124
1878
|
message: "Add NextAuth v5 authentication?",
|
|
2125
1879
|
initialValue: false
|
|
2126
1880
|
});
|
|
2127
|
-
if (
|
|
2128
|
-
|
|
1881
|
+
if (clack12.isCancel(wantsAuth)) {
|
|
1882
|
+
clack12.cancel("Cancelled.");
|
|
2129
1883
|
process6.exit(0);
|
|
2130
1884
|
}
|
|
2131
1885
|
auth = wantsAuth === true;
|
|
@@ -2152,8 +1906,8 @@ async function promptHybridSearchConfig(shared, opts = {}) {
|
|
|
2152
1906
|
}
|
|
2153
1907
|
|
|
2154
1908
|
// src/patterns/hybrid-search/execute.ts
|
|
2155
|
-
import * as
|
|
2156
|
-
import
|
|
1909
|
+
import * as clack13 from "@clack/prompts";
|
|
1910
|
+
import path9 from "path";
|
|
2157
1911
|
|
|
2158
1912
|
// src/generators/hybrid-search-route.ts
|
|
2159
1913
|
function toImportPath6(filePath, pathAlias) {
|
|
@@ -2426,8 +2180,8 @@ async function executeHybridSearchPattern(config, _shared) {
|
|
|
2426
2180
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
2427
2181
|
const freshConfig = { ...config, pathAlias };
|
|
2428
2182
|
const write = (relPath) => (content) => {
|
|
2429
|
-
writeFile(
|
|
2430
|
-
|
|
2183
|
+
writeFile(path9.join(config.targetDir, relPath), content);
|
|
2184
|
+
clack13.log.success(`Created ${relPath}`);
|
|
2431
2185
|
};
|
|
2432
2186
|
write(freshConfig.paths.apiRoute)(generateHybridSearchRoute(freshConfig));
|
|
2433
2187
|
write(freshConfig.paths.bm25)(generateHybridSearchBm25());
|
|
@@ -2436,12 +2190,12 @@ async function executeHybridSearchPattern(config, _shared) {
|
|
|
2436
2190
|
}
|
|
2437
2191
|
|
|
2438
2192
|
// src/patterns/hybrid-search/index.ts
|
|
2439
|
-
function
|
|
2193
|
+
function getPackages3(config) {
|
|
2440
2194
|
const pkgs = [config.provider.package, "ai"];
|
|
2441
2195
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
2442
2196
|
return pkgs;
|
|
2443
2197
|
}
|
|
2444
|
-
function
|
|
2198
|
+
function getPlanEntries3(config) {
|
|
2445
2199
|
return [
|
|
2446
2200
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
2447
2201
|
{ kind: "create", path: config.paths.bm25, ...config.pathOverwrites.bm25 && { overwrite: true } },
|
|
@@ -2456,10 +2210,10 @@ var hybridSearchPattern = {
|
|
|
2456
2210
|
return promptHybridSearchConfig(shared, opts ?? {});
|
|
2457
2211
|
},
|
|
2458
2212
|
getPackages(config) {
|
|
2459
|
-
return
|
|
2213
|
+
return getPackages3(config);
|
|
2460
2214
|
},
|
|
2461
2215
|
getPlanEntries(config) {
|
|
2462
|
-
return
|
|
2216
|
+
return getPlanEntries3(config);
|
|
2463
2217
|
},
|
|
2464
2218
|
getEnvVars(config) {
|
|
2465
2219
|
return [config.provider.envVar];
|
|
@@ -2470,7 +2224,7 @@ var hybridSearchPattern = {
|
|
|
2470
2224
|
};
|
|
2471
2225
|
|
|
2472
2226
|
// src/patterns/memory/prompt-config.ts
|
|
2473
|
-
import * as
|
|
2227
|
+
import * as clack14 from "@clack/prompts";
|
|
2474
2228
|
import process7 from "process";
|
|
2475
2229
|
function defaultEmbeddingModel2(providerId) {
|
|
2476
2230
|
if (providerId === "openai") return "text-embedding-3-small";
|
|
@@ -2508,12 +2262,12 @@ async function promptMemoryConfig(shared, opts = {}) {
|
|
|
2508
2262
|
if (opts.embeddingModel) {
|
|
2509
2263
|
embeddingModel = opts.embeddingModel;
|
|
2510
2264
|
} else if (!opts.yes) {
|
|
2511
|
-
const input = await
|
|
2265
|
+
const input = await clack14.text({
|
|
2512
2266
|
message: "Embedding model ID?",
|
|
2513
2267
|
initialValue: embeddingModel
|
|
2514
2268
|
});
|
|
2515
|
-
if (
|
|
2516
|
-
|
|
2269
|
+
if (clack14.isCancel(input)) {
|
|
2270
|
+
clack14.cancel("Cancelled.");
|
|
2517
2271
|
process7.exit(0);
|
|
2518
2272
|
}
|
|
2519
2273
|
embeddingModel = String(input).trim() || embeddingModel;
|
|
@@ -2522,12 +2276,12 @@ async function promptMemoryConfig(shared, opts = {}) {
|
|
|
2522
2276
|
if (opts.auth !== void 0) {
|
|
2523
2277
|
auth = opts.auth;
|
|
2524
2278
|
} else if (!opts.yes) {
|
|
2525
|
-
const wantsAuth = await
|
|
2279
|
+
const wantsAuth = await clack14.confirm({
|
|
2526
2280
|
message: "Add NextAuth v5 authentication?",
|
|
2527
2281
|
initialValue: false
|
|
2528
2282
|
});
|
|
2529
|
-
if (
|
|
2530
|
-
|
|
2283
|
+
if (clack14.isCancel(wantsAuth)) {
|
|
2284
|
+
clack14.cancel("Cancelled.");
|
|
2531
2285
|
process7.exit(0);
|
|
2532
2286
|
}
|
|
2533
2287
|
auth = wantsAuth === true;
|
|
@@ -2554,8 +2308,8 @@ async function promptMemoryConfig(shared, opts = {}) {
|
|
|
2554
2308
|
}
|
|
2555
2309
|
|
|
2556
2310
|
// src/patterns/memory/execute.ts
|
|
2557
|
-
import * as
|
|
2558
|
-
import
|
|
2311
|
+
import * as clack15 from "@clack/prompts";
|
|
2312
|
+
import path10 from "path";
|
|
2559
2313
|
|
|
2560
2314
|
// src/generators/memory-save-route.ts
|
|
2561
2315
|
function toImportPath7(filePath, pathAlias) {
|
|
@@ -2769,8 +2523,8 @@ async function executeMemoryPattern(config, _shared) {
|
|
|
2769
2523
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
2770
2524
|
const freshConfig = { ...config, pathAlias };
|
|
2771
2525
|
const write = (relPath) => (content) => {
|
|
2772
|
-
writeFile(
|
|
2773
|
-
|
|
2526
|
+
writeFile(path10.join(config.targetDir, relPath), content);
|
|
2527
|
+
clack15.log.success(`Created ${relPath}`);
|
|
2774
2528
|
};
|
|
2775
2529
|
write(freshConfig.paths.saveRoute)(generateMemorySaveRoute(freshConfig));
|
|
2776
2530
|
write(freshConfig.paths.retrieveRoute)(generateMemoryRetrieveRoute(freshConfig));
|
|
@@ -2779,12 +2533,12 @@ async function executeMemoryPattern(config, _shared) {
|
|
|
2779
2533
|
}
|
|
2780
2534
|
|
|
2781
2535
|
// src/patterns/memory/index.ts
|
|
2782
|
-
function
|
|
2536
|
+
function getPackages4(config) {
|
|
2783
2537
|
const pkgs = [config.provider.package, "ai"];
|
|
2784
2538
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
2785
2539
|
return pkgs;
|
|
2786
2540
|
}
|
|
2787
|
-
function
|
|
2541
|
+
function getPlanEntries4(config) {
|
|
2788
2542
|
return [
|
|
2789
2543
|
{ kind: "create", path: config.paths.saveRoute, ...config.pathOverwrites.saveRoute && { overwrite: true } },
|
|
2790
2544
|
{ kind: "create", path: config.paths.retrieveRoute, ...config.pathOverwrites.retrieveRoute && { overwrite: true } },
|
|
@@ -2799,10 +2553,10 @@ var memoryPattern = {
|
|
|
2799
2553
|
return promptMemoryConfig(shared, opts ?? {});
|
|
2800
2554
|
},
|
|
2801
2555
|
getPackages(config) {
|
|
2802
|
-
return
|
|
2556
|
+
return getPackages4(config);
|
|
2803
2557
|
},
|
|
2804
2558
|
getPlanEntries(config) {
|
|
2805
|
-
return
|
|
2559
|
+
return getPlanEntries4(config);
|
|
2806
2560
|
},
|
|
2807
2561
|
getEnvVars(config) {
|
|
2808
2562
|
return [config.provider.envVar];
|
|
@@ -2813,7 +2567,7 @@ var memoryPattern = {
|
|
|
2813
2567
|
};
|
|
2814
2568
|
|
|
2815
2569
|
// src/patterns/multi-agent/prompt-config.ts
|
|
2816
|
-
import * as
|
|
2570
|
+
import * as clack16 from "@clack/prompts";
|
|
2817
2571
|
import process8 from "process";
|
|
2818
2572
|
async function promptMultiAgentConfig(shared, opts = {}) {
|
|
2819
2573
|
const { pathAlias, hasSrcDir, packageManager, targetDir } = shared;
|
|
@@ -2846,12 +2600,12 @@ async function promptMultiAgentConfig(shared, opts = {}) {
|
|
|
2846
2600
|
if (opts.auth !== void 0) {
|
|
2847
2601
|
auth = opts.auth;
|
|
2848
2602
|
} else if (!opts.yes) {
|
|
2849
|
-
const wantsAuth = await
|
|
2603
|
+
const wantsAuth = await clack16.confirm({
|
|
2850
2604
|
message: "Add NextAuth v5 authentication?",
|
|
2851
2605
|
initialValue: false
|
|
2852
2606
|
});
|
|
2853
|
-
if (
|
|
2854
|
-
|
|
2607
|
+
if (clack16.isCancel(wantsAuth)) {
|
|
2608
|
+
clack16.cancel("Cancelled.");
|
|
2855
2609
|
process8.exit(0);
|
|
2856
2610
|
}
|
|
2857
2611
|
auth = wantsAuth === true;
|
|
@@ -2879,8 +2633,8 @@ async function promptMultiAgentConfig(shared, opts = {}) {
|
|
|
2879
2633
|
}
|
|
2880
2634
|
|
|
2881
2635
|
// src/patterns/multi-agent/execute.ts
|
|
2882
|
-
import * as
|
|
2883
|
-
import
|
|
2636
|
+
import * as clack17 from "@clack/prompts";
|
|
2637
|
+
import path11 from "path";
|
|
2884
2638
|
|
|
2885
2639
|
// src/generators/multi-agent-orchestrator-route.ts
|
|
2886
2640
|
function toImportPath10(filePath, pathAlias) {
|
|
@@ -3050,8 +2804,8 @@ async function executeMultiAgentPattern(config, _shared) {
|
|
|
3050
2804
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
3051
2805
|
const freshConfig = { ...config, pathAlias };
|
|
3052
2806
|
const write = (relPath) => (content) => {
|
|
3053
|
-
writeFile(
|
|
3054
|
-
|
|
2807
|
+
writeFile(path11.join(config.targetDir, relPath), content);
|
|
2808
|
+
clack17.log.success(`Created ${relPath}`);
|
|
3055
2809
|
};
|
|
3056
2810
|
write(freshConfig.paths.types)(generateMultiAgentTypes());
|
|
3057
2811
|
write(freshConfig.paths.specialists)(generateMultiAgentSpecialists(freshConfig));
|
|
@@ -3060,12 +2814,12 @@ async function executeMultiAgentPattern(config, _shared) {
|
|
|
3060
2814
|
}
|
|
3061
2815
|
|
|
3062
2816
|
// src/patterns/multi-agent/index.ts
|
|
3063
|
-
function
|
|
2817
|
+
function getPackages5(config) {
|
|
3064
2818
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
3065
2819
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
3066
2820
|
return pkgs;
|
|
3067
2821
|
}
|
|
3068
|
-
function
|
|
2822
|
+
function getPlanEntries5(config) {
|
|
3069
2823
|
return [
|
|
3070
2824
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
3071
2825
|
{ kind: "create", path: config.paths.specialists, ...config.pathOverwrites.specialists && { overwrite: true } },
|
|
@@ -3080,10 +2834,10 @@ var multiAgentPattern = {
|
|
|
3080
2834
|
return promptMultiAgentConfig(shared, opts ?? {});
|
|
3081
2835
|
},
|
|
3082
2836
|
getPackages(config) {
|
|
3083
|
-
return
|
|
2837
|
+
return getPackages5(config);
|
|
3084
2838
|
},
|
|
3085
2839
|
getPlanEntries(config) {
|
|
3086
|
-
return
|
|
2840
|
+
return getPlanEntries5(config);
|
|
3087
2841
|
},
|
|
3088
2842
|
getEnvVars(config) {
|
|
3089
2843
|
return [config.provider.envVar];
|
|
@@ -3094,7 +2848,7 @@ var multiAgentPattern = {
|
|
|
3094
2848
|
};
|
|
3095
2849
|
|
|
3096
2850
|
// src/patterns/structured-output/prompt-config.ts
|
|
3097
|
-
import * as
|
|
2851
|
+
import * as clack18 from "@clack/prompts";
|
|
3098
2852
|
import process9 from "process";
|
|
3099
2853
|
async function promptStructuredOutputConfig(shared, opts = {}) {
|
|
3100
2854
|
const { pathAlias, hasSrcDir, targetDir } = shared;
|
|
@@ -3103,7 +2857,7 @@ async function promptStructuredOutputConfig(shared, opts = {}) {
|
|
|
3103
2857
|
if (opts.schemaName) {
|
|
3104
2858
|
schemaName = opts.schemaName;
|
|
3105
2859
|
} else if (!opts.yes) {
|
|
3106
|
-
const input = await
|
|
2860
|
+
const input = await clack18.text({
|
|
3107
2861
|
message: "Schema name?",
|
|
3108
2862
|
initialValue: "output",
|
|
3109
2863
|
validate(value) {
|
|
@@ -3112,8 +2866,8 @@ async function promptStructuredOutputConfig(shared, opts = {}) {
|
|
|
3112
2866
|
return void 0;
|
|
3113
2867
|
}
|
|
3114
2868
|
});
|
|
3115
|
-
if (
|
|
3116
|
-
|
|
2869
|
+
if (clack18.isCancel(input)) {
|
|
2870
|
+
clack18.cancel("Cancelled.");
|
|
3117
2871
|
process9.exit(0);
|
|
3118
2872
|
}
|
|
3119
2873
|
schemaName = String(input).trim();
|
|
@@ -3155,12 +2909,12 @@ async function promptStructuredOutputConfig(shared, opts = {}) {
|
|
|
3155
2909
|
if (opts.auth !== void 0) {
|
|
3156
2910
|
auth = opts.auth;
|
|
3157
2911
|
} else if (!opts.yes) {
|
|
3158
|
-
const wantsAuth = await
|
|
2912
|
+
const wantsAuth = await clack18.confirm({
|
|
3159
2913
|
message: "Add NextAuth v5 authentication?",
|
|
3160
2914
|
initialValue: false
|
|
3161
2915
|
});
|
|
3162
|
-
if (
|
|
3163
|
-
|
|
2916
|
+
if (clack18.isCancel(wantsAuth)) {
|
|
2917
|
+
clack18.cancel("Cancelled.");
|
|
3164
2918
|
process9.exit(0);
|
|
3165
2919
|
}
|
|
3166
2920
|
auth = wantsAuth === true;
|
|
@@ -3177,8 +2931,8 @@ async function promptStructuredOutputConfig(shared, opts = {}) {
|
|
|
3177
2931
|
}
|
|
3178
2932
|
|
|
3179
2933
|
// src/patterns/structured-output/execute.ts
|
|
3180
|
-
import * as
|
|
3181
|
-
import
|
|
2934
|
+
import * as clack19 from "@clack/prompts";
|
|
2935
|
+
import path12 from "path";
|
|
3182
2936
|
|
|
3183
2937
|
// src/generators/structured-output-route.ts
|
|
3184
2938
|
function toImportPath13(filePath, pathAlias) {
|
|
@@ -3297,8 +3051,8 @@ async function executeStructuredOutputPattern(config, _shared) {
|
|
|
3297
3051
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
3298
3052
|
const freshConfig = { ...config, pathAlias };
|
|
3299
3053
|
const write = (relPath) => (content) => {
|
|
3300
|
-
writeFile(
|
|
3301
|
-
|
|
3054
|
+
writeFile(path12.join(config.targetDir, relPath), content);
|
|
3055
|
+
clack19.log.success(`Created ${relPath}`);
|
|
3302
3056
|
};
|
|
3303
3057
|
write(freshConfig.paths.apiRoute)(generateStructuredOutputRoute(freshConfig));
|
|
3304
3058
|
write(freshConfig.paths.schema)(generateStructuredOutputSchema(freshConfig.schemaName));
|
|
@@ -3308,12 +3062,12 @@ async function executeStructuredOutputPattern(config, _shared) {
|
|
|
3308
3062
|
}
|
|
3309
3063
|
|
|
3310
3064
|
// src/patterns/structured-output/index.ts
|
|
3311
|
-
function
|
|
3065
|
+
function getPackages6(config) {
|
|
3312
3066
|
const pkgs = [config.provider.package, "zod"];
|
|
3313
3067
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
3314
3068
|
return pkgs;
|
|
3315
3069
|
}
|
|
3316
|
-
function
|
|
3070
|
+
function getPlanEntries6(config) {
|
|
3317
3071
|
const entries = [];
|
|
3318
3072
|
entries.push({ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } });
|
|
3319
3073
|
entries.push({ kind: "create", path: config.paths.schema, ...config.pathOverwrites.schema && { overwrite: true } });
|
|
@@ -3329,10 +3083,10 @@ var structuredOutputPattern = {
|
|
|
3329
3083
|
return promptStructuredOutputConfig(shared, opts ?? {});
|
|
3330
3084
|
},
|
|
3331
3085
|
getPackages(config) {
|
|
3332
|
-
return
|
|
3086
|
+
return getPackages6(config);
|
|
3333
3087
|
},
|
|
3334
3088
|
getPlanEntries(config) {
|
|
3335
|
-
return
|
|
3089
|
+
return getPlanEntries6(config);
|
|
3336
3090
|
},
|
|
3337
3091
|
getEnvVars(config) {
|
|
3338
3092
|
return [config.provider.envVar];
|
|
@@ -3343,7 +3097,7 @@ var structuredOutputPattern = {
|
|
|
3343
3097
|
};
|
|
3344
3098
|
|
|
3345
3099
|
// src/patterns/tools/prompt-config.ts
|
|
3346
|
-
import * as
|
|
3100
|
+
import * as clack20 from "@clack/prompts";
|
|
3347
3101
|
import process10 from "process";
|
|
3348
3102
|
function toKebabCase(camel) {
|
|
3349
3103
|
return camel.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
@@ -3355,7 +3109,7 @@ async function promptToolsConfig(shared, opts = {}) {
|
|
|
3355
3109
|
if (opts.toolName) {
|
|
3356
3110
|
toolName = opts.toolName;
|
|
3357
3111
|
} else if (!opts.yes) {
|
|
3358
|
-
const input = await
|
|
3112
|
+
const input = await clack20.text({
|
|
3359
3113
|
message: "Tool name?",
|
|
3360
3114
|
initialValue: "myTool",
|
|
3361
3115
|
validate(value) {
|
|
@@ -3364,8 +3118,8 @@ async function promptToolsConfig(shared, opts = {}) {
|
|
|
3364
3118
|
return void 0;
|
|
3365
3119
|
}
|
|
3366
3120
|
});
|
|
3367
|
-
if (
|
|
3368
|
-
|
|
3121
|
+
if (clack20.isCancel(input)) {
|
|
3122
|
+
clack20.cancel("Cancelled.");
|
|
3369
3123
|
process10.exit(0);
|
|
3370
3124
|
}
|
|
3371
3125
|
toolName = String(input).trim();
|
|
@@ -3386,12 +3140,12 @@ async function promptToolsConfig(shared, opts = {}) {
|
|
|
3386
3140
|
if (opts.auth !== void 0) {
|
|
3387
3141
|
auth = opts.auth;
|
|
3388
3142
|
} else if (!opts.yes) {
|
|
3389
|
-
const wantsAuth = await
|
|
3143
|
+
const wantsAuth = await clack20.confirm({
|
|
3390
3144
|
message: "Add NextAuth v5 authentication?",
|
|
3391
3145
|
initialValue: false
|
|
3392
3146
|
});
|
|
3393
|
-
if (
|
|
3394
|
-
|
|
3147
|
+
if (clack20.isCancel(wantsAuth)) {
|
|
3148
|
+
clack20.cancel("Cancelled.");
|
|
3395
3149
|
process10.exit(0);
|
|
3396
3150
|
}
|
|
3397
3151
|
auth = wantsAuth === true;
|
|
@@ -3414,8 +3168,8 @@ async function promptToolsConfig(shared, opts = {}) {
|
|
|
3414
3168
|
}
|
|
3415
3169
|
|
|
3416
3170
|
// src/patterns/tools/execute.ts
|
|
3417
|
-
import * as
|
|
3418
|
-
import
|
|
3171
|
+
import * as clack21 from "@clack/prompts";
|
|
3172
|
+
import path13 from "path";
|
|
3419
3173
|
|
|
3420
3174
|
// src/generators/tools-route.ts
|
|
3421
3175
|
function toImportPath15(filePath, pathAlias) {
|
|
@@ -3498,20 +3252,20 @@ async function executeToolsPattern(config, _shared) {
|
|
|
3498
3252
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
3499
3253
|
const freshConfig = { ...config, pathAlias };
|
|
3500
3254
|
const write = (relPath) => (content) => {
|
|
3501
|
-
writeFile(
|
|
3502
|
-
|
|
3255
|
+
writeFile(path13.join(config.targetDir, relPath), content);
|
|
3256
|
+
clack21.log.success(`Created ${relPath}`);
|
|
3503
3257
|
};
|
|
3504
3258
|
write(freshConfig.paths.apiRoute)(generateToolsRoute(freshConfig));
|
|
3505
3259
|
write(freshConfig.paths.toolsFile)(generateToolsStub(freshConfig));
|
|
3506
3260
|
}
|
|
3507
3261
|
|
|
3508
3262
|
// src/patterns/tools/index.ts
|
|
3509
|
-
function
|
|
3263
|
+
function getPackages7(config) {
|
|
3510
3264
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
3511
3265
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
3512
3266
|
return pkgs;
|
|
3513
3267
|
}
|
|
3514
|
-
function
|
|
3268
|
+
function getPlanEntries7(config) {
|
|
3515
3269
|
return [
|
|
3516
3270
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
3517
3271
|
{ kind: "create", path: config.paths.toolsFile, ...config.pathOverwrites.toolsFile && { overwrite: true } }
|
|
@@ -3524,10 +3278,10 @@ var toolsPattern = {
|
|
|
3524
3278
|
return promptToolsConfig(shared, opts ?? {});
|
|
3525
3279
|
},
|
|
3526
3280
|
getPackages(config) {
|
|
3527
|
-
return
|
|
3281
|
+
return getPackages7(config);
|
|
3528
3282
|
},
|
|
3529
3283
|
getPlanEntries(config) {
|
|
3530
|
-
return
|
|
3284
|
+
return getPlanEntries7(config);
|
|
3531
3285
|
},
|
|
3532
3286
|
getEnvVars(config) {
|
|
3533
3287
|
return [config.provider.envVar];
|
|
@@ -3538,9 +3292,9 @@ var toolsPattern = {
|
|
|
3538
3292
|
};
|
|
3539
3293
|
|
|
3540
3294
|
// src/patterns/stream-object/prompt-config.ts
|
|
3541
|
-
import * as
|
|
3295
|
+
import * as clack22 from "@clack/prompts";
|
|
3542
3296
|
import fs6 from "fs";
|
|
3543
|
-
import
|
|
3297
|
+
import path14 from "path";
|
|
3544
3298
|
import process11 from "process";
|
|
3545
3299
|
async function promptStreamObjectConfig(shared, opts = {}) {
|
|
3546
3300
|
const { pathAlias, hasSrcDir, targetDir } = shared;
|
|
@@ -3549,7 +3303,7 @@ async function promptStreamObjectConfig(shared, opts = {}) {
|
|
|
3549
3303
|
if (opts.schemaName) {
|
|
3550
3304
|
schemaName = opts.schemaName;
|
|
3551
3305
|
} else if (!opts.yes) {
|
|
3552
|
-
const input = await
|
|
3306
|
+
const input = await clack22.text({
|
|
3553
3307
|
message: "Schema name?",
|
|
3554
3308
|
initialValue: "output",
|
|
3555
3309
|
validate(value) {
|
|
@@ -3558,8 +3312,8 @@ async function promptStreamObjectConfig(shared, opts = {}) {
|
|
|
3558
3312
|
return void 0;
|
|
3559
3313
|
}
|
|
3560
3314
|
});
|
|
3561
|
-
if (
|
|
3562
|
-
|
|
3315
|
+
if (clack22.isCancel(input)) {
|
|
3316
|
+
clack22.cancel("Cancelled.");
|
|
3563
3317
|
process11.exit(0);
|
|
3564
3318
|
}
|
|
3565
3319
|
schemaName = String(input).trim();
|
|
@@ -3576,10 +3330,10 @@ async function promptStreamObjectConfig(shared, opts = {}) {
|
|
|
3576
3330
|
targetDir,
|
|
3577
3331
|
{ ...opts.schemaPath && { prefill: opts.schemaPath }, ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
3578
3332
|
);
|
|
3579
|
-
const schemaAbsPath =
|
|
3333
|
+
const schemaAbsPath = path14.join(targetDir, schemaResult.value);
|
|
3580
3334
|
const schemaAlreadyExists = fs6.existsSync(schemaAbsPath) && !schemaResult.overwrite;
|
|
3581
3335
|
if (schemaAlreadyExists) {
|
|
3582
|
-
|
|
3336
|
+
clack22.log.info(`Schema file already exists \u2014 skipping write. Using existing schema at ${schemaResult.value}.`);
|
|
3583
3337
|
}
|
|
3584
3338
|
const paths = {
|
|
3585
3339
|
apiRoute: apiRouteResult.value,
|
|
@@ -3606,12 +3360,12 @@ async function promptStreamObjectConfig(shared, opts = {}) {
|
|
|
3606
3360
|
if (opts.auth !== void 0) {
|
|
3607
3361
|
auth = opts.auth;
|
|
3608
3362
|
} else if (!opts.yes) {
|
|
3609
|
-
const wantsAuth = await
|
|
3363
|
+
const wantsAuth = await clack22.confirm({
|
|
3610
3364
|
message: "Add NextAuth v5 authentication?",
|
|
3611
3365
|
initialValue: false
|
|
3612
3366
|
});
|
|
3613
|
-
if (
|
|
3614
|
-
|
|
3367
|
+
if (clack22.isCancel(wantsAuth)) {
|
|
3368
|
+
clack22.cancel("Cancelled.");
|
|
3615
3369
|
process11.exit(0);
|
|
3616
3370
|
}
|
|
3617
3371
|
auth = wantsAuth === true;
|
|
@@ -3629,8 +3383,8 @@ async function promptStreamObjectConfig(shared, opts = {}) {
|
|
|
3629
3383
|
}
|
|
3630
3384
|
|
|
3631
3385
|
// src/patterns/stream-object/execute.ts
|
|
3632
|
-
import * as
|
|
3633
|
-
import
|
|
3386
|
+
import * as clack23 from "@clack/prompts";
|
|
3387
|
+
import path15 from "path";
|
|
3634
3388
|
|
|
3635
3389
|
// src/generators/stream-object-route.ts
|
|
3636
3390
|
function toImportPath16(filePath, pathAlias) {
|
|
@@ -3723,8 +3477,8 @@ async function executeStreamObjectPattern(config, _shared) {
|
|
|
3723
3477
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
3724
3478
|
const freshConfig = { ...config, pathAlias };
|
|
3725
3479
|
const write = (relPath) => (content) => {
|
|
3726
|
-
writeFile(
|
|
3727
|
-
|
|
3480
|
+
writeFile(path15.join(config.targetDir, relPath), content);
|
|
3481
|
+
clack23.log.success(`Created ${relPath}`);
|
|
3728
3482
|
};
|
|
3729
3483
|
write(freshConfig.paths.apiRoute)(generateStreamObjectRoute(freshConfig));
|
|
3730
3484
|
if (!freshConfig.schemaAlreadyExists) {
|
|
@@ -3736,12 +3490,12 @@ async function executeStreamObjectPattern(config, _shared) {
|
|
|
3736
3490
|
}
|
|
3737
3491
|
|
|
3738
3492
|
// src/patterns/stream-object/index.ts
|
|
3739
|
-
function
|
|
3493
|
+
function getPackages8(config) {
|
|
3740
3494
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
3741
3495
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
3742
3496
|
return pkgs;
|
|
3743
3497
|
}
|
|
3744
|
-
function
|
|
3498
|
+
function getPlanEntries8(config) {
|
|
3745
3499
|
const entries = [];
|
|
3746
3500
|
entries.push({ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } });
|
|
3747
3501
|
if (!config.schemaAlreadyExists) {
|
|
@@ -3759,10 +3513,10 @@ var streamObjectPattern = {
|
|
|
3759
3513
|
return promptStreamObjectConfig(shared, opts ?? {});
|
|
3760
3514
|
},
|
|
3761
3515
|
getPackages(config) {
|
|
3762
|
-
return
|
|
3516
|
+
return getPackages8(config);
|
|
3763
3517
|
},
|
|
3764
3518
|
getPlanEntries(config) {
|
|
3765
|
-
return
|
|
3519
|
+
return getPlanEntries8(config);
|
|
3766
3520
|
},
|
|
3767
3521
|
getEnvVars(config) {
|
|
3768
3522
|
return [config.provider.envVar];
|
|
@@ -3773,7 +3527,7 @@ var streamObjectPattern = {
|
|
|
3773
3527
|
};
|
|
3774
3528
|
|
|
3775
3529
|
// src/patterns/rag/prompt-config.ts
|
|
3776
|
-
import * as
|
|
3530
|
+
import * as clack24 from "@clack/prompts";
|
|
3777
3531
|
import process12 from "process";
|
|
3778
3532
|
function defaultEmbeddingModel3(providerId) {
|
|
3779
3533
|
if (providerId === "openai") return "text-embedding-3-small";
|
|
@@ -3790,7 +3544,7 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3790
3544
|
} else if (opts.storage === "sqlite") {
|
|
3791
3545
|
storage = "sqlite";
|
|
3792
3546
|
} else if (!opts.yes && !opts.storage) {
|
|
3793
|
-
const selected = await
|
|
3547
|
+
const selected = await clack24.select({
|
|
3794
3548
|
message: "RAG storage backend?",
|
|
3795
3549
|
options: [
|
|
3796
3550
|
{ value: "memory", label: "In-memory", hint: "great for development" },
|
|
@@ -3798,8 +3552,8 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3798
3552
|
{ value: "pgvector", label: "pgvector", hint: "PostgreSQL + pgvector extension" }
|
|
3799
3553
|
]
|
|
3800
3554
|
});
|
|
3801
|
-
if (
|
|
3802
|
-
|
|
3555
|
+
if (clack24.isCancel(selected)) {
|
|
3556
|
+
clack24.cancel("Cancelled.");
|
|
3803
3557
|
process12.exit(0);
|
|
3804
3558
|
}
|
|
3805
3559
|
storage = selected;
|
|
@@ -3808,12 +3562,12 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3808
3562
|
if (opts.embeddingModel) {
|
|
3809
3563
|
embeddingModel = opts.embeddingModel;
|
|
3810
3564
|
} else if (!opts.yes) {
|
|
3811
|
-
const input = await
|
|
3565
|
+
const input = await clack24.text({
|
|
3812
3566
|
message: "Embedding model ID?",
|
|
3813
3567
|
initialValue: embeddingModel
|
|
3814
3568
|
});
|
|
3815
|
-
if (
|
|
3816
|
-
|
|
3569
|
+
if (clack24.isCancel(input)) {
|
|
3570
|
+
clack24.cancel("Cancelled.");
|
|
3817
3571
|
process12.exit(0);
|
|
3818
3572
|
}
|
|
3819
3573
|
embeddingModel = String(input).trim() || embeddingModel;
|
|
@@ -3822,7 +3576,7 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3822
3576
|
if (opts.chunkSize !== void 0) {
|
|
3823
3577
|
chunkSize = opts.chunkSize;
|
|
3824
3578
|
} else if (!opts.yes) {
|
|
3825
|
-
const input = await
|
|
3579
|
+
const input = await clack24.text({
|
|
3826
3580
|
message: "Chunk size (characters)?",
|
|
3827
3581
|
initialValue: "1000",
|
|
3828
3582
|
placeholder: "larger = more context per chunk; smaller = more precise retrieval",
|
|
@@ -3832,8 +3586,8 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3832
3586
|
return void 0;
|
|
3833
3587
|
}
|
|
3834
3588
|
});
|
|
3835
|
-
if (
|
|
3836
|
-
|
|
3589
|
+
if (clack24.isCancel(input)) {
|
|
3590
|
+
clack24.cancel("Cancelled.");
|
|
3837
3591
|
process12.exit(0);
|
|
3838
3592
|
}
|
|
3839
3593
|
chunkSize = parseInt(String(input)) || 1e3;
|
|
@@ -3842,12 +3596,12 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3842
3596
|
if (opts.stream !== void 0) {
|
|
3843
3597
|
stream = opts.stream;
|
|
3844
3598
|
} else if (!opts.yes) {
|
|
3845
|
-
const wantsStream = await
|
|
3599
|
+
const wantsStream = await clack24.confirm({
|
|
3846
3600
|
message: "Stream the query response?",
|
|
3847
3601
|
initialValue: true
|
|
3848
3602
|
});
|
|
3849
|
-
if (
|
|
3850
|
-
|
|
3603
|
+
if (clack24.isCancel(wantsStream)) {
|
|
3604
|
+
clack24.cancel("Cancelled.");
|
|
3851
3605
|
process12.exit(0);
|
|
3852
3606
|
}
|
|
3853
3607
|
stream = wantsStream === true;
|
|
@@ -3936,9 +3690,9 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3936
3690
|
if (opts.auth !== void 0) {
|
|
3937
3691
|
auth = opts.auth;
|
|
3938
3692
|
} else if (!opts.yes) {
|
|
3939
|
-
const wantsAuth = await
|
|
3940
|
-
if (
|
|
3941
|
-
|
|
3693
|
+
const wantsAuth = await clack24.confirm({ message: "Add NextAuth v5 authentication?", initialValue: false });
|
|
3694
|
+
if (clack24.isCancel(wantsAuth)) {
|
|
3695
|
+
clack24.cancel("Cancelled.");
|
|
3942
3696
|
process12.exit(0);
|
|
3943
3697
|
}
|
|
3944
3698
|
auth = wantsAuth === true;
|
|
@@ -3958,8 +3712,8 @@ async function promptRagConfig(shared, opts = {}) {
|
|
|
3958
3712
|
}
|
|
3959
3713
|
|
|
3960
3714
|
// src/patterns/rag/execute.ts
|
|
3961
|
-
import * as
|
|
3962
|
-
import
|
|
3715
|
+
import * as clack25 from "@clack/prompts";
|
|
3716
|
+
import path16 from "path";
|
|
3963
3717
|
|
|
3964
3718
|
// src/generators/rag-embed-route.ts
|
|
3965
3719
|
function toImportPath18(filePath, pathAlias) {
|
|
@@ -4467,8 +4221,8 @@ async function executeRagPattern(config, _shared) {
|
|
|
4467
4221
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
4468
4222
|
const freshConfig = { ...config, pathAlias };
|
|
4469
4223
|
const write = (relPath) => (content) => {
|
|
4470
|
-
writeFile(
|
|
4471
|
-
|
|
4224
|
+
writeFile(path16.join(config.targetDir, relPath), content);
|
|
4225
|
+
clack25.log.success(`Created ${relPath}`);
|
|
4472
4226
|
};
|
|
4473
4227
|
write(freshConfig.paths.embedRoute)(generateRagEmbedRoute(freshConfig));
|
|
4474
4228
|
write(freshConfig.paths.queryRoute)(generateRagQueryRoute(freshConfig));
|
|
@@ -4492,14 +4246,14 @@ async function executeRagPattern(config, _shared) {
|
|
|
4492
4246
|
}
|
|
4493
4247
|
|
|
4494
4248
|
// src/patterns/rag/index.ts
|
|
4495
|
-
function
|
|
4249
|
+
function getPackages9(config) {
|
|
4496
4250
|
const pkgs = [config.provider.package, "ai"];
|
|
4497
4251
|
if (config.storage === "pgvector") pkgs.push("postgres");
|
|
4498
4252
|
if (config.storage === "sqlite") pkgs.push("better-sqlite3", "sqlite-vec");
|
|
4499
4253
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
4500
4254
|
return pkgs;
|
|
4501
4255
|
}
|
|
4502
|
-
function
|
|
4256
|
+
function getPlanEntries9(config) {
|
|
4503
4257
|
const entries = [];
|
|
4504
4258
|
const { paths, pathOverwrites } = config;
|
|
4505
4259
|
entries.push({ kind: "create", path: paths.embedRoute, ...pathOverwrites.embedRoute && { overwrite: true } });
|
|
@@ -4528,10 +4282,10 @@ var ragPattern = {
|
|
|
4528
4282
|
return promptRagConfig(shared, opts ?? {});
|
|
4529
4283
|
},
|
|
4530
4284
|
getPackages(config) {
|
|
4531
|
-
return
|
|
4285
|
+
return getPackages9(config);
|
|
4532
4286
|
},
|
|
4533
4287
|
getPlanEntries(config) {
|
|
4534
|
-
return
|
|
4288
|
+
return getPlanEntries9(config);
|
|
4535
4289
|
},
|
|
4536
4290
|
getEnvVars(config) {
|
|
4537
4291
|
const c = config;
|
|
@@ -4546,7 +4300,7 @@ var ragPattern = {
|
|
|
4546
4300
|
};
|
|
4547
4301
|
|
|
4548
4302
|
// src/patterns/agent/prompt-config.ts
|
|
4549
|
-
import * as
|
|
4303
|
+
import * as clack26 from "@clack/prompts";
|
|
4550
4304
|
import process13 from "process";
|
|
4551
4305
|
function toKebabCase2(camel) {
|
|
4552
4306
|
return camel.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
@@ -4558,7 +4312,7 @@ async function promptAgentConfig(shared, opts = {}) {
|
|
|
4558
4312
|
if (opts.agentName) {
|
|
4559
4313
|
agentName = opts.agentName;
|
|
4560
4314
|
} else if (!opts.yes) {
|
|
4561
|
-
const input = await
|
|
4315
|
+
const input = await clack26.text({
|
|
4562
4316
|
message: "Agent name?",
|
|
4563
4317
|
initialValue: "myAgent",
|
|
4564
4318
|
validate(value) {
|
|
@@ -4567,8 +4321,8 @@ async function promptAgentConfig(shared, opts = {}) {
|
|
|
4567
4321
|
return void 0;
|
|
4568
4322
|
}
|
|
4569
4323
|
});
|
|
4570
|
-
if (
|
|
4571
|
-
|
|
4324
|
+
if (clack26.isCancel(input)) {
|
|
4325
|
+
clack26.cancel("Cancelled.");
|
|
4572
4326
|
process13.exit(0);
|
|
4573
4327
|
}
|
|
4574
4328
|
agentName = String(input).trim();
|
|
@@ -4596,12 +4350,12 @@ async function promptAgentConfig(shared, opts = {}) {
|
|
|
4596
4350
|
if (opts.page !== void 0) {
|
|
4597
4351
|
includePage = opts.page;
|
|
4598
4352
|
} else if (!opts.yes) {
|
|
4599
|
-
const wantsPage = await
|
|
4353
|
+
const wantsPage = await clack26.confirm({
|
|
4600
4354
|
message: "Generate a page component?",
|
|
4601
4355
|
initialValue: true
|
|
4602
4356
|
});
|
|
4603
|
-
if (
|
|
4604
|
-
|
|
4357
|
+
if (clack26.isCancel(wantsPage)) {
|
|
4358
|
+
clack26.cancel("Cancelled.");
|
|
4605
4359
|
process13.exit(0);
|
|
4606
4360
|
}
|
|
4607
4361
|
includePage = wantsPage === true;
|
|
@@ -4619,12 +4373,12 @@ async function promptAgentConfig(shared, opts = {}) {
|
|
|
4619
4373
|
if (opts.auth !== void 0) {
|
|
4620
4374
|
auth = opts.auth;
|
|
4621
4375
|
} else if (!opts.yes) {
|
|
4622
|
-
const wantsAuth = await
|
|
4376
|
+
const wantsAuth = await clack26.confirm({
|
|
4623
4377
|
message: "Add NextAuth v5 authentication?",
|
|
4624
4378
|
initialValue: false
|
|
4625
4379
|
});
|
|
4626
|
-
if (
|
|
4627
|
-
|
|
4380
|
+
if (clack26.isCancel(wantsAuth)) {
|
|
4381
|
+
clack26.cancel("Cancelled.");
|
|
4628
4382
|
process13.exit(0);
|
|
4629
4383
|
}
|
|
4630
4384
|
auth = wantsAuth === true;
|
|
@@ -4654,8 +4408,8 @@ async function promptAgentConfig(shared, opts = {}) {
|
|
|
4654
4408
|
}
|
|
4655
4409
|
|
|
4656
4410
|
// src/patterns/agent/execute.ts
|
|
4657
|
-
import * as
|
|
4658
|
-
import
|
|
4411
|
+
import * as clack27 from "@clack/prompts";
|
|
4412
|
+
import path17 from "path";
|
|
4659
4413
|
|
|
4660
4414
|
// src/generators/agent-route.ts
|
|
4661
4415
|
function toImportPath21(filePath, pathAlias) {
|
|
@@ -4853,8 +4607,8 @@ async function executeAgentPattern(config, _shared) {
|
|
|
4853
4607
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
4854
4608
|
const freshConfig = { ...config, pathAlias };
|
|
4855
4609
|
const write = (relPath) => (content) => {
|
|
4856
|
-
writeFile(
|
|
4857
|
-
|
|
4610
|
+
writeFile(path17.join(config.targetDir, relPath), content);
|
|
4611
|
+
clack27.log.success(`Created ${relPath}`);
|
|
4858
4612
|
};
|
|
4859
4613
|
write(freshConfig.paths.apiRoute)(generateAgentRoute(freshConfig));
|
|
4860
4614
|
write(freshConfig.paths.storage)(generateStorage());
|
|
@@ -4880,12 +4634,12 @@ async function executeAgentPattern(config, _shared) {
|
|
|
4880
4634
|
}
|
|
4881
4635
|
|
|
4882
4636
|
// src/patterns/agent/index.ts
|
|
4883
|
-
function
|
|
4637
|
+
function getPackages10(config) {
|
|
4884
4638
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
4885
4639
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
4886
4640
|
return pkgs;
|
|
4887
4641
|
}
|
|
4888
|
-
function
|
|
4642
|
+
function getPlanEntries10(config) {
|
|
4889
4643
|
const entries = [
|
|
4890
4644
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
4891
4645
|
{ kind: "create", path: config.paths.toolsFile, ...config.pathOverwrites.toolsFile && { overwrite: true } },
|
|
@@ -4903,10 +4657,10 @@ var agentPattern = {
|
|
|
4903
4657
|
return promptAgentConfig(shared, opts ?? {});
|
|
4904
4658
|
},
|
|
4905
4659
|
getPackages(config) {
|
|
4906
|
-
return
|
|
4660
|
+
return getPackages10(config);
|
|
4907
4661
|
},
|
|
4908
4662
|
getPlanEntries(config) {
|
|
4909
|
-
return
|
|
4663
|
+
return getPlanEntries10(config);
|
|
4910
4664
|
},
|
|
4911
4665
|
getEnvVars(config) {
|
|
4912
4666
|
return [config.provider.envVar];
|
|
@@ -4917,7 +4671,7 @@ var agentPattern = {
|
|
|
4917
4671
|
};
|
|
4918
4672
|
|
|
4919
4673
|
// src/patterns/multimodal/prompt-config.ts
|
|
4920
|
-
import * as
|
|
4674
|
+
import * as clack28 from "@clack/prompts";
|
|
4921
4675
|
import process14 from "process";
|
|
4922
4676
|
async function promptMultimodalConfig(shared, opts = {}) {
|
|
4923
4677
|
const { pathAlias, hasSrcDir, targetDir, packageManager } = shared;
|
|
@@ -4932,12 +4686,12 @@ async function promptMultimodalConfig(shared, opts = {}) {
|
|
|
4932
4686
|
if (opts.page !== void 0) {
|
|
4933
4687
|
includePage = opts.page;
|
|
4934
4688
|
} else if (!opts.yes) {
|
|
4935
|
-
const wantsPage = await
|
|
4689
|
+
const wantsPage = await clack28.confirm({
|
|
4936
4690
|
message: "Generate a page component with file upload UI?",
|
|
4937
4691
|
initialValue: true
|
|
4938
4692
|
});
|
|
4939
|
-
if (
|
|
4940
|
-
|
|
4693
|
+
if (clack28.isCancel(wantsPage)) {
|
|
4694
|
+
clack28.cancel("Cancelled.");
|
|
4941
4695
|
process14.exit(0);
|
|
4942
4696
|
}
|
|
4943
4697
|
includePage = wantsPage === true;
|
|
@@ -4955,12 +4709,12 @@ async function promptMultimodalConfig(shared, opts = {}) {
|
|
|
4955
4709
|
if (opts.auth !== void 0) {
|
|
4956
4710
|
auth = opts.auth;
|
|
4957
4711
|
} else if (!opts.yes) {
|
|
4958
|
-
const wantsAuth = await
|
|
4712
|
+
const wantsAuth = await clack28.confirm({
|
|
4959
4713
|
message: "Add NextAuth v5 authentication?",
|
|
4960
4714
|
initialValue: false
|
|
4961
4715
|
});
|
|
4962
|
-
if (
|
|
4963
|
-
|
|
4716
|
+
if (clack28.isCancel(wantsAuth)) {
|
|
4717
|
+
clack28.cancel("Cancelled.");
|
|
4964
4718
|
process14.exit(0);
|
|
4965
4719
|
}
|
|
4966
4720
|
auth = wantsAuth === true;
|
|
@@ -4985,8 +4739,8 @@ async function promptMultimodalConfig(shared, opts = {}) {
|
|
|
4985
4739
|
}
|
|
4986
4740
|
|
|
4987
4741
|
// src/patterns/multimodal/execute.ts
|
|
4988
|
-
import * as
|
|
4989
|
-
import
|
|
4742
|
+
import * as clack29 from "@clack/prompts";
|
|
4743
|
+
import path18 from "path";
|
|
4990
4744
|
|
|
4991
4745
|
// src/generators/multimodal-route.ts
|
|
4992
4746
|
function generateMultimodalRoute(config) {
|
|
@@ -5192,8 +4946,8 @@ async function executeMultimodalPattern(config, _shared) {
|
|
|
5192
4946
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
5193
4947
|
const freshConfig = { ...config, pathAlias };
|
|
5194
4948
|
const write = (relPath) => (content) => {
|
|
5195
|
-
writeFile(
|
|
5196
|
-
|
|
4949
|
+
writeFile(path18.join(config.targetDir, relPath), content);
|
|
4950
|
+
clack29.log.success(`Created ${relPath}`);
|
|
5197
4951
|
};
|
|
5198
4952
|
write(freshConfig.paths.apiRoute)(generateMultimodalRoute(freshConfig));
|
|
5199
4953
|
if (freshConfig.includePage && freshConfig.paths.page) {
|
|
@@ -5208,12 +4962,12 @@ async function executeMultimodalPattern(config, _shared) {
|
|
|
5208
4962
|
}
|
|
5209
4963
|
|
|
5210
4964
|
// src/patterns/multimodal/index.ts
|
|
5211
|
-
function
|
|
4965
|
+
function getPackages11(config) {
|
|
5212
4966
|
const pkgs = [config.provider.package, "ai"];
|
|
5213
4967
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
5214
4968
|
return pkgs;
|
|
5215
4969
|
}
|
|
5216
|
-
function
|
|
4970
|
+
function getPlanEntries11(config) {
|
|
5217
4971
|
const entries = [
|
|
5218
4972
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } }
|
|
5219
4973
|
];
|
|
@@ -5229,10 +4983,10 @@ var multimodalPattern = {
|
|
|
5229
4983
|
return promptMultimodalConfig(shared, opts ?? {});
|
|
5230
4984
|
},
|
|
5231
4985
|
getPackages(config) {
|
|
5232
|
-
return
|
|
4986
|
+
return getPackages11(config);
|
|
5233
4987
|
},
|
|
5234
4988
|
getPlanEntries(config) {
|
|
5235
|
-
return
|
|
4989
|
+
return getPlanEntries11(config);
|
|
5236
4990
|
},
|
|
5237
4991
|
getEnvVars(config) {
|
|
5238
4992
|
return [config.provider.envVar];
|
|
@@ -5302,8 +5056,8 @@ async function promptInterruptConfig(shared, opts = {}) {
|
|
|
5302
5056
|
}
|
|
5303
5057
|
|
|
5304
5058
|
// src/patterns/interrupt/execute.ts
|
|
5305
|
-
import * as
|
|
5306
|
-
import
|
|
5059
|
+
import * as clack30 from "@clack/prompts";
|
|
5060
|
+
import path19 from "path";
|
|
5307
5061
|
|
|
5308
5062
|
// src/generators/interrupt-route.ts
|
|
5309
5063
|
function toImportPath22(filePath, pathAlias) {
|
|
@@ -5441,8 +5195,8 @@ async function executeInterruptPattern(config, _shared) {
|
|
|
5441
5195
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
5442
5196
|
const freshConfig = { ...config, pathAlias };
|
|
5443
5197
|
const write = (relPath) => (content) => {
|
|
5444
|
-
writeFile(
|
|
5445
|
-
|
|
5198
|
+
writeFile(path19.join(config.targetDir, relPath), content);
|
|
5199
|
+
clack30.log.success(`Created ${relPath}`);
|
|
5446
5200
|
};
|
|
5447
5201
|
write(freshConfig.paths.apiRoute)(generateInterruptRoute(freshConfig));
|
|
5448
5202
|
write(freshConfig.paths.tools)(generateInterruptTools(freshConfig));
|
|
@@ -5450,17 +5204,17 @@ async function executeInterruptPattern(config, _shared) {
|
|
|
5450
5204
|
if (freshConfig.includePage && freshConfig.paths.page) {
|
|
5451
5205
|
write(freshConfig.paths.page)(generateInterruptPage(freshConfig));
|
|
5452
5206
|
}
|
|
5453
|
-
|
|
5207
|
+
clack30.note(
|
|
5454
5208
|
"\u26A0 The interrupt pattern is pending further discovery.\nBehaviour under multi-tool sequences and concurrent approval requests\nis not yet fully characterised. Review carefully before production use.",
|
|
5455
5209
|
"Important"
|
|
5456
5210
|
);
|
|
5457
5211
|
}
|
|
5458
5212
|
|
|
5459
5213
|
// src/patterns/interrupt/index.ts
|
|
5460
|
-
function
|
|
5214
|
+
function getPackages12(config) {
|
|
5461
5215
|
return [config.provider.package, "@ai-sdk/react", "zod"];
|
|
5462
5216
|
}
|
|
5463
|
-
function
|
|
5217
|
+
function getPlanEntries12(config) {
|
|
5464
5218
|
const entries = [];
|
|
5465
5219
|
const { paths, pathOverwrites } = config;
|
|
5466
5220
|
entries.push({ kind: "create", path: paths.apiRoute, ...pathOverwrites.apiRoute && { overwrite: true } });
|
|
@@ -5478,10 +5232,10 @@ var interruptPattern = {
|
|
|
5478
5232
|
return promptInterruptConfig(shared, opts ?? {});
|
|
5479
5233
|
},
|
|
5480
5234
|
getPackages(config) {
|
|
5481
|
-
return
|
|
5235
|
+
return getPackages12(config);
|
|
5482
5236
|
},
|
|
5483
5237
|
getPlanEntries(config) {
|
|
5484
|
-
return
|
|
5238
|
+
return getPlanEntries12(config);
|
|
5485
5239
|
},
|
|
5486
5240
|
getEnvVars(config) {
|
|
5487
5241
|
return [config.provider.envVar];
|
|
@@ -5492,21 +5246,89 @@ var interruptPattern = {
|
|
|
5492
5246
|
};
|
|
5493
5247
|
|
|
5494
5248
|
// src/patterns/eval/prompt-config.ts
|
|
5495
|
-
import * as
|
|
5249
|
+
import * as clack31 from "@clack/prompts";
|
|
5250
|
+
import path20 from "path";
|
|
5251
|
+
import process15 from "process";
|
|
5496
5252
|
async function promptEvalConfig(shared, opts = {}) {
|
|
5497
5253
|
const { pathAlias, targetDir } = shared;
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5254
|
+
let useDataset = opts.dataset ?? false;
|
|
5255
|
+
if (!useDataset && !opts.yes) {
|
|
5256
|
+
const answer = await clack31.confirm({
|
|
5257
|
+
message: "Use a dataset file (JSONL)?",
|
|
5258
|
+
initialValue: false
|
|
5259
|
+
});
|
|
5260
|
+
if (clack31.isCancel(answer)) {
|
|
5261
|
+
clack31.cancel();
|
|
5262
|
+
process15.exit(0);
|
|
5263
|
+
}
|
|
5264
|
+
useDataset = answer;
|
|
5265
|
+
}
|
|
5266
|
+
let evalScriptResult;
|
|
5267
|
+
let datasetResult;
|
|
5268
|
+
let runnerResult;
|
|
5269
|
+
if (useDataset) {
|
|
5270
|
+
datasetResult = await promptPath(
|
|
5271
|
+
"Dataset file output path",
|
|
5272
|
+
"evals/dataset.jsonl",
|
|
5273
|
+
targetDir,
|
|
5274
|
+
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
5275
|
+
);
|
|
5276
|
+
runnerResult = await promptPath(
|
|
5277
|
+
"Runner script output path",
|
|
5278
|
+
"evals/dataset-runner.ts",
|
|
5279
|
+
targetDir,
|
|
5280
|
+
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
5281
|
+
);
|
|
5282
|
+
} else {
|
|
5283
|
+
evalScriptResult = await promptPath(
|
|
5284
|
+
"Eval script output path",
|
|
5285
|
+
"evals/my-eval.ts",
|
|
5286
|
+
targetDir,
|
|
5287
|
+
{ ...opts.evalPath && { prefill: opts.evalPath }, ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
5288
|
+
);
|
|
5506
5289
|
}
|
|
5290
|
+
let includeWorkflow = opts.ci ?? false;
|
|
5291
|
+
if (!includeWorkflow && !opts.yes) {
|
|
5292
|
+
const answer = await clack31.confirm({
|
|
5293
|
+
message: "Add GitHub Actions CI workflow?",
|
|
5294
|
+
initialValue: false
|
|
5295
|
+
});
|
|
5296
|
+
if (clack31.isCancel(answer)) {
|
|
5297
|
+
clack31.cancel();
|
|
5298
|
+
process15.exit(0);
|
|
5299
|
+
}
|
|
5300
|
+
includeWorkflow = answer;
|
|
5301
|
+
}
|
|
5302
|
+
let workflowResult;
|
|
5303
|
+
if (includeWorkflow) {
|
|
5304
|
+
workflowResult = await promptPath(
|
|
5305
|
+
"GitHub Actions workflow output path",
|
|
5306
|
+
".github/workflows/eval.yml",
|
|
5307
|
+
targetDir,
|
|
5308
|
+
{ ...opts.overwrite && { overwrite: true }, ...opts.yes && { yes: true } }
|
|
5309
|
+
);
|
|
5310
|
+
}
|
|
5311
|
+
if (!opts.yes) {
|
|
5312
|
+
const runPath = useDataset ? runnerResult.value : evalScriptResult.value;
|
|
5313
|
+
clack31.log.info(`Run evals: npx tsx ${runPath}`);
|
|
5314
|
+
}
|
|
5315
|
+
const datasetRelativeFromRunner = datasetResult && runnerResult ? path20.relative(path20.dirname(runnerResult.value), datasetResult.value) : void 0;
|
|
5507
5316
|
return {
|
|
5508
|
-
|
|
5509
|
-
|
|
5317
|
+
useDataset,
|
|
5318
|
+
includeWorkflow,
|
|
5319
|
+
paths: {
|
|
5320
|
+
...evalScriptResult && { evalScript: evalScriptResult.value },
|
|
5321
|
+
...datasetResult && { dataset: datasetResult.value },
|
|
5322
|
+
...runnerResult && { runner: runnerResult.value },
|
|
5323
|
+
...datasetRelativeFromRunner && { datasetRelativeFromRunner },
|
|
5324
|
+
...workflowResult && { workflow: workflowResult.value }
|
|
5325
|
+
},
|
|
5326
|
+
pathOverwrites: {
|
|
5327
|
+
...evalScriptResult?.overwrite && { evalScript: true },
|
|
5328
|
+
...datasetResult?.overwrite && { dataset: true },
|
|
5329
|
+
...runnerResult?.overwrite && { runner: true },
|
|
5330
|
+
...workflowResult?.overwrite && { workflow: true }
|
|
5331
|
+
},
|
|
5510
5332
|
provider: shared.provider,
|
|
5511
5333
|
pathAlias,
|
|
5512
5334
|
targetDir
|
|
@@ -5514,8 +5336,8 @@ async function promptEvalConfig(shared, opts = {}) {
|
|
|
5514
5336
|
}
|
|
5515
5337
|
|
|
5516
5338
|
// src/patterns/eval/execute.ts
|
|
5517
|
-
import * as
|
|
5518
|
-
import
|
|
5339
|
+
import * as clack32 from "@clack/prompts";
|
|
5340
|
+
import path21 from "path";
|
|
5519
5341
|
|
|
5520
5342
|
// src/generators/eval-script.ts
|
|
5521
5343
|
function generateEvalScript(config) {
|
|
@@ -5634,20 +5456,182 @@ runEvals().catch((err) => {
|
|
|
5634
5456
|
`;
|
|
5635
5457
|
}
|
|
5636
5458
|
|
|
5459
|
+
// src/generators/eval-dataset-jsonl.ts
|
|
5460
|
+
function generateEvalDatasetJsonl() {
|
|
5461
|
+
const records = [
|
|
5462
|
+
{ input: "What is the capital of France?", expectedOutput: "Paris" },
|
|
5463
|
+
{ input: "What is 2 + 2?", expectedOutput: "4" },
|
|
5464
|
+
{ input: "Translate 'hello' to Spanish.", expectedOutput: "hola" },
|
|
5465
|
+
{ input: "Name a primary colour.", expectedOutput: "red, blue, or yellow" },
|
|
5466
|
+
{ input: "What does HTTP stand for?", expectedOutput: "HyperText Transfer Protocol" }
|
|
5467
|
+
];
|
|
5468
|
+
return records.map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
5469
|
+
}
|
|
5470
|
+
|
|
5471
|
+
// src/generators/eval-dataset-runner.ts
|
|
5472
|
+
function generateEvalDatasetRunner(config) {
|
|
5473
|
+
const lines = [];
|
|
5474
|
+
lines.push("// Generated by ai-wingman \u2014 edit freely, you own this file.");
|
|
5475
|
+
lines.push("//");
|
|
5476
|
+
lines.push(`// Run with: npx tsx ${config.paths.runner}`);
|
|
5477
|
+
lines.push("//");
|
|
5478
|
+
lines.push("// Reads every record from dataset.jsonl, calls the model, then uses an");
|
|
5479
|
+
lines.push("// LLM judge to score each output 0\u20131 against expectedOutput.");
|
|
5480
|
+
lines.push("// Exits with code 1 if the mean score falls below PASS_THRESHOLD.");
|
|
5481
|
+
lines.push("");
|
|
5482
|
+
lines.push("import { createReadStream } from 'node:fs'");
|
|
5483
|
+
lines.push("import { createInterface } from 'node:readline'");
|
|
5484
|
+
lines.push("import path from 'node:path'");
|
|
5485
|
+
lines.push("import { generateText } from 'ai'");
|
|
5486
|
+
lines.push(`import { ${config.provider.importName} } from '${config.provider.package}'`);
|
|
5487
|
+
lines.push("");
|
|
5488
|
+
lines.push("// \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5489
|
+
lines.push(`const DATASET_PATH = path.resolve(import.meta.dirname, '${config.paths.datasetRelativeFromRunner}')`);
|
|
5490
|
+
lines.push(`const MODEL = ${config.provider.modelFactory}`);
|
|
5491
|
+
lines.push(`const JUDGE_MODEL = ${config.provider.modelFactory}`);
|
|
5492
|
+
lines.push("const PASS_THRESHOLD = 0.8 // mean score below this \u2192 exit 1");
|
|
5493
|
+
lines.push("");
|
|
5494
|
+
lines.push("// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5495
|
+
lines.push("interface DatasetRecord {");
|
|
5496
|
+
lines.push(" input: string");
|
|
5497
|
+
lines.push(" expectedOutput: string");
|
|
5498
|
+
lines.push("}");
|
|
5499
|
+
lines.push("");
|
|
5500
|
+
lines.push("// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5501
|
+
lines.push("async function loadDataset(): Promise<DatasetRecord[]> {");
|
|
5502
|
+
lines.push(" const records: DatasetRecord[] = []");
|
|
5503
|
+
lines.push(" const rl = createInterface({ input: createReadStream(DATASET_PATH), crlfDelay: Infinity })");
|
|
5504
|
+
lines.push(" for await (const line of rl) {");
|
|
5505
|
+
lines.push(" if (line.trim()) records.push(JSON.parse(line) as DatasetRecord)");
|
|
5506
|
+
lines.push(" }");
|
|
5507
|
+
lines.push(" return records");
|
|
5508
|
+
lines.push("}");
|
|
5509
|
+
lines.push("");
|
|
5510
|
+
lines.push("async function scoreWithJudge(output: string, expected: string): Promise<{ score: number; reason: string }> {");
|
|
5511
|
+
lines.push(" const { text } = await generateText({");
|
|
5512
|
+
lines.push(" model: JUDGE_MODEL,");
|
|
5513
|
+
lines.push(" system: 'You are an evaluator. Score whether the output satisfies the expected answer. Respond ONLY with valid JSON.',");
|
|
5514
|
+
lines.push(" prompt: [");
|
|
5515
|
+
lines.push(" 'Expected answer (or a close paraphrase of it): ' + expected,");
|
|
5516
|
+
lines.push(" 'Model output: ' + output,");
|
|
5517
|
+
lines.push(" '',");
|
|
5518
|
+
lines.push(" 'Score 1 if the output is correct or equivalent, 0.5 if partially correct, 0 if wrong.',");
|
|
5519
|
+
lines.push(` 'Respond with JSON: { "score": <0|0.5|1>, "reason": "<one sentence>" }',`);
|
|
5520
|
+
lines.push(" ].join('\\n'),");
|
|
5521
|
+
lines.push(" })");
|
|
5522
|
+
lines.push(" try {");
|
|
5523
|
+
lines.push(" const json = JSON.parse(text.match(/\\{[^}]+\\}/)?.[0] ?? '{}') as { score?: number; reason?: string }");
|
|
5524
|
+
lines.push(" return { score: json.score ?? 0, reason: json.reason ?? text }");
|
|
5525
|
+
lines.push(" } catch {");
|
|
5526
|
+
lines.push(" return { score: 0, reason: 'Judge returned non-JSON: ' + text }");
|
|
5527
|
+
lines.push(" }");
|
|
5528
|
+
lines.push("}");
|
|
5529
|
+
lines.push("");
|
|
5530
|
+
lines.push("// \u2500\u2500 Runner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5531
|
+
lines.push("async function run() {");
|
|
5532
|
+
lines.push(" console.log('Loading dataset...')");
|
|
5533
|
+
lines.push(" const records = await loadDataset()");
|
|
5534
|
+
lines.push(" console.log(`Running ${records.length} eval cases\\n`)");
|
|
5535
|
+
lines.push("");
|
|
5536
|
+
lines.push(" const results: Array<{ input: string; score: number; reason: string }> = []");
|
|
5537
|
+
lines.push("");
|
|
5538
|
+
lines.push(" for (const record of records) {");
|
|
5539
|
+
lines.push(" process.stdout.write(` ${record.input.slice(0, 60).padEnd(62)} `)");
|
|
5540
|
+
lines.push("");
|
|
5541
|
+
lines.push(" const { text: output } = await generateText({");
|
|
5542
|
+
lines.push(" model: MODEL,");
|
|
5543
|
+
lines.push(" system: 'You are a helpful assistant. Answer concisely.',");
|
|
5544
|
+
lines.push(" prompt: record.input,");
|
|
5545
|
+
lines.push(" })");
|
|
5546
|
+
lines.push("");
|
|
5547
|
+
lines.push(" const { score, reason } = await scoreWithJudge(output, record.expectedOutput)");
|
|
5548
|
+
lines.push(" results.push({ input: record.input, score, reason })");
|
|
5549
|
+
lines.push("");
|
|
5550
|
+
lines.push(" const icon = score >= 0.8 ? '\u2713' : score >= 0.5 ? '~' : '\u2717'");
|
|
5551
|
+
lines.push(" console.log(`${icon} ${score.toFixed(2)} ${reason}`)");
|
|
5552
|
+
lines.push(" }");
|
|
5553
|
+
lines.push("");
|
|
5554
|
+
lines.push(" const mean = results.reduce((s, r) => s + r.score, 0) / results.length");
|
|
5555
|
+
lines.push(" console.log(`\\nMean score: ${mean.toFixed(2)} / 1.00 (threshold: ${PASS_THRESHOLD})`)");
|
|
5556
|
+
lines.push("");
|
|
5557
|
+
lines.push(" const failures = results.filter((r) => r.score < PASS_THRESHOLD)");
|
|
5558
|
+
lines.push(" if (failures.length > 0) {");
|
|
5559
|
+
lines.push(" console.log('\\nFailing cases:')");
|
|
5560
|
+
lines.push(" for (const f of failures) {");
|
|
5561
|
+
lines.push(" console.log(` \u2717 ${f.input.slice(0, 60)}: ${f.reason}`)");
|
|
5562
|
+
lines.push(" }");
|
|
5563
|
+
lines.push(" }");
|
|
5564
|
+
lines.push("");
|
|
5565
|
+
lines.push(" if (mean < PASS_THRESHOLD) {");
|
|
5566
|
+
lines.push(" console.error(`\\n\u2717 Eval failed \u2014 mean score ${mean.toFixed(2)} below threshold ${PASS_THRESHOLD}`)");
|
|
5567
|
+
lines.push(" process.exit(1)");
|
|
5568
|
+
lines.push(" }");
|
|
5569
|
+
lines.push(" console.log('\\n\u2713 Eval passed')");
|
|
5570
|
+
lines.push("}");
|
|
5571
|
+
lines.push("");
|
|
5572
|
+
lines.push("run().catch((err) => { console.error(err); process.exit(1) })");
|
|
5573
|
+
return lines.join("\n") + "\n";
|
|
5574
|
+
}
|
|
5575
|
+
|
|
5576
|
+
// src/generators/eval-dataset-workflow.ts
|
|
5577
|
+
function generateEvalDatasetWorkflow(config) {
|
|
5578
|
+
const lines = [];
|
|
5579
|
+
lines.push("# Generated by ai-wingman \u2014 edit freely, you own this file.");
|
|
5580
|
+
lines.push("#");
|
|
5581
|
+
lines.push("# Runs the dataset eval suite on every pull request targeting main.");
|
|
5582
|
+
lines.push("# The job fails if the mean LLM-judge score drops below PASS_THRESHOLD.");
|
|
5583
|
+
lines.push("# Set OPENAI_API_KEY (or your provider key) as a repository secret.");
|
|
5584
|
+
lines.push("");
|
|
5585
|
+
lines.push("name: AI Eval");
|
|
5586
|
+
lines.push("");
|
|
5587
|
+
lines.push("on:");
|
|
5588
|
+
lines.push(" pull_request:");
|
|
5589
|
+
lines.push(" branches: [main]");
|
|
5590
|
+
lines.push(" workflow_dispatch:");
|
|
5591
|
+
lines.push("");
|
|
5592
|
+
lines.push("jobs:");
|
|
5593
|
+
lines.push(" eval:");
|
|
5594
|
+
lines.push(" name: Dataset eval");
|
|
5595
|
+
lines.push(" runs-on: ubuntu-latest");
|
|
5596
|
+
lines.push(" steps:");
|
|
5597
|
+
lines.push(" - uses: actions/checkout@v4");
|
|
5598
|
+
lines.push("");
|
|
5599
|
+
lines.push(" - uses: actions/setup-node@v4");
|
|
5600
|
+
lines.push(" with:");
|
|
5601
|
+
lines.push(" node-version: 20");
|
|
5602
|
+
lines.push(" cache: npm");
|
|
5603
|
+
lines.push("");
|
|
5604
|
+
lines.push(" - run: npm ci");
|
|
5605
|
+
lines.push("");
|
|
5606
|
+
lines.push(` - run: npx tsx ${config.paths.runner}`);
|
|
5607
|
+
lines.push(" env:");
|
|
5608
|
+
lines.push(` ${config.provider.envVar}: \${{ secrets.${config.provider.envVar} }}`);
|
|
5609
|
+
return lines.join("\n") + "\n";
|
|
5610
|
+
}
|
|
5611
|
+
|
|
5637
5612
|
// src/patterns/eval/execute.ts
|
|
5638
5613
|
async function executeEvalPattern(config, _shared) {
|
|
5639
5614
|
const write = (relPath) => (content) => {
|
|
5640
|
-
writeFile(
|
|
5641
|
-
|
|
5615
|
+
writeFile(path21.join(config.targetDir, relPath), content);
|
|
5616
|
+
clack32.log.success(`Created ${relPath}`);
|
|
5642
5617
|
};
|
|
5643
|
-
|
|
5644
|
-
|
|
5618
|
+
if (config.useDataset) {
|
|
5619
|
+
write(config.paths.dataset)(generateEvalDatasetJsonl());
|
|
5620
|
+
write(config.paths.runner)(generateEvalDatasetRunner(config));
|
|
5621
|
+
clack32.log.info(`Run evals: npx tsx ${config.paths.runner}`);
|
|
5622
|
+
} else {
|
|
5623
|
+
write(config.paths.evalScript)(generateEvalScript(config));
|
|
5624
|
+
clack32.log.info(`Run evals: npx tsx ${config.paths.evalScript}`);
|
|
5625
|
+
}
|
|
5626
|
+
if (config.includeWorkflow && config.paths.workflow) {
|
|
5627
|
+
write(config.paths.workflow)(generateEvalDatasetWorkflow(config));
|
|
5628
|
+
}
|
|
5645
5629
|
}
|
|
5646
5630
|
|
|
5647
5631
|
// src/patterns/eval/index.ts
|
|
5648
5632
|
var evalPattern = {
|
|
5649
5633
|
id: "eval",
|
|
5650
|
-
description: "LLM eval loop \u2014 run prompts, score outputs with a judge model, catch regressions",
|
|
5634
|
+
description: "LLM eval loop \u2014 run prompts, score outputs with a judge model, catch regressions (optional: JSONL dataset, GitHub Actions CI)",
|
|
5651
5635
|
async promptConfig(shared, opts) {
|
|
5652
5636
|
return promptEvalConfig(shared, opts ?? {});
|
|
5653
5637
|
},
|
|
@@ -5657,9 +5641,17 @@ var evalPattern = {
|
|
|
5657
5641
|
},
|
|
5658
5642
|
getPlanEntries(config) {
|
|
5659
5643
|
const c = config;
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5644
|
+
const entries = [];
|
|
5645
|
+
if (c.useDataset) {
|
|
5646
|
+
if (c.paths.dataset) entries.push({ kind: "create", path: c.paths.dataset, ...c.pathOverwrites.dataset && { overwrite: true } });
|
|
5647
|
+
if (c.paths.runner) entries.push({ kind: "create", path: c.paths.runner, ...c.pathOverwrites.runner && { overwrite: true } });
|
|
5648
|
+
} else {
|
|
5649
|
+
if (c.paths.evalScript) entries.push({ kind: "create", path: c.paths.evalScript, ...c.pathOverwrites.evalScript && { overwrite: true } });
|
|
5650
|
+
}
|
|
5651
|
+
if (c.includeWorkflow && c.paths.workflow) {
|
|
5652
|
+
entries.push({ kind: "create", path: c.paths.workflow, ...c.pathOverwrites.workflow && { overwrite: true } });
|
|
5653
|
+
}
|
|
5654
|
+
return entries;
|
|
5663
5655
|
},
|
|
5664
5656
|
getEnvVars(config) {
|
|
5665
5657
|
return [config.provider.envVar];
|
|
@@ -5670,15 +5662,15 @@ var evalPattern = {
|
|
|
5670
5662
|
};
|
|
5671
5663
|
|
|
5672
5664
|
// src/patterns/audio/prompt-config.ts
|
|
5673
|
-
import * as
|
|
5674
|
-
import
|
|
5665
|
+
import * as clack33 from "@clack/prompts";
|
|
5666
|
+
import process16 from "process";
|
|
5675
5667
|
async function promptAudioConfig(shared, opts = {}) {
|
|
5676
5668
|
const { pathAlias, hasSrcDir, targetDir, packageManager } = shared;
|
|
5677
5669
|
const src = hasSrcDir ? "src/" : "";
|
|
5678
5670
|
let includeTranscribe = true;
|
|
5679
5671
|
let includeSpeech = true;
|
|
5680
5672
|
if (!opts.yes) {
|
|
5681
|
-
const components = await
|
|
5673
|
+
const components = await clack33.multiselect({
|
|
5682
5674
|
message: "Which audio components do you want to scaffold?",
|
|
5683
5675
|
options: [
|
|
5684
5676
|
{ value: "transcribe", label: "Speech \u2192 Text (transcription route)", hint: "POST /api/audio/transcribe" },
|
|
@@ -5687,9 +5679,9 @@ async function promptAudioConfig(shared, opts = {}) {
|
|
|
5687
5679
|
initialValues: ["transcribe", "speech"],
|
|
5688
5680
|
required: true
|
|
5689
5681
|
});
|
|
5690
|
-
if (
|
|
5691
|
-
|
|
5692
|
-
|
|
5682
|
+
if (clack33.isCancel(components)) {
|
|
5683
|
+
clack33.cancel("Cancelled.");
|
|
5684
|
+
process16.exit(0);
|
|
5693
5685
|
}
|
|
5694
5686
|
includeTranscribe = components.includes("transcribe");
|
|
5695
5687
|
includeSpeech = components.includes("speech");
|
|
@@ -5716,13 +5708,13 @@ async function promptAudioConfig(shared, opts = {}) {
|
|
|
5716
5708
|
if (opts.page !== void 0) {
|
|
5717
5709
|
includePage = opts.page;
|
|
5718
5710
|
} else if (!opts.yes) {
|
|
5719
|
-
const wantsPage = await
|
|
5711
|
+
const wantsPage = await clack33.confirm({
|
|
5720
5712
|
message: "Generate a page component with recording UI?",
|
|
5721
5713
|
initialValue: true
|
|
5722
5714
|
});
|
|
5723
|
-
if (
|
|
5724
|
-
|
|
5725
|
-
|
|
5715
|
+
if (clack33.isCancel(wantsPage)) {
|
|
5716
|
+
clack33.cancel("Cancelled.");
|
|
5717
|
+
process16.exit(0);
|
|
5726
5718
|
}
|
|
5727
5719
|
includePage = wantsPage === true;
|
|
5728
5720
|
}
|
|
@@ -5739,13 +5731,13 @@ async function promptAudioConfig(shared, opts = {}) {
|
|
|
5739
5731
|
if (opts.auth !== void 0) {
|
|
5740
5732
|
auth = opts.auth;
|
|
5741
5733
|
} else if (!opts.yes) {
|
|
5742
|
-
const wantsAuth = await
|
|
5734
|
+
const wantsAuth = await clack33.confirm({
|
|
5743
5735
|
message: "Add NextAuth v5 authentication?",
|
|
5744
5736
|
initialValue: false
|
|
5745
5737
|
});
|
|
5746
|
-
if (
|
|
5747
|
-
|
|
5748
|
-
|
|
5738
|
+
if (clack33.isCancel(wantsAuth)) {
|
|
5739
|
+
clack33.cancel("Cancelled.");
|
|
5740
|
+
process16.exit(0);
|
|
5749
5741
|
}
|
|
5750
5742
|
auth = wantsAuth === true;
|
|
5751
5743
|
}
|
|
@@ -5773,8 +5765,8 @@ async function promptAudioConfig(shared, opts = {}) {
|
|
|
5773
5765
|
}
|
|
5774
5766
|
|
|
5775
5767
|
// src/patterns/audio/execute.ts
|
|
5776
|
-
import * as
|
|
5777
|
-
import
|
|
5768
|
+
import * as clack34 from "@clack/prompts";
|
|
5769
|
+
import path22 from "path";
|
|
5778
5770
|
|
|
5779
5771
|
// src/generators/audio-transcribe-route.ts
|
|
5780
5772
|
function generateAudioTranscribeRoute(config) {
|
|
@@ -6005,8 +5997,8 @@ async function executeAudioPattern(config, _shared) {
|
|
|
6005
5997
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
6006
5998
|
const freshConfig = { ...config, pathAlias };
|
|
6007
5999
|
const write = (relPath) => (content) => {
|
|
6008
|
-
writeFile(
|
|
6009
|
-
|
|
6000
|
+
writeFile(path22.join(config.targetDir, relPath), content);
|
|
6001
|
+
clack34.log.success(`Created ${relPath}`);
|
|
6010
6002
|
};
|
|
6011
6003
|
if (freshConfig.includeTranscribe && freshConfig.paths.transcribeRoute) {
|
|
6012
6004
|
write(freshConfig.paths.transcribeRoute)(generateAudioTranscribeRoute(freshConfig));
|
|
@@ -6026,12 +6018,12 @@ async function executeAudioPattern(config, _shared) {
|
|
|
6026
6018
|
}
|
|
6027
6019
|
|
|
6028
6020
|
// src/patterns/audio/index.ts
|
|
6029
|
-
function
|
|
6021
|
+
function getPackages13(config) {
|
|
6030
6022
|
const pkgs = [config.provider.package, "ai"];
|
|
6031
6023
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
6032
6024
|
return pkgs;
|
|
6033
6025
|
}
|
|
6034
|
-
function
|
|
6026
|
+
function getPlanEntries13(config) {
|
|
6035
6027
|
const entries = [];
|
|
6036
6028
|
if (config.includeTranscribe && config.paths.transcribeRoute) {
|
|
6037
6029
|
entries.push({ kind: "create", path: config.paths.transcribeRoute, ...config.pathOverwrites.transcribeRoute && { overwrite: true } });
|
|
@@ -6051,10 +6043,10 @@ var audioPattern = {
|
|
|
6051
6043
|
return promptAudioConfig(shared, opts ?? {});
|
|
6052
6044
|
},
|
|
6053
6045
|
getPackages(config) {
|
|
6054
|
-
return
|
|
6046
|
+
return getPackages13(config);
|
|
6055
6047
|
},
|
|
6056
6048
|
getPlanEntries(config) {
|
|
6057
|
-
return
|
|
6049
|
+
return getPlanEntries13(config);
|
|
6058
6050
|
},
|
|
6059
6051
|
getEnvVars(config) {
|
|
6060
6052
|
return [config.provider.envVar];
|
|
@@ -6065,21 +6057,21 @@ var audioPattern = {
|
|
|
6065
6057
|
};
|
|
6066
6058
|
|
|
6067
6059
|
// src/patterns/document-processing/prompt-config.ts
|
|
6068
|
-
import * as
|
|
6069
|
-
import
|
|
6060
|
+
import * as clack35 from "@clack/prompts";
|
|
6061
|
+
import process17 from "process";
|
|
6070
6062
|
async function promptDocumentProcessingConfig(shared, opts = {}) {
|
|
6071
6063
|
const { pathAlias, hasSrcDir, targetDir } = shared;
|
|
6072
6064
|
const src = hasSrcDir ? "src/" : "";
|
|
6073
6065
|
let schemaName = opts.schemaName ?? "";
|
|
6074
6066
|
if (!schemaName && !opts.yes) {
|
|
6075
|
-
const input = await
|
|
6067
|
+
const input = await clack35.text({
|
|
6076
6068
|
message: "Schema / type name (used for the Zod schema and TypeScript type)",
|
|
6077
6069
|
placeholder: "document",
|
|
6078
6070
|
validate: (v) => v.trim() ? void 0 : "Required"
|
|
6079
6071
|
});
|
|
6080
|
-
if (
|
|
6081
|
-
|
|
6082
|
-
|
|
6072
|
+
if (clack35.isCancel(input)) {
|
|
6073
|
+
clack35.cancel("Cancelled.");
|
|
6074
|
+
process17.exit(0);
|
|
6083
6075
|
}
|
|
6084
6076
|
schemaName = input.trim() || "document";
|
|
6085
6077
|
}
|
|
@@ -6100,13 +6092,13 @@ async function promptDocumentProcessingConfig(shared, opts = {}) {
|
|
|
6100
6092
|
if (opts.hook !== void 0) {
|
|
6101
6093
|
includeHook = opts.hook;
|
|
6102
6094
|
} else if (!opts.yes) {
|
|
6103
|
-
const wantsHook = await
|
|
6095
|
+
const wantsHook = await clack35.confirm({
|
|
6104
6096
|
message: "Generate a client hook (useExtract)?",
|
|
6105
6097
|
initialValue: true
|
|
6106
6098
|
});
|
|
6107
|
-
if (
|
|
6108
|
-
|
|
6109
|
-
|
|
6099
|
+
if (clack35.isCancel(wantsHook)) {
|
|
6100
|
+
clack35.cancel("Cancelled.");
|
|
6101
|
+
process17.exit(0);
|
|
6110
6102
|
}
|
|
6111
6103
|
includeHook = wantsHook === true;
|
|
6112
6104
|
}
|
|
@@ -6123,13 +6115,13 @@ async function promptDocumentProcessingConfig(shared, opts = {}) {
|
|
|
6123
6115
|
if (opts.auth !== void 0) {
|
|
6124
6116
|
auth = opts.auth;
|
|
6125
6117
|
} else if (!opts.yes) {
|
|
6126
|
-
const wantsAuth = await
|
|
6118
|
+
const wantsAuth = await clack35.confirm({
|
|
6127
6119
|
message: "Add NextAuth v5 authentication?",
|
|
6128
6120
|
initialValue: false
|
|
6129
6121
|
});
|
|
6130
|
-
if (
|
|
6131
|
-
|
|
6132
|
-
|
|
6122
|
+
if (clack35.isCancel(wantsAuth)) {
|
|
6123
|
+
clack35.cancel("Cancelled.");
|
|
6124
|
+
process17.exit(0);
|
|
6133
6125
|
}
|
|
6134
6126
|
auth = wantsAuth === true;
|
|
6135
6127
|
}
|
|
@@ -6153,8 +6145,8 @@ async function promptDocumentProcessingConfig(shared, opts = {}) {
|
|
|
6153
6145
|
}
|
|
6154
6146
|
|
|
6155
6147
|
// src/patterns/document-processing/execute.ts
|
|
6156
|
-
import * as
|
|
6157
|
-
import
|
|
6148
|
+
import * as clack36 from "@clack/prompts";
|
|
6149
|
+
import path23 from "path";
|
|
6158
6150
|
|
|
6159
6151
|
// src/generators/document-processing-route.ts
|
|
6160
6152
|
function toImportPath24(filePath, pathAlias) {
|
|
@@ -6305,8 +6297,8 @@ async function executeDocumentProcessingPattern(config, _shared) {
|
|
|
6305
6297
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
6306
6298
|
const freshConfig = { ...config, pathAlias };
|
|
6307
6299
|
const write = (relPath) => (content) => {
|
|
6308
|
-
writeFile(
|
|
6309
|
-
|
|
6300
|
+
writeFile(path23.join(config.targetDir, relPath), content);
|
|
6301
|
+
clack36.log.success(`Created ${relPath}`);
|
|
6310
6302
|
};
|
|
6311
6303
|
write(freshConfig.paths.apiRoute)(generateDocumentProcessingRoute(freshConfig));
|
|
6312
6304
|
write(freshConfig.paths.schema)(generateDocumentProcessingSchema(freshConfig.schemaName));
|
|
@@ -6316,12 +6308,12 @@ async function executeDocumentProcessingPattern(config, _shared) {
|
|
|
6316
6308
|
}
|
|
6317
6309
|
|
|
6318
6310
|
// src/patterns/document-processing/index.ts
|
|
6319
|
-
function
|
|
6311
|
+
function getPackages14(config) {
|
|
6320
6312
|
const pkgs = [config.provider.package, "ai", "zod"];
|
|
6321
6313
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
6322
6314
|
return pkgs;
|
|
6323
6315
|
}
|
|
6324
|
-
function
|
|
6316
|
+
function getPlanEntries14(config) {
|
|
6325
6317
|
const entries = [
|
|
6326
6318
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
6327
6319
|
{ kind: "create", path: config.paths.schema, ...config.pathOverwrites.schema && { overwrite: true } }
|
|
@@ -6338,10 +6330,10 @@ var documentProcessingPattern = {
|
|
|
6338
6330
|
return promptDocumentProcessingConfig(shared, opts ?? {});
|
|
6339
6331
|
},
|
|
6340
6332
|
getPackages(config) {
|
|
6341
|
-
return
|
|
6333
|
+
return getPackages14(config);
|
|
6342
6334
|
},
|
|
6343
6335
|
getPlanEntries(config) {
|
|
6344
|
-
return
|
|
6336
|
+
return getPlanEntries14(config);
|
|
6345
6337
|
},
|
|
6346
6338
|
getEnvVars(config) {
|
|
6347
6339
|
return [config.provider.envVar];
|
|
@@ -6352,8 +6344,8 @@ var documentProcessingPattern = {
|
|
|
6352
6344
|
};
|
|
6353
6345
|
|
|
6354
6346
|
// src/patterns/generative-ui/prompt-config.ts
|
|
6355
|
-
import * as
|
|
6356
|
-
import
|
|
6347
|
+
import * as clack37 from "@clack/prompts";
|
|
6348
|
+
import process18 from "process";
|
|
6357
6349
|
async function promptGenerativeUiConfig(shared, opts = {}) {
|
|
6358
6350
|
const { pathAlias, hasSrcDir, targetDir, packageManager } = shared;
|
|
6359
6351
|
const src = hasSrcDir ? "src/" : "";
|
|
@@ -6373,13 +6365,13 @@ async function promptGenerativeUiConfig(shared, opts = {}) {
|
|
|
6373
6365
|
if (opts.auth !== void 0) {
|
|
6374
6366
|
auth = opts.auth;
|
|
6375
6367
|
} else if (!opts.yes) {
|
|
6376
|
-
const wantsAuth = await
|
|
6368
|
+
const wantsAuth = await clack37.confirm({
|
|
6377
6369
|
message: "Add NextAuth v5 authentication?",
|
|
6378
6370
|
initialValue: false
|
|
6379
6371
|
});
|
|
6380
|
-
if (
|
|
6381
|
-
|
|
6382
|
-
|
|
6372
|
+
if (clack37.isCancel(wantsAuth)) {
|
|
6373
|
+
clack37.cancel("Cancelled.");
|
|
6374
|
+
process18.exit(0);
|
|
6383
6375
|
}
|
|
6384
6376
|
auth = wantsAuth === true;
|
|
6385
6377
|
}
|
|
@@ -6402,8 +6394,8 @@ async function promptGenerativeUiConfig(shared, opts = {}) {
|
|
|
6402
6394
|
}
|
|
6403
6395
|
|
|
6404
6396
|
// src/patterns/generative-ui/execute.ts
|
|
6405
|
-
import * as
|
|
6406
|
-
import
|
|
6397
|
+
import * as clack38 from "@clack/prompts";
|
|
6398
|
+
import path24 from "path";
|
|
6407
6399
|
|
|
6408
6400
|
// src/generators/generative-ui-route.ts
|
|
6409
6401
|
function generateGenerativeUiRoute(config) {
|
|
@@ -6577,8 +6569,8 @@ async function executeGenerativeUiPattern(config, _shared) {
|
|
|
6577
6569
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
6578
6570
|
const freshConfig = { ...config, pathAlias: "@/" };
|
|
6579
6571
|
const write = (relPath) => (content) => {
|
|
6580
|
-
writeFile(
|
|
6581
|
-
|
|
6572
|
+
writeFile(path24.join(config.targetDir, relPath), content);
|
|
6573
|
+
clack38.log.success(`Created ${relPath}`);
|
|
6582
6574
|
};
|
|
6583
6575
|
await runAiElements(config.targetDir);
|
|
6584
6576
|
fixFontVars(config.targetDir);
|
|
@@ -6590,12 +6582,12 @@ async function executeGenerativeUiPattern(config, _shared) {
|
|
|
6590
6582
|
}
|
|
6591
6583
|
|
|
6592
6584
|
// src/patterns/generative-ui/index.ts
|
|
6593
|
-
function
|
|
6585
|
+
function getPackages15(config) {
|
|
6594
6586
|
const pkgs = [config.provider.package, "ai", "@ai-sdk/react", "zod"];
|
|
6595
6587
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
6596
6588
|
return pkgs;
|
|
6597
6589
|
}
|
|
6598
|
-
function
|
|
6590
|
+
function getPlanEntries15(config) {
|
|
6599
6591
|
return [
|
|
6600
6592
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } },
|
|
6601
6593
|
{ kind: "create", path: config.paths.page, ...config.pathOverwrites.page && { overwrite: true } }
|
|
@@ -6608,10 +6600,10 @@ var generativeUiPattern = {
|
|
|
6608
6600
|
return promptGenerativeUiConfig(shared, opts ?? {});
|
|
6609
6601
|
},
|
|
6610
6602
|
getPackages(config) {
|
|
6611
|
-
return
|
|
6603
|
+
return getPackages15(config);
|
|
6612
6604
|
},
|
|
6613
6605
|
getPlanEntries(config) {
|
|
6614
|
-
return
|
|
6606
|
+
return getPlanEntries15(config);
|
|
6615
6607
|
},
|
|
6616
6608
|
getEnvVars(config) {
|
|
6617
6609
|
return [config.provider.envVar];
|
|
@@ -6622,14 +6614,14 @@ var generativeUiPattern = {
|
|
|
6622
6614
|
};
|
|
6623
6615
|
|
|
6624
6616
|
// src/patterns/image-gen/prompt-config.ts
|
|
6625
|
-
import * as
|
|
6626
|
-
import
|
|
6617
|
+
import * as clack39 from "@clack/prompts";
|
|
6618
|
+
import process19 from "process";
|
|
6627
6619
|
async function promptImageGenConfig(shared, opts = {}) {
|
|
6628
6620
|
const { pathAlias, hasSrcDir, targetDir, packageManager } = shared;
|
|
6629
6621
|
const src = hasSrcDir ? "src/" : "";
|
|
6630
6622
|
let imageModel = opts.imageModel ?? "";
|
|
6631
6623
|
if (!imageModel && !opts.yes) {
|
|
6632
|
-
const selected = await
|
|
6624
|
+
const selected = await clack39.select({
|
|
6633
6625
|
message: "Which OpenAI image model?",
|
|
6634
6626
|
options: [
|
|
6635
6627
|
{ value: "dall-e-3", label: "DALL\xB7E 3 (best quality, recommended)" },
|
|
@@ -6637,9 +6629,9 @@ async function promptImageGenConfig(shared, opts = {}) {
|
|
|
6637
6629
|
],
|
|
6638
6630
|
initialValue: "dall-e-3"
|
|
6639
6631
|
});
|
|
6640
|
-
if (
|
|
6641
|
-
|
|
6642
|
-
|
|
6632
|
+
if (clack39.isCancel(selected)) {
|
|
6633
|
+
clack39.cancel("Cancelled.");
|
|
6634
|
+
process19.exit(0);
|
|
6643
6635
|
}
|
|
6644
6636
|
imageModel = selected;
|
|
6645
6637
|
}
|
|
@@ -6654,13 +6646,13 @@ async function promptImageGenConfig(shared, opts = {}) {
|
|
|
6654
6646
|
if (opts.page !== void 0) {
|
|
6655
6647
|
includePage = opts.page;
|
|
6656
6648
|
} else if (!opts.yes) {
|
|
6657
|
-
const wantsPage = await
|
|
6649
|
+
const wantsPage = await clack39.confirm({
|
|
6658
6650
|
message: "Generate a page with prompt input and image display?",
|
|
6659
6651
|
initialValue: true
|
|
6660
6652
|
});
|
|
6661
|
-
if (
|
|
6662
|
-
|
|
6663
|
-
|
|
6653
|
+
if (clack39.isCancel(wantsPage)) {
|
|
6654
|
+
clack39.cancel("Cancelled.");
|
|
6655
|
+
process19.exit(0);
|
|
6664
6656
|
}
|
|
6665
6657
|
includePage = wantsPage === true;
|
|
6666
6658
|
}
|
|
@@ -6677,13 +6669,13 @@ async function promptImageGenConfig(shared, opts = {}) {
|
|
|
6677
6669
|
if (opts.auth !== void 0) {
|
|
6678
6670
|
auth = opts.auth;
|
|
6679
6671
|
} else if (!opts.yes) {
|
|
6680
|
-
const wantsAuth = await
|
|
6672
|
+
const wantsAuth = await clack39.confirm({
|
|
6681
6673
|
message: "Add NextAuth v5 authentication?",
|
|
6682
6674
|
initialValue: false
|
|
6683
6675
|
});
|
|
6684
|
-
if (
|
|
6685
|
-
|
|
6686
|
-
|
|
6676
|
+
if (clack39.isCancel(wantsAuth)) {
|
|
6677
|
+
clack39.cancel("Cancelled.");
|
|
6678
|
+
process19.exit(0);
|
|
6687
6679
|
}
|
|
6688
6680
|
auth = wantsAuth === true;
|
|
6689
6681
|
}
|
|
@@ -6707,8 +6699,8 @@ async function promptImageGenConfig(shared, opts = {}) {
|
|
|
6707
6699
|
}
|
|
6708
6700
|
|
|
6709
6701
|
// src/patterns/image-gen/execute.ts
|
|
6710
|
-
import * as
|
|
6711
|
-
import
|
|
6702
|
+
import * as clack40 from "@clack/prompts";
|
|
6703
|
+
import path25 from "path";
|
|
6712
6704
|
|
|
6713
6705
|
// src/generators/image-gen-route.ts
|
|
6714
6706
|
function generateImageGenRoute(config) {
|
|
@@ -6845,8 +6837,8 @@ async function executeImageGenPattern(config, _shared) {
|
|
|
6845
6837
|
const { prefix: pathAlias } = detectPathAlias(config.targetDir);
|
|
6846
6838
|
const freshConfig = { ...config, pathAlias };
|
|
6847
6839
|
const write = (relPath) => (content) => {
|
|
6848
|
-
writeFile(
|
|
6849
|
-
|
|
6840
|
+
writeFile(path25.join(config.targetDir, relPath), content);
|
|
6841
|
+
clack40.log.success(`Created ${relPath}`);
|
|
6850
6842
|
};
|
|
6851
6843
|
write(freshConfig.paths.apiRoute)(generateImageGenRoute(freshConfig));
|
|
6852
6844
|
if (freshConfig.includePage && freshConfig.paths.page) {
|
|
@@ -6861,12 +6853,12 @@ async function executeImageGenPattern(config, _shared) {
|
|
|
6861
6853
|
}
|
|
6862
6854
|
|
|
6863
6855
|
// src/patterns/image-gen/index.ts
|
|
6864
|
-
function
|
|
6856
|
+
function getPackages16(config) {
|
|
6865
6857
|
const pkgs = ["@ai-sdk/openai", "ai"];
|
|
6866
6858
|
if (config.auth) pkgs.push("next-auth@5.0.0-beta.30");
|
|
6867
6859
|
return pkgs;
|
|
6868
6860
|
}
|
|
6869
|
-
function
|
|
6861
|
+
function getPlanEntries16(config) {
|
|
6870
6862
|
const entries = [
|
|
6871
6863
|
{ kind: "create", path: config.paths.apiRoute, ...config.pathOverwrites.apiRoute && { overwrite: true } }
|
|
6872
6864
|
];
|
|
@@ -6882,10 +6874,10 @@ var imageGenPattern = {
|
|
|
6882
6874
|
return promptImageGenConfig(shared, opts ?? {});
|
|
6883
6875
|
},
|
|
6884
6876
|
getPackages(config) {
|
|
6885
|
-
return
|
|
6877
|
+
return getPackages16(config);
|
|
6886
6878
|
},
|
|
6887
6879
|
getPlanEntries(config) {
|
|
6888
|
-
return
|
|
6880
|
+
return getPlanEntries16(config);
|
|
6889
6881
|
},
|
|
6890
6882
|
getEnvVars(_config) {
|
|
6891
6883
|
return ["OPENAI_API_KEY"];
|
|
@@ -6914,8 +6906,7 @@ var patternRegistry = [
|
|
|
6914
6906
|
hybridSearchPattern,
|
|
6915
6907
|
memoryPattern,
|
|
6916
6908
|
multiAgentPattern,
|
|
6917
|
-
backgroundAgentPattern
|
|
6918
|
-
evalDatasetPattern
|
|
6909
|
+
backgroundAgentPattern
|
|
6919
6910
|
];
|
|
6920
6911
|
function resolvePatterns(ids) {
|
|
6921
6912
|
return ids.map((id) => {
|
|
@@ -6932,14 +6923,14 @@ function resolveAllPatterns() {
|
|
|
6932
6923
|
}
|
|
6933
6924
|
|
|
6934
6925
|
// src/steps/detect-prerequisites.ts
|
|
6935
|
-
import * as
|
|
6936
|
-
import
|
|
6926
|
+
import * as clack41 from "@clack/prompts";
|
|
6927
|
+
import process20 from "process";
|
|
6937
6928
|
|
|
6938
6929
|
// src/utils/detect-next.ts
|
|
6939
6930
|
import fs7 from "fs";
|
|
6940
|
-
import
|
|
6931
|
+
import path26 from "path";
|
|
6941
6932
|
function detectNext(targetDir) {
|
|
6942
|
-
const pkgPath =
|
|
6933
|
+
const pkgPath = path26.join(targetDir, "package.json");
|
|
6943
6934
|
if (!fs7.existsSync(pkgPath)) return { found: false, version: null };
|
|
6944
6935
|
try {
|
|
6945
6936
|
const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf8"));
|
|
@@ -6956,9 +6947,9 @@ function detectNext(targetDir) {
|
|
|
6956
6947
|
|
|
6957
6948
|
// src/utils/detect-react.ts
|
|
6958
6949
|
import fs8 from "fs";
|
|
6959
|
-
import
|
|
6950
|
+
import path27 from "path";
|
|
6960
6951
|
function detectReact(targetDir) {
|
|
6961
|
-
const pkgPath =
|
|
6952
|
+
const pkgPath = path27.join(targetDir, "package.json");
|
|
6962
6953
|
if (!fs8.existsSync(pkgPath)) return false;
|
|
6963
6954
|
try {
|
|
6964
6955
|
const pkg = JSON.parse(fs8.readFileSync(pkgPath, "utf8"));
|
|
@@ -6974,38 +6965,38 @@ function detectReact(targetDir) {
|
|
|
6974
6965
|
|
|
6975
6966
|
// src/utils/detect-shadcn.ts
|
|
6976
6967
|
import fs9 from "fs";
|
|
6977
|
-
import
|
|
6968
|
+
import path28 from "path";
|
|
6978
6969
|
function detectShadcn(targetDir) {
|
|
6979
|
-
return fs9.existsSync(
|
|
6970
|
+
return fs9.existsSync(path28.join(targetDir, "components.json"));
|
|
6980
6971
|
}
|
|
6981
6972
|
|
|
6982
6973
|
// src/utils/detect-typescript.ts
|
|
6983
6974
|
import fs10 from "fs";
|
|
6984
|
-
import
|
|
6975
|
+
import path29 from "path";
|
|
6985
6976
|
function detectTypescript(targetDir) {
|
|
6986
|
-
return fs10.existsSync(
|
|
6977
|
+
return fs10.existsSync(path29.join(targetDir, "tsconfig.json"));
|
|
6987
6978
|
}
|
|
6988
6979
|
|
|
6989
6980
|
// src/steps/detect-prerequisites.ts
|
|
6990
6981
|
async function detectPrerequisites(targetDir) {
|
|
6991
6982
|
if (!detectReact(targetDir)) {
|
|
6992
|
-
|
|
6993
|
-
|
|
6983
|
+
clack41.log.error("react and react-dom not found in package.json. This tool requires React.");
|
|
6984
|
+
process20.exit(1);
|
|
6994
6985
|
}
|
|
6995
6986
|
if (!detectTypescript(targetDir)) {
|
|
6996
|
-
|
|
6997
|
-
|
|
6987
|
+
clack41.log.error("No tsconfig.json found. This tool requires TypeScript.");
|
|
6988
|
+
process20.exit(1);
|
|
6998
6989
|
}
|
|
6999
6990
|
const next = detectNext(targetDir);
|
|
7000
6991
|
if (next.found) {
|
|
7001
|
-
|
|
6992
|
+
clack41.log.success(`Next.js ${next.version ?? ""} found`);
|
|
7002
6993
|
}
|
|
7003
6994
|
return { hasShadcn: detectShadcn(targetDir), hasNext: next.found };
|
|
7004
6995
|
}
|
|
7005
6996
|
|
|
7006
6997
|
// src/steps/announce-plan.ts
|
|
7007
|
-
import * as
|
|
7008
|
-
import
|
|
6998
|
+
import * as clack42 from "@clack/prompts";
|
|
6999
|
+
import process21 from "process";
|
|
7009
7000
|
async function announcePlan(plan, opts = {}) {
|
|
7010
7001
|
const lines = [];
|
|
7011
7002
|
const runs = plan.entries.filter((e) => e.kind === "run");
|
|
@@ -7034,12 +7025,12 @@ async function announcePlan(plan, opts = {}) {
|
|
|
7034
7025
|
for (const e of creates) lines.push(` ${e.path}${e.overwrite ? " (overwrite)" : ""}`);
|
|
7035
7026
|
}
|
|
7036
7027
|
}
|
|
7037
|
-
|
|
7028
|
+
clack42.note(lines.join("\n"), "Plan");
|
|
7038
7029
|
if (opts.yes) return;
|
|
7039
|
-
const proceed = await
|
|
7040
|
-
if (
|
|
7041
|
-
|
|
7042
|
-
|
|
7030
|
+
const proceed = await clack42.confirm({ message: "Proceed?", initialValue: true });
|
|
7031
|
+
if (clack42.isCancel(proceed) || !proceed) {
|
|
7032
|
+
clack42.cancel("Aborted \u2014 no changes made.");
|
|
7033
|
+
process21.exit(0);
|
|
7043
7034
|
}
|
|
7044
7035
|
}
|
|
7045
7036
|
|
|
@@ -7061,12 +7052,12 @@ function buildPlan(items) {
|
|
|
7061
7052
|
|
|
7062
7053
|
// src/utils/detect-package-manager.ts
|
|
7063
7054
|
import { existsSync } from "fs";
|
|
7064
|
-
import
|
|
7055
|
+
import path30 from "path";
|
|
7065
7056
|
function detectPackageManager(targetDir) {
|
|
7066
|
-
if (existsSync(
|
|
7067
|
-
if (existsSync(
|
|
7068
|
-
if (existsSync(
|
|
7069
|
-
if (existsSync(
|
|
7057
|
+
if (existsSync(path30.join(targetDir, "bun.lockb"))) return "bun";
|
|
7058
|
+
if (existsSync(path30.join(targetDir, "pnpm-lock.yaml"))) return "pnpm";
|
|
7059
|
+
if (existsSync(path30.join(targetDir, "yarn.lock"))) return "yarn";
|
|
7060
|
+
if (existsSync(path30.join(targetDir, "package-lock.json"))) return "npm";
|
|
7070
7061
|
const execPath = process.env["npm_execpath"] ?? "";
|
|
7071
7062
|
if (execPath.includes("pnpm")) return "pnpm";
|
|
7072
7063
|
if (execPath.includes("yarn")) return "yarn";
|
|
@@ -7092,36 +7083,36 @@ async function promptSharedConfig(targetDir, opts, prereqs) {
|
|
|
7092
7083
|
if (opts.provider !== void 0) {
|
|
7093
7084
|
const valid = registry.providers.map((p) => p.id);
|
|
7094
7085
|
if (!valid.includes(opts.provider)) {
|
|
7095
|
-
|
|
7096
|
-
|
|
7086
|
+
clack43.log.error(`Unknown provider "${opts.provider}". Valid values: ${valid.join(", ")}`);
|
|
7087
|
+
process22.exit(1);
|
|
7097
7088
|
}
|
|
7098
7089
|
}
|
|
7099
7090
|
let provider = registry.providers[0];
|
|
7100
7091
|
if (opts.provider) {
|
|
7101
7092
|
provider = registry.providers.find((p) => p.id === opts.provider);
|
|
7102
7093
|
} else if (!opts.yes) {
|
|
7103
|
-
const providerId = await
|
|
7094
|
+
const providerId = await clack43.select({
|
|
7104
7095
|
message: "AI provider?",
|
|
7105
7096
|
options: registry.providers.map((p) => ({ value: p.id, label: p.label }))
|
|
7106
7097
|
});
|
|
7107
|
-
if (
|
|
7108
|
-
|
|
7109
|
-
|
|
7098
|
+
if (clack43.isCancel(providerId)) {
|
|
7099
|
+
clack43.cancel("Cancelled.");
|
|
7100
|
+
process22.exit(0);
|
|
7110
7101
|
}
|
|
7111
7102
|
provider = registry.providers.find((p) => p.id === providerId);
|
|
7112
7103
|
}
|
|
7113
7104
|
return { provider, pathAlias, hasSrcDir, packageManager, targetDir, prereqs };
|
|
7114
7105
|
}
|
|
7115
7106
|
async function addCommand(patternId, opts) {
|
|
7116
|
-
const targetDir =
|
|
7117
|
-
|
|
7107
|
+
const targetDir = process22.cwd();
|
|
7108
|
+
clack43.intro("ai-wingman");
|
|
7118
7109
|
const prereqs = await detectPrerequisites(targetDir);
|
|
7119
7110
|
let patterns;
|
|
7120
7111
|
try {
|
|
7121
7112
|
patterns = resolvePatterns([patternId]);
|
|
7122
7113
|
} catch (err) {
|
|
7123
|
-
|
|
7124
|
-
|
|
7114
|
+
clack43.log.error(err.message);
|
|
7115
|
+
process22.exit(1);
|
|
7125
7116
|
}
|
|
7126
7117
|
const [pattern] = patterns;
|
|
7127
7118
|
const shared = await promptSharedConfig(targetDir, opts, prereqs);
|
|
@@ -7130,7 +7121,7 @@ async function addCommand(patternId, opts) {
|
|
|
7130
7121
|
await announcePlan(plan, opts);
|
|
7131
7122
|
const pm = shared.packageManager;
|
|
7132
7123
|
for (const pkg of plan.packages) {
|
|
7133
|
-
const spinner3 =
|
|
7124
|
+
const spinner3 = clack43.spinner();
|
|
7134
7125
|
spinner3.start(`Installing ${pkg}...`);
|
|
7135
7126
|
try {
|
|
7136
7127
|
await spawnSilent(pm, installArgs(pm, pkg), targetDir);
|
|
@@ -7138,43 +7129,43 @@ async function addCommand(patternId, opts) {
|
|
|
7138
7129
|
} catch (err) {
|
|
7139
7130
|
spinner3.stop(`Failed to install ${pkg}`);
|
|
7140
7131
|
if (err instanceof ExitError) {
|
|
7141
|
-
|
|
7132
|
+
clack43.log.warn(`Install manually: ${pm} ${installArgs(pm, pkg).join(" ")}`);
|
|
7142
7133
|
}
|
|
7143
7134
|
}
|
|
7144
7135
|
}
|
|
7145
7136
|
await pattern.execute(config, shared);
|
|
7146
7137
|
const envVars = pattern.getEnvVars(config);
|
|
7147
7138
|
if (envVars.length > 0) {
|
|
7148
|
-
|
|
7139
|
+
clack43.note(envVars.map((v) => `${v}=`).join("\n"), "Add these to your .env.local");
|
|
7149
7140
|
}
|
|
7150
|
-
|
|
7141
|
+
clack43.outro(`Done! Start your dev server: ${pm} run dev`);
|
|
7151
7142
|
}
|
|
7152
7143
|
|
|
7153
7144
|
// src/commands/list/index.ts
|
|
7154
|
-
import * as
|
|
7145
|
+
import * as clack44 from "@clack/prompts";
|
|
7155
7146
|
function listCommand() {
|
|
7156
|
-
|
|
7147
|
+
clack44.intro("ai-wingman \u2014 available patterns");
|
|
7157
7148
|
const patterns = resolveAllPatterns();
|
|
7158
7149
|
const idWidth = Math.max(...patterns.map((p) => p.id.length)) + 2;
|
|
7159
7150
|
for (const pattern of patterns) {
|
|
7160
7151
|
const id = pattern.id.padEnd(idWidth);
|
|
7161
|
-
|
|
7152
|
+
clack44.log.info(`${id}${pattern.description}`);
|
|
7162
7153
|
}
|
|
7163
|
-
|
|
7154
|
+
clack44.outro(`Run \`wingman add <pattern>\` to scaffold one or more patterns`);
|
|
7164
7155
|
}
|
|
7165
7156
|
|
|
7166
7157
|
// src/commands/skill/index.ts
|
|
7167
|
-
import * as
|
|
7158
|
+
import * as clack45 from "@clack/prompts";
|
|
7168
7159
|
import https from "https";
|
|
7169
7160
|
import fs11 from "fs";
|
|
7170
|
-
import
|
|
7171
|
-
import
|
|
7161
|
+
import path31 from "path";
|
|
7162
|
+
import process23 from "process";
|
|
7172
7163
|
var SKILL_URL = "https://ai-wingman.dev/SKILL.md";
|
|
7173
7164
|
var DEFAULT_OUTPUT = "SKILL.md";
|
|
7174
7165
|
async function skillCommand(opts) {
|
|
7175
|
-
const outPath =
|
|
7176
|
-
|
|
7177
|
-
const spinner3 =
|
|
7166
|
+
const outPath = path31.resolve(process23.cwd(), opts.output ?? DEFAULT_OUTPUT);
|
|
7167
|
+
clack45.intro("ai-wingman skill");
|
|
7168
|
+
const spinner3 = clack45.spinner();
|
|
7178
7169
|
spinner3.start(`Downloading ${SKILL_URL}`);
|
|
7179
7170
|
await new Promise((resolve, reject) => {
|
|
7180
7171
|
const file = fs11.createWriteStream(outPath);
|
|
@@ -7191,15 +7182,15 @@ async function skillCommand(opts) {
|
|
|
7191
7182
|
}).on("error", reject);
|
|
7192
7183
|
}).catch((err) => {
|
|
7193
7184
|
spinner3.stop("Download failed");
|
|
7194
|
-
|
|
7195
|
-
|
|
7185
|
+
clack45.log.error(err.message);
|
|
7186
|
+
process23.exit(1);
|
|
7196
7187
|
});
|
|
7197
|
-
spinner3.stop(`Saved to ${
|
|
7198
|
-
|
|
7188
|
+
spinner3.stop(`Saved to ${path31.relative(process23.cwd(), outPath)}`);
|
|
7189
|
+
clack45.note(
|
|
7199
7190
|
"Add this file to your AI coding assistant's context or skills directory.",
|
|
7200
7191
|
"Next step"
|
|
7201
7192
|
);
|
|
7202
|
-
|
|
7193
|
+
clack45.outro("Done!");
|
|
7203
7194
|
}
|
|
7204
7195
|
|
|
7205
7196
|
// bin/wingman.ts
|