fuli-context 0.5.0 → 0.7.3

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 (206) hide show
  1. package/README.md +370 -202
  2. package/README.zh-CN.md +448 -0
  3. package/compose.graphiti.yml +6 -6
  4. package/dist/web/assets/AboutPage-DXh7Fwxt.css +1 -0
  5. package/dist/web/assets/AboutPage-qeO_vm0T.js +1 -0
  6. package/dist/web/assets/ConnectionsPage-CBHAdZXT.css +1 -0
  7. package/dist/web/assets/ConnectionsPage-DO0GR9Xg.js +1 -0
  8. package/dist/web/assets/KnowledgeInspector-Bjhdu2mf.css +1 -0
  9. package/dist/web/assets/KnowledgeInspector-DEW5lA1m.js +1 -0
  10. package/dist/web/assets/KnowledgeOrganizerPage-BkM568Ld.js +1 -0
  11. package/dist/web/assets/KnowledgeOrganizerPage-Cx1w1jb2.css +1 -0
  12. package/dist/web/assets/KnowledgePage-BAT4aZIm.js +1 -0
  13. package/dist/web/assets/KnowledgeWorkspace-DyGtBz--.js +4 -0
  14. package/dist/web/assets/OverviewPage-CmCcDCAs.js +1 -0
  15. package/dist/web/assets/PersonalProfilePage-C42mwKN8.js +1 -0
  16. package/dist/web/assets/{PersonalProfilePage-S8ZcG2LU.css → PersonalProfilePage-CdmEzyvZ.css} +1 -1
  17. package/dist/web/assets/PersonalProjectsPage-BwaXR62K.js +1 -0
  18. package/dist/web/assets/PublicProjectsPage-egKBulOq.js +1 -0
  19. package/dist/web/assets/ReviewPage-B3vnZ6gn.js +1 -0
  20. package/dist/web/assets/SearchableSelect-ih69qbcS.js +1 -0
  21. package/dist/web/assets/SettingsPage-C6ouU0sR.css +1 -0
  22. package/dist/web/assets/SettingsPage-oLE8mNs5.js +1 -0
  23. package/dist/web/assets/_plugin-vue_export-helper-BDNMzG2s.js +1 -0
  24. package/dist/web/assets/console-DE40hXGC.js +1 -0
  25. package/dist/web/assets/fuli-logo-Bu9WBuQe.js +1 -0
  26. package/dist/web/assets/fuli-logo-ER1wQ8Kk.png +0 -0
  27. package/dist/web/assets/i18n-CDxBs1sz.js +5 -0
  28. package/dist/web/assets/identity-BCxb1mcy.js +1 -0
  29. package/dist/web/assets/index-BzhNfzU_.js +2 -0
  30. package/dist/web/assets/index-CCOGfZzE.css +1 -0
  31. package/dist/web/assets/model-CCMdt10Q.js +1 -0
  32. package/dist/web/assets/paths-DwHeiGMT.js +1 -0
  33. package/dist/web/assets/useMinimumLoadingDisplay-BpCyBeko.css +1 -0
  34. package/dist/web/assets/useMinimumLoadingDisplay-HdI7XAmu.js +1 -0
  35. package/dist/web/assets/vue-router-Drfl1F8i.js +1 -0
  36. package/dist/web/index.html +9 -6
  37. package/docs/external-knowledge-architecture.md +279 -0
  38. package/examples/external-knowledge/markdown-folder.mjs +235 -0
  39. package/graph-provider/fuli_graph/app.py +57 -1
  40. package/graph-provider/fuli_graph/graph_models.py +3 -0
  41. package/graph-provider/fuli_graph/graph_query.py +62 -16
  42. package/graph-provider/fuli_graph/knowledge_review.py +657 -0
  43. package/graph-provider/fuli_graph/knowledge_review_models.py +133 -0
  44. package/graph-provider/fuli_graph/knowledge_search.py +51 -4
  45. package/graph-provider/fuli_graph/models.py +19 -0
  46. package/graph-provider/fuli_graph/runtime.py +15 -0
  47. package/graph-provider/fuli_graph/store_knowledge.py +2 -1
  48. package/graph-provider/pyproject.toml +1 -1
  49. package/npm-shrinkwrap.json +5 -407
  50. package/package.json +7 -5
  51. package/skills/capturing-session-knowledge/SKILL.md +24 -4
  52. package/skills/flreview/SKILL.md +100 -0
  53. package/skills/flreview/agents/openai.yaml +6 -0
  54. package/src/agent-tools/graph-definitions.js +81 -6
  55. package/src/agent-tools/graph-handlers.js +12 -0
  56. package/src/cli/command-registry.js +3 -3
  57. package/src/cli/local-runtime-command.js +51 -28
  58. package/src/cli/local-runtime-options.js +14 -8
  59. package/src/cli/setup-agent-selection.js +12 -12
  60. package/src/cli/setup-command.js +41 -18
  61. package/src/cli/shell-argument.js +10 -0
  62. package/src/cli/uninstall-command.js +17 -15
  63. package/src/cli/update-command.js +38 -30
  64. package/src/external-knowledge/catalog.js +61 -0
  65. package/src/external-knowledge/conflict-policy.js +58 -0
  66. package/src/external-knowledge/connected-search.js +166 -0
  67. package/src/external-knowledge/connectors/custom.js +133 -0
  68. package/src/external-knowledge/connectors/feishu.js +461 -0
  69. package/src/external-knowledge/connectors/mcp.js +438 -0
  70. package/src/external-knowledge/connectors/notion.js +307 -0
  71. package/src/external-knowledge/connectors/retrieval-api.js +222 -0
  72. package/src/external-knowledge/document-mapping.js +151 -0
  73. package/src/external-knowledge/graph-projection.js +17 -0
  74. package/src/external-knowledge/index.js +8 -0
  75. package/src/external-knowledge/registry.js +91 -0
  76. package/src/external-knowledge/runtime.js +68 -0
  77. package/src/external-knowledge/safe-diagnostic.js +14 -0
  78. package/src/external-knowledge/service.js +811 -0
  79. package/src/graphiti/agent-knowledge-workflows.js +7 -2
  80. package/src/graphiti/federated-application.js +68 -42
  81. package/src/graphiti/knowledge-item-role.js +21 -0
  82. package/src/graphiti/knowledge-review.js +43 -0
  83. package/src/graphiti/project-profile-mapping.js +32 -0
  84. package/src/graphiti/provider-client.js +22 -1
  85. package/src/graphiti/source-marker.js +54 -3
  86. package/src/graphiti/task-knowledge-recall.js +250 -0
  87. package/src/http/api-router.js +23 -108
  88. package/src/http/external-knowledge-api-router.js +104 -0
  89. package/src/http/graph-api-router.js +12 -1
  90. package/src/http/request-policy.js +1 -1
  91. package/src/local-runtime/lifecycle.js +26 -15
  92. package/src/mcp/create-mcp-server.js +4 -1
  93. package/src/mcp/instructions.js +7 -7
  94. package/src/mcp/tool-annotations.js +6 -0
  95. package/src/mcp/tool-result.js +1 -0
  96. package/src/server/application-lifecycle.js +2 -11
  97. package/src/server/blocked-ports.js +11 -0
  98. package/src/server.js +36 -17
  99. package/src/setup/agent-installation-status.js +2 -1
  100. package/src/setup/agents.js +2 -1
  101. package/src/setup/claude-code-config.js +2 -1
  102. package/src/setup/codex-bootstrap.js +12 -7
  103. package/src/setup/container-runtime.js +25 -21
  104. package/src/setup/graph-runtime.js +148 -56
  105. package/src/setup/node-runtime.js +3 -3
  106. package/src/setup/options.js +2 -4
  107. package/src/setup/paths.js +18 -3
  108. package/src/setup/review-skill-adapters.js +49 -0
  109. package/src/setup/setup.js +26 -2
  110. package/src/setup/uninstall.js +4 -2
  111. package/src/system/resource-monitor.js +317 -0
  112. package/src/system/runtime-settings.js +131 -0
  113. package/src/system/system-service.js +119 -0
  114. package/README.en.md +0 -336
  115. package/dist/web/assets/ConnectionsPage-CCKWm-6p.js +0 -1
  116. package/dist/web/assets/KnowledgeInspector-BZkB2wJn.js +0 -1
  117. package/dist/web/assets/KnowledgeInspector-CrGYxEob.css +0 -1
  118. package/dist/web/assets/KnowledgeOrganizerPage-CZAF_OlN.css +0 -1
  119. package/dist/web/assets/KnowledgeOrganizerPage-DlvcLwlL.js +0 -1
  120. package/dist/web/assets/KnowledgePage-CNQXd15y.js +0 -1
  121. package/dist/web/assets/KnowledgeWorkspace-CXPE4GCD.js +0 -4
  122. package/dist/web/assets/OverviewPage-ul7g7HXh.js +0 -1
  123. package/dist/web/assets/PersonalProfilePage-CC40Pw2L.js +0 -1
  124. package/dist/web/assets/PersonalProjectsPage-CPIEcShD.js +0 -1
  125. package/dist/web/assets/PublicProjectsPage-C700sR7z.js +0 -1
  126. package/dist/web/assets/ReviewPage-7MDDUDgA.js +0 -1
  127. package/dist/web/assets/console-B_Ena2DS.js +0 -5
  128. package/dist/web/assets/fuli-logo-DGuyqchQ.png +0 -0
  129. package/dist/web/assets/identity-CjBwYSMX.js +0 -1
  130. package/dist/web/assets/index-CpLDx3of.css +0 -1
  131. package/dist/web/assets/index-DAzeFJSc.js +0 -2
  132. package/dist/web/assets/model-C-5RVIJ2.js +0 -1
  133. package/dist/web/assets/paths-BkULqmGI.js +0 -1
  134. package/dist/web/assets/vue-router-DnD3hUm7.js +0 -1
  135. package/src/agent/candidate-read-service.js +0 -53
  136. package/src/agent/context-pack-service.js +0 -83
  137. package/src/agent/public-read-policy.js +0 -39
  138. package/src/agent/public-read-service.js +0 -69
  139. package/src/agent/read-projection.js +0 -107
  140. package/src/agent/search-service.js +0 -61
  141. package/src/agent/space-boundary.js +0 -33
  142. package/src/app/bootstrap.js +0 -8
  143. package/src/app/create-application.js +0 -143
  144. package/src/app/state-service.js +0 -38
  145. package/src/candidates.js +0 -78
  146. package/src/classifier.js +0 -63
  147. package/src/cli/command-arguments.js +0 -14
  148. package/src/context-pack.js +0 -206
  149. package/src/extractor.js +0 -77
  150. package/src/fact-history.js +0 -39
  151. package/src/facts/fact-service.js +0 -89
  152. package/src/http/bounded-json-array.js +0 -19
  153. package/src/http/lens-route.js +0 -50
  154. package/src/ingestion.js +0 -161
  155. package/src/lens/lens-correction-service.js +0 -81
  156. package/src/lens/lens-fact-writer.js +0 -85
  157. package/src/lens/lens-input.js +0 -62
  158. package/src/lens/lens-query-projection.js +0 -87
  159. package/src/lens/lens-query-ranking.js +0 -62
  160. package/src/lens/lens-query.js +0 -143
  161. package/src/lens/lens-resource-projection.js +0 -93
  162. package/src/lens/lens-resource-selection.js +0 -45
  163. package/src/lens/lens-resource-service.js +0 -103
  164. package/src/lens/lens-search-query.js +0 -122
  165. package/src/lens/lens-service.js +0 -183
  166. package/src/models.js +0 -44
  167. package/src/observer.js +0 -83
  168. package/src/project-rules.js +0 -33
  169. package/src/publication/outbox-service.js +0 -46
  170. package/src/publication/publication-envelope-schema.js +0 -75
  171. package/src/publication/publication-envelope.js +0 -37
  172. package/src/publication/publication-policy.js +0 -82
  173. package/src/publication/publication-service.js +0 -48
  174. package/src/router.js +0 -58
  175. package/src/runtime-options.js +0 -138
  176. package/src/security/episode-visibility.js +0 -14
  177. package/src/security/fact-visibility.js +0 -15
  178. package/src/security/source-metadata-policy.js +0 -8
  179. package/src/storage/episode-evidence-preview.js +0 -100
  180. package/src/storage/fact-search-order.js +0 -18
  181. package/src/storage/file/episode-evidence.js +0 -37
  182. package/src/storage/file/episode-index.js +0 -59
  183. package/src/storage/file/fact-search.js +0 -60
  184. package/src/storage/file-store.js +0 -437
  185. package/src/storage/migrate.js +0 -128
  186. package/src/storage/migrations/001-initial.sql +0 -83
  187. package/src/storage/migrations/002-storage-integrity.sql +0 -113
  188. package/src/storage/record-validation.js +0 -46
  189. package/src/storage/snapshot-defaults.js +0 -54
  190. package/src/storage/sqlite/candidates-repository.js +0 -84
  191. package/src/storage/sqlite/episode-evidence-repository.js +0 -154
  192. package/src/storage/sqlite/episode-privacy-sql.js +0 -33
  193. package/src/storage/sqlite/episodes-repository.js +0 -52
  194. package/src/storage/sqlite/fact-search-repository.js +0 -162
  195. package/src/storage/sqlite/facts-repository.js +0 -146
  196. package/src/storage/sqlite/imports-repository.js +0 -39
  197. package/src/storage/sqlite/mapper.js +0 -84
  198. package/src/storage/sqlite/open-database.js +0 -15
  199. package/src/storage/sqlite/outbox-repository.js +0 -103
  200. package/src/storage/sqlite/snapshot-repository.js +0 -69
  201. package/src/storage/sqlite/spaces-repository.js +0 -52
  202. package/src/storage/sqlite/subscriptions-repository.js +0 -54
  203. package/src/storage/sqlite-store.js +0 -159
  204. package/src/storage/stable-json.js +0 -24
  205. package/src/storage/store-port.js +0 -20
  206. package/src/store.js +0 -2
