@blade-hq/agent-kit 0.5.30 → 0.5.32

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  useSessionStore
3
- } from "./chunk-JWHBUVSM.js";
3
+ } from "./chunk-QMOW3TDA.js";
4
4
 
5
5
  // src/react/hooks/use-session.ts
6
6
  function useSession() {
@@ -27,4 +27,4 @@ function useSession() {
27
27
  export {
28
28
  useSession
29
29
  };
30
- //# sourceMappingURL=chunk-EP5LVNO3.js.map
30
+ //# sourceMappingURL=chunk-YPFIWC45.js.map
@@ -1139,6 +1139,29 @@ interface paths {
1139
1139
  patch?: never;
1140
1140
  trace?: never;
1141
1141
  };
1142
+ "/api/sessions/{session_id}/preview-pdf/{file_path}": {
1143
+ parameters: {
1144
+ query?: never;
1145
+ header?: never;
1146
+ path?: never;
1147
+ cookie?: never;
1148
+ };
1149
+ /**
1150
+ * Preview As Pdf
1151
+ * @description 将 Office 文件(Visio 等)在沙盒内用 soffice 转为 PDF,供前端 PdfPreview 渲染。
1152
+ *
1153
+ * 转换结果按源文件 mtime+size 缓存,避免重复转换。
1154
+ * 需要沙盒镜像内安装 LibreOffice。
1155
+ */
1156
+ get: operations["preview_as_pdf_api_sessions__session_id__preview_pdf__file_path__get"];
1157
+ put?: never;
1158
+ post?: never;
1159
+ delete?: never;
1160
+ options?: never;
1161
+ head?: never;
1162
+ patch?: never;
1163
+ trace?: never;
1164
+ };
1142
1165
  "/api/sessions/{session_id}/upset_extra_info": {
1143
1166
  parameters: {
1144
1167
  query?: never;
@@ -1498,6 +1521,28 @@ interface paths {
1498
1521
  patch?: never;
1499
1522
  trace?: never;
1500
1523
  };
1524
+ "/api/solutions/ensure-from-registry": {
1525
+ parameters: {
1526
+ query?: never;
1527
+ header?: never;
1528
+ path?: never;
1529
+ cookie?: never;
1530
+ };
1531
+ get?: never;
1532
+ put?: never;
1533
+ /**
1534
+ * Ensure Solution From Registry
1535
+ * @description 本地无此 solution 时,按 org/name 从 skill_registry 下载并热加载注册。
1536
+ *
1537
+ * 返回本地 solution_id(= solution.yaml 的 id),前端据此建会话进对话页。
1538
+ */
1539
+ post: operations["ensure_solution_from_registry_api_solutions_ensure_from_registry_post"];
1540
+ delete?: never;
1541
+ options?: never;
1542
+ head?: never;
1543
+ patch?: never;
1544
+ trace?: never;
1545
+ };
1501
1546
  "/api/solutions": {
1502
1547
  parameters: {
1503
1548
  query?: never;
@@ -5085,6 +5130,11 @@ interface components {
5085
5130
  */
5086
5131
  bump: string;
5087
5132
  };
5133
+ /** EnsureFromRegistryRequest */
5134
+ EnsureFromRegistryRequest: {
5135
+ /** Registry Id */
5136
+ registry_id: string;
5137
+ };
5088
5138
  /** EnvBucket */
5089
5139
  EnvBucket: {
5090
5140
  /** Bucket */
@@ -8538,6 +8588,38 @@ interface operations {
8538
8588
  };
8539
8589
  };
8540
8590
  };
8591
+ preview_as_pdf_api_sessions__session_id__preview_pdf__file_path__get: {
8592
+ parameters: {
8593
+ query?: never;
8594
+ header?: never;
8595
+ path: {
8596
+ session_id: string;
8597
+ file_path: string;
8598
+ };
8599
+ cookie?: never;
8600
+ };
8601
+ requestBody?: never;
8602
+ responses: {
8603
+ /** @description Successful Response */
8604
+ 200: {
8605
+ headers: {
8606
+ [name: string]: unknown;
8607
+ };
8608
+ content: {
8609
+ "application/json": unknown;
8610
+ };
8611
+ };
8612
+ /** @description Validation Error */
8613
+ 422: {
8614
+ headers: {
8615
+ [name: string]: unknown;
8616
+ };
8617
+ content: {
8618
+ "application/json": components["schemas"]["HTTPValidationError"];
8619
+ };
8620
+ };
8621
+ };
8622
+ };
8541
8623
  upset_session_extra_info_api_sessions__session_id__upset_extra_info_post: {
8542
8624
  parameters: {
8543
8625
  query?: never;
@@ -9451,6 +9533,41 @@ interface operations {
9451
9533
  };
9452
9534
  };
9453
9535
  };
9536
+ ensure_solution_from_registry_api_solutions_ensure_from_registry_post: {
9537
+ parameters: {
9538
+ query?: never;
9539
+ header?: never;
9540
+ path?: never;
9541
+ cookie?: never;
9542
+ };
9543
+ requestBody: {
9544
+ content: {
9545
+ "application/json": components["schemas"]["EnsureFromRegistryRequest"];
9546
+ };
9547
+ };
9548
+ responses: {
9549
+ /** @description Successful Response */
9550
+ 200: {
9551
+ headers: {
9552
+ [name: string]: unknown;
9553
+ };
9554
+ content: {
9555
+ "application/json": {
9556
+ [key: string]: string;
9557
+ };
9558
+ };
9559
+ };
9560
+ /** @description Validation Error */
9561
+ 422: {
9562
+ headers: {
9563
+ [name: string]: unknown;
9564
+ };
9565
+ content: {
9566
+ "application/json": components["schemas"]["HTTPValidationError"];
9567
+ };
9568
+ };
9569
+ };
9570
+ };
9454
9571
  list_solutions_api_solutions_get: {
9455
9572
  parameters: {
9456
9573
  query?: never;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getClient
3
- } from "../../chunk-JWHBUVSM.js";
3
+ } from "../../chunk-QMOW3TDA.js";
4
4
  import "../../chunk-J3XVFPOV.js";
5
5
  import "../../chunk-ZWO6YBLA.js";
6
6
  import "../../chunk-JCJFFJ42.js";
@@ -16,14 +16,14 @@ import {
16
16
  isErrorMessage,
17
17
  isUserMessage,
18
18
  useWhatIfQuoteContext
19
- } from "../../../chunk-UW55FYRL.js";
19
+ } from "../../../chunk-FXEELOLI.js";
20
20
  import {
21
21
  AskUserQuestionBlock
22
- } from "../../../chunk-S66X23O7.js";
22
+ } from "../../../chunk-CFW62YND.js";
23
23
  import "../../../chunk-2UP7MG3J.js";
24
24
  import "../../../chunk-H62LH2AG.js";
25
- import "../../../chunk-XTEHNSFN.js";
26
- import "../../../chunk-JWHBUVSM.js";
25
+ import "../../../chunk-EAZ7AGFY.js";
26
+ import "../../../chunk-QMOW3TDA.js";
27
27
  import "../../../chunk-J3XVFPOV.js";
28
28
  import "../../../chunk-ZWO6YBLA.js";
29
29
  import "../../../chunk-7LEKQI47.js";
@@ -3,10 +3,10 @@ import {
3
3
  PlanSummaryCard,
4
4
  extractLatestPlanMessages,
5
5
  parsePlanMessages
6
- } from "../../../chunk-S66X23O7.js";
6
+ } from "../../../chunk-CFW62YND.js";
7
7
  import "../../../chunk-2UP7MG3J.js";
8
- import "../../../chunk-XTEHNSFN.js";
9
- import "../../../chunk-JWHBUVSM.js";
8
+ import "../../../chunk-EAZ7AGFY.js";
9
+ import "../../../chunk-QMOW3TDA.js";
10
10
  import "../../../chunk-J3XVFPOV.js";
11
11
  import "../../../chunk-ZWO6YBLA.js";
12
12
  import {
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  useSession
3
- } from "../../../chunk-EP5LVNO3.js";
3
+ } from "../../../chunk-YPFIWC45.js";
4
4
  import {
5
5
  checkoutSession,
6
6
  getSessionCheckpoints,
7
7
  useChatStore,
8
8
  useSessionStore
9
- } from "../../../chunk-JWHBUVSM.js";
9
+ } from "../../../chunk-QMOW3TDA.js";
10
10
  import "../../../chunk-J3XVFPOV.js";
