@uniqueli/openwork 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -107,6 +107,19 @@ CUSTOM_MODEL=your-model-name # optional
107
107
 
108
108
  ## Changelog
109
109
 
110
+ ### v0.2.4 (2026-02-06)
111
+ - ✨ **聊天建议卡片**: 新对话空状态下显示可点击的建议卡片(文件整理、内容创作、文档处理),点击即可快速开始对话
112
+
113
+ ### v0.2.3 (2026-02-04)
114
+ - ✨ **Skills System**: 新增技能配置系统,支持 12 个内置技能和自定义技能创建
115
+ - 🐛 修复 `deleteUserSkill` 误删所有技能记录的严重 Bug
116
+ - 🐛 修复 Switch 组件、创建技能对话框、技能过滤等多个问题
117
+ - ⚡ 技能初始化改为懒加载,提升启动性能
118
+
119
+ ### v0.2.2 (2026-xx-xx)
120
+ - ✨ 支持多个自定义 API 配置
121
+ - 🔧 动态 Provider 系统
122
+
110
123
  ### v0.2.1 (2026-01-19)
111
124
  - 🐛 **Critical Fix**: Fixed "Missing credentials" error for users without OpenAI API key
112
125
  - 🔧 Custom API now works correctly even when OPENAI_API_KEY is not set in environment
@@ -489,6 +489,10 @@
489
489
  margin-top: calc(var(--spacing) * 2);
490
490
  }
491
491
 
492
+ .mt-6 {
493
+ margin-top: calc(var(--spacing) * 6);
494
+ }
495
+
492
496
  .mr-1 {
493
497
  margin-right: calc(var(--spacing) * 1);
494
498
  }
@@ -1434,6 +1438,16 @@
1434
1438
  }
1435
1439
  }
1436
1440
 
1441
+ .bg-accent\/30 {
1442
+ background-color: var(--accent);
1443
+ }
1444
+
1445
+ @supports (color: color-mix(in lab, red, red)) {
1446
+ .bg-accent\/30 {
1447
+ background-color: color-mix(in oklab, var(--accent) 30%, transparent);
1448
+ }
1449
+ }
1450
+
1437
1451
  .bg-amber-500\/5 {
1438
1452
  background-color: #f99c000d;
1439
1453
  }
@@ -12785,6 +12785,24 @@ const Music = createLucideIcon("Music", [
12785
12785
  ["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
12786
12786
  ["circle", { cx: "18", cy: "16", r: "3", key: "1hluhg" }]
12787
12787
  ]);
12788
+ const PenTool = createLucideIcon("PenTool", [
12789
+ [
12790
+ "path",
12791
+ {
12792
+ d: "M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z",
12793
+ key: "nt11vn"
12794
+ }
12795
+ ],
12796
+ [
12797
+ "path",
12798
+ {
12799
+ d: "m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18",
12800
+ key: "15qc1e"
12801
+ }
12802
+ ],
12803
+ ["path", { d: "m2.3 2.3 7.286 7.286", key: "1wuzzi" }],
12804
+ ["circle", { cx: "11", cy: "11", r: "2", key: "xmgehs" }]
12805
+ ]);
12788
12806
  const Pencil = createLucideIcon("Pencil", [
12789
12807
  [
12790
12808
  "path",
@@ -75841,6 +75859,76 @@ function ContextUsageIndicator({
75841
75859
  ] }) })
75842
75860
  ] });
75843
75861
  }
