@webskill/chatbot 0.7.0 → 0.8.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 +153 -22
- package/dist/index.d.ts +85 -5
- package/dist/index.js +225 -72
- package/package.json +2 -2
package/dist/chatbot.css
CHANGED
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
--container-sm: 24rem;
|
|
12
12
|
--container-md: 28rem;
|
|
13
13
|
--container-2xl: 42rem;
|
|
14
|
-
--container-3xl: 48rem;
|
|
15
14
|
--text-xs: 0.75rem;
|
|
16
15
|
--text-xs--line-height: calc(1 / 0.75);
|
|
17
16
|
--text-sm: 0.875rem;
|
|
@@ -429,6 +428,9 @@
|
|
|
429
428
|
.table {
|
|
430
429
|
display: table;
|
|
431
430
|
}
|
|
431
|
+
.aspect-\[4\/3\] {
|
|
432
|
+
aspect-ratio: 4/3;
|
|
433
|
+
}
|
|
432
434
|
.aspect-square {
|
|
433
435
|
aspect-ratio: 1 / 1;
|
|
434
436
|
}
|
|
@@ -582,6 +584,9 @@
|
|
|
582
584
|
.w-40 {
|
|
583
585
|
width: calc(var(--spacing) * 40);
|
|
584
586
|
}
|
|
587
|
+
.w-48 {
|
|
588
|
+
width: calc(var(--spacing) * 48);
|
|
589
|
+
}
|
|
585
590
|
.w-72 {
|
|
586
591
|
width: calc(var(--spacing) * 72);
|
|
587
592
|
}
|
|
@@ -612,9 +617,6 @@
|
|
|
612
617
|
.max-w-2xl {
|
|
613
618
|
max-width: var(--container-2xl);
|
|
614
619
|
}
|
|
615
|
-
.max-w-3xl {
|
|
616
|
-
max-width: var(--container-3xl);
|
|
617
|
-
}
|
|
618
620
|
.max-w-48 {
|
|
619
621
|
max-width: calc(var(--spacing) * 48);
|
|
620
622
|
}
|
|
@@ -725,6 +727,15 @@
|
|
|
725
727
|
.resize-y {
|
|
726
728
|
resize: vertical;
|
|
727
729
|
}
|
|
730
|
+
.snap-x {
|
|
731
|
+
scroll-snap-type: x var(--tw-scroll-snap-strictness);
|
|
732
|
+
}
|
|
733
|
+
.snap-mandatory {
|
|
734
|
+
--tw-scroll-snap-strictness: mandatory;
|
|
735
|
+
}
|
|
736
|
+
.snap-start {
|
|
737
|
+
scroll-snap-align: start;
|
|
738
|
+
}
|
|
728
739
|
.list-decimal {
|
|
729
740
|
list-style-type: decimal;
|
|
730
741
|
}
|
|
@@ -734,6 +745,9 @@
|
|
|
734
745
|
.grid-cols-1 {
|
|
735
746
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
736
747
|
}
|
|
748
|
+
.grid-cols-\[auto_1fr\] {
|
|
749
|
+
grid-template-columns: auto 1fr;
|
|
750
|
+
}
|
|
737
751
|
.flex-col {
|
|
738
752
|
flex-direction: column;
|
|
739
753
|
}
|
|
@@ -796,6 +810,12 @@
|
|
|
796
810
|
margin-block-start: calc(var(--spacing) * var(--tw-space-y-reverse));
|
|
797
811
|
margin-block-end: calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)));
|
|
798
812
|
}
|
|
813
|
+
.gap-x-4 {
|
|
814
|
+
column-gap: calc(var(--spacing) * 4);
|
|
815
|
+
}
|
|
816
|
+
.gap-y-1 {
|
|
817
|
+
row-gap: var(--spacing);
|
|
818
|
+
}
|
|
799
819
|
:where(.divide-y > :not(:last-child)) {
|
|
800
820
|
--tw-divide-y-reverse: 0;
|
|
801
821
|
border-bottom-style: var(--tw-border-style);
|
|
@@ -910,6 +930,10 @@
|
|
|
910
930
|
border-left-style: var(--tw-border-style);
|
|
911
931
|
border-left-width: 1px;
|
|
912
932
|
}
|
|
933
|
+
.border-l-2 {
|
|
934
|
+
border-left-style: var(--tw-border-style);
|
|
935
|
+
border-left-width: 2px;
|
|
936
|
+
}
|
|
913
937
|
.border-dashed {
|
|
914
938
|
--tw-border-style: dashed;
|
|
915
939
|
border-style: dashed;
|
|
@@ -998,18 +1022,6 @@
|
|
|
998
1022
|
.bg-destructive-soft {
|
|
999
1023
|
background-color: var(--destructive-soft);
|
|
1000
1024
|
}
|
|
1001
|
-
.bg-foreground\/35 {
|
|
1002
|
-
background-color: var(--foreground);
|
|
1003
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
1004
|
-
background-color: color-mix(in oklab, var(--foreground) 35%, transparent);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
.bg-foreground\/45 {
|
|
1008
|
-
background-color: var(--foreground);
|
|
1009
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
1010
|
-
background-color: color-mix(in oklab, var(--foreground) 45%, transparent);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
1025
|
.bg-info {
|
|
1014
1026
|
background-color: var(--info);
|
|
1015
1027
|
}
|
|
@@ -1019,12 +1031,6 @@
|
|
|
1019
1031
|
.bg-ink {
|
|
1020
1032
|
background-color: var(--foreground);
|
|
1021
1033
|
}
|
|
1022
|
-
.bg-ink\/35 {
|
|
1023
|
-
background-color: var(--foreground);
|
|
1024
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
1025
|
-
background-color: color-mix(in oklab, var(--foreground) 35%, transparent);
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
1034
|
.bg-muted {
|
|
1029
1035
|
background-color: var(--muted-foreground);
|
|
1030
1036
|
}
|
|
@@ -1037,6 +1043,9 @@
|
|
|
1037
1043
|
.bg-primary {
|
|
1038
1044
|
background-color: var(--primary);
|
|
1039
1045
|
}
|
|
1046
|
+
.bg-scrim {
|
|
1047
|
+
background-color: var(--scrim);
|
|
1048
|
+
}
|
|
1040
1049
|
.bg-secondary {
|
|
1041
1050
|
background-color: var(--secondary);
|
|
1042
1051
|
}
|
|
@@ -1091,6 +1100,9 @@
|
|
|
1091
1100
|
.p-4 {
|
|
1092
1101
|
padding: calc(var(--spacing) * 4);
|
|
1093
1102
|
}
|
|
1103
|
+
.p-5 {
|
|
1104
|
+
padding: calc(var(--spacing) * 5);
|
|
1105
|
+
}
|
|
1094
1106
|
.px-1 {
|
|
1095
1107
|
padding-inline: var(--spacing);
|
|
1096
1108
|
}
|
|
@@ -1178,6 +1190,9 @@
|
|
|
1178
1190
|
.pl-2 {
|
|
1179
1191
|
padding-left: calc(var(--spacing) * 2);
|
|
1180
1192
|
}
|
|
1193
|
+
.pl-3 {
|
|
1194
|
+
padding-left: calc(var(--spacing) * 3);
|
|
1195
|
+
}
|
|
1181
1196
|
.pl-4 {
|
|
1182
1197
|
padding-left: calc(var(--spacing) * 4);
|
|
1183
1198
|
}
|
|
@@ -1323,6 +1338,9 @@
|
|
|
1323
1338
|
.italic {
|
|
1324
1339
|
font-style: italic;
|
|
1325
1340
|
}
|
|
1341
|
+
.not-italic {
|
|
1342
|
+
font-style: normal;
|
|
1343
|
+
}
|
|
1326
1344
|
.tabular-nums {
|
|
1327
1345
|
--tw-numeric-spacing: tabular-nums;
|
|
1328
1346
|
font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);
|
|
@@ -2014,6 +2032,7 @@
|
|
|
2014
2032
|
:where(.dark, .light, [data-theme]) {
|
|
2015
2033
|
--color-background: var(--background);
|
|
2016
2034
|
--color-foreground: var(--foreground);
|
|
2035
|
+
--color-scrim: var(--scrim);
|
|
2017
2036
|
--color-card: var(--card);
|
|
2018
2037
|
--color-card-foreground: var(--card-foreground);
|
|
2019
2038
|
--color-popover: var(--popover);
|
|
@@ -2064,8 +2083,22 @@
|
|
|
2064
2083
|
}
|
|
2065
2084
|
:root, :where(.light, [data-theme='light']) {
|
|
2066
2085
|
--radius: 0.625rem;
|
|
2086
|
+
--shadow-card-vivid: 0 6px 20px oklch(0 0 0 / 12%);
|
|
2087
|
+
--surface-dashboard: oklch(0.2 0.01 260);
|
|
2088
|
+
--border-dashboard: oklch(1 0 0 / 14%);
|
|
2089
|
+
--palette-sky: oklch(0.95 0.03 240);
|
|
2090
|
+
--palette-sky-ink: oklch(0.35 0.09 240);
|
|
2091
|
+
--palette-violet: oklch(0.95 0.03 300);
|
|
2092
|
+
--palette-violet-ink: oklch(0.35 0.1 300);
|
|
2093
|
+
--palette-amber: oklch(0.95 0.05 85);
|
|
2094
|
+
--palette-amber-ink: oklch(0.36 0.09 85);
|
|
2095
|
+
--palette-rose: oklch(0.95 0.03 15);
|
|
2096
|
+
--palette-rose-ink: oklch(0.37 0.11 15);
|
|
2097
|
+
--palette-emerald: oklch(0.95 0.04 160);
|
|
2098
|
+
--palette-emerald-ink: oklch(0.34 0.08 160);
|
|
2067
2099
|
--background: oklch(1 0 0);
|
|
2068
2100
|
--foreground: oklch(0.145 0 0);
|
|
2101
|
+
--scrim: oklch(0.145 0 0 / 45%);
|
|
2069
2102
|
--card: oklch(1 0 0);
|
|
2070
2103
|
--card-foreground: oklch(0.145 0 0);
|
|
2071
2104
|
--popover: oklch(1 0 0);
|
|
@@ -2154,8 +2187,22 @@
|
|
|
2154
2187
|
--code-url: hsl(198, 99%, 37%);
|
|
2155
2188
|
}
|
|
2156
2189
|
:where(.dark, [data-theme='dark']) {
|
|
2190
|
+
--shadow-card-vivid: 0 6px 20px oklch(0 0 0 / 40%);
|
|
2191
|
+
--surface-dashboard: oklch(0.18 0.01 260);
|
|
2192
|
+
--border-dashboard: oklch(1 0 0 / 16%);
|
|
2193
|
+
--palette-sky: oklch(0.3 0.05 240);
|
|
2194
|
+
--palette-sky-ink: oklch(0.88 0.06 240);
|
|
2195
|
+
--palette-violet: oklch(0.3 0.06 300);
|
|
2196
|
+
--palette-violet-ink: oklch(0.88 0.07 300);
|
|
2197
|
+
--palette-amber: oklch(0.32 0.06 85);
|
|
2198
|
+
--palette-amber-ink: oklch(0.9 0.09 85);
|
|
2199
|
+
--palette-rose: oklch(0.31 0.06 15);
|
|
2200
|
+
--palette-rose-ink: oklch(0.89 0.07 15);
|
|
2201
|
+
--palette-emerald: oklch(0.29 0.05 160);
|
|
2202
|
+
--palette-emerald-ink: oklch(0.88 0.08 160);
|
|
2157
2203
|
--background: oklch(0.145 0 0);
|
|
2158
2204
|
--foreground: oklch(0.985 0 0);
|
|
2205
|
+
--scrim: oklch(0 0 0 / 60%);
|
|
2159
2206
|
--card: oklch(0.205 0 0);
|
|
2160
2207
|
--card-foreground: oklch(0.985 0 0);
|
|
2161
2208
|
--popover: oklch(0.205 0 0);
|
|
@@ -2531,8 +2578,86 @@
|
|
|
2531
2578
|
.webskill-surface--error, .webskill-surface--unsupported {
|
|
2532
2579
|
border-color: var(--destructive);
|
|
2533
2580
|
}
|
|
2581
|
+
.webskill-palette-sky {
|
|
2582
|
+
background: var(--palette-sky);
|
|
2583
|
+
color: var(--palette-sky-ink);
|
|
2584
|
+
}
|
|
2585
|
+
.webskill-palette-violet {
|
|
2586
|
+
background: var(--palette-violet);
|
|
2587
|
+
color: var(--palette-violet-ink);
|
|
2588
|
+
}
|
|
2589
|
+
.webskill-palette-amber {
|
|
2590
|
+
background: var(--palette-amber);
|
|
2591
|
+
color: var(--palette-amber-ink);
|
|
2592
|
+
}
|
|
2593
|
+
.webskill-palette-rose {
|
|
2594
|
+
background: var(--palette-rose);
|
|
2595
|
+
color: var(--palette-rose-ink);
|
|
2596
|
+
}
|
|
2597
|
+
.webskill-palette-emerald {
|
|
2598
|
+
background: var(--palette-emerald);
|
|
2599
|
+
color: var(--palette-emerald-ink);
|
|
2600
|
+
}
|
|
2601
|
+
[data-webskill-theme='vivid'] {
|
|
2602
|
+
--radius-card: 1rem;
|
|
2603
|
+
--shadow-card: var(--shadow-card-vivid);
|
|
2604
|
+
}
|
|
2605
|
+
[data-webskill-theme='dashboard-dark'] {
|
|
2606
|
+
--radius-card: 0.375rem;
|
|
2607
|
+
--shadow-card: none;
|
|
2608
|
+
--color-surface: var(--surface-dashboard);
|
|
2609
|
+
--color-border: var(--border-dashboard);
|
|
2610
|
+
}
|
|
2611
|
+
.webskill-spec-split {
|
|
2612
|
+
container-type: inline-size;
|
|
2613
|
+
grid-template-columns: var(--split-ratio, 1fr 1fr);
|
|
2614
|
+
}
|
|
2615
|
+
.webskill-spec-card--span2 {
|
|
2616
|
+
grid-column: span 2;
|
|
2617
|
+
}
|
|
2618
|
+
@container (max-width: 30rem) {
|
|
2619
|
+
.webskill-spec-split {
|
|
2620
|
+
grid-template-columns: 1fr;
|
|
2621
|
+
}
|
|
2622
|
+
.webskill-spec-card--span2 {
|
|
2623
|
+
grid-column: auto;
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
.webskill-spec-form__fields {
|
|
2627
|
+
display: grid;
|
|
2628
|
+
gap: 0.75rem;
|
|
2629
|
+
container-type: inline-size;
|
|
2630
|
+
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
|
2631
|
+
}
|
|
2632
|
+
.webskill-spec-form__fields > :has(textarea), .webskill-spec-form__fields > [data-field-span='full'] {
|
|
2633
|
+
grid-column: 1 / -1;
|
|
2634
|
+
}
|
|
2534
2635
|
.webskill-aui-shell {
|
|
2535
2636
|
background: var(--color-background);
|
|
2637
|
+
--webskill-chat-prose-max: 48rem;
|
|
2638
|
+
--webskill-chat-surface-max: 64rem;
|
|
2639
|
+
}
|
|
2640
|
+
.webskill-aui-shell[data-layout='fullscreen'] {
|
|
2641
|
+
--webskill-chat-surface-max: 80rem;
|
|
2642
|
+
}
|
|
2643
|
+
.webskill-aui-shell[data-layout='mobile'] {
|
|
2644
|
+
--webskill-chat-prose-max: 100%;
|
|
2645
|
+
--webskill-chat-surface-max: 100%;
|
|
2646
|
+
}
|
|
2647
|
+
.webskill-chat-prose {
|
|
2648
|
+
max-width: var(--webskill-chat-prose-max);
|
|
2649
|
+
}
|
|
2650
|
+
.webskill-chat-column {
|
|
2651
|
+
container-type: inline-size;
|
|
2652
|
+
}
|
|
2653
|
+
.webskill-chat-surface-wide:has([data-webskill-multicol]) {
|
|
2654
|
+
--webskill-chat-surface-w: min(var(--webskill-chat-surface-max), 100cqw - 2rem);
|
|
2655
|
+
width: var(--webskill-chat-surface-w);
|
|
2656
|
+
margin-inline: calc((100% - var(--webskill-chat-surface-w)) / 2);
|
|
2657
|
+
}
|
|
2658
|
+
.webskill-aui-shell[data-layout='mobile'] .webskill-chat-surface-wide {
|
|
2659
|
+
width: 100%;
|
|
2660
|
+
margin-inline: 0;
|
|
2536
2661
|
}
|
|
2537
2662
|
.webskill-aui-header {
|
|
2538
2663
|
border-color: var(--color-border);
|
|
@@ -2649,6 +2774,11 @@
|
|
|
2649
2774
|
inherits: false;
|
|
2650
2775
|
initial-value: 0;
|
|
2651
2776
|
}
|
|
2777
|
+
@property --tw-scroll-snap-strictness {
|
|
2778
|
+
syntax: "*";
|
|
2779
|
+
inherits: false;
|
|
2780
|
+
initial-value: proximity;
|
|
2781
|
+
}
|
|
2652
2782
|
@property --tw-space-y-reverse {
|
|
2653
2783
|
syntax: "*";
|
|
2654
2784
|
inherits: false;
|
|
@@ -2884,6 +3014,7 @@
|
|
|
2884
3014
|
--tw-translate-x: 0;
|
|
2885
3015
|
--tw-translate-y: 0;
|
|
2886
3016
|
--tw-translate-z: 0;
|
|
3017
|
+
--tw-scroll-snap-strictness: proximity;
|
|
2887
3018
|
--tw-space-y-reverse: 0;
|
|
2888
3019
|
--tw-divide-y-reverse: 0;
|
|
2889
3020
|
--tw-border-style: solid;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AgentLoopConfig, ApprovalScope, BridgeCapabilities, ExternalSkillProvider, ExternalToolSource, FileSystemProvider, HookRunner, InteractionRequest, InteractionResponse, LifecycleEventInit, LlmClient, NetworkPolicy, Page, PageQuery, RenderBlock, RenderResultRequest, RunSnapshot, RunSnapshotListEntry, RuntimePhase, RuntimeRun, ScriptExecutor, SessionStore, SkillCandidateMarker, SkillCatalogEntry, SkillIntegrityGuard, SkillOutcomeReporter, SkillStateGuard, UiBridge, UiSpecDrafts, UiSpecEvent, UiSpecSnapshot, UiSurfaceActionRequest, UiSurfaceActionResponse, UserProfile, UserProfileExport, WebSkillErrorCode, diffUserProfile } from "@webskill/sdk";
|
|
1
|
+
import { AgentLoopConfig, ApprovalScope, BridgeCapabilities, DocxTextExtractor, ExternalSkillProvider, ExternalToolSource, FileSystemProvider, HookRunner, InteractionRequest, InteractionResponse, LifecycleEventInit, LinkedDocumentReader, LlmClient, NetworkPolicy, Page, PageQuery, RenderBlock, RenderResultRequest, RunSnapshot, RunSnapshotListEntry, RuntimePhase, RuntimeRun, ScriptExecutor, SessionStore, SkillCandidateMarker, SkillCatalogEntry, SkillIntegrityGuard, SkillOutcomeReporter, SkillStateGuard, UiBridge, UiSpecDrafts, UiSpecEvent, UiSpecSnapshot, UiSurfaceActionRequest, UiSurfaceActionResponse, UserProfile, UserProfileExport, WebSkillErrorCode, diffUserProfile } from "@webskill/sdk";
|
|
2
2
|
import { SandboxMode, TypeScriptSupportOptions } from "@webskill/sdk/browser";
|
|
3
3
|
import { CustomSurfaceActionEvent, ReactBridgeState, SpecInteractionChannel, SurfaceRegistry, UiSurfaceActionEvent } from "@webskill/sdk/ui-react";
|
|
4
4
|
import { PageActionPolicy, PagePerceptionPolicy, PerceptionRecord, SkillCandidateSink, TodoItem } from "@webskill/sdk/agent";
|
|
@@ -53,6 +53,10 @@ interface RuntimeLoopConfig {
|
|
|
53
53
|
temperature?: number;
|
|
54
54
|
toolResultMaxBytes: number;
|
|
55
55
|
maxHistoryMessages: number;
|
|
56
|
+
/** `file` 分片的 base64 上限;超出即拒绝并说明,不截断(FR-23.4) */
|
|
57
|
+
maxDocumentBytes: number;
|
|
58
|
+
/** `document-text` 分片的字节上限;同样拒绝而不截断(FR-23.4) */
|
|
59
|
+
maxDocumentTextBytes: number;
|
|
56
60
|
}
|
|
57
61
|
interface RuntimeInteractionConfig {
|
|
58
62
|
missingParams: 'user' | 'llm';
|
|
@@ -74,9 +78,22 @@ interface RuntimeSandboxConfig {
|
|
|
74
78
|
networkPolicy: NetworkPolicy$1;
|
|
75
79
|
capabilities: {
|
|
76
80
|
readReference: CapabilityMode;
|
|
81
|
+
/** 同时管 readAsset 与 readAssetBinary */
|
|
82
|
+
readAsset: CapabilityMode;
|
|
77
83
|
writeArtifact: CapabilityMode;
|
|
78
84
|
confirm: CapabilityMode;
|
|
85
|
+
/**
|
|
86
|
+
* 脚本按宿主声明的数据源取数(分册 16)。
|
|
87
|
+
* 与 `readAsset` **相反**,缺省 `false`:它会出网,缺省开等于每个技能默认拿到出站能力。
|
|
88
|
+
*/
|
|
89
|
+
fetchData: CapabilityMode;
|
|
79
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* 单次取数结果的字节上限(分册 16)。超出即拒绝,**不截断**
|
|
93
|
+
* ——截断后的 JSON 解不出来,比拒绝更糟。结果回到脚本,不进模型上下文,
|
|
94
|
+
* 所以不受 `toolResultMaxBytes` 约束。
|
|
95
|
+
*/
|
|
96
|
+
maxDataSourceBytes: number;
|
|
80
97
|
/**
|
|
81
98
|
* 出站 URL 准入策略(`RemoteUrlPolicy` 的可配置部分):技能安装、MCP 端点连接
|
|
82
99
|
* 这类由宿主发起的取数都按它判定。两项都默认关,即 https-only 且拒绝内网/环回。
|
|
@@ -189,6 +206,17 @@ interface RuntimeAppearanceConfig {
|
|
|
189
206
|
* 两者都会把图像随请求外发给模型提供方,属新增攻击面。
|
|
190
207
|
* @experimental
|
|
191
208
|
*/
|
|
209
|
+
/**
|
|
210
|
+
* 文档投放面(0.11.0 分册 18)。
|
|
211
|
+
*
|
|
212
|
+
* **只有一个闸门字段**。CSP 白名单不在这里:它由 viewer 路由的**响应头**
|
|
213
|
+
* 下发(FR-18.3 第 1 条),是宿主部署时调 `viewerCspHeader` 的入参;
|
|
214
|
+
* 浏览器侧的运行时配置改不动已经发出去的响应头,携在这里只会是个不生效的假开关。
|
|
215
|
+
*/
|
|
216
|
+
interface RuntimeDocumentSurfaceConfig {
|
|
217
|
+
/** 关着即没有这个投放面;开启还要求宿主额外提供一条 viewer 路由 */
|
|
218
|
+
enabled: boolean;
|
|
219
|
+
}
|
|
192
220
|
interface RuntimeMultimodalConfig {
|
|
193
221
|
imageAttachments: boolean;
|
|
194
222
|
/** 页面图像抓取总开关(FR-12.3);关时感知只走纯文本路径 */
|
|
@@ -239,6 +267,7 @@ interface RuntimeConfig {
|
|
|
239
267
|
security: RuntimeSecurityConfig;
|
|
240
268
|
appearance: RuntimeAppearanceConfig;
|
|
241
269
|
multimodal: RuntimeMultimodalConfig;
|
|
270
|
+
documentSurface: RuntimeDocumentSurfaceConfig;
|
|
242
271
|
userProfile: RuntimeUserProfileConfig;
|
|
243
272
|
skillState: RuntimeSkillStateConfig;
|
|
244
273
|
/** 被用户删掉的自动模型条目 id(FR-14.3):删一次就不该再自己长回来 */
|
|
@@ -289,7 +318,7 @@ declare function createMemoryRuntimeConfigStore(initial?: Partial<RuntimeConfig>
|
|
|
289
318
|
//#endregion
|
|
290
319
|
//#region src/core/attachmentKind.d.ts
|
|
291
320
|
/** 附件在模型侧的内容形态(0.6.0 FR-11.2) @experimental */
|
|
292
|
-
type ChatAttachmentKind = 'text' | 'image' | 'file';
|
|
321
|
+
type ChatAttachmentKind = 'text' | 'image' | 'file' | 'document-text';
|
|
293
322
|
//#endregion
|
|
294
323
|
//#region src/core/types.d.ts
|
|
295
324
|
/**
|
|
@@ -387,6 +416,8 @@ interface ChatRunPhase {
|
|
|
387
416
|
endedAt?: number;
|
|
388
417
|
/** 由结构化 `LifecycleEvent.data` 派生的一句摘要 */
|
|
389
418
|
note?: string;
|
|
419
|
+
/** fail 相位的具体说明:`reason` 只有七种取值,说不出「哪个上限、哪个模型」 */
|
|
420
|
+
detail?: string;
|
|
390
421
|
}
|
|
391
422
|
/** 本轮发生的一次已提交交互(FR-17.8:提交后表单保留所填值) @experimental */
|
|
392
423
|
interface ChatInteractionRecord {
|
|
@@ -630,7 +661,8 @@ interface ChatbotConfig {
|
|
|
630
661
|
quickPrompts?: string[];
|
|
631
662
|
/**
|
|
632
663
|
* 开启后模型多一个 `render_ui` 工具,可面向 AI Component Catalog 直接生成声明式 UI。
|
|
633
|
-
* 默认关:工具描述 + 入参 schema 约
|
|
664
|
+
* 默认关:工具描述 + 入参 schema 约 34 KB,会计入每一次请求。
|
|
665
|
+
* 数字的单一来源是 `@webskill/ui` 的 `catalog/budget.ts`(实测终态 12 744 + 21 470)。
|
|
634
666
|
*
|
|
635
667
|
* 接了 `runtimeConfig` 时以 `RuntimeConfig.agentCapabilities.generativeUi` 为准
|
|
636
668
|
* (设置抽屉里的开关就是它),本字段只在未接配置存储的宿主上生效。
|
|
@@ -649,6 +681,14 @@ interface ChatbotConfig {
|
|
|
649
681
|
* `SKILL_GENERATION_DISABLED`,不弹确认框、不产生候选。
|
|
650
682
|
*/
|
|
651
683
|
skillCandidates?: SkillCandidateSink;
|
|
684
|
+
/**
|
|
685
|
+
* 宿主声明的数据源取数入口(分册 16):透传给 `ChatEngineOptions.fetchData`。
|
|
686
|
+
* 不注入即脚本上下文没有 `fetchData` 这个键。
|
|
687
|
+
*
|
|
688
|
+
* **必须是稳定引用**(模块级或 `useMemo`):它进 `ChatEngine` 的 `useMemo`
|
|
689
|
+
* 依赖表,每次渲染新建一个箭头函数会把整个引擎重建掉。
|
|
690
|
+
*/
|
|
691
|
+
fetchData?: (sourceId: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
652
692
|
}
|
|
653
693
|
//#endregion
|
|
654
694
|
//#region src/core/hostAdapter.d.ts
|
|
@@ -685,9 +725,33 @@ interface ChatbotHostAdapter {
|
|
|
685
725
|
* @experimental
|
|
686
726
|
*/
|
|
687
727
|
pageActions?: PageActionPolicy;
|
|
728
|
+
/**
|
|
729
|
+
* 读页面链接指向的文档(分册 22)。实现住在 `@webskill/browser`,
|
|
730
|
+
* 而 chatbot 不依赖它 —— 与 `pagePerception` 同一条装配规矩:宿主注入。
|
|
731
|
+
* 不注入即 `read_linked_document` 不注册。
|
|
732
|
+
*/
|
|
733
|
+
linkedDocuments?: LinkedDocumentReader;
|
|
734
|
+
/** docx → 文本(`extractDocxText`);不注入即 Word 文档明确报「本环境不支持」 */
|
|
735
|
+
docxExtractor?: DocxTextExtractor;
|
|
736
|
+
/** 文档读取留痕出口(FR-22.6) */
|
|
737
|
+
documentAudit?: {
|
|
738
|
+
append(event: {
|
|
739
|
+
type: string;
|
|
740
|
+
target: string;
|
|
741
|
+
data?: Record<string, unknown>;
|
|
742
|
+
}): Promise<unknown>;
|
|
743
|
+
};
|
|
688
744
|
}
|
|
689
745
|
//#endregion
|
|
690
746
|
//#region src/core/chatEngine.d.ts
|
|
747
|
+
/**
|
|
748
|
+
* 条目能否真的发请求:云端要有端点或密钥,浏览器内置两者都不需要。
|
|
749
|
+
*
|
|
750
|
+
* 导出给 UI:选择器不用同一份判据的话,用户能选中一个空配置条目,
|
|
751
|
+
* 而引擎静默回退到另一条——界面说在用 A、实际跑的是 B(UI-UX8 D1)。
|
|
752
|
+
* @experimental
|
|
753
|
+
*/
|
|
754
|
+
declare const isLlmEntryUsable: (entry: RuntimeLlmEntry) => boolean;
|
|
691
755
|
/**
|
|
692
756
|
* 选中条目 → 默认条目 → 首条;命中不可用条目时**回退到下一个可用条目**
|
|
693
757
|
* (0.10.0 复核:选中项失效时宁可静默换用可用模型,也不能把 UI 锁死成
|
|
@@ -742,6 +806,14 @@ interface ChatEngineOptions {
|
|
|
742
806
|
generativeUi?: boolean;
|
|
743
807
|
/** 沙箱执行器替换点(测试注入 spy 断言构造参数;缺省 BrowserWorkerScriptExecutor) */
|
|
744
808
|
executorFactory?: (deps: SandboxExecutorDeps) => ScriptExecutor;
|
|
809
|
+
/**
|
|
810
|
+
* 宿主声明的数据源取数入口(分册 16)。不注入即脚本上下文没有 `fetchData` 这个键。
|
|
811
|
+
*
|
|
812
|
+
* 装配点必须在宿主:策略本体 `DataSourcePolicy` 住在 `@webskill/agent`,
|
|
813
|
+
* 而数据源的目标地址是宿主自己的业务知识,chatbot 无从代为声明。
|
|
814
|
+
* 能力开关 `sandbox.capabilities.fetchData` 缺省关,注入了也还要宿主在配置里打开。
|
|
815
|
+
*/
|
|
816
|
+
fetchData?: (sourceId: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
745
817
|
/**
|
|
746
818
|
* 会话落盘替换点(缺省 `FsSessionStore`,落在 `<chatRoot>/sessions`)。
|
|
747
819
|
* 宕主换自己的实现(如 IndexedDB)与测试统计端口读写量都走这里。
|
|
@@ -1169,8 +1241,10 @@ declare const chatbotDictionary: {
|
|
|
1169
1241
|
'composer.attachment.kind.text': string;
|
|
1170
1242
|
'composer.attachment.kind.image': string;
|
|
1171
1243
|
'composer.attachment.kind.file': string;
|
|
1244
|
+
'composer.attachment.kind.document-text': string;
|
|
1172
1245
|
'composer.attachment.compressed': string;
|
|
1173
1246
|
'composer.model': string;
|
|
1247
|
+
'composer.model.unconfigured': string;
|
|
1174
1248
|
'composer.model.demo': string;
|
|
1175
1249
|
'composer.noModel.title': string;
|
|
1176
1250
|
'composer.noModel.description': string;
|
|
@@ -1506,8 +1580,10 @@ declare const chatbotDictionary: {
|
|
|
1506
1580
|
'composer.attachment.kind.text': string;
|
|
1507
1581
|
'composer.attachment.kind.image': string;
|
|
1508
1582
|
'composer.attachment.kind.file': string;
|
|
1583
|
+
'composer.attachment.kind.document-text': string;
|
|
1509
1584
|
'composer.attachment.compressed': string;
|
|
1510
1585
|
'composer.model': string;
|
|
1586
|
+
'composer.model.unconfigured': string;
|
|
1511
1587
|
'composer.model.demo': string;
|
|
1512
1588
|
'composer.noModel.title': string;
|
|
1513
1589
|
'composer.noModel.description': string;
|
|
@@ -1846,8 +1922,10 @@ declare const useT: () => TranslateFn<{
|
|
|
1846
1922
|
'composer.attachment.kind.text': string;
|
|
1847
1923
|
'composer.attachment.kind.image': string;
|
|
1848
1924
|
'composer.attachment.kind.file': string;
|
|
1925
|
+
'composer.attachment.kind.document-text': string;
|
|
1849
1926
|
'composer.attachment.compressed': string;
|
|
1850
1927
|
'composer.model': string;
|
|
1928
|
+
'composer.model.unconfigured': string;
|
|
1851
1929
|
'composer.model.demo': string;
|
|
1852
1930
|
'composer.noModel.title': string;
|
|
1853
1931
|
'composer.noModel.description': string;
|
|
@@ -2183,8 +2261,10 @@ declare const useT: () => TranslateFn<{
|
|
|
2183
2261
|
'composer.attachment.kind.text': string;
|
|
2184
2262
|
'composer.attachment.kind.image': string;
|
|
2185
2263
|
'composer.attachment.kind.file': string;
|
|
2264
|
+
'composer.attachment.kind.document-text': string;
|
|
2186
2265
|
'composer.attachment.compressed': string;
|
|
2187
2266
|
'composer.model': string;
|
|
2267
|
+
'composer.model.unconfigured': string;
|
|
2188
2268
|
'composer.model.demo': string;
|
|
2189
2269
|
'composer.noModel.title': string;
|
|
2190
2270
|
'composer.noModel.description': string;
|
|
@@ -2598,6 +2678,6 @@ declare function ErrorCard({ code, message, loopLimits, onOpenSettings, onDismis
|
|
|
2598
2678
|
* Version of the published `@webskill/chatbot` package, injected at build time.
|
|
2599
2679
|
* @stable
|
|
2600
2680
|
*/
|
|
2601
|
-
declare const CHATBOT_VERSION = "0.
|
|
2681
|
+
declare const CHATBOT_VERSION = "0.8.0";
|
|
2602
2682
|
//#endregion
|
|
2603
|
-
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 ChatThinking, type ChatTokenUsage, 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, pickUsableLlmEntry, probeA2uiAvailability, probeOpenUiAvailability, sandboxExecutorDeps, useT };
|
|
2683
|
+
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 ChatThinking, type ChatTokenUsage, 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, isLlmEntryUsable, pickUsableLlmEntry, probeA2uiAvailability, probeOpenUiAvailability, sandboxExecutorDeps, useT };
|
package/dist/index.js
CHANGED
|
@@ -7678,7 +7678,7 @@ function SheetContent({ children, className = "", side = "right", title, size, h
|
|
|
7678
7678
|
const gutterClass = side === "left" ? "left-full" : "right-full";
|
|
7679
7679
|
return /* @__PURE__ */ jsxs(DialogPortal, {
|
|
7680
7680
|
container: usePortalContainer(),
|
|
7681
|
-
children: [/* @__PURE__ */ jsx(DialogOverlay, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-
|
|
7681
|
+
children: [/* @__PURE__ */ jsx(DialogOverlay, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-scrim backdrop-blur-[1px]" }), /* @__PURE__ */ jsxs(DialogContent, {
|
|
7682
7682
|
className: `webskill-sheet-content fixed z-[var(--webskill-z-sheet)] flex flex-col bg-surface text-ink shadow-pop outline-none ${positionClass} ${className}`,
|
|
7683
7683
|
style: size === void 0 ? style : {
|
|
7684
7684
|
...style,
|
|
@@ -7730,7 +7730,7 @@ function Dialog({ open, onClose, title, description, footer, hideCloseButton = f
|
|
|
7730
7730
|
onOpenChange: (nextOpen) => !nextOpen && onClose(),
|
|
7731
7731
|
children: /* @__PURE__ */ jsxs(DialogPortal, {
|
|
7732
7732
|
container: usePortalContainer(),
|
|
7733
|
-
children: [/* @__PURE__ */ jsx(DialogOverlay, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-
|
|
7733
|
+
children: [/* @__PURE__ */ jsx(DialogOverlay, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-scrim" }), /* @__PURE__ */ jsxs(DialogContent, {
|
|
7734
7734
|
className: `webskill-dialog-content fixed top-1/2 left-1/2 z-[var(--webskill-z-dialog)] flex max-h-[calc(100dvh-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-card border border-border bg-surface shadow-pop outline-none max-sm:top-0 max-sm:left-0 max-sm:h-dvh max-sm:max-h-dvh max-sm:translate-x-0 max-sm:translate-y-0 max-sm:rounded-none ${className}`,
|
|
7735
7735
|
...size !== void 0 ? { style: { "--webskill-dialog-width": DIALOG_WIDTHS[size] } } : {},
|
|
7736
7736
|
children: [
|
|
@@ -12014,7 +12014,7 @@ function AlertDialog({ open, title, description, footer, className = "", size, c
|
|
|
12014
12014
|
open,
|
|
12015
12015
|
children: /* @__PURE__ */ jsxs(Portal2, {
|
|
12016
12016
|
container: usePortalContainer(),
|
|
12017
|
-
children: [/* @__PURE__ */ jsx(Overlay2, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-
|
|
12017
|
+
children: [/* @__PURE__ */ jsx(Overlay2, { className: "fixed inset-0 z-[var(--webskill-z-scrim)] bg-scrim" }), /* @__PURE__ */ jsxs(Content2, {
|
|
12018
12018
|
onEscapeKeyDown: (event) => event.preventDefault(),
|
|
12019
12019
|
className: `webskill-dialog-content fixed top-1/2 left-1/2 z-[var(--webskill-z-dialog)] flex max-h-[calc(100dvh-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col rounded-card border border-border bg-surface shadow-pop outline-none ${className}`,
|
|
12020
12020
|
...size !== void 0 ? { style: { "--webskill-dialog-width": DIALOG_WIDTHS[size] } } : {},
|
|
@@ -43213,6 +43213,39 @@ const fadeInUp = {
|
|
|
43213
43213
|
}
|
|
43214
43214
|
};
|
|
43215
43215
|
|
|
43216
|
+
//#endregion
|
|
43217
|
+
//#region ../runtime/src/tools/types.ts
|
|
43218
|
+
/**
|
|
43219
|
+
* `file` 分片的上限(FR-23.4),量的是**实际上线的 base64 长度**而不是解码后的字节——
|
|
43220
|
+
* provider 的限额算的是请求载荷。
|
|
43221
|
+
*
|
|
43222
|
+
* 2026-08-14 查证的三家上限:
|
|
43223
|
+
* | provider | 上限 | 出处 |
|
|
43224
|
+
* | --------- | --------------------------------------- | ----------------------- |
|
|
43225
|
+
* | Anthropic | **32 MB**(**整个请求载荷**)、600 页 | PDF support / 请求大小 |
|
|
43226
|
+
* | OpenAI | 单文件 50 MB,全部文件合计 50 MB | File inputs / 使用须知 |
|
|
43227
|
+
* | Gemini | 50 MB 或 1000 页(内联与 Files API 同) | 文档理解 / 技术详情 |
|
|
43228
|
+
*
|
|
43229
|
+
* 取最小值 Anthropic 的 32 MB。它是**整个请求**的额度,不是文档单独的额度,
|
|
43230
|
+
* 所以再留出余量给系统提示词、catalog(约 34 KB)、历史消息与其余分片。
|
|
43231
|
+
* 25 000 KB base64 ≈ 18.75 MB 原始 PDF。取 1024 的整数倍:设置界面按 KB 展示,
|
|
43232
|
+
* 十进制的 24 000 000 会显示成 23437.5 这种读不出来的数。
|
|
43233
|
+
*/
|
|
43234
|
+
const DEFAULT_MAX_DOCUMENT_BYTES = 256e5;
|
|
43235
|
+
/**
|
|
43236
|
+
* `document-text` 分片的上限(FR-23.4)。
|
|
43237
|
+
*
|
|
43238
|
+
* 约束来自**上下文窗口**而不是请求大小:抽出来的文本要整段进上下文。
|
|
43239
|
+
* 按英文约 4 字节/token 折算,500 KB ≈ 128K token,占 200K 窗口的多半,
|
|
43240
|
+
* 给历史消息与模型的回答留下其余。
|
|
43241
|
+
*/
|
|
43242
|
+
const DEFAULT_MAX_DOCUMENT_TEXT_BYTES = 512e3;
|
|
43243
|
+
/**
|
|
43244
|
+
* 单次 fetchData 结果的字节上限(分册 16,FR-16.6):1000 KB。
|
|
43245
|
+
* 结构化数据不是文档,量级差一个数量级;超出**只拒不截**——截断的 JSON 解不出来。
|
|
43246
|
+
*/
|
|
43247
|
+
const DEFAULT_MAX_DATA_SOURCE_BYTES = 1024e3;
|
|
43248
|
+
|
|
43216
43249
|
//#endregion
|
|
43217
43250
|
//#region ../runtime/src/engine/limits.ts
|
|
43218
43251
|
/**
|
|
@@ -43256,7 +43289,9 @@ function defaultRuntimeConfig() {
|
|
|
43256
43289
|
loop: {
|
|
43257
43290
|
...DEFAULT_LOOP_LIMITS$1,
|
|
43258
43291
|
toolResultMaxBytes: 256e3,
|
|
43259
|
-
maxHistoryMessages: 100
|
|
43292
|
+
maxHistoryMessages: 100,
|
|
43293
|
+
maxDocumentBytes: DEFAULT_MAX_DOCUMENT_BYTES,
|
|
43294
|
+
maxDocumentTextBytes: DEFAULT_MAX_DOCUMENT_TEXT_BYTES
|
|
43260
43295
|
},
|
|
43261
43296
|
interaction: {
|
|
43262
43297
|
missingParams: "user",
|
|
@@ -43276,9 +43311,12 @@ function defaultRuntimeConfig() {
|
|
|
43276
43311
|
networkPolicy: "deny-all",
|
|
43277
43312
|
capabilities: {
|
|
43278
43313
|
readReference: true,
|
|
43314
|
+
readAsset: true,
|
|
43279
43315
|
writeArtifact: true,
|
|
43280
|
-
confirm: true
|
|
43316
|
+
confirm: true,
|
|
43317
|
+
fetchData: false
|
|
43281
43318
|
},
|
|
43319
|
+
maxDataSourceBytes: DEFAULT_MAX_DATA_SOURCE_BYTES,
|
|
43282
43320
|
remoteUrl: {
|
|
43283
43321
|
allowHttp: false,
|
|
43284
43322
|
allowPrivateHosts: false
|
|
@@ -43306,9 +43344,10 @@ function defaultRuntimeConfig() {
|
|
|
43306
43344
|
maxImageBytes: 10 * 1024 * 1024,
|
|
43307
43345
|
maxImagesPerMessage: 5
|
|
43308
43346
|
},
|
|
43347
|
+
documentSurface: { enabled: false },
|
|
43309
43348
|
userProfile: {
|
|
43310
43349
|
enabled: false,
|
|
43311
|
-
injectMaxBytes:
|
|
43350
|
+
injectMaxBytes: 4096,
|
|
43312
43351
|
recordLimit: 500,
|
|
43313
43352
|
encrypted: true
|
|
43314
43353
|
},
|
|
@@ -43394,6 +43433,7 @@ function mergeRuntimeConfigDefaults(partial) {
|
|
|
43394
43433
|
security: sub("security", d.security),
|
|
43395
43434
|
appearance: mergeAppearance(p["appearance"], d.appearance),
|
|
43396
43435
|
multimodal: mergeMultimodal(p["multimodal"], d.multimodal),
|
|
43436
|
+
documentSurface: mergeDocumentSurface(p["documentSurface"], d.documentSurface),
|
|
43397
43437
|
userProfile: mergeUserProfile(p["userProfile"], d.userProfile),
|
|
43398
43438
|
skillState: mergeSkillState(p["skillState"], d.skillState),
|
|
43399
43439
|
dismissedAutoEntries: readStringList$1(p["dismissedAutoEntries"], [])
|
|
@@ -43429,6 +43469,14 @@ function mergeMultimodal(raw, d) {
|
|
|
43429
43469
|
maxImagesPerMessage: positive(p["maxImagesPerMessage"], d.maxImagesPerMessage)
|
|
43430
43470
|
};
|
|
43431
43471
|
}
|
|
43472
|
+
/**
|
|
43473
|
+
* CSP 白名单只收字符串数组;存储被污染时回退默认值(空),
|
|
43474
|
+
* **不能**把非法值原样带进 CSP —— `viewerCspHeader` 会抛,等于整条投放面瘫掉。
|
|
43475
|
+
*/
|
|
43476
|
+
function mergeDocumentSurface(raw, d) {
|
|
43477
|
+
const p = typeof raw === "object" && raw !== null ? raw : {};
|
|
43478
|
+
return { enabled: typeof p["enabled"] === "boolean" ? p["enabled"] : d.enabled };
|
|
43479
|
+
}
|
|
43432
43480
|
/** 与 multimodal 同一套判据:非正数上限会让记录/注入通道恒空,回退默认值 */
|
|
43433
43481
|
function mergeUserProfile(raw, d) {
|
|
43434
43482
|
const p = typeof raw === "object" && raw !== null ? raw : {};
|
|
@@ -43563,6 +43611,8 @@ function createMemoryRuntimeConfigStore(initial) {
|
|
|
43563
43611
|
/**
|
|
43564
43612
|
* 条目未显式标注时:`image` 按「不支持」(推断表覆盖不到私有部署的模型名),
|
|
43565
43613
|
* `tools` 按「支持」(只有显式写 false 才降级,否则升级后的存量配置会突然不能用技能)
|
|
43614
|
+
* `document` 同 `image` 按「不支持」:猜错的代价是把 PDF 发给纯文本模型,
|
|
43615
|
+
* 用户拿到的是 provider 的原始报错(FR-23.5)。
|
|
43566
43616
|
* @experimental
|
|
43567
43617
|
*/
|
|
43568
43618
|
function entryCapabilities(entry) {
|
|
@@ -44134,8 +44184,10 @@ const chatbotDictionary = defineDictionary({
|
|
|
44134
44184
|
"composer.attachment.kind.text": "Text",
|
|
44135
44185
|
"composer.attachment.kind.image": "Image",
|
|
44136
44186
|
"composer.attachment.kind.file": "File",
|
|
44187
|
+
"composer.attachment.kind.document-text": "Doc text",
|
|
44137
44188
|
"composer.attachment.compressed": "Compressed {from} → {to}",
|
|
44138
44189
|
"composer.model": "Model",
|
|
44190
|
+
"composer.model.unconfigured": "Not usable: this entry has no API key or base URL. Configure it in the console.",
|
|
44139
44191
|
"composer.model.demo": "Demo model",
|
|
44140
44192
|
"composer.noModel.title": "No model configured",
|
|
44141
44193
|
"composer.noModel.description": "A large language model has not been configured yet. Configure one on the model settings page before chatting.",
|
|
@@ -44213,7 +44265,7 @@ const chatbotDictionary = defineDictionary({
|
|
|
44213
44265
|
"settings.agent.todo": "Task list",
|
|
44214
44266
|
"settings.agent.todoNote": "Lets the model split a multi-step request into a checklist and report progress.",
|
|
44215
44267
|
"settings.agent.generativeUi": "Generative UI",
|
|
44216
|
-
"settings.agent.generativeUiNote": "Gates only the model’s own render_ui tool: letting the model start a screen on its own, picking the components and layout. Off by default: the component catalogue adds ~
|
|
44268
|
+
"settings.agent.generativeUiNote": "Gates only the model’s own render_ui tool: letting the model start a screen on its own, picking the components and layout. Off by default: the component catalogue adds ~34 KB per request.",
|
|
44217
44269
|
"settings.agent.generativeUiUnaffected": "Turning this off does not hide skill-provided screens, interaction cards, or built-in result blocks.",
|
|
44218
44270
|
"settings.agent.skillGeneration": "Skill generation",
|
|
44219
44271
|
"settings.agent.skillGenerationNote": "Lets the model turn a reusable procedure from this conversation into a skill candidate. You confirm each one, and a reviewer approves it before anyone can use it.",
|
|
@@ -44471,8 +44523,10 @@ const chatbotDictionary = defineDictionary({
|
|
|
44471
44523
|
"composer.attachment.kind.text": "文本",
|
|
44472
44524
|
"composer.attachment.kind.image": "图片",
|
|
44473
44525
|
"composer.attachment.kind.file": "文件",
|
|
44526
|
+
"composer.attachment.kind.document-text": "文档正文",
|
|
44474
44527
|
"composer.attachment.compressed": "已压缩 {from} → {to}",
|
|
44475
44528
|
"composer.model": "模型",
|
|
44529
|
+
"composer.model.unconfigured": "不可用:该条目既没有 API 密钥也没有基础地址,请在控制台补全。",
|
|
44476
44530
|
"composer.model.demo": "演示模型",
|
|
44477
44531
|
"composer.noModel.title": "尚未配置大模型",
|
|
44478
44532
|
"composer.noModel.description": "大模型尚未配置,请先前往大模型配置页面完成配置,再开始对话。",
|
|
@@ -44550,7 +44604,7 @@ const chatbotDictionary = defineDictionary({
|
|
|
44550
44604
|
"settings.agent.todo": "待办清单",
|
|
44551
44605
|
"settings.agent.todoNote": "允许模型把多步骤任务拆成清单,并在执行中回报进度。",
|
|
44552
44606
|
"settings.agent.generativeUi": "生成式 UI",
|
|
44553
|
-
"settings.agent.generativeUiNote": "仅控制模型自己的 render_ui 工具:允许模型自行发起界面、自选组件与布局。默认关闭:组件目录会给每次请求增加约
|
|
44607
|
+
"settings.agent.generativeUiNote": "仅控制模型自己的 render_ui 工具:允许模型自行发起界面、自选组件与布局。默认关闭:组件目录会给每次请求增加约 34 KB。",
|
|
44554
44608
|
"settings.agent.generativeUiUnaffected": "关掉它不会隐藏技能自带的界面、交互卡,以及内建的结果块。",
|
|
44555
44609
|
"settings.agent.skillGeneration": "技能自动生成",
|
|
44556
44610
|
"settings.agent.skillGenerationNote": "允许模型把本次对话里可复用的做法整理成技能候选。每个候选都需你当场确认,且经审核通过后才能被使用。",
|
|
@@ -44657,7 +44711,7 @@ const DISPLAY_PHASE = {
|
|
|
44657
44711
|
* 归并后追加一个相位;同相位连续到达时返回原数组本身,
|
|
44658
44712
|
* 调用方据引用相等判断「没变化」,不必再做深比较。
|
|
44659
44713
|
*/
|
|
44660
|
-
function appendRunPhase(phases, phase, at, note) {
|
|
44714
|
+
function appendRunPhase(phases, phase, at, note, detail) {
|
|
44661
44715
|
const display = DISPLAY_PHASE[phase];
|
|
44662
44716
|
const last = phases.at(-1);
|
|
44663
44717
|
if (last?.phase === display) return phases;
|
|
@@ -44667,7 +44721,8 @@ function appendRunPhase(phases, phase, at, note) {
|
|
|
44667
44721
|
}] : [], {
|
|
44668
44722
|
phase: display,
|
|
44669
44723
|
at,
|
|
44670
|
-
...note !== void 0 ? { note } : {}
|
|
44724
|
+
...note !== void 0 ? { note } : {},
|
|
44725
|
+
...detail !== void 0 ? { detail } : {}
|
|
44671
44726
|
}];
|
|
44672
44727
|
}
|
|
44673
44728
|
/** 相位摘要:唯一读 `data` 的地方,此处事件还带着 `phase` 判别,下游不必再猜键名 */
|
|
@@ -44681,6 +44736,10 @@ function phaseNote(event) {
|
|
|
44681
44736
|
default: return;
|
|
44682
44737
|
}
|
|
44683
44738
|
}
|
|
44739
|
+
/** 失败相位的具体说明(`reason` 之外的那句话)。只有 fail 有,其余相位一律 undefined。 */
|
|
44740
|
+
function phaseDetail(event) {
|
|
44741
|
+
return event.phase === "fail" ? event.data.detail : void 0;
|
|
44742
|
+
}
|
|
44684
44743
|
|
|
44685
44744
|
//#endregion
|
|
44686
44745
|
//#region src/core/title.ts
|
|
@@ -44794,8 +44853,10 @@ const CHATBOT_PROFILE_USER_ID = "local";
|
|
|
44794
44853
|
* 终止原因 → 稳定错误码(FR-21.2)。不再全部压平为 RUN_FAILED:
|
|
44795
44854
|
* “跑超时了”与“模型没配对”对用户是两件事,得给不同的下一步。
|
|
44796
44855
|
*/
|
|
44797
|
-
const runFailureCode = (
|
|
44798
|
-
|
|
44856
|
+
const runFailureCode = (run) => {
|
|
44857
|
+
const traced = ((run.trace?.find((event) => event.type === "run.failed"))?.data)?.code;
|
|
44858
|
+
if (typeof traced === "string") return traced;
|
|
44859
|
+
switch (run.terminationReason) {
|
|
44799
44860
|
case "timeout": return "RUN_TIMEOUT";
|
|
44800
44861
|
case "interaction-timeout": return "RUN_INTERACTION_TIMEOUT";
|
|
44801
44862
|
case "max-turns": return "RUN_MAX_TURNS_EXCEEDED";
|
|
@@ -44865,8 +44926,14 @@ const SANDBOX_MODE = {
|
|
|
44865
44926
|
"blob-worker": "worker",
|
|
44866
44927
|
"iframe-sandbox": "iframe"
|
|
44867
44928
|
};
|
|
44868
|
-
/**
|
|
44869
|
-
|
|
44929
|
+
/**
|
|
44930
|
+
* 条目能否真的发请求:云端要有端点或密钥,浏览器内置两者都不需要。
|
|
44931
|
+
*
|
|
44932
|
+
* 导出给 UI:选择器不用同一份判据的话,用户能选中一个空配置条目,
|
|
44933
|
+
* 而引擎静默回退到另一条——界面说在用 A、实际跑的是 B(UI-UX8 D1)。
|
|
44934
|
+
* @experimental
|
|
44935
|
+
*/
|
|
44936
|
+
const isLlmEntryUsable = (entry) => entry.provider === "chrome-builtin" || Boolean(entry.apiKey?.trim()) || Boolean(entry.baseUrl?.trim());
|
|
44870
44937
|
/**
|
|
44871
44938
|
* 选中条目 → 默认条目 → 首条;命中不可用条目时**回退到下一个可用条目**
|
|
44872
44939
|
* (0.10.0 复核:选中项失效时宁可静默换用可用模型,也不能把 UI 锁死成
|
|
@@ -44883,7 +44950,7 @@ function pickUsableLlmEntry(entries, defaultId, selectedId) {
|
|
|
44883
44950
|
byId(selectedId),
|
|
44884
44951
|
byId(defaultId),
|
|
44885
44952
|
...entries
|
|
44886
|
-
].find((entry) => entry !== void 0 &&
|
|
44953
|
+
].find((entry) => entry !== void 0 && isLlmEntryUsable(entry));
|
|
44887
44954
|
}
|
|
44888
44955
|
/** 选中条目 → 默认条目 → 首条;都没有则返回 undefined(走内置演示) */
|
|
44889
44956
|
function pickLlmEntry(rc, selectedId) {
|
|
@@ -45401,12 +45468,13 @@ var ChatEngine = class {
|
|
|
45401
45468
|
for (const attachment of attachments) {
|
|
45402
45469
|
const path = `${this.attachmentsRoot}/${attachment.path}`;
|
|
45403
45470
|
if (!await this.#adapter.storage.exists(path)) continue;
|
|
45404
|
-
if (attachment.kind === "text") {
|
|
45471
|
+
if (attachment.kind === "text" || attachment.kind === "document-text") {
|
|
45405
45472
|
const body = await this.#adapter.storage.readText(path);
|
|
45406
45473
|
const clipped = body.length > ATTACHMENT_TEXT_LIMIT ? `${body.slice(0, ATTACHMENT_TEXT_LIMIT)}\n[truncated]` : body;
|
|
45474
|
+
const label = attachment.kind === "document-text" ? `${attachment.name} (${attachment.contentType}, body text only)` : `${attachment.name} (${attachment.contentType})`;
|
|
45407
45475
|
parts.push({
|
|
45408
45476
|
type: "text",
|
|
45409
|
-
text: `--- Attachment: ${
|
|
45477
|
+
text: `--- Attachment: ${label} ---\n${clipped}`
|
|
45410
45478
|
});
|
|
45411
45479
|
continue;
|
|
45412
45480
|
}
|
|
@@ -45727,6 +45795,7 @@ var ChatEngine = class {
|
|
|
45727
45795
|
toolTimeoutMs: rc.loop.toolTimeoutMs,
|
|
45728
45796
|
...rc.loop.temperature !== void 0 ? { temperature: rc.loop.temperature } : {},
|
|
45729
45797
|
toolResultMaxBytes: rc.loop.toolResultMaxBytes,
|
|
45798
|
+
remoteUrl: rc.sandbox.remoteUrl,
|
|
45730
45799
|
...rc.renderResult ? {} : { renderResult: "off" }
|
|
45731
45800
|
} : {},
|
|
45732
45801
|
...entryCapabilities(pickLlmEntry(rc, this.#selectedModelId)).tools ? {} : { toolCallingDisabled: true },
|
|
@@ -45792,7 +45861,11 @@ var ChatEngine = class {
|
|
|
45792
45861
|
skillProviders: pageSkillSource ? [pageSkillSource] : [],
|
|
45793
45862
|
...this.#governanceDeps(),
|
|
45794
45863
|
...Object.keys(loopConfig).length > 0 ? { config: loopConfig } : {},
|
|
45795
|
-
...model ? { model } : {}
|
|
45864
|
+
...model ? { model } : {},
|
|
45865
|
+
...this.#options.fetchData ? { fetchData: this.#options.fetchData } : {},
|
|
45866
|
+
...this.#adapter.linkedDocuments ? { linkedDocuments: this.#adapter.linkedDocuments } : {},
|
|
45867
|
+
...this.#adapter.docxExtractor ? { docxExtractor: this.#adapter.docxExtractor } : {},
|
|
45868
|
+
...this.#adapter.documentAudit ? { documentAudit: this.#adapter.documentAudit } : {}
|
|
45796
45869
|
};
|
|
45797
45870
|
const runtime = new WebSkillRuntime({
|
|
45798
45871
|
...deps,
|
|
@@ -45827,7 +45900,7 @@ var ChatEngine = class {
|
|
|
45827
45900
|
const toolData = event.phase === "execute" && event.data.kind === "tool" ? event.data : void 0;
|
|
45828
45901
|
if (!toolData) {
|
|
45829
45902
|
const at = Date.parse(event.ts);
|
|
45830
|
-
this.#runPhases.set(event.runId, appendRunPhase(this.#runPhases.get(event.runId) ?? [], event.phase, at, phaseNote(event)));
|
|
45903
|
+
this.#runPhases.set(event.runId, appendRunPhase(this.#runPhases.get(event.runId) ?? [], event.phase, at, phaseNote(event), phaseDetail(event)));
|
|
45831
45904
|
this.#emit({
|
|
45832
45905
|
type: "lifecycle",
|
|
45833
45906
|
runId: event.runId,
|
|
@@ -45939,7 +46012,7 @@ var ChatEngine = class {
|
|
|
45939
46012
|
status,
|
|
45940
46013
|
output: result.output,
|
|
45941
46014
|
activeSkillNames: run.activeSkillNames,
|
|
45942
|
-
...status === "completed" ? {} : { code: runFailureCode(run
|
|
46015
|
+
...status === "completed" ? {} : { code: runFailureCode(run) }
|
|
45943
46016
|
});
|
|
45944
46017
|
this.#emit({
|
|
45945
46018
|
type: "message-complete",
|
|
@@ -46545,7 +46618,10 @@ function terminationParts(phases) {
|
|
|
46545
46618
|
return [{
|
|
46546
46619
|
type: "data",
|
|
46547
46620
|
name: TERMINATION_PART,
|
|
46548
|
-
data: {
|
|
46621
|
+
data: {
|
|
46622
|
+
...last.note !== void 0 ? { reason: last.note } : {},
|
|
46623
|
+
...last.detail !== void 0 ? { detail: last.detail } : {}
|
|
46624
|
+
}
|
|
46549
46625
|
}];
|
|
46550
46626
|
}
|
|
46551
46627
|
/**
|
|
@@ -47138,7 +47214,7 @@ function InteractionWaitBar({ bridge, label, elsewhere = false, panel, onLocate
|
|
|
47138
47214
|
id: INTERACTION_WAIT_ID,
|
|
47139
47215
|
"data-testid": "interaction-wait",
|
|
47140
47216
|
role: "status",
|
|
47141
|
-
className: "mx-auto flex w-full
|
|
47217
|
+
className: "webskill-chat-prose mx-auto flex w-full items-center gap-2 px-4 pt-2 text-xs text-muted",
|
|
47142
47218
|
children: [
|
|
47143
47219
|
/* @__PURE__ */ jsx(Hourglass, {
|
|
47144
47220
|
className: "size-3.5 shrink-0",
|
|
@@ -47290,6 +47366,7 @@ function ModelMenuButton({ models }) {
|
|
|
47290
47366
|
"data-model-option": option.id,
|
|
47291
47367
|
checked: option.id === models.value,
|
|
47292
47368
|
disabled: option.disabled === true,
|
|
47369
|
+
...option.unconfigured === true ? { title: t("composer.model.unconfigured") } : {},
|
|
47293
47370
|
onCheckedChange: () => models.onChange(option.id),
|
|
47294
47371
|
children: /* @__PURE__ */ jsx("span", {
|
|
47295
47372
|
className: "truncate",
|
|
@@ -47314,7 +47391,7 @@ function AssistantUiComposer({ running, disabled = false, waitTarget, placeholde
|
|
|
47314
47391
|
className: "webskill-aui-composer shrink-0 px-4 py-4",
|
|
47315
47392
|
children: /* @__PURE__ */ jsxs(ComposerPrimitive.AttachmentDropzone, {
|
|
47316
47393
|
disabled: !attachments,
|
|
47317
|
-
className: "webskill-aui-composer-shell mx-auto flex w-full
|
|
47394
|
+
className: "webskill-aui-composer-shell webskill-chat-prose mx-auto flex w-full flex-col gap-2 px-3 py-2 transition-colors data-[dragging=true]:border-ring",
|
|
47318
47395
|
children: [
|
|
47319
47396
|
/* @__PURE__ */ jsx("div", {
|
|
47320
47397
|
"aria-label": t("composer.attachments"),
|
|
@@ -47886,18 +47963,29 @@ const TERMINATION_KEY = {
|
|
|
47886
47963
|
/**
|
|
47887
47964
|
* 非正常终态提示(FR-20.5)。停在消息顶层,不进思维链分组——
|
|
47888
47965
|
* 那个容器在 run 结束后自动折叠且折叠时从 DOM 卸载,提示放进去等于没提示(裁决 D-9)。
|
|
47966
|
+
*
|
|
47967
|
+
* `reason` 只有七种取值,说不出「哪个上限、哪个模型、本轮带了文档」——
|
|
47968
|
+
* 那句话在 `RuntimeRun.error.message` 里,此前被整个丢掉(UI-UX8 D15)。
|
|
47889
47969
|
*/
|
|
47890
47970
|
function TerminationNotice({ data }) {
|
|
47891
47971
|
const t = useT();
|
|
47892
47972
|
const reason = readString(data, "reason");
|
|
47973
|
+
const detail = readString(data, "detail");
|
|
47893
47974
|
const key = reason !== void 0 && reason in TERMINATION_KEY ? TERMINATION_KEY[reason] : "run.terminated.unknown";
|
|
47894
|
-
return /* @__PURE__ */ jsxs("
|
|
47975
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
47895
47976
|
"data-webskill-termination": reason ?? "unknown",
|
|
47896
|
-
className: "flex items-
|
|
47977
|
+
className: "flex items-start gap-2 text-xs text-danger",
|
|
47897
47978
|
children: [/* @__PURE__ */ jsx(OctagonX, {
|
|
47898
47979
|
className: "size-3.5 shrink-0",
|
|
47899
47980
|
"aria-hidden": true
|
|
47900
|
-
}), /* @__PURE__ */
|
|
47981
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
47982
|
+
className: "flex min-w-0 flex-col gap-1",
|
|
47983
|
+
children: [/* @__PURE__ */ jsx("span", { children: t(key) }), detail !== void 0 && detail !== "" ? /* @__PURE__ */ jsx("span", {
|
|
47984
|
+
"data-testid": "termination-detail",
|
|
47985
|
+
className: "break-words text-muted",
|
|
47986
|
+
children: detail
|
|
47987
|
+
}) : null]
|
|
47988
|
+
})]
|
|
47901
47989
|
});
|
|
47902
47990
|
}
|
|
47903
47991
|
function ToolGroup({ count, running, children }) {
|
|
@@ -47992,14 +48080,22 @@ function ToolRow({ part }) {
|
|
|
47992
48080
|
]
|
|
47993
48081
|
}), open && (part.argsText !== "" || errorMessage !== void 0) ? /* @__PURE__ */ jsxs("div", {
|
|
47994
48082
|
className: "border-t border-border px-2 py-1.5",
|
|
47995
|
-
children: [errorMessage !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
47996
|
-
|
|
47997
|
-
|
|
47998
|
-
|
|
47999
|
-
|
|
48000
|
-
|
|
48001
|
-
|
|
48002
|
-
|
|
48083
|
+
children: [errorMessage !== void 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
48084
|
+
/* @__PURE__ */ jsx("p", {
|
|
48085
|
+
className: "text-xs text-muted italic",
|
|
48086
|
+
children: t(errorCode !== void 0 ? ERROR_TITLE_KEYS[errorCode] ?? "tool.failed.reason" : "tool.failed.reason")
|
|
48087
|
+
}),
|
|
48088
|
+
/* @__PURE__ */ jsx("p", {
|
|
48089
|
+
"data-testid": "tool-error-reason",
|
|
48090
|
+
className: "text-xs break-words text-ink",
|
|
48091
|
+
children: errorMessage
|
|
48092
|
+
}),
|
|
48093
|
+
errorCode !== void 0 ? /* @__PURE__ */ jsx("p", {
|
|
48094
|
+
"data-testid": "tool-error-code",
|
|
48095
|
+
className: "mt-1 font-mono text-xs text-muted",
|
|
48096
|
+
children: errorCode
|
|
48097
|
+
}) : null
|
|
48098
|
+
] }) : null, part.argsText !== "" ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("p", {
|
|
48003
48099
|
className: "text-xs text-muted italic",
|
|
48004
48100
|
children: t("tool.args")
|
|
48005
48101
|
}), /* @__PURE__ */ jsx("pre", {
|
|
@@ -48063,14 +48159,22 @@ function WorkingIndicator() {
|
|
|
48063
48159
|
})
|
|
48064
48160
|
});
|
|
48065
48161
|
}
|
|
48066
|
-
/**
|
|
48162
|
+
/**
|
|
48163
|
+
* data part → 只读交互卡;请求体是落盘原样,畸形数据直接不渲染而不是抛。
|
|
48164
|
+
*
|
|
48165
|
+
* surfaceId 必须掺入 useId:交互 id 是 run 内序号,不同 run 的第一个交互都叫 `int-1`。
|
|
48166
|
+
* 两张 submitted 卡同屏时若直接用 `interaction-${id}`,surfaceForm 的控件 id 与
|
|
48167
|
+
* `<label htmlFor>` 关联会串到另一张卡(UI-UX8 UX-03:把上一张卡的问题念成这张卡的)。
|
|
48168
|
+
* @internal
|
|
48169
|
+
*/
|
|
48067
48170
|
function PersistedInteraction({ data }) {
|
|
48171
|
+
const domId = useId();
|
|
48068
48172
|
const request = data["request"];
|
|
48069
48173
|
const id = readString(data, "id");
|
|
48070
48174
|
if (typeof request !== "object" || request === null || id === void 0) return null;
|
|
48071
48175
|
const values = data["submittedValues"];
|
|
48072
48176
|
return /* @__PURE__ */ jsx(SubmittedInteraction, {
|
|
48073
|
-
surfaceId: `interaction-${id}`,
|
|
48177
|
+
surfaceId: `interaction-${id}-${domId}`,
|
|
48074
48178
|
request,
|
|
48075
48179
|
...values === void 0 ? {} : { submittedValues: values }
|
|
48076
48180
|
});
|
|
@@ -58627,10 +58731,13 @@ function WebSkillMessageExtensions({ message, onDownload, surfaceRegistry, rende
|
|
|
58627
58731
|
runId: message.runId ?? "",
|
|
58628
58732
|
...onDownload ? { onDownload } : {}
|
|
58629
58733
|
}) : null,
|
|
58630
|
-
renderable.length > 0 ? /* @__PURE__ */ jsx(
|
|
58631
|
-
|
|
58632
|
-
|
|
58633
|
-
|
|
58734
|
+
renderable.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
58735
|
+
className: "webskill-chat-surface-wide",
|
|
58736
|
+
children: /* @__PURE__ */ jsx(HistoricalSurfaces, {
|
|
58737
|
+
snapshots: renderable,
|
|
58738
|
+
...renderer ? { renderer } : {},
|
|
58739
|
+
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
58740
|
+
})
|
|
58634
58741
|
}) : null,
|
|
58635
58742
|
renderable.length < surfaces.length ? /* @__PURE__ */ jsx("p", {
|
|
58636
58743
|
"data-testid": "legacy-surface-placeholder",
|
|
@@ -58833,6 +58940,14 @@ const IMAGE_MIME_SET = new Set(IMAGE_MIME_TYPES);
|
|
|
58833
58940
|
/** 非文本非图片但仍可整体外发的类型(provider 的 file 分片) */
|
|
58834
58941
|
const FILE_MIME_TYPES = ["application/pdf"];
|
|
58835
58942
|
const FILE_MIME_SET = new Set(FILE_MIME_TYPES);
|
|
58943
|
+
/**
|
|
58944
|
+
* 需要**客户端先抽取成文本**才能外发的类型(FR-23.9)。
|
|
58945
|
+
* 不走直通的 `file`:docx 发给 provider 会被当成二进制垃圾。
|
|
58946
|
+
*/
|
|
58947
|
+
const EXTRACTED_MIME_TYPES = ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
|
|
58948
|
+
const EXTRACTED_MIME_SET = new Set(EXTRACTED_MIME_TYPES);
|
|
58949
|
+
const EXTRACTED_EXTENSIONS = ["docx"];
|
|
58950
|
+
const EXTRACTED_EXTENSION_SET = new Set(EXTRACTED_EXTENSIONS);
|
|
58836
58951
|
function extensionOf(fileName) {
|
|
58837
58952
|
return fileName.split(".").pop()?.toLowerCase() ?? "";
|
|
58838
58953
|
}
|
|
@@ -58840,9 +58955,11 @@ function extensionOf(fileName) {
|
|
|
58840
58955
|
function classifyAttachment(contentType, fileName) {
|
|
58841
58956
|
const type = contentType.toLowerCase();
|
|
58842
58957
|
if (IMAGE_MIME_SET.has(type)) return "image";
|
|
58958
|
+
if (EXTRACTED_MIME_SET.has(type)) return "document-text";
|
|
58843
58959
|
if (FILE_MIME_SET.has(type)) return "file";
|
|
58844
58960
|
if (type.startsWith("text/") || type === "application/json") return "text";
|
|
58845
58961
|
if (type === "" && TEXT_EXTENSION_SET.has(extensionOf(fileName))) return "text";
|
|
58962
|
+
if (type === "" && EXTRACTED_EXTENSION_SET.has(extensionOf(fileName))) return "document-text";
|
|
58846
58963
|
}
|
|
58847
58964
|
const TEXT_ACCEPT = [
|
|
58848
58965
|
"text/plain",
|
|
@@ -58859,6 +58976,7 @@ function attachmentAccept(options) {
|
|
|
58859
58976
|
const parts = [...TEXT_ACCEPT, ...TEXT_EXTENSIONS.map((ext) => `.${ext}`)];
|
|
58860
58977
|
if (options.images) parts.push(...IMAGE_MIME_TYPES);
|
|
58861
58978
|
if (options.files) parts.push(...FILE_MIME_TYPES);
|
|
58979
|
+
if (options.documents) parts.push(...EXTRACTED_MIME_TYPES, ...EXTRACTED_EXTENSIONS.map((ext) => `.${ext}`));
|
|
58862
58980
|
return parts.join(",");
|
|
58863
58981
|
}
|
|
58864
58982
|
|
|
@@ -58891,7 +59009,11 @@ var WebSkillAttachmentAdapter = class {
|
|
|
58891
59009
|
}
|
|
58892
59010
|
/** assistant-ui 每次打开文件选择器都读一次,因此开关与模型能力的变化无需重建适配器 */
|
|
58893
59011
|
get accept() {
|
|
58894
|
-
return attachmentAccept({
|
|
59012
|
+
return attachmentAccept({
|
|
59013
|
+
images: this.#imagesAllowed(),
|
|
59014
|
+
files: true,
|
|
59015
|
+
documents: this.#options.docxExtractor !== void 0
|
|
59016
|
+
});
|
|
58895
59017
|
}
|
|
58896
59018
|
#multimodal() {
|
|
58897
59019
|
return this.#options.multimodal?.() ?? DEFAULT_MULTIMODAL;
|
|
@@ -58905,7 +59027,8 @@ var WebSkillAttachmentAdapter = class {
|
|
|
58905
59027
|
if (kind === "image") {
|
|
58906
59028
|
if (!this.#multimodal().imageAttachments) throw new WebSkillError("ATTACHMENT_TYPE_REJECTED", "Image attachments are turned off. Enable them in settings before sending images.");
|
|
58907
59029
|
if (!(this.#options.imageCapable?.() ?? false)) throw new WebSkillError("MODEL_IMAGE_UNSUPPORTED", "Current model does not support image input. Switch model or remove the image.");
|
|
58908
|
-
} else if (
|
|
59030
|
+
} else if (kind === "document-text" && this.#options.docxExtractor === void 0) throw new WebSkillError("ATTACHMENT_TYPE_REJECTED", "Word documents are not supported in this environment: no docx extractor is wired up.");
|
|
59031
|
+
else if (file.size > MAX_BYTES) throw new WebSkillError("ATTACHMENT_TOO_LARGE", `Attachment "${file.name}" is ${Math.round(file.size / 1024 / 1024)} MB, which exceeds the 10 MB limit`);
|
|
58909
59032
|
const id = `att-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
58910
59033
|
const relative = `${this.#options.sessionId() ?? "pending"}/${id}-${safeName(file.name)}`;
|
|
58911
59034
|
const path = `${this.#options.root}/${relative}`;
|
|
@@ -58946,6 +59069,15 @@ var WebSkillAttachmentAdapter = class {
|
|
|
58946
59069
|
size: file.size
|
|
58947
59070
|
};
|
|
58948
59071
|
}
|
|
59072
|
+
if (kind === "document-text") {
|
|
59073
|
+
const extract = this.#options.docxExtractor;
|
|
59074
|
+
if (extract === void 0) throw new WebSkillError("ATTACHMENT_TYPE_REJECTED", "No docx extractor is wired up in this environment.");
|
|
59075
|
+
await this.#options.storage.writeText(path, await extract(new Uint8Array(await file.arrayBuffer())));
|
|
59076
|
+
return {
|
|
59077
|
+
...base,
|
|
59078
|
+
size: file.size
|
|
59079
|
+
};
|
|
59080
|
+
}
|
|
58949
59081
|
if (kind === "file") {
|
|
58950
59082
|
await this.#options.storage.writeBinary(path, new Uint8Array(await file.arrayBuffer()));
|
|
58951
59083
|
return {
|
|
@@ -59023,7 +59155,7 @@ const start = (runId, at) => ({
|
|
|
59023
59155
|
chunks: 0
|
|
59024
59156
|
});
|
|
59025
59157
|
function appendPhase(live, event) {
|
|
59026
|
-
const next = appendRunPhase(live.phases, event.phase, event.at, phaseNote(event));
|
|
59158
|
+
const next = appendRunPhase(live.phases, event.phase, event.at, phaseNote(event), phaseDetail(event));
|
|
59027
59159
|
return next === live.phases ? live : {
|
|
59028
59160
|
...live,
|
|
59029
59161
|
phases: [...next]
|
|
@@ -59349,6 +59481,13 @@ function ActiveInteractionCard({ request, bridge }) {
|
|
|
59349
59481
|
const pageAction = isAuthorize && request.capability === "pageAction" ? pageActionDetails(request.details) : void 0;
|
|
59350
59482
|
const handleAction = (event) => {
|
|
59351
59483
|
if (event.intent !== "submit") {
|
|
59484
|
+
if (request.type === "confirm" || request.type === "authorize") {
|
|
59485
|
+
bridge.resolve({
|
|
59486
|
+
id: request.id,
|
|
59487
|
+
value: false
|
|
59488
|
+
});
|
|
59489
|
+
return;
|
|
59490
|
+
}
|
|
59352
59491
|
bridge.resolve({
|
|
59353
59492
|
id: request.id,
|
|
59354
59493
|
cancelled: true
|
|
@@ -59820,6 +59959,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59820
59959
|
...config?.hooks ? { hooks: config.hooks } : {},
|
|
59821
59960
|
...config?.governance ? { governance: config.governance } : {},
|
|
59822
59961
|
...config?.skillCandidates ? { skillCandidates: config.skillCandidates } : {},
|
|
59962
|
+
...config?.fetchData ? { fetchData: config.fetchData } : {},
|
|
59823
59963
|
...rendererProp ? { renderer: rendererProp } : {}
|
|
59824
59964
|
}), [
|
|
59825
59965
|
adapter,
|
|
@@ -59831,6 +59971,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59831
59971
|
config?.hooks,
|
|
59832
59972
|
config?.governance,
|
|
59833
59973
|
config?.skillCandidates,
|
|
59974
|
+
config?.fetchData,
|
|
59834
59975
|
rendererProp
|
|
59835
59976
|
]);
|
|
59836
59977
|
useEffect(() => {
|
|
@@ -59928,7 +60069,8 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
59928
60069
|
root: engine.attachmentsRoot,
|
|
59929
60070
|
sessionId: () => sessionRef.current,
|
|
59930
60071
|
multimodal: () => multimodalRef.current,
|
|
59931
|
-
imageCapable: () => imageCapableRef.current
|
|
60072
|
+
imageCapable: () => imageCapableRef.current,
|
|
60073
|
+
...adapter.docxExtractor ? { docxExtractor: adapter.docxExtractor } : {}
|
|
59932
60074
|
}), [adapter, engine]);
|
|
59933
60075
|
useEffect(() => {
|
|
59934
60076
|
let cancelled = false;
|
|
@@ -60000,13 +60142,19 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
60000
60142
|
const composerModels = useMemo(() => {
|
|
60001
60143
|
if (llmSelection.entries.length === 0) return void 0;
|
|
60002
60144
|
const selected = modelId ?? llmSelection.defaultId ?? llmSelection.entries[0]?.id ?? "";
|
|
60145
|
+
const effective = pickUsableLlmEntry(llmSelection.entries, llmSelection.defaultId, modelId)?.id ?? selected;
|
|
60003
60146
|
return {
|
|
60004
|
-
options: llmSelection.entries.map((entry) =>
|
|
60005
|
-
|
|
60006
|
-
|
|
60007
|
-
|
|
60008
|
-
|
|
60009
|
-
|
|
60147
|
+
options: llmSelection.entries.map((entry) => {
|
|
60148
|
+
const builtinUnavailable = entry.provider === "chrome-builtin" && chromeBuiltin?.available === false;
|
|
60149
|
+
const unusable = !isLlmEntryUsable(entry);
|
|
60150
|
+
return {
|
|
60151
|
+
id: entry.id,
|
|
60152
|
+
label: entry.label,
|
|
60153
|
+
...builtinUnavailable || unusable ? { disabled: true } : {},
|
|
60154
|
+
...unusable && !builtinUnavailable ? { unconfigured: true } : {}
|
|
60155
|
+
};
|
|
60156
|
+
}),
|
|
60157
|
+
value: effective,
|
|
60010
60158
|
onChange: (id) => {
|
|
60011
60159
|
setModelId(id);
|
|
60012
60160
|
engine.setModel(id);
|
|
@@ -60356,7 +60504,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
60356
60504
|
})
|
|
60357
60505
|
})
|
|
60358
60506
|
})] }), /* @__PURE__ */ jsxs("div", {
|
|
60359
|
-
className: "flex min-h-0 min-w-0 flex-1 flex-col",
|
|
60507
|
+
className: "webskill-chat-column flex min-h-0 min-w-0 flex-1 flex-col",
|
|
60360
60508
|
children: [
|
|
60361
60509
|
/* @__PURE__ */ jsx(AssistantUiThreadToolbar, {
|
|
60362
60510
|
...config?.title ? { title: config.title } : {},
|
|
@@ -60374,7 +60522,7 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
60374
60522
|
/* @__PURE__ */ jsx(AssistantUiViewport, {
|
|
60375
60523
|
grow: !composerCentered,
|
|
60376
60524
|
children: /* @__PURE__ */ jsxs("div", {
|
|
60377
|
-
className: "mx-auto flex w-full min-w-0
|
|
60525
|
+
className: "webskill-chat-prose mx-auto flex w-full min-w-0 flex-col gap-4 px-4 py-6",
|
|
60378
60526
|
children: [
|
|
60379
60527
|
messages.length === 0 && !sending ? /* @__PURE__ */ jsx(AssistantUiEmptyState, {
|
|
60380
60528
|
...config?.title ? { title: config.title } : {},
|
|
@@ -60424,24 +60572,29 @@ function Chatbot({ adapter, config, locale: localeProp, theme: themeProp, render
|
|
|
60424
60572
|
activeRunId: currentRunId,
|
|
60425
60573
|
onDownload: handleDownload
|
|
60426
60574
|
}),
|
|
60427
|
-
|
|
60428
|
-
|
|
60429
|
-
|
|
60430
|
-
|
|
60431
|
-
|
|
60432
|
-
|
|
60433
|
-
|
|
60434
|
-
|
|
60435
|
-
|
|
60436
|
-
|
|
60437
|
-
|
|
60438
|
-
|
|
60439
|
-
|
|
60440
|
-
|
|
60441
|
-
|
|
60442
|
-
|
|
60443
|
-
|
|
60444
|
-
|
|
60575
|
+
/* @__PURE__ */ jsxs("div", {
|
|
60576
|
+
className: "webskill-chat-surface-wide",
|
|
60577
|
+
children: [
|
|
60578
|
+
renderer === "native" && liveSurfaceRunId ? /* @__PURE__ */ jsx(UiSurfaceList, {
|
|
60579
|
+
bridge: engine.bridge,
|
|
60580
|
+
runId: liveSurfaceRunId,
|
|
60581
|
+
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
60582
|
+
}) : null,
|
|
60583
|
+
renderer === "vercel" && liveSurfaceRunId ? /* @__PURE__ */ jsx(VercelSurfaceHost, {
|
|
60584
|
+
bridge: engine.bridge,
|
|
60585
|
+
runId: liveSurfaceRunId
|
|
60586
|
+
}) : null,
|
|
60587
|
+
renderer === "openui" && liveSurfaceRunId ? /* @__PURE__ */ jsx(OpenUiSurfaceHost, {
|
|
60588
|
+
bridge: engine.bridge,
|
|
60589
|
+
runId: liveSurfaceRunId
|
|
60590
|
+
}) : null,
|
|
60591
|
+
renderer === "a2ui" && liveSurfaceRunId ? /* @__PURE__ */ jsx(A2uiSurfaceHost, {
|
|
60592
|
+
bridge: engine.bridge,
|
|
60593
|
+
runId: liveSurfaceRunId,
|
|
60594
|
+
...surfaceRegistry ? { registry: surfaceRegistry } : {}
|
|
60595
|
+
}) : null
|
|
60596
|
+
]
|
|
60597
|
+
}),
|
|
60445
60598
|
error ? /* @__PURE__ */ jsx(ErrorCard, {
|
|
60446
60599
|
message: error.message,
|
|
60447
60600
|
...error.code ? { code: error.code } : {},
|
|
@@ -60558,7 +60711,7 @@ function VercelPayloadPreview({ bridge }) {
|
|
|
60558
60711
|
* Version of the published `@webskill/chatbot` package, injected at build time.
|
|
60559
60712
|
* @stable
|
|
60560
60713
|
*/
|
|
60561
|
-
const CHATBOT_VERSION = "0.
|
|
60714
|
+
const CHATBOT_VERSION = "0.8.0";
|
|
60562
60715
|
|
|
60563
60716
|
//#endregion
|
|
60564
|
-
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, pickUsableLlmEntry, probeA2uiAvailability, probeOpenUiAvailability, sandboxExecutorDeps, useT };
|
|
60717
|
+
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, isLlmEntryUsable, pickUsableLlmEntry, 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.8.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.11.0",
|
|
30
30
|
"react": ">=19.0.0",
|
|
31
31
|
"react-dom": ">=19.0.0",
|
|
32
32
|
"zod": "^3.25.0 || ^4.0.0"
|