@untestutils/ai 0.5.0
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/LICENSE +21 -0
- package/dist/agent/run.d.mts +4 -0
- package/dist/agent/run.d.ts +19 -0
- package/dist/agent/run.d.ts.map +1 -0
- package/dist/agent/run.mjs +140 -0
- package/dist/agent/types.d.mts +33 -0
- package/dist/agent/types.d.ts +34 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.mjs +22 -0
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +14 -0
- package/dist/model.d.mts +1 -0
- package/dist/model.d.ts +14 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.mjs +29 -0
- package/dist/prompts/convert-v1.md +28 -0
- package/dist/prompts/cover-v1.md +36 -0
- package/dist/prompts/fix-v1.md +20 -0
- package/dist/prompts/v1.md +37 -0
- package/dist/prompts.d.ts +14 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.mjs +31 -0
- package/dist/tools/browser.d.mts +9 -0
- package/dist/tools/browser.d.ts +10 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.mjs +146 -0
- package/dist/tools/fs.d.ts +16 -0
- package/dist/tools/fs.d.ts.map +1 -0
- package/dist/tools/fs.mjs +132 -0
- package/dist/tools/registry.d.mts +15 -0
- package/dist/tools/registry.d.ts +16 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.mjs +22 -0
- package/dist/tree.d.ts +18 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.mjs +70 -0
- package/dist/workflows/cover.d.mts +23 -0
- package/dist/workflows/cover.d.ts +24 -0
- package/dist/workflows/cover.d.ts.map +1 -0
- package/dist/workflows/cover.mjs +95 -0
- package/dist/workflows/fix.d.mts +17 -0
- package/dist/workflows/fix.d.ts +18 -0
- package/dist/workflows/fix.d.ts.map +1 -0
- package/dist/workflows/fix.mjs +88 -0
- package/dist/workflows/generate.d.ts +29 -0
- package/dist/workflows/generate.d.ts.map +1 -0
- package/dist/workflows/generate.mjs +167 -0
- package/dist/workflows/types.d.mts +6 -0
- package/dist/workflows/types.d.ts +7 -0
- package/dist/workflows/types.d.ts.map +1 -0
- package/dist/workflows/types.mjs +1 -0
- package/package.json +75 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join, relative, resolve } from "pathe";
|
|
5
|
+
import { resolveArtifactsRoot, debug, envFlag, log } from "@untestutils/core";
|
|
6
|
+
import { runAgent } from "../agent/run.mjs";
|
|
7
|
+
import { loadFixPrompt } from "../prompts.mjs";
|
|
8
|
+
import { createAgentToolkit } from "../tools/registry.mjs";
|
|
9
|
+
import { buildFileTree, fingerprint, treeSignature } from "../tree.mjs";
|
|
10
|
+
export async function fixBrokenTests(opts) {
|
|
11
|
+
const root = resolve(opts.root);
|
|
12
|
+
const filePath = resolve(opts.path);
|
|
13
|
+
const source = await readFile(filePath, "utf8");
|
|
14
|
+
const tree = await buildFileTree(root);
|
|
15
|
+
const treeSig = treeSignature(tree);
|
|
16
|
+
const id = `fix-${createHash("sha1").update(filePath + opts.failureLog).digest("hex").slice(0, 10)}`;
|
|
17
|
+
const fp = fingerprint([
|
|
18
|
+
"fix-v1",
|
|
19
|
+
source,
|
|
20
|
+
opts.failureLog.slice(0, 4e3),
|
|
21
|
+
resolve(root),
|
|
22
|
+
(opts.recipes ?? []).join(","),
|
|
23
|
+
treeSig
|
|
24
|
+
]);
|
|
25
|
+
const artifactsRoot = resolveArtifactsRoot();
|
|
26
|
+
const genDir = join(artifactsRoot, "ai");
|
|
27
|
+
await mkdir(genDir, { recursive: true });
|
|
28
|
+
const genPath = join(genDir, `${id}.${fp.slice(0, 8)}.fixed.gen.ts`);
|
|
29
|
+
if (existsSync(genPath) && !opts.write) {
|
|
30
|
+
const code = await readFile(genPath, "utf8");
|
|
31
|
+
debug("ai", `fix cache hit ${id}`);
|
|
32
|
+
return {
|
|
33
|
+
code,
|
|
34
|
+
genPath,
|
|
35
|
+
fingerprint: fp,
|
|
36
|
+
readPaths: []
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!envFlag("UNTESTUTILS_AI", false) && process.env.UNTESTUTILS_AI_MOCK !== "1") {
|
|
40
|
+
throw new Error(`[untestutils/ai] no cached fix for "${filePath}". Run with UNTESTUTILS_AI=1 (genPath would be ${genPath}).`);
|
|
41
|
+
}
|
|
42
|
+
const toolkit = createAgentToolkit({
|
|
43
|
+
root,
|
|
44
|
+
maxFilesRead: opts.maxFilesRead ?? 30,
|
|
45
|
+
maxBytesTotal: opts.maxBytesTotal ?? 3e5,
|
|
46
|
+
browser: opts.browser ? {
|
|
47
|
+
baseURL: opts.baseURL,
|
|
48
|
+
headless: true
|
|
49
|
+
} : opts.baseURL ? {
|
|
50
|
+
baseURL: opts.baseURL,
|
|
51
|
+
headless: true
|
|
52
|
+
} : false
|
|
53
|
+
});
|
|
54
|
+
try {
|
|
55
|
+
const system = await loadFixPrompt();
|
|
56
|
+
const code = await runAgent({
|
|
57
|
+
system,
|
|
58
|
+
mockKind: "fix",
|
|
59
|
+
mockRecipe: opts.recipes?.[0] ?? "basic",
|
|
60
|
+
maxSteps: opts.maxExploreSteps ?? 16,
|
|
61
|
+
tools: toolkit.tools,
|
|
62
|
+
prompt: [
|
|
63
|
+
`Failing file: ${relative(root, filePath)}`,
|
|
64
|
+
`Recipes: ${(opts.recipes ?? []).join(", ") || "(none)"}`,
|
|
65
|
+
opts.baseURL ? `Base URL: ${opts.baseURL}` : "Base URL: (none — use filesystem tools)",
|
|
66
|
+
`Failure log:\n\`\`\`\n${opts.failureLog.slice(0, 12e3)}\n\`\`\``,
|
|
67
|
+
`Current source:\n\`\`\`ts\n${source}\n\`\`\``,
|
|
68
|
+
`File tree (truncated):\n${tree.slice(0, 400).map((t) => t.path).join("\n")}`,
|
|
69
|
+
`Fix the test file. Explore the app if browser tools are available.`
|
|
70
|
+
].join("\n\n")
|
|
71
|
+
});
|
|
72
|
+
await writeFile(genPath, code, "utf8");
|
|
73
|
+
if (opts.write) {
|
|
74
|
+
await writeFile(filePath, code, "utf8");
|
|
75
|
+
log("ai", `fix wrote ${filePath}`);
|
|
76
|
+
} else {
|
|
77
|
+
log("ai", `fix cached ${genPath}`);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
code,
|
|
81
|
+
genPath,
|
|
82
|
+
fingerprint: fp,
|
|
83
|
+
readPaths: toolkit.readPaths()
|
|
84
|
+
};
|
|
85
|
+
} finally {
|
|
86
|
+
await toolkit.dispose?.();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type FileTreeEntry } from '../tree';
|
|
2
|
+
import type { GenerateResult } from './types';
|
|
3
|
+
export declare const AI_PROMPT_VERSION = "v1";
|
|
4
|
+
export declare const CONVERT_PROMPT_VERSION = "convert-v1";
|
|
5
|
+
export interface AiTestOptions {
|
|
6
|
+
id: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
root: string;
|
|
9
|
+
recipes?: string[];
|
|
10
|
+
focus?: string[];
|
|
11
|
+
maxAttempts?: number;
|
|
12
|
+
maxExploreSteps?: number;
|
|
13
|
+
maxFilesRead?: number;
|
|
14
|
+
maxBytesTotal?: number;
|
|
15
|
+
baseURL?: string;
|
|
16
|
+
browser?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function aiTest(opts: AiTestOptions): Promise<GenerateResult>;
|
|
19
|
+
export interface ConvertTestOptions {
|
|
20
|
+
path: string;
|
|
21
|
+
root: string;
|
|
22
|
+
maxFilesRead?: number;
|
|
23
|
+
maxBytesTotal?: number;
|
|
24
|
+
maxExploreSteps?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function convertTestFile(opts: ConvertTestOptions): Promise<GenerateResult>;
|
|
27
|
+
export declare function aiTestFromFile(path: string, defaults?: Partial<AiTestOptions>): Promise<GenerateResult>;
|
|
28
|
+
export type { FileTreeEntry };
|
|
29
|
+
//# sourceMappingURL=generate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/workflows/generate.ts"],"names":[],"mappings":"AAQA,OAAO,EAA6C,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,sBAAsB,eAAe,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAoBD,wBAAsB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAkEzE;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CA2DvF;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAO,CAAC,aAAa,CAAM,2BA+BvF;AAED,YAAY,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join, relative, resolve } from "pathe";
|
|
5
|
+
import { resolveArtifactsRoot, debug, envFlag, log } from "@untestutils/core";
|
|
6
|
+
import { runAgent } from "../agent/run.mjs";
|
|
7
|
+
import { loadConvertPrompt, loadSystemPrompt } from "../prompts.mjs";
|
|
8
|
+
import { createAgentToolkit } from "../tools/registry.mjs";
|
|
9
|
+
import { buildFileTree, fingerprint, treeSignature } from "../tree.mjs";
|
|
10
|
+
export const AI_PROMPT_VERSION = "v1";
|
|
11
|
+
export const CONVERT_PROMPT_VERSION = "convert-v1";
|
|
12
|
+
function genFingerprint(opts) {
|
|
13
|
+
return fingerprint([
|
|
14
|
+
opts.version ?? AI_PROMPT_VERSION,
|
|
15
|
+
opts.prompt.trim(),
|
|
16
|
+
resolve(opts.root),
|
|
17
|
+
opts.recipes.join(","),
|
|
18
|
+
opts.focus.join(","),
|
|
19
|
+
opts.treeSig
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
22
|
+
export async function aiTest(opts) {
|
|
23
|
+
const root = resolve(opts.root);
|
|
24
|
+
const tree = await buildFileTree(root);
|
|
25
|
+
const treeSig = treeSignature(tree);
|
|
26
|
+
const fp = genFingerprint({
|
|
27
|
+
prompt: opts.prompt,
|
|
28
|
+
root,
|
|
29
|
+
recipes: opts.recipes ?? [],
|
|
30
|
+
focus: opts.focus ?? [],
|
|
31
|
+
treeSig
|
|
32
|
+
});
|
|
33
|
+
const artifactsRoot = resolveArtifactsRoot();
|
|
34
|
+
const genDir = join(artifactsRoot, "ai");
|
|
35
|
+
await mkdir(genDir, { recursive: true });
|
|
36
|
+
const genPath = join(genDir, `${opts.id}.${fp.slice(0, 8)}.spec.gen.ts`);
|
|
37
|
+
if (existsSync(genPath)) {
|
|
38
|
+
const code = await readFile(genPath, "utf8");
|
|
39
|
+
debug("ai", `cache hit ${opts.id}`);
|
|
40
|
+
return {
|
|
41
|
+
code,
|
|
42
|
+
genPath,
|
|
43
|
+
fingerprint: fp,
|
|
44
|
+
readPaths: []
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (!envFlag("UNTESTUTILS_AI", false) && process.env.UNTESTUTILS_AI_MOCK !== "1") {
|
|
48
|
+
throw new Error(`[untestutils/ai] no cached test for "${opts.id}". Run locally with UNTESTUTILS_AI=1 once (genPath would be ${genPath}).`);
|
|
49
|
+
}
|
|
50
|
+
const toolkit = createAgentToolkit({
|
|
51
|
+
root,
|
|
52
|
+
maxFilesRead: opts.maxFilesRead ?? 20,
|
|
53
|
+
maxBytesTotal: opts.maxBytesTotal ?? 2e5,
|
|
54
|
+
browser: opts.browser || opts.baseURL ? { baseURL: opts.baseURL } : false
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
const system = await loadSystemPrompt();
|
|
58
|
+
const treeText = tree.slice(0, 500).map((t) => `${t.path} (${t.size})`).join("\n");
|
|
59
|
+
const code = await runAgent({
|
|
60
|
+
system,
|
|
61
|
+
mockKind: "generate",
|
|
62
|
+
mockRecipe: opts.recipes?.[0] ?? "basic",
|
|
63
|
+
maxSteps: opts.maxExploreSteps ?? 12,
|
|
64
|
+
tools: toolkit.tools,
|
|
65
|
+
prompt: [
|
|
66
|
+
`Recipes: ${(opts.recipes ?? []).join(", ") || "(none)"}`,
|
|
67
|
+
`Focus hints: ${(opts.focus ?? []).join(", ") || "(none)"}`,
|
|
68
|
+
opts.baseURL ? `Base URL: ${opts.baseURL}` : "",
|
|
69
|
+
`File tree under root:\n${treeText}`,
|
|
70
|
+
`User scenario:\n${opts.prompt}`,
|
|
71
|
+
`Use tools to read files you need, then output a single English ts-fenced test file.`
|
|
72
|
+
].filter(Boolean).join("\n\n")
|
|
73
|
+
});
|
|
74
|
+
await writeFile(genPath, code, "utf8");
|
|
75
|
+
log("ai", `wrote ${genPath}`);
|
|
76
|
+
return {
|
|
77
|
+
code,
|
|
78
|
+
genPath,
|
|
79
|
+
fingerprint: fp,
|
|
80
|
+
readPaths: toolkit.readPaths()
|
|
81
|
+
};
|
|
82
|
+
} finally {
|
|
83
|
+
await toolkit.dispose?.();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export async function convertTestFile(opts) {
|
|
87
|
+
const root = resolve(opts.root);
|
|
88
|
+
const filePath = resolve(opts.path);
|
|
89
|
+
const source = await readFile(filePath, "utf8");
|
|
90
|
+
const tree = await buildFileTree(root);
|
|
91
|
+
const treeSig = treeSignature(tree);
|
|
92
|
+
const id = `convert-${createHash("sha1").update(filePath).digest("hex").slice(0, 8)}`;
|
|
93
|
+
const fp = genFingerprint({
|
|
94
|
+
prompt: `${CONVERT_PROMPT_VERSION}\n${source}`,
|
|
95
|
+
root,
|
|
96
|
+
recipes: [],
|
|
97
|
+
focus: [relative(root, filePath)],
|
|
98
|
+
treeSig,
|
|
99
|
+
version: CONVERT_PROMPT_VERSION
|
|
100
|
+
});
|
|
101
|
+
const artifactsRoot = resolveArtifactsRoot();
|
|
102
|
+
const genDir = join(artifactsRoot, "ai");
|
|
103
|
+
await mkdir(genDir, { recursive: true });
|
|
104
|
+
const genPath = join(genDir, `${id}.${fp.slice(0, 8)}.spec.gen.ts`);
|
|
105
|
+
if (existsSync(genPath)) {
|
|
106
|
+
const code = await readFile(genPath, "utf8");
|
|
107
|
+
debug("ai", `convert cache hit ${id}`);
|
|
108
|
+
return {
|
|
109
|
+
code,
|
|
110
|
+
genPath,
|
|
111
|
+
fingerprint: fp,
|
|
112
|
+
readPaths: []
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (!envFlag("UNTESTUTILS_AI", false) && process.env.UNTESTUTILS_AI_MOCK !== "1") {
|
|
116
|
+
throw new Error(`[untestutils/ai] no cached convert for "${filePath}". Run with UNTESTUTILS_AI=1 once (genPath would be ${genPath}).`);
|
|
117
|
+
}
|
|
118
|
+
const toolkit = createAgentToolkit({
|
|
119
|
+
root,
|
|
120
|
+
maxFilesRead: opts.maxFilesRead ?? 20,
|
|
121
|
+
maxBytesTotal: opts.maxBytesTotal ?? 2e5
|
|
122
|
+
});
|
|
123
|
+
try {
|
|
124
|
+
const system = await loadConvertPrompt();
|
|
125
|
+
const code = await runAgent({
|
|
126
|
+
system,
|
|
127
|
+
mockKind: "convert",
|
|
128
|
+
maxSteps: opts.maxExploreSteps ?? 8,
|
|
129
|
+
tools: toolkit.tools,
|
|
130
|
+
prompt: [
|
|
131
|
+
`Convert this test file to untestutils.`,
|
|
132
|
+
`Source path: ${relative(root, filePath)}`,
|
|
133
|
+
`Source:\n\`\`\`ts\n${source}\n\`\`\``
|
|
134
|
+
].join("\n\n")
|
|
135
|
+
});
|
|
136
|
+
await writeFile(genPath, code, "utf8");
|
|
137
|
+
log("ai", `convert wrote ${genPath}`);
|
|
138
|
+
return {
|
|
139
|
+
code,
|
|
140
|
+
genPath,
|
|
141
|
+
fingerprint: fp,
|
|
142
|
+
readPaths: toolkit.readPaths()
|
|
143
|
+
};
|
|
144
|
+
} finally {
|
|
145
|
+
await toolkit.dispose?.();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export async function aiTestFromFile(path, defaults = {}) {
|
|
149
|
+
const raw = await readFile(path, "utf8");
|
|
150
|
+
const fm = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
151
|
+
const meta = {};
|
|
152
|
+
let prompt = raw;
|
|
153
|
+
if (fm) {
|
|
154
|
+
prompt = fm[2].trim();
|
|
155
|
+
for (const line of fm[1].split("\n")) {
|
|
156
|
+
const [k, ...rest] = line.split(":");
|
|
157
|
+
if (k) meta[k.trim()] = rest.join(":").trim().replace(/^['"]|['"]$/g, "");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return aiTest({
|
|
161
|
+
id: String(meta.id ?? defaults.id ?? "from-file"),
|
|
162
|
+
root: String(meta.root ?? defaults.root ?? "."),
|
|
163
|
+
recipes: meta.recipes ? String(meta.recipes).split(",").map((s) => s.trim()) : defaults.recipes,
|
|
164
|
+
focus: meta.focus ? String(meta.focus).split(",").map((s) => s.trim()) : defaults.focus,
|
|
165
|
+
prompt
|
|
166
|
+
});
|
|
167
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflows/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@untestutils/ai",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"files": [
|
|
5
|
+
"dist"
|
|
6
|
+
],
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"pathe": "^2.0.3",
|
|
19
|
+
"tinyglobby": "^0.2.17",
|
|
20
|
+
"@untestutils/core": "0.5.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^26.6.1",
|
|
24
|
+
"publint": "^0.3.24",
|
|
25
|
+
"typescript": "^6.0.3",
|
|
26
|
+
"obuild": "^0.4.40"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@ai-sdk/anthropic": "^4.0.57",
|
|
30
|
+
"@ai-sdk/google": "^4.0.75",
|
|
31
|
+
"@ai-sdk/openai": "^4.0.70",
|
|
32
|
+
"@ai-sdk/xai": "^5.0.3",
|
|
33
|
+
"ai": "^7.0.106",
|
|
34
|
+
"playwright-core": "^1.63.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"ai": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"@ai-sdk/openai": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
43
|
+
"@ai-sdk/anthropic": {
|
|
44
|
+
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"@ai-sdk/google": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"@ai-sdk/xai": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
52
|
+
"playwright-core": {
|
|
53
|
+
"optional": true
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=20"
|
|
58
|
+
},
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"homepage": "https://s00d.github.io/untestutils/",
|
|
61
|
+
"repository": {
|
|
62
|
+
"type": "git",
|
|
63
|
+
"url": "git+https://github.com/s00d/untestutils.git",
|
|
64
|
+
"directory": "packages/ai"
|
|
65
|
+
},
|
|
66
|
+
"main": "./dist/index.mjs",
|
|
67
|
+
"types": "./dist/index.d.ts",
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"access": "public"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "obuild && tsc -p tsconfig.build.json",
|
|
73
|
+
"publint": "publint --strict"
|
|
74
|
+
}
|
|
75
|
+
}
|