Skip to content

feat(test): evals - #1058

Merged
harijoe merged 3 commits into
v2from
julien/sky-546-set-up-the-skybridgeevals-package-beta
Aug 28, 2026
Merged

feat(test): evals#1058
harijoe merged 3 commits into
v2from
julien/sky-546-set-up-the-skybridgeevals-package-beta

Conversation

@harijoe

@harijoe harijoe commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds @skybridge/test: eval runner answering whether a prompt reaches the right tool with the right arguments.
  • Enabled via skybridge({ evals }); scenarios use vitest's own it/expect plus start<AppType>().
  • The model is a provider/model-id string, and only the provider named gets imported.
  • Anthropic, OpenAI, Mistral and Google are optional peers; each reads its own API key variable.
  • For anything those prefixes cannot reach, defineEvalModel() registers a model from a setup file.
  • Extracts core's Vite plugin to @skybridge/vite-plugin.
  • Breaking: skybridge/vite is removed; import skybridge from @skybridge/vite-plugin instead.
  • server.run() now reports its bound port over IPC, letting the runner use an ephemeral port with no bind race.
  • Repeated runs with an acceptance threshold are deferred to SKY-551.

Implements SKY-546. API validated on the POC (#1052) and the design review thread.

@mintlify

mintlify Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
skybridge-staging 🟢 Ready View Preview Aug 20, 2026, 1:58 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds the Skybridge eval runner and extracts the Vite integration into @skybridge/vite-plugin.

  • Adds model-driven MCP evaluation sessions and Vitest chat matchers.
  • Starts eval servers on ephemeral ports using IPC readiness reporting.
  • Migrates projects, examples, templates, and publishing workflows to the extracted Vite plugin.

Confidence Score: 5/5

The PR appears safe to merge because the previously reported matcher failure is fixed and no blocking failure remains.

No blocking failure remains.

Reviews (19): Last reviewed commit: "feat(test): assert on what the assistant..." | Re-trigger Greptile

Comment thread packages/test/src/matchers.ts Outdated
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 7466734 to 7aada9d Compare August 20, 2026 15:02
@harijoe

harijoe commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@greptile-apps

@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch 4 times, most recently from 34007b8 to 50c10e1 Compare August 21, 2026 13:30
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 50c10e1 to df0cfdd Compare August 21, 2026 14:19
@harijoe harijoe changed the title feat(test): eval runner as @skybridge/test, extract @skybridge/vite-plugin feat(test): evals Aug 21, 2026
Comment thread packages/vite-plugin/src/plugin.ts Outdated
Comment on lines +104 to +107
const evals = options?.evals;
if (evals !== undefined) {
plugins.push(loadEvalsPlugin(evals));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to have polymorphic plugins and using skybridge/vite-plugin should "always" package both views folder for build and prepare server for unit test.
Happy to discuss split of concerns between skybridge/test and this package if you want

Comment thread packages/test/src/plugin.ts Outdated
* Everything the runner needs is configured here, so a scenario file imports
* nothing but `start` and its own `AppType`.
*/
export function evals(options: EvalsOptions): Plugin {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not put this directly in @skybridge/vite-plugin ?

throw new Error("The evals plugin needs either `server` or `project`");
}

const server = await startServer(options.project);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be the responsability of the start method instead to avoid booting the server on test suits that don't need it

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is, moving the server booting the start method means spawning a new server per worker. I agree the server shouldn't start for test suites that don't need it though — probably via a config somewhere?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed together, we keep server startup in the setup script of the plugin for now, and see how it affects vitest run performances that are not using chat assertions

Comment thread packages/test/src/chat.ts
Comment thread packages/test/src/chat.ts
Comment thread packages/vite-plugin/src/plugin.ts
Comment thread packages/vite-plugin/src/plugin.ts Outdated
Comment on lines +47 to +52
* Wires the eval runner into vitest: contributes `setupFiles`,
* `globalSetup`, `provide` and `testTimeout` from `@skybridge/test`, loaded
* lazily so production builds never touch it. Set it only in the config
* vitest uses for evals; when omitted, no test config is contributed and
* ordinary unit tests are unaffected. Requires `@skybridge/test` as a dev
* dependency.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels more like a claude comment that something to help end user understand what this config option will allow him to configure


The Vite plugin behind [Skybridge](https://skybridge.tech): it discovers view
modules, serves them as virtual entries, applies the `data-llm` transform, and
tells `skybridge build` which packages to leave unbundled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it also extend vitest assertions with chat-oriented APIs to assert various scenario occurring chances

@fredericbarthelet fredericbarthelet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a few comments, I think you can greatly reduce complexity by avoiding plugin definition polymorphism based on config options and by starting the server in the start chat method itself

@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 874c2eb to dde647a Compare August 24, 2026 09:12
Comment thread .github/workflows/publish.yml Outdated
fi

echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "beta_version=$VERSION-beta" >> "$GITHUB_OUTPUT"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget to remove those lines before merging :)

Comment thread packages/test/src/chat.ts Outdated
}

/** The tool definitions the model was looking at, for failure reports. */
get toolDefinitions(): ToolDefinition[] {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this part of the public API, I feel like assertions on the tool definition is like asserting that an exact line of code is written 😅

Comment thread packages/test/src/chat.ts Outdated
}

/** Takes a turn and returns the model's answer. */
async send(prompt: string): Promise<string> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returning only the last turn text response might be a bit restrictive : it's probably better to have assertion helpers that can dig in all properties of the assistant messages to test for the presence of a response that providing it in the public API and letting people run their own assertion on the string content, WDYT?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you agreed and resolved, but didn't change the API 😅

Comment thread packages/test/package.json Outdated
Comment on lines +16 to +18
"./vitest-config": {
"types": "./dist/vitest-config.d.ts",
"default": "./dist/vitest-config.js"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not used anymore

Comment thread packages/test/package.json Outdated
Comment on lines +60 to +63
"@ai-sdk/anthropic": "^2.0.0",
"@ai-sdk/google": "^2.0.0",
"@ai-sdk/mistral": "^2.0.0",
"@ai-sdk/openai": "^2.0.0",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need all 4?

Comment thread packages/test/package.json Outdated
Comment on lines +46 to +57
"@ai-sdk/anthropic": {
"optional": true
},
"@ai-sdk/google": {
"optional": true
},
"@ai-sdk/mistral": {
"optional": true
},
"@ai-sdk/openai": {
"optional": true
}

@fredericbarthelet fredericbarthelet Aug 25, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you switch to having a model being a LanguageModel , you only need a peer dep to the core ai sdk package

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ecosystem convention is peer + dev on ai, and no @ai-sdk/{openai,anthropic,…} at all.
Evalite uses LanguageModel interface from ai as input for their instrumentation

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eve does that too

Comment thread packages/test/README.md Outdated
```ts
skybridge({
evals: {
model: "anthropic/claude-sonnet-4-5",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this notation is usually reserved for people using the vercel ai gateway, it can be also supported in the project if you don't provide a LanguageModel

Comment thread packages/test/README.md Outdated
`openai/gpt-5` also resolves through the Vercel AI Gateway if you have
`AI_GATEWAY_API_KEY` set and no provider package installed.

## Models the prefixes cannot reach

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this use case is supported by ai sdk custom provider

@fredericbarthelet fredericbarthelet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments, but it starts to take shape :)
Also, could you throw a first version of documentation for this new package in this PR?

@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 0ad9d4b to 8a4b6f5 Compare August 25, 2026 12:54
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 8a4b6f5 to b6f5d60 Compare August 25, 2026 13:02
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from b6f5d60 to f7943e6 Compare August 25, 2026 13:06
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from f7943e6 to 2cdace2 Compare August 25, 2026 13:18

@fredericbarthelet fredericbarthelet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :) Awesome work @harijoe !

@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 1cfaa1d to 2cdace2 Compare August 26, 2026 08:05
@harijoe
harijoe changed the base branch from main to v2 August 26, 2026 08:10
@harijoe
harijoe force-pushed the julien/sky-546-set-up-the-skybridgeevals-package-beta branch from 2cdace2 to 8ceb3ae Compare August 26, 2026 09:56
@harijoe
harijoe changed the base branch from v2 to julien/sky-546-ipc-port August 26, 2026 09:56
@harijoe
harijoe changed the base branch from julien/sky-546-ipc-port to v2 August 26, 2026 09:57
@harijoe
harijoe merged commit 0afcaf6 into v2 Aug 28, 2026
25 checks passed
@harijoe
harijoe deleted the julien/sky-546-set-up-the-skybridgeevals-package-beta branch August 28, 2026 12:44
harijoe added a commit that referenced this pull request Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants