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
@@ -0,0 +1,246 @@
1
+ import json
2
+ from datetime import datetime, timezone
3
+
4
+ from fastapi import HTTPException
5
+
6
+ from .knowledge_audit import record_human_change
7
+ from .knowledge_management import _read_item, _snapshot
8
+ from .models import (
9
+ ConfirmationBasis,
10
+ KnowledgeBatchConfirmationCreate,
11
+ KnowledgeBatchConfirmationResult,
12
+ )
13
+ from .provider_values import stable_uuid as _stable_uuid
14
+
15
+
16
+ async def confirm_knowledge_batch(
17
+ store,
18
+ actor: dict,
19
+ request: KnowledgeBatchConfirmationCreate,
20
+ ) -> KnowledgeBatchConfirmationResult:
21
+ store._require_personal()
22
+ space = await store.authorize(actor, request.personal_space_id, 'maintainer')
23
+ if space['kind'] != 'personal':
24
+ raise HTTPException(
25
+ status_code=422,
26
+ detail='knowledge batch confirmation is personal-only',
27
+ )
28
+
29
+ confirmed_at = datetime.now(timezone.utc)
30
+ rows = []
31
+ for item in request.items:
32
+ current = await _read_item(store, space, item.item_id, item.item_kind)
33
+ if current is None:
34
+ raise HTTPException(status_code=404, detail='knowledge item not found')
35
+ previous = _snapshot(current, item.item_kind)
36
+ if previous.get('invalidAt'):
37
+ raise HTTPException(
38
+ status_code=409,
39
+ detail='historical knowledge cannot be batch confirmed',
40
+ )
41
+ if (
42
+ previous.get('confirmationStateExplicit')
43
+ and previous.get('confirmationStatus') == 'confirmed'
44
+ ):
45
+ raise HTTPException(
46
+ status_code=409,
47
+ detail='confirmed knowledge cannot be batch confirmed again',
48
+ )
49
+
50
+ basis = ConfirmationBasis(
51
+ existence_reason=item.existence_reason,
52
+ quadrant_reason=item.quadrant_reason,
53
+ proposed_by=item.proposed_by,
54
+ confirmed_by=request.confirmer,
55
+ confirmed_at=confirmed_at,
56
+ ).model_dump(mode='json')
57
+ next_value = {
58
+ **previous,
59
+ 'epistemicStatus': 'confirmed',
60
+ 'confirmationStatus': 'confirmed',
61
+ 'confirmationStateExplicit': True,
62
+ 'confirmationBasis': basis,
63
+ }
64
+ revision_id = _stable_uuid(
65
+ space['id'],
66
+ 'knowledge-revision',
67
+ 'batch-confirm',
68
+ item.item_kind,
69
+ item.item_id,
70
+ confirmed_at.isoformat(),
71
+ actor['id'],
72
+ )
73
+ rows.append({
74
+ 'item_id': item.item_id,
75
+ 'item_kind': item.item_kind,
76
+ 'expected_name': previous.get('name'),
77
+ 'expected_summary': previous.get('summary') or '',
78
+ 'expected_fact': previous.get('fact'),
79
+ 'expected_origin_quadrant': previous.get('originQuadrant'),
80
+ 'confirmation_basis_json': json.dumps(
81
+ basis,
82
+ ensure_ascii=False,
83
+ sort_keys=True,
84
+ ),
85
+ 'revision_id': revision_id,
86
+ 'previous_json': json.dumps(
87
+ previous,
88
+ ensure_ascii=False,
89
+ sort_keys=True,
90
+ ),
91
+ 'current_json': json.dumps(
92
+ next_value,
93
+ ensure_ascii=False,
94
+ sort_keys=True,
95
+ ),
96
+ })
97
+
98
+ records, _, _ = await store.runtime.driver.execute_query(
99
+ _BATCH_CONFIRM_QUERY,
100
+ space_id=space['id'],
101
+ group_id=space['group_id'],
102
+ group_kind=request.group_kind,
103
+ group_value=request.group_value,
104
+ items=rows,
105
+ reason=request.reason,
106
+ created_by=actor['id'],
107
+ confirmed_at=confirmed_at,
108
+ )
109
+ if not records:
110
+ raise HTTPException(
111
+ status_code=409,
112
+ detail=(
113
+ 'batch confirmation changed before it could be saved; '
114
+ 'refresh and review the group again'
115
+ ),
116
+ )
117
+ confirmed_count = int(records[0]['confirmed_count'])
118
+ if confirmed_count != len(rows):
119
+ raise HTTPException(
120
+ status_code=409,
121
+ detail='batch confirmation did not update every selected item',
122
+ )
123
+ if request.operation_actor == 'human':
124
+ for item in request.items:
125
+ await record_human_change(
126
+ store,
127
+ actor,
128
+ space,
129
+ item.item_id,
130
+ item.item_kind,
131
+ reason=request.reason,
132
+ operation='batch_confirmation',
133
+ )
134
+ return KnowledgeBatchConfirmationResult(
135
+ group_kind=request.group_kind,
136
+ group_value=request.group_value,
137
+ confirmed_count=confirmed_count,
138
+ confirmed_at=confirmed_at,
139
+ item_keys=[
140
+ f'{item.item_kind}:{item.item_id}'
141
+ for item in request.items
142
+ ],
143
+ )
144
+
145
+
146
+ _BATCH_CONFIRM_QUERY = '''
147
+ MATCH (space:FuliSpace {id: $space_id, kind: 'personal'})
148
+ WITH space, $items AS items
149
+ CALL {
150
+ WITH items
151
+ UNWIND [row IN items WHERE row.item_kind = 'entity'] AS row
152
+ OPTIONAL MATCH (item:Entity {
153
+ uuid: row.item_id,
154
+ group_id: $group_id
155
+ })
156
+ WITH row, item
157
+ WHERE item IS NOT NULL
158
+ AND item.fuli_invalid_at IS NULL
159
+ AND item.fuli_origin_quadrant IS NOT NULL
160
+ AND coalesce(item.fuli_confirmation_status, 'pending') = 'pending'
161
+ AND item.name = row.expected_name
162
+ AND coalesce(item.summary, '') = row.expected_summary
163
+ AND item.fuli_origin_quadrant = row.expected_origin_quadrant
164
+ AND EXISTS {
165
+ MATCH (episode:Episodic {group_id: $group_id})-[:MENTIONS]->(item)
166
+ WHERE ($group_kind = 'source' AND episode.uuid = $group_value)
167
+ OR ($group_kind = 'session'
168
+ AND episode.fuli_session_id = $group_value)
169
+ }
170
+ RETURN collect({item: item, row: row}) AS valid_entities
171
+ }
172
+ CALL {
173
+ WITH items
174
+ UNWIND [row IN items WHERE row.item_kind = 'relationship'] AS row
175
+ OPTIONAL MATCH ()-[item:RELATES_TO {
176
+ uuid: row.item_id,
177
+ group_id: $group_id
178
+ }]->()
179
+ WITH row, item
180
+ WHERE item IS NOT NULL
181
+ AND item.invalid_at IS NULL
182
+ AND item.fuli_origin_quadrant IS NOT NULL
183
+ AND coalesce(item.fuli_confirmation_status, 'pending') = 'pending'
184
+ AND item.fact = row.expected_fact
185
+ AND item.fuli_origin_quadrant = row.expected_origin_quadrant
186
+ AND EXISTS {
187
+ MATCH (episode:Episodic {group_id: $group_id})
188
+ WHERE episode.uuid IN coalesce(item.episodes, [])
189
+ AND (
190
+ ($group_kind = 'source' AND episode.uuid = $group_value)
191
+ OR ($group_kind = 'session'
192
+ AND episode.fuli_session_id = $group_value)
193
+ )
194
+ }
195
+ RETURN collect({item: item, row: row}) AS valid_relationships
196
+ }
197
+ WITH space, items, valid_entities, valid_relationships,
198
+ size(valid_entities) + size(valid_relationships) AS valid_count
199
+ WHERE valid_count = size(items)
200
+ CALL {
201
+ WITH space, valid_entities
202
+ UNWIND valid_entities AS valid
203
+ WITH space, valid.item AS item, valid.row AS row
204
+ SET item.fuli_epistemic_status = 'confirmed',
205
+ item.fuli_confirmation_status = 'confirmed',
206
+ item.fuli_confirmation_basis_json = row.confirmation_basis_json
207
+ CREATE (revision:FuliKnowledgeRevision {
208
+ id: row.revision_id,
209
+ space_id: $space_id,
210
+ item_id: row.item_id,
211
+ item_kind: row.item_kind,
212
+ action: 'batch_confirm',
213
+ reason: $reason,
214
+ previous_json: row.previous_json,
215
+ current_json: row.current_json,
216
+ created_by: $created_by,
217
+ created_at: $confirmed_at
218
+ })
219
+ MERGE (space)-[:HAS_KNOWLEDGE_REVISION]->(revision)
220
+ RETURN count(*) AS entity_count
221
+ }
222
+ CALL {
223
+ WITH space, valid_relationships
224
+ UNWIND valid_relationships AS valid
225
+ WITH space, valid.item AS item, valid.row AS row
226
+ SET item.fuli_epistemic_status = 'confirmed',
227
+ item.fuli_confirmation_status = 'confirmed',
228
+ item.fuli_confirmation_basis_json = row.confirmation_basis_json
229
+ CREATE (revision:FuliKnowledgeRevision {
230
+ id: row.revision_id,
231
+ space_id: $space_id,
232
+ item_id: row.item_id,
233
+ item_kind: row.item_kind,
234
+ action: 'batch_confirm',
235
+ reason: $reason,
236
+ previous_json: row.previous_json,
237
+ current_json: row.current_json,
238
+ created_by: $created_by,
239
+ created_at: $confirmed_at
240
+ })
241
+ MERGE (space)-[:HAS_KNOWLEDGE_REVISION]->(revision)
242
+ RETURN count(*) AS relationship_count
243
+ }
244
+ RETURN valid_count,
245
+ entity_count + relationship_count AS confirmed_count
246
+ '''