Repository navigation
Expand file tree
/
Copy pathharness.ts
More file actions
103 lines (95 loc) · 3.33 KB
/
Copy pathharness.ts
File metadata and controls
103 lines (95 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* Harness axis: registry, middleware, resolver. Mirrors `sequence.ts`.
*/
import { IS_PRODUCTION_BUILD } from '@env';
import { Harness } from '@shared/constants';
import { logToFile } from '@utils/debug';
import { anthropicBackend } from '../harness/anthropic';
import { piBackend } from '../harness/pi';
import type { AgentHarness } from '../harness/types';
import { resolveFlagRoute } from './flags';
import {
runChain,
type HarnessPick,
type Middleware,
type SwitchboardCtx,
} from '.';
export const HARNESS_OPTIONS: Partial<Record<Harness, AgentHarness>> = {
[Harness.anthropic]: anthropicBackend,
[Harness.pi]: piBackend,
};
export function getHarness(name: Harness): AgentHarness {
const harness = HARNESS_OPTIONS[name];
if (!harness) {
throw new Error(`No harness registered for '${name}'.`);
}
return harness;
}
/**
* PostHog-flag routing to pi (see `./flags`). No valid route — flag off, no
* config, or an invalid payload — keeps the non-flagged binding default.
*/
const flagRunnerOverride: Middleware<HarnessPick> = (ctx, next) => {
const pick = next();
const route = resolveFlagRoute(ctx.program, ctx.flags, ctx.flagPayloads);
if (!route) return pick;
if (ctx.trace) {
ctx.trace.harness = 'flag';
// Harness-only routes keep the binding's model — trace it truthfully so
// analytics never attributes the fallback model to the flag.
if (route.model) ctx.trace.model = 'flag';
}
return {
harness: route.harness ?? Harness.pi,
model: route.model ?? pick.model,
thinkingLevel: route.thinkingLevel ?? pick.thinkingLevel,
};
};
/** `--harness` override. Dev/test only — the option is gated out of published builds. */
const cliHarnessOverride: Middleware<HarnessPick> = (ctx, next) => {
const pick = next();
if (!ctx.cliHarness) return pick;
if (ctx.trace) ctx.trace.harness = 'cli';
return { ...pick, harness: ctx.cliHarness };
};
/** `--model` override. Dev/test only — the option is gated out of published builds. */
const cliModelOverride: Middleware<HarnessPick> = (ctx, next) => {
const pick = next();
if (!ctx.cliModel) return pick;
if (ctx.trace) ctx.trace.model = 'cli';
return { ...pick, model: ctx.cliModel };
};
// Order = precedence: CLI > flag > binding default. The prod spread collapses
// to [], dropping the CLI overrides from the chain.
const HARNESS_MIDDLEWARE: Middleware<HarnessPick>[] = [
...(IS_PRODUCTION_BUILD ? [] : [cliHarnessOverride, cliModelOverride]),
flagRunnerOverride,
];
/**
* Resolve the harness for a role. Linear callers omit `role`; orchestrator
* callers pass `'seed'` or `task.type`. `contextMillOverride[role]` overlays.
*/
export function resolveHarness(
ctx: SwitchboardCtx,
role = 'default',
): HarnessPick {
const pick = runChain(HARNESS_MIDDLEWARE, ctx, () => {
if (ctx.trace)
Object.assign(ctx.trace, { harness: 'binding', model: 'binding' });
const { binding } = ctx;
return {
harness: binding.harness,
model: binding.model,
thinkingLevel: binding.thinkingLevel,
...binding.contextMillOverride?.[role],
};
});
logToFile(
`[switchboard] resolved: program=${ctx.program} harness=${pick.harness}` +
`${ctx.trace?.harness ? ` (${ctx.trace.harness})` : ''} model=${
pick.model
}` +
`${ctx.trace?.model ? ` (${ctx.trace.model})` : ''}`,
);
return pick;
}