@tbox.cn/app-template-agent 0.7.5 → 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/.gitignore +5 -0
- package/.tbox/app.json +9 -1
- package/AGENTS.md +12 -4
- package/ENV.md +102 -17
- package/README.md +36 -34
- package/apps/client/VISUAL_RESTORE.md +11 -11
- package/apps/client/index.html +3 -1
- package/apps/client/package.json +9 -8
- package/apps/client/src/business/App.tsx +4 -4
- package/apps/client/src/business/README.md +5 -11
- package/apps/client/src/cards/registry.ts +23 -8
- package/apps/client/src/main.tsx +36 -2
- package/apps/client/src/modules.ts +7 -4
- package/apps/client/src/pages/index/index.tsx +18 -162
- package/apps/client/src/platform/AgentChatApp.tsx +3 -3
- package/apps/client/src/platform/agent-runtime.ts +5 -0
- package/apps/client/src/store/chat.ts +47 -185
- package/apps/client/src/test/setup.ts +7 -0
- package/apps/client/vite.config.ts +16 -1
- package/apps/server/package.json +0 -1
- package/apps/server/src/app-tools.ts +2 -1
- package/apps/server/src/app.ts +178 -110
- package/apps/server/src/config/integration.ts +2 -6
- package/apps/server/src/dev.ts +0 -1
- package/apps/server/src/intent-routes.ts +3 -3
- package/apps/server/src/modules.ts +4 -4
- package/apps/server/src/pre-tools.ts +4 -3
- package/apps/server/tests/agent-prompt.test.ts +81 -0
- package/apps/server/tests/cards-registry.test.ts +1 -3
- package/apps/server/tests/deployment-loader.test.ts +35 -56
- package/apps/server/tests/tool-runtime.test.ts +25 -61
- package/package.json +5 -4
- package/packages/agent-ui-kit/LICENSE +21 -0
- package/packages/agent-ui-kit/README.md +17 -0
- package/packages/agent-ui-kit/package.json +58 -0
- package/packages/agent-ui-kit/src/ChatPage.less +62 -0
- package/packages/agent-ui-kit/src/ChatPage.tsx +305 -0
- package/packages/agent-ui-kit/src/chat-config.test.ts +82 -0
- package/packages/agent-ui-kit/src/chat-config.ts +62 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/ActionBar/DebugButton.tsx +2 -2
- package/{apps/client → packages/agent-ui-kit}/src/components/ActionBar/index.less +19 -16
- package/{apps/client → packages/agent-ui-kit}/src/components/ActionBar/index.tsx +10 -13
- package/packages/agent-ui-kit/src/components/CardRenderer.tsx +36 -0
- package/packages/agent-ui-kit/src/components/ChatHeader/index.less +148 -0
- package/packages/agent-ui-kit/src/components/ChatHeader/index.test.tsx +74 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/ChatHeader/index.tsx +27 -15
- package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/index.less +47 -39
- package/packages/agent-ui-kit/src/components/ChatInput/index.test.tsx +156 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/index.tsx +13 -4
- package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/voice/useVoicePress.ts +2 -2
- package/packages/agent-ui-kit/src/components/HistoryEntry/index.less +49 -0
- package/packages/agent-ui-kit/src/components/HistoryEntry/index.tsx +42 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/MediaList/index.less +3 -3
- package/{apps/client → packages/agent-ui-kit}/src/components/MediaList/index.tsx +6 -6
- package/{apps/client → packages/agent-ui-kit}/src/components/MessageBubble/index.less +25 -20
- package/packages/agent-ui-kit/src/components/MessageBubble/index.test.tsx +112 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/MessageBubble/index.tsx +22 -15
- package/{apps/client → packages/agent-ui-kit}/src/components/PullDownIndicator/index.less +2 -2
- package/{apps/client → packages/agent-ui-kit}/src/components/PullDownIndicator/index.tsx +2 -2
- package/packages/agent-ui-kit/src/components/QuickCommands/index.less +63 -0
- package/packages/agent-ui-kit/src/components/QuickCommands/index.test.tsx +99 -0
- package/packages/agent-ui-kit/src/components/QuickCommands/index.tsx +52 -0
- package/{apps/client → packages/agent-ui-kit}/src/components/ScrollToBottomButton/index.less +1 -1
- package/packages/agent-ui-kit/src/components/ToolCallBlock/detail.test.ts +346 -0
- package/packages/agent-ui-kit/src/components/ToolCallBlock/detail.ts +204 -0
- package/packages/agent-ui-kit/src/components/ToolCallBlock/index.less +312 -0
- package/packages/agent-ui-kit/src/components/ToolCallBlock/index.test.tsx +261 -0
- package/packages/agent-ui-kit/src/components/ToolCallBlock/index.tsx +212 -0
- package/packages/agent-ui-kit/src/components/ToolCallBlock/titles.ts +102 -0
- package/packages/agent-ui-kit/src/hooks/use-drag-gesture.test.ts +66 -0
- package/packages/agent-ui-kit/src/hooks/use-drag-gesture.ts +129 -0
- package/packages/agent-ui-kit/src/hooks/use-pull-down-history.ts +241 -0
- package/packages/agent-ui-kit/src/hooks/use-pull-down-wheel-native.test.ts +64 -0
- package/{apps/client → packages/agent-ui-kit}/src/hooks/useMediaUpload.ts +3 -3
- package/{apps/client → packages/agent-ui-kit}/src/hooks/useTTSAutoPlay.ts +7 -5
- package/packages/agent-ui-kit/src/index.ts +69 -0
- package/packages/agent-ui-kit/src/store-context.tsx +92 -0
- package/packages/agent-ui-kit/src/test/setup.ts +7 -0
- package/packages/agent-ui-kit/src/theme/contract.json +72 -0
- package/packages/agent-ui-kit/src/theme/global.less +99 -0
- package/packages/agent-ui-kit/src/theme/motion.less +19 -0
- package/packages/agent-ui-kit/src/theme/theme-contract.test.ts +69 -0
- package/packages/agent-ui-kit/src/theme/theme.ts +17 -0
- package/packages/agent-ui-kit/src/theme/tokens.less +79 -0
- package/packages/agent-ui-kit/src/utils/haptics.test.ts +51 -0
- package/packages/agent-ui-kit/src/utils/haptics.ts +44 -0
- package/packages/agent-ui-kit/src/utils/pull-down-machine.test.ts +188 -0
- package/packages/agent-ui-kit/src/utils/pull-down-machine.ts +157 -0
- package/packages/agent-ui-kit/src/utils/tool-call-display.test.ts +240 -0
- package/packages/agent-ui-kit/src/utils/tool-call-display.ts +146 -0
- package/packages/agent-ui-kit/src/vite-env.d.ts +1 -0
- package/packages/agent-ui-kit/tsconfig.json +8 -0
- package/packages/agent-ui-kit/vitest.config.ts +7 -0
- package/pnpm-lock.template.yaml +177 -83
- package/pnpm-workspace.template.yaml +12 -4
- package/profiles/mall/config/agent.jsonc +33 -0
- package/profiles/mall/config/chat.json +21 -0
- package/profiles/mall/config/knowledge.json +5 -0
- package/profiles/mall/config/llm_provider.json +5 -0
- package/profiles/mall/config/plugins.json +3 -0
- package/profiles/mall.json +16 -0
- package/scripts/check-workspace.mjs +3 -2
- package/apps/client/assets/copy@2x.png +0 -0
- package/apps/client/assets/debug.png +0 -0
- package/apps/client/assets/dislike@2x.png +0 -0
- package/apps/client/assets/like@2x.png +0 -0
- package/apps/client/assets/speaker@2x.png +0 -0
- package/apps/client/src/cards/CardRenderer.tsx +0 -20
- package/apps/client/src/components/ChatHeader/index.less +0 -104
- package/apps/client/src/components/ErrorBoundary.tsx +0 -2
- package/apps/client/src/components/QuickCommands/index.less +0 -48
- package/apps/client/src/components/QuickCommands/index.tsx +0 -29
- package/apps/client/src/components/ToolCallBlock/index.less +0 -131
- package/apps/client/src/components/ToolCallBlock/index.tsx +0 -125
- package/apps/client/src/examples/tourism/TourismLanding.tsx +0 -96
- package/apps/client/src/examples/tourism/index.less +0 -192
- package/apps/client/src/pages/index/index.less +0 -43
- package/apps/client/src/store/chat-config.ts +0 -40
- package/apps/client/src/styles/global.less +0 -60
- package/apps/client/src/styles/tokens.less +0 -60
- package/apps/server/src/config/deployment.ts +0 -47
- package/packages/module-weather/package.json +0 -36
- package/packages/module-weather/skills/weather-guide/SKILL.md +0 -22
- package/packages/module-weather/skills/weather-guide/references/dressing-tips.md +0 -5
- package/packages/module-weather/src/client/cards/weather/index.less +0 -22
- package/packages/module-weather/src/client/cards/weather/index.tsx +0 -14
- package/packages/module-weather/src/client/index.ts +0 -19
- package/packages/module-weather/src/index.ts +0 -2
- package/packages/module-weather/src/server/cards/weather/meta.ts +0 -27
- package/packages/module-weather/src/server/index.ts +0 -45
- package/packages/module-weather/src/server/pre-tools.ts +0 -20
- package/packages/module-weather/src/server/tool.ts +0 -29
- package/packages/module-weather/tbox.module.json +0 -27
- package/packages/module-weather/tsconfig.json +0 -14
- /package/{apps/client → packages/agent-ui-kit}/assets/keyboard-circle.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/more-circle.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/new-chat.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/quick-command-star.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/send-gradient.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/stop@2x.png +0 -0
- /package/{apps/client → packages/agent-ui-kit}/assets/voice-circle.svg +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/voice/VoicePressField.tsx +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/voice/VoiceRecordingOverlay.tsx +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ChatInput/voice/machine.ts +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ReasoningBlock/index.less +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ReasoningBlock/index.tsx +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/components/ScrollToBottomButton/index.tsx +0 -0
- /package/{apps/client/src/types/chat.ts → packages/agent-ui-kit/src/types.ts} +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/utils/copyText.ts +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/utils/imagePreview.ts +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/utils/session-error.ts +0 -0
- /package/{apps/client → packages/agent-ui-kit}/src/utils/toast.ts +0 -0
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
.tourism-example {
|
|
2
|
-
&__welcome {
|
|
3
|
-
display: flex;
|
|
4
|
-
flex-direction: column;
|
|
5
|
-
align-items: center;
|
|
6
|
-
padding: 44px 48px 32px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
&__welcome-title {
|
|
10
|
-
margin-bottom: 24px;
|
|
11
|
-
color: #1f3b63;
|
|
12
|
-
font-size: 40px;
|
|
13
|
-
font-weight: 700;
|
|
14
|
-
line-height: 48px;
|
|
15
|
-
text-align: center;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
&__welcome-desc {
|
|
19
|
-
color: #1f3b63;
|
|
20
|
-
font-size: 30px;
|
|
21
|
-
line-height: 48px;
|
|
22
|
-
text-align: justify;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
&__section {
|
|
26
|
-
margin: 24px;
|
|
27
|
-
padding: 24px;
|
|
28
|
-
background: #fff9;
|
|
29
|
-
border: 1px solid #fff3;
|
|
30
|
-
border-radius: 24px;
|
|
31
|
-
box-shadow: 0 2px 18px 0 #2a31380a;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
&__carousel-section {
|
|
35
|
-
padding-right: 0;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
&__section-title {
|
|
39
|
-
display: block;
|
|
40
|
-
margin: 0 0 24px;
|
|
41
|
-
color: #1f3b63;
|
|
42
|
-
font-size: 30px;
|
|
43
|
-
font-weight: 500;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
&__carousel {
|
|
47
|
-
display: flex;
|
|
48
|
-
gap: 16px;
|
|
49
|
-
overflow-x: auto;
|
|
50
|
-
padding-right: 24px;
|
|
51
|
-
scrollbar-width: none;
|
|
52
|
-
|
|
53
|
-
&::-webkit-scrollbar {
|
|
54
|
-
display: none;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
&__carousel-item {
|
|
59
|
-
position: relative;
|
|
60
|
-
width: 280px;
|
|
61
|
-
height: 168px;
|
|
62
|
-
flex-shrink: 0;
|
|
63
|
-
overflow: hidden;
|
|
64
|
-
padding: 0;
|
|
65
|
-
background: transparent;
|
|
66
|
-
border: 0;
|
|
67
|
-
border-radius: 32px;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
&__carousel-image {
|
|
71
|
-
display: block;
|
|
72
|
-
width: 100%;
|
|
73
|
-
height: 100%;
|
|
74
|
-
object-fit: cover;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
&__carousel-overlay {
|
|
78
|
-
position: absolute;
|
|
79
|
-
right: 0;
|
|
80
|
-
bottom: 0;
|
|
81
|
-
left: 0;
|
|
82
|
-
display: flex;
|
|
83
|
-
flex-direction: column;
|
|
84
|
-
padding: 16px 20px 14px;
|
|
85
|
-
background: linear-gradient(180deg, transparent 0%, rgb(0 0 0 / 50%) 100%);
|
|
86
|
-
text-align: left;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
&__carousel-title {
|
|
90
|
-
margin-bottom: 4px;
|
|
91
|
-
color: #fff;
|
|
92
|
-
font-size: 30px;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
&__carousel-desc {
|
|
96
|
-
color: rgb(255 255 255 / 80%);
|
|
97
|
-
font-size: 22px;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
&__service-grid,
|
|
101
|
-
&__suggestion-grid {
|
|
102
|
-
display: flex;
|
|
103
|
-
flex-wrap: wrap;
|
|
104
|
-
gap: 16px;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
&__service-item,
|
|
108
|
-
&__suggestion {
|
|
109
|
-
display: flex;
|
|
110
|
-
align-items: center;
|
|
111
|
-
width: calc(50% - 8px);
|
|
112
|
-
box-sizing: border-box;
|
|
113
|
-
background: #fff;
|
|
114
|
-
border: 1px solid #8d9fb866;
|
|
115
|
-
border-radius: 24px;
|
|
116
|
-
box-shadow: 0 0 24px 0 #8d9fb80d;
|
|
117
|
-
color: #1f3b63;
|
|
118
|
-
text-align: left;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
&__service-item {
|
|
122
|
-
height: 112px;
|
|
123
|
-
padding: 0 8px 0 20px;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
&__service-icon {
|
|
127
|
-
display: block;
|
|
128
|
-
width: 72px;
|
|
129
|
-
height: 72px;
|
|
130
|
-
margin-right: 16px;
|
|
131
|
-
flex-shrink: 0;
|
|
132
|
-
object-fit: contain;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
&__service-content {
|
|
136
|
-
display: flex;
|
|
137
|
-
min-width: 0;
|
|
138
|
-
flex: 1;
|
|
139
|
-
flex-direction: column;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
&__service-title-row {
|
|
143
|
-
display: flex;
|
|
144
|
-
align-items: center;
|
|
145
|
-
justify-content: space-between;
|
|
146
|
-
margin-bottom: 4px;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
&__service-title,
|
|
150
|
-
&__service-desc {
|
|
151
|
-
overflow: hidden;
|
|
152
|
-
text-overflow: ellipsis;
|
|
153
|
-
white-space: nowrap;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
&__service-title {
|
|
157
|
-
font-size: 28px;
|
|
158
|
-
font-weight: 500;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
&__service-desc {
|
|
162
|
-
color: #1f3b6373;
|
|
163
|
-
font-size: 22px;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
&__suggestion-header {
|
|
167
|
-
display: flex;
|
|
168
|
-
align-items: center;
|
|
169
|
-
justify-content: space-between;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
&__refresh {
|
|
173
|
-
display: flex;
|
|
174
|
-
align-items: center;
|
|
175
|
-
gap: 9px;
|
|
176
|
-
margin-bottom: 24px;
|
|
177
|
-
padding: 0;
|
|
178
|
-
background: transparent;
|
|
179
|
-
border: 0;
|
|
180
|
-
color: #10295399;
|
|
181
|
-
font-size: 26px;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
&__suggestion {
|
|
185
|
-
justify-content: space-between;
|
|
186
|
-
height: 78px;
|
|
187
|
-
padding: 0 20px;
|
|
188
|
-
overflow: hidden;
|
|
189
|
-
font-size: 26px;
|
|
190
|
-
font-weight: 500;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
.chat-page {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-direction: column;
|
|
4
|
-
height: 100%;
|
|
5
|
-
position: relative;
|
|
6
|
-
background: #eef2f9;
|
|
7
|
-
|
|
8
|
-
&__bg {
|
|
9
|
-
position: absolute;
|
|
10
|
-
inset: 0;
|
|
11
|
-
z-index: 0;
|
|
12
|
-
background-image: linear-gradient(180deg, #9dc6ff 0%, #e5f0ff 63%, #e5f0ff 100%);
|
|
13
|
-
opacity: 0.66;
|
|
14
|
-
pointer-events: none;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&__body-wrapper {
|
|
18
|
-
flex: 1;
|
|
19
|
-
min-height: 0;
|
|
20
|
-
position: relative;
|
|
21
|
-
z-index: 1;
|
|
22
|
-
display: flex;
|
|
23
|
-
flex-direction: column;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
&__body {
|
|
27
|
-
flex: 1;
|
|
28
|
-
min-height: 0;
|
|
29
|
-
overflow-y: auto;
|
|
30
|
-
overflow-anchor: none;
|
|
31
|
-
overscroll-behavior: contain;
|
|
32
|
-
position: relative;
|
|
33
|
-
padding: 10px 0 8px;
|
|
34
|
-
width: 100%;
|
|
35
|
-
max-width: var(--tbox-content-max-width);
|
|
36
|
-
margin: 0 auto;
|
|
37
|
-
scrollbar-width: none;
|
|
38
|
-
|
|
39
|
-
&::-webkit-scrollbar {
|
|
40
|
-
display: none;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
import type { ChatUiSettings } from '@tbox.cn/app-sdk/client';
|
|
3
|
-
import chatConfigJson from '../../../../config/chat.json';
|
|
4
|
-
|
|
5
|
-
export interface QuickCommand {
|
|
6
|
-
/** 纯文案;前导星标/图标由 QuickCommands 组件渲染,不要写进 label */
|
|
7
|
-
label: string;
|
|
8
|
-
query: string;
|
|
9
|
-
icon?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface ChatConfigStore {
|
|
13
|
-
enableImageUpload: boolean;
|
|
14
|
-
enableVideoUpload: boolean;
|
|
15
|
-
enableTTS: boolean;
|
|
16
|
-
enableVoiceInput: boolean;
|
|
17
|
-
defaultInputMode: 'TEXT' | 'VOICE';
|
|
18
|
-
quickCommands: QuickCommand[];
|
|
19
|
-
/** HELLO_ACK settings 水合:服务端单一真源;undefined 键保留构建期快照(五键整组语义,禁部分水合) */
|
|
20
|
-
applyServerSettings: (settings: ChatUiSettings | undefined) => void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const cfg = chatConfigJson as Record<string, unknown>;
|
|
24
|
-
|
|
25
|
-
export const useChatConfigStore = create<ChatConfigStore>()((set) => ({
|
|
26
|
-
enableImageUpload: (cfg.enableImageUpload as boolean) ?? true,
|
|
27
|
-
enableVideoUpload: (cfg.enableVideoUpload as boolean) ?? true,
|
|
28
|
-
enableTTS: (cfg.enableTTS as boolean) ?? true,
|
|
29
|
-
enableVoiceInput: (cfg.enableVoiceInput as boolean) ?? true,
|
|
30
|
-
defaultInputMode: (cfg.defaultInputMode as 'TEXT' | 'VOICE') ?? 'TEXT',
|
|
31
|
-
quickCommands: (cfg.quickCommands as QuickCommand[]) ?? [],
|
|
32
|
-
applyServerSettings: (settings) =>
|
|
33
|
-
set((cur) => ({
|
|
34
|
-
enableImageUpload: settings?.enableImageUpload ?? cur.enableImageUpload,
|
|
35
|
-
enableVideoUpload: settings?.enableVideoUpload ?? cur.enableVideoUpload,
|
|
36
|
-
enableTTS: settings?.enableTTS ?? cur.enableTTS,
|
|
37
|
-
enableVoiceInput: settings?.enableVoiceInput ?? cur.enableVoiceInput,
|
|
38
|
-
defaultInputMode: settings?.defaultInputMode ?? cur.defaultInputMode,
|
|
39
|
-
})),
|
|
40
|
-
}));
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
@import './tokens.less';
|
|
2
|
-
|
|
3
|
-
* {
|
|
4
|
-
box-sizing: border-box;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
html,
|
|
8
|
-
body,
|
|
9
|
-
#root {
|
|
10
|
-
margin: 0;
|
|
11
|
-
padding: 0;
|
|
12
|
-
height: 100%;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
body {
|
|
16
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
17
|
-
font-size: var(--tbox-fs-body);
|
|
18
|
-
color: var(--tbox-text-primary);
|
|
19
|
-
background: var(--tbox-bg-subtle);
|
|
20
|
-
-webkit-font-smoothing: antialiased;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/* 顶层容器全宽(渐变底铺满),内容区由各处 max-width:800px 居中(对齐原模板 #app)。 */
|
|
24
|
-
#root {
|
|
25
|
-
width: 100%;
|
|
26
|
-
position: relative;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/* 去掉移动端点击高亮 */
|
|
30
|
-
* {
|
|
31
|
-
-webkit-tap-highlight-color: transparent;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/* 卡片统一外层 = 卡片「卡框」。所有卡片共有的框在这里,单卡组件别重复写:
|
|
35
|
-
- 间距:卡片与上下元素(工具调用 / 气泡)的间距,与 .tool-calls 一致;
|
|
36
|
-
- 外观:默认背景(白) / 圆角 / 阴影;`overflow:hidden` 把内容裁进圆角。
|
|
37
|
-
值为源码 px(2x 基线、折半渲染):圆角 40≈20、阴影 0 4px 16px≈0 2px 8px。
|
|
38
|
-
⚠️ **内边距不在卡框里**——由卡片自己写。卡框给 padding 会让「自带背景色的卡」在外面露一圈白边(卡里套卡)。
|
|
39
|
-
宽度也不在卡框里:默认占满整列(≈移动端 350~400px 设计宽),紧凑卡自己写 max-width。
|
|
40
|
-
单卡组件(.tbox-<type>)只画内容;**要整卡换底色 / 出血图,直接在自己 root 上 `background:<色>` 或铺满图**——
|
|
41
|
-
会铺满卡框、裁进圆角、不出白边(别再自己设圆角,卡框已裁)。不写背景则露卡框默认白底,不透明。 */
|
|
42
|
-
.tbox-card {
|
|
43
|
-
margin-bottom: 12px;
|
|
44
|
-
background: var(--tbox-bg-card);
|
|
45
|
-
border-radius: 40px;
|
|
46
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
|
47
|
-
overflow: hidden;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/* 兜底态(未知 cardType / 渲染出错,由 CardRenderer 给外层加此修饰类):
|
|
51
|
-
复用卡框,弱化成无阴影的虚线提示框(内边距自带,因为卡框不再给 padding) */
|
|
52
|
-
.tbox-card--fallback {
|
|
53
|
-
max-width: 80%;
|
|
54
|
-
padding: 32px 24px;
|
|
55
|
-
background: var(--tbox-bg-subtle);
|
|
56
|
-
border: 1px dashed var(--tbox-border);
|
|
57
|
-
box-shadow: none;
|
|
58
|
-
color: var(--tbox-text-muted);
|
|
59
|
-
font-size: var(--tbox-fs-caption);
|
|
60
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 设计 token —— 从原 server `cards/_shared/tokens.css` 搬家到 client。
|
|
3
|
-
*
|
|
4
|
-
* C 方案下卡片是 client React 组件、不再有 iframe 下发 tokens,
|
|
5
|
-
* 所以这些设计变量必须落在 client。卡片组件与页面统一用 var(--tbox-*) 引用,
|
|
6
|
-
* 禁止硬编码十六进制色值 / px 字号。
|
|
7
|
-
*
|
|
8
|
-
* 注:这里的 px 会被 postcss-px-to-viewport(750 基准)转成 vw。
|
|
9
|
-
*/
|
|
10
|
-
:root {
|
|
11
|
-
/* 主色 */
|
|
12
|
-
--tbox-primary: #1677ff;
|
|
13
|
-
--tbox-primary-dark: #0958d9;
|
|
14
|
-
--tbox-primary-light: #e6f4ff;
|
|
15
|
-
|
|
16
|
-
/* 文本 */
|
|
17
|
-
--tbox-text-primary: #1f1f1f;
|
|
18
|
-
--tbox-text-secondary: #595959;
|
|
19
|
-
--tbox-text-muted: #8c8c8c;
|
|
20
|
-
|
|
21
|
-
/* 背景 */
|
|
22
|
-
--tbox-bg-card: #ffffff;
|
|
23
|
-
--tbox-bg-subtle: #f5f7fa;
|
|
24
|
-
|
|
25
|
-
/* 边框 */
|
|
26
|
-
--tbox-border: #e8ebed;
|
|
27
|
-
|
|
28
|
-
/* 状态色 */
|
|
29
|
-
--tbox-success: #52c41a;
|
|
30
|
-
--tbox-warning: #faad14;
|
|
31
|
-
--tbox-error: #ff4d4f;
|
|
32
|
-
|
|
33
|
-
/* 字号——按 750/2x 设计稿基线,对标消息气泡(MessageBubble):
|
|
34
|
-
正文 .msg-markdown / __text = 25px,次要信息(时间/角色) = 18~19px,标题 h1~h4 = 36/32/30/28px。
|
|
35
|
-
注意:rootValue 100 + 根字号脚本会把 px 折半渲染(750 稿 → ≈375 手机列),
|
|
36
|
-
所以这里写的是 2x 值,别按普通 web 的 12/14/16 写(那样渲染出来只有一半、发虚)。
|
|
37
|
-
价格等强调大号字单独硬编(~32,≈气泡 h2),不挤进这 3 档。 */
|
|
38
|
-
--tbox-fs-heading: 30px; /* ≈气泡 h3:商品名 / 店名 */
|
|
39
|
-
--tbox-fs-body: 25px; /* =气泡正文 */
|
|
40
|
-
--tbox-fs-caption: 20px; /* ≈气泡次要信息(时间/角色) */
|
|
41
|
-
|
|
42
|
-
/* 圆角 */
|
|
43
|
-
--tbox-radius-sm: 4px;
|
|
44
|
-
--tbox-radius-md: 8px;
|
|
45
|
-
|
|
46
|
-
/* 内容最大宽度(对齐原模板):全宽渐变底 + 内容区 800px 居中。
|
|
47
|
-
大写 PX 不被 postcss-pxtorem 转换(正则大小写敏感),保持固定像素。 */
|
|
48
|
-
--tbox-content-max-width: 800PX;
|
|
49
|
-
|
|
50
|
-
/* 媒体缩略图 */
|
|
51
|
-
--tbox-media-item-size: 174px;
|
|
52
|
-
--tbox-media-item-radius: 12px;
|
|
53
|
-
|
|
54
|
-
/* 输入框(对齐原模板 AdvancedChatInput) */
|
|
55
|
-
--tbox-input-bg: rgba(255, 255, 255, 0.7);
|
|
56
|
-
--tbox-input-radius: 50px;
|
|
57
|
-
--tbox-input-padding: 20px 24px;
|
|
58
|
-
--tbox-send-btn-size: 44px;
|
|
59
|
-
--tbox-icon-color: #4b6282;
|
|
60
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* mall 装配派生层(integrations v4:部署拓扑并入 integrations.json——单文件真源;
|
|
3
|
-
* 与 mall 模板同构,base 无 mallName 包装链)。
|
|
4
|
-
* - 旧 `config/deployments/development.json` 已退役:stale 防线在 integration.ts 装载链
|
|
5
|
-
* (在场且含 malls 键 → error 迁移指引;support 独立体系不受影响);
|
|
6
|
-
* - controlPlane 来源 = integration.ts 的 mallControlPlaneOf 投影(attributes 赋义 zod
|
|
7
|
-
* 单源上收 contracts-mall——本文件不再内嵌 schema);
|
|
8
|
-
* - mall 语义集中在 contracts-mall(TIER1);apps 只做装配组合(011 L6 checklist)。
|
|
9
|
-
*/
|
|
10
|
-
import { createLogger } from '@tbox.cn/app-sdk/server';
|
|
11
|
-
import { createMallRuntimeAssembly, type MallDeploymentControlPlane, type MallRuntimeAssembly } from '@app/contracts-mall';
|
|
12
|
-
import type { LoadedIntegrations } from './integration.js';
|
|
13
|
-
|
|
14
|
-
const deploymentLogger = createLogger('DEPLOYMENT');
|
|
15
|
-
|
|
16
|
-
export interface LoadedDeployment {
|
|
17
|
-
controlPlane: MallDeploymentControlPlane;
|
|
18
|
-
assembly: MallRuntimeAssembly;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/** integrations 装载产物 → mall 装配(恒投影——无参考表 = 空平面,装配零拓扑分支) */
|
|
22
|
-
export function deploymentFromIntegrations(loaded: LoadedIntegrations): LoadedDeployment {
|
|
23
|
-
const assembly = createMallRuntimeAssembly(loaded.controlPlane);
|
|
24
|
-
return { controlPlane: loaded.controlPlane, assembly };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 016:默认商圈 HELLO context(无 URL 参数访问时的服务端兜底;与 mall 模板同构)。
|
|
29
|
-
* v4 mallId-only 注入(D8/D9):miniAppId 是尽力回填的展示值,非会话边界——
|
|
30
|
-
* 读源统一 root config.miniAppId 优先、回落参考表 attributes.miniAppId;双缺不再
|
|
31
|
-
* 阻断注入(此前 warn-refuse 会造成默认商圈静默失效),按 mallId-only 注入。
|
|
32
|
-
* 缺省 defaultMallId → undefined(不兜底)。
|
|
33
|
-
*/
|
|
34
|
-
export function buildDefaultMallContext(
|
|
35
|
-
controlPlane: MallDeploymentControlPlane,
|
|
36
|
-
rootMiniAppId?: string,
|
|
37
|
-
): Record<string, unknown> | undefined {
|
|
38
|
-
if (!controlPlane.defaultMallId) return undefined;
|
|
39
|
-
const mall = controlPlane.malls.find((m) => m.mallId === controlPlane.defaultMallId);
|
|
40
|
-
const miniAppId = rootMiniAppId ?? mall?.miniAppId;
|
|
41
|
-
if (!miniAppId) {
|
|
42
|
-
deploymentLogger.warn(
|
|
43
|
-
`defaultMallId=${controlPlane.defaultMallId} 无 miniAppId 真源(root config 与参考表双缺)——按 mallId-only 注入默认商圈`,
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
return { mall: { mallId: controlPlane.defaultMallId, ...(miniAppId ? { miniAppId } : {}) } };
|
|
47
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@app/module-weather",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"exports": {
|
|
7
|
-
".": {
|
|
8
|
-
"types": "./src/index.ts",
|
|
9
|
-
"import": "./src/index.ts"
|
|
10
|
-
},
|
|
11
|
-
"./server": {
|
|
12
|
-
"types": "./src/server/index.ts",
|
|
13
|
-
"import": "./src/server/index.ts"
|
|
14
|
-
},
|
|
15
|
-
"./client": {
|
|
16
|
-
"types": "./src/client/index.ts",
|
|
17
|
-
"import": "./src/client/index.ts"
|
|
18
|
-
},
|
|
19
|
-
"./package.json": "./package.json"
|
|
20
|
-
},
|
|
21
|
-
"scripts": {
|
|
22
|
-
"typecheck": "tsc --noEmit"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@tbox.cn/app-sdk": "catalog:",
|
|
26
|
-
"@tbox.cn/app-contracts": "catalog:"
|
|
27
|
-
},
|
|
28
|
-
"peerDependencies": {
|
|
29
|
-
"zod": "3.25.76",
|
|
30
|
-
"react": "18.3.1"
|
|
31
|
-
},
|
|
32
|
-
"devDependencies": {
|
|
33
|
-
"@types/react": "18.3.31",
|
|
34
|
-
"typescript": "5.9.3"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: weather-guide
|
|
3
|
-
description: 天气查询与穿衣出行建议(调用 getWeather 真实数据)
|
|
4
|
-
metadata:
|
|
5
|
-
routingTerms: [天气, 穿衣, 温度, 湿度, 出行]
|
|
6
|
-
---
|
|
7
|
-
## 适用意图
|
|
8
|
-
用户询问天气、穿衣建议、出行准备(如"今天穿什么")时使用本规范。
|
|
9
|
-
|
|
10
|
-
## 调用工具
|
|
11
|
-
必须调用 getWeather 工具查询真实天气(city 取用户提到的城市),禁止编造温度/天气数据。
|
|
12
|
-
|
|
13
|
-
## 返回字段说明
|
|
14
|
-
getWeather 返回:temp(温度℃)、weather(天气现象)、humidity(湿度%)。
|
|
15
|
-
|
|
16
|
-
## 回答组织方式
|
|
17
|
-
1. 先报城市与天气现象、温度、湿度
|
|
18
|
-
2. 再给出穿衣/出行建议(结合温度与天气现象)
|
|
19
|
-
3. 温度 <10℃ 提醒保暖,>30℃ 提醒防晒
|
|
20
|
-
|
|
21
|
-
## 出卡规则
|
|
22
|
-
getWeather 结果含天气卡:回复末尾另起一行输出 `<agent-ui-cards>` 引用本轮卡片 id,否则用户看不到卡。
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
.tbox-weather {
|
|
2
|
-
max-width: 80%;
|
|
3
|
-
padding: 32px 24px;
|
|
4
|
-
|
|
5
|
-
&__city {
|
|
6
|
-
font-size: var(--tbox-fs-heading);
|
|
7
|
-
font-weight: 600;
|
|
8
|
-
color: var(--tbox-text-primary);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
&__temp {
|
|
12
|
-
font-size: 56px;
|
|
13
|
-
font-weight: 700;
|
|
14
|
-
color: var(--tbox-primary);
|
|
15
|
-
margin: 8px 0;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
&__meta {
|
|
19
|
-
font-size: var(--tbox-fs-caption);
|
|
20
|
-
color: var(--tbox-text-secondary);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { WeatherCardData } from '../../../server/cards/weather/meta';
|
|
2
|
-
import './index.less';
|
|
3
|
-
|
|
4
|
-
export function WeatherCard({ data }: { data: WeatherCardData; cardId: string; isHistory: boolean }) {
|
|
5
|
-
return (
|
|
6
|
-
<div className="tbox-weather">
|
|
7
|
-
<div className="tbox-weather__city">{data.city}</div>
|
|
8
|
-
<div className="tbox-weather__temp">{data.temp}°</div>
|
|
9
|
-
<div className="tbox-weather__meta">
|
|
10
|
-
{data.weather} · 湿度 {data.humidity}%
|
|
11
|
-
</div>
|
|
12
|
-
</div>
|
|
13
|
-
);
|
|
14
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { CardComponent } from '@tbox.cn/app-contracts';
|
|
2
|
-
import type { ClientContext, ClientModule } from '@tbox.cn/app-sdk/client';
|
|
3
|
-
import { WeatherCard } from './cards/weather/index';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 客户端卡片组件 map(CLI sync 读取)。
|
|
7
|
-
* key 约定 = cardType;渲染边界统一为 CardComponent(data: unknown),具体类型由组件内部收窄。
|
|
8
|
-
*/
|
|
9
|
-
const cards = {
|
|
10
|
-
weather: WeatherCard as CardComponent,
|
|
11
|
-
} as const;
|
|
12
|
-
|
|
13
|
-
/** 模块注册入口:自注册闭环(与服务端 serverModule 对称) */
|
|
14
|
-
export const clientModule = {
|
|
15
|
-
cards,
|
|
16
|
-
register(ctx: ClientContext): void {
|
|
17
|
-
ctx.cards.registerMap(cards);
|
|
18
|
-
},
|
|
19
|
-
} satisfies ClientModule;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import type { CardMeta } from '@tbox.cn/app-contracts';
|
|
3
|
-
|
|
4
|
-
export const dataSchema = z.object({
|
|
5
|
-
city: z.string(),
|
|
6
|
-
temp: z.number(),
|
|
7
|
-
weather: z.string(),
|
|
8
|
-
humidity: z.number(),
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
export type WeatherCardData = z.infer<typeof dataSchema>;
|
|
12
|
-
|
|
13
|
-
const meta: CardMeta<typeof dataSchema> = {
|
|
14
|
-
cardType: 'weather',
|
|
15
|
-
dataSchema,
|
|
16
|
-
displayName: '天气卡片',
|
|
17
|
-
description: '展示某城市的天气数据,含温度、天气状况、湿度',
|
|
18
|
-
sampleData: {
|
|
19
|
-
city: '北京',
|
|
20
|
-
temp: 22,
|
|
21
|
-
weather: '晴',
|
|
22
|
-
humidity: 35,
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default meta;
|
|
27
|
-
export { meta as weatherMeta };
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { weatherTool } from './tool';
|
|
2
|
-
import weatherMeta from './cards/weather/meta';
|
|
3
|
-
import { loadModuleSkills } from '@tbox.cn/app-sdk/server';
|
|
4
|
-
import type { LocalSkill, ServerContext, ServerModule } from '@tbox.cn/app-sdk/server';
|
|
5
|
-
import { weatherPreTool } from './pre-tools';
|
|
6
|
-
|
|
7
|
-
export { weatherTool, weatherMeta };
|
|
8
|
-
|
|
9
|
-
/** 卡片 meta 声明 map(key 约定 = meta.cardType;数据 + 类型源) */
|
|
10
|
-
const cards = {
|
|
11
|
-
weather: weatherMeta,
|
|
12
|
-
} as const;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 模块 skill 声明(009 模块文件化:SKILL.md 目录格式,文件即唯一源)。
|
|
16
|
-
* - 底层能力:SDK `loadModuleSkills(packageName, import.meta.url)` 单策略定位包根
|
|
17
|
-
* (createRequire 包名解析:dev workspace link / 模块 dist / 应用 bundle dist / 发布态
|
|
18
|
-
* node_modules 全形态恒命中;失败 warn 可行动 + 恒 resolve []);
|
|
19
|
-
* - 顶层 await 加载 → 填回 serverModule.skills 声明式通道(装配端 registerAll 自动注册);
|
|
20
|
-
* - 前置:本包 exports 须含 "./package.json"(见 package.json);
|
|
21
|
-
* - 生成应用内(codegen 展开)调用名由 CLI 自动改写为 @app/<id>,源码按字面量包名写法。
|
|
22
|
-
*/
|
|
23
|
-
const skills = Object.fromEntries(
|
|
24
|
-
(await loadModuleSkills('@app/module-weather', import.meta.url)).map((s) => [s.name, s]),
|
|
25
|
-
) satisfies Record<string, LocalSkill>;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 模块前置工具声明(010:key 约定 = toolId,纯数据 + 一个 resolve 函数)。
|
|
29
|
-
* 装配端 registerServerModules 自动注册(register 内无需代码)。
|
|
30
|
-
*/
|
|
31
|
-
const preTools = {
|
|
32
|
-
getWeather: weatherPreTool,
|
|
33
|
-
} as const;
|
|
34
|
-
|
|
35
|
-
/** 模块注册入口:自注册闭环(与客户端 clientModule 对称) */
|
|
36
|
-
export const serverModule = {
|
|
37
|
-
cards,
|
|
38
|
-
skills,
|
|
39
|
-
preTools,
|
|
40
|
-
declaration: { moduleId: 'weather' },
|
|
41
|
-
register(ctx: ServerContext): void {
|
|
42
|
-
ctx.tools.register(weatherTool);
|
|
43
|
-
ctx.cards.registerMap(cards);
|
|
44
|
-
},
|
|
45
|
-
} satisfies ServerModule;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { definePreTool } from '@tbox.cn/app-sdk/server';
|
|
2
|
-
import { weatherTool } from './tool';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 前置工具声明(010):getWeather 的 city 参数可工程化抽取(城市词表),
|
|
6
|
-
* 无需模型抽参——词表命中即预执行,模型第一轮直接作答(省一轮 loop)。
|
|
7
|
-
*
|
|
8
|
-
* 演示形态:文本工程化抽取——决策即构造:
|
|
9
|
-
* 抽到城市 → { decision: 'run', args: { city } }(预执行,args 强类型由 tool 推断);
|
|
10
|
-
* 抽不到 → { decision: 'skip' }(本轮不生效,模型正常调用工具)。
|
|
11
|
-
*/
|
|
12
|
-
const CITIES = ['北京', '上海', '广州', '深圳', '杭州', '成都', '武汉', '西安', '南京', '重庆'];
|
|
13
|
-
|
|
14
|
-
export const weatherPreTool = definePreTool(weatherTool, {
|
|
15
|
-
routing: { mode: 'keywords', terms: ['天气', '气温', '下雨', '下雪', '穿衣', '出行'] },
|
|
16
|
-
decide: ({ text }) => {
|
|
17
|
-
const city = CITIES.find((c) => text.includes(c));
|
|
18
|
-
return city ? { decision: 'run', args: { city } } : { decision: 'skip' };
|
|
19
|
-
},
|
|
20
|
-
});
|