@blade-hq/agent-kit 0.4.5 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +39 -1
  2. package/dist/{SkillStatusBar-DItrW2vv.d.ts → SkillStatusBar-DQyipdzn.d.ts} +112 -8
  3. package/dist/chunk-2UP7MG3J.js +66 -0
  4. package/dist/chunk-2UP7MG3J.js.map +1 -0
  5. package/dist/chunk-4VWLTG5L.js +2984 -0
  6. package/dist/chunk-4VWLTG5L.js.map +1 -0
  7. package/dist/chunk-7LEKQI47.js +32 -0
  8. package/dist/chunk-7LEKQI47.js.map +1 -0
  9. package/dist/chunk-CGOQI7ZL.js +8124 -0
  10. package/dist/chunk-CGOQI7ZL.js.map +1 -0
  11. package/dist/chunk-DQCXSPHP.js +33 -0
  12. package/dist/chunk-DQCXSPHP.js.map +1 -0
  13. package/dist/chunk-I3FFV63W.js +30 -0
  14. package/dist/chunk-I3FFV63W.js.map +1 -0
  15. package/dist/chunk-J3XVFPOV.js +58 -0
  16. package/dist/chunk-J3XVFPOV.js.map +1 -0
  17. package/dist/chunk-JCJFFJ42.js +39 -0
  18. package/dist/chunk-JCJFFJ42.js.map +1 -0
  19. package/dist/chunk-OKQWPNE3.js +1077 -0
  20. package/dist/chunk-OKQWPNE3.js.map +1 -0
  21. package/dist/chunk-PZ5AY32C.js +10 -0
  22. package/dist/chunk-PZ5AY32C.js.map +1 -0
  23. package/dist/chunk-TC5BBLWO.js +29 -0
  24. package/dist/chunk-TC5BBLWO.js.map +1 -0
  25. package/dist/chunk-VD4CKRMT.js +127 -0
  26. package/dist/chunk-VD4CKRMT.js.map +1 -0
  27. package/dist/chunk-X6MEYCU7.js +1401 -0
  28. package/dist/chunk-X6MEYCU7.js.map +1 -0
  29. package/dist/client/index.js +24 -1052
  30. package/dist/client/index.js.map +1 -1
  31. package/dist/react/api/licenses.js +11 -1470
  32. package/dist/react/api/licenses.js.map +1 -1
  33. package/dist/react/api/vibe-coding.js +25 -1481
  34. package/dist/react/api/vibe-coding.js.map +1 -1
  35. package/dist/react/cards/register.js +45 -138
  36. package/dist/react/cards/register.js.map +1 -1
  37. package/dist/react/components/chat/index.d.ts +7 -21
  38. package/dist/react/components/chat/index.js +28 -11366
  39. package/dist/react/components/chat/index.js.map +1 -1
  40. package/dist/react/components/plan/index.js +135 -3054
  41. package/dist/react/components/plan/index.js.map +1 -1
  42. package/dist/react/components/session/index.js +21 -1499
  43. package/dist/react/components/session/index.js.map +1 -1
  44. package/dist/react/components/workspace/index.js +116 -1715
  45. package/dist/react/components/workspace/index.js.map +1 -1
  46. package/dist/react/devtools/bridge-devtools/index.js +8 -51
  47. package/dist/react/devtools/bridge-devtools/index.js.map +1 -1
  48. package/dist/react/index.d.ts +2 -2
  49. package/dist/react/index.js +625 -14035
  50. package/dist/react/index.js.map +1 -1
  51. package/dist/style.css +1 -1
  52. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,11 @@ SDK 通过两个子包暴露能力:
17
17
  pnpm install
18
18
  ```
19
19
 
20
- 第三方项目未来发布后可安装同一个包,并按需要选择子包入口:
20
+ 第三方项目可安装发布包,并按需要选择子包入口:
21
+
22
+ ```bash
23
+ npm install @blade-hq/agent-kit @tanstack/react-query react react-dom sonner
24
+ ```
21
25
 
22
26
  ```ts
