@webskill/chatbot 0.5.0 → 0.6.0
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/chatbot.css +82 -4
- package/dist/index.d.ts +15 -2
- package/dist/index.js +265 -72
- package/package.json +2 -2
package/dist/chatbot.css
CHANGED
|
@@ -291,8 +291,8 @@
|
|
|
291
291
|
.right-full {
|
|
292
292
|
right: 100%;
|
|
293
293
|
}
|
|
294
|
-
.-bottom-
|
|
295
|
-
bottom: calc(var(--spacing) * -
|
|
294
|
+
.-bottom-9 {
|
|
295
|
+
bottom: calc(var(--spacing) * -9);
|
|
296
296
|
}
|
|
297
297
|
.bottom-4 {
|
|
298
298
|
bottom: calc(var(--spacing) * 4);
|
|
@@ -402,8 +402,8 @@
|
|
|
402
402
|
.mb-2 {
|
|
403
403
|
margin-bottom: calc(var(--spacing) * 2);
|
|
404
404
|
}
|
|
405
|
-
.mb-
|
|
406
|
-
margin-bottom: calc(var(--spacing) *
|
|
405
|
+
.mb-9 {
|
|
406
|
+
margin-bottom: calc(var(--spacing) * 9);
|
|
407
407
|
}
|
|
408
408
|
.block {
|
|
409
409
|
display: block;
|
|
@@ -530,6 +530,9 @@
|
|
|
530
530
|
.min-h-0 {
|
|
531
531
|
min-height: 0px;
|
|
532
532
|
}
|
|
533
|
+
.min-h-8 {
|
|
534
|
+
min-height: calc(var(--spacing) * 8);
|
|
535
|
+
}
|
|
533
536
|
.min-h-16 {
|
|
534
537
|
min-height: calc(var(--spacing) * 16);
|
|
535
538
|
}
|
|
@@ -572,6 +575,9 @@
|
|
|
572
575
|
.w-72 {
|
|
573
576
|
width: calc(var(--spacing) * 72);
|
|
574
577
|
}
|
|
578
|
+
.w-\[80\%\] {
|
|
579
|
+
width: 80%;
|
|
580
|
+
}
|
|
575
581
|
.w-\[min\(36rem\,calc\(100vw-2rem\)\)\] {
|
|
576
582
|
width: min(36rem, calc(100vw - 2rem));
|
|
577
583
|
}
|
|
@@ -715,6 +721,9 @@
|
|
|
715
721
|
.grid-cols-1 {
|
|
716
722
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
717
723
|
}
|
|
724
|
+
.grid-cols-\[auto_auto_auto\] {
|
|
725
|
+
grid-template-columns: auto auto auto;
|
|
726
|
+
}
|
|
718
727
|
.flex-col {
|
|
719
728
|
flex-direction: column;
|
|
720
729
|
}
|
|
@@ -730,6 +739,9 @@
|
|
|
730
739
|
.items-center {
|
|
731
740
|
align-items: center;
|
|
732
741
|
}
|
|
742
|
+
.items-end {
|
|
743
|
+
align-items: flex-end;
|
|
744
|
+
}
|
|
733
745
|
.items-start {
|
|
734
746
|
align-items: flex-start;
|
|
735
747
|
}
|
|
@@ -1229,6 +1241,9 @@
|
|
|
1229
1241
|
.whitespace-nowrap {
|
|
1230
1242
|
white-space: nowrap;
|
|
1231
1243
|
}
|
|
1244
|
+
.whitespace-pre {
|
|
1245
|
+
white-space: pre;
|
|
1246
|
+
}
|
|
1232
1247
|
.whitespace-pre-wrap {
|
|
1233
1248
|
white-space: pre-wrap;
|
|
1234
1249
|
}
|
|
@@ -1286,6 +1301,9 @@
|
|
|
1286
1301
|
.uppercase {
|
|
1287
1302
|
text-transform: uppercase;
|
|
1288
1303
|
}
|
|
1304
|
+
.italic {
|
|
1305
|
+
font-style: italic;
|
|
1306
|
+
}
|
|
1289
1307
|
.tabular-nums {
|
|
1290
1308
|
--tw-numeric-spacing: tabular-nums;
|
|
1291
1309
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
@@ -2039,6 +2057,36 @@
|
|
|
2039
2057
|
--brand-foreground: oklch(0.985 0 0);
|
|
2040
2058
|
--text-min: 0.75rem;
|
|
2041
2059
|
--text-code: 0.8125rem;
|
|
2060
|
+
--code-base: hsl(230, 8%, 24%);
|
|
2061
|
+
--code-comment: hsl(230, 4%, 64%);
|
|
2062
|
+
--code-prolog: hsl(230, 4%, 64%);
|
|
2063
|
+
--code-cdata: hsl(230, 4%, 64%);
|
|
2064
|
+
--code-doctype: hsl(230, 8%, 24%);
|
|
2065
|
+
--code-punctuation: hsl(230, 8%, 24%);
|
|
2066
|
+
--code-entity: hsl(230, 8%, 24%);
|
|
2067
|
+
--code-attr-name: hsl(35, 99%, 36%);
|
|
2068
|
+
--code-class-name: hsl(35, 99%, 36%);
|
|
2069
|
+
--code-boolean: hsl(35, 99%, 36%);
|
|
2070
|
+
--code-constant: hsl(35, 99%, 36%);
|
|
2071
|
+
--code-number: hsl(35, 99%, 36%);
|
|
2072
|
+
--code-atrule: hsl(35, 99%, 36%);
|
|
2073
|
+
--code-keyword: hsl(301, 63%, 40%);
|
|
2074
|
+
--code-property: hsl(5, 74%, 59%);
|
|
2075
|
+
--code-tag: hsl(5, 74%, 59%);
|
|
2076
|
+
--code-symbol: hsl(5, 74%, 59%);
|
|
2077
|
+
--code-deleted: hsl(5, 74%, 59%);
|
|
2078
|
+
--code-important: hsl(5, 74%, 59%);
|
|
2079
|
+
--code-selector: hsl(119, 34%, 47%);
|
|
2080
|
+
--code-string: hsl(119, 34%, 47%);
|
|
2081
|
+
--code-char: hsl(119, 34%, 47%);
|
|
2082
|
+
--code-builtin: hsl(119, 34%, 47%);
|
|
2083
|
+
--code-inserted: hsl(119, 34%, 47%);
|
|
2084
|
+
--code-regex: hsl(119, 34%, 47%);
|
|
2085
|
+
--code-attr-value: hsl(119, 34%, 47%);
|
|
2086
|
+
--code-variable: hsl(221, 87%, 60%);
|
|
2087
|
+
--code-operator: hsl(221, 87%, 60%);
|
|
2088
|
+
--code-function: hsl(221, 87%, 60%);
|
|
2089
|
+
--code-url: hsl(198, 99%, 37%);
|
|
2042
2090
|
}
|
|
2043
2091
|
:where(.dark, [data-theme='dark']) {
|
|
2044
2092
|
--background: oklch(0.145 0 0);
|
|
@@ -2092,6 +2140,36 @@
|
|
|
2092
2140
|
--sidebar-ring: oklch(0.556 0 0);
|
|
2093
2141
|
--brand: oklch(0.68 0.14 275);
|
|
2094
2142
|
--brand-foreground: oklch(0.205 0 0);
|
|
2143
|
+
--code-base: hsl(220, 14%, 71%);
|
|
2144
|
+
--code-comment: hsl(220, 10%, 40%);
|
|
2145
|
+
--code-prolog: hsl(220, 10%, 40%);
|
|
2146
|
+
--code-cdata: hsl(220, 10%, 40%);
|
|
2147
|
+
--code-doctype: hsl(220, 14%, 71%);
|
|
2148
|
+
--code-punctuation: hsl(220, 14%, 71%);
|
|
2149
|
+
--code-entity: hsl(220, 14%, 71%);
|
|
2150
|
+
--code-attr-name: hsl(29, 54%, 61%);
|
|
2151
|
+
--code-class-name: hsl(29, 54%, 61%);
|
|
2152
|
+
--code-boolean: hsl(29, 54%, 61%);
|
|
2153
|
+
--code-constant: hsl(29, 54%, 61%);
|
|
2154
|
+
--code-number: hsl(29, 54%, 61%);
|
|
2155
|
+
--code-atrule: hsl(29, 54%, 61%);
|
|
2156
|
+
--code-keyword: hsl(286, 60%, 67%);
|
|
2157
|
+
--code-property: hsl(355, 65%, 65%);
|
|
2158
|
+
--code-tag: hsl(355, 65%, 65%);
|
|
2159
|
+
--code-symbol: hsl(355, 65%, 65%);
|
|
2160
|
+
--code-deleted: hsl(355, 65%, 65%);
|
|
2161
|
+
--code-important: hsl(355, 65%, 65%);
|
|
2162
|
+
--code-selector: hsl(95, 38%, 62%);
|
|
2163
|
+
--code-string: hsl(95, 38%, 62%);
|
|
2164
|
+
--code-char: hsl(95, 38%, 62%);
|
|
2165
|
+
--code-builtin: hsl(95, 38%, 62%);
|
|
2166
|
+
--code-inserted: hsl(95, 38%, 62%);
|
|
2167
|
+
--code-regex: hsl(95, 38%, 62%);
|
|
2168
|
+
--code-attr-value: hsl(95, 38%, 62%);
|
|
2169
|
+
--code-variable: hsl(207, 82%, 66%);
|
|
2170
|
+
--code-operator: hsl(207, 82%, 66%);
|
|
2171
|
+
--code-function: hsl(207, 82%, 66%);
|
|
2172
|
+
--code-url: hsl(187, 47%, 55%);
|
|
2095
2173
|
}
|
|
2096
2174
|
@layer base {
|
|
2097
2175
|
*, ::before, ::after {
|
package/dist/index.d.ts
CHANGED
|
@@ -1059,6 +1059,7 @@ declare const chatbotDictionary: {
|
|
|
1059
1059
|
'result.artifacts': string;
|
|
1060
1060
|
'result.download': string;
|
|
1061
1061
|
'result.file': string;
|
|
1062
|
+
'result.block.unknown': string;
|
|
1062
1063
|
'status.aria': string;
|
|
1063
1064
|
'status.route': string;
|
|
1064
1065
|
'status.activate': string;
|
|
@@ -1379,6 +1380,7 @@ declare const chatbotDictionary: {
|
|
|
1379
1380
|
'result.artifacts': string;
|
|
1380
1381
|
'result.download': string;
|
|
1381
1382
|
'result.file': string;
|
|
1383
|
+
'result.block.unknown': string;
|
|
1382
1384
|
'status.aria': string;
|
|
1383
1385
|
'status.route': string;
|
|
1384
1386
|
'status.activate': string;
|
|
@@ -1702,6 +1704,7 @@ declare const useT: () => TranslateFn<{
|
|
|
1702
1704
|
'result.artifacts': string;
|
|
1703
1705
|
'result.download': string;
|
|
1704
1706
|
'result.file': string;
|
|
1707
|
+
'result.block.unknown': string;
|
|
1705
1708
|
'status.aria': string;
|
|
1706
1709
|
'status.route': string;
|
|
1707
1710
|
'status.activate': string;
|
|
@@ -2022,6 +2025,7 @@ declare const useT: () => TranslateFn<{
|
|
|
2022
2025
|
'result.artifacts': string;
|
|
2023
2026
|
'result.download': string;
|
|
2024
2027
|
'result.file': string;
|
|
2028
|
+
'result.block.unknown': string;
|
|
2025
2029
|
'status.aria': string;
|
|
2026
2030
|
'status.route': string;
|
|
2027
2031
|
'status.activate': string;
|
|
@@ -2256,8 +2260,9 @@ interface ChatbotProps {
|
|
|
2256
2260
|
/**
|
|
2257
2261
|
* 打开配置面(FR-20.4)。配置面本身已迁到 console,chatbot 只负责发出这个请求;
|
|
2258
2262
|
* 宿主不接就不渲染任何「打开设置」出口——给一个点了没反应的按钮更糟。
|
|
2263
|
+
* `section` 可选(FR-16.5):齿轮不带分区(→ Overview),带诉求的入口(错误卡等)才传分区。
|
|
2259
2264
|
*/
|
|
2260
|
-
onOpenSettings?(section
|
|
2265
|
+
onOpenSettings?(section?: SettingsSectionId): void;
|
|
2261
2266
|
/**
|
|
2262
2267
|
* 装配完成后把引擎交给宿主,用于接线跨界面动作(例如 console 的快照恢复入口
|
|
2263
2268
|
* 需要调 `engine.resume(runId)`)。每次重新装配都会再调一次。
|
|
@@ -2447,4 +2452,12 @@ interface ErrorCardProps {
|
|
|
2447
2452
|
/** 结构化错误卡:错误码徽章 + 描述 + 建议(engine error 事件 / 失败 run) @stable */
|
|
2448
2453
|
declare function ErrorCard({ code, message, loopLimits, onOpenSettings, onDismiss }: ErrorCardProps): import("react").JSX.Element;
|
|
2449
2454
|
//#endregion
|
|
2450
|
-
|
|
2455
|
+
//#region src/version.d.ts
|
|
2456
|
+
/** Generated by scripts/syncVersionConstant.mjs from packages/chatbot/package.json. Do not edit by hand. */
|
|
2457
|
+
/**
|
|
2458
|
+
* Version of the published `@webskill/chatbot` package, injected at build time.
|
|
2459
|
+
* @stable
|
|
2460
|
+
*/
|
|
2461
|
+
declare const CHATBOT_VERSION = "0.6.0";
|
|
2462
|
+
//#endregion
|
|
2463
|
+
export { A2uiSurfaceHost, type A2uiSurfaceHostProps, A2uiSurfaceSnapshotHost, type A2uiSurfaceSnapshotHostProps, type AppearanceChange, CHATBOT_VERSION, type ChatAttachmentInput, type ChatAttachmentMeta, ChatEngine, type ChatEngineOptions, type ChatEvent, type ChatInteractionRecord, type ChatLayout, type ChatMessage, type ChatRunPhase, type ChatSessionListResult, type ChatSessionMeta, type ChatTheme, type ChatToolCall, Chatbot, type ChatbotConfig, type ChatbotGovernancePorts, type ChatbotHostAdapter, type ChatbotProps, CompositeUiBridge, type CompositeUiBridgeDeps, DEFAULT_RENDERER_CAPABILITIES, DEFAULT_RUNTIME_CONFIG_STORAGE_KEY, type DownloadableFile, ErrorCard, type ErrorCardProps, InteractionCard, type InteractionCardProps, InterruptedBanner, type InterruptedBannerProps, type Locale, OpenUiSurfaceHost, type OpenUiSurfaceHostProps, OpenUiSurfaceSnapshotHost, type OpenUiSurfaceSnapshotHostProps, type RendererCapability, type RendererKind, type ResolvedChatLayout, ResultBlockList, type ResultBlockListProps, ResultBlocksPro, type ResultBlocksProProps, type RunSnapshot, type RuntimeAppearanceConfig, type RuntimeConfig, type RuntimeConfigStore, type RuntimeRendererId, type SandboxExecutorDeps, type SettingsSectionId, SkillBadges, SpecInteraction, type SpecInteractionProps, VercelPayloadPreview, type VercelPayloadPreviewProps, VercelSurfaceHost, type VercelSurfaceHostProps, VercelSurfaceSnapshotHost, type VercelSurfaceSnapshotHostProps, chatbotDictionary, configureA2uiMarkdown, createLocalStorageRuntimeConfigStore, createMemoryRuntimeConfigStore, probeA2uiAvailability, probeOpenUiAvailability, sandboxExecutorDeps, useT };
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { t as yaml } from "./yaml-C888tCbJ.js";
|
|
|
6
6
|
import { t as json } from "./json-BOcU6nei.js";
|
|
7
7
|
import { t as typescript } from "./typescript-DAau_Qyl.js";
|
|
8
8
|
import { t as jsx$1 } from "./jsx-D2Jv0wvt.js";
|
|
9
|
-
import { BEHAVIOR_RECORDS_KEY, DEFAULT_LOOP_LIMITS, DEFAULT_USER_PROFILE_LIMITS, EventBus, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FsRunTraceStore, FsSessionStore, FullDisclosureRouter, SerializingMemoryStore, SkillDiscovery, USER_PROFILE_KEY, WebSkillError, WebSkillRuntime, applyUserProfileImport, assertRemoteUrlAllowed, diffUserProfile, exportUserProfile, isUnsupportedRunSnapshot, messageOf, readBehaviorRecords, readUserProfile, refineUserProfile, summarizeToolCalls, textParts } from "@webskill/sdk";
|
|
9
|
+
import { BEHAVIOR_RECORDS_KEY, DEFAULT_LOOP_LIMITS, DEFAULT_USER_PROFILE_LIMITS, EventBus, FsArtifactStore, FsMemoryStore, FsRunSnapshotStore, FsRunTraceStore, FsSessionStore, FullDisclosureRouter, SerializingMemoryStore, SkillDiscovery, USER_PROFILE_KEY, WebSkillError, WebSkillRuntime, applyUserProfileImport, assertRemoteUrlAllowed, atomicWriteText, diffUserProfile, exportUserProfile, isUnsupportedRunSnapshot, messageOf, readBehaviorRecords, readUserProfile, refineUserProfile, summarizeToolCalls, textParts } from "@webskill/sdk";
|
|
10
10
|
import { BrowserWorkerScriptExecutor, checkDictationAvailability, compressImageToBudget, createEncryptedMemoryStore, createLlmClient, deleteMemoryEncryptionKey, openMemoryEncryptionKey, probeChromeBuiltinAvailability, startDictation } from "@webskill/sdk/browser";
|
|
11
11
|
import { JsonRenderSpecSurface, NativeSpecSurface, OpenUiSpecSurface, ReactBridgeState, SpecInteractionChannel, SurfaceFormTextsProvider, UiSurfaceList, UiSurfaceSnapshotList, probeJsonRenderAvailability } from "@webskill/sdk/ui-react";
|
|
12
12
|
import { A2UI_SPEC_FORM_PATH, collectFormScopes, createUiCatalogToolSource, fromA2uiSpecAction, fromA2uiSurfaceAction, interactionToFormModel, interactionToUiSpec, loadOpenUiPeers, loadWebSkillLitCatalog, renderMiniChart, shapeInteractionValue, toA2uiSpecMessages, toA2uiSurfaceAction, toVercelToolInvocation, uiCatalog } from "@webskill/sdk/ui";
|
|
@@ -21,6 +21,7 @@ import { DataRenderers, Tools } from "@assistant-ui/core/react";
|
|
|
21
21
|
import { ModelContext, Suggestions } from "@assistant-ui/core/store";
|
|
22
22
|
import { Derived, attachTransformScopes, useClientLookup, useClientResource } from "@assistant-ui/store";
|
|
23
23
|
import { resource, useMemoCache, withKey } from "@assistant-ui/tap";
|
|
24
|
+
import { POLICY_DENIAL_CODES } from "@webskill/sdk/governance";
|
|
24
25
|
|
|
25
26
|
//#region ../ui-kit/src/i18n/createI18n.ts
|
|
26
27
|
/** 字典工厂:各包定义自己的双语字典(恒等返回,保留字面量类型) */
|
|
@@ -1160,7 +1161,7 @@ const variantClasses$1 = {
|
|
|
1160
1161
|
danger: "bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm disabled:opacity-60"
|
|
1161
1162
|
};
|
|
1162
1163
|
const sizeClasses$2 = {
|
|
1163
|
-
sm: "h-
|
|
1164
|
+
sm: "h-8 px-2.5 text-xs gap-1.5 rounded-md",
|
|
1164
1165
|
md: "h-9 px-3.5 text-sm gap-2 rounded-lg"
|
|
1165
1166
|
};
|
|
1166
1167
|
function Button({ variant = "primary", size = "md", loading = false, icon, disabled, className = "", children, type = "button", ...rest }) {
|
|
@@ -1184,7 +1185,7 @@ const variantClasses = {
|
|
|
1184
1185
|
danger: "text-destructive hover:bg-destructive-soft"
|
|
1185
1186
|
};
|
|
1186
1187
|
const sizeClasses$1 = {
|
|
1187
|
-
sm: "size-
|
|
1188
|
+
sm: "size-8",
|
|
1188
1189
|
md: "size-9"
|
|
1189
1190
|
};
|
|
1190
1191
|
/**
|
|
@@ -37803,11 +37804,40 @@ var one_light_default = {
|
|
|
37803
37804
|
|
|
37804
37805
|
//#endregion
|
|
37805
37806
|
//#region ../ui-kit/src/markdown/prismTheme.ts
|
|
37806
|
-
/**
|
|
37807
|
+
/** react-syntax-highlighter 顶层 token 键(comment/punctuation/attr-name…);其余是容器选择器键 */
|
|
37808
|
+
const TOKEN_KEY = /^[a-z][a-z-]*$/;
|
|
37809
|
+
/**
|
|
37810
|
+
* 把主题对象的每个 color 替换为 CSS 变量引用:
|
|
37811
|
+
* - token 键(punctuation/string/attr-name…)→ `var(--code-<token>)`
|
|
37812
|
+
* - 容器选择器键(code[]/pre[]/selection…)→ `var(--code-base)`
|
|
37813
|
+
*
|
|
37814
|
+
* token 内联的是 var 引用而非固定色值;主题切换时 CSS 变量在元素上动态重求值,
|
|
37815
|
+
* **已渲染的旧代码块无需重挂载即可跟随**(0.9.0 分册 13,UX-01 根因修复)。
|
|
37816
|
+
* 色值本体由 theme.css 的 `--code-*`(浅/深两套)持有——单一来源。
|
|
37817
|
+
*/
|
|
37818
|
+
function toVarTheme(theme) {
|
|
37819
|
+
const out = {};
|
|
37820
|
+
for (const [key, rule] of Object.entries(theme)) {
|
|
37821
|
+
const next = { ...rule };
|
|
37822
|
+
if (typeof next.color === "string") next.color = `var(${TOKEN_KEY.test(key) ? `--code-${key}` : "--code-base"})`;
|
|
37823
|
+
out[key] = next;
|
|
37824
|
+
}
|
|
37825
|
+
return out;
|
|
37826
|
+
}
|
|
37827
|
+
/**
|
|
37828
|
+
* 全站唯一的代码高亮主题对。引用相等是验收判据(AC-19.8),不导出到包外。
|
|
37829
|
+
* token 色值一律 `var(--code-*)`(CSS 变量,见 theme.css),不烘焙固定色值。
|
|
37830
|
+
*/
|
|
37807
37831
|
const PRISM_THEME = {
|
|
37808
|
-
dark: one_dark_default,
|
|
37809
|
-
light: one_light_default
|
|
37832
|
+
dark: toVarTheme(one_dark_default),
|
|
37833
|
+
light: toVarTheme(one_light_default)
|
|
37810
37834
|
};
|
|
37835
|
+
/**
|
|
37836
|
+
* token → CSS 变量名(chat 侧用);与 theme.css 的 `--code-*` 一一对应。
|
|
37837
|
+
* 单一来源:Monaco 主题与 Prism 都从这里取变量名,不许手写(AC-G10)。
|
|
37838
|
+
* @stable
|
|
37839
|
+
*/
|
|
37840
|
+
const CODE_TOKEN_VARS = Object.fromEntries(Object.keys(PRISM_THEME.light).filter((key) => TOKEN_KEY.test(key)).map((key) => [key, `--code-${key}`]));
|
|
37811
37841
|
|
|
37812
37842
|
//#endregion
|
|
37813
37843
|
//#region ../ui-kit/src/markdown/Markdown.tsx
|
|
@@ -37816,7 +37846,7 @@ function CodeBlock({ node: _node, className, children, ...rest }) {
|
|
|
37816
37846
|
const language = resolveLanguage(/language-(\w+)/.exec(className ?? "")?.[1]);
|
|
37817
37847
|
if (language) return /* @__PURE__ */ jsxs("div", {
|
|
37818
37848
|
ref: themeRef,
|
|
37819
|
-
className: "my-3 overflow-hidden rounded-card border border-border",
|
|
37849
|
+
className: "my-3 overflow-hidden rounded-card border border-border bg-card",
|
|
37820
37850
|
children: [/* @__PURE__ */ jsx("div", {
|
|
37821
37851
|
className: "border-b border-border bg-subtle px-3 py-1.5 font-mono text-xs text-muted",
|
|
37822
37852
|
children: language
|
|
@@ -43548,16 +43578,25 @@ const STATUS_TONE_VAR = {
|
|
|
43548
43578
|
* 外观配置的读写口(0.6.0 FR-20.1)。chatbot 与 console 共用它,因此两端看到的是
|
|
43549
43579
|
* 同一份数据:谁写都经 `store.save`,再由 `store.subscribe` 广播回另一端。
|
|
43550
43580
|
*
|
|
43581
|
+
* 0.9.0 分册 28 起是显式保存语义:`update` 只改内存 draft(视觉即时),
|
|
43582
|
+
* `save` 才写盘;`updateImmediate` 是快捷切换(非设置表单)的即时持久化出口。
|
|
43583
|
+
*
|
|
43551
43584
|
* 无 `store` 时退回 0.5.x 的 props 受控行为,宿主不必立刻迁移。
|
|
43552
43585
|
* @experimental
|
|
43553
43586
|
*/
|
|
43554
43587
|
function useRuntimeAppearance(store, fallback) {
|
|
43555
43588
|
const [appearance, setAppearance] = useState(fallback);
|
|
43589
|
+
const savedRef = useRef(fallback);
|
|
43590
|
+
const [dirty, setDirty] = useState(false);
|
|
43556
43591
|
const fallbackRef = useRef(fallback);
|
|
43557
43592
|
fallbackRef.current = fallback;
|
|
43593
|
+
const latestRef = useRef(appearance);
|
|
43594
|
+
latestRef.current = appearance;
|
|
43558
43595
|
useEffect(() => {
|
|
43559
43596
|
if (store) return;
|
|
43560
43597
|
setAppearance(fallbackRef.current);
|
|
43598
|
+
savedRef.current = fallbackRef.current;
|
|
43599
|
+
setDirty(false);
|
|
43561
43600
|
}, [
|
|
43562
43601
|
store,
|
|
43563
43602
|
fallback.theme,
|
|
@@ -43571,7 +43610,10 @@ function useRuntimeAppearance(store, fallback) {
|
|
|
43571
43610
|
let cancelled = false;
|
|
43572
43611
|
const reload = () => {
|
|
43573
43612
|
merged.load().then((config) => {
|
|
43574
|
-
if (
|
|
43613
|
+
if (cancelled) return;
|
|
43614
|
+
setAppearance(config.appearance);
|
|
43615
|
+
savedRef.current = config.appearance;
|
|
43616
|
+
setDirty(false);
|
|
43575
43617
|
}).catch(() => void 0);
|
|
43576
43618
|
};
|
|
43577
43619
|
reload();
|
|
@@ -43581,6 +43623,23 @@ function useRuntimeAppearance(store, fallback) {
|
|
|
43581
43623
|
unsubscribe?.();
|
|
43582
43624
|
};
|
|
43583
43625
|
}, [store]);
|
|
43626
|
+
/** 写盘;成功后才把该版本记为「已保存」,失败不破坏本地视觉(保存条保留,可重试) */
|
|
43627
|
+
const persist = useCallback(async (next) => {
|
|
43628
|
+
if (!store) return;
|
|
43629
|
+
const merged = withRuntimeConfigDefaults(store);
|
|
43630
|
+
try {
|
|
43631
|
+
const config = await merged.load();
|
|
43632
|
+
await merged.save({
|
|
43633
|
+
...config,
|
|
43634
|
+
appearance: {
|
|
43635
|
+
...config.appearance,
|
|
43636
|
+
...next
|
|
43637
|
+
}
|
|
43638
|
+
});
|
|
43639
|
+
savedRef.current = next;
|
|
43640
|
+
setDirty(false);
|
|
43641
|
+
} catch {}
|
|
43642
|
+
}, [store]);
|
|
43584
43643
|
return {
|
|
43585
43644
|
appearance,
|
|
43586
43645
|
update: useCallback((patch) => {
|
|
@@ -43588,16 +43647,24 @@ function useRuntimeAppearance(store, fallback) {
|
|
|
43588
43647
|
...current,
|
|
43589
43648
|
...patch
|
|
43590
43649
|
}));
|
|
43591
|
-
|
|
43592
|
-
|
|
43593
|
-
|
|
43594
|
-
|
|
43595
|
-
|
|
43596
|
-
|
|
43597
|
-
|
|
43598
|
-
|
|
43599
|
-
|
|
43600
|
-
}, [
|
|
43650
|
+
setDirty(true);
|
|
43651
|
+
}, []),
|
|
43652
|
+
updateImmediate: useCallback((patch) => {
|
|
43653
|
+
const next = {
|
|
43654
|
+
...latestRef.current,
|
|
43655
|
+
...patch
|
|
43656
|
+
};
|
|
43657
|
+
setAppearance(next);
|
|
43658
|
+
persist(next);
|
|
43659
|
+
}, [persist]),
|
|
43660
|
+
save: useCallback(async () => {
|
|
43661
|
+
await persist(latestRef.current);
|
|
43662
|
+
}, [persist]),
|
|
43663
|
+
discard: useCallback(() => {
|
|
43664
|
+
setAppearance(savedRef.current);
|
|
43665
|
+
setDirty(false);
|
|
43666
|
+
}, []),
|
|
43667
|
+
dirty
|
|
43601
43668
|
};
|
|
43602
43669
|
}
|
|
43603
43670
|
|
|
@@ -43862,6 +43929,23 @@ function phaseNote(event) {
|
|
|
43862
43929
|
}
|
|
43863
43930
|
}
|
|
43864
43931
|
|
|
43932
|
+
//#endregion
|
|
43933
|
+
//#region src/core/title.ts
|
|
43934
|
+
/**
|
|
43935
|
+
* 会话标题按词边界截断(0.9.0 FR-18.1 / UX-11 / A-15):
|
|
43936
|
+
* 固定字符数处回退到最近空格,避免切出半个英文单词;
|
|
43937
|
+
* 找不到空格(如无空格长串)时按 Unicode 码点硬切。
|
|
43938
|
+
* 截断后标题里的词都是完整的——会话搜索按标题原文匹配,
|
|
43939
|
+
* 词边界截断保证开头关键词(如 `ORION-A`)不被切半、仍可命中。
|
|
43940
|
+
*/
|
|
43941
|
+
function truncateTitle(text, max = 30) {
|
|
43942
|
+
const trimmed = text.trim();
|
|
43943
|
+
if (trimmed.length <= max) return trimmed;
|
|
43944
|
+
const cut = trimmed.slice(0, max);
|
|
43945
|
+
const lastSpace = Math.max(cut.lastIndexOf(" "), cut.lastIndexOf(" "));
|
|
43946
|
+
return (lastSpace > 0 ? cut.slice(0, lastSpace) : cut).trimEnd();
|
|
43947
|
+
}
|
|
43948
|
+
|
|
43865
43949
|
//#endregion
|
|
43866
43950
|
//#region src/core/subAgent.ts
|
|
43867
43951
|
/**
|
|
@@ -44152,6 +44236,12 @@ var ChatEngine = class {
|
|
|
44152
44236
|
* 终态消息只承载水位之后的内容,否则同一段正文与表单会出现两遍。
|
|
44153
44237
|
*/
|
|
44154
44238
|
#flushed = /* @__PURE__ */ new Map();
|
|
44239
|
+
/**
|
|
44240
|
+
* runId → 该 run 的结果渲染请求(FR-12.1)。
|
|
44241
|
+
* `bridge.latestResult` 是全局单槽,多 run 并发时被后一个 run 覆盖;这里按 runId 缓存,
|
|
44242
|
+
* #finishRun 按 run 归属取 blocks,终态后清理。
|
|
44243
|
+
*/
|
|
44244
|
+
#runBlocks = /* @__PURE__ */ new Map();
|
|
44155
44245
|
/** 父 run 的预算消耗(委派时按「父级剩余」收紧子 agent 预算,FR-11.4) */
|
|
44156
44246
|
#runStartedMs = 0;
|
|
44157
44247
|
#runTurn = 0;
|
|
@@ -44168,7 +44258,10 @@ var ChatEngine = class {
|
|
|
44168
44258
|
fs: adapter.storage
|
|
44169
44259
|
});
|
|
44170
44260
|
this.#renderer = options.renderer ?? "native";
|
|
44171
|
-
this.bridge = new ReactBridgeState({
|
|
44261
|
+
this.bridge = new ReactBridgeState({
|
|
44262
|
+
onSurfaceDraftChange: (runId, surfaceId, value) => this.#persistSurfaceDraft(runId, surfaceId, value),
|
|
44263
|
+
onRenderResult: (runId, request) => this.#runBlocks.set(runId, request)
|
|
44264
|
+
});
|
|
44172
44265
|
const accumulate = this.bridge.onTextDelta.bind(this.bridge);
|
|
44173
44266
|
this.bridge.onTextDelta = (runId, delta) => {
|
|
44174
44267
|
this.#emit({
|
|
@@ -44421,7 +44514,7 @@ var ChatEngine = class {
|
|
|
44421
44514
|
if (text.trim() === "" && attachments.length === 0) return;
|
|
44422
44515
|
const admitted = await this.#admitAttachments(attachments);
|
|
44423
44516
|
const runtime = await this.#ensureReady();
|
|
44424
|
-
const sessionId = this.#currentSessionId ?? (await this.createSession({ title: text
|
|
44517
|
+
const sessionId = this.#currentSessionId ?? (await this.createSession({ title: truncateTitle(text) })).id;
|
|
44425
44518
|
const session = await this.#requireSession(sessionId);
|
|
44426
44519
|
const prompt = await this.#withAttachments(text, admitted.accepted);
|
|
44427
44520
|
const userMessage = {
|
|
@@ -44434,7 +44527,7 @@ var ChatEngine = class {
|
|
|
44434
44527
|
};
|
|
44435
44528
|
await this.#sessions.appendMessages(sessionId, [userMessage]);
|
|
44436
44529
|
if (!session.title && !session.titleLocked) {
|
|
44437
|
-
await this.#sessions.setTitle(sessionId, text
|
|
44530
|
+
await this.#sessions.setTitle(sessionId, truncateTitle(text));
|
|
44438
44531
|
this.#emit({
|
|
44439
44532
|
type: "session-updated",
|
|
44440
44533
|
session: toSessionMeta(await this.#requireSession(sessionId))
|
|
@@ -44774,13 +44867,17 @@ var ChatEngine = class {
|
|
|
44774
44867
|
};
|
|
44775
44868
|
}
|
|
44776
44869
|
/**
|
|
44777
|
-
*
|
|
44778
|
-
*
|
|
44870
|
+
* 浏览器内置模型自动进模型列表(FR-14.1,B4-01/FR-27.2 调整)。
|
|
44871
|
+
* **只要浏览器支持 Prompt API**(含「模型未就绪」model-not-ready)就加入条目;
|
|
44872
|
+
* API 完全不存在(api-missing / unsupported-browser)才不加——不可用只在列表里
|
|
44873
|
+
* 呈现状态(Unavailable + 原因),不再以「探测成功」为加入门控(否则未就绪时
|
|
44874
|
+
* 条目不出现,用户无从知道为什么没有它)。
|
|
44779
44875
|
*/
|
|
44780
44876
|
async #autoAddChromeBuiltin(rc) {
|
|
44781
44877
|
const store = this.#runtimeConfigStore();
|
|
44782
44878
|
if (rc === void 0 || store === void 0 || !shouldAutoAddChromeBuiltin(rc)) return rc;
|
|
44783
|
-
|
|
44879
|
+
const availability = await probeChromeBuiltinAvailability().catch(() => void 0);
|
|
44880
|
+
if (!(availability?.available === true || availability?.available === false && availability.reason === "model-not-ready")) return rc;
|
|
44784
44881
|
const next = {
|
|
44785
44882
|
...rc,
|
|
44786
44883
|
llm: {
|
|
@@ -44945,7 +45042,7 @@ var ChatEngine = class {
|
|
|
44945
45042
|
const toolCalls = summarizeToolCalls(run);
|
|
44946
45043
|
const flushed = this.#flushed.get(run.id);
|
|
44947
45044
|
const text = (this.bridge.streamingRunId === run.id ? this.bridge.streamingText : "").slice(flushed?.text ?? 0);
|
|
44948
|
-
const latest = this.
|
|
45045
|
+
const latest = this.#runBlocks.get(run.id);
|
|
44949
45046
|
const blocks = latest && latest.runId === run.id ? latest.blocks.filter((_, index) => index !== latest.outputBlockIndex) : void 0;
|
|
44950
45047
|
const surfaces = this.bridge.surfaceSnapshots.filter((snapshot) => snapshot.runId === run.id && !flushed?.surfaces.has(snapshot.id));
|
|
44951
45048
|
const todos = this.#runTodos.get(run.id);
|
|
@@ -44969,6 +45066,20 @@ var ChatEngine = class {
|
|
|
44969
45066
|
...this.#activeModelId !== void 0 ? { model: this.#activeModelId } : {}
|
|
44970
45067
|
};
|
|
44971
45068
|
await this.#sessions.appendMessages(sessionId, [assistantMessage]);
|
|
45069
|
+
if (blocks && blocks.length > 0 || surfaces.length > 0) {
|
|
45070
|
+
const snapshotPath = `${this.#chatRoot}/snapshots/${run.id}.blocks.json`;
|
|
45071
|
+
await atomicWriteText(this.#adapter.storage, snapshotPath, JSON.stringify({
|
|
45072
|
+
runId: run.id,
|
|
45073
|
+
sessionId,
|
|
45074
|
+
status,
|
|
45075
|
+
blocks: blocks ?? [],
|
|
45076
|
+
surfaces: surfaces.map((s) => ({
|
|
45077
|
+
id: s.id,
|
|
45078
|
+
runId: s.runId
|
|
45079
|
+
})),
|
|
45080
|
+
snapshotAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
45081
|
+
}, null, 2)).catch(() => void 0);
|
|
45082
|
+
}
|
|
44972
45083
|
await this.#traceStore.put(run);
|
|
44973
45084
|
this.#emit({
|
|
44974
45085
|
type: "run-completed",
|
|
@@ -44988,6 +45099,7 @@ var ChatEngine = class {
|
|
|
44988
45099
|
this.#runCandidates.delete(run.id);
|
|
44989
45100
|
this.#runPhases.delete(run.id);
|
|
44990
45101
|
this.#flushed.delete(run.id);
|
|
45102
|
+
this.#runBlocks.delete(run.id);
|
|
44991
45103
|
}
|
|
44992
45104
|
/**
|
|
44993
45105
|
* 交互提交后把「到此为止」的助手内容切成一条消息(FR-17.8)。
|
|
@@ -45014,6 +45126,8 @@ var ChatEngine = class {
|
|
|
45014
45126
|
request,
|
|
45015
45127
|
...response.value === void 0 ? {} : { submittedValues: redactInteractionValues(response.value, request) }
|
|
45016
45128
|
};
|
|
45129
|
+
const latestBlocks = this.#runBlocks.get(runId);
|
|
45130
|
+
const blocks = latestBlocks && latestBlocks.runId === runId ? latestBlocks.blocks.filter((_, index) => index !== latestBlocks.outputBlockIndex) : void 0;
|
|
45017
45131
|
const message = {
|
|
45018
45132
|
id: newId("msg"),
|
|
45019
45133
|
role: "assistant",
|
|
@@ -45021,6 +45135,7 @@ var ChatEngine = class {
|
|
|
45021
45135
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45022
45136
|
runId,
|
|
45023
45137
|
interactions: [record],
|
|
45138
|
+
...blocks && blocks.length > 0 ? { blocks } : {},
|
|
45024
45139
|
...surfaces.length > 0 ? { surfaces } : {},
|
|
45025
45140
|
...phases.length > 0 ? { phases } : {},
|
|
45026
45141
|
...this.#activeModelId !== void 0 ? { model: this.#activeModelId } : {}
|
|
@@ -45230,6 +45345,7 @@ const chatbotDictionary = defineDictionary({
|
|
|
45230
45345
|
"result.artifacts": "Artifacts",
|
|
45231
45346
|
"result.download": "Download",
|
|
45232
45347
|
"result.file": "File",
|
|
45348
|
+
"result.block.unknown": "Unsupported result block: {type}.",
|
|
45233
45349
|
"status.aria": "Run status",
|
|
45234
45350
|
"status.route": "Routing",
|
|
45235
45351
|
"status.activate": "Activating skill",
|
|
@@ -45550,6 +45666,7 @@ const chatbotDictionary = defineDictionary({
|
|
|
45550
45666
|
"result.artifacts": "产物",
|
|
45551
45667
|
"result.download": "下载",
|
|
45552
45668
|
"result.file": "文件",
|
|
45669
|
+
"result.block.unknown": "不支持的结果块:{type}。",
|
|
45553
45670
|
"status.aria": "运行状态",
|
|
45554
45671
|
"status.route": "路由中",
|
|
45555
45672
|
"status.activate": "激活技能",
|
|
@@ -46695,6 +46812,16 @@ function AssistantUiEmptyState({ title, prompts, disabled, onPrompt }) {
|
|
|
46695
46812
|
});
|
|
46696
46813
|
}
|
|
46697
46814
|
|
|
46815
|
+
//#endregion
|
|
46816
|
+
//#region src/react/format.ts
|
|
46817
|
+
/** 字节数 → 展示文本;压缩前后要放在同一行才看得出效果。
|
|
46818
|
+
* 单一来源(AC-G10):Composer 附件与消息附件芯片共用。 */
|
|
46819
|
+
function formatBytes(bytes) {
|
|
46820
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
46821
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
46822
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
46823
|
+
}
|
|
46824
|
+
|
|
46698
46825
|
//#endregion
|
|
46699
46826
|
//#region src/react/InteractionWaitBar.tsx
|
|
46700
46827
|
/** composer 的 `aria-describedby` 指向这里:禁用原因必须能被读出来(FR-21.3) */
|
|
@@ -46844,12 +46971,6 @@ function CAPABILITY_ICON_CLASS(supported, interactive) {
|
|
|
46844
46971
|
const base = `inline-flex size-8 shrink-0 items-center justify-center rounded-full ${supported ? "text-ink" : "text-muted"}`;
|
|
46845
46972
|
return interactive ? `${base} transition-colors hover:bg-accent hover:text-ink disabled:cursor-not-allowed disabled:hover:bg-transparent` : base;
|
|
46846
46973
|
}
|
|
46847
|
-
/** 字节数 → 展示文本;压缩前后要放在同一行才看得出效果 */
|
|
46848
|
-
function formatBytes(bytes) {
|
|
46849
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
46850
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
46851
|
-
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
46852
|
-
}
|
|
46853
46974
|
function AttachmentMeta({ info }) {
|
|
46854
46975
|
const t = useT();
|
|
46855
46976
|
if (!info) return null;
|
|
@@ -46882,9 +47003,9 @@ function ModelMenuButton({ models }) {
|
|
|
46882
47003
|
children: /* @__PURE__ */ jsxs("button", {
|
|
46883
47004
|
type: "button",
|
|
46884
47005
|
"data-testid": "composer-model",
|
|
46885
|
-
className: "inline-flex
|
|
47006
|
+
className: "inline-flex max-w-full shrink-0 cursor-pointer items-center gap-1 rounded-full px-2.5 py-1 text-sm text-muted transition-colors hover:bg-accent hover:text-ink",
|
|
46886
47007
|
children: [/* @__PURE__ */ jsx("span", {
|
|
46887
|
-
className: "
|
|
47008
|
+
className: "min-w-0 break-words",
|
|
46888
47009
|
children: current?.label ?? t("composer.model")
|
|
46889
47010
|
}), /* @__PURE__ */ jsx(ChevronDown, {
|
|
46890
47011
|
className: "size-3.5 shrink-0",
|
|
@@ -47307,7 +47428,7 @@ function TraceRunId({ runId }) {
|
|
|
47307
47428
|
const t = useT();
|
|
47308
47429
|
if (typeof runId !== "string" || runId === "") return null;
|
|
47309
47430
|
return /* @__PURE__ */ jsxs("div", {
|
|
47310
|
-
className: "
|
|
47431
|
+
className: "grid grid-cols-[auto_auto_auto] items-center gap-1.5 font-mono text-xs text-muted",
|
|
47311
47432
|
"data-testid": "trace-run-id",
|
|
47312
47433
|
children: [
|
|
47313
47434
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -47315,11 +47436,11 @@ function TraceRunId({ runId }) {
|
|
|
47315
47436
|
children: t("trace.runId")
|
|
47316
47437
|
}),
|
|
47317
47438
|
/* @__PURE__ */ jsx("span", {
|
|
47318
|
-
className: "truncate",
|
|
47439
|
+
className: "min-w-0 truncate",
|
|
47319
47440
|
children: runId
|
|
47320
47441
|
}),
|
|
47321
47442
|
/* @__PURE__ */ jsx(CopyButton, {
|
|
47322
|
-
className: "
|
|
47443
|
+
className: "shrink-0",
|
|
47323
47444
|
value: runId,
|
|
47324
47445
|
label: t("trace.runId.copy"),
|
|
47325
47446
|
copiedLabel: t("trace.runId.copied")
|
|
@@ -47365,24 +47486,26 @@ function LifecycleStep({ data }) {
|
|
|
47365
47486
|
const tone = status !== void 0 ? runStatusTone(status) : endedAt === void 0 ? "info" : "neutral";
|
|
47366
47487
|
return /* @__PURE__ */ jsxs("li", {
|
|
47367
47488
|
"aria-label": duration ? `${label}, ${duration}` : label,
|
|
47368
|
-
className: "
|
|
47489
|
+
className: "grid grid-cols-[auto_auto_auto] items-center gap-2 font-mono text-xs text-muted",
|
|
47369
47490
|
children: [
|
|
47370
|
-
/* @__PURE__ */
|
|
47371
|
-
className: "
|
|
47372
|
-
|
|
47373
|
-
|
|
47374
|
-
|
|
47375
|
-
|
|
47376
|
-
|
|
47377
|
-
|
|
47378
|
-
|
|
47491
|
+
/* @__PURE__ */ jsxs("span", {
|
|
47492
|
+
className: "flex min-w-0 items-center gap-2",
|
|
47493
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
47494
|
+
className: "size-1.5 shrink-0 rounded-full",
|
|
47495
|
+
style: { backgroundColor: `var(${STATUS_TONE_VAR[tone]})` },
|
|
47496
|
+
"data-webskill-step-tone": tone,
|
|
47497
|
+
"aria-hidden": true
|
|
47498
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
47499
|
+
className: "min-w-20 text-ink",
|
|
47500
|
+
children: label
|
|
47501
|
+
})]
|
|
47379
47502
|
}),
|
|
47380
47503
|
note ? /* @__PURE__ */ jsx("span", {
|
|
47381
|
-
className: "truncate",
|
|
47504
|
+
className: "min-w-0 truncate",
|
|
47382
47505
|
children: note
|
|
47383
|
-
}) :
|
|
47506
|
+
}) : /* @__PURE__ */ jsx("span", { "aria-hidden": true }),
|
|
47384
47507
|
/* @__PURE__ */ jsx("span", {
|
|
47385
|
-
className: "
|
|
47508
|
+
className: "shrink-0",
|
|
47386
47509
|
children: duration ?? ""
|
|
47387
47510
|
})
|
|
47388
47511
|
]
|
|
@@ -47452,13 +47575,13 @@ function ToolGroup({ count, running, children }) {
|
|
|
47452
47575
|
}), children]
|
|
47453
47576
|
});
|
|
47454
47577
|
}
|
|
47455
|
-
/** 被 `allowed-tools` 拦下时 runtime 回喂的错误码;与执行失败必须分开显示(需求 1 FR-1.6) */
|
|
47456
|
-
const DENIED_CODE = "TOOL_NOT_ALLOWED";
|
|
47457
47578
|
/** 错误码 → 标题文案;未列出的码走通用「失败原因」(0.6.0 FR-18.2) */
|
|
47458
47579
|
const ERROR_TITLE_KEYS = {
|
|
47459
|
-
[
|
|
47580
|
+
["TOOL_NOT_ALLOWED"]: "tool.denied.reason",
|
|
47460
47581
|
TOOL_NOT_FOUND: "tool.notFound.reason",
|
|
47461
|
-
TOOL_RESOLUTION_EXHAUSTED: "tool.exhausted.reason"
|
|
47582
|
+
TOOL_RESOLUTION_EXHAUSTED: "tool.exhausted.reason",
|
|
47583
|
+
NETWORK_BLOCKED: "tool.denied.reason",
|
|
47584
|
+
FS_PERMISSION_DENIED: "tool.denied.reason"
|
|
47462
47585
|
};
|
|
47463
47586
|
function toolErrorOf(part) {
|
|
47464
47587
|
const result = part.result;
|
|
@@ -47479,7 +47602,7 @@ function ToolRow({ part }) {
|
|
|
47479
47602
|
useEffect(() => {
|
|
47480
47603
|
if (part.isError === true) setOpen(true);
|
|
47481
47604
|
}, [part.isError]);
|
|
47482
|
-
const denied = part.isError === true && errorCode ===
|
|
47605
|
+
const denied = part.isError === true && typeof errorCode === "string" && POLICY_DENIAL_CODES.has(errorCode);
|
|
47483
47606
|
const status = running ? "running" : denied ? "denied" : part.isError === true ? "failed" : "completed";
|
|
47484
47607
|
const duration = part.timing && completedAt !== void 0 ? formatDuration(completedAt - part.timing.startedAt) : void 0;
|
|
47485
47608
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -47524,17 +47647,17 @@ function ToolRow({ part }) {
|
|
|
47524
47647
|
}), open && (part.argsText !== "" || errorMessage !== void 0) ? /* @__PURE__ */ jsxs("div", {
|
|
47525
47648
|
className: "border-t border-border px-2 py-1.5",
|
|
47526
47649
|
children: [errorMessage !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
|
|
47527
|
-
className: "text-xs text-muted",
|
|
47650
|
+
className: "text-xs text-muted italic",
|
|
47528
47651
|
children: t(errorCode !== void 0 ? ERROR_TITLE_KEYS[errorCode] ?? "tool.failed.reason" : "tool.failed.reason")
|
|
47529
47652
|
}), /* @__PURE__ */ jsx("p", {
|
|
47530
47653
|
"data-testid": "tool-error-reason",
|
|
47531
47654
|
className: "text-xs break-words text-ink",
|
|
47532
47655
|
children: errorMessage
|
|
47533
47656
|
})] }) : null, part.argsText !== "" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
|
|
47534
|
-
className: "text-xs text-muted",
|
|
47657
|
+
className: "text-xs text-muted italic",
|
|
47535
47658
|
children: t("tool.args")
|
|
47536
47659
|
}), /* @__PURE__ */ jsx("pre", {
|
|
47537
|
-
className: "overflow-x-auto font-mono text-xs text-ink",
|
|
47660
|
+
className: "overflow-x-auto whitespace-pre font-mono text-xs text-ink",
|
|
47538
47661
|
children: part.argsText
|
|
47539
47662
|
})] }) : null]
|
|
47540
47663
|
}) : null]
|
|
@@ -47758,6 +47881,40 @@ function TodoPanel({ items }) {
|
|
|
47758
47881
|
});
|
|
47759
47882
|
}
|
|
47760
47883
|
|
|
47884
|
+
//#endregion
|
|
47885
|
+
//#region src/react/UserAttachmentChips.tsx
|
|
47886
|
+
/**
|
|
47887
|
+
* 用户消息气泡上方的附件芯片(0.9.0 分册 12,FR-12.2)。
|
|
47888
|
+
* 数据源是持久化的 `ChatMessage.attachments`(旧会话文件无该字段时缺省不渲染)。
|
|
47889
|
+
* 纯 props 组件:不依赖 assistant-ui 上下文,便于单测(AC-12.3)。
|
|
47890
|
+
*/
|
|
47891
|
+
function UserAttachmentChips({ attachments }) {
|
|
47892
|
+
if (!attachments || attachments.length === 0) return null;
|
|
47893
|
+
return /* @__PURE__ */ jsx("div", {
|
|
47894
|
+
"data-testid": "user-attachments",
|
|
47895
|
+
className: "mb-1 flex flex-col items-end gap-1",
|
|
47896
|
+
children: attachments.map((att) => /* @__PURE__ */ jsxs("span", {
|
|
47897
|
+
"data-testid": "user-attachment-chip",
|
|
47898
|
+
"aria-label": `${att.name}, ${formatBytes(att.size)}`,
|
|
47899
|
+
className: "inline-flex max-w-full items-center gap-1.5 rounded-md border border-border bg-surface px-2 py-1 text-xs text-ink",
|
|
47900
|
+
children: [
|
|
47901
|
+
/* @__PURE__ */ jsx(File, {
|
|
47902
|
+
className: "size-3.5 shrink-0 text-muted",
|
|
47903
|
+
"aria-hidden": true
|
|
47904
|
+
}),
|
|
47905
|
+
/* @__PURE__ */ jsx("span", {
|
|
47906
|
+
className: "truncate font-medium",
|
|
47907
|
+
children: att.name
|
|
47908
|
+
}),
|
|
47909
|
+
/* @__PURE__ */ jsx("span", {
|
|
47910
|
+
className: "shrink-0 text-muted",
|
|
47911
|
+
children: formatBytes(att.size)
|
|
47912
|
+
})
|
|
47913
|
+
]
|
|
47914
|
+
}, att.id))
|
|
47915
|
+
});
|
|
47916
|
+
}
|
|
47917
|
+
|
|
47761
47918
|
//#endregion
|
|
47762
47919
|
//#region src/react/OpenUiSurfaceHost.tsx
|
|
47763
47920
|
/** Renders persisted UI spec snapshots through the OpenUI extension without a live bridge. @experimental */
|
|
@@ -57859,6 +58016,7 @@ function TableBlock({ columns, rows }) {
|
|
|
57859
58016
|
});
|
|
57860
58017
|
}
|
|
57861
58018
|
function Block({ block, runId, onDownload }) {
|
|
58019
|
+
const t = useT();
|
|
57862
58020
|
switch (block.type) {
|
|
57863
58021
|
case "markdown": return /* @__PURE__ */ jsx("div", {
|
|
57864
58022
|
className: "rounded-card border border-border bg-surface px-4 py-3 shadow-card",
|
|
@@ -57885,6 +58043,10 @@ function Block({ block, runId, onDownload }) {
|
|
|
57885
58043
|
},
|
|
57886
58044
|
...onDownload ? { onDownload } : {}
|
|
57887
58045
|
});
|
|
58046
|
+
default: return /* @__PURE__ */ jsx("div", {
|
|
58047
|
+
className: "rounded-card border border-border bg-surface px-4 py-3 text-sm text-muted",
|
|
58048
|
+
children: t("result.block.unknown", { type: String(block.type ?? "unknown") })
|
|
58049
|
+
});
|
|
57888
58050
|
}
|
|
57889
58051
|
}
|
|
57890
58052
|
/**
|
|
@@ -58087,7 +58249,7 @@ function AssistantUiMessageActions({ message, onRetry, onDelete, onViewTrace, mo
|
|
|
58087
58249
|
return /* @__PURE__ */ jsxs("div", {
|
|
58088
58250
|
"data-testid": "assistant-ui-message-actions",
|
|
58089
58251
|
"aria-label": t("a11y.messageActions"),
|
|
58090
|
-
className: "pointer-events-none absolute inset-x-0 -bottom-
|
|
58252
|
+
className: "pointer-events-none absolute inset-x-0 -bottom-9 flex h-7 items-center",
|
|
58091
58253
|
children: [/* @__PURE__ */ jsxs(ActionBarPrimitive.Root, {
|
|
58092
58254
|
hideWhenRunning: true,
|
|
58093
58255
|
autohide: "always",
|
|
@@ -58159,12 +58321,12 @@ function AssistantUiMessage(props) {
|
|
|
58159
58321
|
const todos = useAuiState((s) => s.message.metadata?.custom?.["todos"]);
|
|
58160
58322
|
const isEditing = useAuiState((s) => s.composer.isEditing);
|
|
58161
58323
|
if (role === "user") return /* @__PURE__ */ jsxs("div", {
|
|
58162
|
-
className: "webskill-aui-message webskill-aui-message--user relative mb-
|
|
58324
|
+
className: "webskill-aui-message webskill-aui-message--user relative mb-9",
|
|
58163
58325
|
"data-testid": "assistant-ui-user-message",
|
|
58164
58326
|
children: [
|
|
58165
58327
|
isEditing ? /* @__PURE__ */ jsxs(ComposerPrimitive.Root, {
|
|
58166
58328
|
"data-testid": "message-edit-composer",
|
|
58167
|
-
className: "flex flex-col gap-2 rounded-card border border-border bg-surface p-2",
|
|
58329
|
+
className: "flex w-[80%] flex-col gap-2 rounded-card border border-border bg-surface p-2",
|
|
58168
58330
|
children: [/* @__PURE__ */ jsx(ComposerPrimitive.Input, {
|
|
58169
58331
|
autoFocus: true,
|
|
58170
58332
|
className: "min-h-16 w-full resize-none bg-transparent text-sm text-ink outline-none"
|
|
@@ -58180,10 +58342,10 @@ function AssistantUiMessage(props) {
|
|
|
58180
58342
|
children: t("message.editSend")
|
|
58181
58343
|
})]
|
|
58182
58344
|
})]
|
|
58183
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
58345
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(UserAttachmentChips, { attachments: message?.attachments }), /* @__PURE__ */ jsx("div", {
|
|
58184
58346
|
className: "webskill-aui-user-bubble",
|
|
58185
58347
|
children: message?.text ?? ""
|
|
58186
|
-
}),
|
|
58348
|
+
})] }),
|
|
58187
58349
|
message?.notice ? /* @__PURE__ */ jsx("p", {
|
|
58188
58350
|
"data-testid": "message-notice",
|
|
58189
58351
|
className: "mt-1 text-right text-xs text-muted",
|
|
@@ -58193,7 +58355,7 @@ function AssistantUiMessage(props) {
|
|
|
58193
58355
|
]
|
|
58194
58356
|
});
|
|
58195
58357
|
return /* @__PURE__ */ jsxs("div", {
|
|
58196
|
-
className: "webskill-aui-message webskill-aui-message--assistant relative mb-
|
|
58358
|
+
className: "webskill-aui-message webskill-aui-message--assistant relative mb-9 flex min-w-0 flex-col gap-3",
|
|
58197
58359
|
"data-testid": "assistant-ui-assistant-message",
|
|
58198
58360
|
children: [
|
|
58199
58361
|
Array.isArray(todos) ? /* @__PURE__ */ jsx(TodoPanel, { items: todos }) : null,
|
|
@@ -59167,7 +59329,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59167
59329
|
* `theme` / `locale` / `renderer` / `dictationLang` 这几个 props 只作为它缺席时的兜底。
|
|
59168
59330
|
*/
|
|
59169
59331
|
const configStore = config?.runtimeConfig;
|
|
59170
|
-
const { appearance,
|
|
59332
|
+
const { appearance, updateImmediate: updateAppearanceImmediate } = useRuntimeAppearance(configStore, useMemo(() => ({
|
|
59171
59333
|
theme: themeProp ?? "light",
|
|
59172
59334
|
locale: localeProp ?? "en",
|
|
59173
59335
|
renderer: rendererProp ?? "native",
|
|
@@ -59427,12 +59589,32 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59427
59589
|
onError: (e) => setError({ message: toErrorMessage(e) })
|
|
59428
59590
|
});
|
|
59429
59591
|
const flushPendingDeletes = pendingDeletes.flush;
|
|
59592
|
+
/**
|
|
59593
|
+
* 会话创建串行化(0.9.0 复核:AC-21.16 全量偶发红的根因)。
|
|
59594
|
+
* `handleCreate`(点 New chat)与 `handleSend`(无当前会话时兜底建会话)并发时,
|
|
59595
|
+
* 各调一次 `engine.createSession()` 会建出**两个**会话——消息进后建的那个,
|
|
59596
|
+
* 先建的变成永久空会话(列表第一行永远显示兜底文案)。
|
|
59597
|
+
*
|
|
59598
|
+
* 这里用 ref 共享同一个 in-flight promise:谁先发起谁创建,其它调用方拿到同一个会话。
|
|
59599
|
+
* 注意 ref 的生命周期:**不能**在 promise settle 时立刻清空——「handleCreate 建完、
|
|
59600
|
+
* 但 React 还没因 setCurrentSessionId 重渲染」的窗口里,handleSend 兜底仍要复用这个会话,
|
|
59601
|
+
* 立刻清空会在这个窗口里再建一个(第一版修复在全量 e2e 里实测仍红)。
|
|
59602
|
+
* 清空交给下面的 useEffect:一旦 UI 真正选中了某个会话,最近一次创建就已被消费,ref 让位。
|
|
59603
|
+
*/
|
|
59604
|
+
const creatingRef = useRef(void 0);
|
|
59605
|
+
const ensureSession = useCallback(async () => {
|
|
59606
|
+
if (!creatingRef.current) creatingRef.current = engine.createSession();
|
|
59607
|
+
return creatingRef.current;
|
|
59608
|
+
}, [engine]);
|
|
59609
|
+
useEffect(() => {
|
|
59610
|
+
if (creatingRef.current !== void 0) creatingRef.current = void 0;
|
|
59611
|
+
}, [currentSessionId]);
|
|
59430
59612
|
const handleSend = useCallback((text, attachments = []) => {
|
|
59431
59613
|
(async () => {
|
|
59432
59614
|
await flushPendingDeletes();
|
|
59433
59615
|
let sessionId = currentSessionId;
|
|
59434
59616
|
if (!sessionId) {
|
|
59435
|
-
const meta = await
|
|
59617
|
+
const meta = await ensureSession();
|
|
59436
59618
|
sessionId = meta.id;
|
|
59437
59619
|
setCurrentSessionId(meta.id);
|
|
59438
59620
|
await refreshSessions();
|
|
@@ -59445,7 +59627,8 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59445
59627
|
engine,
|
|
59446
59628
|
currentSessionId,
|
|
59447
59629
|
refreshSessions,
|
|
59448
|
-
flushPendingDeletes
|
|
59630
|
+
flushPendingDeletes,
|
|
59631
|
+
ensureSession
|
|
59449
59632
|
]);
|
|
59450
59633
|
const handleStop = useCallback(() => {
|
|
59451
59634
|
if (currentRunId) engine.cancel(currentRunId);
|
|
@@ -59524,7 +59707,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59524
59707
|
loadingEarlierSessions
|
|
59525
59708
|
]);
|
|
59526
59709
|
const handleCreate = useCallback(() => {
|
|
59527
|
-
flushPendingDeletes().then(() =>
|
|
59710
|
+
flushPendingDeletes().then(() => ensureSession()).then(async (meta) => {
|
|
59528
59711
|
setCurrentSessionId(meta.id);
|
|
59529
59712
|
setMessages([]);
|
|
59530
59713
|
setMessagesCursor(void 0);
|
|
@@ -59534,7 +59717,8 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59534
59717
|
}, [
|
|
59535
59718
|
engine,
|
|
59536
59719
|
refreshSessions,
|
|
59537
|
-
flushPendingDeletes
|
|
59720
|
+
flushPendingDeletes,
|
|
59721
|
+
ensureSession
|
|
59538
59722
|
]);
|
|
59539
59723
|
const handleRenameSession = useCallback((id, title) => {
|
|
59540
59724
|
flushPendingDeletes().then(() => engine.renameSession(id, title)).then(refreshSessions).catch((e) => setError({ message: toErrorMessage(e) }));
|
|
@@ -59572,9 +59756,9 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59572
59756
|
flushPendingDeletes
|
|
59573
59757
|
]);
|
|
59574
59758
|
const handleAppearanceChange = useCallback((next) => {
|
|
59575
|
-
|
|
59759
|
+
updateAppearanceImmediate(next);
|
|
59576
59760
|
onAppearanceChange?.(next);
|
|
59577
|
-
}, [onAppearanceChange,
|
|
59761
|
+
}, [onAppearanceChange, updateAppearanceImmediate]);
|
|
59578
59762
|
/** 画像读写全部经引擎(需求 19):设置面板不直接碰存储,加密与作用域只有一处实现 */
|
|
59579
59763
|
const chatRoot = (config?.chatRoot ?? "/chat").replace(/\/+$/, "");
|
|
59580
59764
|
/**
|
|
@@ -59647,7 +59831,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59647
59831
|
onOpenSessions: () => setDrawerOpen(true),
|
|
59648
59832
|
onCreateSession: handleCreate,
|
|
59649
59833
|
onOpenConsole: () => adapter.navigation.openConsole(),
|
|
59650
|
-
...onOpenSettings ? { onOpenSettings: () => onOpenSettings(
|
|
59834
|
+
...onOpenSettings ? { onOpenSettings: () => onOpenSettings() } : {},
|
|
59651
59835
|
theme,
|
|
59652
59836
|
onToggleTheme: () => handleAppearanceChange({ theme: theme === "dark" ? "light" : "dark" })
|
|
59653
59837
|
}),
|
|
@@ -59829,4 +60013,13 @@ function VercelPayloadPreview({ bridge }) {
|
|
|
59829
60013
|
}
|
|
59830
60014
|
|
|
59831
60015
|
//#endregion
|
|
59832
|
-
|
|
60016
|
+
//#region src/version.ts
|
|
60017
|
+
/** Generated by scripts/syncVersionConstant.mjs from packages/chatbot/package.json. Do not edit by hand. */
|
|
60018
|
+
/**
|
|
60019
|
+
* Version of the published `@webskill/chatbot` package, injected at build time.
|
|
60020
|
+
* @stable
|
|
60021
|
+
*/
|
|
60022
|
+
const CHATBOT_VERSION = "0.6.0";
|
|
60023
|
+
|
|
60024
|
+
//#endregion
|
|
60025
|
+
export { A2uiSurfaceHost, A2uiSurfaceSnapshotHost, CHATBOT_VERSION, ChatEngine, Chatbot, CompositeUiBridge, DEFAULT_RENDERER_CAPABILITIES, DEFAULT_RUNTIME_CONFIG_STORAGE_KEY, ErrorCard, InteractionCard, InterruptedBanner, OpenUiSurfaceHost, OpenUiSurfaceSnapshotHost, ResultBlockList, ResultBlocksPro, SkillBadges, SpecInteraction, VercelPayloadPreview, VercelSurfaceHost, VercelSurfaceSnapshotHost, chatbotDictionary, configureA2uiMarkdown, createLocalStorageRuntimeConfigStore, createMemoryRuntimeConfigStore, probeA2uiAvailability, probeOpenUiAvailability, sandboxExecutorDeps, useT };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webskill/chatbot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@a2ui/web_core": "^0.10.5",
|
|
27
27
|
"@lit/context": "^1.1.0",
|
|
28
28
|
"@openuidev/react-lang": "0.2.8",
|
|
29
|
-
"@webskill/sdk": "^0.
|
|
29
|
+
"@webskill/sdk": "^0.9.0",
|
|
30
30
|
"react": ">=19.0.0",
|
|
31
31
|
"react-dom": ">=19.0.0",
|
|
32
32
|
"zod": "^3.25.0 || ^4.0.0"
|