dsh-task-dispatch-table 0.1.1 → 0.1.3
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/dist/calendar-plan.d.ts +1 -1
- package/dist/calendar-plan.js +1 -1
- package/dist/client.js +281 -54
- package/dist/client.js.map +1 -1
- package/dist/dispatch.d.ts +5 -0
- package/dist/dispatch.js +21 -6
- package/dist/index.js +0 -0
- package/dist/receipt.js +67 -20
- package/dist/reconcile.d.ts +1 -1
- package/dist/reconcile.js +30 -13
- package/dist/runtime-index.d.ts +1 -0
- package/dist/scheduler.js +3 -0
- package/dist/store.d.ts +11 -4
- package/dist/store.js +10 -5
- package/dist/task-assets.d.ts +2 -0
- package/dist/tasks.d.ts +1 -0
- package/dist/tasks.js +2 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -169,6 +169,8 @@ window.__ModuleLoader__.load({
|
|
|
169
169
|
*
|
|
170
170
|
* ⚠️ 2026-10-04 从 `task-list.tsx` 上提到这里:卡片「执行记录」面板与**执行记录总查询页**都要用,
|
|
171
171
|
* 同一解析写两遍就是违规(本仓规矩:一类东西一个实现)。
|
|
172
|
+
*
|
|
173
|
+
* ⚠️ 2026-10-10:`process_outputs`(过程文件桶)**同一个形状**,因此继续用它解析,不另写一份。
|
|
172
174
|
*/
|
|
173
175
|
function outputsOf(raw) {
|
|
174
176
|
if (raw === null || raw === void 0 || raw === "") return [];
|
|
@@ -503,7 +505,9 @@ window.__ModuleLoader__.load({
|
|
|
503
505
|
explorerRootName: "(工作区根目录)",
|
|
504
506
|
explorerExpand: "展开目录",
|
|
505
507
|
explorerCollapse: "收起目录",
|
|
508
|
+
explorerEnter: "进入",
|
|
506
509
|
colOutputs: "产出",
|
|
510
|
+
procFilesTitle: "过程文件 · {count} 项",
|
|
507
511
|
deliverRowTitle: "交付文件",
|
|
508
512
|
deliverRowPreparing: "准备交付",
|
|
509
513
|
deliverRowRunning: "正在交付",
|
|
@@ -602,8 +606,10 @@ window.__ModuleLoader__.load({
|
|
|
602
606
|
editorUploadErrEmpty: "文件内容为空",
|
|
603
607
|
editorUploadErrGeneric: "上传失败,请重试",
|
|
604
608
|
editorPickerNoSession: "该工作区下还没有会话,无法读取文件。",
|
|
605
|
-
editorAttachmentsHint: "附加文件会随任务一起派发给执行的 Agent:任务执行过程中,Agent
|
|
609
|
+
editorAttachmentsHint: "附加文件会随任务一起派发给执行的 Agent:任务执行过程中,Agent 可读取或操作这些文件的内容。也可从工作区选择整个目录(连带其下所有文件):Agent 拿到的是这个目录的路径,自己在里面找文件,提示词里写「附件里的 目录名/子文件路径」即可指定其中某一个。",
|
|
606
610
|
editorPickerPick: "选择此文件",
|
|
611
|
+
editorPickerPickDir: "选择此目录(连带其下所有文件)",
|
|
612
|
+
editorPickerSelect: "选择",
|
|
607
613
|
editorOpenEditor: "全屏编辑",
|
|
608
614
|
editorPromptEditorTitle: "提示词编辑器(.md)",
|
|
609
615
|
editorNoVersions: "暂无版本,保存后可在此回滚",
|
|
@@ -632,6 +638,7 @@ window.__ModuleLoader__.load({
|
|
|
632
638
|
editorFullPermB2: "执行命令、发起网络请求等敏感操作",
|
|
633
639
|
editorFullPermCheck: "我已了解风险,并愿意为该任务的执行结果负责。",
|
|
634
640
|
editorTaskSaved: "任务已保存",
|
|
641
|
+
editorTaskDeleted: "任务已删除",
|
|
635
642
|
editorSchedHourlyOnce: "每小时执行一次",
|
|
636
643
|
editorSchedNoDaySuffix: ",但还没选生效日",
|
|
637
644
|
editorSchedWeeklyDayPrefix: "每周",
|
|
@@ -769,6 +776,9 @@ window.__ModuleLoader__.load({
|
|
|
769
776
|
listNextFullTitle: "下次执行:{when}",
|
|
770
777
|
listEmpty: "还没有任务。点右上角「+ 新建任务」创建第一个。",
|
|
771
778
|
listEmptyFiltered: "没有符合当前筛选的任务。",
|
|
779
|
+
listEmptyTitle: "创建你的第一个定时任务",
|
|
780
|
+
listEmptyHint: "写好提示词,到点自动执行;支持每天 / 每周 / 间隔循环。",
|
|
781
|
+
listEmptyAction: "+ 新建定时任务",
|
|
772
782
|
listSectionAttachments: "附加文件",
|
|
773
783
|
listSectionDepends: "前置任务",
|
|
774
784
|
listFieldWorkspace: "工作区",
|
|
@@ -1164,7 +1174,9 @@ window.__ModuleLoader__.load({
|
|
|
1164
1174
|
explorerRootName: "(workspace root)",
|
|
1165
1175
|
explorerExpand: "Expand directory",
|
|
1166
1176
|
explorerCollapse: "Collapse directory",
|
|
1177
|
+
explorerEnter: "Open",
|
|
1167
1178
|
colOutputs: "Outputs",
|
|
1179
|
+
procFilesTitle: "Process files · {count}",
|
|
1168
1180
|
deliverRowTitle: "Deliver files",
|
|
1169
1181
|
deliverRowPreparing: "Preparing delivery",
|
|
1170
1182
|
deliverRowRunning: "Delivering",
|
|
@@ -1263,8 +1275,10 @@ window.__ModuleLoader__.load({
|
|
|
1263
1275
|
editorUploadErrEmpty: "File is empty",
|
|
1264
1276
|
editorUploadErrGeneric: "Upload failed, please retry",
|
|
1265
1277
|
editorPickerNoSession: "No sessions in this workspace yet — its files cannot be read.",
|
|
1266
|
-
editorAttachmentsHint: "Attachments are dispatched along with the task: while it runs, the agent can read and operate on their contents.",
|
|
1278
|
+
editorAttachmentsHint: "Attachments are dispatched along with the task: while it runs, the agent can read and operate on their contents. You can also pick a whole folder: the agent gets the folder path and explores it itself, so refer to a file inside as \"<folder name>/<relative path>\" in the prompt.",
|
|
1267
1279
|
editorPickerPick: "Pick this file",
|
|
1280
|
+
editorPickerPickDir: "Pick this folder (with everything under it)",
|
|
1281
|
+
editorPickerSelect: "Select",
|
|
1268
1282
|
editorOpenEditor: "Full-screen edit",
|
|
1269
1283
|
editorPromptEditorTitle: "Prompt editor (.md)",
|
|
1270
1284
|
editorNoVersions: "No versions yet — save one to roll back here",
|
|
@@ -1293,6 +1307,7 @@ window.__ModuleLoader__.load({
|
|
|
1293
1307
|
editorFullPermB2: "run commands, make network requests and other sensitive operations",
|
|
1294
1308
|
editorFullPermCheck: "I understand the risk and accept responsibility for this task's results.",
|
|
1295
1309
|
editorTaskSaved: "Task saved",
|
|
1310
|
+
editorTaskDeleted: "Task deleted",
|
|
1296
1311
|
editorSchedHourlyOnce: "runs hourly",
|
|
1297
1312
|
editorSchedNoDaySuffix: ", but no active day is selected",
|
|
1298
1313
|
editorSchedWeeklyDayPrefix: "every ",
|
|
@@ -1430,6 +1445,9 @@ window.__ModuleLoader__.load({
|
|
|
1430
1445
|
listNextFullTitle: "Next run: {when}",
|
|
1431
1446
|
listEmpty: "No tasks yet. Use “+ New task” to create the first one.",
|
|
1432
1447
|
listEmptyFiltered: "No task matches the current filter.",
|
|
1448
|
+
listEmptyTitle: "Create your first scheduled task",
|
|
1449
|
+
listEmptyHint: "Write a prompt and it runs automatically on time — every day, every week, or on an interval.",
|
|
1450
|
+
listEmptyAction: "+ New scheduled task",
|
|
1433
1451
|
listSectionAttachments: "Attachments",
|
|
1434
1452
|
listSectionDepends: "Preceding tasks",
|
|
1435
1453
|
listFieldWorkspace: "Workspace",
|
|
@@ -2212,6 +2230,22 @@ body[data-ds-dark-theme]{
|
|
|
2212
2230
|
内层盒子裁了、按「半截文本」平移导致的)。鼠标移开 ⇒ :hover 失效 ⇒ 自动复位回省略号态。 */
|
|
2213
2231
|
.dsh-tdt-mq-run:hover .dsh-tdt-mq-in{max-width:none;overflow:visible;animation:dsh-tdt-mq-scroll var(--dsh-tdt-mq-dur,6s) linear .4s 1 forwards;}
|
|
2214
2232
|
@keyframes dsh-tdt-mq-scroll{from{transform:translateX(0)}to{transform:translateX(var(--dsh-tdt-mq-dist,-40px))}}
|
|
2233
|
+
`;
|
|
2234
|
+
/** 「过程文件」块的皮肤规则(2026-10-10:回执过程文件桶的次级展示件)。 */
|
|
2235
|
+
const PROCESS_FILES_CSS = `
|
|
2236
|
+
/* ── 「过程文件」块:会话弹窗交付卡下方 / 执行记录展开区 / 查看档产出清单三处共用 ──────────
|
|
2237
|
+
(结构在 client/process-files.tsx)。观感纪律 = **次级**:小字浅灰标题 + 数量、默认收起,
|
|
2238
|
+
不许抢主文件(交付卡 / 产出物清单)的视线;展开后的文件行复用 .dsh-tdt-filechip--inline。 */
|
|
2239
|
+
.dsh-tdt-proc{display:flex;flex-direction:column;gap:4px;margin-top:10px;min-width:0;}
|
|
2240
|
+
.dsh-tdt-proc-head{appearance:none;-webkit-appearance:none;align-self:flex-start;display:inline-flex;align-items:center;
|
|
2241
|
+
gap:6px;padding:2px 6px;border:0;border-radius:var(--tdt-radius-xs);background:transparent;color:var(--tdt-fg-3);
|
|
2242
|
+
font:inherit;font-size:var(--tdt-font-xs);line-height:var(--tdt-line-sm);cursor:pointer;
|
|
2243
|
+
transition:background-color var(--tdt-dur) var(--tdt-ease),color var(--tdt-dur) var(--tdt-ease);}
|
|
2244
|
+
.dsh-tdt-proc-head:hover{background:var(--tdt-chip-bg);color:var(--tdt-fg-2);}
|
|
2245
|
+
.dsh-tdt-proc-head:focus-visible{outline:2px solid var(--tdt-focus);outline-offset:1px;}
|
|
2246
|
+
.dsh-tdt-proc-list{display:flex;flex-wrap:wrap;gap:2px 4px;min-width:0;}
|
|
2247
|
+
|
|
2248
|
+
@media (prefers-reduced-motion: reduce){.dsh-tdt-proc-head{transition:none;}}
|
|
2215
2249
|
`;
|
|
2216
2250
|
/** 控件皮肤域的固定名(注入顺序在 tokens 之后)。 */
|
|
2217
2251
|
const CONTROLS_DOMAIN = "controls";
|
|
@@ -2219,7 +2253,7 @@ body[data-ds-dark-theme]{
|
|
|
2219
2253
|
* 确保控件皮肤已登记并注入(幂等;组件渲染时调用一次即可)。
|
|
2220
2254
|
*/
|
|
2221
2255
|
function ensureControlsStyle() {
|
|
2222
|
-
applyStyle(CONTROLS_DOMAIN, SEGMENTED_CSS + BUTTON_CSS + FIELD_CSS + DATETIME_CSS + SELECT_CSS);
|
|
2256
|
+
applyStyle(CONTROLS_DOMAIN, SEGMENTED_CSS + BUTTON_CSS + FIELD_CSS + DATETIME_CSS + SELECT_CSS + PROCESS_FILES_CSS);
|
|
2223
2257
|
}
|
|
2224
2258
|
//#endregion
|
|
2225
2259
|
//#region src/client/ui/Segmented.tsx
|
|
@@ -50177,8 +50211,12 @@ body[data-ds-dark-theme]{
|
|
|
50177
50211
|
.dsh-tdt-sv-crumbs-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
50178
50212
|
/* 目录树:行内 ▸ 开关(内联展开/收起),点它只切展开、不导航。 */
|
|
50179
50213
|
.dsh-tdt-sv-tree-toggle{appearance:none;background:0 0;border:none;flex:none;width:20px;height:20px;padding:0;margin:0;border-radius:var(--tdt-radius-sm,6px);cursor:pointer;color:var(--tdt-fg-2,rgba(128,128,128,.95));display:inline-flex;align-items:center;justify-content:center;transition:transform var(--tdt-dur,.15s) var(--tdt-ease,ease),background var(--tdt-dur,.15s) var(--tdt-ease,ease);}
|
|
50180
|
-
.dsh-tdt-sv-tree-toggle:hover{background:var(--tdt-hover,rgba(38,49,72,.06));}
|
|
50181
50214
|
.dsh-tdt-sv-tree-toggle-open{transform:rotate(90deg);}
|
|
50215
|
+
/* 目录树:行尾「选择」按钮(仅选择器形态,用户 2026-10-10)——平时藏起来,悬停或聚焦该行才出现,
|
|
50216
|
+
点它才把整个文件夹选为附件;平时隐形但保留尺寸,出现时不会顶动行内布局。 */
|
|
50217
|
+
.dsh-tdt-sv-tree-act{flex:none;margin-left:auto;appearance:none;background:0 0;border:1px solid var(--tdt-border,rgba(128,128,128,.35));border-radius:var(--tdt-radius-sm,6px);padding:2px 8px;font-size:var(--tdt-font-sm);line-height:1.4;color:var(--tdt-fg-2,rgba(128,128,128,.95));cursor:pointer;opacity:0;pointer-events:none;transition:opacity var(--tdt-dur,.15s) var(--tdt-ease,ease);}
|
|
50218
|
+
.dsh-tdt-sv-tree-row:hover .dsh-tdt-sv-tree-act,.dsh-tdt-sv-tree-act:focus-visible{opacity:1;pointer-events:auto;}
|
|
50219
|
+
.dsh-tdt-sv-tree-act:hover{background:var(--tdt-hover,rgba(38,49,72,.06));color:var(--tdt-fg);}
|
|
50182
50220
|
/* 内联展开子层:左缩进 + 淡竖线引导层级。 */
|
|
50183
50221
|
.dsh-tdt-sv-tree-children{margin-left:9px;padding-left:7px;border-left:1px solid var(--tdt-border,rgba(128,128,128,.28));display:flex;flex-direction:column;}
|
|
50184
50222
|
.dsh-tdt-sv-tree-loading,.dsh-tdt-sv-tree-err{padding:4px 8px 4px 36px;font-size:var(--tdt-font-sm);color:var(--tdt-fg-3,rgba(128,128,128,.8));}
|
|
@@ -52250,6 +52288,54 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
52250
52288
|
}, (0, react$1.createElement)("span", null, t(expanded ? "deliverCollapse" : "deliverAll", { count: files.length })), expanded ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutlineRegular, {}) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {})) : null);
|
|
52251
52289
|
}
|
|
52252
52290
|
//#endregion
|
|
52291
|
+
//#region src/client/process-files.tsx
|
|
52292
|
+
/** 目录以尾斜杠表达(与 `normalizeOutputs` / `baseNameOf` 同一约定)。 */
|
|
52293
|
+
const isDirPath$1 = (path) => path.endsWith("/");
|
|
52294
|
+
function ProcessFiles(props) {
|
|
52295
|
+
const { paths, onOpen, className, t } = props;
|
|
52296
|
+
const [open, setOpen] = (0, react$1.useState)(false);
|
|
52297
|
+
ensureControlsStyle();
|
|
52298
|
+
const list = paths ?? [];
|
|
52299
|
+
if (list.length === 0) return null;
|
|
52300
|
+
return (0, react$1.createElement)("div", {
|
|
52301
|
+
className: className === void 0 ? "dsh-tdt-proc" : `dsh-tdt-proc ${className}`,
|
|
52302
|
+
"data-process-files": true
|
|
52303
|
+
}, (0, react$1.createElement)("button", {
|
|
52304
|
+
type: "button",
|
|
52305
|
+
className: "dsh-tdt-proc-head",
|
|
52306
|
+
"aria-expanded": open,
|
|
52307
|
+
onClick: () => {
|
|
52308
|
+
setOpen((value) => !value);
|
|
52309
|
+
}
|
|
52310
|
+
}, (0, react$1.createElement)("span", null, t("procFilesTitle", { count: list.length })), open ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutlineRegular, { size: 12 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: 12 })), open ? (0, react$1.createElement)("div", { className: "dsh-tdt-proc-list" }, list.map((path) => {
|
|
52311
|
+
const body = [isDirPath$1(path) ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
52312
|
+
path,
|
|
52313
|
+
size: 14
|
|
52314
|
+
}), (0, react$1.createElement)(MarqueeText, {
|
|
52315
|
+
text: baseNameOf(path),
|
|
52316
|
+
title: path,
|
|
52317
|
+
style: {
|
|
52318
|
+
maxWidth: "40ch",
|
|
52319
|
+
minWidth: 0
|
|
52320
|
+
}
|
|
52321
|
+
})];
|
|
52322
|
+
return onOpen === void 0 ? (0, react$1.createElement)("span", {
|
|
52323
|
+
key: path,
|
|
52324
|
+
className: "dsh-tdt-filechip dsh-tdt-filechip--inline",
|
|
52325
|
+
title: path,
|
|
52326
|
+
"data-noclick": true
|
|
52327
|
+
}, ...body) : (0, react$1.createElement)("button", {
|
|
52328
|
+
key: path,
|
|
52329
|
+
type: "button",
|
|
52330
|
+
className: "dsh-tdt-filechip dsh-tdt-filechip--inline",
|
|
52331
|
+
title: path,
|
|
52332
|
+
onClick: () => {
|
|
52333
|
+
onOpen(path);
|
|
52334
|
+
}
|
|
52335
|
+
}, ...body);
|
|
52336
|
+
})) : null);
|
|
52337
|
+
}
|
|
52338
|
+
//#endregion
|
|
52253
52339
|
//#region src/client/task-file-context.tsx
|
|
52254
52340
|
/**
|
|
52255
52341
|
* 实例快照 → 本任务工作区 path(判上游目录是否跨区用)。
|
|
@@ -52734,7 +52820,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
52734
52820
|
* @param groupPart - 过程分组侧('response' | 'reasoning')。
|
|
52735
52821
|
* @returns 节点视图;null = 决策 28 过滤的噪音 kind。
|
|
52736
52822
|
*/
|
|
52737
|
-
function renderKeyedNode(node, turnProcess, t, onBranchAt, fileOpen, groupPart, deliverFiles, lastTailTurn, host, attachedNames) {
|
|
52823
|
+
function renderKeyedNode(node, turnProcess, t, onBranchAt, fileOpen, groupPart, deliverFiles, lastTailTurn, host, attachedNames, processFiles) {
|
|
52738
52824
|
switch (node.kind) {
|
|
52739
52825
|
case "turn-trigger": return (0, react$1.createElement)(TurnTriggerNodeViewMirror, {
|
|
52740
52826
|
data: node.data,
|
|
@@ -52748,14 +52834,21 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
52748
52834
|
case "turn-tail": {
|
|
52749
52835
|
const data = node.data;
|
|
52750
52836
|
const turn = data?.turn ?? turnLocationOf(node)?.turn;
|
|
52751
|
-
const
|
|
52837
|
+
const atLastTail = turn !== void 0 && lastTailTurn !== void 0 && turn === lastTailTurn;
|
|
52838
|
+
const showGrid = deliverFiles !== void 0 && deliverFiles.length > 0 && atLastTail;
|
|
52839
|
+
const showProc = processFiles !== void 0 && processFiles.length > 0 && atLastTail;
|
|
52840
|
+
const tailSlot = showGrid || showProc ? (0, react$1.createElement)(react$1.Fragment, null, showGrid && host !== void 0 && host !== null && host !== "error" && !host.available ? (0, react$1.createElement)("span", {
|
|
52752
52841
|
className: ocOr("Deliverables", "hostStatus", "dsh-tdt-sv-host-status"),
|
|
52753
52842
|
"data-host-unavailable": true
|
|
52754
|
-
}, t("presented.unavailable")) : null, (0, react$1.createElement)(DeliverablesGridMirror, {
|
|
52843
|
+
}, t("presented.unavailable")) : null, showGrid ? (0, react$1.createElement)(DeliverablesGridMirror, {
|
|
52755
52844
|
files: deliverFiles,
|
|
52756
52845
|
onOpen: fileOpen?.open,
|
|
52757
52846
|
t
|
|
52758
|
-
})
|
|
52847
|
+
}) : null, showProc ? (0, react$1.createElement)(ProcessFiles, {
|
|
52848
|
+
paths: processFiles,
|
|
52849
|
+
onOpen: fileOpen?.open,
|
|
52850
|
+
t
|
|
52851
|
+
}) : null) : null;
|
|
52759
52852
|
return data === void 0 || data.closing === null || data.closing === void 0 ? null : (0, react$1.createElement)(TurnTailNodeViewMirror, {
|
|
52760
52853
|
data,
|
|
52761
52854
|
onBranchAt,
|
|
@@ -53133,7 +53226,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
53133
53226
|
* forkSession / openHostSession 缺一即不渲染按钮(服务未就位时功能降级)。
|
|
53134
53227
|
*/
|
|
53135
53228
|
function SessionViewModal(props) {
|
|
53136
|
-
const { t, heading, sessionId, view, onClose, forkSession, openHostSession, workspaceFiles, onOpenFile, outputs, upstream, attached, workspacePath, headingTask, headingRest, taskId, onOpenTask } = props;
|
|
53229
|
+
const { t, heading, sessionId, view, onClose, forkSession, openHostSession, workspaceFiles, onOpenFile, outputs, processOutputs, upstream, attached, workspacePath, headingTask, headingRest, taskId, onOpenTask } = props;
|
|
53137
53230
|
const tt = (0, react$1.useMemo)(() => interpolateTranslate(t), [t]);
|
|
53138
53231
|
const attachedNames = (0, react$1.useMemo)(() => new Set((attached ?? []).filter((file) => file.path !== null).map((file) => file.name)), [attached]);
|
|
53139
53232
|
const subscribe = (0, react$1.useMemo)(() => (onChange) => view.target.subscribe(onChange), [view]);
|
|
@@ -53234,14 +53327,15 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
53234
53327
|
store
|
|
53235
53328
|
]);
|
|
53236
53329
|
const host = usePresentedHost();
|
|
53237
|
-
const renderNode = (0, react$1.useCallback)((node, turnProcess, groupPart) => renderKeyedNode(node, turnProcess, tt, onBranchAt, fileOpen, groupPart, deliverFiles, lastTailTurn, host, attachedNames), [
|
|
53330
|
+
const renderNode = (0, react$1.useCallback)((node, turnProcess, groupPart) => renderKeyedNode(node, turnProcess, tt, onBranchAt, fileOpen, groupPart, deliverFiles, lastTailTurn, host, attachedNames, processOutputs), [
|
|
53238
53331
|
tt,
|
|
53239
53332
|
onBranchAt,
|
|
53240
53333
|
fileOpen,
|
|
53241
53334
|
deliverFiles,
|
|
53242
53335
|
lastTailTurn,
|
|
53243
53336
|
host,
|
|
53244
|
-
attachedNames
|
|
53337
|
+
attachedNames,
|
|
53338
|
+
processOutputs
|
|
53245
53339
|
]);
|
|
53246
53340
|
const isTurnClosed = (0, react$1.useCallback)((turn) => (turns?.get(turn) ?? turns?.get(String(turn)))?.status !== "open", [turns]);
|
|
53247
53341
|
const groupedView = (0, react$1.useMemo)(() => keyed ? buildProcessGroups(order, (key) => store?.get(key), isTurnClosed) : void 0, [
|
|
@@ -53922,7 +54016,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
53922
54016
|
* ▾ 下拉条目构造(**picker 与 dock 共用同一段代码**,差别只在入参——用户 2026-09-29 点名提炼,
|
|
53923
54017
|
* 严禁两处各写一份):
|
|
53924
54018
|
* - 当前工作区排第一(打开文件夹图标 + 加粗),**其下路径紧跟**(每层一个右箭头位缩进),
|
|
53925
|
-
* 再列其他工作区(关合图标 +
|
|
54019
|
+
* 再列其他工作区(关合图标 + 灰)——「打开哪个就跟在哪个下面」;点当前工作区 = 回到其根目录。
|
|
53926
54020
|
* - 当前工作区未知(rootName 空或不在清单)时路径段置顶、全部工作区按「其他」罗列;
|
|
53927
54021
|
* - workspaces 不传 = 不显示工作区段(旧形态兜底:根无箭头、其下逐层缩进)。
|
|
53928
54022
|
*/
|
|
@@ -53941,7 +54035,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
53941
54035
|
},
|
|
53942
54036
|
title: ws,
|
|
53943
54037
|
onClick: () => {
|
|
53944
|
-
if (
|
|
54038
|
+
if (current) onLoadDir("");
|
|
54039
|
+
else onPickWorkspace?.(ws);
|
|
53945
54040
|
}
|
|
53946
54041
|
}, (0, react$1.createElement)("span", { style: {
|
|
53947
54042
|
display: "inline-flex",
|
|
@@ -54422,7 +54517,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
54422
54517
|
if (!(entry.type === "directory")) {
|
|
54423
54518
|
const pick = () => {
|
|
54424
54519
|
if (picker && onPick !== void 0) {
|
|
54425
|
-
onPick(relativizeToRoot(childPath, sessionId));
|
|
54520
|
+
onPick(relativizeToRoot(childPath, sessionId), false);
|
|
54426
54521
|
return;
|
|
54427
54522
|
}
|
|
54428
54523
|
setViewing(childPath);
|
|
@@ -54446,18 +54541,28 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
54446
54541
|
}
|
|
54447
54542
|
const cached = childCache[childPath];
|
|
54448
54543
|
const isOpen = openDirs.has(childPath);
|
|
54544
|
+
const rowAction = () => {
|
|
54545
|
+
toggleDir(childPath);
|
|
54546
|
+
};
|
|
54547
|
+
/** 行尾动作按钮(stopPropagation 防触发展开):选择器选中整个文件夹;浏览则进入该目录。 */
|
|
54548
|
+
const actThisDir = (event) => {
|
|
54549
|
+
event.stopPropagation();
|
|
54550
|
+
if (picker === true) {
|
|
54551
|
+
if (onPick !== void 0) onPick(relativizeToRoot(childPath, sessionId), true);
|
|
54552
|
+
return;
|
|
54553
|
+
}
|
|
54554
|
+
loadDir(childPath);
|
|
54555
|
+
};
|
|
54449
54556
|
return (0, react$1.createElement)(react$1.Fragment, { key: childPath }, (0, react$1.createElement)("div", {
|
|
54450
54557
|
className: "dsh-tdt-sv-tree-row",
|
|
54451
54558
|
role: "button",
|
|
54452
54559
|
tabIndex: 0,
|
|
54453
54560
|
title: childPath,
|
|
54454
|
-
onClick:
|
|
54455
|
-
loadDir(childPath);
|
|
54456
|
-
},
|
|
54561
|
+
onClick: rowAction,
|
|
54457
54562
|
onKeyDown: (event) => {
|
|
54458
|
-
if (event.key === "Enter" || event.key === " ")
|
|
54563
|
+
if (event.key === "Enter" || event.key === " ") rowAction();
|
|
54459
54564
|
}
|
|
54460
|
-
},
|
|
54565
|
+
}, (0, react$1.createElement)("button", {
|
|
54461
54566
|
type: "button",
|
|
54462
54567
|
className: "dsh-tdt-sv-tree-toggle" + (isOpen ? " dsh-tdt-sv-tree-toggle-open" : ""),
|
|
54463
54568
|
"aria-expanded": isOpen,
|
|
@@ -54466,7 +54571,12 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
54466
54571
|
event.stopPropagation();
|
|
54467
54572
|
toggleDir(childPath);
|
|
54468
54573
|
}
|
|
54469
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, { size: 16 }))
|
|
54574
|
+
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, { size: 16 })), (0, react$1.createElement)("span", { className: "dsh-tdt-sv-tree-name" }, entry.name), picker === true && onPick === void 0 ? null : (0, react$1.createElement)("button", {
|
|
54575
|
+
type: "button",
|
|
54576
|
+
className: "dsh-tdt-sv-tree-act",
|
|
54577
|
+
"aria-label": picker === true ? t("editorPickerPickDir") : t("explorerEnter"),
|
|
54578
|
+
onClick: actThisDir
|
|
54579
|
+
}, t(picker === true ? "editorPickerSelect" : "explorerEnter"))), isOpen ? (0, react$1.createElement)("div", { className: "dsh-tdt-sv-tree-children" }, cached === void 0 || cached.status === "loading" ? null : cached.status === "error" ? (0, react$1.createElement)("div", { className: "dsh-tdt-sv-tree-err" }, t(cached.error.key, cached.error.params)) : (0, react$1.createElement)(react$1.Fragment, null, renderTree(cached.entries, childPath), cached.truncated ? (0, react$1.createElement)("div", { className: "dsh-tdt-sv-tree-truncated" }, t("explorerTruncated")) : null)) : null);
|
|
54470
54580
|
});
|
|
54471
54581
|
};
|
|
54472
54582
|
const rootAbs = workspaceRoots.get(sessionId);
|
|
@@ -64592,7 +64702,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
64592
64702
|
const absPath = item.path;
|
|
64593
64703
|
const anchor = item.anchorSessionId;
|
|
64594
64704
|
const key = item.key ?? item.name;
|
|
64595
|
-
const icon = (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
64705
|
+
const icon = item.isDir === true ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
64596
64706
|
path: item.name,
|
|
64597
64707
|
size: 14
|
|
64598
64708
|
});
|
|
@@ -64678,6 +64788,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
64678
64788
|
const canOpenSession = sid !== null && onOpenSession !== void 0;
|
|
64679
64789
|
const canOpenFile = sid !== null && onOpenFile !== void 0;
|
|
64680
64790
|
const outputs = outputsOf(instance.outputs);
|
|
64791
|
+
const processOutputs = outputsOf(instance.process_outputs);
|
|
64681
64792
|
const dur = durationMsOf(instance);
|
|
64682
64793
|
const tokens = instance.token_in === null && instance.token_out === null ? null : formatTokenCount((instance.token_in ?? 0) + (instance.token_out ?? 0));
|
|
64683
64794
|
const note = instance.note === null || instance.note === void 0 ? "" : instance.note;
|
|
@@ -64761,10 +64872,16 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
64761
64872
|
onClick: () => {
|
|
64762
64873
|
if (canOpenFile && onOpenFile !== void 0 && sid !== null) onOpenFile(sid, output);
|
|
64763
64874
|
}
|
|
64764
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
64875
|
+
}, output.endsWith("/") ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
64765
64876
|
path: output,
|
|
64766
64877
|
size: 14
|
|
64767
|
-
}), (0, react$1.createElement)("span", { className: "dsh-tdt-ellipsis" }, baseNameOf(output)))))))
|
|
64878
|
+
}), (0, react$1.createElement)("span", { className: "dsh-tdt-ellipsis" }, baseNameOf(output)))))), (0, react$1.createElement)(ProcessFiles, {
|
|
64879
|
+
paths: processOutputs,
|
|
64880
|
+
onOpen: canOpenFile && onOpenFile !== void 0 ? (path) => {
|
|
64881
|
+
onOpenFile(sid, path);
|
|
64882
|
+
} : void 0,
|
|
64883
|
+
t
|
|
64884
|
+
}));
|
|
64768
64885
|
}
|
|
64769
64886
|
//#endregion
|
|
64770
64887
|
//#region src/client/event-subscribe.ts
|
|
@@ -65007,7 +65124,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
65007
65124
|
name: item.name,
|
|
65008
65125
|
key: item.id,
|
|
65009
65126
|
path: resolved?.path ?? null,
|
|
65010
|
-
anchorSessionId: resolved?.anchorSessionId ?? null
|
|
65127
|
+
anchorSessionId: resolved?.anchorSessionId ?? null,
|
|
65128
|
+
isDir: item.isDir
|
|
65011
65129
|
};
|
|
65012
65130
|
}),
|
|
65013
65131
|
depends: draft.deps.map((dep) => {
|
|
@@ -65383,7 +65501,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
65383
65501
|
name: item.name,
|
|
65384
65502
|
kind: item.kind,
|
|
65385
65503
|
ref: item.ref,
|
|
65386
|
-
...typeof item.workspace === "string" ? { workspace: item.workspace } : {}
|
|
65504
|
+
...typeof item.workspace === "string" ? { workspace: item.workspace } : {},
|
|
65505
|
+
...typeof item.isDir === "boolean" ? { isDir: item.isDir } : {}
|
|
65387
65506
|
})) : [],
|
|
65388
65507
|
versions: [],
|
|
65389
65508
|
...typeof definition.createdAt === "string" && definition.createdAt !== "" ? { createdAt: definition.createdAt } : {}
|
|
@@ -66250,6 +66369,12 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66250
66369
|
};
|
|
66251
66370
|
}, [pickerOpen]);
|
|
66252
66371
|
const [uploadError, setUploadError] = (0, react$1.useState)(null);
|
|
66372
|
+
/**
|
|
66373
|
+
* 刚上传、还没保存的附件:文件已在**服务端临时区**,但绝对路径只有服务端知道 ⇒ 由上传回包带回来存这里
|
|
66374
|
+
* (用户 2026-10-09:进了列表就要能点开预览,不能等保存)。
|
|
66375
|
+
* ⚠️ 只活组件内存,**绝不写进 draft** —— draft 会被序列化进任务定义 JSON,路径是服务端的、也不该留痕。
|
|
66376
|
+
*/
|
|
66377
|
+
const [uploadPaths, setUploadPaths] = (0, react$1.useState)({});
|
|
66253
66378
|
const [confirmDiscard, setConfirmDiscard] = (0, react$1.useState)(false);
|
|
66254
66379
|
const initialDraftRef = (0, react$1.useRef)(draft);
|
|
66255
66380
|
const dirty = stableStringify(draft) !== stableStringify(initialDraftRef.current);
|
|
@@ -66515,6 +66640,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66515
66640
|
if (sendable.length === 0) return;
|
|
66516
66641
|
setUploading(true);
|
|
66517
66642
|
const added = [];
|
|
66643
|
+
const nextPaths = {};
|
|
66518
66644
|
let lastErr = null;
|
|
66519
66645
|
for (const file of sendable) {
|
|
66520
66646
|
const controller = new AbortController();
|
|
@@ -66533,8 +66659,10 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66533
66659
|
lastErr = typeof data?.error === "string" ? data.error : "upload-failed";
|
|
66534
66660
|
continue;
|
|
66535
66661
|
}
|
|
66662
|
+
const id = makeId();
|
|
66663
|
+
if (typeof data.path === "string" && data.path !== "") nextPaths[id] = data.path;
|
|
66536
66664
|
added.push({
|
|
66537
|
-
id
|
|
66665
|
+
id,
|
|
66538
66666
|
name: data.name,
|
|
66539
66667
|
kind: "upload",
|
|
66540
66668
|
ref: data.ref
|
|
@@ -66547,8 +66675,43 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66547
66675
|
}
|
|
66548
66676
|
setUploading(false);
|
|
66549
66677
|
if (added.length > 0) patch({ attachments: [...draft.attachments, ...added] });
|
|
66678
|
+
if (Object.keys(nextPaths).length > 0) setUploadPaths((prev) => ({
|
|
66679
|
+
...prev,
|
|
66680
|
+
...nextPaths
|
|
66681
|
+
}));
|
|
66550
66682
|
if (lastErr !== null) setUploadError(lastErr);
|
|
66551
66683
|
};
|
|
66684
|
+
/**
|
|
66685
|
+
* 这一行的预览目标(路径 + 锚点会话)。三档递进,**服务端解析优先**(已保存任务的绝对路径最权威):
|
|
66686
|
+
* ① overview 命中(服务端把 ref 绝对化 + 配好锚点会话);
|
|
66687
|
+
* ② link 型当场算:`ref` 本来就是**工作区相对路径**,而 FileBrowser 的 path 就是同一口径
|
|
66688
|
+
* (相对会话 cwd = 工作区根)⇒ **零换算**,锚点取该工作区最近会话(与选择器同一份 workspaceAnchors);
|
|
66689
|
+
* ③ upload 型(还没保存):用上传回包带回的临时区绝对路径,锚点任一有会话的工作区即可
|
|
66690
|
+
* (宿主要的只是「某个有效会话」,与服务端 `attachmentsWithPaths` 的兜底同款)。
|
|
66691
|
+
* 算不出锚点 ⇒ 返回 null ⇒ 该行不可点:**没有会话的工作区宿主列不出文件,不给假入口**。
|
|
66692
|
+
*/
|
|
66693
|
+
const previewTargetOf = (att) => {
|
|
66694
|
+
const anchors = workspaceAnchors ?? {};
|
|
66695
|
+
const hit = resolvedAttachments?.find((r) => r.name === att.name && r.kind === att.kind && r.path !== void 0 && r.anchorSessionId !== void 0);
|
|
66696
|
+
if (hit !== void 0) return {
|
|
66697
|
+
path: hit.path,
|
|
66698
|
+
anchorSessionId: hit.anchorSessionId
|
|
66699
|
+
};
|
|
66700
|
+
if (att.kind === "link") {
|
|
66701
|
+
const anchor = anchors[att.workspace !== void 0 && att.workspace !== "" ? att.workspace : draft.workspace];
|
|
66702
|
+
return anchor === void 0 || anchor === "" ? null : {
|
|
66703
|
+
path: att.ref,
|
|
66704
|
+
anchorSessionId: anchor
|
|
66705
|
+
};
|
|
66706
|
+
}
|
|
66707
|
+
const abs = uploadPaths[att.id];
|
|
66708
|
+
if (abs === void 0 || abs === "") return null;
|
|
66709
|
+
const anyAnchor = Object.values(anchors).find((item) => typeof item === "string" && item !== "");
|
|
66710
|
+
return anyAnchor === void 0 ? null : {
|
|
66711
|
+
path: abs,
|
|
66712
|
+
anchorSessionId: anyAnchor
|
|
66713
|
+
};
|
|
66714
|
+
};
|
|
66552
66715
|
const attachmentsCard = (0, react$1.createElement)("div", { className: `dsh-tdt-ed-card${problemsByField("attachments") ? " dsh-tdt-ed-card--error" : ""}` }, (0, react$1.createElement)("div", { className: "dsh-tdt-ed-card-head" }, (0, react$1.createElement)("div", {
|
|
66553
66716
|
className: "dsh-tdt-ed-label",
|
|
66554
66717
|
style: {
|
|
@@ -66562,20 +66725,20 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66562
66725
|
gap: "6px",
|
|
66563
66726
|
marginBottom: "10px"
|
|
66564
66727
|
} }, draft.attachments.map((att) => {
|
|
66565
|
-
const
|
|
66566
|
-
const canView =
|
|
66728
|
+
const target = previewTargetOf(att);
|
|
66729
|
+
const canView = target !== null && onOpenFile !== void 0;
|
|
66567
66730
|
return (0, react$1.createElement)("div", {
|
|
66568
66731
|
key: att.id,
|
|
66569
66732
|
className: `dsh-tdt-ed-attrow${canView ? " dsh-tdt-ed-attrow--view" : ""}`,
|
|
66570
66733
|
title: canView ? t("editorAttachmentView") : void 0,
|
|
66571
66734
|
onClick: canView ? () => {
|
|
66572
|
-
onOpenFile?.(
|
|
66735
|
+
onOpenFile?.(target.anchorSessionId, target.path);
|
|
66573
66736
|
} : void 0
|
|
66574
66737
|
}, (0, react$1.createElement)("span", { style: {
|
|
66575
66738
|
flex: "none",
|
|
66576
66739
|
display: "flex",
|
|
66577
66740
|
alignItems: "center"
|
|
66578
|
-
} }, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
66741
|
+
} }, att.isDir === true ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
66579
66742
|
path: att.name,
|
|
66580
66743
|
size: 16
|
|
66581
66744
|
})), (0, react$1.createElement)("span", {
|
|
@@ -66601,6 +66764,11 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
66601
66764
|
onClick: (event) => {
|
|
66602
66765
|
event.stopPropagation();
|
|
66603
66766
|
patch({ attachments: draft.attachments.filter((a) => a.id !== att.id) });
|
|
66767
|
+
setUploadPaths((prev) => {
|
|
66768
|
+
const next = { ...prev };
|
|
66769
|
+
delete next[att.id];
|
|
66770
|
+
return next;
|
|
66771
|
+
});
|
|
66604
66772
|
},
|
|
66605
66773
|
title: t("editorAttachmentRemove"),
|
|
66606
66774
|
"aria-label": t("editorAttachmentRemove"),
|
|
@@ -67357,14 +67525,15 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67357
67525
|
setPickerOpen(false);
|
|
67358
67526
|
},
|
|
67359
67527
|
picker: true,
|
|
67360
|
-
onPick: (p) => {
|
|
67528
|
+
onPick: (p, isDir) => {
|
|
67361
67529
|
const name = p.slice(Math.max(p.lastIndexOf("/"), p.lastIndexOf("\\")) + 1);
|
|
67362
67530
|
addAttachment({
|
|
67363
67531
|
id: makeId(),
|
|
67364
67532
|
name,
|
|
67365
67533
|
kind: "link",
|
|
67366
67534
|
ref: p,
|
|
67367
|
-
workspace: pickerWs
|
|
67535
|
+
workspace: pickerWs,
|
|
67536
|
+
isDir
|
|
67368
67537
|
});
|
|
67369
67538
|
setPickerOpen(false);
|
|
67370
67539
|
},
|
|
@@ -67738,6 +67907,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67738
67907
|
minWidth: 0
|
|
67739
67908
|
} }, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconAlarmClockOutlineRegular, { size: 12 }), renderNextExec(row.scheduled_at, t))) : null;
|
|
67740
67909
|
const outputs = outputsOf(row.outputs);
|
|
67910
|
+
const processOutputs = outputsOf(row.process_outputs);
|
|
67741
67911
|
const sid = row.session_id;
|
|
67742
67912
|
const canOpenSession = sid !== null && sid !== "";
|
|
67743
67913
|
const canOpenFile = canOpenSession && openFile !== void 0;
|
|
@@ -67750,8 +67920,9 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67750
67920
|
const actual = clockLabelOf(row.dispatched_at, dayKey, crossFmt, t("recPrevDay"), t("recNextDay"));
|
|
67751
67921
|
const deps = isPlanned ? plannedDeps ?? [] : resolvedDepsOf(snapshot);
|
|
67752
67922
|
const hasOutputs = outputs.length > 0;
|
|
67923
|
+
const hasProcess = processOutputs.length > 0;
|
|
67753
67924
|
const hasDeps = deps.length > 0;
|
|
67754
|
-
const hasExpand = hasOutputs || hasDeps || !isPlanned;
|
|
67925
|
+
const hasExpand = hasOutputs || hasProcess || hasDeps || !isPlanned;
|
|
67755
67926
|
/** token 三段之一:null 给占位(不编造 0)。 */
|
|
67756
67927
|
const tokenPart = (v) => v === null ? "—" : formatTokenCount(v);
|
|
67757
67928
|
/**
|
|
@@ -67865,7 +68036,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67865
68036
|
event.stopPropagation();
|
|
67866
68037
|
if (canOpenFile) openFile?.(sid, path);
|
|
67867
68038
|
}
|
|
67868
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
68039
|
+
}, path.endsWith("/") ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
67869
68040
|
path,
|
|
67870
68041
|
size: 16
|
|
67871
68042
|
})))), outputs.length > 3 ? (0, react$1.createElement)("button", {
|
|
@@ -67894,7 +68065,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67894
68065
|
},
|
|
67895
68066
|
"aria-expanded": open,
|
|
67896
68067
|
style: { transform: open ? "rotate(180deg)" : "none" }
|
|
67897
|
-
})) : null)), open && (hasOutputs || hasDeps || eventsError !== null || events !== null && events.length > 0) ? (0, react$1.createElement)("div", { className: "dsh-tdt-rec-exp" }, outputs.length === 0 ? null : (0, react$1.createElement)("div", { className: "dsh-tdt-rec-expouts" }, outputs.map((path) => (0, react$1.createElement)("button", {
|
|
68068
|
+
})) : null)), open && (hasOutputs || hasProcess || hasDeps || eventsError !== null || events !== null && events.length > 0) ? (0, react$1.createElement)("div", { className: "dsh-tdt-rec-exp" }, outputs.length === 0 ? null : (0, react$1.createElement)("div", { className: "dsh-tdt-rec-expouts" }, outputs.map((path) => (0, react$1.createElement)("button", {
|
|
67898
68069
|
key: path,
|
|
67899
68070
|
type: "button",
|
|
67900
68071
|
title: path,
|
|
@@ -67903,7 +68074,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67903
68074
|
onClick: () => {
|
|
67904
68075
|
if (canOpenFile) openFile?.(sid, path);
|
|
67905
68076
|
}
|
|
67906
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
68077
|
+
}, path.endsWith("/") ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 14 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
67907
68078
|
path,
|
|
67908
68079
|
size: 14
|
|
67909
68080
|
}), (0, react$1.createElement)(MarqueeText, {
|
|
@@ -67913,7 +68084,13 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67913
68084
|
maxWidth: "40ch",
|
|
67914
68085
|
minWidth: 0
|
|
67915
68086
|
}
|
|
67916
|
-
})))),
|
|
68087
|
+
})))), (0, react$1.createElement)(ProcessFiles, {
|
|
68088
|
+
paths: processOutputs,
|
|
68089
|
+
onOpen: canOpenFile ? (path) => {
|
|
68090
|
+
openFile?.(sid, path);
|
|
68091
|
+
} : void 0,
|
|
68092
|
+
t
|
|
68093
|
+
}), deps.length === 0 ? null : (0, react$1.createElement)("div", { className: "dsh-tdt-rec-depsec" }, (0, react$1.createElement)("div", { className: "dsh-tdt-rec-evtitle" }, t("listSectionDepends")), (0, react$1.createElement)("div", { className: "dsh-tdt-rec-depgrid" }, deps.map((dep, index) => {
|
|
67917
68094
|
const depOuts = Array.isArray(dep.outputs) ? dep.outputs : [];
|
|
67918
68095
|
const depSid = dep.sessionId;
|
|
67919
68096
|
const depHasSid = depSid !== null && depSid !== "";
|
|
@@ -67960,7 +68137,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
67960
68137
|
event.stopPropagation();
|
|
67961
68138
|
if (depCanOpen) openFile?.(depSid, path);
|
|
67962
68139
|
}
|
|
67963
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
68140
|
+
}, path.endsWith("/") ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
67964
68141
|
path,
|
|
67965
68142
|
size: 16
|
|
67966
68143
|
})))), depOuts.length > DEP_OUT_MAX ? (0, react$1.createElement)("button", {
|
|
@@ -68362,7 +68539,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
68362
68539
|
*
|
|
68363
68540
|
* ⚠️ 未来**没有实例行**(决策 31 懒建行:到点才 INSERT,不预建、不回看)⇒ 这里算出的是
|
|
68364
68541
|
* 「按当前定义推算的计划」,任务改定义 / 停用后会随之变化 —— 是真实计算、不是模拟数据,
|
|
68365
|
-
* UI
|
|
68542
|
+
* UI 必须把它与「已发生」如实区分(仓库硬规则:正常功能一律真实取数,禁止模拟)。
|
|
68366
68543
|
*/
|
|
68367
68544
|
function planEntriesByDay(tasks, from, to, now) {
|
|
68368
68545
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -69460,7 +69637,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
69460
69637
|
/**
|
|
69461
69638
|
* 任务卡片展开区三面板(决策 55):左下三个分段按钮(基础信息 / 执行记录 / 日志,默认基础信息),
|
|
69462
69639
|
* 中间内容区三选一替换(统一最大高度滚动容器),右下按钮区(编辑任务 + 删除)。
|
|
69463
|
-
* 数据全走 `client/query.ts`
|
|
69640
|
+
* 数据全走 `client/query.ts` 真实取数(仓库硬规则:禁止 mock)。
|
|
69464
69641
|
*/
|
|
69465
69642
|
function TaskExpandPanel(props) {
|
|
69466
69643
|
const { row, t, tt, scheduleLine, modelText, onEdit, onDelete, onRunNow, onOpenFile, onOpenSession, onViewTask, refresh } = props;
|
|
@@ -69723,7 +69900,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
69723
69900
|
name: item.name,
|
|
69724
69901
|
key: `${item.kind}:${item.name}`,
|
|
69725
69902
|
path: item.path ?? null,
|
|
69726
|
-
anchorSessionId: item.anchorSessionId ?? null
|
|
69903
|
+
anchorSessionId: item.anchorSessionId ?? null,
|
|
69904
|
+
isDir: item.isDir
|
|
69727
69905
|
})),
|
|
69728
69906
|
depends: row.depends.map((dep) => ({
|
|
69729
69907
|
id: dep.id,
|
|
@@ -69879,7 +70057,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
69879
70057
|
event.stopPropagation();
|
|
69880
70058
|
if (canOpenFile && openFile !== void 0 && sid !== null) openFile(sid, output);
|
|
69881
70059
|
}
|
|
69882
|
-
}, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
70060
|
+
}, output.endsWith("/") ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconFolderCloseRegular, { size: 16 }) : (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.FileTypeIcon, {
|
|
69883
70061
|
path: output,
|
|
69884
70062
|
size: 16
|
|
69885
70063
|
})))), outputs.length > 3 ? (0, react$1.createElement)("button", {
|
|
@@ -70208,7 +70386,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
70208
70386
|
}) : null);
|
|
70209
70387
|
}
|
|
70210
70388
|
function TaskListView(props) {
|
|
70211
|
-
const { t, rows, ready, onEdit, onViewTask, onDelete, onRunNow, onOpenFile, onOpenSession, onToggleEnabled, refresh, workspaces } = props;
|
|
70389
|
+
const { t, rows, ready, onEdit, onViewTask, onDelete, onRunNow, onOpenFile, onOpenSession, onToggleEnabled, refresh, workspaces, onCreate } = props;
|
|
70212
70390
|
const tt = (0, react$1.useMemo)(() => interpolateTranslate(t), [t]);
|
|
70213
70391
|
ensureTaskListStyle();
|
|
70214
70392
|
ensureTaskInfoStyle();
|
|
@@ -70316,10 +70494,38 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
70316
70494
|
size: "md",
|
|
70317
70495
|
width: WS_WIDTH,
|
|
70318
70496
|
marquee: true
|
|
70319
|
-
}))), visible.length === 0 ? (0, react$1.createElement)("
|
|
70497
|
+
}))), visible.length === 0 ? rows.length === 0 && !ready ? null : rows.length === 0 ? (0, react$1.createElement)("div", { style: {
|
|
70498
|
+
display: "flex",
|
|
70499
|
+
flexDirection: "column",
|
|
70500
|
+
alignItems: "center",
|
|
70501
|
+
justifyContent: "center",
|
|
70502
|
+
margin: "24px auto 0",
|
|
70503
|
+
padding: "48px 32px",
|
|
70504
|
+
textAlign: "center",
|
|
70505
|
+
border: "1px dashed var(--tdt-border-heavy)",
|
|
70506
|
+
borderRadius: "var(--tdt-radius-md)",
|
|
70507
|
+
background: "var(--tdt-surface-1)"
|
|
70508
|
+
} }, (0, react$1.createElement)("div", { style: { color: "var(--tdt-fg-3)" } }, (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconAlarmClockOutlineRegular, { size: 40 })), (0, react$1.createElement)("div", { style: {
|
|
70509
|
+
marginTop: "12px",
|
|
70510
|
+
fontSize: "var(--tdt-font-lg)",
|
|
70511
|
+
fontWeight: 600
|
|
70512
|
+
} }, t("listEmptyTitle")), (0, react$1.createElement)("div", { style: {
|
|
70513
|
+
marginTop: "6px",
|
|
70514
|
+
maxWidth: "360px",
|
|
70515
|
+
fontSize: "var(--tdt-font-sm)",
|
|
70516
|
+
color: "var(--tdt-fg-2)",
|
|
70517
|
+
lineHeight: "var(--tdt-line-sm)"
|
|
70518
|
+
} }, t("listEmptyHint")), (0, react$1.createElement)(Button$2, {
|
|
70519
|
+
variant: "primary",
|
|
70520
|
+
size: "md",
|
|
70521
|
+
style: { marginTop: "16px" },
|
|
70522
|
+
onClick: () => {
|
|
70523
|
+
onCreate();
|
|
70524
|
+
}
|
|
70525
|
+
}, t("listEmptyAction"))) : (0, react$1.createElement)("p", { style: {
|
|
70320
70526
|
...metaStyle,
|
|
70321
70527
|
marginTop: "8px"
|
|
70322
|
-
} },
|
|
70528
|
+
} }, t("listEmptyFiltered")) : (0, react$1.createElement)("div", { style: { position: "relative" } }, visible.map((row) => (0, react$1.createElement)(TaskCard, {
|
|
70323
70529
|
key: row.id,
|
|
70324
70530
|
row,
|
|
70325
70531
|
t,
|
|
@@ -71365,7 +71571,10 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71365
71571
|
const avail = Math.min(Math.floor(window.innerWidth * PREVIEW_MAX_RATIO), window.innerWidth - 760 - reserved);
|
|
71366
71572
|
return Math.min(Math.max(Math.round(value), PREVIEW_MIN), Math.max(PREVIEW_MIN, Math.floor(avail)));
|
|
71367
71573
|
}
|
|
71368
|
-
/**
|
|
71574
|
+
/**
|
|
71575
|
+
* 实例行的产出物(决策 32③写回的列:JSON 数组,兼容逗号串)。
|
|
71576
|
+
* 2026-10-10 起 `outputs`(主文件)与 `process_outputs`(过程文件)**同一形状**,共用这一个解析器。
|
|
71577
|
+
*/
|
|
71369
71578
|
function parseOutputs(raw) {
|
|
71370
71579
|
if (typeof raw === "string" && raw.trim() !== "") {
|
|
71371
71580
|
try {
|
|
@@ -71457,11 +71666,14 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71457
71666
|
const [saving, setSaving] = (0, react$1.useState)(false);
|
|
71458
71667
|
const [failed, setFailed] = (0, react$1.useState)(null);
|
|
71459
71668
|
const [failedKey, setFailedKey] = (0, react$1.useState)(0);
|
|
71460
|
-
const [
|
|
71461
|
-
const
|
|
71462
|
-
const
|
|
71463
|
-
|
|
71464
|
-
|
|
71669
|
+
const [successToast, setSuccessToast] = (0, react$1.useState)(null);
|
|
71670
|
+
const successSeq = (0, react$1.useRef)(0);
|
|
71671
|
+
const notify = (text) => {
|
|
71672
|
+
successSeq.current += 1;
|
|
71673
|
+
setSuccessToast({
|
|
71674
|
+
text,
|
|
71675
|
+
seq: successSeq.current
|
|
71676
|
+
});
|
|
71465
71677
|
};
|
|
71466
71678
|
const [invalidToast, setInvalidToast] = (0, react$1.useState)({
|
|
71467
71679
|
on: false,
|
|
@@ -71729,7 +71941,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71729
71941
|
/**
|
|
71730
71942
|
* 删除任务(决策 55,卡片右下角快捷删除):DELETE /tasks { id }。
|
|
71731
71943
|
* 服务端语义:摘定义 + 整删任务目录(附件 / 版本 / 快照),实例 / 事件保留做审计;
|
|
71732
|
-
* 成功后 overview.refresh()
|
|
71944
|
+
* 成功后 overview.refresh() 让列表立刻少一行;若右侧正在编辑 / 查看该任务则一并关窗;
|
|
71945
|
+
* 失败走 viewErr 条(操作类失败留时间读)。
|
|
71733
71946
|
*/
|
|
71734
71947
|
const deleteTask = async (id) => {
|
|
71735
71948
|
try {
|
|
@@ -71745,6 +71958,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71745
71958
|
return message;
|
|
71746
71959
|
}
|
|
71747
71960
|
overview.refresh();
|
|
71961
|
+
if (editor?.id === id) setEditor(null);
|
|
71962
|
+
notify(t("editorTaskDeleted"));
|
|
71748
71963
|
return null;
|
|
71749
71964
|
} catch (error) {
|
|
71750
71965
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -71803,7 +72018,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71803
72018
|
}
|
|
71804
72019
|
const missing = Array.isArray(body.missingAttachments) ? body.missingAttachments.filter((item) => typeof item === "string") : [];
|
|
71805
72020
|
setEditor(null);
|
|
71806
|
-
|
|
72021
|
+
notify(t("editorTaskSaved"));
|
|
71807
72022
|
if (typeof body.id === "string" && body.id !== "") overview.patchRow(body.id, rowPatchOf(definition));
|
|
71808
72023
|
overview.refresh();
|
|
71809
72024
|
if (missing.length > 0) setViewErr(`已保存,但以下附加文件已不在盘上,请重新上传:${missing.join("、")}`);
|
|
@@ -71829,6 +72044,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
71829
72044
|
}
|
|
71830
72045
|
setEditor(null);
|
|
71831
72046
|
overview.refresh();
|
|
72047
|
+
notify(t("editorTaskDeleted"));
|
|
71832
72048
|
} catch (error) {
|
|
71833
72049
|
setEditorError(humanizeTaskError(error instanceof Error ? error.message : String(error)));
|
|
71834
72050
|
}
|
|
@@ -72024,6 +72240,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
72024
72240
|
view: target,
|
|
72025
72241
|
didUnarchive,
|
|
72026
72242
|
outputs: row === null ? void 0 : parseOutputs(row.outputs),
|
|
72243
|
+
processOutputs: row === null ? void 0 : parseOutputs(row.process_outputs),
|
|
72027
72244
|
upstream: upstreamOf(row?.snapshot ?? null),
|
|
72028
72245
|
attached: row === null ? [] : attachmentsOf(row.snapshot ?? null, row.attachmentPaths),
|
|
72029
72246
|
workspacePath: workspacePathOf(row?.snapshot ?? null)
|
|
@@ -72127,7 +72344,8 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
72127
72344
|
onToggleEnabled: toggleTaskEnabled,
|
|
72128
72345
|
onRunNow: runTaskNow,
|
|
72129
72346
|
onViewTask: openViewer,
|
|
72130
|
-
workspaces: editorOptions.workspaces
|
|
72347
|
+
workspaces: editorOptions.workspaces,
|
|
72348
|
+
onCreate: openCreate
|
|
72131
72349
|
}) : tab === "settings" ? (0, react$1.createElement)(SettingsPage, { t }) : data === void 0 ? (0, react$1.createElement)("div", null, (0, react$1.createElement)("p", { style: hintStyle }, hasRaw ? t("debugRaw") : t("debugEmpty")), hasRaw ? (0, react$1.createElement)("pre", { style: preStyle }, raw) : null) : null, (0, react$1.createElement)(BackToTop, null)), viewing !== null ? (0, react$1.createElement)(SessionViewModal, {
|
|
72132
72350
|
t,
|
|
72133
72351
|
heading: viewing.heading,
|
|
@@ -72138,6 +72356,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
72138
72356
|
sessionId: viewing.sessionId,
|
|
72139
72357
|
view: viewing.view,
|
|
72140
72358
|
outputs: viewing.outputs,
|
|
72359
|
+
processOutputs: viewing.processOutputs,
|
|
72141
72360
|
forkSession: forkSession ?? void 0,
|
|
72142
72361
|
openHostSession: openHostSession ?? void 0,
|
|
72143
72362
|
workspaceFiles: workspaceFiles ?? void 0,
|
|
@@ -72163,6 +72382,14 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
|
|
|
72163
72382
|
onDone: () => {
|
|
72164
72383
|
setViewErr(null);
|
|
72165
72384
|
}
|
|
72385
|
+
}) : null, successToast !== null ? (0, react$1.createElement)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
72386
|
+
key: successToast.seq,
|
|
72387
|
+
text: successToast.text,
|
|
72388
|
+
tone: "success",
|
|
72389
|
+
holdMs: 2500,
|
|
72390
|
+
onDone: () => {
|
|
72391
|
+
setSuccessToast(null);
|
|
72392
|
+
}
|
|
72166
72393
|
}) : null, editor !== null ? (0, react$1.createElement)(TaskEditorDrawer, {
|
|
72167
72394
|
key: editor.id,
|
|
72168
72395
|
t,
|