dsh-lowtide 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +141 -0
  2. package/cordis.patch.yml +39 -0
  3. package/lib/client.js +4793 -0
  4. package/lib/client.js.map +1 -0
  5. package/lib/index.js +7423 -0
  6. package/lib/types/client/api.d.ts +169 -0
  7. package/lib/types/client/components/CandidatesView.d.ts +8 -0
  8. package/lib/types/client/components/ConfirmGate.d.ts +6 -0
  9. package/lib/types/client/components/DroppedRow.d.ts +6 -0
  10. package/lib/types/client/components/InterceptCard.d.ts +17 -0
  11. package/lib/types/client/components/MorningReport.d.ts +6 -0
  12. package/lib/types/client/components/NewTaskModal.d.ts +9 -0
  13. package/lib/types/client/components/PriceBand.d.ts +17 -0
  14. package/lib/types/client/components/PricePill.d.ts +8 -0
  15. package/lib/types/client/components/QueueDock.d.ts +8 -0
  16. package/lib/types/client/components/TaskDetail.d.ts +7 -0
  17. package/lib/types/client/components/TaskForm.d.ts +85 -0
  18. package/lib/types/client/components/TaskRow.d.ts +7 -0
  19. package/lib/types/client/components/WindowEditorModal.d.ts +6 -0
  20. package/lib/types/client/components/atoms.d.ts +25 -0
  21. package/lib/types/client/hooks/useInterceptDraft.d.ts +13 -0
  22. package/lib/types/client/i18n.d.ts +348 -0
  23. package/lib/types/client/index.d.ts +15 -0
  24. package/lib/types/client/lib/taskMeta.d.ts +10 -0
  25. package/lib/types/client/settings.d.ts +5 -0
  26. package/lib/types/client/store.d.ts +188 -0
  27. package/lib/types/src/api-trust.d.ts +18 -0
  28. package/lib/types/src/git.d.ts +16 -0
  29. package/lib/types/src/index.d.ts +10 -0
  30. package/lib/types/src/intake.d.ts +54 -0
  31. package/lib/types/src/models.d.ts +38 -0
  32. package/lib/types/src/routes.d.ts +15 -0
  33. package/lib/types/src/runner.d.ts +89 -0
  34. package/lib/types/src/scheduler.d.ts +37 -0
  35. package/lib/types/src/session-picker.d.ts +14 -0
  36. package/lib/types/src/state-machine.d.ts +13 -0
  37. package/lib/types/src/store.d.ts +116 -0
  38. package/lib/types/src/strategies/review-dimensions.d.ts +14 -0
  39. package/lib/types/src/strategies/smart-iterative.d.ts +61 -0
  40. package/lib/types/src/turns.d.ts +97 -0
  41. package/package.json +105 -0