23
27
  import { BladeClient } from "@blade-hq/agent-kit/client"
@@ -27,6 +31,40 @@ import "@blade-hq/agent-kit/style.css"
27
31
 
28
32
  如果使用 `@blade-hq/agent-kit/chat`、`@blade-hq/agent-kit/session` 等预制 React UI,应用入口必须导入 `@blade-hq/agent-kit/style.css`。只使用 `/client` 或 hooks 自行渲染 UI 时不需要导入这份样式。
29
33
 
34
+ ## ChatView 自定义渲染
35
+
36
+ `ChatView` 默认负责会话数据、Socket.IO 流式更新、历史加载、输入框、技能状态和滚动行为。第三方应用可以只改样式,也可以替换局部渲染。
37
+
38
+ ```tsx
39
+ import { ChatView, type ToolRendererProps } from "@blade-hq/agent-kit/chat"
40
+
41
+ function BashTool({ toolCall }: ToolRendererProps) {
42
+ return <pre>{toolCall.arguments}</pre>
43
+ }
44
+
45
+ <ChatView
46
+ sessionId={sessionId}
47
+ classNames={{
48
+ root: "bg-white text-slate-950",
49
+ messageListContent: "max-w-4xl",
50
+ userMessage: "text-right",
51
+ assistantText: "text-base leading-7",
52
+ chatInputRoot: "border-t",
53
+ }}
54
+ components={{
55
+ EmptyState: () => <div className="py-16 text-center">开始一个新任务</div>,
56
+ SkillStatusBar: ({ sessionId }) => <div>当前会话:{sessionId}</div>,
57
+ }}
58
+ renderers={{
59
+ tool: {
60
+ Bash: BashTool,
61
+ },
62
+ }}
63
+ />
64
+ ```
65
+
66
+ 如果需要完全自建聊天界面,可以直接使用 `useChat(sessionId)` 和 `skillsApi` / `useSkills()`。技能选择、`@skill` mention、会话技能状态等能力仍由现有 skills API 提供;`ChatView` 的 `components.SkillStatusBar` 可替换默认技能状态条,用来接入宿主自己的 Anthropic-style skills 入口或展示方式。
67
+
30
68
  ## 认证
31
69
 
32
70
  SDK 支持 cookie 会话和 Bearer Token 两种模式。
@@ -1,10 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
- import { ReactNode } from 'react';
4
- import { M as MessageContent, C as ChatMessage, A as AskUserAnswerData } from './AskUserQuestionBlock-CjvG_pUY.js';
3
+ import { ComponentType, ReactNode } from 'react';
4
+ import { C as ChatMessage, A as AskUserAnswerData, T as ToolCallInfo, M as MessageContent } from './AskUserQuestionBlock-CjvG_pUY.js';
5
5
  import * as zustand from 'zustand';
6
6
  import { M as ModeId, S as SessionInfo, a as SessionStatus } from './session-CDeiO81j.js';
7
7
  import { m as BladeClient } from './blade-client-nOsdVlb1.js';
8
+ import { C as ContentBlock } from './projection-DIfyh6RK.js';
8
9
 
