dsh-llm-verifier 0.1.13 → 0.1.16
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/LICENSE +22 -22
- package/README.md +328 -301
- package/cordis.patch.yml +4 -4
- package/lib/caller-BWwSVNZf.js.map +1 -0
- package/lib/client.js +176 -14
- package/lib/client.js.map +1 -0
- package/lib/core.js.map +1 -0
- package/lib/index.js +400 -51
- package/lib/index.js.map +1 -0
- package/lib/types/auto.d.ts.map +1 -0
- package/lib/types/auto.js +8 -2
- package/lib/types/auto.js.map +1 -0
- package/lib/types/cache.d.ts.map +1 -0
- package/lib/types/cache.js.map +1 -0
- package/lib/types/caller.d.ts.map +1 -0
- package/lib/types/caller.js.map +1 -0
- package/lib/types/client-i18n.d.ts +27 -0
- package/lib/types/client-i18n.d.ts.map +1 -0
- package/lib/types/client-i18n.js +18 -0
- package/lib/types/client-i18n.js.map +1 -0
- package/lib/types/client.d.ts +15 -2
- package/lib/types/client.d.ts.map +1 -0
- package/lib/types/client.js +137 -10
- package/lib/types/client.js.map +1 -0
- package/lib/types/config.d.ts +4 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +5 -3
- package/lib/types/config.js.map +1 -0
- package/lib/types/core.d.ts.map +1 -0
- package/lib/types/core.js.map +1 -0
- package/lib/types/engine.d.ts.map +1 -0
- package/lib/types/engine.js.map +1 -0
- package/lib/types/images.d.ts.map +1 -0
- package/lib/types/images.js.map +1 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +162 -9
- package/lib/types/index.js.map +1 -0
- package/lib/types/plan-gate.d.ts +27 -0
- package/lib/types/plan-gate.d.ts.map +1 -0
- package/lib/types/plan-gate.js +60 -0
- package/lib/types/plan-gate.js.map +1 -0
- package/lib/types/router.d.ts +28 -32
- package/lib/types/router.d.ts.map +1 -0
- package/lib/types/router.js +41 -9
- package/lib/types/router.js.map +1 -0
- package/lib/types/session.d.ts +11 -0
- package/lib/types/session.d.ts.map +1 -0
- package/lib/types/session.js +41 -11
- package/lib/types/session.js.map +1 -0
- package/lib/types/statistics.d.ts.map +1 -0
- package/lib/types/statistics.js.map +1 -0
- package/lib/types/team-gate.d.ts +20 -0
- package/lib/types/team-gate.d.ts.map +1 -0
- package/lib/types/team-gate.js +59 -0
- package/lib/types/team-gate.js.map +1 -0
- package/lib/types/top-logprobs.d.ts.map +1 -0
- package/lib/types/top-logprobs.js.map +1 -0
- package/lib/types/topic-storage.d.ts.map +1 -0
- package/lib/types/topic-storage.js.map +1 -0
- package/package.json +114 -112
- package/src/auto.test.ts +95 -86
- package/src/auto.ts +140 -133
- package/src/cache.ts +115 -115
- package/src/caller.test.ts +34 -34
- package/src/caller.ts +151 -151
- package/src/client-i18n.ts +18 -0
- package/src/client.tsx +383 -213
- package/src/config.ts +189 -183
- package/src/core.test.ts +71 -71
- package/src/core.ts +205 -205
- package/src/engine.test.ts +136 -136
- package/src/engine.ts +140 -140
- package/src/images.ts +33 -33
- package/src/index.ts +394 -247
- package/src/parity.test.ts +85 -85
- package/src/plan-gate.test.ts +56 -0
- package/src/plan-gate.ts +66 -0
- package/src/router.test.ts +107 -89
- package/src/router.ts +361 -309
- package/src/session.test.ts +71 -36
- package/src/session.ts +132 -103
- package/src/statistics.test.ts +80 -80
- package/src/statistics.ts +328 -328
- package/src/team-gate.test.ts +92 -0
- package/src/team-gate.ts +80 -0
- package/src/top-logprobs.test.ts +84 -84
- package/src/top-logprobs.ts +153 -153
- package/src/topic-storage.test.ts +31 -31
- package/src/topic-storage.ts +42 -42
package/src/caller.ts
CHANGED
|
@@ -13,154 +13,154 @@ function deepFreeze<T>(value: T): T {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
return value
|
|
16
|
-
}
|
|
17
|
-
import type { AttachmentStore } from '@deepseek-ai/dsh-attachment'
|
|
18
|
-
import type { CompletionLogprobs } from './core.ts'
|
|
19
|
-
import { TopLogprobCapabilityCache, TopLogprobsUnsupportedError, callTopLogprobs, resolveTopLogprobRoute } from './top-logprobs.ts'
|
|
20
|
-
import type { Context } from '@deepseek-ai/cordis'
|
|
21
|
-
|
|
22
|
-
export interface VerifierClientConfig {
|
|
23
|
-
ctx: Context
|
|
24
|
-
llm: LlmRuntime
|
|
25
|
-
attachments: AttachmentStore
|
|
26
|
-
topLogprobCapabilities: TopLogprobCapabilityCache
|
|
27
|
-
provider: string
|
|
28
|
-
model: string
|
|
29
|
-
reasoningEffort?: string
|
|
30
|
-
maxTokens: number
|
|
31
|
-
timeoutMs: number
|
|
32
|
-
maxRetries: number
|
|
33
|
-
retryBaseDelayMs: number
|
|
34
|
-
limiter?: RequestLimiter
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface VerifierImage {
|
|
38
|
-
data: Uint8Array
|
|
39
|
-
mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface UsageStats {
|
|
43
|
-
calls: number
|
|
44
|
-
attempts: number
|
|
45
|
-
retries: number
|
|
46
|
-
inputTokens: number
|
|
47
|
-
cachedInputTokens: number
|
|
48
|
-
outputTokens: number
|
|
49
|
-
reasoningTokens: number
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export type ScoringMode = 'top-logprobs' | 'explicit-tag'
|
|
53
|
-
export interface VerifierCompletion extends CompletionLogprobs { usage: UsageStats; scoringMode: ScoringMode }
|
|
54
|
-
|
|
55
|
-
function failureMessage(finish: FinishReason): string | undefined {
|
|
56
|
-
if (finish.kind === 'error' || finish.kind === 'aborted') return finish.failure.message
|
|
57
|
-
if (finish.kind === 'max-tokens') return 'verifier response reached max tokens before completing its answer'
|
|
58
|
-
return undefined
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function delay(ms: number, signal?: AbortSignal): Promise<void> {
|
|
62
|
-
if (signal?.aborted) throw signal.reason
|
|
63
|
-
await new Promise<void>((resolve, reject) => {
|
|
64
|
-
const timer = setTimeout(resolve, ms)
|
|
65
|
-
const abort = () => { clearTimeout(timer); reject(signal?.reason) }
|
|
66
|
-
signal?.addEventListener('abort', abort, { once: true })
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function usage(attempts: number, value = {} as { inputTokens?: number; outputTokens?: number; cacheReadTokens?: number; cacheWriteTokens?: number; reasoningTokens?: number }): UsageStats {
|
|
71
|
-
return { calls: 1, attempts, retries: attempts - 1, inputTokens: value.inputTokens ?? 0, cachedInputTokens: (value.cacheReadTokens ?? 0) + (value.cacheWriteTokens ?? 0), outputTokens: value.outputTokens ?? 0, reasoningTokens: value.reasoningTokens ?? 0 }
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async function callExplicitTag(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
75
|
-
let attempt = 0
|
|
76
|
-
while (true) {
|
|
77
|
-
attempt += 1
|
|
78
|
-
const controller = new AbortController()
|
|
79
|
-
const timeout = setTimeout(() => controller.abort(new Error('llm-verifier: request timed out')), config.timeoutMs)
|
|
80
|
-
const abort = () => controller.abort(signal?.reason)
|
|
81
|
-
signal?.addEventListener('abort', abort, { once: true })
|
|
82
|
-
try {
|
|
83
|
-
const content: ContentBlock[] = [{ type: 'text', text: prompt }]
|
|
84
|
-
for (const image of images ?? []) {
|
|
85
|
-
const ref = await config.attachments.saveImage({ data: image.data, mediaType: image.mediaType })
|
|
86
|
-
content.push({ type: 'image', attachment: ref })
|
|
87
|
-
}
|
|
88
|
-
const messages = [createUserMessage({ content, source: { kind: 'plugin', plugin: 'dsh-llm-verifier' } })]
|
|
89
|
-
const assembler = new BlockAssembler()
|
|
90
|
-
const options = deepFreeze({
|
|
91
|
-
provider: config.provider,
|
|
92
|
-
model: config.model,
|
|
93
|
-
...(config.reasoningEffort ? { reasoningEffort: ReasoningEffortId(config.reasoningEffort) } : {}),
|
|
94
|
-
messages,
|
|
95
|
-
maxTokens: config.maxTokens,
|
|
96
|
-
temperature: 1,
|
|
97
|
-
signal: controller.signal,
|
|
98
|
-
})
|
|
99
|
-
for await (const chunk of config.llm.stream(options)) assembler.push(chunk)
|
|
100
|
-
const failed = failureMessage(assembler.finish)
|
|
101
|
-
if (failed !== undefined) throw new Error('llm-verifier: model call failed: ' + failed)
|
|
102
|
-
const text = assembler.blocks().filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text').map(block => block.text).join('')
|
|
103
|
-
if (!text.trim()) throw new Error('llm-verifier: selected DSH model produced no text')
|
|
104
|
-
// DSH adapters expose provider-neutral text/usage but not top-logprob candidates.
|
|
105
|
-
// extractScore() therefore uses the model's explicit final A–T tags.
|
|
106
|
-
return { text, tokens: [], positions: [], scoringMode: 'explicit-tag', usage: usage(attempt, assembler.usage) }
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (signal?.aborted) throw signal.reason
|
|
109
|
-
if (attempt > config.maxRetries || !(error instanceof Error) || !/rate|quota|timeout|timed out|temporar|network|fetch|socket|5\d\d/i.test(error.message)) throw error
|
|
110
|
-
await delay(Math.min(30000, config.retryBaseDelayMs * 2 ** (attempt - 1) * (0.8 + Math.random() * 0.4)), signal)
|
|
111
|
-
} finally {
|
|
112
|
-
clearTimeout(timeout)
|
|
113
|
-
signal?.removeEventListener('abort', abort)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export class RequestLimiter {
|
|
119
|
-
private active = 0
|
|
120
|
-
private readonly queue: Array<() => void> = []
|
|
121
|
-
constructor(readonly limit: number) { if (!Number.isSafeInteger(limit) || limit < 1) throw new Error('llm-verifier: request concurrency limit must be a positive integer') }
|
|
122
|
-
async run<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {
|
|
123
|
-
if (this.active >= this.limit) await new Promise<void>((resolve, reject) => {
|
|
124
|
-
const enter = () => { signal?.removeEventListener('abort', abort); resolve() }
|
|
125
|
-
const abort = () => { const index = this.queue.indexOf(enter); if (index >= 0) this.queue.splice(index, 1); reject(signal?.reason) }
|
|
126
|
-
this.queue.push(enter); signal?.addEventListener('abort', abort, { once: true })
|
|
127
|
-
})
|
|
128
|
-
if (signal?.aborted) throw signal.reason
|
|
129
|
-
this.active += 1
|
|
130
|
-
try { return await operation() } finally { this.active -= 1; this.queue.shift()?.() }
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/** Best-effort pre-call channel prediction for cache identity only; callAutomatic() stays the runtime source of truth. */
|
|
135
|
-
export async function predictScoringChannel(config: VerifierClientConfig): Promise<ScoringMode> {
|
|
136
|
-
await config.topLogprobCapabilities.ensureLoaded()
|
|
137
|
-
return config.topLogprobCapabilities.isUnsupported(config.provider, config.model) ? 'explicit-tag' : 'top-logprobs'
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async function callAutomatic(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
141
|
-
await config.topLogprobCapabilities.ensureLoaded()
|
|
142
|
-
if (!config.topLogprobCapabilities.isUnsupported(config.provider, config.model)) {
|
|
143
|
-
const route = await resolveTopLogprobRoute(config.ctx, config.provider)
|
|
144
|
-
if (route !== undefined) {
|
|
145
|
-
try { return await callTopLogprobs(route, config.model, prompt, config.maxTokens, config.reasoningEffort, signal, images) }
|
|
146
|
-
catch (error) {
|
|
147
|
-
if (!(error instanceof TopLogprobsUnsupportedError)) throw error
|
|
148
|
-
config.topLogprobCapabilities.markUnsupported(config.provider, config.model)
|
|
149
|
-
}
|
|
150
|
-
} else config.topLogprobCapabilities.markUnsupported(config.provider, config.model)
|
|
151
|
-
}
|
|
152
|
-
return callExplicitTag(config, prompt, signal, images)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export async function callVerifier(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
156
|
-
const invoke = () => callAutomatic(config, prompt, signal, images)
|
|
157
|
-
return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/** Plain-text verifier call for conservative JSON routing; probability labels are intentionally bypassed. */
|
|
161
|
-
export async function callVerifierText(config: VerifierClientConfig, prompt: string, signal?: AbortSignal): Promise<VerifierCompletion> {
|
|
162
|
-
const invoke = () => callExplicitTag(config, prompt, signal)
|
|
163
|
-
return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)
|
|
164
|
-
}
|
|
165
|
-
export function addUsage(target: UsageStats, source: UsageStats): void { for (const key of ['calls', 'attempts', 'retries', 'inputTokens', 'cachedInputTokens', 'outputTokens', 'reasoningTokens'] as const) target[key] += source[key] }
|
|
166
|
-
export function emptyUsage(): UsageStats { return { calls: 0, attempts: 0, retries: 0, inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningTokens: 0 } }
|
|
16
|
+
}
|
|
17
|
+
import type { AttachmentStore } from '@deepseek-ai/dsh-attachment'
|
|
18
|
+
import type { CompletionLogprobs } from './core.ts'
|
|
19
|
+
import { TopLogprobCapabilityCache, TopLogprobsUnsupportedError, callTopLogprobs, resolveTopLogprobRoute } from './top-logprobs.ts'
|
|
20
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
21
|
+
|
|
22
|
+
export interface VerifierClientConfig {
|
|
23
|
+
ctx: Context
|
|
24
|
+
llm: LlmRuntime
|
|
25
|
+
attachments: AttachmentStore
|
|
26
|
+
topLogprobCapabilities: TopLogprobCapabilityCache
|
|
27
|
+
provider: string
|
|
28
|
+
model: string
|
|
29
|
+
reasoningEffort?: string
|
|
30
|
+
maxTokens: number
|
|
31
|
+
timeoutMs: number
|
|
32
|
+
maxRetries: number
|
|
33
|
+
retryBaseDelayMs: number
|
|
34
|
+
limiter?: RequestLimiter
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface VerifierImage {
|
|
38
|
+
data: Uint8Array
|
|
39
|
+
mediaType: 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface UsageStats {
|
|
43
|
+
calls: number
|
|
44
|
+
attempts: number
|
|
45
|
+
retries: number
|
|
46
|
+
inputTokens: number
|
|
47
|
+
cachedInputTokens: number
|
|
48
|
+
outputTokens: number
|
|
49
|
+
reasoningTokens: number
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type ScoringMode = 'top-logprobs' | 'explicit-tag'
|
|
53
|
+
export interface VerifierCompletion extends CompletionLogprobs { usage: UsageStats; scoringMode: ScoringMode }
|
|
54
|
+
|
|
55
|
+
function failureMessage(finish: FinishReason): string | undefined {
|
|
56
|
+
if (finish.kind === 'error' || finish.kind === 'aborted') return finish.failure.message
|
|
57
|
+
if (finish.kind === 'max-tokens') return 'verifier response reached max tokens before completing its answer'
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function delay(ms: number, signal?: AbortSignal): Promise<void> {
|
|
62
|
+
if (signal?.aborted) throw signal.reason
|
|
63
|
+
await new Promise<void>((resolve, reject) => {
|
|
64
|
+
const timer = setTimeout(resolve, ms)
|
|
65
|
+
const abort = () => { clearTimeout(timer); reject(signal?.reason) }
|
|
66
|
+
signal?.addEventListener('abort', abort, { once: true })
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function usage(attempts: number, value = {} as { inputTokens?: number; outputTokens?: number; cacheReadTokens?: number; cacheWriteTokens?: number; reasoningTokens?: number }): UsageStats {
|
|
71
|
+
return { calls: 1, attempts, retries: attempts - 1, inputTokens: value.inputTokens ?? 0, cachedInputTokens: (value.cacheReadTokens ?? 0) + (value.cacheWriteTokens ?? 0), outputTokens: value.outputTokens ?? 0, reasoningTokens: value.reasoningTokens ?? 0 }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function callExplicitTag(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
75
|
+
let attempt = 0
|
|
76
|
+
while (true) {
|
|
77
|
+
attempt += 1
|
|
78
|
+
const controller = new AbortController()
|
|
79
|
+
const timeout = setTimeout(() => controller.abort(new Error('llm-verifier: request timed out')), config.timeoutMs)
|
|
80
|
+
const abort = () => controller.abort(signal?.reason)
|
|
81
|
+
signal?.addEventListener('abort', abort, { once: true })
|
|
82
|
+
try {
|
|
83
|
+
const content: ContentBlock[] = [{ type: 'text', text: prompt }]
|
|
84
|
+
for (const image of images ?? []) {
|
|
85
|
+
const ref = await config.attachments.saveImage({ data: image.data, mediaType: image.mediaType })
|
|
86
|
+
content.push({ type: 'image', attachment: ref })
|
|
87
|
+
}
|
|
88
|
+
const messages = [createUserMessage({ content, source: { kind: 'plugin', plugin: 'dsh-llm-verifier' } })]
|
|
89
|
+
const assembler = new BlockAssembler()
|
|
90
|
+
const options = deepFreeze({
|
|
91
|
+
provider: config.provider,
|
|
92
|
+
model: config.model,
|
|
93
|
+
...(config.reasoningEffort ? { reasoningEffort: ReasoningEffortId(config.reasoningEffort) } : {}),
|
|
94
|
+
messages,
|
|
95
|
+
maxTokens: config.maxTokens,
|
|
96
|
+
temperature: 1,
|
|
97
|
+
signal: controller.signal,
|
|
98
|
+
})
|
|
99
|
+
for await (const chunk of config.llm.stream(options)) assembler.push(chunk)
|
|
100
|
+
const failed = failureMessage(assembler.finish)
|
|
101
|
+
if (failed !== undefined) throw new Error('llm-verifier: model call failed: ' + failed)
|
|
102
|
+
const text = assembler.blocks().filter((block): block is Extract<ContentBlock, { type: 'text' }> => block.type === 'text').map(block => block.text).join('')
|
|
103
|
+
if (!text.trim()) throw new Error('llm-verifier: selected DSH model produced no text')
|
|
104
|
+
// DSH adapters expose provider-neutral text/usage but not top-logprob candidates.
|
|
105
|
+
// extractScore() therefore uses the model's explicit final A–T tags.
|
|
106
|
+
return { text, tokens: [], positions: [], scoringMode: 'explicit-tag', usage: usage(attempt, assembler.usage) }
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (signal?.aborted) throw signal.reason
|
|
109
|
+
if (attempt > config.maxRetries || !(error instanceof Error) || !/rate|quota|timeout|timed out|temporar|network|fetch|socket|5\d\d/i.test(error.message)) throw error
|
|
110
|
+
await delay(Math.min(30000, config.retryBaseDelayMs * 2 ** (attempt - 1) * (0.8 + Math.random() * 0.4)), signal)
|
|
111
|
+
} finally {
|
|
112
|
+
clearTimeout(timeout)
|
|
113
|
+
signal?.removeEventListener('abort', abort)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export class RequestLimiter {
|
|
119
|
+
private active = 0
|
|
120
|
+
private readonly queue: Array<() => void> = []
|
|
121
|
+
constructor(readonly limit: number) { if (!Number.isSafeInteger(limit) || limit < 1) throw new Error('llm-verifier: request concurrency limit must be a positive integer') }
|
|
122
|
+
async run<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {
|
|
123
|
+
if (this.active >= this.limit) await new Promise<void>((resolve, reject) => {
|
|
124
|
+
const enter = () => { signal?.removeEventListener('abort', abort); resolve() }
|
|
125
|
+
const abort = () => { const index = this.queue.indexOf(enter); if (index >= 0) this.queue.splice(index, 1); reject(signal?.reason) }
|
|
126
|
+
this.queue.push(enter); signal?.addEventListener('abort', abort, { once: true })
|
|
127
|
+
})
|
|
128
|
+
if (signal?.aborted) throw signal.reason
|
|
129
|
+
this.active += 1
|
|
130
|
+
try { return await operation() } finally { this.active -= 1; this.queue.shift()?.() }
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Best-effort pre-call channel prediction for cache identity only; callAutomatic() stays the runtime source of truth. */
|
|
135
|
+
export async function predictScoringChannel(config: VerifierClientConfig): Promise<ScoringMode> {
|
|
136
|
+
await config.topLogprobCapabilities.ensureLoaded()
|
|
137
|
+
return config.topLogprobCapabilities.isUnsupported(config.provider, config.model) ? 'explicit-tag' : 'top-logprobs'
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function callAutomatic(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
141
|
+
await config.topLogprobCapabilities.ensureLoaded()
|
|
142
|
+
if (!config.topLogprobCapabilities.isUnsupported(config.provider, config.model)) {
|
|
143
|
+
const route = await resolveTopLogprobRoute(config.ctx, config.provider)
|
|
144
|
+
if (route !== undefined) {
|
|
145
|
+
try { return await callTopLogprobs(route, config.model, prompt, config.maxTokens, config.reasoningEffort, signal, images) }
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (!(error instanceof TopLogprobsUnsupportedError)) throw error
|
|
148
|
+
config.topLogprobCapabilities.markUnsupported(config.provider, config.model)
|
|
149
|
+
}
|
|
150
|
+
} else config.topLogprobCapabilities.markUnsupported(config.provider, config.model)
|
|
151
|
+
}
|
|
152
|
+
return callExplicitTag(config, prompt, signal, images)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function callVerifier(config: VerifierClientConfig, prompt: string, signal?: AbortSignal, images?: readonly VerifierImage[]): Promise<VerifierCompletion> {
|
|
156
|
+
const invoke = () => callAutomatic(config, prompt, signal, images)
|
|
157
|
+
return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Plain-text verifier call for conservative JSON routing; probability labels are intentionally bypassed. */
|
|
161
|
+
export async function callVerifierText(config: VerifierClientConfig, prompt: string, signal?: AbortSignal): Promise<VerifierCompletion> {
|
|
162
|
+
const invoke = () => callExplicitTag(config, prompt, signal)
|
|
163
|
+
return config.limiter === undefined ? invoke() : config.limiter.run(invoke, signal)
|
|
164
|
+
}
|
|
165
|
+
export function addUsage(target: UsageStats, source: UsageStats): void { for (const key of ['calls', 'attempts', 'retries', 'inputTokens', 'cachedInputTokens', 'outputTokens', 'reasoningTokens'] as const) target[key] += source[key] }
|
|
166
|
+
export function emptyUsage(): UsageStats { return { calls: 0, attempts: 0, retries: 0, inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningTokens: 0 } }
|
package/src/client-i18n.ts
CHANGED
|
@@ -151,6 +151,15 @@ export const zh = {
|
|
|
151
151
|
|
|
152
152
|
// Slot label
|
|
153
153
|
'slot.statistics': '工具统计',
|
|
154
|
+
'slot.globalDashboard': 'Verifier 看板',
|
|
155
|
+
'global.panelTitle': 'LLM Verifier 全局监控中心',
|
|
156
|
+
'global.panelIntro': '跨会话全局统计、裁判模型效能大盘与任务验收总览。',
|
|
157
|
+
'guide.verifier.title': 'Verifier 统计',
|
|
158
|
+
'guide.verifier.desc': '大模型复核工具调用、耗时与成本统计',
|
|
159
|
+
'field.autoVerifyTeamTasks.title': '自动验收 Team 任务',
|
|
160
|
+
'field.autoVerifyTeamTasks.help': '当 Agent Teams 中的任务状态变更或进入完成状态时,自动路由进度追踪与任务验收。',
|
|
161
|
+
'field.autoVerifyPlanMode.title': '计划模式自动预审',
|
|
162
|
+
'field.autoVerifyPlanMode.help': '在 Agent 调用 exit_plan_mode 提交计划交付人类评审前,自动对计划完整度与风险进行独立预审。',
|
|
154
163
|
}
|
|
155
164
|
|
|
156
165
|
export type I18nDict = typeof zh
|
|
@@ -306,6 +315,15 @@ export const en: I18nDict = {
|
|
|
306
315
|
|
|
307
316
|
// Slot label
|
|
308
317
|
'slot.statistics': 'Statistics',
|
|
318
|
+
'slot.globalDashboard': 'Verifier Dashboard',
|
|
319
|
+
'global.panelTitle': 'LLM Verifier Global Dashboard',
|
|
320
|
+
'global.panelIntro': 'Cross-session statistics, judge model metrics, and task acceptance overview.',
|
|
321
|
+
'guide.verifier.title': 'Verifier Stats',
|
|
322
|
+
'guide.verifier.desc': 'LLM verifier tool calls, duration and cost statistics',
|
|
323
|
+
'field.autoVerifyTeamTasks.title': 'Verify Team Tasks',
|
|
324
|
+
'field.autoVerifyTeamTasks.help': 'Automatically route progress and verify tasks when Agent Teams task status changes or completes.',
|
|
325
|
+
'field.autoVerifyPlanMode.title': 'Plan Mode Pre-verification',
|
|
326
|
+
'field.autoVerifyPlanMode.help': 'Automatically pre-verify plan feasibility and risks before exit_plan_mode presents it for user review.',
|
|
309
327
|
}
|
|
310
328
|
|
|
311
329
|
export const dictionaries = { zh, en }
|