@@ -0,0 +1,169 @@
1
+ /**
2
+ * HTTP helpers for the /ds-lowtide API (same-origin fetch).
3
+ * Optimistic-write callers handle rollback; these helpers just carry the wire.
4
+ */
5
+ export interface EstimateResponse {
6
+ ok: boolean;
7
+ peak: number;
8
+ off: number;
9
+ model: string;
10
+ batchModel?: string;
11
+ }
12
+ export interface TaskResponse {
13
+ ok: boolean;
14
+ task?: import('./store.ts').HostTask;
15
+ error?: string;
16
+ }
17
+ export declare function estimate(prompt: string, files: {
18
+ size: number;
19
+ }[], model?: string, batchModel?: string): Promise<EstimateResponse>;
20
+ export declare function submitTask(input: {
21
+ prompt: string;
22
+ files: string[];
23
+ workspace: string;
24
+ priority: number;
25
+ permissionPreset: string;
26
+ strategy?: 'single' | 'iterative' | 'sampling' | 'review';
27
+ rounds?: number;
28
+ reasoning?: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
29
+ /** Task-level batch model override (advanced window; absent = follows default). */
30
+ model?: string;
31
+ /** Provider for the task-level model override (absent = follows the live selection). */
32
+ modelProvider?: string;
33
+ strategyHint?: string;
34
+ /** Per-task autonomy override (new-task modal); absent = follow global. */
35
+ autonomy?: 'l1' | 'l2' | 'l3';
36
+ }): Promise<TaskResponse>;
37
+ export declare function triage(id: string, action: 'approve' | 'defer' | 'drop' | 'cancel'): Promise<unknown>;
38
+ /** 采样任务的次日择优:记录用户选定的候选序号。 */
39
+ export declare function chooseCandidate(id: string, index: number): Promise<{
40
+ ok: boolean;
41
+ error?: string;
42
+ }>;
43
+ /** Hard-delete a task for good (as opposed to the soft `drop` triage). */
44
+ export declare function deleteTask(id: string): Promise<{
45
+ ok: boolean;
46
+ error?: string;
47
+ }>;
48
+ /** 重新执行:清错误重新入队,下次窗口或「立即开跑」时执行。 */
49
+ export declare function retryTask(id: string): Promise<{
50
+ ok: boolean;
51
+ error?: string;
52
+ }>;
53
+ /** 恢复已放弃:dropped → pending-review,由用户重新裁定。 */
54
+ export declare function restoreTask(id: string): Promise<{
55
+ ok: boolean;
56
+ error?: string;
57
+ }>;
58
+ export declare function approveAll(): Promise<{
59
+ ok: boolean;
60
+ approved: number;
61
+ }>;
62
+ /** 清空已完成:删除全部 done 任务(执行报告历史保留证据)。 */
63
+ export declare function clearFinished(): Promise<{
64
+ ok: boolean;
65
+ cleared?: number;
66
+ error?: string;
67
+ }>;
68
+ export declare function runNow(): Promise<{
69
+ ok: boolean;
70
+ }>;
71
+ export declare function dismissPeakToday(): Promise<{
72
+ ok: boolean;
73
+ }>;
74
+ export interface ConfigResponse {
75
+ ok: boolean;
76
+ config?: Record<string, unknown>;
77
+ error?: string;
78
+ }
79
+ import type { HostReport } from './store.ts';
80
+ export interface ReportsResponse {
81
+ ok: boolean;
82
+ reports?: HostReport[];
83
+ total?: number;
84
+ /** maxReportHistory (0 = unlimited) — for the "showing latest N" label. */
85
+ limit?: number;
86
+ error?: string;
87
+ }
88
+ /** Morning-report history (newest first). */
89
+ export declare function getReports(): Promise<ReportsResponse>;
90
+ /** Delete a single report by id (ledger and tasks are untouched). */
91
+ export declare function deleteReport(reportId: string): Promise<{
92
+ ok: boolean;
93
+ error?: string;
94
+ }>;
95
+ /** Clear all reports. Returns how many were removed. */
96
+ export declare function clearReports(): Promise<{
97
+ ok: boolean;
98
+ cleared?: number;
99
+ error?: string;
100
+ }>;
101
+ /** Real user conversations per workspace (for the "continue from a
102
+ * conversation" picker). Read-only scan of the dsh storage files. */
103
+ export interface WorkspaceSessionEntry {
104
+ id: string;
105
+ title: string | null;
106
+ lastModified: number;
107
+ }
108
+ export interface WorkspaceSessionsEntry {
109
+ cwd: string;
110
+ label: string | null;
111
+ sessions: WorkspaceSessionEntry[];
112
+ }
113
+ export interface SessionsResponse {
114
+ ok: boolean;
115
+ workspaces?: WorkspaceSessionsEntry[];
116
+ error?: string;
117
+ }
118
+ export declare function getSessions(): Promise<SessionsResponse>;
119
+ /** All registered DSH workspaces (for the task form workspace picker). */
120
+ export interface WorkspaceEntry {
121
+ path: string;
122
+ title: string | null;
123
+ }
124
+ export interface WorkspacesResponse {
125
+ ok: boolean;
126
+ workspaces?: WorkspaceEntry[];
127
+ error?: string;
128
+ }
129
+ export declare function getWorkspaces(): Promise<WorkspacesResponse>;
130
+ /** All models available on this machine (deepseek + any llm-pi-ai). */
131
+ export interface AvailableModel {
132
+ id: string;
133
+ name: string;
134
+ priceKnown: boolean;
135
+ inputModalities?: string[];
136
+ reasoningEfforts?: string[];
137
+ defaultReasoningEffort?: string;
138
+ }
139
+ export interface AvailableProvider {
140
+ provider: string;
141
+ displayName: string;
142
+ models: AvailableModel[];
143
+ }
144
+ export interface ModelsResponse {
145
+ ok: boolean;
146
+ providers?: AvailableProvider[];
147
+ error?: string;
148
+ }
149
+ export declare function getModels(): Promise<ModelsResponse>;
150
+ /** Read the full lowtide config (settings page seed). */
151
+ export declare function getConfig(): Promise<ConfigResponse>;
152
+ /** Settings-page meta from the live state: system timezone + official peak
153
+ * windows converted to the local clock (explainer + one-click adopt). */
154
+ export declare function getStateMeta(): Promise<{
155
+ ok: boolean;
156
+ systemTz?: string;
157
+ officialInLocal?: Array<{
158
+ label: string;
159
+ start: string;
160
+ end: string;
161
+ crossesDay: boolean;
162
+ days?: number[];
163
+ }>;
164
+ error?: string;
165
+ }>;
166
+ /** Persist a partial config update; takes effect immediately (next scheduler tick). */
167
+ export declare function updateConfig(patch: Record<string, unknown>): Promise<ConfigResponse>;
168
+ export declare function lastWorkspace(): string;
169
+ export declare function rememberWorkspace(path: string): void;
@@ -0,0 +1,8 @@
1
+ import { type HostCandidate } from '../store.ts';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export declare function CandidatesView({ candidates, chosenIndex, taskId, t }: {
4
+ candidates: HostCandidate[];
5
+ chosenIndex?: number;
6
+ taskId: string;
7
+ t: NsTranslate;
8
+ }): React.JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export type ConfirmGateProps = PropsRuntime<'shell.overlay'> & {
4
+ t: NsTranslate;
5
+ };
6
+ export declare function ConfirmGate({ t }: ConfirmGateProps): React.JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { type HostTask } from '../store.ts';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export declare function DroppedRow({ task, t }: {
4
+ task: HostTask;
5
+ t: NsTranslate;
6
+ }): React.JSX.Element;
@@ -0,0 +1,17 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { ComposerChainProps } from '@deepseek-ai/dsh-client-ui-conversation/client';
3
+ import { type NsTranslate } from '../i18n.ts';
4
+ export interface InterceptMatched {
5
+ kind: 'lt-intercept';
6
+ }
7
+ /**
8
+ * Pure chain routing: priced window ∧ not dismissed ∧ session present ∧
9
+ * draft non-empty. The draft condition keeps the native bar (and the queue
10
+ * dock) visible until the user actually starts typing (PLAN §6.2).
11
+ */
12
+ export declare function selectIntercept(owner: ComposerChainProps): InterceptMatched | null;
13
+ export type InterceptCardProps = PropsRuntime<'conversation.composer'> & {
14
+ matched: InterceptMatched;
15
+ t: NsTranslate;
16
+ };
17
+ export declare function InterceptCard(props: InterceptCardProps): React.JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export type MorningReportProps = PropsRuntime<'shell.overlay'> & {
4
+ t: NsTranslate;
5
+ };
6
+ export declare function MorningReport({ t }: MorningReportProps): React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { type NsTranslate } from '../i18n.ts';
2
+ import { type AutonomyId } from './TaskForm.tsx';
3
+ export declare function NewTaskModal({ open, t, defaultAutonomy, onClose }: {
4
+ open: boolean;
5
+ t: NsTranslate;
6
+ /** Global autonomy from the live state — the button group starts here. */
7
+ defaultAutonomy: AutonomyId;
8
+ onClose: () => void;
9
+ }): React.JSX.Element;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * PriceBand: 24h price-band preview — 48 cells (30 min each) colored by the
3
+ * given segments, local-time axis labels, and a "now" marker. Shared by the
4
+ * settings page and the pill's window editor (callers own the fallback: pass
5
+ * official-in-local segments when nothing custom is configured).
6
+ */
7
+ import { type NsTranslate } from '../i18n.ts';
8
+ export interface BandSegment {
9
+ level: 'peak' | 'off' | 'custom';
10
+ start: string;
11
+ end: string;
12
+ }
13
+ export declare function PriceBand({ segments, nowIndex, t }: {
14
+ segments: BandSegment[];
15
+ nowIndex: number;
16
+ t: NsTranslate;
17
+ }): React.JSX.Element;
@@ -0,0 +1,8 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export type PricePillProps = PropsRuntime<'conversation.session.header.utilities'> & {
4
+ t: NsTranslate;
5
+ };
6
+ export declare function PricePill({ t }: PricePillProps): React.JSX.Element;
7
+ /** Saved-today number for the tooltip (reused by the dock footer). */
8
+ export declare function SavedToday(): React.JSX.Element;
@@ -0,0 +1,8 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ import { NewTaskModal } from './NewTaskModal.tsx';
4
+ export type QueueDockProps = PropsRuntime<'conversation.input.dock'> & {
5
+ t: NsTranslate;
6
+ };
7
+ export declare function QueueDock(props: QueueDockProps): React.JSX.Element;
8
+ export { NewTaskModal };
@@ -0,0 +1,7 @@
1
+ import { type HostTask } from '../store.ts';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export declare function TaskDetail({ task, t, onClose }: {
4
+ task: HostTask;
5
+ t: NsTranslate;
6
+ onClose: () => void;
7
+ }): React.JSX.Element;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * TaskForm (Phase D + v3.1 + v3.2): the single source of truth for task
3
+ * intake fields.
4
+ *
5
+ * A fully CONTROLLED presentational component — the caller owns the state:
6
+ * - NewTaskModal (variant="modal") holds local state and submits via the
7
+ * task API; it also owns `advancedOpen` (the separate advanced window);
8
+ * - InterceptCard (variant="intercept") binds the prompt to the host input
9
+ * store (inputActions.setDraft) and keeps the workspace in local state.
10
+ *
11
+ * modal: prompt (placeholder follows the strategy) + workspace/priority
12
+ * side by side + strategy (plain pills, hover tooltips, dynamic
13
+ * explanation line, rounds for iterative/sampling, per-strategy
14
+ * guidance text) + permission + an "advanced" gear button that
15
+ * opens a separate SMALL WINDOW (reasoning effort, locked files).
16
+ * intercept: prompt + workspace + empty-workspace warning only — the quick
17
+ * enqueue surface stays minimal.
18
+ */
19
+ import type { ReactElement } from 'react';
20
+ import { type NsTranslate } from '../i18n.ts';
21
+ export type StrategyId = 'single' | 'iterative' | 'sampling' | 'review';
22
+ export type ReasoningId = 'follow' | 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
23
+ export type AutonomyId = 'l1' | 'l2' | 'l3';
24
+ export type SessionModeId = 'new' | 'continue';
25
+ export type TaskModelId = string;
26
+ export interface TaskFormModel {
27
+ id: string;
28
+ name: string;
29
+ provider: string;
30
+ reasoningEfforts?: string[];
31
+ defaultReasoningEffort?: string;
32
+ }
33
+ /** A dsh conversation stored under a workspace (from GET /sessions). */
34
+ export interface SessionWorkspace {
35
+ cwd: string;
36
+ label: string | null;
37
+ sessions: Array<{
38
+ id: string;
39
+ title: string | null;
40
+ lastModified: number;
41
+ }>;
42
+ }
43
+ export interface TaskFormValues {
44
+ prompt: string;
45
+ workspace: string;
46
+ strategy: StrategyId;
47
+ rounds: number;
48
+ priority: number;
49
+ files: string;
50
+ reasoning: ReasoningId;
51
+ /** Task-level batch model (advanced window; '' = follow the live selection). */
52
+ model: TaskModelId;
53
+ /** Provider for the task-level model (advanced window; '' = follow the live selection). */
54
+ modelProvider: string;
55
+ strategyHint: string;
56
+ /** Per-task autonomy override; defaults to the global config value. */
57
+ autonomy: AutonomyId;
58
+ /** new = standalone session; continue = resume a dsh conversation. */
59
+ sessionMode: SessionModeId;
60
+ /** Historical dsh session id when sessionMode === 'continue'. */
61
+ continuesFromSession?: string;
62
+ }
63
+ /** Relative "x min/h ago" label for a session's last activity; falls back
64
+ * to an absolute "MM-DD HH:mm" label once the session is a day old. */
65
+ export declare function sessionTimeLabel(lastModified: number, t: NsTranslate): string;
66
+ export declare function TaskForm(props: {
67
+ t: NsTranslate;
68
+ variant: 'modal' | 'intercept';
69
+ values: TaskFormValues;
70
+ onChange(patch: Partial<TaskFormValues>): void;
71
+ autoFocusPrompt?: boolean;
72
+ /** Modal variant only: the separate advanced window (v3.2). */
73
+ advancedOpen?: boolean;
74
+ onAdvancedOpenChange?(open: boolean): void;
75
+ /** Modal variant only: real conversations per workspace for the
76
+ * "continue from a conversation" mode (from GET /sessions). */
77
+ sessionWorkspaces?: SessionWorkspace[];
78
+ /** Available models from GET /ds-lowtide/models (flattened for the UI). */
79
+ models?: TaskFormModel[];
80
+ /** Registered DSH workspaces from GET /ds-lowtide/workspaces. */
81
+ workspaces?: Array<{
82
+ path: string;
83
+ title: string | null;
84
+ }>;
85
+ }): ReactElement;
@@ -0,0 +1,7 @@
1
+ import { type HostTask } from '../store.ts';
2
+ import { type NsTranslate } from '../i18n.ts';
3
+ export declare function TaskRow({ task, t, onOpenDetail }: {
4
+ task: HostTask;
5
+ t: NsTranslate;
6
+ onOpenDetail: (task: HostTask) => void;
7
+ }): React.JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { type NsTranslate } from '../i18n.ts';
2
+ export declare function WindowEditorModal({ open, onClose, t }: {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ t: NsTranslate;
6
+ }): React.JSX.Element;
@@ -0,0 +1,25 @@
1
+ /** ¥3.82 two-decimals; ¥123 without decimals at ≥¥100; <¥0.01 for dust (PLAN §3.6). */
2
+ export declare function Money({ yuan, className }: {
3
+ yuan: number;
4
+ className?: string;
5
+ }): React.JSX.Element;
6
+ /** HH:MM:SS live countdown to a timestamp (local interval, no network). */
7
+ export declare function Countdown({ targetMs, className }: {
8
+ targetMs: number;
9
+ className?: string;
10
+ }): React.JSX.Element;
11
+ /** HH:MM from a timestamp. */
12
+ export declare function ClockTime({ ms, className }: {
13
+ ms: number;
14
+ className?: string;
15
+ }): React.JSX.Element;
16
+ export type LevelState = 'peak' | 'off' | 'running' | 'ending';
17
+ /** StateDot mapping: red peak / green off / amber window-ending / blue-pulse running. */
18
+ export declare function LevelDot({ state }: {
19
+ state: LevelState;
20
+ }): React.JSX.Element;
21
+ /** Small tag showing which model a task uses. Optionally flags unknown pricing. */
22
+ export declare function ModelBadge({ model, priceKnown }: {
23
+ model?: string;
24
+ priceKnown?: boolean;
25
+ }): React.JSX.Element | null;
@@ -0,0 +1,13 @@
1
+ export declare const INTERCEPT_DISMISS_KEY = "dsh-lowtide:intercept-session-dismissed";
2
+ /** Sync the live draft into the module state (QueueDock stays mounted inside
3
+ * the overlay-kept fallback, so it keeps tracking while the card is up).
4
+ * An emptied draft re-arms interception for the next message. */
5
+ export declare function useInterceptDraftTracking(draft: string): void;
6
+ /** Pure read for the chain selector. */
7
+ export declare function readInterceptDraft(): string;
8
+ /** ✕ exemption: this message will not be intercepted again this session. */
9
+ export declare function dismissInterceptSession(): void;
10
+ /** Clear the per-session exemption (new message = re-arm). */
11
+ export declare function clearInterceptSessionDismissal(): void;
12
+ /** Pure read for the chain selector. */
13
+ export declare function isInterceptSessionDismissed(): boolean;