@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 s00d
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type RunAgentOptions } from "./types.mjs";
|
|
2
|
+
export declare function runAgent(opts: RunAgentOptions): Promise<string>;
|
|
3
|
+
/** Like runAgent but returns raw model text (for multi-file cover). */
|
|
4
|
+
export declare function runAgentRaw(opts: RunAgentOptions): Promise<string>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type RunAgentOptions } from './types';
|
|
2
|
+
export declare function runAgent(opts: RunAgentOptions): Promise<string>;
|
|
3
|
+
/** Like runAgent but returns raw model text (for multi-file cover). */
|
|
4
|
+
export declare function runAgentRaw(opts: RunAgentOptions): Promise<string>;
|
|
5
|
+
/** @internal back-compat for older coverage tests */
|
|
6
|
+
export declare function runLlmGenerate(opts: {
|
|
7
|
+
system: string;
|
|
8
|
+
prompt: string;
|
|
9
|
+
tree?: unknown[];
|
|
10
|
+
focus?: string[];
|
|
11
|
+
recipes?: string[];
|
|
12
|
+
tools: {
|
|
13
|
+
list_dir: (path?: string) => Promise<unknown>;
|
|
14
|
+
read_file: (path: string) => Promise<unknown>;
|
|
15
|
+
grep: (pattern: string, path?: string) => Promise<unknown>;
|
|
16
|
+
};
|
|
17
|
+
maxSteps?: number;
|
|
18
|
+
}): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/agent/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkC,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAqB/E,wBAAsB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA4DrE;AAED,uEAAuE;AACvE,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBxE;AAED,qDAAqD;AACrD,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE;QACL,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;KAC5D,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CA+ClB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { envFlag } from "@untestutils/core";
|
|
2
|
+
import { _internals, resolveModel } from "../model.mjs";
|
|
3
|
+
import { extractTsFence } from "./types.mjs";
|
|
4
|
+
function buildAiTools(toolFactory, tools) {
|
|
5
|
+
const toolsObj = {};
|
|
6
|
+
for (const t of tools) {
|
|
7
|
+
toolsObj[t.name] = toolFactory({
|
|
8
|
+
description: t.description,
|
|
9
|
+
inputSchema: t.inputSchema,
|
|
10
|
+
execute: async (args) => t.execute(args ?? {})
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return toolsObj;
|
|
14
|
+
}
|
|
15
|
+
export async function runAgent(opts) {
|
|
16
|
+
if (process.env.UNTESTUTILS_AI_MOCK === "1") {
|
|
17
|
+
const recipe = opts.mockRecipe ?? "basic";
|
|
18
|
+
const kind = opts.mockKind ?? (/\bconvert\b/i.test(opts.system) ? "convert" : /\bfix broken\b|\byou fix\b/i.test(opts.system) ? "fix" : /\bmissing\b/i.test(opts.system) ? "cover" : "generate");
|
|
19
|
+
if (kind === "convert") {
|
|
20
|
+
return `import { describe, test, expect, useHarness } from 'untestutils/vitest'\n\ndescribe('converted', () => {\n test('placeholder from mock convert', async () => {\n const app = await useHarness('${recipe}')\n expect(app.url || app.dir).toBeTruthy()\n })\n})\n`;
|
|
21
|
+
}
|
|
22
|
+
if (kind === "fix") {
|
|
23
|
+
return `import { describe, test, expect, useHarness } from 'untestutils/vitest'\n\ndescribe('fixed', () => {\n test('placeholder from mock fix', async () => {\n const app = await useHarness('${recipe}')\n expect(app.url || app.dir).toBeTruthy()\n })\n})\n`;
|
|
24
|
+
}
|
|
25
|
+
if (kind === "cover") {
|
|
26
|
+
return `import { describe, test, expect, useHarness } from 'untestutils/vitest'\n\ndescribe('coverage', () => {\n test('placeholder from mock cover', async () => {\n const app = await useHarness('${recipe}')\n const html = await app.$fetch('/')\n expect(html).toBeTruthy()\n })\n})\n`;
|
|
27
|
+
}
|
|
28
|
+
const focus = opts.prompt.match(/Focus[^\n]*:\s*([^\n]+)/i);
|
|
29
|
+
if (focus?.[1] && focus[1] !== "(none)") {
|
|
30
|
+
const first = focus[1].split(",")[0]?.trim();
|
|
31
|
+
if (first) {
|
|
32
|
+
const read = opts.tools.find((t) => t.name === "read_file");
|
|
33
|
+
if (read) await read.execute({ path: first }).catch(() => "");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return `import { describe, test, expect } from 'vitest'\nimport { useHarness } from 'untestutils'\n\ndescribe('ai-generated', () => {\n test('placeholder from mock', async () => {\n const app = await useHarness('${recipe}')\n expect(app.url || app.dir).toBeTruthy()\n })\n})\n`;
|
|
37
|
+
}
|
|
38
|
+
if (!envFlag("UNTESTUTILS_AI", false) && process.env.UNTESTUTILS_AI_MOCK !== "1") {}
|
|
39
|
+
try {
|
|
40
|
+
const ai = await _internals.importAi();
|
|
41
|
+
const { generateText, tool } = ai;
|
|
42
|
+
const stepCountIs = ai.stepCountIs;
|
|
43
|
+
const model = await resolveModel();
|
|
44
|
+
const maxSteps = opts.maxSteps ?? 16;
|
|
45
|
+
const result = await generateText({
|
|
46
|
+
model,
|
|
47
|
+
system: opts.system,
|
|
48
|
+
prompt: opts.prompt,
|
|
49
|
+
tools: buildAiTools(tool, opts.tools),
|
|
50
|
+
...stepCountIs ? { stopWhen: stepCountIs(maxSteps) } : {}
|
|
51
|
+
});
|
|
52
|
+
return extractTsFence(result.text);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
if (String(e).includes("Cannot find package 'ai'") || String(e).includes("MODULE_NOT_FOUND")) {
|
|
55
|
+
throw new Error(`[untestutils/ai] install peer "ai" and a provider. Or set UNTESTUTILS_AI_MOCK=1. Cause: ${e}`);
|
|
56
|
+
}
|
|
57
|
+
throw e;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function runAgentRaw(opts) {
|
|
62
|
+
if (process.env.UNTESTUTILS_AI_MOCK === "1") {
|
|
63
|
+
return `\`\`\`ts file:tests/e2e/generated-cover.test.ts\n${await runAgent({
|
|
64
|
+
...opts,
|
|
65
|
+
mockKind: opts.mockKind ?? "cover"
|
|
66
|
+
})}\n\`\`\``;
|
|
67
|
+
}
|
|
68
|
+
const ai = await _internals.importAi();
|
|
69
|
+
const { generateText, tool } = ai;
|
|
70
|
+
const stepCountIs = ai.stepCountIs;
|
|
71
|
+
const model = await resolveModel();
|
|
72
|
+
const maxSteps = opts.maxSteps ?? 20;
|
|
73
|
+
const result = await generateText({
|
|
74
|
+
model,
|
|
75
|
+
system: opts.system,
|
|
76
|
+
prompt: opts.prompt,
|
|
77
|
+
tools: buildAiTools(tool, opts.tools),
|
|
78
|
+
...stepCountIs ? { stopWhen: stepCountIs(maxSteps) } : {}
|
|
79
|
+
});
|
|
80
|
+
return result.text;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function runLlmGenerate(opts) {
|
|
84
|
+
const tools = [
|
|
85
|
+
{
|
|
86
|
+
name: "list_dir",
|
|
87
|
+
description: "List directory under project root",
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: { path: {
|
|
91
|
+
type: "string",
|
|
92
|
+
description: "Relative directory"
|
|
93
|
+
} }
|
|
94
|
+
},
|
|
95
|
+
execute: async (args) => opts.tools.list_dir(args.path ? String(args.path) : undefined)
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "read_file",
|
|
99
|
+
description: "Read a file under project root",
|
|
100
|
+
inputSchema: {
|
|
101
|
+
type: "object",
|
|
102
|
+
properties: { path: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "Relative file path"
|
|
105
|
+
} },
|
|
106
|
+
required: ["path"]
|
|
107
|
+
},
|
|
108
|
+
execute: async (args) => opts.tools.read_file(String(args.path))
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: "grep",
|
|
112
|
+
description: "Search files for a regex pattern",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: "object",
|
|
115
|
+
properties: {
|
|
116
|
+
pattern: {
|
|
117
|
+
type: "string",
|
|
118
|
+
description: "Regex"
|
|
119
|
+
},
|
|
120
|
+
path: {
|
|
121
|
+
type: "string",
|
|
122
|
+
description: "Relative start path"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
required: ["pattern"]
|
|
126
|
+
},
|
|
127
|
+
execute: async (args) => opts.tools.grep(String(args.pattern), args.path ? String(args.path) : undefined)
|
|
128
|
+
}
|
|
129
|
+
];
|
|
130
|
+
return runAgent({
|
|
131
|
+
system: opts.system,
|
|
132
|
+
maxSteps: opts.maxSteps,
|
|
133
|
+
tools,
|
|
134
|
+
prompt: [
|
|
135
|
+
opts.prompt,
|
|
136
|
+
`Focus: ${(opts.focus ?? []).join(", ") || "(none)"}`,
|
|
137
|
+
`Recipes: ${(opts.recipes ?? []).join(", ") || "(none)"}`
|
|
138
|
+
].join("\n")
|
|
139
|
+
});
|
|
140
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ToolParameter {
|
|
2
|
+
type: "object";
|
|
3
|
+
properties: Record<string, {
|
|
4
|
+
type: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface AgentTool {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
inputSchema: ToolParameter;
|
|
13
|
+
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface AgentToolBag {
|
|
16
|
+
tools: AgentTool[];
|
|
17
|
+
readPaths: () => string[];
|
|
18
|
+
dispose?: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface RunAgentOptions {
|
|
21
|
+
system: string;
|
|
22
|
+
prompt: string;
|
|
23
|
+
tools: AgentTool[];
|
|
24
|
+
maxSteps?: number;
|
|
25
|
+
/** Mock mode key for deterministic fixtures */
|
|
26
|
+
mockKind?: "generate" | "convert" | "fix" | "cover";
|
|
27
|
+
mockRecipe?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function extractTsFence(text: string): string;
|
|
30
|
+
export declare function extractLabeledTsFiles(text: string): {
|
|
31
|
+
path?: string;
|
|
32
|
+
code: string;
|
|
33
|
+
}[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface ToolParameter {
|
|
2
|
+
type: 'object';
|
|
3
|
+
properties: Record<string, {
|
|
4
|
+
type: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}>;
|
|
7
|
+
required?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface AgentTool {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
inputSchema: ToolParameter;
|
|
13
|
+
execute: (args: Record<string, unknown>) => Promise<unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface AgentToolBag {
|
|
16
|
+
tools: AgentTool[];
|
|
17
|
+
readPaths: () => string[];
|
|
18
|
+
dispose?: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export interface RunAgentOptions {
|
|
21
|
+
system: string;
|
|
22
|
+
prompt: string;
|
|
23
|
+
tools: AgentTool[];
|
|
24
|
+
maxSteps?: number;
|
|
25
|
+
/** Mock mode key for deterministic fixtures */
|
|
26
|
+
mockKind?: 'generate' | 'convert' | 'fix' | 'cover';
|
|
27
|
+
mockRecipe?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function extractTsFence(text: string): string;
|
|
30
|
+
export declare function extractLabeledTsFiles(text: string): {
|
|
31
|
+
path?: string;
|
|
32
|
+
code: string;
|
|
33
|
+
}[];
|
|
34
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agent/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,aAAa,CAAC;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,MAAM,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,OAAO,CAAC;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAInD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAarF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function extractTsFence(text) {
|
|
2
|
+
const match = text.match(/```ts\n([\s\S]*?)```/) || text.match(/```typescript\n([\s\S]*?)```/);
|
|
3
|
+
if (!match) throw new Error("[untestutils/ai] model did not return a ts fence");
|
|
4
|
+
return match[1];
|
|
5
|
+
}
|
|
6
|
+
export function extractLabeledTsFiles(text) {
|
|
7
|
+
const blocks = [];
|
|
8
|
+
const re = /```(?:ts|typescript)(?:\s+([^\n]+))?\n([\s\S]*?)```/g;
|
|
9
|
+
let m;
|
|
10
|
+
while (m = re.exec(text)) {
|
|
11
|
+
const label = m[1]?.trim();
|
|
12
|
+
const path = label?.startsWith("file:") ? label.slice(5).trim() : label;
|
|
13
|
+
blocks.push({
|
|
14
|
+
path: path || undefined,
|
|
15
|
+
code: m[2]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (blocks.length === 0) {
|
|
19
|
+
blocks.push({ code: extractTsFence(text) });
|
|
20
|
+
}
|
|
21
|
+
return blocks;
|
|
22
|
+
}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { buildFileTree, treeSignature, fingerprint, listTestFiles, IGNORE } from "./tree.mjs";
|
|
2
|
+
export type { FileTreeEntry } from "./tree.mjs";
|
|
3
|
+
export { loadPrompt, loadSystemPrompt, loadConvertPrompt, loadFixPrompt, loadCoverPrompt, aiFs } from "./prompts.mjs";
|
|
4
|
+
export type { PromptName } from "./prompts.mjs";
|
|
5
|
+
export { resolveModel, _internals } from "./model.mjs";
|
|
6
|
+
export { createFsTools, createAiTools } from "./tools/fs.mjs";
|
|
7
|
+
export { createBrowserTools } from "./tools/browser.mjs";
|
|
8
|
+
export { createAgentToolkit } from "./tools/registry.mjs";
|
|
9
|
+
export type { CreateAgentToolkitOptions } from "./tools/registry.mjs";
|
|
10
|
+
export { runAgent, runAgentRaw, runLlmGenerate } from "./agent/run.mjs";
|
|
11
|
+
export { extractTsFence, extractLabeledTsFiles } from "./agent/types.mjs";
|
|
12
|
+
export type { AgentTool, AgentToolBag, RunAgentOptions } from "./agent/types.mjs";
|
|
13
|
+
export { aiTest, aiTestFromFile, convertTestFile, AI_PROMPT_VERSION, CONVERT_PROMPT_VERSION } from "./workflows/generate.mjs";
|
|
14
|
+
export type { AiTestOptions, ConvertTestOptions } from "./workflows/generate.mjs";
|
|
15
|
+
export type { GenerateResult } from "./workflows/types.mjs";
|
|
16
|
+
export { fixBrokenTests } from "./workflows/fix.mjs";
|
|
17
|
+
export type { FixTestsOptions } from "./workflows/fix.mjs";
|
|
18
|
+
export { coverMissingTests } from "./workflows/cover.mjs";
|
|
19
|
+
export type { CoverTestsOptions, CoverResult } from "./workflows/cover.mjs";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { buildFileTree, treeSignature, fingerprint, listTestFiles, IGNORE } from './tree';
|
|
2
|
+
export type { FileTreeEntry } from './tree';
|
|
3
|
+
export { loadPrompt, loadSystemPrompt, loadConvertPrompt, loadFixPrompt, loadCoverPrompt, aiFs, } from './prompts';
|
|
4
|
+
export type { PromptName } from './prompts';
|
|
5
|
+
export { resolveModel, _internals } from './model';
|
|
6
|
+
export { createFsTools, createAiTools } from './tools/fs';
|
|
7
|
+
export { createBrowserTools } from './tools/browser';
|
|
8
|
+
export { createAgentToolkit } from './tools/registry';
|
|
9
|
+
export type { CreateAgentToolkitOptions } from './tools/registry';
|
|
10
|
+
export { runAgent, runAgentRaw, runLlmGenerate } from './agent/run';
|
|
11
|
+
export { extractTsFence, extractLabeledTsFiles } from './agent/types';
|
|
12
|
+
export type { AgentTool, AgentToolBag, RunAgentOptions } from './agent/types';
|
|
13
|
+
export { aiTest, aiTestFromFile, convertTestFile, AI_PROMPT_VERSION, CONVERT_PROMPT_VERSION, } from './workflows/generate';
|
|
14
|
+
export type { AiTestOptions, ConvertTestOptions } from './workflows/generate';
|
|
15
|
+
export type { GenerateResult } from './workflows/types';
|
|
16
|
+
export { fixBrokenTests } from './workflows/fix';
|
|
17
|
+
export type { FixTestsOptions } from './workflows/fix';
|
|
18
|
+
export { coverMissingTests } from './workflows/cover';
|
|
19
|
+
export type { CoverTestsOptions, CoverResult } from './workflows/cover';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC1F,YAAY,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAM9E,OAAO,EACL,MAAM,EACN,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { buildFileTree, treeSignature, fingerprint, listTestFiles, IGNORE } from "./tree.mjs";
|
|
2
|
+
export { loadPrompt, loadSystemPrompt, loadConvertPrompt, loadFixPrompt, loadCoverPrompt, aiFs } from "./prompts.mjs";
|
|
3
|
+
export { resolveModel, _internals } from "./model.mjs";
|
|
4
|
+
export { createFsTools, createAiTools } from "./tools/fs.mjs";
|
|
5
|
+
export { createBrowserTools } from "./tools/browser.mjs";
|
|
6
|
+
export { createAgentToolkit } from "./tools/registry.mjs";
|
|
7
|
+
export { runAgent, runAgentRaw, runLlmGenerate } from "./agent/run.mjs";
|
|
8
|
+
export { extractTsFence, extractLabeledTsFiles } from "./agent/types.mjs";
|
|
9
|
+
import { runLlmGenerate } from "./agent/run.mjs";
|
|
10
|
+
import { _internals } from "./model.mjs";
|
|
11
|
+
_internals.runLlmGenerate = runLlmGenerate;
|
|
12
|
+
export { aiTest, aiTestFromFile, convertTestFile, AI_PROMPT_VERSION, CONVERT_PROMPT_VERSION } from "./workflows/generate.mjs";
|
|
13
|
+
export { fixBrokenTests } from "./workflows/fix.mjs";
|
|
14
|
+
export { coverMissingTests } from "./workflows/cover.mjs";
|
package/dist/model.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolveModel(): Promise<unknown>;
|
package/dist/model.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { runLlmGenerate } from './agent/run';
|
|
2
|
+
/** @internal test seams for LLM path */
|
|
3
|
+
export declare const _internals: {
|
|
4
|
+
importAi: () => Promise<typeof import("ai")>;
|
|
5
|
+
importAnthropic: () => Promise<typeof import("@ai-sdk/anthropic")>;
|
|
6
|
+
importXai: () => Promise<typeof import("@ai-sdk/xai")>;
|
|
7
|
+
importGoogle: () => Promise<typeof import("@ai-sdk/google")>;
|
|
8
|
+
importOpenai: () => Promise<typeof import("@ai-sdk/openai")>;
|
|
9
|
+
/** Bound after define — coverage tests spy imports then call via _internals */
|
|
10
|
+
resolveModel: () => Promise<unknown>;
|
|
11
|
+
runLlmGenerate: typeof runLlmGenerate;
|
|
12
|
+
};
|
|
13
|
+
export declare function resolveModel(): Promise<unknown>;
|
|
14
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wCAAwC;AACxC,eAAO,MAAM,UAAU;;;;;;IAMrB,+EAA+E;kBAC9C,MAAM,OAAO,CAAC,OAAO,CAAC;oBACpB,OAAO,cAAc;CACzD,CAAC;AAEF,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAgBrD"}
|
package/dist/model.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
export const _internals = {
|
|
3
|
+
importAi: () => import("ai"),
|
|
4
|
+
importAnthropic: () => import("@ai-sdk/anthropic"),
|
|
5
|
+
importXai: () => import("@ai-sdk/xai"),
|
|
6
|
+
importGoogle: () => import("@ai-sdk/google"),
|
|
7
|
+
importOpenai: () => import("@ai-sdk/openai"),
|
|
8
|
+
|
|
9
|
+
resolveModel: null,
|
|
10
|
+
runLlmGenerate: null
|
|
11
|
+
};
|
|
12
|
+
export async function resolveModel() {
|
|
13
|
+
const provider = process.env.UNTESTUTILS_AI_PROVIDER || "openai";
|
|
14
|
+
if (provider === "anthropic") {
|
|
15
|
+
const { anthropic } = await _internals.importAnthropic();
|
|
16
|
+
return anthropic(process.env.UNTESTUTILS_AI_MODEL || "claude-sonnet-4-20250514");
|
|
17
|
+
}
|
|
18
|
+
if (provider === "xai") {
|
|
19
|
+
const { xai } = await _internals.importXai();
|
|
20
|
+
return xai(process.env.UNTESTUTILS_AI_MODEL || "grok-3");
|
|
21
|
+
}
|
|
22
|
+
if (provider === "google") {
|
|
23
|
+
const { google } = await _internals.importGoogle();
|
|
24
|
+
return google(process.env.UNTESTUTILS_AI_MODEL || "gemini-2.0-flash");
|
|
25
|
+
}
|
|
26
|
+
const { openai } = await _internals.importOpenai();
|
|
27
|
+
return openai(process.env.UNTESTUTILS_AI_MODEL || "gpt-4.1");
|
|
28
|
+
}
|
|
29
|
+
_internals.resolveModel = resolveModel;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# untestutils convert
|
|
2
|
+
|
|
3
|
+
Rewrite the given test to untestutils. Keep intent. English only. One \`\`\`ts fence.
|
|
4
|
+
|
|
5
|
+
Map: `@nuxt/test-utils` `setup`/`createPage`/`$fetch` → `useHarness` + `app.$fetch` / vitest `page`/`goto`. Hardcoded `localhost` → harness `url`/`baseURL`. Plain `@playwright/test` → `untestutils/playwright` + `test.use({ harness })`. Drop obsolete setup when harness covers it. Real recipe ids only.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// after (vitest)
|
|
9
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
10
|
+
describe('home', () => {
|
|
11
|
+
test('renders', async ({ page, goto }) => {
|
|
12
|
+
const app = await useHarness('app')
|
|
13
|
+
expect(await app.$fetch('/')).toContain('Welcome')
|
|
14
|
+
await goto('/', { waitUntil: 'hydration' })
|
|
15
|
+
await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible()
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
// after (playwright)
|
|
22
|
+
import { test, expect } from 'untestutils/playwright'
|
|
23
|
+
test.use({ harness: 'site' })
|
|
24
|
+
test('home', async ({ page }) => {
|
|
25
|
+
await page.goto('/')
|
|
26
|
+
await expect(page.getByTestId('title')).toHaveText('Home')
|
|
27
|
+
})
|
|
28
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# untestutils cover
|
|
2
|
+
|
|
3
|
+
Write missing high-value e2e tests only (gaps vs existing tests). English only. Inventory first; if base URL → `browser_goto` + `browser_snapshot`. Real recipe ids. Prefer outDir. Few focused tests, meaningful asserts. No sleeps/invented UI.
|
|
4
|
+
|
|
5
|
+
Output: one \`\`\`ts fence, or multiple \`\`\`ts file:relative/path.test.ts
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
9
|
+
describe('about', () => {
|
|
10
|
+
test('serves about', async () => {
|
|
11
|
+
const app = await useHarness('site')
|
|
12
|
+
expect(await app.$fetch('/about')).toContain('About')
|
|
13
|
+
})
|
|
14
|
+
})
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
19
|
+
test('form', async ({ page, goto }) => {
|
|
20
|
+
await useHarness('site')
|
|
21
|
+
await goto('/contact')
|
|
22
|
+
await page.getByLabel('Email').fill('user@example.com')
|
|
23
|
+
await page.getByRole('button', { name: 'Send' }).click()
|
|
24
|
+
await expect(page.getByRole('status')).toContainText('Thanks')
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { test, expect } from 'untestutils/playwright'
|
|
30
|
+
test.use({ harness: 'site' })
|
|
31
|
+
test('privacy', async ({ page }) => {
|
|
32
|
+
await page.goto('/')
|
|
33
|
+
await page.getByRole('link', { name: 'Privacy' }).click()
|
|
34
|
+
await expect(page.getByRole('heading', { name: 'Privacy' })).toBeVisible()
|
|
35
|
+
})
|
|
36
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# untestutils fix
|
|
2
|
+
|
|
3
|
+
Fix the broken untestutils test. Keep intent — no skip, no weaker asserts, no sleep. English only. Tools/browser first if available. One \`\`\`ts fence, full file.
|
|
4
|
+
|
|
5
|
+
Typical fixes: real recipe id; `getByRole`/`getByTestId` instead of brittle CSS; Nuxt → `goto('/', { waitUntil: 'hydration' })`; fetch via `useHarness` + `$fetch` not hardcoded host; playwright needs `test.use({ harness })`. Ground text/selectors in snapshot/source.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// bad → good
|
|
9
|
+
await goto('/'); await page.locator('div > h1.x').click()
|
|
10
|
+
await goto('/', { waitUntil: 'hydration' }); await page.getByRole('heading', { name: 'Home' }).click()
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
15
|
+
test('title', async ({ page, goto }) => {
|
|
16
|
+
await useHarness('site')
|
|
17
|
+
await goto('/')
|
|
18
|
+
await expect(page.getByRole('heading', { name: 'Home' })).toBeVisible()
|
|
19
|
+
})
|
|
20
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# untestutils test author
|
|
2
|
+
|
|
3
|
+
English code/comments only. Explore tools first (`list_dir`/`read_file`/`grep`; prefer focus). Use real recipe ids from the project. One \`\`\`ts fence, full file, no prose outside.
|
|
4
|
+
|
|
5
|
+
APIs: `useHarness`, `$fetch`, `url`/`dir`/`files`, vitest fixtures `page`/`goto`/`baseURL`/`request`, or playwright `test.use({ harness })`. Prefer `getByRole`/`getByText`/`getByTestId`. No sleeps. No invented UI/secrets.
|
|
6
|
+
|
|
7
|
+
Shapes:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
11
|
+
describe('home', () => {
|
|
12
|
+
test('title', async () => {
|
|
13
|
+
const app = await useHarness('site')
|
|
14
|
+
expect(await app.$fetch('/')).toContain('Welcome')
|
|
15
|
+
})
|
|
16
|
+
})
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { describe, test, expect, useHarness } from 'untestutils/vitest'
|
|
21
|
+
test('nav', async ({ page, goto }) => {
|
|
22
|
+
await useHarness('site')
|
|
23
|
+
await goto('/') // Nuxt: goto('/', { waitUntil: 'hydration' })
|
|
24
|
+
await page.getByRole('link', { name: 'About' }).click()
|
|
25
|
+
await expect(page.getByRole('heading', { name: 'About' })).toBeVisible()
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { test, expect } from 'untestutils/playwright'
|
|
31
|
+
test.use({ harness: 'site' })
|
|
32
|
+
test('home', async ({ page, baseURL }) => {
|
|
33
|
+
expect(baseURL).toBeTruthy()
|
|
34
|
+
await page.goto('/')
|
|
35
|
+
await expect(page.getByTestId('title')).toHaveText('Home')
|
|
36
|
+
})
|
|
37
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare const aiFs: {
|
|
5
|
+
existsSync: typeof existsSync;
|
|
6
|
+
readFile: typeof readFile;
|
|
7
|
+
};
|
|
8
|
+
export type PromptName = 'v1' | 'convert-v1' | 'fix-v1' | 'cover-v1';
|
|
9
|
+
export declare function loadPrompt(name: PromptName): Promise<string>;
|
|
10
|
+
export declare const loadSystemPrompt: () => Promise<string>;
|
|
11
|
+
export declare const loadConvertPrompt: () => Promise<string>;
|
|
12
|
+
export declare const loadFixPrompt: () => Promise<string>;
|
|
13
|
+
export declare const loadCoverPrompt: () => Promise<string>;
|
|
14
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAI5C,gBAAgB;AAChB,eAAO,MAAM,IAAI;;;CAGhB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AASrE,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAWlE;AAED,eAAO,MAAM,gBAAgB,uBAAyB,CAAC;AACvD,eAAO,MAAM,iBAAiB,uBAAiC,CAAC;AAChE,eAAO,MAAM,aAAa,uBAA6B,CAAC;AACxD,eAAO,MAAM,eAAe,uBAA+B,CAAC"}
|
package/dist/prompts.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "pathe";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
export const aiFs = {
|
|
7
|
+
existsSync,
|
|
8
|
+
readFile
|
|
9
|
+
};
|
|
10
|
+
const DEFAULTS = {
|
|
11
|
+
v1: `English untestutils tests. Tools first. useHarness+$fetch or page/goto; playwright test.use({harness}). One ts fence.`,
|
|
12
|
+
"convert-v1": `Convert to untestutils (useHarness / untestutils/vitest|playwright). Keep intent. English. One ts fence.`,
|
|
13
|
+
"fix-v1": `Fix broken untestutils test. Keep intent; no sleep/skip. Real selectors/recipe. English. One ts fence.`,
|
|
14
|
+
"cover-v1": `Missing high-value e2e only. Inventory+snapshot. English. ts fence or ts file:path.`
|
|
15
|
+
};
|
|
16
|
+
export async function loadPrompt(name) {
|
|
17
|
+
const file = `${name}.md`;
|
|
18
|
+
const candidates = [
|
|
19
|
+
join(dirname(fileURLToPath(import.meta.url)), "prompts", file),
|
|
20
|
+
resolve(process.cwd(), "src/ai/prompts", file),
|
|
21
|
+
resolve(process.cwd(), "packages/ai/src/prompts", file)
|
|
22
|
+
];
|
|
23
|
+
for (const c of candidates) {
|
|
24
|
+
if (aiFs.existsSync(c)) return aiFs.readFile(c, "utf8");
|
|
25
|
+
}
|
|
26
|
+
return DEFAULTS[name];
|
|
27
|
+
}
|
|
28
|
+
export const loadSystemPrompt = () => loadPrompt("v1");
|
|
29
|
+
export const loadConvertPrompt = () => loadPrompt("convert-v1");
|
|
30
|
+
export const loadFixPrompt = () => loadPrompt("fix-v1");
|
|
31
|
+
export const loadCoverPrompt = () => loadPrompt("cover-v1");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentToolBag } from "../agent/types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Playwright-backed page tools for the shared AI agent.
|
|
4
|
+
* Optional peer: playwright-core. Used by CLI fix/cover workflows.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBrowserTools(opts?: {
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
headless?: boolean;
|
|
9
|
+
}): AgentToolBag;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AgentToolBag } from '../agent/types';
|
|
2
|
+
/**
|
|
3
|
+
* Playwright-backed page tools for the shared AI agent.
|
|
4
|
+
* Optional peer: playwright-core. Used by CLI fix/cover workflows.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBrowserTools(opts?: {
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
headless?: boolean;
|
|
9
|
+
}): AgentToolBag;
|
|
10
|
+
//# sourceMappingURL=browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/tools/browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,GAAE;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,GACL,YAAY,CAqId"}
|