fuli-context 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +178 -0
  3. package/compose.graphiti.yml +86 -0
  4. package/dist/web/assets/ConnectionsPage-CY6H_mJJ.js +1 -0
  5. package/dist/web/assets/KnowledgeInspector-BSpz5Sfm.js +1 -0
  6. package/dist/web/assets/KnowledgeInspector-CHbB_0rC.css +1 -0
  7. package/dist/web/assets/KnowledgeOrganizerPage-BlEvhPrv.css +1 -0
  8. package/dist/web/assets/KnowledgeOrganizerPage-CvjGPlUc.js +1 -0
  9. package/dist/web/assets/KnowledgePage-Khuo3cNs.js +1 -0
  10. package/dist/web/assets/KnowledgeWorkspace-DVZusvem.js +4 -0
  11. package/dist/web/assets/OverviewPage-DC4C4Fhn.js +1 -0
  12. package/dist/web/assets/PersonalProfilePage-CSV9Mtgz.js +1 -0
  13. package/dist/web/assets/PersonalProfilePage-CVJ3TcRi.css +1 -0
  14. package/dist/web/assets/PersonalProjectsPage-A50EaseQ.js +1 -0
  15. package/dist/web/assets/PublicProjectsPage-BAdO_bae.js +1 -0
  16. package/dist/web/assets/ReviewPage-Dztk2jDG.js +1 -0
  17. package/dist/web/assets/console-tbvTUi6p.js +1 -0
  18. package/dist/web/assets/fuli-logo-DGuyqchQ.png +0 -0
  19. package/dist/web/assets/identity-B3s5CXhv.js +1 -0
  20. package/dist/web/assets/index-Devf7glZ.css +1 -0
  21. package/dist/web/assets/index-DwUDhQKc.js +6 -0
  22. package/dist/web/assets/model-DVT8sjy9.js +1 -0
  23. package/dist/web/assets/paths-B790iniO.js +1 -0
  24. package/dist/web/assets/runtime-dom.esm-bundler-DttsK21F.js +1 -0
  25. package/dist/web/assets/vue-router-BYTAoWT3.js +1 -0
  26. package/dist/web/index.html +22 -0
  27. package/graph-provider/Dockerfile +16 -0
  28. package/graph-provider/fuli_graph/__init__.py +5 -0
  29. package/graph-provider/fuli_graph/app.py +547 -0
  30. package/graph-provider/fuli_graph/auth.py +17 -0
  31. package/graph-provider/fuli_graph/collaboration_context.py +290 -0
  32. package/graph-provider/fuli_graph/config.py +34 -0
  33. package/graph-provider/fuli_graph/graph_models.py +123 -0
  34. package/graph-provider/fuli_graph/graph_projection.py +405 -0
  35. package/graph-provider/fuli_graph/graph_query.py +561 -0
  36. package/graph-provider/fuli_graph/knowledge_audit.py +765 -0
  37. package/graph-provider/fuli_graph/knowledge_batch_confirmation.py +246 -0
  38. package/graph-provider/fuli_graph/knowledge_management.py +816 -0
  39. package/graph-provider/fuli_graph/knowledge_records.py +65 -0
  40. package/graph-provider/fuli_graph/knowledge_search.py +723 -0
  41. package/graph-provider/fuli_graph/knowledge_usage_models.py +52 -0
  42. package/graph-provider/fuli_graph/model_validation.py +58 -0
  43. package/graph-provider/fuli_graph/models.py +1179 -0
  44. package/graph-provider/fuli_graph/personal_project_access.py +29 -0
  45. package/graph-provider/fuli_graph/preference_conflicts.py +420 -0
  46. package/graph-provider/fuli_graph/project_action_models.py +142 -0
  47. package/graph-provider/fuli_graph/project_knowledge.py +707 -0
  48. package/graph-provider/fuli_graph/project_management.py +251 -0
  49. package/graph-provider/fuli_graph/provider_values.py +40 -0
  50. package/graph-provider/fuli_graph/runtime.py +350 -0
  51. package/graph-provider/fuli_graph/search_projection.py +156 -0
  52. package/graph-provider/fuli_graph/store.py +24 -0
  53. package/graph-provider/fuli_graph/store_identity.py +237 -0
  54. package/graph-provider/fuli_graph/store_knowledge.py +447 -0
  55. package/graph-provider/fuli_graph/store_projects.py +242 -0
  56. package/graph-provider/fuli_graph/store_publication.py +370 -0
  57. package/graph-provider/fuli_graph/store_records.py +134 -0
  58. package/graph-provider/pyproject.toml +35 -0
  59. package/npm-shrinkwrap.json +6045 -0
  60. package/package.json +99 -0
  61. package/skills/capturing-session-knowledge/SKILL.md +226 -0
  62. package/skills/capturing-session-knowledge/agents/openai.yaml +13 -0
  63. package/skills/grilling-project/SKILL.md +129 -0
  64. package/skills/grilling-project/agents/openai.yaml +4 -0
  65. package/skills/grilling-project/references/project-profile.md +105 -0
  66. package/src/agent/candidate-read-service.js +53 -0
  67. package/src/agent/context-pack-service.js +83 -0
  68. package/src/agent/public-read-policy.js +39 -0
  69. package/src/agent/public-read-service.js +69 -0
  70. package/src/agent/read-projection.js +107 -0
  71. package/src/agent/search-service.js +61 -0
  72. package/src/agent/space-boundary.js +33 -0
  73. package/src/agent-tools/graph-definitions.js +479 -0
  74. package/src/agent-tools/graph-handlers.js +96 -0
  75. package/src/agent-tools/schema.js +37 -0
  76. package/src/agent-tools.js +16 -0
  77. package/src/app/application-error.js +13 -0
  78. package/src/app/bootstrap.js +8 -0
  79. package/src/app/create-application.js +143 -0
  80. package/src/app/state-service.js +38 -0
  81. package/src/candidates.js +78 -0
  82. package/src/classifier.js +63 -0
  83. package/src/cli/command-arguments.js +14 -0
  84. package/src/cli/command-registry.js +78 -0
  85. package/src/cli/commands/candidates.js +17 -0
  86. package/src/cli/commands/ingestion.js +32 -0
  87. package/src/cli/commands/reads.js +50 -0
  88. package/src/cli/commands/spaces.js +20 -0
  89. package/src/cli/invocation.js +47 -0
  90. package/src/cli/local-runtime-command.js +94 -0
  91. package/src/cli/local-runtime-options.js +64 -0
  92. package/src/cli/migrate-command.js +71 -0
  93. package/src/cli/migration-destination.js +117 -0
  94. package/src/cli/setup-agent-selection.js +195 -0
  95. package/src/cli/setup-command.js +85 -0
  96. package/src/cli/uninstall-command.js +67 -0
  97. package/src/cli.js +90 -0
  98. package/src/context-pack.js +206 -0
  99. package/src/defaults.js +1 -0
  100. package/src/extractor.js +77 -0
  101. package/src/fact-history.js +39 -0
  102. package/src/facts/fact-service.js +89 -0
  103. package/src/graphiti/agent-access-policy.js +88 -0
  104. package/src/graphiti/capture-policy.js +84 -0
  105. package/src/graphiti/federated-application.js +1292 -0
  106. package/src/graphiti/personal-context.js +29 -0
  107. package/src/graphiti/project-path-context.js +159 -0
  108. package/src/graphiti/provider-client.js +288 -0
  109. package/src/graphiti/runtime-config.js +85 -0
  110. package/src/graphiti/setup.js +43 -0
  111. package/src/graphiti/source-marker.js +142 -0
  112. package/src/http/api-router.js +133 -0
  113. package/src/http/bounded-json-array.js +19 -0
  114. package/src/http/error-mapping.js +36 -0
  115. package/src/http/graph-api-router.js +257 -0
  116. package/src/http/lens-route.js +50 -0
  117. package/src/http/request-policy.js +41 -0
  118. package/src/http/response.js +29 -0
  119. package/src/http/static-handler.js +55 -0
  120. package/src/ingestion.js +161 -0
  121. package/src/lens/lens-correction-service.js +81 -0
  122. package/src/lens/lens-fact-writer.js +85 -0
  123. package/src/lens/lens-input.js +62 -0
  124. package/src/lens/lens-query-projection.js +87 -0
  125. package/src/lens/lens-query-ranking.js +62 -0
  126. package/src/lens/lens-query.js +143 -0
  127. package/src/lens/lens-resource-projection.js +93 -0
  128. package/src/lens/lens-resource-selection.js +45 -0
  129. package/src/lens/lens-resource-service.js +103 -0
  130. package/src/lens/lens-search-query.js +122 -0
  131. package/src/lens/lens-service.js +183 -0
  132. package/src/local-runtime/lifecycle.js +254 -0
  133. package/src/mcp/create-mcp-server.js +85 -0
  134. package/src/mcp/instructions.js +10 -0
  135. package/src/mcp/project-action-preview-tokens.js +72 -0
  136. package/src/mcp/runtime.js +71 -0
  137. package/src/mcp/tool-annotations.js +63 -0
  138. package/src/mcp/tool-result.js +167 -0
  139. package/src/mcp/tool-schema.js +60 -0
  140. package/src/mcp-server.js +76 -0
  141. package/src/models.js +44 -0
  142. package/src/observer.js +83 -0
  143. package/src/package-metadata.js +6 -0
  144. package/src/project-rules.js +33 -0
  145. package/src/publication/canonical-json.js +39 -0
  146. package/src/publication/outbox-service.js +46 -0
  147. package/src/publication/publication-envelope-schema.js +75 -0
  148. package/src/publication/publication-envelope.js +37 -0
  149. package/src/publication/publication-policy.js +82 -0
  150. package/src/publication/publication-service.js +48 -0
  151. package/src/router.js +58 -0
  152. package/src/runtime-options.js +139 -0
  153. package/src/security/episode-visibility.js +14 -0
  154. package/src/security/fact-visibility.js +15 -0
  155. package/src/security/sensitive-content.js +18 -0
  156. package/src/security/source-metadata-policy.js +8 -0
  157. package/src/server/application-lifecycle.js +34 -0
  158. package/src/server/listen.js +24 -0
  159. package/src/server.js +135 -0
  160. package/src/setup/agent-installation-status.js +97 -0
  161. package/src/setup/agents.js +123 -0
  162. package/src/setup/codex-bootstrap.js +118 -0
  163. package/src/setup/codex-config.js +122 -0
  164. package/src/setup/config-backup.js +22 -0
  165. package/src/setup/container-runtime.js +388 -0
  166. package/src/setup/cursor-config.js +61 -0
  167. package/src/setup/graph-runtime.js +360 -0
  168. package/src/setup/node-runtime.js +24 -0
  169. package/src/setup/options.js +91 -0
  170. package/src/setup/paths.js +47 -0
  171. package/src/setup/session-skill.js +91 -0
  172. package/src/setup/setup.js +85 -0
  173. package/src/setup/uninstall.js +90 -0
  174. package/src/storage/episode-evidence-preview.js +100 -0
  175. package/src/storage/fact-search-order.js +18 -0
  176. package/src/storage/file/episode-evidence.js +37 -0
  177. package/src/storage/file/episode-index.js +59 -0
  178. package/src/storage/file/fact-search.js +60 -0
  179. package/src/storage/file-store.js +437 -0
  180. package/src/storage/import-json.js +70 -0
  181. package/src/storage/json-file.js +41 -0
  182. package/src/storage/legacy-record-validation.js +152 -0
  183. package/src/storage/legacy-snapshot-validation.js +32 -0
  184. package/src/storage/migrate.js +128 -0
  185. package/src/storage/migrations/001-initial.sql +83 -0
  186. package/src/storage/migrations/002-storage-integrity.sql +113 -0
  187. package/src/storage/record-validation.js +46 -0
  188. package/src/storage/snapshot-defaults.js +54 -0
  189. package/src/storage/sqlite/candidates-repository.js +84 -0
  190. package/src/storage/sqlite/episode-evidence-repository.js +154 -0
  191. package/src/storage/sqlite/episode-privacy-sql.js +33 -0
  192. package/src/storage/sqlite/episodes-repository.js +52 -0
  193. package/src/storage/sqlite/fact-search-repository.js +162 -0
  194. package/src/storage/sqlite/facts-repository.js +146 -0
  195. package/src/storage/sqlite/imports-repository.js +39 -0
  196. package/src/storage/sqlite/mapper.js +84 -0
  197. package/src/storage/sqlite/open-database.js +15 -0
  198. package/src/storage/sqlite/outbox-repository.js +103 -0
  199. package/src/storage/sqlite/snapshot-repository.js +69 -0
  200. package/src/storage/sqlite/spaces-repository.js +52 -0
  201. package/src/storage/sqlite/subscriptions-repository.js +54 -0
  202. package/src/storage/sqlite-store.js +159 -0
  203. package/src/storage/stable-json.js +24 -0
  204. package/src/storage/store-port.js +20 -0
  205. package/src/store.js +2 -0
  206. package/src/workspace-protocol/array-validation.js +19 -0
  207. package/src/workspace-protocol/base64url-contract.js +27 -0
  208. package/src/workspace-protocol/constants.js +37 -0
  209. package/src/workspace-protocol/error-contract.js +24 -0
  210. package/src/workspace-protocol/fact-contract.js +110 -0
  211. package/src/workspace-protocol/governance-contract.js +47 -0
  212. package/src/workspace-protocol/index.js +53 -0
  213. package/src/workspace-protocol/json-budget.js +19 -0
  214. package/src/workspace-protocol/manifest-contract.js +186 -0
  215. package/src/workspace-protocol/publication-contract.js +212 -0
  216. package/src/workspace-protocol/query-contract.js +149 -0
  217. package/src/workspace-protocol/scalar-contract.js +192 -0
  218. package/src/workspace-protocol/sync-contract.js +184 -0
  219. package/src/workspace-protocol/text-contract.js +39 -0
  220. package/src/workspace-protocol/validation.js +66 -0
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Fuli contributors
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # 复利(Fuli)
2
+
3
+ 复利是一个面向 AI Agent 的本地优先上下文图谱。它让 Codex、Claude Code 和
4
+ Cursor 在会话之间复用个人偏好、项目约束、历史决策与 Runbook,同时保留来源和
5
+ 知识边界。
6
+
7
+ 当前 npm 版本是个人版:个人知识与管理界面运行在本机。团队共享 Provider 是独立的
8
+ 服务部署单元,不作为第二个用户 npm 包发布。
9
+
10
+ ## 安装
11
+
12
+ 准备:
13
+
14
+ - Node.js 24.12 或更高版本
15
+ - Docker Compose v2;Docker Desktop 或 Rancher Desktop 均可
16
+ - 至少约 4 GB 可供容器使用的内存
17
+
18
+ 全局安装并初始化:
19
+
20
+ ```bash
21
+ npm install --global fuli-context
22
+ fl setup
23
+ ```
24
+
25
+ `fl setup` 会先展示即将进行的操作,再请求确认。它会检查容器运行时、初始化本机
26
+ Graphiti / Neo4j、创建个人空间、安装配套 Agent Skills,并为检测到的 Agent 注册
27
+ `fuli` MCP。Codex 接入还会在用户级 `AGENTS.md` 中合并一段很短的 Bootstrap:每个
28
+ 用户任务开始时先调用协作偏好工具,并把当前工作目录作为 `projectPath` 传给 Fuli。
29
+ 偏好正文仍以 Fuli 为唯一来源,不会复制到 Codex 配置中。默认不会连接或模拟团队共享
30
+ Provider。
31
+
32
+ 初始化完成后:
33
+
34
+ ```bash
35
+ fl open
36
+ ```
37
+
38
+ 管理界面默认位于 `http://127.0.0.1:2727`。
39
+
40
+ ## 常用命令
41
+
42
+ ```bash
43
+ fl --version
44
+ fl --help
45
+
46
+ fl start
47
+ fl start --open
48
+ fl status
49
+ fl status --json
50
+ fl open
51
+ fl restart
52
+ fl restart --rebuild
53
+ fl stop
54
+ ```
55
+
56
+ `fl stop` 只停止本机服务,不删除图谱数据。需要无人值守初始化时可以使用:
57
+
58
+ ```bash
59
+ fl setup --yes
60
+ ```
61
+
62
+ 只初始化 Provider、不启动管理界面:
63
+
64
+ ```bash
65
+ fl setup --no-start
66
+ ```
67
+
68
+ ## 更新
69
+
70
+ ```bash
71
+ fl stop
72
+ npm install --global fuli-context@latest
73
+ fl setup --yes
74
+ ```
75
+
76
+ 重复执行 setup 会保留既有知识数据,并刷新 Agent 接入和配套 Skills。
77
+
78
+ ## 卸载
79
+
80
+ 先清理 Agent 接入,再移除全局 npm 包:
81
+
82
+ ```bash
83
+ fl uninstall
84
+ npm uninstall --global fuli-context
85
+ ```
86
+
87
+ `fl uninstall` 会:
88
+
89
+ - 停止本机 Fuli 服务;
90
+ - 从 Codex、Claude Code 和 Cursor 中移除 Fuli MCP 接入;
91
+ - 只删除仍与当前安装包完全一致的 Fuli Skills,有本地修改的 Skill 会保留;
92
+ - 保留个人图谱、配置备份与 Neo4j 数据卷。
93
+
94
+ 这样重新安装时可以继续使用原数据。数据永久删除不包含在自动卸载流程中,避免误删。
95
+
96
+ ## 个人版边界
97
+
98
+ - 个人知识写入本机 Provider。
99
+ - Agent 归纳结构化知识,不保存整段会话。
100
+ - Token、Cookie、私钥、凭据、临时日志与原始命令输出不会写入图谱。
101
+ - Graphiti 的远程 LLM 路径被禁用;当前嵌入在本机计算。
102
+ - 搜索按个人空间和项目范围显式限定,不会默认混入所有项目。
103
+ - Fuli 不是实时监控或 Git 服务;实时错误和代码状态应从对应的监控、日志或 Git
104
+ 工具获取。
105
+
106
+ 团队共享能力将通过单独部署的 Provider 提供。个人版 npm 继续作为本地 CLI、管理界面
107
+ 和 Agent 接入客户端,避免用户同时安装两个容易混淆的全局命令包。
108
+
109
+ ## Agent 工作方式
110
+
111
+ Fuli 为支持的 Agent 安装两个用户级 Skills:
112
+
113
+ - `capturing-session-knowledge`:按稳定知识边界检索和静默沉淀上下文;
114
+ - `grilling-project`:帮助用户审视和补全个人项目资料。
115
+
116
+ Codex 的用户级 Bootstrap 要求 Agent 在每个用户任务开始时、调用其他工具或回答之前,
117
+ 调用 `get_collaboration_preferences`。调用只把当前工作目录作为瞬时 `projectPath`
118
+ 传给本机 Fuli;绝对路径不会写入图谱,也不会出现在工具结果中。Fuli 在 MCP 服务端
119
+ 完成匹配:个人全局的品味、个性与判断偏好始终生效;只有仓库根、Codex worktree 的
120
+ 原仓库,或工作区内唯一的精确子项目对应一个已登记个人项目时,才叠加该项目偏好。
121
+ 模糊、多项目、待确认、已失效、冲突或其他项目的偏好不会进入实际生效列表。首次写入
122
+ 或更新 Bootstrap 后,新建或重新打开一个 Codex 任务,让用户级 `AGENTS.md` 重新加载;
123
+ 此后偏好修改会在下一次用户任务中重新读取,不需要重启 Codex。
124
+
125
+ 疑似冲突既可以立即人工处理,也可以标记为“交给 AI,使用时处理”。后者不会提前覆盖
126
+ 任何一条记录;只有后续任务确实需要相关偏好时,Agent 才会先比较双方并调用专用解决
127
+ 工具。解决结果会保留修订历史,并标明该偏好曾发生冲突、由 AI 处理及其判断依据。
128
+ 协作偏好页顶部的“已确认”“待确认”“疑似冲突”均为可点击入口;“待确认”会筛出对应
129
+ 记录并打开首条详情,可继续确认、纠正或标记失效。
130
+
131
+ 主要 MCP 工具包括:
132
+
133
+ | 工具 | 用途 |
134
+ | --- | --- |
135
+ | `get_collaboration_preferences` | 获取当前会话实际生效的全局与项目级协作偏好 |
136
+ | `resolve_deferred_preference_conflict` | 在相关任务首次使用前解决已交给 AI 的偏好冲突并留下审计标记 |
137
+ | `capture_session_knowledge` | 批量写入个人知识或创建发布预审草稿 |
138
+ | `search_knowledge_graph` | 在明确范围内查询个人偏好与项目知识 |
139
+ | `get_knowledge_graph` | 获取有界节点—关系图 |
140
+ | `list_knowledge_spaces` | 查看个人空间、项目与订阅 |
141
+ | `upsert_personal_project` | 新建或更新个人项目资料 |
142
+ | `revise_personal_knowledge` | 修正、失效或恢复个人知识 |
143
+ | `get_graphiti_status` | 检查 Provider 与 Graphiti 状态 |
144
+
145
+ ## 本机服务
146
+
147
+ | 服务 | 默认地址 |
148
+ | --- | --- |
149
+ | 个人 Neo4j Browser / Bolt | `127.0.0.1:7474` / `127.0.0.1:7687` |
150
+ | 个人 Provider | `127.0.0.1:8787` |
151
+ | Fuli 管理界面 | `127.0.0.1:2727` |
152
+
153
+ 如果端口被占用、Docker Compose 不可用或容器引擎未启动,setup 会在修改 Agent 配置前
154
+ 停止,并给出对应错误。
155
+
156
+ ## 源码开发
157
+
158
+ ```bash
159
+ npm install
160
+ npm test
161
+ npm run test:package
162
+ ```
163
+
164
+ Provider 验证:
165
+
166
+ ```bash
167
+ python3 -m compileall -q graph-provider/fuli_graph
168
+ python3 -m pytest -q graph-provider/tests
169
+ docker compose -f compose.graphiti.yml config --quiet
170
+ ```
171
+
172
+ `npm run test:package` 会构建前端、生成真实 npm tarball、安装到隔离的全局前缀,并验证
173
+ `fl`、版本号、帮助信息和已发布 Web UI。测试源码、QA 截图与内部设计文档都不会进入
174
+ npm 包。
175
+
176
+ ## License
177
+
178
+ [Apache-2.0](LICENSE)
@@ -0,0 +1,86 @@
1
+ name: fuli-graphiti
2
+
3
+ services:
4
+ personal-neo4j:
5
+ image: neo4j:5.26-community
6
+ environment:
7
+ NEO4J_AUTH: neo4j/${FULI_PERSONAL_NEO4J_PASSWORD}
8
+ NEO4J_server_memory_heap_initial__size: 256m
9
+ NEO4J_server_memory_heap_max__size: 512m
10
+ NEO4J_server_memory_pagecache_size: 256m
11
+ ports:
12
+ - "127.0.0.1:7474:7474"
13
+ - "127.0.0.1:7687:7687"
14
+ volumes:
15
+ - personal_neo4j_data:/data
16
+ healthcheck:
17
+ test: ["CMD-SHELL", "cypher-shell -u neo4j -p \"$${NEO4J_AUTH#neo4j/}\" 'RETURN 1' >/dev/null"]
18
+ interval: 5s
19
+ timeout: 3s
20
+ retries: 30
21
+ restart: unless-stopped
22
+
23
+ workspace-neo4j:
24
+ image: neo4j:5.26-community
25
+ environment:
26
+ NEO4J_AUTH: neo4j/${FULI_WORKSPACE_NEO4J_PASSWORD}
27
+ NEO4J_server_memory_heap_initial__size: 256m
28
+ NEO4J_server_memory_heap_max__size: 512m
29
+ NEO4J_server_memory_pagecache_size: 256m
30
+ ports:
31
+ - "127.0.0.1:7475:7474"
32
+ - "127.0.0.1:7688:7687"
33
+ volumes:
34
+ - workspace_neo4j_data:/data
35
+ healthcheck:
36
+ test: ["CMD-SHELL", "cypher-shell -u neo4j -p \"$${NEO4J_AUTH#neo4j/}\" 'RETURN 1' >/dev/null"]
37
+ interval: 5s
38
+ timeout: 3s
39
+ retries: 30
40
+ restart: unless-stopped
41
+
42
+ personal-provider:
43
+ build:
44
+ context: ./graph-provider
45
+ environment:
46
+ FULI_PROVIDER_MODE: personal
47
+ FULI_PROVIDER_ID: local-personal
48
+ FULI_PROVIDER_NAME: Fuli Personal Provider
49
+ FULI_BOOTSTRAP_TOKEN: ${FULI_PERSONAL_BOOTSTRAP_TOKEN}
50
+ FULI_NEO4J_URI: bolt://personal-neo4j:7687
51
+ FULI_NEO4J_USER: neo4j
52
+ FULI_NEO4J_PASSWORD: ${FULI_PERSONAL_NEO4J_PASSWORD}
53
+ FULI_EMBEDDING_DIM: 384
54
+ EMBEDDING_DIM: 384
55
+ GRAPHITI_TELEMETRY_ENABLED: "false"
56
+ ports:
57
+ - "127.0.0.1:8787:8787"
58
+ depends_on:
59
+ personal-neo4j:
60
+ condition: service_healthy
61
+ restart: unless-stopped
62
+
63
+ workspace-provider:
64
+ build:
65
+ context: ./graph-provider
66
+ environment:
67
+ FULI_PROVIDER_MODE: workspace
68
+ FULI_PROVIDER_ID: development-workspace
69
+ FULI_PROVIDER_NAME: Fuli Workspace Provider
70
+ FULI_BOOTSTRAP_TOKEN: ${FULI_WORKSPACE_BOOTSTRAP_TOKEN}
71
+ FULI_NEO4J_URI: bolt://workspace-neo4j:7687
72
+ FULI_NEO4J_USER: neo4j
73
+ FULI_NEO4J_PASSWORD: ${FULI_WORKSPACE_NEO4J_PASSWORD}
74
+ FULI_EMBEDDING_DIM: 384
75
+ EMBEDDING_DIM: 384
76
+ GRAPHITI_TELEMETRY_ENABLED: "false"
77
+ ports:
78
+ - "127.0.0.1:8788:8787"
79
+ depends_on:
80
+ workspace-neo4j:
81
+ condition: service_healthy
82
+ restart: unless-stopped
83
+
84
+ volumes:
85
+ personal_neo4j_data:
86
+ workspace_neo4j_data:
@@ -0,0 +1 @@
1
+ import{D as e,L as t,P as n,T as r,a as i,c as a,d as o,m as s,n as c,nt as l,p as u,t as d,u as f,v as p,y as m}from"./console-tbvTUi6p.js";import{o as h}from"./runtime-dom.esm-bundler-DttsK21F.js";import{n as g,r as _,t as v}from"./identity-B3s5CXhv.js";var y={class:`view connections-view`},b={class:`service-connection-grid`,"aria-label":`知识服务连接状态`},x=[`data-status`],S={class:`service-state`},C=[`data-status`],w={class:`service-state`},T={key:0,class:`connection-subscriptions`},E={class:`subscription-list`},D=[`onClick`],O={key:0,class:`empty-state`},k=m({__name:`ConnectionsPage`,setup(m){let k=d(),A=n(``),j=f(()=>k.state?.providers?.personal?.status===`ready`),M=f(()=>k.state?.providers?.workspaces??[]),N=f(()=>M.value.filter(({status:e})=>e===`ready`).length),P=f(()=>k.state?.subscriptions??[]),F=f(()=>new Set(P.value.map(({provider_url:e,project_id:t})=>`${e}::${t}`))),I=f(()=>(k.state?.projects??[]).filter(e=>!F.value.has(R(e)))),L=f(()=>I.value.map(e=>({value:R(e),label:e.name,meta:`#${v(e.id,26)}`,search:g(e.id)})));function R(e){return`${e.providerUrl}::${e.id}`}async function z(){let e=I.value.find(e=>R(e)===A.value);if(e)try{await i(`/api/subscriptions`,{personalSpaceId:k.activePersonalSpace?.id,projectId:e.id,providerUrl:e.providerUrl,projectName:e.name}),A.value=``,k.notify(`已订阅“${e.name}”。`),await k.refresh()}catch(e){k.reportError(e)}}async function B(e){try{let t=new URLSearchParams({personalSpaceId:k.activePersonalSpace?.id??``,providerUrl:e.provider_url});await c(`/api/subscriptions/${encodeURIComponent(e.project_id)}?${t}`),k.notify(`已取消订阅“${e.project_name??e.project_id}”。`),await k.refresh()}catch(e){k.reportError(e)}}return(n,i)=>(r(),s(`section`,y,[i[12]||=o(`div`,{class:`connection-intro`},[o(`h3`,null,`服务连接与订阅`),o(`p`,null,`本地知识库始终独立运行;公共能力只在连接共享 Provider 后开启。`)],-1),o(`div`,b,[o(`article`,{class:`service-connection-card`,"data-status":j.value?`ready`:`error`},[o(`header`,null,[i[1]||=o(`span`,{class:`service-connection-icon local`,"aria-hidden":`true`},[o(`span`,{class:`nav-icon nav-icon-personal-project`})],-1),i[2]||=o(`div`,null,[o(`p`,null,`LOCAL KNOWLEDGE`),o(`h3`,null,`本地 Graphiti`)],-1),o(`span`,S,l(j.value?`已连接`:`连接异常`),1)]),o(`p`,null,l(j.value?`个人项目、协作偏好和会话知识正在写入本机图谱。`:`本地知识库暂时无法使用,请检查 Graphiti 与 Neo4j。`),1),i[3]||=o(`dl`,null,[o(`div`,null,[o(`dt`,null,`存储`),o(`dd`,null,`Neo4j`)]),o(`div`,null,[o(`dt`,null,`用途`),o(`dd`,null,`个人项目与协作偏好`)])],-1)],8,x),o(`article`,{class:`service-connection-card`,"data-status":t(k).publicRuntimeStatus},[o(`header`,null,[i[4]||=o(`span`,{class:`service-connection-icon public`,"aria-hidden":`true`},[o(`span`,{class:`nav-icon nav-icon-public-project`})],-1),i[5]||=o(`div`,null,[o(`p`,null,`PUBLIC PROVIDER`),o(`h3`,null,`公共服务`)],-1),o(`span`,w,l(t(k).publicRuntimeStatus===`ready`?`已连接`:t(k).publicRuntimeStatus===`error`?`连接异常`:`未连接`),1)]),o(`p`,null,l(t(k).publicRuntimeStatus===`ready`?`公共项目、订阅、发布与团队协作功能已经可以使用。`:t(k).publicRuntimeStatus===`error`?`公共服务已经配置,但当前无法访问;本地知识库仍可正常使用。`:`当前未连接公共服务;公共能力保持关闭。`),1),o(`dl`,null,[o(`div`,null,[i[6]||=o(`dt`,null,`当前状态`,-1),o(`dd`,null,l(t(k).publicRuntimeStatus===`ready`?`${N.value||M.value.length} 个共享服务可用`:`尚未可用`),1)]),i[7]||=o(`div`,null,[o(`dt`,null,`用途`),o(`dd`,null,`发现、订阅、发布与协作`)],-1)])],8,C)]),t(k).state?.capabilities?.subscribeProject?(r(),s(`section`,T,[i[11]||=o(`div`,{class:`section-title`},[o(`h3`,null,`公共项目订阅`),o(`p`,null,`只把你主动选择的公共项目加入个人检索范围。`)],-1),o(`div`,E,[(r(!0),s(a,null,e(P.value,e=>(r(),s(`div`,{key:`${e.provider_url}:${e.project_id}`,class:`subscription-row`},[i[9]||=o(`span`,null,`↗`,-1),o(`div`,null,[o(`strong`,null,l(e.project_name??e.project_id),1),i[8]||=o(`span`,null,`团队共享项目`,-1)]),o(`button`,{class:`secondary-action subscription-action`,type:`button`,onClick:t=>B(e)},`取消订阅`,8,D)]))),128)),P.value.length?u(``,!0):(r(),s(`div`,O,`尚未订阅团队共享项目`))]),o(`form`,{class:`subscription-form`,onSubmit:h(z,[`prevent`])},[p(_,{modelValue:A.value,"onUpdate:modelValue":i[0]||=e=>A.value=e,options:L.value,label:`团队共享项目`,placeholder:`选择公共项目`,searchable:``,required:``},null,8,[`modelValue`,`options`]),i[10]||=o(`button`,{type:`submit`},`订阅项目`,-1)],32)])):u(``,!0)]))}});export{k as default};
@@ -0,0 +1 @@
1
+ import{A as e,D as t,L as n,M as r,N as i,P as a,T as o,_ as s,a as c,c as l,d as u,i as d,m as f,nt as p,p as m,t as h,tt as g,u as _,v,y}from"./console-tbvTUi6p.js";import{a as b,n as x,o as S}from"./runtime-dom.esm-bundler-DttsK21F.js";import{n as C,r as w,t as T}from"./identity-B3s5CXhv.js";import{C as E,D,E as O,S as k,T as A,d as j,f as M,g as N,h as P,i as F,l as I,r as L,s as R,u as z,w as B,x as V}from"./model-DVT8sjy9.js";var H=(e,t)=>{let n=e.__vccOpts||e;for(let[e,r]of t)n[e]=r;return n},U={key:0,open:``,class:`knowledge-confirm-dialog vue-dialog`},W={class:`project-dialog-header`},G=[`disabled`],K={class:`knowledge-confirm-summary`},q={class:`knowledge-confirm-fields`},J={class:`knowledge-confirm-acknowledgement`},Y={key:0,class:`publish-dialog-error`,role:`alert`},X={class:`project-profile-dialog-actions`},ee=[`disabled`],te=[`disabled`],ne=H(y({__name:`KnowledgeConfirmDialog`,props:{item:{},personalSpaceId:{},personalProjectId:{}},emits:[`close`,`saved`],setup(t,{emit:i}){let s=t,c=i,l=h(),g=a(``),v=a(``),y=a(``),C=a(!1),w=a(!1),T=a(``),E=a({kind:`import`,label:`历史记录`}),D=_(()=>s.item?.profileAspect?`这条偏好`:`这条知识`);e(()=>s.item,e=>{if(!e)return;let t=e.evidence.at(0),n=e.confirmationBasis;g.value=n?.existence_reason||t?.source_description||t?.summary||`该内容由已保留的来源记录支持。`,v.value=n?.quadrant_reason||e.reasoningSummary||`该内容在发现时符合“${A(e.originQuadrant)}”:${B(e.originQuadrant)}`,E.value=n?.proposed_by??k(t),y.value=`已核对内容与发现时象限,确认无误。`,C.value=!1,T.value=``},{immediate:!0});async function O(){let e=s.item;if(!(!e||w.value)){if(!e.classificationExplicit)return j(`请先补充发现时象限,再确认这条知识`);if(!g.value.trim())return j(`请说明为什么会有这条知识`);if(!v.value.trim())return j(`请说明为什么属于当前象限`);if(!y.value.trim())return j(`请填写确认说明`);if(!C.value)return j(`请先确认已经核对内容与发现时象限`);w.value=!0,T.value=``;try{await d(`/api/knowledge/${e.itemKind}/${encodeURIComponent(e.id)}`,{personalSpaceId:s.personalSpaceId,personalProjectId:s.personalProjectId,action:`confirm`,reason:y.value.trim(),confirmationStatus:`confirmed`,confirmationBasis:{existenceReason:g.value.trim(),quadrantReason:v.value.trim(),proposedBy:E.value,confirmedBy:{kind:`user`,label:`当前用户`},confirmedAt:new Date().toISOString()}}),l.notify(`${D.value}已确认,并记录了确认人和确认时间。`),c(`saved`),c(`close`)}catch(e){T.value=e instanceof Error?e.message:`确认失败`,l.reportError(e)}finally{w.value=!1}}}function k(e){let t={codex:`Codex`,claude_code:`Claude Code`,cursor:`Cursor`,kiro:`Kiro`,other:`其他 Agent`}[e?.source_application??``];return t?{kind:`agent`,label:t}:{kind:`import`,label:`历史记录`}}function j(e){T.value=e}return(e,i)=>t.item?(o(),f(`dialog`,U,[u(`form`,{class:`knowledge-confirm-dialog-shell`,onSubmit:S(O,[`prevent`])},[u(`header`,W,[u(`div`,null,[i[6]||=u(`p`,{class:`eyebrow`},`KNOWLEDGE CONFIRMATION`,-1),u(`h3`,null,`确认`+p(D.value),1),i[7]||=u(`p`,null,`确认表示你已核对内容与发现时象限;系统会记录当前用户和确认时间。`,-1)]),u(`button`,{class:`secondary-action`,type:`button`,disabled:w.value,onClick:i[0]||=e=>c(`close`)},` 关闭 `,8,G)]),u(`section`,K,[u(`span`,null,p(t.item.profileAspect?`协作偏好`:`知识内容`),1),u(`strong`,null,p(t.item.title),1),u(`p`,null,p(t.item.body),1),u(`small`,null,`发现时象限 · `+p(n(A)(t.item.originQuadrant)),1)]),u(`div`,q,[u(`label`,null,[i[8]||=u(`span`,null,`为什么会有这条知识`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[1]||=e=>g.value=e,name:`confirmation-existence-reason`,maxlength:`4096`,rows:`3`,required:``},null,512),[[b,g.value]])]),u(`label`,null,[i[9]||=u(`span`,null,`为什么属于当前象限`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[2]||=e=>v.value=e,name:`confirmation-quadrant-reason`,maxlength:`4096`,rows:`3`,required:``},null,512),[[b,v.value]])]),u(`label`,null,[i[10]||=u(`span`,null,`确认说明`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[3]||=e=>y.value=e,name:`confirmation-reason`,maxlength:`2000`,rows:`2`,required:``},null,512),[[b,y.value]])])]),u(`label`,J,[r(u(`input`,{"onUpdate:modelValue":i[4]||=e=>C.value=e,name:`confirmation-acknowledged`,type:`checkbox`},null,512),[[x,C.value]]),i[11]||=u(`span`,null,`我已核对这条内容及其发现时象限,并确认上述依据准确。`,-1)]),T.value?(o(),f(`p`,Y,p(T.value),1)):m(``,!0),u(`footer`,X,[u(`button`,{class:`secondary-action`,type:`button`,disabled:w.value,onClick:i[5]||=e=>c(`close`)},` 取消 `,8,ee),u(`button`,{class:`primary-action`,type:`submit`,disabled:w.value||!C.value},p(w.value?`正在确认…`:`确认${D.value}`),9,te)])],32)])):m(``,!0)}}),[[`__scopeId`,`data-v-65eb248e`]]),re={key:0,open:``,class:`project-dialog knowledge-edit-dialog vue-dialog`},ie={class:`project-dialog-shell`},ae={class:`project-dialog-header`},oe={class:`knowledge-edit-columns`},se={key:0},ce={key:1},le={key:2},ue={class:`knowledge-taxonomy-fields`},de={class:`knowledge-classification-warning`},fe={key:3,class:`knowledge-classification-warning`},pe={class:`knowledge-confirmation-fields`},me={class:`knowledge-taxonomy-fields`},he={key:4,class:`knowledge-replacement-fields`},ge={key:0},_e={class:`knowledge-replacement-fields`},ve={key:5,class:`publish-dialog-error`,role:`alert`},ye={class:`knowledge-editor-actions`},be=[`disabled`],xe=[`disabled`],Se=[`disabled`],Ce=[`disabled`],we={key:0},Te=[`disabled`],Ee={key:1},De={key:0},Oe=[`disabled`],ke=y({__name:`KnowledgeEditDialog`,props:{item:{},personalSpaceId:{},personalProjectId:{},projects:{},replacementItems:{default:()=>[]}},emits:[`close`,`saved`],setup(t,{emit:g}){let y=t,x=g,E=h(),D=a(!1),O=a(``),k=a(``),j=a(``),M=a(`global`),N=a(``),P=a(``),F=a(``),I=a(``),L=i({name:``,summary:``,fact:``,currentQuadrant:``,confirmationStatus:`pending`,existenceReason:``,quadrantReason:``,proposedByKind:`agent`,proposedByLabel:``,confirmedByKind:`user`,confirmedByLabel:``,profileAspect:`none`,inheritanceMode:`local_only`,reason:``}),R=_(()=>y.item?.itemKind===`relationship`),z=_(()=>!!y.item?.invalidAt),B=_(()=>!!y.item?.raw.profile_aspect),V=_(()=>y.projects.map(e=>({value:e.project_id,label:e.profile.name,meta:`#${T(e.project_id,26)}`,search:C(e.project_id)}))),H=[{value:`known_known`,label:`已知的已知 · 被明确表达的知识或结论`},{value:`known_unknown`,label:`已知的未知 · 被明确提出的未解问题`},{value:`unknown_known`,label:`未知的已知 · 从行为或反馈提炼的隐性知识`},{value:`unknown_unknown`,label:`未知的未知 · 探索中发现的潜在盲点`}],U=[{value:`pending`,label:`待确认 · 尚未完成内容与象限审核`},{value:`confirmed`,label:`已确认 · 内容与象限归类均已确认`}],W=[{value:`local_only`,label:`仅当前项目 · 不自动借给其他项目`},{value:`descendants`,label:`子项目可继承 · 仅沿明确知识关系`},{value:`selected_projects`,label:`仅指定项目可继承`}],G=[{value:`user`,label:`用户`},{value:`agent`,label:`Agent`},{value:`authoritative_source`,label:`权威来源`},{value:`import`,label:`导入记录`}],K=[{value:`user`,label:`用户`},{value:`authoritative_source`,label:`权威来源`}],q=[{value:`none`,label:`不属于协作偏好`},{value:`taste`,label:`品味`},{value:`personality`,label:`个性`},{value:`judgment_preference`,label:`判断偏好`}],J=_(()=>[{value:`global`,label:`个人全局`},{value:`project`,label:`指定个人项目`,disabled:y.projects.length===0}]),Y=_(()=>[{value:``,label:`没有明确的替代内容`},...y.replacementItems.filter(e=>!e.invalidAt&&(e.itemKind!==y.item?.itemKind||e.id!==y.item?.id)).map(e=>({value:Me(e.itemKind,e.id),label:e.title,meta:e.type,search:`${e.body} ${e.id}`}))]),X=_(()=>{if(!I.value)return null;try{let[e,t]=JSON.parse(I.value);return e!==`entity`&&e!==`relationship`||typeof t!=`string`?null:{itemKind:e,id:t}}catch{return null}}),ee=_(()=>y.item?.assignments.at(0)?.project_id??y.item?.evidence.find(({personal_project_id:e})=>e)?.personal_project_id??y.personalProjectId??null);e(()=>y.item,e=>{if(!e)return;let t=e.raw;L.name=e.itemKind===`entity`?t.name:``,L.summary=e.itemKind===`entity`?t.summary??``:``,L.fact=e.itemKind===`relationship`?t.fact??``:``;let n=e.confirmationBasis,r=e.evidence.at(0);L.currentQuadrant=e.classificationExplicit?t.current_quadrant??t.origin_quadrant??`known_known`:``,L.confirmationStatus=e.confirmationStatus===`confirmed`?`confirmed`:`pending`,L.existenceReason=n?.existence_reason??r?.source_description??r?.summary??``,L.quadrantReason=n?.quadrant_reason??t.reasoning_summary??``,L.proposedByKind=n?.proposed_by.kind??`agent`,L.proposedByLabel=n?.proposed_by.label??``,L.confirmedByKind=n?.confirmed_by?.kind??`user`,L.confirmedByLabel=n?.confirmed_by?.label??``,L.profileAspect=t.profile_aspect??`none`,L.inheritanceMode=t.profile_aspect?`local_only`:t.inheritance_mode??`local_only`,F.value=t.inherited_project_ids?.at(0)??y.projects[0]?.project_id??``,L.reason=``,k.value=``,j.value=ee.value??y.projects[0]?.project_id??``,M.value=t.preference_scope??`global`,N.value=t.preference_project_id??y.projects[0]?.project_id??``,P.value=``,I.value=e.replacedByItemId&&e.replacedByItemKind?Me(e.replacedByItemKind,e.replacedByItemId):``,O.value=``},{immediate:!0});async function te(){let e=y.item;if(!e)return;if(!L.reason.trim())return $(`请说明纠正原因`);if(!R.value&&!L.name.trim())return $(`名称不能为空`);if(R.value&&!L.fact.trim())return $(`关系事实不能为空`);if(!L.currentQuadrant||!L.confirmationStatus)return $(`请先明确当前分类与确认状态`);if(!L.existenceReason.trim())return $(`请说明为什么会有这条知识`);if(!L.quadrantReason.trim())return $(`请说明为什么被分到这个象限`);if(!L.proposedByKind)return $(`请选择提出者`);if(L.confirmationStatus===`confirmed`&&!L.confirmedByKind)return $(`已确认状态必须记录确认者`);if(L.inheritanceMode===`selected_projects`&&!F.value)return $(`请选择可以继承这条知识的项目`);let t={...Z(`update`),confirmationStatus:L.confirmationStatus,confirmationBasis:{existenceReason:L.existenceReason.trim(),quadrantReason:L.quadrantReason.trim(),proposedBy:{kind:L.proposedByKind,label:L.proposedByLabel.trim()||null},confirmedBy:L.confirmationStatus===`confirmed`?{kind:L.confirmedByKind,label:L.confirmedByLabel.trim()||null}:null,confirmedAt:L.confirmationStatus===`confirmed`?new Date().toISOString():null},profileAspect:L.profileAspect,inheritanceMode:L.profileAspect===`none`?L.inheritanceMode:`local_only`,inheritedProjectIds:L.profileAspect===`none`&&L.inheritanceMode===`selected_projects`?[F.value]:[],reasoningSummary:L.quadrantReason.trim()};y.item.classificationExplicit?t.currentQuadrant=L.currentQuadrant:t.originQuadrant=L.currentQuadrant,R.value?t.fact=L.fact.trim():(t.name=L.name.trim(),t.summary=L.summary.trim()),await Q(async()=>{await d(`/api/knowledge/${e.itemKind}/${encodeURIComponent(e.id)}`,t),E.notify(`知识已纠正,原始证据仍然保留。`)})}async function ne(e){let t=y.item;if(t){if(!L.reason.trim())return $(e===`invalidate`?`请说明为什么这条知识已经失效`:`请说明为什么恢复有效`);await Q(async()=>{let n=Z(e);e===`invalidate`&&X.value&&(n.replacementItemId=X.value.id,n.replacementItemKind=X.value.itemKind),await d(`/api/knowledge/${t.itemKind}/${encodeURIComponent(t.id)}`,n),E.notify(e===`invalidate`?X.value?`知识已标记为失效,并已关联替代内容。`:`知识已标记为失效,历史记录已保留。`:`知识已恢复为有效。`)})}}async function ke(){let e=y.item,t=X.value;if(!(!e||!z.value)){if(!t)return $(`请选择明确的替代内容`);if(!L.reason.trim())return $(`请说明补充替代关联的依据`);await Q(async()=>{await d(`/api/knowledge/${e.itemKind}/${encodeURIComponent(e.id)}`,{...Z(`link_replacement`),replacementItemId:t.id,replacementItemKind:t.itemKind}),E.notify(`替代关联已保存,现在可以从历史记录直接跳转。`)})}}async function Ae(){let e=y.item;if(e){if(!j.value)return $(`请选择目标个人项目`);if(!k.value.trim())return $(`请说明调整原因`);if(j.value===ee.value)return $(`这条知识已经属于该项目`);await Q(async()=>{await c(`/api/knowledge/${e.itemKind}/${encodeURIComponent(e.id)}/assignment`,{personalSpaceId:y.personalSpaceId,targetProjectId:j.value,reason:k.value.trim()}),E.notify(`项目归属已调整,来源会话和历史证据没有改变。`)})}}async function je(){let e=y.item;if(!e)return;let t=M.value===`project`?N.value:null;if(M.value===`project`&&!t)return $(`请选择生效的个人项目`);if(!P.value.trim())return $(`请说明为什么调整生效范围`);await Q(async()=>{await c(`/api/knowledge/${e.itemKind}/${encodeURIComponent(e.id)}/preference-scope`,{personalSpaceId:y.personalSpaceId,scope:M.value,projectId:t,reason:P.value.trim()}),E.notify(M.value===`global`?`这条协作偏好现在对所有个人项目生效。`:`这条协作偏好现在只对所选个人项目生效。`)})}function Z(e){return{personalSpaceId:y.personalSpaceId,personalProjectId:y.personalProjectId,action:e,reason:L.reason.trim()}}function Me(e,t){return JSON.stringify([e,t])}async function Q(e){D.value=!0,O.value=``;try{await e(),x(`close`),x(`saved`)}catch(e){O.value=e instanceof Error?e.message:`保存失败`,E.reportError(e)}finally{D.value=!1}}function $(e){O.value=e}return(e,i)=>t.item?(o(),f(`dialog`,re,[u(`div`,ie,[u(`header`,ae,[u(`div`,null,[i[24]||=u(`p`,{class:`eyebrow`},`PERSONAL KNOWLEDGE`,-1),u(`h3`,null,p(z.value?`查看和恢复知识`:`纠正知识`),1),i[25]||=u(`p`,null,`修改会新增修订历史;发现时象限保持不变,当前分类可纠正,确认状态记录审核结果。`,-1)]),u(`button`,{class:`secondary-action`,type:`button`,onClick:i[0]||=e=>x(`close`)},`关闭`)]),u(`div`,oe,[u(`section`,null,[i[46]||=u(`h4`,null,`当前内容`,-1),u(`form`,{class:`knowledge-editor-form`,onSubmit:S(te,[`prevent`])},[R.value?m(``,!0):(o(),f(`label`,se,[i[26]||=s(`名称`,-1),r(u(`input`,{"onUpdate:modelValue":i[1]||=e=>L.name=e,maxlength:`512`},null,512),[[b,L.name]])])),R.value?(o(),f(`label`,le,[i[28]||=s(`关系事实`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[3]||=e=>L.fact=e,maxlength:`8192`,rows:`5`},null,512),[[b,L.fact]])])):(o(),f(`label`,ce,[i[27]||=s(`说明`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[2]||=e=>L.summary=e,maxlength:`4096`,rows:`5`},null,512),[[b,L.summary]])])),u(`div`,ue,[u(`label`,null,[i[29]||=s(`当前分类 `,-1),v(w,{modelValue:L.currentQuadrant,"onUpdate:modelValue":i[4]||=e=>L.currentQuadrant=e,options:H,label:`当前分类`},null,8,[`modelValue`])]),u(`label`,null,[i[30]||=s(`确认状态 `,-1),v(w,{modelValue:L.confirmationStatus,"onUpdate:modelValue":i[5]||=e=>L.confirmationStatus=e,options:U,label:`确认状态`},null,8,[`modelValue`])]),u(`label`,null,[i[31]||=s(`协作偏好维度 `,-1),v(w,{modelValue:L.profileAspect,"onUpdate:modelValue":i[6]||=e=>L.profileAspect=e,options:q,label:`协作偏好维度`},null,8,[`modelValue`])])]),u(`p`,de,` 发现时象限:`+p(n(A)(t.item.originQuadrant))+`。这是捕获来源标签,后续编辑不会覆盖。 `,1),t.item.classificationExplicit?m(``,!0):(o(),f(`p`,fe,` 这条旧内容没有显式象限。保存前请人工选择,系统不会再自动补成“已知的已知”。 `)),u(`fieldset`,pe,[i[38]||=u(`legend`,null,`确认依据`,-1),u(`label`,null,[i[32]||=s(`为什么会有这条知识 `,-1),r(u(`textarea`,{"onUpdate:modelValue":i[7]||=e=>L.existenceReason=e,maxlength:`4096`,rows:`3`,required:``},null,512),[[b,L.existenceReason]])]),u(`label`,null,[i[33]||=s(`为什么被分到这个象限 `,-1),r(u(`textarea`,{"onUpdate:modelValue":i[8]||=e=>L.quadrantReason=e,maxlength:`4096`,rows:`3`,required:``},null,512),[[b,L.quadrantReason]])]),u(`div`,me,[u(`label`,null,[i[34]||=s(`提出者 `,-1),v(w,{modelValue:L.proposedByKind,"onUpdate:modelValue":i[9]||=e=>L.proposedByKind=e,options:G,label:`提出者`},null,8,[`modelValue`])]),u(`label`,null,[i[35]||=s(`提出者说明 `,-1),r(u(`input`,{"onUpdate:modelValue":i[10]||=e=>L.proposedByLabel=e,maxlength:`160`,placeholder:`可选,例如 Codex`},null,512),[[b,L.proposedByLabel]])]),L.confirmationStatus===`confirmed`?(o(),f(l,{key:0},[u(`label`,null,[i[36]||=s(`确认者 `,-1),v(w,{modelValue:L.confirmedByKind,"onUpdate:modelValue":i[11]||=e=>L.confirmedByKind=e,options:K,label:`确认者`},null,8,[`modelValue`])]),u(`label`,null,[i[37]||=s(`确认者说明 `,-1),r(u(`input`,{"onUpdate:modelValue":i[12]||=e=>L.confirmedByLabel=e,maxlength:`160`,placeholder:`可选,例如当前用户`},null,512),[[b,L.confirmedByLabel]])])],64)):m(``,!0)]),i[39]||=u(`p`,null,` “Agent 已确认”只能由实际使用证据策略产生;人工在这里可保留待确认,或记录用户/权威来源确认。 `,-1)]),B.value?m(``,!0):(o(),f(`fieldset`,he,[i[42]||=u(`legend`,null,`跨项目知识继承`,-1),u(`label`,null,[i[40]||=s(`继承范围 `,-1),v(w,{modelValue:L.inheritanceMode,"onUpdate:modelValue":i[13]||=e=>L.inheritanceMode=e,options:W,label:`知识继承范围`},null,8,[`modelValue`])]),L.inheritanceMode===`selected_projects`?(o(),f(`label`,ge,[i[41]||=s(`可继承项目 `,-1),v(w,{modelValue:F.value,"onUpdate:modelValue":i[14]||=e=>F.value=e,options:V.value,label:`可继承项目`,searchable:``},null,8,[`modelValue`,`options`])])):m(``,!0),i[43]||=u(`p`,null,` 只有沿 PART_OF 或 USES_KNOWLEDGE_FROM 可达时才会继承;RELATED_TO 不扩展检索范围。 `,-1)])),u(`fieldset`,_e,[u(`legend`,null,p(z.value?`替代内容`:`失效时的替代内容(可选)`),1),u(`label`,null,[s(p(z.value?`这条历史记录被哪条内容取代`:`选择当前有效的内容`)+` `,1),v(w,{modelValue:I.value,"onUpdate:modelValue":i[15]||=e=>I.value=e,options:Y.value,label:`替代内容`,searchable:``},null,8,[`modelValue`,`options`])]),i[44]||=u(`p`,null,` 只有明确选择后才会建立可跳转的替代关联;系统不会根据失效原因自动猜测。 `,-1)]),u(`label`,null,[i[45]||=s(`纠正原因`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[16]||=e=>L.reason=e,maxlength:`2000`,rows:`3`,required:``},null,512),[[b,L.reason]])]),O.value?(o(),f(`p`,ve,p(O.value),1)):m(``,!0),u(`div`,ye,[z.value?(o(),f(l,{key:1},[u(`button`,{class:`secondary-action`,type:`button`,disabled:D.value,onClick:i[18]||=e=>ne(`restore`)},`恢复为有效`,8,xe),u(`button`,{class:`secondary-action`,type:`button`,disabled:D.value,onClick:ke},`保存替代关联`,8,Se)],64)):(o(),f(`button`,{key:0,class:`secondary-action`,type:`button`,disabled:D.value,onClick:i[17]||=e=>ne(`invalidate`)},`标记为失效`,8,be)),u(`button`,{class:`primary-action`,type:`submit`,disabled:D.value},p(D.value?`正在保存…`:L.confirmationStatus===`confirmed`?`保存并确认`:`保存为待确认`),9,Ce)])],32)]),B.value?(o(),f(`section`,Ee,[i[54]||=u(`h4`,null,`偏好生效范围`,-1),i[55]||=u(`p`,null,`个人全局默认跨项目生效;项目范围只对明确选择的项目生效。`,-1),u(`form`,{class:`knowledge-editor-form`,onSubmit:S(je,[`prevent`])},[u(`label`,null,[i[51]||=s(`生效范围 `,-1),v(w,{modelValue:M.value,"onUpdate:modelValue":i[21]||=e=>M.value=e,options:J.value,label:`偏好生效范围`},null,8,[`modelValue`,`options`])]),M.value===`project`?(o(),f(`label`,De,[i[52]||=s(`个人项目 `,-1),v(w,{modelValue:N.value,"onUpdate:modelValue":i[22]||=e=>N.value=e,options:V.value,label:`偏好个人项目`,searchable:``},null,8,[`modelValue`,`options`])])):m(``,!0),u(`label`,null,[i[53]||=s(`调整原因`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[23]||=e=>P.value=e,maxlength:`2000`,rows:`3`,required:``},null,512),[[b,P.value]])]),u(`button`,{class:`primary-action`,type:`submit`,disabled:D.value},`保存生效范围`,8,Oe)],32)])):(o(),f(`section`,we,[i[49]||=u(`h4`,null,`项目归属`,-1),i[50]||=u(`p`,null,`只调整这条知识的项目归属,来源会话和历史证据保持不变。`,-1),u(`form`,{class:`knowledge-editor-form`,onSubmit:S(Ae,[`prevent`])},[u(`label`,null,[i[47]||=s(`目标个人项目 `,-1),v(w,{modelValue:j.value,"onUpdate:modelValue":i[19]||=e=>j.value=e,options:V.value,label:`目标个人项目`,searchable:``,required:``},null,8,[`modelValue`,`options`])]),u(`label`,null,[i[48]||=s(`调整原因`,-1),r(u(`textarea`,{"onUpdate:modelValue":i[20]||=e=>k.value=e,maxlength:`2000`,rows:`3`,required:``},null,512),[[b,k.value]])]),u(`button`,{class:`primary-action`,type:`submit`,disabled:D.value||t.projects.length===0},`调整归属`,8,Te)],32)]))])])])):m(``,!0)}}),Ae={class:`graph-inspector`},je={class:`eyebrow`},Z={class:`inspector-identity`},Me={class:`muted`},Q={key:0,class:`inspector-project-material`},$={key:3,class:`inspector-replacement`},Ne={class:`inspector-replacement-heading`},Pe={key:1},Fe={key:2},Ie={class:`inspector-meta`},Le={key:0},Re={key:1},ze={key:2},Be={key:3},Ve={key:4},He={key:5},Ue={key:6},We={key:7},Ge={key:8},Ke={key:9},qe={key:10},Je={key:12},Ye={key:0,class:`inspector-meta inspector-confirmation-basis`},Xe={key:0},Ze={key:1,class:`inspector-reasoning`},Qe={class:`inspector-meta inspector-attributes`},$e={class:`inspector-reasoning`},et={key:7,class:`inspector-actions`},tt={class:`inspector-relations`},nt={class:`relation-type`},rt={class:`relation-target`},it={class:`inspector-evidence`},at={key:0,class:`evidence-excerpt`},ot={class:`inspector-history`},st={class:`inspector-history inspector-audit-history`},ct={key:0},lt=y({__name:`KnowledgeInspector`,props:{item:{},graph:{},editable:{type:Boolean},currentProjectId:{},canPublishProject:{type:Boolean},canManageProject:{type:Boolean},mode:{}},emits:[`confirm`,`edit`,`createProject`,`openProject`,`publishProject`,`openDirectory`,`openGraph`,`openReplacement`,`manageProject`],setup(e,{emit:r}){let i=e,a=r,s=_(()=>i.item?.itemKind===`entity`?i.item.raw:null),c=_(()=>i.item?.itemKind===`relationship`?i.item.raw:null),d=_(()=>new Map(i.graph?.nodes.map(e=>[e.id,e.name])??[])),h=_(()=>!s.value||!i.graph?[]:i.graph.edges.filter(e=>R(e.source)===s.value?.id||R(e.target)===s.value?.id).slice(0,12)),v=_(()=>Object.entries(i.item?.raw.attributes??{}).filter(([,e])=>e!=null&&e!==``)),y=_(()=>j(i.item)),b=_(()=>V(i.item)),x=_(()=>i.item?.itemKind===`entity`&&[`PersonalProject`,`RelatedPersonalProject`].includes(i.item.type)),S=_(()=>i.editable&&i.item?.itemKind===`entity`&&!i.item.invalidAt&&!i.item.profileAspect&&!y.value),C=_(()=>i.editable&&!y.value),w=_(()=>i.editable&&!y.value&&!i.item?.invalidAt&&!!i.item?.classificationExplicit&&U.value===`pending`),T=_(()=>y.value&&i.canManageProject),H=_(()=>S.value||C.value||w.value||T.value||!!i.mode||x.value&&!!b.value&&b.value!==i.currentProjectId||x.value&&!!b.value&&i.canPublishProject),U=_(()=>i.item?N(i.item):`unclassified`),W=_(()=>i.item?L(i.item):``),G=_(()=>i.item?.confirmationBasis??null),K=_(()=>{let e=i.item?.replacedByItemId,t=i.item?.replacedByItemKind;return!e||!t?null:P(i.graph).find(n=>n.id===e&&n.itemKind===t)??null}),q=_(()=>{let e=i.item;return e?.humanEdited?e.humanChangeStatus===`unseen`?`这次人工修改还没有被 Agent 调用查看,提醒会持续保留。`:e.humanChangeStatus===`viewed`?`Agent 已查看当前版本,但还没有同时完成冲突检查和分类合理性审核。`:`Agent 已对当前人工修改版本完成无冲突与分类合理性审核;历史记录仍永久保留。`:``});function J(e){return typeof e==`string`?e:JSON.stringify(e)}function Y(e){return`${Math.round(e*100)}%`}function X(e){return e.inheritanceMode===`descendants`?`允许子项目继承`:e.inheritanceMode===`selected_projects`?`仅指定项目(${e.inheritedProjectIds.length})`:`仅当前项目`}return(r,i)=>(o(),f(`aside`,Ae,[e.item?(o(),f(l,{key:0},[u(`p`,je,p(y.value?`PROJECT MATERIAL`:e.item.itemKind===`entity`?`ENTITY`:`RELATIONSHIP`),1),u(`h3`,null,p(e.item.itemKind===`entity`?e.item.title:c.value?.type),1),u(`div`,Z,[u(`span`,null,p(y.value?`资料投影 ID`:e.item.itemKind===`entity`?`节点 ID`:`关系 ID`),1),u(`code`,null,p(e.item.id),1)]),u(`p`,Me,p(e.item.body),1),y.value?(o(),f(`section`,Q,[u(`div`,null,[i[9]||=u(`span`,null,`内容归属`,-1),u(`strong`,null,p(n(E)(e.item)),1)]),i[10]||=u(`p`,null,` 这是项目档案在关系图中的投影,不是可独立确认、失效或恢复的知识记录。 如需改变内容,请编辑项目资料。 `,-1)])):(o(),f(`section`,{key:1,class:g([`inspector-classification`,`state-${U.value}`])},[u(`div`,null,[i[11]||=u(`span`,null,`当前判定`,-1),u(`strong`,null,p(n(O)(e.item)),1)]),u(`p`,null,p(W.value),1)],2)),!y.value&&e.item.humanEdited?(o(),f(`section`,{key:2,class:g([`inspector-human-change`,`state-${e.item.humanChangeStatus}`])},[u(`div`,null,[i[12]||=u(`span`,null,`人工变更审核`,-1),u(`strong`,null,p(n(z)(e.item.humanChangeStatus)),1)]),u(`p`,null,p(q.value),1),u(`small`,null,`人工变更版本 `+p(e.item.humanChangeVersion),1)],2)):m(``,!0),!y.value&&e.item.invalidAt?(o(),f(`section`,$,[u(`div`,Ne,[i[13]||=u(`span`,null,`替代关系`,-1),u(`strong`,null,p(K.value?`已被以下内容取代`:`没有可跳转的替代内容`),1)]),K.value?(o(),f(`button`,{key:0,class:`inspector-replacement-link`,type:`button`,onClick:i[0]||=e=>a(`openReplacement`,K.value)},[u(`span`,null,[u(`strong`,null,p(K.value.title),1),u(`small`,null,p(K.value.body),1)]),i[14]||=u(`b`,null,`查看替代内容 →`,-1)])):e.item.replacedByItemId?(o(),f(`p`,Pe,` 已记录替代对象,但它不在当前查看范围内。 `)):(o(),f(`p`,Fe,` 这条历史记录只有失效原因,没有记录明确的替代对象;系统不会根据文字猜测链接。 `))])):m(``,!0),u(`dl`,Ie,[u(`div`,null,[i[15]||=u(`dt`,null,`类型`,-1),u(`dd`,null,p(e.item.type),1)]),y.value?m(``,!0):(o(),f(`div`,Le,[i[16]||=u(`dt`,null,`发现时象限`,-1),u(`dd`,null,p(n(A)(e.item.originQuadrant)),1)])),y.value?m(``,!0):(o(),f(`div`,Re,[i[17]||=u(`dt`,null,`当前分类`,-1),u(`dd`,null,p(n(A)(e.item.currentQuadrant)),1)])),y.value?m(``,!0):(o(),f(`div`,ze,[i[18]||=u(`dt`,null,`象限解释`,-1),u(`dd`,null,p(n(B)(e.item.originQuadrant)),1)])),y.value?m(``,!0):(o(),f(`div`,Be,[i[19]||=u(`dt`,null,`确认状态`,-1),u(`dd`,null,p(n(O)(e.item)),1)])),y.value?m(``,!0):(o(),f(`div`,Ve,[i[20]||=u(`dt`,null,`置信分`,-1),u(`dd`,null,p(Y(e.item.confidenceScore)),1)])),y.value?m(``,!0):(o(),f(`div`,He,[i[21]||=u(`dt`,null,`效用分`,-1),u(`dd`,null,p(Y(e.item.utilityScore)),1)])),y.value?m(``,!0):(o(),f(`div`,Ue,[i[22]||=u(`dt`,null,`有效使用`,-1),u(`dd`,null,p(e.item.qualifiedUseCount)+` 次 / `+p(e.item.distinctTaskCount)+` 个任务`,1)])),y.value?m(``,!0):(o(),f(`div`,We,[i[23]||=u(`dt`,null,`最近使用`,-1),u(`dd`,null,p(n(I)(e.item.lastUsedAt)),1)])),!y.value&&!e.item.profileAspect?(o(),f(`div`,Ge,[i[24]||=u(`dt`,null,`知识继承`,-1),u(`dd`,null,p(X(e.item)),1)])):m(``,!0),!y.value&&e.item.profileAspect?(o(),f(`div`,Ke,[i[25]||=u(`dt`,null,`协作偏好`,-1),u(`dd`,null,p(n(k)(e.item.profileAspect)),1)])):m(``,!0),!y.value&&e.item.profileAspect?(o(),f(`div`,qe,[i[26]||=u(`dt`,null,`生效范围`,-1),u(`dd`,null,p(e.item.preferenceScope===`project`?`指定项目`:`个人全局`),1)])):m(``,!0),c.value?(o(),f(l,{key:11},[u(`div`,null,[i[27]||=u(`dt`,null,`来源`,-1),u(`dd`,null,p(d.value.get(n(R)(c.value.source))??n(R)(c.value.source)),1)]),u(`div`,null,[i[28]||=u(`dt`,null,`目标`,-1),u(`dd`,null,p(d.value.get(n(R)(c.value.target))??n(R)(c.value.target)),1)])],64)):m(``,!0),y.value?m(``,!0):(o(),f(`div`,Je,[i[29]||=u(`dt`,null,`状态`,-1),u(`dd`,null,p(e.item.invalidAt?`历史 · 已失效`:`当前有效`),1)]))]),y.value?m(``,!0):(o(),f(l,{key:4},[i[36]||=u(`h4`,{class:`inspector-subtitle`},`确认依据`,-1),G.value?(o(),f(`dl`,Ye,[u(`div`,null,[i[30]||=u(`dt`,null,`为什么会有`,-1),u(`dd`,null,p(G.value.existence_reason),1)]),u(`div`,null,[i[31]||=u(`dt`,null,`为什么属于该象限`,-1),u(`dd`,null,p(G.value.quadrant_reason),1)]),u(`div`,null,[i[32]||=u(`dt`,null,`提出者`,-1),u(`dd`,null,p(n(F)(G.value.proposed_by)),1)]),u(`div`,null,[i[33]||=u(`dt`,null,`确认者`,-1),u(`dd`,null,p(n(F)(G.value.confirmed_by)),1)]),u(`div`,null,[i[34]||=u(`dt`,null,`确认时间`,-1),u(`dd`,null,p(n(I)(G.value.confirmed_at)),1)]),G.value.agent_policy_version?(o(),f(`div`,Xe,[i[35]||=u(`dt`,null,`Agent 策略`,-1),u(`dd`,null,p(G.value.agent_policy_version),1)])):m(``,!0)])):(o(),f(`p`,Ze,` 旧数据没有结构化的确认依据,因此已放入待确认,不会自动作为已确认知识使用。 `))],64)),v.value.length?(o(),f(l,{key:5},[i[37]||=u(`h4`,{class:`inspector-subtitle`},`内容详情`,-1),u(`dl`,Qe,[(o(!0),f(l,null,t(v.value,([e,t])=>(o(),f(`div`,{key:e},[u(`dt`,null,p(e),1),u(`dd`,null,p(J(t)),1)]))),128))])],64)):m(``,!0),e.item.reasoningSummary?(o(),f(l,{key:6},[i[38]||=u(`h4`,{class:`inspector-subtitle`},`形成过程`,-1),u(`p`,$e,p(e.item.reasoningSummary),1)],64)):m(``,!0),H.value?(o(),f(`div`,et,[w.value?(o(),f(`button`,{key:0,class:`primary-action inspector-confirm-action`,type:`button`,onClick:i[1]||=t=>a(`confirm`,e.item)},p(e.item.profileAspect?`确认这条偏好`:`确认这条知识`),1)):m(``,!0),T.value?(o(),f(`button`,{key:1,class:`primary-action`,type:`button`,onClick:i[2]||=t=>a(`manageProject`,e.item)},` 编辑项目资料 `)):m(``,!0),e.mode===`graph`?(o(),f(`button`,{key:2,class:`secondary-action`,type:`button`,onClick:i[3]||=t=>a(`openDirectory`,e.item)},` 在内容目录中定位 `)):m(``,!0),e.mode===`directory`?(o(),f(`button`,{key:3,class:`secondary-action`,type:`button`,onClick:i[4]||=t=>a(`openGraph`,e.item)},` 在关系图中定位 `)):m(``,!0),x.value&&b.value&&b.value!==e.currentProjectId?(o(),f(`button`,{key:4,class:`primary-action`,type:`button`,onClick:i[5]||=e=>a(`openProject`,b.value)},` 进入这个项目 `)):m(``,!0),x.value&&b.value&&e.canPublishProject?(o(),f(`button`,{key:5,class:`secondary-action`,type:`button`,onClick:i[6]||=e=>a(`publishProject`,b.value)},` 发布 / 同步到公共 `)):m(``,!0),S.value?(o(),f(`button`,{key:6,class:`primary-action`,type:`button`,onClick:i[7]||=t=>a(`createProject`,e.item)},` 基于此创建项目 `)):m(``,!0),C.value?(o(),f(`button`,{key:7,class:`secondary-action inspector-edit-action`,type:`button`,onClick:i[8]||=t=>a(`edit`,e.item)},p(e.item.profileAspect?`纠正这条偏好`:`纠正或调整归属`),1)):m(``,!0)])):m(``,!0),h.value.length?(o(),f(l,{key:8},[i[39]||=u(`h4`,{class:`inspector-subtitle`},`关联关系`,-1),u(`div`,tt,[(o(!0),f(l,null,t(h.value,e=>(o(),f(`div`,{key:e.id,class:`inspector-relation`},[u(`strong`,nt,p(e.type),1),u(`p`,rt,p(e.fact||`关系`),1)]))),128))])],64)):m(``,!0),e.item.evidence.length?(o(),f(l,{key:9},[i[40]||=u(`h4`,{class:`inspector-subtitle`},`证据与来源`,-1),u(`div`,it,[(o(!0),f(l,null,t(e.item.evidence,(e,t)=>(o(),f(`article`,{key:String(e.id??t),class:`evidence-card`},[u(`strong`,null,p(e.name||e.source_description||`来源记录`),1),u(`p`,null,p(e.summary||e.source_description),1),u(`span`,null,p(e.source_kind||`来源`)+` · `+p(n(I)(e.reference_time||e.created_at)),1),e.source_excerpt?(o(),f(`p`,at,p(e.source_excerpt),1)):m(``,!0)]))),128))])],64)):m(``,!0),e.item.revisions.length?(o(),f(l,{key:10},[i[41]||=u(`h4`,{class:`inspector-subtitle`},`修订历史`,-1),u(`div`,ot,[(o(!0),f(l,null,t(e.item.revisions,(e,t)=>(o(),f(`article`,{key:String(e.id??t),class:`history-row`},[u(`strong`,null,p(n(D)(e.action)),1),u(`p`,null,p(e.reason??e.summary??`未填写说明`),1),u(`span`,null,p(n(I)(e.created_at)),1)]))),128))])],64)):m(``,!0),e.item.auditEvents.length?(o(),f(l,{key:11},[i[42]||=u(`h4`,{class:`inspector-subtitle`},`人工与 Agent 记录`,-1),u(`div`,st,[(o(!0),f(l,null,t(e.item.auditEvents,e=>(o(),f(`article`,{key:e.id,class:`history-row`},[u(`strong`,null,p(n(M)(e.action)),1),u(`p`,null,p(e.reason),1),u(`span`,null,` 版本 `+p(e.human_change_version)+` · `+p(n(I)(e.created_at)),1),e.action===`agent_review`?(o(),f(`small`,ct,` 冲突:`+p(e.conflict_check===`no_conflict`?`无冲突`:`有冲突`)+` · 分类:`+p(e.classification_check===`reasonable`?`合理`:`需调整`),1)):m(``,!0)]))),128))])],64)):m(``,!0)],64)):(o(),f(l,{key:1},[i[43]||=u(`p`,{class:`eyebrow`},`内容详情`,-1),i[44]||=u(`h3`,null,`选择一个节点或关系`,-1),i[45]||=u(`p`,{class:`inspector-placeholder`},`点击后查看完整说明、来源证据和关联关系。`,-1)],64))]))}});export{H as i,ke as n,ne as r,lt as t};
@@ -0,0 +1 @@
1
+ .knowledge-confirm-dialog[data-v-65eb248e]{width:min(680px,100vw - 48px)}.knowledge-confirm-dialog-shell[data-v-65eb248e]{gap:18px;padding:24px;display:grid}.knowledge-confirm-summary[data-v-65eb248e]{border-top:1px solid #e1e5e2;border-bottom:1px solid #e1e5e2;gap:6px;padding:14px 0;display:grid}.knowledge-confirm-summary span[data-v-65eb248e],.knowledge-confirm-summary small[data-v-65eb248e]{color:#7d8780;font-size:10px}.knowledge-confirm-summary strong[data-v-65eb248e]{color:#29382f;font-size:16px}.knowledge-confirm-summary p[data-v-65eb248e]{color:#606b63;font-size:12px;line-height:1.65}.knowledge-confirm-fields[data-v-65eb248e]{gap:14px;display:grid}.knowledge-confirm-fields label[data-v-65eb248e]{color:#59645c;gap:6px;font-size:11px;font-weight:600;display:grid}.knowledge-confirm-acknowledgement[data-v-65eb248e]{color:#4e5c53;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:9px;font-size:11px;line-height:1.5;display:grid}
@@ -0,0 +1 @@
1
+ .batch-confirm-dialog[data-v-f18528e4]{width:min(980px,100vw - 64px)}.batch-confirm-form[data-v-f18528e4]{grid-template-columns:320px minmax(0,1fr);gap:24px;padding-top:20px;display:grid}.batch-confirm-controls[data-v-f18528e4]{align-content:start;gap:14px;display:grid}.batch-confirm-controls>label[data-v-f18528e4],.batch-confirmer-fields label[data-v-f18528e4]{color:#5f6962;gap:6px;font-size:10px;font-weight:600;display:grid}.batch-confirm-controls[data-v-f18528e4] .searchable-select{width:100%}.batch-group-summary[data-v-f18528e4]{border-top:1px solid #e1e5e2;border-bottom:1px solid #e1e5e2;gap:4px;padding:12px 0;display:grid}.batch-group-summary span[data-v-f18528e4],.batch-group-summary small[data-v-f18528e4]{color:#89918b;font-size:8px}.batch-group-summary strong[data-v-f18528e4]{color:#35443b;font-size:12px}.batch-group-summary p[data-v-f18528e4]{color:#6e7871;font-size:9px;line-height:1.5}.batch-confirmer-fields[data-v-f18528e4]{grid-template-columns:112px minmax(0,1fr);gap:8px;display:grid}.batch-confirm-rule[data-v-f18528e4],.batch-limit-note[data-v-f18528e4]{color:#7c857f;font-size:9px;line-height:1.5}.batch-confirm-review[data-v-f18528e4]{border-left:1px solid #e1e5e2;min-width:0;padding-left:24px}.batch-review-heading[data-v-f18528e4]{justify-content:space-between;align-items:center;gap:16px;padding-bottom:10px;display:flex}.batch-review-heading h4[data-v-f18528e4]{color:#344239;font-size:13px}.batch-review-heading p[data-v-f18528e4]{color:#858e87;margin-top:2px;font-size:9px}.batch-review-list[data-v-f18528e4]{border-top:1px solid #e3e6e3;border-bottom:1px solid #e3e6e3;max-height:410px;overflow:auto}.batch-review-item[data-v-f18528e4]{cursor:pointer;border-bottom:1px solid #eceeec;grid-template-columns:auto minmax(0,1fr);gap:9px;padding:10px 2px;display:grid}.batch-review-item[data-v-f18528e4]:last-child{border-bottom:0}.batch-review-item>input[data-v-f18528e4]{margin-top:2px}.batch-review-item>span[data-v-f18528e4]{gap:3px;min-width:0;display:grid}.batch-review-item strong[data-v-f18528e4]{color:#3a4740;font-size:10px}.batch-review-item small[data-v-f18528e4]{color:#77817a;font-size:8px}.batch-review-item em[data-v-f18528e4]{color:#848d87;text-overflow:ellipsis;white-space:nowrap;font-size:8px;font-style:normal;line-height:1.4;overflow:hidden}.batch-confirm-acknowledgement[data-v-f18528e4]{color:#4f5d55;cursor:pointer;align-items:flex-start;gap:8px;margin-top:12px;font-size:9px;line-height:1.5;display:flex}.batch-confirm-form>.publish-dialog-error[data-v-f18528e4],.batch-confirm-form>.publish-dialog-actions[data-v-f18528e4]{grid-column:1/-1}@media (width<=820px){.batch-confirm-form[data-v-f18528e4]{grid-template-columns:1fr}.batch-confirm-review[data-v-f18528e4]{border-left:0;padding:0}}.knowledge-organizer[data-v-90794584]{flex-direction:column;gap:12px;padding:18px 24px 20px;display:flex;overflow:hidden}.organizer-head[data-v-90794584]{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px 24px;min-width:0;display:grid}.organizer-principle[data-v-90794584]{align-self:center;min-width:0;padding:0 2px}.organizer-principle h3[data-v-90794584]{font-size:16px}.organizer-principle>p[data-v-90794584]:last-child{color:#6e7771;max-width:760px;margin-top:5px;font-size:11px;line-height:1.55}.organizer-attention[data-v-90794584]{text-align:right;border-left:1px solid #dde2de;grid-area:1/2;min-width:152px;padding-left:20px}.organizer-attention strong[data-v-90794584],.organizer-attention span[data-v-90794584],.organizer-attention small[data-v-90794584]{display:block}.organizer-attention strong[data-v-90794584]{color:#6f582b;font-size:23px;font-weight:620}.organizer-attention span[data-v-90794584]{color:#5f675f;font-size:10px;font-weight:650}.organizer-attention small[data-v-90794584]{color:#8a918b;margin-top:2px;font-size:8px}.organizer-loading-inline[data-v-90794584]{color:#7b847e;text-align:center;font-size:10px}.organizer-toolbar[data-v-90794584]{align-items:center;gap:8px;min-height:34px;display:flex}.organizer-search[data-v-90794584]{flex:300px;min-width:180px;max-width:360px}.organizer-search>span[data-v-90794584]{clip:rect(0 0 0 0);width:1px;height:1px;position:absolute;overflow:hidden}.organizer-search input[data-v-90794584]{width:100%}.review-state-filter[data-v-90794584],.quadrant-filter[data-v-90794584]{white-space:nowrap;background:#f1f4f1;border:1px solid #d7ddd8;border-radius:7px;flex:none;align-items:center;gap:2px;height:31px;padding:2px;display:flex}.quadrant-filter[data-v-90794584]{max-width:470px;overflow-x:auto}.review-state-filter>span[data-v-90794584],.quadrant-filter>span[data-v-90794584]{color:#7a847d;padding:0 6px;font-size:8px;font-weight:650}.review-state-filter button[data-v-90794584],.quadrant-filter button[data-v-90794584]{color:#626d66;white-space:nowrap;background:0 0;border:0;border-radius:5px;height:25px;padding:0 7px;font-size:9px}.review-state-filter button[data-v-90794584]:hover,.quadrant-filter button[data-v-90794584]:hover{color:#35473d;background:#ffffffa8}.review-state-filter button.active[data-v-90794584],.quadrant-filter button.active[data-v-90794584]{color:#30483a;background:#fff;box-shadow:0 1px 3px #2f3d341f}.review-state-filter button.state-pending.active[data-v-90794584]{color:#765d2e}.review-state-filter button.state-agent_confirmed.active[data-v-90794584]{color:#4d5f78}.review-state-filter button.state-confirmed.active[data-v-90794584]{color:#356047}.review-state-filter button strong[data-v-90794584],.quadrant-filter button strong[data-v-90794584]{margin-left:2px;font-size:8px;font-weight:720}.organizer-result-summary[data-v-90794584]{color:#7b847e;white-space:nowrap;flex:none;font-size:9px}.organizer-toolbar .batch-confirm-action[data-v-90794584]{margin-left:auto}.organizer-toolbar .toolbar-action+.toolbar-action[data-v-90794584]{margin-left:0}.organizer-truncated[data-v-90794584]{color:#806536;margin:-4px 0 0;font-size:9px}.organizer-layout[data-v-90794584]{background:#fff;border:1px solid #cfd7d1;border-radius:8px;flex:1;grid-template-columns:minmax(0,1fr);min-height:0;display:grid;overflow:hidden}.organizer-layout.has-selection[data-v-90794584]{grid-template-columns:minmax(0,1fr) 340px}.organizer-layout[data-v-90794584]:not(.has-selection) .graph-inspector{display:none}.organizer-directory[data-v-90794584]{overscroll-behavior:contain;min-width:0;overflow:auto}.organizer-table-head[data-v-90794584],.organizer-row[data-v-90794584]{grid-template-columns:minmax(230px,1.35fr) 114px 130px minmax(160px,.8fr) 118px;align-items:center;gap:12px;min-width:920px;display:grid}.organizer-table-head[data-v-90794584]{z-index:2;color:#8b938d;background:#f7f8f6;border-bottom:1px solid #e0e4e0;padding:10px 15px;font-size:9px;font-weight:680;position:sticky;top:0}.organizer-row[data-v-90794584]{color:#4f5952;text-align:left;background:#fff;border:0;border-bottom:1px solid #e8ebe8;width:100%;min-height:68px;padding:11px 15px}.organizer-row[data-v-90794584]:hover{background:#f8faf8}.organizer-row.selected[data-v-90794584]{background:#f1f6f3;box-shadow:inset 2px 0 #557863}.organizer-item-copy[data-v-90794584]{gap:4px;min-width:0;display:grid}.organizer-item-copy strong[data-v-90794584],.organizer-item-copy small[data-v-90794584]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.organizer-item-copy strong[data-v-90794584]{color:#2f3933;font-size:11px;font-weight:630}.organizer-item-copy small[data-v-90794584],.organizer-basis[data-v-90794584],.organizer-row time[data-v-90794584]{color:#7b847e;font-size:9px}.quadrant-chip[data-v-90794584],.review-chip[data-v-90794584]{white-space:nowrap;border-radius:999px;width:fit-content;padding:4px 7px;font-size:9px;font-weight:650}.quadrant-chip[data-v-90794584]{color:#59655e;background:#f0f2ef;gap:1px;display:grid}.quadrant-chip small[data-v-90794584]{color:inherit;opacity:.75;font-size:7px;font-weight:520}.quadrant-chip.known_known[data-v-90794584]{color:#356047;background:#edf6f0}.quadrant-chip.known_unknown[data-v-90794584]{color:#77602f;background:#f7f2e5}.quadrant-chip.unknown_known[data-v-90794584]{color:#4d5f78;background:#eef2f7}.quadrant-chip.unknown_unknown[data-v-90794584]{color:#725d70;background:#f5eff4}.review-chip.state-confirmed[data-v-90794584]{color:#356047;background:#edf6f0}.review-chip.state-agent_confirmed[data-v-90794584]{color:#4d5f78;background:#eef2f7}.review-chip.state-pending[data-v-90794584]{color:#77602f;background:#f7f2e5}.organizer-basis[data-v-90794584]{overflow-wrap:anywhere}@media (width<=1260px){.review-state-filter>span[data-v-90794584],.quadrant-filter>span[data-v-90794584],.organizer-result-summary[data-v-90794584]{display:none}.organizer-table-head[data-v-90794584],.organizer-row[data-v-90794584]{grid-template-columns:minmax(210px,1fr) 108px 104px minmax(140px,.8fr) 104px;min-width:760px}}@media (width<=1040px){.organizer-layout.has-selection[data-v-90794584]{grid-template-columns:minmax(0,1fr) 280px}.organizer-table-head[data-v-90794584],.organizer-row[data-v-90794584]{grid-template-columns:minmax(210px,1fr) 108px 104px;min-width:470px}.organizer-table-head[data-v-90794584]>:nth-child(n+4),.organizer-basis[data-v-90794584],.organizer-row time[data-v-90794584]{display:none}.batch-confirm-action[data-v-90794584]{text-overflow:ellipsis;white-space:nowrap;max-width:108px;overflow:hidden}}
@@ -0,0 +1 @@
1
+ import{A as e,D as t,L as n,M as r,P as i,T as a,_ as o,a as ee,c as s,d as c,f as l,m as u,nt as d,p as f,r as p,t as te,tt as m,u as h,v as g,y as _}from"./console-tbvTUi6p.js";import{a as v,n as y,o as b}from"./runtime-dom.esm-bundler-DttsK21F.js";import{n as x,r as S,t as C}from"./identity-B3s5CXhv.js";import{E as w,T,_ as E,a as D,g as O,h as k,l as A,n as j,t as M}from"./model-DVT8sjy9.js";import{i as N,n as P,r as ne,t as F}from"./KnowledgeInspector-BSpz5Sfm.js";var I={open:``,class:`project-dialog batch-confirm-dialog vue-dialog`},L={class:`project-dialog-shell`},R={class:`project-dialog-header`},z={class:`batch-confirm-controls`},B={key:0,class:`batch-group-summary`},V={class:`batch-confirmer-fields`},re=[`required`,`placeholder`],H={class:`batch-confirm-review`},ie={class:`batch-review-heading`},U={key:0,class:`batch-limit-note`},ae={class:`batch-review-list`},oe=[`value`],W={class:`batch-confirm-acknowledgement`},G={key:0,class:`publish-dialog-error`,role:`alert`},K={class:`publish-dialog-actions`},q=[`disabled`],se=[`disabled`],J=N(_({__name:`KnowledgeBatchConfirmDialog`,props:{groups:{},personalSpaceId:{}},emits:[`close`,`saved`],setup(l,{emit:p}){let m=l,_=p,w=te(),E=i(``),D=i([]),O=i(`user`),k=i(``),A=i(``),j=i(!1),N=i(!1),P=i(``),ne=h(()=>m.groups.map(e=>({value:e.key,label:e.label,meta:`${e.kind===`source`?`同一来源`:`同一会话`} · ${e.items.length} 条`,search:`${x(e.value)} ${e.description}`}))),F=h(()=>m.groups.find(({key:e})=>e===E.value)??null),J=h(()=>F.value?.items.slice(0,200)??[]),Y=h(()=>{let e=new Set(D.value);return J.value.filter(t=>e.has(Z(t)))}),X=h(()=>J.value.length>0&&Y.value.length===J.value.length),ce=h(()=>!N.value&&Y.value.length>=2&&!!A.value.trim()&&j.value&&(O.value!==`authoritative_source`||!!k.value.trim())),le=[{value:`user`,label:`用户`},{value:`authoritative_source`,label:`权威来源`}];e(()=>m.groups,e=>{e.some(({key:e})=>e===E.value)||(E.value=e[0]?.key??``)},{immediate:!0}),e(E,()=>{D.value=J.value.map(Z),j.value=!1,P.value=``},{immediate:!0});function Z(e){return`${e.itemKind}:${e.id}`}function ue(){D.value=X.value?[]:J.value.map(Z),j.value=!1}function Q(e){let t=F.value;return t?M(e,t):null}async function de(){let e=F.value;if(!e)return $(`请选择一个来源或会话`);if(Y.value.length<2)return $(`批量确认至少需要选择两条知识`);if(!A.value.trim())return $(`请说明本次批量确认的依据`);if(O.value===`authoritative_source`&&!k.value.trim())return $(`请填写权威来源名称`);if(!j.value)return $(`请先确认已经核对内容与发现时象限`);N.value=!0,P.value=``;try{let t=await ee(`/api/knowledge/batch-confirmation`,{personalSpaceId:m.personalSpaceId,groupKind:e.kind,groupValue:e.value,reason:A.value.trim(),confirmer:{kind:O.value,label:k.value.trim()||null},items:Y.value.map(e=>{let t=Q(e);return{itemId:e.id,itemKind:e.itemKind,existenceReason:t.existenceReason,quadrantReason:t.quadrantReason,proposedBy:t.proposedBy}})});w.notify(`已确认 ${t.confirmed_count} 条知识;每条都保留了确认依据与本次确认时间。`),_(`saved`),_(`close`)}catch(e){P.value=e instanceof Error?e.message:`批量确认失败`,w.reportError(e)}finally{N.value=!1}}function $(e){P.value=e}return(e,i)=>(a(),u(`dialog`,I,[c(`div`,L,[c(`header`,R,[i[8]||=c(`div`,null,[c(`p`,{class:`eyebrow`},`BATCH CONFIRMATION`),c(`h3`,null,`按来源或会话批量确认`),c(`p`,null,`一次确认会同时覆盖每条知识的内容与发现时象限,并为每条知识写入独立修订历史。`)],-1),c(`button`,{class:`secondary-action`,type:`button`,onClick:i[0]||=e=>_(`close`)},`关闭`)]),c(`form`,{class:`batch-confirm-form`,onSubmit:b(de,[`prevent`])},[c(`section`,z,[c(`label`,null,[i[9]||=o(`确认范围 `,-1),g(S,{modelValue:E.value,"onUpdate:modelValue":i[1]||=e=>E.value=e,options:ne.value,label:`批量确认范围`,searchable:``},null,8,[`modelValue`,`options`])]),F.value?(a(),u(`div`,B,[c(`span`,null,d(F.value.kind===`source`?`同一来源`:`同一会话`),1),c(`strong`,null,d(F.value.label),1),c(`p`,null,d(F.value.description),1),c(`small`,null,`#`+d(n(C)(F.value.value,28)),1)])):f(``,!0),c(`div`,V,[c(`label`,null,[i[10]||=o(`确认者 `,-1),g(S,{modelValue:O.value,"onUpdate:modelValue":i[2]||=e=>O.value=e,options:le,label:`批量确认者`},null,8,[`modelValue`])]),c(`label`,null,[i[11]||=o(`确认者说明 `,-1),r(c(`input`,{"onUpdate:modelValue":i[3]||=e=>k.value=e,maxlength:`160`,required:O.value===`authoritative_source`,placeholder:O.value===`user`?`可选,例如当前用户`:`必填,例如已批准的 PRD`},null,8,re),[[v,k.value]])])]),c(`label`,null,[i[12]||=o(`批量确认依据 `,-1),r(c(`textarea`,{"onUpdate:modelValue":i[4]||=e=>A.value=e,maxlength:`2000`,rows:`3`,required:``,placeholder:`例如:已按本次会话逐条核对内容及其发现时象限`},null,512),[[v,A.value]])]),i[13]||=c(`p`,{class:`batch-confirm-rule`},` Agent 不能作为确认者。确认时间由服务端统一记录,后续修改内容或象限仍会自动回到待确认。 `,-1)]),c(`section`,H,[c(`div`,ie,[c(`div`,null,[i[14]||=c(`h4`,null,`逐条核对`,-1),c(`p`,null,`已选择 `+d(Y.value.length)+` / `+d(J.value.length)+` 条`,1)]),c(`button`,{class:`secondary-action`,type:`button`,onClick:ue},d(X.value?`全部取消`:`全部选择`),1)]),(F.value?.items.length??0)>200?(a(),u(`p`,U,` 单次最多确认 200 条;完成后可继续处理同一组剩余内容。 `)):f(``,!0),c(`div`,ae,[(a(!0),u(s,null,t(J.value,e=>(a(),u(`label`,{key:Z(e),class:`batch-review-item`},[r(c(`input`,{"onUpdate:modelValue":i[5]||=e=>D.value=e,type:`checkbox`,value:Z(e)},null,8,oe),[[y,D.value]]),c(`span`,null,[c(`strong`,null,d(e.title),1),c(`small`,null,d(n(T)(e.originQuadrant))+` · `+d(e.type),1),c(`em`,null,d(Q(e)?.existenceReason),1),c(`em`,null,d(Q(e)?.quadrantReason),1)])]))),128))]),c(`label`,W,[r(c(`input`,{"onUpdate:modelValue":i[6]||=e=>j.value=e,type:`checkbox`},null,512),[[y,j.value]]),i[15]||=c(`span`,null,`我已核对所选知识的内容与发现时象限,并确认上述依据可追溯。`,-1)])]),P.value?(a(),u(`p`,G,d(P.value),1)):f(``,!0),c(`div`,K,[c(`button`,{class:`secondary-action`,type:`button`,disabled:N.value,onClick:i[7]||=e=>_(`close`)},` 取消 `,8,q),c(`button`,{class:`primary-action`,type:`submit`,disabled:!ce.value},d(N.value?`正在确认…`:`确认 ${Y.value.length} 条知识`),9,se)])],32)])]))}}),[[`__scopeId`,`data-v-f18528e4`]]),Y={class:`view knowledge-organizer`},X={class:`organizer-head`},ce={class:`organizer-attention`},le={class:`organizer-toolbar`},Z={class:`organizer-search`},ue={class:`quadrant-filter`,"aria-label":`发现来源筛选`},Q=[`aria-pressed`],de=[`data-quadrant`,`aria-pressed`,`title`,`onClick`],$={class:`review-state-filter`,"aria-label":`确认状态筛选`},fe=[`aria-pressed`],pe=[`data-review-state`,`aria-pressed`,`title`,`onClick`],me={class:`organizer-result-summary`},he={key:0},ge={key:0,class:`organizer-truncated`},_e={key:1,class:`view-loading`},ve={class:`organizer-directory`,"aria-label":`知识整理目录`},ye={class:`organizer-list`},be=[`onClick`],xe={class:`organizer-item-copy`},Se={class:`organizer-basis`},Ce={key:0,class:`empty-state`},we=N(_({__name:`KnowledgeOrganizerPage`,setup(ee){let _=te(),y=i(null),b=i(!1),x=i(``),S=i(`all`),C=i(`all`),M=i(null),N=i(null),I=i(null),L=i(!1),R=[{value:`known_unknown`,short:`明确问题`,coordinate:`已意识 · 未掌握`},{value:`known_known`,short:`明确表达`,coordinate:`已意识 · 已掌握`},{value:`unknown_unknown`,short:`盲点探索`,coordinate:`未意识 · 未掌握`},{value:`unknown_known`,short:`隐性提炼`,coordinate:`未意识 · 已掌握`}],z=[{value:`pending`,label:`待确认`,hint:`尚无有效的确认人和确认时间`},{value:`agent_confirmed`,label:`Agent 已确认`,hint:`实际使用达到策略阈值,权重低于人工确认`},{value:`confirmed`,label:`已确认`,hint:`内容与象限归类均已确认`}],B=h(()=>k(y.value)),V=h(()=>j(B.value)),re=h(()=>Object.fromEntries([...R.map(({value:e})=>e),`unclassified`].map(e=>[e,B.value.filter(t=>t.originQuadrant===e).length]))),H=h(()=>Object.fromEntries(z.map(({value:e})=>[e,B.value.filter(t=>O(t)===e).length]))),ie=h(()=>S.value!==`all`),U=h(()=>ie.value?B.value.filter(e=>e.originQuadrant===S.value):B.value),ae=h(()=>Object.fromEntries(z.map(({value:e})=>[e,U.value.filter(t=>O(t)===e).length]))),oe=h(()=>H.value.pending),W=h(()=>{let e=x.value.trim().toLocaleLowerCase();return B.value.filter(t=>S.value!==`all`&&t.originQuadrant!==S.value||C.value!==`all`&&O(t)!==C.value?!1:!e||[t.title,t.body,t.type,T(t.originQuadrant),w(t),...t.evidence.flatMap(e=>[e.name,e.summary,e.source_description])].filter(Boolean).join(` `).toLocaleLowerCase().includes(e))});e(()=>_.activePersonalSpace?.id,e=>{e&&G(e)},{immediate:!0}),e(W,e=>{M.value&&!e.some(({id:e,itemKind:t})=>e===M.value?.id&&t===M.value?.itemKind)&&(M.value=null)});async function G(e=_.activePersonalSpace?.id){if(e){b.value=!0;try{let t=new URLSearchParams({spaceId:e,limit:`500`});y.value=await p(`/api/graph?${t}`),M.value&&=B.value.find(({id:e})=>e===M.value?.id)??null}catch(e){y.value=null,_.reportError(e)}finally{b.value=!1}}}function K(e){S.value=S.value===e?`all`:e}function q(e){C.value=e}function se(e){x.value=``,S.value=e.originQuadrant,C.value=`all`,M.value=e}return(e,i)=>(a(),u(`section`,Y,[c(`div`,X,[i[15]||=c(`div`,{class:`organizer-principle`},[c(`p`,{class:`eyebrow`},`HOW CLASSIFICATION WORKS`),c(`h3`,null,`先看知识和确认状态,四象限只保留发现来源`),c(`p`,null,` 待确认内容也可被 Agent 检索;实际使用达到阈值会标记为“Agent 已确认”,人工确认仍具有更高权重。 `)],-1),c(`div`,ce,[c(`strong`,null,d(oe.value),1),i[13]||=c(`span`,null,`条需要你处理`,-1),i[14]||=c(`small`,null,`旧数据缺少确认记录时也会进入这里`,-1)])]),c(`template`,null,[c(`div`,le,[c(`label`,Z,[i[16]||=c(`span`,null,`筛选知识`,-1),r(c(`input`,{"onUpdate:modelValue":i[0]||=e=>x.value=e,type:`search`,placeholder:`搜索内容、类型或来源`},null,512),[[v,x.value]])]),c(`div`,ue,[i[18]||=c(`span`,null,`发现来源`,-1),c(`button`,{type:`button`,"data-quadrant":`all`,class:m({active:S.value===`all`}),"aria-pressed":S.value===`all`,onClick:i[1]||=e=>S.value=`all`},[i[17]||=o(` 全部 `,-1),c(`strong`,null,d(B.value.length),1)],10,Q),(a(),u(s,null,t(R,e=>c(`button`,{key:e.value,type:`button`,"data-quadrant":e.value,class:m({active:S.value===e.value}),"aria-pressed":S.value===e.value,title:e.coordinate,onClick:t=>K(e.value)},[o(d(e.short)+` `,1),c(`strong`,null,d(re.value[e.value]),1)],10,de)),64))]),c(`div`,$,[i[20]||=c(`span`,null,`确认状态`,-1),c(`button`,{type:`button`,"data-review-state":`all`,class:m({active:C.value===`all`}),"aria-pressed":C.value===`all`,onClick:i[2]||=e=>q(`all`)},[i[19]||=o(` 全部 `,-1),c(`strong`,null,d(U.value.length),1)],10,fe),(a(),u(s,null,t(z,e=>c(`button`,{key:e.value,type:`button`,"data-review-state":e.value,class:m([`state-${e.value}`,{active:C.value===e.value}]),"aria-pressed":C.value===e.value,title:e.hint,onClick:t=>q(e.value)},[o(d(e.label)+` `,1),c(`strong`,null,d(ae.value[e.value]),1)],10,pe)),64))]),c(`p`,me,[o(` 显示 `+d(W.value.length)+` / `+d(U.value.length)+` 条 `,1),C.value===`all`?f(``,!0):(a(),u(`span`,he,` · `+d(z.find(({value:e})=>e===C.value)?.label),1))]),V.value.length?(a(),u(`button`,{key:0,class:`toolbar-action batch-confirm-action`,type:`button`,onClick:i[3]||=e=>L.value=!0},` 批量确认 · `+d(V.value.length)+` 组 `,1)):f(``,!0),c(`button`,{class:`toolbar-action`,type:`button`,onClick:i[4]||=e=>G()},`刷新`)]),y.value?.truncated?(a(),u(`p`,ge,` 当前知识量超过单次读取上限;本页统计只覆盖本次读取到的内容。 `)):f(``,!0),b.value&&!y.value?(a(),u(`div`,_e,`正在读取知识…`)):(a(),u(`div`,{key:2,class:m([`organizer-layout`,{"has-selection":M.value}])},[c(`section`,ve,[i[21]||=c(`div`,{class:`organizer-table-head`,"aria-hidden":`true`},[c(`span`,null,`知识内容`),c(`span`,null,`发现时象限`),c(`span`,null,`确认状态`),c(`span`,null,`确认依据`),c(`span`,null,`更新时间`)],-1),c(`div`,ye,[(a(!0),u(s,null,t(W.value,e=>(a(),u(`button`,{key:`${e.itemKind}:${e.id}`,type:`button`,class:m([`organizer-row`,{selected:M.value?.id===e.id}]),onClick:t=>M.value=e},[c(`span`,xe,[c(`strong`,null,d(e.title),1),c(`small`,null,d(e.body),1)]),c(`span`,{class:m([`quadrant-chip`,e.originQuadrant])},d(n(T)(e.originQuadrant)),3),c(`span`,{class:m([`review-chip`,`state-${n(O)(e)}`])},d(n(w)(e)),3),c(`span`,Se,d(n(D)(e)),1),c(`time`,null,d(n(A)(n(E)(e))),1)],10,be))),128))]),W.value.length?f(``,!0):(a(),u(`div`,Ce,d(B.value.length?`当前筛选条件下没有内容`:`个人空间还没有可整理的结构化知识`),1))]),g(F,{item:M.value,graph:y.value,editable:``,onConfirm:i[5]||=e=>N.value=e,onEdit:i[6]||=e=>I.value=e,onOpenReplacement:se},null,8,[`item`,`graph`])],2))]),g(P,{item:I.value,"personal-space-id":n(_).activePersonalSpace?.id??``,"personal-project-id":null,projects:n(_).state?.personalProjects??[],"replacement-items":B.value,onClose:i[7]||=e=>I.value=null,onSaved:i[8]||=e=>G()},null,8,[`item`,`personal-space-id`,`projects`,`replacement-items`]),g(ne,{item:N.value,"personal-space-id":n(_).activePersonalSpace?.id??``,"personal-project-id":null,onClose:i[9]||=e=>N.value=null,onSaved:i[10]||=e=>G()},null,8,[`item`,`personal-space-id`]),L.value?(a(),l(J,{key:0,groups:V.value,"personal-space-id":n(_).activePersonalSpace?.id??``,onClose:i[11]||=e=>L.value=!1,onSaved:i[12]||=e=>G()},null,8,[`groups`,`personal-space-id`])):f(``,!0)]))}}),[[`__scopeId`,`data-v-90794584`]]);export{we as default};
@@ -0,0 +1 @@
1
+ import{T as e,f as t,y as n}from"./console-tbvTUi6p.js";import{t as r}from"./KnowledgeWorkspace-DVZusvem.js";var i=n({__name:`KnowledgePage`,setup(n){return(n,i)=>(e(),t(r))}});export{i as default};