9
10
  /**
10
11
  * 把 whatif-rerun 后端组装的 prompt 文本解析成可折叠展示的结构。
@@ -68,7 +69,102 @@ declare function splitFilesBySize(files: FileList | File[], limitBytes?: number)
68
69
  rejected: OversizedFileInfo[];
69
70
  };
70
71
 
71
- interface ChatViewProps {
72
+ type UserChatMessage = ChatMessage & {
73
+ role: "user";
74
+ };
75
+ type ErrorChatMessage = ChatMessage & {
76
+ role: "error";
77
+ };
78
+ declare function isUserMessage(message: ChatMessage): message is UserChatMessage;
79
+ declare function isErrorMessage(message: ChatMessage): message is ErrorChatMessage;
80
+ interface UserMessageProps {
81
+ message: UserChatMessage;
82
+ className?: string;
83
+ }
84
+ declare function UserMessageBubble({ message, className }: UserMessageProps): react_jsx_runtime.JSX.Element;
85
+ declare function ErrorMessageBlock({ message, className, }: {
86
+ message: ErrorChatMessage;
87
+ className?: string;
88
+ }): react_jsx_runtime.JSX.Element;
89
+
90
+ type ChatViewClassNames = Partial<{
91
+ root: string;
92
+ viewerBanner: string;
93
+ messageListRoot: string;
94
+ messageListContent: string;
95
+ messageListInner: string;
96
+ emptyState: string;
97
+ userMessage: string;
98
+ errorMessage: string;
99
+ assistantTurn: string;
100
+ assistantText: string;
101
+ toolCall: string;
102
+ chatInputRoot: string;
103
+ chatInputInner: string;
104
+ skillStatusBarRoot: string;
105
+ skillStatusBarInner: string;
106
+ }>;
107
+ interface ChatViewComponents {
108
+ EmptyState?: ComponentType;
109
+ UserMessage?: ComponentType<{
110
+ message: UserChatMessage;
111
+ className?: string;
112
+ }>;
113
+ ErrorMessage?: ComponentType<{
114
+ message: ErrorChatMessage;
115
+ className?: string;
116
+ }>;
117
+ AssistantTurn?: ComponentType<AssistantTurnComponentProps>;
118
+ ToolCall?: ComponentType<ToolCallComponentProps>;
119
+ SkillStatusBar?: ComponentType<SkillStatusBarComponentProps>;
120
+ }
121
+ interface ChatViewRenderers {
122
+ tool?: Record<string, ComponentType<ToolRendererProps>>;
123
+ }
124
+ interface ChatViewCustomization {
125
+ classNames?: ChatViewClassNames;
126
+ components?: ChatViewComponents;
127
+ renderers?: ChatViewRenderers;
128
+ }
129
+ interface AssistantTurnComponentProps {
130
+ turnKey: string;
131
+ sessionId: string;
132
+ messages: ChatMessage[];
133
+ isStreaming?: boolean;
134
+ isLastTurn?: boolean;
135
+ askAnswers?: Record<string, AskUserAnswerData>;
136
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
137
+ sessionStatus?: string;
138
+ level?: 1 | 2;
139
+ forceExpanded?: boolean;
140
+ customization?: ChatViewCustomization;
141
+ }
142
+ interface ToolCallComponentProps {
143
+ toolCall: ToolCallInfo;
144
+ onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
145
+ answered?: boolean;
146
+ answerData?: AskUserAnswerData;
147
+ sessionId?: string;
148
+ sessionStatus?: string;
149
+ level?: 1 | 2;
150
+ turnBlocks?: ContentBlock[];
151
+ reasoning?: string;
152
+ customization?: ChatViewCustomization;
153
+ }
154
+ interface ToolRendererProps {
155
+ toolCall: ToolCallInfo;
156
+ sessionId?: string;
157
+ }
158
+ interface SkillStatusBarComponentProps {
159
+ sessionId: string;
160
+ onResync?: () => void;
161
+ isResyncing?: boolean;
162
+ vertical?: boolean;
163
+ className?: string;
164
+ innerClassName?: string;
165
+ }
166
+
167
+ interface ChatViewProps extends ChatViewCustomization {
72
168
  sessionId: string;
73
169
  renderAttachments?: () => ReactNode;
74
170
  onBeforeSend?: (content: MessageContent) => MessageContent;
@@ -77,7 +173,7 @@ interface ChatViewProps {
77
173
  onResyncSkills?: () => void;
78
174
  isResyncingSkills?: boolean;
79
175
  }
80
- declare function ChatView({ sessionId, renderAttachments, onBeforeSend, onCommand, canShareSession, onResyncSkills, isResyncingSkills, }: ChatViewProps): react_jsx_runtime.JSX.Element;
176
+ declare function ChatView({ sessionId, renderAttachments, onBeforeSend, onCommand, canShareSession, onResyncSkills, isResyncingSkills, classNames, components, renderers, }: ChatViewProps): react_jsx_runtime.JSX.Element;
81
177
 
82
178
  type SessionMode = ModeId;
83
179
  interface SessionState extends ClientAwareState {
@@ -160,6 +256,11 @@ interface Props$2 {
160
256
  };
161
257
  /** Tailwind class for the inner max-width wrapper. Defaults to `max-w-3xl`. */
