@linxin666/dsh-client-ui-task-board 0.4.3 → 0.4.5
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.i18n.yaml +2 -2
- package/README.md +56 -18
- package/README.zh.md +56 -18
- package/lib/client.js +6242 -958
- package/lib/client.js.map +1 -1
- package/lib/index.js +3475 -234
- package/lib/types/client/PluginSettingsCard.d.ts +7 -0
- package/lib/types/client/TaskBoardSettingsCard.d.ts +19 -3
- package/lib/types/client/board/ClampedMarkdown.d.ts +3 -0
- package/lib/types/client/board/ConfirmDialog.d.ts +4 -1
- package/lib/types/client/board/EditTaskModal.d.ts +5 -2
- package/lib/types/client/board/LinkSubtaskModal.d.ts +5 -2
- package/lib/types/client/board/NewTaskModal.d.ts +4 -1
- package/lib/types/client/board/TagManagerModal.d.ts +26 -0
- package/lib/types/client/board/TaskBoard.d.ts +10 -1
- package/lib/types/client/board/TaskCard.d.ts +14 -1
- package/lib/types/client/board/TaskDetail.d.ts +3 -1
- package/lib/types/client/board/TaskForm.d.ts +23 -2
- package/lib/types/client/board/VerificationReport.d.ts +23 -0
- package/lib/types/client/board/card-view.d.ts +113 -0
- package/lib/types/client/board/icons.d.ts +32 -0
- package/lib/types/client/board/overlay.d.ts +69 -0
- package/lib/types/client/board/preset-label.d.ts +22 -0
- package/lib/types/client/board/status-key.d.ts +15 -0
- package/lib/types/client/board/task-markdown.d.ts +19 -0
- package/lib/types/client/board-card-seat.d.ts +34 -0
- package/lib/types/client/host-api.d.ts +24 -1
- package/lib/types/client/index.d.ts +19 -0
- package/lib/types/client/locales.d.ts +141 -3
- package/lib/types/client/native-panel.d.ts +6 -20
- package/lib/types/client/schedule-zone.d.ts +47 -0
- package/lib/types/client/seats.d.ts +18 -0
- package/lib/types/client/service.d.ts +32 -0
- package/lib/types/client/settings-form.d.ts +16 -0
- package/lib/types/core/controller.d.ts +38 -1
- package/lib/types/core/degraded-reason.d.ts +46 -0
- package/lib/types/core/extension.d.ts +283 -0
- package/lib/types/core/handover.d.ts +13 -1
- package/lib/types/core/issue-form.d.ts +16 -0
- package/lib/types/core/package-name.d.ts +9 -0
- package/lib/types/core/schedule.d.ts +95 -20
- package/lib/types/core/subtask.d.ts +30 -11
- package/lib/types/core/tasks.d.ts +110 -5
- package/lib/types/core/use-cases/task-create.d.ts +2 -1
- package/lib/types/core/use-cases/task-schedule.d.ts +8 -4
- package/lib/types/core/use-cases/task-tag.d.ts +48 -0
- package/lib/types/core/use-cases/task-update.d.ts +5 -3
- package/lib/types/core/verification.d.ts +386 -0
- package/lib/types/core/workspace-target.d.ts +41 -0
- package/lib/types/host/agent-tools.d.ts +1 -1
- package/lib/types/host/extension-registry.d.ts +111 -0
- package/lib/types/host/llm-dispatch.d.ts +63 -0
- package/lib/types/host/verification-gate.d.ts +71 -0
- package/lib/types/host/verification-runner.d.ts +108 -0
- package/lib/types/host/workspace-evidence.d.ts +53 -0
- package/lib/types/host-ledger.d.ts +107 -11
- package/lib/types/host-runner.d.ts +99 -4
- package/lib/types/host-service.d.ts +114 -2
- package/lib/types/index.d.ts +80 -26
- package/lib/types/protocol.d.ts +53 -3
- package/lib/types/tool-surface.d.ts +71 -0
- package/package.json +27 -26
- package/src/client/PluginSettingsCard.tsx +9 -0
- package/src/client/TaskBoardSettingsCard.tsx +304 -65
- package/src/client/board/ClampedMarkdown.tsx +69 -0
- package/src/client/board/ConfirmDialog.tsx +7 -3
- package/src/client/board/EditTaskModal.tsx +5 -2
- package/src/client/board/LinkSubtaskModal.tsx +30 -15
- package/src/client/board/NewTaskModal.tsx +288 -151
- package/src/client/board/TagManagerModal.tsx +235 -0
- package/src/client/board/TaskBoard.tsx +259 -103
- package/src/client/board/TaskCard.tsx +238 -86
- package/src/client/board/TaskDetail.tsx +154 -59
- package/src/client/board/TaskForm.tsx +61 -6
- package/src/client/board/VerificationReport.tsx +203 -0
- package/src/client/board/card-view.ts +220 -0
- package/src/client/board/icons.tsx +89 -0
- package/src/client/board/overlay.tsx +189 -0
- package/src/client/board/preset-label.ts +44 -0
- package/src/client/board/status-key.ts +27 -0
- package/src/client/board/task-markdown.module.css +137 -0
- package/src/client/board/task-markdown.tsx +106 -0
- package/src/client/board-card-seat.ts +102 -0
- package/src/client/board-settings.module.css +66 -0
- package/src/client/board.module.css +602 -68
- package/src/client/host-api.ts +109 -6
- package/src/client/index.ts +48 -6
- package/src/client/locales.ts +290 -12
- package/src/client/native-panel.tsx +18 -2
- package/src/client/schedule-zone.ts +135 -0
- package/src/client/seats.tsx +58 -0
- package/src/client/service.ts +94 -0
- package/src/client/settings-card.module.css +31 -5
- package/src/client/settings-form.ts +27 -1
- package/src/core/controller.ts +101 -5
- package/src/core/degraded-reason.ts +81 -0
- package/src/core/extension.ts +376 -0
- package/src/core/freeze-snapshot.ts +2 -2
- package/src/core/handover.ts +16 -1
- package/src/core/issue-form.ts +19 -0
- package/src/core/package-name.ts +9 -0
- package/src/core/schedule.ts +211 -55
- package/src/core/store.ts +26 -1
- package/src/core/subtask.ts +77 -22
- package/src/core/tasks.ts +138 -10
- package/src/core/use-cases/task-create.ts +14 -2
- package/src/core/use-cases/task-parent.ts +3 -2
- package/src/core/use-cases/task-schedule.ts +17 -6
- package/src/core/use-cases/task-tag.ts +110 -0
- package/src/core/use-cases/task-update.ts +13 -4
- package/src/core/verification.ts +826 -0
- package/src/core/workspace-target.ts +59 -0
- package/src/host/agent-tools.ts +58 -24
- package/src/host/extension-registry.ts +509 -0
- package/src/host/llm-dispatch.ts +87 -0
- package/src/host/verification-gate.ts +331 -0
- package/src/host/verification-runner.ts +535 -0
- package/src/host/workspace-evidence.ts +176 -0
- package/src/host-ai.ts +15 -9
- package/src/host-ledger.ts +342 -51
- package/src/host-routes.ts +15 -2
- package/src/host-runner.ts +219 -20
- package/src/host-service.ts +346 -26
- package/src/index.ts +204 -16
- package/src/protocol.ts +122 -9
- package/src/tool-surface.ts +95 -0
- package/lib/types/host/run-guarded.d.ts +0 -39
- package/src/host/run-guarded.ts +0 -76
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal acceptance domain: the board's evaluator-backed certification layer for
|
|
3
|
+
* task executions that run in goal form.
|
|
4
|
+
*
|
|
5
|
+
* The board owns WHEN acceptance runs (the goal's completion gate), the
|
|
6
|
+
* per-cycle budget, the feedback it returns, the settlement rule and the
|
|
7
|
+
* report. The algorithm it runs is the DEFAULT final acceptance of the
|
|
8
|
+
* installed `dsh-llm-verifier` 0.8.4 (MIT), mirrored here rather than imported:
|
|
9
|
+
* that plugin is a third-party plugin, not a dependency of this repository, and
|
|
10
|
+
* a host half may only depend on the official `@deepseek-ai/*` SDK.
|
|
11
|
+
*
|
|
12
|
+
* Mirrored contract, byte-identical where the judge prompt depends on it:
|
|
13
|
+
* the three coding criteria of `DEFAULT_CRITERIA` (`CRITERIA_PRESETS.coding`),
|
|
14
|
+
* the 20-letter A-T scale, the required `<score_A>`/`<score_B>` verdict tags,
|
|
15
|
+
* the untrusted-evidence framing, `EMPTY_WORK_BASELINE` as candidate B, two
|
|
16
|
+
* rounds per criterion with the A/B slots swapped on the odd round, per-round
|
|
17
|
+
* scores mapped back to the caller's slots and averaged per criterion, and the
|
|
18
|
+
* pass rule `winner === 'A' && total >= threshold && every criterion >= threshold`.
|
|
19
|
+
*
|
|
20
|
+
* This module is framework-free (no cordis, no SDK imports) so the whole rule
|
|
21
|
+
* set is unit-testable in isolation; the model call itself lives in the host
|
|
22
|
+
* half (`src/host/verification-runner.ts`).
|
|
23
|
+
*/
|
|
24
|
+
/** Schema version of the persisted verification block (per execution record). */
|
|
25
|
+
export declare const VERIFICATION_SCHEMA_VERSION: 1;
|
|
26
|
+
/** Acceptance threshold mirrored from the verifier's `autoVerifyThreshold` default. */
|
|
27
|
+
export declare const VERIFICATION_THRESHOLD = 0.65;
|
|
28
|
+
/** Rounds per criterion: the verifier's `autoVerifyFinalRepeats` default. */
|
|
29
|
+
export declare const VERIFICATION_ROUNDS = 2;
|
|
30
|
+
/**
|
|
31
|
+
* Quality acceptances one goal completion cycle may spend: the first verdict,
|
|
32
|
+
* then one re-verification after the agent repaired the work. A second failure
|
|
33
|
+
* ends the cycle (see {@link MAX_EXCEPTION_ATTEMPTS} for the separate anomaly
|
|
34
|
+
* budget).
|
|
35
|
+
*/
|
|
36
|
+
export declare const MAX_QUALITY_ATTEMPTS = 2;
|
|
37
|
+
/**
|
|
38
|
+
* Anomaly budget of one cycle. A timeout, an authentication failure or an
|
|
39
|
+
* unparseable judge answer is not a quality verdict, so it never consumes a
|
|
40
|
+
* quality attempt; it is still bounded, so an unusable judge route can never
|
|
41
|
+
* turn the completion gate into an unbounded retry loop.
|
|
42
|
+
*/
|
|
43
|
+
export declare const MAX_EXCEPTION_ATTEMPTS = 2;
|
|
44
|
+
/** The fixed baseline a session acceptance measures itself against. */
|
|
45
|
+
export declare const EMPTY_WORK_BASELINE = "(No useful work or verification was performed.)";
|
|
46
|
+
/** Ground-truth note prepended to every judge prompt. */
|
|
47
|
+
export declare const DEFAULT_GROUND_TRUTH_NOTE = "**IMPORTANT:** Focus on observed tool and terminal output as ground truth. Do NOT trust the agent's self-assessment or claims of success.";
|
|
48
|
+
/** Injected-content guardrail shared by every judge prompt. */
|
|
49
|
+
export declare const UNTRUSTED_EVIDENCE_NOTE: string;
|
|
50
|
+
/** Role sentence for a completed-artifact review of a coding task. */
|
|
51
|
+
export declare const EVALUATOR_ROLE = "You are an expert evaluator of AI coding agents. You will see a task description and two agent trajectories, then evaluate them on ONE specific criterion, stated at the end.";
|
|
52
|
+
/** The 20-point A-T scale, mirrored from the verifier. */
|
|
53
|
+
export declare const GRANULARITY = 20;
|
|
54
|
+
/** One criterion of the coding rubric. */
|
|
55
|
+
export interface VerificationCriterion {
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
description: string;
|
|
59
|
+
}
|
|
60
|
+
/** The coding rubric, identical to the verifier's `DEFAULT_CRITERIA`. */
|
|
61
|
+
export declare const CODING_CRITERIA: readonly VerificationCriterion[];
|
|
62
|
+
/** Rating scale text rendered into every judge prompt. */
|
|
63
|
+
export declare const SCALE_DESCRIPTION: string;
|
|
64
|
+
/** A-T letters in scale order (A = best). */
|
|
65
|
+
export declare const LETTERS: readonly string[];
|
|
66
|
+
/**
|
|
67
|
+
* Normalize one score token to an A-T letter.
|
|
68
|
+
* @param token - the raw captured token.
|
|
69
|
+
* @returns the uppercase letter, or undefined when it is not one of A-T.
|
|
70
|
+
*/
|
|
71
|
+
export declare function normalizeScoreLetter(token: string): string | undefined;
|
|
72
|
+
/** Numeric value of one A-T letter (A = 20 ... T = 1). */
|
|
73
|
+
export declare function letterValue(letter: string): number;
|
|
74
|
+
/**
|
|
75
|
+
* Read the LAST `<tag> LETTER </tag>` verdict out of one judge answer.
|
|
76
|
+
*
|
|
77
|
+
* The tag contract is the verifier's explicit-tag channel: this deployment's
|
|
78
|
+
* only scoring channel, because the official DSH adapters expose no token
|
|
79
|
+
* logprobs (the verifier's direct top-logprob transport needs a capability the
|
|
80
|
+
* public SDK does not carry). A missing or unusable tag is an exception, never
|
|
81
|
+
* a score: the verdict stays fail-closed.
|
|
82
|
+
* @param text - the raw judge answer.
|
|
83
|
+
* @param tag - the tag name, e.g. `score_A`.
|
|
84
|
+
* @returns the score in 0..1 (A = 1.0, T = 0.0).
|
|
85
|
+
* @throws Error when the answer carries no valid A-T verdict for this tag.
|
|
86
|
+
*/
|
|
87
|
+
export declare function extractScore(text: string, tag: string): number;
|
|
88
|
+
/**
|
|
89
|
+
* Render one untrusted content block with deterministic nonce-tagged delimiters.
|
|
90
|
+
* @param tag - block tag.
|
|
91
|
+
* @param token - content-derived delimiter token.
|
|
92
|
+
* @param content - the untrusted content.
|
|
93
|
+
* @returns the wrapped block.
|
|
94
|
+
*/
|
|
95
|
+
export declare function renderDelimitedBlock(tag: string, token: string, content: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Deterministic per-prompt delimiter token (FNV-1a, same construction as the
|
|
98
|
+
* verifier's). Not random: the token must depend on the whole content so that
|
|
99
|
+
* identical inputs render an identical prompt while injected text cannot
|
|
100
|
+
* predict the terminator.
|
|
101
|
+
* @param parts - the content parts.
|
|
102
|
+
* @returns a short base-36 token.
|
|
103
|
+
*/
|
|
104
|
+
export declare function evidenceNonce(...parts: readonly string[]): string;
|
|
105
|
+
/**
|
|
106
|
+
* One pairwise judge prompt focused on a single criterion.
|
|
107
|
+
*
|
|
108
|
+
* Everything that does not depend on the criterion comes first and only the
|
|
109
|
+
* criterion varies at the tail, so a prefix-caching backend serves the
|
|
110
|
+
* evidence-heavy body from cache across the criteria of one acceptance.
|
|
111
|
+
* @param problem - the task statement.
|
|
112
|
+
* @param traceA - candidate A's trajectory.
|
|
113
|
+
* @param traceB - candidate B's trajectory.
|
|
114
|
+
* @param criterion - the criterion this call scores.
|
|
115
|
+
* @param groundTruthNote - note prepended to every judge prompt.
|
|
116
|
+
* @param context - optional reference context (the host's own record of what
|
|
117
|
+
* changed on disk), rendered as its own data-only block between the task and
|
|
118
|
+
* the two candidates. Omitted renders nothing, which keeps the prompt
|
|
119
|
+
* byte-identical for a deployment that serves no change service.
|
|
120
|
+
* @returns the rendered prompt.
|
|
121
|
+
*/
|
|
122
|
+
export declare function buildAcceptancePrompt(problem: string, traceA: string, traceB: string, criterion: VerificationCriterion, groundTruthNote?: string, context?: string): string;
|
|
123
|
+
/** Where the judge route of one execution came from. */
|
|
124
|
+
export type VerificationRouteSource = 'inherit' | 'explicit';
|
|
125
|
+
/** The resolved judge route of one execution's acceptance. */
|
|
126
|
+
export interface VerificationRoute {
|
|
127
|
+
provider: string;
|
|
128
|
+
model: string;
|
|
129
|
+
reasoningEffort?: string;
|
|
130
|
+
}
|
|
131
|
+
/** One reasoning-effort option an adapter exposes for an exact model route. */
|
|
132
|
+
export interface CatalogReasoningEffort {
|
|
133
|
+
id: string;
|
|
134
|
+
name?: string;
|
|
135
|
+
}
|
|
136
|
+
/** One adapter-discovered model of the host catalog. */
|
|
137
|
+
export interface CatalogModel {
|
|
138
|
+
id: string;
|
|
139
|
+
name?: string;
|
|
140
|
+
reasoning?: {
|
|
141
|
+
efforts: CatalogReasoningEffort[];
|
|
142
|
+
defaultEffort?: string;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** One provider route and its models. */
|
|
146
|
+
export interface CatalogGroup {
|
|
147
|
+
id: string;
|
|
148
|
+
name?: string;
|
|
149
|
+
models: CatalogModel[];
|
|
150
|
+
}
|
|
151
|
+
/** The host model catalog the acceptance settings resolve against. */
|
|
152
|
+
export interface ModelCatalogView {
|
|
153
|
+
/** The route an unconfigured session starts at: the host's own configuration. */
|
|
154
|
+
default?: VerificationRoute;
|
|
155
|
+
groups: CatalogGroup[];
|
|
156
|
+
}
|
|
157
|
+
/** The acceptance settings as the configuration holds them. */
|
|
158
|
+
export interface VerificationSettings {
|
|
159
|
+
enabled: boolean;
|
|
160
|
+
/** Qualified provider/model route, or '' to inherit the host default. */
|
|
161
|
+
model: string;
|
|
162
|
+
/** Reasoning effort id, or '' to inherit. */
|
|
163
|
+
reasoningEffort: string;
|
|
164
|
+
}
|
|
165
|
+
/** The acceptance configuration frozen when one execution started. */
|
|
166
|
+
export interface VerificationContract {
|
|
167
|
+
/** Whether acceptance is required for this execution (the switch at start time). */
|
|
168
|
+
enabled: boolean;
|
|
169
|
+
/** Whether the judge model came from the host default or from configuration. */
|
|
170
|
+
modelSource: VerificationRouteSource;
|
|
171
|
+
/** Resolved judge route; absent when the deployment serves no model catalog. */
|
|
172
|
+
route?: VerificationRoute;
|
|
173
|
+
/** The reasoning effort configuration asked for, when it named one. */
|
|
174
|
+
requestedEffort?: string;
|
|
175
|
+
/**
|
|
176
|
+
* Set when an explicitly configured reasoning effort is not supported by the
|
|
177
|
+
* resolved model: the incompatible value is NOT sent, and the acceptance runs
|
|
178
|
+
* on `resolved` (the model's own default when that is defined).
|
|
179
|
+
*/
|
|
180
|
+
effortFallback?: {
|
|
181
|
+
requested: string;
|
|
182
|
+
resolved?: string;
|
|
183
|
+
};
|
|
184
|
+
/** Rubric preset. The first version always judges with the coding criteria. */
|
|
185
|
+
preset: 'coding';
|
|
186
|
+
/** Acceptance threshold frozen with the contract. */
|
|
187
|
+
threshold: number;
|
|
188
|
+
}
|
|
189
|
+
/** One criterion's verdict inside an acceptance attempt. */
|
|
190
|
+
export interface VerificationCriterionScore {
|
|
191
|
+
id: string;
|
|
192
|
+
name: string;
|
|
193
|
+
/** Score of the task's own work (0..1). */
|
|
194
|
+
score: number;
|
|
195
|
+
/** Score of the empty-work baseline in the same comparison. */
|
|
196
|
+
baseline: number;
|
|
197
|
+
threshold: number;
|
|
198
|
+
passed: boolean;
|
|
199
|
+
}
|
|
200
|
+
/** Token accounting of one acceptance attempt. */
|
|
201
|
+
export interface VerificationUsage {
|
|
202
|
+
calls: number;
|
|
203
|
+
inputTokens: number;
|
|
204
|
+
outputTokens: number;
|
|
205
|
+
reasoningTokens: number;
|
|
206
|
+
/** At least one call's usage was unknown; the counts are a floor. */
|
|
207
|
+
usageIncomplete?: boolean;
|
|
208
|
+
}
|
|
209
|
+
/** Scope of the evidence one attempt judged. */
|
|
210
|
+
export interface VerificationEvidenceSummary {
|
|
211
|
+
/** Characters handed to the judge after redaction. */
|
|
212
|
+
chars: number;
|
|
213
|
+
/** Characters dropped by the total cap (the newest text is kept). */
|
|
214
|
+
omittedCharacters: number;
|
|
215
|
+
/** Trace entries rendered. */
|
|
216
|
+
entries: number;
|
|
217
|
+
/** Sequence window the evidence was read from. */
|
|
218
|
+
fromSeq?: number;
|
|
219
|
+
toSeq?: number;
|
|
220
|
+
/** Digest of the judged evidence; the pass record is bound to it. */
|
|
221
|
+
hash: string;
|
|
222
|
+
/** Files of host-observed workspace changes rendered into the prompt (0 = none). */
|
|
223
|
+
workspaceFiles?: number;
|
|
224
|
+
}
|
|
225
|
+
/** One recorded acceptance attempt: a quality verdict or an anomaly. */
|
|
226
|
+
export interface VerificationAttempt {
|
|
227
|
+
/** 1-based ordinal within its own stage. */
|
|
228
|
+
index: number;
|
|
229
|
+
/** When the attempt ran (ms epoch). */
|
|
230
|
+
at: number;
|
|
231
|
+
stage: 'quality' | 'exception';
|
|
232
|
+
/** Quality: whether the work passed. A recorded anomaly is never a pass. */
|
|
233
|
+
passed: boolean;
|
|
234
|
+
/** Total score of the task's own work (0 for an anomaly). */
|
|
235
|
+
score: number;
|
|
236
|
+
/** Score of the empty-work baseline. */
|
|
237
|
+
baseline: number;
|
|
238
|
+
criteria: VerificationCriterionScore[];
|
|
239
|
+
/** Bounded, locatable feedback for the agent. */
|
|
240
|
+
findings: string[];
|
|
241
|
+
usage: VerificationUsage;
|
|
242
|
+
evidence: VerificationEvidenceSummary;
|
|
243
|
+
route: VerificationRoute;
|
|
244
|
+
/** Scoring channel that answered. This deployment serves explicit tags only. */
|
|
245
|
+
channel: 'explicit-tag';
|
|
246
|
+
rounds: number;
|
|
247
|
+
/** Anomaly reason; absent on a quality verdict. */
|
|
248
|
+
error?: string;
|
|
249
|
+
}
|
|
250
|
+
/** Persisted acceptance state of one execution. */
|
|
251
|
+
export interface ExecutionVerification {
|
|
252
|
+
contract: VerificationContract;
|
|
253
|
+
attempts: VerificationAttempt[];
|
|
254
|
+
/** True while an acceptance is running, so the board can show 验收中. */
|
|
255
|
+
inFlight?: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Why this execution may not settle as succeeded without a pass record:
|
|
258
|
+
* `disabled` when the switch was off at start, `skipped` when the CARD opted
|
|
259
|
+
* out of the gate (`TaskRecord.skipVerification`), `goal-unavailable` when
|
|
260
|
+
* the run never became a goal run (so no completion gate could ever fire),
|
|
261
|
+
* and `team-member` for a teammate execution (the Lead's acceptance covers
|
|
262
|
+
* the team's aggregated evidence).
|
|
263
|
+
*/
|
|
264
|
+
applicability: 'enforced' | 'disabled' | 'skipped' | 'goal-unavailable' | 'team-member';
|
|
265
|
+
/** Set when the cycle is spent and the execution must fail. */
|
|
266
|
+
failedReason?: string;
|
|
267
|
+
failedAt?: number;
|
|
268
|
+
}
|
|
269
|
+
/** UI/board phase of one execution's acceptance. */
|
|
270
|
+
export type VerificationPhase = 'off' | 'executing' | 'verifying' | 'repairing' | 'passed' | 'failed';
|
|
271
|
+
/** Quality attempts spent by this cycle. */
|
|
272
|
+
export declare function qualityAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
|
|
273
|
+
/** Anomaly attempts spent by this cycle. */
|
|
274
|
+
export declare function exceptionAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
|
|
275
|
+
/** The quality attempt that passed, when one did. */
|
|
276
|
+
export declare function passedAttempt(verification: ExecutionVerification | undefined): VerificationAttempt | undefined;
|
|
277
|
+
/**
|
|
278
|
+
* Whether the board requires a matching pass record before this execution may
|
|
279
|
+
* settle as succeeded. False when acceptance was off at start, and false for a
|
|
280
|
+
* run that never became a goal run or for a teammate execution — those settle
|
|
281
|
+
* on their own verdict, which is why {@link ExecutionVerification.applicability}
|
|
282
|
+
* is persisted rather than re-derived.
|
|
283
|
+
* @param verification - the execution's persisted acceptance state.
|
|
284
|
+
* @returns true when a pass record is required.
|
|
285
|
+
*/
|
|
286
|
+
export declare function verificationRequired(verification: ExecutionVerification | undefined): boolean;
|
|
287
|
+
/** Whether this cycle still has quality budget left. */
|
|
288
|
+
export declare function hasQualityBudget(verification: ExecutionVerification | undefined): boolean;
|
|
289
|
+
/** Whether this cycle still has anomaly budget left. */
|
|
290
|
+
export declare function hasExceptionBudget(verification: ExecutionVerification | undefined): boolean;
|
|
291
|
+
/** Derived board phase of one execution's acceptance. */
|
|
292
|
+
export declare function verificationPhase(verification: ExecutionVerification | undefined): VerificationPhase;
|
|
293
|
+
/**
|
|
294
|
+
* The acceptance rule, mirrored from the verifier's `sessionAccepted`:
|
|
295
|
+
* the work must BEAT the empty-work baseline, reach the total threshold, and
|
|
296
|
+
* reach the threshold on every criterion. A tie or a loss against the baseline
|
|
297
|
+
* fails, so a session indistinguishable from the baseline can never pass.
|
|
298
|
+
* @param score - total score of the task's own work.
|
|
299
|
+
* @param baseline - total score of the empty-work baseline.
|
|
300
|
+
* @param criteria - per-criterion scores of the task's own work.
|
|
301
|
+
* @param threshold - acceptance threshold.
|
|
302
|
+
* @returns true when the work passes.
|
|
303
|
+
*/
|
|
304
|
+
export declare function acceptancePassed(score: number, baseline: number, criteria: readonly {
|
|
305
|
+
score: number;
|
|
306
|
+
}[], threshold: number): boolean;
|
|
307
|
+
/**
|
|
308
|
+
* Repair a persisted acceptance block, or drop it.
|
|
309
|
+
*
|
|
310
|
+
* Deliberately fail-soft on the FIELD and fail-closed on the VERDICT: a block
|
|
311
|
+
* that does not parse is dropped (the execution keeps its own record, and the
|
|
312
|
+
* board then treats the execution as unverified), while a block that does parse
|
|
313
|
+
* keeps every recorded attempt verbatim. Dropping a malformed block can only
|
|
314
|
+
* make the board MORE strict, never less.
|
|
315
|
+
* @param value - the persisted value.
|
|
316
|
+
* @returns the repaired block, or undefined when it is unusable.
|
|
317
|
+
*/
|
|
318
|
+
export declare function normalizeVerification(value: unknown): ExecutionVerification | undefined;
|
|
319
|
+
/** Totals spanning every attempt of one execution (for the report and the card). */
|
|
320
|
+
export interface VerificationTotals {
|
|
321
|
+
quality: number;
|
|
322
|
+
exceptions: number;
|
|
323
|
+
calls: number;
|
|
324
|
+
inputTokens: number;
|
|
325
|
+
outputTokens: number;
|
|
326
|
+
reasoningTokens: number;
|
|
327
|
+
usageIncomplete: boolean;
|
|
328
|
+
}
|
|
329
|
+
/** Sum the attempts of one execution. */
|
|
330
|
+
export declare function verificationTotals(verification: ExecutionVerification | undefined): VerificationTotals;
|
|
331
|
+
/**
|
|
332
|
+
* The failure feedback one acceptance returns to the fixing agent. It names
|
|
333
|
+
* what failed, with the numbers, the locator lines the judge reported and the
|
|
334
|
+
* remaining budget, so the next round can act on it instead of restating the
|
|
335
|
+
* work.
|
|
336
|
+
* @param attempt - the failed quality attempt.
|
|
337
|
+
* @param remaining - quality attempts still available after this one.
|
|
338
|
+
* @returns the model-facing feedback text.
|
|
339
|
+
*/
|
|
340
|
+
export declare function qualityFeedback(attempt: VerificationAttempt, remaining: number): string;
|
|
341
|
+
/**
|
|
342
|
+
* The reason one exhausted acceptance cycle records as the execution's final
|
|
343
|
+
* failure. Unlike {@link qualityFeedback} — which the fixing agent reads while
|
|
344
|
+
* budget remains — this reason is also persisted on the ledger, echoed on every
|
|
345
|
+
* later completion attempt and shown on the card, so it carries the full
|
|
346
|
+
* picture: the scores, the baseline comparison, every failing criterion and the
|
|
347
|
+
* judge's locatable findings, so a later agent (or the user) can act on WHAT to
|
|
348
|
+
* improve, not only on how badly the attempt scored.
|
|
349
|
+
* @param attempt - the failed quality attempt that spent the last budget.
|
|
350
|
+
* @param used - quality attempts spent by the cycle.
|
|
351
|
+
* @param threshold - the contract threshold the work was judged against.
|
|
352
|
+
* @returns the model- and user-facing failure reason.
|
|
353
|
+
*/
|
|
354
|
+
export declare function finalFailureReason(attempt: VerificationAttempt, used: number, threshold: number): string;
|
|
355
|
+
/** `0.42` style percentage. */
|
|
356
|
+
export declare function percent(value: number): string;
|
|
357
|
+
/** Split a qualified `provider/model` route; undefined when it is not one. */
|
|
358
|
+
export declare function parseModelRoute(qualified: string | undefined): {
|
|
359
|
+
provider: string;
|
|
360
|
+
model: string;
|
|
361
|
+
} | undefined;
|
|
362
|
+
/**
|
|
363
|
+
* Normalize the raw `session/modelCatalog` reply into the shape the acceptance
|
|
364
|
+
* settings read. Everything is optional in the wire value, so every level is
|
|
365
|
+
* checked: an unreadable catalog degrades to "unknown", never to a crash.
|
|
366
|
+
* @param value - the raw gateway reply.
|
|
367
|
+
* @returns the normalized catalog, or undefined when nothing usable arrived.
|
|
368
|
+
*/
|
|
369
|
+
export declare function normalizeCatalog(value: unknown): ModelCatalogView | undefined;
|
|
370
|
+
/** Whether the catalog declares the route at all. */
|
|
371
|
+
export declare function catalogHasRoute(catalog: ModelCatalogView | undefined, provider: string, model: string): boolean;
|
|
372
|
+
/**
|
|
373
|
+
* Resolve the acceptance configuration into the contract one execution freezes.
|
|
374
|
+
*
|
|
375
|
+
* "Inherit host" means the host's own model catalog default, never the card's
|
|
376
|
+
* pinned execution model. An explicitly configured reasoning effort is sent
|
|
377
|
+
* ONLY when the target model's adapter declares it: an unsupported value is
|
|
378
|
+
* dropped instead of being passed through, and the fallback to the target
|
|
379
|
+
* model's own default is recorded so the settings card and the report can show
|
|
380
|
+
* exactly what will be sent.
|
|
381
|
+
* @param settings - the live configuration.
|
|
382
|
+
* @param catalog - the host model catalog, when this cohort serves one.
|
|
383
|
+
* @param threshold - acceptance threshold to freeze.
|
|
384
|
+
* @returns the contract.
|
|
385
|
+
*/
|
|
386
|
+
export declare function resolveContract(settings: VerificationSettings, catalog: ModelCatalogView | undefined, threshold?: number): VerificationContract;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace targeting for cards that pin none.
|
|
3
|
+
*
|
|
4
|
+
* The Host answers two questions here instead of leaving them to
|
|
5
|
+
* `session.create`, whose own fallback is the Host process working directory
|
|
6
|
+
* (the desktop app's profile directory): which workspace a root card inherits
|
|
7
|
+
* from the session that created it, and which workspace an unpinned run lands
|
|
8
|
+
* in when nothing could be inherited.
|
|
9
|
+
*
|
|
10
|
+
* Structural types only — the Host's `Workspace` entity satisfies them — so the
|
|
11
|
+
* browser program compiles this module without importing an SDK value.
|
|
12
|
+
*
|
|
13
|
+
* @module dsh-task-board/core/workspace-target
|
|
14
|
+
*/
|
|
15
|
+
/** The workspace facts these rules read (a `Workspace` entity subset). */
|
|
16
|
+
export interface WorkspaceCandidate {
|
|
17
|
+
/** Stable workspace record id. */
|
|
18
|
+
readonly id: string;
|
|
19
|
+
/** ISO-8601 instant of the workspace's last durable mutation. */
|
|
20
|
+
readonly updatedAt: string;
|
|
21
|
+
/** Header-validated session ids the workspace owns, most recent first. */
|
|
22
|
+
readonly sessionIds: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The workspace that owns one session.
|
|
26
|
+
* @param items - the deployment's workspaces.
|
|
27
|
+
* @param sessionId - the session whose workspace is requested.
|
|
28
|
+
* @returns the owning workspace id, or undefined when none claims the session.
|
|
29
|
+
*/
|
|
30
|
+
export declare function workspaceOwningSession(items: readonly WorkspaceCandidate[], sessionId: string): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* The workspace the board treats as most recently used: the one whose record
|
|
33
|
+
* changed last. Attaching a session stamps that instant, so the newest stamp
|
|
34
|
+
* tracks where the user most recently opened or resumed a session. The
|
|
35
|
+
* deployment's own list order breaks ties, and a stamp that does not parse
|
|
36
|
+
* never outranks one that does; a registry whose stamps are all unreadable
|
|
37
|
+
* falls back to list order rather than to "no workspace at all".
|
|
38
|
+
* @param items - the deployment's workspaces.
|
|
39
|
+
* @returns the most recently used workspace id, or undefined when there is none.
|
|
40
|
+
*/
|
|
41
|
+
export declare function mostRecentWorkspaceId(items: readonly WorkspaceCandidate[]): string | undefined;
|
|
@@ -8,7 +8,7 @@ export interface TaskBoardToolHost {
|
|
|
8
8
|
/** Current board snapshot (tasks + scheduler + power + deployment constants). */
|
|
9
9
|
snapshot(): TaskBoardSnapshot;
|
|
10
10
|
/** Submit one confirmed Host action; returns the resulting snapshot. */
|
|
11
|
-
apply(requestId: string, action: TaskBoardAction, initiator?: string): TaskBoardSnapshot
|
|
11
|
+
apply(requestId: string, action: TaskBoardAction, initiator?: string): TaskBoardSnapshot | Promise<TaskBoardSnapshot>;
|
|
12
12
|
}
|
|
13
13
|
/** Registered tool names, in registration order. */
|
|
14
14
|
export declare const TASK_BOARD_TOOL_NAMES: readonly ["task_board_list", "task_board_get", "task_board_create", "task_board_update", "task_board_set_parent", "task_board_run", "task_board_manage", "task_board_schedule"];
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-side extension registry: the one place that admits external providers,
|
|
3
|
+
* negotiates the contract version, gates them on the board's own enable state,
|
|
4
|
+
* fans board events out to them, and routes dispatched provider actions back.
|
|
5
|
+
*
|
|
6
|
+
* Failure policy (mirrors the board's plugin philosophy): a provider that
|
|
7
|
+
* throws, mis-declares its version, or disables itself degrades only its own
|
|
8
|
+
* surface. The board keeps serving; the registry records what it refused.
|
|
9
|
+
*
|
|
10
|
+
* @module dsh-task-board/host/extension-registry
|
|
11
|
+
*/
|
|
12
|
+
import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
|
|
13
|
+
import type { HostTaskLedger } from '../host-ledger.ts';
|
|
14
|
+
import type { TaskBoardAction, TaskBoardSnapshot } from '../protocol.ts';
|
|
15
|
+
import { type TaskBoardExecutionSettledEvent, type TaskBoardExtension, type TaskBoardExtensionActionRequest, type TaskBoardExtensionPayload, type TaskBoardStatusChangedEvent, type TaskBoardTaskDeletedEvent } from '../core/extension.ts';
|
|
16
|
+
/** Diagnosable refusal raised by the registry and the capability face. */
|
|
17
|
+
export declare class TaskBoardExtensionError extends Error {
|
|
18
|
+
readonly code: string;
|
|
19
|
+
constructor(code: string, message: string);
|
|
20
|
+
}
|
|
21
|
+
/** Logging seat the registry uses; a deployment may supply its own. */
|
|
22
|
+
export interface TaskBoardExtensionLogger {
|
|
23
|
+
warn(message: string, ...rest: unknown[]): void;
|
|
24
|
+
error(message: string, ...rest: unknown[]): void;
|
|
25
|
+
}
|
|
26
|
+
/** The deployment's model-visible tool registry, resolved lazily. */
|
|
27
|
+
export interface TaskBoardExtensionToolRegistry {
|
|
28
|
+
register(definition: ToolDefinition): () => void;
|
|
29
|
+
}
|
|
30
|
+
/** Applies one board action with every board gate intact (never an extension action). */
|
|
31
|
+
export type TaskBoardActionApplier = (action: Exclude<TaskBoardAction, {
|
|
32
|
+
kind: 'extension-action';
|
|
33
|
+
}>, initiator?: string) => TaskBoardSnapshot;
|
|
34
|
+
/** Registry dependencies. */
|
|
35
|
+
export interface TaskBoardExtensionRegistryOptions {
|
|
36
|
+
ledger: HostTaskLedger;
|
|
37
|
+
/** Apply an action through the board service (gates, run dispatch, schedule). */
|
|
38
|
+
apply?: TaskBoardActionApplier;
|
|
39
|
+
/** Resolve the deployment's tool registry; absent loses the tool surface only. */
|
|
40
|
+
toolRegistry?: () => TaskBoardExtensionToolRegistry | undefined;
|
|
41
|
+
now?: () => number;
|
|
42
|
+
uuid?: () => string;
|
|
43
|
+
logger?: TaskBoardExtensionLogger;
|
|
44
|
+
}
|
|
45
|
+
export declare class TaskBoardExtensionRegistry {
|
|
46
|
+
private readonly entries;
|
|
47
|
+
private readonly ledger;
|
|
48
|
+
private readonly applyAction;
|
|
49
|
+
private readonly now;
|
|
50
|
+
private readonly uuid;
|
|
51
|
+
private readonly logger;
|
|
52
|
+
private toolResolver;
|
|
53
|
+
/** Board master switch (enabled config); providers start only while it is on. */
|
|
54
|
+
private boardEnabled;
|
|
55
|
+
private disposed;
|
|
56
|
+
constructor(options: TaskBoardExtensionRegistryOptions);
|
|
57
|
+
/**
|
|
58
|
+
* Pin (or replace) the deployment's tool registry. A registry that appears
|
|
59
|
+
* after a provider started is picked up here, which is what keeps the tool
|
|
60
|
+
* surface alive across the board's own late service resolution.
|
|
61
|
+
*/
|
|
62
|
+
setToolRegistry(resolver: (() => TaskBoardExtensionToolRegistry | undefined) | undefined): void;
|
|
63
|
+
/** Apply the board's master switch; providers start and stop with it. */
|
|
64
|
+
setEnabled(enabled: boolean): void;
|
|
65
|
+
/** Whether the board currently runs a given extension (board x extension). */
|
|
66
|
+
isActive(extensionId: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Admit one provider. Idempotent by id: a second registration of the same id
|
|
69
|
+
* is a no-op that returns the same release handle. A contract-version
|
|
70
|
+
* mismatch is refused visibly (logged and thrown) without disturbing the
|
|
71
|
+
* board or any other provider.
|
|
72
|
+
* @param extension - the provider to admit.
|
|
73
|
+
* @returns a disposer releasing the registration (idempotent).
|
|
74
|
+
*/
|
|
75
|
+
registerExtension(extension: TaskBoardExtension): () => void;
|
|
76
|
+
/** Remove one provider; its provider-side work stops and its payload stays stored. */
|
|
77
|
+
unregister(extensionId: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Route one dispatched provider action. Refuses visibly when the extension is
|
|
80
|
+
* unknown, currently gated off, or does not implement the action.
|
|
81
|
+
*/
|
|
82
|
+
handleAction(request: TaskBoardExtensionActionRequest): Promise<unknown>;
|
|
83
|
+
/** Published summaries of currently running providers, keyed by extension id. */
|
|
84
|
+
published(): Record<string, TaskBoardExtensionPayload>;
|
|
85
|
+
/** Fan a status change out to every running provider, isolated per callback. */
|
|
86
|
+
emitStatusChanged(event: TaskBoardStatusChangedEvent): void;
|
|
87
|
+
/** Fan an execution settlement out to every running provider. */
|
|
88
|
+
emitExecutionSettled(event: TaskBoardExecutionSettledEvent): void;
|
|
89
|
+
/** Fan a task deletion out to every running provider. */
|
|
90
|
+
emitTaskDeleted(event: TaskBoardTaskDeletedEvent): void;
|
|
91
|
+
/** Stop every provider and release the registry (idempotent). */
|
|
92
|
+
dispose(): void;
|
|
93
|
+
private emit;
|
|
94
|
+
/** Start or stop one entry against the current board + extension gate. */
|
|
95
|
+
private reconcile;
|
|
96
|
+
private startEntry;
|
|
97
|
+
private stopEntry;
|
|
98
|
+
/** (Re)register every buffered tool against the current tool registry. */
|
|
99
|
+
private syncTools;
|
|
100
|
+
private disposeTools;
|
|
101
|
+
private assertActive;
|
|
102
|
+
/** Build the per-extension capability face. */
|
|
103
|
+
private capabilities;
|
|
104
|
+
private createTask;
|
|
105
|
+
private patchContent;
|
|
106
|
+
private setStatus;
|
|
107
|
+
private linkedTasks;
|
|
108
|
+
private writeIntegration;
|
|
109
|
+
private publish;
|
|
110
|
+
private registerTool;
|
|
111
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-shot model dispatch for the board's Host half.
|
|
3
|
+
*
|
|
4
|
+
* The board makes two one-shot model calls: the goal-acceptance judge
|
|
5
|
+
* (`verification-runner.ts`) and the "parse pasted text" action
|
|
6
|
+
* (`host-ai.ts`). Both call the official `llm` service, and both must call it
|
|
7
|
+
* the way the official agent loop does.
|
|
8
|
+
*
|
|
9
|
+
* The runtime exposes two entry points with the same name shape. The public
|
|
10
|
+
* `stream(options)` is a single-argument convenience method, and it is an
|
|
11
|
+
* ordinary instance property — any plugin may overwrite it. The registration
|
|
12
|
+
* bound path `prepareCall(config)` returns a one-shot handle whose
|
|
13
|
+
* `stream(request)` reaches the adapter through the runtime's internal
|
|
14
|
+
* dispatch instead, and `ctx.on('llm/stream')` remains the supported seam every
|
|
15
|
+
* extension is expected to register on.
|
|
16
|
+
*
|
|
17
|
+
* A third-party provider plugin that patched `llm.stream` with the waterfall
|
|
18
|
+
* listener signature `(options, next)` broke every caller that used the public
|
|
19
|
+
* method: `llm.stream(options)` invoked the listener with `next === undefined`,
|
|
20
|
+
* so the guard's `for await (const chunk of next())` raised
|
|
21
|
+
* `TypeError: next(...) is not a function or its return value is not async
|
|
22
|
+
* iterable`. The agent loop was unaffected because it already dispatches
|
|
23
|
+
* through `prepareCall(...).stream(...)`; the board's two one-shot calls were
|
|
24
|
+
* not, and each completed acceptance was recorded as an anomaly
|
|
25
|
+
* ("验收异常(裁判请求失败)") after two judge attempts.
|
|
26
|
+
*
|
|
27
|
+
* Dispatching through the prepared call fixes that at the owner: the board no
|
|
28
|
+
* longer depends on a mutable instance property that a plugin may legitimately
|
|
29
|
+
* replace, and a plugin that registers on `llm/stream` is still invoked. The
|
|
30
|
+
* public method remains the fallback for a runtime that exposes no
|
|
31
|
+
* `prepareCall` at all, so an older or proxied service keeps working.
|
|
32
|
+
*/
|
|
33
|
+
import { type GenerateOptions, type LlmRuntime, type StreamChunk } from '@deepseek-ai/dsh-llm';
|
|
34
|
+
/** The request fields the board adds around a call config. */
|
|
35
|
+
export type OneShotRequest = Pick<GenerateOptions, 'messages' | 'signal'> & Pick<GenerateOptions, 'system'>;
|
|
36
|
+
/**
|
|
37
|
+
* The call config as this board's own domain types carry it.
|
|
38
|
+
*
|
|
39
|
+
* `VerificationRoute.reasoningEffort` and the parse route are plain strings (the
|
|
40
|
+
* catalog publishes effort ids as strings), while the SDK brands them
|
|
41
|
+
* nominally; the single crossing is branded here so no caller repeats the
|
|
42
|
+
* assertion.
|
|
43
|
+
*/
|
|
44
|
+
export interface OneShotCallConfig {
|
|
45
|
+
provider: string;
|
|
46
|
+
model: string;
|
|
47
|
+
reasoningEffort?: string;
|
|
48
|
+
temperature?: number;
|
|
49
|
+
maxTokens?: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Open one one-shot model stream on the registration-bound dispatch path.
|
|
53
|
+
*
|
|
54
|
+
* The call-config fields must travel inside `config` (not the request): the
|
|
55
|
+
* prepared handle refuses a request whose config fields differ from the ones it
|
|
56
|
+
* resolved, so the request carries only messages, signal, and the optional
|
|
57
|
+
* one-shot system prompt.
|
|
58
|
+
* @param llm - the Host's llm service.
|
|
59
|
+
* @param config - provider/model route plus the caller's sampling controls.
|
|
60
|
+
* @param request - the assembled messages and cancellation for this call.
|
|
61
|
+
* @returns the chunk stream, including any registered `llm/stream` listener.
|
|
62
|
+
*/
|
|
63
|
+
export declare function openOneShotStream(llm: LlmRuntime, config: OneShotCallConfig, request: OneShotRequest): Promise<AsyncIterable<StreamChunk>>;
|