fuli-context 0.7.4-beta.3 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +77 -6
  2. package/README.zh-CN.md +69 -6
  3. package/compose.graphiti.yml +6 -6
  4. package/dist/web/assets/AboutPage-sLV9WChi.js +1 -0
  5. package/dist/web/assets/ConnectionsPage-BWn4ywGJ.js +1 -0
  6. package/dist/web/assets/KnowledgeEditDialog-CZ5ziPrD.js +1 -0
  7. package/dist/web/assets/KnowledgeInspector-CRQWOaos.js +1 -0
  8. package/dist/web/assets/KnowledgeOrganizerPage-Dfj3vIpU.js +1 -0
  9. package/dist/web/assets/KnowledgePage-BRYC9S5Y.js +1 -0
  10. package/dist/web/assets/KnowledgeWorkspace-ChEB5Bwk.js +4 -0
  11. package/dist/web/assets/OverviewPage-Cd66M0RT.js +1 -0
  12. package/dist/web/assets/PersonalProfilePage-RCFHL0Wz.js +1 -0
  13. package/dist/web/assets/PersonalProjectsPage-DEh8XWby.js +1 -0
  14. package/dist/web/assets/ProjectAgentsPage-Crh7PrXa.css +1 -0
  15. package/dist/web/assets/ProjectAgentsPage-DPnaH-TR.js +11 -0
  16. package/dist/web/assets/PublicProjectsPage-mstPEjHe.js +1 -0
  17. package/dist/web/assets/ReviewPage-6Y1SmfZy.js +1 -0
  18. package/dist/web/assets/SearchableSelect-D3HM8YF8.js +1 -0
  19. package/dist/web/assets/SettingsPage--LdTMUm7.js +1 -0
  20. package/dist/web/assets/SettingsPage-CwZp2ka4.css +1 -0
  21. package/dist/web/assets/WritingTastePage-CIpKswvs.js +1 -0
  22. package/dist/web/assets/{console-D_2zC4lm.js → console-BT1P2Db4.js} +1 -1
  23. package/dist/web/assets/{conversation-launcher-settings-DQmMH2j7.js → conversation-launcher-settings-DrJEotdf.js} +1 -1
  24. package/dist/web/assets/i18n-js6gfc7j.js +9 -0
  25. package/dist/web/assets/{identity-DmGcY3Y6.js → identity-CfDfanpa.js} +1 -1
  26. package/dist/web/assets/index-BnH5mcZx.css +1 -0
  27. package/dist/web/assets/index-GqJf1xqg.js +2 -0
  28. package/dist/web/assets/{model-CVoOdRsL.js → model-DJkLAJsg.js} +1 -1
  29. package/dist/web/assets/{useApi-CROJJdhE-CBNg4CdH.js → useApi-CROJJdhE-BdSti7Y2.js} +1 -1
  30. package/dist/web/assets/vue-router-Kk67EaCP.js +1 -0
  31. package/dist/web/index.html +6 -6
  32. package/graph-provider/fuli_graph/app.py +8 -0
  33. package/graph-provider/fuli_graph/collaboration_context.py +69 -6
  34. package/graph-provider/fuli_graph/knowledge_search.py +84 -5
  35. package/graph-provider/fuli_graph/model_validation.py +130 -0
  36. package/graph-provider/fuli_graph/models.py +24 -5
  37. package/graph-provider/fuli_graph/project_agent_access.py +54 -0
  38. package/graph-provider/fuli_graph/project_agent_coordination_models.py +22 -0
  39. package/graph-provider/fuli_graph/project_agent_executor_models.py +635 -0
  40. package/graph-provider/fuli_graph/project_agent_models.py +278 -0
  41. package/graph-provider/fuli_graph/project_agent_routes.py +626 -0
  42. package/graph-provider/fuli_graph/project_agent_task_models.py +545 -0
  43. package/graph-provider/fuli_graph/runtime.py +259 -0
  44. package/graph-provider/fuli_graph/search_projection.py +3 -0
  45. package/graph-provider/fuli_graph/store.py +6 -0
  46. package/graph-provider/fuli_graph/store_knowledge.py +62 -9
  47. package/graph-provider/fuli_graph/store_project_agent_coordination_policy.py +122 -0
  48. package/graph-provider/fuli_graph/store_project_agent_executor_learning.py +756 -0
  49. package/graph-provider/fuli_graph/store_project_agent_executor_routing.py +601 -0
  50. package/graph-provider/fuli_graph/store_project_agent_executors.py +1087 -0
  51. package/graph-provider/fuli_graph/store_project_agent_task_reads.py +458 -0
  52. package/graph-provider/fuli_graph/store_project_agent_task_recruitment.py +705 -0
  53. package/graph-provider/fuli_graph/store_project_agent_task_staffing.py +586 -0
  54. package/graph-provider/fuli_graph/store_project_agent_tasks.py +1151 -0
  55. package/graph-provider/fuli_graph/store_project_agents.py +965 -0
  56. package/graph-provider/pyproject.toml +2 -1
  57. package/npm-shrinkwrap.json +2 -2
  58. package/package.json +1 -1
  59. package/skills/capturing-session-knowledge/SKILL.md +39 -0
  60. package/src/adaptive-runtime/executor-pool.js +127 -0
  61. package/src/adaptive-runtime/graph-services.js +166 -0
  62. package/src/adaptive-runtime/lease-client.js +335 -0
  63. package/src/adaptive-runtime/runtime-broker.js +318 -0
  64. package/src/adaptive-runtime/settings.js +111 -0
  65. package/src/adaptive-runtime/state.js +74 -0
  66. package/src/agent-tools/graph-definitions.js +419 -0
  67. package/src/agent-tools/graph-handlers.js +65 -0
  68. package/src/agent-tools/project-agent-definitions.js +307 -0
  69. package/src/backup/graph-backup.js +289 -0
  70. package/src/backup/identity-reconciliation.js +208 -0
  71. package/src/backup/runtime-adapters.js +269 -0
  72. package/src/cli/command-registry.js +6 -2
  73. package/src/cli/graph-data-command.js +112 -0
  74. package/src/cli/local-runtime-command.js +16 -2
  75. package/src/cli/setup-command.js +19 -3
  76. package/src/cli/update-command.js +4 -0
  77. package/src/cli.js +6 -0
  78. package/src/graphiti/collaboration-preference-projection.js +29 -1
  79. package/src/graphiti/collaboration-preference-workflow.js +121 -0
  80. package/src/graphiti/federated-application.js +53 -90
  81. package/src/graphiti/project-agent-control-plane.js +275 -0
  82. package/src/graphiti/project-agent-mapping.js +1024 -0
  83. package/src/graphiti/project-agent-workflows.js +576 -0
  84. package/src/graphiti/provider-client.js +282 -1
  85. package/src/http/api-router.js +63 -9
  86. package/src/http/graph-api-router.js +290 -0
  87. package/src/local-runtime/lifecycle.js +46 -10
  88. package/src/mcp/context-resources.js +15 -6
  89. package/src/mcp/create-mcp-server.js +51 -16
  90. package/src/mcp/instructions.js +7 -5
  91. package/src/mcp/runtime.js +17 -5
  92. package/src/mcp/session-id.js +38 -1
  93. package/src/mcp/tool-annotations.js +71 -0
  94. package/src/mcp-server.js +23 -6
  95. package/src/native-runtime/runtime.js +717 -0
  96. package/src/server.js +6 -2
  97. package/src/setup/agent-installation-status.js +7 -1
  98. package/src/setup/agents.js +3 -1
  99. package/src/setup/claude-code-config.js +3 -1
  100. package/src/setup/codex-bootstrap.js +11 -10
  101. package/src/setup/codex-config.js +7 -1
  102. package/src/setup/cursor-config.js +3 -1
  103. package/src/setup/graph-runtime.js +158 -13
  104. package/src/setup/neo4j-memory-profile.js +43 -0
  105. package/src/setup/options.js +38 -2
  106. package/src/setup/paths.js +14 -0
  107. package/src/setup/setup.js +37 -1
  108. package/src/system/resource-monitor.js +181 -16
  109. package/src/system/runtime-settings.js +10 -1
  110. package/src/system/system-service.js +27 -2
  111. package/dist/web/assets/AboutPage-Dpf5fRWv.js +0 -1
  112. package/dist/web/assets/ConnectionsPage-D21aUDCP.js +0 -1
  113. package/dist/web/assets/KnowledgeEditDialog-u7lpfN3j.js +0 -1
  114. package/dist/web/assets/KnowledgeInspector-k4xnHtXd.js +0 -1
  115. package/dist/web/assets/KnowledgeOrganizerPage-Bdj7Rn84.js +0 -1
  116. package/dist/web/assets/KnowledgePage-UHVAbC1W.js +0 -1
  117. package/dist/web/assets/KnowledgeWorkspace-Lq3d-MeC.js +0 -4
  118. package/dist/web/assets/OverviewPage-CycAgA1V.js +0 -1
  119. package/dist/web/assets/PersonalProfilePage-U9oIV5FT.js +0 -1
  120. package/dist/web/assets/PersonalProjectsPage-C5RpXKcA.js +0 -1
  121. package/dist/web/assets/PublicProjectsPage-DiWxm35E.js +0 -1
  122. package/dist/web/assets/ReviewPage-jxRfGSJK.js +0 -1
  123. package/dist/web/assets/SearchableSelect-B3-5IPup.js +0 -1
  124. package/dist/web/assets/SettingsPage-BqfGDOho.js +0 -1
  125. package/dist/web/assets/SettingsPage-CAfz4qiV.css +0 -1
  126. package/dist/web/assets/WritingTastePage-BJxhMqJR.js +0 -1
  127. package/dist/web/assets/i18n-CwqXDI1C.js +0 -5
  128. package/dist/web/assets/index-IUGLt4lG.js +0 -2
  129. package/dist/web/assets/index-X2j29j8i.css +0 -1
  130. package/dist/web/assets/vue-router-CWSsUUio.js +0 -1