@@ -0,0 +1,448 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/JevonsCode/fuli/main/web/assets/brand/fuli-logo.png" alt="Fuli Logo" width="72" />
3
+ </p>
4
+
5
+ <h1 align="center">复利(Fuli)</h1>
6
+
7
+ <p align="center">
8
+ <a href="README.md">English</a> · 简体中文
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/fuli-context"><img src="https://img.shields.io/npm/v/fuli-context?style=flat&logo=npm&label=fuli-context" alt="npm 版本" /></a>
13
+ <a href="https://www.npmjs.com/package/fuli-context"><img src="https://img.shields.io/npm/dm/fuli-context?style=flat" alt="npm 月下载量" /></a>
14
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/fuli-context?style=flat" alt="许可证" /></a>
15
+ </p>
16
+
17
+ 复利是一个面向 AI Agent 的本地优先协作上下文图谱。它把人与 AI 在项目中产生的、经得起
18
+ 复用的知识、经验、决策理由和偏好组织成有来源、有作用域、有时间关系的资产,让 Codex、
19
+ Claude Code 和 Cursor 在后续任务中少重复学习一次。
20
+
21
+ 复利不是聊天记录仓库,也不试图建立一个替代人的“人格模型”。AI 负责检索、提醒、归纳和
22
+ 执行;人始终保留最终判断权。
23
+
24
+ ## npm 包
25
+
26
+ | 包 | 状态 | 用途 |
27
+ | --- | --- | --- |
28
+ | [`fuli-context`](https://www.npmjs.com/package/fuli-context) | 已发布 | 个人版;个人知识、图数据库和管理界面都在本机运行 |
29
+ | Fuli Server npm 包 | 开发中 | 面向团队共享场景的独立服务端;目前尚未发布 |
30
+
31
+ 目前唯一可用的 npm 包是个人版 `fuli-context`。团队共享层不会包含个人品味、个性或判断偏好。
32
+
33
+ ## 项目理念
34
+
35
+ ### 1. 衡量复用价值,而不是知识数量
36
+
37
+ 复利的核心问题是:
38
+
39
+ > 如果没有 Fuli,Agent 是否需要重新学习一条已经确认、仍然有效且与当前任务相关的信息?
40
+
41
+ 节点数、对话数和图谱规模不是成功指标。真正需要验证的是:历史资产能否在正确的项目、时间
42
+ 和权威边界内被再次使用,并减少重复解释、修正和返工。
43
+
44
+ ### 2. 每个任务都检查价值,但不强迫每个任务沉淀
45
+
46
+ 一次任务可能产生:
47
+
48
+ - 可复用知识:API 约定、Runbook、发布方式或项目约束;
49
+ - 经验:为什么某个做法有效或失败;
50
+ - 决策轨迹:候选方案、人的选择、理由和后续验证;
51
+ - 判断辅助:偏好、原则、品味或个性倾向。
52
+
53
+ 也可能只有临时输出、猜测或一次性选择。此时正确结果是 `retain_nothing`。复利要求每个任务
54
+ 结束前做一次知识价值检查,并不是把每次聊天都变成长久记忆。
55
+
56
+ ### 3. 人的权威高于 Agent 的重复判断
57
+
58
+ AI 可以发现候选、指出冲突、建议公共化,也可以在得到授权后处理延迟冲突;它不能仅凭语义
59
+ 相似、重复出现或自己的判断伪造人工确认。公共知识提升和有风险的项目写入必须先预览,再由
60
+ 明确的人类选择触发一次性、原子执行。
61
+
62
+ ### 4. 先组装上下文,再按需取证
63
+
64
+ Fuli 不会在会话开始时把全部历史塞给模型。入口阶段始终加载当前任务实际生效的个人全局偏好
65
+ 和精确项目偏好;当任务信号表明可能需要稳定的历史事实、方法、网址、决策、发布、部署或认证
66
+ Runbook 时,同一步骤还会在精确项目及其获授权知识来源中执行一次小规模、有界的自动召回。
67
+ 需要更多证据时,Agent 再使用聚焦查询按需检索。只有真正影响回答、实现或决策的知识才记录为
68
+ 一次使用,单纯检索不会增加权重。
69
+
70
+ ### 5. 保留知识演化,而不是覆盖历史
71
+
72
+ 旧方案可能在当时正确,后来因条件变化被替代。Fuli 保存来源、确认权威、时间、理由、修订、
73
+ 替代和负面证据,让 Agent 能解释“现在应该用什么”以及“为什么过去曾经不同”。负面反馈会
74
+ 降低相关内容的排序或触发复核,但不会静默抹掉历史。
75
+
76
+ ### 6. 公共知识归属上级,项目差异留在子项目
77
+
78
+ 例如,酒店和机票项目可以只保存自己的 PRD、配置和领域规则,把共同的本地运行、Mock、测试
79
+ 和发布方式收敛到活动平台项目:
80
+
81
+ ```text
82
+ 活动平台(父项目:共享 Runbook)
83
+ ├── 酒店项目(子项目:酒店 PRD / 配置 / 覆盖项)
84
+ └── 机票项目(子项目:机票 PRD / 配置 / 覆盖项)
85
+ ```
86
+
87
+ Agent 在酒店项目工作时先搜索酒店本地知识,再沿显式的 `PART_OF` 或
88
+ `USES_KNOWLEDGE_FROM` 关系向上搜索允许继承的知识,最多两跳。同稳定键的子项目内容覆盖
89
+ 父项目内容;普通 `RELATED_TO` 关系不会扩大作用域,项目级个人偏好也不会向下继承。
90
+
91
+ 多个子项目中相似的内容只会形成公共化候选。当前聚类是词法启发式信号,不是语义等价证明;
92
+ 必须由人选择规范项、重复项、上级项目和理由后,才能原子提升。
93
+
94
+ ### 7. 本地优先,公开层不包含个人模型
95
+
96
+ 个人图谱默认留在本机。Fuli 保存结构化、可复用的知识,不保存整段会话、凭据、临时日志或
97
+ 原始命令输出。团队共享层只承载经过确认、具有上下文和来源的项目或领域知识,不包含个人的
98
+ 品味、个性和判断偏好。
99
+
100
+ ## Agent 交互时序
101
+
102
+ 下面是日常任务的简化时序。更完整的项目继承、使用计数、写入预览和来源标记流程见
103
+ [智能体调用时序图](acceptance/智能体调用时序图.md)。
104
+
105
+ ```mermaid
106
+ sequenceDiagram
107
+ autonumber
108
+ actor U as 用户
109
+ participant A as Agent
110
+ participant L as 生命周期接入
111
+ participant F as Fuli MCP
112
+ participant G as 本地图谱
113
+
114
+ U->>A: 在当前项目提交任务
115
+ alt Claude Code(Hook 强制)
116
+ L->>F: begin_task_context(projectPath, taskPrompt)
117
+ F-->>A: 生效偏好、精确项目、有界召回和任务令牌
118
+ else Codex / Cursor(Prompt fallback)
119
+ A->>F: get_collaboration_preferences(projectPath, taskPrompt)
120
+ F-->>A: 生效偏好、精确项目和有界召回
121
+ end
122
+
123
+ A->>A: 检查 task_knowledge_recall
124
+ opt 仍需历史上下文且自动召回未回答
125
+ A->>F: 使用聚焦查询调用 search_current_project_knowledge
126
+ F->>G: 先查子项目,再查获授权的上级
127
+ G-->>A: 有界正文、状态、来源和历史
128
+ opt 知识实际影响结果
129
+ A->>F: record_knowledge_usage
130
+ end
131
+ end
132
+
133
+ A->>A: 完成实现、验证或回答
134
+ opt 产生决策、反证或失效证据
135
+ A->>F: 记录理由或知识反馈
136
+ end
137
+ A->>F: checkpoint_task_knowledge
138
+ alt 有少量可复用候选
139
+ F->>G: capture_candidates
140
+ else 没有值得长期保留的内容
141
+ F-->>A: retain_nothing
142
+ end
143
+
144
+ alt Claude Code Stop Hook
145
+ L->>F: verify_task_checkpoint
146
+ F-->>L: 已检查才允许结束
147
+ else Prompt fallback Agent
148
+ Note over A,F: 遵循同一契约,但宿主不能确定性阻止漏检
149
+ end
150
+ A-->>U: 返回结果与实际使用的 Fuli 来源
151
+ ```
152
+
153
+ ## 外部知识库只读接入
154
+
155
+ 一个第三方知识库连接可以同时绑定到一个或多个已经存在的个人项目,不需要授予 Fuli 对源系统
156
+ 的写权限。每个目标项目独立保存检索模式、同步游标和错误状态;连接页支持多选绑定、连通性
157
+ 检查、手动同步、解绑,以及按项目设置冲突处理开关。
158
+
159
+ | 连接器 | 读取路径 | 当前边界 |
160
+ | --- | --- | --- |
161
+ | MCP | Resources `list/read`;可配置 `search` / `fetch` 工具 | 默认方式;HTTPS、回环 HTTP 或 stdio |
162
+ | Notion | 页面 Markdown 与 Data Source 查询 | 当前 `2026-03-11` API;必须明确页面或数据源 ID |
163
+ | 飞书 / Lark | Wiki 节点、搜索与 Docx 纯文本 | 当前只提取 Docx;搜索可能需要 user access token |
164
+ | RAG Retrieval API | Dify 外部知识库兼容检索协议 | 仅实时;适合 Dify 兼容端点或适配后的 RAGFlow 等系统 |
165
+ | 可信自定义代码 | 本地 ESM `sync` / `retrieve` 契约 | 用户显式安装的可信代码,不是沙箱 |
166
+
167
+ <a id="connect-external-knowledge"></a>
168
+
169
+ ### 给项目连接一个或多个知识库
170
+
171
+ 同一个个人项目可以拥有多个独立知识库绑定,同一个知识库连接也可以绑定多个个人项目。每次
172
+ 提交表单都会新增一个连接,不会覆盖已有连接;连接来源只保存一次,项目目标分别保存检索模式、
173
+ 同步状态和错误。已有连接可用“绑定项目”继续增删目标。
174
+
175
+ 1. 先在“个人项目”中创建或确认目标项目。
176
+ 2. 如果来源需要令牌,在启动 Fuli 的环境中设置令牌,再启动或重启服务。连接配置只填写
177
+ 环境变量名,例如先执行 `export PROJECT_KB_TOKEN='...'`,再执行 `fl restart`。
178
+ 3. 打开 `http://127.0.0.1:2727/connections`,在“外部知识库”中填写连接名称、连接器、
179
+ 绑定项目(可多选)和检索模式。
180
+ 4. MCP HTTP 填写服务 URL 和可选的令牌环境变量名;MCP stdio 填写命令与参数;Notion
181
+ 填写令牌环境变量名以及 Page IDs 或 Data Source IDs;飞书 / Lark 填写令牌环境变量名、
182
+ 区域和明确的 Space ID、根节点 Token 或 Node Tokens;RAG Retrieval API 填写 Dify 兼容
183
+ 端点、知识库 ID 和可选令牌环境变量名;自定义连接器填写受信任本地 ESM 模块与来源 JSON。
184
+ 5. 点击“添加连接”,再点击“检查”。`mirror` 或 `hybrid` 绑定检查成功后可点击“同步”;
185
+ `live` 绑定直接在 Agent 查询时读取来源。
186
+ 6. 连接建立后可点击“绑定项目”,多选增删项目并为每个项目设置检索模式。
187
+
188
+ 绑定后,项目图谱会显示一个“外部知识源”节点以及“使用外部知识”关系。这个节点是连接配置的
189
+ 只读投影;实时正文仍只在 Agent 调用 `search_connected_knowledge` 时按当前项目检索,不会因
190
+ 显示在图谱里而被复制到本地。
191
+
192
+ 三种检索模式的差异:
193
+
194
+ - `live`(仅实时):查询时直接读取第三方,不在 Fuli 中保存正文镜像;依赖来源在线。
195
+ - `mirror`(仅同步):手动把只读正文镜像到绑定的个人项目,Agent 查询本地图谱。
196
+ - `hybrid`(同步 + 实时):同时使用本地镜像和来源实时结果;连接器同时具备两种能力时推荐。
197
+
198
+ 绑定支持 `live`、`mirror` 和 `hybrid`。镜像正文只写入绑定的个人项目,并统一标记为
199
+ `observed`、`pending`、`restricted`、`local_only`。配置只保存环境变量名称,不保存明文凭据;
200
+ 连接器契约中不存在第三方源写入。疑似包含凭据的单个文档会被跳过并返回数量,不进入图谱或
201
+ Agent 上下文。
202
+
203
+ <a id="external-knowledge-conflict-policy"></a>
204
+
205
+ ### 冲突策略
206
+
207
+ 冲突策略按个人项目设置,对该项目的个人图谱、全部外部绑定和明确选择的公共项目统一生效:
208
+
209
+ - “在 Agent 对话中询问”是默认值。Agent 并列展示相互冲突的正文、来源和作用域,由用户选择。
210
+ - “允许 AI 本次判断”允许 Agent 为当前回答选择更可信或更新的来源,但必须说明判断依据;它
211
+ 不会确认、失效、覆盖或写回任何知识。
212
+
213
+ 在项目目录中可以直接要求 Agent:`结合当前项目和已连接知识库查找支付回调规范;如果来源冲突,分别列出并让我决定。`
214
+
215
+ `search_connected_knowledge` 分开返回个人图谱、每个外部绑定和调用方明确选择的公共项目,
216
+ 不会先压成无来源正文。公共项目聚合目前是 **Beta**。Agent 发现实质冲突时,默认在对话中
217
+ 展示并询问用户;可选的“Agent 判断”只对本次回答生效,不能确认、失效或改写任何来源。
218
+ 外部知识直接绑定到公共空间或经审核提升到公共空间、后台定时同步、Webhook 和完整删除对账仍是 **TODO**。
219
+
220
+ 完整边界见[外部知识库只读接入架构](docs/external-knowledge-architecture.md)。
221
+
222
+ ## 当前能力与证据边界
223
+
224
+ 已经由实现和自动化测试覆盖的核心机制包括:
225
+
226
+ - 本地个人空间、精确项目作用域和选择性上级继承;
227
+ - 偏好确认、延迟冲突处理、修订历史和来源标记;
228
+ - 有界的任务提示自动召回、聚焦的按需检索和实际使用审计;
229
+ - 任务入口、任务末尾知识检查,以及 Claude Code 的入口 / Stop Hook;
230
+ - 决策选项、决策理由和首次记录时附带的验证结果;
231
+ - 知识使用事件、负面反馈和内容代际隔离;
232
+ - 支持暂停、恢复和水位线的持久化分范围知识复核;
233
+ - 公共知识候选发现,以及预览令牌保护的原子提升;
234
+ - MCP、Notion、飞书 / Lark、Dify 兼容 RAG Retrieval API 和可信自定义代码的只读多项目绑定与聚合检索。
235
+
236
+ 仍需与“已经证明”区分的内容:
237
+
238
+ - `FULI_ALIGNMENT_BENCHMARK.md` 中 A/B 阈值是验收约定;只有完成足量、同条件的真实配对任务
239
+ 后,才能声称 Fuli 已降低重复解释或返工;
240
+ - Benchmark 的测试项目和对话是明确标注的 **MOCK / 合成数据**,不是用户或生产数据;
241
+ - 当前决策工具可在首次记录时附带验证,但还没有面向既有 `Decision` 单独追加不可变验证结果
242
+ 的专用入口;
243
+ - Claude Code 具备确定性的生命周期 Hook;Codex 和 Cursor 当前是 Prompt fallback,不能把两者
244
+ 表述为同等强制能力;
245
+ - 聚合检索中的选定公共项目仍是 Beta;外部知识提升到公共空间和后台增量同步尚未实现。
246
+
247
+ ## 安装
248
+
249
+ 准备:
250
+
251
+ - Node.js 24.12 或更高版本;
252
+ - Docker Compose v2;Docker Desktop 或 Rancher Desktop 均可;
253
+ - 至少约 4 GB 可供容器使用的内存。
254
+
255
+ 全局安装并初始化:
256
+
257
+ ```bash
258
+ npm install --global fuli-context
259
+ fuli setup
260
+ ```
261
+
262
+ `fuli setup` 会先展示操作计划并请求确认,然后检查容器运行时、初始化本机
263
+ Graphiti / Neo4j、创建个人空间、安装配套 Agent Skills,并为检测到的 Agent 注册 `fuli`
264
+ MCP。默认只连接个人 Provider,不会模拟团队共享服务。
265
+
266
+ 初始化完成后:
267
+
268
+ ```bash
269
+ fuli open
270
+ ```
271
+
272
+ 管理界面默认位于 `http://127.0.0.1:2727`。
273
+
274
+ “设置”页集中管理 Fuli 使用的 7 个本机端口、局域网访问、自动沉淀、Agent 使用、界面语言和
275
+ 资源刷新频率。端口或局域网设置保存后执行 `fuli restart` 生效;资源刷新频率立即生效。
276
+ 同页按设定间隔采集管理服务、Provider、Neo4j、应用文件和本机数据的真实内存/磁盘占用;
277
+ 内存每次重采,磁盘最多每分钟重采一次,并分别显示采样时间。
278
+ 无法取得容器数据时会明确显示为不完整,不使用模拟值。浏览器标签页内存和共享容器虚拟机
279
+ 开销不计入 Fuli 合计。
280
+
281
+ ## CLI
282
+
283
+ 全局安装提供两个等价命令:`fuli` 和短别名 `fl`。
284
+ CLI 的帮助、交互提示、状态和错误信息固定使用英文,不跟随网页或系统语言;路径、空间名等
285
+ 用户数据会按原值显示。
286
+
287
+ | 命令 | 用途 |
288
+ | --- | --- |
289
+ | `fuli --help` / `fuli -h` | 显示所有公开命令及其可用参数 |
290
+ | `fuli --version` / `fuli -v` | 显示当前安装的 Fuli CLI 版本 |
291
+ | `fuli setup [选项]` | 初始化 Provider、管理界面、Agent 接入和 Skills;可重复执行 |
292
+ | `fuli start [选项]` | 启动 Provider 和管理界面;可选择启动后打开浏览器、重建容器或启用 LAN 访问 |
293
+ | `fuli stop [--data-dir DIR]` | 停止服务并保留数据 |
294
+ | `fuli restart [选项]` | 使用与 `start` 相同的运行参数重启本机服务 |
295
+ | `fuli status [--json] [--data-dir DIR] [--port PORT]` | 查看管理界面、个人图谱和公共服务状态;`--json` 输出机器可读结果 |
296
+ | `fuli open [--data-dir DIR]` | 在默认浏览器中打开当前管理界面 |
297
+ | `fuli update [setup 选项]` | 更新 npm 包并刷新本机接入 |
298
+ | `fuli uninstall [--yes] [--data-dir DIR]` | 清理 Agent 接入和服务,保留知识数据和 Neo4j 数据卷 |
299
+
300
+ 常用示例:
301
+
302
+ ```bash
303
+ fuli --version
304
+ fuli status
305
+ fuli restart --rebuild
306
+ fuli start --lan
307
+ fuli stop
308
+ ```
309
+
310
+ `start` 和 `restart` 支持 `--data-dir DIR`、`--personal-space NAME`、`--port PORT`、
311
+ `--open`、`--rebuild`、`--lan` 和 `--no-lan`。未显式传入端口或局域网参数时会使用“设置”
312
+ 页保存的值。其中 `--lan` 会让管理界面监听
313
+ 私有 IPv4 局域网地址,并在终端输出可访问地址、用户名 `fuli` 和本次启动生成的临时访问
314
+ 口令。默认启动仍只监听 `127.0.0.1`;内部 Provider、Neo4j Browser 和 Bolt 不会随
315
+ `--lan` 开放。局域网模式使用 HTTP Basic Auth,只适合可信家庭或办公 Wi-Fi,不等同于
316
+ HTTPS 公网部署。
317
+
318
+ `setup` 和 `update` 支持:
319
+
320
+ | 选项 | 用途 |
321
+ | --- | --- |
322
+ | `--yes` | 跳过确认,适合无人值守执行 |
323
+ | `--codex-only` | 只接入 Codex |
324
+ | `--data-dir DIR` | 使用指定的数据与配置目录 |
325
+ | `--personal-space NAME` | 设置个人空间名称;默认是 `Personal` |
326
+ | `--port PORT` | 设置管理界面端口;默认是 `2727` |
327
+ | `--skip-agents` | 不修改 Agent 配置或 Skills |
328
+ | `--no-start` | 初始化 Provider,但不启动管理界面 |
329
+ | `--personal-only` | 只使用个人 Provider;默认模式 |
330
+ | `--with-dev-public` | 同时启动开发用公共 Provider,仅用于开发或联调 |
331
+
332
+ 更新:
333
+
334
+ ```bash
335
+ fuli update
336
+ ```
337
+
338
+ 更新会先确认不会降级,再停止旧服务、安装 `fuli-context@latest` 并刷新 Agent 接入。
339
+ 既有知识、配置备份和 Neo4j 数据卷会保留。使用过自定义 setup 选项时,更新时应继续传入
340
+ 相同选项。
341
+
342
+ 卸载:
343
+
344
+ ```bash
345
+ fuli uninstall
346
+ npm uninstall --global fuli-context
347
+ ```
348
+
349
+ 自动卸载不会永久删除个人图谱,避免误删。重新安装后可以继续使用原数据。
350
+
351
+ ## Agent 接入与主要工具
352
+
353
+ Fuli 为支持的 Agent 安装 `capturing-session-knowledge`、`grilling-project` 和 `flreview`
354
+ Skills。输入 `/flreview` 后可选择全部、个人偏好或个人项目;若用户表示完全没耐心,流程会
355
+ 跳过心情、时间和 token 询问,只处理少量最高优先级问题。Claude
356
+ Code 使用 `UserPromptSubmit` 和 `Stop` Hook 接入任务生命周期;Codex 的用户级
357
+ `AGENTS.md` 与 Cursor 指令使用 Prompt fallback。偏好正文始终以本机 Fuli 为唯一来源,
358
+ 不会复制到 Agent 配置中。
359
+
360
+ | 工具 | 用途 |
361
+ | --- | --- |
362
+ | `begin_task_context` | Hook 入口:解析任务、在命中信号时执行有界召回并创建任务令牌 |
363
+ | `get_collaboration_preferences` | Fallback 入口:读取生效偏好和有界任务召回 |
364
+ | `search_current_project_knowledge` | 子项目优先、按授权关系向上检索 |
365
+ | `search_knowledge_graph` | 在明确的有界范围内执行更通用的查询 |
366
+ | `search_connected_knowledge` | 分开检索图谱、项目绑定的只读来源和选定公共项目,保留来源边界 |
367
+ | `record_knowledge_usage` | 记录真正影响结果的引用或应用 |
368
+ | `record_knowledge_feedback` | 保存拒绝、验证失败、冲突或过时证据 |
369
+ | `record_decision_trace` | 保存选择、被拒方案、理由和可选初始验证 |
370
+ | `capture_session_knowledge` | 批量写入少量、结构化的候选知识 |
371
+ | `checkpoint_task_knowledge` | 以 `capture_candidates` 或 `retain_nothing` 结束知识检查 |
372
+ | `discover_common_knowledge_candidates` | 只读发现可能属于上级项目的公共候选 |
373
+ | `preview_common_knowledge_promotion` | 预览人类确认的公共知识提升 |
374
+ | `apply_common_knowledge_promotion` | 使用一次性令牌原子执行提升 |
375
+ | `resolve_deferred_preference_conflict` | 在实际需要时处理已授权给 AI 的冲突 |
376
+ | `start_knowledge_review` | 启动或恢复精确范围的个人知识回顾 |
377
+ | `list_knowledge_review_candidates` | 按时间、冲突、权重和跨会话重复顺序列出候选 |
378
+ | `record_knowledge_review_progress` | 保存确认、修改、失效、跳过或稍后处理结果 |
379
+ | `finish_knowledge_review` | 暂停回顾,或完成并推进下次回顾水位线 |
380
+
381
+ ## 隐私与安全边界
382
+
383
+ - 个人知识写入本机 Provider;
384
+ - Agent 归纳结构化知识,不保存原始会话;
385
+ - Token、Cookie、私钥、凭据、私人联系信息、临时日志和原始命令输出不得进入图谱;
386
+ - Graphiti 远程 LLM 路径被禁用,当前嵌入在本机计算;
387
+ - 搜索按个人空间和项目范围限定,不默认混入所有项目;
388
+ - 外部连接器从不写入第三方源,绑定配置拒绝保存明文凭据;
389
+ - 公共提升需要可审计的人工确认,Agent 自己的使用证据最多晋级为
390
+ `agent_confirmed`;
391
+ - Fuli 不是实时监控或 Git 服务,实时状态应从对应系统重新读取。
392
+
393
+ ## 本机服务
394
+
395
+ | 服务 | 默认回环地址 | 启用条件 |
396
+ | --- | --- | --- |
397
+ | Fuli 管理界面 | `127.0.0.1:2727` | 始终启用 |
398
+ | 个人 Provider | `127.0.0.1:8787` | 始终启用 |
399
+ | 个人 Neo4j Browser / Bolt | `127.0.0.1:8060` / `127.0.0.1:7687` | 始终启用 |
400
+ | 开发公共 Provider | `127.0.0.1:8788` | 仅 `--with-dev-public` |
401
+ | 开发公共 Neo4j Browser / Bolt | `127.0.0.1:7475` / `127.0.0.1:7688` | 仅 `--with-dev-public` |
402
+
403
+ 以上共 7 个端口均可在“设置”页修改。即使管理界面以 LAN 模式启动,Provider 和 Neo4j 仍只
404
+ 绑定回环地址。
405
+
406
+ 需要同一 Wi-Fi 下的其他设备访问时,执行 `fuli start --lan`。若当前已经以本机模式运行,
407
+ 命令会安全重启管理界面并保持 Provider 与图谱数据不变。退出局域网模式可在设置页关闭后
408
+ 执行 `fuli restart`,或直接执行 `fuli restart --no-lan`;再次进入局域网模式会更换临时访问
409
+ 口令。
410
+
411
+ 如果端口被占用、Docker Compose 不可用或容器引擎未启动,setup 会在修改 Agent 配置前停止
412
+ 并报告原因。
413
+
414
+ ## 验收与源码开发
415
+
416
+ - [Alignment Benchmark](FULI_ALIGNMENT_BENCHMARK.md)
417
+ - [中文验收索引](acceptance/README.md)
418
+ - [知识检索与确认流程图](acceptance/知识检索与确认流程图.md)
419
+ - [外部知识库只读接入架构](docs/external-knowledge-architecture.md)
420
+
421
+ ```bash
422
+ npm install
423
+ npm test
424
+ npm run test:package
425
+ npm run test:external-knowledge:live
426
+ ```
427
+
428
+ 外部知识联网测试会临时下载两个公开官方文档仓库,验证只读同步和检索后删除整个临时目录。
429
+ 该测试依赖网络,不属于默认测试套件。
430
+
431
+ Provider 验证:
432
+
433
+ ```bash
434
+ python3.12 -m venv .venv
435
+ . .venv/bin/activate
436
+ python -m pip install "./graph-provider[dev]"
437
+ python -m compileall -q graph-provider/fuli_graph
438
+ python -m pytest -q graph-provider/tests
439
+ docker compose -f compose.graphiti.yml config --quiet
440
+ ```
441
+
442
+ `npm run test:package` 会构建前端、生成真实 npm tarball、安装到隔离的全局前缀,并验证
443
+ `fuli` / `fl`、版本号、帮助信息和 Web UI。测试源码、QA 截图和内部设计文档不会进入 npm
444
+ 包。
445
+
446
+ ## License
447
+
448
+ [Apache-2.0](LICENSE)
@@ -9,8 +9,8 @@ services:
9
9
  NEO4J_server_memory_heap_max__size: 512m
10
10
  NEO4J_server_memory_pagecache_size: 256m
11
11
  ports:
12
- - "127.0.0.1:7474:7474"
13
- - "127.0.0.1:7687:7687"
12
+ - "127.0.0.1:${FULI_PERSONAL_NEO4J_HTTP_PORT:-8060}:7474"
13
+ - "127.0.0.1:${FULI_PERSONAL_NEO4J_BOLT_PORT:-7687}:7687"
14
14
  volumes:
15
15
  - personal_neo4j_data:/data
16
16
  healthcheck:
@@ -28,8 +28,8 @@ services:
28
28
  NEO4J_server_memory_heap_max__size: 512m
29
29
  NEO4J_server_memory_pagecache_size: 256m
30
30
  ports:
31
- - "127.0.0.1:7475:7474"
32
- - "127.0.0.1:7688:7687"
31
+ - "127.0.0.1:${FULI_WORKSPACE_NEO4J_HTTP_PORT:-7475}:7474"
32
+ - "127.0.0.1:${FULI_WORKSPACE_NEO4J_BOLT_PORT:-7688}:7687"
33
33
  volumes:
34
34
  - workspace_neo4j_data:/data
35
35
  healthcheck:
@@ -54,7 +54,7 @@ services:
54
54
  EMBEDDING_DIM: 384
55
55
  GRAPHITI_TELEMETRY_ENABLED: "false"
56
56
  ports:
57
- - "127.0.0.1:8787:8787"
57
+ - "127.0.0.1:${FULI_PERSONAL_PROVIDER_PORT:-8787}:8787"
58
58
  depends_on:
59
59
  personal-neo4j:
60
60
  condition: service_healthy
@@ -75,7 +75,7 @@ services:
75
75
  EMBEDDING_DIM: 384
76
76
  GRAPHITI_TELEMETRY_ENABLED: "false"
77
77
  ports:
78
- - "127.0.0.1:8788:8787"
78
+ - "127.0.0.1:${FULI_WORKSPACE_PROVIDER_PORT:-8788}:8787"
79
79
  depends_on:
80
80
  workspace-neo4j:
81
81
  condition: service_healthy
@@ -0,0 +1 @@
1
+ .label-dimension-strip[data-v-b79b7e68]{background:#fff;border:1px solid #d4dad5;border-radius:8px;grid-template-columns:repeat(3,minmax(0,1fr));display:grid;overflow:hidden}.label-dimension-strip article[data-v-b79b7e68]{grid-template-columns:28px minmax(0,1fr);gap:11px;min-width:0;padding:15px 17px;display:grid}.label-dimension-strip article+article[data-v-b79b7e68]{border-left:1px solid #e1e5e1}.label-dimension-strip i[data-v-b79b7e68]{background:#f2f6f3;border:1px solid #cdd7d0;border-radius:7px;width:27px;height:27px;position:relative}.label-dimension-strip i[data-v-b79b7e68]:before,.label-dimension-strip i[data-v-b79b7e68]:after{content:"";position:absolute}.label-dimension-strip [data-dimension=profile] i[data-v-b79b7e68]:before{border:1.5px solid #537461;border-radius:50%;inset:6px}.label-dimension-strip [data-dimension=profile] i[data-v-b79b7e68]:after{background:#8f6b59;border-radius:50%;width:5px;height:5px;top:4px;right:4px}.label-dimension-strip [data-dimension=origin] i[data-v-b79b7e68]:before{border-bottom:1px solid #597266;border-right:1px solid #597266;inset:5px}.label-dimension-strip [data-dimension=origin] i[data-v-b79b7e68]:after{background:#735f79;border-radius:50%;width:6px;height:6px;top:5px;right:5px}.label-dimension-strip [data-dimension=confirmation] i[data-v-b79b7e68]:before{border-bottom:2px solid #537461;border-left:2px solid #537461;width:13px;height:7px;top:6px;left:6px;transform:rotate(-45deg)}.label-dimension-strip strong[data-v-b79b7e68],.label-dimension-strip p[data-v-b79b7e68],.label-dimension-strip small[data-v-b79b7e68]{display:block}.label-dimension-strip strong[data-v-b79b7e68]{color:#33443a;font-size:12px}.label-dimension-strip p[data-v-b79b7e68]{color:#68736c;margin-top:2px;font-size:10px}.label-dimension-strip small[data-v-b79b7e68]{color:#929a94;margin-top:5px;font-size:8px;line-height:1.35}.label-guide-sheet[data-v-b79b7e68]{background:#fff;border:1px solid #d4dad5;border-radius:8px;margin-top:14px;overflow:hidden}.label-guide-section[data-v-b79b7e68]{grid-template-columns:160px minmax(0,1fr);gap:24px;padding:24px;display:grid}.label-guide-section+.label-guide-section[data-v-b79b7e68]{border-top:1px solid #e0e4e0}.label-guide-section>header[data-v-b79b7e68]{grid-template-columns:26px minmax(0,1fr);align-content:start;gap:9px;display:grid}.label-guide-section>header>span[data-v-b79b7e68]{color:#a0a7a2;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px}.label-guide-section h3[data-v-b79b7e68]{color:#2e3c34;font-size:15px}.label-guide-section header p[data-v-b79b7e68]{color:#879089;margin-top:4px;font-size:9px}.label-definition-list[data-v-b79b7e68],.status-definition-list[data-v-b79b7e68]{display:grid}.label-definition-row[data-v-b79b7e68]{grid-template-columns:116px minmax(0,1fr);align-items:start;gap:16px;padding:12px 0;display:grid}.label-definition-row+.label-definition-row[data-v-b79b7e68],.status-definition-row+.status-definition-row[data-v-b79b7e68]{border-top:1px solid #edf0ed}.label-token[data-v-b79b7e68]{white-space:nowrap;border-radius:999px;align-items:center;gap:6px;width:max-content;max-width:100%;padding:5px 9px;font-size:9px;font-weight:680;line-height:1;display:inline-flex}.label-token[data-v-b79b7e68]:before{content:"";opacity:.72;background:currentColor;border-radius:50%;flex:none;width:6px;height:6px}.profile-token[data-kind=taste][data-v-b79b7e68]{color:#7a574b;background:#f5eeeb}.profile-token[data-kind=personality][data-v-b79b7e68]{color:#4f6970;background:#edf3f4}.profile-token[data-kind=judgment][data-v-b79b7e68]{color:#665b7a;background:#f1eef6}.label-definition-row strong[data-v-b79b7e68]{color:#3f4b44;font-size:11px}.label-definition-row p[data-v-b79b7e68]{color:#6f7972;margin-top:4px;font-size:10px;line-height:1.55}.quadrant-explainer[data-v-b79b7e68]{grid-template-rows:auto 28px auto;grid-template-columns:36px minmax(0,1fr);display:grid}.quadrant-y-axis[data-v-b79b7e68]{color:#8a938d;flex-direction:column;grid-row:1;justify-content:space-between;align-items:center;padding:3px 0;font-size:8px;display:flex}.quadrant-y-axis strong[data-v-b79b7e68]{color:#68736c;letter-spacing:.08em;text-orientation:upright;writing-mode:vertical-rl;font-size:8px;font-weight:650}.quadrant-grid[data-v-b79b7e68]{border:1px solid #cfd7d1;border-radius:7px;grid-template-columns:repeat(2,minmax(0,1fr));display:grid;overflow:hidden}.quadrant-grid article[data-v-b79b7e68]{min-height:118px;padding:14px 16px}.quadrant-grid article[data-v-b79b7e68]:nth-child(2n){border-left:1px solid #dce2dd}.quadrant-grid article[data-v-b79b7e68]:nth-child(n+3){border-top:1px solid #dce2dd}.quadrant-grid article[data-quadrant=known-unknown][data-v-b79b7e68]{background:#f6f2e8}.quadrant-grid article[data-quadrant=known-known][data-v-b79b7e68]{background:#edf5f0}.quadrant-grid article[data-quadrant=unknown-unknown][data-v-b79b7e68]{background:#f4eff4}.quadrant-grid article[data-quadrant=unknown-known][data-v-b79b7e68]{background:#edf4f5}.quadrant-grid span[data-v-b79b7e68]{color:#838d86;font-size:8px}.quadrant-grid strong[data-v-b79b7e68]{color:#35443b;margin-top:7px;font-size:13px;display:block}.quadrant-grid p[data-v-b79b7e68]{color:#68736c;max-width:340px;margin-top:6px;font-size:10px;line-height:1.5}.quadrant-x-axis[data-v-b79b7e68]{color:#8a938d;grid-area:2/2;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px;font-size:8px;display:grid}.quadrant-x-axis span[data-v-b79b7e68]:last-child{text-align:right}.quadrant-x-axis strong[data-v-b79b7e68]{color:#68736c;letter-spacing:.08em;font-size:8px}.quadrant-notes[data-v-b79b7e68]{flex-wrap:wrap;grid-area:3/2;gap:6px 20px;padding-top:8px;display:flex}.quadrant-notes p[data-v-b79b7e68],.status-boundaries p[data-v-b79b7e68]{color:#77817a;font-size:9px;line-height:1.45}.status-definition-row[data-v-b79b7e68]{grid-template-columns:120px minmax(0,1fr) minmax(180px,.72fr);align-items:start;gap:16px;padding:12px 0;display:grid}.status-token[data-status=pending][data-v-b79b7e68]{color:#77602f;background:#f7f2e5}.status-token[data-status=agent-confirmed][data-v-b79b7e68]{color:#4d5f78;background:#eef2f7}.status-token[data-status=confirmed][data-v-b79b7e68]{color:#356047;background:#edf6f0}.status-definition-row>p[data-v-b79b7e68]{color:#67726b;font-size:10px;line-height:1.55}.status-definition-row>div[data-v-b79b7e68]{gap:3px;display:grid}.status-definition-row>div span[data-v-b79b7e68]{color:#929a94;font-size:8px}.status-definition-row>div strong[data-v-b79b7e68]{color:#4b5750;font-size:9px;font-weight:620;line-height:1.45}.status-boundaries[data-v-b79b7e68]{border-top:1px solid #edf0ed;flex-wrap:wrap;gap:6px 20px;margin-top:8px;padding-top:10px;display:flex}.label-example[data-v-b79b7e68]{background:#f7f9f7;border-top:1px solid #dce2dd;grid-template-columns:minmax(220px,.8fr) auto minmax(260px,1fr);align-items:center;gap:22px;padding:18px 24px;display:grid}.label-example>div[data-v-b79b7e68]:first-child{gap:4px;display:grid}.label-example>div:first-child span[data-v-b79b7e68]{color:#89928c;letter-spacing:.08em;text-transform:uppercase;font-size:8px}.label-example>div:first-child strong[data-v-b79b7e68]{color:#34433a;font-size:11px}.label-example-tags[data-v-b79b7e68]{flex-wrap:wrap;justify-content:center;gap:6px;display:flex}.origin-token[data-v-b79b7e68]{color:#3f6b55;background:#eaf3ed}.label-example>p[data-v-b79b7e68]{color:#68736c;font-size:9px;line-height:1.5}.label-all-note[data-v-b79b7e68]{color:#7b847e;text-align:center;border-top:1px solid #e3e7e3;padding:12px 24px;font-size:9px}@media (width<=1180px){.label-guide-section[data-v-b79b7e68]{grid-template-columns:1fr;gap:16px}.label-example[data-v-b79b7e68]{grid-template-columns:minmax(210px,.8fr) minmax(0,1.2fr)}.label-example-tags[data-v-b79b7e68]{justify-content:flex-end}.label-example>p[data-v-b79b7e68]{grid-column:1/-1}}.open-source-credits[data-v-8676884b]{background:#fff;border:1px solid #d4dad5;border-radius:9px;overflow:hidden}.credits-roll[data-v-8676884b]{padding:38px 40px 34px}.credits-roll header h3[data-v-8676884b]{color:#2e3c34;font-size:19px}.credits-roll header p[data-v-8676884b]{color:#78817b;margin-top:7px;font-size:11px}.credit-grid[data-v-8676884b]{border-top:1px solid #e1e5e1;border-left:1px solid #e1e5e1;grid-template-columns:repeat(4,minmax(0,1fr));margin-top:28px;display:grid}.credit-grid a[data-v-8676884b]{min-width:0;min-height:118px;color:inherit;border-bottom:1px solid #e1e5e1;border-right:1px solid #e1e5e1;grid-template-columns:46px minmax(0,1fr);align-items:center;gap:14px;padding:20px;text-decoration:none;display:grid}.credit-grid a[data-v-8676884b]:hover{background:#f7f9f7}.credit-grid a[data-v-8676884b]:focus-visible{outline-offset:-2px;outline:2px solid #7e9487}.credit-mark[data-v-8676884b]{place-items:center;width:42px;height:42px;display:grid}.credit-mark img[data-v-8676884b]{object-fit:contain;width:34px;height:34px}.credit-copy[data-v-8676884b]{gap:4px;min-width:0;display:grid}.credit-copy strong[data-v-8676884b]{color:#3a463f;font-size:11px}.credit-copy small[data-v-8676884b]{color:#89918b;font-size:8px}.credit-source-note[data-v-8676884b]{color:#929a94;max-width:760px;margin-top:18px;font-size:9px;line-height:1.55}.fuli-finale[data-v-8676884b]{color:#f2f4f2;text-align:center;background:#222824;place-content:center;justify-items:center;min-height:360px;padding:64px 32px;display:grid}.finale-brand[data-v-8676884b]{align-items:center;gap:24px;display:flex}.finale-brand>img[data-v-8676884b]{object-fit:contain;filter:grayscale()brightness(0)invert();width:124px;height:124px}.finale-brand>div[data-v-8676884b]{text-align:left;gap:3px;display:grid}.finale-brand strong[data-v-8676884b]{letter-spacing:-.04em;font-size:34px}.finale-brand span[data-v-8676884b]{color:#aeb7b0;font-size:13px}.fuli-finale>p[data-v-8676884b]{color:#b8c0ba;max-width:560px;margin-top:34px;font-size:12px;line-height:1.6}@media (width<=1180px){.credits-roll[data-v-8676884b]{padding:32px 28px}.credit-grid[data-v-8676884b]{grid-template-columns:repeat(3,minmax(0,1fr))}.credit-grid a[data-v-8676884b]{padding:16px}}.product-principles[data-v-d823b02d]{background:#fff;border:1px solid #d4dad5;border-radius:9px;overflow:hidden}.principles-lede[data-v-d823b02d]{padding:44px 48px 38px}.principles-lede h3[data-v-d823b02d]{color:#26352d;letter-spacing:-.04em;max-width:720px;font-size:clamp(25px,3vw,38px);font-weight:650;line-height:1.12}.principles-lede p[data-v-d823b02d]{color:#66716a;max-width:820px;font-size:13px;line-height:1.75}.principles-lede h3+p[data-v-d823b02d]{margin-top:24px}.principles-lede p+p[data-v-d823b02d]{margin-top:10px}.principle-sequence[data-v-d823b02d]{border-top:1px solid #dde2de;grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.principle-sequence article[data-v-d823b02d]{grid-template-columns:34px minmax(0,1fr);align-content:start;gap:16px;min-height:174px;padding:28px 32px;display:grid}.principle-sequence article[data-v-d823b02d]:nth-child(2n){border-left:1px solid #e2e6e2}.principle-sequence article[data-v-d823b02d]:nth-child(n+3){border-top:1px solid #e2e6e2}.principle-sequence article>span[data-v-d823b02d]{color:#98a19a;padding-top:3px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:9px}.principle-sequence h4[data-v-d823b02d],.principle-boundaries h4[data-v-d823b02d]{color:#344239;margin:0;font-size:14px;font-weight:680}.principle-sequence p[data-v-d823b02d],.principle-boundaries p[data-v-d823b02d]{color:#6c766f;margin-top:9px;font-size:11px;line-height:1.7}.principle-boundaries[data-v-d823b02d]{background:#f5f7f5;border-top:1px solid #d9dfda;padding:27px 32px 30px}.principle-boundaries>strong[data-v-d823b02d]{color:#77817a;letter-spacing:.1em;font-size:9px}.principle-boundaries>div[data-v-d823b02d]{grid-template-columns:repeat(3,minmax(0,1fr));margin-top:18px;display:grid}.principle-boundaries article[data-v-d823b02d]{min-width:0;padding:0 24px 0 28px;position:relative}.principle-boundaries article[data-v-d823b02d]:first-child{padding-left:0}.principle-boundaries article+article[data-v-d823b02d]{border-left:1px solid #dce2dd}.principle-boundaries i[data-v-d823b02d]{border:1.5px solid #577463;border-radius:50%;width:8px;height:8px;margin-bottom:12px;display:inline-block}.principle-boundaries i[data-boundary=authority][data-v-d823b02d]{border-radius:2px}.principle-boundaries i[data-boundary=scope][data-v-d823b02d]{border-radius:1px;transform:rotate(45deg)}@media (width<=1180px){.principles-lede[data-v-d823b02d]{padding:36px 34px 32px}.principle-sequence article[data-v-d823b02d]{padding:24px}.principle-boundaries article[data-v-d823b02d]{padding-inline:18px}}.about-view[data-v-6bd30c79]{background:#f7f8f6;padding-top:24px}.about-content[data-v-6bd30c79]{gap:18px;width:min(1100px,100%);margin:0 auto;display:grid}.about-labels-section[data-v-6bd30c79]{gap:14px;padding-top:22px;display:grid}.about-labels-section>header h3[data-v-6bd30c79]{color:#2e3c34;font-size:19px}.about-labels-section>header p[data-v-6bd30c79]{color:#78817b;max-width:720px;margin-top:7px;font-size:11px;line-height:1.6}
@@ -0,0 +1 @@
1
+ import{Q as e,_ as t,a as n,b as r,f as i,j as a,k as o,m as s,p as c,tt as l,x as u}from"./i18n-CDxBs1sz.js";import{t as d}from"./fuli-logo-Bu9WBuQe.js";import{t as f}from"./_plugin-vue_export-helper-BDNMzG2s.js";var p=[`aria-label`],m={class:`label-dimension-strip`},h=[`data-dimension`],g={class:`label-guide-sheet`},_={class:`label-guide-section profile-guide`},v={class:`label-definition-list`},y=[`data-kind`],b={class:`label-guide-section quadrant-guide`},x={class:`quadrant-explainer`},S={class:`quadrant-y-axis`,"aria-hidden":`true`},C={class:`quadrant-grid`},w=[`data-quadrant`],T={class:`quadrant-x-axis`,"aria-hidden":`true`},E={class:`quadrant-notes`},D={class:`label-guide-section confirmation-guide`},O={class:`status-definition-list`},k=[`data-status`],A={class:`status-boundaries`},j={class:`label-example`},M={class:`label-example-tags`,"aria-hidden":`true`},N={class:`label-token profile-token`,"data-kind":`taste`},P={class:`label-token origin-token`},ee={class:`label-token status-token`,"data-status":`confirmed`},F={class:`label-all-note`},I=f(u({__name:`LabelGuide`,setup(r){let u=c(()=>[{key:`profile`,title:n(`about.dimensions.profile.title`),question:n(`about.dimensions.profile.question`),timing:n(`about.dimensions.profile.timing`)},{key:`origin`,title:n(`about.dimensions.origin.title`),question:n(`about.dimensions.origin.question`),timing:n(`about.dimensions.origin.timing`)},{key:`confirmation`,title:n(`about.dimensions.confirmation.title`),question:n(`about.dimensions.confirmation.question`),timing:n(`about.dimensions.confirmation.timing`)}]),d=c(()=>[{key:`taste`,label:n(`about.profiles.taste.label`),short:n(`about.profiles.taste.short`),description:n(`about.profiles.taste.description`)},{key:`personality`,label:n(`about.profiles.personality.label`),short:n(`about.profiles.personality.short`),description:n(`about.profiles.personality.description`)},{key:`judgment`,label:n(`about.profiles.judgment.label`),short:n(`about.profiles.judgment.short`),description:n(`about.profiles.judgment.description`)}]),f=c(()=>[{key:`known-unknown`,label:n(`about.quadrants.knownUnknown.label`),coordinate:n(`about.quadrants.knownUnknown.coordinate`),description:n(`about.quadrants.knownUnknown.description`)},{key:`known-known`,label:n(`about.quadrants.knownKnown.label`),coordinate:n(`about.quadrants.knownKnown.coordinate`),description:n(`about.quadrants.knownKnown.description`)},{key:`unknown-unknown`,label:n(`about.quadrants.unknownUnknown.label`),coordinate:n(`about.quadrants.unknownUnknown.coordinate`),description:n(`about.quadrants.unknownUnknown.description`)},{key:`unknown-known`,label:n(`about.quadrants.unknownKnown.label`),coordinate:n(`about.quadrants.unknownKnown.coordinate`),description:n(`about.quadrants.unknownKnown.description`)}]),I=c(()=>[{key:`pending`,label:n(`about.statuses.pending.label`),description:n(`about.statuses.pending.description`),rule:n(`about.statuses.pending.rule`)},{key:`agent-confirmed`,label:n(`about.statuses.agentConfirmed.label`),description:n(`about.statuses.agentConfirmed.description`),rule:n(`about.statuses.agentConfirmed.rule`)},{key:`confirmed`,label:n(`about.statuses.confirmed.label`),description:n(`about.statuses.confirmed.description`),rule:n(`about.statuses.confirmed.rule`)}]);return(r,c)=>(o(),t(`section`,{class:`label-guide`,"aria-label":e(n)(`about.labelsAria`)},[s(`div`,m,[(o(!0),t(i,null,a(u.value,e=>(o(),t(`article`,{key:e.key,"data-dimension":e.key},[c[0]||=s(`i`,{"aria-hidden":`true`},null,-1),s(`div`,null,[s(`strong`,null,l(e.title),1),s(`p`,null,l(e.question),1),s(`small`,null,l(e.timing),1)])],8,h))),128))]),s(`div`,g,[s(`section`,_,[s(`header`,null,[s(`span`,null,l(e(n)(`about.sections.profile.index`)),1),s(`div`,null,[s(`h3`,null,l(e(n)(`about.sections.profile.title`)),1),s(`p`,null,l(e(n)(`about.sections.profile.meta`)),1)])]),s(`div`,v,[(o(!0),t(i,null,a(d.value,e=>(o(),t(`article`,{key:e.key,class:`label-definition-row`},[s(`span`,{class:`label-token profile-token`,"data-kind":e.key},l(e.label),9,y),s(`div`,null,[s(`strong`,null,l(e.short),1),s(`p`,null,l(e.description),1)])]))),128))])]),s(`section`,b,[s(`header`,null,[s(`span`,null,l(e(n)(`about.sections.origin.index`)),1),s(`div`,null,[s(`h3`,null,l(e(n)(`about.sections.origin.title`)),1),s(`p`,null,l(e(n)(`about.sections.origin.meta`)),1)])]),s(`div`,x,[s(`div`,S,[s(`span`,null,l(e(n)(`about.quadrants.aware`)),1),s(`strong`,null,l(e(n)(`about.quadrants.awareness`)),1),s(`span`,null,l(e(n)(`about.quadrants.unaware`)),1)]),s(`div`,C,[(o(!0),t(i,null,a(f.value,e=>(o(),t(`article`,{key:e.key,"data-quadrant":e.key},[s(`span`,null,l(e.coordinate),1),s(`strong`,null,l(e.label),1),s(`p`,null,l(e.description),1)],8,w))),128))]),s(`div`,T,[s(`span`,null,l(e(n)(`about.quadrants.unmastered`)),1),s(`strong`,null,l(e(n)(`about.quadrants.mastery`)),1),s(`span`,null,l(e(n)(`about.quadrants.mastered`)),1)]),s(`div`,E,[s(`p`,null,l(e(n)(`about.quadrants.immutable`)),1),s(`p`,null,l(e(n)(`about.quadrants.unclassified`)),1)])])]),s(`section`,D,[s(`header`,null,[s(`span`,null,l(e(n)(`about.sections.confirmation.index`)),1),s(`div`,null,[s(`h3`,null,l(e(n)(`about.sections.confirmation.title`)),1),s(`p`,null,l(e(n)(`about.sections.confirmation.meta`)),1)])]),s(`div`,null,[s(`div`,O,[(o(!0),t(i,null,a(I.value,r=>(o(),t(`article`,{key:r.key,class:`status-definition-row`},[s(`span`,{class:`label-token status-token`,"data-status":r.key},l(r.label),9,k),s(`p`,null,l(r.description),1),s(`div`,null,[s(`span`,null,l(e(n)(`about.statuses.entryCondition`)),1),s(`strong`,null,l(r.rule),1)])]))),128))]),s(`div`,A,[s(`p`,null,l(e(n)(`about.statuses.usageBoundary`)),1),s(`p`,null,l(e(n)(`about.statuses.resetBoundary`)),1)])])]),s(`section`,j,[s(`div`,null,[s(`span`,null,l(e(n)(`about.example.title`)),1),s(`strong`,null,l(e(n)(`about.example.item`)),1)]),s(`div`,M,[s(`span`,N,l(e(n)(`about.example.profile`)),1),s(`span`,P,l(e(n)(`about.example.origin`)),1),s(`span`,ee,l(e(n)(`about.example.status`)),1)]),s(`p`,null,l(e(n)(`about.example.description`)),1)]),s(`p`,F,l(e(n)(`about.allFilter`)),1)])],8,p))}}),[[`__scopeId`,`data-v-b79b7e68`]]),L={class:`open-source-credits`},R={class:`credits-roll`},z={class:`credit-grid`},B=[`href`],V={class:`credit-mark`},H=[`src`,`alt`],U={class:`credit-copy`},W={class:`credit-source-note`},G={class:`fuli-finale`},K={class:`finale-brand`},q=[`src`],J=f(u({__name:`OpenSourceCredits`,setup(r){let u=c(()=>[{name:`Vue.js`,role:n(`about.credits.roles.vue`),logo:`https://raw.githubusercontent.com/vuejs/docs/main/src/public/logo.svg`,url:`https://vuejs.org/`},{name:`Vite`,role:n(`about.credits.roles.vite`),logo:`https://raw.githubusercontent.com/vitejs/vite/main/docs/public/logo-without-border.svg`,url:`https://vite.dev/`},{name:`Pinia`,role:n(`about.credits.roles.pinia`),logo:`https://raw.githubusercontent.com/vuejs/pinia/v4/packages/docs/public/logo.svg`,url:`https://pinia.vuejs.org/`},{name:`D3.js`,role:n(`about.credits.roles.d3`),logo:`https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg`,url:`https://d3js.org/`},{name:`Vitest`,role:n(`about.credits.roles.vitest`),logo:`https://raw.githubusercontent.com/vitest-dev/vitest/main/docs/public/logo-without-border.svg`,url:`https://vitest.dev/`},{name:`Hono`,role:n(`about.credits.roles.hono`),logo:`https://raw.githubusercontent.com/honojs/website/main/public/images/logo.svg`,url:`https://hono.dev/`},{name:`Neo4j`,role:n(`about.credits.roles.neo4j`),logo:`https://avatars.githubusercontent.com/u/201120?v=4`,url:`https://neo4j.com/`},{name:`Zod`,role:n(`about.credits.roles.zod`),logo:`https://raw.githubusercontent.com/colinhacks/zod/main/packages/docs/public/logo/logo_square.png`,url:`https://zod.dev/`},{name:`FastAPI`,role:n(`about.credits.roles.fastapi`),logo:`https://raw.githubusercontent.com/fastapi/fastapi/master/docs/en/docs/img/favicon.png`,url:`https://fastapi.tiangolo.com/`},{name:`Graphiti`,role:n(`about.credits.roles.graphiti`),logo:`https://avatars.githubusercontent.com/u/132832125?s=128&v=4`,url:`https://github.com/getzep/graphiti`},{name:`Model Context Protocol`,role:n(`about.credits.roles.mcp`),logo:`https://raw.githubusercontent.com/modelcontextprotocol/docs/main/favicon.svg`,url:`https://modelcontextprotocol.io/`}]);return(r,c)=>(o(),t(`section`,L,[s(`div`,R,[s(`header`,null,[s(`h3`,null,l(e(n)(`about.credits.title`)),1),s(`p`,null,l(e(n)(`about.credits.description`)),1)]),s(`div`,z,[(o(!0),t(i,null,a(u.value,e=>(o(),t(`a`,{key:e.name,href:e.url,target:`_blank`,rel:`noreferrer`},[s(`span`,V,[s(`img`,{src:e.logo,alt:e.name},null,8,H)]),s(`span`,U,[s(`strong`,null,l(e.name),1),s(`small`,null,l(e.role),1)])],8,B))),128))]),s(`p`,W,l(e(n)(`about.credits.sourceNote`)),1)]),s(`footer`,G,[s(`div`,K,[s(`img`,{src:e(d),alt:``,"aria-hidden":`true`},null,8,q),s(`div`,null,[s(`strong`,null,l(e(n)(`common.brand`)),1),c[0]||=s(`span`,null,`Context Graph`,-1)])]),s(`p`,null,l(e(n)(`about.credits.finale`)),1)])]))}}),[[`__scopeId`,`data-v-8676884b`]]),Y={class:`product-principles`},X={class:`principles-lede`},Z={class:`principle-sequence`},Q={class:`principle-boundaries`},$=[`data-boundary`],te=f(u({__name:`ProductPrinciples`,setup(r){let u=c(()=>[{key:`capture`,index:n(`about.philosophy.capture.index`),title:n(`about.philosophy.capture.title`),description:n(`about.philosophy.capture.description`)},{key:`project`,index:n(`about.philosophy.project.index`),title:n(`about.philosophy.project.title`),description:n(`about.philosophy.project.description`)},{key:`review`,index:n(`about.philosophy.review.index`),title:n(`about.philosophy.review.title`),description:n(`about.philosophy.review.description`)},{key:`reuse`,index:n(`about.philosophy.reuse.index`),title:n(`about.philosophy.reuse.title`),description:n(`about.philosophy.reuse.description`)}]),d=c(()=>[{key:`local`,title:n(`about.philosophy.local.title`),description:n(`about.philosophy.local.description`)},{key:`authority`,title:n(`about.philosophy.authority.title`),description:n(`about.philosophy.authority.description`)},{key:`scope`,title:n(`about.philosophy.scope.title`),description:n(`about.philosophy.scope.description`)}]);return(r,c)=>(o(),t(`section`,Y,[s(`header`,X,[s(`h3`,null,l(e(n)(`about.philosophy.title`)),1),s(`p`,null,l(e(n)(`about.philosophy.intro`)),1),s(`p`,null,l(e(n)(`about.philosophy.support`)),1)]),s(`div`,Z,[(o(!0),t(i,null,a(u.value,e=>(o(),t(`article`,{key:e.key},[s(`span`,null,l(e.index),1),s(`div`,null,[s(`h4`,null,l(e.title),1),s(`p`,null,l(e.description),1)])]))),128))]),s(`div`,Q,[s(`strong`,null,l(e(n)(`about.philosophy.boundariesTitle`)),1),s(`div`,null,[(o(!0),t(i,null,a(d.value,e=>(o(),t(`article`,{key:e.key},[s(`i`,{"data-boundary":e.key,"aria-hidden":`true`},null,8,$),s(`h4`,null,l(e.title),1),s(`p`,null,l(e.description),1)]))),128))])])]))}}),[[`__scopeId`,`data-v-d823b02d`]]),ne=[`aria-label`],re={class:`about-content`},ie={class:`about-labels-section`},ae=f(u({__name:`AboutPage`,setup(i){return(i,a)=>(o(),t(`section`,{class:`view about-view`,"aria-label":e(n)(`about.aria`)},[s(`div`,re,[r(te),s(`section`,ie,[s(`header`,null,[s(`h3`,null,l(e(n)(`about.labelsIntro.title`)),1),s(`p`,null,l(e(n)(`about.labelsIntro.description`)),1)]),r(I)]),r(J)])],8,ne))}}),[[`__scopeId`,`data-v-6bd30c79`]]);export{ae as default};
@@ -0,0 +1 @@
1
+ .text-field[data-v-6c32205a]{color:#68726b;gap:5px;min-width:0;font-size:9px;display:grid}.text-field input[data-v-6c32205a],.text-field textarea[data-v-6c32205a]{color:#354139;background:#fff;border:1px solid #cfd7d1;border-radius:6px;outline:none;width:100%;min-width:0;padding:7px 8px;font-size:11px}.text-field textarea[data-v-6c32205a]{resize:vertical;line-height:1.5}.text-field input[data-v-6c32205a]:focus,.text-field textarea[data-v-6c32205a]:focus{border-color:#6f8577;box-shadow:0 0 0 2px #54715f1a}
@@ -0,0 +1 @@
1
+ import{$ as e,D as t,E as n,F as r,G as i,O as ee,P as a,Q as o,R as s,T as c,_ as l,a as u,b as d,d as f,f as p,g as m,h,j as g,k as _,m as v,n as te,p as y,q as b,tt as x,u as S,x as C,y as w}from"./i18n-CDxBs1sz.js";import{a as T,i as E,n as D,r as O,t as k}from"./console-DE40hXGC.js";import{t as A}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{t as j}from"./SearchableSelect-ih69qbcS.js";import{r as M,t as N}from"./identity-BCxb1mcy.js";var P=[`data-select-id`],F=[`aria-expanded`,`aria-controls`,`aria-label`,`aria-required`,`disabled`],I={class:`searchable-select-current`},L={class:`searchable-select-current-label`},R={key:0,class:`searchable-select-current-meta`},z=[`hidden`],ne={key:0,class:`searchable-select-search`},B=[`placeholder`,`aria-label`],V=[`id`],re=[`aria-selected`,`disabled`,`onClick`],ie={class:`searchable-select-option-copy`},ae={key:0},oe={key:1,class:`searchable-select-empty`},se=C({__name:`SearchableMultiSelect`,props:{modelValue:{},options:{},label:{},controlId:{default:void 0},placeholder:{default:void 0},searchPlaceholder:{default:void 0},searchable:{type:Boolean,default:void 0},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1}},emits:[`update:modelValue`,`change`],setup(i,{emit:c}){let d=i,h=c,C=b(null),w=b(null),T=b(null),E=b(null),D=b(!1),O=b(!1),k=b(``),A=a().replace(/[^A-Za-z0-9_-]/g,``),j=y(()=>`${d.controlId||`searchable-multi-select-${A}`}-options`),M=y(()=>new Set(d.modelValue)),N=y(()=>d.options.filter(({value:e})=>M.value.has(e))),se=y(()=>N.value.length===0?d.placeholder??u(`common.searchableSelect.placeholder`):N.value.length===1?N.value[0].label:u(`common.searchableSelect.selectedCount`,{count:N.value.length})),ce=y(()=>d.searchPlaceholder??u(`common.searchableSelect.searchPlaceholder`)),H=y(()=>d.searchable??d.options.length>5),U=y(()=>{let e=te(),t=k.value.trim().toLocaleLowerCase(e);return t?d.options.filter(n=>[n.label,n.value,n.meta,n.search].filter(Boolean).join(` `).toLocaleLowerCase(e).includes(t)):d.options});r(()=>d.disabled,e=>{e&&G()}),ee(()=>document.addEventListener(`pointerdown`,me)),t(()=>document.removeEventListener(`pointerdown`,me));async function W(){D.value?G():await le()}async function le(){d.disabled||(k.value=``,_e(),D.value=!0,await n(),H.value?T.value?.focus():ge()?.focus())}function G({restoreFocus:e=!1}={}){D.value=!1,O.value=!1,k.value=``,e&&n(()=>w.value?.focus())}function ue(e){if(d.disabled||e.disabled)return;let t=M.value.has(e.value)?d.modelValue.filter(t=>t!==e.value):[...d.modelValue,e.value];h(`update:modelValue`,t),h(`change`,t)}function de(e){[`ArrowDown`,`Enter`,` `].includes(e.key)&&(e.preventDefault(),D.value&&[`Enter`,` `].includes(e.key)?G():le())}function fe(e){if(e.key===`Escape`){e.preventDefault(),G({restoreFocus:!0});return}if(e.key===`ArrowDown`){e.preventDefault(),q()?.focus();return}e.key===`Enter`&&(e.preventDefault(),q()?.click())}function pe(e){if(e.key===`Escape`){e.preventDefault(),G({restoreFocus:!0});return}if(![`ArrowDown`,`ArrowUp`,`Home`,`End`].includes(e.key))return;e.preventDefault();let t=K(),n=t.indexOf(e.currentTarget);t[e.key===`Home`?0:e.key===`End`?t.length-1:e.key===`ArrowDown`?Math.min(t.length-1,n+1):Math.max(0,n-1)]?.focus()}function me(e){D.value&&!C.value?.contains(e.target)&&G()}function he(e){let t=e.relatedTarget;t&&C.value?.contains(t)||queueMicrotask(()=>{D.value&&!C.value?.contains(document.activeElement)&&G()})}function K(){return[...E.value?.querySelectorAll(`.searchable-select-option:not(:disabled)`)??[]]}function q(){return K()[0]??null}function ge(){return K().find(e=>e.getAttribute(`aria-selected`)===`true`)??q()}function _e(){let e=w.value?.getBoundingClientRect();O.value=!!(e&&window.innerHeight-e.bottom<270&&e.top>270)}return(t,n)=>(_(),l(`div`,{ref_key:`root`,ref:C,class:e([`searchable-select searchable-multi-select`,{open:D.value,"open-up":O.value,disabled:i.disabled}]),"data-select-id":i.controlId,onFocusout:he},[v(`button`,{ref_key:`trigger`,ref:w,type:`button`,class:`searchable-select-trigger`,role:`combobox`,"aria-haspopup":`listbox`,"aria-expanded":D.value,"aria-controls":j.value,"aria-label":i.label,"aria-required":i.required,disabled:i.disabled,onPointerdown:n[0]||=f(()=>{},[`stop`]),onClick:f(W,[`stop`]),onKeydown:de},[v(`span`,I,[v(`span`,L,x(se.value),1),N.value.length>1?(_(),l(`small`,R,x(N.value.map(({label:e})=>e).join(` · `)),1)):m(``,!0)]),n[3]||=v(`i`,{class:`searchable-select-arrow`,"aria-hidden":`true`},null,-1)],40,F),v(`div`,{class:`searchable-select-panel`,hidden:!D.value},[H.value?(_(),l(`div`,ne,[s(v(`input`,{ref_key:`searchInput`,ref:T,"onUpdate:modelValue":n[1]||=e=>k.value=e,type:`search`,autocomplete:`off`,placeholder:ce.value,"aria-label":o(u)(`common.searchableSelect.searchAria`,{label:i.label}),onKeydown:fe},null,40,B),[[S,k.value]])])):m(``,!0),v(`div`,{id:j.value,ref_key:`optionsList`,ref:E,class:`searchable-select-options`,role:`listbox`,"aria-multiselectable":`true`},[(_(!0),l(p,null,g(U.value,e=>(_(),l(`button`,{key:e.value,type:`button`,class:`searchable-select-option`,role:`option`,"aria-selected":M.value.has(e.value),disabled:e.disabled,onMousedown:n[2]||=f(()=>{},[`prevent`]),onClick:t=>ue(e),onKeydown:pe},[v(`span`,ie,[v(`strong`,null,x(e.label),1),e.meta?(_(),l(`small`,ae,x(e.meta),1)):m(``,!0)]),n[4]||=v(`i`,{class:`searchable-select-check`,"aria-hidden":`true`},null,-1)],40,re))),128))],8,V),U.value.length===0?(_(),l(`p`,oe,x(o(u)(`common.searchableSelect.noMatches`)),1)):m(``,!0)],8,z)],42,P))}}),ce={class:`text-field`},H=[`id`,`value`,`name`,`placeholder`,`disabled`,`required`,`rows`],U=[`id`,`value`,`name`,`type`,`placeholder`,`disabled`,`required`],W=A(C({inheritAttrs:!1,__name:`TextField`,props:{modelValue:{},label:{},controlId:{default:void 0},type:{default:`text`},placeholder:{default:void 0},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},multiline:{type:Boolean,default:!1},rows:{default:3},name:{default:void 0}},emits:[`update:modelValue`],setup(e,{emit:t}){let n=t;function r(e){n(`update:modelValue`,e.target.value)}return(t,n)=>(_(),l(`label`,ce,[v(`span`,null,x(e.label),1),e.multiline?(_(),l(`textarea`,c({key:0},t.$attrs,{id:e.controlId,value:e.modelValue,name:e.name,placeholder:e.placeholder,disabled:e.disabled,required:e.required,rows:e.rows,onInput:r}),null,16,H)):(_(),l(`input`,c({key:1},t.$attrs,{id:e.controlId,value:e.modelValue,name:e.name,type:e.type,placeholder:e.placeholder,disabled:e.disabled,required:e.required,onInput:r}),null,16,U))]))}}),[[`__scopeId`,`data-v-6c32205a`]]),le={class:`view connections-view`},G={class:`connection-intro`},ue=[`aria-label`],de=[`data-status`],fe={class:`service-state`},pe=[`data-status`],me={class:`connection-title-row`},he={class:`service-state`},K={class:`external-knowledge-section`},q={class:`section-title section-title-with-help`},ge=[`href`,`aria-label`,`title`],_e={class:`external-binding-count`},ve={class:`external-binding-list`},ye=[`data-status`],be={class:`external-binding-copy`},xe={class:`external-binding-targets`},Se=[`data-status`],Ce={key:0},we={key:1},Te={class:`external-binding-actions`},Ee=[`disabled`,`onClick`],De=[`disabled`,`onClick`],Oe=[`disabled`,`onClick`],ke=[`disabled`,`onClick`],Ae={key:0,class:`external-binding-editor`},je={class:`external-target-mode-list`},Me={class:`external-binding-editor-actions`},Ne=[`disabled`],Pe=[`disabled`,`onClick`],Fe={key:0,class:`compact-empty`},Ie={class:`wide-field`},Le={class:`trusted-code-badge`},Re=[`disabled`],ze={key:0,class:`conflict-policy-section`},Be={class:`section-title section-title-with-help`},Ve=[`href`,`aria-label`,`title`],He={class:`conflict-policy-controls`},Ue={key:1,class:`connection-subscriptions`},We={class:`section-title`},Ge={class:`subscription-list`},Ke=[`onClick`],qe={key:0,class:`empty-state`},Je={type:`submit`},Ye=C({__name:`ConnectionsPage`,setup(e){let t=k(),n=b(``),a=b([]),s=b([]),c=b(!1),S=b(null),C=b([]),A=b({}),P=b(``),F=b(`ask_human`),I=b(!1),L=i({name:``,connectorType:`mcp`,mode:`hybrid`,personalProjectIds:[],mcpTransport:`http`,mcpUrl:``,mcpCommand:``,mcpArgs:``,mcpTokenEnv:``,mcpResourcePrefix:``,notionTokenEnv:``,notionPageIds:``,notionDataSourceIds:``,feishuTokenEnv:``,feishuRegion:`cn`,feishuSpaceId:``,feishuRootNodeToken:``,feishuNodeTokens:``,feishuWebBaseUrl:``,retrievalUrl:``,retrievalTokenEnv:``,retrievalKnowledgeIds:``,retrievalScoreThreshold:`0.5`,customModule:``,customEnvironmentNames:``,customSourceJson:`{}`}),R=y(()=>t.state?.providers?.personal?.status===`ready`),z=y(()=>t.state?.providers?.workspaces??[]),ne=y(()=>z.value.filter(({status:e})=>e===`ready`).length),B=y(()=>t.state?.subscriptions??[]),V=y(()=>t.state?.personalProjects??[]),re=y(()=>Ct(`connect-external-knowledge`)),ie=y(()=>Ct(`external-knowledge-conflict-policy`)),ae=y(()=>new Set(B.value.map(({provider_url:e,project_id:t})=>`${e}::${t}`))),oe=y(()=>(t.state?.projects??[]).filter(e=>!ae.value.has($e(e)))),ce=y(()=>oe.value.map(e=>({value:$e(e),label:e.name,meta:`#${N(e.id,26)}`,search:M(e.id)}))),H=y(()=>a.value.map(e=>({value:e.type,label:e.name,meta:e.description}))),U=y(()=>V.value.map(e=>({value:e.project_id,label:e.profile.name,meta:`#${N(e.project_id,26)}`,search:M(e.project_id)}))),Ye=y(()=>[{value:`hybrid`,label:u(`pages.connections.mode.hybrid`),disabled:!Y(L.connectorType,`hybrid`)},{value:`mirror`,label:u(`pages.connections.mode.mirror`),disabled:!Y(L.connectorType,`mirror`)},{value:`live`,label:u(`pages.connections.mode.live`),disabled:!Y(L.connectorType,`live`)}]),Xe=y(()=>[{value:`http`,label:`Streamable HTTP`},{value:`stdio`,label:`stdio`}]),Ze=y(()=>[{value:`cn`,label:`Feishu`},{value:`global`,label:`Lark`}]),Qe=y(()=>[{value:`ask_human`,label:u(`pages.connections.askHuman`)},{value:`agent_decide`,label:u(`pages.connections.agentDecide`)}]);r(V,e=>{let t=new Set(e.map(({project_id:e})=>e)),n=e[0]?.project_id??``;L.personalProjectIds=L.personalProjectIds.filter(e=>t.has(e)),!L.personalProjectIds.length&&n&&(L.personalProjectIds=[n]),C.value=C.value.filter(e=>t.has(e)),t.has(P.value)||(P.value=n,n&&pt())},{immediate:!0}),r(()=>L.connectorType,e=>{Y(e,L.mode)||(L.mode=gt(e))}),ee(async()=>{await J(),P.value&&await pt()});function $e(e){return`${e.providerUrl}::${e.id}`}async function et(){let e=oe.value.find(e=>$e(e)===n.value);if(e)try{await T(`/api/subscriptions`,{personalSpaceId:t.activePersonalSpace?.id,projectId:e.id,providerUrl:e.providerUrl,projectName:e.name}),n.value=``,t.notify(u(`pages.connections.subscribed`,{name:e.name})),await t.refresh()}catch(e){t.reportError(e)}}async function tt(e){try{let n=new URLSearchParams({personalSpaceId:t.activePersonalSpace?.id??``,providerUrl:e.provider_url});await D(`/api/subscriptions/${encodeURIComponent(e.project_id)}?${n}`),t.notify(u(`pages.connections.unsubscribed`,{name:e.project_name??e.project_id})),await t.refresh()}catch(e){t.reportError(e)}}async function J(){try{let[e,t]=await Promise.all([O(`/api/external-knowledge/connectors`),O(`/api/external-knowledge/bindings`)]);a.value=e,s.value=t}catch(e){t.reportError(e)}}async function nt(){let e=t.activePersonalSpace?.id;if(!(!e||!L.personalProjectIds.length)){c.value=!0;try{let{connectorConfig:n,source:r}=rt();await T(`/api/external-knowledge/bindings`,{name:L.name.trim(),connectorType:L.connectorType,connectorConfig:n,source:r,targets:L.personalProjectIds.map(t=>({personalSpaceId:e,personalProjectId:t,mode:L.mode}))}),t.notify(u(`pages.connections.externalCreated`,{name:L.name.trim()})),L.name=``,await J()}catch(e){t.reportError(e)}finally{c.value=!1}}}function rt(){if(L.connectorType===`notion`)return{connectorConfig:{tokenEnv:$(L.notionTokenEnv,`Notion token env`)},source:{pageIds:Z(L.notionPageIds),dataSourceIds:Z(L.notionDataSourceIds)}};if(L.connectorType===`feishu`)return{connectorConfig:{accessTokenEnv:$(L.feishuTokenEnv,`Feishu token env`),region:L.feishuRegion},source:Q({spaceId:L.feishuSpaceId.trim(),rootNodeToken:L.feishuRootNodeToken.trim(),nodeTokens:Z(L.feishuNodeTokens),webBaseUrl:L.feishuWebBaseUrl.trim()})};if(L.connectorType===`retrieval_api`){let e=Number(L.retrievalScoreThreshold);if(!Number.isFinite(e)||e<0||e>1)throw TypeError(u(`pages.connections.scoreThresholdInvalid`));return{connectorConfig:Q({url:$(L.retrievalUrl,`Retrieval API URL`),tokenEnv:L.retrievalTokenEnv.trim(),scoreThreshold:e}),source:{knowledgeIds:St(L.retrievalKnowledgeIds,`Knowledge IDs`)}}}if(L.connectorType===`custom`){let e=JSON.parse(L.customSourceJson);if(!e||typeof e!=`object`||Array.isArray(e))throw TypeError(u(`pages.connections.customSourceObject`));return{connectorConfig:{module:$(L.customModule,`Custom connector module`),environmentNames:Z(L.customEnvironmentNames)},source:e}}return{connectorConfig:L.mcpTransport===`stdio`?Q({transport:`stdio`,command:L.mcpCommand.trim(),args:Z(L.mcpArgs)}):Q({transport:`http`,url:$(L.mcpUrl,`MCP URL`),tokenEnv:L.mcpTokenEnv.trim()}),source:Q({resourceUriPrefix:L.mcpResourcePrefix.trim()})}}async function it(e){await ot(e,`check`)}async function at(e){await ot(e,`sync`)}async function ot(e,n){c.value=!0;try{let r=await T(`/api/external-knowledge/bindings/${encodeURIComponent(e.id)}/${n}`,{});t.notify(u(n===`sync`&&r.skippedCredentials?`pages.connections.externalSyncedWithSkipped`:n===`sync`?`pages.connections.externalSynced`:`pages.connections.externalChecked`,{name:e.name,count:r.skippedCredentials??0})),await J()}catch(e){t.reportError(e)}finally{c.value=!1}}async function st(e){c.value=!0;try{await D(`/api/external-knowledge/bindings/${encodeURIComponent(e.id)}`),t.notify(u(`pages.connections.externalDeleted`,{name:e.name})),await J()}catch(e){t.reportError(e)}finally{c.value=!1}}function ct(e){let t=X(e);S.value=e.id,C.value=t.map(({personalProjectId:e})=>e),A.value=Object.fromEntries(t.map(({personalProjectId:e,mode:t})=>[e,t]))}function lt(){S.value=null,C.value=[],A.value={}}function ut(e){let t=s.value.find(({id:e})=>e===S.value);if(!t)return;let n=A.value,r=gt(t.connectorType);A.value=Object.fromEntries(e.map(e=>[e,n[e]??t.mode??r]))}function dt(e,t){A.value={...A.value,[e]:t}}async function ft(e){let n=t.activePersonalSpace?.id;if(!(!n||!C.value.length)){c.value=!0;try{await E(`/api/external-knowledge/bindings/${encodeURIComponent(e.id)}/targets`,{targets:C.value.map(t=>({personalSpaceId:n,personalProjectId:t,mode:A.value[t]??e.mode}))}),t.notify(u(`pages.connections.projectsUpdated`,{name:e.name})),lt(),await J()}catch(e){t.reportError(e)}finally{c.value=!1}}}async function pt(){if(P.value)try{let e=await O(`/api/external-knowledge/conflict-policy?${new URLSearchParams({personalProjectId:P.value})}`);F.value=e.mode}catch(e){t.reportError(e)}}async function mt(){let e=t.activePersonalSpace?.id;if(!(!e||!P.value)){I.value=!0;try{let n=await E(`/api/external-knowledge/conflict-policy?${new URLSearchParams({personalProjectId:P.value})}`,{personalSpaceId:e,personalProjectId:P.value,mode:F.value});F.value=n.mode,t.notify(u(`pages.connections.conflictSaved`))}catch(e){t.reportError(e)}finally{I.value=!1}}}function ht(e){return a.value.find(t=>t.type===e)?.name??e}function Y(e,t){let n=a.value.find(t=>t.type===e)?.capabilities;return!n?.length||(t===`live`||t===`hybrid`?n.includes(`retrieve`):!0)&&(t===`mirror`||t===`hybrid`?n.includes(`sync`):!0)}function gt(e){return[`hybrid`,`mirror`,`live`].find(t=>Y(e,t))??`live`}function _t(e){return[`hybrid`,`mirror`,`live`].map(t=>({value:t,label:u(`pages.connections.mode.${t}`),disabled:!Y(e,t)}))}function X(e){return e.targets?.length?e.targets:[{id:e.id,...e.target,mode:e.mode,status:e.status,sync:e.sync}]}function vt(e){return X(e).some(({mode:e})=>e!==`live`)}function yt(e){return V.value.find(({project_id:t})=>t===e)?.profile.name??e}function bt(e){return X(e).find(({sync:e})=>e?.error)?.sync?.error??e.sync?.error}function xt(e){return X(e).reduce((e,t)=>e+(t.sync?.skippedCredentials??0),0)}function Z(e){return[...new Set(e.split(`,`).map(e=>e.trim()).filter(Boolean))]}function St(e,t){let n=Z(e);if(!n.length)throw TypeError(`${t} is required`);return n}function Q(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==``&&(!Array.isArray(e)||e.length>0)))}function $(e,t){if(!e.trim())throw TypeError(`${t} is required`);return e.trim()}function Ct(e){return`https://github.com/JevonsCode/fuli/blob/main/${te()===`zh-CN`?`README.zh-CN.md`:`README.md`}#${e}`}return(e,r)=>(_(),l(`section`,le,[v(`div`,G,[v(`h3`,null,x(o(u)(`pages.connections.title`)),1)]),v(`div`,{class:`service-connection-grid`,"aria-label":o(u)(`pages.connections.statusAria`)},[v(`article`,{class:`service-connection-card`,"data-status":R.value?`ready`:`error`},[v(`header`,null,[r[30]||=v(`span`,{class:`service-connection-icon local`,"aria-hidden":`true`},[v(`span`,{class:`nav-icon nav-icon-personal-project`})],-1),v(`div`,null,[v(`h3`,null,x(o(u)(`pages.connections.localGraphiti`)),1)]),v(`span`,fe,x(R.value?o(u)(`common.status.connected`):o(u)(`common.status.connectionError`)),1)]),v(`dl`,null,[v(`div`,null,[v(`dt`,null,x(o(u)(`pages.connections.storage`)),1),r[31]||=v(`dd`,null,`Neo4j`,-1)]),v(`div`,null,[v(`dt`,null,x(o(u)(`pages.connections.purpose`)),1),v(`dd`,null,x(o(u)(`pages.connections.localPurpose`)),1)])])],8,de),v(`article`,{class:`service-connection-card`,"data-status":o(t).publicRuntimeStatus},[v(`header`,null,[r[33]||=v(`span`,{class:`service-connection-icon public`,"aria-hidden":`true`},[v(`span`,{class:`nav-icon nav-icon-public-project`})],-1),v(`div`,me,[v(`h3`,null,x(o(u)(`pages.connections.publicService`)),1),r[32]||=v(`span`,{class:`feature-badge beta`},`BETA`,-1)]),v(`span`,he,x(o(t).publicRuntimeStatus===`ready`?o(u)(`common.status.connected`):o(t).publicRuntimeStatus===`error`?o(u)(`common.status.connectionError`):o(u)(`common.status.notConnected`)),1)]),v(`dl`,null,[v(`div`,null,[v(`dt`,null,x(o(u)(`pages.connections.currentStatus`)),1),v(`dd`,null,x(o(t).publicRuntimeStatus===`ready`?o(u)(`pages.connections.sharedServicesReady`,{count:ne.value||z.value.length}):o(u)(`pages.connections.notAvailable`)),1)]),v(`div`,null,[v(`dt`,null,x(o(u)(`pages.connections.purpose`)),1),v(`dd`,null,x(o(u)(`pages.connections.publicPurpose`)),1)])])],8,pe)],8,ue),v(`section`,K,[v(`div`,q,[v(`h3`,null,x(o(u)(`pages.connections.externalTitle`)),1),v(`a`,{class:`section-help-link`,"data-testid":`external-knowledge-help`,href:re.value,"aria-label":o(u)(`pages.connections.externalHelp`),title:o(u)(`pages.connections.externalHelp`),target:`_blank`,rel:`noreferrer`},`?`,8,ge),v(`span`,_e,x(o(u)(`pages.connections.bindingCount`,{count:s.value.length})),1)]),v(`div`,ve,[(_(!0),l(p,null,g(s.value,e=>(_(),l(`article`,{key:e.id,class:`external-binding-row`,"data-status":e.status},[r[34]||=v(`i`,{"aria-hidden":`true`},null,-1),v(`div`,be,[v(`strong`,null,x(e.name),1),v(`span`,null,x(ht(e.connectorType)),1),v(`div`,xe,[v(`b`,null,x(o(u)(`pages.connections.boundTo`)),1),(_(!0),l(p,null,g(X(e),e=>(_(),l(`span`,{key:e.id,class:`external-binding-target-chip`,"data-status":e.status},x(yt(e.personalProjectId))+` · `+x(o(u)(`pages.connections.mode.${e.mode}`)),9,Se))),128))]),bt(e)?(_(),l(`small`,Ce,x(bt(e)),1)):xt(e)?(_(),l(`small`,we,x(o(u)(`pages.connections.credentialsSkipped`,{count:xt(e)})),1)):m(``,!0)]),v(`div`,Te,[v(`button`,{class:`quiet-button`,type:`button`,disabled:c.value,onClick:t=>it(e)},x(o(u)(`pages.connections.check`)),9,Ee),v(`button`,{class:`quiet-button external-sync-action`,type:`button`,disabled:c.value||!vt(e),onClick:t=>at(e)},x(o(u)(`pages.connections.sync`)),9,De),v(`button`,{class:`quiet-button`,type:`button`,disabled:c.value,onClick:t=>ct(e)},x(o(u)(`pages.connections.manageProjects`)),9,Oe),v(`button`,{class:`quiet-button danger`,type:`button`,disabled:c.value,onClick:t=>st(e)},x(o(u)(`pages.connections.disconnect`)),9,ke)]),S.value===e.id?(_(),l(`div`,Ae,[v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.targetProjects`)),1),d(se,{modelValue:C.value,"onUpdate:modelValue":r[0]||=e=>C.value=e,"control-id":`external-projects-${e.id}`,label:o(u)(`pages.connections.targetProjects`),options:U.value,disabled:c.value,required:``,searchable:``,onChange:ut},null,8,[`modelValue`,`control-id`,`label`,`options`,`disabled`])]),v(`div`,je,[(_(!0),l(p,null,g(C.value,t=>(_(),l(`div`,{key:t,class:`external-target-mode-row`},[v(`span`,null,x(yt(t)),1),d(j,{"model-value":A.value[t]??e.mode,"control-id":`external-target-mode-${e.id}-${t}`,label:o(u)(`pages.connections.bindingMode`),options:_t(e.connectorType),disabled:c.value,"onUpdate:modelValue":e=>dt(t,e)},null,8,[`model-value`,`control-id`,`label`,`options`,`disabled`,`onUpdate:modelValue`])]))),128))]),v(`div`,Me,[v(`button`,{class:`quiet-button`,type:`button`,disabled:c.value,onClick:lt},x(o(u)(`common.actions.cancel`)),9,Ne),v(`button`,{class:`primary-action`,type:`button`,disabled:c.value||!C.value.length,onClick:t=>ft(e)},x(o(u)(`pages.connections.saveProjects`)),9,Pe)])])):m(``,!0)],8,ye))),128)),s.value.length?m(``,!0):(_(),l(`div`,Fe,x(o(u)(`pages.connections.noExternalBindings`)),1))]),v(`form`,{class:`external-binding-form`,onSubmit:f(nt,[`prevent`])},[d(W,{modelValue:L.name,"onUpdate:modelValue":r[1]||=e=>L.name=e,label:o(u)(`pages.connections.bindingName`),"data-testid":`external-name`,required:``},null,8,[`modelValue`,`label`]),v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.connector`)),1),d(j,{modelValue:L.connectorType,"onUpdate:modelValue":r[2]||=e=>L.connectorType=e,"control-id":`external-connector`,label:o(u)(`pages.connections.connector`),options:H.value,disabled:c.value,required:``},null,8,[`modelValue`,`label`,`options`,`disabled`])]),v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.targetProjects`)),1),d(se,{modelValue:L.personalProjectIds,"onUpdate:modelValue":r[3]||=e=>L.personalProjectIds=e,"control-id":`external-projects`,label:o(u)(`pages.connections.targetProjects`),options:U.value,disabled:c.value,required:``,searchable:``},null,8,[`modelValue`,`label`,`options`,`disabled`])]),v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.bindingMode`)),1),d(j,{modelValue:L.mode,"onUpdate:modelValue":r[4]||=e=>L.mode=e,"control-id":`external-binding-mode`,label:o(u)(`pages.connections.bindingMode`),options:Ye.value,disabled:c.value,required:``},null,8,[`modelValue`,`label`,`options`,`disabled`])]),L.connectorType===`mcp`?(_(),l(p,{key:0},[v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.transport`)),1),d(j,{modelValue:L.mcpTransport,"onUpdate:modelValue":r[5]||=e=>L.mcpTransport=e,"control-id":`external-mcp-transport`,label:o(u)(`pages.connections.transport`),options:Xe.value,disabled:c.value,required:``},null,8,[`modelValue`,`label`,`options`,`disabled`])]),L.mcpTransport===`http`?(_(),h(W,{key:0,modelValue:L.mcpUrl,"onUpdate:modelValue":r[6]||=e=>L.mcpUrl=e,label:`MCP URL`,"data-testid":`mcp-url`,type:`url`,required:``},null,8,[`modelValue`])):(_(),h(W,{key:1,modelValue:L.mcpCommand,"onUpdate:modelValue":r[7]||=e=>L.mcpCommand=e,label:o(u)(`pages.connections.command`),required:``},null,8,[`modelValue`,`label`])),L.mcpTransport===`stdio`?(_(),h(W,{key:2,modelValue:L.mcpArgs,"onUpdate:modelValue":r[8]||=e=>L.mcpArgs=e,label:o(u)(`pages.connections.arguments`)},null,8,[`modelValue`,`label`])):(_(),h(W,{key:3,modelValue:L.mcpTokenEnv,"onUpdate:modelValue":r[9]||=e=>L.mcpTokenEnv=e,label:o(u)(`pages.connections.tokenEnv`),"data-testid":`mcp-token-env`},null,8,[`modelValue`,`label`])),d(W,{modelValue:L.mcpResourcePrefix,"onUpdate:modelValue":r[10]||=e=>L.mcpResourcePrefix=e,label:o(u)(`pages.connections.resourcePrefix`),"data-testid":`mcp-resource-prefix`},null,8,[`modelValue`,`label`])],64)):L.connectorType===`notion`?(_(),l(p,{key:1},[d(W,{modelValue:L.notionTokenEnv,"onUpdate:modelValue":r[11]||=e=>L.notionTokenEnv=e,label:o(u)(`pages.connections.tokenEnv`),required:``},null,8,[`modelValue`,`label`]),d(W,{modelValue:L.notionPageIds,"onUpdate:modelValue":r[12]||=e=>L.notionPageIds=e,label:`Page IDs`},null,8,[`modelValue`]),d(W,{modelValue:L.notionDataSourceIds,"onUpdate:modelValue":r[13]||=e=>L.notionDataSourceIds=e,label:`Data Source IDs`},null,8,[`modelValue`])],64)):L.connectorType===`feishu`?(_(),l(p,{key:2},[d(W,{modelValue:L.feishuTokenEnv,"onUpdate:modelValue":r[14]||=e=>L.feishuTokenEnv=e,label:o(u)(`pages.connections.tokenEnv`),required:``},null,8,[`modelValue`,`label`]),v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.region`)),1),d(j,{modelValue:L.feishuRegion,"onUpdate:modelValue":r[15]||=e=>L.feishuRegion=e,"control-id":`external-feishu-region`,label:o(u)(`pages.connections.region`),options:Ze.value,disabled:c.value,required:``},null,8,[`modelValue`,`label`,`options`,`disabled`])]),d(W,{modelValue:L.feishuSpaceId,"onUpdate:modelValue":r[16]||=e=>L.feishuSpaceId=e,label:`Space ID`},null,8,[`modelValue`]),d(W,{modelValue:L.feishuRootNodeToken,"onUpdate:modelValue":r[17]||=e=>L.feishuRootNodeToken=e,label:`Root Node Token`},null,8,[`modelValue`]),d(W,{modelValue:L.feishuNodeTokens,"onUpdate:modelValue":r[18]||=e=>L.feishuNodeTokens=e,label:`Node Tokens`},null,8,[`modelValue`]),d(W,{modelValue:L.feishuWebBaseUrl,"onUpdate:modelValue":r[19]||=e=>L.feishuWebBaseUrl=e,label:`Web URL`,type:`url`},null,8,[`modelValue`])],64)):L.connectorType===`retrieval_api`?(_(),l(p,{key:3},[d(W,{modelValue:L.retrievalUrl,"onUpdate:modelValue":r[20]||=e=>L.retrievalUrl=e,label:o(u)(`pages.connections.retrievalUrl`),type:`url`,required:``},null,8,[`modelValue`,`label`]),d(W,{modelValue:L.retrievalTokenEnv,"onUpdate:modelValue":r[21]||=e=>L.retrievalTokenEnv=e,label:o(u)(`pages.connections.tokenEnv`)},null,8,[`modelValue`,`label`]),d(W,{modelValue:L.retrievalKnowledgeIds,"onUpdate:modelValue":r[22]||=e=>L.retrievalKnowledgeIds=e,label:o(u)(`pages.connections.knowledgeIds`),required:``},null,8,[`modelValue`,`label`]),d(W,{modelValue:L.retrievalScoreThreshold,"onUpdate:modelValue":r[23]||=e=>L.retrievalScoreThreshold=e,label:o(u)(`pages.connections.scoreThreshold`),inputmode:`decimal`,required:``},null,8,[`modelValue`,`label`])],64)):(_(),l(p,{key:4},[d(W,{modelValue:L.customModule,"onUpdate:modelValue":r[24]||=e=>L.customModule=e,label:o(u)(`pages.connections.module`),required:``},null,8,[`modelValue`,`label`]),d(W,{modelValue:L.customEnvironmentNames,"onUpdate:modelValue":r[25]||=e=>L.customEnvironmentNames=e,label:o(u)(`pages.connections.environmentNames`)},null,8,[`modelValue`,`label`]),v(`div`,Ie,[d(W,{modelValue:L.customSourceJson,"onUpdate:modelValue":r[26]||=e=>L.customSourceJson=e,label:o(u)(`pages.connections.sourceJson`),multiline:``,required:``},null,8,[`modelValue`,`label`])]),v(`span`,Le,x(o(u)(`pages.connections.trustedCode`)),1)],64)),v(`button`,{class:`primary-action external-create-action`,type:`submit`,disabled:c.value||!V.value.length||!L.personalProjectIds.length},[r[35]||=v(`span`,{class:`external-create-action-icon`,"aria-hidden":`true`},null,-1),v(`span`,null,x(o(u)(`pages.connections.connect`)),1)],8,Re)],32)]),V.value.length?(_(),l(`section`,ze,[v(`div`,Be,[v(`h3`,null,x(o(u)(`pages.connections.conflictTitle`)),1),v(`a`,{class:`section-help-link`,"data-testid":`conflict-policy-help`,href:ie.value,"aria-label":o(u)(`pages.connections.conflictHelp`),title:o(u)(`pages.connections.conflictHelp`),target:`_blank`,rel:`noreferrer`},`?`,8,Ve)]),v(`div`,He,[v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.targetProject`)),1),d(j,{modelValue:P.value,"onUpdate:modelValue":r[27]||=e=>P.value=e,"control-id":`external-conflict-project`,label:o(u)(`pages.connections.targetProject`),options:U.value,disabled:I.value,required:``,onChange:pt},null,8,[`modelValue`,`label`,`options`,`disabled`])]),v(`label`,null,[v(`span`,null,x(o(u)(`pages.connections.conflictAction`)),1),d(j,{modelValue:F.value,"onUpdate:modelValue":r[28]||=e=>F.value=e,"control-id":`external-conflict-mode`,label:o(u)(`pages.connections.conflictAction`),options:Qe.value,disabled:I.value,required:``,onChange:mt},null,8,[`modelValue`,`label`,`options`,`disabled`])])])])):m(``,!0),o(t).state?.capabilities?.subscribeProject?(_(),l(`section`,Ue,[v(`div`,We,[v(`h3`,null,[w(x(o(u)(`pages.connections.subscriptionsTitle`))+` `,1),r[36]||=v(`span`,{class:`feature-badge beta`},`BETA`,-1)])]),v(`div`,Ge,[(_(!0),l(p,null,g(B.value,e=>(_(),l(`div`,{key:`${e.provider_url}:${e.project_id}`,class:`subscription-row`},[r[37]||=v(`span`,null,`↗`,-1),v(`div`,null,[v(`strong`,null,x(e.project_name??e.project_id),1),v(`span`,null,x(o(u)(`pages.connections.sharedProject`)),1)]),v(`button`,{class:`secondary-action subscription-action`,type:`button`,onClick:t=>tt(e)},x(o(u)(`pages.connections.unsubscribe`)),9,Ke)]))),128)),B.value.length?m(``,!0):(_(),l(`div`,qe,x(o(u)(`pages.connections.noSubscriptions`)),1))]),v(`form`,{class:`subscription-form`,onSubmit:f(et,[`prevent`])},[d(j,{modelValue:n.value,"onUpdate:modelValue":r[29]||=e=>n.value=e,options:ce.value,label:o(u)(`pages.connections.sharedProjectLabel`),placeholder:o(u)(`pages.connections.choosePublicProject`),searchable:``,required:``},null,8,[`modelValue`,`options`,`label`,`placeholder`]),v(`button`,Je,x(o(u)(`pages.connections.subscribe`)),1)],32)])):m(``,!0)]))}});export{Ye as default};
@@ -0,0 +1 @@
1
+ .virtual-directory-list[data-v-dd2afd66]{min-width:0;height:100%;min-height:0;position:relative;overflow:hidden}.virtual-directory-list__scroller[data-v-dd2afd66]{overscroll-behavior:contain;width:100%;height:100%;overflow:auto}.virtual-directory-list__header[data-v-dd2afd66]{z-index:3;position:sticky;top:0}.virtual-directory-list__canvas[data-v-dd2afd66]{position:relative}.virtual-directory-list__row[data-v-dd2afd66]{isolation:isolate;will-change:transform;width:100%;position:absolute;top:0;left:0;overflow:hidden}.virtual-directory-list__content[data-v-dd2afd66]{width:100%;height:100%;position:relative}.virtual-directory-list__content[data-v-dd2afd66] button>*{z-index:2;position:relative}.virtual-directory-list__watermark[data-v-dd2afd66]{z-index:1;color:#2f39330e;letter-spacing:-.09em;pointer-events:none;-webkit-user-select:none;user-select:none;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:31px;font-weight:760;line-height:1;position:absolute;bottom:-7px;right:9px}.virtual-directory-list__row.is-active .virtual-directory-list__watermark[data-v-dd2afd66]{color:#35604714}.virtual-directory-list__position[data-v-dd2afd66]{z-index:4;color:#8b938d;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);pointer-events:none;background:#ffffffe0;border:1px solid #cfd7d1c7;border-radius:999px;align-items:baseline;gap:4px;padding:6px 9px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:9px;line-height:1;display:flex;position:absolute;bottom:12px;right:12px;box-shadow:0 3px 12px #2f393314}.virtual-directory-list__position strong[data-v-dd2afd66]{color:#425047;font-size:11px;font-weight:720}.knowledge-confirm-dialog[data-v-26170b1a]{width:min(680px,100vw - 48px)}.knowledge-confirm-dialog-shell[data-v-26170b1a]{gap:18px;padding:24px;display:grid}.knowledge-confirm-summary[data-v-26170b1a]{border-top:1px solid #e1e5e2;border-bottom:1px solid #e1e5e2;gap:6px;padding:14px 0;display:grid}.knowledge-confirm-summary span[data-v-26170b1a],.knowledge-confirm-summary small[data-v-26170b1a]{color:#7d8780;font-size:10px}.knowledge-confirm-summary strong[data-v-26170b1a]{color:#29382f;font-size:16px}.knowledge-confirm-summary p[data-v-26170b1a]{color:#606b63;font-size:12px;line-height:1.65}.knowledge-confirm-fields[data-v-26170b1a]{gap:14px;display:grid}.knowledge-confirm-fields label[data-v-26170b1a]{color:#59645c;gap:6px;font-size:11px;font-weight:600;display:grid}.knowledge-confirm-acknowledgement[data-v-26170b1a]{color:#4e5c53;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:9px;font-size:11px;line-height:1.5;display:grid}