11
11
  import "../../../chunk-ZWO6YBLA.js";
12
12
  import {
@@ -23,6 +23,8 @@ interface WorkspaceFilesPanelProps {
23
23
  title?: string;
24
24
  rootPath?: string;
25
25
  readOnly?: boolean;
26
+ expandedDirs?: Set<string>;
27
+ onExpandedDirsChange?: (dirs: Set<string>) => void;
26
28
  onShareFile?: (path: string, name: string) => Promise<void>;
27
29
  onSync?: () => Promise<void>;
28
30
  allowDelete?: boolean;
@@ -33,7 +35,7 @@ interface WorkspaceFilesPanelProps {
33
35
  listDir?: (sessionId: string, dirPath: string) => Promise<WorkspaceFileEntry[]>;
34
36
  queryKeyScope?: readonly unknown[];
35
37
  }
36
- declare function WorkspaceFilesPanel({ sessionId, enableEditor, className, treeContainerClassName, title, rootPath, readOnly, onShareFile, onSync, allowDelete, topSlot, onOpenFile, listDir, queryKeyScope, }: WorkspaceFilesPanelProps): react_jsx_runtime.JSX.Element;
38
+ declare function WorkspaceFilesPanel({ sessionId, enableEditor, className, treeContainerClassName, title, rootPath, readOnly, expandedDirs: controlledExpandedDirs, onExpandedDirsChange, onShareFile, onSync, allowDelete, topSlot, onOpenFile, listDir, queryKeyScope, }: WorkspaceFilesPanelProps): react_jsx_runtime.JSX.Element;
37
39
 
38
40
  type FileEntry = Awaited<ReturnType<typeof listDir>>[number];
39
41
  type ListDirFn = (sessionId: string, dirPath: string) => Promise<FileEntry[]>;
@@ -41,6 +43,8 @@ interface FileTreeProps {
41
43
  sessionId: string | null;
42
44
  checkActiveSession?: boolean;
43
45
  enableEditor?: boolean;
46
+ expandedDirs?: Set<string>;
47
+ defaultExpandedDirs?: Set<string>;
44
48
  onExpandedDirsChange?: (dirs: Set<string>) => void;
45
49
  rootPath?: string;
46
50
  readOnly?: boolean;
@@ -50,6 +54,6 @@ interface FileTreeProps {
50
54
  listDir?: ListDirFn;
51
55
  queryKeyScope?: readonly unknown[];
52
56
  }
53
- declare function FileTree({ sessionId, checkActiveSession, enableEditor, onExpandedDirsChange, rootPath, readOnly, onShareFile, allowDelete, onOpenFile, listDir, queryKeyScope, }: FileTreeProps): react_jsx_runtime.JSX.Element;
57
+ declare function FileTree({ sessionId, checkActiveSession, enableEditor, expandedDirs: controlledExpandedDirs, defaultExpandedDirs, onExpandedDirsChange, rootPath, readOnly, onShareFile, allowDelete, onOpenFile, listDir, queryKeyScope, }: FileTreeProps): react_jsx_runtime.JSX.Element;
54
58
 
55
59
  export { FileTree, WorkspaceFilesPanel };
@@ -5,7 +5,7 @@ import {
5
5
  } from "../../../chunk-H62LH2AG.js";
6
6
  import {
7
7
  resolveSessionFilePreviewTarget
8
- } from "../../../chunk-XTEHNSFN.js";
8
+ } from "../../../chunk-EAZ7AGFY.js";
9
9
  import {
10
10
  apiFetchText,
11
11
  copyFile,
@@ -19,7 +19,7 @@ import {
19
19
  useChatStore,
20
20
  useSessionStore,
21
21
  useUiStore
22
- } from "../../../chunk-JWHBUVSM.js";
22
+ } from "../../../chunk-QMOW3TDA.js";
23
23
  import "../../../chunk-J3XVFPOV.js";
24
24
  import "../../../chunk-ZWO6YBLA.js";
25
25
  import {
@@ -31,7 +31,13 @@ import "../../../chunk-PZ5AY32C.js";
31
31
  // src/react/components/workspace/WorkspaceFilesPanel.tsx
32
32
  import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
33
33
  import { FileText, FolderTree, FolderUp, Loader2 as Loader22, PanelRightOpen, RefreshCw, Upload } from "lucide-react";
34
- import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState3 } from "react";
34
+ import {
35
+ useCallback as useCallback2,
36
+ useEffect as useEffect2,
37
+ useMemo as useMemo2,
38
+ useRef as useRef2,
39
+ useState as useState3
40
+ } from "react";
35
41
 
36
42
  // src/react/components/workspace/FileTree.tsx
37
43
  import { useQuery, useQueryClient } from "@tanstack/react-query";
@@ -284,6 +290,8 @@ function FileTree2({
284
290
  sessionId,
285
291
  checkActiveSession = true,
286
292
  enableEditor = false,
293
+ expandedDirs: controlledExpandedDirs,
294
+ defaultExpandedDirs,
287
295
  onExpandedDirsChange,
288
296
  rootPath = ROOT_PATH,
289
297
  readOnly = false,
@@ -294,14 +302,19 @@ function FileTree2({
294
302
  queryKeyScope
295
303
  }) {
296
304
  const pushArtifact = useUiStore((state) => state.pushArtifact);
297
- const [expandedDirs, setExpandedDirs] = useState2(/* @__PURE__ */ new Set([rootPath]));
305
+ const [internalExpandedDirs, setInternalExpandedDirs] = useState2(
306
+ () => new Set(defaultExpandedDirs ?? [rootPath])
307
+ );
308
+ const expandedDirs = controlledExpandedDirs ?? internalExpandedDirs;
298
309
  const [selectedPath, setSelectedPath] = useState2();
299
310
  const [openingFilePath, setOpeningFilePath] = useState2(null);
300
311
  const isStreaming = useChatStore((s) => sessionId ? s.isStreaming[sessionId] ?? false : false);
301
312
  const queryClient = useQueryClient();
302
313
  const prevStreamingRef = useRef(isStreaming);
303
314
  const applyExpandedDirs = useEffectEvent((dirs) => {
304
- setExpandedDirs(dirs);
315
+ if (!controlledExpandedDirs) {
316
+ setInternalExpandedDirs(dirs);
317
+ }
305
318
  onExpandedDirsChange?.(dirs);
306
319
  });
307
320
  useEffect(() => {
@@ -784,15 +797,34 @@ function FileNode({
784
797
  setActiveAction(null);
785
798
  }
786
799
  };
800
+ const openEntry = () => {
801
+ if (isRenaming) return;
802
+ onSelectPath(entry.path);
803
+ void onOpenFile(entry.path, entry.name);
804
+ };
787
805
  return /* @__PURE__ */ jsxs2(
788
806
  "div",
789
807
  {
790
- className: cn(TREE_ROW_CLASS, isSelected && "bg-muted"),
808
+ className: cn(
809
+ TREE_ROW_CLASS,
810
+ "items-center gap-1.5 py-1.5",
811
+ isSelected && "bg-muted"
812
+ ),
791
813
  draggable: !isRenaming,
814
+ role: !isRenaming ? "button" : void 0,
815
+ tabIndex: !isRenaming ? 0 : void 0,
816
+ onClick: openEntry,
792
817
  onDragStart: (e) => {
793
818
  e.dataTransfer.setData("application/blade-file-ref", JSON.stringify({ path: entry.path, name: entry.name }));
794
819
  e.dataTransfer.effectAllowed = "copy";
795
820
  },
821
+ onKeyDown: (event) => {
822
+ if (isRenaming) return;
823
+ if (event.key === "Enter" || event.key === " ") {
824
+ event.preventDefault();
825
+ openEntry();
826
+ }
827
+ },
796
828
  children: [
797
829
  /* @__PURE__ */ jsx2("span", { className: "size-5 shrink-0" }),
798
830
  /* @__PURE__ */ jsx2(FileTreeIcon, { children: getFileIcon(entry.name) }),
@@ -817,22 +849,12 @@ function FileNode({
817
849
  }
818
850
  }
819
851
  }
820
- ) : /* @__PURE__ */ jsxs2(
821
- "button",
822
- {
823
- type: "button",
824
- className: "flex min-w-0 flex-1 cursor-pointer items-center border-none bg-transparent p-0 text-left",
825
- onClick: () => {
826
- onSelectPath(entry.path);
827
- void onOpenFile(entry.path, entry.name);
828
- },
829
- children: [
830
- /* @__PURE__ */ jsx2(FileTreeName, { className: "min-w-0 flex-1", children: entry.name }),
831
- /* @__PURE__ */ jsx2(FileTagList, { tags: entry.tags })
832
- ]
833
- }
834
- ),
835
- isOpening ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "ml-auto shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : !readOnly ? /* @__PURE__ */ jsxs2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: [
852
+ ) : /* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 flex-1 items-center text-left", children: [
853
+ /* @__PURE__ */ jsx2(FileTreeName, { className: "min-w-0 flex-1", children: entry.name }),
854
+ /* @__PURE__ */ jsx2(FileTagList, { tags: entry.tags })
855
+ ] }),
856
+ isOpening ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "ml-auto shrink-0 animate-spin text-[hsl(var(--muted-foreground))]" }) : null,
857
+ !isOpening && !readOnly ? /* @__PURE__ */ jsxs2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex group-focus-within:flex", children: [
836
858
  /* @__PURE__ */ jsx2(
837
859
  TreeActionButton,
838
860
  {
@@ -896,7 +918,7 @@ function FileNode({
896
918
  children: activeAction === "delete" ? /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "animate-spin" }) : /* @__PURE__ */ jsx2(Trash2, { size: 12 })
897
919
  }
898
920
  )
899
- ] }) : allowDelete ? /* @__PURE__ */ jsx2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex", children: /* @__PURE__ */ jsx2(
921
+ ] }) : !isOpening && allowDelete ? /* @__PURE__ */ jsx2(FileTreeActions, { className: "ml-auto hidden shrink-0 group-hover:flex group-focus-within:flex", children: /* @__PURE__ */ jsx2(
900
922
  TreeActionButton,
901
923
  {
902
924
  disabled: activeAction !== null,
@@ -1031,7 +1053,12 @@ function TreeActionButton({
1031
1053
  {
1032
1054
  type: "button",
1033
1055
  disabled,
1034
- onClick,
1056
+ onPointerDown: (event) => event.stopPropagation(),
1057
+ onKeyDown: (event) => event.stopPropagation(),
1058
+ onClick: (event) => {
1059
+ event.stopPropagation();
1060
+ onClick();
1061
+ },
1035
1062
  title,
1036
1063
  className: "flex items-center rounded p-1 text-[hsl(var(--muted-foreground))] transition-colors hover:bg-[hsl(var(--muted-foreground))/10] hover:text-[hsl(var(--foreground))] disabled:cursor-not-allowed disabled:opacity-50",
1037
1064
  children
@@ -1181,6 +1208,8 @@ function WorkspaceFilesPanel({
1181
1208
  title = "\u5DE5\u4F5C\u533A",
1182
1209
  rootPath = ".",
1183
1210
  readOnly = false,
1211
+ expandedDirs: controlledExpandedDirs,
1212
+ onExpandedDirsChange,
1184
1213
  onShareFile,
1185
1214
  onSync,
1186
1215
  allowDelete = false,
@@ -1189,7 +1218,8 @@ function WorkspaceFilesPanel({
1189
1218
  listDir: listDir2,
1190
1219
  queryKeyScope
1191
1220
  }) {
1192
- const [expandedDirs, setExpandedDirs] = useState3(/* @__PURE__ */ new Set());
1221
+ const [internalExpandedDirs, setInternalExpandedDirs] = useState3(/* @__PURE__ */ new Set([rootPath]));
1222
+ const expandedDirs = controlledExpandedDirs ?? internalExpandedDirs;
1193
1223
  const [isUploading, setIsUploading] = useState3(false);
1194
1224
  const [uploadProgress, setUploadProgress] = useState3(null);
1195
1225
  const [uploadFileCount, setUploadFileCount] = useState3(0);
@@ -1202,6 +1232,15 @@ function WorkspaceFilesPanel({
1202
1232
  (state) => sessionId ? state.messages[sessionId] ?? EMPTY_MESSAGES : EMPTY_MESSAGES
1203
1233
  );
1204
1234
  const pushArtifact = useUiStore((state) => state.pushArtifact);
1235
+ const updateExpandedDirs = useCallback2(
1236
+ (dirs) => {
1237
+ if (!controlledExpandedDirs) {
1238
+ setInternalExpandedDirs(dirs);
1239
+ }
1240
+ onExpandedDirsChange?.(dirs);
1241
+ },
1242
+ [controlledExpandedDirs, onExpandedDirsChange]
1243
+ );
1205
1244
  const inlineResources = useMemo2(() => {
1206
1245
  if (!sessionId) return [];
1207
1246
  return messages.flatMap(
@@ -1290,11 +1329,9 @@ function WorkspaceFilesPanel({
1290
1329
  type: "active"
1291
1330
  });
1292
1331
  if (targetDir !== ".") {
1293
- setExpandedDirs((prev) => {
1294
- const next = new Set(prev);
1295
- next.add(targetDir);
1296
- return next;
1297
- });
1332
+ const next = new Set(expandedDirs);
1333
+ next.add(targetDir);
1334
+ updateExpandedDirs(next);
1298
1335
  }
1299
1336
  if (result.failed.length > 0) {
1300
1337
  alert(`\u90E8\u5206\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: ${result.failed.join(", ")}`);
@@ -1433,7 +1470,8 @@ function WorkspaceFilesPanel({
1433
1470
  {
1434
1471
  sessionId,
1435
1472
  enableEditor,
1436
- onExpandedDirsChange: setExpandedDirs,
1473
+ expandedDirs,
1474
+ onExpandedDirsChange: updateExpandedDirs,
1437
1475
  rootPath,
1438
1476
  readOnly,
1439
1477
  onShareFile,