From cf69eb8ba0f896e3ae68086deeea3087b4afab6a Mon Sep 17 00:00:00 2001 From: Eric Juta Date: Fri, 11 Sep 2026 02:37:44 +0000 Subject: [PATCH 1/4] feat(evals): support native OMP profile authentication Add explicit native and API-key auth modes without copying login stores or generating native provider credentials. Keep canonical skills in the disposable session home, reject missing profile directories before dispatch, and retain existing API-key mode. --- packages/evals/__tests__/live-cli.test.ts | 171 +++++++++++++- packages/evals/src/bin/live.ts | 130 ++++++++--- packages/evals/src/index.ts | 3 +- packages/evals/src/omp-harness.ts | 259 ++++++++++++++-------- 4 files changed, 435 insertions(+), 128 deletions(-) diff --git a/packages/evals/__tests__/live-cli.test.ts b/packages/evals/__tests__/live-cli.test.ts index 6f2d7b9..4199d0a 100644 --- a/packages/evals/__tests__/live-cli.test.ts +++ b/packages/evals/__tests__/live-cli.test.ts @@ -172,10 +172,11 @@ describe("live eval CLI parser", () => { const omp = yield* parseLiveEvalCliOptions(requiredFlags("omp", ["--provider", "anthropic"])); assert.strictEqual(omp.mode, "run"); if (omp.mode === "run" && omp.options.runner === "omp") { - assert.strictEqual(omp.options.provider, "anthropic"); + assert.deepStrictEqual(omp.options.auth, { mode: "api-key", provider: "anthropic" }); assert.strictEqual(omp.options.model, "test-model"); assert.notProperty(omp.options, "maxSteps"); assert.notProperty(omp.options, "maxTurns"); + assert.notProperty(omp.options, "provider"); } const missingProvider = yield* Effect.result(parseLiveEvalCliOptions(requiredFlags("omp"))); @@ -187,6 +188,105 @@ describe("live eval CLI parser", () => { }), ); + it.effect("accepts native OMP auth and rejects mode, path, and runner conflicts", () => + Effect.gen(function* () { + const native = yield* parseLiveEvalCliOptions( + requiredFlags("omp", [ + "--omp-auth", + "native", + "--provider", + "openai-codex", + "--omp-agent-dir", + "/tmp/omp-agent", + ]), + ); + assert.strictEqual(native.mode, "run"); + if (native.mode === "run" && native.options.runner === "omp") { + assert.deepStrictEqual(native.options.auth, { + mode: "native", + provider: "openai-codex", + agentDirectory: "/tmp/omp-agent", + }); + assert.notProperty(native.options, "provider"); + } + + const nativeGoogle = yield* parseLiveEvalCliOptions( + requiredFlags("omp", [ + "--omp-auth", + "native", + "--provider", + "google", + "--omp-agent-dir", + "/tmp/omp-agent", + ]), + ); + assert.strictEqual(nativeGoogle.mode, "run"); + if (nativeGoogle.mode === "run" && nativeGoogle.options.runner === "omp") { + assert.strictEqual(nativeGoogle.options.auth.mode, "native"); + assert.strictEqual(nativeGoogle.options.auth.provider, "google"); + } + + const apiKeyGoogle = yield* Effect.result( + parseLiveEvalCliOptions(requiredFlags("omp", ["--provider", "google"])), + ); + assert.strictEqual(apiKeyGoogle._tag, "Failure"); + + const missingAgentDir = yield* Effect.result( + parseLiveEvalCliOptions( + requiredFlags("omp", ["--omp-auth", "native", "--provider", "openai-codex"]), + ), + ); + assert.strictEqual(missingAgentDir._tag, "Failure"); + + const agentDirOnApiKey = yield* Effect.result( + parseLiveEvalCliOptions( + requiredFlags("omp", ["--provider", "anthropic", "--omp-agent-dir", "/tmp/omp-agent"]), + ), + ); + assert.strictEqual(agentDirOnApiKey._tag, "Failure"); + + const authOnResponses = yield* Effect.result( + parseLiveEvalCliOptions(requiredFlags("responses", ["--omp-auth", "native"])), + ); + assert.strictEqual(authOnResponses._tag, "Failure"); + + const agentDirOnCodex = yield* Effect.result( + parseLiveEvalCliOptions(requiredFlags("codex", ["--omp-agent-dir", "/tmp/omp-agent"])), + ); + assert.strictEqual(agentDirOnCodex._tag, "Failure"); + + const nativeEndpoint = yield* Effect.result( + parseLiveEvalCliOptions( + requiredFlags("omp", [ + "--omp-auth", + "native", + "--provider", + "openai-codex", + "--omp-agent-dir", + "/tmp/omp-agent", + "--server-url", + PRODUCTION_MCP_URL, + ]), + ), + ); + assert.strictEqual(nativeEndpoint._tag, "Failure"); + + const invalidNativeId = yield* Effect.result( + parseLiveEvalCliOptions( + requiredFlags("omp", [ + "--omp-auth", + "native", + "--provider", + "bad/id", + "--omp-agent-dir", + "/tmp/omp-agent", + ]), + ), + ); + assert.strictEqual(invalidNativeId._tag, "Failure"); + }), + ); + it.effect("requires explicit OpenRouter spend and provider controls", () => Effect.gen(function* () { const flags = requiredFlags("openrouter"); @@ -586,7 +686,10 @@ describe("live eval CLI credentials", () => { it.effect("loads OMP pins without OpenAI keys and hides executable paths", () => Effect.gen(function* () { - const missingKey = yield* loadLiveEvalCredentials("omp").pipe( + const missingKey = yield* loadLiveEvalCredentials({ + runner: "omp", + authMode: "api-key", + }).pipe( withEnv({ ASK_GINA_ACCESS_TOKEN: "synthetic-gina-token", OPENAI_API_KEY: "must-not-be-required", @@ -599,7 +702,10 @@ describe("live eval CLI credentials", () => { assert.notInclude(formatLiveEvalCliFailure(missingKey.failure), "must-not-be-required"); } - const relative = yield* loadLiveEvalCredentials("omp").pipe( + const relative = yield* loadLiveEvalCredentials({ + runner: "omp", + authMode: "api-key", + }).pipe( withEnv({ ASK_GINA_ACCESS_TOKEN: "synthetic-gina-token", OMP_EVAL_API_KEY: "synthetic-omp-key", @@ -614,7 +720,7 @@ describe("live eval CLI credentials", () => { assert.notInclude(formatLiveEvalCliFailure(relative.failure), "relative/omp"); } - const loaded = yield* loadLiveEvalCredentials("omp").pipe( + const loaded = yield* loadLiveEvalCredentials({ runner: "omp", authMode: "api-key" }).pipe( withEnv({ ASK_GINA_ACCESS_TOKEN: "synthetic-gina-token", OMP_EVAL_API_KEY: "synthetic-omp-key", @@ -627,6 +733,8 @@ describe("live eval CLI credentials", () => { if (loaded.runner === "omp") { assert.strictEqual(loaded.executablePath, "/usr/bin/omp"); assert.strictEqual(loaded.expectedSha256, "abcdef"); + assert.strictEqual(loaded.auth.mode, "api-key"); + assert.notProperty(loaded, "apiKey"); } const responses = yield* loadLiveEvalCredentials("responses").pipe( @@ -639,6 +747,61 @@ describe("live eval CLI credentials", () => { assert.strictEqual(responses.runner, "responses"); }), ); + + it.effect("loads native OMP credentials without an API key and still requires Gina", () => + Effect.gen(function* () { + const missingGina = yield* loadLiveEvalCredentials({ + runner: "omp", + authMode: "native", + }).pipe( + withEnv({ + OMP_EVAL_EXECUTABLE: "/usr/bin/omp", + OMP_EVAL_EXECUTABLE_SHA256: "abcdef", + }), + Effect.result, + ); + assert.strictEqual(missingGina._tag, "Failure"); + if (missingGina._tag === "Failure") { + assert.strictEqual(missingGina.failure.reason, "invalid-credentials"); + assert.deepStrictEqual(missingGina.failure.missing, ["ASK_GINA_ACCESS_TOKEN"]); + } + + const loaded = yield* loadLiveEvalCredentials({ + runner: "omp", + authMode: "native", + }).pipe( + withEnv({ + ASK_GINA_ACCESS_TOKEN: "synthetic-gina-token", + OMP_EVAL_EXECUTABLE: "/usr/bin/omp", + OMP_EVAL_EXECUTABLE_SHA256: "AbCDEF", + OPENAI_API_KEY: "must-not-be-required", + }), + ); + assert.strictEqual(loaded.runner, "omp"); + if (loaded.runner === "omp") { + assert.strictEqual(loaded.executablePath, "/usr/bin/omp"); + assert.strictEqual(loaded.expectedSha256, "abcdef"); + assert.deepStrictEqual(loaded.auth, { mode: "native" }); + assert.notProperty(loaded, "apiKey"); + } + + const ambientKey = yield* loadLiveEvalCredentials({ + runner: "omp", + authMode: "native", + }).pipe( + withEnv({ + ASK_GINA_ACCESS_TOKEN: "synthetic-gina-token", + OMP_EVAL_API_KEY: "must-not-be-required", + OMP_EVAL_EXECUTABLE: "/usr/bin/omp", + OMP_EVAL_EXECUTABLE_SHA256: "abcdef", + }), + ); + assert.strictEqual(ambientKey.runner, "omp"); + if (ambientKey.runner === "omp") { + assert.deepStrictEqual(ambientKey.auth, { mode: "native" }); + } + }), + ); }); }); diff --git a/packages/evals/src/bin/live.ts b/packages/evals/src/bin/live.ts index f67e58c..8568650 100755 --- a/packages/evals/src/bin/live.ts +++ b/packages/evals/src/bin/live.ts @@ -56,10 +56,11 @@ import { selectCases, } from "../live"; import { - isOmpProvider, + isOmpApiKeyProvider, + isOmpProviderIdentifier, prepareOmpHarnessRuntime, runOmpHarnessPluginEvalTrial, - type OmpProvider, + type OmpApiKeyProvider, type PluginEvalOmpHarnessError, } from "../omp-harness"; import { @@ -142,7 +143,7 @@ export const liveEvalTrialDispatch = (options: LiveEvalCliOptions): LiveEvalTria return { target, maxTurns: options.maxTurns }; } if (options.runner === "omp") { - return { target, model: `${options.provider}/${options.model}` }; + return { target, model: `${options.auth.provider}/${options.model}` }; } return { target, displayedModel: options.model }; }; @@ -185,7 +186,12 @@ export type LiveEvalCliOptions = readonly expectedProvider: string; }) | (LiveEvalCliSharedOptions & { readonly runner: "claude"; readonly maxTurns: number }) - | (LiveEvalCliSharedOptions & { readonly runner: "omp"; readonly provider: OmpProvider }); + | (LiveEvalCliSharedOptions & { + readonly runner: "omp"; + readonly auth: + | { readonly mode: "api-key"; readonly provider: OmpApiKeyProvider } + | { readonly mode: "native"; readonly provider: string; readonly agentDirectory: string }; + }); export type LiveEvalCliParseResult = | { readonly mode: "help"; readonly usage: string } @@ -239,14 +245,14 @@ export const formatLiveEvalCliUsage = (runner?: LiveEvalRunner): string => { } if (runner === "omp") { return [ - `Usage: bun run eval:omp -- ${REQUIRED_LIVE_EVAL_FLAGS} --provider `, - `Environment: ${ASK_GINA_ACCESS_TOKEN}, ${OMP_EVAL_API_KEY}, ${OMP_EVAL_EXECUTABLE}, ${OMP_EVAL_EXECUTABLE_SHA256}`, + `Usage: bun run eval:omp -- ${REQUIRED_LIVE_EVAL_FLAGS} --provider [--omp-auth api-key|native] [--omp-agent-dir ]`, + `--omp-auth default api-key. --provider for api-key: openai|anthropic|openrouter. --omp-agent-dir is required for native and forbidden for api-key. Environment: ${ASK_GINA_ACCESS_TOKEN}, ${OMP_EVAL_EXECUTABLE}, ${OMP_EVAL_EXECUTABLE_SHA256}; ${OMP_EVAL_API_KEY} (api-key).`, ].join("\n"); } return [ `Usage: bun run eval: -- ${REQUIRED_LIVE_EVAL_FLAGS}`, - `OpenRouter-only: --openrouter-endpoint --expected-provider