75862
+ const Card = reactExports.forwardRef(
75863
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(
75864
+ "div",
75865
+ {
75866
+ ref,
75867
+ className: cn("rounded-sm border border-border bg-card text-card-foreground", className),
75868
+ ...props
75869
+ }
75870
+ )
75871
+ );
75872
+ Card.displayName = "Card";
75873
+ const CardHeader = reactExports.forwardRef(
75874
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-4", className), ...props })
75875
+ );
75876
+ CardHeader.displayName = "CardHeader";
75877
+ const CardTitle = reactExports.forwardRef(
75878
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { ref, className: cn("text-section-header", className), ...props })
75879
+ );
75880
+ CardTitle.displayName = "CardTitle";
75881
+ const CardDescription = reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
75882
+ CardDescription.displayName = "CardDescription";
75883
+ const CardContent = reactExports.forwardRef(
75884
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("p-4 pt-0", className), ...props })
75885
+ );
75886
+ CardContent.displayName = "CardContent";
75887
+ const CardFooter = reactExports.forwardRef(
75888
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("flex items-center p-4 pt-0", className), ...props })
75889
+ );
75890
+ CardFooter.displayName = "CardFooter";
75891
+ const ICON_MAP = {
75892
+ FolderOpen,
75893
+ PenTool,
75894
+ FileText
75895
+ };
75896
+ const DEFAULT_SUGGESTIONS = [
75897
+ {
75898
+ icon: "FolderOpen",
75899
+ title: "文件整理",
75900
+ description: "智能整理和管理本地文件"
75901
+ },
75902
+ {
75903
+ icon: "PenTool",
75904
+ title: "内容创作",
75905
+ description: "创建演示文稿、文档和多媒体内容"
75906
+ },
75907
+ {
75908
+ icon: "FileText",
75909
+ title: "文档处理",
75910
+ description: "处理和分析文档数据"
75911
+ }
75912
+ ];
75913
+ function SuggestionCards({ onSelect }) {
75914
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-testid": "suggestion-cards", className: "grid grid-cols-3 gap-3 mt-6 w-full max-w-lg", children: DEFAULT_SUGGESTIONS.map((suggestion) => {
75915
+ const IconComponent = ICON_MAP[suggestion.icon];
75916
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
75917
+ Card,
75918
+ {
75919
+ className: "cursor-pointer transition-colors hover:bg-accent/50",
75920
+ onClick: () => onSelect(suggestion),
75921
+ "data-testid": "suggestion-card",
75922
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "p-4 flex flex-col items-start gap-2", children: [
75923
+ IconComponent && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-lg bg-accent/30 p-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(IconComponent, { className: "size-5 text-muted-foreground" }) }),
75924
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold", children: suggestion.title }),
75925
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: suggestion.description })
75926
+ ] })
75927
+ },
75928
+ suggestion.title
75929
+ );
75930
+ }) });
75931
+ }
75844
75932
  function ChatContainer({ threadId }) {
75845
75933
  const inputRef = reactExports.useRef(null);
75846
75934
  const scrollRef = reactExports.useRef(null);
@@ -76055,11 +76143,33 @@ function ChatContainer({ threadId }) {
76055
76143
  await selectWorkspaceFolder(threadId, setWorkspacePath, setWorkspaceFiles, () => {
76056
76144
  }, void 0);
76057
76145
  };
76146
+ const handleSuggestionSelect = async (suggestion) => {
76147
+ if (isLoading || !stream || !workspacePath) return;
76148
+ const message = suggestion.title;
76149
+ const userMessage = {
76150
+ id: crypto.randomUUID(),
76151
+ role: "user",
76152
+ content: message,
76153
+ created_at: /* @__PURE__ */ new Date()
76154
+ };
76155
+ appendMessage(userMessage);
76156
+ const currentThread = threads.find((t) => t.thread_id === threadId);
76157
+ if (currentThread?.title?.startsWith("Thread ")) {
76158
+ generateTitleForFirstMessage(threadId, message);
76159
+ }
76160
+ await stream.submit(
76161
+ { messages: [{ type: "human", content: message }] },
76162
+ { config: { configurable: { thread_id: threadId, model_id: currentModel } } }
76163
+ );
76164
+ };
76058
76165
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 flex-col min-h-0 overflow-hidden", children: [
76059
76166
  /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "flex-1 min-h-0", ref: scrollRef, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-3xl mx-auto space-y-4", children: [
76060
76167
  displayMessages.length === 0 && !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-20 text-muted-foreground", children: [
76061
76168
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-section-header mb-2", children: "NEW THREAD" }),
76062
- workspacePath ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm", children: "Start a conversation with the agent" }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-center space-y-3", children: [
76169
+ workspacePath ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
76170
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-sm", children: "Start a conversation with the agent" }),
76171
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SuggestionCards, { onSelect: handleSuggestionSelect })
76172
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm text-center space-y-3", children: [
76063
76173
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
76064
76174
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-amber-500", children: "Select a workspace folder" }),
76065
76175
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "block text-xs mt-1 opacity-75", children: "The agent needs a workspace to create and modify files" })
@@ -77728,35 +77838,6 @@ function KanbanColumn({
77728
77838
  }
77729
77839
  );
77730
77840
  }
77731
- const Card = reactExports.forwardRef(
77732
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx(
77733
- "div",
77734
- {
77735
- ref,
77736
- className: cn("rounded-sm border border-border bg-card text-card-foreground", className),
77737
- ...props
77738
- }
77739
- )
77740
- );
77741
- Card.displayName = "Card";
77742
- const CardHeader = reactExports.forwardRef(
77743
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-4", className), ...props })
77744
- );
77745
- CardHeader.displayName = "CardHeader";
77746
- const CardTitle = reactExports.forwardRef(
77747
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { ref, className: cn("text-section-header", className), ...props })
77748
- );
77749
- CardTitle.displayName = "CardTitle";
77750
- const CardDescription = reactExports.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
77751
- CardDescription.displayName = "CardDescription";
77752
- const CardContent = reactExports.forwardRef(
77753
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("p-4 pt-0", className), ...props })
77754
- );
77755
- CardContent.displayName = "CardContent";
77756
- const CardFooter = reactExports.forwardRef(
77757
- ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref, className: cn("flex items-center p-4 pt-0", className), ...props })
77758
- );
77759
- CardFooter.displayName = "CardFooter";
77760
77841
  function ThreadStatusIcon({ threadId }) {
77761
77842
  const { isLoading } = useThreadStream(threadId);
77762
77843
  if (isLoading) {
@@ -78120,7 +78201,7 @@ function App() {
78120
78201
  },
78121
78202
  children: [
78122
78203
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-name", children: "OPENWORK" }),
78123
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-version", children: "0.2.3" })
78204
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "app-badge-version", children: "0.2.4" })
78124
78205
  ]
78125
78206
  }
78126
78207
  ),
@@ -7,8 +7,8 @@
7
7
  http-equiv="Content-Security-Policy"
8
8
  content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
9
9
  />
10
- <script type="module" crossorigin src="./assets/index-DTaVewa6.js"></script>
11
- <link rel="stylesheet" crossorigin href="./assets/index-BmPF126u.css">
10
+ <script type="module" crossorigin src="./assets/index-Be3u7LN6.js"></script>
11
+ <link rel="stylesheet" crossorigin href="./assets/index-B2t12qbx.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniqueli/openwork",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "A tactical agent interface for deepagentsjs with multiple custom API support",
5
5
  "main": "./out/main/index.js",
6
6
  "files": [