@rudderjs/ai 1.5.0 → 1.6.1
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/README.md +482 -4
- package/boost/guidelines.md +60 -0
- package/boost/skills/ai-agents/SKILL.md +7 -0
- package/boost/skills/ai-tools/SKILL.md +7 -0
- package/dist/agent.d.ts +35 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +118 -16
- package/dist/agent.js.map +1 -1
- package/dist/budget/pricing.d.ts +124 -0
- package/dist/budget/pricing.d.ts.map +1 -0
- package/dist/budget/pricing.js +175 -0
- package/dist/budget/pricing.js.map +1 -0
- package/dist/budget/storage.d.ts +104 -0
- package/dist/budget/storage.d.ts.map +1 -0
- package/dist/budget/storage.js +0 -0
- package/dist/budget/storage.js.map +1 -0
- package/dist/budget/with-budget.d.ts +119 -0
- package/dist/budget/with-budget.d.ts.map +1 -0
- package/dist/budget/with-budget.js +175 -0
- package/dist/budget/with-budget.js.map +1 -0
- package/dist/budget-orm/index.d.ts +96 -0
- package/dist/budget-orm/index.d.ts.map +1 -0
- package/dist/budget-orm/index.js +177 -0
- package/dist/budget-orm/index.js.map +1 -0
- package/dist/commands/ai-eval.d.ts +93 -0
- package/dist/commands/ai-eval.d.ts.map +1 -0
- package/dist/commands/ai-eval.js +378 -0
- package/dist/commands/ai-eval.js.map +1 -0
- package/dist/computer-use/actions.d.ts +214 -0
- package/dist/computer-use/actions.d.ts.map +1 -0
- package/dist/computer-use/actions.js +48 -0
- package/dist/computer-use/actions.js.map +1 -0
- package/dist/computer-use/errors.d.ts +57 -0
- package/dist/computer-use/errors.d.ts.map +1 -0
- package/dist/computer-use/errors.js +76 -0
- package/dist/computer-use/errors.js.map +1 -0
- package/dist/computer-use/index.d.ts +53 -0
- package/dist/computer-use/index.d.ts.map +1 -0
- package/dist/computer-use/index.js +51 -0
- package/dist/computer-use/index.js.map +1 -0
- package/dist/computer-use/playwright.d.ts +76 -0
- package/dist/computer-use/playwright.d.ts.map +1 -0
- package/dist/computer-use/playwright.js +270 -0
- package/dist/computer-use/playwright.js.map +1 -0
- package/dist/computer-use/tool.d.ts +154 -0
- package/dist/computer-use/tool.d.ts.map +1 -0
- package/dist/computer-use/tool.js +210 -0
- package/dist/computer-use/tool.js.map +1 -0
- package/dist/eval/fixtures.d.ts +65 -0
- package/dist/eval/fixtures.d.ts.map +1 -0
- package/dist/eval/fixtures.js +110 -0
- package/dist/eval/fixtures.js.map +1 -0
- package/dist/eval/html-reporter.d.ts +25 -0
- package/dist/eval/html-reporter.d.ts.map +1 -0
- package/dist/eval/html-reporter.js +209 -0
- package/dist/eval/html-reporter.js.map +1 -0
- package/dist/eval/index.d.ts +271 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +510 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/json-reporter.d.ts +43 -0
- package/dist/eval/json-reporter.d.ts.map +1 -0
- package/dist/eval/json-reporter.js +40 -0
- package/dist/eval/json-reporter.js.map +1 -0
- package/dist/fake.d.ts +36 -1
- package/dist/fake.d.ts.map +1 -1
- package/dist/fake.js +49 -2
- package/dist/fake.js.map +1 -1
- package/dist/file-search.d.ts +168 -0
- package/dist/file-search.d.ts.map +1 -0
- package/dist/file-search.js +158 -0
- package/dist/file-search.js.map +1 -0
- package/dist/index.d.ts +22 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/client-tools.d.ts +39 -0
- package/dist/mcp/client-tools.d.ts.map +1 -0
- package/dist/mcp/client-tools.js +147 -0
- package/dist/mcp/client-tools.js.map +1 -0
- package/dist/mcp/index.d.ts +16 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +15 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server-from-agent.d.ts +24 -0
- package/dist/mcp/server-from-agent.d.ts.map +1 -0
- package/dist/mcp/server-from-agent.js +113 -0
- package/dist/mcp/server-from-agent.js.map +1 -0
- package/dist/mcp/types.d.ts +64 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +6 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/memory-embedding/index.d.ts +121 -0
- package/dist/memory-embedding/index.d.ts.map +1 -0
- package/dist/memory-embedding/index.js +229 -0
- package/dist/memory-embedding/index.js.map +1 -0
- package/dist/memory-extract.d.ts +60 -0
- package/dist/memory-extract.d.ts.map +1 -0
- package/dist/memory-extract.js +163 -0
- package/dist/memory-extract.js.map +1 -0
- package/dist/memory-inject.d.ts +39 -0
- package/dist/memory-inject.d.ts.map +1 -0
- package/dist/memory-inject.js +135 -0
- package/dist/memory-inject.js.map +1 -0
- package/dist/memory-orm/index.d.ts +118 -0
- package/dist/memory-orm/index.d.ts.map +1 -0
- package/dist/memory-orm/index.js +187 -0
- package/dist/memory-orm/index.js.map +1 -0
- package/dist/memory.d.ts +55 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +132 -0
- package/dist/memory.js.map +1 -0
- package/dist/observers.d.ts +22 -0
- package/dist/observers.d.ts.map +1 -1
- package/dist/observers.js.map +1 -1
- package/dist/provider-tools.d.ts +15 -1
- package/dist/provider-tools.d.ts.map +1 -1
- package/dist/provider-tools.js +21 -1
- package/dist/provider-tools.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +61 -6
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/elevenlabs.d.ts +98 -0
- package/dist/providers/elevenlabs.d.ts.map +1 -0
- package/dist/providers/elevenlabs.js +229 -0
- package/dist/providers/elevenlabs.js.map +1 -0
- package/dist/providers/google.d.ts +83 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +491 -8
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/openai.d.ts +3 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +209 -5
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/voyage.d.ts +91 -0
- package/dist/providers/voyage.d.ts.map +1 -0
- package/dist/providers/voyage.js +166 -0
- package/dist/providers/voyage.js.map +1 -0
- package/dist/queue-job.d.ts +69 -4
- package/dist/queue-job.d.ts.map +1 -1
- package/dist/queue-job.js +114 -11
- package/dist/queue-job.js.map +1 -1
- package/dist/registry.d.ts +3 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +10 -0
- package/dist/registry.js.map +1 -1
- package/dist/server/provider.d.ts.map +1 -1
- package/dist/server/provider.js +23 -1
- package/dist/server/provider.js.map +1 -1
- package/dist/similarity-search.d.ts +163 -0
- package/dist/similarity-search.d.ts.map +1 -0
- package/dist/similarity-search.js +147 -0
- package/dist/similarity-search.js.map +1 -0
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +13 -4
- package/dist/tool.js.map +1 -1
- package/dist/types.d.ts +246 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vector-stores/index.d.ts +96 -0
- package/dist/vector-stores/index.d.ts.map +1 -0
- package/dist/vector-stores/index.js +153 -0
- package/dist/vector-stores/index.js.map +1 -0
- package/package.json +41 -3
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pnpm rudder ai:eval` — discover `evals/**\/*.eval.ts` suites,
|
|
3
|
+
* run each, and report. Console reporter by default; `--json` emits
|
|
4
|
+
* a machine-readable envelope to stdout for CI.
|
|
5
|
+
*
|
|
6
|
+
* Registered from the CLI loader (`packages/cli/src/index.ts`)
|
|
7
|
+
* — the AiProvider doesn't own this so it surfaces even when the
|
|
8
|
+
* user app fails to boot, matching the `command:list --json`
|
|
9
|
+
* graceful-degradation pattern from #349.
|
|
10
|
+
*/
|
|
11
|
+
import { readdir } from 'node:fs/promises';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { pathToFileURL } from 'node:url';
|
|
14
|
+
import { runSuite, reportConsole, evalSuite, stepsFromResponse } from '../eval/index.js';
|
|
15
|
+
import { reportJson } from '../eval/json-reporter.js';
|
|
16
|
+
import { reportHtml } from '../eval/html-reporter.js';
|
|
17
|
+
import { defaultFixturesDir, readFixture, writeFixture } from '../eval/fixtures.js';
|
|
18
|
+
import { AiFake } from '../fake.js';
|
|
19
|
+
/** Register the `ai:eval` command on the rudder runner. */
|
|
20
|
+
export function registerAiEvalCommand(rudder) {
|
|
21
|
+
rudder.command('ai:eval', async (rawArgs) => {
|
|
22
|
+
const code = await runEvalCli(parseArgs(rawArgs));
|
|
23
|
+
if (code !== 0)
|
|
24
|
+
process.exit(code);
|
|
25
|
+
}).description('Run eval suites — pnpm rudder ai:eval [name-pattern] [--bail] [--json] [--record|--replay] [--html <path>]');
|
|
26
|
+
}
|
|
27
|
+
// ─── Args parser ─────────────────────────────────────────
|
|
28
|
+
const VALUE_FLAGS = new Set(['--html']);
|
|
29
|
+
/**
|
|
30
|
+
* Parse the rest-of-line. Recognizes:
|
|
31
|
+
* - boolean flags: `--bail`, `--json`, `--record`, `--replay`
|
|
32
|
+
* - value flags : `--html <path>` or `--html=<path>`
|
|
33
|
+
* - one positional name filter (anything not consumed above)
|
|
34
|
+
*/
|
|
35
|
+
export function parseArgs(args) {
|
|
36
|
+
const positional = [];
|
|
37
|
+
const opts = { bail: false, json: false };
|
|
38
|
+
for (let i = 0; i < args.length; i++) {
|
|
39
|
+
const a = args[i];
|
|
40
|
+
if (!a.startsWith('--')) {
|
|
41
|
+
positional.push(a);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
// `--flag=value` form
|
|
45
|
+
const eq = a.indexOf('=');
|
|
46
|
+
const name = eq >= 0 ? a.slice(0, eq) : a;
|
|
47
|
+
const inline = eq >= 0 ? a.slice(eq + 1) : undefined;
|
|
48
|
+
if (name === '--bail') {
|
|
49
|
+
opts.bail = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (name === '--json') {
|
|
53
|
+
opts.json = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (name === '--record') {
|
|
57
|
+
opts.record = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (name === '--replay') {
|
|
61
|
+
opts.replay = true;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (VALUE_FLAGS.has(name)) {
|
|
65
|
+
const value = inline ?? args[i + 1];
|
|
66
|
+
if (!inline)
|
|
67
|
+
i++; // consumed the next arg
|
|
68
|
+
if (!value)
|
|
69
|
+
throw new Error(`[RudderJS AI] ${name} requires a value`);
|
|
70
|
+
if (name === '--html')
|
|
71
|
+
opts.html = value;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// unknown flag — surface as positional so the user sees the typo
|
|
75
|
+
positional.push(a);
|
|
76
|
+
}
|
|
77
|
+
if (positional[0])
|
|
78
|
+
opts.filter = positional[0];
|
|
79
|
+
return opts;
|
|
80
|
+
}
|
|
81
|
+
// ─── Runner ──────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Execute the CLI flow. Returns the process exit code (0 = all pass,
|
|
84
|
+
* 1 = at least one suite had a failure or no suites discovered).
|
|
85
|
+
*
|
|
86
|
+
* The handler is `process.exit`-free so tests can drive it directly.
|
|
87
|
+
*/
|
|
88
|
+
export async function runEvalCli(opts, deps = {}) {
|
|
89
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
90
|
+
const stdout = deps.stdout ?? process.stdout;
|
|
91
|
+
const stderr = deps.stderr ?? process.stderr;
|
|
92
|
+
if (opts.record && opts.replay) {
|
|
93
|
+
stderr.write('[ai:eval] --record and --replay are mutually exclusive\n');
|
|
94
|
+
return 1;
|
|
95
|
+
}
|
|
96
|
+
const pattern = await Promise.resolve((deps.configPattern ?? loadConfigPattern)()) ?? 'evals/**/*.eval.ts';
|
|
97
|
+
const discover = deps.discover ?? discoverSuiteFiles;
|
|
98
|
+
const files = await discover(cwd, pattern);
|
|
99
|
+
if (files.length === 0) {
|
|
100
|
+
stderr.write(`[ai:eval] no suites found matching ${pattern}\n`);
|
|
101
|
+
return opts.json ? emitJson(stdout, []) : 1;
|
|
102
|
+
}
|
|
103
|
+
const loader = deps.loadSuite ?? defaultSuiteLoader;
|
|
104
|
+
const fixturesDir = deps.fixturesDir ?? defaultFixturesDir(cwd);
|
|
105
|
+
const reports = [];
|
|
106
|
+
const fullReports = [];
|
|
107
|
+
let exitCode = 0;
|
|
108
|
+
// `--replay` swaps the global runtime once, restored when we're done.
|
|
109
|
+
// The per-case fixture is set on the AiFake instance inside the
|
|
110
|
+
// wrapped agent factory just before each case's `agent.prompt()`.
|
|
111
|
+
let fake = null;
|
|
112
|
+
if (opts.replay)
|
|
113
|
+
fake = AiFake.fake();
|
|
114
|
+
try {
|
|
115
|
+
for (const file of files) {
|
|
116
|
+
let suite;
|
|
117
|
+
try {
|
|
118
|
+
suite = await loader(file);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
stderr.write(`[ai:eval] failed to load ${path.relative(cwd, file)}: ${formatError(err)}\n`);
|
|
122
|
+
exitCode = 1;
|
|
123
|
+
if (opts.bail)
|
|
124
|
+
break;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (!suite) {
|
|
128
|
+
stderr.write(`[ai:eval] ${path.relative(cwd, file)} has no default eval suite — skipping\n`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (opts.filter && !suite.name.toLowerCase().includes(opts.filter.toLowerCase()))
|
|
132
|
+
continue;
|
|
133
|
+
const decorated = await decorateForMode(suite, opts, { fixturesDir, stderr, fake });
|
|
134
|
+
const report = await runSuite(decorated);
|
|
135
|
+
fullReports.push(report);
|
|
136
|
+
if (opts.json) {
|
|
137
|
+
reports.push(reportJson(report));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
reportConsole(report, { log: (s) => stdout.write(`${s}\n`) });
|
|
141
|
+
}
|
|
142
|
+
if (report.failed > 0) {
|
|
143
|
+
exitCode = 1;
|
|
144
|
+
if (opts.bail)
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
if (fake)
|
|
151
|
+
fake.restore();
|
|
152
|
+
}
|
|
153
|
+
if (opts.json)
|
|
154
|
+
emitJson(stdout, reports);
|
|
155
|
+
if (opts.html)
|
|
156
|
+
await writeHtmlReport(opts.html, fullReports, cwd, stderr);
|
|
157
|
+
return exitCode;
|
|
158
|
+
}
|
|
159
|
+
async function writeHtmlReport(htmlPath, reports, cwd, stderr) {
|
|
160
|
+
const { writeFile, mkdir } = await import('node:fs/promises');
|
|
161
|
+
const abs = path.isAbsolute(htmlPath) ? htmlPath : path.resolve(cwd, htmlPath);
|
|
162
|
+
try {
|
|
163
|
+
await mkdir(path.dirname(abs), { recursive: true });
|
|
164
|
+
await writeFile(abs, reportHtml(reports));
|
|
165
|
+
stderr.write(`[ai:eval] wrote HTML report → ${path.relative(cwd, abs)}\n`);
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
stderr.write(`[ai:eval] failed to write HTML report ${abs}: ${formatError(err)}\n`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function emitJson(stdout, suites) {
|
|
172
|
+
stdout.write(`${JSON.stringify({ suites }, null, 2)}\n`);
|
|
173
|
+
return 0;
|
|
174
|
+
}
|
|
175
|
+
function formatError(err) {
|
|
176
|
+
return err instanceof Error ? err.message : String(err);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Wrap a suite so each case captures the response (`--record`) or
|
|
180
|
+
* pre-loads the fake's sequence (`--replay`) before running. A
|
|
181
|
+
* normal run returns the suite untouched.
|
|
182
|
+
*
|
|
183
|
+
* Implemented as a per-case `agent` / `assert` decoration so the
|
|
184
|
+
* runner stays unchanged — `runSuite` doesn't need to know about
|
|
185
|
+
* the fixture format. The original `agent`/`assert` for each case
|
|
186
|
+
* are still called; we just slip work in around them.
|
|
187
|
+
*
|
|
188
|
+
* For replay, fixtures load up-front (sync factory contract) so the
|
|
189
|
+
* AiFake is primed before each `agent.prompt()` runs.
|
|
190
|
+
*/
|
|
191
|
+
async function decorateForMode(suite, opts, ctx) {
|
|
192
|
+
if (!opts.record && !opts.replay)
|
|
193
|
+
return suite;
|
|
194
|
+
// Pre-load every fixture for replay so the per-case factory can
|
|
195
|
+
// call `respondWithSequence` synchronously.
|
|
196
|
+
const replaySteps = new Map();
|
|
197
|
+
if (opts.replay) {
|
|
198
|
+
for (let i = 0; i < suite.spec.cases.length; i++) {
|
|
199
|
+
const c = suite.spec.cases[i];
|
|
200
|
+
const caseName = c.name ?? `case-${i}`;
|
|
201
|
+
try {
|
|
202
|
+
const fixture = await readFixture(ctx.fixturesDir, suite.name, caseName);
|
|
203
|
+
if (fixture)
|
|
204
|
+
replaySteps.set(caseName, fixture.steps);
|
|
205
|
+
else
|
|
206
|
+
ctx.stderr.write(`[ai:eval] no fixture for ${suite.name}/${caseName} — running against live provider\n`);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
ctx.stderr.write(`[ai:eval] fixture load error for ${suite.name}/${caseName}: ${formatError(err)}\n`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const wrapped = suite.spec.cases.map((c, i) => {
|
|
214
|
+
const caseName = c.name ?? `case-${i}`;
|
|
215
|
+
const baseFactory = c.agent ?? suite.spec.agent;
|
|
216
|
+
const baseAssert = c.assert;
|
|
217
|
+
const factory = opts.replay
|
|
218
|
+
? wrapReplayFactory(baseFactory, replaySteps.get(caseName), ctx.fake)
|
|
219
|
+
: baseFactory;
|
|
220
|
+
const assert = opts.record
|
|
221
|
+
? wrapRecordAssert(baseAssert, suite.name, caseName, c.input, ctx)
|
|
222
|
+
: baseAssert;
|
|
223
|
+
const out = {
|
|
224
|
+
input: c.input,
|
|
225
|
+
assert,
|
|
226
|
+
agent: factory,
|
|
227
|
+
};
|
|
228
|
+
if (c.name)
|
|
229
|
+
out.name = c.name;
|
|
230
|
+
if (c.timeout !== undefined)
|
|
231
|
+
out.timeout = c.timeout;
|
|
232
|
+
if (c.skip !== undefined)
|
|
233
|
+
out.skip = c.skip;
|
|
234
|
+
return out;
|
|
235
|
+
});
|
|
236
|
+
const newSpec = {
|
|
237
|
+
agent: suite.spec.agent,
|
|
238
|
+
cases: wrapped,
|
|
239
|
+
};
|
|
240
|
+
if (suite.spec.timeout !== undefined)
|
|
241
|
+
newSpec.timeout = suite.spec.timeout;
|
|
242
|
+
return evalSuite(suite.name, newSpec);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Replay path: before each case runs, prime the shared `AiFake`
|
|
246
|
+
* with the case's recorded steps. When the fixture is missing the
|
|
247
|
+
* factory still returns the agent — it'll hit whatever the AiFake
|
|
248
|
+
* is currently scripted to return (typically falling back to the
|
|
249
|
+
* default ambient response, which surfaces as an obvious diff in
|
|
250
|
+
* the case's assertion).
|
|
251
|
+
*/
|
|
252
|
+
function wrapReplayFactory(base, steps, fake) {
|
|
253
|
+
return () => {
|
|
254
|
+
if (fake && steps)
|
|
255
|
+
fake.respondWithSequence(steps);
|
|
256
|
+
return base();
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Record path: after each case's assertion runs, capture the
|
|
261
|
+
* agent response's assistant turns to the fixture file. Wrapping
|
|
262
|
+
* the assert is the cleanest hook — the runner already passes
|
|
263
|
+
* `response` into it, and the wrapped fn still returns the
|
|
264
|
+
* original assertion's result.
|
|
265
|
+
*/
|
|
266
|
+
function wrapRecordAssert(base, suite, caseName, input, ctx) {
|
|
267
|
+
return async (response, mctx) => {
|
|
268
|
+
try {
|
|
269
|
+
const file = await writeFixture(ctx.fixturesDir, suite, caseName, {
|
|
270
|
+
input,
|
|
271
|
+
steps: stepsFromResponse(response),
|
|
272
|
+
});
|
|
273
|
+
ctx.stderr.write(`[ai:eval] recorded ${path.relative(process.cwd(), file)}\n`);
|
|
274
|
+
}
|
|
275
|
+
catch (err) {
|
|
276
|
+
ctx.stderr.write(`[ai:eval] failed to record ${suite}/${caseName}: ${formatError(err)}\n`);
|
|
277
|
+
}
|
|
278
|
+
return base(response, mctx);
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// ─── File discovery ──────────────────────────────────────
|
|
282
|
+
/**
|
|
283
|
+
* Recursive walk constrained to a `<dir>/**\/*<suffix>` shape.
|
|
284
|
+
* Returns absolute paths sorted lexicographically for stable test
|
|
285
|
+
* output and predictable `--bail` ordering.
|
|
286
|
+
*/
|
|
287
|
+
export async function discoverSuiteFiles(cwd, pattern) {
|
|
288
|
+
const { root, suffix } = parsePattern(pattern);
|
|
289
|
+
const absRoot = path.resolve(cwd, root);
|
|
290
|
+
const out = [];
|
|
291
|
+
await walk(absRoot, suffix, out);
|
|
292
|
+
return out.sort();
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Tiny pattern parser — supports `<dir>/**\/*<suffix>` and bare
|
|
296
|
+
* `*<suffix>` (current directory). Anything more elaborate is
|
|
297
|
+
* deferred to userland (run a custom script that imports `runSuite`).
|
|
298
|
+
*
|
|
299
|
+
* Examples:
|
|
300
|
+
* `evals/**\/*.eval.ts` → root=`evals`, suffix=`.eval.ts`
|
|
301
|
+
* `tests/agents/**\/*.ts` → root=`tests/agents`, suffix=`.ts`
|
|
302
|
+
* `*.eval.ts` → root=`.`, suffix=`.eval.ts`
|
|
303
|
+
*/
|
|
304
|
+
function parsePattern(pattern) {
|
|
305
|
+
const doubleStar = pattern.indexOf('**');
|
|
306
|
+
let prefix;
|
|
307
|
+
let postfix;
|
|
308
|
+
if (doubleStar >= 0) {
|
|
309
|
+
prefix = pattern.slice(0, doubleStar).replace(/\/$/, '');
|
|
310
|
+
postfix = pattern.slice(doubleStar + 2).replace(/^\//, '');
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
const lastSlash = pattern.lastIndexOf('/');
|
|
314
|
+
prefix = lastSlash >= 0 ? pattern.slice(0, lastSlash) : '';
|
|
315
|
+
postfix = lastSlash >= 0 ? pattern.slice(lastSlash + 1) : pattern;
|
|
316
|
+
}
|
|
317
|
+
if (!postfix.startsWith('*')) {
|
|
318
|
+
throw new Error(`[RudderJS AI] Unsupported eval pattern "${pattern}". ` +
|
|
319
|
+
`Expected <dir>/**/*<suffix> or *<suffix>.`);
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
root: prefix || '.',
|
|
323
|
+
suffix: postfix.slice(1),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
async function walk(dir, suffix, out) {
|
|
327
|
+
let entries;
|
|
328
|
+
try {
|
|
329
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
330
|
+
}
|
|
331
|
+
catch (err) {
|
|
332
|
+
if (err.code === 'ENOENT')
|
|
333
|
+
return;
|
|
334
|
+
throw err;
|
|
335
|
+
}
|
|
336
|
+
for (const entry of entries) {
|
|
337
|
+
const p = path.join(dir, entry.name);
|
|
338
|
+
if (entry.isDirectory()) {
|
|
339
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.'))
|
|
340
|
+
continue;
|
|
341
|
+
await walk(p, suffix, out);
|
|
342
|
+
}
|
|
343
|
+
else if (entry.isFile() && entry.name.endsWith(suffix)) {
|
|
344
|
+
out.push(p);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// ─── Suite loader ────────────────────────────────────────
|
|
349
|
+
async function defaultSuiteLoader(file) {
|
|
350
|
+
const mod = await import(pathToFileURL(file).href);
|
|
351
|
+
const candidate = (mod['default'] ?? mod['suite']);
|
|
352
|
+
if (!candidate || typeof candidate.name !== 'string' || !candidate.spec)
|
|
353
|
+
return null;
|
|
354
|
+
return candidate;
|
|
355
|
+
}
|
|
356
|
+
// ─── Config lookup ───────────────────────────────────────
|
|
357
|
+
/**
|
|
358
|
+
* Read `config('ai').eval.pattern` from the booted app. Returns
|
|
359
|
+
* `null` (default pattern) when `@rudderjs/core` isn't loadable
|
|
360
|
+
* or the app didn't boot — the CLI must still work in
|
|
361
|
+
* introspective mode (#349).
|
|
362
|
+
*/
|
|
363
|
+
async function loadConfigPattern() {
|
|
364
|
+
try {
|
|
365
|
+
// Dynamic import so the static graph doesn't pin `@rudderjs/core`
|
|
366
|
+
// (optional peer). Falls back to default when core isn't loadable
|
|
367
|
+
// or the app didn't boot.
|
|
368
|
+
const core = await import('@rudderjs/core');
|
|
369
|
+
if (typeof core.config !== 'function')
|
|
370
|
+
return null;
|
|
371
|
+
const cfg = core.config('ai');
|
|
372
|
+
return cfg?.eval?.pattern ?? null;
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=ai-eval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-eval.js","sourceRoot":"","sources":["../../src/commands/ai-eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action vocabulary for `@rudderjs/ai/computer-use` (#A7 Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Anthropic's `computer_20250124` tool schema verbatim — see
|
|
5
|
+
* https://docs.anthropic.com/en/docs/build-with-claude/tool-use/computer-use-tool
|
|
6
|
+
*
|
|
7
|
+
* The model emits a {@link ComputerAction} as the JSON argument of a
|
|
8
|
+
* `computer` tool call; the executor (see `./playwright.ts`) dispatches
|
|
9
|
+
* the action against a Playwright `Page` and returns a
|
|
10
|
+
* {@link ComputerActionResult} the agent loop forwards back to the model.
|
|
11
|
+
*
|
|
12
|
+
* # Why mirror Anthropic exactly?
|
|
13
|
+
*
|
|
14
|
+
* Computer-use is `Anthropic-only` in v1 (see plan
|
|
15
|
+
* `docs/plans/2026-05-10-ai-computer-use.md`). Claude is fine-tuned on
|
|
16
|
+
* this exact action vocabulary; reusing the schema means:
|
|
17
|
+
*
|
|
18
|
+
* - Phase 2's `computerUseTool({ page })` factory maps cleanly to
|
|
19
|
+
* Anthropic's native `{ type: 'computer_20250124', name: 'computer',
|
|
20
|
+
* display_width_px, display_height_px }` block — zero translation
|
|
21
|
+
* layer.
|
|
22
|
+
* - When OpenAI or Google's native computer-use APIs mature enough to
|
|
23
|
+
* route through, only the provider adapter changes; the schema and
|
|
24
|
+
* executor stay put.
|
|
25
|
+
*
|
|
26
|
+
* # Coordinates
|
|
27
|
+
*
|
|
28
|
+
* `[x, y]` in viewport pixels. Origin is top-left. Anthropic suggests a
|
|
29
|
+
* 1280×800 viewport for Claude's training distribution; the executor
|
|
30
|
+
* does not validate bounds — out-of-viewport coordinates pass through
|
|
31
|
+
* to Playwright (which clips the cursor to viewport edges).
|
|
32
|
+
*
|
|
33
|
+
* # Modifier text on click / scroll actions
|
|
34
|
+
*
|
|
35
|
+
* Anthropic encodes "hold these modifier keys while clicking" as a `+`
|
|
36
|
+
* separated string on the `text` field — e.g.
|
|
37
|
+
* `{ action: 'left_click', coordinate: [400, 200], text: 'shift+ctrl' }`.
|
|
38
|
+
* The executor translates `cmd`/`super`/`meta` → `Meta`,
|
|
39
|
+
* `ctrl`/`control` → `Control`, etc. before passing to Playwright.
|
|
40
|
+
*/
|
|
41
|
+
/** Viewport pixel coordinate, top-left origin. `[x, y]`. */
|
|
42
|
+
export type Coordinate = readonly [number, number];
|
|
43
|
+
/**
|
|
44
|
+
* Discriminated union of every action Anthropic's `computer_20250124`
|
|
45
|
+
* tool can emit. The executor dispatches on `action`; downstream code
|
|
46
|
+
* should treat unknown variants as a forward-compatibility hazard
|
|
47
|
+
* rather than a bug — Anthropic versions the schema with dated suffixes
|
|
48
|
+
* (e.g. a future `computer_20260101` may add new variants we'll route
|
|
49
|
+
* here once supported).
|
|
50
|
+
*/
|
|
51
|
+
export type ComputerAction = {
|
|
52
|
+
action: 'screenshot';
|
|
53
|
+
} | {
|
|
54
|
+
action: 'cursor_position';
|
|
55
|
+
}
|
|
56
|
+
/** Pause for `duration` seconds. Useful between an action that triggers async UI and the screenshot that should observe the result. */
|
|
57
|
+
| {
|
|
58
|
+
action: 'wait';
|
|
59
|
+
duration: number;
|
|
60
|
+
} | {
|
|
61
|
+
action: 'mouse_move';
|
|
62
|
+
coordinate: Coordinate;
|
|
63
|
+
}
|
|
64
|
+
/** Single left-button click. `text` holds optional modifier keys, `+`-separated (e.g. `'shift+ctrl'`). */
|
|
65
|
+
| {
|
|
66
|
+
action: 'left_click';
|
|
67
|
+
coordinate: Coordinate;
|
|
68
|
+
text?: string;
|
|
69
|
+
} | {
|
|
70
|
+
action: 'right_click';
|
|
71
|
+
coordinate: Coordinate;
|
|
72
|
+
text?: string;
|
|
73
|
+
} | {
|
|
74
|
+
action: 'middle_click';
|
|
75
|
+
coordinate: Coordinate;
|
|
76
|
+
text?: string;
|
|
77
|
+
} | {
|
|
78
|
+
action: 'double_click';
|
|
79
|
+
coordinate: Coordinate;
|
|
80
|
+
text?: string;
|
|
81
|
+
} | {
|
|
82
|
+
action: 'triple_click';
|
|
83
|
+
coordinate: Coordinate;
|
|
84
|
+
text?: string;
|
|
85
|
+
}
|
|
86
|
+
/** Press the left mouse button. Pair with `left_mouse_up` to drag. `coordinate` (optional) moves first. */
|
|
87
|
+
| {
|
|
88
|
+
action: 'left_mouse_down';
|
|
89
|
+
coordinate?: Coordinate;
|
|
90
|
+
}
|
|
91
|
+
/** Release the left mouse button. `coordinate` (optional) moves first. */
|
|
92
|
+
| {
|
|
93
|
+
action: 'left_mouse_up';
|
|
94
|
+
coordinate?: Coordinate;
|
|
95
|
+
}
|
|
96
|
+
/** Type literal text. No modifier handling — use `key` for shortcuts. */
|
|
97
|
+
| {
|
|
98
|
+
action: 'type';
|
|
99
|
+
text: string;
|
|
100
|
+
}
|
|
101
|
+
/** Press a key chord. `text` is `+`-separated (e.g. `'ctrl+a'`, `'Return'`, `'cmd+shift+t'`). */
|
|
102
|
+
| {
|
|
103
|
+
action: 'key';
|
|
104
|
+
text: string;
|
|
105
|
+
}
|
|
106
|
+
/** Hold a single key for `duration` seconds. `text` is one key, not a chord. */
|
|
107
|
+
| {
|
|
108
|
+
action: 'hold_key';
|
|
109
|
+
text: string;
|
|
110
|
+
duration: number;
|
|
111
|
+
}
|
|
112
|
+
/** Scroll at `coordinate`. `scroll_amount` is in mouse-wheel "clicks" (~100px each). `text` holds optional modifiers. */
|
|
113
|
+
| {
|
|
114
|
+
action: 'scroll';
|
|
115
|
+
coordinate: Coordinate;
|
|
116
|
+
scroll_direction: 'up' | 'down' | 'left' | 'right';
|
|
117
|
+
scroll_amount: number;
|
|
118
|
+
text?: string;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Tool-result content the agent loop hands back to the model after each
|
|
122
|
+
* action. Shape matches Anthropic's tool-result block content vocabulary:
|
|
123
|
+
*
|
|
124
|
+
* - `image` carries a PNG screenshot. The agent loop wraps this as
|
|
125
|
+
* `{ type: 'image', source: { type: 'base64', media_type, data } }`
|
|
126
|
+
* when serializing to the API.
|
|
127
|
+
* - `text` carries a one-line confirmation (`"left-clicked at (400, 200)"`)
|
|
128
|
+
* or the response of an introspective action (`cursor_position`).
|
|
129
|
+
* - `error` carries the failure text from a Playwright throw. Caller
|
|
130
|
+
* typically maps this onto `{ is_error: true, content: [...] }` in
|
|
131
|
+
* the tool-result block so the model knows the action failed and can
|
|
132
|
+
* retry / recover.
|
|
133
|
+
*/
|
|
134
|
+
export type ComputerActionResult = {
|
|
135
|
+
type: 'image';
|
|
136
|
+
media_type: 'image/png';
|
|
137
|
+
data: Uint8Array;
|
|
138
|
+
} | {
|
|
139
|
+
type: 'text';
|
|
140
|
+
text: string;
|
|
141
|
+
} | {
|
|
142
|
+
type: 'error';
|
|
143
|
+
text: string;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Per-run state the executor mutates. Tracks the last known cursor
|
|
147
|
+
* position so the `cursor_position` action can answer it (Playwright
|
|
148
|
+
* has no native API to read the synthesized mouse position).
|
|
149
|
+
*
|
|
150
|
+
* Create one with {@link makeExecutorState} per agent run; pass the
|
|
151
|
+
* same instance to every {@link executeComputerAction} call.
|
|
152
|
+
*/
|
|
153
|
+
export interface ComputerExecutorState {
|
|
154
|
+
/** Last known cursor position in viewport pixels. Updated on move/click/drag. */
|
|
155
|
+
cursor: {
|
|
156
|
+
x: number;
|
|
157
|
+
y: number;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Construct a fresh {@link ComputerExecutorState}. Optional `initial`
|
|
162
|
+
* seeds the cursor (defaults to `(0, 0)`).
|
|
163
|
+
*/
|
|
164
|
+
export declare function makeExecutorState(initial?: {
|
|
165
|
+
x: number;
|
|
166
|
+
y: number;
|
|
167
|
+
}): ComputerExecutorState;
|
|
168
|
+
/**
|
|
169
|
+
* Structural subset of Playwright's `Page` the executor calls. Defining
|
|
170
|
+
* this here means {@link executeComputerAction} types correctly without
|
|
171
|
+
* `@rudderjs/ai` taking a hard dependency on the `playwright` package
|
|
172
|
+
* (which carries a 300MB+ Chromium download). Apps install Playwright
|
|
173
|
+
* themselves and pass `page` in.
|
|
174
|
+
*
|
|
175
|
+
* Any object with this shape works — real Playwright `Page`,
|
|
176
|
+
* `puppeteer-core`'s `Page` (close enough), or a hand-rolled mock for
|
|
177
|
+
* tests. Phase 2's `computerUseTool({ page })` accepts the same type.
|
|
178
|
+
*/
|
|
179
|
+
export interface PageLike {
|
|
180
|
+
mouse: PageMouseLike;
|
|
181
|
+
keyboard: PageKeyboardLike;
|
|
182
|
+
/** Take a screenshot of the current viewport. Returns PNG bytes by default. */
|
|
183
|
+
screenshot(options?: {
|
|
184
|
+
type?: 'png' | 'jpeg';
|
|
185
|
+
}): Promise<Uint8Array>;
|
|
186
|
+
}
|
|
187
|
+
export interface PageMouseLike {
|
|
188
|
+
move(x: number, y: number, options?: {
|
|
189
|
+
steps?: number;
|
|
190
|
+
}): Promise<void>;
|
|
191
|
+
click(x: number, y: number, options?: {
|
|
192
|
+
button?: 'left' | 'right' | 'middle';
|
|
193
|
+
clickCount?: number;
|
|
194
|
+
delay?: number;
|
|
195
|
+
}): Promise<void>;
|
|
196
|
+
down(options?: {
|
|
197
|
+
button?: 'left' | 'right' | 'middle';
|
|
198
|
+
}): Promise<void>;
|
|
199
|
+
up(options?: {
|
|
200
|
+
button?: 'left' | 'right' | 'middle';
|
|
201
|
+
}): Promise<void>;
|
|
202
|
+
wheel(deltaX: number, deltaY: number): Promise<void>;
|
|
203
|
+
}
|
|
204
|
+
export interface PageKeyboardLike {
|
|
205
|
+
type(text: string, options?: {
|
|
206
|
+
delay?: number;
|
|
207
|
+
}): Promise<void>;
|
|
208
|
+
press(key: string, options?: {
|
|
209
|
+
delay?: number;
|
|
210
|
+
}): Promise<void>;
|
|
211
|
+
down(key: string): Promise<void>;
|
|
212
|
+
up(key: string): Promise<void>;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/computer-use/actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action vocabulary for `@rudderjs/ai/computer-use` (#A7 Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Anthropic's `computer_20250124` tool schema verbatim — see
|
|
5
|
+
* https://docs.anthropic.com/en/docs/build-with-claude/tool-use/computer-use-tool
|
|
6
|
+
*
|
|
7
|
+
* The model emits a {@link ComputerAction} as the JSON argument of a
|
|
8
|
+
* `computer` tool call; the executor (see `./playwright.ts`) dispatches
|
|
9
|
+
* the action against a Playwright `Page` and returns a
|
|
10
|
+
* {@link ComputerActionResult} the agent loop forwards back to the model.
|
|
11
|
+
*
|
|
12
|
+
* # Why mirror Anthropic exactly?
|
|
13
|
+
*
|
|
14
|
+
* Computer-use is `Anthropic-only` in v1 (see plan
|
|
15
|
+
* `docs/plans/2026-05-10-ai-computer-use.md`). Claude is fine-tuned on
|
|
16
|
+
* this exact action vocabulary; reusing the schema means:
|
|
17
|
+
*
|
|
18
|
+
* - Phase 2's `computerUseTool({ page })` factory maps cleanly to
|
|
19
|
+
* Anthropic's native `{ type: 'computer_20250124', name: 'computer',
|
|
20
|
+
* display_width_px, display_height_px }` block — zero translation
|
|
21
|
+
* layer.
|
|
22
|
+
* - When OpenAI or Google's native computer-use APIs mature enough to
|
|
23
|
+
* route through, only the provider adapter changes; the schema and
|
|
24
|
+
* executor stay put.
|
|
25
|
+
*
|
|
26
|
+
* # Coordinates
|
|
27
|
+
*
|
|
28
|
+
* `[x, y]` in viewport pixels. Origin is top-left. Anthropic suggests a
|
|
29
|
+
* 1280×800 viewport for Claude's training distribution; the executor
|
|
30
|
+
* does not validate bounds — out-of-viewport coordinates pass through
|
|
31
|
+
* to Playwright (which clips the cursor to viewport edges).
|
|
32
|
+
*
|
|
33
|
+
* # Modifier text on click / scroll actions
|
|
34
|
+
*
|
|
35
|
+
* Anthropic encodes "hold these modifier keys while clicking" as a `+`
|
|
36
|
+
* separated string on the `text` field — e.g.
|
|
37
|
+
* `{ action: 'left_click', coordinate: [400, 200], text: 'shift+ctrl' }`.
|
|
38
|
+
* The executor translates `cmd`/`super`/`meta` → `Meta`,
|
|
39
|
+
* `ctrl`/`control` → `Control`, etc. before passing to Playwright.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Construct a fresh {@link ComputerExecutorState}. Optional `initial`
|
|
43
|
+
* seeds the cursor (defaults to `(0, 0)`).
|
|
44
|
+
*/
|
|
45
|
+
export function makeExecutorState(initial) {
|
|
46
|
+
return { cursor: { x: initial?.x ?? 0, y: initial?.y ?? 0 } };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/computer-use/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAqFH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAkC;IAClE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAA;AAC/D,CAAC"}
|