162
258
  maxWidthClassName?: string;
259
+ className?: string;
260
+ innerClassName?: string;
261
+ SkillStatusBarComponent?: ComponentType<SkillStatusBarComponentProps>;
262
+ skillStatusBarClassName?: string;
263
+ skillStatusBarInnerClassName?: string;
163
264
  onResyncSkills?: () => void;
164
265
  isResyncingSkills?: boolean;
165
266
  }
@@ -174,7 +275,7 @@ type FileComposerAttachment = {
174
275
  uploadedPath?: string;
175
276
  textContent?: string | null;
176
277
  };
177
- declare function ChatInput({ onSend, onStop, isStreaming, mode, onToggleMode, renderAttachments, onBeforeSend, ensureSession, onCommand, canShareSession, slotAboveTextarea, externalDraft, externalAttachments, maxWidthClassName, onResyncSkills, isResyncingSkills, }: Props$2): react_jsx_runtime.JSX.Element;
278
+ declare function ChatInput({ onSend, onStop, isStreaming, mode, onToggleMode, renderAttachments, onBeforeSend, ensureSession, onCommand, canShareSession, slotAboveTextarea, externalDraft, externalAttachments, maxWidthClassName, className, innerClassName, SkillStatusBarComponent, skillStatusBarClassName, skillStatusBarInnerClassName, onResyncSkills, isResyncingSkills, }: Props$2): react_jsx_runtime.JSX.Element;
178
279
 
