dsh-task-dispatch-table 0.1.1 → 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.
@@ -50,6 +50,6 @@ export declare function monthRangeQuery(year: number, month: number): {
50
50
  *
51
51
  * ⚠️ 未来**没有实例行**(决策 31 懒建行:到点才 INSERT,不预建、不回看)⇒ 这里算出的是
52
52
  * 「按当前定义推算的计划」,任务改定义 / 停用后会随之变化 —— 是真实计算、不是模拟数据,
53
- * UI 必须把它与「已发生」如实区分(AGENTS.md 第五条:正常功能一律真实取数,禁止模拟)。
53
+ * UI 必须把它与「已发生」如实区分(仓库硬规则:正常功能一律真实取数,禁止模拟)。
54
54
  */
55
55
  export declare function planEntriesByDay(tasks: readonly CalendarTask[], from: Date, to: Date, now: Date): Map<string, CalendarPlanEntry[]>;
@@ -58,7 +58,7 @@ export function monthRangeQuery(year, month) {
58
58
  *
59
59
  * ⚠️ 未来**没有实例行**(决策 31 懒建行:到点才 INSERT,不预建、不回看)⇒ 这里算出的是
60
60
  * 「按当前定义推算的计划」,任务改定义 / 停用后会随之变化 —— 是真实计算、不是模拟数据,
61
- * UI 必须把它与「已发生」如实区分(AGENTS.md 第五条:正常功能一律真实取数,禁止模拟)。
61
+ * UI 必须把它与「已发生」如实区分(仓库硬规则:正常功能一律真实取数,禁止模拟)。
62
62
  */
63
63
  export function planEntriesByDay(tasks, from, to, now) {
64
64
  const out = new Map();
package/dist/client.js CHANGED
@@ -602,8 +602,9 @@ window.__ModuleLoader__.load({
602
602
  editorUploadErrEmpty: "文件内容为空",
603
603
  editorUploadErrGeneric: "上传失败,请重试",
604
604
  editorPickerNoSession: "该工作区下还没有会话,无法读取文件。",
605
- editorAttachmentsHint: "附加文件会随任务一起派发给执行的 Agent:任务执行过程中,Agent 可读取或操作这些文件的内容。",
605
+ editorAttachmentsHint: "附加文件会随任务一起派发给执行的 Agent:任务执行过程中,Agent 可读取或操作这些文件的内容。也可从工作区选择整个目录(连带其下所有文件):Agent 拿到的是这个目录的路径,自己在里面找文件,提示词里写「附件里的 目录名/子文件路径」即可指定其中某一个。",
606
606
  editorPickerPick: "选择此文件",
607
+ editorPickerPickDir: "选择此目录(连带其下所有文件)",
607
608
  editorOpenEditor: "全屏编辑",
608
609
  editorPromptEditorTitle: "提示词编辑器(.md)",
609
610
  editorNoVersions: "暂无版本,保存后可在此回滚",
@@ -1263,8 +1264,9 @@ window.__ModuleLoader__.load({
1263
1264
  editorUploadErrEmpty: "File is empty",
1264
1265
  editorUploadErrGeneric: "Upload failed, please retry",
1265
1266
  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.",
1267
+ 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
1268
  editorPickerPick: "Pick this file",
1269
+ editorPickerPickDir: "Pick this folder (with everything under it)",
1268
1270
  editorOpenEditor: "Full-screen edit",
1269
1271
  editorPromptEditorTitle: "Prompt editor (.md)",
1270
1272
  editorNoVersions: "No versions yet — save one to roll back here",
@@ -54446,16 +54448,21 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
54446
54448
  }
54447
54449
  const cached = childCache[childPath];
54448
54450
  const isOpen = openDirs.has(childPath);
54451
+ const pickDir = () => {
54452
+ if (picker === true && onPick !== void 0) {
54453
+ onPick(relativizeToRoot(childPath, sessionId));
54454
+ return;
54455
+ }
54456
+ loadDir(childPath);
54457
+ };
54449
54458
  return (0, react$1.createElement)(react$1.Fragment, { key: childPath }, (0, react$1.createElement)("div", {
54450
- className: "dsh-tdt-sv-tree-row",
54459
+ className: "dsh-tdt-sv-tree-row" + (picker === true ? " dsh-tdt-sv-tree-row-pick" : ""),
54451
54460
  role: "button",
54452
54461
  tabIndex: 0,
54453
- title: childPath,
54454
- onClick: () => {
54455
- loadDir(childPath);
54456
- },
54462
+ title: picker === true ? t("editorPickerPickDir") : childPath,
54463
+ onClick: pickDir,
54457
54464
  onKeyDown: (event) => {
54458
- if (event.key === "Enter" || event.key === " ") loadDir(childPath);
54465
+ if (event.key === "Enter" || event.key === " ") pickDir();
54459
54466
  }
54460
54467
  }, tooled(isOpen ? t("explorerCollapse") : t("explorerExpand"), (0, react$1.createElement)("button", {
54461
54468
  type: "button",
@@ -66250,6 +66257,12 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66250
66257
  };
66251
66258
  }, [pickerOpen]);
66252
66259
  const [uploadError, setUploadError] = (0, react$1.useState)(null);
66260
+ /**
66261
+ * 刚上传、还没保存的附件:文件已在**服务端临时区**,但绝对路径只有服务端知道 ⇒ 由上传回包带回来存这里
66262
+ * (用户 2026-10-09:进了列表就要能点开预览,不能等保存)。
66263
+ * ⚠️ 只活组件内存,**绝不写进 draft** —— draft 会被序列化进任务定义 JSON,路径是服务端的、也不该留痕。
66264
+ */
66265
+ const [uploadPaths, setUploadPaths] = (0, react$1.useState)({});
66253
66266
  const [confirmDiscard, setConfirmDiscard] = (0, react$1.useState)(false);
66254
66267
  const initialDraftRef = (0, react$1.useRef)(draft);
66255
66268
  const dirty = stableStringify(draft) !== stableStringify(initialDraftRef.current);
@@ -66515,6 +66528,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66515
66528
  if (sendable.length === 0) return;
66516
66529
  setUploading(true);
66517
66530
  const added = [];
66531
+ const nextPaths = {};
66518
66532
  let lastErr = null;
66519
66533
  for (const file of sendable) {
66520
66534
  const controller = new AbortController();
@@ -66533,8 +66547,10 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66533
66547
  lastErr = typeof data?.error === "string" ? data.error : "upload-failed";
66534
66548
  continue;
66535
66549
  }
66550
+ const id = makeId();
66551
+ if (typeof data.path === "string" && data.path !== "") nextPaths[id] = data.path;
66536
66552
  added.push({
66537
- id: makeId(),
66553
+ id,
66538
66554
  name: data.name,
66539
66555
  kind: "upload",
66540
66556
  ref: data.ref
@@ -66547,8 +66563,43 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66547
66563
  }
66548
66564
  setUploading(false);
66549
66565
  if (added.length > 0) patch({ attachments: [...draft.attachments, ...added] });
66566
+ if (Object.keys(nextPaths).length > 0) setUploadPaths((prev) => ({
66567
+ ...prev,
66568
+ ...nextPaths
66569
+ }));
66550
66570
  if (lastErr !== null) setUploadError(lastErr);
66551
66571
  };
66572
+ /**
66573
+ * 这一行的预览目标(路径 + 锚点会话)。三档递进,**服务端解析优先**(已保存任务的绝对路径最权威):
66574
+ * ① overview 命中(服务端把 ref 绝对化 + 配好锚点会话);
66575
+ * ② link 型当场算:`ref` 本来就是**工作区相对路径**,而 FileBrowser 的 path 就是同一口径
66576
+ * (相对会话 cwd = 工作区根)⇒ **零换算**,锚点取该工作区最近会话(与选择器同一份 workspaceAnchors);
66577
+ * ③ upload 型(还没保存):用上传回包带回的临时区绝对路径,锚点任一有会话的工作区即可
66578
+ * (宿主要的只是「某个有效会话」,与服务端 `attachmentsWithPaths` 的兜底同款)。
66579
+ * 算不出锚点 ⇒ 返回 null ⇒ 该行不可点:**没有会话的工作区宿主列不出文件,不给假入口**。
66580
+ */
66581
+ const previewTargetOf = (att) => {
66582
+ const anchors = workspaceAnchors ?? {};
66583
+ const hit = resolvedAttachments?.find((r) => r.name === att.name && r.kind === att.kind && r.path !== void 0 && r.anchorSessionId !== void 0);
66584
+ if (hit !== void 0) return {
66585
+ path: hit.path,
66586
+ anchorSessionId: hit.anchorSessionId
66587
+ };
66588
+ if (att.kind === "link") {
66589
+ const anchor = anchors[att.workspace !== void 0 && att.workspace !== "" ? att.workspace : draft.workspace];
66590
+ return anchor === void 0 || anchor === "" ? null : {
66591
+ path: att.ref,
66592
+ anchorSessionId: anchor
66593
+ };
66594
+ }
66595
+ const abs = uploadPaths[att.id];
66596
+ if (abs === void 0 || abs === "") return null;
66597
+ const anyAnchor = Object.values(anchors).find((item) => typeof item === "string" && item !== "");
66598
+ return anyAnchor === void 0 ? null : {
66599
+ path: abs,
66600
+ anchorSessionId: anyAnchor
66601
+ };
66602
+ };
66552
66603
  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
66604
  className: "dsh-tdt-ed-label",
66554
66605
  style: {
@@ -66562,14 +66613,14 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66562
66613
  gap: "6px",
66563
66614
  marginBottom: "10px"
66564
66615
  } }, draft.attachments.map((att) => {
66565
- const hit = resolvedAttachments?.find((r) => r.name === att.name && r.kind === att.kind && r.path !== void 0 && r.anchorSessionId !== void 0);
66566
- const canView = hit !== void 0 && onOpenFile !== void 0;
66616
+ const target = previewTargetOf(att);
66617
+ const canView = target !== null && onOpenFile !== void 0;
66567
66618
  return (0, react$1.createElement)("div", {
66568
66619
  key: att.id,
66569
66620
  className: `dsh-tdt-ed-attrow${canView ? " dsh-tdt-ed-attrow--view" : ""}`,
66570
66621
  title: canView ? t("editorAttachmentView") : void 0,
66571
66622
  onClick: canView ? () => {
66572
- onOpenFile?.(hit.anchorSessionId, hit.path);
66623
+ onOpenFile?.(target.anchorSessionId, target.path);
66573
66624
  } : void 0
66574
66625
  }, (0, react$1.createElement)("span", { style: {
66575
66626
  flex: "none",
@@ -66601,6 +66652,11 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
66601
66652
  onClick: (event) => {
66602
66653
  event.stopPropagation();
66603
66654
  patch({ attachments: draft.attachments.filter((a) => a.id !== att.id) });
66655
+ setUploadPaths((prev) => {
66656
+ const next = { ...prev };
66657
+ delete next[att.id];
66658
+ return next;
66659
+ });
66604
66660
  },
66605
66661
  title: t("editorAttachmentRemove"),
66606
66662
  "aria-label": t("editorAttachmentRemove"),
@@ -68362,7 +68418,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
68362
68418
  *
68363
68419
  * ⚠️ 未来**没有实例行**(决策 31 懒建行:到点才 INSERT,不预建、不回看)⇒ 这里算出的是
68364
68420
  * 「按当前定义推算的计划」,任务改定义 / 停用后会随之变化 —— 是真实计算、不是模拟数据,
68365
- * UI 必须把它与「已发生」如实区分(AGENTS.md 第五条:正常功能一律真实取数,禁止模拟)。
68421
+ * UI 必须把它与「已发生」如实区分(仓库硬规则:正常功能一律真实取数,禁止模拟)。
68366
68422
  */
68367
68423
  function planEntriesByDay(tasks, from, to, now) {
68368
68424
  const out = /* @__PURE__ */ new Map();
@@ -69460,7 +69516,7 @@ button.dsh-tdt-sv-tfc-file:focus-visible{box-shadow:inset 0 0 0 2px var(--tdt-fo
69460
69516
  /**
69461
69517
  * 任务卡片展开区三面板(决策 55):左下三个分段按钮(基础信息 / 执行记录 / 日志,默认基础信息),
69462
69518
  * 中间内容区三选一替换(统一最大高度滚动容器),右下按钮区(编辑任务 + 删除)。
69463
- * 数据全走 `client/query.ts` 真实取数(AGENTS.md 第五条,禁止 mock)。
69519
+ * 数据全走 `client/query.ts` 真实取数(仓库硬规则:禁止 mock)。
69464
69520
  */
69465
69521
  function TaskExpandPanel(props) {
69466
69522
  const { row, t, tt, scheduleLine, modelText, onEdit, onDelete, onRunNow, onOpenFile, onOpenSession, onViewTask, refresh } = props;