@@ -0,0 +1,278 @@
1
+ from datetime import datetime
2
+ from typing import Literal
3
+
4
+ from pydantic import AliasChoices, Field, field_validator, model_validator
5
+
6
+ from .model_validation import reject_credentials, validate_emoji_sequence
7
+ from .models import SourceApplication, StrictModel
8
+
9
+
10
+ ProjectAgentStatus = Literal['active', 'inactive', 'archived']
11
+ ProjectAgentType = Literal['coordinator', 'durable', 'hr', 'temporary']
12
+ ProjectAgentMemoryScope = Literal['reviewed_agent', 'task_only']
13
+ ProjectAgentWorkStatus = Literal[
14
+ 'idle',
15
+ 'awaiting_recruitment',
16
+ 'queued',
17
+ 'running',
18
+ 'paused',
19
+ 'failed',
20
+ 'awaiting_review',
21
+ 'blocked',
22
+ 'ended',
23
+ ]
24
+ ProjectAgentAssignmentStatus = Literal['active', 'ended']
25
+ ProjectAgentModelMode = Literal['adaptive', 'fast', 'balanced', 'deep']
26
+ ProjectAgentReasoningEffort = Literal['default', 'low', 'medium', 'high']
27
+ ProjectAgentExecutorPolicyMode = Literal['flexible', 'locked']
28
+ PROJECT_AGENT_CLIENTS: tuple[SourceApplication, ...] = (
29
+ 'codex',
30
+ 'claude_code',
31
+ 'cursor',
32
+ 'kiro',
33
+ 'other',
34
+ )
35
+
36
+
37
+ class ProjectAgentModelStrategy(StrictModel):
38
+ """Provider-neutral intent that each client maps to an available model."""
39
+
40
+ mode: ProjectAgentModelMode = 'adaptive'
41
+ reasoning_effort: ProjectAgentReasoningEffort = 'default'
42
+ capability_hints: list[str] = Field(default_factory=list, max_length=16)
43
+
44
+ @field_validator('capability_hints')
45
+ @classmethod
46
+ def validate_hints(cls, value: list[str]) -> list[str]:
47
+ normalized = [item.strip() for item in value]
48
+ if any(not item or len(item) > 128 for item in normalized):
49
+ raise ValueError('model capability hints must contain 1 to 128 characters')
50
+ if len({item.casefold() for item in normalized}) != len(normalized):
51
+ raise ValueError('model capability hints must be unique')
52
+ return normalized
53
+
54
+
55
+ class ProjectAgentExecutorPolicy(StrictModel):
56
+ """Explicit executor selection policy for an Agent or a Task.
57
+
58
+ ``flexible`` is intentionally the safe default: the coordinator may use
59
+ registered executors that pass all workspace checks. ``locked`` is an
60
+ explicit allow-list; selection may stay within that list, but an
61
+ unavailable list must block rather than silently falling back outside it.
62
+ """
63
+
64
+ mode: ProjectAgentExecutorPolicyMode = 'flexible'
65
+ locked_executor_ids: list[str] = Field(default_factory=list, max_length=32)
66
+ preferred_executor_ids: list[str] = Field(default_factory=list, max_length=32)
67
+
68
+ @field_validator('locked_executor_ids', 'preferred_executor_ids')
69
+ @classmethod
70
+ def validate_executor_ids(cls, value: list[str]) -> list[str]:
71
+ normalized = [item.strip() for item in value]
72
+ if any(not item or len(item) > 128 for item in normalized):
73
+ raise ValueError('executor IDs must contain 1 to 128 characters')
74
+ if len(set(normalized)) != len(normalized):
75
+ raise ValueError('executor IDs must be unique')
76
+ return normalized
77
+
78
+ @model_validator(mode='after')
79
+ def validate_mode(self):
80
+ if self.mode == 'locked' and not self.locked_executor_ids:
81
+ raise ValueError('locked executor policy requires an explicit allow-list')
82
+ if self.mode == 'locked' and self.preferred_executor_ids:
83
+ raise ValueError('locked executor policy cannot contain flexible preferences')
84
+ if set(self.locked_executor_ids) & set(self.preferred_executor_ids):
85
+ raise ValueError('locked and preferred executor IDs must not overlap')
86
+ reject_credentials(self, 'Project Agent executor policy')
87
+ return self
88
+
89
+
90
+ class ProjectAgentProfile(StrictModel):
91
+ name: str = Field(min_length=1, max_length=160)
92
+ # Keep the visual occupation marker as first-class profile data. It is
93
+ # intentionally independent from ``name`` so clients can update either
94
+ # value without rewriting the other and old profiles can omit it.
95
+ occupation_emoji: str | None = Field(
96
+ default=None,
97
+ min_length=1,
98
+ max_length=32,
99
+ validation_alias=AliasChoices('occupation_emoji', 'occupationEmoji'),
100
+ )
101
+ responsibility: str = Field(min_length=1, max_length=4096)
102
+ agent_type: ProjectAgentType = 'durable'
103
+ work_kinds: list[str] = Field(default_factory=list, max_length=32)
104
+ capabilities: list[str] = Field(default_factory=list, max_length=32)
105
+ initial_preferences: list[str] = Field(default_factory=list, max_length=32)
106
+ default_model_strategy: ProjectAgentModelStrategy = Field(
107
+ default_factory=ProjectAgentModelStrategy
108
+ )
109
+ executor_policy: ProjectAgentExecutorPolicy = Field(
110
+ default_factory=ProjectAgentExecutorPolicy
111
+ )
112
+ allowed_clients: list[SourceApplication] = Field(
113
+ default_factory=lambda: list(PROJECT_AGENT_CLIENTS),
114
+ max_length=len(PROJECT_AGENT_CLIENTS),
115
+ )
116
+ test_source: str | None = Field(default=None, min_length=1, max_length=256)
117
+ cleanup_eligible: bool = False
118
+ status: ProjectAgentStatus = 'active'
119
+
120
+ @field_validator('occupation_emoji', mode='before')
121
+ @classmethod
122
+ def validate_occupation_emoji(cls, value):
123
+ return validate_emoji_sequence(value, 'occupation emoji')
124
+
125
+ @field_validator('work_kinds', 'capabilities', 'initial_preferences')
126
+ @classmethod
127
+ def validate_bounded_unique_text(cls, value: list[str]) -> list[str]:
128
+ normalized = [item.strip() for item in value]
129
+ if any(not item or len(item) > 512 for item in normalized):
130
+ raise ValueError(
131
+ 'project Agent list entries must contain 1 to 512 characters'
132
+ )
133
+ if len({item.casefold() for item in normalized}) != len(normalized):
134
+ raise ValueError('project Agent list entries must be unique')
135
+ return normalized
136
+
137
+ @field_validator('allowed_clients')
138
+ @classmethod
139
+ def validate_unique_clients(
140
+ cls,
141
+ value: list[SourceApplication],
142
+ ) -> list[SourceApplication]:
143
+ if len(set(value)) != len(value):
144
+ raise ValueError('allowed clients must be unique')
145
+ return value
146
+
147
+ @model_validator(mode='after')
148
+ def reject_sensitive_values(self):
149
+ reject_credentials(self, 'Project Agent profile')
150
+ return self
151
+
152
+
153
+ class ProjectAgentUpsert(StrictModel):
154
+ personal_space_id: str = Field(min_length=1, max_length=128)
155
+ # Kept optional for backwards-compatible callers. The Agent identity is
156
+ # space-level; project responsibility lives in explicit assignments.
157
+ personal_project_id: str | None = Field(
158
+ default=None,
159
+ min_length=1,
160
+ max_length=128,
161
+ )
162
+ agent_id: str = Field(min_length=1, max_length=128)
163
+ profile: ProjectAgentProfile
164
+
165
+
166
+ class ProjectAgentAssignmentCreate(StrictModel):
167
+ personal_space_id: str = Field(min_length=1, max_length=128)
168
+ personal_project_id: str = Field(min_length=1, max_length=128)
169
+ agent_id: str = Field(min_length=1, max_length=128)
170
+ idempotency_key: str = Field(min_length=8, max_length=256)
171
+ responsibility: str = Field(min_length=1, max_length=4096)
172
+ work_kinds: list[str] = Field(default_factory=list, max_length=32)
173
+ capabilities: list[str] = Field(default_factory=list, max_length=32)
174
+ model_strategy_override: ProjectAgentModelStrategy | None = None
175
+ executor_policy_override: ProjectAgentExecutorPolicy | None = None
176
+ reason: str = Field(min_length=1, max_length=2048)
177
+ source_application: SourceApplication | None = None
178
+ source_session_id: str | None = Field(default=None, min_length=1, max_length=256)
179
+
180
+ @field_validator('work_kinds', 'capabilities')
181
+ @classmethod
182
+ def validate_bounded_unique_text(cls, value: list[str]) -> list[str]:
183
+ return ProjectAgentProfile.validate_bounded_unique_text(value)
184
+
185
+ @model_validator(mode='after')
186
+ def reject_sensitive_values(self):
187
+ reject_credentials(self, 'Project Agent assignment')
188
+ return self
189
+
190
+
191
+ class ProjectAgentAssignmentRecord(StrictModel):
192
+ assignment_id: str
193
+ personal_space_id: str
194
+ personal_project_id: str
195
+ agent_id: str
196
+ responsibility: str
197
+ work_kinds: list[str] = Field(default_factory=list)
198
+ capabilities: list[str] = Field(default_factory=list)
199
+ model_strategy_override: ProjectAgentModelStrategy | None = None
200
+ executor_policy_override: ProjectAgentExecutorPolicy | None = None
201
+ reason: str
202
+ status: ProjectAgentAssignmentStatus
203
+ revision: int = Field(default=0, ge=0)
204
+ source_application: SourceApplication | None = None
205
+ source_session_id: str | None = None
206
+ assigned_at: datetime
207
+ updated_at: datetime
208
+ ended_at: datetime | None = None
209
+ end_reason: str | None = None
210
+ replaced_by_assignment_id: str | None = None
211
+
212
+
213
+ class ProjectAgentAssignmentEnd(StrictModel):
214
+ personal_space_id: str = Field(min_length=1, max_length=128)
215
+ personal_project_id: str = Field(min_length=1, max_length=128)
216
+ assignment_id: str = Field(min_length=1, max_length=128)
217
+ expected_revision: int = Field(ge=0)
218
+ reason: str = Field(min_length=1, max_length=2048)
219
+
220
+ @model_validator(mode='after')
221
+ def reject_sensitive_values(self):
222
+ reject_credentials(self, 'Project Agent assignment end')
223
+ return self
224
+
225
+
226
+ class ProjectAgentAssignmentReplace(StrictModel):
227
+ personal_space_id: str = Field(min_length=1, max_length=128)
228
+ personal_project_id: str = Field(min_length=1, max_length=128)
229
+ assignment_id: str = Field(min_length=1, max_length=128)
230
+ expected_revision: int = Field(ge=0)
231
+ replacement_agent_id: str = Field(min_length=1, max_length=128)
232
+ idempotency_key: str = Field(min_length=8, max_length=256)
233
+ responsibility: str = Field(min_length=1, max_length=4096)
234
+ work_kinds: list[str] = Field(default_factory=list, max_length=32)
235
+ capabilities: list[str] = Field(default_factory=list, max_length=32)
236
+ model_strategy_override: ProjectAgentModelStrategy | None = None
237
+ executor_policy_override: ProjectAgentExecutorPolicy | None = None
238
+ reason: str = Field(min_length=1, max_length=2048)
239
+ source_application: SourceApplication | None = None
240
+ source_session_id: str | None = Field(default=None, min_length=1, max_length=256)
241
+
242
+ @field_validator('work_kinds', 'capabilities')
243
+ @classmethod
244
+ def validate_bounded_unique_text(cls, value: list[str]) -> list[str]:
245
+ return ProjectAgentProfile.validate_bounded_unique_text(value)
246
+
247
+ @model_validator(mode='after')
248
+ def reject_sensitive_values(self):
249
+ reject_credentials(self, 'Project Agent assignment replacement')
250
+ return self
251
+
252
+
253
+ class ProjectAgentAssignmentReplaceResult(StrictModel):
254
+ ended: ProjectAgentAssignmentRecord
255
+ replacement: ProjectAgentAssignmentRecord
256
+
257
+
258
+ class ProjectAgentRecord(StrictModel):
259
+ agent_id: str
260
+ personal_space_id: str
261
+ personal_project_id: str | None = None
262
+ profile: ProjectAgentProfile
263
+ executor_policy: ProjectAgentExecutorPolicy = Field(
264
+ default_factory=ProjectAgentExecutorPolicy
265
+ )
266
+ memory_scope: ProjectAgentMemoryScope = 'reviewed_agent'
267
+ assignments: list[ProjectAgentAssignmentRecord] = Field(default_factory=list)
268
+ recruitment_id: str | None = None
269
+ temporary_task_id: str | None = None
270
+ work_status: ProjectAgentWorkStatus = 'idle'
271
+ open_task_count: int = Field(default=0, ge=0)
272
+ current_task_id: str | None = None
273
+ observed_clients: list[SourceApplication] = Field(default_factory=list)
274
+ recruited_at: datetime | None = None
275
+ recruitment_reason: str | None = None
276
+ recruitment_source_application: SourceApplication | None = None
277
+ created_at: datetime
278
+ updated_at: datetime