vue-agent-start 0.1.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.
Files changed (169) hide show
  1. package/package.json +30 -0
  2. package/pnpm-workspace.yaml +3 -0
  3. package/src/agent-flow/adapter/backend.ts +99 -0
  4. package/src/agent-flow/components/ChatIframePanel.vue +773 -0
  5. package/src/agent-flow/components/DatasetItemCard.vue +313 -0
  6. package/src/agent-flow/components/MemoryWindow.vue +104 -0
  7. package/src/agent-flow/components/PromptEditor.vue +804 -0
  8. package/src/agent-flow/components/PromptEditorTagPanel.vue +460 -0
  9. package/src/agent-flow/components/SvgIcon.vue +32 -0
  10. package/src/agent-flow/components/ToolItemCard.vue +169 -0
  11. package/src/agent-flow/components/VariableCard.vue +161 -0
  12. package/src/agent-flow/components/VariableSelector.vue +162 -0
  13. package/src/agent-flow/components/chat-iframe-types.ts +35 -0
  14. package/src/agent-flow/components/stubs/DatasetChooser.vue +70 -0
  15. package/src/agent-flow/components/stubs/Embedding.vue +22 -0
  16. package/src/agent-flow/components/stubs/ModelSelect.vue +24 -0
  17. package/src/agent-flow/components/stubs/RestfulSelectCard.vue +24 -0
  18. package/src/agent-flow/components/stubs/ToolChooser.vue +96 -0
  19. package/src/agent-flow/components/stubs/TriggersItemCard.vue +126 -0
  20. package/src/agent-flow/components/stubs/VariableModal.vue +115 -0
  21. package/src/agent-flow/index.ts +73 -0
  22. package/src/agent-flow/stores/workflow.ts +72 -0
  23. package/src/agent-flow/utils/langUtils.ts +173 -0
  24. package/src/agent-flow/workflow/Ability.vue +65 -0
  25. package/src/agent-flow/workflow/AuthorizationItem.vue +101 -0
  26. package/src/agent-flow/workflow/ConversationVar.vue +42 -0
  27. package/src/agent-flow/workflow/CustomEdge.vue +94 -0
  28. package/src/agent-flow/workflow/EnvironmentVar.vue +40 -0
  29. package/src/agent-flow/workflow/FlowDesigner.vue +2802 -0
  30. package/src/agent-flow/workflow/Icon.vue +179 -0
  31. package/src/agent-flow/workflow/NodeConfig.vue +509 -0
  32. package/src/agent-flow/workflow/NodeConfigCard.vue +460 -0
  33. package/src/agent-flow/workflow/NodeHandle.vue +147 -0
  34. package/src/agent-flow/workflow/NodeHeaderToolbar.vue +77 -0
  35. package/src/agent-flow/workflow/NodeHoverToolbar.vue +176 -0
  36. package/src/agent-flow/workflow/OutputItemCard.vue +668 -0
  37. package/src/agent-flow/workflow/ParamTableItem.vue +200 -0
  38. package/src/agent-flow/workflow/StructTable.vue +202 -0
  39. package/src/agent-flow/workflow/VarInsertField.vue +517 -0
  40. package/src/agent-flow/workflow/VarSelectField.vue +223 -0
  41. package/src/agent-flow/workflow/VariableSelectorItem.vue +48 -0
  42. package/src/agent-flow/workflow/WfField.vue +206 -0
  43. package/src/agent-flow/workflow/_config-base.css +470 -0
  44. package/src/agent-flow/workflow/composables/useNode.js +55 -0
  45. package/src/agent-flow/workflow/index.vue +53 -0
  46. package/src/agent-flow/workflow/nodeCard/AgentNodeCard.vue +180 -0
  47. package/src/agent-flow/workflow/nodeCard/AnswerNodeCard.vue +65 -0
  48. package/src/agent-flow/workflow/nodeCard/ClassifierCard.vue +152 -0
  49. package/src/agent-flow/workflow/nodeCard/CodeNodeCard.vue +139 -0
  50. package/src/agent-flow/workflow/nodeCard/ConditionNodeCard.vue +323 -0
  51. package/src/agent-flow/workflow/nodeCard/DocumentExtractorCard.vue +83 -0
  52. package/src/agent-flow/workflow/nodeCard/EndNodeCard.vue +123 -0
  53. package/src/agent-flow/workflow/nodeCard/HttpNodeCard.vue +451 -0
  54. package/src/agent-flow/workflow/nodeCard/HumanInputCard.vue +152 -0
  55. package/src/agent-flow/workflow/nodeCard/IterationCard.vue +66 -0
  56. package/src/agent-flow/workflow/nodeCard/KnowledgeRetrievalCard.vue +48 -0
  57. package/src/agent-flow/workflow/nodeCard/LLMNodeCard.vue +206 -0
  58. package/src/agent-flow/workflow/nodeCard/ListOperatorCard.vue +188 -0
  59. package/src/agent-flow/workflow/nodeCard/ParameterExtractorCard.vue +352 -0
  60. package/src/agent-flow/workflow/nodeCard/ServiceApiNodeCard.vue +188 -0
  61. package/src/agent-flow/workflow/nodeCard/StartNodeCard.vue +216 -0
  62. package/src/agent-flow/workflow/nodeCard/VariableAssignerCard.vue +125 -0
  63. package/src/agent-flow/workflow/nodeCard/VariableNodeCard.vue +121 -0
  64. package/src/agent-flow/workflow/nodes/AgentNode.vue +122 -0
  65. package/src/agent-flow/workflow/nodes/AnswerNode.vue +99 -0
  66. package/src/agent-flow/workflow/nodes/ClassifierNode.vue +199 -0
  67. package/src/agent-flow/workflow/nodes/CodeNode.vue +152 -0
  68. package/src/agent-flow/workflow/nodes/ConditionNode.vue +232 -0
  69. package/src/agent-flow/workflow/nodes/DocumentExtractorNode.vue +96 -0
  70. package/src/agent-flow/workflow/nodes/EndNode.vue +119 -0
  71. package/src/agent-flow/workflow/nodes/FileUploadNode.vue +97 -0
  72. package/src/agent-flow/workflow/nodes/HttpNode.vue +204 -0
  73. package/src/agent-flow/workflow/nodes/HumanInputNode.vue +110 -0
  74. package/src/agent-flow/workflow/nodes/IterationNode.vue +98 -0
  75. package/src/agent-flow/workflow/nodes/KnowledgeRetrievalNode.vue +253 -0
  76. package/src/agent-flow/workflow/nodes/LLMNode.vue +134 -0
  77. package/src/agent-flow/workflow/nodes/ListOperatorNode.vue +111 -0
  78. package/src/agent-flow/workflow/nodes/LoopNode.vue +94 -0
  79. package/src/agent-flow/workflow/nodes/ParameterExtractorNode.vue +147 -0
  80. package/src/agent-flow/workflow/nodes/ServiceApiNode.vue +161 -0
  81. package/src/agent-flow/workflow/nodes/StartNode.vue +199 -0
  82. package/src/agent-flow/workflow/nodes/TemplateNode.vue +103 -0
  83. package/src/agent-flow/workflow/nodes/UserInputNode.vue +92 -0
  84. package/src/agent-flow/workflow/nodes/VariableAssignerNode.vue +145 -0
  85. package/src/agent-flow/workflow/nodes/VariableNode.vue +130 -0
  86. package/src/agent-flow/workflow/nodes/_node-base.css +338 -0
  87. package/src/agent-flow/workflow/utils/node_card_form.ts +335 -0
  88. package/src/agent-flow/workflow/utils/node_config.ts +63 -0
  89. package/src/agent-flow/workflow/utils/workflow_utils.ts +151 -0
  90. package/src/agent-studio/adapters/springAgentStart.ts +390 -0
  91. package/src/agent-studio/api/index.ts +1 -0
  92. package/src/agent-studio/api/types.ts +173 -0
  93. package/src/agent-studio/components/AgentApiDocs.vue +500 -0
  94. package/src/agent-studio/components/AgentAppsPage.vue +1601 -0
  95. package/src/agent-studio/components/AgentCardGrid.vue +259 -0
  96. package/src/agent-studio/components/AgentChatPage.vue +553 -0
  97. package/src/agent-studio/components/AgentDebugPanel.vue +350 -0
  98. package/src/agent-studio/components/AgentLogsPanel.vue +391 -0
  99. package/src/agent-studio/components/AgentMonitorPanel.vue +204 -0
  100. package/src/agent-studio/components/AgentOrchestrate.vue +505 -0
  101. package/src/agent-studio/components/AgentPromptEditor.vue +237 -0
  102. package/src/agent-studio/components/AgentStudioShell.vue +227 -0
  103. package/src/agent-studio/components/AgentToolsPanel.vue +394 -0
  104. package/src/agent-studio/components/AgentVariablesPanel.vue +205 -0
  105. package/src/agent-studio/components/ApiKeyManager.vue +251 -0
  106. package/src/agent-studio/components/AppDesignDrawer.vue +3391 -0
  107. package/src/agent-studio/components/CreateAppModal.vue +737 -0
  108. package/src/agent-studio/components/SparkChart.vue +200 -0
  109. package/src/agent-studio/components/VariableEditorModal.vue +499 -0
  110. package/src/agent-studio/composables/useAgentStudio.ts +347 -0
  111. package/src/agent-studio/index.ts +60 -0
  112. package/src/agent-studio/panels/DrawerFlowDesigner.vue +203 -0
  113. package/src/agent-studio/panels/LogAnnotationPanel.vue +490 -0
  114. package/src/agent-studio/panels/MonitorPanel.vue +535 -0
  115. package/src/agent-studio/types.ts +242 -0
  116. package/src/index.ts +155 -0
  117. package/src/knowledge-hub/adapters/springAgentStart.ts +472 -0
  118. package/src/knowledge-hub/components/AddDocumentsWizard.vue +1452 -0
  119. package/src/knowledge-hub/components/CreateDatasetWizard.vue +1723 -0
  120. package/src/knowledge-hub/components/DatasetCardGrid.vue +467 -0
  121. package/src/knowledge-hub/components/DatasetDetailDrawer.vue +888 -0
  122. package/src/knowledge-hub/components/DatasetPicker.vue +65 -0
  123. package/src/knowledge-hub/components/DatasetPickerModal.vue +526 -0
  124. package/src/knowledge-hub/components/DatasetSettingsPanel.vue +908 -0
  125. package/src/knowledge-hub/components/DatasetSidebar.vue +781 -0
  126. package/src/knowledge-hub/components/DocumentChunksView.vue +802 -0
  127. package/src/knowledge-hub/components/DocumentTable.vue +552 -0
  128. package/src/knowledge-hub/components/HitTestingPanel.vue +74 -0
  129. package/src/knowledge-hub/components/KnowledgeApp.vue +66 -0
  130. package/src/knowledge-hub/components/KnowledgeHubApp.vue +504 -0
  131. package/src/knowledge-hub/components/RecallTestingPanelV2.vue +515 -0
  132. package/src/knowledge-hub/components/RetrievalConfigPopover.vue +270 -0
  133. package/src/knowledge-hub/components/RetrievalMethodPicker.vue +547 -0
  134. package/src/knowledge-hub/components/RetrievedList.vue +24 -0
  135. package/src/knowledge-hub/components/internal/KhDialog.vue +195 -0
  136. package/src/knowledge-hub/composables/useKnowledge.ts +89 -0
  137. package/src/knowledge-hub/i18n/index.ts +2 -0
  138. package/src/knowledge-hub/i18n/messages.ts +422 -0
  139. package/src/knowledge-hub/i18n/useKhI18n.ts +107 -0
  140. package/src/knowledge-hub/index.ts +46 -0
  141. package/src/knowledge-hub/styles/index.css +4 -0
  142. package/src/knowledge-hub/styles/tokens.css +138 -0
  143. package/src/knowledge-hub/types/api.ts +213 -0
  144. package/src/knowledge-hub/types/dataset.ts +88 -0
  145. package/src/knowledge-hub/types/document.ts +45 -0
  146. package/src/knowledge-hub/types/index.ts +9 -0
  147. package/src/knowledge-hub/types/retrieval.ts +46 -0
  148. package/src/provider-hub/components/CredentialForm.vue +103 -0
  149. package/src/provider-hub/components/DefaultModelsPanel.vue +270 -0
  150. package/src/provider-hub/components/GroupedModelSelect.vue +445 -0
  151. package/src/provider-hub/components/ModelCardGrid.vue +332 -0
  152. package/src/provider-hub/components/ModelParameterDrawer.vue +739 -0
  153. package/src/provider-hub/components/ModelPickerPopover.vue +1282 -0
  154. package/src/provider-hub/components/ProviderApp.vue +159 -0
  155. package/src/provider-hub/components/ProviderCredentialModal.vue +321 -0
  156. package/src/provider-hub/components/ProviderGallery.vue +131 -0
  157. package/src/provider-hub/components/ProviderHubShell.vue +1992 -0
  158. package/src/provider-hub/components/ProviderIcon.vue +130 -0
  159. package/src/provider-hub/composables/useProviderHub.ts +358 -0
  160. package/src/provider-hub/index.ts +43 -0
  161. package/src/provider-hub/svg/MiniMax.svg +1 -0
  162. package/src/provider-hub/svg/Volcengine.svg +1 -0
  163. package/src/provider-hub/svg/Zhipu.svg +1 -0
  164. package/src/provider-hub/svg/deepseek.svg +1 -0
  165. package/src/provider-hub/svg/moonshot.svg +1 -0
  166. package/src/provider-hub/svg/openai.svg +1 -0
  167. package/src/provider-hub/svg/qwen.svg +1 -0
  168. package/src/provider-hub/svg/siliconflow.svg +1 -0
  169. package/src/provider-hub/types.ts +256 -0
