@guilz-dev/belay 0.2.0 → 0.3.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 +39 -12
- package/dist/adapters/shared/gate-runtime.js +13 -5
- package/dist/bundle/claude-runtime.mjs +1659 -371
- package/dist/bundle/codex-runtime.mjs +1658 -371
- package/dist/bundle/cursor-runtime.mjs +1659 -371
- package/dist/cli.js +198 -8
- package/dist/commands/approve.js +11 -0
- package/dist/commands/config.d.ts +70 -0
- package/dist/commands/config.js +494 -0
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/health-snapshot.d.ts +6 -0
- package/dist/commands/health-snapshot.js +34 -0
- package/dist/commands/judge.d.ts +90 -0
- package/dist/commands/judge.js +285 -0
- package/dist/commands/status.js +2 -2
- package/dist/commands/stdin-key.d.ts +1 -0
- package/dist/commands/stdin-key.js +8 -0
- package/dist/conformance/guarantee-table.js +12 -0
- package/dist/conformance/types.d.ts +2 -0
- package/dist/core/audit-io.d.ts +2 -0
- package/dist/core/audit-io.js +14 -0
- package/dist/core/capability/index.d.ts +2 -2
- package/dist/core/capability/index.js +2 -2
- package/dist/core/capability/paths.d.ts +1 -0
- package/dist/core/capability/paths.js +74 -6
- package/dist/core/capability/reasons.d.ts +3 -0
- package/dist/core/capability/reasons.js +8 -0
- package/dist/core/classify-tool.js +97 -27
- package/dist/core/config-layers.js +2 -1
- package/dist/core/config.d.ts +22 -2
- package/dist/core/config.js +110 -11
- package/dist/core/credential-store.d.ts +11 -0
- package/dist/core/credential-store.js +60 -0
- package/dist/core/gate-engine.js +104 -13
- package/dist/core/integrity.d.ts +2 -0
- package/dist/core/integrity.js +13 -0
- package/dist/core/judge-api-key.d.ts +19 -0
- package/dist/core/judge-api-key.js +74 -0
- package/dist/core/judge-cloud-consent.d.ts +13 -0
- package/dist/core/judge-cloud-consent.js +38 -0
- package/dist/core/judge-config.d.ts +41 -4
- package/dist/core/judge-config.js +263 -57
- package/dist/core/judge-doctor.d.ts +6 -1
- package/dist/core/judge-doctor.js +147 -96
- package/dist/core/judge-model-discovery.d.ts +24 -0
- package/dist/core/judge-model-discovery.js +168 -0
- package/dist/core/judge-model-policy.d.ts +5 -0
- package/dist/core/judge-model-policy.js +21 -0
- package/dist/core/judge-runtime-detection.d.ts +9 -0
- package/dist/core/judge-runtime-detection.js +68 -0
- package/dist/core/transactional/diff-evaluator.js +1 -19
- package/dist/core/types.d.ts +2 -0
- package/dist/core/verdict/adapter.d.ts +1 -0
- package/dist/core/verdict/adapter.js +7 -1
- package/dist/core/verdict/containment.d.ts +5 -0
- package/dist/core/verdict/containment.js +32 -2
- package/dist/core/verdict/judge-catalog.d.ts +40 -0
- package/dist/core/verdict/judge-catalog.js +148 -0
- package/dist/core/verdict/judge-cli.d.ts +23 -0
- package/dist/core/verdict/judge-cli.js +280 -0
- package/dist/core/verdict/judge-factory.d.ts +15 -4
- package/dist/core/verdict/judge-factory.js +117 -14
- package/dist/core/verdict/judge.d.ts +20 -1
- package/dist/core/verdict/judge.js +83 -14
- package/dist/core/verdict/persistent-paths.d.ts +8 -0
- package/dist/core/verdict/persistent-paths.js +52 -0
- package/dist/core/verdict/types.d.ts +6 -2
- package/dist/core/verdict/verdict.js +161 -47
- package/dist/installer.js +66 -15
- package/dist/types.d.ts +7 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/belay/SKILL.md +8 -7
- package/dist/commands/init-wizard.d.ts +0 -21
- package/dist/commands/init-wizard.js +0 -63
|
@@ -1,33 +1,70 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AdapterName } from '../adapters/layouts/types.js';
|
|
2
|
+
import type { BelayJudgeConfig, JudgeProviderId } from './config.js';
|
|
3
|
+
import { isJudgeProviderId } from './verdict/judge-catalog.js';
|
|
2
4
|
export type JudgeProfileName = 'local-ollama' | 'cursor' | 'claude' | 'codex';
|
|
3
5
|
export declare const JUDGE_PROFILE_LOCAL_OLLAMA: BelayJudgeConfig;
|
|
4
6
|
export declare const JUDGE_PROFILE_CURSOR: BelayJudgeConfig;
|
|
5
7
|
export declare const JUDGE_PROFILE_CLAUDE: BelayJudgeConfig;
|
|
6
8
|
export declare const JUDGE_PROFILE_CODEX: BelayJudgeConfig;
|
|
7
9
|
export declare const JUDGE_PROFILES: Record<JudgeProfileName, BelayJudgeConfig>;
|
|
10
|
+
/** Default Tier1 judge catalog id for a host adapter (fresh init, no explicit judge flags). */
|
|
11
|
+
export declare function defaultJudgeProviderForAdapter(adapter: AdapterName): JudgeProviderId;
|
|
8
12
|
export interface ResolveJudgeConfigInput {
|
|
9
13
|
judgeProfile?: JudgeProfileName;
|
|
10
14
|
judgeProvider?: 'ollama' | 'openai-compatible' | 'cursor';
|
|
15
|
+
judgeProviderId?: JudgeProviderId | string;
|
|
11
16
|
judgeModel?: string;
|
|
12
17
|
judgeEndpoint?: string;
|
|
13
18
|
existingJudge?: BelayJudgeConfig;
|
|
14
19
|
}
|
|
15
20
|
export declare function resolveJudgeConfig(input?: ResolveJudgeConfigInput): BelayJudgeConfig;
|
|
16
21
|
export declare class CloudJudgeConsentRequiredError extends Error {
|
|
17
|
-
constructor(
|
|
22
|
+
constructor(details?: {
|
|
23
|
+
consent?: boolean;
|
|
24
|
+
key?: boolean;
|
|
25
|
+
localFallback?: boolean;
|
|
26
|
+
});
|
|
18
27
|
}
|
|
19
28
|
export declare class JudgeEndpointRequiredError extends Error {
|
|
20
|
-
constructor();
|
|
29
|
+
constructor(providerId?: JudgeProviderId);
|
|
21
30
|
}
|
|
31
|
+
export declare function isCloudJudgeConfig(judge: BelayJudgeConfig): boolean;
|
|
32
|
+
export declare function hasValidCloudConsent(judge: BelayJudgeConfig): boolean;
|
|
33
|
+
export declare function isImplicitLocalJudge(judge: BelayJudgeConfig): boolean;
|
|
34
|
+
export declare function migrateImplicitLocalJudgeIfNeeded(existingJudge: BelayJudgeConfig, adapter: AdapterName): BelayJudgeConfig | null;
|
|
22
35
|
export declare function assertJudgeEndpoint(judge: BelayJudgeConfig): void;
|
|
23
36
|
export declare function resolveInitJudgeConfig(input: {
|
|
24
37
|
isFresh: boolean;
|
|
25
38
|
hasExplicitJudgeFlags: boolean;
|
|
26
39
|
judgeProfile?: JudgeProfileName;
|
|
27
40
|
judgeProvider?: 'ollama' | 'openai-compatible' | 'cursor';
|
|
41
|
+
judgeProviderId?: JudgeProviderId | string;
|
|
28
42
|
judgeModel?: string;
|
|
29
43
|
judgeEndpoint?: string;
|
|
30
44
|
acceptCloudJudge?: boolean;
|
|
45
|
+
interactiveConsent?: boolean;
|
|
46
|
+
cloudConsentApprovalId?: string;
|
|
31
47
|
existingJudge?: BelayJudgeConfig;
|
|
32
|
-
|
|
48
|
+
adapter?: AdapterName;
|
|
33
49
|
}): BelayJudgeConfig;
|
|
50
|
+
export declare function applyCloudConsent(judge: BelayJudgeConfig, params: {
|
|
51
|
+
by: string;
|
|
52
|
+
}): BelayJudgeConfig;
|
|
53
|
+
export interface JudgeUseOptions {
|
|
54
|
+
providerId: JudgeProviderId | string;
|
|
55
|
+
model?: string;
|
|
56
|
+
endpoint?: string;
|
|
57
|
+
timeoutMs?: number;
|
|
58
|
+
acceptCloud?: boolean;
|
|
59
|
+
cloudConsentApprovalId?: string;
|
|
60
|
+
credentialMode?: 'project' | 'apiKey';
|
|
61
|
+
keyEnv?: string;
|
|
62
|
+
interactiveTTY?: boolean;
|
|
63
|
+
interactiveConsentApproved?: boolean;
|
|
64
|
+
}
|
|
65
|
+
export declare function resolveJudgeUsePatch(existing: BelayJudgeConfig, options: JudgeUseOptions): {
|
|
66
|
+
judge: BelayJudgeConfig;
|
|
67
|
+
warnings: string[];
|
|
68
|
+
errors: string[];
|
|
69
|
+
};
|
|
70
|
+
export { isJudgeProviderId };
|
|
@@ -1,101 +1,307 @@
|
|
|
1
1
|
import { normalizeJudgeProvider } from './config.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
provider: 'openai-compatible',
|
|
11
|
-
model: 'auto',
|
|
12
|
-
endpoint: 'https://api.openai.com/v1',
|
|
13
|
-
timeoutMs: 8000,
|
|
14
|
-
keepAlive: null,
|
|
15
|
-
};
|
|
16
|
-
export const JUDGE_PROFILE_CLAUDE = {
|
|
17
|
-
...JUDGE_PROFILE_CURSOR,
|
|
18
|
-
};
|
|
19
|
-
export const JUDGE_PROFILE_CODEX = {
|
|
20
|
-
...JUDGE_PROFILE_CURSOR,
|
|
2
|
+
import { rejectDeprecatedJudgeModelAuto } from './judge-model-policy.js';
|
|
3
|
+
import { detectJudgeRuntimeCapabilities } from './judge-runtime-detection.js';
|
|
4
|
+
import { catalogRequiresEndpoint, getJudgeProviderSpec, isCloudProviderId, isJudgeProviderId, JUDGE_PROVIDER_IDS, normalizeLegacyProviderId, resolveJudgeFromCatalog, } from './verdict/judge-catalog.js';
|
|
5
|
+
const PROFILE_TO_PROVIDER_ID = {
|
|
6
|
+
'local-ollama': 'ollama',
|
|
7
|
+
cursor: 'cursor',
|
|
8
|
+
claude: 'claude',
|
|
9
|
+
codex: 'codex',
|
|
21
10
|
};
|
|
11
|
+
export const JUDGE_PROFILE_LOCAL_OLLAMA = resolveJudgeFromCatalog({
|
|
12
|
+
providerId: 'ollama',
|
|
13
|
+
});
|
|
14
|
+
export const JUDGE_PROFILE_CURSOR = resolveJudgeFromCatalog({
|
|
15
|
+
providerId: 'cursor',
|
|
16
|
+
});
|
|
17
|
+
export const JUDGE_PROFILE_CLAUDE = resolveJudgeFromCatalog({
|
|
18
|
+
providerId: 'claude',
|
|
19
|
+
});
|
|
20
|
+
export const JUDGE_PROFILE_CODEX = resolveJudgeFromCatalog({
|
|
21
|
+
providerId: 'codex',
|
|
22
|
+
});
|
|
22
23
|
export const JUDGE_PROFILES = {
|
|
23
24
|
'local-ollama': JUDGE_PROFILE_LOCAL_OLLAMA,
|
|
24
25
|
cursor: JUDGE_PROFILE_CURSOR,
|
|
25
26
|
claude: JUDGE_PROFILE_CLAUDE,
|
|
26
27
|
codex: JUDGE_PROFILE_CODEX,
|
|
27
28
|
};
|
|
28
|
-
|
|
29
|
+
/** Default Tier1 judge catalog id for a host adapter (fresh init, no explicit judge flags). */
|
|
30
|
+
export function defaultJudgeProviderForAdapter(adapter) {
|
|
31
|
+
if (adapter === 'cursor') {
|
|
32
|
+
return 'cursor';
|
|
33
|
+
}
|
|
34
|
+
if (adapter === 'claude') {
|
|
35
|
+
return 'claude';
|
|
36
|
+
}
|
|
37
|
+
if (adapter === 'codex') {
|
|
38
|
+
return 'codex';
|
|
39
|
+
}
|
|
40
|
+
return 'cursor';
|
|
41
|
+
}
|
|
42
|
+
function warnDeprecated(message) {
|
|
43
|
+
process.stderr.write(`Warning: ${message}\n`);
|
|
44
|
+
}
|
|
45
|
+
function resolveProviderIdFromFlags(input) {
|
|
46
|
+
if (input.judgeProviderId) {
|
|
47
|
+
const normalized = normalizeLegacyProviderId(String(input.judgeProviderId));
|
|
48
|
+
if (normalized) {
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
29
52
|
if (input.judgeProvider) {
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
const rawProvider = input.judgeProvider;
|
|
54
|
+
const provider = normalizeJudgeProvider(rawProvider);
|
|
55
|
+
if (rawProvider === 'cursor') {
|
|
56
|
+
return 'cursor';
|
|
57
|
+
}
|
|
58
|
+
if (provider === 'ollama') {
|
|
59
|
+
return 'ollama';
|
|
60
|
+
}
|
|
61
|
+
return 'codex';
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
export function resolveJudgeConfig(input = {}) {
|
|
66
|
+
if (input.judgeModel !== undefined) {
|
|
67
|
+
rejectDeprecatedJudgeModelAuto(input.judgeModel);
|
|
68
|
+
}
|
|
69
|
+
const providerIdFromFlags = resolveProviderIdFromFlags(input);
|
|
70
|
+
if (providerIdFromFlags) {
|
|
71
|
+
return resolveJudgeFromCatalog({
|
|
72
|
+
providerId: providerIdFromFlags,
|
|
73
|
+
model: input.judgeModel,
|
|
74
|
+
endpoint: input.judgeEndpoint,
|
|
75
|
+
});
|
|
37
76
|
}
|
|
38
77
|
if (input.judgeProfile) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
78
|
+
warnDeprecated(`--judge-profile is deprecated; use belay config set judge.providerId <provider-id> (${JUDGE_PROVIDER_IDS.join(', ')}).`);
|
|
79
|
+
const providerId = PROFILE_TO_PROVIDER_ID[input.judgeProfile];
|
|
80
|
+
return resolveJudgeFromCatalog({
|
|
81
|
+
providerId,
|
|
82
|
+
model: input.judgeModel,
|
|
83
|
+
endpoint: input.judgeEndpoint,
|
|
84
|
+
});
|
|
45
85
|
}
|
|
46
86
|
if (input.existingJudge) {
|
|
47
87
|
return { ...input.existingJudge };
|
|
48
88
|
}
|
|
49
89
|
return { ...JUDGE_PROFILE_LOCAL_OLLAMA };
|
|
50
90
|
}
|
|
51
|
-
function openAiCompatibleBase(input) {
|
|
52
|
-
return {
|
|
53
|
-
provider: 'openai-compatible',
|
|
54
|
-
model: input.judgeModel ?? 'auto',
|
|
55
|
-
timeoutMs: 8000,
|
|
56
|
-
endpoint: input.judgeEndpoint?.trim() ?? null,
|
|
57
|
-
keepAlive: null,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
91
|
export class CloudJudgeConsentRequiredError extends Error {
|
|
61
|
-
constructor() {
|
|
62
|
-
|
|
63
|
-
|
|
92
|
+
constructor(details) {
|
|
93
|
+
const parts = [];
|
|
94
|
+
if (details?.consent !== false) {
|
|
95
|
+
parts.push('Cloud judge requires recorded consent (interactive TTY with --accept-cloud, or judge_cloud_consent capability approval).');
|
|
96
|
+
}
|
|
97
|
+
if (details?.key !== false) {
|
|
98
|
+
parts.push('Set provider API keys via env or belay config credential set --key-stdin.');
|
|
99
|
+
}
|
|
100
|
+
if (details?.localFallback !== false) {
|
|
101
|
+
parts.push('Use belay config set judge.providerId ollama for local-only Tier1.');
|
|
102
|
+
}
|
|
103
|
+
super(parts.join(' '));
|
|
64
104
|
this.name = 'CloudJudgeConsentRequiredError';
|
|
65
105
|
}
|
|
66
106
|
}
|
|
67
107
|
export class JudgeEndpointRequiredError extends Error {
|
|
68
|
-
constructor() {
|
|
69
|
-
super(
|
|
108
|
+
constructor(providerId) {
|
|
109
|
+
super(providerId
|
|
110
|
+
? `${providerId} judge requires --endpoint (or judge.endpoint in config).`
|
|
111
|
+
: 'openai-compatible judge requires --judge-endpoint (or judge.endpoint in config). No default cloud base URL is applied.');
|
|
70
112
|
this.name = 'JudgeEndpointRequiredError';
|
|
71
113
|
}
|
|
72
114
|
}
|
|
73
|
-
function isCloudJudgeConfig(judge) {
|
|
74
|
-
|
|
115
|
+
export function isCloudJudgeConfig(judge) {
|
|
116
|
+
if (judge.providerId) {
|
|
117
|
+
return isCloudProviderId(judge.providerId);
|
|
118
|
+
}
|
|
119
|
+
return judge.provider === 'openai-compatible' || judge.provider === 'anthropic';
|
|
120
|
+
}
|
|
121
|
+
export function hasValidCloudConsent(judge) {
|
|
122
|
+
if (!judge.cloudConsent?.accepted) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
if (!judge.endpoint?.trim()) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
const providerId = judge.providerId && normalizeLegacyProviderId(judge.providerId)
|
|
129
|
+
? normalizeLegacyProviderId(judge.providerId)
|
|
130
|
+
: judge.provider === 'ollama'
|
|
131
|
+
? 'ollama'
|
|
132
|
+
: 'codex';
|
|
133
|
+
return (judge.cloudConsent.endpoint === judge.endpoint.trim() &&
|
|
134
|
+
normalizeLegacyProviderId(judge.cloudConsent.providerId) === providerId);
|
|
135
|
+
}
|
|
136
|
+
export function isImplicitLocalJudge(judge) {
|
|
137
|
+
const providerId = judge.providerId && normalizeLegacyProviderId(judge.providerId)
|
|
138
|
+
? normalizeLegacyProviderId(judge.providerId)
|
|
139
|
+
: judge.provider === 'ollama'
|
|
140
|
+
? 'ollama'
|
|
141
|
+
: null;
|
|
142
|
+
if (providerId !== 'ollama') {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
if (judge.cloudConsent?.accepted) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
const factoryDefault = resolveJudgeFromCatalog({ providerId: 'ollama' });
|
|
149
|
+
const endpoint = judge.endpoint?.trim() ?? factoryDefault.endpoint;
|
|
150
|
+
const defaultEndpoint = factoryDefault.endpoint?.trim();
|
|
151
|
+
const endpointMatches = !judge.endpoint ||
|
|
152
|
+
endpoint === defaultEndpoint ||
|
|
153
|
+
endpoint === 'http://127.0.0.1:11434' ||
|
|
154
|
+
endpoint === 'http://localhost:11434';
|
|
155
|
+
return judge.provider === 'ollama' && judge.model === factoryDefault.model && endpointMatches;
|
|
156
|
+
}
|
|
157
|
+
export function migrateImplicitLocalJudgeIfNeeded(existingJudge, adapter) {
|
|
158
|
+
if (!isImplicitLocalJudge(existingJudge)) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
return applyFreshInitDefaults(resolveJudgeFromCatalog({ providerId: defaultJudgeProviderForAdapter(adapter) }));
|
|
75
162
|
}
|
|
76
163
|
export function assertJudgeEndpoint(judge) {
|
|
77
|
-
|
|
78
|
-
|
|
164
|
+
const providerId = judge.providerId && normalizeLegacyProviderId(judge.providerId)
|
|
165
|
+
? normalizeLegacyProviderId(judge.providerId)
|
|
166
|
+
: judge.provider === 'ollama'
|
|
167
|
+
? 'ollama'
|
|
168
|
+
: 'codex';
|
|
169
|
+
const transport = judge.endpoint?.trim()
|
|
170
|
+
? 'http'
|
|
171
|
+
: (detectJudgeRuntimeCapabilities(providerId).cliTransport ?? 'http');
|
|
172
|
+
if (catalogRequiresEndpoint(providerId, { transport }) && !judge.endpoint?.trim()) {
|
|
173
|
+
throw new JudgeEndpointRequiredError(providerId);
|
|
79
174
|
}
|
|
80
175
|
}
|
|
176
|
+
function applyFreshInitDefaults(judge) {
|
|
177
|
+
const endpoint = process.env.BELAY_JUDGE_ENDPOINT?.trim();
|
|
178
|
+
return {
|
|
179
|
+
...judge,
|
|
180
|
+
...(endpoint ? { endpoint } : {}),
|
|
181
|
+
credential: { mode: 'project' },
|
|
182
|
+
};
|
|
183
|
+
}
|
|
81
184
|
export function resolveInitJudgeConfig(input) {
|
|
82
185
|
if (input.hasExplicitJudgeFlags) {
|
|
83
186
|
const judge = resolveJudgeConfig({
|
|
84
187
|
judgeProfile: input.judgeProfile,
|
|
85
188
|
judgeProvider: input.judgeProvider,
|
|
189
|
+
judgeProviderId: input.judgeProviderId,
|
|
86
190
|
judgeModel: input.judgeModel,
|
|
87
191
|
judgeEndpoint: input.judgeEndpoint,
|
|
88
192
|
});
|
|
89
|
-
if (isCloudJudgeConfig(judge) && !input.acceptCloudJudge) {
|
|
90
|
-
throw new CloudJudgeConsentRequiredError();
|
|
91
|
-
}
|
|
92
193
|
assertJudgeEndpoint(judge);
|
|
194
|
+
if (isCloudJudgeConfig(judge) && judge.endpoint?.trim()) {
|
|
195
|
+
if (input.cloudConsentApprovalId) {
|
|
196
|
+
return applyCloudConsent(judge, {
|
|
197
|
+
by: `capability-approval:${input.cloudConsentApprovalId}`,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (input.acceptCloudJudge && input.interactiveConsent) {
|
|
201
|
+
return applyCloudConsent(judge, { by: 'tty' });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
93
204
|
return judge;
|
|
94
205
|
}
|
|
95
206
|
if (!input.isFresh && input.existingJudge) {
|
|
96
|
-
|
|
97
|
-
|
|
207
|
+
return resolveJudgeConfig({ existingJudge: input.existingJudge });
|
|
208
|
+
}
|
|
209
|
+
const adapter = input.adapter ?? 'cursor';
|
|
210
|
+
const judge = resolveJudgeConfig({ judgeProviderId: defaultJudgeProviderForAdapter(adapter) });
|
|
211
|
+
return applyFreshInitDefaults(judge);
|
|
212
|
+
}
|
|
213
|
+
export function applyCloudConsent(judge, params) {
|
|
214
|
+
const providerId = judge.providerId && normalizeLegacyProviderId(judge.providerId)
|
|
215
|
+
? normalizeLegacyProviderId(judge.providerId)
|
|
216
|
+
: 'codex';
|
|
217
|
+
const endpoint = judge.endpoint?.trim();
|
|
218
|
+
if (!endpoint) {
|
|
98
219
|
return judge;
|
|
99
220
|
}
|
|
100
|
-
|
|
221
|
+
const cloudConsent = {
|
|
222
|
+
accepted: true,
|
|
223
|
+
at: new Date().toISOString(),
|
|
224
|
+
providerId,
|
|
225
|
+
endpoint,
|
|
226
|
+
by: params.by,
|
|
227
|
+
};
|
|
228
|
+
return { ...judge, cloudConsent };
|
|
229
|
+
}
|
|
230
|
+
export function resolveJudgeUsePatch(existing, options) {
|
|
231
|
+
const warnings = [];
|
|
232
|
+
const errors = [];
|
|
233
|
+
const normalizedId = normalizeLegacyProviderId(String(options.providerId));
|
|
234
|
+
if (!normalizedId) {
|
|
235
|
+
errors.push(`Unknown judge provider id: ${options.providerId}`);
|
|
236
|
+
return { judge: existing, warnings, errors };
|
|
237
|
+
}
|
|
238
|
+
const spec = getJudgeProviderSpec(normalizedId);
|
|
239
|
+
if (!spec) {
|
|
240
|
+
errors.push(`Unknown judge provider id: ${options.providerId}`);
|
|
241
|
+
return { judge: existing, warnings, errors };
|
|
242
|
+
}
|
|
243
|
+
let judge = resolveJudgeFromCatalog({
|
|
244
|
+
providerId: normalizedId,
|
|
245
|
+
model: options.model ?? (existing.providerId === normalizedId ? existing.model : undefined),
|
|
246
|
+
endpoint: options.endpoint !== undefined
|
|
247
|
+
? options.endpoint
|
|
248
|
+
: existing.providerId === normalizedId
|
|
249
|
+
? existing.endpoint
|
|
250
|
+
: undefined,
|
|
251
|
+
timeoutMs: options.timeoutMs ?? existing.timeoutMs,
|
|
252
|
+
keepAlive: existing.keepAlive,
|
|
253
|
+
});
|
|
254
|
+
if (catalogRequiresEndpoint(normalizedId, {
|
|
255
|
+
transport: judge.endpoint?.trim()
|
|
256
|
+
? 'http'
|
|
257
|
+
: (detectJudgeRuntimeCapabilities(normalizedId).cliTransport ?? 'unavailable'),
|
|
258
|
+
}) &&
|
|
259
|
+
!judge.endpoint?.trim()) {
|
|
260
|
+
errors.push(`${normalizedId} requires --endpoint for HTTP transport.`);
|
|
261
|
+
}
|
|
262
|
+
if (options.credentialMode === 'apiKey') {
|
|
263
|
+
judge = {
|
|
264
|
+
...judge,
|
|
265
|
+
credential: options.keyEnv
|
|
266
|
+
? { mode: 'apiKey', ref: `env:${options.keyEnv}` }
|
|
267
|
+
: { mode: 'apiKey', ref: 'store:judge' },
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
else if (options.credentialMode === 'project') {
|
|
271
|
+
judge = { ...judge, credential: { mode: 'project' } };
|
|
272
|
+
}
|
|
273
|
+
else if (existing.credential) {
|
|
274
|
+
judge = { ...judge, credential: existing.credential };
|
|
275
|
+
}
|
|
276
|
+
const needsNewConsent = spec.isCloud &&
|
|
277
|
+
(!existing.cloudConsent?.accepted ||
|
|
278
|
+
existing.cloudConsent.endpoint !== judge.endpoint?.trim() ||
|
|
279
|
+
normalizeLegacyProviderId(existing.cloudConsent.providerId) !== normalizedId);
|
|
280
|
+
if (spec.isCloud && needsNewConsent) {
|
|
281
|
+
if (options.cloudConsentApprovalId) {
|
|
282
|
+
judge = applyCloudConsent(judge, {
|
|
283
|
+
by: `capability-approval:${options.cloudConsentApprovalId}`,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
else if (options.acceptCloud &&
|
|
287
|
+
options.interactiveTTY &&
|
|
288
|
+
options.interactiveConsentApproved) {
|
|
289
|
+
judge = applyCloudConsent(judge, { by: 'tty' });
|
|
290
|
+
}
|
|
291
|
+
else if (options.acceptCloud && options.interactiveTTY) {
|
|
292
|
+
warnings.push('Cloud consent not recorded (--accept-cloud requires confirmation).');
|
|
293
|
+
}
|
|
294
|
+
else if (options.acceptCloud && !options.interactiveTTY) {
|
|
295
|
+
warnings.push('Cloud consent not recorded in non-interactive mode. Pass --cloud-consent-approval-id after judge_cloud_consent approval.');
|
|
296
|
+
}
|
|
297
|
+
else if (!existing.cloudConsent?.accepted) {
|
|
298
|
+
warnings.push('Cloud judge will remain disabled until consent is recorded.');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else if (existing.cloudConsent?.accepted && spec.isCloud) {
|
|
302
|
+
judge = { ...judge, cloudConsent: existing.cloudConsent };
|
|
303
|
+
}
|
|
304
|
+
return { judge, warnings, errors };
|
|
101
305
|
}
|
|
306
|
+
// Re-export for callers that validate provider ids
|
|
307
|
+
export { isJudgeProviderId };
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { BelayConfigV4 } from './config.js';
|
|
2
|
+
import { type CheckJudgeModelPresenceResult, type JudgeModelDiscoveryDeps } from './judge-model-discovery.js';
|
|
2
3
|
export interface JudgeDoctorResult {
|
|
3
4
|
issues: string[];
|
|
4
5
|
warnings: string[];
|
|
5
6
|
notes: string[];
|
|
7
|
+
modelCheck?: CheckJudgeModelPresenceResult;
|
|
6
8
|
}
|
|
7
|
-
export
|
|
9
|
+
export interface DiagnoseJudgeOptions {
|
|
10
|
+
discoveryDeps?: JudgeModelDiscoveryDeps;
|
|
11
|
+
}
|
|
12
|
+
export declare function diagnoseJudge(config: BelayConfigV4, repoRoot?: string, options?: DiagnoseJudgeOptions): Promise<JudgeDoctorResult>;
|