@linxin666/dsh-client-ui-task-board 0.4.5 → 0.4.7
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 +34 -18
- package/README.zh.md +34 -18
- package/lib/client.js +2804 -1024
- package/lib/client.js.map +1 -1
- package/lib/index.js +2576 -416
- package/lib/types/client/CardDefaultPresetField.d.ts +35 -0
- package/lib/types/client/TaskBoardSettingsCard.d.ts +61 -0
- package/lib/types/client/board/ReasoningEffortField.d.ts +25 -0
- package/lib/types/client/board/model-options.d.ts +67 -0
- package/lib/types/client/board/preset-label.d.ts +21 -0
- package/lib/types/client/board/preset-roster.d.ts +45 -0
- package/lib/types/client/board/team-run-promotion.d.ts +26 -0
- package/lib/types/client/index.d.ts +4 -5
- package/lib/types/client/locales.d.ts +81 -0
- package/lib/types/client/plugin-card-seat.d.ts +5 -0
- package/lib/types/client/schedule-zone.d.ts +50 -0
- package/lib/types/core/card-defaults.d.ts +78 -0
- package/lib/types/core/controller.d.ts +41 -17
- package/lib/types/core/launch-width.d.ts +31 -0
- package/lib/types/core/poll-cadence.d.ts +31 -0
- package/lib/types/core/reasoning-effort.d.ts +57 -0
- package/lib/types/core/subtask.d.ts +30 -8
- package/lib/types/core/tasks.d.ts +163 -14
- package/lib/types/core/use-cases/task-create.d.ts +10 -5
- package/lib/types/core/use-cases/task-schedule.d.ts +68 -10
- package/lib/types/core/use-cases/task-update.d.ts +1 -1
- package/lib/types/core/verification-budget.d.ts +52 -0
- package/lib/types/core/verification.d.ts +376 -9
- package/lib/types/host/launch-admission.d.ts +72 -0
- package/lib/types/host/verification-gate.d.ts +24 -0
- package/lib/types/host/verification-runner.d.ts +38 -7
- package/lib/types/host-ledger.d.ts +91 -11
- package/lib/types/host-runner.d.ts +111 -13
- package/lib/types/host-service.d.ts +199 -8
- package/lib/types/index.d.ts +141 -0
- package/lib/types/protocol.d.ts +63 -12
- package/package.json +29 -33
- package/src/client/CardDefaultPresetField.tsx +101 -0
- package/src/client/TaskBoardSettingsCard.tsx +288 -17
- package/src/client/board/LinkSubtaskModal.tsx +8 -0
- package/src/client/board/NewTaskModal.tsx +237 -60
- package/src/client/board/ReasoningEffortField.tsx +50 -0
- package/src/client/board/TaskCard.tsx +3 -3
- package/src/client/board/TaskDetail.tsx +261 -24
- package/src/client/board/VerificationReport.tsx +132 -13
- package/src/client/board/model-options.ts +178 -0
- package/src/client/board/preset-label.ts +32 -0
- package/src/client/board/preset-roster.ts +58 -0
- package/src/client/board/status-key.ts +3 -0
- package/src/client/board/team-run-promotion.ts +39 -0
- package/src/client/index.ts +105 -108
- package/src/client/locales.ts +171 -6
- package/src/client/plugin-card-seat.ts +7 -0
- package/src/client/schedule-zone.ts +100 -2
- package/src/client/settings-entry-form.ts +0 -1
- package/src/core/card-defaults.ts +132 -0
- package/src/core/controller.ts +55 -16
- package/src/core/launch-width.ts +38 -0
- package/src/core/poll-cadence.ts +41 -0
- package/src/core/reasoning-effort.ts +92 -0
- package/src/core/store.ts +69 -15
- package/src/core/subtask.ts +48 -13
- package/src/core/tasks.ts +213 -39
- package/src/core/use-cases/task-create.ts +57 -25
- package/src/core/use-cases/task-schedule.ts +190 -25
- package/src/core/use-cases/task-update.ts +9 -4
- package/src/core/verification-budget.ts +115 -0
- package/src/core/verification.ts +785 -17
- package/src/host/agent-tools.ts +127 -29
- package/src/host/launch-admission.ts +140 -0
- package/src/host/verification-gate.ts +172 -16
- package/src/host/verification-runner.ts +207 -40
- package/src/host-ledger.ts +346 -48
- package/src/host-runner.ts +234 -35
- package/src/host-service.ts +539 -52
- package/src/index.ts +250 -7
- package/src/protocol.ts +160 -32
- package/lib/invariant.js +0 -6
- package/lib/types/client/board-card-seat.d.ts +0 -34
- package/lib/types/invariant.d.ts +0 -3
- package/src/client/board-card-seat.ts +0 -102
- package/src/invariant.ts +0 -4
package/src/index.ts
CHANGED
|
@@ -18,10 +18,24 @@ import type {} from '@deepseek-ai/dsh-tools'
|
|
|
18
18
|
import type { ToolDefinition } from '@deepseek-ai/dsh-tools'
|
|
19
19
|
import type { LlmRuntime } from '@deepseek-ai/dsh-llm'
|
|
20
20
|
import { TaskBoardHostService, type HostTimerFace, type TaskBoardTeamDispatcher } from './host-service.ts'
|
|
21
|
+
import { createOwnerPeer } from './host-runner.ts'
|
|
21
22
|
import { parseTaskDraft, TaskParseError } from './host-ai.ts'
|
|
22
23
|
import { TASK_PERMISSIONS, isTaskPermission, type TaskPermission } from './core/tasks.ts'
|
|
23
24
|
import { DEFAULT_SUBTASK_DEPTH, SUBTASK_DEPTH_MAX, SUBTASK_DEPTH_MIN } from './core/subtask.ts'
|
|
25
|
+
import { DEFAULT_SESSION_POLL_SECONDS, SESSION_POLL_MAX_SECONDS, SESSION_POLL_MIN_SECONDS } from './core/poll-cadence.ts'
|
|
26
|
+
import { DEFAULT_RUN_LAUNCH_WIDTH, RUN_LAUNCH_WIDTH_MAX, RUN_LAUNCH_WIDTH_MIN } from './core/launch-width.ts'
|
|
27
|
+
import {
|
|
28
|
+
DEFAULT_VERIFICATION_BUDGET_SECONDS,
|
|
29
|
+
DEFAULT_VERIFICATION_CALL_TIMEOUT_SECONDS,
|
|
30
|
+
VERIFICATION_BUDGET_MAX_SECONDS,
|
|
31
|
+
VERIFICATION_BUDGET_MIN_SECONDS,
|
|
32
|
+
VERIFICATION_CALL_TIMEOUT_MAX_SECONDS,
|
|
33
|
+
VERIFICATION_CALL_TIMEOUT_MIN_SECONDS,
|
|
34
|
+
verificationBudgetMs,
|
|
35
|
+
verificationCallTimeoutMs,
|
|
36
|
+
} from './core/verification-budget.ts'
|
|
24
37
|
import { DEFAULT_SESSION_PERMISSION } from './core/handover.ts'
|
|
38
|
+
import type { CardDefaults } from './core/card-defaults.ts'
|
|
25
39
|
import { buildTaskBoardTools, TASK_BOARD_TOOL_NAMES } from './host/agent-tools.ts'
|
|
26
40
|
import { PLUGIN_TOOL_SECTION_ORDERS, visibleToolText } from './tool-surface.ts'
|
|
27
41
|
import { makeTaskBoardRoutes } from './host-routes.ts'
|
|
@@ -88,12 +102,73 @@ export interface Config {
|
|
|
88
102
|
* of the root task opens, so the ceiling is deliberately small.
|
|
89
103
|
*/
|
|
90
104
|
maxSubtaskDepth?: Volatile<number>
|
|
105
|
+
/**
|
|
106
|
+
* How often, in seconds, the Host re-reads the DSH session roster while the
|
|
107
|
+
* board has something to reconcile: a running card, an open execution, or an
|
|
108
|
+
* active provider extension. An idle board with none of those does not poll
|
|
109
|
+
* at all, so this cadence only bounds how quickly a running card settles.
|
|
110
|
+
*/
|
|
111
|
+
sessionPollSeconds?: Volatile<number>
|
|
112
|
+
/**
|
|
113
|
+
* How many run launches this board may have in flight at once (1..16,
|
|
114
|
+
* default 3). One run opens its whole subtree, so without a bound the Host
|
|
115
|
+
* asks DSH for every member's session in the same tick; this is the mechanism
|
|
116
|
+
* that enforces the repository's measured guidance for heavy implementation
|
|
117
|
+
* subagents. Members wait their turn instead of being dropped: the subtree
|
|
118
|
+
* still opens completely, they only enter the running column in batches. Read
|
|
119
|
+
* at each admission, so an edit bounds the next launch of a run that is still
|
|
120
|
+
* queueing.
|
|
121
|
+
*/
|
|
122
|
+
runLaunchWidth?: Volatile<number>
|
|
91
123
|
/**
|
|
92
124
|
* Continuable-subagent provider the Agent Teams service uses to compose a
|
|
93
125
|
* teammate. Matches the Agent Teams tool plugin's `freshProvider` default;
|
|
94
126
|
* only team-mode runs use it.
|
|
95
127
|
*/
|
|
96
128
|
teamProvider?: string
|
|
129
|
+
/**
|
|
130
|
+
* GLOBAL native /goal switch (default OFF), the master control over whether
|
|
131
|
+
* this board starts a run with dsh's built-in /goal at all. A run uses native
|
|
132
|
+
* /goal only when THIS is on AND the task's own `goalRun` is not off; while
|
|
133
|
+
* it is off every task runs one plain turn.
|
|
134
|
+
*
|
|
135
|
+
* The value is frozen when an execution starts, so toggling it only affects
|
|
136
|
+
* executions that begin afterwards and never re-writes a task's stored
|
|
137
|
+
* `goalRun` preference. A run that consequently does not execute native
|
|
138
|
+
* /goal is marked as such (its acceptance applicability is `goal-disabled`)
|
|
139
|
+
* and is never reported as a passed goal acceptance or failed for lacking a
|
|
140
|
+
* completion call. Independent of `goalVerification`; acceptance governs the
|
|
141
|
+
* completing call of a goal-form run, this switch governs whether the run
|
|
142
|
+
* becomes a goal run.
|
|
143
|
+
*/
|
|
144
|
+
goalRunEnabled?: Volatile<boolean>
|
|
145
|
+
/**
|
|
146
|
+
* Agent preset a NEW card starts from (volatile, default blank = not set).
|
|
147
|
+
* A prefill, never a pin: the create dialog opens with it selected, the
|
|
148
|
+
* caller may override it, and the card stores what it was created with. It
|
|
149
|
+
* reaches the create path only when that caller opts in with
|
|
150
|
+
* `applyCardDefaults`, so the extension provider's own create and the legacy
|
|
151
|
+
* import are untouched.
|
|
152
|
+
*/
|
|
153
|
+
cardDefaultMode?: Volatile<string>
|
|
154
|
+
/**
|
|
155
|
+
* Permission a NEW card starts from (volatile, default blank = not set), one
|
|
156
|
+
* of the three presets. A prefill like the rest: a value above
|
|
157
|
+
* `sessionDefaultPermission` still has to be confirmed by a human before the
|
|
158
|
+
* card may run, because the pre-execution gate is what decides that.
|
|
159
|
+
*/
|
|
160
|
+
cardDefaultPermission?: Volatile<TaskPermission | ''>
|
|
161
|
+
/**
|
|
162
|
+
* Model a NEW card starts from (volatile, default blank = not set).
|
|
163
|
+
*/
|
|
164
|
+
cardDefaultModel?: Volatile<string>
|
|
165
|
+
/**
|
|
166
|
+
* Reasoning level a NEW card starts from (volatile, default blank = not set).
|
|
167
|
+
* Bound to `cardDefaultModel` exactly as a card's own level is bound to its
|
|
168
|
+
* own model: it applies only while the card's final model IS that default
|
|
169
|
+
* model, and a blank `cardDefaultModel` makes it inert.
|
|
170
|
+
*/
|
|
171
|
+
cardDefaultReasoningEffort?: Volatile<string>
|
|
97
172
|
/**
|
|
98
173
|
* Goal acceptance for executions this board starts (default ON). When on,
|
|
99
174
|
* update_goal(action: complete) inside a task execution is refused until an
|
|
@@ -119,6 +194,23 @@ export interface Config {
|
|
|
119
194
|
* sent, and the fallback to the model's own default is reported.
|
|
120
195
|
*/
|
|
121
196
|
goalVerificationReasoningEffort?: Volatile<string>
|
|
197
|
+
/**
|
|
198
|
+
* Ceiling of ONE judge request of a goal acceptance, in seconds
|
|
199
|
+
* (30..600, default 150). One acceptance issues six judge requests (three
|
|
200
|
+
* criteria times two rounds), so a ceiling that is too small turns a slow but
|
|
201
|
+
* healthy judge route into a wall of timeouts, and every timeout was charged
|
|
202
|
+
* as an acceptance anomaly. Raise it for a reasoning model reading a long
|
|
203
|
+
* trace.
|
|
204
|
+
*/
|
|
205
|
+
goalVerificationCallTimeoutSeconds?: Volatile<number>
|
|
206
|
+
/**
|
|
207
|
+
* Total ceiling of ONE goal acceptance attempt, in seconds (120..1800,
|
|
208
|
+
* default eight times the per-call default). Keep it at or above
|
|
209
|
+
* `goalVerificationCallTimeoutSeconds` times six or an acceptance can never
|
|
210
|
+
* finish: the attempt then ends early with a budget stop that judges nothing
|
|
211
|
+
* and spends no acceptance budget.
|
|
212
|
+
*/
|
|
213
|
+
goalVerificationBudgetSeconds?: Volatile<number>
|
|
122
214
|
}
|
|
123
215
|
|
|
124
216
|
/**
|
|
@@ -152,14 +244,32 @@ export interface ConfigInput {
|
|
|
152
244
|
sessionDefaultPermission?: TaskPermission
|
|
153
245
|
/** Subtask depth limit, 1..3. */
|
|
154
246
|
maxSubtaskDepth?: number
|
|
247
|
+
/** Roster-poll cadence in seconds while the board has work to reconcile. */
|
|
248
|
+
sessionPollSeconds?: number
|
|
249
|
+
/** Concurrent run launches allowed at once, 1..16. */
|
|
250
|
+
runLaunchWidth?: number
|
|
155
251
|
/** Continuable-subagent provider the Agent Teams service composes a teammate from. */
|
|
156
252
|
teamProvider?: string
|
|
253
|
+
/** Global native /goal switch; default off, frozen per execution. */
|
|
254
|
+
goalRunEnabled?: boolean
|
|
255
|
+
/** Agent preset a new card starts from; blank = not set. */
|
|
256
|
+
cardDefaultMode?: string
|
|
257
|
+
/** Permission a new card starts from; blank = not set. */
|
|
258
|
+
cardDefaultPermission?: TaskPermission | ''
|
|
259
|
+
/** Model a new card starts from; blank = not set. */
|
|
260
|
+
cardDefaultModel?: string
|
|
261
|
+
/** Reasoning level a new card starts from; blank = not set. */
|
|
262
|
+
cardDefaultReasoningEffort?: string
|
|
157
263
|
/** Goal acceptance switch. */
|
|
158
264
|
goalVerification?: boolean
|
|
159
265
|
/** Judge model route for goal acceptance; blank inherits the host default. */
|
|
160
266
|
goalVerificationModel?: string
|
|
161
267
|
/** Judge reasoning effort; blank inherits the host default. */
|
|
162
268
|
goalVerificationReasoningEffort?: string
|
|
269
|
+
/** Ceiling of one judge request of a goal acceptance, in seconds. */
|
|
270
|
+
goalVerificationCallTimeoutSeconds?: number
|
|
271
|
+
/** Total ceiling of one goal acceptance attempt, in seconds. */
|
|
272
|
+
goalVerificationBudgetSeconds?: number
|
|
163
273
|
}
|
|
164
274
|
|
|
165
275
|
export const Config: z<ConfigInput, Config> = z.object({
|
|
@@ -170,15 +280,31 @@ export const Config: z<ConfigInput, Config> = z.object({
|
|
|
170
280
|
proxyTokenEnv: z.string().min(1).default(DEFAULT_PROXY_TOKEN_ENV),
|
|
171
281
|
sessionDefaultPermission: z.union(TASK_PERMISSIONS),
|
|
172
282
|
maxSubtaskDepth: z.number().min(SUBTASK_DEPTH_MIN).max(SUBTASK_DEPTH_MAX).default(DEFAULT_SUBTASK_DEPTH).volatile(),
|
|
283
|
+
sessionPollSeconds: z.number().min(SESSION_POLL_MIN_SECONDS).max(SESSION_POLL_MAX_SECONDS).default(DEFAULT_SESSION_POLL_SECONDS).volatile(),
|
|
284
|
+
runLaunchWidth: z.number().min(RUN_LAUNCH_WIDTH_MIN).max(RUN_LAUNCH_WIDTH_MAX).default(DEFAULT_RUN_LAUNCH_WIDTH).volatile(),
|
|
173
285
|
teamProvider: z.string().min(1).default(DEFAULT_TEAM_PROVIDER),
|
|
286
|
+
goalRunEnabled: z.boolean().default(false).volatile(),
|
|
287
|
+
cardDefaultMode: z.string().default('').volatile(),
|
|
288
|
+
cardDefaultPermission: z.union([...TASK_PERMISSIONS, '']).default('').volatile(),
|
|
289
|
+
cardDefaultModel: z.string().default('').volatile(),
|
|
290
|
+
cardDefaultReasoningEffort: z.string().default('').volatile(),
|
|
174
291
|
goalVerification: z.boolean().default(true).volatile(),
|
|
175
292
|
goalVerificationModel: z.string().default('').volatile(),
|
|
176
293
|
goalVerificationReasoningEffort: z.string().default('').volatile(),
|
|
294
|
+
goalVerificationCallTimeoutSeconds: z.number().min(VERIFICATION_CALL_TIMEOUT_MIN_SECONDS).max(VERIFICATION_CALL_TIMEOUT_MAX_SECONDS).default(DEFAULT_VERIFICATION_CALL_TIMEOUT_SECONDS).volatile(),
|
|
295
|
+
goalVerificationBudgetSeconds: z.number().min(VERIFICATION_BUDGET_MIN_SECONDS).max(VERIFICATION_BUDGET_MAX_SECONDS).default(DEFAULT_VERIFICATION_BUDGET_SECONDS).volatile(),
|
|
177
296
|
})
|
|
178
297
|
|
|
179
298
|
/** Schema default for the goal-acceptance switch, re-read for hand-built contexts. */
|
|
180
299
|
export const DEFAULT_GOAL_VERIFICATION = true
|
|
181
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Schema default for the GLOBAL native-/goal switch, re-read for hand-built
|
|
303
|
+
* contexts. Deliberately false: a deployment that never configured it (and
|
|
304
|
+
* every card written before the option existed) runs plain single turns.
|
|
305
|
+
*/
|
|
306
|
+
export const DEFAULT_GOAL_RUN = false
|
|
307
|
+
|
|
182
308
|
declare module '@deepseek-ai/cordis' {
|
|
183
309
|
interface Events {
|
|
184
310
|
/**
|
|
@@ -395,6 +521,70 @@ export function resolveLlmRuntime(ctx: Context): LlmRuntime | undefined {
|
|
|
395
521
|
}
|
|
396
522
|
}
|
|
397
523
|
|
|
524
|
+
/**
|
|
525
|
+
* The subset of `sessionController` the board uses to wake a cold persisted
|
|
526
|
+
* session before running a slash command on it (issue #1861).
|
|
527
|
+
*/
|
|
528
|
+
interface SessionControllerFace {
|
|
529
|
+
resolveAgent(
|
|
530
|
+
sessionId: Parameters<Context['agents']['get']>[0],
|
|
531
|
+
): Promise<
|
|
532
|
+
| { readonly agent: Parameters<Context['commands']['execute']>[0] }
|
|
533
|
+
| { readonly error: { readonly message?: string } }
|
|
534
|
+
>
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Resolve the optional `sessionController` service. Like the tool registry and
|
|
539
|
+
* the llm runtime, it is read dynamically so capture-only test contexts that do
|
|
540
|
+
* not mount the full session controller still activate the board.
|
|
541
|
+
* @param ctx - the plugin context.
|
|
542
|
+
* @returns the session controller face, or undefined when unavailable.
|
|
543
|
+
*/
|
|
544
|
+
export function resolveSessionController(ctx: Context): SessionControllerFace | undefined {
|
|
545
|
+
try {
|
|
546
|
+
const controller = (ctx as { get?: (name: string) => unknown }).get?.('sessionController') as SessionControllerFace | undefined
|
|
547
|
+
return controller !== undefined && typeof controller.resolveAgent === 'function' ? controller : undefined
|
|
548
|
+
} catch {
|
|
549
|
+
return undefined
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Resolve the live Agent for an execution session, resuming a cold persisted
|
|
555
|
+
* session through `sessionController.resolveAgent` when it is not yet in
|
|
556
|
+
* `ctx.agents` (issue #1861).
|
|
557
|
+
*
|
|
558
|
+
* A fresh run (`session/create`) or a session the browser is currently
|
|
559
|
+
* following is already in `ctx.agents`, so the fast path returns immediately.
|
|
560
|
+
* A scheduled or manual reuse of a cold session — one that `session/list`
|
|
561
|
+
* reports as idle from disk without activating its Agent — is not in
|
|
562
|
+
* `ctx.agents` when `pinAndPrompt` runs `/permission` ahead of
|
|
563
|
+
* `session/selectModel` and `session/prompt`; delegating to
|
|
564
|
+
* `sessionController.resolveAgent` resumes it with its recorded preset and
|
|
565
|
+
* model-selection state, matching what those gateway endpoints do next.
|
|
566
|
+
* @param ctx - the plugin context.
|
|
567
|
+
* @param sessionId - the target execution session id.
|
|
568
|
+
* @returns the live Agent for `sessionId`.
|
|
569
|
+
*/
|
|
570
|
+
export async function resolveExecutionAgent(
|
|
571
|
+
ctx: Context,
|
|
572
|
+
sessionId: Parameters<Context['agents']['get']>[0],
|
|
573
|
+
): Promise<Parameters<Context['commands']['execute']>[0]> {
|
|
574
|
+
const live = ctx.agents.get(sessionId)
|
|
575
|
+
if (live !== undefined) return live
|
|
576
|
+
const controller = resolveSessionController(ctx)
|
|
577
|
+
if (controller !== undefined) {
|
|
578
|
+
const resolved = await controller.resolveAgent(sessionId)
|
|
579
|
+
if ('agent' in resolved && resolved.agent !== undefined) return resolved.agent
|
|
580
|
+
const detail = 'error' in resolved && typeof resolved.error?.message === 'string' && resolved.error.message !== ''
|
|
581
|
+
? `: ${resolved.error.message}`
|
|
582
|
+
: ''
|
|
583
|
+
throw new Error(`execution session ${sessionId} is not available${detail}`)
|
|
584
|
+
}
|
|
585
|
+
throw new Error(`execution session ${sessionId} is not available`)
|
|
586
|
+
}
|
|
587
|
+
|
|
398
588
|
/**
|
|
399
589
|
* Activate the board's host half: ledger, routes, cron scheduler, power
|
|
400
590
|
* inhibitor, and the model-facing announcement.
|
|
@@ -419,6 +609,14 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
419
609
|
const preventIdleSleep = (): boolean => readConfigField(config?.preventIdleSleep, false)
|
|
420
610
|
/** Current subtask depth limit (read live: the settings card edits it in place). */
|
|
421
611
|
const maxSubtaskDepth = (): number => readConfigField(config?.maxSubtaskDepth, DEFAULT_SUBTASK_DEPTH)
|
|
612
|
+
/** Current roster-poll cadence in seconds (read live: the settings card edits it in place). */
|
|
613
|
+
const sessionPollSeconds = (): number => readConfigField(config?.sessionPollSeconds, DEFAULT_SESSION_POLL_SECONDS)
|
|
614
|
+
/**
|
|
615
|
+
* Current run-launch admission width. Read live on every admission, so the
|
|
616
|
+
* settings card bounds the next launch of a run that is still queueing without
|
|
617
|
+
* remounting the row; the Host clamps a hand-edited value into the schema range.
|
|
618
|
+
*/
|
|
619
|
+
const runLaunchWidth = (): number => readConfigField(config?.runLaunchWidth, DEFAULT_RUN_LAUNCH_WIDTH)
|
|
422
620
|
/**
|
|
423
621
|
* The baseline the permission confirmation gate judges against: the row's own
|
|
424
622
|
* `sessionDefaultPermission` when the deployment pins one, otherwise the Host's
|
|
@@ -435,6 +633,15 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
435
633
|
model: readConfigField(config?.goalVerificationModel, ''),
|
|
436
634
|
reasoningEffort: readConfigField(config?.goalVerificationReasoningEffort, ''),
|
|
437
635
|
})
|
|
636
|
+
/**
|
|
637
|
+
* The acceptance time ceilings, read live: raising one must unblock a card
|
|
638
|
+
* whose acceptance is stuck on a slow judge route without a remount, so
|
|
639
|
+
* these deliberately are NOT frozen into the per-execution contract.
|
|
640
|
+
*/
|
|
641
|
+
const verificationCallTimeoutMsLive = (): number =>
|
|
642
|
+
verificationCallTimeoutMs(readConfigField(config?.goalVerificationCallTimeoutSeconds, DEFAULT_VERIFICATION_CALL_TIMEOUT_SECONDS))
|
|
643
|
+
const verificationBudgetMsLive = (): number =>
|
|
644
|
+
verificationBudgetMs(readConfigField(config?.goalVerificationBudgetSeconds, DEFAULT_VERIFICATION_BUDGET_SECONDS))
|
|
438
645
|
// The catalog reader needs the service, and the service needs the reader;
|
|
439
646
|
// the reader only runs after start(), so a late holder is enough.
|
|
440
647
|
let hostForCatalog: TaskBoardHostService | undefined
|
|
@@ -442,18 +649,46 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
442
649
|
const runner = hostForCatalog?.runner
|
|
443
650
|
return runner === undefined ? undefined : normalizeCatalog(await runner.modelCatalog())
|
|
444
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Live reader of the GLOBAL native-/goal switch. The service calls it exactly
|
|
654
|
+
* once per execution and carries the value, so a settings edit only reaches
|
|
655
|
+
* executions that start afterwards.
|
|
656
|
+
*/
|
|
657
|
+
const goalRunEnabled = (): boolean => readConfigField(config?.goalRunEnabled, DEFAULT_GOAL_RUN)
|
|
658
|
+
/**
|
|
659
|
+
* Live reader of the new-card defaults, read at every use like the switch
|
|
660
|
+
* above: the create dialog prefills from the published snapshot, and each
|
|
661
|
+
* creating session re-reads them when it submits the create. A blank value
|
|
662
|
+
* means "not set" and reaches the resolver as an absent target.
|
|
663
|
+
*/
|
|
664
|
+
const cardDefaults = (): CardDefaults => {
|
|
665
|
+
const permission = readConfigField<TaskPermission | ''>(config?.cardDefaultPermission, '')
|
|
666
|
+
return {
|
|
667
|
+
mode: readConfigField(config?.cardDefaultMode, '').trim() || undefined,
|
|
668
|
+
permission: isTaskPermission(permission) ? permission : undefined,
|
|
669
|
+
model: readConfigField(config?.cardDefaultModel, '').trim() || undefined,
|
|
670
|
+
reasoningEffort: readConfigField(config?.cardDefaultReasoningEffort, '').trim() || undefined,
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
// The 0.2.1 gateway requires every request to name the peer it speaks for:
|
|
674
|
+
// the board calls as the host-local owner, so its peer is minted on this
|
|
675
|
+
// fiber and aborts with it (see createOwnerPeer).
|
|
676
|
+
const ownerPeer = createOwnerPeer(ctx)
|
|
445
677
|
const host = new TaskBoardHostService(ctx.typertGateway, {
|
|
446
678
|
workspaceRegistry: ctx.workspaceRegistry,
|
|
679
|
+
ownerPeer,
|
|
447
680
|
sessionDefaultPermission,
|
|
448
681
|
maxSubtaskDepth: maxSubtaskDepth(),
|
|
682
|
+
goalRunEnabled,
|
|
683
|
+
runLaunchWidth,
|
|
684
|
+
cardDefaults,
|
|
449
685
|
verificationSettings,
|
|
450
686
|
verificationCatalog,
|
|
451
687
|
timers: resolveHostTimers(ctx),
|
|
452
688
|
team: buildTeamDispatcher(ctx, config?.teamProvider ?? DEFAULT_TEAM_PROVIDER),
|
|
453
689
|
commandDispatcher: {
|
|
454
690
|
async execute(sessionId, line, signal) {
|
|
455
|
-
const agent = ctx
|
|
456
|
-
if (agent === undefined) throw new Error(`execution session ${sessionId} is not available`)
|
|
691
|
+
const agent = await resolveExecutionAgent(ctx, sessionId)
|
|
457
692
|
return (await ctx.commands.execute(agent, line, [], signal))?.result
|
|
458
693
|
},
|
|
459
694
|
},
|
|
@@ -461,7 +696,7 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
461
696
|
hostForCatalog = host
|
|
462
697
|
// Configuration before start(): a disabled row must not take the first
|
|
463
698
|
// scheduler tick, which would roll schedules the board is not running.
|
|
464
|
-
host.setConfiguration(enabled(), preventIdleSleep())
|
|
699
|
+
host.setConfiguration(enabled(), preventIdleSleep(), sessionPollSeconds())
|
|
465
700
|
host.start()
|
|
466
701
|
|
|
467
702
|
// External providers. The board publishes its registration service so any
|
|
@@ -543,6 +778,8 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
543
778
|
// deployment records it; the acceptance degrades to the trajectory alone
|
|
544
779
|
// when it does not.
|
|
545
780
|
workspaceChanges: () => probeWorkspaceChanges(ctx),
|
|
781
|
+
callTimeoutMs: verificationCallTimeoutMsLive,
|
|
782
|
+
budgetMs: verificationBudgetMsLive,
|
|
546
783
|
logger: {
|
|
547
784
|
warn: (message: string, ...rest: unknown[]) => {
|
|
548
785
|
const logger = (ctx as { logger?: { warn?: (...args: unknown[]) => void } }).logger
|
|
@@ -586,7 +823,7 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
586
823
|
}, 'task-board: host ledger, scheduler, and routes')
|
|
587
824
|
|
|
588
825
|
let disposeSection: (() => void) | undefined
|
|
589
|
-
let applied: { enabled: boolean; announceToAgent: boolean; preventIdleSleep: boolean; maxSubtaskDepth: number } | undefined
|
|
826
|
+
let applied: { enabled: boolean; announceToAgent: boolean; preventIdleSleep: boolean; maxSubtaskDepth: number; sessionPollSeconds: number } | undefined
|
|
590
827
|
|
|
591
828
|
// Apply the current values to the host service and the announcement. A
|
|
592
829
|
// commit that changes nothing visible is a no-op, so following a coarse
|
|
@@ -594,13 +831,19 @@ function applyImpl(ctx: Context, config?: Config): void {
|
|
|
594
831
|
// under one disposer: re-registering first tears the old one down so a
|
|
595
832
|
// duplicate-name registration never throws.
|
|
596
833
|
const sync = (): void => {
|
|
597
|
-
const next = {
|
|
598
|
-
|
|
834
|
+
const next = {
|
|
835
|
+
enabled: enabled(),
|
|
836
|
+
announceToAgent: announceToAgent(),
|
|
837
|
+
preventIdleSleep: preventIdleSleep(),
|
|
838
|
+
maxSubtaskDepth: maxSubtaskDepth(),
|
|
839
|
+
sessionPollSeconds: sessionPollSeconds(),
|
|
840
|
+
}
|
|
841
|
+
if (applied !== undefined && applied.enabled === next.enabled && applied.announceToAgent === next.announceToAgent && applied.preventIdleSleep === next.preventIdleSleep && applied.maxSubtaskDepth === next.maxSubtaskDepth && applied.sessionPollSeconds === next.sessionPollSeconds) {
|
|
599
842
|
return
|
|
600
843
|
}
|
|
601
844
|
applied = next
|
|
602
845
|
host.ledger.setMaxSubtaskDepth(next.maxSubtaskDepth)
|
|
603
|
-
host.setConfiguration(next.enabled, next.preventIdleSleep)
|
|
846
|
+
host.setConfiguration(next.enabled, next.preventIdleSleep, next.sessionPollSeconds)
|
|
604
847
|
setToolsEnabled(next.enabled)
|
|
605
848
|
if (disposeSection !== undefined) {
|
|
606
849
|
disposeSection()
|