oh-my-promptfoo 1.26.0 → 1.28.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/README.md +35 -1
- package/dist/assertions.cjs +3 -3
- package/dist/assertions.cjs.map +1 -1
- package/dist/assertions.d.cts +2 -1
- package/dist/assertions.d.ts +2 -1
- package/dist/assertions.js +3 -3
- package/dist/assertions.js.map +1 -1
- package/dist/{config-CjWHeukN.d.ts → config-L5S9SrkO.d.cts} +2 -1
- package/dist/{config-CjWHeukN.d.cts → config-L5S9SrkO.d.ts} +2 -1
- package/dist/delegate-runner.js +58 -2
- package/dist/delegate-runner.js.map +1 -1
- package/dist/{fs-D9YrrmPG.cjs → fs-CNr5ZxiH.cjs} +15 -2
- package/dist/fs-CNr5ZxiH.cjs.map +1 -0
- package/dist/{fs-CedLyQsv.js → fs-a7zK59AT.js} +15 -2
- package/dist/fs-a7zK59AT.js.map +1 -0
- package/dist/{mcp-CojL00iW.js → mcp-CA38aueh.js} +6 -1
- package/dist/mcp-CA38aueh.js.map +1 -0
- package/dist/mcp-launcher.js +1 -1
- package/dist/providers.cjs +1 -1
- package/dist/providers.d.cts +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/package.json +1 -1
- package/dist/fs-CedLyQsv.js.map +0 -1
- package/dist/fs-D9YrrmPG.cjs.map +0 -1
- package/dist/mcp-CojL00iW.js.map +0 -1
package/README.md
CHANGED
|
@@ -94,7 +94,8 @@ pinned Git and OCI sources, and larger runs.
|
|
|
94
94
|
assertion works with all four agents, with no tracing setup.
|
|
95
95
|
- **Grade many criteria in one judge call.** `llmAssert` works like
|
|
96
96
|
`llm-rubric`, but scores a whole list of named criteria at once, and each
|
|
97
|
-
one shows up as its own score.
|
|
97
|
+
one shows up as its own score. Both rubric assertions default to binary
|
|
98
|
+
scoring; set `config.scoring: graded` for partial credit or thresholds below 1.
|
|
98
99
|
- **Grade what the agent did, not what it says it did.** `agentAssert` sends a
|
|
99
100
|
read-only agent into the workspace to check the changes. Turn on
|
|
100
101
|
`fileChanges` to read them in your own JavaScript assertions.
|
|
@@ -120,6 +121,39 @@ providers here and dropped their `Provider` suffix; the ids of earlier versions
|
|
|
120
121
|
no longer resolve (see the
|
|
121
122
|
[changelog](https://github.com/allagentsdev/oh-my-promptfoo/blob/main/CHANGELOG.md)).
|
|
122
123
|
|
|
124
|
+
## Copilot conversations
|
|
125
|
+
|
|
126
|
+
Use [Promptfoo's ordinary chat templates](https://www.promptfoo.dev/docs/configuration/chat/)
|
|
127
|
+
with either `CopilotSdk` or `Agent` delegating to `copilot-sdk`. JSON and YAML
|
|
128
|
+
prompt files, simplified chat markup expanded by Nunjucks, shared fixed history,
|
|
129
|
+
`_conversation` replay, `metadata.conversationId`, `storeOutputAs` and output
|
|
130
|
+
transforms belong to Promptfoo, not a JavaScript conversation adapter.
|
|
131
|
+
Normal assertions grade each new reply; the provider reads only the rendered prompt.
|
|
132
|
+
|
|
133
|
+
Copilot's optional `inputFormat` is `auto` (default), `chat` or `text`. Set it in
|
|
134
|
+
direct provider config or the Agent's `delegate.config`; per-test
|
|
135
|
+
`options.delegate.config.inputFormat` overrides either. `auto` recognizes only
|
|
136
|
+
complete chat-shaped JSON arrays; business records with other roles or incomplete
|
|
137
|
+
records remain literal. Chat-shaped business data is inherently ambiguous: use
|
|
138
|
+
`text` to bypass provider parsing and preserve the supplied/rendered string exactly.
|
|
139
|
+
It does not bypass Promptfoo's earlier Nunjucks rendering or variable expansion.
|
|
140
|
+
YAML **file** loading is Promptfoo's job; raw YAML text is not provider chat input.
|
|
141
|
+
|
|
142
|
+
All system messages, even later ones, are consolidated in original system order
|
|
143
|
+
and appended to Copilot's core instructions through the public SDK. Other
|
|
144
|
+
messages preserve string names, tool IDs, order and content in a delimited
|
|
145
|
+
**user-channel JSON transcript**, not native assistant/tool roles. Delimiters
|
|
146
|
+
are not a security boundary. Each row uses a fresh session and, with `Agent`, a
|
|
147
|
+
fresh workspace. History is supplied input, not tool evidence or filesystem state.
|
|
148
|
+
Returned errors, including settled aborts, retain published workspaces until
|
|
149
|
+
cleanup; thrown failures release unpublished workspaces.
|
|
150
|
+
|
|
151
|
+
The [two-provider examples](examples/copilot-conversations/promptfooconfig.yaml)
|
|
152
|
+
include three generated turns, interleaved IDs, JSON/YAML and simplified fixed
|
|
153
|
+
history, embedded/literal JSON, full-prompt replay and transformed-output storage.
|
|
154
|
+
See the [feature/provenance and compatibility matrices](docs/provider-guide.md#feature-and-verification-provenance)
|
|
155
|
+
for engine-owned behavior, SDK limits and verification status.
|
|
156
|
+
|
|
123
157
|
## Local MCP fixtures
|
|
124
158
|
|
|
125
159
|
Copilot and Claude candidates can call suite-authored Node MCP servers staged in
|
package/dist/assertions.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_fs = require("./fs-
|
|
2
|
+
const require_fs = require("./fs-CNr5ZxiH.cjs");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
4
|
let node_url = require("node:url");
|
|
5
5
|
let node_fs = require("node:fs");
|
|
@@ -45,11 +45,11 @@ function render(source, vars, label) {
|
|
|
45
45
|
function prepareRubric(output, context, workspace = false) {
|
|
46
46
|
const config = context?.config;
|
|
47
47
|
const components = config?.components;
|
|
48
|
-
const scoring = config?.scoring ?? "
|
|
48
|
+
const scoring = config?.scoring ?? "binary";
|
|
49
49
|
if (config && Object.hasOwn(config, "rubric")) throw new Error("LLM assertion config.rubric was renamed to config.rubricPrompt");
|
|
50
50
|
if (config && Object.hasOwn(config, "candidate")) throw new Error("LLM assertion config.candidate was removed; state the grading rule in config.rubricPrompt");
|
|
51
51
|
if (config?.rubricPrompt !== void 0 && typeof config.rubricPrompt !== "string") throw new Error("LLM assertion rubricPrompt must be a string, not an object or array (including parsed JSON/YAML file contents): use inline text or a text-file string. llmAssert keeps its own system prompt and reply format; chat templates cannot replace them");
|
|
52
|
-
if (!config || !Array.isArray(components) || components.length === 0 || !components.every((component) => component && typeof component.metric === "string" && component.metric.trim() && typeof component.value === "string" && component.value.trim() && (component.weight === void 0 || typeof component.weight === "number" && Number.isFinite(component.weight) && component.weight > 0)) || new Set(components.map(({ metric }) => metric)).size !== components.length || ![config.threshold, ...components.map(({ threshold }) => threshold)].every((threshold) => threshold === void 0 || typeof threshold === "number" && Number.isFinite(threshold) && threshold >= 0 && threshold <= 1 && (scoring !== "binary" || threshold === 1)) || config.rubricPrompt !== void 0 && !config.rubricPrompt.trim() || config.scoring !== void 0 && config.scoring !== "graded" && config.scoring !== "binary") throw new Error("LLM assertion requires unique named components with nonempty criteria, positive weights, a config.threshold and component thresholds between 0 and 1, a nonempty string rubricPrompt, and scoring of 'graded' or 'binary' without a conflicting config.threshold or component threshold");
|
|
52
|
+
if (!config || !Array.isArray(components) || components.length === 0 || !components.every((component) => component && typeof component.metric === "string" && component.metric.trim() && typeof component.value === "string" && component.value.trim() && (component.weight === void 0 || typeof component.weight === "number" && Number.isFinite(component.weight) && component.weight > 0)) || new Set(components.map(({ metric }) => metric)).size !== components.length || ![config.threshold, ...components.map(({ threshold }) => threshold)].every((threshold) => threshold === void 0 || typeof threshold === "number" && Number.isFinite(threshold) && threshold >= 0 && threshold <= 1 && (scoring !== "binary" || threshold === 1)) || config.rubricPrompt !== void 0 && !config.rubricPrompt.trim() || config.scoring !== void 0 && config.scoring !== "graded" && config.scoring !== "binary") throw new Error("LLM assertion requires unique named components with nonempty criteria, positive weights, a config.threshold and component thresholds between 0 and 1, a nonempty string rubricPrompt, and scoring of 'graded' or 'binary' without a conflicting config.threshold or component threshold; scoring defaults to 'binary', so set scoring: 'graded' for thresholds other than 1");
|
|
53
53
|
if (components.some(({ metric }) => Object.hasOwn(Object.prototype, metric))) throw new Error("LLM assertion requires no reserved component metric names");
|
|
54
54
|
const totalWeight = components.reduce((sum, component) => sum + (component.weight ?? 1), 0);
|
|
55
55
|
if (!Number.isFinite(totalWeight)) throw new Error("LLM assertion component weights exceed the supported range");
|