@@ -0,0 +1,500 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * 访问 API tab — reproduces the Dify docs layout (Snipaste_09-01-20):
4
+ * - big heading + subtitle
5
+ * - Base URL block
6
+ * - Auth block
7
+ * - Per-endpoint anchor list on the right
8
+ * - Endpoint sections with request/response code samples
9
+ *
10
+ * All strings are host-provided so the same panel can back any agent. Anchors
11
+ * scroll to their sections inside the panel's scroll container.
12
+ */
13
+ import { computed, onMounted, ref, watch } from 'vue';
14
+ import { KeyOutlined } from '@ant-design/icons-vue';
15
+ import { message, Modal } from 'ant-design-vue';
16
+
17
+ import type { AppStudioApi, StudioApiKey } from '../api/types';
18
+
19
+ import ApiKeyManager from './ApiKeyManager.vue';
20
+
21
+ export interface ApiEndpoint {
22
+ id: string;
23
+ title: string;
24
+ method?: string;
25
+ path?: string;
26
+ description?: string;
27
+ code?: string;
28
+ }
29
+
30
+ interface Props {
31
+ title?: string;
32
+ subtitle?: string;
33
+ baseUrl: string;
34
+ /** Placeholder shown in the "Authorization: Bearer" example. */
35
+ apiKey?: string;
36
+ endpoints?: ApiEndpoint[];
37
+ /** Server status label ("运行中" etc.). */
38
+ serverStatus?: string;
39
+ /**
40
+ * The app the panel is showing docs for. Required to hit the api-tokens
41
+ * endpoints; when absent the "API 密钥" button is hidden.
42
+ */
43
+ appId?: string;
44
+ /**
45
+ * Callback bag from the studio host. Only the {@code listApiKeys /
46
+ * createApiKey / deleteApiKey} fields are used here — everything else is
47
+ * for the log/monitor panels.
48
+ */
49
+ api?: AppStudioApi;
50
+ }
51
+
52
+ const props = withDefaults(defineProps<Props>(), {
53
+ title: '工作流编排对话型应用 API',
54
+ subtitle: '对话应用支持会话持久化,可将之前的聊天记录作为上下文进行回答,可适用于聊天/客服 AI 等。',
55
+ apiKey: '{API_KEY}',
56
+ endpoints: () => [],
57
+ serverStatus: '运行中',
58
+ appId: '',
59
+ api: () => ({}),
60
+ });
61
+
62
+ const emit = defineEmits<{
63
+ (e: 'copy', text: string): void;
64
+ }>();
65
+
66
+ // ── API 密钥 manager wiring ────────────────────────────────────────────────
67
+ // Whether the host wired any key-management endpoints. When none, the button
68
+ // disappears — no point offering an action that goes nowhere.
69
+ const canManageKeys = computed(
70
+ () => !!props.appId && (!!props.api?.listApiKeys || !!props.api?.createApiKey),
71
+ );
72
+
73
+ const managerOpen = ref(false);
74
+ const keys = ref<StudioApiKey[]>([]);
75
+ const loadingKeys = ref(false);
76
+ const creatingKey = ref(false);
77
+
78
+ async function refreshKeys() {
79
+ if (!props.appId || !props.api?.listApiKeys) return;
80
+ loadingKeys.value = true;
81
+ try {
82
+ keys.value = (await props.api.listApiKeys(props.appId)) ?? [];
83
+ } catch (e) {
84
+ message.error(`加载 API 密钥失败:${(e as Error).message ?? e}`);
85
+ } finally {
86
+ loadingKeys.value = false;
87
+ }
88
+ }
89
+
90
+ async function onCreateKey() {
91
+ if (!props.appId || !props.api?.createApiKey) {
92
+ message.warning('未接入创建密钥接口');
93
+ return;
94
+ }
95
+ creatingKey.value = true;
96
+ try {
97
+ const row = await props.api.createApiKey(props.appId);
98
+ keys.value = [row, ...keys.value];
99
+ // Auto-copy the fresh token — Dify's UX pattern — plus a toast so the user
100
+ // knows the copy happened without having to click again.
101
+ try {
102
+ await navigator.clipboard?.writeText(row.token);
103
+ message.success('已创建并复制新密钥');
104
+ } catch {
105
+ message.success('已创建新密钥');
106
+ }
107
+ } catch (e) {
108
+ message.error(`创建密钥失败:${(e as Error).message ?? e}`);
109
+ } finally {
110
+ creatingKey.value = false;
111
+ }
112
+ }
113
+
114
+ async function onDeleteKey(row: StudioApiKey) {
115
+ if (!props.appId || !props.api?.deleteApiKey) {
116
+ message.warning('未接入删除密钥接口');
117
+ return;
118
+ }
119
+ try {
120
+ await props.api.deleteApiKey(props.appId, row.id);
121
+ keys.value = keys.value.filter((k) => k.id !== row.id);
122
+ message.success('已删除密钥');
123
+ } catch (e) {
124
+ message.error(`删除密钥失败:${(e as Error).message ?? e}`);
125
+ }
126
+ }
127
+
128
+ function openManager() {
129
+ managerOpen.value = true;
130
+ refreshKeys();
131
+ }
132
+
133
+ // Refresh whenever the manager is toggled open externally.
134
+ watch(managerOpen, (v) => {
135
+ if (v) refreshKeys();
136
+ });
137
+
138
+ const container = ref<HTMLElement | null>(null);
139
+ const activeAnchor = ref('');
140
+
141
+ const anchors = computed(() =>
142
+ props.endpoints.map((e) => ({ id: e.id, title: e.title })),
143
+ );
144
+
145
+ function goto(id: string) {
146
+ activeAnchor.value = id;
147
+ const el = document.getElementById(`ep-${id}`);
148
+ el?.scrollIntoView({ behavior: 'smooth', block: 'start' });
149
+ }
150
+
151
+ function copy(text: string) {
152
+ if (typeof navigator !== 'undefined' && navigator.clipboard) {
153
+ navigator.clipboard.writeText(text).catch(() => {});
154
+ }
155
+ emit('copy', text);
156
+ }
157
+
158
+ onMounted(() => {
159
+ if (props.endpoints[0]) activeAnchor.value = props.endpoints[0].id;
160
+ });
161
+ </script>
162
+
163
+ <template>
164
+ <div class="api">
165
+ <header class="api-top">
166
+ <h2 class="api-top-title">访问 API</h2>
167
+ <div class="api-top-right">
168
+ <span class="api-status">
169
+ <span class="api-status-dot" />
170
+ {{ serverStatus }}
171
+ </span>
172
+ <button
173
+ v-if="canManageKeys"
174
+ type="button"
175
+ class="api-key-btn"
176
+ @click="openManager"
177
+ >
178
+ <KeyOutlined />
179
+ <span>API 密钥</span>
180
+ </button>
181
+ <span v-else class="api-key-hint">API 密钥</span>
182
+ </div>
183
+ </header>
184
+
185
+ <ApiKeyManager
186
+ v-model:open="managerOpen"
187
+ :keys="keys"
188
+ :loading="loadingKeys"
189
+ :creating="creatingKey"
190
+ @create="onCreateKey"
191
+ @delete="onDeleteKey"
192
+ @refresh="refreshKeys"
193
+ />
194
+
195
+ <div ref="container" class="api-body">
196
+ <div class="api-main">
197
+ <div class="api-headline">
198
+ <h1 class="api-h1">{{ title }}</h1>
199
+ <p class="api-lead">{{ subtitle }}</p>
200
+ </div>
201
+
202
+ <section class="api-section">
203
+ <h3 class="api-h3">基础 URL</h3>
204
+ <div class="api-codeblock">
205
+ <div class="api-codeblock-head">Code</div>
206
+ <pre class="api-code"><code>{{ baseUrl }}</code></pre>
207
+ <button class="api-copy" @click="copy(baseUrl)">复制</button>
208
+ </div>
209
+ </section>
210
+
211
+ <section class="api-section">
212
+ <h3 class="api-h3">鉴权</h3>
213
+ <p class="api-p">
214
+ Service API 使用 <code>API-Key</code> 进行鉴权。
215
+ <b>强烈建议开发者把 <code>API-Key</code> 放在后端存储,而非分享或者放在客户端存储</b>,以免
216
+ <code>API-Key</code> 泄露,导致财产损失。所有 API 请求都应在
217
+ <code>Authorization</code> HTTP Header 中包含您的 <code>API-Key</code>,如下所示:
218
+ </p>
219
+ <div class="api-codeblock">
220
+ <div class="api-codeblock-head">Code</div>
221
+ <pre class="api-code"><code>Authorization: Bearer {{ apiKey }}</code></pre>
222
+ <button class="api-copy" @click="copy(`Authorization: Bearer ${apiKey}`)">
223
+ 复制
224
+ </button>
225
+ </div>
226
+ </section>
227
+
228
+ <section
229
+ v-for="ep in endpoints"
230
+ :id="`ep-${ep.id}`"
231
+ :key="ep.id"
232
+ class="api-section"
233
+ >
234
+ <span
235
+ v-if="ep.method"
236
+ class="api-method"
237
+ :class="`api-method-${ep.method.toLowerCase()}`"
238
+ >
239
+ {{ ep.method }}
240
+ </span>
241
+ <code v-if="ep.path" class="api-path">{{ ep.path }}</code>
242
+ <h3 class="api-h3">{{ ep.title }}</h3>
243
+ <p v-if="ep.description" class="api-p">{{ ep.description }}</p>
244
+ <div v-if="ep.code" class="api-codeblock api-codeblock-dark">
245
+ <div class="api-codeblock-head api-codeblock-head-dark">Request</div>
246
+ <pre class="api-code api-code-dark"><code>{{ ep.code }}</code></pre>
247
+ <button class="api-copy api-copy-dark" @click="copy(ep.code ?? '')">
248
+ 复制
249
+ </button>
250
+ </div>
251
+ </section>
252
+ </div>
253
+
254
+ <aside v-if="anchors.length > 0" class="api-toc">
255
+ <div class="api-toc-title">目录</div>
256
+ <button
257
+ v-for="a in anchors"
258
+ :key="a.id"
259
+ type="button"
260
+ class="api-toc-item"
261
+ :class="{ 'api-toc-item-active': activeAnchor === a.id }"
262
+ @click="goto(a.id)"
263
+ >
264
+ {{ a.title }}
265
+ </button>
266
+ </aside>
267
+ </div>
268
+ </div>
269
+ </template>
270
+
271
+ <style scoped>
272
+ .api {
273
+ display: flex;
274
+ flex-direction: column;
275
+ height: 100%;
276
+ min-height: 0;
277
+ }
278
+ .api-top {
279
+ display: flex;
280
+ align-items: center;
281
+ justify-content: space-between;
282
+ padding: 12px 20px;
283
+ border-bottom: 1px solid #e5e7eb;
284
+ background: #fff;
285
+ }
286
+ .api-top-title {
287
+ margin: 0;
288
+ font-size: 15px;
289
+ font-weight: 600;
290
+ color: #0f172a;
291
+ }
292
+ .api-top-right {
293
+ display: flex;
294
+ align-items: center;
295
+ gap: 14px;
296
+ font-size: 12px;
297
+ color: #64748b;
298
+ }
299
+ .api-status {
300
+ display: inline-flex;
301
+ align-items: center;
302
+ gap: 4px;
303
+ color: #16a34a;
304
+ }
305
+ .api-status-dot {
306
+ width: 6px;
307
+ height: 6px;
308
+ border-radius: 999px;
309
+ background: #22c55e;
310
+ }
311
+ .api-key-hint {
312
+ padding: 3px 8px;
313
+ border: 1px solid #e2e8f0;
314
+ border-radius: 6px;
315
+ background: #f8fafc;
316
+ }
317
+ .api-key-btn {
318
+ display: inline-flex;
319
+ align-items: center;
320
+ gap: 6px;
321
+ padding: 4px 10px;
322
+ border: 1px solid #c7d2fe;
323
+ border-radius: 6px;
324
+ background: #eef2ff;
325
+ color: #4338ca;
326
+ font-size: 12px;
327
+ cursor: pointer;
328
+ transition:
329
+ background 0.15s ease,
330
+ border-color 0.15s ease;
331
+ }
332
+ .api-key-btn:hover {
333
+ background: #e0e7ff;
334
+ border-color: #a5b4fc;
335
+ }
336
+ .api-body {
337
+ flex: 1;
338
+ min-height: 0;
339
+ display: grid;
340
+ grid-template-columns: 1fr 220px;
341
+ gap: 0;
342
+ overflow-y: auto;
343
+ }
344
+ .api-main {
345
+ padding: 24px 40px;
346
+ max-width: 900px;
347
+ }
348
+ .api-headline {
349
+ margin-bottom: 24px;
350
+ }
351
+ .api-h1 {
352
+ margin: 0 0 6px;
353
+ font-size: 22px;
354
+ color: #0f172a;
355
+ }
356
+ .api-lead {
357
+ margin: 0;
358
+ color: #64748b;
359
+ font-size: 13px;
360
+ line-height: 1.6;
361
+ }
362
+ .api-section {
363
+ margin-top: 28px;
364
+ }
365
+ .api-h3 {
366
+ margin: 0 0 8px;
367
+ font-size: 16px;
368
+ font-weight: 600;
369
+ color: #0f172a;
370
+ }
371
+ .api-p {
372
+ color: #475569;
373
+ font-size: 13px;
374
+ line-height: 1.7;
375
+ }
376
+ .api-p code {
377
+ padding: 1px 6px;
378
+ background: #f1f5f9;
379
+ border-radius: 4px;
380
+ color: #dc2626;
381
+ font-family: ui-monospace, monospace;
382
+ font-size: 12px;
383
+ }
384
+ .api-codeblock {
385
+ position: relative;
386
+ margin-top: 8px;
387
+ background: #f8fafc;
388
+ border: 1px solid #e2e8f0;
389
+ border-radius: 8px;
390
+ overflow: hidden;
391
+ }
392
+ .api-codeblock-head {
393
+ padding: 6px 12px;
394
+ background: #eef2f7;
395
+ color: #64748b;
396
+ font-size: 11px;
397
+ font-weight: 600;
398
+ }
399
+ .api-code {
400
+ margin: 0;
401
+ padding: 12px 14px;
402
+ background: transparent;
403
+ color: #0f172a;
404
+ font-family: ui-monospace, monospace;
405
+ font-size: 12px;
406
+ line-height: 1.6;
407
+ white-space: pre-wrap;
408
+ word-break: break-all;
409
+ }
410
+ .api-copy {
411
+ position: absolute;
412
+ top: 4px;
413
+ right: 6px;
414
+ padding: 2px 8px;
415
+ border: none;
416
+ background: transparent;
417
+ color: #64748b;
418
+ font-size: 11px;
419
+ cursor: pointer;
420
+ }
421
+ .api-copy:hover {
422
+ color: #4338ca;
423
+ }
424
+ .api-codeblock-dark {
425
+ background: #0f172a;
426
+ border-color: #1e293b;
427
+ }
428
+ .api-codeblock-head-dark {
429
+ background: #1e293b;
430
+ color: #94a3b8;
431
+ }
432
+ .api-code-dark {
433
+ color: #e2e8f0;
434
+ }
435
+ .api-copy-dark {
436
+ color: #94a3b8;
437
+ }
438
+ .api-method {
439
+ display: inline-block;
440
+ padding: 2px 8px;
441
+ border-radius: 4px;
442
+ font-size: 10px;
443
+ font-weight: 700;
444
+ letter-spacing: 0.05em;
445
+ margin-right: 6px;
446
+ }
447
+ .api-method-post {
448
+ background: #16a34a;
449
+ color: #fff;
450
+ }
451
+ .api-method-get {
452
+ background: #2563eb;
453
+ color: #fff;
454
+ }
455
+ .api-method-delete {
456
+ background: #dc2626;
457
+ color: #fff;
458
+ }
459
+ .api-path {
460
+ font-family: ui-monospace, monospace;
461
+ font-size: 12px;
462
+ color: #475569;
463
+ }
464
+
465
+ /* TOC */
466
+ .api-toc {
467
+ padding: 24px 12px;
468
+ border-left: 1px solid #e5e7eb;
469
+ background: #fff;
470
+ }
471
+ .api-toc-title {
472
+ padding: 4px 8px 6px;
473
+ font-size: 11px;
474
+ font-weight: 600;
475
+ color: #94a3b8;
476
+ text-transform: uppercase;
477
+ letter-spacing: 0.05em;
478
+ }
479
+ .api-toc-item {
480
+ display: block;
481
+ width: 100%;
482
+ padding: 5px 8px;
483
+ border: none;
484
+ background: transparent;
485
+ border-radius: 6px;
486
+ font-size: 12px;
487
+ color: #64748b;
488
+ text-align: left;
489
+ cursor: pointer;
490
+ }
491
+ .api-toc-item:hover {
492
+ background: #f1f5f9;
493
+ color: #0f172a;
494
+ }
495
+ .api-toc-item-active {
496
+ background: #eef2ff;
497
+ color: #4338ca;
498
+ font-weight: 500;
499
+ }
500
+ </style>