@agent-native/core 0.79.2 → 0.79.6
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +30 -0
- package/corpus/core/docs/content/locales/zh-TW/a2a-protocol.md +392 -0
- package/corpus/core/docs/content/locales/zh-TW/actions.md +583 -0
- package/corpus/core/docs/content/locales/zh-TW/agent-mentions.md +164 -0
- package/corpus/core/docs/content/locales/zh-TW/agent-surfaces.md +397 -0
- package/corpus/core/docs/content/locales/zh-TW/agent-teams.md +171 -0
- package/corpus/core/docs/content/locales/zh-TW/agent-web-surfaces.md +161 -0
- package/corpus/core/docs/content/locales/zh-TW/audit-log.md +111 -0
- package/corpus/core/docs/content/locales/zh-TW/authentication.md +332 -0
- package/corpus/core/docs/content/locales/zh-TW/automations.md +268 -0
- package/corpus/core/docs/content/locales/zh-TW/blueprint-installer.md +83 -0
- package/corpus/core/docs/content/locales/zh-TW/cli-adapters.md +129 -0
- package/corpus/core/docs/content/locales/zh-TW/client.md +398 -0
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.md +114 -0
- package/corpus/core/docs/content/locales/zh-TW/code-agents-ui.md +436 -0
- package/corpus/core/docs/content/locales/zh-TW/components.md +368 -0
- package/corpus/core/docs/content/locales/zh-TW/context-awareness.md +373 -0
- package/corpus/core/docs/content/locales/zh-TW/creating-templates.md +411 -0
- package/corpus/core/docs/content/locales/zh-TW/cross-app-sso.md +188 -0
- package/corpus/core/docs/content/locales/zh-TW/database.md +183 -0
- package/corpus/core/docs/content/locales/zh-TW/deployment.md +348 -0
- package/corpus/core/docs/content/locales/zh-TW/dispatch.md +146 -0
- package/corpus/core/docs/content/locales/zh-TW/drop-in-agent.md +260 -0
- package/corpus/core/docs/content/locales/zh-TW/durable-resume.md +65 -0
- package/corpus/core/docs/content/locales/zh-TW/embedding-sdk.md +597 -0
- package/corpus/core/docs/content/locales/zh-TW/evals.md +155 -0
- package/corpus/core/docs/content/locales/zh-TW/extensions.md +360 -0
- package/corpus/core/docs/content/locales/zh-TW/external-agents.md +619 -0
- package/corpus/core/docs/content/locales/zh-TW/faq.md +142 -0
- package/corpus/core/docs/content/locales/zh-TW/file-uploads.md +122 -0
- package/corpus/core/docs/content/locales/zh-TW/frames.md +153 -0
- package/corpus/core/docs/content/locales/zh-TW/getting-started.md +199 -0
- package/corpus/core/docs/content/locales/zh-TW/harness-agents.md +349 -0
- package/corpus/core/docs/content/locales/zh-TW/human-approval.md +86 -0
- package/corpus/core/docs/content/locales/zh-TW/internationalization.md +147 -0
- package/corpus/core/docs/content/locales/zh-TW/key-concepts.md +312 -0
- package/corpus/core/docs/content/locales/zh-TW/local-file-mode.md +433 -0
- package/corpus/core/docs/content/locales/zh-TW/mcp-apps.md +147 -0
- package/corpus/core/docs/content/locales/zh-TW/mcp-clients.md +330 -0
- package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.md +279 -0
- package/corpus/core/docs/content/locales/zh-TW/messaging.md +461 -0
- package/corpus/core/docs/content/locales/zh-TW/migration-workbench.md +33 -0
- package/corpus/core/docs/content/locales/zh-TW/multi-app-workspace.md +312 -0
- package/corpus/core/docs/content/locales/zh-TW/multi-tenancy.md +52 -0
- package/corpus/core/docs/content/locales/zh-TW/native-chat-ui.md +321 -0
- package/corpus/core/docs/content/locales/zh-TW/notifications.md +231 -0
- package/corpus/core/docs/content/locales/zh-TW/observability.md +294 -0
- package/corpus/core/docs/content/locales/zh-TW/observational-memory.md +77 -0
- package/corpus/core/docs/content/locales/zh-TW/onboarding.md +216 -0
- package/corpus/core/docs/content/locales/zh-TW/plan-plugin.md +200 -0
- package/corpus/core/docs/content/locales/zh-TW/pr-visual-recap.md +384 -0
- package/corpus/core/docs/content/locales/zh-TW/processors.md +106 -0
- package/corpus/core/docs/content/locales/zh-TW/progress.md +199 -0
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.md +39 -0
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.md +680 -0
- package/corpus/core/docs/content/locales/zh-TW/recurring-jobs.md +142 -0
- package/corpus/core/docs/content/locales/zh-TW/routing.md +79 -0
- package/corpus/core/docs/content/locales/zh-TW/sandbox-adapters.md +227 -0
- package/corpus/core/docs/content/locales/zh-TW/security.md +330 -0
- package/corpus/core/docs/content/locales/zh-TW/server.md +265 -0
- package/corpus/core/docs/content/locales/zh-TW/sharing.md +219 -0
- package/corpus/core/docs/content/locales/zh-TW/skills-guide.md +281 -0
- package/corpus/core/docs/content/locales/zh-TW/template-analytics.md +259 -0
- package/corpus/core/docs/content/locales/zh-TW/template-assets.md +303 -0
- package/corpus/core/docs/content/locales/zh-TW/template-brain.md +324 -0
- package/corpus/core/docs/content/locales/zh-TW/template-calendar.md +194 -0
- package/corpus/core/docs/content/locales/zh-TW/template-chat.md +129 -0
- package/corpus/core/docs/content/locales/zh-TW/template-clips.md +368 -0
- package/corpus/core/docs/content/locales/zh-TW/template-content.md +402 -0
- package/corpus/core/docs/content/locales/zh-TW/template-design.md +173 -0
- package/corpus/core/docs/content/locales/zh-TW/template-dispatch.md +220 -0
- package/corpus/core/docs/content/locales/zh-TW/template-forms.md +178 -0
- package/corpus/core/docs/content/locales/zh-TW/template-mail.md +239 -0
- package/corpus/core/docs/content/locales/zh-TW/template-plan.md +814 -0
- package/corpus/core/docs/content/locales/zh-TW/template-slides.md +293 -0
- package/corpus/core/docs/content/locales/zh-TW/template-videos.md +222 -0
- package/corpus/core/docs/content/locales/zh-TW/tracking.md +236 -0
- package/corpus/core/docs/content/locales/zh-TW/using-your-agent.md +71 -0
- package/corpus/core/docs/content/locales/zh-TW/voice-input.md +81 -0
- package/corpus/core/docs/content/locales/zh-TW/what-is-agent-native.md +202 -0
- package/corpus/core/docs/content/locales/zh-TW/workspace-connections.md +321 -0
- package/corpus/core/docs/content/locales/zh-TW/workspace-management.md +175 -0
- package/corpus/core/docs/content/locales/zh-TW/workspace.md +323 -0
- package/corpus/core/docs/content/locales/zh-TW/writing-agent-instructions.md +173 -0
- package/corpus/core/package.json +2 -2
- package/corpus/core/scripts/check-dist-imports.mjs +35 -0
- package/corpus/core/src/client/ErrorBoundary.tsx +10 -0
- package/corpus/core/src/client/FeedbackButton.tsx +12 -0
- package/corpus/core/src/client/blocks/library/block-copy.ts +32 -0
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +33 -0
- package/corpus/core/src/client/i18n.tsx +6 -1
- package/corpus/core/src/localization/actions/set-localization-preference.ts +2 -1
- package/corpus/core/src/localization/default-messages.ts +492 -0
- package/corpus/core/src/localization/shared.ts +45 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +38 -0
- package/corpus/core/src/server/onboarding-html.ts +99 -0
- package/corpus/core/src/templates/default/app/i18n/index.ts +2 -0
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +466 -0
- package/corpus/core/src/templates/default/app/root.tsx +8 -0
- package/corpus/templates/analytics/app/i18n/index.ts +2 -0
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +818 -0
- package/corpus/templates/analytics/app/i18n-data.ts +9 -0
- package/corpus/templates/assets/app/i18n/index.ts +2 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +860 -0
- package/corpus/templates/assets/app/i18n-data.ts +3 -0
- package/corpus/templates/brain/app/i18n/index.ts +2 -0
- package/corpus/templates/brain/app/i18n/zh-TW.ts +709 -0
- package/corpus/templates/brain/app/i18n-data.ts +3 -0
- package/corpus/templates/calendar/app/i18n/zh-TW.ts +836 -0
- package/corpus/templates/calendar/app/i18n-data.ts +4 -0
- package/corpus/templates/chat/app/i18n/index.ts +2 -0
- package/corpus/templates/chat/app/i18n/zh-TW.ts +67 -0
- package/corpus/templates/chat/app/i18n-data.ts +3 -0
- package/corpus/templates/clips/app/i18n/index.ts +2 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1280 -0
- package/corpus/templates/content/app/i18n/index.ts +2 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +906 -0
- package/corpus/templates/content/app/i18n-data.ts +4 -0
- package/corpus/templates/design/app/i18n/index.ts +2 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +517 -0
- package/corpus/templates/design/app/i18n-data.ts +6 -0
- package/corpus/templates/dispatch/app/i18n/index.ts +2 -0
- package/corpus/templates/dispatch/app/i18n/zh-TW.ts +195 -0
- package/corpus/templates/dispatch/app/i18n-data.ts +3 -0
- package/corpus/templates/forms/app/i18n/index.ts +2 -0
- package/corpus/templates/forms/app/i18n/zh-TW.ts +349 -0
- package/corpus/templates/macros/app/i18n/index.ts +2 -0
- package/corpus/templates/macros/app/i18n/zh-TW.ts +224 -0
- package/corpus/templates/mail/app/i18n/index.ts +2 -0
- package/corpus/templates/mail/app/i18n/zh-TW.ts +562 -0
- package/corpus/templates/mail/app/root.tsx +6 -0
- package/corpus/templates/plan/app/i18n/index.ts +2 -0
- package/corpus/templates/plan/app/i18n/zh-TW.ts +712 -0
- package/corpus/templates/slides/app/i18n/index.ts +2 -0
- package/corpus/templates/slides/app/i18n/zh-TW.ts +531 -0
- package/corpus/templates/videos/app/i18n/index.ts +2 -0
- package/corpus/templates/videos/app/i18n/zh-TW.ts +435 -0
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +10 -0
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +12 -0
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/blocks/library/block-copy.d.ts.map +1 -1
- package/dist/client/blocks/library/block-copy.js +32 -0
- package/dist/client/blocks/library/block-copy.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +32 -0
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/i18n.d.ts.map +1 -1
- package/dist/client/i18n.js +6 -1
- package/dist/client/i18n.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/localization/actions/set-localization-preference.d.ts.map +1 -1
- package/dist/localization/actions/set-localization-preference.js +2 -2
- package/dist/localization/actions/set-localization-preference.js.map +1 -1
- package/dist/localization/default-messages.d.ts +443 -0
- package/dist/localization/default-messages.d.ts.map +1 -0
- package/dist/localization/default-messages.js +448 -0
- package/dist/localization/default-messages.js.map +1 -0
- package/dist/localization/shared.d.ts +1 -1
- package/dist/localization/shared.d.ts.map +1 -1
- package/dist/localization/shared.js +43 -0
- package/dist/localization/shared.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +7 -7
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +39 -0
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +96 -0
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/default/app/i18n/index.ts +2 -0
- package/dist/templates/default/app/i18n/zh-TW.ts +466 -0
- package/dist/templates/default/app/root.tsx +8 -0
- package/docs/content/locales/zh-TW/a2a-protocol.md +392 -0
- package/docs/content/locales/zh-TW/actions.md +583 -0
- package/docs/content/locales/zh-TW/agent-mentions.md +164 -0
- package/docs/content/locales/zh-TW/agent-surfaces.md +397 -0
- package/docs/content/locales/zh-TW/agent-teams.md +171 -0
- package/docs/content/locales/zh-TW/agent-web-surfaces.md +161 -0
- package/docs/content/locales/zh-TW/audit-log.md +111 -0
- package/docs/content/locales/zh-TW/authentication.md +332 -0
- package/docs/content/locales/zh-TW/automations.md +268 -0
- package/docs/content/locales/zh-TW/blueprint-installer.md +83 -0
- package/docs/content/locales/zh-TW/cli-adapters.md +129 -0
- package/docs/content/locales/zh-TW/client.md +398 -0
- package/docs/content/locales/zh-TW/cloneable-saas.md +114 -0
- package/docs/content/locales/zh-TW/code-agents-ui.md +436 -0
- package/docs/content/locales/zh-TW/components.md +368 -0
- package/docs/content/locales/zh-TW/context-awareness.md +373 -0
- package/docs/content/locales/zh-TW/creating-templates.md +411 -0
- package/docs/content/locales/zh-TW/cross-app-sso.md +188 -0
- package/docs/content/locales/zh-TW/database.md +183 -0
- package/docs/content/locales/zh-TW/deployment.md +348 -0
- package/docs/content/locales/zh-TW/dispatch.md +146 -0
- package/docs/content/locales/zh-TW/drop-in-agent.md +260 -0
- package/docs/content/locales/zh-TW/durable-resume.md +65 -0
- package/docs/content/locales/zh-TW/embedding-sdk.md +597 -0
- package/docs/content/locales/zh-TW/evals.md +155 -0
- package/docs/content/locales/zh-TW/extensions.md +360 -0
- package/docs/content/locales/zh-TW/external-agents.md +619 -0
- package/docs/content/locales/zh-TW/faq.md +142 -0
- package/docs/content/locales/zh-TW/file-uploads.md +122 -0
- package/docs/content/locales/zh-TW/frames.md +153 -0
- package/docs/content/locales/zh-TW/getting-started.md +199 -0
- package/docs/content/locales/zh-TW/harness-agents.md +349 -0
- package/docs/content/locales/zh-TW/human-approval.md +86 -0
- package/docs/content/locales/zh-TW/internationalization.md +147 -0
- package/docs/content/locales/zh-TW/key-concepts.md +312 -0
- package/docs/content/locales/zh-TW/local-file-mode.md +433 -0
- package/docs/content/locales/zh-TW/mcp-apps.md +147 -0
- package/docs/content/locales/zh-TW/mcp-clients.md +330 -0
- package/docs/content/locales/zh-TW/mcp-protocol.md +279 -0
- package/docs/content/locales/zh-TW/messaging.md +461 -0
- package/docs/content/locales/zh-TW/migration-workbench.md +33 -0
- package/docs/content/locales/zh-TW/multi-app-workspace.md +312 -0
- package/docs/content/locales/zh-TW/multi-tenancy.md +52 -0
- package/docs/content/locales/zh-TW/native-chat-ui.md +321 -0
- package/docs/content/locales/zh-TW/notifications.md +231 -0
- package/docs/content/locales/zh-TW/observability.md +294 -0
- package/docs/content/locales/zh-TW/observational-memory.md +77 -0
- package/docs/content/locales/zh-TW/onboarding.md +216 -0
- package/docs/content/locales/zh-TW/plan-plugin.md +200 -0
- package/docs/content/locales/zh-TW/pr-visual-recap.md +384 -0
- package/docs/content/locales/zh-TW/processors.md +106 -0
- package/docs/content/locales/zh-TW/progress.md +199 -0
- package/docs/content/locales/zh-TW/pure-agent-apps.md +39 -0
- package/docs/content/locales/zh-TW/real-time-collaboration.md +680 -0
- package/docs/content/locales/zh-TW/recurring-jobs.md +142 -0
- package/docs/content/locales/zh-TW/routing.md +79 -0
- package/docs/content/locales/zh-TW/sandbox-adapters.md +227 -0
- package/docs/content/locales/zh-TW/security.md +330 -0
- package/docs/content/locales/zh-TW/server.md +265 -0
- package/docs/content/locales/zh-TW/sharing.md +219 -0
- package/docs/content/locales/zh-TW/skills-guide.md +281 -0
- package/docs/content/locales/zh-TW/template-analytics.md +259 -0
- package/docs/content/locales/zh-TW/template-assets.md +303 -0
- package/docs/content/locales/zh-TW/template-brain.md +324 -0
- package/docs/content/locales/zh-TW/template-calendar.md +194 -0
- package/docs/content/locales/zh-TW/template-chat.md +129 -0
- package/docs/content/locales/zh-TW/template-clips.md +368 -0
- package/docs/content/locales/zh-TW/template-content.md +402 -0
- package/docs/content/locales/zh-TW/template-design.md +173 -0
- package/docs/content/locales/zh-TW/template-dispatch.md +220 -0
- package/docs/content/locales/zh-TW/template-forms.md +178 -0
- package/docs/content/locales/zh-TW/template-mail.md +239 -0
- package/docs/content/locales/zh-TW/template-plan.md +814 -0
- package/docs/content/locales/zh-TW/template-slides.md +293 -0
- package/docs/content/locales/zh-TW/template-videos.md +222 -0
- package/docs/content/locales/zh-TW/tracking.md +236 -0
- package/docs/content/locales/zh-TW/using-your-agent.md +71 -0
- package/docs/content/locales/zh-TW/voice-input.md +81 -0
- package/docs/content/locales/zh-TW/what-is-agent-native.md +202 -0
- package/docs/content/locales/zh-TW/workspace-connections.md +321 -0
- package/docs/content/locales/zh-TW/workspace-management.md +175 -0
- package/docs/content/locales/zh-TW/workspace.md +323 -0
- package/docs/content/locales/zh-TW/writing-agent-instructions.md +173 -0
- package/package.json +2 -2
- package/src/templates/default/app/i18n/index.ts +2 -0
- package/src/templates/default/app/i18n/zh-TW.ts +466 -0
- package/src/templates/default/app/root.tsx +8 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "建立範本"
|
|
3
|
+
description: "如何建立和發布您自己的代理本機應用範本。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 建立範本
|
|
7
|
+
|
|
8
|
+
範本是完整的、可分叉的代理本機應用程式,可解決實際工作流程。第一方範本使用您使用的相同框架表面建置:用於 UI 的 React 路由、用於資料的 Drizzle SQL、用於操作的 actions、用於代理行為的工作區資源以及輪詢同步,以便代理和 UI 保持一致。
|
|
9
|
+
|
|
10
|
+
一個好的範本:
|
|
11
|
+
|
|
12
|
+
- 使用有用的種子資料或空狀態流端對端地解決一個工作流。
|
|
13
|
+
- 將持久狀態存儲在 SQL 中,而不是 JSON 檔案中。
|
|
14
|
+
- 將應用操作定義為 `defineAction()` actions。
|
|
15
|
+
- 通過應用程式狀態公開導覽和選取。
|
|
16
|
+
- 為不明顯的工作流程提供清晰的 `AGENTS.md` 和重點 skills。
|
|
17
|
+
- 註冊所需提供者和機密的加入步驟。
|
|
18
|
+
- 作為獨立應用和多應用工作區的一部分工作。
|
|
19
|
+
|
|
20
|
+
## 從聊天開始 {#start-from-chat}
|
|
21
|
+
|
|
22
|
+
當您想要一個框架連線已就位的最小應用程式時,請使用聊天範本:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx @agent-native/core@latest create my-template --template chat --standalone
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
對於具有多個應用程式的工作區,執行選取器並包含與您想要的任何域範本的聊天:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @agent-native/core@latest create my-platform
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
聊天為您提供驗證、持久聊天線程、SQL 支持的資源、工具、應用程式狀態、actions 和輪詢同步。您新增域模型和產品 UI。
|
|
35
|
+
|
|
36
|
+
如果您尚未建置可重複使用的 UI 範本,請使用 [Getting Started](/docs/getting-started#1-create-your-app) 中的無頭入口:定義一個操作,使用 `pnpm agent` 執行它,並在工作流程需要耐用表面時新增 UI。
|
|
37
|
+
|
|
38
|
+
## 專案結構 {#project-structure}
|
|
39
|
+
|
|
40
|
+
每個範本都遵循相同的廣泛布局:
|
|
41
|
+
|
|
42
|
+
```an-file-tree title="範本專案結構"
|
|
43
|
+
{
|
|
44
|
+
"title": "my-template/",
|
|
45
|
+
"entries": [
|
|
46
|
+
{ "path": "app/", "note": "React 前端" },
|
|
47
|
+
{ "path": "app/root.tsx", "note": "HTML shell 和 providers" },
|
|
48
|
+
{ "path": "app/routes/", "note": "React Router 檔案路由" },
|
|
49
|
+
{ "path": "app/components/", "note": "範本 UI" },
|
|
50
|
+
{ "path": "app/hooks/", "note": "UI 狀態和資料 hooks" },
|
|
51
|
+
{ "path": "actions/", "note": "defineAction 操作:唯一事實來源" },
|
|
52
|
+
{ "path": "server/db/schema.ts", "note": "Drizzle 架構" },
|
|
53
|
+
{ "path": "server/plugins/db.ts", "note": "增量 migrations" },
|
|
54
|
+
{ "path": "server/plugins/", "note": "啟動 integrations" },
|
|
55
|
+
{ "path": "server/routes/api/", "note": "僅在 actions 不夠時使用自訂路由" },
|
|
56
|
+
{ "path": "shared/types.ts", "note": "共用的 client/server 型別" },
|
|
57
|
+
{ "path": ".agents/skills/", "note": "<skill>/SKILL.md:複雜工作流的代理指南" },
|
|
58
|
+
{ "path": "AGENTS.md", "note": "範本專用代理指令" },
|
|
59
|
+
{ "path": "package.json" },
|
|
60
|
+
{ "path": "react-router.config.ts" },
|
|
61
|
+
{ "path": "vite.config.ts" }
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
不要為應用程式狀態新增 `data/` 目錄。持久應用資料屬於 SQL,UI 通過 actions 或型別化伺服器處理程序讀取它。
|
|
67
|
+
|
|
68
|
+
每個範本的四個區域通過一個共用操作介面和一個 SQL 資料庫連線在一起 - 代理和 UI 是執行相同操作的平等合作伙伴:
|
|
69
|
+
|
|
70
|
+
```an-diagram title="範本的四個區域如何連線" summary="UI 和代理都通過相同的操作到達 SQL;應用程式狀態和輪詢同步使它們保持一致。"
|
|
71
|
+
{
|
|
72
|
+
"html": "<div class=\"diagram-tmpl\"><div class=\"diagram-col\"><div class=\"diagram-node\">React 介面<br><small class=\"diagram-muted\">app/routes · 元件</small></div><div class=\"diagram-node\">Agent<br><small class=\"diagram-muted\">AGENTS.md · skills</small></div></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-panel center\"><span class=\"diagram-pill accent\">行動</span><small class=\"diagram-muted\">defineAction()</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough>通過 Drizzle 使用 SQL<br><small class=\"diagram-muted\">additive schema</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">↻</div><div class=\"diagram-pill ok\">輪詢ing sync</div></div>",
|
|
73
|
+
"css": ".diagram-tmpl{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-tmpl .diagram-col{display:flex;flex-direction:column;gap:10px}.diagram-tmpl .diagram-arrow{font-size:22px;line-height:1}.diagram-tmpl .center{display:flex;flex-direction:column;align-items:center;gap:4px}"
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## SQL中的模型資料 {#data-models}
|
|
78
|
+
|
|
79
|
+
使用框架 Drizzle 幫助程序定義域表,以便架構在 SQLite、Postgres、D1、Turso、Supabase、Neon 和其他支持的後端之間保持可移植性:
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
// server/db/schema.ts
|
|
83
|
+
import {
|
|
84
|
+
table,
|
|
85
|
+
text,
|
|
86
|
+
integer,
|
|
87
|
+
now,
|
|
88
|
+
ownableColumns,
|
|
89
|
+
createSharesTable,
|
|
90
|
+
} from "@agent-native/core/db/schema";
|
|
91
|
+
|
|
92
|
+
export const projects = table("projects", {
|
|
93
|
+
id: text("id").primaryKey(),
|
|
94
|
+
title: text("title").notNull(),
|
|
95
|
+
status: text("status", {
|
|
96
|
+
enum: ["draft", "active", "archived"],
|
|
97
|
+
})
|
|
98
|
+
.notNull()
|
|
99
|
+
.default("draft"),
|
|
100
|
+
sortOrder: integer("sort_order").notNull().default(0),
|
|
101
|
+
...ownableColumns(),
|
|
102
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
103
|
+
updatedAt: text("updated_at").notNull().default(now()),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
export const projectShares = createSharesTable("project_shares");
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
架構更改必須是附加的。 `server/plugins/db.ts`中通過`runMigrations()`新增表和列;切勿使用破壞性的 SQL、`drizzle-kit push`、表重命名或列刪除。
|
|
110
|
+
|
|
111
|
+
對於應用程式讀取和寫入,請使用 Drizzle 的查詢生成器和 `drizzle-orm` 的可移植運算符。當Drizzle可以表達查詢時,不要使用原始SQL編寫產品程式碼,並且不要在範本中從`drizzle-orm/sqlite-core`或`drizzle-orm/pg-core`匯入。
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
// server/plugins/db.ts
|
|
115
|
+
import { runMigrations } from "@agent-native/core/db";
|
|
116
|
+
|
|
117
|
+
export default runMigrations(
|
|
118
|
+
[
|
|
119
|
+
{
|
|
120
|
+
version: 1,
|
|
121
|
+
sql: `CREATE TABLE IF NOT EXISTS projects (
|
|
122
|
+
id TEXT PRIMARY KEY,
|
|
123
|
+
title TEXT NOT NULL,
|
|
124
|
+
status TEXT NOT NULL DEFAULT 'draft',
|
|
125
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
126
|
+
owner_email TEXT NOT NULL,
|
|
127
|
+
org_id TEXT,
|
|
128
|
+
visibility TEXT NOT NULL DEFAULT 'private',
|
|
129
|
+
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
130
|
+
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
131
|
+
)`,
|
|
132
|
+
},
|
|
133
|
+
],
|
|
134
|
+
{ table: "my_app_migrations" },
|
|
135
|
+
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
在新增儲存使用者或組織資料的架構之前,請使用 [Database](/docs/database) 和 [Security](/docs/security) 檔案。
|
|
139
|
+
|
|
140
|
+
## 將操作定義為行動 {#actions}
|
|
141
|
+
|
|
142
|
+
行動 是應用行為的單一事實來源。代理將它們作為工具調用,前端通過鉤子調用它們,其他應用程式可以通過 MCP/A2A 存取它們。
|
|
143
|
+
|
|
144
|
+
```an-annotated-code title="actions/create-project.ts"
|
|
145
|
+
{
|
|
146
|
+
"filename": "actions/create-project.ts",
|
|
147
|
+
"language": "ts",
|
|
148
|
+
"code": "import { defineAction } from \"@agent-native/core/action\";\nimport { getDb } from \"../server/db/index.js\";\nimport { nanoid } from \"nanoid\";\nimport { z } from \"zod\";\nimport * as schema from \"../server/db/schema\";\n\nexport default defineAction({\n description: \"Create a project.\",\n schema: z.object({\n title: z.string().min(1).describe(\"Project title\"),\n }),\n run: async ({ title }, ctx) => {\n const db = getDb();\n const id = nanoid();\n await db.insert(schema.projects).values({\n id,\n title,\n ownerEmail: ctx.userEmail,\n orgId: ctx.orgId,\n });\n return { id, title };\n },\n});",
|
|
149
|
+
"annotations": [
|
|
150
|
+
{ "lines": "2", "note": "`getDb` is created per app via `createGetDb(schema)` in `server/db/index.ts`." },
|
|
151
|
+
{ "lines": "8", "label": "工具表面", "note": "`description` 是代理讀取的內容,以決定何時將此操作作為工具調用。" },
|
|
152
|
+
{ "lines": "9-11", "label": "型別化契約", "note": "一個 zod `schema` 會驗證來自代理、UI、HTTP、MCP 和 A2A 的輸入。" },
|
|
153
|
+
{ "lines": "18-19", "label": "範圍寫入", "note": "從 `ctx` 標記 `ownerEmail` / `orgId`,以便該行正確地確定共用和存取檢查的範圍。" }
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
使用 `http: { method: "GET" }` 或 `readOnly: true` 表示唯讀 actions。僅將 `parallelSafe: true` 用於變異 actions,這些 actions 可以安全地與同輪工具調用同時執行。將 `toolCallable: false` 用於不應從沙盒工具執行的高爆炸半徑 actions。
|
|
159
|
+
|
|
160
|
+
## 建置 UI {#ui}
|
|
161
|
+
|
|
162
|
+
路由位於 `app/routes/` 中並使用 React Router v8 檔案路由。通過actions或API處理程序查詢資料,並預設使突變樂觀。
|
|
163
|
+
|
|
164
|
+
```tsx
|
|
165
|
+
import { useActionMutation, useActionQuery } from "@agent-native/core/client";
|
|
166
|
+
|
|
167
|
+
export default function ProjectsPage() {
|
|
168
|
+
const { data: projects = [] } = useActionQuery("list-projects", {});
|
|
169
|
+
const create = useActionMutation("create-project");
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<button onClick={() => create.mutate({ title: "Launch plan" })}>
|
|
173
|
+
New project ({projects.length})
|
|
174
|
+
</button>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
在應用程式 shell 附近連線一次實時同步,以便在代理、另一個分頁或操作更改資料時刷新 React 查詢快取:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import { useDbSync } from "@agent-native/core/client";
|
|
183
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
184
|
+
|
|
185
|
+
export function AppSync() {
|
|
186
|
+
const queryClient = useQueryClient();
|
|
187
|
+
useDbSync({ queryClient });
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**代理原生承諾:代理寫入顯示在 UI 中,無需手動刷新。** `useActionQuery` 是簡單路徑 - 當變異操作發出 `source: "action"` 時,每個鉤子都會重新獲取。如果您使用自訂金鑰(例如,讀取整合狀態的低級用戶端幫助程序)獲取原始 `useQuery`,請將每個來源計數器折疊到 queryKey 中以進行有針對性的刷新:
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { useChangeVersions } from "@agent-native/core/client";
|
|
196
|
+
|
|
197
|
+
const v = useChangeVersions(["dashboards", "action"]);
|
|
198
|
+
useQuery({
|
|
199
|
+
queryKey: ["dashboard", id, v],
|
|
200
|
+
queryFn: () => fetchDashboard(id),
|
|
201
|
+
placeholderData: (prev) => prev, // no flicker on refetch
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
常見來源:`"action"`(每個成功的代理操作 - 可靠的後備)、`"app-state"`、`"settings"`,以及您的商店通過 `recordChange` 發出的任何自訂資源來源。完整模式請參見 `real-time-sync` 技能。
|
|
206
|
+
|
|
207
|
+
## 新增應用程式狀態 {#application-state}
|
|
208
|
+
|
|
209
|
+
應用程式狀態是代理如何了解使用者所看到的內容。至少新增:
|
|
210
|
+
|
|
211
|
+
- 一個 UI 鉤子,當路由、所選紀錄、活動分頁或編輯器選取發生更改時,它會寫入語義 `navigation` 狀態。
|
|
212
|
+
- 讀取該狀態並返回目前螢幕快照的 `view-screen` 操作。
|
|
213
|
+
- 一個 `navigate` 操作,寫入一次性 `navigate` 指令以供 UI 使用。
|
|
214
|
+
|
|
215
|
+
使用 `useAgentRouteState` 作為 UI 掛鉤,以便應用程式狀態寫入、分頁範圍指令讀取、讀取後刪除和重複指令保護保持一致:
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
import { useAgentRouteState } from "@agent-native/core/client";
|
|
219
|
+
import { TAB_ID } from "@/lib/tab-id";
|
|
220
|
+
|
|
221
|
+
export function useNavigationState() {
|
|
222
|
+
useAgentRouteState({
|
|
223
|
+
browserTabId: TAB_ID,
|
|
224
|
+
requestSource: TAB_ID,
|
|
225
|
+
getNavigationState: ({ pathname, searchParams }) => ({
|
|
226
|
+
view: pathname === "/" ? "home" : pathname.slice(1),
|
|
227
|
+
selectedId: searchParams.get("id"),
|
|
228
|
+
}),
|
|
229
|
+
getCommandPath: (command: any) => command.path ?? "/",
|
|
230
|
+
navigateOptions: { replace: true, flushSync: true },
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
在 URL 查詢參數中保留可共用過濾器。框架將它們公開為 `<current-url>` 代理,內置代理可以使用 `set-search-params` 更改它們; `navigation` 應儲存語義 ID 和別名,而不是完整查詢字串的第二個副本。
|
|
236
|
+
|
|
237
|
+
對於應用導覽,首選包含同來源的 `navigate` 指令
|
|
238
|
+
`path`(當 URL 已知時)。同一動作不要寫為 `__set_url__`;
|
|
239
|
+
該金鑰是為框架 URL 工具和僅 URL 過濾器更改保留的。
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
// actions/navigate.ts
|
|
243
|
+
import { defineAction } from "@agent-native/core/action";
|
|
244
|
+
import { writeAppState } from "@agent-native/core/application-state";
|
|
245
|
+
import { z } from "zod";
|
|
246
|
+
|
|
247
|
+
export default defineAction({
|
|
248
|
+
description: "Navigate the UI.",
|
|
249
|
+
schema: z.object({
|
|
250
|
+
view: z.enum(["home", "project"]),
|
|
251
|
+
projectId: z.string().optional(),
|
|
252
|
+
path: z.string().optional(),
|
|
253
|
+
}),
|
|
254
|
+
run: async (args) => {
|
|
255
|
+
await writeAppState("navigate", args);
|
|
256
|
+
return { ok: true };
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
請參閱 [Context Awareness](/docs/context-awareness) 了解完整模式。
|
|
262
|
+
|
|
263
|
+
## 謹慎使用 API 路由 {#api-routes}
|
|
264
|
+
|
|
265
|
+
首選 actions 進行應用操作。僅為無法幹淨地成為 actions 的表面建立自訂 Nitro 路線:
|
|
266
|
+
|
|
267
|
+
- 檔案上傳或二進制流。
|
|
268
|
+
- 公開匿名頁面和webhooks。
|
|
269
|
+
- OAuth 回呼和特定於提供者的協議處理程序。
|
|
270
|
+
- 伺服器渲染的公開內容。
|
|
271
|
+
|
|
272
|
+
在使用存取助手之前,接觸可擁有資料的自訂路由必須調用 `getSession(event)` 並將資料庫工作包裝在 `runWithRequestContext({ userEmail, orgId }, fn)` 中。
|
|
273
|
+
|
|
274
|
+
## 編寫代理指令 {#write-agents-md}
|
|
275
|
+
|
|
276
|
+
`AGENTS.md` 是您的應用程式的代理地圖 - 一個可瀏覽的小檔案,帶有
|
|
277
|
+
目的行、核心規則、應用程式狀態鍵、操作表和 skills
|
|
278
|
+
索引:
|
|
279
|
+
|
|
280
|
+
```markdown
|
|
281
|
+
# 我的範本
|
|
282
|
+
|
|
283
|
+
One workspace for projects, tasks, and notes.
|
|
284
|
+
|
|
285
|
+
## 核心規則
|
|
286
|
+
|
|
287
|
+
- Data lives in 通過 Drizzle 使用 SQL. Use actions for all writes; schema is additive.
|
|
288
|
+
- Use `view-screen` before acting on "this project" if the screen is unclear.
|
|
289
|
+
|
|
290
|
+
## 應用狀態
|
|
291
|
+
|
|
292
|
+
- `navigation.view`: `home` | `project`
|
|
293
|
+
- `navigation.projectId`: selected project on a project page
|
|
294
|
+
|
|
295
|
+
## 行動
|
|
296
|
+
|
|
297
|
+
| Action | Purpose |
|
|
298
|
+
| ---------------- | ------------------------ |
|
|
299
|
+
| `list-projects` | List accessible projects |
|
|
300
|
+
| `create-project` | Create a project |
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
每當新增新操作、路線、狀態鍵或重複操作時更新 `AGENTS.md`
|
|
304
|
+
工作流程。 [Writing Agent Instructions](/docs/writing-agent-instructions) 是
|
|
305
|
+
完整指南 - 如何保持 `AGENTS.md` 可略讀,這四個分別屬於什么
|
|
306
|
+
指導面,以及如何表達技能和工具描述,以便代理
|
|
307
|
+
可靠地觸發它們。
|
|
308
|
+
|
|
309
|
+
## 新增Skills {#skills}
|
|
310
|
+
|
|
311
|
+
使用 skills 來獲取會使 `AGENTS.md` 膨脹的詳細模式:特定於提供者的 API、匯入/匯出格式、複雜的編輯流程或域術語。
|
|
312
|
+
|
|
313
|
+
```markdown
|
|
314
|
+
---
|
|
315
|
+
name: project-imports
|
|
316
|
+
description: How to import projects from the legacy CSV export.
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
# 專案進口
|
|
320
|
+
|
|
321
|
+
Use this skill when the user uploads a legacy project CSV.
|
|
322
|
+
|
|
323
|
+
## 規則
|
|
324
|
+
|
|
325
|
+
- Validate required columns before creating rows.
|
|
326
|
+
- Use `create-project` for each project so ownership and sync are correct.
|
|
327
|
+
- Save rejected rows as a note attached to the import summary.
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
將範本 skills 存儲在 `.agents/skills/<name>/SKILL.md` 中。如果使用者應該能夠在執行時編輯指南,也可以通過工作區資源來顯示它。
|
|
331
|
+
|
|
332
|
+
## 註冊設定步驟 {#onboarding}
|
|
333
|
+
|
|
334
|
+
如果範本需要 API 金鑰、OAuth 連線或提供者帳戶,請註冊入門步驟,而不是將要求隱藏在 README 中。
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
// server/plugins/onboarding.ts
|
|
338
|
+
import { defineNitroPlugin } from "@agent-native/core/server";
|
|
339
|
+
import { registerOnboardingStep } from "@agent-native/core/onboarding";
|
|
340
|
+
|
|
341
|
+
export default defineNitroPlugin(() => {
|
|
342
|
+
registerOnboardingStep({
|
|
343
|
+
id: "github",
|
|
344
|
+
title: "Connect GitHub",
|
|
345
|
+
description: "Needed to import repositories and pull requests.",
|
|
346
|
+
order: 100,
|
|
347
|
+
methods: [
|
|
348
|
+
{
|
|
349
|
+
id: "token",
|
|
350
|
+
kind: "form",
|
|
351
|
+
primary: true,
|
|
352
|
+
label: "Save token",
|
|
353
|
+
payload: {
|
|
354
|
+
fields: [
|
|
355
|
+
{ key: "GITHUB_TOKEN", label: "GitHub token", secret: true },
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
isComplete: () => !!process.env.GITHUB_TOKEN,
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
參見[Onboarding & API Keys](/docs/onboarding)。
|
|
366
|
+
|
|
367
|
+
## 使其適合工作空間 {#workspace-ready}
|
|
368
|
+
|
|
369
|
+
範本應自然地適合 [Multi-App Workspaces](/docs/multi-app-workspace),通常由 [Dispatch](/docs/dispatch) 協調。
|
|
370
|
+
|
|
371
|
+
清單:
|
|
372
|
+
|
|
373
|
+
- 通過框架代理聊天外掛或 `mountA2A()` 掛載 A2A,以便同級應用程式可以調用您的代理。
|
|
374
|
+
- 保持代理卡描述足夠具體,以便 Dispatch 準確地安排工作。
|
|
375
|
+
- 註冊所需的機密/加入,以便設定出現在側欄中,並且 Dispatch 可以管理共用憑證。
|
|
376
|
+
- 將橫切指令保留在工作區 `AGENTS.md` 或工作區資源中,而不是複製到每個應用程式中。
|
|
377
|
+
- 對所有可擁有的資源使用共用/存取幫助程序,以便組織範圍內的工作空間保持隔離。
|
|
378
|
+
|
|
379
|
+
## 發布範本 {#publishing}
|
|
380
|
+
|
|
381
|
+
分享之前:
|
|
382
|
+
|
|
383
|
+
1. 執行 `pnpm install`、`pnpm typecheck` 和範本的測試。
|
|
384
|
+
2. 驗證其是否可以在未設定可選提供程序金鑰的情況下正常工作。
|
|
385
|
+
3. 檢查驗證、共用和兩個使用者資料隔離。
|
|
386
|
+
4. 紀錄所需的環境變數和入門步驟。
|
|
387
|
+
5. 通過附加遷移包含範例或種子行,而不是跟蹤的執行時資料檔案。
|
|
388
|
+
|
|
389
|
+
可以從 GitHub 儲存庫建立社區範本:
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
npx @agent-native/core@latest create my-app --template github:user/repo
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## 為框架 monorepo 做出貢獻 {#contributing}
|
|
396
|
+
|
|
397
|
+
### 測試未發布的框架更改 {#test-unpublished-framework-changes}
|
|
398
|
+
|
|
399
|
+
當您在框架 monorepo 中工作並需要生成時
|
|
400
|
+
工作區使用未發布的包或範本更改,使用
|
|
401
|
+
本機包標志:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
AGENT_NATIVE_CREATE_USE_LOCAL_CORE=1 pnpm --filter @agent-native/core create my-platform
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
生成的工作空間連結本機`@agent-native/core`和
|
|
408
|
+
`@agent-native/dispatch` 軟件包,因此更改為 Core API、Dispatch 工作區
|
|
409
|
+
可以在發布之前測試行為或第一方範本。包裹
|
|
410
|
+
`prepack` 腳本在連結之前建置 `dist`,這會保留生成的
|
|
411
|
+
工作空間指向目前建置輸出。
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "跨應用SSO"
|
|
3
|
+
description: "使用 Dispatch 作為身分授權,通過身分聯合在每個託管代理本機應用程式中登入一次 - 每個應用程式選取加入,可通過單個環境變數進行逆轉。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 跨應用SSO
|
|
7
|
+
|
|
8
|
+
`*.agent-native.com` 上的每個託管應用程式都使用其**自己的獨立使用者存儲**執行自己的部署。 `mail.agent-native.com`和`calendar.agent-native.com`不共用資料庫、工作階段表或cookie域。因此,“登入一次,使用每個應用程式”不能是共用 cookie — 它必須是**身分聯合**,其中 [Dispatch](/docs/dispatch) 充當工作區的身分授權機構。
|
|
9
|
+
|
|
10
|
+
這與 [A2A](/docs/a2a-protocol) 和 [External Agents](/docs/external-agents) 已經使用的信任原語相同 - 在請求邊界驗證的 `A2A_SECRET` 簽名的 JWT - 應用於人工登入路徑,而不是代理到代理的調用。
|
|
11
|
+
|
|
12
|
+
> **統一部署與每個域部署。** 如果您在一個來源(`your-agents.com/mail`、`your-agents.com/calendar`)託管所有應用程式,您已經通過單個 cookie 域獲得共用登入 - 無需聯合。僅當應用程式在不同的域上執行時,才需要跨應用程式 SSO。參見[Multi-App Workspaces — Unified deploy](/docs/multi-app-workspace#deployment)。
|
|
13
|
+
|
|
14
|
+
## 什么以及為什么 {#what-why}
|
|
15
|
+
|
|
16
|
+
每個應用程式的使用者存儲意味著瀏覽器 cookie 沒有一個可以被每個應用程式信任的地方。相反,聯合模型將一個應用程式命名為 **Dispatch** 作為身分授權機構。任何其他應用程式都可以委托“這個人是誰?”要調度,取回使用者已驗證電子郵件的短暫簽名斷言,然後**通過電子郵件將其連結到其自己的本機帳戶**。
|
|
17
|
+
|
|
18
|
+
連結規則故意狹窄和附加:
|
|
19
|
+
|
|
20
|
+
- **現有同一電子郵件使用者→連結。**本機帳戶與經過驗證的電子郵件匹配並按原樣重複使用。它**永遠不會被修改、重命名或刪除** - 聯合層只會讀取它並為其建立一個工作階段。
|
|
21
|
+
- **新電子郵件 → 建立。** 為該經過驗證的電子郵件建立一個新的本機帳戶,然後建立一個正常的本機工作階段。
|
|
22
|
+
|
|
23
|
+
這使得部署安全,即使它會導致人們退出。 **預計會登出。** 當應用程式開啟此功能時,現有工作階段將結束,並且使用者通過 Dispatch 重新進行驗證。但他們總是重新登入**同一個電子郵件匹配帳戶,所有資料都完好無損**,因為身分行只會*新增到* — 永遠不會被銷毀、重命名或重新指向。
|
|
24
|
+
|
|
25
|
+
## 它是如何工作的 {#how-it-works}
|
|
26
|
+
|
|
27
|
+
該流程是標準授權 → 簽名權杖 → 回調重新導向,其中電子郵件是唯一跨越信任邊界的內容。
|
|
28
|
+
|
|
29
|
+
```an-diagram title="身分聯合流程" summary="Dispatch 對人員進行驗證,並返回一件事的短暫簽名斷言 - 經過驗證的電子郵件。該應用程式通過電子郵件連結並建立自己的本機工作階段。"
|
|
30
|
+
{
|
|
31
|
+
"html": "<div class=\"diagram-sso\"><div class=\"diagram-card\" data-rough><strong>用戶端應用</strong><small class=\"diagram-muted\">own user store</small></div><div class=\"diagram-step\"><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><span class=\"diagram-pill\">authorize</span></div><div class=\"diagram-card\" data-rough><strong>Dispatch</strong><small class=\"diagram-muted\">identity authority</small><span class=\"diagram-pill accent\">authenticates human</span></div><div class=\"diagram-step\"><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><span class=\"diagram-pill accent\">302 + signed JWT</span></div><div class=\"diagram-card\" data-rough><strong>應用回調</strong><small class=\"diagram-muted\">verify signature · scope:identity · exp ≤ 2 min</small><span class=\"diagram-pill ok\">通過郵箱即時關聯</span><span class=\"diagram-pill ok\">mint local session</span></div></div>",
|
|
32
|
+
"css": ".diagram-sso{display:flex;align-items:stretch;gap:12px;flex-wrap:wrap}.diagram-sso .diagram-card{display:flex;flex-direction:column;gap:6px;padding:14px 16px;min-width:150px}.diagram-sso .diagram-step{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px}.diagram-sso .diagram-arrow{font-size:22px;line-height:1}"
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
1. **應用程式→調度(授權)。**應用程式將使用者發送到身分授權機構:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
GET https://dispatch.agent-native.com/_agent-native/identity/authorize
|
|
40
|
+
?app=<requesting-app>
|
|
41
|
+
&redirect_uri=<app-callback-url>
|
|
42
|
+
&狀態=<csrf-state>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
``an-api title="身分授權端點"
|
|
46
|
+
{
|
|
47
|
+
“方法”:“GET”,
|
|
48
|
+
“路徑”:“/_agent-native/identity/authorize”,
|
|
49
|
+
“summary”:“Dispatch(身分授權)對人員進行驗證並使用簽名的身分權杖重新導向回來”,
|
|
50
|
+
"auth": "調度工作階段(如果沒有則互動式登入)",
|
|
51
|
+
“參數”:[
|
|
52
|
+
{ "name": "app", "in": "query", "type": "string", "required": true, "description": "請求的應用程式標識符。" },
|
|
53
|
+
{ "name": "redirect_uri", "in": "query", "type": "string", "required": true, "description": "應用程式回調 URL。根據嚴格的允許清單進行驗證(預設為 `\*.agent-native.com`或 localhost)。" },
|
|
54
|
+
{ "name": "state", "in": "query", "type": "string", "required": true, "description": "CSRF 狀態在重新導向上回顯。" }
|
|
55
|
+
],
|
|
56
|
+
“回應”:[
|
|
57
|
+
{ "status": "302", "description": "重新導向到`redirect_uri`,攜帶短暫的 `A2A_SECRET` 簽名身分 JWT(`scope: \"identity\"`、`exp`≤ 2 分鐘)加上原始`state`。" },
|
|
58
|
+
{ "status": "400", "description": "`redirect_uri`未通過允許清單驗證(跨來源、方案相關`//host` 或未列出的後綴)。" }
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
2. **Dispatch 對人員進行驗證。** 如果使用者已有 Dispatch 工作階段,則這是透明的。如果沒有,Dispatch 將顯示其自己的正常登入資訊(電子郵件/密碼、Google 等 — 請參閱 [Authentication](/docs/authentication))。 Dispatch 只是一個常規的代理原生應用程式;它沒有執行特殊的驗證模式。
|
|
67
|
+
|
|
68
|
+
3. **調度→應用程式(簽名身分權杖)。**調度根據嚴格的允許清單驗證`redirect_uri`,並302重新導向回應用程式的`redirect_uri`,攜帶短暫的**`A2A_SECRET`簽名身分JWT**。權杖的聲明故意最小化:
|
|
69
|
+
|
|
70
|
+
| 聲明 | 含義 |
|
|
71
|
+
| ------------ | ------------------------------------------- |
|
|
72
|
+
| `sub` | 身分機構的穩定使用者ID |
|
|
73
|
+
| `email` | 使用者的**已驗證**電子郵件 - 唯一的加入金鑰 |
|
|
74
|
+
| `name` | 顯示名稱(非權威,僅適用於UI) |
|
|
75
|
+
| `org_domain` | 工作空間/組織域(如果存在) |
|
|
76
|
+
| `scope` | 始終為 `"identity"` — 此權杖僅授權登入 |
|
|
77
|
+
| `exp` | **≤ 2 分鐘** 距問題 |
|
|
78
|
+
|
|
79
|
+
4. **應用程式通過電子郵件驗證和 JIT 連結。**應用程式使用自己的 `A2A_SECRET` 驗證權杖簽名,檢查 `scope: "identity"` 和 `exp`,然後嚴格通過經過驗證的電子郵件執行**即時連結**:
|
|
80
|
+
- 如果具有該電子郵件地址的本機使用者存在 → 不加修改地重新使用它。
|
|
81
|
+
- 如果沒有 → 為該電子郵件建立本機使用者。
|
|
82
|
+
|
|
83
|
+
5. **應用程式建立一個普通的本機工作階段。**從這裡開始,使用者在該應用程式自己的商店中擁有一個普通的本機工作階段 - 每個現有的存取檢查、組織範圍和操作防護都與以前完全相同。聯邦只發生在前門。
|
|
84
|
+
|
|
85
|
+
### 選取加入 {#opt-in}
|
|
86
|
+
|
|
87
|
+
應用**僅**在其部署中設定此環境變數時參與:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.agent-native.com
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **設定** → 應用程式顯示執行上述流程的**“使用 Agent-Native 登入”**選項。直接本機登入(電子郵件/密碼、Google)仍然可以與它一起使用。
|
|
94
|
+
- **取消設定(預設)** → **零行為改變。** 應用程式的驗證與之前完全相同;聯合程式碼路徑處於休眠狀態。沒有架構更改,也沒有任何需要遷移的內容,因此開啟或關閉變數在任何時候都是完全可逆的。
|
|
95
|
+
|
|
96
|
+
## 安全 {#security}
|
|
97
|
+
|
|
98
|
+
整個模型依賴於一些故意的小保證:
|
|
99
|
+
|
|
100
|
+
- **短暫的簽名權杖。**身分斷言是 `A2A_SECRET` 簽名的 JWT,具有 **≤ 2 分鐘** 到期時間和 `scope: "identity"`。它授權單次登入,並且不能長時間重播或重新用於 API/A2A 存取。
|
|
101
|
+
- **嚴格的 `redirect_uri` 允許清單。** 預設情況下,調度僅重新導向到 `*.agent-native.com` 或本機主機。任意、方案相關 (`//host`) 和跨域重新導向目標都會被拒絕,因此權限無法轉變為開放重新導向或權杖滲透預言機。
|
|
102
|
+
- **從經過驗證的權杖僅通過電子郵件加入。** 跨越信任邊界的*唯一*事物是簽名權杖中經過驗證的電子郵件。該應用程式不接受來自線路的使用者 ID、角色、組織成員資格或任何特權狀態 - 它從匹配的帳戶在本機派生所有內容。
|
|
103
|
+
- **僅新增身分寫入。**連結可以不受影響地重複使用現有的同一電子郵件帳戶,也可以插入一個新帳戶。此路徑上不會發生任何身分行的更新、重命名、重新指向或刪除。
|
|
104
|
+
- **預設情況下關閉。**如果取消設定 `AGENT_NATIVE_IDENTITY_HUB_URL`,則整個功能將處於惰性狀態。
|
|
105
|
+
|
|
106
|
+
```an-callout
|
|
107
|
+
{
|
|
108
|
+
"tone": "success",
|
|
109
|
+
"body": "**啟用安全,恢復安全。**身分寫入**僅可新增**- 現有的同一電子郵件帳戶將不受影響地重複使用,而新電子郵件只需插入新行。沒有架構更改,也沒有任何需要遷移的內容,因此每個應用程式都可以隨時完全可逆地開啟或關閉 `AGENT_NATIVE_IDENTITY_HUB_URL`。"
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
即時連結是完全基於經過驗證的電子郵件的單一決策:
|
|
114
|
+
|
|
115
|
+
```an-diagram title="JIT-link 決定" summary="連結以經過驗證的電子郵件為關鍵,並且僅是附加的 - 現有帳戶不變地重複使用,新電子郵件建立新的本機使用者。"
|
|
116
|
+
{
|
|
117
|
+
"html": "<div class=\"diagram-jit\"><div class=\"diagram-node\" data-rough>已驗證郵箱<br><small class=\"diagram-muted\">來自已簽名身分 JWT</small></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-branch\"><div class=\"diagram-box\" data-rough>Local user exists?<span class=\"diagram-pill ok\">yes → reuse unchanged</span><span class=\"diagram-pill accent\">no → create local user</span></div><div class=\"diagram-arrow diagram-muted\" aria-hidden=\"true\">→</div><div class=\"diagram-box\" data-rough>簽發普通本機工作階段</div></div></div>",
|
|
118
|
+
"css": ".diagram-jit{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-jit .diagram-node{display:flex;flex-direction:column;gap:4px;padding:12px 14px}.diagram-jit .diagram-branch{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.diagram-jit .diagram-box{display:flex;flex-direction:column;gap:6px;padding:12px 14px}.diagram-jit .diagram-arrow{font-size:22px;line-height:1}"
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 自託管 {#self-hosting}
|
|
123
|
+
|
|
124
|
+
任何 Dispatch 部署都可以充當身分中心 - 您不限於 `dispatch.agent-native.com`。在每個用戶端應用程式上設定 `AGENT_NATIVE_IDENTITY_HUB_URL` 以指向您的 Dispatch 執行個體:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.yourcompany.com
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**重新導向允許列表。** 集線器(調度)在發出權杖之前驗證授權端點上的 `redirect_uri`。允許名單在`templates/dispatch/server/lib/identity-sso.ts`中設定:
|
|
131
|
+
|
|
132
|
+
- **預設值:** 僅 `*.agent-native.com` 和 localhost(`DEFAULT_ALLOWED_HOST_SUFFIXES` 常量)。
|
|
133
|
+
- **擴充功能它:**在 Dispatch 部署上設定 `IDENTITY_SSO_ALLOWED_HOST_SUFFIXES` 環境變數,並使用逗號分隔的其他主機後綴列表:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# 除預設值外還允許 yourcompany.com 子域
|
|
137
|
+
IDENTITY_SSO_ALLOWED_HOST_SUFFIXES=".yourcompany.com,.staging.yourcompany.com"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
每個條目都被標準化為點前綴後綴 (`.yourcompany.com`),因此後綴檢查既足夠又最不容易發生 — 無需按應用程式列表保持同步。與所有內容匹配的條目(空或只是 `.`)將被過濾掉。
|
|
141
|
+
|
|
142
|
+
- 無論 `IDENTITY_SSO_ALLOWED_HOST_SUFFIXES` 為何,**Localhost** 始終允許本機開發用戶端應用程式。
|
|
143
|
+
|
|
144
|
+
如果沒有 `IDENTITY_SSO_ALLOWED_HOST_SUFFIXES`,自託管 Dispatch 只能向 `*.agent-native.com` 上的應用程式頒發權杖。在 Dispatch 部署上設定環境變數以解鎖其他域。
|
|
145
|
+
|
|
146
|
+
## 金絲雀推出執行手冊 {#canary-rollout}
|
|
147
|
+
|
|
148
|
+
切換和回滾是**每個應用程式部署的單個環境變數**。一次推出一個應用程式,驗證,然後擴充功能。不要同時在每個應用程式上設定變數。
|
|
149
|
+
|
|
150
|
+
**1。部署程式碼——沒有行為改變。**
|
|
151
|
+
使用 `AGENT_NATIVE_IDENTITY_HUB_URL` **將版本發布到每個應用程式**到處都未設定\*\*。確認正常登入在幾個應用程式上仍然有效。
|
|
152
|
+
|
|
153
|
+
**2。一次在 ONE 應用程式上啟用金絲雀。**
|
|
154
|
+
僅在一次部署上設定:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.agent-native.com
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
保留所有其他應用程式的環境未設定。重新部署/重新啟動,以便它獲取變數。
|
|
161
|
+
|
|
162
|
+
**3。驗證金絲雀(清單)。**
|
|
163
|
+
|
|
164
|
+
- 登出應用程式。
|
|
165
|
+
- 登入螢幕現在顯示**“使用 Agent-Native 登入”**。點選它。
|
|
166
|
+
- 您將進入 **Dispatch** 並完成登入(如果已經登入,則直接通過)。
|
|
167
|
+
- 您將被重新導向**返回應用程式並登入** — 並且它是您之前擁有的**相同的現有帳戶**(同一電子郵件),而不是新帳戶。
|
|
168
|
+
- **應用資料完好無損** — 您的現有紀錄、設定和組織範圍與原來完全相同。
|
|
169
|
+
- **現有的直接登入仍然有效** - 電子郵件/密碼和 Google 登入繼續與 SSO 一起使用。
|
|
170
|
+
|
|
171
|
+
如果任何檢查失敗,請直接進入步驟 4(回滾)——這是即時且資料安全的。
|
|
172
|
+
|
|
173
|
+
**4。逐個應用程式展開。**
|
|
174
|
+
驗證一個應用程式後,對下一個應用程式重複步驟 2-3 - 一次在一個部署上設定 `AGENT_NATIVE_IDENTITY_HUB_URL`。切勿批量啟用。
|
|
175
|
+
|
|
176
|
+
**5。回滾 = 取消設定該應用程式部署上的環境變數。**
|
|
177
|
+
要恢復任何應用程式,**從該應用程式的環境中刪除 `AGENT_NATIVE_IDENTITY_HUB_URL` 並重新部署/重新啟動它。**應用程式立即返回到其之前的驗證行為。 **沒有資料更改可以撤消** - 僅新增了標識行,取消設定變數只會使聯合路徑再次休眠。每個應用的割接和回滾都是獨立且可逆的。
|
|
178
|
+
|
|
179
|
+
> 啟用每個應用程式時,Rollout 會將使用者登出(他們通過 Dispatch 重新進行驗證),但他們始終會重新登入到**相同的電子郵件匹配帳戶,並且資料完好無損**,因為身分行永遠不會被銷毀或重命名 - 只是新增。
|
|
180
|
+
|
|
181
|
+
## 相關 {#related}
|
|
182
|
+
|
|
183
|
+
- [Authentication](/docs/authentication) — 本機驗證模式、工作階段、組織、`A2A_SECRET` 環境變數。
|
|
184
|
+
- [A2A Protocol](/docs/a2a-protocol) — 已簽名的 JWT,它重用的邊界驗證信任模型。
|
|
185
|
+
- [External Agents](/docs/external-agents) — 應用於代理連線和深層連結的相同 `A2A_SECRET` 簽名身分模式。
|
|
186
|
+
- [Dispatch](/docs/dispatch) — 工作區身分授權和路由中心。
|
|
187
|
+
- [Security & Data Scoping](/docs/security) - 僅附加資料寫入和每個帳戶範圍。
|
|
188
|
+
- [Multi-App Workspaces](/docs/multi-app-workspace) — 統一的單來源部署,完全避免跨域 SSO。
|