Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/docs/src/content/docs/reference/config-and-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ related:
| `JUNIOR_CROSS_ACTOR_MID_RUN_MODE` | No | Cross-actor Slack steering policy. Defaults to `follow_up`; see below. |
| `AI_MODEL` | No | Deprecated profile setting. Creates `standard` and remains the fallback for `AI_FAST_MODEL`. Defaults to `openai/gpt-6-luna` with high reasoning. |
| `AI_REASONING_LEVEL` | No | Main-agent reasoning override: `none`, `low`, `medium`, `high`, or `xhigh`. Unset by default. An explicit profile reasoning level takes precedence when routing is enabled. |
| `AI_FAST_MODEL` | No | Faster model for lightweight tasks and routing/classification passes before the main turn begins. Defaults to `openai/gpt-6-luna`. |
| `AI_FAST_MODEL` | No | Faster model for lightweight tasks and utility calls. Defaults to `openai/gpt-6-luna`. |
| `AI_GUARDIAN_MODEL` | No | Model for Guardian action review. Defaults to `openai/gpt-6-luna`. |
| `AI_DECISION_MODEL` | No | Decision model for passive reply routing in subscribed threads. Uses the AI SDK decision API. Defaults to `typesafe-ai/jev`. |
| `AI_DECISION_MODEL` | No | Decision model for the turn router and for passive reply routing in subscribed threads. Uses the AI SDK decision API. Defaults to `typesafe-ai/jev`. |
| `AI_HANDOFF_MODEL` | No | Deprecated profile setting. Creates `handoff`. Defaults to `anthropic/claude-opus-5.5` with high reasoning. |
| `AI_MODEL_PROFILES` | No | Deprecated JSON map of profile names to model IDs for env-only setup. Names must match `^[a-z][a-z0-9_-]*$`. |
| `AI_EMBEDDING_MODEL` | No | Embedding model for plugin-owned vector retrieval. Defaults to `openai/text-embedding-3-small`; memory v1 stores fixed 1536-dimensional vectors. |
Expand Down
2 changes: 1 addition & 1 deletion packages/junior-evals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ There are four independently runnable suites:
- Integration and behavioral cases run the real agent through the agent test fixture.
- Guardian and router cases use `describeEval()` with their own harness. They call one model boundary and do not run the agent.
- Behavioral and integration evals use normal core model configuration, including loaded environment overrides. Without overrides, they use the shared core defaults. Neither suite pins models or adds profiles.
- Router evals use the shared core profiles and configured fast model. Reasoning cases remove fixed profile levels to test the classifier; profile cases retain the defaults.
- Router evals use the shared core profiles and configured decision model. Reasoning cases remove fixed profile levels to test the classifier; profile cases retain the defaults.

## Agent Test Fixture

Expand Down
9 changes: 5 additions & 4 deletions packages/junior-evals/src/router-harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
type DescribeEvalOptions,
type JsonValue,
} from "vitest-evals";
import { completeObject } from "@/chat/pi/client";
import { completeDecision } from "@/chat/pi/client";
import {
DEFAULT_MODEL_PROFILES,
type ModelProfileConfig,
Expand Down Expand Up @@ -48,11 +48,12 @@ async function routeTask(
: timeoutSignal;

return selectTurnRoute({
completeObject: (args) => completeObject({ ...args, signal: routeSignal }),
completeDecision: (args) =>
completeDecision({ ...args, signal: routeSignal }),
conversationContext: input.conversationContext,
currentProfile: input.currentProfile ?? "standard",
fastModelId: botConfig.fastModelId,
messageText: input.messageText,
modelId: botConfig.decisionModelId,
profiles: input.profiles ?? DEFAULT_MODEL_PROFILES,
});
}
Expand Down Expand Up @@ -106,7 +107,7 @@ export const routerHarness = createHarness<RouterEvalInput, RouterEvalOutput>({
],
usage: {
provider: "vercel-ai-gateway",
model: botConfig.fastModelId,
model: botConfig.decisionModelId,
...(route.costUsd !== undefined
? { metadata: { costUsd: route.costUsd } }
: {}),
Expand Down
6 changes: 3 additions & 3 deletions packages/junior/src/chat/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import {
} from "@/chat/credentials/context";
import {
GEN_AI_PROVIDER_NAME,
completeObject,
completeDecision,
completeText,
getGatewayApiKey,
resolveGatewayModel,
Expand Down Expand Up @@ -657,7 +657,7 @@ async function executeAgentRunInPrivacyContext(
// unfinished work there or move a new request to another profile.
const lastProfile = await loadLastModelProfile({ conversationId });
turnRoute = await selectTurnRoute({
completeObject,
completeDecision,
conversationContext: input.conversationContext,
context: {
threadId: conversationId,
Expand All @@ -670,8 +670,8 @@ async function executeAgentRunInPrivacyContext(
? lastProfile
: botConfig.defaultProfile,
currentTurnBlocks: routerBlocks,
fastModelId: botConfig.fastModelId,
messageText: userInput,
modelId: botConfig.decisionModelId,
profiles: botConfig.profiles,
});
const routedProfileReasoningLevel = profileConfig(
Expand Down
2 changes: 1 addition & 1 deletion packages/junior/src/chat/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const DEFAULT_ASSISTANT_LOADING_MESSAGES = [
] as const;

export interface BotModelConfig {
/** Decision model used by the passive reply router. */
/** Decision model used by the turn router and the passive reply router. */
decisionModelId?: string;
/** Model used for embeddings. */
embeddingModelId?: string;
Expand Down
Loading
Loading