@linxin666/dsh-client-ui-task-board 0.4.6 → 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 +14 -6
- package/README.zh.md +14 -6
- package/lib/client.js +1502 -820
- package/lib/client.js.map +1 -1
- package/lib/index.js +674 -75
- package/lib/types/client/CardDefaultPresetField.d.ts +35 -0
- package/lib/types/client/TaskBoardSettingsCard.d.ts +49 -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/locales.d.ts +16 -0
- package/lib/types/core/card-defaults.d.ts +78 -0
- package/lib/types/core/controller.d.ts +32 -7
- package/lib/types/core/launch-width.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 +19 -0
- package/lib/types/core/use-cases/task-create.d.ts +10 -5
- package/lib/types/core/use-cases/task-update.d.ts +1 -1
- package/lib/types/host/launch-admission.d.ts +72 -0
- package/lib/types/host-ledger.d.ts +9 -4
- package/lib/types/host-runner.d.ts +79 -4
- package/lib/types/host-service.d.ts +85 -2
- package/lib/types/index.d.ts +87 -0
- package/lib/types/protocol.d.ts +13 -0
- package/package.json +28 -28
- package/src/client/CardDefaultPresetField.tsx +101 -0
- package/src/client/TaskBoardSettingsCard.tsx +214 -16
- package/src/client/board/LinkSubtaskModal.tsx +8 -0
- package/src/client/board/NewTaskModal.tsx +86 -40
- package/src/client/board/ReasoningEffortField.tsx +50 -0
- package/src/client/board/TaskDetail.tsx +42 -6
- 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/team-run-promotion.ts +39 -0
- package/src/client/index.ts +98 -94
- package/src/client/locales.ts +34 -2
- package/src/client/settings-entry-form.ts +0 -1
- package/src/core/card-defaults.ts +132 -0
- package/src/core/controller.ts +44 -9
- package/src/core/launch-width.ts +38 -0
- package/src/core/reasoning-effort.ts +92 -0
- package/src/core/store.ts +5 -0
- package/src/core/subtask.ts +48 -13
- package/src/core/tasks.ts +20 -0
- package/src/core/use-cases/task-create.ts +27 -16
- package/src/core/use-cases/task-update.ts +6 -1
- package/src/host/agent-tools.ts +21 -8
- package/src/host/launch-admission.ts +140 -0
- package/src/host-ledger.ts +18 -6
- package/src/host-runner.ts +184 -18
- package/src/host-service.ts +247 -23
- package/src/index.ts +149 -2
- package/src/protocol.ts +28 -4
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The default-agent-preset picker of the settings card's new-card-defaults
|
|
3
|
+
* topic.
|
|
4
|
+
*
|
|
5
|
+
* It renders the rows the create dialog's own mode picker renders — built-in
|
|
6
|
+
* presets first, then user presets, each labelled with its default and
|
|
7
|
+
* unavailable suffixes (board/preset-label.ts owns both) — and it renders a
|
|
8
|
+
* preset that cannot compose a session as a row that is visible but NOT
|
|
9
|
+
* selectable, so the board never stores a default no session could be composed
|
|
10
|
+
* from.
|
|
11
|
+
*
|
|
12
|
+
* The shared ChoiceField cannot express that: its choices carry no disabled
|
|
13
|
+
* state, and a stored pin the roster no longer serves would render as an empty
|
|
14
|
+
* trigger rather than as the unavailable preset it is. Both need a native
|
|
15
|
+
* `<select>` (the fallback the shared SelectField itself takes under an
|
|
16
|
+
* appearance skin), styled with the settings card's own field classes so the
|
|
17
|
+
* control stays a sibling of the fields beside it.
|
|
18
|
+
*/
|
|
19
|
+
import type { ExecutionPresetOption } from '../core/controller.ts';
|
|
20
|
+
import type { FieldProps } from './PluginSettingsCard.tsx';
|
|
21
|
+
/** Props of the default-preset field: the shared field contract plus the roster. */
|
|
22
|
+
export interface CardDefaultPresetFieldProps extends FieldProps {
|
|
23
|
+
/**
|
|
24
|
+
* The deployment's agent-preset roster, or undefined while its runtime read
|
|
25
|
+
* has not answered: an unread roster offers the inherit choice alone instead
|
|
26
|
+
* of calling every stored pin "removed".
|
|
27
|
+
*/
|
|
28
|
+
presets: readonly ExecutionPresetOption[] | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Render the default-preset select.
|
|
32
|
+
* @param props - the field contract and the roster to list.
|
|
33
|
+
* @returns the field.
|
|
34
|
+
*/
|
|
35
|
+
export declare function CardDefaultPresetField(props: CardDefaultPresetFieldProps): import("react").JSX.Element;
|
|
@@ -7,6 +7,7 @@ import type { InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime } from '@d
|
|
|
7
7
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
8
8
|
import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
9
9
|
import type { TaskBoardExtensionDispatch } from '../core/extension.ts';
|
|
10
|
+
import type { ExecutionPresetOption } from '../core/controller.ts';
|
|
10
11
|
import { type CardActions, type CardShell, type FieldState as CardFieldState } from './settings-form.ts';
|
|
11
12
|
/** The task-board fields this card edits (the namespace's full schema). */
|
|
12
13
|
export interface TaskBoardSettings {
|
|
@@ -20,6 +21,12 @@ export interface TaskBoardSettings {
|
|
|
20
21
|
maxSubtaskDepth?: number;
|
|
21
22
|
/** Roster-poll cadence in seconds while the board has work to reconcile. */
|
|
22
23
|
sessionPollSeconds?: number;
|
|
24
|
+
/**
|
|
25
|
+
* How many run launches may be in flight at once (1..16, default 3). One run
|
|
26
|
+
* opens its whole subtree, so this bounds the burst of sessions a single run
|
|
27
|
+
* action creates; members enter the running column in batches, none is dropped.
|
|
28
|
+
*/
|
|
29
|
+
runLaunchWidth?: number;
|
|
23
30
|
/**
|
|
24
31
|
* GLOBAL native /goal switch (default off): the master control over whether
|
|
25
32
|
* this board starts a run with dsh's built-in /goal at all. Frozen per
|
|
@@ -32,6 +39,20 @@ export interface TaskBoardSettings {
|
|
|
32
39
|
goalVerificationModel?: string;
|
|
33
40
|
/** Judge reasoning effort; blank inherits the host default level. */
|
|
34
41
|
goalVerificationReasoningEffort?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Agent preset the create dialog of this board opens with. Blank pins
|
|
44
|
+
* nothing, so a new card follows the deployment default as before.
|
|
45
|
+
*/
|
|
46
|
+
cardDefaultMode?: string;
|
|
47
|
+
/** Permission the create dialog opens with; blank applies no default. */
|
|
48
|
+
cardDefaultPermission?: string;
|
|
49
|
+
/** Execution model route the create dialog opens with; blank applies none. */
|
|
50
|
+
cardDefaultModel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Reasoning level bound to `cardDefaultModel`; it applies only while a
|
|
53
|
+
* card's final model IS that configured route, and is inert without one.
|
|
54
|
+
*/
|
|
55
|
+
cardDefaultReasoningEffort?: string;
|
|
35
56
|
}
|
|
36
57
|
/** What the task-board card renders. */
|
|
37
58
|
export interface TaskBoardSettingsCardState extends CardShell {
|
|
@@ -45,6 +66,8 @@ export interface TaskBoardSettingsCardState extends CardShell {
|
|
|
45
66
|
maxSubtaskDepth: CardFieldState;
|
|
46
67
|
/** Roster-poll cadence field. */
|
|
47
68
|
sessionPollSeconds: CardFieldState;
|
|
69
|
+
/** Run-launch admission width field. */
|
|
70
|
+
runLaunchWidth: CardFieldState;
|
|
48
71
|
/** GLOBAL native /goal switch. */
|
|
49
72
|
goalRunEnabled: CardFieldState;
|
|
50
73
|
/** Goal-acceptance switch. */
|
|
@@ -53,6 +76,20 @@ export interface TaskBoardSettingsCardState extends CardShell {
|
|
|
53
76
|
goalVerificationModel: CardFieldState;
|
|
54
77
|
/** Judge reasoning-effort field. */
|
|
55
78
|
goalVerificationReasoningEffort: CardFieldState;
|
|
79
|
+
/** New-card default agent preset. */
|
|
80
|
+
cardDefaultMode: CardFieldState;
|
|
81
|
+
/** New-card default permission. */
|
|
82
|
+
cardDefaultPermission: CardFieldState;
|
|
83
|
+
/** New-card default model route. */
|
|
84
|
+
cardDefaultModel: CardFieldState;
|
|
85
|
+
/** New-card default reasoning level. */
|
|
86
|
+
cardDefaultReasoningEffort: CardFieldState;
|
|
87
|
+
/**
|
|
88
|
+
* The deployment's agent-preset roster, published by the runtime read the
|
|
89
|
+
* plugin wires; undefined until it answers, which leaves the default-preset
|
|
90
|
+
* field offering the inherit choice alone.
|
|
91
|
+
*/
|
|
92
|
+
presets?: readonly ExecutionPresetOption[];
|
|
56
93
|
}
|
|
57
94
|
/** The registration-side face the card's slot entry injects. */
|
|
58
95
|
export interface TaskBoardSettingsCardFace extends CardActions {
|
|
@@ -68,9 +105,21 @@ export declare class TaskBoardSettingsCardController {
|
|
|
68
105
|
private readonly dispatch;
|
|
69
106
|
private readonly form;
|
|
70
107
|
private readonly store;
|
|
108
|
+
/** The deployment's agent-preset roster, once its runtime read has answered. */
|
|
109
|
+
private presets;
|
|
71
110
|
/** @param scope - the bound configuration form for the `task-board` namespace. */
|
|
72
111
|
constructor(scope: ConfigForm<TaskBoardSettings>, dispatch: TaskBoardExtensionDispatch);
|
|
73
112
|
private projection;
|
|
113
|
+
/**
|
|
114
|
+
* Publish the deployment's agent-preset roster to the default-preset field.
|
|
115
|
+
* The roster is a runtime fact read outside this card (src/client/index.ts
|
|
116
|
+
* wires it once for both the board's pickers and this topic); it can arrive
|
|
117
|
+
* late or not at all, and until it does the field lists the inherit choice
|
|
118
|
+
* alone. This never blocks a save: a deployment that serves no roster still
|
|
119
|
+
* has a writable settings document.
|
|
120
|
+
* @param presets - the roster rows.
|
|
121
|
+
*/
|
|
122
|
+
setPresetRoster(presets: readonly ExecutionPresetOption[]): void;
|
|
74
123
|
/**
|
|
75
124
|
* Build the face the card's slot registration injects.
|
|
76
125
|
* @returns the card's snapshot and its form actions.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning-effort field: one picker shared by both execution-target editors
|
|
3
|
+
* (the create dialog and the detail page), so the two never describe the same
|
|
4
|
+
* capability differently. The levels are the ones the picked model's catalog
|
|
5
|
+
* entry declares; an empty value is a real choice — "follow the model or Host
|
|
6
|
+
* default" — and is the default state.
|
|
7
|
+
*
|
|
8
|
+
* A stored level the roster no longer lists (the model left the roster, or its
|
|
9
|
+
* adapter changed) stays shown and labelled, but is not offered again, so the
|
|
10
|
+
* field never silently shows a different value than the one the card will ask
|
|
11
|
+
* for while the choosable set stays exactly the levels the model declares.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExecutionModelOption } from '../../core/controller.ts';
|
|
14
|
+
/** The controlled reasoning-effort picker. */
|
|
15
|
+
export declare function ReasoningEffortField({ models, modelId, value, pending, onChange }: {
|
|
16
|
+
/** The roster the picked model is looked up in. */
|
|
17
|
+
models: readonly ExecutionModelOption[];
|
|
18
|
+
/** The model this card pins; '' means "no pin". */
|
|
19
|
+
modelId: string;
|
|
20
|
+
/** The selected effort; '' means "follow the model or Host default". */
|
|
21
|
+
value: string;
|
|
22
|
+
/** Whether a mutation is in flight (the field locks with the rest of the form). */
|
|
23
|
+
pending: boolean;
|
|
24
|
+
onChange: (next: string) => void;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution model options: the picker rows built from the official
|
|
3
|
+
* `session/modelCatalog` reply, and the reasoning-effort derivation both
|
|
4
|
+
* execution-target editors read off them (the create dialog and the detail
|
|
5
|
+
* page share one contract here, so they cannot promise different levels).
|
|
6
|
+
*
|
|
7
|
+
* The pickers must offer each model's real reasoning levels, which only the
|
|
8
|
+
* catalog declares — so the reply is normalized once, here, instead of every
|
|
9
|
+
* picker re-reading the wire shape. The fallback discovery path carries no
|
|
10
|
+
* capability metadata at all; its rows stay silent about reasoning rather than
|
|
11
|
+
* claiming a model supports none.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExecutionModelOption } from '../../core/controller.ts';
|
|
14
|
+
import type { TaskBoardKey } from '../locales.ts';
|
|
15
|
+
/**
|
|
16
|
+
* Normalize a `session/modelCatalog` reply into picker rows: one row per model
|
|
17
|
+
* of every provider group, keyed by the qualified route an execution pins.
|
|
18
|
+
* @param value - the raw catalog reply.
|
|
19
|
+
* @returns the rows, empty when the reply is unreadable.
|
|
20
|
+
*/
|
|
21
|
+
export declare function modelOptionsFromCatalog(value: unknown): ExecutionModelOption[];
|
|
22
|
+
/**
|
|
23
|
+
* Normalize the flat `llm/discoverModels` list into picker rows. That reply
|
|
24
|
+
* names models only, so every row leaves the reasoning capability unknown.
|
|
25
|
+
* @param value - the raw discovery list.
|
|
26
|
+
* @returns the rows, empty when the list is unreadable.
|
|
27
|
+
*/
|
|
28
|
+
export declare function modelOptionsFromDiscoveredModels(value: unknown): ExecutionModelOption[];
|
|
29
|
+
/**
|
|
30
|
+
* The picker rows of a model roster: the qualified `provider/model` route as
|
|
31
|
+
* the value a pin stores, and the provider beside the model name so two
|
|
32
|
+
* providers offering one model name stay distinguishable.
|
|
33
|
+
* @param models - the roster rows.
|
|
34
|
+
* @returns the choice rows, in roster order.
|
|
35
|
+
*/
|
|
36
|
+
export declare function modelChoiceRows(models: readonly ExecutionModelOption[]): Array<{
|
|
37
|
+
value: string;
|
|
38
|
+
label: string;
|
|
39
|
+
}>;
|
|
40
|
+
/**
|
|
41
|
+
* The capability row the roster publishes for one model route.
|
|
42
|
+
* @returns undefined when no model is pinned, or the roster does not describe
|
|
43
|
+
* the pinned one — an unknown model is not the same as a model without
|
|
44
|
+
* reasoning.
|
|
45
|
+
*/
|
|
46
|
+
export declare function reasoningOfModel(models: readonly ExecutionModelOption[], modelId: string): ExecutionModelOption['reasoning'] | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* The effort ids the picker offers for a model, in catalog order.
|
|
49
|
+
* @returns an empty list when the model is unpinned, unknown, declares no
|
|
50
|
+
* reasoning, or publishes no selectable level.
|
|
51
|
+
*/
|
|
52
|
+
export declare function reasoningEffortsFor(models: readonly ExecutionModelOption[], modelId: string): string[];
|
|
53
|
+
/** Whether the effort picker may be operated: a pinned model with declared, selectable levels. */
|
|
54
|
+
export declare function reasoningPickerEnabled(models: readonly ExecutionModelOption[], modelId: string): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* The effort to keep when the picked model changes. Only a model that declares
|
|
57
|
+
* its levels can invalidate one: a model the roster cannot describe keeps the
|
|
58
|
+
* stored value, because the roster has no grounds to call it invalid.
|
|
59
|
+
* @param effort - the effort currently stored/selected ('' = follow the default).
|
|
60
|
+
* @returns the effort to keep.
|
|
61
|
+
*/
|
|
62
|
+
export declare function reconcileReasoningEffort(models: readonly ExecutionModelOption[], modelId: string, effort: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* The copy explaining why the picker is in its current state. One lookup for
|
|
65
|
+
* both editors, so the create dialog and the detail page never drift apart.
|
|
66
|
+
*/
|
|
67
|
+
export declare function reasoningHintKey(models: readonly ExecutionModelOption[], modelId: string): TaskBoardKey;
|
|
@@ -20,3 +20,24 @@ export declare function presetLabel(preset: Pick<ExecutionPresetOption, 'id' | '
|
|
|
20
20
|
* marks with `isDefault`.
|
|
21
21
|
*/
|
|
22
22
|
export declare function inheritPresetLabel(presets: readonly ExecutionPresetOption[]): string;
|
|
23
|
+
/** One preset row a picker renders: the stored id, its label, and whether it may be picked. */
|
|
24
|
+
export interface PresetChoiceRow {
|
|
25
|
+
/** The value a pin stores. */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Display label, already carrying the default and unavailable suffixes. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** True when the preset cannot compose a session: the row is shown but not selectable. */
|
|
30
|
+
disabled: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The picker rows of one roster, split into the built-in and the user presets.
|
|
34
|
+
* Both pickers render these rows — the create dialog's mode select and the
|
|
35
|
+
* settings card's default-preset field — so their wording and their
|
|
36
|
+
* unavailable rows cannot drift apart.
|
|
37
|
+
* @param presets - the roster options.
|
|
38
|
+
* @returns one row list per group, in roster order.
|
|
39
|
+
*/
|
|
40
|
+
export declare function presetChoiceRows(presets: readonly ExecutionPresetOption[]): {
|
|
41
|
+
builtin: PresetChoiceRow[];
|
|
42
|
+
custom: PresetChoiceRow[];
|
|
43
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The agent-preset roster the execution-target pickers read: one read of the
|
|
3
|
+
* generated api-remotes face, and its normalization into the option rows the
|
|
4
|
+
* board controller and the settings card's new-card-defaults topic both
|
|
5
|
+
* consume.
|
|
6
|
+
*
|
|
7
|
+
* The roster is a runtime fact of the deployment, not ledger state. The
|
|
8
|
+
* namespace mounts with the official api-remotes assembly, so the read itself
|
|
9
|
+
* is wired through a scoped inject at the call site (see src/client/index.ts);
|
|
10
|
+
* this module owns only the shape both consumers agree on, so neither has to
|
|
11
|
+
* know how the wire face answers.
|
|
12
|
+
*/
|
|
13
|
+
import type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client';
|
|
14
|
+
import type { ExecutionPresetOption } from '../../core/controller.ts';
|
|
15
|
+
/** The generated Remote namespace the mode pickers read their roster from. */
|
|
16
|
+
export type PresetRemote = ClientRemote['agentPresets'];
|
|
17
|
+
/** One agent-preset row the wire face answers with. */
|
|
18
|
+
export interface PresetRosterRow {
|
|
19
|
+
id: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
/** Why this preset cannot compose a session; absent when it can. */
|
|
23
|
+
broken?: string;
|
|
24
|
+
isDefault: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read the agent-preset roster of one deployment. The caller passes the
|
|
28
|
+
* namespace resolved inside its scoped inject, so a host that serves no such
|
|
29
|
+
* namespace never reaches here; a host that serves it answers `ok: false`
|
|
30
|
+
* instead, which leaves the caller's options untouched.
|
|
31
|
+
* @param remote - the `remote.agentPresets` namespace.
|
|
32
|
+
* @returns the roster, or a failed read the caller ignores.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readPresetRoster(remote: PresetRemote): Promise<{
|
|
35
|
+
ok: boolean;
|
|
36
|
+
presets: readonly PresetRosterRow[];
|
|
37
|
+
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Normalize one roster into the picker rows the UI consumes. A preset that
|
|
40
|
+
* cannot compose a session keeps its `broken` reason: the pickers show it and
|
|
41
|
+
* disable it, so a missing preset never looks like a missing roster.
|
|
42
|
+
* @param presets - the roster rows.
|
|
43
|
+
* @returns the picker options.
|
|
44
|
+
*/
|
|
45
|
+
export declare function presetOptionsFromRoster(presets: readonly PresetRosterRow[]): ExecutionPresetOption[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team-run promotion for a parent card that just gained a subtask. A card with
|
|
3
|
+
* subtasks is exactly what the Agent Team mode is for, so the two join actions
|
|
4
|
+
* (create a subtask, link an existing task) opt the parent in — but only after
|
|
5
|
+
* the Host confirmed the join, and only where the deployment serves Agent
|
|
6
|
+
* Teams. A refused join changes nothing, and a parent that already opted in is
|
|
7
|
+
* left alone rather than rewritten.
|
|
8
|
+
*
|
|
9
|
+
* Nothing here runs on mount or from a render effect: an existing card is only
|
|
10
|
+
* ever touched by the user's own join action, so switching the option off by
|
|
11
|
+
* hand stays off.
|
|
12
|
+
*/
|
|
13
|
+
import type { BoardController } from '../../core/controller.ts';
|
|
14
|
+
import type { TaskRecord } from '../../core/tasks.ts';
|
|
15
|
+
/**
|
|
16
|
+
* Whether a join would promote this parent: the deployment serves Agent Teams
|
|
17
|
+
* and the parent has not opted in yet.
|
|
18
|
+
* @param controller - the board controller (the snapshot carries both facts).
|
|
19
|
+
* @param parent - the task that gained a subtask, if there is one.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parentAwaitsTeamRunPromotion(controller: BoardController, parent: TaskRecord | undefined): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Opt the parent in after the Host confirmed the join.
|
|
24
|
+
* @returns true when the opt-in was written; false when it did not apply.
|
|
25
|
+
*/
|
|
26
|
+
export declare function promoteParentForTeamRun(controller: BoardController, parent: TaskRecord | undefined): Promise<boolean>;
|
|
@@ -244,6 +244,14 @@ export declare const zh: {
|
|
|
244
244
|
'exec.permission.danger-full-access': string;
|
|
245
245
|
'exec.model.default': string;
|
|
246
246
|
'exec.model.unknown': string;
|
|
247
|
+
'exec.reasoning': string;
|
|
248
|
+
'exec.reasoning.inherit': string;
|
|
249
|
+
'exec.reasoning.unknown': string;
|
|
250
|
+
'exec.reasoning.hint.pickModel': string;
|
|
251
|
+
'exec.reasoning.hint.unknownModel': string;
|
|
252
|
+
'exec.reasoning.hint.noEfforts': string;
|
|
253
|
+
'exec.reasoning.hint.inherit': string;
|
|
254
|
+
'exec.teamRunAutoHint': string;
|
|
247
255
|
'exec.reuseSession': string;
|
|
248
256
|
'exec.teamRun': string;
|
|
249
257
|
'exec.teamRunHint': string;
|
|
@@ -288,6 +296,8 @@ export declare const zh: {
|
|
|
288
296
|
'settings.maxSubtaskDepth': string;
|
|
289
297
|
'settings.maxSubtaskDepthHint': string;
|
|
290
298
|
'settings.maxSubtaskDepthOption': string;
|
|
299
|
+
'settings.runLaunchWidth': string;
|
|
300
|
+
'settings.runLaunchWidthHint': string;
|
|
291
301
|
'settings.runBehaviorTitle': string;
|
|
292
302
|
'settings.runBehaviorCardHint': string;
|
|
293
303
|
'settings.goalRunGlobal': string;
|
|
@@ -317,6 +327,11 @@ export declare const zh: {
|
|
|
317
327
|
'settings.goalVerificationEffortFallback': string;
|
|
318
328
|
'settings.goalVerificationEffortFallbackNone': string;
|
|
319
329
|
'settings.goalVerificationModelInvalid': string;
|
|
330
|
+
'settings.cardDefaultsTitle': string;
|
|
331
|
+
'settings.cardDefaultsCardHint': string;
|
|
332
|
+
'settings.cardDefaultModeHint': string;
|
|
333
|
+
'settings.cardDefaultPermissionHint': string;
|
|
334
|
+
'settings.cardDefaultModelHint': string;
|
|
320
335
|
'running.executing': string;
|
|
321
336
|
'running.verifying': string;
|
|
322
337
|
'running.repairing': string;
|
|
@@ -391,6 +406,7 @@ export declare const zh: {
|
|
|
391
406
|
'detail.subtasks.detach': string;
|
|
392
407
|
'detail.subtasks.runningLock': string;
|
|
393
408
|
'detail.subtasks.runHint': string;
|
|
409
|
+
'detail.subtasks.runHintSettled': string;
|
|
394
410
|
'detail.subtasks.waiting': string;
|
|
395
411
|
'detail.subtasks.depthLimit': string;
|
|
396
412
|
'detail.subtasks.hostOnly': string;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* New-card defaults: the execution targets a freshly created card starts from,
|
|
3
|
+
* and how they combine with what the caller picked and with the card a subtask
|
|
4
|
+
* or a duplicate is created from.
|
|
5
|
+
*
|
|
6
|
+
* Framework-free (no cordis, no runtime imports) because BOTH halves compile
|
|
7
|
+
* it: the Host resolves the seed when it writes the card, and the browser
|
|
8
|
+
* resolves the same seed to open the new-task dialog on it. One pure function
|
|
9
|
+
* is the only place the rules live, so the dialog and the ledger cannot drift.
|
|
10
|
+
*
|
|
11
|
+
* Every target is resolved in ONE order: what the caller picked wins over the
|
|
12
|
+
* value carried over from the card this one is created from, which wins over
|
|
13
|
+
* the board's new-card defaults, and a target nothing supplies stays blank
|
|
14
|
+
* ("no pin, resolved at run time"). A duplicate is a copy of its source and a
|
|
15
|
+
* subtask is derived from its parent, so both keep the source's own pins and
|
|
16
|
+
* fill only the fields that source left unset.
|
|
17
|
+
*
|
|
18
|
+
* The permission of a PARENT is the one exception: it never participates. The
|
|
19
|
+
* permission is not copied onto a card at creation — doing so would also have
|
|
20
|
+
* to copy the parent's human confirmation to stay runnable, and a detached
|
|
21
|
+
* child would keep both, so one confirmed parent would mint unbounded confirmed
|
|
22
|
+
* elevated roots. It is resolved along the ancestor chain at launch instead
|
|
23
|
+
* (core/subtask.ts), which is what makes detaching remove the inheritance by
|
|
24
|
+
* construction. A duplicate is not a hierarchy link, so it copies the
|
|
25
|
+
* permission like every other target. The board's own default permission is not
|
|
26
|
+
* a parent binding either and does apply to a subtask; it only pre-fills the
|
|
27
|
+
* card, and a value above the session baseline still needs a human
|
|
28
|
+
* confirmation before the card may run.
|
|
29
|
+
*
|
|
30
|
+
* The reasoning level is bound to the model route it was chosen for and never
|
|
31
|
+
* crosses to another one:
|
|
32
|
+
*
|
|
33
|
+
* - a level the caller picked is used as it stands;
|
|
34
|
+
* - a caller that pinned a model of its own inherits no level at all, not
|
|
35
|
+
* even one the same model happens to carry on the source card;
|
|
36
|
+
* - otherwise the source card's level travels with the source value it was
|
|
37
|
+
* stored on, exactly as the card's own model/level pair does, and wins over
|
|
38
|
+
* the board default level, so a board that configures none behaves exactly
|
|
39
|
+
* as the create path always has;
|
|
40
|
+
* - a board default level applies only while the card's final model IS the
|
|
41
|
+
* configured default model, and a blank default model makes it inert —
|
|
42
|
+
* a level the resolved model does not declare could only be refused by
|
|
43
|
+
* model selection at run time.
|
|
44
|
+
*/
|
|
45
|
+
import type { TaskRecord } from './tasks.ts';
|
|
46
|
+
/** The board's configured new-card defaults; a blank target means "not set". */
|
|
47
|
+
export interface CardDefaults {
|
|
48
|
+
/** Agent preset a new card starts from. */
|
|
49
|
+
mode?: string;
|
|
50
|
+
/** Permission a new card starts from. */
|
|
51
|
+
permission?: string;
|
|
52
|
+
/** Model a new card starts from. */
|
|
53
|
+
model?: string;
|
|
54
|
+
/** Reasoning level a new card starts from, for the model above. */
|
|
55
|
+
reasoningEffort?: string;
|
|
56
|
+
}
|
|
57
|
+
/** The card a new one is created from, and how it is derived from it. */
|
|
58
|
+
export interface CardTargetSource {
|
|
59
|
+
/** A copy of the source card, or a subtask of it. */
|
|
60
|
+
kind: 'duplicate' | 'parent';
|
|
61
|
+
/** The source card's execution targets. */
|
|
62
|
+
task: Pick<TaskRecord, 'mode' | 'permission' | 'model' | 'reasoningEffort'>;
|
|
63
|
+
}
|
|
64
|
+
/** The resolved targets of the card about to be created; blank means "unset". */
|
|
65
|
+
export interface CardTargetSeed {
|
|
66
|
+
mode: string;
|
|
67
|
+
permission: string;
|
|
68
|
+
model: string;
|
|
69
|
+
reasoningEffort: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the execution targets a new card starts from.
|
|
73
|
+
* @param defaults - the board's configured new-card defaults, if any.
|
|
74
|
+
* @param source - the card this one is created from (a duplicate or a parent), if any.
|
|
75
|
+
* @param picked - what the caller chose explicitly; a non-blank value wins.
|
|
76
|
+
* @returns the four targets, blank where nothing supplies a value.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveCardTargets(defaults: CardDefaults | undefined, source: CardTargetSource | undefined, picked?: Partial<CardTargetSeed>): CardTargetSeed;
|
|
@@ -100,6 +100,17 @@ export interface ExecutionModelOption {
|
|
|
100
100
|
name?: string;
|
|
101
101
|
label?: string;
|
|
102
102
|
provider?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Reasoning metadata the adapter declares for this exact route. An effort
|
|
105
|
+
* picker is offered only while `supported`, and its choices are `efforts` —
|
|
106
|
+
* the ids the target model really accepts, so the UI never offers (or keeps)
|
|
107
|
+
* a level the model would reject. Absent means the deployment published no
|
|
108
|
+
* capability for this model; the card value is then left untouched.
|
|
109
|
+
*/
|
|
110
|
+
reasoning?: {
|
|
111
|
+
supported: boolean;
|
|
112
|
+
efforts?: readonly string[];
|
|
113
|
+
};
|
|
103
114
|
}
|
|
104
115
|
/** The execution-target option sets the UI feeds into the controller. */
|
|
105
116
|
export interface ExecutionOptionsSnapshot {
|
|
@@ -112,7 +123,7 @@ export interface ExecutionOptionsSnapshot {
|
|
|
112
123
|
* (revision/scheduler/power); a full snapshot also carries the deployment
|
|
113
124
|
* constants the UI reads (session default permission, subtask depth).
|
|
114
125
|
*/
|
|
115
|
-
export type HostMirror = Pick<TaskBoardSnapshot, 'revision' | 'scheduler' | 'power' | 'sessionDefaultPermission' | 'maxSubtaskDepth' | 'teamRunAvailable' | 'goalRunEnabled' | 'extensions'>;
|
|
126
|
+
export type HostMirror = Pick<TaskBoardSnapshot, 'revision' | 'scheduler' | 'power' | 'sessionDefaultPermission' | 'maxSubtaskDepth' | 'teamRunAvailable' | 'goalRunEnabled' | 'cardDefaults' | 'extensions'>;
|
|
116
127
|
/** Immutable controller snapshot for UI subscriptions. */
|
|
117
128
|
export interface ControllerSnapshot {
|
|
118
129
|
tasks: readonly TaskRecord[];
|
|
@@ -187,6 +198,19 @@ export declare class BoardController {
|
|
|
187
198
|
isHostBacked(): boolean;
|
|
188
199
|
/** Retry initial migration/state synchronization after an explicit Host error. */
|
|
189
200
|
retryHostSync(): Promise<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* Re-read the authoritative Host snapshot.
|
|
203
|
+
*
|
|
204
|
+
* The board's volatile deployment configuration — the new-card defaults among
|
|
205
|
+
* it — is republished the moment the settings document is written, but the SSE
|
|
206
|
+
* frame that republish emits carries the value as of BEFORE the write (the
|
|
207
|
+
* loader hands the update to the fiber while the new document is not yet
|
|
208
|
+
* visible to it), so a mirror that followed frames alone would stay one edit
|
|
209
|
+
* behind and the create dialog would prefill from the previous defaults for
|
|
210
|
+
* the rest of the session. The surface that owns the write asks for the
|
|
211
|
+
* snapshot again instead of trusting the frame.
|
|
212
|
+
*/
|
|
213
|
+
refreshHostState(): void;
|
|
190
214
|
/**
|
|
191
215
|
* Show the board. The layout owns which panel the center column renders, so
|
|
192
216
|
* the state flip and the panel selection travel together here; a composition
|
|
@@ -359,12 +383,13 @@ export declare class BoardController {
|
|
|
359
383
|
*/
|
|
360
384
|
private mirrorDepth;
|
|
361
385
|
/**
|
|
362
|
-
* Project a Host snapshot onto the browser's mirror.
|
|
363
|
-
*
|
|
364
|
-
* deployment constants the UI reads
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
386
|
+
* Project a Host snapshot onto the browser's mirror. Every snapshot the
|
|
387
|
+
* transport serves is a full document (bootstrap/state/action all answer
|
|
388
|
+
* `TaskBoardHostService.snapshot()`), so the deployment constants the UI reads
|
|
389
|
+
* — the session-default permission the confirmation banner compares against,
|
|
390
|
+
* the subtask depth limit, the platform switches and the extensions a provider
|
|
391
|
+
* published — are taken as published, carried over only where the snapshot
|
|
392
|
+
* itself omits the key.
|
|
368
393
|
*/
|
|
369
394
|
private mirrorOf;
|
|
370
395
|
private refreshRemote;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run-launch admission width: the one bound on how many sessions this board
|
|
3
|
+
* starts at the same time.
|
|
4
|
+
*
|
|
5
|
+
* One board action opens a whole subtree, and a team run hands every member of
|
|
6
|
+
* it to the Lead at once, so without a bound the Host asks DSH for dozens of
|
|
7
|
+
* sessions in a single tick. The repository's own measured guidance caps heavy
|
|
8
|
+
* implementation subagents at three (docs/multi-agent-resources.md) and no
|
|
9
|
+
* runtime mechanism enforced it; this setting is that mechanism.
|
|
10
|
+
*
|
|
11
|
+
* The bounds and the default live here rather than in either half, exactly like
|
|
12
|
+
* the roster cadence: the settings card validates a draft against the same
|
|
13
|
+
* range the Host clamps a hand-edited configuration to, and a programmatic
|
|
14
|
+
* mount that names no width gets the default.
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-task-board/core/launch-width
|
|
17
|
+
*/
|
|
18
|
+
/** Width used when neither the settings document nor the mount names one. */
|
|
19
|
+
export declare const DEFAULT_RUN_LAUNCH_WIDTH = 3;
|
|
20
|
+
/** Narrowest accepted width: one launch at a time. */
|
|
21
|
+
export declare const RUN_LAUNCH_WIDTH_MIN = 1;
|
|
22
|
+
/** Widest accepted width. */
|
|
23
|
+
export declare const RUN_LAUNCH_WIDTH_MAX = 16;
|
|
24
|
+
/**
|
|
25
|
+
* Clamp a configured width into the supported range. A value the schema would
|
|
26
|
+
* refuse (non-finite, below the floor, above the ceiling) still leaves the
|
|
27
|
+
* board launching: an out-of-range setting never stalls a run.
|
|
28
|
+
* @param width - configured width, or undefined for the default.
|
|
29
|
+
* @returns the effective width.
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeRunLaunchWidth(width: number | undefined): number;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which reasoning effort one execution may actually send.
|
|
3
|
+
*
|
|
4
|
+
* The rule lives here, in one pure place, so the launch path cannot drift from
|
|
5
|
+
* what the picker promises: an effort is sent ONLY for the exact model route
|
|
6
|
+
* whose adapter declares that id. An unsupported value is dropped rather than
|
|
7
|
+
* passed through — the Host validates the selection against the same
|
|
8
|
+
* capability (`resolveCallConfig` rejects an unsupported effort) and the whole
|
|
9
|
+
* model selection would fail with it. An absent effort stays absent: the SDK
|
|
10
|
+
* then materializes the model's own default, which is exactly what "inherit
|
|
11
|
+
* the model" means.
|
|
12
|
+
*
|
|
13
|
+
* A card that pins a bare model id also gets its provider resolved here: the
|
|
14
|
+
* session wire contract requires `provider` (ModelSelection), so the catalog is
|
|
15
|
+
* the only place that can complete the documented `provider/model` or model-id
|
|
16
|
+
* pin.
|
|
17
|
+
*/
|
|
18
|
+
import type { CatalogModel, ModelCatalogView } from './verification.ts';
|
|
19
|
+
/** One execution route an effort resolves against: `provider/model`, or a bare model id. */
|
|
20
|
+
export interface ReasoningRoute {
|
|
21
|
+
provider?: string;
|
|
22
|
+
model: string;
|
|
23
|
+
}
|
|
24
|
+
/** The catalog entry a route names, once the catalog can complete it. */
|
|
25
|
+
export interface DeclaredReasoningRoute {
|
|
26
|
+
provider: string;
|
|
27
|
+
model: string;
|
|
28
|
+
/** The adapter's reasoning metadata; absent when it exposes none. */
|
|
29
|
+
reasoning?: CatalogModel['reasoning'];
|
|
30
|
+
}
|
|
31
|
+
/** What one card's effort resolves to for one route. */
|
|
32
|
+
export interface ReasoningEffortDecision {
|
|
33
|
+
/** The effort to send; absent means "send none". */
|
|
34
|
+
effort?: string;
|
|
35
|
+
/** The card's own value when it will NOT be sent. */
|
|
36
|
+
dropped?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Trim one optional effort: blank text means "not set", like every other pinned target. */
|
|
39
|
+
export declare function normalizeReasoningEffort(value: string | undefined): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Complete one route through the host catalog: a qualified route must match its
|
|
42
|
+
* provider group, and a bare model id matches the first group carrying it —
|
|
43
|
+
* which is the provider the request then names.
|
|
44
|
+
* @param catalog - the host model catalog, when this deployment serves one.
|
|
45
|
+
* @param route - the route as the card pins it.
|
|
46
|
+
* @returns the completed route with its reasoning metadata, or undefined when
|
|
47
|
+
* the catalog declares no such model.
|
|
48
|
+
*/
|
|
49
|
+
export declare function declaredRoute(catalog: ModelCatalogView | undefined, route: ReasoningRoute): DeclaredReasoningRoute | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the effort one execution sends.
|
|
52
|
+
* @param requested - the card's stored effort (absent or blank = inherit).
|
|
53
|
+
* @param catalog - the host model catalog, when this deployment serves one.
|
|
54
|
+
* @param route - the route the execution will actually run at.
|
|
55
|
+
* @returns the effort to send, or the dropped value that will not be sent.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveReasoningEffort(requested: string | undefined, catalog: ModelCatalogView | undefined, route: ReasoningRoute | undefined): ReasoningEffortDecision;
|
|
@@ -76,11 +76,32 @@ export interface ParentLinkCheck {
|
|
|
76
76
|
export declare function checkParentLink(tasks: readonly TaskRecord[], childId: string, parentId: string | null, maxSubtaskDepth: number, lineage?: LineageIndex): ParentLinkCheck;
|
|
77
77
|
/**
|
|
78
78
|
* The tasks one run request opens executions for: the requested task first,
|
|
79
|
-
* then its on-board descendants within the configured depth.
|
|
80
|
-
*
|
|
81
|
-
* the
|
|
79
|
+
* then its on-board descendants within the configured depth. This is the
|
|
80
|
+
* SHAPE of a cascade — every walk that must see the whole tree (settlement,
|
|
81
|
+
* archive/restore, the running lock) reads it. The run path filters it with
|
|
82
|
+
* {@link joinsCascadeRun}: archived tasks never run, a participant that already
|
|
83
|
+
* has an open execution is skipped by the caller, which cannot start it twice,
|
|
84
|
+
* and a finished descendant is left alone.
|
|
82
85
|
*/
|
|
83
86
|
export declare function cascadeTargets(tasks: readonly TaskRecord[], rootId: string, maxSubtaskDepth: number): TaskRecord[];
|
|
87
|
+
/**
|
|
88
|
+
* Whether a cascade member takes part in a new run.
|
|
89
|
+
*
|
|
90
|
+
* The task the user ran is always a member: the request names that card, and
|
|
91
|
+
* the operator asked for it to run whatever its column says. A descendant does
|
|
92
|
+
* not join once it sits in the `done` column — its work is finished, so running
|
|
93
|
+
* the parent again is a run of the parent, never a second execution of work
|
|
94
|
+
* that is already done. The rule keys on the column alone, so it covers both a
|
|
95
|
+
* subtask that ran and one an operator moved to done by hand, and it holds for
|
|
96
|
+
* every trigger: a manual run, a re-run, and a due occurrence of a schedule.
|
|
97
|
+
* A card whose own schedule is enabled settles back into `todo`, so a scheduled
|
|
98
|
+
* subtask stays a participant; to make a finished one run again, move it back
|
|
99
|
+
* to `todo` or run it on its own.
|
|
100
|
+
* @param task - the candidate member.
|
|
101
|
+
* @param rootId - the task the run request named.
|
|
102
|
+
* @returns false when this member is left alone by the run.
|
|
103
|
+
*/
|
|
104
|
+
export declare function joinsCascadeRun(task: TaskRecord, rootId: string): boolean;
|
|
84
105
|
/** One still-open execution belonging to a cascade run group. */
|
|
85
106
|
export interface OpenCascadeChild {
|
|
86
107
|
taskId: string;
|
|
@@ -114,11 +135,12 @@ export declare function effectiveTaskPermission(task: TaskRecord): TaskRecord['p
|
|
|
114
135
|
/**
|
|
115
136
|
* Resolve the execution targets a (sub)task actually runs with: its own value
|
|
116
137
|
* wins, and an unset target inherits the nearest ancestor up to the root.
|
|
117
|
-
* Workspace, agent preset and
|
|
118
|
-
* handover bundle is a per-card continuation artefact and is never
|
|
119
|
-
* The permission inherits the ancestor's EFFECTIVE binding, and its
|
|
120
|
-
* confirmation travels with it, so a subtask of an already-confirmed
|
|
121
|
-
* card is runnable while a subtask's own unconfirmed binding stays
|
|
138
|
+
* Workspace, agent preset, model and reasoning effort inherit the ancestor's
|
|
139
|
+
* PIN only — a handover bundle is a per-card continuation artefact and is never
|
|
140
|
+
* inherited. The permission inherits the ancestor's EFFECTIVE binding, and its
|
|
141
|
+
* human confirmation travels with it, so a subtask of an already-confirmed
|
|
142
|
+
* elevated card is runnable while a subtask's own unconfirmed binding stays
|
|
143
|
+
* gated.
|
|
122
144
|
*/
|
|
123
145
|
/**
|
|
124
146
|
* The immutable teammate name for one team-mode member. Teammate names are
|