179
280
  interface Props$1 {
180
281
  open: boolean;
@@ -190,14 +291,17 @@ interface Props {
190
291
  onAnswer?: (answer: string, toolCallId: string, answerData: AskUserAnswerData) => void;
191
292
  sessionStatus?: string;
192
293
  onConfirmPlan?: (action: "execute" | "revise", text?: string) => void;
294
+ customization?: ChatViewCustomization;
193
295
  }
194
- declare function MessageList({ sessionId, messages: rawMessages, onAnswer, sessionStatus, onConfirmPlan, }: Props): react_jsx_runtime.JSX.Element;
296
+ declare function MessageList({ sessionId, messages: rawMessages, onAnswer, sessionStatus, onConfirmPlan, customization, }: Props): react_jsx_runtime.JSX.Element;
195
297
 
196
- declare function SkillStatusBar({ sessionId, onResync, isResyncing, vertical, }: {
298
+ declare function SkillStatusBar({ sessionId, onResync, isResyncing, vertical, className, innerClassName, }: {
197
299
  sessionId: string;
198
300
  onResync?: () => void;
199
301
  isResyncing?: boolean;
200
302
  vertical?: boolean;
303
+ className?: string;
304
+ innerClassName?: string;
201
305
  }): react_jsx_runtime.JSX.Element;
202
306
 
203
- export { ATTACHMENT_SIZE_LIMIT_BYTES as A, type BuildWhatIfPromptInput as B, ChatInput as C, type FileComposerAttachment as F, MessageList as M, type OversizedFileInfo as O, type ParsedWhatIfPrompt as P, SkillStatusBar as S, type WhatIfQuote as W, ChatView as a, FileSizeLimitDialog as b, type ClientAwareState as c, buildWhatIfPrompt as d, formatFileSize as f, invalidateHomeSidebarSessions as i, parseWhatIfPrompt as p, splitFilesBySize as s, useSessionStore as u };
307
+ export { type AssistantTurnComponentProps as A, type BuildWhatIfPromptInput as B, type ChatViewCustomization as C, ErrorMessageBlock as E, type FileComposerAttachment as F, MessageList as M, type OversizedFileInfo as O, type ParsedWhatIfPrompt as P, SkillStatusBar as S, type ToolCallComponentProps as T, UserMessageBubble as U, type WhatIfQuote as W, ChatInput as a, ChatView as b, type ChatViewClassNames as c, type ChatViewComponents as d, type ChatViewProps as e, type ChatViewRenderers as f, FileSizeLimitDialog as g, type SkillStatusBarComponentProps as h, type ToolRendererProps as i, isErrorMessage as j, isUserMessage as k, type ClientAwareState as l, ATTACHMENT_SIZE_LIMIT_BYTES as m, buildWhatIfPrompt as n, formatFileSize as o, invalidateHomeSidebarSessions as p, parseWhatIfPrompt as q, splitFilesBySize as s, useSessionStore as u };
@@ -0,0 +1,66 @@
1
+ // src/react/lib/card-registry.ts
2
+ var CardComponentRegistry = class {
3
+ components;
4
+ constructor(initial) {
5
+ if (initial instanceof Map) {
6
+ this.components = new Map(initial);
7
+ } else if (initial) {
8
+ this.components = new Map(Object.entries(initial));
9
+ } else {
10
+ this.components = /* @__PURE__ */ new Map();
11
+ }
12
+ }
13
+ register(type, component) {
14
+ this.components.set(type, component);
15
+ }
16
+ get(type) {
17
+ return this.components.get(type);
18
+ }
19
+ has(type) {
20
+ return this.components.has(type);
21
+ }
22
+ keys() {
23
+ return Array.from(this.components.keys());
24
+ }
25
+ clear() {
26
+ this.components.clear();
27
+ }
28
+ get size() {
29
+ return this.components.size;
30
+ }
31
+ };
32
+ var cardRegistry = new CardComponentRegistry();
33
+ var CardJSON = {
34
+ safeParseJSON(text) {
35
+ try {
36
+ const value = JSON.parse(text);
37
+ return { ok: true, value };
38
+ } catch (error) {
39
+ return {
40
+ ok: false,
41
+ error: error instanceof Error ? error.message : "Unknown parsing error"
42
+ };
43
+ }
44
+ },
45
+ toCardArray(value) {
46
+ if (value && typeof value === "object" && "type" in value && typeof value.type === "string") {
47
+ return [value];
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const cards = value.filter(
51
+ (item) => item && typeof item === "object" && "type" in item && typeof item.type === "string"
52
+ );
53
+ return cards.length > 0 ? cards : null;
54
+ }
55
+ return null;
56
+ },
57
+ isCardsLanguage(lang) {
58
+ return lang === "card+json";
59
+ }
60
+ };
61
+
62
+ export {
63
+ cardRegistry,
64
+ CardJSON
65
+ };
66
+ //# sourceMappingURL=chunk-2UP7MG3J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/lib/card-registry.ts"],"sourcesContent":["import type { ComponentType } from \"react\"\n\nexport interface Card {\n type: string\n title?: string\n payload?: Record<string, unknown>\n data?: unknown\n id?: string\n}\n\nexport interface CardComponentProps {\n card: Card\n sendMessage?: (content: string) => Promise<void>\n sessionId?: string\n}\n\nexport type CardComponent = ComponentType<CardComponentProps>\n\nexport class CardComponentRegistry {\n private readonly components: Map<string, CardComponent>\n\n constructor(initial?: Record<string, CardComponent> | Map<string, CardComponent>) {\n if (initial instanceof Map) {\n this.components = new Map(initial)\n } else if (initial) {\n this.components = new Map(Object.entries(initial))\n } else {\n this.components = new Map()\n }\n }\n\n register(type: string, component: CardComponent): void {\n this.components.set(type, component)\n }\n\n get(type: string): CardComponent | undefined {\n return this.components.get(type)\n }\n\n has(type: string): boolean {\n return this.components.has(type)\n }\n\n keys(): string[] {\n return Array.from(this.components.keys())\n }\n\n clear(): void {\n this.components.clear()\n }\n\n get size(): number {\n return this.components.size\n }\n}\n\nexport const cardRegistry = new CardComponentRegistry()\n\nexport interface ParseResult<T> {\n ok: boolean\n value?: T\n error?: string\n}\n\nexport const CardJSON = {\n safeParseJSON<T = unknown>(text: string): ParseResult<T> {\n try {\n const value = JSON.parse(text) as T\n return { ok: true, value }\n } catch (error) {\n return {\n ok: false,\n error: error instanceof Error ? error.message : \"Unknown parsing error\",\n }\n }\n },\n\n toCardArray(value: unknown): Card[] | null {\n if (\n value &&\n typeof value === \"object\" &&\n \"type\" in (value as Record<string, unknown>) &&\n typeof (value as { type?: unknown }).type === \"string\"\n ) {\n return [value as Card]\n }\n\n if (Array.isArray(value)) {\n const cards = value.filter(\n (item): item is Card =>\n item &&\n typeof item === \"object\" &&\n \"type\" in (item as Record<string, unknown>) &&\n typeof (item as { type?: unknown }).type === \"string\",\n )\n return cards.length > 0 ? cards : null\n }\n\n return null\n },\n\n isCardsLanguage(lang?: string): boolean {\n return lang === \"card+json\"\n },\n}\n"],"mappings":";AAkBO,IAAM,wBAAN,MAA4B;AAAA,EAChB;AAAA,EAEjB,YAAY,SAAsE;AAChF,QAAI,mBAAmB,KAAK;AAC1B,WAAK,aAAa,IAAI,IAAI,OAAO;AAAA,IACnC,WAAW,SAAS;AAClB,WAAK,aAAa,IAAI,IAAI,OAAO,QAAQ,OAAO,CAAC;AAAA,IACnD,OAAO;AACL,WAAK,aAAa,oBAAI,IAAI;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,SAAS,MAAc,WAAgC;AACrD,SAAK,WAAW,IAAI,MAAM,SAAS;AAAA,EACrC;AAAA,EAEA,IAAI,MAAyC;AAC3C,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,IAAI,MAAuB;AACzB,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,OAAiB;AACf,WAAO,MAAM,KAAK,KAAK,WAAW,KAAK,CAAC;AAAA,EAC1C;AAAA,EAEA,QAAc;AACZ,SAAK,WAAW,MAAM;AAAA,EACxB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,WAAW;AAAA,EACzB;AACF;AAEO,IAAM,eAAe,IAAI,sBAAsB;AAQ/C,IAAM,WAAW;AAAA,EACtB,cAA2B,MAA8B;AACvD,QAAI;AACF,YAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,aAAO,EAAE,IAAI,MAAM,MAAM;AAAA,IAC3B,SAAS,OAAO;AACd,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,OAA+B;AACzC,QACE,SACA,OAAO,UAAU,YACjB,UAAW,SACX,OAAQ,MAA6B,SAAS,UAC9C;AACA,aAAO,CAAC,KAAa;AAAA,IACvB;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAM,QAAQ,MAAM;AAAA,QAClB,CAAC,SACC,QACA,OAAO,SAAS,YAChB,UAAW,QACX,OAAQ,KAA4B,SAAS;AAAA,MACjD;AACA,aAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,IACpC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,MAAwB;AACtC,WAAO,SAAS;AAAA,EAClB;AACF;","names":[]}