@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,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal acceptance gate: the board's evaluator-backed certification of a goal
|
|
3
|
+
* completion claim.
|
|
4
|
+
*
|
|
5
|
+
* The gate sits on the official tool pre-execute lifecycle and intercepts the
|
|
6
|
+
* one call that ends a goal run — `update_goal` with `action: 'complete'`
|
|
7
|
+
* — BEFORE it takes effect. This is why the board does not ask the agent to
|
|
8
|
+
* verify itself: the tool call that finishes the goal is refused until a
|
|
9
|
+
* matching acceptance pass record exists, so no prompt wording and no
|
|
10
|
+
* self-report can route around it.
|
|
11
|
+
*
|
|
12
|
+
* Semantics owned here:
|
|
13
|
+
* - one acceptance cycle per EXECUTION, spent at most twice: the first failure
|
|
14
|
+
* returns its findings to the fixing agent, the second ends the cycle;
|
|
15
|
+
* - a repeated completion call during a repair, a new automatic goal round, a
|
|
16
|
+
* plugin reload and a Host restart all reuse the same cycle rather than
|
|
17
|
+
* resetting it (the budget is persisted on the execution record);
|
|
18
|
+
* - an anomaly (timeout, authentication, unparseable answer, an unusable judge
|
|
19
|
+
* route) is recorded separately from a quality verdict and is never treated
|
|
20
|
+
* as one;
|
|
21
|
+
* - concurrent completion calls for one execution share one acceptance.
|
|
22
|
+
*/
|
|
23
|
+
import type { PreToolDecision } from '@deepseek-ai/dsh-tools';
|
|
24
|
+
import type { LlmRuntime } from '@deepseek-ai/dsh-llm';
|
|
25
|
+
import { type WorkspaceChangeSource } from './workspace-evidence.ts';
|
|
26
|
+
import type { HostTaskLedger } from '../host-ledger.ts';
|
|
27
|
+
/** The subset of the official goal service this gate drives. */
|
|
28
|
+
export interface GoalFace {
|
|
29
|
+
get(agent: unknown): {
|
|
30
|
+
id: string;
|
|
31
|
+
revision: number;
|
|
32
|
+
objective: string;
|
|
33
|
+
} | undefined;
|
|
34
|
+
block(agent: unknown, ref: {
|
|
35
|
+
id: string;
|
|
36
|
+
revision: number;
|
|
37
|
+
}, reason: {
|
|
38
|
+
code: string;
|
|
39
|
+
message: string;
|
|
40
|
+
}): unknown;
|
|
41
|
+
}
|
|
42
|
+
/** Everything the gate needs from its owner. */
|
|
43
|
+
export interface GoalVerificationGateDeps {
|
|
44
|
+
ledger: HostTaskLedger;
|
|
45
|
+
/** Resolve the optional model runtime lazily (it may activate later). */
|
|
46
|
+
llm?: () => LlmRuntime | undefined;
|
|
47
|
+
/** Resolve the optional goal service lazily. */
|
|
48
|
+
goals?: () => GoalFace | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the optional host change service lazily. Absent (or a deployment
|
|
51
|
+
* that serves none) simply means the judge sees the trajectory alone.
|
|
52
|
+
*/
|
|
53
|
+
workspaceChanges?: () => WorkspaceChangeSource | undefined;
|
|
54
|
+
logger: {
|
|
55
|
+
warn(message: string, ...rest: unknown[]): void;
|
|
56
|
+
};
|
|
57
|
+
now?: () => number;
|
|
58
|
+
}
|
|
59
|
+
/** The shape of one tool pre-execution the gate inspects. */
|
|
60
|
+
export interface GateExecution {
|
|
61
|
+
name: string;
|
|
62
|
+
arguments: unknown;
|
|
63
|
+
agent?: unknown;
|
|
64
|
+
signal: AbortSignal;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create the goal acceptance gate.
|
|
68
|
+
* @param deps - the ledger, the model runtime, the goal service and the settings.
|
|
69
|
+
* @returns the `tools/pre-execute` listener body (without the waterfall next()).
|
|
70
|
+
*/
|
|
71
|
+
export declare function createGoalVerificationGate(deps: GoalVerificationGateDeps): (exec: GateExecution) => Promise<PreToolDecision | undefined>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Goal acceptance runner: evidence assembly and the judge calls of one
|
|
3
|
+
* acceptance attempt.
|
|
4
|
+
*
|
|
5
|
+
* Lives in the host half because it needs the live session event log and the
|
|
6
|
+
* official `llm` service; every rule it applies (criteria, scale, tags,
|
|
7
|
+
* thresholds, budgets, caps) comes from `../core/verification.ts`, which mirrors
|
|
8
|
+
* the installed dsh-llm-verifier 0.8.4 default final acceptance.
|
|
9
|
+
*/
|
|
10
|
+
import { type LlmRuntime } from '@deepseek-ai/dsh-llm';
|
|
11
|
+
import { type VerificationAttempt, type VerificationRoute, type VerificationUsage } from '../core/verification.ts';
|
|
12
|
+
/** Largest trace handed to the judge, mirroring the verifier's default cap. */
|
|
13
|
+
export declare const VERIFICATION_MAX_TRACE_CHARS = 80000;
|
|
14
|
+
/** Largest single trace entry; one huge tool result must not eat the budget. */
|
|
15
|
+
export declare const VERIFICATION_MAX_ENTRY_CHARS = 4000;
|
|
16
|
+
/** Largest per-finding text kept from one judge answer. */
|
|
17
|
+
export declare const VERIFICATION_MAX_FINDING_CHARS = 400;
|
|
18
|
+
/** Findings kept per judge answer and per acceptance. */
|
|
19
|
+
export declare const VERIFICATION_MAX_FINDINGS_PER_CALL = 3;
|
|
20
|
+
export declare const VERIFICATION_MAX_FINDINGS = 6;
|
|
21
|
+
/** One judge request's ceiling and its retry budget. */
|
|
22
|
+
export declare const VERIFICATION_CALL_TIMEOUT_MS = 120000;
|
|
23
|
+
export declare const VERIFICATION_MAX_TOKENS = 16384;
|
|
24
|
+
export declare const VERIFICATION_TEMPERATURE = 0.2;
|
|
25
|
+
export declare const VERIFICATION_REQUEST_ATTEMPTS = 3;
|
|
26
|
+
/** Redaction patterns, mirrored from the verifier's defaults. */
|
|
27
|
+
export declare const VERIFICATION_REDACT_PATTERNS: readonly string[];
|
|
28
|
+
/** Why one acceptance could not produce a verdict. */
|
|
29
|
+
export type VerificationErrorKind = 'route-unavailable' | 'timeout' | 'auth' | 'parse' | 'request' | 'aborted';
|
|
30
|
+
/** An acceptance anomaly: never a quality verdict, always recorded as one. */
|
|
31
|
+
export declare class VerificationError extends Error {
|
|
32
|
+
readonly kind: VerificationErrorKind;
|
|
33
|
+
readonly usage: VerificationUsage;
|
|
34
|
+
constructor(kind: VerificationErrorKind, message: string, usage?: VerificationUsage, options?: {
|
|
35
|
+
cause?: unknown;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** Fresh zeroed usage counters. */
|
|
39
|
+
export declare function emptyUsage(): VerificationUsage;
|
|
40
|
+
/** Structural view of one session event, as the host log carries it. */
|
|
41
|
+
interface RawEvent {
|
|
42
|
+
type?: unknown;
|
|
43
|
+
seq?: unknown;
|
|
44
|
+
time?: unknown;
|
|
45
|
+
data?: unknown;
|
|
46
|
+
}
|
|
47
|
+
/** Read one session's events across the shapes the SDK cohort exposes. */
|
|
48
|
+
export declare function sessionEvents(session: unknown): readonly RawEvent[];
|
|
49
|
+
/** Evidence assembled for one acceptance attempt. */
|
|
50
|
+
export interface AcceptanceEvidence {
|
|
51
|
+
problem: string;
|
|
52
|
+
trace: string;
|
|
53
|
+
entries: number;
|
|
54
|
+
fromSeq?: number;
|
|
55
|
+
toSeq?: number;
|
|
56
|
+
omittedCharacters: number;
|
|
57
|
+
hash: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Assemble the evidence one acceptance judges.
|
|
61
|
+
*
|
|
62
|
+
* The window starts at the execution's own `startedAt`, never at the session's
|
|
63
|
+
* first event: a reused session carries the history of earlier executions, and
|
|
64
|
+
* those runs must not be judged as this one's work. Only observed output is
|
|
65
|
+
* rendered — tool calls with their arguments and their results, assistant
|
|
66
|
+
* prose, goal round markers and team messages — and the result is redacted and
|
|
67
|
+
* capped before it ever reaches a judge.
|
|
68
|
+
* @param session - the live session of the execution.
|
|
69
|
+
* @param problem - the execution's composed prompt, shown as the task statement.
|
|
70
|
+
* @param startedAt - the instant the execution opened (ms epoch).
|
|
71
|
+
* @returns the bounded, redacted evidence.
|
|
72
|
+
*/
|
|
73
|
+
/**
|
|
74
|
+
* The session events inside one execution's own window.
|
|
75
|
+
*
|
|
76
|
+
* A reused session carries the history of earlier executions; only the events
|
|
77
|
+
* at or after this execution's start belong to the work being judged.
|
|
78
|
+
* @param session - the live session.
|
|
79
|
+
* @param startedAt - the execution's start instant (ms epoch).
|
|
80
|
+
* @returns the events of this execution, oldest first.
|
|
81
|
+
*/
|
|
82
|
+
export declare function evidenceEvents(session: unknown, startedAt: number): readonly RawEvent[];
|
|
83
|
+
export declare function collectEvidence(session: unknown, problem: string, startedAt: number): AcceptanceEvidence;
|
|
84
|
+
/** The verdict of one acceptance attempt. */
|
|
85
|
+
export interface AcceptanceResult {
|
|
86
|
+
attempt: VerificationAttempt;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Run one acceptance: every criterion is judged twice, the odd round with the
|
|
90
|
+
* A/B slots swapped, and the per-round scores are mapped back and averaged per
|
|
91
|
+
* criterion.
|
|
92
|
+
* @param input - the judge route, evidence, threshold and cancellation.
|
|
93
|
+
* @returns the recorded attempt (quality verdict or anomaly).
|
|
94
|
+
*/
|
|
95
|
+
export declare function runAcceptance(input: {
|
|
96
|
+
llm: LlmRuntime;
|
|
97
|
+
route: VerificationRoute;
|
|
98
|
+
evidence: AcceptanceEvidence;
|
|
99
|
+
threshold: number;
|
|
100
|
+
index: number;
|
|
101
|
+
signal: AbortSignal;
|
|
102
|
+
/** Host-observed workspace changes, rendered as the prompt's reference context. */
|
|
103
|
+
context?: string;
|
|
104
|
+
/** How many changed files that context shows. */
|
|
105
|
+
workspaceFiles?: number;
|
|
106
|
+
now?: () => number;
|
|
107
|
+
}): Promise<AcceptanceResult>;
|
|
108
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** The subset of the host change service this module drives. */
|
|
2
|
+
export interface WorkspaceChangeSource {
|
|
3
|
+
summary(sessionId: string, seq: number): unknown;
|
|
4
|
+
diff(sessionId: string, seq: number, index: number, signal: AbortSignal): Promise<unknown>;
|
|
5
|
+
}
|
|
6
|
+
/** One session event, as the host log carries it. */
|
|
7
|
+
interface RawEvent {
|
|
8
|
+
type?: unknown;
|
|
9
|
+
seq?: unknown;
|
|
10
|
+
}
|
|
11
|
+
/** How many changed files one evidence block renders. */
|
|
12
|
+
export declare const MAX_WORKSPACE_FILES = 8;
|
|
13
|
+
/** Character ceiling for the whole rendered block. */
|
|
14
|
+
export declare const WORKSPACE_EVIDENCE_MAX_CHARS = 24000;
|
|
15
|
+
/** Character ceiling for one file's rendered comparison. */
|
|
16
|
+
export declare const WORKSPACE_EVIDENCE_MAX_FILE_CHARS = 6000;
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the optional host change service from a context-like object.
|
|
19
|
+
* @param ctx - anything exposing @@get(name)@@.
|
|
20
|
+
* @returns the service, or undefined when this deployment serves none.
|
|
21
|
+
*/
|
|
22
|
+
export declare function probeWorkspaceChanges(ctx: {
|
|
23
|
+
get(name: string): unknown;
|
|
24
|
+
}): WorkspaceChangeSource | undefined;
|
|
25
|
+
/** The sequence of the newest change event inside the reviewed window. */
|
|
26
|
+
export declare function latestChangeEvent(events: readonly RawEvent[]): {
|
|
27
|
+
seq: number;
|
|
28
|
+
turn?: number;
|
|
29
|
+
} | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Render the host's own record of what the reviewed window changed.
|
|
32
|
+
*
|
|
33
|
+
* Bounded twice — at most {@link MAX_WORKSPACE_FILES} files, and a shared
|
|
34
|
+
* character budget split across them — so one enormous generated file cannot
|
|
35
|
+
* crowd out every other change. Every failure degrades to less evidence (or an
|
|
36
|
+
* empty block) instead of an error, because the acceptance being prepared must
|
|
37
|
+
* still reach a verdict.
|
|
38
|
+
* @param events - session events already bounded to the execution's window.
|
|
39
|
+
* @param sessionId - the session whose changes these are.
|
|
40
|
+
* @param source - the probed host service.
|
|
41
|
+
* @param options - budget, cancellation and the diagnostic sink.
|
|
42
|
+
* @returns the rendered block plus how many files it shows.
|
|
43
|
+
*/
|
|
44
|
+
export declare function renderWorkspaceEvidence(events: readonly RawEvent[], sessionId: string, source: WorkspaceChangeSource, options: {
|
|
45
|
+
signal: AbortSignal;
|
|
46
|
+
warn?: (message: string) => void;
|
|
47
|
+
maxChars?: number;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
text: string;
|
|
50
|
+
files: number;
|
|
51
|
+
hash: string;
|
|
52
|
+
}>;
|
|
53
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ExecutionOutcome, type ExecutionRecord, type TaskRecord } from './core/tasks.ts';
|
|
2
2
|
import { type TaskBoardAction, type TaskBoardSchedulerSnapshot } from './protocol.ts';
|
|
3
|
+
import type { ExecutionVerification } from './core/verification.ts';
|
|
3
4
|
import { type TaskPermission } from './core/handover.ts';
|
|
4
5
|
export interface LedgerState {
|
|
5
6
|
revision: number;
|
|
@@ -23,11 +24,20 @@ export interface OpenExecutionReference {
|
|
|
23
24
|
readonly executionId: string;
|
|
24
25
|
readonly sessionId: string | undefined;
|
|
25
26
|
readonly startedAt: number;
|
|
27
|
+
/**
|
|
28
|
+
* True for a member of a team-mode run other than its Lead. A teammate is a
|
|
29
|
+
* durable member of the Team: it stays alive after its turn ends, so the
|
|
30
|
+
* roster may keep reporting its session as running, and the turn it completed
|
|
31
|
+
* is the only verdict it exposes.
|
|
32
|
+
*/
|
|
33
|
+
readonly teamMember: boolean;
|
|
26
34
|
}
|
|
27
35
|
/** Minimal value copy used by the Host scheduler. */
|
|
28
36
|
export interface DueScheduleReference {
|
|
29
37
|
readonly taskId: string;
|
|
30
38
|
readonly cron: string;
|
|
39
|
+
/** Zone this rule's wall clock is read in. */
|
|
40
|
+
readonly timeZone: string;
|
|
31
41
|
readonly nextRunAt: number;
|
|
32
42
|
}
|
|
33
43
|
/** Derived runtime data for one session-poll pass. */
|
|
@@ -80,8 +90,14 @@ export declare class HostTaskLedger {
|
|
|
80
90
|
readonly lockFile: string;
|
|
81
91
|
/** Small sidecar for the 30 s scheduler heartbeat (lastTickAt only). */
|
|
82
92
|
readonly schedulerFile: string;
|
|
83
|
-
/**
|
|
84
|
-
readonly
|
|
93
|
+
/** Resolves the baseline the confirmation gate compares a binding against. */
|
|
94
|
+
private readonly sessionDefault;
|
|
95
|
+
/**
|
|
96
|
+
* Session-default permission the confirmation gate compares against. Read
|
|
97
|
+
* through the resolver on every use, so a baseline that follows the Host's
|
|
98
|
+
* own default preset tracks a Settings change made while the board runs.
|
|
99
|
+
*/
|
|
100
|
+
get sessionDefaultPermission(): TaskPermission;
|
|
85
101
|
/**
|
|
86
102
|
* Deployment subtask depth limit (1..3): the lineage gate every write obeys.
|
|
87
103
|
* The settings card edits it live, so {@link setMaxSubtaskDepth} mutates it
|
|
@@ -89,7 +105,7 @@ export declare class HostTaskLedger {
|
|
|
89
105
|
*/
|
|
90
106
|
private depthLimit;
|
|
91
107
|
constructor(dir?: string, now?: () => number, options?: {
|
|
92
|
-
sessionDefaultPermission?: TaskPermission;
|
|
108
|
+
sessionDefaultPermission?: TaskPermission | (() => TaskPermission);
|
|
93
109
|
maxSubtaskDepth?: number;
|
|
94
110
|
});
|
|
95
111
|
/** Current subtask depth limit (1..3). */
|
|
@@ -149,16 +165,21 @@ export declare class HostTaskLedger {
|
|
|
149
165
|
*/
|
|
150
166
|
settle(taskId: string, executionId: string, outcome: ExecutionOutcome, error?: string): void;
|
|
151
167
|
attachSession(taskId: string, executionId: string, sessionId: string): void;
|
|
168
|
+
allTasks(): readonly TaskRecord[];
|
|
169
|
+
getTask(id: string): TaskRecord | undefined;
|
|
170
|
+
saveTaskRecord(task: TaskRecord): void;
|
|
152
171
|
private apply;
|
|
153
172
|
/**
|
|
154
173
|
* The binding that makes a run illegal, if any.
|
|
155
174
|
*
|
|
156
175
|
* A plain cascade launches one session per participant, so every participant
|
|
157
176
|
* carries its own resolved binding and each one gates the run. A team run
|
|
158
|
-
* launches only the Lead session: the Lead's binding gates it,
|
|
159
|
-
*
|
|
160
|
-
* refused
|
|
161
|
-
*
|
|
177
|
+
* launches only the Lead session: the Lead's binding gates it, and a
|
|
178
|
+
* teammate inherits that session's permission, so a subtask's OWN pin is
|
|
179
|
+
* refused exactly when the Lead session does not already carry it — the
|
|
180
|
+
* teammate could never be given that authority, and dropping the pin
|
|
181
|
+
* silently would misreport the work (an inherited binding is the Lead's own
|
|
182
|
+
* and stays allowed once the Lead is confirmed).
|
|
162
183
|
* @param root - the task being run.
|
|
163
184
|
* @returns the first refusal, or undefined when the run may start.
|
|
164
185
|
*/
|
|
@@ -191,15 +212,90 @@ export declare class HostTaskLedger {
|
|
|
191
212
|
* (failure dominates, then cancellation).
|
|
192
213
|
*/
|
|
193
214
|
private settleCascade;
|
|
215
|
+
/**
|
|
216
|
+
* Close every run that is already decided, and fold every lineage whose
|
|
217
|
+
* members are all settled. The Host poll calls this on every tick, so a run
|
|
218
|
+
* can no longer be left in the running column by a settle nobody observed:
|
|
219
|
+
*
|
|
220
|
+
* - A team run is governed by its Lead. Once the Lead's own outcome is
|
|
221
|
+
* recorded, its still-open members are settled with that verdict. A
|
|
222
|
+
* teammate is a durable member of the Team and may never report a turn of
|
|
223
|
+
* its own, and without this the whole lineage waits on it forever.
|
|
224
|
+
* - A cascade parent whose members are all settled is finalized here even
|
|
225
|
+
* when the settle that completed the tree happened in another process, or
|
|
226
|
+
* was interrupted between its child write and its parent write.
|
|
227
|
+
*
|
|
228
|
+
* Idempotent: a run that is already folded is left untouched, so a caller may
|
|
229
|
+
* invoke it on every tick.
|
|
230
|
+
* @param persist - false to leave the document for the caller to commit.
|
|
231
|
+
* @returns whether the document changed.
|
|
232
|
+
*/
|
|
233
|
+
finalizeReadyRuns(persist?: boolean): boolean;
|
|
234
|
+
/**
|
|
235
|
+
* The verdict a team run's Lead has already recorded: its own turn outcome
|
|
236
|
+
* once that turn ended, or the folded outcome once its card settled.
|
|
237
|
+
*/
|
|
238
|
+
private leadVerdict;
|
|
239
|
+
/**
|
|
240
|
+
* Settle every still-open member of a team run with the Lead's verdict.
|
|
241
|
+
* A teammate that already reported its own outcome keeps it: the ordinary
|
|
242
|
+
* fold still lets a failure dominate.
|
|
243
|
+
* @param leadId - the Lead card's task id (never settled here).
|
|
244
|
+
* @param groupId - the team run's group.
|
|
245
|
+
* @param verdict - the Lead's outcome, inherited by members that never reported.
|
|
246
|
+
* @param error - the Lead's failure text, inherited with a failed verdict.
|
|
247
|
+
* @param now - clock instant (ms epoch).
|
|
248
|
+
* @returns whether the document changed.
|
|
249
|
+
*/
|
|
250
|
+
private closeTeamMembers;
|
|
194
251
|
private repairSchedules;
|
|
195
252
|
private reconcileInterruptedStarts;
|
|
196
253
|
/**
|
|
197
|
-
* Field-preserving
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
254
|
+
* Field-preserving migration of an older document. It first proves every task
|
|
255
|
+
* row is structurally valid, so a document that would silently drop or coerce
|
|
256
|
+
* rows fails loudly instead (no quarantined-empty restart), and then reuses
|
|
257
|
+
* the current normalization.
|
|
258
|
+
*
|
|
259
|
+
* v4 adds `ScheduleRule.timeZone`. A rule written before v4 was evaluated in
|
|
260
|
+
* whatever zone the Host process happened to report, so the migration stamps
|
|
261
|
+
* that zone onto every enabled rule: the trigger instant is preserved exactly
|
|
262
|
+
* (the stored `nextRunAt` already encodes the old zone), but the rule stops
|
|
263
|
+
* following a later `TZ` change, which is what made an existing schedule
|
|
264
|
+
* silently move when the Host's zone changed.
|
|
265
|
+
*
|
|
266
|
+
* v5 adds the per-execution acceptance block. The migration deliberately does
|
|
267
|
+
* NOT stamp one: an execution opened before v5 keeps no contract, so it
|
|
268
|
+
* settles on its own historical verdict and no in-flight run is retroactively
|
|
269
|
+
* judged by a gate that was never armed for it.
|
|
201
270
|
*/
|
|
202
271
|
private migrateLegacyDocument;
|
|
272
|
+
/**
|
|
273
|
+
* Find the still-open execution that ran in one session, with its task.
|
|
274
|
+
*
|
|
275
|
+
* The completion gate keys on the session id its tool call arrives from: the
|
|
276
|
+
* execution record is the only object binding a session to a card, and an
|
|
277
|
+
* already-settled execution is deliberately not returned (a session the board
|
|
278
|
+
* no longer owns must not be gated).
|
|
279
|
+
* @param sessionId - the DSH session the tool call runs in.
|
|
280
|
+
* @returns the open execution and its task, or undefined.
|
|
281
|
+
*/
|
|
282
|
+
findOpenExecutionBySession(sessionId: string): {
|
|
283
|
+
task: TaskRecord;
|
|
284
|
+
execution: ExecutionRecord;
|
|
285
|
+
} | undefined;
|
|
286
|
+
/**
|
|
287
|
+
* Replace one execution's acceptance block (creating it when absent).
|
|
288
|
+
*
|
|
289
|
+
* A no-op when the serialized value is unchanged, so a coarse caller that
|
|
290
|
+
* re-writes the same state never bumps the ledger revision. A settled
|
|
291
|
+
* execution keeps its record: the report of a finished cycle must survive,
|
|
292
|
+
* and only the board's own settlement moves the card.
|
|
293
|
+
* @param taskId - the task owning the execution.
|
|
294
|
+
* @param executionId - the execution to update.
|
|
295
|
+
* @param verification - the new block.
|
|
296
|
+
* @returns true when the ledger changed.
|
|
297
|
+
*/
|
|
298
|
+
setVerification(taskId: string, executionId: string, verification: ExecutionVerification): boolean;
|
|
203
299
|
private load;
|
|
204
300
|
private normalizeDocument;
|
|
205
301
|
/** Quarantine an unreadable document and start from an empty ledger. */
|
|
@@ -3,7 +3,10 @@ import type { SessionSummary } from '@deepseek-ai/dsh-api-session-controller/typ
|
|
|
3
3
|
import type { CommandResult } from '@deepseek-ai/dsh-commands/types';
|
|
4
4
|
import type { Workspace } from '@deepseek-ai/dsh-workspace/types';
|
|
5
5
|
import type { TaskRecord } from './core/tasks.ts';
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Host services needed to validate a task's workspace before creating a
|
|
8
|
+
* session, and to resolve the workspace an unpinned card runs in.
|
|
9
|
+
*/
|
|
7
10
|
export interface TaskBoardWorkspaceRegistry {
|
|
8
11
|
list(): readonly Workspace[];
|
|
9
12
|
}
|
|
@@ -23,8 +26,18 @@ type ExecutionSessionId = SessionSummary['sessionId'];
|
|
|
23
26
|
export interface SessionCommandDispatcher {
|
|
24
27
|
execute(sessionId: ExecutionSessionId, line: string, signal: AbortSignal): Promise<CommandResult | undefined>;
|
|
25
28
|
}
|
|
26
|
-
export type ExecutionInspection =
|
|
29
|
+
export type ExecutionInspection =
|
|
30
|
+
/**
|
|
31
|
+
* No verdict yet. `unreadable` separates "the work may still be in progress"
|
|
32
|
+
* from "this session's history could not be read at all": a reader failure is
|
|
33
|
+
* not progress, and the caller decides how long to keep waiting before it
|
|
34
|
+
* reports the execution as undeterminable instead of holding a card open
|
|
35
|
+
* forever.
|
|
36
|
+
*/
|
|
37
|
+
{
|
|
27
38
|
outcome: 'pending';
|
|
39
|
+
unreadable?: true;
|
|
40
|
+
reason?: string;
|
|
28
41
|
} | {
|
|
29
42
|
outcome: 'succeeded';
|
|
30
43
|
} | {
|
|
@@ -64,6 +77,17 @@ export interface PromptContext {
|
|
|
64
77
|
peers?: readonly PromptPeer[];
|
|
65
78
|
/** True when those members run as teammates inside this session (Team Lead). */
|
|
66
79
|
team?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Scheduled-run provenance: the instant the cron rule actually fired and the
|
|
82
|
+
* IANA zone its wall clock was read in. Present only for a cron-triggered
|
|
83
|
+
* run, so the model can resolve an unqualified date in the run's own terms
|
|
84
|
+
* instead of guessing from the Host clock (issue #1722).
|
|
85
|
+
*/
|
|
86
|
+
schedule?: {
|
|
87
|
+
triggeredAt: number;
|
|
88
|
+
timeZone: string;
|
|
89
|
+
cron: string;
|
|
90
|
+
};
|
|
67
91
|
}
|
|
68
92
|
/**
|
|
69
93
|
* Build the execution prompt for one task.
|
|
@@ -72,6 +96,16 @@ export interface PromptContext {
|
|
|
72
96
|
* @returns the prompt text.
|
|
73
97
|
*/
|
|
74
98
|
export declare function promptText(task: TaskRecord, context?: PromptContext): string;
|
|
99
|
+
/**
|
|
100
|
+
* Build the objective the built-in `/goal` command receives. A prompt whose
|
|
101
|
+
* text would be read as a goal operation is prefixed with a neutral label: the
|
|
102
|
+
* instruction stays intact, and the command arms an objective instead of
|
|
103
|
+
* clearing, pausing, or editing an unrelated goal (or refusing for a missing
|
|
104
|
+
* one).
|
|
105
|
+
* @param prompt - the composed execution prompt.
|
|
106
|
+
* @returns the objective text for `/goal <objective>`.
|
|
107
|
+
*/
|
|
108
|
+
export declare function goalObjective(prompt: string): string;
|
|
75
109
|
export declare class HostExecutionRunner {
|
|
76
110
|
private readonly gateway;
|
|
77
111
|
private readonly commands?;
|
|
@@ -87,6 +121,14 @@ export declare class HostExecutionRunner {
|
|
|
87
121
|
});
|
|
88
122
|
private invoke;
|
|
89
123
|
private stream;
|
|
124
|
+
/**
|
|
125
|
+
* The workspace an unpinned run lands in: the deployment's most recently used
|
|
126
|
+
* one. Undefined when the deployment serves no workspace registry or has
|
|
127
|
+
* registered none yet; the launch then keeps the "let the Host decide" shape,
|
|
128
|
+
* which is the only remaining path to the Host's own working directory.
|
|
129
|
+
* @returns the workspace id to create the session in, when one is known.
|
|
130
|
+
*/
|
|
131
|
+
private recentWorkspaceId;
|
|
90
132
|
/**
|
|
91
133
|
* Launch one execution. Without `options.reuseSessionId` a fresh session is
|
|
92
134
|
* created, renamed, pinned, and prompted (the historical contract). With it,
|
|
@@ -100,6 +142,8 @@ export declare class HostExecutionRunner {
|
|
|
100
142
|
launch(task: TaskRecord, options?: {
|
|
101
143
|
reuseSessionId?: string;
|
|
102
144
|
promptContext?: PromptContext;
|
|
145
|
+
onSession?: (sessionId: string) => void;
|
|
146
|
+
onGoalArmed?: (armed: boolean) => void;
|
|
103
147
|
}): Promise<string>;
|
|
104
148
|
/**
|
|
105
149
|
* Fail closed when a reused session records a different Agent preset than
|
|
@@ -122,6 +166,46 @@ export declare class HostExecutionRunner {
|
|
|
122
166
|
* the same permission/model pins before the prompt.
|
|
123
167
|
*/
|
|
124
168
|
private pinAndPrompt;
|
|
169
|
+
/**
|
|
170
|
+
* Read the host's model catalog: the default route an unconfigured session
|
|
171
|
+
* starts at, and each provider's models with the reasoning metadata its
|
|
172
|
+
* adapter exposes. The acceptance settings card and the frozen contract both
|
|
173
|
+
* resolve against it, so "inherit host" means the host's own configuration
|
|
174
|
+
* rather than a session's or a card's pinned model.
|
|
175
|
+
* @returns the raw catalog value, or undefined when this cohort serves none.
|
|
176
|
+
*/
|
|
177
|
+
modelCatalog(): Promise<unknown>;
|
|
178
|
+
/**
|
|
179
|
+
* Arm dsh's built-in goal on the session. The task prompt is queued FIRST, so
|
|
180
|
+
* the session's first turn carries the instruction verbatim; `/goal
|
|
181
|
+
* <objective>` then turns the same text into a persistent objective, and
|
|
182
|
+
* dsh's goal-round driver keeps starting continuation rounds until the agent
|
|
183
|
+
* marks it complete (see {@link goalVerdict} for how the run settles).
|
|
184
|
+
*
|
|
185
|
+
* Opt-out: a task whose `goalRun` is an explicit false runs one plain turn.
|
|
186
|
+
* A refusal (no command dispatcher, no `/goal` command in this cohort, an
|
|
187
|
+
* objective the command rejects) is reported and the run continues as that
|
|
188
|
+
* plain turn: the task was asked to run, and a missing goal mode must not
|
|
189
|
+
* lose the work.
|
|
190
|
+
*/
|
|
191
|
+
private armGoal;
|
|
192
|
+
/**
|
|
193
|
+
* The verdict an armed dsh goal imposes on an otherwise completed turn.
|
|
194
|
+
*
|
|
195
|
+
* A goal run is one session working many automatic continuation rounds:
|
|
196
|
+
* dsh's goal-round driver queues the next round whenever the agent goes
|
|
197
|
+
* idle, so the first completed `turn/end` is not the execution's result.
|
|
198
|
+
* Settling there would leave the card in `done` while the session keeps
|
|
199
|
+
* working, and a scheduled task would fire a second, concurrent session.
|
|
200
|
+
* The session projection is the authority: an `active` goal keeps the
|
|
201
|
+
* execution pending, a `blocked` goal fails it with the recorded reason, and
|
|
202
|
+
* any other phase (complete, paused, or no goal at all) leaves the turn
|
|
203
|
+
* verdict in place.
|
|
204
|
+
*
|
|
205
|
+
* An unreadable projection falls back to that turn verdict: a cohort whose
|
|
206
|
+
* gateway withdrew `session/projections` must not hang every execution.
|
|
207
|
+
*/
|
|
208
|
+
private goalVerdict;
|
|
125
209
|
listRunning(): Promise<{
|
|
126
210
|
known: true;
|
|
127
211
|
count: number;
|
|
@@ -129,6 +213,17 @@ export declare class HostExecutionRunner {
|
|
|
129
213
|
} | {
|
|
130
214
|
known: false;
|
|
131
215
|
}>;
|
|
132
|
-
/**
|
|
133
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Resolve an execution outcome from the session list and bounded history pages.
|
|
218
|
+
* @param sessionId - the session the execution runs in.
|
|
219
|
+
* @param startedAt - instant the execution opened; earlier events are not its own.
|
|
220
|
+
* @param sessions - roster from the caller's own poll, when it already has one.
|
|
221
|
+
* @param options.whileRunning - read the first completed turn even while the
|
|
222
|
+
* roster reports the session as running. A durable Agent Teams teammate
|
|
223
|
+
* stays alive after its turn ends, so `running` never clears for it and the
|
|
224
|
+
* turn it completed is the only verdict it will ever expose.
|
|
225
|
+
*/
|
|
226
|
+
inspect(sessionId: string, startedAt?: number, sessions?: readonly SessionSummary[], options?: {
|
|
227
|
+
whileRunning?: boolean;
|
|
228
|
+
}): Promise<ExecutionInspection>;
|
|
134
229
|
}
|