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.
Files changed (90) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +328 -301
  3. package/cordis.patch.yml +4 -4
  4. package/lib/caller-BWwSVNZf.js.map +1 -0
  5. package/lib/client.js +176 -14
  6. package/lib/client.js.map +1 -0
  7. package/lib/core.js.map +1 -0
  8. package/lib/index.js +400 -51
  9. package/lib/index.js.map +1 -0
  10. package/lib/types/auto.d.ts.map +1 -0
  11. package/lib/types/auto.js +8 -2
  12. package/lib/types/auto.js.map +1 -0
  13. package/lib/types/cache.d.ts.map +1 -0
  14. package/lib/types/cache.js.map +1 -0
  15. package/lib/types/caller.d.ts.map +1 -0
  16. package/lib/types/caller.js.map +1 -0
  17. package/lib/types/client-i18n.d.ts +27 -0
  18. package/lib/types/client-i18n.d.ts.map +1 -0
  19. package/lib/types/client-i18n.js +18 -0
  20. package/lib/types/client-i18n.js.map +1 -0
  21. package/lib/types/client.d.ts +15 -2
  22. package/lib/types/client.d.ts.map +1 -0
  23. package/lib/types/client.js +137 -10
  24. package/lib/types/client.js.map +1 -0
  25. package/lib/types/config.d.ts +4 -0
  26. package/lib/types/config.d.ts.map +1 -0
  27. package/lib/types/config.js +5 -3
  28. package/lib/types/config.js.map +1 -0
  29. package/lib/types/core.d.ts.map +1 -0
  30. package/lib/types/core.js.map +1 -0
  31. package/lib/types/engine.d.ts.map +1 -0
  32. package/lib/types/engine.js.map +1 -0
  33. package/lib/types/images.d.ts.map +1 -0
  34. package/lib/types/images.js.map +1 -0
  35. package/lib/types/index.d.ts +2 -0
  36. package/lib/types/index.d.ts.map +1 -0
  37. package/lib/types/index.js +162 -9
  38. package/lib/types/index.js.map +1 -0
  39. package/lib/types/plan-gate.d.ts +27 -0
  40. package/lib/types/plan-gate.d.ts.map +1 -0
  41. package/lib/types/plan-gate.js +60 -0
  42. package/lib/types/plan-gate.js.map +1 -0
  43. package/lib/types/router.d.ts +28 -32
  44. package/lib/types/router.d.ts.map +1 -0
  45. package/lib/types/router.js +41 -9
  46. package/lib/types/router.js.map +1 -0
  47. package/lib/types/session.d.ts +11 -0
  48. package/lib/types/session.d.ts.map +1 -0
  49. package/lib/types/session.js +41 -11
  50. package/lib/types/session.js.map +1 -0
  51. package/lib/types/statistics.d.ts.map +1 -0
  52. package/lib/types/statistics.js.map +1 -0
  53. package/lib/types/team-gate.d.ts +20 -0
  54. package/lib/types/team-gate.d.ts.map +1 -0
  55. package/lib/types/team-gate.js +59 -0
  56. package/lib/types/team-gate.js.map +1 -0
  57. package/lib/types/top-logprobs.d.ts.map +1 -0
  58. package/lib/types/top-logprobs.js.map +1 -0
  59. package/lib/types/topic-storage.d.ts.map +1 -0
  60. package/lib/types/topic-storage.js.map +1 -0
  61. package/package.json +114 -112
  62. package/src/auto.test.ts +95 -86
  63. package/src/auto.ts +140 -133
  64. package/src/cache.ts +115 -115
  65. package/src/caller.test.ts +34 -34
  66. package/src/caller.ts +151 -151
  67. package/src/client-i18n.ts +18 -0
  68. package/src/client.tsx +383 -213
  69. package/src/config.ts +189 -183
  70. package/src/core.test.ts +71 -71
  71. package/src/core.ts +205 -205
  72. package/src/engine.test.ts +136 -136
  73. package/src/engine.ts +140 -140
  74. package/src/images.ts +33 -33
  75. package/src/index.ts +394 -247
  76. package/src/parity.test.ts +85 -85
  77. package/src/plan-gate.test.ts +56 -0
  78. package/src/plan-gate.ts +66 -0
  79. package/src/router.test.ts +107 -89
  80. package/src/router.ts +361 -309
  81. package/src/session.test.ts +71 -36
  82. package/src/session.ts +132 -103
  83. package/src/statistics.test.ts +80 -80
  84. package/src/statistics.ts +328 -328
  85. package/src/team-gate.test.ts +92 -0
  86. package/src/team-gate.ts +80 -0
  87. package/src/top-logprobs.test.ts +84 -84
  88. package/src/top-logprobs.ts +153 -153
  89. package/src/topic-storage.test.ts +31 -31
  90. 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 } }
@@ -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 }